diff --git a/lib/words.py b/lib/words.py index 7361253..660397a 100644 --- a/lib/words.py +++ b/lib/words.py @@ -1,7 +1,7 @@ import copy import json import re -from typing import Any, Optional, cast +from typing import Any, Dict, Optional, cast from PyQt6.QtCore import ( QByteArray, @@ -29,15 +29,12 @@ from PyQt6.QtGui import ( QTextOption, QTransform, ) -from PyQt6.QtNetwork import ( - QNetworkAccessManager, - QNetworkReply, - QNetworkRequest, -) +from PyQt6.QtNetwork import QNetworkAccessManager, QNetworkRequest from PyQt6.QtSql import QSqlQuery from PyQt6.QtWidgets import QScrollArea, QWidget from lib import query_error +from lib.sounds import SoundOff class Fragment: @@ -71,13 +68,14 @@ class Fragment: self._color = QColor() self._asis = asis self._left = 0 + self._target = "word" return def __str__(self) -> str: return self.__repr__() def size(self, width: int) -> QSize: - rect = QRect(self._position, QSize(width, 2000)) + rect = QRect(self._position, QSize(width - self._position.x(), 2000)) flags = ( Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignBaseline @@ -144,6 +142,10 @@ class Fragment: self._text = text return + def setTarget(self, target: str) -> None: + self._target = target + return + def setFont(self, font: QFont) -> None: self._font = font return @@ -361,6 +363,8 @@ class Word: 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) @@ -370,6 +374,8 @@ class Word: 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: @@ -470,7 +476,7 @@ class Word: fields = token.split("|") token = fields[0] if token in [ - "a_line", + "a_link", "d_link", "dxt", "et_link", @@ -481,6 +487,7 @@ class Word: 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"]: @@ -490,16 +497,30 @@ class Word: wref = fields[2] if token == "i_link": frag.setFont(italic) - elif token == "i_link": - if fields[2] == "": - wref = fields[1] - else: + 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() @@ -594,9 +615,10 @@ class Word: return self._leading + self._maxHeight _lines: list[Line] = [] + _resources: Dict[str, Any] = {} def __init__(self, word: str) -> None: - self.resources = {} + self._resources = {} # # Have we already retrieved this word? # @@ -653,8 +675,24 @@ class Word: query_error(query) return + @pyqtSlot() + def playPRS(self) -> None: + try: + prs = self.current[0]["hwi"]["prs"] + audio = QUrl(self.mw_sound_url(prs)) + snd = SoundOff() + snd.playSound(audio) + except KeyError: + pass + return + + @pyqtSlot() + def finished(self) -> None: + print("finished") + return + def getWord(self) -> str: - return self.current["word"] + return cast(str, self.current["word"]) def get_html(self) -> str | None: if self.current["source"] == "mw": @@ -667,7 +705,7 @@ class Word: def get_def(self) -> list[Line] | None: if len(self._lines) > 0: return self._lines - if len(self.resources.keys()) < 1: + if len(self._resources.keys()) < 1: # # Colors we used # @@ -679,15 +717,19 @@ class Word: boldFont.setPixelSize(20) textFont = QFont(boldFont) italicFont = QFont(boldFont) + capsFont = QFont(boldFont) + smallCapsFont = QFont(boldFont) headerFont.setWeight(QFont.Weight.Bold) boldFont.setBold(True) italicFont.setItalic(True) + capsFont.setCapitalization(QFont.Capitalization.AllUppercase) + smallCapsFont.setCapitalization(QFont.Capitalization.SmallCaps) phonicFont = QFontDatabase.font("Gentium", None, 10) phonicFont.setPixelSize(20) - self.resources = { + self._resources = { "colors": { "base": QColor(Qt.GlobalColor.white), "blue": QColor("#4a7d95"), @@ -699,6 +741,8 @@ class Word: "bold": boldFont, "italic": italicFont, "text": textFont, + "caps": capsFont, + "smallCaps": smallCapsFont, }, } if self.current["source"] == "mw": @@ -710,6 +754,7 @@ class Word: def mw_def(self) -> list[Line]: lines: list[Word.Line] = [] + # print(json.dumps(self.current,indent=2)) for entry in self.current["definition"]: lines += self.mw_def_entry(entry) self._lines = lines @@ -720,6 +765,10 @@ class Word: 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 @@ -734,59 +783,99 @@ class Word: outer = sns[0] else: inner = sns[0] - - for dt in sense["dt"]: - if dt[0] == "text": - line = Word.Line() - frag = Fragment( - f"{outer} {inner} ", - self.resources["fonts"]["bold"], - color=self.resources["colors"]["base"], - ) - outer = " " - frag.setLeft(10) - line.addFragment(frag) - frag = Fragment( - dt[1], - self.resources["fonts"]["text"], - color=self.resources["colors"]["base"], - ) - frag.setLeft(30) - line.addFragment(frag) - lines.append(line) - elif dt[0] == "vis": - for vis in dt[1]: + try: + text = ", ".join(sense["sls"]) + line = Word.Line() + frag = Fragment( + f"{outer} {inner} ", + self._resources["fonts"]["bold"], + color=self._resources["colors"]["base"], + ) + outer = " " + line.addFragment(frag) + frag = Fragment( + text, + self._resources["fonts"]["italic"], + color=self._resources["colors"]["base"], + ) + frag.setLeft(30) + line.addFragment(frag) + except KeyError: + pass + try: + for dt in sense["dt"]: + if dt[0] == "text": line = Word.Line() frag = Fragment( - f" ", - self.resources["fonts"]["bold"], + f"{outer} {inner} ", + self._resources["fonts"]["bold"], + color=self._resources["colors"]["base"], ) - frag.setLeft(45) + outer = " " + frag.setLeft(10) line.addFragment(frag) - line.addFragment( - Fragment( - vis["t"], - self.resources["fonts"]["text"], - color=QColor("#aaa"), - ) + frag = Fragment( + dt[1], + self._resources["fonts"]["text"], + color=self._resources["colors"]["base"], ) + frag.setLeft(30) + line.addFragment(frag) lines.append(line) + elif dt[0] == "vis": + for vis in dt[1]: + line = Word.Line() + frag = Fragment( + f" ", + self._resources["fonts"]["bold"], + ) + frag.setLeft(45) + line.addFragment(frag) + line.addFragment( + Fragment( + vis["t"], + self._resources["fonts"]["text"], + 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 = Word.Line() + frag = Fragment( + "\u27F6 " + seg[1], + self._resources["fonts"]["text"], + color=self._resources["colors"]["base"], + ) + frag.setLeft(30) + line.addFragment(frag) + lines.append(line) + + else: + raise Exception(f"Unknown key {dt[0]} in {sense['dt']}") + except KeyError: + pass return lines - def mw_def_entry(self, entry) -> list[Line]: + def mw_def_entry(self, entry: dict[str, Any]) -> list[Line]: # # Easy reference to colors # - base = self.resources["colors"]["base"] - blue = self.resources["colors"]["blue"] + base = self._resources["colors"]["base"] + blue = self._resources["colors"]["blue"] lines: list[Word.Line] = [] line = Word.Line() hw = re.sub(r"\*", "", entry["hwi"]["hw"]) - frag = Fragment(hw, self.resources["fonts"]["header"], color=base) + frag = Fragment(hw, self._resources["fonts"]["header"], color=base) line.addFragment(frag) frag = Fragment( - " " + entry["fl"], self.resources["fonts"]["label"], color=blue + " " + entry["fl"], self._resources["fonts"]["label"], color=blue ) line.addFragment(frag) lines.append(line) @@ -797,7 +886,7 @@ class Word: for vrs in entry["vrs"]: frag = Fragment( space + vrs["va"], - self.resources["fonts"]["label"], + self._resources["fonts"]["label"], color=base, ) space = " " @@ -807,7 +896,7 @@ class Word: line = self.Line() frag = Fragment( entry["hwi"]["hw"] + " ", - self.resources["fonts"]["phonic"], + self._resources["fonts"]["phonic"], color=base, ) line.addFragment(frag) @@ -816,7 +905,7 @@ class Word: if audio is None: audio = "" frag = Fragment( - prs["mw"], self.resources["fonts"]["phonic"], color=blue + prs["mw"], self._resources["fonts"]["phonic"], color=blue ) frag.setAudio(audio) line.addFragment(frag) @@ -827,7 +916,7 @@ class Word: for ins in entry["ins"]: try: frag = Fragment( - ins["il"], self.resources["fonts"]["text"], color=base + ins["il"], self._resources["fonts"]["text"], color=base ) line.addFragment(frag) space = " " @@ -835,7 +924,7 @@ class Word: pass frag = Fragment( space + ins["if"], - self.resources["fonts"]["bold"], + self._resources["fonts"]["bold"], color=base, ) line.addFragment(frag) @@ -845,7 +934,7 @@ class Word: line = self.Line() frag = Fragment( "; ".join(entry["lbs"]), - self.resources["fonts"]["bold"], + self._resources["fonts"]["bold"], color=base, ) line.addFragment(frag) @@ -860,7 +949,7 @@ class Word: line = self.Line() line.addFragment( Fragment( - v, self.resources["fonts"]["italic"], color=blue + v, self._resources["fonts"]["italic"], color=blue ) ) lines.append(line) @@ -961,10 +1050,18 @@ class Word: class Definition(QWidget): pronounce = pyqtSignal(str) - def __init__(self, w: Word, *args: Any, **kwargs: Any) -> None: + def __init__( + self, word: Optional[Word] = None, *args: Any, **kwargs: Any + ) -> None: super(Definition, self).__init__(*args, **kwargs) - self._word: str = w.getWord() - lines = w.get_def() + self._word = word + if word is not None: + self.setWord(word) + return + + def setWord(self, word: Word) -> None: + self._word = word + lines = word.get_def() assert lines is not None self._lines = lines self._buttons: list[Fragment] = [] @@ -982,7 +1079,7 @@ class Definition(QWidget): self.setFixedHeight(base) return - def resizeEvent(self, event: QResizeEvent) -> None: + def resizeEvent(self, event: Optional[QResizeEvent] = None) -> None: base = 0 for line in self._lines: line.finalizeLine(self.width(), base)