[accounts-dialog] Use unique display names if real names clash



commit 391024867429ba756c85ed17eacd9fbae7752812
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Jan 24 03:03:25 2010 -0500

    Use unique display names if real names clash

 src/main.c            |    8 ++-
 src/um-user-manager.c |  106 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/um-user-manager.h |    2 +-
 src/um-user.c         |   82 ++++++++++++++++++++++++++++++-------
 src/um-user.h         |    3 +
 5 files changed, 181 insertions(+), 20 deletions(-)
---
diff --git a/src/main.c b/src/main.c
index bb60f28..36dd6ef 100644
--- a/src/main.c
+++ b/src/main.c
@@ -136,7 +136,7 @@ user_added (UmUserManager *um, UmUser *user, UserAccountDialog *d)
 
         pixbuf = um_user_render_icon (user, TRUE, 48);
         text = g_strdup_printf ("<b>%s</b>\n<i>%s</i>",
-                                um_user_get_real_name (user),
+                                um_user_get_display_name (user),
                                 um_account_type_get_name (um_user_get_account_type (user)));
 
         if (um_user_get_uid (user) == getuid ()) {
@@ -234,7 +234,7 @@ user_changed (UmUserManager *um, UmUser *user, UserAccountDialog *d)
                 if (current == user) {
                         pixbuf = um_user_render_icon (user, TRUE, 48);
                         text = g_strdup_printf ("<b>%s</b>\n<i>%s</i>",
-                                                um_user_get_real_name (user),
+                                                um_user_get_display_name (user),
                                                 um_account_type_get_name (um_user_get_account_type (user)));
 
                         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
@@ -904,6 +904,9 @@ users_loaded (UmUserManager     *manager,
 
         list = um_user_manager_list_users (d->um);
         g_debug ("Got %d users\n", g_slist_length (list));
+
+        g_signal_connect (d->um, "user-changed", G_CALLBACK (user_changed), d);
+
         for (l = list; l; l = l->next) {
                 user = l->data;
                 g_debug ("adding user %s\n", um_user_get_real_name (user));
@@ -913,7 +916,6 @@ users_loaded (UmUserManager     *manager,
 
         g_signal_connect (d->um, "user-added", G_CALLBACK (user_added), d);
         g_signal_connect (d->um, "user-removed", G_CALLBACK (user_removed), d);
-        g_signal_connect (d->um, "user-changed", G_CALLBACK (user_changed), d);
 }
 
 static void
diff --git a/src/um-user-manager.c b/src/um-user-manager.c
index 695037c..7330e91 100644
--- a/src/um-user-manager.c
+++ b/src/um-user-manager.c
@@ -104,10 +104,90 @@ um_user_manager_class_init (UmUserManagerClass *klass)
                               G_TYPE_NONE, 1, UM_TYPE_USER);
 }
 
+
+/* We maintain a ring for each group of users with the same real name.
+ * We need this to pick the right display names.
+ */
+static void
+remove_user_from_dupe_ring (UmUserManager *manager,
+                            UmUser        *user)
+{
+        GList *dupes;
+        UmUser *dup;
+
+        um_user_show_short_display_name (user);
+
+        dupes = g_object_get_data (user, "dupes");
+
+        if (dupes == NULL) {
+                return;
+        }
+
+        if (dupes->next == dupes->prev) {
+                dup = dupes->next->data;
+                um_user_show_short_display_name (dup);
+                g_signal_emit (manager, signals[USER_CHANGED], 0, dup);
+
+                g_list_free_1 (dupes->next);
+                g_object_set_data (dup, "dupes", NULL);
+        }
+        else {
+                dupes->next->prev = dupes->prev;
+                dupes->prev->next = dupes->next;
+        }
+
+        g_list_free_1 (dupes);
+        g_object_set_data (user, "dupes", NULL);
+}
+
+static gboolean
+match_real_name_hrfunc (gpointer key,
+                        gpointer value,
+                        gpointer user)
+{
+        return (value != user && g_strcmp0 (um_user_get_real_name (user), um_user_get_real_name (value)) == 0);
+}
+
+static void
+add_user_to_dupe_ring (UmUserManager *manager,
+                       UmUser        *user)
+{
+        UmUser *dup;
+        GList *dupes;
+        GList *l;
+
+        dup = g_hash_table_find (manager->user_by_object_path,
+                                 match_real_name_hrfunc, user);
+
+        if (!dup) {
+                return;
+        }
+
+        um_user_show_full_display_name (user);
+
+        dupes = g_object_get_data (dup, "dupes");
+        if (!dupes) {
+                um_user_show_full_display_name (dup);
+                g_signal_emit (manager, signals[USER_CHANGED], 0, dup);
+                dupes = g_list_append (NULL, dup);
+                g_object_set_data (dup, "dupes", dupes);
+                dupes->next = dupes->prev = dupes;
+        }
+
+        l = g_list_append (NULL, user);
+        g_object_set_data (user, "dupes", l);
+        l->prev = dupes->prev;
+        dupes->prev->next = l;
+        l->next = dupes;
+        dupes->prev = l;
+}
+
 static void
 user_changed_handler (UmUser        *user,
                       UmUserManager *manager)
 {
+        remove_user_from_dupe_ring (manager, user);
+        add_user_to_dupe_ring (manager, user);
         g_signal_emit (manager, signals[USER_CHANGED], 0, user);
 }
 
@@ -125,10 +205,14 @@ user_added_handler (DBusGProxy *proxy,
         user = um_user_new_from_object_path (object_path);
         if (!user)
                 return;
+
+        add_user_to_dupe_ring (manager, user);
+
         g_signal_connect (user, "changed",
                           G_CALLBACK (user_changed_handler), manager);
         g_hash_table_insert (manager->user_by_object_path, (gpointer)um_user_get_object_path (user), g_object_ref (user));
         g_hash_table_insert (manager->user_by_name, (gpointer)um_user_get_user_name (user), g_object_ref (user));
+
         g_signal_emit (manager, signals[USER_ADDED], 0, user);
         g_object_unref (user);
 }
@@ -144,6 +228,9 @@ user_deleted_handler (DBusGProxy *proxy,
         user = g_hash_table_lookup (manager->user_by_object_path, object_path);
         g_object_ref (user);
         g_signal_handlers_disconnect_by_func (user, user_changed_handler, manager);
+
+        remove_user_from_dupe_ring (manager, user);
+
         g_hash_table_remove (manager->user_by_object_path, um_user_get_object_path (user));
         g_hash_table_remove (manager->user_by_name, um_user_get_user_name (user));
         g_signal_emit (manager, signals[USER_REMOVED], 0, user);
@@ -237,12 +324,31 @@ um_user_manager_init (UmUserManager *manager)
 }
 
 static void
+clear_dup (gpointer key,
+           gpointer value,
+           gpointer data)
+{
+        GList *dupes;
+
+        /* don't bother maintaining the ring, we're destroying the
+         * entire hash table anyway
+         */
+        dupes = g_object_get_data (value, "dupes");
+
+        if (dupes) {
+                g_list_free_1 (dupes);
+                g_object_set_data (value, "dupes", NULL);
+        }
+}
+
+static void
 um_user_manager_finalize (GObject *object)
 {
         UmUserManager *manager;
 
         manager = UM_USER_MANAGER (object);
 
+        g_hash_table_foreach (manager->user_by_object_path, clear_dup, NULL);
         g_hash_table_destroy (manager->user_by_object_path);
         g_hash_table_destroy (manager->user_by_name);
 
diff --git a/src/um-user-manager.h b/src/um-user-manager.h
index fe8b193..a25b36a 100644
--- a/src/um-user-manager.h
+++ b/src/um-user-manager.h
@@ -45,7 +45,7 @@ typedef struct
         GHashTable *user_by_object_path;
         GHashTable *user_by_name;
 
-	gboolean no_service;
+        gboolean no_service;
 } UmUserManager;
 
 typedef struct
diff --git a/src/um-user.c b/src/um-user.c
index 0d12b80..756e3c9 100644
--- a/src/um-user.c
+++ b/src/um-user.c
@@ -182,6 +182,8 @@ struct _UmUser {
         gchar           *object_path;
 
         UserProperties  *props;
+
+        gchar           *display_name;
 };
 
 typedef struct _UmUserClass
@@ -260,6 +262,15 @@ um_user_get_real_name (UmUser *user)
 }
 
 const gchar *
+um_user_get_display_name (UmUser *user)
+{
+        g_return_val_if_fail (UM_IS_USER (user), NULL);
+
+       return user->display_name ? user->display_name
+                                 : user->props->real_name;
+}
+
+const gchar *
 um_user_get_user_name (UmUser *user)
 {
         g_return_val_if_fail (UM_IS_USER (user), NULL);
@@ -665,8 +676,8 @@ um_user_get_language (UmUser *user)
 {
         g_return_val_if_fail (UM_IS_USER (user), NULL);
 
-	if (*user->props->language == '\0')
-		return NULL;
+        if (*user->props->language == '\0')
+                return NULL;
         return user->props->language;
 }
 
@@ -742,6 +753,10 @@ changed_handler (DBusGProxy *proxy,
         UmUser *user = UM_USER (data);
 
         if (update_info (user)) {
+                if (user->display_name != NULL) {
+                        um_user_show_full_display_name (user);
+                }
+
                 g_signal_emit (user, signals[CHANGED], 0);
         }
 }
@@ -1020,37 +1035,37 @@ gboolean
 um_user_is_logged_in (UmUser *user)
 {
         DBusGProxy *proxy;
-	GPtrArray *array;
-	GError *error;
-	gint n_sessions;
+        GPtrArray *array;
+        GError *error;
+        gint n_sessions;
 
         proxy = dbus_g_proxy_new_for_name (user->bus,
-					   "org.freedesktop.ConsoleKit",
+                                           "org.freedesktop.ConsoleKit",
                                            "/org/freedesktop/ConsoleKit/Manager",
                                            "org.freedesktop.ConsoleKit.Manager");
 
-	array = NULL;
-	error = NULL;
+        array = NULL;
+        error = NULL;
         if (!dbus_g_proxy_call (proxy,
                                 "GetSessionsForUnixUser",
                                 &error,
                                 G_TYPE_UINT, um_user_get_uid (user),
                                 G_TYPE_INVALID,
-				dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &array,
+                                dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &array,
                                 G_TYPE_INVALID)) {
                 g_warning ("GetSessionsForUnixUser failed: %s", error->message);
-		g_error_free (error);
-		return FALSE;
-	}
+                g_error_free (error);
+                return FALSE;
+        }
 
-	n_sessions = array->len;
+        n_sessions = array->len;
 
         g_ptr_array_foreach (array, (GFunc)g_free, NULL);
-	g_ptr_array_free (array, TRUE);
+        g_ptr_array_free (array, TRUE);
 
-	g_object_unref (proxy);
+        g_object_unref (proxy);
 
-	return n_sessions > 0;
+        return n_sessions > 0;
 }
 
 
@@ -1071,3 +1086,38 @@ um_user_set_automatic_login (UmUser   *user,
         }
 }
 
