/* * Copyright (C) 2010 Bastien Nocera * * Written by: Bastien Nocera * * 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, 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., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "gnome-region-panel-lang.h" #include "gnome-region-panel-formats.h" #include "gnome-region-panel-system.h" #include "cc-common-language.h" #include "cc-language-chooser.h" static GDBusProxy *proxy = NULL; static GDBusProxy *sm_proxy = NULL; static char *old_locale = NULL; static void logout_requested (GtkButton *button, gpointer user_data) { GError *error = NULL; GVariant *res; g_return_if_fail (sm_proxy != NULL); res = g_dbus_proxy_call_sync (sm_proxy, "Logout", g_variant_new ("(u)", 0), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (res == NULL) { g_warning ("Logout failed: %s", error->message); g_error_free (error); } else g_variant_unref (res); } static void set_old_locale (void) { GError *error = NULL; GVariant *variant; variant = g_dbus_proxy_call_sync (sm_proxy, "GetLocale", g_variant_new ("(i)", LC_MESSAGES), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (variant == NULL) { g_warning ("Could not get current locale: %s", error->message); g_error_free (error); return; } g_variant_get (variant, "(s)", &old_locale); g_variant_unref (variant); } static gboolean is_old_locale (const char *new_locale) { gboolean ret = FALSE; g_debug ("Comparing locale '%s' (old) and '%s' (new)", old_locale, new_locale); if (g_strcmp0 (old_locale, new_locale) == 0) ret = TRUE; return ret; } static void update_logout_button (GtkBuilder *builder, const char *locale) { GtkWidget *button, *notebook; char *old_lang; /* Offer log out in the new language, unless it is * the original session language */ button = (GtkWidget *)gtk_builder_get_object (builder, "logout_button"); notebook = (GtkWidget *)gtk_builder_get_object (builder, "logout_notebook"); if (is_old_locale (locale) == FALSE) { old_lang = g_strdup (setlocale (LC_MESSAGES, NULL)); setlocale (LC_MESSAGES, locale); gtk_button_set_label (GTK_BUTTON (button), _("Log out for changes to take effect")); setlocale (LC_MESSAGES, old_lang); g_free (old_lang); gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 1); } else { gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0); } } static void selection_changed (GtkTreeSelection *selection, GtkBuilder *builder) { GtkTreeModel *model; GtkTreeIter iter; char *locale; GDBusProxy *user; GVariant *variant; GError *error = NULL; char *object_path; if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) { g_warning ("No selected languages, this shouldn't happen"); return; } user = NULL; variant = NULL; gtk_tree_model_get (model, &iter, LOCALE_COL, &locale, -1); if (proxy == NULL) { g_warning ("Would change the language to '%s', but no D-Bus connection available", locale); goto bail; } variant = g_dbus_proxy_call_sync (proxy, "FindUserByName", g_variant_new ("(s)", g_get_user_name ()), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (variant == NULL) { g_warning ("Could not contact accounts service to look up '%s': %s", g_get_user_name (), error->message); g_error_free (error); goto bail; } g_variant_get (variant, "(o)", &object_path); user = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.freedesktop.Accounts", object_path, "org.freedesktop.Accounts.User", NULL, &error); g_free (object_path); if (user == NULL) { g_warning ("Could not create proxy for user '%s': %s", g_variant_get_string (variant, NULL), error->message); g_error_free (error); goto bail; } g_variant_unref (variant); variant = g_dbus_proxy_call_sync (user, "SetLanguage", g_variant_new ("(s)", locale), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (variant == NULL) { g_warning ("Failed to set the language '%s': %s", locale, error->message); g_error_free (error); goto bail; } /* Update the other tabs */ formats_update_language (builder, locale); system_update_language (builder, locale); update_logout_button (builder, locale); bail: if (variant != NULL) g_variant_unref (variant); if (user != NULL) g_object_unref (user); g_free (locale); } static void language_response (GtkDialog *dialog, gint response_id, GtkWidget *treeview) { gchar *lang; GtkTreeModel *model; GtkTreeSelection *selection; GtkTreeIter iter; gtk_widget_hide (GTK_WIDGET (dialog)); if (response_id != GTK_RESPONSE_OK) { return; } lang = cc_language_chooser_get_language (GTK_WIDGET (dialog)); if (lang == NULL) { return; } model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); if (cc_common_language_get_iter_for_language (model, lang, &iter)) { gtk_tree_selection_select_iter (selection, &iter); } gtk_widget_grab_focus (treeview); g_free (lang); } static void add_language (GtkWidget *button, GtkWidget *treeview) { GtkWidget *toplevel; GtkWidget *chooser; toplevel = gtk_widget_get_toplevel (button); chooser = g_object_get_data (G_OBJECT (button), "chooser"); if (chooser == NULL) { chooser = cc_language_chooser_new (toplevel, FALSE); g_signal_connect (chooser, "response", G_CALLBACK (language_response), treeview); g_signal_connect (chooser, "delete-event", G_CALLBACK (gtk_widget_hide_on_delete), NULL); g_object_set_data_full (G_OBJECT (button), "chooser", chooser, (GDestroyNotify)gtk_widget_destroy); } else { cc_language_chooser_clear_filter (chooser); } gdk_window_set_cursor (gtk_widget_get_window (toplevel), NULL); gtk_window_present (GTK_WINDOW (chooser)); } void setup_language (GtkBuilder *builder) { GtkWidget *treeview; GHashTable *user_langs, *popular_langs; GError *error = NULL; GtkWidget *widget; GtkStyleContext *context; GtkTreeSelection *selection; char *locale; /* Setup junction between toolbar and treeview */ widget = (GtkWidget *)gtk_builder_get_object (builder, "language-swindow"); context = gtk_widget_get_style_context (widget); gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM); widget = (GtkWidget *)gtk_builder_get_object (builder, "language-toolbar"); context = gtk_widget_get_style_context (widget); gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP); treeview = GTK_WIDGET (gtk_builder_get_object (builder, "display_language_treeview")); /* Connect buttons */ widget = (GtkWidget *)gtk_builder_get_object (builder, "language_add"); g_signal_connect (widget, "clicked", G_CALLBACK (add_language), treeview); widget = (GtkWidget *)gtk_builder_get_object (builder, "logout_button"); g_signal_connect (widget, "clicked", G_CALLBACK (logout_requested), NULL); /* Setup accounts service */ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", NULL, &error); if (proxy == NULL) { g_warning ("Failed to contact accounts service: %s", error->message); g_clear_error (&error); } else { g_object_weak_ref (G_OBJECT (treeview), (GWeakNotify) g_object_unref, proxy); } /* And the session proxy */ sm_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.gnome.SessionManager", "/org/gnome/SessionManager", "org.gnome.SessionManager", NULL, &error); if (sm_proxy == NULL) { g_warning ("Failed to contact accounts service: %s", error->message); g_error_free (error); } else { g_object_weak_ref (G_OBJECT (treeview), (GWeakNotify) g_object_unref, sm_proxy); set_old_locale (); g_object_weak_ref (G_OBJECT (treeview), (GWeakNotify) g_free, old_locale); } /* Add user languages */ user_langs = cc_common_language_get_user_languages (); popular_langs = cc_common_language_get_initial_languages (); cc_common_language_setup_list (treeview, user_langs, popular_langs); g_object_set_data_full (G_OBJECT (treeview), "user-langs", user_langs, (GDestroyNotify) g_hash_table_destroy); g_object_set_data_full (G_OBJECT (treeview), "popular-langs", popular_langs, (GDestroyNotify) g_hash_table_destroy); /* And select the current language */ cc_common_language_select_current_language (GTK_TREE_VIEW (treeview)); /* Show the logout button if necessary */ locale = cc_common_language_get_current_language (); update_logout_button (builder, locale); /* And now listen for changes */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (selection_changed), builder); gtk_widget_grab_focus (treeview); }