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() |
|