diff options
Diffstat (limited to 'src')
27 files changed, 1477 insertions, 2232 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 4b42fd11d..a2aa31d5b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,9 +30,7 @@ noinst_LTLIBRARIES = libempathy-accounts-common.la libempathy_accounts_common_la_SOURCES = \ empathy-accounts-common.c empathy-accounts-common.h \ - empathy-account-assistant.c empathy-account-assistant.h \ empathy-accounts-dialog.c empathy-accounts-dialog.h \ - empathy-auto-salut-account-helper.c empathy-auto-salut-account-helper.h \ empathy-import-dialog.c empathy-import-dialog.h \ empathy-import-pidgin.c empathy-import-pidgin.h \ empathy-import-widget.c empathy-import-widget.h \ diff --git a/src/empathy-account-assistant.c b/src/empathy-account-assistant.c deleted file mode 100644 index 0a5f1d76b..000000000 --- a/src/empathy-account-assistant.c +++ /dev/null @@ -1,1309 +0,0 @@ -/* - * Copyright (C) 2009 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> - */ - -/* empathy-account-assistant.c */ - -#include <config.h> -#include <glib/gi18n-lib.h> -#include <telepathy-glib/util.h> -#include <gdk/gdkkeysyms.h> - -#include "empathy-account-assistant.h" -#include "empathy-import-widget.h" -#include "empathy-import-utils.h" -#include "empathy-auto-salut-account-helper.h" - -#include <libempathy/empathy-account-settings.h> -#include <libempathy/empathy-utils.h> - -#include <libempathy-gtk/empathy-account-widget.h> -#include <libempathy-gtk/empathy-protocol-chooser.h> -#include <libempathy-gtk/empathy-ui-utils.h> - -#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT -#include <libempathy/empathy-debug.h> - -G_DEFINE_TYPE (EmpathyAccountAssistant, empathy_account_assistant, - GTK_TYPE_ASSISTANT) - -#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountAssistant) - -typedef enum { - RESPONSE_IMPORT = 1, - RESPONSE_ENTER_ACCOUNT = 2, - RESPONSE_CREATE_ACCOUNT = 3, - RESPONSE_SALUT_ONLY = 4 -} FirstPageResponse; - -typedef enum { - RESPONSE_CREATE_AGAIN = 1, - RESPONSE_CREATE_STOP = 2 -} CreateEnterPageResponse; - -typedef enum { - PAGE_INTRO = 0, - PAGE_IMPORT = 1, - PAGE_ENTER_CREATE = 2, - PAGE_SALUT = 3, -} PageID; - -enum { - PROP_PARENT = 1, - PROP_CONNECTION_MGRS, -}; - -typedef struct { - FirstPageResponse first_resp; - CreateEnterPageResponse create_enter_resp; - gboolean enter_create_forward; - TpAccountManager *account_mgr; - EmpathyConnectionManagers *connection_mgrs; - PageID current_page_id; - - /* enter or create page */ - GtkWidget *enter_or_create_page; - GtkWidget *current_account_widget; - EmpathyAccountWidget *current_widget_object; - GtkWidget *first_label; - GtkWidget *second_label; - GtkWidget *chooser; - GtkWidget *create_again_radio; - EmpathyAccountSettings *settings; - gboolean is_creating; - - /* import page */ - EmpathyImportWidget *iw; - GtkWidget *import_page; - - /* salut page */ - GtkWidget *salut_page; - EmpathyAccountSettings *salut_settings; - GtkWidget *salut_account_widget; - gboolean create_salut_account; - gboolean display_salut_page; - - GtkWindow *parent_window; - - gboolean dispose_run; -} EmpathyAccountAssistantPriv; - -static GtkWidget * account_assistant_build_enter_or_create_page ( - EmpathyAccountAssistant *self); -static void account_assistant_finish_enter_or_create_page ( - EmpathyAccountAssistant *self, - gboolean is_enter); - -static void do_constructed (GObject *object); - -static GtkWidget * -build_error_vbox (const gchar *primary_message, - const gchar *secondary_message) -{ - GtkWidget *main_vbox, *w, *hbox; - PangoAttrList *list; - - main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); - gtk_widget_show (main_vbox); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - w = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, - GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); - gtk_widget_show (w); - - w = gtk_label_new (primary_message); - gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); - list = pango_attr_list_new (); - pango_attr_list_insert (list, pango_attr_scale_new (PANGO_SCALE_LARGE)); - pango_attr_list_insert (list, pango_attr_weight_new (PANGO_WEIGHT_BOLD)); - gtk_label_set_attributes (GTK_LABEL (w), list); - gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); - gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_widget_show (w); - - pango_attr_list_unref (list); - - w = gtk_label_new (secondary_message); - gtk_label_set_use_markup (GTK_LABEL (w), TRUE); - gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); - gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); - gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_widget_show (w); - - return main_vbox; -} - -static GtkWidget * -account_assistant_build_error_page (EmpathyAccountAssistant *self, - GError *error, gint page_num) -{ - GtkWidget *main_vbox, *w; - const char *primary_message; - gchar *secondary_message, *markup; - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - - if (page_num == PAGE_IMPORT) - primary_message = _("There was an error while importing the accounts."); - else if (page_num >= PAGE_ENTER_CREATE && - priv->first_resp == RESPONSE_ENTER_ACCOUNT) - primary_message = _("There was an error while parsing the account details."); - else if (page_num >= PAGE_ENTER_CREATE && - priv->first_resp == RESPONSE_CREATE_ACCOUNT) - primary_message = _("There was an error while creating the account."); - else - primary_message = _("There was an error."); - - markup = g_markup_printf_escaped ("<span style=\"italic\">%s</span>", - error->message); - secondary_message = g_strdup_printf (_("The error message was: %s"), markup); - - main_vbox = build_error_vbox (primary_message, secondary_message); - - w = gtk_label_new (_("You can either go back and try to enter your " - "accounts' details again or quit this assistant and add accounts " - "later from the Edit menu.")); - gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 6); - gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); - gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_widget_show (w); - - g_free (markup); - g_free (secondary_message); - return main_vbox; -} - -static void -account_assistant_back_button_clicked_cb (GtkButton *button, - EmpathyAccountAssistant *self) -{ - gint page_num; - - page_num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), - "page-num")); - gtk_assistant_remove_action_widget (GTK_ASSISTANT (self), - GTK_WIDGET (button)); - gtk_assistant_set_current_page (GTK_ASSISTANT (self), page_num); -} - -static void -account_assistant_present_error_page (EmpathyAccountAssistant *self, - GError *error, gint page_num) -{ - GtkWidget *error_page, *back_button; - gint num; - - error_page = account_assistant_build_error_page (self, error, - page_num); - num = gtk_assistant_append_page (GTK_ASSISTANT (self), error_page); - gtk_assistant_set_page_title (GTK_ASSISTANT (self), error_page, - _("An error occurred")); - gtk_assistant_set_page_type (GTK_ASSISTANT (self), error_page, - GTK_ASSISTANT_PAGE_SUMMARY); - - back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK); - gtk_assistant_add_action_widget (GTK_ASSISTANT (self), back_button); - g_object_set_data (G_OBJECT (back_button), - "page-num", GINT_TO_POINTER (page_num)); - g_signal_connect (back_button, "clicked", - G_CALLBACK (account_assistant_back_button_clicked_cb), self); - gtk_widget_show (back_button); - - gtk_assistant_set_current_page (GTK_ASSISTANT (self), num); -} - -static void -update_create_page_buttons (EmpathyAccountAssistant *self) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - GtkAssistantPageType type; - - if (priv->display_salut_page || - priv->create_enter_resp == RESPONSE_CREATE_AGAIN) - type = GTK_ASSISTANT_PAGE_CONTENT; - else - type = GTK_ASSISTANT_PAGE_CONFIRM; - - gtk_assistant_set_page_type (GTK_ASSISTANT (self), priv->enter_or_create_page, - type); -} - -static void -account_assistant_reset_enter_create_page (EmpathyAccountAssistant *self) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - GtkWidget *page; - gint idx; - - page = account_assistant_build_enter_or_create_page (self); - idx = gtk_assistant_append_page (GTK_ASSISTANT (self), page); - priv->enter_or_create_page = page; - update_create_page_buttons (self); - - gtk_assistant_set_current_page (GTK_ASSISTANT (self), idx); - - account_assistant_finish_enter_or_create_page (self, - priv->first_resp == RESPONSE_ENTER_ACCOUNT ? - TRUE : FALSE); -} - -static void -account_assistant_account_enabled_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GError *error = NULL; - EmpathyAccountAssistant *self = user_data; - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - const gchar *protocol; - TpAccount *account = TP_ACCOUNT (source); - gint current_idx; - gboolean salut_created = FALSE; - - tp_account_set_enabled_finish (account, result, &error); - - if (error) - { - g_warning ("Error enabling an account: %s", error->message); - g_error_free (error); - } - - protocol = tp_account_get_protocol (account); - if (!tp_strdiff (protocol, "local-xmpp")) - { - salut_created = TRUE; - } - - empathy_connect_new_account (account, priv->account_mgr); - - current_idx = gtk_assistant_get_current_page (GTK_ASSISTANT (self)); - if (current_idx == PAGE_SALUT && !salut_created) - /* We are on the Salut page and aren't creating the salut account so don't - * terminate the assistant. */ - return; - - if (priv->create_enter_resp == RESPONSE_CREATE_STOP) - g_signal_emit_by_name (self, "close"); - else - account_assistant_reset_enter_create_page (self); -} - -static void -account_assistant_apply_account_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GError *error = NULL; - EmpathyAccountAssistant *self = user_data; - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source); - TpAccount *account; - - empathy_account_settings_apply_finish (settings, result, NULL, &error); - - priv->is_creating = FALSE; - - if (error != NULL) - { - account_assistant_present_error_page (self, error, - gtk_assistant_get_current_page (GTK_ASSISTANT (self))); - g_error_free (error); - return; - } - - /* enable the newly created account */ - account = empathy_account_settings_get_account (settings); - tp_account_set_enabled_async (account, TRUE, - account_assistant_account_enabled_cb, self); -} - -static void -account_assistant_apply_account_and_finish (EmpathyAccountAssistant *self, - EmpathyAccountSettings *settings, - gboolean set_display_name) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - - if (settings == NULL) - return; - - priv->is_creating = TRUE; - - if (set_display_name) - { - gchar *display_name; - - display_name = empathy_account_widget_get_default_display_name ( - priv->current_widget_object); - - empathy_account_settings_set_display_name_async (settings, - display_name, NULL, NULL); - - g_free (display_name); - } - - empathy_account_settings_apply_async (settings, - account_assistant_apply_account_cb, self); -} - -static void -account_assistant_handle_apply_cb (EmpathyAccountWidget *widget_object, - gboolean is_valid, - EmpathyAccountAssistant *self) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - - gtk_assistant_set_page_complete (GTK_ASSISTANT (self), - priv->enter_or_create_page, is_valid); -} - -static void -account_assistant_protocol_changed_cb (GtkComboBox *chooser, - EmpathyAccountAssistant *self) -{ - EmpathyAccountSettings *settings; - EmpathyAccountAssistantPriv *priv; - GtkWidget *account_widget; - EmpathyAccountWidget *widget_object = NULL; - - priv = GET_PRIV (self); - - settings = empathy_protocol_chooser_create_account_settings ( - EMPATHY_PROTOCOL_CHOOSER (chooser)); - - if (settings == NULL) - return; - - if (priv->first_resp == RESPONSE_CREATE_ACCOUNT) - empathy_account_settings_set_boolean (settings, "register", TRUE); - - widget_object = empathy_account_widget_new_for_protocol (settings, TRUE); - account_widget = empathy_account_widget_get_widget (widget_object); - - if (priv->current_account_widget != NULL) - { - g_signal_handlers_disconnect_by_func (priv->current_widget_object, - account_assistant_handle_apply_cb, self); - gtk_widget_destroy (priv->current_account_widget); - } - - empathy_account_widget_hide_buttons (widget_object); - - priv->current_account_widget = account_widget; - priv->current_widget_object = widget_object; - - if (priv->settings != NULL) - g_object_unref (priv->settings); - - priv->settings = settings; - - g_signal_connect (priv->current_widget_object, "handle-apply", - G_CALLBACK (account_assistant_handle_apply_cb), self); - - if (empathy_account_settings_is_valid (settings)) - { - gtk_assistant_set_page_complete (GTK_ASSISTANT (self), - priv->enter_or_create_page, TRUE); - } - - gtk_box_pack_start (GTK_BOX (priv->enter_or_create_page), account_widget, - FALSE, FALSE, 0); - gtk_widget_show (account_widget); -} - -static gboolean -account_assistant_chooser_enter_details_filter_func ( - TpConnectionManager *cm, - TpConnectionManagerProtocol *protocol, - const gchar *service, - gpointer user_data) -{ - if (!tp_strdiff (protocol->name, "local-xmpp")) - return FALSE; - - return TRUE; -} - -static gboolean -account_assistant_chooser_create_account_filter_func ( - TpConnectionManager *cm, - TpConnectionManagerProtocol *protocol, - const gchar *service, - gpointer user_data) -{ - if (service != NULL) - return FALSE; - - return tp_connection_manager_protocol_can_register (protocol); -} - -static void -account_assistant_finish_enter_or_create_page (EmpathyAccountAssistant *self, - gboolean is_enter) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - - if (is_enter) - { - gtk_label_set_label (GTK_LABEL (priv->first_label), - _("What kind of chat account do you have?")); - /* gtk_label_set_label (GTK_LABEL (priv->second_label), - _("If you have other accounts to set up, you can do " - "that at any time from the Edit menu.")); - */ - gtk_label_set_label (GTK_LABEL (priv->second_label), - _("Do you have any other chat accounts you want to set up?")); - empathy_protocol_chooser_set_visible ( - EMPATHY_PROTOCOL_CHOOSER (priv->chooser), - account_assistant_chooser_enter_details_filter_func, self); - - gtk_assistant_set_page_title (GTK_ASSISTANT (self), - priv->enter_or_create_page, _("Enter your account details")); - } - else - { - gtk_label_set_label (GTK_LABEL (priv->first_label), - _("What kind of chat account do you want to create?")); - /* gtk_label_set_label (GTK_LABEL (priv->second_label), - _("You can register other accounts, or setup " - "an existing one at any time from the Edit menu.")); - */ - gtk_label_set_label (GTK_LABEL (priv->second_label), - _("Do you want to create other chat accounts?")); - empathy_protocol_chooser_set_visible ( - EMPATHY_PROTOCOL_CHOOSER (priv->chooser), - account_assistant_chooser_create_account_filter_func, self); - - gtk_assistant_set_page_title (GTK_ASSISTANT (self), - priv->enter_or_create_page, - _("Enter the details for the new account")); - } - - g_signal_connect (priv->chooser, "changed", - G_CALLBACK (account_assistant_protocol_changed_cb), self); - - /* trigger show the first account widget */ - account_assistant_protocol_changed_cb (GTK_COMBO_BOX (priv->chooser), self); -} - -static gint -account_assistant_page_forward_func (gint current_page, - gpointer user_data) -{ - EmpathyAccountAssistant *self = user_data; - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - gint retval; - - retval = current_page; - - if (current_page == PAGE_INTRO) - { - if (priv->first_resp == RESPONSE_ENTER_ACCOUNT || - priv->first_resp == RESPONSE_CREATE_ACCOUNT) - retval = PAGE_ENTER_CREATE; - else if (priv->first_resp == RESPONSE_IMPORT) - retval = PAGE_IMPORT; - else if (priv->first_resp == RESPONSE_SALUT_ONLY) - retval = PAGE_SALUT; - } - else if (current_page == PAGE_IMPORT) - { - if (priv->display_salut_page) - retval = PAGE_SALUT; - else - /* Don't go forward */ - retval = -1; - } - else if (current_page == PAGE_SALUT) - { - /* Don't go forward */ - retval = -1; - } - else if (current_page >= PAGE_ENTER_CREATE) - { - if (priv->create_enter_resp == RESPONSE_CREATE_AGAIN) - { - priv->enter_create_forward = TRUE; - retval = current_page; - } - else if (priv->display_salut_page) - { - retval = PAGE_SALUT; - } - else - { - /* Don't go forward */ - retval = -1; - } - } - - return retval; -} - -static void -update_intro_page_buttons (EmpathyAccountAssistant *self) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - GtkWidget *intro_page; - - intro_page = gtk_assistant_get_nth_page (GTK_ASSISTANT (self), - PAGE_INTRO); - - if (priv->first_resp == RESPONSE_SALUT_ONLY && - !priv->display_salut_page) - gtk_assistant_set_page_type (GTK_ASSISTANT (self), intro_page, - GTK_ASSISTANT_PAGE_SUMMARY); - else - gtk_assistant_set_page_type (GTK_ASSISTANT (self), intro_page, - GTK_ASSISTANT_PAGE_INTRO); -} - -static void -account_assistant_radio_choice_toggled_cb (GtkToggleButton *button, - EmpathyAccountAssistant *self) -{ - FirstPageResponse response; - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - - response = GPOINTER_TO_INT (g_object_get_data - (G_OBJECT (button), "response")); - - priv->first_resp = response; - - update_intro_page_buttons (self); -} - -static GtkWidget * -account_assistant_build_introduction_page (EmpathyAccountAssistant *self) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - GtkWidget *main_vbox, *hbox_1, *w, *vbox_1; - GtkWidget *radio = NULL; - GdkPixbuf *pix; - const gchar *str; - - main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); - gtk_widget_show (main_vbox); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); - - hbox_1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox_1, TRUE, TRUE, 0); - gtk_widget_show (hbox_1); - - w = gtk_label_new ( - _("With Empathy you can chat with people " - "online nearby and with friends and colleagues " - "who use Google Talk, AIM, Windows Live " - "and many other chat programs. With a microphone " - "or a webcam you can also have audio or video calls.")); - gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); - gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_box_pack_start (GTK_BOX (hbox_1), w, FALSE, FALSE, 0); - gtk_widget_show (w); - - pix = empathy_pixbuf_from_icon_name_sized ("empathy", 80); - w = gtk_image_new_from_pixbuf (pix); - gtk_box_pack_start (GTK_BOX (hbox_1), w, FALSE, FALSE, 6); - gtk_widget_show (w); - - g_object_unref (pix); - - w = gtk_label_new (_("Do you have an account you've been using " - "with another chat program?")); - gtk_misc_set_alignment (GTK_MISC (w), 0, 0); - gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); - gtk_widget_show (w); - - w = gtk_alignment_new (0, 0, 0, 0); - gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), w, TRUE, TRUE, 0); - gtk_widget_show (w); - - vbox_1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_box_set_homogeneous (GTK_BOX (vbox_1), TRUE); - gtk_container_add (GTK_CONTAINER (w), vbox_1); - gtk_widget_show (vbox_1); - - if (empathy_import_accounts_to_import ()) - { - hbox_1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - gtk_box_pack_start (GTK_BOX (vbox_1), hbox_1, TRUE, TRUE, 0); - gtk_widget_show (hbox_1); - - radio = gtk_radio_button_new_with_label (NULL, - _("Yes, import my account details from ")); - gtk_box_pack_start (GTK_BOX (hbox_1), radio, TRUE, TRUE, 0); - g_object_set_data (G_OBJECT (radio), "response", - GINT_TO_POINTER (RESPONSE_IMPORT)); - gtk_widget_show (radio); - - w = gtk_combo_box_text_new (); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (w), "Pidgin"); - gtk_box_pack_start (GTK_BOX (hbox_1), w, TRUE, TRUE, 0); - gtk_combo_box_set_active (GTK_COMBO_BOX (w), 0); - gtk_widget_show (w); - - g_signal_connect (radio, "clicked", - G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); - priv->first_resp = RESPONSE_IMPORT; - } - else - { - priv->first_resp = RESPONSE_ENTER_ACCOUNT; - } - - str = _("Yes, I'll enter my account details now"); - - if (radio == NULL) - { - radio = gtk_radio_button_new_with_label (NULL, str); - w = radio; - } - else - { - w = gtk_radio_button_new_with_label_from_widget ( - GTK_RADIO_BUTTON (radio), str); - } - - gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0); - g_object_set_data (G_OBJECT (w), "response", - GINT_TO_POINTER (RESPONSE_ENTER_ACCOUNT)); - gtk_widget_show (w); - - g_signal_connect (w, "clicked", - G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); - - w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), - _("No, I want a new account")); - gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0); - g_object_set_data (G_OBJECT (w), "response", - GINT_TO_POINTER (RESPONSE_CREATE_ACCOUNT)); - gtk_widget_show (w); - - g_signal_connect (w, "clicked", - G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); - - w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), - _("No, I just want to see people online nearby for now")); - gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0); - g_object_set_data (G_OBJECT (w), "response", - GINT_TO_POINTER (RESPONSE_SALUT_ONLY)); - gtk_widget_show (w); - - g_signal_connect (w, "clicked", - G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); - - return main_vbox; -} - -static GtkWidget * -account_assistant_build_import_page (EmpathyAccountAssistant *self) -{ - GtkWidget *main_vbox, *w, *import; - EmpathyImportWidget *iw; - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - - main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); - w = gtk_label_new (_("Select the accounts you want to import:")); - gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); - gtk_widget_show (w); - gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 6); - - w = gtk_alignment_new (0, 0, 1, 1); - gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), w, TRUE, TRUE, 0); - gtk_widget_show (w); - - /* NOTE: this is hardcoded as we support pidgin only */ - iw = empathy_import_widget_new (EMPATHY_IMPORT_APPLICATION_PIDGIN); - import = empathy_import_widget_get_widget (iw); - gtk_container_add (GTK_CONTAINER (w), import); - gtk_widget_show (import); - - priv->iw = iw; - - gtk_widget_show (main_vbox); - - return main_vbox; -} - -static void -account_assistant_radio_create_again_clicked_cb (GtkButton *button, - EmpathyAccountAssistant *self) -{ - CreateEnterPageResponse response; - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - - response = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), - "response")); - - priv->create_enter_resp = response; - - update_create_page_buttons (self); -} - -static GtkWidget * -account_assistant_build_enter_or_create_page (EmpathyAccountAssistant *self) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - GtkWidget *main_vbox, *w, *chooser, *vbox, *hbox, *radio; - - main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); - gtk_widget_show (main_vbox); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - w = gtk_label_new (NULL); - gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); - gtk_widget_show (w); - priv->first_label = w; - - w = gtk_alignment_new (0, 0, 0, 0); - gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); - gtk_widget_show (w); - - chooser = empathy_protocol_chooser_new (); - gtk_box_pack_start (GTK_BOX (hbox), chooser, FALSE, FALSE, 0); - gtk_widget_show (chooser); - priv->chooser = chooser; - - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); - gtk_box_pack_end (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); - gtk_widget_show (vbox); - - w = gtk_label_new (NULL); - gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0); - gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); - gtk_widget_show (w); - priv->second_label = w; - - w = gtk_alignment_new (0, 0, 0, 0); - gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); - gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0); - gtk_widget_show (w); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - gtk_container_add (GTK_CONTAINER (w), hbox); - gtk_widget_show (hbox); - - radio = gtk_radio_button_new_with_label (NULL, _("Yes")); - gtk_box_pack_start (GTK_BOX (hbox), radio, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (radio), "response", - GINT_TO_POINTER (RESPONSE_CREATE_AGAIN)); - gtk_widget_show (radio); - - w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), - _("No, that's all for now")); - gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (w), "response", - GINT_TO_POINTER (RESPONSE_CREATE_STOP)); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), TRUE); - priv->create_enter_resp = RESPONSE_CREATE_STOP; - priv->create_again_radio = w; - gtk_widget_show (w); - - g_signal_connect (w, "clicked", - G_CALLBACK (account_assistant_radio_create_again_clicked_cb), self); - g_signal_connect (radio, "clicked", - G_CALLBACK (account_assistant_radio_create_again_clicked_cb), self); - - return main_vbox; -} - -static void -account_assistant_close_cb (GtkAssistant *assistant, - gpointer user_data) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (assistant); - - if (priv->is_creating) - return; - - gtk_widget_destroy (GTK_WIDGET (assistant)); -} - -static void -impl_signal_apply (GtkAssistant *assistant) -{ - EmpathyAccountAssistant *self = EMPATHY_ACCOUNT_ASSISTANT (assistant); - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - gint current_page; - - current_page = gtk_assistant_get_current_page (assistant); - - if (current_page == PAGE_SALUT) - { - if (priv->create_salut_account) - /* create_salut_account_settings() already set the display name of the - * account so there is no need to set it again. */ - account_assistant_apply_account_and_finish (self, priv->salut_settings, - FALSE); - return; - } - else if (current_page >= PAGE_ENTER_CREATE && - priv->settings != NULL && - empathy_account_settings_is_valid (priv->settings)) - { - account_assistant_apply_account_and_finish (self, priv->settings, TRUE); - g_object_unref (priv->settings); - priv->settings = NULL; - } - else if (current_page == PAGE_IMPORT) - { - empathy_import_widget_add_selected_accounts (priv->iw); - } -} - -static void -impl_signal_cancel (GtkAssistant *assistant) -{ - gtk_widget_destroy (GTK_WIDGET (assistant)); -} - -static void -impl_signal_prepare (GtkAssistant *assistant, - GtkWidget *current_page) -{ - EmpathyAccountAssistant *self = EMPATHY_ACCOUNT_ASSISTANT (assistant); - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - gint current_idx; - - /* check from which page we are coming from */ - if (priv->current_page_id == PAGE_IMPORT) - empathy_import_widget_add_selected_accounts (priv->iw); - - current_idx = gtk_assistant_get_current_page (assistant); - priv->current_page_id = current_idx; - - if (current_idx >= PAGE_ENTER_CREATE) - { - if (!priv->enter_create_forward && current_idx != PAGE_SALUT) - { - account_assistant_finish_enter_or_create_page (self, - priv->first_resp == RESPONSE_ENTER_ACCOUNT ? - TRUE : FALSE); - } - else - { - priv->enter_create_forward = FALSE; - } - - if (priv->settings != NULL && - empathy_account_settings_is_valid (priv->settings)) - { - account_assistant_apply_account_and_finish (self, priv->settings, - TRUE); - g_object_unref (priv->settings); - priv->settings = NULL; - } - } -} - -static void -do_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (object); - - switch (property_id) - { - case PROP_PARENT: - g_value_set_object (value, priv->parent_window); - break; - case PROP_CONNECTION_MGRS: - g_value_set_object (value, priv->connection_mgrs); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -do_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (object); - - switch (property_id) - { - case PROP_PARENT: - priv->parent_window = g_value_get_object (value); - break; - case PROP_CONNECTION_MGRS: - priv->connection_mgrs = g_value_dup_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -do_dispose (GObject *obj) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (obj); - - if (priv->dispose_run) - return; - - priv->dispose_run = TRUE; - - if (priv->settings != NULL) - { - g_object_unref (priv->settings); - priv->settings = NULL; - } - - g_object_unref (priv->account_mgr); - priv->account_mgr = NULL; - - g_object_unref (priv->connection_mgrs); - priv->connection_mgrs = NULL; - - if (G_OBJECT_CLASS (empathy_account_assistant_parent_class)->dispose != NULL) - G_OBJECT_CLASS (empathy_account_assistant_parent_class)->dispose (obj); -} - -static void -empathy_account_assistant_class_init (EmpathyAccountAssistantClass *klass) -{ - GObjectClass *oclass = G_OBJECT_CLASS (klass); - GtkAssistantClass *gtkclass = GTK_ASSISTANT_CLASS (klass); - GParamSpec *param_spec; - - oclass->get_property = do_get_property; - oclass->set_property = do_set_property; - oclass->constructed = do_constructed; - oclass->dispose = do_dispose; - - gtkclass->apply = impl_signal_apply; - gtkclass->prepare = impl_signal_prepare; - gtkclass->cancel = impl_signal_cancel; - - param_spec = g_param_spec_object ("parent-window", - "parent-window", "The parent window", - GTK_TYPE_WINDOW, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (oclass, PROP_PARENT, param_spec); - - param_spec = g_param_spec_object ("connection-managers", - "connection-managers", "A EmpathyConnectionManagers", - EMPATHY_TYPE_CONNECTION_MANAGERS, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (oclass, PROP_CONNECTION_MGRS, param_spec); - - g_type_class_add_private (klass, sizeof (EmpathyAccountAssistantPriv)); -} - -static void -create_salut_check_box_toggled_cb (GtkWidget *widget, - EmpathyAccountAssistant *self) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - gboolean sensitive; - gboolean page_valid; - - sensitive = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); - - gtk_widget_set_sensitive (priv->salut_account_widget, sensitive); - - if (!sensitive) - { - page_valid = TRUE; - priv->create_salut_account = FALSE; - } - else - { - /* page is complete if the account is valid */ - page_valid = empathy_account_settings_is_valid (priv->salut_settings); - priv->create_salut_account = TRUE; - } - - gtk_assistant_set_page_complete (GTK_ASSISTANT (self), priv->salut_page, - page_valid); -} - -static void -account_assistant_salut_handle_apply_cb (EmpathyAccountWidget *widget_object, - gboolean is_valid, - EmpathyAccountAssistant *self) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - - gtk_assistant_set_page_complete (GTK_ASSISTANT (self), - priv->salut_page, is_valid); -} - -static GtkWidget * -account_assistant_build_salut_page (EmpathyAccountAssistant *self) -{ - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - GtkWidget *main_vbox, *hbox_1, *w; - GdkPixbuf *pix; - EmpathyAccountSettings *settings; - GtkWidget *account_widget; - EmpathyAccountWidget *widget_object; - gchar *markup; - - main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); - gtk_widget_show (main_vbox); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); - - hbox_1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox_1, TRUE, TRUE, 0); - gtk_widget_show (hbox_1); - - w = gtk_label_new (NULL); - markup = g_strdup_printf ("%s (<span style=\"italic\">%s</span>).", - _("Empathy can automatically discover and chat with the people " - "connected on the same network as you. " - "If you want to use this feature, please check that the " - "details below are correct. " - "You can easily change these details later or disable this feature " - "by using the 'Accounts' dialog"), - _("Edit->Accounts")); - gtk_label_set_markup (GTK_LABEL (w), markup); - g_free (markup); - gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); - gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_box_pack_start (GTK_BOX (hbox_1), w, FALSE, FALSE, 0); - gtk_widget_show (w); - - pix = empathy_pixbuf_from_icon_name_sized ("im-local-xmpp", 80); - w = gtk_image_new_from_pixbuf (pix); - gtk_box_pack_start (GTK_BOX (hbox_1), w, FALSE, FALSE, 6); - gtk_widget_show (w); - - g_object_unref (pix); - - w = gtk_check_button_new_with_mnemonic ( - _("I do _not want to enable this feature for now")); - gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); - g_signal_connect (w, "toggled", - G_CALLBACK (create_salut_check_box_toggled_cb), self); - gtk_widget_show (w); - - w = gtk_alignment_new (0, 0, 0, 0); - gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), w, TRUE, TRUE, 0); - gtk_widget_show (w); - - settings = create_salut_account_settings (); - - widget_object = empathy_account_widget_new_for_protocol (settings, TRUE); - account_widget = empathy_account_widget_get_widget (widget_object); - - priv->salut_settings = settings; - priv->salut_account_widget = account_widget; - - g_signal_connect (widget_object, "handle-apply", - G_CALLBACK (account_assistant_salut_handle_apply_cb), self); - - gtk_box_pack_start (GTK_BOX (main_vbox), account_widget, - FALSE, FALSE, 0); - gtk_widget_show (account_widget); - - return main_vbox; -} - -static GtkWidget * -account_assistant_build_salut_error_page (EmpathyAccountAssistant *self) -{ - GtkWidget *vbox; - gchar *markup; - - markup = g_strdup_printf ("%s (<span style=\"italic\">%s</span>).", - _("You won't be able to chat with people connected to your local " - "network, as telepathy-salut is not installed. If you want to enable " - "this feature, please install the telepathy-salut package and create " - "a People Nearby account from the Accounts dialog"), - _("Edit->Accounts")); - - vbox = build_error_vbox (_("telepathy-salut not installed"), markup); - g_free (markup); - return vbox; -} - -static void -account_mgr_prepare_cb (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - EmpathyAccountAssistant *self = user_data; - EmpathyAccountAssistantPriv *priv = GET_PRIV (self); - TpAccountManager *manager = TP_ACCOUNT_MANAGER (source_object); - GError *error = NULL; - - if (!tp_proxy_prepare_finish (manager, result, &error)) - { - DEBUG ("Failed to prepare account manager: %s", error->message); - g_error_free (error); - return; - } - - if (!should_create_salut_account (manager)) - { - DEBUG ("No need to create a Salut account"); - priv->display_salut_page = FALSE; - - update_intro_page_buttons (self); - - gtk_assistant_set_page_type (GTK_ASSISTANT (self), priv->import_page, - GTK_ASSISTANT_PAGE_CONFIRM); - - update_create_page_buttons (self); - } -} - -static void -empathy_account_assistant_init (EmpathyAccountAssistant *self) -{ - EmpathyAccountAssistantPriv *priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_ACCOUNT_ASSISTANT, - EmpathyAccountAssistantPriv); - self->priv = priv; - - gtk_window_set_title (GTK_WINDOW (self), - _("Messaging and VoIP Accounts Assistant")); - - priv->account_mgr = tp_account_manager_dup (); -} - -static void -do_constructed (GObject *object) -{ - GtkAssistant *assistant = GTK_ASSISTANT (object); - EmpathyAccountAssistant *self = EMPATHY_ACCOUNT_ASSISTANT (object); - EmpathyAccountAssistantPriv *priv = GET_PRIV (object); - GtkWidget *page; - - /* set us as transient for the parent window if any */ - if (priv->parent_window) - gtk_window_set_transient_for (GTK_WINDOW (object), - priv->parent_window); - - /* set the dialog hint, so this will be centered over the parent window */ - gtk_window_set_type_hint (GTK_WINDOW (object), GDK_WINDOW_TYPE_HINT_DIALOG); - - g_assert (priv->connection_mgrs != NULL); - g_assert (empathy_connection_managers_is_ready (priv->connection_mgrs)); - - g_signal_connect (self, "close", - G_CALLBACK (account_assistant_close_cb), NULL); - - gtk_assistant_set_forward_page_func (assistant, - account_assistant_page_forward_func, self, NULL); - - /* first page (introduction) */ - page = account_assistant_build_introduction_page (self); - gtk_assistant_append_page (assistant, page); - gtk_assistant_set_page_title (assistant, page, - _("Welcome to Empathy")); - gtk_assistant_set_page_type (assistant, page, - GTK_ASSISTANT_PAGE_INTRO); - gtk_assistant_set_page_complete (assistant, page, TRUE); - - /* second page (import accounts) */ - page = account_assistant_build_import_page (self); - gtk_assistant_append_page (assistant, page); - gtk_assistant_set_page_title (assistant, page, - _("Import your existing accounts")); - gtk_assistant_set_page_complete (assistant, page, TRUE); - gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONTENT); - priv->import_page = page; - - /* third page (enter account details) */ - page = account_assistant_build_enter_or_create_page (self); - gtk_assistant_append_page (assistant, page); - gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONTENT); - priv->enter_or_create_page = page; - - /* fourth page (salut details) */ - if (empathy_connection_managers_get_cm (priv->connection_mgrs, "salut") - != NULL) - { - page = account_assistant_build_salut_page (self); - gtk_assistant_append_page (assistant, page); - gtk_assistant_set_page_title (assistant, page, - _("Please enter personal details")); - gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONFIRM); - - priv->create_salut_account = TRUE; - - if (empathy_account_settings_is_valid (priv->salut_settings)) - { - gtk_assistant_set_page_complete (GTK_ASSISTANT (self), - page, TRUE); - } - } - else - { - page = account_assistant_build_salut_error_page (self); - gtk_assistant_append_page (assistant, page); - gtk_assistant_set_page_title (assistant, page, _("An error occurred")); - gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_SUMMARY); - - priv->create_salut_account = FALSE; - } - - priv->salut_page = page; - priv->display_salut_page = TRUE; - - tp_proxy_prepare_async (priv->account_mgr, NULL, - account_mgr_prepare_cb, self); - - gtk_window_set_resizable (GTK_WINDOW (self), FALSE); -} - -GtkWidget * -empathy_account_assistant_show (GtkWindow *window, - EmpathyConnectionManagers *connection_mgrs) -{ - static GtkWidget *dialog = NULL; - - if (dialog == NULL) - { - dialog = g_object_new (EMPATHY_TYPE_ACCOUNT_ASSISTANT, - "parent-window", window, - "connection-managers", connection_mgrs, - NULL); - g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer *) &dialog); - } - - gtk_window_present (GTK_WINDOW (dialog)); - - return dialog; -} - - diff --git a/src/empathy-account-assistant.h b/src/empathy-account-assistant.h deleted file mode 100644 index d99475fe3..000000000 --- a/src/empathy-account-assistant.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2009 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> - */ - -/* empathy-account-assistant.h */ - -#ifndef __EMPATHY_ACCOUNT_ASSISTANT_H__ -#define __EMPATHY_ACCOUNT_ASSISTANT_H__ - -#include <glib-object.h> -#include <gtk/gtk.h> - -#include <libempathy/empathy-connection-managers.h> - -G_BEGIN_DECLS - -#define EMPATHY_TYPE_ACCOUNT_ASSISTANT empathy_account_assistant_get_type() -#define EMPATHY_ACCOUNT_ASSISTANT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_ACCOUNT_ASSISTANT,\ - EmpathyAccountAssistant)) -#define EMPATHY_ACCOUNT_ASSISTANT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_ACCOUNT_ASSISTANT,\ - EmpathyAccountAssistantClass)) -#define EMPATHY_IS_ACCOUNT_ASSISTANT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_ACCOUNT_ASSISTANT)) -#define EMPATHY_IS_ACCOUNT_ASSISTANT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_ACCOUNT_ASSISTANT)) -#define EMPATHY_ACCOUNT_ASSISTANT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_ACCOUNT_ASSISTANT,\ - EmpathyAccountAssistantClass)) - -typedef struct { - GtkAssistant parent; - - /* private */ - gpointer priv; -} EmpathyAccountAssistant; - -typedef struct { - GtkAssistantClass parent_class; -} EmpathyAccountAssistantClass; - -GType empathy_account_assistant_get_type (void); - -GtkWidget *empathy_account_assistant_show (GtkWindow *parent, - EmpathyConnectionManagers *connection_mgrs); - -G_END_DECLS - -#endif /* __EMPATHY_ACCOUNT_ASSISTANT_H__ */ diff --git a/src/empathy-accounts-common.c b/src/empathy-accounts-common.c index 88d14c321..f6bb40278 100644 --- a/src/empathy-accounts-common.c +++ b/src/empathy-accounts-common.c @@ -41,8 +41,6 @@ #include "empathy-accounts-common.h" #include "empathy-accounts-dialog.h" -#include "empathy-account-assistant.h" -#include "empathy-auto-salut-account-helper.h" #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT #include <libempathy/empathy-debug.h> @@ -82,13 +80,16 @@ empathy_accounts_has_accounts (TpAccountManager *manager) return has_accounts; } -static void -do_show_accounts_ui (TpAccountManager *manager, +void +empathy_accounts_show_accounts_ui (TpAccountManager *manager, TpAccount *account, GApplication *app) { static GtkWidget *accounts_window = NULL; + g_return_if_fail (TP_IS_ACCOUNT_MANAGER (manager)); + g_return_if_fail (!account || TP_IS_ACCOUNT (account)); + if (accounts_window == NULL) { accounts_window = empathy_accounts_dialog_show (NULL, account); @@ -99,63 +100,3 @@ do_show_accounts_ui (TpAccountManager *manager, gtk_window_present (GTK_WINDOW (accounts_window)); } - -static GtkWidget * -show_account_assistant (EmpathyConnectionManagers *connection_mgrs, - GApplication *app) -{ - GtkWidget *assistant; - - assistant = empathy_account_assistant_show (NULL, connection_mgrs); - - gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (assistant)); - - return assistant; -} - -static void -connection_managers_prepare_for_accounts (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - EmpathyConnectionManagers *cm_mgr = EMPATHY_CONNECTION_MANAGERS (source); - GApplication *app = user_data; - - if (!empathy_connection_managers_prepare_finish (cm_mgr, result, NULL)) - goto out; - - show_account_assistant (cm_mgr, app); - DEBUG ("would show the account assistant"); - -out: - g_object_unref (cm_mgr); - g_application_release (app); -} - -void -empathy_accounts_show_accounts_ui (TpAccountManager *manager, - TpAccount *account, - gboolean assistant, - GApplication *app) -{ - g_return_if_fail (TP_IS_ACCOUNT_MANAGER (manager)); - g_return_if_fail (!account || TP_IS_ACCOUNT (account)); - - if ((empathy_accounts_has_non_salut_accounts (manager) && !assistant) || - account != NULL) - { - do_show_accounts_ui (manager, account, app); - } - else - { - EmpathyConnectionManagers *cm_mgr; - - cm_mgr = empathy_connection_managers_dup_singleton (); - - /* Hold the application while preparing cm_mgr */ - g_application_hold (app); - - empathy_connection_managers_prepare_async (cm_mgr, - connection_managers_prepare_for_accounts, app); - } -} diff --git a/src/empathy-accounts-common.h b/src/empathy-accounts-common.h index f9294fbd2..39d094d22 100644 --- a/src/empathy-accounts-common.h +++ b/src/empathy-accounts-common.h @@ -28,7 +28,6 @@ gboolean empathy_accounts_has_accounts (TpAccountManager *manager); void empathy_accounts_show_accounts_ui (TpAccountManager *manager, TpAccount *account, - gboolean assistant, GApplication *app); #endif /* __EMPATHY_ACCOUNTS_COMMON_H__ */ diff --git a/src/empathy-accounts-dialog.c b/src/empathy-accounts-dialog.c index 0e33de2a6..b2b57dec1 100644 --- a/src/empathy-accounts-dialog.c +++ b/src/empathy-accounts-dialog.c @@ -51,8 +51,10 @@ #include <libempathy-gtk/empathy-cell-renderer-activatable.h> #include <libempathy-gtk/empathy-contact-widget.h> #include <libempathy-gtk/empathy-images.h> +#include <libempathy-gtk/empathy-local-xmpp-assistant-widget.h> #include <libempathy-gtk/empathy-new-account-dialog.h> +#include "empathy-accounts-common.h" #include "empathy-accounts-dialog.h" #include "empathy-import-dialog.h" #include "empathy-import-utils.h" @@ -78,7 +80,8 @@ G_DEFINE_TYPE (EmpathyAccountsDialog, empathy_accounts_dialog, GTK_TYPE_DIALOG); enum { NOTEBOOK_PAGE_ACCOUNT = 0, - NOTEBOOK_PAGE_LOADING + NOTEBOOK_PAGE_LOADING, + NOTEBOOK_PAGE_NO_PROTOCOL }; typedef struct { @@ -91,7 +94,6 @@ typedef struct { GtkWidget *image_status; GtkWidget *throbber; GtkWidget *enabled_switch; - GtkWidget *frame_no_protocol; GtkWidget *treeview; @@ -99,8 +101,6 @@ typedef struct { GtkWidget *button_remove; GtkWidget *button_import; - GtkWidget *hbox_protocol; - GtkWidget *image_type; GtkWidget *label_name; GtkWidget *label_type; @@ -161,21 +161,13 @@ enum { static EmpathyAccountSettings * accounts_dialog_model_get_selected_settings ( EmpathyAccountsDialog *dialog); -static gboolean accounts_dialog_get_settings_iter ( - EmpathyAccountsDialog *dialog, - EmpathyAccountSettings *settings, - GtkTreeIter *iter); - static void accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog); static void accounts_dialog_update_settings (EmpathyAccountsDialog *dialog, EmpathyAccountSettings *settings); -static void accounts_dialog_add (EmpathyAccountsDialog *dialog, - EmpathyAccountSettings *settings); - static void accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog, - EmpathyAccountSettings *settings); + TpAccount *account); static void accounts_dialog_connection_changed_cb (TpAccount *account, guint old_status, @@ -220,6 +212,9 @@ accounts_dialog_status_infobar_set_message (EmpathyAccountsDialog *dialog, message_markup = g_markup_printf_escaped ("<i>%s</i>", message); gtk_label_set_markup (GTK_LABEL (priv->label_status), message_markup); + + gtk_widget_set_tooltip_text (priv->label_status, message); + g_free (message_markup); } @@ -940,12 +935,16 @@ accounts_dialog_button_add_clicked_cb (GtkWidget *button, if (response == GTK_RESPONSE_OK) { EmpathyAccountSettings *settings; + TpAccount *account; settings = empathy_new_account_dialog_get_settings ( EMPATHY_NEW_ACCOUNT_DIALOG (dialog)); - accounts_dialog_add (self, settings); - accounts_dialog_model_set_selected (self, settings); + /* The newly created account has already been added by + * accounts_dialog_account_validity_changed_cb so we just + * have to select it. */ + account = empathy_account_settings_get_account (settings); + accounts_dialog_model_set_selected (self, account); } gtk_widget_destroy (dialog); @@ -984,28 +983,19 @@ accounts_dialog_update_settings (EmpathyAccountsDialog *dialog, return; } - if (empathy_connection_managers_get_cms_num (priv->cms) > 0) - { - /* We have no account configured but we have some - * profiles installed. The user obviously wants to add - * an account. Click on the Add button for him. */ - accounts_dialog_button_add_clicked_cb (priv->button_add, - dialog); - return; - } /* No account and no profile, warn the user */ gtk_widget_hide (priv->vbox_details); - gtk_widget_show (priv->frame_no_protocol); gtk_widget_set_sensitive (priv->button_add, FALSE); + + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook_account), + NOTEBOOK_PAGE_NO_PROTOCOL); return; } /* We have an account selected, destroy old settings and create a new * one for the account selected */ - gtk_widget_hide (priv->frame_no_protocol); gtk_widget_show (priv->vbox_details); - gtk_widget_hide (priv->hbox_protocol); if (priv->dialog_content) { @@ -1585,41 +1575,6 @@ accounts_dialog_model_setup (EmpathyAccountsDialog *dialog) } static gboolean -accounts_dialog_get_settings_iter (EmpathyAccountsDialog *dialog, - EmpathyAccountSettings *settings, - GtkTreeIter *iter) -{ - GtkTreeView *view; - GtkTreeModel *model; - gboolean ok; - EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - - /* Update the status in the model */ - view = GTK_TREE_VIEW (priv->treeview); - model = gtk_tree_view_get_model (view); - - for (ok = gtk_tree_model_get_iter_first (model, iter); - ok; - ok = gtk_tree_model_iter_next (model, iter)) - { - EmpathyAccountSettings *this_settings; - gboolean equal; - - gtk_tree_model_get (model, iter, - COL_ACCOUNT_SETTINGS, &this_settings, - -1); - - equal = (this_settings == settings); - g_object_unref (this_settings); - - if (equal) - return TRUE; - } - - return FALSE; -} - -static gboolean accounts_dialog_get_account_iter (EmpathyAccountsDialog *dialog, TpAccount *account, GtkTreeIter *iter) @@ -1637,15 +1592,15 @@ accounts_dialog_get_account_iter (EmpathyAccountsDialog *dialog, ok; ok = gtk_tree_model_iter_next (model, iter)) { - EmpathyAccountSettings *settings; + TpAccount *this_account; gboolean equal; gtk_tree_model_get (model, iter, - COL_ACCOUNT_SETTINGS, &settings, + COL_ACCOUNT, &this_account, -1); - equal = empathy_account_settings_has_account (settings, account); - g_object_unref (settings); + equal = (this_account == account); + g_object_unref (this_account); if (equal) return TRUE; @@ -1678,11 +1633,11 @@ select_and_scroll_to_iter (EmpathyAccountsDialog *dialog, static void accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog, - EmpathyAccountSettings *settings) + TpAccount *account) { GtkTreeIter iter; - if (accounts_dialog_get_settings_iter (dialog, settings, &iter)) + if (accounts_dialog_get_account_iter (dialog, account, &iter)) select_and_scroll_to_iter (dialog, &iter); } @@ -1781,27 +1736,6 @@ finally: } static void -accounts_dialog_add (EmpathyAccountsDialog *dialog, - EmpathyAccountSettings *settings) -{ - GtkTreeModel *model; - GtkTreeIter iter; - const gchar *name; - EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); - name = empathy_account_settings_get_display_name (settings); - - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_NAME, name, - COL_STATUS, TP_CONNECTION_STATUS_DISCONNECTED, - COL_ACCOUNT_SETTINGS, settings, - -1); -} - -static void accounts_dialog_connection_changed_cb (TpAccount *account, guint old_status, guint current, @@ -1925,6 +1859,7 @@ accounts_dialog_add_account (EmpathyAccountsDialog *dialog, const gchar *name; EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); gboolean selected = FALSE; + GtkTreeSelection *selection; model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); status = tp_account_get_connection_status (account, NULL); @@ -1932,15 +1867,18 @@ accounts_dialog_add_account (EmpathyAccountsDialog *dialog, settings = empathy_account_settings_new_for_account (account); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + if (!accounts_dialog_get_account_iter (dialog, account, &iter)) { + /* Select the account if it's the first added */ + if (gtk_tree_selection_count_selected_rows (selection) == 0) + selected = TRUE; + gtk_list_store_append (GTK_LIST_STORE (model), &iter); } else { - GtkTreeSelection *selection; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); selected = gtk_tree_selection_iter_is_selected (selection, &iter); } @@ -1980,31 +1918,12 @@ accounts_dialog_add_account (EmpathyAccountsDialog *dialog, } static void -account_prepare_cb (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (user_data); - TpAccount *account = TP_ACCOUNT (source_object); - GError *error = NULL; - - if (!tp_proxy_prepare_finish (account, result, &error)) - { - DEBUG ("Failed to prepare account: %s", error->message); - g_error_free (error); - return; - } - - accounts_dialog_add_account (dialog, account); -} - -static void accounts_dialog_account_validity_changed_cb (TpAccountManager *manager, TpAccount *account, gboolean valid, EmpathyAccountsDialog *dialog) { - tp_proxy_prepare_async (account, NULL, account_prepare_cb, dialog); + accounts_dialog_add_account (dialog, account); } static void @@ -2083,15 +2002,24 @@ accounts_dialog_account_enabled_cb (TpAccountManager *manager, enable_or_disable_account (dialog, account, TRUE); } -static void -accounts_dialog_button_import_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +static GtkWidget * +display_import_dialog (EmpathyAccountsDialog *dialog) { + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); GtkWidget *import_dialog; import_dialog = empathy_import_dialog_new (GTK_WINDOW (dialog), - FALSE); + FALSE, priv->cms); gtk_widget_show (import_dialog); + + return import_dialog; +} + +static void +accounts_dialog_button_import_clicked_cb (GtkWidget *button, + EmpathyAccountsDialog *dialog) +{ + display_import_dialog (dialog); } static void @@ -2127,6 +2055,85 @@ accounts_dialog_set_selected_account (EmpathyAccountsDialog *dialog, } static void +salut_valid_cb (GtkWidget *widget, + gboolean valid, + GtkWidget *button) +{ + gtk_widget_set_sensitive (button, valid); +} + +static void +maybe_show_salut_dialog (EmpathyAccountsDialog *self) +{ + EmpathyAccountsDialogPriv *priv = GET_PRIV (self); + GtkWidget *dialog, *widget, *content, *button; + gint response; + + if (!empathy_local_xmpp_assistant_widget_should_create_account ( + priv->account_manager)) + return; + + widget = empathy_local_xmpp_assistant_widget_new (); + gtk_widget_show (widget); + + dialog = gtk_dialog_new (); + + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Skip"), + GTK_RESPONSE_NO); + + button = gtk_dialog_add_button (GTK_DIALOG (dialog), + _("_Connect"), GTK_RESPONSE_YES); + gtk_widget_set_sensitive (button, FALSE); + + g_signal_connect (widget, "valid", G_CALLBACK (salut_valid_cb), + button); + + content = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + gtk_box_pack_start (GTK_BOX (content), widget, TRUE, TRUE, 0); + + response = gtk_dialog_run (GTK_DIALOG (dialog)); + + if (response == GTK_RESPONSE_YES) + { + empathy_local_xmpp_assistant_widget_create_account ( + EMPATHY_LOCAL_XMPP_ASSISTANT_WIDGET (widget)); + } + + gtk_widget_destroy (dialog); +} + +static void +import_dialog_response_cb (GtkDialog *dialog, + gint response_id, + EmpathyAccountsDialog *self) +{ + maybe_show_salut_dialog (self); +} + +static void +maybe_show_import_dialog (EmpathyAccountsDialog *self) +{ + EmpathyAccountsDialogPriv *priv = GET_PRIV (self); + GtkWidget *dialog; + + if (empathy_accounts_has_non_salut_accounts (priv->account_manager)) + return; + + if (!empathy_import_accounts_to_import ()) + { + maybe_show_salut_dialog (self); + return; + } + + dialog = display_import_dialog (self); + + tp_g_signal_connect_object (dialog, "response", + G_CALLBACK (import_dialog_response_cb), self, 0); +} + +static void finished_loading (EmpathyAccountsDialog *self) { EmpathyAccountsDialogPriv *priv = GET_PRIV (self); @@ -2147,6 +2154,8 @@ finished_loading (EmpathyAccountsDialog *self) gtk_spinner_stop (GTK_SPINNER (priv->spinner)); gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook_account), NOTEBOOK_PAGE_ACCOUNT); + + maybe_show_import_dialog (self); } static void @@ -2289,14 +2298,12 @@ accounts_dialog_build_ui (EmpathyAccountsDialog *dialog) gui = empathy_builder_get_file (filename, "accounts_dialog_hbox", &top_hbox, "vbox_details", &priv->vbox_details, - "frame_no_protocol", &priv->frame_no_protocol, "alignment_settings", &priv->alignment_settings, "alignment_infobar", &priv->alignment_infobar, "treeview", &priv->treeview, "button_add", &priv->button_add, "button_remove", &priv->button_remove, "button_import", &priv->button_import, - "hbox_protocol", &priv->hbox_protocol, "notebook_account", &priv->notebook_account, "alignment_loading", &alig, "accounts_sw", &sw, @@ -2304,8 +2311,6 @@ accounts_dialog_build_ui (EmpathyAccountsDialog *dialog) NULL); g_free (filename); - gtk_widget_set_no_show_all (priv->frame_no_protocol, TRUE); - empathy_builder_connect (gui, dialog, "button_add", "clicked", accounts_dialog_button_add_clicked_cb, "button_remove", "clicked", accounts_dialog_button_remove_clicked_cb, @@ -2387,7 +2392,7 @@ accounts_dialog_build_ui (EmpathyAccountsDialog *dialog) TP_CONNECTION_PRESENCE_TYPE_OFFLINE), GTK_ICON_SIZE_SMALL_TOOLBAR); priv->label_status = gtk_label_new (NULL); - gtk_label_set_line_wrap (GTK_LABEL (priv->label_status), TRUE); + gtk_label_set_ellipsize (GTK_LABEL (priv->label_status), PANGO_ELLIPSIZE_END); gtk_box_pack_start (GTK_BOX (hbox), priv->throbber, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), priv->image_status, FALSE, FALSE, 0); diff --git a/src/empathy-accounts-dialog.ui b/src/empathy-accounts-dialog.ui index 4a1b8bbb3..549a92651 100644 --- a/src/empathy-accounts-dialog.ui +++ b/src/empathy-accounts-dialog.ui @@ -112,31 +112,6 @@ <property name="visible">True</property> <property name="spacing">18</property> <child> - <object class="GtkHBox" id="hbox_protocol"> - <property name="visible">True</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="label_protocol"> - <property name="visible">True</property> - <property name="label" translatable="yes">Protocol:</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> <object class="GtkVBox" id="vbox_details"> <property name="visible">True</property> <property name="spacing">18</property> @@ -173,43 +148,6 @@ <property name="position">1</property> </packing> </child> - <child> - <object class="GtkFrame" id="frame_no_protocol"> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> - <child> - <object class="GtkAlignment" id="alignment21"> - <property name="visible">True</property> - <property name="top_padding">6</property> - <property name="left_padding">12</property> - <child> - <object class="GtkLabel" id="label4"> - <property name="visible">True</property> - <property name="label" translatable="yes">To add a new account, you first have to install a backend for each protocol you want to use.</property> - <property name="wrap">True</property> - </object> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label_no_protocol"> - <property name="visible">True</property> - <property name="label" translatable="yes">No protocol installed</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> - <child> - <placeholder/> - </child> </object> </child> <child type="tab"> @@ -254,6 +192,49 @@ <property name="position">1</property> </packing> </child> + <child> + <object class="GtkVBox" id="vbox_no_protocol"> + <property name="visible">True</property> + <property name="spacing">18</property> + <child> + <object class="GtkFrame" id="frame_no_protocol"> + <property name="label_xalign">0</property> + <property name="shadow_type">none</property> + <child> + <object class="GtkAlignment" id="alignment21"> + <property name="visible">True</property> + <property name="top_padding">6</property> + <property name="left_padding">12</property> + <child> + <object class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">To add a new account, you first have to install a backend for each protocol you want to use.</property> + <property name="wrap">True</property> + </object> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="label_no_protocol"> + <property name="visible">True</property> + <property name="label" translatable="yes">No protocol backends installed</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + </child> </object> <packing> <property name="position">1</property> diff --git a/src/empathy-accounts.c b/src/empathy-accounts.c index 3b25201c5..6b51820f7 100644 --- a/src/empathy-accounts.c +++ b/src/empathy-accounts.c @@ -43,8 +43,6 @@ #include "empathy-accounts.h" #include "empathy-accounts-common.h" #include "empathy-accounts-dialog.h" -#include "empathy-account-assistant.h" -#include "empathy-auto-salut-account-helper.h" #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT #include <libempathy/empathy-debug.h> @@ -54,7 +52,6 @@ static gboolean only_if_needed = FALSE; static gboolean hidden = FALSE; static gchar *selected_account_name = NULL; -static gboolean assistant = FALSE; static void maybe_show_accounts_ui (TpAccountManager *manager, @@ -66,7 +63,7 @@ maybe_show_accounts_ui (TpAccountManager *manager, if (only_if_needed && empathy_accounts_has_non_salut_accounts (manager)) return; - empathy_accounts_show_accounts_ui (manager, NULL, assistant, app); + empathy_accounts_show_accounts_ui (manager, NULL, app); } static TpAccount * @@ -123,7 +120,7 @@ account_manager_ready_for_accounts_cb (GObject *source_object, if (account != NULL) { - empathy_accounts_show_accounts_ui (manager, account, assistant, app); + empathy_accounts_show_accounts_ui (manager, account, app); goto out; } else @@ -191,10 +188,6 @@ local_cmdline (GApplication *app, N_("Initially select given account (eg, " "gabble/jabber/foo_40example_2eorg0)"), N_("<account-id>") }, - { "assistant", 'a', - 0, G_OPTION_ARG_NONE, &assistant, - N_("Show account assistant"), - NULL }, { NULL } }; diff --git a/src/empathy-auto-salut-account-helper.c b/src/empathy-auto-salut-account-helper.c deleted file mode 100644 index 409b6936c..000000000 --- a/src/empathy-auto-salut-account-helper.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2007-2010 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: Xavier Claessens <xclaesse@gmail.com> - * Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> - */ - -#include <config.h> - -#include <glib.h> -#include <glib/gi18n-lib.h> - -#include <telepathy-glib/account-manager.h> -#include <telepathy-glib/util.h> - -#if HAVE_EDS -#include <libebook/e-book.h> -#endif - -#include <libempathy/empathy-account-settings.h> - -#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT -#include <libempathy/empathy-debug.h> - -#include "empathy-auto-salut-account-helper.h" - -/* Salut account creation. The TpAccountManager first argument - * must already be prepared when calling this function. */ -gboolean -should_create_salut_account (TpAccountManager *manager) -{ - gboolean salut_created = FALSE; - GList *accounts, *l; - - accounts = tp_account_manager_get_valid_accounts (manager); - - for (l = accounts; l != NULL; l = g_list_next (l)) - { - TpAccount *account = TP_ACCOUNT (l->data); - - if (!tp_strdiff (tp_account_get_protocol (account), "local-xmpp")) - { - salut_created = TRUE; - break; - } - } - - g_list_free (accounts); - - return !salut_created; -} - -EmpathyAccountSettings * -create_salut_account_settings (void) -{ - EmpathyAccountSettings *settings; -#if HAVE_EDS - EBook *book; - EContact *contact; - gchar *nickname = NULL; - gchar *first_name = NULL; - gchar *last_name = NULL; - gchar *email = NULL; - gchar *jid = NULL; - GError *error = NULL; -#endif - - settings = empathy_account_settings_new ("salut", "local-xmpp", NULL, - _("People nearby")); - -#if HAVE_EDS - /* Get self EContact from EDS */ - if (!e_book_get_self (&contact, &book, &error)) - { - DEBUG ("Failed to get self econtact: %s", error->message); - g_error_free (error); - return settings; - } - - nickname = e_contact_get (contact, E_CONTACT_NICKNAME); - first_name = e_contact_get (contact, E_CONTACT_GIVEN_NAME); - last_name = e_contact_get (contact, E_CONTACT_FAMILY_NAME); - email = e_contact_get (contact, E_CONTACT_EMAIL_1); - jid = e_contact_get (contact, E_CONTACT_IM_JABBER_HOME_1); - - if (!tp_strdiff (nickname, "nickname")) - { - g_free (nickname); - nickname = NULL; - } - - DEBUG ("Salut account created:\nnickname=%s\nfirst-name=%s\n" - "last-name=%s\nemail=%s\njid=%s\n", - nickname, first_name, last_name, email, jid); - - empathy_account_settings_set_string (settings, - "nickname", nickname ? nickname : ""); - empathy_account_settings_set_string (settings, - "first-name", first_name ? first_name : ""); - empathy_account_settings_set_string (settings, - "last-name", last_name ? last_name : ""); - empathy_account_settings_set_string (settings, "email", email ? email : ""); - empathy_account_settings_set_string (settings, "jid", jid ? jid : ""); - - g_free (nickname); - g_free (first_name); - g_free (last_name); - g_free (email); - g_free (jid); - g_object_unref (contact); - g_object_unref (book); -#endif - - return settings; -} diff --git a/src/empathy-auto-salut-account-helper.h b/src/empathy-auto-salut-account-helper.h deleted file mode 100644 index f0409d01d..000000000 --- a/src/empathy-auto-salut-account-helper.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2010 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: Xavier Claessens <xclaesse@gmail.com> - * Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> - */ - -/* Helper functions to automatically create a Salut account */ - -#ifndef __AUTO_SALUT_ACCOUNT_HELPER_H__ -#define __AUTO_SALUT_ACCOUNT_HELPER_H__ - -#include <telepathy-glib/account-manager.h> - -#include <libempathy/empathy-connection-managers.h> -#include <libempathy/empathy-account-settings.h> - -gboolean should_create_salut_account (TpAccountManager *manager); - -EmpathyAccountSettings * create_salut_account_settings (void); - -#endif diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c index dc3c65358..51732e024 100644 --- a/src/empathy-call-window.c +++ b/src/empathy-call-window.c @@ -396,8 +396,11 @@ create_video_output_widget (EmpathyCallWindow *self) clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (priv->video_output), TRUE); - priv->video_output_sink = clutter_gst_video_sink_new ( - CLUTTER_TEXTURE (priv->video_output)); + priv->video_output_sink = gst_element_factory_make ("cluttersink", NULL); + if (priv->video_output_sink == NULL) + g_error ("Missing cluttersink"); + else + g_object_set (priv->video_output_sink, "texture", priv->video_output, NULL); clutter_container_add_actor (CLUTTER_CONTAINER (priv->video_box), priv->video_output); @@ -1070,8 +1073,12 @@ create_video_preview (EmpathyCallWindow *self) preview = empathy_rounded_texture_new (); clutter_actor_set_size (preview, SELF_VIDEO_SECTION_WIDTH, SELF_VIDEO_SECTION_HEIGHT); - priv->video_preview_sink = clutter_gst_video_sink_new ( - CLUTTER_TEXTURE (preview)); + + priv->video_preview_sink = gst_element_factory_make ("cluttersink", NULL); + if (priv->video_preview_sink == NULL) + g_error ("Missing cluttersink"); + else + g_object_set (priv->video_preview_sink, "texture", preview, NULL); /* Add a little offset to the video preview */ layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, diff --git a/src/empathy-call.c b/src/empathy-call.c index 21b751df9..5f45d1ee5 100644 --- a/src/empathy-call.c +++ b/src/empathy-call.c @@ -30,6 +30,10 @@ #include <clutter-gtk/clutter-gtk.h> #include <clutter-gst/clutter-gst.h> +#ifdef CLUTTER_WINDOWING_X11 +#include <X11/Xlib.h> +#endif + #include <telepathy-glib/debug-sender.h> #include <libempathy/empathy-client-factory.h> @@ -185,6 +189,12 @@ main (int argc, /* Init */ g_thread_init (NULL); +#ifdef GDK_WINDOWING_X11 + /* We can't call clutter_gst_init() before gtk_clutter_init(), so no choice + * but to intiialise X11 threading ourself */ + XInitThreads (); +#endif + /* Clutter needs this */ gdk_disable_multidevice (); diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c index 1bb9de4aa..ccf22ff01 100644 --- a/src/empathy-chat-window.c +++ b/src/empathy-chat-window.c @@ -47,6 +47,7 @@ #include <libempathy/empathy-tp-contact-factory.h> #include <libempathy/empathy-contact-list.h> #include <libempathy/empathy-request-util.h> +#include <libempathy/empathy-individual-manager.h> #include <libempathy-gtk/empathy-images.h> #include <libempathy-gtk/empathy-contact-dialogs.h> @@ -129,12 +130,14 @@ static const guint tab_accel_keys[] = { typedef enum { DND_DRAG_TYPE_CONTACT_ID, + DND_DRAG_TYPE_INDIVIDUAL_ID, DND_DRAG_TYPE_URI_LIST, DND_DRAG_TYPE_TAB } DndDragType; static const GtkTargetEntry drag_types_dest[] = { { "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID }, + { "text/x-individual-id", 0, DND_DRAG_TYPE_INDIVIDUAL_ID }, { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, DND_DRAG_TYPE_TAB }, { "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST }, { "text/path-list", 0, DND_DRAG_TYPE_URI_LIST }, @@ -142,6 +145,7 @@ static const GtkTargetEntry drag_types_dest[] = { static const GtkTargetEntry drag_types_dest_contact[] = { { "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID }, + { "text/x-individual-id", 0, DND_DRAG_TYPE_INDIVIDUAL_ID }, }; static const GtkTargetEntry drag_types_dest_file[] = { @@ -213,13 +217,168 @@ chat_window_find_chat (EmpathyChat *chat) } static void +remove_all_chats (EmpathyChatWindow *window) +{ + EmpathyChatWindowPriv *priv; + + priv = GET_PRIV (window); + g_object_ref (window); + + while (priv->chats) { + empathy_chat_window_remove_chat (window, priv->chats->data); + } + + g_object_unref (window); +} + +static void +confirm_close_response_cb (GtkWidget *dialog, + int response, + EmpathyChatWindow *window) +{ + EmpathyChat *chat; + + chat = g_object_get_data (G_OBJECT (dialog), "chat"); + + gtk_widget_destroy (dialog); + + if (response != GTK_RESPONSE_ACCEPT) + return; + + if (chat != NULL) { + empathy_chat_window_remove_chat (window, chat); + } else { + remove_all_chats (window); + } +} + +static void +confirm_close (EmpathyChatWindow *window, + gboolean close_window, + guint n_rooms, + EmpathyChat *chat) +{ + EmpathyChatWindowPriv *priv; + GtkWidget *dialog; + gchar *primary, *secondary; + + g_return_if_fail (n_rooms > 0); + + if (n_rooms > 1) { + g_return_if_fail (chat == NULL); + } else { + g_return_if_fail (chat != NULL); + } + + priv = GET_PRIV (window); + + /* If there are no chats in this window, how could we possibly have got + * here? + */ + g_return_if_fail (priv->chats != NULL); + + /* Treat closing a window which only has one tab exactly like closing + * that tab. + */ + if (close_window && priv->chats->next == NULL) { + close_window = FALSE; + chat = priv->chats->data; + } + + if (close_window) { + primary = g_strdup (_("Close this window?")); + + if (n_rooms == 1) { + gchar *chat_name = empathy_chat_dup_name (chat); + secondary = g_strdup_printf ( + _("Closing this window will leave %s. You will " + "not receive any further messages until you " + "rejoin it."), + chat_name); + g_free (chat_name); + } else { + secondary = g_strdup_printf ( + /* Note to translators: the number of chats will + * always be at least 2. + */ + ngettext ( + "Closing this window will leave a chat room. You will " + "not receive any further messages until you rejoin it.", + "Closing this window will leave %u chat rooms. You will " + "not receive any further messages until you rejoin them.", + n_rooms), + n_rooms); + } + } else { + gchar *chat_name = empathy_chat_dup_name (chat); + primary = g_strdup_printf (_("Leave %s?"), chat_name); + secondary = g_strdup (_("You will not receive any further messages from this chat " + "room until you rejoin it.")); + g_free (chat_name); + } + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (priv->dialog), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_CANCEL, + "%s", primary); + + gtk_window_set_title (GTK_WINDOW (dialog), ""); + g_object_set (dialog, "secondary-text", secondary, NULL); + + g_free (primary); + g_free (secondary); + + gtk_dialog_add_button (GTK_DIALOG (dialog), + close_window ? _("Close window") : _("Leave room"), + GTK_RESPONSE_ACCEPT); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), + GTK_RESPONSE_ACCEPT); + + if (!close_window) { + g_object_set_data (G_OBJECT (dialog), "chat", chat); + } + + g_signal_connect (dialog, "response", + G_CALLBACK (confirm_close_response_cb), window); + + gtk_window_present (GTK_WINDOW (dialog)); +} + +/* Returns TRUE if we should check if the user really wants to leave. If it's + * a multi-user chat, and it has a TpChat (so there's an underlying channel, so + * the user is actually in the room as opposed to having been kicked or gone + * offline or something), then we should check. + */ +static gboolean +chat_needs_close_confirmation (EmpathyChat *chat) +{ + return (empathy_chat_is_room (chat) + && empathy_chat_get_tp_chat (chat) != NULL); +} + +static void +maybe_close_chat (EmpathyChatWindow *window, + EmpathyChat *chat) +{ + g_return_if_fail (chat != NULL); + + if (chat_needs_close_confirmation (chat)) { + confirm_close (window, FALSE, 1, chat); + } else { + empathy_chat_window_remove_chat (window, chat); + } +} + +static void chat_window_close_clicked_cb (GtkAction *action, EmpathyChat *chat) { EmpathyChatWindow *window; window = chat_window_find_chat (chat); - empathy_chat_window_remove_chat (window, chat); + maybe_close_chat (window, chat); } static void @@ -765,6 +924,19 @@ chat_window_update_chat_tab_full (EmpathyChat *chat, append_markup_printf (tooltip, "\n%s", _("Typing a message.")); } + if (remote_contact != NULL) { + const gchar * const *types; + + types = empathy_contact_get_client_types (remote_contact); + if (types != NULL && !tp_strdiff (types[0], "phone")) { + /* I'm on a phone ! */ + gchar *tmp = name; + + name = g_strdup_printf ("☎ %s", name); + g_free (tmp); + } + } + markup = g_string_free (tooltip, FALSE); widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-tooltip-widget"); gtk_widget_set_tooltip_markup (widget, markup); @@ -773,10 +945,19 @@ chat_window_update_chat_tab_full (EmpathyChat *chat, g_free (markup); /* Update tab and menu label */ + if (empathy_chat_is_highlighted (chat)) { + markup = g_markup_printf_escaped ( + "<span color=\"red\" weight=\"bold\">%s</span>", + name); + } else { + markup = g_markup_escape_text (name, -1); + } + widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-label"); - gtk_label_set_text (GTK_LABEL (widget), name); + gtk_label_set_markup (GTK_LABEL (widget), markup); widget = g_object_get_data (G_OBJECT (chat), "chat-window-menu-label"); - gtk_label_set_text (GTK_LABEL (widget), name); + gtk_label_set_markup (GTK_LABEL (widget), markup); + g_free (markup); /* Update the window if it's the current chat */ if (priv->current_chat == chat) { @@ -1027,7 +1208,7 @@ chat_window_close_activate_cb (GtkAction *action, g_return_if_fail (priv->current_chat != NULL); - empathy_chat_window_remove_chat (window, priv->current_chat); + maybe_close_chat (window, priv->current_chat); } static void @@ -1271,14 +1452,25 @@ chat_window_delete_event_cb (GtkWidget *dialog, EmpathyChatWindow *window) { EmpathyChatWindowPriv *priv = GET_PRIV (window); + EmpathyChat *chat = NULL; + guint n_rooms = 0; + GList *l; DEBUG ("Delete event received"); - g_object_ref (window); - while (priv->chats) { - empathy_chat_window_remove_chat (window, priv->chats->data); + for (l = priv->chats; l != NULL; l = l->next) { + if (chat_needs_close_confirmation (l->data)) { + chat = l->data; + n_rooms++; + } + } + + if (n_rooms > 0) { + confirm_close (window, TRUE, n_rooms, + (n_rooms == 1 ? chat : NULL)); + } else { + remove_all_chats (window); } - g_object_unref (window); return TRUE; } @@ -1394,30 +1586,6 @@ chat_window_show_or_update_notification (EmpathyChatWindow *window, g_free (escaped); } -static void -chat_window_set_highlight_room_labels (EmpathyChat *chat) -{ - gchar *markup, *name; - GtkWidget *widget; - - if (!empathy_chat_is_room (chat)) - return; - - name = empathy_chat_dup_name (chat); - markup = g_markup_printf_escaped ( - "<span color=\"red\" weight=\"bold\">%s</span>", - name); - - widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-label"); - gtk_label_set_markup (GTK_LABEL (widget), markup); - - widget = g_object_get_data (G_OBJECT (chat), "chat-window-menu-label"); - gtk_label_set_markup (GTK_LABEL (widget), markup); - - g_free (name); - g_free (markup); -} - static gboolean empathy_chat_window_has_focus (EmpathyChatWindow *window) { @@ -1437,6 +1605,7 @@ static void chat_window_new_message_cb (EmpathyChat *chat, EmpathyMessage *message, gboolean pending, + gboolean should_highlight, EmpathyChatWindow *window) { EmpathyChatWindowPriv *priv; @@ -1496,15 +1665,13 @@ chat_window_new_message_cb (EmpathyChat *chat, if (chatroom != NULL && empathy_chatroom_is_always_urgent (chatroom)) { needs_urgency = TRUE; } else { - needs_urgency = empathy_message_should_highlight (message); + needs_urgency = should_highlight; } } else { needs_urgency = TRUE; } if (needs_urgency) { - chat_window_set_highlight_room_labels (chat); - if (!has_focus) { chat_window_set_urgency_hint (window, TRUE); } @@ -1818,6 +1985,70 @@ chat_window_drag_motion (GtkWidget *widget, } static void +drag_data_received_individual_id (EmpathyChatWindow *self, + GtkWidget *widget, + GdkDragContext *context, + int x, + int y, + GtkSelectionData *selection, + guint info, + guint time_) +{ + const gchar *id; + EmpathyIndividualManager *manager; + FolksIndividual *individual; + EmpathyChatWindowPriv *priv = GET_PRIV (self); + EmpathyTpChat *chat; + TpContact *tp_contact; + TpConnection *conn; + EmpathyContact *contact; + + id = (const gchar *) gtk_selection_data_get_data (selection); + + DEBUG ("DND invididual %s", id); + + if (priv->current_chat == NULL) + goto out; + + chat = empathy_chat_get_tp_chat (priv->current_chat); + if (chat == NULL) + goto out; + + if (!empathy_tp_chat_can_add_contact (chat)) { + DEBUG ("Can't invite contact to %s", + tp_proxy_get_object_path (chat)); + goto out; + } + + manager = empathy_individual_manager_dup_singleton (); + + individual = empathy_individual_manager_lookup_member (manager, id); + if (individual == NULL) { + DEBUG ("Failed to find individual %s", id); + goto out; + } + + conn = tp_channel_borrow_connection ((TpChannel *) chat); + tp_contact = empathy_get_tp_contact_for_individual (individual, conn); + if (tp_contact == NULL) { + DEBUG ("Can't find a TpContact on connection %s for %s", + tp_proxy_get_object_path (conn), id); + goto out; + } + + DEBUG ("Inviting %s to join %s", tp_contact_get_identifier (tp_contact), + tp_channel_get_identifier ((TpChannel *) chat)); + + contact = empathy_contact_dup_from_tp_contact (tp_contact); + empathy_contact_list_add (EMPATHY_CONTACT_LIST (chat), contact, NULL); + g_object_unref (contact); + +out: + gtk_drag_finish (context, TRUE, FALSE, time_); + tp_clear_object (&manager); +} + +static void chat_window_drag_data_received (GtkWidget *widget, GdkDragContext *context, int x, @@ -1897,6 +2128,10 @@ chat_window_drag_data_received (GtkWidget *widget, */ gtk_drag_finish (context, TRUE, FALSE, time_); } + else if (info == DND_DRAG_TYPE_INDIVIDUAL_ID) { + drag_data_received_individual_id (window, widget, context, x, y, + selection, info, time_); + } else if (info == DND_DRAG_TYPE_URI_LIST) { EmpathyChatWindowPriv *priv; EmpathyContact *contact; diff --git a/src/empathy-chat-window.ui b/src/empathy-chat-window.ui index 25749861c..bf95bff16 100644 --- a/src/empathy-chat-window.ui +++ b/src/empathy-chat-window.ui @@ -205,8 +205,8 @@ <object class="GtkWindow" id="chat_window"> <property name="title" translatable="yes">Chat</property> <property name="role">chat</property> - <property name="default_width">350</property> - <property name="default_height">250</property> + <property name="default_width">580</property> + <property name="default_height">480</property> <child> <object class="GtkVBox" id="chat_vbox"> <property name="visible">True</property> diff --git a/src/empathy-chat.c b/src/empathy-chat.c index 43ab00270..bebca4382 100644 --- a/src/empathy-chat.c +++ b/src/empathy-chat.c @@ -31,6 +31,7 @@ #include <telepathy-glib/debug-sender.h> #include <libempathy/empathy-presence-manager.h> +#include <libempathy/empathy-individual-manager.h> #include <libempathy-gtk/empathy-theme-manager.h> #include <libempathy-gtk/empathy-ui-utils.h> @@ -100,6 +101,7 @@ main (int argc, EmpathyPresenceManager *presence_mgr; EmpathyThemeManager *theme_mgr; gint retval; + EmpathyIndividualManager *individual_mgr; /* Init */ g_thread_init (NULL); @@ -143,6 +145,10 @@ main (int argc, /* Keep the theme manager alive as it does some caching */ theme_mgr = empathy_theme_manager_dup_singleton (); + /* Keep the individual manager alive so we won't fetch everything from Folks + * each time we need to use it. */ + individual_mgr = empathy_individual_manager_dup_singleton (); + if (g_getenv ("EMPATHY_PERSIST") != NULL) { DEBUG ("Disable timer"); @@ -163,6 +169,7 @@ main (int argc, g_object_unref (presence_mgr); g_object_unref (theme_mgr); tp_clear_object (&chat_mgr); + g_object_unref (individual_mgr); #ifdef ENABLE_DEBUG g_object_unref (debug_sender); diff --git a/src/empathy-debug-window.c b/src/empathy-debug-window.c index b298600a9..3aa8c1502 100644 --- a/src/empathy-debug-window.c +++ b/src/empathy-debug-window.c @@ -69,6 +69,9 @@ enum COL_NAME = 0, COL_UNIQUE_NAME, COL_GONE, + COL_ACTIVE_BUFFER, + COL_PAUSE_BUFFER, + COL_PROXY, NUM_COLS }; @@ -91,11 +94,7 @@ typedef struct GtkToolItem *level_label; GtkWidget *level_filter; - /* Cache */ - GHashTable *cache; - /* TreeView */ - GtkListStore *store; GtkTreeModel *store_filter; GtkWidget *view; GtkWidget *scrolled_win; @@ -104,10 +103,7 @@ typedef struct /* Connection */ TpDBusDaemon *dbus; - TpProxy *proxy; - TpProxySignalConnection *new_debug_message_signal; TpProxySignalConnection *name_owner_changed_signal; - gulong invalid_signal_id; /* Whether NewDebugMessage will be fired */ gboolean paused; @@ -115,12 +111,17 @@ typedef struct /* Service (CM, Client) chooser store */ GtkListStore *service_store; + /* Counters on services detected and added */ + guint services_detected; + guint name_owner_cb_count; + /* Debug to show upon creation */ gchar *select_name; /* Misc. */ gboolean dispose_run; TpAccountManager *am; + GtkListStore *all_active_buffer; } EmpathyDebugWindowPriv; static const gchar * @@ -152,48 +153,6 @@ log_level_to_string (guint level) } } -typedef struct -{ - gdouble timestamp; - gchar *domain; - guint level; - gchar *message; -} DebugMessage; - -static DebugMessage * -debug_message_new (gdouble timestamp, - const gchar *domain, - guint level, - const gchar *message) -{ - DebugMessage *retval = g_slice_new0 (DebugMessage); - - retval->timestamp = timestamp; - retval->domain = g_strdup (domain); - retval->level = level; - retval->message = g_strdup (message); - - return retval; -} - -static void -debug_message_free (DebugMessage *dm) -{ - g_free (dm->domain); - g_free (dm->message); - - g_slice_free (DebugMessage, dm); -} - -static void -debug_message_list_free (gpointer data) -{ - GList *list = data; - - g_list_foreach (list, (GFunc) debug_message_free, NULL); - g_list_free (list); -} - static gchar * get_active_service_name (EmpathyDebugWindow *self) { @@ -210,30 +169,66 @@ get_active_service_name (EmpathyDebugWindow *self) return name; } -static void -debug_window_cache_new_message (EmpathyDebugWindow *debug_window, - gdouble timestamp, - const gchar *domain, - guint level, - const gchar *message) +static gboolean +copy_buffered_messages (GtkTreeModel *buffer, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) { - EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); - GList *messages; - DebugMessage *dm; - char *name; + GtkListStore *active_buffer = data; + GtkTreeIter active_buffer_iter; + gdouble timestamp; + gchar *domain, *category, *message, *level_string; + guint level; - name = get_active_service_name (debug_window); - messages = g_hash_table_lookup (priv->cache, name); + gtk_tree_model_get (buffer, iter, + COL_DEBUG_TIMESTAMP, ×tamp, + COL_DEBUG_DOMAIN, &domain, + COL_DEBUG_CATEGORY, &category, + COL_DEBUG_LEVEL_STRING, &level_string, + COL_DEBUG_MESSAGE, &message, + COL_DEBUG_LEVEL_VALUE, &level, + -1); + gtk_list_store_insert_with_values (active_buffer, &active_buffer_iter, -1, + COL_DEBUG_TIMESTAMP, timestamp, + COL_DEBUG_DOMAIN, domain, + COL_DEBUG_CATEGORY, category, + COL_DEBUG_LEVEL_STRING, level_string, + COL_DEBUG_MESSAGE, message, + COL_DEBUG_LEVEL_VALUE, level, + -1); + + g_free (domain); + g_free (category); + g_free (level_string); + g_free (message); - dm = debug_message_new (timestamp, domain, level, message); - messages = g_list_append (messages, dm); + return FALSE; +} - g_hash_table_insert (priv->cache, name, messages); +static void +insert_values_in_buffer (GtkListStore *store, + gdouble timestamp, + const gchar *domain, + const gchar *category, + guint level, + const gchar *string) +{ + GtkTreeIter iter; + + gtk_list_store_insert_with_values (store, &iter, -1, + COL_DEBUG_TIMESTAMP, timestamp, + COL_DEBUG_DOMAIN, domain, + COL_DEBUG_CATEGORY, category, + COL_DEBUG_LEVEL_STRING, log_level_to_string (level), + COL_DEBUG_MESSAGE, string, + COL_DEBUG_LEVEL_VALUE, level, + -1); } static void debug_window_add_message (EmpathyDebugWindow *debug_window, - gboolean should_cache, + TpProxy *proxy, gdouble timestamp, const gchar *domain_category, guint level, @@ -241,12 +236,8 @@ debug_window_add_message (EmpathyDebugWindow *debug_window, { EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); gchar *domain, *category; - GtkTreeIter iter; gchar *string; - - if (should_cache) - debug_window_cache_new_message (debug_window, timestamp, domain_category, - level, message); + GtkListStore *active_buffer, *pause_buffer; if (g_strrstr (domain_category, "/")) { @@ -266,16 +257,26 @@ debug_window_add_message (EmpathyDebugWindow *debug_window, else string = g_strdup (message); + pause_buffer = g_object_get_data (G_OBJECT (proxy), "pause-buffer"); + active_buffer = g_object_get_data (G_OBJECT (proxy), "active-buffer"); - gtk_list_store_append (priv->store, &iter); - gtk_list_store_set (priv->store, &iter, - COL_DEBUG_TIMESTAMP, timestamp, - COL_DEBUG_DOMAIN, domain, - COL_DEBUG_CATEGORY, category, - COL_DEBUG_LEVEL_STRING, log_level_to_string (level), - COL_DEBUG_MESSAGE, string, - COL_DEBUG_LEVEL_VALUE, level, - -1); + if (priv->paused) + { + insert_values_in_buffer (pause_buffer, timestamp, + domain, category, level, + string); + } + else + { + /* Append 'this' message to this service's and All's active-buffers */ + insert_values_in_buffer (active_buffer, timestamp, + domain, category, level, + string); + + insert_values_in_buffer (priv->all_active_buffer, timestamp, + domain, category, level, + string); + } g_free (string); g_free (domain); @@ -293,20 +294,21 @@ debug_window_new_debug_message_cb (TpProxy *proxy, { EmpathyDebugWindow *debug_window = (EmpathyDebugWindow *) user_data; - debug_window_add_message (debug_window, TRUE, timestamp, domain, level, + debug_window_add_message (debug_window, proxy, timestamp, domain, level, message); } static void -debug_window_set_enabled (EmpathyDebugWindow *debug_window, +debug_window_set_enabled (TpProxy *proxy, gboolean enabled) { - EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); GValue *val; + g_return_if_fail (proxy != NULL); + val = tp_g_value_slice_new_boolean (enabled); - tp_cli_dbus_properties_call_set (priv->proxy, -1, TP_IFACE_DEBUG, + tp_cli_dbus_properties_call_set (proxy, -1, TP_IFACE_DEBUG, "Enabled", val, NULL, NULL, NULL, NULL); tp_g_value_slice_free (val); @@ -344,6 +346,74 @@ debug_window_set_toolbar_sensitivity (EmpathyDebugWindow *debug_window, } } +static gboolean +debug_window_get_iter_for_active_buffer (GtkListStore *active_buffer, + GtkTreeIter *iter, + EmpathyDebugWindow *debug_window) +{ + EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); + gboolean valid_iter; + GtkTreeModel *model = GTK_TREE_MODEL (priv->service_store); + + gtk_tree_model_get_iter_first (model, iter); + for (valid_iter = gtk_tree_model_iter_next (model, iter); + valid_iter; + valid_iter = gtk_tree_model_iter_next (model, iter)) + { + GtkListStore *stored_active_buffer; + + gtk_tree_model_get (model, iter, + COL_ACTIVE_BUFFER, &stored_active_buffer, + -1); + if (active_buffer == stored_active_buffer) + { + g_object_unref (stored_active_buffer); + return valid_iter; + } + g_object_unref (stored_active_buffer); + } + + return valid_iter; +} + +static void refresh_all_buffer (EmpathyDebugWindow *debug_window); + +static void +proxy_invalidated_cb (TpProxy *proxy, + guint domain, + gint code, + gchar *msg, + gpointer user_data) +{ + EmpathyDebugWindow *self = (EmpathyDebugWindow *) user_data; + EmpathyDebugWindowPriv *priv = GET_PRIV (self); + GtkTreeModel *service_store = GTK_TREE_MODEL (priv->service_store); + TpProxy *stored_proxy; + GtkTreeIter iter; + gboolean valid_iter; + + /* Proxy has been invalidated so we find and set it to NULL + * in service store */ + gtk_tree_model_get_iter_first (service_store, &iter); + for (valid_iter = gtk_tree_model_iter_next (service_store, &iter); + valid_iter; + valid_iter = gtk_tree_model_iter_next (service_store, &iter)) + { + gtk_tree_model_get (service_store, &iter, + COL_PROXY, &stored_proxy, + -1); + + if (proxy == stored_proxy) + gtk_list_store_set (priv->service_store, &iter, + COL_PROXY, NULL, + -1); + } + + /* Also, we refresh "All" selection's active buffer since it should not + * show messages obtained from the proxy getting destroyed above */ + refresh_all_buffer (self); +} + static void debug_window_get_messages_cb (TpProxy *proxy, const GPtrArray *messages, @@ -353,87 +423,301 @@ debug_window_get_messages_cb (TpProxy *proxy, { EmpathyDebugWindow *debug_window = (EmpathyDebugWindow *) user_data; EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); - gchar *name; - GList *old_messages; + gchar *active_service_name; guint i; + GtkListStore *active_buffer; + gboolean valid_iter; + GtkTreeIter iter; + gchar *proxy_service_name; + active_buffer = g_object_get_data (G_OBJECT (proxy), "active-buffer"); + valid_iter = debug_window_get_iter_for_active_buffer (active_buffer, &iter, + debug_window); + gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), &iter, + COL_NAME, &proxy_service_name, + -1); + + active_service_name = get_active_service_name (debug_window); if (error != NULL) { DEBUG ("GetMessages failed: %s", error->message); - debug_window_set_toolbar_sensitivity (debug_window, FALSE); + + /* We want to set the window sensitivity to false only when proxy for the + * selected service is unable to fetch debug messages */ + if (!tp_strdiff (active_service_name, proxy_service_name)) + debug_window_set_toolbar_sensitivity (debug_window, FALSE); + + /* We created the proxy for GetMessages call. Now destroy it. */ + tp_clear_object (&proxy); return; } + DEBUG ("Retrieved debug messages for %s", active_service_name); + g_free (active_service_name); debug_window_set_toolbar_sensitivity (debug_window, TRUE); - name = get_active_service_name (debug_window); - old_messages = g_hash_table_lookup (priv->cache, name); - - /* we call get_messages either when a new CM is added or - * when a CM that we've already seen re-appears; in both cases - * we don't need our old cache anymore. - */ - if (old_messages != NULL) - { - g_hash_table_remove (priv->cache, name); - debug_message_list_free (old_messages); - } for (i = 0; i < messages->len; i++) { GValueArray *values = g_ptr_array_index (messages, i); - debug_window_add_message (debug_window, TRUE, + debug_window_add_message (debug_window, proxy, g_value_get_double (g_value_array_get_nth (values, 0)), g_value_get_string (g_value_array_get_nth (values, 1)), g_value_get_uint (g_value_array_get_nth (values, 2)), g_value_get_string (g_value_array_get_nth (values, 3))); } - /* Connect to NewDebugMessage */ - priv->new_debug_message_signal = emp_cli_debug_connect_to_new_debug_message ( + /* Now we save this precious proxy in the service_store along its service */ + if (valid_iter) + { + DEBUG ("Proxy for service: %s was successful in fetching debug" + " messages. Saving it.", proxy_service_name); + + gtk_list_store_set (priv->service_store, &iter, + COL_PROXY, proxy, + -1); + } + + g_free (proxy_service_name); + + /* Connect to "invalidated" signal */ + g_signal_connect (proxy, "invalidated", + G_CALLBACK (proxy_invalidated_cb), debug_window); + + /* Connect to NewDebugMessage */ + emp_cli_debug_connect_to_new_debug_message ( proxy, debug_window_new_debug_message_cb, debug_window, NULL, NULL, NULL); - /* Set Enabled as appropriate */ - debug_window_set_enabled (debug_window, !priv->paused); + /* Now that active-buffer is up to date, we can see which messages are + * to be visible */ + gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->store_filter)); + + /* Set the proxy to signal for new debug messages */ + debug_window_set_enabled (proxy, TRUE); } static void -debug_window_add_log_messages_from_cache (EmpathyDebugWindow *debug_window, - const gchar *name) +create_proxy_to_get_messages (EmpathyDebugWindow *debug_window, + GtkTreeIter *iter, + TpDBusDaemon *dbus) { - GList *messages, *l; - DebugMessage *dm; EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); + gchar *bus_name, *name = NULL; + TpProxy *new_proxy, *stored_proxy = NULL; + GtkTreeModel *pause_buffer, *active_buffer; + gboolean gone; - DEBUG ("Adding logs from cache for CM %s", name); + gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), iter, + COL_NAME, &name, + COL_GONE, &gone, + COL_ACTIVE_BUFFER, &active_buffer, + COL_PAUSE_BUFFER, &pause_buffer, + COL_PROXY, &stored_proxy, + -1); - messages = g_hash_table_lookup (priv->cache, name); + /* If the stored_proxy is not NULL then messages have been obtained and + * new-debug-message-signal has been set on it. Also, the proxy is valid. + * If the service is gone, we still display the messages-cached till now. */ + if (gone || + (!gone && stored_proxy != NULL)) + { + /* Nothing needs to be done. The associated active-buffer has already + * been set as view's model */ + goto finally; + } - if (messages == NULL) - return; + DEBUG ("Preparing proxy to obtain messages for service %s", name); - for (l = messages; l != NULL; l = l->next) - { - dm = l->data; + gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), iter, + COL_UNIQUE_NAME, &bus_name, -1); + new_proxy = g_object_new (TP_TYPE_PROXY, + "bus-name", bus_name, + "dbus-daemon", dbus, + "object-path", DEBUG_OBJECT_PATH, + NULL); + g_free (bus_name); + + g_object_set_data (G_OBJECT (new_proxy), "active-buffer", active_buffer); + g_object_set_data (G_OBJECT (new_proxy), "pause-buffer", pause_buffer); + + /* Now we call GetMessages with fresh proxy. + * The old proxy is NULL due to one of the following - + * * Wasn't saved as last GetMessages call failed + * * The service has newly arrived and no proxy has been prepared yet for it + * * A service with the same name has reappeared but the owner maybe new */ + tp_proxy_add_interface_by_id (new_proxy, emp_iface_quark_debug ()); + + emp_cli_debug_call_get_messages (new_proxy, -1, + debug_window_get_messages_cb, debug_window, NULL, NULL); + +finally: + g_free (name); + tp_clear_object (&stored_proxy); + g_object_unref (active_buffer); + g_object_unref (pause_buffer); +} + +static GtkListStore* +new_list_store_for_service (void) +{ + return gtk_list_store_new (NUM_DEBUG_COLS, + G_TYPE_DOUBLE, /* COL_DEBUG_TIMESTAMP */ + G_TYPE_STRING, /* COL_DEBUG_DOMAIN */ + G_TYPE_STRING, /* COL_DEBUG_CATEGORY */ + G_TYPE_STRING, /* COL_DEBUG_LEVEL_STRING */ + G_TYPE_STRING, /* COL_DEBUG_MESSAGE */ + G_TYPE_UINT); /* COL_DEBUG_LEVEL_VALUE */ +} + +static gboolean +debug_window_visible_func (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data) +{ + EmpathyDebugWindow *debug_window = (EmpathyDebugWindow *) user_data; + EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); + guint filter_value, level; + GtkTreeModel *filter_model; + GtkTreeIter filter_iter; + + filter_model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->level_filter)); + gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->level_filter), + &filter_iter); + + gtk_tree_model_get (model, iter, COL_DEBUG_LEVEL_VALUE, &level, -1); + gtk_tree_model_get (filter_model, &filter_iter, + COL_LEVEL_VALUE, &filter_value, -1); + + if (level <= filter_value) + return TRUE; + + return FALSE; +} + +static gboolean +tree_view_search_equal_func_cb (GtkTreeModel *model, + gint column, + const gchar *key, + + GtkTreeIter *iter, + gpointer search_data) +{ + gchar *str; + gint key_len; + gint len; + gint i; + gboolean ret = TRUE; /* The return value is counter-intuitive */ + + gtk_tree_model_get (model, iter, column, &str, -1); - debug_window_add_message (debug_window, FALSE, dm->timestamp, - dm->domain, dm->level, dm->message); + key_len = strlen (key); + len = strlen (str) - key_len; + + for (i = 0; i <= len; ++i) + { + if (!g_ascii_strncasecmp (key, str + i, key_len)) + { + ret = FALSE; + break; + } } + + g_free (str); + return ret; } static void -proxy_invalidated_cb (TpProxy *proxy, - guint domain, - gint code, - gchar *msg, - EmpathyDebugWindowPriv *self) +update_store_filter (EmpathyDebugWindow *debug_window, + GtkListStore *active_buffer) { - EmpathyDebugWindowPriv *priv = GET_PRIV (self); + EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); + debug_window_set_toolbar_sensitivity (debug_window, FALSE); - /* Proxy has been invalidated so we can't disconnect the signal any more */ - priv->new_debug_message_signal = NULL; + tp_clear_object (&priv->store_filter); + priv->store_filter = gtk_tree_model_filter_new ( + GTK_TREE_MODEL (active_buffer), NULL); + + gtk_tree_model_filter_set_visible_func ( + GTK_TREE_MODEL_FILTER (priv->store_filter), + debug_window_visible_func, debug_window, NULL); + gtk_tree_view_set_model (GTK_TREE_VIEW (priv->view), + priv->store_filter); + + /* Since view's model has changed, reset the search column and + * search_equal_func */ + gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->view), + COL_DEBUG_MESSAGE); + gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (priv->view), + tree_view_search_equal_func_cb, NULL, NULL); + + debug_window_set_toolbar_sensitivity (debug_window, TRUE); +} + +static void +refresh_all_buffer (EmpathyDebugWindow *debug_window) +{ + EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); + gboolean valid_iter; + GtkTreeIter iter; + GtkTreeModel *service_store = GTK_TREE_MODEL (priv->service_store); + + /* Clear All's active-buffer */ + gtk_list_store_clear (priv->all_active_buffer); + + /* Skipping the first service store iter which is reserved for "All" */ + gtk_tree_model_get_iter_first (service_store, &iter); + for (valid_iter = gtk_tree_model_iter_next (service_store, &iter); + valid_iter; + valid_iter = gtk_tree_model_iter_next (service_store, &iter)) + { + TpProxy *proxy = NULL; + GtkListStore *service_active_buffer; + gboolean gone; + + gtk_tree_model_get (service_store, &iter, + COL_GONE, &gone, + COL_PROXY, &proxy, + COL_ACTIVE_BUFFER, &service_active_buffer, + -1); + + if (gone) + { + gtk_tree_model_foreach (GTK_TREE_MODEL (service_active_buffer), + copy_buffered_messages, priv->all_active_buffer); + } + else + { + if (proxy != NULL) + { + if (service_active_buffer == NULL) + break; + + /* Copy the debug messages to all_active_buffer */ + gtk_tree_model_foreach (GTK_TREE_MODEL (service_active_buffer), + copy_buffered_messages, priv->all_active_buffer); + } + else + { + GError *error = NULL; + TpDBusDaemon *dbus = tp_dbus_daemon_dup (&error); + + if (error != NULL) + { + DEBUG ("Failed at duping the dbus daemon: %s", error->message); + g_error_free (error); + } + + create_proxy_to_get_messages (debug_window, &iter, dbus); + + g_object_unref (dbus); + } + } + + g_object_unref (service_active_buffer); + tp_clear_object (&proxy); + } } static void @@ -443,8 +727,8 @@ debug_window_service_chooser_changed_cb (GtkComboBox *chooser, EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); TpDBusDaemon *dbus; GError *error = NULL; - gchar *bus_name, *name = NULL; - TpProxy *proxy; + GtkListStore *stored_active_buffer = NULL; + gchar *name = NULL; GtkTreeIter iter; gboolean gone; @@ -459,64 +743,44 @@ debug_window_service_chooser_changed_cb (GtkComboBox *chooser, return; } - gtk_list_store_clear (priv->store); + debug_window_set_toolbar_sensitivity (debug_window, TRUE); gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), &iter, - COL_NAME, &name, COL_GONE, &gone, -1); + COL_NAME, &name, + COL_GONE, &gone, + COL_ACTIVE_BUFFER, &stored_active_buffer, + -1); + + DEBUG ("Service chosen: %s", name); - if (gone) + if (tp_strdiff (name, "All") && stored_active_buffer == NULL) { - debug_window_add_log_messages_from_cache (debug_window, name); - g_free (name); - return; + DEBUG ("No list store assigned to service %s", name); + goto finally; } - g_free (name); - - dbus = tp_dbus_daemon_dup (&error); - - if (error != NULL) + if (!tp_strdiff (name, "All")) { - DEBUG ("Failed at duping the dbus daemon: %s", error->message); + update_store_filter (debug_window, priv->all_active_buffer); + goto finally; } - gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), &iter, - COL_UNIQUE_NAME, &bus_name, -1); - proxy = g_object_new (TP_TYPE_PROXY, - "bus-name", bus_name, - "dbus-daemon", dbus, - "object-path", DEBUG_OBJECT_PATH, - NULL); - g_free (bus_name); - - /* Disable debug signalling */ - if (priv->proxy != NULL) - debug_window_set_enabled (debug_window, FALSE); + update_store_filter (debug_window, stored_active_buffer); - /* Disconnect from previous NewDebugMessage signal */ - if (priv->new_debug_message_signal != NULL) - { - tp_proxy_signal_connection_disconnect (priv->new_debug_message_signal); - priv->new_debug_message_signal = NULL; - } + dbus = tp_dbus_daemon_dup (&error); - if (priv->proxy != NULL) + if (error != NULL) { - g_signal_handler_disconnect (priv->proxy, priv->invalid_signal_id); - g_object_unref (priv->proxy); + DEBUG ("Failed at duping the dbus daemon: %s", error->message); } - priv->proxy = proxy; - - tp_proxy_add_interface_by_id (priv->proxy, emp_iface_quark_debug ()); - - emp_cli_debug_call_get_messages (priv->proxy, -1, - debug_window_get_messages_cb, debug_window, NULL, NULL); - - priv->invalid_signal_id = g_signal_connect (proxy, "invalidated", - G_CALLBACK (proxy_invalidated_cb), debug_window); + create_proxy_to_get_messages (debug_window, &iter, dbus); g_object_unref (dbus); + +finally: + g_free (name); + tp_clear_object (&stored_active_buffer); } typedef struct @@ -673,6 +937,9 @@ debug_window_get_name_owner_cb (TpDBusDaemon *proxy, FillServiceChooserData *data = (FillServiceChooserData *) user_data; EmpathyDebugWindow *self = EMPATHY_DEBUG_WINDOW (data->debug_window); EmpathyDebugWindowPriv *priv = GET_PRIV (data->debug_window); + GtkTreeIter iter; + + priv->name_owner_cb_count++; if (error != NULL) { @@ -682,8 +949,8 @@ debug_window_get_name_owner_cb (TpDBusDaemon *proxy, if (!debug_window_service_is_in_model (data->debug_window, out, NULL, FALSE)) { - GtkTreeIter iter; char *name; + GtkListStore *active_buffer, *pause_buffer; DEBUG ("Adding %s to list: %s at unique name: %s", data->type == SERVICE_TYPE_CM? "CM": "Client", @@ -694,12 +961,21 @@ debug_window_get_name_owner_cb (TpDBusDaemon *proxy, else name = g_strdup (data->name); - gtk_list_store_append (priv->service_store, &iter); - gtk_list_store_set (priv->service_store, &iter, + active_buffer = new_list_store_for_service (); + pause_buffer = new_list_store_for_service (); + + gtk_list_store_insert_with_values (priv->service_store, &iter, -1, COL_NAME, name, COL_UNIQUE_NAME, out, + COL_GONE, FALSE, + COL_ACTIVE_BUFFER, active_buffer, + COL_PAUSE_BUFFER, pause_buffer, + COL_PROXY, NULL, -1); + g_object_unref (active_buffer); + g_object_unref (pause_buffer); + if (priv->select_name != NULL && !tp_strdiff (name, priv->select_name)) { @@ -710,6 +986,22 @@ debug_window_get_name_owner_cb (TpDBusDaemon *proxy, g_free (name); } + if (priv->services_detected == priv->name_owner_cb_count) + { + /* Time to add "All" selection to service_store */ + gtk_list_store_insert_with_values (priv->service_store, &iter, 0, + COL_NAME, "All", + COL_ACTIVE_BUFFER, NULL, + -1); + + priv->all_active_buffer = new_list_store_for_service (); + + /* Populate active buffers for all services */ + refresh_all_buffer (self); + + gtk_combo_box_set_active (GTK_COMBO_BOX (priv->chooser), 0); + } + OUT: fill_service_chooser_data_free (data); } @@ -724,6 +1016,7 @@ debug_window_list_connection_names_cb (const gchar * const *names, GObject *weak_object) { EmpathyDebugWindow *debug_window = (EmpathyDebugWindow *) user_data; + EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); guint i; TpDBusDaemon *dbus; GError *error2 = NULL; @@ -751,6 +1044,8 @@ debug_window_list_connection_names_cb (const gchar * const *names, tp_cli_dbus_daemon_call_get_name_owner (dbus, -1, names[i], debug_window_get_name_owner_cb, data, NULL, NULL); + + priv->services_detected ++; } g_object_unref (dbus); @@ -786,6 +1081,7 @@ debug_window_name_owner_changed_cb (TpDBusDaemon *proxy, if (EMP_STR_EMPTY (arg1) && !EMP_STR_EMPTY (arg2)) { + GtkTreeIter *found_at_iter = NULL; gchar *display_name; if (type == SERVICE_TYPE_CM) @@ -794,41 +1090,72 @@ debug_window_name_owner_changed_cb (TpDBusDaemon *proxy, display_name = g_strdup (name); /* A service joined */ - if (!g_hash_table_lookup (priv->cache, name)) + if (!debug_window_service_is_in_model (user_data, display_name, + &found_at_iter, TRUE)) { GtkTreeIter iter; + GtkListStore *active_buffer, *pause_buffer; DEBUG ("Adding new service '%s' at %s.", name, arg2); - gtk_list_store_append (priv->service_store, &iter); - gtk_list_store_set (priv->service_store, &iter, + active_buffer = new_list_store_for_service (); + pause_buffer = new_list_store_for_service (); + + gtk_list_store_insert_with_values (priv->service_store, &iter, -1, COL_NAME, display_name, COL_UNIQUE_NAME, arg2, + COL_GONE, FALSE, + COL_ACTIVE_BUFFER, active_buffer, + COL_PAUSE_BUFFER, pause_buffer, + COL_PROXY, NULL, -1); + + g_object_unref (active_buffer); + g_object_unref (pause_buffer); } else { - /* a service with the same name is already in the hash table, - * update it and set it as re-enabled in the model. + /* a service with the same name is already in the service_store, + * update it and set it as re-enabled. */ - GtkTreeIter *iter = NULL; + GtkListStore *active_buffer, *pause_buffer; + TpProxy *stored_proxy; - if (debug_window_service_is_in_model (user_data, name, &iter, TRUE)) - { - DEBUG ("Refreshing CM '%s' at '%s'.", name, arg2); + DEBUG ("Refreshing CM '%s' at '%s'.", name, arg2); - gtk_list_store_set (priv->service_store, iter, - COL_NAME, display_name, - COL_UNIQUE_NAME, arg2, - COL_GONE, FALSE, - -1); - gtk_tree_iter_free (iter); + active_buffer= new_list_store_for_service (); + pause_buffer = new_list_store_for_service (); - debug_window_service_chooser_changed_cb - (GTK_COMBO_BOX (priv->chooser), user_data); - } + gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), + found_at_iter, COL_PROXY, &stored_proxy, -1); + + tp_clear_object (&stored_proxy); + + gtk_list_store_set (priv->service_store, found_at_iter, + COL_NAME, display_name, + COL_UNIQUE_NAME, arg2, + COL_GONE, FALSE, + COL_ACTIVE_BUFFER, active_buffer, + COL_PAUSE_BUFFER, pause_buffer, + COL_PROXY, NULL, + -1); + + g_object_unref (active_buffer); + g_object_unref (pause_buffer); + + gtk_tree_iter_free (found_at_iter); + + debug_window_service_chooser_changed_cb + (GTK_COMBO_BOX (priv->chooser), user_data); } + /* If a new service arrives when "All" is selected, the view will + * not show its messages which we do not want. So we refresh All's + * active buffer. + * Similarly for when a service with an already seen service name + * appears. */ + refresh_all_buffer (self); + g_free (display_name); } else if (!EMP_STR_EMPTY (arg1) && EMP_STR_EMPTY (arg2)) @@ -845,6 +1172,9 @@ debug_window_name_owner_changed_cb (TpDBusDaemon *proxy, iter, COL_GONE, TRUE, -1); gtk_tree_iter_free (iter); } + + /* Refresh all's active buffer */ + refresh_all_buffer (self); } } @@ -862,6 +1192,8 @@ add_client (EmpathyDebugWindow *self, tp_cli_dbus_daemon_call_get_name_owner (priv->dbus, -1, name, debug_window_get_name_owner_cb, data, NULL, NULL); + + priv->services_detected ++; } static void @@ -895,6 +1227,7 @@ debug_window_fill_service_chooser (EmpathyDebugWindow *debug_window) EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); GError *error = NULL; GtkTreeIter iter; + GtkListStore *active_buffer, *pause_buffer; priv->dbus = tp_dbus_daemon_dup (&error); @@ -905,18 +1238,28 @@ debug_window_fill_service_chooser (EmpathyDebugWindow *debug_window) return; } + /* Keep a count of the services detected and added */ + priv->services_detected = 0; + priv->name_owner_cb_count = 0; + /* Add CMs to list */ tp_list_connection_names (priv->dbus, debug_window_list_connection_names_cb, debug_window, NULL, NULL); /* add Mission Control */ - gtk_list_store_append (priv->service_store, &iter); - gtk_list_store_set (priv->service_store, &iter, + active_buffer= new_list_store_for_service (); + pause_buffer = new_list_store_for_service (); + + gtk_list_store_insert_with_values (priv->service_store, &iter, -1, COL_NAME, "mission-control", COL_UNIQUE_NAME, "org.freedesktop.Telepathy.MissionControl5", + COL_GONE, FALSE, + COL_ACTIVE_BUFFER, active_buffer, + COL_PAUSE_BUFFER, pause_buffer, + COL_PROXY, NULL, -1); - - gtk_combo_box_set_active (GTK_COMBO_BOX (priv->chooser), 0); + g_object_unref (active_buffer); + g_object_unref (pause_buffer); /* add clients */ tp_dbus_daemon_list_names (priv->dbus, 2000, @@ -932,35 +1275,41 @@ debug_window_pause_toggled_cb (GtkToggleToolButton *pause_, EmpathyDebugWindow *debug_window) { EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); + GtkTreeIter iter; + gboolean valid_iter; + GtkTreeModel *model = GTK_TREE_MODEL (priv->service_store); priv->paused = gtk_toggle_tool_button_get_active (pause_); - debug_window_set_enabled (debug_window, !priv->paused); -} - -static gboolean -debug_window_visible_func (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data) -{ - EmpathyDebugWindow *debug_window = (EmpathyDebugWindow *) user_data; - EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); - guint filter_value, level; - GtkTreeModel *filter_model; - GtkTreeIter filter_iter; + if (!priv->paused) + { + /* Pause has been released - flush all pause buffers */ + GtkTreeModel *service_store = GTK_TREE_MODEL (priv->service_store); + + /* Skipping the first iter which is reserved for "All" */ + gtk_tree_model_get_iter_first (model, &iter); + for (valid_iter = gtk_tree_model_iter_next (model, &iter); + valid_iter; + valid_iter = gtk_tree_model_iter_next (model, &iter)) + { + GtkListStore *pause_buffer, *active_buffer; - filter_model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->level_filter)); - gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->level_filter), - &filter_iter); + gtk_tree_model_get (service_store, &iter, + COL_PAUSE_BUFFER, &pause_buffer, + COL_ACTIVE_BUFFER, &active_buffer, + -1); - gtk_tree_model_get (model, iter, COL_DEBUG_LEVEL_VALUE, &level, -1); - gtk_tree_model_get (filter_model, &filter_iter, - COL_LEVEL_VALUE, &filter_value, -1); + gtk_tree_model_foreach (GTK_TREE_MODEL (pause_buffer), + copy_buffered_messages, active_buffer); + gtk_tree_model_foreach (GTK_TREE_MODEL (pause_buffer), + copy_buffered_messages, priv->all_active_buffer); - if (level <= filter_value) - return TRUE; + gtk_list_store_clear (pause_buffer); - return FALSE; + g_object_unref (active_buffer); + g_object_unref (pause_buffer); + } + } } static void @@ -978,8 +1327,16 @@ debug_window_clear_clicked_cb (GtkToolButton *clear_button, EmpathyDebugWindow *debug_window) { EmpathyDebugWindowPriv *priv = GET_PRIV (debug_window); + GtkTreeIter iter; + GtkListStore *active_buffer; - gtk_list_store_clear (priv->store); + gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->chooser), &iter); + gtk_tree_model_get (GTK_TREE_MODEL (priv->service_store), &iter, + COL_ACTIVE_BUFFER, &active_buffer, -1); + + gtk_list_store_clear (active_buffer); + + g_object_unref (active_buffer); } static void @@ -1347,37 +1704,6 @@ debug_window_key_press_event_cb (GtkWidget *widget, return FALSE; } -static gboolean -tree_view_search_equal_func_cb (GtkTreeModel *model, - gint column, - const gchar *key, - GtkTreeIter *iter, - gpointer search_data) -{ - gchar *str; - gint key_len; - gint len; - gint i; - gboolean ret = TRUE; /* The return value is counter-intuitive */ - - gtk_tree_model_get (model, iter, column, &str, -1); - - key_len = strlen (key); - len = strlen (str) - key_len; - - for (i = 0; i <= len; ++i) - { - if (!g_ascii_strncasecmp (key, str + i, key_len)) - { - ret = FALSE; - break; - } - } - - g_free (str); - return ret; -} - static void empathy_debug_window_select_name (EmpathyDebugWindow *self, const gchar *name) @@ -1456,8 +1782,13 @@ am_prepared_cb (GObject *am, /* CM */ priv->chooser = gtk_combo_box_text_new (); - priv->service_store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_BOOLEAN); + priv->service_store = gtk_list_store_new (NUM_COLS, + G_TYPE_STRING, /* COL_NAME */ + G_TYPE_STRING, /* COL_UNIQUE_NAME */ + G_TYPE_BOOLEAN, /* COL_GONE */ + G_TYPE_OBJECT, /* COL_ACTIVE_BUFFER */ + G_TYPE_OBJECT, /* COL_PAUSE_BUFFER */ + TP_TYPE_PROXY); /* COL_PROXY */ gtk_combo_box_set_model (GTK_COMBO_BOX (priv->chooser), GTK_TREE_MODEL (priv->service_store)); gtk_widget_show (priv->chooser); @@ -1544,38 +1875,32 @@ am_prepared_cb (GObject *am, gtk_combo_box_set_model (GTK_COMBO_BOX (priv->level_filter), GTK_TREE_MODEL (level_store)); - gtk_list_store_append (level_store, &iter); - gtk_list_store_set (level_store, &iter, + gtk_list_store_insert_with_values (level_store, &iter, -1, COL_LEVEL_NAME, _("Debug"), COL_LEVEL_VALUE, TP_DEBUG_LEVEL_DEBUG, -1); - gtk_list_store_append (level_store, &iter); - gtk_list_store_set (level_store, &iter, + gtk_list_store_insert_with_values (level_store, &iter, -1, COL_LEVEL_NAME, _("Info"), COL_LEVEL_VALUE, TP_DEBUG_LEVEL_INFO, -1); - gtk_list_store_append (level_store, &iter); - gtk_list_store_set (level_store, &iter, + gtk_list_store_insert_with_values (level_store, &iter, -1, COL_LEVEL_NAME, _("Message"), COL_LEVEL_VALUE, TP_DEBUG_LEVEL_MESSAGE, -1); - gtk_list_store_append (level_store, &iter); - gtk_list_store_set (level_store, &iter, + gtk_list_store_insert_with_values (level_store, &iter, -1, COL_LEVEL_NAME, _("Warning"), COL_LEVEL_VALUE, TP_DEBUG_LEVEL_WARNING, -1); - gtk_list_store_append (level_store, &iter); - gtk_list_store_set (level_store, &iter, + gtk_list_store_insert_with_values (level_store, &iter, -1, COL_LEVEL_NAME, _("Critical"), COL_LEVEL_VALUE, TP_DEBUG_LEVEL_CRITICAL, -1); - gtk_list_store_append (level_store, &iter); - gtk_list_store_set (level_store, &iter, + gtk_list_store_insert_with_values (level_store, &iter, -1, COL_LEVEL_NAME, _("Error"), COL_LEVEL_VALUE, TP_DEBUG_LEVEL_ERROR, -1); @@ -1609,24 +1934,10 @@ am_prepared_cb (GObject *am, gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->view), -1, _("Message"), renderer, "text", COL_DEBUG_MESSAGE, NULL); - priv->store = gtk_list_store_new (NUM_DEBUG_COLS, G_TYPE_DOUBLE, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_UINT); - - priv->store_filter = gtk_tree_model_filter_new ( - GTK_TREE_MODEL (priv->store), NULL); - - gtk_tree_model_filter_set_visible_func ( - GTK_TREE_MODEL_FILTER (priv->store_filter), - debug_window_visible_func, object, NULL); + priv->store_filter = NULL; gtk_tree_view_set_model (GTK_TREE_VIEW (priv->view), priv->store_filter); - gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->view), - COL_DEBUG_MESSAGE); - gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (priv->view), - tree_view_search_equal_func_cb, NULL, NULL); - /* Scrolled window */ priv->scrolled_win = g_object_ref (gtk_scrolled_window_new (NULL, NULL)); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolled_win), @@ -1647,6 +1958,8 @@ am_prepared_cb (GObject *am, priv->view_visible = FALSE; + priv->all_active_buffer = NULL; + debug_window_set_toolbar_sensitivity (EMPATHY_DEBUG_WINDOW (object), FALSE); debug_window_fill_service_chooser (EMPATHY_DEBUG_WINDOW (object)); gtk_widget_show (GTK_WIDGET (object)); @@ -1671,8 +1984,6 @@ empathy_debug_window_init (EmpathyDebugWindow *empathy_debug_window) empathy_debug_window->priv = priv; priv->dispose_run = FALSE; - priv->cache = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); } static void @@ -1707,22 +2018,9 @@ static void debug_window_finalize (GObject *object) { EmpathyDebugWindowPriv *priv = GET_PRIV (object); - GHashTableIter iter; - char *key; - GList *values; g_free (priv->select_name); - g_hash_table_iter_init (&iter, priv->cache); - - while (g_hash_table_iter_next (&iter, (gpointer *) &key, - (gpointer *) &values)) - { - debug_message_list_free (values); - } - - g_hash_table_unref (priv->cache); - (G_OBJECT_CLASS (empathy_debug_window_parent_class)->finalize) (object); } @@ -1737,22 +2035,9 @@ debug_window_dispose (GObject *object) priv->dispose_run = TRUE; - if (priv->store != NULL) - g_object_unref (priv->store); - if (priv->name_owner_changed_signal != NULL) tp_proxy_signal_connection_disconnect (priv->name_owner_changed_signal); - if (priv->new_debug_message_signal != NULL) - tp_proxy_signal_connection_disconnect (priv->new_debug_message_signal); - - if (priv->proxy != NULL) - { - debug_window_set_enabled (EMPATHY_DEBUG_WINDOW (object), FALSE); - g_signal_handler_disconnect (priv->proxy, priv->invalid_signal_id); - g_object_unref (priv->proxy); - } - if (priv->service_store != NULL) g_object_unref (priv->service_store); @@ -1765,6 +2050,8 @@ debug_window_dispose (GObject *object) priv->am = NULL; } + tp_clear_object (&priv->all_active_buffer); + (G_OBJECT_CLASS (empathy_debug_window_parent_class)->dispose) (object); } diff --git a/src/empathy-import-dialog.c b/src/empathy-import-dialog.c index 77d11298f..4e00bd11a 100644 --- a/src/empathy-import-dialog.c +++ b/src/empathy-import-dialog.c @@ -39,7 +39,8 @@ enum { PROP_PARENT = 1, - PROP_SHOW_WARNING + PROP_SHOW_WARNING, + PROP_CMS, }; typedef struct { @@ -48,6 +49,7 @@ typedef struct { EmpathyImportWidget *iw; gboolean show_warning; + EmpathyConnectionManagers *cms; } EmpathyImportDialogPriv; G_DEFINE_TYPE (EmpathyImportDialog, empathy_import_dialog, GTK_TYPE_DIALOG) @@ -62,15 +64,17 @@ import_dialog_add_import_widget (EmpathyImportDialog *self) area = gtk_dialog_get_content_area (GTK_DIALOG (self)); - iw = empathy_import_widget_new (EMPATHY_IMPORT_APPLICATION_ALL); + iw = empathy_import_widget_new (EMPATHY_IMPORT_APPLICATION_ALL, priv->cms); widget = empathy_import_widget_get_widget (iw); - gtk_box_pack_start (GTK_BOX (area), widget, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (area), widget, TRUE, TRUE, 0); gtk_widget_show (widget); priv->iw = iw; - gtk_dialog_add_buttons (GTK_DIALOG (self), GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); + gtk_dialog_add_buttons (GTK_DIALOG (self), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + _("_Import"), GTK_RESPONSE_OK, + NULL); } static void @@ -134,6 +138,9 @@ do_get_property (GObject *object, case PROP_SHOW_WARNING: g_value_set_boolean (value, priv->show_warning); break; + case PROP_CMS: + g_value_set_object (value, priv->cms); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -155,6 +162,9 @@ do_set_property (GObject *object, case PROP_SHOW_WARNING: priv->show_warning = g_value_get_boolean (value); break; + case PROP_CMS: + priv->cms = g_value_dup_object (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -199,6 +209,15 @@ empathy_import_dialog_init (EmpathyImportDialog *self) gtk_window_set_title (GTK_WINDOW (self), _("Import Accounts")); gtk_window_set_modal (GTK_WINDOW (self), TRUE); } +static void +do_dispose (GObject *obj) +{ + EmpathyImportDialogPriv *priv = GET_PRIV (obj); + + g_clear_object (&priv->cms); + + G_OBJECT_CLASS (empathy_import_dialog_parent_class)->dispose (obj); +} static void empathy_import_dialog_class_init (EmpathyImportDialogClass *klass) @@ -210,6 +229,7 @@ empathy_import_dialog_class_init (EmpathyImportDialogClass *klass) oclass->constructed = do_constructed; oclass->get_property = do_get_property; oclass->set_property = do_set_property; + oclass->dispose = do_dispose; gtkclass->response = impl_signal_response; @@ -226,13 +246,25 @@ empathy_import_dialog_class_init (EmpathyImportDialogClass *klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (oclass, PROP_SHOW_WARNING, param_spec); + param_spec = g_param_spec_object ("cms", + "EmpathyConnectionManagers", "EmpathyConnectionManager", + EMPATHY_TYPE_CONNECTION_MANAGERS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_CMS, param_spec); + g_type_class_add_private (klass, sizeof (EmpathyImportDialogPriv)); } GtkWidget * empathy_import_dialog_new (GtkWindow *parent, - gboolean warning) + gboolean warning, + EmpathyConnectionManagers *cms) { - return g_object_new (EMPATHY_TYPE_IMPORT_DIALOG, "parent-window", - parent, "show-warning", warning, NULL); + g_return_val_if_fail (EMPATHY_IS_CONNECTION_MANAGERS (cms), NULL); + + return g_object_new (EMPATHY_TYPE_IMPORT_DIALOG, + "parent-window", parent, + "show-warning", warning, + "cms", cms, + NULL); } diff --git a/src/empathy-import-dialog.h b/src/empathy-import-dialog.h index 0e9d225c4..a412037d1 100644 --- a/src/empathy-import-dialog.h +++ b/src/empathy-import-dialog.h @@ -25,6 +25,8 @@ #ifndef __EMPATHY_IMPORT_DIALOG_H__ #define __EMPATHY_IMPORT_DIALOG_H__ +#include <libempathy/empathy-connection-managers.h> + G_BEGIN_DECLS #define EMPATHY_TYPE_IMPORT_DIALOG empathy_import_dialog_get_type() @@ -56,7 +58,8 @@ typedef struct { GType empathy_import_dialog_get_type (void); GtkWidget* empathy_import_dialog_new (GtkWindow *parent_window, - gboolean show_warning); + gboolean show_warning, + EmpathyConnectionManagers *cms); G_END_DECLS diff --git a/src/empathy-import-widget.c b/src/empathy-import-widget.c index aaf20d5c5..041c51003 100644 --- a/src/empathy-import-widget.c +++ b/src/empathy-import-widget.c @@ -55,7 +55,8 @@ enum }; enum { - PROP_APPLICATION_ID = 1 + PROP_APPLICATION_ID = 1, + PROP_CMS }; typedef struct { @@ -359,20 +360,6 @@ import_widget_set_up_account_list (EmpathyImportWidget *self) } static void -import_widget_cms_prepare_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - EmpathyImportWidget *self = user_data; - - if (!empathy_connection_managers_prepare_finish ( - EMPATHY_CONNECTION_MANAGERS (source), result, NULL)) - return; - - import_widget_set_up_account_list (self); -} - -static void import_widget_destroy_cb (GtkWidget *w, EmpathyImportWidget *self) { @@ -392,6 +379,9 @@ do_get_property (GObject *object, case PROP_APPLICATION_ID: g_value_set_int (value, priv->app_id); break; + case PROP_CMS: + g_value_set_object (value, priv->cms); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -410,6 +400,9 @@ do_set_property (GObject *object, case PROP_APPLICATION_ID: priv->app_id = g_value_get_int (value); break; + case PROP_CMS: + priv->cms = g_value_dup_object (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -468,8 +461,7 @@ do_constructed (GObject *obj) g_signal_connect (priv->vbox, "destroy", G_CALLBACK (import_widget_destroy_cb), self); - empathy_connection_managers_prepare_async (priv->cms, - import_widget_cms_prepare_cb, self); + import_widget_set_up_account_list (self); } static void @@ -490,6 +482,12 @@ empathy_import_widget_class_init (EmpathyImportWidgetClass *klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (oclass, PROP_APPLICATION_ID, param_spec); + param_spec = g_param_spec_object ("cms", + "EmpathyConnectionManagers", "EmpathyConnectionManager", + EMPATHY_TYPE_CONNECTION_MANAGERS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_CMS, param_spec); + g_type_class_add_private (klass, sizeof (EmpathyImportWidgetPriv)); } @@ -501,14 +499,18 @@ empathy_import_widget_init (EmpathyImportWidget *self) EmpathyImportWidgetPriv); self->priv = priv; - - priv->cms = empathy_connection_managers_dup_singleton (); } EmpathyImportWidget * -empathy_import_widget_new (EmpathyImportApplication id) +empathy_import_widget_new (EmpathyImportApplication id, + EmpathyConnectionManagers *cms) { - return g_object_new (EMPATHY_TYPE_IMPORT_WIDGET, "application-id", id, NULL); + g_return_val_if_fail (EMPATHY_IS_CONNECTION_MANAGERS (cms), NULL); + + return g_object_new (EMPATHY_TYPE_IMPORT_WIDGET, + "application-id", id, + "cms", cms, + NULL); } GtkWidget * diff --git a/src/empathy-import-widget.h b/src/empathy-import-widget.h index 48f2e1d48..14a01d79d 100644 --- a/src/empathy-import-widget.h +++ b/src/empathy-import-widget.h @@ -27,6 +27,8 @@ #include <glib-object.h> +#include <libempathy/empathy-connection-managers.h> + #include "empathy-import-utils.h" G_BEGIN_DECLS @@ -59,7 +61,8 @@ typedef struct { GType empathy_import_widget_get_type (void); -EmpathyImportWidget* empathy_import_widget_new (EmpathyImportApplication id); +EmpathyImportWidget* empathy_import_widget_new (EmpathyImportApplication id, + EmpathyConnectionManagers *cms); GtkWidget * empathy_import_widget_get_widget (EmpathyImportWidget *self); diff --git a/src/empathy-preferences.c b/src/empathy-preferences.c index 6775d4a24..77ec49c26 100644 --- a/src/empathy-preferences.c +++ b/src/empathy-preferences.c @@ -67,7 +67,7 @@ struct _EmpathyPreferencesPriv { GtkWidget *checkbutton_show_smileys; GtkWidget *checkbutton_show_contacts_in_rooms; - GtkWidget *checkbutton_separate_chat_windows; + GtkWidget *radiobutton_chats_new_windows; GtkWidget *checkbutton_events_notif_area; GtkWidget *checkbutton_autoconnect; GtkWidget *checkbutton_logging; @@ -166,7 +166,7 @@ static SoundEventEntry sound_entries [] = { { N_("Message received"), EMPATHY_PREFS_SOUNDS_INCOMING_MESSAGE }, { N_("Message sent"), EMPATHY_PREFS_SOUNDS_OUTGOING_MESSAGE }, { N_("New conversation"), EMPATHY_PREFS_SOUNDS_NEW_CONVERSATION }, - { N_("Contact goes online"), EMPATHY_PREFS_SOUNDS_CONTACT_LOGIN }, + { N_("Contact comes online"), EMPATHY_PREFS_SOUNDS_CONTACT_LOGIN }, { N_("Contact goes offline"), EMPATHY_PREFS_SOUNDS_CONTACT_LOGOUT }, { N_("Account connected"), EMPATHY_PREFS_SOUNDS_SERVICE_LOGIN }, { N_("Account disconnected"), EMPATHY_PREFS_SOUNDS_SERVICE_LOGOUT } @@ -248,7 +248,7 @@ preferences_setup_widgets (EmpathyPreferences *preferences) g_settings_bind (priv->gsettings_ui, EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS, - priv->checkbutton_separate_chat_windows, + priv->radiobutton_chats_new_windows, "active", G_SETTINGS_BIND_DEFAULT); @@ -678,7 +678,8 @@ static void preferences_preview_theme_append_message (EmpathyChatView *view, EmpathyContact *sender, EmpathyContact *receiver, - const gchar *text) + const gchar *text, + gboolean should_highlight) { EmpathyMessage *message; @@ -688,7 +689,7 @@ preferences_preview_theme_append_message (EmpathyChatView *view, "body", text, NULL); - empathy_chat_view_append_message (view, message); + empathy_chat_view_append_message (view, message, should_highlight); g_object_unref (message); } @@ -735,19 +736,20 @@ preferences_preview_theme_changed_cb (EmpathyThemeManager *manager, preferences_preview_theme_append_message (priv->chat_theme_preview, /* translators: Quote from Romeo & Julier, for chat theme preview */ - juliet, romeo, _("O Romeo, Romeo, wherefore art thou Romeo?")); + juliet, romeo, _("O Romeo, Romeo, wherefore art thou Romeo?"), + TRUE /* this message mentions Romeo */); preferences_preview_theme_append_message (priv->chat_theme_preview, /* translators: Quote from Romeo & Julier, for chat theme preview */ - juliet, romeo, _("Deny thy father and refuse thy name;")); + juliet, romeo, _("Deny thy father and refuse thy name;"), FALSE); preferences_preview_theme_append_message (priv->chat_theme_preview, /* translators: Quote from Romeo & Julier, for chat theme preview */ - juliet, romeo, _("Or if thou wilt not, be but sworn my love")); + juliet, romeo, _("Or if thou wilt not, be but sworn my love"), FALSE); preferences_preview_theme_append_message (priv->chat_theme_preview, /* translators: Quote from Romeo & Julier, for chat theme preview */ - juliet, romeo, _("And I'll no longer be a Capulet.")); + juliet, romeo, _("And I'll no longer be a Capulet."), FALSE); preferences_preview_theme_append_message (priv->chat_theme_preview, /* translators: Quote from Romeo & Julier, for chat theme preview */ - romeo, juliet, _("Shall I hear more, or shall I speak at this?")); + romeo, juliet, _("Shall I hear more, or shall I speak at this?"), FALSE); /* translators: Quote from Romeo & Julier, for chat theme preview */ empathy_chat_view_append_event (priv->chat_theme_preview, _("Juliet has disconnected")); @@ -1170,7 +1172,7 @@ empathy_preferences_init (EmpathyPreferences *preferences) "combobox_chat_theme_variant", &priv->combobox_chat_theme_variant, "hbox_chat_theme_variant", &priv->hbox_chat_theme_variant, "sw_chat_theme_preview", &priv->sw_chat_theme_preview, - "checkbutton_separate_chat_windows", &priv->checkbutton_separate_chat_windows, + "radiobutton_chats_new_windows", &priv->radiobutton_chats_new_windows, "checkbutton_events_notif_area", &priv->checkbutton_events_notif_area, "checkbutton_autoconnect", &priv->checkbutton_autoconnect, "checkbutton_logging", &priv->checkbutton_logging, diff --git a/src/empathy-preferences.ui b/src/empathy-preferences.ui index 03a628cb6..f13f6c0b2 100644 --- a/src/empathy-preferences.ui +++ b/src/empathy-preferences.ui @@ -107,14 +107,47 @@ <property name="can_focus">False</property> <property name="orientation">vertical</property> <child> - <object class="GtkCheckButton" id="checkbutton_separate_chat_windows"> - <property name="label" translatable="yes">_Open new chats in separate windows</property> + <object class="GtkBox" id="vbox2180"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="can_focus">False</property> + <property name="orientation">horizontal</property> + <property name="spacing">3</property> + <child> + <object class="GtkLabel" id="label1000"> + <property name="label" translatable="yes">Start chats in:</property> + <property name="visible">True</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="radiobutton_chats_new_tabs"> + <property name="label" translatable="yes">new ta_bs</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="radiobutton_chats_new_windows"> + <property name="label" translatable="yes">new _windows</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <property name="group">radiobutton_chats_new_tabs</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> </object> <packing> <property name="expand">False</property> diff --git a/src/empathy-roster-window-menubar.ui b/src/empathy-roster-window-menubar.ui index 0bb5d14f0..d342abca8 100644 --- a/src/empathy-roster-window-menubar.ui +++ b/src/empathy-roster-window-menubar.ui @@ -109,12 +109,6 @@ <accelerator key="F4" modifiers=""/> </child> <child> - <object class="GtkAction" id="edit_personal_information"> - <property name="name">edit_personal_information</property> - <property name="label" translatable="yes">_Personal Information</property> - </object> - </child> - <child> <object class="GtkAction" id="edit_blocked_contacts"> <property name="name">edit_blocked_contacts</property> <property name="label" translatable="yes">_Blocked Contacts</property> @@ -263,7 +257,6 @@ <menuitem action="edit_context"/> <separator name="edit_context_separator"/> <menuitem action="edit_accounts"/> - <menuitem action="edit_personal_information"/> <menuitem action="edit_search_contacts"/> <menuitem action="edit_blocked_contacts"/> <separator/> diff --git a/src/empathy-roster-window.c b/src/empathy-roster-window.c index f45474cf2..454cd256a 100644 --- a/src/empathy-roster-window.c +++ b/src/empathy-roster-window.c @@ -92,7 +92,7 @@ enum { PAGE_CONTACT_LIST = 0, - PAGE_NO_MATCH + PAGE_MESSAGE }; enum @@ -111,6 +111,7 @@ struct _EmpathyRosterWindowPriv { EmpathyEventManager *event_manager; EmpathySoundManager *sound_mgr; EmpathyCallObserver *call_observer; + EmpathyIndividualManager *individual_manager; guint flash_timeout_id; gboolean flash_on; gboolean empty; @@ -129,6 +130,8 @@ struct _EmpathyRosterWindowPriv { GtkWidget *search_bar; GtkWidget *notebook; GtkWidget *no_entry_label; + GtkWidget *button_account_settings; + GtkWidget *spinner_loading; GtkToggleAction *show_protocols; GtkRadioAction *sort_by_name; @@ -608,6 +611,53 @@ OUT: } static void +button_account_settings_clicked_cb (GtkButton *button, + EmpathyRosterWindow *self) +{ + empathy_accounts_dialog_show_application (gdk_screen_get_default (), + NULL, FALSE, FALSE); +} + +static void +display_page_message (EmpathyRosterWindow *self, + const gchar *msg, + gboolean display_accounts_button, + gboolean display_spinner) +{ + if (msg != NULL) + { + gchar *tmp; + + tmp = g_strdup_printf ("<b><span size='xx-large'>%s</span></b>", msg); + + gtk_label_set_markup (GTK_LABEL (self->priv->no_entry_label), tmp); + g_free (tmp); + + gtk_label_set_line_wrap (GTK_LABEL (self->priv->no_entry_label), TRUE); + gtk_widget_show (self->priv->no_entry_label); + } + else + { + gtk_widget_hide (self->priv->no_entry_label); + } + + gtk_widget_set_visible (self->priv->button_account_settings, + display_accounts_button); + gtk_widget_set_visible (self->priv->spinner_loading, + display_spinner); + + gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook), + PAGE_MESSAGE); +} + +static void +display_page_no_account (EmpathyRosterWindow *self) +{ + display_page_message (self, + _("You need to setup an account to see contacts here."), TRUE, FALSE); +} + +static void roster_window_row_deleted_cb (GtkTreeModel *model, GtkTreePath *path, EmpathyRosterWindow *self) @@ -620,24 +670,24 @@ roster_window_row_deleted_cb (GtkTreeModel *model, if (empathy_individual_view_is_searching (self->priv->individual_view)) { - gchar *tmp; - - tmp = g_strdup_printf ("<b><span size='xx-large'>%s</span></b>", - _("No match found")); - - gtk_label_set_markup (GTK_LABEL (self->priv->no_entry_label), tmp); - g_free (tmp); - - gtk_label_set_line_wrap (GTK_LABEL (self->priv->no_entry_label), - TRUE); - - gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook), - PAGE_NO_MATCH); + display_page_message (self, _("No match found"), FALSE, FALSE); } } } static void +display_page_contact_list (EmpathyRosterWindow *self) +{ + if (!empathy_individual_manager_get_contacts_loaded ( + self->priv->individual_manager)) + /* We'll display the contact list once we're done loading */ + return; + + gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook), + PAGE_CONTACT_LIST); +} + +static void roster_window_row_inserted_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, @@ -646,8 +696,8 @@ roster_window_row_inserted_cb (GtkTreeModel *model, if (self->priv->empty) { self->priv->empty = FALSE; - gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook), - PAGE_CONTACT_LIST); + + display_page_contact_list (self); gtk_widget_grab_focus (GTK_WIDGET (self->priv->individual_view)); /* The store is being filled, it will be done after an idle cb. @@ -1376,6 +1426,7 @@ empathy_roster_window_finalize (GObject *window) g_object_unref (self->priv->gsettings_ui); g_object_unref (self->priv->gsettings_contacts); + g_object_unref (self->priv->individual_manager); G_OBJECT_CLASS (empathy_roster_window_parent_class)->finalize (window); } @@ -1941,13 +1992,6 @@ roster_window_edit_accounts_cb (GtkAction *action, } static void -roster_window_edit_personal_information_cb (GtkAction *action, - EmpathyRosterWindow *self) -{ - empathy_contact_personal_dialog_show (GTK_WINDOW (self)); -} - -static void roster_window_edit_blocked_contacts_cb (GtkAction *action, EmpathyRosterWindow *self) { @@ -2095,6 +2139,81 @@ add_account (EmpathyRosterWindow *self, roster_window_setup_balance (self, account); } +/* @account: if not %NULL, the only account which can be enabled */ +static void +display_page_account_not_enabled (EmpathyRosterWindow *self, + TpAccount *account) +{ + if (account == NULL) + { + display_page_message (self, + _("You need to enable one of your accounts to see contacts here."), + TRUE, FALSE); + } + else + { + gchar *tmp; + + /* translators: argument is an account name */ + tmp = g_strdup_printf (_("You need to enable %s to see contacts here."), + tp_account_get_display_name (account)); + + display_page_message (self, tmp, TRUE, FALSE); + g_free (tmp); + } +} +static gboolean +has_enabled_account (GList *accounts) +{ + GList *l; + + for (l = accounts; l != NULL; l = g_list_next (l)) + { + TpAccount *account = l->data; + + if (tp_account_is_enabled (account)) + return TRUE; + } + + return FALSE; +} + +static void +set_notebook_page (EmpathyRosterWindow *self) +{ + GList *accounts; + guint len; + + accounts = tp_account_manager_get_valid_accounts ( + self->priv->account_manager); + + len = g_list_length (accounts); + + if (len == 0) + { + /* No account */ + display_page_no_account (self); + goto out; + } + + if (!has_enabled_account (accounts)) + { + TpAccount *account = NULL; + + /* Pass the account if there is only one which can be enabled */ + if (len == 1) + account = accounts->data; + + display_page_account_not_enabled (self, account); + goto out; + } + + display_page_contact_list (self); + +out: + g_list_free (accounts); +} + static void roster_window_account_validity_changed_cb (TpAccountManager *manager, TpAccount *account, @@ -2105,6 +2224,8 @@ roster_window_account_validity_changed_cb (TpAccountManager *manager, add_account (self, account); else roster_window_account_removed_cb (manager, account, self); + + set_notebook_page (self); } static void @@ -2130,7 +2251,6 @@ roster_window_connection_items_setup (EmpathyRosterWindow *self, "chat_new_call", "chat_search_contacts", "chat_add_contact", - "edit_personal_information", "edit_blocked_contacts", "edit_search_contacts" }; @@ -2145,6 +2265,22 @@ roster_window_connection_items_setup (EmpathyRosterWindow *self, } static void +account_enabled_cb (TpAccountManager *manager, + TpAccount *account, + EmpathyRosterWindow *self) +{ + set_notebook_page (self); +} + +static void +account_disabled_cb (TpAccountManager *manager, + TpAccount *account, + EmpathyRosterWindow *self) +{ + set_notebook_page (self); +} + +static void account_manager_prepared_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) @@ -2171,6 +2307,10 @@ account_manager_prepared_cb (GObject *source_object, g_signal_connect (manager, "account-validity-changed", G_CALLBACK (roster_window_account_validity_changed_cb), self); + tp_g_signal_connect_object (manager, "account-disabled", + G_CALLBACK (account_disabled_cb), self, 0); + tp_g_signal_connect_object (manager, "account-enabled", + G_CALLBACK (account_enabled_cb), self, 0); roster_window_update_status (self); @@ -2178,6 +2318,8 @@ account_manager_prepared_cb (GObject *source_object, gtk_action_set_sensitive (self->priv->view_history, g_list_length (accounts) > 0); + set_notebook_page (self); + g_list_free (accounts); } @@ -2271,9 +2413,31 @@ empathy_roster_window_class_init (EmpathyRosterWindowClass *klass) } static void +show_contacts_loading (EmpathyRosterWindow *self) +{ + display_page_message (self, NULL, FALSE, TRUE); + + gtk_spinner_start (GTK_SPINNER (self->priv->spinner_loading)); +} + +static void +hide_contacts_loading (EmpathyRosterWindow *self) +{ + gtk_spinner_stop (GTK_SPINNER (self->priv->spinner_loading)); + + display_page_contact_list (self); +} + +static void +contacts_loaded_cb (EmpathyIndividualManager *manager, + EmpathyRosterWindow *self) +{ + hide_contacts_loading (self); +} + +static void empathy_roster_window_init (EmpathyRosterWindow *self) { - EmpathyIndividualManager *individual_manager; GtkBuilder *gui, *gui_mgr; GtkWidget *sw; GtkToggleAction *show_offline_widget; @@ -2313,6 +2477,8 @@ empathy_roster_window_init (EmpathyRosterWindow *self) "notebook", &self->priv->notebook, "no_entry_label", &self->priv->no_entry_label, "roster_scrolledwindow", &sw, + "button_account_settings", &self->priv->button_account_settings, + "spinner_loading", &self->priv->spinner_loading, NULL); g_free (filename); @@ -2365,7 +2531,6 @@ empathy_roster_window_init (EmpathyRosterWindow *self) "view_show_map", "activate", roster_window_view_show_map_cb, "edit", "activate", roster_window_edit_cb, "edit_accounts", "activate", roster_window_edit_accounts_cb, - "edit_personal_information", "activate", roster_window_edit_personal_information_cb, "edit_blocked_contacts", "activate", roster_window_edit_blocked_contacts_cb, "edit_preferences", "activate", roster_window_edit_preferences_cb, "edit_search_contacts", "activate", roster_window_edit_search_contacts_cb, @@ -2442,10 +2607,19 @@ empathy_roster_window_init (EmpathyRosterWindow *self) * so it's got a race condition between its signal handlers and its * finalization. The class is planned to be removed, so we won't fix * this before then. */ - individual_manager = empathy_individual_manager_dup_singleton (); + self->priv->individual_manager = empathy_individual_manager_dup_singleton (); + + if (!empathy_individual_manager_get_contacts_loaded ( + self->priv->individual_manager)) + { + show_contacts_loading (self); + + tp_g_signal_connect_object (self->priv->individual_manager, + "contacts-loaded", G_CALLBACK (contacts_loaded_cb), self, 0); + } + self->priv->individual_store = EMPATHY_INDIVIDUAL_STORE ( - empathy_individual_store_manager_new (individual_manager)); - g_object_unref (individual_manager); + empathy_individual_store_manager_new (self->priv->individual_manager)); /* For the moment, we disallow Persona drops onto the roster contact list * (e.g. from things such as the EmpathyPersonaView in the linking dialogue). @@ -2469,7 +2643,6 @@ empathy_roster_window_init (EmpathyRosterWindow *self) EMPATHY_INDIVIDUAL_FEATURE_CALL | EMPATHY_INDIVIDUAL_FEATURE_EDIT | EMPATHY_INDIVIDUAL_FEATURE_INFO | - EMPATHY_INDIVIDUAL_FEATURE_LINK | EMPATHY_INDIVIDUAL_FEATURE_SMS | EMPATHY_INDIVIDUAL_FEATURE_CALL_PHONE); @@ -2512,6 +2685,9 @@ empathy_roster_window_init (EmpathyRosterWindow *self) self->priv->balance_vbox, "visible", G_BINDING_SYNC_CREATE); + g_settings_bind (self->priv->gsettings_ui, "show-groups", + self->priv->individual_store, "show-groups", G_SETTINGS_BIND_DEFAULT); + /* Enable event handling */ self->priv->call_observer = empathy_call_observer_dup_singleton (); self->priv->event_manager = empathy_event_manager_dup_singleton (); @@ -2565,6 +2741,9 @@ empathy_roster_window_init (EmpathyRosterWindow *self) roster_window_notify_contact_list_size_cb (self->priv->gsettings_ui, EMPATHY_PREFS_UI_SHOW_AVATARS, self); + + g_signal_connect (self->priv->button_account_settings, "clicked", + G_CALLBACK (button_account_settings_clicked_cb), self); } GtkWidget * diff --git a/src/empathy-roster-window.ui b/src/empathy-roster-window.ui index a09d123f8..8c8f63001 100644 --- a/src/empathy-roster-window.ui +++ b/src/empathy-roster-window.ui @@ -91,10 +91,82 @@ </object> </child> <child> - <object class="GtkLabel" id="no_entry_label"> + <object class="GtkBox" id="box1"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="yalign">0.30000001192092896</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="yalign">1</property> + <property name="ypad">1</property> + <property name="icon_name">avatar-default</property> + <property name="icon-size">6</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="no_entry_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="yalign">0.30000001192092896</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="yalign">0</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <object class="GtkButton" id="button_account_settings"> + <property name="label" translatable="yes">Account settings</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">6</property> + <property name="margin_right">6</property> + <property name="use_action_appearance">False</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="yalign">0</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <object class="GtkSpinner" id="spinner_loading"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> </object> <packing> <property name="position">1</property> diff --git a/src/empathy-rounded-actor.c b/src/empathy-rounded-actor.c index 0537dea96..045f08de7 100644 --- a/src/empathy-rounded-actor.c +++ b/src/empathy-rounded-actor.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include <clutter/clutter.h> #include <clutter-gtk/clutter-gtk.h> diff --git a/src/empathy-rounded-rectangle.c b/src/empathy-rounded-rectangle.c index e06889d58..4cce28b06 100644 --- a/src/empathy-rounded-rectangle.c +++ b/src/empathy-rounded-rectangle.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + #include <math.h> #include <clutter/clutter.h> |