]> git.0d.be Git - empathy.git/commitdiff
Merge branch 'people-nearby-fake-group-613558'
authorDanielle Madeley <danielle.madeley@collabora.co.uk>
Tue, 30 Mar 2010 10:37:25 +0000 (21:37 +1100)
committerDanielle Madeley <danielle.madeley@collabora.co.uk>
Tue, 30 Mar 2010 10:37:25 +0000 (21:37 +1100)
1  2 
libempathy-gtk/empathy-contact-list-store.c
libempathy-gtk/empathy-contact-list-store.h
libempathy-gtk/empathy-contact-list-view.c
libempathy/empathy-tp-contact-list.c

index 7ff41d69af38eb5368d99388ae9171cea79dc94c,152dd61b77bc5d7bb2f1c55075709c5cc31dda2d..6b35b082440ab1835f2f35578828a1eb4bec67b7
@@@ -833,9 -833,8 +833,9 @@@ contact_list_store_setup (EmpathyContac
                GDK_TYPE_PIXBUF,      /* Avatar pixbuf */
                G_TYPE_BOOLEAN,       /* Avatar pixbuf visible */
                G_TYPE_STRING,        /* Name */
 +              G_TYPE_UINT,          /* Presence type */
                G_TYPE_STRING,        /* Status string */
 -              G_TYPE_BOOLEAN,       /* Show status */
 +              G_TYPE_BOOLEAN,       /* Compact view */
                EMPATHY_TYPE_CONTACT, /* Contact type */
                G_TYPE_BOOLEAN,       /* Is group */
                G_TYPE_BOOLEAN,       /* Is active */
@@@ -1038,6 -1037,7 +1038,7 @@@ contact_list_store_add_contact (Empathy
        GList                      *groups = NULL, *l;
        TpConnection               *connection;
        EmpathyContactListFlags     flags = 0;
+       char                       *protocol_name;
  
        priv = GET_PRIV (store);
  
                flags = empathy_contact_manager_get_flags_for_connection (
                        EMPATHY_CONTACT_MANAGER (priv->list), connection);
        }
+       tp_connection_parse_object_path (connection, &protocol_name, NULL);
        if (!groups) {
  #if HAVE_FAVOURITE_CONTACTS
                GtkTreeIter iter_group;
  
-               contact_list_store_get_group (store, EMPATHY_CONTACT_LIST_STORE_UNGROUPED,
-                       &iter_group, NULL, NULL, TRUE);
+               if (!tp_strdiff (protocol_name, "local-xmpp")) {
+                       /* these are People Nearby */
+                       contact_list_store_get_group (store,
+                               EMPATHY_CONTACT_LIST_STORE_PEOPLE_NEARBY,
+                               &iter_group, NULL, NULL, TRUE);
+               } else {
+                       contact_list_store_get_group (store,
+                               EMPATHY_CONTACT_LIST_STORE_UNGROUPED,
+                               &iter_group, NULL, NULL, TRUE);
+               }
  
                gtk_tree_store_insert_after (GTK_TREE_STORE (store), &iter,
                                             &iter_group, NULL);
                add_contact_to_store (GTK_TREE_STORE (store), &iter, contact, flags);
        }
  
+       g_free (protocol_name);
        /* Else add to each group. */
        for (l = groups; l; l = l->next) {
                GtkTreeIter iter_group;
@@@ -1278,11 -1291,8 +1292,11 @@@ contact_list_store_contact_update (Empa
                                    EMPATHY_CONTACT_LIST_STORE_COL_PIXBUF_AVATAR, pixbuf_avatar,
                                    EMPATHY_CONTACT_LIST_STORE_COL_PIXBUF_AVATAR_VISIBLE, show_avatar,
                                    EMPATHY_CONTACT_LIST_STORE_COL_NAME, empathy_contact_get_name (contact),
 -                                  EMPATHY_CONTACT_LIST_STORE_COL_STATUS, empathy_contact_get_status (contact),
 -                                  EMPATHY_CONTACT_LIST_STORE_COL_STATUS_VISIBLE, !priv->is_compact,
 +                                  EMPATHY_CONTACT_LIST_STORE_COL_PRESENCE_TYPE,
 +                                    empathy_contact_get_presence (contact),
 +                                  EMPATHY_CONTACT_LIST_STORE_COL_STATUS,
 +                                    empathy_contact_get_presence_message (contact),
 +                                  EMPATHY_CONTACT_LIST_STORE_COL_COMPACT, priv->is_compact,
                                    EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, FALSE,
                                    EMPATHY_CONTACT_LIST_STORE_COL_IS_ONLINE, now_online,
                                    EMPATHY_CONTACT_LIST_STORE_COL_IS_SEPARATOR, FALSE,
@@@ -1530,6 -1540,20 +1544,20 @@@ contact_list_store_get_group (EmpathyCo
        }
  }
  
+ static gint
+ get_position (const char **strv,
+             const char *str)
+ {
+       int i;
+       for (i = 0; strv[i] != NULL; i++) {
+               if (!tp_strdiff (strv[i], str))
+                       return i;
+       }
+       return -1;
+ }
  static gint
  compare_separator_and_groups (gboolean is_separator_a,
                              gboolean is_separator_b,
                              gboolean fake_group_a,
                              gboolean fake_group_b)
  {
+       /* these two lists are the sorted list of fake groups to include at the
+        * top and bottom of the roster */
+       const char *top_groups[] = {
+               EMPATHY_CONTACT_LIST_STORE_FAVORITE,
+               NULL
+       };
+       const char *bottom_groups[] = {
+               EMPATHY_CONTACT_LIST_STORE_UNGROUPED,
+               NULL
+       };
        if (is_separator_a || is_separator_b) {
                /* We have at least one separator */
                if (is_separator_a) {
        } else if (contact_a && !contact_b) {
                return -1;
        } else if (!contact_a && !contact_b) {
-               /* Two groups. The 'Ungrouped' fake group is display at the bottom of the
-                * contact list and the 'Favorites' at the top. */
-               if (fake_group_a && !tp_strdiff (name_a, EMPATHY_CONTACT_LIST_STORE_UNGROUPED))
-                       return 1;
-               else if (fake_group_b && !tp_strdiff (name_b, EMPATHY_CONTACT_LIST_STORE_UNGROUPED))
-                       return -1;
-               else if (fake_group_a && !tp_strdiff (name_a, EMPATHY_CONTACT_LIST_STORE_FAVORITE))
+               gboolean a_in_top, b_in_top, a_in_bottom, b_in_bottom;
+               a_in_top = fake_group_a &&
+                       tp_strv_contains (top_groups, name_a);
+               b_in_top = fake_group_b &&
+                       tp_strv_contains (top_groups, name_b);
+               a_in_bottom = fake_group_b &&
+                       tp_strv_contains (bottom_groups, name_a);
+               b_in_bottom = fake_group_b &&
+                       tp_strv_contains (bottom_groups, name_b);
+               if (a_in_top && b_in_top) {
+                       /* compare positions */
+                       return CLAMP (get_position (top_groups, name_a) -
+                                     get_position (top_groups, name_b),
+                                     -1, 1);
+               } else if (a_in_bottom && b_in_bottom) {
+                       /* compare positions */
+                       return CLAMP (get_position (bottom_groups, name_a) -
+                                     get_position (bottom_groups, name_b),
+                                     -1, 1);
+               } else if (a_in_top || b_in_bottom) {
                        return -1;
-               else if (fake_group_b && !tp_strdiff (name_b, EMPATHY_CONTACT_LIST_STORE_FAVORITE))
+               } else if (b_in_top || a_in_bottom) {
                        return 1;
-               else
+               } else {
                        return g_utf8_collate (name_a, name_b);
+               }
        }
  
        /* Two contacts, ordering depends of the sorting policy */
@@@ -1755,7 -1807,7 +1811,7 @@@ contact_list_store_update_list_mode_for
        gtk_tree_store_set (GTK_TREE_STORE (store), iter,
                            EMPATHY_CONTACT_LIST_STORE_COL_ICON_STATUS, pixbuf_status,
                            EMPATHY_CONTACT_LIST_STORE_COL_PIXBUF_AVATAR_VISIBLE, show_avatar,
 -                          EMPATHY_CONTACT_LIST_STORE_COL_STATUS_VISIBLE, !priv->is_compact,
 +                          EMPATHY_CONTACT_LIST_STORE_COL_COMPACT, priv->is_compact,
                            -1);
  
        return FALSE;
index 26a2cc2b292e0cf5d2144bf9e31c7f2b5b67a766,7fa400e3dbc62eb0682788c7115a3adae798b22e..b8008cadb95fa72bf00320ef53c65cffef2f5583
@@@ -53,9 -53,8 +53,9 @@@ typedef enum 
        EMPATHY_CONTACT_LIST_STORE_COL_PIXBUF_AVATAR,
        EMPATHY_CONTACT_LIST_STORE_COL_PIXBUF_AVATAR_VISIBLE,
        EMPATHY_CONTACT_LIST_STORE_COL_NAME,
 +      EMPATHY_CONTACT_LIST_STORE_COL_PRESENCE_TYPE,
        EMPATHY_CONTACT_LIST_STORE_COL_STATUS,
 -      EMPATHY_CONTACT_LIST_STORE_COL_STATUS_VISIBLE,
 +      EMPATHY_CONTACT_LIST_STORE_COL_COMPACT,
        EMPATHY_CONTACT_LIST_STORE_COL_CONTACT,
        EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP,
        EMPATHY_CONTACT_LIST_STORE_COL_IS_ACTIVE,
@@@ -70,6 -69,7 +70,7 @@@
  
  #define EMPATHY_CONTACT_LIST_STORE_UNGROUPED _("Ungrouped")
  #define EMPATHY_CONTACT_LIST_STORE_FAVORITE  _("Favorite People")
+ #define EMPATHY_CONTACT_LIST_STORE_PEOPLE_NEARBY _("People Nearby")
  
  struct _EmpathyContactListStore {
        GtkTreeStore parent;
index 9d85ecb8733cdd5e41bcfc35c727882c37d552af,5aab817d759158c3e0cde8e47bcada022918a639..05823435a04727f9b9d42f501b5477156e38a733
@@@ -942,11 -942,14 +942,14 @@@ contact_list_view_group_icon_cell_data_
        if (!is_group)
                goto out;
  
-       if (tp_strdiff (name, EMPATHY_CONTACT_LIST_STORE_FAVORITE))
-               goto out;
-       pixbuf = empathy_pixbuf_from_icon_name ("emblem-favorite",
-               GTK_ICON_SIZE_MENU);
+       if (!tp_strdiff (name, EMPATHY_CONTACT_LIST_STORE_FAVORITE)) {
+               pixbuf = empathy_pixbuf_from_icon_name ("emblem-favorite",
+                       GTK_ICON_SIZE_MENU);
+       }
+       else if (!tp_strdiff (name, EMPATHY_CONTACT_LIST_STORE_PEOPLE_NEARBY)) {
+               pixbuf = empathy_pixbuf_from_icon_name ("im-local-xmpp",
+                       GTK_ICON_SIZE_MENU);
+       }
  
  out:
        g_object_set (cell,
@@@ -1027,12 -1030,22 +1030,12 @@@ contact_list_view_text_cell_data_func (
  {
        gboolean is_group;
        gboolean is_active;
 -      gboolean show_status;
 -      gchar *name;
  
        gtk_tree_model_get (model, iter,
                            EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, &is_group,
                            EMPATHY_CONTACT_LIST_STORE_COL_IS_ACTIVE, &is_active,
 -                          EMPATHY_CONTACT_LIST_STORE_COL_STATUS_VISIBLE, &show_status,
 -                          EMPATHY_CONTACT_LIST_STORE_COL_NAME, &name,
                            -1);
  
 -      g_object_set (cell,
 -                    "show-status", show_status,
 -                    "text", name,
 -                    NULL);
 -      g_free (name);
 -
        contact_list_view_cell_set_background (view, cell, is_group, is_active);
  }
  
@@@ -1213,16 -1226,10 +1216,16 @@@ contact_list_view_setup (EmpathyContact
  
        gtk_tree_view_column_add_attribute (col, cell,
                                            "name", EMPATHY_CONTACT_LIST_STORE_COL_NAME);
 +      gtk_tree_view_column_add_attribute (col, cell,
 +                                          "text", EMPATHY_CONTACT_LIST_STORE_COL_NAME);
 +      gtk_tree_view_column_add_attribute (col, cell,
 +                                          "presence-type", EMPATHY_CONTACT_LIST_STORE_COL_PRESENCE_TYPE);
        gtk_tree_view_column_add_attribute (col, cell,
                                            "status", EMPATHY_CONTACT_LIST_STORE_COL_STATUS);
        gtk_tree_view_column_add_attribute (col, cell,
                                            "is_group", EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP);
 +      gtk_tree_view_column_add_attribute (col, cell,
 +                                          "compact", EMPATHY_CONTACT_LIST_STORE_COL_COMPACT);
  
        /* Audio Call Icon */
        cell = empathy_cell_renderer_activatable_new ();
index 9288baa4c2c3773f32c09112e82b084cc67f3334,49168cdb1e670e3ca20a06d50aa6d42ee75c52c3..95ec3bea2109631ee34d9ef2d22b599996792b68
@@@ -43,7 -43,6 +43,6 @@@
  typedef struct {
        EmpathyTpContactFactory *factory;
        TpConnection   *connection;
-       const gchar    *protocol_group;
  
        TpChannel      *publish;
        TpChannel      *subscribe;
@@@ -54,8 -53,6 +53,8 @@@
        GHashTable     *add_to_group; /* group name -> GArray of handles */
  
        EmpathyContactListFlags flags;
 +
 +      TpProxySignalConnection *new_channels_sig;
  } EmpathyTpContactListPriv;
  
  typedef enum {
@@@ -699,113 -696,45 +698,113 @@@ tp_contact_list_finalize (GObject *obje
        G_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object);
  }
  
 +static gboolean
 +received_all_list_channels (EmpathyTpContactList *self)
 +{
 +      EmpathyTpContactListPriv *priv = GET_PRIV (self);
 +
 +      return (priv->stored != NULL && priv->publish != NULL &&
 +              priv->subscribe != NULL);
 +}
 +
  static void
 -list_ensure_channel_cb (TpConnection *conn,
 -                      gboolean yours,
 -                      const gchar *path,
 -                      GHashTable *properties,
 -                      const GError *error,
 -                      gpointer user_data,
 -                      GObject *weak_object)
 +got_list_channel (EmpathyTpContactList *list,
 +                TpChannel *channel)
  {
 -      EmpathyTpContactList *list = user_data;
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
        const gchar *id;
 -      TpChannel *channel;
 -
 -      if (error != NULL) {
 -              DEBUG ("failed: %s\n", error->message);
 -              return;
 -      }
  
        /* We requested that channel by providing TargetID property, so it's
         * guaranteed that tp_channel_get_identifier will return it. */
 -      channel = tp_channel_new_from_properties (conn, path, properties, NULL);
        id = tp_channel_get_identifier (channel);
  
        /* TpChannel emits initial set of members just before being ready */
        if (!tp_strdiff (id, "stored")) {
 -              priv->stored = channel;
 +              if (priv->stored != NULL)
 +                      return;
 +              priv->stored = g_object_ref (channel);
        } else if (!tp_strdiff (id, "publish")) {
 -              priv->publish = channel;
 +              if (priv->publish != NULL)
 +                      return;
 +              priv->publish = g_object_ref (channel);
                g_signal_connect (priv->publish, "group-members-changed",
                                  G_CALLBACK (tp_contact_list_publish_group_members_changed_cb),
                                  list);
        } else if (!tp_strdiff (id, "subscribe")) {
 -              priv->subscribe = channel;
 +              if (priv->subscribe != NULL)
 +                      return;
 +              priv->subscribe = g_object_ref (channel);
                g_signal_connect (priv->subscribe, "group-members-changed",
                                  G_CALLBACK (tp_contact_list_subscribe_group_members_changed_cb),
                                  list);
 -      } else {
 -              g_warn_if_reached ();
 +      }
 +
 +      if (received_all_list_channels (list) && priv->new_channels_sig != NULL) {
 +              /* We don't need to watch NewChannels anymore */
 +              tp_proxy_signal_connection_disconnect (priv->new_channels_sig);
 +              priv->new_channels_sig = NULL;
 +      }
 +}
 +
 +static void
 +list_ensure_channel_cb (TpConnection *conn,
 +                      gboolean yours,
 +                      const gchar *path,
 +                      GHashTable *properties,
 +                      const GError *error,
 +                      gpointer user_data,
 +                      GObject *weak_object)
 +{
 +      EmpathyTpContactList *list = user_data;
 +      TpChannel *channel;
 +
 +      if (error != NULL) {
 +              DEBUG ("failed: %s\n", error->message);
 +              return;
 +      }
 +
 +      channel = tp_channel_new_from_properties (conn, path, properties, NULL);
 +      got_list_channel (list, channel);
 +      g_object_unref (channel);
 +}
 +
 +static void
 +new_channels_cb (TpConnection *conn,
 +               const GPtrArray *channels,
 +               gpointer user_data,
 +               GObject *weak_object)
 +{
 +      EmpathyTpContactList *list = EMPATHY_TP_CONTACT_LIST (weak_object);
 +      guint i;
 +
 +      for (i = 0; i < channels->len ; i++) {
 +              GValueArray *arr = g_ptr_array_index (channels, i);
 +              const gchar *path;
 +              GHashTable *properties;
 +              const gchar *id;
 +              TpChannel *channel;
 +
 +              path = g_value_get_boxed (g_value_array_get_nth (arr, 0));
 +              properties = g_value_get_boxed (g_value_array_get_nth (arr, 1));
 +
 +              if (tp_strdiff (tp_asv_get_string (properties,
 +                              TP_IFACE_CHANNEL ".ChannelType"),
 +                  TP_IFACE_CHANNEL_TYPE_CONTACT_LIST))
 +                      return;
 +
 +              if (tp_asv_get_uint32 (properties,
 +                                     TP_IFACE_CHANNEL ".TargetHandleType", NULL)
 +                  != TP_HANDLE_TYPE_LIST)
 +                      return;
 +
 +              id = tp_asv_get_string (properties,
 +                                      TP_IFACE_CHANNEL ".TargetID");
 +              if (id == NULL)
 +                      return;
 +
 +              channel = tp_channel_new_from_properties (conn, path,
 +                                                        properties, NULL);
 +              got_list_channel (list, channel);
                g_object_unref (channel);
        }
  }
@@@ -829,13 -758,6 +828,13 @@@ conn_ready_cb (TpConnection *connection
                TP_IFACE_CHANNEL ".TargetHandleType", G_TYPE_UINT, TP_HANDLE_TYPE_LIST,
                NULL);
  
 +      /* Watch the NewChannels signal so if ensuring list channels fails (for
 +       * example because the server is slow and the D-Bus call timeouts before CM
 +       * fetches the roster), we have a chance to get them later. */
 +      priv->new_channels_sig =
 +        tp_cli_connection_interface_requests_connect_to_new_channels (
 +              priv->connection, new_channels_cb, NULL, NULL, G_OBJECT (list), NULL);
 +
        /* Request the 'stored' list. */
        tp_asv_set_static_string (request, TP_IFACE_CHANNEL ".TargetID", "stored");
        tp_cli_connection_interface_requests_call_ensure_channel (priv->connection,
@@@ -860,7 -782,6 +859,6 @@@ static voi
  tp_contact_list_constructed (GObject *list)
  {
        EmpathyTpContactListPriv *priv = GET_PRIV (list);
-       gchar                    *protocol_name = NULL;
  
        priv->factory = empathy_tp_contact_factory_dup_singleton (priv->connection);
  
                                                  tp_contact_list_new_channel_cb,
                                                  NULL, NULL,
                                                  list, NULL);
-       /* Check for protocols that does not support contact groups. We can
-        * put all contacts into a special group in that case.
-        * FIXME: Default group should be an information in the profile */
-       tp_connection_parse_object_path (priv->connection, &protocol_name, NULL);
-       if (!tp_strdiff (protocol_name, "local-xmpp")) {
-               priv->protocol_group = _("People nearby");
-       }
-       g_free (protocol_name);
  }
  
  static void
@@@ -1112,10 -1024,6 +1101,6 @@@ tp_contact_list_get_all_groups (Empathy
                l->data = g_strdup (l->data);
        }
  
-       if (priv->protocol_group) {
-               ret = g_list_prepend (ret, g_strdup (priv->protocol_group));
-       }
        return ret;
  }
  
@@@ -1141,10 -1049,6 +1126,6 @@@ tp_contact_list_get_groups (EmpathyCont
                }
        }
  
-       if (priv->protocol_group) {
-               ret = g_list_prepend (ret, g_strdup (priv->protocol_group));
-       }
        return ret;
  }