From 522f9fa9e51b1e2e6f011c6b34a829f1c245111f Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 12 Jan 2010 08:29:47 +0100 Subject: Reorder functions to not declare them on top --- libempathy-gtk/empathy-contact-widget.c | 2101 +++++++++++++++---------------- 1 file changed, 1028 insertions(+), 1073 deletions(-) (limited to 'libempathy-gtk/empathy-contact-widget.c') 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,698 +144,731 @@ 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) +static void +contact_widget_details_setup (EmpathyContactWidget *information) { - EmpathyContactWidget *information; - GtkBuilder *gui; - gchar *filename; + /* FIXME: Needs new telepathy spec */ + gtk_widget_hide (information->vbox_details); +} - g_return_val_if_fail (contact == NULL || EMPATHY_IS_CONTACT (contact), NULL); +static void +contact_widget_details_update (EmpathyContactWidget *information) +{ + /* FIXME: Needs new telepathy spec */ +} - information = g_slice_new0 (EmpathyContactWidget); - information->flags = flags; +static void +contact_widget_client_update (EmpathyContactWidget *information) +{ + /* FIXME: Needs new telepathy spec */ +} - 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); +static void +contact_widget_client_setup (EmpathyContactWidget *information) +{ + /* FIXME: Needs new telepathy spec */ + gtk_widget_hide (information->vbox_client); +} - 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; +static void +contact_widget_cell_toggled (GtkCellRendererToggle *cell, + gchar *path_string, + EmpathyContactWidget *information) +{ + GtkTreeView *view; + GtkTreeModel *model; + GtkListStore *store; + GtkTreePath *path; + GtkTreeIter iter; + gboolean enabled; + gchar *group; - g_object_set_data (G_OBJECT (information->vbox_contact_widget), - "EmpathyContactWidget", - information); + view = GTK_TREE_VIEW (information->treeview_groups); + model = gtk_tree_view_get_model (view); + store = GTK_LIST_STORE (model); - /* Create widgets */ - contact_widget_contact_setup (information); - contact_widget_groups_setup (information); - contact_widget_details_setup (information); - contact_widget_client_setup (information); + path = gtk_tree_path_new_from_string (path_string); - if (contact != NULL) - contact_widget_set_contact (information, contact); + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + COL_ENABLED, &enabled, + COL_NAME, &group, + -1); - else if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT || - information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) - contact_widget_change_contact (information); + gtk_list_store_set (store, &iter, COL_ENABLED, !enabled, -1); + gtk_tree_path_free (path); - return empathy_builder_unref_and_keep_widget (gui, - information->vbox_contact_widget); + if (group) + { + 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); + } } -/** - * 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) +static void +contact_widget_model_populate_columns (EmpathyContactWidget *information) { - EmpathyContactWidget *information; + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + guint col_offset; - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + view = GTK_TREE_VIEW (information->treeview_groups); + model = gtk_tree_view_get_model (view); - information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); - if (!information) - return NULL; + renderer = gtk_cell_renderer_toggle_new (); + g_signal_connect (renderer, "toggled", + G_CALLBACK (contact_widget_cell_toggled), information); - return information->contact; -} + column = gtk_tree_view_column_new_with_attributes (_("Select"), renderer, + "active", COL_ENABLED, NULL); -/** - * 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; + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); + gtk_tree_view_column_set_fixed_width (column, 50); + gtk_tree_view_append_column (view, column); - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (EMPATHY_IS_CONTACT (contact)); + renderer = gtk_cell_renderer_text_new (); + col_offset = gtk_tree_view_insert_column_with_attributes (view, + -1, _("Group"), + renderer, + "text", COL_NAME, + /* "editable", COL_EDITABLE, */ + NULL); - information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); - if (!information) - return; + g_object_set_data (G_OBJECT (renderer), + "column", GINT_TO_POINTER (COL_NAME)); - contact_widget_set_contact (information, contact); + column = gtk_tree_view_get_column (view, col_offset - 1); + gtk_tree_view_column_set_sort_column_id (column, COL_NAME); + gtk_tree_view_column_set_resizable (column,FALSE); + gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE); } -/** - * 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) +static void +contact_widget_model_setup (EmpathyContactWidget *information) { - EmpathyContactWidget *information; - EmpathyAccountChooser *chooser; + GtkTreeView *view; + GtkListStore *store; + GtkTreeSelection *selection; - g_return_if_fail (GTK_IS_WIDGET (widget)); + view = GTK_TREE_VIEW (information->treeview_groups); - information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); - if (!information) - return; + store = gtk_list_store_new (COL_COUNT, + G_TYPE_STRING, /* name */ + G_TYPE_BOOLEAN, /* enabled */ + G_TYPE_BOOLEAN); /* editable */ - chooser = EMPATHY_ACCOUNT_CHOOSER (information->widget_account); - if (chooser) - empathy_account_chooser_set_filter (chooser, filter, user_data); -} + gtk_tree_view_set_model (view, GTK_TREE_MODEL (store)); -static void -contact_widget_destroy_cb (GtkWidget *widget, - EmpathyContactWidget *information) -{ - contact_widget_remove_contact (information); + selection = gtk_tree_view_get_selection (view); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - if (information->widget_id_timeout != 0) - { - g_source_remove (information->widget_id_timeout); - } - if (information->manager) - { - g_object_unref (information->manager); - } + contact_widget_model_populate_columns (information); - g_slice_free (EmpathyContactWidget, 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_remove_contact (EmpathyContactWidget *information) +contact_widget_groups_populate_data (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); + GtkTreeView *view; + GtkListStore *store; + GtkTreeIter iter; + GList *my_groups, *l; + GList *all_groups; - g_object_unref (information->contact); - g_object_unref (information->factory); - information->contact = NULL; - information->factory = NULL; - } -} + view = GTK_TREE_VIEW (information->treeview_groups); + store = GTK_LIST_STORE (gtk_tree_view_get_model (view)); + gtk_list_store_clear (store); -static void -contact_widget_set_contact (EmpathyContactWidget *information, - EmpathyContact *contact) -{ - if (contact == information->contact) - return; + all_groups = empathy_contact_list_get_all_groups ( + EMPATHY_CONTACT_LIST (information->manager)); + my_groups = empathy_contact_list_get_groups ( + EMPATHY_CONTACT_LIST (information->manager), + information->contact); - contact_widget_remove_contact (information); - if (contact) + for (l = all_groups; l; l = l->next) { - 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)); - } + const gchar *group_str; + gboolean enabled; - /* 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); -} + group_str = l->data; -static gboolean -contact_widget_id_activate_timeout (EmpathyContactWidget *self) -{ - contact_widget_change_contact (self); - return FALSE; -} + enabled = g_list_find_custom (my_groups, + group_str, (GCompareFunc) strcmp) != NULL; -static void -contact_widget_id_changed_cb (GtkEntry *entry, - EmpathyContactWidget *self) -{ - if (self->widget_id_timeout != 0) - { - g_source_remove (self->widget_id_timeout); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COL_NAME, group_str, + COL_EDITABLE, TRUE, + COL_ENABLED, enabled, + -1); } - self->widget_id_timeout = - g_timeout_add_seconds (ID_CHANGED_TIMEOUT, - (GSourceFunc) contact_widget_id_activate_timeout, self); + g_list_foreach (all_groups, (GFunc) g_free, NULL); + g_list_foreach (my_groups, (GFunc) g_free, NULL); + g_list_free (all_groups); + g_list_free (my_groups); } -static void -save_avatar_menu_activate_cb (GtkWidget *widget, - EmpathyContactWidget *information) +static gboolean +contact_widget_model_find_name_foreach (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + FindName *data) { - GtkWidget *dialog; - EmpathyAvatar *avatar; - gchar *ext = NULL, *filename; + gchar *name; - 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_tree_model_get (model, iter, + COL_NAME, &name, + -1); - gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), - TRUE); + if (!name) + return FALSE; - /* look for the avatar extension */ - avatar = empathy_contact_get_avatar (information->contact); - if (avatar->format != NULL) + if (data->name && strcmp (data->name, name) == 0) { - gchar **splitted; + data->found = TRUE; + data->found_iter = *iter; - splitted = g_strsplit (avatar->format, "/", 2); - if (splitted[0] != NULL && splitted[1] != NULL) - ext = g_strdup (splitted[1]); + g_free (name); - g_strfreev (splitted); - } - else - { - /* Avatar was loaded from the cache so was converted to PNG */ - ext = g_strdup ("png"); + return TRUE; } - if (ext != NULL) - { - gchar *id; - - id = tp_escape_as_identifier (empathy_contact_get_id ( - information->contact)); + g_free (name); - filename = g_strdup_printf ("%s.%s", id, ext); - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename); + return FALSE; +} - g_free (id); - g_free (ext); - g_free (filename); - } +static gboolean +contact_widget_model_find_name (EmpathyContactWidget *information, + const gchar *name, + GtkTreeIter *iter) +{ + GtkTreeView *view; + GtkTreeModel *model; + FindName data; - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) - { - GError *error = NULL; + if (EMP_STR_EMPTY (name)) + return FALSE; - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + data.information = information; + data.name = name; + data.found = FALSE; - if (!empathy_avatar_save_to_file (avatar, filename, &error)) - { - /* Save error */ - GtkWidget *error_dialog; + view = GTK_TREE_VIEW (information->treeview_groups); + model = gtk_tree_view_get_model (view); - error_dialog = gtk_message_dialog_new (NULL, 0, - GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - _("Unable to save avatar")); + gtk_tree_model_foreach (model, + (GtkTreeModelForeachFunc) contact_widget_model_find_name_foreach, + &data); - gtk_message_dialog_format_secondary_text ( - GTK_MESSAGE_DIALOG (error_dialog), "%s", error->message); + if (data.found == TRUE) + { + *iter = data.found_iter; + return TRUE; + } - g_signal_connect (error_dialog, "response", - G_CALLBACK (gtk_widget_destroy), NULL); + return FALSE; +} - gtk_window_present (GTK_WINDOW (error_dialog)); +static void +contact_widget_entry_group_changed_cb (GtkEditable *editable, + EmpathyContactWidget *information) +{ + GtkTreeIter iter; + const gchar *group; - g_clear_error (&error); - } + group = gtk_entry_get_text (GTK_ENTRY (information->entry_group)); - g_free (filename); - } + if (contact_widget_model_find_name (information, group, &iter)) + gtk_widget_set_sensitive (GTK_WIDGET (information->button_group), FALSE); + else + gtk_widget_set_sensitive (GTK_WIDGET (information->button_group), + !EMP_STR_EMPTY (group)); +} - gtk_widget_destroy (dialog); +static void +contact_widget_entry_group_activate_cb (GtkEntry *entry, + EmpathyContactWidget *information) +{ + gtk_widget_activate (GTK_WIDGET (information->button_group)); } static void -popup_avatar_menu (EmpathyContactWidget *information, - GtkWidget *parent, - GdkEventButton *event) +contact_widget_button_group_clicked_cb (GtkButton *button, + EmpathyContactWidget *information) { - GtkWidget *menu, *item; - gint button, event_time; + GtkTreeView *view; + GtkListStore *store; + GtkTreeIter iter; + const gchar *group; - if (information->contact == NULL || - empathy_contact_get_avatar (information->contact) == NULL) - return; + view = GTK_TREE_VIEW (information->treeview_groups); + store = GTK_LIST_STORE (gtk_tree_view_get_model (view)); - menu = gtk_menu_new (); + group = gtk_entry_get_text (GTK_ENTRY (information->entry_group)); - /* 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); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COL_NAME, group, + COL_ENABLED, TRUE, + -1); - g_signal_connect (item, "activate", - G_CALLBACK (save_avatar_menu_activate_cb), information); + empathy_contact_list_add_to_group ( + EMPATHY_CONTACT_LIST (information->manager), information->contact, + group); +} - if (event) +static void +contact_widget_groups_notify_cb (EmpathyContactWidget *information) +{ + /* FIXME: not implemented */ +} + +static void +contact_widget_groups_setup (EmpathyContactWidget *information) +{ + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_GROUPS) { - button = event->button; - event_time = event->time; + information->manager = empathy_contact_manager_dup_singleton (); + contact_widget_model_setup (information); } - 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) +static void +contact_widget_groups_update (EmpathyContactWidget *information) { - popup_avatar_menu (information, widget, NULL); + 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); - return TRUE; + gtk_widget_show (information->vbox_groups); + } + else + gtk_widget_hide (information->vbox_groups); } -static gboolean -widget_avatar_button_press_event_cb (GtkWidget *widget, - GdkEventButton *event, - EmpathyContactWidget *information) +/* Converts the Location's GHashTable's key to a user readable string */ +static const gchar * +location_key_to_label (const gchar *key) { - /* 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; + if (tp_strdiff (key, EMPATHY_LOCATION_COUNTRY_CODE) == FALSE) + return _("Country ISO Code:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_COUNTRY) == FALSE) + return _("Country:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_REGION) == FALSE) + return _("State:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_LOCALITY) == FALSE) + return _("City:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_AREA) == FALSE) + return _("Area:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_POSTAL_CODE) == FALSE) + return _("Postal Code:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_STREET) == FALSE) + return _("Street:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_BUILDING) == FALSE) + return _("Building:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_FLOOR) == FALSE) + return _("Floor:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_ROOM) == FALSE) + return _("Room:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_TEXT) == FALSE) + return _("Text:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_DESCRIPTION) == FALSE) + return _("Description:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_URI) == FALSE) + return _("URI:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_ACCURACY_LEVEL) == FALSE) + return _("Accuracy Level:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_ERROR) == FALSE) + return _("Error:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_VERTICAL_ERROR_M) == FALSE) + return _("Vertical Error (meters):"); + else if (tp_strdiff (key, EMPATHY_LOCATION_HORIZONTAL_ERROR_M) == FALSE) + return _("Horizontal Error (meters):"); + else if (tp_strdiff (key, EMPATHY_LOCATION_SPEED) == FALSE) + return _("Speed:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_BEARING) == FALSE) + return _("Bearing:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_CLIMB) == FALSE) + return _("Climb Speed:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_TIMESTAMP) == FALSE) + return _("Last Updated on:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_LON) == FALSE) + return _("Longitude:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_LAT) == FALSE) + return _("Latitude:"); + else if (tp_strdiff (key, EMPATHY_LOCATION_ALT) == FALSE) + return _("Altitude:"); + else + { + DEBUG ("Unexpected Location key: %s", key); + return key; + } } static void -update_avatar_chooser_account_cb (EmpathyAccountChooser *account_chooser, - EmpathyAvatarChooser *avatar_chooser) +contact_widget_location_update (EmpathyContactWidget *information) { - TpConnection *connection; + GHashTable *location; + GValue *value; + gdouble lat = 0.0, lon = 0.0; + gboolean has_position = TRUE; + GtkWidget *label; + guint row = 0; + static const gchar* ordered_geolocation_keys[] = { + EMPATHY_LOCATION_TEXT, + EMPATHY_LOCATION_URI, + EMPATHY_LOCATION_DESCRIPTION, + EMPATHY_LOCATION_BUILDING, + EMPATHY_LOCATION_FLOOR, + EMPATHY_LOCATION_ROOM, + EMPATHY_LOCATION_STREET, + EMPATHY_LOCATION_AREA, + EMPATHY_LOCATION_LOCALITY, + EMPATHY_LOCATION_REGION, + EMPATHY_LOCATION_COUNTRY, + NULL + }; + int i; + const gchar *skey; - connection = empathy_account_chooser_get_connection (account_chooser); - g_object_set (avatar_chooser, "connection", connection, NULL); -} + if (!(information->flags & EMPATHY_CONTACT_WIDGET_SHOW_LOCATION)) + { + gtk_widget_hide (information->vbox_location); + return; + } -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); + location = empathy_contact_get_location (information->contact); + if (location == NULL || g_hash_table_size (location) == 0) + { + gtk_widget_hide (information->vbox_location); + return; + } - if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) - gtk_label_set_selectable (GTK_LABEL (information->label_status), TRUE); + value = g_hash_table_lookup (location, EMPATHY_LOCATION_LAT); + if (value == NULL) + has_position = FALSE; + else + lat = g_value_get_double (value); - gtk_box_pack_start (GTK_BOX (information->hbox_presence), - information->label_status, TRUE, TRUE, 0); - gtk_widget_show (information->label_status); + value = g_hash_table_lookup (location, EMPATHY_LOCATION_LON); + if (value == NULL) + has_position = FALSE; + else + lon = g_value_get_double (value); - /* Setup account label/chooser */ - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) + value = g_hash_table_lookup (location, EMPATHY_LOCATION_TIMESTAMP); + if (value == NULL) { - information->widget_account = empathy_account_chooser_new (); - - g_signal_connect_swapped (information->widget_account, "changed", - G_CALLBACK (contact_widget_change_contact), - information); + gchar *loc = g_strdup_printf ("%s", _("Location")); + gtk_label_set_markup (GTK_LABEL (information->label_location), loc); + g_free (loc); } else { - /* Pack the protocol icon with the account name in an hbox */ - information->widget_account = gtk_hbox_new (FALSE, 6); + gchar *user_date; + gchar *text; + gint64 stamp; + time_t time_; - 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); + stamp = g_value_get_int64 (value); + time_ = stamp; - information->image_account = gtk_image_new (); - gtk_widget_show (information->image_account); + user_date = empathy_time_to_string_relative (time_); - 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); + text = g_strconcat ( _("Location, "), user_date, NULL); + gtk_label_set_markup (GTK_LABEL (information->label_location), text); + g_free (text); } - 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) + + /* Prepare the location information table */ + if (information->table_location != NULL) { - 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)); - } + gtk_widget_destroy (information->table_location); } - 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); - } + information->table_location = gtk_table_new (1, 2, FALSE); + gtk_box_pack_start (GTK_BOX (information->subvbox_location), + information->table_location, FALSE, FALSE, 5); - 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 + for (i = 0; (skey = ordered_geolocation_keys[i]); i++) { - 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); -} + const gchar* user_label; + GValue *gvalue; + char *svalue = NULL; -static void -contact_widget_contact_update (EmpathyContactWidget *information) -{ - TpAccount *account = NULL; - const gchar *id = NULL; + gvalue = g_hash_table_lookup (location, (gpointer) skey); + if (gvalue == NULL) + continue; - /* 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); + user_label = location_key_to_label (skey); - account = empathy_contact_get_account (information->contact); - id = empathy_contact_get_id (information->contact); - } + label = gtk_label_new (user_label); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_table_attach (GTK_TABLE (information->table_location), + label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, 10, 0); + gtk_widget_show (label); - /* Update account widget */ - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) - { - if (account) + if (G_VALUE_TYPE (gvalue) == G_TYPE_DOUBLE) { - 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); + gdouble dvalue; + dvalue = g_value_get_double (gvalue); + svalue = g_strdup_printf ("%f", dvalue); } - } - else - { - if (account) + else if (G_VALUE_TYPE (gvalue) == G_TYPE_STRING) { - const gchar *name; - - name = tp_account_get_display_name (account); - gtk_label_set_label (GTK_LABEL (information->label_account), name); + svalue = g_value_dup_string (gvalue); + } + else if (G_VALUE_TYPE (gvalue) == G_TYPE_INT64) + { + time_t time_; - name = tp_account_get_icon_name (account); - gtk_image_set_from_icon_name (GTK_IMAGE (information->image_account), - name, GTK_ICON_SIZE_MENU); + time_ = g_value_get_int64 (value); + svalue = empathy_time_to_string_utc (time_, _("%B %e, %Y at %R UTC")); } - } - /* 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 : ""); + if (svalue != NULL) + { + label = gtk_label_new (svalue); + gtk_table_attach_defaults (GTK_TABLE (information->table_location), + label, 1, 2, row, row + 1); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0); + gtk_widget_show (label); - /* Update other widgets */ - if (information->contact) - { - contact_widget_name_notify_cb (information); - contact_widget_presence_notify_cb (information); - contact_widget_avatar_notify_cb (information); + if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) + gtk_label_set_selectable (GTK_LABEL (label), TRUE); + } - gtk_widget_show (information->label_alias); - gtk_widget_show (information->widget_alias); - gtk_widget_show (information->hbox_presence); - gtk_widget_show (information->widget_avatar); + g_free (svalue); + row++; } - else + + if (row == 0) { - gtk_widget_hide (information->label_alias); - gtk_widget_hide (information->widget_alias); - gtk_widget_hide (information->hbox_presence); - gtk_widget_hide (information->widget_avatar); + gtk_widget_hide (information->vbox_location); + return; } -} -static void -contact_widget_got_contact_cb (EmpathyTpContactFactory *factory, - EmpathyContact *contact, - const GError *error, - gpointer user_data, - GObject *weak_object) -{ - EmpathyContactWidget *information = user_data; + gtk_widget_show (information->table_location); - if (error != NULL) +#if HAVE_LIBCHAMPLAIN + /* Cannot be displayed in tooltips until Clutter-Gtk can deal with such + * windows + */ + if (has_position && + !(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) { - DEBUG ("Error: %s", error->message); - return; + ClutterActor *marker; + ChamplainLayer *layer; + + information->map_view_embed = gtk_champlain_embed_new (); + information->map_view = gtk_champlain_embed_get_view ( + GTK_CHAMPLAIN_EMBED (information->map_view_embed)); + + gtk_container_add (GTK_CONTAINER (information->viewport_map), + information->map_view_embed); + g_object_set (G_OBJECT (information->map_view), "show-license", FALSE, + "scroll-mode", CHAMPLAIN_SCROLL_MODE_KINETIC, + NULL); + + layer = champlain_layer_new (); + champlain_view_add_layer (information->map_view, layer); + + marker = champlain_marker_new_with_text ( + empathy_contact_get_name (information->contact), NULL, NULL, NULL); + champlain_base_marker_set_position (CHAMPLAIN_BASE_MARKER (marker), lat, lon); + clutter_container_add (CLUTTER_CONTAINER (layer), marker, NULL); + + champlain_view_center_on (information->map_view, lat, lon); + gtk_widget_show_all (information->viewport_map); } +#endif - contact_widget_set_contact (information, contact); + gtk_widget_show (information->vbox_location); } static void -contact_widget_change_contact (EmpathyContactWidget *information) +save_avatar_menu_activate_cb (GtkWidget *widget, + EmpathyContactWidget *information) { - EmpathyTpContactFactory *factory; - TpConnection *connection; + GtkWidget *dialog; + EmpathyAvatar *avatar; + gchar *ext = NULL, *filename; - connection = empathy_account_chooser_get_connection ( - EMPATHY_ACCOUNT_CHOOSER (information->widget_account)); - if (!connection) - return; + 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); - factory = empathy_tp_contact_factory_dup_singleton (connection); - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) + 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) { - const gchar *id; + gchar **splitted; - 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)); - } + splitted = g_strsplit (avatar->format, "/", 2); + if (splitted[0] != NULL && splitted[1] != NULL) + ext = g_strdup (splitted[1]); + + g_strfreev (splitted); } 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)); + /* Avatar was loaded from the cache so was converted to PNG */ + ext = g_strdup ("png"); } - g_object_unref (factory); -} + if (ext != NULL) + { + gchar *id; -static void -contact_widget_avatar_changed_cb (EmpathyAvatarChooser *chooser, - EmpathyContactWidget *information) -{ - const gchar *data; - gsize size; - const gchar *mime_type; + id = tp_escape_as_identifier (empathy_contact_get_id ( + information->contact)); - 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); -} + filename = g_strdup_printf ("%s.%s", id, ext); + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename); -static gboolean -contact_widget_id_focus_out_cb (GtkWidget *widget, - GdkEventFocus *event, - EmpathyContactWidget *information) -{ - contact_widget_change_contact (information); - return FALSE; -} + 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, @@ -903,25 +888,13 @@ contact_widget_entry_alias_focus_event_cb (GtkEditable *editable, } static void -contact_widget_name_notify_cb (EmpathyContactWidget *information) +update_avatar_chooser_account_cb (EmpathyAccountChooser *account_chooser, + EmpathyAvatarChooser *avatar_chooser) { - 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)); -} + TpConnection *connection; -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); + connection = empathy_account_chooser_get_connection (account_chooser); + g_object_set (avatar_chooser, "connection", connection, NULL); } static void @@ -948,567 +921,549 @@ contact_widget_avatar_notify_cb (EmpathyContactWidget *information) } static void -contact_widget_groups_setup (EmpathyContactWidget *information) +contact_widget_name_notify_cb (EmpathyContactWidget *information) { - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_GROUPS) - { - information->manager = empathy_contact_manager_dup_singleton (); - contact_widget_model_setup (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_groups_update (EmpathyContactWidget *information) +contact_widget_presence_notify_cb (EmpathyContactWidget *information) { - if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_GROUPS && - information->contact) + 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_connect_swapped (information->contact, "notify::groups", - G_CALLBACK (contact_widget_groups_notify_cb), information); - contact_widget_groups_populate_data (information); + 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); - gtk_widget_show (information->vbox_groups); + g_object_unref (information->contact); + g_object_unref (information->factory); + information->contact = NULL; + information->factory = NULL; } - else - gtk_widget_hide (information->vbox_groups); } +static void contact_widget_change_contact (EmpathyContactWidget *information); + static void -contact_widget_model_setup (EmpathyContactWidget *information) +contact_widget_contact_update (EmpathyContactWidget *information) { - GtkTreeView *view; - GtkListStore *store; - GtkTreeSelection *selection; + TpAccount *account = NULL; + const gchar *id = NULL; - view = GTK_TREE_VIEW (information->treeview_groups); + /* 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); - store = gtk_list_store_new (COL_COUNT, - G_TYPE_STRING, /* name */ - G_TYPE_BOOLEAN, /* enabled */ - G_TYPE_BOOLEAN); /* editable */ + account = empathy_contact_get_account (information->contact); + id = empathy_contact_get_id (information->contact); + } - gtk_tree_view_set_model (view, GTK_TREE_MODEL (store)); + /* 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; - selection = gtk_tree_view_get_selection (view); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + name = tp_account_get_display_name (account); + gtk_label_set_label (GTK_LABEL (information->label_account), name); - contact_widget_model_populate_columns (information); + name = tp_account_get_icon_name (account); + gtk_image_set_from_icon_name (GTK_IMAGE (information->image_account), + name, GTK_ICON_SIZE_MENU); + } + } - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), - COL_NAME, GTK_SORT_ASCENDING); + /* 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 : ""); - g_object_unref (store); -} + /* Update other widgets */ + if (information->contact) + { + contact_widget_name_notify_cb (information); + contact_widget_presence_notify_cb (information); + contact_widget_avatar_notify_cb (information); -static void -contact_widget_model_populate_columns (EmpathyContactWidget *information) -{ - GtkTreeView *view; - GtkTreeModel *model; - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - guint col_offset; - - view = GTK_TREE_VIEW (information->treeview_groups); - model = gtk_tree_view_get_model (view); - - renderer = gtk_cell_renderer_toggle_new (); - g_signal_connect (renderer, "toggled", - G_CALLBACK (contact_widget_cell_toggled), 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); + } +} - column = gtk_tree_view_column_new_with_attributes (_("Select"), renderer, - "active", COL_ENABLED, NULL); +static void +contact_widget_set_contact (EmpathyContactWidget *information, + EmpathyContact *contact) +{ + if (contact == information->contact) + return; - gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width (column, 50); - gtk_tree_view_append_column (view, column); + contact_widget_remove_contact (information); + if (contact) + { + TpConnection *connection; - renderer = gtk_cell_renderer_text_new (); - col_offset = gtk_tree_view_insert_column_with_attributes (view, - -1, _("Group"), - renderer, - "text", COL_NAME, - /* "editable", COL_EDITABLE, */ - NULL); + connection = empathy_contact_get_connection (contact); + information->contact = g_object_ref (contact); + information->factory = empathy_tp_contact_factory_dup_singleton (connection); + } - g_object_set_data (G_OBJECT (renderer), - "column", GINT_TO_POINTER (COL_NAME)); + /* 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)); + } - column = gtk_tree_view_get_column (view, col_offset - 1); - gtk_tree_view_column_set_sort_column_id (column, COL_NAME); - gtk_tree_view_column_set_resizable (column,FALSE); - gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE); + /* 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_groups_populate_data (EmpathyContactWidget *information) +contact_widget_got_contact_cb (EmpathyTpContactFactory *factory, + EmpathyContact *contact, + const GError *error, + gpointer user_data, + GObject *weak_object) { - GtkTreeView *view; - GtkListStore *store; - GtkTreeIter iter; - GList *my_groups, *l; - GList *all_groups; - - view = GTK_TREE_VIEW (information->treeview_groups); - store = GTK_LIST_STORE (gtk_tree_view_get_model (view)); - gtk_list_store_clear (store); - - all_groups = empathy_contact_list_get_all_groups ( - EMPATHY_CONTACT_LIST (information->manager)); - my_groups = empathy_contact_list_get_groups ( - EMPATHY_CONTACT_LIST (information->manager), - information->contact); + EmpathyContactWidget *information = user_data; - for (l = all_groups; l; l = l->next) + if (error != NULL) { - const gchar *group_str; - gboolean enabled; - - group_str = l->data; - - enabled = g_list_find_custom (my_groups, - group_str, (GCompareFunc) strcmp) != NULL; - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - COL_NAME, group_str, - COL_EDITABLE, TRUE, - COL_ENABLED, enabled, - -1); + DEBUG ("Error: %s", error->message); + return; } - g_list_foreach (all_groups, (GFunc) g_free, NULL); - g_list_foreach (my_groups, (GFunc) g_free, NULL); - g_list_free (all_groups); - g_list_free (my_groups); + contact_widget_set_contact (information, contact); } 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) +contact_widget_change_contact (EmpathyContactWidget *information) { - GtkTreeView *view; - GtkTreeModel *model; - FindName data; - - if (EMP_STR_EMPTY (name)) - return FALSE; - - data.information = information; - data.name = name; - data.found = FALSE; + EmpathyTpContactFactory *factory; + TpConnection *connection; - view = GTK_TREE_VIEW (information->treeview_groups); - model = gtk_tree_view_get_model (view); + connection = empathy_account_chooser_get_connection ( + EMPATHY_ACCOUNT_CHOOSER (information->widget_account)); + if (!connection) + return; - gtk_tree_model_foreach (model, - (GtkTreeModelForeachFunc) contact_widget_model_find_name_foreach, - &data); + factory = empathy_tp_contact_factory_dup_singleton (connection); + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) + { + const gchar *id; - if (data.found == TRUE) + 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 { - *iter = data.found_iter; - return TRUE; + 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)); } - return FALSE; + g_object_unref (factory); } static gboolean -contact_widget_model_find_name_foreach (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - FindName *data) +contact_widget_id_activate_timeout (EmpathyContactWidget *self) { - gchar *name; - - gtk_tree_model_get (model, iter, - COL_NAME, &name, - -1); - - if (!name) - return FALSE; + contact_widget_change_contact (self); + return FALSE; +} - if (data->name && strcmp (data->name, name) == 0) +static void +contact_widget_id_changed_cb (GtkEntry *entry, + EmpathyContactWidget *self) +{ + if (self->widget_id_timeout != 0) { - data->found = TRUE; - data->found_iter = *iter; - - g_free (name); - - return TRUE; + g_source_remove (self->widget_id_timeout); } - g_free (name); + 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_cell_toggled (GtkCellRendererToggle *cell, - gchar *path_string, - EmpathyContactWidget *information) +contact_widget_contact_setup (EmpathyContactWidget *information) { - GtkTreeView *view; - GtkTreeModel *model; - GtkListStore *store; - GtkTreePath *path; - GtkTreeIter iter; - gboolean enabled; - gchar *group; - - view = GTK_TREE_VIEW (information->treeview_groups); - model = gtk_tree_view_get_model (view); - store = GTK_LIST_STORE (model); + /* 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); - path = gtk_tree_path_new_from_string (path_string); + if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) + gtk_label_set_selectable (GTK_LABEL (information->label_status), TRUE); - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, - COL_ENABLED, &enabled, - COL_NAME, &group, - -1); + gtk_box_pack_start (GTK_BOX (information->hbox_presence), + information->label_status, TRUE, TRUE, 0); + gtk_widget_show (information->label_status); - gtk_list_store_set (store, &iter, COL_ENABLED, !enabled, -1); - gtk_tree_path_free (path); + /* Setup account label/chooser */ + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) + { + information->widget_account = empathy_account_chooser_new (); - if (group) + g_signal_connect_swapped (information->widget_account, "changed", + G_CALLBACK (contact_widget_change_contact), + information); + } + else { - 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); - } -} - -static void -contact_widget_entry_group_changed_cb (GtkEditable *editable, - EmpathyContactWidget *information) -{ - GtkTreeIter iter; - const gchar *group; - - group = gtk_entry_get_text (GTK_ENTRY (information->entry_group)); - - if (contact_widget_model_find_name (information, group, &iter)) - gtk_widget_set_sensitive (GTK_WIDGET (information->button_group), FALSE); - else - gtk_widget_set_sensitive (GTK_WIDGET (information->button_group), - !EMP_STR_EMPTY (group)); -} - -static void -contact_widget_entry_group_activate_cb (GtkEntry *entry, - EmpathyContactWidget *information) -{ - gtk_widget_activate (GTK_WIDGET (information->button_group)); -} - -static void -contact_widget_button_group_clicked_cb (GtkButton *button, - EmpathyContactWidget *information) -{ - GtkTreeView *view; - GtkListStore *store; - GtkTreeIter iter; - const gchar *group; - - view = GTK_TREE_VIEW (information->treeview_groups); - store = GTK_LIST_STORE (gtk_tree_view_get_model (view)); - - group = gtk_entry_get_text (GTK_ENTRY (information->entry_group)); + /* Pack the protocol icon with the account name in an hbox */ + information->widget_account = gtk_hbox_new (FALSE, 6); - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - COL_NAME, group, - COL_ENABLED, TRUE, - -1); + 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); - empathy_contact_list_add_to_group ( - EMPATHY_CONTACT_LIST (information->manager), information->contact, - group); -} + information->image_account = gtk_image_new (); + gtk_widget_show (information->image_account); -static void -contact_widget_details_setup (EmpathyContactWidget *information) -{ - /* FIXME: Needs new telepathy spec */ - gtk_widget_hide (information->vbox_details); -} + 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); -static void -contact_widget_details_update (EmpathyContactWidget *information) -{ - /* FIXME: Needs new telepathy spec */ -} + /* 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 (); -static void -contact_widget_client_setup (EmpathyContactWidget *information) -{ - /* FIXME: Needs new telepathy spec */ - gtk_widget_hide (information->vbox_client); -} + 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); + } -static void -contact_widget_client_update (EmpathyContactWidget *information) -{ - /* FIXME: Needs new telepathy spec */ -} + gtk_box_pack_start (GTK_BOX (information->vbox_avatar), + information->widget_avatar, + FALSE, FALSE, + 6); + gtk_widget_show (information->widget_avatar); -/* Converts the Location's GHashTable's key to a user readable string */ -static const gchar * -location_key_to_label (const gchar *key) -{ - if (tp_strdiff (key, EMPATHY_LOCATION_COUNTRY_CODE) == FALSE) - return _("Country ISO Code:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_COUNTRY) == FALSE) - return _("Country:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_REGION) == FALSE) - return _("State:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_LOCALITY) == FALSE) - return _("City:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_AREA) == FALSE) - return _("Area:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_POSTAL_CODE) == FALSE) - return _("Postal Code:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_STREET) == FALSE) - return _("Street:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_BUILDING) == FALSE) - return _("Building:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_FLOOR) == FALSE) - return _("Floor:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_ROOM) == FALSE) - return _("Room:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_TEXT) == FALSE) - return _("Text:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_DESCRIPTION) == FALSE) - return _("Description:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_URI) == FALSE) - return _("URI:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_ACCURACY_LEVEL) == FALSE) - return _("Accuracy Level:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_ERROR) == FALSE) - return _("Error:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_VERTICAL_ERROR_M) == FALSE) - return _("Vertical Error (meters):"); - else if (tp_strdiff (key, EMPATHY_LOCATION_HORIZONTAL_ERROR_M) == FALSE) - return _("Horizontal Error (meters):"); - else if (tp_strdiff (key, EMPATHY_LOCATION_SPEED) == FALSE) - return _("Speed:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_BEARING) == FALSE) - return _("Bearing:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_CLIMB) == FALSE) - return _("Climb Speed:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_TIMESTAMP) == FALSE) - return _("Last Updated on:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_LON) == FALSE) - return _("Longitude:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_LAT) == FALSE) - return _("Latitude:"); - else if (tp_strdiff (key, EMPATHY_LOCATION_ALT) == FALSE) - return _("Altitude:"); + /* 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 - { - DEBUG ("Unexpected Location key: %s", key); - return key; - } -} - -static void -contact_widget_location_update (EmpathyContactWidget *information) -{ - GHashTable *location; - GValue *value; - gdouble lat = 0.0, lon = 0.0; - gboolean has_position = TRUE; - GtkWidget *label; - guint row = 0; - static const gchar* ordered_geolocation_keys[] = { - EMPATHY_LOCATION_TEXT, - EMPATHY_LOCATION_URI, - EMPATHY_LOCATION_DESCRIPTION, - EMPATHY_LOCATION_BUILDING, - EMPATHY_LOCATION_FLOOR, - EMPATHY_LOCATION_ROOM, - EMPATHY_LOCATION_STREET, - EMPATHY_LOCATION_AREA, - EMPATHY_LOCATION_LOCALITY, - EMPATHY_LOCATION_REGION, - EMPATHY_LOCATION_COUNTRY, - NULL - }; - int i; - const gchar *skey; - - if (!(information->flags & EMPATHY_CONTACT_WIDGET_SHOW_LOCATION)) { - gtk_widget_hide (information->vbox_location); - return; + 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); - location = empathy_contact_get_location (information->contact); - if (location == NULL || g_hash_table_size (location) == 0) + /* Setup alias label/entry */ + if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ALIAS) { - gtk_widget_hide (information->vbox_location); - return; + 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); } - - value = g_hash_table_lookup (location, EMPATHY_LOCATION_LAT); - if (value == NULL) - has_position = FALSE; else - lat = g_value_get_double (value); + { + 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); +} - value = g_hash_table_lookup (location, EMPATHY_LOCATION_LON); - if (value == NULL) - has_position = FALSE; - else - lon = g_value_get_double (value); +static void +contact_widget_destroy_cb (GtkWidget *widget, + EmpathyContactWidget *information) +{ + contact_widget_remove_contact (information); - value = g_hash_table_lookup (location, EMPATHY_LOCATION_TIMESTAMP); - if (value == NULL) + if (information->widget_id_timeout != 0) { - gchar *loc = g_strdup_printf ("%s", _("Location")); - gtk_label_set_markup (GTK_LABEL (information->label_location), loc); - g_free (loc); + g_source_remove (information->widget_id_timeout); } - else + if (information->manager) { - gchar *user_date; - gchar *text; - gint64 stamp; - time_t time_; - - stamp = g_value_get_int64 (value); - time_ = stamp; - - user_date = empathy_time_to_string_relative (time_); - - text = g_strconcat ( _("Location, "), user_date, NULL); - gtk_label_set_markup (GTK_LABEL (information->label_location), text); - g_free (text); + g_object_unref (information->manager); } + g_slice_free (EmpathyContactWidget, information); +} - /* Prepare the location information table */ - if (information->table_location != NULL) - { - gtk_widget_destroy (information->table_location); - } +/** + * 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; - information->table_location = gtk_table_new (1, 2, FALSE); - gtk_box_pack_start (GTK_BOX (information->subvbox_location), - information->table_location, FALSE, FALSE, 5); + g_return_val_if_fail (contact == NULL || EMPATHY_IS_CONTACT (contact), NULL); + information = g_slice_new0 (EmpathyContactWidget); + information->flags = flags; - for (i = 0; (skey = ordered_geolocation_keys[i]); i++) - { - const gchar* user_label; - GValue *gvalue; - char *svalue = NULL; + 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); - gvalue = g_hash_table_lookup (location, (gpointer) skey); - if (gvalue == NULL) - continue; + 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; - user_label = location_key_to_label (skey); + g_object_set_data (G_OBJECT (information->vbox_contact_widget), + "EmpathyContactWidget", + information); - label = gtk_label_new (user_label); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - gtk_table_attach (GTK_TABLE (information->table_location), - label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, 10, 0); - gtk_widget_show (label); + /* Create widgets */ + contact_widget_contact_setup (information); + contact_widget_groups_setup (information); + contact_widget_details_setup (information); + contact_widget_client_setup (information); - if (G_VALUE_TYPE (gvalue) == G_TYPE_DOUBLE) - { - gdouble dvalue; - dvalue = g_value_get_double (gvalue); - svalue = g_strdup_printf ("%f", dvalue); - } - else if (G_VALUE_TYPE (gvalue) == G_TYPE_STRING) - { - svalue = g_value_dup_string (gvalue); - } - else if (G_VALUE_TYPE (gvalue) == G_TYPE_INT64) - { - time_t time_; + if (contact != NULL) + contact_widget_set_contact (information, contact); - time_ = g_value_get_int64 (value); - svalue = empathy_time_to_string_utc (time_, _("%B %e, %Y at %R UTC")); - } + else if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT || + information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) + contact_widget_change_contact (information); - if (svalue != NULL) - { - label = gtk_label_new (svalue); - gtk_table_attach_defaults (GTK_TABLE (information->table_location), - label, 1, 2, row, row + 1); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0); - gtk_widget_show (label); + return empathy_builder_unref_and_keep_widget (gui, + information->vbox_contact_widget); +} - if (!(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) - gtk_label_set_selectable (GTK_LABEL (label), TRUE); - } +/** + * 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_free (svalue); - row++; - } + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - if (row == 0) - { - gtk_widget_hide (information->vbox_location); - return; - } + information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); + if (!information) + return NULL; - gtk_widget_show (information->table_location); + return information->contact; +} -#if HAVE_LIBCHAMPLAIN - /* Cannot be displayed in tooltips until Clutter-Gtk can deal with such - * windows - */ - if (has_position && - !(information->flags & EMPATHY_CONTACT_WIDGET_FOR_TOOLTIP)) - { - ClutterActor *marker; - ChamplainLayer *layer; +/** + * 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; - information->map_view_embed = gtk_champlain_embed_new (); - information->map_view = gtk_champlain_embed_get_view ( - GTK_CHAMPLAIN_EMBED (information->map_view_embed)); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (EMPATHY_IS_CONTACT (contact)); - gtk_container_add (GTK_CONTAINER (information->viewport_map), - information->map_view_embed); - g_object_set (G_OBJECT (information->map_view), "show-license", FALSE, - "scroll-mode", CHAMPLAIN_SCROLL_MODE_KINETIC, - NULL); + information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget"); + if (!information) + return; - layer = champlain_layer_new (); - champlain_view_add_layer (information->map_view, layer); + contact_widget_set_contact (information, contact); +} - marker = champlain_marker_new_with_text ( - empathy_contact_get_name (information->contact), NULL, NULL, NULL); - champlain_base_marker_set_position (CHAMPLAIN_BASE_MARKER (marker), lat, lon); - clutter_container_add (CLUTTER_CONTAINER (layer), marker, NULL); +/** + * 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; - champlain_view_center_on (information->map_view, lat, lon); - gtk_widget_show_all (information->viewport_map); - } -#endif + g_return_if_fail (GTK_IS_WIDGET (widget)); - gtk_widget_show (information->vbox_location); + 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); } + -- cgit v1.2.3