src/gtkutils.c

changeset 14195
0f7cb3b272b2
parent 14097
0c340861ab79
child 14196
0e1b46d494b4
equal deleted inserted replaced
14194:b371a53b1695 14195:0f7cb3b272b2
2209 return; 2209 return;
2210 2210
2211 gdk_window_set_cursor(widget->window, NULL); 2211 gdk_window_set_cursor(widget->window, NULL);
2212 } 2212 }
2213 2213
2214 struct _icon_chooser {
2215 GtkWidget *icon_filesel;
2216 GtkWidget *icon_preview;
2217 GtkWidget *icon_text;
2218
2219 void (*callback)(const char*,gpointer);
2220 gpointer data;
2221 };
2222
2223 #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2224 static void
2225 icon_filesel_delete_cb(GtkWidget *w, struct _icon_chooser *dialog)
2226 {
2227 if (dialog->icon_filesel != NULL)
2228 gtk_widget_destroy(dialog->icon_filesel);
2229
2230 if (dialog->callback)
2231 dialog->callback(NULL, data);
2232
2233 g_free(dialog);
2234 }
2235 #endif /* FILECHOOSER */
2236
2237
2238
2239 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2240 static void
2241 icon_filesel_choose_cb(GtkWidget *widget, gint response, struct _icon_chooser *dialog)
2242 {
2243 char *filename, *current_folder;
2244
2245 if (response != GTK_RESPONSE_ACCEPT) {
2246 if (response == GTK_RESPONSE_CANCEL) {
2247 gtk_widget_destroy(dialog->icon_filesel);
2248 }
2249 dialog->icon_filesel = NULL;
2250 if (dialog->callback)
2251 dialog->callback(NULL, dialog->data);
2252 g_free(dialog);
2253 return;
2254 }
2255
2256 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog->icon_filesel));
2257 current_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog->icon_filesel));
2258 if (current_folder != NULL) {
2259 gaim_prefs_set_string("/gaim/gtk/filelocations/last_icon_folder", current_folder);
2260 g_free(current_folder);
2261 }
2262
2263 #else /* FILECHOOSER */
2264 static void
2265 icon_filesel_choose_cb(GtkWidget *w, AccountPrefsDialog *dialog)
2266 {
2267 char *filename, *current_folder;
2268
2269 filename = g_strdup(gtk_file_selection_get_filename(
2270 GTK_FILE_SELECTION(dialog->icon_filesel)));
2271
2272 /* If they typed in a directory, change there */
2273 if (gaim_gtk_check_if_dir(filename,
2274 GTK_FILE_SELECTION(dialog->icon_filesel)))
2275 {
2276 g_free(filename);
2277 return;
2278 }
2279
2280 current_folder = g_path_get_dirname(filename);
2281 if (current_folder != NULL) {
2282 gaim_prefs_set_string("/gaim/gtk/filelocations/last_icon_folder", current_folder);
2283 g_free(current_folder);
2284 }
2285
2286 #endif /* FILECHOOSER */
2287 if (dialog->callback)
2288 dialog->callback(filename, dialog->data);
2289 gtk_widget_destroy(dialog->icon_filesel);
2290 g_free(filename);
2291 g_free(dialog);
2292 }
2293
2294
2295 static void
2296 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2297 icon_preview_change_cb(GtkFileChooser *widget, struct _icon_chooser *dialog)
2298 #else /* FILECHOOSER */
2299 icon_preview_change_cb(GtkTreeSelection *sel, struct _icon_chooser *dialog)
2300 #endif /* FILECHOOSER */
2301 {
2302 GdkPixbuf *pixbuf, *scale;
2303 int height, width;
2304 char *basename, *markup, *size;
2305 struct stat st;
2306 char *filename;
2307
2308 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2309 filename = gtk_file_chooser_get_preview_filename(
2310 GTK_FILE_CHOOSER(dialog->icon_filesel));
2311 #else /* FILECHOOSER */
2312 filename = g_strdup(gtk_file_selection_get_filename(
2313 GTK_FILE_SELECTION(dialog->icon_filesel)));
2314 #endif /* FILECHOOSER */
2315
2316 if (!filename || g_stat(filename, &st))
2317 {
2318 g_free(filename);
2319 return;
2320 }
2321
2322 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
2323 if (!pixbuf) {
2324 gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), NULL);
2325 gtk_label_set_markup(GTK_LABEL(dialog->icon_text), "");
2326 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2327 gtk_file_chooser_set_preview_widget_active(
2328 GTK_FILE_CHOOSER(dialog->icon_filesel), FALSE);
2329 #endif /* FILECHOOSER */
2330 g_free(filename);
2331 return;
2332 }
2333
2334 width = gdk_pixbuf_get_width(pixbuf);
2335 height = gdk_pixbuf_get_height(pixbuf);
2336 basename = g_path_get_basename(filename);
2337 size = gaim_str_size_to_units(st.st_size);
2338 markup = g_strdup_printf(_("<b>File:</b> %s\n"
2339 "<b>File size:</b> %s\n"
2340 "<b>Image size:</b> %dx%d"),
2341 basename, size, width, height);
2342
2343 scale = gdk_pixbuf_scale_simple(pixbuf, width * 50 / height,
2344 50, GDK_INTERP_BILINEAR);
2345 gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), scale);
2346 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2347 gtk_file_chooser_set_preview_widget_active(
2348 GTK_FILE_CHOOSER(dialog->icon_filesel), TRUE);
2349 #endif /* FILECHOOSER */
2350 gtk_label_set_markup(GTK_LABEL(dialog->icon_text), markup);
2351
2352 g_object_unref(G_OBJECT(pixbuf));
2353 g_object_unref(G_OBJECT(scale));
2354 g_free(filename);
2355 g_free(basename);
2356 g_free(size);
2357 g_free(markup);
2358 }
2359
2360
2361 GtkWidget *gaim_gtk_buddy_icon_chooser_new(GtkWindow *parent, void(*callback)(const char*,gpointer), gpointer data) {
2362 struct _icon_chooser *dialog = g_new0(struct _icon_chooser, 1);
2363
2364 #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2365 GtkWidget *hbox;
2366 GtkWidget *tv;
2367 GtkTreeSelection *sel;
2368
2369 #endif /* FILECHOOSER */
2370 const char *current_folder;
2371
2372 dialog->callback = callback;
2373 dialog->data = data;
2374
2375 if (dialog->icon_filesel != NULL) {
2376 gtk_window_present(GTK_WINDOW(dialog->icon_filesel));
2377 return NULL;
2378 }
2379
2380 current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_icon_folder");
2381 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2382
2383 dialog->icon_filesel = gtk_file_chooser_dialog_new(_("Buddy Icon"),
2384 parent,
2385 GTK_FILE_CHOOSER_ACTION_OPEN,
2386 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2387 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
2388 NULL);
2389 gtk_dialog_set_default_response(GTK_DIALOG(dialog->icon_filesel), GTK_RESPONSE_ACCEPT);
2390 if ((current_folder != NULL) && (*current_folder != '\0'))
2391 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog->icon_filesel),
2392 current_folder);
2393
2394 dialog->icon_preview = gtk_image_new();
2395 dialog->icon_text = gtk_label_new(NULL);
2396 gtk_widget_set_size_request(GTK_WIDGET(dialog->icon_preview), -1, 50);
2397 gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog->icon_filesel),
2398 GTK_WIDGET(dialog->icon_preview));
2399 g_signal_connect(G_OBJECT(dialog->icon_filesel), "update-preview",
2400 G_CALLBACK(icon_preview_change_cb), dialog);
2401 g_signal_connect(G_OBJECT(dialog->icon_filesel), "response",
2402 G_CALLBACK(icon_filesel_choose_cb), dialog);
2403 icon_preview_change_cb(NULL, dialog);
2404 #else /* FILECHOOSER */
2405 dialog->icon_filesel = gtk_file_selection_new(_("Buddy Icon"));
2406 dialog->icon_preview = gtk_image_new();
2407 dialog->icon_text = gtk_label_new(NULL);
2408 if ((current_folder != NULL) && (*current_folder != '\0'))
2409 gtk_file_selection_set_filename(GTK_FILE_SELECTION(dialog->icon_filesel),
2410 current_folder);
2411
2412 gtk_widget_set_size_request(GTK_WIDGET(dialog->icon_preview), -1, 50);
2413 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE);
2414 gtk_box_pack_start(
2415 GTK_BOX(GTK_FILE_SELECTION(dialog->icon_filesel)->main_vbox),
2416 hbox, FALSE, FALSE, 0);
2417 gtk_box_pack_end(GTK_BOX(hbox), dialog->icon_preview,
2418 FALSE, FALSE, 0);
2419 gtk_box_pack_end(GTK_BOX(hbox), dialog->icon_text, FALSE, FALSE, 0);
2420
2421 tv = GTK_FILE_SELECTION(dialog->icon_filesel)->file_list;
2422 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv));
2423
2424 g_signal_connect(G_OBJECT(sel), "changed",
2425 G_CALLBACK(icon_preview_change_cb), dialog);
2426 g_signal_connect(
2427 G_OBJECT(GTK_FILE_SELECTION(dialog->icon_filesel)->ok_button),
2428 "clicked",
2429 G_CALLBACK(icon_filesel_choose_cb), dialog);
2430 g_signal_connect(
2431 G_OBJECT(GTK_FILE_SELECTION(dialog->icon_filesel)->cancel_button),
2432 "clicked",
2433 G_CALLBACK(icon_filesel_delete_cb), dialog);
2434 g_signal_connect(G_OBJECT(dialog->icon_filesel), "destroy",
2435 G_CALLBACK(icon_filesel_delete_cb), dialog);
2436 #endif /* FILECHOOSER */
2437 return dialog->icon_filesel;
2438 }
2439
2440
2441 #if GTK_CHECK_VERSION(2,2,0)
2442 static gboolean
2443 str_array_match(char **a, char **b)
2444 {
2445 int i, j;
2446
2447 if (!a || !b)
2448 return FALSE;
2449 for (i = 0; a[i] != NULL; i++)
2450 for (j = 0; b[j] != NULL; j++)
2451 if (!g_ascii_strcasecmp(a[i], b[j]))
2452 return TRUE;
2453 return FALSE;
2454 }
2455 #endif
2456
2457 char*
2458 gaim_gtk_convert_buddy_icon(GaimPlugin *plugin, const char *path)
2459 {
2460 #if GTK_CHECK_VERSION(2,2,0)
2461 int width, height;
2462 char **pixbuf_formats = NULL;
2463 GdkPixbufFormat *format;
2464 GdkPixbuf *pixbuf;
2465 GaimPluginProtocolInfo *prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
2466 char **prpl_formats = g_strsplit (prpl_info->icon_spec.format,",",0);
2467 #if !GTK_CHECK_VERSION(2,4,0)
2468 GdkPixbufLoader *loader;
2469 FILE *file;
2470 struct stat st;
2471 void *data = NULL;
2472 #endif
2473 #endif
2474 const char *dirname = gaim_buddy_icons_get_cache_dir();
2475 char *random = g_strdup_printf("%x", g_random_int());
2476 char *filename = g_build_filename(dirname, random, NULL);
2477
2478 if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
2479 gaim_debug_info("buddyicon", "Creating icon cache directory.\n");
2480
2481 if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) {
2482 gaim_debug_error("buddyicon",
2483 "Unable to create directory %s: %s\n",
2484 dirname, strerror(errno));
2485 #if GTK_CHECK_VERSION(2,2,0)
2486 g_strfreev(prpl_formats);
2487 #endif
2488 g_free(random);
2489 g_free(filename);
2490 return NULL;
2491 }
2492 }
2493
2494 #if GTK_CHECK_VERSION(2,2,0)
2495 #if GTK_CHECK_VERSION(2,4,0)
2496 format = gdk_pixbuf_get_file_info (path, &width, &height);
2497 #else
2498 loader = gdk_pixbuf_loader_new();
2499 if (!g_stat(path, &st) && (file = g_fopen(path, "rb")) != NULL) {
2500 data = g_malloc(st.st_size);
2501 fread(data, 1, st.st_size, file);
2502 fclose(file);
2503 gdk_pixbuf_loader_write(loader, data, st.st_size, NULL);
2504 g_free(data);
2505 }
2506 gdk_pixbuf_loader_close(loader, NULL);
2507 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
2508 width = gdk_pixbuf_get_width(pixbuf);
2509 height = gdk_pixbuf_get_height(pixbuf);
2510 format = gdk_pixbuf_loader_get_format(loader);
2511 g_object_unref(G_OBJECT(loader));
2512 #endif
2513 pixbuf_formats = gdk_pixbuf_format_get_extensions(format);
2514
2515 if (str_array_match(pixbuf_formats, prpl_formats) && /* This is an acceptable format AND */
2516 (!(prpl_info->icon_spec.scale_rules & GAIM_ICON_SCALE_SEND) || /* The prpl doesn't scale before it sends OR */
2517 (prpl_info->icon_spec.min_width <= width &&
2518 prpl_info->icon_spec.max_width >= width &&
2519 prpl_info->icon_spec.min_height <= height &&
2520 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */
2521 #endif
2522 {
2523 gchar *contents;
2524 gsize length;
2525 FILE *image;
2526
2527 #if GTK_CHECK_VERSION(2,2,0)
2528 g_strfreev(prpl_formats);
2529 g_strfreev(pixbuf_formats);
2530 #endif
2531
2532 /* Copy the image to the cache folder as "filename". */
2533
2534 if (!g_file_get_contents(path, &contents, &length, NULL) ||
2535 (image = g_fopen(filename, "wb")) == NULL)
2536 {
2537 g_free(random);
2538 g_free(filename);
2539 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0)
2540 g_object_unref(G_OBJECT(pixbuf));
2541 #endif
2542 return NULL;
2543 }
2544
2545 if (fwrite(contents, 1, length, image) != length)
2546 {
2547 fclose(image);
2548 g_unlink(filename);
2549
2550 g_free(random);
2551 g_free(filename);
2552 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0)
2553 g_object_unref(G_OBJECT(pixbuf));
2554 #endif
2555 return NULL;
2556 }
2557 fclose(image);
2558
2559 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0)
2560 g_object_unref(G_OBJECT(pixbuf));
2561 #endif
2562
2563 g_free(filename);
2564 return random;
2565 }
2566 #if GTK_CHECK_VERSION(2,2,0)
2567 else
2568 {
2569 int i;
2570 GError *error = NULL;
2571 GdkPixbuf *scale;
2572 pixbuf = gdk_pixbuf_new_from_file(path, &error);
2573 g_strfreev(pixbuf_formats);
2574 if (!error && (prpl_info->icon_spec.scale_rules & GAIM_ICON_SCALE_SEND) &&
2575 (width < prpl_info->icon_spec.min_width ||
2576 width > prpl_info->icon_spec.max_width ||
2577 height < prpl_info->icon_spec.min_height ||
2578 height > prpl_info->icon_spec.max_height))
2579 {
2580 int new_width = width;
2581 int new_height = height;
2582
2583 if(new_width > prpl_info->icon_spec.max_width)
2584 new_width = prpl_info->icon_spec.max_width;
2585 else if(new_width < prpl_info->icon_spec.min_width)
2586 new_width = prpl_info->icon_spec.min_width;
2587 if(new_height > prpl_info->icon_spec.max_height)
2588 new_height = prpl_info->icon_spec.max_height;
2589 else if(new_height < prpl_info->icon_spec.min_height)
2590 new_height = prpl_info->icon_spec.min_height;
2591
2592 /* preserve aspect ratio */
2593 if ((double)height * (double)new_width >
2594 (double)width * (double)new_height) {
2595 new_width = 0.5 + (double)width * (double)new_height / (double)height;
2596 } else {
2597 new_height = 0.5 + (double)height * (double)new_width / (double)width;
2598 }
2599
2600 scale = gdk_pixbuf_scale_simple (pixbuf, new_width, new_height,
2601 GDK_INTERP_HYPER);
2602 g_object_unref(G_OBJECT(pixbuf));
2603 pixbuf = scale;
2604 }
2605 if (error) {
2606 g_free(random);
2607 g_free(filename);
2608 gaim_debug_error("buddyicon", "Could not open icon for conversion: %s\n", error->message);
2609 g_error_free(error);
2610 g_strfreev(prpl_formats);
2611 return NULL;
2612 }
2613
2614 for (i = 0; prpl_formats[i]; i++) {
2615 gaim_debug_info("buddyicon", "Converting buddy icon to %s as %s\n", prpl_formats[i], filename);
2616 /* The gdk-pixbuf documentation is wrong. gdk_pixbuf_save returns TRUE if it was successful,
2617 * FALSE if an error was set. */
2618 if (gdk_pixbuf_save (pixbuf, filename, prpl_formats[i], &error, NULL) == TRUE)
2619 break;
2620 gaim_debug_warning("buddyicon", "Could not convert to %s: %s\n", prpl_formats[i], error->message);
2621 g_error_free(error);
2622 error = NULL;
2623 }
2624 g_strfreev(prpl_formats);
2625 if (!error) {
2626 g_object_unref(G_OBJECT(pixbuf));
2627 g_free(filename);
2628 return random;
2629 } else {
2630 gaim_debug_error("buddyicon", "Could not convert icon to usable format: %s\n", error->message);
2631 g_error_free(error);
2632 }
2633 g_free(random);
2634 g_free(filename);
2635 g_object_unref(G_OBJECT(pixbuf));
2636 }
2637 return NULL;
2638 #endif
2639 }

mercurial