uimanager.c 60.4 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
#ifdef HAVE_CONFIG_H
32
#include "config.h"
33
34
35
#endif

#include "gtk2_wrappers.h"
36
#include "str_utils.h"
37
38
39
40
41
#include "preferencesdialog.h"
#include "logger.h"
#include "dbus/dbus.h"
#include "mainwindow.h"
#include "assistant.h"
42
43
#include <glib.h>
#include <glib/gi18n.h>
44
#include <gtk/gtk.h>
45
#include <string.h>
46

47
48
49
#include "uimanager.h"
#include "statusicon.h"
#include "eel-gconf-extensions.h"
50

51
#include "config/audioconf.h"
52
#include "unused.h"
Julien Bonjean's avatar
Julien Bonjean committed
53
54
#include "uimanager.h"
#include "statusicon.h"
55
56

#include "contacts/addrbookfactory.h"
57
#include "contacts/calltab.h"
58
#include "config/addressbook-config.h"
59

Tristan Matthews's avatar
Tristan Matthews committed
60
61
#include "eel-gconf-extensions.h"

Julien Bonjean's avatar
Julien Bonjean committed
62
#include "accountlist.h"
63
#include "account_schema.h"
Julien Bonjean's avatar
Julien Bonjean committed
64
65
#include "config/accountlistconfigdialog.h"

Emmanuel Lepage's avatar
Emmanuel Lepage committed
66
67
#include "messaging/message_tab.h"

68
69
#include <sys/stat.h>

70
71
#include <sliders.h>

72
73
74
75
void show_edit_number(callable_obj_t *call);

static GtkWidget *toolbar_;

Alexandre Savard's avatar
Alexandre Savard committed
76
77
78
79
// store the signal ID in case we need to
// intercept this signal
static guint transferButtonConnId_;
static guint recordButtonConnId_;
80
81
82
83

static GtkAction * pickUpAction_;
static GtkAction * newCallAction_;
static GtkAction * hangUpAction_;
Alexandre Savard's avatar
Alexandre Savard committed
84
85
86
87
88
89
90
91
92
static GtkAction * copyAction_;
static GtkAction * pasteAction_;
static GtkAction * recordAction_;
static GtkAction * muteAction_;
static GtkAction * voicemailAction_;
static GtkAction * imAction_;

static GtkWidget * pickUpWidget_;
static GtkWidget * newCallWidget_;
93
94
95
96
97
98
static GtkWidget * hangUpWidget_;
static GtkWidget * holdMenu_;
static GtkWidget * holdToolbar_;
static GtkWidget * offHoldToolbar_;
static GtkWidget * transferToolbar_;
static GtkWidget * recordWidget_;
99
static GtkWidget * muteWidget_;
100
101
static GtkWidget * voicemailToolbar_;
static GtkWidget * imToolbar_;
Alexandre Savard's avatar
Alexandre Savard committed
102

103
104
static GtkWidget * editable_num_;
static GtkWidget * edit_dialog_;
105

106
107
// GtkToolItem *separator_;

108
109
static void
remove_from_toolbar(GtkWidget *widget)
110
{
111
112
    /* We must ensure that a widget is a child of a container
     * before removing it. */
113
    if (gtk_widget_get_parent(widget) == toolbar_)
114
        gtk_container_remove(GTK_CONTAINER(toolbar_), widget);
115
116
}

117
static gboolean
118
is_non_empty(const char *str)
Tristan Matthews's avatar
Tristan Matthews committed
119
120
121
122
{
    return str && strlen(str) > 0;
}

123
124
125
126
127
128
129
130
/* Inserts an item in a toolbar at a given position, making sure that the index
 * is valid, that it does not exceed the number of elements */
static void add_to_toolbar(GtkWidget *toolbar, GtkWidget *item, int pos)
{
    g_assert(gtk_toolbar_get_n_items(GTK_TOOLBAR(toolbar)) >= pos);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(item), pos);
}

131
132
133
static void
call_mute(void)
{
134
    DEBUG("Mute call button pressed");
135
136
137
    sflphone_mute_call();
}

Alexandre Savard's avatar
Alexandre Savard committed
138
139

