From b62cfc017ba18ffd41ca04fc88310c4ccddf094b Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 Aug 2020 16:10:30 +0200 Subject: [PATCH 1/9] Added the archive root folder type --- nw/constants/constants.py | 3 +++ nw/constants/enum.py | 3 ++- nw/gui/mainmenu.py | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/nw/constants/constants.py b/nw/constants/constants.py index cd7bf350..a8859873 100644 --- a/nw/constants/constants.py +++ b/nw/constants/constants.py @@ -84,6 +84,7 @@ class nwLabels(): nwItemClass.OBJECT : "Objects", nwItemClass.ENTITY : "Entity", nwItemClass.CUSTOM : "Custom", + nwItemClass.ARCHIVE : "Outtakes", nwItemClass.TRASH : "Trash", } CLASS_FLAG = { @@ -96,6 +97,7 @@ class nwLabels(): nwItemClass.OBJECT : "O", nwItemClass.ENTITY : "E", nwItemClass.CUSTOM : "X", + nwItemClass.ARCHIVE : "U", nwItemClass.TRASH : "R", } CLASS_ICON = { @@ -108,6 +110,7 @@ class nwLabels(): nwItemClass.OBJECT : "cls_object", nwItemClass.ENTITY : "cls_entity", nwItemClass.CUSTOM : "cls_custom", + nwItemClass.ARCHIVE : "cls_archive", nwItemClass.TRASH : "cls_trash", } LAYOUT_NAME = { diff --git a/nw/constants/enum.py b/nw/constants/enum.py index ea40c9bf..49d76f5e 100644 --- a/nw/constants/enum.py +++ b/nw/constants/enum.py @@ -48,7 +48,8 @@ class nwItemClass(Enum): OBJECT = 6 ENTITY = 7 CUSTOM = 8 - TRASH = 9 + ARCHIVE = 9 + TRASH = 10 # END Enum nwItemClass diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py index 99a4b5c9..d7a0a833 100644 --- a/nw/gui/mainmenu.py +++ b/nw/gui/mainmenu.py @@ -245,6 +245,7 @@ class GuiMainMenu(QMenuBar): self.rootItems[nwItemClass.OBJECT] = QAction("Object Root", self.rootMenu) self.rootItems[nwItemClass.ENTITY] = QAction("Entity Root", self.rootMenu) self.rootItems[nwItemClass.CUSTOM] = QAction("Custom Root", self.rootMenu) + self.rootItems[nwItemClass.ARCHIVE] = QAction("Outtakes Root", self.rootMenu) nCount = 0 for itemClass in self.rootItems.keys(): nCount += 1 # This forces the lambdas to be unique From e0a824cfb6a4f450e7a7e362af76586eb445712b Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 Aug 2020 16:28:51 +0200 Subject: [PATCH 2/9] Drag and drop of archived files now works --- nw/gui/projtree.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py index a4a9b8f7..5fd83f5e 100644 --- a/nw/gui/projtree.py +++ b/nw/gui/projtree.py @@ -663,14 +663,16 @@ class GuiProjectTree(QTreeWidget): self.makeAlert("The item cannot be moved to that location.", nwAlert.ERROR) return - wCount = int(sItem.text(self.C_COUNT)) - isSame = snItem.itemClass == dnItem.itemClass - isNone = snItem.itemClass == nwItemClass.NO_CLASS - isNote = snItem.itemLayout == nwItemLayout.NOTE - onFile = dnItem.itemType == nwItemType.FILE - isRoot = snItem.itemType == nwItemType.ROOT + wCount = int(sItem.text(self.C_COUNT)) + isSame = snItem.itemClass == dnItem.itemClass + isNone = snItem.itemClass == nwItemClass.NO_CLASS + isNote = snItem.itemLayout == nwItemLayout.NOTE + onFile = dnItem.itemType == nwItemType.FILE + isRoot = snItem.itemType == nwItemType.ROOT + isArch = snItem.itemClass == nwItemClass.ARCHIVE + isArch |= dnItem.itemClass == nwItemClass.ARCHIVE isOnTop = self.dropIndicatorPosition() == QAbstractItemView.OnItem - if (isSame or isNone or isNote) and not (onFile and isOnTop) and not isRoot: + if (isSame or isNone or isNote or isArch) and not (onFile and isOnTop) and not isRoot: logger.debug("Drag'n'drop of item %s accepted" % sHandle) self.propagateCount(sHandle, 0) QTreeWidget.dropEvent(self, theEvent) @@ -679,7 +681,7 @@ class GuiProjectTree(QTreeWidget): self._cleanOrphanedRoot() else: self._updateItemParent(sHandle) - if not isSame: + if not isSame and not isArch: logger.debug("Item %s class has been changed from %s to %s" % ( sHandle, snItem.itemClass.name, From 65131e87c7622805b48f6608be9f052275ca3359 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 Aug 2020 16:51:07 +0200 Subject: [PATCH 3/9] The deleted and outtake files are now properly handled by the index --- nw/core/index.py | 23 +++++++++++++++++++++++ nw/gui/projtree.py | 34 ++++++++++++++++++++++++---------- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/nw/core/index.py b/nw/core/index.py index c542a459..5b7cc05c 100644 --- a/nw/core/index.py +++ b/nw/core/index.py @@ -34,6 +34,7 @@ from time import time from nw.constants import ( nwFiles, nwKeyWords, nwItemType, nwItemClass, nwItemLayout, nwAlert ) +from nw.core.document import NWDoc from nw.core.tools import countWords logger = logging.getLogger(__name__) @@ -106,6 +107,8 @@ class NWIndex(): def deleteHandle(self, tHandle): """Delete all entries of a given document handle. """ + logger.debug("Removing item %s from the index" % tHandle) + delTags = [] for tTag in self.tagIndex: if self.tagIndex[tTag][1] == tHandle: @@ -121,6 +124,26 @@ class NWIndex(): return + def reIndexHandle(self, tHandle): + """Put a file back into the index. This is used when files are + moved from the archive or trash folders back into the active + project. + """ + logger.debug("Re-indexing item %s" % tHandle) + + tItem = self.theProject.projTree[tHandle] + if tItem is None: + return False + if tItem.itemType != nwItemType.FILE: + return False + + theDoc = NWDoc(self.theProject, self.theParent) + theText = theDoc.openDocument(tHandle, showStatus=False) + if theText: + self.scanText(tHandle, theText) + + return True + ## # Load and Save Index to/from File ## diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py index 5fd83f5e..f80437ed 100644 --- a/nw/gui/projtree.py +++ b/nw/gui/projtree.py @@ -663,25 +663,30 @@ class GuiProjectTree(QTreeWidget): self.makeAlert("The item cannot be moved to that location.", nwAlert.ERROR) return - wCount = int(sItem.text(self.C_COUNT)) - isSame = snItem.itemClass == dnItem.itemClass - isNone = snItem.itemClass == nwItemClass.NO_CLASS - isNote = snItem.itemLayout == nwItemLayout.NOTE - onFile = dnItem.itemType == nwItemType.FILE - isRoot = snItem.itemType == nwItemType.ROOT - isArch = snItem.itemClass == nwItemClass.ARCHIVE - isArch |= dnItem.itemClass == nwItemClass.ARCHIVE + wCount = int(sItem.text(self.C_COUNT)) + isSame = snItem.itemClass == dnItem.itemClass + isNone = snItem.itemClass == nwItemClass.NO_CLASS + isNote = snItem.itemLayout == nwItemLayout.NOTE + onFile = dnItem.itemType == nwItemType.FILE + isRoot = snItem.itemType == nwItemType.ROOT + onFree = dnItem.itemClass == nwItemClass.ARCHIVE + onFree |= dnItem.itemClass == nwItemClass.TRASH isOnTop = self.dropIndicatorPosition() == QAbstractItemView.OnItem - if (isSame or isNone or isNote or isArch) and not (onFile and isOnTop) and not isRoot: + if (isSame or isNone or isNote or onFree) and not (onFile and isOnTop) and not isRoot: logger.debug("Drag'n'drop of item %s accepted" % sHandle) self.propagateCount(sHandle, 0) QTreeWidget.dropEvent(self, theEvent) + + # Handle orphaned files differently than tracked files if isNone: self._moveOrphanedItem(sHandle, dHandle) self._cleanOrphanedRoot() else: self._updateItemParent(sHandle) - if not isSame and not isArch: + + # If the item does not have the same class as the target, + # and the target is not a free root folder, update its class + if not isSame and not onFree: logger.debug("Item %s class has been changed from %s to %s" % ( sHandle, snItem.itemClass.name, @@ -689,7 +694,16 @@ class GuiProjectTree(QTreeWidget): )) snItem.setClass(dnItem.itemClass) self.setTreeItemValues(sHandle) + self.propagateCount(sHandle, wCount) + + # The items dropped into archive or trash should be removed + # from the project index + if onFree: + self.theParent.theIndex.deleteHandle(sHandle) + else: + self.theParent.theIndex.reIndexHandle(sHandle) + else: logger.debug("Drag'n'drop of item %s not accepted" % sHandle) self.makeAlert("The item cannot be moved to that location.", nwAlert.ERROR) From 68a7dd439078b00e534e74fe42db12ddf35c88d9 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 Aug 2020 17:25:11 +0200 Subject: [PATCH 4/9] Fixed menu entries and drop options for trash and archive folders --- nw/core/index.py | 11 +++++++++++ nw/core/tree.py | 6 ++---- nw/gui/projtree.py | 18 +++++++++++++++--- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/nw/core/index.py b/nw/core/index.py index 5b7cc05c..6962dbb7 100644 --- a/nw/core/index.py +++ b/nw/core/index.py @@ -267,13 +267,24 @@ class NWIndex(): files before we save them, unless we're rebuilding the index. """ theItem = self.theProject.projTree[tHandle] + theRoot = self.theProject.projTree.getRootItem(tHandle) if theItem is None: + logger.error("Not indexing unknown item %s" % tHandle) return False if theItem.itemType != nwItemType.FILE: + logger.error("Not indexing non-file item %s" % tHandle) return False if theItem.parHandle == self.theProject.projTree.trashRoot(): + logger.error("Not indexing trash item %s" % tHandle) return False if theItem.itemLayout == nwItemLayout.NO_LAYOUT: + logger.error("Not indexing no-layout item %s" % tHandle) + return False + if theRoot is None: + logger.error("Not indexing homeless item %s" % tHandle) + return False + if theRoot.itemClass == nwItemClass.ARCHIVE: + logger.error("Not indexing archived item %s" % tHandle) return False itemClass = theItem.itemClass diff --git a/nw/core/tree.py b/nw/core/tree.py index 74080bd3..3181892a 100644 --- a/nw/core/tree.py +++ b/nw/core/tree.py @@ -245,12 +245,10 @@ class NWTree(): if tItem is not None: for i in range(200): if tItem.parHandle is None: - return tHandle + return tItem else: tHandle = tItem.parHandle - tItem = self.__getitem__(tHandle) - if tItem is None: - return tHandle + tItem = self.__getitem__(tHandle) return None def getItemPath(self, tHandle): diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py index f80437ed..bcc81036 100644 --- a/nw/gui/projtree.py +++ b/nw/gui/projtree.py @@ -201,7 +201,17 @@ class GuiProjectTree(QTreeWidget): if pHandle == self.theProject.projTree.trashRoot(): self.makeAlert( - "Cannot add new files or folders to the trash folder.", nwAlert.ERROR + "Cannot add new files or folders to the %s folder." % ( + nwLabels.CLASS_NAME[nwItemClass.TRASH] + ), nwAlert.ERROR + ) + return False + + if pItem.itemClass == nwItemClass.ARCHIVE: + self.makeAlert( + "Cannot add new files or folders to the %s folder." % ( + nwLabels.CLASS_NAME[nwItemClass.ARCHIVE] + ), nwAlert.ERROR ) return False @@ -671,6 +681,7 @@ class GuiProjectTree(QTreeWidget): isRoot = snItem.itemType == nwItemType.ROOT onFree = dnItem.itemClass == nwItemClass.ARCHIVE onFree |= dnItem.itemClass == nwItemClass.TRASH + onFree &= snItem.itemType == nwItemType.FILE isOnTop = self.dropIndicatorPosition() == QAbstractItemView.OnItem if (isSame or isNone or isNote or onFree) and not (onFile and isOnTop) and not isRoot: logger.debug("Drag'n'drop of item %s accepted" % sHandle) @@ -944,14 +955,15 @@ class GuiProjectTreeMenu(QMenu): inTrash = theItem.parHandle == trashHandle isTrash = theItem.itemHandle == trashHandle isFile = theItem.itemType == nwItemType.FILE + isArch = theItem.itemClass == nwItemClass.ARCHIVE isOrph = isFile and theItem.parHandle is None showOpen = isFile showView = isFile showEdit = not isTrash and not isOrph showExport = isFile and not inTrash and not isOrph - showNewFile = not isTrash and not inTrash and not isOrph - showNewFolder = not isTrash and not inTrash and not isOrph + showNewFile = not isTrash and not inTrash and not isOrph and not isArch + showNewFolder = not isTrash and not inTrash and not isOrph and not isArch showDelete = not isTrash showEmpty = isTrash From cc3c938e16fde37daa5e0dd0351dc4196123cd92 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 Aug 2020 17:39:18 +0200 Subject: [PATCH 5/9] Fix build to exclude archived files --- nw/core/tree.py | 12 ++++++++++++ nw/gui/build.py | 2 ++ 2 files changed, 14 insertions(+) diff --git a/nw/core/tree.py b/nw/core/tree.py index 3181892a..aab0e563 100644 --- a/nw/core/tree.py +++ b/nw/core/tree.py @@ -67,6 +67,7 @@ class NWTree(): self._treeOrder = [] self._treeRoots = [] self._trashRoot = None + self._archRoot = None self._theLength = 0 self._theIndex = 0 self._treeChanged = False @@ -96,6 +97,9 @@ class NWTree(): if nwItem.itemType == nwItemType.ROOT: logger.verbose("Entry %s is a root item" % str(tHandle)) self._treeRoots.append(tHandle) + if nwItem.itemClass == nwItemClass.ARCHIVE: + logger.verbose("Entry %s is the archive folder" % str(tHandle)) + self._archRoot = tHandle if nwItem.itemType == nwItemType.TRASH: if self._trashRoot is None: @@ -211,6 +215,14 @@ class NWTree(): return self._trashRoot return None + def archiveRoot(self): + """Returns the handle of the archive folder, or None if there + isn't one. + """ + if self._archRoot: + return self._archRoot + return None + def findRoot(self, theClass): """Find the root item for a given class. Note: This returns the first item for class CUSTOM. diff --git a/nw/gui/build.py b/nw/gui/build.py index 9bc09e61..c5949e4e 100644 --- a/nw/gui/build.py +++ b/nw/gui/build.py @@ -478,6 +478,7 @@ class GuiBuildNovel(QDialog): noteRoot = noteFiles noteRoot &= tItem.itemType == nwItemType.ROOT noteRoot &= tItem.itemClass != nwItemClass.NOVEL + noteRoot &= tItem.itemClass != nwItemClass.ARCHIVE try: if noteRoot: @@ -551,6 +552,7 @@ class GuiBuildNovel(QDialog): isNone |= theItem.itemClass == nwItemClass.NO_CLASS isNone |= theItem.itemClass == nwItemClass.TRASH isNone |= theItem.parHandle == self.theProject.projTree.trashRoot() + isNone |= theItem.parHandle == self.theProject.projTree.archiveRoot() isNone |= theItem.parHandle is None isNote = theItem.itemLayout == nwItemLayout.NOTE isNovel = not isNone and not isNote From 3f47aef77b54d634a07de9a17642e12e36939678 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 Aug 2020 17:45:36 +0200 Subject: [PATCH 6/9] Added an icon for the outtakes folder --- nw/assets/icons/typicons_colour_dark/icons.conf | 1 + nw/assets/icons/typicons_colour_light/icons.conf | 1 + nw/assets/icons/typicons_grey_dark/icons.conf | 1 + nw/assets/icons/typicons_grey_light/icons.conf | 1 + nw/gui/build.py | 1 - nw/gui/theme.py | 1 + 6 files changed, 5 insertions(+), 1 deletion(-) diff --git a/nw/assets/icons/typicons_colour_dark/icons.conf b/nw/assets/icons/typicons_colour_dark/icons.conf index c4167b90..8432bf1a 100644 --- a/nw/assets/icons/typicons_colour_dark/icons.conf +++ b/nw/assets/icons/typicons_colour_dark/icons.conf @@ -25,6 +25,7 @@ cls_timeline = calendar.svg cls_object = key.svg cls_entity = flag.svg cls_custom = star.svg +cls_archive = delete.svg cls_trash = trash.svg proj_document = document-text.svg proj_folder = folder.svg diff --git a/nw/assets/icons/typicons_colour_light/icons.conf b/nw/assets/icons/typicons_colour_light/icons.conf index be0b1853..eb0f9b2e 100644 --- a/nw/assets/icons/typicons_colour_light/icons.conf +++ b/nw/assets/icons/typicons_colour_light/icons.conf @@ -25,6 +25,7 @@ cls_timeline = calendar.svg cls_object = key.svg cls_entity = flag.svg cls_custom = star.svg +cls_archive = delete.svg cls_trash = trash.svg proj_document = document-text.svg proj_folder = folder.svg diff --git a/nw/assets/icons/typicons_grey_dark/icons.conf b/nw/assets/icons/typicons_grey_dark/icons.conf index fba00697..5fa6d680 100644 --- a/nw/assets/icons/typicons_grey_dark/icons.conf +++ b/nw/assets/icons/typicons_grey_dark/icons.conf @@ -25,6 +25,7 @@ cls_timeline = calendar.svg cls_object = key.svg cls_entity = flag.svg cls_custom = star.svg +cls_archive = delete.svg cls_trash = trash.svg proj_document = document-text.svg proj_folder = folder.svg diff --git a/nw/assets/icons/typicons_grey_light/icons.conf b/nw/assets/icons/typicons_grey_light/icons.conf index 62aba87f..4363e16f 100644 --- a/nw/assets/icons/typicons_grey_light/icons.conf +++ b/nw/assets/icons/typicons_grey_light/icons.conf @@ -25,6 +25,7 @@ cls_timeline = calendar.svg cls_object = key.svg cls_entity = flag.svg cls_custom = star.svg +cls_archive = delete.svg cls_trash = trash.svg proj_document = document-text.svg proj_folder = folder.svg diff --git a/nw/gui/build.py b/nw/gui/build.py index c5949e4e..81af3fa4 100644 --- a/nw/gui/build.py +++ b/nw/gui/build.py @@ -540,7 +540,6 @@ class GuiBuildNovel(QDialog): * Items that appear in the TRASH folder or have parent set to None (orphaned files). """ - if theItem is None: return False diff --git a/nw/gui/theme.py b/nw/gui/theme.py index a368eaf6..fd2826a0 100644 --- a/nw/gui/theme.py +++ b/nw/gui/theme.py @@ -514,6 +514,7 @@ class GuiIcons: "cls_object" : (QStyle.SP_DriveHDIcon, "drive-harddisk"), "cls_entity" : (QStyle.SP_DriveHDIcon, "drive-harddisk"), "cls_custom" : (QStyle.SP_DriveHDIcon, "drive-harddisk"), + "cls_archive" : (QStyle.SP_DriveHDIcon, "drive-harddisk"), "cls_trash" : (QStyle.SP_DriveHDIcon, "drive-harddisk"), "proj_document" : (QStyle.SP_FileIcon, "x-office-document"), "proj_folder" : (QStyle.SP_DirIcon, "folder"), From 7b39bc0780bad6a3fbf1398d5585e062c53821a7 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 Aug 2020 17:51:33 +0200 Subject: [PATCH 7/9] Updated sample project with an example of archived files --- sample/ToC.json | 5 ++++ sample/ToC.txt | 1 + sample/content/8a5deb88c0e97.nwd | 4 +++ sample/nwProject.nwx | 47 ++++++++++++++++++++++---------- 4 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 sample/content/8a5deb88c0e97.nwd diff --git a/sample/ToC.json b/sample/ToC.json index 4e6ff3d1..c00f8735 100644 --- a/sample/ToC.json +++ b/sample/ToC.json @@ -29,6 +29,11 @@ "NOVEL", "Chapter Two" ], + [ + "content/8a5deb88c0e97.nwd", + "NOVEL", + "Old File" + ], [ "content/96b68994dfa3d.nwd", "NOVEL", diff --git a/sample/ToC.txt b/sample/ToC.txt index da23e664..92237107 100644 --- a/sample/ToC.txt +++ b/sample/ToC.txt @@ -10,6 +10,7 @@ content/636b6aa9b697b.nwd NOVEL Making a Scene content/6a2d6d5f4f401.nwd NOVEL Chapter One content/88706ddc78b1b.nwd NOVEL Chapter Two + content/8a5deb88c0e97.nwd NOVEL Old File content/96b68994dfa3d.nwd NOVEL A Note on Structure content/974e400180a99.nwd NOVEL Page content/ae7339df26ded.nwd NOVEL We Found John! diff --git a/sample/content/8a5deb88c0e97.nwd b/sample/content/8a5deb88c0e97.nwd new file mode 100644 index 00000000..2ed2609f --- /dev/null +++ b/sample/content/8a5deb88c0e97.nwd @@ -0,0 +1,4 @@ +%%~ 8a5deb88c0e97:6827118336ac1:NOVEL:SCENE:Old File +### Discarded Scene + +If you have files you no longer want in your main project, you can move them to the “Outtakes” folder. This is equivalent to turning off the “Include when building project” switch, just that you also put the file away, although the switch can be ignored when building the project, this folder cannot. diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index a1d6fe7f..05c459a5 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,13 +1,13 @@ - + Sample Project Sample Project Jane Smith Jay Doh - 684 - 125 - 33351 + 713 + 138 + 35134 False @@ -15,8 +15,8 @@ True 636b6aa9b697b 636b6aa9b697b - 1022 - 646 + 1071 + 695 376 B @@ -46,7 +46,7 @@ Main - + Novel ROOT @@ -119,7 +119,7 @@ 1811 318 8 - 1880 + 1364 Another Scene @@ -137,13 +137,13 @@ Interlude FILE NOVEL - Finished + New True UNNUMBERED 633 101 3 - 1238 + 0 A Note on Structure @@ -262,7 +262,26 @@ 1 45 - + + Outtakes + ROOT + ARCHIVE + None + True + + + Old File + FILE + NOVEL + 1st Draft + True + SCENE + 315 + 55 + 1 + 322 + + Trash TRASH TRASH @@ -276,9 +295,9 @@ New True SCENE - 30 - 6 - 1 + 0 + 0 + 0 36 From 00f3909e19c83f0500fec6fca789beb86b9ed215 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 Aug 2020 17:58:40 +0200 Subject: [PATCH 8/9] Fix bug in update available root list when deleting root item --- nw/core/tree.py | 5 +++++ nw/gui/mainmenu.py | 3 +++ nw/gui/projtree.py | 1 + 3 files changed, 9 insertions(+) diff --git a/nw/core/tree.py b/nw/core/tree.py index aab0e563..7d1bef46 100644 --- a/nw/core/tree.py +++ b/nw/core/tree.py @@ -401,7 +401,12 @@ class NWTree(): return False self._treeOrder.remove(tHandle) self._theLength = len(self._treeOrder) + + if tHandle in self._treeRoots: + self._treeRoots.remove(tHandle) + self._setTreeChanged(True) + return True def __contains__(self, tHandle): diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py index d7a0a833..c462c748 100644 --- a/nw/gui/mainmenu.py +++ b/nw/gui/mainmenu.py @@ -75,6 +75,9 @@ class GuiMainMenu(QMenuBar): ## def setAvailableRoot(self): + """Update the list of available root folders and set the ones + that are active. + """ for itemClass in nwItemClass: if itemClass == nwItemClass.NO_CLASS: continue diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py index bcc81036..ab2fe52b 100644 --- a/nw/gui/projtree.py +++ b/nw/gui/projtree.py @@ -469,6 +469,7 @@ class GuiProjectTree(QTreeWidget): tIndex = self.indexOfTopLevelItem(trItemS) if trItemS.childCount() == 0: self.takeTopLevelItem(tIndex) + del self.theProject.projTree[tHandle] self.theParent.mainMenu.setAvailableRoot() self._setTreeChanged(True) else: From f1b2b1766d7c02db7379be6aa9b931e7591be24e Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 Aug 2020 18:17:33 +0200 Subject: [PATCH 9/9] Updated documentation --- docs/source/interface.rst | 21 +++++++++++++++++++++ docs/source/projects.rst | 18 +++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/docs/source/interface.rst b/docs/source/interface.rst index 770b7d59..d0435abf 100644 --- a/docs/source/interface.rst +++ b/docs/source/interface.rst @@ -43,6 +43,27 @@ currently selected item. This panel also includes the latest paragraph and chara addition to the word count. +.. _a_ui_tree_dnd: + +Project Tree Drag and Drop +-------------------------- + +The project tree allows dragging and drop to a certain extent, but it does not allow bulk actions. +This is deliberate to avoid accidentally messing up your project. The project tree has no undo +function. + +Document files and their folders can be rearranged freely within their root folders. Novel files +cannot be moved out of the :guilabel:`Novel` folder, except to :guilabel:`Trash` and the +:guilabel:`Outtakes` folder. Note files can be moved freely anywhere. + +Folders cannot be moved at all outside their root tree. Neither can a folder containing files be +deleted. You must first delete the files. + +Root folders in the project tree cannot be dragged and dropped. However, if you want to reorder +them, you can move them up or down with respect to eachother from the :guilabel:`Tools` menu, or by +pressing :kbd:`Ctrl`:kbd:`Shift` and the :kbd:`Up` or :kbd:`Down` key. + + .. _a_ui_edit: Editing and Viewing Documents diff --git a/docs/source/projects.rst b/docs/source/projects.rst index cc3808ec..199ed904 100644 --- a/docs/source/projects.rst +++ b/docs/source/projects.rst @@ -87,7 +87,7 @@ Deleted Documents Deleted document files will be moved into a special :guilabel:`Trash` root folder. Files in the trash folder can then be deleted permanently, either individually, or by emptying the trash from the -menu. +menu. Files in this folder are removed from the project index and cannot be referenced. Folders and root folders can only be deleted when they are empty. Recursive deletion is not supported. @@ -96,6 +96,22 @@ A document file or a folder can be deleted from the :guilabel:`project` menu, or :kbd:`Ctrl`:kbd:`Del`. +.. _a_proj_roots_out: + +Archived Documents (Outtakes) +----------------------------- + +If you don't want to delete a file, or put it in the :guilabel:`Trash` folder where it may be +deleted, but still want it out of your main project tree, you can create an :guilabel:`Outtakes` +root folder from the :guilabel:`project` menu. This folder is similar to the :guilabel:`Trash` +folder in that it doesn't allow subfolders and creating new files. + +You can drag any file to this folder and preserve its settings. The file will always be excluded +from the :guilabel:`Build Novel Project` builds, even with the setting to ignore the excluded files +option. The file is also removed from the project index, so the tags and references defined in it +will not show up anywhere else. + + .. _a_proj_roots_orph: Orphaned Documents