calllogs.c 14.3 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
/*
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 "linphone.h"

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#define CONFIG_FILE ".linphone-call-history.db"

char *linphone_gtk_call_logs_storage_get_db_file(const char *filename){
	const int path_max=1024;
	char *db_file=NULL;

	db_file=(char *)g_malloc(path_max*sizeof(char));
	if (filename==NULL) filename=CONFIG_FILE;
	/*try accessing a local file first if exists*/
	if (access(CONFIG_FILE,F_OK)==0){
		snprintf(db_file,path_max,"%s",filename);
	}else{
#ifdef WIN32
		const char *appdata=getenv("APPDATA");
		if (appdata){
			snprintf(db_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR);
			CreateDirectory(db_file,NULL);
			snprintf(db_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename);
		}
#else
		const char *home=getenv("HOME");
		if (home==NULL) home=".";
		snprintf(db_file,path_max,"%s/%s",home,filename);
#endif
	}
	return db_file;
}

50 51
static void fill_renderers(GtkTreeView *v){
	GtkTreeViewColumn *c;
Margaux Clerc's avatar
Margaux Clerc committed
52
	GtkCellRenderer *r;
53

54 55
	r=gtk_cell_renderer_pixbuf_new();
	c=gtk_tree_view_column_new_with_attributes("icon",r,"icon-name",0,NULL);
56 57 58 59 60 61 62
	gtk_tree_view_append_column (v,c);

	r=gtk_cell_renderer_text_new ();
	c=gtk_tree_view_column_new_with_attributes("sipaddress",r,"markup",1,NULL);
	gtk_tree_view_append_column (v,c);
}

63 64 65
void call_log_selection_changed(GtkTreeView *v){
	GtkTreeSelection *select;
	GtkTreeIter iter;
66
	GtkTreeModel *model=NULL;
67

68
	select = gtk_tree_view_get_selection(v);
69 70 71 72 73 74 75
	if (select!=NULL){
		if (gtk_tree_selection_get_selected (select, &model, &iter)){
			GtkTreePath *path=gtk_tree_model_get_path(model,&iter);
			gtk_tree_view_collapse_all(v);
			gtk_tree_view_expand_row(v,path,TRUE);
			gtk_tree_path_free(path);
		}
76 77 78
	}
}

79 80 81
void linphone_gtk_call_log_chat_selected(GtkWidget *w){
	GtkTreeSelection *select;
	GtkTreeIter iter;
82

83 84 85 86
	select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
	if (select!=NULL){
		GtkTreeModel *model=NULL;
		if (gtk_tree_selection_get_selected (select,&model,&iter)){
87
			gpointer pcl;
88
			LinphoneAddress *la;
89 90 91 92 93
			LinphoneCallLog *cl;
			gtk_tree_model_get(model,&iter,2,&pcl,-1);
			cl = (LinphoneCallLog *)pcl;
			la = linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl);
			if (la != NULL){
Margaux Clerc's avatar
Margaux Clerc committed
94
				linphone_gtk_friend_list_set_chat_conversation(la);
95 96 97 98 99 100
			}
		}
	}
}

void linphone_gtk_call_log_add_contact(GtkWidget *w){
101
	GtkWidget *main_window = gtk_widget_get_toplevel(w);
102 103
	GtkTreeSelection *select;
	GtkTreeIter iter;
104

105 106 107 108
	select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
	if (select!=NULL){
		GtkTreeModel *model=NULL;
		if (gtk_tree_selection_get_selected (select,&model,&iter)){
109
			gpointer pcl;
110
			LinphoneAddress *la;
111
			LinphoneCallLog *cl;
112
			LinphoneFriend *lf;
113 114 115 116
			gtk_tree_model_get(model,&iter,2,&pcl,-1);
			cl = (LinphoneCallLog *)pcl;
			la = linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl);
			if (la != NULL){
117
				char *uri=linphone_address_as_string(la);
118
				lf=linphone_friend_new_with_address(uri);
119
				linphone_gtk_show_contact(lf, main_window);
120 121 122 123 124 125 126 127 128 129 130 131 132 133
				ms_free(uri);
			}
		}
	}
}

static bool_t put_selection_to_uribar(GtkWidget *treeview){
	GtkTreeSelection *sel;
	sel=gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
	if (sel!=NULL){
		GtkTreeModel *model=NULL;
		GtkTreeIter iter;
		if (gtk_tree_selection_get_selected (sel,&model,&iter)){
			char *tmp;
134
			gpointer pcl;
135
			LinphoneAddress *la;
136 137 138 139 140
			LinphoneCallLog *cl;
			gtk_tree_model_get(model,&iter,2,&pcl,-1);
			cl = (LinphoneCallLog *)pcl;
			la = linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl);
			tmp = linphone_address_as_string(la);
141
			if(tmp!=NULL)
142
				gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),tmp);
