~ubuntu-branches/ubuntu/natty/empathy/natty

« back to all changes in this revision

Viewing changes to .pc/00_git_tooltip_on_error_info.patch/src/empathy-main-window.c

  • Committer: Bazaar Package Importer
  • Author(s): Brian Curtis
  • Date: 2011-01-25 13:20:01 UTC
  • Revision ID: james.westby@ubuntu.com-20110125132001-vyasbmnk6n4d3gvq
Tags: 2.32.2-0ubuntu7
* debian/patches/00_git_conn_disc_notif.patch (LP: #582757)
* debian/patches/00_git_F2_opens_contact_info.patch (LP: #387991)
* debian/patches/00_git_tooltip_on_error_info.patch (LP: #681413)
* debian/rules
  - added --with-ca-file='/etc/ssl/certs/ca-certificates.crt'

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
/*
 
3
 * Copyright (C) 2002-2007 Imendio AB
 
4
 * Copyright (C) 2007-2010 Collabora Ltd.
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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
 
20
 *
 
21
 * Authors: Xavier Claessens <xclaesse@gmail.com>
 
22
 *          Danielle Madeley <danielle.madeley@collabora.co.uk>
 
23
 */
 
24
 
 
25
#include <config.h>
 
26
 
 
27
#include <sys/stat.h>
 
28
#include <gtk/gtk.h>
 
29
#include <gdk/gdkkeysyms.h>
 
30
#include <glib/gi18n.h>
 
31
 
 
32
#include <telepathy-glib/account-manager.h>
 
33
#include <telepathy-glib/util.h>
 
34
#include <folks/folks.h>
 
35
 
 
36
#include <libempathy/empathy-contact.h>
 
37
#include <libempathy/empathy-idle.h>
 
38
#include <libempathy/empathy-utils.h>
 
39
#include <libempathy/empathy-dispatcher.h>
 
40
#include <libempathy/empathy-chatroom-manager.h>
 
41
#include <libempathy/empathy-chatroom.h>
 
42
#include <libempathy/empathy-contact-list.h>
 
43
#include <libempathy/empathy-contact-manager.h>
 
44
#include <libempathy/empathy-gsettings.h>
 
45
#include <libempathy/empathy-individual-manager.h>
 
46
#include <libempathy/empathy-gsettings.h>
 
47
#include <libempathy/empathy-status-presets.h>
 
48
#include <libempathy/empathy-tp-contact-factory.h>
 
49
 
 
50
#include <libempathy-gtk/empathy-contact-dialogs.h>
 
51
#include <libempathy-gtk/empathy-contact-list-store.h>
 
52
#include <libempathy-gtk/empathy-contact-list-view.h>
 
53
#include <libempathy-gtk/empathy-live-search.h>
 
54
#include <libempathy-gtk/empathy-geometry.h>
 
55
#include <libempathy-gtk/empathy-gtk-enum-types.h>
 
56
#include <libempathy-gtk/empathy-individual-dialogs.h>
 
57
#include <libempathy-gtk/empathy-individual-store.h>
 
58
#include <libempathy-gtk/empathy-individual-view.h>
 
59
#include <libempathy-gtk/empathy-new-message-dialog.h>
 
60
#include <libempathy-gtk/empathy-new-call-dialog.h>
 
61
#include <libempathy-gtk/empathy-log-window.h>
 
62
#include <libempathy-gtk/empathy-presence-chooser.h>
 
63
#include <libempathy-gtk/empathy-sound.h>
 
64
#include <libempathy-gtk/empathy-ui-utils.h>
 
65
 
 
66
#include "empathy-accounts-dialog.h"
 
67
#include "empathy-chat-manager.h"
 
68
#include "empathy-main-window.h"
 
69
#include "empathy-preferences.h"
 
70
#include "empathy-about-dialog.h"
 
71
#include "empathy-debug-window.h"
 
72
#include "empathy-new-chatroom-dialog.h"
 
73
#include "empathy-map-view.h"
 
74
#include "empathy-chatrooms-window.h"
 
75
#include "empathy-event-manager.h"
 
76
#include "empathy-ft-manager.h"
 
77
#include "empathy-migrate-butterfly-logs.h"
 
78
 
 
79
#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
 
80
#include <libempathy/empathy-debug.h>
 
81
 
 
82
/* Flashing delay for icons (milliseconds). */
 
83
#define FLASH_TIMEOUT 500
 
84
 
 
85
/* Minimum width of roster window if something goes wrong. */
 
86
#define MIN_WIDTH 50
 
87
 
 
88
/* Accels (menu shortcuts) can be configured and saved */
 
89
#define ACCELS_FILENAME "accels.txt"
 
90
 
 
91
/* Name in the geometry file */
 
92
#define GEOMETRY_NAME "main-window"
 
93
 
 
94
enum {
 
95
        PAGE_CONTACT_LIST = 0,
 
96
        PAGE_NO_MATCH
 
97
};
 
98
 
 
99
G_DEFINE_TYPE (EmpathyMainWindow, empathy_main_window, GTK_TYPE_WINDOW);
 
100
 
 
101
#define GET_PRIV(self) ((EmpathyMainWindowPriv *)((EmpathyMainWindow *) self)->priv)
 
102
 
 
103
struct _EmpathyMainWindowPriv {
 
104
        EmpathyIndividualStore  *individual_store;
 
105
        EmpathyIndividualView   *individual_view;
 
106
        TpAccountManager        *account_manager;
 
107
        EmpathyChatroomManager  *chatroom_manager;
 
108
        EmpathyEventManager     *event_manager;
 
109
        guint                    flash_timeout_id;
 
110
        gboolean                 flash_on;
 
111
        gboolean                 empty;
 
112
 
 
113
        GSettings              *gsettings_ui;
 
114
        GSettings              *gsettings_contacts;
 
115
 
 
116
        GtkWidget              *preferences;
 
117
        GtkWidget              *main_vbox;
 
118
        GtkWidget              *throbber;
 
119
        GtkWidget              *throbber_tool_item;
 
120
        GtkWidget              *presence_toolbar;
 
121
        GtkWidget              *presence_chooser;
 
122
        GtkWidget              *errors_vbox;
 
123
        GtkWidget              *search_bar;
 
124
        GtkWidget              *notebook;
 
125
        GtkWidget              *no_entry_label;
 
126
 
 
127
        GtkToggleAction        *show_protocols;
 
128
        GtkRadioAction         *sort_by_name;
 
129
        GtkRadioAction         *sort_by_status;
 
130
        GtkRadioAction         *normal_with_avatars;
 
131
        GtkRadioAction         *normal_size;
 
132
        GtkRadioAction         *compact_size;
 
133
 
 
134
        GtkUIManager           *ui_manager;
 
135
        GtkAction              *view_history;
 
136
        GtkAction              *room_join_favorites;
 
137
        GtkWidget              *room_menu;
 
138
        GtkWidget              *room_separator;
 
139
        GtkWidget              *edit_context;
 
140
        GtkWidget              *edit_context_separator;
 
141
 
 
142
        guint                   size_timeout_id;
 
143
        GHashTable             *errors;
 
144
 
 
145
        /* stores a mapping from TpAccount to Handler ID to prevent
 
146
         * to listen more than once to the status-changed signal */
 
147
        GHashTable             *status_changed_handlers;
 
148
 
 
149
        /* Actions that are enabled when there are connected accounts */
 
150
        GList                  *actions_connected;
 
151
 
 
152
        /* The idle event source to migrate butterfly's logs */
 
153
        guint butterfly_log_migration_members_changed_id;
 
154
};
 
155
 
 
156
static void
 
157
main_window_flash_stop (EmpathyMainWindow *window)
 
158
{
 
159
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
160
 
 
161
        if (priv->flash_timeout_id == 0) {
 
162
                return;
 
163
        }
 
164
 
 
165
        DEBUG ("Stop flashing");
 
166
        g_source_remove (priv->flash_timeout_id);
 
167
        priv->flash_timeout_id = 0;
 
168
        priv->flash_on = FALSE;
 
169
}
 
170
 
 
171
typedef struct {
 
172
        EmpathyEvent       *event;
 
173
        gboolean            on;
 
174
        EmpathyMainWindow  *window;
 
175
} FlashForeachData;
 
176
 
 
177
static gboolean
 
178
main_window_flash_foreach (GtkTreeModel *model,
 
179
                           GtkTreePath  *path,
 
180
                           GtkTreeIter  *iter,
 
181
                           gpointer      user_data)
 
182
{
 
183
        FlashForeachData *data = (FlashForeachData *) user_data;
 
184
        FolksIndividual *individual;
 
185
        EmpathyContact   *contact;
 
186
        const gchar      *icon_name;
 
187
        GtkTreePath      *parent_path = NULL;
 
188
        GtkTreeIter       parent_iter;
 
189
        GdkPixbuf        *pixbuf = NULL;
 
190
 
 
191
        gtk_tree_model_get (model, iter,
 
192
                            EMPATHY_INDIVIDUAL_STORE_COL_INDIVIDUAL,
 
193
                                &individual,
 
194
                            -1);
 
195
 
 
196
        if (individual == NULL)
 
197
                return FALSE;
 
198
 
 
199
        contact = empathy_contact_dup_from_folks_individual (individual);
 
200
        if (contact != data->event->contact) {
 
201
                tp_clear_object (&contact);
 
202
                return FALSE;
 
203
        }
 
204
 
 
205
        if (data->on) {
 
206
                icon_name = data->event->icon_name;
 
207
                pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
 
208
        } else {
 
209
                pixbuf = empathy_individual_store_get_individual_status_icon (
 
210
                                                GET_PRIV (data->window)->individual_store,
 
211
                                                individual);
 
212
        }
 
213
 
 
214
        gtk_tree_store_set (GTK_TREE_STORE (model), iter,
 
215
                            EMPATHY_INDIVIDUAL_STORE_COL_ICON_STATUS, pixbuf,
 
216
                            -1);
 
217
 
 
218
        /* To make sure the parent is shown correctly, we emit
 
219
         * the row-changed signal on the parent so it prompts
 
220
         * it to be refreshed by the filter func.
 
221
         */
 
222
        if (gtk_tree_model_iter_parent (model, &parent_iter, iter)) {
 
223
                parent_path = gtk_tree_model_get_path (model, &parent_iter);
 
224
        }
 
225
        if (parent_path) {
 
226
                gtk_tree_model_row_changed (model, parent_path, &parent_iter);
 
227
                gtk_tree_path_free (parent_path);
 
228
        }
 
229
 
 
230
        g_object_unref (individual);
 
231
        tp_clear_object (&contact);
 
232
 
 
233
        return FALSE;
 
234
}
 
235
 
 
236
static gboolean
 
237
main_window_flash_cb (EmpathyMainWindow *window)
 
238
{
 
239
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
240
        GtkTreeModel     *model;
 
241
        GSList           *events, *l;
 
242
        gboolean          found_event = FALSE;
 
243
        FlashForeachData  data;
 
244
 
 
245
        priv->flash_on = !priv->flash_on;
 
246
        data.on = priv->flash_on;
 
247
        model = GTK_TREE_MODEL (priv->individual_store);
 
248
 
 
249
        events = empathy_event_manager_get_events (priv->event_manager);
 
250
        for (l = events; l; l = l->next) {
 
251
                data.event = l->data;
 
252
                data.window = window;
 
253
                if (!data.event->contact || !data.event->must_ack) {
 
254
                        continue;
 
255
                }
 
256
 
 
257
                found_event = TRUE;
 
258
                gtk_tree_model_foreach (model,
 
259
                                        main_window_flash_foreach,
 
260
                                        &data);
 
261
        }
 
262
 
 
263
        if (!found_event) {
 
264
                main_window_flash_stop (window);
 
265
        }
 
266
 
 
267
        return TRUE;
 
268
}
 
269
 
 
270
static void
 
271
main_window_flash_start (EmpathyMainWindow *window)
 
272
{
 
273
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
274
 
 
275
        if (priv->flash_timeout_id != 0) {
 
276
                return;
 
277
        }
 
278
 
 
279
        DEBUG ("Start flashing");
 
280
        priv->flash_timeout_id = g_timeout_add (FLASH_TIMEOUT,
 
281
                                                (GSourceFunc) main_window_flash_cb,
 
282
                                                window);
 
283
        main_window_flash_cb (window);
 
284
}
 
285
 
 
286
static void
 
287
main_window_event_added_cb (EmpathyEventManager *manager,
 
288
                            EmpathyEvent        *event,
 
289
                            EmpathyMainWindow   *window)
 
290
{
 
291
        if (event->contact) {
 
292
                main_window_flash_start (window);
 
293
        }
 
294
}
 
295
 
 
296
static void
 
297
main_window_event_removed_cb (EmpathyEventManager *manager,
 
298
                              EmpathyEvent        *event,
 
299
                              EmpathyMainWindow   *window)
 
300
{
 
301
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
302
        FlashForeachData data;
 
303
 
 
304
        if (!event->contact) {
 
305
                return;
 
306
        }
 
307
 
 
308
        data.on = FALSE;
 
309
        data.event = event;
 
310
        data.window = window;
 
311
        gtk_tree_model_foreach (GTK_TREE_MODEL (priv->individual_store),
 
312
                                main_window_flash_foreach,
 
313
                                &data);
 
314
}
 
315
 
 
316
static void
 
317
main_window_row_activated_cb (EmpathyContactListView *view,
 
318
                              GtkTreePath            *path,
 
319
                              GtkTreeViewColumn      *col,
 
320
                              EmpathyMainWindow      *window)
 
321
{
 
322
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
323
        EmpathyContact *contact = NULL;
 
324
        FolksIndividual *individual;
 
325
        GtkTreeModel   *model;
 
326
        GtkTreeIter     iter;
 
327
        GSList         *events, *l;
 
328
 
 
329
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->individual_view));
 
330
        gtk_tree_model_get_iter (model, &iter, path);
 
331
 
 
332
        gtk_tree_model_get (model, &iter,
 
333
                            EMPATHY_INDIVIDUAL_STORE_COL_INDIVIDUAL,
 
334
                                &individual,
 
335
                            -1);
 
336
 
 
337
        if (individual != NULL) {
 
338
                contact = empathy_contact_dup_from_folks_individual (individual);
 
339
        }
 
340
 
 
341
        if (!contact) {
 
342
                goto OUT;
 
343
        }
 
344
 
 
345
        /* If the contact has an event activate it, otherwise the
 
346
         * default handler of row-activated will be called. */
 
347
        events = empathy_event_manager_get_events (priv->event_manager);
 
348
        for (l = events; l; l = l->next) {
 
349
                EmpathyEvent *event = l->data;
 
350
 
 
351
                if (event->contact == contact) {
 
352
                        DEBUG ("Activate event");
 
353
                        empathy_event_activate (event);
 
354
 
 
355
                        /* We don't want the default handler of this signal
 
356
                         * (e.g. open a chat) */
 
357
                        g_signal_stop_emission_by_name (view, "row-activated");
 
358
                        break;
 
359
                }
 
360
        }
 
361
 
 
362
        g_object_unref (contact);
 
363
OUT:
 
364
        tp_clear_object (&individual);
 
365
}
 
366
 
 
367
static void
 
368
main_window_row_deleted_cb (GtkTreeModel      *model,
 
369
                            GtkTreePath       *path,
 
370
                            EmpathyMainWindow *window)
 
371
{
 
372
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
373
        GtkTreeIter help_iter;
 
374
 
 
375
        if (!gtk_tree_model_get_iter_first (model, &help_iter)) {
 
376
                priv->empty = TRUE;
 
377
 
 
378
                if (empathy_individual_view_is_searching (
 
379
                                priv->individual_view)) {
 
380
                        gchar *tmp;
 
381
 
 
382
                        tmp = g_strdup_printf ("<b><span size='xx-large'>%s</span></b>",
 
383
                                _("No match found"));
 
384
 
 
385
                        gtk_label_set_markup (GTK_LABEL (priv->no_entry_label), tmp);
 
386
                        g_free (tmp);
 
387
 
 
388
                        gtk_label_set_ellipsize (GTK_LABEL (priv->no_entry_label),
 
389
                                PANGO_ELLIPSIZE_END);
 
390
 
 
391
                        gtk_notebook_set_current_page (
 
392
                                        GTK_NOTEBOOK (priv->notebook), PAGE_NO_MATCH);
 
393
                }
 
394
        }
 
395
}
 
396
 
 
397
static void
 
398
main_window_row_inserted_cb (GtkTreeModel      *model,
 
399
                             GtkTreePath       *path,
 
400
                             GtkTreeIter       *iter,
 
401
                             EmpathyMainWindow *window)
 
402
{
 
403
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
404
 
 
405
        if (priv->empty) {
 
406
                priv->empty = FALSE;
 
407
                gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
 
408
                                PAGE_CONTACT_LIST);
 
409
                gtk_widget_grab_focus (GTK_WIDGET (priv->individual_view));
 
410
        }
 
411
}
 
