eric7/WebBrowser/GreaseMonkey/GreaseMonkeyManager.py

branch
eric7
changeset 8312
800c432b34c8
parent 8240
93b8a353c4bf
child 8318
962bce857696
diff -r 4e8b98454baa -r 800c432b34c8 eric7/WebBrowser/GreaseMonkey/GreaseMonkeyManager.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/WebBrowser/GreaseMonkey/GreaseMonkeyManager.py	Sat May 15 18:45:04 2021 +0200
@@ -0,0 +1,340 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2012 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the manager for GreaseMonkey scripts.
+"""
+
+import os
+import contextlib
+
+from PyQt5.QtCore import (
+    pyqtSignal, pyqtSlot, Qt, QObject, QTimer, QFile, QFileInfo, QDir,
+    QSettings, QMetaObject, QUrl, Q_ARG, QCoreApplication
+)
+from PyQt5.QtWidgets import QDialog
+
+from E5Gui import E5MessageBox
+
+import Utilities
+import Preferences
+
+from WebBrowser.WebBrowserWindow import WebBrowserWindow
+from WebBrowser.JavaScript.ExternalJsObject import ExternalJsObject
+
+from .GreaseMonkeyJsObject import GreaseMonkeyJsObject
+
+
+class GreaseMonkeyManager(QObject):
+    """
+    Class implementing the manager for GreaseMonkey scripts.
+    
+    @signal scriptsChanged() emitted to indicate a change of scripts
+    """
+    scriptsChanged = pyqtSignal()
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent object (QObject)
+        """
+        super().__init__(parent)
+        
+        self.__disabledScripts = []
+        self.__scripts = []
+        self.__downloaders = []
+        
+        self.__jsObject = GreaseMonkeyJsObject(self)
+        
+        QTimer.singleShot(0, self.__load)
+    
+    def showConfigurationDialog(self, parent=None):
+        """
+        Public method to show the configuration dialog.
+        
+        @param parent reference to the parent widget (QWidget)
+        """
+        from .GreaseMonkeyConfiguration import GreaseMonkeyConfigurationDialog
+        self.__configDiaolg = (
+            GreaseMonkeyConfigurationDialog.GreaseMonkeyConfigurationDialog(
+                self, parent)
+        )
+        self.__configDiaolg.show()
+    
+    def downloadScript(self, url):
+        """
+        Public method to download a GreaseMonkey script.
+        
+        @param url URL to download script from
+        @type QUrl
+        """
+        QMetaObject.invokeMethod(
+            self, "doDownloadScript", Qt.ConnectionType.QueuedConnection,
+            Q_ARG(QUrl, url))
+    
+    @pyqtSlot(QUrl)
+    def doDownloadScript(self, url):
+        """
+        Public slot to download a GreaseMonkey script.
+        
+        Note: The download needed to be separated in the invoking part
+        (s.a.) and the one doing the real download because the invoking
+        part runs in a different thread (i.e. the web engine thread).
+        
+        @param url URL to download script from
+        @type QUrl
+        """
+        from .GreaseMonkeyDownloader import GreaseMonkeyDownloader
+        downloader = GreaseMonkeyDownloader(
+            url, self, GreaseMonkeyDownloader.DownloadMainScript)
+        downloader.finished.connect(
+            lambda f: self.__downloaderFinished(f, downloader))
+        self.__downloaders.append(downloader)
+    
+    def __downloaderFinished(self, fileName, downloader):
+        """
+        Private slot to handle the completion of a script download.
+        
+        @param fileName name of the downloaded script
+        @type str
+        @param downloader reference to the downloader object
+        @type GreaseMonkeyDownloader
+        """
+        if downloader in self.__downloaders:
+            self.__downloaders.remove(downloader)
+            
+            deleteScript = True
+            from .GreaseMonkeyScript import GreaseMonkeyScript
+            script = GreaseMonkeyScript(self, fileName)
+            if script.isValid():
+                if not self.containsScript(script.fullName()):
+                    from .GreaseMonkeyAddScriptDialog import (
+                        GreaseMonkeyAddScriptDialog
+                    )
+                    dlg = GreaseMonkeyAddScriptDialog(self, script)
+                    deleteScript = dlg.exec() != QDialog.DialogCode.Accepted
+                else:
+                    E5MessageBox.information(
+                        None,
+                        QCoreApplication.translate(
+                            "GreaseMonkeyManager",
+                            "Install GreaseMonkey Script"),
+                        QCoreApplication.translate(
+                            "GreaseMonkeyManager",
+                            """'{0}' is already installed.""").format(
+                            script.fullName())
+                    )
+            
+            if deleteScript:
+                with contextlib.suppress(OSError):
+                    os.remove(fileName)
+    
+    def scriptsDirectory(self):
+        """
+        Public method to get the path of the scripts directory.
+        
+        @return path of the scripts directory (string)
+        """
+        return os.path.join(
+            Utilities.getConfigDir(), "web_browser", "greasemonkey")
+    
+    def requireScriptsDirectory(self):
+        """
+        Public method to get the path of the scripts directory.
+        
+        @return path of the scripts directory (string)
+        """
+        return os.path.join(self.scriptsDirectory(), "requires")
+    
+    def requireScripts(self, urlList):
+        """
+        Public method to get the sources of all required scripts.
+        
+        @param urlList list of URLs (list of string)
+        @return sources of all required scripts (string)
+        """
+        requiresDir = QDir(self.requireScriptsDirectory())
+        if not requiresDir.exists() or len(urlList) == 0:
+            return ""
+        
+        script = ""
+        
+        settings = QSettings(
+            os.path.join(self.requireScriptsDirectory(), "requires.ini"),
+            QSettings.Format.IniFormat)
+        settings.beginGroup("Files")
+        for url in urlList:
+            if settings.contains(url):
+                fileName = settings.value(url)
+                if not QFileInfo(fileName).isAbsolute():
+                    fileName = os.path.join(self.requireScriptsDirectory(),
+                                            fileName)
+                try:
+                    with open(fileName, "r", encoding="utf-8") as f:
+                        source = f.read().strip()
+                except OSError:
+                    source = ""
+                if source:
+                    script += source + "\n"
+        
+        return script
+    
+    def saveConfiguration(self):
+        """
+        Public method to save the configuration.
+        """
+        Preferences.setWebBrowser("GreaseMonkeyDisabledScripts",
+                                  self.__disabledScripts)
+    
+    def allScripts(self):
+        """
+        Public method to get a list of all scripts.
+        
+        @return list of all scripts (list of GreaseMonkeyScript)
+        """
+        return self.__scripts[:]
+    
+    def containsScript(self, fullName):
+        """
+        Public method to check, if the given script exists.
+        
+        @param fullName full name of the script (string)
+        @return flag indicating the existence (boolean)
+        """
+        return any(script.fullName() == fullName for script in self.__scripts)
+    
+    def enableScript(self, script):
+        """
+        Public method to enable the given script.
+        
+        @param script script to be enabled (GreaseMonkeyScript)
+        """
+        script.setEnabled(True)
+        fullName = script.fullName()
+        if fullName in self.__disabledScripts:
+            self.__disabledScripts.remove(fullName)
+        
+        collection = WebBrowserWindow.webProfile().scripts()
+        collection.insert(script.webScript())
+    
+    def disableScript(self, script):
+        """
+        Public method to disable the given script.
+        
+        @param script script to be disabled (GreaseMonkeyScript)
+        """
+        script.setEnabled(False)
+        fullName = script.fullName()
+        if fullName not in self.__disabledScripts:
+            self.__disabledScripts.append(fullName)
+        
+        collection = WebBrowserWindow.webProfile().scripts()
+        collection.remove(collection.findScript(fullName))
+    
+    def addScript(self, script):
+        """
+        Public method to add a script.
+        
+        @param script script to be added (GreaseMonkeyScript)
+        @return flag indicating success (boolean)
+        """
+        if not script or not script.isValid():
+            return False
+        
+        self.__scripts.append(script)
+        script.scriptChanged.connect(lambda: self.__scriptChanged(script))
+        
+        collection = WebBrowserWindow.webProfile().scripts()
+        collection.insert(script.webScript())
+        
+        self.scriptsChanged.emit()
+        return True
+    
+    def removeScript(self, script, removeFile=True):
+        """
+        Public method to remove a script.
+        
+        @param script script to be removed (GreaseMonkeyScript)
+        @param removeFile flag indicating to remove the script file as well
+            (bool)
+        @return flag indicating success (boolean)
+        """
+        if not script:
+            return False
+        
+        with contextlib.suppress(ValueError):
+            self.__scripts.remove(script)
+        
+        fullName = script.fullName()
+        collection = WebBrowserWindow.webProfile().scripts()
+        collection.remove(collection.findScript(fullName))
+        
+        if fullName in self.__disabledScripts:
+            self.__disabledScripts.remove(fullName)
+        
+        if removeFile:
+            QFile.remove(script.fileName())
+            del script
+        
+        self.scriptsChanged.emit()
+        return True
+    
+    def canRunOnScheme(self, scheme):
+        """
+        Public method to check, if scripts can be run on a scheme.
+        
+        @param scheme scheme to check (string)
+        @return flag indicating, that scripts can be run (boolean)
+        """
+        return scheme in ["http", "https", "data", "ftp"]
+    
+    def __load(self):
+        """
+        Private slot to load the available scripts into the manager.
+        """
+        scriptsDir = QDir(self.scriptsDirectory())
+        if not scriptsDir.exists():
+            scriptsDir.mkpath(self.scriptsDirectory())
+        
+        if not scriptsDir.exists("requires"):
+            scriptsDir.mkdir("requires")
+        
+        self.__disabledScripts = Preferences.getWebBrowser(
+            "GreaseMonkeyDisabledScripts")
+        
+        from .GreaseMonkeyScript import GreaseMonkeyScript
+        for fileName in scriptsDir.entryList(["*.js"], QDir.Filter.Files):
+            absolutePath = scriptsDir.absoluteFilePath(fileName)
+            script = GreaseMonkeyScript(self, absolutePath)
+            
+            if not script.isValid():
+                del script
+                continue
+            
+            self.__scripts.append(script)
+            
+            if script.fullName() in self.__disabledScripts:
+                script.setEnabled(False)
+            else:
+                collection = WebBrowserWindow.webProfile().scripts()
+                collection.insert(script.webScript())
+        
+        self.__jsObject.setSettingsFile(os.path.join(
+            Utilities.getConfigDir(), "web_browser",
+            "greasemonkey_values.ini"))
+        ExternalJsObject.registerExtraObject("GreaseMonkey", self.__jsObject)
+    
+    def __scriptChanged(self, script):
+        """
+        Private slot handling a changed script.
+        
+        @param script reference to the changed script
+        @type GreaseMonkeyScript
+        """
+        fullName = script.fullName()
+        collection = WebBrowserWindow.webProfile().scripts()
+        collection.remove(collection.findScript(fullName))
+        collection.insert(script.webScript())

eric ide

mercurial