Skip to content

Commit

Permalink
Rewrite and improve the index event signal feature
Browse files Browse the repository at this point in the history
  • Loading branch information
vkbo committed Nov 16, 2023
1 parent 844240b commit 123d9df
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 49 deletions.
40 changes: 27 additions & 13 deletions novelwriter/core/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ def clearIndex(self) -> None:
self._itemIndex.clear()
self._indexChange = 0.0
self._rootChange = {}
SHARED.indexCallBack({"event": "clearIndex"})
return

def rebuildIndex(self) -> None:
Expand All @@ -122,31 +123,35 @@ def rebuildIndex(self) -> None:
if nwItem.isFileType():
tHandle = nwItem.itemHandle
theDoc = self._project.storage.getDocument(tHandle)
self.scanText(tHandle, theDoc.readDocument() or "")
self.scanText(tHandle, theDoc.readDocument() or "", blockSignal=True)
self._indexBroken = False
SHARED.indexCallBack({"event": "buildIndex"})
return

def deleteHandle(self, tHandle: str) -> None:
"""Delete all entries of a given document handle."""
logger.debug("Removing item '%s' from the index", tHandle)
for tTag in self._itemIndex.allItemTags(tHandle):
delTags = self._itemIndex.allItemTags(tHandle)
for tTag in delTags:
del self._tagsIndex[tTag]
del self._itemIndex[tHandle]
SHARED.indexCallBack({
"event": "updateTags",
"deleted": delTags,
})
return

def reIndexHandle(self, tHandle: str | None) -> bool:
"""Put a file back into the index. This is used when files are
moved from the archive or trash folders back into the active
project.
"""
if tHandle is None or not self._project.tree.checkType(tHandle, nwItemType.FILE):
return False

logger.debug("Re-indexing item '%s'", tHandle)
theDoc = self._project.storage.getDocument(tHandle)
self.scanText(tHandle, theDoc.readDocument() or "")

return True
if tHandle and self._project.tree.checkType(tHandle, nwItemType.FILE):
logger.debug("Re-indexing item '%s'", tHandle)
theDoc = self._project.storage.getDocument(tHandle)
self.scanText(tHandle, theDoc.readDocument() or "")
return True
return False

def indexChangedSince(self, checkTime: int | float) -> bool:
"""Check if the index has changed since a given time."""
Expand Down Expand Up @@ -201,6 +206,7 @@ def loadIndex(self) -> bool:
self.reIndexHandle(fHandle)

self._indexChange = time()
SHARED.indexCallBack({"event": "buildIndex"})

logger.debug("Index loaded in %.3f ms", (time() - tStart)*1000)

Expand Down Expand Up @@ -239,7 +245,7 @@ def saveIndex(self) -> bool:
# Index Building
##

