calltree.c 30.3 KB
Newer Older
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
1 2
/*
 *  Copyright (C) 2007 Savoir-Faire Linux inc.
3
 *  Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>
4
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
5
 *
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
6 7
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 3 of the License, or
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
9
 *  (at your option) any later version.
10
 *
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
11 12 13 14
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
15
 *
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
16 17 18 19 20
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    // Load the parameters
    addressbook_load_parameters (&addressbook_config);
Emmanuel Milou's avatar
Emmanuel Milou committed
237 238 239 240 241 242 243

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

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

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

  static void
Julien Bonjean's avatar
Julien Bonjean committed
273
show_contacts_tab(GtkToggleToolButton *toggle_tool_button UNUSED,
274 275
    gpointer  user_data UNUSED)
{
276 277 278 279 280 281 282
  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
283

284 285 286 287 288 289 290
  // freeing calls
  while((j = (call_t *)g_queue_pop_tail (contacts->callQueue)) != NULL)
  {
    free_call_t(j);
  }

  // reset previous results
291
  reset_call_tree(contacts);
292
  call_list_reset(contacts);
293

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

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

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

    /* Check if the information is valid */
307
    if (g_strcasecmp (contact_phone, EMPTY_ENTRY) != 0){
308 309
        from = g_strconcat("\"" , contact_name, "\"<", contact_phone, ">", NULL);
        create_new_call (from, from, CALL_STATE_DIALING, "", &new_call);
310
        new_call->contact_type = type;
311 312 313 314 315 316
        call_list_add (contacts, new_call);
        update_call_tree_add(contacts, new_call);
    }

}

317
  static void
318
call_mailbox( GtkWidget* widget UNUSED, gpointer data UNUSED)
319
{
Emmanuel Milou's avatar
Emmanuel Milou committed
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
    account_t* current;
    call_t *mailbox_call;
    gchar *to, *from, *account_id;

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

alexandresavard's avatar
alexandresavard committed
341 342 343 344 345


/**
 * Static rec_button
 */
346
static void
alexandresavard's avatar
alexandresavard committed
347 348 349 350 351 352
rec_button( GtkWidget *widget UNUSED, gpointer   data UNUSED)
{
  sflphone_rec_call();
}


353
  void
354
toolbar_update_buttons ()
355
{
Emmanuel Milou's avatar
Emmanuel Milou committed
356 357 358 359 360 361
  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
362
  gtk_widget_set_sensitive( GTK_WIDGET(recButton),        FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
363 364
  g_object_ref(holdButton);
  g_object_ref(unholdButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
365 366
  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
367 368 369
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), holdButton, 3);
  g_object_ref(callButton);
  g_object_ref(pickupButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
370 371
  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
372
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), callButton, 0);
alexandresavard's avatar
alexandresavard committed
373
  //gtk_toolbar_insert(GTK_TOOLBAR(toolbar), recButton, 0);
Emmanuel Milou's avatar
Emmanuel Milou committed
374 375 376 377 378 379 380 381 382


  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)
  {
383
    switch(selectedCall->state)
Emmanuel Milou's avatar
Emmanuel Milou committed
384 385 386 387
    {
      case CALL_STATE_INCOMING:
	gtk_widget_set_sensitive( GTK_WIDGET(pickupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),	TRUE);
388
	g_object_ref(callButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
389 390 391 392 393 394 395
	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);
396 397
	g_object_ref(holdButton);
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(holdButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
398 399 400 401 402 403 404 405 406
	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
407 408
	g_object_ref(callButton);
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(callButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
409 410 411 412 413 414 415
	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
416
        gtk_widget_set_sensitive( GTK_WIDGET(recButton),        TRUE);
Emmanuel Milou's avatar
Emmanuel Milou committed
417 418 419 420
	break;
      case CALL_STATE_BUSY:
      case CALL_STATE_FAILURE:
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
421
	break;
422
      case CALL_STATE_TRANSFERT:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
423
	gtk_signal_handler_block(GTK_OBJECT(transfertButton),transfertButtonConnId);
Emmanuel Milou's avatar
Emmanuel Milou committed
424
	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transfertButton), TRUE);
425
	gtk_signal_handler_unblock(transfertButton, transfertButtonConnId);
Emmanuel Milou's avatar
Emmanuel Milou committed
426 427 428 429 430
	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;
431 432 433 434 435 436 437
      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
438
      default:
439
	g_warning("Toolbar update - Should not happen!");
Emmanuel Milou's avatar
Emmanuel Milou committed
440 441 442
	break;
    }
  }
443
  else
Emmanuel Milou's avatar
Emmanuel Milou committed
444 445 446 447 448 449 450 451 452 453 454
  {
    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);
    }
  }
