Skip to content

Commit 86190b6

Browse files
committed
Add force option to UniversalSpeech.say and update calls
Introduces a 'force' parameter to UniversalSpeech.say to allow speech output regardless of configuration. Updates all relevant calls across the UI to use force=True where immediate speech feedback is required, improving accessibility and user feedback consistency.
1 parent fc21f8c commit 86190b6

File tree

6 files changed

+34
-35
lines changed

6 files changed

+34
-35
lines changed

ui/dialogs/tasbih_dialog.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def open_tasbih_entry_dialog(self):
151151
tasbih_entry = self.controller.get_entry(entry_id)
152152
logger.info(f"Opening Tasbih entry dialog for: {tasbih_entry.name} (ID: {entry_id}, Count: {tasbih_entry.counter})")
153153
dialog = TasbihEntryDialog(self, self.controller, tasbih_entry)
154-
UniversalSpeech.say(F"مرحبا بك في المِسْبَحَة، التسبيح: {tasbih_entry.name}، العدد: {tasbih_entry.counter}. استخدم المفاتيح التالية لزيادة العداد: Space, Enter, +,أو C. لإنقاص العداد استخدم: D, Ctrl+Space, -, أو Backspace. لإعادة تعيين العداد استخدم: Ctrl+R. للمعلومات استخدم: V للعدد، T للذِكر، I للكل.")
154+
UniversalSpeech.say(F"مرحبا بك في المِسْبَحَة، التسبيح: {tasbih_entry.name}، العدد: {tasbih_entry.counter}. استخدم المفاتيح التالية لزيادة العداد: Space, Enter, +,أو C. لإنقاص العداد استخدم: D, Ctrl+Space, -, أو Backspace. لإعادة تعيين العداد استخدم: Ctrl+R. للمعلومات استخدم: V للعدد، T للذِكر، I للكل.", force=True)
155155
dialog.exec()
156156

157157
def OnItemSelectionChanged(self):
@@ -388,7 +388,7 @@ def load_details(self, tasbih_entry: TasbihEntry = None):
388388
def handle_entry_updated(self, tasbih_entry: TasbihEntry):
389389
self.load_details(tasbih_entry)
390390
logger.debug(f"Tasbih entry updated: {tasbih_entry.name} (ID: {tasbih_entry.id}, New Count: {tasbih_entry.counter})")
391-
UniversalSpeech.say(str(tasbih_entry.counter))
391+
UniversalSpeech.say(str(tasbih_entry.counter), force=True)
392392

393393
def handle_increment(self):
394394
"""Handle the increment action."""
@@ -418,11 +418,11 @@ def set_shortcuts(self):
418418

419419
#Info shortcuts
420420
counter_info_shortcut = QShortcut(QKeySequence("V"), self)
421-
counter_info_shortcut.activated.connect(lambda: UniversalSpeech.say(str(self.counter_label.text())))
421+
counter_info_shortcut.activated.connect(lambda: UniversalSpeech.say(str(self.counter_label.text()), force=True))
422422
name_info_shortcut = QShortcut(QKeySequence("T"), self)
423-
name_info_shortcut.activated.connect(lambda: UniversalSpeech.say(str(self.name_label.text())))
423+
name_info_shortcut.activated.connect(lambda: UniversalSpeech.say(str(self.name_label.text()), force=True))
424424
all_info_shortcut = QShortcut(QKeySequence("I"), self)
425-
all_info_shortcut.activated.connect(lambda: UniversalSpeech.say(f"{self.name_label.text()}، {self.counter_label.text()}"))
425+
all_info_shortcut.activated.connect(lambda: UniversalSpeech.say(f"{self.name_label.text()}، {self.counter_label.text()}", force=True))
426426

427427
for widget, key_sequence in shortcuts.items():
428428
key_sequence = [key_sequence] if isinstance(key_sequence, str) else key_sequence