143 144 145 146 147 148 149 150 151 152 153 154 155 156
			ms_free(tmp);
			return TRUE;
		}
	}
	return FALSE;
}

static void linphone_gtk_call_selected(GtkTreeView *treeview){
	put_selection_to_uribar(GTK_WIDGET(treeview));
	linphone_gtk_start_call(linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(treeview)),
					"start_call"));
}

static GtkWidget *linphone_gtk_create_call_log_menu(GtkWidget *call_log){
157
	GtkWidget *menu=NULL;
158 159 160
	GtkWidget *menu_item;
	gchar *call_label=NULL;
	gchar *text_label=NULL;
161
	gchar *add_contact_label=NULL;
162 163 164 165
	gchar *name=NULL;
	GtkWidget *image;
	GtkTreeSelection *select;
	GtkTreeIter iter;
166

167 168 169 170
	select=gtk_tree_view_get_selection(GTK_TREE_VIEW(call_log));
	if (select!=NULL){
		GtkTreeModel *model=NULL;
		if (gtk_tree_selection_get_selected (select,&model,&iter)){
171
			gpointer pcl;
172
			LinphoneAddress *la;
173 174 175 176
			LinphoneCallLog *cl;
			gtk_tree_model_get(model,&iter,2,&pcl,-1);
			cl = (LinphoneCallLog *)pcl;
			la = linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl);
177 178 179
			name=linphone_address_as_string(la);
			call_label=g_strdup_printf(_("Call %s"),name);
			text_label=g_strdup_printf(_("Send text to %s"),name);
180 181 182
			if (!linphone_gtk_is_friend(linphone_gtk_get_core(), name)) {
				add_contact_label=g_strdup_printf(_("Add %s to your contact list"),name);
			}
183
			ms_free(name);
184
			menu=gtk_menu_new();
185 186
		}
	}
187
	if (menu && call_label){
188
		menu_item=gtk_image_menu_item_new_with_label(call_label);
189
		image=gtk_image_new_from_icon_name("linphone-start-call",GTK_ICON_SIZE_MENU);
190 191 192 193 194 195
		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,call_log);
	}
196
	if (menu && text_label){
197
		menu_item=gtk_image_menu_item_new_with_label(text_label);
198
		image=gtk_image_new_from_icon_name("linphone-start-chat",GTK_ICON_SIZE_MENU);
199 200 201 202 203 204
		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_log_chat_selected,call_log);
	}
205 206 207 208 209 210 211 212 213 214 215 216 217
	if (menu && add_contact_label){
		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);
		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_log_add_contact,call_log);
	}
	if (menu) {
		gtk_widget_show(menu);
		gtk_menu_attach_to_widget(GTK_MENU(menu),call_log, NULL);
	}
218

219
	if (add_contact_label) g_free(add_contact_label);
220 221 222 223 224 225 226
	if (call_label) g_free(call_label);
	if (text_label) g_free(text_label);
	return menu;
}

gboolean linphone_gtk_call_log_popup_contact(GtkWidget *list, GdkEventButton *event){
	GtkWidget *m=linphone_gtk_create_call_log_menu(list);
227 228 229 230 231 232
	if (m) {
		gtk_menu_popup (GTK_MENU (m), NULL, NULL, NULL, NULL,
			event ? event->button : 0, event ? event->time : gtk_get_current_event_time());
		return TRUE;
	}
	return FALSE;
233 234 235 236 237 238 239 240 241
}

gboolean linphone_gtk_call_log_button_pressed(GtkWidget *widget, GdkEventButton *event){
	if (event->button == 3 && event->type == GDK_BUTTON_PRESS){
		return linphone_gtk_call_log_popup_contact(widget, event);
	}
	return FALSE;
}

242
void linphone_gtk_call_log_clear_missed_call(void){
243 244 245
	GtkWidget *mw = linphone_gtk_get_main_window();
	GtkWidget *label = linphone_gtk_get_widget(mw, "history_tab_label");
	gtk_label_set_text(GTK_LABEL(label), _("Recent calls"));
246 247 248
}

gboolean linphone_gtk_call_log_reset_missed_call(GtkWidget *w, GdkEvent *event,gpointer user_data){
Margaux Clerc's avatar
Margaux Clerc committed
249 250 251
	GtkWidget *mw=linphone_gtk_get_main_window();
	GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(mw,"viewswitch"));
	gtk_notebook_set_current_page(notebook,0);
252 253 254 255 256 257
	linphone_core_reset_missed_calls_count(linphone_gtk_get_core());
	linphone_gtk_call_log_clear_missed_call();
	return TRUE;
}