455
}
alexandresavard's avatar
alexandresavard committed
456 457 458



459
/* Call back when the user click on a call in the list */
460 461
  static void
selected(GtkTreeSelection *sel, void* data UNUSED )
462
{
Emmanuel Milou's avatar
Emmanuel Milou committed
463 464 465
  GtkTreeIter  iter;
  GValue val;
  GtkTreeModel *model = (GtkTreeModel*)active_calltree->store;
466

Emmanuel Milou's avatar
Emmanuel Milou committed
467 468
  if (! gtk_tree_selection_get_selected (sel, &model, &iter))
    return;
469

Emmanuel Milou's avatar
Emmanuel Milou committed
470
  val.g_type = 0;
471
  gtk_tree_model_get_value (model, &iter, 2, &val);
472

Emmanuel Milou's avatar
Emmanuel Milou committed
473 474
  call_select(active_calltree, (call_t*) g_value_get_pointer(&val));
  g_value_unset(&val);
475

Emmanuel Milou's avatar
Emmanuel Milou committed
476
  toolbar_update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
477 478
}

479
/* A row is activated when it is double clicked */
480 481 482
void  row_activated(GtkTreeView       *tree_view UNUSED,
    GtkTreePath       *path UNUSED,
    GtkTreeViewColumn *column UNUSED,
483
    void * data UNUSED)
484
{
485 486
  g_print("double click action\n");
  call_t* selectedCall;
487 488
  call_t* new_call;
  gchar *to, *from, *account_id;
489 490
  selectedCall = call_get_selected( active_calltree );

Emmanuel Milou's avatar
Emmanuel Milou committed
491 492
  if (selectedCall)
  {
493 494
    // Get the right event from the right calltree
    if( active_calltree == current_calls )
Emmanuel Milou's avatar
Emmanuel Milou committed
495
    {
496
      switch(selectedCall->state)
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
      {
	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:
513
	  g_warning("Row activated - Should not happen!");
514 515
	  break;
      }
Emmanuel Milou's avatar
Emmanuel Milou committed
516
    }
517
    // if history
518 519
    else
    {
520 521 522 523 524 525 526 527 528
      to = g_strdup(call_get_number(selectedCall));
      from = g_strconcat("\"\" <", call_get_number(selectedCall), ">",NULL);
      account_id = g_strdup (selectedCall->accountID);

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

      call_list_add(current_calls, new_call);
      update_call_tree_add(current_calls, new_call);
      sflphone_place_call(new_call);
529
      switch_tab(current_calls);
530 531 532
    }
  }
}
533

534
  GtkWidget *
areversat's avatar
areversat committed
535 536
create_toolbar ()
{
Emmanuel Milou's avatar
Emmanuel Milou committed
537 538 539 540 541 542 543 544 545
  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);

546 547
  image = gtk_image_new_from_file( ICONS_DIR "/call.svg");
  callButton = gtk_tool_button_new (image, _("Place a call"));
548
#if GTK_CHECK_VERSION(2,12,0)
549
  gtk_widget_set_tooltip_text(GTK_WIDGET(callButton), _("Place a call"));
550
#endif
551 552 553
  g_signal_connect (G_OBJECT (callButton), "clicked",
      G_CALLBACK (call_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(callButton), -1);
554

555 556
  image = gtk_image_new_from_file( ICONS_DIR "/accept.svg");
  pickupButton = gtk_tool_button_new(image, _("Pick up"));
557
#if GTK_CHECK_VERSION(2,12,0)
558
  gtk_widget_set_tooltip_text(GTK_WIDGET(pickupButton), _("Pick up"));
559
#endif
560
  gtk_widget_set_state( GTK_WIDGET(pickupButton), GTK_STATE_INSENSITIVE);
561
  g_signal_connect(G_OBJECT (pickupButton), "clicked",
562 563
      G_CALLBACK (call_button), NULL);
  gtk_widget_show_all(GTK_WIDGET(pickupButton));
564

565 566
  image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg");
  hangupButton = gtk_tool_button_new (image, _("Hang up"));
567
#if GTK_CHECK_VERSION(2,12,0)
568
  gtk_widget_set_tooltip_text(GTK_WIDGET(hangupButton), _("Hang up"));
569
#endif
570 571 572
  gtk_widget_set_state( GTK_WIDGET(hangupButton), GTK_STATE_INSENSITIVE);
  g_signal_connect (G_OBJECT (hangupButton), "clicked",
      G_CALLBACK (hang_up), NULL);
573
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(hangupButton), -1);
574

575 576
  image = gtk_image_new_from_file( ICONS_DIR "/unhold.svg");
  unholdButton = gtk_tool_button_new (image, _("Off Hold"));
