Tighten up the item class (#937)

* Protect the attributes of the NWItem class
* Fix test coverage
* Add a type checker function to the tree class
This commit is contained in:
Veronica Berglyd Olsen
2021-12-31 16:25:20 +01:00
committed by GitHub
parent af3d0d2eb0
commit 6ac9e1aec4
14 changed files with 255 additions and 183 deletions
+1 -5
View File
@@ -107,11 +107,7 @@ class NWIndex():
project. project.
""" """
logger.debug("Re-indexing item '%s'", tHandle) logger.debug("Re-indexing item '%s'", tHandle)
if not self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
tItem = self.theProject.projTree[tHandle]
if tItem is None:
return False
if tItem.itemType != nwItemType.FILE:
return False return False
theDoc = NWDoc(self.theProject, tHandle) theDoc = NWDoc(self.theProject, tHandle)
+135 -65
View File
@@ -42,26 +42,96 @@ class NWItem():
self.theProject = theProject self.theProject = theProject
self.itemName = "" self._name = ""
self.itemHandle = None self._handle = None
self.itemParent = None self._parent = None
self.itemOrder = 0 self._order = 0
self.itemType = nwItemType.NO_TYPE self._type = nwItemType.NO_TYPE
self.itemClass = nwItemClass.NO_CLASS self._class = nwItemClass.NO_CLASS
self.itemLayout = nwItemLayout.NO_LAYOUT self._layout = nwItemLayout.NO_LAYOUT
self.itemStatus = None self._status = None
self.isExpanded = False self._expanded = False
self.isExported = True self._exported = True
# Document Meta Data # Document Meta Data
self.charCount = 0 # Current character count self._charCount = 0 # Current character count
self.wordCount = 0 # Current word count self._wordCount = 0 # Current word count
self.paraCount = 0 # Current paragraph count self._paraCount = 0 # Current paragraph count
self.initCount = 0 # Initial word count self._cursorPos = 0 # Last cursor position
self.cursorPos = 0 # Last cursor position self._initCount = 0 # Initial word count
return return
def __repr__(self):
return f"<NWItem handle={self._handle}, parent={self._parent}, name='{self._name}'>"
def __bool__(self):
return self._handle is not None
##
# Properties
##
@property
def itemName(self):
return self._name
@property
def itemHandle(self):
return self._handle
@property
def itemParent(self):
return self._parent
@property
def itemOrder(self):
return self._order
@property
def itemType(self):
return self._type
@property
def itemClass(self):
return self._class
@property
def itemLayout(self):
return self._layout
@property
def itemStatus(self):
return self._status
@property
def isExpanded(self):
return self._expanded
@property
def isExported(self):
return self._exported
@property
def charCount(self):
return self._charCount
@property
def wordCount(self):
return self._wordCount
@property
def paraCount(self):
return self._paraCount
@property
def initCount(self):
return self._initCount
@property
def cursorPos(self):
return self._cursorPos
## ##
# XML Pack/Unpack # XML Pack/Unpack
## ##
@@ -70,23 +140,23 @@ class NWItem():
"""Pack all the data in the class instance into an XML object. """Pack all the data in the class instance into an XML object.
""" """
xPack = etree.SubElement(xParent, "item", attrib={ xPack = etree.SubElement(xParent, "item", attrib={
"handle": str(self.itemHandle), "handle": str(self._handle),
"order": str(self.itemOrder), "order": str(self._order),
"parent": str(self.itemParent), "parent": str(self._parent),
}) })
self._subPack(xPack, "name", text=str(self.itemName)) self._subPack(xPack, "name", text=str(self._name))
self._subPack(xPack, "type", text=str(self.itemType.name)) self._subPack(xPack, "type", text=str(self._type.name))
self._subPack(xPack, "class", text=str(self.itemClass.name)) self._subPack(xPack, "class", text=str(self._class.name))
self._subPack(xPack, "status", text=str(self.itemStatus)) self._subPack(xPack, "status", text=str(self._status))
if self.itemType == nwItemType.FILE: if self._type == nwItemType.FILE:
self._subPack(xPack, "exported", text=str(self.isExported)) self._subPack(xPack, "exported", text=str(self._exported))
self._subPack(xPack, "layout", text=str(self.itemLayout.name)) self._subPack(xPack, "layout", text=str(self._layout.name))
self._subPack(xPack, "charCount", text=str(self.charCount), none=False) self._subPack(xPack, "charCount", text=str(self._charCount), none=False)
self._subPack(xPack, "wordCount", text=str(self.wordCount), none=False) self._subPack(xPack, "wordCount", text=str(self._wordCount), none=False)
self._subPack(xPack, "paraCount", text=str(self.paraCount), none=False) self._subPack(xPack, "paraCount", text=str(self._paraCount), none=False)
self._subPack(xPack, "cursorPos", text=str(self.cursorPos), none=False) self._subPack(xPack, "cursorPos", text=str(self._cursorPos), none=False)
else: else:
self._subPack(xPack, "expanded", text=str(self.isExpanded)) self._subPack(xPack, "expanded", text=str(self._expanded))
return return
@@ -162,12 +232,12 @@ class NWItem():
"""Return a string description of the item. """Return a string description of the item.
""" """
descKey = "none" descKey = "none"
if self.itemType == nwItemType.ROOT: if self._type == nwItemType.ROOT:
descKey = "root" descKey = "root"
elif self.itemType == nwItemType.FOLDER: elif self._type == nwItemType.FOLDER:
descKey = "folder" descKey = "folder"
elif self.itemType == nwItemType.FILE: elif self._type == nwItemType.FILE:
if self.itemLayout == nwItemLayout.DOCUMENT: if self._layout == nwItemLayout.DOCUMENT:
if hLevel == "H1": if hLevel == "H1":
descKey = "doc_h1" descKey = "doc_h1"
elif hLevel == "H2": elif hLevel == "H2":
@@ -176,7 +246,7 @@ class NWItem():
descKey = "doc_h3" descKey = "doc_h3"
else: else:
descKey = "document" descKey = "document"
elif self.itemLayout == nwItemLayout.NOTE: elif self._layout == nwItemLayout.NOTE:
descKey = "note" descKey = "note"
return trConst(nwLabels.ITEM_DESCRIPTION.get(descKey, "")) return trConst(nwLabels.ITEM_DESCRIPTION.get(descKey, ""))
@@ -189,29 +259,29 @@ class NWItem():
"""Set the item name. """Set the item name.
""" """
if isinstance(theName, str): if isinstance(theName, str):
self.itemName = theName.strip() self._name = theName.strip()
else: else:
self.itemName = "" self._name = ""
return return
def setHandle(self, theHandle): def setHandle(self, theHandle):
"""Set the item handle, and ensure it is valid. """Set the item handle, and ensure it is valid.
""" """
if isHandle(theHandle): if isHandle(theHandle):
self.itemHandle = theHandle self._handle = theHandle
else: else:
self.itemHandle = None self._handle = None
return return
def setParent(self, theParent): def setParent(self, theParent):
"""Set the parent handle, and ensure it is valid. """Set the parent handle, and ensure it is valid.
""" """
if theParent is None: if theParent is None:
self.itemParent = None self._parent = None
elif isHandle(theParent): elif isHandle(theParent):
self.itemParent = theParent self._parent = theParent
else: else:
self.itemParent = None self._parent = None
return return
def setOrder(self, theOrder): def setOrder(self, theOrder):
@@ -219,7 +289,7 @@ class NWItem():
is purely a meta value, and not actually used by novelWriter at is purely a meta value, and not actually used by novelWriter at
the moment. the moment.
""" """
self.itemOrder = checkInt(theOrder, 0) self._order = checkInt(theOrder, 0)
return return
def setType(self, theType): def setType(self, theType):
@@ -227,12 +297,12 @@ class NWItem():
from a string representing an nwItemType. from a string representing an nwItemType.
""" """
if isinstance(theType, nwItemType): if isinstance(theType, nwItemType):
self.itemType = theType self._type = theType
elif isItemType(theType): elif isItemType(theType):
self.itemType = nwItemType[theType] self._type = nwItemType[theType]
else: else:
logger.error("Unrecognised item type '%s'", theType) logger.error("Unrecognised item type '%s'", theType)
self.itemType = nwItemType.NO_TYPE self._type = nwItemType.NO_TYPE
return return
def setClass(self, theClass): def setClass(self, theClass):
@@ -240,12 +310,12 @@ class NWItem():
it from a string representing an nwItemClass. it from a string representing an nwItemClass.
""" """
if isinstance(theClass, nwItemClass): if isinstance(theClass, nwItemClass):
self.itemClass = theClass self._class = theClass
elif isItemClass(theClass): elif isItemClass(theClass):
self.itemClass = nwItemClass[theClass] self._class = nwItemClass[theClass]
else: else:
logger.error("Unrecognised item class '%s'", theClass) logger.error("Unrecognised item class '%s'", theClass)
self.itemClass = nwItemClass.NO_CLASS self._class = nwItemClass.NO_CLASS
return return
def setLayout(self, theLayout): def setLayout(self, theLayout):
@@ -253,42 +323,42 @@ class NWItem():
it from a string representing an nwItemLayout. it from a string representing an nwItemLayout.
""" """
if isinstance(theLayout, nwItemLayout): if isinstance(theLayout, nwItemLayout):
self.itemLayout = theLayout self._layout = theLayout
elif isItemLayout(theLayout): elif isItemLayout(theLayout):
self.itemLayout = nwItemLayout[theLayout] self._layout = nwItemLayout[theLayout]
elif theLayout in nwLists.DEP_LAYOUT: elif theLayout in nwLists.DEP_LAYOUT:
self.itemLayout = nwItemLayout.DOCUMENT self._layout = nwItemLayout.DOCUMENT
else: else:
logger.error("Unrecognised item layout '%s'", theLayout) logger.error("Unrecognised item layout '%s'", theLayout)
self.itemLayout = nwItemLayout.NO_LAYOUT self._layout = nwItemLayout.NO_LAYOUT
return return
def setStatus(self, theStatus): def setStatus(self, theStatus):
"""Set the item status by looking it up in the valid status """Set the item status by looking it up in the valid status
items of the current project. items of the current project.
""" """
if self.itemClass in nwLists.CLS_NOVEL: if self._class in nwLists.CLS_NOVEL:
self.itemStatus = self.theProject.statusItems.checkEntry(theStatus) self._status = self.theProject.statusItems.checkEntry(theStatus)
else: else:
self.itemStatus = self.theProject.importItems.checkEntry(theStatus) self._status = self.theProject.importItems.checkEntry(theStatus)
return return
def setExpanded(self, expState): def setExpanded(self, expState):
"""Set the expanded status of an item in the project tree. """Set the expanded status of an item in the project tree.
""" """
if isinstance(expState, str): if isinstance(expState, str):
self.isExpanded = (expState == str(True)) self._expanded = (expState == str(True))
else: else:
self.isExpanded = (expState is True) self._expanded = (expState is True)
return return
def setExported(self, expState): def setExported(self, expState):
"""Set the export flag. """Set the export flag.
""" """
if isinstance(expState, str): if isinstance(expState, str):
self.isExported = (expState == str(True)) self._exported = (expState == str(True))
else: else:
self.isExported = (expState is True) self._exported = (expState is True)
return return
## ##
@@ -298,31 +368,31 @@ class NWItem():
def setCharCount(self, theCount): def setCharCount(self, theCount):
"""Set the character count, and ensure that it is an integer. """Set the character count, and ensure that it is an integer.
""" """
self.charCount = max(0, checkInt(theCount, 0)) self._charCount = max(0, checkInt(theCount, 0))
return return
def setWordCount(self, theCount): def setWordCount(self, theCount):
"""Set the word count, and ensure that it is an integer. """Set the word count, and ensure that it is an integer.
""" """
self.wordCount = max(0, checkInt(theCount, 0)) self._wordCount = max(0, checkInt(theCount, 0))
return return
def setParaCount(self, theCount): def setParaCount(self, theCount):
"""Set the paragraph count, and ensure that it is an integer. """Set the paragraph count, and ensure that it is an integer.
""" """
self.paraCount = max(0, checkInt(theCount, 0)) self._paraCount = max(0, checkInt(theCount, 0))
return return
def setCursorPos(self, thePosition): def setCursorPos(self, thePosition):
"""Set the cursor position, and ensure that it is an integer. """Set the cursor position, and ensure that it is an integer.
""" """
self.cursorPos = max(0, checkInt(thePosition, 0)) self._cursorPos = max(0, checkInt(thePosition, 0))
return return
def saveInitialCount(self): def saveInitialCount(self):
"""Save the initial word count. """Save the initial word count.
""" """
self.initCount = self.wordCount self._initCount = self._wordCount
return return
# END Class NWItem # END Class NWItem
+1 -1
View File
@@ -1166,7 +1166,7 @@ class NWProject():
nMax = min(len(iterItems), 10000) nMax = min(len(iterItems), 10000)
while n < nMax: while n < nMax:
tHandle = iterItems[n] tHandle = iterItems[n]
tItem = self.projTree[tHandle] tItem = self.projTree[tHandle]
n += 1 n += 1
if tItem is None: if tItem is None:
# Technically a bug since treeOrder is built from the # Technically a bug since treeOrder is built from the
+3 -6
View File
@@ -270,11 +270,7 @@ class Tokenizer():
def addRootHeading(self, theHandle): def addRootHeading(self, theHandle):
"""Add a heading at the start of a new root folder. """Add a heading at the start of a new root folder.
""" """
theItem = self.theProject.projTree[theHandle] if not self.theProject.projTree.checkType(theHandle, nwItemType.ROOT):
if theItem is None:
return False
if theItem.itemType != nwItemType.ROOT:
return False return False
if self._isFirst: if self._isFirst:
@@ -283,6 +279,7 @@ class Tokenizer():
else: else:
textAlign = self.A_PBB | self.A_CENTRE textAlign = self.A_PBB | self.A_CENTRE
theItem = self.theProject.projTree[theHandle]
locNotes = self._localLookup("Notes") locNotes = self._localLookup("Notes")
theTitle = f"{locNotes}: {theItem.itemName}" theTitle = f"{locNotes}: {theItem.itemName}"
self._theTokens = [] self._theTokens = []
@@ -299,7 +296,7 @@ class Tokenizer():
not set, load it from the file. not set, load it from the file.
""" """
self._theHandle = theHandle self._theHandle = theHandle
self._theItem = self.theProject.projTree[theHandle] self._theItem = self.theProject.projTree[theHandle]
if self._theItem is None: if self._theItem is None:
return False return False
+8
View File
@@ -210,6 +210,14 @@ class NWTree():
# Tree Structure Methods # Tree Structure Methods
## ##
def checkType(self, tHandle, itemType):
"""Return true of item exists and is of the specified item type.
"""
tItem = self.__getitem__(tHandle)
if not tItem:
return False
return tItem.itemType == itemType
def trashRoot(self): def trashRoot(self):
"""Returns the handle of the trash folder, or None if there """Returns the handle of the trash folder, or None if there
isn't one. isn't one.
+1 -5
View File
@@ -159,14 +159,10 @@ class GuiDocViewer(QTextBrowser):
def loadText(self, tHandle, updateHistory=True): def loadText(self, tHandle, updateHistory=True):
"""Load text into the viewer from an item handle. """Load text into the viewer from an item handle.
""" """
tItem = self.theProject.projTree[tHandle] if not self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
if tItem is None:
logger.warning("Item not found") logger.warning("Item not found")
return False return False
if tItem.itemType != nwItemType.FILE:
return False
logger.debug("Generating preview for item '%s'", tHandle) logger.debug("Generating preview for item '%s'", tHandle)
qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
+2 -6
View File
@@ -1051,16 +1051,12 @@ class GuiProjectTree(QTreeWidget):
def _emitItemChange(self, tHandle): def _emitItemChange(self, tHandle):
"""Emit an item change signal for a given handle. """Emit an item change signal for a given handle.
""" """
nwItem = self.theProject.projTree[tHandle] if self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
if nwItem is None: nwItem = self.theProject.projTree[tHandle]
return
if nwItem.itemType == nwItemType.FILE:
if nwItem.itemClass == nwItemClass.NOVEL: if nwItem.itemClass == nwItemClass.NOVEL:
self.novelItemChanged.emit() self.novelItemChanged.emit()
else: else:
self.noteItemChanged.emit() self.noteItemChanged.emit()
return return
def _recordLastMove(self, srcItem, parItem, parIndex): def _recordLastMove(self, srcItem, parItem, parIndex):
+10 -21
View File
@@ -623,9 +623,7 @@ class GuiMain(QMainWindow):
fHandle = None # The first file handle we encounter fHandle = None # The first file handle we encounter
foundIt = False # We've found tHandle, pick the next we see foundIt = False # We've found tHandle, pick the next we see
for tItem in self.theProject.projTree: for tItem in self.theProject.projTree:
if tItem is None: if not self.theProject.projTree.checkType(tItem.itemHandle, nwItemType.FILE):
continue
if tItem.itemType != nwItemType.FILE:
continue continue
if fHandle is None: if fHandle is None:
fHandle = tItem.itemHandle fHandle = tItem.itemHandle
@@ -812,9 +810,7 @@ class GuiMain(QMainWindow):
return False return False
logger.verbose("Opening item '%s'", tHandle) logger.verbose("Opening item '%s'", tHandle)
nwItem = self.theProject.projTree[tHandle] if self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
if nwItem.itemType == nwItemType.FILE:
logger.verbose("Requested item '%s' is a file", tHandle)
self.openDocument(tHandle, doScroll=False) self.openDocument(tHandle, doScroll=False)
else: else:
logger.verbose("Requested item '%s' is not a file", tHandle) logger.verbose("Requested item '%s' is not a file", tHandle)
@@ -1572,13 +1568,10 @@ class GuiMain(QMainWindow):
tHandle = tItem.data(self.treeView.C_NAME, Qt.UserRole) tHandle = tItem.data(self.treeView.C_NAME, Qt.UserRole)
logger.verbose("User double clicked tree item with handle '%s'", tHandle) logger.verbose("User double clicked tree item with handle '%s'", tHandle)
nwItem = self.theProject.projTree[tHandle] if self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
if nwItem is not None: self.openDocument(tHandle, changeFocus=False, doScroll=False)
if nwItem.itemType == nwItemType.FILE: else:
logger.verbose("Requested item '%s' is a file", tHandle) logger.verbose("Requested item '%s' is a folder", tHandle)
self.openDocument(tHandle, changeFocus=False, doScroll=False)
else:
logger.verbose("Requested item '%s' is a folder", tHandle)
return return
@@ -1603,14 +1596,10 @@ class GuiMain(QMainWindow):
""" """
tHandle = self.treeView.getSelectedHandle() tHandle = self.treeView.getSelectedHandle()
logger.verbose("User pressed return on tree item with handle '%s'", tHandle) logger.verbose("User pressed return on tree item with handle '%s'", tHandle)
if self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
nwItem = self.theProject.projTree[tHandle] self.openDocument(tHandle, changeFocus=False, doScroll=False)
if nwItem is not None: else:
if nwItem.itemType == nwItemType.FILE: logger.verbose("Requested item '%s' is a folder", tHandle)
logger.verbose("Requested item '%s' is a file", tHandle)
self.openDocument(tHandle, changeFocus=False, doScroll=False)
else:
logger.verbose("Requested item '%s' is a folder", tHandle)
return return
+2 -2
View File
@@ -433,7 +433,7 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI):
# Page wo/Title # Page wo/Title
# ============= # =============
theProject.projTree[pHandle].itemLayout = nwItemLayout.DOCUMENT theProject.projTree[pHandle]._layout = nwItemLayout.DOCUMENT
assert theIndex.scanText(pHandle, ( assert theIndex.scanText(pHandle, (
"This is a page with some text on it.\n\n" "This is a page with some text on it.\n\n"
)) ))
@@ -446,7 +446,7 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI):
assert theIndex._fileIndex[pHandle]["T000000"]["pCount"] == 1 assert theIndex._fileIndex[pHandle]["T000000"]["pCount"] == 1
assert theIndex._fileIndex[pHandle]["T000000"]["synopsis"] == "" assert theIndex._fileIndex[pHandle]["T000000"]["synopsis"] == ""
theProject.projTree[pHandle].itemLayout = nwItemLayout.NOTE theProject.projTree[pHandle]._layout = nwItemLayout.NOTE
assert theIndex.scanText(pHandle, ( assert theIndex.scanText(pHandle, (
"This is a page with some text on it.\n\n" "This is a page with some text on it.\n\n"
)) ))
+28 -13
View File
@@ -86,7 +86,7 @@ def testCoreItem_Setters(mockGUI):
assert theItem.itemStatus == "Main" assert theItem.itemStatus == "Main"
# Status # Status
theItem.itemClass = nwItemClass.NOVEL theItem._class = nwItemClass.NOVEL
theItem.setStatus("Nonsense") theItem.setStatus("Nonsense")
assert theItem.itemStatus == "New" assert theItem.itemStatus == "New"
theItem.setStatus("New") theItem.setStatus("New")
@@ -100,31 +100,31 @@ def testCoreItem_Setters(mockGUI):
# Expanded # Expanded
theItem.setExpanded(8) theItem.setExpanded(8)
assert not theItem.isExpanded assert theItem.isExpanded is False
theItem.setExpanded(None) theItem.setExpanded(None)
assert not theItem.isExpanded assert theItem.isExpanded is False
theItem.setExpanded("None") theItem.setExpanded("None")
assert not theItem.isExpanded assert theItem.isExpanded is False
theItem.setExpanded("What?") theItem.setExpanded("What?")
assert not theItem.isExpanded assert theItem.isExpanded is False
theItem.setExpanded("True") theItem.setExpanded("True")
assert theItem.isExpanded assert theItem.isExpanded is True
theItem.setExpanded(True) theItem.setExpanded(True)
assert theItem.isExpanded assert theItem.isExpanded is True
# Exported # Exported
theItem.setExported(8) theItem.setExported(8)
assert not theItem.isExported assert theItem.isExported is False
theItem.setExported(None) theItem.setExported(None)
assert not theItem.isExported assert theItem.isExported is False
theItem.setExported("None") theItem.setExported("None")
assert not theItem.isExported assert theItem.isExported is False
theItem.setExported("What?") theItem.setExported("What?")
assert not theItem.isExported assert theItem.isExported is False
theItem.setExported("True") theItem.setExported("True")
assert theItem.isExported assert theItem.isExported is True
theItem.setExported(True) theItem.setExported(True)
assert theItem.isExported assert theItem.isExported is True
# CharCount # CharCount
theItem.setCharCount(None) theItem.setCharCount(None)
@@ -196,6 +196,21 @@ def testCoreItem_Methods(mockGUI):
theItem.setLayout("NOTE") theItem.setLayout("NOTE")
assert theItem.describeMe() == "Project Note" assert theItem.describeMe() == "Project Note"
# Representation
# ==============
theItem.setName("New Item")
theItem.setHandle("1234567890abc")
theItem.setParent("4567890abcdef")
assert repr(theItem) == "<NWItem handle=1234567890abc, parent=4567890abcdef, name='New Item'>"
# Truthiness
# ==========
assert bool(theItem) is True
theItem.setHandle(None)
assert bool(theItem) is False
# END Test testCoreItem_Methods # END Test testCoreItem_Methods
+56 -51
View File
@@ -39,61 +39,61 @@ def mockItems(mockGUI):
theProject = NWProject(mockGUI) theProject = NWProject(mockGUI)
itemA = NWItem(theProject) itemA = NWItem(theProject)
itemA.itemName = "Novel" itemA._name = "Novel"
itemA.itemType = nwItemType.ROOT itemA._type = nwItemType.ROOT
itemA.itemClass = nwItemClass.NOVEL itemA._class = nwItemClass.NOVEL
itemA.isExpanded = True itemA._expanded = True
itemB = NWItem(theProject) itemB = NWItem(theProject)
itemB.itemName = "Act One" itemB._name = "Act One"
itemB.itemType = nwItemType.FOLDER itemB._type = nwItemType.FOLDER
itemB.itemClass = nwItemClass.NOVEL itemB._class = nwItemClass.NOVEL
itemB.isExpanded = True itemB._expanded = True
itemC = NWItem(theProject) itemC = NWItem(theProject)
itemC.itemName = "Chapter One" itemC._name = "Chapter One"
itemC.itemType = nwItemType.FILE itemC._type = nwItemType.FILE
itemC.itemClass = nwItemClass.NOVEL itemC._class = nwItemClass.NOVEL
itemC.itemLayout = nwItemLayout.DOCUMENT itemC._layout = nwItemLayout.DOCUMENT
itemC.charCount = 300 itemC._charCount = 300
itemC.wordCount = 50 itemC._wordCount = 50
itemC.paraCount = 2 itemC._paraCount = 2
itemD = NWItem(theProject) itemD = NWItem(theProject)
itemD.itemName = "Scene One" itemD._name = "Scene One"
itemD.itemType = nwItemType.FILE itemD._type = nwItemType.FILE
itemD.itemClass = nwItemClass.NOVEL itemD._class = nwItemClass.NOVEL
itemD.itemLayout = nwItemLayout.DOCUMENT itemD._layout = nwItemLayout.DOCUMENT
itemD.charCount = 3000 itemD._charCount = 3000
itemD.wordCount = 500 itemD._wordCount = 500
itemD.paraCount = 20 itemD._paraCount = 20
itemE = NWItem(theProject) itemE = NWItem(theProject)
itemE.itemName = "Outtakes" itemE._name = "Outtakes"
itemE.itemType = nwItemType.ROOT itemE._type = nwItemType.ROOT
itemE.itemClass = nwItemClass.ARCHIVE itemE._class = nwItemClass.ARCHIVE
itemE.isExpanded = False itemE._expanded = False
itemF = NWItem(theProject) itemF = NWItem(theProject)
itemF.itemName = "Trash" itemF._name = "Trash"
itemF.itemType = nwItemType.TRASH itemF._type = nwItemType.TRASH
itemF.itemClass = nwItemClass.TRASH itemF._class = nwItemClass.TRASH
itemF.isExpanded = False itemF._expanded = False
itemG = NWItem(theProject) itemG = NWItem(theProject)
itemG.itemName = "Characters" itemG._name = "Characters"
itemG.itemType = nwItemType.ROOT itemG._type = nwItemType.ROOT
itemG.itemClass = nwItemClass.CHARACTER itemG._class = nwItemClass.CHARACTER
itemG.isExpanded = True itemG._expanded = True
itemH = NWItem(theProject) itemH = NWItem(theProject)
itemH.itemName = "Jane Doe" itemH._name = "Jane Doe"
itemH.itemType = nwItemType.FILE itemH._type = nwItemType.FILE
itemH.itemClass = nwItemClass.CHARACTER itemH._class = nwItemClass.CHARACTER
itemH.itemLayout = nwItemLayout.NOTE itemH._layout = nwItemLayout.NOTE
itemH.charCount = 2000 itemH._charCount = 2000
itemH.wordCount = 400 itemH._wordCount = 400
itemH.paraCount = 16 itemH._paraCount = 16
theItems = [ theItems = [
("a000000000001", None, itemA), ("a000000000001", None, itemA),
@@ -154,20 +154,20 @@ def testCoreTree_BuildTree(mockGUI, mockItems):
# Try to add another trash folder # Try to add another trash folder
itemT = NWItem(theProject) itemT = NWItem(theProject)
itemT.itemName = "Trash" itemT._name = "Trash"
itemT.itemType = nwItemType.TRASH itemT._type = nwItemType.TRASH
itemT.itemClass = nwItemClass.TRASH itemT._class = nwItemClass.TRASH
itemT.isExpanded = False itemT._expanded = False
assert not theTree.append("1234567890abc", None, itemT) assert not theTree.append("1234567890abc", None, itemT)
assert len(theTree) == len(mockItems) assert len(theTree) == len(mockItems)
# Generate handle automatically # Generate handle automatically
itemT = NWItem(theProject) itemT = NWItem(theProject)
itemT.itemName = "New File" itemT._name = "New File"
itemT.itemType = nwItemType.FILE itemT._type = nwItemType.FILE
itemT.itemClass = nwItemClass.NOVEL itemT._class = nwItemClass.NOVEL
itemT.itemLayout = nwItemLayout.DOCUMENT itemT._layout = nwItemLayout.DOCUMENT
assert theTree.append(None, None, itemT) assert theTree.append(None, None, itemT)
assert len(theTree) == len(mockItems) + 1 assert len(theTree) == len(mockItems) + 1
@@ -218,6 +218,11 @@ def testCoreTree_Methods(mockGUI, mockItems):
assert len(theTree) == len(mockItems) assert len(theTree) == len(mockItems)
# Chech type
assert theTree.checkType("blabla", nwItemType.FILE) is False
assert theTree.checkType("b000000000001", nwItemType.FILE) is False
assert theTree.checkType("c000000000001", nwItemType.FILE) is True
# Root item lookup # Root item lookup
theTree._treeRoots.append("stuff") theTree._treeRoots.append("stuff")
assert theTree.findRoot(nwItemClass.WORLD) is None assert theTree.findRoot(nwItemClass.WORLD) is None
@@ -243,12 +248,12 @@ def testCoreTree_Methods(mockGUI, mockItems):
] ]
# Break the folder parent handle # Break the folder parent handle
theTree["b000000000001"].itemParent = "stuff" theTree["b000000000001"]._parent = "stuff"
assert theTree.getItemPath("c000000000001") == [ assert theTree.getItemPath("c000000000001") == [
"c000000000001", "b000000000001" "c000000000001", "b000000000001"
] ]
theTree["b000000000001"].itemParent = "a000000000001" theTree["b000000000001"]._parent = "a000000000001"
assert theTree.getItemPath("c000000000001") == [ assert theTree.getItemPath("c000000000001") == [
"c000000000001", "b000000000001", "a000000000001" "c000000000001", "b000000000001", "a000000000001"
] ]
+2 -2
View File
@@ -62,9 +62,9 @@ def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncProj):
assert nwGUI.editItem() is False assert nwGUI.editItem() is False
# Invalid Type # Invalid Type
nwGUI.theProject.projTree["0e17daca5f3e1"].itemType = nwItemType.NO_TYPE nwGUI.theProject.projTree["0e17daca5f3e1"]._type = nwItemType.NO_TYPE
assert nwGUI.editItem() is False assert nwGUI.editItem() is False
nwGUI.theProject.projTree["0e17daca5f3e1"].itemType = nwItemType.FILE nwGUI.theProject.projTree["0e17daca5f3e1"]._type = nwItemType.FILE
# Open Properly # Open Properly
assert nwGUI.editItem() is True assert nwGUI.editItem() is True
+5 -5
View File
@@ -1225,8 +1225,8 @@ def testGuiEditor_WordCounters(qtbot, monkeypatch, caplog, nwGUI, nwMinimal, ips
# Open a document and populate it # Open a document and populate it
sHandle = "8c659a11cd429" sHandle = "8c659a11cd429"
nwGUI.theProject.projTree[sHandle].initCount = 0 # Clear item's count nwGUI.theProject.projTree[sHandle]._initCount = 0 # Clear item's count
nwGUI.theProject.projTree[sHandle].wordCount = 0 # Clear item's count nwGUI.theProject.projTree[sHandle]._wordCount = 0 # Clear item's count
assert nwGUI.openDocument(sHandle) is True assert nwGUI.openDocument(sHandle) is True
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
@@ -1252,9 +1252,9 @@ def testGuiEditor_WordCounters(qtbot, monkeypatch, caplog, nwGUI, nwMinimal, ips
nwGUI.docEditor.wCounterDoc.run() nwGUI.docEditor.wCounterDoc.run()
# nwGUI.docEditor._updateDocCounts(cC, wC, pC) # nwGUI.docEditor._updateDocCounts(cC, wC, pC)
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
assert nwGUI.theProject.projTree[sHandle].charCount == cC assert nwGUI.theProject.projTree[sHandle]._charCount == cC
assert nwGUI.theProject.projTree[sHandle].wordCount == wC assert nwGUI.theProject.projTree[sHandle]._wordCount == wC
assert nwGUI.theProject.projTree[sHandle].paraCount == pC assert nwGUI.theProject.projTree[sHandle]._paraCount == pC
assert nwGUI.docEditor.docFooter.wordsText.text() == f"Words: {wC} (+{wC})" assert nwGUI.docEditor.docFooter.wordsText.text() == f"Words: {wC} (+{wC})"
# Select all text # Select all text
+1 -1
View File
@@ -223,7 +223,7 @@ def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
# Add new file after one that has no parent handle # Add new file after one that has no parent handle
chItem = nwTree._getTreeItem("44cb730c42048") chItem = nwTree._getTreeItem("44cb730c42048")
nwTree.setCurrentItem(chItem, QItemSelectionModel.Current) nwTree.setCurrentItem(chItem, QItemSelectionModel.Current)
nwTree.theProject.projTree["44cb730c42048"].itemParent = None nwTree.theProject.projTree["44cb730c42048"]._parent = None
assert not nwTree.newTreeItem(nwItemType.FILE, nwItemClass.NOVEL) assert not nwTree.newTreeItem(nwItemType.FILE, nwItemClass.NOVEL)
nwTree.clearSelection() nwTree.clearSelection()