/* * Copyright (C) 2007-2008 Guillaume Desmottes * * 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: Guillaume Desmottes */ #include "config.h" #include "tpaw-irc-network-dialog.h" #include #include #include "tpaw-builder.h" #include "tpaw-utils.h" #include "totem-subtitle-encoding.h" typedef struct { TpawIrcNetwork *network; GtkWidget *dialog; GtkWidget *button_close; GtkWidget *entry_network; GtkWidget *combobox_charset; GtkWidget *treeview_servers; GtkWidget *button_add; GtkWidget *button_remove; GtkWidget *button_up; GtkWidget *button_down; } TpawIrcNetworkDialog; static void irc_network_dialog_destroy_cb (GtkWidget *widget, TpawIrcNetworkDialog *dialog) { g_object_unref (dialog->network); g_slice_free (TpawIrcNetworkDialog, dialog); } static void irc_network_dialog_close_clicked_cb (GtkWidget *widget, TpawIrcNetworkDialog *dialog) { gtk_widget_destroy (dialog->dialog); } enum { COL_SRV_OBJ, COL_ADR, COL_PORT, COL_SSL }; static void add_server_to_store (GtkListStore *store, TpawIrcServer *server, GtkTreeIter *iter) { gchar *address; guint port; gboolean ssl; g_object_get (server, "address", &address, "port", &port, "ssl", &ssl, NULL); gtk_list_store_insert_with_values (store, iter, -1, COL_SRV_OBJ, server, COL_ADR, address, COL_PORT, port, COL_SSL, ssl, -1); g_free (address); } static void irc_network_dialog_setup (TpawIrcNetworkDialog *dialog) { gchar *name, *charset; GSList *servers, *l; GtkListStore *store; g_object_get (dialog->network, "name", &name, "charset", &charset, NULL); gtk_entry_set_text (GTK_ENTRY (dialog->entry_network), name); store = GTK_LIST_STORE (gtk_tree_view_get_model ( GTK_TREE_VIEW (dialog->treeview_servers))); servers = tpaw_irc_network_get_servers (dialog->network); for (l = servers; l != NULL; l = g_slist_next (l)) { TpawIrcServer *server = l->data; GtkTreeIter iter; add_server_to_store (store, server, &iter); } totem_subtitle_encoding_set (GTK_COMBO_BOX (dialog->combobox_charset), charset); g_slist_foreach (servers, (GFunc) g_object_unref, NULL); g_slist_free (servers); g_free (name); g_free (charset); } static void irc_network_dialog_address_edited_cb (GtkCellRendererText *renderer, gchar *path, gchar *new_text, TpawIrcNetworkDialog *dialog) { TpawIrcServer *server; GtkTreeModel *model; GtkTreePath *treepath; GtkTreeIter iter; model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_servers)); treepath = gtk_tree_path_new_from_string (path); gtk_tree_model_get_iter (model, &iter, treepath); gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1); gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_ADR, new_text, -1); g_object_set (server, "address", new_text, NULL); gtk_tree_path_free (treepath); g_object_unref (server); } static void irc_network_dialog_port_edited_cb (GtkCellRendererText *renderer, gchar *path, gchar *new_text, TpawIrcNetworkDialog *dialog) { TpawIrcServer *server; GtkTreeModel *model; GtkTreePath *treepath; GtkTreeIter iter; guint port; port = strtoul (new_text, NULL, 10); model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_servers)); treepath = gtk_tree_path_new_from_string (path); gtk_tree_model_get_iter (model, &iter, treepath); gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1); gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_PORT, port, -1); g_object_set (server, "port", port, NULL); gtk_tree_path_free (treepath); g_object_unref (server); } static void irc_network_dialog_ssl_toggled_cb (GtkCellRendererText *renderer, gchar *path, TpawIrcNetworkDialog *dialog) { TpawIrcServer *server; GtkTreeModel *model; GtkTreePath *treepath; GtkTreeIter iter; gboolean ssl; model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_servers)); treepath = gtk_tree_path_new_from_string (path); gtk_tree_model_get_iter (model, &iter, treepath); gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, COL_SSL, &ssl, -1); ssl = !ssl; gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_SSL, ssl, -1); g_object_set (server, "ssl", ssl, NULL); gtk_tree_path_free (treepath); g_object_unref (server); } static gboolean irc_network_dialog_network_focus_cb (GtkWidget *widget, GdkEventFocus *event, TpawIrcNetworkDialog *dialog) { const gchar *str; str = gtk_entry_get_text (GTK_ENTRY (widget)); g_object_set (dialog->network, "name", str, NULL); return FALSE; } static void irc_network_dialog_network_update_buttons (TpawIrcNetworkDialog *dialog) { GtkTreeSelection *selection; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; gboolean can_remove = FALSE, can_move_up = FALSE, can_move_down = FALSE; int selected; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW ( dialog->treeview_servers)); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { path = gtk_tree_model_get_path (model, &iter); selected = gtk_tree_path_get_indices (path)[0]; can_remove = TRUE; can_move_up = selected > 0; can_move_down = selected < gtk_tree_model_iter_n_children (model, NULL) - 1; gtk_tree_path_free (path); } gtk_widget_set_sensitive (dialog->button_remove, can_remove); gtk_widget_set_sensitive (dialog->button_up, can_move_up); gtk_widget_set_sensitive (dialog->button_down, can_move_down); } static void irc_network_dialog_button_add_clicked_cb (GtkWidget *widget, TpawIrcNetworkDialog *dialog) { TpawIrcServer *server; GtkListStore *store; GtkTreeIter iter; GtkTreePath *path; GtkTreeViewColumn *column; store = GTK_LIST_STORE (gtk_tree_view_get_model ( GTK_TREE_VIEW (dialog->treeview_servers))); server = tpaw_irc_server_new (_("new server"), 6667, FALSE); tpaw_irc_network_append_server (dialog->network, server); add_server_to_store (store, server, &iter); path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter); column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_servers), 0); gtk_tree_view_set_cursor (GTK_TREE_VIEW (dialog->treeview_servers), path, column, TRUE); irc_network_dialog_network_update_buttons (dialog); gtk_tree_path_free (path); g_object_unref (server); } static void irc_network_dialog_button_remove_clicked_cb (GtkWidget *widget, TpawIrcNetworkDialog *dialog) { GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; TpawIrcServer *server; selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (dialog->treeview_servers)); if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1); gtk_list_store_remove (GTK_LIST_STORE (model), &iter); tpaw_irc_network_remove_server (dialog->network, server); irc_network_dialog_network_update_buttons (dialog); g_object_unref (server); } static void irc_network_dialog_button_up_clicked_cb (GtkWidget *widget, TpawIrcNetworkDialog *dialog) { GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter, iter_prev; GtkTreePath *path; gint *pos; TpawIrcServer *server; selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (dialog->treeview_servers)); if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; path = gtk_tree_model_get_path (model, &iter); if (!gtk_tree_path_prev (path)) { gtk_tree_path_free (path); return; } gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1); gtk_tree_model_get_iter (model, &iter_prev, path); gtk_list_store_swap (GTK_LIST_STORE (model), &iter_prev, &iter); pos = gtk_tree_path_get_indices (path); tpaw_irc_network_set_server_position (dialog->network, server, *pos); irc_network_dialog_network_update_buttons (dialog); g_object_unref (server); gtk_tree_path_free (path); } static void irc_network_dialog_button_down_clicked_cb (GtkWidget *widget, TpawIrcNetworkDialog *dialog) { GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter, iter_prev; GtkTreePath *path; TpawIrcServer *server; gint *pos; selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (dialog->treeview_servers)); if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; path = gtk_tree_model_get_path (model, &iter); gtk_tree_path_next (path); if (!gtk_tree_model_get_iter (model, &iter_prev, path)) { gtk_tree_path_free (path); return; } gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1); gtk_list_store_swap (GTK_LIST_STORE (model), &iter_prev, &iter); pos = gtk_tree_path_get_indices (path); tpaw_irc_network_set_server_position (dialog->network, server, *pos); irc_network_dialog_network_update_buttons (dialog); gtk_tree_path_free (path); } static void irc_network_dialog_selection_changed_cb (GtkTreeSelection *treeselection, TpawIrcNetworkDialog *dialog) { irc_network_dialog_network_update_buttons (dialog); } static void irc_network_dialog_combobox_charset_changed_cb (GtkWidget *combobox, TpawIrcNetworkDialog *dialog) { const gchar *charset; charset = totem_subtitle_encoding_get_selected (GTK_COMBO_BOX (combobox)); g_object_set (dialog->network, "charset", charset, NULL); } static void change_network (TpawIrcNetworkDialog *dialog, TpawIrcNetwork *network) { GtkListStore *store; if (dialog->network == network) /* No need to change */ return; if (dialog->network != NULL) { g_object_unref (dialog->network); } dialog->network = network; g_object_ref (network); store = GTK_LIST_STORE (gtk_tree_view_get_model ( GTK_TREE_VIEW (dialog->treeview_servers))); gtk_list_store_clear (store); irc_network_dialog_setup (dialog); } /** * tpaw_irc_network_dialog_show: * @network: the #TpawIrcNetwork to configure * @parent: the parent of this dialog * * Display a dialog to configure a given #TpawIrcNetwork. * This function is a singleton so if a configuration dialog already * exists we use this one to edit the network. * * Returns: The displayed #GtkDialog */ GtkWidget * tpaw_irc_network_dialog_show (TpawIrcNetwork *network, GtkWidget *parent) { static TpawIrcNetworkDialog *dialog = NULL; GtkBuilder *gui; GtkListStore *store; GtkCellRenderer *renderer; GtkAdjustment *adjustment; GtkTreeSelection *selection; GtkTreeViewColumn *column; GtkWidget *sw, *toolbar; GtkStyleContext *context; g_return_val_if_fail (network != NULL, NULL); if (dialog != NULL) { change_network (dialog, network); gtk_window_present (GTK_WINDOW (dialog->dialog)); return dialog->dialog; } dialog = g_slice_new0 (TpawIrcNetworkDialog); dialog->network = network; g_object_ref (dialog->network); gui = tpaw_builder_get_resource (TPAW_ACCOUNT_WIDGETS_RESOURCES_PREFIX "/tpaw-account-widget-irc.ui", "irc_network_dialog", &dialog->dialog, "button_close", &dialog->button_close, "entry_network", &dialog->entry_network, "combobox_charset", &dialog->combobox_charset, "treeview_servers", &dialog->treeview_servers, "button_add", &dialog->button_add, "button_remove", &dialog->button_remove, "button_up", &dialog->button_up, "button_down", &dialog->button_down, "scrolledwindow_network_server", &sw, "toolbar_network_server", &toolbar, NULL); store = gtk_list_store_new (4, G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_BOOLEAN); gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->treeview_servers), GTK_TREE_MODEL (store)); g_object_unref (store); /* address */ renderer = gtk_cell_renderer_text_new (); g_object_set (renderer, "editable", TRUE, NULL); g_signal_connect (renderer, "edited", G_CALLBACK (irc_network_dialog_address_edited_cb), dialog); gtk_tree_view_insert_column_with_attributes ( GTK_TREE_VIEW (dialog->treeview_servers), -1, _("Server"), renderer, "text", COL_ADR, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_servers), 0); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_column_set_expand (column, TRUE); /* port */ adjustment = (GtkAdjustment *) gtk_adjustment_new (6667, 1, G_MAXUINT16, 1, 10, 0); renderer = gtk_cell_renderer_spin_new (); g_object_set (renderer, "editable", TRUE, "adjustment", adjustment, NULL); g_signal_connect (renderer, "edited", G_CALLBACK (irc_network_dialog_port_edited_cb), dialog); gtk_tree_view_insert_column_with_attributes ( GTK_TREE_VIEW (dialog->treeview_servers), -1, _("Port"), renderer, "text", COL_PORT, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_servers), 1); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_column_set_expand (column, TRUE); /* SSL */ renderer = gtk_cell_renderer_toggle_new (); g_object_set (renderer, "activatable", TRUE, NULL); g_signal_connect (renderer, "toggled", G_CALLBACK (irc_network_dialog_ssl_toggled_cb), dialog); gtk_tree_view_insert_column_with_attributes ( GTK_TREE_VIEW (dialog->treeview_servers), -1, _("SSL"), renderer, "active", COL_SSL, NULL); selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (dialog->treeview_servers)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_servers), 2); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_column_set_expand (column, TRUE); /* charset */ totem_subtitle_encoding_init (GTK_COMBO_BOX (dialog->combobox_charset)); irc_network_dialog_setup (dialog); tpaw_builder_connect (gui, dialog, "irc_network_dialog", "destroy", irc_network_dialog_destroy_cb, "button_close", "clicked", irc_network_dialog_close_clicked_cb, "entry_network", "focus-out-event", irc_network_dialog_network_focus_cb, "button_add", "clicked", irc_network_dialog_button_add_clicked_cb, "button_remove", "clicked", irc_network_dialog_button_remove_clicked_cb, "button_up", "clicked", irc_network_dialog_button_up_clicked_cb, "button_down", "clicked", irc_network_dialog_button_down_clicked_cb, "combobox_charset", "changed", irc_network_dialog_combobox_charset_changed_cb, NULL); g_object_unref (gui); g_object_add_weak_pointer (G_OBJECT (dialog->dialog), (gpointer) &dialog); g_signal_connect (selection, "changed", G_CALLBACK (irc_network_dialog_selection_changed_cb), dialog); gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), GTK_WINDOW (parent)); gtk_window_set_modal (GTK_WINDOW (dialog->dialog), TRUE); /* join the add/remove toolbar to the treeview */ context = gtk_widget_get_style_context (sw); gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM); context = gtk_widget_get_style_context (toolbar); gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP); irc_network_dialog_network_update_buttons (dialog); gtk_widget_show_all (dialog->dialog); gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE); return dialog->dialog; }