ui/quran_interface.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -510,27 +510,27 @@ def say_played_ayah(self):
510510
logger.debug(f"Text to be spoken: {text}")
511511
if text:
512512
if self.toolbar.player.is_playing():
513-
UniversalSpeech.say(f"{text}، الآية المشغلة.")
513+
UniversalSpeech.say(f"{text}، الآية المشغلة.", force=True)
514514
logger.debug(f"{text} is currently playing.")
515515
elif self.toolbar.player.is_paused():
516-
UniversalSpeech.say(f"{text}، تم إيقافها مؤقتًا.")
516+
UniversalSpeech.say(f"{text}، تم إيقافها مؤقتًا.", force=True)
517517
logger.debug(f"{text} is paused.")
518518
elif self.toolbar.player.is_stopped():
519-
UniversalSpeech.say(f"{text}، تم إيقافها.")
519+
UniversalSpeech.say(f"{text}، تم إيقافها.", force=True)
520520
logger.debug(f"{text} is stopped.")
521521
elif self.toolbar.player.is_stalled():
522-
UniversalSpeech.say(f"{text}، يجري تحميلها.")
522+
UniversalSpeech.say(f"{text}، يجري تحميلها.", force=True)
523523
logger.debug(f"{text} is stalled.")
524524
else:
525-
UniversalSpeech.say("لم يتم تشغيل أي آية.")
525+
UniversalSpeech.say("لم يتم تشغيل أي آية.", force=True)
526526
logger.debug("No Ayah is currently playing.")
527527

528528
def say_focused_ayah(self):
529529
logger.debug("Say focused Ayah action triggered.")
530530
current_aya = self.get_current_ayah()
531531
text = f"آية {current_aya.number_in_surah} من {current_aya.sura_name}، الآية الحالية."
532532
logger.debug(f"Text to be spoken: {text}")
533-
UniversalSpeech.say(text)
533+
UniversalSpeech.say(text, force=True)
534534

535535
@exception_handler(ui_element=QMessageBox)
536536
def OnSaveBookmark(self, event):

ui/sura_player_ui/audio_looper.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def set_loop_start(self):
4444
self.loop_end = self.player.get_length()
4545
logger.debug(f"Loop end adjusted to track length: {self.loop_end} ms.")
4646
logger.debug(f"Loop start set to {self.parent.format_time(self.loop_start)}.")
47-
UniversalSpeech.say(f"تم تحديد البداية عند: {self.parent.format_time(self.loop_start)}.")
47+
UniversalSpeech.say(f"تم تحديد البداية عند: {self.parent.format_time(self.loop_start)}.", force=True)
4848

4949
def set_loop_end(self):
5050
"""Set the end point (B) for the repeat loop."""
@@ -55,7 +55,7 @@ def set_loop_end(self):
5555
self.loop_start = 0
5656
logger.debug("Loop start reset to 0 because end is before start.")
5757
logger.debug(f"Loop end set to {self.parent.format_time(self.loop_end)}.")
58-
UniversalSpeech.say(f"تم تحديد النهاية عند: {self.parent.format_time(self.loop_end)}.")
58+
UniversalSpeech.say(f"تم تحديد النهاية عند: {self.parent.format_time(self.loop_end)}.", force=True)
5959

6060
def toggle_loop(self):
6161
"""
@@ -64,22 +64,22 @@ def toggle_loop(self):
6464
"""
6565
logger.debug("Toggling loop playback.")
6666
if not self.loop_start and not self.loop_end:
67-
UniversalSpeech.say("لم يتم تحديد البداية والنهاية.")
67+
UniversalSpeech.say("لم يتم تحديد البداية والنهاية.", force=True)
6868
logger.warning("Loop start and end not set; cannot toggle loop.")
6969
return
7070

