Lint picking

This commit is contained in:
Christopher T. Johnson
2024-02-04 15:06:07 -05:00
parent 38aeb76196
commit 61ebe6cc0b
6 changed files with 112 additions and 119 deletions

View File

@@ -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)

View File

@@ -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"

View File

@@ -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
@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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