static void
140
141
update_toolbar_for_call(callable_obj_t *selectedCall, gboolean instant_messaging_enabled)
{
Alexandre Savard's avatar
Alexandre Savard committed
142
143
    int pos = 0;

144
    DEBUG("Update actions for call %s", selectedCall->_callID);
Alexandre Savard's avatar
Alexandre Savard committed
145
146
147
148
149
150
151
152
153
154
155
156
157
158

    if(selectedCall == NULL) {
        ERROR("Selected call is NULL while updating toolbar");
        return;
    }

    // update icon in systray
    show_status_hangup_icon();

    gtk_action_set_sensitive(copyAction_, TRUE);

    switch (selectedCall->_state) {
        case CALL_STATE_INCOMING:
        {
159
                DEBUG("Call State Incoming");
Alexandre Savard's avatar
Alexandre Savard committed
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
                // Make the button toolbar clickable
                gtk_action_set_sensitive(pickUpAction_, TRUE);
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_action_set_sensitive(muteAction_, TRUE);
                // Replace the dial button with the hangup button
                g_object_ref(newCallWidget_);
                remove_from_toolbar(newCallWidget_);
                pos = 0;
                add_to_toolbar(toolbar_, pickUpWidget_, pos++);
                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                add_to_toolbar(toolbar_, muteWidget_, pos++);
                break;
        }
        case CALL_STATE_HOLD:
        {
175
                DEBUG("Call State Hold");
Alexandre Savard's avatar
Alexandre Savard committed
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_widget_set_sensitive(holdMenu_, TRUE);
                gtk_widget_set_sensitive(offHoldToolbar_, TRUE);
                gtk_widget_set_sensitive(newCallWidget_, TRUE);

                // Replace the hold button with the off-hold button
                pos = 1;
                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                add_to_toolbar(toolbar_, offHoldToolbar_, pos++);

                if (instant_messaging_enabled) {
                    gtk_action_set_sensitive(imAction_, TRUE);
                    add_to_toolbar(toolbar_, imToolbar_, pos++);
                }

                break;
        }
        case CALL_STATE_RINGING:
        {
195
                DEBUG("Call State Ringing");
Alexandre Savard's avatar
Alexandre Savard committed
196
197
198
199
200
201
202
203
204
                gtk_action_set_sensitive(pickUpAction_, TRUE);
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                pos = 1;
                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                add_to_toolbar(toolbar_, muteWidget_, pos++);
                break;
        }
        case CALL_STATE_DIALING:
        {
205
                DEBUG("Call State Dialing");
Alexandre Savard's avatar
Alexandre Savard committed
206
207
                gtk_action_set_sensitive(pickUpAction_, TRUE);

208
                if (calltab_has_name(active_calltree_tab, CURRENT_CALLS))
Alexandre Savard's avatar
Alexandre Savard committed
209
210
211
212
213
214
215
                    gtk_action_set_sensitive(hangUpAction_, TRUE);

                g_object_ref(newCallWidget_);
                remove_from_toolbar(newCallWidget_);
                pos = 0;
                add_to_toolbar(toolbar_, pickUpWidget_, pos++);

216
                if (calltab_has_name(active_calltree_tab, CURRENT_CALLS)) {
Alexandre Savard's avatar
Alexandre Savard committed
217
                    add_to_toolbar(toolbar_, hangUpWidget_, pos++);
218
                    main_window_hide_playback_scale();
219
                } else if (calltab_has_name(active_calltree_tab, HISTORY)) {
220
                    main_window_show_playback_scale();
221
                    if (is_non_empty(selectedCall->_recordfile))
222
                        main_window_set_playback_scale_sensitive();
223
                    else
224
                        main_window_set_playback_scale_unsensitive();
225
                } else {
226
                    main_window_hide_playback_scale();
Alexandre Savard's avatar
Alexandre Savard committed
227
228
229
230
231
                }
                break;
        }
        case CALL_STATE_CURRENT:
        {
232
                DEBUG("Call State Current");
233
234
235
                g_signal_handler_block(transferToolbar_, transferButtonConnId_);
                g_signal_handler_block(recordWidget_, recordButtonConnId_);

Alexandre Savard's avatar
Alexandre Savard committed
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_action_set_sensitive(recordAction_, TRUE);
                gtk_action_set_sensitive(muteAction_, TRUE);
                gtk_widget_set_sensitive(holdMenu_, TRUE);
                gtk_widget_set_sensitive(holdToolbar_, TRUE);
                gtk_widget_set_sensitive(transferToolbar_, TRUE);
                gtk_widget_set_sensitive(muteWidget_, TRUE);
                if (instant_messaging_enabled)
                    gtk_action_set_sensitive(imAction_, TRUE);

                pos = 1;
                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                add_to_toolbar(toolbar_, holdToolbar_, pos++);
                add_to_toolbar(toolbar_, transferToolbar_, pos++);
                add_to_toolbar(toolbar_, recordWidget_, pos++);
                add_to_toolbar(toolbar_, muteWidget_, pos++);
                if (instant_messaging_enabled)
                    add_to_toolbar(toolbar_, imToolbar_, pos++);

                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), FALSE);
256
                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(recordWidget_), dbus_get_is_recording(selectedCall));
