Layout is good, click boxes is wrong

This commit is contained in:
Christopher T. Johnson
2024-05-07 11:26:15 -04:00
parent 51b1121176
commit 7d2532d775
6 changed files with 568 additions and 574 deletions

View File

@@ -2,8 +2,8 @@ import json
import re
from typing import Any, Literal, NotRequired, TypedDict, cast
from PyQt6.QtCore import QEventLoop, Qt, QUrl
from PyQt6.QtGui import QColor, QFont
from PyQt6.QtCore import QEventLoop, QUrl
from PyQt6.QtGui import QFont, QFontDatabase, QTextCharFormat, QTextLayout
from PyQt6.QtNetwork import QNetworkRequest
from trycast import trycast
@@ -151,6 +151,18 @@ class DefinitionSection(TypedDict):
sls: NotRequired[list[str]]
sseq: Any # list[list[Pair]]
DefinedRunOn = TypedDict(
"DefinedRunOn",
{
"drp": str,
"def": list[DefinitionSection],
"et": NotRequired[list[Pair]],
"lbs": NotRequired[list[str]],
"prs": NotRequired[list[Pronunciation]],
"sls": NotRequired[list[str]],
"vrs": NotRequired[list[Variant]]
}
)
Definition = TypedDict(
"Definition",
@@ -302,13 +314,9 @@ def getFirstSound(definition: Any) -> QUrl:
return QUrl()
def do_prs(prs: list[Pronunciation] | None) -> list[Fragment]:
def do_prs(frag: Fragment, prs: list[Pronunciation] | None) -> None:
assert prs is not None
r = Resources()
frags: list[Fragment] = []
font = r.labelFont
linkColor = r.linkColor
subduedColor = r.subduedColor
for pr in prs:
if "pun" in pr:
@@ -316,22 +324,30 @@ def do_prs(prs: list[Pronunciation] | None) -> list[Fragment]:
else:
pun = " "
if "l" in pr:
frags.append(
Fragment(pr["l"] + pun, r.italicFont, color=subduedColor)
)
frag = Fragment(pr["mw"], font, color=subduedColor)
frag.addText(pr["l"] + pun, r.subduedItalicFormat)
fmt = r.phonticFormat
if "sound" in pr:
frag.setAudio(soundUrl(pr["sound"]))
frag.setColor(linkColor)
frags.append(frag)
frags.append(Fragment(" ", r.phonicFont))
fmt = QTextCharFormat(r.phonticFormat)
fmt.setAnchor(True)
fmt.setAnchorHref(soundUrl(pr["sound"]).toString())
fmt.setForeground(r.linkColor)
#text = pr["mw"] +' \N{SPEAKER} '
text = pr["mw"] +' '
else:
text = pr['mw'] + ' '
print(f"text: {text}, length: {len(text)}")
frag.addText(text, fmt)
if "l2" in pr:
frags.append(Fragment(pun + pr["l2"], font, color=subduedColor))
return frags
frag.addText(pun + pr["l2"], r.subduedLabelFormat)
text = frag.layout().text()
for fmt in frag.layout().formats():
print(f"start: {fmt.start}, length: {fmt.length}, text: \"{text[fmt.start:fmt.start+fmt.length]}\"")
return
def do_aq(aq: AttributionOfQuote | None) -> list[Line]:
assert aq is not None
raise NotImplementedError("aq")
return []
@@ -341,7 +357,8 @@ def do_vis(vis: list[VerbalIllustration] | None, indent=0) -> list[Line]:
lines: list[Line] = []
for vi in vis:
line = Line()
frag = Fragment(vi["t"], r.textFont, color=r.subduedColor)
frag = Fragment()
frag.addText(vi['t'], r.subduedFormat)
if indent > 0:
frag.setIndent(indent)
line.addFragment(frag)
@@ -376,90 +393,95 @@ def do_uns(
return (frags, lines)
def do_dt(
dt: list[list[Pair]] | None, indent: int
) -> tuple[list[Fragment], list[Line]]:
def do_dt(frag, dt: list[list[Pair]] | None, indent: int) -> list[Line]:
assert dt is not None
frags: list[Fragment] = []
lines: list[Line] = []
r = Resources()
first = True
for entry in dt:
for pair in entry:
if pair["objType"] == "text":
frag = Fragment(pair["obj"], r.textFont, color=r.baseColor)
frag.setIndent(indent)
if first:
frags.append(frag)
frag.setIndent(indent)
frag.addText(pair["obj"], r.textFormat)
else:
line = Line()
f = Fragment()
f.setIndent(indent)
f.addText(pair["obj"], r.textFormat)
line.addFragment(frag)
lines.append(line)
elif pair["objType"] == "vis":
first = False
lines += do_vis(
trycast(list[VerbalIllustration], pair["obj"]), indent
)
elif pair["objType"] == "uns":
first = False
(newFrags, newLines) = do_uns(
trycast(list[list[list[Pair]]], pair["obj"]), indent
)
frags += newFrags
lines += newLines
#frags += newFrags
#lines += newLines
raise NotImplementedError("uns")
else:
print(json.dumps(pair, indent=2))
raise NotImplementedError(
f"Unknown or unimplimented element {pair['objType']}"
)
first = False
return (frags, lines)
return lines
def do_sense(
sense: Sense | None, indent: int = 3
) -> tuple[list[Fragment], list[Line]]:
if sense is None:
return ([], [])
sense: Sense | None, indent: int = 3
) -> tuple[Fragment, list[Line]]:
assert sense is not None
lines: list[Line] = []
frags: list[Fragment] = []
r = Resources()
first = True
frag = Fragment()
for k, v in sense.items():
if k == "sn":
continue
elif k == "dt":
(newFrags, newLines) = do_dt(
trycast(list[list[Pair]], sense["dt"]), indent
)
frags += newFrags
newLines = do_dt(frag, trycast(list[list[Pair]], sense["dt"]), indent)
if first:
firstFrag = frag
frag = Fragment()
else:
line = Line()
line.addFragment(frag)
lines.append(line)
lines += newLines
elif k == "sdsense":
# XXX - This needs to expand to handle et, ins, lbs, prs, sgram, sls, vrs
sdsense = trycast(DividedSense, v)
assert sdsense is not None
frag = Fragment(
sdsense["sd"] + " ", r.italicFont, color=r.baseColor
)
frag = Fragment()
frag.setIndent(indent)
frag.addText(sdsense["sd"] + ' ', r.italicFormat)
line = Line()
line.addFragment(frag)
(newFrags, newLines) = do_dt(
trycast(list[list[Pair]], sdsense["dt"]), indent=indent
)
line.addFragment(newFrags)
lines.append(line)
newLines = do_dt(frag, trycast(list[list[Pair]], sdsense["dt"]), indent=indent)
if first:
firstFrag = frag
frag = Fragment()
else:
line = Line()
line.addFragment(frag)
lines.append(line)
lines += newLines
elif k == "sls":
labels = trycast(list[str], v)
assert labels is not None
frag = Fragment(
", ".join(labels) + " ", r.boldFont, color=r.subduedColor
)
frag.setIndent(indent)
frag.setBackground(r.subduedBackground)
frags.append(frag)
frag.addText(", ".join(labels) + " ",r.boldOnSFormat)
elif "lbs" == k:
pass
else:
print(k, v)
raise NotImplementedError(f"Unknown or unimplimented element {k}")
return (frags, lines)
return (firstFrag, lines)
def do_pseq(
@@ -475,28 +497,23 @@ def do_pseq(
for pair in entry:
if pair["objType"] == "bs":
sense = pair["obj"]["sense"]
(newFrags, newLines) = do_sense(
(frag, newLines) = do_sense(
trycast(Sense, sense), indent=indent
)
frags += newFrags
frags.append(frag)
lines += newLines
newLine = True
elif pair["objType"] == "sense":
frag = Fragment(f"({count})", r.textFont, color=r.baseColor)
frag.setIndent(indent)
sn = Fragment()
sn.addText(f"({count})", r.textFormat)
sn.setIndent(indent)
(frag, newLines) = do_sense(trycast(Sense, pair["obj"]), indent=indent + 1)
if newLine:
line = Line()
line.addFragment(sn)
line.addFragment(frag)
else:
frags.append(frag)
(newFrags, newLines) = do_sense(
trycast(Sense, pair["obj"]), indent=indent + 1
)
if newLine:
line.addFragment(newFrags)
lines.append(line)
else:
frags += newFrags
frags = [sn, frag, ]
newLine = True
lines += newLines
count += 1
@@ -510,17 +527,17 @@ def do_pseq(
def do_sseq(sseq: list[list[list[Pair]]]) -> list[Line]:
lines: list[Line] = []
r = Resources()
line = Line()
for outer, item_o in enumerate(sseq):
line = Line()
frag = Fragment(str(outer + 1), r.boldFont, color=r.baseColor)
frag = Fragment()
frag.setIndent(1)
frag.addText(str(outer +1), r.boldFormat)
line.addFragment(frag)
for inner, item_i in enumerate(item_o):
indent = 2
if len(item_o) > 1:
frag = Fragment(
chr(ord("a") + inner), r.boldFont, color=r.baseColor
)
frag = Fragment()
frag.addText(chr(ord("a") + inner), r.boldFormat)
frag.setIndent(2)
line.addFragment(frag)
indent = 3
@@ -528,8 +545,8 @@ def do_sseq(sseq: list[list[list[Pair]]]) -> list[Line]:
objType = pair["objType"]
if objType == "sense":
sense = trycast(Sense, pair["obj"])
(frags, newlines) = do_sense(sense, indent=indent)
line.addFragment(frags)
(frag, newlines) = do_sense(sense, indent=indent)
line.addFragment(frag)
lines.append(line)
line = Line()
lines += newlines
@@ -542,6 +559,7 @@ def do_sseq(sseq: list[list[list[Pair]]]) -> list[Line]:
line = Line()
lines += newlines
elif objType == "bs":
raise NotImplementedError("bs")
sense = pair["obj"]["sense"]
(newFrags, newLines) = do_sense(
trycast(Sense, sense), indent=indent
@@ -557,18 +575,15 @@ def do_sseq(sseq: list[list[list[Pair]]]) -> list[Line]:
return lines
def do_ins(inflections: list[Inflection] | None) -> list[Fragment]:
def do_ins(frag: Fragment, inflections: list[Inflection] | None) -> None:
assert inflections is not None
r = Resources()
frags: list[Fragment] = []
sep = ""
for inflection in inflections:
if sep == "; ":
frag = Fragment("; ", font=r.boldFont, color=r.baseColor)
frags.append(frag)
frag.addText(sep, r.boldFormat)
elif sep != "":
frag = Fragment(sep, font=r.italicFont, color=r.baseColor)
frags.append(frag)
frag.addText(sep, r.italicFormat)
if "ifc" in inflection:
text = inflection["ifc"]
@@ -577,19 +592,18 @@ def do_ins(inflections: list[Inflection] | None) -> list[Fragment]:
else:
raise ValueError(f"Missing 'if' or 'ifc' in {inflection}")
frag = Fragment(text, r.boldFont, color=r.baseColor)
frags.append(frag)
text = re.sub(r'\*', '\u00b7', text)
frag.addText(text, r.boldFormat)
sep = "; "
if "il" in inflection:
sep = " " + inflection["il"] + " "
if "prs" in inflection:
newFrags = do_prs(trycast(list[Pronunciation], inflection["prs"]))
frags += newFrags
do_prs(frag, trycast(list[Pronunciation], inflection["prs"]))
if "spl" in inflection:
raise NotImplementedError(
f"We haven't implimented 'spl' for inflection: {inflection}"
)
return frags
return
def do_ets(ets: list[list[Pair]] | None) -> list[Line]:
@@ -600,17 +614,15 @@ def do_ets(ets: list[list[Pair]] | None) -> list[Line]:
for pair in et:
if pair["objType"] == "text":
line = Line()
line.addFragment(
Fragment(pair["obj"], r.textFont, color=r.baseColor)
)
frag = Fragment('', r.textFont)
frag.addText(pair['obj'], r.textFormat)
line.addFragment(frag)
lines.append(line)
elif pair["objType"] == "et_snote":
line = Line()
line.addFragment(
Fragment(
"Note: " + pair["obj"], r.textFont, color=r.baseColor
)
)
frag = Fragment('', r.textFont)
frag.addText(f"Note: {pair['obj']}",r.textFormat)
line.addFragment(frag)
lines.append(line)
else:
raise NotImplementedError(
@@ -625,7 +637,9 @@ def do_def(entry: DefinitionSection) -> list[Line]:
lines: list[Line] = []
if "vd" in entry:
line = Line()
line.addFragment(Fragment(entry["vd"], r.italicFont, color=r.linkColor))
frag = Fragment()
frag.addText(entry["vd"], r.italicFormat)
line.addFragment(frag)
lines.append(line)
#
# sseg is required
@@ -634,6 +648,46 @@ def do_def(entry: DefinitionSection) -> list[Line]:
lines += do_sseq(sseq)
return lines
def do_vrs(vrs: list[Variant]|None) -> Line:
assert vrs is not None
r = Resources()
line = Line()
frag = Fragment()
frag.addText('variants: ', r.sOnSFormat)
for var in vrs:
if 'vl' in var:
frag.addText(var['vl']+' ', r.italicFormat)
if 'spl' in var:
frag.addText(var['spl']+' ', r.sOnSFormat)
frag.addText(var['va'], r.boldFormat)
if 'prs' in var:
frag.addText(' ')
do_prs(frag, trycast(list[Pronunciation], var['prs']))
frag.addText(' ')
line.addFragment(frag)
return line
def do_dros(dros: list[DefinedRunOn]|None) -> list[Line]:
assert dros is not None
r = Resources()
lines: list[Line] = []
for dro in dros:
line = Line()
frag = Fragment()
frag.addText(dro["drp"], r.boldFormat)
line.addFragment(frag)
lines.append(line)
for entry in dro['def']:
lines += do_def(entry)
for k,v in dro.items():
if 'drp' == k or 'def' == k:
continue
elif 'et' == k:
lines += do_ets(trycast(list[list[Pair]], v))
else:
raise NotImplementedError(f"Key of {k}")
return lines
def getDef(defines: Any) -> list[Line]:
Line.setParseText(parseText)
@@ -667,7 +721,7 @@ def getDef(defines: Any) -> list[Line]:
used[k] = 0
ets: list[Line] = []
phrases: list[Line] = []
for count, work in enumerate(workList):
testId = work["meta"]["id"].lower().split(":")[0]
#
@@ -679,30 +733,26 @@ def getDef(defines: Any) -> list[Line]:
# Create the First line from the hwi, [ahws] and fl
#
line = Line()
frag = Fragment()
hwi = trycast(HeadWordInformation, work["hwi"])
assert hwi is not None
hw = re.sub(r"\*", "", hwi["hw"])
line.addFragment(Fragment(hw, r.headerFont, color=r.baseColor))
frag.addText(hw,r.headerFormat)
if "ahws" in work:
ahws = trycast(list[AlternanteHeadword], work["ahws"])
assert ahws is not None
for ahw in ahws:
hw = re.sub(r"\*", "", ahw["hw"])
line.addFragment(
Fragment(", " + hw, r.headerFont, color=r.baseColor)
)
frag.addText(", " + hw)
if entries > 1:
frag = Fragment(
f" {count + 1} of {entries} ", r.textFont, color=r.subduedColor
)
frag.setBackground(r.subduedBackground)
line.addFragment(frag)
frag.addText(f" {count + 1} of {entries} ", r.sOnSFormat)
if "fl" in work:
text = work["fl"]
used[text] += 1
if uses[text] > 1:
text += f" ({used[text]})"
line.addFragment(Fragment(text, r.labelFont, color=r.baseColor))
frag.addText(text, r.labelFormat)
line.addFragment(frag)
lines.append(line)
#
@@ -710,55 +760,65 @@ def getDef(defines: Any) -> list[Line]:
# While 'prs' is optional, the headword is not. This gets us what we want.
#
line = Line()
frag = Fragment()
if hwi["hw"].find("*") >= 0:
hw = re.sub(r"\*", "\u00b7", hwi["hw"])
line.addFragment(
Fragment(hw + " ", r.textFont, color=r.subduedColor)
)
frag.addText(hw + " ", r.subduedFormat)
if "prs" in hwi:
newFrags = do_prs(trycast(list[Pronunciation], hwi["prs"]))
line.addFragment(newFrags)
do_prs(frag, trycast(list[Pronunciation], hwi["prs"]))
line.addFragment(frag)
lines.append(line)
line = Line()
frag = Fragment()
if 'vrs' in work:
lines.append(do_vrs(trycast(list[Variant], work['vrs'])))
if "ins" in work:
inflections = trycast(list[Inflection], work["ins"])
newFrags = do_ins(inflections)
line = Line()
line.addFragment(newFrags)
do_ins(frag,inflections)
line.addFragment(frag)
lines.append(line)
line = Line()
frag = Fragment()
defines = trycast(list[DefinitionSection], work["def"])
assert defines is not None
for define in defines:
try:
lines += do_def(define)
except NotImplementedError as e:
print(e)
except NotImplementedError:
raise
if "dros" in work:
dros = trycast(list[DefinedRunOn], work["dros"])
if len(phrases) < 1:
frag = Fragment()
frag.addText("Phrases", r.labelFormat)
line = Line()
line.addFragment(frag)
phrases.append(line)
phrases += do_dros(dros)
if "et" in work:
line = Line()
line.addFragment(
Fragment(
f"{work['fl']} ({used[work['fl']]})",
r.labelFont,
color=r.baseColor,
)
)
ets.append(line)
frag = Fragment('', r.textFont)
frag.addText(f"{work['fl']} ({used[work['fl']]})",r.labelFormat)
line.addFragment(frag)
ets += do_ets(trycast(list[list[Pair]], work["et"]))
for k in work.keys():
if k not in [
"meta",
"hom",
"hwi",
"fl",
"def",
"ins",
"prs",
"et",
"date",
"shortdef",
"meta",
"hom",
"hwi",
"fl",
"def",
"ins",
"prs",
"et",
"date",
"shortdef",
"vrs",
"dros",
]:
# raise NotImplementedError(f"Unknown key {k} in work")
print(f"Unknown key {k} in work")
raise NotImplementedError(f"Unknown key {k} in work")
if len(phrases) > 0:
lines += phrases
if len(ets) > 0:
line = Line()
line.addFragment(Fragment("Etymology", r.labelFont, color=r.baseColor))
@@ -766,185 +826,116 @@ def getDef(defines: Any) -> list[Line]:
lines += ets
return lines
def parseText(frag: Fragment) -> list[Fragment]:
org = frag.text()
if frag.asis():
return [frag]
#
# Get the fonts we might need.
# We can't use Resources() because we don't know the original font.
textFont = QFont(frag.font())
textFont.setWeight(QFont.Weight.Normal)
textFont.setItalic(False)
textFont.setCapitalization(QFont.Capitalization.MixedCase)
boldFont = QFont(textFont)
boldFont.setBold(True)
italicFont = QFont(textFont)
italicFont.setItalic(True)
smallCapsFont = QFont(textFont)
smallCapsFont.setCapitalization(QFont.Capitalization.SmallCaps)
scriptFont = QFont(textFont)
scriptFont.setPixelSize(int(scriptFont.pixelSize() / 4))
boldItalicFont = QFont(boldFont)
boldItalicFont.setItalic(True)
boldSmallCapsFont = QFont(smallCapsFont)
boldSmallCapsFont.setBold(True)
capsFont = QFont(textFont)
capsFont.setCapitalization(QFont.Capitalization.AllUppercase)
#
# Default color:
#
baseColor = frag.color()
def replaceCode(code:str) -> tuple[str, QTextCharFormat]:
r = Resources()
results: list[Fragment] = []
while True:
text = frag.text()
start = text.find("{")
if start < 0:
results.append(frag)
return results
if start > 0:
newFrag = Fragment(frag)
newFrag.setText(text[:start])
results.append(newFrag)
frag.setText(text[start:])
continue
#
# Start == 0
#
#
# If the token is an end-token, return now.
#
if text.startswith("{/"):
results.append(frag)
return results
#
# extract this token
#
end = text.find("}")
token = text[1:end]
frag.setText(text[end + 1 :])
oldFont = QFont(frag.font())
if token == "bc":
newFrag = Fragment(": ", boldFont, color=baseColor)
newFrag.setIndent(frag.indent())
results.append(newFrag)
continue
if token in [
"b",
"inf",
"it",
"sc",
"sup",
"phrase",
"parahw",
"gloss",
"qword",
"wi",
"dx",
"dx_def",
"dx_ety",
"ma",
]:
if token == "b":
frag.setFont(boldFont)
elif token in ["it", "qword", "wi"]:
frag.setFont(italicFont)
elif token == "sc":
frag.setFont(smallCapsFont)
elif token in ["inf", "sup"]:
frag.setFont(scriptFont)
elif token == "phrase":
frag.setFont(boldItalicFont)
elif token == "parahw":
frag.setFont(boldSmallCapsFont)
elif token == "gloss":
frag.setText("[" + frag.text())
elif token in ["dx", "dx_ety"]:
frag.setText("\u2014" + frag.text())
elif token == "ma":
frag.setText("\u2014 more at " + frag.text())
elif token == "dx_def":
frag.setText("(" + frag.text())
fmt = QTextCharFormat()
if code == 'bc':
fmt.setFontWeight(QFont.Weight.Bold)
return (': ', fmt)
elif code == 'ldquo':
return ('\u201c', fmt)
elif code == 'rdquo':
return ('\u201d', fmt)
fmt.setAnchor(True)
fmt.setForeground(r.linkColor)
fmt.setFontUnderline(True)
fmt.setUnderlineColor(r.linkColor)
fmt.setFontUnderline(True)
fields = code.split('|')
token = fields[0]
if token == 'a_link':
text = fields[1]
fmt.setAnchorHref(fields[1])
elif token in ['d_link', 'et_link', 'mat', 'sx', 'i_link']:
text = fields[1]
pre = 'word://'
if fields[2] == '':
fmt.setAnchorHref(pre+fields[1])
else:
fmt.setAnchorHref(pre+fields[2])
if token == 'i_link':
fmt.setFontItalic(True)
elif token == 'sx':
fmt.setFontCapitalization(QFont.Capitalization.SmallCaps)
elif token == 'dxt':
if fields[3] == 'illustration':
fmt.setAnchorHref('article://'+fields[2])
elif fields[3] == 'table':
fmt.setAnchorHref('table://'+fields[2])
elif fields[3] != "":
fmt.setAnchorHref('sense://'+fields[3])
else:
raise NotImplementedError(f"Unknown block marker: {token}")
results += parseText(frag)
frag = results.pop()
frag.setFont(oldFont)
text = frag.text()
if not text.startswith("{/" + token + "}"):
raise NotImplementedError(
f"No matching close for {token} in {org}"
)
if token == "gloss":
results[-1].setText(results[-1].text() + "]")
elif token == "dx_def":
results[-1].setText(results[-1].text() + ")")
end = text.find("}")
text = text[end + 1 :]
frag.setText(text)
continue
#
# These are codes that include all information within the token
#
fields = token.split("|")
token = fields[0]
if token in [
"a_link",
"d_link",
"dxt",
"et_link",
"i_link",
"mat",
"sx",
]:
wref = ""
htext = fields[1]
oldFont = QFont(frag.font())
target = "word"
if token == "a_link":
wref = fields[1]
elif token in ["d_link", "et_link", "mat", "sx", "i_link"]:
if fields[2] == "":
wref = fields[1]
else:
wref = fields[2]
if token == "i_link":
frag.setFont(italicFont)
elif token == "sx":
frag.setFont(capsFont)
elif token == "dxt":
if fields[3] == "illustration":
wref = fields[2]
target = "article"
elif fields[3] == "table":
wref = fields[2]
target = "table"
elif fields[3] != "":
wref = fields[3]
target = "sense"
else:
wref = fields[1]
target = "word"
elif token == "a_link":
target = "word"
wref = fields[1]
fmt.setAnchorHref('word://'+fields[1])
elif token == 'et_link':
if fields[2] != '':
fmt.setAnchorHref('etymology://'+fields[2])
else:
raise NotImplementedError(f"Unknown code: {token} in {org}")
newFrag = Fragment(frag)
newFrag.setText(htext)
newFrag.setWRef(wref)
newFrag.setTarget(target)
newFrag.setColor(r.linkColor)
results.append(newFrag)
frag.setFont(oldFont)
text = frag.text()
continue
raise NotImplementedError(
f"Unable to locate a known token {token} in {org}"
)
fmt.setAnchorHref('etymology://' + fields[1])
else:
raise NotImplementedError(f"Token {code} not implimented")
fmt.setForeground(r.linkColor)
print(f"Format.capitalization(): {fmt.fontCapitalization()}")
return (text,fmt)
def markup(offset: int, text:str) -> tuple[str, list[QTextLayout.FormatRange]]:
close = text.find('}')
code = text[1:close]
text = text[close+1:-(close+2)]
fmt = QTextCharFormat()
if code == 'b':
fmt.setFontWeight(QFont.Weight.Bold)
elif code == 'inf':
fmt.setVerticalAlignment(QTextCharFormat.VerticalAlignment.AlignSubScript)
elif code == 'it':
fmt.setFontItalic(True)
elif code == 'sc':
fmt.setFontCapitalization(QFont.Capitalization.SmallCaps)
fr = QTextLayout.FormatRange()
fr.start = offset
fr.length = len(text)
fr.format = fmt
return (text, [fr,])
def parseText(frag: Fragment) -> QTextLayout:
layout = frag.layout()
text = layout.text()
formats = layout.formats()
REPLACE_TEXT = [
'bc','a_link', 'd_link', 'dxt', 'et_link', 'i_link', 'mat',
'sx'
]
pos = 0
start = text[pos:].find('{')
while start >= 0:
start += pos
end = text[start+1:].find('}')
end += start
code = text[start+1:end+1]
pos = end+2
for maybe in REPLACE_TEXT:
if code.startswith(maybe):
(repl, tfmt) = replaceCode(code)
text = text[:start] + repl + text[end+2:]
fmt = QTextLayout.FormatRange()
fmt.format = tfmt
fmt.start=start
fmt.length = len(repl)
formats.append(fmt)
pos = start + len(repl)
code = ''
break
if code != '':
needle = f'{{/{code}}}'
codeEnd = text[start:].find(needle)
codeEnd += start+len(needle)
straw = text[start:codeEnd]
(repl, frs) = markup(start, straw)
fmt = QTextLayout.FormatRange()
formats += frs
text = text[:start] + repl + text[codeEnd:]
pos = start + len(repl)
start = text[pos:].find('{')
layout.setFormats(formats)
layout.setText(text)
return layout