25 |
30 |
26 |
31 |
27 class GreaseMonkeyScript(QObject): |
32 class GreaseMonkeyScript(QObject): |
28 """ |
33 """ |
29 Class implementing the GreaseMonkey script. |
34 Class implementing the GreaseMonkey script. |
30 |
35 |
31 @signal scriptChanged() emitted to indicate a script change |
36 @signal scriptChanged() emitted to indicate a script change |
32 @signal updatingChanged(bool) emitted to indicate a change of the |
37 @signal updatingChanged(bool) emitted to indicate a change of the |
33 updating state |
38 updating state |
34 """ |
39 """ |
|
40 |
35 DocumentStart = 0 |
41 DocumentStart = 0 |
36 DocumentEnd = 1 |
42 DocumentEnd = 1 |
37 DocumentIdle = 2 |
43 DocumentIdle = 2 |
38 |
44 |
39 scriptChanged = pyqtSignal() |
45 scriptChanged = pyqtSignal() |
40 updatingChanged = pyqtSignal(bool) |
46 updatingChanged = pyqtSignal(bool) |
41 |
47 |
42 def __init__(self, manager, path): |
48 def __init__(self, manager, path): |
43 """ |
49 """ |
44 Constructor |
50 Constructor |
45 |
51 |
46 @param manager reference to the manager object (GreaseMonkeyManager) |
52 @param manager reference to the manager object (GreaseMonkeyManager) |
47 @param path path of the Javascript file (string) |
53 @param path path of the Javascript file (string) |
48 """ |
54 """ |
49 super().__init__(manager) |
55 super().__init__(manager) |
50 |
56 |
51 self.__manager = manager |
57 self.__manager = manager |
52 self.__fileWatcher = DelayedFileWatcher(parent=None) |
58 self.__fileWatcher = DelayedFileWatcher(parent=None) |
53 |
59 |
54 self.__name = "" |
60 self.__name = "" |
55 self.__namespace = "GreaseMonkeyNS" |
61 self.__namespace = "GreaseMonkeyNS" |
56 self.__description = "" |
62 self.__description = "" |
57 self.__version = "" |
63 self.__version = "" |
58 |
64 |
59 self.__include = [] |
65 self.__include = [] |
60 self.__exclude = [] |
66 self.__exclude = [] |
61 self.__require = [] |
67 self.__require = [] |
62 |
68 |
63 self.__icon = QIcon() |
69 self.__icon = QIcon() |
64 self.__iconUrl = QUrl() |
70 self.__iconUrl = QUrl() |
65 self.__downloadUrl = QUrl() |
71 self.__downloadUrl = QUrl() |
66 self.__updateUrl = QUrl() |
72 self.__updateUrl = QUrl() |
67 self.__startAt = GreaseMonkeyScript.DocumentEnd |
73 self.__startAt = GreaseMonkeyScript.DocumentEnd |
68 |
74 |
69 self.__script = "" |
75 self.__script = "" |
70 self.__fileName = path |
76 self.__fileName = path |
71 self.__enabled = True |
77 self.__enabled = True |
72 self.__valid = False |
78 self.__valid = False |
73 self.__noFrames = False |
79 self.__noFrames = False |
74 |
80 |
75 self.__updating = False |
81 self.__updating = False |
76 |
82 |
77 self.__downloaders = [] |
83 self.__downloaders = [] |
78 self.__iconReplies = [] |
84 self.__iconReplies = [] |
79 |
85 |
80 self.__parseScript() |
86 self.__parseScript() |
81 |
87 |
82 self.__fileWatcher.delayedFileChanged.connect( |
88 self.__fileWatcher.delayedFileChanged.connect(self.__watchedFileChanged) |
83 self.__watchedFileChanged) |
89 |
84 |
|
85 def isValid(self): |
90 def isValid(self): |
86 """ |
91 """ |
87 Public method to check the validity of the script. |
92 Public method to check the validity of the script. |
88 |
93 |
89 @return flag indicating a valid script (boolean) |
94 @return flag indicating a valid script (boolean) |
90 """ |
95 """ |
91 return self.__valid |
96 return self.__valid |
92 |
97 |
93 def name(self): |
98 def name(self): |
94 """ |
99 """ |
95 Public method to get the name of the script. |
100 Public method to get the name of the script. |
96 |
101 |
97 @return name of the script (string) |
102 @return name of the script (string) |
98 """ |
103 """ |
99 return self.__name |
104 return self.__name |
100 |
105 |
101 def nameSpace(self): |
106 def nameSpace(self): |
102 """ |
107 """ |
103 Public method to get the name space of the script. |
108 Public method to get the name space of the script. |
104 |
109 |
105 @return name space of the script (string) |
110 @return name space of the script (string) |
106 """ |
111 """ |
107 return self.__namespace |
112 return self.__namespace |
108 |
113 |
109 def fullName(self): |
114 def fullName(self): |
110 """ |
115 """ |
111 Public method to get the full name of the script. |
116 Public method to get the full name of the script. |
112 |
117 |
113 @return full name of the script (string) |
118 @return full name of the script (string) |
114 """ |
119 """ |
115 return "{0}/{1}".format(self.__namespace, self.__name) |
120 return "{0}/{1}".format(self.__namespace, self.__name) |
116 |
121 |
117 def description(self): |
122 def description(self): |
118 """ |
123 """ |
119 Public method to get the description of the script. |
124 Public method to get the description of the script. |
120 |
125 |
121 @return description of the script (string) |
126 @return description of the script (string) |
122 """ |
127 """ |
123 return self.__description |
128 return self.__description |
124 |
129 |
125 def version(self): |
130 def version(self): |
126 """ |
131 """ |
127 Public method to get the version of the script. |
132 Public method to get the version of the script. |
128 |
133 |
129 @return version of the script (string) |
134 @return version of the script (string) |
130 """ |
135 """ |
131 return self.__version |
136 return self.__version |
132 |
137 |
133 def icon(self): |
138 def icon(self): |
134 """ |
139 """ |
135 Public method to get the icon of the script. |
140 Public method to get the icon of the script. |
136 |
141 |
137 @return script icon |
142 @return script icon |
138 @rtype QIcon |
143 @rtype QIcon |
139 """ |
144 """ |
140 return self.__icon |
145 return self.__icon |
141 |
146 |
142 def iconUrl(self): |
147 def iconUrl(self): |
143 """ |
148 """ |
144 Public method to get the icon URL of the script. |
149 Public method to get the icon URL of the script. |
145 |
150 |
146 @return icon URL of the script (QUrl) |
151 @return icon URL of the script (QUrl) |
147 """ |
152 """ |
148 return QUrl(self.__iconUrl) |
153 return QUrl(self.__iconUrl) |
149 |
154 |
150 def downloadUrl(self): |
155 def downloadUrl(self): |
151 """ |
156 """ |
152 Public method to get the download URL of the script. |
157 Public method to get the download URL of the script. |
153 |
158 |
154 @return download URL of the script (QUrl) |
159 @return download URL of the script (QUrl) |
155 """ |
160 """ |
156 return QUrl(self.__downloadUrl) |
161 return QUrl(self.__downloadUrl) |
157 |
162 |
158 def updateUrl(self): |
163 def updateUrl(self): |
159 """ |
164 """ |
160 Public method to get the update URL of the script. |
165 Public method to get the update URL of the script. |
161 |
166 |
162 @return update URL of the script (QUrl) |
167 @return update URL of the script (QUrl) |
163 """ |
168 """ |
164 return QUrl(self.__updateUrl) |
169 return QUrl(self.__updateUrl) |
165 |
170 |
166 def startAt(self): |
171 def startAt(self): |
167 """ |
172 """ |
168 Public method to get the start point of the script. |
173 Public method to get the start point of the script. |
169 |
174 |
170 @return start point of the script (DocumentStart or DocumentEnd) |
175 @return start point of the script (DocumentStart or DocumentEnd) |
171 """ |
176 """ |
172 return self.__startAt |
177 return self.__startAt |
173 |
178 |
174 def noFrames(self): |
179 def noFrames(self): |
175 """ |
180 """ |
176 Public method to get the noFrames flag. |
181 Public method to get the noFrames flag. |
177 |
182 |
178 @return flag indicating to not run on sub frames |
183 @return flag indicating to not run on sub frames |
179 @rtype bool |
184 @rtype bool |
180 """ |
185 """ |
181 return self.__noFrames |
186 return self.__noFrames |
182 |
187 |
183 def isEnabled(self): |
188 def isEnabled(self): |
184 """ |
189 """ |
185 Public method to check, if the script is enabled. |
190 Public method to check, if the script is enabled. |
186 |
191 |
187 @return flag indicating an enabled state (boolean) |
192 @return flag indicating an enabled state (boolean) |
188 """ |
193 """ |
189 return self.__enabled and self.__valid |
194 return self.__enabled and self.__valid |
190 |
195 |
191 def setEnabled(self, enable): |
196 def setEnabled(self, enable): |
192 """ |
197 """ |
193 Public method to enable a script. |
198 Public method to enable a script. |
194 |
199 |
195 @param enable flag indicating the new enabled state (boolean) |
200 @param enable flag indicating the new enabled state (boolean) |
196 """ |
201 """ |
197 self.__enabled = enable |
202 self.__enabled = enable |
198 |
203 |
199 def include(self): |
204 def include(self): |
200 """ |
205 """ |
201 Public method to get the list of included URLs. |
206 Public method to get the list of included URLs. |
202 |
207 |
203 @return list of included URLs (list of strings) |
208 @return list of included URLs (list of strings) |
204 """ |
209 """ |
205 return self.__include[:] |
210 return self.__include[:] |
206 |
211 |
207 def exclude(self): |
212 def exclude(self): |
208 """ |
213 """ |
209 Public method to get the list of excluded URLs. |
214 Public method to get the list of excluded URLs. |
210 |
215 |
211 @return list of excluded URLs (list of strings) |
216 @return list of excluded URLs (list of strings) |
212 """ |
217 """ |
213 return self.__exclude[:] |
218 return self.__exclude[:] |
214 |
219 |
215 def require(self): |
220 def require(self): |
216 """ |
221 """ |
217 Public method to get the list of required scripts. |
222 Public method to get the list of required scripts. |
218 |
223 |
219 @return list of required scripts (list of strings) |
224 @return list of required scripts (list of strings) |
220 """ |
225 """ |
221 return self.__require[:] |
226 return self.__require[:] |
222 |
227 |
223 def fileName(self): |
228 def fileName(self): |
224 """ |
229 """ |
225 Public method to get the path of the Javascript file. |
230 Public method to get the path of the Javascript file. |
226 |
231 |
227 @return path of the Javascript file (string) |
232 @return path of the Javascript file (string) |
228 """ |
233 """ |
229 return self.__fileName |
234 return self.__fileName |
230 |
235 |
231 def isUpdating(self): |
236 def isUpdating(self): |
232 """ |
237 """ |
233 Public method to get the updating flag. |
238 Public method to get the updating flag. |
234 |
239 |
235 @return updating flag |
240 @return updating flag |
236 @rtype bool |
241 @rtype bool |
237 """ |
242 """ |
238 return self.__updating |
243 return self.__updating |
239 |
244 |
240 @pyqtSlot(str) |
245 @pyqtSlot(str) |
241 def __watchedFileChanged(self, fileName): |
246 def __watchedFileChanged(self, fileName): |
242 """ |
247 """ |
243 Private slot handling changes of the script file. |
248 Private slot handling changes of the script file. |
244 |
249 |
245 @param fileName path of the script file |
250 @param fileName path of the script file |
246 @type str |
251 @type str |
247 """ |
252 """ |
248 if self.__fileName == fileName: |
253 if self.__fileName == fileName: |
249 self.__reloadScript() |
254 self.__reloadScript() |
250 |
255 |
251 def __parseScript(self): |
256 def __parseScript(self): |
252 """ |
257 """ |
253 Private method to parse the given script and populate the data |
258 Private method to parse the given script and populate the data |
254 structure. |
259 structure. |
255 """ |
260 """ |
256 self.__name = "" |
261 self.__name = "" |
257 self.__namespace = "GreaseMonkeyNS" |
262 self.__namespace = "GreaseMonkeyNS" |
258 self.__description = "" |
263 self.__description = "" |
259 self.__version = "" |
264 self.__version = "" |
260 |
265 |
261 self.__include = [] |
266 self.__include = [] |
262 self.__exclude = [] |
267 self.__exclude = [] |
263 self.__require = [] |
268 self.__require = [] |
264 |
269 |
265 self.__icon = QIcon() |
270 self.__icon = QIcon() |
266 self.__iconUrl = QUrl() |
271 self.__iconUrl = QUrl() |
267 self.__downloadUrl = QUrl() |
272 self.__downloadUrl = QUrl() |
268 self.__updateUrl = QUrl() |
273 self.__updateUrl = QUrl() |
269 self.__startAt = GreaseMonkeyScript.DocumentEnd |
274 self.__startAt = GreaseMonkeyScript.DocumentEnd |
270 |
275 |
271 self.__script = "" |
276 self.__script = "" |
272 self.__enabled = True |
277 self.__enabled = True |
273 self.__valid = False |
278 self.__valid = False |
274 self.__noFrames = False |
279 self.__noFrames = False |
275 |
280 |
276 try: |
281 try: |
277 with open(self.__fileName, "r", encoding="utf-8") as f: |
282 with open(self.__fileName, "r", encoding="utf-8") as f: |
278 fileData = f.read() |
283 fileData = f.read() |
279 except OSError: |
284 except OSError: |
280 # silently ignore because it shouldn't happen |
285 # silently ignore because it shouldn't happen |
281 return |
286 return |
282 |
287 |
283 if self.__fileName not in self.__fileWatcher.files(): |
288 if self.__fileName not in self.__fileWatcher.files(): |
284 self.__fileWatcher.addPath(self.__fileName) |
289 self.__fileWatcher.addPath(self.__fileName) |
285 |
290 |
286 rx = re.compile( |
291 rx = re.compile(r"""// ==UserScript==(.*)// ==/UserScript==""", re.DOTALL) |
287 r"""// ==UserScript==(.*)// ==/UserScript==""", |
|
288 re.DOTALL |
|
289 ) |
|
290 match = rx.search(fileData) |
292 match = rx.search(fileData) |
291 if match is None: |
293 if match is None: |
292 # invalid script file |
294 # invalid script file |
293 return |
295 return |
294 |
296 |
295 metaDataBlock = match.group(1).strip() |
297 metaDataBlock = match.group(1).strip() |
296 if metaDataBlock == "": |
298 if metaDataBlock == "": |
297 # invalid script file |
299 # invalid script file |
298 return |
300 return |
299 |
301 |
300 for line in metaDataBlock.splitlines(): |
302 for line in metaDataBlock.splitlines(): |
301 if not line.strip(): |
303 if not line.strip(): |
302 continue |
304 continue |
303 |
305 |
304 if not line.startswith("// @"): |
306 if not line.startswith("// @"): |
305 continue |
307 continue |
306 |
308 |
307 line = line[3:].replace("\t", " ") |
309 line = line[3:].replace("\t", " ") |
308 index = line.find(" ") |
310 index = line.find(" ") |
309 |
311 |
310 key = line[:index].strip() |
312 key = line[:index].strip() |
311 value = line[index + 1:].strip() if index > 0 else "" |
313 value = line[index + 1 :].strip() if index > 0 else "" |
312 |
314 |
313 if not key: |
315 if not key: |
314 continue |
316 continue |
315 |
317 |
316 if key == "@name": |
318 if key == "@name": |
317 self.__name = value |
319 self.__name = value |
318 |
320 |
319 elif key == "@namespace": |
321 elif key == "@namespace": |
320 self.__namespace = value |
322 self.__namespace = value |
321 |
323 |
322 elif key == "@description": |
324 elif key == "@description": |
323 self.__description = value |
325 self.__description = value |
324 |
326 |
325 elif key == "@version": |
327 elif key == "@version": |
326 self.__version = value |
328 self.__version = value |
327 |
329 |
328 elif key in ["@include", "@match"]: |
330 elif key in ["@include", "@match"]: |
329 self.__include.append(value) |
331 self.__include.append(value) |
330 |
332 |
331 elif key in ["@exclude", "@exclude_match"]: |
333 elif key in ["@exclude", "@exclude_match"]: |
332 self.__exclude.append(value) |
334 self.__exclude.append(value) |
333 |
335 |
334 elif key == "@require": |
336 elif key == "@require": |
335 self.__require.append(value) |
337 self.__require.append(value) |
336 |
338 |
337 elif key == "@run-at": |
339 elif key == "@run-at": |
338 if value == "document-end": |
340 if value == "document-end": |
339 self.__startAt = GreaseMonkeyScript.DocumentEnd |
341 self.__startAt = GreaseMonkeyScript.DocumentEnd |
340 elif value == "document-start": |
342 elif value == "document-start": |
341 self.__startAt = GreaseMonkeyScript.DocumentStart |
343 self.__startAt = GreaseMonkeyScript.DocumentStart |
342 elif value == "document-idle": |
344 elif value == "document-idle": |
343 self.__startAt = GreaseMonkeyScript.DocumentIdle |
345 self.__startAt = GreaseMonkeyScript.DocumentIdle |
344 |
346 |
345 elif key == "@downloadURL" and self.__downloadUrl.isEmpty(): |
347 elif key == "@downloadURL" and self.__downloadUrl.isEmpty(): |
346 self.__downloadUrl = QUrl(value) |
348 self.__downloadUrl = QUrl(value) |
347 |
349 |
348 elif key == "@updateURL" and self.__updateUrl.isEmpty(): |
350 elif key == "@updateURL" and self.__updateUrl.isEmpty(): |
349 self.__updateUrl = QUrl(value) |
351 self.__updateUrl = QUrl(value) |
350 |
352 |
351 elif key == "@icon": |
353 elif key == "@icon": |
352 self.__iconUrl = QUrl(value) |
354 self.__iconUrl = QUrl(value) |
353 |
355 |
354 elif key == "@noframes": |
356 elif key == "@noframes": |
355 self.__noFrames = True |
357 self.__noFrames = True |
356 |
358 |
357 self.__iconUrl = self.__downloadUrl.resolved(self.__iconUrl) |
359 self.__iconUrl = self.__downloadUrl.resolved(self.__iconUrl) |
358 |
360 |
359 if not self.__include: |
361 if not self.__include: |
360 self.__include.append("*") |
362 self.__include.append("*") |
361 |
363 |
362 nspace = bytes(QCryptographicHash.hash( |
364 nspace = bytes( |
363 QByteArray(self.fullName().encode("utf-8")), |
365 QCryptographicHash.hash( |
364 QCryptographicHash.Algorithm.Md4).toHex()).decode("ascii") |
366 QByteArray(self.fullName().encode("utf-8")), |
|
367 QCryptographicHash.Algorithm.Md4, |
|
368 ).toHex() |
|
369 ).decode("ascii") |
365 valuesScript = values_js.format(nspace) |
370 valuesScript = values_js.format(nspace) |
366 self.__script = "(function(){{{0}\n{1}\n{2}\n}})();".format( |
371 self.__script = "(function(){{{0}\n{1}\n{2}\n}})();".format( |
367 valuesScript, self.__manager.requireScripts(self.__require), |
372 valuesScript, self.__manager.requireScripts(self.__require), fileData |
368 fileData |
|
369 ) |
373 ) |
370 self.__valid = True |
374 self.__valid = True |
371 |
375 |
372 self.__downloadIcon() |
376 self.__downloadIcon() |
373 self.__downloadRequires() |
377 self.__downloadRequires() |
374 |
378 |
375 def webScript(self): |
379 def webScript(self): |
376 """ |
380 """ |
377 Public method to create a script object. |
381 Public method to create a script object. |
378 |
382 |
379 @return prepared script object |
383 @return prepared script object |
380 @rtype QWebEngineScript |
384 @rtype QWebEngineScript |
381 """ |
385 """ |
382 script = QWebEngineScript() |
386 script = QWebEngineScript() |
383 script.setSourceCode("{0}\n{1}".format( |
387 script.setSourceCode("{0}\n{1}".format(bootstrap_js, self.__script)) |
384 bootstrap_js, self.__script |
|
385 )) |
|
386 script.setName(self.fullName()) |
388 script.setName(self.fullName()) |
387 script.setWorldId(WebBrowserPage.SafeJsWorld) |
389 script.setWorldId(WebBrowserPage.SafeJsWorld) |
388 script.setRunsOnSubFrames(not self.__noFrames) |
390 script.setRunsOnSubFrames(not self.__noFrames) |
389 return script |
391 return script |
390 |
392 |
391 def updateScript(self): |
393 def updateScript(self): |
392 """ |
394 """ |
393 Public method to updated the script. |
395 Public method to updated the script. |
394 """ |
396 """ |
395 if not self.__downloadUrl.isValid() or self.__updating: |
397 if not self.__downloadUrl.isValid() or self.__updating: |
396 return |
398 return |
397 |
399 |
398 self.__updating = True |
400 self.__updating = True |
399 self.updatingChanged.emit(self.__updating) |
401 self.updatingChanged.emit(self.__updating) |
400 |
402 |
401 downloader = GreaseMonkeyDownloader( |
403 downloader = GreaseMonkeyDownloader( |
402 self.__downloadUrl, |
404 self.__downloadUrl, |
403 self.__manager, |
405 self.__manager, |
404 GreaseMonkeyDownloader.DownloadMainScript) |
406 GreaseMonkeyDownloader.DownloadMainScript, |
|
407 ) |
405 downloader.updateScript(self.__fileName) |
408 downloader.updateScript(self.__fileName) |
406 downloader.finished.connect( |
409 downloader.finished.connect(lambda: self.__downloaderFinished(downloader)) |
407 lambda: self.__downloaderFinished(downloader)) |
410 downloader.error.connect(lambda: self.__downloaderError(downloader)) |
408 downloader.error.connect( |
|
409 lambda: self.__downloaderError(downloader)) |
|
410 self.__downloaders.append(downloader) |
411 self.__downloaders.append(downloader) |
411 |
412 |
412 self.__downloadRequires() |
413 self.__downloadRequires() |
413 |
414 |
414 def __downloaderFinished(self, downloader): |
415 def __downloaderFinished(self, downloader): |
415 """ |
416 """ |
416 Private slot to handle a finished download. |
417 Private slot to handle a finished download. |
417 |
418 |
418 @param downloader reference to the downloader object |
419 @param downloader reference to the downloader object |
419 @type GreaseMonkeyDownloader |
420 @type GreaseMonkeyDownloader |
420 """ |
421 """ |
421 if downloader in self.__downloaders: |
422 if downloader in self.__downloaders: |
422 self.__downloaders.remove(downloader) |
423 self.__downloaders.remove(downloader) |
423 self.__updating = False |
424 self.__updating = False |
424 self.updatingChanged.emit(self.__updating) |
425 self.updatingChanged.emit(self.__updating) |
425 |
426 |
426 def __downloaderError(self, downloader): |
427 def __downloaderError(self, downloader): |
427 """ |
428 """ |
428 Private slot to handle a downloader error. |
429 Private slot to handle a downloader error. |
429 |
430 |
430 @param downloader reference to the downloader object |
431 @param downloader reference to the downloader object |
431 @type GreaseMonkeyDownloader |
432 @type GreaseMonkeyDownloader |
432 """ |
433 """ |
433 if downloader in self.__downloaders: |
434 if downloader in self.__downloaders: |
434 self.__downloaders.remove(downloader) |
435 self.__downloaders.remove(downloader) |
435 self.__updating = False |
436 self.__updating = False |
436 self.updatingChanged.emit(self.__updating) |
437 self.updatingChanged.emit(self.__updating) |
437 |
438 |
438 def __reloadScript(self): |
439 def __reloadScript(self): |
439 """ |
440 """ |
440 Private method to reload the script. |
441 Private method to reload the script. |
441 """ |
442 """ |
442 self.__parseScript() |
443 self.__parseScript() |
443 |
444 |
444 self.__manager.removeScript(self, False) |
445 self.__manager.removeScript(self, False) |
445 self.__manager.addScript(self) |
446 self.__manager.addScript(self) |
446 |
447 |
447 self.scriptChanged.emit() |
448 self.scriptChanged.emit() |
448 |
449 |
449 def __downloadRequires(self): |
450 def __downloadRequires(self): |
450 """ |
451 """ |
451 Private method to download the required scripts. |
452 Private method to download the required scripts. |
452 """ |
453 """ |
453 for urlStr in self.__require: |
454 for urlStr in self.__require: |
454 if not self.__manager.requireScripts([urlStr]): |
455 if not self.__manager.requireScripts([urlStr]): |
455 downloader = GreaseMonkeyDownloader( |
456 downloader = GreaseMonkeyDownloader( |
456 QUrl(urlStr), |
457 QUrl(urlStr), |
457 self.__manager, |
458 self.__manager, |
458 GreaseMonkeyDownloader.DownloadRequireScript) |
459 GreaseMonkeyDownloader.DownloadRequireScript, |
|
460 ) |
459 downloader.finished.connect( |
461 downloader.finished.connect( |
460 lambda: self.__requireDownloaded(downloader)) |
462 lambda: self.__requireDownloaded(downloader) |
|
463 ) |
461 downloader.error.connect( |
464 downloader.error.connect( |
462 lambda: self.__requireDownloadError(downloader)) |
465 lambda: self.__requireDownloadError(downloader) |
|
466 ) |
463 self.__downloaders.append(downloader) |
467 self.__downloaders.append(downloader) |
464 |
468 |
465 def __requireDownloaded(self, downloader): |
469 def __requireDownloaded(self, downloader): |
466 """ |
470 """ |
467 Private slot to handle a finished download of a required script. |
471 Private slot to handle a finished download of a required script. |
468 |
472 |
469 @param downloader reference to the downloader object |
473 @param downloader reference to the downloader object |
470 @type GreaseMonkeyDownloader |
474 @type GreaseMonkeyDownloader |
471 """ |
475 """ |
472 if downloader in self.__downloaders: |
476 if downloader in self.__downloaders: |
473 self.__downloaders.remove(downloader) |
477 self.__downloaders.remove(downloader) |
474 |
478 |
475 self.__reloadScript() |
479 self.__reloadScript() |
476 |
480 |
477 def __requireDownloadError(self, downloader): |
481 def __requireDownloadError(self, downloader): |
478 """ |
482 """ |
479 Private slot to handle a downloader error. |
483 Private slot to handle a downloader error. |
480 |
484 |
481 @param downloader reference to the downloader object |
485 @param downloader reference to the downloader object |
482 @type GreaseMonkeyDownloader |
486 @type GreaseMonkeyDownloader |
483 """ |
487 """ |
484 if downloader in self.__downloaders: |
488 if downloader in self.__downloaders: |
485 self.__downloaders.remove(downloader) |
489 self.__downloaders.remove(downloader) |
486 |
490 |
487 def __downloadIcon(self): |
491 def __downloadIcon(self): |
488 """ |
492 """ |
489 Private slot to download the script icon. |
493 Private slot to download the script icon. |
490 """ |
494 """ |
491 if self.__iconUrl.isValid(): |
495 if self.__iconUrl.isValid(): |
492 request = QNetworkRequest(self.__iconUrl) |
496 request = QNetworkRequest(self.__iconUrl) |
493 reply = WebBrowserWindow.networkManager().get(request) |
497 reply = WebBrowserWindow.networkManager().get(request) |
494 reply.finished.connect(lambda: self.__iconDownloaded(reply)) |
498 reply.finished.connect(lambda: self.__iconDownloaded(reply)) |
495 self.__iconReplies.append(reply) |
499 self.__iconReplies.append(reply) |
496 |
500 |
497 def __iconDownloaded(self, reply): |
501 def __iconDownloaded(self, reply): |
498 """ |
502 """ |
499 Private slot to handle a finished download of a script icon. |
503 Private slot to handle a finished download of a script icon. |
500 |
504 |
501 @param reply reference to the network reply |
505 @param reply reference to the network reply |
502 @type QNetworkReply |
506 @type QNetworkReply |
503 """ |
507 """ |
504 if reply in self.__iconReplies: |
508 if reply in self.__iconReplies: |
505 self.__iconReplies.remove(reply) |
509 self.__iconReplies.remove(reply) |
506 |
510 |
507 reply.deleteLater() |
511 reply.deleteLater() |
508 if reply.error() == QNetworkReply.NetworkError.NoError: |
512 if reply.error() == QNetworkReply.NetworkError.NoError: |
509 self.__icon = QPixmap.fromImage(QImage.fromData(reply.readAll())) |
513 self.__icon = QPixmap.fromImage(QImage.fromData(reply.readAll())) |