| 1 | /* |
|---|
| 2 | linphone, gtk-glade interface. |
|---|
| 3 | Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) |
|---|
| 4 | |
|---|
| 5 | This program is free software; you can redistribute it and/or |
|---|
| 6 | modify it under the terms of the GNU General Public License |
|---|
| 7 | as published by the Free Software Foundation; either version 2 |
|---|
| 8 | of the License, or (at your option) any later version. |
|---|
| 9 | |
|---|
| 10 | This program is distributed in the hope that it will be useful, |
|---|
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | GNU General Public License for more details. |
|---|
| 14 | |
|---|
| 15 | You should have received a copy of the GNU General Public License |
|---|
| 16 | along with this program; if not, write to the Free Software |
|---|
| 17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 18 | */ |
|---|
| 19 | |
|---|
| 20 | #include "linphone.h" |
|---|
| 21 | #include "sipsetup.h" |
|---|
| 22 | |
|---|
| 23 | static void linphone_gtk_display_lookup_results(GtkWidget *w, const MSList *results); |
|---|
| 24 | |
|---|
| 25 | enum { |
|---|
| 26 | LOOKUP_RESULT_NAME, |
|---|
| 27 | LOOKUP_RESULT_SIP_URI, |
|---|
| 28 | LOOKUP_RESULT_ADDRESS, |
|---|
| 29 | LOOKUP_RESULT_ICON, |
|---|
| 30 | LOOKUP_RESULT_NCOL |
|---|
| 31 | }; |
|---|
| 32 | |
|---|
| 33 | void linphone_gtk_buddy_lookup_window_destroyed(GtkWidget *w){ |
|---|
| 34 | guint tid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"typing_timeout")); |
|---|
| 35 | if (tid!=0){ |
|---|
| 36 | g_source_remove(tid); |
|---|
| 37 | } |
|---|
| 38 | tid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"buddylookup_processing")); |
|---|
| 39 | if (tid!=0){ |
|---|
| 40 | g_source_remove(tid); |
|---|
| 41 | } |
|---|
| 42 | } |
|---|
| 43 | |
|---|
| 44 | static void enable_add_buddy_button(GtkWidget *w){ |
|---|
| 45 | gtk_widget_set_sensitive(linphone_gtk_get_widget(w,"add_buddy"),TRUE); |
|---|
| 46 | } |
|---|
| 47 | |
|---|
| 48 | static void disable_add_buddy_button(GtkWidget *w){ |
|---|
| 49 | gtk_widget_set_sensitive(linphone_gtk_get_widget(w,"add_buddy"),FALSE); |
|---|
| 50 | } |
|---|
| 51 | |
|---|
| 52 | static void buddy_selection_changed(GtkWidget *w){ |
|---|
| 53 | GtkWidget *results=linphone_gtk_get_widget(w,"search_results"); |
|---|
| 54 | GtkTreeSelection *select; |
|---|
| 55 | GtkTreeIter iter; |
|---|
| 56 | GtkTreeModel *model; |
|---|
| 57 | enable_add_buddy_button(w); |
|---|
| 58 | |
|---|
| 59 | select = gtk_tree_view_get_selection(GTK_TREE_VIEW(results)); |
|---|
| 60 | if (gtk_tree_selection_get_selected (select, &model, &iter)) |
|---|
| 61 | { |
|---|
| 62 | GtkTreePath *path=gtk_tree_model_get_path(model,&iter); |
|---|
| 63 | gtk_tree_view_collapse_all(GTK_TREE_VIEW(results)); |
|---|
| 64 | gtk_tree_view_expand_row(GTK_TREE_VIEW(results),path,FALSE); |
|---|
| 65 | gtk_tree_path_free(path); |
|---|
| 66 | } |
|---|
| 67 | } |
|---|
| 68 | |
|---|
| 69 | GtkWidget * linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx){ |
|---|
| 70 | GtkTreeStore *store; |
|---|
| 71 | GtkCellRenderer *renderer,*pbuf_renderer; |
|---|
| 72 | GtkTreeViewColumn *column; |
|---|
| 73 | GtkTreeSelection *select; |
|---|
| 74 | GtkWidget *w=linphone_gtk_create_window("buddylookup"); |
|---|
| 75 | GtkWidget *results=linphone_gtk_get_widget(w,"search_results"); |
|---|
| 76 | GtkProgressBar *pb=GTK_PROGRESS_BAR(linphone_gtk_get_widget(w,"progressbar")); |
|---|
| 77 | |
|---|
| 78 | store = gtk_tree_store_new(LOOKUP_RESULT_NCOL, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF); |
|---|
| 79 | |
|---|
| 80 | /*gtk_tree_view_set_hover_expand(GTK_TREE_VIEW(results),TRUE);*/ |
|---|
| 81 | gtk_tree_view_set_model(GTK_TREE_VIEW(results),GTK_TREE_MODEL(store)); |
|---|
| 82 | g_object_unref(G_OBJECT(store)); |
|---|
| 83 | |
|---|
| 84 | renderer = gtk_cell_renderer_text_new (); |
|---|
| 85 | column = gtk_tree_view_column_new_with_attributes (_("Firstname, Lastname"), |
|---|
| 86 | renderer, |
|---|
| 87 | "markup", LOOKUP_RESULT_NAME, |
|---|
| 88 | NULL); |
|---|
| 89 | g_object_set (G_OBJECT(column), "resizable", TRUE, NULL); |
|---|
| 90 | |
|---|
| 91 | |
|---|
| 92 | pbuf_renderer=gtk_cell_renderer_pixbuf_new(); |
|---|
| 93 | g_object_set(G_OBJECT(renderer),"is-expander",TRUE,NULL); |
|---|
| 94 | gtk_tree_view_column_pack_start(column,pbuf_renderer,FALSE); |
|---|
| 95 | gtk_tree_view_column_add_attribute (column,pbuf_renderer, |
|---|
| 96 | "pixbuf", |
|---|
| 97 | LOOKUP_RESULT_ICON); |
|---|
| 98 | gtk_tree_view_append_column (GTK_TREE_VIEW (results), column); |
|---|
| 99 | |
|---|
| 100 | /* |
|---|
| 101 | column = gtk_tree_view_column_new_with_attributes (_("SIP address"), |
|---|
| 102 | renderer, |
|---|
| 103 | "text", LOOKUP_RESULT_SIP_URI, |
|---|
| 104 | NULL); |
|---|
| 105 | g_object_set (G_OBJECT(column), "resizable", TRUE, NULL); |
|---|
| 106 | gtk_tree_view_append_column (GTK_TREE_VIEW (results), column); |
|---|
| 107 | */ |
|---|
| 108 | |
|---|
| 109 | select = gtk_tree_view_get_selection (GTK_TREE_VIEW (results)); |
|---|
| 110 | gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE); |
|---|
| 111 | g_signal_connect_swapped(G_OBJECT(select),"changed",(GCallback)buddy_selection_changed,w); |
|---|
| 112 | /* |
|---|
| 113 | #if GTK_CHECK_VERSION(2,12,0) |
|---|
| 114 | gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(results),LOOKUP_RESULT_ADDRESS); |
|---|
| 115 | #endif |
|---|
| 116 | */ |
|---|
| 117 | g_object_set_data(G_OBJECT(w),"SipSetupContext",ctx); |
|---|
| 118 | g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_gtk_buddy_lookup_window_destroyed,w); |
|---|
| 119 | //g_signal_connect_swapped(G_OBJECT(w),"destroy",(GCallback)linphone_gtk_buddy_lookup_window_destroyed,w); |
|---|
| 120 | gtk_progress_bar_set_fraction(pb,0); |
|---|
| 121 | gtk_progress_bar_set_text(pb,NULL); |
|---|
| 122 | gtk_dialog_add_button(GTK_DIALOG(w),GTK_STOCK_CLOSE,GTK_RESPONSE_CLOSE); |
|---|
| 123 | g_object_set_data(G_OBJECT(w),"last_state",GINT_TO_POINTER(-1)); |
|---|
| 124 | |
|---|
| 125 | gtk_widget_show(w); |
|---|
| 126 | return w; |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | |
|---|
| 130 | void linphone_gtk_buddy_lookup_set_keyword(GtkWidget *w, const char *kw){ |
|---|
| 131 | gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"keyword")),kw); |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| 134 | static gboolean linphone_gtk_process_buddy_lookup(GtkWidget *w){ |
|---|
| 135 | BuddyLookupStatus bls; |
|---|
| 136 | SipSetupContext *ctx; |
|---|
| 137 | int last_state; |
|---|
| 138 | gchar *tmp; |
|---|
| 139 | MSList *results=NULL; |
|---|
| 140 | GtkProgressBar *pb=GTK_PROGRESS_BAR(linphone_gtk_get_widget(w,"progressbar")); |
|---|
| 141 | BuddyLookupRequest *req=(BuddyLookupRequest*)g_object_get_data(G_OBJECT(w),"buddylookup_request"); |
|---|
| 142 | |
|---|
| 143 | ctx=(SipSetupContext*)g_object_get_data(G_OBJECT(w),"SipSetupContext"); |
|---|
| 144 | last_state=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"last_state")); |
|---|
| 145 | |
|---|
| 146 | if (req==NULL) return FALSE; |
|---|
| 147 | bls=req->status; |
|---|
| 148 | if (last_state==bls) return TRUE; |
|---|
| 149 | switch(bls){ |
|---|
| 150 | case BuddyLookupNone: |
|---|
| 151 | gtk_progress_bar_set_fraction(pb,0); |
|---|
| 152 | gtk_progress_bar_set_text(pb,NULL); |
|---|
| 153 | break; |
|---|
| 154 | case BuddyLookupFailure: |
|---|
| 155 | gtk_progress_bar_set_fraction(pb,0); |
|---|
| 156 | gtk_progress_bar_set_text(pb,_("Error communicating with server.")); |
|---|
| 157 | break; |
|---|
| 158 | case BuddyLookupConnecting: |
|---|
| 159 | gtk_progress_bar_set_fraction(pb,0.2); |
|---|
| 160 | gtk_progress_bar_set_text(pb,_("Connecting...")); |
|---|
| 161 | break; |
|---|
| 162 | case BuddyLookupConnected: |
|---|
| 163 | gtk_progress_bar_set_fraction(pb,0.4); |
|---|
| 164 | gtk_progress_bar_set_text(pb,_("Connected")); |
|---|
| 165 | break; |
|---|
| 166 | case BuddyLookupReceivingResponse: |
|---|
| 167 | gtk_progress_bar_set_fraction(pb,0.8); |
|---|
| 168 | gtk_progress_bar_set_text(pb,_("Receiving data...")); |
|---|
| 169 | break; |
|---|
| 170 | case BuddyLookupDone: |
|---|
| 171 | results=req->results; |
|---|
| 172 | linphone_gtk_display_lookup_results( |
|---|
| 173 | linphone_gtk_get_widget(w,"search_results"), |
|---|
| 174 | results); |
|---|
| 175 | gtk_progress_bar_set_fraction(pb,1); |
|---|
| 176 | tmp=g_strdup_printf(ngettext("Found %i contact", |
|---|
| 177 | "Found %i contacts", ms_list_size(results)), |
|---|
| 178 | ms_list_size(results)); |
|---|
| 179 | gtk_progress_bar_set_text(pb,tmp); |
|---|
| 180 | g_free(tmp); |
|---|
| 181 | sip_setup_context_buddy_lookup_free(ctx,req); |
|---|
| 182 | g_object_set_data(G_OBJECT(w),"buddylookup_request",NULL); |
|---|
| 183 | break; |
|---|
| 184 | } |
|---|
| 185 | g_object_set_data(G_OBJECT(w),"last_state",GINT_TO_POINTER(bls)); |
|---|
| 186 | return TRUE; |
|---|
| 187 | } |
|---|
| 188 | |
|---|
| 189 | static gboolean keyword_typing_finished(GtkWidget *w){ |
|---|
| 190 | guint tid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"typing_timeout")); |
|---|
| 191 | const char *keyword; |
|---|
| 192 | SipSetupContext *ctx; |
|---|
| 193 | if (tid!=0){ |
|---|
| 194 | g_source_remove(tid); |
|---|
| 195 | } |
|---|
| 196 | keyword=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"keyword"))); |
|---|
| 197 | if (strlen(keyword)>=1){ |
|---|
| 198 | BuddyLookupRequest *req; |
|---|
| 199 | guint tid2; |
|---|
| 200 | ctx=(SipSetupContext*)g_object_get_data(G_OBJECT(w),"SipSetupContext"); |
|---|
| 201 | req=(BuddyLookupRequest*)g_object_get_data(G_OBJECT(w),"buddylookup_request"); |
|---|
| 202 | if (req!=NULL){ |
|---|
| 203 | sip_setup_context_buddy_lookup_free(ctx,req); |
|---|
| 204 | } |
|---|
| 205 | req=sip_setup_context_create_buddy_lookup_request(ctx); |
|---|
| 206 | buddy_lookup_request_set_key(req,keyword); |
|---|
| 207 | sip_setup_context_buddy_lookup_submit(ctx,req); |
|---|
| 208 | g_object_set_data(G_OBJECT(w),"buddylookup_request",req); |
|---|
| 209 | if (g_object_get_data(G_OBJECT(w),"buddylookup_processing")==NULL){ |
|---|
| 210 | tid2=g_timeout_add(20,(GSourceFunc)linphone_gtk_process_buddy_lookup,w); |
|---|
| 211 | g_object_set_data(G_OBJECT(w),"buddylookup_processing",GINT_TO_POINTER(tid2)); |
|---|
| 212 | } |
|---|
| 213 | } |
|---|
| 214 | return FALSE; |
|---|
| 215 | } |
|---|
| 216 | |
|---|
| 217 | void linphone_gtk_keyword_changed(GtkEditable *e){ |
|---|
| 218 | GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(e)); |
|---|
| 219 | guint tid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"typing_timeout")); |
|---|
| 220 | if (tid!=0){ |
|---|
| 221 | g_source_remove(tid); |
|---|
| 222 | } |
|---|
| 223 | tid=g_timeout_add(2000,(GSourceFunc)keyword_typing_finished,w); |
|---|
| 224 | g_object_set_data(G_OBJECT(w),"typing_timeout",GINT_TO_POINTER(tid)); |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | static void linphone_gtk_display_lookup_results(GtkWidget *w, const MSList *results){ |
|---|
| 228 | GtkTreeStore *store; |
|---|
| 229 | GtkTreeIter iter; |
|---|
| 230 | gchar *tmp; |
|---|
| 231 | const MSList *elem; |
|---|
| 232 | store=GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(w))); |
|---|
| 233 | gtk_tree_store_clear(store); |
|---|
| 234 | disable_add_buddy_button(gtk_widget_get_toplevel(w)); |
|---|
| 235 | for(elem=results;elem!=NULL;elem=elem->next){ |
|---|
| 236 | BuddyInfo *bi=(BuddyInfo*)elem->data; |
|---|
| 237 | GdkPixbuf *pbuf; |
|---|
| 238 | GtkTreeIter depth1; |
|---|
| 239 | gtk_tree_store_append(store,&iter,NULL); |
|---|
| 240 | tmp=g_strdup_printf("%s, %s (%s)",bi->firstname,bi->lastname,bi->displayname); |
|---|
| 241 | gtk_tree_store_set(store,&iter,LOOKUP_RESULT_NAME, tmp,-1); |
|---|
| 242 | g_free(tmp); |
|---|
| 243 | gtk_tree_store_set(store,&iter,LOOKUP_RESULT_SIP_URI, bi->sip_uri,-1); |
|---|
| 244 | tmp=g_strdup_printf("%s, %s %s\n%s",bi->address.street, bi->address.zip, bi->address.town, bi->address.country); |
|---|
| 245 | gtk_tree_store_set(store,&iter,LOOKUP_RESULT_ADDRESS, tmp,-1); |
|---|
| 246 | g_free(tmp); |
|---|
| 247 | if (bi->image_data!=NULL){ |
|---|
| 248 | pbuf=_gdk_pixbuf_new_from_memory_at_scale(bi->image_data,bi->image_length,-1,40,TRUE); |
|---|
| 249 | if (pbuf) { |
|---|
| 250 | gtk_tree_store_set(store,&iter,LOOKUP_RESULT_ICON,pbuf,-1); |
|---|
| 251 | g_object_unref(G_OBJECT(pbuf)); |
|---|
| 252 | } |
|---|
| 253 | } |
|---|
| 254 | gtk_tree_store_append(store,&depth1,&iter); |
|---|
| 255 | tmp=g_strdup_printf("<big>%s, %s (%s)</big>\n<i>%s</i>, <b>%s</b> %s\n%s\n%s", |
|---|
| 256 | bi->firstname,bi->lastname,bi->displayname,bi->address.street, |
|---|
| 257 | bi->address.zip, bi->address.town, bi->address.country,bi->sip_uri); |
|---|
| 258 | gtk_tree_store_set(store,&depth1,LOOKUP_RESULT_NAME,tmp,-1); |
|---|
| 259 | g_free(tmp); |
|---|
| 260 | if (bi->image_data!=NULL){ |
|---|
| 261 | pbuf=_gdk_pixbuf_new_from_memory_at_scale(bi->image_data,bi->image_length,-1,-1,TRUE); |
|---|
| 262 | if (pbuf) { |
|---|
| 263 | gtk_tree_store_set(store,&depth1,LOOKUP_RESULT_ICON,pbuf,-1); |
|---|
| 264 | g_object_unref(G_OBJECT(pbuf)); |
|---|
| 265 | } |
|---|
| 266 | } |
|---|
| 267 | } |
|---|
| 268 | } |
|---|
| 269 | |
|---|
| 270 | void linphone_gtk_add_buddy_from_database(GtkWidget *button){ |
|---|
| 271 | GtkWidget *w=gtk_widget_get_toplevel(button); |
|---|
| 272 | GtkTreeSelection *select; |
|---|
| 273 | GtkTreeIter iter; |
|---|
| 274 | GtkTreeModel *model; |
|---|
| 275 | select = gtk_tree_view_get_selection(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"search_results"))); |
|---|
| 276 | if (gtk_tree_selection_get_selected (select, &model, &iter)) |
|---|
| 277 | { |
|---|
| 278 | char *uri; |
|---|
| 279 | char *name; |
|---|
| 280 | char *addr; |
|---|
| 281 | LinphoneFriend *lf; |
|---|
| 282 | gtk_tree_model_get (model, &iter,LOOKUP_RESULT_SIP_URI , &uri,LOOKUP_RESULT_NAME, &name, -1); |
|---|
| 283 | addr=g_strdup_printf("%s <%s>",name,uri); |
|---|
| 284 | lf=linphone_friend_new_with_addr(addr); |
|---|
| 285 | linphone_core_add_friend(linphone_gtk_get_core(),lf); |
|---|
| 286 | linphone_gtk_show_friends(); |
|---|
| 287 | g_free(addr); |
|---|
| 288 | g_free(uri); |
|---|
| 289 | g_free(name); |
|---|
| 290 | } |
|---|
| 291 | } |
|---|
| 292 | |
|---|
| 293 | /*called when double clicking on a contact */ |
|---|
| 294 | void linphone_gtk_buddy_lookup_contact_activated(GtkWidget *treeview){ |
|---|
| 295 | linphone_gtk_add_buddy_from_database(treeview); |
|---|
| 296 | gtk_widget_destroy(gtk_widget_get_toplevel(treeview)); |
|---|
| 297 | } |
|---|