412
 
 
413
static void
 
414
main_window_remove_error (EmpathyMainWindow *window,
 
415
                          TpAccount         *account)
 
416
{
 
417
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
418
        GtkWidget *error_widget;
 
419
 
 
420
        error_widget = g_hash_table_lookup (priv->errors, account);
 
421
        if (error_widget != NULL) {
 
422
                gtk_widget_destroy (error_widget);
 
423
                g_hash_table_remove (priv->errors, account);
 
424
        }
 
425
}
 
426
 
 
427
static void
 
428
main_window_account_disabled_cb (TpAccountManager  *manager,
 
429
                                 TpAccount         *account,
 
430
                                 EmpathyMainWindow *window)
 
431
{
 
432
        main_window_remove_error (window, account);
 
433
}
 
434
 
 
435
static void
 
436
main_window_error_retry_clicked_cb (GtkButton         *button,
 
437
                                    EmpathyMainWindow *window)
 
438
{
 
439
        TpAccount *account;
 
440
 
 
441
        account = g_object_get_data (G_OBJECT (button), "account");
 
442
        tp_account_reconnect_async (account, NULL, NULL);
 
443
 
 
444
        main_window_remove_error (window, account);
 
445
}
 
446
 
 
447
static void
 
448
main_window_error_edit_clicked_cb (GtkButton         *button,
 
449
                                   EmpathyMainWindow *window)
 
450
{
 
451
        TpAccount *account;
 
452
 
 
453
        account = g_object_get_data (G_OBJECT (button), "account");
 
454
 
 
455
        empathy_accounts_dialog_show_application (
 
456
                        gtk_widget_get_screen (GTK_WIDGET (button)),
 
457
                        account, FALSE, FALSE);
 
458
 
 
459
        main_window_remove_error (window, account);
 
460
}
 
461
 
 
462
static void
 
463
main_window_error_close_clicked_cb (GtkButton         *button,
 
464
                                    EmpathyMainWindow *window)
 
465
{
 
466
        TpAccount *account;
 
467
 
 
468
        account = g_object_get_data (G_OBJECT (button), "account");
 
469
        main_window_remove_error (window, account);
 
470
}
 
471
 
 
472
static void
 
473
main_window_error_display (EmpathyMainWindow *window,
 
474
                           TpAccount         *account)
 
