friendlist.c 36.7 KB
Newer Older
aymeric's avatar
aymeric committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
linphone, gtk-glade interface.
Copyright (C) 2008  Simon MORLAT (simon.morlat@linphone.org)

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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include <gtk/gtk.h>
#include "linphone.h"

static GtkWidget *linphone_gtk_create_contact_menu(GtkWidget *contact_list);

enum{
	FRIEND_PRESENCE_IMG,
	FRIEND_NAME,
	FRIEND_ID,
29
	FRIEND_CHATROOM,
aymeric's avatar
aymeric committed
30
	FRIEND_SIP_ADDRESS,
31
	FRIEND_CHAT,
32
	FRIEND_CALL_BUTTON_VISIBLE,
33
	FRIEND_CHAT_BUTTON_VISIBLE,
aymeric's avatar
aymeric committed
34 35 36 37 38 39 40 41 42
	FRIEND_LIST_NCOL
};

typedef struct _status_picture_tab_t{
	LinphoneOnlineStatus status;
	const char *img;
} status_picture_tab_t;

status_picture_tab_t status_picture_tab[]={
43 44 45 46 47 48 49 50 51 52 53 54
	{ LinphoneStatusOnline       , "linphone-status-online"       },
	{ LinphoneStatusBusy         , "linphone-status-away"         },
	{ LinphoneStatusBeRightBack  , "linphone-status-away"         },
	{ LinphoneStatusAway         , "linphone-status-away"         },
	{ LinphoneStatusOnThePhone   , "linphone-status-away"         },
	{ LinphoneStatusOutToLunch   , "linphone-status-away"         },
	{ LinphoneStatusDoNotDisturb , "linphone-status-donotdisturb" },
	{ LinphoneStatusMoved        , "linphone-status-away"         },
	{ LinphoneStatusAltService   , "linphone-status-away"         },
	{ LinphoneStatusOffline      , "linphone-status-offline"      },
	{ LinphoneStatusPending      , "linphone-status-offline"      },
	{ LinphoneStatusEnd          , NULL                           }
aymeric's avatar
aymeric committed
55 56
};

57
static const char *status_to_icon_name(LinphoneOnlineStatus ss) {
aymeric's avatar
aymeric committed
58 59
	status_picture_tab_t *t=status_picture_tab;
	while(t->img!=NULL){
60 61
		if (ss==t->status) {
			return t->img;
aymeric's avatar
aymeric committed
62 63 64
		}
		++t;
	}
65
	g_error("No icon name defined for status %i",ss);
aymeric's avatar
aymeric committed
66 67 68
	return NULL;
}

69 70 71 72
static GtkWidget *create_status_picture(LinphoneOnlineStatus ss, GtkIconSize icon_size){
	const char *icon_name = status_to_icon_name(ss);
	if(icon_name) return gtk_image_new_from_icon_name(icon_name, icon_size);
	else return NULL;
73 74
}

75 76 77 78 79 80 81 82 83
gboolean linphone_gtk_friend_list_is_contact(const LinphoneAddress *addr){
	LinphoneFriend *lf;
	char *addr_str=linphone_address_as_string(addr);
	lf=linphone_core_get_friend_by_address(linphone_gtk_get_core(),addr_str);
	if(lf == NULL){
		return FALSE;
	} return TRUE;
}

aymeric's avatar
aymeric committed
84 85 86 87 88 89 90 91 92 93
static void linphone_gtk_set_selection_to_uri_bar(GtkTreeView *treeview){
	GtkTreeSelection *select;
	GtkTreeIter iter;
	GtkTreeModel *model;
	LinphoneFriend *lf=NULL;
	gchar* friend;
	select = gtk_tree_view_get_selection (treeview);
	if (gtk_tree_selection_get_selected (select, &model, &iter))
	{
		gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
94
		friend=linphone_address_as_string(linphone_friend_get_address(lf));
aymeric's avatar
aymeric committed
95 96 97 98 99
		gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),friend);
		ms_free(friend);
	}
}

100
void linphone_gtk_add_contact(void){
101
	GtkWidget *w=linphone_gtk_create_window("contact", linphone_gtk_get_main_window());
102
	int presence_enabled=linphone_gtk_get_ui_config_int("use_subscribe_notify",1);
103

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"show_presence")),presence_enabled);
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"allow_presence")),
					presence_enabled);
	gtk_widget_show(w);
}

void linphone_gtk_edit_contact(GtkWidget *button){
	GtkWidget *w=gtk_widget_get_toplevel(button);
	GtkTreeSelection *select;
	GtkTreeIter iter;
	GtkTreeModel *model;
	LinphoneFriend *lf=NULL;
	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"contact_list")));
	if (gtk_tree_selection_get_selected (select, &model, &iter))
	{
		gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
120
		linphone_gtk_show_contact(lf, w);
121 122 123 124 125 126 127 128 129
	}
}

void linphone_gtk_remove_contact(GtkWidget *button){
	GtkWidget *w=gtk_widget_get_toplevel(button);
	GtkTreeSelection *select;
	GtkTreeIter iter;
	GtkTreeModel *model;
	LinphoneFriend *lf=NULL;
130
	LinphoneChatRoom *cr=NULL;
131 132 133 134 135
	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"contact_list")));
	if (gtk_tree_selection_get_selected (select, &model, &iter))
	{
		gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
		linphone_core_remove_friend(linphone_gtk_get_core(),lf);
136 137
		gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
		linphone_chat_room_delete_history(cr);
138 139 140 141
		linphone_gtk_show_friends();
	}
}

Margaux Clerc's avatar
Margaux Clerc committed
142
void linphone_gtk_delete_history(GtkWidget *button){
143
	GtkWidget *w=linphone_gtk_get_main_window();
Margaux Clerc's avatar
Margaux Clerc committed
144 145 146
	GtkTreeSelection *select;
	GtkTreeIter iter;
	GtkTreeModel *model;
147
	GtkWidget *chat_view;
Margaux Clerc's avatar
Margaux Clerc committed
148
	LinphoneFriend *lf=NULL;
149
	GtkWidget *friendlist;
150

151 152 153
	friendlist=linphone_gtk_get_widget(w,"contact_list");
	chat_view=(GtkWidget *)g_object_get_data(G_OBJECT(friendlist),"chatview");
	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(friendlist));
