1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2002-2007 Imendio AB
4 * Copyright (C) 2007-2010 Collabora Ltd.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 * Authors: Xavier Claessens <xclaesse@gmail.com>
22 * Danielle Madeley <danielle.madeley@collabora.co.uk>
29 #include <gdk/gdkkeysyms.h>
30 #include <glib/gi18n.h>
32 #include <telepathy-glib/account-manager.h>
33 #include <telepathy-glib/util.h>
34 #include <folks/folks.h>
36 #include <libempathy/empathy-contact.h>
37 #include <libempathy/empathy-utils.h>
38 #include <libempathy/empathy-request-util.h>
39 #include <libempathy/empathy-chatroom-manager.h>
40 #include <libempathy/empathy-chatroom.h>
41 #include <libempathy/empathy-contact-list.h>
42 #include <libempathy/empathy-contact-manager.h>
43 #include <libempathy/empathy-gsettings.h>
44 #include <libempathy/empathy-individual-manager.h>
45 #include <libempathy/empathy-gsettings.h>
46 #include <libempathy/empathy-status-presets.h>
47 #include <libempathy/empathy-tp-contact-factory.h>
49 #include <libempathy-gtk/empathy-contact-dialogs.h>
50 #include <libempathy-gtk/empathy-contact-list-store.h>
51 #include <libempathy-gtk/empathy-contact-list-view.h>
52 #include <libempathy-gtk/empathy-live-search.h>
53 #include <libempathy-gtk/empathy-contact-blocking-dialog.h>
54 #include <libempathy-gtk/empathy-contact-search-dialog.h>
55 #include <libempathy-gtk/empathy-geometry.h>
56 #include <libempathy-gtk/empathy-gtk-enum-types.h>
57 #include <libempathy-gtk/empathy-individual-dialogs.h>
58 #include <libempathy-gtk/empathy-individual-store.h>
59 #include <libempathy-gtk/empathy-individual-view.h>
60 #include <libempathy-gtk/empathy-new-message-dialog.h>
61 #include <libempathy-gtk/empathy-new-call-dialog.h>
62 #include <libempathy-gtk/empathy-log-window.h>
63 #include <libempathy-gtk/empathy-presence-chooser.h>
64 #include <libempathy-gtk/empathy-sound-manager.h>
65 #include <libempathy-gtk/empathy-ui-utils.h>
67 #include "empathy-accounts-dialog.h"
68 #include "empathy-call-observer.h"
69 #include "empathy-chat-manager.h"
70 #include "empathy-main-window.h"
71 #include "empathy-preferences.h"
72 #include "empathy-about-dialog.h"
73 #include "empathy-debug-window.h"
74 #include "empathy-new-chatroom-dialog.h"
75 #include "empathy-map-view.h"
76 #include "empathy-chatrooms-window.h"
77 #include "empathy-event-manager.h"
78 #include "empathy-ft-manager.h"
79 #include "empathy-migrate-butterfly-logs.h"
81 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
82 #include <libempathy/empathy-debug.h>
84 /* Flashing delay for icons (milliseconds). */
85 #define FLASH_TIMEOUT 500
87 /* Minimum width of roster window if something goes wrong. */
90 /* Accels (menu shortcuts) can be configured and saved */
91 #define ACCELS_FILENAME "accels.txt"
93 /* Name in the geometry file */
94 #define GEOMETRY_NAME "main-window"
97 PAGE_CONTACT_LIST
= 0,
101 G_DEFINE_TYPE (EmpathyMainWindow
, empathy_main_window
, GTK_TYPE_WINDOW
);
103 #define GET_PRIV(self) ((EmpathyMainWindowPriv *)((EmpathyMainWindow *) self)->priv)
105 struct _EmpathyMainWindowPriv
{
106 EmpathyContactList
*contact_manager
;
107 EmpathyIndividualStore
*individual_store
;
108 EmpathyIndividualView
*individual_view
;
109 TpAccountManager
*account_manager
;
110 EmpathyChatroomManager
*chatroom_manager
;
111 EmpathyEventManager
*event_manager
;
112 EmpathySoundManager
*sound_mgr
;
113 EmpathyCallObserver
*call_observer
;
114 guint flash_timeout_id
;
118 GSettings
*gsettings_ui
;
119 GSettings
*gsettings_contacts
;
121 GtkWidget
*preferences
;
122 GtkWidget
*main_vbox
;
124 GtkWidget
*throbber_tool_item
;
125 GtkWidget
*presence_toolbar
;
126 GtkWidget
*presence_chooser
;
127 GtkWidget
*errors_vbox
;
128 GtkWidget
*auth_vbox
;
129 GtkWidget
*search_bar
;
131 GtkWidget
*no_entry_label
;
133 GtkToggleAction
*show_protocols
;
134 GtkRadioAction
*sort_by_name
;
135 GtkRadioAction
*sort_by_status
;
136 GtkRadioAction
*normal_with_avatars
;
137 GtkRadioAction
*normal_size
;
138 GtkRadioAction
*compact_size
;
140 GtkUIManager
*ui_manager
;
141 GtkAction
*view_history
;
142 GtkAction
*room_join_favorites
;
143 GtkWidget
*room_menu
;
144 GtkWidget
*room_separator
;
145 GtkWidget
*edit_context
;
146 GtkWidget
*edit_context_separator
;
148 GtkActionGroup
*balance_action_group
;
149 GtkAction
*view_balance_show_in_roster
;
150 GtkWidget
*balance_vbox
;
152 guint size_timeout_id
;
154 /* reffed TpAccount* => visible GtkInfoBar* */
157 /* EmpathyEvent* => visible GtkInfoBar* */
160 /* stores a mapping from TpAccount to Handler ID to prevent
161 * to listen more than once to the status-changed signal */
162 GHashTable
*status_changed_handlers
;
164 /* Actions that are enabled when there are connected accounts */
165 GList
*actions_connected
;
167 /* The idle event source to migrate butterfly's logs */
168 guint butterfly_log_migration_members_changed_id
;
172 main_window_flash_stop (EmpathyMainWindow
*window
)
174 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
176 if (priv
->flash_timeout_id
== 0) {
180 DEBUG ("Stop flashing");
181 g_source_remove (priv
->flash_timeout_id
);
182 priv
->flash_timeout_id
= 0;
183 priv
->flash_on
= FALSE
;
189 EmpathyMainWindow
*window
;
193 main_window_flash_foreach (GtkTreeModel
*model
,
198 FlashForeachData
*data
= (FlashForeachData
*) user_data
;
199 FolksIndividual
*individual
;
200 EmpathyContact
*contact
;
201 const gchar
*icon_name
;
202 GtkTreePath
*parent_path
= NULL
;
203 GtkTreeIter parent_iter
;
204 GdkPixbuf
*pixbuf
= NULL
;
206 gtk_tree_model_get (model
, iter
,
207 EMPATHY_INDIVIDUAL_STORE_COL_INDIVIDUAL
, &individual
,
210 if (individual
== NULL
)
213 contact
= empathy_contact_dup_from_folks_individual (individual
);
214 if (contact
!= data
->event
->contact
)
218 icon_name
= data
->event
->icon_name
;
219 pixbuf
= empathy_pixbuf_from_icon_name (icon_name
, GTK_ICON_SIZE_MENU
);
221 pixbuf
= empathy_individual_store_get_individual_status_icon (
222 GET_PRIV (data
->window
)->individual_store
,
225 g_object_ref (pixbuf
);
228 gtk_tree_store_set (GTK_TREE_STORE (model
), iter
,
229 EMPATHY_INDIVIDUAL_STORE_COL_ICON_STATUS
, pixbuf
,
232 /* To make sure the parent is shown correctly, we emit
233 * the row-changed signal on the parent so it prompts
234 * it to be refreshed by the filter func.
236 if (gtk_tree_model_iter_parent (model
, &parent_iter
, iter
)) {
237 parent_path
= gtk_tree_model_get_path (model
, &parent_iter
);
240 gtk_tree_model_row_changed (model
, parent_path
, &parent_iter
);
241 gtk_tree_path_free (parent_path
);
245 g_object_unref (individual
);
246 tp_clear_object (&contact
);
247 tp_clear_object (&pixbuf
);
253 main_window_flash_cb (EmpathyMainWindow
*window
)
255 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
258 gboolean found_event
= FALSE
;
259 FlashForeachData data
;
261 priv
->flash_on
= !priv
->flash_on
;
262 data
.on
= priv
->flash_on
;
263 model
= GTK_TREE_MODEL (priv
->individual_store
);
265 events
= empathy_event_manager_get_events (priv
->event_manager
);
266 for (l
= events
; l
; l
= l
->next
) {
267 data
.event
= l
->data
;
268 data
.window
= window
;
269 if (!data
.event
->contact
|| !data
.event
->must_ack
) {
274 gtk_tree_model_foreach (model
,
275 main_window_flash_foreach
,
280 main_window_flash_stop (window
);
287 main_window_flash_start (EmpathyMainWindow
*window
)
289 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
291 if (priv
->flash_timeout_id
!= 0) {
295 DEBUG ("Start flashing");
296 priv
->flash_timeout_id
= g_timeout_add (FLASH_TIMEOUT
,
297 (GSourceFunc
) main_window_flash_cb
,
299 main_window_flash_cb (window
);
303 main_window_remove_auth (EmpathyMainWindow
*window
,
306 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
307 GtkWidget
*error_widget
;
309 error_widget
= g_hash_table_lookup (priv
->auths
, event
);
310 if (error_widget
!= NULL
) {
311 gtk_widget_destroy (error_widget
);
312 g_hash_table_remove (priv
->auths
, event
);
317 main_window_auth_add_clicked_cb (GtkButton
*button
,
318 EmpathyMainWindow
*window
)
322 event
= g_object_get_data (G_OBJECT (button
), "event");
324 empathy_event_approve (event
);
326 main_window_remove_auth (window
, event
);
330 main_window_auth_close_clicked_cb (GtkButton
*button
,
331 EmpathyMainWindow
*window
)
335 event
= g_object_get_data (G_OBJECT (button
), "event");
337 empathy_event_decline (event
);
338 main_window_remove_auth (window
, event
);
342 main_window_auth_display (EmpathyMainWindow
*window
,
345 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
346 TpAccount
*account
= event
->account
;
348 GtkWidget
*content_area
;
351 GtkWidget
*add_button
;
352 GtkWidget
*close_button
;
353 GtkWidget
*action_area
;
354 GtkWidget
*action_table
;
355 const gchar
*icon_name
;
358 if (g_hash_table_lookup (priv
->auths
, event
) != NULL
) {
362 info_bar
= gtk_info_bar_new ();
363 gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar
), GTK_MESSAGE_QUESTION
);
365 gtk_widget_set_no_show_all (info_bar
, TRUE
);
366 gtk_box_pack_start (GTK_BOX (priv
->auth_vbox
), info_bar
, FALSE
, TRUE
, 0);
367 gtk_widget_show (info_bar
);
369 icon_name
= tp_account_get_icon_name (account
);
370 image
= gtk_image_new_from_icon_name (icon_name
, GTK_ICON_SIZE_SMALL_TOOLBAR
);
371 gtk_widget_show (image
);
373 str
= g_markup_printf_escaped ("<b>%s</b>\n%s",
374 tp_account_get_display_name (account
),
375 _("Password required"));
377 label
= gtk_label_new (str
);
378 gtk_label_set_use_markup (GTK_LABEL (label
), TRUE
);
379 gtk_label_set_ellipsize (GTK_LABEL (label
), PANGO_ELLIPSIZE_END
);
380 gtk_misc_set_alignment (GTK_MISC (label
), 0, 0.5);
381 gtk_widget_show (label
);
385 content_area
= gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar
));
386 gtk_box_pack_start (GTK_BOX (content_area
), image
, FALSE
, FALSE
, 0);
387 gtk_box_pack_start (GTK_BOX (content_area
), label
, TRUE
, TRUE
, 0);
389 image
= gtk_image_new_from_stock (GTK_STOCK_ADD
, GTK_ICON_SIZE_BUTTON
);
390 add_button
= gtk_button_new ();
391 gtk_button_set_image (GTK_BUTTON (add_button
), image
);
392 gtk_widget_set_tooltip_text (add_button
, _("Provide Password"));
393 gtk_widget_show (add_button
);
395 image
= gtk_image_new_from_stock (GTK_STOCK_CLOSE
, GTK_ICON_SIZE_BUTTON
);
396 close_button
= gtk_button_new ();
397 gtk_button_set_image (GTK_BUTTON (close_button
), image
);
398 gtk_widget_set_tooltip_text (close_button
, _("Disconnect"));
399 gtk_widget_show (close_button
);
401 action_table
= gtk_table_new (1, 2, FALSE
);
402 gtk_table_set_col_spacings (GTK_TABLE (action_table
), 6);
403 gtk_widget_show (action_table
);
405 action_area
= gtk_info_bar_get_action_area (GTK_INFO_BAR (info_bar
));
406 gtk_box_pack_start (GTK_BOX (action_area
), action_table
, FALSE
, FALSE
, 0);
408 gtk_table_attach (GTK_TABLE (action_table
), add_button
, 0, 1, 0, 1,
409 (GtkAttachOptions
) (GTK_SHRINK
),
410 (GtkAttachOptions
) (GTK_SHRINK
), 0, 0);
411 gtk_table_attach (GTK_TABLE (action_table
), close_button
, 1, 2, 0, 1,
412 (GtkAttachOptions
) (GTK_SHRINK
),
413 (GtkAttachOptions
) (GTK_SHRINK
), 0, 0);
415 g_object_set_data_full (G_OBJECT (info_bar
),
416 "event", event
, NULL
);
417 g_object_set_data_full (G_OBJECT (add_button
),
418 "event", event
, NULL
);
419 g_object_set_data_full (G_OBJECT (close_button
),
420 "event", event
, NULL
);
422 g_signal_connect (add_button
, "clicked",
423 G_CALLBACK (main_window_auth_add_clicked_cb
),
425 g_signal_connect (close_button
, "clicked",
426 G_CALLBACK (main_window_auth_close_clicked_cb
),
429 gtk_widget_show (priv
->auth_vbox
);
431 g_hash_table_insert (priv
->auths
, event
, info_bar
);
435 modify_event_count (GtkTreeModel
*model
,
440 FolksIndividual
*individual
;
441 EmpathyContact
*contact
;
444 gtk_tree_model_get (model
, iter
,
445 EMPATHY_INDIVIDUAL_STORE_COL_INDIVIDUAL
, &individual
,
446 EMPATHY_INDIVIDUAL_STORE_COL_EVENT_COUNT
, &count
,
449 if (individual
== NULL
)
452 increase
? count
++ : count
--;
454 contact
= empathy_contact_dup_from_folks_individual (individual
);
455 if (contact
== event
->contact
) {
456 gtk_tree_store_set (GTK_TREE_STORE (model
), iter
,
457 EMPATHY_INDIVIDUAL_STORE_COL_EVENT_COUNT
, count
, -1);
460 tp_clear_object (&contact
);
461 g_object_unref (individual
);
465 increase_event_count_foreach (GtkTreeModel
*model
,
470 EmpathyEvent
*event
= user_data
;
472 modify_event_count (model
, iter
, event
, TRUE
);
478 increase_event_count (EmpathyMainWindow
*self
,
481 EmpathyMainWindowPriv
*priv
= GET_PRIV (self
);
484 model
= GTK_TREE_MODEL (priv
->individual_store
);
486 gtk_tree_model_foreach (model
, increase_event_count_foreach
, event
);
490 decrease_event_count_foreach (GtkTreeModel
*model
,
495 EmpathyEvent
*event
= user_data
;
497 modify_event_count (model
, iter
, event
, FALSE
);
503 decrease_event_count (EmpathyMainWindow
*self
,
506 EmpathyMainWindowPriv
*priv
= GET_PRIV (self
);
509 model
= GTK_TREE_MODEL (priv
->individual_store
);
511 gtk_tree_model_foreach (model
, decrease_event_count_foreach
, event
);
515 main_window_event_added_cb (EmpathyEventManager
*manager
,
517 EmpathyMainWindow
*window
)
519 if (event
->contact
) {
520 increase_event_count (window
, event
);
522 main_window_flash_start (window
);
523 } else if (event
->type
== EMPATHY_EVENT_TYPE_AUTH
) {
524 main_window_auth_display (window
, event
);
529 main_window_event_removed_cb (EmpathyEventManager
*manager
,
531 EmpathyMainWindow
*window
)
533 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
534 FlashForeachData data
;
536 if (event
->type
== EMPATHY_EVENT_TYPE_AUTH
) {
537 main_window_remove_auth (window
, event
);
541 if (!event
->contact
) {
545 decrease_event_count (window
, event
);
549 data
.window
= window
;
550 gtk_tree_model_foreach (GTK_TREE_MODEL (priv
->individual_store
),
551 main_window_flash_foreach
,
556 main_window_row_activated_cb (EmpathyContactListView
*view
,
558 GtkTreeViewColumn
*col
,
559 EmpathyMainWindow
*window
)
561 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
562 EmpathyContact
*contact
= NULL
;
563 FolksIndividual
*individual
;
568 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (priv
->individual_view
));
569 gtk_tree_model_get_iter (model
, &iter
, path
);
571 gtk_tree_model_get (model
, &iter
,
572 EMPATHY_INDIVIDUAL_STORE_COL_INDIVIDUAL
,
576 if (individual
!= NULL
) {
577 contact
= empathy_contact_dup_from_folks_individual (individual
);
584 /* If the contact has an event activate it, otherwise the
585 * default handler of row-activated will be called. */
586 events
= empathy_event_manager_get_events (priv
->event_manager
);
587 for (l
= events
; l
; l
= l
->next
) {
588 EmpathyEvent
*event
= l
->data
;
590 if (event
->contact
== contact
) {
591 DEBUG ("Activate event");
592 empathy_event_activate (event
);
594 /* We don't want the default handler of this signal
595 * (e.g. open a chat) */
596 g_signal_stop_emission_by_name (view
, "row-activated");
601 g_object_unref (contact
);
603 tp_clear_object (&individual
);
607 main_window_row_deleted_cb (GtkTreeModel
*model
,
609 EmpathyMainWindow
*window
)
611 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
612 GtkTreeIter help_iter
;
614 if (!gtk_tree_model_get_iter_first (model
, &help_iter
)) {
617 if (empathy_individual_view_is_searching (
618 priv
->individual_view
)) {
621 tmp
= g_strdup_printf ("<b><span size='xx-large'>%s</span></b>",
622 _("No match found"));
624 gtk_label_set_markup (GTK_LABEL (priv
->no_entry_label
), tmp
);
627 gtk_label_set_line_wrap (GTK_LABEL (priv
->no_entry_label
),
630 gtk_notebook_set_current_page (
631 GTK_NOTEBOOK (priv
->notebook
), PAGE_NO_MATCH
);
637 main_window_row_inserted_cb (GtkTreeModel
*model
,
640 EmpathyMainWindow
*window
)
642 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
646 gtk_notebook_set_current_page (GTK_NOTEBOOK (priv
->notebook
),
648 gtk_widget_grab_focus (GTK_WIDGET (priv
->individual_view
));
653 main_window_remove_error (EmpathyMainWindow
*window
,
656 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
657 GtkWidget
*error_widget
;
659 error_widget
= g_hash_table_lookup (priv
->errors
, account
);
660 if (error_widget
!= NULL
) {
661 gtk_widget_destroy (error_widget
);
662 g_hash_table_remove (priv
->errors
, account
);
667 main_window_account_disabled_cb (TpAccountManager
*manager
,
669 EmpathyMainWindow
*window
)
671 main_window_remove_error (window
, account
);
675 main_window_error_retry_clicked_cb (GtkButton
*button
,
676 EmpathyMainWindow
*window
)
680 account
= g_object_get_data (G_OBJECT (button
), "account");
681 tp_account_reconnect_async (account
, NULL
, NULL
);
683 main_window_remove_error (window
, account
);
687 main_window_error_edit_clicked_cb (GtkButton
*button
,
688 EmpathyMainWindow
*window
)
692 account
= g_object_get_data (G_OBJECT (button
), "account");
694 empathy_accounts_dialog_show_application (
695 gtk_widget_get_screen (GTK_WIDGET (button
)),
696 account
, FALSE
, FALSE
);
698 main_window_remove_error (window
, account
);
702 main_window_error_close_clicked_cb (GtkButton
*button
,
703 EmpathyMainWindow
*window
)
707 account
= g_object_get_data (G_OBJECT (button
), "account");
708 main_window_remove_error (window
, account
);
712 main_window_error_display (EmpathyMainWindow
*window
,
715 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
717 GtkWidget
*content_area
;
720 GtkWidget
*retry_button
;
721 GtkWidget
*edit_button
;
722 GtkWidget
*close_button
;
723 GtkWidget
*action_area
;
724 GtkWidget
*action_table
;
726 const gchar
*icon_name
;
727 const gchar
*error_message
;
728 gboolean user_requested
;
731 empathy_account_get_error_message (account
, &user_requested
);
733 if (user_requested
) {
737 str
= g_markup_printf_escaped ("<b>%s</b>\n%s",
738 tp_account_get_display_name (account
),
741 info_bar
= g_hash_table_lookup (priv
->errors
, account
);
743 label
= g_object_get_data (G_OBJECT (info_bar
), "label");
745 /* Just set the latest error and return */
746 gtk_label_set_markup (GTK_LABEL (label
), str
);
752 info_bar
= gtk_info_bar_new ();
753 gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar
), GTK_MESSAGE_ERROR
);
755 gtk_widget_set_no_show_all (info_bar
, TRUE
);
756 gtk_box_pack_start (GTK_BOX (priv
->errors_vbox
), info_bar
, FALSE
, TRUE
, 0);
757 gtk_widget_show (info_bar
);
759 icon_name
= tp_account_get_icon_name (account
);
760 image
= gtk_image_new_from_icon_name (icon_name
, GTK_ICON_SIZE_SMALL_TOOLBAR
);
761 gtk_widget_show (image
);
763 label
= gtk_label_new (str
);
764 gtk_label_set_use_markup (GTK_LABEL (label
), TRUE
);
765 gtk_label_set_ellipsize (GTK_LABEL (label
), PANGO_ELLIPSIZE_END
);
766 gtk_misc_set_alignment (GTK_MISC (label
), 0, 0.5);
767 gtk_widget_show (label
);
770 content_area
= gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar
));
771 gtk_box_pack_start (GTK_BOX (content_area
), image
, FALSE
, FALSE
, 0);
772 gtk_box_pack_start (GTK_BOX (content_area
), label
, TRUE
, TRUE
, 0);
774 image
= gtk_image_new_from_stock (GTK_STOCK_REFRESH
, GTK_ICON_SIZE_BUTTON
);
775 retry_button
= gtk_button_new ();
776 gtk_button_set_image (GTK_BUTTON (retry_button
), image
);
777 gtk_widget_set_tooltip_text (retry_button
, _("Reconnect"));
778 gtk_widget_show (retry_button
);
780 image
= gtk_image_new_from_stock (GTK_STOCK_EDIT
, GTK_ICON_SIZE_BUTTON
);
781 edit_button
= gtk_button_new ();
782 gtk_button_set_image (GTK_BUTTON (edit_button
), image
);
783 gtk_widget_set_tooltip_text (edit_button
, _("Edit Account"));
784 gtk_widget_show (edit_button
);
786 image
= gtk_image_new_from_stock (GTK_STOCK_CLOSE
, GTK_ICON_SIZE_BUTTON
);
787 close_button
= gtk_button_new ();
788 gtk_button_set_image (GTK_BUTTON (close_button
), image
);
789 gtk_widget_set_tooltip_text (close_button
, _("Close"));
790 gtk_widget_show (close_button
);
792 action_table
= gtk_table_new (1, 3, FALSE
);
793 gtk_table_set_col_spacings (GTK_TABLE (action_table
), 2);
794 gtk_widget_show (action_table
);
796 action_area
= gtk_info_bar_get_action_area (GTK_INFO_BAR (info_bar
));
797 gtk_box_pack_start (GTK_BOX (action_area
), action_table
, FALSE
, FALSE
, 0);
799 gtk_table_attach (GTK_TABLE (action_table
), retry_button
, 0, 1, 0, 1,
800 (GtkAttachOptions
) (GTK_SHRINK
),
801 (GtkAttachOptions
) (GTK_SHRINK
), 0, 0);
802 gtk_table_attach (GTK_TABLE (action_table
), edit_button
, 1, 2, 0, 1,
803 (GtkAttachOptions
) (GTK_SHRINK
),
804 (GtkAttachOptions
) (GTK_SHRINK
), 0, 0);
805 gtk_table_attach (GTK_TABLE (action_table
), close_button
, 2, 3, 0, 1,
806 (GtkAttachOptions
) (GTK_SHRINK
),
807 (GtkAttachOptions
) (GTK_SHRINK
), 0, 0);
809 g_object_set_data (G_OBJECT (info_bar
), "label", label
);
810 g_object_set_data_full (G_OBJECT (info_bar
),
811 "account", g_object_ref (account
),
813 g_object_set_data_full (G_OBJECT (edit_button
),
814 "account", g_object_ref (account
),
816 g_object_set_data_full (G_OBJECT (close_button
),
817 "account", g_object_ref (account
),
819 g_object_set_data_full (G_OBJECT (retry_button
),
820 "account", g_object_ref (account
),
823 g_signal_connect (edit_button
, "clicked",
824 G_CALLBACK (main_window_error_edit_clicked_cb
),
826 g_signal_connect (close_button
, "clicked",
827 G_CALLBACK (main_window_error_close_clicked_cb
),
829 g_signal_connect (retry_button
, "clicked",
830 G_CALLBACK (main_window_error_retry_clicked_cb
),
833 gtk_widget_set_tooltip_text (priv
->errors_vbox
, error_message
);
834 gtk_widget_show (priv
->errors_vbox
);
836 g_hash_table_insert (priv
->errors
, g_object_ref (account
), info_bar
);
840 main_window_update_status (EmpathyMainWindow
*window
)
842 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
843 gboolean connected
, connecting
;
846 connected
= empathy_account_manager_get_accounts_connected (&connecting
);
848 /* Update the spinner state */
850 gtk_spinner_start (GTK_SPINNER (priv
->throbber
));
851 gtk_widget_show (priv
->throbber_tool_item
);
853 gtk_spinner_stop (GTK_SPINNER (priv
->throbber
));
854 gtk_widget_hide (priv
->throbber_tool_item
);
857 /* Update widgets sensibility */
858 for (l
= priv
->actions_connected
; l
; l
= l
->next
) {
859 gtk_action_set_sensitive (l
->data
, connected
);
862 /* Update favourite rooms sensitivity */
863 children
= gtk_container_get_children (GTK_CONTAINER (priv
->room_menu
));
864 for (l
= children
; l
!= NULL
; l
= l
->next
) {
865 if (g_object_get_data (G_OBJECT (l
->data
), "is_favorite") != NULL
) {
866 gtk_widget_set_sensitive (GTK_WIDGET (l
->data
), connected
);
869 g_list_free (children
);
873 main_window_account_to_action_name (TpAccount
*account
)
877 /* action names can't have '/' in them, replace it with '.' */
878 r
= g_strdup (tp_account_get_path_suffix (account
));
879 r
= g_strdelimit (r
, "/", '.');
885 main_window_balance_activate_cb (GtkAction
*action
,
886 EmpathyMainWindow
*window
)
890 uri
= g_object_get_data (G_OBJECT (action
), "manage-credit-uri");
892 if (!tp_str_empty (uri
)) {
893 DEBUG ("Top-up credit URI: %s", uri
);
894 empathy_url_show (GTK_WIDGET (window
), uri
);
896 DEBUG ("unknown protocol for top-up");
901 main_window_balance_update_balance (GtkAction
*action
,
904 TpAccount
*account
= g_object_get_data (G_OBJECT (action
), "account");
907 guint scale
= G_MAXINT32
;
908 const gchar
*currency
= "";
911 if (!tp_connection_get_balance (conn
, &amount
, &scale
, ¤cy
))
915 scale
== G_MAXINT32
&&
916 tp_str_empty (currency
)) {
917 /* unknown balance */
918 money
= g_strdup ("--");
920 char *tmp
= empathy_format_currency (amount
, scale
, currency
);
922 money
= g_strdup_printf ("%s %s", currency
, tmp
);
926 /* Translators: this string will be something like:
927 * Top up My Account ($1.23)..." */
928 str
= g_strdup_printf (_("Top up %s (%s)..."),
929 tp_account_get_display_name (account
),
932 gtk_action_set_label (action
, str
);
935 /* update the money label in the roster */
936 label
= g_object_get_data (G_OBJECT (action
), "money-label");
938 gtk_label_set_text (GTK_LABEL (label
), money
);
943 main_window_balance_changed_cb (TpConnection
*conn
,
946 const gchar
*currency
,
949 main_window_balance_update_balance (action
, conn
);
953 main_window_setup_balance_create_action (EmpathyMainWindow
*window
,
956 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
960 GError
*error
= NULL
;
962 /* create the action group if required */
963 if (priv
->balance_action_group
== NULL
) {
964 priv
->balance_action_group
=
965 gtk_action_group_new ("balance-action-group");
967 gtk_ui_manager_insert_action_group (priv
->ui_manager
,
968 priv
->balance_action_group
, -1);
971 /* create the action */
972 name
= main_window_account_to_action_name (account
);
973 action
= gtk_action_new (name
,
974 tp_account_get_display_name (account
),
975 _("Top up account credit"),
977 g_object_bind_property (account
, "icon-name", action
, "icon-name",
978 G_BINDING_SYNC_CREATE
);
980 g_object_set_data (G_OBJECT (action
), "account", account
);
981 g_signal_connect (action
, "activate",
982 G_CALLBACK (main_window_balance_activate_cb
), window
);
984 gtk_action_group_add_action (priv
->balance_action_group
, action
);
985 g_object_unref (action
);
987 ui
= g_strdup_printf (
989 " <menubar name='menubar'>"
990 " <menu action='view'>"
991 " <placeholder name='view_balance_placeholder'>"
992 " <menuitem action='%s'/>"
999 merge_id
= gtk_ui_manager_add_ui_from_string (priv
->ui_manager
,
1001 if (error
!= NULL
) {
1002 DEBUG ("Failed to add balance UI for %s: %s",
1003 tp_account_get_display_name (account
),
1005 g_error_free (error
);
1008 g_object_set_data (G_OBJECT (action
),
1009 "merge-id", GUINT_TO_POINTER (merge_id
));
1018 main_window_setup_balance_create_widget (EmpathyMainWindow
*window
,
1021 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1023 GtkWidget
*hbox
, *image
, *label
, *button
;
1025 account
= g_object_get_data (G_OBJECT (action
), "account");
1026 g_return_val_if_fail (TP_IS_ACCOUNT (account
), NULL
);
1028 hbox
= gtk_hbox_new (FALSE
, 6);
1031 image
= gtk_image_new ();
1032 gtk_box_pack_start (GTK_BOX (hbox
), image
, FALSE
, TRUE
, 0);
1033 g_object_bind_property (action
, "icon-name", image
, "icon-name",
1034 G_BINDING_SYNC_CREATE
);
1036 /* account name label */
1037 label
= gtk_label_new ("");
1038 gtk_misc_set_alignment (GTK_MISC (label
), 0.0, 0.5);
1039 gtk_box_pack_start (GTK_BOX (hbox
), label
, TRUE
, TRUE
, 0);
1040 g_object_bind_property (account
, "display-name", label
, "label",
1041 G_BINDING_SYNC_CREATE
);
1044 label
= gtk_label_new ("");
1045 gtk_misc_set_alignment (GTK_MISC (label
), 0.0, 0.5);
1046 gtk_box_pack_start (GTK_BOX (hbox
), label
, FALSE
, TRUE
, 0);
1047 g_object_set_data (G_OBJECT (action
), "money-label", label
);
1050 button
= gtk_button_new_with_label (_("Top Up..."));
1051 gtk_box_pack_start (GTK_BOX (hbox
), button
, FALSE
, TRUE
, 0);
1052 g_signal_connect_swapped (button
, "clicked",
1053 G_CALLBACK (gtk_action_activate
), action
);
1055 gtk_box_pack_start (GTK_BOX (priv
->balance_vbox
), hbox
, FALSE
, TRUE
, 0);
1056 gtk_widget_show_all (hbox
);
1058 /* tie the lifetime of the widget to the lifetime of the action */
1059 g_object_weak_ref (G_OBJECT (action
),
1060 (GWeakNotify
) gtk_widget_destroy
, hbox
);
1066 main_window_setup_balance_conn_ready (GObject
*source
,
1067 GAsyncResult
*result
,
1070 EmpathyMainWindow
*window
= user_data
;
1071 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1072 TpConnection
*conn
= TP_CONNECTION (source
);
1073 TpAccount
*account
= g_object_get_data (source
, "account");
1075 GError
*error
= NULL
;
1078 if (!tp_proxy_prepare_finish (conn
, result
, &error
)) {
1079 DEBUG ("Failed to prepare connection: %s", error
->message
);
1081 g_error_free (error
);
1085 if (!tp_proxy_is_prepared (conn
, TP_CONNECTION_FEATURE_BALANCE
))
1088 DEBUG ("Setting up balance for acct: %s",
1089 tp_account_get_display_name (account
));
1091 /* create the action */
1092 action
= main_window_setup_balance_create_action (window
, account
);
1097 gtk_action_set_visible (priv
->view_balance_show_in_roster
, TRUE
);
1099 /* create the display widget */
1100 main_window_setup_balance_create_widget (window
, action
);
1102 /* check the current balance and monitor for any changes */
1103 uri
= tp_connection_get_balance_uri (conn
);
1105 g_object_set_data_full (G_OBJECT (action
), "manage-credit-uri",
1106 g_strdup (uri
), g_free
);
1107 gtk_action_set_sensitive (GTK_ACTION (action
), !tp_str_empty (uri
));
1109 main_window_balance_update_balance (GTK_ACTION (action
), conn
);
1111 g_signal_connect (conn
, "balance-changed",
1112 G_CALLBACK (main_window_balance_changed_cb
), action
);
1116 main_window_setup_balance (EmpathyMainWindow
*window
,
1119 TpConnection
*conn
= tp_account_get_connection (account
);
1120 GQuark features
[] = { TP_CONNECTION_FEATURE_BALANCE
, 0 };
1125 /* need to prepare the connection:
1126 * store the account on the connection */
1127 g_object_set_data (G_OBJECT (conn
), "account", account
);
1128 tp_proxy_prepare_async (conn
, features
,
1129 main_window_setup_balance_conn_ready
, window
);
1133 main_window_remove_balance_action (EmpathyMainWindow
*window
,
1136 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1141 if (priv
->balance_action_group
== NULL
)
1144 name
= main_window_account_to_action_name (account
);
1146 action
= gtk_action_group_get_action (
1147 priv
->balance_action_group
, name
);
1149 if (action
!= NULL
) {
1152 DEBUG ("Removing action");
1154 merge_id
= GPOINTER_TO_UINT (g_object_get_data (
1158 gtk_ui_manager_remove_ui (priv
->ui_manager
,
1160 gtk_action_group_remove_action (
1161 priv
->balance_action_group
, action
);
1166 a
= gtk_action_group_list_actions (
1167 priv
->balance_action_group
);
1169 gtk_action_set_visible (
1170 priv
->view_balance_show_in_roster
,
1171 g_list_length (a
) > 0);
1177 main_window_connection_changed_cb (TpAccount
*account
,
1181 gchar
*dbus_error_name
,
1182 GHashTable
*details
,
1183 EmpathyMainWindow
*window
)
1185 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1187 main_window_update_status (window
);
1189 if (current
== TP_CONNECTION_STATUS_DISCONNECTED
&&
1190 reason
!= TP_CONNECTION_STATUS_REASON_REQUESTED
) {
1191 main_window_error_display (window
, account
);
1194 if (current
== TP_CONNECTION_STATUS_DISCONNECTED
) {
1195 empathy_sound_manager_play (priv
->sound_mgr
, GTK_WIDGET (window
),
1196 EMPATHY_SOUND_ACCOUNT_DISCONNECTED
);
1198 /* remove balance action if required */
1199 main_window_remove_balance_action (window
, account
);
1202 if (current
== TP_CONNECTION_STATUS_CONNECTED
) {
1203 empathy_sound_manager_play (priv
->sound_mgr
, GTK_WIDGET (window
),
1204 EMPATHY_SOUND_ACCOUNT_CONNECTED
);
1206 /* Account connected without error, remove error message if any */
1207 main_window_remove_error (window
, account
);
1208 main_window_setup_balance (window
, account
);
1213 main_window_accels_load (void)
1217 filename
= g_build_filename (g_get_user_config_dir (), PACKAGE_NAME
, ACCELS_FILENAME
, NULL
);
1218 if (g_file_test (filename
, G_FILE_TEST_EXISTS
)) {
1219 DEBUG ("Loading from:'%s'", filename
);
1220 gtk_accel_map_load (filename
);
1227 main_window_accels_save (void)
1230 gchar
*file_with_path
;
1232 dir
= g_build_filename (g_get_user_config_dir (), PACKAGE_NAME
, NULL
);
1233 g_mkdir_with_parents (dir
, S_IRUSR
| S_IWUSR
| S_IXUSR
);
1234 file_with_path
= g_build_filename (dir
, ACCELS_FILENAME
, NULL
);
1237 DEBUG ("Saving to:'%s'", file_with_path
);
1238 gtk_accel_map_save (file_with_path
);
1240 g_free (file_with_path
);
1244 empathy_main_window_finalize (GObject
*window
)
1246 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1247 GHashTableIter iter
;
1248 gpointer key
, value
;
1250 /* Save user-defined accelerators. */
1251 main_window_accels_save ();
1253 g_list_free (priv
->actions_connected
);
1255 g_object_unref (priv
->account_manager
);
1256 g_object_unref (priv
->individual_store
);
1257 g_object_unref (priv
->contact_manager
);
1258 g_object_unref (priv
->sound_mgr
);
1259 g_hash_table_destroy (priv
->errors
);
1260 g_hash_table_destroy (priv
->auths
);
1262 /* disconnect all handlers of status-changed signal */
1263 g_hash_table_iter_init (&iter
, priv
->status_changed_handlers
);
1264 while (g_hash_table_iter_next (&iter
, &key
, &value
))
1265 g_signal_handler_disconnect (TP_ACCOUNT (key
),
1266 GPOINTER_TO_UINT (value
));
1268 g_hash_table_destroy (priv
->status_changed_handlers
);
1270 g_signal_handlers_disconnect_by_func (priv
->event_manager
,
1271 main_window_event_added_cb
,
1273 g_signal_handlers_disconnect_by_func (priv
->event_manager
,
1274 main_window_event_removed_cb
,
1276 g_object_unref (priv
->call_observer
);
1277 g_object_unref (priv
->event_manager
);
1278 g_object_unref (priv
->ui_manager
);
1279 g_object_unref (priv
->chatroom_manager
);
1281 g_object_unref (priv
->gsettings_ui
);
1282 g_object_unref (priv
->gsettings_contacts
);
1284 G_OBJECT_CLASS (empathy_main_window_parent_class
)->finalize (window
);
1288 main_window_key_press_event_cb (GtkWidget
*window
,
1292 if (event
->keyval
== GDK_KEY_T
1293 && event
->state
& GDK_SHIFT_MASK
1294 && event
->state
& GDK_CONTROL_MASK
) {
1295 empathy_chat_manager_call_undo_closed_chat ();
1301 main_window_chat_quit_cb (GtkAction
*action
,
1302 EmpathyMainWindow
*window
)
1308 main_window_view_history_cb (GtkAction
*action
,
1309 EmpathyMainWindow
*window
)
1311 empathy_log_window_show (NULL
, NULL
, FALSE
, GTK_WINDOW (window
));
1315 main_window_chat_new_message_cb (GtkAction
*action
,
1316 EmpathyMainWindow
*window
)
1318 empathy_new_message_dialog_show (GTK_WINDOW (window
));
1322 main_window_chat_new_call_cb (GtkAction
*action
,
1323 EmpathyMainWindow
*window
)
1325 empathy_new_call_dialog_show (GTK_WINDOW (window
));
1329 main_window_chat_add_contact_cb (GtkAction
*action
,
1330 EmpathyMainWindow
*window
)
1332 empathy_new_individual_dialog_show (GTK_WINDOW (window
));
1336 main_window_chat_search_contacts_cb (GtkAction
*action
,
1337 EmpathyMainWindow
*window
)
1339 GtkWidget
*dialog
= empathy_contact_search_dialog_new (
1340 GTK_WINDOW (window
));
1341 gtk_widget_show (dialog
);
1345 main_window_view_show_ft_manager (GtkAction
*action
,
1346 EmpathyMainWindow
*window
)
1348 empathy_ft_manager_show ();
1352 main_window_view_show_offline_cb (GtkToggleAction
*action
,
1353 EmpathyMainWindow
*window
)
1355 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1358 current
= gtk_toggle_action_get_active (action
);
1359 g_settings_set_boolean (priv
->gsettings_ui
,
1360 EMPATHY_PREFS_UI_SHOW_OFFLINE
,
1363 empathy_individual_view_set_show_offline (priv
->individual_view
,
1368 main_window_notify_sort_contact_cb (GSettings
*gsettings
,
1370 EmpathyMainWindow
*window
)
1372 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1375 str
= g_settings_get_string (gsettings
, key
);
1379 GEnumClass
*enum_class
;
1380 GEnumValue
*enum_value
;
1382 type
= empathy_individual_store_sort_get_type ();
1383 enum_class
= G_ENUM_CLASS (g_type_class_peek (type
));
1384 enum_value
= g_enum_get_value_by_nick (enum_class
, str
);
1386 /* By changing the value of the GtkRadioAction,
1387 it emits a signal that calls main_window_view_sort_contacts_cb
1388 which updates the contacts list */
1389 gtk_radio_action_set_current_value (priv
->sort_by_name
,
1392 g_warning ("Wrong value for sort_criterium configuration : %s", str
);
1399 main_window_view_sort_contacts_cb (GtkRadioAction
*action
,
1400 GtkRadioAction
*current
,
1401 EmpathyMainWindow
*window
)
1403 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1404 EmpathyContactListStoreSort value
;
1407 GEnumClass
*enum_class
;
1408 GEnumValue
*enum_value
;
1410 value
= gtk_radio_action_get_current_value (action
);
1411 group
= gtk_radio_action_get_group (action
);
1413 /* Get string from index */
1414 type
= empathy_individual_store_sort_get_type ();
1415 enum_class
= G_ENUM_CLASS (g_type_class_peek (type
));
1416 enum_value
= g_enum_get_value (enum_class
, g_slist_index (group
, current
));
1419 g_warning ("No GEnumValue for EmpathyContactListSort with GtkRadioAction index:%d",
1420 g_slist_index (group
, action
));
1422 g_settings_set_string (priv
->gsettings_contacts
,
1423 EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM
,
1424 enum_value
->value_nick
);
1426 empathy_individual_store_set_sort_criterium (priv
->individual_store
,
1431 main_window_view_show_protocols_cb (GtkToggleAction
*action
,
1432 EmpathyMainWindow
*window
)
1434 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1437 value
= gtk_toggle_action_get_active (action
);
1439 g_settings_set_boolean (priv
->gsettings_ui
,
1440 EMPATHY_PREFS_UI_SHOW_PROTOCOLS
,
1442 empathy_individual_store_set_show_protocols (priv
->individual_store
,
1446 /* Matches GtkRadioAction values set in empathy-main-window.ui */
1447 #define CONTACT_LIST_NORMAL_SIZE_WITH_AVATARS 0
1448 #define CONTACT_LIST_NORMAL_SIZE 1
1449 #define CONTACT_LIST_COMPACT_SIZE 2
1452 main_window_view_contacts_list_size_cb (GtkRadioAction
*action
,
1453 GtkRadioAction
*current
,
1454 EmpathyMainWindow
*window
)
1456 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1457 GSettings
*gsettings_ui
;
1460 value
= gtk_radio_action_get_current_value (action
);
1461 /* create a new GSettings, so we can delay the setting until both
1463 gsettings_ui
= g_settings_new (EMPATHY_PREFS_UI_SCHEMA
);
1465 DEBUG ("radio button toggled, value = %i", value
);
1467 g_settings_delay (gsettings_ui
);
1468 g_settings_set_boolean (gsettings_ui
,
1469 EMPATHY_PREFS_UI_SHOW_AVATARS
,
1470 value
== CONTACT_LIST_NORMAL_SIZE_WITH_AVATARS
);
1472 g_settings_set_boolean (gsettings_ui
,
1473 EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST
,
1474 value
== CONTACT_LIST_COMPACT_SIZE
);
1475 g_settings_apply (gsettings_ui
);
1477 /* FIXME: these enums probably have the wrong namespace */
1478 empathy_individual_store_set_show_avatars (priv
->individual_store
,
1479 value
== CONTACT_LIST_NORMAL_SIZE_WITH_AVATARS
);
1480 empathy_individual_store_set_is_compact (priv
->individual_store
,
1481 value
== CONTACT_LIST_COMPACT_SIZE
);
1483 g_object_unref (gsettings_ui
);
1486 static void main_window_notify_show_protocols_cb (GSettings
*gsettings
,
1488 EmpathyMainWindow
*window
)
1490 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1492 gtk_toggle_action_set_active (priv
->show_protocols
,
1493 g_settings_get_boolean (gsettings
,
1494 EMPATHY_PREFS_UI_SHOW_PROTOCOLS
));
1499 main_window_notify_contact_list_size_cb (GSettings
*gsettings
,
1501 EmpathyMainWindow
*window
)
1503 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1506 if (g_settings_get_boolean (gsettings
,
1507 EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST
)) {
1508 value
= CONTACT_LIST_COMPACT_SIZE
;
1509 } else if (g_settings_get_boolean (gsettings
,
1510 EMPATHY_PREFS_UI_SHOW_AVATARS
)) {
1511 value
= CONTACT_LIST_NORMAL_SIZE_WITH_AVATARS
;
1513 value
= CONTACT_LIST_NORMAL_SIZE
;
1516 DEBUG ("setting changed, value = %i", value
);
1518 /* By changing the value of the GtkRadioAction,
1519 it emits a signal that calls main_window_view_contacts_list_size_cb
1520 which updates the contacts list */
1521 gtk_radio_action_set_current_value (priv
->normal_with_avatars
, value
);
1525 main_window_edit_search_contacts_cb (GtkCheckMenuItem
*item
,
1526 EmpathyMainWindow
*window
)
1528 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1530 empathy_individual_view_start_search (priv
->individual_view
);
1534 main_window_view_show_map_cb (GtkCheckMenuItem
*item
,
1535 EmpathyMainWindow
*window
)
1537 #ifdef HAVE_LIBCHAMPLAIN
1538 empathy_map_view_show ();
1543 join_chatroom (EmpathyChatroom
*chatroom
,
1549 account
= empathy_chatroom_get_account (chatroom
);
1550 room
= empathy_chatroom_get_room (chatroom
);
1552 DEBUG ("Requesting channel for '%s'", room
);
1553 empathy_join_muc (account
, room
, timestamp
);
1559 EmpathyChatroom
*chatroom
;
1563 } join_fav_account_sig_ctx
;
1565 static join_fav_account_sig_ctx
*
1566 join_fav_account_sig_ctx_new (TpAccount
*account
,
1567 EmpathyChatroom
*chatroom
,
1570 join_fav_account_sig_ctx
*ctx
= g_slice_new0 (
1571 join_fav_account_sig_ctx
);
1573 ctx
->account
= g_object_ref (account
);
1574 ctx
->chatroom
= g_object_ref (chatroom
);
1575 ctx
->timestamp
= timestamp
;
1580 join_fav_account_sig_ctx_free (join_fav_account_sig_ctx
*ctx
)
1582 g_object_unref (ctx
->account
);
1583 g_object_unref (ctx
->chatroom
);
1584 g_slice_free (join_fav_account_sig_ctx
, ctx
);
1588 account_status_changed_cb (TpAccount
*account
,
1589 TpConnectionStatus old_status
,
1590 TpConnectionStatus new_status
,
1592 gchar
*dbus_error_name
,
1593 GHashTable
*details
,
1596 join_fav_account_sig_ctx
*ctx
= user_data
;
1598 switch (new_status
) {
1599 case TP_CONNECTION_STATUS_DISCONNECTED
:
1600 /* Don't wait any longer */
1604 case TP_CONNECTION_STATUS_CONNECTING
:
1608 case TP_CONNECTION_STATUS_CONNECTED
:
1609 /* We can join the room */
1613 g_assert_not_reached ();
1616 join_chatroom (ctx
->chatroom
, ctx
->timestamp
);
1619 g_source_remove (ctx
->timeout
);
1620 g_signal_handler_disconnect (account
, ctx
->sig_id
);
1623 #define JOIN_FAVORITE_TIMEOUT 5
1626 join_favorite_timeout_cb (gpointer data
)
1628 join_fav_account_sig_ctx
*ctx
= data
;
1630 /* stop waiting for joining the favorite room */
1631 g_signal_handler_disconnect (ctx
->account
, ctx
->sig_id
);
1636 main_window_favorite_chatroom_join (EmpathyChatroom
*chatroom
)
1640 account
= empathy_chatroom_get_account (chatroom
);
1641 if (tp_account_get_connection_status (account
, NULL
) !=
1642 TP_CONNECTION_STATUS_CONNECTED
) {
1643 join_fav_account_sig_ctx
*ctx
;
1645 ctx
= join_fav_account_sig_ctx_new (account
, chatroom
,
1646 empathy_get_current_action_time ());
1648 ctx
->sig_id
= g_signal_connect_data (account
, "status-changed",
1649 G_CALLBACK (account_status_changed_cb
), ctx
,
1650 (GClosureNotify
) join_fav_account_sig_ctx_free
, 0);
1652 ctx
->timeout
= g_timeout_add_seconds (JOIN_FAVORITE_TIMEOUT
,
1653 join_favorite_timeout_cb
, ctx
);
1657 join_chatroom (chatroom
, empathy_get_current_action_time ());
1661 main_window_favorite_chatroom_menu_activate_cb (GtkMenuItem
*menu_item
,
1662 EmpathyChatroom
*chatroom
)
1664 main_window_favorite_chatroom_join (chatroom
);
1668 main_window_favorite_chatroom_menu_add (EmpathyMainWindow
*window
,
1669 EmpathyChatroom
*chatroom
)
1671 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1672 GtkWidget
*menu_item
;
1673 const gchar
*name
, *account_name
;
1677 if (g_object_get_data (G_OBJECT (chatroom
), "menu_item")) {
1681 name
= empathy_chatroom_get_name (chatroom
);
1682 account_name
= tp_account_get_display_name (
1683 empathy_chatroom_get_account (chatroom
));
1684 label
= g_strdup_printf ("%s (%s)", name
, account_name
);
1685 menu_item
= gtk_menu_item_new_with_label (label
);
1687 g_object_set_data (G_OBJECT (menu_item
), "is_favorite",
1688 GUINT_TO_POINTER (TRUE
));
1690 g_object_set_data (G_OBJECT (chatroom
), "menu_item", menu_item
);
1691 g_signal_connect (menu_item
, "activate",
1692 G_CALLBACK (main_window_favorite_chatroom_menu_activate_cb
),
1695 gtk_menu_shell_insert (GTK_MENU_SHELL (priv
->room_menu
),
1698 gtk_widget_show (menu_item
);
1702 main_window_favorite_chatroom_menu_added_cb (EmpathyChatroomManager
*manager
,
1703 EmpathyChatroom
*chatroom
,
1704 EmpathyMainWindow
*window
)
1706 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1708 main_window_favorite_chatroom_menu_add (window
, chatroom
);
1709 gtk_widget_show (priv
->room_separator
);
1710 gtk_action_set_sensitive (priv
->room_join_favorites
, TRUE
);
1714 main_window_favorite_chatroom_menu_removed_cb (EmpathyChatroomManager
*manager
,
1715 EmpathyChatroom
*chatroom
,
1716 EmpathyMainWindow
*window
)
1718 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1719 GtkWidget
*menu_item
;
1722 menu_item
= g_object_get_data (G_OBJECT (chatroom
), "menu_item");
1723 g_object_set_data (G_OBJECT (chatroom
), "menu_item", NULL
);
1724 gtk_widget_destroy (menu_item
);
1726 chatrooms
= empathy_chatroom_manager_get_chatrooms (priv
->chatroom_manager
, NULL
);
1728 gtk_widget_show (priv
->room_separator
);
1730 gtk_widget_hide (priv
->room_separator
);
1733 gtk_action_set_sensitive (priv
->room_join_favorites
, chatrooms
!= NULL
);
1734 g_list_free (chatrooms
);
1738 main_window_favorite_chatroom_menu_setup (EmpathyMainWindow
*window
)
1740 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1741 GList
*chatrooms
, *l
;
1744 priv
->chatroom_manager
= empathy_chatroom_manager_dup_singleton (NULL
);
1745 chatrooms
= empathy_chatroom_manager_get_chatrooms (
1746 priv
->chatroom_manager
, NULL
);
1747 room
= gtk_ui_manager_get_widget (priv
->ui_manager
,
1749 priv
->room_menu
= gtk_menu_item_get_submenu (GTK_MENU_ITEM (room
));
1750 priv
->room_separator
= gtk_ui_manager_get_widget (priv
->ui_manager
,
1751 "/menubar/room/room_separator");
1753 for (l
= chatrooms
; l
; l
= l
->next
) {
1754 main_window_favorite_chatroom_menu_add (window
, l
->data
);
1758 gtk_widget_hide (priv
->room_separator
);
1761 gtk_action_set_sensitive (priv
->room_join_favorites
, chatrooms
!= NULL
);
1763 g_signal_connect (priv
->chatroom_manager
, "chatroom-added",
1764 G_CALLBACK (main_window_favorite_chatroom_menu_added_cb
),
1766 g_signal_connect (priv
->chatroom_manager
, "chatroom-removed",
1767 G_CALLBACK (main_window_favorite_chatroom_menu_removed_cb
),
1770 g_list_free (chatrooms
);
1774 main_window_room_join_new_cb (GtkAction
*action
,
1775 EmpathyMainWindow
*window
)
1777 empathy_new_chatroom_dialog_show (GTK_WINDOW (window
));
1781 main_window_room_join_favorites_cb (GtkAction
*action
,
1782 EmpathyMainWindow
*window
)
1784 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1785 GList
*chatrooms
, *l
;
1787 chatrooms
= empathy_chatroom_manager_get_chatrooms (priv
->chatroom_manager
, NULL
);
1788 for (l
= chatrooms
; l
; l
= l
->next
) {
1789 main_window_favorite_chatroom_join (l
->data
);
1791 g_list_free (chatrooms
);
1795 main_window_room_manage_favorites_cb (GtkAction
*action
,
1796 EmpathyMainWindow
*window
)
1798 empathy_chatrooms_window_show (GTK_WINDOW (window
));
1802 main_window_edit_cb (GtkAction
*action
,
1803 EmpathyMainWindow
*window
)
1805 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1808 /* FIXME: It should use the UIManager to merge the contact/group submenu */
1809 submenu
= empathy_individual_view_get_individual_menu (
1810 priv
->individual_view
);
1815 item
= GTK_MENU_ITEM (priv
->edit_context
);
1816 label
= gtk_bin_get_child (GTK_BIN (item
));
1817 gtk_label_set_text (GTK_LABEL (label
), _("Contact"));
1819 gtk_widget_show (priv
->edit_context
);
1820 gtk_widget_show (priv
->edit_context_separator
);
1822 gtk_menu_item_set_submenu (item
, submenu
);
1827 submenu
= empathy_individual_view_get_group_menu (
1828 priv
->individual_view
);
1833 item
= GTK_MENU_ITEM (priv
->edit_context
);
1834 label
= gtk_bin_get_child (GTK_BIN (item
));
1835 gtk_label_set_text (GTK_LABEL (label
), _("Group"));
1837 gtk_widget_show (priv
->edit_context
);
1838 gtk_widget_show (priv
->edit_context_separator
);
1840 gtk_menu_item_set_submenu (item
, submenu
);
1845 gtk_widget_hide (priv
->edit_context
);
1846 gtk_widget_hide (priv
->edit_context_separator
);
1852 main_window_edit_accounts_cb (GtkAction
*action
,
1853 EmpathyMainWindow
*window
)
1855 empathy_accounts_dialog_show_application (gdk_screen_get_default (),
1856 NULL
, FALSE
, FALSE
);
1860 main_window_edit_personal_information_cb (GtkAction
*action
,
1861 EmpathyMainWindow
*window
)
1863 empathy_contact_personal_dialog_show (GTK_WINDOW (window
));
1867 main_window_edit_blocked_contacts_cb (GtkAction
*action
,
1868 EmpathyMainWindow
*window
)
1872 dialog
= empathy_contact_blocking_dialog_new (GTK_WINDOW (window
));
1873 gtk_widget_show (dialog
);
1874 g_signal_connect (dialog
, "response",
1875 G_CALLBACK (gtk_widget_destroy
), NULL
);
1879 main_window_edit_preferences_cb (GtkAction
*action
,
1880 EmpathyMainWindow
*window
)
1882 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1884 if (priv
->preferences
== NULL
) {
1885 priv
->preferences
= empathy_preferences_new (GTK_WINDOW (window
));
1886 g_object_add_weak_pointer (G_OBJECT (priv
->preferences
),
1887 (gpointer
) &priv
->preferences
);
1889 gtk_widget_show (priv
->preferences
);
1891 gtk_window_present (GTK_WINDOW (priv
->preferences
));
1896 main_window_help_about_cb (GtkAction
*action
,
1897 EmpathyMainWindow
*window
)
1899 empathy_about_dialog_new (GTK_WINDOW (window
));
1903 main_window_help_debug_cb (GtkAction
*action
,
1904 EmpathyMainWindow
*window
)
1906 GdkDisplay
*display
;
1907 GError
*error
= NULL
;
1910 GdkAppLaunchContext
*context
= NULL
;
1912 /* Try to run from source directory if possible */
1913 path
= g_build_filename (g_getenv ("EMPATHY_SRCDIR"), "src",
1914 "empathy-debugger", NULL
);
1916 if (!g_file_test (path
, G_FILE_TEST_EXISTS
)) {
1918 path
= g_build_filename (BIN_DIR
, "empathy-debugger", NULL
);
1921 app_info
= g_app_info_create_from_commandline (path
, NULL
, 0, &error
);
1922 if (app_info
== NULL
) {
1923 DEBUG ("Failed to create app info: %s", error
->message
);
1924 g_error_free (error
);
1928 display
= gdk_display_get_default ();
1929 context
= gdk_display_get_app_launch_context (display
);
1931 if (!g_app_info_launch (app_info
, NULL
, (GAppLaunchContext
*) context
,
1933 g_warning ("Failed to open debug window: %s", error
->message
);
1934 g_error_free (error
);
1939 tp_clear_object (&app_info
);
1940 tp_clear_object (&context
);
1945 main_window_help_contents_cb (GtkAction
*action
,
1946 EmpathyMainWindow
*window
)
1948 empathy_url_show (GTK_WIDGET (window
), "ghelp:empathy");
1952 main_window_throbber_button_press_event_cb (GtkWidget
*throbber
,
1953 GdkEventButton
*event
,
1954 EmpathyMainWindow
*window
)
1956 if (event
->type
!= GDK_BUTTON_PRESS
||
1957 event
->button
!= 1) {
1961 empathy_accounts_dialog_show_application (
1962 gtk_widget_get_screen (GTK_WIDGET (throbber
)),
1963 NULL
, FALSE
, FALSE
);
1969 main_window_account_removed_cb (TpAccountManager
*manager
,
1971 EmpathyMainWindow
*window
)
1973 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
1976 a
= tp_account_manager_get_valid_accounts (manager
);
1978 gtk_action_set_sensitive (priv
->view_history
,
1979 g_list_length (a
) > 0);
1983 /* remove errors if any */
1984 main_window_remove_error (window
, account
);
1986 /* remove the balance action if required */
1987 main_window_remove_balance_action (window
, account
);
1991 main_window_account_validity_changed_cb (TpAccountManager
*manager
,
1994 EmpathyMainWindow
*window
)
1996 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
2000 handler_id
= GPOINTER_TO_UINT (g_hash_table_lookup (
2001 priv
->status_changed_handlers
, account
));
2003 /* connect signal only if it was not connected yet */
2004 if (handler_id
== 0) {
2005 handler_id
= g_signal_connect (account
,
2007 G_CALLBACK (main_window_connection_changed_cb
),
2009 g_hash_table_insert (priv
->status_changed_handlers
,
2010 account
, GUINT_TO_POINTER (handler_id
));
2014 main_window_account_removed_cb (manager
, account
, window
);
2018 main_window_notify_show_offline_cb (GSettings
*gsettings
,
2020 gpointer toggle_action
)
2022 gtk_toggle_action_set_active (toggle_action
,
2023 g_settings_get_boolean (gsettings
, key
));
2027 main_window_connection_items_setup (EmpathyMainWindow
*window
,
2030 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
2034 const gchar
*actions_connected
[] = {
2036 "room_join_favorites",
2040 "edit_personal_information",
2041 "edit_blocked_contacts"
2044 for (i
= 0, list
= NULL
; i
< G_N_ELEMENTS (actions_connected
); i
++) {
2045 action
= gtk_builder_get_object (gui
, actions_connected
[i
]);
2046 list
= g_list_prepend (list
, action
);
2049 priv
->actions_connected
= list
;
2053 account_manager_prepared_cb (GObject
*source_object
,
2054 GAsyncResult
*result
,
2057 GList
*accounts
, *j
;
2058 TpAccountManager
*manager
= TP_ACCOUNT_MANAGER (source_object
);
2059 EmpathyMainWindow
*window
= user_data
;
2060 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
2061 GError
*error
= NULL
;
2063 if (!tp_account_manager_prepare_finish (manager
, result
, &error
)) {
2064 DEBUG ("Failed to prepare account manager: %s", error
->message
);
2065 g_error_free (error
);
2069 accounts
= tp_account_manager_get_valid_accounts (priv
->account_manager
);
2070 for (j
= accounts
; j
!= NULL
; j
= j
->next
) {
2071 TpAccount
*account
= TP_ACCOUNT (j
->data
);
2074 handler_id
= g_signal_connect (account
, "status-changed",
2075 G_CALLBACK (main_window_connection_changed_cb
),
2077 g_hash_table_insert (priv
->status_changed_handlers
,
2078 account
, GUINT_TO_POINTER (handler_id
));
2080 main_window_setup_balance (window
, account
);
2083 g_signal_connect (manager
, "account-validity-changed",
2084 G_CALLBACK (main_window_account_validity_changed_cb
),
2087 main_window_update_status (window
);
2089 /* Disable the "Previous Conversations" menu entry if there is no account */
2090 gtk_action_set_sensitive (priv
->view_history
,
2091 g_list_length (accounts
) > 0);
2093 g_list_free (accounts
);
2097 main_window_members_changed_cb (EmpathyContactList
*list
,
2098 EmpathyContact
*contact
,
2099 EmpathyContact
*actor
,
2103 EmpathyMainWindow
*window
)
2105 EmpathyMainWindowPriv
*priv
= GET_PRIV (window
);
2110 if (!empathy_migrate_butterfly_logs (contact
)) {
2111 g_signal_handler_disconnect (list
,
2112 priv
->butterfly_log_migration_members_changed_id
);
2113 priv
->butterfly_log_migration_members_changed_id
= 0;
2118 empathy_main_window_constructor (GType type
,
2119 guint n_construct_params
,
2120 GObjectConstructParam
*construct_params
)
2122 static GObject
*window
= NULL
;
2125 return g_object_ref (window
);
2127 window
= G_OBJECT_CLASS (empathy_main_window_parent_class
)->constructor (
2128 type
, n_construct_params
, construct_params
);
2130 g_object_add_weak_pointer (window
, (gpointer
) &window
);
2136 empathy_main_window_class_init (EmpathyMainWindowClass
*klass
)
2138 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
2140 object_class
->finalize
= empathy_main_window_finalize
;
2141 object_class
->constructor
= empathy_main_window_constructor
;
2143 g_type_class_add_private (object_class
, sizeof (EmpathyMainWindowPriv
));
2147 empathy_main_window_init (EmpathyMainWindow
*window
)
2149 EmpathyMainWindowPriv
*priv
;
2150 EmpathyIndividualManager
*individual_manager
;
2153 GtkToggleAction
*show_offline_widget
;
2154 GtkAction
*show_map_widget
;
2156 gboolean show_offline
;
2159 GtkTreeModel
*model
;
2161 priv
= window
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (window
,
2162 EMPATHY_TYPE_MAIN_WINDOW
, EmpathyMainWindowPriv
);
2164 priv
->gsettings_ui
= g_settings_new (EMPATHY_PREFS_UI_SCHEMA
);
2165 priv
->gsettings_contacts
= g_settings_new (EMPATHY_PREFS_CONTACTS_SCHEMA
);
2167 priv
->sound_mgr
= empathy_sound_manager_dup_singleton ();
2169 gtk_window_set_title (GTK_WINDOW (window
), _("Contact List"));
2170 gtk_window_set_role (GTK_WINDOW (window
), "contact_list");
2171 gtk_window_set_default_size (GTK_WINDOW (window
), 225, 325);
2173 /* Set up interface */
2174 filename
= empathy_file_lookup ("empathy-main-window.ui", "src");
2175 gui
= empathy_builder_get_file (filename
,
2176 "main_vbox", &priv
->main_vbox
,
2177 "balance_vbox", &priv
->balance_vbox
,
2178 "errors_vbox", &priv
->errors_vbox
,
2179 "auth_vbox", &priv
->auth_vbox
,
2180 "ui_manager", &priv
->ui_manager
,
2181 "view_show_offline", &show_offline_widget
,
2182 "view_show_protocols", &priv
->show_protocols
,
2183 "view_sort_by_name", &priv
->sort_by_name
,
2184 "view_sort_by_status", &priv
->sort_by_status
,
2185 "view_normal_size_with_avatars", &priv
->normal_with_avatars
,
2186 "view_normal_size", &priv
->normal_size
,
2187 "view_compact_size", &priv
->compact_size
,
2188 "view_history", &priv
->view_history
,
2189 "view_show_map", &show_map_widget
,
2190 "room_join_favorites", &priv
->room_join_favorites
,
2191 "presence_toolbar", &priv
->presence_toolbar
,
2192 "notebook", &priv
->notebook
,
2193 "no_entry_label", &priv
->no_entry_label
,
2194 "roster_scrolledwindow", &sw
,
2195 "view_balance_show_in_roster", &priv
->view_balance_show_in_roster
,
2199 gtk_container_add (GTK_CONTAINER (window
), priv
->main_vbox
);
2200 gtk_widget_show (priv
->main_vbox
);
2202 g_signal_connect (window
, "key-press-event",
2203 G_CALLBACK (main_window_key_press_event_cb
), NULL
);
2205 empathy_builder_connect (gui
, window
,
2206 "chat_quit", "activate", main_window_chat_quit_cb
,
2207 "chat_new_message", "activate", main_window_chat_new_message_cb
,
2208 "chat_new_call", "activate", main_window_chat_new_call_cb
,
2209 "view_history", "activate", main_window_view_history_cb
,
2210 "room_join_new", "activate", main_window_room_join_new_cb
,
2211 "room_join_favorites", "activate", main_window_room_join_favorites_cb
,
2212 "room_manage_favorites", "activate", main_window_room_manage_favorites_cb
,
2213 "chat_add_contact", "activate", main_window_chat_add_contact_cb
,
2214 "chat_search_contacts", "activate", main_window_chat_search_contacts_cb
,
2215 "view_show_ft_manager", "activate", main_window_view_show_ft_manager
,
2216 "view_show_offline", "toggled", main_window_view_show_offline_cb
,
2217 "view_show_protocols", "toggled", main_window_view_show_protocols_cb
,
2218 "view_sort_by_name", "changed", main_window_view_sort_contacts_cb
,
2219 "view_normal_size_with_avatars", "changed", main_window_view_contacts_list_size_cb
,
2220 "view_show_map", "activate", main_window_view_show_map_cb
,
2221 "edit", "activate", main_window_edit_cb
,
2222 "edit_accounts", "activate", main_window_edit_accounts_cb
,
2223 "edit_personal_information", "activate", main_window_edit_personal_information_cb
,
2224 "edit_blocked_contacts", "activate", main_window_edit_blocked_contacts_cb
,
2225 "edit_preferences", "activate", main_window_edit_preferences_cb
,
2226 "edit_search_contacts", "activate", main_window_edit_search_contacts_cb
,
2227 "help_about", "activate", main_window_help_about_cb
,
2228 "help_debug", "activate", main_window_help_debug_cb
,
2229 "help_contents", "activate", main_window_help_contents_cb
,
2232 /* Set up connection related widgets. */
2233 main_window_connection_items_setup (window
, gui
);
2235 g_object_ref (priv
->ui_manager
);
2236 g_object_unref (gui
);
2238 #ifndef HAVE_LIBCHAMPLAIN
2239 gtk_action_set_visible (show_map_widget
, FALSE
);
2242 priv
->account_manager
= tp_account_manager_dup ();
2244 tp_account_manager_prepare_async (priv
->account_manager
, NULL
,
2245 account_manager_prepared_cb
, window
);
2247 priv
->errors
= g_hash_table_new_full (g_direct_hash
,
2252 priv
->auths
= g_hash_table_new (NULL
, NULL
);
2254 priv
->status_changed_handlers
= g_hash_table_new_full (g_direct_hash
,
2260 main_window_favorite_chatroom_menu_setup (window
);
2262 priv
->edit_context
= gtk_ui_manager_get_widget (priv
->ui_manager
,
2263 "/menubar/edit/edit_context");
2264 priv
->edit_context_separator
= gtk_ui_manager_get_widget (
2266 "/menubar/edit/edit_context_separator");
2267 gtk_widget_hide (priv
->edit_context
);
2268 gtk_widget_hide (priv
->edit_context_separator
);
2270 /* Set up contact list. */
2271 empathy_status_presets_get_all ();
2273 /* Set up presence chooser */
2274 priv
->presence_chooser
= empathy_presence_chooser_new ();
2275 gtk_widget_show (priv
->presence_chooser
);
2276 item
= gtk_tool_item_new ();
2277 gtk_widget_show (GTK_WIDGET (item
));
2278 gtk_widget_set_size_request (priv
->presence_chooser
, 10, -1);
2279 gtk_container_add (GTK_CONTAINER (item
), priv
->presence_chooser
);
2280 gtk_tool_item_set_is_important (item
, TRUE
);
2281 gtk_tool_item_set_expand (item
, TRUE
);
2282 gtk_toolbar_insert (GTK_TOOLBAR (priv
->presence_toolbar
), item
, -1);
2284 /* Set up the throbber */
2285 priv
->throbber
= gtk_spinner_new ();
2286 gtk_widget_set_size_request (priv
->throbber
, 16, -1);
2287 gtk_widget_set_tooltip_text (priv
->throbber
, _("Show and edit accounts"));
2288 gtk_widget_set_events (priv
->throbber
, GDK_BUTTON_PRESS_MASK
);
2289 g_signal_connect (priv
->throbber
, "button-press-event",
2290 G_CALLBACK (main_window_throbber_button_press_event_cb
),
2292 gtk_widget_show (priv
->throbber
);
2294 item
= gtk_tool_item_new ();
2295 gtk_container_set_border_width (GTK_CONTAINER (item
), 6);
2296 gtk_toolbar_insert (GTK_TOOLBAR (priv
->presence_toolbar
), item
, -1);
2297 gtk_container_add (GTK_CONTAINER (item
), priv
->throbber
);
2298 priv
->throbber_tool_item
= GTK_WIDGET (item
);
2300 /* XXX: this class is designed to live for the duration of the program,
2301 * so it's got a race condition between its signal handlers and its
2302 * finalization. The class is planned to be removed, so we won't fix
2303 * this before then. */
2304 priv
->contact_manager
= EMPATHY_CONTACT_LIST (
2305 empathy_contact_manager_dup_singleton ());
2306 individual_manager
= empathy_individual_manager_dup_singleton ();
2307 priv
->individual_store
= empathy_individual_store_new (
2308 individual_manager
);
2309 g_object_unref (individual_manager
);
2311 /* For the moment, we disallow Persona drops onto the main contact list (e.g. from things such as
2312 * the EmpathyPersonaView in the linking dialogue). No code is hooked up to do anything on a Persona
2313 * drop, so allowing them would achieve nothing except confusion. */
2314 priv
->individual_view
= empathy_individual_view_new (
2315 priv
->individual_store
,
2316 EMPATHY_INDIVIDUAL_VIEW_FEATURE_ALL
^ EMPATHY_INDIVIDUAL_VIEW_FEATURE_PERSONA_DROP
,
2317 EMPATHY_INDIVIDUAL_FEATURE_ALL
);
2319 priv
->butterfly_log_migration_members_changed_id
= g_signal_connect (
2320 priv
->contact_manager
, "members-changed",
2321 G_CALLBACK (main_window_members_changed_cb
), window
);
2323 gtk_widget_show (GTK_WIDGET (priv
->individual_view
));
2324 gtk_container_add (GTK_CONTAINER (sw
),
2325 GTK_WIDGET (priv
->individual_view
));
2326 g_signal_connect (priv
->individual_view
, "row-activated",
2327 G_CALLBACK (main_window_row_activated_cb
),
2330 /* Set up search bar */
2331 priv
->search_bar
= empathy_live_search_new (
2332 GTK_WIDGET (priv
->individual_view
));
2333 empathy_individual_view_set_live_search (priv
->individual_view
,
2334 EMPATHY_LIVE_SEARCH (priv
->search_bar
));
2335 gtk_box_pack_start (GTK_BOX (priv
->main_vbox
), priv
->search_bar
,
2337 g_signal_connect_swapped (window
, "map",
2338 G_CALLBACK (gtk_widget_grab_focus
), priv
->individual_view
);
2340 /* Connect to proper signals to check if contact list is empty or not */
2341 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (priv
->individual_view
));
2343 g_signal_connect (model
, "row-inserted",
2344 G_CALLBACK (main_window_row_inserted_cb
),
2346 g_signal_connect (model
, "row-deleted",
2347 G_CALLBACK (main_window_row_deleted_cb
),
2350 /* Load user-defined accelerators. */
2351 main_window_accels_load ();
2353 /* Set window size. */
2354 empathy_geometry_bind (GTK_WINDOW (window
), GEOMETRY_NAME
);
2356 /* bind view_balance_show_in_roster */
2357 g_settings_bind (priv
->gsettings_ui
, "show-balance-in-roster",
2358 priv
->view_balance_show_in_roster
, "active",
2359 G_SETTINGS_BIND_DEFAULT
);
2360 g_object_bind_property (priv
->view_balance_show_in_roster
, "active",
2361 priv
->balance_vbox
, "visible",
2362 G_BINDING_SYNC_CREATE
);
2364 /* Enable event handling */
2365 priv
->call_observer
= empathy_call_observer_dup_singleton ();
2366 priv
->event_manager
= empathy_event_manager_dup_singleton ();
2368 g_signal_connect (priv
->event_manager
, "event-added",
2369 G_CALLBACK (main_window_event_added_cb
), window
);
2370 g_signal_connect (priv
->event_manager
, "event-removed",
2371 G_CALLBACK (main_window_event_removed_cb
), window
);
2372 g_signal_connect (priv
->account_manager
, "account-validity-changed",
2373 G_CALLBACK (main_window_account_validity_changed_cb
),
2375 g_signal_connect (priv
->account_manager
, "account-removed",
2376 G_CALLBACK (main_window_account_removed_cb
),
2378 g_signal_connect (priv
->account_manager
, "account-disabled",
2379 G_CALLBACK (main_window_account_disabled_cb
),
2382 l
= empathy_event_manager_get_events (priv
->event_manager
);
2384 main_window_event_added_cb (priv
->event_manager
, l
->data
,
2389 /* Show offline ? */
2390 show_offline
= g_settings_get_boolean (priv
->gsettings_ui
,
2391 EMPATHY_PREFS_UI_SHOW_OFFLINE
);
2392 g_signal_connect (priv
->gsettings_ui
,
2393 "changed::" EMPATHY_PREFS_UI_SHOW_OFFLINE
,
2394 G_CALLBACK (main_window_notify_show_offline_cb
),
2395 show_offline_widget
);
2397 gtk_toggle_action_set_active (show_offline_widget
, show_offline
);
2399 /* Show protocol ? */
2400 g_signal_connect (priv
->gsettings_ui
,
2401 "changed::" EMPATHY_PREFS_UI_SHOW_PROTOCOLS
,
2402 G_CALLBACK (main_window_notify_show_protocols_cb
),
2405 main_window_notify_show_protocols_cb (priv
->gsettings_ui
,
2406 EMPATHY_PREFS_UI_SHOW_PROTOCOLS
,
2409 /* Sort by name / by status ? */
2410 g_signal_connect (priv
->gsettings_contacts
,
2411 "changed::" EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM
,
2412 G_CALLBACK (main_window_notify_sort_contact_cb
),
2415 main_window_notify_sort_contact_cb (priv
->gsettings_contacts
,
2416 EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM
,
2419 /* Contacts list size */
2420 g_signal_connect (priv
->gsettings_ui
,
2421 "changed::" EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST
,
2422 G_CALLBACK (main_window_notify_contact_list_size_cb
),
2424 g_signal_connect (priv
->gsettings_ui
,
2425 "changed::" EMPATHY_PREFS_UI_SHOW_AVATARS
,
2426 G_CALLBACK (main_window_notify_contact_list_size_cb
),
2429 main_window_notify_contact_list_size_cb (priv
->gsettings_ui
,
2430 EMPATHY_PREFS_UI_SHOW_AVATARS
,
2435 empathy_main_window_dup (void)
2437 return g_object_new (EMPATHY_TYPE_MAIN_WINDOW
, NULL
);