+void
+um_user_show_full_display_name (UmUser *user)
+{
+        char *uniq_name;
+
+        g_return_if_fail (UM_IS_USER (user));
+
+        if (user->props->real_name != NULL) {
+                uniq_name = g_strdup_printf ("%s (%s)",
+                                             user->props->real_name,
+                                             user->props->user_name);
+        } else {
+                uniq_name = NULL;
+        }
+
+        if (uniq_name && g_strcmp0 (uniq_name, user->display_name) != 0) {
+                g_free (user->display_name);
+                user->display_name = uniq_name;
+        }
+        else {
+                g_free (uniq_name);
+        }
+}
+
+void
+um_user_show_short_display_name (UmUser *user)
+{
+        g_return_if_fail (UM_IS_USER (user));
+
+        if (user->display_name) {
+                g_free (user->display_name);
+                user->display_name = NULL;
+        }
+}
+
diff --git a/src/um-user.h b/src/um-user.h
index 5f0e50d..6c487b6 100644
--- a/src/um-user.h
+++ b/src/um-user.h
@@ -97,6 +97,9 @@ GdkPixbuf     *um_user_render_icon         (UmUser   *user,
 gint           um_user_collate             (UmUser   *user1,
                                             UmUser   *user2);
 
+void           um_user_show_short_display_name (UmUser *user);
+void           um_user_show_full_display_name  (UmUser *user);
+
 G_END_DECLS
 
 #endif



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