src/eric7/WebBrowser/GreaseMonkey/GreaseMonkeyScript.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9473
3f23dbf37dbe
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
8 """ 8 """
9 9
10 import re 10 import re
11 11
12 from PyQt6.QtCore import ( 12 from PyQt6.QtCore import (
13 pyqtSignal, pyqtSlot, QObject, QUrl, QByteArray, QCryptographicHash 13 pyqtSignal,
14 pyqtSlot,
15 QObject,
16 QUrl,
17 QByteArray,
18 QCryptographicHash,
14 ) 19 )
15 from PyQt6.QtGui import QIcon, QPixmap, QImage 20 from PyQt6.QtGui import QIcon, QPixmap, QImage
16 from PyQt6.QtNetwork import QNetworkRequest, QNetworkReply 21 from PyQt6.QtNetwork import QNetworkRequest, QNetworkReply
17 from PyQt6.QtWebEngineCore import QWebEngineScript 22 from PyQt6.QtWebEngineCore import QWebEngineScript
18 23
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()))

eric ide

mercurial