diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 910ae4a0..468bb16a 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -55,7 +55,7 @@ from PyQt5.QtWidgets import ( from novelwriter import CONFIG, SHARED from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemClass, nwTrinary from novelwriter.common import minmax, transferCase -from novelwriter.constants import nwKeyWords, nwLabels, nwShortcode, nwUnicode, trConst +from novelwriter.constants import nwKeyWords, nwShortcode, nwUnicode from novelwriter.tools.lipsum import GuiLipsum from novelwriter.core.document import NWDocument from novelwriter.text.counting import standardCounter @@ -99,6 +99,7 @@ class GuiDocEditor(QPlainTextEdit): toggleFocusModeRequest = pyqtSignal() requestProjectItemSelected = pyqtSignal(str, bool) requestProjectItemRenamed = pyqtSignal(str, str) + requestNewNoteCreation = pyqtSignal(str, nwItemClass) def __init__(self, mainGui: GuiMain) -> None: super().__init__(parent=mainGui) @@ -1863,7 +1864,10 @@ class GuiDocEditor(QPlainTextEdit): if text.startswith("@") and self._docHandle: isGood, tBits, tPos = SHARED.project.index.scanThis(text) - if not isGood or not tBits or tBits[0] == nwKeyWords.TAG_KEY: + if ( + not isGood or not tBits or tBits[0] == nwKeyWords.TAG_KEY + or tBits[0] not in nwKeyWords.VALID_KEYS + ): return nwTrinary.NEUTRAL tag = "" @@ -1891,13 +1895,9 @@ class GuiDocEditor(QPlainTextEdit): "Do you want to create a new project note for the tag '{0}'?" ).format(tag)): itemClass = nwKeyWords.KEY_CLASS.get(tBits[0], nwItemClass.NO_CLASS) - if SHARED.mainGui.projView.createNewNote(tag, itemClass): - self._qDocument.syntaxHighlighter.rehighlightBlock(block) - else: - SHARED.error(self.tr( - "Could not create note in a root folder for '{0}'. " - "If one doesn't exist, you must create one first." - ).format(trConst(nwLabels.CLASS_NAME[itemClass]))) + self.requestNewNoteCreation.emit(tag, itemClass) + qApp.processEvents() + self._qDocument.syntaxHighlighter.rehighlightBlock(block) return nwTrinary.POSITIVE if exist else nwTrinary.NEGATIVE @@ -2804,7 +2804,6 @@ class GuiDocEditHeader(QWidget): logger.debug("Create: GuiDocEditHeader") self.docEditor = docEditor - self.mainGui = docEditor.mainGui self._docHandle = None self._docOutline: dict[int, str] = {} diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index 131bb398..674f9da2 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -142,7 +142,6 @@ class GuiProjectView(QWidget): self.requestDeleteItem = self.projTree.requestDeleteItem self.getSelectedHandle = self.projTree.getSelectedHandle self.changedSince = self.projTree.changedSince - self.createNewNote = self.projTree.createNewNote return @@ -240,6 +239,12 @@ class GuiProjectView(QWidget): self.projBar.buildQuickLinksMenu() return + @pyqtSlot(str, nwItemClass) + def createNewNote(self, tag: str, itemClass: nwItemClass) -> None: + """Process new not request.""" + self.projTree.createNewNote(tag, itemClass) + return + # END Class GuiProjectView @@ -606,18 +611,18 @@ class GuiProjectTree(QTreeWidget): self._timeChanged = 0.0 return - def createNewNote(self, tag: str, itemClass: nwItemClass | None) -> bool: + def createNewNote(self, tag: str, itemClass: nwItemClass) -> None: """Create a new note. This function is used by the document editor to create note files for unknown tags. """ - rHandle = SHARED.project.tree.findRoot(itemClass) - if rHandle: - tHandle = SHARED.project.newFile(tag, rHandle) - if tHandle: + if itemClass != nwItemClass.NO_CLASS: + if not (rHandle := SHARED.project.tree.findRoot(itemClass)): + self.newTreeItem(nwItemType.ROOT, itemClass) + rHandle = SHARED.project.tree.findRoot(itemClass) + if rHandle and (tHandle := SHARED.project.newFile(tag, rHandle)): SHARED.project.writeNewFile(tHandle, 1, False, f"@tag: {tag}\n\n") self.revealNewTreeItem(tHandle, wordCount=True) - return True - return False + return def newTreeItem(self, itemType: nwItemType, itemClass: nwItemClass | None = None, hLevel: int = 1, isNote: bool = False, copyDoc: str | None = None) -> bool: diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index c6ea31f2..3be987a7 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -273,6 +273,7 @@ class GuiMain(QMainWindow): self.docEditor.toggleFocusModeRequest.connect(self.toggleFocusMode) self.docEditor.requestProjectItemSelected.connect(self.projView.setSelectedHandle) self.docEditor.requestProjectItemRenamed.connect(self.projView.renameTreeItem) + self.docEditor.requestNewNoteCreation.connect(self.projView.createNewNote) self.docViewer.documentLoaded.connect(self.docViewerPanel.updateHandle) self.docViewer.loadDocumentTagRequest.connect(self._followTag) diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py index 60f75fe8..a1229b89 100644 --- a/tests/test_gui/test_gui_doceditor.py +++ b/tests/test_gui/test_gui_doceditor.py @@ -30,7 +30,9 @@ from PyQt5.QtCore import QThreadPool, Qt from PyQt5.QtWidgets import QAction, QMenu, qApp from novelwriter import CONFIG, SHARED -from novelwriter.enum import nwDocAction, nwDocInsert, nwItemLayout, nwTrinary, nwWidget +from novelwriter.enum import ( + nwDocAction, nwDocInsert, nwItemClass, nwItemLayout, nwTrinary, nwWidget +) from novelwriter.constants import nwKeyWords, nwUnicode from novelwriter.gui.doceditor import GuiDocEditor, GuiDocToolBar from novelwriter.text.counting import standardCounter @@ -1527,7 +1529,12 @@ def testGuiEditor_Tags(qtbot, nwGUI, projPath, ipsumText, mockRnd): assert "0000000000012" not in SHARED.project.tree nwGUI.docEditor.setCursorPosition(42) assert nwGUI.docEditor._processTag(create=True) is nwTrinary.NEGATIVE - assert "0000000000012" not in SHARED.project.tree + oHandle = SHARED.project.tree.findRoot(nwItemClass.OBJECT) + assert oHandle == "0000000000012" + + oItem = SHARED.project.tree["0000000000013"] + assert oItem is not None + assert oItem.itemParent == "0000000000012" nwGUI.docEditor.setCursorPosition(47) assert nwGUI.docEditor._processTag() is nwTrinary.NEUTRAL