diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2011-11-08 21:06:49 +0800 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2011-11-24 19:28:44 +0800 |
commit | cbeb879c831699105fb6943e55caa8bcf72f8eaf (patch) | |
tree | da480b3deaf33dca0da2acbe0ec9de175c7d287d | |
parent | ef0d55ead126f53aa4544877d2df5ab712f00f28 (diff) | |
download | gsoc2013-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.c | 140 | ||||
-rw-r--r-- | libempathy-gtk/empathy-individual-menu.h | 10 | ||||
-rw-r--r-- | libempathy-gtk/empathy-individual-view.c | 3 | ||||
-rw-r--r-- | libempathy/empathy-client-factory.c | 21 | ||||
-rw-r--r-- | src/empathy-main-window.c | 2 |
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), |