calltree.c 29.4 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

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

225 226 227
}

  static void
Julien Bonjean's avatar
Julien Bonjean committed
228
show_contacts_tab(GtkToggleToolButton *toggle_tool_button UNUSED,
229 230 231
    gpointer  user_data UNUSED)
{
  GtkTreeSelection *sel;
Julien Bonjean's avatar
Julien Bonjean committed
232 233
  GList *results;
  GList *i;
234 235 236 237 238 239 240
  call_t *j;
  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
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
249
  reset_call_tree(contacts);
250
  call_list_reset(contacts);
251

252
  // do a synchronous search
Julien Bonjean's avatar
Julien Bonjean committed
253
  results = search_sync (gtk_entry_get_text(GTK_ENTRY(filter_entry)), 50);
Julien Bonjean's avatar
Julien Bonjean committed
254 255 256 257 258

  for (i = results; i != NULL; i = i->next)
  {
    Hit *entry;
    entry = i->data;
Emmanuel Milou's avatar
Emmanuel Milou committed
259
    if (entry)
Julien Bonjean's avatar
Julien Bonjean committed
260
    {
261
        /* Create entry for business phone information */
262
        create_new_entry_in_contactlist (entry->name, entry->phone_business, CONTACT_PHONE_BUSINESS);
263
        /* Create entry for home phone information */
264
        create_new_entry_in_contactlist (entry->name, entry->phone_home, CONTACT_PHONE_HOME);
265
        /* Create entry for mobile phone information */
266
        create_new_entry_in_contactlist (entry->name, entry->phone_mobile, CONTACT_PHONE_MOBILE);
Julien Bonjean's avatar
Julien Bonjean committed
267
    }
268
    free_hit(entry);
Julien Bonjean's avatar
Julien Bonjean committed
269
  }
270 271
  g_list_free(results);

272
  active_calltree = contacts;
273 274 275 276
  gtk_widget_hide(current_calls->tree);
  gtk_widget_hide(history->tree);
  gtk_widget_show(contacts->tree);

277
  sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (active_calltree->view));
278 279
  g_signal_emit_by_name(sel, "changed");
  toolbar_update_buttons();
areversat's avatar
areversat committed
280
}
281

282
void create_new_entry_in_contactlist (gchar *contact_name, gchar *contact_phone, contact_type_t type){
283 284 285 286 287 288 289 290
   
    gchar *from;
    call_t *new_call;

    /* Check if the information is valid */
    if (strcmp (contact_phone, EMPTY_ENTRY) != 0){
        from = g_strconcat("\"" , contact_name, "\"<", contact_phone, ">", NULL);
        create_new_call (from, from, CALL_STATE_DIALING, "", &new_call);
291
        new_call->contact_type = type;
292 293 294 295 296 297
        call_list_add (contacts, new_call);
        update_call_tree_add(contacts, new_call);
    }

}

298
  static void
299
call_mailbox( GtkWidget* widget UNUSED, gpointer data UNUSED)
300
{
Emmanuel Milou's avatar
Emmanuel Milou committed
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
    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);
320 321
}

alexandresavard's avatar
alexandresavard committed
322 323 324 325 326


/**
 * Static rec_button
 */
327
static void
alexandresavard's avatar
alexandresavard committed
328 329 330 331 332 333
rec_button( GtkWidget *widget UNUSED, gpointer   data UNUSED)
{
  sflphone_rec_call();
}


334
  void
335
toolbar_update_buttons ()
336
{
Emmanuel Milou's avatar
Emmanuel Milou committed
337 338 339 340 341 342
  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
343
  gtk_widget_set_sensitive( GTK_WIDGET(recButton),        FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
344 345
  g_object_ref(holdButton);
  g_object_ref(unholdButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
346 347
  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
348 349 350
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), holdButton, 3);
  g_object_ref(callButton);
  g_object_ref(pickupButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
351 352
  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
353
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), callButton, 0);
alexandresavard's avatar
alexandresavard committed
354
  //gtk_toolbar_insert(GTK_TOOLBAR(toolbar), recButton, 0);
