calltree.c 27.5 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
areversat's avatar
areversat committed
44
gboolean history_shown;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
45

46
  void
47 48
switch_tab()
{
49
  (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(historyButton)))?
Emmanuel Milou's avatar
Emmanuel Milou committed
50 51
    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(historyButton), FALSE):
    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(historyButton), TRUE);
52
}
53

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

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

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

105 106 107 108
      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);
109
      g_sprintf(newCall->callID, "%d", rand());
110 111
      newCall->_start = 0;
      newCall->_stop = 0;
112

113 114 115 116 117 118
      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);
      if( active_calltree == history )  switch_tab();
    }
119 120 121 122 123 124 125 126
    else
    {
      sflphone_new_call();
      if( active_calltree == history )  switch_tab();
    }
  }
  else
  {
Emmanuel Milou's avatar
Emmanuel Milou committed
127
    sflphone_new_call();
128
    if( active_calltree == history )  switch_tab();
129
  }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
130 131
}

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

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

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

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

Emmanuel Milou's avatar
Emmanuel Milou committed
177
  static void
178 179
toggle_history(GtkToggleToolButton *toggle_tool_button UNUSED,
    gpointer	user_data UNUSED)
areversat's avatar
areversat committed
180 181
{
	GtkTreeSelection *sel;
182

183 184 185 186 187
  active_calltree = history;
  gtk_widget_hide(current_calls->tree);
  gtk_widget_hide(contacts->tree);
  gtk_widget_show(history->tree);
  history_shown = TRUE;
188

areversat's avatar
areversat committed
189 190 191
	sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (active_calltree->view));
	g_signal_emit_by_name(sel, "changed");
	toolbar_update_buttons();
192
	gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(histfilter));
193

194 195 196 197 198 199 200 201
}

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

  GtkTreeSelection *sel;
Julien Bonjean's avatar
Julien Bonjean committed
202 203
  GList *results;
  GList *i;
204
  char ext[30];
Julien Bonjean's avatar
Julien Bonjean committed
205

206 207 208 209 210 211
  // Reset previous results
  call_list_reset(contacts);
  reset_call_tree(contacts);

  // Do a synchronized search
  results = search_sync ("j", 50);
Julien Bonjean's avatar
Julien Bonjean committed
212 213 214

  if(results == NULL)
  {
215 216
    printf("No results\n");
    return ;
Julien Bonjean's avatar
Julien Bonjean committed
217
  }
218

Julien Bonjean's avatar
Julien Bonjean committed
219 220 221 222 223 224 225 226 227 228 229 230
  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);
      call->accountID = g_strdup("Account:1235677223");
      call->callID = g_new0(gchar, 30);
      g_sprintf(call->callID, "%d", rand());
231 232
      sprintf(ext, "%d", rand()%100 + 100);
      call->from = g_strconcat("\"" , entry->text, "\"<", ext, ">", NULL);
Julien Bonjean's avatar
Julien Bonjean committed
233 234 235 236 237 238 239
      call->state = CALL_STATE_RECORD;
      call->history_state = OUTGOING;

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

241 242 243 244 245 246 247 248 249 250
  gtk_widget_hide(current_calls->tree);
  gtk_widget_hide(history->tree);
  gtk_widget_show(contacts->tree);
  history_shown = FALSE;

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

  gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(contactfilter));
areversat's avatar
areversat committed
251
}
252 253

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

alexandresavard's avatar
alexandresavard committed
276 277 278 279 280


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


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


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



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

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

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

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

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

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

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

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

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

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

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

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

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

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

578

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


591
  return ret;
592

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

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

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

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

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

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

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

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

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

663

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

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

  //toolbar_update_buttons();

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

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

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

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

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

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

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

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

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

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

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

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

865

Emmanuel Milou's avatar
Emmanuel Milou committed
866 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
  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:
898
	g_warning("History - Should not happen!");
Emmanuel Milou's avatar
Emmanuel Milou committed
899
    }
900
    date = timestamp_get_call_date();
901 902 903 904
    if(tab == contacts)
      description = g_strconcat( description , NULL);
    else
      description = g_strconcat( date , description , NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
905
  }
906

Emmanuel Milou's avatar
Emmanuel Milou committed
907 908 909 910 911 912 913 914 915 916
  //Resize it
  if(pixbuf)
  {
    if(gdk_pixbuf_get_width(pixbuf) > 32 || gdk_pixbuf_get_height(pixbuf) > 32)
    {
      pixbuf =  gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
    }
  }
  gtk_list_store_set(tab->store, &iter,
      0, pixbuf, // Icon
Emmanuel Milou's avatar
Emmanuel Milou committed
917
      1, description, // Description
918
      2, c,      // Pointer
Emmanuel Milou's avatar