475
{
 
476
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
477
        GtkWidget *info_bar;
 
478
        GtkWidget *content_area;
 
479
        GtkWidget *label;
 
480
        GtkWidget *image;
 
481
        GtkWidget *retry_button;
 
482
        GtkWidget *edit_button;
 
483
        GtkWidget *close_button;
 
484
        GtkWidget *action_area;
 
485
        GtkWidget *action_table;
 
486
        gchar     *str;
 
487
        const gchar     *icon_name;
 
488
        const gchar *error_message;
 
489
        gboolean user_requested;
 
490
 
 
491
        error_message =
 
492
                empathy_account_get_error_message (account, &user_requested);
 
493
 
 
494
        if (user_requested) {
 
495
                return;
 
496
        }
 
497
 
 
498
        str = g_markup_printf_escaped ("<b>%s</b>\n%s",
 
499
                                               tp_account_get_display_name (account),
 
500
                                               error_message);
 
501
 
 
502
        info_bar = g_hash_table_lookup (priv->errors, account);
 
503
        if (info_bar) {
 
504
                label = g_object_get_data (G_OBJECT (info_bar), "label");
 
505
 
 
506
                /* Just set the latest error and return */
 
507
                gtk_label_set_markup (GTK_LABEL (label), str);
 
508
                g_free (str);
 
509
 
 
510
                return;
 
511
        }
 
512
 
 
513
        info_bar = gtk_info_bar_new ();
 
514
        gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_ERROR);
 
515
 
 
516
        gtk_widget_set_no_show_all (info_bar, TRUE);
 
517
        gtk_box_pack_start (GTK_BOX (priv->errors_vbox), info_bar, FALSE, TRUE, 0);
 
518
        gtk_widget_show (info_bar);
 
519
 
 
520
        icon_name = tp_account_get_icon_name (account);
 
521
        image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_SMALL_TOOLBAR);
 
522
        gtk_widget_show (image);
 
523
 
 
524
        label = gtk_label_new (str);
 
525
        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
 
526
        gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
 
527
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
 
528
        gtk_widget_show (label);
 
529
        g_free (str);
 
530
 
 
531
        content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar));
 
532
        gtk_box_pack_start (GTK_BOX (content_area), image, FALSE, FALSE, 0);
 
533
        gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
 
534
 
 
535
        image = gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_BUTTON);
 
536
        retry_button = gtk_button_new ();
 
537
        gtk_button_set_image (GTK_BUTTON (retry_button), image);
 
538
        gtk_widget_set_tooltip_text (retry_button, _("Reconnect"));
 
539
        gtk_widget_show (retry_button);
 
540
 
 
541
        image = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON);
 
542
        edit_button = gtk_button_new ();
 
543
        gtk_button_set_image (GTK_BUTTON (edit_button), image);
 
544
        gtk_widget_set_tooltip_text (edit_button, _("Edit Account"));
 
545
        gtk_widget_show (edit_button);
 
546
 
 
547
        image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_BUTTON);
 
548
        close_button = gtk_button_new ();
 
549
        gtk_button_set_image (GTK_BUTTON (close_button), image);
 
550
        gtk_widget_set_tooltip_text (close_button, _("Close"));
 
551
        gtk_widget_show (close_button);
 
552
 
 
553
        action_table = gtk_table_new (1, 3, FALSE);
 
554
        gtk_table_set_col_spacings (GTK_TABLE (action_table), 2);
 
555
        gtk_widget_show (action_table);
 
556
 
 
557
        action_area = gtk_info_bar_get_action_area (GTK_INFO_BAR (info_bar));
 
558
        gtk_box_pack_start (GTK_BOX (action_area), action_table, FALSE, FALSE, 0);
 
559
 
 
560
        gtk_table_attach (GTK_TABLE (action_table), retry_button, 0, 1, 0, 1,
 
561
                                                                                (GtkAttachOptions) (GTK_SHRINK),
 
562
                                                                                (GtkAttachOptions) (GTK_SHRINK), 0, 0);
 
563
        gtk_table_attach (GTK_TABLE (action_table), edit_button, 1, 2, 0, 1,
 
564
                                                                                (GtkAttachOptions) (GTK_SHRINK),
 
565
                                                                                (GtkAttachOptions) (GTK_SHRINK), 0, 0);
 
566
        gtk_table_attach (GTK_TABLE (action_table), close_button, 2, 3, 0, 1,
 
567
                                                                                (GtkAttachOptions) (GTK_SHRINK),
 
568
                                                                                (GtkAttachOptions) (GTK_SHRINK), 0, 0);
 
569
 
 
570
        g_object_set_data (G_OBJECT (info_bar), "label", label);
 
571
        g_object_set_data_full (G_OBJECT (info_bar),
 
572
                                "account", g_object_ref (account),
 
573
                                g_object_unref);
 
574
        g_object_set_data_full (G_OBJECT (edit_button),
 
575
                                "account", g_object_ref (account),
 
576
                                g_object_unref);
 
577
        g_object_set_data_full (G_OBJECT (close_button),
 
578
                                "account", g_object_ref (account),
 
579
                                g_object_unref);
 
580
        g_object_set_data_full (G_OBJECT (retry_button),
 
581
                                "account", g_object_ref (account),
 
582
                                g_object_unref);
 
583
 
 
584
        g_signal_connect (edit_button, "clicked",
 
585
                          G_CALLBACK (main_window_error_edit_clicked_cb),
 
586
                          window);
 
587
        g_signal_connect (close_button, "clicked",
 
588
                          G_CALLBACK (main_window_error_close_clicked_cb),
 
589
                          window);
 
590
        g_signal_connect (retry_button, "clicked",
 
591
                          G_CALLBACK (main_window_error_retry_clicked_cb),
 
592
                          window);
 
593
 
 
594
        gtk_widget_show (priv->errors_vbox);
 
595
 
 
596
        g_hash_table_insert (priv->errors, g_object_ref (account), info_bar);
 
597
}
 
598
 
 
599
static void
 
600
main_window_update_status (EmpathyMainWindow *window)
 
601
{
 
602
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
603
        gboolean connected, connecting;
 
604
        GList *l;
 
605
 
 
606
        connected = empathy_account_manager_get_accounts_connected (&connecting);
 
607
 
 
608
        /* Update the spinner state */
 
609
        if (connecting) {
 
610
                gtk_spinner_start (GTK_SPINNER (priv->throbber));
 
611
                gtk_widget_show (priv->throbber_tool_item);
 
612
        } else {
 
613
                gtk_spinner_stop (GTK_SPINNER (priv->throbber));
 
614
                gtk_widget_hide (priv->throbber_tool_item);
 
615
        }
 
616
 
 
617
        /* Update widgets sensibility */
 
618
        for (l = priv->actions_connected; l; l = l->next) {
 
619
                gtk_action_set_sensitive (l->data, connected);
 
620
        }
 
621
}
 
622
 
 
623
static void
 
624
main_window_connection_changed_cb (TpAccount  *account,
 
625
                                   guint       old_status,
 
626
                                   guint       current,
 
627
                                   guint       reason,
 
628
                                   gchar      *dbus_error_name,
 
629
                                   GHashTable *details,
 
630
                                   EmpathyMainWindow *window)
 
631
{
 
632
        main_window_update_status (window);
 
633
 
 
634
        if (current == TP_CONNECTION_STATUS_DISCONNECTED &&
 
635
            reason != TP_CONNECTION_STATUS_REASON_REQUESTED) {
 
636
                main_window_error_display (window, account);
 
637
        }
 
638
 
 
639
        if (current == TP_CONNECTION_STATUS_DISCONNECTED) {
 
640
                empathy_sound_play (GTK_WIDGET (window),
 
641
                                    EMPATHY_SOUND_ACCOUNT_DISCONNECTED);
 
642
        }
 
643
 
 
644
        if (current == TP_CONNECTION_STATUS_CONNECTED) {
 
645
                empathy_sound_play (GTK_WIDGET (window),
 
646
                                    EMPATHY_SOUND_ACCOUNT_CONNECTED);
 
647
 
 
648
                /* Account connected without error, remove error message if any */
 
649
                main_window_remove_error (window, account);
 
650
        }
 
651
}
 
652
 
 
653
static void
 
654
main_window_accels_load (void)
 
655
{
 
656
        gchar *filename;
 
657
 
 
658
        filename = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, ACCELS_FILENAME, NULL);
 
659
        if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
 
660
                DEBUG ("Loading from:'%s'", filename);
 
661
                gtk_accel_map_load (filename);
 
662
        }
 
663
 
 
664
        g_free (filename);
 
665
}
 
666
 
 
667
static void
 
668
main_window_accels_save (void)
 
669
{
 
670
        gchar *dir;
 
671
        gchar *file_with_path;
 
672
 
 
673
        dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL);
 
674
        g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
 
675
        file_with_path = g_build_filename (dir, ACCELS_FILENAME, NULL);
 
676
        g_free (dir);
 
677
 
 
678
        DEBUG ("Saving to:'%s'", file_with_path);
 
679
        gtk_accel_map_save (file_with_path);
 
680
 
 
681
        g_free (file_with_path);
 
682
}
 
683
 
 
684
static void
 
685
empathy_main_window_finalize (GObject *window)
 
686
{
 
687
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
688
        GHashTableIter iter;
 
689
        gpointer key, value;
 
690
 
 
691
        /* Save user-defined accelerators. */
 
692
        main_window_accels_save ();
 
693
 
 
694
        g_list_free (priv->actions_connected);
 
695
 
 
696
        g_object_unref (priv->account_manager);
 
697
        g_object_unref (priv->individual_store);
 
698
        g_hash_table_destroy (priv->errors);
 
699
 
 
700
        /* disconnect all handlers of status-changed signal */
 
701
        g_hash_table_iter_init (&iter, priv->status_changed_handlers);
 
702
        while (g_hash_table_iter_next (&iter, &key, &value))
 
703
                g_signal_handler_disconnect (TP_ACCOUNT (key),
 
704
                                             GPOINTER_TO_UINT (value));
 
705
 
 
706
        g_hash_table_destroy (priv->status_changed_handlers);
 
707
 
 
708
        g_signal_handlers_disconnect_by_func (priv->event_manager,
 
709
                                              main_window_event_added_cb,
 
710
                                              window);
 
711
        g_signal_handlers_disconnect_by_func (priv->event_manager,
 
712
                                              main_window_event_removed_cb,
 
713
                                              window);
 
714
        g_object_unref (priv->event_manager);
 
715
        g_object_unref (priv->ui_manager);
 
716
        g_object_unref (priv->chatroom_manager);
 
717
 
 
718
        g_object_unref (priv->gsettings_ui);
 
719
        g_object_unref (priv->gsettings_contacts);
 
720
 
 
721
        G_OBJECT_CLASS (empathy_main_window_parent_class)->finalize (window);
 
722
}
 
