Redesign Build Settings tool to match other config dialogs

This commit is contained in:
Veronica Berglyd Olsen
2024-01-27 15:22:37 +01:00
parent d113b3feb3
commit 855c525670
4 changed files with 92 additions and 81 deletions
+12 -1
View File
@@ -52,7 +52,18 @@ class NFixedPage(QFrame):
super().__init__(parent=parent) super().__init__(parent=parent)
self.setFrameShadow(QFrame.Shadow.Sunken) self.setFrameShadow(QFrame.Shadow.Sunken)
self.setFrameShape(QFrame.Shape.StyledPanel) self.setFrameShape(QFrame.Shape.StyledPanel)
self.setCentralLayout = self.setLayout return
def setCentralLayout(self, layout: QLayout) -> None:
"""Set a layout as the central object."""
self.setLayout(layout)
return
def setCentralWidget(self, widget: QWidget) -> None:
"""Set a layout as the central object."""
layout = QHBoxLayout()
layout.addWidget(widget)
self.setLayout(layout)
return return
# END Class NFixedPage # END Class NFixedPage
+60 -60
View File
@@ -42,7 +42,9 @@ from novelwriter.constants import nwHeadFmt, nwLabels, trConst
from novelwriter.core.buildsettings import BuildSettings, FilterMode from novelwriter.core.buildsettings import BuildSettings, FilterMode
from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.switch import NSwitch
from novelwriter.extensions.switchbox import NSwitchBox from novelwriter.extensions.switchbox import NSwitchBox
from novelwriter.extensions.configlayout import NConfigLayout, NSimpleLayout from novelwriter.extensions.configlayout import (
NColourLabel, NConfigLayout, NFixedPage, NScrollablePage, NSimpleLayout
)
from novelwriter.extensions.pagedsidebar import NPagedSideBar from novelwriter.extensions.pagedsidebar import NPagedSideBar
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING: # pragma: no cover
@@ -90,34 +92,37 @@ class GuiBuildSettings(QDialog):
CONFIG.pxInt(pOptions.getInt("GuiBuildSettings", "winHeight", hWin)) CONFIG.pxInt(pOptions.getInt("GuiBuildSettings", "winHeight", hWin))
) )
# Options SideBar # Title
# =============== self.titleLabel = NColourLabel(
self.tr("Manuscript Build Settings"), SHARED.theme.helpText,
parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
)
self.optSideBar = NPagedSideBar(self) # Settings Name
self.optSideBar.setMinimumWidth(mPx) self.lblBuildName = QLabel(self.tr("Name"))
self.optSideBar.setMaximumWidth(mPx) self.editBuildName = QLineEdit(self)
self.optSideBar.setLabelColor(SHARED.theme.helpText)
self.optSideBar.addLabel(self.tr("Options")) # SideBar
self.optSideBar.addButton(self.tr("Selection"), self.OPT_FILTERS) self.sidebar = NPagedSideBar(self)
self.optSideBar.addButton(self.tr("Headings"), self.OPT_HEADINGS) self.sidebar.setMinimumWidth(mPx)
self.optSideBar.addButton(self.tr("Content"), self.OPT_CONTENT) self.sidebar.setMaximumWidth(mPx)
self.optSideBar.addButton(self.tr("Format"), self.OPT_FORMAT) self.sidebar.setLabelColor(SHARED.theme.helpText)
self.optSideBar.addButton(self.tr("Output"), self.OPT_OUTPUT)
self.optSideBar.buttonClicked.connect(self._stackPageSelected) self.sidebar.addButton(self.tr("Selection"), self.OPT_FILTERS)
self.sidebar.addButton(self.tr("Headings"), self.OPT_HEADINGS)
self.sidebar.addButton(self.tr("Content"), self.OPT_CONTENT)
self.sidebar.addButton(self.tr("Format"), self.OPT_FORMAT)
self.sidebar.addButton(self.tr("Output"), self.OPT_OUTPUT)
# Options Area self.sidebar.buttonClicked.connect(self._stackPageSelected)
# ============
# Create Tabs # Content
self.optTabSelect = _FilterTab(self, self._build) self.optTabSelect = _FilterTab(self, self._build)
self.optTabHeadings = _HeadingsTab(self, self._build) self.optTabHeadings = _HeadingsTab(self, self._build)
self.optTabContent = _ContentTab(self, self._build) self.optTabContent = _ContentTab(self, self._build)
self.optTabFormat = _FormatTab(self, self._build) self.optTabFormat = _FormatTab(self, self._build)
self.optTabOutput = _OutputTab(self, self._build) self.optTabOutput = _OutputTab(self, self._build)
# Add Tabs
self.toolStack = QStackedWidget(self) self.toolStack = QStackedWidget(self)
self.toolStack.addWidget(self.optTabSelect) self.toolStack.addWidget(self.optTabSelect)
self.toolStack.addWidget(self.optTabHeadings) self.toolStack.addWidget(self.optTabHeadings)
@@ -125,38 +130,36 @@ class GuiBuildSettings(QDialog):
self.toolStack.addWidget(self.optTabContent) self.toolStack.addWidget(self.optTabContent)
self.toolStack.addWidget(self.optTabOutput) self.toolStack.addWidget(self.optTabOutput)
# Main Settings + Buttons # Buttons
# ======================= self.buttonBox = QDialogButtonBox(
QDialogButtonBox.StandardButton.Apply
self.lblBuildName = QLabel(self.tr("Name")) | QDialogButtonBox.StandardButton.Save
self.editBuildName = QLineEdit() | QDialogButtonBox.StandardButton.Close
self.dlgButtons = QDialogButtonBox(
QDialogButtonBox.Apply | QDialogButtonBox.Save | QDialogButtonBox.Close
) )
self.dlgButtons.clicked.connect(self._dialogButtonClicked) self.buttonBox.clicked.connect(self._dialogButtonClicked)
self.buttonBox = QHBoxLayout() # Assemble
self.buttonBox.addWidget(self.lblBuildName) self.topBox = QHBoxLayout()
self.buttonBox.addWidget(self.editBuildName) self.topBox.addWidget(self.titleLabel)
self.buttonBox.addWidget(self.dlgButtons) self.topBox.addStretch(1)
self.topBox.addWidget(self.lblBuildName)
# Assemble GUI self.topBox.addWidget(self.editBuildName, 1)
# ============
self.mainBox = QHBoxLayout() self.mainBox = QHBoxLayout()
self.mainBox.addWidget(self.optSideBar) self.mainBox.addWidget(self.sidebar)
self.mainBox.addWidget(self.toolStack) self.mainBox.addWidget(self.toolStack)
self.mainBox.setContentsMargins(0, 0, 0, 0) self.mainBox.setContentsMargins(0, 0, 0, 0)
self.outerBox = QVBoxLayout() self.outerBox = QVBoxLayout()
self.outerBox.addLayout(self.topBox)
self.outerBox.addLayout(self.mainBox) self.outerBox.addLayout(self.mainBox)
self.outerBox.addLayout(self.buttonBox) self.outerBox.addWidget(self.buttonBox)
self.outerBox.setSpacing(CONFIG.pxInt(12)) self.outerBox.setSpacing(CONFIG.pxInt(12))
self.setLayout(self.outerBox) self.setLayout(self.outerBox)
# Set Default Tab # Set Default Tab
self.optSideBar.setSelected(self.OPT_FILTERS) self.sidebar.setSelected(self.OPT_FILTERS)
logger.debug("Ready: GuiBuildSettings") logger.debug("Ready: GuiBuildSettings")
@@ -185,6 +188,21 @@ class GuiBuildSettings(QDialog):
"""The build ID of the build of the dialog.""" """The build ID of the build of the dialog."""
return self._build.buildID return self._build.buildID
##
# Events
##
def closeEvent(self, event: QEvent) -> None:
"""Capture the user closing the window so we can save
settings.
"""
logger.debug("Closing: GuiBuildSettings")
self._askToSaveBuild()
self._saveSettings()
event.accept()
self.deleteLater()
return
## ##
# Private Slots # Private Slots
## ##
@@ -207,7 +225,7 @@ class GuiBuildSettings(QDialog):
@pyqtSlot("QAbstractButton*") @pyqtSlot("QAbstractButton*")
def _dialogButtonClicked(self, button: QAbstractButton) -> None: def _dialogButtonClicked(self, button: QAbstractButton) -> None:
"""Handle button clicks from the dialog button box.""" """Handle button clicks from the dialog button box."""
role = self.dlgButtons.buttonRole(button) role = self.buttonBox.buttonRole(button)
if role == QDialogButtonBox.ApplyRole: if role == QDialogButtonBox.ApplyRole:
self._emitBuildData() self._emitBuildData()
elif role == QDialogButtonBox.AcceptRole: elif role == QDialogButtonBox.AcceptRole:
@@ -217,21 +235,6 @@ class GuiBuildSettings(QDialog):
self.close() self.close()
return return
##
# Events
##
def closeEvent(self, event: QEvent) -> None:
"""Capture the user closing the window so we can save
settings.
"""
logger.debug("Closing: GuiBuildSettings")
self._askToSaveBuild()
self._saveSettings()
event.accept()
self.deleteLater()
return
## ##
# Internal Functions # Internal Functions
## ##
@@ -279,7 +282,7 @@ class GuiBuildSettings(QDialog):
# END Class GuiBuildSettings # END Class GuiBuildSettings
class _FilterTab(QWidget): class _FilterTab(NFixedPage):
C_DATA = 0 C_DATA = 0
C_NAME = 0 C_NAME = 0
@@ -395,11 +398,7 @@ class _FilterTab(QWidget):
CONFIG.pxInt(pOptions.getInt("GuiBuildSettings", "filterWidth", 300)) CONFIG.pxInt(pOptions.getInt("GuiBuildSettings", "filterWidth", 300))
]) ])
self.outerBox = QHBoxLayout() self.setCentralWidget(self.mainSplit)
self.outerBox.addWidget(self.mainSplit)
self.outerBox.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.outerBox)
return return
@@ -580,7 +579,7 @@ class _FilterTab(QWidget):
# END Class _FilterTab # END Class _FilterTab
class _HeadingsTab(QWidget): class _HeadingsTab(NScrollablePage):
EDIT_TITLE = 1 EDIT_TITLE = 1
EDIT_CHAPTER = 2 EDIT_CHAPTER = 2
@@ -758,7 +757,7 @@ class _HeadingsTab(QWidget):
self.outerBox.addLayout(self.editFormBox) self.outerBox.addLayout(self.editFormBox)
self.outerBox.addStretch(1) self.outerBox.addStretch(1)
self.setLayout(self.outerBox) self.setCentralLayout(self.outerBox)
return return
@@ -825,6 +824,7 @@ class _HeadingsTab(QWidget):
# Private Slots # Private Slots
## ##
@pyqtSlot()
def _saveFormat(self) -> None: def _saveFormat(self) -> None:
"""Save the format from the edit text box.""" """Save the format from the edit text box."""
heading = self._editing heading = self._editing
+2 -2
View File
@@ -116,7 +116,7 @@ def testManuscript_Builds(qtbot: QtBot, nwGUI: GuiMain, projPath: Path):
with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000): with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000):
bSettings.newSettingsReady.connect(_testNewSettingsReady) bSettings.newSettingsReady.connect(_testNewSettingsReady)
bSettings.dlgButtons.button(QDialogButtonBox.Save).click() bSettings.buttonBox.button(QDialogButtonBox.Save).click()
assert isinstance(build, BuildSettings) assert isinstance(build, BuildSettings)
assert build.name == "Test Build" assert build.name == "Test Build"
@@ -133,7 +133,7 @@ def testManuscript_Builds(qtbot: QtBot, nwGUI: GuiMain, projPath: Path):
with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000): with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000):
bSettings.newSettingsReady.connect(_testNewSettingsReady) bSettings.newSettingsReady.connect(_testNewSettingsReady)
bSettings.dlgButtons.button(QDialogButtonBox.Apply).click() # Should leave the dialog open bSettings.buttonBox.button(QDialogButtonBox.Apply).click() # Should leave the dialog open
assert isinstance(build, BuildSettings) assert isinstance(build, BuildSettings)
assert build.name == "Test Build" assert build.name == "Test Build"
+18 -18
View File
@@ -53,19 +53,19 @@ def testBuildSettings_Init(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockRnd
bSettings.loadContent() bSettings.loadContent()
# Flip through pages # Flip through pages
bSettings.optSideBar._group.button(bSettings.OPT_OUTPUT).click() bSettings.sidebar._group.button(bSettings.OPT_OUTPUT).click()
assert isinstance(bSettings.toolStack.currentWidget(), _OutputTab) assert isinstance(bSettings.toolStack.currentWidget(), _OutputTab)
bSettings.optSideBar._group.button(bSettings.OPT_FORMAT).click() bSettings.sidebar._group.button(bSettings.OPT_FORMAT).click()
assert isinstance(bSettings.toolStack.currentWidget(), _FormatTab) assert isinstance(bSettings.toolStack.currentWidget(), _FormatTab)
bSettings.optSideBar._group.button(bSettings.OPT_CONTENT).click() bSettings.sidebar._group.button(bSettings.OPT_CONTENT).click()
assert isinstance(bSettings.toolStack.currentWidget(), _ContentTab) assert isinstance(bSettings.toolStack.currentWidget(), _ContentTab)
bSettings.optSideBar._group.button(bSettings.OPT_HEADINGS).click() bSettings.sidebar._group.button(bSettings.OPT_HEADINGS).click()
assert isinstance(bSettings.toolStack.currentWidget(), _HeadingsTab) assert isinstance(bSettings.toolStack.currentWidget(), _HeadingsTab)
bSettings.optSideBar._group.button(bSettings.OPT_FILTERS).click() bSettings.sidebar._group.button(bSettings.OPT_FILTERS).click()
assert isinstance(bSettings.toolStack.currentWidget(), _FilterTab) assert isinstance(bSettings.toolStack.currentWidget(), _FilterTab)
# Check dialog buttons # Check dialog buttons
@@ -80,7 +80,7 @@ def testBuildSettings_Init(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockRnd
# Capture Apply button # Capture Apply button
with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000): with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000):
bSettings.newSettingsReady.connect(_testNewSettingsReady) bSettings.newSettingsReady.connect(_testNewSettingsReady)
bSettings._dialogButtonClicked(bSettings.dlgButtons.button(QDialogButtonBox.Apply)) bSettings._dialogButtonClicked(bSettings.buttonBox.button(QDialogButtonBox.Apply))
assert triggered assert triggered
@@ -89,7 +89,7 @@ def testBuildSettings_Init(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockRnd
with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000): with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000):
bSettings.newSettingsReady.connect(_testNewSettingsReady) bSettings.newSettingsReady.connect(_testNewSettingsReady)
bSettings._dialogButtonClicked(bSettings.dlgButtons.button(QDialogButtonBox.Save)) bSettings._dialogButtonClicked(bSettings.buttonBox.button(QDialogButtonBox.Save))
assert triggered assert triggered
@@ -106,7 +106,7 @@ def testBuildSettings_Init(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockRnd
assert triggered assert triggered
# Finish # Finish
bSettings._dialogButtonClicked(bSettings.dlgButtons.button(QDialogButtonBox.Close)) bSettings._dialogButtonClicked(bSettings.buttonBox.button(QDialogButtonBox.Close))
# qtbot.stop() # qtbot.stop()
# END Test testBuildSettings_Init # END Test testBuildSettings_Init
@@ -141,7 +141,7 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
bSettings.loadContent() bSettings.loadContent()
filterTab = bSettings.optTabSelect filterTab = bSettings.optTabSelect
bSettings.optSideBar._group.button(bSettings.OPT_FILTERS).click() bSettings.sidebar._group.button(bSettings.OPT_FILTERS).click()
assert bSettings.toolStack.currentWidget() is filterTab assert bSettings.toolStack.currentWidget() is filterTab
# Check content # Check content
@@ -312,7 +312,7 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
] ]
# Finish # Finish
bSettings._dialogButtonClicked(bSettings.dlgButtons.button(QDialogButtonBox.Close)) bSettings._dialogButtonClicked(bSettings.buttonBox.button(QDialogButtonBox.Close))
# qtbot.stop() # qtbot.stop()
# END Test testBuildSettings_Filter # END Test testBuildSettings_Filter
@@ -343,7 +343,7 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
bSettings.loadContent() bSettings.loadContent()
headTab = bSettings.optTabHeadings headTab = bSettings.optTabHeadings
bSettings.optSideBar._group.button(bSettings.OPT_HEADINGS).click() bSettings.sidebar._group.button(bSettings.OPT_HEADINGS).click()
assert bSettings.toolStack.currentWidget() is headTab assert bSettings.toolStack.currentWidget() is headTab
# Check initial values # Check initial values
@@ -468,7 +468,7 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
assert build.getBool("headings.hideSection") is True assert build.getBool("headings.hideSection") is True
# Finish # Finish
bSettings._dialogButtonClicked(bSettings.dlgButtons.button(QDialogButtonBox.Close)) bSettings._dialogButtonClicked(bSettings.buttonBox.button(QDialogButtonBox.Close))
# qtbot.stop() # qtbot.stop()
# END Test testBuildSettings_Headings # END Test testBuildSettings_Headings
@@ -492,7 +492,7 @@ def testBuildSettings_Content(qtbot: QtBot, nwGUI: GuiMain):
bSettings.loadContent() bSettings.loadContent()
contTab = bSettings.optTabContent contTab = bSettings.optTabContent
bSettings.optSideBar._group.button(bSettings.OPT_CONTENT).click() bSettings.sidebar._group.button(bSettings.OPT_CONTENT).click()
assert bSettings.toolStack.currentWidget() is contTab assert bSettings.toolStack.currentWidget() is contTab
# Check initial values # Check initial values
@@ -522,7 +522,7 @@ def testBuildSettings_Content(qtbot: QtBot, nwGUI: GuiMain):
assert build.getBool("text.addNoteHeadings") is True assert build.getBool("text.addNoteHeadings") is True
# Finish # Finish
bSettings._dialogButtonClicked(bSettings.dlgButtons.button(QDialogButtonBox.Close)) bSettings._dialogButtonClicked(bSettings.buttonBox.button(QDialogButtonBox.Close))
# qtbot.stop() # qtbot.stop()
# END Test testBuildSettings_Content # END Test testBuildSettings_Content
@@ -559,7 +559,7 @@ def testBuildSettings_Format(monkeypatch, qtbot: QtBot, nwGUI: GuiMain):
bSettings.loadContent() bSettings.loadContent()
fmtTab = bSettings.optTabFormat fmtTab = bSettings.optTabFormat
bSettings.optSideBar._group.button(bSettings.OPT_FORMAT).click() bSettings.sidebar._group.button(bSettings.OPT_FORMAT).click()
assert bSettings.toolStack.currentWidget() is fmtTab assert bSettings.toolStack.currentWidget() is fmtTab
# Check initial values # Check initial values
@@ -624,7 +624,7 @@ def testBuildSettings_Format(monkeypatch, qtbot: QtBot, nwGUI: GuiMain):
assert fmtTab.textSize.value() == 10 assert fmtTab.textSize.value() == 10
# Finish # Finish
bSettings._dialogButtonClicked(bSettings.dlgButtons.button(QDialogButtonBox.Close)) bSettings._dialogButtonClicked(bSettings.buttonBox.button(QDialogButtonBox.Close))
# qtbot.stop() # qtbot.stop()
# END Test testBuildSettings_Format # END Test testBuildSettings_Format
@@ -644,7 +644,7 @@ def testBuildSettings_Output(qtbot: QtBot, nwGUI: GuiMain):
bSettings.loadContent() bSettings.loadContent()
outTab = bSettings.optTabOutput outTab = bSettings.optTabOutput
bSettings.optSideBar._group.button(bSettings.OPT_OUTPUT).click() bSettings.sidebar._group.button(bSettings.OPT_OUTPUT).click()
assert bSettings.toolStack.currentWidget() is outTab assert bSettings.toolStack.currentWidget() is outTab
# Check initial values # Check initial values
@@ -662,7 +662,7 @@ def testBuildSettings_Output(qtbot: QtBot, nwGUI: GuiMain):
assert build.getBool("html.addStyles") is True assert build.getBool("html.addStyles") is True
# Finish # Finish
bSettings._dialogButtonClicked(bSettings.dlgButtons.button(QDialogButtonBox.Close)) bSettings._dialogButtonClicked(bSettings.buttonBox.button(QDialogButtonBox.Close))
# qtbot.stop() # qtbot.stop()
# END Test testBuildSettings_Output # END Test testBuildSettings_Output