eric6/Helpviewer/History/HistoryManager.py

changeset 7220
5cf645f6daab
parent 7218
eaf2cf171f3a
parent 7211
1c97f3142fa8
child 7221
0485ccdf7877
--- a/eric6/Helpviewer/History/HistoryManager.py	Sat Sep 07 14:45:27 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,528 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2009 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module implementing the history manager.
-"""
-
-from __future__ import unicode_literals
-
-import os
-
-from PyQt5.QtCore import pyqtSignal, pyqtSlot, QFileInfo, QDateTime, QDate, \
-    QTime, QUrl, QTimer, QFile, QIODevice, QByteArray, QDataStream, \
-    QTemporaryFile
-from PyQt5.QtWebKit import QWebHistoryInterface, QWebSettings
-
-from E5Gui import E5MessageBox
-
-from Utilities.AutoSaver import AutoSaver
-import Utilities
-import Preferences
-
-HISTORY_VERSION = 42
-
-
-class HistoryEntry(object):
-    """
-    Class implementing a history entry.
-    """
-    def __init__(self, url=None, dateTime=None, title=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)
-        """
-        self.url = url and url or ""
-        self.dateTime = dateTime and dateTime or QDateTime()
-        self.title = title and title or ""
-    
-    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
-    
-    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:
-            page = QFileInfo(QUrl(self.url).path()).fileName()
-            if page:
-                return page
-            return self.url
-        return self.title
-
-
-class HistoryManager(QWebHistoryInterface):
-    """
-    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
-        added
-    @signal entryRemoved(HistoryEntry) emitted after a history entry has been
-        removed
-    @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(HistoryManager, self).__init__(parent)
-        
-        self.__saveTimer = AutoSaver(self, self.save)
-        self.__daysToExpire = Preferences.getHelp("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)
-        
-        super(HistoryManager, self).setDefaultInterface(self)
-        self.__startFrequencyTimer()
-    
-    def close(self):
-        """
-        Public method to close the history manager.
-        """
-        # remove history items on application exit
-        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
-            (boolean)
-        """
-        self.__history = history[:]
-        if not loadedAndSorted:
-            self.__history.sort()
-        
-        self.__checkForExpired()
-        
-        if loadedAndSorted:
-            try:
-                self.__lastSavedUrl = self.__history[0].url
-            except IndexError:
-                self.__lastSavedUrl = ""
-        else:
-            self.__lastSavedUrl = ""
-            self.__saveTimer.changeOccurred()
-        self.historyReset.emit()
-    
-    def historyContains(self, url):
-        """
-        Public method to check the history for an entry.
-        
-        @param url URL to check for (string)
-        @return flag indicating success (boolean)
-        """
-        return self.__historyFilterModel.historyContains(url)
-    
-    def _addHistoryEntry(self, itm):
-        """
-        Protected method to add a history item.
-        
-        @param itm reference to the history item to add (HistoryEntry)
-        """
-        globalSettings = QWebSettings.globalSettings()
-        if globalSettings.testAttribute(QWebSettings.PrivateBrowsingEnabled):
-            return
-        
-        self.__history.insert(0, itm)
-        self.entryAdded.emit(itm)
-        if len(self.__history) == 1:
-            self.__checkForExpired()
-    
-    def _removeHistoryEntry(self, itm):
-        """
-        Protected method to remove a history item.
-        
-        @param itm reference to the history item to remove (HistoryEntry)
-        """
-        self.__lastSavedUrl = ""
-        self.__history.remove(itm)
-        self.entryRemoved.emit(itm)
-    
-    def addHistoryEntry(self, url):
-        """
-        Public method to add a history entry.
-        
-        @param url URL to be added (string)
-        """
-        cleanurl = QUrl(url)
-        if cleanurl.scheme() not in ["eric", "about"]:
-            if cleanurl.password():
-                # don't save the password in the history
-                cleanurl.setPassword("")
-            if cleanurl.host():
-                cleanurl.setHost(cleanurl.host().lower())
-            itm = HistoryEntry(cleanurl.toString(),
-                               QDateTime.currentDateTime())
-            self._addHistoryEntry(itm)
-    
-    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)
-        """
-        cleanurl = QUrl(url)
-        if cleanurl.scheme() not in ["eric", "about"]:
-            for index in range(len(self.__history)):
-                if url == self.__history[index].url:
-                    self.__history[index].title = title
-                    self.__saveTimer.changeOccurred()
-                    if not self.__lastSavedUrl:
-                        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)
-        """
-        for index in range(len(self.__history)):
-            if url == QUrl(self.__history[index].url) and \
-               (not title or title == self.__history[index].title):
-                self._removeHistoryEntry(self.__history[index])
-                break
-    
-    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))
-            if now.daysTo(checkForExpired) > 7:
-                nextTimeout = 7 * 86400
-            else:
-                nextTimeout = 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.getHelp("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:
-            self.__history = []
-            self.historyReset.emit()
-        else:
-            breakMS = QDateTime.currentMSecsSinceEpoch() - period
-            while self.__history and \
-                (QDateTime(self.__history[0].dateTime).toMSecsSinceEpoch() >
-                 breakMS):
-                itm = self.__history.pop(0)
-                self.entryRemoved.emit(itm)
-        self.__lastSavedUrl = ""
-        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(), "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.
-        """
-        historyFile = QFile(self.getFileName())
-        if not historyFile.exists():
-            return
-        if not historyFile.open(QIODevice.ReadOnly):
-            E5MessageBox.warning(
-                None,
-                self.tr("Loading History"),
-                self.tr(
-                    """<p>Unable to open history file <b>{0}</b>.<br/>"""
-                    """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()
-        data = QByteArray(historyFile.readAll())
-        stream = QDataStream(data, QIODevice.ReadOnly)
-        stream.setVersion(QDataStream.Qt_4_6)
-        while not stream.atEnd():
-            ver = stream.readUInt32()
-            if ver != HISTORY_VERSION:
-                continue
-            itm = HistoryEntry()
-            itm.url = Utilities.readStringFromStream(stream)
-            stream >> itm.dateTime
-            itm.title = Utilities.readStringFromStream(stream)
-            
-            if not itm.dateTime.isValid():
-                continue
-            
-            if itm == lastInsertedItem:
-                if not lastInsertedItem.title and len(history) > 0:
-                    history[0].title = itm.title
-                continue
-            
-            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.
-        """
-        historyFile = QFile(self.getFileName())
-        if not historyFile.exists():
-            self.__lastSavedUrl = ""
-        
-        saveAll = self.__lastSavedUrl == ""
-        first = len(self.__history) - 1
-        if not saveAll:
-            # find the first one to save
-            for index in range(len(self.__history)):
-                if self.__history[index].url == self.__lastSavedUrl:
-                    first = index - 1
-                    break
-        if first == len(self.__history) - 1:
-            saveAll = True
-        
-        if saveAll:
-            # use a temporary file when saving everything
-            f = QTemporaryFile()
-            f.setAutoRemove(False)
-            opened = f.open()
-        else:
-            f = historyFile
-            opened = f.open(QIODevice.Append)
-        
-        if not opened:
-            E5MessageBox.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()))
-            return
-        
-        for index in range(first, -1, -1):
-            data = QByteArray()
-            stream = QDataStream(data, QIODevice.WriteOnly)
-            stream.setVersion(QDataStream.Qt_4_6)
-            itm = self.__history[index]
-            stream.writeUInt32(HISTORY_VERSION)
-            stream.writeString(itm.url.encode("utf-8"))
-            stream << itm.dateTime
-            stream.writeString(itm.title.encode('utf-8'))
-            f.write(data)
-        
-        f.close()
-        if saveAll:
-            if historyFile.exists() and not historyFile.remove():
-                E5MessageBox.warning(
-                    None,
-                    self.tr("Saving History"),
-                    self.tr(
-                        """<p>Error removing old history file <b>{0}</b>."""
-                        """<br/>Reason: {1}</p>""")
-                    .format(historyFile.fileName(),
-                            historyFile.errorString()))
-            if not f.copy(historyFile.fileName()):
-                E5MessageBox.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()))
-            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)

eric ide

mercurial