Move colour theme to Tokenizer class
This commit is contained in:
@@ -29,6 +29,8 @@ import re
|
||||
|
||||
from enum import Flag, IntEnum
|
||||
|
||||
from PyQt5.QtGui import QColor
|
||||
|
||||
ESCAPES = {r"\*": "*", r"\~": "~", r"\_": "_", r"\[": "[", r"\]": "]", r"\ ": ""}
|
||||
RX_ESC = re.compile("|".join([re.escape(k) for k in ESCAPES.keys()]), flags=re.DOTALL)
|
||||
|
||||
@@ -40,6 +42,23 @@ def stripEscape(text: str) -> str:
|
||||
return text
|
||||
|
||||
|
||||
class TextDocumentTheme:
|
||||
"""Default document theme."""
|
||||
|
||||
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)
|
||||
|
||||
|
||||
# Enums
|
||||
# =====
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ from typing import NamedTuple
|
||||
from zipfile import ZIP_DEFLATED, ZipFile
|
||||
|
||||
from PyQt5.QtCore import QMarginsF, QSizeF
|
||||
from PyQt5.QtGui import QColor
|
||||
|
||||
from novelwriter import __version__
|
||||
from novelwriter.common import firstFloat, xmlSubElem
|
||||
@@ -41,6 +42,7 @@ from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, nwStyles
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt
|
||||
from novelwriter.formats.tokenizer import Tokenizer
|
||||
from novelwriter.types import QtHexRgb
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -80,6 +82,11 @@ def _mkTag(ns: str, tag: str) -> str:
|
||||
return tag
|
||||
|
||||
|
||||
def _docXCol(color: QColor) -> str:
|
||||
"""Format a QColor as the DocX accepted value."""
|
||||
return color.name(QtHexRgb).lstrip("#")
|
||||
|
||||
|
||||
# Formatting Codes
|
||||
X_BLD = 0x001 # Bold format
|
||||
X_ITA = 0x002 # Italic format
|
||||
@@ -115,8 +122,6 @@ S_HEAD = "Header"
|
||||
S_FNOTE = "FootnoteText"
|
||||
|
||||
# Colours
|
||||
COL_HEAD_L12 = "2a6099"
|
||||
COL_HEAD_L34 = "444444"
|
||||
COL_DIALOG_M = "2a6099"
|
||||
COL_DIALOG_A = "813709"
|
||||
COL_META_TXT = "813709"
|
||||
@@ -535,7 +540,7 @@ class ToDocX(Tokenizer):
|
||||
styles: list[DocXParStyle] = []
|
||||
|
||||
hScale = self._scaleHeads
|
||||
hColor = self._colorHeads
|
||||
hColor = _docXCol(self._theme.head) if self._colorHeads else None
|
||||
fSz = self._fontSize
|
||||
fnSz = 0.8 * self._fontSize
|
||||
fSz0 = (nwStyles.H_SIZES[0] * fSz) if hScale else fSz
|
||||
@@ -582,7 +587,7 @@ class ToDocX(Tokenizer):
|
||||
after=fSz * self._marginHead1[1],
|
||||
line=fSz1 * self._lineHeight,
|
||||
level=0,
|
||||
color=COL_HEAD_L12 if hColor else None,
|
||||
color=hColor,
|
||||
bold=self._boldHeads,
|
||||
))
|
||||
|
||||
@@ -597,7 +602,7 @@ class ToDocX(Tokenizer):
|
||||
after=fSz * self._marginHead2[1],
|
||||
line=fSz2 * self._lineHeight,
|
||||
level=1,
|
||||
color=COL_HEAD_L12 if hColor else None,
|
||||
color=hColor,
|
||||
bold=self._boldHeads,
|
||||
))
|
||||
|
||||
@@ -612,7 +617,7 @@ class ToDocX(Tokenizer):
|
||||
after=fSz * self._marginHead3[1],
|
||||
line=fSz3 * self._lineHeight,
|
||||
level=1,
|
||||
color=COL_HEAD_L34 if hColor else None,
|
||||
color=hColor,
|
||||
bold=self._boldHeads,
|
||||
))
|
||||
|
||||
@@ -627,7 +632,7 @@ class ToDocX(Tokenizer):
|
||||
after=fSz * self._marginHead4[1],
|
||||
line=fSz4 * self._lineHeight,
|
||||
level=1,
|
||||
color=COL_HEAD_L34 if hColor else None,
|
||||
color=hColor,
|
||||
bold=self._boldHeads,
|
||||
))
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ from novelwriter.constants import nwHeadFmt, nwHtmlUnicode, nwKeyWords, nwLabels
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt, stripEscape
|
||||
from novelwriter.formats.tokenizer import Tokenizer
|
||||
from novelwriter.types import FONT_STYLE, FONT_WEIGHTS
|
||||
from novelwriter.types import FONT_STYLE, FONT_WEIGHTS, QtHexRgb
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -354,16 +354,18 @@ class ToHtml(Tokenizer):
|
||||
return []
|
||||
|
||||
mScale = self._lineHeight/1.15
|
||||
tColor = self._theme.text.name(QtHexRgb)
|
||||
hColor = self._theme.head.name(QtHexRgb) if self._colorHeads else tColor
|
||||
|
||||
styles = []
|
||||
font = self._textFont
|
||||
styles.append((
|
||||
"body {{"
|
||||
"font-family: '{0:s}'; font-size: {1:d}pt; "
|
||||
"font-weight: {2:d}; font-style: {3:s};"
|
||||
"color: {0:s}; font-family: '{1:s}'; font-size: {2:d}pt; "
|
||||
"font-weight: {3:d}; font-style: {4:s};"
|
||||
"}}"
|
||||
).format(
|
||||
font.family(), font.pointSize(),
|
||||
tColor, font.family(), font.pointSize(),
|
||||
FONT_WEIGHTS.get(font.weight(), 400),
|
||||
FONT_STYLE.get(font.style(), "normal"),
|
||||
))
|
||||
@@ -380,43 +382,43 @@ class ToHtml(Tokenizer):
|
||||
))
|
||||
styles.append((
|
||||
"h1 {{"
|
||||
"color: rgb(66, 113, 174); "
|
||||
"color: {0:s}; "
|
||||
"page-break-after: avoid; "
|
||||
"margin-top: {0:.2f}em; "
|
||||
"margin-bottom: {1:.2f}em;"
|
||||
"margin-top: {1:.2f}em; "
|
||||
"margin-bottom: {2:.2f}em;"
|
||||
"}}"
|
||||
).format(
|
||||
mScale * self._marginHead1[0], mScale * self._marginHead1[1]
|
||||
hColor, mScale * self._marginHead1[0], mScale * self._marginHead1[1]
|
||||
))
|
||||
styles.append((
|
||||
"h2 {{"
|
||||
"color: rgb(66, 113, 174); "
|
||||
"color: {0:s}; "
|
||||
"page-break-after: avoid; "
|
||||
"margin-top: {0:.2f}em; "
|
||||
"margin-bottom: {1:.2f}em;"
|
||||
"margin-top: {1:.2f}em; "
|
||||
"margin-bottom: {2:.2f}em;"
|
||||
"}}"
|
||||
).format(
|
||||
mScale * self._marginHead2[0], mScale * self._marginHead2[1]
|
||||
hColor, mScale * self._marginHead2[0], mScale * self._marginHead2[1]
|
||||
))
|
||||
styles.append((
|
||||
"h3 {{"
|
||||
"color: rgb(50, 50, 50); "
|
||||
"color: {0:s}; "
|
||||
"page-break-after: avoid; "
|
||||
"margin-top: {0:.2f}em; "
|
||||
"margin-bottom: {1:.2f}em;"
|
||||
"margin-top: {1:.2f}em; "
|
||||
"margin-bottom: {2:.2f}em;"
|
||||
"}}"
|
||||
).format(
|
||||
mScale * self._marginHead3[0], mScale * self._marginHead3[1]
|
||||
hColor, mScale * self._marginHead3[0], mScale * self._marginHead3[1]
|
||||
))
|
||||
styles.append((
|
||||
"h4 {{"
|
||||
"color: rgb(50, 50, 50); "
|
||||
"color: {0:s}; "
|
||||
"page-break-after: avoid; "
|
||||
"margin-top: {0:.2f}em; "
|
||||
"margin-bottom: {1:.2f}em;"
|
||||
"margin-top: {1:.2f}em; "
|
||||
"margin-bottom: {2:.2f}em;"
|
||||
"}}"
|
||||
).format(
|
||||
mScale * self._marginHead4[0], mScale * self._marginHead4[1]
|
||||
hColor, mScale * self._marginHead4[0], mScale * self._marginHead4[1]
|
||||
))
|
||||
styles.append((
|
||||
".title {{"
|
||||
|
||||
@@ -44,7 +44,9 @@ from novelwriter.constants import (
|
||||
from novelwriter.core.index import processComment
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.enum import nwComment, nwItemLayout
|
||||
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Block, T_Formats, T_Note, TextFmt
|
||||
from novelwriter.formats.shared import (
|
||||
BlockFmt, BlockTyp, T_Block, T_Formats, T_Note, TextDocumentTheme, TextFmt
|
||||
)
|
||||
from novelwriter.text.patterns import REGEX_PATTERNS
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -110,6 +112,9 @@ class Tokenizer(ABC):
|
||||
self._keepBreaks = True # Keep line breaks in paragraphs
|
||||
self._defaultAlign = "left" # The default text alignment
|
||||
|
||||
# Other Setting
|
||||
self._theme = TextDocumentTheme()
|
||||
|
||||
# Margins
|
||||
self._marginTitle = nwStyles.T_MARGIN["H0"]
|
||||
self._marginHead1 = nwStyles.T_MARGIN["H1"]
|
||||
@@ -218,6 +223,11 @@ class Tokenizer(ABC):
|
||||
# Setters
|
||||
##
|
||||
|
||||
def setTheme(self, theme: TextDocumentTheme) -> None:
|
||||
"""Set the document colour theme."""
|
||||
self._theme = theme
|
||||
return
|
||||
|
||||
def setPartitionFormat(self, hFormat: str, hide: bool = False) -> None:
|
||||
"""Set the partition format pattern."""
|
||||
self._fmtPart = hFormat.strip()
|
||||
|
||||
@@ -35,7 +35,7 @@ from hashlib import sha256
|
||||
from pathlib import Path
|
||||
from zipfile import ZIP_DEFLATED, ZipFile
|
||||
|
||||
from PyQt5.QtGui import QFont
|
||||
from PyQt5.QtGui import QColor, QFont
|
||||
|
||||
from novelwriter import __version__
|
||||
from novelwriter.common import xmlIndent, xmlSubElem
|
||||
@@ -220,10 +220,6 @@ class ToOdt(Tokenizer):
|
||||
self._mDocRight = "2.000cm"
|
||||
|
||||
# Colour
|
||||
self._colHead12 = None
|
||||
self._opaHead12 = None
|
||||
self._colHead34 = None
|
||||
self._opaHead34 = None
|
||||
self._colDialogM = "#2a6099"
|
||||
self._colDialogA = "#813709"
|
||||
self._colMetaTx = "#813709"
|
||||
@@ -318,12 +314,6 @@ class ToOdt(Tokenizer):
|
||||
self._mLeftFoot = self._emToCm(self._marginFoot[0])
|
||||
self._mBotFoot = self._emToCm(self._marginFoot[1])
|
||||
|
||||
if self._colorHeads:
|
||||
self._colHead12 = "#2a6099"
|
||||
self._opaHead12 = "100%"
|
||||
self._colHead34 = "#444444"
|
||||
self._opaHead34 = "100%"
|
||||
|
||||
self._fLineHeight = f"{round(100 * self._lineHeight):d}%"
|
||||
self._fBlockIndent = self._emToCm(self._blockIndent)
|
||||
self._fTextIndent = self._emToCm(self._firstWidth)
|
||||
@@ -894,6 +884,8 @@ class ToOdt(Tokenizer):
|
||||
|
||||
def _useableStyles(self) -> None:
|
||||
"""Set the usable styles."""
|
||||
hColor = self._theme.head if self._colorHeads else None
|
||||
|
||||
# Add Text Body Style
|
||||
style = ODTParagraphStyle(S_TEXT)
|
||||
style.setDisplayName("Text body")
|
||||
@@ -931,8 +923,7 @@ class ToOdt(Tokenizer):
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeText)
|
||||
style.setFontWeight(self._fontWeight)
|
||||
style.setColour(self._colMetaTx)
|
||||
style.setOpacity(self._opaMetaTx)
|
||||
style.setColour(self._theme.note)
|
||||
style.packXML(self._xStyl)
|
||||
self._mainPara[style.name] = style
|
||||
|
||||
@@ -982,8 +973,7 @@ class ToOdt(Tokenizer):
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeHead1)
|
||||
style.setFontWeight(self._headWeight)
|
||||
style.setColour(self._colHead12)
|
||||
style.setOpacity(self._opaHead12)
|
||||
style.setColour(hColor)
|
||||
style.packXML(self._xStyl)
|
||||
self._mainPara[style.name] = style
|
||||
|
||||
@@ -1000,8 +990,7 @@ class ToOdt(Tokenizer):
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeHead2)
|
||||
style.setFontWeight(self._headWeight)
|
||||
style.setColour(self._colHead12)
|
||||
style.setOpacity(self._opaHead12)
|
||||
style.setColour(hColor)
|
||||
style.packXML(self._xStyl)
|
||||
self._mainPara[style.name] = style
|
||||
|
||||
@@ -1018,8 +1007,7 @@ class ToOdt(Tokenizer):
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeHead3)
|
||||
style.setFontWeight(self._headWeight)
|
||||
style.setColour(self._colHead34)
|
||||
style.setOpacity(self._opaHead34)
|
||||
style.setColour(hColor)
|
||||
style.packXML(self._xStyl)
|
||||
self._mainPara[style.name] = style
|
||||
|
||||
@@ -1036,8 +1024,7 @@ class ToOdt(Tokenizer):
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeHead4)
|
||||
style.setFontWeight(self._headWeight)
|
||||
style.setColour(self._colHead34)
|
||||
style.setOpacity(self._opaHead34)
|
||||
style.setColour(hColor)
|
||||
style.packXML(self._xStyl)
|
||||
self._mainPara[style.name] = style
|
||||
|
||||
@@ -1298,14 +1285,14 @@ class ODTParagraphStyle:
|
||||
self._tAttr["font-weight"][1] = None
|
||||
return
|
||||
|
||||
def setColour(self, value: str | None) -> None:
|
||||
def setColour(self, value: QColor | None) -> None:
|
||||
"""Set text colour."""
|
||||
self._tAttr["color"][1] = value
|
||||
return
|
||||
|
||||
def setOpacity(self, value: str | None) -> None:
|
||||
"""Set text opacity."""
|
||||
self._tAttr["opacity"][1] = value
|
||||
if isinstance(value, QColor):
|
||||
self._tAttr["color"][1] = value.name(QColor.NameFormat.HexRgb)
|
||||
self._tAttr["opacity"][1] = f"{int(100.0 * value.alphaF())}%"
|
||||
else:
|
||||
self._tAttr["color"][1] = None
|
||||
self._tAttr["opacity"][1] = None
|
||||
return
|
||||
|
||||
##
|
||||
|
||||
@@ -29,7 +29,7 @@ from pathlib import Path
|
||||
|
||||
from PyQt5.QtCore import QMarginsF, QSizeF
|
||||
from PyQt5.QtGui import (
|
||||
QColor, QFont, QFontMetricsF, QPageSize, QTextBlockFormat, QTextCharFormat,
|
||||
QFont, QFontMetricsF, QPageSize, QTextBlockFormat, QTextCharFormat,
|
||||
QTextCursor, QTextDocument
|
||||
)
|
||||
from PyQt5.QtPrintSupport import QPrinter
|
||||
@@ -49,21 +49,6 @@ logger = logging.getLogger(__name__)
|
||||
T_TextStyle = tuple[QTextBlockFormat, QTextCharFormat]
|
||||
|
||||
|
||||
class TextDocumentTheme:
|
||||
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:
|
||||
if cursor.position() > 0:
|
||||
cursor.insertBlock(bFmt)
|
||||
@@ -84,7 +69,6 @@ class ToQTextDocument(Tokenizer):
|
||||
self._document.setUndoRedoEnabled(False)
|
||||
self._document.setDocumentMargin(0)
|
||||
|
||||
self._theme = TextDocumentTheme()
|
||||
self._styles: dict[int, T_TextStyle] = {}
|
||||
self._usedNotes: dict[str, int] = {}
|
||||
|
||||
@@ -110,11 +94,6 @@ class ToQTextDocument(Tokenizer):
|
||||
# Setters
|
||||
##
|
||||
|
||||
def setTheme(self, theme: TextDocumentTheme) -> None:
|
||||
"""Set the document colour theme."""
|
||||
self._theme = theme
|
||||
return
|
||||
|
||||
def setPageLayout(
|
||||
self, width: float, height: float, top: float, bottom: float, left: float, right: float
|
||||
) -> None:
|
||||
|
||||
@@ -44,7 +44,8 @@ from novelwriter.error import logException
|
||||
from novelwriter.extensions.configlayout import NColourLabel
|
||||
from novelwriter.extensions.eventfilters import WheelEventFilter
|
||||
from novelwriter.extensions.modified import NIconToolButton
|
||||
from novelwriter.formats.toqdoc import TextDocumentTheme, ToQTextDocument
|
||||
from novelwriter.formats.shared import TextDocumentTheme
|
||||
from novelwriter.formats.toqdoc import ToQTextDocument
|
||||
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
|
||||
from novelwriter.types import (
|
||||
QtAlignCenterTop, QtKeepAnchor, QtMouseLeft, QtMoveAnchor,
|
||||
|
||||
@@ -65,6 +65,10 @@ QtPaintAnitAlias = QPainter.RenderHint.Antialiasing
|
||||
QtMouseOver = QStyle.StateFlag.State_MouseOver
|
||||
QtSelected = QStyle.StateFlag.State_Selected
|
||||
|
||||
# Qt Colour Types
|
||||
|
||||
QtHexRgb = QColor.NameFormat.HexRgb
|
||||
|
||||
# Qt Tree and Table Types
|
||||
|
||||
QtDecoration = Qt.ItemDataRole.DecorationRole
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</w:pPr>
|
||||
<w:rPr>
|
||||
<w:b />
|
||||
<w:color w:val="2a6099" />
|
||||
<w:color w:val="4271ae" />
|
||||
<w:sz w:val="48" />
|
||||
<w:szCs w:val="48" />
|
||||
</w:rPr>
|
||||
@@ -65,7 +65,7 @@
|
||||
</w:pPr>
|
||||
<w:rPr>
|
||||
<w:b />
|
||||
<w:color w:val="2a6099" />
|
||||
<w:color w:val="4271ae" />
|
||||
<w:sz w:val="42" />
|
||||
<w:szCs w:val="42" />
|
||||
</w:rPr>
|
||||
@@ -80,7 +80,7 @@
|
||||
</w:pPr>
|
||||
<w:rPr>
|
||||
<w:b />
|
||||
<w:color w:val="444444" />
|
||||
<w:color w:val="4271ae" />
|
||||
<w:sz w:val="36" />
|
||||
<w:szCs w:val="36" />
|
||||
</w:rPr>
|
||||
@@ -95,7 +95,7 @@
|
||||
</w:pPr>
|
||||
<w:rPr>
|
||||
<w:b />
|
||||
<w:color w:val="444444" />
|
||||
<w:color w:val="4271ae" />
|
||||
<w:sz w:val="30" />
|
||||
<w:szCs w:val="30" />
|
||||
</w:rPr>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<office:document xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:meta>
|
||||
<meta:creation-date>2024-10-17T22:22:08</meta:creation-date>
|
||||
<meta:creation-date>2024-10-22T11:39:53</meta:creation-date>
|
||||
<meta:generator>novelWriter/2.6a1</meta:generator>
|
||||
<meta:initial-creator>Jane Smith</meta:initial-creator>
|
||||
<meta:editing-cycles>1234</meta:editing-cycles>
|
||||
<meta:editing-duration>P42DT12H34M56S</meta:editing-duration>
|
||||
<dc:title>Test Project</dc:title>
|
||||
<dc:date>2024-10-17T22:22:08</dc:date>
|
||||
<dc:date>2024-10-22T11:39:53</dc:date>
|
||||
<dc:creator>Jane Smith</dc:creator>
|
||||
</office:meta>
|
||||
<office:font-face-decls>
|
||||
@@ -47,19 +47,19 @@
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:family="paragraph" style:display-name="Heading 1" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.601cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="24pt" fo:font-weight="bold" fo:color="#2a6099" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="24pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:family="paragraph" style:display-name="Heading 2" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.707cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="21pt" fo:font-weight="bold" fo:color="#2a6099" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="21pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:family="paragraph" style:display-name="Heading 3" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.495cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="18pt" fo:font-weight="bold" fo:color="#444444" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="18pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_4" style:family="paragraph" style:display-name="Heading 4" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="4" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.495cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="15pt" fo:font-weight="bold" fo:color="#444444" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="15pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Header" style:family="paragraph" style:display-name="Header" style:parent-style-name="Header_20_and_20_Footer">
|
||||
<style:paragraph-properties fo:text-align="right" />
|
||||
|
||||
@@ -37,19 +37,19 @@
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:family="paragraph" style:display-name="Heading 1" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.601cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="24pt" fo:font-weight="bold" fo:color="#2a6099" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="24pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:family="paragraph" style:display-name="Heading 2" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.707cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="21pt" fo:font-weight="bold" fo:color="#2a6099" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="21pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:family="paragraph" style:display-name="Heading 3" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.495cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="18pt" fo:font-weight="bold" fo:color="#444444" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="18pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_4" style:family="paragraph" style:display-name="Heading 4" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="4" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.495cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="15pt" fo:font-weight="bold" fo:color="#444444" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="15pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Header" style:family="paragraph" style:display-name="Header" style:parent-style-name="Header_20_and_20_Footer">
|
||||
<style:paragraph-properties fo:text-align="right" />
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
<title>Lorem Ipsum</title>
|
||||
</head>
|
||||
<style>
|
||||
body {font-family: 'Arial'; font-size: 12pt; font-weight: 400; font-style: normal;}
|
||||
body {color: #000000; font-family: 'Arial'; font-size: 12pt; font-weight: 400; font-style: normal;}
|
||||
p {text-align: left; line-height: 150%; margin-top: 0.00em; margin-bottom: 0.76em;}
|
||||
h1 {color: rgb(66, 113, 174); page-break-after: avoid; margin-top: 1.85em; margin-bottom: 0.65em;}
|
||||
h2 {color: rgb(66, 113, 174); page-break-after: avoid; margin-top: 2.18em; margin-bottom: 0.65em;}
|
||||
h3 {color: rgb(50, 50, 50); page-break-after: avoid; margin-top: 1.53em; margin-bottom: 0.65em;}
|
||||
h4 {color: rgb(50, 50, 50); page-break-after: avoid; margin-top: 1.53em; margin-bottom: 0.65em;}
|
||||
h1 {color: #4271ae; page-break-after: avoid; margin-top: 1.85em; margin-bottom: 0.65em;}
|
||||
h2 {color: #4271ae; page-break-after: avoid; margin-top: 2.18em; margin-bottom: 0.65em;}
|
||||
h3 {color: #4271ae; page-break-after: avoid; margin-top: 1.53em; margin-bottom: 0.65em;}
|
||||
h4 {color: #4271ae; page-break-after: avoid; margin-top: 1.53em; margin-bottom: 0.65em;}
|
||||
.title {font-size: 2.5em; margin-top: 1.85em; margin-bottom: 0.65em;}
|
||||
.sep, .skip {text-align: center; margin-top: 1.30em; margin-bottom: 1.30em;}
|
||||
a {color: rgb(66, 113, 174);}
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
"meta": {
|
||||
"projectName": "Lorem Ipsum",
|
||||
"novelAuthor": "lipsum.com",
|
||||
"buildTime": 1729529369,
|
||||
"buildTimeStr": "2024-10-21 18:49:29"
|
||||
"buildTime": 1729590078,
|
||||
"buildTimeStr": "2024-10-22 11:41:18"
|
||||
},
|
||||
"text": {
|
||||
"css": [
|
||||
"body {font-family: 'Arial'; font-size: 12pt; font-weight: 400; font-style: normal;}",
|
||||
"body {color: #000000; font-family: 'Arial'; font-size: 12pt; font-weight: 400; font-style: normal;}",
|
||||
"p {text-align: left; line-height: 150%; margin-top: 0.00em; margin-bottom: 0.76em;}",
|
||||
"h1 {color: rgb(66, 113, 174); page-break-after: avoid; margin-top: 1.85em; margin-bottom: 0.65em;}",
|
||||
"h2 {color: rgb(66, 113, 174); page-break-after: avoid; margin-top: 2.18em; margin-bottom: 0.65em;}",
|
||||
"h3 {color: rgb(50, 50, 50); page-break-after: avoid; margin-top: 1.53em; margin-bottom: 0.65em;}",
|
||||
"h4 {color: rgb(50, 50, 50); page-break-after: avoid; margin-top: 1.53em; margin-bottom: 0.65em;}",
|
||||
"h1 {color: #4271ae; page-break-after: avoid; margin-top: 1.85em; margin-bottom: 0.65em;}",
|
||||
"h2 {color: #4271ae; page-break-after: avoid; margin-top: 2.18em; margin-bottom: 0.65em;}",
|
||||
"h3 {color: #4271ae; page-break-after: avoid; margin-top: 1.53em; margin-bottom: 0.65em;}",
|
||||
"h4 {color: #4271ae; page-break-after: avoid; margin-top: 1.53em; margin-bottom: 0.65em;}",
|
||||
".title {font-size: 2.5em; margin-top: 1.85em; margin-bottom: 0.65em;}",
|
||||
".sep, .skip {text-align: center; margin-top: 1.30em; margin-bottom: 1.30em;}",
|
||||
"a {color: rgb(66, 113, 174);}",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<office:document xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:meta>
|
||||
<meta:creation-date>2024-10-21T18:49:29</meta:creation-date>
|
||||
<meta:creation-date>2024-10-22T11:39:52</meta:creation-date>
|
||||
<meta:generator>novelWriter/2.6a1</meta:generator>
|
||||
<meta:initial-creator>lipsum.com</meta:initial-creator>
|
||||
<meta:editing-cycles>45</meta:editing-cycles>
|
||||
<meta:editing-duration>P0DT0H36M8S</meta:editing-duration>
|
||||
<dc:title>Lorem Ipsum</dc:title>
|
||||
<dc:date>2024-10-21T18:49:29</dc:date>
|
||||
<dc:date>2024-10-22T11:39:52</dc:date>
|
||||
<dc:creator>lipsum.com</dc:creator>
|
||||
</office:meta>
|
||||
<office:font-face-decls>
|
||||
@@ -47,19 +47,19 @@
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:family="paragraph" style:display-name="Heading 1" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.784cm" fo:margin-bottom="0.276cm" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="24pt" fo:font-weight="bold" fo:color="#2a6099" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="24pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:family="paragraph" style:display-name="Heading 2" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.922cm" fo:margin-bottom="0.276cm" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="21pt" fo:font-weight="bold" fo:color="#2a6099" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="21pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:family="paragraph" style:display-name="Heading 3" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.646cm" fo:margin-bottom="0.276cm" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="18pt" fo:font-weight="bold" fo:color="#444444" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="18pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_4" style:family="paragraph" style:display-name="Heading 4" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="4" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.646cm" fo:margin-bottom="0.276cm" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="15pt" fo:font-weight="bold" fo:color="#444444" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="15pt" fo:font-weight="bold" fo:color="#4271ae" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Header" style:family="paragraph" style:display-name="Header" style:parent-style-name="Header_20_and_20_Footer">
|
||||
<style:paragraph-properties fo:text-align="right" />
|
||||
|
||||
@@ -27,6 +27,8 @@ from shutil import copyfile
|
||||
|
||||
import pytest
|
||||
|
||||
from PyQt5.QtGui import QColor
|
||||
|
||||
from novelwriter.common import xmlIndent
|
||||
from novelwriter.constants import nwHeadFmt
|
||||
from novelwriter.core.project import NWProject
|
||||
@@ -1106,11 +1108,15 @@ def testFmtToOdt_ODTParagraphStyle():
|
||||
assert parStyle._tAttr["color"] == ["fo", None]
|
||||
assert parStyle._tAttr["opacity"] == ["loext", None]
|
||||
|
||||
parStyle.setColour("#000000")
|
||||
parStyle.setOpacity("1.00")
|
||||
parStyle.setColour(QColor(0, 0, 0, 128))
|
||||
|
||||
assert parStyle._tAttr["color"] == ["fo", "#000000"]
|
||||
assert parStyle._tAttr["opacity"] == ["loext", "1.00"]
|
||||
assert parStyle._tAttr["opacity"] == ["loext", "50%"]
|
||||
|
||||
parStyle.setColour(None)
|
||||
|
||||
assert parStyle._tAttr["color"] == ["fo", None]
|
||||
assert parStyle._tAttr["opacity"] == ["loext", None]
|
||||
|
||||
# Pack XML
|
||||
# ========
|
||||
@@ -1124,7 +1130,7 @@ def testFmtToOdt_ODTParagraphStyle():
|
||||
'fo:margin-left="0.000cm" fo:margin-right="0.000cm" fo:text-indent="0.000cm" '
|
||||
'fo:line-height="1.15" />'
|
||||
'<style:text-properties style:font-name="Verdana" fo:font-family="Verdana" '
|
||||
'fo:font-size="12pt" fo:color="#000000" loext:opacity="1.00" />'
|
||||
'fo:font-size="12pt" />'
|
||||
'</style:style>'
|
||||
'</test>'
|
||||
)
|
||||
@@ -1151,8 +1157,8 @@ def testFmtToOdt_ODTParagraphStyle():
|
||||
|
||||
aStyle = ODTParagraphStyle("test")
|
||||
oStyle = ODTParagraphStyle("test")
|
||||
aStyle.setColour("#000000")
|
||||
oStyle.setColour("#111111")
|
||||
aStyle.setColour(QColor(0, 0, 0))
|
||||
oStyle.setColour(QColor(42, 42, 42))
|
||||
assert aStyle.checkNew(oStyle) is True
|
||||
assert aStyle.getID() != oStyle.getID()
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ from PyQt5.QtGui import QTextBlock, QTextCharFormat, QTextCursor
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.constants import nwUnicode
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.formats.shared import BlockFmt, BlockTyp
|
||||
from novelwriter.formats.toqdoc import TextDocumentTheme, ToQTextDocument
|
||||
from novelwriter.formats.shared import BlockFmt, BlockTyp, TextDocumentTheme
|
||||
from novelwriter.formats.toqdoc import ToQTextDocument
|
||||
from novelwriter.types import (
|
||||
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight,
|
||||
QtPageBreakAfter, QtTransparent, QtVAlignNormal, QtVAlignSub, QtVAlignSuper
|
||||
|
||||
Reference in New Issue
Block a user