Margaux Clerc's avatar
Margaux Clerc committed
154 155
	if (gtk_tree_selection_get_selected (select, &model, &iter))
	{
Simon Morlat's avatar
Simon Morlat committed
156
		LinphoneChatRoom *cr;
Margaux Clerc's avatar
Margaux Clerc committed
157
		gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
158
		gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
Simon Morlat's avatar
Simon Morlat committed
159
		linphone_chat_room_delete_history(cr);
160
		if(chat_view!=NULL){
161 162 163
			const LinphoneAddress *from=linphone_gtk_friend_list_get_active_address();
			const LinphoneAddress *addr=linphone_friend_get_address(lf);
			if(linphone_address_weak_equal(from,addr)){
164 165 166 167
				GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview"));
				GtkTextIter start;
				GtkTextIter end;
				GtkTextBuffer *text_buffer;
168

169 170 171 172 173 174
				text_buffer=gtk_text_view_get_buffer(text_view);
				gtk_text_buffer_get_bounds(text_buffer, &start, &end);
				gtk_text_buffer_delete (text_buffer, &start, &end);
				g_object_set_data(G_OBJECT(chat_view),"from_message",NULL);
			}
		}
Margaux Clerc's avatar
Margaux Clerc committed
175 176 177 178
		linphone_gtk_show_friends();
	}
}

aymeric's avatar
aymeric committed
179 180 181 182 183 184
static void linphone_gtk_call_selected(GtkTreeView *treeview){
	linphone_gtk_set_selection_to_uri_bar(treeview);
	linphone_gtk_start_call(linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(treeview)),
					"start_call"));
}

185
void linphone_gtk_friend_list_update_button_display(GtkTreeView *friendlist){
186
	GtkTreeIter iter, selected_iter;
187 188
	GtkTreeModel *model=gtk_tree_view_get_model(friendlist);
	GtkTreeSelection *select=gtk_tree_view_get_selection(friendlist);
Margaux Clerc's avatar
Margaux Clerc committed
189
	LinphoneChatRoom *cr=NULL;
190
	gboolean is_composing;
Margaux Clerc's avatar
Margaux Clerc committed
191
	int nbmsg=0;
192
	GtkTreePath *selected_path = NULL;
193
	GtkTreePath *hovered_row = (GtkTreePath *)g_object_get_data(G_OBJECT(friendlist), "hovered_row");
194 195 196 197 198
	
	if (gtk_tree_selection_get_selected(select, &model, &selected_iter)){
		selected_path = gtk_tree_model_get_path(model, &selected_iter);
	}
	
199 200
	if (gtk_tree_model_get_iter_first(model,&iter)) {
		do{
201
			const char *icon_name = NULL;
202 203 204
			gboolean show_chat_button = FALSE;
			gboolean show_call_button = FALSE;
			GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
205
			
206
			gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
Margaux Clerc's avatar
Margaux Clerc committed
207
			nbmsg=linphone_chat_room_get_unread_messages_count(cr);
208
			is_composing=linphone_chat_room_is_remote_composing(cr);
Margaux Clerc's avatar
Margaux Clerc committed
209
			if(nbmsg != 0){
210
				if (is_composing) icon_name = "linphone-chat-new-message-and-writing";
211
				else icon_name = "linphone-chat-new-message";
212
				show_chat_button = TRUE;
Margaux Clerc's avatar
Margaux Clerc committed
213
			} else {
214
				if (is_composing) {
215
					icon_name = "linphone-chat-writing";
216 217
					show_chat_button = TRUE;
				} else {
218 219
					icon_name = "linphone-chat-nothing";
				}
Margaux Clerc's avatar
Margaux Clerc committed
220
			}
221 222 223 224 225
			if ((selected_path && gtk_tree_path_compare(path, selected_path) == 0) 
					|| (hovered_row && gtk_tree_path_compare(path, hovered_row) == 0)){
				show_chat_button = TRUE;
				show_call_button = TRUE;
			}
226
			gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,icon_name,
227 228 229 230
						FRIEND_CHAT_BUTTON_VISIBLE, show_chat_button, -1);
			gtk_list_store_set(GTK_LIST_STORE(model), &iter, FRIEND_CALL_BUTTON_VISIBLE, show_call_button, -1);
			
			gtk_tree_path_free(path);
231 232
		}while(gtk_tree_model_iter_next(model,&iter));
	}
233
	if (selected_path) gtk_tree_path_free(selected_path);
234 235
}

236 237 238 239 240
static gboolean grab_focus(GtkWidget *w){
	gtk_widget_grab_focus(w);
	return FALSE;
}

241 242 243
void linphone_gtk_friend_list_set_active_address(const LinphoneAddress *addr){
	GtkWidget *w=linphone_gtk_get_main_window();
	GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
Simon Morlat's avatar
Simon Morlat committed
244
	g_object_set_data_full(G_OBJECT(friendlist),"from", addr ? linphone_address_clone(addr) : NULL, (GDestroyNotify)linphone_address_destroy);
245 246 247 248 249 250 251 252
}

const LinphoneAddress *linphone_gtk_friend_list_get_active_address(void){
	GtkWidget *w=linphone_gtk_get_main_window();
	GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
	return (const LinphoneAddress*)g_object_get_data(G_OBJECT(friendlist),"from");
}

Margaux Clerc's avatar
Margaux Clerc committed
253
void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la){
Margaux Clerc's avatar
Margaux Clerc committed
254
	GtkTreeIter iter;
255 256 257 258 259 260
	GtkListStore *store=NULL;
	GtkWidget *w = linphone_gtk_get_main_window();
	GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
	GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist));
	GtkWidget *chat_view=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
	LinphoneFriend *lf=NULL;
