[accounts-dialog] Implement login options saving



commit a9caf59c8f6c1ecc8be9af2a57187e3b8f5f8cdf
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Jan 20 13:40:12 2010 -0500

    Implement login options saving
    
    Autologin is saved via the SetAutomaticLogin method in the accounts-service,
    all the others are saved via the GConf defaults mechanism to the mandatory
    GConf database. One icky aspect of this is that we have to run
    gconftool-2 directly to get updates of the current state, since gconfd
    does not notice changes in the defaults and mandatory databases.
    
    At the same time, try using a PolkitLockButton for controlling access
    to the login options page.

 configure.ac           |    3 +-
 src/Makefile.am        |    2 +
 src/um-login-options.c |  253 +++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 221 insertions(+), 37 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 98d7feb..fa72053 100644
--- a/configure.ac
+++ b/configure.ac
@@ -36,8 +36,9 @@ PKG_CHECK_MODULES(GTK, gtk+-2.0)
 PKG_CHECK_MODULES(GNOME_DESKTOP, gnome-desktop-2.0)
 PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1)
 PKG_CHECK_MODULES(UNIQUE, unique-1.0)
-PKG_CHECK_MODULES(POLKIT, polkit-gobject-1)
+PKG_CHECK_MODULES(POLKIT, polkit-gtk-1)
 PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1)
+PKG_CHECK_MODULES(GCONF, gconf-2.0)
 PKG_CHECK_MODULES(CHEESE, cheese-gtk, have_cheese=yes, have_cheese=no)
 
 if test x$have_cheese = xyes ; then
diff --git a/src/Makefile.am b/src/Makefile.am
index d05d2ad..5a40447 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,6 +13,7 @@ INCLUDES = \
 	$(POLKIT_CFLAGS)				\
 	$(CHEESE_CFLAGS)				\
 	$(DBUS_GLIB_CFLAGS)				\
+	$(GCONF_CFLAGS)					\
 	$(WARN_CFLAGS)
 
 accounts_dialog_SOURCES = \
@@ -60,6 +61,7 @@ accounts_dialog_LDADD = 		\
 	$(POLKIT_LIBS)			\
 	$(CHEESE_LIBS)			\
 	$(DBUS_GLIB_LIBS)		\
+	$(GCONF_LIBS)			\
 	-lcrypt
 
 MARSHALFILES = marshal.c marshal.h
