gdm r5689 - in trunk: . gui/simple-greeter



Author: mccann
Date: Mon Feb  4 15:23:19 2008
New Revision: 5689
URL: http://svn.gnome.org/viewvc/gdm?rev=5689&view=rev

Log:
2008-02-04  William Jon McCann  <jmccann redhat com>

	* gui/simple-greeter/gdm-chooser-widget.c: (foreach_item),
	(compare_item), (gdm_chooser_widget_init),
	(gdm_chooser_widget_update_item), (gdm_chooser_widget_add_item),
	(gdm_chooser_widget_lookup_item),
	(gdm_chooser_widget_set_item_priority):
	* gui/simple-greeter/gdm-chooser-widget.h:
	* gui/simple-greeter/gdm-language-chooser-widget.c:
	(gdm_language_chooser_widget_add_language):
	* gui/simple-greeter/gdm-session-chooser-widget.c: (add_session),
	(add_available_sessions):
	* gui/simple-greeter/gdm-user-chooser-widget.c:
	(add_special_users), (on_user_added),
	(on_user_login_frequency_changed), (gdm_user_chooser_widget_init):
	* gui/simple-greeter/gdm-user-manager.c: (parse_value_as_ulong),
	(parse_ck_history_line), (process_ck_history_line),
	(ck_history_watch), (reload_users), (reload_users_timeout),
	(queue_reload_users), (gdm_user_manager_class_init),
	(gdm_user_manager_init), (gdm_user_manager_finalize):
	* gui/simple-greeter/gdm-user-manager.h:
	* gui/simple-greeter/gdm-user.c: (_gdm_user_set_login_frequency),
	(gdm_user_set_property), (gdm_user_get_property),
	(gdm_user_class_init), (gdm_user_init),
	(gdm_user_get_login_frequency):
	* gui/simple-greeter/gdm-user.h:
	Only show users that have frequently logged in.



Modified:
   trunk/ChangeLog
   trunk/gui/simple-greeter/gdm-chooser-widget.c
   trunk/gui/simple-greeter/gdm-chooser-widget.h
   trunk/gui/simple-greeter/gdm-language-chooser-widget.c
   trunk/gui/simple-greeter/gdm-session-chooser-widget.c
   trunk/gui/simple-greeter/gdm-user-chooser-widget.c
   trunk/gui/simple-greeter/gdm-user-manager.c
   trunk/gui/simple-greeter/gdm-user-manager.h
   trunk/gui/simple-greeter/gdm-user.c
   trunk/gui/simple-greeter/gdm-user.h

Modified: trunk/gui/simple-greeter/gdm-chooser-widget.c
==============================================================================
--- trunk/gui/simple-greeter/gdm-chooser-widget.c	(original)
+++ trunk/gui/simple-greeter/gdm-chooser-widget.c	Mon Feb  4 15:23:19 2008
@@ -114,6 +114,7 @@
         CHOOSER_IMAGE_COLUMN = 0,
         CHOOSER_NAME_COLUMN,
         CHOOSER_COMMENT_COLUMN,
+        CHOOSER_PRIORITY_COLUMN,
         CHOOSER_ITEM_IS_IN_USE_COLUMN,
         CHOOSER_ITEM_IS_SEPARATED_COLUMN,
         CHOOSER_ITEM_IS_VISIBLE_COLUMN,
@@ -176,6 +177,7 @@
         gboolean   is_separate;
         gboolean   res;
         char      *id;
+        gulong     priority;
 
         gtk_tree_model_get (model,
                             iter,
@@ -183,6 +185,7 @@
                             CHOOSER_IMAGE_COLUMN, &image,
                             CHOOSER_NAME_COLUMN, &name,
                             CHOOSER_COMMENT_COLUMN, &comment,
+                            CHOOSER_PRIORITY_COLUMN, &priority,
                             CHOOSER_ITEM_IS_IN_USE_COLUMN, &in_use,
                             CHOOSER_ITEM_IS_SEPARATED_COLUMN, &is_separate,
                             -1);
@@ -191,6 +194,7 @@
                           &image,
                           &name,
                           &comment,
+                          &priority,
                           &in_use,
                           &is_separate,
                           data->user_data);
@@ -201,6 +205,7 @@
                                     CHOOSER_IMAGE_COLUMN, image,
                                     CHOOSER_NAME_COLUMN, name,
                                     CHOOSER_COMMENT_COLUMN, comment,
+                                    CHOOSER_PRIORITY_COLUMN, priority,
                                     CHOOSER_ITEM_IS_IN_USE_COLUMN, in_use,
                                     CHOOSER_ITEM_IS_SEPARATED_COLUMN, is_separate,
                                     -1);
@@ -1226,11 +1231,14 @@
         GdmChooserWidget *widget;
         char             *name_a;
         char             *name_b;
+        gulong            prio_a;
+        gulong            prio_b;
         gboolean          is_separate_a;
         gboolean          is_separate_b;
         int               result;
         int               direction;
         GtkTreeIter      *separator_iter;
