diff options
Diffstat (limited to 'libempathy-gtk')
-rw-r--r-- | libempathy-gtk/empathy-contact-widget.c | 1773 |
1 files changed, 864 insertions, 909 deletions
diff --git a/libempathy-gtk/empathy-contact-widget.c b/libempathy-gtk/empathy-contact-widget.c index 0475b48ed..00ecf46ca 100644 --- a/libempathy-gtk/empathy-contact-widget.c +++ b/libempathy-gtk/empathy-contact-widget.c @@ -136,54 +136,6 @@ typedef struct GtkTreeIter found_iter; } FindName; -static void contact_widget_destroy_cb (GtkWidget *widget, - EmpathyContactWidget *information); -static void contact_widget_remove_contact (EmpathyContactWidget *information); -static void contact_widget_set_contact (EmpathyContactWidget *information, - EmpathyContact *contact); -static void contact_widget_contact_setup (EmpathyContactWidget *information); -static void contact_widget_contact_update (EmpathyContactWidget *information); -static void contact_widget_change_contact (EmpathyContactWidget *information); -static void contact_widget_avatar_changed_cb (EmpathyAvatarChooser *chooser, - EmpathyContactWidget *information); -static gboolean contact_widget_id_focus_out_cb (GtkWidget *widget, - GdkEventFocus *event, EmpathyContactWidget *information); -static gboolean contact_widget_entry_alias_focus_event_cb ( - GtkEditable *editable, GdkEventFocus *event, - EmpathyContactWidget *information); -static void contact_widget_name_notify_cb (EmpathyContactWidget *information); -static void contact_widget_presence_notify_cb ( - EmpathyContactWidget *information); -static void contact_widget_avatar_notify_cb ( - EmpathyContactWidget *information); -static void contact_widget_groups_setup ( - EmpathyContactWidget *information); -static void contact_widget_groups_update (EmpathyContactWidget *information); -static void contact_widget_model_setup (EmpathyContactWidget *information); -static void contact_widget_model_populate_columns ( - EmpathyContactWidget *information); -static void contact_widget_groups_populate_data ( - EmpathyContactWidget *information); -static void contact_widget_groups_notify_cb ( - EmpathyContactWidget *information); -static gboolean contact_widget_model_find_name ( - EmpathyContactWidget *information,const gchar *name, GtkTreeIter *iter); -static gboolean contact_widget_model_find_name_foreach (GtkTreeModel *model, - GtkTreePath *path, GtkTreeIter *iter, FindName *data); -static void contact_widget_cell_toggled (GtkCellRendererToggle *cell, - gchar *path_string, EmpathyContactWidget *information); -static void contact_widget_entry_group_changed_cb (GtkEditable *editable, - EmpathyContactWidget *information); -static void contact_widget_entry_group_activate_cb (GtkEntry *entry, - EmpathyContactWidget *information); -static void contact_widget_button_group_clicked_cb (GtkButton *button, - EmpathyContactWidget *information); -static void contact_widget_details_setup (EmpathyContactWidget *information); -static void contact_widget_details_update (EmpathyContactWidget *information); -static void contact_widget_client_setup (EmpathyContactWidget *information); -static void contact_widget_client_update (EmpathyContactWidget *information); -static void contact_widget_location_update (EmpathyContactWidget *information); - enum { COL_NAME, @@ -192,812 +144,76 @@ enum COL_COUNT }; -/** - * empathy_contact_widget_new: - * @contact: an #EmpathyContact - * @flags: #EmpathyContactWidgetFlags for the new contact widget - * - * Creates a new #EmpathyContactWidget. - * - * Return value: a new #EmpathyContactWidget - */ -GtkWidget * -empathy_contact_widget_new (EmpathyContact *contact, - EmpathyContactWidgetFlags flags) -{ - EmpathyContactWidget *information; - GtkBuilder *gui; - gchar *filename; - - g_return_val_if_fail (contact == NULL || EMPATHY_IS_CONTACT (contact), NULL); - - information = g_slice_new0 (EmpathyContactWidget); - information->flags = flags; - - filename = empathy_file_lookup ("empathy-contact-widget.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_contact_widget", &information->vbox_contact_widget, - "vbox_contact", &information->vbox_contact, - "hbox_presence", &information->hbox_presence, - "label_alias", &information->label_alias, - "image_state", &information->image_state, - "table_contact", &information->table_contact, - "vbox_avatar", &information->vbox_avatar, - "vbox_location", &information->vbox_location, - "subvbox_location", &information->subvbox_location, - "label_location", &information->label_location, -#if HAVE_LIBCHAMPLAIN - "viewport_map", &information->viewport_map, -#endif - "vbox_groups", &information->vbox_groups, - "entry_group", &information->entry_group, - "button_group", &information->button_group, - "treeview_groups", &information->treeview_groups, - "vbox_details", &information->vbox_details, - "table_details", &information->table_details, - "hbox_details_requested", &information->hbox_details_requested, - "vbox_client", &information->vbox_client, - "table_client", &information->table_client, - "hbox_client_requested", &information->hbox_client_requested, - NULL); - g_free (filename); - - empathy_builder_connect (gui, information, - "vbox_contact_widget", "destroy", contact_widget_destroy_cb, - "entry_group", "changed", contact_widget_entry_group_changed_cb, - "entry_group", "activate", contact_widget_entry_group_activate_cb, - "button_group", "clicked", contact_widget_button_group_clicked_cb, - NULL); - information->table_location = NULL; - - g_object_set_data (G_OBJECT (information->vbox_contact_widget), - "EmpathyContactWidget", - information); - - /* Create widgets */ - contact_widget_contact_setup (information); - contact_widget_groups_setup (information); - contact_widget_details_setup (information); - contact_widget_client_setup (information); - - if (contact != NULL) - contact_widget_set_contact (information, contact); - - else if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT || - information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) - contact_widget_change_contact (information); - - return empathy_builder_unref_and_keep_widget (gui, - information->vbox_contact_widget); -} - -/** - * empathy_contact_widget_get_contact: - * @widget: an #EmpathyContactWidget - * - * Get the #EmpathyContact related with the #EmpathyContactWidget @widget. - * - * Returns: the #EmpathyContact associated with @widget - */ -EmpathyContact * -empathy_contact_widget_get_contact (GtkWidget *widget) -{ - EmpathyContactWidget *information; - - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - - information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); - if (!information) - return NULL; - - return information->contact; -} - -/** - * empathy_contact_widget_set_contact: - * @widget: an #EmpathyContactWidget - * @contact: a different #EmpathyContact - * - * Change the #EmpathyContact related with the #EmpathyContactWidget @widget. - */ -void -empathy_contact_widget_set_contact (GtkWidget *widget, - EmpathyContact *contact) -{ - EmpathyContactWidget *information; - - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (EMPATHY_IS_CONTACT (contact)); - - information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); - if (!information) - return; - - contact_widget_set_contact (information, contact); -} - -/** - * empathy_contact_widget_set_account_filter: - * @widget: an #EmpathyContactWidget - * @filter: a #EmpathyAccountChooserFilterFunc - * @user_data: user data to pass to @filter, or %NULL - * - * Set a filter on the #EmpathyAccountChooser included in the - * #EmpathyContactWidget. - */ -void -empathy_contact_widget_set_account_filter ( - GtkWidget *widget, - EmpathyAccountChooserFilterFunc filter, - gpointer user_data) -{ - EmpathyContactWidget *information; - EmpathyAccountChooser *chooser; - - g_return_if_fail (GTK_IS_WIDGET (widget)); - - information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); - if (!information) - return; - - chooser = EMPATHY_ACCOUNT_CHOOSER (information->widget_account); - if (chooser) - empathy_account_chooser_set_filter (chooser, filter, user_data); -} - -static void -contact_widget_destroy_cb (GtkWidget *widget, - EmpathyContactWidget *information) -{ - contact_widget_remove_contact (information); - - if (information->widget_id_timeout != 0) - { - g_source_remove (information->widget_id_timeout); - } - if (information->manager) - { - g_object_unref (information->manager); - } - - g_slice_free (EmpathyContactWidget, information); -} - static void -contact_widget_remove_contact (EmpathyContactWidget *information) +contact_widget_details_setup (EmpathyContactWidget *information) { - if (information->contact) - { - g_signal_handlers_disconnect_by_func (information->contact, - contact_widget_name_notify_cb, information); - g_signal_handlers_disconnect_by_func (information->contact, - contact_widget_presence_notify_cb, information); - g_signal_handlers_disconnect_by_func (information->contact, - contact_widget_avatar_notify_cb, information); - g_signal_handlers_disconnect_by_func (information->contact, - contact_widget_groups_notify_cb, information); - - g_object_unref (information->contact); - g_object_unref (information->factory); - information->contact = NULL; - information->factory = NULL; - } + /* FIXME: Needs new telepathy spec */ + gtk_widget_hide (information->vbox_details); } static void -contact_widget_set_contact (EmpathyContactWidget *information, - EmpathyContact *contact) -{ - if (contact == information->contact) - return; - - contact_widget_remove_contact (information); - if (contact) - { - TpConnection *connection; - - connection = empathy_contact_get_connection (contact); - information->contact = g_object_ref (contact); - information->factory = empathy_tp_contact_factory_dup_singleton (connection); - } - - /* set the selected account to be the account this contact came from */ - if (contact && EMPATHY_IS_ACCOUNT_CHOOSER (information->widget_account)) { - empathy_account_chooser_set_account ( - EMPATHY_ACCOUNT_CHOOSER (information->widget_account), - empathy_contact_get_account (contact)); - } - - /* Update information for widgets */ - contact_widget_contact_update (information); - contact_widget_groups_update (information); - contact_widget_details_update (information); - contact_widget_client_update (information); - contact_widget_location_update (information); -} - -static gboolean -contact_widget_id_activate_timeout (EmpathyContactWidget *self) +contact_widget_details_update (EmpathyContactWidget *information) { - contact_widget_change_contact (self); - return FALSE; + /* FIXME: Needs new telepathy spec */ } static void -contact_widget_id_changed_cb (GtkEntry *entry, - EmpathyContactWidget *self) +contact_widget_client_update (EmpathyContactWidget *information) { - if (self->widget_id_timeout != 0) - { - g_source_remove (self->widget_id_timeout); - } - - self->widget_id_timeout = - g_timeout_add_seconds (ID_CHANGED_TIMEOUT, - (GSourceFunc) contact_widget_id_activate_timeout, self); + /* FIXME: Needs new telepathy spec */ } static void -save_avatar_menu_activate_cb (GtkWidget *widget, - EmpathyContactWidget *information) +contact_widget_client_setup (EmpathyContactWidget *information) { - GtkWidget *dialog; - EmpathyAvatar *avatar; - gchar *ext = NULL, *filename; - - dialog = gtk_file_chooser_dialog_new (_("Save Avatar"), - NULL, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); - - gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), - TRUE); - - /* look for the avatar extension */ - avatar = empathy_contact_get_avatar (information->contact); - if (avatar->format != NULL) - { - gchar **splitted; - - splitted = g_strsplit (avatar->format, "/", 2); - if (splitted[0] != NULL && splitted[1] != NULL) - ext = g_strdup (splitted[1]); - - g_strfreev (splitted); - } - else - { - /* Avatar was loaded from the cache so was converted to PNG */ - ext = g_strdup ("png"); - } - - if (ext != NULL) - { - gchar *id; - - id = tp_escape_as_identifier (empathy_contact_get_id ( - information->contact)); - - filename = g_strdup_printf ("%s.%s", id, ext); - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename); - - g_free (id); - g_free (ext); - g_free (filename); - } - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) - { - GError *error = NULL; - - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - - if (!empathy_avatar_save_to_file (avatar, filename, &error)) - { - /* Save error */ - GtkWidget *error_dialog; - - error_dialog = gtk_message_dialog_new (NULL, 0, - GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - _("Unable to save avatar")); - - gtk_message_dialog_format_secondary_text ( - GTK_MESSAGE_DIALOG (error_dialog), "%s", error->message); - - g_signal_connect (error_dialog, "response", - G_CALLBACK (gtk_widget_destroy), NULL); - - gtk_window_present (GTK_WINDOW (error_dialog)); - - g_clear_error (&error); - } - - g_free (filename); - } - - gtk_widget_destroy (dialog); + /* FIXME: Needs new telepathy spec */ + gtk_widget_hide (information->vbox_client); } static void -popup_avatar_menu (EmpathyContactWidget *information, - GtkWidget *parent, - GdkEventButton *event) -{ - GtkWidget *menu, *item; - gint button, event_time; - - if (information->contact == NULL || - empathy_contact_get_avatar (information->contact) == NULL) - return; - - menu = gtk_menu_new (); - - /* Add "Save as..." entry */ - item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, NULL); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); - - g_signal_connect (item, "activate", - G_CALLBACK (save_avatar_menu_activate_cb), information); - - if (event) - { - button = event->button; - event_time = event->time; - } - else - { - button = 0; - event_time = gtk_get_current_event_time (); - } - - gtk_menu_attach_to_widget (GTK_MENU (menu), parent, NULL); - gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, - button, event_time); -} - -static gboolean -widget_avatar_popup_menu_cb (GtkWidget *widget, +contact_widget_cell_toggled (GtkCellRendererToggle *cell, + gchar *path_string, EmpathyContactWidget *information) { - popup_avatar_menu (information, widget, NULL); - - return TRUE; -} - -static gboolean -widget_avatar_button_press_event_cb (GtkWidget *widget, - GdkEventButton *event, - EmpathyContactWidget *information) -{ - /* Ignore double-clicks and triple-clicks */ - if (event->button == 3 && event->type == GDK_BUTTON_PRESS) - { - popup_avatar_menu (information, widget, event); - return TRUE; - } - - return FALSE; -} - -static void -update_avatar_chooser_account_cb (EmpathyAccountChooser *account_chooser, - EmpathyAvatarChooser *avatar_chooser) -{ - TpConnection *connection; - - connection = empathy_account_chooser_get_connection (account_chooser); - g_object_set (avatar_chooser, "connection", connection, NULL); -} - -static void -contact_widget_contact_setup (EmpathyContactWidget *information) -{ - /* Setup label_status as a KludgeLabel */ - information->label_status = empathy_kludge_label_new (""); - gtk_label_set_line_wrap_mode (GTK_LABEL (information->label_status), - PANGO_WRAP_WORD_CHAR); - gtk_label_set_line_wrap (GTK_LABEL (information->label_status), - TRUE); - - if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) - gtk_label_set_selectable (GTK_LABEL (information->label_status), TRUE); - - gtk_box_pack_start (GTK_BOX (information->hbox_presence), - information->label_status, TRUE, TRUE, 0); - gtk_widget_show (information->label_status); - - /* Setup account label/chooser */ - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) - { - information->widget_account = empathy_account_chooser_new (); - - g_signal_connect_swapped (information->widget_account, "changed", - G_CALLBACK (contact_widget_change_contact), - information); - } - else - { - /* Pack the protocol icon with the account name in an hbox */ - information->widget_account = gtk_hbox_new (FALSE, 6); - - information->label_account = gtk_label_new (NULL); - if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) { - gtk_label_set_selectable (GTK_LABEL (information->label_account), TRUE); - } - gtk_misc_set_alignment (GTK_MISC (information->label_account), 0, 0.5); - gtk_widget_show (information->label_account); - - information->image_account = gtk_image_new (); - gtk_widget_show (information->image_account); - - gtk_box_pack_start (GTK_BOX (information->widget_account), - information->image_account, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (information->widget_account), - information->label_account, FALSE, TRUE, 0); - } - gtk_table_attach_defaults (GTK_TABLE (information->table_contact), - information->widget_account, - 1, 2, 0, 1); - gtk_widget_show (information->widget_account); - - /* Set up avatar chooser/display */ - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_AVATAR) - { - information->widget_avatar = empathy_avatar_chooser_new (); - g_signal_connect (information->widget_avatar, "changed", - G_CALLBACK (contact_widget_avatar_changed_cb), - information); - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) - { - g_signal_connect (information->widget_account, "changed", - G_CALLBACK (update_avatar_chooser_account_cb), - information->widget_avatar); - update_avatar_chooser_account_cb ( - EMPATHY_ACCOUNT_CHOOSER (information->widget_account), - EMPATHY_AVATAR_CHOOSER (information->widget_avatar)); - } - } - else - { - information->widget_avatar = empathy_avatar_image_new (); - - g_signal_connect (information->widget_avatar, "popup-menu", - G_CALLBACK (widget_avatar_popup_menu_cb), information); - g_signal_connect (information->widget_avatar, "button-press-event", - G_CALLBACK (widget_avatar_button_press_event_cb), information); - } - - gtk_box_pack_start (GTK_BOX (information->vbox_avatar), - information->widget_avatar, - FALSE, FALSE, - 6); - gtk_widget_show (information->widget_avatar); - - /* Setup id label/entry */ - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) - { - information->widget_id = gtk_entry_new (); - g_signal_connect (information->widget_id, "focus-out-event", - G_CALLBACK (contact_widget_id_focus_out_cb), - information); - g_signal_connect (information->widget_id, "changed", - G_CALLBACK (contact_widget_id_changed_cb), - information); - } - else - { - information->widget_id = gtk_label_new (NULL); - if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) { - gtk_label_set_selectable (GTK_LABEL (information->widget_id), TRUE); - } - gtk_misc_set_alignment (GTK_MISC (information->widget_id), 0, 0.5); - } - gtk_table_attach_defaults (GTK_TABLE (information->table_contact), - information->widget_id, - 1, 2, 1, 2); - gtk_widget_show (information->widget_id); + GtkTreeView *view; + GtkTreeModel *model; + GtkListStore *store; + GtkTreePath *path; + GtkTreeIter iter; + gboolean enabled; + gchar *group; - /* Setup alias label/entry */ - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ALIAS) - { - information->widget_alias = gtk_entry_new (); - g_signal_connect (information->widget_alias, "focus-out-event", - G_CALLBACK (contact_widget_entry_alias_focus_event_cb), - information); - /* Make return activate the window default (the Close button) */ - gtk_entry_set_activates_default (GTK_ENTRY (information->widget_alias), - TRUE); - } - else - { - information->widget_alias = gtk_label_new (NULL); - if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) { - gtk_label_set_selectable (GTK_LABEL (information->widget_alias), TRUE); - } - gtk_misc_set_alignment (GTK_MISC (information->widget_alias), 0, 0.5); - } - gtk_table_attach_defaults (GTK_TABLE (information->table_contact), - information->widget_alias, - 1, 2, 2, 3); - if (information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP) { - gtk_label_set_selectable (GTK_LABEL (information->label_status), FALSE); - } - gtk_widget_show (information->widget_alias); -} + view = GTK_TREE_VIEW (information->treeview_groups); + model = gtk_tree_view_get_model (view); + store = GTK_LIST_STORE (model); -static void -contact_widget_contact_update (EmpathyContactWidget *information) -{ - TpAccount *account = NULL; - const gchar *id = NULL; + path = gtk_tree_path_new_from_string (path_string); - /* Connect and get info from new contact */ - if (information->contact) - { - g_signal_connect_swapped (information->contact, "notify::name", - G_CALLBACK (contact_widget_name_notify_cb), information); - g_signal_connect_swapped (information->contact, "notify::presence", - G_CALLBACK (contact_widget_presence_notify_cb), information); - g_signal_connect_swapped (information->contact, - "notify::presence-message", - G_CALLBACK (contact_widget_presence_notify_cb), information); - g_signal_connect_swapped (information->contact, "notify::avatar", - G_CALLBACK (contact_widget_avatar_notify_cb), information); + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + COL_ENABLED, &enabled, + COL_NAME, &group, + -1); - account = empathy_contact_get_account (information->contact); - id = empathy_contact_get_id (information->contact); - } + gtk_list_store_set (store, &iter, COL_ENABLED, !enabled, -1); + gtk_tree_path_free (path); - /* Update account widget */ - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) - { - if (account) - { - g_signal_handlers_block_by_func (information->widget_account, - contact_widget_change_contact, - information); - empathy_account_chooser_set_account ( - EMPATHY_ACCOUNT_CHOOSER (information->widget_account), account); - g_signal_handlers_unblock_by_func (information->widget_account, - contact_widget_change_contact, information); - } - } - else + if (group) { - if (account) + if (enabled) { - const gchar *name; - - name = tp_account_get_display_name (account); - gtk_label_set_label (GTK_LABEL (information->label_account), name); - - name = tp_account_get_icon_name (account); - gtk_image_set_from_icon_name (GTK_IMAGE (information->image_account), - name, GTK_ICON_SIZE_MENU); + empathy_contact_list_remove_from_group ( + EMPATHY_CONTACT_LIST (information->manager), information->contact, + group); } - } - - /* Update id widget */ - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) - gtk_entry_set_text (GTK_ENTRY (information->widget_id), id ? id : ""); - else - gtk_label_set_label (GTK_LABEL (information->widget_id), id ? id : ""); - - /* Update other widgets */ - if (information->contact) - { - contact_widget_name_notify_cb (information); - contact_widget_presence_notify_cb (information); - contact_widget_avatar_notify_cb (information); - - gtk_widget_show (information->label_alias); - gtk_widget_show (information->widget_alias); - gtk_widget_show (information->hbox_presence); - gtk_widget_show (information->widget_avatar); - } - else - { - gtk_widget_hide (information->label_alias); - gtk_widget_hide (information->widget_alias); - gtk_widget_hide (information->hbox_presence); - gtk_widget_hide (information->widget_avatar); - } -} - -static void -contact_widget_got_contact_cb (EmpathyTpContactFactory *factory, - EmpathyContact *contact, - const GError *error, - gpointer user_data, - GObject *weak_object) -{ - EmpathyContactWidget *information = user_data; - - if (error != NULL) - { - DEBUG ("Error: %s", error->message); - return; - } - - contact_widget_set_contact (information, contact); -} - -static void -contact_widget_change_contact (EmpathyContactWidget *information) -{ - EmpathyTpContactFactory *factory; - TpConnection *connection; - - connection = empathy_account_chooser_get_connection ( - EMPATHY_ACCOUNT_CHOOSER (information->widget_account)); - if (!connection) - return; - - factory = empathy_tp_contact_factory_dup_singleton (connection); - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) - { - const gchar *id; - - id = gtk_entry_get_text (GTK_ENTRY (information->widget_id)); - if (!EMP_STR_EMPTY (id)) + else { - empathy_tp_contact_factory_get_from_id (factory, id, - contact_widget_got_contact_cb, information, NULL, - G_OBJECT (information->vbox_contact_widget)); + empathy_contact_list_add_to_group ( + EMPATHY_CONTACT_LIST (information->manager), information->contact, + group); } + g_free (group); } - else - { - empathy_tp_contact_factory_get_from_handle (factory, - tp_connection_get_self_handle (connection), - contact_widget_got_contact_cb, information, NULL, - G_OBJECT (information->vbox_contact_widget)); - } - - g_object_unref (factory); -} - -static void -contact_widget_avatar_changed_cb (EmpathyAvatarChooser *chooser, - EmpathyContactWidget *information) -{ - const gchar *data; - gsize size; - const gchar *mime_type; - - empathy_avatar_chooser_get_image_data ( - EMPATHY_AVATAR_CHOOSER (information->widget_avatar), - &data, &size, &mime_type); - empathy_tp_contact_factory_set_avatar (information->factory, - data, size, mime_type); -} - -static gboolean -contact_widget_id_focus_out_cb (GtkWidget *widget, - GdkEventFocus *event, - EmpathyContactWidget *information) -{ - contact_widget_change_contact (information); - return FALSE; -} - -static gboolean -contact_widget_entry_alias_focus_event_cb (GtkEditable *editable, - GdkEventFocus *event, - EmpathyContactWidget *information) -{ - if (information->contact) - { - const gchar *alias; - - alias = gtk_entry_get_text (GTK_ENTRY (editable)); - empathy_tp_contact_factory_set_alias (information->factory, - information->contact, alias); - } - - return FALSE; -} - -static void -contact_widget_name_notify_cb (EmpathyContactWidget *information) -{ - if (GTK_IS_ENTRY (information->widget_alias)) - gtk_entry_set_text (GTK_ENTRY (information->widget_alias), - empathy_contact_get_name (information->contact)); - else - gtk_label_set_label (GTK_LABEL (information->widget_alias), - empathy_contact_get_name (information->contact)); -} - -static void -contact_widget_presence_notify_cb (EmpathyContactWidget *information) -{ - gtk_label_set_text (GTK_LABEL (information->label_status), - empathy_contact_get_status (information->contact)); - gtk_image_set_from_icon_name (GTK_IMAGE (information->image_state), - empathy_icon_name_for_contact (information->contact), - GTK_ICON_SIZE_BUTTON); - gtk_widget_show (information->image_state); -} - -static void -contact_widget_avatar_notify_cb (EmpathyContactWidget *information) -{ - EmpathyAvatar *avatar = NULL; - - if (information->contact) - avatar = empathy_contact_get_avatar (information->contact); - - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_AVATAR) - { - g_signal_handlers_block_by_func (information->widget_avatar, - contact_widget_avatar_changed_cb, - information); - empathy_avatar_chooser_set ( - EMPATHY_AVATAR_CHOOSER (information->widget_avatar), avatar); - g_signal_handlers_unblock_by_func (information->widget_avatar, - contact_widget_avatar_changed_cb, information); - } - else - empathy_avatar_image_set ( - EMPATHY_AVATAR_IMAGE (information->widget_avatar), avatar); -} - -static void -contact_widget_groups_setup (EmpathyContactWidget *information) -{ - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_GROUPS) - { - information->manager = empathy_contact_manager_dup_singleton (); - contact_widget_model_setup (information); - } -} - -static void -contact_widget_groups_update (EmpathyContactWidget *information) -{ - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_GROUPS && - information->contact) - { - g_signal_connect_swapped (information->contact, "notify::groups", - G_CALLBACK (contact_widget_groups_notify_cb), information); - contact_widget_groups_populate_data (information); - - gtk_widget_show (information->vbox_groups); - } - else - gtk_widget_hide (information->vbox_groups); -} - -static void -contact_widget_model_setup (EmpathyContactWidget *information) -{ - GtkTreeView *view; - GtkListStore *store; - GtkTreeSelection *selection; - - view = GTK_TREE_VIEW (information->treeview_groups); - - store = gtk_list_store_new (COL_COUNT, - G_TYPE_STRING, /* name */ - G_TYPE_BOOLEAN, /* enabled */ - G_TYPE_BOOLEAN); /* editable */ - - gtk_tree_view_set_model (view, GTK_TREE_MODEL (store)); - - selection = gtk_tree_view_get_selection (view); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - - contact_widget_model_populate_columns (information); - - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), - COL_NAME, GTK_SORT_ASCENDING); - - g_object_unref (store); } static void @@ -1041,6 +257,33 @@ contact_widget_model_populate_columns (EmpathyContactWidget *information) } static void +contact_widget_model_setup (EmpathyContactWidget *information) +{ + GtkTreeView *view; + GtkListStore *store; + GtkTreeSelection *selection; + + view = GTK_TREE_VIEW (information->treeview_groups); + + store = gtk_list_store_new (COL_COUNT, + G_TYPE_STRING, /* name */ + G_TYPE_BOOLEAN, /* enabled */ + G_TYPE_BOOLEAN); /* editable */ + + gtk_tree_view_set_model (view, GTK_TREE_MODEL (store)); + + selection = gtk_tree_view_get_selection (view); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + contact_widget_model_populate_columns (information); + + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), + COL_NAME, GTK_SORT_ASCENDING); + + g_object_unref (store); +} + +static void contact_widget_groups_populate_data (EmpathyContactWidget *information) { GtkTreeView *view; @@ -1083,44 +326,6 @@ contact_widget_groups_populate_data (EmpathyContactWidget *information) g_list_free (my_groups); } -static void -contact_widget_groups_notify_cb (EmpathyContactWidget *information) -{ - /* FIXME: not implemented */ -} - -static gboolean -contact_widget_model_find_name (EmpathyContactWidget *information, - const gchar *name, - GtkTreeIter *iter) -{ - GtkTreeView *view; - GtkTreeModel *model; - FindName data; - - if (EMP_STR_EMPTY (name)) - return FALSE; - - data.information = information; - data.name = name; - data.found = FALSE; - - view = GTK_TREE_VIEW (information->treeview_groups); - model = gtk_tree_view_get_model (view); - - gtk_tree_model_foreach (model, - (GtkTreeModelForeachFunc) contact_widget_model_find_name_foreach, - &data); - - if (data.found == TRUE) - { - *iter = data.found_iter; - return TRUE; - } - - return FALSE; -} - static gboolean contact_widget_model_find_name_foreach (GtkTreeModel *model, GtkTreePath *path, @@ -1151,50 +356,36 @@ contact_widget_model_find_name_foreach (GtkTreeModel *model, return FALSE; } -static void -contact_widget_cell_toggled (GtkCellRendererToggle *cell, - gchar *path_string, - EmpathyContactWidget *information) +static gboolean +contact_widget_model_find_name (EmpathyContactWidget *information, + const gchar *name, + GtkTreeIter *iter) { GtkTreeView *view; GtkTreeModel *model; - GtkListStore *store; - GtkTreePath *path; - GtkTreeIter iter; - gboolean enabled; - gchar *group; + FindName data; - view = GTK_TREE_VIEW (information->treeview_groups); - model = gtk_tree_view_get_model (view); - store = GTK_LIST_STORE (model); + if (EMP_STR_EMPTY (name)) + return FALSE; - path = gtk_tree_path_new_from_string (path_string); + data.information = information; + data.name = name; + data.found = FALSE; - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, - COL_ENABLED, &enabled, - COL_NAME, &group, - -1); + view = GTK_TREE_VIEW (information->treeview_groups); + model = gtk_tree_view_get_model (view); - gtk_list_store_set (store, &iter, COL_ENABLED, !enabled, -1); - gtk_tree_path_free (path); + gtk_tree_model_foreach (model, + (GtkTreeModelForeachFunc) contact_widget_model_find_name_foreach, + &data); - if (group) + if (data.found == TRUE) { - if (enabled) - { - empathy_contact_list_remove_from_group ( - EMPATHY_CONTACT_LIST (information->manager), information->contact, - group); - } - else - { - empathy_contact_list_add_to_group ( - EMPATHY_CONTACT_LIST (information->manager), information->contact, - group); - } - g_free (group); + *iter = data.found_iter; + return TRUE; } + + return FALSE; } static void @@ -1246,29 +437,35 @@ contact_widget_button_group_clicked_cb (GtkButton *button, } static void -contact_widget_details_setup (EmpathyContactWidget *information) +contact_widget_groups_notify_cb (EmpathyContactWidget *information) { - /* FIXME: Needs new telepathy spec */ - gtk_widget_hide (information->vbox_details); + /* FIXME: not implemented */ } static void -contact_widget_details_update (EmpathyContactWidget *information) +contact_widget_groups_setup (EmpathyContactWidget *information) { - /* FIXME: Needs new telepathy spec */ + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_GROUPS) + { + information->manager = empathy_contact_manager_dup_singleton (); + contact_widget_model_setup (information); + } } static void -contact_widget_client_setup (EmpathyContactWidget *information) +contact_widget_groups_update (EmpathyContactWidget *information) { - /* FIXME: Needs new telepathy spec */ - gtk_widget_hide (information->vbox_client); -} + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_GROUPS && + information->contact) + { + g_signal_connect_swapped (information->contact, "notify::groups", + G_CALLBACK (contact_widget_groups_notify_cb), information); + contact_widget_groups_populate_data (information); -static void -contact_widget_client_update (EmpathyContactWidget *information) -{ - /* FIXME: Needs new telepathy spec */ + gtk_widget_show (information->vbox_groups); + } + else + gtk_widget_hide (information->vbox_groups); } /* Converts the Location's GHashTable's key to a user readable string */ @@ -1512,3 +709,761 @@ contact_widget_location_update (EmpathyContactWidget *information) gtk_widget_show (information->vbox_location); } + +static void +save_avatar_menu_activate_cb (GtkWidget *widget, + EmpathyContactWidget *information) +{ + GtkWidget *dialog; + EmpathyAvatar *avatar; + gchar *ext = NULL, *filename; + + dialog = gtk_file_chooser_dialog_new (_("Save Avatar"), + NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), + TRUE); + + /* look for the avatar extension */ + avatar = empathy_contact_get_avatar (information->contact); + if (avatar->format != NULL) + { + gchar **splitted; + + splitted = g_strsplit (avatar->format, "/", 2); + if (splitted[0] != NULL && splitted[1] != NULL) + ext = g_strdup (splitted[1]); + + g_strfreev (splitted); + } + else + { + /* Avatar was loaded from the cache so was converted to PNG */ + ext = g_strdup ("png"); + } + + if (ext != NULL) + { + gchar *id; + + id = tp_escape_as_identifier (empathy_contact_get_id ( + information->contact)); + + filename = g_strdup_printf ("%s.%s", id, ext); + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename); + + g_free (id); + g_free (ext); + g_free (filename); + } + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + GError *error = NULL; + + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + if (!empathy_avatar_save_to_file (avatar, filename, &error)) + { + /* Save error */ + GtkWidget *error_dialog; + + error_dialog = gtk_message_dialog_new (NULL, 0, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + _("Unable to save avatar")); + + gtk_message_dialog_format_secondary_text ( + GTK_MESSAGE_DIALOG (error_dialog), "%s", error->message); + + g_signal_connect (error_dialog, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + + gtk_window_present (GTK_WINDOW (error_dialog)); + + g_clear_error (&error); + } + + g_free (filename); + } + + gtk_widget_destroy (dialog); +} + +static void +popup_avatar_menu (EmpathyContactWidget *information, + GtkWidget *parent, + GdkEventButton *event) +{ + GtkWidget *menu, *item; + gint button, event_time; + + if (information->contact == NULL || + empathy_contact_get_avatar (information->contact) == NULL) + return; + + menu = gtk_menu_new (); + + /* Add "Save as..." entry */ + item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, NULL); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + + g_signal_connect (item, "activate", + G_CALLBACK (save_avatar_menu_activate_cb), information); + + if (event) + { + button = event->button; + event_time = event->time; + } + else + { + button = 0; + event_time = gtk_get_current_event_time (); + } + + gtk_menu_attach_to_widget (GTK_MENU (menu), parent, NULL); + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, + button, event_time); +} + +static gboolean +widget_avatar_popup_menu_cb (GtkWidget *widget, + EmpathyContactWidget *information) +{ + popup_avatar_menu (information, widget, NULL); + + return TRUE; +} + +static gboolean +widget_avatar_button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + EmpathyContactWidget *information) +{ + /* Ignore double-clicks and triple-clicks */ + if (event->button == 3 && event->type == GDK_BUTTON_PRESS) + { + popup_avatar_menu (information, widget, event); + return TRUE; + } + + return FALSE; +} + +static void +contact_widget_avatar_changed_cb (EmpathyAvatarChooser *chooser, + EmpathyContactWidget *information) +{ + const gchar *data; + gsize size; + const gchar *mime_type; + + empathy_avatar_chooser_get_image_data ( + EMPATHY_AVATAR_CHOOSER (information->widget_avatar), + &data, &size, &mime_type); + empathy_tp_contact_factory_set_avatar (information->factory, + data, size, mime_type); +} + +static gboolean +contact_widget_entry_alias_focus_event_cb (GtkEditable *editable, + GdkEventFocus *event, + EmpathyContactWidget *information) +{ + if (information->contact) + { + const gchar *alias; + + alias = gtk_entry_get_text (GTK_ENTRY (editable)); + empathy_tp_contact_factory_set_alias (information->factory, + information->contact, alias); + } + + return FALSE; +} + +static void +update_avatar_chooser_account_cb (EmpathyAccountChooser *account_chooser, + EmpathyAvatarChooser *avatar_chooser) +{ + TpConnection *connection; + + connection = empathy_account_chooser_get_connection (account_chooser); + g_object_set (avatar_chooser, "connection", connection, NULL); +} + +static void +contact_widget_avatar_notify_cb (EmpathyContactWidget *information) +{ + EmpathyAvatar *avatar = NULL; + + if (information->contact) + avatar = empathy_contact_get_avatar (information->contact); + + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_AVATAR) + { + g_signal_handlers_block_by_func (information->widget_avatar, + contact_widget_avatar_changed_cb, + information); + empathy_avatar_chooser_set ( + EMPATHY_AVATAR_CHOOSER (information->widget_avatar), avatar); + g_signal_handlers_unblock_by_func (information->widget_avatar, + contact_widget_avatar_changed_cb, information); + } + else + empathy_avatar_image_set ( + EMPATHY_AVATAR_IMAGE (information->widget_avatar), avatar); +} + +static void +contact_widget_name_notify_cb (EmpathyContactWidget *information) +{ + if (GTK_IS_ENTRY (information->widget_alias)) + gtk_entry_set_text (GTK_ENTRY (information->widget_alias), + empathy_contact_get_name (information->contact)); + else + gtk_label_set_label (GTK_LABEL (information->widget_alias), + empathy_contact_get_name (information->contact)); +} + +static void +contact_widget_presence_notify_cb (EmpathyContactWidget *information) +{ + gtk_label_set_text (GTK_LABEL (information->label_status), + empathy_contact_get_status (information->contact)); + gtk_image_set_from_icon_name (GTK_IMAGE (information->image_state), + empathy_icon_name_for_contact (information->contact), + GTK_ICON_SIZE_BUTTON); + gtk_widget_show (information->image_state); +} + +static void +contact_widget_remove_contact (EmpathyContactWidget *information) +{ + if (information->contact) + { + g_signal_handlers_disconnect_by_func (information->contact, + contact_widget_name_notify_cb, information); + g_signal_handlers_disconnect_by_func (information->contact, + contact_widget_presence_notify_cb, information); + g_signal_handlers_disconnect_by_func (information->contact, + contact_widget_avatar_notify_cb, information); + g_signal_handlers_disconnect_by_func (information->contact, + contact_widget_groups_notify_cb, information); + + g_object_unref (information->contact); + g_object_unref (information->factory); + information->contact = NULL; + information->factory = NULL; + } +} + +static void contact_widget_change_contact (EmpathyContactWidget *information); + +static void +contact_widget_contact_update (EmpathyContactWidget *information) +{ + TpAccount *account = NULL; + const gchar *id = NULL; + + /* Connect and get info from new contact */ + if (information->contact) + { + g_signal_connect_swapped (information->contact, "notify::name", + G_CALLBACK (contact_widget_name_notify_cb), information); + g_signal_connect_swapped (information->contact, "notify::presence", + G_CALLBACK (contact_widget_presence_notify_cb), information); + g_signal_connect_swapped (information->contact, + "notify::presence-message", + G_CALLBACK (contact_widget_presence_notify_cb), information); + g_signal_connect_swapped (information->contact, "notify::avatar", + G_CALLBACK (contact_widget_avatar_notify_cb), information); + + account = empathy_contact_get_account (information->contact); + id = empathy_contact_get_id (information->contact); + } + + /* Update account widget */ + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) + { + if (account) + { + g_signal_handlers_block_by_func (information->widget_account, + contact_widget_change_contact, + information); + empathy_account_chooser_set_account ( + EMPATHY_ACCOUNT_CHOOSER (information->widget_account), account); + g_signal_handlers_unblock_by_func (information->widget_account, + contact_widget_change_contact, information); + } + } + else + { + if (account) + { + const gchar *name; + + name = tp_account_get_display_name (account); + gtk_label_set_label (GTK_LABEL (information->label_account), name); + + name = tp_account_get_icon_name (account); + gtk_image_set_from_icon_name (GTK_IMAGE (information->image_account), + name, GTK_ICON_SIZE_MENU); + } + } + + /* Update id widget */ + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) + gtk_entry_set_text (GTK_ENTRY (information->widget_id), id ? id : ""); + else + gtk_label_set_label (GTK_LABEL (information->widget_id), id ? id : ""); + + /* Update other widgets */ + if (information->contact) + { + contact_widget_name_notify_cb (information); + contact_widget_presence_notify_cb (information); + contact_widget_avatar_notify_cb (information); + + gtk_widget_show (information->label_alias); + gtk_widget_show (information->widget_alias); + gtk_widget_show (information->hbox_presence); + gtk_widget_show (information->widget_avatar); + } + else + { + gtk_widget_hide (information->label_alias); + gtk_widget_hide (information->widget_alias); + gtk_widget_hide (information->hbox_presence); + gtk_widget_hide (information->widget_avatar); + } +} + +static void +contact_widget_set_contact (EmpathyContactWidget *information, + EmpathyContact *contact) +{ + if (contact == information->contact) + return; + + contact_widget_remove_contact (information); + if (contact) + { + TpConnection *connection; + + connection = empathy_contact_get_connection (contact); + information->contact = g_object_ref (contact); + information->factory = empathy_tp_contact_factory_dup_singleton (connection); + } + + /* set the selected account to be the account this contact came from */ + if (contact && EMPATHY_IS_ACCOUNT_CHOOSER (information->widget_account)) { + empathy_account_chooser_set_account ( + EMPATHY_ACCOUNT_CHOOSER (information->widget_account), + empathy_contact_get_account (contact)); + } + + /* Update information for widgets */ + contact_widget_contact_update (information); + contact_widget_groups_update (information); + contact_widget_details_update (information); + contact_widget_client_update (information); + contact_widget_location_update (information); +} + +static void +contact_widget_got_contact_cb (EmpathyTpContactFactory *factory, + EmpathyContact *contact, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyContactWidget *information = user_data; + + if (error != NULL) + { + DEBUG ("Error: %s", error->message); + return; + } + + contact_widget_set_contact (information, contact); +} + +static void +contact_widget_change_contact (EmpathyContactWidget *information) +{ + EmpathyTpContactFactory *factory; + TpConnection *connection; + + connection = empathy_account_chooser_get_connection ( + EMPATHY_ACCOUNT_CHOOSER (information->widget_account)); + if (!connection) + return; + + factory = empathy_tp_contact_factory_dup_singleton (connection); + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) + { + const gchar *id; + + id = gtk_entry_get_text (GTK_ENTRY (information->widget_id)); + if (!EMP_STR_EMPTY (id)) + { + empathy_tp_contact_factory_get_from_id (factory, id, + contact_widget_got_contact_cb, information, NULL, + G_OBJECT (information->vbox_contact_widget)); + } + } + else + { + empathy_tp_contact_factory_get_from_handle (factory, + tp_connection_get_self_handle (connection), + contact_widget_got_contact_cb, information, NULL, + G_OBJECT (information->vbox_contact_widget)); + } + + g_object_unref (factory); +} + +static gboolean +contact_widget_id_activate_timeout (EmpathyContactWidget *self) +{ + contact_widget_change_contact (self); + return FALSE; +} + +static void +contact_widget_id_changed_cb (GtkEntry *entry, + EmpathyContactWidget *self) +{ + if (self->widget_id_timeout != 0) + { + g_source_remove (self->widget_id_timeout); + } + + self->widget_id_timeout = + g_timeout_add_seconds (ID_CHANGED_TIMEOUT, + (GSourceFunc) contact_widget_id_activate_timeout, self); +} + +static gboolean +contact_widget_id_focus_out_cb (GtkWidget *widget, + GdkEventFocus *event, + EmpathyContactWidget *information) +{ + contact_widget_change_contact (information); + return FALSE; +} + +static void +contact_widget_contact_setup (EmpathyContactWidget *information) +{ + /* Setup label_status as a KludgeLabel */ + information->label_status = empathy_kludge_label_new (""); + gtk_label_set_line_wrap_mode (GTK_LABEL (information->label_status), + PANGO_WRAP_WORD_CHAR); + gtk_label_set_line_wrap (GTK_LABEL (information->label_status), + TRUE); + + if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) + gtk_label_set_selectable (GTK_LABEL (information->label_status), TRUE); + + gtk_box_pack_start (GTK_BOX (information->hbox_presence), + information->label_status, TRUE, TRUE, 0); + gtk_widget_show (information->label_status); + + /* Setup account label/chooser */ + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) + { + information->widget_account = empathy_account_chooser_new (); + + g_signal_connect_swapped (information->widget_account, "changed", + G_CALLBACK (contact_widget_change_contact), + information); + } + else + { + /* Pack the protocol icon with the account name in an hbox */ + information->widget_account = gtk_hbox_new (FALSE, 6); + + information->label_account = gtk_label_new (NULL); + if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) { + gtk_label_set_selectable (GTK_LABEL (information->label_account), TRUE); + } + gtk_misc_set_alignment (GTK_MISC (information->label_account), 0, 0.5); + gtk_widget_show (information->label_account); + + information->image_account = gtk_image_new (); + gtk_widget_show (information->image_account); + + gtk_box_pack_start (GTK_BOX (information->widget_account), + information->image_account, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (information->widget_account), + information->label_account, FALSE, TRUE, 0); + } + gtk_table_attach_defaults (GTK_TABLE (information->table_contact), + information->widget_account, + 1, 2, 0, 1); + gtk_widget_show (information->widget_account); + + /* Set up avatar chooser/display */ + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_AVATAR) + { + information->widget_avatar = empathy_avatar_chooser_new (); + g_signal_connect (information->widget_avatar, "changed", + G_CALLBACK (contact_widget_avatar_changed_cb), + information); + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) + { + g_signal_connect (information->widget_account, "changed", + G_CALLBACK (update_avatar_chooser_account_cb), + information->widget_avatar); + update_avatar_chooser_account_cb ( + EMPATHY_ACCOUNT_CHOOSER (information->widget_account), + EMPATHY_AVATAR_CHOOSER (information->widget_avatar)); + } + } + else + { + information->widget_avatar = empathy_avatar_image_new (); + + g_signal_connect (information->widget_avatar, "popup-menu", + G_CALLBACK (widget_avatar_popup_menu_cb), information); + g_signal_connect (information->widget_avatar, "button-press-event", + G_CALLBACK (widget_avatar_button_press_event_cb), information); + } + + gtk_box_pack_start (GTK_BOX (information->vbox_avatar), + information->widget_avatar, + FALSE, FALSE, + 6); + gtk_widget_show (information->widget_avatar); + + /* Setup id label/entry */ + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) + { + information->widget_id = gtk_entry_new (); + g_signal_connect (information->widget_id, "focus-out-event", + G_CALLBACK (contact_widget_id_focus_out_cb), + information); + g_signal_connect (information->widget_id, "changed", + G_CALLBACK (contact_widget_id_changed_cb), + information); + } + else + { + information->widget_id = gtk_label_new (NULL); + if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) { + gtk_label_set_selectable (GTK_LABEL (information->widget_id), TRUE); + } + gtk_misc_set_alignment (GTK_MISC (information->widget_id), 0, 0.5); + } + gtk_table_attach_defaults (GTK_TABLE (information->table_contact), + information->widget_id, + 1, 2, 1, 2); + gtk_widget_show (information->widget_id); + + /* Setup alias label/entry */ + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ALIAS) + { + information->widget_alias = gtk_entry_new (); + g_signal_connect (information->widget_alias, "focus-out-event", + G_CALLBACK (contact_widget_entry_alias_focus_event_cb), + information); + /* Make return activate the window default (the Close button) */ + gtk_entry_set_activates_default (GTK_ENTRY (information->widget_alias), + TRUE); + } + else + { + information->widget_alias = gtk_label_new (NULL); + if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) { + gtk_label_set_selectable (GTK_LABEL (information->widget_alias), TRUE); + } + gtk_misc_set_alignment (GTK_MISC (information->widget_alias), 0, 0.5); + } + gtk_table_attach_defaults (GTK_TABLE (information->table_contact), + information->widget_alias, + 1, 2, 2, 3); + if (information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP) { + gtk_label_set_selectable (GTK_LABEL (information->label_status), FALSE); + } + gtk_widget_show (information->widget_alias); +} + +static void +contact_widget_destroy_cb (GtkWidget *widget, + EmpathyContactWidget *information) +{ + contact_widget_remove_contact (information); + + if (information->widget_id_timeout != 0) + { + g_source_remove (information->widget_id_timeout); + } + if (information->manager) + { + g_object_unref (information->manager); + } + + g_slice_free (EmpathyContactWidget, information); +} + +/** + * empathy_contact_widget_new: + * @contact: an #EmpathyContact + * @flags: #EmpathyContactWidgetFlags for the new contact widget + * + * Creates a new #EmpathyContactWidget. + * + * Return value: a new #EmpathyContactWidget + */ +GtkWidget * +empathy_contact_widget_new (EmpathyContact *contact, + EmpathyContactWidgetFlags flags) +{ + EmpathyContactWidget *information; + GtkBuilder *gui; + gchar *filename; + + g_return_val_if_fail (contact == NULL || EMPATHY_IS_CONTACT (contact), NULL); + + information = g_slice_new0 (EmpathyContactWidget); + information->flags = flags; + + filename = empathy_file_lookup ("empathy-contact-widget.ui", + "libempathy-gtk"); + gui = empathy_builder_get_file (filename, + "vbox_contact_widget", &information->vbox_contact_widget, + "vbox_contact", &information->vbox_contact, + "hbox_presence", &information->hbox_presence, + "label_alias", &information->label_alias, + "image_state", &information->image_state, + "table_contact", &information->table_contact, + "vbox_avatar", &information->vbox_avatar, + "vbox_location", &information->vbox_location, + "subvbox_location", &information->subvbox_location, + "label_location", &information->label_location, +#if HAVE_LIBCHAMPLAIN + "viewport_map", &information->viewport_map, +#endif + "vbox_groups", &information->vbox_groups, + "entry_group", &information->entry_group, + "button_group", &information->button_group, + "treeview_groups", &information->treeview_groups, + "vbox_details", &information->vbox_details, + "table_details", &information->table_details, + "hbox_details_requested", &information->hbox_details_requested, + "vbox_client", &information->vbox_client, + "table_client", &information->table_client, + "hbox_client_requested", &information->hbox_client_requested, + NULL); + g_free (filename); + + empathy_builder_connect (gui, information, + "vbox_contact_widget", "destroy", contact_widget_destroy_cb, + "entry_group", "changed", contact_widget_entry_group_changed_cb, + "entry_group", "activate", contact_widget_entry_group_activate_cb, + "button_group", "clicked", contact_widget_button_group_clicked_cb, + NULL); + information->table_location = NULL; + + g_object_set_data (G_OBJECT (information->vbox_contact_widget), + "EmpathyContactWidget", + information); + + /* Create widgets */ + contact_widget_contact_setup (information); + contact_widget_groups_setup (information); + contact_widget_details_setup (information); + contact_widget_client_setup (information); + + if (contact != NULL) + contact_widget_set_contact (information, contact); + + else if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT || + information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) + contact_widget_change_contact (information); + + return empathy_builder_unref_and_keep_widget (gui, + information->vbox_contact_widget); +} + +/** + * empathy_contact_widget_get_contact: + * @widget: an #EmpathyContactWidget + * + * Get the #EmpathyContact related with the #EmpathyContactWidget @widget. + * + * Returns: the #EmpathyContact associated with @widget + */ +EmpathyContact * +empathy_contact_widget_get_contact (GtkWidget *widget) +{ + EmpathyContactWidget *information; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); + if (!information) + return NULL; + + return information->contact; +} + +/** + * empathy_contact_widget_set_contact: + * @widget: an #EmpathyContactWidget + * @contact: a different #EmpathyContact + * + * Change the #EmpathyContact related with the #EmpathyContactWidget @widget. + */ +void +empathy_contact_widget_set_contact (GtkWidget *widget, + EmpathyContact *contact) +{ + EmpathyContactWidget *information; + + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (EMPATHY_IS_CONTACT (contact)); + + information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); + if (!information) + return; + + contact_widget_set_contact (information, contact); +} + +/** + * empathy_contact_widget_set_account_filter: + * @widget: an #EmpathyContactWidget + * @filter: a #EmpathyAccountChooserFilterFunc + * @user_data: user data to pass to @filter, or %NULL + * + * Set a filter on the #EmpathyAccountChooser included in the + * #EmpathyContactWidget. + */ +void +empathy_contact_widget_set_account_filter ( + GtkWidget *widget, + EmpathyAccountChooserFilterFunc filter, + gpointer user_data) +{ + EmpathyContactWidget *information; + EmpathyAccountChooser *chooser; + + g_return_if_fail (GTK_IS_WIDGET (widget)); + + information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); + if (!information) + return; + + chooser = EMPATHY_ACCOUNT_CHOOSER (information->widget_account); + if (chooser) + empathy_account_chooser_set_filter (chooser, filter, user_data); +} + |