diff --git a/novelwriter/assets/icons/typicons_dark/icons.conf b/novelwriter/assets/icons/typicons_dark/icons.conf index f372c60c..568c5b24 100644 --- a/novelwriter/assets/icons/typicons_dark/icons.conf +++ b/novelwriter/assets/icons/typicons_dark/icons.conf @@ -84,6 +84,7 @@ view_editor = mixed_edit.svg view_novel = typ_book-grey.svg view_outline = typ_puzzle-outline.svg +deco_doc_h0 = nw_deco-h0.svg deco_doc_h1 = nw_deco-h1.svg deco_doc_h2 = nw_deco-h2.svg deco_doc_h3 = nw_deco-h3.svg diff --git a/novelwriter/assets/icons/typicons_light/icons.conf b/novelwriter/assets/icons/typicons_light/icons.conf index 4514eab9..1d6a6c0c 100644 --- a/novelwriter/assets/icons/typicons_light/icons.conf +++ b/novelwriter/assets/icons/typicons_light/icons.conf @@ -84,6 +84,7 @@ view_editor = mixed_edit.svg view_novel = typ_book-grey.svg view_outline = typ_puzzle-outline.svg +deco_doc_h0 = nw_deco-h0.svg deco_doc_h1 = nw_deco-h1.svg deco_doc_h2 = nw_deco-h2.svg deco_doc_h3 = nw_deco-h3.svg diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py index fb81f033..4b470d69 100644 --- a/novelwriter/core/project.py +++ b/novelwriter/core/project.py @@ -97,7 +97,6 @@ class NWProject(): self.autoReplace = {} # Text to auto-replace on exports self.titleFormat = {} # The formatting of titles for exports self.spellCheck = False # Controls the spellcheck-as-you-type feature - self.autoOutline = True # If true, the Project Outline is updated automatically self.statusItems = None # Novel file progress status values self.importItems = None # Note file importance values self.lastEdited = None # The handle of the last file to be edited @@ -258,7 +257,6 @@ class NWProject(): "section": "", } self.spellCheck = False - self.autoOutline = True self.statusItems = NWStatus(NWStatus.STATUS) self.statusItems.write(None, self.tr("New"), (100, 100, 100)) self.statusItems.write(None, self.tr("Note"), (200, 50, 0)) @@ -608,8 +606,6 @@ class NWProject(): self.spellCheck = checkBool(xItem.text, False) elif xItem.tag == "spellLang": self.projSpell = checkString(xItem.text, None, True) - elif xItem.tag == "autoOutline": - self.autoOutline = checkBool(xItem.text, True) elif xItem.tag == "lastEdited": self.lastEdited = checkString(xItem.text, None, True) elif xItem.tag == "lastViewed": @@ -735,7 +731,6 @@ class NWProject(): self._packProjectValue(xSettings, "language", self.projLang) self._packProjectValue(xSettings, "spellCheck", self.spellCheck) self._packProjectValue(xSettings, "spellLang", self.projSpell) - self._packProjectValue(xSettings, "autoOutline", self.autoOutline) self._packProjectValue(xSettings, "lastEdited", self.lastEdited) self._packProjectValue(xSettings, "lastViewed", self.lastViewed) self._packProjectValue(xSettings, "lastNovel", self.lastNovel) @@ -1096,14 +1091,6 @@ class NWProject(): self.setProjectChanged(True) return True - def setAutoOutline(self, theMode): - """Enable/disable automatic update of project outline. - """ - if self.autoOutline != theMode: - self.autoOutline = theMode - self.setProjectChanged(True) - return self.autoOutline - def setTreeOrder(self, newOrder): """A list representing the linear/flattened order of project items in the GUI project tree. The user can rearrange the order @@ -1139,6 +1126,14 @@ class NWProject(): self.setProjectChanged(True) return True + def setLastOutlineViewed(self, tHandle): + """Set last viewed novel root in the outline view. + """ + if self.lastOutline != tHandle: + self.lastOutline = tHandle + self.setProjectChanged(True) + return True + def setStatusColours(self, newCols, delCols): """Update the list of novel file status flags. """ diff --git a/novelwriter/gui/noveltree.py b/novelwriter/gui/noveltree.py index b96f5331..c8d88b88 100644 --- a/novelwriter/gui/noveltree.py +++ b/novelwriter/gui/noveltree.py @@ -69,8 +69,8 @@ class GuiNovelView(QWidget): self.theProject = mainGui.theProject # Build GUI - self.novelTree = GuiNovelTree(self) self.novelBar = GuiNovelToolBar(self) + self.novelTree = GuiNovelTree(self) # Assemble self.outerBox = QVBoxLayout() @@ -93,6 +93,8 @@ class GuiNovelView(QWidget): ## def initSettings(self): + """Initialise GUI elements that depend on specific settings. + """ self.novelTree.initSettings() return @@ -110,7 +112,7 @@ class GuiNovelView(QWidget): return def openProjectTasks(self): - """Run opening project tasks. + """Run open project tasks. """ lastNovel = self.theProject.lastNovel if lastNovel not in self.theProject.tree: @@ -136,8 +138,8 @@ class GuiNovelView(QWidget): self.theProject.options.setValue("GuiNovelView", "lastCol", lastColType) return - def setFocus(self): - """Forward the set focus call to the tree widget. + def setTreeFocus(self): + """Set the focus to the tree widget. """ self.novelTree.setFocus() return @@ -174,7 +176,7 @@ class GuiNovelToolBar(QWidget): self.mainTheme = novelView.mainGui.mainTheme iPx = self.mainTheme.baseIconSize - mPx = self.mainConf.pxInt(3) + mPx = self.mainConf.pxInt(2) self.setContentsMargins(0, 0, 0, 0) self.setAutoFillBackground(True) @@ -396,8 +398,6 @@ class GuiNovelTree(QTreeWidget): self.mainTheme.loadDecoration("deco_doc_h4", pxH=iPx), ] self._pMore = self.mainTheme.loadDecoration("deco_doc_more", pxH=iPx) - self._pActive = self.mainTheme.loadDecoration("deco_more_on", pxH=iPx) - self._pInactive = self.mainTheme.loadDecoration("deco_more_off", pxH=iPx) # Connect signals self.clicked.connect(self._treeItemClicked) diff --git a/novelwriter/gui/outline.py b/novelwriter/gui/outline.py index 0ae253f9..e8514c15 100644 --- a/novelwriter/gui/outline.py +++ b/novelwriter/gui/outline.py @@ -37,16 +37,16 @@ from PyQt5.QtCore import ( Qt, pyqtSignal, pyqtSlot, QSize, QT_TRANSLATE_NOOP ) from PyQt5.QtWidgets import ( - QAbstractItemView, QAction, QGridLayout, QGroupBox, QHBoxLayout, QLabel, - QMenu, QScrollArea, QSplitter, QTreeWidget, QTreeWidgetItem, QVBoxLayout, - QWidget, QFrame, QToolBar, QSizePolicy, QComboBox, QToolButton + QAbstractItemView, QAction, QComboBox, QFrame, QGridLayout, QGroupBox, + QHBoxLayout, QLabel, QMenu, QScrollArea, QSizePolicy, QSplitter, QToolBar, + QToolButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget ) from novelwriter.enum import ( nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline ) from novelwriter.common import checkInt -from novelwriter.constants import trConst, nwKeyWords, nwLabels +from novelwriter.constants import nwHeaders, trConst, nwKeyWords, nwLabels logger = logging.getLogger(__name__) @@ -59,8 +59,9 @@ class GuiOutlineView(QWidget): def __init__(self, mainGui): QWidget.__init__(self, mainGui) - self.mainConf = novelwriter.CONFIG - self.mainGui = mainGui + self.mainConf = novelwriter.CONFIG + self.mainGui = mainGui + self.theProject = mainGui.theProject # Build GUI self.outlineBar = GuiOutlineToolBar(self) @@ -96,33 +97,58 @@ class GuiOutlineView(QWidget): # Methods ## - def splitSizes(self): - return self.splitOutline.sizes() + def initSettings(self): + """Initialise GUI elements that depend on specific settings. + """ + self.outlineTree.initSettings() + self.outlineData.initSettings() + return - def clearOutline(self): + def refreshTree(self): + """Refresh the current tree. + """ + self.outlineTree.refreshTree(rootHandle=self.theProject.lastOutline) + return + + def clearProject(self): + """Clear project-related GUI content. + """ self.outlineData.clearDetails() return - def initOutline(self): - self.outlineTree.initOutline() - self.outlineData.initDetails() + def openProjectTasks(self): + """Run open project tasks. + """ + lastOutline = self.theProject.lastOutline + if not (lastOutline in self.theProject.tree or lastOutline is None): + lastOutline = self.theProject.tree.findRoot(nwItemClass.NOVEL) + + logger.debug("Setting outline tree to root item '%s'", lastOutline) + + self.clearProject() + self.outlineBar.populateNovelList() + self.outlineBar.setCurrentRoot(lastOutline) + return - def closeOutline(self): - self.outlineTree.closeOutline() + def closeProjectTasks(self): + self.outlineTree.closeProjectTasks() self.outlineData.updateClasses() return - def refreshView(self, overRide=False, novelChanged=False): - self.outlineTree.refreshTree(overRide=overRide, novelChanged=novelChanged) - return - - def treeHasFocus(self): - return self.outlineTree.hasFocus() + def splitSizes(self): + return self.splitOutline.sizes() def setTreeFocus(self): + """Set the focus to the tree widget. + """ return self.outlineTree.setFocus() + def treeHasFocus(self): + """Check if the outline tree has focus. + """ + return self.outlineTree.hasFocus() + ## # Public Slots ## @@ -243,6 +269,17 @@ class GuiOutlineToolBar(QToolBar): self.novelValue.addItem(tIcon, self.tr("All Novel Folders"), "") return + def setCurrentRoot(self, rootHandle): + """Set the current active root handle. + """ + if rootHandle is None: + rootIdx = self.novelValue.count() - 1 + else: + rootIdx = self.novelValue.findData(rootHandle) + if rootIdx >= 0: + self.novelValue.setCurrentIndex(rootIdx) + return + def setColumnHiddenState(self, hiddenState): """Forward the change of column hidden states to the menu. """ @@ -313,6 +350,9 @@ class GuiOutlineTree(QTreeWidget): nwOutline.SYNOP: False, } + D_HANDLE = Qt.UserRole + D_TITLE = Qt.UserRole + 1 + hiddenStateChanged = pyqtSignal() activeItemChanged = pyqtSignal(str, str) @@ -337,11 +377,35 @@ class GuiOutlineTree(QTreeWidget): iPx = self.mainTheme.baseIconSize self.setIconSize(QSize(iPx, iPx)) - self.setIndentation(iPx) + self.setIndentation(0) self.treeHead = self.header() self.treeHead.sectionMoved.connect(self._columnMoved) + # Pre-Generate Tree Formatting + fH1 = self.font() + fH1.setBold(True) + fH1.setUnderline(True) + + fH2 = self.font() + fH2.setBold(True) + + self._hFonts = [self.font(), fH1, fH2, self.font(), self.font()] + self._pIndent = [ + self.mainTheme.loadDecoration("deco_doc_h0", pxH=iPx), + self.mainTheme.loadDecoration("deco_doc_h1", pxH=iPx), + self.mainTheme.loadDecoration("deco_doc_h2", pxH=iPx), + self.mainTheme.loadDecoration("deco_doc_h3", pxH=iPx), + self.mainTheme.loadDecoration("deco_doc_h4", pxH=iPx), + ] + self._dIcon = { + "H0": self.mainTheme.getItemIcon(nwItemType.FILE, None, nwItemLayout.DOCUMENT, "H0"), + "H1": self.mainTheme.getItemIcon(nwItemType.FILE, None, nwItemLayout.DOCUMENT, "H1"), + "H2": self.mainTheme.getItemIcon(nwItemType.FILE, None, nwItemLayout.DOCUMENT, "H2"), + "H3": self.mainTheme.getItemIcon(nwItemType.FILE, None, nwItemLayout.DOCUMENT, "H3"), + "H4": self.mainTheme.getItemIcon(nwItemType.FILE, None, nwItemLayout.DOCUMENT, "H4"), + } + # Internals self._treeOrder = [] self._colWidth = {} @@ -351,8 +415,8 @@ class GuiOutlineTree(QTreeWidget): self._firstView = True self._lastBuild = 0 - self.initOutline() - self.clearOutline() + self.initSettings() + self.clearContent() self.hiddenStateChanged.emit() @@ -372,7 +436,7 @@ class GuiOutlineTree(QTreeWidget): # Methods ## - def initOutline(self): + def initSettings(self): """Set or update outline settings. """ # Scroll bars @@ -388,7 +452,7 @@ class GuiOutlineTree(QTreeWidget): return - def clearOutline(self): + def clearContent(self): """Clear the tree and header and set the default values for the columns arrays. """ @@ -426,18 +490,20 @@ class GuiOutlineTree(QTreeWidget): # If the novel index or novel tree has changed since the tree # was last built, we rebuild the tree from the updated index. indexChanged = self.theProject.index.rootChangedSince(rootHandle, self._lastBuild) - doBuild = (novelChanged or indexChanged) and self.theProject.autoOutline - if doBuild or overRide: - logger.debug("Rebuilding Project Outline") - self._populateTree(rootHandle) + if not (novelChanged or indexChanged or overRide): + logger.verbose("No changes have been made to the novel index") + return + + self._populateTree(rootHandle) + self.theProject.setLastOutlineViewed(rootHandle or None) return - def closeOutline(self): + def closeProjectTasks(self): """Called before a project is closed. """ self._saveHeaderState() - self.clearOutline() + self.clearContent() self._firstView = True return @@ -449,7 +515,7 @@ class GuiOutlineTree(QTreeWidget): tHandle = None tLine = 0 if selItem: - tHandle = selItem[0].data(self._colIdx[nwOutline.TITLE], Qt.UserRole) + tHandle = selItem[0].data(self._colIdx[nwOutline.TITLE], self.D_HANDLE) tLine = checkInt(selItem[0].text(self._colIdx[nwOutline.LINE]), 1) - 1 return tHandle, tLine @@ -475,8 +541,8 @@ class GuiOutlineTree(QTreeWidget): """ selItems = self.selectedItems() if selItems: - tHandle = selItems[0].data(self._colIdx[nwOutline.TITLE], Qt.UserRole) - sTitle = selItems[0].data(self._colIdx[nwOutline.LINE], Qt.UserRole) + tHandle = selItems[0].data(self._colIdx[nwOutline.TITLE], self.D_HANDLE) + sTitle = selItems[0].data(self._colIdx[nwOutline.TITLE], self.D_TITLE) self.activeItemChanged.emit(tHandle, sTitle) return @@ -614,8 +680,7 @@ class GuiOutlineTree(QTreeWidget): self.setColumnWidth(self._colIdx[hItem], self._colWidth[hItem]) self.setColumnHidden(self._colIdx[hItem], self._colHidden[hItem]) - # Make sure title column is always visible, - # and handle column always hidden + # Make sure title column is always visible self.setColumnHidden(self._colIdx[nwOutline.TITLE], False) headItem = self.headerItem() @@ -623,101 +688,51 @@ class GuiOutlineTree(QTreeWidget): headItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignRight) headItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignRight) - currTitle = None - currChapter = None - currScene = None - novStruct = self.theProject.index.novelStructure(rootHandle=rootHandle, skipExcl=True) for _, tHandle, sTitle, novIdx in novStruct: - tItem = self._createTreeItem(tHandle, sTitle, novIdx) + iLevel = nwHeaders.H_LEVEL.get(novIdx.level, 0) + dLevel = self.theProject.index.getHandleHeaderLevel(tHandle) + if iLevel == 0: + continue - tLevel = novIdx.level - if tLevel == "H1": - self.addTopLevelItem(tItem) - currTitle = tItem - currChapter = None - currScene = None + trItem = QTreeWidgetItem() + nwItem = self.theProject.tree[tHandle] - elif tLevel == "H2": - if currTitle is None: - self.addTopLevelItem(tItem) - else: - currTitle.addChild(tItem) - currChapter = tItem - currScene = None + trItem.setData(self._colIdx[nwOutline.TITLE], Qt.DecorationRole, self._pIndent[iLevel]) + trItem.setText(self._colIdx[nwOutline.TITLE], novIdx.title) + trItem.setData(self._colIdx[nwOutline.TITLE], self.D_HANDLE, tHandle) + trItem.setData(self._colIdx[nwOutline.TITLE], self.D_TITLE, sTitle) + trItem.setFont(self._colIdx[nwOutline.TITLE], self._hFonts[iLevel]) + trItem.setText(self._colIdx[nwOutline.LEVEL], novIdx.level) + trItem.setIcon(self._colIdx[nwOutline.LABEL], self._dIcon[dLevel]) + trItem.setText(self._colIdx[nwOutline.LABEL], nwItem.itemName) + trItem.setText(self._colIdx[nwOutline.LINE], sTitle[1:].lstrip("0")) + trItem.setText(self._colIdx[nwOutline.SYNOP], novIdx.synopsis) + trItem.setText(self._colIdx[nwOutline.CCOUNT], f"{novIdx.charCount:n}") + trItem.setText(self._colIdx[nwOutline.WCOUNT], f"{novIdx.wordCount:n}") + trItem.setText(self._colIdx[nwOutline.PCOUNT], f"{novIdx.paraCount:n}") + trItem.setTextAlignment(self._colIdx[nwOutline.CCOUNT], Qt.AlignRight) + trItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignRight) + trItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignRight) - elif tLevel == "H3": - if currChapter is None: - if currTitle is None: - self.addTopLevelItem(tItem) - else: - currTitle.addChild(tItem) - else: - currChapter.addChild(tItem) - currScene = tItem + refs = self.theProject.index.getReferences(tHandle, sTitle) + trItem.setText(self._colIdx[nwOutline.POV], ", ".join(refs[nwKeyWords.POV_KEY])) + trItem.setText(self._colIdx[nwOutline.FOCUS], ", ".join(refs[nwKeyWords.FOCUS_KEY])) + trItem.setText(self._colIdx[nwOutline.CHAR], ", ".join(refs[nwKeyWords.CHAR_KEY])) + trItem.setText(self._colIdx[nwOutline.PLOT], ", ".join(refs[nwKeyWords.PLOT_KEY])) + trItem.setText(self._colIdx[nwOutline.TIME], ", ".join(refs[nwKeyWords.TIME_KEY])) + trItem.setText(self._colIdx[nwOutline.WORLD], ", ".join(refs[nwKeyWords.WORLD_KEY])) + trItem.setText(self._colIdx[nwOutline.OBJECT], ", ".join(refs[nwKeyWords.OBJECT_KEY])) + trItem.setText(self._colIdx[nwOutline.ENTITY], ", ".join(refs[nwKeyWords.ENTITY_KEY])) + trItem.setText(self._colIdx[nwOutline.CUSTOM], ", ".join(refs[nwKeyWords.CUSTOM_KEY])) - elif tLevel == "H4": - if currScene is None: - if currChapter is None: - if currTitle is None: - self.addTopLevelItem(tItem) - else: - currTitle.addChild(tItem) - else: - currChapter.addChild(tItem) - else: - currScene.addChild(tItem) - - tItem.setExpanded(True) + self.addTopLevelItem(trItem) self._lastBuild = time() return - def _createTreeItem(self, tHandle, sTitle, novIdx): - """Populate a tree item with all the column values. - """ - nwItem = self.theProject.tree[tHandle] - newItem = QTreeWidgetItem() - hIcon = "doc_%s" % novIdx.level.lower() - - hLevel = self.theProject.index.getHandleHeaderLevel(tHandle) - dIcon = self.mainTheme.getItemIcon(nwItemType.FILE, None, nwItemLayout.DOCUMENT, hLevel) - - cC = int(novIdx.charCount) - wC = int(novIdx.wordCount) - pC = int(novIdx.paraCount) - - newItem.setText(self._colIdx[nwOutline.TITLE], novIdx.title) - newItem.setData(self._colIdx[nwOutline.TITLE], Qt.UserRole, tHandle) - newItem.setIcon(self._colIdx[nwOutline.TITLE], self.mainTheme.getIcon(hIcon)) - newItem.setText(self._colIdx[nwOutline.LEVEL], novIdx.level) - newItem.setText(self._colIdx[nwOutline.LABEL], nwItem.itemName) - newItem.setIcon(self._colIdx[nwOutline.LABEL], dIcon) - newItem.setText(self._colIdx[nwOutline.LINE], sTitle[1:].lstrip("0")) - newItem.setData(self._colIdx[nwOutline.LINE], Qt.UserRole, sTitle) - newItem.setText(self._colIdx[nwOutline.SYNOP], novIdx.synopsis) - newItem.setText(self._colIdx[nwOutline.CCOUNT], f"{cC:n}") - newItem.setText(self._colIdx[nwOutline.WCOUNT], f"{wC:n}") - newItem.setText(self._colIdx[nwOutline.PCOUNT], f"{pC:n}") - newItem.setTextAlignment(self._colIdx[nwOutline.CCOUNT], Qt.AlignRight) - newItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignRight) - newItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignRight) - - theRefs = self.theProject.index.getReferences(tHandle, sTitle) - newItem.setText(self._colIdx[nwOutline.POV], ", ".join(theRefs[nwKeyWords.POV_KEY])) - newItem.setText(self._colIdx[nwOutline.FOCUS], ", ".join(theRefs[nwKeyWords.FOCUS_KEY])) - newItem.setText(self._colIdx[nwOutline.CHAR], ", ".join(theRefs[nwKeyWords.CHAR_KEY])) - newItem.setText(self._colIdx[nwOutline.PLOT], ", ".join(theRefs[nwKeyWords.PLOT_KEY])) - newItem.setText(self._colIdx[nwOutline.TIME], ", ".join(theRefs[nwKeyWords.TIME_KEY])) - newItem.setText(self._colIdx[nwOutline.WORLD], ", ".join(theRefs[nwKeyWords.WORLD_KEY])) - newItem.setText(self._colIdx[nwOutline.OBJECT], ", ".join(theRefs[nwKeyWords.OBJECT_KEY])) - newItem.setText(self._colIdx[nwOutline.ENTITY], ", ".join(theRefs[nwKeyWords.ENTITY_KEY])) - newItem.setText(self._colIdx[nwOutline.CUSTOM], ", ".join(theRefs[nwKeyWords.CUSTOM_KEY])) - - return newItem - # END Class GuiOutlineTree @@ -964,13 +979,13 @@ class GuiOutlineDetails(QScrollArea): self.setWidgetResizable(True) self.setFrameStyle(QFrame.NoFrame) - self.initDetails() + self.initSettings() logger.debug("GuiOutlineDetails initialisation complete") return - def initDetails(self): + def initSettings(self): """Set or update outline settings. """ # Scroll bars diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index 13b0b619..a1b5bf8e 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -55,7 +55,6 @@ class GuiProjectView(QWidget): # Signals triggered when the meta data values of items change treeItemChanged = pyqtSignal(str) - novelItemChanged = pyqtSignal(str) rootFolderChanged = pyqtSignal(str) wordCountsChanged = pyqtSignal() @@ -177,7 +176,7 @@ class GuiProjectToolBar(QWidget): self.mainTheme = projView.mainGui.mainTheme iPx = self.mainTheme.baseIconSize - mPx = self.mainConf.pxInt(3) + mPx = self.mainConf.pxInt(2) self.setContentsMargins(0, 0, 0, 0) self.setAutoFillBackground(True) @@ -1356,8 +1355,6 @@ class GuiProjectTree(QTreeWidget): itemType = tItem.itemType if itemType == nwItemType.ROOT: self.projView.rootFolderChanged.emit(tHandle) - elif itemType == nwItemType.FILE and tItem.isNovelLike(): - self.projView.novelItemChanged.emit(tHandle) self.projView.treeItemChanged.emit(tHandle) diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index e34b873e..bad8c904 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -199,7 +199,6 @@ class GuiMain(QMainWindow): self.projView.selectedItemChanged.connect(self.itemDetails.updateViewBox) self.projView.openDocumentRequest.connect(self._openDocument) - self.projView.novelItemChanged.connect(self._treeNovelItemChanged) self.projView.wordCountsChanged.connect(self._updateStatusWordCount) self.projView.treeItemChanged.connect(self.docEditor.updateDocInfo) self.projView.treeItemChanged.connect(self.docViewer.updateDocInfo) @@ -303,7 +302,7 @@ class GuiMain(QMainWindow): self.docEditor.clearEditor() self.docEditor.setDictionaries() self.closeDocViewer() - self.outlineView.clearOutline() + self.outlineView.clearProject() # General self.statusBar.clearStatus() @@ -365,8 +364,8 @@ class GuiMain(QMainWindow): self.rebuildTrees() self.saveProject() self.docEditor.setDictionaries() - self.outlineView.updateRootItem(None) self.novelView.openProjectTasks() + self.outlineView.openProjectTasks() self.rebuildIndex(beQuiet=True) self.statusBar.setRefTime(self.theProject.projOpened) self.statusBar.setProjectStatus(nwState.GOOD) @@ -422,7 +421,7 @@ class GuiMain(QMainWindow): if saveOK: self.closeDocument() self.docViewer.clearNavHistory() - self.outlineView.closeOutline() + self.outlineView.closeProjectTasks() self.novelView.closeProjectTasks() self.theProject.closeProject(self.idleTime) @@ -514,8 +513,8 @@ class GuiMain(QMainWindow): self.docEditor.setDictionaries() self.docEditor.toggleSpellCheck(self.theProject.spellCheck) self.statusBar.setRefTime(self.theProject.projOpened) - self.outlineView.updateRootItem(None) self.novelView.openProjectTasks() + self.outlineView.openProjectTasks() self._updateStatusWordCount() # Restore previously open documents, if any @@ -931,7 +930,7 @@ class GuiMain(QMainWindow): self.docViewer.initViewer() self.projView.initSettings() self.novelView.initSettings() - self.outlineView.initOutline() + self.outlineView.initSettings() self._updateStatusWordCount() return @@ -1192,7 +1191,7 @@ class GuiMain(QMainWindow): if tabIdx == self.idxProjView: self.projView.setFocus() elif tabIdx == self.idxNovelView: - self.novelView.setFocus() + self.novelView.setTreeFocus() elif paneNo == nwWidget.EDITOR: self._changeView(nwView.EDITOR) self.docEditor.setFocus() @@ -1552,18 +1551,6 @@ class GuiMain(QMainWindow): return - @pyqtSlot() - def _treeNovelItemChanged(self): - """Triggered when there is a change to a novel item in the - project tree. - """ - if self.mainStack.currentIndex() == self.idxOutlineView: - logger.verbose("Novel tree changed while Outline tab active") - if self.hasProject: - self.outlineView.refreshView(novelChanged=True) - - return - @pyqtSlot() def _keyPressReturn(self): """Forward the return/enter keypress to the function that opens @@ -1593,7 +1580,7 @@ class GuiMain(QMainWindow): elif stIndex == self.idxOutlineView: logger.verbose("Outline View activated") if self.hasProject: - self.outlineView.refreshView() + self.outlineView.refreshTree() return diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index 6ba4b5f1..b5bf2647 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,24 +1,23 @@ - + Sample Project Sample Project Jane Smith Jay Doh - 1371 + 1378 236 - 69222 + 69273 False en_GB True None - True 636b6aa9b697b 636b6aa9b697b 7031beac91f75 - None + 7031beac91f75 1363 954 409 diff --git a/tests/lipsum/nwProject.nwx b/tests/lipsum/nwProject.nwx index a8cf6393..4eac7bc6 100644 --- a/tests/lipsum/nwProject.nwx +++ b/tests/lipsum/nwProject.nwx @@ -13,7 +13,6 @@ en_GB False None - True 7a992350f3eb6 None None diff --git a/tests/minimal/nwProject.nwx b/tests/minimal/nwProject.nwx index 430ecf17..5862d48c 100644 --- a/tests/minimal/nwProject.nwx +++ b/tests/minimal/nwProject.nwx @@ -14,7 +14,6 @@ en_GB False None - True None None None diff --git a/tests/reference/coreProject_NewCustomA_nwProject.nwx b/tests/reference/coreProject_NewCustomA_nwProject.nwx index f046fceb..48ae6363 100644 --- a/tests/reference/coreProject_NewCustomA_nwProject.nwx +++ b/tests/reference/coreProject_NewCustomA_nwProject.nwx @@ -1,5 +1,5 @@ - + Test Custom Test Novel @@ -14,7 +14,6 @@ None False None - True None None None diff --git a/tests/reference/coreProject_NewCustomB_nwProject.nwx b/tests/reference/coreProject_NewCustomB_nwProject.nwx index 5d02172c..9399dd3f 100644 --- a/tests/reference/coreProject_NewCustomB_nwProject.nwx +++ b/tests/reference/coreProject_NewCustomB_nwProject.nwx @@ -14,7 +14,6 @@ None False None - True None None None diff --git a/tests/reference/coreProject_NewFileFolder_nwProject.nwx b/tests/reference/coreProject_NewFileFolder_nwProject.nwx index 20aeb027..b8df1c93 100644 --- a/tests/reference/coreProject_NewFileFolder_nwProject.nwx +++ b/tests/reference/coreProject_NewFileFolder_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project New Novel @@ -13,7 +13,6 @@ None False None - True None None None diff --git a/tests/reference/coreProject_NewMinimal_nwProject.nwx b/tests/reference/coreProject_NewMinimal_nwProject.nwx index ba08600f..633f9f4c 100644 --- a/tests/reference/coreProject_NewMinimal_nwProject.nwx +++ b/tests/reference/coreProject_NewMinimal_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project @@ -12,7 +12,6 @@ None False None - True None None None diff --git a/tests/reference/coreProject_NewRoot_nwProject.nwx b/tests/reference/coreProject_NewRoot_nwProject.nwx index 0a606137..9102601d 100644 --- a/tests/reference/coreProject_NewRoot_nwProject.nwx +++ b/tests/reference/coreProject_NewRoot_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project New Novel @@ -13,7 +13,6 @@ None False None - True None None None diff --git a/tests/reference/guiEditor_Main_Final_nwProject.nwx b/tests/reference/guiEditor_Main_Final_nwProject.nwx index ecc96604..884ab272 100644 --- a/tests/reference/guiEditor_Main_Final_nwProject.nwx +++ b/tests/reference/guiEditor_Main_Final_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project New Novel @@ -13,11 +13,10 @@ None True None - True 000000000000f None 0000000000008 - None + 0000000000008 129 102 27 diff --git a/tests/reference/guiEditor_Main_Initial_nwProject.nwx b/tests/reference/guiEditor_Main_Initial_nwProject.nwx index 1a79d2c2..0563c440 100644 --- a/tests/reference/guiEditor_Main_Initial_nwProject.nwx +++ b/tests/reference/guiEditor_Main_Initial_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project New Novel @@ -13,7 +13,6 @@ None False None - True None None None diff --git a/tests/reference/guiProjSettings_Dialog_nwProject.nwx b/tests/reference/guiProjSettings_Dialog_nwProject.nwx index 883cb26d..1db9d48c 100644 --- a/tests/reference/guiProjSettings_Dialog_nwProject.nwx +++ b/tests/reference/guiProjSettings_Dialog_nwProject.nwx @@ -1,5 +1,5 @@ - + Project Name Project Title @@ -14,7 +14,6 @@ None False en - True None None None diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py index a6409b98..3be812e1 100644 --- a/tests/test_core/test_core_project.py +++ b/tests/test_core/test_core_project.py @@ -934,12 +934,6 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd): assert theProject.localLookup(1) == "One" assert theProject.localLookup(10) == "Ten" - # Automatic outline update - theProject.projChanged = False - assert theProject.setAutoOutline(True) - assert not theProject.setAutoOutline(False) - assert theProject.projChanged - # Last edited theProject.projChanged = False assert theProject.setLastEdited("0123456789abc") diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py index 6407b84b..a27fc816 100644 --- a/tests/test_gui/test_gui_guimain.py +++ b/tests/test_gui/test_gui_guimain.py @@ -149,9 +149,7 @@ def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): with monkeypatch.context() as mp: mp.setattr(GuiOutlineView, "treeHasFocus", lambda *a: True) assert nwGUI.docEditor.docHandle() is None - actItem = nwGUI.outlineView.outlineTree.topLevelItem(0) - chpItem = actItem.child(0) - selItem = chpItem.child(0) + selItem = nwGUI.outlineView.outlineTree.topLevelItem(2) nwGUI.outlineView.outlineTree.setCurrentItem(selItem) nwGUI._keyPressReturn() assert nwGUI.docEditor.docHandle() == sHandle diff --git a/tests/test_gui/test_gui_outline.py b/tests/test_gui/test_gui_outline.py index 26ca9803..2f33cf7a 100644 --- a/tests/test_gui/test_gui_outline.py +++ b/tests/test_gui/test_gui_outline.py @@ -54,7 +54,7 @@ def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, fncDir): # Toggle scrollbars nwGUI.mainConf.hideVScroll = True nwGUI.mainConf.hideHScroll = True - outlineView.initOutline() + outlineView.initSettings() assert outlineTree.verticalScrollBarPolicy() == Qt.ScrollBarAlwaysOff assert outlineTree.horizontalScrollBarPolicy() == Qt.ScrollBarAlwaysOff assert outlineData.verticalScrollBarPolicy() == Qt.ScrollBarAlwaysOff @@ -62,7 +62,7 @@ def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, fncDir): nwGUI.mainConf.hideVScroll = False nwGUI.mainConf.hideHScroll = False - outlineView.initOutline() + outlineView.initSettings() assert outlineTree.verticalScrollBarPolicy() == Qt.ScrollBarAsNeeded assert outlineTree.horizontalScrollBarPolicy() == Qt.ScrollBarAsNeeded assert outlineData.verticalScrollBarPolicy() == Qt.ScrollBarAsNeeded @@ -232,9 +232,7 @@ def testGuiOutline_Content(qtbot, monkeypatch, nwGUI, nwLipsum): assert outlineData.pCValue.text() == "3" # Scene One - actItem = outlineTree.topLevelItem(1) - chpItem = actItem.child(0) - selItem = chpItem.child(0) + selItem = outlineTree.topLevelItem(4) outlineTree.setCurrentItem(selItem) tHandle, tLine = outlineTree.getSelectedHandle() @@ -252,10 +250,7 @@ def testGuiOutline_Content(qtbot, monkeypatch, nwGUI, nwLipsum): assert nwGUI.docViewer.docHandle() == "4c4f28287af27" # Scene One, Section Two - actItem = outlineTree.topLevelItem(1) - chpItem = actItem.child(0) - scnItem = chpItem.child(0) - selItem = scnItem.child(0) + selItem = outlineTree.topLevelItem(5) outlineTree.setCurrentItem(selItem) tHandle, tLine = outlineTree.getSelectedHandle()