src/eric7/WebBrowser/History/HistoryManager.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
--- a/src/eric7/WebBrowser/History/HistoryManager.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/WebBrowser/History/HistoryManager.py	Wed Jul 13 14:55:47 2022 +0200
@@ -11,8 +11,19 @@
 import pathlib
 
 from PyQt6.QtCore import (
-    pyqtSignal, pyqtSlot, QDateTime, QDate, QTime, QUrl, QTimer, QFile,
-    QIODevice, QByteArray, QDataStream, QTemporaryFile, QObject
+    pyqtSignal,
+    pyqtSlot,
+    QDateTime,
+    QDate,
+    QTime,
+    QUrl,
+    QTimer,
+    QFile,
+    QIODevice,
+    QByteArray,
+    QDataStream,
+    QTemporaryFile,
+    QObject,
 )
 
 from EricWidgets import EricMessageBox
@@ -30,10 +41,11 @@
     """
     Class implementing a history entry.
     """
+
     def __init__(self, url=None, dateTime=None, title=None, visitCount=None):
         """
         Constructor
-        
+
         @param url URL of the history entry (string)
         @param dateTime date and time this entry was created (QDateTime)
         @param title title string for the history entry (string)
@@ -43,37 +55,37 @@
         self.dateTime = dateTime and dateTime or QDateTime()
         self.title = title and title or ""
         self.visitCount = visitCount and visitCount or 0
-    
+
     def __eq__(self, other):
         """
         Special method determining equality.
-        
+
         @param other reference to the history entry to compare against
             (HistoryEntry)
         @return flag indicating equality (boolean)
         """
         return (
-            other.title == self.title and
-            other.url == self.url and
-            other.dateTime == self.dateTime
+            other.title == self.title
+            and other.url == self.url
+            and other.dateTime == self.dateTime
         )
-    
+
     def __lt__(self, other):
         """
         Special method determining less relation.
-        
+
         Note: History is sorted in reverse order by date and time
-        
+
         @param other reference to the history entry to compare against
             (HistoryEntry)
         @return flag indicating less (boolean)
         """
         return self.dateTime > other.dateTime
-    
+
     def userTitle(self):
         """
         Public method to get the title of the history entry.
-        
+
         @return title of the entry (string)
         """
         if not self.title:
@@ -82,11 +94,11 @@
                 return page
             return self.url
         return self.title
-    
+
     def isValid(self):
         """
         Public method to determine validity.
-        
+
         @return flag indicating validity
         @rtype bool
         """
@@ -96,7 +108,7 @@
 class HistoryManager(QObject):
     """
     Class implementing the history manager.
-    
+
     @signal historyCleared() emitted after the history has been cleared
     @signal historyReset() emitted after the history has been reset
     @signal entryAdded(HistoryEntry) emitted after a history entry has been
@@ -106,51 +118,50 @@
     @signal entryUpdated(int) emitted after a history entry has been updated
     @signal historySaved() emitted after the history was saved
     """
+
     historyCleared = pyqtSignal()
     historyReset = pyqtSignal()
     entryAdded = pyqtSignal(HistoryEntry)
     entryRemoved = pyqtSignal(HistoryEntry)
     entryUpdated = pyqtSignal(int)
     historySaved = pyqtSignal()
-    
+
     def __init__(self, parent=None):
         """
         Constructor
