calltree.c 14.1 KB
Newer Older
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 *  Copyright (C) 2007 Savoir-Faire Linux inc.
 *  Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>
 *                                                                              
 *  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
 *  the Free Software Foundation; either version 2 of the License, or
 *  (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.
 */

#include <gtk/gtk.h>
21
#include <actions.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
22
23
#include <calltree.h>
#include <calllist.h>
24
#include <dbus.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
25
26

GtkListStore * store;
27
28
GtkWidget *view;

29
30
GtkWidget * callButton;
GtkWidget * hangupButton;
31
GtkWidget * holdButton;
32
GtkWidget * transfertButton;
33
GtkWidget * unholdButton;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
34

35
/**
36
 * Make a call
37
38
 */
static void 
39
call_button( GtkWidget *widget, gpointer   data )
40
{
41
  call_t * selectedCall = call_get_selected();
42
  if(selectedCall)
43
  {
44
45
46
    switch(selectedCall->state)
    {
      case CALL_STATE_DIALING:
47
        sflphone_place_call (selectedCall);
48
49
50
51
        break;
      case CALL_STATE_INCOMING:
        dbus_accept (selectedCall);
        break;
52
53
54
      default:
        g_error("Should not happen!");
        break;
55
    }
56
57
58
59
  }
}

/**
60
 * Hang up the line
61
62
 */
static void 
63
hang_up( GtkWidget *widget, gpointer   data )
64
{
65
  call_t * selectedCall = call_get_selected();
66
  if(selectedCall)
67
  {
68
69
70
71
72
    switch(selectedCall->state)
    {
      case CALL_STATE_CURRENT:
      case CALL_STATE_HOLD:
      case CALL_STATE_DIALING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
73
      case CALL_STATE_RINGING:
74
75
76
77
78
        dbus_hang_up (selectedCall);
        break;
      case CALL_STATE_INCOMING:  
        dbus_refuse (selectedCall);
        break;
79
80
81
      default:
        g_error("Should not happen!");
        break;
82
    }
83
84
85
86
  }
}

/**
87
 * Hold the line
88
89
 */
static void 
90
hold( GtkWidget *widget, gpointer   data )
91
{
92
  call_t * selectedCall = call_get_selected();
93
  if(selectedCall)
94
  {
95
96
97
98
99
    switch(selectedCall->state)
    {
      case CALL_STATE_CURRENT:
        dbus_hold (selectedCall);
        break;
100
101
102
      default:
        g_error("Should not happen!");
        break;
103
    }
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  }
}

/**
 * Transfert the line
 */
static void 
transfert( GtkWidget *widget, gpointer   data )
{
  call_t * c = (call_t*) call_list_get_by_state (CALL_STATE_CURRENT);
  if(c)
  {
    dbus_transfert(c,"124");
  }
}

120
121
122
123
124
125
/**
 * Unhold call
 */
static void 
unhold( GtkWidget *widget, gpointer   data )
{
126
  call_t * selectedCall = call_get_selected();
127
128
129
130
131
132
133
  if(selectedCall)
  {
    switch(selectedCall->state)
    {
      case CALL_STATE_HOLD:
        dbus_unhold (selectedCall);
        break;
134
135
136
      default:
        g_error("Should not happen!");
        break;
137
138
139
140
141
142
143
144
145
146
147
      }
  }
}
void 
update_buttons ()
{
  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(unholdButton),     FALSE);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
148
	
149
	call_t * selectedCall = call_get_selected();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
150
	if (selectedCall)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
151
	{
152
    switch(selectedCall->state) 
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
  	{
  	  case CALL_STATE_INCOMING:
        gtk_widget_set_sensitive( GTK_WIDGET(callButton),       TRUE);
        gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
        break;
      case CALL_STATE_HOLD:
    	  gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
        gtk_widget_set_sensitive( GTK_WIDGET(unholdButton),     TRUE);
        break;
      case CALL_STATE_RINGING:
    	  gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
        break;
      case CALL_STATE_DIALING:
        gtk_widget_set_sensitive( GTK_WIDGET(callButton),       TRUE);
        gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
        break;
      case CALL_STATE_CURRENT:
        gtk_widget_show( hangupButton );
        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;
      case CALL_STATE_BUSY:
      case CALL_STATE_FAILURE:
        gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
        break; 
  	  default:
  	    g_error("Should not happen!");
  	    break;
  	}
  }
184
185
186
187
188
189
190
191
192
193
194
}
/* Call back when the user click on a call in the list */
static void 
selected(GtkTreeSelection *sel, GtkTreeModel *model) 
{
	GtkTreeIter  iter;
	GValue val;
	
	if (! gtk_tree_selection_get_selected (sel, &model, &iter))
		return;
  
195
	val.g_type = 0;
196
197
	gtk_tree_model_get_value (model, &iter, 2, &val);
	
198
	call_select((call_t*) g_value_get_pointer(&val));
199
  g_value_unset(&val);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
200
  
201
  update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
202
203
}

