From 18f27b18da951d4c8834111212e47009053f6793 Mon Sep 17 00:00:00 2001
From: areversat <areversat@laptop33.(none)>
Date: Sun, 6 Apr 2008 14:45:50 -0400
Subject: [PATCH] Add code to manage call history tabs. - Change callist to
 handle multiple lists - Change calltree to handle multiple trees

---
 sflphone-gtk/src/actions.c    | 71 ++++++++++++++++-------------
 sflphone-gtk/src/calllist.c   | 49 ++++++++++----------
 sflphone-gtk/src/calllist.h   | 34 +++++++++-----
 sflphone-gtk/src/calltree.c   | 84 ++++++++++++++++++-----------------
 sflphone-gtk/src/calltree.h   | 10 +++--
 sflphone-gtk/src/dbus.c       |  3 +-
 sflphone-gtk/src/mainwindow.c |  2 +-
 sflphone-gtk/src/menus.c      | 19 ++++----
 sflphone-gtk/src/notebook.c   | 43 +++++++++++++-----
 sflphone-gtk/src/notebook.h   | 16 +++++++
 10 files changed, 200 insertions(+), 131 deletions(-)

diff --git a/sflphone-gtk/src/actions.c b/sflphone-gtk/src/actions.c
index d8b72f8c63..98bcf0108c 100644
--- a/sflphone-gtk/src/actions.c
+++ b/sflphone-gtk/src/actions.c
@@ -25,6 +25,7 @@
 #include <menus.h>
 #include <screen.h>
 #include <statusicon.h>
+#include <notebook.h>
 
 #include <gtk/gtk.h>
 #include <string.h>
@@ -100,7 +101,7 @@ status_bar_display_account( call_t* c)
 sflphone_quit ()
 {
 	gboolean quit = FALSE;
-	guint count = call_list_get_size();
+	guint count = call_list_get_size(tabs[TAB_CALL]);
 	if(count > 0){
 		quit = main_window_ask_quit();
 	}
@@ -123,7 +124,7 @@ sflphone_quit ()
 sflphone_hold(call_t * c )
 {
 	c->state = CALL_STATE_HOLD;
-	update_call_tree(c);
+	update_call_tree(tabs[TAB_CALL],c);
 	update_menus();
 }
 
@@ -131,15 +132,15 @@ sflphone_hold(call_t * c )
 sflphone_ringing(call_t * c )
 {
 	c->state = CALL_STATE_RINGING;
-	update_call_tree(c);
+	update_call_tree(tabs[TAB_CALL],c);
 	update_menus();
 }
 
   void
 sflphone_hung_up( call_t * c)
 {
-  call_list_remove( c->callID);
-  update_call_tree_remove(c);
+  call_list_remove( tabs[TAB_CALL], c->callID);
+  update_call_tree_remove(tabs[TAB_CALL], c);
   update_menus();
   status_tray_icon_blink( FALSE );
 }
@@ -191,18 +192,23 @@ sflphone_fill_account_list()
 
 	}
 
