calltree.c 27.9 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
/**
 * Show popup menu
 */
48
  static gboolean
49
popup_menu (GtkWidget *widget,
50
    gpointer   user_data UNUSED)
51 52 53
{
  show_popup_menu(widget, NULL);
  return TRUE;
54
}
Emmanuel Milou's avatar
Emmanuel Milou committed
55

Emmanuel Milou's avatar
Emmanuel Milou committed
56 57 58 59 60 61
  static gboolean
is_inserted( GtkWidget* button )
{
  return ( GTK_WIDGET(button)->parent == GTK_WIDGET( toolbar ) );
}

Emmanuel Milou's avatar
Emmanuel Milou committed
62
  static gboolean
Emmanuel Milou's avatar
Emmanuel Milou committed
63
button_pressed(GtkWidget* widget, GdkEventButton *event, gpointer user_data UNUSED)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
64 65 66
{
  if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
  {
67 68 69 70 71 72 73 74 75 76
    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
77 78 79
  }
  return FALSE;
}
80
/**
81
 * Make a call
82
 */
83
  static void
84
call_button( GtkWidget *widget UNUSED, gpointer   data UNUSED)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
85
{
86
  call_t * selectedCall = call_get_selected(active_calltree);
87
  call_t* newCall =  g_new0 (call_t, 1);
Emmanuel Milou's avatar
Emmanuel Milou committed
88 89 90 91
  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){
92 93 94
    if( selectedCall)
    {
      printf("Calling a called num\n");
95

96 97 98 99
      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);
100
      g_sprintf(newCall->callID, "%d", rand());
101 102
      newCall->_start = 0;
      newCall->_stop = 0;
103

104 105 106 107
      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);
108
      switch_tab(current_calls);
109
    }
110 111 112
    else
    {
      sflphone_new_call();
113
      switch_tab(current_calls);
114 115 116 117
    }
  }
  else
  {
Emmanuel Milou's avatar
Emmanuel Milou committed
118
    sflphone_new_call();
119
    switch_tab(current_calls);
120
  }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
121 122
}

123
/**
124
 * Hang up the line
125
 */
126
  static void
127
hang_up( GtkWidget *widget UNUSED, gpointer   data UNUSED)
128
{
Emmanuel Milou's avatar
Emmanuel Milou committed
129
  sflphone_hang_up();
130 131 132
}

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

/**
 * Transfert the line
 */
144
  static void
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
145
transfert  (GtkToggleToolButton *toggle_tool_button,
146
    gpointer             user_data UNUSED )
147
{
Emmanuel Milou's avatar
Emmanuel Milou committed
148 149 150 151 152 153 154 155 156
  gboolean up = gtk_toggle_tool_button_get_active(toggle_tool_button);
  if(up)
  {
    sflphone_set_transfert();
  }
  else
  {
    sflphone_unset_transfert();
  }
157 158
}

159 160 161
/**
 * Unhold call
 */
162
  static void
163
unhold( GtkWidget *widget UNUSED, gpointer   data UNUSED)
164
{
Emmanuel Milou's avatar
Emmanuel Milou committed
165
  sflphone_off_hold();
166
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
167

168 169 170 171 172 173 174 175 176 177
  static void
toggle_current_calls(GtkToggleToolButton *toggle_tool_button UNUSED,
    gpointer  user_data UNUSED)
{
  GtkTreeSelection *sel;

  active_calltree = current_calls;
  gtk_widget_hide(history->tree);
  gtk_widget_hide(contacts->tree);
  gtk_widget_show(current_calls->tree);
178
  printf("current calls toggle\n");
179 180 181 182 183 184

  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
185
  static void
186 187
toggle_history(GtkToggleToolButton *toggle_tool_button UNUSED,
    gpointer	user_data UNUSED)
areversat's avatar
areversat committed
188 189
{
	GtkTreeSelection *sel;
190

191 192 193 194
  active_calltree = history;
  gtk_widget_hide(current_calls->tree);
  gtk_widget_hide(contacts->tree);
  gtk_widget_show(history->tree);
195

areversat's avatar
areversat committed
196 197 198
	sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (active_calltree->view));
	g_signal_emit_by_name(sel, "changed");
	toolbar_update_buttons();
199
	gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(histfilter));
200

201 202 203 204 205 206 207 208
}

  static void