void linphone_gtk_call_log_display_missed_call(int nb){
258 259 260 261
	GtkWidget *mw = linphone_gtk_get_main_window();
	GtkWidget *label = linphone_gtk_get_widget(mw, "history_tab_label");
	gchar *buf = g_markup_printf_escaped(_("<b>Recent calls (%i)</b>"), nb);
	gtk_label_set_markup(GTK_LABEL(label), buf);
262 263
}

aymeric's avatar
aymeric committed
264
void linphone_gtk_call_log_update(GtkWidget *w){
265
	GtkTreeView *v=GTK_TREE_VIEW(linphone_gtk_get_widget(w,"logs_view"));
Margaux Clerc's avatar
Margaux Clerc committed
266
	GtkTreeStore *store;
267
	const MSList *logs;
268
	GtkTreeSelection *select;
269 270
	GtkWidget *notebook=linphone_gtk_get_widget(w,"viewswitch");
	gint nb;
271

Margaux Clerc's avatar
Margaux Clerc committed
272
	store=(GtkTreeStore*)gtk_tree_view_get_model(v);
273
	if (store==NULL){
274
		store=gtk_tree_store_new(3,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_POINTER,G_TYPE_STRING);
275
		gtk_tree_view_set_model(v,GTK_TREE_MODEL(store));
Simon Morlat's avatar
Simon Morlat committed
276
		g_object_unref(G_OBJECT(store));
277
		fill_renderers(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"logs_view")));
278 279 280
		select=gtk_tree_view_get_selection(v);
		gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
		g_signal_connect_swapped(G_OBJECT(select),"changed",(GCallback)call_log_selection_changed,v);
281
		g_signal_connect(G_OBJECT(notebook),"focus-tab",(GCallback)linphone_gtk_call_log_reset_missed_call,NULL);
282
		g_signal_connect(G_OBJECT(v),"button-press-event",(GCallback)linphone_gtk_call_log_button_pressed,NULL);
283
	}
284 285 286
	nb=linphone_core_get_missed_calls_count(linphone_gtk_get_core());
	if(nb > 0)
		linphone_gtk_call_log_display_missed_call(nb);
Margaux Clerc's avatar
Margaux Clerc committed
287
	gtk_tree_store_clear (store);
288

aymeric's avatar
aymeric committed
289 290
	for (logs=linphone_core_get_call_logs(linphone_gtk_get_core());logs!=NULL;logs=logs->next){
		LinphoneCallLog *cl=(LinphoneCallLog*)logs->data;
Margaux Clerc's avatar
Margaux Clerc committed
291
		GtkTreeIter iter, iter2;
292
		LinphoneAddress *la=linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl);
293
		char *addr= linphone_address_as_string(la);
294
		const char *display;
Margaux Clerc's avatar
Margaux Clerc committed
295
		gchar *logtxt, *headtxt, *minutes, *seconds;
296
		gchar quality[20];
297
		const char *status=NULL;
298
		gchar *start_date=NULL;
299
		LinphoneFriend *lf=NULL;
300
		int duration=linphone_call_log_get_duration(cl);
301
		time_t start_date_time=linphone_call_log_get_start_date(cl);
302
		const gchar *call_status_icon_name;
303

Simon Morlat's avatar
Simon Morlat committed
304
#if GLIB_CHECK_VERSION(2,26,0)
305 306
		if (start_date_time){
			GDateTime *dt=g_date_time_new_from_unix_local(start_date_time);
307 308 309
			start_date=g_date_time_format(dt,"%c");
			g_date_time_unref(dt);
		}
310
#else
Simon Morlat's avatar
Simon Morlat committed
311
		start_date=g_strdup(ctime(&start_date_time));
Simon Morlat's avatar
Simon Morlat committed
312
#endif
313 314
		lf=linphone_core_get_friend_by_address(linphone_gtk_get_core(),addr);
		if(lf != NULL){
315 316 317 318
			if ((display=linphone_address_get_display_name(linphone_friend_get_address(lf)))) {
				/*update display name from friend*/
				linphone_address_set_display_name(la,display);
			}
319 320 321
		} else {
			display=linphone_address_get_display_name(la);
		}
322 323
		if (display==NULL){
			display=linphone_address_get_username (la);
324
			if (display==NULL){
325
				display=linphone_address_get_domain (la);
326
			}
327
		}
328

329 330 331 332
		if (linphone_call_log_get_quality(cl)!=-1){
			snprintf(quality,sizeof(quality),"%.1f",linphone_call_log_get_quality(cl));
		}else snprintf(quality,sizeof(quality)-1,"%s",_("n/a"));
		switch(linphone_call_log_get_status(cl)){
333 334 335 336 337 338 339 340 341 342 343 344
			case LinphoneCallAborted:
				status=_("Aborted");
			break;
			case LinphoneCallMissed:
				status=_("Missed");
			break;
			case LinphoneCallDeclined:
				status=_("Declined");
			break;
			default:
			break;
		}
