Add a context menu option to rename a document from any title within it

This commit is contained in:
Veronica Berglyd Olsen
2023-11-23 19:40:17 +01:00
parent d35dfda92f
commit 3f842c2fbe
4 changed files with 34 additions and 24 deletions
+13 -1
View File
@@ -98,6 +98,7 @@ class GuiDocEditor(QPlainTextEdit):
closeDocumentRequest = pyqtSignal() closeDocumentRequest = pyqtSignal()
toggleFocusModeRequest = pyqtSignal() toggleFocusModeRequest = pyqtSignal()
requestProjectItemSelected = pyqtSignal(str, bool) requestProjectItemSelected = pyqtSignal(str, bool)
requestProjectItemRenamed = pyqtSignal(str, str)
def __init__(self, mainGui: GuiMain) -> None: def __init__(self, mainGui: GuiMain) -> None:
super().__init__(parent=mainGui) super().__init__(parent=mainGui)
@@ -371,7 +372,7 @@ class GuiDocEditor(QPlainTextEdit):
return return
def loadText(self, tHandle, tLine=None) -> bool: def loadText(self, tHandle: str, tLine=None) -> bool:
"""Load text from a document into the editor. If we have an I/O """Load text from a document into the editor. If we have an I/O
error, we must handle this and clear the editor so that we don't error, we must handle this and clear the editor so that we don't
risk overwriting the file if it exists. This can for instance risk overwriting the file if it exists. This can for instance
@@ -1071,8 +1072,12 @@ class GuiDocEditor(QPlainTextEdit):
""" """
uCursor = self.textCursor() uCursor = self.textCursor()
pCursor = self.cursorForPosition(pos) pCursor = self.cursorForPosition(pos)
pBlock = pCursor.block()
ctxMenu = QMenu(self) ctxMenu = QMenu(self)
if pBlock.userState() == GuiDocHighlighter.BLOCK_TITLE:
aLabel = ctxMenu.addAction(self.tr("Set as Document Name"))
aLabel.triggered.connect(lambda: self._emitRenameItem(pBlock))
# Follow # Follow
status = self._processTag(cursor=pCursor, follow=False) status = self._processTag(cursor=pCursor, follow=False)
@@ -1867,6 +1872,13 @@ class GuiDocEditor(QPlainTextEdit):
return nwTrinary.NEUTRAL return nwTrinary.NEUTRAL
def _emitRenameItem(self, block: QTextBlock) -> None:
"""Emit a signal to request an item be renamed."""
if self._docHandle:
text = block.text().lstrip("#").lstrip("!").strip()
self.requestProjectItemRenamed.emit(self._docHandle, text)
return
def _openContextFromCursor(self) -> None: def _openContextFromCursor(self) -> None:
"""Open the spell check context menu at the cursor.""" """Open the spell check context menu at the cursor."""
self._openContextMenu(self.cursorRect().center()) self._openContextMenu(self.cursorRect().center())
+17 -17
View File
@@ -190,17 +190,20 @@ class GuiProjectView(QWidget):
"""Check if the project tree has focus.""" """Check if the project tree has focus."""
return self.projTree.hasFocus() return self.projTree.hasFocus()
def renameTreeItem(self, tHandle: str | None = None) -> bool: ##
# Public Slots
##
@pyqtSlot(str, str)
def renameTreeItem(self, tHandle: str | None = None, name: str = "") -> None:
"""External request to rename an item or the currently selected """External request to rename an item or the currently selected
item. This is triggered by the global menu or keyboard shortcut. item. This is triggered by the global menu or keyboard shortcut.
""" """
if tHandle is None: if tHandle is None:
tHandle = self.projTree.getSelectedHandle() tHandle = self.projTree.getSelectedHandle()
return self.projTree.renameTreeItem(tHandle) if tHandle else False if tHandle:
self.projTree.renameTreeItem(tHandle, name=name)
## return
# Public Slots
##
@pyqtSlot(str, bool) @pyqtSlot(str, bool)
def setSelectedHandle(self, tHandle: str, doScroll: bool = False) -> None: def setSelectedHandle(self, tHandle: str, doScroll: bool = False) -> None:
@@ -766,19 +769,16 @@ class GuiProjectTree(QTreeWidget):
self.setCurrentItem(tItem.child(0)) self.setCurrentItem(tItem.child(0))
return return
def renameTreeItem(self, tHandle: str) -> bool: def renameTreeItem(self, tHandle: str, name: str = "") -> None:
"""Open a dialog to edit the label of an item.""" """Open a dialog to edit the label of an item."""
tItem = SHARED.project.tree[tHandle] tItem = SHARED.project.tree[tHandle]
if tItem is None: if tItem:
return False newLabel, dlgOk = GuiEditLabel.getLabel(self, text=name or tItem.itemName)
if dlgOk:
newLabel, dlgOk = GuiEditLabel.getLabel(self, text=tItem.itemName) tItem.setName(newLabel)
if dlgOk: self.setTreeItemValues(tHandle)
tItem.setName(newLabel) self._alertTreeChange(tHandle, flush=False)
self.setTreeItemValues(tHandle) return
self._alertTreeChange(tHandle, flush=False)
return True
def saveTreeOrder(self) -> None: def saveTreeOrder(self) -> None:
"""Build a list of the items in the project tree and send them """Build a list of the items in the project tree and send them
+1
View File
@@ -285,6 +285,7 @@ class GuiMain(QMainWindow):
self.docEditor.closeDocumentRequest.connect(self.closeDocEditor) self.docEditor.closeDocumentRequest.connect(self.closeDocEditor)
self.docEditor.toggleFocusModeRequest.connect(self.toggleFocusMode) self.docEditor.toggleFocusModeRequest.connect(self.toggleFocusMode)
self.docEditor.requestProjectItemSelected.connect(self.projView.setSelectedHandle) self.docEditor.requestProjectItemSelected.connect(self.projView.setSelectedHandle)
self.docEditor.requestProjectItemRenamed.connect(self.projView.renameTreeItem)
self.docViewer.documentLoaded.connect(self.docViewerPanel.updateHandle) self.docViewer.documentLoaded.connect(self.docViewerPanel.updateHandle)
self.docViewer.loadDocumentTagRequest.connect(self._followTag) self.docViewer.loadDocumentTagRequest.connect(self._followTag)
+3 -6
View File
@@ -156,12 +156,9 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, projPath, mockRn
# Rename plot folder # Rename plot folder
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(GuiEditLabel, "getLabel", lambda *a, **k: ("Stuff", True)) mp.setattr(GuiEditLabel, "getLabel", lambda *a, **k: ("Stuff", True))
projTree.renameTreeItem(C.hPlotRoot) is True projTree.renameTreeItem(C.hPlotRoot)
assert project.tree[C.hPlotRoot].itemName == "Stuff" # type: ignore assert project.tree[C.hPlotRoot].itemName == "Stuff" # type: ignore
# Rename invalid folder
projTree.renameTreeItem("0000000000000") is False
# Other Checks # Other Checks
# ============ # ============
@@ -1095,12 +1092,12 @@ def testGuiProjTree_Other(qtbot, monkeypatch, nwGUI: GuiMain, projPath, mockRnd)
mp.setattr(GuiEditLabel, "getLabel", lambda *a, **k: ("FooBar", True)) mp.setattr(GuiEditLabel, "getLabel", lambda *a, **k: ("FooBar", True))
projTree.clearSelection() projTree.clearSelection()
assert SHARED.project.tree[C.hChapterDoc].itemName == "New Chapter" # type: ignore assert SHARED.project.tree[C.hChapterDoc].itemName == "New Chapter" # type: ignore
assert projView.renameTreeItem(C.hChapterDoc) is True projView.renameTreeItem(C.hChapterDoc)
assert SHARED.project.tree[C.hChapterDoc].itemName == "FooBar" # type: ignore assert SHARED.project.tree[C.hChapterDoc].itemName == "FooBar" # type: ignore
projTree.setSelectedHandle(C.hSceneDoc) projTree.setSelectedHandle(C.hSceneDoc)
assert SHARED.project.tree[C.hSceneDoc].itemName == "New Scene" # type: ignore assert SHARED.project.tree[C.hSceneDoc].itemName == "New Scene" # type: ignore
assert projView.renameTreeItem() is True projView.renameTreeItem()
assert SHARED.project.tree[C.hSceneDoc].itemName == "FooBar" # type: ignore assert SHARED.project.tree[C.hSceneDoc].itemName == "FooBar" # type: ignore
# Check Crash Resistance # Check Crash Resistance