diff --git a/novelwriter/core/buildsettings.py b/novelwriter/core/buildsettings.py
index b68dd97d..a1f215fd 100644
--- a/novelwriter/core/buildsettings.py
+++ b/novelwriter/core/buildsettings.py
@@ -25,21 +25,21 @@ along with this program. If not, see .
from __future__ import annotations
import json
-import uuid
import logging
+import uuid
+from collections.abc import Iterable
from enum import Enum
from pathlib import Path
-from collections.abc import Iterable
from PyQt5.QtCore import QT_TRANSLATE_NOOP, QCoreApplication
from novelwriter import CONFIG
-from novelwriter.enum import nwBuildFmt
-from novelwriter.error import logException
from novelwriter.common import checkUuid, isHandle, jsonEncode
from novelwriter.constants import nwFiles, nwHeadFmt
from novelwriter.core.project import NWProject
+from novelwriter.enum import nwBuildFmt
+from novelwriter.error import logException
logger = logging.getLogger(__name__)
@@ -82,6 +82,9 @@ SETTINGS_TEMPLATE = {
"format.justifyText": (bool, False),
"format.stripUnicode": (bool, False),
"format.replaceTabs": (bool, False),
+ "format.firstLineIndent": (bool, False),
+ "format.firstIndentWidth": (float, 1.4),
+ "format.indentFirstPar": (bool, False),
"format.pageUnit": (str, "cm"),
"format.pageSize": (str, "A4"),
"format.pageWidth": (float, 21.0),
@@ -93,65 +96,69 @@ SETTINGS_TEMPLATE = {
"odt.addColours": (bool, True),
"odt.pageHeader": (str, nwHeadFmt.ODT_AUTO),
"odt.pageCountOffset": (int, 0),
- "odt.firstLineIndent": (bool, False),
"md.preserveBreaks": (bool, True),
"html.addStyles": (bool, True),
"html.preserveTabs": (bool, False),
}
SETTINGS_LABELS = {
- "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"),
+ "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"),
- "headings": QT_TRANSLATE_NOOP("Builds", "Headings"),
- "headings.fmtTitle": QT_TRANSLATE_NOOP("Builds", "Partition Format"),
- "headings.fmtChapter": QT_TRANSLATE_NOOP("Builds", "Chapter Format"),
- "headings.fmtUnnumbered": QT_TRANSLATE_NOOP("Builds", "Unnumbered Format"),
- "headings.fmtScene": QT_TRANSLATE_NOOP("Builds", "Scene Format"),
- "headings.fmtAltScene": QT_TRANSLATE_NOOP("Builds", "Alt. Scene Format"),
- "headings.fmtSection": QT_TRANSLATE_NOOP("Builds", "Section Format"),
+ "headings": QT_TRANSLATE_NOOP("Builds", "Headings"),
+ "headings.fmtTitle": QT_TRANSLATE_NOOP("Builds", "Partition Format"),
+ "headings.fmtChapter": QT_TRANSLATE_NOOP("Builds", "Chapter Format"),
+ "headings.fmtUnnumbered": QT_TRANSLATE_NOOP("Builds", "Unnumbered Format"),
+ "headings.fmtScene": QT_TRANSLATE_NOOP("Builds", "Scene Format"),
+ "headings.fmtAltScene": QT_TRANSLATE_NOOP("Builds", "Alt. Scene Format"),
+ "headings.fmtSection": QT_TRANSLATE_NOOP("Builds", "Section Format"),
- "text.grpContent": QT_TRANSLATE_NOOP("Builds", "Text Content"),
- "text.includeSynopsis": QT_TRANSLATE_NOOP("Builds", "Include Synopsis"),
- "text.includeComments": QT_TRANSLATE_NOOP("Builds", "Include Comments"),
- "text.includeKeywords": QT_TRANSLATE_NOOP("Builds", "Include Keywords"),
- "text.includeBodyText": QT_TRANSLATE_NOOP("Builds", "Include Body Text"),
- "text.ignoredKeywords": QT_TRANSLATE_NOOP("Builds", "Ignore These Keywords"),
- "text.grpInsert": QT_TRANSLATE_NOOP("Builds", "Insert Content"),
- "text.addNoteHeadings": QT_TRANSLATE_NOOP("Builds", "Add Titles for Notes"),
+ "text.grpContent": QT_TRANSLATE_NOOP("Builds", "Text Content"),
+ "text.includeSynopsis": QT_TRANSLATE_NOOP("Builds", "Include Synopsis"),
+ "text.includeComments": QT_TRANSLATE_NOOP("Builds", "Include Comments"),
+ "text.includeKeywords": QT_TRANSLATE_NOOP("Builds", "Include Keywords"),
+ "text.includeBodyText": QT_TRANSLATE_NOOP("Builds", "Include Body Text"),
+ "text.ignoredKeywords": QT_TRANSLATE_NOOP("Builds", "Ignore These Keywords"),
+ "text.grpInsert": QT_TRANSLATE_NOOP("Builds", "Insert Content"),
+ "text.addNoteHeadings": QT_TRANSLATE_NOOP("Builds", "Add Titles for Notes"),
- "format.grpFormat": QT_TRANSLATE_NOOP("Builds", "Text Format"),
- "format.textFont": QT_TRANSLATE_NOOP("Builds", "Font Family"),
- "format.textSize": QT_TRANSLATE_NOOP("Builds", "Font Size"),
- "format.lineHeight": QT_TRANSLATE_NOOP("Builds", "Line Height"),
- "format.grpOptions": QT_TRANSLATE_NOOP("Builds", "Text Options"),
- "format.justifyText": QT_TRANSLATE_NOOP("Builds", "Justify Text Margins"),
- "format.stripUnicode": QT_TRANSLATE_NOOP("Builds", "Replace Unicode Characters"),
- "format.replaceTabs": QT_TRANSLATE_NOOP("Builds", "Replace Tabs with Spaces"),
- "format.grpPage": QT_TRANSLATE_NOOP("Builds", "Page Layout"),
- "format.pageUnit": QT_TRANSLATE_NOOP("Builds", "Unit"),
- "format.pageSize": QT_TRANSLATE_NOOP("Builds", "Page Size"),
- "format.pageWidth": QT_TRANSLATE_NOOP("Builds", "Page Width"),
- "format.pageHeight": QT_TRANSLATE_NOOP("Builds", "Page Height"),
- "format.topMargin": QT_TRANSLATE_NOOP("Builds", "Top Margin"),
- "format.bottomMargin": QT_TRANSLATE_NOOP("Builds", "Bottom Margin"),
- "format.leftMargin": QT_TRANSLATE_NOOP("Builds", "Left Margin"),
- "format.rightMargin": QT_TRANSLATE_NOOP("Builds", "Right Margin"),
+ "format.grpFormat": QT_TRANSLATE_NOOP("Builds", "Text Format"),
+ "format.textFont": QT_TRANSLATE_NOOP("Builds", "Font Family"),
+ "format.textSize": QT_TRANSLATE_NOOP("Builds", "Font Size"),
+ "format.lineHeight": QT_TRANSLATE_NOOP("Builds", "Line Height"),
+ "format.grpOptions": QT_TRANSLATE_NOOP("Builds", "Text Options"),
+ "format.justifyText": QT_TRANSLATE_NOOP("Builds", "Justify Text Margins"),
+ "format.stripUnicode": QT_TRANSLATE_NOOP("Builds", "Replace Unicode Characters"),
+ "format.replaceTabs": QT_TRANSLATE_NOOP("Builds", "Replace Tabs with Spaces"),
- "odt": QT_TRANSLATE_NOOP("Builds", "Open Document (.odt)"),
- "odt.addColours": QT_TRANSLATE_NOOP("Builds", "Add Highlight Colours"),
- "odt.pageHeader": QT_TRANSLATE_NOOP("Builds", "Page Header"),
- "odt.pageCountOffset": QT_TRANSLATE_NOOP("Builds", "Page Counter Offset"),
- "odt.firstLineIndent": QT_TRANSLATE_NOOP("Builds", "First Line Indent"),
+ "format.grpParIndent": QT_TRANSLATE_NOOP("Builds", "First Line Indent"),
+ "format.firstLineIndent": QT_TRANSLATE_NOOP("Builds", "Enable Indent"),
+ "format.firstIndentWidth": QT_TRANSLATE_NOOP("Builds", "Indent Width"),
+ "format.indentFirstPar": QT_TRANSLATE_NOOP("Builds", "Indent First Paragraph"),
- "md": QT_TRANSLATE_NOOP("Builds", "Markdown (.md)"),
- "md.preserveBreaks": QT_TRANSLATE_NOOP("Builds", "Preserve Hard Line Breaks"),
+ "format.grpPage": QT_TRANSLATE_NOOP("Builds", "Page Layout"),
+ "format.pageUnit": QT_TRANSLATE_NOOP("Builds", "Unit"),
+ "format.pageSize": QT_TRANSLATE_NOOP("Builds", "Page Size"),
+ "format.pageWidth": QT_TRANSLATE_NOOP("Builds", "Page Width"),
+ "format.pageHeight": QT_TRANSLATE_NOOP("Builds", "Page Height"),
+ "format.topMargin": QT_TRANSLATE_NOOP("Builds", "Top Margin"),
+ "format.bottomMargin": QT_TRANSLATE_NOOP("Builds", "Bottom Margin"),
+ "format.leftMargin": QT_TRANSLATE_NOOP("Builds", "Left Margin"),
+ "format.rightMargin": QT_TRANSLATE_NOOP("Builds", "Right Margin"),
- "html": QT_TRANSLATE_NOOP("Builds", "HTML (.html)"),
- "html.addStyles": QT_TRANSLATE_NOOP("Builds", "Add CSS Styles"),
- "html.preserveTabs": QT_TRANSLATE_NOOP("Builds", "Preserve Tab Characters"),
+ "odt": QT_TRANSLATE_NOOP("Builds", "Open Document (.odt)"),
+ "odt.addColours": QT_TRANSLATE_NOOP("Builds", "Add Highlight Colours"),
+ "odt.pageHeader": QT_TRANSLATE_NOOP("Builds", "Page Header"),
+ "odt.pageCountOffset": QT_TRANSLATE_NOOP("Builds", "Page Counter Offset"),
+
+ "md": QT_TRANSLATE_NOOP("Builds", "Markdown (.md)"),
+ "md.preserveBreaks": QT_TRANSLATE_NOOP("Builds", "Preserve Hard Line Breaks"),
+
+ "html": QT_TRANSLATE_NOOP("Builds", "HTML (.html)"),
+ "html.addStyles": QT_TRANSLATE_NOOP("Builds", "Add CSS Styles"),
+ "html.preserveTabs": QT_TRANSLATE_NOOP("Builds", "Preserve Tab Characters"),
}
diff --git a/novelwriter/core/docbuild.py b/novelwriter/core/docbuild.py
index 3c791334..17452c22 100644
--- a/novelwriter/core/docbuild.py
+++ b/novelwriter/core/docbuild.py
@@ -25,22 +25,22 @@ from __future__ import annotations
import logging
-from pathlib import Path
from collections.abc import Iterable
+from pathlib import Path
from PyQt5.QtGui import QFont, QFontInfo
from novelwriter import CONFIG
-from novelwriter.enum import nwBuildFmt
-from novelwriter.error import formatException, logException
from novelwriter.constants import nwLabels
+from novelwriter.core.buildsettings import BuildSettings
from novelwriter.core.item import NWItem
+from novelwriter.core.project import NWProject
+from novelwriter.core.tohtml import ToHtml
+from novelwriter.core.tokenizer import Tokenizer
from novelwriter.core.tomd import ToMarkdown
from novelwriter.core.toodt import ToOdt
-from novelwriter.core.tohtml import ToHtml
-from novelwriter.core.project import NWProject
-from novelwriter.core.tokenizer import Tokenizer
-from novelwriter.core.buildsettings import BuildSettings
+from novelwriter.enum import nwBuildFmt
+from novelwriter.error import formatException, logException
logger = logging.getLogger(__name__)
@@ -333,6 +333,11 @@ class NWBuildDocument:
bldObj.setFont(fontFamily, textSize, textFixed)
bldObj.setJustify(self._build.getBool("format.justifyText"))
bldObj.setLineHeight(self._build.getFloat("format.lineHeight"))
+ bldObj.setFirstLineIndent(
+ self._build.getBool("format.firstLineIndent"),
+ self._build.getFloat("format.firstIndentWidth"),
+ self._build.getBool("format.indentFirstPar"),
+ )
bldObj.setBodyText(self._build.getBool("text.includeBodyText"))
bldObj.setSynopsis(self._build.getBool("text.includeSynopsis"))
@@ -350,7 +355,6 @@ class NWBuildDocument:
bldObj.setHeaderFormat(
self._build.getStr("odt.pageHeader"), self._build.getInt("odt.pageCountOffset")
)
- bldObj.setFirstLineIndent(self._build.getBool("odt.firstLineIndent"))
scale = nwLabels.UNIT_SCALE.get(self._build.getStr("format.pageUnit"), 1.0)
pW, pH = nwLabels.PAPER_SIZE.get(self._build.getStr("format.pageSize"), (-1.0, -1.0))
diff --git a/novelwriter/core/tokenizer.py b/novelwriter/core/tokenizer.py
index efeaacde..148fe574 100644
--- a/novelwriter/core/tokenizer.py
+++ b/novelwriter/core/tokenizer.py
@@ -116,6 +116,7 @@ class Tokenizer(ABC):
# Lookups
L_HEADINGS = [T_TITLE, T_HEAD1, T_HEAD2, T_HEAD3, T_HEAD4]
+ L_SKIP_INDENT = [T_TITLE, T_HEAD1, T_HEAD2, T_HEAD2, T_HEAD3, T_HEAD4, T_SEP, T_SKIP]
def __init__(self, project: NWProject) -> None:
@@ -142,7 +143,9 @@ class Tokenizer(ABC):
self._textFixed = False # Fixed width text
self._lineHeight = 1.15 # Line height in units of em
self._blockIndent = 4.00 # Block indent in units of em
- self._textIndent = 1.40 # First line indent in units of em
+ self._firstIndent = False # Enable first line indent
+ self._firstWidth = 1.40 # First line indent in units of em
+ self._indentFirst = False # Indent first paragraph
self._doJustify = False # Justify text
self._doBodyText = True # Include body text
self._doSynopsis = False # Also process synopsis comments
@@ -327,6 +330,15 @@ class Tokenizer(ABC):
self._blockIndent = min(max(float(indent), 0.0), 10.0)
return
+ def setFirstLineIndent(self, state: bool, indent: float, first: bool) -> None:
+ """Set first line indent and whether to also indent first
+ paragraph after a heading.
+ """
+ self._firstIndent = state
+ self._firstWidth = indent
+ self._indentFirst = first
+ return
+
def setJustify(self, state: bool) -> None:
"""Enable or disable text justification."""
self._doJustify = state
diff --git a/novelwriter/core/toodt.py b/novelwriter/core/toodt.py
index 435f6d0c..92003f52 100644
--- a/novelwriter/core/toodt.py
+++ b/novelwriter/core/toodt.py
@@ -141,7 +141,6 @@ class ToOdt(Tokenizer):
self._textSize = 12
self._textFixed = False
self._colourHead = False
- self._firstIndent = False
self._headerFormat = ""
self._pageOffset = 0
@@ -240,11 +239,6 @@ class ToOdt(Tokenizer):
self._pageOffset = offset
return
- def setFirstLineIndent(self, state: bool) -> None:
- """Enable or disable first line indent."""
- self._firstIndent = state
- return
-
##
# Class Methods
##
@@ -301,7 +295,7 @@ class ToOdt(Tokenizer):
self._fLineHeight = f"{round(100 * self._lineHeight):d}%"
self._fBlockIndent = self._emToCm(self._blockIndent)
- self._fTextIndent = self._emToCm(self._textIndent)
+ self._fTextIndent = self._emToCm(self._firstWidth)
self._textAlign = "justify" if self._doJustify else "left"
# Clear Errors
@@ -447,7 +441,7 @@ class ToOdt(Tokenizer):
if tStyle & self.A_IND_R:
oStyle.setMarginRight(self._fBlockIndent)
- if tType not in (self.T_EMPTY, self.T_TEXT):
+ if not self._indentFirst and tType in self.L_SKIP_INDENT:
pIndent = False
# Process Text Types
diff --git a/novelwriter/tools/manussettings.py b/novelwriter/tools/manussettings.py
index 77b8035a..b3f7d1d5 100644
--- a/novelwriter/tools/manussettings.py
+++ b/novelwriter/tools/manussettings.py
@@ -1113,6 +1113,25 @@ class _FormatTab(NScrollableForm):
self.addRow(self._build.getLabel("format.stripUnicode"), self.stripUnicode)
self.addRow(self._build.getLabel("format.replaceTabs"), self.replaceTabs)
+ # First Line Indent
+ # =================
+
+ self.addGroupLabel(self._build.getLabel("format.grpParIndent"))
+
+ self.firstIndent = NSwitch(self, height=iPx)
+ self.indentFirstPar = NSwitch(self, height=iPx)
+
+ self.indentWidth = NDoubleSpinBox(self)
+ self.indentWidth.setFixedWidth(spW)
+ self.indentWidth.setMinimum(0.1)
+ self.indentWidth.setMaximum(9.9)
+ self.indentWidth.setSingleStep(0.1)
+ self.indentWidth.setDecimals(1)
+
+ self.addRow(self._build.getLabel("format.firstLineIndent"), self.firstIndent)
+ self.addRow(self._build.getLabel("format.firstIndentWidth"), self.indentWidth, unit="em")
+ self.addRow(self._build.getLabel("format.indentFirstPar"), self.indentFirstPar)
+
# Page Layout
# ===========
@@ -1176,6 +1195,10 @@ class _FormatTab(NScrollableForm):
self.stripUnicode.setChecked(self._build.getBool("format.stripUnicode"))
self.replaceTabs.setChecked(self._build.getBool("format.replaceTabs"))
+ self.firstIndent.setChecked(self._build.getBool("format.firstLineIndent"))
+ self.indentWidth.setValue(self._build.getFloat("format.firstIndentWidth"))
+ self.indentFirstPar.setChecked(self._build.getBool("format.indentFirstPar"))
+
pageUnit = self._build.getStr("format.pageUnit")
index = self.pageUnit.findData(pageUnit)
if index >= 0:
@@ -1211,6 +1234,10 @@ class _FormatTab(NScrollableForm):
self._build.setValue("format.stripUnicode", self.stripUnicode.isChecked())
self._build.setValue("format.replaceTabs", self.replaceTabs.isChecked())
+ self._build.setValue("format.firstLineIndent", self.firstIndent.isChecked())
+ self._build.setValue("format.firstIndentWidth", self.indentWidth.value())
+ self._build.setValue("format.indentFirstPar", self.indentFirstPar.isChecked())
+
self._build.setValue("format.pageUnit", str(self.pageUnit.currentData()))
self._build.setValue("format.pageSize", str(self.pageSize.currentData()))
self._build.setValue("format.pageWidth", self.pageWidth.value())
@@ -1355,9 +1382,6 @@ class _OutputTab(NScrollableForm):
self.odtPageCountOffset.setMinimumWidth(spW)
self.addRow(self._build.getLabel("odt.pageCountOffset"), self.odtPageCountOffset)
- self.odtFirstLineIndent = NSwitch(self, height=iPx)
- self.addRow(self._build.getLabel("odt.firstLineIndent"), self.odtFirstLineIndent)
-
# HTML Document
self.addGroupLabel(self._build.getLabel("html"))
@@ -1383,7 +1407,6 @@ class _OutputTab(NScrollableForm):
self.odtAddColours.setChecked(self._build.getBool("odt.addColours"))
self.odtPageHeader.setText(self._build.getStr("odt.pageHeader"))
self.odtPageCountOffset.setValue(self._build.getInt("odt.pageCountOffset"))
- self.odtFirstLineIndent.setChecked(self._build.getBool("odt.firstLineIndent"))
self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
self.htmlPreserveTabs.setChecked(self._build.getBool("html.preserveTabs"))
self.mdPreserveBreaks.setChecked(self._build.getBool("md.preserveBreaks"))
@@ -1395,7 +1418,6 @@ class _OutputTab(NScrollableForm):
self._build.setValue("odt.addColours", self.odtAddColours.isChecked())
self._build.setValue("odt.pageHeader", self.odtPageHeader.text())
self._build.setValue("odt.pageCountOffset", self.odtPageCountOffset.value())
- self._build.setValue("odt.firstLineIndent", self.odtFirstLineIndent.isChecked())
self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
self._build.setValue("html.preserveTabs", self.htmlPreserveTabs.isChecked())
self._build.setValue("md.preserveBreaks", self.mdPreserveBreaks.isChecked())
diff --git a/tests/reference/mBuildDocBuild_OpenDocument_Lorem_Ipsum.fodt b/tests/reference/mBuildDocBuild_OpenDocument_Lorem_Ipsum.fodt
index 802a929f..902f37a5 100644
--- a/tests/reference/mBuildDocBuild_OpenDocument_Lorem_Ipsum.fodt
+++ b/tests/reference/mBuildDocBuild_OpenDocument_Lorem_Ipsum.fodt
@@ -1,13 +1,13 @@
- 2024-04-27T16:43:44
- novelWriter/2.5a2
+ 2024-05-10T15:23:56
+ novelWriter/2.5a3
lipsum.com
45
P0DT0H36M8S
Lorem Ipsum
- 2024-04-27T16:43:44
+ 2024-05-10T15:23:56
lipsum.com
@@ -121,7 +121,7 @@
“Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit…”
“There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain…”
Comment: Exctracted from the lipsum.com website.
- Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
Prologue
Synopsis: Explanation from the lipsum.com website.
diff --git a/tests/test_core/test_core_docbuild.py b/tests/test_core/test_core_docbuild.py
index 634d6e92..928d5d73 100644
--- a/tests/test_core/test_core_docbuild.py
+++ b/tests/test_core/test_core_docbuild.py
@@ -21,21 +21,22 @@ along with this program. If not, see .
from __future__ import annotations
import json
+
+from pathlib import Path
+from shutil import copyfile
+
import pytest
-from shutil import copyfile
-from pathlib import Path
-
-from tools import C, ODT_IGNORE, buildTestProject, cmpFiles
-from mocked import causeException, causeOSError
-
-from novelwriter.enum import nwBuildFmt
+from novelwriter.core.buildsettings import BuildSettings
+from novelwriter.core.docbuild import NWBuildDocument
+from novelwriter.core.project import NWProject
+from novelwriter.core.tohtml import ToHtml
from novelwriter.core.tomd import ToMarkdown
from novelwriter.core.toodt import ToOdt
-from novelwriter.core.tohtml import ToHtml
-from novelwriter.core.project import NWProject
-from novelwriter.core.docbuild import NWBuildDocument
-from novelwriter.core.buildsettings import BuildSettings
+from novelwriter.enum import nwBuildFmt
+
+from tests.mocked import causeException, causeOSError
+from tests.tools import ODT_IGNORE, C, buildTestProject, cmpFiles
BUILD_CONF = {
"name": "Test Build",
@@ -63,8 +64,8 @@ BUILD_CONF = {
"format.justifyText": True,
"format.stripUnicode": False,
"format.replaceTabs": True,
+ "format.firstLineIndent": True,
"odt.addColours": True,
- "odt.firstLineIndent": True,
"html.addStyles": True,
},
"content": {
diff --git a/tests/test_core/test_core_toodt.py b/tests/test_core/test_core_toodt.py
index 2428a567..4231b884 100644
--- a/tests/test_core/test_core_toodt.py
+++ b/tests/test_core/test_core_toodt.py
@@ -753,8 +753,10 @@ def testCoreToOdt_SaveFlat(mockGUI, fncPath, tstPaths):
assert odt._colourHead is True
odt.setHeaderFormat(nwHeadFmt.ODT_AUTO, 1)
assert odt._headerFormat == nwHeadFmt.ODT_AUTO
- odt.setFirstLineIndent(True)
+ odt.setFirstLineIndent(True, 1.4, False)
assert odt._firstIndent is True
+ assert odt._fTextIndent == "0.499cm"
+ assert odt._indentFirst is False
odt.setPageLayout(148, 210, 20, 18, 17, 15)
assert odt._mDocWidth == "14.800cm"
diff --git a/tests/test_tools/test_tools_manussettings.py b/tests/test_tools/test_tools_manussettings.py
index 3f51c9cd..9cb34a46 100644
--- a/tests/test_tools/test_tools_manussettings.py
+++ b/tests/test_tools/test_tools_manussettings.py
@@ -22,27 +22,24 @@ from __future__ import annotations
import pytest
-from pathlib import Path
-from pytestqt.qtbot import QtBot
-
-from tools import C, buildTestProject
-
-from PyQt5.QtGui import QFont
from PyQt5.QtCore import pyqtSlot
+from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QFontDialog
from novelwriter import CONFIG, SHARED
-from novelwriter.guimain import GuiMain
from novelwriter.constants import nwHeadFmt
from novelwriter.core.buildsettings import BuildSettings, FilterMode
from novelwriter.tools.manussettings import (
- GuiBuildSettings, _OutputTab, _FormatTab, _ContentTab, _HeadingsTab, _FilterTab
+ GuiBuildSettings, _ContentTab, _FilterTab, _FormatTab, _HeadingsTab,
+ _OutputTab
)
from novelwriter.types import QtDialogApply, QtDialogClose, QtDialogSave
+from tests.tools import C, buildTestProject
+
@pytest.mark.gui
-def testBuildSettings_Init(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockRnd):
+def testBuildSettings_Init(qtbot, nwGUI, projPath, mockRnd):
"""Test the initialisation of the GuiBuildSettings dialog."""
buildTestProject(nwGUI, projPath)
nwGUI.openProject(projPath)
@@ -114,7 +111,7 @@ def testBuildSettings_Init(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockRnd
@pytest.mark.gui
-def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockRnd):
+def testBuildSettings_Filter(qtbot, nwGUI, projPath, mockRnd):
"""Test the Filter Tab of the GuiBuildSettings dialog."""
buildTestProject(nwGUI, projPath)
nwGUI.openProject(projPath)
@@ -320,7 +317,7 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
@pytest.mark.gui
-def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
+def testBuildSettings_Headings(qtbot, nwGUI):
"""Test the Headings Tab of the GuiBuildSettings dialog."""
build = BuildSettings()
@@ -492,7 +489,7 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
@pytest.mark.gui
-def testBuildSettings_Content(qtbot: QtBot, nwGUI: GuiMain):
+def testBuildSettings_Content(qtbot, nwGUI):
"""Test the Content Tab of the GuiBuildSettings dialog."""
build = BuildSettings()
@@ -554,7 +551,7 @@ def testBuildSettings_Content(qtbot: QtBot, nwGUI: GuiMain):
@pytest.mark.gui
-def testBuildSettings_Format(monkeypatch, qtbot: QtBot, nwGUI: GuiMain):
+def testBuildSettings_Format(monkeypatch, qtbot, nwGUI):
"""Test the Format Tab of the GuiBuildSettings dialog."""
build = BuildSettings()
@@ -596,6 +593,10 @@ def testBuildSettings_Format(monkeypatch, qtbot: QtBot, nwGUI: GuiMain):
assert fmtTab.stripUnicode.isChecked() is False
assert fmtTab.replaceTabs.isChecked() is False
+ assert fmtTab.firstIndent.isChecked() is False
+ assert fmtTab.indentWidth.value() == 1.4
+ assert fmtTab.indentFirstPar.isChecked() is False
+
assert fmtTab.pageUnit.currentData() == "mm"
assert fmtTab.pageSize.currentData() == "Custom"
assert fmtTab.pageWidth.value() == 180.0
@@ -614,6 +615,10 @@ def testBuildSettings_Format(monkeypatch, qtbot: QtBot, nwGUI: GuiMain):
fmtTab.stripUnicode.setChecked(True)
fmtTab.replaceTabs.setChecked(True)
+ fmtTab.firstIndent.setChecked(True)
+ fmtTab.indentWidth.setValue(2.0)
+ fmtTab.indentFirstPar.setChecked(True)
+
fmtTab.pageUnit.setCurrentIndex(fmtTab.pageUnit.findData("cm"))
fmtTab.pageSize.setCurrentIndex(fmtTab.pageSize.findData("A4"))
@@ -628,6 +633,10 @@ def testBuildSettings_Format(monkeypatch, qtbot: QtBot, nwGUI: GuiMain):
assert build.getBool("format.stripUnicode") is True
assert build.getBool("format.replaceTabs") is True
+ assert build.getBool("format.firstLineIndent") is True
+ assert build.getFloat("format.firstIndentWidth") == 2.0
+ assert build.getBool("format.indentFirstPar") is True
+
assert fmtTab.pageUnit.currentData() == "cm"
assert fmtTab.pageSize.currentData() == "A4"
assert fmtTab.pageWidth.value() == 21.0
@@ -656,7 +665,7 @@ def testBuildSettings_Format(monkeypatch, qtbot: QtBot, nwGUI: GuiMain):
@pytest.mark.gui
-def testBuildSettings_Output(qtbot: QtBot, nwGUI: GuiMain):
+def testBuildSettings_Output(qtbot, nwGUI):
"""Test the Output Tab of the GuiBuildSettings dialog."""
build = BuildSettings()
@@ -676,14 +685,12 @@ def testBuildSettings_Output(qtbot: QtBot, nwGUI: GuiMain):
assert outTab.odtAddColours.isChecked() is False
assert outTab.odtPageHeader.text() == nwHeadFmt.ODT_AUTO
assert outTab.odtPageCountOffset.value() == 0
- assert outTab.odtFirstLineIndent.isChecked() is False
assert outTab.htmlAddStyles.isChecked() is False
assert outTab.htmlPreserveTabs.isChecked() is False
assert outTab.mdPreserveBreaks.isChecked() is True
# Toggle all
outTab.odtAddColours.setChecked(True)
- outTab.odtFirstLineIndent.setChecked(True)
outTab.htmlAddStyles.setChecked(True)
outTab.htmlPreserveTabs.setChecked(True)
outTab.mdPreserveBreaks.setChecked(False)
@@ -698,7 +705,6 @@ def testBuildSettings_Output(qtbot: QtBot, nwGUI: GuiMain):
assert build.getBool("odt.addColours") is True
assert build.getStr("odt.pageHeader") == "Stuff"
assert build.getInt("odt.pageCountOffset") == 1
- assert build.getBool("odt.firstLineIndent") is True
assert build.getBool("html.addStyles") is True
assert build.getBool("html.preserveTabs") is True
assert build.getBool("md.preserveBreaks") is False