From f732d1380727b5608eb8384add5c9e121d429d78 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sun, 28 Jan 2024 15:15:03 +0100 Subject: [PATCH] Add build setting for customising ODT page header (#1505) --- novelwriter/constants.py | 8 ++++- novelwriter/core/buildsettings.py | 2 ++ novelwriter/core/docbuild.py | 1 + novelwriter/core/toodt.py | 51 ++++++++++++++++------------ novelwriter/tools/manussettings.py | 54 +++++++++++++++++++++--------- 5 files changed, 78 insertions(+), 38 deletions(-) diff --git a/novelwriter/constants.py b/novelwriter/constants.py index ce8223ea..d4a944cc 100644 --- a/novelwriter/constants.py +++ b/novelwriter/constants.py @@ -309,7 +309,13 @@ class nwHeadFmt: SC_NUM = "{Scene}" SC_ABS = "{Scene:Abs}" - ALL = [TITLE, CH_NUM, CH_WORD, CH_ROMU, CH_ROML, SC_NUM, SC_ABS] + PAGE_HEADERS = [TITLE, CH_NUM, CH_WORD, CH_ROMU, CH_ROML, SC_NUM, SC_ABS] + + # ODT Document Page Header + ODT_PROJECT = "{Project}" + ODT_AUTHOR = "{Author}" + ODT_PAGE = "{Page}" + ODT_AUTO = "{Project} / {Author} / {Page}" # END Class nwHeadFmt diff --git a/novelwriter/core/buildsettings.py b/novelwriter/core/buildsettings.py index a796940c..3a7665c8 100644 --- a/novelwriter/core/buildsettings.py +++ b/novelwriter/core/buildsettings.py @@ -79,6 +79,7 @@ SETTINGS_TEMPLATE = { "format.leftMargin": (float, 2.0), "format.rightMargin": (float, 2.0), "odt.addColours": (bool, True), + "odt.pageHeader": (str, nwHeadFmt.ODT_AUTO), "html.addStyles": (bool, True), } @@ -125,6 +126,7 @@ SETTINGS_LABELS = { "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"), "html": QT_TRANSLATE_NOOP("Builds", "HTML (.html)"), "html.addStyles": QT_TRANSLATE_NOOP("Builds", "Add CSS Styles"), diff --git a/novelwriter/core/docbuild.py b/novelwriter/core/docbuild.py index 2caa9abe..e45c5f06 100644 --- a/novelwriter/core/docbuild.py +++ b/novelwriter/core/docbuild.py @@ -284,6 +284,7 @@ class NWBuildDocument: if isinstance(bldObj, ToOdt): bldObj.setColourHeaders(self._build.getBool("odt.addColours")) bldObj.setLanguage(self._project.data.language) + bldObj.setHeaderFormat(self._build.getStr("odt.pageHeader")) 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/toodt.py b/novelwriter/core/toodt.py index 0c2bd5e1..e173c9de 100644 --- a/novelwriter/core/toodt.py +++ b/novelwriter/core/toodt.py @@ -132,11 +132,11 @@ class ToOdt(Tokenizer): self._errData = [] # List of errors encountered # Properties - self._textFont = "Liberation Serif" - self._textSize = 12 - self._textFixed = False - self._colourHead = False - self._headerText = "" + self._textFont = "Liberation Serif" + self._textSize = 12 + self._textFixed = False + self._colourHead = False + self._headerFormat = "" # Internal self._fontFamily = "'Liberation Serif'" @@ -222,6 +222,11 @@ class ToOdt(Tokenizer): self._mDocRight = f"{right/10.0:.3f}cm" return + def setHeaderFormat(self, format: str) -> None: + """Set the document header format.""" + self._headerFormat = format.strip() + return + ## # Class Methods ## @@ -279,12 +284,6 @@ class ToOdt(Tokenizer): # Clear Errors self._errData = [] - # Document Header - # =============== - - if self._headerText == "": - self._headerText = f"{self._project.data.name} / {self._project.data.author} /" - # Create Roots # ============ @@ -1010,17 +1009,27 @@ class ToOdt(Tokenizer): xPage = ET.SubElement(self._xMast, _mkTag("style", "master-page"), attrib=tAttr) # Standard Page Header - xHead = ET.SubElement(xPage, _mkTag("style", "header")) - xPar = ET.SubElement(xHead, _mkTag("text", "p"), attrib={ - _mkTag("text", "style-name"): "Header" - }) - xPar.text = self._headerText.strip() + " " + if self._headerFormat: + pre, page, post = self._headerFormat.partition(nwHeadFmt.ODT_PAGE) - xTail = ET.SubElement(xPar, _mkTag("text", "page-number"), attrib={ - _mkTag("text", "select-page"): "current" - }) - xTail.text = "2" - xTail.tail = "" # Prevent line break in indented XML + pre = pre.replace(nwHeadFmt.ODT_PROJECT, self._project.data.name) + pre = pre.replace(nwHeadFmt.ODT_AUTHOR, self._project.data.author) + post = post.replace(nwHeadFmt.ODT_PROJECT, self._project.data.name) + post = post.replace(nwHeadFmt.ODT_AUTHOR, self._project.data.author) + + xHead = ET.SubElement(xPage, _mkTag("style", "header")) + xPar = ET.SubElement(xHead, _mkTag("text", "p"), attrib={ + _mkTag("text", "style-name"): "Header" + }) + xPar.text = pre + if page: + xTail = ET.SubElement(xPar, _mkTag("text", "page-number"), attrib={ + _mkTag("text", "select-page"): "current" + }) + xTail.text = "2" + xTail.tail = post + else: + xPar.text += post # First Page Header xHead = ET.SubElement(xPage, _mkTag("style", "header-first")) diff --git a/novelwriter/tools/manussettings.py b/novelwriter/tools/manussettings.py index 1ba232fc..701fe2e4 100644 --- a/novelwriter/tools/manussettings.py +++ b/novelwriter/tools/manussettings.py @@ -79,17 +79,16 @@ class GuiBuildSettings(QDialog): self._build = build self.setWindowTitle(self.tr("Manuscript Build Settings")) - self.setMinimumWidth(CONFIG.pxInt(700)) - self.setMinimumHeight(CONFIG.pxInt(400)) + self.setMinimumSize(CONFIG.pxInt(700), CONFIG.pxInt(400)) mPx = CONFIG.pxInt(150) wWin = CONFIG.pxInt(750) hWin = CONFIG.pxInt(550) - pOptions = SHARED.project.options + options = SHARED.project.options self.resize( - CONFIG.pxInt(pOptions.getInt("GuiBuildSettings", "winWidth", wWin)), - CONFIG.pxInt(pOptions.getInt("GuiBuildSettings", "winHeight", hWin)) + CONFIG.pxInt(options.getInt("GuiBuildSettings", "winWidth", wWin)), + CONFIG.pxInt(options.getInt("GuiBuildSettings", "winHeight", hWin)) ) # Title @@ -604,9 +603,9 @@ class _HeadingsTab(NScrollablePage): # Title Heading self.lblTitle = QLabel(self._build.getLabel("headings.fmtTitle")) - self.fmtTitle = QLineEdit("") + self.fmtTitle = QLineEdit("", self) self.fmtTitle.setReadOnly(True) - self.btnTitle = QToolButton() + self.btnTitle = QToolButton(self) self.btnTitle.setIcon(SHARED.theme.getIcon("edit")) self.btnTitle.clicked.connect(lambda: self._editHeading(self.EDIT_TITLE)) @@ -620,9 +619,9 @@ class _HeadingsTab(NScrollablePage): # Chapter Heading self.lblChapter = QLabel(self._build.getLabel("headings.fmtChapter")) - self.fmtChapter = QLineEdit("") + self.fmtChapter = QLineEdit("", self) self.fmtChapter.setReadOnly(True) - self.btnChapter = QToolButton() + self.btnChapter = QToolButton(self) self.btnChapter.setIcon(SHARED.theme.getIcon("edit")) self.btnChapter.clicked.connect(lambda: self._editHeading(self.EDIT_CHAPTER)) @@ -636,9 +635,9 @@ class _HeadingsTab(NScrollablePage): # Unnumbered Chapter Heading self.lblUnnumbered = QLabel(self._build.getLabel("headings.fmtUnnumbered")) - self.fmtUnnumbered = QLineEdit("") + self.fmtUnnumbered = QLineEdit("", self) self.fmtUnnumbered.setReadOnly(True) - self.btnUnnumbered = QToolButton() + self.btnUnnumbered = QToolButton(self) self.btnUnnumbered.setIcon(SHARED.theme.getIcon("edit")) self.btnUnnumbered.clicked.connect(lambda: self._editHeading(self.EDIT_UNNUM)) @@ -653,9 +652,9 @@ class _HeadingsTab(NScrollablePage): # Scene Heading sceneHideTip = self._build.getLabel("headings.hideScene") self.lblScene = QLabel(self._build.getLabel("headings.fmtScene")) - self.fmtScene = QLineEdit("") + self.fmtScene = QLineEdit("", self) self.fmtScene.setReadOnly(True) - self.btnScene = QToolButton() + self.btnScene = QToolButton(self) self.btnScene.setIcon(SHARED.theme.getIcon("edit")) self.btnScene.clicked.connect(lambda: self._editHeading(self.EDIT_SCENE)) self.hdeScene = QLabel(self.tr("Hide")) @@ -680,9 +679,9 @@ class _HeadingsTab(NScrollablePage): # Section Heading sectionHideTip = self._build.getLabel("headings.hideSection") self.lblSection = QLabel(self._build.getLabel("headings.fmtSection")) - self.fmtSection = QLineEdit("") + self.fmtSection = QLineEdit("", self) self.fmtSection.setReadOnly(True) - self.btnSection = QToolButton() + self.btnSection = QToolButton(self) self.btnSection.setIcon(SHARED.theme.getIcon("edit")) self.btnSection.clicked.connect(lambda: self._editHeading(self.EDIT_SECTION)) self.hdeSection = QLabel(self.tr("Hide")) @@ -867,7 +866,7 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter): def highlightBlock(self, text: str) -> None: """Add syntax highlighting to the text block.""" - for heading in nwHeadFmt.ALL: + for heading in nwHeadFmt.PAGE_HEADERS: pos = text.find(heading) if pos >= 0: chars = len(heading) @@ -1214,11 +1213,23 @@ class _OutputTab(NScrollableForm): # Open Document self.addGroupLabel(self._build.getLabel("odt")) + self.odtAddColours = NSwitch(self, width=2*iPx, height=iPx) self.addRow(self._build.getLabel("odt.addColours"), self.odtAddColours) + self.odtPageHeader = QLineEdit(self) + self.odtPageHeader.setMinimumWidth(CONFIG.pxInt(200)) + self.btnPageHeader = QToolButton(self) + self.btnPageHeader.setIcon(SHARED.theme.getIcon("revert")) + self.btnPageHeader.clicked.connect(self._resetPageHeader) + self.addRow( + self._build.getLabel("odt.pageHeader"), self.odtPageHeader, + button=self.btnPageHeader, stretch=(1, 1) + ) + # HTML Document self.addGroupLabel(self._build.getLabel("html")) + self.htmlAddStyles = NSwitch(self, width=2*iPx, height=iPx) self.addRow(self._build.getLabel("html.addStyles"), self.htmlAddStyles) @@ -1230,13 +1241,24 @@ class _OutputTab(NScrollableForm): def loadContent(self) -> None: """Populate the widgets.""" self.odtAddColours.setChecked(self._build.getBool("odt.addColours")) + self.odtPageHeader.setText(self._build.getStr("odt.pageHeader")) self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles")) return def saveContent(self) -> None: """Save choices back into build object.""" self._build.setValue("odt.addColours", self.odtAddColours.isChecked()) + self._build.setValue("odt.pageHeader", self.odtPageHeader.text()) self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked()) return + ## + # Private Slots + ## + + def _resetPageHeader(self) -> None: + """Reset the ODT header format to default.""" + self.odtPageHeader.setText(nwHeadFmt.ODT_AUTO) + return + # END Class _OutputTab