-	toolbar_update_buttons();
+	printf("Updating buttons\n");
+	//toolbar_update_buttons();
 	
 }
 
 	gboolean
 sflphone_init()
 {
-	call_list_init ();
+	int i;
+	for (i=0; i < NR_TABS; i++){
+		tabs[i] = calltab_init();	
+		call_list_init (tabs[i]);
+	}
 	account_list_init ();
         codec_list_init();
-	if(!dbus_connect ())
-	{
+	if(!dbus_connect ()){
+	
 		main_window_error_message(_("Unable to connect to the SFLphone server.\nMake sure the daemon is running."));
 		return FALSE;
 	}
@@ -219,7 +225,7 @@ sflphone_init()
 	void 
 sflphone_hang_up()
 {
-	call_t * selectedCall = call_get_selected();
+	call_t * selectedCall = call_get_selected(tabs[TAB_CALL]);
 	if(selectedCall)
 	{
 		switch(selectedCall->state)
@@ -249,7 +255,7 @@ sflphone_hang_up()
 	void 
 sflphone_pick_up()
 {
-	call_t * selectedCall = call_get_selected();
+	call_t * selectedCall = call_get_selected(tabs[TAB_CALL]);
 	if(selectedCall)
 	{
 		switch(selectedCall->state)
@@ -282,7 +288,7 @@ sflphone_pick_up()
 	void 
 sflphone_on_hold ()
 {
-	call_t * selectedCall = call_get_selected();
+	call_t * selectedCall = call_get_selected(tabs[TAB_CALL]);
 	if(selectedCall)
 	{
 		switch(selectedCall->state)
@@ -300,7 +306,7 @@ sflphone_on_hold ()
 	void 
 sflphone_off_hold ()
 {
-	call_t * selectedCall = call_get_selected();
+	call_t * selectedCall = call_get_selected(tabs[TAB_CALL]);
 	if(selectedCall)
 	{
 		switch(selectedCall->state)
@@ -320,7 +326,7 @@ sflphone_off_hold ()
 sflphone_fail( call_t * c )
 {
 	c->state = CALL_STATE_FAILURE;
-	update_call_tree(c);
+	update_call_tree(tabs[TAB_CALL],c);
 	update_menus();
 }
 
@@ -328,7 +334,7 @@ sflphone_fail( call_t * c )
 sflphone_busy( call_t * c )
 {
 	c->state = CALL_STATE_BUSY;
-	update_call_tree(c);
+	update_call_tree(tabs[TAB_CALL], c);
 	update_menus();
 }
 
@@ -336,19 +342,19 @@ sflphone_busy( call_t * c )
 sflphone_current( call_t * c )
 {
 	c->state = CALL_STATE_CURRENT;
-	update_call_tree(c);
+	update_call_tree(tabs[TAB_CALL],c);
 	update_menus();
 }
 
 	void 
 sflphone_set_transfert()
 {
-	call_t * c = call_get_selected();
+	call_t * c = call_get_selected(tabs[TAB_CALL]);
 	if(c)
 	{
 		c->state = CALL_STATE_TRANSFERT;
 		c->to = g_strdup("");
-		update_call_tree(c);
+		update_call_tree(tabs[TAB_CALL],c);
 		update_menus();
 	}
 	toolbar_update_buttons();
@@ -357,12 +363,12 @@ sflphone_set_transfert()
 	void 
 sflphone_unset_transfert()
 {
-	call_t * c = call_get_selected();
+	call_t * c = call_get_selected(tabs[TAB_CALL]);
 	if(c)
 	{
 		c->state = CALL_STATE_CURRENT;
 		c->to = g_strdup("");
-		update_call_tree(c);
+		update_call_tree(tabs[TAB_CALL],c);
 		update_menus();
 	}
 	toolbar_update_buttons();
@@ -371,9 +377,9 @@ sflphone_unset_transfert()
 	void
 sflphone_incoming_call (call_t * c) 
 {
-	call_list_add ( c );
+	call_list_add ( tabs[TAB_CALL],c );
 	//status_icon_unminimize();
-	update_call_tree_add(c);
+	update_call_tree_add(tabs[TAB_CALL],c);
 	update_menus();
 }
 
@@ -406,7 +412,7 @@ void process_dialing(call_t * c, guint keyval, gchar * key)
 						g_free(c->from);
 						c->from = g_strconcat("\"\" <", c->to, ">", NULL);
 					}
-					update_call_tree(c);
+					update_call_tree(tabs[TAB_CALL],c);
 				} 
 				else if(strlen(c->to) == 0)
 				{
@@ -434,7 +440,7 @@ void process_dialing(call_t * c, guint keyval, gchar * key)
 					g_free(c->from);
 					c->from = g_strconcat("\"\" <", c->to, ">", NULL);
 				}
-				update_call_tree(c);
+				update_call_tree(tabs[TAB_CALL],c);
 			}
 			break;
 	}
@@ -445,7 +451,7 @@ void process_dialing(call_t * c, guint keyval, gchar * key)
 call_t * sflphone_new_call()
 {
 	// Play a tone when creating a new call
-	if( call_list_get_size() == 0 )
+	if( call_list_get_size(tabs[TAB_CALL]) == 0 )
 	  dbus_start_tone( TRUE , ( voice_mails > 0 )? TONE_WITH_MESSAGE : TONE_WITHOUT_MESSAGE) ;
 
 	call_t * c = g_new0 (call_t, 1);
@@ -457,17 +463,18 @@ call_t * sflphone_new_call()
 
 	c->to = g_strdup("");
 
-	call_list_add(c);
-	update_call_tree_add(c);  
+
+	call_list_add(tabs[TAB_CALL],c);
+	update_call_tree_add(tabs[TAB_CALL],c);  
 	update_menus();
 
 	return c;
 }
 
 	void 
-sflphone_keypad( guint keyval, gchar * key)
-{
-	call_t * c = call_get_selected();
+sflphone_keypad( guint keyval, gchar * key){
+
+	call_t * c = call_get_selected(current_tab);
 	if(c)
 	{
 
@@ -492,7 +499,7 @@ sflphone_keypad( guint keyval, gchar * key)
 							c->from = g_strconcat("\"",call_get_name(c) ,"\" <", temp, ">", NULL);
 							g_free(before);
 							g_free(temp);
-							//update_call_tree(c);
+							//update_call_tree(tabs[TAB_CALL],c);
 						}
 						break;
 				}
@@ -594,6 +601,7 @@ sflphone_place_call ( call_t * c )
 			{
 				c->accountID = default_account;
 				dbus_place_call(c);
+				update_call_tree_add(tabs[TAB_CALLED], c);
 			}
 			else
 			{
@@ -607,6 +615,7 @@ sflphone_place_call ( call_t * c )
 			{
 				c->accountID = account->accountID;
 				dbus_place_call(c);
+				update_call_tree_add(tabs[TAB_CALLED], c);
 			}
 			else
 			{
diff --git a/sflphone-gtk/src/calllist.c b/sflphone-gtk/src/calllist.c
index 1d5411e3df..f3154dbfbb 100644
--- a/sflphone-gtk/src/calllist.c
+++ b/sflphone-gtk/src/calllist.c
@@ -21,8 +21,10 @@
 
 #include <string.h>
 
-GQueue * callQueue = NULL;
-call_t * selectedCall = NULL;
+/*
+ * GQueue * callQueue = NULL;
+ * call_t * selectedCall = NULL;
+ */
 
 /* GCompareFunc to compare a callID (gchar* and a call_t) */
 gint 
@@ -55,39 +57,40 @@ get_state_callstruct ( gconstpointer a, gconstpointer b)
 }
 
 void 
-call_list_init ()
+call_list_init (calltab_t* tab)
 {
-  callQueue = g_queue_new ();
+  tab->callQueue = g_queue_new ();
+  tab->selectedCall = NULL;
 }
 
 void 
-call_list_clean ()
+call_list_clean (calltab_t* tab)
 {
-  g_queue_free (callQueue);
+  g_queue_free (tab->callQueue);
 }
 
 void 
-call_list_add (call_t * c)
+call_list_add (calltab_t* tab, call_t * c)
 {
-  g_queue_push_tail (callQueue, (gpointer *) c);
+  g_queue_push_tail (tab->callQueue, (gpointer *) c);
 }
 
 
 void 
-call_list_remove (const gchar * callID)
+call_list_remove (calltab_t* tab, const gchar * callID)
 {
-  call_t * c = call_list_get(callID);
+  call_t * c = call_list_get(tab, callID);
   if (c)
   {
-    g_queue_remove(callQueue, c);
+    g_queue_remove(tab->callQueue, c);
   }
 }
 
 
 call_t * 
-call_list_get_by_state (call_state_t state )
+call_list_get_by_state (calltab_t* tab, call_state_t state )
 {
-  GList * c = g_queue_find_custom (callQueue, &state, get_state_callstruct);
+  GList * c = g_queue_find_custom (tab->callQueue, &state, get_state_callstruct);
   if (c)
   {
     return (call_t *)c->data;
@@ -100,15 +103,15 @@ call_list_get_by_state (call_state_t state )
 }
 
 guint
-call_list_get_size ( )
+call_list_get_size (calltab_t* tab)
 {
-  return g_queue_get_length (callQueue);
+  return g_queue_get_length (tab->callQueue);
 }
 
 call_t * 
-call_list_get_nth ( guint n )
+call_list_get_nth (calltab_t* tab, guint n )
 {
-  return g_queue_peek_nth (callQueue, n);
+  return g_queue_peek_nth (tab->callQueue, n);
 }
 
 gchar * 
@@ -134,9 +137,9 @@ call_get_number (const call_t * c)
 
 
 call_t * 
-call_list_get ( const gchar * callID )
+call_list_get (calltab_t* tab, const gchar * callID )
 {
-  GList * c = g_queue_find_custom (callQueue, callID, is_callID_callstruct);
+  GList * c = g_queue_find_custom (tab->callQueue, callID, is_callID_callstruct);
   if (c)
   {
     return (call_t *)c->data;
@@ -148,14 +151,14 @@ call_list_get ( const gchar * callID )
 }
 
 void
-call_select ( call_t * c )
+call_select (calltab_t* tab, call_t * c )
 {
-  selectedCall = c;
+  tab->selectedCall = c;
 }
 
 
 call_t *
-call_get_selected ()
+call_get_selected (calltab_t* tab)
 {
-  return selectedCall;
+  return tab->selectedCall;
 }
diff --git a/sflphone-gtk/src/calllist.h b/sflphone-gtk/src/calllist.h
index cf7d21bbc2..b756430ef9 100644
--- a/sflphone-gtk/src/calllist.h
+++ b/sflphone-gtk/src/calllist.h
@@ -68,45 +68,55 @@ typedef struct  {
   call_state_t state;
 } call_t;
 
-/** This function initialize the call list. */
-void call_list_init ();
+typedef struct {
+	GtkListStore* store;
+	GtkWidget* view;
+	GtkWidget* tree;
+
+	// Calllist vars
+	GQueue* callQueue;
+	call_t* selectedCall;
+} calltab_t;
+
+/** This function initialize a call list. */
+void call_list_init (calltab_t* tab);
 
 /** This function empty and free the call list. */
-void call_list_clean ();
+void call_list_clean (calltab_t* tab);
 
 /** This function append a call to list. 
   * @param c The call you want to add */
-void call_list_add (call_t * c);
+void call_list_add (calltab_t* tab, call_t * c);
 
 /** This function remove a call from list. 
   * @param callID The callID of the call you want to remove
   */
-void call_list_remove (const gchar * callID);
+void call_list_remove (calltab_t* tab, const gchar * callID);
 
 /** Return the first call that corresponds to the state.  
   * This is usefull for unique states as DIALING and CURRENT.
   * @param state The state
   * @return A call or NULL */
-call_t * call_list_get_by_state ( call_state_t state);
+call_t * call_list_get_by_state (calltab_t* tab, call_state_t state);
 
 /** Return the number of calls in the list
   * @return The number of calls in the list */
-guint call_list_get_size ( );
+guint call_list_get_size (calltab_t* tab);
 
 /** Return the call at the nth position in the list
   * @param n The position of the call you want
   * @return A call or NULL */
-call_t * call_list_get_nth ( guint n );
+call_t * call_list_get_nth (calltab_t* tab, guint n );
 
 /** Return the call corresponding to the callID
   * @param n The callID of the call you want
   * @return A call or NULL */
-call_t * call_list_get ( const gchar * callID );
+call_t * call_list_get (calltab_t* tab, const gchar * callID );
 
 /** This function parse the call_t.from field to return the name
   * @param c The call
   * @return The full name of the caller or an empty string */
-gchar * call_get_name (const call_t * c);
+gchar * call_get_name ( const call_t * c);
 
 /** This function parse the call_t.from field to return the number
   * @param c The call
@@ -116,9 +126,9 @@ gchar * call_get_number (const call_t * c);
 /** Mark a call as selected.  There can be only one selected call.  This call
   * is the currently highlighted one in the list.
   * @param c The call */
-void call_select ( call_t * c );
+void call_select (calltab_t* tab, call_t * c );
 
 /** Return the selected call.
   * @return The number of the caller */
-call_t * call_get_selected ();
+call_t * call_get_selected (calltab_t* tab);
 #endif 
diff --git a/sflphone-gtk/src/calltree.c b/sflphone-gtk/src/calltree.c
index 6be55acdbc..fa545fa4e1 100644
--- a/sflphone-gtk/src/calltree.c
+++ b/sflphone-gtk/src/calltree.c
@@ -18,6 +18,7 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <stdlib.h>
 #include <gtk/gtk.h>
 #include <actions.h>
 #include <calltree.h>
@@ -25,8 +26,6 @@
 #include <menus.h>
 #include <dbus.h>
 
-GtkListStore * store;
-GtkWidget *view;
 
 
 GtkWidget   * toolbar;
@@ -66,7 +65,7 @@ button_pressed(GtkWidget* widget, GdkEventButton *event, gpointer user_data)
 	static void 
 call_button( GtkWidget *widget, gpointer   data )
 {
-	if(call_list_get_size()>0)
+	if(call_list_get_size(current_tab)>0)
 		sflphone_pick_up();
 	else
 		sflphone_new_call();
@@ -142,7 +141,7 @@ toolbar_update_buttons ()
 	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(transfertButton), FALSE);
 	gtk_signal_handler_unblock(transfertButton, transfertButtonConnId);
 
-	call_t * selectedCall = call_get_selected();
+	call_t * selectedCall = call_get_selected(current_tab);
 	if (selectedCall)
 	{
 		switch(selectedCall->state) 
@@ -211,10 +210,11 @@ toolbar_update_buttons ()
 }
 /* Call back when the user click on a call in the list */
 	static void 
-selected(GtkTreeSelection *sel, GtkTreeModel *model) 
+selected(GtkTreeSelection *sel, void* data) 
 {
 	GtkTreeIter  iter;
 	GValue val;
+	GtkTreeModel *model = (GtkTreeModel*)current_tab->store;
 
 	if (! gtk_tree_selection_get_selected (sel, &model, &iter))
 		return;
@@ -222,7 +222,7 @@ selected(GtkTreeSelection *sel, GtkTreeModel *model)
 	val.g_type = 0;
 	gtk_tree_model_get_value (model, &iter, 2, &val);
 
-	call_select((call_t*) g_value_get_pointer(&val));
+	call_select(current_tab, (call_t*) g_value_get_pointer(&val));
 	g_value_unset(&val);
 
 	toolbar_update_buttons();
@@ -232,9 +232,9 @@ selected(GtkTreeSelection *sel, GtkTreeModel *model)
 void  row_activated(GtkTreeView       *tree_view,
 		GtkTreePath       *path,
 		GtkTreeViewColumn *column,
-		void * foo) 
+		void * data) 
 {
-	call_t * selectedCall = call_get_selected();
+	call_t * selectedCall = call_get_selected(current_tab);
 	if (selectedCall)
 	{
 		switch(selectedCall->state)  
@@ -325,38 +325,38 @@ create_toolbar (){
 
 }  
 
-GtkWidget * 
-create_call_tree (){
-	GtkWidget *ret;
+void 
+create_call_tree (calltab_t* tab){
 	GtkWidget *sw;
 	GtkCellRenderer *rend;
 	GtkTreeViewColumn *col;
 	GtkTreeSelection *sel;
 
-	ret = gtk_vbox_new(FALSE, 10); 
-	gtk_container_set_border_width (GTK_CONTAINER (ret), 0);
+	tab->tree = gtk_vbox_new(FALSE, 10); 
+
+	gtk_container_set_border_width (GTK_CONTAINER (tab->tree), 0);
 
 	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);
 
-	store = gtk_list_store_new (3, 
+	tab->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));
-	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
-	g_signal_connect (G_OBJECT (view), "row-activated",
+	tab->view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(tab->store));
+	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);
 
   // Connect the popup menu
-	g_signal_connect (G_OBJECT (view), "popup-menu",
+	g_signal_connect (G_OBJECT (tab->view), "popup-menu",
 			G_CALLBACK (popup_menu), 
 			NULL);
-	g_signal_connect (G_OBJECT (view), "button-press-event",
+	g_signal_connect (G_OBJECT (tab->view), "button-press-event",
 			G_CALLBACK (button_pressed), 
 			NULL);
 
@@ -365,38 +365,38 @@ create_call_tree (){
 			rend,
 			"pixbuf", 0,
 			NULL);
-	gtk_tree_view_append_column (GTK_TREE_VIEW(view), col);
+	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(view), col);
-	g_object_unref(G_OBJECT(store));
-	gtk_container_add(GTK_CONTAINER(sw), view);
+	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 (view));
+	sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (tab->view));
 	g_signal_connect (G_OBJECT (sel), "changed",
 			G_CALLBACK (selected),
-			store);
-
-	gtk_box_pack_start(GTK_BOX(ret), sw, TRUE, TRUE, 0);
-
-	gtk_widget_show(ret); 
-
-	toolbar_update_buttons();
+			NULL);
 
-	return ret;
+	gtk_box_pack_start(GTK_BOX(tab->tree), sw, TRUE, TRUE, 0);
 
+	gtk_widget_show(tab->tree); 
+	
+	//toolbar_update_buttons();
+	
 }
 
 void 
-update_call_tree_remove (call_t * c)
+update_call_tree_remove (calltab_t* tab, call_t * c)
 {
 	GtkTreeIter iter;
 	GValue val;
 	call_t * iterCall;
+	GtkListStore* store = tab->store;
+	GtkWidget* view = tab->view;
 
 	int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
 	int i;
@@ -416,19 +416,21 @@ update_call_tree_remove (call_t * c)
 			}
 		}
 	}
-	call_t * selectedCall = call_get_selected();
+	call_t * selectedCall = call_get_selected(tab);
 	if(selectedCall == c)
-		call_select(NULL);
+		call_select(tab, NULL);
 	toolbar_update_buttons();
 }
 
 void 
-update_call_tree (call_t * c)
+update_call_tree (calltab_t* tab, call_t * c)
 {
 	GdkPixbuf *pixbuf;
 	GtkTreeIter iter;
 	GValue val;
 	call_t * iterCall;
+	GtkListStore* store = tab->store;
+	GtkWidget* view = tab->view;
 
 	int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
 	int i;
@@ -513,11 +515,13 @@ update_call_tree (call_t * c)
 }
 
 void 
-update_call_tree_add (call_t * c)
+update_call_tree_add (calltab_t* tab, call_t * c)
 {
 	GdkPixbuf *pixbuf;
 	GtkTreeIter iter;
 	GtkTreeSelection* sel;
+	//GtkListStore* store = tab->store;
+	//GtkWidget* view = tab->view;
 
 	// New call in the list
 	gchar * markup;
@@ -526,7 +530,7 @@ update_call_tree_add (call_t * c)
 			call_get_name(c), 
 			call_get_number(c));
 
-	gtk_list_store_append (store, &iter);
+	gtk_list_store_append (tab->store, &iter);
 
 	switch(c->state)
 	{
@@ -551,7 +555,7 @@ update_call_tree_add (call_t * c)
 			pixbuf =  gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
 		}
 	}
-	gtk_list_store_set(store, &iter,
+	gtk_list_store_set(tab->store, &iter,
 			0, pixbuf, // Icon
 			1, markup, // Description
 			2, c,      // Pointer
@@ -560,7 +564,7 @@ update_call_tree_add (call_t * c)
 	if (pixbuf != NULL)
 		g_object_unref(G_OBJECT(pixbuf));
 
-	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tab->view));
 	gtk_tree_selection_select_iter(GTK_TREE_SELECTION(sel), &iter);
 	toolbar_update_buttons();
 }
diff --git a/sflphone-gtk/src/calltree.h b/sflphone-gtk/src/calltree.h
index 8d64507ac2..8ead8a089a 100644
--- a/sflphone-gtk/src/calltree.h
+++ b/sflphone-gtk/src/calltree.h
@@ -22,17 +22,19 @@
 
 #include <gtk/gtk.h>
 #include <calllist.h>
+#include <notebook.h>
+
 
 /** @file calltree.h
   * @brief The GtkTreeView that list calls in the main window.
   */
-GtkWidget * create_call_tree();
+void create_call_tree(calltab_t* tab);
 
 void toolbar_update_buttons();
 
-void update_call_tree_add (call_t * c);
-void update_call_tree (call_t * c);
-void update_call_tree_remove (call_t * c);
+void update_call_tree_add (calltab_t* ct, call_t * c);
+void update_call_tree (calltab_t* ct, call_t * c);
+void update_call_tree_remove (calltab_t* ct, call_t * c);
 
 GtkWidget * create_toolbar();
 
diff --git a/sflphone-gtk/src/dbus.c b/sflphone-gtk/src/dbus.c
index 191108d4ec..ec9c42d206 100644
--- a/sflphone-gtk/src/dbus.c
+++ b/sflphone-gtk/src/dbus.c
@@ -21,6 +21,7 @@
  
 #include <accountlist.h>
 #include <calllist.h>
+#include <notebook.h>
 #include <callmanager-glue.h>
 #include <configurationmanager-glue.h>
 #include <instance-glue.h>
@@ -97,7 +98,7 @@ call_state_cb (DBusGProxy *proxy,
                   void * foo  )
 {
   g_print ("Call %s state %s\n",callID, state);
-  call_t * c = call_list_get(callID);
+  call_t * c = call_list_get(tabs[TAB_CALL], callID);
   if(c)
   {
     if ( strcmp(state, "HUNGUP") == 0 )
diff --git a/sflphone-gtk/src/mainwindow.c b/sflphone-gtk/src/mainwindow.c
index e18a48ee6f..f41ae77d79 100644
--- a/sflphone-gtk/src/mainwindow.c
+++ b/sflphone-gtk/src/mainwindow.c
@@ -54,7 +54,7 @@ on_delete (GtkWidget * widget, gpointer data)
 /** Ask the user if he wants to hangup current calls */
 gboolean 
 main_window_ask_quit(){
-  guint count = call_list_get_size();
+  guint count = call_list_get_size(tabs[TAB_CALL]);
   GtkWidget * dialog;
   guint response;
   gchar * question;
diff --git a/sflphone-gtk/src/menus.c b/sflphone-gtk/src/menus.c
index df13d1216f..9e6ef2f7bd 100644
--- a/sflphone-gtk/src/menus.c
+++ b/sflphone-gtk/src/menus.c
@@ -26,6 +26,7 @@
 #include <dbus.h>
 #include <mainwindow.h>
 #include <screen.h>
+#include <notebook.h>
 #include <gtk/gtk.h>
 
 #include <string.h> // for strlen
@@ -50,7 +51,7 @@ void update_menus()
   gtk_widget_set_sensitive( GTK_WIDGET(copyMenu),   FALSE);
   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(holdMenu), FALSE);
 	
-	call_t * selectedCall = call_get_selected();
+	call_t * selectedCall = call_get_selected(current_tab);
 	if (selectedCall)
 	{
     gtk_widget_set_sensitive( GTK_WIDGET(copyMenu),   TRUE);
@@ -176,7 +177,7 @@ call_minimize ( void * foo)
 static void 
 call_hold  (void* foo)
 {
-  call_t * selectedCall = call_get_selected();
+  call_t * selectedCall = call_get_selected(tabs[TAB_CALL]);
   
   if(selectedCall)
   {
@@ -297,7 +298,7 @@ static void
 edit_copy ( void * foo)
 {
   GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
-  call_t * selectedCall = call_get_selected();
+  call_t * selectedCall = call_get_selected(current_tab);
   gchar * no = NULL;
   
   if(selectedCall)
@@ -329,7 +330,7 @@ static void
 edit_paste ( void * foo)
 {
   GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
-  call_t * selectedCall = call_get_selected();
+  call_t * selectedCall = call_get_selected(current_tab);
   gchar * no = gtk_clipboard_wait_for_text (clip);
   
   if(no && selectedCall)
@@ -351,7 +352,7 @@ edit_paste ( void * foo)
             selectedCall->from = g_strconcat("\"\" <", selectedCall->to, ">", NULL);
           }
           screen_set_call(selectedCall);
-          update_call_tree(selectedCall);
+          update_call_tree(tabs[TAB_CALL], selectedCall);
         }
         break;
       case CALL_STATE_RINGING:  
@@ -371,7 +372,7 @@ edit_paste ( void * foo)
           selectedCall->from = g_strconcat("\"\" <", selectedCall->to, ">", NULL);
           
           screen_set_call(selectedCall);
-          update_call_tree(selectedCall);
+          update_call_tree(tabs[TAB_CALL], selectedCall);
         }
         break;
       case CALL_STATE_CURRENT:
@@ -390,7 +391,7 @@ edit_paste ( void * foo)
             g_free(before);
             g_free(temp);
             screen_set_call(selectedCall);
-            update_call_tree(selectedCall);
+            update_call_tree(tabs[TAB_CALL], selectedCall);
           
           }
         }
@@ -411,7 +412,7 @@ edit_paste ( void * foo)
     selectedCall->from = g_strconcat("\"\" <", selectedCall->to, ">", NULL);
     
     screen_set_call(selectedCall);
-    update_call_tree(selectedCall);
+    update_call_tree(tabs[TAB_CALL], selectedCall);
   }
   
 }
@@ -544,7 +545,7 @@ show_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
   
   gboolean pickup = FALSE, hangup = FALSE, hold = FALSE, copy = FALSE;
   
-	call_t * selectedCall = call_get_selected();
+	call_t * selectedCall = call_get_selected(current_tab);
 	if (selectedCall)
 	{
     copy = TRUE;
diff --git a/sflphone-gtk/src/notebook.c b/sflphone-gtk/src/notebook.c
index 9b1e7c2cd4..8d4d1ac51f 100644
--- a/sflphone-gtk/src/notebook.c
+++ b/sflphone-gtk/src/notebook.c
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2007 Savoir-Faire Linux inc.
- *  Author: Antoine Reversat <antoine.reversat@savoirfairelinux.net>
+ *  Author: Antoine Reversat <antoine.reversat@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
@@ -18,24 +18,47 @@
  */
 
 #include <gtk/gtk.h>
+#include <stdlib.h>
 #include <calltree.h>
 #include <calllist.h>
 #include <notebook.h>
 
+calltab_t* calltab_init(){
+	calltab_t* ret;
+	ret = malloc(sizeof(calltab_t));
+
+	ret->store = NULL;
+	ret->view = NULL;
+	ret->tree = NULL;
+	ret->callQueue = NULL;
+	ret->selectedCall = NULL;
+	
+	return ret;
+}
+
+void*
+calltab_change(GtkNotebook* notebook,
+		GtkNotebookPage* page,
+		guint page_num,
+		gpointer data){
+	current_tab = tabs[page_num];
+}
+
 GtkWidget*
 create_call_notebook(){
 	GtkWidget* notebook;
-	GtkWidget* call_tab;
-	GtkWidget* called_tab;
-	GtkWidget* rcvd_tab;
-	GtkWidget* missed_tab;
+	int i;
 
 	notebook = gtk_notebook_new();
 
-	call_tab = create_call_tree();
-	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), call_tab, gtk_label_new("Call"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), called_tab, gtk_label_new("Called"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), rcvd_tab, gtk_label_new("Received"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), missed_tab, gtk_label_new("Missed"));
+	for(i=0; i < NR_TABS; i++){
+		create_call_tree(tabs[i]);
+	}
+	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tabs[TAB_CALL]->tree, gtk_label_new("Call"));
+	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tabs[TAB_CALLED]->tree, gtk_label_new("Called"));
+	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tabs[TAB_RCVD]->tree, gtk_label_new("Received"));
+	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tabs[TAB_MISSED]->tree, gtk_label_new("Missed"));
+	current_tab = tabs[TAB_CALL];
+	g_signal_connect(notebook, "switch-page", G_CALLBACK(calltab_change), NULL);
 	return notebook;
 }
diff --git a/sflphone-gtk/src/notebook.h b/sflphone-gtk/src/notebook.h
index b23fc4ecef..4ac806c291 100644
--- a/sflphone-gtk/src/notebook.h
+++ b/sflphone-gtk/src/notebook.h
@@ -20,7 +20,23 @@
 #ifndef __NOTEBOOK_H__
 #define __NOTEBOOK_H__
 
+#include <calllist.h>
 #include <gtk/gtk.h>
+
+
+enum {
+	TAB_CALL,
+	TAB_CALLED,
+	TAB_RCVD,
+	TAB_MISSED	
+};
+
+#define NR_TABS 4
+calltab_t* calltab_init();
 GtkWidget* create_call_notebook();
 
+calltab_t* tabs[NR_TABS];
+//calltab_t* call_tab, *called_tab, *rcvd_tab, *missed_tab;
+calltab_t* current_tab;
+
 #endif
-- 
GitLab