checkpoint

This commit is contained in:
Christopher T. Johnson
2024-04-09 11:45:56 -04:00
parent 46580b75ea
commit ad5904f3ae
3 changed files with 312 additions and 182 deletions

View File

@@ -1,7 +1,9 @@
"""Utility Functions."""
from typing import NoReturn
from typing import NoReturn, Self
from PyQt6.QtCore import QCoreApplication
from PyQt6.QtCore import QCoreApplication, QDir, QStandardPaths, Qt
from PyQt6.QtGui import QColor, QFont, QFontDatabase
from PyQt6.QtNetwork import QNetworkAccessManager, QNetworkDiskCache
from PyQt6.QtSql import QSqlQuery
translate = QCoreApplication.translate
@@ -19,3 +21,72 @@ def query_error(query: QSqlQuery) -> NoReturn:
)
)
raise Exception(translate("MainWindow", "SQL Error"))
class Resources:
_instance = None
nam = QNetworkAccessManager()
headerFont: QFont
labelFont: QFont
boldFont: QFont
textFont: QFont
italicFont: QFont
capsFont: QFont
smallCapsFont: QFont
phonicFont: QFont
baseColor: QColor
linkColor: QColor
subduedColor: QColor
def __new__(cls: type[Self]) -> Self:
if cls._instance:
return cls._instance
cls._instance = super(Resources, cls).__new__(cls)
return cls._instance
def __init__(self) -> None:
super(Resources, self).__init__()
#
# Fonts
#
self.headerFont = QFontDatabase.font("OpenDyslexic", None, 10)
self.headerFont.setPixelSize(48)
self.labelFont = QFont(self.headerFont)
self.labelFont.setPixelSize(30)
self.boldFont = QFont(self.headerFont)
self.boldFont.setPixelSize(20)
self.textFont = QFont(self.boldFont)
self.italicFont = QFont(self.boldFont)
self.capsFont = QFont(self.boldFont)
self.smallCapsFont = QFont(self.boldFont)
self.headerFont.setWeight(QFont.Weight.Bold)
self.boldFont.setBold(True)
self.italicFont.setItalic(True)
self.capsFont.setCapitalization(QFont.Capitalization.AllUppercase)
self.smallCapsFont.setCapitalization(QFont.Capitalization.SmallCaps)
self.phonicFont = QFontDatabase.font("Gentium", None, 10)
self.phonicFont.setPixelSize(20)
#
# colors
#
self.baseColor = QColor(Qt.GlobalColor.white)
self.linkColor = QColor("#4a7d95")
self.subduedColor = QColor(Qt.GlobalColor.gray)
#
# Setup the Network Manager
#
cacheDir = QDir(
QStandardPaths.writableLocation(
QStandardPaths.StandardLocation.GenericCacheLocation
)
)
cacheDir.mkdir("Troglodite")
cacheDir = QDir(cacheDir.path() + QDir.separator() + "Troglodite")
netCache = QNetworkDiskCache()
netCache.setCacheDirectory(cacheDir.path())
self.nam.setCache(netCache)
return

View File

