From 3db99879668e3a1d86afe9b3951985b74f1322be Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 6 Feb 2021 23:22:23 +0100 Subject: [PATCH 1/2] Add a default header to Open Document files --- nw/core/toodt.py | 112 ++++++++++++++++++++++++++++++++++++++++++++++- nw/gui/build.py | 5 +-- 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/nw/core/toodt.py b/nw/core/toodt.py index 78cab3d3..b45e5c04 100644 --- a/nw/core/toodt.py +++ b/nw/core/toodt.py @@ -80,9 +80,12 @@ class ToOdt(Tokenizer): self._xMeta = None # Office meta root self._xStyl = None # Office styles root self._xAuto = None # Office auto-styles root + self._xMast = None # Office master-styles root self._xBody = None # Office body root self._xText = None # Office text root + self._xAut2 = None # Page layout auto-styles for ODT file + self._mainPara = {} # User-accessible paragraph styles self._autoPara = {} # Auto-generated paragraph styles self._autoText = {} # Auto-generated text styles @@ -92,6 +95,8 @@ class ToOdt(Tokenizer): self.textSize = 12 self.textFixed = False self.colourHead = False + self.addHeader = True + self.headerText = "" # Internal self._fontFamily = "'Liberation Sans'" @@ -212,6 +217,14 @@ class ToOdt(Tokenizer): self._lineHeight = f"{round(100 * self.lineHeight):d}%" self._textAlign = "justify" if self.doJustify else "left" + # Document Header + # =============== + + if self.headerText == "": + theTitle = self.theProject.bookTitle + theAuth = self.theProject.getAuthors() + self.headerText = f"{theTitle} / {theAuth} /" + # Create Roots # ============ @@ -236,6 +249,7 @@ class ToOdt(Tokenizer): self._xFont = etree.SubElement(self._dFlat, _mkTag("office", "font-face-decls")) self._xStyl = etree.SubElement(self._dFlat, _mkTag("office", "styles")) self._xAuto = etree.SubElement(self._dFlat, _mkTag("office", "automatic-styles")) + self._xMast = etree.SubElement(self._dFlat, _mkTag("office", "master-styles")) self._xBody = etree.SubElement(self._dFlat, _mkTag("office", "body")) etree.SubElement(self._xFont, _mkTag("style", "font-face"), attrib=fAttr) @@ -249,17 +263,22 @@ class ToOdt(Tokenizer): tMeta = _mkTag("office", "document-meta") tStyl = _mkTag("office", "document-styles") + # content.xml self._dCont = etree.Element(tCont, attrib=tAttr, nsmap=XML_NS) self._xFnt1 = etree.SubElement(self._dCont, _mkTag("office", "font-face-decls")) self._xAuto = etree.SubElement(self._dCont, _mkTag("office", "automatic-styles")) self._xBody = etree.SubElement(self._dCont, _mkTag("office", "body")) + # meta.xml self._dMeta = etree.Element(tMeta, attrib=tAttr, nsmap=XML_NS) self._xMeta = etree.SubElement(self._dMeta, _mkTag("office", "meta")) + # styles.xml self._dStyl = etree.Element(tStyl, attrib=tAttr, nsmap=XML_NS) - self._xFnt2 = etree.SubElement(self._dCont, _mkTag("office", "font-face-decls")) + self._xFnt2 = etree.SubElement(self._dStyl, _mkTag("office", "font-face-decls")) self._xStyl = etree.SubElement(self._dStyl, _mkTag("office", "styles")) + self._xAut2 = etree.SubElement(self._dStyl, _mkTag("office", "automatic-styles")) + self._xMast = etree.SubElement(self._dStyl, _mkTag("office", "master-styles")) etree.SubElement(self._xFnt1, _mkTag("style", "font-face"), attrib=fAttr) etree.SubElement(self._xFnt2, _mkTag("style", "font-face"), attrib=fAttr) @@ -276,8 +295,10 @@ class ToOdt(Tokenizer): xMeta = etree.SubElement(self._xMeta, _mkTag("meta", "generator")) xMeta.text = f"novelWriter/{nw.__version__}" + self._pageStyles() self._defaultStyles() self._useableStyles() + self._writeHeader() return @@ -659,6 +680,38 @@ class ToOdt(Tokenizer): # Style Elements ## + def _pageStyles(self): + """Set the default page style. + """ + # If we're in flat layout, the page style goes to the main auto-styles + # In archived file, we make a duplicate auto-styles in the self._xPage + # variable which is later added to the styles.xml to go with the + # master-page definition + theAttr = {} + theAttr[_mkTag("style", "name")] = "PM1" + if self._isFlat: + xPage = etree.SubElement(self._xAuto, _mkTag("style", "page-layout"), attrib=theAttr) + else: + xPage = etree.SubElement(self._xAut2, _mkTag("style", "page-layout"), attrib=theAttr) + + theAttr = {} + theAttr[_mkTag("fo", "margin-top")] = "2.000cm" + theAttr[_mkTag("fo", "margin-bottom")] = "2.000cm" + theAttr[_mkTag("fo", "margin-left")] = "2.000cm" + theAttr[_mkTag("fo", "margin-right")] = "2.000cm" + etree.SubElement(xPage, _mkTag("style", "page-layout-properties"), attrib=theAttr) + + xHead = etree.SubElement(xPage, _mkTag("style", "header-style")) + + theAttr = {} + theAttr[_mkTag("fo", "min-height")] = "0.600cm" + theAttr[_mkTag("fo", "margin-left")] = "0.000cm" + theAttr[_mkTag("fo", "margin-right")] = "0.000cm" + theAttr[_mkTag("fo", "margin-bottom")] = "0.499cm" + etree.SubElement(xHead, _mkTag("style", "header-footer-properties"), attrib=theAttr) + + return + def _defaultStyles(self): """Set the default styles. """ @@ -721,6 +774,19 @@ class ToOdt(Tokenizer): theAttr[_mkTag("fo", "font-size")] = self._fSizeHead etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr) + # Add Header and Footer Styles + # ============================ + if not self.addHeader: + return + + theAttr = {} + theAttr[_mkTag("style", "name")] = "Header_and_Footer" + theAttr[_mkTag("style", "display-name")] = "Header and Footer" + theAttr[_mkTag("style", "family")] = "paragraph" + theAttr[_mkTag("style", "parent-style-name")] = "Standard" + theAttr[_mkTag("style", "class")] = "extra" + etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr) + return def _useableStyles(self): @@ -866,6 +932,50 @@ class ToOdt(Tokenizer): self._mainPara["Heading_4"] = oStyle + # Add Header Style + # ================ + if not self.addHeader: + return + + oStyle = ODTParagraphStyle() + oStyle.setDisplayName("Header") + oStyle.setParentStyleName("Header_and_Footer") + oStyle.setTextAlign("right") + oStyle.packXML(self._xStyl, "Header") + + self._mainPara["Header"] = oStyle + + return + + def _writeHeader(self): + """Write the header elements. + """ + if not self.addHeader: + return + + theAttr = {} + theAttr[_mkTag("style", "name")] = "Standard" + theAttr[_mkTag("style", "page-layout-name")] = "PM1" + xPage = etree.SubElement(self._xMast, _mkTag("style", "master-page"), attrib=theAttr) + + # Standard Page Header + xHead = etree.SubElement(xPage, _mkTag("style", "header")) + xPar = etree.SubElement(xHead, _mkTag("text", "p"), attrib={ + _mkTag("text", "style-name"): "Header" + }) + xPar.text = self.headerText.strip() + " " + + xTail = etree.SubElement(xPar, _mkTag("text", "page-number"), attrib={ + _mkTag("text", "select-page"): "current" + }) + xTail.text = "2" + + # First Page Header + xHead = etree.SubElement(xPage, _mkTag("style", "header-first")) + xPar = etree.SubElement(xHead, _mkTag("text", "p"), attrib={ + _mkTag("text", "style-name"): "Header" + }) + return # END Class ToOdt diff --git a/nw/gui/build.py b/nw/gui/build.py index f3d0cad5..a252fc9d 100644 --- a/nw/gui/build.py +++ b/nw/gui/build.py @@ -365,10 +365,9 @@ class GuiBuildNovel(QDialog): # Build Button # ============ - self.buildProgress = QProgressBar() self.buildProgress = QProgressBar() - self.buildNovel = QPushButton("Build Project") + self.buildNovel = QPushButton("Build Preview") self.buildNovel.clicked.connect(self._buildPreview) # Action Buttons @@ -1155,7 +1154,7 @@ class GuiBuildNovelDocView(QTextBrowser): self.qDocument.setDocumentMargin(self.mainConf.getTextMargin()) self.setPlaceholderText( "This area will show the content of the document to be " - "exported or printed. Press the \"Build Project\" button " + "exported or printed. Press the \"Build Preview\" button " "to generate content." ) From f816f3d29b5cccab68bcc472090e98fb01af81b6 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 6 Feb 2021 23:28:41 +0100 Subject: [PATCH 2/2] Turn document margins into settings --- nw/core/toodt.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/nw/core/toodt.py b/nw/core/toodt.py index b45e5c04..ee83673c 100644 --- a/nw/core/toodt.py +++ b/nw/core/toodt.py @@ -132,6 +132,12 @@ class ToOdt(Tokenizer): self._mBotText = "0.247cm" self._mBotMeta = "0.106cm" + ## Document Margins + self._mDocTop = "2.000cm" + self._mDocBtm = "2.000cm" + self._mDocLeft = "2.000cm" + self._mDocRight = "2.000cm" + ## Colour self._colHead12 = None self._opaHead12 = None @@ -683,10 +689,6 @@ class ToOdt(Tokenizer): def _pageStyles(self): """Set the default page style. """ - # If we're in flat layout, the page style goes to the main auto-styles - # In archived file, we make a duplicate auto-styles in the self._xPage - # variable which is later added to the styles.xml to go with the - # master-page definition theAttr = {} theAttr[_mkTag("style", "name")] = "PM1" if self._isFlat: @@ -695,10 +697,10 @@ class ToOdt(Tokenizer): xPage = etree.SubElement(self._xAut2, _mkTag("style", "page-layout"), attrib=theAttr) theAttr = {} - theAttr[_mkTag("fo", "margin-top")] = "2.000cm" - theAttr[_mkTag("fo", "margin-bottom")] = "2.000cm" - theAttr[_mkTag("fo", "margin-left")] = "2.000cm" - theAttr[_mkTag("fo", "margin-right")] = "2.000cm" + theAttr[_mkTag("fo", "margin-top")] = self._mDocTop + theAttr[_mkTag("fo", "margin-bottom")] = self._mDocBtm + theAttr[_mkTag("fo", "margin-left")] = self._mDocLeft + theAttr[_mkTag("fo", "margin-right")] = self._mDocRight etree.SubElement(xPage, _mkTag("style", "page-layout-properties"), attrib=theAttr) xHead = etree.SubElement(xPage, _mkTag("style", "header-style")) @@ -707,7 +709,7 @@ class ToOdt(Tokenizer): theAttr[_mkTag("fo", "min-height")] = "0.600cm" theAttr[_mkTag("fo", "margin-left")] = "0.000cm" theAttr[_mkTag("fo", "margin-right")] = "0.000cm" - theAttr[_mkTag("fo", "margin-bottom")] = "0.499cm" + theAttr[_mkTag("fo", "margin-bottom")] = "0.500cm" etree.SubElement(xHead, _mkTag("style", "header-footer-properties"), attrib=theAttr) return