257
258

                g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
Alexandre Savard's avatar
Alexandre Savard committed
259
260
261
                g_signal_handler_unblock(recordWidget_, recordButtonConnId_);
                break;
        }
262

Alexandre Savard's avatar
Alexandre Savard committed
263
264
265
266
        case CALL_STATE_BUSY:
        case CALL_STATE_FAILURE:
        {
                pos = 1;
267
                DEBUG("Call State Busy/Failure");
Alexandre Savard's avatar
Alexandre Savard committed
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                break;
        }
        case CALL_STATE_TRANSFER:
        {
                pos = 1;
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_action_set_sensitive(muteAction_, TRUE);
                gtk_widget_set_sensitive(holdMenu_, TRUE);
                gtk_widget_set_sensitive(holdToolbar_, TRUE);
                gtk_widget_set_sensitive(transferToolbar_, TRUE);
                gtk_widget_set_sensitive(transferToolbar_, TRUE);
                gtk_widget_set_sensitive(muteWidget_, TRUE);

                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                add_to_toolbar(toolbar_, transferToolbar_, pos++);
                g_signal_handler_block(transferToolbar_, transferButtonConnId_);
                gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transferToolbar_), TRUE);
                g_signal_handler_unblock(transferToolbar_, transferButtonConnId_);
                add_to_toolbar(toolbar_, muteWidget_, pos++);
                break;
        }
        default:
292
            ERROR("Unknown state in action update!");
Alexandre Savard's avatar
Alexandre Savard committed
293
294
295
296
297
298
299
300
            break;
    }
}

