calltree.c 12.7 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
21
22
/*
 *  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>
#include <calltree.h>
#include <calllist.h>
23
#include <dbus.h>
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
24
25

GtkListStore * store;
26
27
GtkWidget *view;

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

call_t * selectedCall;

36
/**
37
 * Make a call
38
39
 */
static void 
40
call_button( GtkWidget *widget, gpointer   data )
41
{
42
  if(selectedCall)
43
  {
44
45
46
47
48
49
50
51
    switch(selectedCall->state)
    {
      case CALL_STATE_DIALING:
        dbus_place_call (selectedCall);
        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
  if(selectedCall)
66
  {
67
68
69
70
71
    switch(selectedCall->state)
    {
      case CALL_STATE_CURRENT:
      case CALL_STATE_HOLD:
      case CALL_STATE_DIALING:
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
72
      case CALL_STATE_RINGING:
73
74
75
76
77
        dbus_hang_up (selectedCall);
        break;
      case CALL_STATE_INCOMING:  
        dbus_refuse (selectedCall);
        break;
78
79
80
      default:
        g_error("Should not happen!");
        break;
81
    }
82
83
84
85
  }
}

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

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

118
119
120
121
122
123
124
125
126
127
128
129
130
/**
 * Unhold call
 */
static void 
unhold( GtkWidget *widget, gpointer   data )
{
  if(selectedCall)
  {
    switch(selectedCall->state)
    {
      case CALL_STATE_HOLD:
        dbus_unhold (selectedCall);
        break;
131
132
133
      default:
        g_error("Should not happen!");
        break;
134
135
136
137
138
139
140
141
142
143
144
      }
  }
}
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
145
	
146
	if(selectedCall)  // TODO Make this a switch
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
147
148
149
	{
	  if( selectedCall->state == CALL_STATE_INCOMING)
	  {
150
151
      gtk_widget_set_sensitive( GTK_WIDGET(callButton),       TRUE);
      gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
152
153
154
    }
    else if( selectedCall->state == CALL_STATE_HOLD)
	  {
155
      gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
156
      gtk_widget_set_sensitive( GTK_WIDGET(unholdButton),     TRUE);
157
158
159
160
    }
    else if( selectedCall->state == CALL_STATE_RINGING)
	  {
      gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
161
    }
162
163
164
    else if(selectedCall->state == CALL_STATE_DIALING)
    {
      gtk_widget_set_sensitive( GTK_WIDGET(callButton),       TRUE);
165
      gtk_widget_set_sensitive( GTK_WIDGET(hangupButton),     TRUE);
166
167
168
169
170
171
172
173
174
175
176
177
178
    }
    else if (selectedCall->state == CALL_STATE_CURRENT)
    {
      //gtk_widget_hide( callButton  );
      /* Hack : if hangupButton is put on the window in create_screen()
       * the hbox will request space for 4 buttons making the window larger than needed */
      //gtk_box_pack_start (GTK_BOX (hbox), hangupButton, TRUE /*expand*/, TRUE /*fill*/, 10 /*padding*/);
      //gtk_box_reorder_child(GTK_BOX (hbox), hangupButton, 0);
      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);
    }
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
179
180
	  
	}
181
182
183
184
185
186
187
188
189
190
191
}
/* 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;
  
192
	val.g_type = 0;
193
194
195
196
	gtk_tree_model_get_value (model, &iter, 2, &val);
	
	selectedCall = (call_t*) g_value_get_pointer(&val);
  g_value_unset(&val);
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
197
  
198
  update_buttons();
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
199
200
201
202
203
204
205
206
207
208
209
210
}


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

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

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

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

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

}

void 
update_call_tree_add (call_t * c)
{
  GdkPixbuf *pixbuf;
	GtkTreeIter iter;
409
	GtkTreeSelection* sel;
410
411
412

  // New call in the list
  gchar * markup;
413
  markup = g_markup_printf_escaped("<b>%s</b>\n"
414
415
416
  				    "%s", 
  				    call_get_name(c), 
  				    call_get_number(c));
417
  
418
419
  gtk_list_store_append (store, &iter);

420
  if (c->state == CALL_STATE_INCOMING)
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  {
    pixbuf = gdk_pixbuf_new_from_file(PIXMAPS_DIR "/ring.svg", NULL);
  }
  else if (c->state == CALL_STATE_DIALING)
  {
    pixbuf = gdk_pixbuf_new_from_file(PIXMAPS_DIR "/dial.svg", NULL);
  }
  //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);
446
447
  sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
  gtk_tree_selection_select_iter(GTK_TREE_SELECTION(sel), &iter);
448
  update_buttons();
449
	//return row_ref;
Pierre-Luc Beaudoin's avatar
Pierre-Luc Beaudoin committed
450
}