diff --git a/libempathy-gtk/empathy-account-chooser.c b/libempathy-gtk/empathy-account-chooser.c index 5e261eb..f1c0ec6 100644 --- a/libempathy-gtk/empathy-account-chooser.c +++ b/libempathy-gtk/empathy-account-chooser.c @@ -74,6 +74,36 @@ 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. @@ -724,33 +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); - - /* Skip rows without account associated */ - if (account == NULL) - return; - 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, @@ -766,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 @@ -879,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 diff --git a/libempathy-gtk/empathy-account-chooser.h b/libempathy-gtk/empathy-account-chooser.h index f80d700..dfd372c 100644 --- a/libempathy-gtk/empathy-account-chooser.h +++ b/libempathy-gtk/empathy-account-chooser.h @@ -38,8 +38,26 @@ G_BEGIN_DECLS #define EMPATHY_IS_ACCOUNT_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_ACCOUNT_CHOOSER)) #define EMPATHY_ACCOUNT_CHOOSER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_ACCOUNT_CHOOSER, EmpathyAccountChooserClass)) -typedef gboolean (* EmpathyAccountChooserFilterFunc) (TpAccount *account, - gpointer user_data); +/** + * EmpathyAccountChooserFilterResultCallback: + * @is_enabled: indicated whether the account should be enabled + * @user_data: user data passed to the callback + */ +typedef void (* EmpathyAccountChooserFilterResultCallback) (gboolean is_enabled, + gpointer user_data); + +/** + * EmpathyAccountChooserFilterFunc: + * @account: a #TpAccount + * @callback: an #EmpathyAccountChooserFilterResultCallback accepting the result + * @callback_data: data passed to the @callback + * @user_data: user data passed to the callback + */ +typedef void (* EmpathyAccountChooserFilterFunc) ( + TpAccount *account, + EmpathyAccountChooserFilterResultCallback callback, + gpointer callback_data, + gpointer user_data); typedef struct _EmpathyAccountChooser EmpathyAccountChooser; @@ -69,7 +87,9 @@ void empathy_account_chooser_set_has_all_option (EmpathyAccountChooser void empathy_account_chooser_set_filter (EmpathyAccountChooser *chooser, EmpathyAccountChooserFilterFunc filter, gpointer user_data); -gboolean empathy_account_chooser_filter_is_connected (TpAccount *account, +void empathy_account_chooser_filter_is_connected (TpAccount *account, + EmpathyAccountChooserFilterResultCallback callback, + gpointer callback_data, gpointer user_data); gboolean empathy_account_chooser_is_ready (EmpathyAccountChooser *chooser); diff --git a/libempathy-gtk/empathy-contact-dialogs.c b/libempathy-gtk/empathy-contact-dialogs.c index a5ae51d..fb57f34 100644 --- a/libempathy-gtk/empathy-contact-dialogs.c +++ b/libempathy-gtk/empathy-contact-dialogs.c @@ -354,24 +354,28 @@ empathy_contact_personal_dialog_show (GtkWindow *parent) * New contact dialog */ -static gboolean -can_add_contact_to_account (TpAccount *account, - gpointer user_data) +static void +can_add_contact_to_account (TpAccount *account, + EmpathyAccountChooserFilterResultCallback callback, + gpointer callback_data, + gpointer user_data) { EmpathyContactManager *contact_manager; TpConnection *connection; gboolean result; connection = tp_account_get_connection (account); - if (connection == NULL) - return FALSE; + if (connection == NULL) { + callback (FALSE, callback_data); + return; + } contact_manager = empathy_contact_manager_dup_singleton (); result = empathy_contact_manager_get_flags_for_connection ( contact_manager, connection) & EMPATHY_CONTACT_LIST_CAN_ADD; g_object_unref (contact_manager); - return result; + callback (result, callback_data); } static void diff --git a/libempathy-gtk/empathy-contact-selector-dialog.c b/libempathy-gtk/empathy-contact-selector-dialog.c index 62b9027..3ed7f30 100644 --- a/libempathy-gtk/empathy-contact-selector-dialog.c +++ b/libempathy-gtk/empathy-contact-selector-dialog.c @@ -243,8 +243,10 @@ entry_activate_cb (GtkEntry *entry, gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT); } -static gboolean +static void account_chooser_filter (TpAccount *account, + EmpathyAccountChooserFilterResultCallback callback, + gpointer callback_data, gpointer user_data) { EmpathyContactSelectorDialog *self = user_data; @@ -252,9 +254,13 @@ account_chooser_filter (TpAccount *account, EMPATHY_CONTACT_SELECTOR_DIALOG_GET_CLASS (self); if (class->account_filter == NULL) - return empathy_account_chooser_filter_is_connected (account, user_data); + { + empathy_account_chooser_filter_is_connected ( + account,callback, callback_data, user_data); + return; + } - return class->account_filter (self, account); + class->account_filter (self, callback, callback_data, account); } static gboolean diff --git a/libempathy-gtk/empathy-contact-selector-dialog.h b/libempathy-gtk/empathy-contact-selector-dialog.h index 402f1c7..27d689c 100644 --- a/libempathy-gtk/empathy-contact-selector-dialog.h +++ b/libempathy-gtk/empathy-contact-selector-dialog.h @@ -29,6 +29,8 @@ #include #include +#include "empathy-account-chooser.h" + G_BEGIN_DECLS typedef struct _EmpathyContactSelectorDialog EmpathyContactSelectorDialog; @@ -38,7 +40,9 @@ typedef struct _EmpathyContactSelectorDialogClass \ struct _EmpathyContactSelectorDialogClass { GtkDialogClass parent_class; - gboolean (*account_filter) (EmpathyContactSelectorDialog *self, + void (*account_filter) (EmpathyContactSelectorDialog *self, + EmpathyAccountChooserFilterResultCallback callback, + gpointer callback_data, TpAccount *account); gboolean (*contact_filter) (EmpathyContactSelectorDialog *self, const char *id); diff --git a/libempathy-gtk/empathy-individual-dialogs.c b/libempathy-gtk/empathy-individual-dialogs.c index 85ed7d1..2c98010 100644 --- a/libempathy-gtk/empathy-individual-dialogs.c +++ b/libempathy-gtk/empathy-individual-dialogs.c @@ -43,8 +43,10 @@ static GtkWidget *new_individual_dialog = NULL; * New contact dialog */ -static gboolean +static void can_add_contact_to_account (TpAccount *account, + EmpathyAccountChooserFilterResultCallback callback, + gpointer callback_data, gpointer user_data) { EmpathyIndividualManager *individual_manager; @@ -53,13 +55,16 @@ can_add_contact_to_account (TpAccount *account, connection = tp_account_get_connection (account); if (connection == NULL) - return FALSE; + { + callback (FALSE, callback_data); + return; + } individual_manager = empathy_individual_manager_dup_singleton (); result = empathy_connection_can_add_personas (connection); g_object_unref (individual_manager); - return result; + callback (result, callback_data); } static void diff --git a/libempathy-gtk/empathy-new-call-dialog.c b/libempathy-gtk/empathy-new-call-dialog.c index 3d51283..ab9a86a 100644 --- a/libempathy-gtk/empathy-new-call-dialog.c +++ b/libempathy-gtk/empathy-new-call-dialog.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT @@ -50,6 +49,11 @@ G_DEFINE_TYPE(EmpathyNewCallDialog, empathy_new_call_dialog, typedef struct _EmpathyNewCallDialogPriv EmpathyNewCallDialogPriv; +typedef struct { + EmpathyAccountChooserFilterResultCallback callback; + gpointer user_data; +} FilterCallbackData; + struct _EmpathyNewCallDialogPriv { GtkWidget *check_video; }; @@ -136,36 +140,80 @@ out: gtk_widget_destroy (GTK_WIDGET (dialog)); } -static gboolean +static void +conn_prepared_cb (GObject *conn, + GAsyncResult *result, + gpointer user_data) +{ + FilterCallbackData *data = user_data; + GError *myerr = NULL; + TpCapabilities *caps; + GPtrArray *classes; + guint i; + + if (!tp_proxy_prepare_finish (conn, result, &myerr)) + goto out; + + caps = tp_connection_get_capabilities (TP_CONNECTION (conn)); + classes = tp_capabilities_get_channel_classes (caps); + + for (i = 0; i < classes->len; i++) + { + GHashTable *fixed; + GStrv allowed; + const gchar *chan_type; + + tp_value_array_unpack (g_ptr_array_index (classes, i), 2, + &fixed, &allowed); + + chan_type = tp_asv_get_string (fixed, TP_PROP_CHANNEL_CHANNEL_TYPE); + + if (tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA)) + continue; + + if (tp_asv_get_uint32 (fixed, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) != + TP_HANDLE_TYPE_CONTACT) + continue; + + data->callback (TRUE, data->user_data); + g_slice_free (FilterCallbackData, data); + return; + } + +out: + data->callback (FALSE, data->user_data); + g_slice_free (FilterCallbackData, data); +} + +static void empathy_new_call_dialog_account_filter (EmpathyContactSelectorDialog *dialog, + EmpathyAccountChooserFilterResultCallback callback, + gpointer callback_data, TpAccount *account) { TpConnection *connection; - EmpathyDispatcher *dispatcher; - GList *classes; + FilterCallbackData *cb_data; + GQuark features[] = { TP_CONNECTION_FEATURE_CAPABILITIES, 0 }; if (tp_account_get_connection_status (account, NULL) != TP_CONNECTION_STATUS_CONNECTED) - return FALSE; + { + callback (FALSE, callback_data); + return; + } /* check if CM supports calls */ connection = tp_account_get_connection (account); if (connection == NULL) - return FALSE; - - dispatcher = empathy_dispatcher_dup_singleton (); - - classes = empathy_dispatcher_find_requestable_channel_classes - (dispatcher, connection, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, - TP_HANDLE_TYPE_CONTACT, NULL); - - g_object_unref (dispatcher); - - if (classes == NULL) - return FALSE; + { + callback (FALSE, callback_data); + return; + } - g_list_free (classes); - return TRUE; + cb_data = g_slice_new0 (FilterCallbackData); + cb_data->callback = callback; + cb_data->user_data = callback_data; + tp_proxy_prepare_async (connection, features, conn_prepared_cb, cb_data); } static GObject * diff --git a/libempathy-gtk/empathy-new-message-dialog.c b/libempathy-gtk/empathy-new-message-dialog.c index a174814..4747dfb 100644 --- a/libempathy-gtk/empathy-new-message-dialog.c +++ b/libempathy-gtk/empathy-new-message-dialog.c @@ -42,6 +42,11 @@ #include "empathy-new-message-dialog.h" #include "empathy-account-chooser.h" +typedef struct { + EmpathyAccountChooserFilterResultCallback callback; + gpointer user_data; +} FilterCallbackData; + static EmpathyNewMessageDialog *dialog_singleton = NULL; G_DEFINE_TYPE(EmpathyNewMessageDialog, empathy_new_message_dialog, @@ -77,36 +82,57 @@ out: gtk_widget_destroy (GTK_WIDGET (dialog)); } -static gboolean +static void +conn_prepared_cb (GObject *conn, + GAsyncResult *result, + gpointer user_data) +{ + FilterCallbackData *data = user_data; + GError *myerr = NULL; + TpCapabilities *caps; + + if (!tp_proxy_prepare_finish (conn, result, &myerr)) + { + data->callback (FALSE, data->user_data); + g_slice_free (FilterCallbackData, data); + } + + caps = tp_connection_get_capabilities (TP_CONNECTION (conn)); + data->callback (tp_capabilities_supports_text_chats (caps), + data->user_data); + + g_slice_free (FilterCallbackData, data); +} + +static void empathy_new_message_account_filter (EmpathyContactSelectorDialog *dialog, + EmpathyAccountChooserFilterResultCallback callback, + gpointer callback_data, TpAccount *account) { TpConnection *connection; - EmpathyDispatcher *dispatcher; - GList *classes; + FilterCallbackData *cb_data; + GQuark features[] = { TP_CONNECTION_FEATURE_CAPABILITIES, 0 }; if (tp_account_get_connection_status (account, NULL) != TP_CONNECTION_STATUS_CONNECTED) - return FALSE; + { + callback (FALSE, callback_data); + return; + } /* check if CM supports 1-1 text chat */ connection = tp_account_get_connection (account); if (connection == NULL) - return FALSE; - - dispatcher = empathy_dispatcher_dup_singleton (); - - classes = empathy_dispatcher_find_requestable_channel_classes - (dispatcher, connection, TP_IFACE_CHANNEL_TYPE_TEXT, - TP_HANDLE_TYPE_CONTACT, NULL); - - g_object_unref (dispatcher); - - if (classes == NULL) - return FALSE; + { + callback (FALSE, callback_data); + return; + } - g_list_free (classes); - return TRUE; + cb_data = g_slice_new0 (FilterCallbackData); + cb_data->callback = callback; + cb_data->user_data = callback_data; + tp_proxy_prepare_async (connection, features, conn_prepared_cb, cb_data); } static GObject * diff --git a/src/empathy-about-dialog.c b/src/empathy-about-dialog.c index c1e1848..1a66fb2 100644 --- a/src/empathy-about-dialog.c +++ b/src/empathy-about-dialog.c @@ -45,7 +45,7 @@ static const char *authors[] = { "Frederic Crozat", "Frederic Peters", "Geert-Jan Van den Bogaerde", - "Guillaume Desmottes", + "Guillaume Desmottes ", "Johan Hammar", "Jonatan Magnusson", "Jonny Lamb", diff --git a/src/empathy-new-chatroom-dialog.c b/src/empathy-new-chatroom-dialog.c index 3808daa..58690d1 100644 --- a/src/empathy-new-chatroom-dialog.c +++ b/src/empathy-new-chatroom-dialog.c @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -74,6 +73,11 @@ typedef struct { GtkWidget *viewport_error; } EmpathyNewChatroomDialog; +typedef struct { + EmpathyAccountChooserFilterResultCallback callback; + gpointer user_data; +} FilterCallbackData; + enum { COL_NEED_PASSWORD, COL_INVITE_ONLY, @@ -133,46 +137,69 @@ static void new_chatroom_dialog_button_close_error_clicked_cb (GtkButton static EmpathyNewChatroomDialog *dialog_p = NULL; + +static void +conn_prepared_cb (GObject *conn, + GAsyncResult *result, + gpointer user_data) +{ + FilterCallbackData *data = user_data; + GError *myerr = NULL; + TpCapabilities *caps; + + if (!tp_proxy_prepare_finish (conn, result, &myerr)) { + data->callback (FALSE, data->user_data); + g_slice_free (FilterCallbackData, data); + } + + caps = tp_connection_get_capabilities (TP_CONNECTION (conn)); + data->callback (tp_capabilities_supports_text_chatrooms (caps), + data->user_data); + + g_slice_free (FilterCallbackData, data); +} + /** * empathy_account_chooser_filter_supports_multichat: * @account: a #TpAccount + * @callback: an #EmpathyAccountChooserFilterResultCallback accepting the result + * @callback_data: data passed to the @callback * @user_data: user data or %NULL * * An #EmpathyAccountChooserFilterFunc that returns accounts that both * support multiuser text chat and are connected. * - * Return value: TRUE if @account both supports muc and is connected + * Returns (via the callback) TRUE if @account both supports muc and is connected */ -static gboolean -empathy_account_chooser_filter_supports_multichat (TpAccount *account, - gpointer user_data) +static void +empathy_account_chooser_filter_supports_multichat ( + TpAccount *account, + EmpathyAccountChooserFilterResultCallback callback, + gpointer callback_data, + gpointer user_data) { - TpConnection *connection; - EmpathyDispatcher *dispatcher; - GList *classes; + TpConnection *connection; + FilterCallbackData *cb_data; + GQuark features[] = { TP_CONNECTION_FEATURE_CAPABILITIES, 0 }; if (tp_account_get_connection_status (account, NULL) != - TP_CONNECTION_STATUS_CONNECTED) - return FALSE; + TP_CONNECTION_STATUS_CONNECTED) { + callback (FALSE, callback_data); + return; + } /* check if CM supports multiuser text chat */ connection = tp_account_get_connection (account); - if (connection == NULL) - return FALSE; - - dispatcher = empathy_dispatcher_dup_singleton (); - - classes = empathy_dispatcher_find_requestable_channel_classes - (dispatcher, connection, TP_IFACE_CHANNEL_TYPE_TEXT, - TP_HANDLE_TYPE_ROOM, NULL); - - g_object_unref (dispatcher); - - if (classes == NULL) - return FALSE; + if (connection == NULL) { + callback (FALSE, callback_data); + return; + } - g_list_free (classes); - return TRUE; + cb_data = g_slice_new0 (FilterCallbackData); + cb_data->callback = callback; + cb_data->user_data = callback_data; + tp_proxy_prepare_async (connection, features, conn_prepared_cb, + cb_data); } void diff --git a/tests/interactive/test-empathy-account-chooser.c b/tests/interactive/test-empathy-account-chooser.c index d2ce7cc..7622a62 100644 --- a/tests/interactive/test-empathy-account-chooser.c +++ b/tests/interactive/test-empathy-account-chooser.c @@ -5,12 +5,14 @@ #include #include -static gboolean +static void filter_func (TpAccount *account, + EmpathyAccountChooserFilterResultCallback callback, + gpointer callback_data, gpointer user_data) { g_assert (TP_IS_ACCOUNT (account)); - return TRUE; + callback (TRUE, callback_data); } int