723
 
 
724
static gboolean
 
725
main_window_key_press_event_cb  (GtkWidget   *window,
 
726
                                 GdkEventKey *event,
 
727
                                 gpointer     user_data)
 
728
{
 
729
        EmpathyChatManager *chat_manager;
 
730
 
 
731
        if (event->keyval == GDK_T
 
732
            && event->state & GDK_SHIFT_MASK
 
733
            && event->state & GDK_CONTROL_MASK) {
 
734
                chat_manager = empathy_chat_manager_dup_singleton ();
 
735
                empathy_chat_manager_undo_closed_chat (chat_manager);
 
736
                g_object_unref (chat_manager);
 
737
        }
 
738
        return FALSE;
 
739
}
 
740
 
 
741
static void
 
742
main_window_chat_quit_cb (GtkAction         *action,
 
743
                          EmpathyMainWindow *window)
 
744
{
 
745
        gtk_main_quit ();
 
746
}
 
747
 
 
748
static void
 
749
main_window_view_history_cb (GtkAction         *action,
 
750
                             EmpathyMainWindow *window)
 
751
{
 
752
        empathy_log_window_show (NULL, NULL, FALSE, GTK_WINDOW (window));
 
753
}
 
754
 
 
755
static void
 
756
main_window_chat_new_message_cb (GtkAction         *action,
 
757
                                 EmpathyMainWindow *window)
 
758
{
 
759
        empathy_new_message_dialog_show (GTK_WINDOW (window));
 
760
}
 
761
 
 
762
static void
 
763
main_window_chat_new_call_cb (GtkAction         *action,
 
764
                              EmpathyMainWindow *window)
 
765
{
 
766
        empathy_new_call_dialog_show (GTK_WINDOW (window));
 
767
}
 
768
 
 
769
static void
 
770
main_window_chat_add_contact_cb (GtkAction         *action,
 
771
                                 EmpathyMainWindow *window)
 
772
{
 
773
        empathy_new_individual_dialog_show (GTK_WINDOW (window));
 
774
}
 
775
 
 
776
static void
 
777
main_window_view_show_ft_manager (GtkAction         *action,
 
778
                                  EmpathyMainWindow *window)
 
779
{
 
780
        empathy_ft_manager_show ();
 
781
}
 
782
 
 
783
static void
 
784
main_window_view_show_offline_cb (GtkToggleAction   *action,
 
785
                                  EmpathyMainWindow *window)
 
786
{
 
787
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
788
        gboolean current;
 
789
 
 
790
        current = gtk_toggle_action_get_active (action);
 
791
        g_settings_set_boolean (priv->gsettings_ui,
 
792
                                EMPATHY_PREFS_UI_SHOW_OFFLINE,
 
793
                                current);
 
794
 
 
795
        empathy_individual_view_set_show_offline (priv->individual_view,
 
796
                        current);
 
797
}
 
798
 
 
799
static void
 
800
main_window_notify_sort_contact_cb (GSettings         *gsettings,
 
801
                                    const gchar       *key,
 
802
                                    EmpathyMainWindow *window)
 
803
{
 
804
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
805
        gchar *str;
 
806
 
 
807
        str = g_settings_get_string (gsettings, key);
 
808
 
 
809
        if (str != NULL) {
 
810
                GType       type;
 
811
                GEnumClass *enum_class;
 
812
                GEnumValue *enum_value;
 
813
 
 
814
                type = empathy_individual_store_sort_get_type ();
 
815
                enum_class = G_ENUM_CLASS (g_type_class_peek (type));
 
816
                enum_value = g_enum_get_value_by_nick (enum_class, str);
 
817
                if (enum_value) {
 
818
                        /* By changing the value of the GtkRadioAction,
 
819
                           it emits a signal that calls main_window_view_sort_contacts_cb
 
820
                           which updates the contacts list */
 
821
                        gtk_radio_action_set_current_value (priv->sort_by_name,
 
822
                                                            enum_value->value);
 
823
                } else {
 
824
                        g_warning ("Wrong value for sort_criterium configuration : %s", str);
 
825
                }
 
826
                g_free (str);
 
827
        }
 
828
}
 
829
 
 
830
static void
 
831
main_window_view_sort_contacts_cb (GtkRadioAction    *action,
 
832
                                   GtkRadioAction    *current,
 
833
                                   EmpathyMainWindow *window)
 
834
{
 
835
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
836
        EmpathyContactListStoreSort value;
 
837
        GSList      *group;
 
838
        GType        type;
 
839
        GEnumClass  *enum_class;
 
840
        GEnumValue  *enum_value;
 
841
 
 
842
        value = gtk_radio_action_get_current_value (action);
 
843
        group = gtk_radio_action_get_group (action);
 
844
 
 
845
        /* Get string from index */
 
846
        type = empathy_individual_store_sort_get_type ();
 
847
        enum_class = G_ENUM_CLASS (g_type_class_peek (type));
 
848
        enum_value = g_enum_get_value (enum_class, g_slist_index (group, current));
 
849
 
 
850
        if (!enum_value) {
 
851
                g_warning ("No GEnumValue for EmpathyContactListSort with GtkRadioAction index:%d",
 
852
                           g_slist_index (group, action));
 
853
        } else {
 
854
                g_settings_set_string (priv->gsettings_contacts,
 
855
                                       EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM,
 
856
                                       enum_value->value_nick);
 
857
        }
 
858
        empathy_individual_store_set_sort_criterium (priv->individual_store,
 
859
                        value);
 
860
}
 
861
 
 
862
static void
 
863
main_window_view_show_protocols_cb (GtkToggleAction   *action,
 
864
                                    EmpathyMainWindow *window)
 
865
{
 
866
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
867
        gboolean value;
 
868
 
 
869
        value = gtk_toggle_action_get_active (action);
 
870
 
 
871
        g_settings_set_boolean (priv->gsettings_ui,
 
872
                                EMPATHY_PREFS_UI_SHOW_PROTOCOLS,
 
873
                                value);
 
874
        empathy_individual_store_set_show_protocols (priv->individual_store,
 
875
                                                     value);
 
876
}
 
877
 
 
878
/* Matches GtkRadioAction values set in empathy-main-window.ui */
 
879
#define CONTACT_LIST_NORMAL_SIZE_WITH_AVATARS           0
 
880
#define CONTACT_LIST_NORMAL_SIZE                        1
 
881
#define CONTACT_LIST_COMPACT_SIZE                       2
 
882
 
 
883
static void
 
884
main_window_view_contacts_list_size_cb (GtkRadioAction    *action,
 
885
                                        GtkRadioAction    *current,
 
886
                                        EmpathyMainWindow *window)
 
887
{
 
888
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
889
        GSettings *gsettings_ui;
 
890
        gint value;
 
891
 
 
892
        value = gtk_radio_action_get_current_value (action);
 
893
        /* create a new GSettings, so we can delay the setting until both
 
894
         * values are set */
 
895
        gsettings_ui = g_settings_new (EMPATHY_PREFS_UI_SCHEMA);
 
896
 
 
897
        DEBUG ("radio button toggled, value = %i", value);
 
898
 
 
899
        g_settings_delay (gsettings_ui);
 
900
        g_settings_set_boolean (gsettings_ui,
 
901
                                EMPATHY_PREFS_UI_SHOW_AVATARS,
 
902
                                value == CONTACT_LIST_NORMAL_SIZE_WITH_AVATARS);
 
903
 
 
904
        g_settings_set_boolean (gsettings_ui,
 
905
                                EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
 
906
                                value == CONTACT_LIST_COMPACT_SIZE);
 
907
        g_settings_apply (gsettings_ui);
 
908
 
 
909
        /* FIXME: these enums probably have the wrong namespace */
 
910
        empathy_individual_store_set_show_avatars (priv->individual_store,
 
911
                        value == CONTACT_LIST_NORMAL_SIZE_WITH_AVATARS);
 
912
        empathy_individual_store_set_is_compact (priv->individual_store,
 
913
                        value == CONTACT_LIST_COMPACT_SIZE);
 
914
 
 
915
        g_object_unref (gsettings_ui);
 
916
}
 
917
 
 
918
static void main_window_notify_show_protocols_cb (GSettings         *gsettings,
 
919
                                                  const gchar       *key,
 
920
                                                  EmpathyMainWindow *window)
 
921
{
 
922
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
923
 
 
924
        gtk_toggle_action_set_active (priv->show_protocols,
 
925
                        g_settings_get_boolean (gsettings,
 
926
                                EMPATHY_PREFS_UI_SHOW_PROTOCOLS));
 
927
}
 
928
 
 
929
 
 
930
static void
 
931
main_window_notify_contact_list_size_cb (GSettings         *gsettings,
 
932
                                         const gchar       *key,
 
933
                                         EmpathyMainWindow *window)
 
934
{
 
935
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
936
        gint value;
 
937
 
 
938
        if (g_settings_get_boolean (gsettings,
 
939
                        EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST)) {
 
940
                value = CONTACT_LIST_COMPACT_SIZE;
 
941
        } else if (g_settings_get_boolean (gsettings,
 
942
                        EMPATHY_PREFS_UI_SHOW_AVATARS)) {
 
943
                value = CONTACT_LIST_NORMAL_SIZE_WITH_AVATARS;
 
944
        } else {
 
945
                value = CONTACT_LIST_NORMAL_SIZE;
 
946
        }
 
947
 
 
948
        DEBUG ("setting changed, value = %i", value);
 
949
 
 
950
        /* By changing the value of the GtkRadioAction,
 
951
           it emits a signal that calls main_window_view_contacts_list_size_cb
 
952
           which updates the contacts list */
 
953
        gtk_radio_action_set_current_value (priv->normal_with_avatars, value);
 
954
}
 
