Layout is good, click boxes is wrong
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user