static void
update_toolbar_for_conference(conference_obj_t * selectedConf, gboolean instant_messaging_enabled) {
    int pos = 0;

301
    DEBUG("Update actions for conference");
Alexandre Savard's avatar
Alexandre Savard committed
302
303
304
305
306
307
308
309

    // update icon in systray
    show_status_hangup_icon();

    switch (selectedConf->_state) {

        case CONFERENCE_STATE_ACTIVE_ATTACHED:
        case CONFERENCE_STATE_ACTIVE_DETACHED:
310
            DEBUG("Conference State Active");
311
            g_signal_handler_block(recordWidget_, recordButtonConnId_);
312
            if (calltab_has_name(active_calltree_tab, CURRENT_CALLS)) {
Alexandre Savard's avatar
Alexandre Savard committed
313
314
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_widget_set_sensitive(holdToolbar_, TRUE);
315
                gtk_widget_set_sensitive(recordWidget_, TRUE);
Alexandre Savard's avatar
Alexandre Savard committed
316
317
318
319
320
321
322
323
324
                pos = 1;
                add_to_toolbar(toolbar_, hangUpWidget_, pos++);
                add_to_toolbar(toolbar_, holdToolbar_, pos++);
                add_to_toolbar(toolbar_, recordWidget_, pos++);

                if (instant_messaging_enabled) {
                    gtk_action_set_sensitive(imAction_, TRUE);
                    add_to_toolbar(toolbar_, imToolbar_, pos);
                }
325
                main_window_hide_playback_scale();
326
            } else if (calltab_has_name(active_calltree_tab, HISTORY)) {
327
                main_window_show_playback_scale();
328
                if (is_non_empty(selectedConf->_recordfile))
329
                    main_window_set_playback_scale_sensitive();
330
                else
331
                    main_window_set_playback_scale_unsensitive();
332
            } else {
333
                main_window_hide_playback_scale();
Alexandre Savard's avatar
Alexandre Savard committed
334
            }
335
            g_signal_handler_unblock(recordWidget_, recordButtonConnId_);
Alexandre Savard's avatar
Alexandre Savard committed
336
337
338
            break;
        case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
        case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD: {
339
            g_signal_handler_block(recordWidget_, recordButtonConnId_);
Alexandre Savard's avatar
Alexandre Savard committed
340
            pos = 1;
341
            DEBUG("Conference State Record");
Alexandre Savard's avatar
Alexandre Savard committed
342
343
            gtk_action_set_sensitive(hangUpAction_, TRUE);
            gtk_widget_set_sensitive(holdToolbar_, TRUE);
344
            gtk_widget_set_sensitive(recordWidget_, TRUE);
Alexandre Savard's avatar
Alexandre Savard committed
345
346
347
348
349
350
351
352
            add_to_toolbar(toolbar_, hangUpWidget_, pos++);
            add_to_toolbar(toolbar_, holdToolbar_, pos++);
            add_to_toolbar(toolbar_, recordWidget_, pos++);

            if (instant_messaging_enabled) {
                gtk_action_set_sensitive(imAction_, TRUE);
                add_to_toolbar(toolbar_, imToolbar_, pos);
            }
353
            g_signal_handler_unblock(recordWidget_, recordButtonConnId_);
Alexandre Savard's avatar
Alexandre Savard committed
354
355
356
357
            break;
        }
        case CONFERENCE_STATE_HOLD:
        case CONFERENCE_STATE_HOLD_RECORD: {
358
            DEBUG("Conference State Hold");
359
            g_signal_handler_block(recordWidget_, recordButtonConnId_);
Alexandre Savard's avatar
Alexandre Savard committed
360
361
362
            pos = 1;
            gtk_action_set_sensitive(hangUpAction_, TRUE);
            gtk_widget_set_sensitive(offHoldToolbar_, TRUE);
363
            gtk_widget_set_sensitive(recordWidget_, TRUE);
Alexandre Savard's avatar
Alexandre Savard committed
364
365
366
367
368
369
370
371
            add_to_toolbar(toolbar_, hangUpWidget_, pos++);
            add_to_toolbar(toolbar_, offHoldToolbar_, pos++);
            add_to_toolbar(toolbar_, recordWidget_, pos++);

            if (instant_messaging_enabled) {
                gtk_action_set_sensitive(imAction_, TRUE);
                add_to_toolbar(toolbar_, imToolbar_, pos);
            }
372
            g_signal_handler_unblock(recordWidget_, recordButtonConnId_);
Alexandre Savard's avatar
Alexandre Savard committed
373
374
375
376

            break;
        }
        default:
377
            WARN("Should not happen in action update!");
Alexandre Savard's avatar
Alexandre Savard committed
378
379
380
381
382
            break;
    }

}

