Add PDF format
This commit is contained in:
@@ -250,6 +250,7 @@ class nwLabels:
|
||||
nwBuildFmt.NWD: QT_TRANSLATE_NOOP("Constant", "novelWriter Markup (.txt)"),
|
||||
nwBuildFmt.STD_MD: QT_TRANSLATE_NOOP("Constant", "Standard Markdown (.md)"),
|
||||
nwBuildFmt.EXT_MD: QT_TRANSLATE_NOOP("Constant", "Extended Markdown (.md)"),
|
||||
nwBuildFmt.PDF: QT_TRANSLATE_NOOP("Constant", "Portable Document Format (.pdf)"),
|
||||
nwBuildFmt.J_HTML: QT_TRANSLATE_NOOP("Constant", "JSON + novelWriter HTML (.json)"),
|
||||
nwBuildFmt.J_NWD: QT_TRANSLATE_NOOP("Constant", "JSON + novelWriter Markup (.json)"),
|
||||
}
|
||||
@@ -260,6 +261,7 @@ class nwLabels:
|
||||
nwBuildFmt.NWD: ".txt",
|
||||
nwBuildFmt.STD_MD: ".md",
|
||||
nwBuildFmt.EXT_MD: ".md",
|
||||
nwBuildFmt.PDF: ".pdf",
|
||||
nwBuildFmt.J_HTML: ".json",
|
||||
nwBuildFmt.J_NWD: ".json",
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ from novelwriter.formats.tohtml import ToHtml
|
||||
from novelwriter.formats.tokenizer import Tokenizer
|
||||
from novelwriter.formats.tomarkdown import ToMarkdown
|
||||
from novelwriter.formats.toodt import ToOdt
|
||||
from novelwriter.formats.toqdoc import TextDocumentTheme, ToQTextDocument
|
||||
from novelwriter.formats.toqdoc import ToQTextDocument
|
||||
from novelwriter.formats.toraw import ToRaw
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -121,24 +121,15 @@ class NWBuildDocument:
|
||||
self._queue.append(item.itemHandle)
|
||||
return
|
||||
|
||||
def iterBuildPreview(self, theme: TextDocumentTheme) -> Iterable[tuple[int, bool]]:
|
||||
def iterBuildPreview(self) -> Iterable[tuple[int, bool]]:
|
||||
"""Build a preview QTextDocument."""
|
||||
makeObj = ToQTextDocument(self._project)
|
||||
filtered = self._setupBuild(makeObj)
|
||||
makeObj.initDocument()
|
||||
|
||||
self._count = True
|
||||
self._outline = True
|
||||
|
||||
font = QFont()
|
||||
font.fromString(self._build.getStr("format.textFont"))
|
||||
|
||||
makeObj.initDocument(font, theme)
|
||||
for i, tHandle in enumerate(self._queue):
|
||||
self._error = None
|
||||
if filtered.get(tHandle, (False, 0))[0]:
|
||||
yield i, self._doBuild(makeObj, tHandle)
|
||||
else:
|
||||
yield i, False
|
||||
yield from self._iterBuild(makeObj, filtered)
|
||||
|
||||
makeObj.appendFootnotes()
|
||||
|
||||
@@ -191,6 +182,19 @@ class NWBuildDocument:
|
||||
if self._build.getBool("format.replaceTabs"):
|
||||
makeObj.replaceTabs(nSpaces=4, spaceChar=" ")
|
||||
|
||||
elif bFormat == nwBuildFmt.PDF:
|
||||
makeObj = ToQTextDocument(self._project)
|
||||
filtered = self._setupBuild(makeObj)
|
||||
makeObj.initDocument()
|
||||
|
||||
yield from self._iterBuild(makeObj, filtered)
|
||||
|
||||
makeObj.appendFootnotes()
|
||||
|
||||
else:
|
||||
logger.error("Unsupported document format")
|
||||
return
|
||||
|
||||
self._error = None
|
||||
self._cache = makeObj
|
||||
|
||||
@@ -308,6 +312,9 @@ class NWBuildDocument:
|
||||
scale*self._build.getFloat("format.rightMargin"),
|
||||
)
|
||||
|
||||
if isinstance(bldObj, ToQTextDocument):
|
||||
pass
|
||||
|
||||
filtered = self._build.buildItemFilter(
|
||||
self._project, withRoots=self._build.getBool("text.addNoteHeadings")
|
||||
)
|
||||
|
||||
+3
-2
@@ -184,8 +184,9 @@ class nwBuildFmt(Enum):
|
||||
NWD = 3
|
||||
STD_MD = 4
|
||||
EXT_MD = 5
|
||||
J_HTML = 6
|
||||
J_NWD = 7
|
||||
PDF = 6
|
||||
J_HTML = 7
|
||||
J_NWD = 8
|
||||
|
||||
|
||||
class nwStatusShape(Enum):
|
||||
|
||||
@@ -31,14 +31,15 @@ from PyQt5.QtGui import (
|
||||
QColor, QFont, QFontMetricsF, QTextBlockFormat, QTextCharFormat,
|
||||
QTextCursor, QTextDocument
|
||||
)
|
||||
from PyQt5.QtPrintSupport import QPrinter
|
||||
|
||||
from novelwriter.constants import nwHeaders, nwHeadFmt, nwKeyWords, nwLabels, nwUnicode
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.formats.tokenizer import T_Formats, Tokenizer
|
||||
from novelwriter.types import (
|
||||
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight,
|
||||
QtBlack, QtPageBreakAfter, QtPageBreakBefore, QtTransparent,
|
||||
QtVAlignNormal, QtVAlignSub, QtVAlignSuper
|
||||
QtPageBreakAfter, QtPageBreakBefore, QtTransparent, QtVAlignNormal,
|
||||
QtVAlignSub, QtVAlignSuper
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -47,18 +48,18 @@ T_TextStyle = tuple[QTextBlockFormat, QTextCharFormat]
|
||||
|
||||
|
||||
class TextDocumentTheme:
|
||||
text: QColor = QtBlack
|
||||
highlight: QColor = QtTransparent
|
||||
head: QColor = QtBlack
|
||||
comment: QColor = QtBlack
|
||||
note: QColor = QtBlack
|
||||
code: QColor = QtBlack
|
||||
modifier: QColor = QtBlack
|
||||
keyword: QColor = QtBlack
|
||||
tag: QColor = QtBlack
|
||||
optional: QColor = QtBlack
|
||||
dialog: QColor = QtBlack
|
||||
altdialog: QColor = QtBlack
|
||||
text: QColor = QColor(0, 0, 0)
|
||||
highlight: QColor = QColor(255, 255, 166)
|
||||
head: QColor = QColor(66, 113, 174)
|
||||
comment: QColor = QColor(100, 100, 100)
|
||||
note: QColor = QColor(129, 55, 9)
|
||||
code: QColor = QColor(66, 113, 174)
|
||||
modifier: QColor = QColor(129, 55, 9)
|
||||
keyword: QColor = QColor(245, 135, 31)
|
||||
tag: QColor = QColor(66, 113, 174)
|
||||
optional: QColor = QColor(66, 113, 174)
|
||||
dialog: QColor = QColor(66, 113, 174)
|
||||
altdialog: QColor = QColor(129, 55, 9)
|
||||
|
||||
|
||||
def newBlock(cursor: QTextCursor, bFmt: QTextBlockFormat) -> None:
|
||||
@@ -91,11 +92,21 @@ class ToQTextDocument(Tokenizer):
|
||||
|
||||
return
|
||||
|
||||
def initDocument(self, font: QFont, theme: TextDocumentTheme) -> None:
|
||||
"""Initialise all computed values of the document."""
|
||||
self._textFont = font
|
||||
self._theme = theme
|
||||
##
|
||||
# Setters
|
||||
##
|
||||
|
||||
def setTheme(self, theme: TextDocumentTheme) -> None:
|
||||
"""Set the document colour theme."""
|
||||
self._theme = theme
|
||||
return
|
||||
|
||||
##
|
||||
# Class Methods
|
||||
##
|
||||
|
||||
def initDocument(self) -> None:
|
||||
"""Initialise all computed values of the document."""
|
||||
self._document.setUndoRedoEnabled(False)
|
||||
self._document.blockSignals(True)
|
||||
self._document.clear()
|
||||
@@ -276,7 +287,12 @@ class ToQTextDocument(Tokenizer):
|
||||
return
|
||||
|
||||
def saveDocument(self, path: Path) -> None:
|
||||
"""Not implemented."""
|
||||
"""Save the document to a PDF file."""
|
||||
printer = QPrinter(QPrinter.PrinterMode.PrinterResolution)
|
||||
printer.setOutputFormat(QPrinter.OutputFormat.PdfFormat)
|
||||
printer.setPaperSize(QPrinter.PageSize.A4)
|
||||
printer.setOutputFileName(str(path))
|
||||
self._document.print(printer)
|
||||
return
|
||||
|
||||
def appendFootnotes(self) -> None:
|
||||
|
||||
@@ -211,7 +211,9 @@ class GuiDocViewer(QTextBrowser):
|
||||
qDoc = ToQTextDocument(SHARED.project)
|
||||
qDoc.setJustify(CONFIG.doJustify)
|
||||
qDoc.setDialogueHighlight(True)
|
||||
qDoc.initDocument(CONFIG.textFont, self._docTheme)
|
||||
qDoc.setFont(CONFIG.textFont)
|
||||
qDoc.setTheme(self._docTheme)
|
||||
qDoc.initDocument()
|
||||
qDoc.setKeywords(True)
|
||||
qDoc.setComments(CONFIG.viewComments)
|
||||
qDoc.setSynopsis(CONFIG.viewSynopsis)
|
||||
|
||||
@@ -45,7 +45,7 @@ from novelwriter.core.docbuild import NWBuildDocument
|
||||
from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton, NToolDialog
|
||||
from novelwriter.extensions.progressbars import NProgressCircle
|
||||
from novelwriter.formats.tokenizer import HeadingFormatter
|
||||
from novelwriter.formats.toqdoc import TextDocumentTheme, ToQTextDocument
|
||||
from novelwriter.formats.toqdoc import ToQTextDocument
|
||||
from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON
|
||||
from novelwriter.tools.manusbuild import GuiManuscriptBuild
|
||||
from novelwriter.tools.manussettings import GuiBuildSettings
|
||||
@@ -330,22 +330,8 @@ class GuiManuscript(NToolDialog):
|
||||
docBuild = NWBuildDocument(SHARED.project, build)
|
||||
docBuild.queueAll()
|
||||
|
||||
theme = TextDocumentTheme()
|
||||
theme.text = QColor(0, 0, 0)
|
||||
theme.highlight = QColor(255, 255, 166)
|
||||
theme.head = QColor(66, 113, 174)
|
||||
theme.comment = QColor(100, 100, 100)
|
||||
theme.note = QColor(129, 55, 9)
|
||||
theme.code = QColor(66, 113, 174)
|
||||
theme.modifier = QColor(129, 55, 9)
|
||||
theme.keyword = QColor(245, 135, 31)
|
||||
theme.tag = QColor(66, 113, 174)
|
||||
theme.optional = QColor(66, 113, 174)
|
||||
theme.dialog = QColor(66, 113, 174)
|
||||
theme.altdialog = QColor(129, 55, 9)
|
||||
|
||||
self.docPreview.beginNewBuild(len(docBuild))
|
||||
for step, _ in docBuild.iterBuildPreview(theme):
|
||||
for step, _ in docBuild.iterBuildPreview():
|
||||
self.docPreview.buildStep(step + 1)
|
||||
QApplication.processEvents()
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from PyQt5.QtGui import QColor, QTextBlock, QTextCharFormat, QTextCursor
|
||||
from PyQt5.QtGui import QTextBlock, QTextCharFormat, QTextCursor
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.constants import nwUnicode
|
||||
@@ -34,18 +34,6 @@ from novelwriter.types import (
|
||||
)
|
||||
|
||||
THEME = TextDocumentTheme()
|
||||
THEME.text = QColor(0, 0, 0)
|
||||
THEME.highlight = QColor(255, 255, 166)
|
||||
THEME.head = QColor(66, 113, 174)
|
||||
THEME.comment = QColor(100, 100, 100)
|
||||
THEME.note = QColor(129, 55, 9)
|
||||
THEME.code = QColor(66, 113, 174)
|
||||
THEME.modifier = QColor(129, 55, 9)
|
||||
THEME.keyword = QColor(245, 135, 31)
|
||||
THEME.tag = QColor(66, 113, 174)
|
||||
THEME.optional = QColor(66, 113, 174)
|
||||
THEME.dialog = QColor(113, 140, 0)
|
||||
THEME.altdialog = QColor(234, 183, 0)
|
||||
|
||||
|
||||
def charFmtInBlock(block: QTextBlock, pos: int) -> QTextCharFormat:
|
||||
@@ -60,8 +48,8 @@ def testFmtToQTextDocument_ConvertHeaders(mockGUI):
|
||||
"""Test header formats in the ToQTextDocument class."""
|
||||
project = NWProject()
|
||||
qdoc = ToQTextDocument(project)
|
||||
qdoc.initDocument(CONFIG.textFont, THEME)
|
||||
qdoc.saveDocument("") # Doesn't do anything for this format
|
||||
qdoc.initDocument()
|
||||
# qdoc.saveDocument("") # Doesn't do anything for this format
|
||||
|
||||
qdoc._isNovel = True
|
||||
qdoc._isFirst = True
|
||||
@@ -137,7 +125,7 @@ def testFmtToQTextDocument_SeparatorSkip(mockGUI):
|
||||
"""Test separator and skip in the ToQTextDocument class."""
|
||||
project = NWProject()
|
||||
qdoc = ToQTextDocument(project)
|
||||
qdoc.initDocument(CONFIG.textFont, THEME)
|
||||
qdoc.initDocument()
|
||||
|
||||
qdoc._isNovel = True
|
||||
qdoc._isFirst = True
|
||||
@@ -203,7 +191,7 @@ def testFmtToQTextDocument_NovelMeta(mockGUI):
|
||||
"""Test novel meta formats in the ToQTextDocument class."""
|
||||
project = NWProject()
|
||||
qdoc = ToQTextDocument(project)
|
||||
qdoc.initDocument(CONFIG.textFont, THEME)
|
||||
qdoc.initDocument()
|
||||
|
||||
qdoc._isNovel = True
|
||||
qdoc._isFirst = True
|
||||
@@ -280,7 +268,7 @@ def testFmtToQTextDocument_NoteMeta(mockGUI):
|
||||
"""Test note meta formats in the ToQTextDocument class."""
|
||||
project = NWProject()
|
||||
qdoc = ToQTextDocument(project)
|
||||
qdoc.initDocument(CONFIG.textFont, THEME)
|
||||
qdoc.initDocument()
|
||||
|
||||
qdoc._isNovel = False
|
||||
qdoc._isFirst = True
|
||||
@@ -338,7 +326,7 @@ def testFmtToQTextDocument_TextBlockFormats(mockGUI):
|
||||
project = NWProject()
|
||||
qdoc = ToQTextDocument(project)
|
||||
qdoc.setFirstLineIndent(True, 2.0, False)
|
||||
qdoc.initDocument(CONFIG.textFont, THEME)
|
||||
qdoc.initDocument()
|
||||
|
||||
qdoc._isNovel = True
|
||||
qdoc._isFirst = True
|
||||
@@ -460,7 +448,7 @@ def testFmtToQTextDocument_TextCharFormats(mockGUI):
|
||||
assert qdoc.document.toPlainText() == ""
|
||||
|
||||
# Init
|
||||
qdoc.initDocument(CONFIG.textFont, THEME)
|
||||
qdoc.initDocument()
|
||||
|
||||
qdoc._isNovel = True
|
||||
qdoc._isFirst = True
|
||||
@@ -581,7 +569,7 @@ def testFmtToQTextDocument_Footnotes(mockGUI):
|
||||
"""Test footnotes in the ToQTextDocument class."""
|
||||
project = NWProject()
|
||||
qdoc = ToQTextDocument(project)
|
||||
qdoc.initDocument(CONFIG.textFont, THEME)
|
||||
qdoc.initDocument()
|
||||
|
||||
qdoc._isNovel = True
|
||||
qdoc._isFirst = True
|
||||
|
||||
Reference in New Issue
Block a user