calltree.c 26 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>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
5
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
10
11
12
13
14
15
16
17
18
19
20
 *  (at your option) any later version.
 *                                                                                
 *  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.
 *                                                                              
 *  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>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
30

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;
areversat's avatar
areversat committed
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()
{
Emmanuel Milou's avatar
Emmanuel Milou committed
49
50
51
  (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(historyButton)))? 
    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
 */
Emmanuel Milou's avatar
Emmanuel Milou committed
57
  static gboolean            
58
popup_menu (GtkWidget *widget,
59
    gpointer   user_data UNUSED)
60
61
62
63
{
  show_popup_menu(widget, NULL);
  return TRUE;
}            
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
 */
Emmanuel Milou's avatar
Emmanuel Milou committed
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
109
110
111
      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);
      g_sprintf(newCall->callID, "%d", rand()); 
      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
 */
Emmanuel Milou's avatar
Emmanuel Milou committed
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
 */
Emmanuel Milou's avatar
Emmanuel Milou committed
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
 */
Emmanuel Milou's avatar
Emmanuel Milou committed
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
 */
Emmanuel Milou's avatar
Emmanuel Milou committed
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
{
	GtkTreeSelection *sel;
	if(history_shown){
		active_calltree = current_calls;
		gtk_widget_hide(history->tree);
		gtk_widget_show(current_calls->tree);
		history_shown = FALSE;
	}else{
		active_calltree = history;
		gtk_widget_hide(current_calls->tree);
		gtk_widget_show(history->tree);
		history_shown = TRUE;
	}
	sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (active_calltree->view));
	g_signal_emit_by_name(sel, "changed");
	toolbar_update_buttons();
196
	gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(histfilter));
197

areversat's avatar
areversat committed
198
}
199
200

  static void
201
call_mailbox( GtkWidget* widget UNUSED, gpointer data UNUSED)
202
{
Emmanuel Milou's avatar
Emmanuel Milou committed
203
204
205
206
207
  account_t* current = account_list_get_current();
  if( current == NULL ) // Should not happens
    return; 
  call_t* mailboxCall = g_new0( call_t , 1);
  mailboxCall->state = CALL_STATE_DIALING;
208
  mailboxCall->to = g_strdup(g_hash_table_lookup(current->properties, ACCOUNT_MAILBOX));
Emmanuel Milou's avatar
Emmanuel Milou committed
209
  mailboxCall->from = g_markup_printf_escaped(_("\"Voicemail\" <%s>"),  mailboxCall->to);
Emmanuel Milou's avatar
Emmanuel Milou committed
210
211
212
  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
213
214
  mailboxCall->_start = 0;
  mailboxCall->_stop = 0;
Emmanuel Milou's avatar
Emmanuel Milou committed
215
216
217
218
219
  g_print("TO : %s\n" , mailboxCall->to);
  call_list_add( current_calls , mailboxCall );
  update_call_tree_add( current_calls , mailboxCall );    
  update_menus();
  sflphone_place_call( mailboxCall );
220
  if( active_calltree == history )  switch_tab();
221
222
}

alexandresavard's avatar
alexandresavard committed
223
224
225
226
227
228
229
230
231
232
233
234


/**
 * Static rec_button
 */
static void 
rec_button( GtkWidget *widget UNUSED, gpointer   data UNUSED)
{
  sflphone_rec_call();
}


Emmanuel Milou's avatar
Emmanuel Milou committed
235
  void 
236
toolbar_update_buttons ()
237
{
Emmanuel Milou's avatar
Emmanuel Milou committed
238
239
240
241
242
243
  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
244
  gtk_widget_set_sensitive( GTK_WIDGET(recButton),        FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
245
246
  g_object_ref(holdButton);
  g_object_ref(unholdButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
247
248
  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
249
250
251
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), holdButton, 3);
  g_object_ref(callButton);
  g_object_ref(pickupButton);
Emmanuel Milou's avatar
Emmanuel Milou committed
252
253
  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
254
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), callButton, 0);
alexandresavard's avatar
alexandresavard committed
255
  //gtk_toolbar_insert(GTK_TOOLBAR(toolbar), recButton, 0);
