Add clocks to shared class and add search cache clearing
This commit is contained in:
+31
-12
@@ -23,9 +23,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import time
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
|
||||||
from PyQt5.QtCore import QSize, Qt, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import QSize, Qt, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtGui import QKeyEvent, QPalette
|
from PyQt5.QtGui import QKeyEvent, QPalette
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
@@ -40,6 +41,8 @@ from novelwriter.core.item import NWItem
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
CACHE_TIMEOUT = 120.0 # 2 minutes
|
||||||
|
|
||||||
|
|
||||||
class GuiProjectSearch(QWidget):
|
class GuiProjectSearch(QWidget):
|
||||||
|
|
||||||
@@ -50,8 +53,8 @@ class GuiProjectSearch(QWidget):
|
|||||||
D_HANDLE = Qt.ItemDataRole.UserRole
|
D_HANDLE = Qt.ItemDataRole.UserRole
|
||||||
D_RESULT = Qt.ItemDataRole.UserRole + 1
|
D_RESULT = Qt.ItemDataRole.UserRole + 1
|
||||||
|
|
||||||
openDocumentSelectRequest = pyqtSignal(str, int, int, bool)
|
|
||||||
selectedItemChanged = pyqtSignal(str)
|
selectedItemChanged = pyqtSignal(str)
|
||||||
|
openDocumentSelectRequest = pyqtSignal(str, int, int, bool)
|
||||||
|
|
||||||
def __init__(self, parent: QWidget) -> None:
|
def __init__(self, parent: QWidget) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
@@ -61,7 +64,9 @@ class GuiProjectSearch(QWidget):
|
|||||||
iPx = SHARED.theme.baseIconSize
|
iPx = SHARED.theme.baseIconSize
|
||||||
mPx = CONFIG.pxInt(2)
|
mPx = CONFIG.pxInt(2)
|
||||||
|
|
||||||
|
self._time = time()
|
||||||
self._search = DocSearch()
|
self._search = DocSearch()
|
||||||
|
self._blocked = False
|
||||||
|
|
||||||
# Header
|
# Header
|
||||||
self.viewLabel = QLabel(self.tr("Project Search"))
|
self.viewLabel = QLabel(self.tr("Project Search"))
|
||||||
@@ -130,6 +135,8 @@ class GuiProjectSearch(QWidget):
|
|||||||
self.setLayout(self.outerBox)
|
self.setLayout(self.outerBox)
|
||||||
self.updateTheme()
|
self.updateTheme()
|
||||||
|
|
||||||
|
SHARED.slowClockTick.connect(self._cacheTimeout)
|
||||||
|
|
||||||
logger.debug("Ready: GuiProjectSearch")
|
logger.debug("Ready: GuiProjectSearch")
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -205,7 +212,8 @@ class GuiProjectSearch(QWidget):
|
|||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def clearSearchCache(self, tHandle: str) -> None:
|
def clearSearchCache(self, tHandle: str) -> None:
|
||||||
"""Process document content change."""
|
"""Process document content change."""
|
||||||
self._search.clearTextCache(tHandle)
|
if not self._blocked:
|
||||||
|
self._search.clearTextCache(tHandle)
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -215,15 +223,19 @@ class GuiProjectSearch(QWidget):
|
|||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _processSearch(self) -> None:
|
def _processSearch(self) -> None:
|
||||||
"""Perform a search."""
|
"""Perform a search."""
|
||||||
start = time.time()
|
if not self._blocked:
|
||||||
self.searchResult.clear()
|
start = time()
|
||||||
if text := self.searchText.text():
|
self._blocked = True
|
||||||
self._search.setUserRegEx(self.toggleRegEx.isChecked())
|
self.searchResult.clear()
|
||||||
self._search.setCaseSensitive(self.toggleCase.isChecked())
|
if text := self.searchText.text():
|
||||||
self._search.setWholeWords(self.toggleWord.isChecked())
|
self._search.setUserRegEx(self.toggleRegEx.isChecked())
|
||||||
for item, results, capped in self._search.iterSearch(SHARED.project, text):
|
self._search.setCaseSensitive(self.toggleCase.isChecked())
|
||||||
self._appendResultSet(item, results, capped)
|
self._search.setWholeWords(self.toggleWord.isChecked())
|
||||||
logger.debug("Search took %.3f ms", 1000*(time.time() - start))
|
for item, results, capped in self._search.iterSearch(SHARED.project, text):
|
||||||
|
self._appendResultSet(item, results, capped)
|
||||||
|
logger.debug("Search took %.3f ms", 1000*(time() - start))
|
||||||
|
self._time = time()
|
||||||
|
self._blocked = False
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@@ -272,6 +284,13 @@ class GuiProjectSearch(QWidget):
|
|||||||
CONFIG.searchProjRegEx = state
|
CONFIG.searchProjRegEx = state
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def _cacheTimeout(self) -> None:
|
||||||
|
"""Clear the cache after a period of inactivity."""
|
||||||
|
if not self._blocked and time() - self._time > CACHE_TIMEOUT:
|
||||||
|
self._search.clearTextCache(None)
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|||||||
+10
-16
@@ -220,6 +220,7 @@ class GuiMain(QMainWindow):
|
|||||||
SHARED.indexScannedText.connect(self.itemDetails.updateViewBox)
|
SHARED.indexScannedText.connect(self.itemDetails.updateViewBox)
|
||||||
SHARED.indexCleared.connect(self.docViewerPanel.indexWasCleared)
|
SHARED.indexCleared.connect(self.docViewerPanel.indexWasCleared)
|
||||||
SHARED.indexAvailable.connect(self.docViewerPanel.indexHasAppeared)
|
SHARED.indexAvailable.connect(self.docViewerPanel.indexHasAppeared)
|
||||||
|
SHARED.mainClockTick.connect(self._timeTick)
|
||||||
|
|
||||||
self.mainMenu.requestDocAction.connect(self._passDocumentAction)
|
self.mainMenu.requestDocAction.connect(self._passDocumentAction)
|
||||||
self.mainMenu.requestDocInsert.connect(self._passDocumentInsert)
|
self.mainMenu.requestDocInsert.connect(self._passDocumentInsert)
|
||||||
@@ -287,12 +288,6 @@ class GuiMain(QMainWindow):
|
|||||||
self.asDocTimer = QTimer(self)
|
self.asDocTimer = QTimer(self)
|
||||||
self.asDocTimer.timeout.connect(self._autoSaveDocument)
|
self.asDocTimer.timeout.connect(self._autoSaveDocument)
|
||||||
|
|
||||||
# Main Clock
|
|
||||||
self.mainTimer = QTimer(self)
|
|
||||||
self.mainTimer.setInterval(1000)
|
|
||||||
self.mainTimer.timeout.connect(self._timeTick)
|
|
||||||
self.mainTimer.start()
|
|
||||||
|
|
||||||
# Shortcuts and Actions
|
# Shortcuts and Actions
|
||||||
self._connectMenuActions()
|
self._connectMenuActions()
|
||||||
|
|
||||||
@@ -1212,16 +1207,15 @@ class GuiMain(QMainWindow):
|
|||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _timeTick(self) -> None:
|
def _timeTick(self) -> None:
|
||||||
"""Process time tick of the main timer."""
|
"""Process time tick of the main timer."""
|
||||||
if not SHARED.hasProject:
|
if SHARED.hasProject:
|
||||||
return
|
currTime = time()
|
||||||
currTime = time()
|
editIdle = currTime - self.docEditor.lastActive > CONFIG.userIdleTime
|
||||||
editIdle = currTime - self.docEditor.lastActive > CONFIG.userIdleTime
|
userIdle = qApp.applicationState() != Qt.ApplicationActive
|
||||||
userIdle = qApp.applicationState() != Qt.ApplicationActive
|
self.mainStatus.setUserIdle(editIdle or userIdle)
|
||||||
self.mainStatus.setUserIdle(editIdle or userIdle)
|
SHARED.updateIdleTime(currTime, editIdle or userIdle)
|
||||||
SHARED.updateIdleTime(currTime, editIdle or userIdle)
|
self.mainStatus.updateTime(idleTime=SHARED.projectIdleTime)
|
||||||
self.mainStatus.updateTime(idleTime=SHARED.projectIdleTime)
|
if CONFIG.memInfo and int(currTime) % 5 == 0: # pragma: no cover
|
||||||
if CONFIG.memInfo and int(currTime) % 5 == 0: # pragma: no cover
|
self.mainStatus.memInfo()
|
||||||
self.mainStatus.memInfo()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
|||||||
+13
-1
@@ -30,7 +30,7 @@ from time import time
|
|||||||
from typing import TYPE_CHECKING, TypeVar
|
from typing import TYPE_CHECKING, TypeVar
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal
|
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, QTimer, pyqtSignal
|
||||||
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QWidget
|
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QWidget
|
||||||
from novelwriter.common import formatFileFilter
|
from novelwriter.common import formatFileFilter
|
||||||
|
|
||||||
@@ -62,6 +62,8 @@ class SharedData(QObject):
|
|||||||
indexChangedTags = pyqtSignal(list, list)
|
indexChangedTags = pyqtSignal(list, list)
|
||||||
indexCleared = pyqtSignal()
|
indexCleared = pyqtSignal()
|
||||||
indexAvailable = pyqtSignal()
|
indexAvailable = pyqtSignal()
|
||||||
|
mainClockTick = pyqtSignal()
|
||||||
|
slowClockTick = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -79,6 +81,14 @@ class SharedData(QObject):
|
|||||||
self._idleRefTime = time()
|
self._idleRefTime = time()
|
||||||
self._focusMode = False
|
self._focusMode = False
|
||||||
|
|
||||||
|
self._fClock = QTimer(self)
|
||||||
|
self._fClock.setInterval(1000)
|
||||||
|
self._fClock.timeout.connect(lambda: self.mainClockTick.emit())
|
||||||
|
|
||||||
|
self._sClock = QTimer(self)
|
||||||
|
self._sClock.setInterval(10000)
|
||||||
|
self._sClock.timeout.connect(lambda: self.slowClockTick.emit())
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -158,6 +168,8 @@ class SharedData(QObject):
|
|||||||
soon as the Main GUI is created to ensure the SHARED singleton
|
soon as the Main GUI is created to ensure the SHARED singleton
|
||||||
has the properties needed for operation.
|
has the properties needed for operation.
|
||||||
"""
|
"""
|
||||||
|
self._fClock.start()
|
||||||
|
self._sClock.start()
|
||||||
self._gui = gui
|
self._gui = gui
|
||||||
self._theme = theme
|
self._theme = theme
|
||||||
self._resetProject()
|
self._resetProject()
|
||||||
|
|||||||
@@ -794,11 +794,7 @@ class _PreviewWidget(QTextBrowser):
|
|||||||
self._updateDocMargins()
|
self._updateDocMargins()
|
||||||
self._updateBuildAge()
|
self._updateBuildAge()
|
||||||
|
|
||||||
# Age Timer
|
SHARED.slowClockTick.connect(self._updateBuildAge)
|
||||||
self.ageTimer = QTimer(self)
|
|
||||||
self.ageTimer.setInterval(10)
|
|
||||||
self.ageTimer.timeout.connect(self._updateBuildAge)
|
|
||||||
self.ageTimer.start()
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user