diff --git a/lib/definition.py b/lib/definition.py index 6ed7dbe..ccbcabb 100644 --- a/lib/definition.py +++ b/lib/definition.py @@ -37,7 +37,7 @@ class Fragment: self._color = QColor() self._background = QColor() self._asis = asis - self._left = 0 + self._indent = 0 self._target = "word" return @@ -243,8 +243,8 @@ class Fragment: def setBackground(self, color: QColor) -> None: self._background = color return - def setLeft(self, left: int) -> None: - self._left = left + def setIndent(self, indent: int) -> None: + self._indent = indent return # @@ -292,8 +292,8 @@ class Fragment: def asis(self) -> bool: return self._asis - def left(self) -> int: - return self._left + def indent(self) -> int: + return self._indent class Line: def __init__(self) -> None: @@ -322,7 +322,7 @@ class Line: def parseText(self, frag: Fragment) -> list[Fragment]: org = frag.text() - if frag.asis(): + if frag.asis() or True: return [frag] # # Needed Fonts @@ -537,8 +537,11 @@ class Line: self._leading = leading x = 0 for frag in self._fragments: - if x < frag.left(): - x = frag.left() + left = frag.indent() * 30 + if left > 0: + print(frag.indent(), frag.text()) + if x < left: + x = left # # We need to calculate the location to draw the # text. We also need to calculate the bounding Rectangle diff --git a/lib/words.py b/lib/words.py index 123f6af..0ecc5ef 100644 --- a/lib/words.py +++ b/lib/words.py @@ -1,23 +1,18 @@ import importlib import pkgutil import json -import re from typing import Any, TypedDict, cast from PyQt6.QtCore import ( - QUrl, Qt, pyqtSlot, ) -from PyQt6.QtGui import ( - QColor, -) from PyQt6.QtSql import QSqlQuery from PyQt6.QtWidgets import QScrollArea -from lib.utils import query_error, Resources +from lib.utils import query_error from lib.sounds import SoundOff -from lib.definition import Definition, Line, Fragment +from lib.definition import Definition, Line import plugins def find_plugins(ns_pkg): @@ -108,281 +103,6 @@ class Word: except KeyError: raise Exception(f"Unknown source: {self.current['source']}") - def mw_seq(self, seq: list[Any]) -> list[Line]: - r=Resources() - lines: list[Line] = [] - outer = " " - inner = " " - for value in seq: - if value[0] == 'pseq': - continue - print(value[0]) - print(value[1]) - sense = value[1] - # - # The optional 'sn' field tells us what sort of labeling to do - # - sn = sense.get("sn", "") - sns = sn.split(" ") - if len(sns) == 2: - outer = sns[0] - inner = sns[1] - elif len(sns) == 1: - if inner == " ": - outer = sns[0] - else: - inner = sns[0] - try: - text = ", ".join(sense["sls"]) - line = Line() - frag = Fragment( - f"{outer} {inner} ", - r.boldFont, - color=r.baseColor - ) - outer = " " - line.addFragment(frag) - frag = Fragment( - text, - r.italicFont, - color=r.baseColor - ) - frag.setLeft(30) - line.addFragment(frag) - except KeyError: - pass - try: - for dt in sense["dt"]: - if dt[0] == "text": - line = Line() - frag = Fragment( - f"{outer} {inner} ", - r.boldFont, - color=r.baseColor - ) - outer = " " - frag.setLeft(10) - line.addFragment(frag) - frag = Fragment( - dt[1], - r.textFont, - color=r.baseColor - ) - frag.setLeft(30) - line.addFragment(frag) - lines.append(line) - elif dt[0] == "vis": - for vis in dt[1]: - line = Line() - frag = Fragment( - f" ", - r.boldFont - ) - frag.setLeft(45) - line.addFragment(frag) - line.addFragment( - Fragment( - vis["t"], - r.textFont, - color=QColor("#aaa"), - ) - ) - lines.append(line) - elif dt[0] == "uns": - for uns in dt[1]: - for seg in uns: - if seg[0] == "text": - try: - line = lines.pop() - except IndexError: - line = Line() - frag = Fragment( - "\u27F6 " + seg[1], - r.textFont, - color=r.baseColor - ) - frag.setLeft(30) - line.addFragment(frag) - lines.append(line) - elif dt[0] == 'ca': - continue - else: - raise Exception(f"Unknown key {dt[0]} in {sense['dt']}") - except KeyError: - pass - return lines - - def mw_def_entry(self, entry: dict[str, Any]) -> list[Line]: - r = Resources() - # - # Easy reference to colors - # - lines: list[Line] = [] - line = Line() - hw = re.sub(r"\*", "", entry["hwi"]["hw"]) - frag = Fragment(hw, r.headerFont, color=r.baseColor) - line.addFragment(frag) - frag = Fragment( - " " + entry["fl"], r.labelFont, color=r.linkColor - ) - line.addFragment(frag) - lines.append(line) - - if "vrs" in entry.keys(): - line = Line() - space = "" - for vrs in entry["vrs"]: - frag = Fragment( - space + vrs["va"], - r.labelFont, - color=r.baseColor - ) - space = " " - line.addFragment(frag) - lines.append(line) - if "prs" in entry["hwi"]: - line = Line() - frag = Fragment( - entry["hwi"]["hw"] + " ", - r.phonicFont, - color=r.baseColor, - ) - line.addFragment(frag) - for prs in entry["hwi"]["prs"]: - audio = None - if audio is None: - audio = "" - frag = Fragment( - prs["mw"], r.phonicFont, color=r.linkColor - ) - frag.setAudio(audio) - line.addFragment(frag) - lines.append(line) - if "ins" in entry.keys(): - line = Line() - space = "" - for ins in entry["ins"]: - try: - frag = Fragment( - ins["il"], r.textFont, color=r.baseColor - ) - line.addFragment(frag) - space = " " - except KeyError: - pass - frag = Fragment( - space + ins["if"], - r.boldFont, - color=r.baseColor - ) - line.addFragment(frag) - space = "; " - lines.append(line) - if "lbs" in entry.keys(): - line = Line() - frag = Fragment( - "; ".join(entry["lbs"]), - r.boldFont, - color=r.baseColor - ) - line.addFragment(frag) - lines.append(line) - for value in entry["def"]: # has multiple 'sseg' or 'vd' init - for k, v in value.items(): - if k == "sseq": # has multiple 'senses' - for seq in v: - rr = self.mw_seq(seq) - lines += rr - elif k == "vd": - line = Line() - line.addFragment( - Fragment( - v, r.italicFont, color=r.linkColor - ) - ) - lines.append(line) - return lines - - def mw_html(self) -> str: - # - # Create the header, base word and its label - # - word = self.current['definition']["hwi"]["hw"] - label = self.current["fl"] - html = f'