Emmanuel Milou's avatar
Emmanuel Milou committed
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277


  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)
  {
    switch(selectedCall->state) 
    {
      case CALL_STATE_INCOMING:
	gtk_widget_set_sensitive( GTK_WIDGET(pickupButton),     TRUE);
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),	TRUE);
	g_object_ref(callButton);	
	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);
278
279
	g_object_ref(holdButton);
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(holdButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
280
281
282
283
284
285
286
287
288
	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
289
290
	g_object_ref(callButton);
	gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(callButton));
Emmanuel Milou's avatar
Emmanuel Milou committed
291
292
293
294
295
296
297
	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
298
        gtk_widget_set_sensitive( GTK_WIDGET(recButton),        TRUE);
Emmanuel Milou's avatar
Emmanuel Milou committed
299
300
301
302
303
	break;
      case CALL_STATE_BUSY:
      case CALL_STATE_FAILURE:
	gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
	break; 
304
      case CALL_STATE_TRANSFERT:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
305
	gtk_signal_handler_block(GTK_OBJECT(transfertButton),transfertButtonConnId);
Emmanuel Milou's avatar
Emmanuel Milou committed
306
	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transfertButton), TRUE);
307
	gtk_signal_handler_unblock(transfertButton, transfertButtonConnId);
Emmanuel Milou's avatar
Emmanuel Milou committed
308
309
310
311
312
	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;
313
314
315
316
317
318
319
      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
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
      default:
	g_warning("Should not happen!");
	break;
    }
  }
  else 
  {
    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);
    }
  }
337
}
alexandresavard's avatar
alexandresavard committed
338
339
340



341
/* Call back when the user click on a call in the list */
Emmanuel Milou's avatar
Emmanuel Milou committed
342
  static void 
343
selected(GtkTreeSelection *sel, void* data UNUSED ) 
344
{
Emmanuel Milou's avatar
Emmanuel Milou committed
345
346
347
  GtkTreeIter  iter;
  GValue val;
  GtkTreeModel *model = (GtkTreeModel*)active_calltree->store;
348

Emmanuel Milou's avatar
Emmanuel Milou committed
349
350
  if (! gtk_tree_selection_get_selected (sel, &model, &iter))
    return;
351

Emmanuel Milou's avatar
Emmanuel Milou committed
352
  val.g_type = 0;
353
  gtk_tree_model_get_value (model, &iter, 2, &val);
354

Emmanuel Milou's avatar
Emmanuel Milou committed
355
356
  call_select(active_calltree, (call_t*) g_value_get_pointer(&val));
  g_value_unset(&val);
357

Emmanuel Milou's avatar
Emmanuel Milou committed
358
  toolbar_update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
359
360
}

361
/* A row is activated when it is double clicked */
362
363
364
365
void  row_activated(GtkTreeView       *tree_view UNUSED,
    GtkTreePath       *path UNUSED,
    GtkTreeViewColumn *column UNUSED,
    void * data UNUSED) 
366
{
367
368
369
370
371
  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
372
373
  if (selectedCall)
  {
374
375
    // Get the right event from the right calltree
    if( active_calltree == current_calls )
Emmanuel Milou's avatar
Emmanuel Milou committed
376
    {
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
      switch(selectedCall->state)  
      {
	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
397
    }
398
399
400
401
402
403
404
405
406
407
    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);
      g_sprintf(newCall->callID, "%d", rand()); 
      newCall->_start = 0;
      newCall->_stop = 0;
408

409
410
411
412
413
414
415
416
      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();
    }
  }
}
417

Emmanuel Milou's avatar
Emmanuel Milou committed
418
  GtkWidget * 
areversat's avatar
areversat committed
419
420
create_toolbar ()
{
Emmanuel Milou's avatar
Emmanuel Milou committed
421
422
423
424
425
426
427
428
429
  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);

430
431
  image = gtk_image_new_from_file( ICONS_DIR "/call.svg");
  callButton = gtk_tool_button_new (image, _("Place a call"));