-        
+
         @param parent reference to the parent object (QObject)
         """
         super().__init__(parent)
-        
+
         self.__saveTimer = AutoSaver(self, self.save)
         self.__daysToExpire = Preferences.getWebBrowser("HistoryLimit")
         self.__history = []
         self.__lastSavedUrl = ""
-        
+
         self.__expiredTimer = QTimer(self)
         self.__expiredTimer.setSingleShot(True)
         self.__expiredTimer.timeout.connect(self.__checkForExpired)
-        
+
         self.__frequencyTimer = QTimer(self)
         self.__frequencyTimer.setSingleShot(True)
         self.__frequencyTimer.timeout.connect(self.__refreshFrequencies)
-        
+
         self.entryAdded.connect(self.__saveTimer.changeOccurred)
         self.entryRemoved.connect(self.__saveTimer.changeOccurred)
-        
+
         self.__load()
-        
+
         from .HistoryModel import HistoryModel
         from .HistoryFilterModel import HistoryFilterModel
         from .HistoryTreeModel import HistoryTreeModel
-        
+
         self.__historyModel = HistoryModel(self, self)
-        self.__historyFilterModel = HistoryFilterModel(
-            self.__historyModel, self)
-        self.__historyTreeModel = HistoryTreeModel(
-            self.__historyFilterModel, self)
-        
+        self.__historyFilterModel = HistoryFilterModel(self.__historyModel, self)
+        self.__historyTreeModel = HistoryTreeModel(self.__historyFilterModel, self)
+
         self.__startFrequencyTimer()
-    
+
     def close(self):
         """
         Public method to close the history manager.
@@ -159,19 +170,19 @@
         if self.__daysToExpire == -2:
             self.clear()
         self.__saveTimer.saveIfNeccessary()
-    
+
     def history(self):
         """
         Public method to return the history.
-        
+
         @return reference to the list of history entries (list of HistoryEntry)
         """
         return self.__history[:]
-    
+
     def setHistory(self, history, loadedAndSorted=False):
         """
         Public method to set a new history.
-        
+
         @param history reference to the list of history entries to be set
             (list of HistoryEntry)
         @param loadedAndSorted flag indicating that the list is sorted
@@ -180,9 +191,9 @@
         self.__history = history[:]
         if not loadedAndSorted:
             self.__history.sort()
-        
+
         self.__checkForExpired()
-        
+
         if loadedAndSorted:
             try:
                 self.__lastSavedUrl = self.__history[0].url
@@ -192,11 +203,11 @@
             self.__lastSavedUrl = ""
             self.__saveTimer.changeOccurred()
         self.historyReset.emit()
-    
+
     def __findFirstHistoryEntry(self, url):
         """
         Private method to find the first entry for the given URL.
-        
+
         @param url URL to search for
         @type str
         @return first entry for the given URL
@@ -205,15 +216,15 @@
         for index in range(len(self.__history)):
             if url == self.__history[index].url:
                 return self.__history[index]
-        
+
         # not found, return an empty entry
         return HistoryEntry()
-    
+
     def __updateVisitCount(self, url, count):
         """
         Private method to update the visit count for all entries of the
         given URL.
-        
+
         @param url URL to be updated
         @type str
         @param count new visit count
@@ -222,21 +233,22 @@
         for index in range(len(self.__history)):
             if url == self.__history[index].url:
                 self.__history[index].visitCount = count
-    
+
     def addHistoryEntry(self, view):
         """
         Public method to add a history entry.
-        
+
         @param view reference to the view to add an entry for
         @type WebBrowserView
         """
         import WebBrowser.WebBrowserWindow
+
         if WebBrowser.WebBrowserWindow.WebBrowserWindow.isPrivate():
             return
-        
+
         url = view.url()
         title = view.title()
-        
+
         if url.scheme() not in ["eric", "about", "data", "chrome"]:
             cleanUrlStr = self.__cleanUrlStr(url)
             firstEntry = self.__findFirstHistoryEntry(cleanUrlStr)
@@ -245,19 +257,18 @@
                 self.__updateVisitCount(cleanUrlStr, visitCount)
             else:
                 visitCount = 1
-            itm = HistoryEntry(cleanUrlStr,
-                               QDateTime.currentDateTime(),
-                               title,
-                               visitCount)
+            itm = HistoryEntry(
+                cleanUrlStr, QDateTime.currentDateTime(), title, visitCount
+            )
             self.__history.insert(0, itm)
             self.entryAdded.emit(itm)
             if len(self.__history) == 1:
                 self.__checkForExpired()
-    
+
     def updateHistoryEntry(self, url, title):
         """
         Public method to update a history entry.