383
void
384
update_actions()
385
{
386
387
388
    gtk_action_set_sensitive(newCallAction_, TRUE);
    gtk_action_set_sensitive(pickUpAction_, FALSE);
    gtk_action_set_sensitive(hangUpAction_, FALSE);
Alexandre Savard's avatar
Alexandre Savard committed
389
390
391
    gtk_action_set_sensitive(recordAction_, FALSE);
    gtk_action_set_sensitive(muteAction_, FALSE);
    gtk_action_set_sensitive(copyAction_, FALSE);
392
393
    gtk_action_set_sensitive(imAction_, FALSE);

Alexandre Savard's avatar
Alexandre Savard committed
394
395
396
397
398
399
400
401
    gtk_widget_set_sensitive(holdMenu_, FALSE);
    gtk_widget_set_sensitive(holdToolbar_, FALSE);
    gtk_widget_set_sensitive(offHoldToolbar_, FALSE);
    gtk_widget_set_sensitive(recordWidget_, FALSE);
    gtk_widget_set_sensitive(muteWidget_, FALSE);
    gtk_widget_set_sensitive(historyButton_, FALSE);

    // Increment the reference counter
402
403
    g_object_ref(hangUpWidget_);
    g_object_ref(recordWidget_);
404
    g_object_ref(muteWidget_);
405
406
407
408
409
410
411
    g_object_ref(holdToolbar_);
    g_object_ref(offHoldToolbar_);
    g_object_ref(historyButton_);
    g_object_ref(transferToolbar_);
    g_object_ref(voicemailToolbar_);
    g_object_ref(imToolbar_);

Alexandre Savard's avatar
Alexandre Savard committed
412
413
414
415
416
417
    if (addrbook)
        g_object_ref(contactButton_);

    // Make sure the toolbar is reinitialized
    // Widget will be added according to the state
    // of the selected call
418
419
    remove_from_toolbar(hangUpWidget_);
    remove_from_toolbar(recordWidget_);
420
    remove_from_toolbar(muteWidget_);
421
422
423
424
425
426
427
428
429
    remove_from_toolbar(transferToolbar_);
    remove_from_toolbar(historyButton_);
    remove_from_toolbar(voicemailToolbar_);
    remove_from_toolbar(imToolbar_);
    remove_from_toolbar(holdToolbar_);
    remove_from_toolbar(offHoldToolbar_);
    remove_from_toolbar(newCallWidget_);
    remove_from_toolbar(pickUpWidget_);

Alexandre Savard's avatar
Alexandre Savard committed
430
431
432
433
434
435
436
437
438
439
    if (addrbook) {
        remove_from_toolbar(contactButton_);
        gtk_widget_set_sensitive(contactButton_, FALSE);
        gtk_widget_set_tooltip_text(contactButton_, _("No address book selected"));
    }

    // New call widget always present
    add_to_toolbar(toolbar_, newCallWidget_, 0);

    // Add the history button and set it to sensitive if enabled
440
    if (eel_gconf_get_integer(HISTORY_ENABLED)) {
441
        add_to_toolbar(toolbar_, historyButton_, -1);
442
        gtk_widget_set_sensitive(historyButton_, TRUE);
443
444
    }

445

446
    // If addressbook support has been enabled and all addressbooks are loaded, display the icon
Rafaël Carré's avatar
Cleanup    
Rafaël Carré committed
447
    if (addrbook && addrbook->is_ready() && addressbook_config_load_parameters()->enable) {
448
        add_to_toolbar(toolbar_, contactButton_, -1);
449

Rafaël Carré's avatar
Cleanup    
Rafaël Carré committed
450
451
452
453
        // 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"));
454
455
456
        }
    }

Tristan Matthews's avatar
Tristan Matthews committed
457
458
    callable_obj_t * selectedCall = calltab_get_selected_call(active_calltree_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree_tab);
459

460
    gboolean instant_messaging_enabled = TRUE;
461

462
463
    if (eel_gconf_key_exists(INSTANT_MESSAGING_ENABLED))
        instant_messaging_enabled = eel_gconf_get_integer(INSTANT_MESSAGING_ENABLED);
464

465
    if (selectedCall) {
Alexandre Savard's avatar
Alexandre Savard committed
466
        update_toolbar_for_call(selectedCall, instant_messaging_enabled);
467
    } else if (selectedConf) {
Alexandre Savard's avatar
Alexandre Savard committed
468
        update_toolbar_for_conference(selectedConf, instant_messaging_enabled);
469
    } else {
470
471
472
473
        // update icon in systray
        hide_status_hangup_icon();

        if (account_list_get_size() > 0 && current_account_has_mailbox()) {
474
            add_to_toolbar(toolbar_, voicemailToolbar_, -1);
475
476
477
            update_voicemail_status();
        }
    }
478
479
}

480
void
481
update_voicemail_status()
482
{
483
    gchar *messages = g_markup_printf_escaped(_("Voicemail(%i)"),
484
                      current_account_get_message_number());
485
486
487

    if (current_account_has_new_message())
        gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(voicemailToolbar_),
488
                                      "mail-message-new");
489
490
491
    else
        gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(voicemailToolbar_),
                                      "mail-read");
492

493
494
    gtk_tool_button_set_label(GTK_TOOL_BUTTON(voicemailToolbar_), messages);
    g_free(messages);
495
496
}

497
static void
498
volume_bar_cb(GtkToggleAction *togglemenuitem, gpointer user_data UNUSED)
499
{
500
    gboolean toggled = gtk_toggle_action_get_active(togglemenuitem);
501
502
503
504

    if (toggled == SHOW_VOLUME)
        return;

505
    main_window_volume_controls(toggled);
506
507

    if (toggled || SHOW_VOLUME)
508
        eel_gconf_set_integer(SHOW_VOLUME_CONTROLS, toggled);
509
510
}

