Lint picking
This commit is contained in:
@@ -7,6 +7,7 @@ from email import policy
|
|||||||
from email.message import EmailMessage
|
from email.message import EmailMessage
|
||||||
from html.parser import HTMLParser
|
from html.parser import HTMLParser
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
from typing import Any, List
|
||||||
|
|
||||||
import css_inline
|
import css_inline
|
||||||
from PyQt6.QtCore import QResource, QSize, Qt, QUrl, pyqtSlot
|
from PyQt6.QtCore import QResource, QSize, Qt, QUrl, pyqtSlot
|
||||||
@@ -21,7 +22,7 @@ from ui.PeopleDialog import Ui_Dialog
|
|||||||
|
|
||||||
class blockHandler(HTMLParser):
|
class blockHandler(HTMLParser):
|
||||||
text = ""
|
text = ""
|
||||||
blocks = []
|
blocks: List[str] = []
|
||||||
active = 0
|
active = 0
|
||||||
tags = [
|
tags = [
|
||||||
"h1",
|
"h1",
|
||||||
@@ -39,7 +40,7 @@ class blockHandler(HTMLParser):
|
|||||||
]
|
]
|
||||||
space = ["b", "i", "em", "st", "span"]
|
space = ["b", "i", "em", "st", "span"]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.reset()
|
self.reset()
|
||||||
self.strict = False
|
self.strict = False
|
||||||
@@ -49,7 +50,7 @@ class blockHandler(HTMLParser):
|
|||||||
self.active = 0
|
self.active = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
def handle_starttag(self, tag, attrs):
|
def handle_starttag(self, tag: str, attrs: Any) -> None:
|
||||||
if not tag in self.tags:
|
if not tag in self.tags:
|
||||||
return
|
return
|
||||||
self.active += 1
|
self.active += 1
|
||||||
@@ -58,7 +59,7 @@ class blockHandler(HTMLParser):
|
|||||||
self.text += f"<{tag}>"
|
self.text += f"<{tag}>"
|
||||||
return
|
return
|
||||||
|
|
||||||
def handle_endtag(self, tag):
|
def handle_endtag(self, tag: str) -> None:
|
||||||
if not tag in self.tags:
|
if not tag in self.tags:
|
||||||
return
|
return
|
||||||
self.active -= 1
|
self.active -= 1
|
||||||
@@ -71,21 +72,21 @@ class blockHandler(HTMLParser):
|
|||||||
self.active = 0
|
self.active = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
def handle_data(self, data):
|
def handle_data(self, data: str) -> None:
|
||||||
self.text += data
|
self.text += data
|
||||||
return
|
return
|
||||||
|
|
||||||
def get_block(self, block):
|
def get_block(self, block: int) -> str:
|
||||||
return self.blocks[block]
|
return self.blocks[block]
|
||||||
|
|
||||||
|
|
||||||
class MLStripper(HTMLParser):
|
class MLStripper(HTMLParser):
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.reset()
|
self.reset()
|
||||||
return
|
return
|
||||||
|
|
||||||
def reset(self):
|
def reset(self) -> None:
|
||||||
super().reset()
|
super().reset()
|
||||||
self.strict = False
|
self.strict = False
|
||||||
self.convert_charrefs = True
|
self.convert_charrefs = True
|
||||||
@@ -93,13 +94,13 @@ class MLStripper(HTMLParser):
|
|||||||
self.first = True
|
self.first = True
|
||||||
return
|
return
|
||||||
|
|
||||||
def handle_data(self, d):
|
def handle_data(self, d: str) -> None:
|
||||||
if self.first:
|
if self.first:
|
||||||
self.text.write(d)
|
self.text.write(d)
|
||||||
self.first = False
|
self.first = False
|
||||||
return
|
return
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self) -> str:
|
||||||
return self.text.getvalue()
|
return self.text.getvalue()
|
||||||
|
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ class PersonDialog(QDialog, Ui_Dialog):
|
|||||||
person_id = 0
|
person_id = 0
|
||||||
inliner = css_inline.CSSInliner(keep_style_tags=True, keep_link_tags=True)
|
inliner = css_inline.CSSInliner(keep_style_tags=True, keep_link_tags=True)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
self.person_id = kwargs.pop("person_id", 0)
|
self.person_id = kwargs.pop("person_id", 0)
|
||||||
super(PersonDialog, self).__init__(*args, **kwargs)
|
super(PersonDialog, self).__init__(*args, **kwargs)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@@ -128,7 +129,7 @@ class PersonDialog(QDialog, Ui_Dialog):
|
|||||||
self.bookCombo.setModel(model)
|
self.bookCombo.setModel(model)
|
||||||
self.bookCombo.setModelColumn(1)
|
self.bookCombo.setModelColumn(1)
|
||||||
self.bookCombo.setCurrentIndex(-1)
|
self.bookCombo.setCurrentIndex(-1)
|
||||||
model = QStandardItemModel()
|
model: QStandardItemModel = QStandardItemModel() # type: ignore[no-redef]
|
||||||
self.sectionCombo.setPlaceholderText("Select A Section")
|
self.sectionCombo.setPlaceholderText("Select A Section")
|
||||||
self.sectionCombo.setModel(model)
|
self.sectionCombo.setModel(model)
|
||||||
self.sectionCombo.setEnabled(False)
|
self.sectionCombo.setEnabled(False)
|
||||||
@@ -349,7 +350,7 @@ class PersonDialog(QDialog, Ui_Dialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def checkLineEdits(self):
|
def checkLineEdits(self) -> None:
|
||||||
name = self.nameEdit.text().strip()
|
name = self.nameEdit.text().strip()
|
||||||
org = self.orgEdit.text().strip()
|
org = self.orgEdit.text().strip()
|
||||||
button = self.buttonBox.button(QDialogButtonBox.StandardButton.Ok)
|
button = self.buttonBox.button(QDialogButtonBox.StandardButton.Ok)
|
||||||
|
|||||||
@@ -1,41 +1,42 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from typing import Any, Dict, List, Optional, Type, cast
|
||||||
|
|
||||||
from PyQt6.QtCore import Qt, pyqtSlot
|
from PyQt6.QtCore import Qt, pyqtSlot
|
||||||
from PyQt6.QtMultimedia import QMediaDevices
|
from PyQt6.QtMultimedia import QMediaDevices
|
||||||
from PyQt6.QtWidgets import QAbstractItemView, QDialog, QListWidgetItem
|
from PyQt6.QtWidgets import QAbstractItemView, QDialog, QListWidgetItem, QWidget
|
||||||
|
|
||||||
from ui.Preferences import Ui_Dialog
|
from ui.Preferences import Ui_Dialog
|
||||||
|
|
||||||
|
|
||||||
class Preferences(QDialog, Ui_Dialog):
|
class Preferences(QDialog, Ui_Dialog):
|
||||||
_instance = None
|
_instance = None
|
||||||
|
preferences: Dict[str, str | List[str]]
|
||||||
|
|
||||||
def __new__(cls):
|
def __new__(cls: Type[Preferences]) -> Preferences:
|
||||||
if cls._instance:
|
if cls._instance:
|
||||||
return cls._instance
|
return cls._instance
|
||||||
cls._instance = super(Preferences, cls).__new__(cls)
|
cls._instance = super(Preferences, cls).__new__(cls)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def done(self, r):
|
def done(self, r: int) -> None:
|
||||||
self.hide()
|
self.hide()
|
||||||
super().done(r)
|
super().done(r)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def exec(self):
|
def exec(self) -> int:
|
||||||
self.show()
|
self.show()
|
||||||
super().exec()
|
return super().exec()
|
||||||
return
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def open(self):
|
def open(self) -> None:
|
||||||
self.show()
|
self.show()
|
||||||
super().open()
|
super().open()
|
||||||
return
|
return
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
super(Preferences, self).__init__(*args, **kwargs)
|
super(Preferences, self).__init__(*args, **kwargs)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.hide()
|
self.hide()
|
||||||
@@ -61,7 +62,7 @@ class Preferences(QDialog, Ui_Dialog):
|
|||||||
self.setCurrent()
|
self.setCurrent()
|
||||||
return
|
return
|
||||||
|
|
||||||
def setCurrent(self):
|
def setCurrent(self) -> None:
|
||||||
if os.path.exists("preferences.json"):
|
if os.path.exists("preferences.json"):
|
||||||
with open("preferences.json", "r") as f:
|
with open("preferences.json", "r") as f:
|
||||||
self.preferences = json.load(f)
|
self.preferences = json.load(f)
|
||||||
@@ -94,12 +95,14 @@ class Preferences(QDialog, Ui_Dialog):
|
|||||||
self.phoneticsCombo.setCurrentIndex(index)
|
self.phoneticsCombo.setCurrentIndex(index)
|
||||||
return
|
return
|
||||||
|
|
||||||
def get(self, name: str = None):
|
def get(
|
||||||
|
self, name: Optional[str] = None
|
||||||
|
) -> str | List[str] | Dict[str, str | List[str]]:
|
||||||
if not name:
|
if not name:
|
||||||
return self.preferences
|
return self.preferences
|
||||||
return self.preferences[name]
|
return self.preferences[name]
|
||||||
|
|
||||||
def accept(self):
|
def accept(self) -> None:
|
||||||
self.preferences["readerFont"] = self.readerCombo.currentFont().family()
|
self.preferences["readerFont"] = self.readerCombo.currentFont().family()
|
||||||
self.preferences[
|
self.preferences[
|
||||||
"phoneticFont"
|
"phoneticFont"
|
||||||
|
|||||||
114
lib/read.py
114
lib/read.py
@@ -1,6 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
from typing import cast
|
from typing import Any, Dict, List, Optional, cast
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from PyQt6.QtCore import (
|
from PyQt6.QtCore import (
|
||||||
@@ -30,35 +30,38 @@ from PyQt6.QtGui import (
|
|||||||
QTextListFormat,
|
QTextListFormat,
|
||||||
)
|
)
|
||||||
from PyQt6.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
|
from PyQt6.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
|
||||||
from PyQt6.QtWidgets import QDialog, QPushButton
|
from PyQt6.QtWidgets import QDialog, QPushButton, QTextEdit, QWidget
|
||||||
|
|
||||||
|
from lib.preferences import Preferences
|
||||||
|
from lib.session import SessionDialog
|
||||||
|
from lib.sounds import SoundOff
|
||||||
from main import query_error
|
from main import query_error
|
||||||
from ui.ReadDialog import Ui_Dialog
|
from ui.ReadDialog import Ui_Dialog
|
||||||
from lib.preferences import Preferences
|
|
||||||
from lib.sounds import SoundOff
|
|
||||||
|
|
||||||
class ReadDialog(QDialog, Ui_Dialog):
|
class ReadDialog(QDialog, Ui_Dialog):
|
||||||
playSound = pyqtSignal(str)
|
playSound = pyqtSignal(str)
|
||||||
playAlert = pyqtSignal()
|
playAlert = pyqtSignal()
|
||||||
block: int
|
block: int
|
||||||
|
preferences: Dict[str, str | List[str]]
|
||||||
paragraphs = True
|
paragraphs = True
|
||||||
sessionSignal = pyqtSignal()
|
sessionSignal = pyqtSignal()
|
||||||
displayedWord = pyqtSignal(int)
|
displayedWord = pyqtSignal(int)
|
||||||
newParagraph = pyqtSignal(int, int)
|
newParagraph = pyqtSignal(int, int)
|
||||||
|
|
||||||
def __init__(self, parent, session, person_id: int) -> None:
|
def __init__(
|
||||||
|
self, parent: Optional[QWidget], session: SessionDialog, person_id: int
|
||||||
|
) -> None:
|
||||||
self.session = session
|
self.session = session
|
||||||
super(ReadDialog, self).__init__(parent)
|
super(ReadDialog, self).__init__(parent)
|
||||||
self.person_id = person_id
|
self.person_id = person_id
|
||||||
self.preferences = Preferences().get()
|
self.preferences = cast(Dict[str, str | List[str]], Preferences().get())
|
||||||
self.sound = SoundOff()
|
self.sound = SoundOff()
|
||||||
styleSheet = QResource(":/display.css").data().decode("utf-8")
|
styleSheet = QResource(":/display.css").data().decode("utf-8")
|
||||||
styleSheet = styleSheet.replace(
|
readerFont = cast(str, self.preferences["readerFont"])
|
||||||
'{readerFont}',self.preferences['readerFont']
|
phoneticFont = cast(str, self.preferences["phoneticFont"])
|
||||||
)
|
styleSheet = styleSheet.replace("{readerFont}", readerFont)
|
||||||
styleSheet = styleSheet.replace(
|
styleSheet = styleSheet.replace("{phoneticFont}", phoneticFont)
|
||||||
'{phoneticFont}',self.preferences['phoneticFont']
|
|
||||||
)
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
#
|
#
|
||||||
# Override UI
|
# Override UI
|
||||||
@@ -88,7 +91,7 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
self.prevBtn.clicked.connect(self.prevAction)
|
self.prevBtn.clicked.connect(self.prevAction)
|
||||||
self.sessionBtn.clicked.connect(self.timerAction)
|
self.sessionBtn.clicked.connect(self.timerAction)
|
||||||
self.paraEdit.verticalScrollBar().valueChanged.connect(self.scrollSlot)
|
self.paraEdit.verticalScrollBar().valueChanged.connect(self.scrollSlot)
|
||||||
#self.defEdit.selectionChanged.connect(self.recursiveDef)
|
# self.defEdit.selectionChanged.connect(self.recursiveDef)
|
||||||
self.returnBtn.clicked.connect(self.returnAction)
|
self.returnBtn.clicked.connect(self.returnAction)
|
||||||
#
|
#
|
||||||
# Connect signals
|
# Connect signals
|
||||||
@@ -107,7 +110,7 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
# slots
|
# slots
|
||||||
#
|
#
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def timerAction(self):
|
def timerAction(self) -> None:
|
||||||
if self.session.isActive(): # We are stopping
|
if self.session.isActive(): # We are stopping
|
||||||
self.sessionBtn.setText("Start")
|
self.sessionBtn.setText("Start")
|
||||||
else:
|
else:
|
||||||
@@ -115,8 +118,9 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
self.session.timerAction()
|
self.session.timerAction()
|
||||||
self.newParagraph.emit(self.section_id, self.block)
|
self.newParagraph.emit(self.section_id, self.block)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def recursiveDef(self):
|
def recursiveDef(self) -> None:
|
||||||
cursor = self.defEdit.textCursor()
|
cursor = self.defEdit.textCursor()
|
||||||
selection = cursor.selectedText().strip()
|
selection = cursor.selectedText().strip()
|
||||||
if len(selection) <= 0:
|
if len(selection) <= 0:
|
||||||
@@ -125,7 +129,7 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
query.prepare("SELECT * FROM words " "WHERE word = :word")
|
query.prepare("SELECT * FROM words " "WHERE word = :word")
|
||||||
query.bindValue(":word", selection)
|
query.bindValue(":word", selection)
|
||||||
if not query.exec():
|
if not query.exec():
|
||||||
query_error()
|
query_error(query)
|
||||||
if not query.next():
|
if not query.next():
|
||||||
response = requests.get(
|
response = requests.get(
|
||||||
f"https://api.dictionaryapi.dev/api/v2/entries/en/{selection}"
|
f"https://api.dictionaryapi.dev/api/v2/entries/en/{selection}"
|
||||||
@@ -144,7 +148,7 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def sessionAction(self) -> None:
|
def sessionAction(self) -> None:
|
||||||
self.sessionSignal.emit()
|
self.sessionSignal.emit()
|
||||||
self.session.addParagraph(self.section_id, self.block)
|
self.newParagraph.emit(self.section_id, self.block)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@@ -248,10 +252,7 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def nextAction(self) -> None:
|
def nextAction(self) -> None:
|
||||||
if self.stackedWidget.currentIndex() == 1:
|
if self.paragraphs:
|
||||||
print("Next Definition")
|
|
||||||
self.nextDefinition()
|
|
||||||
elif self.paragraphs:
|
|
||||||
self.nextParagraph()
|
self.nextParagraph()
|
||||||
else:
|
else:
|
||||||
self.nextSection()
|
self.nextSection()
|
||||||
@@ -259,15 +260,15 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def prevAction(self) -> None:
|
def prevAction(self) -> None:
|
||||||
if self.stackedWidget.currentIndex() == 1:
|
if self.paragraphs:
|
||||||
print("Previous Definition")
|
|
||||||
self.prevDefinition()
|
|
||||||
elif self.paragraphs:
|
|
||||||
self.prevParagraph()
|
self.prevParagraph()
|
||||||
else:
|
else:
|
||||||
self.prevSection()
|
self.prevSection()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
#
|
||||||
|
# Called when the "define" button is pressed
|
||||||
|
#
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def defineAction(self) -> None:
|
def defineAction(self) -> None:
|
||||||
editor = self.paraEdit
|
editor = self.paraEdit
|
||||||
@@ -277,10 +278,10 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
self.showDefinition()
|
self.showDefinition()
|
||||||
return
|
return
|
||||||
|
|
||||||
def defToHtml(self, word: str, definition) -> str:
|
def defToHtml(self, word: str, definition: Dict[str, Any]) -> str:
|
||||||
html = f'<h1 class="def-word">{word}</h1>' + "\n"
|
html = f'<h1 class="def-word">{word}</h1>' + "\n"
|
||||||
try:
|
try:
|
||||||
words = []
|
words: List[str] = []
|
||||||
for phonetic in definition["phonetics"]:
|
for phonetic in definition["phonetics"]:
|
||||||
if phonetic["text"] in words:
|
if phonetic["text"] in words:
|
||||||
continue
|
continue
|
||||||
@@ -389,7 +390,7 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
#
|
#
|
||||||
# Event handlers
|
# Event handlers
|
||||||
#
|
#
|
||||||
def keyReleaseEvent(self, event: QKeyEvent) -> None:
|
def keyReleaseEvent(self, event: Optional[QKeyEvent]) -> None:
|
||||||
self.nextBtn.setText("Next Para")
|
self.nextBtn.setText("Next Para")
|
||||||
self.prevBtn.setText("Prev Para")
|
self.prevBtn.setText("Prev Para")
|
||||||
self.defineBtn.setText("Show Def")
|
self.defineBtn.setText("Show Def")
|
||||||
@@ -397,7 +398,7 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
super().keyReleaseEvent(event)
|
super().keyReleaseEvent(event)
|
||||||
return
|
return
|
||||||
|
|
||||||
def keyPressEvent(self, event: QKeyEvent) -> None:
|
def keyPressEvent(self, event: Optional[QKeyEvent]) -> None:
|
||||||
self.nextBtn.setText("Next Sect")
|
self.nextBtn.setText("Next Sect")
|
||||||
self.prevBtn.setText("Prev Sect")
|
self.prevBtn.setText("Prev Sect")
|
||||||
self.defineBtn.setText("Add Def")
|
self.defineBtn.setText("Add Def")
|
||||||
@@ -447,7 +448,7 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
self.savePosition()
|
self.savePosition()
|
||||||
return
|
return
|
||||||
|
|
||||||
def addWord(self,editor) -> None:
|
def addWord(self, editor: QTextEdit) -> None:
|
||||||
#
|
#
|
||||||
# Find the word
|
# Find the word
|
||||||
#
|
#
|
||||||
@@ -470,7 +471,9 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
#
|
#
|
||||||
# Find the block
|
# Find the block
|
||||||
#
|
#
|
||||||
textBlock = editor.document().findBlock(cursor.position())
|
document = editor.document()
|
||||||
|
assert document is not None
|
||||||
|
textBlock = document.findBlock(cursor.position())
|
||||||
blockNum = textBlock.blockNumber()
|
blockNum = textBlock.blockNumber()
|
||||||
start = start - textBlock.position()
|
start = start - textBlock.position()
|
||||||
end = end - textBlock.position()
|
end = end - textBlock.position()
|
||||||
@@ -490,7 +493,7 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
f"https://api.dictionaryapi.dev/api/v2/entries/en/{word}"
|
f"https://api.dictionaryapi.dev/api/v2/entries/en/{word}"
|
||||||
)
|
)
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
print(f"{word}: {response.content}")
|
print(f"{word}: {response.content.decode('utf8')}")
|
||||||
self.playAlert.emit()
|
self.playAlert.emit()
|
||||||
return
|
return
|
||||||
definitions = json.loads(response.content.decode("utf-8"))
|
definitions = json.loads(response.content.decode("utf-8"))
|
||||||
@@ -551,6 +554,10 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# XXX - rename
|
# XXX - rename
|
||||||
|
#
|
||||||
|
# Create a definition for the word under the cursor on the current
|
||||||
|
# panel.
|
||||||
|
#
|
||||||
def display_definition(self, idx: int) -> bool:
|
def display_definition(self, idx: int) -> bool:
|
||||||
if idx == 0:
|
if idx == 0:
|
||||||
editor = self.paraEdit
|
editor = self.paraEdit
|
||||||
@@ -559,14 +566,11 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
cursor = editor.textCursor()
|
cursor = editor.textCursor()
|
||||||
cursor.select(QTextCursor.SelectionType.WordUnderCursor)
|
cursor.select(QTextCursor.SelectionType.WordUnderCursor)
|
||||||
word = cursor.selectedText()
|
word = cursor.selectedText()
|
||||||
fmt = cursor.charFormat()
|
# fmt = cursor.charFormat()
|
||||||
if not fmt.fontUnderline():
|
# if not fmt.fontUnderline():
|
||||||
self.addWord(editor)
|
# self.addWord(editor)
|
||||||
query = QSqlQuery()
|
query = QSqlQuery()
|
||||||
query.prepare(
|
query.prepare("SELECT w.* FROM words w " "WHERE word = :word")
|
||||||
"SELECT w.* FROM words w "
|
|
||||||
"WHERE word = :word"
|
|
||||||
)
|
|
||||||
query.bindValue(":word", word)
|
query.bindValue(":word", word)
|
||||||
if not query.exec():
|
if not query.exec():
|
||||||
query_error(query)
|
query_error(query)
|
||||||
@@ -577,7 +581,9 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
self.setDefEdit(word, query.value("word_id"), definition)
|
self.setDefEdit(word, query.value("word_id"), definition)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setDefEdit(self, word, word_id, definition):
|
def setDefEdit(
|
||||||
|
self, word: str, word_id: int, definition: Dict[str, str]
|
||||||
|
) -> None:
|
||||||
if "phonetics" in definition:
|
if "phonetics" in definition:
|
||||||
self.phonetics = definition["phonetics"]
|
self.phonetics = definition["phonetics"]
|
||||||
else:
|
else:
|
||||||
@@ -615,34 +621,6 @@ class ReadDialog(QDialog, Ui_Dialog):
|
|||||||
self.update()
|
self.update()
|
||||||
return
|
return
|
||||||
|
|
||||||
def nextDefinition(self) -> None:
|
|
||||||
cursor = self.paraEdit.textCursor()
|
|
||||||
formats = self.paraEdit.document().allFormats()
|
|
||||||
found = None
|
|
||||||
for f in formats:
|
|
||||||
wc = QTextCursor(cursor)
|
|
||||||
wc.setPosition(f.start)
|
|
||||||
wc.movePosition(
|
|
||||||
QTextCursor.MoveOperation.Right,
|
|
||||||
QTextCursor.MoveMode.KeepAnchor,
|
|
||||||
f.length,
|
|
||||||
)
|
|
||||||
word = wc.selectedText()
|
|
||||||
cf = wc.charFormat()
|
|
||||||
if f.start <= position:
|
|
||||||
continue
|
|
||||||
if not cf.fontUnderline():
|
|
||||||
continue
|
|
||||||
if not found:
|
|
||||||
found = f
|
|
||||||
elif f.start < found.start:
|
|
||||||
found = f
|
|
||||||
if found:
|
|
||||||
cursor.setPosition(found.start)
|
|
||||||
self.paraEdit.setTextCursor(cursor)
|
|
||||||
self.display_definition(0)
|
|
||||||
return
|
|
||||||
|
|
||||||
def scrollTo(self, position: int) -> None:
|
def scrollTo(self, position: int) -> None:
|
||||||
cursor = self.paraEdit.textCursor()
|
cursor = self.paraEdit.textCursor()
|
||||||
cursor.setPosition(position)
|
cursor.setPosition(position)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from typing import Optional, cast
|
||||||
|
|
||||||
from PyQt6.QtCore import QModelIndex, Qt, QTime, QTimer, pyqtSignal, pyqtSlot
|
from PyQt6.QtCore import QModelIndex, Qt, QTime, QTimer, pyqtSignal, pyqtSlot
|
||||||
from PyQt6.QtGui import (
|
from PyQt6.QtGui import (
|
||||||
@@ -11,7 +12,7 @@ from PyQt6.QtGui import (
|
|||||||
QTextDocument,
|
QTextDocument,
|
||||||
)
|
)
|
||||||
from PyQt6.QtSql import QSqlQuery
|
from PyQt6.QtSql import QSqlQuery
|
||||||
from PyQt6.QtWidgets import QDialog
|
from PyQt6.QtWidgets import QCheckBox, QDialog, QListView, QMessageBox
|
||||||
|
|
||||||
from main import query_error
|
from main import query_error
|
||||||
from ui.SessionDialog import Ui_Dialog
|
from ui.SessionDialog import Ui_Dialog
|
||||||
@@ -25,7 +26,7 @@ class SessionDialog(QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
timer = QTimer()
|
timer = QTimer()
|
||||||
startTime = datetime.now()
|
startTime = datetime.now()
|
||||||
totalTime = 0 # seconds
|
totalTime = timedelta(seconds=0)
|
||||||
sessionStart = None
|
sessionStart = None
|
||||||
sessionEnd = None
|
sessionEnd = None
|
||||||
blocks = QStandardItemModel()
|
blocks = QStandardItemModel()
|
||||||
@@ -49,8 +50,11 @@ class SessionDialog(QDialog, Ui_Dialog):
|
|||||||
flag = index.data(SessionDialog.WordImportantRole)
|
flag = index.data(SessionDialog.WordImportantRole)
|
||||||
flag = 1 - flag
|
flag = 1 - flag
|
||||||
model = index.model()
|
model = index.model()
|
||||||
|
assert model is not None
|
||||||
|
model = cast(QStandardItemModel, model)
|
||||||
model.setData(index, flag, SessionDialog.WordImportantRole)
|
model.setData(index, flag, SessionDialog.WordImportantRole)
|
||||||
item = model.itemFromIndex(index)
|
item = model.itemFromIndex(index)
|
||||||
|
assert item is not None
|
||||||
if flag:
|
if flag:
|
||||||
item.setForeground(Qt.GlobalColor.red)
|
item.setForeground(Qt.GlobalColor.red)
|
||||||
else:
|
else:
|
||||||
@@ -62,13 +66,13 @@ class SessionDialog(QDialog, Ui_Dialog):
|
|||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def resetForm(self) -> None:
|
def resetForm(self) -> None:
|
||||||
self.nameLbl.setText("")
|
self.nameLbl.setText("")
|
||||||
self.totalTime = timedelta()
|
self.totalTime = timedelta(seconds=0)
|
||||||
self.wordView.model().clear()
|
self.wordView.model().clear()
|
||||||
self.textBrowser.document().clear()
|
self.textBrowser.document().clear()
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def setPerson(self, person_id) -> None:
|
def setPerson(self, person_id: int) -> None:
|
||||||
self.resetForm()
|
self.resetForm()
|
||||||
self.person_id = person_id
|
self.person_id = person_id
|
||||||
query = QSqlQuery()
|
query = QSqlQuery()
|
||||||
@@ -79,12 +83,12 @@ class SessionDialog(QDialog, Ui_Dialog):
|
|||||||
if not query.next():
|
if not query.next():
|
||||||
raise Exception(f"Bad person_id: {person_id}")
|
raise Exception(f"Bad person_id: {person_id}")
|
||||||
self.nameLbl.setText(query.value("name"))
|
self.nameLbl.setText(query.value("name"))
|
||||||
self.totalTime = timedelta()
|
self.totalTime = timedelta(seconds=0)
|
||||||
self.wordView.model().clear()
|
self.wordView.model().clear()
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def rejected(self) -> None:
|
def rejected(self): # type: ignore[no-untyped-def]
|
||||||
msg = QMessageBox()
|
msg = QMessageBox()
|
||||||
msg.setText("There is unsaved data.")
|
msg.setText("There is unsaved data.")
|
||||||
msg.setInformativeText("Do you want to save the session?")
|
msg.setInformativeText("Do you want to save the session?")
|
||||||
@@ -100,7 +104,7 @@ class SessionDialog(QDialog, Ui_Dialog):
|
|||||||
super().reject()
|
super().reject()
|
||||||
return
|
return
|
||||||
self.accept()
|
self.accept()
|
||||||
self.done()
|
self.done(QDialog.DialogCode.Accepted)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@@ -164,7 +168,8 @@ class SessionDialog(QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def tickAction(self) -> None:
|
def tickAction(self) -> None:
|
||||||
delta = self.totalTime + (datetime.now() - self.startTime)
|
td = datetime.now() - self.startTime
|
||||||
|
delta = self.totalTime + td
|
||||||
seconds = delta.seconds % 60
|
seconds = delta.seconds % 60
|
||||||
minutes = int(delta.seconds / 60) % 60
|
minutes = int(delta.seconds / 60) % 60
|
||||||
hours = int(delta.seconds / 3600)
|
hours = int(delta.seconds / 3600)
|
||||||
@@ -211,7 +216,7 @@ class SessionDialog(QDialog, Ui_Dialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(int, int)
|
@pyqtSlot(int, int)
|
||||||
def addBlock(self, section_id, block) -> None:
|
def addBlock(self, section_id: int, block: int) -> None:
|
||||||
if not self.activeBox.isChecked():
|
if not self.activeBox.isChecked():
|
||||||
return
|
return
|
||||||
new_block = QStandardItem()
|
new_block = QStandardItem()
|
||||||
@@ -265,5 +270,6 @@ class SessionDialog(QDialog, Ui_Dialog):
|
|||||||
#
|
#
|
||||||
# End Slots
|
# End Slots
|
||||||
#
|
#
|
||||||
def isActive(self):
|
def isActive(self) -> bool:
|
||||||
return self.activeBox.isChecked()
|
active: bool = self.activeBox.isChecked()
|
||||||
|
return active
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
from typing import Optional, Type, cast
|
||||||
|
|
||||||
from PyQt6.QtCore import QObject, Qt, QUrl, pyqtSlot
|
from PyQt6.QtCore import QObject, Qt, QUrl, pyqtSlot
|
||||||
from PyQt6.QtMultimedia import (
|
from PyQt6.QtMultimedia import (
|
||||||
QAudioDevice,
|
QAudioDevice,
|
||||||
@@ -13,13 +15,13 @@ from PyQt6.QtMultimedia import (
|
|||||||
class SoundOff(QObject):
|
class SoundOff(QObject):
|
||||||
_instance = None
|
_instance = None
|
||||||
|
|
||||||
def __new__(cls):
|
def __new__(cls: Type[SoundOff]) -> SoundOff:
|
||||||
if cls._instance:
|
if cls._instance:
|
||||||
return cls._instance
|
return cls._instance
|
||||||
cls._instance = super(SoundOff, cls).__new__(cls)
|
cls._instance = super(SoundOff, cls).__new__(cls)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
#
|
#
|
||||||
# Setup devices
|
# Setup devices
|
||||||
@@ -61,36 +63,38 @@ class SoundOff(QObject):
|
|||||||
self.virtualPlayer.playbackStateChanged.connect(self.playbackState)
|
self.virtualPlayer.playbackStateChanged.connect(self.playbackState)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def alert(self):
|
def alert(self) -> None:
|
||||||
self.alertEffect.play()
|
self.alertEffect.play()
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(QMediaPlayer.Error, str)
|
@pyqtSlot(QMediaPlayer.Error, str)
|
||||||
def mediaError(self, error, string):
|
def mediaError(self, error: QMediaPlayer.Error, string: str) -> None:
|
||||||
print(error)
|
print(error)
|
||||||
print(str)
|
print(str)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(QMediaPlayer.MediaStatus)
|
@pyqtSlot(QMediaPlayer.MediaStatus)
|
||||||
def mediaStatus(self, status):
|
def mediaStatus(self, status: QMediaPlayer.MediaStatus) -> None:
|
||||||
if status == QMediaPlayer.MediaStatus.LoadedMedia:
|
if status == QMediaPlayer.MediaStatus.LoadedMedia:
|
||||||
self.sender().play()
|
player: Optional[QMediaPlayer] = cast(QMediaPlayer, self.sender())
|
||||||
|
assert player is not None
|
||||||
|
player.play()
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(QMediaPlayer.PlaybackState)
|
@pyqtSlot(QMediaPlayer.PlaybackState)
|
||||||
def playbackState(self, state):
|
def playbackState(self, state: QMediaPlayer.PlaybackState) -> None:
|
||||||
return
|
return
|
||||||
|
|
||||||
#
|
#
|
||||||
# Communications slots
|
# Communications slots
|
||||||
#
|
#
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def soundAlert(self):
|
def soundAlert(self) -> None:
|
||||||
self.alertEffect.play()
|
self.alertEffect.play()
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def playSound(self, url):
|
def playSound(self, url: str) -> None:
|
||||||
src = QUrl(url)
|
src = QUrl(url)
|
||||||
if not self.localPlayer.audioOutput():
|
if not self.localPlayer.audioOutput():
|
||||||
self.localPlayer.setAudioOutput(self.localOutput)
|
self.localPlayer.setAudioOutput(self.localOutput)
|
||||||
|
|||||||
9
main.py
9
main.py
@@ -16,7 +16,7 @@ import os
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import cast
|
from typing import Optional
|
||||||
|
|
||||||
from PyQt6.QtCore import (
|
from PyQt6.QtCore import (
|
||||||
QModelIndex,
|
QModelIndex,
|
||||||
@@ -98,7 +98,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def editPreferences(self):
|
def editPreferences(self) -> None:
|
||||||
dlg = Preferences()
|
dlg = Preferences()
|
||||||
dlg.exec()
|
dlg.exec()
|
||||||
return
|
return
|
||||||
@@ -134,12 +134,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@pyqtSlot(QModelIndex)
|
@pyqtSlot(QModelIndex)
|
||||||
def editPerson(self, index=None) -> None:
|
def editPerson(self, index: Optional[QModelIndex] = None) -> None:
|
||||||
if not index:
|
if not index:
|
||||||
indexes = self.peopleView.selectedIndexes()
|
indexes = self.peopleView.selectedIndexes()
|
||||||
if len(indexes) < 1:
|
if len(indexes) < 1:
|
||||||
return
|
return
|
||||||
index = indexes[0]
|
index = indexes[0]
|
||||||
|
assert index is not None
|
||||||
dlg = PersonDialog(person_id=index.siblingAtColumn(0).data())
|
dlg = PersonDialog(person_id=index.siblingAtColumn(0).data())
|
||||||
dlg.exec()
|
dlg.exec()
|
||||||
return
|
return
|
||||||
@@ -324,7 +325,7 @@ if __name__ == "__main__":
|
|||||||
uiName = "ui/" + fileName[:-3] + ".ui"
|
uiName = "ui/" + fileName[:-3] + ".ui"
|
||||||
rccName = "ui/" + fileName[:-3] + ".qrc"
|
rccName = "ui/" + fileName[:-3] + ".qrc"
|
||||||
if not os.path.isfile(uiName) and not os.path.isfile(rccName):
|
if not os.path.isfile(uiName) and not os.path.isfile(rccName):
|
||||||
outOfDate.append(filenName)
|
outOfDate.append(fileName)
|
||||||
continue
|
continue
|
||||||
if os.path.isfile(uiName) and os.path.getmtime(
|
if os.path.isfile(uiName) and os.path.getmtime(
|
||||||
uiName
|
uiName
|
||||||
|
|||||||
Reference in New Issue
Block a user