diff --git a/src/um-login-options.c b/src/um-login-options.c
index 42a19fc..5cab924 100644
--- a/src/um-login-options.c
+++ b/src/um-login-options.c
@@ -25,23 +25,31 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+#include <gconf/gconf-client.h>
+#include <gconf/gconf-value.h>
+#include <polkitgtk/polkitgtk.h>
 
 #include "um-login-options.h"
 #include "um-user-manager.h"
 #include "um-user.h"
 
 struct _UmLoginOptions {
-	GtkWidget *autologin_combo;
-	GtkWidget *userlist_check;
-	GtkWidget *power_check;
-	GtkWidget *hints_check;
-	GtkWidget *guest_check;
+        GtkWidget *autologin_combo;
+        GtkWidget *userlist_check;
+        GtkWidget *power_check;
+        GtkWidget *hints_check;
+        GtkWidget *guest_check;
+        GtkWidget *lock_button;
 
-	UmUserManager *manager;
+        UmUserManager *manager;
+
+        DBusGProxy *proxy;
+        DBusGConnection *connection;
 };
 
 enum {
@@ -85,31 +93,37 @@ sort_login_users (GtkTreeModel *model,
 static void
 user_added (UmUserManager *um, UmUser *user, UmLoginOptions *d)
 {
-	GtkComboBox *combo;
-	GtkListStore *store;
-	GtkTreeIter iter;
+        GtkComboBox *combo;
+        GtkListStore *store;
+        GtkTreeIter iter;
 
-	combo = GTK_COMBO_BOX (d->autologin_combo);
+        g_debug ("adding user '%s', %d", um_user_get_user_name (user), um_user_get_automatic_login (user));
+        combo = GTK_COMBO_BOX (d->autologin_combo);
         store = (GtkListStore*)gtk_combo_box_get_model (combo);
         gtk_list_store_append (store, &iter);
         gtk_list_store_set (store, &iter,
                             AUTOLOGIN_NAME_COL, um_user_get_real_name (user),
                             AUTOLOGIN_USER_COL, user,
                             -1);
+
+        if (um_user_get_automatic_login (user)) {
+                gtk_combo_box_set_active_iter (combo, &iter);
+        }
 }
 
 static void
 user_removed (UmUserManager *um, UmUser *user, UmLoginOptions *d)
 {
-	GtkComboBox *combo;
-	GtkTreeModel *model;
-	GtkListStore *store;
-	GtkTreeIter iter;
-	UmUser *u;
+        GtkComboBox *combo;
+        GtkTreeModel *model;
+        GtkListStore *store;
+        GtkTreeIter iter;
+        UmUser *u;
 
-	combo = GTK_COMBO_BOX (d->autologin_combo);
+        combo = GTK_COMBO_BOX (d->autologin_combo);
         model = gtk_combo_box_get_model (combo);
         store = (GtkListStore*)model;
+
         gtk_combo_box_get_active_iter (combo, &iter);
         gtk_tree_model_get (model, &iter, AUTOLOGIN_USER_COL, &u, -1);
         if (u != NULL) {
@@ -143,15 +157,15 @@ user_changed (UmUserManager  *manager,
               UmUser         *user,
               UmLoginOptions *d)
 {
-	/* FIXME */
+        /* FIXME */
 }
 
 static void
 users_loaded (UmUserManager  *manager,
               UmLoginOptions *d)
 {
-	GSList *list, *l;
-	UmUser *user;
+        GSList *list, *l;
+        UmUser *user;
 
         list = um_user_manager_list_users (manager);
         for (l = list; l; l = l->next) {
@@ -165,32 +179,167 @@ users_loaded (UmUserManager  *manager,
         g_signal_connect (manager, "user-changed", G_CALLBACK (user_changed), d);
 }
 
+static void update_login_options (GtkWidget *widget, UmLoginOptions *d);
+
+static void
+update_boolean_from_gconf (GtkWidget      *widget,
+                           UmLoginOptions *d)
+{
+        gchar *cmdline;
+        gboolean value;
+        gchar *std_out;
+        gchar *std_err;
+        gint status;
+        GError *error;
+        const gchar *key;
+
+        key = g_object_get_data (G_OBJECT (widget), "gconf-key");
+
+        cmdline = g_strdup_printf ("gconftool-2 --direct --config-source=\"xml:readonly:/ect/gconf/gconf.xml.defaults;xml:readonly:/etc/gconf/gconf.xml.mandatory\" --get %s", key);
+
+        error = NULL;
+        std_out = NULL;
+        std_err = NULL;
+        if (!g_spawn_command_line_sync (cmdline, &std_out, &std_err, &status, &error)) {
+                g_warning ("Failed to run '%s': %s", cmdline, error->message);
+                g_error_free (error);
+                g_free (cmdline);
+                g_free (std_out);
+                g_free (std_err);
+                return;
+        }
+        if (WEXITSTATUS (status) != 0) {
+                g_warning ("Failed to run '%s': %s", cmdline, std_err);
+                g_free (cmdline);
+                g_free (std_out);
+                g_free (std_err);
+                return;
+        }
+
+        if (std_out[strlen (std_out) - 1] == '\n') {
+                std_out[strlen (std_out) - 1] = 0;
+        }
+
+        if (g_strcmp0 (std_out, "true") == 0) {
+                value = TRUE;
+        }
+        else {
+                value = FALSE;
+        }
+        g_signal_handlers_block_by_func (widget, update_login_options, d);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), !value);
+        g_signal_handlers_unblock_by_func (widget, update_login_options, d);
+
+        g_free (cmdline);
+        g_free (std_out);
+        g_free (std_err);
+}
+
 static void
 update_login_options (GtkWidget      *widget,
                       UmLoginOptions *d)
 {
+        GError *error;
+        gboolean active;
+        GConfValue *value;
+        const gchar *key = NULL;
+        gchar *value_string;
+
+        if (widget == d->userlist_check ||
+            widget == d->power_check) {
+                active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+                key = g_object_get_data (G_OBJECT (widget), "gconf-key");
+        }
+        else {
+                g_warning ("unhandled option in update_login_options");
+                return;
+        }
+
+        error = NULL;
+        value = gconf_value_new (GCONF_VALUE_BOOL);
+        gconf_value_set_bool (value, !active);
+        value_string = gconf_value_encode (value);
+        if (!dbus_g_proxy_call (d->proxy, "SetMandatoryValue",
+                                &error,
+                                G_TYPE_STRING, key,
+                                G_TYPE_STRING, value_string,
+                                G_TYPE_INVALID,
+                                G_TYPE_INVALID)) {
+               g_warning ("error calling SetMandatoryValue: %s\n", error->message);
+               g_error_free (error);
+       }
+       g_free (value_string);
+       gconf_value_free (value);
+       update_boolean_from_gconf (widget, d);
+}
+
+static void
+update_autologin (GtkWidget      *widget,
+                  UmLoginOptions *d)
+{
+        GtkComboBox *combo = GTK_COMBO_BOX (widget);
+        GtkTreeModel *model;
+        GtkTreeIter iter;
+        UmUserManager *manager;
+        UmUser *user;
+        gboolean enabled;
+
+        if (!gtk_widget_is_sensitive (widget))
+                return;
+
+        model = gtk_combo_box_get_model (combo);
+        gtk_combo_box_get_active_iter (combo, &iter);
+        gtk_tree_model_get (model, &iter, AUTOLOGIN_USER_COL, &user, -1);
+        if (user) {
+                enabled = TRUE;
+        }
+        else {
+                enabled = FALSE;
+
+                manager = um_user_manager_ref_default ();
+                user = um_user_manager_get_user_by_id (manager, getuid ());
+                g_object_unref (manager);
+        }
+
+        um_user_set_automatic_login (user, enabled);
+}
+
+static void
+lockbutton_changed (PolkitLockButton *button,
+                    gpointer          data)
+{
+        UmLoginOptions *d = data;
+        gboolean authorized;
+
+        authorized = polkit_lock_button_get_is_authorized (button);
+
+        gtk_widget_set_sensitive (d->autologin_combo, authorized);
+        gtk_widget_set_sensitive (d->userlist_check, authorized);
+        gtk_widget_set_sensitive (d->power_check, authorized);
+        gtk_widget_set_sensitive (d->hints_check, authorized);
+        gtk_widget_set_sensitive (d->guest_check, authorized);
 }
 
 UmLoginOptions *
 um_login_options_new (GtkBuilder *builder)
 {
         GtkWidget *widget;
+        GtkWidget *box;
         GtkListStore *store;
         GtkTreeIter iter;
-	gchar *filename;
-	GError *error;
-	UmLoginOptions *um;
+        GError *error;
+        UmLoginOptions *um;
 
         /* TODO: get actual login screen options */
 
-	um = g_new0 (UmLoginOptions, 1);
+        um = g_new0 (UmLoginOptions, 1);
 
-	um->manager = um_user_manager_ref_default ();
-	g_signal_connect (um->manager, "users-loaded",
+        um->manager = um_user_manager_ref_default ();
+        g_signal_connect (um->manager, "users-loaded",
                           G_CALLBACK (users_loaded), um);
 
-	widget = (GtkWidget *) gtk_builder_get_object (builder, "dm-automatic-login-combobox");
-	um->autologin_combo = widget;
+        widget = (GtkWidget *) gtk_builder_get_object (builder, "dm-automatic-login-combobox");
+        um->autologin_combo = widget;
 
         store = gtk_list_store_new (2, G_TYPE_STRING, UM_TYPE_USER);
         gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (store));
@@ -203,26 +352,58 @@ um_login_options_new (GtkBuilder *builder)
         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
 
         g_signal_connect (widget, "changed",
-                          G_CALLBACK (update_login_options), um);
+                          G_CALLBACK (update_autologin), um);
 
-	widget = (GtkWidget *) gtk_builder_get_object (builder, "dm-show-user-list-checkbutton");
-	um->userlist_check = widget;
+        widget = (GtkWidget *) gtk_builder_get_object (builder, "dm-show-user-list-checkbutton");
+        um->userlist_check = widget;
         g_signal_connect (widget, "toggled",
                           G_CALLBACK (update_login_options), um);
+        g_object_set_data (G_OBJECT (widget), "gconf-key",
+                           "/apps/gdm/simple-greeter/disable_user_list");
+        update_boolean_from_gconf (widget, um);
 
-	widget = (GtkWidget *) gtk_builder_get_object (builder, "dm-show-power-buttons-checkbutton");
-	um->power_check = widget;
+        widget = (GtkWidget *) gtk_builder_get_object (builder, "dm-show-power-buttons-checkbutton");
+        um->power_check = widget;
         g_signal_connect(widget, "toggled",
                          G_CALLBACK (update_login_options), um);
+        g_object_set_data (G_OBJECT (widget), "gconf-key",
+                           "/apps/gdm/simple-greeter/disable_restart_buttons");
+        update_boolean_from_gconf (widget, um);
 
-	widget = (GtkWidget *) gtk_builder_get_object (builder, "dm-show-password-hints-checkbutton");
-	um->hints_check = widget;
+        widget = (GtkWidget *) gtk_builder_get_object (builder, "dm-show-password-hints-checkbutton");
+        um->hints_check = widget;
         g_signal_connect (widget, "toggled",
                           G_CALLBACK (update_login_options), um);
 
-	widget = (GtkWidget *) gtk_builder_get_object (builder, "dm-allow-guest-login-checkbutton");
-	um->guest_check = widget;
+        widget = (GtkWidget *) gtk_builder_get_object (builder, "dm-allow-guest-login-checkbutton");
+        um->guest_check = widget;
         g_signal_connect (widget, "toggled",
                           G_CALLBACK (update_login_options), um);
+
+        widget = polkit_lock_button_new ("org.freedesktop.accounts.set-login-option");
+        gtk_widget_show (widget);
+        box = (GtkWidget *)gtk_builder_get_object (builder, "main-login-window-vbox");
+        gtk_box_pack_end (GTK_BOX (box), widget, FALSE, FALSE, 0);
+        g_signal_connect (widget, "changed",
+                          G_CALLBACK (lockbutton_changed), um);
+        lockbutton_changed (POLKIT_LOCK_BUTTON (widget), um);
+
+        error = NULL;
+        um->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (error != NULL) {
+                g_warning ("Failed to get system bus connection: %s", error->message);
+                g_error_free (error);
+        }
+
+        um->proxy = dbus_g_proxy_new_for_name (um->connection,
+                                               "org.gnome.GConf.Defaults",
+                                               "/",
+                                               "org.gnome.GConf.Defaults");
+
+        if (um->proxy == NULL) {
+                g_warning ("Cannot connect to GConf defaults mechanism");
+        }
+
+        return um;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]