diff --git a/novelwriter/core/item.py b/novelwriter/core/item.py index f6d93b36..e23b4fb9 100644 --- a/novelwriter/core/item.py +++ b/novelwriter/core/item.py @@ -160,13 +160,12 @@ class NWItem(): itemAttrib["layout"] = str(self._layout.name) metaAttrib = {} + metaAttrib["expanded"] = str(self._expanded) if self._type == nwItemType.FILE: metaAttrib["charCount"] = str(self._charCount) metaAttrib["wordCount"] = str(self._wordCount) metaAttrib["paraCount"] = str(self._paraCount) metaAttrib["cursorPos"] = str(self._cursorPos) - else: - metaAttrib["expanded"] = str(self._expanded) nameAttrib = {} nameAttrib["status"] = str(self._status) @@ -409,6 +408,8 @@ class NWItem(): self._type = value elif isItemType(value): self._type = nwItemType[value] + elif value == "TRASH": + self._type = nwItemType.ROOT else: logger.error("Unrecognised item type '%s'", value) self._type = nwItemType.NO_TYPE diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py index 0d24d74c..26efb323 100644 --- a/novelwriter/core/project.py +++ b/novelwriter/core/project.py @@ -158,7 +158,7 @@ class NWProject(): if trashHandle is None: newItem = NWItem(self) newItem.setName(trConst(nwLabels.CLASS_NAME[nwItemClass.TRASH])) - newItem.setType(nwItemType.TRASH) + newItem.setType(nwItemType.ROOT) newItem.setClass(nwItemClass.TRASH) self.projTree.append(None, None, newItem) self.projTree.updateItemData(newItem.itemHandle) diff --git a/novelwriter/core/tree.py b/novelwriter/core/tree.py index a158c37a..ee57e0db 100644 --- a/novelwriter/core/tree.py +++ b/novelwriter/core/tree.py @@ -100,14 +100,13 @@ class NWTree(): if nwItem.itemClass == nwItemClass.ARCHIVE: logger.verbose("Item '%s' is the archive folder", str(tHandle)) self._archRoot = tHandle - - if nwItem.itemType == nwItemType.TRASH: - if self._trashRoot is None: - logger.verbose("Item '%s' is the trash folder", str(tHandle)) - self._trashRoot = tHandle - else: - logger.error("Only one trash folder allowed") - return False + elif nwItem.itemClass == nwItemClass.TRASH: + if self._trashRoot is None: + logger.verbose("Item '%s' is the trash folder", str(tHandle)) + self._trashRoot = tHandle + else: + logger.error("Only one trash folder allowed") + return False self._projTree[tHandle] = nwItem self._treeOrder.append(tHandle) @@ -352,30 +351,6 @@ class NWTree(): return True - ## - # Getters - ## - - def countTypes(self): - """Count the number of files, folders and roots in the project. - """ - nRoot = 0 - nFolder = 0 - nFile = 0 - - for tHandle in self._treeOrder: - tItem = self.__getitem__(tHandle) - if tItem is None: - continue - elif tItem.itemType == nwItemType.ROOT: - nRoot += 1 - elif tItem.itemType == nwItemType.FOLDER: - nFolder += 1 - elif tItem.itemType == nwItemType.FILE: - nFile += 1 - - return nRoot, nFolder, nFile - ## # Meta Methods ## diff --git a/novelwriter/enum.py b/novelwriter/enum.py index 3360d8c5..56340541 100644 --- a/novelwriter/enum.py +++ b/novelwriter/enum.py @@ -32,7 +32,6 @@ class nwItemType(Enum): ROOT = 1 FOLDER = 2 FILE = 3 - TRASH = 4 # END Enum nwItemType diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index 23238b84..cb59c9ee 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -82,7 +82,7 @@ class GuiProjectTree(QTreeWidget): # Tree Settings iPx = self.theTheme.baseIconSize self.setIconSize(QSize(iPx, iPx)) - self.setExpandsOnDoubleClick(True) + self.setExpandsOnDoubleClick(False) self.setIndentation(iPx) self.setColumnCount(4) self.setHeaderLabels([ @@ -349,6 +349,14 @@ class GuiProjectTree(QTreeWidget): theList = self._scanChildren(theList, theItem, 0) return theList + def toggleExpanded(self, tHandle): + """Expand an item based on its handle. + """ + trItem = self._getTreeItem(tHandle) + if trItem is not None: + trItem.setExpanded(not trItem.isExpanded()) + return + def getColumnSizes(self): """Return the column widths for the tree columns. """ @@ -435,7 +443,7 @@ class GuiProjectTree(QTreeWidget): logger.error("Could not find tree item for deletion") return False - wCount = int(trItemS.data(self.C_COUNT, Qt.UserRole)) + wCount = self._getItemWordCount(tHandle) if nwItemS.itemType == nwItemType.FILE: logger.debug("User requested file '%s' deleted", tHandle) trItemP = trItemS.parent() @@ -576,7 +584,7 @@ class GuiProjectTree(QTreeWidget): return - def propagateCount(self, tHandle, theCount): + def propagateCount(self, tHandle, newCount, countChildren=False): """Recursive function setting the word count for a given item, and propagating that count upwards in the tree until reaching a root item. This function is more efficient than recalculating @@ -588,8 +596,12 @@ class GuiProjectTree(QTreeWidget): if tItem is None: return - tItem.setText(self.C_COUNT, f"{theCount:n}") - tItem.setData(self.C_COUNT, Qt.UserRole, int(theCount)) + if countChildren: + for i in range(tItem.childCount()): + newCount += int(tItem.child(i).data(self.C_COUNT, Qt.UserRole)) + + tItem.setText(self.C_COUNT, f"{newCount:n}") + tItem.setData(self.C_COUNT, Qt.UserRole, int(newCount)) pItem = tItem.parent() if pItem is None: @@ -602,7 +614,12 @@ class GuiProjectTree(QTreeWidget): pHandle = pItem.data(self.C_NAME, Qt.UserRole) if pHandle: - self.propagateCount(pHandle, pCount) + if self.theProject.projTree.checkType(pHandle, nwItemType.FILE): + # A file has an internal word count we need to account + # for, but a folder always has 0 words on its own. + pCount += self.theIndex.getCounts(pHandle)[1] + + self.propagateCount(pHandle, pCount, countChildren=False) return @@ -646,11 +663,11 @@ class GuiProjectTree(QTreeWidget): return False dstIndex = min(max(0, dstIndex), dstItem.childCount()) - wCount = int(srcItem.data(self.C_COUNT, Qt.UserRole)) sHandle = srcItem.data(self.C_NAME, Qt.UserRole) dHandle = dstItem.data(self.C_NAME, Qt.UserRole) logger.debug("Moving item '%s' back to '%s', index %d", sHandle, dHandle, dstIndex) + wCount = self._getItemWordCount(sHandle) self.propagateCount(sHandle, 0) parItem = srcItem.parent() srcIndex = parItem.indexOfChild(srcItem) @@ -724,7 +741,7 @@ class GuiProjectTree(QTreeWidget): def doUpdateCounts(self, tHandle, cCount, wCount, pCount): """Slot for updating the word count of a specific item. """ - self.propagateCount(tHandle, wCount) + self.propagateCount(tHandle, wCount, countChildren=True) self.wordCountsChanged.emit() return @@ -765,61 +782,28 @@ class GuiProjectTree(QTreeWidget): """ sHandle = self.getSelectedHandle() if sHandle is None: - logger.error("No handle selected") + logger.error("Invalid drag and drop event") return - dIndex = self.indexAt(theEvent.pos()) - if not dIndex.isValid(): - logger.error("Invalid drop index") - return + logger.debug("Drag'n'drop of item '%s' accepted", sHandle) sItem = self._getTreeItem(sHandle) - dItem = self.itemFromIndex(dIndex) - dHandle = dItem.data(self.C_NAME, Qt.UserRole) - snItem = self.theProject.projTree[sHandle] - dnItem = self.theProject.projTree[dHandle] - if dnItem is None: - self.theParent.makeAlert(self.tr( - "The item cannot be moved to that location." - ), nwAlert.ERROR) - return + isExpanded = False + if sItem is not None: + isExpanded = sItem.isExpanded() pItem = sItem.parent() pIndex = 0 if pItem is not None: pIndex = pItem.indexOfChild(sItem) - # Determine if the drag and drop is allowed: - # - Files can be moved anywhere - # - Folders can only be moved within the same root folder - # - Root folders cannot be moved at all - # - Items cannot be dropped on top of a file (moved inside) + wCount = self._getItemWordCount(sHandle) + self.propagateCount(sHandle, 0) - isFile = snItem.itemType == nwItemType.FILE - isRoot = snItem.itemType == nwItemType.ROOT - onFile = dnItem.itemType == nwItemType.FILE - inSame = snItem.itemRoot == dnItem.itemRoot - - allowDrop = inSame or isFile - allowDrop &= not (self.dropIndicatorPosition() == QAbstractItemView.OnItem and onFile) - - if allowDrop and not isRoot: - logger.debug("Drag'n'drop of item '%s' accepted", sHandle) - - wCount = int(sItem.data(self.C_COUNT, Qt.UserRole)) - self.propagateCount(sHandle, 0) - - QTreeWidget.dropEvent(self, theEvent) - self._postItemMove(sHandle, wCount) - self._recordLastMove(sItem, pItem, pIndex) - - else: - logger.debug("Drag'n'drop of item '%s' not accepted", sHandle) - - theEvent.ignore() - self.theParent.makeAlert(self.tr( - "The item cannot be moved to that location." - ), nwAlert.ERROR) + QTreeWidget.dropEvent(self, theEvent) + self._postItemMove(sHandle, wCount) + self._recordLastMove(sItem, pItem, pIndex) + sItem.setExpanded(isExpanded) return @@ -841,28 +825,40 @@ class GuiProjectTree(QTreeWidget): # is updated accordingly, and update word count pHandle = trItemP.data(self.C_NAME, Qt.UserRole) nwItemS.setParent(pHandle) - self.theProject.projTree.updateItemData(tHandle) - self.setTreeItemValues(tHandle) - self.propagateCount(tHandle, wCount) - + trItemP.setExpanded(True) logger.debug("The parent of item '%s' has been changed to '%s'", tHandle, pHandle) - # The items dropped into archive or trash should be removed - # from the project index, for all other items, we rescan the - # file to ensure the index is up to date. - if nwItemS.isInactive(): - self.theIndex.deleteHandle(tHandle) - else: - self.theIndex.reIndexHandle(tHandle) + mHandles = self.getTreeFromHandle(tHandle) + logger.debug("A total of %d item(s) were moved", len(mHandles)) + for mHandle in mHandles: + logger.debug("Updating item '%s'", mHandle) + self.theProject.projTree.updateItemData(mHandle) + + # Update the index + if nwItemS.isInactive(): + self.theIndex.deleteHandle(mHandle) + else: + self.theIndex.reIndexHandle(mHandle) + + self.setTreeItemValues(mHandle) # Trigger dependent updates + self.propagateCount(tHandle, wCount) self._setTreeChanged(True) self._emitItemChange(tHandle) return True + def _getItemWordCount(self, tHandle): + """Retrun the word count of a given item handle. + """ + tItem = self._getTreeItem(tHandle) + if tItem is None: + return 0 + return int(tItem.data(self.C_COUNT, Qt.UserRole)) + def _getTreeItem(self, tHandle): - """Returns the QTreeWidgetItem of a given item handle. + """Return the QTreeWidgetItem of a given item handle. """ return self._treeMap.get(tHandle, None) @@ -878,12 +874,17 @@ class GuiProjectTree(QTreeWidget): starting at a given QTreeWidgetItem. """ tHandle = tItem.data(self.C_NAME, Qt.UserRole) + cCount = tItem.childCount() + + # Update tree-related meta data nwItem = self.theProject.projTree[tHandle] - nwItem.setExpanded(tItem.isExpanded()) + nwItem.setExpanded(tItem.isExpanded() and cCount > 0) nwItem.setOrder(tIndex) + theList.append(tHandle) - for i in range(tItem.childCount()): + for i in range(cCount): self._scanChildren(theList, tItem.child(i), i) + return theList def _addTreeItem(self, nwItem, nHandle=None): @@ -910,8 +911,7 @@ class GuiProjectTree(QTreeWidget): self._treeMap[tHandle] = newItem if pHandle is None: if nwItem.itemType == nwItemType.ROOT: - self.addTopLevelItem(newItem) - elif nwItem.itemType == nwItemType.TRASH: + newItem.setFlags(newItem.flags() ^ Qt.ItemIsDragEnabled) self.addTopLevelItem(newItem) else: self.theParent.makeAlert(self.tr( @@ -931,7 +931,7 @@ class GuiProjectTree(QTreeWidget): self._treeMap[pHandle].insertChild(byIndex+1, newItem) else: self._treeMap[pHandle].addChild(newItem) - self.propagateCount(tHandle, nwItem.wordCount) + self.propagateCount(tHandle, nwItem.wordCount, countChildren=True) self.setTreeItemValues(tHandle) newItem.setExpanded(nwItem.isExpanded) @@ -1057,7 +1057,7 @@ class GuiProjectTreeMenu(QMenu): trashHandle = self.theTree.theProject.projTree.trashRoot() - inTrash = theItem.itemParent == trashHandle and trashHandle is not None + inTrash = self.theTree.theProject.projTree.isTrash(theItem.itemHandle) isTrash = theItem.itemHandle == trashHandle and trashHandle is not None isFile = theItem.itemType == nwItemType.FILE diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index 3c180b50..19fe823a 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -639,9 +639,6 @@ class GuiIcons: iconName = "proj_scene" elif tLayout == nwItemLayout.NOTE: iconName = "proj_note" - elif tType == nwItemType.TRASH: - iconName = nwLabels.CLASS_ICON[tClass] - if iconName is None: return QIcon() diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index fabd3867..60fe0d23 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -906,7 +906,7 @@ class GuiMain(QMainWindow): tItem.setCharCount(cC) tItem.setWordCount(wC) tItem.setParaCount(pC) - self.treeView.propagateCount(tItem.itemHandle, wC) + self.treeView.propagateCount(tItem.itemHandle, wC, countChildren=True) self.treeView.setTreeItemValues(tItem.itemHandle) tEnd = time() @@ -1568,11 +1568,17 @@ class GuiMain(QMainWindow): @pyqtSlot("QTreeWidgetItem*", int) def _treeDoubleClick(self, tItem, colNo): """The user double-clicked an item in the tree. If it is a file, - we open it. Otherwise, we do nothing. + we open it. Otherwise, we toggle the expanded status. """ tHandle = self.treeView.getSelectedHandle() if tHandle is not None: - self.openDocument(tHandle, changeFocus=False, doScroll=False) + tItem = self.theProject.projTree[tHandle] + if tItem is None: + return + if tItem.itemType == nwItemType.FILE: + self.openDocument(tHandle, changeFocus=False, doScroll=False) + else: + self.treeView.toggleExpanded(tHandle) return @pyqtSlot() diff --git a/sample/content/636b6aa9b697b.nwd b/sample/content/636b6aa9b697b.nwd index 8fe96042..2927b7d0 100644 --- a/sample/content/636b6aa9b697b.nwd +++ b/sample/content/636b6aa9b697b.nwd @@ -1,5 +1,5 @@ %%~name: Making a Scene -%%~path: e7ded148d6e4a/636b6aa9b697b +%%~path: 6a2d6d5f4f401/636b6aa9b697b %%~kind: NOVEL/DOCUMENT ### Making a Scene diff --git a/sample/content/ae7339df26ded.nwd b/sample/content/ae7339df26ded.nwd index 9b135713..1eb7a65d 100644 --- a/sample/content/ae7339df26ded.nwd +++ b/sample/content/ae7339df26ded.nwd @@ -1,5 +1,5 @@ %%~name: We Found John! -%%~path: e7ded148d6e4a/ae7339df26ded +%%~path: 88706ddc78b1b/ae7339df26ded %%~kind: NOVEL/DOCUMENT ### We Found John! diff --git a/sample/content/bc0cbd2a407f3.nwd b/sample/content/bc0cbd2a407f3.nwd index 3c95e8ff..4ebbca1d 100644 --- a/sample/content/bc0cbd2a407f3.nwd +++ b/sample/content/bc0cbd2a407f3.nwd @@ -1,5 +1,5 @@ %%~name: Another Scene -%%~path: e7ded148d6e4a/bc0cbd2a407f3 +%%~path: 6a2d6d5f4f401/bc0cbd2a407f3 %%~kind: NOVEL/DOCUMENT ### Another Scene diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index 23660870..406fa423 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,13 +1,13 @@ - + Sample Project Sample Project Jane Smith Jay Doh - 1306 - 199 - 65149 + 1327 + 207 + 66285 False @@ -54,15 +54,15 @@ Novel - + Title Page - + Page - + Part One @@ -70,31 +70,31 @@ A Folder - + Chapter One - - + + Making a Scene - - + + Another Scene - - + + Interlude - - + + A Note on Structure - - + + Chapter Two - - + + We Found John! @@ -106,11 +106,11 @@ Main Characters - + John Smith - + Jane Smith @@ -118,15 +118,15 @@ Locations - + Earth - + Space - + Mars @@ -138,15 +138,15 @@ Scenes - + Old File - + Trash - + Delete Me! diff --git a/tests/conftest.py b/tests/conftest.py index c6634f7c..769f855c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -164,9 +164,7 @@ def nwGUI(qtbot, monkeypatch, fncDir, fncConf): """ monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes) monkeypatch.setattr("novelwriter.CONFIG", fncConf) - nwGUI = novelwriter.main( - ["--testmode", "--info", "--config=%s" % fncDir, "--data=%s" % fncDir] - ) + nwGUI = novelwriter.main(["--testmode", "--config=%s" % fncDir, "--data=%s" % fncDir]) qtbot.addWidget(nwGUI) nwGUI.show() qtbot.wait(20) diff --git a/tests/lipsum/nwProject.nwx b/tests/lipsum/nwProject.nwx index d8d7a49e..02e3df49 100644 --- a/tests/lipsum/nwProject.nwx +++ b/tests/lipsum/nwProject.nwx @@ -1,12 +1,12 @@ - + Lorem Ipsum Lorem Ipsum lipsum.com - 24 + 26 24 - 1856 + 1863 False @@ -49,19 +49,19 @@ Novel - + Lorem Ipsum - + Front Matter - + Prologue - + Act One @@ -69,19 +69,19 @@ Chapter One - + Chapter One - + Scene One - + Scene Two - + Interlude @@ -89,19 +89,19 @@ Chapter Two - + Chapter Two - + Scene Three - + Scene Four - + Scene Five @@ -109,7 +109,7 @@ Characters - + Mr. Nobody @@ -117,7 +117,7 @@ Plot - + Main @@ -125,7 +125,7 @@ World - + Ancient Europe diff --git a/tests/minimal/nwProject.nwx b/tests/minimal/nwProject.nwx index 6945dc08..af7595a4 100644 --- a/tests/minimal/nwProject.nwx +++ b/tests/minimal/nwProject.nwx @@ -1,13 +1,13 @@ - + Test Minimal Minimal Jane Doe John Doh - 15 + 17 2 - 146 + 150 True @@ -47,7 +47,7 @@ Novel - + Title Page @@ -55,11 +55,11 @@ New Chapter - + New Chapter - + New Scene diff --git a/tests/reference/coreProject_NewCustomA_nwProject.nwx b/tests/reference/coreProject_NewCustomA_nwProject.nwx index 8747363b..14abf9e2 100644 --- a/tests/reference/coreProject_NewCustomA_nwProject.nwx +++ b/tests/reference/coreProject_NewCustomA_nwProject.nwx @@ -1,5 +1,5 @@ - + Test Custom Test Novel @@ -71,7 +71,7 @@ Entities - + Title Page @@ -79,19 +79,19 @@ Chapter 1 - + Chapter 1 - + Scene 1.1 - + Scene 1.2 - + Scene 1.3 @@ -99,19 +99,19 @@ Chapter 2 - + Chapter 2 - + Scene 2.1 - + Scene 2.2 - + Scene 2.3 @@ -119,19 +119,19 @@ Chapter 3 - + Chapter 3 - + Scene 3.1 - + Scene 3.2 - + Scene 3.3 diff --git a/tests/reference/coreProject_NewCustomB_nwProject.nwx b/tests/reference/coreProject_NewCustomB_nwProject.nwx index 7f397e85..bca6ea80 100644 --- a/tests/reference/coreProject_NewCustomB_nwProject.nwx +++ b/tests/reference/coreProject_NewCustomB_nwProject.nwx @@ -1,5 +1,5 @@ - + Test Custom Test Novel @@ -71,31 +71,31 @@ Entities - + Title Page - + Scene 1 - + Scene 2 - + Scene 3 - + Scene 4 - + Scene 5 - + Scene 6 diff --git a/tests/reference/coreProject_NewFile_nwProject.nwx b/tests/reference/coreProject_NewFile_nwProject.nwx index 86f9cf11..d253ebcc 100644 --- a/tests/reference/coreProject_NewFile_nwProject.nwx +++ b/tests/reference/coreProject_NewFile_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project @@ -57,7 +57,7 @@ World - + Title Page @@ -65,19 +65,19 @@ New Chapter - + New Chapter - + New Scene - + Hello - + Jane diff --git a/tests/reference/coreProject_NewMinimal_nwProject.nwx b/tests/reference/coreProject_NewMinimal_nwProject.nwx index 37a5428b..a6711a84 100644 --- a/tests/reference/coreProject_NewMinimal_nwProject.nwx +++ b/tests/reference/coreProject_NewMinimal_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project @@ -57,7 +57,7 @@ World - + Title Page @@ -65,11 +65,11 @@ New Chapter - + New Chapter - + New Scene diff --git a/tests/reference/coreProject_NewRoot_nwProject.nwx b/tests/reference/coreProject_NewRoot_nwProject.nwx index 67c49f05..2ab62301 100644 --- a/tests/reference/coreProject_NewRoot_nwProject.nwx +++ b/tests/reference/coreProject_NewRoot_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project @@ -57,7 +57,7 @@ World - + Title Page @@ -65,11 +65,11 @@ New Chapter - + New Chapter - + New Scene diff --git a/tests/reference/guiEditor_Main_Final_nwProject.nwx b/tests/reference/guiEditor_Main_Final_nwProject.nwx index 3900c6d2..c4ba847c 100644 --- a/tests/reference/guiEditor_Main_Final_nwProject.nwx +++ b/tests/reference/guiEditor_Main_Final_nwProject.nwx @@ -1,11 +1,11 @@ - + New Project 5 2 - 4 + 3 True @@ -45,7 +45,7 @@ Novel - + Title Page @@ -53,11 +53,11 @@ New Chapter - + New Chapter - + New Scene @@ -65,7 +65,7 @@ Plot - + New Note @@ -73,7 +73,7 @@ Characters - + New Note @@ -81,11 +81,11 @@ World - + New Note - - + + Trash diff --git a/tests/reference/guiEditor_Main_Initial_nwProject.nwx b/tests/reference/guiEditor_Main_Initial_nwProject.nwx index 66a4c94e..1a5fd5be 100644 --- a/tests/reference/guiEditor_Main_Initial_nwProject.nwx +++ b/tests/reference/guiEditor_Main_Initial_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project @@ -45,7 +45,7 @@ Novel - + Title Page @@ -53,11 +53,11 @@ New Chapter - + New Chapter - + New Scene diff --git a/tests/reference/guiProjSettings_Dialog_nwProject.nwx b/tests/reference/guiProjSettings_Dialog_nwProject.nwx index 77d01d45..326c63e5 100644 --- a/tests/reference/guiProjSettings_Dialog_nwProject.nwx +++ b/tests/reference/guiProjSettings_Dialog_nwProject.nwx @@ -1,5 +1,5 @@ - + Project Name Project Title @@ -51,7 +51,7 @@ Novel - + Title Page @@ -59,11 +59,11 @@ New Chapter - + New Chapter - + New Scene diff --git a/tests/test_base/test_base_common.py b/tests/test_base/test_base_common.py index d7ad4119..0ce153b4 100644 --- a/tests/test_base/test_base_common.py +++ b/tests/test_base/test_base_common.py @@ -161,6 +161,7 @@ def testBaseCommon_IsItemClass(): assert isItemClass("ARCHIVE") is True assert isItemClass("TRASH") is True + # Invalid assert isItemClass("None") is False assert isItemClass(None) is False assert isItemClass("STUFF") is False @@ -176,8 +177,11 @@ def testBaseCommon_IsItemType(): assert isItemType("ROOT") is True assert isItemType("FOLDER") is True assert isItemType("FILE") is True - assert isItemType("TRASH") is True + # Deprecated Type + assert isItemType("TRASH") is False + + # Invalid assert isItemType("None") is False assert isItemType(None) is False assert isItemType("STUFF") is False @@ -193,6 +197,16 @@ def testBaseCommon_IsItemLayout(): assert isItemLayout("DOCUMENT") is True assert isItemLayout("NOTE") is True + # Deprecated Layouts + assert isItemLayout("TITLE") is False + assert isItemLayout("PAGE") is False + assert isItemLayout("BOOK") is False + assert isItemLayout("PARTITION") is False + assert isItemLayout("UNNUMBERED") is False + assert isItemLayout("CHAPTER") is False + assert isItemLayout("SCENE") is False + + # Invalid assert isItemLayout("None") is False assert isItemLayout(None) is False assert isItemLayout("STUFF") is False diff --git a/tests/test_core/test_core_item.py b/tests/test_core/test_core_item.py index 572b31d7..fbc0ded3 100644 --- a/tests/test_core/test_core_item.py +++ b/tests/test_core/test_core_item.py @@ -283,8 +283,6 @@ def testCoreItem_TypeSetter(mockGUI): assert theItem.itemType == nwItemType.FOLDER theItem.setType("FILE") assert theItem.itemType == nwItemType.FILE - theItem.setType("TRASH") - assert theItem.itemType == nwItemType.TRASH # Alternative theItem.setType(nwItemType.ROOT) @@ -500,8 +498,9 @@ def testCoreItem_XMLPackUnpack(mockGUI, caplog, mockRnd): assert etree.tostring(xContent, pretty_print=False, encoding="utf-8") == ( b'' b'A Name' + b'type="FILE" class="NOVEL" layout="NOTE">A Name' b'' ) % bytes(importKeys[3], encoding="utf8") @@ -711,4 +710,8 @@ def testCoreItem_ConvertFromFmt13(mockGUI): assert theItem.itemType == nwItemType.FILE assert theItem.itemLayout == nwItemLayout.DOCUMENT + # Deprecated Type + theItem.setType("TRASH") + assert theItem.itemType == nwItemType.ROOT + # END Test testCoreItem_ConvertFromFmt13 diff --git a/tests/test_core/test_core_tree.py b/tests/test_core/test_core_tree.py index c70cc4bb..5c05f679 100644 --- a/tests/test_core/test_core_tree.py +++ b/tests/test_core/test_core_tree.py @@ -76,7 +76,7 @@ def mockItems(mockGUI, mockRnd): itemF = NWItem(theProject) itemF._name = "Trash" - itemF._type = nwItemType.TRASH + itemF._type = nwItemType.ROOT itemF._class = nwItemClass.TRASH itemF._expanded = False @@ -172,7 +172,7 @@ def testCoreTree_BuildTree(mockGUI, mockItems): # Try to add another trash folder itemT = NWItem(theProject) itemT._name = "Trash" - itemT._type = nwItemType.TRASH + itemT._type = nwItemType.ROOT itemT._class = nwItemClass.TRASH itemT._expanded = False @@ -353,12 +353,6 @@ def testCoreTree_Stats(mockGUI, mockItems): assert novelWords == 550 assert noteWords == 400 - # Count types - nRoot, nFolder, nFile = theTree.countTypes() - assert nRoot == 3 - assert nFolder == 1 - assert nFile == 3 - # END Test testCoreTree_Stats @@ -419,25 +413,25 @@ def testCoreTree_XMLPackUnpack(mockGUI, mockItems): b'type="FOLDER" class="NOVEL">Act One' b'Chapter One' b'Scene One' b'Outtakes' - b'Trash' b'Characters' b'Jane Doe' b'' b'' diff --git a/tests/test_gui/test_gui_projtree.py b/tests/test_gui/test_gui_projtree.py index d7d44a78..84563086 100644 --- a/tests/test_gui/test_gui_projtree.py +++ b/tests/test_gui/test_gui_projtree.py @@ -304,9 +304,7 @@ def testGuiProjTree_DeleteItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockR # Delete item without focus -> blocked monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: False) nwTree.setSelectedHandle("0000000000012") - caplog.clear() assert nwTree.deleteItem() is False - assert "blocked" in caplog.text monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True) # No selection made @@ -399,10 +397,8 @@ def testGuiProjTree_DeleteItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockR # =========== # Try to empty trash that is already empty - caplog.clear() assert nwTree.getTreeFromHandle(trashHandle) == [trashHandle] assert nwTree.emptyTrash() is False - assert "already empty" in caplog.text # Move the two remaining scene documents to trash assert nwTree.deleteItem("000000000000f") is True