From 3536b4840a51c29037890cf394e0b76b8ac8cb38 Mon Sep 17 00:00:00 2001 From: smorlat Date: Wed, 21 Oct 2009 19:21:04 +0000 Subject: [PATCH] Implement display of user's icon in buddylookup's list. git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@726 3f6dc0c8-ddfe-455d-9043-3cd528dc4637 --- linphone/coreapi/plugins/buddylookup/INSTALL | 0 .../coreapi/plugins/buddylookup/src/lookup.c | 31 +++++-- linphone/coreapi/sipsetup.c | 13 ++- linphone/coreapi/sipsetup.h | 7 ++ linphone/gtk-glade/buddylookup.c | 81 +++++++++++++++---- linphone/gtk-glade/buddylookup.glade | 2 + linphone/gtk-glade/linphone.h | 3 + linphone/gtk-glade/utils.c | 21 +++++ 8 files changed, 137 insertions(+), 21 deletions(-) mode change 100755 => 100644 linphone/coreapi/plugins/buddylookup/INSTALL diff --git a/linphone/coreapi/plugins/buddylookup/INSTALL b/linphone/coreapi/plugins/buddylookup/INSTALL old mode 100755 new mode 100644 diff --git a/linphone/coreapi/plugins/buddylookup/src/lookup.c b/linphone/coreapi/plugins/buddylookup/src/lookup.c index 01a905511..488a2146d 100644 --- a/linphone/coreapi/plugins/buddylookup/src/lookup.c +++ b/linphone/coreapi/plugins/buddylookup/src/lookup.c @@ -81,8 +81,8 @@ static void fill_item(GHashTable *ht , const char *name, char *dest, size_t dest }else ms_warning("no field named '%s'", name); } -static void fill_buddy_info(BuddyInfo *bi, GHashTable *ht){ - char tmp[128]; +static void fill_buddy_info(BuddyLookupState *s, BuddyInfo *bi, GHashTable *ht){ + char tmp[256]; fill_item(ht,"first_name",bi->firstname,sizeof(bi->firstname)); fill_item(ht,"last_name",bi->lastname,sizeof(bi->lastname)); fill_item(ht,"display_name",bi->displayname,sizeof(bi->displayname)); @@ -98,9 +98,28 @@ static void fill_buddy_info(BuddyInfo *bi, GHashTable *ht){ fill_item(ht,"city",bi->address.town,sizeof(bi->address.town)); fill_item(ht,"country",bi->address.country,sizeof(bi->address.country)); fill_item(ht,"email",bi->email,sizeof(bi->email)); + tmp[0]='\0'; + fill_item(ht,"image",tmp,sizeof(tmp)); + if (tmp[0]!='\0'){ + SoupMessage *msg; + guint status; + ms_message("This buddy has an image, let's download it: %s",tmp); + msg=soup_message_new("GET",tmp); + if ((status=soup_session_send_message(s->session,msg))==200){ + SoupMessageBody *body=msg->response_body; + ms_message("Received %i bytes",body->length); + strncpy(bi->image_type,"png",sizeof(bi->image_type)); + bi->image_length=body->length; + bi->image_data=ms_malloc(body->length+4); /*add padding bytes*/ + memcpy(bi->image_data,body->data,bi->image_length); + }else{ + ms_error("Fail to fetch the image %i",status); + } + } + } -static MSList * make_buddy_list(GValue *retval){ +static MSList * make_buddy_list(BuddyLookupState *s, GValue *retval){ MSList *ret=NULL; if (G_VALUE_TYPE(retval)==G_TYPE_VALUE_ARRAY){ GValueArray *array=(GValueArray*)g_value_get_boxed(retval); @@ -110,8 +129,8 @@ static MSList * make_buddy_list(GValue *retval){ gelem=g_value_array_get_nth(array,i); if (G_VALUE_TYPE(gelem)==G_TYPE_HASH_TABLE){ GHashTable *ht=(GHashTable*)g_value_get_boxed(gelem); - BuddyInfo *bi=ms_new0(BuddyInfo,1); - fill_buddy_info(bi,ht); + BuddyInfo *bi=buddy_info_new(); + fill_buddy_info(s,bi,ht); ret=ms_list_append(ret,bi); }else{ ms_error("Element is not a hash table"); @@ -139,7 +158,7 @@ static int xml_rpc_parse_response(SipSetupContext *ctx, SoupMessage *sm){ s->status=BuddyLookupFailure; }else{ ms_message("Extracting values from return type..."); - s->results=make_buddy_list(&retval); + s->results=make_buddy_list(s,&retval); g_value_unset(&retval); s->status=BuddyLookupDone; } diff --git a/linphone/coreapi/sipsetup.c b/linphone/coreapi/sipsetup.c index 84c221105..738e273db 100644 --- a/linphone/coreapi/sipsetup.c +++ b/linphone/coreapi/sipsetup.c @@ -176,7 +176,7 @@ const char ** sip_setup_context_get_domains(SipSetupContext *ctx){ void sip_setup_context_free_results(MSList *results){ - ms_list_for_each(results,(void (*)(void*))&ms_free); + ms_list_for_each(results,(void (*)(void*))&buddy_info_free); ms_list_free(results); } @@ -193,3 +193,14 @@ void sip_setup_context_free(SipSetupContext *ctx){ } ms_free(ctx); } + + +BuddyInfo *buddy_info_new(){ + return ms_new0(BuddyInfo,1); +} + +void buddy_info_free(BuddyInfo *info){ + if (info->image_data!=NULL) + ms_free(info->image_data); + ms_free(info); +} diff --git a/linphone/coreapi/sipsetup.h b/linphone/coreapi/sipsetup.h index d0840e915..6e3443953 100644 --- a/linphone/coreapi/sipsetup.h +++ b/linphone/coreapi/sipsetup.h @@ -68,6 +68,9 @@ typedef struct _BuddyInfo{ char sip_uri[128]; char email[128]; BuddyAddress address; + char image_type[32]; + uint8_t *image_data; + int image_length; }BuddyInfo; @@ -100,6 +103,10 @@ typedef struct _SipSetup SipSetup; extern "C"{ #endif +BuddyInfo *buddy_info_new(); +void buddy_info_free(BuddyInfo *info); + + void sip_setup_register(SipSetup *ss); void sip_setup_register_all(void); SipSetup *sip_setup_lookup(const char *type_name); diff --git a/linphone/gtk-glade/buddylookup.c b/linphone/gtk-glade/buddylookup.c index 9518a2a70..8aa5479a9 100644 --- a/linphone/gtk-glade/buddylookup.c +++ b/linphone/gtk-glade/buddylookup.c @@ -26,6 +26,7 @@ enum { LOOKUP_RESULT_NAME, LOOKUP_RESULT_SIP_URI, LOOKUP_RESULT_ADDRESS, + LOOKUP_RESULT_ICON, LOOKUP_RESULT_NCOL }; @@ -48,41 +49,71 @@ static void disable_add_buddy_button(GtkWidget *w){ gtk_widget_set_sensitive(linphone_gtk_get_widget(w,"add_buddy"),FALSE); } +static void buddy_selection_changed(GtkWidget *w){ + GtkWidget *results=linphone_gtk_get_widget(w,"search_results"); + GtkTreeSelection *select; + GtkTreeIter iter; + GtkTreeModel *model; + enable_add_buddy_button(w); + + select = gtk_tree_view_get_selection(GTK_TREE_VIEW(results)); + if (gtk_tree_selection_get_selected (select, &model, &iter)) + { + GtkTreePath *path=gtk_tree_model_get_path(model,&iter); + gtk_tree_view_collapse_all(GTK_TREE_VIEW(results)); + gtk_tree_view_expand_row(GTK_TREE_VIEW(results),path,FALSE); + gtk_tree_path_free(path); + } +} + GtkWidget * linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx){ - GtkListStore *store; - GtkCellRenderer *renderer; + GtkTreeStore *store; + GtkCellRenderer *renderer,*pbuf_renderer; GtkTreeViewColumn *column; GtkTreeSelection *select; GtkWidget *w=linphone_gtk_create_window("buddylookup"); GtkWidget *results=linphone_gtk_get_widget(w,"search_results"); GtkProgressBar *pb=GTK_PROGRESS_BAR(linphone_gtk_get_widget(w,"progressbar")); - store = gtk_list_store_new(LOOKUP_RESULT_NCOL, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + store = gtk_tree_store_new(LOOKUP_RESULT_NCOL, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF); + /*gtk_tree_view_set_hover_expand(GTK_TREE_VIEW(results),TRUE);*/ gtk_tree_view_set_model(GTK_TREE_VIEW(results),GTK_TREE_MODEL(store)); g_object_unref(G_OBJECT(store)); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Firstname, Lastname"), renderer, - "text", LOOKUP_RESULT_NAME, + "markup", LOOKUP_RESULT_NAME, NULL); g_object_set (G_OBJECT(column), "resizable", TRUE, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (results), column); + + pbuf_renderer=gtk_cell_renderer_pixbuf_new(); + g_object_set(G_OBJECT(renderer),"is-expander",TRUE,NULL); + gtk_tree_view_column_pack_start(column,pbuf_renderer,FALSE); + gtk_tree_view_column_add_attribute (column,pbuf_renderer, + "pixbuf", + LOOKUP_RESULT_ICON); + gtk_tree_view_append_column (GTK_TREE_VIEW (results), column); + +/* column = gtk_tree_view_column_new_with_attributes (_("SIP address"), renderer, "text", LOOKUP_RESULT_SIP_URI, NULL); g_object_set (G_OBJECT(column), "resizable", TRUE, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (results), column); - +*/ + select = gtk_tree_view_get_selection (GTK_TREE_VIEW (results)); gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE); - g_signal_connect_swapped(G_OBJECT(select),"changed",(GCallback)enable_add_buddy_button,w); + g_signal_connect_swapped(G_OBJECT(select),"changed",(GCallback)buddy_selection_changed,w); +/* #if GTK_CHECK_VERSION(2,12,0) gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(results),LOOKUP_RESULT_ADDRESS); #endif +*/ g_object_set_data(G_OBJECT(w),"SipSetupContext",ctx); g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_gtk_buddy_lookup_window_destroyed,w); //g_signal_connect_swapped(G_OBJECT(w),"destroy",(GCallback)linphone_gtk_buddy_lookup_window_destroyed,w); @@ -181,23 +212,45 @@ void linphone_gtk_keyword_changed(GtkEditable *e){ } static void linphone_gtk_display_lookup_results(GtkWidget *w, const MSList *results){ - GtkListStore *store; + GtkTreeStore *store; GtkTreeIter iter; gchar *tmp; const MSList *elem; - store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(w))); - gtk_list_store_clear(store); + store=GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(w))); + gtk_tree_store_clear(store); disable_add_buddy_button(gtk_widget_get_toplevel(w)); for(elem=results;elem!=NULL;elem=elem->next){ BuddyInfo *bi=(BuddyInfo*)elem->data; - gtk_list_store_append(store,&iter); + GdkPixbuf *pbuf; + GtkTreeIter depth1; + gtk_tree_store_append(store,&iter,NULL); tmp=g_strdup_printf("%s, %s (%s)",bi->firstname,bi->lastname,bi->displayname); - gtk_list_store_set(store,&iter,LOOKUP_RESULT_NAME, tmp,-1); + gtk_tree_store_set(store,&iter,LOOKUP_RESULT_NAME, tmp,-1); g_free(tmp); - gtk_list_store_set(store,&iter,LOOKUP_RESULT_SIP_URI, bi->sip_uri,-1); + gtk_tree_store_set(store,&iter,LOOKUP_RESULT_SIP_URI, bi->sip_uri,-1); tmp=g_strdup_printf("%s, %s %s\n%s",bi->address.street, bi->address.zip, bi->address.town, bi->address.country); - gtk_list_store_set(store,&iter,LOOKUP_RESULT_ADDRESS, tmp,-1); + gtk_tree_store_set(store,&iter,LOOKUP_RESULT_ADDRESS, tmp,-1); g_free(tmp); + if (bi->image_data!=NULL){ + pbuf=_gdk_pixbuf_new_from_memory_at_scale(bi->image_data,bi->image_length,-1,40,TRUE); + if (pbuf) { + gtk_tree_store_set(store,&iter,LOOKUP_RESULT_ICON,pbuf,-1); + g_object_unref(G_OBJECT(pbuf)); + } + } + gtk_tree_store_append(store,&depth1,&iter); + tmp=g_strdup_printf("%s, %s (%s)\n%s, %s %s\n%s\n%s", + bi->firstname,bi->lastname,bi->displayname,bi->address.street, + bi->address.zip, bi->address.town, bi->address.country,bi->sip_uri); + gtk_tree_store_set(store,&depth1,LOOKUP_RESULT_NAME,tmp,-1); + g_free(tmp); + if (bi->image_data!=NULL){ + pbuf=_gdk_pixbuf_new_from_memory_at_scale(bi->image_data,bi->image_length,-1,-1,TRUE); + if (pbuf) { + gtk_tree_store_set(store,&depth1,LOOKUP_RESULT_ICON,pbuf,-1); + g_object_unref(G_OBJECT(pbuf)); + } + } } } diff --git a/linphone/gtk-glade/buddylookup.glade b/linphone/gtk-glade/buddylookup.glade index 8265f7bde..2e6eb96bd 100644 --- a/linphone/gtk-glade/buddylookup.glade +++ b/linphone/gtk-glade/buddylookup.glade @@ -116,6 +116,8 @@ + False + False 3 diff --git a/linphone/gtk-glade/linphone.h b/linphone/gtk-glade/linphone.h index 83e4c1da6..d1ba99459 100644 --- a/linphone/gtk-glade/linphone.h +++ b/linphone/gtk-glade/linphone.h @@ -43,6 +43,9 @@ GdkPixbuf * create_pixbuf(const gchar *filename); GdkPixbufAnimation *create_pixbuf_animation(const gchar *filename); void add_pixmap_directory(const gchar *directory); GtkWidget*create_pixmap(const gchar *filename); +GtkWidget *_gtk_image_new_from_memory_at_scale(const void *data, gint len, gint w, gint h, gboolean preserve_ratio); +GdkPixbuf *_gdk_pixbuf_new_from_memory_at_scale(const void *data, gint len, gint w, gint h, gboolean preserve_ratio); + GtkWidget *linphone_gtk_create_window(const char *window_name); GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name); LinphoneCore *linphone_gtk_get_core(void); diff --git a/linphone/gtk-glade/utils.c b/linphone/gtk-glade/utils.c index 97f263a8d..0c9fdd204 100644 --- a/linphone/gtk-glade/utils.c +++ b/linphone/gtk-glade/utils.c @@ -92,3 +92,24 @@ gchar *linphone_gtk_get_display_name(const char *sip_uri){ return ret; } +GdkPixbuf *_gdk_pixbuf_new_from_memory_at_scale(const void *data, gint len, gint w, gint h, gboolean preserve_ratio){ + GInputStream *stream=g_memory_input_stream_new_from_data (data,len,NULL); + GError *error=NULL; + + GdkPixbuf *pbuf=gdk_pixbuf_new_from_stream_at_scale (stream,w,h,preserve_ratio,NULL,&error); + g_input_stream_close(stream,NULL,NULL); + g_object_unref(G_OBJECT(stream)); + if (pbuf==NULL){ + g_warning("Could not open image from memory"); + } + return pbuf; +} + +GtkWidget * _gtk_image_new_from_memory_at_scale(const void *data, gint len, gint w, gint h, gboolean preserve_ratio){ + GtkWidget *image; + GdkPixbuf *pbuf=_gdk_pixbuf_new_from_memory_at_scale(data,len,w,h,preserve_ratio); + if (pbuf==NULL) return NULL; + image=gtk_image_new_from_pixbuf(pbuf); + g_object_unref(G_OBJECT(pbuf)); + return image; +}