42 Commits

Author SHA1 Message Date
hjozwiak e72cc79c6a When dismissing a message, it should be removed from the list and the tree view. 2026-04-06 23:53:46 -04:00
hjozwiak 667c0babcb Add support for getting at the actions of notifications inline. 2026-04-06 23:08:20 -04:00
hjozwiak a8950c42e2 Initial support for mako notification daemon. 2026-04-06 21:09:41 -04:00
hjozwiak 91edf64a72 Drop claude.md. 2026-04-06 20:27:17 -04:00
Storm Dragon 296c47be36 Sounds split off into own tab in settings. 2026-04-05 21:32:06 -04:00
Storm Dragon 5779444d4b Add persisted progress bar beep interval setting 2026-04-05 21:05:39 -04:00
Storm Dragon c072f903db Add sounds tab design spec 2026-04-05 20:48:41 -04:00
Storm Dragon 64ad1ab3e0 Hopefully fixed weird gstreamer traceback. 2026-04-04 23:04:33 -04:00
Storm Dragon 20e61d6259 Merge branch 'testing' 2026-04-04 21:44:47 -04:00
Storm Dragon a750761f61 Steam UI improvements. 2026-04-04 20:22:54 -04:00
Storm Dragon 03b3880622 Merge branch 'testing' 2026-04-04 19:05:35 -04:00
Storm Dragon f4af54228a Tightened up Steam notifications. Fixed a system notifications regression.? 2026-04-04 19:04:45 -04:00
Storm Dragon 518d2b3bb6 Attempt to make the sound system more robust. Improve some web component detection. Fixed a place where Cthulhu gets stuck on netgear's web interface. 2026-04-04 18:31:11 -04:00
Storm Dragon 7043f08dab Simplify GStreamer sound playback 2026-03-23 13:51:42 -04:00
Storm Dragon d0bc7d8a3a I tested these changes for so long I actually forgot what they were, but they seem to work, so committing. 2026-03-23 12:46:27 -04:00
Storm Dragon 438fae4fef Fix script manager resets and isolate startup sound 2026-03-23 12:44:12 -04:00
Storm Dragon a7cd1d033a Speculative fix on preferences weirdness. 2026-03-09 01:14:01 -04:00
Storm Dragon c4890f31af Fix 2026.03.02 release versioning 2026-03-02 17:56:45 -05:00
Storm Dragon c44245189a Merge branch 'testing' 2026-03-02 15:42:15 -05:00
Storm Dragon c7b8e4a30d Clean stale autostart source references from translations 2026-03-02 15:42:04 -05:00
Storm Dragon 20fe1a7e30 Remove autogenerated autostart desktop template 2026-03-02 15:38:29 -05:00
Storm Dragon 25931758f7 Merge branch 'testing'
# Conflicts:
#	distro-packages/Arch-Linux/PKGBUILD
#	meson.build
#	src/cthulhu/cthulhuVersion.py
2026-03-02 15:37:50 -05:00
Storm Dragon daf57ef22c Removed the autogenerated autostart desktop file. Moved the desktop file to contrib so it's still available if people want it. 2026-02-25 23:20:05 -05:00
Storm Dragon 1d2d727fa2 Requested feature added. It is now possible to customize speech used for echo settings including speech module, voice, rate, volume, pitch. 2026-02-22 01:44:19 -05:00
Storm Dragon 11bd7107d2 Attempt to stop plugins from spontaneously re-enabling themselves. 2026-02-19 02:40:46 -05:00
Storm Dragon 95d33047fa Fix prefs state churn and sound-only role speech
Some settings were being reset when tab changed and a key was pressed, e.g. control.

Radio buttons were still announced even with sound only set.

Controls for AI assistant tab were vanishing after being set.
2026-02-18 07:03:12 -05:00
Storm Dragon 523b896053 Couple minor bug fixes, new speech code added in prefs. 2026-02-18 06:10:57 -05:00
Storm Dragon 9152455227 Speech in settings now uses the voice when switched to it. 2026-02-18 06:07:55 -05:00
Storm Dragon c0fdaca4d0 Merge remote-tracking branch 'origin/web-and-punctuation-fixes' into testing 2026-02-17 14:50:01 -05:00
destructatron 8312a842c1 Fix duplicate role name when aria-roledescription is present
When an element has aria-roledescription (e.g. Discord messages use
'Message'), _generateRoleName was adding both the roledescription AND
the standard localized role name (e.g. 'article'). This resulted in
the role being announced twice.

The aria-roledescription attribute is intended to replace the standard
role name, not supplement it. Return early after adding the
roledescription to match Orca's behavior.
2026-02-17 19:21:36 +00:00
destructatron 07138197cb Fix web content editable label, line boundary, and punctuation bugs
Bug 1: Content editable entry label not announced on caret-nav focus
- When navigating into a content editable via caret navigation (e.g. down
  arrow from message list to message entry in Discord), the label and role
  were suppressed because the code treated entering the field the same as
  navigating within it.
- Fixed locus_of_focus_changed in web/script.py to detect when focus enters
  a content editable from outside and generate full object speech.
- Fixed _generateLabelOrName in web/speech_generator.py to preserve the
  label when the prior object was outside the content editable.

Bug 2: Adjacent button included in line contents on first line
- When reading line contents inside a content editable, the layout-mode
  expansion could walk outside the content editable boundary and include
  adjacent UI elements (e.g. a 'More options' button) that happened to
  share the same visual line.
- Fixed _getLineContentsAtOffset in web/script_utilities.py to stop
  expanding at content editable boundaries in both directions.

Bug 3: Punctuation stripped from live regions and AT-SPI announcements
- presentMessage uses resetStyles=True by default, which sets punctuation
  to NONE for system voice messages. This is correct for generated text
  but wrong for user content in live regions and AT-SPI announcements.
- Fixed liveregions.py pumpMessages and default.py onAnnouncement to pass
  resetStyles=False, preserving the user's punctuation settings.
