diff --git a/nw/core/toodt.py b/nw/core/toodt.py index 78cab3d3..ee83673c 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'" @@ -127,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 @@ -212,6 +223,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 +255,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 +269,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 +301,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 +686,34 @@ class ToOdt(Tokenizer): # Style Elements ## + def _pageStyles(self): + """Set the default page style. + """ + 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")] = 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")) + + 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.500cm" + etree.SubElement(xHead, _mkTag("style", "header-footer-properties"), attrib=theAttr) + + return + def _defaultStyles(self): """Set the default styles. """ @@ -721,6 +776,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 +934,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." )