calltree.c 12.9 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
{
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
41
  sflphone_pick_up();
42
43
44
}

/**
45
 * Hang up the line
46
47
 */
static void 
48
hang_up( GtkWidget *widget, gpointer   data )
49
{
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
50
  sflphone_hang_up();
51
52
53
}

/**
54
 * Hold the line
55
56
 */
static void 
57
hold( GtkWidget *widget, gpointer   data )
58
{
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
59
  sflphone_on_hold();
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
}

/**
 * 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");
  }
}

75
76
77
78
79
80
/**
 * Unhold call
 */
static void 
unhold( GtkWidget *widget, gpointer   data )
{
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
81
  sflphone_off_hold();
82
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
83

84
85
86
87
88
89
90
91
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
92
	
93
	call_t * selectedCall = call_get_selected();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
94
	if (selectedCall)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
95
	{
96
    switch(selectedCall->state) 
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  	{
  	  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;
  	}
  }
128
129
130
131
132
133
134
135
136
137
138
}
/* 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;
  
139
	val.g_type = 0;
140
141
	gtk_tree_model_get_value (model, &iter, 2, &val);
	
142
	call_select((call_t*) g_value_get_pointer(&val));
143
  g_value_unset(&val);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
144
  
145
  update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
146
147
}

148
149
150
151
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
/* 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
179
180
181
182
183
184
185
186
187
188

GtkWidget * 
create_call_tree (){
  GtkWidget *ret;
	GtkWidget *sw;
  GtkWidget *hbox;
	GtkWidget *image;
	GtkCellRenderer *rend;
	GtkTreeViewColumn *col;
	GtkTreeSelection *sel;
189
	
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
190
191
192
193
	ret = gtk_vbox_new(FALSE, 10); 
	gtk_container_set_border_width (GTK_CONTAINER (ret), 0);

	sw = gtk_scrolled_window_new( NULL, NULL);
194
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
195
196
197
198
199
200
201
202
203
204
	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));
205
  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
206
207
208
  g_signal_connect (G_OBJECT (view), "row-activated",
			  G_CALLBACK (row_activated),
			  NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
	
  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 */     
232
  hbox = gtk_hbox_new (FALSE, 5);       
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
233
  
234
  callButton = gtk_button_new ();
235
  gtk_widget_set_state( GTK_WIDGET(callButton), GTK_STATE_INSENSITIVE);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
236
  image = gtk_image_new_from_file( ICONS_DIR "/call.svg");
237
238
  gtk_button_set_image(GTK_BUTTON(callButton), image);
  //gtk_button_set_image_position( button, GTK_POS_TOP);
239
  gtk_box_pack_start (GTK_BOX (hbox), callButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
240
  g_signal_connect (G_OBJECT (callButton), "clicked",
241
                    G_CALLBACK (call_button), NULL);
242

243
  hangupButton = gtk_button_new ();
244
245
  gtk_widget_hide( hangupButton );
  gtk_widget_set_state( GTK_WIDGET(hangupButton), GTK_STATE_INSENSITIVE);
246
  gtk_box_pack_start (GTK_BOX (hbox), hangupButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
247
  image = gtk_image_new_from_file( ICONS_DIR "/hang_up.svg");
248
249
250
251
  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);
252
253
                      
  unholdButton = gtk_button_new ();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
254
  image = gtk_image_new_from_file( ICONS_DIR "/unhold.svg");
255
256
257
258
259
260
261
  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
262
  image = gtk_image_new_from_file( ICONS_DIR "/hold.svg");
263
  gtk_button_set_image(GTK_BUTTON(holdButton), image);
264
265
  gtk_widget_set_state( GTK_WIDGET(holdButton), GTK_STATE_INSENSITIVE);
  gtk_box_pack_end (GTK_BOX (hbox), holdButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
266
267
268
  g_signal_connect (G_OBJECT (holdButton), "clicked",
                    G_CALLBACK (hold), NULL);

269
  transfertButton = gtk_button_new ();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
270
  image = gtk_image_new_from_file( ICONS_DIR "/transfert.svg");
271
  gtk_button_set_image(GTK_BUTTON(transfertButton), image);
272
273
  gtk_widget_set_state( GTK_WIDGET(transfertButton), GTK_STATE_INSENSITIVE);
  gtk_box_pack_end (GTK_BOX (hbox), transfertButton, FALSE /*expand*/, FALSE /*fill*/, 0 /*padding*/);
274
275
  g_signal_connect (G_OBJECT (transfertButton), "clicked",
                    G_CALLBACK (transfert), NULL);
276
277
278
279
                    
  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
280
281
282
283
284
285
	gtk_widget_show(ret); 
	
	return ret;
	
}
void 
286
update_call_tree_remove (call_t * c)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
287
288
{
	GtkTreeIter iter;
289
290
	GValue val;
	call_t * iterCall;
291
 
292
293
294
295
296
297
	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))
	  {
298
	    val.g_type = 0;
299
300
301
302
303
304
305
306
307
308
309
    	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);
      }
	  }
	}