+        char             *id;
 
         g_assert (GDM_IS_CHOOSER_WIDGET (data));
 
@@ -1260,17 +1268,18 @@
         if (separator_iter != a) {
                 gtk_tree_model_get (model, a,
                                     CHOOSER_NAME_COLUMN, &name_a,
+                                    CHOOSER_PRIORITY_COLUMN, &prio_a,
                                     CHOOSER_ITEM_IS_SEPARATED_COLUMN, &is_separate_a,
                                     -1);
         }
 
-        char *id;
         name_b = NULL;
         is_separate_b = FALSE;
         if (separator_iter != b) {
                 gtk_tree_model_get (model, b,
                                     CHOOSER_NAME_COLUMN, &name_b,
                                     CHOOSER_ID_COLUMN, &id,
+                                    CHOOSER_PRIORITY_COLUMN, &prio_b,
                                     CHOOSER_ITEM_IS_SEPARATED_COLUMN, &is_separate_b,
                                     -1);
         }
@@ -1288,7 +1297,13 @@
                 result = is_separate_b? -1 : 1;
                 result *= direction;
         } else if (is_separate_b == is_separate_a) {
-                result = g_utf8_collate (name_a, name_b);
+                if (prio_a == prio_b) {
+                        result = g_utf8_collate (name_a, name_b);
+                } else if (prio_a > prio_b) {
+                        result = -1;
+                } else {
+                        result = 1;
+                }
         } else {
                 result = is_separate_a - is_separate_b;
                 result *= direction;
@@ -1545,11 +1560,12 @@
         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->priv->items_view));
         gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
 
-        g_assert (NUMBER_OF_CHOOSER_COLUMNS == 7);
+        g_assert (NUMBER_OF_CHOOSER_COLUMNS == 8);
         widget->priv->list_store = gtk_list_store_new (NUMBER_OF_CHOOSER_COLUMNS,
                                                        GDK_TYPE_PIXBUF,
                                                        G_TYPE_STRING,
                                                        G_TYPE_STRING,
+                                                       G_TYPE_ULONG,
                                                        G_TYPE_BOOLEAN,
                                                        G_TYPE_BOOLEAN,
                                                        G_TYPE_BOOLEAN,
@@ -1667,6 +1683,7 @@
                                 GdkPixbuf        *new_image,
                                 const char       *new_name,
                                 const char       *new_comment,
+                                gulong            new_priority,
                                 gboolean          new_in_use,
                                 gboolean          new_is_separate)
 {
@@ -1728,6 +1745,7 @@
                             CHOOSER_IMAGE_COLUMN, new_image,
                             CHOOSER_NAME_COLUMN, new_name,
                             CHOOSER_COMMENT_COLUMN, new_comment,
+                            CHOOSER_PRIORITY_COLUMN, new_priority,
                             CHOOSER_ITEM_IS_IN_USE_COLUMN, new_in_use,
                             CHOOSER_ITEM_IS_SEPARATED_COLUMN, new_is_separate,
                             -1);
@@ -1739,6 +1757,7 @@
                              GdkPixbuf        *image,
                              const char       *name,
                              const char       *comment,
+                             gulong            priority,
                              gboolean          in_use,
                              gboolean          keep_separate)
 {
@@ -1769,6 +1788,7 @@
                                            CHOOSER_IMAGE_COLUMN, image,
                                            CHOOSER_NAME_COLUMN, name,
                                            CHOOSER_COMMENT_COLUMN, comment,
+                                           CHOOSER_PRIORITY_COLUMN, priority,
                                            CHOOSER_ITEM_IS_IN_USE_COLUMN, in_use,
                                            CHOOSER_ITEM_IS_SEPARATED_COLUMN, keep_separate,
                                            CHOOSER_ITEM_IS_VISIBLE_COLUMN, is_visible,
@@ -1831,6 +1851,7 @@
                                 GdkPixbuf       **image,
                                 char            **name,
                                 char            **comment,
+                                gulong           *priority,
                                 gboolean         *is_in_use,
                                 gboolean         *is_separate)
 {
@@ -1854,6 +1875,7 @@
         gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter,
                             CHOOSER_IMAGE_COLUMN, image,
                             CHOOSER_NAME_COLUMN, name,
+                            CHOOSER_PRIORITY_COLUMN, priority,
                             CHOOSER_ITEM_IS_IN_USE_COLUMN, is_in_use,
                             CHOOSER_ITEM_IS_SEPARATED_COLUMN, is_separate,
                             -1);
@@ -1897,6 +1919,34 @@
 }
 
 void