@@ -2,22 +2,20 @@ import importlib
import pkgutil
import json
import re
from typing import Any, Dict, cast
from typing import Any, TypedDict, cast
from PyQt6.QtCore import (
QUrl,
Qt,
pyqtSlot,
)
from PyQt6.QtGui import (
QColor,
QFont,
QFontDatabase,
)
from PyQt6.QtNetwork import QNetworkAccessManager
from PyQt6.QtSql import QSqlQuery
from PyQt6.QtWidgets import QScrollArea
from lib import query_error
from lib.utils import query_error, Resources
from lib.sounds import SoundOff
from lib.definition import Definition, Line, Fragment
@@ -32,20 +30,22 @@ discovered_plugins = {
API = "https://api.dictionaryapi.dev/api/v2/entries/en/{word}"
class WordType(TypedDict):
word: str
source: str
definition: str
class Word:
"""All processing of a dictionary word."""
_words: dict[str, Any] = {}
_resources: Dict[str, Any] = {}
_nam = QNetworkAccessManager()
_words: dict[str, WordType] = {}
def __init__(self, word: str) -> None:
Word.set_resources()
#
# Have we already retrieved this word?
#
try:
self.current = json.loads(Word._words[word])
self.current = Word._words[word]
return
except KeyError:
pass
@@ -82,50 +82,6 @@ class Word:
query_error(query)
return
@classmethod
def set_resources(cls) -> None:
if len(cls._resources.keys()) > 0:
return
#
# Colors we used
#
headerFont = QFontDatabase.font("OpenDyslexic", None, 10)
headerFont.setPixelSize(48)
labelFont = QFont(headerFont)
labelFont.setPixelSize(30)
boldFont = QFont(headerFont)
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)
cls._resources = {
"colors": {
"base": QColor(Qt.GlobalColor.white),
"link": QColor("#4a7d95"),
"subdued": QColor(Qt.GlobalColor.gray),
},
"fonts": {
"header": headerFont,
"label": labelFont,
"phonic": phonicFont,
"bold": boldFont,
"italic": italicFont,
"text": textFont,
"caps": capsFont,
"smallCaps": smallCapsFont,
},
}
@pyqtSlot()
def playSound(self) -> None:
url = discovered_plugins[self.current['source']].getFirstSound(self.current['definition'])
@@ -145,23 +101,15 @@ class Word:
raise Exception(f"Unknown source: {src}")
def get_def(self) -> list[Line]:
if len(self._lines) > 0:
return self._lines
src = self.current['source']
try:
return discovered_plugins[src].getDef(self.current)
lines = discovered_plugins[src].getDef(self.current["definition"])
return lines
except KeyError:
raise Exception(f"Unknown source: {self.current['source']}")
def mw_def(self) -> list[Line]:
lines: list[Line] = []
# print(json.dumps(self.current,indent=2))
for entry in self.current["definition"]:
lines += self.mw_def_entry(entry)
self._lines = lines
return lines
def mw_seq(self, seq: list[Any]) -> list[Line]:
r=Resources()
lines: list[Line] = []
outer = " "
inner = " "
@@ -189,15 +137,15 @@ class Word:
line = Line()
frag = Fragment(
f"{outer} {inner} ",
self._resources["fonts"]["bold"],
color=self._resources["colors"]["base"],
r.boldFont,
color=r.baseColor
)
outer = " "
line.addFragment(frag)
frag = Fragment(
text,
self._resources["fonts"]["italic"],
color=self._resources["colors"]["base"],
r.italicFont,
color=r.baseColor
)
frag.setLeft(30)
line.addFragment(frag)
@@ -209,16 +157,16 @@ class Word:
line = Line()
frag = Fragment(
f"{outer} {inner} ",
self._resources["fonts"]["bold"],
color=self._resources["colors"]["base"],
r.boldFont,
color=r.baseColor
)
outer = " "
frag.setLeft(10)
line.addFragment(frag)
frag = Fragment(
dt[1],
self._resources["fonts"]["text"],
color=self._resources["colors"]["base"],
r.textFont,
color=r.baseColor
)
frag.setLeft(30)
line.addFragment(frag)
@@ -228,14 +176,14 @@ class Word:
line = Line()
frag = Fragment(
f" ",
self._resources["fonts"]["bold"],
r.boldFont
)
frag.setLeft(45)
line.addFragment(frag)
line.addFragment(
Fragment(
vis["t"],
self._resources["fonts"]["text"],
r.textFont,
color=QColor("#aaa"),
)
)
@@ -250,8 +198,8 @@ class Word:
line = Line()
frag = Fragment(
"\u27F6 " + seg[1],
self._resources["fonts"]["text"],
color=self._resources["colors"]["base"],
r.textFont,
color=r.baseColor
)
frag.setLeft(30)
line.addFragment(frag)
@@ -265,19 +213,17 @@ class Word:
return lines
def mw_def_entry(self, entry: dict[str, Any]) -> list[Line]:
r = Resources()
#
# Easy reference to colors
#
base = self._resources["colors"]["base"]
blue = self._resources["colors"]["blue"]
lines: list[Line] = []
line = Line()
hw = re.sub(r"\*", "", entry["hwi"]["hw"])
frag = Fragment(hw, self._resources["fonts"]["header"], color=base)
frag = Fragment(hw, r.headerFont, color=r.baseColor)
line.addFragment(frag)
frag = Fragment(
" " + entry["fl"], self._resources["fonts"]["label"], color=blue
" " + entry["fl"], r.labelFont, color=r.linkColor
)
line.addFragment(frag)
lines.append(line)
@@ -288,8 +234,8 @@ class Word:
for vrs in entry["vrs"]:
frag = Fragment(
space + vrs["va"],
self._resources["fonts"]["label"],
color=base,
r.labelFont,
color=r.baseColor
)
space = " "
line.addFragment(frag)
@@ -298,16 +244,16 @@ class Word:
line = Line()
frag = Fragment(
entry["hwi"]["hw"] + " ",
self._resources["fonts"]["phonic"],
color=base,
r.phonicFont,
color=r.baseColor,
)
line.addFragment(frag)
for prs in entry["hwi"]["prs"]:
audio = self.mw_sound_url(prs)
audio = None
if audio is None:
audio = ""
frag = Fragment(
prs["mw"], self._resources["fonts"]["phonic"], color=blue
prs["mw"], r.phonicFont, color=r.linkColor
)
frag.setAudio(audio)
line.addFragment(frag)
@@ -318,7 +264,7 @@ class Word:
for ins in entry["ins"]:
try:
frag = Fragment(
ins["il"], self._resources["fonts"]["text"], color=base
ins["il"], r.textFont, color=r.baseColor
)
line.addFragment(frag)
space = " "
@@ -326,8 +272,8 @@ class Word:
pass
frag = Fragment(
space + ins["if"],
self._resources["fonts"]["bold"],
color=base,
r.boldFont,
color=r.baseColor
)
line.addFragment(frag)
space = "; "
@@ -336,8 +282,8 @@ class Word:
line = Line()
frag = Fragment(
"; ".join(entry["lbs"]),
self._resources["fonts"]["bold"],
color=base,
r.boldFont,
color=r.baseColor
)
line.addFragment(frag)
lines.append(line)
@@ -345,13 +291,13 @@ class Word:
for k, v in value.items():
if k == "sseq": # has multiple 'senses'
for seq in v:
r = self.mw_seq(seq)
lines += r
rr = self.mw_seq(seq)
lines += rr
elif k == "vd":
line = Line()
line.addFragment(
Fragment(
v, self._resources["fonts"]["italic"], color=blue
v, r.italicFont, color=r.linkColor
)
)
lines.append(line)
@@ -361,7 +307,7 @@ class Word:
#
# Create the header, base word and its label
#
word = self.current["hwi"]["hw"]
word = self.current['definition']["hwi"]["hw"]
label = self.current["fl"]
html = f'<h1 class="def-word">{word} <span class="def-label">{label}</span></h1>\n'
@@ -383,7 +329,7 @@ class Word:
if "prs" in self.current["hwi"].keys():
tmp = []
for prs in self.current["hwi"]["prs"]:
url = self.mw_sound_url(prs)
url = QUrl()
how = prs["mw"]
if url:
tmp.append(f'<a href="{url}">\\{how}\\</a>')