]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-account-chooser.c
Merge branch 'sasl'
[empathy.git] / libempathy-gtk / empathy-account-chooser.c
index bd46efc16a0a326902caf910443658733f7d5e3d..f1c0ec6b4e87ace664373999628b4f975d95e1ef 100644 (file)
@@ -30,6 +30,7 @@
 #include <gtk/gtk.h>
 
 #include <telepathy-glib/account-manager.h>
+#include <telepathy-glib/util.h>
 
 #include <libempathy/empathy-utils.h>
 
@@ -73,10 +74,51 @@ typedef struct {
        gboolean               set;
 } SetAccountData;
 
+typedef struct {
+       EmpathyAccountChooser *chooser;
+       TpAccount             *account;
+       GtkTreeIter           *iter;
+} FilterResultCallbackData;
+
+static FilterResultCallbackData *
+filter_result_callback_data_new (EmpathyAccountChooser *chooser,
+                                TpAccount             *account,
+                                GtkTreeIter           *iter)
+{
+       FilterResultCallbackData *data;
+
+       data = g_slice_new0 (FilterResultCallbackData);
+       data->chooser = g_object_ref (chooser);
+       data->account = g_object_ref (account);
+       data->iter = gtk_tree_iter_copy (iter);
+
+       return data;
+}
+
+static void
+filter_result_callback_data_free (FilterResultCallbackData *data)
+{
+       g_object_unref (data->chooser);
+       g_object_unref (data->account);
+       gtk_tree_iter_free (data->iter);
+       g_slice_free (FilterResultCallbackData, data);
+}
+
+/* Distinguishes between store entries which are actually accounts, and special
+ * items like the "All" entry and the separator below it, so they can be sorted
+ * correctly. Higher-numbered entries will sort earlier.
+ */
+typedef enum {
+       ROW_ACCOUNT = 0,
+       ROW_SEPARATOR,
+       ROW_ALL
+} RowType;
+
 enum {
        COL_ACCOUNT_IMAGE,
        COL_ACCOUNT_TEXT,
        COL_ACCOUNT_ENABLED, /* Usually tied to connected state */
+       COL_ACCOUNT_ROW_TYPE,
        COL_ACCOUNT_POINTER,
        COL_ACCOUNT_COUNT
 };
@@ -443,6 +485,7 @@ empathy_account_chooser_set_has_all_option (EmpathyAccountChooser *chooser,
                                    COL_ACCOUNT_TEXT, NULL,
                                    COL_ACCOUNT_ENABLED, TRUE,
                                    COL_ACCOUNT_POINTER, NULL,
+                                   COL_ACCOUNT_ROW_TYPE, ROW_SEPARATOR,
                                    -1);
 
                gtk_list_store_prepend (store, &iter);