310
	call_t * selectedCall = call_get_selected();
311
	if(selectedCall == c)
312
	  call_select(NULL);
313
314
	update_buttons();
}
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
315

316
317
318
319
320
321
322
323
324
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
325
  int i;
326
	for( i = 0; i < nbChild; i++)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
327
	{
328
329
	  if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i))
	  {
330
	    val.g_type = 0;
331
332
333
334
335
336
    	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
337
      {
338
339
        // Existing call in the list
        gchar * markup;
340
        markup = g_markup_printf_escaped("<b>%s</b>\n"
341
342
343
    						    "%s", 
    						    call_get_name(c), 
    						    call_get_number(c));
344
    		    		
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
345
    		switch(c->state)
346
    		{
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
347
      		case CALL_STATE_HOLD:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
348
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/hold.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
349
350
      		  break;
      		case CALL_STATE_RINGING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
351
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
352
353
      		  break;
      		case CALL_STATE_CURRENT:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
354
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/current.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
355
356
      		  break;
      		case CALL_STATE_DIALING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
357
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
358
359
      		  break;
      		case CALL_STATE_FAILURE:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
360
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/fail.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
361
362
      		  break;
      		case CALL_STATE_BUSY:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
363
      		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/busy.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
364
365
366
      		  break;
      		default:
      		  g_error("Should not happen!");
367
    		}
368
369
    	  //Resize it
        if(pixbuf)
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
370
        {
371
372
373
374
          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
375
        }
376
    		gtk_list_store_set(store, &iter,
377
378
379
    				  0, pixbuf, // Icon
  		        1, markup, // Description
  		        -1);
380
381
382
383
384
385
    				   
    		if (pixbuf != NULL)
    			g_object_unref(G_OBJECT(pixbuf));
        
      } 
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
386
387
    
  } 
388
  update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
389
	//return row_ref;
390
391
392
393
394
395
396
397

}

void 
update_call_tree_add (call_t * c)
{
  GdkPixbuf *pixbuf;
	GtkTreeIter iter;
398
	GtkTreeSelection* sel;
399
400
401

  // New call in the list
  gchar * markup;
402
  markup = g_markup_printf_escaped("<b>%s</b>\n"
403
404
405
  				    "%s", 
  				    call_get_name(c), 
  				    call_get_number(c));
406
  
407
408
  gtk_list_store_append (store, &iter);

Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
409
410
411
  switch(c->state)
	{
		case CALL_STATE_INCOMING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
412
		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
413
414
		  break;
		case CALL_STATE_DIALING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
415
		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
416
417
		  break;
		case CALL_STATE_RINGING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
418
		  pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
419
420
421
422
423
		  break;
		default:
		  g_error("Should not happen!");
	}
	
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  //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);
442
443
  sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
  gtk_tree_selection_select_iter(GTK_TREE_SELECTION(sel), &iter);
444
  update_buttons();
445
	//return row_ref;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
446
}