Mostly working!
This commit is contained in:
14
deftest.py
14
deftest.py
@@ -5,7 +5,7 @@ import signal
|
|||||||
import sys
|
import sys
|
||||||
from typing import Any, cast
|
from typing import Any, cast
|
||||||
|
|
||||||
from PyQt6.QtCore import QResource, QSettings, Qt
|
from PyQt6.QtCore import QResource, QSettings, Qt, pyqtSlot
|
||||||
from PyQt6.QtGui import QFontDatabase
|
from PyQt6.QtGui import QFontDatabase
|
||||||
from PyQt6.QtSql import QSqlDatabase, QSqlQuery
|
from PyQt6.QtSql import QSqlDatabase, QSqlQuery
|
||||||
from PyQt6.QtWidgets import QApplication, QScrollArea
|
from PyQt6.QtWidgets import QApplication, QScrollArea
|
||||||
@@ -18,12 +18,20 @@ from lib.words import Definition
|
|||||||
class DefinitionArea(QScrollArea):
|
class DefinitionArea(QScrollArea):
|
||||||
def __init__(self, w: Word, *args: Any, **kwargs: Any) -> None:
|
def __init__(self, w: Word, *args: Any, **kwargs: Any) -> None:
|
||||||
super(DefinitionArea, self).__init__(*args, *kwargs)
|
super(DefinitionArea, self).__init__(*args, *kwargs)
|
||||||
d = Definition(w)
|
self.definition = Definition(w)
|
||||||
self.setWidget(d)
|
self.setWidget(self.definition)
|
||||||
self.setWidgetResizable(True)
|
self.setWidgetResizable(True)
|
||||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
|
||||||
|
self.definition.newWord.connect(self.newWord)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def newWord(self, word:str) -> None:
|
||||||
|
print(f"newWord: {word}")
|
||||||
|
w = Word(word)
|
||||||
|
self.definition.setWord(w)
|
||||||
|
return
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
settings = QSettings("Troglodite", "esl_reader")
|
settings = QSettings("Troglodite", "esl_reader")
|
||||||
settings.setValue("geometry", self.saveGeometry())
|
settings.setValue("geometry", self.saveGeometry())
|
||||||
|
|||||||
@@ -16,10 +16,16 @@ from PyQt6.QtGui import (
|
|||||||
QTextLayout,
|
QTextLayout,
|
||||||
QTextOption,
|
QTextOption,
|
||||||
)
|
)
|
||||||
|
from lib.sounds import SoundOff
|
||||||
from PyQt6.QtWidgets import QWidget
|
from PyQt6.QtWidgets import QWidget
|
||||||
from trycast import trycast
|
|
||||||
|
|
||||||
|
class MyPointF(QPointF):
|
||||||
|
def __repr__(self):
|
||||||
|
return f"({self.x()}, {self.y()})"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.__repr__()
|
||||||
|
|
||||||
class Fragment:
|
class Fragment:
|
||||||
"""A fragment of text to be displayed"""
|
"""A fragment of text to be displayed"""
|
||||||
|
|
||||||
@@ -117,12 +123,17 @@ class Fragment:
|
|||||||
painter.brush().setColor(Qt.GlobalColor.green)
|
painter.brush().setColor(Qt.GlobalColor.green)
|
||||||
for fmt in self._layout.formats():
|
for fmt in self._layout.formats():
|
||||||
if fmt.format.isAnchor():
|
if fmt.format.isAnchor():
|
||||||
#text = self._layout.text()[fmt.start:fmt.start+fmt.length]
|
|
||||||
runs = self._layout.glyphRuns(fmt.start, fmt.length)
|
runs = self._layout.glyphRuns(fmt.start, fmt.length)
|
||||||
bb = runs[0].boundingRect()
|
bb = runs[0].boundingRect()
|
||||||
bb.moveTo(bb.topLeft() + self._layout.position())
|
bb.moveTo(bb.topLeft() + self._layout.position())
|
||||||
painter.drawRect(bb)
|
url = QUrl(fmt.format.anchorHref())
|
||||||
#print(f"({bb.left()}-{bb.right()}, {bb.top()}-{bb.bottom()}): {text}")
|
if url.scheme() == 'audio':
|
||||||
|
painter.setPen(QColor('red'))
|
||||||
|
radius = (bb.topLeft() - bb.bottomLeft()).manhattanLength()/4
|
||||||
|
painter.drawRoundedRect(bb, radius,radius)
|
||||||
|
else:
|
||||||
|
painter.setPen(QColor("blue"))
|
||||||
|
#painter.drawRect(bb)
|
||||||
|
|
||||||
painter.restore()
|
painter.restore()
|
||||||
return QSize(int(size.width()), int(size.height()))
|
return QSize(int(size.width()), int(size.height()))
|
||||||
@@ -434,12 +445,16 @@ class Clickable(TypedDict):
|
|||||||
fmt: QTextCharFormat
|
fmt: QTextCharFormat
|
||||||
|
|
||||||
class Definition(QWidget):
|
class Definition(QWidget):
|
||||||
pronounce = pyqtSignal(str)
|
pronounce = pyqtSignal(QUrl)
|
||||||
|
alert = pyqtSignal()
|
||||||
|
newWord = pyqtSignal(str)
|
||||||
def __init__(
|
def __init__(
|
||||||
self, word: Optional[Any] = None, *args: Any, **kwargs: Any
|
self, word: Optional[Any] = None, *args: Any, **kwargs: Any
|
||||||
) -> None:
|
) -> None:
|
||||||
super(Definition, self).__init__(*args, **kwargs)
|
super(Definition, self).__init__(*args, **kwargs)
|
||||||
|
self._sound = SoundOff()
|
||||||
|
self.pronounce.connect(self._sound.playSound)
|
||||||
|
self.alert.connect(self._sound.alert)
|
||||||
self._word = word
|
self._word = word
|
||||||
if word is not None:
|
if word is not None:
|
||||||
self.setWord(word)
|
self.setWord(word)
|
||||||
@@ -450,7 +465,6 @@ class Definition(QWidget):
|
|||||||
lines: list[Line] = word.get_def()
|
lines: list[Line] = word.get_def()
|
||||||
assert lines is not None
|
assert lines is not None
|
||||||
self._lines = lines
|
self._lines = lines
|
||||||
self._buttons: list[Clickable] = []
|
|
||||||
base = 0
|
base = 0
|
||||||
|
|
||||||
for line in self._lines:
|
for line in self._lines:
|
||||||
@@ -474,12 +488,23 @@ class Definition(QWidget):
|
|||||||
def mousePressEvent(self, event: Optional[QMouseEvent]) -> None:
|
def mousePressEvent(self, event: Optional[QMouseEvent]) -> None:
|
||||||
if not event:
|
if not event:
|
||||||
return super().mousePressEvent(event)
|
return super().mousePressEvent(event)
|
||||||
print(f"mousePressEvent: {event.position()}")
|
position = MyPointF(event.position())
|
||||||
for clk in self._buttons:
|
print(f"mousePressEvent: {position}")
|
||||||
if clk["bb"].contains(event.position()):
|
for line in self._lines:
|
||||||
print("inside")
|
for frag in line.getLine():
|
||||||
self._downClickable = clk
|
layout = frag.layout()
|
||||||
return
|
for fmtRng in layout.formats():
|
||||||
|
if fmtRng.format.isAnchor():
|
||||||
|
runs = layout.glyphRuns(fmtRng.start, fmtRng.length)
|
||||||
|
assert len(runs) == 1
|
||||||
|
bb = runs[0].boundingRect()
|
||||||
|
bb.moveTo(bb.topLeft() + layout.position())
|
||||||
|
if bb.contains(event.position()):
|
||||||
|
self._downClickable = {
|
||||||
|
'bb': bb,
|
||||||
|
'fmt': fmtRng.format,
|
||||||
|
'frag': frag,
|
||||||
|
}
|
||||||
return super().mousePressEvent(event)
|
return super().mousePressEvent(event)
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event: Optional[QMouseEvent]) -> None:
|
def mouseReleaseEvent(self, event: Optional[QMouseEvent]) -> None:
|
||||||
@@ -490,9 +515,15 @@ class Definition(QWidget):
|
|||||||
):
|
):
|
||||||
print(f"mousePressPseudoEvent: {event.position()}")
|
print(f"mousePressPseudoEvent: {event.position()}")
|
||||||
clk = self._downClickable
|
clk = self._downClickable
|
||||||
bb = clk['bb']
|
url = QUrl(clk['fmt'].anchorHref())
|
||||||
print(f"({bb.left()}-{bb.right()}, {bb.top()}-{bb.bottom()})", clk["fmt"].anchorHref(),)
|
if url.scheme() == 'audio':
|
||||||
#self.pronounce.emit(audio)
|
url.setScheme('https')
|
||||||
|
self.pronounce.emit(url)
|
||||||
|
elif url.scheme() == 'word':
|
||||||
|
self.newWord.emit(url.path())
|
||||||
|
else:
|
||||||
|
print(f"{clk['fmt'].anchorHref()}: {url.scheme()}")
|
||||||
|
self.alert.emit()
|
||||||
self._downClickable = None
|
self._downClickable = None
|
||||||
return
|
return
|
||||||
self._downClickable = None
|
self._downClickable = None
|
||||||
@@ -510,29 +541,7 @@ class Definition(QWidget):
|
|||||||
#
|
#
|
||||||
# All text on this line needs to be on the same baseline
|
# All text on this line needs to be on the same baseline
|
||||||
#
|
#
|
||||||
buildButtons = (len(self._buttons) < 1)
|
|
||||||
|
|
||||||
assert self._lines is not None
|
assert self._lines is not None
|
||||||
for line in self._lines:
|
for line in self._lines:
|
||||||
line.paintEvent(painter)
|
line.paintEvent(painter)
|
||||||
if not buildButtons:
|
|
||||||
continue
|
|
||||||
for frag in line.getLine():
|
|
||||||
for fmtRng in frag.layout().formats():
|
|
||||||
if fmtRng.format.isAnchor():
|
|
||||||
runs = frag.layout().glyphRuns(fmtRng.start,fmtRng.start+fmtRng.length)
|
|
||||||
run = runs[0]
|
|
||||||
bb = run.boundingRect()
|
|
||||||
bb.moveTo(bb.topLeft() + frag.layout().position())
|
|
||||||
self._buttons.append(
|
|
||||||
{
|
|
||||||
'bb': bb,
|
|
||||||
'frag': frag,
|
|
||||||
'fmt': fmtRng.format,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
painter.setPen(QColor("cyan"))
|
|
||||||
for click in self._buttons:
|
|
||||||
if click['fmt'].isAnchor():
|
|
||||||
painter.drawRect(click['bb'])
|
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from PyQt6.QtNetwork import (
|
|||||||
QNetworkReply,
|
QNetworkReply,
|
||||||
QNetworkRequest,
|
QNetworkRequest,
|
||||||
)
|
)
|
||||||
|
from trycast import trycast
|
||||||
|
|
||||||
# from PyQt6.QtWidgets import QWidget
|
# from PyQt6.QtWidgets import QWidget
|
||||||
|
|
||||||
@@ -90,7 +91,6 @@ class SoundOff(QObject):
|
|||||||
self.virtualPlayer.errorOccurred.connect(self.mediaError)
|
self.virtualPlayer.errorOccurred.connect(self.mediaError)
|
||||||
self.virtualPlayer.mediaStatusChanged.connect(self.mediaStatus)
|
self.virtualPlayer.mediaStatusChanged.connect(self.mediaStatus)
|
||||||
self.virtualPlayer.playbackStateChanged.connect(self.playbackState)
|
self.virtualPlayer.playbackStateChanged.connect(self.playbackState)
|
||||||
self.nam.finished.connect(self.finished)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(QMediaPlayer.Error, str)
|
@pyqtSlot(QMediaPlayer.Error, str)
|
||||||
@@ -101,11 +101,13 @@ class SoundOff(QObject):
|
|||||||
|
|
||||||
@pyqtSlot(QMediaPlayer.MediaStatus)
|
@pyqtSlot(QMediaPlayer.MediaStatus)
|
||||||
def mediaStatus(self, status: QMediaPlayer.MediaStatus) -> None:
|
def mediaStatus(self, status: QMediaPlayer.MediaStatus) -> None:
|
||||||
# print(f"mediaStatus: {status}")
|
|
||||||
if status == QMediaPlayer.MediaStatus.LoadedMedia:
|
if status == QMediaPlayer.MediaStatus.LoadedMedia:
|
||||||
player: Optional[QMediaPlayer] = cast(QMediaPlayer, self.sender())
|
player = trycast(QMediaPlayer, self.sender())
|
||||||
|
if player is None:
|
||||||
|
player = trycast(QMediaPlayer, self.lastSender)
|
||||||
assert player is not None
|
assert player is not None
|
||||||
player.play()
|
player.play()
|
||||||
|
self.lastSender = self.sender()
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(QMediaPlayer.PlaybackState)
|
@pyqtSlot(QMediaPlayer.PlaybackState)
|
||||||
@@ -122,6 +124,7 @@ class SoundOff(QObject):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
|
@pyqtSlot(QUrl)
|
||||||
def playSound(self, url: str | QUrl) -> None:
|
def playSound(self, url: str | QUrl) -> None:
|
||||||
if isinstance(url, str):
|
if isinstance(url, str):
|
||||||
url = QUrl(url)
|
url = QUrl(url)
|
||||||
@@ -131,8 +134,10 @@ class SoundOff(QObject):
|
|||||||
self.virtualPlayer.setAudioOutput(self.virtualOutput)
|
self.virtualPlayer.setAudioOutput(self.virtualOutput)
|
||||||
if url != self._lastUrl:
|
if url != self._lastUrl:
|
||||||
request = QNetworkRequest(url)
|
request = QNetworkRequest(url)
|
||||||
self.nam.get(request)
|
reply = self.nam.get(request)
|
||||||
|
assert reply is not None
|
||||||
self._lastUrl = url
|
self._lastUrl = url
|
||||||
|
reply.finished.connect(self.finished)
|
||||||
return
|
return
|
||||||
for player in [self.localPlayer, self.virtualPlayer]:
|
for player in [self.localPlayer, self.virtualPlayer]:
|
||||||
if not player:
|
if not player:
|
||||||
@@ -154,23 +159,25 @@ class SoundOff(QObject):
|
|||||||
_buffer: dict[QMediaPlayer, QBuffer] = {}
|
_buffer: dict[QMediaPlayer, QBuffer] = {}
|
||||||
_lastUrl = QUrl()
|
_lastUrl = QUrl()
|
||||||
|
|
||||||
@pyqtSlot(QNetworkReply)
|
@pyqtSlot()
|
||||||
def finished(self, reply: QNetworkReply) -> None:
|
def finished(self) -> None:
|
||||||
storage = reply.readAll()
|
reply = trycast(QNetworkReply, self.sender())
|
||||||
|
assert reply is not None
|
||||||
|
code = reply.attribute(QNetworkRequest.Attribute.HttpStatusCodeAttribute)
|
||||||
|
print(f"HttpStatusCodeAttribute: {code}, error: {reply.error()}")
|
||||||
|
self._reply = reply.readAll()
|
||||||
|
url = reply.request().url()
|
||||||
reply.close()
|
reply.close()
|
||||||
crypto = QCryptographicHash(QCryptographicHash.Algorithm.Sha256)
|
if self._reply.isEmpty() or self._reply.isNull():
|
||||||
|
return
|
||||||
for player in [self.localPlayer, self.virtualPlayer]:
|
for player in [self.localPlayer, self.virtualPlayer]:
|
||||||
if not player:
|
if not player:
|
||||||
continue
|
continue
|
||||||
self._storage[player] = QByteArray(storage)
|
self._storage[player] = QByteArray(self._reply)
|
||||||
crypto.addData(self._storage[player])
|
|
||||||
# print(player, crypto.result().toHex())
|
|
||||||
crypto.reset()
|
|
||||||
self._buffer[player] = QBuffer(self._storage[player])
|
self._buffer[player] = QBuffer(self._storage[player])
|
||||||
url = reply.request().url()
|
|
||||||
player.setSourceDevice(self._buffer[player], url)
|
player.setSourceDevice(self._buffer[player], url)
|
||||||
player.setPosition(0)
|
player.setPosition(0)
|
||||||
if player.mediaStatus() == QMediaPlayer.MediaStatus.LoadedMedia:
|
if player.mediaStatus() == QMediaPlayer.MediaStatus.LoadedMedia:
|
||||||
player.play()
|
player.play()
|
||||||
# print("play")
|
print("play")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -151,6 +151,17 @@ class DefinitionSection(TypedDict):
|
|||||||
sls: NotRequired[list[str]]
|
sls: NotRequired[list[str]]
|
||||||
sseq: Any # list[list[Pair]]
|
sseq: Any # list[list[Pair]]
|
||||||
|
|
||||||
|
class UndefinedRunOn(TypedDict):
|
||||||
|
ure: str
|
||||||
|
fl: str
|
||||||
|
utxt: NotRequired[list[list[Pair]]]
|
||||||
|
ins: NotRequired[list[Inflection]]
|
||||||
|
lbs: NotRequired[list[str]]
|
||||||
|
prs: NotRequired[list[Pronunciation]]
|
||||||
|
sls: NotRequired[list[str]]
|
||||||
|
vrs: NotRequired[list[Variant]]
|
||||||
|
|
||||||
|
|
||||||
DefinedRunOn = TypedDict(
|
DefinedRunOn = TypedDict(
|
||||||
"DefinedRunOn",
|
"DefinedRunOn",
|
||||||
{
|
{
|
||||||
@@ -287,7 +298,7 @@ def fetch(word: str) -> WordType:
|
|||||||
|
|
||||||
def soundUrl(sound: Sound, fmt="ogg") -> QUrl:
|
def soundUrl(sound: Sound, fmt="ogg") -> QUrl:
|
||||||
"""Create a URL from a PRS structure."""
|
"""Create a URL from a PRS structure."""
|
||||||
base = f"https://media.merriam-webster.com/audio/prons/en/us/{fmt}"
|
base = f"audio://media.merriam-webster.com/audio/prons/en/us/{fmt}"
|
||||||
audio = sound["audio"]
|
audio = sound["audio"]
|
||||||
m = re.match(r"(bix|gg|[a-zA-Z])", audio)
|
m = re.match(r"(bix|gg|[a-zA-Z])", audio)
|
||||||
if m:
|
if m:
|
||||||
@@ -345,10 +356,26 @@ def do_prs(frag: Fragment, prs: list[Pronunciation] | None) -> None:
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def do_aq(aq: AttributionOfQuote | None) -> list[Line]:
|
def do_aq(aq: AttributionOfQuote | None) -> Line:
|
||||||
assert aq is not None
|
assert aq is not None
|
||||||
raise NotImplementedError("aq")
|
r = Resources()
|
||||||
return []
|
frag = Fragment()
|
||||||
|
if 'auth' in aq:
|
||||||
|
frag.addText(aq['auth']+', ', r.subduedFormat)
|
||||||
|
if 'source' in aq:
|
||||||
|
frag.addText(aq['source'], r.subduedFormat)
|
||||||
|
if 'aqdate' in aq:
|
||||||
|
frag.addText(', '+aq['aqdate'], r.subduedFormat)
|
||||||
|
if 'subsource' in aq:
|
||||||
|
ss = trycast(SubSource, aq['subsource'])
|
||||||
|
assert ss is not None
|
||||||
|
if 'source' in ss:
|
||||||
|
frag.addText(', '+ss['source'], r.subduedFormat)
|
||||||
|
if 'aqdate' in ss:
|
||||||
|
frag.addText(', '+ss['aqdate'], r.subduedFormat)
|
||||||
|
line = Line()
|
||||||
|
line.addFragment(frag)
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
def do_vis(vis: list[VerbalIllustration] | None, indent=0) -> list[Line]:
|
def do_vis(vis: list[VerbalIllustration] | None, indent=0) -> list[Line]:
|
||||||
@@ -364,7 +391,7 @@ def do_vis(vis: list[VerbalIllustration] | None, indent=0) -> list[Line]:
|
|||||||
line.addFragment(frag)
|
line.addFragment(frag)
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
if "aq" in vi:
|
if "aq" in vi:
|
||||||
lines += do_aq(trycast(AttributionOfQuote, vi["aq"]))
|
lines.append(do_aq(trycast(AttributionOfQuote, vi["aq"])))
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
@@ -688,7 +715,32 @@ def do_dros(dros: list[DefinedRunOn]|None) -> list[Line]:
|
|||||||
raise NotImplementedError(f"Key of {k}")
|
raise NotImplementedError(f"Key of {k}")
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
def do_uros(uros: list[UndefinedRunOn]|None) -> list[Line]:
|
||||||
|
assert uros is not None
|
||||||
|
r = Resources()
|
||||||
|
lines: list[Line] = []
|
||||||
|
for uro in uros:
|
||||||
|
frag = Fragment()
|
||||||
|
text = re.sub(r'\*', '', uro['ure'])
|
||||||
|
frag.addText(text, r.labelFormat)
|
||||||
|
if 'prs' in uro:
|
||||||
|
do_prs(frag, uro['prs'])
|
||||||
|
frag.addText(' '+uro['fl'],r.textFormat) # r.linkFormat
|
||||||
|
line = Line()
|
||||||
|
line.addFragment(frag)
|
||||||
|
lines.append(line)
|
||||||
|
if 'utxt' in uro:
|
||||||
|
for entry in uro['utxt']:
|
||||||
|
for pair in entry:
|
||||||
|
if pair['objType'] == 'vis':
|
||||||
|
lines += do_vis(trycast(list[VerbalIllustration], pair['obj']))
|
||||||
|
elif pair['objType'] == 'uns':
|
||||||
|
(newFrags, newLines) = do_uns(trycast(list[list[list[Pair]]],pair['obj']),0)
|
||||||
|
line = Line()
|
||||||
|
line.addFragment(newFrags)
|
||||||
|
lines.append(line)
|
||||||
|
lines += newLines
|
||||||
|
return lines
|
||||||
def getDef(defines: Any) -> list[Line]:
|
def getDef(defines: Any) -> list[Line]:
|
||||||
Line.setParseText(parseText)
|
Line.setParseText(parseText)
|
||||||
workList = restructure(defines)
|
workList = restructure(defines)
|
||||||
@@ -786,6 +838,10 @@ def getDef(defines: Any) -> list[Line]:
|
|||||||
lines += do_def(define)
|
lines += do_def(define)
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
raise
|
raise
|
||||||
|
if "uros" in work:
|
||||||
|
print(json.dumps(work['uros'],indent=2))
|
||||||
|
uros = trycast(list[UndefinedRunOn], work['uros'])
|
||||||
|
lines += do_uros(uros)
|
||||||
if "dros" in work:
|
if "dros" in work:
|
||||||
dros = trycast(list[DefinedRunOn], work["dros"])
|
dros = trycast(list[DefinedRunOn], work["dros"])
|
||||||
if len(phrases) < 1:
|
if len(phrases) < 1:
|
||||||
@@ -815,6 +871,7 @@ def getDef(defines: Any) -> list[Line]:
|
|||||||
"shortdef",
|
"shortdef",
|
||||||
"vrs",
|
"vrs",
|
||||||
"dros",
|
"dros",
|
||||||
|
'uros',
|
||||||
]:
|
]:
|
||||||
raise NotImplementedError(f"Unknown key {k} in work")
|
raise NotImplementedError(f"Unknown key {k} in work")
|
||||||
if len(phrases) > 0:
|
if len(phrases) > 0:
|
||||||
@@ -845,10 +902,10 @@ def replaceCode(code:str) -> tuple[str, QTextCharFormat]:
|
|||||||
token = fields[0]
|
token = fields[0]
|
||||||
if token == 'a_link':
|
if token == 'a_link':
|
||||||
text = fields[1]
|
text = fields[1]
|
||||||
fmt.setAnchorHref(fields[1])
|
fmt.setAnchorHref('auto://'+fields[1])
|
||||||
elif token in ['d_link', 'et_link', 'mat', 'sx', 'i_link']:
|
elif token in ['d_link', 'et_link', 'mat', 'sx', 'i_link']:
|
||||||
text = fields[1]
|
text = fields[1]
|
||||||
pre = 'word://'
|
pre = 'word:///'
|
||||||
if fields[2] == '':
|
if fields[2] == '':
|
||||||
fmt.setAnchorHref(pre+fields[1])
|
fmt.setAnchorHref(pre+fields[1])
|
||||||
else:
|
else:
|
||||||
@@ -859,18 +916,18 @@ def replaceCode(code:str) -> tuple[str, QTextCharFormat]:
|
|||||||
fmt.setFontCapitalization(QFont.Capitalization.SmallCaps)
|
fmt.setFontCapitalization(QFont.Capitalization.SmallCaps)
|
||||||
elif token == 'dxt':
|
elif token == 'dxt':
|
||||||
if fields[3] == 'illustration':
|
if fields[3] == 'illustration':
|
||||||
fmt.setAnchorHref('article://'+fields[2])
|
fmt.setAnchorHref('article:///'+fields[2])
|
||||||
elif fields[3] == 'table':
|
elif fields[3] == 'table':
|
||||||
fmt.setAnchorHref('table://'+fields[2])
|
fmt.setAnchorHref('table:///'+fields[2])
|
||||||
elif fields[3] != "":
|
elif fields[3] != "":
|
||||||
fmt.setAnchorHref('sense://'+fields[3])
|
fmt.setAnchorHref('sense:///'+fields[3])
|
||||||
else:
|
else:
|
||||||
fmt.setAnchorHref('word://'+fields[1])
|
fmt.setAnchorHref('word:///'+fields[1])
|
||||||
elif token == 'et_link':
|
elif token == 'et_link':
|
||||||
if fields[2] != '':
|
if fields[2] != '':
|
||||||
fmt.setAnchorHref('etymology://'+fields[2])
|
fmt.setAnchorHref('etymology:///'+fields[2])
|
||||||
else:
|
else:
|
||||||
fmt.setAnchorHref('etymology://' + fields[1])
|
fmt.setAnchorHref('etymology:///' + fields[1])
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(f"Token {code} not implimented")
|
raise NotImplementedError(f"Token {code} not implimented")
|
||||||
fmt.setForeground(r.linkColor)
|
fmt.setForeground(r.linkColor)
|
||||||
|
|||||||
Reference in New Issue
Block a user