From 981e26e1b6c728b08c04dc87fe08644d9a4dd4b8 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:02:45 +0100 Subject: [PATCH] Use actual novel word count in project details, and update index test --- nw/core/index.py | 65 +++++++++++++++++---------------- nw/gui/projdetails.py | 5 +-- tests/test_core_index.py | 78 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 114 insertions(+), 34 deletions(-) diff --git a/nw/core/index.py b/nw/core/index.py index 6128a177..2b14a5d4 100644 --- a/nw/core/index.py +++ b/nw/core/index.py @@ -292,10 +292,12 @@ class NWIndex(): "updated" : round(time()), } if itemLayout == nwItemLayout.NOTE: + self._novelIndex.pop(tHandle, None) self._noteIndex[tHandle] = {} isNovel = False else: self._novelIndex[tHandle] = {} + self._noteIndex.pop(tHandle, None) isNovel = True # Also clear references to file in tag index @@ -580,34 +582,26 @@ class NWIndex(): they appear in the tree view and in the respective document files, but skipping all note files. """ - for tItem in self.theProject.projTree: - if tItem is None: - continue - if not tItem.isExported and skipExcluded: - continue - - tHandle = tItem.itemHandle - if tHandle not in self._novelIndex: - continue - + for tHandle in self._listNovelHandles(skipExcluded): for sTitle in sorted(self._novelIndex[tHandle]): tKey = "%s:%s" % (tHandle, sTitle) yield tKey, tHandle, sTitle, self._novelIndex[tHandle][sTitle] - def getNovelCounts(self, skipExcluded=True): + def getNovelWordCount(self, skipExcluded=True): + """Count the number of words in the novel project. + """ + wCount = 0 + for tHandle in self._listNovelHandles(skipExcluded): + for sTitle in self._novelIndex[tHandle]: + wCount += self._novelIndex[tHandle][sTitle]["wCount"] + + return wCount + + def getNovelTitleCounts(self, skipExcluded=True): """Count the number of titles in the novel project. """ hCount = [0, 0, 0, 0, 0] - for tItem in self.theProject.projTree: - if tItem is None: - continue - if not tItem.isExported and skipExcluded: - continue - - tHandle = tItem.itemHandle - if tHandle not in self._novelIndex: - continue - + for tHandle in self._listNovelHandles(skipExcluded): for sTitle in self._novelIndex[tHandle]: theData = self._novelIndex[tHandle][sTitle] iLevel = self.H_LEVEL.get(theData["level"], 0) @@ -621,16 +615,7 @@ class NWIndex(): tOrder = [] tData = {} pKey = None - for tItem in self.theProject.projTree: - if tItem is None: - continue - if not tItem.isExported and skipExcluded: - continue - - tHandle = tItem.itemHandle - if tHandle not in self._novelIndex: - continue - + for tHandle in self._listNovelHandles(skipExcluded): for sTitle in sorted(self._novelIndex[tHandle]): tKey = "%s:%s" % (tHandle, sTitle) theData = self._novelIndex[tHandle][sTitle] @@ -740,4 +725,22 @@ class NWIndex(): return theRef[1], theRef[0], theRef[3] return None, 0, "T000000" + ## + # Internal Functions + ## + + def _listNovelHandles(self, skipExcluded): + """Return a list of all handles that exist in the novel index. + """ + theHandles = [] + for tItem in self.theProject.projTree: + if tItem is None: + continue + if not tItem.isExported and skipExcluded: + continue + if tItem.itemHandle in self._novelIndex: + theHandles.append(tItem.itemHandle) + + return theHandles + # END Class NWIndex diff --git a/nw/gui/projdetails.py b/nw/gui/projdetails.py index 0270476d..ae001483 100644 --- a/nw/gui/projdetails.py +++ b/nw/gui/projdetails.py @@ -168,10 +168,11 @@ class GuiProjectDetailsMain(QWidget): # Stats # ===== - hCounts = self.theIndex.getNovelCounts() + hCounts = self.theIndex.getNovelTitleCounts() + nwCount = self.theIndex.getNovelWordCount() self.wordCountLbl = QLabel("Words:") - self.wordCountVal = QLabel(f"{self.theProject.currWCount:n}") + self.wordCountVal = QLabel(f"{nwCount:n}") self.chapCountLbl = QLabel("Chapters:") self.chapCountVal = QLabel(f"{hCounts[2]:n}") diff --git a/tests/test_core_index.py b/tests/test_core_index.py index b19af00d..d865cd41 100644 --- a/tests/test_core_index.py +++ b/tests/test_core_index.py @@ -276,6 +276,7 @@ def testCoreIndex_ScanText(nwMinimal, dummyGUI): assert not theIndex.scanText(xHandle, "Hello World!") # Make some usable items + pHandle = theProject.newFile("Page", nwItemClass.NOVEL, "a508bb932959c") nHandle = theProject.newFile("Hello", nwItemClass.NOVEL, "a508bb932959c") cHandle = theProject.newFile("Jane", nwItemClass.CHARACTER, "afb3043c7b2b3") sHandle = theProject.newFile("Scene", nwItemClass.NOVEL, "a508bb932959c") @@ -310,7 +311,7 @@ def testCoreIndex_ScanText(nwMinimal, dummyGUI): "#### Title Four\n\n" "% synopsis: Synopsis Four.\n\n" "Paragraph Four.\n\n" - "##### Title Five\n\n" # Not interpreted as a title, the hashes is counted as a word + "##### Title Five\n\n" # Not interpreted as a title, the hashes are counted as a word "Paragraph Five.\n\n" )) assert theIndex._refIndex[nHandle].get("T000000", None) is not None # Always there @@ -411,6 +412,33 @@ def testCoreIndex_ScanText(nwMinimal, dummyGUI): [[3, "@pov", "One"], [5, "@char", "Two"]] ) + # Page wo/Title + theProject.projTree[pHandle].itemLayout = nwItemLayout.PAGE + assert theIndex.scanText(pHandle, ( + "This is a page with some text on it.\n\n" + )) + assert theIndex._novelIndex[pHandle]["T000000"]["level"] == "H0" + assert theIndex._novelIndex[pHandle]["T000000"]["title"] == "Untitled Page" + assert theIndex._novelIndex[pHandle]["T000000"]["layout"] == "PAGE" + assert theIndex._novelIndex[pHandle]["T000000"]["synopsis"] == "" + assert theIndex._novelIndex[pHandle]["T000000"]["cCount"] == 36 + assert theIndex._novelIndex[pHandle]["T000000"]["wCount"] == 9 + assert theIndex._novelIndex[pHandle]["T000000"]["pCount"] == 1 + assert pHandle not in theIndex._noteIndex + + theProject.projTree[pHandle].itemLayout = nwItemLayout.NOTE + assert theIndex.scanText(pHandle, ( + "This is a page with some text on it.\n\n" + )) + assert theIndex._noteIndex[pHandle]["T000000"]["level"] == "H0" + assert theIndex._noteIndex[pHandle]["T000000"]["title"] == "Untitled Page" + assert theIndex._noteIndex[pHandle]["T000000"]["layout"] == "NOTE" + assert theIndex._noteIndex[pHandle]["T000000"]["synopsis"] == "" + assert theIndex._noteIndex[pHandle]["T000000"]["cCount"] == 36 + assert theIndex._noteIndex[pHandle]["T000000"]["wCount"] == 9 + assert theIndex._noteIndex[pHandle]["T000000"]["pCount"] == 1 + assert pHandle not in theIndex._novelIndex + assert theProject.closeProject() # END Test testCoreIndex_ScanText @@ -579,6 +607,54 @@ def testCoreIndex_ExtractData(nwMinimal, dummyGUI): assert wC == 12 assert pC == 2 + ## + # Novel Stats + ## + + hHandle = theProject.newFile("Chapter", nwItemClass.NOVEL, "a508bb932959c") + sHandle = theProject.newFile("Scene One", nwItemClass.NOVEL, "a508bb932959c") + tHandle = theProject.newFile("Scene Two", nwItemClass.NOVEL, "a508bb932959c") + + theProject.projTree[hHandle].itemLayout == nwItemLayout.CHAPTER + theProject.projTree[sHandle].itemLayout == nwItemLayout.SCENE + theProject.projTree[tHandle].itemLayout == nwItemLayout.SCENE + + assert theIndex.scanText(hHandle, "## Chapter One\n\n") + assert theIndex.scanText(sHandle, "### Scene One\n\n") + assert theIndex.scanText(tHandle, "### Scene Two\n\n") + + assert theIndex._listNovelHandles(False) == [nHandle, hHandle, sHandle, tHandle] + assert theIndex._listNovelHandles(True) == [hHandle, sHandle, tHandle] + + # Add a fake handle to the tree and check that it's ignored + theProject.projTree._treeOrder.append("0000000000000") + assert theIndex._listNovelHandles(False) == [nHandle, hHandle, sHandle, tHandle] + theProject.projTree._treeOrder.remove("0000000000000") + + # Extract stats + assert theIndex.getNovelWordCount(False) == 30 + assert theIndex.getNovelWordCount(True) == 6 + assert theIndex.getNovelTitleCounts(False) == [0, 2, 1, 2, 0] + assert theIndex.getNovelTitleCounts(True) == [0, 0, 1, 2, 0] + + # Table of Contents + assert theIndex.getTableOfContents(0, True) == [] + assert theIndex.getTableOfContents(1, True) == [] + assert theIndex.getTableOfContents(2, True) == [ + ("%s:T000001" % hHandle, "H2", "Chapter One", 6), + ] + assert theIndex.getTableOfContents(3, True) == [ + ("%s:T000001" % hHandle, "H2", "Chapter One", 2), + ("%s:T000001" % sHandle, "H3", "Scene One", 2), + ("%s:T000001" % tHandle, "H3", "Scene Two", 2), + ] + + assert theIndex.getTableOfContents(0, False) == [] + assert theIndex.getTableOfContents(1, False) == [ + ("%s:T000001" % nHandle, "H1", "Hello World!", 12), + ("%s:T000011" % nHandle, "H1", "Hello World!", 18), + ] + assert theProject.closeProject() # END Test testCoreIndex_ExtractData