345
		minutes=g_markup_printf_escaped(
346 347
			ngettext("%i minute", "%i minutes", duration/60),
			duration/60);
348
		seconds=g_markup_printf_escaped(
349 350
			ngettext("%i second", "%i seconds", duration%60),
			duration%60);
Margaux Clerc's avatar
Margaux Clerc committed
351
		if (status==NULL) {
352
				headtxt=g_markup_printf_escaped("<big><b>%s</b></big>\t%s",display,start_date ? start_date : "");
Margaux Clerc's avatar
Margaux Clerc committed
353
				logtxt=g_markup_printf_escaped(
354
				_("<small><i>%s</i>\t"
Margaux Clerc's avatar
Margaux Clerc committed
355 356 357 358 359
				  "<i>Quality: %s</i></small>\n%s\t%s\t"),
				addr, quality, minutes, seconds);
		} else {
			headtxt=g_markup_printf_escaped(_("<big><b>%s</b></big>\t%s"),display,start_date ? start_date : "");
			logtxt=g_markup_printf_escaped(
360 361
			"<small><i>%s</i></small>\t"
				"\n%s",addr, status);
Margaux Clerc's avatar
Margaux Clerc committed
362
		}
363 364
		g_free(minutes);
		g_free(seconds);
365
		if (start_date) g_free(start_date);
Margaux Clerc's avatar
Margaux Clerc committed
366
		gtk_tree_store_append (store,&iter,NULL);
367 368
		call_status_icon_name = linphone_call_log_get_dir(cl) == LinphoneCallOutgoing ?
			"linphone-call-status-outgoing" : "linphone-call-status-incoming";
Margaux Clerc's avatar
Margaux Clerc committed
369
		gtk_tree_store_set (store,&iter,
370
		               0, call_status_icon_name,
371
		               1, headtxt,2,cl,-1);
Margaux Clerc's avatar
Margaux Clerc committed
372
		gtk_tree_store_append (store,&iter2,&iter);
373
		gtk_tree_store_set (store,&iter2,1,logtxt,-1);
374 375
		ms_free(addr);
		g_free(logtxt);
Margaux Clerc's avatar
Margaux Clerc committed
376
		g_free(headtxt);
377 378 379
	}
}

Simon Morlat's avatar
Simon Morlat committed
380
void linphone_gtk_history_row_activated(GtkWidget *treeview){
381 382 383 384 385 386
	if (put_selection_to_uribar(treeview)){
		GtkWidget *mw=linphone_gtk_get_main_window();
		linphone_gtk_start_call(linphone_gtk_get_widget(mw,"start_call"));
	}
}

387 388 389 390
void linphone_gtk_history_row_selected(GtkWidget *treeview){
	put_selection_to_uribar(treeview);
}

391 392
void linphone_gtk_clear_call_logs(GtkWidget *button){
	linphone_core_clear_call_logs (linphone_gtk_get_core());
Margaux Clerc's avatar
Margaux Clerc committed
393
	linphone_gtk_call_log_clear_missed_call();
394 395 396 397 398 399 400
	linphone_gtk_call_log_update(gtk_widget_get_toplevel(button));
}

void linphone_gtk_call_log_callback(GtkWidget *button){
	GtkWidget *mw=linphone_gtk_get_main_window();
	if (put_selection_to_uribar(linphone_gtk_get_widget(mw,"logs_view")))
			linphone_gtk_start_call(linphone_gtk_get_widget(mw,"start_call"));
aymeric's avatar
aymeric committed
401 402
}

Simon Morlat's avatar
Simon Morlat committed
403
void linphone_gtk_call_log_response(GtkWidget *w, guint response_id){
aymeric's avatar
aymeric committed
404
	GtkWidget *mw=linphone_gtk_get_main_window();
Simon Morlat's avatar
Simon Morlat committed
405 406 407 408 409 410 411 412
	if (response_id==1){
		if (put_selection_to_uribar(linphone_gtk_get_widget(w,"logs_view")))
			linphone_gtk_start_call(linphone_gtk_get_widget(mw,"start_call"));
	}else if (response_id==2){
		linphone_core_clear_call_logs (linphone_gtk_get_core());
		linphone_gtk_call_log_update(w);
		return;
	}
aymeric's avatar
aymeric committed
413 414 415
	g_object_set_data(G_OBJECT(mw),"call_logs",NULL);
	gtk_widget_destroy(w);
}