uimanager.c 61.5 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
 */

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

41
#include <uimanager.h>
42
#include <statusicon.h>
Jonas Fonseca's avatar
im    
Jonas Fonseca committed
43
#include <widget/imwidget.h>
Julien Bonjean's avatar
Julien Bonjean committed
44
#include <eel-gconf-extensions.h>
45
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 "config/addressbook-config.h"
53

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

57
58
#include <sys/stat.h>

59
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
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_;
89

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

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

103
void
104
update_actions()
105
{
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    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_);
    if (abookfactory_is_addressbook_loaded())
        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_);

    if (abookfactory_is_addressbook_loaded())
        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);

    if (abookfactory_is_addressbook_loaded())
        gtk_widget_set_sensitive(contactButton_, FALSE);

    gtk_widget_set_sensitive(historyButton_, FALSE);
    if (abookfactory_is_addressbook_loaded())
        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);
163
164
165
    }

    // If addressbook support has been enabled and all addressbooks are loaded, display the icon
166
    if (abookfactory_is_addressbook_loaded()) {
167
        AddrBookFactory *bookFactory = abookfactory_get_factory();
168
        AddressBook_Config *addressbook_config;
169
170
        addressbook_config_load_parameters(&addressbook_config);

171
        if (addressbook_config->enable && bookFactory->addrbook->is_ready()) {
172
            gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(contactButton_), -1);
173
174
175

            // Make the icon clickable only if at least one address book is active
            if (bookFactory->addrbook->is_active()) {
176
177
                gtk_widget_set_sensitive(contactButton_, TRUE);
                gtk_widget_set_tooltip_text(contactButton_, _("Address book"));
178
            }
179
180
181
        }
    }

182
183
    callable_obj_t * selectedCall = calltab_get_selected_call(active_calltree);
    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);
184

185
    gboolean instant_messaging_enabled = TRUE;
186

187
188
    if (eel_gconf_key_exists(INSTANT_MESSAGING_ENABLED))
        instant_messaging_enabled = eel_gconf_get_integer(INSTANT_MESSAGING_ENABLED);
189

190
191
    if (selectedCall) {
        DEBUG("UIManager: Update actions for call %s", selectedCall->_callID);
192

193
194
195
        // update icon in systray
        show_status_hangup_icon();

196
        gtk_action_set_sensitive(copyAction_, TRUE);
197
198
199

        switch (selectedCall->_state) {
            case CALL_STATE_INCOMING:
200
                DEBUG("UIManager: Call State Incoming");
201
                // Make the button toolbar clickable
202
203
                gtk_action_set_sensitive(pickUpAction_, TRUE);
                gtk_action_set_sensitive(hangUpAction_, TRUE);
204
                // Replace the dial button with the hangup button
205
206
207
208
209
210
                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);
211
212
                break;
            case CALL_STATE_HOLD:
213
214
215
216
217
                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);
218

219
                // Replace the hold button with the off-hold button
220
221
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), 1);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(offHoldToolbar_), 2);
222
223

                if (instant_messaging_enabled) {
224
225
                    gtk_action_set_sensitive(imAction_, TRUE);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), 3);
226
227
                }

228
229
                break;
            case CALL_STATE_RINGING:
230
231
232
233
                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);
234
235
                break;
            case CALL_STATE_DIALING:
236
                DEBUG("UIManager: Call State Dialing");
237
                gtk_action_set_sensitive(pickUpAction_, TRUE);
238
239

                if (active_calltree == current_calls)
240
                    gtk_action_set_sensitive(hangUpAction_, TRUE);
241

242
243
244
                g_object_ref(newCallWidget_);
                gtk_container_remove(GTK_CONTAINER(toolbar_), newCallWidget_);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(pickUpWidget_), 0);
245
246

                if (active_calltree == current_calls)
247
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), 1);
248
                else if (active_calltree == history) {
249
                    if (selectedCall->_recordfile &&(g_strcmp0(selectedCall->_recordfile, "") != 0)) {
250
                        if (selectedCall->_record_is_playing)
251
                            gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(stopRecordWidget_), 3);
252
                        else
253
                            gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(playRecordWidget_), 3);
