/* * Copyright (C) 2008 Collabora Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program 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 * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA * * Authors: Jonny Lamb * */ #include #include #include #include #include #include #include "empathy-import-dialog.h" #include "empathy-import-pidgin.h" #define DEBUG_FLAG EMPATHY_DEBUG_OTHER #include #include #include #include #include typedef struct { GtkWidget *window; GtkWidget *treeview; GtkWidget *button_ok; GtkWidget *button_cancel; GList *accounts; } EmpathyImportDialog; enum { COL_IMPORT = 0, COL_PROTOCOL, COL_NAME, COL_SOURCE, COL_ACCOUNT_DATA, COL_COUNT }; EmpathyImportAccountData * empathy_import_account_data_new (const gchar *source) { EmpathyImportAccountData *data; g_return_val_if_fail (!EMP_STR_EMPTY (source), NULL); data = g_slice_new0 (EmpathyImportAccountData); data->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); data->source = g_strdup (source); data->protocol = NULL; data->connection_manager = NULL; return data; } void empathy_import_account_data_free (EmpathyImportAccountData *data) { if (data == NULL) return; if (data->protocol != NULL) g_free (data->protocol); if (data->connection_manager != NULL) g_free (data->connection_manager); if (data->settings != NULL) g_hash_table_destroy (data->settings); if (data->source != NULL) g_free (data->source); g_slice_free (EmpathyImportAccountData, data); } static void import_dialog_create_account_cb (GObject *source, GAsyncResult *result, gpointer user_data) { EmpathyImportAccountData *data = (EmpathyImportAccountData *) user_data; EmpathyAccount *account; GError *error = NULL; account = empathy_account_manager_create_account_finish ( EMPATHY_ACCOUNT_MANAGER (source), result, &error); if (account == NULL) { DEBUG ("Failed to create account: %s", error ? error->message : "No error given"); g_clear_error (&error); empathy_import_account_data_free (data); return; } DEBUG ("account created\n"); g_object_unref (account); } static void import_dialog_add_account (EmpathyImportAccountData *data) { EmpathyAccountManager *account_manager; gchar *display_name; GHashTable *properties; GValue *username; account_manager = empathy_account_manager_dup_singleton (); DEBUG ("connection_manager: %s\n", data->connection_manager); /* Set the display name of the account */ username = g_hash_table_lookup (data->settings, "account"); display_name = g_strdup_printf ("%s (%s)", data->protocol, g_value_get_string (username)); DEBUG ("display name: %s\n", display_name); properties = g_hash_table_new (NULL, NULL); empathy_account_manager_create_account_async (account_manager, (const gchar*) data->connection_manager, data->protocol, display_name, data->settings, properties, import_dialog_create_account_cb, NULL); g_hash_table_unref (properties); g_free (display_name); g_object_unref (account_manager); } static gboolean import_dialog_account_id_in_list (GList *accounts, const gchar *account_id) { GList *l; for (l = accounts; l; l = l->next) { EmpathyAccount *account = l->data; const gchar *account_string; GValue *value; gboolean result; const GHashTable *parameters; parameters = empathy_account_get_parameters (account); value = g_hash_table_lookup ((GHashTable *) parameters, "account"); if (value == NULL) continue; account_string = g_value_get_string (value); result = tp_strdiff (account_string, account_id); if (!result) return TRUE; } return FALSE; } static gboolean protocol_is_supported (EmpathyImportAccountData *data) { EmpathyConnectionManagers *cm = empathy_connection_managers_dup_singleton (); GList *cms = empathy_connection_managers_get_cms (cm); GList *l; gboolean proto_is_supported = FALSE; for (l = cms; l; l = l->next) { TpConnectionManager *tp_cm = l->data; const gchar *cm_name = tp_connection_manager_get_name (tp_cm); if (tp_connection_manager_has_protocol (tp_cm, (const gchar*)data->protocol)) { data->connection_manager = g_strdup (cm_name); proto_is_supported = TRUE; break; } } g_object_unref (cm); return proto_is_supported; } static void import_dialog_add_accounts_to_model (EmpathyImportDialog *dialog) { GtkTreeModel *model; GtkTreeIter iter; GList *l; EmpathyAccountManager *manager = empathy_account_manager_dup_singleton (); model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); for (l = dialog->accounts; l; l = l->next) { GValue *value; EmpathyImportAccountData *data = l->data; gboolean import; GList *accounts; if (!protocol_is_supported (data)) continue; value = g_hash_table_lookup (data->settings, "account"); accounts = empathy_account_manager_dup_accounts (manager); /* Only set the "Import" cell to be active if there isn't already an * account set up with the same account id. */ import = !import_dialog_account_id_in_list (accounts, g_value_get_string (value)); g_list_foreach (accounts, (GFunc) g_object_unref, NULL); g_list_free (accounts); gtk_list_store_append (GTK_LIST_STORE (model), &iter); gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_IMPORT, import, COL_PROTOCOL, data->protocol, COL_NAME, g_value_get_string (value), COL_SOURCE, data->source, COL_ACCOUNT_DATA, data, -1); } g_object_unref (manager); } static void import_dialog_cell_toggled_cb (GtkCellRendererToggle *cell_renderer, const gchar *path_str, EmpathyImportDialog *dialog) { GtkTreeModel *model; GtkTreeIter iter; GtkTreePath *path; path = gtk_tree_path_new_from_string (path_str); model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); gtk_tree_model_get_iter (model, &iter, path); gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_IMPORT, !gtk_cell_renderer_toggle_get_active (cell_renderer), -1); gtk_tree_path_free (path); } static void import_dialog_set_up_account_list (EmpathyImportDialog *dialog) { GtkListStore *store; GtkTreeView *view; GtkTreeViewColumn *column; GtkCellRenderer *cell; store = gtk_list_store_new (COL_COUNT, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->treeview), GTK_TREE_MODEL (store)); g_object_unref (store); view = GTK_TREE_VIEW (dialog->treeview); gtk_tree_view_set_headers_visible (view, TRUE); /* Import column */ cell = gtk_cell_renderer_toggle_new (); gtk_tree_view_insert_column_with_attributes (view, -1, /* Translators: this is the header of a treeview column */ _("Import"), cell, "active", COL_IMPORT, NULL); g_signal_connect (cell, "toggled", G_CALLBACK (import_dialog_cell_toggled_cb), dialog); /* Protocol column */ column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (column, _("Protocol")); gtk_tree_view_column_set_expand (column, TRUE); gtk_tree_view_append_column (view, column); cell = gtk_cell_renderer_text_new (); g_object_set (cell, "editable", FALSE, NULL); gtk_tree_view_column_pack_start (column, cell, TRUE); gtk_tree_view_column_add_attribute (column, cell, "text", COL_PROTOCOL); /* Account column */ column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (column, _("Account")); gtk_tree_view_column_set_expand (column, TRUE); gtk_tree_view_append_column (view, column); cell = gtk_cell_renderer_text_new (); g_object_set (cell, "editable", FALSE, NULL); gtk_tree_view_column_pack_start (column, cell, TRUE); gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME); /* Source column */ column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (column, _("Source")); gtk_tree_view_column_set_expand (column, TRUE); gtk_tree_view_append_column (view, column); cell = gtk_cell_renderer_text_new (); g_object_set (cell, "editable", FALSE, NULL); gtk_tree_view_column_pack_start (column, cell, TRUE); gtk_tree_view_column_add_attribute (column, cell, "text", COL_SOURCE); import_dialog_add_accounts_to_model (dialog); } static gboolean import_dialog_tree_model_foreach (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) { gboolean to_import; EmpathyImportAccountData *data; gtk_tree_model_get (model, iter, COL_IMPORT, &to_import, COL_ACCOUNT_DATA, &data, -1); if (to_import) import_dialog_add_account (data); return FALSE; } static void import_dialog_response_cb (GtkWidget *widget, gint response, EmpathyImportDialog *dialog) { if (response == GTK_RESPONSE_OK) { GtkTreeModel *model; model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); gtk_tree_model_foreach (model, import_dialog_tree_model_foreach, dialog); } gtk_widget_destroy (dialog->window); } static void import_dialog_destroy_cb (GtkWidget *widget, EmpathyImportDialog *dialog) { g_list_foreach (dialog->accounts, (GFunc) empathy_import_account_data_free, NULL); g_list_free (dialog->accounts); g_slice_free (EmpathyImportDialog, dialog); } gboolean empathy_import_dialog_accounts_to_import (void) { return empathy_import_pidgin_accounts_to_import (); } void empathy_import_dialog_show (GtkWindow *parent, gboolean warning) { static EmpathyImportDialog *dialog = NULL; GtkBuilder *gui; gchar *filename; GList *accounts = NULL; /* This window is a singleton. If it already exist, present it */ if (dialog) { gtk_window_present (GTK_WINDOW (dialog->window)); return; } /* Load all accounts from all supported applications */ accounts = g_list_concat (accounts, empathy_import_pidgin_load ()); /* Check if we have accounts to import before creating the window */ if (!accounts) { GtkWidget *message; if (warning) { message = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, _("No accounts to import could be found. Empathy currently only " "supports importing accounts from Pidgin.")); gtk_dialog_run (GTK_DIALOG (message)); gtk_widget_destroy (message); } else DEBUG ("No accounts to import; closing dialog silently."); return; } /* We have accounts, let's display the window with them */ dialog = g_slice_new0 (EmpathyImportDialog); dialog->accounts = accounts; filename = empathy_file_lookup ("empathy-import-dialog.ui", "src"); gui = empathy_builder_get_file (filename, "import_dialog", &dialog->window, "treeview", &dialog->treeview, NULL); empathy_builder_connect (gui, dialog, "import_dialog", "destroy", import_dialog_destroy_cb, "import_dialog", "response", import_dialog_response_cb, NULL); g_object_add_weak_pointer (G_OBJECT (dialog->window), (gpointer) &dialog); g_free (filename); g_object_unref (gui); if (parent) gtk_window_set_transient_for (GTK_WINDOW (dialog->window), parent); import_dialog_set_up_account_list (dialog); gtk_widget_show (dialog->window); }