calltree.c 13.2 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
	{
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
152
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
    switch(selectedCall->state)  // TODO Make this a switch
  	{
  	  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
}


GtkWidget * 
create_call_tree (){
  GtkWidget *ret;
	GtkWidget *sw;
  GtkWidget *hbox;
	GtkWidget *image;
	GtkCellRenderer *rend;
	GtkTreeViewColumn *col;
	GtkTreeSelection *sel;
214
	
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
215
216
217
218
	ret = gtk_vbox_new(FALSE, 10); 
	gtk_container_set_border_width (GTK_CONTAINER (ret), 0);

	sw = gtk_scrolled_window_new( NULL, NULL);
219
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
220
221
222
223
224
225
226
227
228
229
	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));
230
  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
	
  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 */     
254
  hbox = gtk_hbox_new (FALSE, 5);       
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
255
  
256
  callButton = gtk_button_new ();
257
  gtk_widget_set_state( GTK_WIDGET(callButton), GTK_STATE_INSENSITIVE);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
258
  image = gtk_image_new_from_file( ICONS_DIR "/call.svg");
259
260
  gtk_button_set_image(GTK_BUTTON(callButton), image);
  //gtk_button_set_image_position( button, GTK_POS_TOP);
261
  gtk_box_pack_start (GTK_BOX (hbox), callButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
262
  g_signal_connect (G_OBJECT (callButton), "clicked",
263
                    G_CALLBACK (call_button), NULL);
264

265
  hangupButton = gtk_button_new ();
266
267
  gtk_widget_hide( hangupButton );
  gtk_widget_set_state( GTK_WIDGET(hangupButton), GTK_STATE_INSENSITIVE);
268
  gtk_box_pack_start (GTK_BOX (hbox), hangupButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
269
  image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg");
270
271
272
273
  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);
274
275
                      
  unholdButton = gtk_button_new ();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
276
  image = gtk_image_new_from_file( ICONS_DIR "/unhold.svg");
277
278
279
280
281
282
283
  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
284
  image = gtk_image_new_from_file( ICONS_DIR "/hold.svg");
285
  gtk_button_set_image(GTK_BUTTON(holdButton), image);
286
287
  gtk_widget_set_state( GTK_WIDGET(holdButton), GTK_STATE_INSENSITIVE);
  gtk_box_pack_end (GTK_BOX (hbox), holdButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
288
289
290
  g_signal_connect (G_OBJECT (holdButton), "clicked",
                    G_CALLBACK (hold), NULL);

291
  transfertButton = gtk_button_new ();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
292
  image = gtk_image_new_from_file( ICONS_DIR "/transfert.svg");
293
  gtk_button_set_image(GTK_BUTTON(transfertButton), image);
294
295
  gtk_widget_set_state( GTK_WIDGET(transfertButton), GTK_STATE_INSENSITIVE);
  gtk_box_pack_end (GTK_BOX (hbox), transfertButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
296
297
  g_signal_connect (G_OBJECT (transfertButton), "clicked",
                    G_CALLBACK (transfert), NULL);
298
299
300
301
                    
  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
302
303
304
305
306
307
	gtk_widget_show(ret); 
	
	return ret;
	
}
void 
308
update_call_tree_remove (call_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
309
310
{
	GtkTreeIter iter;
311
312
	GValue val;
	call_t * iterCall;
313
 
314
315
316
317
318
319
	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))
	  {
320
	    val.g_type = 0;
321
322
323
324
325
326
327
328
329
330
331
    	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);
      }
	  }
	}
332
	call_t * selectedCall = call_get_selected();
333
	if(selectedCall == c)
334
	  call_select(NULL);
335
336
	update_buttons();
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
337

338
339
340
341
342
343
344
345
346
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
347
  int i;
348
	for( i = 0; i < nbChild; i++)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
349
	{
350
351
	  if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i))
	  {
352
	    val.g_type = 0;
353
354
355
356
357
358
    	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
359
      {
360
361
        // Existing call in the list
        gchar * markup;
362
        markup = g_markup_printf_escaped("<b>%s</b>\n"
363
364
365
    						    "%s", 
    						    call_get_name(c), 
    						    call_get_number(c));
366
    		    		
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
367
    		switch(c->state)
368
    		{
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
369
      		case CALL_STATE_HOLD:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
370
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/hold.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
371
372
      		  break;
      		case CALL_STATE_RINGING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
373
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
374
375
      		  break;
      		case CALL_STATE_CURRENT:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
376
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/current.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
377
378
      		  break;
      		case CALL_STATE_DIALING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
379
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
380
381
      		  break;
      		case CALL_STATE_FAILURE:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
382
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/fail.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
383
384
      		  break;
      		case CALL_STATE_BUSY:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
385
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/busy.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
386
387
388
      		  break;
      		default:
      		  g_error("Should not happen!");
389
    		}
390
391
    	  //Resize it
        if(pixbuf)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
392
        {
393
394
395
396
          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
397
        }
398
    		gtk_list_store_set(store, &iter,
399
400
401
    				  0, pixbuf, // Icon
  		        1, markup, // Description
  		        -1);
402
403
404
405
406
407
    				   
    		if (pixbuf != NULL)
    			g_object_unref(G_OBJECT(pixbuf));
        
      } 
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
408
409
    
  } 
410
  update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
411
	//return row_ref;
412
413
414
415
416
417
418
419

}

void 
update_call_tree_add (call_t * c)
{
  GdkPixbuf *pixbuf;
	GtkTreeIter iter;
420
	GtkTreeSelection* sel;
421
422
423

  // New call in the list
  gchar * markup;
424
  markup = g_markup_printf_escaped("<b>%s</b>\n"
425
426
427
  				    "%s", 
  				    call_get_name(c), 
  				    call_get_number(c));
428
  
429
430
  gtk_list_store_append (store, &iter);

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
431
432
433
  switch(c->state)
	{
		case CALL_STATE_INCOMING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
434
		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
435
436
		  break;
		case CALL_STATE_DIALING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
437
		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
438
439
		  break;
		case CALL_STATE_RINGING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
440
		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
441
442
443
444
445
		  break;
		default:
		  g_error("Should not happen!");
	}
	
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
  //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);
464
465
  sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
  gtk_tree_selection_select_iter(GTK_TREE_SELECTION(sel), &iter);
466
  update_buttons();
467
	//return row_ref;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
468
}