204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/* A row is activated when it is double clicked */
void  row_activated(GtkTreeView       *tree_view,
                    GtkTreePath       *path,
                    GtkTreeViewColumn *column,
                    void * foo) 
{
  call_t * selectedCall = call_get_selected();
	if (selectedCall)
	{
    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_error("Should not happen!");
  	    break;
  	}
  }
}                    
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
235
236
237
238
239
240
241
242
243
244

GtkWidget * 
create_call_tree (){
  GtkWidget *ret;
	GtkWidget *sw;
  GtkWidget *hbox;
	GtkWidget *image;
	GtkCellRenderer *rend;
	GtkTreeViewColumn *col;
	GtkTreeSelection *sel;
245
	
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
246
247
248
249
	ret = gtk_vbox_new(FALSE, 10); 
	gtk_container_set_border_width (GTK_CONTAINER (ret), 0);

	sw = gtk_scrolled_window_new( NULL, NULL);
250
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
251
252
253
254
255
256
257
258
259
260
	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);

	store = gtk_list_store_new (3, 
	  GDK_TYPE_PIXBUF,// Icon 
	  G_TYPE_STRING,  // Description
	  G_TYPE_POINTER  // Pointer to the Object
	  );


	view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store));
261
  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
262
263
264
  g_signal_connect (G_OBJECT (view), "row-activated",
			  G_CALLBACK (row_activated),
			  NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
	
  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(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(view), col);
	g_object_unref(G_OBJECT(store));
	gtk_container_add(GTK_CONTAINER(sw), view);

  sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
  g_signal_connect (G_OBJECT (sel), "changed",
			  G_CALLBACK (selected),
			  store);
  
  /* Action button */     
288
  hbox = gtk_hbox_new (FALSE, 5);       
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
289
  
290
  callButton = gtk_button_new ();
291
  gtk_widget_set_state( GTK_WIDGET(callButton), GTK_STATE_INSENSITIVE);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
292
  image = gtk_image_new_from_file( ICONS_DIR "/call.svg");
293
294
  gtk_button_set_image(GTK_BUTTON(callButton), image);
  //gtk_button_set_image_position( button, GTK_POS_TOP);
295
  gtk_box_pack_start (GTK_BOX (hbox), callButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
296
  g_signal_connect (G_OBJECT (callButton), "clicked",
297
                    G_CALLBACK (call_button), NULL);
298

299
  hangupButton = gtk_button_new ();
300
301
  gtk_widget_hide( hangupButton );
  gtk_widget_set_state( GTK_WIDGET(hangupButton), GTK_STATE_INSENSITIVE);
302
  gtk_box_pack_start (GTK_BOX (hbox), hangupButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
303
  image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg");
304
305
306
307
  gtk_button_set_image(GTK_BUTTON(hangupButton), image);
  //gtk_button_set_image_position( button, GTK_POS_TOP);
  g_signal_connect (G_OBJECT (hangupButton), "clicked",
                    G_CALLBACK (hang_up), NULL);
308
309
                      
  unholdButton = gtk_button_new ();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
310
  image = gtk_image_new_from_file( ICONS_DIR "/unhold.svg");
311
312
313
314
315
316
317
  gtk_button_set_image(GTK_BUTTON(unholdButton), image);
  gtk_widget_set_state( GTK_WIDGET(unholdButton), GTK_STATE_INSENSITIVE);
  gtk_box_pack_end (GTK_BOX (hbox), unholdButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
  g_signal_connect (G_OBJECT (unholdButton), "clicked",
                    G_CALLBACK (unhold), NULL);
             
  holdButton = gtk_button_new ();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
318
  image = gtk_image_new_from_file( ICONS_DIR "/hold.svg");
319
  gtk_button_set_image(GTK_BUTTON(holdButton), image);
320
321
  gtk_widget_set_state( GTK_WIDGET(holdButton), GTK_STATE_INSENSITIVE);
  gtk_box_pack_end (GTK_BOX (hbox), holdButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
322
323
324
  g_signal_connect (G_OBJECT (holdButton), "clicked",
                    G_CALLBACK (hold), NULL);

325
  transfertButton = gtk_button_new ();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
326
  image = gtk_image_new_from_file( ICONS_DIR "/transfert.svg");
327
  gtk_button_set_image(GTK_BUTTON(transfertButton), image);
328
329
  gtk_widget_set_state( GTK_WIDGET(transfertButton), GTK_STATE_INSENSITIVE);
  gtk_box_pack_end (GTK_BOX (hbox), transfertButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
330
331
  g_signal_connect (G_OBJECT (transfertButton), "clicked",
                    G_CALLBACK (transfert), NULL);
332
333
334
335
                    
  gtk_box_pack_start (GTK_BOX (ret), hbox, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
  gtk_box_pack_start(GTK_BOX(ret), sw, TRUE, TRUE, 0);
	
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
336
337
338
339
340
341
	gtk_widget_show(ret); 
	
	return ret;
	
}
void 
342
update_call_tree_remove (call_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
343
344
{
	GtkTreeIter iter;
345
346
	GValue val;
	call_t * iterCall;
347
 
348
349
350
351
352
353
	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))
	  {
354
	    val.g_type = 0;
355
356
357
358
359
360
361
362
363
364
365
    	gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
    	
    	iterCall = (call_t*) g_value_get_pointer(&val);
      g_value_unset(&val);
      
      if(iterCall == c)
      {
        gtk_list_store_remove(store, &iter);
      }
	  }
	}
366
	call_t * selectedCall = call_get_selected();
367
	if(selectedCall == c)
368
	  call_select(NULL);
369
370
	update_buttons();
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
371

372
373
374
375
376
377
378
379
380
void 
update_call_tree (call_t * c)
{
  GdkPixbuf *pixbuf;
  GtkTreeIter iter;
	GValue val;
	call_t * iterCall;
	
	int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
381
  int i;
382
	for( i = 0; i < nbChild; i++)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
383
	{
384
385
	  if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i))
	  {
386
	    val.g_type = 0;
387
388
389
390
391
392
    	gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, 2, &val);
    	
    	iterCall = (call_t*) g_value_get_pointer(&val);
      g_value_unset(&val);
      
      if(iterCall == c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
393
      {
394
395
        // Existing call in the list
        gchar * markup;
396
        markup = g_markup_printf_escaped("<b>%s</b>\n"
397
398
399
    						    "%s", 
    						    call_get_name(c), 
    						    call_get_number(c));
400
    		    		
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
401
    		switch(c->state)
402
    		{
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
403
      		case CALL_STATE_HOLD:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
404
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/hold.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
405
406
      		  break;
      		case CALL_STATE_RINGING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
407
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
408
409
      		  break;
      		case CALL_STATE_CURRENT:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
410
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/current.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
411
412
      		  break;
      		case CALL_STATE_DIALING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
413
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
414
415
      		  break;
      		case CALL_STATE_FAILURE:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
416
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/fail.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
417
418
      		  break;
      		case CALL_STATE_BUSY:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
419
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/busy.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
420
421
422
      		  break;
      		default:
      		  g_error("Should not happen!");
423
    		}
424
425
    	  //Resize it
        if(pixbuf)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
426
        {
427
428
429
430
          if(gdk_pixbuf_get_width(pixbuf) > 32 || gdk_pixbuf_get_height(pixbuf) > 32)
          {
            pixbuf =  gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
          }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
431
        }
432
    		gtk_list_store_set(store, &iter,
433
434
435
    				  0, pixbuf, // Icon
  		        1, markup, // Description
  		        -1);
436
437
438
439
440
441
    				   
    		if (pixbuf != NULL)
    			g_object_unref(G_OBJECT(pixbuf));
        
      } 
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
442
443
    
  } 
444
  update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
445
	//return row_ref;
446
447
448
449
450
451
452
453

}

void 
update_call_tree_add (call_t * c)
{
  GdkPixbuf *pixbuf;
	GtkTreeIter iter;
454
	GtkTreeSelection* sel;
455
456
457

  // New call in the list
  gchar * markup;
458
  markup = g_markup_printf_escaped("<b>%s</b>\n"
459
460
461
  				    "%s", 
  				    call_get_name(c), 
  				    call_get_number(c));
462
  
463
464
  gtk_list_store_append (store, &iter);

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
465
466
467
  switch(c->state)
	{
		case CALL_STATE_INCOMING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
468
		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
469
470
		  break;
		case CALL_STATE_DIALING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
471
		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
472
473
		  break;
		case CALL_STATE_RINGING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
474
		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
475
476
477
478
479
		  break;
		default:
		  g_error("Should not happen!");
	}
	
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
  //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(store, &iter,
  		   0, pixbuf, // Icon
  		   1, markup, // Description
  		   2, c,      // Pointer
  		   -1);
  		   
  if (pixbuf != NULL)
  	g_object_unref(G_OBJECT(pixbuf));

  //g_free(markup);
498
499
  sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
  gtk_tree_selection_select_iter(GTK_TREE_SELECTION(sel), &iter);
500
  update_buttons();
501
	//return row_ref;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
502
}