Emmanuel Milou's avatar
Emmanuel Milou committed
355 356 357 358 359 360 361 362 363


  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)
  {
364
    switch(selectedCall->state)
Emmanuel Milou's avatar
Emmanuel Milou committed
365 366 367 368
    {
      case CALL_STATE_INCOMING:
	gtk_widget_set_sensitive( GTK_WIDGET(pickupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),	TRUE);
369
	g_object_ref(callButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
370 371 372 373 374 375 376
	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);
377 378
	g_object_ref(holdButton);
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(holdButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
379 380 381 382 383 384 385 386 387
	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
388 389
	g_object_ref(callButton);
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(callButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
390 391 392 393 394 395 396
	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
397
        gtk_widget_set_sensitive( GTK_WIDGET(recButton),        TRUE);
Emmanuel Milou's avatar
Emmanuel Milou committed
398 399 400 401
	break;
      case CALL_STATE_BUSY:
      case CALL_STATE_FAILURE:
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
402
	break;
403
      case CALL_STATE_TRANSFERT:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
404
	gtk_signal_handler_block(GTK_OBJECT(transfertButton),transfertButtonConnId);
Emmanuel Milou's avatar
Emmanuel Milou committed
405
	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transfertButton), TRUE);
406
	gtk_signal_handler_unblock(transfertButton, transfertButtonConnId);
Emmanuel Milou's avatar
Emmanuel Milou committed
407 408 409 410 411
	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;
412 413 414 415 416 417 418
      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
419
      default:
420
	g_warning("Toolbar update - Should not happen!");
Emmanuel Milou's avatar
Emmanuel Milou committed
421 422 423
	break;
    }
  }
424
  else
Emmanuel Milou's avatar
Emmanuel Milou committed
425 426 427 428 429 430 431 432 433 434 435
  {
    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);
    }
  }
436
}
alexandresavard's avatar
alexandresavard committed
437 438 439



440
/* Call back when the user click on a call in the list */
441 442
  static void
selected(GtkTreeSelection *sel, void* data UNUSED )
443
{
Emmanuel Milou's avatar
Emmanuel Milou committed
444 445 446
  GtkTreeIter  iter;
  GValue val;
  GtkTreeModel *model = (GtkTreeModel*)active_calltree->store;
447

Emmanuel Milou's avatar
Emmanuel Milou committed
448 449
  if (! gtk_tree_selection_get_selected (sel, &model, &iter))
    return;
450

Emmanuel Milou's avatar
Emmanuel Milou committed
451
  val.g_type = 0;
452
  gtk_tree_model_get_value (model, &iter, 2, &val);
453

Emmanuel Milou's avatar
Emmanuel Milou committed
454 455
  call_select(active_calltree, (call_t*) g_value_get_pointer(&val));
  g_value_unset(&val);
456

Emmanuel Milou's avatar
Emmanuel Milou committed
457
  toolbar_update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
458 459
}

460
/* A row is activated when it is double clicked */
461 462 463
void  row_activated(GtkTreeView       *tree_view UNUSED,
    GtkTreePath       *path UNUSED,
    GtkTreeViewColumn *column UNUSED,
464
    void * data UNUSED)
465
{
466 467
  g_print("double click action\n");
  call_t* selectedCall;
468 469
  call_t* new_call;
  gchar *to, *from, *account_id;
470 471
  selectedCall = call_get_selected( active_calltree );

Emmanuel Milou's avatar
Emmanuel Milou committed
472 473
  if (selectedCall)
  {
474 475
    // Get the right event from the right calltree
    if( active_calltree == current_calls )
Emmanuel Milou's avatar
Emmanuel Milou committed
476
    {
477
      switch(selectedCall->state)
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
      {
	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:
494
	  g_warning("Row activated - Should not happen!");
495 496
	  break;
      }
Emmanuel Milou's avatar
Emmanuel Milou committed
497
    }
498
    // if history
499 500
    else
    {
501 502 503 504 505 506 507 508 509
      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);
510
      switch_tab(current_calls);
511 512 513
    }
  }
}
514