toggle_contacts(GtkToggleToolButton *toggle_tool_button UNUSED,
    gpointer  user_data UNUSED)
{

  GtkTreeSelection *sel;
Julien Bonjean's avatar
Julien Bonjean committed
209 210 211
  GList *results;
  GList *i;

Julien Bonjean's avatar
Julien Bonjean committed
212 213
  printf("EDS : %s\n",gtk_entry_get_text(GTK_ENTRY(filter_entry)));

214 215 216 217 218
  // Reset previous results
  call_list_reset(contacts);
  reset_call_tree(contacts);

  // Do a synchronized search
Julien Bonjean's avatar
Julien Bonjean committed
219
  results = search_sync (gtk_entry_get_text(GTK_ENTRY(filter_entry)), 50);
Julien Bonjean's avatar
Julien Bonjean committed
220 221 222

  if(results == NULL)
  {
223 224
    printf("No results\n");
    return ;
Julien Bonjean's avatar
Julien Bonjean committed
225
  }
226

Julien Bonjean's avatar
Julien Bonjean committed
227 228 229 230 231 232 233 234 235
  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
236
      call->from = g_strconcat("\"" , entry->name, "\"<", entry->phone, ">", NULL);
Julien Bonjean's avatar
Julien Bonjean committed
237 238 239 240 241 242 243
      call->state = CALL_STATE_RECORD;
      call->history_state = OUTGOING;

      call_list_add (contacts, call);
      update_call_tree_add(contacts,call);
    }
  }
244

245
  active_calltree = contacts;
246 247 248 249
  gtk_widget_hide(current_calls->tree);
  gtk_widget_hide(history->tree);
  gtk_widget_show(contacts->tree);

250
  sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (active_calltree->view));
251 252
  g_signal_emit_by_name(sel, "changed");
  toolbar_update_buttons();
areversat's avatar
areversat committed
253
}
254 255

  static void
256
call_mailbox( GtkWidget* widget UNUSED, gpointer data UNUSED)
257
{
Emmanuel Milou's avatar
Emmanuel Milou committed
258 259
  account_t* current = account_list_get_current();
  if( current == NULL ) // Should not happens
260
    return;
Emmanuel Milou's avatar
Emmanuel Milou committed
261 262
  call_t* mailboxCall = g_new0( call_t , 1);
  mailboxCall->state = CALL_STATE_DIALING;
263
  mailboxCall->to = g_strdup(g_hash_table_lookup(current->properties, ACCOUNT_MAILBOX));
Emmanuel Milou's avatar
Emmanuel Milou committed
264
  mailboxCall->from = g_markup_printf_escaped(_("\"Voicemail\" <%s>"),  mailboxCall->to);
Emmanuel Milou's avatar
Emmanuel Milou committed
265 266 267
  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
268 269
  mailboxCall->_start = 0;
  mailboxCall->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
270 271
  g_print("TO : %s\n" , mailboxCall->to);
  call_list_add( current_calls , mailboxCall );
272
  update_call_tree_add( current_calls , mailboxCall );
Emmanuel Milou's avatar
Emmanuel Milou committed
273 274
  update_menus();
  sflphone_place_call( mailboxCall );
275
  switch_tab(current_calls);
276 277
}

alexandresavard's avatar
alexandresavard committed
278 279 280 281 282


/**
 * Static rec_button
 */
283
static void
alexandresavard's avatar
alexandresavard committed
284 285 286 287 288 289
rec_button( GtkWidget *widget UNUSED, gpointer   data UNUSED)
{
  sflphone_rec_call();
}


290
  void
291
toolbar_update_buttons ()
292
{
Emmanuel Milou's avatar
Emmanuel Milou committed
293 294 295 296 297 298
  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
299
  gtk_widget_set_sensitive( GTK_WIDGET(recButton),        FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
300 301
  g_object_ref(holdButton);
  g_object_ref(unholdButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
302 303
  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
304 305 306
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), holdButton, 3);
  g_object_ref(callButton);
  g_object_ref(pickupButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
307 308
  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
309
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), callButton, 0);
alexandresavard's avatar
alexandresavard committed
310
  //gtk_toolbar_insert(GTK_TOOLBAR(toolbar), recButton, 0);
