diff options
Diffstat (limited to 'sound-theme/gvc-sound-theme-chooser.c')
-rw-r--r-- | sound-theme/gvc-sound-theme-chooser.c | 1147 |
1 files changed, 0 insertions, 1147 deletions
diff --git a/sound-theme/gvc-sound-theme-chooser.c b/sound-theme/gvc-sound-theme-chooser.c deleted file mode 100644 index 303c08b..0000000 --- a/sound-theme/gvc-sound-theme-chooser.c +++ /dev/null @@ -1,1147 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Bastien Nocera <[email protected]> - * Copyright (C) 2008 William Jon McCann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <utime.h> -#include <errno.h> - -#include <glib.h> -#include <glib/gi18n.h> -#include <glib-object.h> -#include <gio/gio.h> -#include <gtk/gtk.h> -#include <canberra-gtk.h> -#include <libxml/tree.h> - -#include "gvc-sound-theme-chooser.h" -#include "sound-theme-file-utils.h" - -#define GVC_SOUND_THEME_CHOOSER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_SOUND_THEME_CHOOSER, GvcSoundThemeChooserPrivate)) - -struct GvcSoundThemeChooserPrivate -{ - GtkWidget *combo_box; - GtkWidget *treeview; - GtkWidget *theme_box; - GtkWidget *selection_box; - GtkWidget *click_feedback_button; - GSettings *sound_settings; -}; - -static void gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass); -static void gvc_sound_theme_chooser_init (GvcSoundThemeChooser *sound_theme_chooser); -static void gvc_sound_theme_chooser_dispose (GObject *object); - -#if GTK_CHECK_VERSION (3, 0, 0) -G_DEFINE_TYPE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX) -#else -G_DEFINE_TYPE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_VBOX) -#endif - -#define KEY_SOUNDS_SCHEMA "org.mate.sound" -#define EVENT_SOUNDS_KEY "event-sounds" -#define INPUT_SOUNDS_KEY "input-feedback-sounds" -#define SOUND_THEME_KEY "theme-name" - -#define DEFAULT_ALERT_ID "__default" -#define CUSTOM_THEME_NAME "__custom" -#define NO_SOUNDS_THEME_NAME "__no_sounds" - -enum { - THEME_DISPLAY_COL, - THEME_IDENTIFIER_COL, - THEME_PARENT_ID_COL, - THEME_NUM_COLS -}; - -enum { - ALERT_DISPLAY_COL, - ALERT_IDENTIFIER_COL, - ALERT_SOUND_TYPE_COL, - ALERT_ACTIVE_COL, - ALERT_NUM_COLS -}; - -enum { - SOUND_TYPE_UNSET, - SOUND_TYPE_OFF, - SOUND_TYPE_DEFAULT_FROM_THEME, - SOUND_TYPE_BUILTIN, - SOUND_TYPE_CUSTOM -}; - -static void -on_combobox_changed (GtkComboBox *widget, - GvcSoundThemeChooser *chooser) -{ - GtkTreeIter iter; - GtkTreeModel *model; - char *theme_name; - - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) { - return; - } - - model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box)); - gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1); - - g_assert (theme_name != NULL); - - /* It is necessary to update the theme name before any other setting as - * the "changed" notification will reload the contents of the widget */ - g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name); - - /* special case for no sounds */ - if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) { - g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE); - return; - } else { - g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE); - } - - g_free (theme_name); - - /* FIXME: reset alert model */ -} - -static char * -load_index_theme_name (const char *index, - char **parent) -{ - GKeyFile *file; - char *indexname = NULL; - gboolean hidden; - - file = g_key_file_new (); - if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) { - g_key_file_free (file); - return NULL; - } - /* Don't add hidden themes to the list */ - hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL); - if (!hidden) { - indexname = g_key_file_get_locale_string (file, - "Sound Theme", - "Name", - NULL, - NULL); - - /* Save the parent theme, if there's one */ - if (parent != NULL) { - *parent = g_key_file_get_string (file, - "Sound Theme", - "Inherits", - NULL); - } - } - - g_key_file_free (file); - return indexname; -} - -static void -sound_theme_in_dir (GHashTable *hash, - const char *dir) -{ - GDir *d; - const char *name; - - d = g_dir_open (dir, 0, NULL); - if (d == NULL) { - return; - } - - while ((name = g_dir_read_name (d)) != NULL) { - char *dirname, *index, *indexname; - - /* Look for directories */ - dirname = g_build_filename (dir, name, NULL); - if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) { - g_free (dirname); - continue; - } - - /* Look for index files */ - index = g_build_filename (dirname, "index.theme", NULL); - g_free (dirname); - - /* Check the name of the theme in the index.theme file */ - indexname = load_index_theme_name (index, NULL); - g_free (index); - if (indexname == NULL) { - continue; - } - - g_hash_table_insert (hash, g_strdup (name), indexname); - } - - g_dir_close (d); -} - -static void -add_theme_to_store (const char *key, - const char *value, - GtkListStore *store) -{ - char *parent; - - parent = NULL; - - /* Get the parent, if we're checking the custom theme */ - if (strcmp (key, CUSTOM_THEME_NAME) == 0) { - char *name, *path; - - path = custom_theme_dir_path ("index.theme"); - name = load_index_theme_name (path, &parent); - g_free (name); - g_free (path); - } - gtk_list_store_insert_with_values (store, NULL, G_MAXINT, - THEME_DISPLAY_COL, value, - THEME_IDENTIFIER_COL, key, - THEME_PARENT_ID_COL, parent, - -1); - g_free (parent); -} - -static void -set_combox_for_theme_name (GvcSoundThemeChooser *chooser, - const char *name) -{ - GtkTreeIter iter; - GtkTreeModel *model; - gboolean found; - - /* If the name is empty, use "freedesktop" */ - if (name == NULL || *name == '\0') { - name = "freedesktop"; - } - - model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box)); - - if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) { - return; - } - - do { - char *value; - - gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1); - found = (value != NULL && strcmp (value, name) == 0); - g_free (value); - - } while (!found && gtk_tree_model_iter_next (model, &iter)); - - /* When we can't find the theme we need to set, try to set the default - * one "freedesktop" */ - if (found) { - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter); - } else if (strcmp (name, "freedesktop") != 0) { - g_debug ("not found, falling back to fdo"); - set_combox_for_theme_name (chooser, "freedesktop"); - } -} - -static void -set_input_feedback_enabled (GvcSoundThemeChooser *chooser, - gboolean enabled) -{ - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button), - enabled); -} - -static void -setup_theme_selector (GvcSoundThemeChooser *chooser) -{ - GHashTable *hash; - GtkListStore *store; - GtkCellRenderer *renderer; - const char * const *data_dirs; - const char *data_dir; - char *dir; - guint i; - - /* Add the theme names and their display name to a hash table, - * makes it easy to avoid duplicate themes */ - hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - data_dirs = g_get_system_data_dirs (); - for (i = 0; data_dirs[i] != NULL; i++) { - dir = g_build_filename (data_dirs[i], "sounds", NULL); - sound_theme_in_dir (hash, dir); - g_free (dir); - } - - data_dir = g_get_user_data_dir (); - dir = g_build_filename (data_dir, "sounds", NULL); - sound_theme_in_dir (hash, dir); - g_free (dir); - - /* If there isn't at least one theme, make everything - * insensitive, LAME! */ - if (g_hash_table_size (hash) == 0) { - gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE); - g_warning ("Bad setup, install the freedesktop sound theme"); - g_hash_table_destroy (hash); - return; - } - - /* Setup the tree model, 3 columns: - * - internal theme name/directory - * - display theme name - * - the internal id for the parent theme, used for the custom theme */ - store = gtk_list_store_new (THEME_NUM_COLS, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING); - - /* Add the themes to a combobox */ - gtk_list_store_insert_with_values (store, - NULL, - G_MAXINT, - THEME_DISPLAY_COL, _("No sounds"), - THEME_IDENTIFIER_COL, "__no_sounds", - THEME_PARENT_ID_COL, NULL, - -1); - g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store); - g_hash_table_destroy (hash); - - /* Set the display */ - gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box), - GTK_TREE_MODEL (store)); - - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box), - renderer, - TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box), - renderer, - "text", THEME_DISPLAY_COL, - NULL); - - g_signal_connect (G_OBJECT (chooser->priv->combo_box), - "changed", - G_CALLBACK (on_combobox_changed), - chooser); -} - -#define GVC_SOUND_SOUND (xmlChar *) "sound" -#define GVC_SOUND_NAME (xmlChar *) "name" -#define GVC_SOUND_FILENAME (xmlChar *) "filename" - -/* Adapted from yelp-toc-pager.c */ -static xmlChar * -xml_get_and_trim_names (xmlNodePtr node) -{ - xmlNodePtr cur, keep = NULL; - xmlChar *keep_lang = NULL; - xmlChar *value; - int j, keep_pri = INT_MAX; - - const gchar * const * langs = g_get_language_names (); - - value = NULL; - - for (cur = node->children; cur; cur = cur->next) { - if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) { - xmlChar *cur_lang = NULL; - int cur_pri = INT_MAX; - - cur_lang = xmlNodeGetLang (cur); - - if (cur_lang) { - for (j = 0; langs[j]; j++) { - if (g_str_equal (cur_lang, langs[j])) { - cur_pri = j; - break; - } - } - } else { - cur_pri = INT_MAX - 1; - } - - if (cur_pri <= keep_pri) { - if (keep_lang) - xmlFree (keep_lang); - if (value) - xmlFree (value); - - value = xmlNodeGetContent (cur); - - keep_lang = cur_lang; - keep_pri = cur_pri; - keep = cur; - } else { - if (cur_lang) - xmlFree (cur_lang); - } - } - } - - /* Delete all GVC_SOUND_NAME nodes */ - cur = node->children; - while (cur) { - xmlNodePtr this = cur; - cur = cur->next; - if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) { - xmlUnlinkNode (this); - xmlFreeNode (this); - } - } - - return value; -} - -static void -populate_model_from_node (GvcSoundThemeChooser *chooser, - GtkTreeModel *model, - xmlNodePtr node) -{ - xmlNodePtr child; - xmlChar *filename; - xmlChar *name; - - filename = NULL; - name = xml_get_and_trim_names (node); - for (child = node->children; child; child = child->next) { - if (xmlNodeIsText (child)) { - continue; - } - - if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) { - filename = xmlNodeGetContent (child); - } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) { - /* EH? should have been trimmed */ - } - } - - if (filename != NULL && name != NULL) { - gtk_list_store_insert_with_values (GTK_LIST_STORE (model), - NULL, - G_MAXINT, - ALERT_IDENTIFIER_COL, filename, - ALERT_DISPLAY_COL, name, - ALERT_SOUND_TYPE_COL, _("Built-in"), - ALERT_ACTIVE_COL, FALSE, - -1); - } - - xmlFree (filename); - xmlFree (name); -} - -static void -populate_model_from_file (GvcSoundThemeChooser *chooser, - GtkTreeModel *model, - const char *filename) -{ - xmlDocPtr doc; - xmlNodePtr root; - xmlNodePtr child; - gboolean exists; - - exists = g_file_test (filename, G_FILE_TEST_EXISTS); - if (! exists) { - return; - } - - doc = xmlParseFile (filename); - if (doc == NULL) { - return; - } - - root = xmlDocGetRootElement (doc); - - for (child = root->children; child; child = child->next) { - if (xmlNodeIsText (child)) { - continue; - } - if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) { - continue; - } - - populate_model_from_node (chooser, model, child); - } - - xmlFreeDoc (doc); -} - -static void -populate_model_from_dir (GvcSoundThemeChooser *chooser, - GtkTreeModel *model, - const char *dirname) -{ - GDir *d; - const char *name; - - d = g_dir_open (dirname, 0, NULL); - if (d == NULL) { - return; - } - - while ((name = g_dir_read_name (d)) != NULL) { - char *path; - - if (! g_str_has_suffix (name, ".xml")) { - continue; - } - - path = g_build_filename (dirname, name, NULL); - populate_model_from_file (chooser, model, path); - g_free (path); - } -} - -static gboolean -save_alert_sounds (GvcSoundThemeChooser *chooser, - const char *id) -{ - const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL }; - char *path; - - if (strcmp (id, DEFAULT_ALERT_ID) == 0) { - delete_old_files (sounds); - delete_disabled_files (sounds); - } else { - delete_old_files (sounds); - delete_disabled_files (sounds); - add_custom_file (sounds, id); - } - - /* And poke the directory so the theme gets updated */ - path = custom_theme_dir_path (NULL); - if (utime (path, NULL) != 0) { - g_warning ("Failed to update mtime for directory '%s': %s", - path, g_strerror (errno)); - } - g_free (path); - - return FALSE; -} - - -static void -update_alert_model (GvcSoundThemeChooser *chooser, - const char *id) -{ - GtkTreeModel *model; - GtkTreeIter iter; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview)); - gtk_tree_model_get_iter_first (model, &iter); - do { - gboolean toggled; - char *this_id; - - gtk_tree_model_get (model, &iter, - ALERT_IDENTIFIER_COL, &this_id, - -1); - - if (strcmp (this_id, id) == 0) { - toggled = TRUE; - } else { - toggled = FALSE; - } - g_free (this_id); - - gtk_list_store_set (GTK_LIST_STORE (model), - &iter, - ALERT_ACTIVE_COL, toggled, - -1); - } while (gtk_tree_model_iter_next (model, &iter)); -} - -static void -update_alert (GvcSoundThemeChooser *chooser, - const char *alert_id) -{ - GtkTreeModel *theme_model; - GtkTreeIter iter; - char *theme; - char *parent; - gboolean is_custom; - gboolean is_default; - gboolean add_custom; - gboolean remove_custom; - - theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box)); - /* Get the current theme's name, and set the parent */ - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) { - return; - } - - gtk_tree_model_get (theme_model, &iter, - THEME_IDENTIFIER_COL, &theme, - THEME_IDENTIFIER_COL, &parent, - -1); - is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0; - is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0; - - /* So a few possibilities: - * 1. Named theme, default alert selected: noop - * 2. Named theme, alternate alert selected: create new custom with sound - * 3. Custom theme, default alert selected: remove sound and possibly custom - * 4. Custom theme, alternate alert selected: update custom sound - */ - add_custom = FALSE; - remove_custom = FALSE; - if (! is_custom && is_default) { - /* remove custom just in case */ - remove_custom = TRUE; - } else if (! is_custom && ! is_default) { - create_custom_theme (parent); - save_alert_sounds (chooser, alert_id); - add_custom = TRUE; - } else if (is_custom && is_default) { - save_alert_sounds (chooser, alert_id); - /* after removing files check if it is empty */ - if (custom_theme_dir_is_empty ()) { - remove_custom = TRUE; - } - } else if (is_custom && ! is_default) { - save_alert_sounds (chooser, alert_id); - } - - if (add_custom) { - gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model), - NULL, - G_MAXINT, - THEME_DISPLAY_COL, _("Custom"), - THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME, - THEME_PARENT_ID_COL, theme, - -1); - set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME); - } else if (remove_custom) { - gtk_tree_model_get_iter_first (theme_model, &iter); - do { - char *this_parent; - - gtk_tree_model_get (theme_model, &iter, - THEME_PARENT_ID_COL, &this_parent, - -1); - if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) { - g_free (this_parent); - gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter); - break; - } - g_free (this_parent); - } while (gtk_tree_model_iter_next (theme_model, &iter)); - - delete_custom_theme_dir (); - - set_combox_for_theme_name (chooser, parent); - } - - update_alert_model (chooser, alert_id); - - g_free (theme); - g_free (parent); -} - -static void -on_alert_toggled (GtkCellRendererToggle *renderer, - char *path_str, - GvcSoundThemeChooser *chooser) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; - gboolean toggled; - char *id; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview)); - - path = gtk_tree_path_new_from_string (path_str); - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_path_free (path); - - id = NULL; - gtk_tree_model_get (model, &iter, - ALERT_IDENTIFIER_COL, &id, - ALERT_ACTIVE_COL, &toggled, - -1); - - toggled ^= 1; - if (toggled) { - update_alert (chooser, id); - } - - g_free (id); -} - -static void -play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreeIter theme_iter; - gchar *id = NULL; - gchar *parent_theme = NULL; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview)); - if (gtk_tree_model_get_iter (model, &iter, path) == FALSE) - return; - - gtk_tree_model_get (model, &iter, - ALERT_IDENTIFIER_COL, &id, - -1); - if (id == NULL) - return; - - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) { - GtkTreeModel *theme_model; - gchar *theme_id = NULL; - gchar *parent_id = NULL; - - theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box)); - - gtk_tree_model_get (theme_model, &theme_iter, - THEME_IDENTIFIER_COL, &theme_id, - THEME_PARENT_ID_COL, &parent_id, -1); - if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0) - parent_theme = g_strdup (parent_id); - - g_free (theme_id); - g_free (parent_id); - } - - /* special case: for the default item on custom themes - * play the alert for the parent theme */ - if (strcmp (id, DEFAULT_ALERT_ID) == 0) { - if (parent_theme != NULL) { - ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0, - CA_PROP_APPLICATION_NAME, _("Sound Preferences"), - CA_PROP_EVENT_ID, "bell-window-system", - CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme, - CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"), - CA_PROP_CANBERRA_CACHE_CONTROL, "never", - CA_PROP_APPLICATION_ID, "org.mate.VolumeControl", -#ifdef CA_PROP_CANBERRA_ENABLE - CA_PROP_CANBERRA_ENABLE, "1", -#endif - NULL); - } else { - ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0, - CA_PROP_APPLICATION_NAME, _("Sound Preferences"), - CA_PROP_EVENT_ID, "bell-window-system", - CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"), - CA_PROP_CANBERRA_CACHE_CONTROL, "never", - CA_PROP_APPLICATION_ID, "org.mate.VolumeControl", -#ifdef CA_PROP_CANBERRA_ENABLE - CA_PROP_CANBERRA_ENABLE, "1", -#endif - NULL); - } - } else { - ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0, - CA_PROP_APPLICATION_NAME, _("Sound Preferences"), - CA_PROP_MEDIA_FILENAME, id, - CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"), - CA_PROP_CANBERRA_CACHE_CONTROL, "never", - CA_PROP_APPLICATION_ID, "org.mate.VolumeControl", -#ifdef CA_PROP_CANBERRA_ENABLE - CA_PROP_CANBERRA_ENABLE, "1", -#endif - NULL); - - } - g_free (parent_theme); - g_free (id); -} - -static void -on_treeview_row_activated (GtkTreeView *treeview, - GtkTreePath *path, - GtkTreeViewColumn *column, - GvcSoundThemeChooser *chooser) -{ - play_preview_for_path (chooser, path); -} - -static void -on_treeview_selection_changed (GtkTreeSelection *selection, - GvcSoundThemeChooser *chooser) -{ - GList *paths; - GtkTreeModel *model; - GtkTreePath *path; - - if (chooser->priv->treeview == NULL) - return; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview)); - - paths = gtk_tree_selection_get_selected_rows (selection, &model); - if (paths == NULL) - return; - - path = paths->data; - play_preview_for_path (chooser, path); - - g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL); - g_list_free (paths); -} - -static GtkWidget * -create_alert_treeview (GvcSoundThemeChooser *chooser) -{ - GtkListStore *store; - GtkWidget *treeview; - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - GtkTreeSelection *selection; - - treeview = gtk_tree_view_new (); - - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); - g_signal_connect (G_OBJECT (treeview), - "row-activated", - G_CALLBACK (on_treeview_row_activated), - chooser); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); - - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - g_signal_connect (G_OBJECT (selection), - "changed", - G_CALLBACK (on_treeview_selection_changed), - chooser); - - /* Setup the tree model, 3 columns: - * - display name - * - sound id - * - sound type - */ - store = gtk_list_store_new (ALERT_NUM_COLS, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_BOOLEAN); - - gtk_list_store_insert_with_values (store, - NULL, - G_MAXINT, - ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID, - ALERT_DISPLAY_COL, _("Default"), - ALERT_SOUND_TYPE_COL, _("From theme"), - ALERT_ACTIVE_COL, TRUE, - -1); - - populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR); - - gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), - GTK_TREE_MODEL (store)); - - renderer = gtk_cell_renderer_toggle_new (); - gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE); - - column = gtk_tree_view_column_new_with_attributes (NULL, - renderer, - "active", ALERT_ACTIVE_COL, - NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); - g_signal_connect (renderer, - "toggled", - G_CALLBACK (on_alert_toggled), - chooser); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Name"), - renderer, - "text", ALERT_DISPLAY_COL, - NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Type"), - renderer, - "text", ALERT_SOUND_TYPE_COL, - NULL); - - gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); - - return treeview; -} - -static int -get_file_type (const char *sound_name, - char **linked_name) -{ - char *name, *filename; - - *linked_name = NULL; - - name = g_strdup_printf ("%s.disabled", sound_name); - filename = custom_theme_dir_path (name); - g_free (name); - - if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) { - g_free (filename); - return SOUND_TYPE_OFF; - } - g_free (filename); - - /* We only check for .ogg files because those are the - * only ones we create */ - name = g_strdup_printf ("%s.ogg", sound_name); - filename = custom_theme_dir_path (name); - g_free (name); - - if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) { - *linked_name = g_file_read_link (filename, NULL); - g_free (filename); - return SOUND_TYPE_CUSTOM; - } - g_free (filename); - - return SOUND_TYPE_BUILTIN; -} - -static void -update_alerts_from_theme_name (GvcSoundThemeChooser *chooser, - const gchar *name) -{ - if (strcmp (name, CUSTOM_THEME_NAME) != 0) { - /* reset alert to default */ - update_alert (chooser, DEFAULT_ALERT_ID); - } else { - int sound_type; - char *linkname; - - linkname = NULL; - sound_type = get_file_type ("bell-terminal", &linkname); - g_debug ("Found link: %s", linkname); - if (sound_type == SOUND_TYPE_CUSTOM) { - update_alert (chooser, linkname); - } - } -} - -static void -update_theme (GvcSoundThemeChooser *chooser) -{ - char *theme_name; - gboolean events_enabled; - gboolean feedback_enabled; - - feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY); - set_input_feedback_enabled (chooser, feedback_enabled); - - events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY); - if (events_enabled) { - theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY); - } else { - theme_name = g_strdup (NO_SOUNDS_THEME_NAME); - } - - gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled); - gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled); - - set_combox_for_theme_name (chooser, theme_name); - - update_alerts_from_theme_name (chooser, theme_name); - - g_free (theme_name); -} - -static void -gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = gvc_sound_theme_chooser_dispose; - - g_type_class_add_private (klass, sizeof (GvcSoundThemeChooserPrivate)); -} - -static void -on_click_feedback_toggled (GtkToggleButton *button, - GvcSoundThemeChooser *chooser) -{ - gboolean enabled; - - enabled = gtk_toggle_button_get_active (button); - - g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled); -} - -static void -on_key_changed (GSettings *settings, - gchar *key, - GvcSoundThemeChooser *chooser) -{ - if (!strcmp (key, EVENT_SOUNDS_KEY) || - !strcmp (key, SOUND_THEME_KEY) || - !strcmp (key, INPUT_SOUNDS_KEY)) - update_theme (chooser); -} - -#if !GTK_CHECK_VERSION (3, 0, 0) -static void -constrain_list_size (GtkWidget *widget, - GtkRequisition *requisition, - GtkWidget *to_size) -{ - GtkRequisition req; - int max_height; - - /* Constrain height to be the tree height up to a max */ - max_height = (gdk_screen_get_height (gtk_widget_get_screen (widget))) / 4; - - gtk_widget_size_request (to_size, &req); - - requisition->height = MIN (req.height, max_height); -} -#endif - -static void -setup_list_size_constraint (GtkWidget *widget, - GtkWidget *to_size) -{ -#if GTK_CHECK_VERSION (3, 0, 0) - GtkRequisition req; - int max_height; - - /* Constrain height to be the tree height up to a max */ - max_height = (gdk_screen_get_height (gtk_widget_get_screen (widget))) / 4; - - // XXX this doesn't work - gtk_widget_get_preferred_size (to_size, NULL, &req); - - gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget), - MIN (req.height, max_height)); -#else - g_signal_connect (G_OBJECT (widget), - "size-request", - G_CALLBACK (constrain_list_size), - to_size); -#endif -} - -static void -gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser) -{ - GtkWidget *box; - GtkWidget *label; - GtkWidget *scrolled_window; - GtkWidget *alignment; - gchar *str; - - chooser->priv = GVC_SOUND_THEME_CHOOSER_GET_PRIVATE (chooser); - -#if GTK_CHECK_VERSION (3, 0, 0) - chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); -#else - chooser->priv->theme_box = gtk_hbox_new (FALSE, 0); -#endif - - gtk_box_pack_start (GTK_BOX (chooser), - chooser->priv->theme_box, FALSE, FALSE, 0); - - label = gtk_label_new_with_mnemonic (_("Sound _theme:")); - gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0); - chooser->priv->combo_box = gtk_combo_box_new (); - gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box); - - chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA); - - str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:")); - chooser->priv->selection_box = box = gtk_frame_new (str); - g_free (str); - - label = gtk_frame_get_label_widget (GTK_FRAME (box)); - gtk_label_set_use_underline (GTK_LABEL (label), TRUE); - gtk_label_set_use_markup (GTK_LABEL (label), TRUE); - gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE); - - alignment = gtk_alignment_new (0, 0, 1, 1); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0); - gtk_container_add (GTK_CONTAINER (alignment), box); - gtk_box_pack_start (GTK_BOX (chooser), alignment, TRUE, TRUE, 6); - - alignment = gtk_alignment_new (0, 0, 1, 1); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0); - gtk_container_add (GTK_CONTAINER (box), alignment); - - chooser->priv->treeview = create_alert_treeview (chooser); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview); - - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_SHADOW_IN); - - gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview); - gtk_container_add (GTK_CONTAINER (alignment), scrolled_window); - - chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button), - g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY)); - - gtk_box_pack_start (GTK_BOX (chooser), - chooser->priv->click_feedback_button, - FALSE, FALSE, 0); - - g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button), - "toggled", - G_CALLBACK (on_click_feedback_toggled), - chooser); - g_signal_connect (G_OBJECT (chooser->priv->sound_settings), - "changed", - G_CALLBACK (on_key_changed), - chooser); - - setup_theme_selector (chooser); - update_theme (chooser); - - setup_list_size_constraint (scrolled_window, chooser->priv->treeview); -} - -static void -gvc_sound_theme_chooser_dispose (GObject *object) -{ - GvcSoundThemeChooser *chooser; - - chooser = GVC_SOUND_THEME_CHOOSER (object); - - g_clear_object (&chooser->priv->sound_settings); - - G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object); -} - -GtkWidget * -gvc_sound_theme_chooser_new (void) -{ - return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER, - "spacing", 6, -#if GTK_CHECK_VERSION (3, 0, 0) - "orientation", GTK_ORIENTATION_VERTICAL, -#endif - NULL); -} |