7171
self.loop_active = not self.loop_active
7272
logger.debug(f"Loop toggled {'ON' if self.loop_active else 'OFF'}.")
7373
if self.loop_active:
7474
logger.debug(f"Loop started from {self.loop_start} ms to {self.loop_end} ms.")
75-
UniversalSpeech.say(f"بدأ التكرار من {self.parent.format_time(self.loop_start)} إلى {self.parent.format_time(self.loop_end)}.")
75+
UniversalSpeech.say(f"بدأ التكرار من {self.parent.format_time(self.loop_start)} إلى {self.parent.format_time(self.loop_end)}.", force=True)
7676
# Start playback from the loop start and start the monitor timer.
7777
self.player.set_position(self.loop_start)
7878
self.player.play()
7979
logger.debug(f"Loop started from {self.parent.format_time(self.loop_start)} to {self.parent.format_time(self.loop_end)}.")
8080
self.monitor_timer.start()
8181
else:
82-
UniversalSpeech.say("تم إيقاف التكرار.")
82+
UniversalSpeech.say("تم إيقاف التكرار.", force=True)
8383
self.monitor_timer.stop()
8484
logger.debug("Loop stopped.")
8585

@@ -128,13 +128,13 @@ def return_to_start(self):
128128
"""Return playback to the loop start point."""
129129
logger.debug("Returning to loop start point.")
130130
if self.loop_start == 0:
131-
UniversalSpeech.say("لم يتم تحديد البداية.")
131+
UniversalSpeech.say("لم يتم تحديد البداية.", force=True)
132132
logger.warning("Cannot return to start; loop start is not set.")
133133
return
134134

135135
self.player.set_position(self.loop_start)
136136
logger.debug(f"Returning to loop start at {self.parent.format_time(self.loop_start)}.")
137-
UniversalSpeech.say(f"يتم التشغيل من: {self.parent.format_time(self.loop_start)}.")
137+
UniversalSpeech.say(f"يتم التشغيل من: {self.parent.format_time(self.loop_start)}.", force=True)
138138

139139
def clear_loop(self):
140140
"""Clear the loop points and stop the loop."""
@@ -150,7 +150,7 @@ def clear_loop(self):
150150
self.monitor_timer.stop()
151151
logger.debug("monitor timer stopped.")
152152

153-
UniversalSpeech.say(F"تم مسح البداية والنهاية وإيقاف التكرار.")
153+
UniversalSpeech.say(F"تم مسح البداية والنهاية وإيقاف التكرار.", force=True)
154154
logger.debug("Loop points cleared.")
155155

156156
def set_loop_delay(self, delay: int):

ui/sura_player_ui/key_handler.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ def __init__(self, parent):
3838

