diff --git a/novelwriter/core/coretools.py b/novelwriter/core/coretools.py index eb113a5d..08b96957 100644 --- a/novelwriter/core/coretools.py +++ b/novelwriter/core/coretools.py @@ -348,7 +348,9 @@ class DocSearch: rxMatch = rxItt.next() pos = rxMatch.capturedStart() num = rxMatch.capturedLength() - context = text[pos:pos+100].partition("\n")[0] + lim = text[:pos].rfind("\n") + 1 + cut = text[lim:pos].rfind(" ") + lim + 1 + context = text[cut:cut+100].partition("\n")[0] if context: results.append((pos, num, context)) count += 1 diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index 551ad6e6..f6e897cb 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -997,7 +997,7 @@ class GuiProjectTree(QTreeWidget): trItemP.takeChild(tIndex) for dHandle in reversed(self.getTreeFromHandle(tHandle)): - SHARED.closeDocument(dHandle) + SHARED.closeEditor(dHandle) SHARED.project.removeItem(dHandle) self._treeMap.pop(dHandle, None) @@ -1404,7 +1404,7 @@ class GuiProjectTree(QTreeWidget): return False # Save the open document first, in case it's part of merge - SHARED.saveDocument() + SHARED.saveEditor() # Create merge object, and append docs docMerger = DocMerger(SHARED.project) @@ -1805,7 +1805,7 @@ class _TreeContextMenu(QMenu): def _itemHeader(self) -> None: """Check if there is a header that can be used for rename.""" - SHARED.ensureEditorSaved(self._handle) + SHARED.saveEditor() if hItem := SHARED.project.index.getItemHeading(self._handle, "T0001"): action = self.addAction(self.tr("Rename to Heading")) action.triggered.connect( diff --git a/novelwriter/gui/search.py b/novelwriter/gui/search.py index f19c419d..65f23a44 100644 --- a/novelwriter/gui/search.py +++ b/novelwriter/gui/search.py @@ -208,6 +208,12 @@ class GuiProjectSearch(QWidget): self.searchResult.clear() return + def refreshCurrentSearch(self) -> None: + """Refresh the search if there is one.""" + if self.searchResult.topLevelItemCount() > 0: + self._processSearch() + return + ## # Events ## @@ -259,7 +265,7 @@ class GuiProjectSearch(QWidget): if not self._blocked: QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) start = time() - SHARED.saveDocument() + SHARED.saveEditor() self._blocked = True self._map = {} self.searchResult.clear() @@ -298,18 +304,21 @@ class GuiProjectSearch(QWidget): def _toggleCase(self, state: bool) -> None: """Enable/disable case sensitive mode.""" CONFIG.searchProjCase = state + self.refreshCurrentSearch() return @pyqtSlot(bool) def _toggleWord(self, state: bool) -> None: """Enable/disable whole word search mode.""" CONFIG.searchProjWord = state + self.refreshCurrentSearch() return @pyqtSlot(bool) def _toggleRegEx(self, state: bool) -> None: """Enable/disable regular expression search mode.""" CONFIG.searchProjRegEx = state + self.refreshCurrentSearch() return ## diff --git a/novelwriter/shared.py b/novelwriter/shared.py index 95c59068..2c8f9ce3 100644 --- a/novelwriter/shared.py +++ b/novelwriter/shared.py @@ -172,15 +172,21 @@ class SharedData(QObject): logger.debug("Thread Pool Max Count: %d", QThreadPool.globalInstance().maxThreadCount()) return - def closeDocument(self, tHandle: str | None = None) -> None: + def closeEditor(self, tHandle: str | None = None) -> None: """Close the document editor, optionally a specific document.""" if tHandle is None or tHandle == self.mainGui.docEditor.docHandle: self.mainGui.closeDocument() return - def saveDocument(self) -> None: - """Forward save document call to main GUI.""" - self.mainGui.saveDocument() + def saveEditor(self, tHandle: str | None = None) -> None: + """Save the editor content, optionally a specific document.""" + docEditor = self.mainGui.docEditor + if ( + self.hasProject and docEditor.docHandle + and (tHandle is None or tHandle == docEditor.docHandle) + ): + logger.debug("Saving editor document before action") + docEditor.saveText() return def openProject(self, path: str | Path, clearLock: bool = False) -> bool: @@ -216,19 +222,6 @@ class SharedData(QObject): self._resetIdleTimer() return - def ensureEditorSaved(self, tHandle: str | None) -> None: - """Ensure that the editor content is saved. Optionally, only if - it is a specific handle. - """ - docEditor = self.mainGui.docEditor - if ( - self.hasProject and docEditor.docHandle - and (tHandle is None or tHandle == docEditor.docHandle) - ): - logger.debug("Saving editor document before action") - docEditor.saveText() - return - def updateSpellCheckLanguage(self, reload: bool = False) -> None: """Update the active spell check language from settings.""" from novelwriter import CONFIG diff --git a/novelwriter/tools/manusbuild.py b/novelwriter/tools/manusbuild.py index d87b9be2..90f6f296 100644 --- a/novelwriter/tools/manusbuild.py +++ b/novelwriter/tools/manusbuild.py @@ -327,7 +327,7 @@ class GuiManuscriptBuild(NDialog): return False # Make sure editor content is saved before we start - SHARED.saveDocument() + SHARED.saveEditor() docBuild = NWBuildDocument(SHARED.project, self._build) docBuild.queueAll() diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py index fba899a8..53f3a17b 100644 --- a/novelwriter/tools/manuscript.py +++ b/novelwriter/tools/manuscript.py @@ -325,7 +325,7 @@ class GuiManuscript(NToolDialog): start = time() # Make sure editor content is saved before we start - SHARED.ensureEditorSaved(None) + SHARED.saveEditor() docBuild = NWBuildDocument(SHARED.project, build) docBuild.queueAll() diff --git a/tests/test_core/test_core_coretools.py b/tests/test_core/test_core_coretools.py index a0aa86e0..faf11cfc 100644 --- a/tests/test_core/test_core_coretools.py +++ b/tests/test_core/test_core_coretools.py @@ -449,8 +449,8 @@ def testCoreTools_DocSearch(monkeypatch, mockGUI, fncPath, mockRnd, ipsumText): assert pruneResult(search.iterSearch(project, "Lor"), 2) == [] search.setWholeWords(False) assert pruneResult(search.iterSearch(project, "Lor"), 2) == [ - (15, 3, "Lorem"), (29, 3, "lor"), (754, 3, "lorem"), (2056, 3, "lorem,"), - (2209, 3, "lorem"), (2425, 3, "lorem"), (2840, 3, "lorem."), (3328, 3, "lor."), + (15, 3, "Lorem"), (29, 3, "dolor"), (754, 3, "lorem"), (2056, 3, "lorem,"), + (2209, 3, "lorem"), (2425, 3, "lorem"), (2840, 3, "lorem."), (3328, 3, "dolor."), (3399, 3, "lorem"), ] @@ -458,7 +458,7 @@ def testCoreTools_DocSearch(monkeypatch, mockGUI, fncPath, mockRnd, ipsumText): search.setWholeWords(False) search.setUserRegEx(True) assert pruneResult(search.iterSearch(project, r"Lor\b"), 2) == [ - (29, 3, "lor"), (3328, 3, "lor."), + (29, 3, "dolor"), (3328, 3, "dolor."), ] # Max Results