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:
committed by
GitHub
parent
af3d0d2eb0
commit
6ac9e1aec4
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user