Emmanuel Milou's avatar
Emmanuel Milou committed
311 312 313 314 315 316 317 318 319


  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)
  {
320
    switch(selectedCall->state)
Emmanuel Milou's avatar
Emmanuel Milou committed
321 322 323 324
    {
      case CALL_STATE_INCOMING:
	gtk_widget_set_sensitive( GTK_WIDGET(pickupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),	TRUE);
325
	g_object_ref(callButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
326 327 328 329 330 331 332
	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);
333 334
	g_object_ref(holdButton);
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(holdButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
335 336 337 338 339 340 341 342 343
	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
344 345
	g_object_ref(callButton);
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(callButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
346 347 348 349 350 351 352
	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
353
        gtk_widget_set_sensitive( GTK_WIDGET(recButton),        TRUE);
Emmanuel Milou's avatar
Emmanuel Milou committed
354 355 356 357
	break;
      case CALL_STATE_BUSY:
      case CALL_STATE_FAILURE:
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
358
	break;
359
      case CALL_STATE_TRANSFERT:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
360
	gtk_signal_handler_block(GTK_OBJECT(transfertButton),transfertButtonConnId);
Emmanuel Milou's avatar
Emmanuel Milou committed
361
	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transfertButton), TRUE);
362
	gtk_signal_handler_unblock(transfertButton, transfertButtonConnId);
Emmanuel Milou's avatar
Emmanuel Milou committed
363 364 365 366 367
	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;
368 369 370 371 372 373 374
      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
375 376 377 378 379
      default:
	g_warning("Should not happen!");
	break;
    }
  }
380
  else
Emmanuel Milou's avatar
Emmanuel Milou committed
381 382 383 384 385 386 387 388 389 390 391
  {
    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);
    }
  }
392
}
alexandresavard's avatar
alexandresavard committed
393 394 395



396
/* Call back when the user click on a call in the list */
397 398
  static void
selected(GtkTreeSelection *sel, void* data UNUSED )
399
{
Emmanuel Milou's avatar
Emmanuel Milou committed
400 401 402
  GtkTreeIter  iter;
  GValue val;
  GtkTreeModel *model = (GtkTreeModel*)active_calltree->store;
403

Emmanuel Milou's avatar
Emmanuel Milou committed
404 405
  if (! gtk_tree_selection_get_selected (sel, &model, &iter))
    return;
406

Emmanuel Milou's avatar
Emmanuel Milou committed
407
  val.g_type = 0;
408
  gtk_tree_model_get_value (model, &iter, 2, &val);
409

Emmanuel Milou's avatar
Emmanuel Milou committed
410 411
  call_select(active_calltree, (call_t*) g_value_get_pointer(&val));
  g_value_unset(&val);
412

Emmanuel Milou's avatar
Emmanuel Milou committed
413
  toolbar_update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
414 415
}

416
/* A row is activated when it is double clicked */
417 418 419
void  row_activated(GtkTreeView       *tree_view UNUSED,
    GtkTreePath       *path UNUSED,
    GtkTreeViewColumn *column UNUSED,
420
    void * data UNUSED)
421
{
422 423 424 425 426
  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
427 428
  if (selectedCall)
  {
429 430
    // Get the right event from the right calltree
    if( active_calltree == current_calls )
Emmanuel Milou's avatar
Emmanuel Milou committed
431
    {
432
      switch(selectedCall->state)
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
      {
	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
452
    }
453
    // if history
454 455 456 457 458 459 460
    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);
461
      g_sprintf(newCall->callID, "%d", rand());
462 463
      newCall->_start = 0;
      newCall->_stop = 0;
464 465
      printf("call : account : %s \n", selectedCall->accountID);
      newCall->accountID = selectedCall->accountID;
466 467 468 469
      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);
470
      switch_tab(current_calls);
471 472 473
    }
  }
}
474

475
  GtkWidget *