261 262
	LinphoneChatRoom *cr=NULL;
	GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch");
263

264
	lf=linphone_core_find_friend(linphone_gtk_get_core(),la);
265 266
	if(lf==NULL){
		cr=linphone_gtk_create_chatroom(la);
267
		linphone_gtk_friend_list_set_active_address(la);
268 269 270 271 272 273 274
		if(chat_view==NULL){
			chat_view=linphone_gtk_init_chatroom(cr,la);
			g_object_set_data(G_OBJECT(friendlist),"chatview",(gpointer)chat_view);
		} else {
			linphone_gtk_load_chatroom(cr,la,chat_view);
		}
		gtk_notebook_set_current_page(notebook,gtk_notebook_page_num(notebook,chat_view));
275
		linphone_gtk_friend_list_update_button_display(GTK_TREE_VIEW(chat_view));
276 277 278 279 280 281
		g_idle_add((GSourceFunc)grab_focus,linphone_gtk_get_widget(chat_view,"text_entry"));
	} else {
		store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist)));
		if (gtk_tree_model_get_iter_first(model,&iter)) {
			do{
				const LinphoneAddress *uri;
282
				gtk_tree_model_get(model, &iter,FRIEND_ID , &lf, -1);
283
				uri=linphone_friend_get_address(lf);
284
				if (linphone_address_weak_equal(uri,la)){
285 286 287 288 289
					gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
					if(cr==NULL){
						cr=linphone_gtk_create_chatroom(uri);
						gtk_list_store_set(store,&iter,FRIEND_CHATROOM,cr,-1);
					}
290
					linphone_gtk_friend_list_set_active_address(uri);
291 292 293
					if(chat_view==NULL){
						chat_view=linphone_gtk_init_chatroom(cr,uri);
						g_object_set_data(G_OBJECT(friendlist),"chatview",(gpointer)chat_view);
Margaux Clerc's avatar
Margaux Clerc committed
294
					} else {
295
						linphone_gtk_load_chatroom(cr,uri,chat_view);
Margaux Clerc's avatar
Margaux Clerc committed
296
					}
297
					gtk_notebook_set_current_page(notebook,gtk_notebook_page_num(notebook,chat_view));
298
					linphone_gtk_friend_list_update_button_display(GTK_TREE_VIEW(chat_view));
299 300
					g_idle_add((GSourceFunc)grab_focus,linphone_gtk_get_widget(chat_view,"text_entry"));
					break;
Margaux Clerc's avatar
Margaux Clerc committed
301
				}
302 303
			}while(gtk_tree_model_iter_next(model,&iter));
		}
304
	}
305 306 307 308 309 310 311
}

void linphone_gtk_notebook_tab_select(GtkNotebook *notebook,GtkWidget *page,guint page_num, gpointer data){
	GtkWidget *w=linphone_gtk_get_main_window();
	GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
	GtkWidget *chat_view;
	LinphoneChatRoom *cr=NULL;
Margaux Clerc's avatar
Margaux Clerc committed
312 313 314 315 316 317
 	chat_view=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
 	if(page != NULL){
 		notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch");
 		if(gtk_notebook_page_num(notebook,page)==gtk_notebook_page_num(notebook,chat_view)){
 			cr=g_object_get_data(G_OBJECT(chat_view),"cr");
 			if(cr!=NULL){
318
				linphone_chat_room_mark_as_read(cr);
Margaux Clerc's avatar
Margaux Clerc committed
319
 				linphone_gtk_show_friends();
320
			}
Margaux Clerc's avatar
Margaux Clerc committed
321
 		}
Margaux Clerc's avatar
Margaux Clerc committed
322
	}
323 324
}

325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
void linphone_gtk_chat_selected(GtkWidget *item){
	GtkWidget *w=gtk_widget_get_toplevel(item);
	GtkTreeSelection *select;
	GtkListStore *store=NULL;
	GtkTreeIter iter;
	GtkTreeModel *model;
	LinphoneFriend *lf=NULL;
	LinphoneChatRoom *cr=NULL;
	GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
	GtkWidget *page;

	select=gtk_tree_view_get_selection(GTK_TREE_VIEW(friendlist));
	store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(item)));
	if (gtk_tree_selection_get_selected (select, &model, &iter)){
		GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch");
		const LinphoneAddress *uri;
		gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
Margaux Clerc's avatar
Margaux Clerc committed
342
		gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
343
		uri=linphone_friend_get_address(lf);
Margaux Clerc's avatar
Margaux Clerc committed
344
		if(cr==NULL){
345
			cr=linphone_gtk_create_chatroom(uri);
Margaux Clerc's avatar
Margaux Clerc committed
346
			gtk_list_store_set(store,&iter,FRIEND_CHATROOM,cr,-1);
347
		}
348
		page=GTK_WIDGET(g_object_get_data(G_OBJECT(friendlist),"chatview"));
349
		linphone_gtk_friend_list_set_active_address(uri);
350 351 352 353 354 355
		if(page==NULL){
			page=linphone_gtk_init_chatroom(cr,uri);
			g_object_set_data(G_OBJECT(friendlist),"chatview",(gpointer)page);
		} else {
			linphone_gtk_load_chatroom(cr,uri,page);
		}
356
		linphone_chat_room_mark_as_read(cr);
357
		gtk_notebook_set_current_page(notebook,gtk_notebook_page_num(notebook,page));
358
		g_idle_add((GSourceFunc)grab_focus,linphone_gtk_get_widget(page,"text_entry"));
359 360 361
	}
}

smorlat's avatar
smorlat committed
362
void linphone_gtk_contact_clicked(GtkTreeView     *treeview){
aymeric's avatar
aymeric committed
363
	linphone_gtk_set_selection_to_uri_bar(treeview);
364
	linphone_gtk_friend_list_update_button_display(treeview);
365 366 367 368 369 370 371 372
	if(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(treeview),"numcol"))==1){
		linphone_gtk_call_selected(treeview);
	} else {
		if(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(treeview),"numcol"))==2){
			linphone_gtk_chat_selected(GTK_WIDGET(treeview));
		}
	}
	g_object_set_data(G_OBJECT(treeview),"numcol",GINT_TO_POINTER(0));