432
#if GTK_CHECK_VERSION(2,12,0)
433
  gtk_widget_set_tooltip_text(GTK_WIDGET(callButton), _("Place a call"));
434
#endif
435
436
437
  g_signal_connect (G_OBJECT (callButton), "clicked",
      G_CALLBACK (call_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(callButton), -1);
438

439
440
  image = gtk_image_new_from_file( ICONS_DIR "/accept.svg");
  pickupButton = gtk_tool_button_new(image, _("Pick up"));
441
#if GTK_CHECK_VERSION(2,12,0)
442
  gtk_widget_set_tooltip_text(GTK_WIDGET(pickupButton), _("Pick up"));
443
#endif
444
445
446
447
  gtk_widget_set_state( GTK_WIDGET(pickupButton), GTK_STATE_INSENSITIVE);
  g_signal_connect(G_OBJECT (pickupButton), "clicked", 
      G_CALLBACK (call_button), NULL);
  gtk_widget_show_all(GTK_WIDGET(pickupButton));
448

449
450
  image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg");
  hangupButton = gtk_tool_button_new (image, _("Hang up"));
451
#if GTK_CHECK_VERSION(2,12,0)
452
  gtk_widget_set_tooltip_text(GTK_WIDGET(hangupButton), _("Hang up"));
453
#endif
454
455
456
457
  gtk_widget_set_state( GTK_WIDGET(hangupButton), GTK_STATE_INSENSITIVE);
  g_signal_connect (G_OBJECT (hangupButton), "clicked",
      G_CALLBACK (hang_up), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(hangupButton), -1);  
458

459
460
  image = gtk_image_new_from_file( ICONS_DIR "/unhold.svg");
  unholdButton = gtk_tool_button_new (image, _("Off Hold"));
461
#if GTK_CHECK_VERSION(2,12,0)
462
  gtk_widget_set_tooltip_text(GTK_WIDGET(unholdButton), _("Off Hold"));
463
#endif
464
465
466
467
468
469
470
471
  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"));
472
#if GTK_CHECK_VERSION(2,12,0)
473
  gtk_widget_set_tooltip_text(GTK_WIDGET(holdButton), _("On Hold"));
474
#endif
475
476
477
478
479
480
481
482
  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);
483
#if GTK_CHECK_VERSION(2,12,0)
484
  gtk_widget_set_tooltip_text(GTK_WIDGET(transfertButton), _("Transfer"));
485
#endif
486
487
488
489
490
491
492
493
494
  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);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(transfertButton), -1);  

  image = gtk_image_new_from_file( ICONS_DIR "/history2.svg");
  historyButton = gtk_toggle_tool_button_new();
  gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(historyButton), image);
495
#if GTK_CHECK_VERSION(2,12,0)
496
  gtk_widget_set_tooltip_text(GTK_WIDGET(historyButton), _("History"));
497
#endif
498
499
500
501
502
503
504
505
  gtk_tool_button_set_label(GTK_TOOL_BUTTON(historyButton), _("History"));
  g_signal_connect (G_OBJECT (historyButton), "toggled",
      G_CALLBACK (toggle_history), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(historyButton), -1);  
  history_shown = FALSE;
  active_calltree = current_calls;

  image = gtk_image_new_from_file( ICONS_DIR "/mailbox.svg");
Emmanuel Milou's avatar
Emmanuel Milou committed
506
  mailboxButton = gtk_tool_button_new( image , _("Voicemail"));
507
508
  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 );
509
#if GTK_CHECK_VERSION(2,12,0)
Emmanuel Milou's avatar
Emmanuel Milou committed
510
  gtk_widget_set_tooltip_text(GTK_WIDGET(mailboxButton), _("Voicemail"));
511
#endif
512
513
514
  g_signal_connect (G_OBJECT (mailboxButton), "clicked",
      G_CALLBACK (call_mailbox), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(mailboxButton), -1);
515

alexandresavard's avatar
alexandresavard committed
516
  
517
518
519
  //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
520
521
522
#if GTK_CHECK_VERSION(2,12,0)
  gtk_widget_set_tooltip_text(GTK_WIDGET(recButton), _("Record a call"));