515
  GtkWidget *
areversat's avatar
areversat committed
516 517
create_toolbar ()
{
Emmanuel Milou's avatar
Emmanuel Milou committed
518 519 520 521 522 523 524 525 526
  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);

527 528
  image = gtk_image_new_from_file( ICONS_DIR "/call.svg");
  callButton = gtk_tool_button_new (image, _("Place a call"));
529
#if GTK_CHECK_VERSION(2,12,0)
530
  gtk_widget_set_tooltip_text(GTK_WIDGET(callButton), _("Place a call"));
531
#endif
532 533 534
  g_signal_connect (G_OBJECT (callButton), "clicked",
      G_CALLBACK (call_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(callButton), -1);
535

536 537
  image = gtk_image_new_from_file( ICONS_DIR "/accept.svg");
  pickupButton = gtk_tool_button_new(image, _("Pick up"));
538
#if GTK_CHECK_VERSION(2,12,0)
539
  gtk_widget_set_tooltip_text(GTK_WIDGET(pickupButton), _("Pick up"));
540
#endif
541
  gtk_widget_set_state( GTK_WIDGET(pickupButton), GTK_STATE_INSENSITIVE);
542
  g_signal_connect(G_OBJECT (pickupButton), "clicked",
543 544
      G_CALLBACK (call_button), NULL);
  gtk_widget_show_all(GTK_WIDGET(pickupButton));
545

546 547
  image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg");
  hangupButton = gtk_tool_button_new (image, _("Hang up"));
548
#if GTK_CHECK_VERSION(2,12,0)
549
  gtk_widget_set_tooltip_text(GTK_WIDGET(hangupButton), _("Hang up"));
550
#endif
551 552 553
  gtk_widget_set_state( GTK_WIDGET(hangupButton), GTK_STATE_INSENSITIVE);
  g_signal_connect (G_OBJECT (hangupButton), "clicked",
      G_CALLBACK (hang_up), NULL);
554
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(hangupButton), -1);
555

556 557
  image = gtk_image_new_from_file( ICONS_DIR "/unhold.svg");
  unholdButton = gtk_tool_button_new (image, _("Off Hold"));
558
#if GTK_CHECK_VERSION(2,12,0)
559
  gtk_widget_set_tooltip_text(GTK_WIDGET(unholdButton), _("Off Hold"));
560
#endif
561 562 563 564 565 566 567 568
  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"));
569
#if GTK_CHECK_VERSION(2,12,0)
570
  gtk_widget_set_tooltip_text(GTK_WIDGET(holdButton), _("On Hold"));
571
#endif
572 573 574 575 576 577 578 579
  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);
580
#if GTK_CHECK_VERSION(2,12,0)
581
  gtk_widget_set_tooltip_text(GTK_WIDGET(transfertButton), _("Transfer"));
582
#endif
583 584 585 586
  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);
587
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(transfertButton), -1);
588 589

  image = gtk_image_new_from_file( ICONS_DIR "/history2.svg");
590
  historyButton = gtk_tool_button_new(image, _("History"));
591
#if GTK_CHECK_VERSION(2,12,0)
592
  gtk_widget_set_tooltip_text(GTK_WIDGET(historyButton), _("History"));
593
#endif
594
  g_signal_connect (G_OBJECT (historyButton), "clicked",
Julien Bonjean's avatar
Julien Bonjean committed
595
      G_CALLBACK (show_history_tab), NULL);
596
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(historyButton), -1);
597 598
  active_calltree = current_calls;

599
  image = gtk_image_new_from_file( ICONS_DIR "/addressbook.svg");
600
  contactButton = gtk_tool_button_new(image, _("Contacts"));
601 602 603
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(contactButton), _("Contacts"));
#endif
604
  g_signal_connect (G_OBJECT (contactButton), "clicked",
Julien Bonjean's avatar
Julien Bonjean committed
605
      G_CALLBACK (show_contacts_tab), NULL);
606 607
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(contactButton), -1);

608
  image = gtk_image_new_from_file( ICONS_DIR "/mailbox.svg");
Emmanuel Milou's avatar
Emmanuel Milou committed
609
  mailboxButton = gtk_tool_button_new( image , _("Voicemail"));
610 611
  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 );
612
#if GTK_CHECK_VERSION(2,12,0)
Emmanuel Milou's avatar
Emmanuel Milou committed
613
  gtk_widget_set_tooltip_text(GTK_WIDGET(mailboxButton), _("Voicemail"));
614
#endif
615 616 617
  g_signal_connect (G_OBJECT (mailboxButton), "clicked",
      G_CALLBACK (call_mailbox), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(mailboxButton), -1);
618

619
  recButton = gtk_tool_button_new_from_stock (GTK_STOCK_MEDIA_RECORD);
alexandresavard's avatar
alexandresavard committed
620 621 622
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(recButton), _("Record a call"));
#endif
623
  gtk_widget_set_state( GTK_WIDGET(recButton), GTK_STATE_INSENSITIVE);
alexandresavard's avatar
alexandresavard committed
624 625 626 627 628
  g_signal_connect (G_OBJECT (recButton), "clicked",
      G_CALLBACK (rec_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(recButton), -1);


629
  return ret;
630

631
}
632
static gboolean
633
on_key_released (GtkWidget   *widget UNUSED,
634
                GdkEventKey *event,
635
                gpointer     user_data UNUSED)
636 637
{
  // If a modifier key is pressed, it's a shortcut, pass along
638
  if(event->state & GDK_CONTROL_MASK ||
639 640 641 642 643 644 645 646 647 648 649 650 651 652
     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
653

654 655 656 657 658 659 660 661 662
/**
 * Reset call tree
 */
  void
reset_call_tree (calltab_t* tab)
{
  gtk_list_store_clear (tab->store);
}

663
  void
areversat's avatar
areversat committed
664 665
create_call_tree (calltab_t* tab)
{
Emmanuel Milou's avatar
Emmanuel Milou committed
666 667 668 669
  GtkWidget *sw;
  GtkCellRenderer *rend;
  GtkTreeViewColumn *col;
  GtkTreeSelection *sel;
670

671
  tab->tree = gtk_vbox_new(FALSE, 10);
672

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

Emmanuel Milou's avatar
Emmanuel Milou committed
675 676 677
  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);
678
  g_signal_connect (G_OBJECT ( sw ), "key-release-event",G_CALLBACK (on_key_released), NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
679

680 681
  tab->store = gtk_list_store_new (3,
      GDK_TYPE_PIXBUF,// Icon
Emmanuel Milou's avatar
Emmanuel Milou committed
682 683 684
      G_TYPE_STRING,  // Description
      G_TYPE_POINTER  // Pointer to the Object
      );
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
685

Emmanuel Milou's avatar
Emmanuel Milou committed
686
  tab->view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(tab->store));
687
  gtk_tree_view_set_enable_search( GTK_TREE_VIEW(tab->view), FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
688 689 690 691
  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);
692

693
  // Connect the popup menu
Emmanuel Milou's avatar
Emmanuel Milou committed
694
  g_signal_connect (G_OBJECT (tab->view), "popup-menu",
695
      G_CALLBACK (popup_menu),
Emmanuel Milou's avatar
Emmanuel Milou committed
696 697
      NULL);
  g_signal_connect (G_OBJECT (tab->view), "button-press-event",
698
      G_CALLBACK (button_pressed),
Emmanuel Milou's avatar
Emmanuel Milou committed
699 700
      NULL);

701

Emmanuel Milou's avatar
Emmanuel Milou committed
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
  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);

726
  gtk_widget_show(tab->tree);
Emmanuel Milou's avatar
Emmanuel Milou committed
727 728 729

  //toolbar_update_buttons();

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
730
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
731

732
  void
733
update_call_tree_remove (calltab_t* tab, call_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
734
{
Emmanuel Milou's avatar
Emmanuel Milou committed
735 736 737 738 739 740 741 742 743 744 745 746
  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;
747
      gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
Emmanuel Milou's avatar
Emmanuel Milou committed
748 749 750 751 752 753 754 755 756 757 758 759 760 761

      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();
762
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
763

764
  void
765
update_call_tree (calltab_t* tab, call_t * c)
766
{
767 768
    g_print("update call tree\n");
  GdkPixbuf *pixbuf=NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
769 770 771 772 773 774 775 776 777 778 779 780
  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;
781
      gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
Emmanuel Milou's avatar
Emmanuel Milou committed
782 783 784 785 786 787 788 789

      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
790 791
	gchar * date="";
	gchar * duration="";
Emmanuel Milou's avatar
Emmanuel Milou committed
792
	if(c->state == CALL_STATE_TRANSFERT)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
793
	{
794 795 796
	  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
797 798 799 800
	      c->to);
	}
	else
	{
801
	  description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>",
802
	      call_get_number(c),
803
	      call_get_name(c));
Emmanuel Milou's avatar
Emmanuel Milou committed
804
	}
805

806 807
	if( tab == current_calls )
	{
Emmanuel Milou's avatar
Emmanuel Milou committed
808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
	  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);
830 831 832
              break;
            case CALL_STATE_RECORD:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/rec_call.svg", NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
833 834
	      break;
	    default:
835
	      g_warning("Update calltree - Should not happen!");
Emmanuel Milou's avatar
Emmanuel Milou committed
836
	  }
837
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
838 839
	else
	{
840 841 842
	  switch(c->history_state)
	  {
	    case OUTGOING:
Emmanuel Milou's avatar
Emmanuel Milou committed
843 844 845 846 847 848
	      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);
849 850
	      break;
	    case MISSED:
Emmanuel Milou's avatar
Emmanuel Milou committed
851 852
	      g_print("Missed state\n");
	      pixbuf = gdk_pixbuf_new_from_file( ICONS_DIR "/missed.svg", NULL);
853 854
	      break;
	    default:
855
	      g_print("No history state\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
856
	      break;
857
	  }
858
	  date = timestamp_get_call_date();
Emmanuel Milou's avatar
Emmanuel Milou committed
859
	  duration = process_call_duration(c);
860 861
	  duration = g_strconcat( date , duration , NULL);
	  description = g_strconcat( description , duration, NULL);
862
	}
863 864 865
	//Resize it
	if(pixbuf)
	{
Emmanuel Milou's avatar
Emmanuel Milou committed
866 867 868 869
	  if(gdk_pixbuf_get_width(pixbuf) > 32 || gdk_pixbuf_get_height(pixbuf) > 32)
	  {
	    pixbuf =  gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
	  }
870
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
871 872 873 874
	gtk_list_store_set(store, &iter,
	    0, pixbuf, // Icon
	    1, description, // Description
	    -1);
875 876

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

879
      }
Emmanuel Milou's avatar
Emmanuel Milou committed
880 881
    }

882
  }
Emmanuel Milou's avatar
Emmanuel Milou committed
883 884 885
  toolbar_update_buttons();
}

886
  void
Emmanuel Milou's avatar
Emmanuel Milou committed
887 888 889 890 891
update_call_tree_add (calltab_t* tab, call_t * c)
{
  if( tab == history && ( call_list_get_size( tab ) > dbus_get_max_calls() ) )
    return;

892
  GdkPixbuf *pixbuf=NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
893 894 895 896
  GtkTreeIter iter;
  GtkTreeSelection* sel;

  // New call in the list
Emmanuel Milou's avatar
Emmanuel Milou committed
897
  gchar * description;
Emmanuel Milou's avatar
Emmanuel Milou committed
898
  gchar * date="";
Julien Bonjean's avatar