254
255
                    }
                }
256
                break;
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
            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_);
275
276

                if (instant_messaging_enabled) {
277
278
                    gtk_action_set_sensitive(imAction_, TRUE);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), pos);
279
                }
280
                break;
281
            }
282

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
            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_);
301
302

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

307
                break;
308
            }
309
310
            case CALL_STATE_BUSY:
            case CALL_STATE_FAILURE:
311
312
313
                DEBUG("UIManager: Call State Busy/Failure");
                gtk_action_set_sensitive(hangUpAction_, TRUE);
                gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(hangUpWidget_), 1);
314
                break;
315
316
317
318
319
320
321
322
323
324
            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);
325
326
                break;
            default:
327
                ERROR("UIMAnager: Error: Unknown state in action update!");
328
329
330
331
                break;
        }
    } else if (selectedConf) {

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

334
335
336
337
338
339
340
        // update icon in systray
        show_status_hangup_icon();

        switch (selectedConf->_state) {

            case CONFERENCE_STATE_ACTIVE_ATACHED:
            case CONFERENCE_STATE_ACTIVE_DETACHED:
341
342
343
344
345
346
347
348
349
                DEBUG("UIManager: Conference State Active");
                if (active_calltree == current_calls) {
                    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
                    if (instant_messaging_enabled) {
351
352
                        gtk_action_set_sensitive(imAction_, TRUE);
                        gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), pos);
353
                    }
354
355
356
357
358
                }
                else if (active_calltree == history) {
                    if (selectedConf->_recordfile &&(g_strcmp0(selectedConf->_recordfile, "") != 0)) {
                        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
                break;
364
            case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
365
366
367
368
369
370
371
372
373
            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++);
374
                if (instant_messaging_enabled) {
375
376
                    gtk_action_set_sensitive(imAction_, TRUE);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), pos);
377
                }
378
                break;
379
            }
380
            case CONFERENCE_STATE_HOLD:
381
382
383
384
385
386
387
388
389
            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++);
390
                if (instant_messaging_enabled) {
391
392
                    gtk_action_set_sensitive(imAction_, TRUE);
                    gtk_toolbar_insert(GTK_TOOLBAR(toolbar_), GTK_TOOL_ITEM(imToolbar_), pos);
393
                }
394
                break;
395
            }
396
            default:
397
                WARN("UIManager: Error: Should not happen in action update!");
398
399
                break;
        }
400
    } else {
401
402
403
404
        // update icon in systray
        hide_status_hangup_icon();

        if (account_list_get_size() > 0 && current_account_has_mailbox()) {
405
406
            gtk_toolbar_insert(GTK_TOOLBAR(toolbar_),
                                GTK_TOOL_ITEM(voicemailToolbar_), -2);
407
408
409
            update_voicemail_status();
        }
    }
410
411
}

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

    if (current_account_has_new_message())
        gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(voicemailToolbar_),
                                       "mail-message-new");
    else
        gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(voicemailToolbar_),
                                      "mail-read");
    gtk_tool_button_set_label(GTK_TOOL_BUTTON(voicemailToolbar_), messages);
    g_free(messages);
426
427
}

428
static void
429
volume_bar_cb(GtkToggleAction *togglemenuitem, gpointer user_data UNUSED)
430
{
431
    gboolean toggled = gtk_toggle_action_get_active(togglemenuitem);
432
433
434
435

    if (toggled == SHOW_VOLUME)
        return;

436
    main_window_volume_controls(toggled);
437
438

    if (toggled || SHOW_VOLUME)
439
        eel_gconf_set_integer(SHOW_VOLUME_CONTROLS, toggled);
440
441
}

442
static void
443
dialpad_bar_cb(GtkToggleAction *togglemenuitem, gpointer user_data UNUSED)
444
{
445
446
    gboolean toggled = gtk_toggle_action_get_active(togglemenuitem);
    gboolean conf_dialpad = eel_gconf_get_boolean(CONF_SHOW_DIALPAD);
447
448
449
450

    if (toggled == conf_dialpad)
        return;

451
    main_window_dialpad(toggled);
452
453

    if (toggled || conf_dialpad)
454
        eel_gconf_set_boolean(CONF_SHOW_DIALPAD, toggled);
455
456
}

