diff --git a/nw/enum.py b/nw/enum.py index 63be9e73..61540882 100644 --- a/nw/enum.py +++ b/nw/enum.py @@ -38,15 +38,15 @@ class nwItemClass(Enum): class nwItemLayout(Enum): - NO_LAYOUT = 0 - TITLE = 1 - BOOK = 2 - PAGE = 3 - PARTITION = 4 - UNNUMBERED = 5 - CHAPTER = 6 - SCENE = 7 - NOTE = 8 + NO_LAYOUT = 0 + TITLE = 1 + BOOK = 2 + PAGE = 3 + PARTITION = 4 + UNNUMBERED = 5 + CHAPTER = 6 + SCENE = 7 + NOTE = 8 # END Enum nwItemLayout diff --git a/nw/gui/doctree.py b/nw/gui/doctree.py index c35d443c..8844866c 100644 --- a/nw/gui/doctree.py +++ b/nw/gui/doctree.py @@ -92,11 +92,8 @@ class GuiDocTree(QTreeWidget): def newTreeItem(self, itemType, itemClass): pHandle = self.getSelectedHandle() - if pHandle is None: - self.makeAlert("No valid parent item selected", nwAlert.ERROR) - return False - if itemClass is None: + if itemClass is None and pHandle is not None: itemClass = self.theProject.getItem(pHandle).itemClass if itemClass is None: self.makeAlert("Failed to find an appropriate item class for item %s" % pHandle, nwAlert.BUG) @@ -296,8 +293,7 @@ class GuiDocTree(QTreeWidget): def buildTree(self): self.clear() - for tHandle in self.theProject.treeOrder: - nwItem = self.theProject.projTree[tHandle] + for nwItem in self.theProject.getProjectItems(): self._addTreeItem(nwItem) return True diff --git a/nw/project/project.py b/nw/project/project.py index f468e73d..a2462d4d 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -368,6 +368,47 @@ class NWProject(): logger.error("No tree item with handle %s" % str(tHandle)) return None + def getProjectItems(self): + """This function is called from the tree view when building the tree. Each item in the + project is returned in the order saved in the project file, but first it checks that it has + a parent item already sent to the tree. + """ + sentItems = [] + iterItems = self.treeOrder.copy() + n = 0 + nMax = len(iterItems) + while n < nMax: + tHandle = iterItems[n] + tItem = self.getItem(tHandle) + n += 1 + if n > 10000: + return # Just in case + if tItem is None: + # Technically a bug since treeOrder is built from the same data as projTree + continue + elif tItem.parHandle is None: + # Item is a root, or already been identified as an orphaned item + sentItems.append(tHandle) + yield tItem + elif tItem.parHandle in sentItems: + # Item's parent has been sent, so all is fine + sentItems.append(tHandle) + yield tItem + elif tItem.parHandle in iterItems: + # Item's parent exists, but hasn't been sent yet, so add it again to the end + logger.warning("Item %s found before its parent" % tHandle) + iterItems.append(tHandle) + nMax = len(iterItems) + else: + # Item is orphaned + logger.error("Item %s has no parent in current tree" % tHandle) + tItem.setParent(None) + yield tItem + + ## + # Class Methods + ## + def findRootItem(self, theClass): for aRoot in self.treeRoots: if theClass == self.projTree[aRoot].itemClass: diff --git a/sample/sampleNovel/nwProject.nwx b/sample/sampleNovel/nwProject.nwx index 0c44701b..0d421f0e 100644 --- a/sample/sampleNovel/nwProject.nwx +++ b/sample/sampleNovel/nwProject.nwx @@ -1,5 +1,5 @@ - + Sample Project Sample Project @@ -8,10 +8,10 @@ True - 636b6aa9b697b + 4cd0bd12b087d 636b6aa9b697b - + Novel ROOT @@ -112,55 +112,43 @@ 1 0 - + Locations ROOT WORLD 0 True - + Earth FILE WORLD 0 False NOTE - 66 - 13 - 1 + 0 + 0 + 0 0 - + Trash TRASH TRASH 0 True - - Orphaned File 1 + + Orphaned File 2 FILE NO_CLASS 0 False NO_LAYOUT - 0 - 0 + 14 + 3 0 - 0 - - - New File - FILE - CHARACTER - 0 - False - NOTE - 0 - 0 - 0 - 0 + 1