aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-11-08 21:06:49 +0800
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-11-24 19:28:44 +0800
commitcbeb879c831699105fb6943e55caa8bcf72f8eaf (patch)
treeda480b3deaf33dca0da2acbe0ec9de175c7d287d
parentef0d55ead126f53aa4544877d2df5ab712f00f28 (diff)
downloadgsoc2013-empathy-cbeb879c831699105fb6943e55caa8bcf72f8eaf.tar
gsoc2013-empathy-cbeb879c831699105fb6943e55caa8bcf72f8eaf.tar.gz
gsoc2013-empathy-cbeb879c831699105fb6943e55caa8bcf72f8eaf.tar.bz2
gsoc2013-empathy-cbeb879c831699105fb6943e55caa8bcf72f8eaf.tar.lz
gsoc2013-empathy-cbeb879c831699105fb6943e55caa8bcf72f8eaf.tar.xz
gsoc2013-empathy-cbeb879c831699105fb6943e55caa8bcf72f8eaf.tar.zst
gsoc2013-empathy-cbeb879c831699105fb6943e55caa8bcf72f8eaf.zip
add EMPATHY_INDIVIDUAL_FEATURE_ADD_CONTACT
https://bugzilla.gnome.org/show_bug.cgi?id=663387
-rw-r--r--libempathy-gtk/empathy-individual-menu.c140
-rw-r--r--libempathy-gtk/empathy-individual-menu.h10
-rw-r--r--libempathy-gtk/empathy-individual-view.c3
-rw-r--r--libempathy/empathy-client-factory.c21
-rw-r--r--src/empathy-main-window.c2
5 files changed, 171 insertions, 5 deletions
diff --git a/libempathy-gtk/empathy-individual-menu.c b/libempathy-gtk/empathy-individual-menu.c
index 27b2c67c2..607455f9b 100644
--- a/libempathy-gtk/empathy-individual-menu.c
+++ b/libempathy-gtk/empathy-individual-menu.c
@@ -49,6 +49,7 @@
#include "empathy-share-my-desktop.h"
#include "empathy-linking-dialog.h"
#include "empathy-call-utils.h"
+#include "empathy-individual-store-channel.h"
#define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
#include <libempathy/empathy-debug.h>
@@ -58,11 +59,13 @@
typedef struct {
FolksIndividual *individual; /* owned */
EmpathyIndividualFeatureFlags features;
+ EmpathyIndividualStore *store;
} EmpathyIndividualMenuPriv;
enum {
PROP_INDIVIDUAL = 1,
PROP_FEATURES,
+ PROP_STORE,
};
enum {
@@ -454,6 +457,17 @@ constructed (GObject *object)
individual = priv->individual;
features = priv->features;
+ /* Add contact */
+ if (features & EMPATHY_INDIVIDUAL_FEATURE_ADD_CONTACT)
+ {
+ item = empathy_individual_add_menu_item_new (self, individual);
+ if (item != NULL)
+ {
+ gtk_menu_shell_append (GTK_MENU_SHELL (shell), item);
+ gtk_widget_show (item);
+ }
+ }
+
/* Chat */
if (features & EMPATHY_INDIVIDUAL_FEATURE_CHAT)
{
@@ -586,6 +600,9 @@ get_property (GObject *object,
case PROP_FEATURES:
g_value_set_flags (value, priv->features);
break;
+ case PROP_STORE:
+ g_value_set_object (value, priv->store);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -610,6 +627,9 @@ set_property (GObject *object,
case PROP_FEATURES:
priv->features = g_value_get_flags (value);
break;
+ case PROP_STORE:
+ priv->store = g_value_dup_object (value); /* read only */
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -622,6 +642,7 @@ dispose (GObject *object)
EmpathyIndividualMenuPriv *priv = GET_PRIV (object);
tp_clear_object (&priv->individual);
+ tp_clear_object (&priv->store);
G_OBJECT_CLASS (empathy_individual_menu_parent_class)->dispose (object);
}
@@ -661,6 +682,13 @@ empathy_individual_menu_class_init (EmpathyIndividualMenuClass *klass)
EMPATHY_INDIVIDUAL_FEATURE_NONE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_STORE,
+ g_param_spec_object ("store",
+ "Store",
+ "The EmpathyIndividualStore to use to get contact owner",
+ EMPATHY_TYPE_INDIVIDUAL_STORE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
signals[SIGNAL_LINK_CONTACTS_ACTIVATED] =
g_signal_new ("link-contacts-activated", G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
@@ -672,14 +700,17 @@ empathy_individual_menu_class_init (EmpathyIndividualMenuClass *klass)
GtkWidget *
empathy_individual_menu_new (FolksIndividual *individual,
- EmpathyIndividualFeatureFlags features)
+ EmpathyIndividualFeatureFlags features,
+ EmpathyIndividualStore *store)
{
g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+ g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_STORE (store), NULL);
g_return_val_if_fail (features != EMPATHY_INDIVIDUAL_FEATURE_NONE, NULL);
return g_object_new (EMPATHY_TYPE_INDIVIDUAL_MENU,
"individual", individual,
"features", features,
+ "store", store,
NULL);
}
@@ -1427,3 +1458,110 @@ empathy_individual_invite_menu_item_new (FolksIndividual *individual,
return item;
}
+
+static void
+add_menu_item_activated (GtkMenuItem *item,
+ TpContact *tp_contact)
+{
+ GtkWidget *toplevel;
+ EmpathyContact *contact;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item));
+ if (!gtk_widget_is_toplevel (toplevel) || !GTK_IS_WINDOW (toplevel))
+ toplevel = NULL;
+
+ contact = empathy_contact_dup_from_tp_contact (tp_contact);
+
+ empathy_new_contact_dialog_show_with_contact (GTK_WINDOW (toplevel),
+ contact);
+
+ g_object_unref (contact);
+}
+
+GtkWidget *
+empathy_individual_add_menu_item_new (EmpathyIndividualMenu *self,
+ FolksIndividual *individual)
+{
+ EmpathyIndividualMenuPriv *priv = GET_PRIV (self);
+ GtkWidget *item, *image;
+ GeeSet *personas;
+ GeeIterator *iter;
+ TpContact *to_add = NULL;
+
+ /* find the first of this Individual's personas which are not in our contact
+ * list. */
+ personas = folks_individual_get_personas (individual);
+ iter = gee_iterable_iterator (GEE_ITERABLE (personas));
+ while (gee_iterator_next (iter))
+ {
+ TpfPersona *persona = gee_iterator_get (iter);
+ TpContact *contact;
+ TpConnection *conn;
+
+ if (!TPF_IS_PERSONA (persona))
+ goto next;
+
+ contact = tpf_persona_get_contact (persona);
+ if (contact == NULL)
+ goto next;
+
+ /* be sure to use a not channel specific contact.
+ * TODO: Ideally tp-glib should do this for us (fdo #42702)*/
+ if (EMPATHY_IS_INDIVIDUAL_STORE_CHANNEL (priv->store))
+ {
+ TpChannel *channel;
+ TpChannelGroupFlags flags;
+
+ channel = empathy_individual_store_channel_get_channel (
+ EMPATHY_INDIVIDUAL_STORE_CHANNEL (priv->store));
+
+ flags = tp_channel_group_get_flags (channel);
+ if ((flags & TP_CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES) != 0)
+ {
+ /* Channel uses channel specific handles (thanks XMPP...) */
+ contact = tp_channel_group_get_contact_owner (channel, contact);
+
+ /* If we don't know the owner, we can't add the contact */
+ if (contact == NULL)
+ goto next;
+ }
+ }
+
+ conn = tp_contact_get_connection (contact);
+ if (conn == NULL)
+ goto next;
+
+ /* No point to try adding a contact if the CM doesn't support it */
+ if (!tp_connection_get_can_change_contact_list (conn))
+ goto next;
+
+ /* Can't add ourself */
+ if (tp_connection_get_self_contact (conn) == contact)
+ goto next;
+
+ if (tp_contact_get_subscribe_state (contact) == TP_SUBSCRIPTION_STATE_YES)
+ goto next;
+
+ g_object_unref (persona);
+ to_add = contact;
+ break;
+
+next:
+ g_object_unref (persona);
+ }
+
+ g_object_unref (iter);
+
+ if (to_add == NULL)
+ return NULL;
+
+ item = gtk_image_menu_item_new_with_mnemonic (_("_Add Contact…"));
+ image = gtk_image_new_from_icon_name (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+
+ g_signal_connect_data (item, "activate",
+ G_CALLBACK (add_menu_item_activated),
+ g_object_ref (to_add), (GClosureNotify) g_object_unref, 0);
+
+ return item;
+}
diff --git a/libempathy-gtk/empathy-individual-menu.h b/libempathy-gtk/empathy-individual-menu.h
index 2a51605d6..31acc156e 100644
--- a/libempathy-gtk/empathy-individual-menu.h
+++ b/libempathy-gtk/empathy-individual-menu.h
@@ -25,6 +25,8 @@
#include <gtk/gtk.h>
+#include "empathy-individual-store.h"
+
G_BEGIN_DECLS
typedef enum {
@@ -38,7 +40,8 @@ typedef enum {
EMPATHY_INDIVIDUAL_FEATURE_LINK = 1 << 6,
EMPATHY_INDIVIDUAL_FEATURE_SMS = 1 << 7,
EMPATHY_INDIVIDUAL_FEATURE_CALL_PHONE = 1 << 8,
- EMPATHY_INDIVIDUAL_FEATURE_ALL = (1 << 9) - 1,
+ EMPATHY_INDIVIDUAL_FEATURE_ADD_CONTACT = 1 << 9,
+ EMPATHY_INDIVIDUAL_FEATURE_ALL = (1 << 10) - 1,
} EmpathyIndividualFeatureFlags;
#define EMPATHY_TYPE_INDIVIDUAL_MENU (empathy_individual_menu_get_type ())
@@ -68,7 +71,8 @@ typedef struct {
GType empathy_individual_menu_get_type (void) G_GNUC_CONST;
GtkWidget * empathy_individual_menu_new (FolksIndividual *individual,
- EmpathyIndividualFeatureFlags features);
+ EmpathyIndividualFeatureFlags features,
+ EmpathyIndividualStore *store);
GtkWidget * empathy_individual_chat_menu_item_new (FolksIndividual *individual,
EmpathyContact *contact);
GtkWidget * empathy_individual_sms_menu_item_new (FolksIndividual *individual,
@@ -95,6 +99,8 @@ GtkWidget * empathy_individual_share_my_desktop_menu_item_new (
EmpathyContact *contact);
GtkWidget * empathy_individual_favourite_menu_item_new (
FolksIndividual *individual);
+GtkWidget * empathy_individual_add_menu_item_new (EmpathyIndividualMenu *self,
+ FolksIndividual *individual);
G_END_DECLS
diff --git a/libempathy-gtk/empathy-individual-view.c b/libempathy-gtk/empathy-individual-view.c
index 3cd1500a8..64aaf5a0a 100644
--- a/libempathy-gtk/empathy-individual-view.c
+++ b/libempathy-gtk/empathy-individual-view.c
@@ -2650,7 +2650,8 @@ empathy_individual_view_get_individual_menu (EmpathyIndividualView *view)
}
g_clear_object (&iter);
- menu = empathy_individual_menu_new (individual, priv->individual_features);
+ menu = empathy_individual_menu_new (individual, priv->individual_features,
+ priv->store);
/* Remove contact */
if ((priv->view_features &
diff --git a/libempathy/empathy-client-factory.c b/libempathy/empathy-client-factory.c
index edc5463c9..a02b8b144 100644
--- a/libempathy/empathy-client-factory.c
+++ b/libempathy/empathy-client-factory.c
@@ -170,6 +170,24 @@ empathy_client_factory_dup_connection_features (TpSimpleClientFactory *factory,
return features;
}
+static GArray *
+empathy_client_factory_dup_contact_features (TpSimpleClientFactory *factory,
+ TpConnection *connection)
+{
+ GArray *features;
+ TpContactFeature feature;
+
+ features = chainup->dup_contact_features (factory, connection);
+
+ /* Needed by empathy_individual_add_menu_item_new to check if a contact is
+ * already in the contact list. This feature is pretty cheap to prepare as
+ * it doesn't prepare the full roster. */
+ feature = TP_CONTACT_FEATURE_SUBSCRIPTION_STATES;
+ g_array_append_val (features, feature);
+
+ return features;
+}
+
static void
empathy_client_factory_class_init (EmpathyClientFactoryClass *cls)
{
@@ -184,6 +202,9 @@ empathy_client_factory_class_init (EmpathyClientFactoryClass *cls)
simple_class->dup_connection_features =
empathy_client_factory_dup_connection_features;
+
+ simple_class->dup_contact_features =
+ empathy_client_factory_dup_contact_features;
}
static void
diff --git a/src/empathy-main-window.c b/src/empathy-main-window.c
index 7dd631048..2f73acf92 100644
--- a/src/empathy-main-window.c
+++ b/src/empathy-main-window.c
@@ -2472,7 +2472,7 @@ empathy_main_window_init (EmpathyMainWindow *window)
priv->individual_view = empathy_individual_view_new (
priv->individual_store,
EMPATHY_INDIVIDUAL_VIEW_FEATURE_ALL ^ EMPATHY_INDIVIDUAL_VIEW_FEATURE_PERSONA_DROP,
- EMPATHY_INDIVIDUAL_FEATURE_ALL);
+ EMPATHY_INDIVIDUAL_FEATURE_ALL ^ EMPATHY_INDIVIDUAL_FEATURE_ADD_CONTACT);
gtk_widget_show (GTK_WIDGET (priv->individual_view));
gtk_container_add (GTK_CONTAINER (sw),