Almost there
This commit is contained in:
24
deftest.py
24
deftest.py
@@ -3,7 +3,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from PyQt6.QtCore import QResource
|
from PyQt6.QtCore import QResource, QSettings
|
||||||
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
|
from PyQt6.QtWidgets import QApplication
|
||||||
@@ -22,15 +22,31 @@ def main() -> int:
|
|||||||
raise Exception(db.lastError())
|
raise Exception(db.lastError())
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
#
|
#
|
||||||
|
# Set Default settings
|
||||||
|
#
|
||||||
|
settings = QSettings('Troglodite', 'esl_reader')
|
||||||
|
settings.beginGroup('font')
|
||||||
|
if not settings.contains('display/url'):
|
||||||
|
settings.setValue('display/url', ':/fonts/opendyslexic/OpenDyslexic-Regular.otf')
|
||||||
|
if not settings.contains('display/name'):
|
||||||
|
settings.setValue('display/name', 'OpenDyslexic')
|
||||||
|
if not settings.contains('phonic/name'):
|
||||||
|
settings.setValue('phonic/name', 'Gentium')
|
||||||
|
settings.endGroup()
|
||||||
|
if not settings.contains('keys/mw-api'):
|
||||||
|
settings.setValue('keys/mw-api','51d9df34-ee13-489e-8656-478c215e846c')
|
||||||
|
#
|
||||||
# Setup resources
|
# Setup resources
|
||||||
#
|
#
|
||||||
if not QResource.registerResource(
|
if not QResource.registerResource(
|
||||||
os.path.join(os.path.dirname(__file__), "ui/resources.rcc"), "/"
|
os.path.join(os.path.dirname(__file__), "ui/resources.rcc"), "/"
|
||||||
):
|
):
|
||||||
raise Exception("Unable to register resources.rcc")
|
raise Exception("Unable to register resources.rcc")
|
||||||
QFontDatabase.addApplicationFont(
|
settings.beginGroup('font')
|
||||||
":/fonts/opendyslexic/OpenDyslexic-Regular.otf"
|
for name in settings.childGroups():
|
||||||
)
|
if settings.contains(f'{name}/url'):
|
||||||
|
QFontDatabase.addApplicationFont(settings.value(f'{name}/url'))
|
||||||
|
settings.endGroup()
|
||||||
query = QSqlQuery()
|
query = QSqlQuery()
|
||||||
if not query.exec(
|
if not query.exec(
|
||||||
"CREATE TABLE IF NOT EXISTS words "
|
"CREATE TABLE IF NOT EXISTS words "
|
||||||
|
|||||||
230
lib/words.py
230
lib/words.py
@@ -4,7 +4,7 @@ import re
|
|||||||
from typing import Any, Optional, cast
|
from typing import Any, Optional, cast
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from PyQt6.QtCore import QPoint, QRect, QUrl, Qt, pyqtSignal
|
from PyQt6.QtCore import QMargins, QPoint, QRect, QSize, QUrl, Qt, pyqtSignal
|
||||||
from PyQt6.QtGui import (
|
from PyQt6.QtGui import (
|
||||||
QBrush,
|
QBrush,
|
||||||
QColor,
|
QColor,
|
||||||
@@ -40,13 +40,14 @@ class Fragment:
|
|||||||
Qt.AlignmentFlag.AlignLeft
|
Qt.AlignmentFlag.AlignLeft
|
||||||
| Qt.AlignmentFlag.AlignBaseline
|
| Qt.AlignmentFlag.AlignBaseline
|
||||||
)
|
)
|
||||||
self._padding = [0, 0, 0, 0]
|
self._padding = QMargins()
|
||||||
self._border = [0, 0, 0, 0]
|
self._border = QMargins()
|
||||||
self._margin = [0, 0, 0, 0]
|
self._margin = QMargins()
|
||||||
self._wref = ''
|
self._wref = ''
|
||||||
self._position = QPoint()
|
self._position = QPoint()
|
||||||
self._rect = QRect()
|
self._rect = QRect()
|
||||||
self._borderRect = QRect()
|
self._borderRect = QRect()
|
||||||
|
self._clickRect = QRect()
|
||||||
if color:
|
if color:
|
||||||
self._color = color
|
self._color = color
|
||||||
else:
|
else:
|
||||||
@@ -56,20 +57,40 @@ class Fragment:
|
|||||||
return
|
return
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self._text
|
return self.__repr__()
|
||||||
|
|
||||||
|
def size(self, width:int) -> QSize:
|
||||||
|
rect = QRect(self._position,QSize(width,2000))
|
||||||
|
flags = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignBaseline | Qt.TextFlag.TextWordWrap
|
||||||
|
fm = QFontMetrics(self._font)
|
||||||
|
bounding = fm.boundingRect(rect, flags, self._text)
|
||||||
|
size = bounding.size()
|
||||||
|
size = size.grownBy(self._padding)
|
||||||
|
size = size.grownBy(self._border)
|
||||||
|
size = size.grownBy(self._margin)
|
||||||
|
return size
|
||||||
|
|
||||||
|
def height(self, width: int) -> int:
|
||||||
|
return self.size(width).height()
|
||||||
|
|
||||||
|
def width(self, width:int) -> int:
|
||||||
|
return self.size(width).width()
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f'({self._position.x()}, {self._position.y()}): {self._text}'
|
||||||
|
|
||||||
def repaintEvent(self, painter:QPainter) -> int:
|
def repaintEvent(self, painter:QPainter) -> int:
|
||||||
painter.save()
|
painter.save()
|
||||||
painter.setFont(self._font)
|
painter.setFont(self._font)
|
||||||
painter.setPen(self._color)
|
painter.setPen(self._color)
|
||||||
rect = QRect()
|
rect = QRect()
|
||||||
rect.setLeft(self._position.x())
|
rect.setLeft(self._position.x())
|
||||||
rect.setTop(self._position.y() - painter.fontMetrics().ascent())
|
rect.setTop(self._position.y() + painter.fontMetrics().descent() - painter.fontMetrics().height())
|
||||||
rect.setWidth(painter.viewport().width() - self._position.x())
|
rect.setWidth(painter.viewport().width() - self._position.x())
|
||||||
rect.setHeight(2000)
|
rect.setHeight(2000)
|
||||||
flags = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignBaseline | Qt.TextFlag.TextWordWrap
|
flags = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignBaseline | Qt.TextFlag.TextWordWrap
|
||||||
bounding = painter.boundingRect(rect,flags, self._text)
|
bounding = painter.boundingRect(rect,flags, self._text)
|
||||||
height = bounding.height()+self._padding[2]+self._border[2]+self._margin[2]
|
size = bounding.size()
|
||||||
|
|
||||||
painter.setPen(QColor("#f00"))
|
painter.setPen(QColor("#f00"))
|
||||||
if self._audio.isValid():
|
if self._audio.isValid():
|
||||||
@@ -86,7 +107,10 @@ class Fragment:
|
|||||||
self._text
|
self._text
|
||||||
)
|
)
|
||||||
painter.restore()
|
painter.restore()
|
||||||
return height
|
size = size.grownBy(self._margin)
|
||||||
|
size = size.grownBy(self._border)
|
||||||
|
size = size.grownBy(self._padding)
|
||||||
|
return size.height()
|
||||||
#
|
#
|
||||||
# Setters
|
# Setters
|
||||||
#
|
#
|
||||||
@@ -108,71 +132,88 @@ class Fragment:
|
|||||||
def setRect(self,rect:QRect) -> None:
|
def setRect(self,rect:QRect) -> None:
|
||||||
self._rect = rect
|
self._rect = rect
|
||||||
return
|
return
|
||||||
def setPadding(self, top:int = -1, right:int = -1, bottom:int = -1, left:int = -1, *args:int) -> None:
|
def setPadding(self, *args:int, **kwargs:int) -> None:
|
||||||
|
top = kwargs.get('top', -1)
|
||||||
|
right = kwargs.get('right', -1)
|
||||||
|
bottom = kwargs.get('bottom', -1)
|
||||||
|
left = kwargs.get('left', -1)
|
||||||
if top > -1 or right > -1 or bottom > -1 or left > -1:
|
if top > -1 or right > -1 or bottom > -1 or left > -1:
|
||||||
if top >= 0:
|
if top >= 0:
|
||||||
self._padding[0] = top
|
self._padding.setTop(top)
|
||||||
if right >= 0:
|
if right >= 0:
|
||||||
self._padding[1] = right
|
self._padding.setRight(right)
|
||||||
if bottom >= 0:
|
if bottom >= 0:
|
||||||
self._padding[2] = bottom
|
self._padding.setBottom(bottom)
|
||||||
if left >= 0:
|
if left >= 0:
|
||||||
self._padding[3] = left
|
self._padding.setLeft(left)
|
||||||
return
|
return
|
||||||
if len(args) == 4:
|
if len(args) == 4:
|
||||||
self._padding = [args[0], args[1], args[2], args[3]]
|
(top, right, bottom, left) = [args[0], args[1], args[2], args[3]]
|
||||||
elif len(args) == 3:
|
elif len(args) == 3:
|
||||||
self._padding = [args[0], args[1], args[2], args[1]]
|
(top, right, bottom, left) = [args[0], args[1], args[2], args[1]]
|
||||||
elif len(args) == 2:
|
elif len(args) == 2:
|
||||||
self._padding = [args[0], args[1], args[0], args[1]]
|
(top, right, bottom, left) = [args[0], args[1], args[0], args[1]]
|
||||||
elif len(args) == 1:
|
elif len(args) == 1:
|
||||||
self._padding = [args[0], args[0], args[0], args[0]]
|
(top, right, bottom, left) = [args[0], args[0], args[0], args[0]]
|
||||||
else:
|
else:
|
||||||
raise Exception("argument error")
|
raise Exception("argument error")
|
||||||
|
self._padding = QMargins(left, top, right, bottom)
|
||||||
return
|
return
|
||||||
def setBorder(self, top:int = -1, right:int = -1, bottom:int = -1, left:int = -1, *args:int) -> None:
|
|
||||||
|
def setBorder(self, *args:int, **kwargs:int) -> None:
|
||||||
|
top = kwargs.get('top', -1)
|
||||||
|
right = kwargs.get('right', -1)
|
||||||
|
bottom = kwargs.get('bottom', -1)
|
||||||
|
left = kwargs.get('left', -1)
|
||||||
if top > -1 or right > -1 or bottom > -1 or left > -1:
|
if top > -1 or right > -1 or bottom > -1 or left > -1:
|
||||||
if top >= 0:
|
if top >= 0:
|
||||||
self._border[0] = top
|
self._border.setTop(top)
|
||||||
if right >= 0:
|
if right >= 0:
|
||||||
self._border[1] = right
|
self._border.setRight(right)
|
||||||
if bottom >= 0:
|
if bottom >= 0:
|
||||||
self._border[2] = bottom
|
self._border.setBottom(bottom)
|
||||||
if left >= 0:
|
if left >= 0:
|
||||||
self._border[3] = left
|
self._border.setLeft(left)
|
||||||
return
|
return
|
||||||
if len(args) == 4:
|
if len(args) == 4:
|
||||||
self._border = [args[0], args[1], args[2], args[3]]
|
(top, right, bottom, left) = [args[0], args[1], args[2], args[3]]
|
||||||
elif len(args) == 3:
|
elif len(args) == 3:
|
||||||
self._border = [args[0], args[1], args[2], args[1]]
|
(top, right, bottom, left) = [args[0], args[1], args[2], args[1]]
|
||||||
elif len(args) == 2:
|
elif len(args) == 2:
|
||||||
self._border = [args[0], args[1], args[0], args[1]]
|
(top, right, bottom, left) = [args[0], args[1], args[0], args[1]]
|
||||||
elif len(args) == 1:
|
elif len(args) == 1:
|
||||||
self._border = [args[0], args[0], args[0], args[0]]
|
(top, right, bottom, left) = [args[0], args[0], args[0], args[0]]
|
||||||
else:
|
else:
|
||||||
raise Exception("argument error")
|
raise Exception("argument error")
|
||||||
|
self._border = QMargins(left, top, right, bottom)
|
||||||
return
|
return
|
||||||
def setMargin(self, top:int = -1, right:int = -1, bottom:int = -1, left:int = -1, *args:int) -> None:
|
def setMargin(self, *args:int, **kwargs:int) -> None:
|
||||||
|
top = kwargs.get('top', -1)
|
||||||
|
right = kwargs.get('right', -1)
|
||||||
|
bottom = kwargs.get('bottom', -1)
|
||||||
|
left = kwargs.get('left', -1)
|
||||||
|
|
||||||
if top > -1 or right > -1 or bottom > -1 or left > -1:
|
if top > -1 or right > -1 or bottom > -1 or left > -1:
|
||||||
if top >= 0:
|
if top >= 0:
|
||||||
self._margin[0] = top
|
self._margin.setTop(top)
|
||||||
if right >= 0:
|
if right >= 0:
|
||||||
self._margin[1] = right
|
self._margin.setRight(right)
|
||||||
if bottom >= 0:
|
if bottom >= 0:
|
||||||
self._margin[2] = bottom
|
self._margin.setBottom(bottom)
|
||||||
if left >= 0:
|
if left >= 0:
|
||||||
self._margin[3] = left
|
self._margin.setLeft(left)
|
||||||
return
|
return
|
||||||
if len(args) == 4:
|
if len(args) == 4:
|
||||||
self._margin = [args[0], args[1], args[2], args[3]]
|
(top, right, bottom, left) =[args[0], args[1], args[2], args[3]]
|
||||||
elif len(args) == 3:
|
elif len(args) == 3:
|
||||||
self._margin = [args[0], args[1], args[2], args[1]]
|
(top, right, bottom, left) = [args[0], args[1], args[2], args[1]]
|
||||||
elif len(args) == 2:
|
elif len(args) == 2:
|
||||||
self._margin = [args[0], args[1], args[0], args[1]]
|
(top, right, bottom, left) = [args[0], args[1], args[0], args[1]]
|
||||||
elif len(args) == 1:
|
elif len(args) == 1:
|
||||||
self._margin = [args[0], args[0], args[0], args[0]]
|
(top, right, bottom, left) = [args[0], args[0], args[0], args[0]]
|
||||||
else:
|
else:
|
||||||
raise Exception("argument error")
|
raise Exception("argument error")
|
||||||
|
self._margin = QMargins(left, top, right, bottom)
|
||||||
return
|
return
|
||||||
def setWRef(self, ref:str) -> None:
|
def setWRef(self, ref:str) -> None:
|
||||||
self._wref = ref
|
self._wref = ref
|
||||||
@@ -183,6 +224,9 @@ class Fragment:
|
|||||||
def setBorderRect(self, rect:QRect) -> None:
|
def setBorderRect(self, rect:QRect) -> None:
|
||||||
self._borderRect = rect
|
self._borderRect = rect
|
||||||
return
|
return
|
||||||
|
def setClickRect(self, rect:QRect) -> None:
|
||||||
|
self._clickRect = rect
|
||||||
|
return
|
||||||
def setColor(self,color:QColor) -> None:
|
def setColor(self,color:QColor) -> None:
|
||||||
self._color = color
|
self._color = color
|
||||||
return
|
return
|
||||||
@@ -204,16 +248,18 @@ class Fragment:
|
|||||||
return self._align
|
return self._align
|
||||||
def rect(self) -> QRect:
|
def rect(self) -> QRect:
|
||||||
return self._rect
|
return self._rect
|
||||||
def padding(self) -> list[int]:
|
def padding(self) -> QMargins:
|
||||||
return self._padding
|
return self._padding
|
||||||
def border(self) -> list[int]:
|
def border(self) -> QMargins:
|
||||||
return self._border
|
return self._border
|
||||||
def margin(self) -> list[int]:
|
def margin(self) -> QMargins:
|
||||||
return self._margin
|
return self._margin
|
||||||
def position(self) -> QPoint:
|
def position(self) -> QPoint:
|
||||||
return self._position
|
return self._position
|
||||||
def borderRect(self) -> QRect:
|
def borderRect(self) -> QRect:
|
||||||
return self._borderRect
|
return self._borderRect
|
||||||
|
def clickRect(self) -> QRect:
|
||||||
|
return self._clickRect
|
||||||
def color(self) -> QColor:
|
def color(self) -> QColor:
|
||||||
return self._color
|
return self._color
|
||||||
def asis(self) -> bool:
|
def asis(self) -> bool:
|
||||||
@@ -387,7 +433,7 @@ class Word:
|
|||||||
def addFragment(self, frag: Fragment,) -> None:
|
def addFragment(self, frag: Fragment,) -> None:
|
||||||
SPEAKER = "\U0001F508"
|
SPEAKER = "\U0001F508"
|
||||||
|
|
||||||
if frag.audio():
|
if frag.audio().isValid():
|
||||||
frag.setText(frag.text() + ' ' + SPEAKER)
|
frag.setText(frag.text() + ' ' + SPEAKER)
|
||||||
|
|
||||||
text = frag.text()
|
text = frag.text()
|
||||||
@@ -396,14 +442,14 @@ class Word:
|
|||||||
text = re.sub(r"\{rdquo\}", "\u201d", text)
|
text = re.sub(r"\{rdquo\}", "\u201d", text)
|
||||||
frag.setText(text)
|
frag.setText(text)
|
||||||
if frag.audio().isValid():
|
if frag.audio().isValid():
|
||||||
frag.setPadding(3)
|
frag.setPadding(3,0,0,5)
|
||||||
frag.setBorder(1)
|
frag.setBorder(1)
|
||||||
frag.setMargin(2)
|
frag.setMargin(0,0,0,0)
|
||||||
items = self.parseText(frag)
|
items = self.parseText(frag)
|
||||||
self._fragments += items
|
self._fragments += items
|
||||||
return
|
return
|
||||||
|
|
||||||
def finalizeLine(self) -> None:
|
def finalizeLine(self, width: int, base:int ) -> None:
|
||||||
"""Create all of the positions for all the fragments."""
|
"""Create all of the positions for all the fragments."""
|
||||||
#
|
#
|
||||||
# Find the maximum hight and max baseline
|
# Find the maximum hight and max baseline
|
||||||
@@ -413,23 +459,10 @@ class Word:
|
|||||||
leading = -1
|
leading = -1
|
||||||
for frag in self._fragments:
|
for frag in self._fragments:
|
||||||
fm = QFontMetrics(frag.font())
|
fm = QFontMetrics(frag.font())
|
||||||
rect = fm.boundingRect(frag.text(), frag.align())
|
height = frag.height(width)
|
||||||
height = rect.height()
|
bl = fm.height() - fm.descent()
|
||||||
bl = height - fm.descent()
|
|
||||||
if fm.leading() > leading:
|
if fm.leading() > leading:
|
||||||
leading = fm.leading()
|
leading = fm.leading()
|
||||||
#
|
|
||||||
# Add the padding, border and margin to adjust the baseline and height
|
|
||||||
#
|
|
||||||
b = frag.padding()
|
|
||||||
height += b[0] + b[2]
|
|
||||||
bl += b[2]
|
|
||||||
b = frag.border()
|
|
||||||
height += b[0] + b[2]
|
|
||||||
bl += b[2]
|
|
||||||
b = frag.margin()
|
|
||||||
height += b[0] + b[2]
|
|
||||||
bl += b[2]
|
|
||||||
if height > maxHeight:
|
if height > maxHeight:
|
||||||
maxHeight = height
|
maxHeight = height
|
||||||
if bl > baseLine:
|
if bl > baseLine:
|
||||||
@@ -441,19 +474,16 @@ class Word:
|
|||||||
for frag in self._fragments:
|
for frag in self._fragments:
|
||||||
if x < frag.left():
|
if x < frag.left():
|
||||||
x = frag.left()
|
x = frag.left()
|
||||||
|
#
|
||||||
|
# We need to calculate the location to draw the
|
||||||
|
# text. We also need to calculate the bounding Rectangle
|
||||||
|
# for this fragment
|
||||||
|
#
|
||||||
|
size = frag.size(width)
|
||||||
fm = QFontMetrics(frag.font())
|
fm = QFontMetrics(frag.font())
|
||||||
width = fm.horizontalAdvance(frag.text())
|
offset = frag.margin().left() + frag.border().left() + frag.padding().left()
|
||||||
padding = frag.padding()
|
|
||||||
offset = padding[3] # Left margin
|
|
||||||
width += padding[1] + padding[3]
|
|
||||||
border = frag.border()
|
|
||||||
offset += border[3]
|
|
||||||
width += border[1] + border[3]
|
|
||||||
margin = frag.margin()
|
|
||||||
offset += margin[3]
|
|
||||||
width += margin[1] + margin[3]
|
|
||||||
frag.setPosition(QPoint(x+offset, self._baseLine))
|
frag.setPosition(QPoint(x+offset, self._baseLine))
|
||||||
if frag.border()[0] != 0:
|
if not frag.border().isNull() or not frag.wRef():
|
||||||
#
|
#
|
||||||
# self._baseLine is where the text will be drawn
|
# self._baseLine is where the text will be drawn
|
||||||
# fm.descent is the distance from the baseline of the
|
# fm.descent is the distance from the baseline of the
|
||||||
@@ -462,16 +492,20 @@ class Word:
|
|||||||
# + fm.descent - rect.height
|
# + fm.descent - rect.height
|
||||||
# The border is drawn at top-padding-border-margin+marin
|
# The border is drawn at top-padding-border-margin+marin
|
||||||
#
|
#
|
||||||
top = self._baseLine + fm.descent() - rect.height() -1
|
top = self._baseLine + fm.descent() - fm.height()
|
||||||
y = top - padding[0] - border[0]
|
y = top - frag.padding().top() - frag.border().top()
|
||||||
frag.setBorderRect(QRect(x+margin[3], y, width, height))
|
pos = QPoint(x, y)
|
||||||
x += width
|
rect = QRect(pos, size.shrunkBy(frag.margin()))
|
||||||
|
frag.setBorderRect(rect)
|
||||||
|
pos.setY(pos.y()+base)
|
||||||
|
frag.setClickRect(QRect(pos, size.shrunkBy(frag.margin())))
|
||||||
|
x += size.width()
|
||||||
return
|
return
|
||||||
|
|
||||||
def getLine(self) -> list[Fragment]:
|
def getLine(self) -> list[Fragment]:
|
||||||
return self._fragments
|
return self._fragments
|
||||||
|
|
||||||
def getLeading(self) -> int:
|
def getLineSpacing(self) -> int:
|
||||||
return self._leading + self._maxHeight
|
return self._leading + self._maxHeight
|
||||||
|
|
||||||
_lines: list[Line] = []
|
_lines: list[Line] = []
|
||||||
@@ -499,6 +533,10 @@ class Word:
|
|||||||
}
|
}
|
||||||
self.current = Word._words[word]
|
self.current = Word._words[word]
|
||||||
return
|
return
|
||||||
|
#
|
||||||
|
# The code should look at our settings to see if we have an API
|
||||||
|
# key for MW to decide on the source to use.
|
||||||
|
#
|
||||||
source = 'mw'
|
source = 'mw'
|
||||||
response = requests.get(MWAPI.format(word=word))
|
response = requests.get(MWAPI.format(word=word))
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
@@ -679,14 +717,11 @@ class Word:
|
|||||||
frag = Fragment(entry['hwi']['hw'] + ' ', self.resources['fonts']['phonic'], color=base)
|
frag = Fragment(entry['hwi']['hw'] + ' ', self.resources['fonts']['phonic'], color=base)
|
||||||
line.addFragment(frag)
|
line.addFragment(frag)
|
||||||
for prs in entry["hwi"]["prs"]:
|
for prs in entry["hwi"]["prs"]:
|
||||||
audio = self.sound_url(prs)
|
audio = self.mw_sound_url(prs)
|
||||||
if audio is None:
|
if audio is None:
|
||||||
audio = ""
|
audio = ""
|
||||||
frag = Fragment(prs['mw'], self.resources['fonts']['phonic'], color=blue)
|
frag = Fragment(prs['mw'], self.resources['fonts']['phonic'], color=blue)
|
||||||
frag.setAudio(audio)
|
frag.setAudio(audio)
|
||||||
frag.setPadding(0,10,3,12)
|
|
||||||
frag.setBorder(1)
|
|
||||||
frag.setMargin(0,3,0,3)
|
|
||||||
line.addFragment(frag)
|
line.addFragment(frag)
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
if "ins" in entry.keys():
|
if "ins" in entry.keys():
|
||||||
@@ -724,7 +759,7 @@ class Word:
|
|||||||
lines.append(line)
|
lines.append(line)
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
def sound_url(self, prs: dict[str, Any], fmt: str = "ogg") -> str | None:
|
def mw_sound_url(self, prs: dict[str, Any], fmt: str = "ogg") -> str | None:
|
||||||
"""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"https://media.merriam-webster.com/audio/prons/en/us/{fmt}"
|
||||||
if "sound" not in prs.keys():
|
if "sound" not in prs.keys():
|
||||||
@@ -735,7 +770,7 @@ class Word:
|
|||||||
url = base + f"/{m.group(1)}/"
|
url = base + f"/{m.group(1)}/"
|
||||||
else:
|
else:
|
||||||
url = base + "/number/"
|
url = base + "/number/"
|
||||||
url += audio + f".fmt"
|
url += audio + f".{fmt}"
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def mw_html(self) -> str:
|
def mw_html(self) -> str:
|
||||||
@@ -764,7 +799,7 @@ class Word:
|
|||||||
if "prs" in self.current["hwi"].keys():
|
if "prs" in self.current["hwi"].keys():
|
||||||
tmp = []
|
tmp = []
|
||||||
for prs in self.current["hwi"]["prs"]:
|
for prs in self.current["hwi"]["prs"]:
|
||||||
url = self.sound_url(prs)
|
url = self.mw_sound_url(prs)
|
||||||
how = prs["mw"]
|
how = prs["mw"]
|
||||||
if url:
|
if url:
|
||||||
tmp.append(f'<a href="{url}">\\{how}\\</a>')
|
tmp.append(f'<a href="{url}">\\{how}\\</a>')
|
||||||
@@ -827,43 +862,52 @@ class Definition(QWidget):
|
|||||||
self._lines = lines
|
self._lines = lines
|
||||||
self._buttons:list[Fragment] = []
|
self._buttons:list[Fragment] = []
|
||||||
base = 0
|
base = 0
|
||||||
|
|
||||||
for line in self._lines:
|
for line in self._lines:
|
||||||
line.finalizeLine()
|
line.finalizeLine(self.width(), base)
|
||||||
base += line.getLeading()
|
for frag in line.getLine():
|
||||||
|
if frag.audio().isValid():
|
||||||
|
self._buttons.append(frag)
|
||||||
|
if frag.wRef():
|
||||||
|
print(f"Adding {frag} as an anchor")
|
||||||
|
self._buttons.append(frag)
|
||||||
|
base += line.getLineSpacing()
|
||||||
self.setFixedHeight(base)
|
self.setFixedHeight(base)
|
||||||
return
|
return
|
||||||
|
|
||||||
def resizeEvent(self, event: QResizeEvent) -> None:
|
def resizeEvent(self, event: QResizeEvent) -> None:
|
||||||
base = 0
|
base = 0
|
||||||
for line in self._lines:
|
for line in self._lines:
|
||||||
line.finalizeLine()
|
line.finalizeLine(self.width(),base)
|
||||||
base += line.getLeading()
|
base += line.getLineSpacing()
|
||||||
self.setFixedHeight(base)
|
self.setFixedHeight(base)
|
||||||
super(Definition,self).resizeEvent(event)
|
super(Definition,self).resizeEvent(event)
|
||||||
return
|
return
|
||||||
|
|
||||||
_downRect: QRect | None = None
|
_downFrag: Optional[Fragment|None] = None
|
||||||
|
|
||||||
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.pos()}')
|
||||||
for frag in self._buttons:
|
for frag in self._buttons:
|
||||||
rect = frag.borderRect()
|
rect = frag.clickRect()
|
||||||
if rect.contains(event.pos()):
|
if rect.contains(event.pos()):
|
||||||
self._downRect = rect
|
self._downFrag = frag
|
||||||
return
|
return
|
||||||
return super().mousePressEvent(event)
|
return super().mousePressEvent(event)
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event: Optional[QMouseEvent]) -> None:
|
def mouseReleaseEvent(self, event: Optional[QMouseEvent]) -> None:
|
||||||
if not event:
|
if not event:
|
||||||
return super().mouseReleaseEvent(event)
|
return super().mouseReleaseEvent(event)
|
||||||
if self._downRect is not None and self._downRect.contains(event.pos()):
|
if self._downFrag is not None and self._downFrag.clickRect().contains(event.pos()):
|
||||||
self.pronounce.emit(
|
audio = self._downFrag.audio().url()
|
||||||
"https://media.merriam-webster.com/audio/prons/en/us/ogg/a/await001.ogg"
|
print(audio)
|
||||||
)
|
self.pronounce.emit(audio)
|
||||||
self._downRect = None
|
print('emit done')
|
||||||
|
self._downFrag = None
|
||||||
return
|
return
|
||||||
self._downRect = None
|
self._downFrag = None
|
||||||
return super().mouseReleaseEvent(event)
|
return super().mouseReleaseEvent(event)
|
||||||
|
|
||||||
def paintEvent(self, _: Optional[QPaintEvent]) -> None: # noqa
|
def paintEvent(self, _: Optional[QPaintEvent]) -> None: # noqa
|
||||||
|
|||||||
Reference in New Issue
Block a user