511
static void
512
dialpad_bar_cb(GtkToggleAction *togglemenuitem, gpointer user_data UNUSED)
513
{
514
515
    gboolean toggled = gtk_toggle_action_get_active(togglemenuitem);
    gboolean conf_dialpad = eel_gconf_get_boolean(CONF_SHOW_DIALPAD);
516
517
518
519

    if (toggled == conf_dialpad)
        return;

520
    main_window_dialpad(toggled);
521
522

    if (toggled || conf_dialpad)
523
        eel_gconf_set_boolean(CONF_SHOW_DIALPAD, toggled);
524
525
}

526
static void
527
help_contents_cb(GtkAction *action UNUSED)
528
{
529
    GError *error = NULL;
Tristan Matthews's avatar
Tristan Matthews committed
530
    gtk_show_uri(NULL, "ghelp:sflphone", GDK_CURRENT_TIME, &error);
531
    if (error != NULL) {
532
533
        g_warning("%s", error->message);
        g_error_free(error);
534
    }
535
536
}

537
static void
538
help_about(void * foo UNUSED)
539
{
Tristan Matthews's avatar
Tristan Matthews committed
540
    static const gchar *authors[] = {
541
542
543
544
545
546
547
548
549
550
551
552
553
        "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
    };
Tristan Matthews's avatar
Tristan Matthews committed
554
555
556
557
    static const gchar *artists[] = {
        "Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>",
        "Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>", NULL
    };
558

Tristan Matthews's avatar
Tristan Matthews committed
559
560
561
562
    gtk_show_about_dialog(GTK_WINDOW(get_main_window()),
            "artists", artists,
            "authors", authors,
            "comments", _("SFLphone is a VoIP client compatible with SIP and IAX2 protocols."),
563
            "copyright", "Copyright © 2004-2012 Savoir-faire Linux Inc.",
Tristan Matthews's avatar
Tristan Matthews committed
564
565
566
567
568
            "name", PACKAGE,
            "title", _("About SFLphone"),
            "version", VERSION,
            "website", "http://www.sflphone.org",
            NULL);
569
570
571
572
}

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

573
static void
574
call_new_call(void * foo UNUSED)
575
{
576
    DEBUG("New call button pressed");
577
    sflphone_new_call();
578
579
}

580
static void
581
call_quit(void * foo UNUSED)
582
{
583
    sflphone_quit(FALSE);
584
585
}

586
static void
587
call_minimize(void * foo UNUSED)
588
{
589
590
591
592
    if (eel_gconf_get_integer(SHOW_STATUSICON)) {
        gtk_widget_hide(get_main_window());
        set_minimized(TRUE);
    } else
593
        sflphone_quit(FALSE);
594
595
}

596
static void
597
switch_account(GtkWidget* item, gpointer data UNUSED)
598
{
599
600
601
    account_t* acc = g_object_get_data(G_OBJECT(item), "account");
    DEBUG("%s" , acc->accountID);
    account_list_set_current(acc);
602
    status_bar_display_account();
603
604
}

605
static void
606
call_hold(void* foo UNUSED)
607
{
Tristan Matthews's avatar
Tristan Matthews committed
608
609
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab);
610

611
    DEBUG("Hold button pressed");
612

613
    if (selectedCall) {
614
        if (selectedCall->_state == CALL_STATE_HOLD)
615
            sflphone_off_hold();
616
        else
617
618
619
            sflphone_on_hold();
    } else if (selectedConf) {
        switch (selectedConf->_state) {
620
            case CONFERENCE_STATE_HOLD:
621
                selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED;
622
                dbus_unhold_conference(selectedConf);
623
624
625
                break;
            case CONFERENCE_STATE_HOLD_RECORD:
                selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD;
626
                dbus_unhold_conference(selectedConf);
627
                break;
628

629
            case CONFERENCE_STATE_ACTIVE_ATTACHED:
630
            case CONFERENCE_STATE_ACTIVE_DETACHED:
631
                selectedConf->_state = CONFERENCE_STATE_HOLD;
632
                dbus_hold_conference(selectedConf);
633
634
635
                break;
            case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
            case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD:
636
637
638
                selectedConf->_state = CONFERENCE_STATE_HOLD_RECORD;
                dbus_hold_conference(selectedConf);
                break;
639
640
641
642
            default:
                break;
        }
    }
643
644
}

