calltree.c 30.7 KB
Newer Older
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
1 2
/*
 *  Copyright (C) 2007 Savoir-Faire Linux inc.
3
 *  Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>
4
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
5
 *
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
6 7
 *  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
8
 *  the Free Software Foundation; either version 3 of the License, or
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
9
 *  (at your option) any later version.
10
 *
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
11 12 13 14
 *  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.
15
 *
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
16 17 18 19 20
 *  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.
 */

21
#include <stdlib.h>
22 23
#include <glib/gprintf.h>

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
24
#include <gtk/gtk.h>
25
#include <actions.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
26 27
#include <calltree.h>
#include <calllist.h>
28
#include <menus.h>
29
#include <dbus.h>
Julien Bonjean's avatar
Julien Bonjean committed
30
#include <contactlist/eds.h>
31
#include "addressbook-config.h"
32

33
GtkWidget   * toolbar;
Emmanuel Milou's avatar
Emmanuel Milou committed
34
GtkToolItem * pickupButton;
35 36 37 38 39
GtkToolItem * callButton;
GtkToolItem * hangupButton;
GtkToolItem * holdButton;
GtkToolItem * transfertButton;
GtkToolItem * unholdButton;
40
// GtkToolItem * historyButton;
41
GtkToolItem * mailboxButton;
alexandresavard's avatar
alexandresavard committed
42
GtkToolItem * recButton;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
43
guint transfertButtonConnId; //The button toggled signal connection ID
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
44

45 46 47 48 49 50 51 52 53 54
void
free_call_t (call_t *c)
{
    g_free (c->callID);
    g_free (c->accountID);
    g_free (c->from);
    g_free (c->to);
    g_free (c);
}

55 56 57
/**
 * Show popup menu
 */
58
  static gboolean
59
popup_menu (GtkWidget *widget,
60
    gpointer   user_data UNUSED)
61 62 63
{
  show_popup_menu(widget, NULL);
  return TRUE;
64
}
Emmanuel Milou's avatar
Emmanuel Milou committed
65

Emmanuel Milou's avatar
Emmanuel Milou committed
66 67 68 69 70 71
  static gboolean
is_inserted( GtkWidget* button )
{
  return ( GTK_WIDGET(button)->parent == GTK_WIDGET( toolbar ) );
}

Emmanuel Milou's avatar
Emmanuel Milou committed
72
  static gboolean