@@ -450,6 +493,7 @@ empathy_account_chooser_set_has_all_option (EmpathyAccountChooser *chooser,
                                    COL_ACCOUNT_TEXT, _("All"),
                                    COL_ACCOUNT_ENABLED, TRUE,
                                    COL_ACCOUNT_POINTER, NULL,
+                                   COL_ACCOUNT_ROW_TYPE, ROW_ALL,
                                    -1);
        } else {
                if (gtk_tree_model_get_iter_first (model, &iter)) {
@@ -492,9 +536,9 @@ account_manager_prepared_cb (GObject *source_object,
 
                account_chooser_account_add_foreach (account, chooser);
 
-               empathy_signal_connect_weak (account, "status-changed",
+               tp_g_signal_connect_object (account, "status-changed",
                                             G_CALLBACK (account_chooser_status_changed_cb),
-                                            G_OBJECT (chooser));
+                                            chooser, 0);
        }
 
        g_list_free (accounts);
@@ -509,12 +553,25 @@ account_cmp (GtkTreeModel *model,
             GtkTreeIter *b,
             gpointer user_data)
 {
+       RowType a_type, b_type;
        gboolean a_enabled, b_enabled;
        gchar *a_text, *b_text;
        gint result;
 
-       gtk_tree_model_get (model, a, COL_ACCOUNT_ENABLED, &a_enabled, -1);
-       gtk_tree_model_get (model, b, COL_ACCOUNT_ENABLED, &b_enabled, -1);
+       gtk_tree_model_get (model, a,
+               COL_ACCOUNT_ENABLED, &a_enabled,
+               COL_ACCOUNT_ROW_TYPE, &a_type,
+               -1);
+       gtk_tree_model_get (model, b,
+               COL_ACCOUNT_ENABLED, &b_enabled,
+               COL_ACCOUNT_ROW_TYPE, &b_type,
+               -1);
+
+       /* This assumes that we have at most one of each special row type. */
+       if (a_type != b_type) {
+               /* Display higher-numbered special row types first. */
+               return (b_type - a_type);
+       }
 
        /* Enabled accounts are displayed first */
        if (a_enabled != b_enabled)
@@ -557,6 +614,7 @@ account_chooser_setup (EmpathyAccountChooser *chooser)
                                    G_TYPE_STRING,    /* Image */
                                    G_TYPE_STRING,    /* Name */
                                    G_TYPE_BOOLEAN,   /* Enabled */
+                                   G_TYPE_UINT,      /* Row type */
                                    TP_TYPE_ACCOUNT);
 
        gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (store),
@@ -696,29 +754,26 @@ account_chooser_account_remove_foreach (TpAccount             *account,
 }
 
 static void
-account_chooser_update_iter (EmpathyAccountChooser *chooser,
-                            GtkTreeIter           *iter)
+account_chooser_filter_ready_cb (gboolean is_enabled,
+                                gpointer data)
 {
+       FilterResultCallbackData  *fr_data = data;
+       EmpathyAccountChooser     *chooser;
        EmpathyAccountChooserPriv *priv;
+       TpAccount                 *account;
+       GtkTreeIter               *iter;
        GtkListStore              *store;
        GtkComboBox               *combobox;
-       TpAccount                 *account;
        const gchar               *icon_name;
-       gboolean                   is_enabled = TRUE;
 
+       chooser = fr_data->chooser;
        priv = GET_PRIV (chooser);
-
+       account = fr_data->account;
+       iter = fr_data->iter;
        combobox = GTK_COMBO_BOX (chooser);
        store = GTK_LIST_STORE (gtk_combo_box_get_model (combobox));
 
-       gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
-                           COL_ACCOUNT_POINTER, &account,
-                           -1);
-
        icon_name = tp_account_get_icon_name (account);
-       if (priv->filter) {
-               is_enabled = priv->filter (account, priv->filter_data);
-       }
 
        gtk_list_store_set (store, iter,
                            COL_ACCOUNT_IMAGE, icon_name,
@@ -734,6 +789,39 @@ account_chooser_update_iter (EmpathyAccountChooser *chooser,
        }
 
        g_object_unref (account);
+       filter_result_callback_data_free (fr_data);
+}
+
+static void
+account_chooser_update_iter (EmpathyAccountChooser *chooser,
+                            GtkTreeIter           *iter)
+{
+       EmpathyAccountChooserPriv *priv;
+       GtkListStore              *store;
+       GtkComboBox               *combobox;
+       TpAccount                 *account;
+       FilterResultCallbackData  *data;
+
+       priv = GET_PRIV (chooser);
+
+       combobox = GTK_COMBO_BOX (chooser);
+       store = GTK_LIST_STORE (gtk_combo_box_get_model (combobox));
+
+       gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
+                           COL_ACCOUNT_POINTER, &account,
+                           -1);
+
+       /* Skip rows without account associated */
+       if (account == NULL)
+               return;
+
+       data = filter_result_callback_data_new (chooser, account, iter);
+
+       if (priv->filter)
+               priv->filter (account, account_chooser_filter_ready_cb,
+                             (gpointer) data, priv->filter_data);
+       else
+               account_chooser_filter_ready_cb (TRUE, (gpointer) data);
 }
 
 static void
@@ -758,21 +846,10 @@ account_chooser_separator_func (GtkTreeModel         *model,
                                GtkTreeIter          *iter,
                                EmpathyAccountChooser *chooser)
 {
-       EmpathyAccountChooserPriv *priv;
-       gchar                    *text;
-       gboolean                  is_separator;
-
-       priv = GET_PRIV (chooser);
-
-       if (!priv->has_all_option) {
-               return FALSE;
-       }
-
-       gtk_tree_model_get (model, iter, COL_ACCOUNT_TEXT, &text, -1);
-       is_separator = text == NULL;
-       g_free (text);
+       RowType row_type;
 
-       return is_separator;
+       gtk_tree_model_get (model, iter, COL_ACCOUNT_ROW_TYPE, &row_type, -1);
+       return (row_type == ROW_SEPARATOR);
 }
 
 static gboolean
@@ -786,13 +863,7 @@ account_chooser_set_account_foreach (GtkTreeModel   *model,
 
        gtk_tree_model_get (model, iter, COL_ACCOUNT_POINTER, &account, -1);
 
-       /* Special case so we can make it possible to select the All option */
-       if ((data->account == NULL) != (account == NULL)) {
-               equal = FALSE;
-       }
-       else {
-               equal = (data->account == account);
-       }
+       equal = (data->account == account);
 
        if (account) {
                g_object_unref (account);
@@ -864,19 +935,26 @@ empathy_account_chooser_set_filter (EmpathyAccountChooser           *chooser,
 /**
  * empathy_account_chooser_filter_is_connected:
  * @account: a #TpAccount
+ * @callback: an #EmpathyAccountChooserFilterResultCallback accepting the result
+ * @callback_data: data passed to the @callback
  * @user_data: user data or %NULL
  *
  * A useful #EmpathyAccountChooserFilterFunc that one could pass into
  * empathy_account_chooser_set_filter() and only show connected accounts.
  *
- * Return value: Whether @account is connected
+ * Returns (via the callback) TRUE is @account is connected
  */
-gboolean
-empathy_account_chooser_filter_is_connected (TpAccount *account,
-                                            gpointer   user_data)
+void
+empathy_account_chooser_filter_is_connected (
+       TpAccount                                 *account,
+       EmpathyAccountChooserFilterResultCallback  callback,
+       gpointer                                   callback_data,
+       gpointer                                   user_data)
 {
-       return (tp_account_get_connection_status (account, NULL)
-           == TP_CONNECTION_STATUS_CONNECTED);
+       gboolean is_connected =
+               tp_account_get_connection_status (account, NULL)
+               == TP_CONNECTION_STATUS_CONNECTED;
+       callback (is_connected, callback_data);
 }
 
 gboolean
@@ -886,3 +964,17 @@ empathy_account_chooser_is_ready (EmpathyAccountChooser *self)
 
        return priv->ready;
 }
+
+TpAccount *
+empathy_account_chooser_get_account (EmpathyAccountChooser *chooser)
+{
+       TpAccount *account;
+
+       account = empathy_account_chooser_dup_account (chooser);
+       if (account == NULL)
+               return NULL;
+
+       g_object_unref (account);
+
+       return account;
+}