areversat's avatar
areversat committed
476 477
create_toolbar ()
{
Emmanuel Milou's avatar
Emmanuel Milou committed
478 479 480 481 482 483 484 485 486
  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);

487 488
  image = gtk_image_new_from_file( ICONS_DIR "/call.svg");
  callButton = gtk_tool_button_new (image, _("Place a call"));
489
#if GTK_CHECK_VERSION(2,12,0)
490
  gtk_widget_set_tooltip_text(GTK_WIDGET(callButton), _("Place a call"));
491
#endif
492 493 494
  g_signal_connect (G_OBJECT (callButton), "clicked",
      G_CALLBACK (call_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(callButton), -1);
495

496 497
  image = gtk_image_new_from_file( ICONS_DIR "/accept.svg");
  pickupButton = gtk_tool_button_new(image, _("Pick up"));
498
#if GTK_CHECK_VERSION(2,12,0)
499
  gtk_widget_set_tooltip_text(GTK_WIDGET(pickupButton), _("Pick up"));
500
#endif
501
  gtk_widget_set_state( GTK_WIDGET(pickupButton), GTK_STATE_INSENSITIVE);
502
  g_signal_connect(G_OBJECT (pickupButton), "clicked",
503 504
      G_CALLBACK (call_button), NULL);
  gtk_widget_show_all(GTK_WIDGET(pickupButton));
505

506 507
  image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg");
  hangupButton = gtk_tool_button_new (image, _("Hang up"));
508
#if GTK_CHECK_VERSION(2,12,0)
509
  gtk_widget_set_tooltip_text(GTK_WIDGET(hangupButton), _("Hang up"));
510
#endif
511 512 513
  gtk_widget_set_state( GTK_WIDGET(hangupButton), GTK_STATE_INSENSITIVE);
  g_signal_connect (G_OBJECT (hangupButton), "clicked",
      G_CALLBACK (hang_up), NULL);
514
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(hangupButton), -1);
515

516 517
  image = gtk_image_new_from_file( ICONS_DIR "/unhold.svg");
  unholdButton = gtk_tool_button_new (image, _("Off Hold"));
518
#if GTK_CHECK_VERSION(2,12,0)
519
  gtk_widget_set_tooltip_text(GTK_WIDGET(unholdButton), _("Off Hold"));
520
#endif
521 522 523 524 525 526 527 528
  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"));
529
#if GTK_CHECK_VERSION(2,12,0)
530
  gtk_widget_set_tooltip_text(GTK_WIDGET(holdButton), _("On Hold"));
531
#endif
532 533 534 535 536 537 538 539
  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);
540
#if GTK_CHECK_VERSION(2,12,0)
541
  gtk_widget_set_tooltip_text(GTK_WIDGET(transfertButton), _("Transfer"));
542
#endif
543 544 545 546
  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);
547
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(transfertButton), -1);
548 549

  image = gtk_image_new_from_file( ICONS_DIR "/history2.svg");
550
  historyButton = gtk_tool_button_new(image, _("History"));
551
#if GTK_CHECK_VERSION(2,12,0)
552
  gtk_widget_set_tooltip_text(GTK_WIDGET(historyButton), _("History"));
553
#endif
554
  g_signal_connect (G_OBJECT (historyButton), "clicked",
555
      G_CALLBACK (toggle_history), NULL);
556
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(historyButton), -1);
557 558
  active_calltree = current_calls;

559 560
  image = gtk_image_new_from_file( ICONS_DIR "/contacts.svg");
  contactButton = gtk_tool_button_new(image, _("Contacts"));
561 562 563
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(contactButton), _("Contacts"));
#endif
564
  g_signal_connect (G_OBJECT (contactButton), "clicked",
565 566 567
      G_CALLBACK (toggle_contacts), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(contactButton), -1);

568
  image = gtk_image_new_from_file( ICONS_DIR "/mailbox.svg");
Emmanuel Milou's avatar
Emmanuel Milou committed
569
  mailboxButton = gtk_tool_button_new( image , _("Voicemail"));
570 571
  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 );
572
#if GTK_CHECK_VERSION(2,12,0)
Emmanuel Milou's avatar
Emmanuel Milou committed
573
  gtk_widget_set_tooltip_text(GTK_WIDGET(mailboxButton), _("Voicemail"));
