Move colour theme to Tokenizer class

This commit is contained in:
Veronica Berglyd Olsen
2024-10-22 17:07:57 +02:00
parent 2d8664b3ce
commit e759aa8d1b
16 changed files with 132 additions and 119 deletions
+19
View File
@@ -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
# =====
+12 -7
View File
@@ -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,
))
+22 -20
View File
@@ -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 {{"
+11 -1
View File
@@ -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()
+15 -28
View File
@@ -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
##
+1 -22
View File
@@ -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: