From fd27f8d1e8b6d8ef2cbc55082035560c30e8dff4 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 23 May 2020 21:15:08 +0200 Subject: [PATCH] Added note root headings, changed some formatting, and improved export --- nw/core/tohtml.py | 6 +- nw/core/tokenizer.py | 31 +++++-- nw/gui/build.py | 140 +++++++++++++++++-------------- sample/sampleNovel/nwProject.nwx | 8 +- 4 files changed, 110 insertions(+), 75 deletions(-) diff --git a/nw/core/tohtml.py b/nw/core/tohtml.py index 9b5eb425..ba099335 100644 --- a/nw/core/tohtml.py +++ b/nw/core/tohtml.py @@ -119,9 +119,9 @@ class ToHtml(Tokenizer): if self.isNovel and self.genMode != self.M_PREVIEW: # For novel files for export, we bump the titles one level - # up, as this is more useful for printing and word processor + # up as this is more useful for printing and word processor # imports. - h1 = "h1 class=\"title\"" + h1 = "h1 class='title'" h2 = "h1" h3 = "h2" h4 = "h3" @@ -254,7 +254,7 @@ class ToHtml(Tokenizer): theStyles.append(r"h1, h2 {color: rgb(66, 113, 174);}") theStyles.append(r"h3, h4 {color: rgb(50, 50, 50);}") theStyles.append(r"h1, h2, h3, h4 {page-break-after: avoid;}") - theStyles.append(r".title {font-size: 2.5em; font-weight: bold;}") + theStyles.append(r".title {font-size: 2.5em;}") theStyles.append(r".tags {color: rgb(245, 135, 31); font-weight: bold;}") theStyles.append(r".break {text-align: left;}") theStyles.append(r".sep {text-align: center; margin-top: 1em; margin-bottom: 1em;}") diff --git a/nw/core/tokenizer.py b/nw/core/tokenizer.py index d4e001f5..c94f418f 100644 --- a/nw/core/tokenizer.py +++ b/nw/core/tokenizer.py @@ -34,7 +34,7 @@ from PyQt5.QtCore import QRegularExpression from nw.core.document import NWDoc from nw.core.tools import numberToWord -from nw.constants import nwItemLayout +from nw.constants import nwItemLayout, nwItemType logger = logging.getLogger(__name__) @@ -198,6 +198,25 @@ class Tokenizer(): # Class Methods ## + def addRootHeading(self, theHandle): + """Add a heading at the start if a new root folder. + """ + theItem = self.theProject.projTree[theHandle] + if theItem is None: + return False + + if theItem.itemType != nwItemType.ROOT: + return False + + theTitle = "Notes: %s" % theItem.itemName + self.theTokens = [] + self.theTokens.append(( + self.T_TITLE, theTitle, None, self.A_PBB | self.A_CENTRE + )) + self.theMarkdown = "# %s\n\n" % theTitle + + return True + def setText(self, theHandle, theText=None): """Set the text for the tokenizer from a handle. If theText is not set, load it from the file. @@ -205,6 +224,8 @@ class Tokenizer(): self.theHandle = theHandle self.theItem = self.theProject.projTree[theHandle] + if self.theItem is None: + return if theText is not None: # If the text is set, just use that @@ -319,7 +340,7 @@ class Tokenizer(): elif aLine[:2] == "# ": self.theTokens.append(( - self.T_HEAD1, aLine[2:].strip(), None, self.A_PBB + self.T_HEAD1, aLine[2:].strip(), None, self.A_NONE )) tmpMarkdown.append("%s\n" % aLine) @@ -386,8 +407,8 @@ class Tokenizer(): if self.isNone or self.isNote: return - # For novel files, we need to handle chapter numbering and scene - # breaks + # For novel files, we need to handle chapter numbering, scene + # numbering, and scene breaks if self.isNovel: for n in range(len(self.theTokens)): @@ -504,7 +525,7 @@ class Tokenizer(): ) else: self.theTokens[n] = ( - tType, tText, tFormat, self.A_PBB | self.A_CENTRE + tType, tText, tFormat, self.A_PBB | self.A_CENTRE ) else: self.theTokens[n] = ( diff --git a/nw/gui/build.py b/nw/gui/build.py index 8baf00fc..1bf268eb 100644 --- a/nw/gui/build.py +++ b/nw/gui/build.py @@ -34,7 +34,7 @@ from time import time from PyQt5.QtCore import Qt, QByteArray from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog from PyQt5.QtGui import ( - QTextOption, QPalette, QColor, QTextDocumentWriter + QTextOption, QPalette, QColor, QTextDocumentWriter, QFont ) from PyQt5.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QTextBrowser, QPushButton, QLabel, @@ -44,7 +44,7 @@ from PyQt5.QtWidgets import ( from nw.gui.additions import QSwitch from nw.core import ToHtml from nw.constants import ( - nwConst, nwFiles, nwAlert, nwItemType, nwItemLayout, nwItemClass + nwAlert, nwItemType, nwItemLayout, nwItemClass ) logger = logging.getLogger(__name__) @@ -69,10 +69,9 @@ class GuiBuildNovel(QDialog): self.theTheme = theParent.theTheme self.optState = self.theProject.optState - self.htmlText = [] # List of html document - self.htmlStyle = [] # List of html styles - self.nwdText = [] # List of markdown documents - self.textLayout = [] # List of nwItemLayout entries + self.htmlText = [] # List of html document + self.htmlStyle = [] # List of html styles + self.nwdText = [] # List of markdown documents self.setWindowTitle("Build Novel Project") self.setMinimumWidth(800) @@ -323,10 +322,21 @@ class GuiBuildNovel(QDialog): self.htmlText = [] self.htmlStyle = [] self.nwdText = [] - self.textLayout = [] for nItt, tItem in enumerate(self.theProject.projTree): - if self._checkInclude(tItem, noteFiles, novelFiles, ignoreFlag): + + noteRoot = noteFiles + noteRoot &= tItem.itemType == nwItemType.ROOT + noteRoot &= tItem.itemClass != nwItemClass.NOVEL + + if noteRoot: + # Add headers for root folders of notes + makeHtml.addRootHeading(tItem.itemHandle) + makeHtml.doConvert() + self.htmlText.append(makeHtml.getResult()) + self.nwdText.append(makeHtml.getFilteredMarkdown()) + + elif self._checkInclude(tItem, noteFiles, novelFiles, ignoreFlag): makeHtml.setText(tItem.itemHandle) makeHtml.doAutoReplace() makeHtml.tokenizeText() @@ -335,7 +345,6 @@ class GuiBuildNovel(QDialog): makeHtml.doPostProcessing() self.htmlText.append(makeHtml.getResult()) self.nwdText.append(makeHtml.getFilteredMarkdown()) - self.textLayout.append(tItem.itemLayout) # Update progress bar, also for skipped items self.buildProgress.setValue(nItt+1) @@ -461,61 +470,53 @@ class GuiBuildNovel(QDialog): return False # Do the actual writing + wSuccess = False + errMsg = "" if outTool == "Qt": docWriter = QTextDocumentWriter() docWriter.setFileName(savePath) docWriter.setFormat(byteFmt) - if docWriter.write(self.docView.qDocument): - self.theParent.makeAlert( - "Document successfully written in %s format to file: %s" % ( - textFmt, savePath - ), nwAlert.INFO - ) - else: - self.theParent.makeAlert( - "Failed to write document in %s format to file: %s" % ( - textFmt, savePath - ), nwAlert.ERROR - ) + wSuccess = docWriter.write(self.docView.qDocument) elif outTool == "NW": try: with open(savePath, mode="w", encoding="utf8") as outFile: if theFormat == self.FMT_HTM: # Write novelWriter HTML data - outFile.write("\n") - outFile.write("\n") - outFile.write("\n") - outFile.write("\n") - outFile.write("\n") - outFile.write("\n") - outFile.write("\n") - outFile.write("
\n") - for aLine in self.htmlText: - outFile.write(aLine) - outFile.write("
\n") - outFile.write("\n") - outFile.write("\n") + theStyle = self.htmlStyle.copy() + theStyle.append(r"article {width: 800px; margin: 40px auto;}") + theHtml = ( + "\n" + "\n" + "\n" + "\n" + "{projTitle:s}\n" + "\n" + "\n" + "\n" + "
\n" + "{bodyText:s}\n" + "
\n" + "\n" + "\n" + ).format( + projTitle = self.theProject.projName, + htmlStyle = "\n".join(theStyle), + bodyText = "".join(self.htmlText), + ) + outFile.write(theHtml) elif theFormat == self.FMT_NWD: # Write novelWriter markdown data for aLine in self.nwdText: outFile.write(aLine) - self.theParent.makeAlert( - "Document successfully written in %s format to file: %s" % ( - textFmt, savePath - ), nwAlert.INFO - ) + wSuccess = True except Exception as e: - self.theParent.makeAlert( - "Failed to write document in %s format to file: %s" % ( - textFmt, str(e) - ), nwAlert.ERROR - ) + errMsg = str(e) elif outTool == "QtPrint" and theFormat == self.FMT_PDF: try: @@ -527,23 +528,29 @@ class GuiBuildNovel(QDialog): thePrinter.setColorMode(QPrinter.Color) thePrinter.setOutputFileName(savePath) self.docView.qDocument.print(thePrinter) - self.theParent.makeAlert( - "Document successfully written in %s format to file: %s" % ( - textFmt, savePath - ), nwAlert.INFO - ) + wSuccess = True except Exception as e: - self.theParent.makeAlert( - "Failed to write document in %s format to file: %s" % ( - textFmt, str(e) - ), nwAlert.ERROR - ) + errMsg - str(e) else: - return False + errMsg = "Unknown format" - return True + # Report to user + if wSuccess: + self.theParent.makeAlert( + "%s file successfully written to:
%s" % ( + textFmt, savePath + ), nwAlert.INFO + ) + else: + self.theParent.makeAlert( + "Failed to write %s file. %s" % ( + textFmt, errMsg + ), nwAlert.ERROR + ) + + return wSuccess def _printDocument(self): """Open the print preview dialog. @@ -557,7 +564,6 @@ class GuiBuildNovel(QDialog): """Connect the print preview painter to the document viewer. """ thePrinter.setOrientation(QPrinter.Portrait) - thePrinter.setOutputFormat(QPrinter.NativeFormat | QPrinter.PdfFormat) self.docView.qDocument.print(thePrinter) return @@ -646,6 +652,14 @@ class GuiBuildNovelDocView(QTextBrowser): self.qDocument = self.document() self.qDocument.setDocumentMargin(self.mainConf.textMargin) + theFont = QFont() + if self.mainConf.textFont is None: + # If none is defined, set the default back to config + self.mainConf.textFont = self.qDocument.defaultFont().family() + theFont.setFamily(self.mainConf.textFont) + theFont.setPointSize(self.mainConf.textSize) + self.setFont(theFont) + theOpt = QTextOption() if self.mainConf.doJustify: theOpt.setAlignment(Qt.AlignJustify) @@ -667,10 +681,10 @@ class GuiBuildNovelDocView(QTextBrowser): def setContent(self, theText): """Set the content, either from text or list of text. """ - if isinstance(theText, str): - self.setHtml(theText) - else: - self.setHtml("".join(theText)) + if isinstance(theText, list): + theText = "".join(theText) + theText = theText.replace(" "," "*4) + self.setHtml(theText) return def setStyleSheet(self, theStyles=[]): diff --git a/sample/sampleNovel/nwProject.nwx b/sample/sampleNovel/nwProject.nwx index d0405ad5..b4b7b117 100644 --- a/sample/sampleNovel/nwProject.nwx +++ b/sample/sampleNovel/nwProject.nwx @@ -1,5 +1,5 @@ - + Sample Project Sample Project @@ -20,12 +20,12 @@ %title% - Chapter %chnum%.\\%title% + Chapter %chnum%: %title% %title% - Scene %chnum%.%scnum%: %title% + * * *
True - False + True False