Emmanuel Milou's avatar
Emmanuel Milou committed
73
button_pressed(GtkWidget* widget, GdkEventButton *event, gpointer user_data UNUSED)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
74 75 76
{
  if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
  {
77 78 79 80 81 82 83 84 85 86
    if( active_calltree == current_calls )
    {
      show_popup_menu(widget,  event);
      return TRUE;
    }
    else
    {
      show_popup_menu_history(widget,  event);
      return TRUE;
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
87 88 89
  }
  return FALSE;
}
90
/**
91
 * Make a call
92
 */
93
  static void
94
call_button( GtkWidget *widget UNUSED, gpointer   data UNUSED)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
95
{
96 97 98 99 100 101
  call_t * selectedCall;
  call_t* new_call;
  gchar *to, *from;

  selectedCall = call_get_selected(active_calltree);
  
Emmanuel Milou's avatar
Emmanuel Milou committed
102 103
  if(call_list_get_size(current_calls)>0)
    sflphone_pick_up();
104
  
Emmanuel Milou's avatar
Emmanuel Milou committed
105
  else if(call_list_get_size(active_calltree) > 0){
106 107 108
    if( selectedCall)
    {
      printf("Calling a called num\n");
109

110 111 112 113 114 115 116 117 118 119
      to = g_strdup(call_get_number(selectedCall));
      from = g_strconcat("\"\" <", call_get_number(selectedCall), ">",NULL);

      create_new_call (to, from, CALL_STATE_DIALING, "", &new_call);

      printf("call : from : %s to %s\n", new_call->from, new_call->to);

      call_list_add(current_calls, new_call);
      update_call_tree_add(current_calls, new_call);
      sflphone_place_call(new_call);
120
      switch_tab(current_calls);
121
    }
122 123 124
    else
    {
      sflphone_new_call();
125
      switch_tab(current_calls);
126 127 128 129
    }
  }
  else
  {
Emmanuel Milou's avatar
Emmanuel Milou committed
130
    sflphone_new_call();
131
    switch_tab(current_calls);
132
  }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
133 134
}

135
/**
136
 * Hang up the line
137
 */
138
  static void
139
hang_up( GtkWidget *widget UNUSED, gpointer   data UNUSED)
140
{
Emmanuel Milou's avatar
Emmanuel Milou committed
141
  sflphone_hang_up();
142 143 144
}

/**
145
 * Hold the line
146
 */
147
  static void
148
hold( GtkWidget *widget UNUSED, gpointer   data UNUSED)
149
{
Emmanuel Milou's avatar
Emmanuel Milou committed
150
  sflphone_on_hold();
151 152 153 154 155
}

/**
 * Transfert the line
 */
156
  static void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
157
transfert  (GtkToggleToolButton *toggle_tool_button,
158
    gpointer             user_data UNUSED )
159
{
Emmanuel Milou's avatar
Emmanuel Milou committed
160 161 162 163 164 165 166 167 168
  gboolean up = gtk_toggle_tool_button_get_active(toggle_tool_button);
  if(up)
  {
    sflphone_set_transfert();
  }
  else
  {
    sflphone_unset_transfert();
  }
169 170
}

171 172 173
/**
 * Unhold call
 */
174
  static void
175
unhold( GtkWidget *widget UNUSED, gpointer   data UNUSED)
176
{
Emmanuel Milou's avatar
Emmanuel Milou committed
177
  sflphone_off_hold();
178
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
179

180
  static void
Julien Bonjean's avatar
Julien Bonjean committed
181
show_current_calls_tab(GtkToggleToolButton *toggle_tool_button UNUSED,
182 183 184
    gpointer  user_data UNUSED)
{
  GtkTreeSelection *sel;
185 186 187 188 189 190
  gchar* msg;

  // temporary display in status bar
  msg = g_strdup("Current calls");
  statusbar_push_message( msg , __MSG_ACCOUNT_DEFAULT);
  g_free(msg);
191 192 193 194 195

  active_calltree = current_calls;
  gtk_widget_hide(history->tree);
  gtk_widget_hide(contacts->tree);
  gtk_widget_show(current_calls->tree);
196
  printf("current calls toggle\n");
197 198 199 200 201 202

  sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (active_calltree->view));
  g_signal_emit_by_name(sel, "changed");
  toolbar_update_buttons();
}

Emmanuel Milou's avatar
Emmanuel Milou committed
203
  static void
Julien Bonjean's avatar
Julien Bonjean committed
204
show_history_tab(GtkToggleToolButton *toggle_tool_button UNUSED,
205
    gpointer	user_data UNUSED)
areversat's avatar
areversat committed
206 207
{
	GtkTreeSelection *sel;
208 209 210 211 212 213
  gchar* msg;

  // temporary display in status bar
  msg = g_strdup("History");
  statusbar_push_message( msg , __MSG_ACCOUNT_DEFAULT);
  g_free(msg);
214

215 216 217 218
  active_calltree = history;
  gtk_widget_hide(current_calls->tree);
  gtk_widget_hide(contacts->tree);
  gtk_widget_show(history->tree);
219

areversat's avatar
areversat committed
220 221 222
	sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (active_calltree->view));
	g_signal_emit_by_name(sel, "changed");
	toolbar_update_buttons();
223
	gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(histfilter));
224

Emmanuel Milou's avatar
Emmanuel Milou committed
225 226 227 228 229 230 231
}

    static void 
handler_async_search (GList *hits, gpointer user_data) {

    GtkTreeSelection *sel;
    GList *i;
232 233
    GdkPixbuf *photo = NULL;
    AddressBook_Config *addressbook_config;
234
    call_t *j;
235 236 237

    // Load the parameters
    addressbook_load_parameters (&addressbook_config);
Emmanuel Milou's avatar
Emmanuel Milou committed
238

239 240 241 242 243 244 245 246 247 248
    // freeing calls
    while((j = (call_t *)g_queue_pop_tail (contacts->callQueue)) != NULL)
    {
        free_call_t(j);
    }

    // reset previous results
    reset_call_tree(contacts);
    call_list_reset(contacts);

Emmanuel Milou's avatar
Emmanuel Milou committed
249 250 251 252 253 254
    for (i = hits; i != NULL; i = i->next)
    {
        Hit *entry;
        entry = i->data;
        if (entry)
        {
255
            /* Get the photo */
256 257
            if (addressbook_display (addressbook_config, ADDRESSBOOK_DISPLAY_CONTACT_PHOTO))
                photo = entry->photo;
Emmanuel Milou's avatar
Emmanuel Milou committed
258
            /* Create entry for business phone information */
259 260
            if (addressbook_display (addressbook_config, ADDRESSBOOK_DISPLAY_PHONE_BUSINESS))
                create_new_entry_in_contactlist (entry->name, entry->phone_business, CONTACT_PHONE_BUSINESS, photo);
Emmanuel Milou's avatar
Emmanuel Milou committed
261
            /* Create entry for home phone information */
262 263
            if (addressbook_display (addressbook_config, ADDRESSBOOK_DISPLAY_PHONE_HOME))
                create_new_entry_in_contactlist (entry->name, entry->phone_home, CONTACT_PHONE_HOME, photo);
Emmanuel Milou's avatar
Emmanuel Milou committed
264
            /* Create entry for mobile phone information */
265 266
            if (addressbook_display (addressbook_config, ADDRESSBOOK_DISPLAY_PHONE_MOBILE))
                create_new_entry_in_contactlist (entry->name, entry->phone_mobile, CONTACT_PHONE_MOBILE, photo);
Emmanuel Milou's avatar
Emmanuel Milou committed
267 268 269 270 271 272 273 274 275 276 277 278 279 280
        }
        free_hit(entry);
    }
    g_list_free(hits);

    active_calltree = contacts;
    gtk_widget_hide(current_calls->tree);
    gtk_widget_hide(history->tree);
    gtk_widget_show(contacts->tree);

    sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (active_calltree->view));
    g_signal_emit_by_name(sel, "changed");
    toolbar_update_buttons();
 
281 282 283
}

  static void
Julien Bonjean's avatar
Julien Bonjean committed
284
show_contacts_tab(GtkToggleToolButton *toggle_tool_button UNUSED,
285 286
    gpointer  user_data UNUSED)
{
287 288 289 290 291 292
  gchar* msg;

  // temporary display in status bar
  msg = g_strdup("Contacts");
  statusbar_push_message( msg , __MSG_ACCOUNT_DEFAULT);
  g_free(msg);
Julien Bonjean's avatar
Julien Bonjean committed
293

294
  // do a synchronous search
Emmanuel Milou's avatar
Emmanuel Milou committed
295
  //results = search_sync (gtk_entry_get_text(GTK_ENTRY(filter_entry)), 50);
296

Emmanuel Milou's avatar
Emmanuel Milou committed
297 298
  // do an asynchronous search
   search_async (gtk_entry_get_text (GTK_ENTRY (filter_entry)), 50, &handler_async_search, NULL); 
areversat's avatar
areversat committed
299
}
300

301
void create_new_entry_in_contactlist (gchar *contact_name, gchar *contact_phone, contact_type_t type, GdkPixbuf *photo){
302 303 304
   
    gchar *from;
    call_t *new_call;
305
    GdkPixbuf *pixbuf;
306 307

    /* Check if the information is valid */
308
    if (g_strcasecmp (contact_phone, EMPTY_ENTRY) != 0){
309 310
        from = g_strconcat("\"" , contact_name, "\"<", contact_phone, ">", NULL);
        create_new_call (from, from, CALL_STATE_DIALING, "", &new_call);
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333

        // Attach a pixbuf to a contact
        if (photo) {
            attach_thumbnail (new_call, photo);
        }
        else {
            switch (type) {
                case CONTACT_PHONE_BUSINESS:
                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/face-monkey.svg", NULL);
                    break;
                case CONTACT_PHONE_HOME:
                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/home.svg", NULL);
                    break;
                case CONTACT_PHONE_MOBILE:
                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/users.svg", NULL);
                    break;
                default:
                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/contact_default.svg", NULL);
                    break;
            }
            attach_thumbnail (new_call, pixbuf);
        }

334 335 336 337 338 339
        call_list_add (contacts, new_call);
        update_call_tree_add(contacts, new_call);
    }

}

340
  static void
341
call_mailbox( GtkWidget* widget UNUSED, gpointer data UNUSED)
342
{
Emmanuel Milou's avatar
Emmanuel Milou committed
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
    account_t* current;
    call_t *mailbox_call;
    gchar *to, *from, *account_id;

    current = account_list_get_current ();
    if( current == NULL ) // Should not happens
        return;
  
    to = g_strdup(g_hash_table_lookup(current->properties, ACCOUNT_MAILBOX));
    from = g_markup_printf_escaped(_("\"Voicemail\" <%s>"),  to);
    account_id = g_strdup (current->accountID);
  
    create_new_call (to, from, CALL_STATE_DIALING, account_id, &mailbox_call);
    g_print("TO : %s\n" , mailbox_call->to);
    call_list_add( current_calls , mailbox_call );
    update_call_tree_add( current_calls , mailbox_call );
    update_menus();
    sflphone_place_call( mailbox_call );
    switch_tab(current_calls);
362 363
}

alexandresavard's avatar
alexandresavard committed
364 365 366 367 368


/**
 * Static rec_button
 */
369
static void
alexandresavard's avatar
alexandresavard committed
370 371 372 373 374 375
rec_button( GtkWidget *widget UNUSED, gpointer   data UNUSED)
{
  sflphone_rec_call();
}


376
  void
377
toolbar_update_buttons ()
378
{
Emmanuel Milou's avatar
Emmanuel Milou committed
379 380 381 382 383 384
  gtk_widget_set_sensitive( GTK_WIDGET(callButton),       FALSE);
  gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     FALSE);
  gtk_widget_set_sensitive( GTK_WIDGET(holdButton),       FALSE);
  gtk_widget_set_sensitive( GTK_WIDGET(transfertButton),  FALSE);
  gtk_widget_set_sensitive( GTK_WIDGET(mailboxButton) ,   FALSE);
  gtk_widget_set_sensitive( GTK_WIDGET(unholdButton),     FALSE);
alexandresavard's avatar
alexandresavard committed
385
  gtk_widget_set_sensitive( GTK_WIDGET(recButton),        FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
386 387
  g_object_ref(holdButton);
  g_object_ref(unholdButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
388 389
  if( is_inserted( GTK_WIDGET(holdButton) ) )   gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(holdButton));
  if( is_inserted( GTK_WIDGET(unholdButton) ) )	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(unholdButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
390 391 392
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), holdButton, 3);
  g_object_ref(callButton);
  g_object_ref(pickupButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
393 394
  if( is_inserted( GTK_WIDGET(callButton) ) )	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(callButton));
  if( is_inserted( GTK_WIDGET(pickupButton) ) )	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(pickupButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
395
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), callButton, 0);
alexandresavard's avatar
alexandresavard committed
396
  //gtk_toolbar_insert(GTK_TOOLBAR(toolbar), recButton, 0);
Emmanuel Milou's avatar
Emmanuel Milou committed
397 398 399 400 401 402 403 404 405


  gtk_signal_handler_block(GTK_OBJECT(transfertButton),transfertButtonConnId);
  gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transfertButton), FALSE);
  gtk_signal_handler_unblock(transfertButton, transfertButtonConnId);

  call_t * selectedCall = call_get_selected(active_calltree);
  if (selectedCall)
  {
406
    switch(selectedCall->state)
Emmanuel Milou's avatar
Emmanuel Milou committed
407 408 409 410
    {
      case CALL_STATE_INCOMING:
	gtk_widget_set_sensitive( GTK_WIDGET(pickupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),	TRUE);
411
	g_object_ref(callButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
412 413 414 415 416 417 418
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(callButton));
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), pickupButton, 0);
	break;
      case CALL_STATE_HOLD:
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(unholdButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(callButton),       TRUE);
419 420
	g_object_ref(holdButton);
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(holdButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
421 422 423 424 425 426 427 428 429
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), unholdButton, 3);
	break;
      case CALL_STATE_RINGING:
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(callButton),     TRUE);
	break;
      case CALL_STATE_DIALING:
	if( active_calltree != history )  gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(pickupButton),       TRUE);
Emmanuel Milou's avatar
Emmanuel Milou committed
430 431
	g_object_ref(callButton);
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(callButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
432 433 434 435 436 437 438
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), pickupButton, 0);
	break;
      case CALL_STATE_CURRENT:
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(holdButton),       TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(transfertButton),  TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(callButton),       TRUE);
alexandresavard's avatar
alexandresavard committed
439
        gtk_widget_set_sensitive( GTK_WIDGET(recButton),        TRUE);
Emmanuel Milou's avatar
Emmanuel Milou committed
440 441 442 443
	break;
      case CALL_STATE_BUSY:
      case CALL_STATE_FAILURE:
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
444
	break;
445
      case CALL_STATE_TRANSFERT:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
446
	gtk_signal_handler_block(GTK_OBJECT(transfertButton),transfertButtonConnId);
Emmanuel Milou's avatar
Emmanuel Milou committed
447
	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transfertButton), TRUE);
448
	gtk_signal_handler_unblock(transfertButton, transfertButtonConnId);
Emmanuel Milou's avatar
Emmanuel Milou committed
449 450 451 452 453
	gtk_widget_set_sensitive( GTK_WIDGET(callButton),       TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(holdButton),       TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(transfertButton),  TRUE);
	break;
454 455 456 457 458 459 460
      case CALL_STATE_RECORD:
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(holdButton),       TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(transfertButton),  TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(callButton),       TRUE);
        gtk_widget_set_sensitive( GTK_WIDGET(recButton),        TRUE);
	break;
Emmanuel Milou's avatar
Emmanuel Milou committed
461
      default:
462
	g_warning("Toolbar update - Should not happen!");
Emmanuel Milou's avatar
Emmanuel Milou committed
463 464 465
	break;
    }
  }
466
  else
Emmanuel Milou's avatar
Emmanuel Milou committed
467 468 469 470 471 472 473 474 475 476 477
  {
    if( account_list_get_size() > 0 )
    {
      gtk_widget_set_sensitive( GTK_WIDGET(callButton), TRUE );
      gtk_widget_set_sensitive( GTK_WIDGET(mailboxButton), TRUE );
    }
    else
    {
      gtk_widget_set_sensitive( GTK_WIDGET(callButton), FALSE);
    }
  }
478
}
alexandresavard's avatar
alexandresavard committed
479 480 481



482
/* Call back when the user click on a call in the list */
483 484
  static void
selected(GtkTreeSelection *sel, void* data UNUSED )
485
{
Emmanuel Milou's avatar
Emmanuel Milou committed
486 487 488
  GtkTreeIter  iter;
  GValue val;
  GtkTreeModel *model = (GtkTreeModel*)active_calltree->store;
489

Emmanuel Milou's avatar
Emmanuel Milou committed
490 491
  if (! gtk_tree_selection_get_selected (sel, &model, &iter))
    return;
492

Emmanuel Milou's avatar
Emmanuel Milou committed
493
  val.g_type = 0;
494
  gtk_tree_model_get_value (model, &iter, 2, &val);
495

Emmanuel Milou's avatar
Emmanuel Milou committed
496 497
  call_select(active_calltree, (call_t*) g_value_get_pointer(&val));
  g_value_unset(&val);
498

Emmanuel Milou's avatar
Emmanuel Milou committed
499
  toolbar_update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
500 501
}

502
/* A row is activated when it is double clicked */
503 504 505
void  row_activated(GtkTreeView       *tree_view UNUSED,
    GtkTreePath       *path UNUSED,
    GtkTreeViewColumn *column UNUSED,
506
    void * data UNUSED)
507
{
508 509
  g_print("double click action\n");
  call_t* selectedCall;
510 511
  call_t* new_call;
  gchar *to, *from, *account_id;
512 513
  selectedCall = call_get_selected( active_calltree );

Emmanuel Milou's avatar
Emmanuel Milou committed
514 515
  if (selectedCall)
  {
516 517
    // Get the right event from the right calltree
    if( active_calltree == current_calls )
Emmanuel Milou's avatar
Emmanuel Milou committed
518
    {
519
      switch(selectedCall->state)
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
      {
	case CALL_STATE_INCOMING:
	  dbus_accept(selectedCall);
	  break;
	case CALL_STATE_HOLD:
	  dbus_unhold(selectedCall);
	  break;
	case CALL_STATE_RINGING:
	case CALL_STATE_CURRENT:
	case CALL_STATE_BUSY:
	case CALL_STATE_FAILURE:
	  break;
	case CALL_STATE_DIALING:
	  sflphone_place_call (selectedCall);
	  break;
	default:
536
	  g_warning("Row activated - Should not happen!");
537 538
	  break;
      }
Emmanuel Milou's avatar
Emmanuel Milou committed
539
    }
540
    // if history
541 542
    else
    {
543 544 545 546 547 548 549 550 551
      to = g_strdup(call_get_number(selectedCall));
      from = g_strconcat("\"\" <", call_get_number(selectedCall), ">",NULL);
      account_id = g_strdup (selectedCall->accountID);

      create_new_call (to, from, CALL_STATE_DIALING, account_id, &new_call);

      call_list_add(current_calls, new_call);
      update_call_tree_add(current_calls, new_call);
      sflphone_place_call(new_call);
552
      switch_tab(current_calls);
553 554 555
    }
  }
}
556

557
  GtkWidget *
areversat's avatar
areversat committed
558 559
create_toolbar ()
{
Emmanuel Milou's avatar
Emmanuel Milou committed
560 561 562 563 564 565 566 567 568
  GtkWidget *ret;
  GtkWidget *image;

  ret = gtk_toolbar_new();
  toolbar = ret;

  gtk_toolbar_set_orientation(GTK_TOOLBAR(ret), GTK_ORIENTATION_HORIZONTAL);
  gtk_toolbar_set_style(GTK_TOOLBAR(ret), GTK_TOOLBAR_ICONS);

569 570
  image = gtk_image_new_from_file( ICONS_DIR "/call.svg");
  callButton = gtk_tool_button_new (image, _("Place a call"));
571
#if GTK_CHECK_VERSION(2,12,0)
572
  gtk_widget_set_tooltip_text(GTK_WIDGET(callButton), _("Place a call"));
573
#endif
574 575 576
  g_signal_connect (G_OBJECT (callButton), "clicked",
      G_CALLBACK (call_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(callButton), -1);
577

578 579
  image = gtk_image_new_from_file( ICONS_DIR "/accept.svg");
  pickupButton = gtk_tool_button_new(image, _("Pick up"));
580
#if GTK_CHECK_VERSION(2,12,0)
581
  gtk_widget_set_tooltip_text(GTK_WIDGET(pickupButton), _("Pick up"));
582
#endif
583
  gtk_widget_set_state( GTK_WIDGET(pickupButton), GTK_STATE_INSENSITIVE);
584
  g_signal_connect(G_OBJECT (pickupButton), "clicked",
585 586
      G_CALLBACK (call_button), NULL);
  gtk_widget_show_all(GTK_WIDGET(pickupButton));
587

588 589
  image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg");
  hangupButton = gtk_tool_button_new (image, _("Hang up"));
590
#if GTK_CHECK_VERSION(2,12,0)
591
  gtk_widget_set_tooltip_text(GTK_WIDGET(hangupButton), _("Hang up"));
592
#endif
593 594 595
  gtk_widget_set_state( GTK_WIDGET(hangupButton), GTK_STATE_INSENSITIVE);
  g_signal_connect (G_OBJECT (hangupButton), "clicked",
      G_CALLBACK (hang_up), NULL);
596
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(hangupButton), -1);
597

598 599
  image = gtk_image_new_from_file( ICONS_DIR "/unhold.svg");
  unholdButton = gtk_tool_button_new (image, _("Off Hold"));
600
#if GTK_CHECK_VERSION(2,12,0)
601
  gtk_widget_set_tooltip_text(GTK_WIDGET(unholdButton), _("Off Hold"));
602
#endif
603 604 605 606 607 608 609 610
  gtk_widget_set_state( GTK_WIDGET(unholdButton), GTK_STATE_INSENSITIVE);
  g_signal_connect (G_OBJECT (unholdButton), "clicked",
      G_CALLBACK (unhold), NULL);
  //gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(unholdButton), -1);
  gtk_widget_show_all(GTK_WIDGET(unholdButton));

  image = gtk_image_new_from_file( ICONS_DIR "/hold.svg");
  holdButton =  gtk_tool_button_new (image, _("On Hold"));
611
#if GTK_CHECK_VERSION(2,12,0)
612
  gtk_widget_set_tooltip_text(GTK_WIDGET(holdButton), _("On Hold"));
613
#endif
614 615 616 617 618 619 620 621
  gtk_widget_set_state( GTK_WIDGET(holdButton), GTK_STATE_INSENSITIVE);
  g_signal_connect (G_OBJECT (holdButton), "clicked",
      G_CALLBACK (hold), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(holdButton), -1);

  image = gtk_image_new_from_file( ICONS_DIR "/transfert.svg");
  transfertButton = gtk_toggle_tool_button_new ();
  gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(transfertButton), image);
622
#if GTK_CHECK_VERSION(2,12,0)
623
  gtk_widget_set_tooltip_text(GTK_WIDGET(transfertButton), _("Transfer"));
624
#endif
625 626 627 628
  gtk_tool_button_set_label(GTK_TOOL_BUTTON(transfertButton), _("Transfer"));
  gtk_widget_set_state( GTK_WIDGET(transfertButton), GTK_STATE_INSENSITIVE);
  transfertButtonConnId = g_signal_connect (G_OBJECT (transfertButton), "toggled",
      G_CALLBACK (transfert), NULL);
629
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(transfertButton), -1);
630 631

  image = gtk_image_new_from_file( ICONS_DIR "/history2.svg");
632
  historyButton = gtk_tool_button_new(image, _("History"));
633
#if GTK_CHECK_VERSION(2,12,0)
634
  gtk_widget_set_tooltip_text(GTK_WIDGET(historyButton), _("History"));
635
#endif
636
  g_signal_connect (G_OBJECT (historyButton), "clicked",
Julien Bonjean's avatar
Julien Bonjean committed
637
      G_CALLBACK (show_history_tab), NULL);
638
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(historyButton), -1);
639 640
  active_calltree = current_calls;

641
  image = gtk_image_new_from_file( ICONS_DIR "/addressbook.svg");
642
  contactButton = gtk_tool_button_new(image, _("Contacts"));
643 644 645
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(contactButton), _("Contacts"));
#endif
646
  g_signal_connect (G_OBJECT (contactButton), "clicked",
Julien Bonjean's avatar
Julien Bonjean committed
647
      G_CALLBACK (show_contacts_tab), NULL);
648 649
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(contactButton), -1);

650
  image = gtk_image_new_from_file( ICONS_DIR "/mailbox.svg");
Emmanuel Milou's avatar
Emmanuel Milou committed
651
  mailboxButton = gtk_tool_button_new( image , _("Voicemail"));
652 653
  gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mailboxButton), image);
  if( account_list_get_size() ==0 ) gtk_widget_set_state( GTK_WIDGET(mailboxButton), GTK_STATE_INSENSITIVE );
654
#if GTK_CHECK_VERSION(2,12,0)
Emmanuel Milou's avatar
Emmanuel Milou committed
655
  gtk_widget_set_tooltip_text(GTK_WIDGET(mailboxButton), _("Voicemail"));
656
#endif
657 658 659
  g_signal_connect (G_OBJECT (mailboxButton), "clicked",
      G_CALLBACK (call_mailbox), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(mailboxButton), -1);
660

661
  recButton = gtk_tool_button_new_from_stock (GTK_STOCK_MEDIA_RECORD);
alexandresavard's avatar
alexandresavard committed
662 663 664
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(recButton), _("Record a call"));
#endif
665
  gtk_widget_set_state( GTK_WIDGET(recButton), GTK_STATE_INSENSITIVE);
alexandresavard's avatar
alexandresavard committed
666 667 668 669 670
  g_signal_connect (G_OBJECT (recButton), "clicked",
      G_CALLBACK (rec_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(recButton), -1);


671
  return ret;
672

673
}
674
static gboolean
675
on_key_released (GtkWidget   *widget UNUSED,
676
                GdkEventKey *event,
677
                gpointer     user_data UNUSED)
678 679
{
  // If a modifier key is pressed, it's a shortcut, pass along
680
  if(event->state & GDK_CONTROL_MASK ||
681 682 683 684 685 686 687 688 689 690 691 692 693 694
     event->state & GDK_MOD1_MASK    ||
     event->keyval == 60             || // <
     event->keyval == 62             || // >
     event->keyval == 34             || // "
     event->keyval == 65361          || // left arrow
     event->keyval == 65363          || // right arrow
     event->keyval >= 65470          || // F-keys
     event->keyval == 32                // space
     )
    return FALSE;
  else
    sflphone_keypad(event->keyval, event->string);
  return TRUE;
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
695

696 697 698 699 700 701 702 703 704
/**
 * Reset call tree
 */
  void
reset_call_tree (calltab_t* tab)
{
  gtk_list_store_clear (tab->store);
}

705
  void
areversat's avatar
areversat committed
706 707
create_call_tree (calltab_t* tab)
{
Emmanuel Milou's avatar
Emmanuel Milou committed
708 709 710 711
  GtkWidget *sw;
  GtkCellRenderer *rend;
  GtkTreeViewColumn *col;
  GtkTreeSelection *sel;
712

713
  tab->tree = gtk_vbox_new(FALSE, 10);
714

Emmanuel Milou's avatar
Emmanuel Milou committed
715
  gtk_container_set_border_width (GTK_CONTAINER (tab->tree), 0);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
716

Emmanuel Milou's avatar
Emmanuel Milou committed
717 718 719
  sw = gtk_scrolled_window_new( NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
720
  g_signal_connect (G_OBJECT ( sw ), "key-release-event",G_CALLBACK (on_key_released), NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
721

722 723
  tab->store = gtk_list_store_new (3,
      GDK_TYPE_PIXBUF,// Icon
Emmanuel Milou's avatar
Emmanuel Milou committed
724 725 726
      G_TYPE_STRING,  // Description
      G_TYPE_POINTER  // Pointer to the Object
      );
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
727

Emmanuel Milou's avatar
Emmanuel Milou committed
728
  tab->view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(tab->store));
729
  gtk_tree_view_set_enable_search( GTK_TREE_VIEW(tab->view), FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
730 731 732 733
  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(tab->view), FALSE);
  g_signal_connect (G_OBJECT (tab->view), "row-activated",
      G_CALLBACK (row_activated),
      NULL);
734

735
  // Connect the popup menu
Emmanuel Milou's avatar
Emmanuel Milou committed
736
  g_signal_connect (G_OBJECT (tab->view), "popup-menu",
737
      G_CALLBACK (popup_menu),
Emmanuel Milou's avatar
Emmanuel Milou committed
738 739
      NULL);
  g_signal_connect (G_OBJECT (tab->view), "button-press-event",
740
      G_CALLBACK (button_pressed),
Emmanuel Milou's avatar
Emmanuel Milou committed
741 742
      NULL);

743

Emmanuel Milou's avatar
Emmanuel Milou committed
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767
  rend = gtk_cell_renderer_pixbuf_new();
  col = gtk_tree_view_column_new_with_attributes ("Icon",
      rend,
      "pixbuf", 0,
      NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW(tab->view), col);

  rend = gtk_cell_renderer_text_new();
  col = gtk_tree_view_column_new_with_attributes ("Description",
      rend,
      "markup", 1,
      NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW(tab->view), col);

  g_object_unref(G_OBJECT(tab->store));
  gtk_container_add(GTK_CONTAINER(sw), tab->view);

  sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (tab->view));
  g_signal_connect (G_OBJECT (sel), "changed",
      G_CALLBACK (selected),
      NULL);

  gtk_box_pack_start(GTK_BOX(tab->tree), sw, TRUE, TRUE, 0);

768
  gtk_widget_show(tab->tree);
Emmanuel Milou's avatar
Emmanuel Milou committed
769 770 771

  //toolbar_update_buttons();

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
772
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
773

774
  void
775
update_call_tree_remove (calltab_t* tab, call_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
776
{
Emmanuel Milou's avatar
Emmanuel Milou committed
777 778 779 780 781 782 783 784 785 786 787 788
  GtkTreeIter iter;
  GValue val;
  call_t * iterCall;
  GtkListStore* store = tab->store;

  int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
  int i;
  for( i = 0; i < nbChild; i++)
  {
    if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i))
    {
      val.g_type = 0;
789
      gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
Emmanuel Milou's avatar
Emmanuel Milou committed
790 791 792 793 794 795 796 797 798 799 800 801 802 803

      iterCall = (call_t*) g_value_get_pointer(&val);
      g_value_unset(&val);

      if(iterCall == c)
      {
	gtk_list_store_remove(store, &iter);
      }
    }
  }
  call_t * selectedCall = call_get_selected(tab);
  if(selectedCall == c)
    call_select(tab, NULL);
  toolbar_update_buttons();
804
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
805

806
  void
807
update_call_tree (calltab_t* tab, call_t * c)
808
{
809 810
    g_print("update call tree\n");
  GdkPixbuf *pixbuf=NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
811 812 813 814 815 816 817 818 819 820 821 822
  GtkTreeIter iter;
  GValue val;
  call_t * iterCall;
  GtkListStore* store = tab->store;

  int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
  int i;
  for( i = 0; i < nbChild; i++)
  {
    if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i))
    {
      val.g_type = 0;
823
      gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
Emmanuel Milou's avatar
Emmanuel Milou committed
824 825 826 827 828 829 830 831

      iterCall = (call_t*) g_value_get_pointer(&val);
      g_value_unset(&val);

      if(iterCall == c)
      {
	// Existing call in the list
	gchar * description;
Emmanuel Milou's avatar
Emmanuel Milou committed
832 833
	gchar * date="";
	gchar * duration="";
Emmanuel Milou's avatar
Emmanuel Milou committed
834
	if(c->state == CALL_STATE_TRANSFERT)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
835
	{
836 837 838
	  description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>\n<i>Transfert to:</i> %s",
	      call_get_number(c),
	      call_get_name(c),
Emmanuel Milou's avatar
Emmanuel Milou committed
839 840 841 842
	      c->to);
	}
	else
	{
843
	  description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>",
844
	      call_get_number(c),
845
	      call_get_name(c));
Emmanuel Milou's avatar
Emmanuel Milou committed
846
	}
847

848 849
	if( tab == current_calls )
	{
Emmanuel Milou's avatar
Emmanuel Milou committed
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
	  switch(c->state)
	  {
	    case CALL_STATE_HOLD:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/hold.svg", NULL);
	      break;
	    case CALL_STATE_RINGING:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
	      break;
	    case CALL_STATE_CURRENT:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/current.svg", NULL);
	      break;
	    case CALL_STATE_DIALING:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL);
	      break;
	    case CALL_STATE_FAILURE:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/fail.svg", NULL);
	      break;
	    case CALL_STATE_BUSY:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/busy.svg", NULL);
	      break;
	    case CALL_STATE_TRANSFERT:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/transfert.svg", NULL);
872 873 874
              break;
            case CALL_STATE_RECORD:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/rec_call.svg", NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
875 876
	      break;
	    default:
877
	      g_warning("Update calltree - Should not happen!");
Emmanuel Milou's avatar
Emmanuel Milou committed
878
	  }
879
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
880 881
	else
	{
882 883 884
	  switch(c->history_state)
	  {
	    case OUTGOING:
Emmanuel Milou's avatar
Emmanuel Milou committed
885 886 887 888 889 890
	      g_print("Outgoing state\n");
	      pixbuf = gdk_pixbuf_new_from_file( ICONS_DIR "/outgoing.svg", NULL);
	      break;
	    case INCOMING:
	      g_print("Incoming state\n");
	      pixbuf = gdk_pixbuf_new_from_file( ICONS_DIR "/incoming.svg", NULL);
891 892
	      break;
	    case MISSED:
Emmanuel Milou's avatar
Emmanuel Milou committed
893 894
	      g_print("Missed state\n");
	      pixbuf = gdk_pixbuf_new_from_file( ICONS_DIR "/missed.svg", NULL);
895 896
	      break;
	    default:
897
	      g_print("No history state\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
898
	      break;
899
	  }
900
	  date = timestamp_get_call_date();
Emmanuel Milou's avatar
Emmanuel Milou committed
901
	  duration = process_call_duration(c);
902 903
	  duration = g_strconcat( date , duration , NULL);
	  description = g_strconcat( description , duration, NULL);
904
	}
905 906 907
	//Resize it
	if(pixbuf)
	{
Emmanuel Milou's avatar
Emmanuel Milou committed
908 909 910 911
	  if(gdk_pixbuf_get_width(pixbuf) > 32 || gdk_pixbuf_get_height(pixbuf) > 32)
	  {
	    pixbuf =  gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
	  }
912
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
913 914 915 916
	gtk_list_store_set(store, &iter,
	    0, pixbuf, // Icon
	    1, description, // Description
	    -1);
917 918

	if (pixbuf != NULL)
Emmanuel Milou's avatar
Emmanuel Milou committed
919 920
	  g_object_unref(G_OBJECT(pixbuf));

921
      }
Emmanuel Milou's avatar
Emmanuel Milou committed
922 923
    }