def scanText(self, tHandle: str, text: str) -> bool:
def scanText(self, tHandle: str, text: str, blockSignal: bool = False) -> bool:
"""Scan a piece of text associated with a handle. This will
update the indices accordingly. This function takes the handle
and text as separate inputs as we want to primarily scan the
Expand Down Expand Up @@ -283,7 +289,11 @@ def scanText(self, tHandle: str, text: str) -> bool:
nowTime = time()
self._indexChange = nowTime
self._rootChange[tItem.itemRoot] = nowTime
SHARED.indexDocumentScanned(tHandle)
if not blockSignal:
SHARED.indexCallBack({
"event": "scanText",
"handle": tHandle,
})

return True

Expand Down Expand Up @@ -358,7 +368,11 @@ def _scanActive(self, tHandle: str, nwItem: NWItem, text: str, tags: dict[str, b
del self._tagsIndex[tTag]
deleted.append(tTag)
if updated or deleted:
SHARED.indexUpdatedTags(updated, deleted)
SHARED.indexCallBack({
"event": "updateTags",
"updated": updated,
"deleted": deleted,
})

return

Expand Down
44 changes: 23 additions & 21 deletions novelwriter/gui/docviewerpanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,30 +103,27 @@ def updateTheme(self) -> None:

return

def openProjectTasks(self) -> None:
"""Run open project tasks."""
self.clearClassTabs()
for key, name, tClass, iItem, hItem in SHARED.project.index.getTagsData():
if tClass in self.kwTabs and iItem and hItem:
self.kwTabs[tClass].addUpdateEntry(key, name, iItem, hItem)
self._updateTabVisibility()
return

def closeProjectTasks(self) -> None:
"""Run closing project tasks."""
self.tabBackRefs.refreshContent(None)
self.clearClassTabs()
return
##
# Public Slots
##

def clearClassTabs(self) -> None:
"""Clear all the class tabs"""
@pyqtSlot()
def indexWasCleared(self) -> None:
"""Handle event when the index has been cleared of content."""
self.tabBackRefs.clearContent()
for cTab in self.kwTabs.values():
cTab.clearContent()
return

##
# Public Slots
##
@pyqtSlot()
def indexHasAppeared(self) -> None:
"""Handle event when the index has appeared."""
for key, name, tClass, iItem, hItem in SHARED.project.index.getTagsData():
if tClass in self.kwTabs and iItem and hItem:
self.kwTabs[tClass].addUpdateEntry(key, name, iItem, hItem)
self._updateTabVisibility()
self.updateHandle(self._lastHandle)
return

@pyqtSlot(str)
def projectItemChanged(self, tHandle: str) -> None:
Expand Down Expand Up @@ -218,10 +215,15 @@ def __init__(self, parent: GuiDocViewerPanel) -> None:

return

def refreshContent(self, dHandle: str | None) -> None:
"""Update the content."""
def clearContent(self) -> None:
"""Clear the widget."""
self.clear()
self._treeMap = {}
return

def refreshContent(self, dHandle: str | None) -> None:
"""Update the content."""
self.clearContent()
if dHandle:
refs = SHARED.project.index.getBackReferenceList(dHandle)
for tHandle, (sTitle, hItem) in refs.items():
Expand Down
11 changes: 5 additions & 6 deletions novelwriter/guimain.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,11 @@ def __init__(self) -> None:
SHARED.projectStatusMessage.connect(self.mainStatus.setStatusMessage)
SHARED.spellLanguageChanged.connect(self.mainStatus.setLanguage)
SHARED.indexChangedTags.connect(self.docViewerPanel.updateChangedTags)
SHARED.indexScannedDocument.connect(self.docViewerPanel.projectItemChanged)
SHARED.indexScannedDocument.connect(self.projView.updateItemValues)
SHARED.indexScannedDocument.connect(self.itemDetails.updateViewBox)
SHARED.indexScannedText.connect(self.docViewerPanel.projectItemChanged)
SHARED.indexScannedText.connect(self.projView.updateItemValues)
SHARED.indexScannedText.connect(self.itemDetails.updateViewBox)
SHARED.indexCleared.connect(self.docViewerPanel.indexWasCleared)
SHARED.indexAvailable.connect(self.docViewerPanel.indexHasAppeared)

self.mainMenu.requestDocAction.connect(self._passDocumentAction)
self.mainMenu.requestDocInsert.connect(self._passDocumentInsert)
Expand Down Expand Up @@ -448,7 +450,6 @@ def closeProject(self, isYes: bool = False) -> bool:
self.docViewer.clearNavHistory()
self.closeDocViewer(byUser=False)

self.docViewerPanel.closeProjectTasks()
self.outlineView.closeProjectTasks()
self.novelView.closeProjectTasks()
self.projView.clearProjectView()
Expand Down Expand Up @@ -522,7 +523,6 @@ def openProject(self, projFile: str | Path | None) -> bool:
self.projView.openProjectTasks()
self.novelView.openProjectTasks()
self.outlineView.openProjectTasks()
self.docViewerPanel.openProjectTasks()
self._updateStatusWordCount()

# Restore previously open documents, if any
Expand Down Expand Up @@ -816,7 +816,6 @@ def rebuildIndex(self, beQuiet: bool = False) -> bool:
tStart = time()

self.projView.saveProjectTasks()
self.docViewerPanel.clearClassTabs()
SHARED.project.index.rebuildIndex()
self.projView.populateTree()
self.novelView.refreshTree()
Expand Down
24 changes: 15 additions & 9 deletions novelwriter/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ class SharedData(QObject):
projectStatusChanged = pyqtSignal(bool)
projectStatusMessage = pyqtSignal(str)
spellLanguageChanged = pyqtSignal(str, str)
indexScannedDocument = pyqtSignal(str)
indexScannedText = pyqtSignal(str)
indexChangedTags = pyqtSignal(list, list)
indexCleared = pyqtSignal()
indexAvailable = pyqtSignal()

def __init__(self) -> None:
super().__init__()
Expand Down Expand Up @@ -216,14 +218,18 @@ def runInThreadPool(self, runnable: QRunnable, priority: int = 0) -> None:
# Call-Back Functions
##

def indexUpdatedTags(self, updated: list[str], deleted: list[str]) -> None:
"""Emit the index changed tags signal."""
self.indexChangedTags.emit(updated, deleted)
return

def indexDocumentScanned(self, tHandle: str) -> None:
"""Emit the index scanned document signal."""
self.indexScannedDocument.emit(tHandle)
def indexCallBack(self, data: dict) -> None:
"""Emit signals on behalf of the index."""
event = data.get("event")
logger.debug("Received '%s' event from the index", event)
if event == "updateTags":
self.indexChangedTags.emit(data.get("updated", []), data.get("deleted", []))
elif event == "scanText":
self.indexScannedText.emit(data.get("handle", ""))
elif event == "clearIndex":
self.indexCleared.emit()
elif event == "buildIndex":
self.indexAvailable.emit()
return

##
Expand Down

0 comments on commit 123d9df

Please sign in to comment.