#endif
523
  gtk_widget_set_state( GTK_WIDGET(recButton), GTK_STATE_INSENSITIVE);
alexandresavard's avatar
alexandresavard committed
524
525
526
527
528
  g_signal_connect (G_OBJECT (recButton), "clicked",
      G_CALLBACK (rec_button), NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(recButton), -1);


529
  return ret;
530
531

}  
532
static gboolean
533
on_key_released (GtkWidget   *widget UNUSED,
534
                GdkEventKey *event,
535
                gpointer     user_data UNUSED)  
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
{
  // If a modifier key is pressed, it's a shortcut, pass along
  if(event->state & GDK_CONTROL_MASK || 
     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
553

Emmanuel Milou's avatar
Emmanuel Milou committed
554
  void 
areversat's avatar
areversat committed
555
556
create_call_tree (calltab_t* tab)
{
Emmanuel Milou's avatar
Emmanuel Milou committed
557
558
559
560
  GtkWidget *sw;
  GtkCellRenderer *rend;
  GtkTreeViewColumn *col;
  GtkTreeSelection *sel;
561

Emmanuel Milou's avatar
Emmanuel Milou committed
562
  tab->tree = gtk_vbox_new(FALSE, 10); 
563

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

Emmanuel Milou's avatar
Emmanuel Milou committed
566
567
568
  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);
569
  g_signal_connect (G_OBJECT ( sw ), "key-release-event",G_CALLBACK (on_key_released), NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
570

571
  tab->store = gtk_list_store_new (3, 
Emmanuel Milou's avatar
Emmanuel Milou committed
572
573
574
575
      GDK_TYPE_PIXBUF,// Icon 
      G_TYPE_STRING,  // Description
      G_TYPE_POINTER  // Pointer to the Object
      );
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
576

Emmanuel Milou's avatar
Emmanuel Milou committed
577
  tab->view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(tab->store));
578
  gtk_tree_view_set_enable_search( GTK_TREE_VIEW(tab->view), FALSE);
Emmanuel Milou's avatar
Emmanuel Milou committed
579
580
581
582
  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);
583

584
  // Connect the popup menu
Emmanuel Milou's avatar
Emmanuel Milou committed
585
586
587
588
589
590
591
  g_signal_connect (G_OBJECT (tab->view), "popup-menu",
      G_CALLBACK (popup_menu), 
      NULL);
  g_signal_connect (G_OBJECT (tab->view), "button-press-event",
      G_CALLBACK (button_pressed), 
      NULL);

592

Emmanuel Milou's avatar
Emmanuel Milou committed
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
  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);

  gtk_widget_show(tab->tree); 

  //toolbar_update_buttons();

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
621
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
622

Emmanuel Milou's avatar
Emmanuel Milou committed
623
  void 
624
update_call_tree_remove (calltab_t* tab, call_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
625
{
Emmanuel Milou's avatar
Emmanuel Milou committed
626
627
628
629
630
631
632
633
634
635
636
637
  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;
638
      gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
Emmanuel Milou's avatar
Emmanuel Milou committed
639
640
641
642
643
644
645
646
647
648
649
650
651
652

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

Emmanuel Milou's avatar
Emmanuel Milou committed
655
  void 
656
update_call_tree (calltab_t* tab, call_t * c)
657
{
658
659
    g_print("update call tree\n");
  GdkPixbuf *pixbuf=NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
660
661
662
663
664
665
666
667
668
669
670
671
  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;
672
      gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
Emmanuel Milou's avatar
Emmanuel Milou committed
673
674
675
676
677
678
679
680

      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
681
682
	gchar * date="";
	gchar * duration="";
Emmanuel Milou's avatar
Emmanuel Milou committed
683
	if(c->state == CALL_STATE_TRANSFERT)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
684
	{
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
685
	  description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>\n<i>Transfert to:</i> %s",  
Emmanuel Milou's avatar
Emmanuel Milou committed
686
	      call_get_number(c), 
687
	      call_get_name(c), 
Emmanuel Milou's avatar
Emmanuel Milou committed
688
689
690
691
	      c->to);
	}
	else
	{
692
693
694
	  description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>", 
	      call_get_number(c),
	      call_get_name(c)); 
Emmanuel Milou's avatar
Emmanuel Milou committed
695
	}
696

697
698
	if( tab == current_calls )
	{
Emmanuel Milou's avatar
Emmanuel Milou committed
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
	  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);
721
722
723
              break;
            case CALL_STATE_RECORD:
	      pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/rec_call.svg", NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
724
725
726
727
	      break;
	    default:
	      g_warning("Should not happen!");
	  }