373 374 375 376 377 378 379 380 381 382 383 384 385
}


void linphone_gtk_add_button_clicked(void){
	linphone_gtk_add_contact();
}

void linphone_gtk_edit_button_clicked(GtkWidget *button){
	linphone_gtk_edit_contact(button);
}

void linphone_gtk_remove_button_clicked(GtkWidget *button){
	linphone_gtk_remove_contact(button);
aymeric's avatar
aymeric committed
386 387 388 389 390 391 392
}

static GtkWidget * create_presence_menu(){
	GtkWidget *menu=gtk_menu_new();
	GtkWidget *menu_item;
	status_picture_tab_t *t;
	for(t=status_picture_tab;t->img!=NULL;++t){
Simon Morlat's avatar
Simon Morlat committed
393
		if (t->status==LinphoneStatusPending){
aymeric's avatar
aymeric committed
394 395 396 397
			continue;
		}
		menu_item=gtk_image_menu_item_new_with_label(linphone_online_status_to_string(t->status));
		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
398
				gtk_image_new_from_icon_name(t->img, GTK_ICON_SIZE_LARGE_TOOLBAR));
aymeric's avatar
aymeric committed
399 400 401 402 403 404 405 406 407
		gtk_widget_show(menu_item);
		gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_set_my_presence,GINT_TO_POINTER(t->status));
	}
	return menu;
}

void linphone_gtk_set_my_presence(LinphoneOnlineStatus ss){
	GtkWidget *button=linphone_gtk_get_widget(linphone_gtk_get_main_window(),"presence_button");
408
	GtkWidget *image=create_status_picture(ss, GTK_ICON_SIZE_LARGE_TOOLBAR);
aymeric's avatar
aymeric committed
409
	GtkWidget *menu;
410

411
	gtk_widget_set_tooltip_text(button,linphone_online_status_to_string(ss));
aymeric's avatar
aymeric committed
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
	gtk_button_set_image(GTK_BUTTON(button),image);
	/*prepare menu*/
	menu=(GtkWidget*)g_object_get_data(G_OBJECT(button),"presence_menu");
	if (menu==NULL){
		menu=create_presence_menu();
		/*the menu is destroyed when the button is destroyed*/
		g_object_weak_ref(G_OBJECT(button),(GWeakNotify)gtk_widget_destroy,menu);
		g_object_set_data(G_OBJECT(button),"presence_menu",menu);
	}
	linphone_core_set_presence_info(linphone_gtk_get_core(),0,NULL,ss);
}

void linphone_gtk_my_presence_clicked(GtkWidget *button){
	GtkWidget *menu=(GtkWidget*)g_object_get_data(G_OBJECT(button),"presence_menu");
	gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,
			gtk_get_current_event_time());
	gtk_widget_show(menu);
}

431
static void icon_press_handler(GtkEntry *entry){
432
	GtkWidget *w = gtk_widget_get_toplevel(GTK_WIDGET(entry));
433 434
	const char *text=gtk_entry_get_text(entry);
	if (text && strlen(text)>0){
435
		LinphoneAddress *addr;
436
		LinphoneFriend *lf;
437 438 439
		char *uri;
		addr=linphone_core_interpret_url(linphone_gtk_get_core(),text);
		if (addr==NULL){
440 441
			return ;
		}
442
		uri=linphone_address_as_string_uri_only(addr);
443
		lf=linphone_core_get_friend_by_address(linphone_gtk_get_core(),uri);
444
		ms_free(uri);
445
		if (lf==NULL)
446
			lf=linphone_friend_new();
447
		if (lf!=NULL){
448
			linphone_friend_set_address(lf,addr);
449
			linphone_gtk_show_contact(lf, w);
450
		}
451
		linphone_address_destroy(addr);
452 453 454 455
	}
}

static void update_star(GtkEntry *entry, gboolean is_known){
456 457
	if (is_known){
		gtk_entry_set_icon_from_icon_name(entry,GTK_ENTRY_ICON_SECONDARY,"linphone-contact-bookmarked");
458
		gtk_entry_set_icon_tooltip_text(GTK_ENTRY(entry),GTK_ENTRY_ICON_SECONDARY,NULL);
459 460
	}else{
		gtk_entry_set_icon_from_icon_name(entry,GTK_ENTRY_ICON_SECONDARY,"linphone-contact-not-bookmarked");
461
		gtk_entry_set_icon_tooltip_text(GTK_ENTRY(entry),GTK_ENTRY_ICON_SECONDARY,_("Add to addressbook"));
462 463 464 465 466 467 468
	}
}

static void check_contact(GtkEditable *editable, LinphoneCore *lc){
	char *tmp=gtk_editable_get_chars(editable,0,-1);
	if (tmp!=NULL){
		if (strlen(tmp)>0){
469 470 471
			LinphoneAddress *addr=linphone_core_interpret_url(lc,tmp);
			if (addr){
				char *uri=linphone_address_as_string_uri_only(addr);
472 473
				LinphoneFriend *lf=linphone_core_get_friend_by_address(lc,uri);
				ms_free(uri);
474
				linphone_address_destroy(addr);
475 476 477 478 479 480 481 482 483 484 485 486 487
				if (lf) {
					update_star(GTK_ENTRY(editable),TRUE);
					g_free(tmp);
					return;
				}
			}
		}
		g_free(tmp);
	}
	update_star(GTK_ENTRY(editable),FALSE);
}

static void linphone_gtk_init_bookmark_icon(void){
488
	GtkWidget *entry = linphone_gtk_get_widget(linphone_gtk_get_main_window(), "uribar");
489 490 491
	g_signal_connect(G_OBJECT(entry),"icon-release",(GCallback)icon_press_handler,NULL);
	g_signal_connect(G_OBJECT(GTK_EDITABLE(entry)),"changed",(GCallback)check_contact,linphone_gtk_get_core());
}
aymeric's avatar
aymeric committed
492

