diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 468bb16a..f401a9a3 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -1192,7 +1192,10 @@ class GuiDocEditor(QPlainTextEdit): if time() - self._lastEdit < 25.0: logger.debug("Running word counter") SHARED.runInThreadPool(self.wCounterDoc) - self._updateOutline() + self.docHeader.setOutline({ + block.blockNumber(): block.text() + for block in self._qDocument.iterBlockByType(BLOCK_TITLE) + }) return @@ -1837,14 +1840,6 @@ class GuiDocEditor(QPlainTextEdit): # Internal Functions ## - def _updateOutline(self) -> None: - """Scan the text for headings and update the outline.""" - self.docHeader.setOutline({ - block.blockNumber(): block.text() - for block in self._qDocument.iterBlockByType(BLOCK_TITLE) - }) - return - def _processTag(self, cursor: QTextCursor | None = None, follow: bool = True, create: bool = False) -> nwTrinary: """Activated by Ctrl+Enter. Checks that we're in a block diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index 3be987a7..baf881c7 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -524,24 +524,19 @@ class GuiMain(QMainWindow): # Document Actions ## - def closeDocument(self, beforeOpen: bool = False) -> bool: + def closeDocument(self, beforeOpen: bool = False) -> None: """Close the document and clear the editor and title field.""" - if not SHARED.hasProject: - logger.error("No project open") - return False - - # Disable focus mode if it is active - if SHARED.focusMode: - SHARED.setFocusMode(False) - - self.docEditor.saveCursorPosition() - if self.docEditor.docChanged: - self.saveDocument() - self.docEditor.clearEditor() - if not beforeOpen: - self.novelView.setActiveHandle(None) - - return True + if SHARED.hasProject: + # Disable focus mode if it is active + if SHARED.focusMode: + SHARED.setFocusMode(False) + self.docEditor.saveCursorPosition() + if self.docEditor.docChanged: + self.saveDocument() + self.docEditor.clearEditor() + if not beforeOpen: + self.novelView.setActiveHandle(None) + return def openDocument(self, tHandle: str | None, tLine: int | None = None, changeFocus: bool = True, doScroll: bool = False) -> bool: @@ -732,57 +727,53 @@ class GuiMain(QMainWindow): tHandle, sTitle = self.outlineView.getSelectedHandle() else: logger.warning("No item selected") - return False - if tHandle is not None and sTitle is not None: - hItem = SHARED.project.index.getItemHeading(tHandle, sTitle) - if hItem is not None: + return + + if tHandle and sTitle: + if hItem := SHARED.project.index.getItemHeading(tHandle, sTitle): tLine = hItem.line - if tHandle is not None: + if tHandle: self.openDocument(tHandle, tLine=tLine, changeFocus=False, doScroll=False) + return - def editItemLabel(self, tHandle: str | None = None) -> bool: + def editItemLabel(self, tHandle: str | None = None) -> None: """Open the edit item dialog.""" - if not SHARED.hasProject: - logger.error("No project open") - return False - if tHandle is None and (self.docEditor.anyFocus() or SHARED.focusMode): - tHandle = self.docEditor.docHandle - self.projView.renameTreeItem(tHandle) - return True + if SHARED.hasProject: + if tHandle is None and (self.docEditor.anyFocus() or SHARED.focusMode): + tHandle = self.docEditor.docHandle + self.projView.renameTreeItem(tHandle) + return def rebuildTrees(self) -> None: """Rebuild the project tree.""" self.projView.populateTree() return - def rebuildIndex(self, beQuiet: bool = False) -> bool: + def rebuildIndex(self, beQuiet: bool = False) -> None: """Rebuild the entire index.""" - if not SHARED.hasProject: - logger.error("No project open") - return False + if SHARED.hasProject: + logger.info("Rebuilding index ...") + qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) + tStart = time() - logger.info("Rebuilding index ...") - qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) - tStart = time() + self.projView.saveProjectTasks() + SHARED.project.index.rebuildIndex() + self.projView.populateTree() + self.novelView.refreshTree() - self.projView.saveProjectTasks() - SHARED.project.index.rebuildIndex() - self.projView.populateTree() - self.novelView.refreshTree() + tEnd = time() + self.mainStatus.setStatusMessage( + self.tr("Indexing completed in {0} ms").format(f"{(tEnd - tStart)*1000.0:.1f}") + ) + self.docEditor.updateTagHighLighting() + self._updateStatusWordCount() + qApp.restoreOverrideCursor() - tEnd = time() - self.mainStatus.setStatusMessage( - self.tr("Indexing completed in {0} ms").format(f"{(tEnd - tStart)*1000.0:.1f}") - ) - self.docEditor.updateTagHighLighting() - self._updateStatusWordCount() - qApp.restoreOverrideCursor() + if not beQuiet: + SHARED.info(self.tr("The project index has been successfully rebuilt.")) - if not beQuiet: - SHARED.info(self.tr("The project index has been successfully rebuilt.")) - - return True + return ## # Main Dialogs @@ -892,15 +883,14 @@ class GuiMain(QMainWindow): SHARED.error(self.tr("Could not initialise the dialog.")) return - def reportConfErr(self) -> bool: + def reportConfErr(self) -> None: """Checks if the Config module has any errors to report, and let the user know if this is the case. The Config module caches errors since it is initialised before the GUI itself. """ if CONFIG.hasError: SHARED.error(CONFIG.errorText()) - return True - return False + return ## # Main Window Actions diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py index a1229b89..000bfdc6 100644 --- a/tests/test_gui/test_gui_doceditor.py +++ b/tests/test_gui/test_gui_doceditor.py @@ -125,7 +125,7 @@ def testGuiEditor_LoadText(qtbot, nwGUI, projPath, ipsumText, mockRnd): longText = "### Lorem Ipsum\n\n%s" % "\n\n".join(ipsumText*20) nwGUI.docEditor.replaceText(longText) nwGUI.saveDocument() - assert nwGUI.closeDocument() is True + nwGUI.closeDocument() # Invalid handle assert nwGUI.docEditor.loadText("abcdefghijklm") is False diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py index cc9097c7..8b8a1bd7 100644 --- a/tests/test_gui/test_gui_guimain.py +++ b/tests/test_gui/test_gui_guimain.py @@ -49,13 +49,10 @@ def testGuiMain_ProjectBlocker(nwGUI): # Test no-project blocking assert nwGUI.closeProject() is True assert nwGUI.saveProject() is False - assert nwGUI.closeDocument() is False assert nwGUI.openDocument(None) is False assert nwGUI.openNextDocument(None) is False assert nwGUI.viewDocument(None) is False assert nwGUI.importDocument() is False - assert nwGUI.editItemLabel() is False - assert nwGUI.rebuildIndex() is False # END Test testGuiMain_ProjectBlocker @@ -120,7 +117,7 @@ def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd): nwGUI.projView.projTree._getTreeItem(sHandle).setSelected(True) nwGUI._keyPressReturn() assert nwGUI.docEditor.docHandle == sHandle - assert nwGUI.closeDocument() is True + nwGUI.closeDocument() # Novel Tree has focus nwGUI._changeView(nwView.NOVEL) @@ -132,7 +129,7 @@ def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd): nwGUI.novelView.novelTree.setCurrentItem(selItem) nwGUI._keyPressReturn() assert nwGUI.docEditor.docHandle == sHandle - assert nwGUI.closeDocument() is True + nwGUI.closeDocument() # Project Outline has focus nwGUI._changeView(nwView.OUTLINE) @@ -144,7 +141,7 @@ def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd): nwGUI.outlineView.outlineTree.setCurrentItem(selItem) nwGUI._keyPressReturn() assert nwGUI.docEditor.docHandle == sHandle - assert nwGUI.closeDocument() is True + nwGUI.closeDocument() # qtbot.stop()