728
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
729
730
	else
	{
731
732
733
	  switch(c->history_state)
	  {
	    case OUTGOING:
Emmanuel Milou's avatar
Emmanuel Milou committed
734
735
736
737
738
739
	      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);
740
741
	      break;
	    case MISSED:
Emmanuel Milou's avatar
Emmanuel Milou committed
742
743
	      g_print("Missed state\n");
	      pixbuf = gdk_pixbuf_new_from_file( ICONS_DIR "/missed.svg", NULL);
744
745
	      break;
	    default:
Emmanuel Milou's avatar
Emmanuel Milou committed
746
747
	      g_print("No history state\n");  
	      break;
748
	  }
Emmanuel Milou's avatar
Emmanuel Milou committed
749
750
	  date = timestamp_get_call_date(); 
	  duration = process_call_duration(c);
751
752
	  duration = g_strconcat( date , duration , NULL);
	  description = g_strconcat( description , duration, NULL);
753
	}
754
755
756
	//Resize it
	if(pixbuf)
	{
Emmanuel Milou's avatar
Emmanuel Milou committed
757
758
759
760
	  if(gdk_pixbuf_get_width(pixbuf) > 32 || gdk_pixbuf_get_height(pixbuf) > 32)
	  {
	    pixbuf =  gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
	  }
761
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
762
763
764
765
	gtk_list_store_set(store, &iter,
	    0, pixbuf, // Icon
	    1, description, // Description
	    -1);
766
767

	if (pixbuf != NULL)
Emmanuel Milou's avatar
Emmanuel Milou committed
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
	  g_object_unref(G_OBJECT(pixbuf));

      } 
    }

  } 
  toolbar_update_buttons();
}

  void 
update_call_tree_add (calltab_t* tab, call_t * c)
{
  if( tab == history && ( call_list_get_size( tab ) > dbus_get_max_calls() ) )
    return;

783
  GdkPixbuf *pixbuf=NULL;
Emmanuel Milou's avatar
Emmanuel Milou committed
784
785
786
787
  GtkTreeIter iter;
  GtkTreeSelection* sel;

  // New call in the list
Emmanuel Milou's avatar
Emmanuel Milou committed
788
  gchar * description;
Emmanuel Milou's avatar
Emmanuel Milou committed
789
  gchar * date="";
Emmanuel Milou's avatar
Emmanuel Milou committed
790
  description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>", 
791
792
      call_get_number(c),
      call_get_name(c)); 
Emmanuel Milou's avatar
Emmanuel Milou committed
793

794

Emmanuel Milou's avatar
Emmanuel Milou committed
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
  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:
827
	g_warning("History - Should not happen!");
Emmanuel Milou's avatar
Emmanuel Milou committed
828
    }
Emmanuel Milou's avatar
Emmanuel Milou committed
829
830
    date = timestamp_get_call_date(); 
    description = g_strconcat( date , description , NULL);
Emmanuel Milou's avatar
Emmanuel Milou committed
831
  }
832

Emmanuel Milou's avatar
Emmanuel Milou committed
833
834
835
836
837
838
839
840
841
842
  //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
843
      1, description, // Description
844
      2, c,      // Pointer
Emmanuel Milou's avatar
Emmanuel Milou committed
845
846
847
848
849
      -1);

  if (pixbuf != NULL)
    g_object_unref(G_OBJECT(pixbuf));

850

Emmanuel Milou's avatar
Emmanuel Milou committed
851
852
853
  sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tab->view));
  gtk_tree_selection_select_iter(GTK_TREE_SELECTION(sel), &iter);
  toolbar_update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
854
}