+gdm_chooser_widget_set_item_priority (GdmChooserWidget *widget,
+                                      const char       *id,
+                                      gulong            priority)
+{
+        GtkTreeIter   iter;
+        gulong        was_priority;
+
+        g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
+
+        if (!find_item (widget, id, &iter)) {
+                return;
+        }
+
+        gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter,
+                            CHOOSER_PRIORITY_COLUMN, &was_priority,
+                            -1);
+
+        if (was_priority != priority) {
+
+                gtk_list_store_set (widget->priv->list_store,
+                                    &iter,
+                                    CHOOSER_PRIORITY_COLUMN, priority,
+                                    -1);
+                gtk_tree_model_filter_refilter (widget->priv->model_filter);
+        }
+}
+
+void
 gdm_chooser_widget_set_in_use_message (GdmChooserWidget *widget,
                                        const char       *message)
 {

Modified: trunk/gui/simple-greeter/gdm-chooser-widget.h
==============================================================================
--- trunk/gui/simple-greeter/gdm-chooser-widget.h	(original)
+++ trunk/gui/simple-greeter/gdm-chooser-widget.h	Mon Feb  4 15:23:19 2008
@@ -64,6 +64,7 @@
                                                           GdkPixbuf       **image,
                                                           char            **name,
                                                           char            **comment,
+                                                          gulong           *priority,
                                                           gboolean         *is_in_use,
                                                           gboolean         *is_separate,
                                                           gpointer          data);
@@ -77,6 +78,7 @@
                                                                   GdkPixbuf        *image,
                                                                   const char       *name,
                                                                   const char       *comment,
+                                                                  gulong            priority,
                                                                   gboolean          is_in_use,
                                                                   gboolean          keep_separate);
 
@@ -89,6 +91,7 @@
                                                                   GdkPixbuf        *new_image,
                                                                   const char       *new_name,
                                                                   const char       *new_comment,
+                                                                  gulong            priority,
                                                                   gboolean          new_in_use,
                                                                   gboolean          new_is_separate);
 
@@ -100,6 +103,7 @@
                                                                   GdkPixbuf       **image,
                                                                   char            **name,
                                                                   char            **comment,
+                                                                  gulong           *priority,
                                                                   gboolean         *is_in_use,
                                                                   gboolean         *is_separate);
 
@@ -110,6 +114,9 @@
 void                   gdm_chooser_widget_set_item_in_use        (GdmChooserWidget *widget,
                                                                   const char       *id,
                                                                   gboolean          is_in_use);
+void                   gdm_chooser_widget_set_item_priority      (GdmChooserWidget *widget,
+                                                                  const char       *id,
+                                                                  gulong            priority);
 
 void                   gdm_chooser_widget_set_in_use_message     (GdmChooserWidget *widget,
                                                                   const char       *message);

Modified: trunk/gui/simple-greeter/gdm-language-chooser-widget.c
==============================================================================
--- trunk/gui/simple-greeter/gdm-language-chooser-widget.c	(original)
+++ trunk/gui/simple-greeter/gdm-language-chooser-widget.c	Mon Feb  4 15:23:19 2008
@@ -127,7 +127,11 @@
         if (language != NULL) {
                 gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
                                              normalized_name,
-                                             NULL, language, "", FALSE,
+                                             NULL,
+                                             language,
+                                             "",
+                                             0,
+                                             FALSE,
                                              FALSE);
                 g_free (language);
         }

Modified: trunk/gui/simple-greeter/gdm-session-chooser-widget.c
==============================================================================
--- trunk/gui/simple-greeter/gdm-session-chooser-widget.c	(original)
+++ trunk/gui/simple-greeter/gdm-session-chooser-widget.c	Mon Feb  4 15:23:19 2008
@@ -349,9 +349,14 @@
                 g_debug ("Not adding session to list: %s", session->filename);
         }
 
-        gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget), name,
-                                     NULL, session->translated_name,
-                                     session->translated_comment, FALSE, FALSE);
+        gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
+                                     name,
+                                     NULL,
+                                     session->translated_name,
+                                     session->translated_comment,
+                                     0,
+                                     FALSE,
+                                     FALSE);
 }
 
 static void
@@ -359,15 +364,21 @@
 {
         gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
                                      GDM_SESSION_CHOOSER_SESSION_PREVIOUS,
-                                     NULL, _("Default"),
+                                     NULL,
+                                     _("Default"),
                                      _("Login with the same session as "
                                        "last time."),
-                                     FALSE, TRUE);
+                                     0,
+                                     FALSE,
+                                     TRUE);
         gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
                                      GDM_SESSION_CHOOSER_SESSION_DEFAULT,
-                                     NULL, _("Legacy"),
+                                     NULL,
+                                     _("Legacy"),
                                      _("Login based on preset legacy configuration"),
