14 # define WIN32_MEAN_AND_LEAN
15 # include <windows.h> /* ExtractAssociatedIcon */
17 # define localtime_r(t,b) localtime(t)
19 # define S_ISREG(m) ((m) & _S_IFREG)
21 # include <gdk/win32/gdkwin32.h> /* gdk_win32_hdc_get */
24 #include "prop-editor.h"
26 static GtkWidget *preview_label;
27 static GtkWidget *preview_image;
28 static GtkFileChooserAction action;
31 print_current_folder (GtkFileChooser *chooser)
35 uri = gtk_file_chooser_get_current_folder_uri (chooser);
36 g_print ("Current folder changed :\n %s\n", uri ? uri : "(null)");
41 print_selected (GtkFileChooser *chooser)
43 GSList *uris = gtk_file_chooser_get_uris (chooser);
46 g_print ("Selection changed :\n");
47 for (tmp_list = uris; tmp_list; tmp_list = tmp_list->next)
49 gchar *uri = tmp_list->data;
50 g_print (" %s\n", uri);
58 response_cb (GtkDialog *dialog,
61 if (response_id == GTK_RESPONSE_OK)
65 list = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
71 g_print ("Selected files:\n");
73 for (l = list; l; l = l->next)
75 g_print ("%s\n", (char *) l->data);
82 g_print ("No selected files\n");
85 g_print ("Dialog was closed\n");
91 no_backup_files_filter (const GtkFileFilterInfo *filter_info,
94 gsize len = filter_info->display_name ? strlen (filter_info->display_name) : 0;
95 if (len > 0 && filter_info->display_name[len - 1] == '~')
102 format_time (time_t t)
106 time_t now = time (NULL);
109 if (abs (now - t) < 24*60*60)
114 localtime_r (&t, &tm_buf);
115 if (strftime (buf, sizeof (buf), format, &tm_buf) == 0)
116 return g_strdup ("<unknown>");
118 return g_strdup (buf);
122 format_size (gint64 size)
124 if (size < (gint64)1024)
125 return g_strdup_printf ("%d bytes", (gint)size);
126 else if (size < (gint64)1024*1024)
127 return g_strdup_printf ("%.1f K", size / (1024.));
128 else if (size < (gint64)1024*1024*1024)
129 return g_strdup_printf ("%.1f M", size / (1024.*1024.));
131 return g_strdup_printf ("%.1f G", size / (1024.*1024.*1024.));
139 size_prepared_cb (GdkPixbufLoader *loader,
144 int des_width = data[0];
145 int des_height = data[1];
147 if (des_height >= height && des_width >= width) {
149 } else if ((double)height * des_width > (double)width * des_height) {
150 width = 0.5 + (double)width * des_height / (double)height;
153 height = 0.5 + (double)height * des_width / (double)width;
157 gdk_pixbuf_loader_set_size (loader, width, height);
161 my_new_from_file_at_size (const char *filename,
166 GdkPixbufLoader *loader;
171 guchar buffer [4096];
175 g_return_val_if_fail (filename != NULL, NULL);
176 g_return_val_if_fail (width > 0 && height > 0, NULL);
178 if (stat (filename, &st) != 0) {
181 g_file_error_from_errno (errno),
182 _("Could not get information for file '%s': %s"),
183 filename, g_strerror (errno));
187 if (!S_ISREG (st.st_mode))
190 f = fopen (filename, "rb");
194 g_file_error_from_errno (errno),
195 _("Failed to open file '%s': %s"),
196 filename, g_strerror (errno));
200 loader = gdk_pixbuf_loader_new ();
201 #ifdef DONT_PRESERVE_ASPECT
202 gdk_pixbuf_loader_set_size (loader, width, height);
206 g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), info);
210 length = fread (buffer, 1, sizeof (buffer), f);
212 if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
213 gdk_pixbuf_loader_close (loader, NULL);
215 g_object_unref (G_OBJECT (loader));
222 if (!gdk_pixbuf_loader_close (loader, error)) {
223 g_object_unref (G_OBJECT (loader));
227 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
230 g_object_unref (G_OBJECT (loader));
233 GDK_PIXBUF_ERROR_FAILED,
234 _("Failed to load image '%s': reason not known, probably a corrupt image file"),
239 g_object_ref (pixbuf);
241 g_object_unref (G_OBJECT (loader));
247 update_preview_cb (GtkFileChooser *chooser)
249 gchar *filename = gtk_file_chooser_get_preview_filename (chooser);
250 gboolean have_preview = FALSE;
255 GError *error = NULL;
257 pixbuf = my_new_from_file_at_size (filename, 128, 128, &error);
260 gtk_image_set_from_pixbuf (GTK_IMAGE (preview_image), pixbuf);
261 g_object_unref (pixbuf);
262 gtk_widget_show (preview_image);
263 gtk_widget_hide (preview_label);
269 if (stat (filename, &buf) == 0)
273 gchar *modified_time;
275 size_str = format_size (buf.st_size);
276 modified_time = format_time (buf.st_mtime);
278 preview_text = g_strdup_printf ("<i>Modified:</i>\t%s\n"
279 "<i>Size:</i>\t%s\n",
282 gtk_label_set_markup (GTK_LABEL (preview_label), preview_text);
283 g_free (modified_time);
285 g_free (preview_text);
287 gtk_widget_hide (preview_image);
288 gtk_widget_show (preview_label);
296 g_error_free (error);
299 gtk_file_chooser_set_preview_widget_active (chooser, have_preview);
303 set_current_folder (GtkFileChooser *chooser,
306 if (!gtk_file_chooser_set_current_folder (chooser, name))
310 dialog = gtk_message_dialog_new (GTK_WINDOW (chooser),
311 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
314 "Could not set the folder to %s",
316 gtk_dialog_run (GTK_DIALOG (dialog));
317 gtk_widget_destroy (dialog);
322 set_folder_nonexistent_cb (GtkButton *button,
323 GtkFileChooser *chooser)
325 set_current_folder (chooser, "/nonexistent");
329 set_folder_existing_nonexistent_cb (GtkButton *button,
330 GtkFileChooser *chooser)
332 set_current_folder (chooser, "/usr/nonexistent");
336 set_filename (GtkFileChooser *chooser,
339 if (!gtk_file_chooser_set_filename (chooser, name))
343 dialog = gtk_message_dialog_new (GTK_WINDOW (chooser),
344 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
347 "Could not select %s",
349 gtk_dialog_run (GTK_DIALOG (dialog));
350 gtk_widget_destroy (dialog);
355 set_filename_nonexistent_cb (GtkButton *button,
356 GtkFileChooser *chooser)
358 set_filename (chooser, "/nonexistent");
362 set_filename_existing_nonexistent_cb (GtkButton *button,
363 GtkFileChooser *chooser)
365 set_filename (chooser, "/usr/nonexistent");
369 main (int argc, char **argv)
371 GtkWidget *control_window;
375 GtkWidget *prop_editor;
377 GtkFileFilter *filter;
378 GtkWidget *preview_vbox;
381 gtk_init (&argc, &argv);
383 action = GTK_FILE_CHOOSER_ACTION_OPEN;
385 /* lame-o arg parsing */
386 for (i = 1; i < argc; i++)
388 if (! strcmp ("--action=open", argv[i]))
389 action = GTK_FILE_CHOOSER_ACTION_OPEN;
390 else if (! strcmp ("--action=save", argv[i]))
391 action = GTK_FILE_CHOOSER_ACTION_SAVE;
392 else if (! strcmp ("--action=select_folder", argv[i]))
393 action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
394 else if (! strcmp ("--action=create_folder", argv[i]))
395 action = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
398 dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
400 "file-system-backend", "gtk+",
404 case GTK_FILE_CHOOSER_ACTION_OPEN:
405 case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
406 gtk_window_set_title (GTK_WINDOW (dialog), "Select a file");
407 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
408 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
409 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
412 case GTK_FILE_CHOOSER_ACTION_SAVE:
413 case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
414 gtk_window_set_title (GTK_WINDOW (dialog), "Save a file");
415 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
416 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
417 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
421 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
423 g_signal_connect (dialog, "selection-changed",
424 G_CALLBACK (print_selected), NULL);
425 g_signal_connect (dialog, "current-folder-changed",
426 G_CALLBACK (print_current_folder), NULL);
427 g_signal_connect (dialog, "response",
428 G_CALLBACK (response_cb), NULL);
431 filter = gtk_file_filter_new ();
432 gtk_file_filter_set_name (filter, "All Files");
433 gtk_file_filter_add_pattern (filter, "*");
434 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
436 filter = gtk_file_filter_new ();
437 gtk_file_filter_set_name (filter, "No backup files");
438 gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_DISPLAY_NAME,
439 no_backup_files_filter, NULL, NULL);
440 gtk_file_filter_add_mime_type (filter, "image/png");
441 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
443 /* Make this filter the default */
444 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
446 filter = gtk_file_filter_new ();
447 gtk_file_filter_set_name (filter, "PNG and JPEG");
448 gtk_file_filter_add_mime_type (filter, "image/jpeg");
449 gtk_file_filter_add_mime_type (filter, "image/png");
450 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
453 preview_vbox = gtk_vbox_new (0, FALSE);
454 gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog), preview_vbox);
456 preview_label = gtk_label_new (NULL);
457 gtk_box_pack_start (GTK_BOX (preview_vbox), preview_label, TRUE, TRUE, 0);
458 gtk_misc_set_padding (GTK_MISC (preview_label), 6, 6);
460 preview_image = gtk_image_new ();
461 gtk_box_pack_start (GTK_BOX (preview_vbox), preview_image, TRUE, TRUE, 0);
462 gtk_misc_set_padding (GTK_MISC (preview_image), 6, 6);
464 update_preview_cb (GTK_FILE_CHOOSER (dialog));
465 g_signal_connect (dialog, "update-preview",
466 G_CALLBACK (update_preview_cb), NULL);
470 extra = gtk_check_button_new_with_mnemonic ("Lar_t whoever asks about this button");
471 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (extra), TRUE);
472 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), extra);
476 gtk_file_chooser_add_shortcut_folder_uri (GTK_FILE_CHOOSER (dialog),
477 "file:///usr/share/pixmaps",
480 /* show_all() to reveal bugs in composite widget handling */
481 gtk_widget_show_all (dialog);
483 /* Extra controls for manipulating the test environment
485 prop_editor = create_prop_editor (G_OBJECT (dialog), GTK_TYPE_FILE_CHOOSER);
487 control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
489 vbbox = gtk_vbutton_box_new ();
490 gtk_container_add (GTK_CONTAINER (control_window), vbbox);
492 button = gtk_button_new_with_mnemonic ("_Select all");
493 gtk_container_add (GTK_CONTAINER (vbbox), button);
494 g_signal_connect_swapped (button, "clicked",
495 G_CALLBACK (gtk_file_chooser_select_all), dialog);
497 button = gtk_button_new_with_mnemonic ("_Unselect all");
498 gtk_container_add (GTK_CONTAINER (vbbox), button);
499 g_signal_connect_swapped (button, "clicked",
500 G_CALLBACK (gtk_file_chooser_unselect_all), dialog);
502 button = gtk_button_new_with_label ("set_current_folder (\"/nonexistent\")");
503 gtk_container_add (GTK_CONTAINER (vbbox), button);
504 g_signal_connect (button, "clicked",
505 G_CALLBACK (set_folder_nonexistent_cb), dialog);
507 button = gtk_button_new_with_label ("set_current_folder (\"/usr/nonexistent\"");
508 gtk_container_add (GTK_CONTAINER (vbbox), button);
509 g_signal_connect (button, "clicked",
510 G_CALLBACK (set_folder_existing_nonexistent_cb), dialog);
512 button = gtk_button_new_with_label ("set_filename (\"/nonexistent\"");
513 gtk_container_add (GTK_CONTAINER (vbbox), button);
514 g_signal_connect (button, "clicked",
515 G_CALLBACK (set_filename_nonexistent_cb), dialog);
517 button = gtk_button_new_with_label ("set_filename (\"/usr/nonexistent\"");
518 gtk_container_add (GTK_CONTAINER (vbbox), button);
519 g_signal_connect (button, "clicked",
520 G_CALLBACK (set_filename_existing_nonexistent_cb), dialog);
522 gtk_widget_show_all (control_window);