X-Git-Url: https://git.0d.be/?p=empathy.git;a=blobdiff_plain;f=libempathy-gtk%2Fempathy-new-message-dialog.c;h=aa55ae01d74821bfa250afeac2d4ffe473af62e2;hp=3ce3b3211ea9232906736a108d09533885bb6cfb;hb=4edb0bd465045faf92efdbe835c38d78c5e8208b;hpb=3aadcbead0634ad2a9ef6f182b75fda18758fafb diff --git a/libempathy-gtk/empathy-new-message-dialog.c b/libempathy-gtk/empathy-new-message-dialog.c index 3ce3b321..aa55ae01 100644 --- a/libempathy-gtk/empathy-new-message-dialog.c +++ b/libempathy-gtk/empathy-new-message-dialog.c @@ -1,4 +1,3 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2007-2008 Collabora Ltd. * @@ -19,32 +18,29 @@ * Authors: Xavier Claessens */ -#include - -#include -#include +#include "config.h" +#include "empathy-new-message-dialog.h" -#include #include -#include -#include -#include -#include +#include "empathy-request-util.h" +#include "empathy-contact-chooser.h" +#include "empathy-ui-utils.h" +#include "empathy-images.h" #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT -#include - -#include -#include - -#include "empathy-new-message-dialog.h" -#include "empathy-account-chooser.h" +#include "empathy-debug.h" static EmpathyNewMessageDialog *dialog_singleton = NULL; G_DEFINE_TYPE(EmpathyNewMessageDialog, empathy_new_message_dialog, - GTK_TYPE_DIALOG) + GTK_TYPE_DIALOG) + +struct _EmpathyNewMessageDialogPriv { + GtkWidget *chooser; + GtkWidget *button_chat; + GtkWidget *button_sms; +}; /** * SECTION:empathy-new-message-dialog @@ -52,317 +48,302 @@ G_DEFINE_TYPE(EmpathyNewMessageDialog, empathy_new_message_dialog, * @short_description: A dialog to show a new message * @include: libempathy-gtk/empathy-new-message-dialog.h * - * #EmpathyNewMessageDialog is a dialog which allows a text chat or - * call to be started with any contact on any enabled account. + * #EmpathyNewMessageDialog is a dialog which allows a text chat + * to be started with any contact on any enabled account. */ -typedef struct _EmpathyNewMessageDialogPriv EmpathyNewMessageDialogPriv; - -struct _EmpathyNewMessageDialogPriv { - GtkWidget *dialog; - GtkWidget *table_contact; - GtkWidget *account_chooser; - GtkWidget *entry_id; - GtkWidget *button_chat; - EmpathyContactManager *contact_manager; +enum +{ + EMP_NEW_MESSAGE_TEXT, + EMP_NEW_MESSAGE_SMS, }; -#define GET_PRIV(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_NEW_MESSAGE_DIALOG, \ - EmpathyNewMessageDialogPriv)) - -enum { - COMPLETION_COL_TEXT, - COMPLETION_COL_ID, - COMPLETION_COL_NAME, -} CompletionCol; - -static void -new_message_dialog_account_changed_cb (GtkWidget *widget, - EmpathyNewMessageDialog *dialog) +static const gchar * +get_error_display_message (GError *error) { - EmpathyNewMessageDialogPriv *priv = GET_PRIV (dialog); - EmpathyAccountChooser *chooser; - TpConnection *connection; - EmpathyTpContactList *contact_list; - GList *members; - GtkListStore *store; - GtkEntryCompletion *completion; - GtkTreeIter iter; - gchar *tmpstr; - - /* Remove completions */ - completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry_id)); - store = GTK_LIST_STORE (gtk_entry_completion_get_model (completion)); - gtk_list_store_clear (store); - - /* Get members of the new account */ - chooser = EMPATHY_ACCOUNT_CHOOSER (priv->account_chooser); - connection = empathy_account_chooser_get_connection (chooser); - if (!connection) { - return; - } - contact_list = empathy_contact_manager_get_list (priv->contact_manager, - connection); - members = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (contact_list)); - - /* Add members to the completion */ - while (members) { - EmpathyContact *contact = members->data; - - DEBUG ("Adding contact ID %s, Name %s", - empathy_contact_get_id (contact), - empathy_contact_get_name (contact)); - - tmpstr = g_strdup_printf ("%s (%s)", - empathy_contact_get_name (contact), - empathy_contact_get_id (contact)); - - gtk_list_store_insert_with_values (store, &iter, -1, - COMPLETION_COL_TEXT, tmpstr, - COMPLETION_COL_ID, empathy_contact_get_id (contact), - COMPLETION_COL_NAME, empathy_contact_get_name (contact), - -1); - - g_free (tmpstr); - - g_object_unref (contact); - members = g_list_delete_link (members, members); - } + if (error->domain != TP_ERROR) + goto out; + + switch (error->code) + { + case TP_ERROR_NETWORK_ERROR: + return _("Network error"); + case TP_ERROR_OFFLINE: + return _("The contact is offline"); + case TP_ERROR_INVALID_HANDLE: + return _("The specified contact is either invalid or unknown"); + case TP_ERROR_NOT_CAPABLE: + return _("The contact does not support this kind of conversation"); + case TP_ERROR_NOT_IMPLEMENTED: + return _("The requested functionality is not implemented " + "for this protocol"); + case TP_ERROR_INVALID_ARGUMENT: + /* Not very user friendly to say 'invalid arguments' */ + break; + case TP_ERROR_NOT_AVAILABLE: + return _("Could not start a conversation with the given contact"); + case TP_ERROR_CHANNEL_BANNED: + return _("You are banned from this channel"); + case TP_ERROR_CHANNEL_FULL: + return _("This channel is full"); + case TP_ERROR_CHANNEL_INVITE_ONLY: + return _("You must be invited to join this channel"); + case TP_ERROR_DISCONNECTED: + return _("Can't proceed while disconnected"); + case TP_ERROR_PERMISSION_DENIED: + return _("Permission denied"); + default: + DEBUG ("Unhandled error code: %d", error->code); + } + +out: + return _("There was an error starting the conversation"); } -static gboolean -new_message_dialog_match_selected_cb (GtkEntryCompletion *widget, - GtkTreeModel *model, - GtkTreeIter *iter, - EmpathyNewMessageDialog *dialog) +static void +show_chat_error (GError *error, + GtkWindow *parent) { - EmpathyNewMessageDialogPriv *priv = GET_PRIV (dialog); - gchar *id; - - if (!iter || !model) { - return FALSE; - } + GtkWidget *dialog; - gtk_tree_model_get (model, iter, COMPLETION_COL_ID, &id, -1); - gtk_entry_set_text (GTK_ENTRY (priv->entry_id), id); + dialog = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + "%s", + get_error_display_message (error)); - DEBUG ("Got selected match **%s**", id); + g_signal_connect_swapped (dialog, "response", + G_CALLBACK (gtk_widget_destroy), + dialog); - g_free (id); - - return TRUE; + gtk_widget_show (dialog); } -static gboolean -new_message_dialog_match_func (GtkEntryCompletion *completion, - const gchar *key, - GtkTreeIter *iter, - gpointer user_data) +static void +ensure_text_channel_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) { - GtkTreeModel *model; - gchar *id; - gchar *name; - - model = gtk_entry_completion_get_model (completion); - if (!model || !iter) { - return FALSE; - } - - gtk_tree_model_get (model, iter, COMPLETION_COL_NAME, &name, -1); - if (strstr (name, key)) { - DEBUG ("Key %s is matching name **%s**", key, name); - g_free (name); - return TRUE; - } - g_free (name); - - gtk_tree_model_get (model, iter, COMPLETION_COL_ID, &id, -1); - if (strstr (id, key)) { - DEBUG ("Key %s is matching ID **%s**", key, id); - g_free (id); - return TRUE; - } - g_free (id); - - return FALSE; + GError *error = NULL; + + if (!tp_account_channel_request_ensure_channel_finish ( + TP_ACCOUNT_CHANNEL_REQUEST (source), result, &error)) + { + DEBUG ("Failed to ensure text channel: %s", error->message); + show_chat_error (error, user_data); + g_error_free (error); + } } static void -new_message_dialog_response_cb (GtkWidget *widget, - gint response, - EmpathyNewMessageDialog *dialog) +empathy_new_message_dialog_response (GtkDialog *dialog, + int response_id) { - EmpathyNewMessageDialogPriv *priv = GET_PRIV (dialog); - TpConnection *connection; - const gchar *id; - - connection = empathy_account_chooser_get_connection ( - EMPATHY_ACCOUNT_CHOOSER (priv->account_chooser)); - id = gtk_entry_get_text (GTK_ENTRY (priv->entry_id)); - if (!connection || EMP_STR_EMPTY (id)) { - gtk_widget_destroy (widget); - return; - } - - if (response == GTK_RESPONSE_ACCEPT) { - empathy_dispatcher_chat_with_contact_id (connection, id, NULL, NULL); - } - - gtk_widget_destroy (widget); + EmpathyNewMessageDialog *self = (EmpathyNewMessageDialog *) dialog; + FolksIndividual *individual = NULL; + EmpathyContact *contact = NULL; + + if (response_id < EMP_NEW_MESSAGE_TEXT) + goto out; + + individual = empathy_contact_chooser_dup_selected ( + EMPATHY_CONTACT_CHOOSER (self->priv->chooser)); + if (individual == NULL) + goto out; + + switch (response_id) + { + case EMP_NEW_MESSAGE_TEXT: + contact = empathy_contact_dup_best_for_action (individual, + EMPATHY_ACTION_CHAT); + g_return_if_fail (contact != NULL); + + empathy_chat_with_contact_id (empathy_contact_get_account (contact), + empathy_contact_get_id (contact), + empathy_get_current_action_time (), + ensure_text_channel_cb, + gtk_widget_get_parent_window (GTK_WIDGET (dialog))); + break; + + case EMP_NEW_MESSAGE_SMS: + contact = empathy_contact_dup_best_for_action (individual, + EMPATHY_ACTION_SMS); + g_return_if_fail (contact != NULL); + + empathy_sms_contact_id (empathy_contact_get_account (contact), + empathy_contact_get_id (contact), + empathy_get_current_action_time (), + ensure_text_channel_cb, + gtk_widget_get_parent_window (GTK_WIDGET (dialog))); + break; + + default: + g_warn_if_reached (); + } + +out: + tp_clear_object (&individual); + tp_clear_object (&contact); + gtk_widget_destroy (GTK_WIDGET (dialog)); } -static void -new_message_change_state_button_cb (GtkEditable *editable, - EmpathyNewMessageDialog *dialog) +static GObject * +empathy_new_message_dialog_constructor (GType type, + guint n_props, + GObjectConstructParam *props) { - EmpathyNewMessageDialogPriv *priv = GET_PRIV (dialog); - const gchar *id; - gboolean sensitive; + GObject *retval; + + if (dialog_singleton) + { + retval = G_OBJECT (dialog_singleton); + g_object_ref (retval); + } + else + { + retval = G_OBJECT_CLASS ( + empathy_new_message_dialog_parent_class)->constructor (type, + n_props, props); + + dialog_singleton = EMPATHY_NEW_MESSAGE_DIALOG (retval); + g_object_add_weak_pointer (retval, (gpointer) &dialog_singleton); + } + + return retval; +} - id = gtk_entry_get_text (GTK_ENTRY (editable)); - sensitive = !EMP_STR_EMPTY (id); +static gboolean +individual_supports_action (FolksIndividual *individual, + EmpathyActionType action) +{ + EmpathyContact *contact; - gtk_widget_set_sensitive (priv->button_chat, sensitive); + contact = empathy_contact_dup_best_for_action (individual, action); + if (contact == NULL) + return FALSE; + + g_object_unref (contact); + return TRUE; } -static GObject * -empathy_new_message_dialog_constructor (GType type, - guint n_props, - GObjectConstructParam *props) +static gboolean +filter_individual (EmpathyContactChooser *chooser, + FolksIndividual *individual, + gboolean is_online, + gboolean searching, + gpointer user_data) { - GObject *retval; - - if (dialog_singleton) { - retval = G_OBJECT (dialog_singleton); - g_object_ref (retval); - } - else { - retval = G_OBJECT_CLASS ( - empathy_new_message_dialog_parent_class)->constructor (type, - n_props, props); - - dialog_singleton = EMPATHY_NEW_MESSAGE_DIALOG (retval); - g_object_add_weak_pointer (retval, (gpointer) &dialog_singleton); - } - - return retval; + return individual_supports_action (individual, EMPATHY_ACTION_CHAT) || + individual_supports_action (individual, EMPATHY_ACTION_SMS); } static void -empathy_new_message_dialog_init (EmpathyNewMessageDialog *dialog) +selection_changed_cb (GtkWidget *chooser, + FolksIndividual *selected, + EmpathyNewMessageDialog *self) { - EmpathyNewMessageDialogPriv *priv = GET_PRIV (dialog); - GtkBuilder *gui; - gchar *filename; - GtkEntryCompletion *completion; - GtkListStore *model; - GtkWidget *content_area; - GtkWidget *image; - - /* create a contact manager */ - priv->contact_manager = empathy_contact_manager_dup_singleton (); - - filename = empathy_file_lookup ("empathy-new-message-dialog.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "table_contact", &priv->table_contact, - "entry_id", &priv->entry_id, - NULL); - g_free (filename); - - content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); - gtk_container_add (GTK_CONTAINER (content_area), priv->table_contact); - - /* add buttons */ - gtk_dialog_add_button (GTK_DIALOG (dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); - - priv->button_chat = gtk_button_new_with_mnemonic (_("C_hat")); - image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_NEW_MESSAGE, - GTK_ICON_SIZE_BUTTON); - gtk_button_set_image (GTK_BUTTON (priv->button_chat), image); - - gtk_dialog_add_action_widget (GTK_DIALOG (dialog), priv->button_chat, - GTK_RESPONSE_ACCEPT); - gtk_widget_show (priv->button_chat); - - /* Tweak the dialog */ - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); - - gtk_window_set_title (GTK_WINDOW (dialog), _("New Conversation")); - gtk_window_set_role (GTK_WINDOW (dialog), "new_message"); - gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); - gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT); - gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_DIALOG); - - /* text completion */ - completion = gtk_entry_completion_new (); - model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); - gtk_entry_completion_set_text_column (completion, COMPLETION_COL_TEXT); - gtk_entry_completion_set_match_func (completion, - new_message_dialog_match_func, - NULL, NULL); - gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (model)); - gtk_entry_set_completion (GTK_ENTRY (priv->entry_id), completion); - g_signal_connect (completion, "match-selected", - G_CALLBACK (new_message_dialog_match_selected_cb), - dialog); - g_object_unref (completion); - g_object_unref (model); - - g_signal_connect (dialog, "response", - G_CALLBACK (new_message_dialog_response_cb), dialog); - - empathy_builder_connect (gui, dialog, - "entry_id", "changed", new_message_change_state_button_cb, - NULL); - - g_object_unref (gui); - - /* Create account chooser */ - priv->account_chooser = empathy_account_chooser_new (); - gtk_table_attach_defaults (GTK_TABLE (priv->table_contact), - priv->account_chooser, - 1, 2, 0, 1); - empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (priv->account_chooser), - empathy_account_chooser_filter_is_connected, - NULL); - gtk_widget_show (priv->account_chooser); - - new_message_dialog_account_changed_cb (priv->account_chooser, dialog); - g_signal_connect (priv->account_chooser, "changed", - G_CALLBACK (new_message_dialog_account_changed_cb), - dialog); - - gtk_widget_set_sensitive (priv->button_chat, FALSE); + gboolean can_chat, can_sms; + + if (selected == NULL) + { + can_chat = can_sms = FALSE; + } + else + { + can_chat = individual_supports_action (selected, EMPATHY_ACTION_CHAT); + can_sms = individual_supports_action (selected, EMPATHY_ACTION_SMS); + } + + gtk_widget_set_sensitive (self->priv->button_chat, can_chat); +#if 0 + gtk_widget_set_sensitive (self->priv->button_sms, can_sms); +#endif } static void -empathy_new_message_dialog_dispose (GObject *object) +selection_activate_cb (GtkWidget *chooser, + EmpathyNewMessageDialog *self) { - EmpathyNewMessageDialogPriv *priv = GET_PRIV (object); - - if (priv->contact_manager != NULL) { - g_object_unref (priv->contact_manager); - priv->contact_manager = NULL; - } + gtk_dialog_response (GTK_DIALOG (self), EMP_NEW_MESSAGE_TEXT); +} - if (G_OBJECT_CLASS (empathy_new_message_dialog_parent_class)->dispose) - G_OBJECT_CLASS (empathy_new_message_dialog_parent_class)->dispose (object); +static void +empathy_new_message_dialog_init (EmpathyNewMessageDialog *self) +{ + GtkWidget *image; + GtkWidget *content; + + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + EMPATHY_TYPE_NEW_MESSAGE_DIALOG, EmpathyNewMessageDialogPriv); + + content = gtk_dialog_get_content_area (GTK_DIALOG (self)); + + /* contact chooser */ + self->priv->chooser = empathy_contact_chooser_new (); + + empathy_contact_chooser_set_filter_func ( + EMPATHY_CONTACT_CHOOSER (self->priv->chooser), filter_individual, self); + + gtk_box_pack_start (GTK_BOX (content), self->priv->chooser, TRUE, TRUE, 0); + gtk_widget_show (self->priv->chooser); + + g_signal_connect (self->priv->chooser, "selection-changed", + G_CALLBACK (selection_changed_cb), self); + g_signal_connect (self->priv->chooser, "activate", + G_CALLBACK (selection_activate_cb), self); + + /* close button */ + gtk_dialog_add_button (GTK_DIALOG (self), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); + +#if 0 + /* add SMS button */ + self->priv->button_sms = gtk_button_new_with_mnemonic (_("_SMS")); + image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_SMS, + GTK_ICON_SIZE_BUTTON); + gtk_button_set_image (GTK_BUTTON (self->priv->button_sms), image); +#endif + + /* add chat button */ + self->priv->button_chat = gtk_button_new_with_mnemonic (_("_Done")); + image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_NEW_MESSAGE, + GTK_ICON_SIZE_BUTTON); + gtk_button_set_image (GTK_BUTTON (self->priv->button_chat), image); + +#if 0 + gtk_dialog_add_action_widget (GTK_DIALOG (self), self->priv->button_sms, + EMP_NEW_MESSAGE_SMS); + gtk_widget_show (self->priv->button_sms); +#endif + + gtk_dialog_add_action_widget (GTK_DIALOG (self), self->priv->button_chat, + EMP_NEW_MESSAGE_TEXT); + gtk_widget_show (self->priv->button_chat); + + /* Tweak the dialog */ + gtk_window_set_title (GTK_WINDOW (self), _("New Conversation")); + gtk_window_set_role (GTK_WINDOW (self), "new_message"); + + /* Set a default height so a few contacts are displayed */ + gtk_window_set_default_size (GTK_WINDOW (self), -1, 600); + + gtk_widget_set_sensitive (self->priv->button_chat, FALSE); +#if 0 + gtk_widget_set_sensitive (self->priv->button_sms, FALSE); +#endif } static void empathy_new_message_dialog_class_init ( EmpathyNewMessageDialogClass *class) { - GObjectClass *object_class = G_OBJECT_CLASS (class); + GObjectClass *object_class = G_OBJECT_CLASS (class); + GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (class); - g_type_class_add_private (class, sizeof (EmpathyNewMessageDialogPriv)); + object_class->constructor = empathy_new_message_dialog_constructor; - object_class->constructor = empathy_new_message_dialog_constructor; + dialog_class->response = empathy_new_message_dialog_response; - object_class->dispose = empathy_new_message_dialog_dispose; + g_type_class_add_private (class, sizeof (EmpathyNewMessageDialogPriv)); } /** @@ -376,15 +357,18 @@ empathy_new_message_dialog_class_init ( GtkWidget * empathy_new_message_dialog_show (GtkWindow *parent) { - GtkWidget *dialog; + GtkWidget *dialog; - dialog = g_object_new (EMPATHY_TYPE_NEW_MESSAGE_DIALOG, NULL); + dialog = g_object_new (EMPATHY_TYPE_NEW_MESSAGE_DIALOG, + "use-header-bar", 1, + NULL); - if (parent) { - gtk_window_set_transient_for (GTK_WINDOW (dialog), - GTK_WINDOW (parent)); - } + if (parent) + { + gtk_window_set_transient_for (GTK_WINDOW (dialog), + GTK_WINDOW (parent)); + } - gtk_widget_show (dialog); - return dialog; + gtk_widget_show (dialog); + return dialog; }