574
#endif
575 576 577
  g_signal_connect (G_OBJECT (mailboxButton), "clicked",
      G_CALLBACK (call_mailbox), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(mailboxButton), -1);
578

579

580 581 582
  //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
583 584 585
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(recButton), _("Record a call"));
#endif
586
  gtk_widget_set_state( GTK_WIDGET(recButton), GTK_STATE_INSENSITIVE);
alexandresavard's avatar
alexandresavard committed
587 588 589 590 591
  g_signal_connect (G_OBJECT (recButton), "clicked",
      G_CALLBACK (rec_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(recButton), -1);


592
  return ret;
593

594
}
595
static gboolean
596
on_key_released (GtkWidget   *widget UNUSED,
597
                GdkEventKey *event,
598
                gpointer     user_data UNUSED)
599 600
{
  // If a modifier key is pressed, it's a shortcut, pass along
601
  if(event->state & GDK_CONTROL_MASK ||
602 603 604 605 606 607 608 609 610 611 612 613 614 615
     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
616

617 618 619 620 621 622 623 624 625
/**
 * Reset call tree
 */
  void
reset_call_tree (calltab_t* tab)
{
  gtk_list_store_clear (tab->store);
}

626
  void
areversat's avatar
areversat committed
627 628
create_call_tree (calltab_t* tab)
{
Emmanuel Milou's avatar
Emmanuel Milou committed
629 630 631 632
  GtkWidget *sw;
  GtkCellRenderer *rend;
  GtkTreeViewColumn *col;
  GtkTreeSelection *sel;
633

634
  tab->tree = gtk_vbox_new(FALSE, 10);
635

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

Emmanuel Milou's avatar
Emmanuel Milou committed
638 639 640
  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);
641
  g_signal_connect (G_OBJECT ( sw ), "key-release-event",G_CALLBACK (on_key_released), NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
642

643 644
  tab->store = gtk_list_store_new (3,
      GDK_TYPE_PIXBUF,// Icon
Emmanuel Milou's avatar
Emmanuel Milou committed
645 646 647
      G_TYPE_STRING,  // Description
      G_TYPE_POINTER  // Pointer to the Object
      );
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
648

Emmanuel Milou's avatar
Emmanuel Milou committed
649
  tab->view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(tab->store));
650
  gtk_tree_view_set_enable_search( GTK_TREE_VIEW(tab->view), FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
651 652 653 654
  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);
655

656
  // Connect the popup menu
Emmanuel Milou's avatar
Emmanuel Milou committed
657
  g_signal_connect (G_OBJECT (tab->view), "popup-menu",
658
      G_CALLBACK (popup_menu),
Emmanuel Milou's avatar
Emmanuel Milou committed
659 660
      NULL);
  g_signal_connect (G_OBJECT (tab->view), "button-press-event",
661
      G_CALLBACK (button_pressed),
Emmanuel Milou's avatar
Emmanuel Milou committed
662 663
      NULL);

664

Emmanuel Milou's avatar
Emmanuel Milou committed
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
  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);

689
  gtk_widget_show(tab->tree);
Emmanuel Milou's avatar
Emmanuel Milou committed
690 691 692

  //toolbar_update_buttons();

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
693
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
694

695
  void
696
update_call_tree_remove (calltab_t* tab, call_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
697
{
Emmanuel Milou's avatar
Emmanuel Milou committed
698 699 700 701 702 703 704 705 706 707 708 709
  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;
710
      gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
Emmanuel Milou's avatar
Emmanuel Milou committed
711 712 713 714 715 716 717 718 719 720 721 722 723 724

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

727
  void
728
update_call_tree (calltab_t* tab, call_t * c)
729
{
730 731
    g_print("update call tree\n");
  GdkPixbuf *pixbuf=NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
732 733 734 735 736 737 738 739 740 741 742 743
  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;
744
      gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
Emmanuel Milou's avatar
Emmanuel Milou committed
745 746 747 748 749 750 751 752

      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
753 754
	gchar * date="";
	gchar * duration="";
Emmanuel Milou's avatar
Emmanuel Milou committed
755
	if(c->state == CALL_STATE_TRANSFERT)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
756
	{
757 758 759
	  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
760 761 762 763
	      c->to);
	}
	else
	{
764
	  description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>",
765
	      call_get_number(c),
766
	      call_get_name(c));
Emmanuel Milou's avatar
Emmanuel Milou committed
767
	}
768

769 770
	if( tab == current_calls )
	{
Emmanuel Milou's avatar
Emmanuel Milou committed
771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
	  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);
793 794 795
              break;
            case CALL_STATE_RECORD:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/rec_call.svg", NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
796 797 798 799
	      break;
	    default:
	      g_warning("Should not happen!");
	  }
800
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
801 802
	else
	{
803 804 805
	  switch(c->history_state)
	  {
	    case OUTGOING:
Emmanuel Milou's avatar
Emmanuel Milou committed
806 807 808 809 810 811
	      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);
812 813
	      break;
	    case MISSED:
Emmanuel Milou's avatar
Emmanuel Milou committed
814 815
	      g_print("Missed state\n");
	      pixbuf = gdk_pixbuf_new_from_file( ICONS_DIR "/missed.svg", NULL);
816 817
	      break;
	    default:
818
	      g_print("No history state\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
819
	      break;
820
	  }
821
	  date = timestamp_get_call_date();
Emmanuel Milou's avatar
Emmanuel Milou committed
822
	  duration = process_call_duration(c);
823 824
	  duration = g_strconcat( date , duration , NULL);
	  description = g_strconcat( description , duration, NULL);
825
	}
826 827 828
	//Resize it
	if(pixbuf)
	{
Emmanuel Milou's avatar
Emmanuel Milou committed
829 830 831 832
	  if(gdk_pixbuf_get_width(pixbuf) > 32 || gdk_pixbuf_get_height(pixbuf) > 32)
	  {
	    pixbuf =  gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
	  }
833
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
834 835 836 837
	gtk_list_store_set(store, &iter,
	    0, pixbuf, // Icon
	    1, description, // Description
	    -1);
838 839

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

842
      }
Emmanuel Milou's avatar
Emmanuel Milou committed
843 844
    }

