Re-enable project tree context menu and clean up split and merge

This commit is contained in:
Veronica Berglyd Olsen
2024-11-20 16:42:08 +01:00
parent 3f41e62e21
commit 072be78991
4 changed files with 539 additions and 604 deletions
+88 -100
View File
@@ -56,10 +56,17 @@ class DocMerger:
def __init__(self, project: NWProject) -> None: def __init__(self, project: NWProject) -> None:
self._project = project self._project = project
self._error = "" self._error = ""
self._targetDoc = None self._target = None
self._targetText = [] self._text = []
return return
@property
def targetHandle(self) -> str | None:
"""Get the handle of the target document."""
if self._target:
return self._target.itemHandle
return None
## ##
# Methods # Methods
## ##
@@ -72,63 +79,56 @@ class DocMerger:
"""Set the target document for the merging. Calling this """Set the target document for the merging. Calling this
function resets the class. function resets the class.
""" """
self._targetDoc = tHandle self._target = self._project.tree[tHandle]
self._targetText = [] self._text = []
return return
def newTargetDoc(self, srcHandle: str, docLabel: str) -> str | None: def newTargetDoc(self, sHandle: str, label: str) -> None:
"""Create a brand new target document based on a source handle """Create a brand new target document based on a source handle
and a new doc label. Calling this function resets the class. and a new doc label. Calling this function resets the class.
""" """
srcItem = self._project.tree[srcHandle] sItem = self._project.tree[sHandle]
if srcItem is None or srcItem.itemParent is None: if sItem and sItem.itemParent:
return None tHandle = self._project.newFile(label, sItem.itemParent)
if nwItem := self._project.tree[tHandle]:
nwItem.setLayout(sItem.itemLayout)
nwItem.setStatus(sItem.itemStatus)
nwItem.setImport(sItem.itemImport)
nwItem.notifyToRefresh()
self._target = nwItem
self._text = []
return
newHandle = self._project.newFile(docLabel, srcItem.itemParent) def appendText(self, sHandle: str, addComment: bool, cmtPrefix: str) -> None:
newItem = self._project.tree[newHandle]
if isinstance(newItem, NWItem):
newItem.setLayout(srcItem.itemLayout)
newItem.setStatus(srcItem.itemStatus)
newItem.setImport(srcItem.itemImport)
self._targetDoc = newHandle
self._targetText = []
return newHandle
def appendText(self, srcHandle: str, addComment: bool, cmtPrefix: str) -> bool:
"""Append text from an existing document to the text buffer.""" """Append text from an existing document to the text buffer."""
srcItem = self._project.tree[srcHandle] if item := self._project.tree[sHandle]:
if srcItem is None: text = self._project.storage.getDocumentText(sHandle).rstrip("\n")
return False if addComment:
info = item.describeMe()
docText = self._project.storage.getDocumentText(srcHandle).rstrip("\n") status, _ = item.getImportStatus()
if addComment: text = f"% {cmtPrefix} {info}: {item.itemName} [{status}]\n\n{text}"
docInfo = srcItem.describeMe() self._text.append(text)
docSt, _ = srcItem.getImportStatus() return
cmtLine = f"% {cmtPrefix} {docInfo}: {srcItem.itemName} [{docSt}]\n\n"
docText = cmtLine + docText
self._targetText.append(docText)
return True
def writeTargetDoc(self) -> bool: def writeTargetDoc(self) -> bool:
"""Write the accumulated text into the designated target """Write the accumulated text into the designated target
document, appending any existing text. document, appending any existing text.
""" """
if self._targetDoc is None: if self._target:
return False outDoc = self._project.storage.getDocument(self._target.itemHandle)
if text := (outDoc.readDocument() or "").rstrip("\n"):
self._text.insert(0, text)
outDoc = self._project.storage.getDocument(self._targetDoc) status = outDoc.writeDocument("\n\n".join(self._text) + "\n\n")
if text := (outDoc.readDocument() or "").rstrip("\n"): if not status:
self._targetText.insert(0, text) self._error = outDoc.getError()
status = outDoc.writeDocument("\n\n".join(self._targetText) + "\n\n") self._project.index.reIndexHandle(self._target.itemHandle)
if not status: self._target.notifyToRefresh()
self._error = outDoc.getError()
return status return status
return False
class DocSplitter: class DocSplitter:
@@ -172,23 +172,19 @@ class DocSplitter:
self._inFolder = False self._inFolder = False
return return
def newParentFolder(self, pHandle: str, folderLabel: str) -> str | None: def newParentFolder(self, pHandle: str, folderLabel: str) -> None:
"""Create a new folder that will be the top level parent item """Create a new folder that will be the top level parent item
for the new documents. for the new documents.
""" """
if self._srcItem is None: if self._srcItem:
return None nHandle = self._project.newFolder(folderLabel, pHandle)
if nwItem := self._project.tree[nHandle]:
newHandle = self._project.newFolder(folderLabel, pHandle) nwItem.setStatus(self._srcItem.itemStatus)
newItem = self._project.tree[newHandle] nwItem.setImport(self._srcItem.itemImport)
if isinstance(newItem, NWItem): nwItem.notifyToRefresh()
newItem.setStatus(self._srcItem.itemStatus) self._parHandle = nHandle
newItem.setImport(self._srcItem.itemImport) self._inFolder = True
return
self._parHandle = newHandle
self._inFolder = True
return newHandle
def splitDocument(self, splitData: list, splitText: list[str]) -> None: def splitDocument(self, splitData: list, splitText: list[str]) -> None:
"""Loop through the split data record and perform the split job """Loop through the split data record and perform the split job
@@ -202,58 +198,50 @@ class DocSplitter:
self._rawData.insert(0, (chunk, hLevel, hLabel)) self._rawData.insert(0, (chunk, hLevel, hLabel))
return return
def writeDocuments(self, docHierarchy: bool) -> Iterable[tuple[bool, str | None, str | None]]: def writeDocuments(self, docHierarchy: bool) -> Iterable[bool]:
"""An iterator that will write each document in the buffer, and """An iterator that will write each document in the buffer, and
return its new handle, parent handle, and sibling handle. return its new handle, parent handle, and sibling handle.
""" """
if self._srcHandle is None or self._srcItem is None or self._parHandle is None: if self._srcHandle and self._srcItem and self._parHandle:
return pHandle = self._parHandle
hHandle = [self._parHandle, None, None, None, None]
pLevel = 0
for docText, hLevel, docLabel in self._rawData:
pHandle = self._parHandle hLevel = minmax(hLevel, 1, 4)
nHandle = self._parHandle if self._inFolder else self._srcHandle if pLevel == 0:
hHandle = [self._parHandle, None, None, None, None] pLevel = hLevel
pLevel = 0 if docHierarchy:
for docText, hLevel, docLabel in self._rawData: if hLevel == 1:
pHandle = self._parHandle
elif hLevel == 2:
pHandle = hHandle[1] or hHandle[0]
elif hLevel == 3:
pHandle = hHandle[2] or hHandle[1] or hHandle[0]
elif hLevel == 4:
pHandle = hHandle[3] or hHandle[2] or hHandle[1] or hHandle[0]
hLevel = minmax(hLevel, 1, 4) if (
if pLevel == 0: (dHandle := self._project.newFile(docLabel, pHandle))
pLevel = hLevel and (nwItem := self._project.tree[dHandle])
):
hHandle[hLevel] = dHandle
nwItem.setStatus(self._srcItem.itemStatus)
nwItem.setImport(self._srcItem.itemImport)
if docHierarchy: outDoc = self._project.storage.getDocument(dHandle)
if hLevel == 1: status = outDoc.writeDocument("\n".join(docText))
pHandle = self._parHandle if not status:
elif hLevel == 2: self._error = outDoc.getError()
pHandle = hHandle[1] or hHandle[0]
elif hLevel == 3:
pHandle = hHandle[2] or hHandle[1] or hHandle[0]
elif hLevel == 4:
pHandle = hHandle[3] or hHandle[2] or hHandle[1] or hHandle[0]
if hLevel < pLevel: self._project.index.reIndexHandle(dHandle)
nHandle = hHandle[hLevel] or hHandle[0] nwItem.notifyToRefresh()
elif hLevel > pLevel:
nHandle = pHandle
dHandle = self._project.newFile(docLabel, pHandle) yield status
hHandle[hLevel] = dHandle
newItem = self._project.tree[dHandle]
if isinstance(newItem, NWItem):
newItem.setStatus(self._srcItem.itemStatus)
newItem.setImport(self._srcItem.itemImport)
outDoc = self._project.storage.getDocument(dHandle)
status = outDoc.writeDocument("\n".join(docText))
if not status:
self._error = outDoc.getError()
yield status, dHandle, nHandle
hHandle[hLevel] = dHandle
nHandle = dHandle
pLevel = hLevel
hHandle[hLevel] = dHandle
pLevel = hLevel
return return
+6
View File
@@ -391,6 +391,12 @@ class NWTree:
return tTree return tTree
def subTree(self, tHandle: str) -> list[str]:
"""Get the subtree from a given handle."""
if node := self._nodes.get(tHandle):
return [child.item.itemHandle for child in node.allChildren()]
return []
## ##
# Tree Root Methods # Tree Root Methods
## ##
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1321,11 +1321,11 @@ def testGuiProjTree_ContextMenu(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
# Click no on the dialog # Click no on the dialog
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.StandardButton.No) mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.StandardButton.No)
ctxMenu._covertFolderToFile(nwItemLayout.DOCUMENT) ctxMenu._convertFolderToFile(nwItemLayout.DOCUMENT)
assert SHARED.project.tree[hNewFolderOne].isFolderType() # type: ignore assert SHARED.project.tree[hNewFolderOne].isFolderType() # type: ignore
# Convert the first folder to a document # Convert the first folder to a document
ctxMenu._covertFolderToFile(nwItemLayout.DOCUMENT) ctxMenu._convertFolderToFile(nwItemLayout.DOCUMENT)
assert SHARED.project.tree[hNewFolderOne].isFileType() # type: ignore assert SHARED.project.tree[hNewFolderOne].isFileType() # type: ignore
assert SHARED.project.tree[hNewFolderOne].isDocumentLayout() # type: ignore assert SHARED.project.tree[hNewFolderOne].isDocumentLayout() # type: ignore
@@ -1335,7 +1335,7 @@ def testGuiProjTree_ContextMenu(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
ctxMenu.buildSingleSelectMenu(False) ctxMenu.buildSingleSelectMenu(False)
# Convert the second folder to a note # Convert the second folder to a note
ctxMenu._covertFolderToFile(nwItemLayout.NOTE) ctxMenu._convertFolderToFile(nwItemLayout.NOTE)
assert SHARED.project.tree[hNewFolderTwo].isFileType() # type: ignore assert SHARED.project.tree[hNewFolderTwo].isFileType() # type: ignore
assert SHARED.project.tree[hNewFolderTwo].isNoteLayout() # type: ignore assert SHARED.project.tree[hNewFolderTwo].isNoteLayout() # type: ignore