-                                     FALSE, TRUE);
+                                     0,
+                                     FALSE,
+                                     TRUE);
 
         g_hash_table_foreach (widget->priv->available_sessions,
                               (GHFunc) add_session,

Modified: trunk/gui/simple-greeter/gdm-user-chooser-widget.c
==============================================================================
--- trunk/gui/simple-greeter/gdm-user-chooser-widget.c	(original)
+++ trunk/gui/simple-greeter/gdm-user-chooser-widget.c	Mon Feb  4 15:23:19 2008
@@ -312,14 +312,18 @@
                                      GDM_USER_CHOOSER_USER_OTHER,
                                      widget->priv->stock_person_pixbuf,
                                      _("Other..."),
-                                     _("Choose a different account"), FALSE,
+                                     _("Choose a different account"),
+                                     0,
+                                     FALSE,
                                      TRUE);
 
         gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
                                      GDM_USER_CHOOSER_USER_GUEST,
                                      widget->priv->stock_person_pixbuf,
                                      _("Guest"),
-                                     _("Login as a temporary guest"), FALSE,
+                                     _("Login as a temporary guest"),
+                                     0,
+                                     FALSE,
                                      TRUE);
 
         return FALSE;
@@ -354,6 +358,7 @@
                                      pixbuf,
                                      gdm_user_get_real_name (user),
                                      tooltip,
+                                     gdm_user_get_login_frequency (user),
                                      is_logged_in,
                                      FALSE);
         g_free (tooltip);
@@ -397,6 +402,24 @@
 }
 
 static void
+on_user_login_frequency_changed (GdmUserManager       *manager,
+                                 GdmUser              *user,
+                                 GdmUserChooserWidget *widget)
+{
+        const char *user_name;
+        gulong      freq;
+
+        g_debug ("GdmUserChooserWidget: User login frequency changed: %s", gdm_user_get_user_name (user));
+
+        user_name = gdm_user_get_user_name (user);
+        freq = gdm_user_get_login_frequency (user);
+
+        gdm_chooser_widget_set_item_priority (GDM_CHOOSER_WIDGET (widget),
+                                              user_name,
+                                              freq);
+}
+
+static void
 gdm_user_chooser_widget_init (GdmUserChooserWidget *widget)
 {
         widget->priv = GDM_USER_CHOOSER_WIDGET_GET_PRIVATE (widget);
@@ -419,6 +442,10 @@
                           "user-is-logged-in-changed",
                           G_CALLBACK (on_user_is_logged_in_changed),
                           widget);
+        g_signal_connect (widget->priv->manager,
+                          "user-login-frequency-changed",
+                          G_CALLBACK (on_user_login_frequency_changed),
+                          widget);
 
         setup_icons (widget);
         add_special_users (widget);

Modified: trunk/gui/simple-greeter/gdm-user-manager.c
==============================================================================
--- trunk/gui/simple-greeter/gdm-user-manager.c	(original)
+++ trunk/gui/simple-greeter/gdm-user-manager.c	Mon Feb  4 15:23:19 2008
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2007 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2007-2008 William Jon McCann <mccann jhu edu>
  *
  * 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
@@ -34,13 +34,11 @@
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
 #include <glib-object.h>
-#define DBUS_API_SUBJECT_TO_CHANGE
+
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
-#include <libgnomevfs/gnome-vfs.h>
-
 #include "gdm-user-manager.h"
 #include "gdm-user-private.h"
 
@@ -60,15 +58,10 @@
 #define DEFAULT_MAX_ICON_SIZE   128
 #define DEFAULT_USER_MAX_FILE   65536
 
-#ifdef __sun
-#define DEFAULT_MINIMAL_UID     100
-#else
-#define DEFAULT_MINIMAL_UID     500
-#endif
-
 #define DEFAULT_GLOBAL_FACE_DIR DATADIR "/faces"
 #define DEFAULT_USER_ICON       "stock_person"
 #define DEFAULT_EXCLUDE         { "bin",        \
+                                  "root",       \
                                   "daemon",     \
                                   "adm",        \
                                   "lp",         \
@@ -92,16 +85,13 @@
 {
         GHashTable            *users;
         GHashTable            *sessions;
-        GHashTable            *shells;
         GHashTable            *exclusions;
-        GnomeVFSMonitorHandle *passwd_monitor;
-        GnomeVFSMonitorHandle *shells_monitor;
         DBusGConnection       *connection;
         DBusGProxy            *seat_proxy;
         char                  *seat_id;
 
         guint                  reload_id;
-        uid_t                  minimal_uid;
+        guint                  ck_history_id;
 
         guint8                 users_dirty : 1;
 };
@@ -110,6 +100,7 @@
         USER_ADDED,
         USER_REMOVED,
         USER_IS_LOGGED_IN_CHANGED,
+        USER_LOGIN_FREQUENCY_CHANGED,
         LAST_SIGNAL
 };
 
@@ -664,143 +655,236 @@
         return g_slist_sort (retval, (GCompareFunc) gdm_user_collate);
 }
 
