Remove max folder depth restriction, and simplify adding folders and files in the tree
This commit is contained in:
@@ -42,7 +42,6 @@ class nwConst():
|
|||||||
FMT_DSTAMP = "%Y-%m-%d" # Date only format
|
FMT_DSTAMP = "%Y-%m-%d" # Date only format
|
||||||
|
|
||||||
# Various Hard Limits
|
# Various Hard Limits
|
||||||
MAX_DEPTH = 30 # Maximum folder depth of a project
|
|
||||||
MAX_DOCSIZE = 5000000 # Maxium size of a single document
|
MAX_DOCSIZE = 5000000 # Maxium size of a single document
|
||||||
MAX_BUILDSIZE = 10000000 # Maxium size of a project build
|
MAX_BUILDSIZE = 10000000 # Maxium size of a project build
|
||||||
|
|
||||||
|
|||||||
@@ -308,7 +308,9 @@ class NWItem():
|
|||||||
"""Set the default values based on the item's class and the
|
"""Set the default values based on the item's class and the
|
||||||
project settings.
|
project settings.
|
||||||
"""
|
"""
|
||||||
self.setClass(itemClass)
|
if self._parent is not None:
|
||||||
|
# Only update for child items
|
||||||
|
self.setClass(itemClass)
|
||||||
|
|
||||||
if self._class in nwLists.CLS_NOVEL:
|
if self._class in nwLists.CLS_NOVEL:
|
||||||
self._layout = nwItemLayout.DOCUMENT
|
self._layout = nwItemLayout.DOCUMENT
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ from hashlib import sha256
|
|||||||
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout
|
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout
|
||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
from novelwriter.common import checkHandle
|
from novelwriter.common import checkHandle
|
||||||
from novelwriter.constants import nwConst, nwFiles
|
from novelwriter.constants import nwFiles
|
||||||
from novelwriter.core.item import NWItem
|
from novelwriter.core.item import NWItem
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -41,6 +41,8 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class NWTree():
|
class NWTree():
|
||||||
|
|
||||||
|
MAX_DEPTH = 1000 # Cap of tree traversing for loops
|
||||||
|
|
||||||
def __init__(self, theProject):
|
def __init__(self, theProject):
|
||||||
|
|
||||||
self.theProject = theProject
|
self.theProject = theProject
|
||||||
@@ -219,7 +221,7 @@ class NWTree():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
iItem = tItem
|
iItem = tItem
|
||||||
for _ in range(nwConst.MAX_DEPTH + 1):
|
for _ in range(self.MAX_DEPTH):
|
||||||
if iItem.itemParent is None:
|
if iItem.itemParent is None:
|
||||||
tItem.setRoot(iItem.itemHandle)
|
tItem.setRoot(iItem.itemHandle)
|
||||||
tItem.setClassDefaults(iItem.itemClass)
|
tItem.setClassDefaults(iItem.itemClass)
|
||||||
@@ -228,8 +230,8 @@ class NWTree():
|
|||||||
iItem = self.__getitem__(iItem.itemParent)
|
iItem = self.__getitem__(iItem.itemParent)
|
||||||
if iItem is None:
|
if iItem is None:
|
||||||
return False
|
return False
|
||||||
|
else:
|
||||||
return False
|
raise RecursionError("Critical internal error")
|
||||||
|
|
||||||
def checkType(self, tHandle, itemType):
|
def checkType(self, tHandle, itemType):
|
||||||
"""Return true of item exists and is of the specified item type.
|
"""Return true of item exists and is of the specified item type.
|
||||||
@@ -249,7 +251,7 @@ class NWTree():
|
|||||||
tItem = self.__getitem__(tHandle)
|
tItem = self.__getitem__(tHandle)
|
||||||
if tItem is not None:
|
if tItem is not None:
|
||||||
tTree.append(tHandle)
|
tTree.append(tHandle)
|
||||||
for _ in range(nwConst.MAX_DEPTH + 1):
|
for _ in range(self.MAX_DEPTH):
|
||||||
if tItem.itemParent is None:
|
if tItem.itemParent is None:
|
||||||
return tTree
|
return tTree
|
||||||
else:
|
else:
|
||||||
@@ -259,6 +261,9 @@ class NWTree():
|
|||||||
return tTree
|
return tTree
|
||||||
else:
|
else:
|
||||||
tTree.append(tHandle)
|
tTree.append(tHandle)
|
||||||
|
else:
|
||||||
|
raise RecursionError("Critical internal error")
|
||||||
|
|
||||||
return tTree
|
return tTree
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -270,6 +275,23 @@ class NWTree():
|
|||||||
"""
|
"""
|
||||||
return tHandle in self._treeRoots
|
return tHandle in self._treeRoots
|
||||||
|
|
||||||
|
def isTrash(self, tHandle):
|
||||||
|
"""Check if an item is in or is the trash folder.
|
||||||
|
"""
|
||||||
|
tItem = self.__getitem__(tHandle)
|
||||||
|
if tItem is None:
|
||||||
|
return True
|
||||||
|
if tItem.itemClass == nwItemClass.TRASH:
|
||||||
|
return True
|
||||||
|
if self._trashRoot is not None:
|
||||||
|
if tHandle == self._trashRoot:
|
||||||
|
return True
|
||||||
|
elif tItem.itemParent == self._trashRoot:
|
||||||
|
return True
|
||||||
|
elif tItem.itemRoot == self._trashRoot:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def isTrashRoot(self, tHandle):
|
def isTrashRoot(self, tHandle):
|
||||||
"""Check if a handle is the trash folder.
|
"""Check if a handle is the trash folder.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ from PyQt5.QtWidgets import (
|
|||||||
|
|
||||||
from novelwriter.core import NWDoc
|
from novelwriter.core import NWDoc
|
||||||
from novelwriter.enum import nwAlert, nwItemType
|
from novelwriter.enum import nwAlert, nwItemType
|
||||||
from novelwriter.constants import nwConst
|
|
||||||
from novelwriter.gui.custom import QHelpLabel
|
from novelwriter.gui.custom import QHelpLabel
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -160,16 +159,6 @@ class GuiDocSplit(QDialog):
|
|||||||
), nwAlert.ERROR)
|
), nwAlert.ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check that another folder can be created
|
|
||||||
parTree = self.theProject.projTree.getItemPath(srcItem.itemParent)
|
|
||||||
if len(parTree) >= nwConst.MAX_DEPTH - 1:
|
|
||||||
self.theParent.makeAlert(self.tr(
|
|
||||||
"Cannot add new folder for the document split. "
|
|
||||||
"Maximum folder depth has been reached. "
|
|
||||||
"Please move the file to another level in the project tree."
|
|
||||||
), nwAlert.ERROR)
|
|
||||||
return False
|
|
||||||
|
|
||||||
msgYes = self.theParent.askQuestion(
|
msgYes = self.theParent.askQuestion(
|
||||||
self.tr("Split Document"),
|
self.tr("Split Document"),
|
||||||
"{0}<br><br>{1}".format(
|
"{0}<br><br>{1}".format(
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ class GuiMainMenu(QMenuBar):
|
|||||||
# Project > New Folder
|
# Project > New Folder
|
||||||
self.aCreateFolder = QAction(self.tr("Create Folder"), self)
|
self.aCreateFolder = QAction(self.tr("Create Folder"), self)
|
||||||
self.aCreateFolder.setShortcut("Ctrl+Shift+N")
|
self.aCreateFolder.setShortcut("Ctrl+Shift+N")
|
||||||
self.aCreateFolder.triggered.connect(lambda: self._newTreeItem(nwItemType.FOLDER, None))
|
self.aCreateFolder.triggered.connect(lambda: self._newTreeItem(nwItemType.FOLDER))
|
||||||
self.projMenu.addAction(self.aCreateFolder)
|
self.projMenu.addAction(self.aCreateFolder)
|
||||||
|
|
||||||
# Project > Separator
|
# Project > Separator
|
||||||
@@ -259,7 +259,7 @@ class GuiMainMenu(QMenuBar):
|
|||||||
# Document > New
|
# Document > New
|
||||||
self.aNewDoc = QAction(self.tr("New Document"), self)
|
self.aNewDoc = QAction(self.tr("New Document"), self)
|
||||||
self.aNewDoc.setShortcut("Ctrl+N")
|
self.aNewDoc.setShortcut("Ctrl+N")
|
||||||
self.aNewDoc.triggered.connect(lambda: self._newTreeItem(nwItemType.FILE, None))
|
self.aNewDoc.triggered.connect(lambda: self._newTreeItem(nwItemType.FILE))
|
||||||
self.docuMenu.addAction(self.aNewDoc)
|
self.docuMenu.addAction(self.aNewDoc)
|
||||||
|
|
||||||
# Document > Open
|
# Document > Open
|
||||||
|
|||||||
+37
-90
@@ -37,7 +37,7 @@ from PyQt5.QtWidgets import (
|
|||||||
|
|
||||||
from novelwriter.core import NWDoc
|
from novelwriter.core import NWDoc
|
||||||
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
|
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
|
||||||
from novelwriter.constants import nwConst, trConst, nwLists, nwLabels
|
from novelwriter.constants import trConst, nwLists, nwLabels
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -161,114 +161,64 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
self._timeChanged = 0
|
self._timeChanged = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
def newTreeItem(self, itemType, itemClass):
|
def newTreeItem(self, itemType, itemClass=None):
|
||||||
"""Add new item to the tree, with a given itemType and
|
"""Add new item to the tree, with a given itemType (and
|
||||||
itemClass, and attach it to the selected handle. Also make sure
|
itemClass if Root), and attach it to the selected handle. Also make
|
||||||
the item is added in a place it can be added, and that other
|
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.
|
meta data is set correctly to ensure a valid project tree.
|
||||||
"""
|
"""
|
||||||
pHandle = self.getSelectedHandle()
|
|
||||||
nHandle = None
|
|
||||||
|
|
||||||
if not self.theParent.hasProject:
|
if not self.theParent.hasProject:
|
||||||
logger.error("No project open")
|
logger.error("No project open")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not isinstance(itemType, nwItemType):
|
nHandle = None
|
||||||
# This would indicate an internal bug
|
tHandle = None
|
||||||
logger.error("No itemType provided")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# The item needs to be assigned an item class, so one must be
|
if itemType == nwItemType.ROOT and isinstance(itemClass, nwItemClass):
|
||||||
# provided, or it must be possible to extract it from the parent
|
|
||||||
# item of the new item.
|
|
||||||
if itemClass is None and pHandle is not None:
|
|
||||||
pItem = self.theProject.projTree[pHandle]
|
|
||||||
if pItem is not None:
|
|
||||||
itemClass = pItem.itemClass
|
|
||||||
|
|
||||||
# If class is still not set, alert the user and exit
|
|
||||||
if itemClass is None:
|
|
||||||
if itemType == nwItemType.FILE:
|
|
||||||
self.theParent.makeAlert(self.tr(
|
|
||||||
"Please select a valid location in the tree to add the document."
|
|
||||||
), nwAlert.ERROR)
|
|
||||||
else:
|
|
||||||
self.theParent.makeAlert(self.tr(
|
|
||||||
"Please select a valid location in the tree to add the folder."
|
|
||||||
), nwAlert.ERROR)
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Everything is fine, we have what we need, so we proceed
|
|
||||||
logger.verbose(
|
|
||||||
"Adding new item of type '%s' and class '%s' to handle '%s'",
|
|
||||||
itemType.name, itemClass.name, str(pHandle)
|
|
||||||
)
|
|
||||||
|
|
||||||
if itemType == nwItemType.ROOT:
|
|
||||||
tHandle = self.theProject.newRoot(
|
tHandle = self.theProject.newRoot(
|
||||||
trConst(nwLabels.CLASS_NAME[itemClass]), itemClass
|
trConst(nwLabels.CLASS_NAME[itemClass]), itemClass
|
||||||
)
|
)
|
||||||
if tHandle is None:
|
|
||||||
logger.error("No root item added")
|
|
||||||
return False
|
|
||||||
|
|
||||||
else:
|
elif itemType in (nwItemType.FILE, nwItemType.FOLDER):
|
||||||
# If no parent has been selected, make the new file under
|
|
||||||
# the root NOVEL item.
|
|
||||||
if pHandle is None:
|
|
||||||
pHandle = self.theProject.projTree.findRoot(nwItemClass.NOVEL)
|
|
||||||
|
|
||||||
# If still nothing, give up
|
sHandle = self.getSelectedHandle()
|
||||||
if pHandle is None:
|
if sHandle is None or sHandle not in self.theProject.projTree:
|
||||||
self.theParent.makeAlert(self.tr(
|
self.theParent.makeAlert(self.tr(
|
||||||
"Did not find anywhere to add the file or folder!"
|
"Did not find anywhere to add the file or folder!"
|
||||||
), nwAlert.ERROR)
|
), nwAlert.ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Now check if the selected item is a file, in which case
|
# If the selected item is a file, the new item will be a sibling
|
||||||
# the new file will be a sibling
|
pItem = self.theProject.projTree[sHandle]
|
||||||
pItem = self.theProject.projTree[pHandle]
|
|
||||||
if pItem.itemType == nwItemType.FILE:
|
if pItem.itemType == nwItemType.FILE:
|
||||||
nHandle = pHandle
|
nHandle = sHandle
|
||||||
pHandle = pItem.itemParent
|
sHandle = pItem.itemParent
|
||||||
|
if sHandle is None:
|
||||||
|
logger.error("Internal error") # Bug
|
||||||
|
return False
|
||||||
|
|
||||||
# If we again have no home, give up
|
if self.theProject.projTree.isTrash(sHandle):
|
||||||
if pHandle is None:
|
|
||||||
self.theParent.makeAlert(self.tr(
|
|
||||||
"Did not find anywhere to add the file or folder!"
|
|
||||||
), nwAlert.ERROR)
|
|
||||||
return False
|
|
||||||
|
|
||||||
if self.theProject.projTree.isTrashRoot(pHandle):
|
|
||||||
self.theParent.makeAlert(self.tr(
|
self.theParent.makeAlert(self.tr(
|
||||||
"Cannot add new files or folders to the Trash folder."
|
"Cannot add new files or folders to the Trash folder."
|
||||||
), nwAlert.ERROR)
|
), nwAlert.ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
parTree = self.theProject.projTree.getItemPath(pHandle)
|
# Add the file or folder
|
||||||
|
|
||||||
# If we're still here, add the file or folder
|
|
||||||
if itemType == nwItemType.FILE:
|
if itemType == nwItemType.FILE:
|
||||||
tHandle = self.theProject.newFile(self.tr("New File"), pHandle)
|
if pItem.itemClass in nwLists.CLS_NOVEL:
|
||||||
|
tHandle = self.theProject.newFile(self.tr("New Document"), sHandle)
|
||||||
|
else:
|
||||||
|
tHandle = self.theProject.newFile(self.tr("New Note"), sHandle)
|
||||||
elif itemType == nwItemType.FOLDER:
|
elif itemType == nwItemType.FOLDER:
|
||||||
if len(parTree) >= nwConst.MAX_DEPTH - 1:
|
tHandle = self.theProject.newFolder(self.tr("New Folder"), sHandle)
|
||||||
# Folders cannot be deeper than MAX_DEPTH - 1, leaving room
|
|
||||||
# for one more level of files.
|
|
||||||
self.theParent.makeAlert(self.tr(
|
|
||||||
"Cannot add new folder to this item. "
|
|
||||||
"Maximum folder depth has been reached."
|
|
||||||
), nwAlert.ERROR)
|
|
||||||
return False
|
|
||||||
tHandle = self.theProject.newFolder(self.tr("New Folder"), pHandle)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error("Failed to add new item")
|
logger.error("Failed to add new item")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# If there is no handle set, return here
|
# If there is no handle set, return here. This is a bug
|
||||||
if tHandle is None:
|
if tHandle is None: # pragma: no cover
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Add the new item to the tree
|
# Add the new item to the tree
|
||||||
@@ -282,11 +232,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
|
|
||||||
# This is a new file, so let's add some content
|
# This is a new file, so let's add some content
|
||||||
newDoc = NWDoc(self.theProject, tHandle)
|
newDoc = NWDoc(self.theProject, tHandle)
|
||||||
curTxt = newDoc.readDocument()
|
if not newDoc.readDocument():
|
||||||
if curTxt is None:
|
|
||||||
curTxt = ""
|
|
||||||
|
|
||||||
if curTxt == "":
|
|
||||||
if nwItem.itemLayout == nwItemLayout.DOCUMENT:
|
if nwItem.itemLayout == nwItemLayout.DOCUMENT:
|
||||||
newText = f"### {nwItem.itemName}\n\n"
|
newText = f"### {nwItem.itemName}\n\n"
|
||||||
else:
|
else:
|
||||||
@@ -633,7 +579,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def propagateCount(self, tHandle, theCount, nDepth=0):
|
def propagateCount(self, tHandle, theCount):
|
||||||
"""Recursive function setting the word count for a given item,
|
"""Recursive function setting the word count for a given item,
|
||||||
and propagating that count upwards in the tree until reaching a
|
and propagating that count upwards in the tree until reaching a
|
||||||
root item. This function is more efficient than recalculating
|
root item. This function is more efficient than recalculating
|
||||||
@@ -653,12 +599,13 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
pCount = 0
|
pCount = 0
|
||||||
|
pHandle = None
|
||||||
for i in range(pItem.childCount()):
|
for i in range(pItem.childCount()):
|
||||||
pCount += int(pItem.child(i).data(self.C_COUNT, Qt.UserRole))
|
pCount += int(pItem.child(i).data(self.C_COUNT, Qt.UserRole))
|
||||||
pHandle = pItem.data(self.C_NAME, Qt.UserRole)
|
pHandle = pItem.data(self.C_NAME, Qt.UserRole)
|
||||||
|
|
||||||
if not nDepth > nwConst.MAX_DEPTH + 1 and pHandle != "":
|
if pHandle:
|
||||||
self.propagateCount(pHandle, pCount, nDepth+1)
|
self.propagateCount(pHandle, pCount)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1180,7 +1127,7 @@ class GuiProjectTreeMenu(QMenu):
|
|||||||
"""Forward the new file call to the project tree.
|
"""Forward the new file call to the project tree.
|
||||||
"""
|
"""
|
||||||
if self.theItem is not None:
|
if self.theItem is not None:
|
||||||
self.theTree.newTreeItem(nwItemType.FILE, None)
|
self.theTree.newTreeItem(nwItemType.FILE)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@@ -1188,7 +1135,7 @@ class GuiProjectTreeMenu(QMenu):
|
|||||||
"""Forward the new folder call to the project tree.
|
"""Forward the new folder call to the project tree.
|
||||||
"""
|
"""
|
||||||
if self.theItem is not None:
|
if self.theItem is not None:
|
||||||
self.theTree.newTreeItem(nwItemType.FOLDER, None)
|
self.theTree.newTreeItem(nwItemType.FOLDER)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
%%~name: New File
|
%%~name: New Note
|
||||||
%%~path: 44cb730c42048/031b4af5197ec
|
%%~path: 44cb730c42048/031b4af5197ec
|
||||||
%%~kind: PLOT/NOTE
|
%%~kind: PLOT/NOTE
|
||||||
# Main Plot
|
# Main Plot
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
%%~name: New File
|
%%~name: New Note
|
||||||
%%~path: 71ee45a3c0db9/1a6562590ef19
|
%%~path: 71ee45a3c0db9/1a6562590ef19
|
||||||
%%~kind: CHARACTER/NOTE
|
%%~kind: CHARACTER/NOTE
|
||||||
# Jane Doe
|
# Jane Doe
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
%%~name: New File
|
%%~name: New Note
|
||||||
%%~path: 811786ad1ae74/41cfc0d1f2d12
|
%%~path: 811786ad1ae74/41cfc0d1f2d12
|
||||||
%%~kind: WORLD/NOTE
|
%%~kind: WORLD/NOTE
|
||||||
# Main Location
|
# Main Location
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="1.7-alpha0" hexVersion="0x010700a0" fileVersion="1.4" timeStamp="2022-04-16 20:52:26">
|
<novelWriterXML appVersion="1.7-alpha0" hexVersion="0x010700a0" fileVersion="1.4" timeStamp="2022-04-17 14:18:28">
|
||||||
<project>
|
<project>
|
||||||
<name>New Project</name>
|
<name>New Project</name>
|
||||||
<title></title>
|
<title></title>
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
</item>
|
</item>
|
||||||
<item handle="031b4af5197ec" parent="44cb730c42048" root="44cb730c42048" order="0" type="FILE" class="PLOT" layout="NOTE">
|
<item handle="031b4af5197ec" parent="44cb730c42048" root="44cb730c42048" order="0" type="FILE" class="PLOT" layout="NOTE">
|
||||||
<meta charCount="48" wordCount="10" paraCount="1" cursorPos="69"/>
|
<meta charCount="48" wordCount="10" paraCount="1" cursorPos="69"/>
|
||||||
<name status="sa3b179" import="i466852" exported="True">New File</name>
|
<name status="sa3b179" import="i466852" exported="True">New Note</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="71ee45a3c0db9" parent="None" root="71ee45a3c0db9" order="2" type="ROOT" class="CHARACTER">
|
<item handle="71ee45a3c0db9" parent="None" root="71ee45a3c0db9" order="2" type="ROOT" class="CHARACTER">
|
||||||
<meta expanded="True"/>
|
<meta expanded="True"/>
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
</item>
|
</item>
|
||||||
<item handle="1a6562590ef19" parent="71ee45a3c0db9" root="71ee45a3c0db9" order="0" type="FILE" class="CHARACTER" layout="NOTE">
|
<item handle="1a6562590ef19" parent="71ee45a3c0db9" root="71ee45a3c0db9" order="0" type="FILE" class="CHARACTER" layout="NOTE">
|
||||||
<meta charCount="34" wordCount="8" paraCount="1" cursorPos="51"/>
|
<meta charCount="34" wordCount="8" paraCount="1" cursorPos="51"/>
|
||||||
<name status="sa3b179" import="i466852" exported="True">New File</name>
|
<name status="sa3b179" import="i466852" exported="True">New Note</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="811786ad1ae74" parent="None" root="811786ad1ae74" order="3" type="ROOT" class="WORLD">
|
<item handle="811786ad1ae74" parent="None" root="811786ad1ae74" order="3" type="ROOT" class="WORLD">
|
||||||
<meta expanded="True"/>
|
<meta expanded="True"/>
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
</item>
|
</item>
|
||||||
<item handle="41cfc0d1f2d12" parent="811786ad1ae74" root="811786ad1ae74" order="0" type="FILE" class="WORLD" layout="NOTE">
|
<item handle="41cfc0d1f2d12" parent="811786ad1ae74" root="811786ad1ae74" order="0" type="FILE" class="WORLD" layout="NOTE">
|
||||||
<meta charCount="51" wordCount="9" paraCount="1" cursorPos="68"/>
|
<meta charCount="51" wordCount="9" paraCount="1" cursorPos="68"/>
|
||||||
<name status="sa3b179" import="i466852" exported="True">New File</name>
|
<name status="sa3b179" import="i466852" exported="True">New Note</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="2fca346db6561" parent="None" root="2fca346db6561" order="4" type="TRASH" class="TRASH">
|
<item handle="2fca346db6561" parent="None" root="2fca346db6561" order="4" type="TRASH" class="TRASH">
|
||||||
<meta expanded="True"/>
|
<meta expanded="True"/>
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ def testCoreTree_BuildTree(mockGUI, mockItems):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreTree_Methods(monkeypatch, mockGUI, mockItems):
|
def testCoreTree_Methods(mockGUI, mockItems):
|
||||||
"""Test various class methods.
|
"""Test various class methods.
|
||||||
"""
|
"""
|
||||||
theProject = NWProject(mockGUI)
|
theProject = NWProject(mockGUI)
|
||||||
@@ -235,9 +235,11 @@ def testCoreTree_Methods(monkeypatch, mockGUI, mockItems):
|
|||||||
assert theTree.updateItemData("b000000000001") is True
|
assert theTree.updateItemData("b000000000001") is True
|
||||||
|
|
||||||
# Update item data, root is unreachable
|
# Update item data, root is unreachable
|
||||||
with monkeypatch.context() as mp:
|
maxDepth = theTree.MAX_DEPTH
|
||||||
mp.setattr("novelwriter.constants.nwConst.MAX_DEPTH", 0)
|
theTree.MAX_DEPTH = 0
|
||||||
assert theTree.updateItemData("b000000000001") is False
|
with pytest.raises(RecursionError):
|
||||||
|
theTree.updateItemData("b000000000001")
|
||||||
|
theTree.MAX_DEPTH = maxDepth
|
||||||
|
|
||||||
# Chech type
|
# Chech type
|
||||||
assert theTree.checkType("blabla", nwItemType.FILE) is False
|
assert theTree.checkType("blabla", nwItemType.FILE) is False
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncProj):
|
|||||||
nwGUI.switchFocus(nwWidget.TREE)
|
nwGUI.switchFocus(nwWidget.TREE)
|
||||||
nwGUI.treeView.clearSelection()
|
nwGUI.treeView.clearSelection()
|
||||||
nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True)
|
nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True)
|
||||||
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
|
nwGUI.treeView.newTreeItem(nwItemType.FILE)
|
||||||
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
|
nwGUI.treeView.newTreeItem(nwItemType.FILE)
|
||||||
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
|
nwGUI.treeView.newTreeItem(nwItemType.FILE)
|
||||||
|
|
||||||
assert nwGUI.saveProject() is True
|
assert nwGUI.saveProject() is True
|
||||||
assert nwGUI.closeProject() is True
|
assert nwGUI.closeProject() is True
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj):
|
|||||||
nwGUI.switchFocus(nwWidget.TREE)
|
nwGUI.switchFocus(nwWidget.TREE)
|
||||||
nwGUI.treeView.clearSelection()
|
nwGUI.treeView.clearSelection()
|
||||||
nwGUI.treeView._getTreeItem(hNovelRoot).setSelected(True)
|
nwGUI.treeView._getTreeItem(hNovelRoot).setSelected(True)
|
||||||
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
|
nwGUI.treeView.newTreeItem(nwItemType.FILE)
|
||||||
|
|
||||||
assert nwGUI.saveProject() is True
|
assert nwGUI.saveProject() is True
|
||||||
assert nwGUI.closeProject() is True
|
assert nwGUI.closeProject() is True
|
||||||
@@ -230,12 +230,6 @@ def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj):
|
|||||||
mp.setattr(QMessageBox, "question", lambda *a: QMessageBox.No)
|
mp.setattr(QMessageBox, "question", lambda *a: QMessageBox.No)
|
||||||
assert nwSplit._doSplit() is False
|
assert nwSplit._doSplit() is False
|
||||||
|
|
||||||
# Block folder creation by returning that the folder has a depth
|
|
||||||
# of 50 items in the tree
|
|
||||||
with monkeypatch.context() as mp:
|
|
||||||
mp.setattr(NWTree, "getItemPath", lambda *a: [""]*50)
|
|
||||||
assert nwSplit._doSplit() is False
|
|
||||||
|
|
||||||
# Clear the list
|
# Clear the list
|
||||||
nwSplit.listBox.clear()
|
nwSplit.listBox.clear()
|
||||||
assert nwSplit._doSplit() is False
|
assert nwSplit._doSplit() is False
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ def testDlgItemEditor_Note(qtbot, monkeypatch, nwGUI, fncProj, constData):
|
|||||||
itemEdit.show()
|
itemEdit.show()
|
||||||
|
|
||||||
# Check Existing Settings
|
# Check Existing Settings
|
||||||
assert itemEdit.editName.text() == "New File"
|
assert itemEdit.editName.text() == "New Note"
|
||||||
assert itemEdit.editStatus.currentData() == constData.importKeys[0]
|
assert itemEdit.editStatus.currentData() == constData.importKeys[0]
|
||||||
assert itemEdit.editLayout.currentData() == nwItemLayout.NOTE
|
assert itemEdit.editLayout.currentData() == nwItemLayout.NOTE
|
||||||
assert itemEdit.editExport.isChecked() is True
|
assert itemEdit.editExport.isChecked() is True
|
||||||
|
|||||||
Reference in New Issue
Block a user