WebBrowser/GreaseMonkey/GreaseMonkeyDownloader.py

changeset 5715
cbcca230679f
parent 5389
9b1c800daff3
child 5726
e1dbd217214a
equal deleted inserted replaced
5714:90c57b50600f 5715:cbcca230679f
9 9
10 from __future__ import unicode_literals 10 from __future__ import unicode_literals
11 11
12 import os 12 import os
13 13
14 from PyQt5.QtCore import pyqtSignal, QObject, QSettings, QRegExp, QUrl 14 from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QSettings, QFileInfo
15 from PyQt5.QtWidgets import QDialog
16 from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest 15 from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
17
18 from E5Gui import E5MessageBox
19 16
20 from WebBrowser.WebBrowserWindow import WebBrowserWindow 17 from WebBrowser.WebBrowserWindow import WebBrowserWindow
21 18
22 19
20 # TODO: document signals
23 class GreaseMonkeyDownloader(QObject): 21 class GreaseMonkeyDownloader(QObject):
24 """ 22 """
25 Class implementing the downloader for GreaseMonkey scripts. 23 Class implementing the downloader for GreaseMonkey scripts.
26 """ 24 """
27 finished = pyqtSignal() 25 finished = pyqtSignal(str)
26 error = pyqtSignal()
28 27
29 def __init__(self, url, manager): 28 DownloadMainScript = 1
29 DownloadRequireScript = 2
30
31 def __init__(self, url, manager, mode):
30 """ 32 """
31 Constructor 33 Constructor
32 34
33 @param url URL to download script from 35 @param url URL to download script from
34 @type QUrl 36 @type QUrl
35 @param manager reference to the GreaseMonkey manager 37 @param manager reference to the GreaseMonkey manager
36 @type GreaseMonkeyManager 38 @type GreaseMonkeyManager
39 @param mode download mode
40 @type int (one of DownloadMainScript, DownloadRequireScript)
37 """ 41 """
38 super(GreaseMonkeyDownloader, self).__init__() 42 super(GreaseMonkeyDownloader, self).__init__()
39 43
40 self.__manager = manager 44 self.__manager = manager
41 45
42 self.__reply = WebBrowserWindow.networkManager().get( 46 self.__reply = WebBrowserWindow.networkManager().get(
43 QNetworkRequest(url)) 47 QNetworkRequest(url))
44 self.__reply.finished.connect(self.__scriptDownloaded) 48 if mode == GreaseMonkeyDownloader.DownloadMainScript:
49 self.__reply.finished.connect(self.__scriptDownloaded)
50 else:
51 self.__reply.finished.connect(self.__requireDownloaded)
45 52
46 self.__fileName = "" 53 self.__fileName = ""
47 self.__requireUrls = []
48 54
55 def updateScript(self, fileName):
56 """
57 Public method to set the file name for the script to be downloaded.
58
59 @param fileName file name for the script
60 @type str
61 """
62 self.__fileName = fileName
63
64 @pyqtSlot()
49 def __scriptDownloaded(self): 65 def __scriptDownloaded(self):
50 """ 66 """
51 Private slot to handle the finished download of a script. 67 Private slot to handle the finished download of a script.
52 """ 68 """
69 self.deleteLater()
70 self.__reply.deleteLater()
71
53 if self.sender() != self.__reply: 72 if self.sender() != self.__reply:
54 self.finished.emit() 73 self.error.emit()
74 return
75
76 if self.__reply.error() != QNetworkReply.NoError:
77 self.error.emit()
55 return 78 return
56 79
57 response = bytes(self.__reply.readAll()).decode() 80 response = bytes(self.__reply.readAll()).decode()
58 81
59 if self.__reply.error() == QNetworkReply.NoError and \ 82 if "// ==UserScript==" not in response:
60 "// ==UserScript==" in response: 83 self.error.emit()
84 return
85
86 if not self.__fileName:
61 from WebBrowser.Tools import WebBrowserTools 87 from WebBrowser.Tools import WebBrowserTools
62 filePath = os.path.join( 88 filePath = os.path.join(
63 self.__manager.scriptsDirectory(), 89 self.__manager.scriptsDirectory(),
64 WebBrowserTools.getFileNameFromUrl(self.__reply.url())) 90 WebBrowserTools.getFileNameFromUrl(self.__reply.url()))
65 self.__fileName = WebBrowserTools.ensureUniqueFilename(filePath) 91 self.__fileName = WebBrowserTools.ensureUniqueFilename(filePath)
66
67 try:
68 f = open(self.__fileName, "w", encoding="utf-8")
69 except (IOError, OSError) as err:
70 E5MessageBox.critical(
71 None,
72 self.tr("GreaseMonkey Download"),
73 self.tr(
74 """<p>The file <b>{0}</b> could not be opened"""
75 """ for writing.<br/>Reason: {1}</p>""").format(
76 self.__fileName, str(err)))
77 self.finished.emit()
78 return
79 f.write(response)
80 f.close()
81
82 settings = QSettings(
83 os.path.join(self.__manager.requireScriptsDirectory(),
84 "requires.ini"),
85 QSettings.IniFormat)
86 settings.beginGroup("Files")
87
88 rx = QRegExp("@require(.*)\\n")
89 rx.setMinimal(True)
90 rx.indexIn(response)
91
92 for i in range(1, rx.captureCount() + 1):
93 url = rx.cap(i).strip()
94 if url and not settings.contains(url):
95 self.__requireUrls.append(QUrl(url))
96 92
97 self.__reply.deleteLater() 93 try:
98 self.__reply = None 94 f = open(self.__fileName, "w", encoding="utf-8")
95 except (IOError, OSError) as err:
96 self.error.emit()
97 return
98 f.write(response)
99 f.close()
99 100
100 self.__downloadRequires() 101 self.finished.emit(self.__fileName)
101 102
103 @pyqtSlot()
102 def __requireDownloaded(self): 104 def __requireDownloaded(self):
103 """ 105 """
104 Private slot to handle the finished download of a required script. 106 Private slot to handle the finished download of a required script.
105 """ 107 """
108 self.deleteLater()
109 self.__reply.deleteLater()
110
106 if self.sender() != self.__reply: 111 if self.sender() != self.__reply:
107 self.finished.emit() 112 self.error.emit()
113 return
114
115 if self.__reply.error() != QNetworkReply.NoError:
116 self.error.emit()
108 return 117 return
109 118
110 response = bytes(self.__reply.readAll()).decode() 119 response = bytes(self.__reply.readAll()).decode()
111 120
112 if self.__reply.error() == QNetworkReply.NoError and response: 121 if not response:
113 from WebBrowser.Tools import WebBrowserTools 122 self.error.emit()
114 filePath = os.path.join(self.__manager.requireScriptsDirectory(), 123 return
115 "require.js")
116 fileName = WebBrowserTools.ensureUniqueFilename(filePath, "{0}")
117
118 try:
119 f = open(fileName, "w", encoding="utf-8")
120 except (IOError, OSError) as err:
121 E5MessageBox.critical(
122 None,
123 self.tr("GreaseMonkey Download"),
124 self.tr(
125 """<p>The file <b>{0}</b> could not be opened"""
126 """ for writing.<br/>Reason: {1}</p>""").format(
127 fileName, str(err)))
128 self.finished.emit()
129 return
130 f.write(response)
131 f.close()
132
133 settings = QSettings(
134 os.path.join(self.__manager.requireScriptsDirectory(),
135 "requires.ini"),
136 QSettings.IniFormat)
137 settings.beginGroup("Files")
138 settings.setValue(self.__reply.originalUrl().toString(), fileName)
139 124
140 self.__reply.deleteLater() 125 settings = QSettings(
141 self.__reply = None 126 os.path.join(self.__manager.requireScriptsDirectory(),
127 "requires.ini"),
128 QSettings.IniFormat)
129 settings.beginGroup("Files")
142 130
143 self.__downloadRequires() 131 if not self.__fileName:
144 132 self.__fileName = settings.value(
145 def __downloadRequires(self): 133 self.__reply.request().url().toString())
146 """ 134 if not self.__fileName:
147 Private slot to initiate the download of required scripts. 135 name = QFileInfo(self.__reply.request().url().path())\
148 """ 136 .fileName()
149 if self.__requireUrls: 137 if not name:
150 self.__reply = WebBrowserWindow.networkManager().get( 138 name = "require.js"
151 QNetworkRequest(self.__requireUrls.pop(0))) 139 elif not name.endswith(".js"):
152 self.__reply.finished.connect(self.__requireDownloaded) 140 name += ".js"
153 else: 141 filePath = os.path.join(
154 from .GreaseMonkeyScript import GreaseMonkeyScript 142 self.__manager.requireScriptsDirectory(), name)
155 deleteScript = True 143 from WebBrowser.Tools import WebBrowserTools
156 script = GreaseMonkeyScript(self.__manager, self.__fileName) 144 self.__fileName = WebBrowserTools.ensureUniqueFilename(
157 145 filePath, "{0}")
158 if script.isValid(): 146 if not QFileInfo(self.__fileName).isAbsolute():
159 if not self.__manager.containsScript(script.fullName()): 147 self.__fileName = os.path.join(
160 from .GreaseMonkeyAddScriptDialog import \ 148 self.__manager.requireScriptsDirectory(),
161 GreaseMonkeyAddScriptDialog 149 self.__fileName)
162 dlg = GreaseMonkeyAddScriptDialog(self.__manager, script) 150
163 deleteScript = dlg.exec_() != QDialog.Accepted 151 try:
164 else: 152 f = open(self.__fileName, "w", encoding="utf-8")
165 E5MessageBox.information( 153 except (IOError, OSError) as err:
166 None, 154 self.error.emit()
167 self.tr("GreaseMonkey Download"), 155 return
168 self.tr( 156 f.write(response)
169 """<p><b>{0}</b> is already installed.</p>""") 157 f.close()
170 .format(script.name())) 158
171 159 settings.setValue(self.__reply.request().url().toString(),
172 if deleteScript: 160 QFileInfo(self.__fileName).fileName())
173 try: 161
174 os.remove(self.__fileName) 162 self.finished.emit(self.__fileName)
175 except (IOError, OSError):
176 # ignore
177 pass
178
179 self.finished.emit()

eric ide

mercurial