955
 
 
956
static void
 
957
main_window_view_show_map_cb (GtkCheckMenuItem  *item,
 
958
                              EmpathyMainWindow *window)
 
959
{
 
960
#ifdef HAVE_LIBCHAMPLAIN
 
961
        empathy_map_view_show ();
 
962
#endif
 
963
}
 
964
 
 
965
static void
 
966
join_chatroom (EmpathyChatroom *chatroom,
 
967
               gint64 timestamp)
 
968
{
 
969
        TpAccount      *account;
 
970
        const gchar    *room;
 
971
 
 
972
        account = empathy_chatroom_get_account (chatroom);
 
973
        room = empathy_chatroom_get_room (chatroom);
 
974
 
 
975
        DEBUG ("Requesting channel for '%s'", room);
 
976
        empathy_dispatcher_join_muc (account, room, timestamp);
 
977
}
 
978
 
 
979
typedef struct
 
980
{
 
981
        TpAccount *account;
 
982
        EmpathyChatroom *chatroom;
 
983
        gint64 timestamp;
 
984
        glong sig_id;
 
985
        guint timeout;
 
986
} join_fav_account_sig_ctx;
 
987
 
 
988
static join_fav_account_sig_ctx *
 
989
join_fav_account_sig_ctx_new (TpAccount *account,
 
990
                             EmpathyChatroom *chatroom,
 
991
                              gint64 timestamp)
 
992
{
 
993
        join_fav_account_sig_ctx *ctx = g_slice_new0 (
 
994
                join_fav_account_sig_ctx);
 
995
 
 
996
        ctx->account = g_object_ref (account);
 
997
        ctx->chatroom = g_object_ref (chatroom);
 
998
        ctx->timestamp = timestamp;
 
999
        return ctx;
 
1000
}
 
1001
 
 
1002
static void
 
1003
join_fav_account_sig_ctx_free (join_fav_account_sig_ctx *ctx)
 
1004
{
 
1005
        g_object_unref (ctx->account);
 
1006
        g_object_unref (ctx->chatroom);
 
1007
        g_slice_free (join_fav_account_sig_ctx, ctx);
 
1008
}
 
1009
 
 
1010
static void
 
1011
account_status_changed_cb (TpAccount  *account,
 
1012
                           TpConnectionStatus old_status,
 
1013
                           TpConnectionStatus new_status,
 
1014
                           guint reason,
 
1015
                           gchar *dbus_error_name,
 
1016
                           GHashTable *details,
 
1017
                           gpointer user_data)
 
1018
{
 
1019
        join_fav_account_sig_ctx *ctx = user_data;
 
1020
 
 
1021
        switch (new_status) {
 
1022
                case TP_CONNECTION_STATUS_DISCONNECTED:
 
1023
                        /* Don't wait any longer */
 
1024
                        goto finally;
 
1025
                        break;
 
1026
 
 
1027
                case TP_CONNECTION_STATUS_CONNECTING:
 
1028
                        /* Wait a bit */
 
1029
                        return;
 
1030
 
 
1031
                case TP_CONNECTION_STATUS_CONNECTED:
 
1032
                        /* We can join the room */
 
1033
                        break;
 
1034
 
 
1035
                default:
 
1036
                        g_assert_not_reached ();
 
1037
        }
 
1038
 
 
1039
        join_chatroom (ctx->chatroom, ctx->timestamp);
 
1040
 
 
1041
finally:
 
1042
        g_source_remove (ctx->timeout);
 
1043
        g_signal_handler_disconnect (account, ctx->sig_id);
 
1044
}
 
1045
 
 
1046
#define JOIN_FAVORITE_TIMEOUT 5
 
1047
 
 
1048
static gboolean
 
1049
join_favorite_timeout_cb (gpointer data)
 
1050
{
 
1051
        join_fav_account_sig_ctx *ctx = data;
 
1052
 
 
1053
        /* stop waiting for joining the favorite room */
 
1054
        g_signal_handler_disconnect (ctx->account, ctx->sig_id);
 
1055
        return FALSE;
 
1056
}
 
1057
 
 
1058
static void
 
1059
main_window_favorite_chatroom_join (EmpathyChatroom *chatroom)
 
1060
{
 
1061
        TpAccount      *account;
 
1062
 
 
1063
        account = empathy_chatroom_get_account (chatroom);
 
1064
        if (tp_account_get_connection_status (account, NULL) !=
 
1065
                                             TP_CONNECTION_STATUS_CONNECTED) {
 
1066
                join_fav_account_sig_ctx *ctx;
 
1067
 
 
1068
                ctx = join_fav_account_sig_ctx_new (account, chatroom,
 
1069
                        gtk_get_current_event_time ());
 
1070
 
 
1071
                ctx->sig_id = g_signal_connect_data (account, "status-changed",
 
1072
                        G_CALLBACK (account_status_changed_cb), ctx,
 
1073
                        (GClosureNotify) join_fav_account_sig_ctx_free, 0);
 
1074
 
 
1075
                ctx->timeout = g_timeout_add_seconds (JOIN_FAVORITE_TIMEOUT,
 
1076
                        join_favorite_timeout_cb, ctx);
 
1077
                return;
 
1078
        }
 
1079
 
 
1080
        join_chatroom (chatroom, gtk_get_current_event_time ());
 
1081
}
 
1082
 
 
1083
static void
 
1084
main_window_favorite_chatroom_menu_activate_cb (GtkMenuItem     *menu_item,
 
1085
                                                EmpathyChatroom *chatroom)
 
1086
{
 
1087
        main_window_favorite_chatroom_join (chatroom);
 
1088
}
 
1089
 
 
1090
static void
 
1091
main_window_favorite_chatroom_menu_add (EmpathyMainWindow *window,
 
1092
                                        EmpathyChatroom   *chatroom)
 
1093
{
 
1094
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1095
        GtkWidget   *menu_item;
 
1096
        const gchar *name;
 
1097
 
 
1098
        if (g_object_get_data (G_OBJECT (chatroom), "menu_item")) {
 
1099
                return;
 
1100
        }
 
1101
 
 
1102
        name = empathy_chatroom_get_name (chatroom);
 
1103
        menu_item = gtk_menu_item_new_with_label (name);
 
1104
 
 
1105
        g_object_set_data (G_OBJECT (chatroom), "menu_item", menu_item);
 
1106
        g_signal_connect (menu_item, "activate",
 
1107
                          G_CALLBACK (main_window_favorite_chatroom_menu_activate_cb),
 
1108
                          chatroom);
 
1109
 
 
1110
        gtk_menu_shell_insert (GTK_MENU_SHELL (priv->room_menu),
 
1111
                               menu_item, 4);
 
1112
 
 
1113
        gtk_widget_show (menu_item);
 
1114
}
 
1115
 
 
1116
static void
 
1117
main_window_favorite_chatroom_menu_added_cb (EmpathyChatroomManager *manager,
 
1118
                                             EmpathyChatroom        *chatroom,
 
1119
                                             EmpathyMainWindow      *window)
 
1120
{
 
1121
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1122
 
 
1123
        main_window_favorite_chatroom_menu_add (window, chatroom);
 
1124
        gtk_widget_show (priv->room_separator);
 
1125
        gtk_action_set_sensitive (priv->room_join_favorites, TRUE);
 
1126
}
 
1127
 
 
1128
static void
 
1129
main_window_favorite_chatroom_menu_removed_cb (EmpathyChatroomManager *manager,
 
1130
                                               EmpathyChatroom        *chatroom,
 
1131
                                               EmpathyMainWindow      *window)
 
1132
{
 
1133
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1134
        GtkWidget *menu_item;
 
1135
        GList *chatrooms;
 
1136
 
 
1137
        menu_item = g_object_get_data (G_OBJECT (chatroom), "menu_item");
 
1138
        g_object_set_data (G_OBJECT (chatroom), "menu_item", NULL);
 
1139
        gtk_widget_destroy (menu_item);
 
1140
 
 
1141
        chatrooms = empathy_chatroom_manager_get_chatrooms (priv->chatroom_manager, NULL);
 
1142
        if (chatrooms) {
 
1143
                gtk_widget_show (priv->room_separator);
 
1144
        } else {
 
1145
                gtk_widget_hide (priv->room_separator);
 
1146
        }
 
1147
 
 
1148
        gtk_action_set_sensitive (priv->room_join_favorites, chatrooms != NULL);
 
1149
        g_list_free (chatrooms);
 
1150
}
 
1151
 
 
1152
static void
 
1153
main_window_favorite_chatroom_menu_setup (EmpathyMainWindow *window)
 
1154
{
 
1155
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1156
        GList *chatrooms, *l;
 
1157
        GtkWidget *room;
 
1158
 
 
1159
        priv->chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL);
 
1160
        chatrooms = empathy_chatroom_manager_get_chatrooms (
 
1161
                priv->chatroom_manager, NULL);
 
1162
        room = gtk_ui_manager_get_widget (priv->ui_manager,
 
1163
                "/menubar/room");
 
1164
        priv->room_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (room));
 
1165
        priv->room_separator = gtk_ui_manager_get_widget (priv->ui_manager,
 
1166
                "/menubar/room/room_separator");
 
1167
 
 
1168
        for (l = chatrooms; l; l = l->next) {
 
1169
                main_window_favorite_chatroom_menu_add (window, l->data);
 
1170
        }
 
1171
 
 
1172
        if (!chatrooms) {
 
1173
                gtk_widget_hide (priv->room_separator);
 
1174
        }
 
1175
 
 
1176
        gtk_action_set_sensitive (priv->room_join_favorites, chatrooms != NULL);
 
1177
 
 
1178
        g_signal_connect (priv->chatroom_manager, "chatroom-added",
 
1179
                          G_CALLBACK (main_window_favorite_chatroom_menu_added_cb),
 
1180
                          window);
 
1181
        g_signal_connect (priv->chatroom_manager, "chatroom-removed",
 
1182
                          G_CALLBACK (main_window_favorite_chatroom_menu_removed_cb),
 
1183
                          window);
 
