diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py
index 41663a42..5ece68b1 100644
--- a/novelwriter/dialogs/preferences.py
+++ b/novelwriter/dialogs/preferences.py
@@ -63,11 +63,6 @@ class GuiPreferences(QDialog):
)
self.titleLabel.setIndent(CONFIG.pxInt(4))
- # SideBar
- self.sidebar = NPagedSideBar(self)
- self.sidebar.setLabelColor(SHARED.theme.helpText)
- self.sidebar.buttonClicked.connect(self._sidebarClicked)
-
# Search Box
self.searchText = QLineEdit(self)
self.searchText.setPlaceholderText(self.tr("Search"))
@@ -77,10 +72,10 @@ class GuiPreferences(QDialog):
)
self.searchAction.triggered.connect(self._gotoSearch)
- self.searchBox = QHBoxLayout()
- self.searchBox.addWidget(self.titleLabel)
- self.searchBox.addStretch(1)
- self.searchBox.addWidget(self.searchText, 1)
+ # SideBar
+ self.sidebar = NPagedSideBar(self)
+ self.sidebar.setLabelColor(SHARED.theme.helpText)
+ self.sidebar.buttonClicked.connect(self._sidebarClicked)
# Form
self.mainForm = NScrollableForm(self)
@@ -95,6 +90,11 @@ class GuiPreferences(QDialog):
self.buttonBox.clicked.connect(self._dialogButtonClicked)
# Assemble
+ self.searchBox = QHBoxLayout()
+ self.searchBox.addWidget(self.titleLabel)
+ self.searchBox.addStretch(1)
+ self.searchBox.addWidget(self.searchText, 1)
+
self.mainBox = QHBoxLayout()
self.mainBox.addWidget(self.sidebar)
self.mainBox.addWidget(self.mainForm)
diff --git a/novelwriter/dialogs/projdetails.py b/novelwriter/dialogs/projdetails.py
index a6e12163..31ffea62 100644
--- a/novelwriter/dialogs/projdetails.py
+++ b/novelwriter/dialogs/projdetails.py
@@ -419,7 +419,7 @@ class GuiProjectDetailsContents(QWidget):
def updateValues(self) -> None:
"""Populate the tree."""
self._currentRoot = None
- self.novelValue.updateList()
+ self.novelValue.refreshNovelList()
self.novelValue.setHandle(self.novelValue.firstHandle)
self._prepareData(self.novelValue.firstHandle)
self._populateTree()
diff --git a/novelwriter/extensions/novelselector.py b/novelwriter/extensions/novelselector.py
index 035ab570..793a475d 100644
--- a/novelwriter/extensions/novelselector.py
+++ b/novelwriter/extensions/novelselector.py
@@ -3,7 +3,7 @@ novelWriter – Custom Widget: Novel Selector
===========================================
File History:
-Created: 2022-11-17 [2.0]
+Created: 2022-11-17 [2.0] NovelSelector
This file is a part of novelWriter
Copyright 2018–2024, Veronica Berglyd Olsen
@@ -43,6 +43,8 @@ class NovelSelector(QComboBox):
super().__init__(parent=parent)
self._blockSignal = False
self._firstHandle = None
+ self._includeAll = False
+ self._listFormat = None
self.currentIndexChanged.connect(self._indexChanged)
return
@@ -74,7 +76,23 @@ class NovelSelector(QComboBox):
self._blockSignal = False
return
- def updateList(self, includeAll: bool = False, prefix: str | None = None) -> None:
+ def setIncludeAll(self, value: bool) -> None:
+ """Set flag to add an "All Novel Folders" option."""
+ self._includeAll = value
+ return
+
+ def setListFormat(self, value: str | None) -> None:
+ """Set a format string for the list entries."""
+ if value is None or "{0}" in value:
+ self._listFormat = value
+ return
+
+ ##
+ # Public Slots
+ ##
+
+ @pyqtSlot()
+ def refreshNovelList(self) -> None:
"""Rebuild the list of novel items."""
self._blockSignal = True
self._firstHandle = None
@@ -83,8 +101,8 @@ class NovelSelector(QComboBox):
icon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[nwItemClass.NOVEL])
handle = self.currentData()
for tHandle, nwItem in SHARED.project.tree.iterRoots(nwItemClass.NOVEL):
- if prefix:
- name = prefix.format(nwItem.itemName)
+ if self._listFormat:
+ name = self._listFormat.format(nwItem.itemName)
self.addItem(name, tHandle)
else:
name = nwItem.itemName
@@ -92,7 +110,7 @@ class NovelSelector(QComboBox):
if self._firstHandle is None:
self._firstHandle = tHandle
- if includeAll:
+ if self._includeAll:
self.insertSeparator(self.count())
self.addItem(icon, self.tr("All Novel Folders"), "")
diff --git a/novelwriter/gui/mainmenu.py b/novelwriter/gui/mainmenu.py
index 94cd1d20..4ad1ab09 100644
--- a/novelwriter/gui/mainmenu.py
+++ b/novelwriter/gui/mainmenu.py
@@ -162,7 +162,7 @@ class GuiMainMenu(QMenuBar):
# Project > Novel Info
self.aNovelInfo = self.projMenu.addAction(self.tr("Novel Info"))
self.aNovelInfo.setShortcut("Shift+F6")
- self.aNovelInfo.triggered.connect(self.mainGui.showNovelInfoDialog)
+ self.aNovelInfo.triggered.connect(self.mainGui.showNovelDetailsDialog)
# Project > Separator
self.projMenu.addSeparator()
diff --git a/novelwriter/gui/noveltree.py b/novelwriter/gui/noveltree.py
index 1569262b..959ec7ae 100644
--- a/novelwriter/gui/noveltree.py
+++ b/novelwriter/gui/noveltree.py
@@ -207,9 +207,10 @@ class GuiNovelToolBar(QWidget):
# Novel Selector
selFont = self.font()
selFont.setWeight(QFont.Weight.Bold)
- self.novelPrefix = self.tr("Outline of {0}")
+
self.novelValue = NovelSelector(self)
self.novelValue.setFont(selFont)
+ self.novelValue.setListFormat(self.tr("Outline of {0}"))
self.novelValue.setMinimumWidth(CONFIG.pxInt(150))
self.novelValue.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.novelValue.novelSelectionChanged.connect(self.setCurrentRoot)
@@ -294,7 +295,7 @@ class GuiNovelToolBar(QWidget):
"QComboBox {border-style: none; padding-left: 0;} "
"QComboBox::drop-down {border-style: none}"
)
- self.novelValue.updateList(prefix=self.novelPrefix)
+ self.novelValue.refreshNovelList()
self.tbNovel.setVisible(self.novelValue.count() > 1)
return
@@ -307,7 +308,7 @@ class GuiNovelToolBar(QWidget):
def buildNovelRootMenu(self) -> None:
"""Build the novel root menu."""
- self.novelValue.updateList(prefix=self.novelPrefix)
+ self.novelValue.refreshNovelList()
self.tbNovel.setVisible(self.novelValue.count() > 1)
return
diff --git a/novelwriter/gui/outline.py b/novelwriter/gui/outline.py
index db066cee..cd441bae 100644
--- a/novelwriter/gui/outline.py
+++ b/novelwriter/gui/outline.py
@@ -220,6 +220,7 @@ class GuiOutlineToolBar(QToolBar):
self.novelLabel.setContentsMargins(0, 0, mPx, 0)
self.novelValue = NovelSelector(self)
+ self.novelValue.setIncludeAll(True)
self.novelValue.setMinimumWidth(CONFIG.pxInt(200))
self.novelValue.novelSelectionChanged.connect(self._novelValueChanged)
@@ -258,7 +259,7 @@ class GuiOutlineToolBar(QToolBar):
def updateTheme(self) -> None:
"""Update theme elements."""
self.setStyleSheet("QToolBar {border: 0px;}")
- self.novelValue.updateList(includeAll=True)
+ self.novelValue.refreshNovelList()
self.aRefresh.setIcon(SHARED.theme.getIcon("refresh"))
self.tbColumns.setIcon(SHARED.theme.getIcon("menu"))
self.tbColumns.setStyleSheet("QToolButton::menu-indicator {image: none;}")
@@ -266,7 +267,7 @@ class GuiOutlineToolBar(QToolBar):
def populateNovelList(self) -> None:
"""Reload the content of the novel list."""
- self.novelValue.updateList(includeAll=True)
+ self.novelValue.refreshNovelList()
return
def setCurrentRoot(self, rootHandle: str | None) -> None:
diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py
index fea65021..8f4c3e4d 100644
--- a/novelwriter/guimain.py
+++ b/novelwriter/guimain.py
@@ -56,9 +56,9 @@ from novelwriter.dialogs.preferences import GuiPreferences
from novelwriter.dialogs.projdetails import GuiProjectDetails
from novelwriter.dialogs.projsettings import GuiProjectSettings
from novelwriter.tools.welcome import GuiWelcome
-from novelwriter.tools.novelinfo import GuiNovelInfo
from novelwriter.tools.manuscript import GuiManuscript
from novelwriter.tools.dictionaries import GuiDictionaries
+from novelwriter.tools.noveldetails import GuiNovelDetails
from novelwriter.tools.writingstats import GuiWritingStats
from novelwriter.enum import (
@@ -838,10 +838,10 @@ class GuiMain(QMainWindow):
return
@pyqtSlot()
- def showNovelInfoDialog(self) -> None:
- """Open the novel info dialog."""
+ def showNovelDetailsDialog(self) -> None:
+ """Open the novel details dialog."""
if SHARED.hasProject:
- dialog = GuiNovelInfo(self)
+ dialog = GuiNovelDetails(self)
dialog.setModal(True)
dialog.show()
dialog.raise_()
diff --git a/novelwriter/tools/noveldetails.py b/novelwriter/tools/noveldetails.py
new file mode 100644
index 00000000..66eec029
--- /dev/null
+++ b/novelwriter/tools/noveldetails.py
@@ -0,0 +1,122 @@
+"""
+novelWriter – GUI Novel Info
+============================
+
+File History:
+Created: 2024-01-18 [2.3b1] GuiNovelDetails
+
+This file is a part of novelWriter
+Copyright 2018–2024, Veronica Berglyd Olsen
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+"""
+from __future__ import annotations
+
+import logging
+
+from PyQt5.QtGui import QCloseEvent
+from PyQt5.QtWidgets import (
+ QDialog, QDialogButtonBox, QHBoxLayout, QStackedWidget, QVBoxLayout,
+ QWidget
+)
+
+from novelwriter import CONFIG, SHARED
+from novelwriter.extensions.configlayout import NColourLabel
+from novelwriter.extensions.novelselector import NovelSelector
+from novelwriter.extensions.pagedsidebar import NPagedSideBar
+
+logger = logging.getLogger(__name__)
+
+
+class GuiNovelDetails(QDialog):
+
+ def __init__(self, parent: QWidget) -> None:
+ super().__init__(parent=parent)
+
+ logger.debug("Create: GuiNovelDetails")
+ self.setObjectName("GuiNovelDetails")
+ self.setWindowTitle(self.tr("Novel Details"))
+ self.setMinimumSize(CONFIG.pxInt(600), CONFIG.pxInt(500))
+
+ # Title
+ self.titleLabel = NColourLabel(
+ self.tr("Novel Details"), SHARED.theme.helpText, parent=self, scale=1.25
+ )
+ self.titleLabel.setIndent(CONFIG.pxInt(4))
+
+ # Novel Selector
+ self.novelSelector = NovelSelector(self)
+ self.novelSelector.refreshNovelList()
+
+ # SideBar
+ self.sidebar = NPagedSideBar(self)
+ self.sidebar.setLabelColor(SHARED.theme.helpText)
+ # self.sidebar.buttonClicked.connect(self._sidebarClicked)
+
+ # Content
+ self.mainStack = QStackedWidget(self)
+
+ # Buttons
+ self.buttonBox = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
+ self.buttonBox.rejected.connect(self.close)
+
+ # Assemble
+ self.topBox = QHBoxLayout()
+ self.topBox.addWidget(self.titleLabel)
+ self.topBox.addStretch(1)
+ self.topBox.addWidget(self.novelSelector, 1)
+
+ self.mainBox = QHBoxLayout()
+ self.mainBox.addWidget(self.sidebar)
+ self.mainBox.addWidget(self.mainStack)
+ self.mainBox.setContentsMargins(0, 0, 0, 0)
+
+ self.outerBox = QVBoxLayout()
+ self.outerBox.addLayout(self.topBox)
+ self.outerBox.addLayout(self.mainBox)
+ self.outerBox.addWidget(self.buttonBox)
+ self.outerBox.setSpacing(CONFIG.pxInt(8))
+
+ self.setLayout(self.outerBox)
+ self.setSizeGripEnabled(True)
+
+ logger.debug("Ready: GuiNovelDetails")
+
+ return
+
+ def __del__(self) -> None: # pragma: no cover
+ logger.debug("Delete: GuiNovelDetails")
+ return
+
+ ##
+ # Events
+ ##
+
+ def closeEvent(self, event: QCloseEvent) -> None:
+ """Capture the user closing the window and save settings."""
+ self._saveSettings()
+ event.accept()
+ self.deleteLater()
+ return
+
+ ##
+ # Internal Functions
+ ##
+
+ def _saveSettings(self) -> None:
+ """Save the user GUI settings."""
+ logger.debug("Saving State: GuiNovelDetails")
+ return
+
+# END Class GuiNovelDetails
diff --git a/novelwriter/tools/novelinfo.py b/novelwriter/tools/novelinfo.py
deleted file mode 100644
index 611c80b3..00000000
--- a/novelwriter/tools/novelinfo.py
+++ /dev/null
@@ -1,71 +0,0 @@
-"""
-novelWriter – GUI Novel Info
-============================
-
-File History:
-Created: 2024-01-18 [2.3b1] GuiNovelInfo
-
-This file is a part of novelWriter
-Copyright 2018–2024, Veronica Berglyd Olsen
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-from __future__ import annotations
-
-import logging
-
-from PyQt5.QtGui import QCloseEvent
-from PyQt5.QtWidgets import QDialog, QWidget
-
-logger = logging.getLogger(__name__)
-
-
-class GuiNovelInfo(QDialog):
-
- def __init__(self, parent: QWidget) -> None:
- super().__init__(parent=parent)
-
- logger.debug("Create: GuiNovelInfo")
- self.setObjectName("GuiNovelInfo")
-
- self.setWindowTitle(self.tr("Novel Info"))
- logger.debug("Ready: GuiNovelInfo")
-
- return
-
- def __del__(self) -> None: # pragma: no cover
- logger.debug("Delete: GuiNovelInfo")
- return
-
- ##
- # Events
- ##
-
- def closeEvent(self, event: QCloseEvent) -> None:
- """Capture the user closing the window and save settings."""
- self._saveSettings()
- event.accept()
- self.deleteLater()
- return
-
- ##
- # Internal Functions
- ##
-
- def _saveSettings(self) -> None:
- """Save the user GUI settings."""
- logger.debug("Saving State: GuiNovelInfo")
- return
-
-# END Class GuiNovelInfo