{word} {label}

\n' - - # - # If there are variants, then add them in an unordered list. - # CSS will make it pretty - # - if "vrs" in self.current.keys(): - html += "\n" - - # - # If there is a pronunciation section, create it - # - if "prs" in self.current["hwi"].keys(): - tmp = [] - for prs in self.current["hwi"]["prs"]: - url = QUrl() - how = prs["mw"] - if url: - tmp.append(f'\\{how}\\') - else: - tmp.append(f"\\{how}\\") - html += '' - html += ''.join(tmp) - html += "\n" - - # - # If there are inflections, create a header for that. - # - if "ins" in self.current.keys(): - html += '

' - html += ", ".join([ins["if"] for ins in self.current["ins"]]) - html += "

\n" - - # - # Start creating the definition section - # - html += "\n" - return html - - def apidictionary_html(self) -> str: - html = "" - return html - - - - class DefinitionArea(QScrollArea): def __init__(self, w: Word, *args: Any, **kwargs: Any) -> None: super(DefinitionArea, self).__init__(*args, *kwargs) diff --git a/plugins/merriam-webster.py b/plugins/merriam-webster.py index a71c296..3f55057 100644 --- a/plugins/merriam-webster.py +++ b/plugins/merriam-webster.py @@ -1,8 +1,9 @@ +from importlib.abc import InspectLoader from PyQt6.QtGui import QColor from trycast import trycast import json import re -from typing import Any, NamedTuple, NotRequired, TypedDict +from typing import Any, Literal, NotRequired, TypedDict, cast from PyQt6.QtCore import QEventLoop, QUrl, Qt from PyQt6.QtNetwork import QNetworkRequest @@ -17,16 +18,15 @@ registration = { API = "https://www.dictionaryapi.com/api/v3/references/collegiate/json/{word}?key={key}" key = "51d9df34-ee13-489e-8656-478c215e846c" -class TextTuple(NamedTuple): - type_: str # 'text' - text: str -class TTuple(NamedTuple): - type_: str # 't' - text: str -class VerbalIllustration(TypedDict): - t: str - aq: str - +class Meta(TypedDict): + id: str + uuid: str + sort: str + src: str + section: str + stems: list[str] + offensive: bool + class Sound(TypedDict): audio: str ref: str @@ -39,73 +39,70 @@ class Pronunciation(TypedDict): pun: NotRequired[str] sound: NotRequired[Sound] -class Meta(TypedDict): - id: str - uuid: str - sort: str - src: str - section: str - stems: list[str] - offensive: bool +class SubSource(TypedDict): + source: NotRequired[str] + aqdate: NotRequired[str] -class HeadWordInfo(TypedDict): +class AttributionOfQuote(TypedDict): + auth: NotRequired[str] + source: NotRequired[str] + aqdate: NotRequired[str] + subsource: NotRequired[SubSource] + +class VerbalIllustration(TypedDict): + t: str + aq: NotRequired[AttributionOfQuote] + +class HeadWordInformation(TypedDict): hw: str prs: NotRequired[list[Pronunciation]] - -class HeadWord(TypedDict): + +class AlternanteHeadword(TypedDict): hw: str - prs: NotRequired[list[Pronunciation]] psl: NotRequired[str] class Variant(TypedDict): va: str - vl: str - prs: list[Pronunciation] - spl: str + vl: NotRequired[str] + prs: NotRequired[list[Pronunciation]] + spl: NotRequired[str] -class Inflection(TypedDict): - if_: str - ifc: str - il: str - prs: list[Pronunciation] - spl: str +Inflection =TypedDict('Inflection', { + 'if': NotRequired[str], + 'ifc': NotRequired[str], + 'il': NotRequired[str], + 'prs': NotRequired[list[Pronunciation]], + 'spl': NotRequired[str] + }) + +class CrossReferenceTarget(TypedDict): + cxl: str + cxr: NotRequired[str] + cxt: str + cxn: NotRequired[str] + +class CognateCrossRef(TypedDict): + cxl: str + cxtis: list[CrossReferenceTarget] + +class Pair(TypedDict): + objType: str + obj: Any class DividedSense(TypedDict): sd: str - et: list[str] # Not full - ins: list[Inflection] - lbs: list[str] - prs: list[Pronunciation] - sgram: str - sls: list[str] - vrs: list[Variant] + dt: list[list[Pair]] + et: NotRequired[list[Pair]] + ins: NotRequired[list[Inflection]] + lbs: NotRequired[list[str]] + prs: NotRequired[list[Pronunciation]] + sgram: NotRequired[str] + sls: NotRequired[list[str]] + vrs: NotRequired[list[Variant]] -class BioGraphicalNameWrap(TypedDict): - pname: str - sname: str - altname: str - prs: list[Pronunciation] - -class CalledAlsoTarget(TypedDict): - cat: str - catref: str - pn: str - prs: list[Pronunciation] - psl: str - -class CalledAlso(TypedDict): - intro: str - cats: list[CalledAlsoTarget] - -class RunInWrap(TypedDict): - rie: str - prs: list[Pronunciation] - text: str - vrs: list[Variant] - class Sense(TypedDict): - dt: list[list] # not full - et: NotRequired[list[str]] + dt: list[list[Pair]] + et: NotRequired[list[Pair]] ins: NotRequired[list[Inflection]] lbs: NotRequired[list[str]] prs: NotRequired[list[Pronunciation]] @@ -114,44 +111,94 @@ class Sense(TypedDict): sls: NotRequired[list[str]] sn: NotRequired[str] vrs: NotRequired[list[Variant]] - -class Definition(TypedDict): - sseq: list[list[list[Any]]] + +class TruncatedSense(Sense): pass + +class BindingSubstitutePair(TypedDict): + objType: Literal['bs'] + obj: Sense + +class SensePair(TypedDict): + objType: Literal['sense'] + obj: Sense + +class DefinitionSection(TypedDict): vd: NotRequired[str] + sls: NotRequired[list[str]] + sseq: Any # list[list[Pair]] -class Pair(TypedDict): - objType: str - obj: list[Sense]|Sense|str|list[VerbalIllustration]|list[Any] - -Entry = TypedDict( - 'Entry', - { - 'meta': Meta, - 'hom': NotRequired[str], - 'hwi': HeadWordInfo, - 'ahws': NotRequired[list[HeadWord]], - 'vrs': NotRequired[list[Variant]], - 'fl': NotRequired[str], - 'def': list[Definition], - } -) -class WordType(TypedDict): - word: str - source: str - definition: dict[str, Any] - +Definition =TypedDict('Definition', { + 'meta': Meta, + 'hom': NotRequired[int], + 'hwi': HeadWordInformation, + 'ahws': NotRequired[list[AlternanteHeadword]], + 'vrs': NotRequired[list[Variant]], + 'fl': str, + 'lbs': NotRequired[list[str]], + 'sls': NotRequired[list[str]], + 'ins': NotRequired[list[Inflection]], + 'cxs': NotRequired[list[CognateCrossRef]], + 'def': list[DefinitionSection], +}) + def make_pairs(src: list[Any]) -> list[Pair]: result:list[Pair] = [] iters = [iter(src)]*2 for entry in zip(*iters): - pair = { 'objType': entry[0], + pair0 = { 'objType': entry[0], 'obj': entry[1], } - pair = trycast(Pair, pair) - assert pair is not None - result.append(pair) + if isinstance(pair0['obj'], list): + result.append(cast(Pair,pair0)) + continue + pair1 = trycast(Pair, pair0) + if pair1 is None: + print(pair0['objType'], type(pair0['obj']), + json.dumps(pair0['obj'],indent=2) + ) + assert pair1 is not None + result.append(pair1) return result +Elements = [ 'dt', 'sen', 'bs', 'pseq', 'snot', 't', 'text', 'vis', 'sens', 'uns', 'sense' ] +def restructure(obj: Any) -> Any: + if isinstance(obj, list): + if len(obj) == 0: + return [] + if isinstance(obj[0], str) and obj[0] in Elements: + pairs = make_pairs(obj) + result = [] + for pair in pairs: + if isinstance(pair['obj'], list): + r2 = [] + for item in pair['obj']: + r2.append(restructure(item)) + pair['obj'] = r2 + elif isinstance(pair['obj'], dict): + r2 = {} + for k,v in pair['obj'].items(): + r2[k] = restructure(v) + pair['obj'] = r2 + result.append(pair) + return result + result = [] + for v in obj: + result.append(restructure(v)) + return result + elif isinstance(obj, dict): + obj2 = cast(dict, obj) + result = {} + for k,v in obj2.items(): + result[k] = restructure(v) + return result + else: + return obj + +class WordType(TypedDict): + word: str + source: str + definition: Any + def fetch(word:str) -> WordType: request = QNetworkRequest() url = QUrl(API.format(word=word, key=key)) @@ -182,11 +229,11 @@ def soundUrl(sound:Sound, fmt='ogg') -> QUrl: url += audio + f".{fmt}" return QUrl(url) -def getFirstSound(definition: list[Entry]) -> QUrl: +def getFirstSound(definition: Any) -> QUrl: # ahws, cats, dros, hwi, ins, ri, sdsense, sen, sense, uros, vrs for entry in definition: for v in entry.values(): - hwi = trycast(HeadWordInfo, v) + hwi = v # trycast if hwi is None: continue if 'prs' in hwi: @@ -197,7 +244,7 @@ def getFirstSound(definition: list[Entry]) -> QUrl: return url return QUrl() -def do_prs(hwi: HeadWordInfo) -> list[Fragment]: +def do_prs(hwi: Any) -> list[Fragment]: r = Resources() frags: list[Fragment] = [] font = r.labelFont @@ -226,49 +273,153 @@ def do_prs(hwi: HeadWordInfo) -> list[Fragment]: ) return frags -def do_sense(sense: Sense|None) -> tuple[list[Fragment], list[Line]]: +def do_aq(aq: AttributionOfQuote|None) -> list[Line]: + assert aq is not None + return [] + +def do_vis(vis: list[VerbalIllustration]|None,indent=0) -> list[Line]: + assert vis is not None + r = Resources() + lines: list[Line] = [] + for vi in vis: + line = Line() + frag = Fragment(vi['t'], r.textFont, color=r.baseColor) + if indent > 0: + frag.setIndent(indent) + line.addFragment(frag) + lines.append(line) + if 'aq' in vi: + lines += do_aq(trycast(AttributionOfQuote, vi['aq'])) + return [] + +def do_uns(uns: list[list[list[Pair]]]|None, indent:int) -> list[Line]: + assert uns is not None + r = Resources() + lines:list[Line] = [] + for note in uns: + for entry in note: + for pair in entry: + if pair['objType'] == 'text': + frag = Fragment(' \u2014'+pair['obj'], r.textFont, color=r.baseColor) + frag.setIndent(indent) + line = Line() + line.addFragment(frag) + lines.append(line) + elif pair['objType'] == 'vis': + lines += do_vis(trycast(list[VerbalIllustration], pair['obj']), indent) + elif pair['objType'] == 'ri': + raise NotImplementedError("NO ri") + return lines + +def do_dt(dt: list[list[Pair]]|None, indent: int) -> tuple[list[Fragment], 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) + else: + line = Line() + line.addFragment(frag) + lines.append(line) + elif pair['objType'] == 'vis': + lines += do_vis(trycast(list[VerbalIllustration], pair['obj'])) + elif pair['objType'] == 'uns': + newLines = do_uns(trycast(list[list[list[Pair]]], pair['obj']),indent) + lines += newLines + else: + print(json.dumps(pair, indent=2)) + raise NotImplementedError(f"Unknown or unimplimented element {pair['objType']}") + first = False + return (frags, lines) + +def do_sense(sense: Sense|None, indent:int=3) -> tuple[list[Fragment], list[Line]]: if sense is None: return ([],[]) lines: list[Line] = [] frags: list[Fragment] = [] r = Resources() - if 'sn' in sense: - sn = sense['sn'] - else: - sn = '' - print(f'{sn}\n\n',json.dumps(sense['dt'], indent=2)) - iters = [iter(sense['dt'])]*2 - for pair in zip(*iters): - pair = trycast(tuple[str, Any], pair) - assert pair is not None - print(pair[0]) - if pair[0] == 'text': + dt = sense['dt'] + (newFrags, newLines) = do_dt(trycast(list[list[Pair]], dt),indent) + frags += newFrags + lines += newLines + for k,v in sense.items(): + print(k) + if k == 'dt' or k == 'sn': + continue + 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.setIndent(indent) line = Line() - line.addFragment( - Fragment(pair[1], r.textFont, color=r.baseColor) - ) + line.addFragment(frag) + (newFrags, newLines) = do_dt(trycast(list[list[Pair]], sdsense['dt']), indent=indent) + for frag in newFrags: + 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.textFont, color=r.subduedColor) + frags.append(frag) + else: + print(k,v) + raise NotImplementedError(f"Unknown or unimplimented element {k}") return (frags, lines) def do_pseq(outer: int, inner: int, - pseq: list[list[Pair]]| None ) -> tuple[list[Fragment], list[Line]]: - assert pseq is not None + pseq: list[Any] ) -> tuple[list[Fragment], list[Line]]: lines: list[Line] = [] frags: list[Fragment] = [] + count = 1 + r = Resources() + first = True for entry in pseq: - pairs = make_pairs(entry) - for pair in pairs: + for pair in entry: if pair['objType'] == 'bs': - (newFrags, newLines) = do_sense(trycast(Sense, pair['obj'])) - frags += newFrags + # TODO - bs has to be more than just a wrapper for Sense + sense = pair['obj']['sense'] + (newFrags, newLines) = do_sense(trycast(Sense, sense)) + if first: + frags += newFrags + first = False + else: + line = Line() + for frag in newFrags: + line.addFragment(frag) + lines.append(line) lines += newLines elif pair['objType'] == 'sense': - (newFrags, newLines) = do_sense(trycast(Sense, pair['obj'])) - frags += newFrags + if first: + frag = Fragment(f"({count})", r.textFont, color=r.baseColor) + frag.setIndent(3) + frags.append(frag) + (newFrags, newLines) = do_sense(trycast(Sense, pair['obj']), indent=4) + frags += newFrags + first = False + else: + line = Line() + frag = Fragment(f"({count})", r.textFont, color=r.baseColor) + frag.setIndent(3) + line.addFragment(frag) + (newFrags, newLines) = do_sense(trycast(Sense, pair['obj']), indent=4) + for frag in newFrags: + line.addFragment(frag) + lines.append(line) lines += newLines + count += 1 else: - raise Exception(f"Unknown object type {pair['objType']}") + raise NotImplementedError(f"Unknown object type {pair['objType']}") return (frags, lines) def do_sseq(sseq:list[list[list[Pair]]]) -> list[Line]: @@ -276,15 +427,14 @@ def do_sseq(sseq:list[list[list[Pair]]]) -> list[Line]: r = Resources() for outer, item_o in enumerate(sseq): line = Line() - line.addFragment( - Fragment(str(outer+1), r.boldFont, color=r.baseColor) - ) + frag =Fragment(str(outer+1), r.boldFont, color=r.baseColor) + frag.setIndent(1) + line.addFragment(frag) for inner, item_i in enumerate(item_o): - line.addFragment( - Fragment(chr(ord('a')+inner), r.boldFont, color=r.baseColor) - ) - pairs = make_pairs(item_i) - for pair in pairs: + frag =Fragment(chr(ord('a')+inner), r.boldFont, color=r.baseColor) + frag.setIndent(2) + line.addFragment(frag) + for pair in item_i: objType = pair['objType'] if objType == 'sense': sense = trycast(Sense, pair['obj']) @@ -292,26 +442,27 @@ def do_sseq(sseq:list[list[list[Pair]]]) -> list[Line]: for frag in frags: line.addFragment(frag) lines.append(line) + line = Line() lines += newlines elif objType == 'sen': - raise Exception(f"sen unimplimented") + raise NotImplementedError(f"sen unimplimented") elif objType == 'pseq': - pseq = trycast(list[list[Pair]], pair['obj']) - (frags, newlines) = do_pseq(inner, outer, trycast(list[list[Pair]], pair['obj'])) + (frags, newlines) = do_pseq(inner, outer, pair['obj']) for frag in frags: line.addFragment(frag) lines.append(line) + line = Line() lines += newlines elif objType == 'bs': - raise Exception(f"bs unimplimented") + raise NotImplementedError(f"bs unimplimented") else: - raise Exception(f"Unknown object[{objType}] for \n{json.dumps(pair['obj'],indent=2)}") + raise NotImplementedError(f"Unknown object[{objType}] for \n{json.dumps(pair['obj'],indent=2)}") return lines -def do_def(entry: Definition) -> list[Line]: +def do_def(entry: DefinitionSection) -> list[Line]: + assert entry is not None r = Resources() lines: list[Line] = [] - assert trycast(Definition, entry) is not None if 'vd' in entry: line = Line() line.addFragment( @@ -325,67 +476,68 @@ def do_def(entry: Definition) -> list[Line]: lines += do_sseq(sseq) return lines -def getDef(definition: list[Entry]) -> list[Line]: +def getDef(defines: Any) -> list[Line]: + workList = restructure(defines) + workList = trycast(list[Definition], workList) + assert workList is not None r = Resources() lines:list[Line] = [] - # - # Pull the fonts for ease of use - # - headerFont = r.headerFont - textFont = r.textFont - labelFont = r.labelFont - # - # Pull the colors for ease of use - # - baseColor = r.baseColor - linkColor = r.linkColor - subduedColor = r.subduedColor # # No need to figure it out each time it is used # entries = 0 - id = definition[0]['meta']['id'].lower().split(':')[0] + id = workList[0]['meta']['id'].lower().split(':')[0] uses: dict[str,int] = {} - for entry in definition: + for entry in workList: testId = entry['meta']['id'].lower().split(':')[0] if testId == id: entries += 1 + # + # If there is a Functional Lable, then we are going + # to capture the count of each FL + # try: uses[entry['fl']] = uses.get(entry['fl'], 0) + 1 except KeyError: pass + del(entry) used: dict[str, int] = {} for k in uses.keys(): used[k] = 0 - for count, entry in enumerate(definition): - testId = entry['meta']['id'].lower().split(':')[0] + + for count, work in enumerate(workList): + testId = work['meta']['id'].lower().split(':')[0] + # + # Skip entries which are not part of the primary definition + # if testId != id: continue # # Create the First line from the hwi, [ahws] and fl # line = Line() - hwi = trycast(HeadWordInfo, entry['hwi']) + hwi = trycast(HeadWordInformation, work['hwi']) assert hwi is not None hw = re.sub(r'\*', '', hwi['hw']) - line.addFragment(Fragment(hw, headerFont, color=baseColor)) - if 'ahws' in entry: - ahws = trycast(list[HeadWord], entry['ahws']) + line.addFragment(Fragment(hw, r.headerFont, color=r.baseColor)) + 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, headerFont, color=baseColor)) + line.addFragment(Fragment(', ' + hw, r.headerFont, color=r.baseColor)) if entries > 1: - frag = Fragment(f" {count + 1} of {entries} ", textFont, color= subduedColor) + frag = Fragment(f" {count + 1} of {entries} ", r.textFont, color= r.subduedColor) + # XXX - Use a resource color!!! frag.setBackground(QColor(Qt.GlobalColor.gray)) line.addFragment(frag) - if 'fl' in entry: - text = entry['fl'] + if 'fl' in work: + text = work['fl'] used[text] += 1 if uses[text] > 1: text += f' ({used[text]})' - line.addFragment(Fragment(text, labelFont, color=baseColor)) + line.addFragment(Fragment(text, r.labelFont, color=r.baseColor)) lines.append(line) # @@ -395,13 +547,16 @@ def getDef(definition: list[Entry]) -> list[Line]: line = Line() if hwi['hw'].find('*') >= 0: hw = re.sub(r'\*', '\u00b7', hwi['hw']) - line.addFragment(Fragment(hw + ' ', textFont, color=subduedColor)) + line.addFragment(Fragment(hw + ' ', r.textFont, color=r.subduedColor)) for frag in do_prs(hwi): line.addFragment(frag) if len(line.getLine()) > 0: lines.append(line) - defines = trycast(list[Definition], entry['def']) + defines = trycast(list[DefinitionSection], work['def']) assert defines is not None for define in defines: - lines += do_def(define) + try: + lines += do_def(define) + except NotImplementedError as e: + print(e) return lines