Files
novelWriter/tests/test_tools/test_tools_manussettings.py
T
Veronica Berglyd Olsen 5bdbd7c195 Update linting for tests
2025-08-27 21:04:32 +02:00

839 lines
30 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
novelWriter Manuscript Build Settings Dialog Tester
=====================================================
This file is a part of novelWriter
Copyright (C) 2023 Veronica Berglyd Olsen and novelWriter contributors
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 <https://www.gnu.org/licenses/>.
""" # noqa
from __future__ import annotations
import pytest
from PyQt6.QtCore import pyqtSlot
from PyQt6.QtGui import QFont
from PyQt6.QtWidgets import QFontDialog
from novelwriter import SHARED
from novelwriter.common import describeFont
from novelwriter.constants import nwHeadFmt
from novelwriter.core.buildsettings import BuildSettings, FilterMode
from novelwriter.tools.manussettings import (
GuiBuildSettings, _FilterTab, _FormattingTab, _HeadingsTab
)
from novelwriter.types import QtDialogApply, QtDialogClose, QtDialogSave
from tests.tools import C, buildTestProject
@pytest.mark.gui
def testToolBuildSettings_Init(qtbot, nwGUI, projPath, mockRnd):
"""Test the initialisation of the GuiBuildSettings dialog."""
buildTestProject(nwGUI, projPath)
nwGUI.openProject(projPath)
build = BuildSettings()
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
# Flip through pages
button = bSettings.sidebar._group.button(bSettings.OPT_FORMATTING + 1)
assert button is not None
button.click()
assert isinstance(bSettings.toolStack.currentWidget(), _FormattingTab)
button = bSettings.sidebar._group.button(bSettings.OPT_HEADINGS)
assert button is not None
button.click()
assert isinstance(bSettings.toolStack.currentWidget(), _HeadingsTab)
button = bSettings.sidebar._group.button(bSettings.OPT_FILTERS)
assert button is not None
button.click()
assert isinstance(bSettings.toolStack.currentWidget(), _FilterTab)
# Check dialog buttons
triggered = False
@pyqtSlot(BuildSettings)
def _testNewSettingsReady(new: BuildSettings):
nonlocal triggered
assert new.buildID == build.buildID
triggered = True
# Capture Apply button
with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000):
bSettings.newSettingsReady.connect(_testNewSettingsReady)
button = bSettings.buttonBox.button(QtDialogApply)
assert button is not None
bSettings._dialogButtonClicked(button)
assert triggered
# Capture Save button
triggered = False
with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000):
bSettings.newSettingsReady.connect(_testNewSettingsReady)
button = bSettings.buttonBox.button(QtDialogSave)
assert button is not None
bSettings._dialogButtonClicked(button)
assert triggered
# Close manually
# This pops the ask to save dialog, which is automatically handled
triggered = False
build._changed = True
bSettings.show()
with qtbot.waitSignal(bSettings.newSettingsReady, timeout=5000):
bSettings.newSettingsReady.connect(_testNewSettingsReady)
bSettings._build._changed = True
bSettings.close()
assert triggered
# Finish
button = bSettings.buttonBox.button(QtDialogClose)
assert button is not None
bSettings._dialogButtonClicked(button)
# qtbot.stop()
@pytest.mark.gui
def testToolBuildSettings_Filter(qtbot, nwGUI, projPath, mockRnd):
"""Test the Filter Tab of the GuiBuildSettings dialog."""
buildTestProject(nwGUI, projPath)
nwGUI.openProject(projPath)
build = BuildSettings()
switchMap = {
"incNovel": 1,
"incNotes": 2,
"incInactive": 3,
"novelRoot": 6,
"plotRoot": 7,
"charRoot": 8,
"worldRoot": 9,
}
hPlotDoc = SHARED.project.newFile("Main Plot", C.hPlotRoot)
hCharDoc = SHARED.project.newFile("Jane Doe", C.hCharRoot)
SHARED.project.tree[hPlotDoc].setActive(False) # type: ignore
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
sBuild = bSettings._build
assert sBuild.buildID == build.buildID
filterTab = bSettings.optTabSelect
button = bSettings.sidebar._group.button(bSettings.OPT_FILTERS)
assert button is not None
button.click()
assert bSettings.toolStack.currentWidget() is filterTab
# Check content
assert filterTab.optTree.topLevelItemCount() == 4 # The 4 root folders
assert filterTab.filterOpt._index == 10 # 2 headers, 1 sep, 3 opt and 4 roots
# Un-toggle note folders
filterTab.filterOpt._widgets[switchMap["worldRoot"]].setChecked(False) # World Root
assert filterTab.optTree.topLevelItemCount() == 3
assert C.hWorldRoot in sBuild._skipRoot
filterTab.filterOpt._widgets[switchMap["charRoot"]].setChecked(False) # Char Root
assert filterTab.optTree.topLevelItemCount() == 2
assert C.hCharRoot in sBuild._skipRoot
filterTab.filterOpt._widgets[switchMap["plotRoot"]].setChecked(False) # Plot Root
assert filterTab.optTree.topLevelItemCount() == 1
assert C.hPlotRoot in sBuild._skipRoot
# Reset Plot and Char
filterTab.filterOpt._widgets[switchMap["plotRoot"]].setChecked(True)
filterTab.filterOpt._widgets[switchMap["charRoot"]].setChecked(True)
assert filterTab.optTree.topLevelItemCount() == 3
# Switch off novel docs
filterTab.filterOpt._widgets[switchMap["incNovel"]].setChecked(False)
assert sBuild.buildItemFilter(SHARED.project) == {
C.hNovelRoot: (False, FilterMode.SKIPPED),
C.hTitlePage: (False, FilterMode.FILTERED),
C.hChapterDir: (False, FilterMode.SKIPPED),
C.hChapterDoc: (False, FilterMode.FILTERED),
C.hSceneDoc: (False, FilterMode.FILTERED),
C.hPlotRoot: (False, FilterMode.SKIPPED),
hPlotDoc: (False, FilterMode.FILTERED),
C.hCharRoot: (False, FilterMode.SKIPPED),
hCharDoc: (False, FilterMode.FILTERED),
C.hWorldRoot: (False, FilterMode.SKIPPED),
C.hTrashRoot: (False, FilterMode.SKIPPED),
}
# Switch on note docs
filterTab.filterOpt._widgets[switchMap["incNotes"]].setChecked(True)
assert sBuild.buildItemFilter(SHARED.project) == {
C.hNovelRoot: (False, FilterMode.SKIPPED),
C.hTitlePage: (False, FilterMode.FILTERED),
C.hChapterDir: (False, FilterMode.SKIPPED),
C.hChapterDoc: (False, FilterMode.FILTERED),
C.hSceneDoc: (False, FilterMode.FILTERED),
C.hPlotRoot: (False, FilterMode.SKIPPED),
hPlotDoc: (False, FilterMode.FILTERED), # Set to inactive
C.hCharRoot: (False, FilterMode.SKIPPED),
hCharDoc: (True, FilterMode.FILTERED), # Now enabled
C.hWorldRoot: (False, FilterMode.SKIPPED),
C.hTrashRoot: (False, FilterMode.SKIPPED),
}
# Switch on inactive docs
filterTab.filterOpt._widgets[switchMap["incInactive"]].setChecked(True)
assert sBuild.buildItemFilter(SHARED.project) == {
C.hNovelRoot: (False, FilterMode.SKIPPED),
C.hTitlePage: (False, FilterMode.FILTERED),
C.hChapterDir: (False, FilterMode.SKIPPED),
C.hChapterDoc: (False, FilterMode.FILTERED),
C.hSceneDoc: (False, FilterMode.FILTERED),
C.hPlotRoot: (False, FilterMode.SKIPPED),
hPlotDoc: (True, FilterMode.FILTERED), # Now enabled
C.hCharRoot: (False, FilterMode.SKIPPED),
hCharDoc: (True, FilterMode.FILTERED),
C.hWorldRoot: (False, FilterMode.SKIPPED),
C.hTrashRoot: (False, FilterMode.SKIPPED),
}
# Set chapter and scene docs to included
filterTab._treeMap[C.hChapterDoc].setSelected(True)
filterTab._treeMap[C.hSceneDoc].setSelected(True)
filterTab.includedButton.click()
assert sBuild.buildItemFilter(SHARED.project) == {
C.hNovelRoot: (False, FilterMode.SKIPPED),
C.hTitlePage: (False, FilterMode.FILTERED),
C.hChapterDir: (False, FilterMode.SKIPPED),
C.hChapterDoc: (True, FilterMode.INCLUDED), # Now included
C.hSceneDoc: (True, FilterMode.INCLUDED), # Now included
C.hPlotRoot: (False, FilterMode.SKIPPED),
hPlotDoc: (True, FilterMode.FILTERED),
C.hCharRoot: (False, FilterMode.SKIPPED),
hCharDoc: (True, FilterMode.FILTERED),
C.hWorldRoot: (False, FilterMode.SKIPPED),
C.hTrashRoot: (False, FilterMode.SKIPPED),
}
# Set char and plot docs to excluded
filterTab.optTree.clearSelection()
filterTab._treeMap[hPlotDoc].setSelected(True) # type: ignore
filterTab._treeMap[hCharDoc].setSelected(True) # type: ignore
filterTab.excludedButton.click()
assert sBuild.buildItemFilter(SHARED.project) == {
C.hNovelRoot: (False, FilterMode.SKIPPED),
C.hTitlePage: (False, FilterMode.FILTERED),
C.hChapterDir: (False, FilterMode.SKIPPED),
C.hChapterDoc: (True, FilterMode.INCLUDED),
C.hSceneDoc: (True, FilterMode.INCLUDED),
C.hPlotRoot: (False, FilterMode.SKIPPED),
hPlotDoc: (False, FilterMode.EXCLUDED), # Now excluded
C.hCharRoot: (False, FilterMode.SKIPPED),
hCharDoc: (False, FilterMode.EXCLUDED), # Now excluded
C.hWorldRoot: (False, FilterMode.SKIPPED),
C.hTrashRoot: (False, FilterMode.SKIPPED),
}
# Switch on novel docs
filterTab.filterOpt._widgets[switchMap["incNovel"]].setChecked(True)
assert sBuild.buildItemFilter(SHARED.project) == {
C.hNovelRoot: (False, FilterMode.SKIPPED),
C.hTitlePage: (True, FilterMode.FILTERED), # Now enabled
C.hChapterDir: (False, FilterMode.SKIPPED),
C.hChapterDoc: (True, FilterMode.INCLUDED),
C.hSceneDoc: (True, FilterMode.INCLUDED),
C.hPlotRoot: (False, FilterMode.SKIPPED),
hPlotDoc: (False, FilterMode.EXCLUDED),
C.hCharRoot: (False, FilterMode.SKIPPED),
hCharDoc: (False, FilterMode.EXCLUDED),
C.hWorldRoot: (False, FilterMode.SKIPPED),
C.hTrashRoot: (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 sBuild.buildItemFilter(SHARED.project) == {
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),
C.hTrashRoot: (False, FilterMode.SKIPPED),
}
# Set everything back to filtered
filterTab.optTree.clearSelection()
filterTab._treeMap[C.hNovelRoot].setSelected(True)
filterTab._treeMap[C.hSceneDoc].setSelected(True)
filterTab._treeMap[hPlotDoc].setSelected(True) # type: ignore
filterTab._treeMap[hCharDoc].setSelected(True) # type: ignore
filterTab.resetButton.click()
assert sBuild.buildItemFilter(SHARED.project) == {
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: (True, FilterMode.FILTERED),
C.hCharRoot: (False, FilterMode.SKIPPED),
hCharDoc: (True, FilterMode.FILTERED),
C.hWorldRoot: (False, FilterMode.SKIPPED),
C.hTrashRoot: (False, FilterMode.SKIPPED),
}
# Check handling of invalid project items
assert list(filterTab._treeMap.keys()) == [
C.hNovelRoot, C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
C.hPlotRoot, hPlotDoc, C.hCharRoot, hCharDoc,
]
SHARED.project.tree[hCharDoc].setRoot(None) # type: ignore
SHARED.project.tree[hPlotDoc].setParent(None) # type: ignore
filterTab._populateTree()
assert list(filterTab._treeMap.keys()) == [
C.hNovelRoot, C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
C.hPlotRoot, C.hCharRoot
]
# Finish
button = bSettings.buttonBox.button(QtDialogClose)
assert button is not None
bSettings._dialogButtonClicked(button)
# qtbot.stop()
@pytest.mark.gui
def testToolBuildSettings_Headings(qtbot, nwGUI):
"""Test the Headings Tab of the GuiBuildSettings dialog."""
build = BuildSettings()
ttTitle = f"Part: {nwHeadFmt.TITLE}"
chTitle = f"Chapter: {nwHeadFmt.TITLE}"
unTitle = f"Interlude: {nwHeadFmt.TITLE}"
scTitle = f"Scene: {nwHeadFmt.TITLE}"
shTitle = f"Hard Scene: {nwHeadFmt.TITLE}"
sxTitle = f"Section: {nwHeadFmt.TITLE}"
build.setValue("headings.fmtPart", ttTitle)
build.setValue("headings.fmtChapter", chTitle)
build.setValue("headings.fmtUnnumbered", unTitle)
build.setValue("headings.fmtScene", scTitle)
build.setValue("headings.fmtAltScene", shTitle)
build.setValue("headings.fmtSection", sxTitle)
build.setValue("headings.hideScene", False)
build.setValue("headings.hideSection", False)
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
headTab = bSettings.optTabHeadings
button = bSettings.sidebar._group.button(bSettings.OPT_HEADINGS)
assert button is not None
button.click()
assert bSettings.toolStack.currentWidget() is headTab
# Check initial values
assert headTab.fmtPart.text() == ttTitle
assert headTab.fmtChapter.text() == chTitle
assert headTab.fmtUnnumbered.text() == unTitle
assert headTab.fmtScene.text() == scTitle
assert headTab.fmtAScene.text() == shTitle
assert headTab.fmtSection.text() == sxTitle
assert headTab.swtScene.isChecked() is False
assert headTab.swtSection.isChecked() is False
# Edit in Turn
# ============
# Nothing to apply
assert headTab._editing == 0
assert headTab.editTextBox.isEnabled() is False
headTab.btnApply.click()
assert headTab.editTextBox.isEnabled() is False
# Title
headTab.btnPart.click()
assert headTab._editing == headTab.EDIT_TITLE
assert headTab.editTextBox.isEnabled() is True
assert headTab.editTextBox.toPlainText() == ttTitle
headTab.btnApply.click()
assert headTab.editTextBox.isEnabled() is False
# Chapter
headTab.btnChapter.click()
assert headTab._editing == headTab.EDIT_CHAPTER
assert headTab.editTextBox.isEnabled() is True
assert headTab.editTextBox.toPlainText() == chTitle
headTab.btnApply.click()
assert headTab.editTextBox.isEnabled() is False
# Unnumbered
headTab.btnUnnumbered.click()
assert headTab._editing == headTab.EDIT_UNNUM
assert headTab.editTextBox.isEnabled() is True
assert headTab.editTextBox.toPlainText() == unTitle
headTab.btnApply.click()
assert headTab.editTextBox.isEnabled() is False
# Scene
headTab.btnScene.click()
assert headTab._editing == headTab.EDIT_SCENE
assert headTab.editTextBox.isEnabled() is True
assert headTab.editTextBox.toPlainText() == scTitle
headTab.btnApply.click()
assert headTab.editTextBox.isEnabled() is False
# Hard Scene
headTab.btnAScene.click()
assert headTab._editing == headTab.EDIT_HSCENE
assert headTab.editTextBox.isEnabled() is True
assert headTab.editTextBox.toPlainText() == shTitle
headTab.btnApply.click()
assert headTab.editTextBox.isEnabled() is False
# Section
headTab.btnSection.click()
assert headTab._editing == headTab.EDIT_SECTION
assert headTab.editTextBox.isEnabled() is True
assert headTab.editTextBox.toPlainText() == sxTitle
headTab.btnApply.click()
assert headTab.editTextBox.isEnabled() is False
# Edit a Heading
# ==============
sBuild = bSettings._build
assert sBuild.buildID == build.buildID
# Create new format of all bits
headTab.btnChapter.click()
allFmt = (
f"{nwHeadFmt.TITLE}{nwHeadFmt.CH_NUM}{nwHeadFmt.CH_WORD}{nwHeadFmt.CH_ROMU}"
f"{nwHeadFmt.CH_ROML}{nwHeadFmt.SC_NUM}{nwHeadFmt.SC_ABS}"
)
headTab.editTextBox.clear()
assert headTab.editTextBox.toPlainText() == ""
headTab.aInsTitle.trigger()
headTab.aInsChNum.trigger()
headTab.aInsChWord.trigger()
headTab.aInsChRomU.trigger()
headTab.aInsChRomL.trigger()
headTab.aInsScNum.trigger()
headTab.aInsScAbs.trigger()
assert headTab.editTextBox.toPlainText() == allFmt
headTab.btnApply.click()
assert sBuild.getStr("headings.fmtChapter") == allFmt
# Check complex format
headTab.btnChapter.click()
headTab.editTextBox.setPlainText(f"Chapter {nwHeadFmt.CH_NUM}\n{nwHeadFmt.TITLE}\n")
headTab.btnApply.click()
assert sBuild.getStr("headings.fmtChapter") == (
f"Chapter {nwHeadFmt.CH_NUM}{nwHeadFmt.BR}{nwHeadFmt.TITLE}"
)
# Set all to plain title
headTab.btnPart.click()
headTab.editTextBox.setPlainText(nwHeadFmt.TITLE)
headTab.btnApply.click()
assert sBuild.getStr("headings.fmtPart") == nwHeadFmt.TITLE
headTab.btnChapter.click()
headTab.editTextBox.setPlainText(nwHeadFmt.TITLE)
headTab.btnApply.click()
assert sBuild.getStr("headings.fmtChapter") == nwHeadFmt.TITLE
headTab.btnUnnumbered.click()
headTab.editTextBox.setPlainText(nwHeadFmt.TITLE)
headTab.btnApply.click()
assert sBuild.getStr("headings.fmtUnnumbered") == nwHeadFmt.TITLE
headTab.btnScene.click()
headTab.editTextBox.setPlainText(nwHeadFmt.TITLE)
headTab.btnApply.click()
assert sBuild.getStr("headings.fmtScene") == nwHeadFmt.TITLE
headTab.btnAScene.click()
headTab.editTextBox.setPlainText(nwHeadFmt.TITLE)
headTab.btnApply.click()
assert sBuild.getStr("headings.fmtAltScene") == nwHeadFmt.TITLE
headTab.btnSection.click()
headTab.editTextBox.setPlainText(nwHeadFmt.TITLE)
headTab.btnApply.click()
assert sBuild.getStr("headings.fmtSection") == nwHeadFmt.TITLE
# Check hide switches
headTab.swtScene.setChecked(True)
headTab.swtSection.setChecked(True)
headTab.saveContent()
sBuild = bSettings._build
assert sBuild.buildID == build.buildID
assert sBuild.getBool("headings.hideScene") is True
assert sBuild.getBool("headings.hideSection") is True
# Finish
button = bSettings.buttonBox.button(QtDialogClose)
assert button is not None
bSettings._dialogButtonClicked(button)
# qtbot.stop()
@pytest.mark.gui
def testToolBuildSettings_FormatTextContent(qtbot, nwGUI):
"""Test the Text Content settings."""
build = BuildSettings()
build.setValue("text.includeBodyText", False)
build.setValue("text.includeSynopsis", False)
build.setValue("text.includeComments", False)
build.setValue("text.includeStory", False)
build.setValue("text.includeNotes", False)
build.setValue("text.includeKeywords", False)
build.setValue("text.ignoredKeywords", "")
build.setValue("text.addNoteHeadings", False)
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
fmtTab = bSettings.optTabFormatting
button = bSettings.sidebar._group.button(bSettings.OPT_FORMATTING + 1)
assert button is not None
button.click()
assert bSettings.toolStack.currentWidget() is fmtTab
# Check initial values
assert fmtTab.incBodyText.isChecked() is False
assert fmtTab.incSynopsis.isChecked() is False
assert fmtTab.incComments.isChecked() is False
assert fmtTab.incStory.isChecked() is False
assert fmtTab.incNotes.isChecked() is False
assert fmtTab.incKeywords.isChecked() is False
assert fmtTab.ignoredKeywords.text() == ""
assert fmtTab.addNoteHead.isChecked() is False
# Toggle switches
fmtTab.incBodyText.setChecked(True)
fmtTab.incSynopsis.setChecked(True)
fmtTab.incComments.setChecked(True)
fmtTab.incStory.setChecked(True)
fmtTab.incNotes.setChecked(True)
fmtTab.incKeywords.setChecked(True)
fmtTab.addNoteHead.setChecked(True)
# Test cleanup of ignored keywords
fmtTab.ignoredKeywords.setText("@stuff, @pizza, @object") # First two are invalid
fmtTab._updateIgnoredKeywords("@custom") # Adding a new should trigger cleanup
assert fmtTab.ignoredKeywords.text() in ("@custom, @object", "@object, @custom")
# Save values
fmtTab.saveContent()
sBuild = bSettings._build
assert sBuild.buildID == build.buildID
assert sBuild.getBool("text.includeBodyText") is True
assert sBuild.getBool("text.includeSynopsis") is True
assert sBuild.getBool("text.includeComments") is True
assert sBuild.getBool("text.includeStory") is True
assert sBuild.getBool("text.includeNotes") is True
assert sBuild.getBool("text.includeKeywords") is True
assert sBuild.getStr("text.ignoredKeywords") in ("@custom, @object", "@object, @custom")
assert sBuild.getBool("text.addNoteHeadings") is True
# Finish
button = bSettings.buttonBox.button(QtDialogClose)
assert button is not None
bSettings._dialogButtonClicked(button)
# qtbot.stop()
@pytest.mark.gui
def testToolBuildSettings_FormatTextFormat(monkeypatch, qtbot, nwGUI):
"""Test the Text Format settings."""
build = BuildSettings()
build.setValue("format.buildLang", "en_US")
build.setValue("format.textFont", "") # Will fall back to config value
build.setValue("format.lineHeight", 1.2)
build.setValue("format.justifyText", False)
build.setValue("format.stripUnicode", False)
build.setValue("format.replaceTabs", False)
build.setValue("format.keepBreaks", True)
build.setValue("format.showDialogue", False)
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
fmtTab = bSettings.optTabFormatting
button = bSettings.sidebar._group.button(bSettings.OPT_FORMATTING + 2)
assert button is not None
button.click()
assert bSettings.toolStack.currentWidget() is fmtTab
# Check initial values
assert fmtTab.lineHeight.value() == 1.2
assert fmtTab.justifyText.isChecked() is False
assert fmtTab.stripUnicode.isChecked() is False
assert fmtTab.replaceTabs.isChecked() is False
assert fmtTab.keepBreaks.isChecked() is True
assert fmtTab.showDialogue.isChecked() is False
# Change values
testFont = QFont("Arial", 11)
fmtTab._textFont = testFont
fmtTab.textFont.setText(describeFont(testFont))
fmtTab.lineHeight.setValue(1.15)
fmtTab.justifyText.setChecked(True)
fmtTab.stripUnicode.setChecked(True)
fmtTab.replaceTabs.setChecked(True)
fmtTab.keepBreaks.setChecked(False)
fmtTab.showDialogue.setChecked(True)
# Save values
fmtTab.saveContent()
sBuild = bSettings._build
assert sBuild.buildID == build.buildID
assert sBuild.getStr("format.textFont") == testFont.toString()
assert sBuild.getFloat("format.lineHeight") == 1.15
assert sBuild.getBool("format.justifyText") is True
assert sBuild.getBool("format.stripUnicode") is True
assert sBuild.getBool("format.replaceTabs") is True
assert sBuild.getBool("format.keepBreaks") is False
assert sBuild.getBool("format.showDialogue") is True
# Check that the font dialog doesn't fail
with monkeypatch.context() as mp:
font = QFont()
font.setFamily("Times")
font.setPointSize(10)
mp.setattr(QFontDialog, "getFont", lambda *a, **k: (font, True))
fmtTab.btnTextFont.click()
assert fmtTab._textFont == font
# Finish
button = bSettings.buttonBox.button(QtDialogClose)
assert button is not None
bSettings._dialogButtonClicked(button)
# qtbot.stop()
@pytest.mark.gui
def testToolBuildSettings_FormatFirstLineIndent(monkeypatch, qtbot, nwGUI):
"""Test the First Line Indent settings."""
build = BuildSettings()
build.setValue("format.firstLineIndent", False)
build.setValue("format.firstIndentWidth", 1.4)
build.setValue("format.indentFirstPar", False)
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
fmtTab = bSettings.optTabFormatting
button = bSettings.sidebar._group.button(bSettings.OPT_FORMATTING + 3)
assert button is not None
button.click()
assert bSettings.toolStack.currentWidget() is fmtTab
# Check initial values
assert fmtTab.firstIndent.isChecked() is False
assert fmtTab.indentWidth.value() == 1.4
assert fmtTab.indentFirstPar.isChecked() is False
# Change values
fmtTab.firstIndent.setChecked(True)
fmtTab.indentWidth.setValue(2.0)
fmtTab.indentFirstPar.setChecked(True)
# Save values
fmtTab.saveContent()
sBuild = bSettings._build
assert sBuild.buildID == build.buildID
assert sBuild.getBool("format.firstLineIndent") is True
assert sBuild.getFloat("format.firstIndentWidth") == 2.0
assert sBuild.getBool("format.indentFirstPar") is True
# Finish
button = bSettings.buttonBox.button(QtDialogClose)
assert button is not None
bSettings._dialogButtonClicked(button)
# qtbot.stop()
@pytest.mark.gui
def testToolBuildSettings_FormatPageLayout(monkeypatch, qtbot, nwGUI):
"""Test the First Line Indent settings."""
build = BuildSettings()
build.setValue("format.pageUnit", "mm")
build.setValue("format.pageSize", "Custom")
build.setValue("format.pageWidth", 180.0)
build.setValue("format.pageHeight", 250.0)
build.setValue("format.topMargin", 25.0)
build.setValue("format.bottomMargin", 25.0)
build.setValue("format.leftMargin", 15.0)
build.setValue("format.rightMargin", 15.0)
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
fmtTab = bSettings.optTabFormatting
button = bSettings.sidebar._group.button(bSettings.OPT_FORMATTING + 4)
assert button is not None
button.click()
assert bSettings.toolStack.currentWidget() is fmtTab
# Check initial values
assert fmtTab.pageUnit.currentData() == "mm"
assert fmtTab.pageSize.currentData() == "Custom"
assert fmtTab.pageWidth.value() == 180.0
assert fmtTab.pageHeight.value() == 250.0
assert fmtTab.topMargin.value() == 25.0
assert fmtTab.bottomMargin.value() == 25.0
assert fmtTab.leftMargin.value() == 15.0
assert fmtTab.rightMargin.value() == 15.0
# Change values
fmtTab.pageUnit.setCurrentIndex(fmtTab.pageUnit.findData("cm"))
fmtTab.pageSize.setCurrentIndex(fmtTab.pageSize.findData("A4"))
# Save values
fmtTab.saveContent()
assert fmtTab.pageUnit.currentData() == "cm"
assert fmtTab.pageSize.currentData() == "A4"
assert fmtTab.pageWidth.value() == 21.0
assert fmtTab.pageHeight.value() == 29.7
assert fmtTab.topMargin.value() == 2.5
assert fmtTab.bottomMargin.value() == 2.5
assert fmtTab.leftMargin.value() == 1.5
assert fmtTab.rightMargin.value() == 1.5
# Finish
button = bSettings.buttonBox.button(QtDialogClose)
assert button is not None
bSettings._dialogButtonClicked(button)
# qtbot.stop()
@pytest.mark.gui
def testToolBuildSettings_FormatOutput(qtbot, nwGUI):
"""Test the format-specific settings."""
build = BuildSettings()
build.setValue("doc.pageHeader", nwHeadFmt.DOC_AUTO)
build.setValue("doc.pageCountOffset", 0)
build.setValue("doc.colorHeadings", True)
build.setValue("doc.scaleHeadings", True)
build.setValue("doc.boldHeadings", True)
build.setValue("html.addStyles", False)
build.setValue("html.preserveTabs", False)
# Create the dialog and populate it
bSettings = GuiBuildSettings(nwGUI, build)
bSettings.show()
bSettings.loadContent()
fmtTab = bSettings.optTabFormatting
button = bSettings.sidebar._group.button(bSettings.OPT_FORMATTING + 5)
assert button is not None
button.click()
assert bSettings.toolStack.currentWidget() is fmtTab
# Check initial values
assert fmtTab.odtPageHeader.text() == nwHeadFmt.DOC_AUTO
assert fmtTab.odtPageCountOffset.value() == 0
assert fmtTab.colorHeadings.isChecked() is True
assert fmtTab.scaleHeadings.isChecked() is True
assert fmtTab.boldHeadings.isChecked() is True
assert fmtTab.htmlAddStyles.isChecked() is False
assert fmtTab.htmlPreserveTabs.isChecked() is False
# Change Values
fmtTab.odtPageCountOffset.setValue(1)
fmtTab.odtPageHeader.setText("Stuff")
# Toggle all
fmtTab.colorHeadings.setChecked(False)
fmtTab.scaleHeadings.setChecked(False)
fmtTab.boldHeadings.setChecked(False)
fmtTab.htmlAddStyles.setChecked(True)
fmtTab.htmlPreserveTabs.setChecked(True)
# Save values
fmtTab.saveContent()
sBuild = bSettings._build
assert sBuild.buildID == build.buildID
assert sBuild.getStr("doc.pageHeader") == "Stuff"
assert sBuild.getInt("doc.pageCountOffset") == 1
assert sBuild.getBool("doc.colorHeadings") is False
assert sBuild.getBool("doc.scaleHeadings") is False
assert sBuild.getBool("doc.boldHeadings") is False
assert sBuild.getBool("html.addStyles") is True
assert sBuild.getBool("html.preserveTabs") is True
# Reset header format
fmtTab.btnPageHeader.click()
assert fmtTab.odtPageHeader.text() == nwHeadFmt.DOC_AUTO
# Finish
button = bSettings.buttonBox.button(QtDialogClose)
assert button is not None
bSettings._dialogButtonClicked(button)
# qtbot.stop()