pidgin/gtksmiley.c

branch
custom_smiley
changeset 22898
206c1f2a1fd7
parent 22655
718f1149a81c
child 22899
df30ef921ee6
equal deleted inserted replaced
22897:93d7ad160755 22898:206c1f2a1fd7
32 #include "notify.h" 32 #include "notify.h"
33 #include "smiley.h" 33 #include "smiley.h"
34 34
35 #include "gtkimhtml.h" 35 #include "gtkimhtml.h"
36 #include "gtksmiley.h" 36 #include "gtksmiley.h"
37 #include "gtkutils.h"
38 #include "pidginstock.h"
37 39
38 typedef struct 40 typedef struct
39 { 41 {
42 PurpleSmiley *smiley;
40 GtkWidget *parent; 43 GtkWidget *parent;
41 GtkWidget *smile; 44 GtkWidget *smile;
42 GtkWidget *file_chooser; 45 GtkWidget *smiley_image;
43 gchar *filename; 46 gchar *filename;
44 } PidginSmiley; 47 } PidginSmiley;
45 48
46 typedef struct 49 typedef struct
47 { 50 {
53 56
54 enum 57 enum
55 { 58 {
56 ICON, 59 ICON,
57 SHORTCUT, 60 SHORTCUT,
58 DATA, 61 SMILEY,
59 N_COL 62 N_COL
60 }; 63 };
61 64
62 static SmileyManager *smiley_manager = NULL; 65 static SmileyManager *smiley_manager = NULL;
63 static GSList *gtk_smileys = NULL; 66 static GSList *gtk_smileys = NULL;
182 185
183 static void do_add(GtkWidget *widget, PidginSmiley *s) 186 static void do_add(GtkWidget *widget, PidginSmiley *s)
184 { 187 {
185 const gchar *entry; 188 const gchar *entry;
186 PurpleSmiley *emoticon; 189 PurpleSmiley *emoticon;
187 gchar *file;
188 190
189 entry = gtk_entry_get_text(GTK_ENTRY(s->smile)); 191 entry = gtk_entry_get_text(GTK_ENTRY(s->smile));
190 192 emoticon = purple_smileys_find_by_shortcut(entry);
191 if (s->filename == NULL || *entry == 0) { 193 if (emoticon && emoticon != s->smiley) {
192 purple_notify_error(s->parent, _("Custom Smiley"), 194 purple_notify_error(s->parent, _("Custom Smiley"),
193 _("More Data needed"), 195 _("Duplicate Shortcut"),
194 s->filename ? _("Please provide a shortcut to associate with the smiley.") 196 _("A custom smiley for the selected shortcut already exists. Please specify a different shortcut."));
197 return;
198 }
199
200 if (s->smiley) {
201 if (s->filename) {
202 gchar *data = NULL;
203 size_t len;
204 GError *err = NULL;
205
206 if (!g_file_get_contents(s->filename, &data, &len, &err)) {
207 purple_debug_error("gtksmiley", "Error reading %s: %s\n",
208 s->filename, err->message);
209 g_error_free(err);
210
211 return;
212 }
213 purple_smiley_set_data(s->smiley, (guchar*)data, len, FALSE);
214 }
215 purple_smiley_set_shortcut(s->smiley, entry);
216 } else {
217 if ((s->filename == NULL || *entry == 0)) {
218 purple_notify_error(s->parent, _("Custom Smiley"),
219 _("More Data needed"),
220 s->filename ? _("Please provide a shortcut to associate with the smiley.")
195 : _("Please select an image for the smiley.")); 221 : _("Please select an image for the smiley."));
196 return; 222 return;
197 } 223 }
198 224
199 purple_debug_info("gtksmiley", "adding a new smiley\n"); 225 purple_debug_info("gtksmiley", "adding a new smiley\n");
200 file = g_path_get_basename(s->filename); 226 emoticon = purple_smiley_new_from_file(entry, s->filename);
201 emoticon = purple_smiley_new_from_file(entry, s->filename, file); 227 purple_smileys_add(emoticon);
202 purple_smileys_add(emoticon); 228 if (gtk_smileys != NULL)
203 g_free(file); 229 pidgin_smiley_add_to_list(emoticon);
204 230 }
205 if (gtk_smileys != NULL)
206 pidgin_smiley_add_to_list(emoticon);
207 231
208 if (smiley_manager != NULL) 232 if (smiley_manager != NULL)
209 refresh_list(); 233 refresh_list();
210 234
211 gtk_widget_destroy(s->parent); 235 gtk_widget_destroy(s->parent);
225 purple_debug_error("gtksmiley", "no valid response\n"); 249 purple_debug_error("gtksmiley", "no valid response\n");
226 break; 250 break;
227 } 251 }
228 } 252 }
229 253
230 static void do_add_file_cb(GtkWidget *widget, gint resp, PidginSmiley *s) 254 static void do_add_file_cb(const char *filename, gpointer data)
231 { 255 {
232 if (resp == GTK_RESPONSE_ACCEPT) 256 PidginSmiley *s = data;
233 s->filename = gtk_file_chooser_get_filename( 257 GdkPixbuf *pixbuf;
234 GTK_FILE_CHOOSER(s->file_chooser)); 258
235 } 259 if (!filename)
236 260 return;
237 void pidgin_smiley_add(GtkWidget *widget) 261
262 g_free(s->filename);
263 s->filename = g_strdup(filename);
264 pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, 64, 64, FALSE, NULL);
265 gtk_image_set_from_pixbuf(GTK_IMAGE(s->smiley_image), pixbuf);
266 if (pixbuf)
267 gdk_pixbuf_unref(pixbuf);
268 }
269
270 static void
271 open_image_selector(GtkWidget *widget, PidginSmiley *psmiley)
272 {
273 GtkWidget *file_chooser;
274 file_chooser = pidgin_buddy_icon_chooser_new(GTK_WINDOW(gtk_widget_get_toplevel(widget)),
275 do_add_file_cb, psmiley);
276 gtk_window_set_title(GTK_WINDOW(file_chooser), _("Custom Smiley"));
277 gtk_window_set_role(GTK_WINDOW(file_chooser), "file-selector-custom-smiley");
278 gtk_widget_show_all(file_chooser);
279 }
280
281 void pidgin_smiley_edit(GtkWidget *widget, PurpleSmiley *smiley)
238 { 282 {
239 GtkWidget *vbox; 283 GtkWidget *vbox;
240 GtkWidget *hbox; 284 GtkWidget *hbox;
241 GtkWidget *label; 285 GtkWidget *label;
242 GtkWidget *filech; 286 GtkWidget *filech;
243 GtkWidget *window; 287 GtkWidget *window;
288 GdkPixbuf *pixbuf = NULL;
289 PurpleStoredImage *stored_img;
244 290
245 PidginSmiley *s = g_new0(PidginSmiley, 1); 291 PidginSmiley *s = g_new0(PidginSmiley, 1);
246 292 s->smiley = smiley;
247 window = gtk_dialog_new_with_buttons(_("Add Smiley"), 293
294 window = gtk_dialog_new_with_buttons(smiley ? _("Edit Smiley") : _("Add Smiley"),
248 GTK_WINDOW(widget), 295 GTK_WINDOW(widget),
249 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, 296 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
250 GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT, 297 smiley ? GTK_STOCK_SAVE : GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT,
251 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 298 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
252 NULL); 299 NULL);
253 s->parent = window; 300 s->parent = window;
254 301
255 gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); 302 gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER);
263 310
264 /* The hbox */ 311 /* The hbox */
265 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); 312 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
266 gtk_container_add(GTK_CONTAINER(GTK_VBOX(vbox)), hbox); 313 gtk_container_add(GTK_CONTAINER(GTK_VBOX(vbox)), hbox);
267 314
268 label = gtk_label_new(_("Select the file:")); 315 label = gtk_label_new_with_mnemonic(_("Smiley _Image"));
269 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); 316 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
270 gtk_widget_show(label); 317 gtk_widget_show(label);
271 318
272 s->file_chooser = gtk_file_chooser_dialog_new(_("Custom Smiley"), 319 filech = gtk_button_new();
273 GTK_WINDOW(window), 320 gtk_box_pack_end(GTK_BOX(hbox), filech, FALSE, FALSE, 0);
274 GTK_FILE_CHOOSER_ACTION_OPEN, 321 pidgin_set_accessible_label(filech, label);
275 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 322
276 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, 323 s->smiley_image = gtk_image_new();
277 NULL); 324 gtk_container_add(GTK_CONTAINER(filech), s->smiley_image);
278 325 if (smiley && (stored_img = purple_smiley_get_stored_image(smiley))) {
279 g_signal_connect(s->file_chooser, "response", G_CALLBACK(do_add_file_cb), s); 326 pixbuf = pidgin_pixbuf_from_imgstore(stored_img);
280 327 purple_imgstore_unref(stored_img);
281 filech = gtk_file_chooser_button_new_with_dialog(GTK_WIDGET(s->file_chooser)); 328 } else {
282 329 GtkIconSize icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL);
283 gtk_box_pack_end(GTK_BOX(hbox), filech, TRUE, TRUE, 0); 330 pixbuf = gtk_widget_render_icon(window, PIDGIN_STOCK_TOOLBAR_SELECT_AVATAR,
284 gtk_widget_show(filech); 331 icon_size, "PidginSmiley");
285 332 }
286 gtk_widget_show(hbox); 333
334 gtk_image_set_from_pixbuf(GTK_IMAGE(s->smiley_image), pixbuf);
335 if (pixbuf != NULL)
336 g_object_unref(G_OBJECT(pixbuf));
337 g_signal_connect(G_OBJECT(filech), "clicked", G_CALLBACK(open_image_selector), s);
338
339 gtk_widget_show_all(hbox);
287 340
288 /* info */ 341 /* info */
289 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); 342 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
290 gtk_container_add(GTK_CONTAINER(GTK_VBOX(vbox)),hbox); 343 gtk_container_add(GTK_CONTAINER(GTK_VBOX(vbox)),hbox);
291 344
292 /* Smiley shortcut */ 345 /* Smiley shortcut */
293 label = gtk_label_new(_("Define Smiley's shortcut")); 346 label = gtk_label_new_with_mnemonic(_("Smiley S_hortcut"));
294 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); 347 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
295 gtk_widget_show(label); 348 gtk_widget_show(label);
296 349
297 s->smile = gtk_entry_new(); 350 s->smile = gtk_entry_new();
298 gtk_entry_set_activates_default(GTK_ENTRY(s->smile), TRUE); 351 gtk_entry_set_activates_default(GTK_ENTRY(s->smile), TRUE);
299 gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_WIDGET(s->smile)); 352 pidgin_set_accessible_label(s->smile, label);
353 if (smiley)
354 gtk_entry_set_text(GTK_ENTRY(s->smile), purple_smiley_get_shortcut(smiley));
300 355
301 g_signal_connect(s->smile, "activate", G_CALLBACK(do_add), s); 356 g_signal_connect(s->smile, "activate", G_CALLBACK(do_add), s);
302 357
303 gtk_box_pack_end(GTK_BOX(hbox), s->smile, FALSE, FALSE, 0); 358 gtk_box_pack_end(GTK_BOX(hbox), s->smile, FALSE, FALSE, 0);
304 gtk_widget_show(s->smile); 359 gtk_widget_show(s->smile);
386 return; 441 return;
387 442
388 img = purple_smiley_get_stored_image(smiley); 443 img = purple_smiley_get_stored_image(smiley);
389 444
390 if (img != NULL) { 445 if (img != NULL) {
391 GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); 446 GdkPixbuf *smiley_image = pidgin_pixbuf_from_imgstore(img);
392 GdkPixbuf *smiley_image = NULL;
393
394 gdk_pixbuf_loader_write(loader, purple_imgstore_get_data(img),
395 purple_imgstore_get_size(img), NULL);
396 gdk_pixbuf_loader_close(loader, NULL);
397 smiley_image = gdk_pixbuf_loader_get_pixbuf(loader);
398
399 purple_imgstore_unref(img); 447 purple_imgstore_unref(img);
400 448
401 if (smiley_image != NULL) 449 if (smiley_image != NULL)
402 sized_smiley = gdk_pixbuf_scale_simple(smiley_image, 450 sized_smiley = gdk_pixbuf_scale_simple(smiley_image,
403 22, 22, GDK_INTERP_HYPER); 451 22, 22, GDK_INTERP_HYPER);
404
405 g_object_unref(loader);
406 } 452 }
407 453
408 454
409 gtk_list_store_append(smiley_manager->model, &iter); 455 gtk_list_store_append(smiley_manager->model, &iter);
410 456
411 gtk_list_store_set(smiley_manager->model, &iter, 457 gtk_list_store_set(smiley_manager->model, &iter,
412 ICON, sized_smiley, 458 ICON, sized_smiley,
413 SHORTCUT, purple_smiley_get_shortcut(smiley), 459 SHORTCUT, purple_smiley_get_shortcut(smiley),
414 DATA, NULL, 460 SMILEY, smiley,
415 -1); 461 -1);
416 462
417 if (sized_smiley != NULL) 463 if (sized_smiley != NULL)
418 g_object_unref(G_OBJECT(sized_smiley)); 464 g_object_unref(G_OBJECT(sized_smiley));
419 } 465 }
439 485
440 selected = gtk_tree_selection_count_selected_rows(sel); 486 selected = gtk_tree_selection_count_selected_rows(sel);
441 487
442 gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog->window), 488 gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog->window),
443 GTK_RESPONSE_NO, selected > 0); 489 GTK_RESPONSE_NO, selected > 0);
490 }
491
492 static void smiley_edit_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
493 {
494 GtkTreeIter iter;
495 SmileyManager *dialog = data;
496 PurpleSmiley *smiley = NULL;
497
498 gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, path);
499 gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter, SMILEY, &smiley, -1);
500 pidgin_smiley_edit(gtk_widget_get_toplevel(GTK_WIDGET(treeview)), smiley);
444 } 501 }
445 502
446 static GtkWidget *smiley_list_create(SmileyManager *dialog) 503 static GtkWidget *smiley_list_create(SmileyManager *dialog)
447 { 504 {
448 GtkWidget *sw; 505 GtkWidget *sw;
452 sw = gtk_scrolled_window_new(NULL, NULL); 509 sw = gtk_scrolled_window_new(NULL, NULL);
453 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), 510 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
454 GTK_POLICY_AUTOMATIC, 511 GTK_POLICY_AUTOMATIC,
455 GTK_POLICY_AUTOMATIC); 512 GTK_POLICY_AUTOMATIC);
456 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), 513 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
457 GTK_SHADOW_NONE); 514 GTK_SHADOW_IN);
458 gtk_widget_show(sw); 515 gtk_widget_show(sw);
459 516
460 /* Create the list model */ 517 /* Create the list model */
461 dialog->model = gtk_list_store_new(N_COL, 518 dialog->model = gtk_list_store_new(N_COL,
462 GDK_TYPE_PIXBUF, /* ICON */ 519 GDK_TYPE_PIXBUF, /* ICON */
463 G_TYPE_STRING, /* SHORTCUT */ 520 G_TYPE_STRING, /* SHORTCUT */
464 G_TYPE_POINTER /* DATA */ 521 G_TYPE_POINTER /* SMILEY */
465 ); 522 );
466 523
467 /* the actual treeview */ 524 /* the actual treeview */
468 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); 525 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
469 dialog->treeview = treeview; 526 dialog->treeview = treeview;
470 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); 527 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
471 528
529
472 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); 530 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
473 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE); 531 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
474 gtk_container_add(GTK_CONTAINER(sw), treeview); 532 gtk_container_add(GTK_CONTAINER(sw), treeview);
475 533
476 g_signal_connect(G_OBJECT(sel), "changed", 534 g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(smile_selected_cb), dialog);
477 G_CALLBACK(smile_selected_cb), dialog); 535 g_signal_connect(G_OBJECT(treeview), "row_activated", G_CALLBACK(smiley_edit_cb), dialog);
478 536
479 gtk_widget_show(treeview); 537 gtk_widget_show(treeview);
480 538
481 add_columns(treeview, dialog); 539 add_columns(treeview, dialog);
482 populate_smiley_list(dialog); 540 populate_smiley_list(dialog);
491 549
492 static void smiley_manager_select_cb(GtkWidget *widget, gint resp, SmileyManager *dialog) 550 static void smiley_manager_select_cb(GtkWidget *widget, gint resp, SmileyManager *dialog)
493 { 551 {
494 switch (resp) { 552 switch (resp) {
495 case GTK_RESPONSE_YES: 553 case GTK_RESPONSE_YES:
496 pidgin_smiley_add(dialog->window); 554 pidgin_smiley_edit(dialog->window, NULL);
497 break; 555 break;
498 case GTK_RESPONSE_NO: 556 case GTK_RESPONSE_NO:
499 smiley_delete(dialog); 557 smiley_delete(dialog);
500 refresh_list(); 558 refresh_list();
501 break; 559 break;

mercurial