845
  }
Emmanuel Milou's avatar
Emmanuel Milou committed
846 847 848
  toolbar_update_buttons();
}

849
  void
Emmanuel Milou's avatar
Emmanuel Milou committed
850 851 852 853 854
update_call_tree_add (calltab_t* tab, call_t * c)
{
  if( tab == history && ( call_list_get_size( tab ) > dbus_get_max_calls() ) )
    return;

855
  GdkPixbuf *pixbuf=NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
856 857 858 859
  GtkTreeIter iter;
  GtkTreeSelection* sel;

  // New call in the list
Emmanuel Milou's avatar
Emmanuel Milou committed
860
  gchar * description;
Emmanuel Milou's avatar
Emmanuel Milou committed
861
  gchar * date="";
862
  description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>",
863
      call_get_number(c),
864
      call_get_name(c));
Emmanuel Milou's avatar
Emmanuel Milou committed
865

866

Emmanuel Milou's avatar
Emmanuel Milou committed
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
  gtk_list_store_prepend (tab->store, &iter);

  if( tab == current_calls )
  {
    switch(c->state)
    {
      case CALL_STATE_INCOMING:
	pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
	break;
      case CALL_STATE_DIALING:
	pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL);
	break;
      case CALL_STATE_RINGING:
	pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
	break;
      default:
	g_warning("Should not happen!");
    }
  }
  else{
    switch(c->history_state)
    {
      case INCOMING:
	pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/incoming.svg", NULL);
	break;
      case OUTGOING:
	pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/outgoing.svg", NULL);
	break;
      case MISSED:
	pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/missed.svg", NULL);
	break;
      default:
899
	g_warning("History - Should not happen!");
Emmanuel Milou's avatar
Emmanuel Milou committed
900
    }
901
    date = timestamp_get_call_date();
902 903 904 905
    if(tab == contacts)
      description = g_strconcat( description , NULL);
    else
      description = g_strconcat( date , description , NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
906
  }
907

Emmanuel Milou's avatar
Emmanuel Milou committed
908 909 910 911 912 913 914