577
#if GTK_CHECK_VERSION(2,12,0)
578
  gtk_widget_set_tooltip_text(GTK_WIDGET(unholdButton), _("Off Hold"));
579
#endif
580 581 582 583 584 585 586 587
  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"));
588
#if GTK_CHECK_VERSION(2,12,0)
589
  gtk_widget_set_tooltip_text(GTK_WIDGET(holdButton), _("On Hold"));
590
#endif
591 592 593 594 595 596 597 598
  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);
599
#if GTK_CHECK_VERSION(2,12,0)
600
  gtk_widget_set_tooltip_text(GTK_WIDGET(transfertButton), _("Transfer"));
601
#endif
602 603 604 605
  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);
606
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(transfertButton), -1);
607 608

  image = gtk_image_new_from_file( ICONS_DIR "/history2.svg");
609
  historyButton = gtk_tool_button_new(image, _("History"));
610
#if GTK_CHECK_VERSION(2,12,0)
611
  gtk_widget_set_tooltip_text(GTK_WIDGET(historyButton), _("History"));
612
#endif
613
  g_signal_connect (G_OBJECT (historyButton), "clicked",
Julien Bonjean's avatar
Julien Bonjean committed
614
      G_CALLBACK (show_history_tab), NULL);
615
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(historyButton), -1);
616 617
  active_calltree = current_calls;

618
  image = gtk_image_new_from_file( ICONS_DIR "/addressbook.svg");
619
  contactButton = gtk_tool_button_new(image, _("Contacts"));
620 621 622
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(contactButton), _("Contacts"));
#endif
623
  g_signal_connect (G_OBJECT (contactButton), "clicked",
Julien Bonjean's avatar
Julien Bonjean committed
624
      G_CALLBACK (show_contacts_tab), NULL);
625 626
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(contactButton), -1);

627
  image = gtk_image_new_from_file( ICONS_DIR "/mailbox.svg");
Emmanuel Milou's avatar
Emmanuel Milou committed
628
  mailboxButton = gtk_tool_button_new( image , _("Voicemail"));
629 630
  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 );
631
#if GTK_CHECK_VERSION(2,12,0)
Emmanuel Milou's avatar
Emmanuel Milou committed
632
  gtk_widget_set_tooltip_text(GTK_WIDGET(mailboxButton), _("Voicemail"));
633
#endif
634 635 636
  g_signal_connect (G_OBJECT (mailboxButton), "clicked",
      G_CALLBACK (call_mailbox), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(mailboxButton), -1);
637

638
  recButton = gtk_tool_button_new_from_stock (GTK_STOCK_MEDIA_RECORD);
alexandresavard's avatar
alexandresavard committed
639 640 641
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(recButton), _("Record a call"));
#endif
642
  gtk_widget_set_state( GTK_WIDGET(recButton), GTK_STATE_INSENSITIVE);
alexandresavard's avatar
alexandresavard committed
643 644 645 646 647
  g_signal_connect (G_OBJECT (recButton), "clicked",
      G_CALLBACK (rec_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(recButton), -1);


648
  return ret;
649

650
}
651
static gboolean
652
on_key_released (GtkWidget   *widget UNUSED,
653
                GdkEventKey *event,
654
                gpointer     user_data UNUSED)