-        
+
         @param url URL of the entry to update (string)
         @param title title of the entry to update (string)
         """
@@ -271,31 +282,30 @@
                         self.__lastSavedUrl = self.__history[index].url
                     self.entryUpdated.emit(index)
                     break
-    
+
     def removeHistoryEntry(self, url, title=""):
         """
         Public method to remove a history entry.
-        
+
         @param url URL of the entry to remove (QUrl)
         @param title title of the entry to remove (string)
         """
         if url.scheme() not in ["eric", "about", "data", "chrome"]:
             cleanUrlStr = self.__cleanUrlStr(url)
             for index in range(len(self.__history)):
-                if (
-                    cleanUrlStr == self.__history[index].url and
-                    (not title or title == self.__history[index].title)
+                if cleanUrlStr == self.__history[index].url and (
+                    not title or title == self.__history[index].title
                 ):
                     itm = self.__history[index]
                     self.__lastSavedUrl = ""
                     self.__history.remove(itm)
                     self.entryRemoved.emit(itm)
                     break
-    
+
     def __cleanUrl(self, url):
         """
         Private method to generate a clean URL usable for the history entry.
-        
+
         @param url original URL
         @type QUrl
         @return cleaned URL
@@ -308,13 +318,13 @@
         if cleanurl.host():
             # convert host to lower case
             cleanurl.setHost(url.host().lower())
-        
+
         return cleanurl
-    
+
     def __cleanUrlStr(self, url):
         """
         Private method to generate a clean URL usable for the history entry.
-        
+
         @param url original URL
         @type QUrl
         @return cleaned URL
@@ -322,93 +332,92 @@
         """
         cleanurl = self.__cleanUrl(url)
         return cleanurl.toString()
-    
+
     def historyModel(self):
         """
         Public method to get a reference to the history model.
-        
+
         @return reference to the history model (HistoryModel)
         """
         return self.__historyModel
-    
+
     def historyFilterModel(self):
         """
         Public method to get a reference to the history filter model.
-        
+
         @return reference to the history filter model (HistoryFilterModel)
         """
         return self.__historyFilterModel
-    
+
     def historyTreeModel(self):
         """
         Public method to get a reference to the history tree model.
-        
+
         @return reference to the history tree model (HistoryTreeModel)
         """
         return self.__historyTreeModel
-    
+
     def __checkForExpired(self):
         """
         Private slot to check entries for expiration.
         """
         if self.__daysToExpire < 0 or len(self.__history) == 0:
             return
-        
+
         now = QDateTime.currentDateTime()
         nextTimeout = 0
-        
+
         while self.__history:
             checkForExpired = QDateTime(self.__history[-1].dateTime)
-            checkForExpired.setDate(
-                checkForExpired.date().addDays(self.__daysToExpire))
+            checkForExpired.setDate(checkForExpired.date().addDays(self.__daysToExpire))
             nextTimeout = (
                 7 * 86400
-                if now.daysTo(checkForExpired) > 7 else
-                now.secsTo(checkForExpired)
+                if now.daysTo(checkForExpired) > 7
+                else now.secsTo(checkForExpired)
             )
             if nextTimeout > 0:
                 break
-            
+
             itm = self.__history.pop(-1)
             self.__lastSavedUrl = ""
             self.entryRemoved.emit(itm)
         self.__saveTimer.saveIfNeccessary()
-        
+
         if nextTimeout > 0:
             self.__expiredTimer.start(nextTimeout * 1000)
-    
+
     def daysToExpire(self):
         """
         Public method to get the days for entry expiration.
-        
+
         @return days for entry expiration (integer)
         """
         return self.__daysToExpire