1184
 
 
1185
        g_list_free (chatrooms);
 
1186
}
 
1187
 
 
1188
static void
 
1189
main_window_room_join_new_cb (GtkAction         *action,
 
1190
                              EmpathyMainWindow *window)
 
1191
{
 
1192
        empathy_new_chatroom_dialog_show (GTK_WINDOW (window));
 
1193
}
 
1194
 
 
1195
static void
 
1196
main_window_room_join_favorites_cb (GtkAction         *action,
 
1197
                                    EmpathyMainWindow *window)
 
1198
{
 
1199
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1200
        GList *chatrooms, *l;
 
1201
 
 
1202
        chatrooms = empathy_chatroom_manager_get_chatrooms (priv->chatroom_manager, NULL);
 
1203
        for (l = chatrooms; l; l = l->next) {
 
1204
                main_window_favorite_chatroom_join (l->data);
 
1205
        }
 
1206
        g_list_free (chatrooms);
 
1207
}
 
1208
 
 
1209
static void
 
1210
main_window_room_manage_favorites_cb (GtkAction         *action,
 
1211
                                      EmpathyMainWindow *window)
 
1212
{
 
1213
        empathy_chatrooms_window_show (GTK_WINDOW (window));
 
1214
}
 
1215
 
 
1216
static void
 
1217
main_window_edit_cb (GtkAction         *action,
 
1218
                     EmpathyMainWindow *window)
 
1219
{
 
1220
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1221
        GtkWidget *submenu;
 
1222
 
 
1223
        /* FIXME: It should use the UIManager to merge the contact/group submenu */
 
1224
        submenu = empathy_individual_view_get_individual_menu (
 
1225
                        priv->individual_view);
 
1226
        if (submenu) {
 
1227
                GtkMenuItem *item;
 
1228
                GtkWidget   *label;
 
1229
 
 
1230
                item = GTK_MENU_ITEM (priv->edit_context);
 
1231
                label = gtk_bin_get_child (GTK_BIN (item));
 
1232
                gtk_label_set_text (GTK_LABEL (label), _("Contact"));
 
1233
 
 
1234
                gtk_widget_show (priv->edit_context);
 
1235
                gtk_widget_show (priv->edit_context_separator);
 
1236
 
 
1237
                gtk_menu_item_set_submenu (item, submenu);
 
1238
 
 
1239
                return;
 
1240
        }
 
1241
 
 
1242
        submenu = empathy_individual_view_get_group_menu (
 
1243
                        priv->individual_view);
 
1244
        if (submenu) {
 
1245
                GtkMenuItem *item;
 
1246
                GtkWidget   *label;
 
1247
 
 
1248
                item = GTK_MENU_ITEM (priv->edit_context);
 
1249
                label = gtk_bin_get_child (GTK_BIN (item));
 
1250
                gtk_label_set_text (GTK_LABEL (label), _("Group"));
 
1251
 
 
1252
                gtk_widget_show (priv->edit_context);
 
1253
                gtk_widget_show (priv->edit_context_separator);
 
1254
 
 
1255
                gtk_menu_item_set_submenu (item, submenu);
 
1256
 
 
1257
                return;
 
1258
        }
 
1259
 
 
1260
        gtk_widget_hide (priv->edit_context);
 
1261
        gtk_widget_hide (priv->edit_context_separator);
 
1262
 
 
1263
        return;
 
1264
}
 
1265
 
 
1266
static void
 
1267
main_window_edit_accounts_cb (GtkAction         *action,
 
1268
                              EmpathyMainWindow *window)
 
1269
{
 
1270
        empathy_accounts_dialog_show_application (gdk_screen_get_default (),
 
1271
                        NULL, FALSE, FALSE);
 
1272
}
 
1273
 
 
1274
static void
 
1275
main_window_edit_personal_information_cb (GtkAction         *action,
 
1276
                                          EmpathyMainWindow *window)
 
1277
{
 
1278
        empathy_contact_personal_dialog_show (GTK_WINDOW (window));
 
1279
}
 
1280
 
 
1281
static void
 
1282
main_window_edit_preferences_cb (GtkAction         *action,
 
1283
                                 EmpathyMainWindow *window)
 
1284
{
 
1285
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1286
 
 
1287
        if (priv->preferences == NULL) {
 
1288
                priv->preferences = empathy_preferences_new (GTK_WINDOW (window));
 
1289
                g_object_add_weak_pointer (G_OBJECT (priv->preferences),
 
1290
                                           (gpointer) &priv->preferences);
 
1291
 
 
1292
                gtk_widget_show (priv->preferences);
 
1293
        } else {
 
1294
                gtk_window_present (GTK_WINDOW (priv->preferences));
 
1295
        }
 
1296
}
 
1297
 
 
1298
static void
 
1299
main_window_help_about_cb (GtkAction         *action,
 
1300
                           EmpathyMainWindow *window)
 
1301
{
 
1302
        empathy_about_dialog_new (GTK_WINDOW (window));
 
1303
}
 
1304
 
 
1305
static void
 
1306
main_window_help_debug_cb (GtkAction         *action,
 
1307
                           EmpathyMainWindow *window)
 
1308
{
 
1309
        GdkScreen *screen = gdk_screen_get_default ();
 
1310
        GError *error = NULL;
 
1311
        gchar *argv[2] = { NULL, };
 
1312
        gint i = 0;
 
1313
        gchar *path;
 
1314
 
 
1315
        g_return_if_fail (GDK_IS_SCREEN (screen));
 
1316
 
 
1317
        /* Try to run from source directory if possible */
 
1318
        path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), "src",
 
1319
                        "empathy-debugger", NULL);
 
1320
 
 
1321
        if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
 
1322
                g_free (path);
 
1323
                path = g_build_filename (BIN_DIR, "empathy-debugger", NULL);
 
1324
        }
 
1325
 
 
1326
        argv[i++] = path;
 
1327
 
 
1328
        gdk_spawn_on_screen (screen, NULL, argv, NULL,
 
1329
                        G_SPAWN_SEARCH_PATH,
 
1330
                        NULL, NULL, NULL, &error);
 
1331
 
 
1332
        if (error) {
 
1333
                g_warning ("Failed to open debug window: %s", error->message);
 
1334
                g_error_free (error);
 
1335
        }
 
1336
 
 
1337
        g_free (path);
 
1338
}
 
1339
 
 
1340
static void
 
1341
main_window_help_contents_cb (GtkAction         *action,
 
1342
                              EmpathyMainWindow *window)
 
1343
{
 
1344
        empathy_url_show (GTK_WIDGET (window), "ghelp:empathy");
 
1345
}
 
1346
 
 
1347
static gboolean
 
1348
main_window_throbber_button_press_event_cb (GtkWidget         *throbber,
 
1349
                                            GdkEventButton    *event,
 
1350
                                            EmpathyMainWindow *window)
 
1351
{
 
1352
        if (event->type != GDK_BUTTON_PRESS ||
 
1353
            event->button != 1) {
 
1354
                return FALSE;
 
1355
        }
 
1356
 
 
1357
        empathy_accounts_dialog_show_application (
 
1358
                        gtk_widget_get_screen (GTK_WIDGET (throbber)),
 
1359
                        NULL, FALSE, FALSE);
 
1360
 
 
1361
        return FALSE;
 
1362
}
 
1363
 
 
1364
static void
 
1365
main_window_account_removed_cb (TpAccountManager  *manager,
 
1366
                                TpAccount         *account,
 
1367
                                EmpathyMainWindow *window)
 
1368
{
 
1369
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1370
        GList *a;
 
1371
 
 
1372
        a = tp_account_manager_get_valid_accounts (manager);
 
1373
 
 
1374
        gtk_action_set_sensitive (priv->view_history,
 
1375
                g_list_length (a) > 0);
 
1376
 
 
1377
        g_list_free (a);
 
1378
 
 
1379
        /* remove errors if any */
 
1380
        main_window_remove_error (window, account);
 
1381
}
 
1382
 
 
1383
static void
 
1384
main_window_account_validity_changed_cb (TpAccountManager  *manager,
 
1385
                                         TpAccount         *account,
 
1386
                                         gboolean           valid,
 
1387
                                         EmpathyMainWindow *window)
 
1388
{
 
1389
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1390
 
 
1391
        if (valid) {
 
1392
                gulong handler_id;
 
1393
                handler_id = GPOINTER_TO_UINT (g_hash_table_lookup (
 
1394
                        priv->status_changed_handlers, account));
 
1395
 
 
1396
                /* connect signal only if it was not connected yet */
 
1397
                if (handler_id == 0) {
 
1398
                        handler_id = g_signal_connect (account,
 
1399
                                "status-changed",
 
1400
                                G_CALLBACK (main_window_connection_changed_cb),
 
1401
                                window);
 
1402
                        g_hash_table_insert (priv->status_changed_handlers,
 
1403
                                account, GUINT_TO_POINTER (handler_id));
 
1404
                }
 
1405
        }
 
1406
 
 
1407
        main_window_account_removed_cb (manager, account, window);
 
1408
}
 
1409
 
 
1410
static void
 
1411
main_window_notify_show_offline_cb (GSettings   *gsettings,
 
1412
                                    const gchar *key,
 
1413
                                    gpointer     toggle_action)
 
1414
{
 
1415
        gtk_toggle_action_set_active (toggle_action,
 
1416
                        g_settings_get_boolean (gsettings, key));
 
1417
}
 
1418
 
 
1419
static void
 
1420
main_window_connection_items_setup (EmpathyMainWindow *window,
 
1421
                                    GtkBuilder        *gui)
 