457
static void
458
help_contents_cb(GtkAction *action UNUSED)
459
{
460
    GError *error = NULL;
461

462
    gnome_help_display("sflphone.xml", NULL, &error);
463
464

    if (error != NULL) {
465
466
        g_warning("%s", error->message);
        g_error_free(error);
467
    }
468
469
}

470
static void
471
help_about(void * foo UNUSED)
472
{
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
    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
                       };

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

}

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

503
static void
504
call_new_call(void * foo UNUSED)
505
{
506
    DEBUG("UIManager: New call button pressed");
507
    sflphone_new_call();
508
509
}

510
static void
511
call_quit(void * foo UNUSED)
512
{
513
    sflphone_quit();
514
515
}

516
static void
517
call_minimize(void * foo UNUSED)
518
{
519
520
521
522
523
    if (eel_gconf_get_integer(SHOW_STATUSICON)) {
        gtk_widget_hide(get_main_window());
        set_minimized(TRUE);
    } else
        sflphone_quit();
524
525
}

526
static void
527
switch_account(GtkWidget* item, gpointer data UNUSED)
528
{
529
530
531
    account_t* acc = g_object_get_data(G_OBJECT(item), "account");
    DEBUG("%s" , acc->accountID);
    account_list_set_current(acc);
532
    status_bar_display_account();
533
534
}

535
static void
536
call_hold(void* foo UNUSED)
537
{
538
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
539
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls);
540

541
    DEBUG("UIManager: Hold button pressed");
542

543
    if (selectedCall) {
544
        if (selectedCall->_state == CALL_STATE_HOLD)
545
            sflphone_off_hold();
546
        else
547
548
549
            sflphone_on_hold();
    } else if (selectedConf) {
        switch (selectedConf->_state) {
550
            case CONFERENCE_STATE_HOLD:
551
                selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATACHED;
552
                sflphone_conference_off_hold(selectedConf);
553
554
555
                break;
            case CONFERENCE_STATE_HOLD_RECORD:
                selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD;
556
                sflphone_conference_off_hold(selectedConf);
557
                break;
558
559

            case CONFERENCE_STATE_ACTIVE_ATACHED:
560
            case CONFERENCE_STATE_ACTIVE_DETACHED:
561
                selectedConf->_state = CONFERENCE_STATE_HOLD;
562
                sflphone_conference_on_hold(selectedConf);
563
564
565
566
                break;
            case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
            case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD:
              selectedConf->_state = CONFERENCE_STATE_HOLD_RECORD;
567
              sflphone_conference_on_hold(selectedConf);
568
              break;
569
570
571
572
            default:
                break;
        }
    }
573
574
}

575
static void
576
call_im(void* foo UNUSED)
Jonas Fonseca's avatar
im    
Jonas Fonseca committed
577
{
578
    callable_obj_t *selectedCall = calltab_get_selected_call(current_calls);
579
    conference_obj_t *selectedConf = calltab_get_selected_conf(current_calls);
580

581
582
583
584
585
    if (calltab_get_selected_type(current_calls) == A_CALL) {
        if (selectedCall)
            im_widget_display((IMWidget **) (&selectedCall->_im_widget), NULL, selectedCall->_callID, NULL);
        else
            WARN("Sorry. Instant messaging is not allowed outside a call\n");
586
    } else {
587
588
589
590
        if (selectedConf)
            im_widget_display((IMWidget **) (&selectedConf->_im_widget), NULL, selectedConf->_confID, NULL);
        else
            WARN("Sorry. Instant messaging is not allowed outside a call\n");
591
    }
Jonas Fonseca's avatar
im    
Jonas Fonseca committed
592
593
}

594
static void
595
conference_hold(void* foo UNUSED)
596
{
597
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls);
598

599
    DEBUG("UIManager: Hold button pressed for conference");
600

601
    if (selectedConf == NULL) {
602
        ERROR("UIManager: No conference selected");
603
        return;
604
    }
605

606
    switch (selectedConf->_state) {
607
        case CONFERENCE_STATE_HOLD:
608
            selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATACHED;
609
            sflphone_conference_off_hold(selectedConf);
610
611
612
            break;
        case CONFERENCE_STATE_HOLD_RECORD:
            selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD;
613
            sflphone_conference_off_hold(selectedConf);
614
            break;
615
        case CONFERENCE_STATE_ACTIVE_ATACHED:
616
        case CONFERENCE_STATE_ACTIVE_DETACHED:
617
            selectedConf->_state = CONFERENCE_STATE_HOLD;
618
            sflphone_conference_on_hold(selectedConf);
619
620
621
622
623
            break;
        case CONFERENCE_STATE_ACTIVE_ATTACHED_RECORD:
        case CONFERENCE_STATE_ACTIVE_DETACHED_RECORD:
            selectedConf->_state = CONFERENCE_STATE_HOLD_RECORD;
            sflphone_conference_on_hold(selectedConf);
624
625
626
        default:
            break;
    }
627
628
}

629
static void
630
call_pick_up(void * foo UNUSED)
631
{
632
    DEBUG("UIManager: Pick up");
633

634
    if (calllist_get_size(current_calls) > 0) {
635
        sflphone_pick_up();
636
637
    } else if (calllist_get_size(active_calltree) > 0) {
        callable_obj_t *selectedCall = calltab_get_selected_call(active_calltree);
638

639
        if (selectedCall) {
640
641
642
643
644
645
            callable_obj_t *new_call = create_new_call(CALL, CALL_STATE_DIALING, "", "", "",
                                                       selectedCall->_peer_number);
            calllist_add_call(current_calls, new_call);
            calltree_add_call(current_calls, new_call, NULL);
            sflphone_place_call(new_call);
            calltree_display(current_calls);
646
647
        } else {
            sflphone_new_call();
648
            calltree_display(current_calls);
649
650
651
        }
    } else {
        sflphone_new_call();
652
        calltree_display(current_calls);
653
    }
654
655
}

656
static void
657
call_hang_up(void)
658
{
659
    DEBUG("UIManager: Hang up button pressed(call)");
660
661
662
663
    /*
     * [#3020]	Restore the record toggle button
     *			We set it to FALSE, as when we hang up a call, the recording is stopped.
     */
664

665
    sflphone_hang_up();
666
667
}

668
static void
669
conference_hang_up(void)
670
{
671
    DEBUG("UIManager: Hang up button pressed(conference)");
672
673
    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls);
    if (selectedConf)
674
        dbus_hang_up_conference(selectedConf);
675
676
}

677
static void
678
call_record(void)
679
{
680
    DEBUG("UIManager: Record button pressed");
681
    sflphone_rec_call();
682
683
}

684
static void
685
start_playback_record_cb(void)
686
{
687
    DEBUG("UIManager: Start playback button pressed");
688

689
690
    callable_obj_t *selectedCall = calltab_get_selected_call(history);
    conference_obj_t *selectedConf = calltab_get_selected_conf(history);
691

692
    if (selectedCall == NULL && selectedConf == NULL) {
693
        ERROR("UIManager: Error: No selected object in playback record callback");
694
        return;
695
696
    }

697
698
699
    if (selectedCall && selectedConf) {
        ERROR("UIManager: Error: Two selected object in playback record callback");
        return;
Alexandre Savard's avatar
Alexandre Savard committed
700
701
    }

702
703
704
705
706
707
708
    if (selectedCall) {
        DEBUG("UIManager: Start selected call file playback %s", selectedCall->_recordfile);
        selectedCall->_record_is_playing = dbus_start_recorded_file_playback(selectedCall->_recordfile);
    }
    else if (selectedConf) {
        DEBUG("UIMAnager: Start selected conf file playback %s", selectedConf->_recordfile);
        selectedConf->_record_is_playing = dbus_start_recorded_file_playback(selectedConf->_recordfile);
709
710
711
712
713
714
715
716
717
718
    }

    update_actions();
}

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

719
    callable_obj_t *selectedCall = calltab_get_selected_call(history);
720
721
    conference_obj_t *selectedConf = calltab_get_selected_conf(history);

722
    if (selectedCall && selectedConf) {
723
        ERROR("UIManager: Error: Two selected object in history treeview");
724
        return;
725
726
    }

727
    if (selectedCall == NULL && selectedConf == NULL) {
728
        ERROR("UIManager: Error: No selected object in history treeview");
729
        return;
730
731
    }

732
733
    if (selectedCall) {
        if (selectedCall->_recordfile == NULL) {
Alexandre Savard's avatar
Alexandre Savard committed
734
            ERROR("UIManager: Error: Record file is NULL");
735
            return;
Alexandre Savard's avatar
Alexandre Savard committed
736
        }
737
738
739
740
741
742
        dbus_stop_recorded_file_playback(selectedCall->_recordfile);
        DEBUG("UIManager: Stop selected call file playback %s", selectedCall->_recordfile);
        selectedCall->_record_is_playing = FALSE;
    }
    else if (selectedConf) {
        if (selectedConf->_recordfile == NULL) {
Alexandre Savard's avatar
Alexandre Savard committed
743
            ERROR("UIManager: Error: Record file is NULL");
744
745
            return;
        }
746
        dbus_stop_recorded_file_playback(selectedConf->_recordfile);
747
748
        DEBUG("UIMAnager: Start selected call file playback: %s", selectedConf->_recordfile);
        selectedConf->_record_is_playing = FALSE;
749
750
751
    }

    update_actions();
752
753
}

754
static void
755
call_configuration_assistant(void * foo UNUSED)
756
757
{
#if GTK_CHECK_VERSION(2,10,0)
758
    build_wizard();
759
760
761
#endif
}

762
static void
763
remove_from_history(void * foo UNUSED)
764
{
765
    callable_obj_t* call = calltab_get_selected_call(history);
766

767
    DEBUG("UIManager: Remove the call from the history");
768

769
770
    if (call == NULL) {
        ERROR("UIManager: Error: Call is NULL");
771
    	return;
772
    }
773

774
    calllist_remove_from_history(call);
775
776
}

777
static void
778
call_back(void * foo UNUSED)
779
{
780
    callable_obj_t *selected_call = calltab_get_selected_call(active_calltree);
781

782
    DEBUG("UIManager: Call back");
783

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

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

793
794
795
796
    calllist_add_call(current_calls, new_call);
    calltree_add_call(current_calls, new_call, NULL);
    sflphone_place_call(new_call);
    calltree_display(current_calls);
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
816
    GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
817

818
    DEBUG("UIManager: Edit/Copy");
819

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

825
826
827
    DEBUG("UIManager: Clipboard number: %s\n", selectedCall->_peer_number);
    gtk_clipboard_set_text(clip, selectedCall->_peer_number,
                            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
835
836
    GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
    gchar * no = gtk_clipboard_wait_for_text(clip);
837
838
839

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

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

853
                calltree_update_call(current_calls, selectedCall, NULL);
854
855
856
857
858
859
860
861
862
            }
            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();

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

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

872
                calltree_update_call(current_calls, selectedCall, NULL);
873
874
875
            }
            break;
            case CALL_STATE_CURRENT:
876
            case CALL_STATE_RECORD:
877
            default: {
878
879
880
881
                for(unsigned i = 0; i < strlen(no); i++) {
                    gchar * oneNo = g_strndup(&no[i], 1);
                    DEBUG("<%s>", oneNo);
                    dbus_play_dtmf(oneNo);
882

883
                    gchar * temp = g_strconcat(selectedCall->_peer_number, oneNo,
884
                                                NULL);
885
886
887
888
889
                    g_free(selectedCall->_peer_info);
                    selectedCall->_peer_info = get_peer_info(temp, selectedCall->_peer_name);
                    g_free(temp);
                    g_free(oneNo);
                    calltree_update_call(current_calls, selectedCall, NULL);
890
891
892
893
894
895
896
897
                }
            }
            break;
        }
    } else { // There is no current call, create one
        selectedCall = sflphone_new_call();

        gchar * before = selectedCall->_peer_number;