29 |
38 |
30 |
39 |
31 class GreaseMonkeyManager(QObject): |
40 class GreaseMonkeyManager(QObject): |
32 """ |
41 """ |
33 Class implementing the manager for GreaseMonkey scripts. |
42 Class implementing the manager for GreaseMonkey scripts. |
34 |
43 |
35 @signal scriptsChanged() emitted to indicate a change of scripts |
44 @signal scriptsChanged() emitted to indicate a change of scripts |
36 """ |
45 """ |
|
46 |
37 scriptsChanged = pyqtSignal() |
47 scriptsChanged = pyqtSignal() |
38 |
48 |
39 def __init__(self, parent=None): |
49 def __init__(self, parent=None): |
40 """ |
50 """ |
41 Constructor |
51 Constructor |
42 |
52 |
43 @param parent reference to the parent object (QObject) |
53 @param parent reference to the parent object (QObject) |
44 """ |
54 """ |
45 super().__init__(parent) |
55 super().__init__(parent) |
46 |
56 |
47 self.__disabledScripts = [] |
57 self.__disabledScripts = [] |
48 self.__scripts = [] |
58 self.__scripts = [] |
49 self.__downloaders = [] |
59 self.__downloaders = [] |
50 |
60 |
51 self.__jsObject = GreaseMonkeyJsObject(self) |
61 self.__jsObject = GreaseMonkeyJsObject(self) |
52 |
62 |
53 QTimer.singleShot(0, self.__load) |
63 QTimer.singleShot(0, self.__load) |
54 |
64 |
55 def showConfigurationDialog(self, parent=None): |
65 def showConfigurationDialog(self, parent=None): |
56 """ |
66 """ |
57 Public method to show the configuration dialog. |
67 Public method to show the configuration dialog. |
58 |
68 |
59 @param parent reference to the parent widget (QWidget) |
69 @param parent reference to the parent widget (QWidget) |
60 """ |
70 """ |
61 from .GreaseMonkeyConfiguration import GreaseMonkeyConfigurationDialog |
71 from .GreaseMonkeyConfiguration import GreaseMonkeyConfigurationDialog |
|
72 |
62 self.__configDiaolg = ( |
73 self.__configDiaolg = ( |
63 GreaseMonkeyConfigurationDialog.GreaseMonkeyConfigurationDialog( |
74 GreaseMonkeyConfigurationDialog.GreaseMonkeyConfigurationDialog( |
64 self, parent) |
75 self, parent |
|
76 ) |
65 ) |
77 ) |
66 self.__configDiaolg.show() |
78 self.__configDiaolg.show() |
67 |
79 |
68 def downloadScript(self, url): |
80 def downloadScript(self, url): |
69 """ |
81 """ |
70 Public method to download a GreaseMonkey script. |
82 Public method to download a GreaseMonkey script. |
71 |
83 |
72 @param url URL to download script from |
84 @param url URL to download script from |
73 @type QUrl |
85 @type QUrl |
74 """ |
86 """ |
75 QMetaObject.invokeMethod( |
87 QMetaObject.invokeMethod( |
76 self, "doDownloadScript", Qt.ConnectionType.QueuedConnection, |
88 self, |
77 Q_ARG(QUrl, url)) |
89 "doDownloadScript", |
78 |
90 Qt.ConnectionType.QueuedConnection, |
|
91 Q_ARG(QUrl, url), |
|
92 ) |
|
93 |
79 @pyqtSlot(QUrl) |
94 @pyqtSlot(QUrl) |
80 def doDownloadScript(self, url): |
95 def doDownloadScript(self, url): |
81 """ |
96 """ |
82 Public slot to download a GreaseMonkey script. |
97 Public slot to download a GreaseMonkey script. |
83 |
98 |
84 Note: The download needed to be separated in the invoking part |
99 Note: The download needed to be separated in the invoking part |
85 (s.a.) and the one doing the real download because the invoking |
100 (s.a.) and the one doing the real download because the invoking |
86 part runs in a different thread (i.e. the web engine thread). |
101 part runs in a different thread (i.e. the web engine thread). |
87 |
102 |
88 @param url URL to download script from |
103 @param url URL to download script from |
89 @type QUrl |
104 @type QUrl |
90 """ |
105 """ |
91 from .GreaseMonkeyDownloader import GreaseMonkeyDownloader |
106 from .GreaseMonkeyDownloader import GreaseMonkeyDownloader |
|
107 |
92 downloader = GreaseMonkeyDownloader( |
108 downloader = GreaseMonkeyDownloader( |
93 url, self, GreaseMonkeyDownloader.DownloadMainScript) |
109 url, self, GreaseMonkeyDownloader.DownloadMainScript |
94 downloader.finished.connect( |
110 ) |
95 lambda f: self.__downloaderFinished(f, downloader)) |
111 downloader.finished.connect(lambda f: self.__downloaderFinished(f, downloader)) |
96 self.__downloaders.append(downloader) |
112 self.__downloaders.append(downloader) |
97 |
113 |
98 def __downloaderFinished(self, fileName, downloader): |
114 def __downloaderFinished(self, fileName, downloader): |
99 """ |
115 """ |
100 Private slot to handle the completion of a script download. |
116 Private slot to handle the completion of a script download. |
101 |
117 |
102 @param fileName name of the downloaded script |
118 @param fileName name of the downloaded script |
103 @type str |
119 @type str |
104 @param downloader reference to the downloader object |
120 @param downloader reference to the downloader object |
105 @type GreaseMonkeyDownloader |
121 @type GreaseMonkeyDownloader |
106 """ |
122 """ |
107 if downloader in self.__downloaders: |
123 if downloader in self.__downloaders: |
108 self.__downloaders.remove(downloader) |
124 self.__downloaders.remove(downloader) |
109 |
125 |
110 deleteScript = True |
126 deleteScript = True |
111 from .GreaseMonkeyScript import GreaseMonkeyScript |
127 from .GreaseMonkeyScript import GreaseMonkeyScript |
|
128 |
112 script = GreaseMonkeyScript(self, fileName) |
129 script = GreaseMonkeyScript(self, fileName) |
113 if script.isValid(): |
130 if script.isValid(): |
114 if not self.containsScript(script.fullName()): |
131 if not self.containsScript(script.fullName()): |
115 from .GreaseMonkeyAddScriptDialog import ( |
132 from .GreaseMonkeyAddScriptDialog import GreaseMonkeyAddScriptDialog |
116 GreaseMonkeyAddScriptDialog |
133 |
117 ) |
|
118 dlg = GreaseMonkeyAddScriptDialog(self, script) |
134 dlg = GreaseMonkeyAddScriptDialog(self, script) |
119 deleteScript = dlg.exec() != QDialog.DialogCode.Accepted |
135 deleteScript = dlg.exec() != QDialog.DialogCode.Accepted |
120 else: |
136 else: |
121 EricMessageBox.information( |
137 EricMessageBox.information( |
122 None, |
138 None, |
123 QCoreApplication.translate( |
139 QCoreApplication.translate( |
124 "GreaseMonkeyManager", |
140 "GreaseMonkeyManager", "Install GreaseMonkey Script" |
125 "Install GreaseMonkey Script"), |
141 ), |
126 QCoreApplication.translate( |
142 QCoreApplication.translate( |
127 "GreaseMonkeyManager", |
143 "GreaseMonkeyManager", """'{0}' is already installed.""" |
128 """'{0}' is already installed.""").format( |
144 ).format(script.fullName()), |
129 script.fullName()) |
|
130 ) |
145 ) |
131 |
146 |
132 if deleteScript: |
147 if deleteScript: |
133 with contextlib.suppress(OSError): |
148 with contextlib.suppress(OSError): |
134 os.remove(fileName) |
149 os.remove(fileName) |
135 |
150 |
136 def scriptsDirectory(self): |
151 def scriptsDirectory(self): |
137 """ |
152 """ |
138 Public method to get the path of the scripts directory. |
153 Public method to get the path of the scripts directory. |
139 |
154 |
140 @return path of the scripts directory (string) |
155 @return path of the scripts directory (string) |
141 """ |
156 """ |
142 return os.path.join( |
157 return os.path.join(Utilities.getConfigDir(), "web_browser", "greasemonkey") |
143 Utilities.getConfigDir(), "web_browser", "greasemonkey") |
158 |
144 |
|
145 def requireScriptsDirectory(self): |
159 def requireScriptsDirectory(self): |
146 """ |
160 """ |
147 Public method to get the path of the scripts directory. |
161 Public method to get the path of the scripts directory. |
148 |
162 |
149 @return path of the scripts directory (string) |
163 @return path of the scripts directory (string) |
150 """ |
164 """ |
151 return os.path.join(self.scriptsDirectory(), "requires") |
165 return os.path.join(self.scriptsDirectory(), "requires") |
152 |
166 |
153 def requireScripts(self, urlList): |
167 def requireScripts(self, urlList): |
154 """ |
168 """ |
155 Public method to get the sources of all required scripts. |
169 Public method to get the sources of all required scripts. |
156 |
170 |
157 @param urlList list of URLs (list of string) |
171 @param urlList list of URLs (list of string) |
158 @return sources of all required scripts (string) |
172 @return sources of all required scripts (string) |
159 """ |
173 """ |
160 requiresDir = QDir(self.requireScriptsDirectory()) |
174 requiresDir = QDir(self.requireScriptsDirectory()) |
161 if not requiresDir.exists() or len(urlList) == 0: |
175 if not requiresDir.exists() or len(urlList) == 0: |
162 return "" |
176 return "" |
163 |
177 |
164 script = "" |
178 script = "" |
165 |
179 |
166 settings = QSettings( |
180 settings = QSettings( |
167 os.path.join(self.requireScriptsDirectory(), "requires.ini"), |
181 os.path.join(self.requireScriptsDirectory(), "requires.ini"), |
168 QSettings.Format.IniFormat) |
182 QSettings.Format.IniFormat, |
|
183 ) |
169 settings.beginGroup("Files") |
184 settings.beginGroup("Files") |
170 for url in urlList: |
185 for url in urlList: |
171 if settings.contains(url): |
186 if settings.contains(url): |
172 fileName = settings.value(url) |
187 fileName = settings.value(url) |
173 if not pathlib.Path(fileName).is_absolute(): |
188 if not pathlib.Path(fileName).is_absolute(): |
174 fileName = os.path.join(self.requireScriptsDirectory(), |
189 fileName = os.path.join(self.requireScriptsDirectory(), fileName) |
175 fileName) |
|
176 try: |
190 try: |
177 with open(fileName, "r", encoding="utf-8") as f: |
191 with open(fileName, "r", encoding="utf-8") as f: |
178 source = f.read().strip() |
192 source = f.read().strip() |
179 except OSError: |
193 except OSError: |
180 source = "" |
194 source = "" |
181 if source: |
195 if source: |
182 script += source + "\n" |
196 script += source + "\n" |
183 |
197 |
184 return script |
198 return script |
185 |
199 |
186 def saveConfiguration(self): |
200 def saveConfiguration(self): |
187 """ |
201 """ |
188 Public method to save the configuration. |
202 Public method to save the configuration. |
189 """ |
203 """ |
190 Preferences.setWebBrowser("GreaseMonkeyDisabledScripts", |
204 Preferences.setWebBrowser("GreaseMonkeyDisabledScripts", self.__disabledScripts) |
191 self.__disabledScripts) |
205 |
192 |
|
193 def allScripts(self): |
206 def allScripts(self): |
194 """ |
207 """ |
195 Public method to get a list of all scripts. |
208 Public method to get a list of all scripts. |
196 |
209 |
197 @return list of all scripts (list of GreaseMonkeyScript) |
210 @return list of all scripts (list of GreaseMonkeyScript) |
198 """ |
211 """ |
199 return self.__scripts[:] |
212 return self.__scripts[:] |
200 |
213 |
201 def containsScript(self, fullName): |
214 def containsScript(self, fullName): |
202 """ |
215 """ |
203 Public method to check, if the given script exists. |
216 Public method to check, if the given script exists. |
204 |
217 |
205 @param fullName full name of the script (string) |
218 @param fullName full name of the script (string) |
206 @return flag indicating the existence (boolean) |
219 @return flag indicating the existence (boolean) |
207 """ |
220 """ |
208 return any(script.fullName() == fullName for script in self.__scripts) |
221 return any(script.fullName() == fullName for script in self.__scripts) |
209 |
222 |
210 def enableScript(self, script): |
223 def enableScript(self, script): |
211 """ |
224 """ |
212 Public method to enable the given script. |
225 Public method to enable the given script. |
213 |
226 |
214 @param script script to be enabled (GreaseMonkeyScript) |
227 @param script script to be enabled (GreaseMonkeyScript) |
215 """ |
228 """ |
216 script.setEnabled(True) |
229 script.setEnabled(True) |
217 fullName = script.fullName() |
230 fullName = script.fullName() |
218 if fullName in self.__disabledScripts: |
231 if fullName in self.__disabledScripts: |
219 self.__disabledScripts.remove(fullName) |
232 self.__disabledScripts.remove(fullName) |
220 |
233 |
221 collection = WebBrowserWindow.webProfile().scripts() |
234 collection = WebBrowserWindow.webProfile().scripts() |
222 collection.insert(script.webScript()) |
235 collection.insert(script.webScript()) |
223 |
236 |
224 def disableScript(self, script): |
237 def disableScript(self, script): |
225 """ |
238 """ |
226 Public method to disable the given script. |
239 Public method to disable the given script. |
227 |
240 |
228 @param script script to be disabled (GreaseMonkeyScript) |
241 @param script script to be disabled (GreaseMonkeyScript) |
229 """ |
242 """ |
230 script.setEnabled(False) |
243 script.setEnabled(False) |
231 fullName = script.fullName() |
244 fullName = script.fullName() |
232 if fullName not in self.__disabledScripts: |
245 if fullName not in self.__disabledScripts: |
233 self.__disabledScripts.append(fullName) |
246 self.__disabledScripts.append(fullName) |
234 |
247 |
235 collection = WebBrowserWindow.webProfile().scripts() |
248 collection = WebBrowserWindow.webProfile().scripts() |
236 foundScripts = collection.find(fullName) |
249 foundScripts = collection.find(fullName) |
237 if foundScripts: |
250 if foundScripts: |
238 collection.remove(foundScripts[0]) |
251 collection.remove(foundScripts[0]) |
239 |
252 |
240 def addScript(self, script): |
253 def addScript(self, script): |
241 """ |
254 """ |
242 Public method to add a script. |
255 Public method to add a script. |
243 |
256 |
244 @param script script to be added (GreaseMonkeyScript) |
257 @param script script to be added (GreaseMonkeyScript) |
245 @return flag indicating success (boolean) |
258 @return flag indicating success (boolean) |
246 """ |
259 """ |
247 if not script or not script.isValid(): |
260 if not script or not script.isValid(): |
248 return False |
261 return False |
249 |
262 |
250 self.__scripts.append(script) |
263 self.__scripts.append(script) |
251 script.scriptChanged.connect(lambda: self.__scriptChanged(script)) |
264 script.scriptChanged.connect(lambda: self.__scriptChanged(script)) |
252 |
265 |
253 collection = WebBrowserWindow.webProfile().scripts() |
266 collection = WebBrowserWindow.webProfile().scripts() |
254 collection.insert(script.webScript()) |
267 collection.insert(script.webScript()) |
255 |
268 |
256 self.scriptsChanged.emit() |
269 self.scriptsChanged.emit() |
257 return True |
270 return True |
258 |
271 |
259 def removeScript(self, script, removeFile=True): |
272 def removeScript(self, script, removeFile=True): |
260 """ |
273 """ |
261 Public method to remove a script. |
274 Public method to remove a script. |
262 |
275 |
263 @param script script to be removed (GreaseMonkeyScript) |
276 @param script script to be removed (GreaseMonkeyScript) |
264 @param removeFile flag indicating to remove the script file as well |
277 @param removeFile flag indicating to remove the script file as well |
265 (bool) |
278 (bool) |
266 @return flag indicating success (boolean) |
279 @return flag indicating success (boolean) |
267 """ |
280 """ |
268 if not script: |
281 if not script: |
269 return False |
282 return False |
270 |
283 |
271 with contextlib.suppress(ValueError): |
284 with contextlib.suppress(ValueError): |
272 self.__scripts.remove(script) |
285 self.__scripts.remove(script) |
273 |
286 |
274 fullName = script.fullName() |
287 fullName = script.fullName() |
275 collection = WebBrowserWindow.webProfile().scripts() |
288 collection = WebBrowserWindow.webProfile().scripts() |
276 foundScripts = collection.find(fullName) |
289 foundScripts = collection.find(fullName) |
277 if foundScripts: |
290 if foundScripts: |
278 collection.remove(foundScripts[0]) |
291 collection.remove(foundScripts[0]) |
279 |
292 |
280 if fullName in self.__disabledScripts: |
293 if fullName in self.__disabledScripts: |
281 self.__disabledScripts.remove(fullName) |
294 self.__disabledScripts.remove(fullName) |
282 |
295 |
283 if removeFile: |
296 if removeFile: |
284 os.unlink(script.fileName()) |
297 os.unlink(script.fileName()) |
285 del script |
298 del script |
286 |
299 |
287 self.scriptsChanged.emit() |
300 self.scriptsChanged.emit() |
288 return True |
301 return True |
289 |
302 |
290 def canRunOnScheme(self, scheme): |
303 def canRunOnScheme(self, scheme): |
291 """ |
304 """ |
292 Public method to check, if scripts can be run on a scheme. |
305 Public method to check, if scripts can be run on a scheme. |
293 |
306 |
294 @param scheme scheme to check (string) |
307 @param scheme scheme to check (string) |
295 @return flag indicating, that scripts can be run (boolean) |
308 @return flag indicating, that scripts can be run (boolean) |
296 """ |
309 """ |
297 return scheme in ["http", "https", "data", "ftp"] |
310 return scheme in ["http", "https", "data", "ftp"] |
298 |
311 |
299 def __load(self): |
312 def __load(self): |
300 """ |
313 """ |
301 Private slot to load the available scripts into the manager. |
314 Private slot to load the available scripts into the manager. |
302 """ |
315 """ |
303 scriptsDir = QDir(self.scriptsDirectory()) |
316 scriptsDir = QDir(self.scriptsDirectory()) |
304 if not scriptsDir.exists(): |
317 if not scriptsDir.exists(): |
305 scriptsDir.mkpath(self.scriptsDirectory()) |
318 scriptsDir.mkpath(self.scriptsDirectory()) |
306 |
319 |
307 if not scriptsDir.exists("requires"): |
320 if not scriptsDir.exists("requires"): |
308 scriptsDir.mkdir("requires") |
321 scriptsDir.mkdir("requires") |
309 |
322 |
310 self.__disabledScripts = Preferences.getWebBrowser( |
323 self.__disabledScripts = Preferences.getWebBrowser( |
311 "GreaseMonkeyDisabledScripts") |
324 "GreaseMonkeyDisabledScripts" |
312 |
325 ) |
|
326 |
313 from .GreaseMonkeyScript import GreaseMonkeyScript |
327 from .GreaseMonkeyScript import GreaseMonkeyScript |
|
328 |
314 for fileName in scriptsDir.entryList(["*.js"], QDir.Filter.Files): |
329 for fileName in scriptsDir.entryList(["*.js"], QDir.Filter.Files): |
315 absolutePath = scriptsDir.absoluteFilePath(fileName) |
330 absolutePath = scriptsDir.absoluteFilePath(fileName) |
316 script = GreaseMonkeyScript(self, absolutePath) |
331 script = GreaseMonkeyScript(self, absolutePath) |
317 |
332 |
318 if not script.isValid(): |
333 if not script.isValid(): |
319 del script |
334 del script |
320 continue |
335 continue |
321 |
336 |
322 self.__scripts.append(script) |
337 self.__scripts.append(script) |
323 |
338 |
324 if script.fullName() in self.__disabledScripts: |
339 if script.fullName() in self.__disabledScripts: |
325 script.setEnabled(False) |
340 script.setEnabled(False) |
326 else: |
341 else: |
327 collection = WebBrowserWindow.webProfile().scripts() |
342 collection = WebBrowserWindow.webProfile().scripts() |
328 collection.insert(script.webScript()) |
343 collection.insert(script.webScript()) |
329 |
344 |
330 self.__jsObject.setSettingsFile(os.path.join( |
345 self.__jsObject.setSettingsFile( |
331 Utilities.getConfigDir(), "web_browser", |
346 os.path.join( |
332 "greasemonkey_values.ini")) |
347 Utilities.getConfigDir(), "web_browser", "greasemonkey_values.ini" |
|
348 ) |
|
349 ) |
333 ExternalJsObject.registerExtraObject("GreaseMonkey", self.__jsObject) |
350 ExternalJsObject.registerExtraObject("GreaseMonkey", self.__jsObject) |
334 |
351 |
335 def __scriptChanged(self, script): |
352 def __scriptChanged(self, script): |
336 """ |
353 """ |
337 Private slot handling a changed script. |
354 Private slot handling a changed script. |
338 |
355 |
339 @param script reference to the changed script |
356 @param script reference to the changed script |
340 @type GreaseMonkeyScript |
357 @type GreaseMonkeyScript |
341 """ |
358 """ |
342 fullName = script.fullName() |
359 fullName = script.fullName() |
343 collection = WebBrowserWindow.webProfile().scripts() |
360 collection = WebBrowserWindow.webProfile().scripts() |