-static void
-reload_passwd (GdmUserManager *manager)
+static gboolean
+parse_value_as_ulong (const char *value,
+                      gulong     *ulongval)
 {
-        struct passwd *pwent;
-        GSList        *old_users;
-        GSList        *new_users;
-        GSList        *list;
-
-        old_users = NULL;
-        new_users = NULL;
-
-        g_hash_table_foreach (manager->priv->users, listify_hash_values_hfunc, &old_users);
-        g_slist_foreach (old_users, (GFunc) g_object_ref, NULL);
-
-        /* Make sure we keep users who are logged in no matter what. */
-        for (list = old_users; list; list = list->next) {
-                if (gdm_user_get_num_sessions (list->data) > 0) {
-                        g_object_freeze_notify (G_OBJECT (list->data));
-                        new_users = g_slist_prepend (new_users, g_object_ref (list->data));
-                }
+        char  *end_of_valid_long;
+        glong  long_value;
+        gulong ulong_value;
+
+        errno = 0;
+        long_value = strtol (value, &end_of_valid_long, 10);
+
+        if (*value == '\0' || *end_of_valid_long != '\0') {
+                return FALSE;
         }
 
-        setpwent ();
+        ulong_value = long_value;
+        if (ulong_value != long_value || errno == ERANGE) {
+                return FALSE;
+        }
 
-        for (pwent = getpwent (); pwent; pwent = getpwent ()) {
-                GdmUser *user;
+        *ulongval = ulong_value;
 
-                user = NULL;
+        return TRUE;
+}
 
-                /* Skip users below MinimalUID... */
-                if (pwent->pw_uid < manager->priv->minimal_uid) {
-                        continue;
-                }
+static gboolean
+parse_ck_history_line (const char *line,
+                       char      **user_namep,
+                       gulong     *frequencyp)
+{
+        GRegex     *re;
+        GMatchInfo *match_info;
+        gboolean    res;
+        gboolean    ret;
+        GError     *error;
 
-                /* ...And users w/ invalid shells... */
-                if (!pwent->pw_shell ||
-                    !g_hash_table_lookup (manager->priv->shells, pwent->pw_shell)) {
-                        continue;
-                }
+        ret = FALSE;
+        re = NULL;
+        match_info = NULL;
 
-                /* ...And explicitly excluded users */
-                if (g_hash_table_lookup (manager->priv->exclusions, pwent->pw_name)) {
-                        continue;
-                }
+        error = NULL;
+        re = g_regex_new ("(?P<username>[0-9a-zA-Z]+)[ ]+(?P<frequency>[0-9]+)", 0, 0, &error);
+        if (re == NULL) {
+                g_critical (error->message);
+                goto out;
+        }
 
-                user = g_hash_table_lookup (manager->priv->users, pwent->pw_name);
+        g_regex_match (re, line, 0, &match_info);
 
-                /* Update users already in the *new* list */
-                if (g_slist_find (new_users, user)) {
-                        _gdm_user_update (user, pwent);
-                        continue;
-                }
+        res = g_match_info_matches (match_info);
+        if (! res) {
+                g_warning ("Unable to parse history: %s", line);
+                goto out;
+        }
+
+        if (user_namep != NULL) {
+                *user_namep = g_match_info_fetch_named (match_info, "username");
+        }
 
-                if (user == NULL) {
-                        user = create_user (manager);
-                } else {
-                        g_object_ref (user);
+        if (frequencyp != NULL) {
+                char *freq;
+                freq = g_match_info_fetch_named (match_info, "frequency");
+                res = parse_value_as_ulong (freq, frequencyp);
+                g_free (freq);
+                if (! res) {
+                        goto out;
                 }
+        }
 
-                /* Freeze & update users not already in the new list */
-                g_object_freeze_notify (G_OBJECT (user));
-                _gdm_user_update (user, pwent);
+        ret = TRUE;
 
-                new_users = g_slist_prepend (new_users, user);
+ out:
+        if (match_info != NULL) {
+                g_match_info_free (match_info);
+        }
+        if (re != NULL) {
+                g_regex_unref (re);
         }
+        return ret;
+}
 
-        endpwent ();
+static void
+process_ck_history_line (GdmUserManager *manager,
+                         const char     *line)
+{
+        gboolean res;
+        char    *username;
+        gulong   frequency;
+        GdmUser *user;
 
-        /* Go through and handle added users */
-        for (list = new_users; list; list = list->next) {
-                if (! g_slist_find (old_users, list->data)) {
-                        add_user (manager, list->data);
-                }
+        frequency = 0;
+        username = NULL;
+        res = parse_ck_history_line (line, &username, &frequency);
+        if (! res) {
+                return;
         }
 
-        /* Go through and handle removed users */
-        for (list = old_users; list; list = list->next) {
-                if (! g_slist_find (new_users, list->data)) {
-                        g_signal_emit (manager, signals[USER_REMOVED], 0, list->data);
-                        g_hash_table_remove (manager->priv->users,
-                                             gdm_user_get_user_name (list->data));
+        if (g_hash_table_lookup (manager->priv->exclusions, username)) {
+                g_debug ("GdmUserManager: excluding user '%s'", username);
+                g_free (username);
+                return;
+        }
+
+        user = gdm_user_manager_get_user (manager, username);
+        g_object_set (user, "login-frequency", frequency, NULL);
+        g_signal_emit (manager, signals [USER_LOGIN_FREQUENCY_CHANGED], 0, user);
+}
+
+static gboolean
+ck_history_watch (GIOChannel     *source,
+                  GIOCondition    condition,
+                  GdmUserManager *manager)
+{
+        GIOStatus status;
+        gboolean  done  = FALSE;
+
+        g_return_val_if_fail (manager != NULL, FALSE);
+
+        if (condition & G_IO_IN) {
+                char   *str;
+                GError *error;
+
+                error = NULL;
+                status = g_io_channel_read_line (source, &str, NULL, NULL, &error);
+                if (error != NULL) {
+                        g_warning ("GdmUserManager: unable to read line: %s", error->message);
+                        g_error_free (error);
+                }
+
+                if (status == G_IO_STATUS_NORMAL) {
+                        g_debug ("GdmUserManager: history output: %s", str);
+                        process_ck_history_line (manager, str);
+                } else if (status == G_IO_STATUS_EOF) {
+                        done = TRUE;
                 }
+
+                g_free (str);
+        } else if (condition & G_IO_HUP) {
+                done = TRUE;
         }
 
-        /* Cleanup */
-        g_slist_foreach (new_users, (GFunc) g_object_thaw_notify, NULL);
-        g_slist_foreach (new_users, (GFunc) g_object_unref, NULL);
-        g_slist_free (new_users);
+        if (done) {
+                manager->priv->ck_history_id = 0;
+                return FALSE;
+        }
 
-        g_slist_foreach (old_users, (GFunc) g_object_unref, NULL);
-        g_slist_free (old_users);
+        return TRUE;
 }
 
 static void
-reload_shells (GdmUserManager *manager)
+reload_users (GdmUserManager *manager)
 {
-        char *shell;
+        char       *command;
+        const char *seat_id;
+        GError     *error;
+        gboolean    res;
+        char      **argv;
+        int         standard_out;
+        GIOChannel *channel;
 
-        setusershell ();
+        seat_id = NULL;
+        if (manager->priv->seat_id != NULL
+            && g_str_has_prefix (manager->priv->seat_id, "/org/freedesktop/ConsoleKit/")) {
 
-        g_hash_table_remove_all (manager->priv->shells);
-        for (shell = getusershell (); shell; shell = getusershell ()) {
-                g_hash_table_insert (manager->priv->shells,
-                                     g_strdup (shell),
-                                     GUINT_TO_POINTER (TRUE));
+                seat_id = manager->priv->seat_id + strlen ("/org/freedesktop/ConsoleKit/");
+        }
+
+        if (seat_id == NULL) {
+                g_warning ("Unable to find users: no seat-id found");
         }
 
-        endusershell ();
+        command = g_strdup_printf ("ck-history --frequent --seat='%s' --session-type=''",
+                                   seat_id);
+        g_debug ("GdmUserManager: running '%s'", command);
+        error = NULL;
+        if (! g_shell_parse_argv (command, NULL, &argv, &error)) {
+                g_warning ("Could not parse command: %s", error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+        error = NULL;
+        res = g_spawn_async_with_pipes (NULL,
+                                        argv,
+                                        NULL,
+                                        G_SPAWN_SEARCH_PATH,
+                                        NULL,
+                                        NULL,
+                                        NULL, /* pid */
+                                        NULL,
+                                        &standard_out,
+                                        NULL,
+                                        &error);
+        if (! res) {
+                g_warning ("Unable to run ck-history: %s", error->message);
+                g_error_free (error);
+        }
+        g_strfreev (argv);
+
+        channel = g_io_channel_unix_new (standard_out);
+        g_io_channel_set_close_on_unref (channel, TRUE);
+        g_io_channel_set_flags (channel,
+                                g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK,
+                                NULL);
+        manager->priv->ck_history_id = g_io_add_watch (channel,
+                                                       G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+                                                       (GIOFunc)ck_history_watch,
+                                                       manager);
+        g_io_channel_unref (channel);
+
+ out:
+        g_free (command);
 }
 
-static void
-shells_monitor_cb (GnomeVFSMonitorHandle    *handle,
-                   const gchar              *text_uri,
-                   const gchar              *info_uri,
-                   GnomeVFSMonitorEventType  event_type,
-                   GdmUserManager           *manager)
+static gboolean
+reload_users_timeout (GdmUserManager *manager)
 {
-        if (event_type != GNOME_VFS_MONITOR_EVENT_CHANGED &&
-            event_type != GNOME_VFS_MONITOR_EVENT_CREATED)
-                return;
-
-        reload_shells (manager);
-        reload_passwd (manager);
+        reload_users (manager);
+        manager->priv->reload_id = 0;
+        return FALSE;
 }
 
 static void
-passwd_monitor_cb (GnomeVFSMonitorHandle    *handle,
-                   const gchar              *text_uri,
-                   const gchar              *info_uri,
-                   GnomeVFSMonitorEventType  event_type,
-                   GdmUserManager           *manager)
+queue_reload_users (GdmUserManager *manager)
 {
-        if (event_type != GNOME_VFS_MONITOR_EVENT_CHANGED &&
-            event_type != GNOME_VFS_MONITOR_EVENT_CREATED)
+        if (manager->priv->reload_id > 0) {
                 return;
+        }
 
-        reload_passwd (manager);
+        manager->priv->reload_id = g_idle_add ((GSourceFunc)reload_users_timeout, manager);
 }
 
 static void
@@ -834,45 +918,26 @@
                               NULL, NULL,
                               g_cclosure_marshal_VOID__OBJECT,
                               G_TYPE_NONE, 1, GDM_TYPE_USER);
+        signals [USER_LOGIN_FREQUENCY_CHANGED] =
+                g_signal_new ("user-login-frequency-changed",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GdmUserManagerClass, user_login_frequency_changed),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE, 1, GDM_TYPE_USER);
 
         g_type_class_add_private (klass, sizeof (GdmUserManagerPrivate));
 }
 
-static gboolean
-reload_passwd_timeout (GdmUserManager *manager)
-{
-        reload_passwd (manager);
-        manager->priv->reload_id = 0;
-        return FALSE;
-}
-
-static void
-queue_reload_passwd (GdmUserManager *manager)
-{
-        if (manager->priv->reload_id > 0) {
-                return;
-        }
-
-        manager->priv->reload_id = g_idle_add ((GSourceFunc)reload_passwd_timeout, manager);
-}
-
 static void
 gdm_user_manager_init (GdmUserManager *manager)
 {
-        GError        *error;
-        char          *uri;
-        GnomeVFSResult result;
         int            i;
         const char    *exclude_default[] = DEFAULT_EXCLUDE;
 
-        if (! gnome_vfs_initialized ()) {
-                gnome_vfs_init ();
-        }
-
         manager->priv = GDM_USER_MANAGER_GET_PRIVATE (manager);
 
-        manager->priv->minimal_uid = DEFAULT_MINIMAL_UID;
-
         /* sessions */
         manager->priv->sessions = g_hash_table_new_full (g_str_hash,
                                                          g_str_equal,
@@ -890,58 +955,14 @@
                                      GUINT_TO_POINTER (TRUE));
         }
 
-        /* /etc/shells */
-        manager->priv->shells = g_hash_table_new_full (g_str_hash,
-                                                       g_str_equal,
-                                                       g_free,
-                                                       NULL);
-        reload_shells (manager);
-        error = NULL;
-        uri = g_filename_to_uri ("/etc/shells", NULL, &error);
-        if (uri == NULL) {
-                g_warning ("Could not create URI for shells file `/etc/shells': %s",
-                            error->message);
-                g_error_free (error);
-        } else {
-                result = gnome_vfs_monitor_add (&(manager->priv->shells_monitor),
-                                                uri,
-                                                GNOME_VFS_MONITOR_FILE,
-                                                (GnomeVFSMonitorCallback)shells_monitor_cb,
-                                                manager);
-                g_free (uri);
-
-                if (result != GNOME_VFS_OK)
-                        g_warning ("Could not install monitor for shells file `/etc/shells': %s",
-                                    gnome_vfs_result_to_string (result));
-        }
-
-        /* /etc/passwd */
         manager->priv->users = g_hash_table_new_full (g_str_hash,
                                                       g_str_equal,
                                                       g_free,
                                                       (GDestroyNotify) g_object_run_dispose);
-        error = NULL;
-        uri = g_filename_to_uri ("/etc/passwd", NULL, &error);
-        if (uri == NULL) {
-                g_warning ("Could not create URI for password file `/etc/passwd': %s",
-                            error->message);
-                g_error_free (error);
-        } else {
-                result = gnome_vfs_monitor_add (&(manager->priv->passwd_monitor),
-                                                uri,
-                                                GNOME_VFS_MONITOR_FILE,
-                                                (GnomeVFSMonitorCallback)passwd_monitor_cb,
-                                                manager);
-                g_free (uri);
-
-                if (result != GNOME_VFS_OK)
-                        g_warning ("Could not install monitor for password file `/etc/passwd: %s",
-                                   gnome_vfs_result_to_string (result));
-        }
 
         get_seat_proxy (manager);
 
-        queue_reload_passwd (manager);
+        queue_reload_users (manager);
 
         manager->priv->users_dirty = FALSE;
 }
@@ -962,6 +983,11 @@
                 g_object_unref (manager->priv->seat_proxy);
         }
 
+        if (manager->priv->ck_history_id != 0) {
+                g_source_remove (manager->priv->ck_history_id);
+                manager->priv->ck_history_id = 0;
+        }
+
         if (manager->priv->reload_id > 0) {
                 g_source_remove (manager->priv->reload_id);
                 manager->priv->reload_id = 0;
@@ -969,10 +995,6 @@
 
         g_hash_table_destroy (manager->priv->sessions);
 
-        gnome_vfs_monitor_cancel (manager->priv->shells_monitor);
-        g_hash_table_destroy (manager->priv->shells);
-
-        gnome_vfs_monitor_cancel (manager->priv->passwd_monitor);
         g_hash_table_destroy (manager->priv->users);
 
         g_free (manager->priv->seat_id);

Modified: trunk/gui/simple-greeter/gdm-user-manager.h
==============================================================================
--- trunk/gui/simple-greeter/gdm-user-manager.h	(original)
+++ trunk/gui/simple-greeter/gdm-user-manager.h	Mon Feb  4 15:23:19 2008
@@ -52,6 +52,8 @@
                                                      GdmUser        *user);
         void          (* user_is_logged_in_changed) (GdmUserManager *user_manager,
                                                      GdmUser        *user);
+        void          (* user_login_frequency_changed) (GdmUserManager *user_manager,
+                                                        GdmUser        *user);
 } GdmUserManagerClass;
 
 typedef enum

Modified: trunk/gui/simple-greeter/gdm-user.c
==============================================================================
--- trunk/gui/simple-greeter/gdm-user.c	(original)
+++ trunk/gui/simple-greeter/gdm-user.c	Mon Feb  4 15:23:19 2008
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  *
  * Copyright (C) 2004-2005 James M. Cape <jcape ignore-your tv>.
- * Copyright (C) 2007 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2007-2008 William Jon McCann <mccann jhu edu>
  *
  * 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
@@ -51,6 +51,7 @@
         PROP_UID,
         PROP_HOME_DIR,
         PROP_SHELL,
+        PROP_LOGIN_FREQUENCY,
 };
 
 enum {
@@ -70,6 +71,7 @@
         char           *home_dir;
         char           *shell;
         GSList         *sessions;
+        gulong          login_frequency;
 };
 
 typedef struct _GdmUserClass
@@ -145,6 +147,14 @@
 }
 
 static void
+_gdm_user_set_login_frequency (GdmUser *user,
+                               gulong   login_frequency)
+{
+        user->login_frequency = login_frequency;
+        g_object_notify (G_OBJECT (user), "login-frequency");
+}
+
+static void
 gdm_user_set_property (GObject      *object,
                        guint         param_id,
                        const GValue *value,
@@ -159,7 +169,9 @@
                 user->manager = g_value_get_object (value);
                 g_assert (user->manager);
                 break;
-
+        case PROP_LOGIN_FREQUENCY:
+                _gdm_user_set_login_frequency (user, g_value_get_ulong (value));
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                 break;
@@ -195,6 +207,9 @@
         case PROP_SHELL:
                 g_value_set_string (value, user->shell);
                 break;
+        case PROP_LOGIN_FREQUENCY:
+                g_value_set_ulong (value, user->login_frequency);
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                 break;
@@ -257,6 +272,15 @@
                                                               "The shell for this user.",
                                                               NULL,
                                                               G_PARAM_READABLE));
