Process comments in the Tokenizer

This commit is contained in:
Veronica Berglyd Olsen
2024-10-22 17:37:00 +02:00
parent e759aa8d1b
commit c537d0f396
17 changed files with 392 additions and 334 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
"Short Description": "Short Description",
"Footnotes": "Footnotes",
"Comment": "Comment",
"Notes": "Notes",
"Note": "Note",
"Tag": "Tag",
"Point of View": "Point of View",
"Focus": "Focus",
+21 -19
View File
@@ -84,12 +84,14 @@ class TextFmt(IntEnum):
SUP_E = 12 # End superscript
SUB_B = 13 # Begin subscript
SUB_E = 14 # End subscript
DL_B = 15 # Begin dialogue
DL_E = 16 # End dialogue
ADL_B = 17 # Begin alt dialogue
ADL_E = 18 # End alt dialogue
FNOTE = 19 # Footnote marker
STRIP = 20 # Strip the format code
COL_B = 15 # Begin colour
COL_E = 16 # End colour
DL_B = 17 # Begin dialogue
DL_E = 18 # End dialogue
ADL_B = 19 # Begin alt dialogue
ADL_E = 20 # End alt dialogue
FNOTE = 21 # Footnote marker
STRIP = 22 # Strip the format code
class BlockTyp(IntEnum):
@@ -98,19 +100,19 @@ class BlockTyp(IntEnum):
An enum indicating the type of a text block.
"""
EMPTY = 1 # Empty line (new paragraph)
SYNOPSIS = 2 # Synopsis comment
SHORT = 3 # Short description comment
COMMENT = 4 # Comment line
KEYWORD = 5 # Command line
TITLE = 6 # Title
HEAD1 = 7 # Heading 1
HEAD2 = 8 # Heading 2
HEAD3 = 9 # Heading 3
HEAD4 = 10 # Heading 4
TEXT = 11 # Text line
SEP = 12 # Scene separator
SKIP = 13 # Paragraph break
EMPTY = 1 # Empty line (new paragraph)
TITLE = 2 # Title
HEAD1 = 3 # Heading 1
HEAD2 = 4 # Heading 2
HEAD3 = 5 # Heading 3
HEAD4 = 6 # Heading 4
TEXT = 7 # Text line
SEP = 8 # Scene separator
SKIP = 9 # Paragraph break
SUMMARY = 10 # Synopsis/short comment
NOTE = 11 # Note
COMMENT = 12 # Comment
KEYWORD = 13 # Tag/reference keywords
class BlockFmt(Flag):
+28 -44
View File
@@ -95,8 +95,9 @@ X_UND = 0x008 # Underline format
X_MRK = 0x010 # Marked format
X_SUP = 0x020 # Superscript
X_SUB = 0x040 # Subscript
X_DLG = 0x080 # Dialogue
X_DLA = 0x100 # Alt. Dialogue
X_COL = 0x080 # Coloured text
X_DLG = 0x100 # Dialogue
X_DLA = 0x200 # Alt. Dialogue
# Formatting Masks
M_BLD = ~X_BLD
@@ -106,6 +107,7 @@ M_UND = ~X_UND
M_MRK = ~X_MRK
M_SUP = ~X_SUP
M_SUB = ~X_SUB
M_COL = ~X_COL
M_DLG = ~X_DLG
M_DLA = ~X_DLA
@@ -214,6 +216,7 @@ class ToDocX(Tokenizer):
def initDocument(self) -> None:
"""Initialises the DocX document structure."""
super().initDocument()
self._fontFamily = self._textFont.family()
self._fontSize = self._textFont.pointSizeF()
self._generateStyles()
@@ -289,17 +292,8 @@ class ToDocX(Tokenizer):
elif tType == BlockTyp.SKIP:
self._processFragments(par, S_NORM, "")
elif tType == BlockTyp.SYNOPSIS and self._doSynopsis:
tTemp, tFmt = self._formatSynopsis(tText, tFormat, True)
self._processFragments(par, S_META, tTemp, tFmt)
elif tType == BlockTyp.SHORT and self._doSynopsis:
tTemp, tFmt = self._formatSynopsis(tText, tFormat, False)
self._processFragments(par, S_META, tTemp, tFmt)
elif tType == BlockTyp.COMMENT and self._doComments:
tTemp, tFmt = self._formatComments(tText, tFormat)
self._processFragments(par, S_META, tTemp, tFmt)
elif tType in self.L_NOTES:
self._processFragments(par, S_META, tText, tFormat)
elif tType == BlockTyp.KEYWORD and self._doKeywords:
tTemp, tFmt = self._formatKeywords(tText)
@@ -379,24 +373,6 @@ class ToDocX(Tokenizer):
# Internal Functions
##
def _formatSynopsis(self, text: str, fmt: T_Formats, synopsis: bool) -> tuple[str, T_Formats]:
"""Apply formatting to synopsis lines."""
name = self._localLookup("Synopsis" if synopsis else "Short Description")
shift = len(name) + 2
rTxt = f"{name}: {text}"
rFmt: T_Formats = [(0, TextFmt.B_B, ""), (len(name) + 1, TextFmt.B_E, "")]
rFmt.extend((p + shift, f, d) for p, f, d in fmt)
return rTxt, rFmt
def _formatComments(self, text: str, fmt: T_Formats) -> tuple[str, T_Formats]:
"""Apply formatting to comments."""
name = self._localLookup("Comment")
shift = len(name) + 2
rTxt = f"{name}: {text}"
rFmt: T_Formats = [(0, TextFmt.B_B, ""), (len(name) + 1, TextFmt.B_E, "")]
rFmt.extend((p + shift, f, d) for p, f, d in fmt)
return rTxt, rFmt
def _formatKeywords(self, text: str) -> tuple[str, T_Formats]:
"""Apply formatting to keywords."""
valid, bits, _ = self._project.index.scanThis("@"+text)
@@ -421,6 +397,7 @@ class ToDocX(Tokenizer):
xFmt = 0x00
xNode = None
fStart = 0
fClass = ""
for fPos, fFmt, fData in tFmt or []:
if xNode is not None:
@@ -428,7 +405,7 @@ class ToDocX(Tokenizer):
xNode = None
if temp := text[fStart:fPos]:
par.addContent(self._textRunToXml(temp, xFmt))
par.addContent(self._textRunToXml(temp, xFmt, fClass))
if fFmt == TextFmt.B_B:
xFmt |= X_BLD
@@ -458,6 +435,12 @@ class ToDocX(Tokenizer):
xFmt |= X_SUB
elif fFmt == TextFmt.SUB_E:
xFmt &= M_SUB
elif fFmt == TextFmt.COL_B:
xFmt |= X_COL
fClass = fData
elif fFmt == TextFmt.COL_E:
xFmt &= M_COL
fClass = ""
elif fFmt == TextFmt.DL_B:
xFmt |= X_DLG
elif fFmt == TextFmt.DL_E:
@@ -478,33 +461,35 @@ class ToDocX(Tokenizer):
par.addContent(xNode)
if temp := text[fStart:]:
par.addContent(self._textRunToXml(temp, xFmt))
par.addContent(self._textRunToXml(temp, xFmt, fClass))
return
def _textRunToXml(self, text: str, fmt: int) -> ET.Element:
def _textRunToXml(self, text: str, fmt: int, fClass: str = "") -> ET.Element:
"""Encode the text run into XML."""
run = ET.Element(_wTag("r"))
rPr = xmlSubElem(run, _wTag("rPr"))
if fmt & X_BLD == X_BLD:
if fmt & X_BLD:
xmlSubElem(rPr, _wTag("b"))
if fmt & X_ITA == X_ITA:
if fmt & X_ITA:
xmlSubElem(rPr, _wTag("i"))
if fmt & X_UND == X_UND:
if fmt & X_UND:
xmlSubElem(rPr, _wTag("u"), attrib={_wTag("val"): "single"})
if fmt & X_MRK == X_MRK:
if fmt & X_MRK:
xmlSubElem(rPr, _wTag("shd"), attrib={
_wTag("fill"): COL_MARK_TXT, _wTag("val"): "clear",
})
if fmt & X_DEL == X_DEL:
if fmt & X_DEL:
xmlSubElem(rPr, _wTag("strike"))
if fmt & X_SUP == X_SUP:
if fmt & X_SUP:
xmlSubElem(rPr, _wTag("vertAlign"), attrib={_wTag("val"): "superscript"})
if fmt & X_SUB == X_SUB:
if fmt & X_SUB:
xmlSubElem(rPr, _wTag("vertAlign"), attrib={_wTag("val"): "subscript"})
if fmt & X_DLG == X_DLG:
if fmt & X_COL and (color := self._classes.get(fClass)):
xmlSubElem(rPr, _wTag("color"), attrib={_wTag("val"): _docXCol(color)})
if fmt & X_DLG:
xmlSubElem(rPr, _wTag("color"), attrib={_wTag("val"): COL_DIALOG_M})
if fmt & X_DLA == X_DLA:
if fmt & X_DLA:
xmlSubElem(rPr, _wTag("color"), attrib={_wTag("val"): COL_DIALOG_A})
for segment in RX_TEXT.split(text):
@@ -659,7 +644,6 @@ class ToDocX(Tokenizer):
before=fSz * self._marginMeta[0],
after=fSz * self._marginMeta[1],
line=fSz * self._lineHeight,
color=COL_META_TXT,
))
# Header
+3 -19
View File
@@ -251,14 +251,11 @@ class ToHtml(Tokenizer):
elif tType == BlockTyp.SKIP:
lines.append(f"<p class='skip'{hStyle}>&nbsp;</p>\n")
elif tType == BlockTyp.SYNOPSIS and self._doSynopsis:
lines.append(self._formatSynopsis(self._formatText(tText, tFormat), True))
elif tType == BlockTyp.SHORT and self._doSynopsis:
lines.append(self._formatSynopsis(self._formatText(tText, tFormat), False))
elif tType == BlockTyp.SUMMARY:
lines.append(f"<p class='synopsis'>{self._formatText(tText, tFormat)}</p>\n")
elif tType == BlockTyp.COMMENT and self._doComments:
lines.append(self._formatComments(self._formatText(tText, tFormat)))
lines.append(f"<p class='comment'>{self._formatText(tText, tFormat)}</p>\n")
elif tType == BlockTyp.KEYWORD and self._doKeywords:
tag, text = self._formatKeywords(tText)
@@ -499,19 +496,6 @@ class ToHtml(Tokenizer):
return stripEscape(temp)
def _formatSynopsis(self, text: str, synopsis: bool) -> str:
"""Apply HTML formatting to synopsis."""
if synopsis:
sSynop = self._localLookup("Synopsis")
else:
sSynop = self._localLookup("Short Description")
return f"<p class='synopsis'><strong>{sSynop}:</strong> {text}</p>\n"
def _formatComments(self, text: str) -> str:
"""Apply HTML formatting to comments."""
sComm = self._localLookup("Comment")
return f"<p class='comment'><strong>{sComm}:</strong> {text}</p>\n"
def _formatKeywords(self, text: str) -> tuple[str, str]:
"""Apply HTML formatting to keywords."""
valid, bits, _ = self._project.index.scanThis("@"+text)
+62 -40
View File
@@ -32,9 +32,10 @@ from abc import ABC, abstractmethod
from functools import partial
from pathlib import Path
from time import time
from typing import NamedTuple
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QFont
from PyQt5.QtGui import QColor, QFont
from novelwriter import CONFIG
from novelwriter.common import checkInt, formatTimeStamp, numberToRoman
@@ -52,6 +53,26 @@ from novelwriter.text.patterns import REGEX_PATTERNS
logger = logging.getLogger(__name__)
class ComStyle(NamedTuple):
label: str = ""
labelClass: str = ""
textClass: str = ""
blockType: BlockTyp = BlockTyp.TEXT
COMMENT_STYLE = {
nwComment.PLAIN: ComStyle("Comment", "comment", "comment", BlockTyp.COMMENT),
nwComment.IGNORE: ComStyle(),
nwComment.SYNOPSIS: ComStyle("Synopsis", "modifier", "synopsis", BlockTyp.SUMMARY),
nwComment.SHORT: ComStyle("Short Description", "modifier", "synopsis", BlockTyp.SUMMARY),
nwComment.NOTE: ComStyle("Note", "modifier", "note", BlockTyp.NOTE),
nwComment.FOOTNOTE: ComStyle("", "modifier", "note"),
nwComment.COMMENT: ComStyle(),
nwComment.STORY: ComStyle("", "modifier", "note", BlockTyp.NOTE),
}
class Tokenizer(ABC):
"""Core: Text Tokenizer Abstract Base Class
@@ -72,7 +93,7 @@ class Tokenizer(ABC):
BlockTyp.TITLE, BlockTyp.HEAD1, BlockTyp.HEAD2, BlockTyp.HEAD2, BlockTyp.HEAD3,
BlockTyp.HEAD4, BlockTyp.SEP, BlockTyp.SKIP,
]
L_SUMMARY = [BlockTyp.SYNOPSIS, BlockTyp.SHORT]
L_NOTES = [BlockTyp.SUMMARY, BlockTyp.NOTE, BlockTyp.COMMENT]
def __init__(self, project: NWProject) -> None:
@@ -114,6 +135,7 @@ class Tokenizer(ABC):
# Other Setting
self._theme = TextDocumentTheme()
self._classes: dict[str, QColor] = {}
# Margins
self._marginTitle = nwStyles.T_MARGIN["H0"]
@@ -433,6 +455,13 @@ class Tokenizer(ABC):
def saveDocument(self, path: Path) -> None:
raise NotImplementedError
def initDocument(self) -> None:
"""Initialise data after settings."""
self._classes["modifier"] = self._theme.modifier
self._classes["synopsis"] = self._theme.note
self._classes["comment"] = self._theme.comment
return
def addRootHeading(self, tHandle: str) -> None:
"""Add a heading at the start of a new root folder."""
self._text = ""
@@ -569,36 +598,29 @@ class Tokenizer(ABC):
if aLine.startswith("%~"):
continue
cStyle, cKey, cText, _, _ = processComment(aLine)
if cStyle in (nwComment.SYNOPSIS, nwComment.SHORT) and not self._doSynopsis:
continue
if cStyle == nwComment.PLAIN and not self._doComments:
continue
if self._doJustify and not sAlign & self.M_ALIGNED:
sAlign |= BlockFmt.JUSTIFY
cStyle, cKey, cText, _, _ = processComment(aLine)
if cStyle == nwComment.SYNOPSIS:
tLine, tFmt = self._extractFormats(cText)
blocks.append((
BlockTyp.SYNOPSIS, nHead, tLine, tFmt, sAlign
))
if self._doSynopsis and self._keepRaw:
tmpMarkdown.append(f"{aLine}\n")
elif cStyle == nwComment.SHORT:
tLine, tFmt = self._extractFormats(cText)
blocks.append((
BlockTyp.SHORT, nHead, tLine, tFmt, sAlign
))
if self._doSynopsis and self._keepRaw:
if cStyle in (nwComment.SYNOPSIS, nwComment.SHORT, nwComment.PLAIN):
bStyle = COMMENT_STYLE[cStyle]
tLine, tFmt = self._formatNote(bStyle, cKey, cText)
blocks.append((bStyle.blockType, nHead, tLine, tFmt, sAlign))
if self._keepRaw:
tmpMarkdown.append(f"{aLine}\n")
elif cStyle == nwComment.FOOTNOTE:
tLine, tFmt = self._extractFormats(cText, skip=TextFmt.FNOTE)
self._footnotes[f"{tHandle}:{cKey}"] = (tLine, tFmt)
if self._keepRaw:
tmpMarkdown.append(f"{aLine}\n")
else:
tLine, tFmt = self._extractFormats(cText)
blocks.append((
BlockTyp.COMMENT, nHead, tLine, tFmt, sAlign
))
if self._doComments and self._keepRaw:
tmpMarkdown.append(f"{aLine}\n")
continue
elif aLine.startswith("@"):
# Keywords
@@ -992,25 +1014,10 @@ class Tokenizer(ABC):
allChars += nChars
allWordChars += nWChars
elif tType == BlockTyp.SYNOPSIS and self._doSynopsis:
text = "{0}: {1}".format(self._localLookup("Synopsis"), tText)
words = text.split()
elif tType in self.L_NOTES:
words = tText.split()
allWords += len(words)
allChars += len(text)
allWordChars += len("".join(words))
elif tType == BlockTyp.SHORT and self._doSynopsis:
text = "{0}: {1}".format(self._localLookup("Short Description"), tText)
words = text.split()
allWords += len(words)
allChars += len(text)
allWordChars += len("".join(words))
elif tType == BlockTyp.COMMENT and self._doComments:
text = "{0}: {1}".format(self._localLookup("Comment"), tText)
words = text.split()
allWords += len(words)
allChars += len(text)
allChars += len(tText)
allWordChars += len("".join(words))
elif tType == BlockTyp.KEYWORD and self._doKeywords:
@@ -1071,6 +1078,21 @@ class Tokenizer(ABC):
# Internal Functions
##
def _formatNote(self, style: ComStyle, key: str, text: str) -> tuple[str, T_Formats]:
"""Apply formatting to comments and notes."""
tTxt, tFmt = self._extractFormats(text)
tFmt.insert(0, (0, TextFmt.COL_B, style.textClass))
tFmt.append((len(tTxt), TextFmt.COL_E, ""))
if label := (self._localLookup(style.label) + (f" ({key})" if key else "")).strip():
shift = len(label) + 2
tTxt = f"{label}: {tTxt}"
rFmt = [(0, TextFmt.B_B, ""), (shift - 1, TextFmt.B_E, "")]
if style.labelClass:
rFmt.insert(1, (0, TextFmt.COL_B, style.labelClass))
rFmt.append((shift - 1, TextFmt.COL_E, ""))
rFmt.extend((p + shift, f, d) for p, f, d in tFmt)
return tTxt, rFmt
def _extractFormats(
self, text: str, skip: int = 0, hDialog: bool = False
) -> tuple[str, T_Formats]:
+2 -11
View File
@@ -150,17 +150,8 @@ class ToMarkdown(Tokenizer):
elif tType == BlockTyp.SKIP:
lines.append(f"{cSkip}\n\n")
elif tType == BlockTyp.SYNOPSIS and self._doSynopsis:
label = self._localLookup("Synopsis")
lines.append(f"**{label}:** {self._formatText(tText, tFormat, mTags)}\n\n")
elif tType == BlockTyp.SHORT and self._doSynopsis:
label = self._localLookup("Short Description")
lines.append(f"**{label}:** {self._formatText(tText, tFormat, mTags)}\n\n")
elif tType == BlockTyp.COMMENT and self._doComments:
label = self._localLookup("Comment")
lines.append(f"**{label}:** {self._formatText(tText, tFormat, mTags)}\n\n")
elif tType in self.L_NOTES:
lines.append(f"{self._formatText(tText, tFormat, mTags)}\n\n")
elif tType == BlockTyp.KEYWORD and self._doKeywords:
lines.append(self._formatKeywords(tText, tStyle))
+44 -55
View File
@@ -90,8 +90,9 @@ X_UND = 0x008 # Underline format
X_MRK = 0x010 # Marked format
X_SUP = 0x020 # Superscript
X_SUB = 0x040 # Subscript
X_DLG = 0x080 # Dialogue
X_DLA = 0x100 # Alt. Dialogue
X_COL = 0x080 # Coloured text
X_DLG = 0x100 # Dialogue
X_DLA = 0x200 # Alt. Dialogue
# Formatting Masks
M_BLD = ~X_BLD
@@ -101,6 +102,7 @@ M_UND = ~X_UND
M_MRK = ~X_MRK
M_SUP = ~X_SUP
M_SUB = ~X_SUB
M_COL = ~X_COL
M_DLG = ~X_DLG
M_DLA = ~X_DLA
@@ -152,7 +154,7 @@ class ToOdt(Tokenizer):
self._mainPara: dict[str, ODTParagraphStyle] = {} # User-accessible paragraph styles
self._autoPara: dict[str, ODTParagraphStyle] = {} # Auto-generated paragraph styles
self._autoText: dict[int, ODTTextStyle] = {} # Auto-generated text styles
self._autoText: dict[str, ODTTextStyle] = {} # Auto-generated text styles
# Footnotes
self._nNote = 0
@@ -264,6 +266,8 @@ class ToOdt(Tokenizer):
def initDocument(self) -> None:
"""Initialises a new open document XML tree."""
super().initDocument()
# Initialise Variables
# ====================
@@ -480,17 +484,8 @@ class ToOdt(Tokenizer):
elif tType == BlockTyp.SKIP:
self._addTextPar(xText, S_TEXT, oStyle, "")
elif tType == BlockTyp.SYNOPSIS and self._doSynopsis:
tTemp, tFmt = self._formatSynopsis(tText, tFormat, True)
self._addTextPar(xText, S_META, oStyle, tTemp, tFmt=tFmt)
elif tType == BlockTyp.SHORT and self._doSynopsis:
tTemp, tFmt = self._formatSynopsis(tText, tFormat, False)
self._addTextPar(xText, S_META, oStyle, tTemp, tFmt=tFmt)
elif tType == BlockTyp.COMMENT and self._doComments:
tTemp, tFmt = self._formatComments(tText, tFormat)
self._addTextPar(xText, S_META, oStyle, tTemp, tFmt=tFmt)
elif tType in self.L_NOTES:
self._addTextPar(xText, S_META, oStyle, tText, tFmt=tFormat)
elif tType == BlockTyp.KEYWORD and self._doKeywords:
tTemp, tFmt = self._formatKeywords(tText)
@@ -562,24 +557,6 @@ class ToOdt(Tokenizer):
# Internal Functions
##
def _formatSynopsis(self, text: str, fmt: T_Formats, synopsis: bool) -> tuple[str, T_Formats]:
"""Apply formatting to synopsis lines."""
name = self._localLookup("Synopsis" if synopsis else "Short Description")
shift = len(name) + 2
rTxt = f"{name}: {text}"
rFmt: T_Formats = [(0, TextFmt.B_B, ""), (len(name) + 1, TextFmt.B_E, "")]
rFmt.extend((p + shift, f, d) for p, f, d in fmt)
return rTxt, rFmt
def _formatComments(self, text: str, fmt: T_Formats) -> tuple[str, T_Formats]:
"""Apply formatting to comments."""
name = self._localLookup("Comment")
shift = len(name) + 2
rTxt = f"{name}: {text}"
rFmt: T_Formats = [(0, TextFmt.B_B, ""), (len(name) + 1, TextFmt.B_E, "")]
rFmt.extend((p + shift, f, d) for p, f, d in fmt)
return rTxt, rFmt
def _formatKeywords(self, text: str) -> tuple[str, T_Formats]:
"""Apply formatting to keywords."""
valid, bits, _ = self._project.index.scanThis("@"+text)
@@ -630,6 +607,7 @@ class ToOdt(Tokenizer):
tFrag = ""
fLast = 0
xNode = None
fClass = ""
for fPos, fFmt, fData in tFmt or []:
# Add any extra nodes
@@ -642,7 +620,7 @@ class ToOdt(Tokenizer):
if xFmt == 0x00:
parProc.appendText(tFrag)
else:
parProc.appendSpan(tFrag, self._textStyle(xFmt))
parProc.appendSpan(tFrag, self._textStyle(xFmt, fClass))
# Calculate the change of format
if fFmt == TextFmt.B_B:
@@ -673,6 +651,12 @@ class ToOdt(Tokenizer):
xFmt |= X_SUB
elif fFmt == TextFmt.SUB_E:
xFmt &= M_SUB
elif fFmt == TextFmt.COL_B:
xFmt |= X_COL
fClass = fData
elif fFmt == TextFmt.COL_E:
xFmt &= M_COL
fClass = ""
elif fFmt == TextFmt.DL_B:
xFmt |= X_DLG
elif fFmt == TextFmt.DL_E:
@@ -697,7 +681,7 @@ class ToOdt(Tokenizer):
if xFmt == 0x00:
parProc.appendText(tFrag)
else:
parProc.appendSpan(tFrag, self._textStyle(xFmt))
parProc.appendSpan(tFrag, self._textStyle(xFmt, fClass))
if pErr > 0:
self._errData.append("Unknown format tag encountered")
@@ -731,10 +715,14 @@ class ToOdt(Tokenizer):
return modStyle.name
def _textStyle(self, hFmt: int) -> str:
def _textStyle(self, hFmt: int, fClass: str = "") -> str:
"""Return a text style for a given style code."""
if hFmt in self._autoText:
return self._autoText[hFmt].name
tKey = str(hFmt)
if fClass and (color := self._classes.get(fClass)):
tKey = f"{tKey}:{fClass}"
if tKey in self._autoText:
return self._autoText[tKey].name
style = ODTTextStyle(f"T{len(self._autoText)+1:d}")
if hFmt & X_BLD:
@@ -747,18 +735,20 @@ class ToOdt(Tokenizer):
if hFmt & X_UND:
style.setUnderlineStyle("solid")
style.setUnderlineWidth("auto")
style.setUnderlineColour("font-color")
style.setUnderlineColor("font-color")
if hFmt & X_MRK:
style.setBackgroundColour(self._markText)
style.setBackgroundColor(self._markText)
if hFmt & X_SUP:
style.setTextPosition("super")
if hFmt & X_SUB:
style.setTextPosition("sub")
if hFmt & X_DLG:
style.setColour(self._colDialogM)
if hFmt & X_DLA:
style.setColour(self._colDialogA)
self._autoText[hFmt] = style
if hFmt & X_COL and color:
style.setColor(color)
# if hFmt & X_DLG:
# style.setColour(self._colDialogM)
# if hFmt & X_DLA:
# style.setColour(self._colDialogA)
self._autoText[tKey] = style
return style.name
@@ -923,7 +913,6 @@ class ToOdt(Tokenizer):
style.setFontFamily(self._fontFamily)
style.setFontSize(self._fSizeText)
style.setFontWeight(self._fontWeight)
style.setColour(self._theme.note)
style.packXML(self._xStyl)
self._mainPara[style.name] = style
@@ -973,7 +962,7 @@ class ToOdt(Tokenizer):
style.setFontFamily(self._fontFamily)
style.setFontSize(self._fSizeHead1)
style.setFontWeight(self._headWeight)
style.setColour(hColor)
style.setColor(hColor)
style.packXML(self._xStyl)
self._mainPara[style.name] = style
@@ -990,7 +979,7 @@ class ToOdt(Tokenizer):
style.setFontFamily(self._fontFamily)
style.setFontSize(self._fSizeHead2)
style.setFontWeight(self._headWeight)
style.setColour(hColor)
style.setColor(hColor)
style.packXML(self._xStyl)
self._mainPara[style.name] = style
@@ -1007,7 +996,7 @@ class ToOdt(Tokenizer):
style.setFontFamily(self._fontFamily)
style.setFontSize(self._fSizeHead3)
style.setFontWeight(self._headWeight)
style.setColour(hColor)
style.setColor(hColor)
style.packXML(self._xStyl)
self._mainPara[style.name] = style
@@ -1024,7 +1013,7 @@ class ToOdt(Tokenizer):
style.setFontFamily(self._fontFamily)
style.setFontSize(self._fSizeHead4)
style.setFontWeight(self._headWeight)
style.setColour(hColor)
style.setColor(hColor)
style.packXML(self._xStyl)
self._mainPara[style.name] = style
@@ -1285,7 +1274,7 @@ class ODTParagraphStyle:
self._tAttr["font-weight"][1] = None
return
def setColour(self, value: QColor | None) -> None:
def setColor(self, value: QColor | None) -> None:
"""Set text colour."""
if isinstance(value, QColor):
self._tAttr["color"][1] = value.name(QColor.NameFormat.HexRgb)
@@ -1393,15 +1382,15 @@ class ODTTextStyle:
self._tAttr["font-style"][1] = None
return
def setColour(self, value: str | None) -> None:
def setColor(self, value: QColor | None) -> None:
"""Set text colour."""
if value and len(value) == 7 and value[0] == "#":
self._tAttr["color"][1] = value
if isinstance(value, QColor):
self._tAttr["color"][1] = value.name(QColor.NameFormat.HexRgb)
else:
self._tAttr["color"][1] = None
return
def setBackgroundColour(self, value: str | None) -> None:
def setBackgroundColor(self, value: str | None) -> None:
"""Set text background colour."""
if value and len(value) == 7 and value[0] == "#":
self._tAttr["background-color"][1] = value
@@ -1449,7 +1438,7 @@ class ODTTextStyle:
self._tAttr["text-underline-width"][1] = None
return
def setUnderlineColour(self, value: str | None) -> None:
def setUnderlineColor(self, value: str | None) -> None:
"""Set text underline colour."""
if value in self.VALID_LCOL:
self._tAttr["text-underline-color"][1] = value
+13 -26
View File
@@ -108,6 +108,8 @@ class ToQTextDocument(Tokenizer):
def initDocument(self) -> None:
"""Initialise all computed values of the document."""
super().initDocument()
self._document.setUndoRedoEnabled(False)
self._document.blockSignals(True)
self._document.clear()
@@ -162,23 +164,9 @@ class ToQTextDocument(Tokenizer):
self._cText.setBackground(QtTransparent)
self._cText.setForeground(self._theme.text)
self._cComment = QTextCharFormat(self._cText)
self._cComment.setForeground(self._theme.comment)
self._cCommentMod = QTextCharFormat(self._cText)
self._cCommentMod.setForeground(self._theme.comment)
self._cCommentMod.setFontWeight(self._bold)
self._cNote = QTextCharFormat(self._cText)
self._cNote.setForeground(self._theme.note)
self._cCode = QTextCharFormat(self._cText)
self._cCode.setForeground(self._theme.code)
self._cModifier = QTextCharFormat(self._cText)
self._cModifier.setForeground(self._theme.modifier)
self._cModifier.setFontWeight(self._bold)
self._cKeyword = QTextCharFormat(self._cText)
self._cKeyword.setForeground(self._theme.keyword)
@@ -252,19 +240,9 @@ class ToQTextDocument(Tokenizer):
newBlock(cursor, bFmt)
cursor.insertText(nwUnicode.U_NBSP, self._cText)
elif tType in self.L_SUMMARY and self._doSynopsis:
elif tType in self.L_NOTES:
newBlock(cursor, bFmt)
modifier = self._localLookup(
"Short Description" if tType == BlockTyp.SHORT else "Synopsis"
)
cursor.insertText(f"{modifier}: ", self._cModifier)
self._insertFragments(tText, tFormat, cursor, self._cNote)
elif tType == BlockTyp.COMMENT and self._doComments:
newBlock(cursor, bFmt)
modifier = self._localLookup("Comment")
cursor.insertText(f"{modifier}: ", self._cCommentMod)
self._insertFragments(tText, tFormat, cursor, self._cComment)
self._insertFragments(tText, tFormat, cursor, self._cText)
elif tType == BlockTyp.KEYWORD and self._doKeywords:
newBlock(cursor, bFmt)
@@ -359,6 +337,15 @@ class ToQTextDocument(Tokenizer):
cFmt.setVerticalAlignment(QtVAlignSub)
elif fmt == TextFmt.SUB_E:
cFmt.setVerticalAlignment(QtVAlignNormal)
elif fmt == TextFmt.SUB_B:
cFmt.setVerticalAlignment(QtVAlignSub)
elif fmt == TextFmt.SUB_E:
cFmt.setVerticalAlignment(QtVAlignNormal)
elif fmt == TextFmt.COL_B:
if color := self._classes.get(data):
cFmt.setForeground(color)
elif fmt == TextFmt.COL_E:
cFmt.setForeground(self._theme.text)
elif fmt == TextFmt.DL_B:
cFmt.setForeground(self._theme.dialog)
elif fmt == TextFmt.DL_E: