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

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
  call_t * selectedCall = call_get_selected(active_calltree);
97
  call_t* newCall =  g_new0 (call_t, 1);
Emmanuel Milou's avatar
Emmanuel Milou committed
98 99 100 101
  printf("Call button pressed\n");
  if(call_list_get_size(current_calls)>0)
    sflphone_pick_up();
  else if(call_list_get_size(active_calltree) > 0){
102 103 104
    if( selectedCall)
    {
      printf("Calling a called num\n");
105

106 107 108 109
      newCall->to = g_strdup(call_get_number(selectedCall));
      newCall->from = g_strconcat("\"\" <", call_get_number(selectedCall), ">",NULL);
      newCall->state = CALL_STATE_DIALING;
      newCall->callID = g_new0(gchar, 30);
110
      g_sprintf(newCall->callID, "%d", rand());
111 112
      newCall->_start = 0;
      newCall->_stop = 0;
113

114 115 116 117
      printf("call : from : %s to %s\n", newCall->from, newCall->to);
      call_list_add(current_calls, newCall);
      update_call_tree_add(current_calls, newCall);
      sflphone_place_call(newCall);
118
      switch_tab(current_calls);
119
    }
120 121 122
    else
    {
      sflphone_new_call();
123
      switch_tab(current_calls);
124 125 126 127
    }
  }
  else
  {
Emmanuel Milou's avatar
Emmanuel Milou committed
128
    sflphone_new_call();
129
    switch_tab(current_calls);
130
  }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
131 132
}

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

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

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

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

178 179 180 181 182
  static void
toggle_current_calls(GtkToggleToolButton *toggle_tool_button UNUSED,
    gpointer  user_data UNUSED)
{
  GtkTreeSelection *sel;
183 184 185 186 187 188
  gchar* msg;

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

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

  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
201
  static void
202 203
toggle_history(GtkToggleToolButton *toggle_tool_button UNUSED,
    gpointer	user_data UNUSED)
areversat's avatar
areversat committed
204 205
{
	GtkTreeSelection *sel;
206 207 208 209 210 211
  gchar* msg;

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

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

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

223 224 225 226 227 228 229
}

  static void
toggle_contacts(GtkToggleToolButton *toggle_tool_button UNUSED,
    gpointer  user_data UNUSED)
{
  GtkTreeSelection *sel;
Julien Bonjean's avatar
Julien Bonjean committed
230 231
  GList *results;
  GList *i;
232 233 234 235 236 237 238
  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
239

240
  // debug
Julien Bonjean's avatar
Julien Bonjean committed
241 242
  printf("EDS : %s\n",gtk_entry_get_text(GTK_ENTRY(filter_entry)));

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

  // reset previous results
250
  reset_call_tree(contacts);
251
  call_list_reset(contacts);
252

253
  // do a synchronized search
Julien Bonjean's avatar
Julien Bonjean committed
254
  results = search_sync (gtk_entry_get_text(GTK_ENTRY(filter_entry)), 50);
Julien Bonjean's avatar
Julien Bonjean committed
255 256 257 258 259 260 261 262 263 264

  for (i = results; i != NULL; i = i->next)
  {
    Hit *entry;
    entry = i->data;
    if (i->data)
    {
      call_t * call;

      call = g_new0 (call_t, 1);
Julien Bonjean's avatar
Julien Bonjean committed
265
      call->from = g_strconcat("\"" , entry->name, "\"<", entry->phone, ">", NULL);
Julien Bonjean's avatar
Julien Bonjean committed
266 267 268 269 270 271
      call->state = CALL_STATE_RECORD;
      call->history_state = OUTGOING;

      call_list_add (contacts, call);
      update_call_tree_add(contacts,call);
    }
272
    free_hit(entry);
Julien Bonjean's avatar
Julien Bonjean committed
273
  }
274 275
  g_list_free(results);

276

277
  active_calltree = contacts;
278 279 280 281
  gtk_widget_hide(current_calls->tree);
  gtk_widget_hide(history->tree);
  gtk_widget_show(contacts->tree);

282
  sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (active_calltree->view));
283 284
  g_signal_emit_by_name(sel, "changed");
  toolbar_update_buttons();
areversat's avatar
areversat committed
285
}
286 287

  static void
288
call_mailbox( GtkWidget* widget UNUSED, gpointer data UNUSED)
289
{
Emmanuel Milou's avatar
Emmanuel Milou committed
290 291
  account_t* current = account_list_get_current();
  if( current == NULL ) // Should not happens
292
    return;
Emmanuel Milou's avatar
Emmanuel Milou committed
293 294
  call_t* mailboxCall = g_new0( call_t , 1);
  mailboxCall->state = CALL_STATE_DIALING;
295
  mailboxCall->to = g_strdup(g_hash_table_lookup(current->properties, ACCOUNT_MAILBOX));
Emmanuel Milou's avatar
Emmanuel Milou committed
296
  mailboxCall->from = g_markup_printf_escaped(_("\"Voicemail\" <%s>"),  mailboxCall->to);
Emmanuel Milou's avatar
Emmanuel Milou committed
297 298 299
  mailboxCall->callID = g_new0(gchar, 30);
  g_sprintf(mailboxCall->callID, "%d", rand());
  mailboxCall->accountID = g_strdup(current->accountID);
Emmanuel Milou's avatar
Emmanuel Milou committed
300 301
  mailboxCall->_start = 0;
  mailboxCall->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
302 303
  g_print("TO : %s\n" , mailboxCall->to);
  call_list_add( current_calls , mailboxCall );
304
  update_call_tree_add( current_calls , mailboxCall );
Emmanuel Milou's avatar
Emmanuel Milou committed
305 306
  update_menus();
  sflphone_place_call( mailboxCall );
307
  switch_tab(current_calls);
308 309
}

alexandresavard's avatar
alexandresavard committed
310 311 312 313 314


/**
 * Static rec_button
 */
315
static void
alexandresavard's avatar
alexandresavard committed
316 317 318 319 320 321
rec_button( GtkWidget *widget UNUSED, gpointer   data UNUSED)
{
  sflphone_rec_call();
}


322
  void
323
toolbar_update_buttons ()
324
{
Emmanuel Milou's avatar
Emmanuel Milou committed
325 326 327 328 329 330
  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
331
  gtk_widget_set_sensitive( GTK_WIDGET(recButton),        FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
332 333
  g_object_ref(holdButton);
  g_object_ref(unholdButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
334 335
  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
336 337 338
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), holdButton, 3);
  g_object_ref(callButton);
  g_object_ref(pickupButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
339 340
  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
341
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), callButton, 0);
alexandresavard's avatar
alexandresavard committed
342
  //gtk_toolbar_insert(GTK_TOOLBAR(toolbar), recButton, 0);
Emmanuel Milou's avatar
Emmanuel Milou committed
343 344 345 346 347 348 349 350 351


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



428
/* Call back when the user click on a call in the list */
429 430
  static void
selected(GtkTreeSelection *sel, void* data UNUSED )
431
{
Emmanuel Milou's avatar
Emmanuel Milou committed
432 433 434
  GtkTreeIter  iter;
  GValue val;
  GtkTreeModel *model = (GtkTreeModel*)active_calltree->store;
435

Emmanuel Milou's avatar
Emmanuel Milou committed
436 437
  if (! gtk_tree_selection_get_selected (sel, &model, &iter))
    return;
438

Emmanuel Milou's avatar
Emmanuel Milou committed
439
  val.g_type = 0;
440
  gtk_tree_model_get_value (model, &iter, 2, &val);
441

Emmanuel Milou's avatar
Emmanuel Milou committed
442 443
  call_select(active_calltree, (call_t*) g_value_get_pointer(&val));
  g_value_unset(&val);
444

Emmanuel Milou's avatar
Emmanuel Milou committed
445
  toolbar_update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
446 447
}

448
/* A row is activated when it is double clicked */
449 450 451
void  row_activated(GtkTreeView       *tree_view UNUSED,
    GtkTreePath       *path UNUSED,
    GtkTreeViewColumn *column UNUSED,
452
    void * data UNUSED)
453
{
454 455 456 457 458
  g_print("double click action\n");
  call_t* selectedCall;
  call_t* newCall;
  selectedCall = call_get_selected( active_calltree );

Emmanuel Milou's avatar
Emmanuel Milou committed
459 460
  if (selectedCall)
  {
461 462
    // Get the right event from the right calltree
    if( active_calltree == current_calls )
Emmanuel Milou's avatar
Emmanuel Milou committed
463
    {
464
      switch(selectedCall->state)
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
      {
	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:
	  g_warning("Should not happen!");
	  break;
      }
Emmanuel Milou's avatar
Emmanuel Milou committed
484
    }
485
    // if history
486 487 488 489 490 491 492
    else
    {
      newCall = g_new0( call_t, 1 );
      newCall->to = g_strdup(call_get_number(selectedCall));
      newCall->from = g_strconcat("\"\" <", call_get_number(selectedCall), ">",NULL);
      newCall->state = CALL_STATE_DIALING;
      newCall->callID = g_new0(gchar, 30);
493
      g_sprintf(newCall->callID, "%d", rand());
494 495
      newCall->_start = 0;
      newCall->_stop = 0;
496 497
      printf("call : account : %s \n", selectedCall->accountID);
      newCall->accountID = selectedCall->accountID;
498 499 500 501
      printf("call : from : %s to %s\n", newCall->from, newCall->to);
      call_list_add(current_calls, newCall);
      update_call_tree_add(current_calls, newCall);
      sflphone_place_call(newCall);
502
      switch_tab(current_calls);
503 504 505
    }
  }
}
506

507
  GtkWidget *
areversat's avatar
areversat committed
508 509
create_toolbar ()
{
Emmanuel Milou's avatar
Emmanuel Milou committed
510 511 512 513 514 515 516 517 518
  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);

519 520
  image = gtk_image_new_from_file( ICONS_DIR "/call.svg");
  callButton = gtk_tool_button_new (image, _("Place a call"));
521
#if GTK_CHECK_VERSION(2,12,0)
522
  gtk_widget_set_tooltip_text(GTK_WIDGET(callButton), _("Place a call"));
523
#endif
524 525 526
  g_signal_connect (G_OBJECT (callButton), "clicked",
      G_CALLBACK (call_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(callButton), -1);
527

528 529
  image = gtk_image_new_from_file( ICONS_DIR "/accept.svg");
  pickupButton = gtk_tool_button_new(image, _("Pick up"));
530
#if GTK_CHECK_VERSION(2,12,0)
531
  gtk_widget_set_tooltip_text(GTK_WIDGET(pickupButton), _("Pick up"));
532
#endif
533
  gtk_widget_set_state( GTK_WIDGET(pickupButton), GTK_STATE_INSENSITIVE);
534
  g_signal_connect(G_OBJECT (pickupButton), "clicked",
535 536
      G_CALLBACK (call_button), NULL);
  gtk_widget_show_all(GTK_WIDGET(pickupButton));
537

538 539
  image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg");
  hangupButton = gtk_tool_button_new (image, _("Hang up"));
540
#if GTK_CHECK_VERSION(2,12,0)
541
  gtk_widget_set_tooltip_text(GTK_WIDGET(hangupButton), _("Hang up"));
542
#endif
543 544 545
  gtk_widget_set_state( GTK_WIDGET(hangupButton), GTK_STATE_INSENSITIVE);
  g_signal_connect (G_OBJECT (hangupButton), "clicked",
      G_CALLBACK (hang_up), NULL);
546
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(hangupButton), -1);
547

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

  image = gtk_image_new_from_file( ICONS_DIR "/history2.svg");
582
  historyButton = gtk_tool_button_new(image, _("History"));
583
#if GTK_CHECK_VERSION(2,12,0)
584
  gtk_widget_set_tooltip_text(GTK_WIDGET(historyButton), _("History"));
585
#endif
586
  g_signal_connect (G_OBJECT (historyButton), "clicked",
587
      G_CALLBACK (toggle_history), NULL);
588
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(historyButton), -1);
589 590
  active_calltree = current_calls;

591 592
  image = gtk_image_new_from_file( ICONS_DIR "/contacts.svg");
  contactButton = gtk_tool_button_new(image, _("Contacts"));
593 594 595
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(contactButton), _("Contacts"));
#endif
596
  g_signal_connect (G_OBJECT (contactButton), "clicked",
597 598 599
      G_CALLBACK (toggle_contacts), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(contactButton), -1);

600
  image = gtk_image_new_from_file( ICONS_DIR "/mailbox.svg");
Emmanuel Milou's avatar
Emmanuel Milou committed
601
  mailboxButton = gtk_tool_button_new( image , _("Voicemail"));
602 603
  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 );
604
#if GTK_CHECK_VERSION(2,12,0)
Emmanuel Milou's avatar
Emmanuel Milou committed
605
  gtk_widget_set_tooltip_text(GTK_WIDGET(mailboxButton), _("Voicemail"));
606
#endif
607 608 609
  g_signal_connect (G_OBJECT (mailboxButton), "clicked",
      G_CALLBACK (call_mailbox), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(mailboxButton), -1);
610

611

612 613 614
  //image = gtk_image_new_from_file( ICONS_DIR "/record.svg");
  //recButton = gtk_tool_button_new (image, _("Record a call"));
  recButton = gtk_tool_button_new_from_stock (GTK_STOCK_MEDIA_RECORD);
alexandresavard's avatar
alexandresavard committed
615 616 617
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(recButton), _("Record a call"));
#endif
618
  gtk_widget_set_state( GTK_WIDGET(recButton), GTK_STATE_INSENSITIVE);
alexandresavard's avatar
alexandresavard committed
619 620 621 622 623
  g_signal_connect (G_OBJECT (recButton), "clicked",
      G_CALLBACK (rec_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(recButton), -1);


624
  return ret;
625

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

649 650 651 652 653 654 655 656 657
/**
 * Reset call tree
 */
  void
reset_call_tree (calltab_t* tab)
{
  gtk_list_store_clear (tab->store);
}

658
  void
areversat's avatar
areversat committed
659 660
create_call_tree (calltab_t* tab)
{
Emmanuel Milou's avatar
Emmanuel Milou committed
661 662 663 664
  GtkWidget *sw;
  GtkCellRenderer *rend;
  GtkTreeViewColumn *col;
  GtkTreeSelection *sel;
665

666
  tab->tree = gtk_vbox_new(FALSE, 10);
667

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

Emmanuel Milou's avatar
Emmanuel Milou committed
670 671 672
  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);
673
  g_signal_connect (G_OBJECT ( sw ), "key-release-event",G_CALLBACK (on_key_released), NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
674

675 676
  tab->store = gtk_list_store_new (3,
      GDK_TYPE_PIXBUF,// Icon
Emmanuel Milou's avatar
Emmanuel Milou committed
677 678 679
      G_TYPE_STRING,  // Description
      G_TYPE_POINTER  // Pointer to the Object
      );
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
680

Emmanuel Milou's avatar
Emmanuel Milou committed
681
  tab->view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(tab->store));
682
  gtk_tree_view_set_enable_search( GTK_TREE_VIEW(tab->view), FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
683 684 685 686
  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);
687

688
  // Connect the popup menu
Emmanuel Milou's avatar
Emmanuel Milou committed
689
  g_signal_connect (G_OBJECT (tab->view), "popup-menu",
690
      G_CALLBACK (popup_menu),
Emmanuel Milou's avatar
Emmanuel Milou committed
691 692
      NULL);
  g_signal_connect (G_OBJECT (tab->view), "button-press-event",
693
      G_CALLBACK (button_pressed),
Emmanuel Milou's avatar
Emmanuel Milou committed
694 695
      NULL);

696

Emmanuel Milou's avatar
Emmanuel Milou committed
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
  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);

721
  gtk_widget_show(tab->tree);
Emmanuel Milou's avatar
Emmanuel Milou committed
722 723 724

  //toolbar_update_buttons();

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
725
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
726

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

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

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

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

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

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

874
      }
Emmanuel Milou's avatar
Emmanuel Milou committed
875 876
    }

877
  }
Emmanuel Milou's avatar
Emmanuel Milou committed
878 879 880
  toolbar_update_buttons();
}

881
  void
Emmanuel Milou's avatar
Emmanuel Milou committed
882 883 884 885 886
update_call_tree_add (calltab_t* tab, call_t * c)
{
  if( tab == history && ( call_list_get_size( tab ) > dbus_get_max_calls() ) )
    return;

887
  GdkPixbuf *pixbuf=NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
888 889 890 891
  GtkTreeIter iter;
  GtkTreeSelection* sel;

  // New call in the list
Emmanuel Milou's avatar
Emmanuel Milou committed
892
  gchar * description;
Emmanuel Milou's avatar
Emmanuel Milou committed
893
  gchar * date="";
894
  description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>",
895
      call_get_number(c),
896
      call_get_name(c));
Emmanuel Milou's avatar
Emmanuel Milou committed
897

898

Emmanuel Milou's avatar
Emmanuel Milou committed
899 900 901