2026-02-17 19:07:41 +00:00
Storm Dragon ed78ffc248 Visual speech monitor added to speech history plugin. Toggle with cthulhu+shift+D 2026-02-17 08:40:51 -05:00
Storm Dragon 4add36f5ca latest changed merged, seems to be reasonably stable. 2026-02-17 08:01:47 -05:00
Storm Dragon 40e63150a6 Read a list of applications that should always be started in sleep mode from sleep.toml. 2026-02-17 07:57:14 -05:00
Storm Dragon 4dba0ec0cd Fixed a bug with sleep mode, was not suspending review keys for sleeping applications. 2026-02-16 14:55:56 -05:00
Storm Dragon e6f780c38b New code tested and seems pretty stable so merged and bumped version. 2026-02-15 12:10:36 -05:00
Storm Dragon 0f7f73a6a0 Fixed flat review bug affecting some sites in chrome. 2026-02-13 13:23:14 -05:00
Storm Dragon aa71d02036 Merge remote-tracking branch 'origin/keyboard-monitoring-api' into testing 2026-02-13 11:19:40 -05:00
destructatron 51ef3de672 Port keyboard monitoring API from Orca, and fix flat review bug in GTK apps 2026-02-13 10:14:04 +00:00
Storm Dragon c6049ef5f3 Preparing for release. 2026-01-26 13:07:33 -05:00
Storm Dragon 78ef51d01f Latest code, hopefully stable. 2026-01-19 05:24:48 -05:00
Storm Dragon 30a40f6974 Merged dbus implementation for plugins. 2026-01-12 11:54:42 -05:00
150 changed files with 7068 additions and 1170 deletions
+15
View File
@@ -14,6 +14,16 @@ This repository is a screen reader. Prioritize accessibility, correctness, and s
- `meson compile -C _build`
- `meson install -C _build`
## Runtime target and testing rules
- Make source changes in this repo, not in `~/.local/lib/python*/site-packages/cthulhu/`, unless the user explicitly asks for an installed-package hotfix.
- If you confirm the active import comes from `~/.local/...`, that does **not** mean you should edit there. It means you should update the repo and then run `./build-local.sh` to replace the installed copy for testing.
- Default test/apply workflow for local Cthulhu fixes:
- edit repo files
- run `./build-local.sh`
- reproduce/test against the refreshed `~/.local` install
- If repo and installed behavior differ, prefer rebuilding with `./build-local.sh` over patching the installed package directly.
- Treat direct edits under `~/.local/.../cthulhu/` as an exception path that requires explicit user approval.
## Coding guidelines
- **When modifying existing code:** follow the surrounding codes conventions.
- **When writing new code from scratch:** prefer
@@ -55,3 +65,8 @@ This repository is a screen reader. Prioritize accessibility, correctness, and s
## Meson install reminder (important)
- If you add new Python modules under `src/cthulhu/`, update `src/cthulhu/meson.build` so they get installed (otherwise imports can fail after install).
- If you add a new plugin directory, update `src/cthulhu/plugins/meson.build` and add a `meson.build` in the plugin directory.
## Common Cthulhu agent mistakes
- Checking the import origin, seeing `~/.local/...`, and then editing the installed package instead of the repo.
- Forgetting that `./build-local.sh` is the normal way to apply repo changes into the installed copy for testing.
- Making repo fixes and then diagnosing the old installed copy without rebuilding.
-182
View File
@@ -1,182 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Cthulhu is a fork of the Orca screen reader, designed as a desktop-agnostic screen reader for Linux. It works with applications supporting AT-SPI (Assistive Technology Service Provider Interface) including GTK+, Qt, Java Swing, LibreOffice, Gecko, and WebKitGtk.
**Key differentiators from Orca:**
- Desktop-agnostic: Works on KDE, XFCE, i3, Sway, and other environments (not just GNOME)
- Extensible plugin architecture using pluggy framework
- D-Bus remote control interface for external automation
- Enhanced support for tiling window managers
## Build Commands
```bash
# Local development build (installs to ~/.local)
./build-local.sh
# Test local installation
./test-local.sh
# Run local version
~/.local/bin/cthulhu
# Clean build artifacts and local installation
./clean-local.sh
./clean-local.sh --build-only # Clean only build artifacts
./clean-local.sh --install-only # Remove only local installation
# Manual Meson build
meson setup _build --prefix=$HOME/.local
meson compile -C _build
meson install -C _build
```
## Testing
Manual testing is recommended. The legacy keystroke-driven test harness has been removed.
## Architecture Overview
### Core Components (`src/cthulhu/`)
**Event & Input Processing:**
- `event_manager.py` - Central AT-SPI event handling and routing
- `input_event_manager.py` - Keyboard/mouse input processing
- `input_event.py` - Input event data structures
- `focus_manager.py` - Focus tracking across applications
**Accessibility Layer (ax_* files):**
- `ax_object.py` - Core accessible object abstraction
- `ax_utilities.py` - Common accessibility utilities
- `ax_utilities_role.py` - Role-based accessibility helpers
- `ax_utilities_collection.py` - Collection traversal utilities
- `ax_text.py`, `ax_table.py`, `ax_component.py` - Specialized interfaces
**Output Systems:**
- `speech.py`, `speechdispatcherfactory.py` - Speech synthesis
- `braille.py`, `braille_generator.py` - Braille display support
- `speech_generator.py` - Generate speech from accessible objects
- `sound.py`, `sound_generator.py` - Audio cue generation
**Script System:**
- `script_manager.py` - Loads/manages application-specific scripts
- `script.py` - Base script class
- `scripts/default.py` - Default behavior for all applications
- `scripts/apps/` - Application-specific customizations (Firefox, LibreOffice, etc.)
- `scripts/toolkits/` - Toolkit-specific scripts (GTK, Qt, WebKitGtk)
- `scripts/web/` - Web content handling
**Plugin System:**
- `plugin.py` - Base plugin class with `cthulhu_hookimpl` decorator
- `plugin_system_manager.py` - Plugin discovery and lifecycle
- `plugins/` - Built-in plugins (OCR, Clipboard, SpeechHistory, etc.)
**D-Bus Remote Control:**
- `dbus_service.py` - D-Bus service implementation
- Service: `org.stormux.Cthulhu.Service`
- Path: `/org/stormux/Cthulhu/Service`
**Settings & State:**
- `settings_manager.py` - User preferences persistence
- `settings.py` - Default settings values
- `cthulhu_state.py` - Runtime state (active script, focus, etc.)
### Key Design Patterns
**Script Inheritance:** Application scripts extend `default.Script`, overriding methods for custom behavior. The script manager selects scripts based on the focused application.
**Event Flow:** AT-SPI events → `event_manager` → active script's event handler → generators → output systems (speech/braille)
**Plugin Hooks:** Plugins implement hooks via `@cthulhu_hookimpl` decorator. Use `registerGestureByString()` for keybindings.
## Adding New Modules
When adding new Python modules under `src/cthulhu/`:
1. **Update `src/cthulhu/meson.build`** - Add the `.py` file to `cthulhu_python_sources`
2. **For new script modules** (e.g., `scripts/newmodule/`):
- Create the directory with `__init__.py` and `script.py`
- Add `meson.build` in the new directory
- Add subdirectory to `src/cthulhu/scripts/meson.build`
3. **For new plugins**:
- Create directory under `src/cthulhu/plugins/` with:
- `__init__.py`, `plugin.py`, `plugin.info`, `meson.build`
- Add subdirectory to `src/cthulhu/plugins/meson.build`
## Plugin Structure
```
src/cthulhu/plugins/MyPlugin/
├── __init__.py # from .plugin import *
├── plugin.py # Main implementation extending Plugin
├── plugin.info # Metadata (name, version, description, etc.)
└── meson.build # install_data for .py and .info files
```
Example plugin.py:
```python
from cthulhu.plugin import Plugin, cthulhu_hookimpl
class MyPlugin(Plugin):
@cthulhu_hookimpl
def activate(self, plugin=None):
if plugin is not None and plugin is not self:
return
self.registerGestureByString(self.myHandler, "description", "kb:cthulhu+key")
def myHandler(self, script=None, inputEvent=None):
self.app.getDynamicApiManager().getAPI('CthulhuState').activeScript.presentMessage('Message')
return True
```
## D-Bus Testing
```bash
# Check service availability
busctl --user list | grep Cthulhu
# Get version
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service GetVersion
# Present message
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service PresentMessage s "Hello"
# Introspect available methods
busctl --user introspect org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service
```
## Key Keybindings
- `Cthulhu+Space` - Open preferences
- `Cthulhu+H` - Enter learn mode
- `Cthulhu+Ctrl+Alt+Shift+Q` - Toggle sleep mode for current application
- `Cthulhu+Q` - Quit Cthulhu
## Self-Voicing Interface
External applications can speak through Cthulhu via Unix socket:
```bash
echo "Hello world" | socat - UNIX-CLIENT:/tmp/cthulhu.sock
echo "<!#APPEND#!>Without interrupt" | socat - UNIX-CLIENT:/tmp/cthulhu.sock
```
## Dependencies
**Core:** Python 3.9+, pygobject-3.0, gtk+-3.0, AT-SPI2, ATK
**Speech:** python-speechd, gstreamer-1.0
**Plugins:** pluggy, python-dasbus (optional, for D-Bus)
**Braille:** BrlTTY, BrlAPI, liblouis (optional)
## Repository
- **Main repo:** https://git.stormux.org/storm/cthulhu
- **Community:** IRC #stormux on irc.stormux.org
- **Email patches:** storm_dragon@stormux.org
+2 -2
View File
@@ -98,11 +98,11 @@ git status
## Dependencies
- **Runtime**: python3, pygobject-3.0, pluggy, AT-SPI2
- **Runtime**: python3, pygobject-3.0, pluggy, tomlkit, AT-SPI2
- **Build**: meson, ninja, gettext
- **Optional**: dasbus (for D-Bus service), BrlTTY, speech-dispatcher, piper-tts
Install build dependencies on Arch Linux:
```bash
sudo pacman -S meson ninja gettext python-dasbus
sudo pacman -S meson ninja gettext python-dasbus python-tomlkit
```
+2
View File
@@ -179,6 +179,7 @@ Ensure you have the development dependencies installed:
```bash
sudo pacman -S python python-gobject gtk3 at-spi2-core at-spi2-atk \
python-speechd gstreamer python-pluggy python-dasbus \
python-tomlkit \
meson ninja pkgconf intltool gettext
```
@@ -187,6 +188,7 @@ sudo pacman -S python python-gobject gtk3 at-spi2-core at-spi2-atk \
sudo apt install python3 python3-gi python3-gi-cairo gir1.2-gtk-3.0 \
at-spi2-core libatk-adaptor python3-speechd \
gstreamer1.0-plugins-base python3-pluggy python3-dasbus \
python3-tomlkit \
meson ninja-build pkg-config intltool gettext
```
+6
View File
@@ -26,6 +26,12 @@ for cmd in meson ninja python3; do
fi
done
if ! python3 -c "import tomlkit" 2>/dev/null; then
echo "Error: Python module tomlkit is not installed"
echo "Please install: python-tomlkit"
exit 1
fi
# Check for optional dependencies
missingOptional=()
if ! python3 -c "import gi" 2>/dev/null; then
-8
View File
@@ -8,13 +8,11 @@ set -e # Exit on error
# Colors for output (only if stdout is a terminal)
if [[ -t 1 ]]; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
else
RED=''
GREEN=''
YELLOW=''
BLUE=''
@@ -56,12 +54,6 @@ if [[ $REPLY =~ ^[Yy]$ ]]; then
# Remove data files
# Remove desktop files
if [[ -f "$HOME/.local/share/applications/cthulhu-autostart.desktop" ]]; then
rm -f "$HOME/.local/share/applications/cthulhu-autostart.desktop"
echo " Removed: ~/.local/share/applications/cthulhu-autostart.desktop"
fi
# Remove icons
for size in 16x16 22x22 24x24 32x32 48x48 256x256 scalable symbolic; do
icon_path="$HOME/.local/share/icons/hicolor/$size/apps"
-11
View File
@@ -1,11 +0,0 @@
[Desktop Entry]
Type=Application
Name=Cthulhu Screen Reader
Exec=cthulhu
NoDisplay=true
# Desktop-neutral autostart - no GNOME-specific conditions
# Users can enable/disable via their desktop environment's accessibility settings
# or by adding/removing this file from ~/.config/autostart/
X-GNOME-AutoRestart=true
Categories=Accessibility;
Keywords=screen;reader;accessibility;speech;braille;
+2 -7
View File
@@ -1,7 +1,7 @@
# Maintainer: Storm Dragon <storm_dragon@stormux.org>
pkgname=cthulhu
pkgver=2026.01.19
pkgver=2026.03.02
pkgrel=1
pkgdesc="Desktop-agnostic screen reader with plugin system, forked from Orca"
url="https://git.stormux.org/storm/cthulhu"
@@ -84,7 +84,7 @@ makedepends=(
)
install=cthulhu.install
source=(
"git+https://git.stormux.org/storm/cthulhu.git"
"git+https://git.stormux.org/storm/cthulhu.git#tag=${pkgver}"
"cthulhu.install"
)
b2sums=(
@@ -92,11 +92,6 @@ b2sums=(
'SKIP'
)
pkgver() {
cd cthulhu
grep "^version = " src/cthulhu/cthulhuVersion.py | sed 's/version = "\(.*\)"/\1/'
}
build() {
cd cthulhu
arch-meson _build
@@ -0,0 +1,171 @@
# Sounds Tab Design
Date: 2026-04-05
## Context
Cthulhu currently stores several non-speech sound settings in the general settings file, but the preferences dialog does not present them coherently:
- The General tab contains an inline Sound section for backend, theme, and role-sound presentation.
- The progress-bar beep checkbox lives in the General tab's progress-bar section.
- `soundVolume` exists in settings and the user's active profile, but there is no UI control for it.
- `enableSound`, `playSoundForRole`, `playSoundForState`, `playSoundForPositionInSet`, and `playSoundForValue` exist as persisted settings but are not currently exposed in the dialog.
- `progressBarBeepInterval` exists in runtime defaults but is not part of the normal persisted general-settings key list.
The result is that sound-related behavior is split across the dialog and some active settings cannot be inspected or changed from the UI.
## Goals
- Add a dedicated `Sounds` preferences tab.
- Move currently exposed sound-related controls out of `General` and into `Sounds`.
- Move the progress-bar beep option into `Sounds` while leaving the rest of the progress-bar section in `General`.
- Expose currently hidden sound-related settings in the UI.
- Add a UI control for `soundVolume`.
- Expose and persist `progressBarBeepInterval`.
- Preserve the existing settings model and save format.
- Avoid clobbering unrelated settings when saving preferences.
## Non-Goals
- No refactor of the broader preferences architecture.
- No changes to sound playback implementation outside what is needed to load and save settings correctly.
- No new settings schema beyond persisting the existing hidden `progressBarBeepInterval`.
- No dynamic enable/disable logic for sound controls in this pass.
## Design Summary
Add a new notebook page labeled `Sounds` and make it the single home for non-speech sound configuration. Remove the inline Sound frame from `General`. Keep the existing progress-bar speech/braille controls and shared progress-bar behavior controls in `General`, but move beep-specific controls into `Sounds`.
The new tab will use existing settings keys wherever possible and will save through the existing `prefsDict` and settings-manager flow.
## Sounds Tab Layout
The `Sounds` tab will contain three sections.
### Output
- `enableSound` checkbox
- `soundVolume` slider
- `soundSink` combo box
`soundVolume` should be represented by a native `GtkScale` and persisted back to the existing floating-point `soundVolume` setting. The control should initialize from `prefsDict.get("soundVolume", settings.soundVolume)`.
For this implementation, the slider should match the stored setting directly rather than introducing a new percentage representation. That keeps the implementation small and avoids conversion-only complexity in a settings path that already exists.
### Presentation
- `soundTheme` combo box
- `roleSoundPresentation` combo box
- `playSoundForRole` checkbox
- `playSoundForState` checkbox
- `playSoundForPositionInSet` checkbox
- `playSoundForValue` checkbox
These controls will expose already-existing settings and use the same `prefsDict` update pattern already used by the current dialog.
### Alerts
- `beepProgressBarUpdates` checkbox
- `progressBarBeepInterval` spin button
This section controls only beep-based progress-bar alerts. The label should make it clear that the interval is beep-specific, not the general progress-bar announcement interval.
## General Tab Changes
Keep these controls in `General`:
- `speakProgressBarUpdates`
- `brailleProgressBarUpdates`
- `progressBarUpdateInterval`
- `progressBarVerbosity`
- `ignoreStatusBarProgressBars`
Remove these from `General`:
- the inline Sound frame
- `beepProgressBarUpdates`
This preserves the current organization for general progress-bar announcement behavior while moving sound-only concerns into the new tab.
## Settings and Persistence
### Existing Keys Reused
The new UI will continue to use the existing settings keys:
- `enableSound`
- `soundVolume`
- `soundSink`
- `soundTheme`
- `roleSoundPresentation`
- `playSoundForRole`
- `playSoundForState`
- `playSoundForPositionInSet`
- `playSoundForValue`
- `beepProgressBarUpdates`
### Persisted Hidden Key
Add `progressBarBeepInterval` to the persisted general-settings key list so it round-trips through:
- defaults in `settings.py`
- settings-manager general settings
- TOML backend save/load
- `prefsDict` in the preferences dialog
This avoids the current mismatch where beep interval exists as a runtime default but is not part of the normal persisted general-settings path.
### Save Behavior
The implementation should continue to update individual keys in `prefsDict` and then rely on the existing general-settings save flow. No bulk replacement of the whole settings structure should be introduced.
This is specifically intended to avoid accidental overwrites of unrelated settings already present in `user-settings.toml`.
## Default Values
- Keep `progressBarUpdateInterval = 10` as the default for speech and braille progress-bar updates.
- Keep `progressBarBeepInterval = 0` as the default for beep-based progress-bar updates.
- Keep `soundVolume = 0.5` as the existing default unless the user explicitly changes it.
The new UI should reflect these values accurately on load.
## Accessibility
Use native GTK controls and follow the existing preferences-dialog patterns:
- every label must be associated with its control via `mnemonic_widget`
- checkboxes should use the existing `checkButtonToggled` convention when possible
- combo boxes should keep proper `label-for` / `labelled-by` relationships
- no custom-drawn controls
- no keyboard traps
The new tab should be fully reachable with standard tab navigation.
## Implementation Notes
Expected files to change:
- `src/cthulhu/cthulhu-setup.ui`
- `src/cthulhu/cthulhu_gui_prefs.py`
- `src/cthulhu/settings.py`
Implementation should:
- add the new notebook page and move or recreate the relevant widgets there
- initialize and save the new sound controls using existing dialog patterns
- add explicit handling for `soundVolume`
- add explicit handling for `progressBarBeepInterval`
- keep all unrelated preference behavior unchanged
## Verification
The implementation should be considered complete only after all of the following are checked:
1. The preferences dialog opens and the new `Sounds` tab is present.
2. Existing sound settings load into the correct controls.
3. Changing sound settings updates `prefsDict` without breaking unrelated settings.
4. Saving preferences preserves unrelated keys in `user-settings.toml`.
5. `progressBarBeepInterval` is written and reloaded correctly.
6. The General tab still handles speech/braille progress-bar settings correctly.
7. Touched Python files pass compile checks.
8. Manual verification confirms keyboard navigation and label association remain intact.
+1 -11
View File
@@ -1,5 +1,5 @@
project('cthulhu',
version: '2026.01.19-testing',
version: '2026.03.02-master',
meson_version: '>= 1.0.0',
)
@@ -93,16 +93,6 @@ else
summary += {'sound support': 'no (missing gstreamer)'}
endif
# Integration with session startup
i18n.merge_file(
input: 'cthulhu-autostart.desktop.in',
output: '@BASENAME@',
type: 'desktop',
po_dir: meson.project_source_root() / 'po',
install: true,
install_dir: get_option('sysconfdir') / 'xdg' / 'autostart',
)
# Update icon cache manually (desktop-neutral) - optional, ignore failures
gtk_update_icon_cache = find_program('gtk4-update-icon-cache', required: false)
if gtk_update_icon_cache.found()
-1
View File
@@ -1,6 +1,5 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
cthulhu-autostart.desktop.in
src/cthulhu/braille_rolenames.py
src/cthulhu/brltablenames.py
src/cthulhu/chnames.py
-2
View File
@@ -13,11 +13,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-DamnedLies-Scope: partial\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.6.10\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector de pantalla Cthulhu"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "lector de pantalla; fabla; braille;"
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
"X-Poedit-Language: Arabic\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "قارئ الشاشة Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "شاشة;قارئ;إمكانية الوصول;كلام;برايل;"
-2
View File
@@ -19,11 +19,9 @@ msgstr ""
"X-Poedit-Language: Asturian\n"
"X-Poedit-SourceCharset: utf-8\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Llector de pantalla d'Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -17,11 +17,9 @@ msgstr ""
"X-Generator: Poedit 3.3.2\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Чытач з экрана Cthulhu"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "чытач з экрана;экран;голас;маўленне;Брайль;"
-2
View File
@@ -23,11 +23,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu — екранен четец"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "екран;четец;достъпност;говор;брайл;"
-2
View File
@@ -21,12 +21,10 @@ msgstr ""
"X-Generator: KBabel 1.9.1\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "অর্কা স্ক্রীন রিডার / বিবর্ধন"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,12 +18,10 @@ msgstr ""
"X-Generator: KBabel 1.9.1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu'র বৈশিষ্ট্য"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -15,11 +15,9 @@ msgstr ""
"X-Launchpad-Export-Date: 2015-02-05 06:46+0000\n"
"X-Generator: Poedit 1.7.4\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu čitač ekrana"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "čitač ekrana;govor;brailleovo pismo;"
-2
View File
@@ -27,11 +27,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector de pantalla Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "pantalla;lector;accessibilitat;veu;braille;"
-2
View File
@@ -27,11 +27,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Poedit 1.8.11\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector de pantalla Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "lector de pantalla;pronunciació;braille;"
-2
View File
@@ -19,12 +19,10 @@ msgstr ""
"X-Launchpad-Export-Date: 2020-05-04 21:32+0000\n"
"X-Generator: Poedit 2.3\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "خوێنەری پەردەی ئۆرکا"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Čtečka obrazovky Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "obrazovka;čtečka;přístupnost;řeč;braille;"
-2
View File
@@ -17,12 +17,10 @@ msgstr ""
"Plural-Forms: nplurals=4; plural= (n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != "
"11) ? 2 : 3;\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Hoffterau Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -32,11 +32,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0.1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Skærmlæseren Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "skærm;læser;tilgængelighed;tale;braille;"
-2
View File
@@ -37,11 +37,9 @@ msgstr ""
"X-Generator: Poedit 3.3.2\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu-Bildschirmleser"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "bildschirm;leser;barrierefreiheit;sprache;braille;"
-2
View File
@@ -20,12 +20,10 @@ msgstr ""
"X-Poedit-SourceCharset: utf-8\n"
"Plural-Forms: nplurals=2; plural=(n!=1)\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "ཨོར་ཀ་གསལ་གཞི་ལྷག་བྱེད་/ཆེ་ཤེལ་"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -28,11 +28,9 @@ msgstr ""
"X-Generator: Poedit 2.3\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Αναγνώστης οθόνης Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "οθόνη;αναγνώστης;προσβασιμότητα;ομιλία;μπράιγ;"
-2
View File
@@ -17,11 +17,9 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -21,11 +21,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 45.3\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu Screen Reader"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "screen reader;speech;braille;"
-2
View File
@@ -21,11 +21,9 @@ msgstr ""
"X-Generator: Poedit 3.2.2\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Ekranlegilo Orko"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ekranlegilo;parolo;brajlo;"
-2
View File
@@ -28,11 +28,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Gtranslator 45.alpha0\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector de pantalla Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "lector;pantalla;accesibilidad;voz;braille;"
-2
View File
@@ -20,12 +20,10 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu ekraanilugeja ja luup"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu pantaila-irakurlea"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "pantaila;irakurlea;irisgarritasuna;mintzamena;braillea;"
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.4\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "صفحه‌خوان اورکا"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -27,11 +27,9 @@ msgstr ""
"X-Generator: Poedit 3.3.2\n"
"X-Poedit-Bookmarks: 814,-1,-1,-1,-1,-1,-1,-1,-1,-1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu-näytönlukija"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "näyttö;lukija;saavutettavuus;puhe;pistekirjoitus;"
-2
View File
@@ -31,11 +31,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lecteur d’écran Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "lecteur;écran;accessibilité;parole;braille;"
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.3\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,12 +18,10 @@ msgstr ""
"Plural-Forms: nplurals=5; plural=n==1 ? 0 : (n%10==1 || n%10==2) ? 1 : "
"(n%10>=3 && n%10<= 6) ? 2 : ((n%10>=7 && n%10<=9) || n==10) ? 3 : 4;\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Léitheoir Scáileáin agus Formhéadaitheoir Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -34,11 +34,9 @@ msgstr ""
"X-DL-Domain: po\n"
"X-DL-State: Translating\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector da pantalla Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "pantalla;lector;accesibilidade;fala;braille;"
-2
View File
@@ -33,12 +33,10 @@ msgstr ""
"\n"
"\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu સ્ક્રીન વાંચક અને વિસ્તૃતકારક"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -14,11 +14,9 @@ msgstr ""
"2 : 3);\n"
"X-Generator: Poedit 3.4.1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "מקריא המסך Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "מסך;קורא;נגישות;דיבור;ברייל;"
-2
View File
@@ -22,11 +22,9 @@ msgstr ""
"\n"
"X-Generator: Lokalize 1.5\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu स्क्रीन वाचक"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "स्क्रीन रीडर;भाषण;ब्रेल;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"X-Launchpad-Export-Date: 2016-09-15 12:40+0000\n"
"X-Generator: Poedit 1.6.10\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu čitač zaslona"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "čitač zaslona;govor;brajica;"
-2
View File
@@ -22,11 +22,9 @@ msgstr ""
"X-Generator: Poedit 2.3\n"
# Megjegyzés: Mivel mindenhol régóta Gáborral egyeztetve az Cthulhu nevet magyarosan Orkaként írjuk a fordításban, így a fordítást megváltoztattam Orka képernyőolvasóra az Cthulhu képernyőolvasó helyett.
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Orka képernyőolvasó"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "képernyő;olvasó;akadálymentesítés;beszéd;braille;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Pembaca Layar Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "layar;pembaca;aksesibilitas;ucapan;braille;"
-2
View File
@@ -17,11 +17,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Lokalize 1.5\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu skjálestur"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -39,11 +39,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Gtranslator 42.0\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lettore schermo Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "lettore;schermo;accessibilità;voce;braille;"
-2
View File
@@ -25,11 +25,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu スクリーンリーダー"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "スクリーン;リーダー;アクセシビリティ;音声;点字;"
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu - ეკრანის მკითხველი"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ეკრანი;მკითხველი;ხელმისაწვდომობა;მეტყველება;ბრაილი;"
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 3.0\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu экраннан оқитын қолданбасы"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,12 +18,10 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: KBabel 1.11.4\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "ಆದ್ಯತೆಗಳು"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -15,11 +15,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu 화면 낭독기"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "화면;리더;접근성;음성;점자;"
-2
View File
@@ -25,11 +25,9 @@ msgstr ""
"(n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu ekrano skaityklė"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ekrano skaityklė;kalba;brailio raštas;"
-2
View File
@@ -23,11 +23,9 @@ msgstr ""
"2);\n"
"X-Generator: Lokalize 21.12.3\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu ekrāna lasītājs"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ekrāna lasītājs;runa;Brails;"
-2
View File
@@ -19,12 +19,10 @@ msgstr ""
"\n"
"\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu स्क्रीन पाठक / आवर्द्धक"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural= n==1 || n%10==1 ? 0 : 1\n"
"X-Generator: KBabel 1.11.4\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu читач на екранот"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -22,12 +22,10 @@ msgstr ""
"X-Generator: Poedit 2.0.1\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "സ്ക്രീന്‍ വായന അവസാനിപ്പിക്കാം."
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,12 +18,10 @@ msgstr ""
"X-Generator: KBabel 1.9.1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "वर्धक भिंग"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 2.0.6\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Pembaca skrin Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "skrin;pembaca;kebolehcapaian;pertuturan;braille;"
-2
View File
@@ -19,11 +19,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu skjermleser"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "skjerm;leser;tilgjengelighet;tale;blindeskrift;"
-2
View File
@@ -13,11 +13,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0.1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "ओर्का दृष्टि वाचक"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "दृष्टि वाचक; वाचन;ब्रेल;"
-2
View File
@@ -31,11 +31,9 @@ msgstr ""
"X-Generator: Poedit 3.2.2\n"
# vergrootglas/loep
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu schermlezer"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "scherm;lezer;toegankelijkheid;spraak;braille;"
-2
View File
@@ -18,12 +18,10 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu skjermlesar og forstørringsglas"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -23,11 +23,9 @@ msgstr ""
"X-Launchpad-Export-Date: 2015-05-21 18:05+0000\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector d'ecran Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
"lector d'ecran;oral;braille;votz;sintèsi vocala;sintesi vocala;lector "
-2
View File
@@ -22,12 +22,10 @@ msgstr ""
"\n"
"\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "ଓର୍କା ସ୍କ୍ରିନ ପାଠକ /ଛୋଟକୁ ବଡ ଦେଖଉଥିବା ଉପକରଣ "
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-Bookmarks: 589,-1,-1,-1,-1,-1,-1,-1,-1,-1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "ਓਰਕਾ ਸਕਰੀਨ ਰੀਡਰ"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Czytnik ekranowy Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "czytnik;ekran;dostępność;mowa;braille;"
-2
View File
@@ -28,11 +28,9 @@ msgstr ""
"X-Source-Language: C\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Leitor de ecrã Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "leitor;ecrã;acessibilidade;voz;braille;"
-2
View File
@@ -49,11 +49,9 @@ msgstr ""
"X-DL-Domain: po\n"
"X-DL-State: Translating\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Leitor de tela Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "leitor;tela;acessibilidade;voz;braille;"
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"X-Project-Style: gnome\n"
"X-Poedit-SourceCharset: UTF-8\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cititorul de ecran Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ecran;cititor;accesibilitate;vorbire;braille;"
-2
View File
@@ -22,11 +22,9 @@ msgstr ""
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Экранный диктор Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "экран;чтец;доступность;речь;брайль;"
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: KBabel 1.11.4\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -19,11 +19,9 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
"X-Generator: Gtranslator 2.91.7\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Ukončí čítačku obrazovky"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -22,11 +22,9 @@ msgstr ""
"X-Poedit-SourceCharset: utf-8\n"
"X-Generator: Poedit 3.0.1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Zaslonski bralnik Orka"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "govor;zaslonski bralnik;Braillova pisava;brajica;povečevalnik"
-2
View File
@@ -17,12 +17,10 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Ekrani Zmadhues (Lupë)"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -21,11 +21,9 @@ msgstr ""
"X-Project-Style: gnome\n"
"X-Generator: Poedit 3.1.1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Читач екрана Орка"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "читач екрана;говор;брајева азбука;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"X-Project-Style: gnome\n"
"X-Generator: Poedit 2.0.3\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Čitač ekrana Orka"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "čitač ekrana;govor;brajeva azbuka;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu skärmläsare"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "skärm;läsare;tillgänglighet;tal;punktskrift;"
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n!=1);\\n\n"
"\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "ஆர்கா திரை படிப்பி "
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "திரைபடிப்பான்;பேசுதல்;ப்ரெய்ல்;"
-2
View File
@@ -23,11 +23,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
"X-Generator: KBabel 1.11.4\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "ఓర్కా తెరచదువరి"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.6.3\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Хонандаи экрани Cthulhu"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "хонандаи экран;нутқ;брайл;"
-2
View File
@@ -19,11 +19,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "โปรแกรมอ่านหน้าจอ Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "หน้าจอ;อ่าน;การเข้าถึง;เสียงพูด;อักษรเบรลล์;"
-2
View File
@@ -27,11 +27,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.4\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu Ekran Okuyucu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ekran;okuyucu;erişilebilirlik;konuşma;braille;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu ئېكران ئوقۇغۇ"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "screen reader;speech;braille;ئېكران ئوقۇغۇچ;تاۋۇش;ئەمالار ئېلىپبەسى;"
-2
View File
@@ -26,11 +26,9 @@ msgstr ""
"n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Lokalize 20.12.0\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Інструмент читання з екрана «Cthulhu»"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "екран;читач;доступність;мовлення;брайль;"
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: LocFactoryEditor 1.8\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Trình đọc màn hình Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "màn hình;đọc;trợ năng;giọng nói;chữ nổi;"
-2
View File
@@ -29,11 +29,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu 屏幕阅读器"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "屏幕;阅读器;无障碍;语音;盲文;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 1.6.5\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu 螢幕閱讀器"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "screen reader;speech;braille;螢幕閱讀器;語音;點字;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 1.8.12\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu 螢幕閱讀器"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "螢幕;閱讀器;無障礙;語音;點字;"
+37 -2
View File
@@ -204,10 +204,21 @@ class AXHypertext:
@staticmethod
def find_child_at_offset(obj: Atspi.Accessible, offset: int) -> Optional[Atspi.Accessible]:
"""Attempts to correct for off-by-one brokenness in implementations"""
"""Returns the child at offset, correcting for broken hypertext offset mappings."""
if child := AXHypertext.get_child_at_offset(obj, offset):
return child
offset_in_parent = AXHypertext.get_character_offset_in_parent(child)
if offset_in_parent == offset:
return child
tokens = [
f"AXHypertext: Child at offset {offset} in",
obj,
"is",
child,
f"but reports offset {offset_in_parent}",
]
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
if child_before := AXHypertext.get_child_at_offset(obj, offset - 1):
offset_in_parent = AXHypertext.get_character_offset_in_parent(child_before)
@@ -225,6 +236,30 @@ class AXHypertext:
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
return child_after
for i in range(AXHypertext._get_link_count(obj)):
link = AXHypertext._get_link_at_index(obj, i)
if link is None or AXHypertext.get_link_start_offset(link) != offset:
continue
try:
child = Atspi.Hyperlink.get_object(link, 0)
except GLib.GError as error:
msg = f"AXHypertext: Exception in find_child_at_offset: {error}"
debug.print_message(debug.LEVEL_INFO, msg, True)
continue
if child is None:
continue
tokens = [
f"AXHypertext: Child at offset {offset} in",
obj,
"found via link enumeration:",
child,
]
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
return child
return None
@staticmethod
+48 -2
View File
@@ -85,12 +85,16 @@ class Backend:
with open(fileName, 'w', encoding='utf-8') as settingsFile:
settingsFile.write(dumps(prefsDoc))
def _updateTable(self, targetTable, newValues):
def _updateTable(self, targetTable, newValues, preserveMissingKeys=None):
if not isinstance(newValues, dict):
return
preserveMissingKeys = set(preserveMissingKeys or [])
for key in list(targetTable.keys()):
if key not in newValues:
if key in preserveMissingKeys:
continue
del targetTable[key]
continue
newValue = newValues[key]
@@ -173,7 +177,12 @@ class Backend:
profiles[profile] = {}
profileTable = profiles[profile]
self._updateTable(profileTable, general)
# Keep plugin persistence keys when callers provide partial updates.
self._updateTable(
profileTable,
general,
preserveMissingKeys={"activePlugins", "pluginSources"},
)
self._writeDocument(self.settingsFile, prefsDoc)
def _getSettings(self):
@@ -213,12 +222,33 @@ class Backend:
return settingsDict
def _hasLikelyCustomEchoVoice(self, echoVoice, defaultVoice):
"""Return True when echoVoice appears intentionally customized."""
if not echoVoice:
return False
echoEstablished = bool(echoVoice.get('established', False))
if not defaultVoice:
return echoEstablished or bool(echoVoice.get(acss.ACSS.FAMILY))
for key in [acss.ACSS.RATE, acss.ACSS.AVERAGE_PITCH, acss.ACSS.GAIN, acss.ACSS.FAMILY]:
echoValue = echoVoice.get(key)
defaultValue = defaultVoice.get(key)
if echoValue is not None and echoValue != defaultValue:
return True
return echoEstablished and bool(echoVoice.get(acss.ACSS.FAMILY))
def getGeneral(self, profile=None):
""" Get general settings from default settings and
override with profile values. """
self._getSettings()
generalSettings = self.general.copy()
generalSettings = self._migrateSettings(generalSettings)
# Plugin state is profile-scoped; ignore legacy/global values.
generalSettings.pop('activePlugins', None)
generalSettings.pop('pluginSources', None)
defaultProfile = generalSettings.get('startingProfile',
['Default', 'default'])
if profile is None:
@@ -229,8 +259,24 @@ class Backend:
if key == 'voices':
for voiceType, voiceDef in value.items():
value[voiceType] = acss.ACSS(voiceDef)
if key == 'echoVoice' and isinstance(value, dict):
value = acss.ACSS(value)
if key not in ['startingProfile', 'activeProfile']:
generalSettings[key] = value
# Backward compatibility: recover custom echo behavior when legacy
# profiles have echoVoice but are missing custom-echo toggle keys.
if 'useCustomEchoVoice' not in profileSettings:
voices = generalSettings.get('voices') or {}
defaultVoice = voices.get(settings.DEFAULT_VOICE)
echoVoice = generalSettings.get('echoVoice')
if self._hasLikelyCustomEchoVoice(echoVoice, defaultVoice):
generalSettings['useCustomEchoVoice'] = True
if 'useCustomEchoForKey' not in profileSettings:
generalSettings['useCustomEchoForKey'] = True
if 'useCustomEchoForCharacter' not in profileSettings:
generalSettings['useCustomEchoForCharacter'] = True
try:
generalSettings['activeProfile'] = profileSettings['profile']
except KeyError:
+670 -54
View File
@@ -124,6 +124,12 @@
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="progressBarBeepIntervalAdjustment">
<property name="upper">9999</property>
<property name="value">0</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="rateAdjustment">
<property name="upper">100</property>
<property name="value">50</property>
@@ -136,6 +142,30 @@
<property name="step_increment">0.10000000149</property>
<property name="page_increment">1</property>
</object>
<object class="GtkAdjustment" id="soundVolumeAdjustment">
<property name="upper">1</property>
<property name="value">0.5</property>
<property name="step_increment">0.05000000075</property>
<property name="page_increment">0.10000000149</property>
</object>
<object class="GtkAdjustment" id="echoPitchAdjustment">
<property name="upper">10</property>
<property name="value">5</property>
<property name="step_increment">0.10000000149</property>
<property name="page_increment">1</property>
</object>
<object class="GtkAdjustment" id="echoRateAdjustment">
<property name="upper">100</property>
<property name="value">50</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="echoVolumeAdjustment">
<property name="upper">10</property>
<property name="value">10</property>
<property name="step_increment">0.10000000149</property>
<property name="page_increment">1</property>
</object>
<object class="GtkDialog" id="cthulhuSetupWindow">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Cthulhu Preferences</property>
@@ -553,7 +583,7 @@
<property name="use_underline">True</property>
<property name="mnemonic_widget">timeFormatCombo</property>
<accessibility>
<relation type="label-for" target="availableProfilesComboBox1"/>
<relation type="label-for" target="timeFormatCombo"/>
</accessibility>
</object>
<packing>
@@ -570,7 +600,7 @@
<property name="use_underline">True</property>
<property name="mnemonic_widget">dateFormatCombo</property>
<accessibility>
<relation type="label-for" target="availableProfilesComboBox2"/>
<relation type="label-for" target="dateFormatCombo"/>
</accessibility>
</object>
<packing>
@@ -759,25 +789,6 @@
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="beepProgressBarUpdatesCheckButton">
<property name="label" translatable="yes" comments="Translators: This is an option in the Preferences dialog box related to the presentation of progress bar updates. If this checkbox is checked, Cthulhu will periodically emit beeps which increase in pitch as the value of the progress bar increases.">Bee_p updates</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="valign">start</property>
<property name="hexpand">True</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
</object>
</child>
</object>
@@ -1018,23 +1029,178 @@
<property name="height">2</property>
</packing>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="generalTabLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">General</property>
</object>
<packing>
<property name="position">0</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="soundsGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="row_spacing">10</property>
<property name="column_spacing">10</property>
<child>
<object class="GtkFrame" id="soundThemeFrame">
<object class="GtkFrame" id="soundOutputFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="soundThemeAlignment">
<object class="GtkAlignment" id="soundOutputAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkBox" id="soundThemeVBox">
<object class="GtkGrid" id="soundOutputGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<property name="row_spacing">10</property>
<property name="column_spacing">20</property>
<child>
<object class="GtkCheckButton" id="enableSoundCheckButton">
<property name="label" translatable="yes">Enable _sounds</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="soundVolumeLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Sound _volume:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">soundVolumeScale</property>
<accessibility>
<relation type="label-for" target="soundVolumeScale"/>
</accessibility>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkScale" id="soundVolumeScale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">soundVolumeAdjustment</property>
<property name="digits">2</property>
<property name="round_digits">2</property>
<property name="value_pos">right</property>
<signal name="value-changed" handler="soundVolumeValueChanged" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="soundSinkHBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="soundSinkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes" comments="Translators: This is the label for a combo box where users can choose which audio backend Cthulhu should use.">Audio _backend:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">soundSinkCombo</property>
<accessibility>
<relation type="label-for" target="soundSinkCombo"/>
</accessibility>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="soundSinkCombo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="changed" handler="soundSinkComboChanged" swapped="no"/>
<accessibility>
<relation type="labelled-by" target="soundSinkLabel"/>
</accessibility>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="soundOutputTitleLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Output</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="soundPresentationFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="soundPresentationAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkGrid" id="soundPresentationGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">10</property>
<property name="column_spacing">20</property>
<child>
<object class="GtkBox" id="soundThemeHBox">
<property name="visible">True</property>
@@ -1075,9 +1241,9 @@
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
</packing>
</child>
<child>
@@ -1120,9 +1286,77 @@
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="playSoundForRoleCheckButton">
<property name="label" translatable="yes">Play sound for _role</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="playSoundForStateCheckButton">
<property name="label" translatable="yes">Play sound for _state</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="playSoundForPositionInSetCheckButton">
<property name="label" translatable="yes">Play sound for p_osition in set</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="playSoundForValueCheckButton">
<property name="label" translatable="yes">Play sound for _value</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
<property name="width">2</property>
</packing>
</child>
</object>
@@ -1130,10 +1364,10 @@
</object>
</child>
<child type="label">
<object class="GtkLabel" id="soundThemeTitleLabel">
<object class="GtkLabel" id="soundPresentationTitleLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" comments="Translators: This is the title of a section in the preferences dialog containing sound theme options.">Sound Theme</property>
<property name="label" translatable="yes">Presentation</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
@@ -1142,18 +1376,111 @@
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">4</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="soundAlertsFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="soundAlertsAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkGrid" id="soundAlertsGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">10</property>
<property name="column_spacing">20</property>
<child>
<object class="GtkCheckButton" id="beepProgressBarUpdatesCheckButton">
<property name="label" translatable="yes" comments="Translators: This is an option in the Preferences dialog box related to the presentation of progress bar updates. If this checkbox is checked, Cthulhu will periodically emit beeps which increase in pitch as the value of the progress bar increases.">Bee_p progress bar updates</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="progressBarBeepIntervalLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Beep _frequency (secs):</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">progressBarBeepIntervalSpinButton</property>
<accessibility>
<relation type="label-for" target="progressBarBeepIntervalSpinButton"/>
</accessibility>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="progressBarBeepIntervalSpinButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">progressBarBeepIntervalAdjustment</property>
<property name="climb_rate">1</property>
<property name="numeric">True</property>
<property name="value">0</property>
<signal name="value-changed" handler="progressBarBeepIntervalValueChanged" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="soundAlertsTitleLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Alerts</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="generalTabLabel">
<object class="GtkLabel" id="soundsTabLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">General</property>
<property name="label" translatable="yes">Sounds</property>
</object>
<packing>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -1551,7 +1878,7 @@
</child>
</object>
<packing>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child type="tab">
@@ -1561,7 +1888,7 @@
<property name="label" translatable="yes">Voice</property>
</object>
<packing>
<property name="position">1</property>
<property name="position">2</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -2249,7 +2576,7 @@
</child>
</object>
<packing>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
<child type="tab">
@@ -2259,7 +2586,7 @@
<property name="label" translatable="yes">Speech</property>
</object>
<packing>
<property name="position">2</property>
<property name="position">3</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -2848,7 +3175,7 @@
</child>
</object>
<packing>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
<child type="tab">
@@ -2858,7 +3185,7 @@
<property name="label" translatable="yes">Braille</property>
</object>
<packing>
<property name="position">3</property>
<property name="position">4</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -3037,6 +3364,295 @@
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="echoVoiceFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="echoVoiceAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkGrid" id="echoVoiceGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">10</property>
<property name="column_spacing">8</property>
<child>
<object class="GtkCheckButton" id="useCustomEchoVoiceCheckButton">
<property name="label" translatable="yes">Use c_ustom echo voice settings</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="useCustomEchoVoiceToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="useCustomEchoSpeechServerCheckButton">
<property name="label" translatable="yes">Use custom _speech-dispatcher module for echo</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="useCustomEchoSpeechServerToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="echoSpeechServersLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Echo _module:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">echoSpeechServers</property>
<accessibility>
<relation type="label-for" target="echoSpeechServers"/>
</accessibility>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="echoSpeechServers">
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="changed" handler="echoSpeechServersChanged" swapped="no"/>
<accessibility>
<relation type="labelled-by" target="echoSpeechServersLabel"/>
</accessibility>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="echoSpeechFamiliesLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Echo _voice:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">echoSpeechFamilies</property>
<accessibility>
<relation type="label-for" target="echoSpeechFamilies"/>
</accessibility>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="echoSpeechFamilies">
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="changed" handler="echoSpeechFamiliesChanged" swapped="no"/>
<accessibility>
<relation type="labelled-by" target="echoSpeechFamiliesLabel"/>
</accessibility>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="echoRateLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Echo ra_te:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">echoRateScale</property>
<accessibility>
<relation type="label-for" target="echoRateScale"/>
</accessibility>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkScale" id="echoRateScale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">echoRateAdjustment</property>
<property name="round_digits">0</property>
<property name="digits">0</property>
<property name="value_pos">right</property>
<signal name="value-changed" handler="echoRateValueChanged" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="echoPitchLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Echo pi_tch:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">echoPitchScale</property>
<accessibility>
<relation type="label-for" target="echoPitchScale"/>
</accessibility>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
</packing>
</child>
<child>
<object class="GtkScale" id="echoPitchScale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">echoPitchAdjustment</property>
<property name="round_digits">1</property>
<property name="value_pos">right</property>
<signal name="value-changed" handler="echoPitchValueChanged" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="echoVolumeLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Echo vo_lume:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">echoVolumeScale</property>
<accessibility>
<relation type="label-for" target="echoVolumeScale"/>
</accessibility>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
</packing>
</child>
<child>
<object class="GtkScale" id="echoVolumeScale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">echoVolumeAdjustment</property>
<property name="round_digits">1</property>
<property name="value_pos">right</property>
<signal name="value-changed" handler="echoVolumeValueChanged" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">6</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="useCustomEchoForKeyCheckButton">
<property name="label" translatable="yes">Use custom voice for _key echo</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">7</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="useCustomEchoForCharacterCheckButton">
<property name="label" translatable="yes">Use custom voice for _character echo</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">8</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="useCustomEchoForWordCheckButton">
<property name="label" translatable="yes">Use custom voice for _word echo</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">9</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="useCustomEchoForSentenceCheckButton">
<property name="label" translatable="yes">Use custom voice for _sentence echo</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="checkButtonToggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">10</property>
<property name="width">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="echoVoiceLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Echo Voice</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="enableEchoByCharacterCheckButton">
<property name="label" translatable="yes" comments="Translators: When this option is enabled, inserted text of length 1 is spoken.">Enable echo by cha_racter</property>
@@ -3049,7 +3665,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
@@ -3064,7 +3680,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
@@ -3079,12 +3695,12 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
<property name="top_attach">5</property>
</packing>
</child>
</object>
<packing>
<property name="position">4</property>
<property name="position">5</property>
</packing>
</child>
<child type="tab">
@@ -3094,7 +3710,7 @@
<property name="label" translatable="yes">Echo</property>
</object>
<packing>
<property name="position">4</property>
<property name="position">5</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -3176,7 +3792,7 @@
</child>
</object>
<packing>
<property name="position">5</property>
<property name="position">6</property>
</packing>
</child>
<child type="tab">
@@ -3186,7 +3802,7 @@
<property name="label" translatable="yes">Key Bindings</property>
</object>
<packing>
<property name="position">5</property>
<property name="position">6</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -3286,7 +3902,7 @@
</child>
</object>
<packing>
<property name="position">6</property>
<property name="position">7</property>
</packing>
</child>
<child type="tab">
@@ -3296,7 +3912,7 @@
<property name="label" translatable="yes">Pronunciation</property>
</object>
<packing>
<property name="position">6</property>
<property name="position">7</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -3631,7 +4247,7 @@
</child>
</object>
<packing>
<property name="position">7</property>
<property name="position">8</property>
</packing>
</child>
<child type="tab">
@@ -3641,7 +4257,7 @@
<property name="label" translatable="yes">Text Attributes</property>
</object>
<packing>
<property name="position">7</property>
<property name="position">8</property>
<property name="tab_fill">False</property>
</packing>
</child>
+19 -2
View File
@@ -261,6 +261,7 @@ from . import event_manager
from . import keybindings
from . import learn_mode_presenter
from . import logger
from . import mako_notification_monitor
from . import messages
from . import notification_presenter
from . import focus_manager
@@ -719,6 +720,7 @@ def start() -> None:
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Starting Atspi main event loop', True)
# Start D-Bus remote controller service after ATSPI is ready
cthulhuApp.getMakoNotificationMonitor().start()
GObject.idle_add(_start_dbus_service)
Atspi.event_main()
@@ -769,8 +771,9 @@ def shutdown(script: Optional[Any] = None, inputEvent: Optional[Any] = None) ->
cthulhu_state.activeScript.presentationInterrupt()
cthulhuApp.getSignalManager().emitSignal('stop-application-completed')
sound_theme_manager.getManager().playStopSound(wait=True)
sound_theme_manager.getManager().playStopSound(wait=True, timeoutSeconds=1)
cthulhuApp.getPluginSystemManager().unloadAllPlugins(ForceAllPlugins=True)
cthulhuApp.getMakoNotificationMonitor().stop()
# Deactivate the event manager first so that it clears its queue and will not
# accept new events. Then let the script manager unregister script event listeners.
@@ -893,7 +896,14 @@ def main() -> int:
debug.printMessage(debug.LEVEL_INFO, "CTHULHU: Initialized.", True)
script = cthulhu_state.activeScript
sound_theme_manager.getManager().playStartSound(wait=True)
sound_theme_manager.getManager().playStartSound(wait=False)
soundFailureReason = sound.getSoundSystemFailureReason()
if soundFailureReason:
debug.printMessage(
debug.LEVEL_INFO,
f"CTHULHU: Startup sound failed. Continuing without sound. Reason: {soundFailureReason}",
True
)
cthulhuApp.getSignalManager().emitSignal('start-application-completed')
if script:
window = script.utilities.activeWindow()
@@ -944,12 +954,15 @@ class Cthulhu(GObject.Object):
self.settingsManager: SettingsManager = settings_manager.SettingsManager(self) # Directly instantiate
self.eventManager: EventManager = event_manager.EventManager(self) # Directly instantiate
self.scriptManager: ScriptManager = script_manager.ScriptManager(self) # Directly instantiate
script_manager._manager = self.scriptManager
self.logger: logger.Logger = logger.Logger() # Directly instantiate
self.signalManager: SignalManager = signal_manager.SignalManager(self)
self.dynamicApiManager: DynamicApiManager = dynamic_api_manager.DynamicApiManager(self)
self.translationManager: TranslationManager = translation_manager.TranslationManager(self)
self.debugManager: Any = debug
self.APIHelper: APIHelper = APIHelper(self)
self.makoNotificationMonitor: mako_notification_monitor.MakoNotificationMonitor = \
mako_notification_monitor.MakoNotificationMonitor(self)
self.createCompatAPI()
self.pluginSystemManager: PluginSystemManager = plugin_system_manager.PluginSystemManager(self)
# Scan for available plugins at startup
@@ -961,6 +974,9 @@ class Cthulhu(GObject.Object):
def getPluginSystemManager(self) -> PluginSystemManager:
return self.pluginSystemManager
def getMakoNotificationMonitor(self) -> mako_notification_monitor.MakoNotificationMonitor:
return self.makoNotificationMonitor
def getDynamicApiManager(self) -> DynamicApiManager:
return self.dynamicApiManager
@@ -1019,6 +1035,7 @@ class Cthulhu(GObject.Object):
self.getDynamicApiManager().registerAPI('Messages', messages)
self.getDynamicApiManager().registerAPI('Cmdnames', cmdnames)
self.getDynamicApiManager().registerAPI('NotificationPresenter', notification_presenter)
self.getDynamicApiManager().registerAPI('MakoNotificationMonitor', self.makoNotificationMonitor)
self.getDynamicApiManager().registerAPI('CthulhuState', cthulhu_state)
self.getDynamicApiManager().registerAPI('CthulhuPlatform', cthulhu_platform)
self.getDynamicApiManager().registerAPI('Settings', settings)
+2 -2
View File
@@ -23,5 +23,5 @@
# Forked from Orca screen reader.
# Cthulhu project: https://git.stormux.org/storm/cthulhu
version = "2026.01.19"
codeName = "testing"
version = "2026.03.02"
codeName = "master"
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More