Commit eadb6efd authored by Nick Schermer's avatar Nick Schermer

Allow setting most of the dialog values.

parent 40e86e82
......@@ -64,7 +64,8 @@ LT_INIT([disable-static])
dnl **********************************
dnl *** Check for standard headers ***
dnl **********************************
AC_CHECK_HEADERS([errno.h memory.h math.h stdlib.h string.h unistd.h signal.h time.h sys/types.h sys/wait.h])
AC_CHECK_HEADERS([errno.h memory.h math.h stdlib.h string.h unistd.h \
signal.h time.h sys/types.h sys/wait.h utmp.h pwd.h])
AC_CHECK_FUNCS([daemon setsid])
dnl ******************************
......@@ -127,6 +128,8 @@ dnl *** Optional support for accountsservice ***
dnl ********************************************
XDT_CHECK_OPTIONAL_PACKAGE([ACCOUNTSSERVICE], [accountsservice], [0.6.11],
[accountsservice], [User editing support])
XDT_CHECK_OPTIONAL_PACKAGE([GIO_UNIX], [gio-unix-2.0],
[2.24.0], [gio-unix], [GIO UNIX features])
dnl ***********************************
dnl *** Optional support for hwdata ***
......
......@@ -19,8 +19,9 @@ xfce4_user_settings_CFLAGS = \
$(GTK_CFLAGS) \
$(EXO_CFLAGS) \
$(LIBXFCE4UI_CFLAGS) \
$(XFCONF_CFLAGS) \
$(ACCOUNTSSERVICE_CFLAGS) \
$(GIO_CFLAGS) \
$(GIO_UNIX_CFLAGS) \
$(PLATFORM_CFLAGS)
xfce4_user_settings_LDFLAGS = \
......@@ -32,7 +33,8 @@ xfce4_user_settings_LDADD = \
$(EXO_LIBS) \
$(LIBXFCE4UI_LIBS) \
$(ACCOUNTSSERVICE_LIBS) \
$(XFCONF_LIBS)
$(GIO_LIBS) \
$(GIO_UNIX_LIBS)
if MAINTAINER_MODE
......
......@@ -23,39 +23,117 @@
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_UTMP_H
#include <utmp.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#include <glib.h>
#include <gtk/gtk.h>
#include <glib/gstdio.h>
#include <gio/gunixoutputstream.h>
#include <libxfce4ui/libxfce4ui.h>
#include <libxfce4util/libxfce4util.h>
#include <act/act-user-manager.h>
#include <xfconf/xfconf.h>
#include <exo/exo.h>
#include "user-dialog_ui.h"
#include "avatar_default.h"
#define MAX_ICON_SIZE 128
#define USER_ICON_SIZE 48
#define VALIDNAME_REGEX "^[a-z_][a-z0-9_-]*[$]?$"
/* Timeout id for updates on real name entry changes */
static guint real_name_entry_changed = 0;
/* Quark to bind the ActUserManager on the GtkBuilder */
static GQuark manager_quark = 0;
/* If the interface is updating (and saving should the skipped) */
static gboolean updating_widgets = FALSE;
/* GOptionEntry entry stuff */
static GdkNativeWindow opt_socket_id = 0;
static gboolean opt_version = FALSE;
static GQuark manager_quark;
static GOptionEntry entries[] =
static GOptionEntry opt_entries[] =
{
{ "socket-id", 's', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_INT, &opt_socket_id, N_("Settings manager socket"), N_("SOCKET ID") },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_("Version information"), NULL },
{ "socket-id", 's', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_INT,
&opt_socket_id, N_("Settings manager socket"), N_("SOCKET ID") },
{ "version", 'v', 0, G_OPTION_ARG_NONE,
&opt_version, N_("Version information"), NULL },
{ NULL }
};
/* Keep in sync with users-model store in glade */
enum
{
USERS_COL_ICON,
USERS_COL_UID,
USERS_COL_NAME,
USERS_COL_ABSTRACT
};
enum
{
USER_LANG_CODE,
USER_LANG_NAME
};
static const gchar *
user_settings_user_real_name (ActUser *user)
{
const gchar *name;
name = act_user_get_real_name (user);
if (exo_str_is_empty (name))
name = act_user_get_user_name (user);
return name;
}
/*static const gchar *
user_settings_user_language (ActUser *user)
{
const gchar *lang;
const gchar * const *langs;
lang = act_user_get_language (user);
if (exo_str_is_empty (lang))
{
lang = setlocale (LC_MESSAGES, NULL);
if (exo_str_is_empty (lang))
{
langs = g_get_language_names ();
if (langs != NULL && *langs != NULL)
lang = *langs;
else
lang = "en_US";
}
}
return lang;
}*/
static GdkPixbuf *
......@@ -97,26 +175,197 @@ user_settings_user_icon (ActUser *user,
static ActUser *
user_settings_user_get_selected (GtkBuilder *builder)
{
gchar *name = NULL;
GtkTreeModel *model;
GtkTreeIter iter;
ActUserManager *manager;
ActUser *user;
GObject *treeview;
GtkTreeSelection *selection;
/* Get selected iter */
treeview = gtk_builder_get_object (builder, "users-treeview");
g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), NULL);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
if (!gtk_tree_selection_get_selected (selection, &model, &iter))
return NULL;
/* Get the Username */
gtk_tree_model_get (model, &iter, USERS_COL_NAME, &name, -1);
if (name == NULL)
return NULL;
/* Get object from manager */
manager = g_object_get_qdata (G_OBJECT (builder), manager_quark);
user = act_user_manager_get_user (manager, name);
g_free (name);
g_assert (user != NULL);
return user;
}
static void
user_settings_user_icon_clicked (GtkWidget *button,
GtkBuilder *builder)
{
ActUser *user;
GtkWidget *dialog;
gchar *title;
GtkFileFilter *filter;
gint response;
gchar *filename;
GdkPixbuf *pixbuf;
GError *error = NULL;
GOutputStream *stream;
gchar *path = NULL;
gint fd;
g_return_if_fail (GTK_IS_WIDGET (button));
g_return_if_fail (GTK_IS_BUILDER (builder));
user = user_settings_user_get_selected (builder);
title = g_strdup_printf (_("Browse for an icon for %s"),
user_settings_user_real_name (user));
dialog = gtk_file_chooser_dialog_new (title,
GTK_WINDOW (gtk_widget_get_toplevel (button)),
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
exo_gtk_file_chooser_add_thumbnail_preview (GTK_FILE_CHOOSER (dialog));
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
/* add file chooser filters */
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("Image Files"));
gtk_file_filter_add_pixbuf_formats (filter);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_hide (dialog);
if (response == GTK_RESPONSE_OK)
{
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
pixbuf = exo_gdk_pixbuf_new_from_file_at_max_size (filename, MAX_ICON_SIZE,
MAX_ICON_SIZE, TRUE, &error);
if (pixbuf != NULL)
{
fd = g_file_open_tmp (NULL, &path, &error);
if (fd != -1)
{
stream = g_unix_output_stream_new (fd, TRUE);
if (gdk_pixbuf_save_to_stream (pixbuf, stream, "png", NULL, &error, NULL))
{
act_user_set_icon_file (user, path);
}
else
{
g_warning ("Failed to save image: %s", error->message);
g_error_free (error);
}
g_object_unref (stream);
g_remove (path);
}
else
{
g_critical ("Failed to create temporary file for user icon: %s", error->message);
g_error_free (error);
}
g_free (path);
g_object_unref (pixbuf);
}
else
{
g_critical ("Failed to load \"%s\": %s", filename, error->message);
g_error_free (error);
}
g_free (filename);
}
gtk_widget_destroy (dialog);
}
static void
user_settings_user_update (ActUserManager *manager,
ActUser *user,
GtkBuilder *builder)
user_settings_user_passwd_clicked (GtkWidget *button,
GtkBuilder *builder)
{
GObject *dialog;
gchar *title;
ActUser *user;
guint i;
GObject *object;
const gchar *name;
GdkPixbuf *icon;
const gchar *pwd_entries[] = { "pwd-old", "pwd-new",
"pwd-verify", "pwd-hint" };
g_return_if_fail (GTK_IS_WIDGET (button));
g_return_if_fail (GTK_IS_BUILDER (builder));
dialog = gtk_builder_get_object (builder, "pwd-dialog");
gtk_window_set_transient_for (GTK_WINDOW (dialog),
GTK_WINDOW (gtk_widget_get_toplevel (button)));
gtk_window_set_default_size (GTK_WINDOW (dialog), 400, -1);
user = user_settings_user_get_selected (builder);
title = g_strdup_printf (_("Changing password for %s"),
user_settings_user_real_name (user));
gtk_window_set_title (GTK_WINDOW (dialog), title);
g_free (title);
/* Make sure the text is not visible */
object = gtk_builder_get_object (builder, "pwd-visible");
g_return_if_fail (GTK_IS_TOGGLE_BUTTON (object));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (object), FALSE);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == 1)
{
/* Todo */
}
gtk_widget_hide (GTK_WIDGET (dialog));
/* Clear the passwords */
for (i = 0; i < G_N_ELEMENTS (pwd_entries); i++)
{
object = gtk_builder_get_object (builder, pwd_entries[i]);
g_return_if_fail (GTK_IS_ENTRY (object));
gtk_entry_set_text (GTK_ENTRY (object), "");
}
}
static void
user_settings_user_update (ActUser *user,
GtkBuilder *builder)
{
GObject *object;
GdkPixbuf *icon;
const gchar *lang;
GtkTreeModel *model;
GtkTreeIter iter;
gchar *code;
g_return_if_fail (ACT_IS_USER_MANAGER (manager));
g_return_if_fail (ACT_IS_USER (user));
g_return_if_fail (GTK_IS_BUILDER (builder));
name = act_user_get_real_name (user);
if (name == NULL || *name == '\0')
name = act_user_get_user_name (user);
updating_widgets = TRUE;
object = gtk_builder_get_object (builder, "user-name");
g_return_if_fail (GTK_IS_ENTRY (object));
gtk_entry_set_text (GTK_ENTRY (object), name);
gtk_entry_set_text (GTK_ENTRY (object),
user_settings_user_real_name (user));
object = gtk_builder_get_object (builder, "user-type-combo");
g_return_if_fail (GTK_IS_COMBO_BOX (object));
......@@ -125,6 +374,24 @@ user_settings_user_update (ActUserManager *manager,
object = gtk_builder_get_object (builder, "user-lang-combo");
g_return_if_fail (GTK_IS_COMBO_BOX (object));
lang = act_user_get_language (user);
model = gtk_combo_box_get_model (GTK_COMBO_BOX (object));
if (gtk_tree_model_get_iter_first (model, &iter))
{
do
{
gtk_tree_model_get (model, &iter, USER_LANG_CODE, &code, -1);
if (g_strcmp0 (lang, code) == 0)
{
g_free (code);
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (object), &iter);
break;
}
g_free (code);
}
while (gtk_tree_model_iter_next (model, &iter));
}
object = gtk_builder_get_object (builder, "user-auto-login");
g_return_if_fail (GTK_IS_TOGGLE_BUTTON (object));
......@@ -133,50 +400,44 @@ user_settings_user_update (ActUserManager *manager,
object = gtk_builder_get_object (builder, "user-icon");
g_return_if_fail (GTK_IS_IMAGE (object));
icon = user_settings_user_icon (user, 48);
gtk_widget_set_size_request (GTK_WIDGET (object), USER_ICON_SIZE, USER_ICON_SIZE);
icon = user_settings_user_icon (user, USER_ICON_SIZE);
gtk_image_set_from_pixbuf (GTK_IMAGE (object), icon);
if (icon != NULL)
g_object_unref (G_OBJECT (icon));
updating_widgets = FALSE;
}
static void
user_settings_user_added (ActUserManager *manager,
ActUser *user,
GtkBuilder *builder,
GtkTreeIter *iter_return)
user_settings_user_set_model (ActUser *user,
GtkListStore *model,
GtkTreeIter *iter)
{
gchar *abstract;
GObject *model;
GtkTreeIter iter;
const gchar *name;
const gchar *role;
GdkPixbuf *icon;
g_return_if_fail (ACT_IS_USER_MANAGER (manager));
g_return_if_fail (ACT_IS_USER (user));
g_return_if_fail (GTK_IS_BUILDER (builder));
model = gtk_builder_get_object (builder, "users-model");
g_return_if_fail (GTK_IS_LIST_STORE (model));
name = act_user_get_real_name (user);
if (name == NULL || *name == '\0')
name = act_user_get_user_name (user);
name = user_settings_user_real_name (user);
if (act_user_get_account_type (user) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR)
role = _("Administrator");
role = _("Administrator");
else
role = _("Standard");
role = _("Standard");
abstract = g_markup_printf_escaped ("%s\n<small>%s</small>", name, role);
icon = user_settings_user_icon (user, 32);
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
gtk_list_store_set (GTK_LIST_STORE (model), iter,
USERS_COL_ICON, icon,
USERS_COL_UID, act_user_get_uid (user),
USERS_COL_NAME, act_user_get_user_name (user),
USERS_COL_ABSTRACT, abstract,
-1);
......@@ -184,9 +445,67 @@ user_settings_user_added (ActUserManager *manager,
if (icon != NULL)
g_object_unref (G_OBJECT (icon));
g_free (abstract);
}
static void
user_settings_user_added (ActUserManager *manager,
ActUser *user,
GtkBuilder *builder)
{
GObject *model;
GtkTreeIter iter;
g_return_if_fail (ACT_IS_USER_MANAGER (manager));
g_return_if_fail (ACT_IS_USER (user));
g_return_if_fail (GTK_IS_BUILDER (builder));
model = gtk_builder_get_object (builder, "users-model");
g_return_if_fail (GTK_IS_LIST_STORE (model));
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
user_settings_user_set_model (user, GTK_LIST_STORE (model), &iter);
}
static gboolean
user_settings_user_model_find (ActUser *user,
GtkBuilder *builder,
GtkTreeModel **model_return,
GtkTreeIter *iter_return)
{
GtkTreeIter iter;
GtkTreeModel *model;
gboolean result = FALSE;
guint find_uid, uid;
model = GTK_TREE_MODEL (gtk_builder_get_object (builder, "users-model"));
g_return_val_if_fail (GTK_IS_LIST_STORE (model), FALSE);
find_uid = act_user_get_uid (user);
if (gtk_tree_model_get_iter_first (model, &iter))
{
do
{
gtk_tree_model_get (model, &iter, USERS_COL_UID, &uid, -1);
if (uid == find_uid)
{
result = TRUE;
break;
}
}
while (gtk_tree_model_iter_next (model, &iter));
}
if (model_return != NULL)
*model_return = GTK_TREE_MODEL (model);
if (iter_return != NULL)
*iter_return = iter;
return result;
}
......@@ -196,11 +515,15 @@ user_settings_user_removed (ActUserManager *manager,
ActUser *user,
GtkBuilder *builder)
{
GtkTreeModel *model;
GtkTreeIter iter;
g_return_if_fail (ACT_IS_USER_MANAGER (manager));
g_return_if_fail (ACT_IS_USER (user));
g_return_if_fail (GTK_IS_BUILDER (builder));
g_message ("user %s removed", act_user_get_user_name (user));
if (user_settings_user_model_find (user, builder, &model, &iter))
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
}
......@@ -210,11 +533,140 @@ user_settings_user_changed (ActUserManager *manager,
ActUser *user,
GtkBuilder *builder)
{
GtkTreeModel *model;
GtkTreeIter iter;
GObject *treeview;
GtkTreeSelection *selection;
g_return_if_fail (ACT_IS_USER_MANAGER (manager));
g_return_if_fail (ACT_IS_USER (user));
g_return_if_fail (GTK_IS_BUILDER (builder));
g_message ("user %s changed", act_user_get_user_name (user));
if (user_settings_user_model_find (user, builder, &model, &iter))
{
/* Set new values for the user selector */
user_settings_user_set_model (user, GTK_LIST_STORE (model), &iter);
/* Check if we need to update the widgets */
treeview = gtk_builder_get_object (builder, "users-treeview");
g_return_if_fail (GTK_IS_TREE_VIEW (treeview));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
if (gtk_tree_selection_iter_is_selected (selection, &iter))
user_settings_user_update (user, builder);
}
}
static gboolean
user_settings_user_name_done_timeout (gpointer data)
{
GtkBuilder *builder = GTK_BUILDER (data);
GObject *entry;
const gchar *name;
ActUser *user;
g_return_val_if_fail (GTK_IS_BUILDER (builder), FALSE);
entry = gtk_builder_get_object (builder, "user-name");
name = gtk_entry_get_text (GTK_ENTRY (entry));
user = user_settings_user_get_selected (builder);
act_user_set_real_name (user, name);
return FALSE;
}
static void
user_settings_user_name_done_timeout_destroyed (gpointer data)
{
real_name_entry_changed = 0;
}
static void
user_settings_user_change_name_now (GtkBuilder *builder)
{
if (real_name_entry_changed != 0)
{
g_source_remove (real_name_entry_changed);
user_settings_user_name_done_timeout (builder);
}
}
static void
user_settings_user_change_name (GtkBuilder *builder)
{
g_return_if_fail (GTK_IS_BUILDER (builder));
/* Leave if widgets are updating */
if (updating_widgets)
return;
/* Abort pending update */
if (real_name_entry_changed != 0)
g_source_remove (real_name_entry_changed);
/* Schedule a new update */
real_name_entry_changed = g_timeout_add_seconds_full (
G_PRIORITY_DEFAULT_IDLE, 1,
user_settings_user_name_done_timeout,
builder, user_settings_user_name_done_timeout_destroyed);
}
static void
user_settings_user_change_language (GtkWidget *combobox,
GtkBuilder *builder)
{
GtkTreeIter iter;
GtkTreeModel *model;
gchar *code;
ActUser *user;
g_return_if_fail (GTK_IS_BUILDER (builder));
g_return_if_fail (GTK_IS_COMBO_BOX (combobox));
/* Leave if widgets are updating */
if (updating_widgets)
return;
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &iter))
{
model = gtk_combo_box_get_model (GTK_COMBO_BOX (combobox));
gtk_tree_model_get (model, &iter, USER_LANG_CODE, &code, -1);
user = user_settings_user_get_selected (builder);
act_user_set_language (user, code);
g_free (code);
}
}
static void
user_settings_user_change_type (GtkWidget *combobox,
GtkBuilder *builder)
{
gint account_type;
ActUser *user;
g_return_if_fail (GTK_IS_BUILDER (builder));
g_return_if_fail (GTK_IS_COMBO_BOX (combobox));
/* Leave if widgets are updating */
if (updating_widgets)
return;
account_type = gtk_combo_box_get_active (GTK_COMBO_BOX (combobox));
user = user_settings_user_get_selected (builder);
act_user_set_account_type (user, account_type);
}
......@@ -223,30 +675,250 @@ static void
user_settings_user_selection_changed (GtkTreeSelection *selection,
GtkBuilder *builder)
{
gchar *name = NULL;
GtkTreeModel *model;
GtkTreeIter iter;
ActUser *user;
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
g_return_if_fail (GTK_IS_BUILDER (builder));
/* Save pending update */