-    
+
     def setDaysToExpire(self, limit):
         """
         Public method to set the days for entry expiration.
-        
+
         @param limit days for entry expiration (integer)
         """
         if self.__daysToExpire == limit:
             return
-        
+
         self.__daysToExpire = limit
         self.__checkForExpired()
         self.__saveTimer.changeOccurred()
-    
+
     def preferencesChanged(self):
         """
         Public method to indicate a change of preferences.
         """
         self.setDaysToExpire(Preferences.getWebBrowser("HistoryLimit"))
-    
+
     @pyqtSlot()
     def clear(self, period=0):
         """
         Public slot to clear the complete history.
-        
+
         @param period history period in milliseconds to be cleared (integer)
         """
         if period == 0:
@@ -416,10 +425,8 @@
             self.historyReset.emit()
         else:
             breakMS = QDateTime.currentMSecsSinceEpoch() - period
-            while (
-                self.__history and
-                (QDateTime(self.__history[0].dateTime).toMSecsSinceEpoch() >
-                 breakMS)
+            while self.__history and (
+                QDateTime(self.__history[0].dateTime).toMSecsSinceEpoch() > breakMS
             ):
                 itm = self.__history.pop(0)
                 self.entryRemoved.emit(itm)
@@ -427,21 +434,21 @@
         self.__saveTimer.changeOccurred()
         self.__saveTimer.saveIfNeccessary()
         self.historyCleared.emit()
-    
+
     def getFileName(self):
         """
         Public method to get the file name of the history file.
-        
+
         @return name of the history file (string)
         """
         return os.path.join(Utilities.getConfigDir(), "web_browser", "history")
-    
+
     def reload(self):
         """
         Public method to reload the history.
         """
         self.__load()
-    
+
     def __load(self):
         """
         Private method to load the saved history entries from disk.
@@ -455,12 +462,13 @@
                 self.tr("Loading History"),
                 self.tr(
                     """<p>Unable to open history file <b>{0}</b>.<br/>"""
-                    """Reason: {1}</p>""")
-                .format(historyFile.fileName, historyFile.errorString()))
+                    """Reason: {1}</p>"""
+                ).format(historyFile.fileName, historyFile.errorString()),
+            )
             return
-        
+
         history = []
-        
+
         # double check, that the history file is sorted as it is read
         needToSort = False
         lastInsertedItem = HistoryEntry()
@@ -477,15 +485,15 @@
             itm.title = Utilities.readStringFromStream(stream)
             if ver == HISTORY_VERSION_60:
                 itm.visitCount = stream.readUInt32()
-            
+
             if not itm.dateTime.isValid():
                 continue
-            
+
             if itm == lastInsertedItem:
                 if not lastInsertedItem.title and len(history) > 0:
                     history[0].title = itm.title
                 continue
-            
+
             if ver == HISTORY_VERSION_42:
                 firstEntry = self.__findFirstHistoryEntry(itm.url)
                 if firstEntry.isValid():
@@ -494,24 +502,24 @@
                 else:
                     visitCount = 1
                 itm.visitCount = visitCount
-            
+
             if not needToSort and history and lastInsertedItem < itm:
                 needToSort = True
-            
+
             history.insert(0, itm)
             lastInsertedItem = itm
         historyFile.close()
-        
+
         if needToSort:
             history.sort()
-        
+
         self.setHistory(history, True)
-        
+
         # if the history had to be sorted, rewrite the history sorted
         if needToSort:
             self.__lastSavedUrl = ""
             self.__saveTimer.changeOccurred()
-    
+
     def save(self):
         """
         Public slot to save the history entries to disk.
@@ -519,7 +527,7 @@
         historyFile = QFile(self.getFileName())
         if not historyFile.exists():
             self.__lastSavedUrl = ""
-        
+
         saveAll = self.__lastSavedUrl == ""
         first = len(self.__history) - 1
         if not saveAll:
@@ -530,7 +538,7 @@
                     break
         if first == len(self.__history) - 1:
             saveAll = True
-        
+
         if saveAll:
             # use a temporary file when saving everything
             f = QTemporaryFile()
@@ -539,17 +547,18 @@
         else:
             f = historyFile
             opened = f.open(QIODevice.OpenModeFlag.Append)
-        
+
         if not opened:
             EricMessageBox.warning(
                 None,
                 self.tr("Saving History"),
                 self.tr(
                     """<p>Unable to open history file <b>{0}</b>.<br/>"""
-                    """Reason: {1}</p>""")
-                .format(f.fileName(), f.errorString()))
+                    """Reason: {1}</p>"""
+                ).format(f.fileName(), f.errorString()),
+            )
             return