655 656
{
  // If a modifier key is pressed, it's a shortcut, pass along
657
  if(event->state & GDK_CONTROL_MASK ||
658 659 660 661 662 663 664 665 666 667 668 669 670 671
     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
672

673 674 675 676 677 678 679 680 681
/**
 * Reset call tree
 */
  void
reset_call_tree (calltab_t* tab)
{
  gtk_list_store_clear (tab->store);
}

682
  void
areversat's avatar
areversat committed
683 684
create_call_tree (calltab_t* tab)
{
Emmanuel Milou's avatar
Emmanuel Milou committed
685 686 687 688
  GtkWidget *sw;
  GtkCellRenderer *rend;
  GtkTreeViewColumn *col;
  GtkTreeSelection *sel;
689

690
  tab->tree = gtk_vbox_new(FALSE, 10);
691

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

Emmanuel Milou's avatar
Emmanuel Milou committed
694 695 696
  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);
697
  g_signal_connect (G_OBJECT ( sw ), "key-release-event",G_CALLBACK (on_key_released), NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
698

699 700
  tab->store = gtk_list_store_new (3,
      GDK_TYPE_PIXBUF,// Icon
Emmanuel Milou's avatar
Emmanuel Milou committed
701 702 703
      G_TYPE_STRING,  // Description
      G_TYPE_POINTER  // Pointer to the Object
      );
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
704

Emmanuel Milou's avatar
Emmanuel Milou committed
705
  tab->view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(tab->store));
706
  gtk_tree_view_set_enable_search( GTK_TREE_VIEW(tab->view), FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
707 708 709 710
  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);
711

712
  // Connect the popup menu
Emmanuel Milou's avatar
Emmanuel Milou committed
713
  g_signal_connect (G_OBJECT (tab->view), "popup-menu",
714
      G_CALLBACK (popup_menu),
Emmanuel Milou's avatar
Emmanuel Milou committed
715 716
      NULL);
  g_signal_connect (G_OBJECT (tab->view), "button-press-event",
717
      G_CALLBACK (button_pressed),
Emmanuel Milou's avatar
Emmanuel Milou committed
718 719
      NULL);

720

Emmanuel Milou's avatar
Emmanuel Milou committed
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
  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);

745
  gtk_widget_show(tab->tree);
Emmanuel Milou's avatar
Emmanuel Milou committed
746 747 748

  //toolbar_update_buttons();

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
749
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
750

751
  void
752
update_call_tree_remove (calltab_t* tab, call_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
753
{
Emmanuel Milou's avatar
Emmanuel Milou committed
754 755 756 757 758 759 760 761 762 763 764 765
  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;
766
      gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
Emmanuel Milou's avatar
Emmanuel Milou committed
767 768 769 770 771 772 773 774 775 776 777 778 779 780

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

783
  void
784
update_call_tree (calltab_t* tab, call_t * c)
785
{
786 787
    g_print("update call tree\n");
  GdkPixbuf *pixbuf=NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
788 789 790 791 792 793 794 795 796 797 798 799
  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;
800
      gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
Emmanuel Milou's avatar
Emmanuel Milou committed
801 802 803 804 805 806 807 808

      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
809 810
	gchar * date="";
	gchar * duration="";
Emmanuel Milou's avatar
Emmanuel Milou committed
811
	if(c->state == CALL_STATE_TRANSFERT)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
812
	{
813 814 815
	  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
816 817 818 819
	      c->to);
	}
	else
	{
820
	  description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>",
821
	      call_get_number(c),
822
	      call_get_name(c));
Emmanuel Milou's avatar
Emmanuel Milou committed
823
	}
824

825 826
	if( tab == current_calls )
	{
Emmanuel Milou's avatar
Emmanuel Milou committed
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
	  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);
849 850 851
              break;
            case CALL_STATE_RECORD:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/rec_call.svg", NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
852 853
	      break;
	    default:
854
	      g_warning("Update calltree - Should not happen!");
Emmanuel Milou's avatar
Emmanuel Milou committed
855
	  }
856
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
857 858
	else
	{
859 860 861
	  switch(c->history_state)
	  {
	    case OUTGOING:
Emmanuel Milou's avatar
Emmanuel Milou committed
862 863 864 865 866 867
	      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);
868 869
	      break;
	    case MISSED:
Emmanuel Milou's avatar
Emmanuel Milou committed
870 871
	      g_print("Missed state\n");
	      pixbuf = gdk_pixbuf_new_from_file( ICONS_DIR "/missed.svg", NULL);
872 873
	      break;
	    default:
874
	      g_print("No history state\n");
Emmanuel Milou's avatar
Emmanuel Milou committed
875
	      break;
876
	  }
877
	  date = timestamp_get_call_date();
Emmanuel Milou's avatar
Emmanuel Milou committed
878
	  duration = process_call_duration(c);
879 880
	  duration = g_strconcat( date , duration , NULL);
	  description = g_strconcat( description , duration, NULL);
881
	}
882 883 884
	//Resize it
	if(pixbuf)
	{
Emmanuel Milou's avatar
Emmanuel Milou committed
885 886 887 888
	  if(gdk_pixbuf_get_width(pixbuf) > 32 || gdk_pixbuf_get_height(pixbuf) > 32)
	  {
	    pixbuf =  gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
	  }
889
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
890 891 892 893
	gtk_list_store_set(store, &iter,
	    0, pixbuf, // Icon
	    1, description, // Description
	    -1);
894 895

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

898
      }
Emmanuel Milou's avatar
Emmanuel Milou committed
899 900
    }

901
  }
Emmanuel Milou's avatar
Emmanuel Milou committed
902 903 904
  toolbar_update_buttons();
}

905
  void
Emmanuel Milou's avatar
Emmanuel Milou committed
906 907 908 909 910
update_call_tree_add (calltab_t* tab, call_t * c)
{
  if( tab == history && ( call_list_get_size( tab ) > dbus_get_max_calls() ) )
    return;

911
  GdkPixbuf *pixbuf=NULL;