diff --git a/novelwriter/core/tree.py b/novelwriter/core/tree.py index ee57e0db..11842a5a 100644 --- a/novelwriter/core/tree.py +++ b/novelwriter/core/tree.py @@ -265,6 +265,14 @@ class NWTree(): # Tree Root Methods ## + def rootClasses(self): + """Return a set of all root classes in use by the project. + """ + rootClasses = set() + for nwItem in self._treeRoots.values(): + rootClasses.add(nwItem.itemClass) + return rootClasses + def isRoot(self, tHandle): """Check if a handle is a root item. """ diff --git a/novelwriter/gui/outline.py b/novelwriter/gui/outline.py index cdb4c7c2..c29b9ff9 100644 --- a/novelwriter/gui/outline.py +++ b/novelwriter/gui/outline.py @@ -39,7 +39,9 @@ from PyQt5.QtWidgets import ( QWidget, QFrame ) -from novelwriter.enum import nwItemLayout, nwItemType, nwOutline, nwView +from novelwriter.enum import ( + nwItemClass, nwItemLayout, nwItemType, nwOutline, nwView +) from novelwriter.common import checkInt from novelwriter.constants import trConst, nwKeyWords, nwLabels @@ -75,6 +77,7 @@ class GuiOutline(QWidget): # Function Mappings self.getSelectedHandle = self.outlineView.getSelectedHandle + self.updateClasses = self.outlineData.updateClasses return @@ -96,6 +99,7 @@ class GuiOutline(QWidget): def closeOutline(self): self.outlineView.closeOutline() + self.outlineData.updateClasses() return def refreshView(self, overRide=False, novelChanged=False): @@ -307,7 +311,6 @@ class GuiOutlineView(QTreeWidget): tHandle = selItems[0].data(self._colIdx[nwOutline.TITLE], Qt.UserRole) sTitle = selItems[0].data(self._colIdx[nwOutline.LINE], Qt.UserRole) self.theOutline.outlineData.showItem(tHandle, sTitle) - self.theParent.treeView.setSelectedHandle(tHandle) return @@ -824,6 +827,8 @@ class GuiOutlineDetails(QScrollArea): else: self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) + self.updateClasses() + return def clearDetails(self): @@ -846,6 +851,7 @@ class GuiOutlineDetails(QScrollArea): self.objKeyValue.setText("") self.entKeyValue.setText("") self.cstKeyValue.setText("") + self.updateClasses() return def showItem(self, tHandle, sTitle): @@ -895,6 +901,7 @@ class GuiOutlineDetails(QScrollArea): # Slots ## + @pyqtSlot(str) def _tagClicked(self, theLink): """Capture the click of a tag in the right-most column. """ @@ -906,6 +913,34 @@ class GuiOutlineDetails(QScrollArea): self.theParent.docViewer.loadFromTag(theBits[1]) return + @pyqtSlot() + def updateClasses(self): + """Update the visibility status of class details. + """ + usedClasses = self.theProject.projTree.rootClasses() + + pltVisible = nwItemClass.PLOT in usedClasses + timVisible = nwItemClass.TIMELINE in usedClasses + wldVisible = nwItemClass.WORLD in usedClasses + objVisible = nwItemClass.OBJECT in usedClasses + entVisible = nwItemClass.ENTITY in usedClasses + cstVisible = nwItemClass.CUSTOM in usedClasses + + self.pltKeyLabel.setVisible(pltVisible) + self.pltKeyValue.setVisible(pltVisible) + self.timKeyLabel.setVisible(timVisible) + self.timKeyValue.setVisible(timVisible) + self.wldKeyLabel.setVisible(wldVisible) + self.wldKeyValue.setVisible(wldVisible) + self.objKeyLabel.setVisible(objVisible) + self.objKeyValue.setVisible(objVisible) + self.entKeyLabel.setVisible(entVisible) + self.entKeyValue.setVisible(entVisible) + self.cstKeyLabel.setVisible(cstVisible) + self.cstKeyValue.setVisible(cstVisible) + + return + ## # Internal Functions ## diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index b134b901..9cbd5d18 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -51,6 +51,7 @@ class GuiProjectTree(QTreeWidget): novelItemChanged = pyqtSignal() noteItemChanged = pyqtSignal() wordCountsChanged = pyqtSignal() + rootFoldersChanged = pyqtSignal() def __init__(self, theParent): QTreeWidget.__init__(self, theParent) @@ -177,6 +178,7 @@ class GuiProjectTree(QTreeWidget): if itemType == nwItemType.ROOT and isinstance(itemClass, nwItemClass): tHandle = self.theProject.newRoot(itemClass) + self.rootFoldersChanged.emit() elif itemType in (nwItemType.FILE, nwItemType.FOLDER): @@ -450,6 +452,7 @@ class GuiProjectTree(QTreeWidget): self.takeTopLevelItem(tIndex) self._deleteTreeItem(tHandle) self._setTreeChanged(True) + self.rootFoldersChanged.emit() else: self.theParent.makeAlert(self.tr( "Cannot delete root folder. It is not empty. " @@ -541,7 +544,7 @@ class GuiProjectTree(QTreeWidget): else: expIcon = self.theTheme.getIcon("cross") - itempStatus, statusIcon = nwItem.getImportStatus() + itemStatus, statusIcon = nwItem.getImportStatus() hLevel = self.theIndex.getHandleHeaderLevel(tHandle) itemIcon = self.theTheme.getItemIcon( nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel @@ -551,7 +554,7 @@ class GuiProjectTree(QTreeWidget): trItem.setText(self.C_NAME, nwItem.itemName) trItem.setIcon(self.C_EXPORT, expIcon) trItem.setIcon(self.C_STATUS, statusIcon) - trItem.setToolTip(self.C_STATUS, itempStatus) + trItem.setToolTip(self.C_STATUS, itemStatus) if self.mainConf.emphLabels and nwItem.itemLayout == nwItemLayout.DOCUMENT: trFont = trItem.font(self.C_NAME) diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index ea92aacd..8f7814e0 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -126,6 +126,7 @@ class GuiMain(QMainWindow): self.treeView.itemDoubleClicked.connect(self._treeDoubleClick) self.treeView.novelItemChanged.connect(self._treeNovelItemChanged) self.treeView.wordCountsChanged.connect(self._updateStatusWordCount) + self.treeView.rootFoldersChanged.connect(self.projView.updateClasses) self.viewsBar.viewChangeRequested.connect(self._changeView) self.projView.viewChangeRequested.connect(self._changeView) @@ -352,6 +353,7 @@ class GuiMain(QMainWindow): self.rebuildTrees() self.saveProject() self.docEditor.setDictionaries() + self.projView.updateClasses() self.rebuildIndex(beQuiet=True) self.statusBar.setRefTime(self.theProject.projOpened) self.statusBar.setProjectStatus(nwState.GOOD) @@ -499,6 +501,7 @@ class GuiMain(QMainWindow): self.docEditor.toggleSpellCheck(self.theProject.spellCheck) self.mainMenu.setAutoOutline(self.theProject.autoOutline) self.statusBar.setRefTime(self.theProject.projOpened) + self.projView.updateClasses() self._updateStatusWordCount() # Restore previously open documents, if any diff --git a/tests/test_core/test_core_tree.py b/tests/test_core/test_core_tree.py index 5c05f679..23eb7f73 100644 --- a/tests/test_core/test_core_tree.py +++ b/tests/test_core/test_core_tree.py @@ -149,6 +149,11 @@ def testCoreTree_BuildTree(mockGUI, mockItems): assert theTree.isTrash("a000000000003") is True assert theTree.isRoot("a000000000002") is True + # Check that we have the root classes + assert theTree.rootClasses() == { + nwItemClass.NOVEL, nwItemClass.CHARACTER, nwItemClass.ARCHIVE, nwItemClass.TRASH + } + # Check the isTrash function assert theTree.isTrash("0000000000000") is True # Doesn't exist assert theTree.isTrash("a000000000003") is True # This the trash folder