import json import os from typing import Any, Dict, List, Optional, Type, cast from PyQt6.QtCore import Qt, pyqtSlot from PyQt6.QtMultimedia import QMediaDevices from PyQt6.QtWidgets import QAbstractItemView, QDialog, QListWidgetItem, QWidget from ui.Preferences import Ui_Dialog class Preferences(QDialog, Ui_Dialog): _instance = None preferences: Dict[str, str | List[str]] def __new__(cls: Type[Preferences]) -> Preferences: if cls._instance: return cls._instance cls._instance = super(Preferences, cls).__new__(cls) return cls._instance @pyqtSlot(int) def done(self, r: int) -> None: self.hide() super().done(r) return @pyqtSlot() def exec(self) -> int: self.show() return super().exec() @pyqtSlot() def open(self) -> None: self.show() super().open() return def __init__(self, *args: Any, **kwargs: Any) -> None: super(Preferences, self).__init__(*args, **kwargs) self.setupUi(self) self.hide() # # Overrides # self.alertList.setSelectionMode( QAbstractItemView.SelectionMode.MultiSelection ) self.playerList.setSelectionMode( QAbstractItemView.SelectionMode.MultiSelection ) self.readerCombo.setEditable(False) self.phoneticsCombo.setEditable(False) # # End OverRides # for index, output in enumerate(QMediaDevices.audioOutputs()): identifier = output.id().data().decode("utf-8") description = output.description() self.alertList.addItem(description) self.playerList.addItem(description) self.setCurrent() return def setCurrent(self) -> None: if os.path.exists("preferences.json"): with open("preferences.json", "r") as f: self.preferences = json.load(f) else: self.preferences = { "readerFont": "OpenDyslexic", "phoneticFont": "Gentium", "alertOutputs": ["default"], "playerOutputs": ["Feed for virtual microphone"], } for output in self.preferences["alertOutputs"]: if output == "default": output = QMediaDevices.defaultAudioOutput().description() for item in self.alertList.findItems( output, Qt.MatchFlag.MatchExactly ): item.setSelected(True) for output in self.preferences["playerOutputs"]: if output == "default": output = QMediaDevices.defaultAudioOutput().description() for item in self.playerList.findItems( output, Qt.MatchFlag.MatchExactly ): item.setSelected(True) index = self.readerCombo.findText(self.preferences["readerFont"]) if index >= 0: self.readerCombo.setCurrentIndex(index) index = self.phoneticsCombo.findText(self.preferences["phoneticFont"]) if index >= 0: self.phoneticsCombo.setCurrentIndex(index) return def get( self, name: Optional[str] = None ) -> str | List[str] | Dict[str, str | List[str]]: if not name: return self.preferences return self.preferences[name] def accept(self) -> None: self.preferences["readerFont"] = self.readerCombo.currentFont().family() self.preferences[ "phoneticFont" ] = self.phoneticsCombo.currentFont().family() self.preferences["alertOutputs"] = [ x.data(Qt.ItemDataRole.DisplayRole) for x in self.alertList.selectedItems() ] self.preferences["playerOutputs"] = [ x.data(Qt.ItemDataRole.DisplayRole) for x in self.playerList.selectedItems() ] with open("preferences.json", "w") as f: json.dump(self.preferences, f, indent=2) super().accept() return