493 494 495 496 497 498 499 500
static gboolean friend_search_func(GtkTreeModel *model, gint column,
                                                         const gchar *key,
                                                         GtkTreeIter *iter,
                                                         gpointer search_data){
	char *name=NULL;
	gboolean ret=TRUE;
	gtk_tree_model_get(model,iter,FRIEND_NAME,&name,-1);
	if (name!=NULL){
Margaux Clerc's avatar
Margaux Clerc committed
501 502 503 504 505
		gchar *uname=g_utf8_casefold(name,-1); /* need that to perform case-insensitive search in utf8 */
		gchar *ukey=g_utf8_casefold(key,-1);
		ret=strstr(uname,ukey)==NULL;
		g_free(uname);
		g_free(ukey);
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
		g_free(name);
	}
	return ret;
}

static gint friend_sort(GtkTreeModel *model, GtkTreeIter *a,GtkTreeIter *b,gpointer user_data){
	char *n1=NULL,*n2=NULL;
	int ret;
	gtk_tree_model_get(model,a,FRIEND_NAME,&n1,-1);
	gtk_tree_model_get(model,b,FRIEND_NAME,&n2,-1);
	if (n1 && n2) {
		ret=strcmp(n1,n2);
		g_free(n1);
		g_free(n2);
	}else if (n1){
		g_free(n1);
		ret=-1;
	}else if (n2){
		g_free(n2);
		ret=1;
	}else ret=0;
	return ret;
}

530
void linphone_gtk_friend_list_on_name_column_clicked(GtkTreeModel *model){
531 532
	GtkSortType st;
	gint column;
533

534 535 536 537 538 539 540 541 542 543
	gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model),&column,&st);
	if (column==FRIEND_NAME){
		if (st==GTK_SORT_ASCENDING) st=GTK_SORT_DESCENDING;
		else st=GTK_SORT_ASCENDING;
	}else st=GTK_SORT_ASCENDING;
	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),FRIEND_NAME,st);
}

static int get_friend_weight(const LinphoneFriend *lf){
	int w=0;
544 545
	LinphoneCore *lc=linphone_gtk_get_core();
	LinphoneChatRoom *cr=linphone_core_get_chat_room(lc,linphone_friend_get_address(lf));
546

547 548 549
	if (cr && linphone_chat_room_get_unread_messages_count(cr)>0){
		w+=2000;
	}
550

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
	switch(linphone_friend_get_status(lf)){
		case LinphoneStatusOnline:
			w+=1000;
		break;
		case LinphoneStatusOffline:
			if (linphone_friend_get_send_subscribe(lf))
				w+=100;
		break;
		default:
			w+=500;
		break;
	}
	return w;
}

static int friend_compare_func(const LinphoneFriend *lf1, const LinphoneFriend *lf2){
	int w1,w2;
	w1=get_friend_weight(lf1);
	w2=get_friend_weight(lf2);
	if (w1==w2){
		const char *u1,*u2;
		const LinphoneAddress *addr1,*addr2;
		addr1=linphone_friend_get_address(lf1);
		addr2=linphone_friend_get_address(lf2);
		u1=linphone_address_get_username(addr1);
		u2=linphone_address_get_username(addr2);
		if (u1 && u2) return strcasecmp(u1,u2);
		if (u1) return 1;
		else return -1;
	}
	return w2-w1;
}

static MSList *sort_friend_list(const MSList *friends){
	MSList *ret=NULL;
	const MSList *elem;
	LinphoneFriend *lf;

	for(elem=friends;elem!=NULL;elem=elem->next){
		lf=(LinphoneFriend*)elem->data;
		ret=ms_list_insert_sorted(ret,lf,(MSCompareFunc)friend_compare_func);
	}
	return ret;
}

596 597
#if 0
void linphone_gtk_friend_list_on_presence_column_clicked(GtkTreeModel *model){
598 599
	GtkSortType st;
	gint column;
600

601 602 603 604 605 606 607
	gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model),&column,&st);
	if (column==FRIEND_ID){
		if (st==GTK_SORT_ASCENDING) st=GTK_SORT_DESCENDING;
		else st=GTK_SORT_ASCENDING;
	}else st=GTK_SORT_ASCENDING;
	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),FRIEND_ID,st);
}
608
#endif
609

610 611 612 613
void create_button(){
	GtkWidget *main_window = linphone_gtk_get_main_window ();
	GtkWidget *button_add = linphone_gtk_get_widget(main_window,"add_button");
	GtkWidget *image;
614

615
	image=gtk_image_new_from_stock(GTK_STOCK_ADD,GTK_ICON_SIZE_MENU);
616
	gtk_container_add (GTK_CONTAINER (button_add), image);
617 618 619
}

static void linphone_gtk_friend_list_init(GtkWidget *friendlist){
620 621
	GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist));
	GtkTreeSelection *select = gtk_tree_view_get_selection (GTK_TREE_VIEW (friendlist));
622 623

	linphone_gtk_init_bookmark_icon();
624 625
	gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(friendlist),friend_search_func,NULL,NULL);
	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store),FRIEND_NAME,friend_sort,NULL,NULL);
aymeric's avatar
aymeric committed
626
	gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
627 628
	
	g_object_set_data(G_OBJECT(friendlist), "friendlist_initialized", (gpointer)TRUE);
aymeric's avatar
aymeric committed
629 630
}

