163 lines
7.4 KiB
C
163 lines
7.4 KiB
C
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
#include "native_internal.h"
|
|
|
|
static GtkListStore *reading_store;
|
|
static const struct { const char *id; const char *label; } reading_rows[] = {
|
|
{"only_speak_displayed_text", "Only speak displayed text"},
|
|
{"automatically_read_title_changes", "Automatically read title changes"},
|
|
{"automatically_read_clipboard_changes", "Automatically read clipboard changes"},
|
|
{"enable_pause_breaks", "Break speech into chunks between pauses"},
|
|
{"speak_numbers_as_digits", "Speak numbers as digits"},
|
|
{"speak_multicase_strings_as_words", "Speak multicase strings as words"},
|
|
{"enable_indentation", "Enable indentation presentation"},
|
|
{"speak_blank_lines", "Speak blank lines"},
|
|
{"enable_mnemonic_speaking", "Speak object mnemonics"},
|
|
{"enable_position_speaking", "Speak child position"},
|
|
{"enable_tutorial_messages", "Speak tutorial messages"},
|
|
{"speak_description", "Speak object descriptions"},
|
|
{"messages_are_detailed", "System messages are detailed"},
|
|
{"use_color_names", "Speak colors as names"},
|
|
{"speak_misspelled_indicator", "Speak misspelled-word indicator"},
|
|
{"speak_context_blockquote", "Announce block quotes during navigation"},
|
|
{"speak_context_list", "Announce lists during navigation"},
|
|
{"speak_context_table", "Announce tables during navigation"},
|
|
{"speak_context_panel", "Announce panels during navigation"},
|
|
{"speak_context_landmark", "Announce landmarks during navigation"},
|
|
{"speak_context_non_landmark_form", "Announce forms during navigation"},
|
|
{"read_full_row_in_gui_table", "Speak full row in GUI tables"},
|
|
{"read_full_row_in_document_table", "Speak full row in document tables"},
|
|
{"read_full_row_in_spreadsheet", "Speak full row in spreadsheets"},
|
|
{"present_tooltips", "Present tooltips"},
|
|
{"enable_mouse_review", "Speak object under mouse"},
|
|
{"say_all_context_blockquote", "Announce block quotes in Say All"},
|
|
{"say_all_context_list", "Announce lists in Say All"},
|
|
{"say_all_context_table", "Announce tables in Say All"},
|
|
{"say_all_context_panel", "Announce panels in Say All"},
|
|
{"say_all_context_non_landmark_form", "Announce forms in Say All"},
|
|
{"say_all_context_landmark", "Announce landmarks in Say All"},
|
|
};
|
|
|
|
enum {
|
|
READING_ID,
|
|
READING_LABEL,
|
|
READING_ENABLED,
|
|
READING_N_COLUMNS
|
|
};
|
|
static void name_reading_toggle_cells(void);
|
|
|
|
static void reading_toggled(GtkCellRendererToggle *renderer, gchar *path_string, gpointer data) {
|
|
(void)renderer; (void)data;
|
|
GtkTreeIter iter;
|
|
if (!gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(reading_store), &iter, path_string)) {
|
|
return;
|
|
}
|
|
gboolean active;
|
|
gtk_tree_model_get(GTK_TREE_MODEL(reading_store), &iter, READING_ENABLED, &active, -1);
|
|
gtk_list_store_set(reading_store, &iter, READING_ENABLED, !active, -1);
|
|
name_reading_toggle_cells();
|
|
}
|
|
|
|
static gboolean reading_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data) {
|
|
(void)data;
|
|
if (event->keyval != GDK_KEY_space && event->keyval != GDK_KEY_KP_Space) return FALSE;
|
|
GtkTreePath *path = NULL;
|
|
gtk_tree_view_get_cursor(GTK_TREE_VIEW(widget), &path, NULL);
|
|
if (!path) return FALSE;
|
|
GtkTreeIter iter;
|
|
gboolean found = gtk_tree_model_get_iter(GTK_TREE_MODEL(reading_store), &iter, path);
|
|
gtk_tree_path_free(path);
|
|
if (!found) return FALSE;
|
|
gboolean active;
|
|
gtk_tree_model_get(GTK_TREE_MODEL(reading_store), &iter, READING_ENABLED, &active, -1);
|
|
gtk_list_store_set(reading_store, &iter, READING_ENABLED, !active, -1);
|
|
name_reading_toggle_cells();
|
|
return TRUE;
|
|
}
|
|
|
|
static void name_reading_toggle_cells(void) {
|
|
AtkObject *accessible = gtk_widget_get_accessible(prefs_widget("readingSettingsTreeview"));
|
|
if (!ATK_IS_TABLE(accessible)) return;
|
|
for (unsigned int i = 0; i < G_N_ELEMENTS(reading_rows); i++) {
|
|
AtkObject *cell = atk_table_ref_at(ATK_TABLE(accessible), i, 0);
|
|
if (!cell) continue;
|
|
GtkTreeIter iter;
|
|
gboolean active = FALSE;
|
|
if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(reading_store), &iter, NULL, i))
|
|
gtk_tree_model_get(GTK_TREE_MODEL(reading_store), &iter, READING_ENABLED, &active, -1);
|
|
const char *name = active ? "checked" : "unchecked";
|
|
if (g_strcmp0(atk_object_get_name(cell), name) != 0) atk_object_set_name(cell, name);
|
|
g_object_unref(cell);
|
|
}
|
|
}
|
|
|
|
void prefs_init_reading_settings(void) {
|
|
reading_store = gtk_list_store_new(READING_N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
|
|
for (unsigned int i = 0; i < G_N_ELEMENTS(reading_rows); i++) {
|
|
GtkTreeIter iter;
|
|
gtk_list_store_append(reading_store, &iter);
|
|
gtk_list_store_set(reading_store, &iter,
|
|
READING_ID, reading_rows[i].id,
|
|
READING_LABEL, reading_rows[i].label,
|
|
READING_ENABLED, FALSE,
|
|
-1);
|
|
}
|
|
|
|
GtkTreeView *view = GTK_TREE_VIEW(prefs_widget("readingSettingsTreeview"));
|
|
gtk_tree_view_set_model(view, GTK_TREE_MODEL(reading_store));
|
|
gtk_tree_view_set_headers_visible(view, TRUE);
|
|
GtkCellRenderer *text_renderer = gtk_cell_renderer_text_new();
|
|
GtkTreeViewColumn *setting_column = gtk_tree_view_column_new_with_attributes(
|
|
"Setting", text_renderer, "text", READING_LABEL, NULL);
|
|
GtkCellRenderer *toggle_renderer = gtk_cell_renderer_toggle_new();
|
|
g_object_set(toggle_renderer, "activatable", TRUE, NULL);
|
|
g_signal_connect(toggle_renderer, "toggled", G_CALLBACK(reading_toggled), NULL);
|
|
GtkTreeViewColumn *enabled_column = gtk_tree_view_column_new_with_attributes(
|
|
"Enabled", toggle_renderer, "active", READING_ENABLED, NULL);
|
|
gtk_tree_view_append_column(view, enabled_column);
|
|
gtk_tree_view_append_column(view, setting_column);
|
|
g_signal_connect(view, "key-press-event", G_CALLBACK(reading_key_press), NULL);
|
|
name_reading_toggle_cells();
|
|
}
|
|
|
|
void prefs_reading_set(const char *id, int value) {
|
|
GtkTreeIter iter;
|
|
gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(reading_store), &iter);
|
|
while (valid) {
|
|
gchar *row_id;
|
|
gboolean active;
|
|
gtk_tree_model_get(GTK_TREE_MODEL(reading_store), &iter,
|
|
READING_ID, &row_id, READING_ENABLED, &active, -1);
|
|
if (g_strcmp0(row_id, id) == 0) {
|
|
if (active != (value != 0)) {
|
|
gtk_list_store_set(reading_store, &iter, READING_ENABLED, value != 0, -1);
|
|
name_reading_toggle_cells();
|
|
}
|
|
g_free(row_id);
|
|
return;
|
|
}
|
|
g_free(row_id);
|
|
valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(reading_store), &iter);
|
|
}
|
|
}
|
|
|
|
int prefs_reading_get(const char *id) {
|
|
GtkTreeIter iter;
|
|
gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(reading_store), &iter);
|
|
while (valid) {
|
|
gchar *row_id;
|
|
gtk_tree_model_get(GTK_TREE_MODEL(reading_store), &iter, READING_ID, &row_id, -1);
|
|
if (g_strcmp0(row_id, id) == 0) {
|
|
gboolean active;
|
|
gtk_tree_model_get(GTK_TREE_MODEL(reading_store), &iter, READING_ENABLED, &active, -1);
|
|
g_free(row_id);
|
|
return active ? 1 : 0;
|
|
}
|
|
g_free(row_id);
|
|
valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(reading_store), &iter);
|
|
}
|
|
return 0;
|
|
}
|
|
|