645
static void
646
call_im(void* foo UNUSED)
Jonas Fonseca's avatar
im    
Jonas Fonseca committed
647
{
Tristan Matthews's avatar
Tristan Matthews committed
648
649
    callable_obj_t *selectedCall = calltab_get_selected_call(current_calls_tab);
    conference_obj_t *selectedConf = calltab_get_selected_conf(current_calls_tab);
650

Tristan Matthews's avatar
Tristan Matthews committed
651
    if (calltab_get_selected_type(current_calls_tab) == A_CALL) {
652
        if (selectedCall) {
653
            create_messaging_tab(selectedCall);
654
        } else
655
            WARN("Sorry. Instant messaging is not allowed outside a call\n");
656
    } else {
657
        if (selectedConf) {
658
            create_messaging_tab_conf(selectedConf);
659
        } else
660
            WARN("Sorry. Instant messaging is not allowed outside a call\n");
661
    }
Jonas Fonseca's avatar
im    
Jonas Fonseca committed
662
663
}

664
static void
665
conference_hold(void* foo UNUSED)
666
{
Tristan Matthews's avatar
Tristan Matthews committed
667
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab);
668

669
    DEBUG("Hold button pressed for conference");
670

671
    if (selectedConf == NULL) {
672
        ERROR("No conference selected");
673
        return;
674
    }
675

676
    switch (selectedConf->_state) {
677
        case CONFERENCE_STATE_HOLD:
678
            selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED;
679
            dbus_unhold_conference(selectedConf);
680
681
682
            break;
        case CONFERENCE_STATE_HOLD_RECORD:
            selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD;
683
            dbus_unhold_conference(selectedConf);
684
            break;
685
        case CONFERENCE_STATE_ACTIVE_ATTACHED:
686
        case CONFERENCE_STATE_ACTIVE_DETACHED:
687
            selectedConf->_state = CONFERENCE_STATE_HOLD;
688
            dbus_hold_conference(selectedConf);
689
690
691
692
            break;
        case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
        case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD:
            selectedConf->_state = CONFERENCE_STATE_HOLD_RECORD;
693
            dbus_hold_conference(selectedConf);
694
695
696
        default:
            break;
    }
697
698
}

699
static void
700
call_pick_up(void * foo UNUSED)
701
{
702
    DEBUG("Pick up");
703

Tristan Matthews's avatar
Tristan Matthews committed
704
    if (calllist_get_size(current_calls_tab) > 0) {
705
        sflphone_pick_up();
Tristan Matthews's avatar
Tristan Matthews committed
706
707
    } else if (calllist_get_size(active_calltree_tab) > 0) {
        callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree_tab);
708

709
        if (selectedCall) {
710
            callable_obj_t *new_call = create_new_call(CALL, CALL_STATE_DIALING, "", "", "",
711
                                       selectedCall->_peer_number);
Tristan Matthews's avatar
Tristan Matthews committed
712
713
            calllist_add_call(current_calls_tab, new_call);
            calltree_add_call(current_calls_tab, new_call, NULL);
714
            sflphone_place_call(new_call);
Tristan Matthews's avatar
Tristan Matthews committed
715
            calltree_display(current_calls_tab);
716
717
        } else {
            sflphone_new_call();
Tristan Matthews's avatar
Tristan Matthews committed
718
            calltree_display(current_calls_tab);
719
720
721
        }
    } else {
        sflphone_new_call();
Tristan Matthews's avatar
Tristan Matthews committed
722
        calltree_display(current_calls_tab);
723
    }
724
725
}

726
static void
727
call_hang_up(void)
728
{
729
    DEBUG("Hang up button pressed(call)");
730
731
732
733
    /*
     * [#3020]	Restore the record toggle button
     *			We set it to FALSE, as when we hang up a call, the recording is stopped.
     */
734

735
    sflphone_hang_up();
736
737
}

738
static void
739
conference_hang_up(void)
740
{
741
    DEBUG("Hang up button pressed(conference)");
Tristan Matthews's avatar
Tristan Matthews committed
742
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls_tab);
743

744
    if (selectedConf)
745
        dbus_hang_up_conference(selectedConf);
746
747
}

748
static void
749
call_record(void)
750
{
751
    DEBUG("Record button pressed");
752
    sflphone_rec_call();
753
754
}

755
static void
756
call_configuration_assistant(void * foo UNUSED)
757
{
758
    build_wizard();
759
760
}

