Move project tree context menu to a separate class

This commit is contained in:
Veronica Berglyd Olsen
2023-11-22 18:08:07 +01:00
parent d7730fb7c2
commit ea0358b2ed
+308 -269
View File
@@ -836,6 +836,7 @@ class GuiProjectTree(QTreeWidget):
return status return status
@pyqtSlot()
def emptyTrash(self) -> bool: def emptyTrash(self) -> bool:
"""Permanently delete all documents in the Trash folder. This """Permanently delete all documents in the Trash folder. This
function only asks for confirmation once, and calls the regular function only asks for confirmation once, and calls the regular
@@ -1175,163 +1176,29 @@ class GuiProjectTree(QTreeWidget):
tItem = None tItem = None
tHandle = None tHandle = None
hasChild = False hasChild = False
selItem = self.itemAt(clickPos) sItem = self.itemAt(clickPos)
if isinstance(selItem, QTreeWidgetItem): sItems = self.selectedItems()
tHandle = selItem.data(self.C_DATA, self.D_HANDLE) if isinstance(sItem, QTreeWidgetItem):
tHandle = sItem.data(self.C_DATA, self.D_HANDLE)
tItem = SHARED.project.tree[tHandle] tItem = SHARED.project.tree[tHandle]
hasChild = selItem.childCount() > 0 hasChild = sItem.childCount() > 0
if tItem is None or tHandle is None: if tItem is None or tHandle is None:
logger.debug("No item found") logger.debug("No item found")
return False return False
if len(self.selectedItems()) > 1: ctxMenu = _TreeContextMenu(self, tItem)
return self._openMultiSelectContextMenu(clickPos, tItem)
ctxMenu = QMenu(self)
# Trash Folder
# ============
trashHandle = SHARED.project.tree.trashRoot trashHandle = SHARED.project.tree.trashRoot
if tItem.itemHandle == trashHandle and trashHandle is not None: if trashHandle and tHandle == trashHandle:
# The trash folder only has one option ctxMenu.buildTrashMenu()
aEmptyTrash = ctxMenu.addAction(self.tr("Empty Trash")) elif len(sItems) > 1:
aEmptyTrash.triggered.connect(lambda: self.emptyTrash()) handles = [str(x.data(self.C_DATA, self.D_HANDLE)) for x in sItems]
ctxMenu.exec_(self.viewport().mapToGlobal(clickPos)) ctxMenu.buildMultiSelectMenu(handles)
return True
# Document Actions
# ================
isRoot = tItem.isRootType()
isFolder = tItem.isFolderType()
isFile = tItem.isFileType()
if isFile:
aOpenDoc = ctxMenu.addAction(self.tr("Open Document"))
aOpenDoc.triggered.connect(
lambda: self.projView.openDocumentRequest.emit(tHandle, nwDocMode.EDIT, "", True)
)
aViewDoc = ctxMenu.addAction(self.tr("View Document"))
aViewDoc.triggered.connect(
lambda: self.projView.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, "", False)
)
ctxMenu.addSeparator()
# Edit Item Settings
# ==================
aLabel = ctxMenu.addAction(self.tr("Rename"))
aLabel.triggered.connect(lambda: self.renameTreeItem(tHandle))
if isFile:
aActive = ctxMenu.addAction(self.tr("Toggle Active"))
aActive.triggered.connect(lambda: self._toggleItemActive(tHandle))
checkMark = f" ({nwUnicode.U_CHECK})"
if tItem.isNovelLike():
mStatus = ctxMenu.addMenu(self.tr("Set Status to ..."))
for n, (key, entry) in enumerate(SHARED.project.data.itemStatus.items()):
entryName = entry["name"] + (checkMark if tItem.itemStatus == key else "")
aStatus = mStatus.addAction(entry["icon"], entryName)
aStatus.triggered.connect(
lambda n, key=key: self._changeItemStatus(tHandle, key)
)
mStatus.addSeparator()
aManage1 = mStatus.addAction(self.tr("Manage Labels ..."))
aManage1.triggered.connect(
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_STATUS)
)
else: else:
mImport = ctxMenu.addMenu(self.tr("Set Importance to ...")) ctxMenu.buildSingleSelectMenu(hasChild)
for n, (key, entry) in enumerate(SHARED.project.data.itemImport.items()):
entryName = entry["name"] + (checkMark if tItem.itemImport == key else "")
aImport = mImport.addAction(entry["icon"], entryName)
aImport.triggered.connect(
lambda n, key=key: self._changeItemImport(tHandle, key)
)
mImport.addSeparator()
aManage2 = mImport.addAction(self.tr("Manage Labels ..."))
aManage2.triggered.connect(
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_IMPORT)
)
# Transform Item
# ==============
if not isRoot:
mTrans = ctxMenu.addMenu(self.tr("Transform"))
trDoc = trConst(nwLabels.LAYOUT_NAME[nwItemLayout.DOCUMENT])
trNote = trConst(nwLabels.LAYOUT_NAME[nwItemLayout.NOTE])
isDocFile = isFile and tItem.isDocumentLayout()
isNoteFile = isFile and tItem.isNoteLayout()
if isNoteFile and tItem.documentAllowed():
aConvert1 = mTrans.addAction(self.tr("Convert to {0}").format(trDoc))
aConvert1.triggered.connect(
lambda: self._changeItemLayout(tHandle, nwItemLayout.DOCUMENT)
)
if isDocFile:
aConvert2 = mTrans.addAction(self.tr("Convert to {0}").format(trNote))
aConvert2.triggered.connect(
lambda: self._changeItemLayout(tHandle, nwItemLayout.NOTE)
)
if isFolder and tItem.documentAllowed():
aConvert3 = mTrans.addAction(self.tr("Convert to {0}").format(trDoc))
aConvert3.triggered.connect(
lambda: self._covertFolderToFile(tHandle, nwItemLayout.DOCUMENT)
)
if isFolder:
aConvert4 = mTrans.addAction(self.tr("Convert to {0}").format(trNote))
aConvert4.triggered.connect(
lambda: self._covertFolderToFile(tHandle, nwItemLayout.NOTE)
)
if hasChild and isFile:
aMerge1 = mTrans.addAction(self.tr("Merge Child Items into Self"))
aMerge1.triggered.connect(lambda: self._mergeDocuments(tHandle, False))
aMerge2 = mTrans.addAction(self.tr("Merge Child Items into New"))
aMerge2.triggered.connect(lambda: self._mergeDocuments(tHandle, True))
if hasChild and isFolder:
aMerge3 = mTrans.addAction(self.tr("Merge Documents in Folder"))
aMerge3.triggered.connect(lambda: self._mergeDocuments(tHandle, True))
if isFile:
aSplit1 = mTrans.addAction(self.tr("Split Document by Headers"))
aSplit1.triggered.connect(lambda: self._splitDocument(tHandle))
# Expand/Collapse/Delete/Duplicate
# ================================
ctxMenu.addSeparator()
if hasChild:
aExpand = ctxMenu.addAction(self.tr("Expand All"))
aExpand.triggered.connect(lambda: self.setExpandedFromHandle(tHandle, True))
aCollapse = ctxMenu.addAction(self.tr("Collapse All"))
aCollapse.triggered.connect(lambda: self.setExpandedFromHandle(tHandle, False))
aDuplicate = ctxMenu.addAction(self.tr("Duplicate from Here"))
aDuplicate.triggered.connect(lambda: self._duplicateFromHandle(tHandle))
elif isFile:
aDuplicate = ctxMenu.addAction(self.tr("Duplicate Document"))
aDuplicate.triggered.connect(lambda: self._duplicateFromHandle(tHandle))
if tItem.itemClass == nwItemClass.TRASH or isRoot or (isFolder and not hasChild):
aDelete = ctxMenu.addAction(self.tr("Delete Permanently"))
aDelete.triggered.connect(lambda: self.permDeleteItem(tHandle))
else:
aMoveTrash = ctxMenu.addAction(self.tr("Move to Trash"))
aMoveTrash.triggered.connect(lambda: self.moveItemToTrash(tHandle))
# Show Context Menu
ctxMenu.exec_(self.viewport().mapToGlobal(clickPos)) ctxMenu.exec_(self.viewport().mapToGlobal(clickPos))
ctxMenu.deleteLater()
return True return True
@@ -1482,15 +1349,6 @@ class GuiProjectTree(QTreeWidget):
"""Return the QTreeWidgetItem of a given item handle.""" """Return the QTreeWidgetItem of a given item handle."""
return self._treeMap.get(tHandle, None) if tHandle else None return self._treeMap.get(tHandle, None) if tHandle else None
def _toggleItemActive(self, tHandle: str) -> None:
"""Toggle the active status of an item."""
tItem = SHARED.project.tree[tHandle]
if tItem is not None:
tItem.setActive(not tItem.isActive)
self.setTreeItemValues(tItem.itemHandle)
self._alertTreeChange(tHandle, flush=False)
return
def _recursiveSetExpanded(self, trItem: QTreeWidgetItem, isExpanded: bool) -> None: def _recursiveSetExpanded(self, trItem: QTreeWidgetItem, isExpanded: bool) -> None:
"""Recursive function to set expanded status starting from (and """Recursive function to set expanded status starting from (and
not including) a given item. not including) a given item.
@@ -1503,60 +1361,6 @@ class GuiProjectTree(QTreeWidget):
self._recursiveSetExpanded(chItem, isExpanded) self._recursiveSetExpanded(chItem, isExpanded)
return return
def _changeItemStatus(self, tHandle: str, tStatus: str) -> None:
"""Set a new status value of an item."""
tItem = SHARED.project.tree[tHandle]
if tItem and tItem.isDocumentLayout():
tItem.setStatus(tStatus)
self.setTreeItemValues(tItem.itemHandle)
self._alertTreeChange(tHandle, flush=False)
return
def _changeItemImport(self, tHandle: str, tImport: str) -> None:
"""Set a new importance value of an item."""
tItem = SHARED.project.tree[tHandle]
if tItem and tItem.isNoteLayout():
tItem.setImport(tImport)
self.setTreeItemValues(tItem.itemHandle)
self._alertTreeChange(tHandle, flush=False)
return
def _changeItemLayout(self, tHandle: str, itemLayout: nwItemLayout) -> None:
"""Set a new item layout value of an item."""
tItem = SHARED.project.tree[tHandle]
if tItem is not None:
if itemLayout == nwItemLayout.DOCUMENT and tItem.documentAllowed():
tItem.setLayout(nwItemLayout.DOCUMENT)
self.setTreeItemValues(tHandle)
self._alertTreeChange(tHandle, flush=False)
elif itemLayout == nwItemLayout.NOTE:
tItem.setLayout(nwItemLayout.NOTE)
self.setTreeItemValues(tHandle)
self._alertTreeChange(tHandle, flush=False)
return
def _covertFolderToFile(self, tHandle: str, itemLayout: nwItemLayout) -> None:
"""Convert a folder to a note or document."""
tItem = SHARED.project.tree[tHandle]
if tItem is not None and tItem.isFolderType():
msgYes = SHARED.question(self.tr(
"Do you want to convert the folder to a {0}? "
"This action cannot be reversed."
).format(trConst(nwLabels.LAYOUT_NAME[itemLayout])))
if msgYes and itemLayout == nwItemLayout.DOCUMENT and tItem.documentAllowed():
tItem.setType(nwItemType.FILE)
tItem.setLayout(nwItemLayout.DOCUMENT)
self.setTreeItemValues(tHandle)
self._alertTreeChange(tHandle, flush=False)
elif msgYes and itemLayout == nwItemLayout.NOTE:
tItem.setType(nwItemType.FILE)
tItem.setLayout(nwItemLayout.NOTE)
self.setTreeItemValues(tHandle)
self._alertTreeChange(tHandle, flush=False)
else:
logger.info("Folder conversion cancelled")
return
def _mergeDocuments(self, tHandle: str, newFile: bool) -> bool: def _mergeDocuments(self, tHandle: str, newFile: bool) -> bool:
"""Merge an item's child documents into a single document.""" """Merge an item's child documents into a single document."""
logger.info("Request to merge items under handle '%s'", tHandle) logger.info("Request to merge items under handle '%s'", tHandle)
@@ -1822,87 +1626,322 @@ class GuiProjectTree(QTreeWidget):
return return
# END Class GuiProjectTree
class _TreeContextMenu(QMenu):
def __init__(self, projTree: GuiProjectTree, nwItem: NWItem) -> None:
super().__init__(parent=projTree)
self.projTree = projTree
self.projView = projTree.projView
self._item = nwItem
self._handle = nwItem.itemHandle
self._items: list[str] = []
logger.debug("Ready: _TreeContextMenu")
return
def __del__(self): # pragma: no cover
logger.debug("Delete: _TreeContextMenu")
return
## ##
# Multi-Select Context Menu Functions # Methods
## ##
def _openMultiSelectContextMenu(self, clickPos: QPoint, tItem: NWItem) -> bool: def buildTrashMenu(self) -> None:
"""Alternative menu for multiple selected items.""" """Build the special menu for the Trash folder."""
ctxMenu = QMenu(self) action = self.addAction(self.tr("Empty Trash"))
action.triggered.connect(self.projTree.emptyTrash)
return
mActive = ctxMenu.addMenu(self.tr("Set Active to ...")) def buildSingleSelectMenu(self, hasChild: bool) -> None:
aActive = mActive.addAction(SHARED.theme.getIcon("checked"), self.tr("Active")) """Build the single-select menu."""
aActive.triggered.connect(lambda: self._iterItemActive(True)) isFile = self._item.isFileType()
aInactive = mActive.addAction(SHARED.theme.getIcon("unchecked"), self.tr("Inactive")) isFolder = self._item.isFolderType()
aInactive.triggered.connect(lambda: self._iterItemActive(False)) isRoot = self._item.isRootType()
if tItem.isNovelLike(): # Document Actions
mStatus = ctxMenu.addMenu(self.tr("Set Status to ...")) if isFile:
self._docActions()
self.addSeparator()
# Edit Item Settings
aLabel = self.addAction(self.tr("Rename"))
aLabel.triggered.connect(lambda: self.projTree.renameTreeItem(self._handle))
if isFile:
self._itemActive(False)
self._itemStatusImport(False)
# Transform Item
if isFile or isFolder:
self._itemTransform(isFile, isFolder, hasChild)
self.addSeparator()
# Process Item
self._itemProcess(isFile, isFolder, isRoot, hasChild)
return
def buildMultiSelectMenu(self, items: list[str]) -> None:
"""Build the multi-select menu."""
self._items = items
self._itemActive(True)
self._itemStatusImport(True)
self.addSeparator()
self._moveToTrash(True)
return
##
# Menu Builders
##
def _docActions(self) -> None:
"""Add document actions."""
action = self.addAction(self.tr("Open Document"))
action.triggered.connect(
lambda: self.projView.openDocumentRequest.emit(self._handle, nwDocMode.EDIT, "", True)
)
action = self.addAction(self.tr("View Document"))
action.triggered.connect(
lambda: self.projView.openDocumentRequest.emit(self._handle, nwDocMode.VIEW, "", False)
)
return
def _itemActive(self, multi: bool) -> None:
"""Add Active/Inactive actions."""
if multi:
mSub = self.addMenu(self.tr("Set Active to ..."))
aOne = mSub.addAction(SHARED.theme.getIcon("checked"), self.tr("Active"))
aOne.triggered.connect(lambda: self._iterItemActive(True))
aTwo = mSub.addAction(SHARED.theme.getIcon("unchecked"), self.tr("Inactive"))
aTwo.triggered.connect(lambda: self._iterItemActive(False))
else:
action = self.addAction(self.tr("Toggle Active"))
action.triggered.connect(self._toggleItemActive)
return
def _itemStatusImport(self, multi: bool) -> None:
"""Add actions for changing status or importance."""
if self._item.isNovelLike():
menu = self.addMenu(self.tr("Set Status to ..."))
current = self._item.itemStatus
for n, (key, entry) in enumerate(SHARED.project.data.itemStatus.items()): for n, (key, entry) in enumerate(SHARED.project.data.itemStatus.items()):
aStatus = mStatus.addAction(entry["icon"], entry["name"]) name = entry["name"]
aStatus.triggered.connect(lambda n, key=key: self._iterSetItemStatus(key)) if not multi and current == key:
mStatus.addSeparator() name += f" ({nwUnicode.U_CHECK})"
aManage1 = mStatus.addAction(self.tr("Manage Labels ...")) action = menu.addAction(entry["icon"], name)
aManage1.triggered.connect( if multi:
action.triggered.connect(lambda n, key=key: self._iterSetItemStatus(key))
else:
action.triggered.connect(lambda n, key=key: self._changeItemStatus(key))
menu.addSeparator()
action = menu.addAction(self.tr("Manage Labels ..."))
action.triggered.connect(
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_STATUS) lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_STATUS)
) )
else: else:
mImport = ctxMenu.addMenu(self.tr("Set Importance to ...")) menu = self.addMenu(self.tr("Set Importance to ..."))
current = self._item.itemImport
for n, (key, entry) in enumerate(SHARED.project.data.itemImport.items()): for n, (key, entry) in enumerate(SHARED.project.data.itemImport.items()):
aImport = mImport.addAction(entry["icon"], entry["name"], ) name = entry["name"]
aImport.triggered.connect(lambda n, key=key: self._iterSetItemImport(key)) if not multi and current == key:
mImport.addSeparator() name += f" ({nwUnicode.U_CHECK})"
aManage2 = mImport.addAction(self.tr("Manage Labels ...")) action = menu.addAction(entry["icon"], name)
aManage2.triggered.connect( if multi:
action.triggered.connect(lambda n, key=key: self._iterSetItemImport(key))
else:
action.triggered.connect(lambda n, key=key: self._changeItemImport(key))
menu.addSeparator()
action = menu.addAction(self.tr("Manage Labels ..."))
action.triggered.connect(
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_IMPORT) lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_IMPORT)
) )
ctxMenu.addSeparator()
aMoveTrash = ctxMenu.addAction(self.tr("Move to Trash"))
aMoveTrash.triggered.connect(self._iterMoveToTrash)
# Show Context Menu
ctxMenu.exec_(self.viewport().mapToGlobal(clickPos))
return True
def _iterItemActive(self, isActive: bool) -> None:
"""Change the active status multiple items."""
for item in self.selectedItems():
tHandle = str(item.data(self.C_DATA, self.D_HANDLE))
tItem = SHARED.project.tree[tHandle]
if tItem and tItem.isFileType():
tItem.setActive(isActive)
self.setTreeItemValues(tItem.itemHandle)
self._alertTreeChange(tHandle, flush=False)
return return
def _iterSetItemStatus(self, tStatus: str) -> None: def _itemTransform(self, isFile: bool, isFolder: bool, hasChild: bool) -> None:
"""Change the status value for multiple items.""" """Add actions for the Transform menu."""
for item in self.selectedItems(): menu = self.addMenu(self.tr("Transform"))
tHandle = str(item.data(self.C_DATA, self.D_HANDLE))
self._changeItemStatus(tHandle, tStatus) tree = self.projTree
tHandle = self._handle
trDoc = trConst(nwLabels.LAYOUT_NAME[nwItemLayout.DOCUMENT])
trNote = trConst(nwLabels.LAYOUT_NAME[nwItemLayout.NOTE])
loDoc = nwItemLayout.DOCUMENT
loNote = nwItemLayout.NOTE
isDocFile = isFile and self._item.isDocumentLayout()
isNoteFile = isFile and self._item.isNoteLayout()
if isNoteFile and self._item.documentAllowed():
action = menu.addAction(self.tr("Convert to {0}").format(trDoc))
action.triggered.connect(lambda: self._changeItemLayout(loDoc))
if isDocFile:
action = menu.addAction(self.tr("Convert to {0}").format(trNote))
action.triggered.connect(lambda: self._changeItemLayout(loNote))
if isFolder and self._item.documentAllowed():
action = menu.addAction(self.tr("Convert to {0}").format(trDoc))
action.triggered.connect(lambda: self._covertFolderToFile(loDoc))
if isFolder:
action = menu.addAction(self.tr("Convert to {0}").format(trNote))
action.triggered.connect(lambda: self._covertFolderToFile(loNote))
if hasChild and isFile:
action = menu.addAction(self.tr("Merge Child Items into Self"))
action.triggered.connect(lambda: tree._mergeDocuments(tHandle, False))
action = menu.addAction(self.tr("Merge Child Items into New"))
action.triggered.connect(lambda: tree._mergeDocuments(tHandle, True))
if hasChild and isFolder:
action = menu.addAction(self.tr("Merge Documents in Folder"))
action.triggered.connect(lambda: tree._mergeDocuments(tHandle, True))
if isFile:
action = menu.addAction(self.tr("Split Document by Headers"))
action.triggered.connect(lambda: tree._splitDocument(tHandle))
return return
def _iterSetItemImport(self, tStatus: str) -> None: def _itemProcess(self, isFile: bool, isFolder: bool, isRoot: bool, hasChild: bool) -> None:
"""Change the importance value for multiple items.""" """Add actions for item processing."""
for item in self.selectedItems(): tree = self.projTree
tHandle = str(item.data(self.C_DATA, self.D_HANDLE)) tHandle = self._handle
self._changeItemImport(tHandle, tStatus) if hasChild:
action = self.addAction(self.tr("Expand All"))
action.triggered.connect(lambda: tree.setExpandedFromHandle(tHandle, True))
action = self.addAction(self.tr("Collapse All"))
action.triggered.connect(lambda: tree.setExpandedFromHandle(tHandle, False))
action = self.addAction(self.tr("Duplicate from Here"))
action.triggered.connect(lambda: tree._duplicateFromHandle(tHandle))
elif isFile:
action = self.addAction(self.tr("Duplicate Document"))
action.triggered.connect(lambda: tree._duplicateFromHandle(tHandle))
if self._item.itemClass == nwItemClass.TRASH or isRoot or (isFolder and not hasChild):
action = self.addAction(self.tr("Delete Permanently"))
action.triggered.connect(lambda: tree.permDeleteItem(tHandle))
else:
action = self.addAction(self.tr("Move to Trash"))
action.triggered.connect(lambda: tree.moveItemToTrash(tHandle))
return return
def _moveToTrash(self, multi: bool) -> None:
"""Add move to Trash action."""
action = self.addAction(self.tr("Move to Trash"))
if multi:
action.triggered.connect(self._iterMoveToTrash)
return
##
# Private Slots
##
@pyqtSlot() @pyqtSlot()
def _iterMoveToTrash(self) -> None: def _iterMoveToTrash(self) -> None:
"""Iterate through files and move them to Trash.""" """Iterate through files and move them to Trash."""
items = self.selectedItems() if SHARED.question(self.tr("Move {0} items to Trash?").format(len(self._items))):
if SHARED.question(self.tr("Move {0} items to Trash?").format(len(items))): for tHandle in self._items:
for item in self.selectedItems():
tHandle = str(item.data(self.C_DATA, self.D_HANDLE))
tItem = SHARED.project.tree[tHandle] tItem = SHARED.project.tree[tHandle]
if tItem and tItem.isFileType(): if tItem and tItem.isFileType():
self.moveItemToTrash(tHandle, askFirst=False, flush=False) self.projTree.moveItemToTrash(tHandle, askFirst=False, flush=False)
self.saveTreeOrder() self.projTree.saveTreeOrder()
return return
# END Class GuiProjectTree @pyqtSlot()
def _toggleItemActive(self) -> None:
"""Toggle the active status of an item."""
self._item.setActive(not self._item.isActive)
self.projTree.setTreeItemValues(self._handle)
self.projTree._alertTreeChange(self._handle, flush=False)
return
##
# Internal Functions
##
def _iterItemActive(self, isActive: bool) -> None:
"""Set the active status of multiple items."""
for tHandle in self._items:
tItem = SHARED.project.tree[tHandle]
if tItem and tItem.isFileType():
tItem.setActive(isActive)
self.projTree.setTreeItemValues(tHandle)
self.projTree._alertTreeChange(tHandle, flush=False)
return
def _changeItemStatus(self, key: str) -> None:
"""Set a new status value of an item."""
self._item.setStatus(key)
self.projTree.setTreeItemValues(self._handle)
self.projTree._alertTreeChange(self._handle, flush=False)
return
def _iterSetItemStatus(self, key: str) -> None:
"""Change the status value for multiple items."""
for tHandle in self._items:
tItem = SHARED.project.tree[tHandle]
if tItem and tItem.isNovelLike():
tItem.setStatus(key)
self.projTree.setTreeItemValues(tHandle)
self.projTree._alertTreeChange(tHandle, flush=False)
return
def _changeItemImport(self, key: str) -> None:
"""Set a new importance value of an item."""
self._item.setImport(key)
self.projTree.setTreeItemValues(self._handle)
self.projTree._alertTreeChange(self._handle, flush=False)
return
def _iterSetItemImport(self, key: str) -> None:
"""Change the status value for multiple items."""
for tHandle in self._items:
tItem = SHARED.project.tree[tHandle]
if tItem and not tItem.isNovelLike():
tItem.setImport(key)
self.projTree.setTreeItemValues(tHandle)
self.projTree._alertTreeChange(tHandle, flush=False)
return
def _changeItemLayout(self, itemLayout: nwItemLayout) -> None:
"""Set a new item layout value of an item."""
if itemLayout == nwItemLayout.DOCUMENT and self._item.documentAllowed():
self._item.setLayout(nwItemLayout.DOCUMENT)
self.projTree.setTreeItemValues(self._handle)
self.projTree._alertTreeChange(self._handle, flush=False)
elif itemLayout == nwItemLayout.NOTE:
self._item.setLayout(nwItemLayout.NOTE)
self.projTree.setTreeItemValues(self._handle)
self.projTree._alertTreeChange(self._handle, flush=False)
return
def _covertFolderToFile(self, itemLayout: nwItemLayout) -> None:
"""Convert a folder to a note or document."""
if self._item.isFolderType():
msgYes = SHARED.question(self.tr(
"Do you want to convert the folder to a {0}? "
"This action cannot be reversed."
).format(trConst(nwLabels.LAYOUT_NAME[itemLayout])))
if msgYes and itemLayout == nwItemLayout.DOCUMENT and self._item.documentAllowed():
self._item.setType(nwItemType.FILE)
self._item.setLayout(nwItemLayout.DOCUMENT)
self.projTree.setTreeItemValues(self._handle)
self.projTree._alertTreeChange(self._handle, flush=False)
elif msgYes and itemLayout == nwItemLayout.NOTE:
self._item.setType(nwItemType.FILE)
self._item.setLayout(nwItemLayout.NOTE)
self.projTree.setTreeItemValues(self._handle)
self.projTree._alertTreeChange(self._handle, flush=False)
else:
logger.info("Folder conversion cancelled")
return
# END Class _TreeContextMenu