631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
void linphone_gtk_show_directory_search(void){
	LinphoneProxyConfig *cfg=NULL;
	SipSetupContext * ssc=NULL;
	GtkWidget *mw=linphone_gtk_get_main_window();
	GtkWidget *search_box=linphone_gtk_get_widget(mw,"directory_search_box");

	linphone_core_get_default_proxy(linphone_gtk_get_core(),&cfg);
	if (cfg){
		ssc=linphone_proxy_config_get_sip_setup_context(cfg);
		if (ssc!=NULL && sip_setup_context_get_capabilities(ssc) & SIP_SETUP_CAP_BUDDY_LOOKUP){
			GtkWidget *entry=linphone_gtk_get_widget(mw,"directory_search_entry");
			gchar  *tooltip;
			GdkColor grey={0,40000,40000,40000};
			gtk_widget_show(search_box);
			tooltip=g_strdup_printf(_("Search in %s directory"),linphone_proxy_config_get_domain(cfg));
			gtk_widget_modify_text(entry,GTK_STATE_NORMAL,&grey);
			gtk_entry_set_text(GTK_ENTRY(entry),tooltip);
			g_object_set_data(G_OBJECT(entry),"active",GINT_TO_POINTER(0));
			g_free(tooltip);
			return;
		}
	}
	gtk_widget_hide(search_box);
}

gboolean linphone_gtk_directory_search_focus_out(GtkWidget *entry){
	if (gtk_entry_get_text_length(GTK_ENTRY(entry))==0)
		linphone_gtk_show_directory_search();
	return FALSE;
}

gboolean linphone_gtk_directory_search_focus_in(GtkWidget *entry){
	if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(entry),"active"))==0){
		gtk_entry_set_text(GTK_ENTRY(entry),"");
		gtk_widget_modify_text(entry,GTK_STATE_NORMAL,NULL);
		g_object_set_data(G_OBJECT(entry),"active",GINT_TO_POINTER(1));
	}
	return FALSE;
}

void linphone_gtk_directory_search_activate(GtkWidget *entry){
	LinphoneProxyConfig *cfg;
673
	GtkWidget *w;
674
	linphone_core_get_default_proxy(linphone_gtk_get_core(),&cfg);
675
	w=linphone_gtk_show_buddy_lookup_window(linphone_proxy_config_get_sip_setup_context(cfg));
smorlat's avatar
smorlat committed
676 677
	if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(entry),"active"))==1)
		linphone_gtk_buddy_lookup_set_keyword(w,gtk_entry_get_text(GTK_ENTRY(entry)));
678 679 680 681 682 683 684
}

void linphone_gtk_directory_search_button_clicked(GtkWidget *button){
	linphone_gtk_directory_search_activate(
		linphone_gtk_get_widget(gtk_widget_get_toplevel(button),"directory_search_entry"));
}

aymeric's avatar
aymeric committed
685 686 687 688 689 690 691
void linphone_gtk_show_friends(void){
	GtkWidget *mw=linphone_gtk_get_main_window();
	GtkWidget *friendlist=linphone_gtk_get_widget(mw,"contact_list");
	GtkListStore *store=NULL;
	GtkTreeIter iter;
	const MSList *itf;
	LinphoneCore *core=linphone_gtk_get_core();
692
	MSList *sorted;
Margaux Clerc's avatar
Margaux Clerc committed
693
	LinphoneChatRoom *cr=NULL;
694

695
	linphone_gtk_show_directory_search();
696
	if (!g_object_get_data(G_OBJECT(friendlist), "friendlist_initialized")) {
aymeric's avatar
aymeric committed
697 698
		linphone_gtk_friend_list_init(friendlist);
	}
699

aymeric's avatar
aymeric committed
700 701 702
	store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist)));
	gtk_list_store_clear(store);

703 704 705
	sorted=sort_friend_list(linphone_core_get_friend_list(core));

	for(itf=sorted;itf!=NULL;itf=ms_list_next(itf)){
aymeric's avatar
aymeric committed
706
		LinphoneFriend *lf=(LinphoneFriend*)itf->data;
707
		const LinphoneAddress *f_uri=linphone_friend_get_address(lf);
708
		char *uri=linphone_address_as_string(f_uri);
709
		const char *name=linphone_address_get_display_name(f_uri);
710
		const char *display=name;
aymeric's avatar
aymeric committed
711
		char *escaped=NULL;
Margaux Clerc's avatar
Margaux Clerc committed
712 713
		int nbmsg=0;

714 715 716
		//BuddyInfo *bi;
		gboolean send_subscribe=linphone_friend_get_send_subscribe(lf);
		if (name==NULL || name[0]=='\0') {
717
			display=linphone_address_get_username(f_uri);
aymeric's avatar
aymeric committed
718
		}
719 720
		gtk_list_store_append(store,&iter);
		gtk_list_store_set(store,&iter,FRIEND_NAME, display,FRIEND_ID,lf,
721
				FRIEND_PRESENCE_IMG, send_subscribe ? status_to_icon_name(linphone_friend_get_status(lf)) : NULL,
722
				FRIEND_CHAT,"linphone-chat-nothing", -1);
723 724 725 726
		cr=linphone_gtk_create_chatroom(f_uri);
		gtk_list_store_set(store,&iter,FRIEND_CHATROOM,cr,-1);
		nbmsg=linphone_chat_room_get_unread_messages_count(cr);
		if(nbmsg != 0){
727
			gtk_list_store_set(store,&iter,FRIEND_CHAT,"linphone-chat-new-message",-1);
Margaux Clerc's avatar
Margaux Clerc committed
728
		}
729 730 731
		escaped=g_markup_escape_text(uri,-1);
		gtk_list_store_set(store,&iter,FRIEND_SIP_ADDRESS,escaped,-1);
		g_free(escaped);
aymeric's avatar
aymeric committed
732 733
		ms_free(uri);
	}
734
	ms_list_free(sorted);
aymeric's avatar
aymeric committed
735 736
}

737 738
void linphone_gtk_show_contact(LinphoneFriend *lf, GtkWidget *parent){
	GtkWidget *w=linphone_gtk_create_window("contact", parent);
739
	char *uri;
740
	const char *name;
741
	const LinphoneAddress *f_uri=linphone_friend_get_address(lf);
742
	uri=linphone_address_as_string_uri_only(f_uri);
743
	name=linphone_address_get_display_name(f_uri);
aymeric's avatar
aymeric committed
744 745 746 747 748 749 750 751 752 753 754 755
	if (uri) {
		gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"sip_address")),uri);
		ms_free(uri);
	}
	if (name){
		gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"name")),name);
	}
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"show_presence")),
					linphone_friend_get_send_subscribe(lf));
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"allow_presence")),
					linphone_friend_get_inc_subscribe_policy(lf)==LinphoneSPAccept);
	g_object_set_data(G_OBJECT(w),"friend_ref",(gpointer)lf);