1422
{
 
1423
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1424
        GList         *list;
 
1425
        GObject       *action;
 
1426
        guint          i;
 
1427
        const gchar *actions_connected[] = {
 
1428
                "room",
 
1429
                "chat_new_message",
 
1430
                "chat_new_call",
 
1431
                "chat_add_contact",
 
1432
                "edit_personal_information"
 
1433
        };
 
1434
 
 
1435
        for (i = 0, list = NULL; i < G_N_ELEMENTS (actions_connected); i++) {
 
1436
                action = gtk_builder_get_object (gui, actions_connected[i]);
 
1437
                list = g_list_prepend (list, action);
 
1438
        }
 
1439
 
 
1440
        priv->actions_connected = list;
 
1441
}
 
1442
 
 
1443
static void
 
1444
account_manager_prepared_cb (GObject      *source_object,
 
1445
                             GAsyncResult *result,
 
1446
                             gpointer      user_data)
 
1447
{
 
1448
        GList *accounts, *j;
 
1449
        TpAccountManager *manager = TP_ACCOUNT_MANAGER (source_object);
 
1450
        EmpathyMainWindow *window = user_data;
 
1451
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1452
        GError *error = NULL;
 
1453
 
 
1454
        if (!tp_account_manager_prepare_finish (manager, result, &error)) {
 
1455
                DEBUG ("Failed to prepare account manager: %s", error->message);
 
1456
                g_error_free (error);
 
1457
                return;
 
1458
        }
 
1459
 
 
1460
        accounts = tp_account_manager_get_valid_accounts (priv->account_manager);
 
1461
        for (j = accounts; j != NULL; j = j->next) {
 
1462
                TpAccount *account = TP_ACCOUNT (j->data);
 
1463
                gulong handler_id;
 
1464
 
 
1465
                handler_id = g_signal_connect (account, "status-changed",
 
1466
                                  G_CALLBACK (main_window_connection_changed_cb),
 
1467
                                  window);
 
1468
                g_hash_table_insert (priv->status_changed_handlers,
 
1469
                                     account, GUINT_TO_POINTER (handler_id));
 
1470
        }
 
1471
 
 
1472
        g_signal_connect (manager, "account-validity-changed",
 
1473
                          G_CALLBACK (main_window_account_validity_changed_cb),
 
1474
                          window);
 
1475
 
 
1476
        main_window_update_status (window);
 
1477
 
 
1478
        /* Disable the "Previous Conversations" menu entry if there is no account */
 
1479
        gtk_action_set_sensitive (priv->view_history,
 
1480
                g_list_length (accounts) > 0);
 
1481
 
 
1482
        g_list_free (accounts);
 
1483
}
 
1484
 
 
1485
static void
 
1486
main_window_members_changed_cb (EmpathyContactList *list,
 
1487
                                EmpathyContact     *contact,
 
1488
                                EmpathyContact     *actor,
 
1489
                                guint               reason,
 
1490
                                gchar              *message,
 
1491
                                gboolean            is_member,
 
1492
                                EmpathyMainWindow  *window)
 
1493
{
 
1494
        EmpathyMainWindowPriv *priv = GET_PRIV (window);
 
1495
 
 
1496
        if (!is_member)
 
1497
                return;
 
1498
 
 
1499
        if (!empathy_migrate_butterfly_logs (contact)) {
 
1500
                g_signal_handler_disconnect (list,
 
1501
                        priv->butterfly_log_migration_members_changed_id);
 
1502
                priv->butterfly_log_migration_members_changed_id = 0;
 
1503
        }
 
1504
}
 
1505
 
 
1506
static GObject *
 
1507
empathy_main_window_constructor (GType type,
 
1508
                                 guint n_construct_params,
 
1509
                                 GObjectConstructParam *construct_params)
 
1510
{
 
1511
        static GObject *window = NULL;
 
1512
 
 
1513
        if (window != NULL)
 
1514
                return g_object_ref (window);
 
1515
 
 
1516
        window = G_OBJECT_CLASS (empathy_main_window_parent_class)->constructor (
 
1517
                type, n_construct_params, construct_params);
 
1518
 
 
1519
        g_object_add_weak_pointer (window, (gpointer) &window);
 
1520
 
 
1521
        return window;
 
1522
}
 
1523
 
 
1524
static void
 
1525
empathy_main_window_class_init (EmpathyMainWindowClass *klass)
 
1526
{
 
1527
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
1528
 
 
1529
        object_class->finalize = empathy_main_window_finalize;
 
1530
        object_class->constructor = empathy_main_window_constructor;
 
1531
 
 
1532
        g_type_class_add_private (object_class, sizeof (EmpathyMainWindowPriv));
 
1533
}
 
1534
 
 
1535
static void
 
1536
empathy_main_window_init (EmpathyMainWindow *window)
 
1537
{
 
1538
        EmpathyMainWindowPriv    *priv;
 
1539
        EmpathyContactList       *list_iface;
 
1540
        EmpathyIndividualManager *individual_manager;
 
1541
        GtkBuilder               *gui;
 
1542
        GtkWidget                *sw;
 
1543
        GtkToggleAction          *show_offline_widget;
 
1544
        GtkAction                *show_map_widget;
 
1545
        GtkToolItem              *item;
 
1546
        gboolean                  show_offline;
 
1547
        gchar                    *filename;
 
1548
        GSList                   *l;
 
1549
        GtkTreeModel             *model;
 
1550
 
 
1551
        priv = window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
 
1552
                        EMPATHY_TYPE_MAIN_WINDOW, EmpathyMainWindowPriv);
 
1553
 
 
1554
        priv->gsettings_ui = g_settings_new (EMPATHY_PREFS_UI_SCHEMA);
 
1555
        priv->gsettings_contacts = g_settings_new (EMPATHY_PREFS_CONTACTS_SCHEMA);
 
1556
 
 
1557
        gtk_window_set_title (GTK_WINDOW (window), _("Contact List"));
 
1558
        gtk_window_set_role (GTK_WINDOW (window), "contact_list");
 
1559
        gtk_window_set_default_size (GTK_WINDOW (window), 225, 325);
 
1560
 
 
1561
        /* Set up interface */
 
1562
        filename = empathy_file_lookup ("empathy-main-window.ui", "src");
 
1563
        gui = empathy_builder_get_file (filename,
 
1564
                                       "main_vbox", &priv->main_vbox,
 
1565
                                       "errors_vbox", &priv->errors_vbox,
 
1566
                                       "ui_manager", &priv->ui_manager,
 
1567
                                       "view_show_offline", &show_offline_widget,
 
1568
                                       "view_show_protocols", &priv->show_protocols,
 
1569
                                       "view_sort_by_name", &priv->sort_by_name,
 
1570
                                       "view_sort_by_status", &priv->sort_by_status,
 
1571
                                       "view_normal_size_with_avatars", &priv->normal_with_avatars,
 
1572
                                       "view_normal_size", &priv->normal_size,
 
1573
                                       "view_compact_size", &priv->compact_size,
 
1574
                                       "view_history", &priv->view_history,
 
1575
                                       "view_show_map", &show_map_widget,
 
1576
                                       "room_join_favorites", &priv->room_join_favorites,
 
1577
                                       "presence_toolbar", &priv->presence_toolbar,
 
1578
                                       "notebook", &priv->notebook,
 
1579
                                       "no_entry_label", &priv->no_entry_label,
 
1580
                                       "roster_scrolledwindow", &sw,
 
1581
                                       NULL);
 
1582
        g_free (filename);
 
1583
 
 
1584
        gtk_container_add (GTK_CONTAINER (window), priv->main_vbox);
 
1585
        gtk_widget_show (priv->main_vbox);
 
1586
 
 
1587
        g_signal_connect (window, "key-press-event",
 
1588
                          G_CALLBACK (main_window_key_press_event_cb), NULL);
 
1589
 
 
1590
        empathy_builder_connect (gui, window,
 
1591
                              "chat_quit", "activate", main_window_chat_quit_cb,
 
1592
                              "chat_new_message", "activate", main_window_chat_new_message_cb,
 
1593
                              "chat_new_call", "activate", main_window_chat_new_call_cb,
 
1594
                              "view_history", "activate", main_window_view_history_cb,
 
1595
                              "room_join_new", "activate", main_window_room_join_new_cb,
 
1596
                              "room_join_favorites", "activate", main_window_room_join_favorites_cb,
 
1597
                              "room_manage_favorites", "activate", main_window_room_manage_favorites_cb,
 
1598
                              "chat_add_contact", "activate", main_window_chat_add_contact_cb,
 
1599
                              "view_show_ft_manager", "activate", main_window_view_show_ft_manager,
 
1600
                              "view_show_offline", "toggled", main_window_view_show_offline_cb,
 
1601
                              "view_show_protocols", "toggled", main_window_view_show_protocols_cb,
 
1602
                              "view_sort_by_name", "changed", main_window_view_sort_contacts_cb,
 
1603
                              "view_normal_size_with_avatars", "changed", main_window_view_contacts_list_size_cb,
 
1604
                              "view_show_map", "activate", main_window_view_show_map_cb,
 
1605
                              "edit", "activate", main_window_edit_cb,
 
1606
                              "edit_accounts", "activate", main_window_edit_accounts_cb,
 
1607
                              "edit_personal_information", "activate", main_window_edit_personal_information_cb,
 
1608
                              "edit_preferences", "activate", main_window_edit_preferences_cb,
 
1609
                              "help_about", "activate", main_window_help_about_cb,
 
1610
                              "help_debug", "activate", main_window_help_debug_cb,
 
1611
                              "help_contents", "activate", main_window_help_contents_cb,
 
1612
                              NULL);
 
1613
 
 
1614
        /* Set up connection related widgets. */
 
1615
        main_window_connection_items_setup (window, gui);
 
1616
 
 
1617
        g_object_ref (priv->ui_manager);
 
1618
        g_object_unref (gui);
 
1619
 
 
1620
#ifndef HAVE_LIBCHAMPLAIN
 
1621
        gtk_action_set_visible (show_map_widget, FALSE);
 
1622
#endif
 
1623
 
 
1624
        priv->account_manager = tp_account_manager_dup ();
 
1625
 
 
1626
        tp_account_manager_prepare_async (priv->account_manager, NULL,
 
1627
                                          account_manager_prepared_cb, window);
 
