Merge pull request #478 from vkbo/code_cleanup

Code Cleanup and Improvements
This commit is contained in:
Veronica K. Berglyd Olsen
2020-10-15 22:57:32 +02:00
committed by GitHub
24 changed files with 148 additions and 120 deletions
+2 -2
View File
@@ -25,5 +25,5 @@ jobs:
flake8 tests --count --select=E9,F63,F7,F82 --show-source --statistics flake8 tests --count --select=E9,F63,F7,F82 --show-source --statistics
- name: Coding Style Violations - name: Coding Style Violations
run: | run: |
flake8 nw --count --max-line-length=99 --ignore E203,E221,E226,E241,E251,E261,E266,E302,E305 --show-source --statistics flake8 nw --count --max-line-length=99 --ignore E203,E221,E226,E228,E241,E251,E261,E266,E302,E305 --show-source --statistics
flake8 tests --count --max-line-length=99 --ignore E203,E221,E226,E241,E251,E261,E266,E302,E305 --show-source --statistics flake8 tests --count --max-line-length=99 --ignore E203,E221,E226,E228,E241,E251,E261,E266,E302,E305 --show-source --statistics
+9 -6
View File
@@ -67,7 +67,9 @@ class NWDoc():
def openDocument(self, tHandle, showStatus=True, isOrphan=False): def openDocument(self, tHandle, showStatus=True, isOrphan=False):
"""Open a document from handle, capturing potential file system """Open a document from handle, capturing potential file system
errors and parse meta data. errors and parse meta data. If the document doesn't exist on
disk, return an empty string. If something went wrong, return
None.
""" """
if not isHandle(tHandle): if not isHandle(tHandle):
return None return None
@@ -120,13 +122,13 @@ class NWDoc():
logger.verbose("DocMeta: '%s'" % self._docMeta) logger.verbose("DocMeta: '%s'" % self._docMeta)
if showStatus and not isOrphan: if showStatus and not isOrphan:
self.theParent.statusBar.setStatus("Opened Document: %s" % self._theItem.itemName) self.theParent.setStatus("Opened Document: %s" % self._theItem.itemName)
return theText return theText
def saveDocument(self, docText): def saveDocument(self, docText):
"""Save the document via temp file in case of save failure, and """Save the document. The file is saved via a temp file in case
in any case keep a backup of the file. of save failure. Returns True if successful, False if not.
""" """
if self._docHandle is None: if self._docHandle is None:
return False return False
@@ -139,6 +141,7 @@ class NWDoc():
docPath = os.path.join(self.theProject.projContent, docFile) docPath = os.path.join(self.theProject.projContent, docFile)
docTemp = os.path.join(self.theProject.projContent, docFile+"~") docTemp = os.path.join(self.theProject.projContent, docFile+"~")
# DocMeta line
if self._theItem is None: if self._theItem is None:
docMeta = "" docMeta = ""
else: else:
@@ -166,12 +169,12 @@ class NWDoc():
os.unlink(docPath) os.unlink(docPath)
os.rename(docTemp, docPath) os.rename(docTemp, docPath)
self.theParent.statusBar.setStatus("Saved Document: %s" % self._theItem.itemName) self.theParent.setStatus("Saved Document: %s" % self._theItem.itemName)
return True return True
def deleteDocument(self, tHandle): def deleteDocument(self, tHandle):
"""Permanently delete a document source file and its backups """Permanently delete a document source file and related files
from the project data folder. from the project data folder.
""" """
if not isHandle(tHandle): if not isHandle(tHandle):
+3 -3
View File
@@ -279,7 +279,7 @@ class NWIndex():
if theItem.itemLayout == nwItemLayout.NO_LAYOUT: if theItem.itemLayout == nwItemLayout.NO_LAYOUT:
logger.info("Not indexing no-layout item %s" % tHandle) logger.info("Not indexing no-layout item %s" % tHandle)
return False return False
if theItem.parHandle is None: if theItem.itemParent is None:
logger.info("Not indexing orphaned item %s" % tHandle) logger.info("Not indexing orphaned item %s" % tHandle)
return False return False
@@ -288,7 +288,7 @@ class NWIndex():
self.textCounts[tHandle] = [cC, wC, pC] self.textCounts[tHandle] = [cC, wC, pC]
# If the file is archived or trashed, we don't index the file itself # If the file is archived or trashed, we don't index the file itself
if self.theProject.projTree.isTrashRoot(theItem.parHandle): if self.theProject.projTree.isTrashRoot(theItem.itemParent):
logger.info("Not indexing trash item %s" % tHandle) logger.info("Not indexing trash item %s" % tHandle)
return False return False
if theRoot.itemClass == nwItemClass.ARCHIVE: if theRoot.itemClass == nwItemClass.ARCHIVE:
@@ -583,7 +583,7 @@ class NWIndex():
def getCounts(self, tHandle, sTitle=None): def getCounts(self, tHandle, sTitle=None):
"""Returns the counts for a file, or a section of a file """Returns the counts for a file, or a section of a file
starting at title nTitle. starting at title sTitle if it is provided.
""" """
cC = 0 cC = 0
wC = 0 wC = 0
+11 -8
View File
@@ -42,7 +42,7 @@ class NWItem():
self.itemName = "" self.itemName = ""
self.itemHandle = None self.itemHandle = None
self.parHandle = None self.itemParent = None
self.itemOrder = None self.itemOrder = None
self.itemType = nwItemType.NO_TYPE self.itemType = nwItemType.NO_TYPE
self.itemClass = nwItemClass.NO_CLASS self.itemClass = nwItemClass.NO_CLASS
@@ -70,7 +70,7 @@ class NWItem():
xPack = etree.SubElement(xParent, "item", attrib={ xPack = etree.SubElement(xParent, "item", attrib={
"handle" : str(self.itemHandle), "handle" : str(self.itemHandle),
"order" : str(self.itemOrder), "order" : str(self.itemOrder),
"parent" : str(self.parHandle), "parent" : str(self.itemParent),
}) })
self._subPack(xPack, "name", text=str(self.itemName)) self._subPack(xPack, "name", text=str(self.itemName))
self._subPack(xPack, "type", text=str(self.itemType.name)) self._subPack(xPack, "type", text=str(self.itemType.name))
@@ -85,6 +85,7 @@ class NWItem():
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.isExpanded))
return return
def unpackXML(self, xItem): def unpackXML(self, xItem):
@@ -101,7 +102,7 @@ class NWItem():
return False return False
if "parent" in xItem.attrib: if "parent" in xItem.attrib:
self.parHandle = xItem.attrib["parent"] self.itemParent = xItem.attrib["parent"]
setMap = { setMap = {
"name" : self.setName, "name" : self.setName,
@@ -131,9 +132,11 @@ class NWItem():
""" """
if not none and (text is None or text == "None"): if not none and (text is None or text == "None"):
return None return None
xSub = etree.SubElement(xParent, name, attrib=attrib) xAttr = {} if attrib is None else attrib
xSub = etree.SubElement(xParent, name, attrib=xAttr)
if text is not None: if text is not None:
xSub.text = text xSub.text = text
return return
## ##
@@ -162,14 +165,14 @@ class NWItem():
"""Set the parent handle, and ensure that it is valid. """Set the parent handle, and ensure that it is valid.
""" """
if theParent is None: if theParent is None:
self.parHandle = None self.itemParent = None
elif isinstance(theParent, str): elif isinstance(theParent, str):
if len(theParent) == 13: if len(theParent) == 13:
self.parHandle = theParent self.itemParent = theParent
else: else:
self.parHandle = None self.itemParent = None
else: else:
self.parHandle = None self.itemParent = None
return return
def setOrder(self, theOrder): def setOrder(self, theOrder):
+5 -5
View File
@@ -782,7 +782,7 @@ class NWProject():
"""Create a zip file of the entire project. """Create a zip file of the entire project.
""" """
logger.info("Backing up project") logger.info("Backing up project")
self.theParent.statusBar.setStatus("Backing up project ...") self.theParent.setStatus("Backing up project ...")
if self.mainConf.backupPath is None or self.mainConf.backupPath == "": if self.mainConf.backupPath is None or self.mainConf.backupPath == "":
self.theParent.makeAlert(( self.theParent.makeAlert((
@@ -847,7 +847,7 @@ class NWProject():
) )
return False return False
self.theParent.statusBar.setStatus("Project backed up to '%s.zip'" % baseName) self.theParent.setStatus("Project backed up to '%s.zip'" % baseName)
return True return True
@@ -1139,16 +1139,16 @@ class NWProject():
# Technically a bug since treeOrder is built from the # Technically a bug since treeOrder is built from the
# same data as projTree # same data as projTree
continue continue
elif tItem.parHandle is None: elif tItem.itemParent is None:
# Item is a root, or already been identified as an # Item is a root, or already been identified as an
# orphaned item # orphaned item
sentItems.append(tHandle) sentItems.append(tHandle)
yield tItem yield tItem
elif tItem.parHandle in sentItems: elif tItem.itemParent in sentItems:
# Item's parent has been sent, so all is fine # Item's parent has been sent, so all is fine
sentItems.append(tHandle) sentItems.append(tHandle)
yield tItem yield tItem
elif tItem.parHandle in iterItems: elif tItem.itemParent in iterItems:
# Item's parent exists, but hasn't been sent yet, so add # Item's parent exists, but hasn't been sent yet, so add
# it again to the end # it again to the end
logger.warning("Item %s found before its parent" % tHandle) logger.warning("Item %s found before its parent" % tHandle)
+1
View File
@@ -41,6 +41,7 @@ class ToHtml(Tokenizer):
def __init__(self, theProject, theParent): def __init__(self, theProject, theParent):
Tokenizer.__init__(self, theProject, theParent) Tokenizer.__init__(self, theProject, theParent)
self.genMode = self.M_EXPORT self.genMode = self.M_EXPORT
self.cssStyles = True self.cssStyles = True
+8 -9
View File
@@ -136,7 +136,6 @@ def numberToWord(numVal, theLanguage):
def _numberToWordEN(numVal): def _numberToWordEN(numVal):
"""Convert numbers to English words. """Convert numbers to English words.
""" """
numWord = ""
oneWord = "" oneWord = ""
tenWord = "" tenWord = ""
hunWord = "" hunWord = ""
@@ -145,8 +144,8 @@ def _numberToWordEN(numVal):
return "Zero" return "Zero"
oneVal = numVal % 10 oneVal = numVal % 10
tenVal = (numVal-oneVal) % 100 tenVal = (numVal - oneVal) % 100
hunVal = (numVal-tenVal-oneVal) % 1000 hunVal = (numVal - tenVal - oneVal) % 1000
theHundreds = { theHundreds = {
100: "One Hundred", 200: "Two Hundred", 300: "Three Hundred", 100: "One Hundred", 200: "Two Hundred", 300: "Three Hundred",
@@ -167,18 +166,18 @@ def _numberToWordEN(numVal):
} }
hunWord = theHundreds.get(hunVal, "") hunWord = theHundreds.get(hunVal, "")
tenWord = theTens.get(tenVal, "")
if tenVal == 10: if tenVal == 10:
oneWord = theTeens.get(oneVal, "") oneWord = theTeens.get(oneVal, "")
numWord = ("%s %s" % (hunWord, oneWord)).strip() return f"{hunWord} {oneWord}".strip()
else: else:
oneWord = theOnes.get(oneVal, "") oneWord = theOnes.get(oneVal, "")
if tenVal == 0: if tenVal == 0:
numWord = ("%s %s" % (hunWord, oneWord)).strip() return f"{hunWord} {oneWord}".strip()
else: else:
tenWord = theTens.get(tenVal, "")
if oneVal == 0: if oneVal == 0:
numWord = ("%s %s" % (hunWord, tenWord)).strip() return f"{hunWord} {tenWord}".strip()
else: else:
numWord = ("%s %s-%s" % (hunWord, tenWord, oneWord)).strip() return f"{hunWord} {tenWord}-{oneWord}".strip()
return numWord return ""
+5 -5
View File
@@ -134,7 +134,7 @@ class NWTree():
for xItem in xContent: for xItem in xContent:
nwItem = NWItem(self.theProject) nwItem = NWItem(self.theProject)
if nwItem.unpackXML(xItem): if nwItem.unpackXML(xItem):
self.append(nwItem.itemHandle, nwItem.parHandle, nwItem) self.append(nwItem.itemHandle, nwItem.itemParent, nwItem)
nwItem.saveInitialCount() nwItem.saveInitialCount()
return True return True
@@ -261,10 +261,10 @@ class NWTree():
tItem = self.__getitem__(tHandle) tItem = self.__getitem__(tHandle)
if tItem is not None: if tItem is not None:
for i in range(nwConst.maxDepth + 1): for i in range(nwConst.maxDepth + 1):
if tItem.parHandle is None: if tItem.itemParent is None:
return tItem return tItem
else: else:
tHandle = tItem.parHandle tHandle = tItem.itemParent
tItem = self.__getitem__(tHandle) tItem = self.__getitem__(tHandle)
return None return None
@@ -279,10 +279,10 @@ class NWTree():
if tItem is not None: if tItem is not None:
tTree.append(tHandle) tTree.append(tHandle)
for i in range(nwConst.maxDepth + 1): for i in range(nwConst.maxDepth + 1):
if tItem.parHandle is None: if tItem.itemParent is None:
return tTree return tTree
else: else:
tHandle = tItem.parHandle tHandle = tItem.itemParent
tItem = self.__getitem__(tHandle) tItem = self.__getitem__(tHandle)
if tItem is None: if tItem is None:
return tTree return tTree
-1
View File
@@ -222,7 +222,6 @@ class GuiAbout(QDialog):
hColB = self.theParent.theTheme.colHead[2], hColB = self.theParent.theTheme.colHead[2],
) )
self.pageAbout.document().setDefaultStyleSheet(styleSheet) self.pageAbout.document().setDefaultStyleSheet(styleSheet)
# self.pageCredit.document().setDefaultStyleSheet(styleSheet)
self.pageLicense.document().setDefaultStyleSheet(styleSheet) self.pageLicense.document().setDefaultStyleSheet(styleSheet)
return return
+2 -2
View File
@@ -684,8 +684,8 @@ class GuiBuildNovel(QDialog):
isNone |= theItem.itemLayout == nwItemLayout.NO_LAYOUT isNone |= theItem.itemLayout == nwItemLayout.NO_LAYOUT
isNone |= theItem.itemClass == nwItemClass.NO_CLASS isNone |= theItem.itemClass == nwItemClass.NO_CLASS
isNone |= theItem.itemClass == nwItemClass.TRASH isNone |= theItem.itemClass == nwItemClass.TRASH
isNone |= theItem.parHandle == self.theProject.projTree.trashRoot() isNone |= theItem.itemParent == self.theProject.projTree.trashRoot()
isNone |= theItem.parHandle is None isNone |= theItem.itemParent is None
isNote = theItem.itemLayout == nwItemLayout.NOTE isNote = theItem.itemLayout == nwItemLayout.NOTE
isNovel = not isNone and not isNote isNovel = not isNone and not isNote
+9 -10
View File
@@ -807,16 +807,16 @@ class GuiDocEditor(QTextEdit):
return self.docSearch.cycleFocus(toNext) return self.docSearch.cycleFocus(toNext)
return True return True
def mouseReleaseEvent(self, mEvent): def mouseReleaseEvent(self, theEvent):
"""If the mouse button is released and the control key is """If the mouse button is released and the control key is
pressed, check if we're clicking on a tag, and trigger the pressed, check if we're clicking on a tag, and trigger the
follow tag function. follow tag function.
""" """
if qApp.keyboardModifiers() == Qt.ControlModifier: if qApp.keyboardModifiers() == Qt.ControlModifier:
theCursor = self.cursorForPosition(mEvent.pos()) theCursor = self.cursorForPosition(theEvent.pos())
self._followTag(theCursor) self._followTag(theCursor)
QTextEdit.mouseReleaseEvent(self, mEvent) QTextEdit.mouseReleaseEvent(self, theEvent)
self.docFooter.updateLineCount() self.docFooter.updateLineCount()
return return
@@ -1203,20 +1203,19 @@ class GuiDocEditor(QTextEdit):
"""Check if document size crosses the big document limit set in """Check if document size crosses the big document limit set in
config. If so, we will set the big document flag to True. config. If so, we will set the big document flag to True.
""" """
newState = theSize > self.mainConf.bigDocLimit*1000 bigLim = self.mainConf.bigDocLimit*1000
newState = theSize > bigLim
if newState != self.bigDoc: if newState != self.bigDoc:
if newState: if newState:
logger.info( logger.info(
"The document size is {:n} > {:n}, big doc mode has been enabled".format( f"The document size is {theSize:n} > {bigLim:n}, "
theSize, self.mainConf.bigDocLimit*1000 f"big doc mode has been enabled"
)
) )
else: else:
logger.info( logger.info(
"The document size is {:n} <= {:n}, big doc mode has been disabled".format( f"The document size is {theSize:n} <= {bigLim:n}, "
theSize, self.mainConf.bigDocLimit*1000 f"big doc mode has been disabled"
)
) )
self.bigDoc = newState self.bigDoc = newState
+7 -3
View File
@@ -149,18 +149,22 @@ class GuiDocHighlighter(QSyntaxHighlighter):
# Quoted Strings # Quoted Strings
if self.mainConf.highlightQuotes: if self.mainConf.highlightQuotes:
fmtDO = self.mainConf.fmtDoubleQuotes[0]
fmtDC = self.mainConf.fmtDoubleQuotes[1]
fmtSO = self.mainConf.fmtSingleQuotes[0]
fmtSC = self.mainConf.fmtSingleQuotes[1]
self.hRules.append(( self.hRules.append((
"\\B{:s}(.*?){:s}\\B".format('"', '"'), { "\\B\"(.*?)\"\\B", {
0 : self.hStyles["dialogue1"], 0 : self.hStyles["dialogue1"],
} }
)) ))
self.hRules.append(( self.hRules.append((
"\\B{:s}(.*?){:s}\\B".format(*self.mainConf.fmtDoubleQuotes), { f"\\B{fmtDO:s}(.*?){fmtDC:s}\\B", {
0 : self.hStyles["dialogue2"], 0 : self.hStyles["dialogue2"],
} }
)) ))
self.hRules.append(( self.hRules.append((
"\\B{:s}(.*?){:s}\\B".format(*self.mainConf.fmtSingleQuotes), { f"\\B{fmtSO:s}(.*?){fmtSC:s}\\B", {
0 : self.hStyles["dialogue3"], 0 : self.hStyles["dialogue3"],
} }
)) ))
+1 -1
View File
@@ -127,7 +127,7 @@ class GuiDocMerge(QDialog):
), nwAlert.ERROR) ), nwAlert.ERROR)
return return
nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.parHandle) nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.itemParent)
newItem = self.theProject.projTree[nHandle] newItem = self.theProject.projTree[nHandle]
newItem.setStatus(srcItem.itemStatus) newItem.setStatus(srcItem.itemStatus)
+2 -2
View File
@@ -154,7 +154,7 @@ class GuiDocSplit(QDialog):
return return
# Check that another folder can be created # Check that another folder can be created
parTree = self.theProject.projTree.getItemPath(srcItem.parHandle) parTree = self.theProject.projTree.getItemPath(srcItem.itemParent)
if len(parTree) >= nwConst.maxDepth - 1: if len(parTree) >= nwConst.maxDepth - 1:
self.theParent.makeAlert(( self.theParent.makeAlert((
"Cannot add new folder for the document split. " "Cannot add new folder for the document split. "
@@ -176,7 +176,7 @@ class GuiDocSplit(QDialog):
# Create the folder # Create the folder
fHandle = self.theProject.newFolder( fHandle = self.theProject.newFolder(
srcItem.itemName, srcItem.itemClass, srcItem.parHandle srcItem.itemName, srcItem.itemClass, srcItem.itemParent
) )
self.theParent.treeView.revealNewTreeItem(fHandle) self.theParent.treeView.revealNewTreeItem(fHandle)
logger.verbose("Creating folder %s" % fHandle) logger.verbose("Creating folder %s" % fHandle)
+7 -3
View File
@@ -439,6 +439,10 @@ class GuiOutline(QTreeWidget):
newItem = QTreeWidgetItem() newItem = QTreeWidgetItem()
hIcon = "doc_%s" % tLevel.lower() hIcon = "doc_%s" % tLevel.lower()
cC = int(novIdx["cCount"])
wC = int(novIdx["wCount"])
pC = int(novIdx["pCount"])
newItem.setText(self.colIndex[nwOutline.TITLE], novIdx["title"]) newItem.setText(self.colIndex[nwOutline.TITLE], novIdx["title"])
newItem.setData(self.colIndex[nwOutline.TITLE], Qt.UserRole, tHandle) newItem.setData(self.colIndex[nwOutline.TITLE], Qt.UserRole, tHandle)
newItem.setIcon(self.colIndex[nwOutline.TITLE], self.theTheme.getIcon(hIcon)) newItem.setIcon(self.colIndex[nwOutline.TITLE], self.theTheme.getIcon(hIcon))
@@ -448,9 +452,9 @@ class GuiOutline(QTreeWidget):
newItem.setText(self.colIndex[nwOutline.LINE], sTitle[1:].lstrip("0")) newItem.setText(self.colIndex[nwOutline.LINE], sTitle[1:].lstrip("0"))
newItem.setData(self.colIndex[nwOutline.LINE], Qt.UserRole, sTitle) newItem.setData(self.colIndex[nwOutline.LINE], Qt.UserRole, sTitle)
newItem.setText(self.colIndex[nwOutline.SYNOP], novIdx["synopsis"]) newItem.setText(self.colIndex[nwOutline.SYNOP], novIdx["synopsis"])
newItem.setText(self.colIndex[nwOutline.CCOUNT], "{:n}".format(novIdx["cCount"])) newItem.setText(self.colIndex[nwOutline.CCOUNT], f"{cC:n}")
newItem.setText(self.colIndex[nwOutline.WCOUNT], "{:n}".format(novIdx["wCount"])) newItem.setText(self.colIndex[nwOutline.WCOUNT], f"{wC:n}")
newItem.setText(self.colIndex[nwOutline.PCOUNT], "{:n}".format(novIdx["pCount"])) newItem.setText(self.colIndex[nwOutline.PCOUNT], f"{pC:n}")
newItem.setTextAlignment(self.colIndex[nwOutline.CCOUNT], Qt.AlignRight) newItem.setTextAlignment(self.colIndex[nwOutline.CCOUNT], Qt.AlignRight)
newItem.setTextAlignment(self.colIndex[nwOutline.WCOUNT], Qt.AlignRight) newItem.setTextAlignment(self.colIndex[nwOutline.WCOUNT], Qt.AlignRight)
newItem.setTextAlignment(self.colIndex[nwOutline.PCOUNT], Qt.AlignRight) newItem.setTextAlignment(self.colIndex[nwOutline.PCOUNT], Qt.AlignRight)
+7 -3
View File
@@ -266,9 +266,13 @@ class GuiOutlineDetails(QScrollArea):
self.fileValue.setText(nwItem.itemName) self.fileValue.setText(nwItem.itemName)
self.itemValue.setText(nwItem.itemStatus) self.itemValue.setText(nwItem.itemStatus)
self.cCValue.setText("{:n}".format(checkInt(novIdx["cCount"], 0))) cC = checkInt(novIdx["cCount"], 0)
self.wCValue.setText("{:n}".format(checkInt(novIdx["wCount"], 0))) wC = checkInt(novIdx["wCount"], 0)
self.pCValue.setText("{:n}".format(checkInt(novIdx["pCount"], 0))) pC = checkInt(novIdx["pCount"], 0)
self.cCValue.setText(f"{cC:n}")
self.wCValue.setText(f"{wC:n}")
self.pCValue.setText(f"{pC:n}")
self.synopValue.setText(novIdx["synopsis"]) self.synopValue.setText(novIdx["synopsis"])
+4 -3
View File
@@ -270,11 +270,12 @@ class GuiProjectEditMeta(QWidget):
self.revLabel = QLabel("Revision count:") self.revLabel = QLabel("Revision count:")
self.revLabel.setIndent(xInd) self.revLabel.setIndent(xInd)
self.revValue = QLabel("{:n}".format(self.theProject.saveCount)) self.revValue = QLabel(f"{self.theProject.saveCount:n}")
editHours = self.theProject.editTime/3600
self.editLabel = QLabel("Edit time:") self.editLabel = QLabel("Edit time:")
self.editLabel.setIndent(xInd) self.editLabel.setIndent(xInd)
self.editValue = QLabel("{:.2f} hours".format(self.theProject.editTime/3600)) self.editValue = QLabel(f"{editHours:.2f} hours")
self.statsLabel = QLabel("<b>Project Stats</b>") self.statsLabel = QLabel("<b>Project Stats</b>")
@@ -294,7 +295,7 @@ class GuiProjectEditMeta(QWidget):
self.wordsLabel = QLabel("Word count:") self.wordsLabel = QLabel("Word count:")
self.wordsLabel.setIndent(xInd) self.wordsLabel.setIndent(xInd)
self.wordsValue = QLabel("{:n}".format(self.theProject.currWCount)) self.wordsValue = QLabel(f"{self.theProject.currWCount:n}")
self.mainForm.addWidget(self.headLabel, 0, 0, 1, 2, Qt.AlignTop) self.mainForm.addWidget(self.headLabel, 0, 0, 1, 2, Qt.AlignTop)
self.mainForm.addWidget(self.nameLabel, 1, 0, 1, 1, Qt.AlignTop) self.mainForm.addWidget(self.nameLabel, 1, 0, 1, 1, Qt.AlignTop)
+6 -6
View File
@@ -219,7 +219,7 @@ class GuiProjectTree(QTreeWidget):
pItem = self.theProject.projTree[pHandle] pItem = self.theProject.projTree[pHandle]
if pItem.itemType == nwItemType.FILE: if pItem.itemType == nwItemType.FILE:
nHandle = pHandle nHandle = pHandle
pHandle = pItem.parHandle pHandle = pItem.itemParent
# If we again have no home, give up # If we again have no home, give up
if pHandle is None: if pHandle is None:
@@ -270,7 +270,7 @@ class GuiProjectTree(QTreeWidget):
""" """
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.projTree[tHandle]
trItem = self._addTreeItem(nwItem, nHandle) trItem = self._addTreeItem(nwItem, nHandle)
pHandle = nwItem.parHandle pHandle = nwItem.itemParent
if pHandle is not None and pHandle in self.theMap: if pHandle is not None and pHandle in self.theMap:
self.theMap[pHandle].setExpanded(True) self.theMap[pHandle].setExpanded(True)
self.clearSelection() self.clearSelection()
@@ -430,7 +430,7 @@ class GuiProjectTree(QTreeWidget):
logger.error("Could not delete item") logger.error("Could not delete item")
return False return False
pHandle = nwItemS.parHandle pHandle = nwItemS.itemParent
if self.theProject.projTree.isTrashRoot(pHandle): if self.theProject.projTree.isTrashRoot(pHandle):
# If the file is in the trash folder already, as the # If the file is in the trash folder already, as the
# user if they want to permanently delete the file. # user if they want to permanently delete the file.
@@ -815,7 +815,7 @@ class GuiProjectTree(QTreeWidget):
project tree. project tree.
""" """
tHandle = nwItem.itemHandle tHandle = nwItem.itemHandle
pHandle = nwItem.parHandle pHandle = nwItem.itemParent
tClass = nwItem.itemClass tClass = nwItem.itemClass
newItem = QTreeWidgetItem([""]*4) newItem = QTreeWidgetItem([""]*4)
@@ -1022,11 +1022,11 @@ class GuiProjectTreeMenu(QMenu):
trashHandle = self.theTree.theProject.projTree.trashRoot() trashHandle = self.theTree.theProject.projTree.trashRoot()
inTrash = theItem.parHandle == trashHandle and trashHandle is not None inTrash = theItem.itemParent == trashHandle and trashHandle is not None
isTrash = theItem.itemHandle == trashHandle and trashHandle is not None isTrash = theItem.itemHandle == trashHandle and trashHandle is not None
isFile = theItem.itemType == nwItemType.FILE isFile = theItem.itemType == nwItemType.FILE
isArch = theRoot.itemClass == nwItemClass.ARCHIVE isArch = theRoot.itemClass == nwItemClass.ARCHIVE
isOrph = isFile and theItem.parHandle is None isOrph = isFile and theItem.itemParent is None
showOpen = isFile showOpen = isFile
showView = isFile showView = isFile
+8 -15
View File
@@ -195,28 +195,21 @@ class GuiMainStatus(QStatusBar):
self.statsText.setToolTip( self.statsText.setToolTip(
"Project word count (session change)" "Project word count (session change)"
) )
self.statsText.setText(( self.statsText.setText(
"Words: {pWC:n} ({sWC:+n})" f"Words: {self.projWords:n} ({self.sessWords:+n})"
).format( )
pWC = self.projWords,
sWC = self.sessWords,
))
return return
def _updateTime(self): def _updateTime(self):
"""Update the session clock. """Update the session clock.
""" """
if self.refTime is None: if self.refTime is None:
theTime = "00:00:00" self.timeText.setText("00:00:00")
else: else:
# This is much faster than using datetime format
tS = int(time() - self.refTime) tS = int(time() - self.refTime)
tM = int(tS/60) self.timeText.setText(
tH = int(tM/60) f"{tS//3600:02d}:{tS%3600//60:02d}:{tS%60:02d}"
tM = tM - tH*60 )
tS = tS - tM*60 - tH*3600
theTime = "%02d:%02d:%02d" % (tH, tM, tS)
self.timeText.setText(theTime)
return return
# END Class GuiMainStatus # END Class GuiMainStatus
@@ -237,7 +230,7 @@ class StatusLED(QAbstractButton):
return return
## ##
# Getters and Setters # Setters
## ##
def setState(self, theState): def setState(self, theState):
+42 -25
View File
@@ -62,7 +62,9 @@ class GuiMain(QMainWindow):
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.threadPool = QThreadPool() self.threadPool = QThreadPool()
# Some runtime info useful for debugging # System Info
# ===========
logger.info("OS: %s" % self.mainConf.osType) logger.info("OS: %s" % self.mainConf.osType)
logger.info("Kernel: %s" % self.mainConf.kernelVer) logger.info("Kernel: %s" % self.mainConf.kernelVer)
logger.info("Host: %s" % self.mainConf.hostName) logger.info("Host: %s" % self.mainConf.hostName)
@@ -76,6 +78,9 @@ class GuiMain(QMainWindow):
self.mainConf.verPyString, self.mainConf.verPyHexVal) self.mainConf.verPyString, self.mainConf.verPyHexVal)
) )
# Core Classes
# ============
# Core Classes and settings # Core Classes and settings
self.theTheme = GuiTheme(self) self.theTheme = GuiTheme(self)
self.theProject = NWProject(self) self.theProject = NWProject(self)
@@ -89,7 +94,7 @@ class GuiMain(QMainWindow):
self.setWindowIcon(QIcon(self.mainConf.appIcon)) self.setWindowIcon(QIcon(self.mainConf.appIcon))
# Build the GUI # Build the GUI
################ # =============
# Main GUI Elements # Main GUI Elements
self.statusBar = GuiMainStatus(self) self.statusBar = GuiMainStatus(self)
@@ -106,7 +111,7 @@ class GuiMain(QMainWindow):
self.statusIcons = [] self.statusIcons = []
self.importIcons = [] self.importIcons = []
# Assemble Main Window # Project Tree View
self.treePane = QWidget() self.treePane = QWidget()
self.treeBox = QVBoxLayout() self.treeBox = QVBoxLayout()
self.treeBox.setContentsMargins(0, 0, 0, 0) self.treeBox.setContentsMargins(0, 0, 0, 0)
@@ -114,20 +119,24 @@ class GuiMain(QMainWindow):
self.treeBox.addWidget(self.treeMeta) self.treeBox.addWidget(self.treeMeta)
self.treePane.setLayout(self.treeBox) self.treePane.setLayout(self.treeBox)
# Splitter : Document Viewer / Document Meta
self.splitView = QSplitter(Qt.Vertical) self.splitView = QSplitter(Qt.Vertical)
self.splitView.addWidget(self.docViewer) self.splitView.addWidget(self.docViewer)
self.splitView.addWidget(self.viewMeta) self.splitView.addWidget(self.viewMeta)
self.splitView.setSizes(self.mainConf.getViewPanePos()) self.splitView.setSizes(self.mainConf.getViewPanePos())
# Splitter : Document Editor / Document Viewer
self.splitDocs = QSplitter(Qt.Horizontal) self.splitDocs = QSplitter(Qt.Horizontal)
self.splitDocs.addWidget(self.docEditor) self.splitDocs.addWidget(self.docEditor)
self.splitDocs.addWidget(self.splitView) self.splitDocs.addWidget(self.splitView)
# Splitter : Project Outlie / Outline Details
self.splitOutline = QSplitter(Qt.Vertical) self.splitOutline = QSplitter(Qt.Vertical)
self.splitOutline.addWidget(self.projView) self.splitOutline.addWidget(self.projView)
self.splitOutline.addWidget(self.projMeta) self.splitOutline.addWidget(self.projMeta)
self.splitOutline.setSizes(self.mainConf.getOutlinePanePos()) self.splitOutline.setSizes(self.mainConf.getOutlinePanePos())
# Main Tabs : Edirot / Outline
self.tabWidget = QTabWidget() self.tabWidget = QTabWidget()
self.tabWidget.setTabPosition(QTabWidget.East) self.tabWidget.setTabPosition(QTabWidget.East)
self.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;}") self.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;}")
@@ -135,6 +144,7 @@ class GuiMain(QMainWindow):
self.tabWidget.addTab(self.splitOutline, "Outline") self.tabWidget.addTab(self.splitOutline, "Outline")
self.tabWidget.currentChanged.connect(self._mainTabChanged) self.tabWidget.currentChanged.connect(self._mainTabChanged)
# Splitter : Project Tree / Main Tabs
xCM = self.mainConf.pxInt(4) xCM = self.mainConf.pxInt(4)
self.splitMain = QSplitter(Qt.Horizontal) self.splitMain = QSplitter(Qt.Horizontal)
self.splitMain.setContentsMargins(xCM, xCM, xCM, xCM) self.splitMain.setContentsMargins(xCM, xCM, xCM, xCM)
@@ -142,6 +152,7 @@ class GuiMain(QMainWindow):
self.splitMain.addWidget(self.tabWidget) self.splitMain.addWidget(self.tabWidget)
self.splitMain.setSizes(self.mainConf.getMainPanePos()) self.splitMain.setSizes(self.mainConf.getMainPanePos())
# Indices of All Splitter Widgets
self.idxTree = self.splitMain.indexOf(self.treePane) self.idxTree = self.splitMain.indexOf(self.treePane)
self.idxMain = self.splitMain.indexOf(self.tabWidget) self.idxMain = self.splitMain.indexOf(self.tabWidget)
self.idxEditor = self.splitDocs.indexOf(self.docEditor) self.idxEditor = self.splitDocs.indexOf(self.docEditor)
@@ -151,6 +162,7 @@ class GuiMain(QMainWindow):
self.idxTabEdit = self.tabWidget.indexOf(self.splitDocs) self.idxTabEdit = self.tabWidget.indexOf(self.splitDocs)
self.idxTabProj = self.tabWidget.indexOf(self.splitOutline) self.idxTabProj = self.tabWidget.indexOf(self.splitOutline)
# Splitter Behaviour
self.splitMain.setCollapsible(self.idxTree, False) self.splitMain.setCollapsible(self.idxTree, False)
self.splitMain.setCollapsible(self.idxMain, False) self.splitMain.setCollapsible(self.idxMain, False)
self.splitDocs.setCollapsible(self.idxEditor, False) self.splitDocs.setCollapsible(self.idxEditor, False)
@@ -158,10 +170,11 @@ class GuiMain(QMainWindow):
self.splitView.setCollapsible(self.idxViewDoc, False) self.splitView.setCollapsible(self.idxViewDoc, False)
self.splitView.setCollapsible(self.idxViewMeta, False) self.splitView.setCollapsible(self.idxViewMeta, False)
# Editor / Viewer Default State
self.splitView.setVisible(False) self.splitView.setVisible(False)
self.docEditor.closeSearch() self.docEditor.closeSearch()
# Build the Tree View # Initialise the Project Tree
self.treeView.itemSelectionChanged.connect(self._treeSingleClick) self.treeView.itemSelectionChanged.connect(self._treeSingleClick)
self.treeView.itemDoubleClicked.connect(self._treeDoubleClick) self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
self.rebuildTree() self.rebuildTree()
@@ -172,13 +185,13 @@ class GuiMain(QMainWindow):
self.setStatusBar(self.statusBar) self.setStatusBar(self.statusBar)
# Finalise Initialisation # Finalise Initialisation
########################## # =======================
# Set Up Autosaving Project Timer # Set Up Auto-Save Project Timer
self.asProjTimer = QTimer() self.asProjTimer = QTimer()
self.asProjTimer.timeout.connect(self._autoSaveProject) self.asProjTimer.timeout.connect(self._autoSaveProject)
# Set Up Autosaving Document Timer # Set Up Auto-Save Document Timer
self.asDocTimer = QTimer() self.asDocTimer = QTimer()
self.asDocTimer.timeout.connect(self._autoSaveDocument) self.asDocTimer.timeout.connect(self._autoSaveDocument)
@@ -203,11 +216,13 @@ class GuiMain(QMainWindow):
# Check that config loaded fine # Check that config loaded fine
self.reportConfErr() self.reportConfErr()
# Initialise Main GUI
self.initMain() self.initMain()
self.asProjTimer.start() self.asProjTimer.start()
self.asDocTimer.start() self.asDocTimer.start()
self.statusBar.clearStatus() self.statusBar.clearStatus()
# Handle Windows Mode
self.showNormal() self.showNormal()
if self.mainConf.isFullScreen: if self.mainConf.isFullScreen:
self.toggleFullScreenMode() self.toggleFullScreenMode()
@@ -224,7 +239,7 @@ class GuiMain(QMainWindow):
self.showProjectLoadDialog() self.showProjectLoadDialog()
logger.debug("novelWriter is ready ...") logger.debug("novelWriter is ready ...")
self.statusBar.setStatus("novelWriter is ready ...") self.setStatus("novelWriter is ready ...")
return return
@@ -249,8 +264,7 @@ class GuiMain(QMainWindow):
## ##
def newProject(self, projData=None): def newProject(self, projData=None):
"""Create new project with a few default files and folders. """Create new project via the new project wizard.
The variable forceNew is used for testing.
""" """
if self.hasProject: if self.hasProject:
self.makeAlert( self.makeAlert(
@@ -293,7 +307,7 @@ class GuiMain(QMainWindow):
def closeProject(self, isYes=False): def closeProject(self, isYes=False):
"""Closes the project if one is open. isYes is passed on from """Closes the project if one is open. isYes is passed on from
the close application event so the user doesn't get prompted the close application event so the user doesn't get prompted
twice. twice to confirm.
""" """
if not self.hasProject: if not self.hasProject:
# There is no project loaded, everything OK # There is no project loaded, everything OK
@@ -302,7 +316,7 @@ class GuiMain(QMainWindow):
if not isYes: if not isYes:
msgBox = QMessageBox() msgBox = QMessageBox()
msgRes = msgBox.question( msgRes = msgBox.question(
self, "Close Project", "Save changes and close current project?" self, "Close Project", "Save changes and close the current project?"
) )
if msgRes != QMessageBox.Yes: if msgRes != QMessageBox.Yes:
return False return False
@@ -318,7 +332,7 @@ class GuiMain(QMainWindow):
if self.mainConf.askBeforeBackup: if self.mainConf.askBeforeBackup:
msgBox = QMessageBox() msgBox = QMessageBox()
msgRes = msgBox.question( msgRes = msgBox.question(
self, "Backup Project", "Backup current project?" self, "Backup Project", "Backup the current project?"
) )
if msgRes != QMessageBox.Yes: if msgRes != QMessageBox.Yes:
doBackup = False doBackup = False
@@ -433,6 +447,7 @@ class GuiMain(QMainWindow):
if self.theProject.projPath is None: if self.theProject.projPath is None:
projPath = self.selectProjectPath() projPath = self.selectProjectPath()
self.theProject.setProjectPath(projPath) self.theProject.setProjectPath(projPath)
if self.theProject.projPath is None: if self.theProject.projPath is None:
return False return False
@@ -454,6 +469,7 @@ class GuiMain(QMainWindow):
if self.docEditor.docChanged: if self.docEditor.docChanged:
self.saveDocument() self.saveDocument()
self.docEditor.clearEditor() self.docEditor.clearEditor()
return True return True
def openDocument(self, tHandle, tLine=None, changeFocus=True, doScroll=False): def openDocument(self, tHandle, tLine=None, changeFocus=True, doScroll=False):
@@ -469,6 +485,7 @@ class GuiMain(QMainWindow):
self.treeView.setSelectedHandle(tHandle, doScroll=doScroll) self.treeView.setSelectedHandle(tHandle, doScroll=doScroll)
else: else:
return False return False
return True return True
def openNextDocument(self, tHandle, wrapAround=False): def openNextDocument(self, tHandle, wrapAround=False):
@@ -546,6 +563,7 @@ class GuiMain(QMainWindow):
vPos[1] = bPos[1] - vPos[0] vPos[1] = bPos[1] - vPos[0]
self.splitDocs.setSizes(vPos) self.splitDocs.setSizes(vPos)
self.viewMeta.setVisible(self.mainConf.showRefPanel) self.viewMeta.setVisible(self.mainConf.showRefPanel)
self.docViewer.navigateTo(tAnchor) self.docViewer.navigateTo(tAnchor)
return True return True
@@ -697,9 +715,9 @@ class GuiMain(QMainWindow):
for nDone, tItem in enumerate(self.theProject.projTree): for nDone, tItem in enumerate(self.theProject.projTree):
if tItem is not None: if tItem is not None:
self.statusBar.setStatus("Indexing: '%s'" % tItem.itemName) self.setStatus("Indexing: '%s'" % tItem.itemName)
else: else:
self.statusBar.setStatus("Indexing: Unknown item") self.setStatus("Indexing: Unknown item")
if tItem is not None and tItem.itemType == nwItemType.FILE: if tItem is not None and tItem.itemType == nwItemType.FILE:
logger.verbose("Scanning: %s" % tItem.itemName) logger.verbose("Scanning: %s" % tItem.itemName)
@@ -717,7 +735,7 @@ class GuiMain(QMainWindow):
self.treeView.projectWordCount() self.treeView.projectWordCount()
tEnd = time() tEnd = time()
self.statusBar.setStatus("Indexing completed in %.1f ms" % ((tEnd - tStart)*1000.0)) self.setStatus("Indexing completed in %.1f ms" % ((tEnd - tStart)*1000.0))
self.docEditor.updateTagHighLighting() self.docEditor.updateTagHighLighting()
qApp.restoreOverrideCursor() qApp.restoreOverrideCursor()
@@ -754,7 +772,8 @@ class GuiMain(QMainWindow):
def showProjectLoadDialog(self): def showProjectLoadDialog(self):
"""Opens the projects dialog for selecting either existing """Opens the projects dialog for selecting either existing
projects from a cache of recently opened projects, or provide a projects from a cache of recently opened projects, or provide a
browse button for projects not yet cached. browse button for projects not yet cached. Selecting to create a
new project is forwarded to the new project wizard.
""" """
dlgProj = GuiProjectLoad(self) dlgProj = GuiProjectLoad(self)
dlgProj.exec_() dlgProj.exec_()
@@ -767,7 +786,7 @@ class GuiMain(QMainWindow):
return True return True
def showNewProjectDialog(self): def showNewProjectDialog(self):
"""Open the wizard and assemble the project options dict. """Open the wizard and assemble a project options dict.
""" """
newProj = GuiProjectWizard(self) newProj = GuiProjectWizard(self)
newProj.exec_() newProj.exec_()
@@ -865,8 +884,7 @@ class GuiMain(QMainWindow):
def makeAlert(self, theMessage, theLevel=nwAlert.INFO): def makeAlert(self, theMessage, theLevel=nwAlert.INFO):
"""Alert both the user and the logger at the same time. Message """Alert both the user and the logger at the same time. Message
can be either a string or an array of strings. Severity level is can be either a string or an array of strings.
0 = info, 1 = warning, and 2 = error.
""" """
if isinstance(theMessage, list): if isinstance(theMessage, list):
popMsg = "<br>".join(theMessage) popMsg = "<br>".join(theMessage)
@@ -955,7 +973,7 @@ class GuiMain(QMainWindow):
return True return True
def setFocus(self, paneNo): def setFocus(self, paneNo):
"""Switch focus to one of the three main gUi panes. """Switch focus to one of the three main GUI panes.
""" """
if paneNo == 1: if paneNo == 1:
self.treeView.setFocus() self.treeView.setFocus()
@@ -1236,9 +1254,9 @@ class GuiMain(QMainWindow):
return return
def _treeKeyPressReturn(self): def _treeKeyPressReturn(self):
"""The user pressed return an item in the tree. If it is a file, """The user pressed return on an item in the tree. If it is a
we open it. Otherwise, we do nothing. Pressing return does not file, we open it. Otherwise, we do nothing. Pressing return does
change focus to the editor as double click does. not change focus to the editor as double click does.
""" """
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)
@@ -1257,7 +1275,6 @@ class GuiMain(QMainWindow):
""" """
if self.docEditor.docSearch.isVisible(): if self.docEditor.docSearch.isVisible():
self.docEditor.closeSearch() self.docEditor.closeSearch()
return
elif self.isFocusMode: elif self.isFocusMode:
self.toggleFocusMode() self.toggleFocusMode()
return return
+1 -1
View File
@@ -6,6 +6,6 @@ version = attr: nw.__version__
universal = 0 universal = 0
[flake8] [flake8]
ignore = E203,E221,E226,E241,E251,E261,E266,E302,E305 ignore = E203,E221,E226,E228,E241,E251,E261,E266,E302,E305
max-line-length = 99 max-line-length = 99
exclude = docs/* exclude = docs/*
+5 -5
View File
@@ -31,13 +31,13 @@ def testItemSettersSimple(nwDummy):
# Parent # Parent
theItem.setParent(None) theItem.setParent(None)
assert theItem.parHandle is None assert theItem.itemParent is None
theItem.setParent(123) theItem.setParent(123)
assert theItem.parHandle is None assert theItem.itemParent is None
theItem.setParent("0123456789abcdef") theItem.setParent("0123456789abcdef")
assert theItem.parHandle is None assert theItem.itemParent is None
theItem.setParent("0123456789abc") theItem.setParent("0123456789abc")
assert theItem.parHandle == "0123456789abc" assert theItem.itemParent == "0123456789abc"
# Order # Order
theItem.setOrder(None) theItem.setOrder(None)
@@ -227,7 +227,7 @@ def testItemXMLPackUnpack(nwDummy):
# Unpack # Unpack
assert theItem.unpackXML(xContent[0]) assert theItem.unpackXML(xContent[0])
assert theItem.itemHandle == "0123456789abc" assert theItem.itemHandle == "0123456789abc"
assert theItem.parHandle == "0123456789abc" assert theItem.itemParent == "0123456789abc"
assert theItem.itemOrder == 1 assert theItem.itemOrder == 1
assert theItem.isExpanded assert theItem.isExpanded
assert theItem.paraCount == 3 assert theItem.paraCount == 3
+2 -2
View File
@@ -521,7 +521,7 @@ def testProjectOrphanedFiles(nwDummy, nwLipsum):
assert oItem is not None assert oItem is not None
assert oItem.itemName == "Mars" assert oItem.itemName == "Mars"
assert oItem.itemHandle == "636b6aa9b697b" assert oItem.itemHandle == "636b6aa9b697b"
assert oItem.parHandle is None assert oItem.itemParent is None
assert oItem.itemClass == nwItemClass.WORLD assert oItem.itemClass == nwItemClass.WORLD
assert oItem.itemType == nwItemType.FILE assert oItem.itemType == nwItemType.FILE
assert oItem.itemLayout == nwItemLayout.NOTE assert oItem.itemLayout == nwItemLayout.NOTE
@@ -531,7 +531,7 @@ def testProjectOrphanedFiles(nwDummy, nwLipsum):
assert oItem is not None assert oItem is not None
assert oItem.itemName == "Orphaned File 1" assert oItem.itemName == "Orphaned File 1"
assert oItem.itemHandle == "736b6aa9b697b" assert oItem.itemHandle == "736b6aa9b697b"
assert oItem.parHandle is None assert oItem.itemParent is None
assert oItem.itemClass == nwItemClass.NO_CLASS assert oItem.itemClass == nwItemClass.NO_CLASS
assert oItem.itemType == nwItemType.FILE assert oItem.itemType == nwItemType.FILE
assert oItem.itemLayout == nwItemLayout.NO_LAYOUT assert oItem.itemLayout == nwItemLayout.NO_LAYOUT
+1
View File
@@ -61,6 +61,7 @@ def testNumberWords():
assert numberToWord(21, "en") == "Twenty-One" assert numberToWord(21, "en") == "Twenty-One"
assert numberToWord(29, "en") == "Twenty-Nine" assert numberToWord(29, "en") == "Twenty-Nine"
assert numberToWord(42, "en") == "Forty-Two" assert numberToWord(42, "en") == "Forty-Two"
assert numberToWord(114, "en") == "One Hundred Fourteen"
assert numberToWord(142, "en") == "One Hundred Forty-Two" assert numberToWord(142, "en") == "One Hundred Forty-Two"
assert numberToWord(999, "en") == "Nine Hundred Ninety-Nine" assert numberToWord(999, "en") == "Nine Hundred Ninety-Nine"