From 8babbe716032acbc72e5ff1f23f8b5fc37f24d55 Mon Sep 17 00:00:00 2001 From: "Christopher T. Johnson" Date: Sat, 13 Apr 2024 15:38:47 -0400 Subject: [PATCH] Functional version. Needs much tweaking. --- lib/definition.py | 196 ++++--------------------------------- plugins/merriam-webster.py | 187 ++++++++++++++++++++++++++++++++++- 2 files changed, 204 insertions(+), 179 deletions(-) diff --git a/lib/definition.py b/lib/definition.py index ccbcabb..4e1a14c 100644 --- a/lib/definition.py +++ b/lib/definition.py @@ -45,7 +45,9 @@ class Fragment: return self.__repr__() def size(self, width: int) -> QSize: - rect = QRect(self._position, QSize(width - self._position.x(), 2000)) + pos = self._position + pos.setX(self._indent * 30) + rect = QRect(pos, QSize(width - self._position.x(), 2000)) flags = ( Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignBaseline @@ -87,6 +89,10 @@ class Fragment: | Qt.TextFlag.TextWordWrap ) bounding = painter.boundingRect(rect, flags, self._text) + # + # We need to determine if the text caused a word wrap. + # If it has wrapped. We need to locate that exact break point + # size = bounding.size() painter.setPen(QColor("#f00")) @@ -296,6 +302,7 @@ class Fragment: return self._indent class Line: + parseText = None def __init__(self) -> None: self._maxHeight = -1 self._baseLine = -1 @@ -308,7 +315,12 @@ class Line: "|".join([x.text() for x in self._fragments]) + f"|{self._maxHeight}" ) - + @classmethod + def setParseText(cls, call) -> None: + print(call) + cls.parseText = call + return + def repaintEvent(self, painter: QPainter) -> int: # # we do not have an event field because we are not a true widget @@ -320,177 +332,6 @@ class Line: lineSpacing = ls return lineSpacing - def parseText(self, frag: Fragment) -> list[Fragment]: - org = frag.text() - if frag.asis() or True: - return [frag] - # - # Needed Fonts - # We can't use _resources because that might not be the font - # for this piece of text - # - bold = QFont(frag.font()) - bold.setWeight(QFont.Weight.Bold) - italic = QFont(frag.font()) - italic.setItalic(True) - smallCaps = QFont(frag.font()) - smallCaps.setCapitalization(QFont.Capitalization.SmallCaps) - script = QFont(frag.font()) - script.setPixelSize(int(script.pixelSize() / 4)) - caps = QFont(frag.font()) - caps.setCapitalization(QFont.Capitalization.AllUppercase) - - results: list[Fragment] = [] - while True: - text = frag.text() - start = text.find("{") - if start < 0: - results.append(frag) - return results - if start > 0: - newFrag = copy.copy(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 :]) - newFrag = copy.copy(frag) - oldFont = QFont(frag.font()) - if token == "bc": - results.append(Fragment(": ", bold, color=QColor("#fff"))) - 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(bold) - elif token in ["it", "qword", "wi"]: - frag.setFont(italic) - elif token == "sc": - frag.setFont(smallCaps) - elif token in ["inf", "sup"]: - frag.setFont(script) - elif token == "phrase": - font = QFont(bold) - font.setItalic(True) - frag.setFont(font) - elif token == "parahw": - font = QFont(smallCaps) - font.setWeight(QFont.Weight.Bold) - frag.setFont(font) - 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()) - else: - raise Exception(f"Unknown block marker: {token}") - results += self.parseText(frag) - frag = results.pop() - frag.setFont(oldFont) - text = frag.text() - if not text.startswith("{/" + token + "}"): - raise Exception( - 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(italic) - elif token == "sx": - frag.setFont(caps) - 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] - else: - raise Exception(f"Unknown code: {token} in {org}") - newFrag = copy.copy(frag) - newFrag.setText(htext) - newFrag.setWRef(wref) - newFrag.setTarget(target) - results.append(newFrag) - frag.setFont(oldFont) - text = frag.text() - continue - raise Exception( - f"Unable to locate a known token {token} in {org}" - ) def addFragment( self, @@ -510,8 +351,11 @@ class Line: frag.setPadding(3, 0, 0, 5) frag.setBorder(1) frag.setMargin(0, 0, 0, 0) - items = self.parseText(frag) - self._fragments += items + if Line.parseText: + items = Line.parseText(frag) + self._fragments += items + else: + self._fragments.append(frag) return def finalizeLine(self, width: int, base: int) -> None: @@ -538,8 +382,6 @@ class Line: x = 0 for frag in self._fragments: left = frag.indent() * 30 - if left > 0: - print(frag.indent(), frag.text()) if x < left: x = left # diff --git a/plugins/merriam-webster.py b/plugins/merriam-webster.py index 3f55057..bb38f6f 100644 --- a/plugins/merriam-webster.py +++ b/plugins/merriam-webster.py @@ -1,5 +1,6 @@ +import copy from importlib.abc import InspectLoader -from PyQt6.QtGui import QColor +from PyQt6.QtGui import QColor, QFont from trycast import trycast import json import re @@ -350,7 +351,6 @@ def do_sense(sense: Sense|None, indent:int=3) -> tuple[list[Fragment], list[Line frags += newFrags lines += newLines for k,v in sense.items(): - print(k) if k == 'dt' or k == 'sn': continue elif k == 'sdsense': @@ -477,6 +477,7 @@ def do_def(entry: DefinitionSection) -> list[Line]: return lines def getDef(defines: Any) -> list[Line]: + Line.setParseText(parseText) workList = restructure(defines) workList = trycast(list[Definition], workList) assert workList is not None @@ -560,3 +561,185 @@ def getDef(defines: Any) -> list[Line]: except NotImplementedError as e: print(e) 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 = 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() + 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 = copy.copy(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 :]) + newFrag = copy.copy(frag) + oldFont = QFont(frag.font()) + if token == "bc": + results.append(Fragment(": ", boldFont, color=baseColor)) + 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()) + 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] + else: + raise NotImplementedError(f"Unknown code: {token} in {org}") + newFrag = copy.copy(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}" + ) +