1628
 
 
1629
        priv->errors = g_hash_table_new_full (g_direct_hash,
 
1630
                                              g_direct_equal,
 
1631
                                              g_object_unref,
 
1632
                                              NULL);
 
1633
 
 
1634
        priv->status_changed_handlers = g_hash_table_new_full (g_direct_hash,
 
1635
                                                               g_direct_equal,
 
1636
                                                               NULL,
 
1637
                                                               NULL);
 
1638
 
 
1639
        /* Set up menu */
 
1640
        main_window_favorite_chatroom_menu_setup (window);
 
1641
 
 
1642
        priv->edit_context = gtk_ui_manager_get_widget (priv->ui_manager,
 
1643
                "/menubar/edit/edit_context");
 
1644
        priv->edit_context_separator = gtk_ui_manager_get_widget (
 
1645
                priv->ui_manager,
 
1646
                "/menubar/edit/edit_context_separator");
 
1647
        gtk_widget_hide (priv->edit_context);
 
1648
        gtk_widget_hide (priv->edit_context_separator);
 
1649
 
 
1650
        /* Set up contact list. */
 
1651
        empathy_status_presets_get_all ();
 
1652
 
 
1653
        /* Set up presence chooser */
 
1654
        priv->presence_chooser = empathy_presence_chooser_new ();
 
1655
        gtk_widget_show (priv->presence_chooser);
 
1656
        item = gtk_tool_item_new ();
 
1657
        gtk_widget_show (GTK_WIDGET (item));
 
1658
        gtk_container_add (GTK_CONTAINER (item), priv->presence_chooser);
 
1659
        gtk_tool_item_set_is_important (item, TRUE);
 
1660
        gtk_tool_item_set_expand (item, TRUE);
 
1661
        gtk_toolbar_insert (GTK_TOOLBAR (priv->presence_toolbar), item, -1);
 
1662
 
 
1663
        /* Set up the throbber */
 
1664
        priv->throbber = gtk_spinner_new ();
 
1665
        gtk_widget_set_size_request (priv->throbber, 16, -1);
 
1666
        gtk_widget_set_tooltip_text (priv->throbber, _("Show and edit accounts"));
 
1667
        gtk_widget_set_has_window (GTK_WIDGET (priv->throbber), TRUE);
 
1668
        gtk_widget_set_events (priv->throbber, GDK_BUTTON_PRESS_MASK);
 
1669
        g_signal_connect (priv->throbber, "button-press-event",
 
1670
                G_CALLBACK (main_window_throbber_button_press_event_cb),
 
1671
                window);
 
1672
        gtk_widget_show (priv->throbber);
 
1673
 
 
1674
        item = gtk_tool_item_new ();
 
1675
        gtk_container_set_border_width (GTK_CONTAINER (item), 6);
 
1676
        gtk_toolbar_insert (GTK_TOOLBAR (priv->presence_toolbar), item, -1);
 
1677
        gtk_container_add (GTK_CONTAINER (item), priv->throbber);
 
1678
        priv->throbber_tool_item = GTK_WIDGET (item);
 
1679
 
 
1680
        list_iface = EMPATHY_CONTACT_LIST (empathy_contact_manager_dup_singleton ());
 
1681
        individual_manager = empathy_individual_manager_dup_singleton ();
 
1682
        priv->individual_store = empathy_individual_store_new (
 
1683
                        individual_manager);
 
1684
        g_object_unref (individual_manager);
 
1685
 
 
1686
        /* For the moment, we disallow Persona drops onto the main contact list (e.g. from things such as
 
1687
         * the EmpathyPersonaView in the linking dialogue). No code is hooked up to do anything on a Persona
 
1688
         * drop, so allowing them would achieve nothing except confusion. */
 
1689
        priv->individual_view = empathy_individual_view_new (
 
1690
                        priv->individual_store,
 
1691
                        EMPATHY_INDIVIDUAL_VIEW_FEATURE_ALL ^ EMPATHY_INDIVIDUAL_VIEW_FEATURE_PERSONA_DROP,
 
1692
                        EMPATHY_INDIVIDUAL_FEATURE_ALL);
 
1693
 
 
1694
        priv->butterfly_log_migration_members_changed_id = g_signal_connect (
 
1695
                        list_iface, "members-changed",
 
1696
                        G_CALLBACK (main_window_members_changed_cb), window);
 
1697
 
 
1698
        g_object_unref (list_iface);
 
1699
 
 
1700
        gtk_widget_show (GTK_WIDGET (priv->individual_view));
 
1701
        gtk_container_add (GTK_CONTAINER (sw),
 
1702
                           GTK_WIDGET (priv->individual_view));
 
1703
        g_signal_connect (priv->individual_view, "row-activated",
 
1704
                          G_CALLBACK (main_window_row_activated_cb),
 
1705
                          window);
 
1706
 
 
1707
        /* Set up search bar */
 
1708
        priv->search_bar = empathy_live_search_new (
 
1709
                GTK_WIDGET (priv->individual_view));
 
1710
        empathy_individual_view_set_live_search (priv->individual_view,
 
1711
                EMPATHY_LIVE_SEARCH (priv->search_bar));
 
1712
        gtk_box_pack_start (GTK_BOX (priv->main_vbox), priv->search_bar,
 
1713
                FALSE, TRUE, 0);
 
1714
        g_signal_connect_swapped (window, "map",
 
1715
                G_CALLBACK (gtk_widget_grab_focus), priv->individual_view);
 
1716
 
 
1717
        /* Connect to proper signals to check if contact list is empty or not */
 
1718
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->individual_view));
 
1719
        priv->empty = TRUE;
 
1720
        g_signal_connect (model, "row-inserted",
 
1721
                          G_CALLBACK (main_window_row_inserted_cb),
 
1722
                          window);
 
1723
        g_signal_connect (model, "row-deleted",
 
1724
                          G_CALLBACK (main_window_row_deleted_cb),
 
1725
                          window);
 
1726
 
 
1727
        /* Load user-defined accelerators. */
 
1728
        main_window_accels_load ();
 
1729
 
 
1730
        /* Set window size. */
 
1731
        empathy_geometry_bind (GTK_WINDOW (window), GEOMETRY_NAME);
 
1732
 
 
1733
        /* Enable event handling */
 
1734
        priv->event_manager = empathy_event_manager_dup_singleton ();
 
1735
 
 
1736
        g_signal_connect (priv->event_manager, "event-added",
 
1737
                          G_CALLBACK (main_window_event_added_cb), window);
 
1738
        g_signal_connect (priv->event_manager, "event-removed",
 
1739
                          G_CALLBACK (main_window_event_removed_cb), window);
 
1740
        g_signal_connect (priv->account_manager, "account-validity-changed",
 
1741
                          G_CALLBACK (main_window_account_validity_changed_cb),
 
1742
                          window);
 
1743
        g_signal_connect (priv->account_manager, "account-removed",
 
1744
                          G_CALLBACK (main_window_account_removed_cb),
 
1745
                          window);
 
1746
        g_signal_connect (priv->account_manager, "account-disabled",
 
1747
                          G_CALLBACK (main_window_account_disabled_cb),
 
1748
                          window);
 
1749
 
 
1750
        l = empathy_event_manager_get_events (priv->event_manager);
 
1751
        while (l) {
 
1752
                main_window_event_added_cb (priv->event_manager, l->data,
 
1753
                                window);
 
1754
                l = l->next;
 
1755
        }
 
1756
 
 
1757
        /* Show offline ? */
 
1758
        show_offline = g_settings_get_boolean (priv->gsettings_ui,
 
1759
                                               EMPATHY_PREFS_UI_SHOW_OFFLINE);
 
1760
        g_signal_connect (priv->gsettings_ui,
 
1761
                          "changed::" EMPATHY_PREFS_UI_SHOW_OFFLINE,
 
1762
                          G_CALLBACK (main_window_notify_show_offline_cb),
 
1763
                          show_offline_widget);
 
1764
 
 
1765
        gtk_toggle_action_set_active (show_offline_widget, show_offline);
 
1766
 
 
1767
        /* Show protocol ? */
 
1768
        g_signal_connect (priv->gsettings_ui,
 
1769
                          "changed::" EMPATHY_PREFS_UI_SHOW_PROTOCOLS,
 
1770
                          G_CALLBACK (main_window_notify_show_protocols_cb),
 
1771
                          window);
 
1772
 
 
1773
        main_window_notify_show_protocols_cb (priv->gsettings_ui,
 
1774
                                              EMPATHY_PREFS_UI_SHOW_PROTOCOLS,
 
1775
                                              window);
 
1776
 
 
1777
        /* Sort by name / by status ? */
 
1778
        g_signal_connect (priv->gsettings_contacts,
 
1779
                          "changed::" EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM,
 
1780
                          G_CALLBACK (main_window_notify_sort_contact_cb),
 
1781
                          window);
 
1782
 
 
1783
        main_window_notify_sort_contact_cb (priv->gsettings_contacts,
 
1784
                                            EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM,
 
1785
                                            window);
 
1786
 
 
1787
        /* Contacts list size */
 
1788
        g_signal_connect (priv->gsettings_ui,
 
1789
                          "changed::" EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
 
1790
                          G_CALLBACK (main_window_notify_contact_list_size_cb),
 
1791
                          window);
 
1792
        g_signal_connect (priv->gsettings_ui,
 
1793
                          "changed::" EMPATHY_PREFS_UI_SHOW_AVATARS,
 
1794
                          G_CALLBACK (main_window_notify_contact_list_size_cb),
 
1795
                          window);
 
1796
 
 
1797
        main_window_notify_contact_list_size_cb (priv->gsettings_ui,
 
1798
                                                 EMPATHY_PREFS_UI_SHOW_AVATARS,
 
1799
                                                 window);
 
1800
}
 
1801
 
 
1802
GtkWidget *
 
1803
empathy_main_window_dup (void)
 
1804
{
 
1805
        return g_object_new (EMPATHY_TYPE_MAIN_WINDOW, NULL);
 
1806
}