]> Pileus Git - ~andy/gtk/blob - tests/testfilechooser.c
Removed. (gtk_file_system_gnome_vfs_set_bookmarks): Removed.
[~andy/gtk] / tests / testfilechooser.c
1 #include <string.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <stdlib.h>
5 #include <time.h>
6 #include <unistd.h>
7
8 #include <gtk/gtk.h>
9 #include "gtkfilechooserdialog.h"
10 #include "gtkfilechooser.h"
11 #include "prop-editor.h"
12
13 #ifdef USE_GNOME_VFS
14 #include "gtkfilesystemgnomevfs.h"
15 #else
16 #include "gtkfilesystemunix.h"
17 #endif
18
19 static GtkWidget *preview_label;
20 static GtkWidget *preview_image;
21
22 static void
23 print_current_folder (GtkFileChooser *chooser)
24 {
25   gchar *uri;
26
27   uri = gtk_file_chooser_get_current_folder_uri (chooser);
28   g_print ("Current folder changed :\n  %s\n", uri);
29   g_free (uri);
30 }
31
32 static void
33 print_selected (GtkFileChooser *chooser)
34 {
35   GSList *uris = gtk_file_chooser_get_uris (chooser);
36   GSList *tmp_list;
37
38   g_print ("Selection changed :\n");
39   for (tmp_list = uris; tmp_list; tmp_list = tmp_list->next)
40     {
41       gchar *uri = tmp_list->data;
42       g_print ("  %s\n", uri);
43       g_free (uri);
44     }
45   g_print ("\n");
46   g_slist_free (uris);
47 }
48
49 static void
50 response_cb (GtkDialog *dialog,
51              gint       response_id)
52 {
53   if (response_id == GTK_RESPONSE_OK)
54     {
55       GSList *list;
56
57       list = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
58
59       if (list)
60         {
61           GSList *l;
62
63           g_print ("Selected files:\n");
64
65           for (l = list; l; l = l->next)
66             {
67               g_print ("%s\n", (char *) l->data);
68               g_free (l->data);
69             }
70
71           g_slist_free (list);
72         }
73       else
74         g_print ("No selected files\n");
75     }
76   else
77     g_print ("Dialog was closed\n");
78   
79   gtk_main_quit ();
80 }
81
82 static gboolean
83 no_backup_files_filter (const GtkFileFilterInfo *filter_info,
84                         gpointer                 data)
85 {
86   gsize len = strlen (filter_info->display_name);
87   if (len > 0 && filter_info->display_name[len - 1] == '~')
88     return 0;
89   else
90     return 1;
91 }
92
93 static char *
94 format_time (time_t t)
95 {
96   gchar buf[128];
97   struct tm tm_buf;
98   time_t now = time (NULL);
99   const char *format;
100
101   if (abs (now - t) < 24*60*60)
102     format = "%X";
103   else
104     format = "%x";
105
106   localtime_r (&t, &tm_buf);
107   if (strftime (buf, sizeof (buf), format, &tm_buf) == 0)
108     return g_strdup ("<unknown>");
109   else
110     return g_strdup (buf);
111 }
112
113 static char *
114 format_size (gint64 size)
115 {
116   if (size < (gint64)1024)
117     return g_strdup_printf ("%d bytes", (gint)size);
118   else if (size < (gint64)1024*1024)
119     return g_strdup_printf ("%.1f K", size / (1024.));
120   else if (size < (gint64)1024*1024*1024)
121     return g_strdup_printf ("%.1f M", size / (1024.*1024.));
122   else
123     return g_strdup_printf ("%.1f G", size / (1024.*1024.*1024.));
124 }
125
126 #include <stdio.h>
127 #include <errno.h>
128 #define _(s) (s)
129
130 static void
131 size_prepared_cb (GdkPixbufLoader *loader, 
132                   int              width,
133                   int              height,
134                   gpointer         data)
135 {
136         struct {
137                 int width;
138                 int height;
139         } *info = data;
140
141         if ((double)height * (double)info->width >
142             (double)width * (double)info->height) {
143                 width = 0.5 + (double)width * (double)info->height / (double)height;
144                 height = info->height;
145         } else {
146                 height = 0.5 + (double)height * (double)info->width / (double)width;
147                 width = info->width;
148         }
149
150         gdk_pixbuf_loader_set_size (loader, width, height);
151 }
152
153 GdkPixbuf *
154 my_new_from_file_at_size (const char *filename,
155                           int         width, 
156                           int         height,
157                           GError    **error)
158 {
159         GdkPixbufLoader *loader;
160         GdkPixbuf       *pixbuf;
161         struct {
162                 int width;
163                 int height;
164         } info;
165         struct stat st;
166
167         guchar buffer [4096];
168         int length;
169         FILE *f;
170
171         g_return_val_if_fail (filename != NULL, NULL);
172         g_return_val_if_fail (width > 0 && height > 0, NULL);
173
174         if (stat (filename, &st) != 0) {
175                 g_set_error (error,
176                              G_FILE_ERROR,
177                              g_file_error_from_errno (errno),
178                              _("Could not get information for file '%s': %s"),
179                              filename, g_strerror (errno));
180                 return NULL;
181         }
182
183         if (!S_ISREG (st.st_mode))
184                 return NULL;
185
186         f = fopen (filename, "rb");
187         if (!f) {
188                 g_set_error (error,
189                              G_FILE_ERROR,
190                              g_file_error_from_errno (errno),
191                              _("Failed to open file '%s': %s"),
192                              filename, g_strerror (errno));
193                 return NULL;
194         }
195         
196         loader = gdk_pixbuf_loader_new ();
197 #ifdef DONT_PRESERVE_ASPECT
198         gdk_pixbuf_loader_set_size (loader, width, height);
199 #else
200         info.width = width;
201         info.height = height;
202         g_signal_connect (loader, "size-prepared", G_CALLBACK (&size_prepared_cb), &info);
203 #endif  
204
205         while (!feof (f)) {
206                 length = fread (buffer, 1, sizeof (buffer), f);
207                 if (length > 0)
208                         if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
209                                 gdk_pixbuf_loader_close (loader, NULL);
210                                 fclose (f);
211                                 g_object_unref (G_OBJECT (loader));
212                                 return NULL;
213                         }
214         }
215
216         fclose (f);
217
218         if (!gdk_pixbuf_loader_close (loader, error)) {
219                 g_object_unref (G_OBJECT (loader));
220                 return NULL;
221         }
222
223         pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
224
225         if (!pixbuf) {
226                 g_object_unref (G_OBJECT (loader));
227                 g_set_error (error,
228                              GDK_PIXBUF_ERROR,
229                              GDK_PIXBUF_ERROR_FAILED,
230                              _("Failed to load image '%s': reason not known, probably a corrupt image file"),
231                              filename);
232                 return NULL;
233         }
234
235         g_object_ref (pixbuf);
236
237         g_object_unref (G_OBJECT (loader));
238
239         return pixbuf;
240 }
241
242 static void
243 update_preview_cb (GtkFileChooser *chooser)
244 {
245   gchar *filename = gtk_file_chooser_get_preview_filename (chooser);
246   gboolean have_preview = FALSE;
247   
248   if (filename)
249     {
250       GdkPixbuf *pixbuf;
251       GError *error = NULL;
252
253       pixbuf = my_new_from_file_at_size (filename, 128, 128, &error);
254       if (pixbuf)
255         {
256           gtk_image_set_from_pixbuf (GTK_IMAGE (preview_image), pixbuf);
257           g_object_unref (pixbuf);
258           gtk_widget_show (preview_image);
259           gtk_widget_hide (preview_label);
260           have_preview = TRUE;
261         }
262       else
263         {
264           struct stat buf;
265           if (stat (filename, &buf) == 0)
266             {
267               gchar *preview_text;
268               gchar *size_str;
269               gchar *modified_time;
270               
271               size_str = format_size (buf.st_size);
272               modified_time = format_time (buf.st_mtime);
273               
274               preview_text = g_strdup_printf ("<i>Modified:</i>\t%s\n"
275                                               "<i>Size:</i>\t%s\n",
276                                               modified_time,
277                                               size_str);
278               gtk_label_set_markup (GTK_LABEL (preview_label), preview_text);
279               g_free (modified_time);
280               g_free (size_str);
281               g_free (preview_text);
282               
283               gtk_widget_hide (preview_image);
284               gtk_widget_show (preview_label);
285               have_preview = TRUE;
286             }
287         }
288       
289       g_free (filename);
290     }
291
292   gtk_file_chooser_set_preview_widget_active (chooser, have_preview);
293 }
294
295 int
296 main (int argc, char **argv)
297 {
298   GtkWidget *control_window;
299   GtkWidget *vbbox;
300   GtkWidget *button;
301   GtkWidget *dialog;
302   GtkWidget *prop_editor;
303   GtkFileSystem *file_system;
304   GtkFileFilter *filter;
305   GtkWidget *preview_vbox;
306   GtkWidget *extra;
307   
308   gtk_init (&argc, &argv);
309
310 #ifdef USE_GNOME_VFS
311   file_system = gtk_file_system_gnome_vfs_new ();
312 #else  
313   file_system = gtk_file_system_unix_new ();
314 #endif
315   
316   dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
317                          "action", GTK_FILE_CHOOSER_ACTION_OPEN,
318                          "file-system", file_system,
319                          "title", "Select a file",
320                          NULL);
321                          
322   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
323                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
324                           GTK_STOCK_OPEN, GTK_RESPONSE_OK,
325                           NULL);
326   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
327   
328   g_signal_connect (dialog, "selection-changed",
329                     G_CALLBACK (print_selected), NULL);
330   g_signal_connect (dialog, "current-folder-changed",
331                     G_CALLBACK (print_current_folder), NULL);
332   g_signal_connect (dialog, "response",
333                     G_CALLBACK (response_cb), NULL);
334
335   /* Filters */
336   filter = gtk_file_filter_new ();
337   gtk_file_filter_set_name (filter, "All Files");
338   gtk_file_filter_add_pattern (filter, "*");
339   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
340   
341   filter = gtk_file_filter_new ();
342   gtk_file_filter_set_name (filter, "No backup files");
343   gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_DISPLAY_NAME,
344                               no_backup_files_filter, NULL, NULL);
345   gtk_file_filter_add_mime_type (filter, "image/png");
346   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
347
348   /* Make this filter the default */
349   gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
350   
351   filter = gtk_file_filter_new ();
352   gtk_file_filter_set_name (filter, "PNG and JPEG");
353   gtk_file_filter_add_mime_type (filter, "image/jpeg");
354   gtk_file_filter_add_mime_type (filter, "image/png");
355   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
356
357   /* Preview widget */
358   preview_vbox = gtk_vbox_new (0, FALSE);
359   gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog), preview_vbox);
360   
361   preview_label = gtk_label_new (NULL);
362   gtk_box_pack_start (GTK_BOX (preview_vbox), preview_label, TRUE, TRUE, 0);
363   gtk_misc_set_padding (GTK_MISC (preview_label), 6, 6);
364   
365   preview_image = gtk_image_new ();
366   gtk_box_pack_start (GTK_BOX (preview_vbox), preview_image, TRUE, TRUE, 0);
367   gtk_misc_set_padding (GTK_MISC (preview_image), 6, 6);
368   
369   update_preview_cb (GTK_FILE_CHOOSER (dialog));
370   g_signal_connect (dialog, "update-preview",
371                     G_CALLBACK (update_preview_cb), NULL);
372
373   /* Extra widget */
374   extra = gtk_check_button_new_with_mnemonic ("_Frobnicate the file");
375   gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), extra);
376
377   /* Shortcuts */
378
379   gtk_file_chooser_add_shortcut_folder_uri (GTK_FILE_CHOOSER (dialog),
380                                             "file:///usr/share/pixmaps",
381                                             NULL);
382
383   /* Done with the dialog */
384   gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
385   /* show_all() to reveal bugs in composite widget handling */
386   gtk_widget_show_all (dialog);
387
388   /* Extra controls for manipulating the test environment
389    */
390   prop_editor = create_prop_editor (G_OBJECT (dialog), GTK_TYPE_FILE_CHOOSER);
391
392   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
393   
394   vbbox = gtk_vbutton_box_new ();
395   gtk_container_add (GTK_CONTAINER (control_window), vbbox);
396
397   button = gtk_button_new_with_mnemonic ("_Select all");
398   gtk_container_add (GTK_CONTAINER (vbbox), button);
399   g_signal_connect_swapped (button, "clicked",
400                             G_CALLBACK (gtk_file_chooser_select_all), dialog);
401   
402   button = gtk_button_new_with_mnemonic ("_Unselect all");
403   gtk_container_add (GTK_CONTAINER (vbbox), button);
404   g_signal_connect_swapped (button, "clicked",
405                             G_CALLBACK (gtk_file_chooser_unselect_all), dialog);
406
407   gtk_widget_show_all (control_window);
408   
409   gtk_main ();
410
411   return 0;
412 }