+        g_object_class_install_property (gobject_class,
+                                         PROP_LOGIN_FREQUENCY,
+                                         g_param_spec_ulong ("login-frequency",
+                                                             "login frequency",
+                                                             "login frequency",
+                                                             0,
+                                                             G_MAXULONG,
+                                                             0,
+                                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
         signals [ICON_CHANGED] =
                 g_signal_new ("icon-changed",
@@ -283,6 +307,10 @@
         user->user_name = NULL;
         user->real_name = NULL;
         user->sessions = NULL;
+
+        if (! gnome_vfs_initialized ()) {
+                gnome_vfs_init ();
+        }
 }
 
 static void
@@ -507,6 +535,14 @@
         return user->shell;
 }
 
+gulong
+gdm_user_get_login_frequency (GdmUser *user)
+{
+        g_return_val_if_fail (GDM_IS_USER (user), 0);
+
+        return user->login_frequency;
+}
+
 gint
 gdm_user_collate (GdmUser *user1,
                   GdmUser *user2)

Modified: trunk/gui/simple-greeter/gdm-user.h
==============================================================================
--- trunk/gui/simple-greeter/gdm-user.h	(original)
+++ trunk/gui/simple-greeter/gdm-user.h	Mon Feb  4 15:23:19 2008
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  *
  * Copyright (C) 2004-2005 James M. Cape <jcape ignore-your tv>.
+ * Copyright (C) 2007-2008 William Jon McCann <mccann jhu edu>
  *
  * 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
@@ -44,6 +45,7 @@
 G_CONST_RETURN char  *gdm_user_get_home_directory (GdmUser   *user);
 G_CONST_RETURN char  *gdm_user_get_shell          (GdmUser   *user);
 guint                 gdm_user_get_num_sessions   (GdmUser   *user);
+gulong                gdm_user_get_login_frequency (GdmUser   *user);
 
 GdkPixbuf            *gdm_user_render_icon        (GdmUser   *user,
                                                    gint       icon_size);



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