756
	
aymeric's avatar
aymeric committed
757 758 759 760 761 762 763 764 765 766
	gtk_widget_show(w);
}

void linphone_gtk_contact_cancel(GtkWidget *button){
	gtk_widget_destroy(gtk_widget_get_toplevel(button));
}

void linphone_gtk_contact_ok(GtkWidget *button){
	GtkWidget *w=gtk_widget_get_toplevel(button);
	LinphoneFriend *lf=(LinphoneFriend*)g_object_get_data(G_OBJECT(w),"friend_ref");
767
	LinphoneFriend *lf2;
768
	gboolean show_presence=FALSE,allow_presence=FALSE;
aymeric's avatar
aymeric committed
769
	const gchar *name,*uri;
770
	LinphoneAddress* friend_address;
aymeric's avatar
aymeric committed
771 772
	if (lf==NULL){
		lf=linphone_friend_new();
773 774 775 776 777 778
		if (linphone_gtk_get_ui_config_int("use_subscribe_notify",1)==1){
			show_presence=FALSE;
			allow_presence=FALSE;
		}
		linphone_friend_set_inc_subscribe_policy(lf,allow_presence ? LinphoneSPAccept : LinphoneSPDeny);
		linphone_friend_send_subscribe(lf,show_presence);
aymeric's avatar
aymeric committed
779
	}
Margaux Clerc's avatar
Margaux Clerc committed
780 781 782 783 784

	name = NULL;
	if(gtk_entry_get_text_length(GTK_ENTRY(linphone_gtk_get_widget(w,"name"))) != 0){
		name=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"name")));
	}
aymeric's avatar
aymeric committed
785 786 787
	uri=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"sip_address")));
	show_presence=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"show_presence")));
	allow_presence=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"allow_presence")));
788 789
	friend_address=linphone_core_interpret_url(linphone_gtk_get_core(),uri);
	if (friend_address==NULL){
smorlat's avatar
smorlat committed
790 791 792
		linphone_gtk_display_something(GTK_MESSAGE_WARNING,_("Invalid sip contact !"));
		return ;
	}
Margaux Clerc's avatar
Margaux Clerc committed
793

jehan's avatar
jehan committed
794
	linphone_address_set_display_name(friend_address,name);
Margaux Clerc's avatar
Margaux Clerc committed
795
	linphone_friend_set_name(lf,name);
Ghislain MARY's avatar
Ghislain MARY committed
796
	linphone_friend_set_address(lf,friend_address);
aymeric's avatar
aymeric committed
797 798
	linphone_friend_send_subscribe(lf,show_presence);
	linphone_friend_set_inc_subscribe_policy(lf,allow_presence==TRUE ? LinphoneSPAccept : LinphoneSPDeny);
smorlat's avatar
smorlat committed
799
	if (linphone_friend_in_list(lf)) {
aymeric's avatar
aymeric committed
800
		linphone_friend_done(lf);
801
	} else {
802 803 804
		char *uri=linphone_address_as_string_uri_only(friend_address);
		lf2=linphone_core_get_friend_by_address(linphone_gtk_get_core(),uri);
		ms_free(uri);
805 806 807
		if(lf2==NULL){
			linphone_core_add_friend(linphone_gtk_get_core(),lf);
		}
aymeric's avatar
aymeric committed
808
	}
809
	linphone_address_destroy(friend_address);
aymeric's avatar
aymeric committed
810 811 812 813 814 815 816 817 818
	linphone_gtk_show_friends();
	gtk_widget_destroy(w);
}

static GtkWidget *linphone_gtk_create_contact_menu(GtkWidget *contact_list){
	GtkWidget *menu=gtk_menu_new();
	GtkWidget *menu_item;
	gchar *call_label=NULL;
	gchar *text_label=NULL;
smorlat's avatar
smorlat committed
819 820
	gchar *edit_label=NULL;
	gchar *delete_label=NULL;
Margaux Clerc's avatar
Margaux Clerc committed
821
	gchar *delete_hist_label=NULL;
822
	gchar *add_contact_label=NULL;
aymeric's avatar
aymeric committed
823 824 825 826 827
	gchar *name=NULL;
	GtkTreeSelection *select;
	GtkTreeIter iter;
	GtkTreeModel *model;
	GtkWidget *image;
smorlat's avatar
smorlat committed
828 829 830
	LinphoneCore *lc=linphone_gtk_get_core();
	LinphoneProxyConfig *cfg=NULL;
	SipSetupContext * ssc=NULL;
831
	bool_t show_menu_separator=FALSE;
832

smorlat's avatar
smorlat committed
833 834 835 836
	linphone_core_get_default_proxy(lc,&cfg);
	if (cfg){
		ssc=linphone_proxy_config_get_sip_setup_context(cfg);
	}
smorlat's avatar
smorlat committed
837

aymeric's avatar
aymeric committed
838 839
	g_signal_connect(G_OBJECT(menu), "selection-done", G_CALLBACK (gtk_widget_destroy), NULL);
	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(contact_list));
840
	add_contact_label=g_strdup_printf(_("Add a new contact"));
aymeric's avatar
aymeric committed
841 842 843 844
	if (gtk_tree_selection_get_selected (select, &model, &iter)){
		gtk_tree_model_get(model, &iter,FRIEND_NAME , &name, -1);
		call_label=g_strdup_printf(_("Call %s"),name);
		text_label=g_strdup_printf(_("Send text to %s"),name);
smorlat's avatar
smorlat committed
845 846
		edit_label=g_strdup_printf(_("Edit contact '%s'"),name);
		delete_label=g_strdup_printf(_("Delete contact '%s'"),name);
Margaux Clerc's avatar
Margaux Clerc committed
847
		delete_hist_label=g_strdup_printf(_("Delete chat history of '%s'"),name);
aymeric's avatar
aymeric committed
848
		g_free(name);
849
		show_menu_separator=TRUE;
smorlat's avatar
smorlat committed
850
	}
