src/eric7/WebBrowser/OpenSearch/OpenSearchManager.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
--- a/src/eric7/WebBrowser/OpenSearch/OpenSearchManager.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/WebBrowser/OpenSearch/OpenSearchManager.py	Wed Jul 13 14:55:47 2022 +0200
@@ -10,9 +10,7 @@
 import os
 import contextlib
 
-from PyQt6.QtCore import (
-    pyqtSignal, QObject, QUrl, QFile, QDir, QIODevice, QUrlQuery
-)
+from PyQt6.QtCore import pyqtSignal, QObject, QUrl, QFile, QDir, QIODevice, QUrlQuery
 from PyQt6.QtWidgets import QLineEdit, QInputDialog
 from PyQt6.QtNetwork import QNetworkRequest, QNetworkReply
 
@@ -27,164 +25,166 @@
 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 = ericApp()
         super().__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 WebBrowser.WebBrowserWindow import WebBrowserWindow
 
         reply = WebBrowserWindow.networkManager().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)
@@ -192,44 +192,45 @@
         file_ = QFile(filename)
         if not file_.open(QIODevice.OpenModeFlag.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 addEngineFromForm(self, res, view):
         """
         Public method to add a new search engine from a form.
-        
+
         @param res result of the JavaScript run on by
             WebBrowserView.__addSearchEngine()
         @type dict or None
@@ -238,165 +239,168 @@
         """
         if not res:
             return
-        
+
         method = res["method"]
         actionUrl = QUrl(res["action"])
         inputName = res["inputName"]
-        
+
         if method != "get":
             EricMessageBox.warning(
                 self,
                 self.tr("Method not supported"),
-                self.tr(
-                    """{0} method is not supported.""").format(method.upper()))
+                self.tr("""{0} method is not supported.""").format(method.upper()),
+            )
             return
-        
+
         if actionUrl.isRelative():
             actionUrl = view.url().resolved(actionUrl)
-        
+
         searchUrlQuery = QUrlQuery(actionUrl)
         searchUrlQuery.addQueryItem(inputName, "{searchTerms}")
-        
+
         inputFields = res["inputs"]
         for inputField in inputFields:
             name = inputField[0]
             value = inputField[1]
-            
+
             if not name or name == inputName or not value:
                 continue
-            
+
             searchUrlQuery.addQueryItem(name, value)
-        
+
         engineName, ok = QInputDialog.getText(
             view,
             self.tr("Engine name"),
             self.tr("Enter a name for the engine"),
-            QLineEdit.EchoMode.Normal)
+            QLineEdit.EchoMode.Normal,
+        )
         if not ok:
             return
-        
+
         actionUrl.setQuery(searchUrlQuery)
-        
+
         from .OpenSearchEngine import OpenSearchEngine
+
         engine = OpenSearchEngine()
         engine.setName(engineName)
         engine.setDescription(engineName)
         engine.setSearchUrlTemplate(
-            actionUrl.toDisplayString(
-                QUrl.ComponentFormattingOption.FullyDecoded))
+            actionUrl.toDisplayString(QUrl.ComponentFormattingOption.FullyDecoded)
+        )
         engine.setImage(view.icon().pixmap(16, 16).toImage())
-        
+
         self.__addEngineByEngine(engine)
-    
+
     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]:
+        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))
+            self.generateEngineFileName(name)
+        )
         os.unlink(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 += '_'
+                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.OpenModeFlag.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.setWebBrowser("WebSearchEngine", self.__current)
         keywords = []
         for k in self.__keywords:
             if self.__keywords[k]:
                 keywords.append((k, self.__keywords[k].name()))
         Preferences.setWebBrowser("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 os.path.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.
@@ -404,22 +408,19 @@
         self.__loading = True
         self.__current = Preferences.getWebBrowser("WebSearchEngine")
         keywords = Preferences.getWebBrowser("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
-        ):
+
+        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.
@@ -427,86 +428,88 @@
         from .OpenSearchReader import OpenSearchReader
 
         reader = OpenSearchReader()
-        defaultEnginesDirectory = os.path.join(os.path.dirname(__file__),
-                                               "DefaultSearchEngines")
-        for engineFileName in (
-            QDir(defaultEnginesDirectory, "*.xml").entryList()
-        ):
-            engineFile = QFile(os.path.join(defaultEnginesDirectory,
-                                            engineFileName))
+        defaultEnginesDirectory = os.path.join(
+            os.path.dirname(__file__), "DefaultSearchEngines"
+        )
+        for engineFileName in QDir(defaultEnginesDirectory, "*.xml").entryList():
+            engineFile = QFile(os.path.join(defaultEnginesDirectory, engineFileName))
             if not engineFile.open(QIODevice.OpenModeFlag.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(), "web_browser", "searchengines")
-    
+        return os.path.join(Utilities.getConfigDir(), "web_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 = EricMessageBox.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))
+                """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.NetworkError.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 WebBrowser.WebBrowserWindow import WebBrowserWindow
+
             WebBrowserWindow.getWindow().statusBar().showMessage(
-                reply.errorString(), 10000)
-    
+                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)
         """
@@ -514,77 +517,77 @@
             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:
             with contextlib.suppress(KeyError):
                 del self.__keywords[keyword]
         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

eric ide

mercurial