]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-contact-selector.c
Don't forget to show the contact widget in some places
[empathy.git] / libempathy-gtk / empathy-contact-selector.c
index dd7da1d8d4b5f4eb80bf4a3dfad6400705bb5cb8..539629a234de8d31aa50c2d0a41f4b52dd348ea8 100644 (file)
@@ -37,13 +37,15 @@ G_DEFINE_TYPE (EmpathyContactSelector, empathy_contact_selector,
 enum
 {
   PROP_0,
-  PROP_STORE
+  PROP_CONTACT_LIST
 };
 
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyContactSelector)
 typedef struct
 {
+  EmpathyContactList *contact_list;
   EmpathyContactListStore *store;
+  GtkTreeModel *model;
   gboolean dispose_run;
 } EmpathyContactSelectorPriv;
 
@@ -51,17 +53,17 @@ static void contact_selector_manage_blank_contact (
     EmpathyContactSelector *selector);
 
 static guint
-contact_selector_get_number_online_contacts (GtkTreeStore *store)
+contact_selector_get_number_online_contacts (GtkTreeModel *model)
 {
   GtkTreeIter tmp_iter;
   gboolean is_online;
   guint number_online_contacts = 0;
   gboolean ok;
 
-  for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &tmp_iter);
-      ok; ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &tmp_iter))
+  for (ok = gtk_tree_model_get_iter_first (model, &tmp_iter);
+      ok; ok = gtk_tree_model_iter_next (model, &tmp_iter))
     {
-      gtk_tree_model_get (GTK_TREE_MODEL (store),
+      gtk_tree_model_get (model,
           &tmp_iter, EMPATHY_CONTACT_LIST_STORE_COL_IS_ONLINE,
           &is_online, -1);
       if (is_online)
@@ -72,7 +74,7 @@ contact_selector_get_number_online_contacts (GtkTreeStore *store)
 }
 
 static gboolean
-contact_selector_get_iter_for_blank_contact (GtkTreeStore *store,
+contact_selector_get_iter_for_blank_contact (GtkTreeStore *model,
                                              GtkTreeIter *blank_iter)
 {
   GtkTreeIter tmp_iter;
@@ -80,10 +82,10 @@ contact_selector_get_iter_for_blank_contact (GtkTreeStore *store,
   gboolean is_present = FALSE;
   gboolean ok;
 
-  for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &tmp_iter);
-      ok; ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &tmp_iter))
+  for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &tmp_iter);
+      ok; ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &tmp_iter))
     {
-      gtk_tree_model_get (GTK_TREE_MODEL (store),
+      gtk_tree_model_get (GTK_TREE_MODEL (model),
           &tmp_iter, EMPATHY_CONTACT_LIST_STORE_COL_CONTACT,
           &tmp_contact, -1);
       if (tmp_contact == NULL)
@@ -102,16 +104,21 @@ static void
 contact_selector_add_blank_contact (EmpathyContactSelector *selector)
 {
   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
-  GtkTreeIter blank_iter;
+  GtkTreeIter blank_iter, iter;
 
   gtk_tree_store_insert_with_values (
-      GTK_TREE_STORE (priv->store),&blank_iter, NULL, 0,
+      GTK_TREE_STORE (priv->store), &blank_iter, NULL, 0,
       EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, NULL,
       EMPATHY_CONTACT_LIST_STORE_COL_NAME, (_("Select a contact")),
       EMPATHY_CONTACT_LIST_STORE_COL_IS_ONLINE, FALSE, -1);
+
+  /* look up blank_iter in the filter model */
+  g_return_if_fail (gtk_tree_model_filter_convert_child_iter_to_iter (
+      GTK_TREE_MODEL_FILTER (priv->model), &iter, &blank_iter));
+
   g_signal_handlers_block_by_func (selector,
       contact_selector_manage_blank_contact, selector);
-  gtk_combo_box_set_active_iter (GTK_COMBO_BOX (selector), &blank_iter);
+  gtk_combo_box_set_active_iter (GTK_COMBO_BOX (selector), &iter);
   g_signal_handlers_unblock_by_func (selector,
       contact_selector_manage_blank_contact, selector);
 }
@@ -122,8 +129,8 @@ contact_selector_remove_blank_contact (EmpathyContactSelector *selector)
   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
   GtkTreeIter blank_iter;
 
-  if (contact_selector_get_iter_for_blank_contact (
-        GTK_TREE_STORE (priv->store), &blank_iter))
+  if (contact_selector_get_iter_for_blank_contact
+      (GTK_TREE_STORE (priv->store), &blank_iter))
     gtk_tree_store_remove (GTK_TREE_STORE (priv->store), &blank_iter);
 }
 
@@ -133,12 +140,7 @@ contact_selector_manage_sensitivity (EmpathyContactSelector *selector)
   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
   guint number_online_contacts;
 
-  /* FIXME - make this work when offline contacts are shown.
-   * The following value needs to be the number of entries shown
-   * excluding the blank entry (if present).
-   */
-  number_online_contacts = contact_selector_get_number_online_contacts (
-      GTK_TREE_STORE (priv->store));
+  number_online_contacts = contact_selector_get_number_online_contacts (priv->model);
 
   if (number_online_contacts != 0)
     gtk_widget_set_sensitive (GTK_WIDGET (selector), TRUE);
@@ -189,6 +191,8 @@ contact_selector_constructor (GType type,
   contact_selector = EMPATHY_CONTACT_SELECTOR (object);
   cell_layout = GTK_CELL_LAYOUT (object);
 
+  priv->store = empathy_contact_list_store_new (priv->contact_list);
+
   g_object_set (priv->store, "is-compact", TRUE, "show-avatars", FALSE,
       "show-offline", FALSE, "show-groups", FALSE,
       "sort-criterium", EMPATHY_CONTACT_LIST_STORE_SORT_NAME, NULL);
@@ -203,8 +207,9 @@ contact_selector_constructor (GType type,
       G_CALLBACK (contact_selector_manage_blank_contact),
       contact_selector);
 
-  gtk_combo_box_set_model (GTK_COMBO_BOX (contact_selector),
-      GTK_TREE_MODEL (priv->store));
+  priv->model = gtk_tree_model_filter_new (GTK_TREE_MODEL (priv->store), NULL);
+
+  gtk_combo_box_set_model (GTK_COMBO_BOX (contact_selector), priv->model);
   gtk_widget_set_sensitive (GTK_WIDGET (contact_selector), FALSE);
 
   renderer = gtk_cell_renderer_pixbuf_new ();
@@ -245,8 +250,8 @@ contact_selector_set_property (GObject *object,
 
   switch (prop_id)
     {
-      case PROP_STORE:
-        priv->store = g_value_dup_object (value);
+      case PROP_CONTACT_LIST:
+        priv->contact_list = g_value_dup_object (value);
         break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -264,8 +269,8 @@ contact_selector_get_property (GObject *object,
 
   switch (prop_id)
     {
-      case PROP_STORE:
-        g_value_set_object (value, priv->store);
+      case PROP_CONTACT_LIST:
+        g_value_set_object (value, priv->contact_list);
         break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -284,6 +289,18 @@ contact_selector_dispose (GObject *object)
 
   priv->dispose_run = TRUE;
 
+  if (priv->contact_list)
+    {
+      g_object_unref (priv->contact_list);
+      priv->contact_list = NULL;
+    }
+
+  if (priv->model)
+    {
+      g_object_unref (priv->model);
+      priv->model = NULL;
+    }
+
   if (priv->store)
     {
       g_object_unref (priv->store);
@@ -303,24 +320,25 @@ empathy_contact_selector_class_init (EmpathyContactSelectorClass *klass)
   object_class->get_property = contact_selector_get_property;
   g_type_class_add_private (klass, sizeof (EmpathyContactSelectorPriv));
 
-  g_object_class_install_property (object_class, PROP_STORE,
-      g_param_spec_object ("store", "store", "store",
-      EMPATHY_TYPE_CONTACT_LIST_STORE, G_PARAM_CONSTRUCT_ONLY |
+  g_object_class_install_property (object_class, PROP_CONTACT_LIST,
+      g_param_spec_object ("contact-list", "contact list", "contact list",
+      EMPATHY_TYPE_CONTACT_LIST, G_PARAM_CONSTRUCT_ONLY |
       G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
 }
 
 /* public methods */
 
 GtkWidget *
-empathy_contact_selector_new (EmpathyContactListStore *store)
+empathy_contact_selector_new (EmpathyContactList *contact_list)
 {
-  g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST_STORE (store), NULL);
+  g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (contact_list), NULL);
 
-  return GTK_WIDGET (g_object_new (EMPATHY_TYPE_CONTACT_SELECTOR, "store", store, NULL));
+  return GTK_WIDGET (g_object_new (EMPATHY_TYPE_CONTACT_SELECTOR,
+      "contact-list", contact_list, NULL));
 }
 
 EmpathyContact *
-empathy_contact_selector_get_selected (EmpathyContactSelector *selector)
+empathy_contact_selector_dup_selected (EmpathyContactSelector *selector)
 {
   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
   EmpathyContact *contact = NULL;
@@ -331,8 +349,61 @@ empathy_contact_selector_get_selected (EmpathyContactSelector *selector)
   if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (selector), &iter))
     return NULL;
 
-  gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+  gtk_tree_model_get (priv->model, &iter,
       EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact, -1);
 
   return contact;
 }
+
+typedef struct
+{
+  EmpathyContactSelectorFilterFunc func;
+  gpointer user_data;
+} FilterData;
+
+static void
+filter_data_free (gpointer data)
+{
+  g_slice_free (FilterData, data);
+}
+
+static gboolean
+contact_selector_filter_visible_func (GtkTreeModel *model,
+                                     GtkTreeIter *iter,
+                                     gpointer user_data)
+{
+  EmpathyContact *contact;
+  gboolean visible = TRUE;
+  FilterData *data = (FilterData *) user_data;
+
+  gtk_tree_model_get (model, iter,
+      EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact,
+      -1);
+
+  if (contact != NULL)
+    {
+      visible = data->func(contact, data->user_data);
+
+      g_object_unref (contact);
+    }
+
+  return visible;
+}
+
+void
+empathy_contact_selector_set_visible (EmpathyContactSelector *selector,
+                                      EmpathyContactSelectorFilterFunc func,
+                                      gpointer user_data)
+{
+  EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
+  FilterData *data;
+
+  data = g_slice_new0 (FilterData);
+  data->func = func;
+  data->user_data = user_data;
+
+  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->model),
+      contact_selector_filter_visible_func, data, filter_data_free);
+
+  gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->model));
+}