/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2012 Red Hat
*
* 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, see .
*
* Written by:
* Jasper St. Pierre
* Michael Wood
*
* Based on gnome-control-center cc-region-panel.c
*/
/* Language page {{{1 */
#define PAGE_ID "language"
#define GNOME_SYSTEM_LOCALE_DIR "org.gnome.system.locale"
#define REGION_KEY "region"
#include "config.h"
#include "language-resources.h"
#include "gis-welcome-widget.h"
#include "cc-language-chooser.h"
#include "gis-language-page.h"
#include
#include
#include
#include
struct _GisLanguagePagePrivate
{
GtkWidget *logo;
GtkWidget *welcome_widget;
GtkWidget *language_chooser;
GDBusProxy *localed;
GPermission *permission;
const gchar *new_locale_id;
GCancellable *cancellable;
};
typedef struct _GisLanguagePagePrivate GisLanguagePagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GisLanguagePage, gis_language_page, GIS_TYPE_PAGE);
static void
set_localed_locale (GisLanguagePage *self)
{
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (self);
GVariantBuilder *b;
gchar *s;
b = g_variant_builder_new (G_VARIANT_TYPE ("as"));
s = g_strconcat ("LANG=", priv->new_locale_id, NULL);
g_variant_builder_add (b, "s", s);
g_free (s);
g_dbus_proxy_call (priv->localed,
"SetLocale",
g_variant_new ("(asb)", b, TRUE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL, NULL);
g_variant_builder_unref (b);
}
static void
change_locale_permission_acquired (GObject *source,
GAsyncResult *res,
gpointer data)
{
GisLanguagePage *page = GIS_LANGUAGE_PAGE (data);
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
GError *error = NULL;
gboolean allowed;
allowed = g_permission_acquire_finish (priv->permission, res, &error);
if (error) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed to acquire permission: %s", error->message);
g_error_free (error);
return;
}
if (allowed)
set_localed_locale (page);
}
static void
user_loaded (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
gchar *new_locale_id = user_data;
act_user_set_language (ACT_USER (object), new_locale_id);
g_free (new_locale_id);
}
static void
language_changed (CcLanguageChooser *chooser,
GParamSpec *pspec,
GisLanguagePage *page)
{
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
GisDriver *driver;
GSettings *region_settings;
ActUser *user;
priv->new_locale_id = cc_language_chooser_get_language (chooser);
driver = GIS_PAGE (page)->driver;
gis_driver_set_user_language (driver, priv->new_locale_id, TRUE);
gtk_widget_set_default_direction (gtk_get_locale_direction ());
if (gis_driver_get_mode (driver) == GIS_DRIVER_MODE_NEW_USER) {
if (g_permission_get_allowed (priv->permission)) {
set_localed_locale (page);
}
else if (g_permission_get_can_acquire (priv->permission)) {
g_permission_acquire_async (priv->permission,
NULL,
change_locale_permission_acquired,
page);
}
}
/* Ensure we won't override the selected language for format strings */
region_settings = g_settings_new (GNOME_SYSTEM_LOCALE_DIR);
g_settings_reset (region_settings, REGION_KEY);
g_object_unref (region_settings);
user = act_user_manager_get_user (act_user_manager_get_default (),
g_get_user_name ());
if (act_user_is_loaded (user))
act_user_set_language (user, priv->new_locale_id);
else
g_signal_connect (user,
"notify::is-loaded",
G_CALLBACK (user_loaded),
g_strdup (priv->new_locale_id));
gis_welcome_widget_show_locale (GIS_WELCOME_WIDGET (priv->welcome_widget),
priv->new_locale_id);
}
static void
localed_proxy_ready (GObject *source,
GAsyncResult *res,
gpointer data)
{
GisLanguagePage *self = data;
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (self);
GDBusProxy *proxy;
GError *error = NULL;
proxy = g_dbus_proxy_new_finish (res, &error);
if (!proxy) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed to contact localed: %s", error->message);
g_error_free (error);
return;
}
priv->localed = proxy;
}
static void
update_distro_logo (GisLanguagePage *page)
{
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
g_autofree char *id = g_get_os_info (G_OS_INFO_KEY_ID);
gsize i;
static const struct {
const char *id;
const char *logo;
} id_to_logo[] = {
{ "debian", "emblem-debian" },
{ "fedora", "fedora-logo-icon" },
{ "ubuntu", "ubuntu-logo-icon" },
{ "openSUSE Tumbleweed", "opensuse-logo-icon" },
{ "openSUSE Leap", "opensuse-logo-icon" },
{ "SLED", "suse-logo-icon" },
{ "SLES", "suse-logo-icon" },
};
for (i = 0; i < G_N_ELEMENTS (id_to_logo); i++)
{
if (g_strcmp0 (id, id_to_logo[i].id) == 0)
{
g_object_set (priv->logo, "icon-name", id_to_logo[i].logo, NULL);
break;
}
}
}
static void
language_confirmed (CcLanguageChooser *chooser,
GisLanguagePage *page)
{
gis_assistant_next_page (gis_driver_get_assistant (GIS_PAGE (page)->driver));
}
static void
gis_language_page_constructed (GObject *object)
{
GisLanguagePage *page = GIS_LANGUAGE_PAGE (object);
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
GDBusConnection *bus;
g_type_ensure (CC_TYPE_LANGUAGE_CHOOSER);
G_OBJECT_CLASS (gis_language_page_parent_class)->constructed (object);
update_distro_logo (page);
g_signal_connect (priv->language_chooser, "notify::language",
G_CALLBACK (language_changed), page);
g_signal_connect (priv->language_chooser, "confirm",
G_CALLBACK (language_confirmed), page);
/* If we're in new user mode then we're manipulating system settings */
if (gis_driver_get_mode (GIS_PAGE (page)->driver) == GIS_DRIVER_MODE_NEW_USER)
{
priv->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-locale", NULL, NULL, NULL);
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
g_dbus_proxy_new (bus,
G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
NULL,
"org.freedesktop.locale1",
"/org/freedesktop/locale1",
"org.freedesktop.locale1",
priv->cancellable,
(GAsyncReadyCallback) localed_proxy_ready,
object);
g_object_unref (bus);
}
gis_page_set_complete (GIS_PAGE (page), TRUE);
gtk_widget_show (GTK_WIDGET (page));
}
static void
gis_language_page_locale_changed (GisPage *page)
{
gis_page_set_title (GIS_PAGE (page), _("Welcome"));
}
static void
gis_language_page_dispose (GObject *object)
{
GisLanguagePage *page = GIS_LANGUAGE_PAGE (object);
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
g_clear_object (&priv->permission);
g_clear_object (&priv->localed);
g_clear_object (&priv->cancellable);
G_OBJECT_CLASS (gis_language_page_parent_class)->dispose (object);
}
static void
gis_language_page_class_init (GisLanguagePageClass *klass)
{
GisPageClass *page_class = GIS_PAGE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/initial-setup/gis-language-page.ui");
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisLanguagePage, welcome_widget);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisLanguagePage, language_chooser);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisLanguagePage, logo);
page_class->page_id = PAGE_ID;
page_class->locale_changed = gis_language_page_locale_changed;
object_class->constructed = gis_language_page_constructed;
object_class->dispose = gis_language_page_dispose;
}
static void
gis_language_page_init (GisLanguagePage *page)
{
g_resources_register (language_get_resource ());
g_type_ensure (GIS_TYPE_WELCOME_WIDGET);
g_type_ensure (CC_TYPE_LANGUAGE_CHOOSER);
gtk_widget_init_template (GTK_WIDGET (page));
}
GisPage *
gis_prepare_language_page (GisDriver *driver)
{
return g_object_new (GIS_TYPE_LANGUAGE_PAGE,
"driver", driver,
NULL);
}