Add back create new project item functionality

This commit is contained in:
Veronica Berglyd Olsen
2024-11-19 00:22:59 +01:00
parent a5575992d6
commit 53e70c118c
5 changed files with 279 additions and 332 deletions
+96 -112
View File
@@ -39,7 +39,7 @@ from PyQt5.QtWidgets import (
from novelwriter import CONFIG, SHARED
from novelwriter.common import qtLambda
from novelwriter.constants import nwLabels, nwUnicode, trConst
from novelwriter.constants import nwLabels, nwStyles, nwUnicode, trConst
from novelwriter.core.item import NWItem
from novelwriter.core.itemmodel import ProjectModel, ProjectNode
from novelwriter.dialogs.editlabel import GuiEditLabel
@@ -568,8 +568,8 @@ class GuiProjectTree(QTreeView):
self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
# Connect signals
self.clicked.connect(self._treeSingleClick)
self.doubleClicked.connect(self._treeDoubleClick)
self.clicked.connect(self._onSingleClick)
self.doubleClicked.connect(self._onDoubleClick)
# Auto Scroll
# self._scrollMargin = SHARED.theme.baseIconHeight
@@ -639,13 +639,19 @@ class GuiProjectTree(QTreeView):
treeHeader.resizeSection(self.C_ACTIVE, iPx + cMg)
treeHeader.resizeSection(self.C_STATUS, iPx + cMg)
self.blockSignals(True)
for index in SHARED.project.tree.model.allExpanded():
self.setExpanded(index, True)
self.blockSignals(False)
self.restoreExpandedState()
return
def restoreExpandedState(self) -> None:
"""Expand all nodes that were previously expanded."""
if model := self._getModel():
self.blockSignals(True)
for index in model.allExpanded():
self.setExpanded(index, True)
self.blockSignals(False)
return
def setSelectedHandle(self, tHandle: str | None, doScroll: bool = False) -> None:
"""Set a specific handle as the selected item."""
if (model := self._getModel()) and (index := model.indexFromHandle(tHandle)).isValid():
@@ -655,6 +661,87 @@ class GuiProjectTree(QTreeView):
self.projView.selectedItemChanged.emit(tHandle)
return
def newTreeItem(
self, itemType: nwItemType, itemClass: nwItemClass | None = None,
hLevel: int = 1, isNote: bool = False, copyDoc: str | None = None,
) -> None:
"""Add new item to the tree, with a given itemType (and
itemClass if Root), and attach it to the selected handle. Also
make sure the item is added in a place it can be added, and that
other meta data is set correctly to ensure a valid project tree.
"""
if not SHARED.hasProject:
logger.error("No project open")
return
tHandle = None
if itemType == nwItemType.ROOT and isinstance(itemClass, nwItemClass):
pos = -1
if (node := self._getNode(self.currentIndex())) and (itemRoot := node.item.itemRoot):
if root := SHARED.project.tree.nodes.get(itemRoot):
pos = root.row() + 1
SHARED.project.newRoot(itemClass, pos)
self.restoreExpandedState()
elif itemType in (nwItemType.FILE, nwItemType.FOLDER):
if not ((model := self._getModel()) and (node := model.node(self.currentIndex()))):
SHARED.error(self.tr("Did not find anywhere to add the file or folder!"))
return
if node.item.itemClass == nwItemClass.TRASH:
SHARED.error(self.tr("Cannot add new files or folders to the Trash folder."))
return
# Collect some information about the selected item
sLevel = nwStyles.H_LEVEL.get(node.item.mainHeading, 0)
sIsParent = node.childCount() > 0
# Set default label and determine if new item is to be added
# as child or sibling to the selected item
if itemType == nwItemType.FILE:
if copyDoc and (cItem := SHARED.project.tree[copyDoc]):
newLabel = cItem.itemName
asChild = sIsParent and node.item.isDocumentLayout()
elif isNote:
newLabel = self.tr("New Note")
asChild = sIsParent
elif hLevel == 2:
newLabel = self.tr("New Chapter")
asChild = sIsParent and node.item.isDocumentLayout() and sLevel < 2
elif hLevel == 3:
newLabel = self.tr("New Scene")
asChild = sIsParent and node.item.isDocumentLayout() and sLevel < 3
else:
newLabel = self.tr("New Document")
asChild = sIsParent and node.item.isDocumentLayout()
else:
newLabel = self.tr("New Folder")
asChild = False
pos = -1
sHandle = None
if not (asChild or node.item.isFolderType() or node.item.isRootType()):
pos = node.row() + 1
sHandle = node.item.itemParent
sHandle = sHandle or node.item.itemHandle
newLabel, dlgOk = GuiEditLabel.getLabel(self, text=newLabel)
if dlgOk:
# Add the file or folder
if itemType == nwItemType.FILE:
tHandle = SHARED.project.newFile(newLabel, sHandle, pos)
if tHandle and copyDoc:
SHARED.project.copyFileContent(tHandle, copyDoc)
elif tHandle and hLevel > 0:
SHARED.project.writeNewFile(tHandle, hLevel, not isNote)
else:
tHandle = SHARED.project.newFolder(newLabel, sHandle, pos)
return
##
# Events
##
@@ -736,14 +823,14 @@ class GuiProjectTree(QTreeView):
##
@pyqtSlot(QModelIndex)
def _treeSingleClick(self, index: QModelIndex) -> None:
def _onSingleClick(self, index: QModelIndex) -> None:
"""The user changed which item is selected."""
if node := self._getNode(index):
self.projView.selectedItemChanged.emit(node.item.itemHandle)
return
@pyqtSlot(QModelIndex)
def _treeDoubleClick(self, index: QModelIndex) -> None:
def _onDoubleClick(self, index: QModelIndex) -> None:
"""Capture a double-click event and either request the document
for editing if it is a file, or expand/close the node if not.
"""
@@ -789,109 +876,6 @@ class GuiProjectTree(QTreeView):
# self.revealNewTreeItem(tHandle, wordCount=True)
return
def newTreeItem(self, itemType: nwItemType, itemClass: nwItemClass | None = None,
hLevel: int = 1, isNote: bool = False, copyDoc: str | None = None) -> bool:
"""Add new item to the tree, with a given itemType (and
itemClass if Root), and attach it to the selected handle. Also
make sure the item is added in a place it can be added, and that
other meta data is set correctly to ensure a valid project tree.
"""
# if not SHARED.hasProject:
# logger.error("No project open")
# return False
# nHandle = None
# tHandle = None
# if itemType == nwItemType.ROOT and isinstance(itemClass, nwItemClass):
# tHandle = SHARED.project.newRoot(itemClass)
# sHandle = self.getSelectedHandle()
# pItem = SHARED.project.tree[sHandle] if sHandle else None
# nHandle = pItem.itemRoot if pItem else None
# elif itemType in (nwItemType.FILE, nwItemType.FOLDER):
# sHandle = self.getSelectedHandle()
# pItem = SHARED.project.tree[sHandle] if sHandle else None
# if sHandle is None or pItem is None:
# SHARED.error(self.tr("Did not find anywhere to add the file or folder!"))
# return False
# # Collect some information about the selected item
# qItem = self._getTreeItem(sHandle)
# sLevel = nwStyles.H_LEVEL.get(pItem.mainHeading, 0)
# sIsParent = False if qItem is None else qItem.childCount() > 0
# if SHARED.project.tree.isTrash(sHandle):
# SHARED.error(self.tr("Cannot add new files or folders to the Trash folder."))
# return False
# # Set default label and determine if new item is to be added
# # as child or sibling to the selected item
# if itemType == nwItemType.FILE:
# if copyDoc and (cItem := SHARED.project.tree[copyDoc]):
# newLabel = cItem.itemName
# asChild = sIsParent and pItem.isDocumentLayout()
# elif isNote:
# newLabel = self.tr("New Note")
# asChild = sIsParent
# elif hLevel == 2:
# newLabel = self.tr("New Chapter")
# asChild = sIsParent and pItem.isDocumentLayout() and sLevel < 2
# elif hLevel == 3:
# newLabel = self.tr("New Scene")
# asChild = sIsParent and pItem.isDocumentLayout() and sLevel < 3
# else:
# newLabel = self.tr("New Document")
# asChild = sIsParent and pItem.isDocumentLayout()
# else:
# newLabel = self.tr("New Folder")
# asChild = False
# if not (asChild or pItem.isFolderType() or pItem.isRootType()):
# # Move to the parent item so that the new item is added
# # as a sibling instead
# nHandle = sHandle
# sHandle = pItem.itemParent
# if sHandle is None:
# # Bug: We have a condition that is unhandled
# logger.error("Internal error")
# return False
# # Ask for label
# newLabel, dlgOk = GuiEditLabel.getLabel(self, text=newLabel)
# if not dlgOk:
# logger.info("New item creation cancelled by user")
# return False
# # Add the file or folder
# if itemType == nwItemType.FILE:
# tHandle = SHARED.project.newFile(newLabel, sHandle)
# else:
# tHandle = SHARED.project.newFolder(newLabel, sHandle)
# else:
# logger.error("Failed to add new item")
# return False
# # If there is no handle set, return here. This is a bug.
# if tHandle is None: # pragma: no cover
# logger.error("Internal error")
# return True
# # Handle new file creation
# if itemType == nwItemType.FILE and copyDoc:
# SHARED.project.copyFileContent(tHandle, copyDoc)
# elif itemType == nwItemType.FILE and hLevel > 0:
# SHARED.project.writeNewFile(tHandle, hLevel, not isNote)
# # Add the new item to the project tree
# self.revealNewTreeItem(tHandle, nHandle=nHandle, wordCount=True)
# self.projView.setTreeFocus() # See issue #1376
return True
def revealNewTreeItem(self, tHandle: str | None, nHandle: str | None = None,
wordCount: bool = False) -> bool:
"""Reveal a newly added project item in the project tree."""