3939
# Mapping shortcut keys to their corresponding actions
4040
self.shortcuts = {
41-
ord("E"): lambda: UniversalSpeech.say(f"{parent.elapsed_time_label.text()}، الوقت المنقَضي."),
42-
ord("R"): lambda: UniversalSpeech.say(f"{parent.remaining_time_label.text()}، الوقت المتبقي."),
43-
ord("T"): lambda: UniversalSpeech.say(f"{parent.total_time.text()}، الوقت الإجمالي."),
44-
ord("C"): lambda: UniversalSpeech.say(f"{parent.reciter_combo.currentText().split(' - ')[0]}، القارئ الحالي."),
45-
ord("V"): lambda: UniversalSpeech.say(f"{parent.surah_combo.currentText()}، السورة الحالية."),
41+
ord("E"): lambda: UniversalSpeech.say(f"{parent.elapsed_time_label.text()}، الوقت المنقَضي.", force=True),
42+
ord("R"): lambda: UniversalSpeech.say(f"{parent.remaining_time_label.text()}، الوقت المتبقي.", force=True),
43+
ord("T"): lambda: UniversalSpeech.say(f"{parent.total_time.text()}، الوقت الإجمالي.", force=True),
44+
ord("C"): lambda: UniversalSpeech.say(f"{parent.reciter_combo.currentText().split(' - ')[0]}، القارئ الحالي.", force=True),
45+
ord("V"): lambda: UniversalSpeech.say(f"{parent.surah_combo.currentText()}، السورة الحالية.", force=True),
4646
ord("I"): lambda: UniversalSpeech.say(
47-
f"{parent.surah_combo.currentText()}، للقارئ، {parent.reciter_combo.currentText()}."
47+
f"{parent.surah_combo.currentText()}، للقارئ، {parent.reciter_combo.currentText()}.", force=True
4848
),
4949
Qt.Key_MediaTogglePlayPause: parent.toggle_play_pause,
5050
Qt.Key_MediaStop: parent.stop,

ui/sura_player_ui/sura_player_ui.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -457,20 +457,20 @@ def OnFilterModeChange(self, active: bool) -> None:
457457
widgets = self.buttons + self.menubar.get_player_actions()
458458
for widget in widgets:
459459
widget.setEnabled(not active)
460-
UniversalSpeech.say("وضع الفلترة مفعَّل. استخدم الأسهم اليمين و اليسار للتنقل بين القُرَّاء و السور، واستخدم الأسهم للأعلى والأسفل لتصفح المحدد، اكتب لتصفية القُرَّاء و السور." if active else "وضع الفلترة معطَّل.")
460+
UniversalSpeech.say("وضع الفلترة مفعَّل. استخدم الأسهم اليمين و اليسار للتنقل بين القُرَّاء و السور، واستخدم الأسهم للأعلى والأسفل لتصفح المحدد، اكتب لتصفية القُرَّاء و السور." if active else "وضع الفلترة معطَّل.", force=True)
461461

462462
def OnActiveCategoryChanged(self, label: str) -> None:
463463
logger.debug(f"Active category changed to: {label}")
464-
UniversalSpeech.say(label)
464+
UniversalSpeech.say(label, force=True)
465465

466466
def OnSearchQueryUpdated(self, search_query: str) -> None:
467467
logger.debug(f"Search query updated: {search_query}")
468-
UniversalSpeech.say(search_query)
468+
UniversalSpeech.say(search_query, force=True)
469469

470470
def OnItemSelectionChanged(self, widget: QComboBox, index: int) -> None:
471471
logger.debug(f"Selection changed in {widget.objectName()} to index {index}")
472472
widget.setCurrentIndex(index)
473-
UniversalSpeech.say(f"{widget.currentText()} {widget.currentIndex() + 1} من {widget.count()}")
473+
UniversalSpeech.say(f"{widget.currentText()} {widget.currentIndex() + 1} من {widget.count()}", force=True)
474474

475475
def OnOutOfRange(self):
476476
logger.debug("Out of range event triggered.")
@@ -484,7 +484,7 @@ def OnFilteredItemsUpdated(self, widget: QComboBox, items: List[Item], selected_
484484

485485
#Set last selected item before filtering
486486
widget.setCurrentText(selected_item_text)
487-
UniversalSpeech.say(f"{widget.currentText()} {widget.currentIndex() + 1} من {widget.count()}", False)
487+
UniversalSpeech.say(f"{widget.currentText()} {widget.currentIndex() + 1} من {widget.count()}", interrupt=False, force=True)
488488
logger.debug(f"Filtered selection set to {widget.currentText()} {widget.currentIndex() + 1} uf {widget.count()}")
489489

490490
def keyPressEvent(self, event: QKeyEvent):

utils/universal_speech.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ class UniversalSpeech:
1212
logger.debug(f"Using screen reader: {reader}")
1313

1414
@classmethod
15-
def say(cls, msg: str, interrupt: bool = True) -> None:
16-
if Config.audio.speak_actions_enabled:
15+
def say(cls, msg: str, interrupt: bool = True, force: bool = False) -> None:
16+
if Config.audio.speak_actions_enabled or force:
1717
cls.universal_speech.say(msg, interrupt)
18-
logger.debug(f"Speaking: {msg} (Interrupt: {interrupt})")
18+
logger.debug(f"Speaking: {msg} (Interrupt: {interrupt}, Force: {force})")
1919
else:
20-
logger.debug(f"Speech action skipped. Message: '{msg}'")
21-
20+
logger.debug(f"Speech action skipped. Message: '{msg}' (Force: {force})")

0 commit comments

Comments
 (0)