From c40cfeb0fe12b6803d25a11664fd16d49a4a9b2a Mon Sep 17 00:00:00 2001 From: Simon Morlat <simon.morlat@linphone.org> Date: Thu, 12 Jan 2012 17:16:06 +0100 Subject: [PATCH] gtk-ui: implement friend lookup and sorting --- NEWS | 3 + gtk/friendlist.c | 170 ++++++++++++++++++++++++++++++++++------------- gtk/main.ui | 19 +++--- mediastreamer2 | 2 +- 4 files changed, 136 insertions(+), 58 deletions(-) diff --git a/NEWS b/NEWS index 15cefbb713..a4b134ddfc 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +linphone-3.5.1 -- ?? + * gtk - implement friend search by typing into the friendlist, and friend sorting + linphone-3.5.0 -- December 22, 2011 * added VP-8 video codec * added G722 audio codec diff --git a/gtk/friendlist.c b/gtk/friendlist.c index 9dacac7178..d5a056feff 100644 --- a/gtk/friendlist.c +++ b/gtk/friendlist.c @@ -239,6 +239,119 @@ static void linphone_gtk_init_bookmark_icon(void){ g_signal_connect(G_OBJECT(GTK_EDITABLE(entry)),"changed",(GCallback)check_contact,linphone_gtk_get_core()); } +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){ + ret=strstr(name,key)==NULL; + 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; +} + +static void on_name_column_clicked(GtkTreeModel *model){ + GtkSortType st; + gint column; + + 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; + 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 gint friend_sort_with_presence(GtkTreeModel *model, GtkTreeIter *a,GtkTreeIter *b,gpointer user_data){ + LinphoneFriend *lf1=NULL,*lf2=NULL; + gtk_tree_model_get(model,a,FRIEND_ID,&lf1,-1); + gtk_tree_model_get(model,b,FRIEND_ID,&lf2,-1); + return friend_compare_func(lf1,lf2); +} + + +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; +} + +static void on_presence_column_clicked(GtkTreeModel *model){ + GtkSortType st; + gint column; + + 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); +} + static void linphone_gtk_friend_list_init(GtkWidget *friendlist) { GtkListStore *store; @@ -254,12 +367,21 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist) gtk_tree_view_set_model(GTK_TREE_VIEW(friendlist),GTK_TREE_MODEL(store)); g_object_unref(G_OBJECT(store)); + gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(friendlist),friend_search_func,NULL,NULL); + gtk_tree_view_set_search_column(GTK_TREE_VIEW(friendlist),FRIEND_NAME); + + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store),FRIEND_NAME,friend_sort,NULL,NULL); + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store),FRIEND_ID,friend_sort_with_presence,NULL,NULL); + renderer = gtk_cell_renderer_pixbuf_new (); column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, "pixbuf", FRIEND_ICON, NULL); g_object_set (G_OBJECT(column), "resizable", TRUE, NULL); + g_signal_connect_swapped(G_OBJECT(column),"clicked",(GCallback)on_name_column_clicked,GTK_TREE_MODEL(store)); + gtk_tree_view_column_set_clickable(column,TRUE); + renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start(column,renderer,FALSE); gtk_tree_view_column_add_attribute (column,renderer, @@ -273,6 +395,8 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist) "text", FRIEND_PRESENCE_STATUS, NULL); g_object_set (G_OBJECT(column), "resizable", TRUE, NULL); + g_signal_connect_swapped(G_OBJECT(column),"clicked",(GCallback)on_presence_column_clicked,GTK_TREE_MODEL(store)); + gtk_tree_view_column_set_clickable(column,TRUE); gtk_tree_view_column_set_visible(column,linphone_gtk_get_ui_config_int("friendlist_status",1)); renderer = gtk_cell_renderer_pixbuf_new(); @@ -344,52 +468,6 @@ void linphone_gtk_directory_search_button_clicked(GtkWidget *button){ linphone_gtk_get_widget(gtk_widget_get_toplevel(button),"directory_search_entry")); } -static int get_friend_weight(const LinphoneFriend *lf){ - int w=0; - 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; -} void linphone_gtk_show_friends(void){ GtkWidget *mw=linphone_gtk_get_main_window(); diff --git a/gtk/main.ui b/gtk/main.ui index 7ebe953635..fde3a794a6 100644 --- a/gtk/main.ui +++ b/gtk/main.ui @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <interface> <requires lib="gtk+" version="2.18"/> - <!-- interface-naming-policy toplevel-contextual --> <object class="GtkWindow" id="dummy_conf_window"> <property name="can_focus">False</property> <child> @@ -652,8 +651,6 @@ <property name="invisible_char">â—</property> <property name="primary_icon_activatable">False</property> <property name="secondary_icon_activatable">False</property> - <property name="primary_icon_sensitive">True</property> - <property name="secondary_icon_sensitive">True</property> <signal name="activate" handler="linphone_gtk_uri_bar_activate" swapped="no"/> </object> <packing> @@ -745,8 +742,6 @@ <property name="invisible_char_set">True</property> <property name="primary_icon_activatable">False</property> <property name="secondary_icon_activatable">False</property> - <property name="primary_icon_sensitive">True</property> - <property name="secondary_icon_sensitive">True</property> <signal name="changed" handler="linphone_gtk_show_friends" swapped="no"/> </object> <packing> @@ -808,10 +803,15 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="reorderable">True</property> + <property name="search_column">0</property> <signal name="button-press-event" handler="linphone_gtk_contact_list_button_pressed" swapped="no"/> <signal name="cursor-changed" handler="linphone_gtk_contact_clicked" swapped="no"/> <signal name="row-activated" handler="linphone_gtk_contact_activated" swapped="no"/> <signal name="popup-menu" handler="linphone_gtk_popup_contact_menu" swapped="no"/> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="treeview-selection1"/> + </child> </object> </child> </object> @@ -837,8 +837,6 @@ <property name="invisible_char_set">True</property> <property name="primary_icon_activatable">False</property> <property name="secondary_icon_activatable">False</property> - <property name="primary_icon_sensitive">True</property> - <property name="secondary_icon_sensitive">True</property> <signal name="activate" handler="linphone_gtk_directory_search_activate" swapped="no"/> <signal name="icon-press" handler="linphone_gtk_directory_search_activate" swapped="no"/> <signal name="focus-in-event" handler="linphone_gtk_directory_search_focus_in" swapped="no"/> @@ -1037,6 +1035,9 @@ <property name="headers_visible">False</property> <signal name="cursor-changed" handler="linphone_gtk_history_row_selected" swapped="no"/> <signal name="row-activated" handler="linphone_gtk_history_row_activated" swapped="no"/> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="treeview-selection2"/> + </child> </object> </child> </object> @@ -1540,8 +1541,6 @@ <property name="invisible_char">â—</property> <property name="primary_icon_activatable">False</property> <property name="secondary_icon_activatable">False</property> - <property name="primary_icon_sensitive">True</property> - <property name="secondary_icon_sensitive">True</property> </object> <packing> <property name="left_attach">1</property> @@ -1556,8 +1555,6 @@ <property name="invisible_char">â—</property> <property name="primary_icon_activatable">False</property> <property name="secondary_icon_activatable">False</property> - <property name="primary_icon_sensitive">True</property> - <property name="secondary_icon_sensitive">True</property> </object> <packing> <property name="left_attach">1</property> diff --git a/mediastreamer2 b/mediastreamer2 index 668bdcc2c0..c8106487fa 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 668bdcc2c04a487fb94f31b7790ef301908c47b5 +Subproject commit c8106487faa8cee02f4dd94b03e4f9185b236b4e -- GitLab