761
static void
762
remove_from_history(void * foo UNUSED)
763
{
Tristan Matthews's avatar
Tristan Matthews committed
764
    callable_obj_t* call = calltab_get_selected_call(history_tab);
765

766
    DEBUG("Remove the call from the history");
767

768
    if (call == NULL) {
769
        ERROR("Call is NULL");
770
        return;
771
    }
772

773
    calllist_remove_from_history(call);
774
    update_actions();
775
776
}

777
static void
778
call_back(void * foo UNUSED)
779
{
Tristan Matthews's avatar
Tristan Matthews committed
780
    callable_obj_t *selected_call = calltab_get_selected_call(active_calltree_tab);
781

782
    DEBUG("Call back");
783

784
    if (selected_call == NULL) {
785
        ERROR("No selected call");
786
        return;
787
    }
788

789
    callable_obj_t *new_call = create_new_call(CALL, CALL_STATE_DIALING, "",
790
                               "", selected_call->_display_name,
791
                               selected_call->_peer_number);
792

Tristan Matthews's avatar
Tristan Matthews committed
793
794
    calllist_add_call(current_calls_tab, new_call);
    calltree_add_call(current_calls_tab, new_call, NULL);
795
    sflphone_place_call(new_call);
Tristan Matthews's avatar
Tristan Matthews committed
796
    calltree_display(current_calls_tab);
797
798
}

799
static void
800
edit_preferences(void * foo UNUSED)
801
{
802
    show_preferences_dialog();
803
804
}

805
static void
806
edit_accounts(void * foo UNUSED)
807
{
808
    show_account_list_config_dialog();
809
810
811
}

// The menu Edit/Copy should copy the current selected call's number
812
static void
813
edit_copy(void * foo UNUSED)
814
{
815
    GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
Tristan Matthews's avatar
Tristan Matthews committed
816
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
817

818
    DEBUG("Edit/Copy");
819

820
    if (selectedCall == NULL) {
821
        ERROR("No selected call", selectedCall);
822
        return;
823
    }
824

825
    DEBUG("Clipboard number: %s\n", selectedCall->_peer_number);
826
    gtk_clipboard_set_text(clip, selectedCall->_peer_number,
827
                           strlen(selectedCall->_peer_number));
828
829
830
}

// The menu Edit/Paste should paste the clipboard into the current selected call
831
static void
832
edit_paste(void * foo UNUSED)
833
{
834
    GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
Tristan Matthews's avatar
Tristan Matthews committed
835
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls_tab);
836
    gchar * no = gtk_clipboard_wait_for_text(clip);
837
838
839

    if (no && selectedCall) {
        switch (selectedCall->_state) {
840
            case CALL_STATE_TRANSFER:
841
            case CALL_STATE_DIALING: {
842
                /* Add the text to the number */
843
844
845
846
                gchar *old = selectedCall->_peer_number;
                DEBUG("TO: %s\n", old);
                selectedCall->_peer_number = g_strconcat(old, no, NULL);
                g_free(old);
847

Tristan Matthews's avatar
Tristan Matthews committed
848
                if (selectedCall->_state == CALL_STATE_DIALING)
849
                    selectedCall->_peer_info = g_strconcat("\"\" <",
850
                                                           selectedCall->_peer_number, ">", NULL);
851

Tristan Matthews's avatar
Tristan Matthews committed
852
                calltree_update_call(current_calls_tab, selectedCall);
853
854
855
856
857
858
859
860
861
            }
            break;
            case CALL_STATE_RINGING:
            case CALL_STATE_INCOMING:
            case CALL_STATE_BUSY:
            case CALL_STATE_FAILURE:
            case CALL_STATE_HOLD: { // Create a new call to hold the new text
                selectedCall = sflphone_new_call();

862
863
864
                gchar *old = selectedCall->_peer_number;
                selectedCall->_peer_number = g_strconcat(old, no, NULL);
                g_free(old);
865
                DEBUG("TO: %s", selectedCall->_peer_number);
866

867
868
                g_free(selectedCall->_peer_info);
                selectedCall->_peer_info = g_strconcat("\"\" <",
869
                                                       selectedCall->_peer_number, ">", NULL);
870

Tristan Matthews's avatar
Tristan Matthews committed
871
                calltree_update_call(current_calls_tab, selectedCall);
872
873
874
875
            }
            break;
            case CALL_STATE_CURRENT:
            default: {