Improve build settings dialog (#1499)

This commit is contained in:
Veronica Berglyd Olsen
2023-08-06 22:08:31 +01:00
committed by GitHub
17 changed files with 261 additions and 171 deletions
@@ -21,7 +21,7 @@ backward = typ_chevron-left.svg
bookmark = typ_bookmark.svg
browse = typ_folder-open.svg
build_excluded = typ_cancel.svg
build_filtered = typ_filter.svg
build_filtered = typ_arrow-forward.svg
build_included = typ_pin.svg
bullet-off = typ_media-record-outline.svg
bullet-on = typ_media-record.svg
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24" height="24" version="1.2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="m13.25 3.5625c-0.32 0-0.64 0.12125-0.88375 0.365-0.24375 0.245-0.36625 0.565-0.36625 0.885v3.1988c-5.625 0.6225-10 5.3862-10 11.176v1.25c2.8062-4.2788 6.5625-4.9 10-4.9862v3.1112c0 0.31875 0.1225 0.64 0.36625 0.88375s0.56375 0.36625 0.88375 0.36625 0.64-0.1225 0.88375-0.36625l7.8662-7.7588-7.8662-7.76c-0.24375-0.24375-0.56375-0.365-0.88375-0.365z" fill="#9c9" stroke-width="1.25"/>
</svg>

After

Width:  |  Height:  |  Size: 538 B

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24" height="24" version="1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="m20.694 2h-17.387c-1.3661 0-1.7387 0.85714-0.74516 2l5.2161 6c0.99354 1.1429 1.7387 3.2857 1.7387 4.8571v7.1429l4.9677-2.8571v-5c0-1.1429 0.74516-3 1.7387-4.1429l5.2161-6c0.99354-1.1429 0.62096-2-0.74516-2z" fill="#f99157" stroke-width="1.332"/>
</svg>

Before

Width:  |  Height:  |  Size: 398 B

@@ -21,7 +21,7 @@ backward = typ_chevron-left.svg
bookmark = typ_bookmark.svg
browse = typ_folder-open.svg
build_excluded = typ_cancel.svg
build_filtered = typ_filter.svg
build_filtered = typ_arrow-forward.svg
build_included = typ_pin.svg
bullet-off = typ_media-record-outline.svg
bullet-on = typ_media-record.svg
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24" height="24" version="1.2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="m13.25 3.5625c-0.32 0-0.64 0.12125-0.88375 0.365-0.24375 0.245-0.36625 0.565-0.36625 0.885v3.1988c-5.625 0.6225-10 5.3862-10 11.176v1.25c2.8062-4.2788 6.5625-4.9 10-4.9862v3.1112c0 0.31875 0.1225 0.64 0.36625 0.88375s0.56375 0.36625 0.88375 0.36625 0.64-0.1225 0.88375-0.36625l7.8662-7.7588-7.8662-7.76c-0.24375-0.24375-0.56375-0.365-0.88375-0.365z" fill="#718c00" stroke-width="1.25"/>
</svg>

After

Width:  |  Height:  |  Size: 541 B

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24" height="24" version="1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="m20.694 2h-17.387c-1.3661 0-1.7387 0.85714-0.74516 2l5.2161 6c0.99354 1.1429 1.7387 3.2857 1.7387 4.8571v7.1429l4.9677-2.8571v-5c0-1.1429 0.74516-3 1.7387-4.1429l5.2161-6c0.99354-1.1429 0.62096-2-0.74516-2z" fill="#f5871f" stroke-width="1.332"/>
</svg>

Before

Width:  |  Height:  |  Size: 398 B

+1
View File
@@ -257,6 +257,7 @@ class nwLabels:
class nwHeadFmt:
BR = "{BR}"
TITLE = "{Title}"
CH_NUM = "{Chapter}"
CH_WORD = "{Chapter:Word}"
+3 -3
View File
@@ -84,7 +84,7 @@ SETTINGS_TEMPLATE = {
}
SETTINGS_LABELS = {
"filter": QT_TRANSLATE_NOOP("Builds", "Document Types"),
"filter": QT_TRANSLATE_NOOP("Builds", "Document Filters"),
"filter.includeNovel": QT_TRANSLATE_NOOP("Builds", "Novel Documents"),
"filter.includeNotes": QT_TRANSLATE_NOOP("Builds", "Project Notes"),
"filter.includeInactive": QT_TRANSLATE_NOOP("Builds", "Inactive Documents"),
@@ -125,10 +125,10 @@ SETTINGS_LABELS = {
"format.leftMargin": QT_TRANSLATE_NOOP("Builds", "Left Margin"),
"format.rightMargin": QT_TRANSLATE_NOOP("Builds", "Right Margin"),
"odt": QT_TRANSLATE_NOOP("Builds", "Open Document"),
"odt": QT_TRANSLATE_NOOP("Builds", "Open Document (.odt)"),
"odt.addColours": QT_TRANSLATE_NOOP("Builds", "Add Highlight Colours"),
"html": QT_TRANSLATE_NOOP("Builds", "HTML"),
"html": QT_TRANSLATE_NOOP("Builds", "HTML (.html)"),
"html.addStyles": QT_TRANSLATE_NOOP("Builds", "Add CSS Styles"),
}
+7 -7
View File
@@ -31,7 +31,7 @@ from pathlib import Path
from novelwriter import CONFIG
from novelwriter.common import formatTimeStamp
from novelwriter.constants import nwKeyWords, nwLabels, nwHtmlUnicode
from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, nwHtmlUnicode
from novelwriter.core.project import NWProject
from novelwriter.core.tokenizer import Tokenizer, stripEscape
@@ -244,27 +244,27 @@ class ToHtml(Tokenizer):
parStyle = None
elif tType == self.T_TITLE:
tHead = tText.replace(r"\\", "<br/>")
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
tmpResult.append(f"<h1 class='title'{hStyle}>{aNm}{tHead}</h1>\n")
elif tType == self.T_UNNUM:
tHead = tText.replace(r"\\", "<br/>")
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
tmpResult.append(f"<{h2}{hStyle}>{aNm}{tHead}</{h2}>\n")
elif tType == self.T_HEAD1:
tHead = tText.replace(r"\\", "<br/>")
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
tmpResult.append(f"<{h1}{h1Cl}{hStyle}>{aNm}{tHead}</{h1}>\n")
elif tType == self.T_HEAD2:
tHead = tText.replace(r"\\", "<br/>")
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
tmpResult.append(f"<{h2}{hStyle}>{aNm}{tHead}</{h2}>\n")
elif tType == self.T_HEAD3:
tHead = tText.replace(r"\\", "<br/>")
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
tmpResult.append(f"<{h3}{hStyle}>{aNm}{tHead}</{h3}>\n")
elif tType == self.T_HEAD4:
tHead = tText.replace(r"\\", "<br/>")
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
tmpResult.append(f"<{h4}{hStyle}>{aNm}{tHead}</{h4}>\n")
elif tType == self.T_SEP:
+7 -7
View File
@@ -27,7 +27,7 @@ import logging
from pathlib import Path
from novelwriter.constants import nwLabels
from novelwriter.constants import nwHeadFmt, nwLabels
from novelwriter.core.project import NWProject
from novelwriter.core.tokenizer import Tokenizer
@@ -122,27 +122,27 @@ class ToMarkdown(Tokenizer):
thisPar = []
elif tType == self.T_TITLE:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
tmpResult.append(f"# {tHead}\n\n")
elif tType == self.T_UNNUM:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
tmpResult.append(f"## {tHead}\n\n")
elif tType == self.T_HEAD1:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
tmpResult.append(f"# {tHead}\n\n")
elif tType == self.T_HEAD2:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
tmpResult.append(f"## {tHead}\n\n")
elif tType == self.T_HEAD3:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
tmpResult.append(f"### {tHead}\n\n")
elif tType == self.T_HEAD4:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
tmpResult.append(f"#### {tHead}\n\n")
elif tType == self.T_SEP:
+7 -7
View File
@@ -36,7 +36,7 @@ from datetime import datetime
from novelwriter import __version__
from novelwriter.common import xmlIndent
from novelwriter.constants import nwKeyWords, nwLabels
from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels
from novelwriter.core.project import NWProject
from novelwriter.core.tokenizer import Tokenizer, stripEscape
@@ -445,27 +445,27 @@ class ToOdt(Tokenizer):
parStyle = None
elif tType == self.T_TITLE:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
self._addTextPar("Title", oStyle, tHead, isHead=False) # Title must be text:p
elif tType == self.T_UNNUM:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
self._addTextPar("Heading_20_2", oStyle, tHead, isHead=True, oLevel="2")
elif tType == self.T_HEAD1:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
self._addTextPar("Heading_20_1", oStyle, tHead, isHead=True, oLevel="1")
elif tType == self.T_HEAD2:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
self._addTextPar("Heading_20_2", oStyle, tHead, isHead=True, oLevel="2")
elif tType == self.T_HEAD3:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
self._addTextPar("Heading_20_3", oStyle, tHead, isHead=True, oLevel="3")
elif tType == self.T_HEAD4:
tHead = tText.replace(r"\\", "\n")
tHead = tText.replace(nwHeadFmt.BR, "\n")
self._addTextPar("Heading_20_4", oStyle, tHead, isHead=True, oLevel="4")
elif tType == self.T_SEP:
+45 -28
View File
@@ -1,7 +1,6 @@
"""
novelWriter Custom Widget: Paged SideBar
==========================================
A custom widget for making a sidebar for flipping through pages
File History:
Created: 2023-02-21 [2.1b1] NPagedSideBar
@@ -24,20 +23,26 @@ 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 <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations
from PyQt5.QtGui import QColor, QPainter
from PyQt5.QtCore import QRectF, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QColor, QPaintEvent, QPainter, QPolygon
from PyQt5.QtCore import QPoint, QRectF, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import (
QButtonGroup, QLabel, QSizePolicy, QStyle, QStyleOptionToolButton, QToolBar,
QToolButton, QWidget
QAbstractButton, QAction, QButtonGroup, QLabel, QSizePolicy, QStyle,
QStyleOptionToolButton, QToolBar, QToolButton, QWidget
)
class NPagedSideBar(QToolBar):
"""Extensions: Paged Side Bar
A side bar widget that holds buttons that mimic tabs. It is designed
to be used in combination with a QStackedWidget for options panels.
"""
buttonClicked = pyqtSignal(int)
def __init__(self, parent):
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)
self._buttons = []
@@ -58,7 +63,7 @@ class NPagedSideBar(QToolBar):
return
def setLabelColor(self, color):
def setLabelColor(self, color: list | QColor) -> None:
"""Set the text color for the labels."""
if isinstance(color, list):
self._labelCol = QColor(*color)
@@ -66,7 +71,7 @@ class NPagedSideBar(QToolBar):
self._labelCol = color
return
def addSeparator(self):
def addSeparator(self) -> None:
"""Add a spacer widget."""
spacer = QWidget(self)
spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
@@ -74,16 +79,16 @@ class NPagedSideBar(QToolBar):
self.insertWidget(self._stretchAction, spacer)
return
def addLabel(self, text):
def addLabel(self, text: str) -> None:
"""Add a new label to the toolbar."""
label = NPagedToolLabel(self, self._labelCol)
label = _NPagedToolLabel(self, self._labelCol)
label.setText(text)
self.insertWidget(self._stretchAction, label)
return
def addButton(self, text, buttonId=-1):
def addButton(self, text: str, buttonId: int = -1) -> QAction:
"""Add a new button to the toolbar."""
button = NPagedToolButton(self)
button = _NPagedToolButton(self)
button.setText(text)
action = self.insertWidget(self._stretchAction, button)
@@ -94,7 +99,7 @@ class NPagedSideBar(QToolBar):
return action
def setSelected(self, buttonId):
def setSelected(self, buttonId: int) -> None:
"""Set the selected button."""
self._group.button(buttonId).setChecked(True)
return
@@ -104,7 +109,7 @@ class NPagedSideBar(QToolBar):
##
@pyqtSlot("QAbstractButton*")
def _buttonClicked(self, button):
def _buttonClicked(self, button: QAbstractButton) -> None:
"""A button was clicked in the group, emit its id."""
buttonId = self._group.id(button)
if buttonId != -1:
@@ -114,11 +119,11 @@ class NPagedSideBar(QToolBar):
# END Class NPagedSideBar
class NPagedToolButton(QToolButton):
class _NPagedToolButton(QToolButton):
__slots__ = ("_bH", "_tM", "_lM", "_cR")
__slots__ = ("_bH", "_tM", "_lM", "_cR", "_aH")
def __init__(self, parent):
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
@@ -126,14 +131,15 @@ class NPagedToolButton(QToolButton):
fH = self.fontMetrics().height()
self._bH = round(fH * 1.7)
self._tM = (self._bH - fH) // 2
self._lM = self.style().pixelMetric(QStyle.PM_ButtonMargin)
self._cR = self._lM // 2
self._tM = (self._bH - fH)//2
self._lM = 3*self.style().pixelMetric(QStyle.PM_ButtonMargin)//2
self._cR = self._lM//2
self._aH = 2*fH//7
self.setFixedHeight(self._bH)
return
def paintEvent(self, event):
def paintEvent(self, event: QPaintEvent) -> None:
"""Overload the paint event to draw a simple, left aligned text
label, with a highlight when selected and a transparent base
colour when hovered.
@@ -144,6 +150,7 @@ class NPagedToolButton(QToolButton):
paint = QPainter(self)
paint.setRenderHint(QPainter.Antialiasing, True)
paint.setPen(Qt.NoPen)
paint.setBrush(Qt.NoBrush)
width = self.width()
height = self.height()
@@ -171,31 +178,41 @@ class NPagedToolButton(QToolButton):
paint.setOpacity(1.0)
paint.drawText(QRectF(self._lM, self._tM, tW, tH), Qt.AlignLeft, self.text())
tC = self.height()//2
tW = self.width() - self._aH - self._lM
if self.isChecked():
paint.setBrush(textCol)
paint.drawPolygon(QPolygon([
QPoint(tW, tC - self._aH),
QPoint(tW + self._aH, tC),
QPoint(tW, tC + self._aH),
]))
return
# END Class NPagedToolButton
# END Class _NPagedToolButton
class NPagedToolLabel(QLabel):
class _NPagedToolLabel(QLabel):
__slots__ = ("_bH", "_tM", "_lM", "_textCol")
def __init__(self, parent, textColor=None):
def __init__(self, parent: QWidget, textColor: QColor | None = None) -> None:
super().__init__(parent=parent)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
fH = self.fontMetrics().height()
self._bH = round(fH * 1.7)
self._tM = (self._bH - fH) // 2
self._lM = self.style().pixelMetric(QStyle.PM_ButtonMargin)
self._tM = (self._bH - fH)//2
self._lM = self.style().pixelMetric(QStyle.PM_ButtonMargin)//2
self.setFixedHeight(self._bH)
self._textCol = textColor or self.palette().text().color()
return
def paintEvent(self, event):
def paintEvent(self, event: QPaintEvent) -> None:
"""Overload the paint event to draw a simple, left aligned text
label that matches the button style.
"""
@@ -215,4 +232,4 @@ class NPagedToolLabel(QLabel):
return
# END Class NPagedToolLabel
# END Class _NPagedToolLabel
+2 -1
View File
@@ -1202,6 +1202,7 @@ class GuiProjectTree(QTreeWidget):
open a context menu in-place.
"""
tItem = None
tHandle = None
hasChild = False
selItem = self.itemAt(clickPos)
if isinstance(selItem, QTreeWidgetItem):
@@ -1209,7 +1210,7 @@ class GuiProjectTree(QTreeWidget):
tItem = self.theProject.tree[tHandle]
hasChild = selItem.childCount() > 0
if tItem is None:
if tItem is None or tHandle is None:
logger.debug("No item found")
return False
+28 -17
View File
@@ -30,7 +30,7 @@ from time import time
from typing import TYPE_CHECKING
from datetime import datetime
from PyQt5.QtGui import QColor, QCursor, QFont, QPalette, QResizeEvent
from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent
from PyQt5.QtCore import QSize, QTimer, Qt, pyqtSlot
from PyQt5.QtWidgets import (
QDialog, QGridLayout, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPushButton,
@@ -231,13 +231,13 @@ class GuiManuscript(QDialog):
# Events
##
def closeEvent(self, event):
def closeEvent(self, event: QCloseEvent):
"""Capture the user closing the window so we can save GUI
settings. We also check that we don't have a build settings
dialog open.
"""
self._saveSettings()
for obj in self.children():
for obj in self.mainGui.children():
# Make sure we don't have any settings windows open
if isinstance(obj, GuiBuildSettings) and obj.isVisible():
obj.close()
@@ -330,15 +330,13 @@ class GuiManuscript(QDialog):
def _buildManuscript(self):
"""Open the build dialog and build the manuscript."""
build = self._getSelectedBuild()
if build is None:
return
if isinstance(build, BuildSettings):
dlgBuild = GuiManuscriptBuild(self, self.mainGui, build)
dlgBuild.exec_()
dlgBuild = GuiManuscriptBuild(self, self.mainGui, build)
dlgBuild.exec_()
# After the build is done, save build settings changes
if build.changed:
self._builds.setBuild(build)
# After the build is done, save build settings changes
if build.changed:
self._builds.setBuild(build)
return
@@ -376,10 +374,13 @@ class GuiManuscript(QDialog):
return
def _getSelectedBuild(self) -> BuildSettings | None:
"""Get the currently selected build."""
bItems = self.buildList.selectedItems()
if bItems:
build = self._builds.getBuild(bItems[0].data(self.D_KEY))
"""Get the currently selected build. If none are selected,
automatically select the first one.
"""
items = self.buildList.selectedItems()
item = items[0] if items else self.buildList.item(0)
if item:
build = self._builds.getBuild(item.data(self.D_KEY))
if isinstance(build, BuildSettings):
return build
return None
@@ -406,13 +407,23 @@ class GuiManuscript(QDialog):
def _openSettingsDialog(self, build: BuildSettings):
"""Open the build settings dialog."""
dlgSettings = GuiBuildSettings(self, self.mainGui, build)
for obj in self.mainGui.children():
# Don't open a second dialog if one exists
if isinstance(obj, GuiBuildSettings):
if obj.buildID == build.buildID:
logger.debug("Found instance of GuiBuildSettings")
obj.show()
obj.raise_()
return
dlgSettings = GuiBuildSettings(self.mainGui, build)
dlgSettings.setModal(False)
dlgSettings.show()
dlgSettings.raise_()
qApp.processEvents()
dlgSettings.loadContent()
dlgSettings.newSettingsReady.connect(self._processNewSettings)
return
def _updateBuildsList(self):
@@ -634,7 +645,7 @@ class _PreviewWidget(QTextBrowser):
)
else:
strBuildTime = self.tr("Unknown")
text = "{0} {1}".format(self.tr("Built"), strBuildTime)
text = "{0}: {1}".format(self.tr("Built"), strBuildTime)
if self._buildName:
text = "<b>{0}</b><br>{1}".format(self._buildName, text)
self.ageLabel.setText(text)
+113 -67
View File
@@ -69,8 +69,8 @@ class GuiBuildSettings(QDialog):
newSettingsReady = pyqtSignal(BuildSettings)
def __init__(self, parent: QWidget, mainGui: GuiMain, build: BuildSettings):
super().__init__(parent=parent)
def __init__(self, mainGui: GuiMain, build: BuildSettings) -> None:
super().__init__(parent=mainGui)
logger.debug("Create: GuiBuildSettings")
self.setObjectName("GuiBuildSettings")
@@ -106,7 +106,7 @@ class GuiBuildSettings(QDialog):
self.optSideBar.setLabelColor(self.mainTheme.helpText)
self.optSideBar.addLabel(self.tr("Options"))
self.optSideBar.addButton(self.tr("Filters"), self.OPT_FILTERS)
self.optSideBar.addButton(self.tr("Selection"), self.OPT_FILTERS)
self.optSideBar.addButton(self.tr("Headings"), self.OPT_HEADINGS)
self.optSideBar.addButton(self.tr("Content"), self.OPT_CONTENT)
self.optSideBar.addButton(self.tr("Format"), self.OPT_FORMAT)
@@ -169,10 +169,11 @@ class GuiBuildSettings(QDialog):
return
def __del__(self): # pragma: no cover
def __del__(self) -> None: # pragma: no cover
logger.debug("Delete: GuiBuildSettings")
return
def loadContent(self):
def loadContent(self) -> None:
"""Populate the child widgets."""
self.editBuildName.setText(self._build.name)
self.optTabSelect.loadContent()
@@ -182,12 +183,21 @@ class GuiBuildSettings(QDialog):
self.optTabOutput.loadContent()
return
##
# Properties
##
@property
def buildID(self) -> str:
"""The build ID of the build of the dialog."""
return self._build.buildID
##
# Private Slots
##
@pyqtSlot(int)
def _stackPageSelected(self, pageId: int):
def _stackPageSelected(self, pageId: int) -> None:
"""Process a user request to switch page."""
if pageId == self.OPT_FILTERS:
self.toolStack.setCurrentWidget(self.optTabSelect)
@@ -202,7 +212,7 @@ class GuiBuildSettings(QDialog):
return
@pyqtSlot("QAbstractButton*")
def _dialogButtonClicked(self, button: QAbstractButton):
def _dialogButtonClicked(self, button: QAbstractButton) -> None:
"""Handle button clicks from the dialog button box."""
role = self.dlgButtons.buttonRole(button)
if role == QDialogButtonBox.ApplyRole:
@@ -218,7 +228,7 @@ class GuiBuildSettings(QDialog):
# Events
##
def closeEvent(self, event: QEvent):
def closeEvent(self, event: QEvent) -> None:
"""Capture the user closing the window so we can save
settings.
"""
@@ -233,7 +243,7 @@ class GuiBuildSettings(QDialog):
# Internal Functions
##
def _askToSaveBuild(self):
def _askToSaveBuild(self) -> None:
"""Check if there are unsaved changes, and if there are, ask if
it's ok to reject them.
"""
@@ -247,7 +257,7 @@ class GuiBuildSettings(QDialog):
self._build.resetChangedState()
return
def _saveSettings(self):
def _saveSettings(self) -> None:
"""Save the various user settings."""
logger.debug("Saving GuiBuildSettings settings")
@@ -265,7 +275,7 @@ class GuiBuildSettings(QDialog):
return
def _emitBuildData(self):
def _emitBuildData(self) -> None:
"""Assemble the build data and emit the signal."""
self._build.setName(self.editBuildName.text())
self.optTabHeadings.saveContent()
@@ -294,23 +304,26 @@ class _FilterTab(QWidget):
F_INCLUDED = 2
F_EXCLUDED = 3
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
super().__init__(parent=buildMain)
self.mainGui = buildMain.mainGui
self.mainTheme = buildMain.mainGui.mainTheme
self.theProject = buildMain.mainGui.theProject
self._treeMap = {}
self._treeMap: dict[str, QTreeWidgetItem] = {}
self._build = build
self._statusFlags = {
self.F_NONE: ("", QIcon()),
self.F_FILTERED: (self.tr("Filtered"), self.mainTheme.getIcon("build_filtered")),
self.F_INCLUDED: (self.tr("Included"), self.mainTheme.getIcon("build_included")),
self.F_EXCLUDED: (self.tr("Excluded"), self.mainTheme.getIcon("build_excluded")),
self._statusFlags: dict[int, QIcon] = {
self.F_NONE: QIcon(),
self.F_FILTERED: self.mainTheme.getIcon("build_filtered"),
self.F_INCLUDED: self.mainTheme.getIcon("build_included"),
self.F_EXCLUDED: self.mainTheme.getIcon("build_excluded"),
}
self._trIncluded = self.tr("Included in manuscript")
self._trExcluded = self.tr("Excluded from manuscript")
# Project Tree
# ============
@@ -341,27 +354,28 @@ class _FilterTab(QWidget):
# Filters
# =======
self.filteredButton = QToolButton(self)
self.filteredButton.setToolTip(self._statusFlags[self.F_FILTERED][0])
self.filteredButton.setIcon(self._statusFlags[self.F_FILTERED][1])
self.filteredButton.clicked.connect(lambda: self._setSelectedMode(self.F_FILTERED))
self.includedButton = QToolButton(self)
self.includedButton.setToolTip(self._statusFlags[self.F_INCLUDED][0])
self.includedButton.setIcon(self._statusFlags[self.F_INCLUDED][1])
self.includedButton.setToolTip(self.tr("Always included"))
self.includedButton.setIcon(self._statusFlags[self.F_INCLUDED])
self.includedButton.clicked.connect(lambda: self._setSelectedMode(self.F_INCLUDED))
self.excludedButton = QToolButton(self)
self.excludedButton.setToolTip(self._statusFlags[self.F_EXCLUDED][0])
self.excludedButton.setIcon(self._statusFlags[self.F_EXCLUDED][1])
self.excludedButton.setToolTip(self.tr("Always excluded"))
self.excludedButton.setIcon(self._statusFlags[self.F_EXCLUDED])
self.excludedButton.clicked.connect(lambda: self._setSelectedMode(self.F_EXCLUDED))
self.resetButton = QToolButton(self)
self.resetButton.setToolTip(self.tr("Reset to default"))
self.resetButton.setIcon(self.mainTheme.getIcon("revert"))
self.resetButton.clicked.connect(lambda: self._setSelectedMode(self.F_FILTERED))
self.modeBox = QHBoxLayout()
self.modeBox.addWidget(QLabel(self.tr("Mark selection as")))
self.modeBox.addStretch(1)
self.modeBox.addWidget(self.filteredButton)
self.modeBox.addWidget(self.includedButton)
self.modeBox.addWidget(self.excludedButton)
self.modeBox.addWidget(self.resetButton)
self.modeBox.setSpacing(CONFIG.pxInt(4))
# Filer Options
self.filterOpt = NSwitchBox(self, iPx)
@@ -401,7 +415,7 @@ class _FilterTab(QWidget):
return
def loadContent(self):
def loadContent(self) -> None:
"""Populate the widgets."""
self._populateTree()
self._populateFilters()
@@ -418,7 +432,7 @@ class _FilterTab(QWidget):
##
@pyqtSlot(str, bool)
def _applyFilterSwitch(self, key: str, state: bool):
def _applyFilterSwitch(self, key: str, state: bool) -> None:
"""Apply filter switch and update the settings."""
if key.startswith("doc:"):
self._build.setValue(key[4:], state)
@@ -432,7 +446,7 @@ class _FilterTab(QWidget):
# Internal Functions
##
def _populateTree(self):
def _populateTree(self) -> None:
"""Build the tree of project items."""
logger.debug("Building project tree")
self._treeMap = {}
@@ -486,7 +500,7 @@ class _FilterTab(QWidget):
return
def _populateFilters(self):
def _populateFilters(self) -> None:
"""Populate the filter options switches."""
self.filterOpt.clear()
self.filterOpt.addLabel(self._build.getLabel("filter"))
@@ -512,7 +526,7 @@ class _FilterTab(QWidget):
self.filterOpt.addSeparator()
# Root Classes
self.filterOpt.addLabel(self.tr("Root Folders"))
self.filterOpt.addLabel(self.tr("Select Root Folders"))
for tHandle, nwItem in self.theProject.tree.iterRoots(None):
if not nwItem.isInactiveClass():
itemIcon = self.mainTheme.getItemIcon(
@@ -525,9 +539,13 @@ class _FilterTab(QWidget):
return
def _setSelectedMode(self, mode: int):
def _setSelectedMode(self, mode: int) -> None:
"""Set the mode for the selected items."""
for item in self.optTree.selectedItems():
items = self.optTree.selectedItems()
if len(items) == 1 and isinstance(items[0], QTreeWidgetItem):
items = self._scanChildren(items[0], [])
for item in items:
if isinstance(item, QTreeWidgetItem):
tHandle = item.data(self.C_DATA, self.D_HANDLE)
isFile = item.data(self.C_DATA, self.D_FILE)
@@ -543,21 +561,34 @@ class _FilterTab(QWidget):
return
def _setTreeItemMode(self):
def _setTreeItemMode(self) -> None:
"""Update the filtered mode icon on all items."""
filtered = self._build.buildItemFilter(self.theProject)
for tHandle, item in self._treeMap.items():
allow, mode = filtered.get(tHandle, (False, FilterMode.UNKNOWN))
if mode == FilterMode.INCLUDED:
item.setIcon(self.C_STATUS, self._statusFlags[self.F_INCLUDED][1])
item.setIcon(self.C_STATUS, self._statusFlags[self.F_INCLUDED])
item.setToolTip(self.C_STATUS, self._trIncluded)
elif mode == FilterMode.EXCLUDED:
item.setIcon(self.C_STATUS, self._statusFlags[self.F_EXCLUDED][1])
item.setIcon(self.C_STATUS, self._statusFlags[self.F_EXCLUDED])
item.setToolTip(self.C_STATUS, self._trExcluded)
elif mode == FilterMode.FILTERED and allow:
item.setIcon(self.C_STATUS, self._statusFlags[self.F_FILTERED][1])
item.setIcon(self.C_STATUS, self._statusFlags[self.F_FILTERED])
item.setToolTip(self.C_STATUS, self._trIncluded)
else:
item.setIcon(self.C_STATUS, self._statusFlags[self.F_NONE][1])
item.setIcon(self.C_STATUS, self._statusFlags[self.F_NONE])
return
def _scanChildren(self, item: QTreeWidgetItem | None, items: list) -> list[QTreeWidgetItem]:
"""This is a recursive function returning all items in a tree
starting at a given QTreeWidgetItem.
"""
if isinstance(item, QTreeWidgetItem):
items.append(item)
for i in range(item.childCount()):
self._scanChildren(item.child(i), items)
return items
# END Class _FilterTab
@@ -569,7 +600,7 @@ class _HeadingsTab(QWidget):
EDIT_SCENE = 4
EDIT_SECTION = 5
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
super().__init__(parent=buildMain)
self.mainGui = buildMain.mainGui
@@ -747,7 +778,7 @@ class _HeadingsTab(QWidget):
return
def loadContent(self):
def loadContent(self) -> None:
"""Populate the widgets."""
self.fmtTitle.setText(self._build.getStr("headings.fmtTitle"))
self.fmtChapter.setText(self._build.getStr("headings.fmtChapter"))
@@ -758,7 +789,7 @@ class _HeadingsTab(QWidget):
self.swtSection.setChecked(self._build.getBool("headings.hideSection"))
return
def saveContent(self):
def saveContent(self) -> None:
"""Save choices back into build object."""
self._build.setValue("headings.hideScene", self.swtScene.isChecked())
self._build.setValue("headings.hideSection", self.swtSection.isChecked())
@@ -768,7 +799,7 @@ class _HeadingsTab(QWidget):
# Internal Functions
##
def _insertIntoForm(self, text: str):
def _insertIntoForm(self, text: str) -> None:
"""Insert formatting text from the dropdown menu."""
if self._editing > 0:
cursor = self.editTextBox.textCursor()
@@ -776,7 +807,7 @@ class _HeadingsTab(QWidget):
self.editTextBox.setFocus()
return
def _editHeading(self, heading: int):
def _editHeading(self, heading: int) -> None:
"""Populate the form with a specific heading format."""
self._editing = heading
self.editTextBox.setEnabled(True)
@@ -801,7 +832,7 @@ class _HeadingsTab(QWidget):
text = ""
label = self.tr("None")
self.editTextBox.setPlainText(text.replace("//", "\n"))
self.editTextBox.setPlainText(text.replace(nwHeadFmt.BR, "\n"))
self.lblEditForm.setText(self.tr("Editing: {0}").format(label))
return
@@ -810,10 +841,10 @@ class _HeadingsTab(QWidget):
# Private Slots
##
def _saveFormat(self):
def _saveFormat(self) -> None:
"""Save the format from the edit text box."""
heading = self._editing
text = self.editTextBox.toPlainText().strip().replace("\n", "//")
text = self.editTextBox.toPlainText().strip().replace("\n", nwHeadFmt.BR)
if heading == self.EDIT_TITLE:
self.fmtTitle.setText(text)
self._build.setValue("headings.fmtTitle", text)
@@ -842,7 +873,7 @@ class _HeadingsTab(QWidget):
class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
def __init__(self, document: QTextDocument, mainTheme: GuiTheme):
def __init__(self, document: QTextDocument, mainTheme: GuiTheme) -> None:
super().__init__(document)
self._fmtSymbol = QTextCharFormat()
self._fmtSymbol.setForeground(QColor(*mainTheme.colHead))
@@ -850,7 +881,7 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
self._fmtFormat.setForeground(QColor(*mainTheme.colEmph))
return
def highlightBlock(self, text: str):
def highlightBlock(self, text: str) -> None:
"""Add syntax highlighting to the text block."""
for heading in nwHeadFmt.ALL:
pos = text.find(heading)
@@ -868,7 +899,7 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
class _ContentTab(QWidget):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
super().__init__(parent=buildMain)
self.mainGui = buildMain.mainGui
@@ -917,7 +948,7 @@ class _ContentTab(QWidget):
return
def loadContent(self):
def loadContent(self) -> None:
"""Populate the widgets."""
self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis"))
self.incComments.setChecked(self._build.getBool("text.includeComments"))
@@ -926,7 +957,7 @@ class _ContentTab(QWidget):
self.addNoteHead.setChecked(self._build.getBool("text.addNoteHeadings"))
return
def saveContent(self):
def saveContent(self) -> None:
"""Save choices back into build object."""
self._build.setValue("text.includeSynopsis", self.incSynopsis.isChecked())
self._build.setValue("text.includeComments", self.incComments.isChecked())
@@ -940,7 +971,7 @@ class _ContentTab(QWidget):
class _FormatTab(QWidget):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
super().__init__(parent=buildMain)
self.buildMain = buildMain
@@ -1033,10 +1064,12 @@ class _FormatTab(QWidget):
self.pageWidth = QDoubleSpinBox(self)
self.pageWidth.setFixedWidth(dbW)
self.pageWidth.setMaximum(500.0)
self.pageWidth.valueChanged.connect(self._pageSizeValueChanged)
self.pageHeight = QDoubleSpinBox(self)
self.pageHeight.setFixedWidth(dbW)
self.pageHeight.setMaximum(500.0)
self.pageHeight.valueChanged.connect(self._pageSizeValueChanged)
self.topMargin = QDoubleSpinBox(self)
self.topMargin.setFixedWidth(dbW)
@@ -1085,7 +1118,7 @@ class _FormatTab(QWidget):
return
def loadContent(self):
def loadContent(self) -> None:
"""Populate the widgets."""
langIdx = self.buildLang.findData(self._build.getStr("format.buildLang"))
if langIdx != -1:
@@ -1128,7 +1161,7 @@ class _FormatTab(QWidget):
return
def saveContent(self):
def saveContent(self) -> None:
"""Save choices back into build object."""
self._build.setValue("format.buildLang", str(self.buildLang.currentData()))
self._build.setValue("format.textFont", self.textFont.text())
@@ -1154,7 +1187,7 @@ class _FormatTab(QWidget):
##
@pyqtSlot()
def _selectFont(self):
def _selectFont(self) -> None:
"""Open the QFontDialog and set a font for the font style."""
currFont = QFont()
currFont.setFamily(self.textFont.text())
@@ -1166,7 +1199,7 @@ class _FormatTab(QWidget):
return
@pyqtSlot(int)
def _changeUnit(self, index: int):
def _changeUnit(self, index: int) -> None:
"""The current unit change, so recalculate sizes."""
newUnit = self.pageUnit.itemData(index)
newScale = nwLabels.UNIT_SCALE.get(newUnit, 1.0)
@@ -1185,15 +1218,19 @@ class _FormatTab(QWidget):
pMax = 500.0 if isMM else 50.0
mMax = 150.0 if isMM else 15.0
self.pageWidth.blockSignals(True)
self.pageWidth.setDecimals(nDec)
self.pageWidth.setSingleStep(nStep)
self.pageWidth.setMaximum(pMax)
self.pageWidth.setValue(pageWidth)
self.pageWidth.blockSignals(False)
self.pageHeight.blockSignals(True)
self.pageHeight.setDecimals(nDec)
self.pageHeight.setSingleStep(nStep)
self.pageHeight.setMaximum(pMax)
self.pageHeight.setValue(pageHeight)
self.pageHeight.blockSignals(False)
self.topMargin.setDecimals(nDec)
self.topMargin.setSingleStep(nStep)
@@ -1216,22 +1253,31 @@ class _FormatTab(QWidget):
self.rightMargin.setValue(rightMargin)
self._unitScale = newScale
self._changePageSize(self.pageSize.currentIndex())
return
@pyqtSlot(int)
def _changePageSize(self, index: int):
def _changePageSize(self, index: int) -> None:
"""The page size has changed."""
self.pageWidth.setEnabled(True)
self.pageHeight.setEnabled(True)
w, h = nwLabels.PAPER_SIZE[self.pageSize.itemData(index)] if index >= 0 else (-1.0, -1.0)
if w > 0.0 and h > 0.0:
self.pageWidth.setEnabled(False)
self.pageHeight.setEnabled(False)
self.pageWidth.blockSignals(True)
self.pageWidth.setValue(w/self._unitScale)
self.pageWidth.blockSignals(False)
self.pageHeight.blockSignals(True)
self.pageHeight.setValue(h/self._unitScale)
self.pageHeight.blockSignals(False)
return
@pyqtSlot()
def _pageSizeValueChanged(self):
"""The user has changed the page size spin boxes, so we flip
the page size box to Custom.
"""
index = self.pageSize.findData("Custom")
if index >= 0:
self.pageSize.setCurrentIndex(index)
return
# END Class _FormatTab
@@ -1239,7 +1285,7 @@ class _FormatTab(QWidget):
class _OutputTab(QWidget):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
super().__init__(parent=buildMain)
self.mainGui = buildMain.mainGui
@@ -1282,13 +1328,13 @@ class _OutputTab(QWidget):
return
def loadContent(self):
def loadContent(self) -> None:
"""Populate the widgets."""
self.odtAddColours.setChecked(self._build.getBool("odt.addColours"))
self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
return
def saveContent(self):
def saveContent(self) -> None:
"""Save choices back into build object."""
self._build.setValue("odt.addColours", self.odtAddColours.isChecked())
self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
+2 -7
View File
@@ -168,11 +168,12 @@ def testManuscript_Features(monkeypatch, qtbot: QtBot, nwGUI: GuiMain, projPath:
# ========
# No build selected
manus.buildList.clearSelection()
manus.buildList.clear()
manus.btnPreview.click()
qtbot.wait(200) # Should be enough to run the build
assert manus.docPreview.toPlainText().strip() == ""
assert cacheFile.exists() is False
manus._updateBuildsList()
# Preview the first, but fail to save cache
manus.buildList.setCurrentRow(0)
@@ -207,12 +208,6 @@ def testManuscript_Features(monkeypatch, qtbot: QtBot, nwGUI: GuiMain, projPath:
with monkeypatch.context() as mp:
mp.setattr("novelwriter.tools.manusbuild.GuiManuscriptBuild.exec_", lambda *a: None)
# With no selection, no dialog should be created
manus.btnBuild.click()
for obj in manus.children():
assert not isinstance(obj, GuiManuscriptBuild)
# With a selection, there should be one
manus.buildList.setCurrentRow(0)
manus.btnBuild.click()
for obj in manus.children():
+36 -17
View File
@@ -47,7 +47,7 @@ def testBuildSettings_Init(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockRnd
build = BuildSettings()
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
@@ -132,10 +132,10 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
hCharDoc = nwGUI.theProject.newFile("Jane Doe", C.hCharRoot)
nwGUI.projView.projTree.revealNewTreeItem(hPlotDoc)
nwGUI.projView.projTree.revealNewTreeItem(hCharDoc)
nwGUI.theProject.tree[hPlotDoc].setActive(False)
nwGUI.theProject.tree[hPlotDoc].setActive(False) # type: ignore
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
@@ -147,7 +147,7 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
assert filterTab.optTree.topLevelItemCount() == 4 # The 4 root folders
assert filterTab.filterOpt._index == 10 # 2 headers, 1 sep, 3 opt and 4 roots
# Untoggle note folders
# Un-toggle note folders
filterTab.filterOpt._widgets[switchMap["worldRoot"]].setChecked(False) # World Root
assert filterTab.optTree.topLevelItemCount() == 3
assert C.hWorldRoot in build._skipRoot
@@ -229,8 +229,8 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
# Set char and plot docs to excluded
filterTab.optTree.clearSelection()
filterTab._treeMap[hPlotDoc].setSelected(True)
filterTab._treeMap[hCharDoc].setSelected(True)
filterTab._treeMap[hPlotDoc].setSelected(True) # type: ignore
filterTab._treeMap[hCharDoc].setSelected(True) # type: ignore
filterTab.excludedButton.click()
assert build.buildItemFilter(nwGUI.theProject) == {
C.hNovelRoot: (False, FilterMode.SKIPPED),
@@ -260,13 +260,30 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
C.hWorldRoot: (False, FilterMode.SKIPPED),
}
# Selecting only novel root should iterate through all children
filterTab.optTree.clearSelection()
filterTab._treeMap[C.hNovelRoot].setSelected(True)
filterTab.resetButton.click()
assert build.buildItemFilter(nwGUI.theProject) == {
C.hNovelRoot: (False, FilterMode.SKIPPED),
C.hTitlePage: (True, FilterMode.FILTERED),
C.hChapterDir: (False, FilterMode.SKIPPED),
C.hChapterDoc: (True, FilterMode.FILTERED),
C.hSceneDoc: (True, FilterMode.FILTERED),
C.hPlotRoot: (False, FilterMode.SKIPPED),
hPlotDoc: (False, FilterMode.EXCLUDED),
C.hCharRoot: (False, FilterMode.SKIPPED),
hCharDoc: (False, FilterMode.EXCLUDED),
C.hWorldRoot: (False, FilterMode.SKIPPED),
}
# Set everything back to filtered
filterTab.optTree.clearSelection()
filterTab._treeMap[C.hChapterDoc].setSelected(True)
filterTab._treeMap[C.hNovelRoot].setSelected(True)
filterTab._treeMap[C.hSceneDoc].setSelected(True)
filterTab._treeMap[hPlotDoc].setSelected(True)
filterTab._treeMap[hCharDoc].setSelected(True)
filterTab.filteredButton.click()
filterTab._treeMap[hPlotDoc].setSelected(True) # type: ignore
filterTab._treeMap[hCharDoc].setSelected(True) # type: ignore
filterTab.resetButton.click()
assert build.buildItemFilter(nwGUI.theProject) == {
C.hNovelRoot: (False, FilterMode.SKIPPED),
C.hTitlePage: (True, FilterMode.FILTERED),
@@ -285,8 +302,8 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
C.hNovelRoot, C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
C.hPlotRoot, hPlotDoc, C.hCharRoot, hCharDoc,
]
nwGUI.theProject.tree[hCharDoc].setRoot(None) # Char doc has no root handle
nwGUI.theProject.tree[hPlotDoc].setParent(None) # Plot doc has no parent handle
nwGUI.theProject.tree[hCharDoc].setRoot(None) # type: ignore
nwGUI.theProject.tree[hPlotDoc].setParent(None) # type: ignore
filterTab._populateTree()
assert list(filterTab._treeMap.keys()) == [
C.hNovelRoot, C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
@@ -320,7 +337,7 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
build.setValue("headings.hideSection", False)
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
@@ -412,7 +429,9 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
headTab.btnChapter.click()
headTab.editTextBox.setPlainText(f"Chapter {nwHeadFmt.CH_NUM}\n{nwHeadFmt.TITLE}\n")
headTab.btnApply.click()
assert build.getStr("headings.fmtChapter") == f"Chapter {nwHeadFmt.CH_NUM}//{nwHeadFmt.TITLE}"
assert build.getStr("headings.fmtChapter") == (
f"Chapter {nwHeadFmt.CH_NUM}{nwHeadFmt.BR}{nwHeadFmt.TITLE}"
)
# Set all to plain title
headTab.btnTitle.click()
@@ -467,7 +486,7 @@ def testBuildSettings_Content(qtbot: QtBot, nwGUI: GuiMain):
build.setValue("text.addNoteHeadings", False)
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
@@ -534,7 +553,7 @@ def testBuildSettings_Format(monkeypatch, qtbot: QtBot, nwGUI: GuiMain):
build.setValue("format.rightMargin", 15.0)
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
@@ -622,7 +641,7 @@ def testBuildSettings_Output(qtbot: QtBot, nwGUI: GuiMain):
build.setValue("html.addStyles", False)
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()