15 # define localtime_r(t,b) *(b) = *localtime (t)
17 # define S_ISREG(m) ((m) & _S_IFREG)
21 #include "prop-editor.h"
23 static GtkWidget *preview_label;
24 static GtkWidget *preview_image;
25 static GtkFileChooserAction action;
28 print_current_folder (GtkFileChooser *chooser)
32 uri = gtk_file_chooser_get_current_folder_uri (chooser);
33 g_print ("Current folder changed :\n %s\n", uri ? uri : "(null)");
38 print_selected (GtkFileChooser *chooser)
40 GSList *uris = gtk_file_chooser_get_uris (chooser);
43 g_print ("Selection changed :\n");
44 for (tmp_list = uris; tmp_list; tmp_list = tmp_list->next)
46 gchar *uri = tmp_list->data;
47 g_print (" %s\n", uri);
55 response_cb (GtkDialog *dialog,
58 if (response_id == GTK_RESPONSE_OK)
62 list = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
68 g_print ("Selected files:\n");
70 for (l = list; l; l = l->next)
72 g_print ("%s\n", (char *) l->data);
79 g_print ("No selected files\n");
82 g_print ("Dialog was closed\n");
88 no_backup_files_filter (const GtkFileFilterInfo *filter_info,
91 gsize len = filter_info->display_name ? strlen (filter_info->display_name) : 0;
92 if (len > 0 && filter_info->display_name[len - 1] == '~')
99 format_time (time_t t)
103 time_t now = time (NULL);
106 if (abs (now - t) < 24*60*60)
111 localtime_r (&t, &tm_buf);
112 if (strftime (buf, sizeof (buf), format, &tm_buf) == 0)
113 return g_strdup ("<unknown>");
115 return g_strdup (buf);
119 format_size (gint64 size)
121 if (size < (gint64)1024)
122 return g_strdup_printf ("%d bytes", (gint)size);
123 else if (size < (gint64)1024*1024)
124 return g_strdup_printf ("%.1f K", size / (1024.));
125 else if (size < (gint64)1024*1024*1024)
126 return g_strdup_printf ("%.1f M", size / (1024.*1024.));
128 return g_strdup_printf ("%.1f G", size / (1024.*1024.*1024.));
136 size_prepared_cb (GdkPixbufLoader *loader,
141 int des_width = data[0];
142 int des_height = data[1];
144 if (des_height >= height && des_width >= width) {
146 } else if ((double)height * des_width > (double)width * des_height) {
147 width = 0.5 + (double)width * des_height / (double)height;
150 height = 0.5 + (double)height * des_width / (double)width;
154 gdk_pixbuf_loader_set_size (loader, width, height);
158 my_new_from_file_at_size (const char *filename,
163 GdkPixbufLoader *loader;
168 guchar buffer [4096];
172 g_return_val_if_fail (filename != NULL, NULL);
173 g_return_val_if_fail (width > 0 && height > 0, NULL);
175 if (stat (filename, &st) != 0) {
178 g_file_error_from_errno (errno),
179 _("Could not get information for file '%s': %s"),
180 filename, g_strerror (errno));
184 if (!S_ISREG (st.st_mode))
187 f = fopen (filename, "rb");
191 g_file_error_from_errno (errno),
192 _("Failed to open file '%s': %s"),
193 filename, g_strerror (errno));
197 loader = gdk_pixbuf_loader_new ();
198 #ifdef DONT_PRESERVE_ASPECT
199 gdk_pixbuf_loader_set_size (loader, width, height);
203 g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), info);
207 length = fread (buffer, 1, sizeof (buffer), f);
209 if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
210 gdk_pixbuf_loader_close (loader, NULL);
212 g_object_unref (G_OBJECT (loader));
219 g_assert (*error == NULL);
220 if (!gdk_pixbuf_loader_close (loader, error)) {
221 g_object_unref (G_OBJECT (loader));
225 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
228 g_object_unref (G_OBJECT (loader));
230 /* did the loader set an error? */
236 GDK_PIXBUF_ERROR_FAILED,
237 _("Failed to load image '%s': reason not known, probably a corrupt image file"),
242 g_object_ref (pixbuf);
244 g_object_unref (G_OBJECT (loader));
250 update_preview_cb (GtkFileChooser *chooser)
252 gchar *filename = gtk_file_chooser_get_preview_filename (chooser);
253 gboolean have_preview = FALSE;
258 GError *error = NULL;
260 pixbuf = my_new_from_file_at_size (filename, 128, 128, &error);
263 gtk_image_set_from_pixbuf (GTK_IMAGE (preview_image), pixbuf);
264 g_object_unref (pixbuf);
265 gtk_widget_show (preview_image);
266 gtk_widget_hide (preview_label);
272 if (stat (filename, &buf) == 0)
276 gchar *modified_time;
278 size_str = format_size (buf.st_size);
279 modified_time = format_time (buf.st_mtime);
281 preview_text = g_strdup_printf ("<i>Modified:</i>\t%s\n"
282 "<i>Size:</i>\t%s\n",
285 gtk_label_set_markup (GTK_LABEL (preview_label), preview_text);
286 g_free (modified_time);
288 g_free (preview_text);
290 gtk_widget_hide (preview_image);
291 gtk_widget_show (preview_label);
299 g_error_free (error);
302 gtk_file_chooser_set_preview_widget_active (chooser, have_preview);
306 set_current_folder (GtkFileChooser *chooser,
309 if (!gtk_file_chooser_set_current_folder (chooser, name))
313 dialog = gtk_message_dialog_new (GTK_WINDOW (chooser),
314 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
317 "Could not set the folder to %s",
319 gtk_dialog_run (GTK_DIALOG (dialog));
320 gtk_widget_destroy (dialog);
325 set_folder_nonexistent_cb (GtkButton *button,
326 GtkFileChooser *chooser)
328 set_current_folder (chooser, "/nonexistent");
332 set_folder_existing_nonexistent_cb (GtkButton *button,
333 GtkFileChooser *chooser)
335 set_current_folder (chooser, "/usr/nonexistent");
339 set_filename (GtkFileChooser *chooser,
342 if (!gtk_file_chooser_set_filename (chooser, name))
346 dialog = gtk_message_dialog_new (GTK_WINDOW (chooser),
347 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
350 "Could not select %s",
352 gtk_dialog_run (GTK_DIALOG (dialog));
353 gtk_widget_destroy (dialog);
358 set_filename_nonexistent_cb (GtkButton *button,
359 GtkFileChooser *chooser)
361 set_filename (chooser, "/nonexistent");
365 set_filename_existing_nonexistent_cb (GtkButton *button,
366 GtkFileChooser *chooser)
368 set_filename (chooser, "/usr/nonexistent");
372 main (int argc, char **argv)
374 GtkWidget *control_window;
378 GtkWidget *prop_editor;
380 GtkFileFilter *filter;
381 GtkWidget *preview_vbox;
383 gboolean multiple = FALSE;
385 gtk_init (&argc, &argv);
387 action = GTK_FILE_CHOOSER_ACTION_OPEN;
389 /* lame-o arg parsing */
390 for (i = 1; i < argc; i++)
392 if (! strcmp ("--action=open", argv[i]))
393 action = GTK_FILE_CHOOSER_ACTION_OPEN;
394 else if (! strcmp ("--action=save", argv[i]))
395 action = GTK_FILE_CHOOSER_ACTION_SAVE;
396 else if (! strcmp ("--action=select_folder", argv[i]))
397 action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
398 else if (! strcmp ("--action=create_folder", argv[i]))
399 action = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
400 else if (! strcmp ("--multiple", argv[i]))
404 dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
406 /* "file-system-backend", "gtk+",*/
407 "select-multiple", multiple,
411 case GTK_FILE_CHOOSER_ACTION_OPEN:
412 case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
413 gtk_window_set_title (GTK_WINDOW (dialog), "Select a file");
414 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
415 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
416 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
419 case GTK_FILE_CHOOSER_ACTION_SAVE:
420 case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
421 gtk_window_set_title (GTK_WINDOW (dialog), "Save a file");
422 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
423 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
424 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
428 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
430 g_signal_connect (dialog, "selection-changed",
431 G_CALLBACK (print_selected), NULL);
432 g_signal_connect (dialog, "current-folder-changed",
433 G_CALLBACK (print_current_folder), NULL);
434 g_signal_connect (dialog, "response",
435 G_CALLBACK (response_cb), NULL);
438 filter = gtk_file_filter_new ();
439 gtk_file_filter_set_name (filter, "All Files");
440 gtk_file_filter_add_pattern (filter, "*");
441 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
443 filter = gtk_file_filter_new ();
444 gtk_file_filter_set_name (filter, "No backup files");
445 gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_DISPLAY_NAME,
446 no_backup_files_filter, NULL, NULL);
447 gtk_file_filter_add_mime_type (filter, "image/png");
448 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
450 /* Make this filter the default */
451 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
453 filter = gtk_file_filter_new ();
454 gtk_file_filter_set_name (filter, "PNG and JPEG");
455 gtk_file_filter_add_mime_type (filter, "image/jpeg");
456 gtk_file_filter_add_mime_type (filter, "image/png");
457 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
460 /* THIS IS A TERRIBLE PREVIEW WIDGET, AND SHOULD NOT BE COPIED AT ALL.
462 preview_vbox = gtk_vbox_new (0, FALSE);
463 /* gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog), preview_vbox);*/
465 preview_label = gtk_label_new (NULL);
466 gtk_box_pack_start (GTK_BOX (preview_vbox), preview_label, TRUE, TRUE, 0);
467 gtk_misc_set_padding (GTK_MISC (preview_label), 6, 6);
469 preview_image = gtk_image_new ();
470 gtk_box_pack_start (GTK_BOX (preview_vbox), preview_image, TRUE, TRUE, 0);
471 gtk_misc_set_padding (GTK_MISC (preview_image), 6, 6);
473 update_preview_cb (GTK_FILE_CHOOSER (dialog));
474 g_signal_connect (dialog, "update-preview",
475 G_CALLBACK (update_preview_cb), NULL);
479 extra = gtk_check_button_new_with_mnemonic ("Lar_t whoever asks about this button");
480 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (extra), TRUE);
481 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), extra);
485 gtk_file_chooser_add_shortcut_folder_uri (GTK_FILE_CHOOSER (dialog),
486 "file:///usr/share/pixmaps",
489 /* show_all() to reveal bugs in composite widget handling */
490 gtk_widget_show_all (dialog);
492 /* Extra controls for manipulating the test environment
494 prop_editor = create_prop_editor (G_OBJECT (dialog), GTK_TYPE_FILE_CHOOSER);
496 control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
498 vbbox = gtk_vbutton_box_new ();
499 gtk_container_add (GTK_CONTAINER (control_window), vbbox);
501 button = gtk_button_new_with_mnemonic ("_Select all");
502 gtk_widget_set_sensitive (button, multiple);
503 gtk_container_add (GTK_CONTAINER (vbbox), button);
504 g_signal_connect_swapped (button, "clicked",
505 G_CALLBACK (gtk_file_chooser_select_all), dialog);
507 button = gtk_button_new_with_mnemonic ("_Unselect all");
508 gtk_container_add (GTK_CONTAINER (vbbox), button);
509 g_signal_connect_swapped (button, "clicked",
510 G_CALLBACK (gtk_file_chooser_unselect_all), dialog);
512 button = gtk_button_new_with_label ("set_current_folder (\"/nonexistent\")");
513 gtk_container_add (GTK_CONTAINER (vbbox), button);
514 g_signal_connect (button, "clicked",
515 G_CALLBACK (set_folder_nonexistent_cb), dialog);
517 button = gtk_button_new_with_label ("set_current_folder (\"/usr/nonexistent\"");
518 gtk_container_add (GTK_CONTAINER (vbbox), button);
519 g_signal_connect (button, "clicked",
520 G_CALLBACK (set_folder_existing_nonexistent_cb), dialog);
522 button = gtk_button_new_with_label ("set_filename (\"/nonexistent\"");
523 gtk_container_add (GTK_CONTAINER (vbbox), button);
524 g_signal_connect (button, "clicked",
525 G_CALLBACK (set_filename_nonexistent_cb), dialog);
527 button = gtk_button_new_with_label ("set_filename (\"/usr/nonexistent\"");
528 gtk_container_add (GTK_CONTAINER (vbbox), button);
529 g_signal_connect (button, "clicked",
530 G_CALLBACK (set_filename_existing_nonexistent_cb), dialog);
532 gtk_widget_show_all (control_window);