eric6/Helpviewer/OpenSearch/OpenSearchManager.py

changeset 7220
5cf645f6daab
parent 7218
eaf2cf171f3a
parent 7211
1c97f3142fa8
child 7221
0485ccdf7877
diff -r eaf2cf171f3a -r 5cf645f6daab eric6/Helpviewer/OpenSearch/OpenSearchManager.py
--- a/eric6/Helpviewer/OpenSearch/OpenSearchManager.py	Sat Sep 07 14:45:27 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,535 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2009 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module implementing a manager for open search engines.
-"""
-
-from __future__ import unicode_literals
-
-import os
-
-from PyQt5.QtCore import pyqtSignal, QObject, QUrl, QFile, QDir, QIODevice
-from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
-
-from E5Gui.E5Application import e5App
-from E5Gui import E5MessageBox
-
-from Utilities.AutoSaver import AutoSaver
-import Utilities
-import Preferences
-
-
-class OpenSearchManager(QObject):
-    """
-    Class implementing a manager for open search engines.
-    
-    @signal changed() emitted to indicate a change
-    @signal currentEngineChanged() emitted to indicate a change of
-            the current search engine
-    """
-    changed = pyqtSignal()
-    currentEngineChanged = pyqtSignal()
-    
-    def __init__(self, parent=None):
-        """
-        Constructor
-        
-        @param parent reference to the parent object (QObject)
-        """
-        if parent is None:
-            parent = e5App()
-        super(OpenSearchManager, self).__init__(parent)
-        
-        self.__replies = []
-        self.__engines = {}
-        self.__keywords = {}
-        self.__current = ""
-        self.__loading = False
-        self.__saveTimer = AutoSaver(self, self.save)
-        
-        self.changed.connect(self.__saveTimer.changeOccurred)
-        
-        self.load()
-    
-    def close(self):
-        """
-        Public method to close the open search engines manager.
-        """
-        self.__saveTimer.saveIfNeccessary()
-    
-    def currentEngineName(self):
-        """
-        Public method to get the name of the current search engine.
-        
-        @return name of the current search engine (string)
-        """
-        return self.__current
-    
-    def setCurrentEngineName(self, name):
-        """
-        Public method to set the current engine by name.
-        
-        @param name name of the new current engine (string)
-        """
-        if name not in self.__engines:
-            return
-        
-        self.__current = name
-        self.currentEngineChanged.emit()
-        self.changed.emit()
-    
-    def currentEngine(self):
-        """
-        Public method to get a reference to the current engine.
-        
-        @return reference to the current engine (OpenSearchEngine)
-        """
-        if not self.__current or self.__current not in self.__engines:
-            return None
-        
-        return self.__engines[self.__current]
-    
-    def setCurrentEngine(self, engine):
-        """
-        Public method to set the current engine.
-        
-        @param engine reference to the new current engine (OpenSearchEngine)
-        """
-        if engine is None:
-            return
-        
-        for engineName in self.__engines:
-            if self.__engines[engineName] == engine:
-                self.setCurrentEngineName(engineName)
-                break
-    
-    def engine(self, name):
-        """
-        Public method to get a reference to the named engine.
-        
-        @param name name of the engine (string)
-        @return reference to the engine (OpenSearchEngine)
-        """
-        if name not in self.__engines:
-            return None
-        
-        return self.__engines[name]
-    
-    def engineExists(self, name):
-        """
-        Public method to check, if an engine exists.
-        
-        @param name name of the engine (string)
-        @return flag indicating an existing engine (boolean)
-        """
-        return name in self.__engines
-    
-    def allEnginesNames(self):
-        """
-        Public method to get a list of all engine names.
-        
-        @return sorted list of all engine names (list of strings)
-        """
-        return sorted(self.__engines.keys())
-    
-    def enginesCount(self):
-        """
-        Public method to get the number of available engines.
-        
-        @return number of engines (integer)
-        """
-        return len(self.__engines)
-    
-    def addEngine(self, engine):
-        """
-        Public method to add a new search engine.
-        
-        @param engine URL of the engine definition file (QUrl) or
-            name of a file containing the engine definition (string)
-            or reference to an engine object (OpenSearchEngine)
-        @return flag indicating success (boolean)
-        """
-        from .OpenSearchEngine import OpenSearchEngine
-        if isinstance(engine, QUrl):
-            return self.__addEngineByUrl(engine)
-        elif isinstance(engine, OpenSearchEngine):
-            return self.__addEngineByEngine(engine)
-        else:
-            return self.__addEngineByFile(engine)
-    
-    def __addEngineByUrl(self, url):
-        """
-        Private method to add a new search engine given its URL.
-        
-        @param url URL of the engine definition file (QUrl)
-        @return flag indicating success (boolean)
-        """
-        if not url.isValid():
-            return False
-        
-        from Helpviewer.HelpWindow import HelpWindow
-
-        reply = HelpWindow.networkAccessManager().get(QNetworkRequest(url))
-        reply.finished.connect(lambda: self.__engineFromUrlAvailable(reply))
-        reply.setParent(self)
-        self.__replies.append(reply)
-        
-        return True
-    
-    def __addEngineByFile(self, filename):
-        """
-        Private method to add a new search engine given a filename.
-        
-        @param filename name of a file containing the engine definition
-            (string)
-        @return flag indicating success (boolean)
-        """
-        file_ = QFile(filename)
-        if not file_.open(QIODevice.ReadOnly):
-            return False
-        
-        from .OpenSearchReader import OpenSearchReader
-        reader = OpenSearchReader()
-        engine = reader.read(file_)
-        
-        if not self.__addEngineByEngine(engine):
-            return False
-        
-        return True
-    
-    def __addEngineByEngine(self, engine):
-        """
-        Private method to add a new search engine given a reference to an
-        engine.
-        
-        @param engine reference to an engine object (OpenSearchEngine)
-        @return flag indicating success (boolean)
-        """
-        if engine is None:
-            return False
-        
-        if not engine.isValid():
-            return False
-        
-        if engine.name() in self.__engines:
-            return False
-        
-        engine.setParent(self)
-        self.__engines[engine.name()] = engine
-        
-        self.changed.emit()
-        
-        return True
-    
-    def removeEngine(self, name):
-        """
-        Public method to remove an engine.
-        
-        @param name name of the engine (string)
-        """
-        if len(self.__engines) <= 1:
-            return
-        
-        if name not in self.__engines:
-            return
-        
-        engine = self.__engines[name]
-        for keyword in [k for k in self.__keywords
-                        if self.__keywords[k] == engine]:
-            del self.__keywords[keyword]
-        del self.__engines[name]
-        
-        file_ = QDir(self.enginesDirectory()).filePath(
-            self.generateEngineFileName(name))
-        QFile.remove(file_)
-        
-        if name == self.__current:
-            self.setCurrentEngineName(list(self.__engines.keys())[0])
-        
-        self.changed.emit()
-    
-    def generateEngineFileName(self, engineName):
-        """
-        Public method to generate a valid engine file name.
-        
-        @param engineName name of the engine (string)
-        @return valid engine file name (string)
-        """
-        fileName = ""
-        
-        # strip special characters
-        for c in engineName:
-            if c.isspace():
-                fileName += '_'
-                continue
-            
-            if c.isalnum():
-                fileName += c
-        
-        fileName += ".xml"
-        
-        return fileName
-    
-    def saveDirectory(self, dirName):
-        """
-        Public method to save the search engine definitions to files.
-        
-        @param dirName name of the directory to write the files to (string)
-        """
-        qdir = QDir()
-        if not qdir.mkpath(dirName):
-            return
-        qdir.setPath(dirName)
-        
-        from .OpenSearchWriter import OpenSearchWriter
-        writer = OpenSearchWriter()
-        
-        for engine in list(self.__engines.values()):
-            name = self.generateEngineFileName(engine.name())
-            fileName = qdir.filePath(name)
-            
-            file = QFile(fileName)
-            if not file.open(QIODevice.WriteOnly):
-                continue
-            
-            writer.write(file, engine)
-    
-    def save(self):
-        """
-        Public method to save the search engines configuration.
-        """
-        if self.__loading:
-            return
-        
-        self.saveDirectory(self.enginesDirectory())
-        
-        Preferences.setHelp("WebSearchEngine", self.__current)
-        keywords = []
-        for k in self.__keywords:
-            if self.__keywords[k]:
-                keywords.append((k, self.__keywords[k].name()))
-        Preferences.setHelp("WebSearchKeywords", keywords)
-    
-    def loadDirectory(self, dirName):
-        """
-        Public method to load the search engine definitions from files.
-        
-        @param dirName name of the directory to load the files from (string)
-        @return flag indicating success (boolean)
-        """
-        if not QFile.exists(dirName):
-            return False
-        
-        success = False
-        
-        qdir = QDir(dirName)
-        for name in qdir.entryList(["*.xml"]):
-            fileName = qdir.filePath(name)
-            if self.__addEngineByFile(fileName):
-                success = True
-        
-        return success
-    
-    def load(self):
-        """
-        Public method to load the search engines configuration.
-        """
-        self.__loading = True
-        self.__current = Preferences.getHelp("WebSearchEngine")
-        keywords = Preferences.getHelp("WebSearchKeywords")
-        
-        if not self.loadDirectory(self.enginesDirectory()):
-            self.restoreDefaults()
-        
-        for keyword, engineName in keywords:
-            self.__keywords[keyword] = self.engine(engineName)
-        
-        if self.__current not in self.__engines and \
-           len(self.__engines) > 0:
-            self.__current = list(self.__engines.keys())[0]
-        
-        self.__loading = False
-        self.currentEngineChanged.emit()
-    
-    def restoreDefaults(self):
-        """
-        Public method to restore the default search engines.
-        """
-        from .OpenSearchReader import OpenSearchReader
-        from .DefaultSearchEngines import DefaultSearchEngines_rc
-        # __IGNORE_WARNING__
-        
-        defaultEngineFiles = ["Amazoncom.xml", "Bing.xml",
-                              "DeEn_Beolingus.xml", "DuckDuckGo.xml",
-                              "Facebook.xml", "Google.xml",
-                              "Google_Im_Feeling_Lucky.xml", "LEO_DeuEng.xml",
-                              "LinuxMagazin.xml", "Reddit.xml", "Wikia.xml",
-                              "Wikia_en.xml", "Wikipedia.xml",
-                              "Wiktionary.xml", "Yahoo.xml", "YouTube.xml", ]
-        # Keep this list in sync with the contents of the resource file.
-
-        reader = OpenSearchReader()
-        for engineFileName in defaultEngineFiles:
-            engineFile = QFile(":/" + engineFileName)
-            if not engineFile.open(QIODevice.ReadOnly):
-                continue
-            engine = reader.read(engineFile)
-            self.__addEngineByEngine(engine)
-    
-    def enginesDirectory(self):
-        """
-        Public method to determine the directory containing the search engine
-        descriptions.
-        
-        @return directory name (string)
-        """
-        return os.path.join(
-            Utilities.getConfigDir(), "browser", "searchengines")
-    
-    def __confirmAddition(self, engine):
-        """
-        Private method to confirm the addition of a new search engine.
-        
-        @param engine reference to the engine to be added (OpenSearchEngine)
-        @return flag indicating the engine shall be added (boolean)
-        """
-        if engine is None or not engine.isValid():
-            return False
-        
-        host = QUrl(engine.searchUrlTemplate()).host()
-        
-        res = E5MessageBox.yesNo(
-            None,
-            "",
-            self.tr(
-                """<p>Do you want to add the following engine to your"""
-                """ list of search engines?<br/><br/>Name: {0}<br/>"""
-                """Searches on: {1}</p>""").format(engine.name(), host))
-        return res
-    
-    def __engineFromUrlAvailable(self, reply):
-        """
-        Private slot to add a search engine from the net.
-        
-        @param reply reference to the network reply
-        @type QNetworkReply
-        """
-        reply.close()
-        if reply in self.__replies:
-            self.__replies.remove(reply)
-        
-        if reply.error() == QNetworkReply.NoError:
-            from .OpenSearchReader import OpenSearchReader
-            reader = OpenSearchReader()
-            engine = reader.read(reply)
-            
-            if not engine.isValid():
-                return
-            
-            if self.engineExists(engine.name()):
-                return
-            
-            if not self.__confirmAddition(engine):
-                return
-            
-            if not self.__addEngineByEngine(engine):
-                return
-        else:
-            # some error happened
-            from Helpviewer.HelpWindow import HelpWindow
-            HelpWindow.getWindow().statusBar().showMessage(
-                reply.errorString(), 10000)
-    
-    def convertKeywordSearchToUrl(self, keywordSearch):
-        """
-        Public method to get the search URL for a keyword search.
-        
-        @param keywordSearch search string for keyword search (string)
-        @return search URL (QUrl)
-        """
-        try:
-            keyword, term = keywordSearch.split(" ", 1)
-        except ValueError:
-            return QUrl()
-        
-        if not term:
-            return QUrl()
-        
-        engine = self.engineForKeyword(keyword)
-        if engine:
-            return engine.searchUrl(term)
-        
-        return QUrl()
-    
-    def engineForKeyword(self, keyword):
-        """
-        Public method to get the engine for a keyword.
-        
-        @param keyword keyword to get engine for (string)
-        @return reference to the search engine object (OpenSearchEngine)
-        """
-        if keyword and keyword in self.__keywords:
-            return self.__keywords[keyword]
-        
-        return None
-    
-    def setEngineForKeyword(self, keyword, engine):
-        """
-        Public method to set the engine for a keyword.
-        
-        @param keyword keyword to get engine for (string)
-        @param engine reference to the search engine object (OpenSearchEngine)
-            or None to remove the keyword
-        """
-        if not keyword:
-            return
-        
-        if engine is None:
-            try:
-                del self.__keywords[keyword]
-            except KeyError:
-                pass
-        else:
-            self.__keywords[keyword] = engine
-        
-        self.changed.emit()
-    
-    def keywordsForEngine(self, engine):
-        """
-        Public method to get the keywords for a given engine.
-        
-        @param engine reference to the search engine object (OpenSearchEngine)
-        @return list of keywords (list of strings)
-        """
-        return [k for k in self.__keywords if self.__keywords[k] == engine]
-    
-    def setKeywordsForEngine(self, engine, keywords):
-        """
-        Public method to set the keywords for an engine.
-        
-        @param engine reference to the search engine object (OpenSearchEngine)
-        @param keywords list of keywords (list of strings)
-        """
-        if engine is None:
-            return
-        
-        for keyword in self.keywordsForEngine(engine):
-            del self.__keywords[keyword]
-        
-        for keyword in keywords:
-            if not keyword:
-                continue
-            
-            self.__keywords[keyword] = engine
-        
-        self.changed.emit()
-    
-    def enginesChanged(self):
-        """
-        Public slot to tell the search engine manager, that something has
-        changed.
-        """
-        self.changed.emit()

eric ide

mercurial