aymeric's avatar
aymeric committed
851 852
	if (call_label){
		menu_item=gtk_image_menu_item_new_with_label(call_label);
853
		image=gtk_image_new_from_icon_name("linphone-start-call",GTK_ICON_SIZE_MENU);
aymeric's avatar
aymeric committed
854 855 856 857 858 859 860 861
		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
		gtk_widget_show(image);
		gtk_widget_show(menu_item);
		gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_call_selected,contact_list);
	}
	if (text_label){
		menu_item=gtk_image_menu_item_new_with_label(text_label);
862
		image=gtk_image_new_from_icon_name("linphone-start-chat",GTK_ICON_SIZE_MENU);
aymeric's avatar
aymeric committed
863 864 865 866 867 868
		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
		gtk_widget_show(image);
		gtk_widget_show(menu_item);
		gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_chat_selected,contact_list);
	}
smorlat's avatar
smorlat committed
869 870
	if (edit_label){
		menu_item=gtk_image_menu_item_new_with_label(edit_label);
871
		image=gtk_image_new_from_icon_name("linphone-edit",GTK_ICON_SIZE_MENU);
smorlat's avatar
smorlat committed
872 873 874 875 876 877 878 879
		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
		gtk_widget_show(image);
		gtk_widget_show(menu_item);
		gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_edit_contact,contact_list);
	}
	if (delete_label){
		menu_item=gtk_image_menu_item_new_with_label(delete_label);
880
		image=gtk_image_new_from_icon_name("linphone-delete",GTK_ICON_SIZE_MENU);
smorlat's avatar
smorlat committed
881 882 883 884 885 886
		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
		gtk_widget_show(image);
		gtk_widget_show(menu_item);
		gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_remove_contact,contact_list);
	}
887

Margaux Clerc's avatar
Margaux Clerc committed
888 889 890 891 892 893 894 895 896
	if (delete_hist_label){
		menu_item=gtk_image_menu_item_new_with_label(delete_hist_label);
		image=gtk_image_new_from_stock(GTK_STOCK_CLEAR,GTK_ICON_SIZE_MENU);
		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
		gtk_widget_show(image);
		gtk_widget_show(menu_item);
		gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_delete_history,contact_list);
	}
smorlat's avatar
smorlat committed
897

smorlat's avatar
smorlat committed
898
	if (ssc && (sip_setup_context_get_capabilities(ssc) & SIP_SETUP_CAP_BUDDY_LOOKUP)) {
smorlat's avatar
smorlat committed
899 900 901
		gchar *tmp=g_strdup_printf(_("Add new contact from %s directory"),linphone_proxy_config_get_domain(cfg));
		menu_item=gtk_image_menu_item_new_with_label(tmp);
		g_free(tmp);
902
		image=gtk_image_new_from_icon_name("linphone-contact-add",GTK_ICON_SIZE_MENU);
smorlat's avatar
smorlat committed
903 904 905 906 907 908
		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
		gtk_widget_show(image);
		gtk_widget_show(menu_item);
		gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_show_buddy_lookup_window,ssc);
	}
909

910 911 912 913 914 915 916 917 918 919
	if (show_menu_separator) {
		GtkWidget *menu_item_separator=gtk_separator_menu_item_new();
		gtk_widget_show(menu_item_separator);
		gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item_separator);
	}

	menu_item=gtk_image_menu_item_new_with_label(add_contact_label);
	image=gtk_image_new_from_icon_name("linphone-contact-add",GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
	gtk_widget_show(image);
aymeric's avatar
aymeric committed
920 921 922 923 924
	gtk_widget_show(menu_item);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
	g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_add_contact,contact_list);
	gtk_widget_show(menu);
	gtk_menu_attach_to_widget (GTK_MENU (menu), contact_list, NULL);
smorlat's avatar
smorlat committed
925

926
	g_free(add_contact_label);
aymeric's avatar
aymeric committed
927 928
	if (call_label) g_free(call_label);
	if (text_label) g_free(text_label);
smorlat's avatar
smorlat committed
929 930
	if (edit_label) g_free(edit_label);
	if (delete_label) g_free(delete_label);
aymeric's avatar
aymeric committed
931 932 933 934 935
	return menu;
}

gboolean linphone_gtk_popup_contact_menu(GtkWidget *list, GdkEventButton *event){
	GtkWidget *m=linphone_gtk_create_contact_menu(list);
936
	gtk_menu_popup (GTK_MENU (m), NULL, NULL, NULL, NULL,
aymeric's avatar
aymeric committed
937 938 939 940
                  event ? event->button : 0, event ? event->time : gtk_get_current_event_time());
	return TRUE;
}

941
gint get_col_number_from_tree_view_column (GtkTreeViewColumn *col){
Margaux Clerc's avatar
Margaux Clerc committed
942 943 944 945 946 947 948
	GList *cols;
	gint   num;
	g_return_val_if_fail ( col != NULL, -1 );
	g_return_val_if_fail ( col->tree_view != NULL, -1 );
	cols = gtk_tree_view_get_columns(GTK_TREE_VIEW(col->tree_view));
	num = g_list_index(cols, (gpointer) col);
	g_list_free(cols);
949

Margaux Clerc's avatar
Margaux Clerc committed
950
	return num;
951 952 953
}

static gint tree_view_get_cell_from_pos(GtkTreeView *view, guint x, guint y){
954 955
	GtkTreeViewColumn *col = NULL;
	GList *node, *columns;
956
	gint colx = 0;
Margaux Clerc's avatar
Margaux Clerc committed
957 958
	GtkTreePath *path;
	GtkTreeViewDropPosition pos;
959

960
	g_return_val_if_fail ( view != NULL, 0 );
961 962
	columns = gtk_tree_view_get_columns(view);

Margaux Clerc's avatar
Margaux Clerc committed
963 964 965 966 967