Helpviewer/GreaseMonkey/GreaseMonkeyManager.py

changeset 1953
26aa6fd94dc2
child 1954
5072605ad4dd
diff -r af4103f0e93f -r 26aa6fd94dc2 Helpviewer/GreaseMonkey/GreaseMonkeyManager.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Helpviewer/GreaseMonkey/GreaseMonkeyManager.py	Sun Jul 22 15:32:52 2012 +0200
@@ -0,0 +1,306 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the manager for GreaseMonkey scripts.
+"""
+
+import os
+
+from PyQt4.QtCore import pyqtSignal, QObject, QTimer, QFile, QDir, QSettings, QUrl, \
+    QByteArray
+from PyQt4.QtNetwork import QNetworkAccessManager
+
+from .GreaseMonkeyJavaScript import bootstrap_js
+from .GreaseMonkeyDownloader import GreaseMonkeyDownloader
+from .GreaseMonkeyScript import GreaseMonkeyScript
+
+from .GreaseMonkeyConfiguration.GreaseMonkeyConfigurationDialog import \
+    GreaseMonkeyConfigurationDialog
+
+from Helpviewer.Network.EmptyNetworkReply import EmptyNetworkReply
+
+import Utilities
+import Preferences
+
+
+class GreaseMonkeyManager(QObject):
+    """
+    Class implementing the manager for GreaseMonkey scripts.
+    """
+    scriptsChanged = pyqtSignal()
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent object (QObject)
+        """
+        super().__init__(parent)
+        
+        self.__disabledScripts = []
+        self.__endScripts = []
+        self.__startScripts = []
+        self.__downloaders = []
+        
+        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)
+        """
+        self.__configDiaolg = GreaseMonkeyConfigurationDialog(self, parent)
+        self.__configDiaolg.show()
+    
+    def downloadScript(self, request):
+        """
+        Public method to download a GreaseMonkey script.
+        
+        @param request reference to the request (QNetworkRequest)
+        """
+        downloader = GreaseMonkeyDownloader(request, self)
+        downloader.finished.connect(self.__downloaderFinished)
+        self.__downloaders.append(downloader)
+    
+    def __downloaderFinished(self):
+        """
+        Private slot to handle the completion of a script download.
+        """
+        downloader = self.sender()
+        if downloader is None or downloader not in self.__downloaders:
+            return
+        
+        self.__downloaders.remove(downloader)
+    
+    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(), "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.IniFormat)
+        settings.beginGroup("Files")
+        for url in urlList:
+            if settings.contains(url):
+                fileName = settings.value(url)
+                try:
+                    f = open(fileName, "r")
+                    source = f.read()
+                    f.close()
+                except (IOError, OSError):
+                    source = ""
+                script += source.strip() + "\n"
+        
+        return script
+    
+    def saveConfiguration(self):
+        """
+        Public method to save the configuration.
+        """
+        Preferences.setHelp("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.__startScripts[:] + self.__endScripts[:]
+    
+    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)
+        """
+        for script in self.__startScripts:
+            if script.fullName() == fullName:
+                return True
+        for script in self.__endScripts:
+            if script.fullName() == fullName:
+                return True
+        return False
+    
+    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)
+    
+    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)
+    
+    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:
+            return False
+        
+        if script.startAt() == GreaseMonkeyScript.DocumentStart:
+            self.__startScripts.append(script)
+        else:
+            self.__endScripts.append(script)
+        
+        self.scriptsChanged.emit()
+        return True
+    
+    def removeScript(self, script):
+        """
+        Public method to remove a script.
+        
+        @param script script to be removed (GreaseMonkeyScript)
+        @return flag indicating success (boolean)
+        """
+        if not script:
+            return False
+        
+        if script.startAt() == GreaseMonkeyScript.DocumentStart:
+            try:
+                self.__startScripts.remove(script)
+            except ValueError:
+                pass
+        else:
+            try:
+                self.__endScripts.remove(script)
+            except ValueError:
+                pass
+        
+        fullName = script.fullName()
+        if fullName in self.__disabledScripts:
+            self.__disabledScripts.remove(fullName)
+        QFile.remove(script.fileName())
+        
+        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 pageLoadStarted(self):
+        """
+        Public slot to handle the start of loading a page.
+        """
+        frame = self.sender()
+        if not frame:
+            return
+        
+        urlScheme = frame.url().scheme()
+        urlString = bytes(frame.url().toEncoded()).decode()
+        
+        if not self.canRunOnScheme(urlScheme):
+            return
+        
+        for script in self.__startScripts:
+            if script.match(urlString):
+                frame.evaluateJavaScript(bootstrap_js + script.script())
+        
+        for script in self.__endScripts:
+            if script.match(urlString):
+                javascript = 'window.addEventListener("DOMContentLoaded",' \
+                    'function(e) {{ {0} }}, false);'.format(
+                    bootstrap_js + script.script())
+                frame.evaluateJavaScript(javascript)
+    
+    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.getHelp("GreaseMonkeyDisabledScripts")
+        
+        for fileName in scriptsDir.entryList(["*.js"], QDir.Files):
+            absolutePath = scriptsDir.absoluteFilePath(fileName)
+            script = GreaseMonkeyScript(self, absolutePath)
+            
+            if script.fullName() in self.__disabledScripts:
+                script.setEnabled(False)
+            
+            if script.startAt() == GreaseMonkeyScript.DocumentStart:
+                self.__startScripts.append(script)
+            else:
+                self.__endScripts.append(script)
+    
+    def connectPage(self, page):
+        """
+        Public method to allow the GreaseMonkey manager to connect to the page.
+        
+        @param page reference to the web page (HelpWebPage)
+        """
+        page.mainFrame().javaScriptWindowObjectCleared.connect(self.pageLoadStarted)
+    
+    def createRequest(self, op, request, outgoingData=None):
+        """
+        Public method to create a request.
+        
+        @param op the operation to be performed (QNetworkAccessManager.Operation)
+        @param request reference to the request object (QNetworkRequest)
+        @param outgoingData reference to an IODevice containing data to be sent
+            (QIODevice)
+        @return reference to the created reply object (QNetworkReply)
+        """
+        if op == QNetworkAccessManager.GetOperation and \
+           request.rawHeader("X-Eric5-UserLoadAction") == QByteArray("1"):
+            urlString = request.url().toString(QUrl.RemoveFragment | QUrl.RemoveQuery)
+            if urlString.endswith(".user.js"):
+                self.downloadScript(request)
+                return EmptyNetworkReply(self)
+        
+        return None

eric ide

mercurial