-        
+
         for index in range(first, -1, -1):
             data = QByteArray()
             stream = QDataStream(data, QIODevice.OpenModeFlag.WriteOnly)
@@ -558,10 +567,10 @@
             stream.writeUInt32(HISTORY_VERSION_60)
             stream.writeString(itm.url.encode("utf-8"))
             stream << itm.dateTime
-            stream.writeString(itm.title.encode('utf-8'))
+            stream.writeString(itm.title.encode("utf-8"))
             stream.writeUInt32(itm.visitCount)
             f.write(data)
-        
+
         f.close()
         if saveAll:
             if historyFile.exists() and not historyFile.remove():
@@ -570,44 +579,44 @@
                     self.tr("Saving History"),
                     self.tr(
                         """<p>Error removing old history file <b>{0}</b>."""
-                        """<br/>Reason: {1}</p>""")
-                    .format(historyFile.fileName(),
-                            historyFile.errorString()))
+                        """<br/>Reason: {1}</p>"""
+                    ).format(historyFile.fileName(), historyFile.errorString()),
+                )
             if not f.copy(historyFile.fileName()):
                 EricMessageBox.warning(
                     None,
                     self.tr("Saving History"),
                     self.tr(
                         """<p>Error moving new history file over old one """
-                        """(<b>{0}</b>).<br/>Reason: {1}</p>""")
-                    .format(historyFile.fileName(), f.errorString()))
+                        """(<b>{0}</b>).<br/>Reason: {1}</p>"""
+                    ).format(historyFile.fileName(), f.errorString()),
+                )
             f.remove()  # get rid of the temporary file
         self.historySaved.emit()
         try:
             self.__lastSavedUrl = self.__history[0].url
         except IndexError:
             self.__lastSavedUrl = ""
-    
+
     def __refreshFrequencies(self):
         """
         Private slot to recalculate the refresh frequencies.
         """
         self.__historyFilterModel.recalculateFrequencies()
         self.__startFrequencyTimer()
-    
+
     def __startFrequencyTimer(self):
         """
         Private method to start the timer to recalculate the frequencies.
         """
         tomorrow = QDateTime(QDate.currentDate().addDays(1), QTime(3, 0))
-        self.__frequencyTimer.start(
-            QDateTime.currentDateTime().secsTo(tomorrow) * 1000)
-    
+        self.__frequencyTimer.start(QDateTime.currentDateTime().secsTo(tomorrow) * 1000)
+
     def siteVisitsCount(self, scheme, host):
         """
         Public method to get the visit count for a web site using the given
         scheme.
-        
+
         @param scheme scheme to look for
         @type str
         @param host host to look for
@@ -617,13 +626,13 @@
         """
         count = 0
         url = "{0}://{1}".format(scheme.lower(), host.lower())
-        
+
         seenUrls = []
-        
+
         for index in range(len(self.__history)):
             historyUrl = self.__history[index].url
             if historyUrl.startswith(url) and historyUrl not in seenUrls:
                 count += self.__history[index].visitCount
                 seenUrls.append(historyUrl)
-        
+
         return count

eric ide

mercurial