2 * Copyright (C) 2007-2008 Guillaume Desmottes
3 * Copyright (C) 2010 Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Authors: Guillaume Desmottes <gdesmott@gnome.org>
28 #include <glib/gi18n-lib.h>
31 #include <libempathy/empathy-utils.h>
32 #include <libempathy/empathy-irc-network-manager.h>
34 #include "empathy-irc-network-dialog.h"
35 #include "empathy-ui-utils.h"
36 #include "empathy-live-search.h"
38 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT | EMPATHY_DEBUG_IRC
39 #include <libempathy/empathy-debug.h>
41 #include "empathy-irc-network-chooser-dialog.h"
43 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIrcNetworkChooserDialog)
51 EmpathyAccountSettings
*settings
;
52 EmpathyIrcNetwork
*network
;
54 EmpathyIrcNetworkManager
*network_manager
;
59 GtkTreeModelFilter
*filter
;
61 GtkWidget
*select_button
;
64 } EmpathyIrcNetworkChooserDialogPriv
;
71 G_DEFINE_TYPE (EmpathyIrcNetworkChooserDialog
, empathy_irc_network_chooser_dialog
,
75 empathy_irc_network_chooser_dialog_set_property (GObject
*object
,
80 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (object
);
85 priv
->settings
= g_value_dup_object (value
);
88 priv
->network
= g_value_dup_object (value
);
91 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
97 empathy_irc_network_chooser_dialog_get_property (GObject
*object
,
102 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (object
);
107 g_value_set_object (value
, priv
->settings
);
110 g_value_set_object (value
, priv
->network
);
113 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
118 /* The iter returned by *it is a priv->store iter (not a filter one) */
119 static EmpathyIrcNetwork
*
120 dup_selected_network (EmpathyIrcNetworkChooserDialog
*self
,
123 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
124 EmpathyIrcNetwork
*network
;
125 GtkTreeSelection
*selection
;
129 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->treeview
));
130 if (!gtk_tree_selection_get_selected (selection
, &model
, &iter
))
133 gtk_tree_model_get (model
, &iter
, COL_NETWORK_OBJ
, &network
, -1);
134 g_assert (network
!= NULL
);
138 gtk_tree_model_filter_convert_iter_to_child_iter (priv
->filter
, it
,
146 treeview_changed_cb (GtkTreeView
*treeview
,
147 EmpathyIrcNetworkChooserDialog
*self
)
149 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
150 EmpathyIrcNetwork
*network
;
152 network
= dup_selected_network (self
, NULL
);
153 if (network
== priv
->network
)
155 g_object_unref (network
);
159 tp_clear_object (&priv
->network
);
160 /* Transfer the reference */
161 priv
->network
= network
;
163 priv
->changed
= TRUE
;
166 /* Take a filter iterator as argument */
168 scroll_to_iter (EmpathyIrcNetworkChooserDialog
*self
,
169 GtkTreeIter
*filter_iter
)
171 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
174 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (priv
->filter
), filter_iter
);
178 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv
->treeview
),
179 path
, NULL
, FALSE
, 0, 0);
181 gtk_tree_path_free (path
);
185 /* Take a filter iterator as argument */
187 select_iter (EmpathyIrcNetworkChooserDialog
*self
,
188 GtkTreeIter
*filter_iter
,
189 gboolean emulate_changed
)
191 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
192 GtkTreeSelection
*selection
;
195 /* Select the network */
196 selection
= gtk_tree_view_get_selection (
197 GTK_TREE_VIEW (priv
->treeview
));
199 gtk_tree_selection_select_iter (selection
, filter_iter
);
201 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (priv
->filter
), filter_iter
);
204 gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv
->treeview
), path
,
207 gtk_tree_path_free (path
);
210 /* Scroll to the selected network */
211 scroll_to_iter (self
, filter_iter
);
215 /* gtk_tree_selection_select_iter doesn't fire the 'cursor-changed' signal
216 * so we call the callback manually. */
217 treeview_changed_cb (GTK_TREE_VIEW (priv
->treeview
), self
);
222 fill_store (EmpathyIrcNetworkChooserDialog
*self
)
224 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
225 GSList
*networks
, *l
;
227 networks
= empathy_irc_network_manager_get_networks (
228 priv
->network_manager
);
230 for (l
= networks
; l
!= NULL
; l
= g_slist_next (l
))
232 EmpathyIrcNetwork
*network
= l
->data
;
235 gtk_list_store_insert_with_values (priv
->store
, &iter
, -1,
236 COL_NETWORK_OBJ
, network
,
237 COL_NETWORK_NAME
, empathy_irc_network_get_name (network
),
240 if (network
== priv
->network
)
242 GtkTreeIter filter_iter
;
244 /* Convert to a filter iter */
245 g_assert (gtk_tree_model_filter_convert_child_iter_to_iter (
246 priv
->filter
, &filter_iter
, &iter
));
248 select_iter (self
, &filter_iter
, FALSE
);
251 g_object_unref (network
);
254 g_slist_free (networks
);
258 irc_network_dialog_destroy_cb (GtkWidget
*widget
,
259 EmpathyIrcNetworkChooserDialog
*self
)
261 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
262 EmpathyIrcNetwork
*network
;
263 GtkTreeIter iter
, filter_iter
;
265 priv
->changed
= TRUE
;
267 network
= dup_selected_network (self
, &iter
);
271 /* name could be changed */
272 gtk_list_store_set (GTK_LIST_STORE (priv
->store
), &iter
,
273 COL_NETWORK_NAME
, empathy_irc_network_get_name (network
), -1);
275 /* Convert to a filter iter */
276 g_assert (gtk_tree_model_filter_convert_child_iter_to_iter (priv
->filter
,
277 &filter_iter
, &iter
));
279 scroll_to_iter (self
, &iter
);
281 g_object_unref (network
);
285 display_irc_network_dialog (EmpathyIrcNetworkChooserDialog
*self
,
286 EmpathyIrcNetwork
*network
)
290 dialog
= empathy_irc_network_dialog_show (network
, NULL
);
292 g_signal_connect (dialog
, "destroy",
293 G_CALLBACK (irc_network_dialog_destroy_cb
), self
);
297 edit_network (EmpathyIrcNetworkChooserDialog
*self
)
299 EmpathyIrcNetwork
*network
;
301 network
= dup_selected_network (self
, NULL
);
305 display_irc_network_dialog (self
, network
);
307 g_object_unref (network
);
311 add_network (EmpathyIrcNetworkChooserDialog
*self
)
313 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
314 EmpathyIrcNetwork
*network
;
315 GtkTreeIter iter
, filter_iter
;
317 network
= empathy_irc_network_new (_("New Network"));
318 empathy_irc_network_manager_add (priv
->network_manager
, network
);
320 gtk_list_store_insert_with_values (priv
->store
, &iter
, -1,
321 COL_NETWORK_OBJ
, network
,
322 COL_NETWORK_NAME
, empathy_irc_network_get_name (network
),
325 /* Convert to a filter iter */
326 g_assert (gtk_tree_model_filter_convert_child_iter_to_iter (priv
->filter
,
327 &filter_iter
, &iter
));
329 select_iter (self
, &filter_iter
, TRUE
);
331 display_irc_network_dialog (self
, network
);
333 g_object_unref (network
);
337 remove_network (EmpathyIrcNetworkChooserDialog
*self
)
339 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
340 EmpathyIrcNetwork
*network
;
343 network
= dup_selected_network (self
, &iter
);
347 DEBUG ("Remove network %s", empathy_irc_network_get_name (network
));
349 gtk_list_store_remove (priv
->store
, &iter
);
350 empathy_irc_network_manager_remove (priv
->network_manager
, network
);
352 /* Select next network */
353 if (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv
->store
), &iter
))
354 select_iter (self
, &iter
, TRUE
);
356 g_object_unref (network
);
360 dialog_response_cb (GtkDialog
*dialog
,
362 EmpathyIrcNetworkChooserDialog
*self
)
364 if (response
== GTK_RESPONSE_OK
)
366 else if (response
== GTK_RESPONSE_APPLY
)
368 else if (response
== GTK_RESPONSE_REJECT
)
369 remove_network (self
);
373 filter_visible_func (GtkTreeModel
*model
,
377 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (user_data
);
378 EmpathyIrcNetwork
*network
;
381 gtk_tree_model_get (model
, iter
, COL_NETWORK_OBJ
, &network
, -1);
383 visible
= empathy_live_search_match (EMPATHY_LIVE_SEARCH (priv
->search
),
384 empathy_irc_network_get_name (network
));
386 g_object_unref (network
);
392 search_text_notify_cb (EmpathyLiveSearch
*search
,
394 EmpathyIrcNetworkChooserDialog
*self
)
396 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
398 gboolean sensitive
= FALSE
;
400 gtk_tree_model_filter_refilter (priv
->filter
);
402 /* Select first matching network */
403 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv
->filter
), &iter
))
405 select_iter (self
, &iter
, TRUE
);
409 gtk_widget_set_sensitive (priv
->select_button
, sensitive
);
413 dialog_destroy_cb (GtkWidget
*widget
,
414 EmpathyIrcNetworkChooserDialog
*self
)
416 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
418 g_signal_handler_disconnect (priv
->search
, priv
->search_sig
);
422 empathy_irc_network_chooser_dialog_constructed (GObject
*object
)
424 EmpathyIrcNetworkChooserDialog
*self
= (EmpathyIrcNetworkChooserDialog
*) object
;
425 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
426 GtkDialog
*dialog
= GTK_DIALOG (self
);
427 GtkCellRenderer
*renderer
;
429 GtkTreeViewColumn
*column
;
432 g_assert (priv
->settings
!= NULL
);
434 gtk_window_set_title (GTK_WINDOW (self
), _("Choose an IRC network"));
436 /* Create store and treeview */
437 priv
->store
= gtk_list_store_new (2, G_TYPE_OBJECT
, G_TYPE_STRING
);
439 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv
->store
),
443 priv
->treeview
= gtk_tree_view_new ();
444 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv
->treeview
), FALSE
);
445 gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv
->treeview
), FALSE
);
447 column
= gtk_tree_view_column_new ();
448 gtk_tree_view_append_column (GTK_TREE_VIEW (priv
->treeview
), column
);
450 renderer
= gtk_cell_renderer_text_new ();
451 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (column
), renderer
, TRUE
);
452 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (column
),
454 "text", COL_NETWORK_NAME
,
457 /* add the treeview in a GtkScrolledWindow */
458 vbox
= gtk_dialog_get_content_area (dialog
);
460 scroll
= gtk_scrolled_window_new (NULL
, NULL
);
461 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll
),
462 GTK_POLICY_NEVER
, GTK_POLICY_AUTOMATIC
);
464 gtk_container_add (GTK_CONTAINER (scroll
), priv
->treeview
);
465 gtk_box_pack_start (GTK_BOX (vbox
), scroll
, TRUE
, TRUE
, 6);
468 priv
->search
= empathy_live_search_new (priv
->treeview
);
470 gtk_box_pack_start (GTK_BOX (vbox
), priv
->search
, FALSE
, TRUE
, 0);
472 priv
->filter
= GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (
473 GTK_TREE_MODEL (priv
->store
), NULL
));
474 gtk_tree_model_filter_set_visible_func (priv
->filter
,
475 filter_visible_func
, self
, NULL
);
477 gtk_tree_view_set_model (GTK_TREE_VIEW (priv
->treeview
),
478 GTK_TREE_MODEL (priv
->filter
));
480 priv
->search_sig
= g_signal_connect (priv
->search
, "notify::text",
481 G_CALLBACK (search_text_notify_cb
), self
);
484 gtk_dialog_add_buttons (dialog
,
485 GTK_STOCK_ADD
, GTK_RESPONSE_OK
,
486 GTK_STOCK_EDIT
, GTK_RESPONSE_APPLY
,
487 GTK_STOCK_REMOVE
, GTK_RESPONSE_REJECT
,
490 priv
->select_button
= gtk_dialog_add_button (dialog
, _("Select"),
495 g_signal_connect (priv
->treeview
, "cursor-changed",
496 G_CALLBACK (treeview_changed_cb
), self
);
498 g_signal_connect (self
, "response",
499 G_CALLBACK (dialog_response_cb
), self
);
500 g_signal_connect (self
, "destroy",
501 G_CALLBACK (dialog_destroy_cb
), self
);
503 /* Request a side ensuring to display at least some networks */
504 gtk_widget_set_size_request (GTK_WIDGET (self
), -1, 300);
508 empathy_irc_network_chooser_dialog_dispose (GObject
*object
)
510 EmpathyIrcNetworkManager
*self
= (EmpathyIrcNetworkManager
*) object
;
511 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
513 tp_clear_object (&priv
->settings
);
514 tp_clear_object (&priv
->network
);
515 tp_clear_object (&priv
->network_manager
);
516 tp_clear_object (&priv
->store
);
517 tp_clear_object (&priv
->filter
);
519 if (G_OBJECT_CLASS (empathy_irc_network_chooser_dialog_parent_class
)->dispose
)
520 G_OBJECT_CLASS (empathy_irc_network_chooser_dialog_parent_class
)->dispose (object
);
524 empathy_irc_network_chooser_dialog_class_init (EmpathyIrcNetworkChooserDialogClass
*klass
)
526 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
528 object_class
->get_property
= empathy_irc_network_chooser_dialog_get_property
;
529 object_class
->set_property
= empathy_irc_network_chooser_dialog_set_property
;
530 object_class
->constructed
= empathy_irc_network_chooser_dialog_constructed
;
531 object_class
->dispose
= empathy_irc_network_chooser_dialog_dispose
;
533 g_object_class_install_property (object_class
, PROP_SETTINGS
,
534 g_param_spec_object ("settings",
536 "The EmpathyAccountSettings to show and edit",
537 EMPATHY_TYPE_ACCOUNT_SETTINGS
,
538 G_PARAM_STATIC_STRINGS
| G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
540 g_object_class_install_property (object_class
, PROP_NETWORK
,
541 g_param_spec_object ("network",
543 "The EmpathyIrcNetwork selected in the treeview",
544 EMPATHY_TYPE_IRC_NETWORK
,
545 G_PARAM_STATIC_STRINGS
| G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
547 g_type_class_add_private (object_class
,
548 sizeof (EmpathyIrcNetworkChooserDialogPriv
));
552 empathy_irc_network_chooser_dialog_init (EmpathyIrcNetworkChooserDialog
*self
)
554 EmpathyIrcNetworkChooserDialogPriv
*priv
;
556 priv
= G_TYPE_INSTANCE_GET_PRIVATE (self
,
557 EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG
, EmpathyIrcNetworkChooserDialogPriv
);
560 priv
->network_manager
= empathy_irc_network_manager_dup_default ();
564 empathy_irc_network_chooser_dialog_new (EmpathyAccountSettings
*settings
,
565 EmpathyIrcNetwork
*network
)
567 return g_object_new (EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG
,
568 "settings", settings
,
574 empathy_irc_network_chooser_dialog_get_network (
575 EmpathyIrcNetworkChooserDialog
*self
)
577 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
579 return priv
->network
;
583 empathy_irc_network_chooser_dialog_get_changed (
584 EmpathyIrcNetworkChooserDialog
*self
)
586 EmpathyIrcNetworkChooserDialogPriv
*priv
= GET_PRIV (self
);
588 return priv
->changed
;