From 11b6ed87d4cdcb3f017e786b6766535b843a4d29 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Fri, 18 Nov 2022 00:44:58 +0100 Subject: [PATCH] Add the novel selector widget and use it for the outline --- novelwriter/gui/components.py | 66 +++++++++++++++++++++++++++++++++-- novelwriter/gui/outline.py | 38 ++++++++------------ 2 files changed, 79 insertions(+), 25 deletions(-) diff --git a/novelwriter/gui/components.py b/novelwriter/gui/components.py index dac50d28..201469d5 100644 --- a/novelwriter/gui/components.py +++ b/novelwriter/gui/components.py @@ -4,7 +4,8 @@ novelWriter – GUI Components Module A module of various small GUI components File History: -Created: 2020-05-17 [0.5.1] StatusLED +Created: 2020-05-17 [0.5.1] StatusLED +Created: 2022-11-17 [2.0rc2] NovelSelector This file is a part of novelWriter Copyright 2018–2022, Veronica Berglyd Olsen @@ -26,11 +27,72 @@ along with this program. If not, see . import logging from PyQt5.QtGui import QPainter -from PyQt5.QtWidgets import QAbstractButton +from PyQt5.QtCore import pyqtSignal, pyqtSlot +from PyQt5.QtWidgets import QAbstractButton, QComboBox + +from novelwriter.enum import nwItemClass logger = logging.getLogger(__name__) +class NovelSelector(QComboBox): + + novelSelectionChanged = pyqtSignal(str) + + def __init__(self, parent, project, icon): + super().__init__(parent=parent) + + self._project = project + self._icon = icon + + self._blockSignal = False + + self.currentIndexChanged.connect(self._indexChanged) + + return + + @property + def handle(self): + return self.currentData() + + def setHandle(self, tHandle, blockSignal=True): + """Set the currently selected handle. + """ + self._blockSignal = blockSignal + if tHandle is None: + index = self.count() - 1 + else: + index = self.findData(tHandle) + if index >= 0: + self.setCurrentIndex(index) + self._blockSignal = False + return + + def updateList(self): + """Rebuild the list of novel items. + """ + self._blockSignal = True + self.clear() + for tHandle, nwItem in self._project.tree.iterRoots(nwItemClass.NOVEL): + self.addItem(self._icon, nwItem.itemName, tHandle) + self.insertSeparator(self.count()) + self.addItem(self._icon, self.tr("All Novel Folders"), "") + self._blockSignal = False + return + + ## + # Private Slots + ## + + @pyqtSlot(int) + def _indexChanged(self, index): + if not self._blockSignal: + self.novelSelectionChanged.emit(self.currentData()) + return + +# END Class NovelSelector + + class StatusLED(QAbstractButton): S_NONE = 0 diff --git a/novelwriter/gui/outline.py b/novelwriter/gui/outline.py index ef898237..e142ecd3 100644 --- a/novelwriter/gui/outline.py +++ b/novelwriter/gui/outline.py @@ -37,9 +37,9 @@ from PyQt5.QtCore import ( Qt, pyqtSignal, pyqtSlot, QSize, QT_TRANSLATE_NOOP ) from PyQt5.QtWidgets import ( - QAbstractItemView, QAction, QComboBox, QFrame, QGridLayout, QGroupBox, - QHBoxLayout, QLabel, QMenu, QScrollArea, QSizePolicy, QSplitter, QToolBar, - QToolButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget + QAbstractItemView, QAction, QFrame, QGridLayout, QGroupBox, QHBoxLayout, + QLabel, QMenu, QScrollArea, QSizePolicy, QSplitter, QToolBar, QToolButton, + QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget ) from novelwriter.enum import ( @@ -47,6 +47,7 @@ from novelwriter.enum import ( ) from novelwriter.common import checkInt from novelwriter.constants import nwHeaders, trConst, nwKeyWords, nwLabels +from novelwriter.gui.components import NovelSelector logger = logging.getLogger(__name__) @@ -233,9 +234,10 @@ class GuiOutlineToolBar(QToolBar): self.novelLabel = QLabel(self.tr("Outline of")) self.novelLabel.setContentsMargins(0, 0, mPx, 0) - self.novelValue = QComboBox(self) + tIcon = self.mainTheme.getIcon(nwLabels.CLASS_ICON[nwItemClass.NOVEL]) + self.novelValue = NovelSelector(self, self.theProject, tIcon) self.novelValue.setMinimumWidth(self.mainConf.pxInt(200)) - self.novelValue.currentIndexChanged.connect(self._novelValueChanged) + self.novelValue.novelSelectionChanged.connect(self._novelValueChanged) # Actions self.aRefresh = QAction(self.tr("Refresh"), self) @@ -280,25 +282,15 @@ class GuiOutlineToolBar(QToolBar): return def populateNovelList(self): - """Fill the novel combo box with a list of all novel folders. + """Relaod the content of the novel list. """ - self.novelValue.clear() - tIcon = self.mainTheme.getIcon(nwLabels.CLASS_ICON[nwItemClass.NOVEL]) - for tHandle, nwItem in self.theProject.tree.iterRoots(nwItemClass.NOVEL): - self.novelValue.addItem(tIcon, nwItem.itemName, tHandle) - self.novelValue.insertSeparator(self.novelValue.count()) - self.novelValue.addItem(tIcon, self.tr("All Novel Folders"), "") + self.novelValue.updateList() 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) + self.novelValue.setHandle(rootHandle) return def setColumnHiddenState(self, hiddenState): @@ -311,19 +303,18 @@ class GuiOutlineToolBar(QToolBar): # Private Slots ## - @pyqtSlot(int) - def _novelValueChanged(self, index): + @pyqtSlot(str) + def _novelValueChanged(self, tHandle): """Emit a signal containing the handle of the selected item. """ - if index >= 0: - self.loadNovelRootRequest.emit(self.novelValue.currentData()) + self.loadNovelRootRequest.emit(tHandle) return @pyqtSlot() def _refreshRequested(self): """Emit a signal containing the handle of the selected item. """ - self.loadNovelRootRequest.emit(self.novelValue.currentData()) + self.loadNovelRootRequest.emit(self.novelValue.handle) return # END Class GuiOutlineToolBar @@ -679,6 +670,7 @@ class GuiOutlineTree(QTreeWidget): if they are hidden. This ensures that showing and hiding columns is fast and doesn't require a rebuild of the tree. """ + logger.debug("Rebuilding Outline tree") self.clear() if self._firstView: