uimanager.c 61.1 KB
Newer Older
1
/*
2
 *  Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 *  Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19
20
21
22
23
24
25
26
27
28
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
29
30
 */

31
32
33
34
35
36
#include "config.h"
#include "preferencesdialog.h"
#include "logger.h"
#include "dbus/dbus.h"
#include "mainwindow.h"
#include "assistant.h"
37
#include <gtk/gtk.h>
38
#include <string.h>
39
40
#include <glib/gprintf.h>
#include <libgnome/gnome-help.h>
41

42
43
44
45
#include "uimanager.h"
#include "statusicon.h"
#include "widget/imwidget.h"
#include "eel-gconf-extensions.h"
46

47
#include "config/audioconf.h"
Julien Bonjean's avatar
Julien Bonjean committed
48
49
#include "uimanager.h"
#include "statusicon.h"
50
51

#include "contacts/addrbookfactory.h"
52
#include "contacts/calltab.h"
53
#include "config/addressbook-config.h"
54

Julien Bonjean's avatar
Julien Bonjean committed
55
56
57
#include "accountlist.h"
#include "config/accountlistconfigdialog.h"

58
59
#include <sys/stat.h>

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
void show_edit_number(callable_obj_t *call);

static GtkWidget *toolbar_;

static guint transferButtonConnId_; //The button toggled signal connection ID
static guint recordButtonConnId_; //The button toggled signal connection ID

static GtkAction * pickUpAction_;
static GtkWidget * pickUpWidget_;
static GtkAction * newCallAction_;
static GtkWidget * newCallWidget_;
static GtkAction * hangUpAction_;
static GtkWidget * hangUpWidget_;
static GtkWidget * holdMenu_;
static GtkWidget * holdToolbar_;
static GtkWidget * offHoldToolbar_;
static GtkWidget * transferToolbar_;
static GtkAction * copyAction_;
static GtkAction * pasteAction_;
static GtkAction * recordAction_;
static GtkWidget * recordWidget_;
static GtkAction * voicemailAction_;
static GtkWidget * voicemailToolbar_;
static GtkWidget * imToolbar_;
static GtkAction * imAction_;
static GtkWidget * playRecordWidget_;
static GtkWidget * stopRecordWidget_;

static GtkWidget * editable_num_;
static GtkWidget * edit_dialog_;
90

91
92
enum {
    CALLTREE_CALLS, CALLTREE_HISTORY, CALLTREE_CONTACTS
93
};
94

95
96
static void
remove_from_toolbar(GtkWidget *widget)
97
{
98
99
    /* We must ensure that a widget is a child of a container
     * before removing it. */
100
    if (gtk_widget_get_parent(widget) == toolbar_)
101
        gtk_container_remove(GTK_CONTAINER(toolbar_), widget);
102
103
}

104
void
105
update_actions()
106
{
107
108
109
110
111
112
113
114
115
116
117
    DEBUG("UIManager: Update action");

    gtk_action_set_sensitive(newCallAction_, TRUE);
    gtk_action_set_sensitive(pickUpAction_, FALSE);
    gtk_action_set_sensitive(hangUpAction_, FALSE);
    gtk_action_set_sensitive(imAction_, FALSE);

    g_object_ref(hangUpWidget_);
    g_object_ref(recordWidget_);
    g_object_ref(holdToolbar_);
    g_object_ref(offHoldToolbar_);
118

Rafaël Carré's avatar
Rafaël Carré committed
119
    if (addrbook)
120
121
122
123
124
125
126
127
128
129
130
131
        g_object_ref(contactButton_);

    g_object_ref(historyButton_);
    g_object_ref(transferToolbar_);
    g_object_ref(voicemailToolbar_);
    g_object_ref(imToolbar_);

    remove_from_toolbar(hangUpWidget_);
    remove_from_toolbar(recordWidget_);
    remove_from_toolbar(transferToolbar_);
    remove_from_toolbar(historyButton_);

Rafaël Carré's avatar
Rafaël Carré committed
132
    if (addrbook)
133
134
135
136
137
138
139
140
141
142
143
144
        remove_from_toolbar(contactButton_);

    remove_from_toolbar(voicemailToolbar_);
    remove_from_toolbar(imToolbar_);

    gtk_widget_set_sensitive(holdMenu_, FALSE);
    gtk_widget_set_sensitive(holdToolbar_, FALSE);
    gtk_widget_set_sensitive(offHoldToolbar_, FALSE);
    gtk_action_set_sensitive(recordAction_, FALSE);
    gtk_widget_set_sensitive(recordWidget_, FALSE);
    gtk_action_set_sensitive(copyAction_, FALSE);

Rafaël Carré's avatar
Rafaël Carré committed
145
    if (addrbook)
146
147
148
        gtk_widget_set_sensitive(contactButton_, FALSE);

    gtk_widget_set_sensitive(historyButton_, FALSE);
149

Rafaël Carré's avatar
Rafaël Carré committed
150
    if (addrbook)
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
        gtk_widget_set_tooltip_text(contactButton_, _("No address book selected"));

    remove_from_toolbar(holdToolbar_);
    remove_from_toolbar(offHoldToolbar_);
    remove_from_toolbar(newCallWidget_);
    remove_from_toolbar(pickUpWidget_);

    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(newCallWidget_), 0);

    remove_from_toolbar(playRecordWidget_);
    remove_from_toolbar(stopRecordWidget_);

    if (eel_gconf_get_integer(HISTORY_ENABLED)) {
        gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(historyButton_), -1);
        gtk_widget_set_sensitive(historyButton_, TRUE);
166
167
168
    }

    // If addressbook support has been enabled and all addressbooks are loaded, display the icon
Rafaël Carré's avatar
Cleanup    
Rafaël Carré committed
169
170
    if (addrbook && addrbook->is_ready() && addressbook_config_load_parameters()->enable) {
        gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(contactButton_), -1);
171

Rafaël Carré's avatar
Cleanup    
Rafaël Carré committed
172
173
174
175
        // Make the icon clickable only if at least one address book is active
        if (addrbook->is_active()) {
            gtk_widget_set_sensitive(contactButton_, TRUE);
            gtk_widget_set_tooltip_text(contactButton_, _("Address book"));
176
177
178
        }
    }

Tristan Matthews's avatar
Tristan Matthews committed
179
180
    callable_obj_t * selectedCall = calltab_get_selected_call(active_calltree_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
181

182
    gboolean instant_messaging_enabled = TRUE;
183

184
185
    if (eel_gconf_key_exists(INSTANT_MESSAGING_ENABLED))
        instant_messaging_enabled = eel_gconf_get_integer(INSTANT_MESSAGING_ENABLED);
186

187
188
    if (selectedCall) {
        DEBUG("UIManager: Update actions for call %s", selectedCall->_callID);
189

190
191
192
        // update icon in systray
        show_status_hangup_icon();

193
        gtk_action_set_sensitive(copyAction_, TRUE);
194
195
196

        switch (selectedCall->_state) {
            case CALL_STATE_INCOMING:
197
                DEBUG("UIManager: Call State Incoming");
198
                // Make the button toolbar clickable
199
200
                gtk_action_set_sensitive(pickUpAction_, TRUE);
                gtk_action_set_sensitive(hangUpAction_, TRUE);
201
                // Replace the dial button with the hangup button
202
203
204
205
206
207
                g_object_ref(newCallWidget_);
                gtk_container_remove(GTK_CONTAINER(toolbar_), newCallWidget_);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(pickUpWidget_),
                                   0);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_),
                                   1);
208
209
                break;
            case CALL_STATE_HOLD:
210
211
212
213
214
                DEBUG("UIManager: Call State Hold");
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_widget_set_sensitive(holdMenu_, TRUE);
                gtk_widget_set_sensitive(offHoldToolbar_, TRUE);
                gtk_widget_set_sensitive(newCallWidget_, TRUE);
215

216
                // Replace the hold button with the off-hold button
217
218
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), 1);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(offHoldToolbar_), 2);
219
220

                if (instant_messaging_enabled) {
221
222
                    gtk_action_set_sensitive(imAction_, TRUE);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), 3);
223
224
                }

225
226
                break;
            case CALL_STATE_RINGING:
227
228
229
230
                DEBUG("UIManager: Call State Ringing");
                gtk_action_set_sensitive(pickUpAction_, TRUE);
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), 1);
231
232
                break;
            case CALL_STATE_DIALING:
233
                DEBUG("UIManager: Call State Dialing");
234
                gtk_action_set_sensitive(pickUpAction_, TRUE);
235

Tristan Matthews's avatar
Tristan Matthews committed
236
                if (active_calltree_tab == current_calls_tab)
237
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
238

239
240
241
                g_object_ref(newCallWidget_);
                gtk_container_remove(GTK_CONTAINER(toolbar_), newCallWidget_);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(pickUpWidget_), 0);
242

Tristan Matthews's avatar
Tristan Matthews committed
243
                if (active_calltree_tab == current_calls_tab)
244
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), 1);
Tristan Matthews's avatar
Tristan Matthews committed
245
                else if (active_calltree_tab == history_tab) {
246
                    if (selectedCall->_recordfile && strlen(selectedCall->_recordfile) > 0) {
247
                        if (selectedCall->_record_is_playing)
248
                            gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(stopRecordWidget_), 3);
249
                        else
250
                            gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(playRecordWidget_), 3);
251
252
                    }
                }
253

254
                break;
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
            case CALL_STATE_CURRENT: {
                DEBUG("UIManager: Call State Current");
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                int pos = 1;
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), pos++);
                gtk_widget_set_sensitive(holdMenu_, TRUE);
                gtk_widget_set_sensitive(holdToolbar_, TRUE);
                gtk_widget_set_sensitive(transferToolbar_, TRUE);
                gtk_action_set_sensitive(recordAction_, TRUE);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(holdToolbar_), pos++);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(transferToolbar_), pos++);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(recordWidget_), pos++);
                gtk_signal_handler_block(GTK_OBJECT(transferToolbar_), transferButtonConnId_);
                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE);
                gtk_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
                g_signal_handler_block(GTK_OBJECT(recordWidget_), recordButtonConnId_);
                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), FALSE);
                g_signal_handler_unblock(GTK_OBJECT(recordWidget_), recordButtonConnId_);
273
274

                if (instant_messaging_enabled) {
275
276
                    gtk_action_set_sensitive(imAction_, TRUE);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), pos);
277
                }
278

279
                break;
280
            }
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
            case CALL_STATE_RECORD: {
                DEBUG("UIManager: Call State Record");
                int pos = 1;
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), pos++);
                gtk_widget_set_sensitive(holdMenu_, TRUE);
                gtk_widget_set_sensitive(holdToolbar_, TRUE);
                gtk_widget_set_sensitive(transferToolbar_, TRUE);
                gtk_action_set_sensitive(recordAction_, TRUE);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(holdToolbar_), pos++);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(transferToolbar_), pos++);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(recordWidget_), pos++);
                gtk_signal_handler_block(GTK_OBJECT(transferToolbar_), transferButtonConnId_);
                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE);
                gtk_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
                g_signal_handler_block(GTK_OBJECT(recordWidget_), recordButtonConnId_);
                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), TRUE);
                g_signal_handler_unblock(GTK_OBJECT(recordWidget_), recordButtonConnId_);
300
301

                if (instant_messaging_enabled) {
302
303
                    gtk_action_set_sensitive(imAction_, TRUE);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), pos);
304
305
                }

306
                break;
307
            }
308
309
            case CALL_STATE_BUSY:
            case CALL_STATE_FAILURE:
310
311
312
                DEBUG("UIManager: Call State Busy/Failure");
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), 1);
313
                break;
314
315
316
317
318
319
320
321
322
323
            case CALL_STATE_TRANSFER:
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), 1);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(transferToolbar_), 2);
                gtk_signal_handler_block(GTK_OBJECT(transferToolbar_), transferButtonConnId_);
                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE);
                gtk_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_widget_set_sensitive(holdMenu_, TRUE);
                gtk_widget_set_sensitive(holdToolbar_, TRUE);
                gtk_widget_set_sensitive(transferToolbar_, TRUE);
324
325
                break;
            default:
326
                ERROR("UIMAnager: Error: Unknown state in action update!");
327
328
329
330
                break;
        }
    } else if (selectedConf) {

331
332
        DEBUG("UIManager: Update actions for conference");

333
334
335
336
337
        // update icon in systray
        show_status_hangup_icon();

        switch (selectedConf->_state) {

338
            case CONFERENCE_STATE_ACTIVE_ATTACHED:
339
            case CONFERENCE_STATE_ACTIVE_DETACHED:
340
                DEBUG("UIManager: Conference State Active");
341

Tristan Matthews's avatar
Tristan Matthews committed
342
                if (active_calltree_tab == current_calls_tab) {
343
344
345
346
347
348
349
                    int pos = 1;
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
                    gtk_widget_set_sensitive(holdToolbar_, TRUE);
                    gtk_action_set_sensitive(recordAction_, TRUE);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), pos++);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(holdToolbar_), pos++);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(recordWidget_), pos++);
350

351
                    if (instant_messaging_enabled) {
352
353
                        gtk_action_set_sensitive(imAction_, TRUE);
                        gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), pos);
354
                    }
Tristan Matthews's avatar
Tristan Matthews committed
355
                } else if (active_calltree_tab == history_tab) {
356
                    if (selectedConf->_recordfile && strlen(selectedConf->_recordfile) > 0) {
357
358
                        if (selectedConf->_record_is_playing)
                            gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(stopRecordWidget_), 3);
359
                        else
360
                            gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(playRecordWidget_), 3);
361
                    }
362
                }
363

364
                break;
365
            case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
366
367
368
369
370
371
372
373
374
            case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: {
                int pos = 1;
                DEBUG("UIManager: Conference State Record");
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_widget_set_sensitive(holdToolbar_, TRUE);
                gtk_action_set_sensitive(recordAction_, TRUE);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), pos++);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(holdToolbar_), pos++);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(recordWidget_), pos++);
375

376
                if (instant_messaging_enabled) {
377
378
                    gtk_action_set_sensitive(imAction_, TRUE);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), pos);
379
                }
380

381
                break;
382
            }
383
            case CONFERENCE_STATE_HOLD:
384
385
386
387
388
389
390
391
392
            case CONFERENCE_STATE_HOLD_RECORD: {
                DEBUG("UIManager: Conference State Hold");
                int pos = 1;
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_widget_set_sensitive(offHoldToolbar_, TRUE);
                gtk_action_set_sensitive(recordAction_, TRUE);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), pos++);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(offHoldToolbar_), pos++);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(recordWidget_), pos++);
393

394
                if (instant_messaging_enabled) {
395
396
                    gtk_action_set_sensitive(imAction_, TRUE);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), pos);
397
                }
398

399
                break;
400
            }
401
            default:
402
                WARN("UIManager: Error: Should not happen in action update!");
403
404
                break;
        }
405
    } else {
406
407
408
409
        // update icon in systray
        hide_status_hangup_icon();

        if (account_list_get_size() > 0 && current_account_has_mailbox()) {
410
            gtk_toolbar_insert(GTK_TOOLBAR(toolbar_),
411
                               GTK_TOOL_ITEM(voicemailToolbar_), -2);
412
413
414
            update_voicemail_status();
        }
    }
415
416
}

417
void
418
update_voicemail_status()
419
{
420
    gchar *messages = g_markup_printf_escaped(_("Voicemail(%i)"),
421
                      current_account_get_message_number());
422
423
424

    if (current_account_has_new_message())
        gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(voicemailToolbar_),
425
                                      "mail-message-new");
426
427
428
    else
        gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(voicemailToolbar_),
                                      "mail-read");
429

430
431
    gtk_tool_button_set_label(GTK_TOOL_BUTTON(voicemailToolbar_), messages);
    g_free(messages);
432
433
}

434
static void
435
volume_bar_cb(GtkToggleAction *togglemenuitem, gpointer user_data UNUSED)
436
{
437
    gboolean toggled = gtk_toggle_action_get_active(togglemenuitem);
438
439
440
441

    if (toggled == SHOW_VOLUME)
        return;

442
    main_window_volume_controls(toggled);
443
444

    if (toggled || SHOW_VOLUME)
445
        eel_gconf_set_integer(SHOW_VOLUME_CONTROLS, toggled);
446
447
}

448
static void
449
dialpad_bar_cb(GtkToggleAction *togglemenuitem, gpointer user_data UNUSED)
450
{
451
452
    gboolean toggled = gtk_toggle_action_get_active(togglemenuitem);
    gboolean conf_dialpad = eel_gconf_get_boolean(CONF_SHOW_DIALPAD);
453
454
455
456

    if (toggled == conf_dialpad)
        return;

457
    main_window_dialpad(toggled);
458
459

    if (toggled || conf_dialpad)
460
        eel_gconf_set_boolean(CONF_SHOW_DIALPAD, toggled);
461
462
}

463
static void
464
help_contents_cb(GtkAction *action UNUSED)
465
{
466
    GError *error = NULL;
467

468
    gnome_help_display("sflphone.xml", NULL, &error);
469
470

    if (error != NULL) {
471
472
        g_warning("%s", error->message);
        g_error_free(error);
473
    }
474
475
}

476
static void
477
help_about(void * foo UNUSED)
478
{
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
    gchar
    *authors[] = {
        "Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>",
        "Jean-Philippe Barrette-LaPierre",
        "Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>",
        "Julien Bonjean <julien.bonjean@savoirfairelinux.com>",
        "Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>",
        "Laurielle Lea",
        "Yun Liu <yun.liu@savoirfairelinux.com>",
        "Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>",
        "Yan Morin <yan.morin@savoirfairelinux.com>",
        "Jérôme Oufella <jerome.oufella@savoirfairelinux.com>",
        "Julien Plissonneau Duquene <julien.plissonneau.duquene@savoirfairelinux.com>",
        "Alexandre Savard <alexandre.savard@savoirfairelinux.com>", NULL
    };
    gchar *artists[] = { "Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>",
                         "Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>", NULL
                       };

498
    gtk_show_about_dialog(GTK_WINDOW(get_main_window()), "artists", artists,
499
500
501
502
503
                          "authors", authors, "comments",
                          _("SFLphone is a VoIP client compatible with SIP and IAX2 protocols."),
                          "copyright", "Copyright © 2004-2011 Savoir-faire Linux Inc.", "name",
                          PACKAGE, "title", _("About SFLphone"), "version", VERSION, "website",
                          "http://www.sflphone.org", NULL);
504
505
506
507
508

}

/* ----------------------------------------------------------------- */

509
static void
510
call_new_call(void * foo UNUSED)
511
{
512
    DEBUG("UIManager: New call button pressed");
513
    sflphone_new_call();
514
515
}

516
static void
517
call_quit(void * foo UNUSED)
518
{
519
    sflphone_quit();
520
521
}

522
static void
523
call_minimize(void * foo UNUSED)
524
{
525
526
527
528
529
    if (eel_gconf_get_integer(SHOW_STATUSICON)) {
        gtk_widget_hide(get_main_window());
        set_minimized(TRUE);
    } else
        sflphone_quit();
530
531
}

532
static void
533
switch_account(GtkWidget* item, gpointer data UNUSED)
534
{
535
536
537
    account_t* acc = g_object_get_data(G_OBJECT(item), "account");
    DEBUG("%s" , acc->accountID);
    account_list_set_current(acc);
538
    status_bar_display_account();
539
540
}

541
static void
542
call_hold(void* foo UNUSED)
543
{
Tristan Matthews's avatar
Tristan Matthews committed
544
545
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab);
546

547
    DEBUG("UIManager: Hold button pressed");
548

549
    if (selectedCall) {
550
        if (selectedCall->_state == CALL_STATE_HOLD)
551
            sflphone_off_hold();
552
        else
553
554
555
            sflphone_on_hold();
    } else if (selectedConf) {
        switch (selectedConf->_state) {
556
            case CONFERENCE_STATE_HOLD:
557
                selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED;
558
                dbus_unhold_conference(selectedConf);
559
560
561
                break;
            case CONFERENCE_STATE_HOLD_RECORD:
                selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD;
562
                dbus_unhold_conference(selectedConf);
563
                break;
564

565
            case CONFERENCE_STATE_ACTIVE_ATTACHED:
566
            case CONFERENCE_STATE_ACTIVE_DETACHED:
567
                selectedConf->_state = CONFERENCE_STATE_HOLD;
568
                dbus_hold_conference(selectedConf);
569
570
571
                break;
            case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
            case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD:
572
573
574
                selectedConf->_state = CONFERENCE_STATE_HOLD_RECORD;
                dbus_hold_conference(selectedConf);
                break;
575
576
577
578
            default:
                break;
        }
    }
579
580
}

581
static void
582
call_im(void* foo UNUSED)
Jonas Fonseca's avatar
im    
Jonas Fonseca committed
583
{
Tristan Matthews's avatar
Tristan Matthews committed
584
585
    callable_obj_t *selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t *selectedConf = calltab_get_selected_conf(current_calls_tab);
586

Tristan Matthews's avatar
Tristan Matthews committed
587
    if (calltab_get_selected_type(current_calls_tab) == A_CALL) {
588
589
590
591
        if (selectedCall) {
            if (!selectedCall->_im_widget)
                selectedCall->_im_widget = im_widget_display(selectedCall->_callID);
        } else
592
            WARN("Sorry. Instant messaging is not allowed outside a call\n");
593
    } else {
594
595
596
597
        if (selectedConf) {
            if (!selectedConf->_im_widget)
                selectedConf->_im_widget = im_widget_display(selectedConf->_confID);
        } else
598
            WARN("Sorry. Instant messaging is not allowed outside a call\n");
599
    }
Jonas Fonseca's avatar
im    
Jonas Fonseca committed
600
601
}

602
static void
603
conference_hold(void* foo UNUSED)
604
{
Tristan Matthews's avatar
Tristan Matthews committed
605
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab);
606

607
    DEBUG("UIManager: Hold button pressed for conference");
608

609
    if (selectedConf == NULL) {
610
        ERROR("UIManager: No conference selected");
611
        return;
612
    }
613

614
    switch (selectedConf->_state) {
615
        case CONFERENCE_STATE_HOLD:
616
            selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED;
617
            dbus_unhold_conference(selectedConf);
618
619
620
            break;
        case CONFERENCE_STATE_HOLD_RECORD:
            selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD;
621
            dbus_unhold_conference(selectedConf);
622
            break;
623
        case CONFERENCE_STATE_ACTIVE_ATTACHED:
624
        case CONFERENCE_STATE_ACTIVE_DETACHED:
625
            selectedConf->_state = CONFERENCE_STATE_HOLD;
626
            dbus_hold_conference(selectedConf);
627
628
629
630
            break;
        case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
        case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD:
            selectedConf->_state = CONFERENCE_STATE_HOLD_RECORD;
631
            dbus_hold_conference(selectedConf);
632
633
634
        default:
            break;
    }
635
636
}

637
static void
638
call_pick_up(void * foo UNUSED)
639
{
640
    DEBUG("UIManager: Pick up");
641

Tristan Matthews's avatar
Tristan Matthews committed
642
    if (calllist_get_size(current_calls_tab) > 0) {
643
        sflphone_pick_up();
Tristan Matthews's avatar
Tristan Matthews committed
644
645
    } else if (calllist_get_size(active_calltree_tab) > 0) {
        callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree_tab);
646

647
        if (selectedCall) {
648
            callable_obj_t *new_call = create_new_call(CALL, CALL_STATE_DIALING, "", "", "",
649
                                       selectedCall->_peer_number);
Tristan Matthews's avatar
Tristan Matthews committed
650
651
            calllist_add_call(current_calls_tab, new_call);
            calltree_add_call(current_calls_tab, new_call, NULL);
652
            sflphone_place_call(new_call);
Tristan Matthews's avatar
Tristan Matthews committed
653
            calltree_display(current_calls_tab);
654
655
        } else {
            sflphone_new_call();
Tristan Matthews's avatar
Tristan Matthews committed
656
            calltree_display(current_calls_tab);
657
658
659
        }
    } else {
        sflphone_new_call();
Tristan Matthews's avatar
Tristan Matthews committed
660
        calltree_display(current_calls_tab);
661
    }
662
663
}

664
static void
665
call_hang_up(void)
666
{
667
    DEBUG("UIManager: Hang up button pressed(call)");
668
669
670
671
    /*
     * [#3020]	Restore the record toggle button
     *			We set it to FALSE, as when we hang up a call, the recording is stopped.
     */
672

673
    sflphone_hang_up();
674
675
}

676
static void
677
conference_hang_up(void)
678
{
679
    DEBUG("UIManager: Hang up button pressed(conference)");
Tristan Matthews's avatar
Tristan Matthews committed
680
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab);
681

682
    if (selectedConf)
683
        dbus_hang_up_conference(selectedConf);
684
685
}

686
static void
687
call_record(void)
688
{
689
    DEBUG("UIManager: Record button pressed");
690
    sflphone_rec_call();
691
692
}

693
static void
694
start_playback_record_cb(void)
695
{
696
    DEBUG("UIManager: Start playback button pressed");
697

Tristan Matthews's avatar
Tristan Matthews committed
698
699
    callable_obj_t *selectedCall = calltab_get_selected_call(history_tab);
    conference_obj_t *selectedConf = calltab_get_selected_conf(history_tab);
700

701
    if (selectedCall == NULL && selectedConf == NULL) {
702
        ERROR("UIManager: Error: No selected object in playback record callback");
703
        return;
704
705
    }

706
707
708
    if (selectedCall && selectedConf) {
        ERROR("UIManager: Error: Two selected object in playback record callback");
        return;
Alexandre Savard's avatar
Alexandre Savard committed
709
710
    }

711
712
713
    if (selectedCall) {
        DEBUG("UIManager: Start selected call file playback %s", selectedCall->_recordfile);
        selectedCall->_record_is_playing = dbus_start_recorded_file_playback(selectedCall->_recordfile);
714
    } else if (selectedConf) {
715
716
        DEBUG("UIMAnager: Start selected conf file playback %s", selectedConf->_recordfile);
        selectedConf->_record_is_playing = dbus_start_recorded_file_playback(selectedConf->_recordfile);
717
718
719
720
721
722
723
724
725
726
    }

    update_actions();
}

static void
stop_playback_record_cb(void)
{
    DEBUG("UIManager: Stop playback button pressed");

Tristan Matthews's avatar
Tristan Matthews committed
727
728
    callable_obj_t *selectedCall = calltab_get_selected_call(history_tab);
    conference_obj_t *selectedConf = calltab_get_selected_conf(history_tab);
729

730
    if (selectedCall && selectedConf) {
731
        ERROR("UIManager: Error: Two selected object in history treeview");
732
        return;
733
734
    }

735
    if (selectedCall == NULL && selectedConf == NULL) {
736
        ERROR("UIManager: Error: No selected object in history treeview");
737
        return;
738
739
    }

740
741
    if (selectedCall) {
        if (selectedCall->_recordfile == NULL) {
Alexandre Savard's avatar
Alexandre Savard committed
742
            ERROR("UIManager: Error: Record file is NULL");
743
            return;
Alexandre Savard's avatar
Alexandre Savard committed
744
        }
745

746
747
748
        dbus_stop_recorded_file_playback(selectedCall->_recordfile);
        DEBUG("UIManager: Stop selected call file playback %s", selectedCall->_recordfile);
        selectedCall->_record_is_playing = FALSE;
749
    } else if (selectedConf) {
750
        if (selectedConf->_recordfile == NULL) {
Alexandre Savard's avatar
Alexandre Savard committed
751
            ERROR("UIManager: Error: Record file is NULL");
752
753
            return;
        }
754

755
        dbus_stop_recorded_file_playback(selectedConf->_recordfile);
756
757
        DEBUG("UIMAnager: Start selected call file playback: %s", selectedConf->_recordfile);
        selectedConf->_record_is_playing = FALSE;
758
759
760
    }

    update_actions();
761
762
}

763
static void
764
call_configuration_assistant(void * foo UNUSED)
765
{
766
    build_wizard();
767
768
}

769
static void
770
remove_from_history(void * foo UNUSED)
771
{
Tristan Matthews's avatar
Tristan Matthews committed
772
    callable_obj_t* call = calltab_get_selected_call(history_tab);
773

774
    DEBUG("UIManager: Remove the call from the history");
775

776
777
    if (call == NULL) {
        ERROR("UIManager: Error: Call is NULL");
778
        return;
779
    }
780

781
    calllist_remove_from_history(call);
782
783
}

784
static void
785
call_back(void * foo UNUSED)
786
{
Tristan Matthews's avatar
Tristan Matthews committed
787
    callable_obj_t *selected_call = calltab_get_selected_call(active_calltree_tab);
788

789
    DEBUG("UIManager: Call back");
790

791
792
793
    if (selected_call == NULL) {
        ERROR("UIManager: Error: No selected call");
        return;
794
    }
795

796
    callable_obj_t *new_call = create_new_call(CALL, CALL_STATE_DIALING, "",
797
798
                               "", selected_call->_peer_name,
                               selected_call->_peer_number);
799

Tristan Matthews's avatar
Tristan Matthews committed
800
801
    calllist_add_call(current_calls_tab, new_call);
    calltree_add_call(current_calls_tab, new_call, NULL);
802
    sflphone_place_call(new_call);
Tristan Matthews's avatar
Tristan Matthews committed
803
    calltree_display(current_calls_tab);
804
805
}

806
static void
807
edit_preferences(void * foo UNUSED)
808
{
809
    show_preferences_dialog();
810
811
}

812
static void
813
edit_accounts(void * foo UNUSED)
814
{
815
    show_account_list_config_dialog();
816
817
818
}

// The menu Edit/Copy should copy the current selected call's number
819
static void
820
edit_copy(void * foo UNUSED)
821
{
822
    GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
Tristan Matthews's avatar
Tristan Matthews committed
823
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
824

825
    DEBUG("UIManager: Edit/Copy");
826

827
    if (selectedCall == NULL) {
828
        ERROR("UIManager: Error: No selected call", selectedCall);
829
        return;
830
    }
831

832
833
    DEBUG("UIManager: Clipboard number: %s\n", selectedCall->_peer_number);
    gtk_clipboard_set_text(clip, selectedCall->_peer_number,
834
                           strlen(selectedCall->_peer_number));
835
836
837
}

// The menu Edit/Paste should paste the clipboard into the current selected call
838
static void
839
edit_paste(void * foo UNUSED)
840
{
Tristan Matthews's avatar