Add over-big test case for preview (much of size from a modified copy of

Wed Jul 23 17:52:01 2003  Owen Taylor  <otaylor@redhat.com>

        * testfilechooser.c: Add over-big test case for preview
        (much of size from a modified copy of
        gdk_pixbuf_new_from_file_at_size())

        * gtkfilechooserutils.[ch] gtkfilechooser.c
        gtkfilechooserprivate.h gtkfilechooserimpldefault.c:
        Add get_preview_path() as a virtual function; implement
        update-preview signal that was in the header file.

        * gtkfilechooserimpldefault.c: Finish a simple preview
        widget implementation.
This commit is contained in:
Owen Taylor 2003-07-23 22:30:32 +00:00 committed by Owen Taylor
parent a19781c504
commit d97d7df947
6 changed files with 393 additions and 29 deletions

View File

@ -28,7 +28,6 @@
static void gtk_file_chooser_base_init (gpointer g_iface);
static GtkFilePath *gtk_file_chooser_get_path (GtkFileChooser *chooser);
static GtkFilePath *gtk_file_chooser_get_preview_path (GtkFileChooser *chooser);
GType
gtk_file_chooser_get_type (void)
@ -77,6 +76,13 @@ gtk_file_chooser_base_init (gpointer g_iface)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
g_signal_new ("update-preview",
iface_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkFileChooserIface, update_preview),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
g_object_interface_install_property (g_iface,
g_param_spec_enum ("action",
@ -771,7 +777,7 @@ gtk_file_chooser_get_current_folder_uri (GtkFileChooser *chooser)
* @path: the #GtkFilePath for the new folder
*
* Sets the current folder for @chooser from a #GtkFilePath.
* Internal function, see _gtk_file_chooser_set_current_folder_uri().
* Internal function, see gtk_file_chooser_set_current_folder_uri().
**/
void
_gtk_file_chooser_set_current_folder_path (GtkFileChooser *chooser,
@ -993,10 +999,22 @@ gtk_file_chooser_get_preview_widget_active (GtkFileChooser *chooser)
return active;
}
static GtkFilePath *
gtk_file_chooser_get_preview_path (GtkFileChooser *chooser)
/**
* gtk_file_chooser_get_preview_filename:
* @chooser: a #GtkFileChooser
*
* Gets the filename that should be previewed in a custom preview
* Internal function, see gtk_file_chooser_get_preview_uri().n
*
* Return value: the #GtkFilePath for the file to preview, or %NULL if no file
* is selected. Free with gtk_file_path_free().
**/
GtkFilePath *
_gtk_file_chooser_get_preview_path (GtkFileChooser *chooser)
{
return NULL;
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_preview_path (chooser);
}
/**
@ -1006,11 +1024,11 @@ gtk_file_chooser_get_preview_path (GtkFileChooser *chooser)
* Gets the filename that should be previewed in a custom preview
* widget. See gtk_file_chooser_set_preview_widget().
*
* Return value: the filename to display, or %NULL if no file
* Return value: the filename to preview, or %NULL if no file
* is selected, or if the selected file cannot be represented
* as a local filename. Free with g_free()
**/
const char *
char *
gtk_file_chooser_get_preview_filename (GtkFileChooser *chooser)
{
GtkFileSystem *file_system;
@ -1020,7 +1038,7 @@ gtk_file_chooser_get_preview_filename (GtkFileChooser *chooser)
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
file_system = _gtk_file_chooser_get_file_system (chooser);
path = gtk_file_chooser_get_preview_path (chooser);
path = _gtk_file_chooser_get_preview_path (chooser);
if (path)
{
result = gtk_file_system_path_to_filename (file_system, path);
@ -1037,10 +1055,10 @@ gtk_file_chooser_get_preview_filename (GtkFileChooser *chooser)
* Gets the URI that should be previewed in a custom preview
* widget. See gtk_file_chooser_set_preview_widget().
*
* Return value: the URI to display, or %NULL if no file
* is selected.
* Return value: the URI for the file to preview, or %NULL if no file
* is selected. Free with g_free().
**/
const char *
char *
gtk_file_chooser_get_preview_uri (GtkFileChooser *chooser)
{
GtkFileSystem *file_system;
@ -1050,7 +1068,7 @@ gtk_file_chooser_get_preview_uri (GtkFileChooser *chooser)
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
file_system = _gtk_file_chooser_get_file_system (chooser);
path = gtk_file_chooser_get_path (chooser);
path = _gtk_file_chooser_get_preview_path (chooser);
if (path)
{
result = gtk_file_system_path_to_uri (file_system, path);
@ -1161,5 +1179,3 @@ gtk_file_chooser_get_filter (GtkFileChooser *chooser)
return filter;
}

View File

@ -98,8 +98,8 @@ void gtk_file_chooser_set_preview_widget_active (GtkFileChooser *chooser,
gboolean active);
gboolean gtk_file_chooser_get_preview_widget_active (GtkFileChooser *chooser);
const char *gtk_file_chooser_get_preview_filename (GtkFileChooser *file_chooser);
const char *gtk_file_chooser_get_preview_uri (GtkFileChooser *file_chooser);
char *gtk_file_chooser_get_preview_filename (GtkFileChooser *file_chooser);
char *gtk_file_chooser_get_preview_uri (GtkFileChooser *file_chooser);
/* List of user selectable filters
*/

View File

@ -29,6 +29,7 @@
#include <gtk/gtkcellrendererpixbuf.h>
#include <gtk/gtkcellrenderertext.h>
#include <gtk/gtkentry.h>
#include <gtk/gtkframe.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtkhpaned.h>
#include <gtk/gtkicontheme.h>
@ -36,6 +37,7 @@
#include <gtk/gtkmenuitem.h>
#include <gtk/gtkoptionmenu.h>
#include <gtk/gtkscrolledwindow.h>
#include <gtk/gtktable.h>
#include <gtk/gtktreeview.h>
#include <gtk/gtktreemodelsort.h>
#include <gtk/gtktreeselection.h>
@ -69,6 +71,9 @@ struct _GtkFileChooserImplDefault
GSList *filters;
GtkFilePath *current_folder;
GtkFilePath *preview_path;
GtkWidget *preview_frame;
guint folder_mode : 1;
guint local_only : 1;
@ -116,6 +121,7 @@ static void gtk_file_chooser_impl_default_unselect_path (GtkFileC
static void gtk_file_chooser_impl_default_select_all (GtkFileChooser *chooser);
static void gtk_file_chooser_impl_default_unselect_all (GtkFileChooser *chooser);
static GSList * gtk_file_chooser_impl_default_get_paths (GtkFileChooser *chooser);
static GtkFilePath * gtk_file_chooser_impl_default_get_preview_path (GtkFileChooser *chooser);
static GtkFileSystem *gtk_file_chooser_impl_default_get_file_system (GtkFileChooser *chooser);
static void gtk_file_chooser_impl_default_add_filter (GtkFileChooser *chooser,
GtkFileFilter *filter);
@ -123,8 +129,9 @@ static void gtk_file_chooser_impl_default_remove_filter (GtkFileC
GtkFileFilter *filter);
static GSList * gtk_file_chooser_impl_default_list_filters (GtkFileChooser *chooser);
static void set_current_filter (GtkFileChooserImplDefault *impl,
GtkFileFilter *filter);
static void set_current_filter (GtkFileChooserImplDefault *impl,
GtkFileFilter *filter);
static void check_preview_change (GtkFileChooserImplDefault *impl);
static void filter_option_menu_changed (GtkOptionMenu *option_menu,
GtkFileChooserImplDefault *impl);
@ -221,6 +228,7 @@ gtk_file_chooser_impl_default_iface_init (GtkFileChooserIface *iface)
iface->select_all = gtk_file_chooser_impl_default_select_all;
iface->unselect_all = gtk_file_chooser_impl_default_unselect_all;
iface->get_paths = gtk_file_chooser_impl_default_get_paths;
iface->get_preview_path = gtk_file_chooser_impl_default_get_preview_path;
iface->get_file_system = gtk_file_chooser_impl_default_get_file_system;
iface->set_current_folder = gtk_file_chooser_impl_default_set_current_folder;
iface->get_current_folder = gtk_file_chooser_impl_default_get_current_folder;
@ -252,6 +260,15 @@ gtk_file_chooser_impl_default_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
update_preview_widget_visibility (GtkFileChooserImplDefault *impl)
{
if (impl->preview_widget_active && impl->preview_widget)
gtk_widget_show (impl->preview_frame);
else
gtk_widget_hide (impl->preview_frame);
}
static void
set_preview_widget (GtkFileChooserImplDefault *impl,
GtkWidget *preview_widget)
@ -263,6 +280,9 @@ set_preview_widget (GtkFileChooserImplDefault *impl,
{
g_object_unref (impl->preview_widget);
impl->preview_widget = NULL;
gtk_container_remove (GTK_CONTAINER (impl->preview_frame),
impl->preview_widget);
}
impl->preview_widget = preview_widget;
@ -270,7 +290,13 @@ set_preview_widget (GtkFileChooserImplDefault *impl,
{
g_object_ref (impl->preview_widget);
gtk_object_sink (GTK_OBJECT (impl->preview_widget));
gtk_widget_show (impl->preview_widget);
gtk_container_add (GTK_CONTAINER (impl->preview_frame),
impl->preview_widget);
}
update_preview_widget_visibility (impl);
}
static GObject*
@ -282,6 +308,7 @@ gtk_file_chooser_impl_default_constructor (GType type,
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
GObject *object;
GtkWidget *table;
GtkWidget *hpaned;
GtkWidget *hbox;
GtkWidget *label;
@ -299,9 +326,17 @@ gtk_file_chooser_impl_default_constructor (GType type,
gtk_widget_push_composite_child ();
table = gtk_table_new (3, 2, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
gtk_box_pack_start (GTK_BOX (impl), table, TRUE, TRUE, 0);
gtk_widget_show (table);
impl->filter_alignment = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
gtk_alignment_set_padding (GTK_ALIGNMENT (impl->filter_alignment), 0, 6, 0, 0);
gtk_box_pack_start (GTK_BOX (impl), impl->filter_alignment, FALSE, FALSE, 0);
gtk_table_attach (GTK_TABLE (table), impl->filter_alignment,
0, 1, 0, 1,
GTK_EXPAND | GTK_FILL, 0,
0, 0);
/* Don't show filter initially */
hbox = gtk_hbox_new (FALSE, 6);
@ -324,7 +359,10 @@ gtk_file_chooser_impl_default_constructor (GType type,
G_CALLBACK (filter_option_menu_changed), impl);
hpaned = gtk_hpaned_new ();
gtk_box_pack_start (GTK_BOX (impl), hpaned, TRUE, TRUE, 0);
gtk_table_attach (GTK_TABLE (table), hpaned,
0, 1, 1, 2,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
0, 0);
gtk_widget_show (hpaned);
impl->tree_scrollwin = gtk_scrolled_window_new (NULL, NULL);
@ -365,7 +403,10 @@ gtk_file_chooser_impl_default_constructor (GType type,
G_CALLBACK (list_selection_changed), impl);
hbox = gtk_hbox_new (FALSE, 6);
gtk_box_pack_start (GTK_BOX (impl), hbox, FALSE, FALSE, 6);
gtk_table_attach (GTK_TABLE (table), hbox,
0, 2, 2, 3,
GTK_EXPAND | GTK_FILL, 0,
0, 6);
gtk_widget_show (hbox);
label = gtk_label_new_with_mnemonic ("_Location:");
@ -382,6 +423,13 @@ gtk_file_chooser_impl_default_constructor (GType type,
gtk_label_set_mnemonic_widget (GTK_LABEL (label), impl->entry);
impl->preview_frame = gtk_frame_new ("Preview");
gtk_table_attach (GTK_TABLE (table), impl->preview_frame,
1, 2, 0, 2,
0, GTK_EXPAND | GTK_FILL,
0, 0);
/* Don't show preview frame initially */
#if 0
focus_chain = g_list_append (NULL, impl->entry);
focus_chain = g_list_append (focus_chain, impl->tree);
@ -488,6 +536,7 @@ gtk_file_chooser_impl_default_set_property (GObject *object,
break;
case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
impl->preview_widget_active = g_value_get_boolean (value);
update_preview_widget_visibility (impl);
break;
case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
{
@ -500,6 +549,8 @@ gtk_file_chooser_impl_default_set_property (GObject *object,
gtk_tree_selection_set_mode (selection,
(select_multiple ?
GTK_SELECTION_MULTIPLE : GTK_SELECTION_BROWSE));
/* FIXME: See note in check_preview_change() */
check_preview_change (impl);
}
}
break;
@ -722,7 +773,7 @@ get_paths_foreach (GtkTreeModel *model,
gtk_tree_model_get_iter (GTK_TREE_MODEL (info->impl->list_model), &child_iter, child_path);
gtk_tree_path_free (child_path);
file_path = _gtk_file_system_model_get_path (info->impl->tree_model, &child_iter);
file_path = _gtk_file_system_model_get_path (info->impl->list_model, &child_iter);
info->result = g_slist_prepend (info->result, gtk_file_path_copy (file_path));
}
@ -737,7 +788,7 @@ gtk_file_chooser_impl_default_get_paths (GtkFileChooser *chooser)
GtkFileChooserImplDefault *impl;
} info = { NULL, };
if (!gtk_tree_view_get_model (GTK_TREE_VIEW (impl->list)))
if (!impl->sort_model)
return NULL;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->list));
@ -748,6 +799,17 @@ gtk_file_chooser_impl_default_get_paths (GtkFileChooser *chooser)
return g_slist_reverse (info.result);
}
static GtkFilePath *
gtk_file_chooser_impl_default_get_preview_path (GtkFileChooser *chooser)
{
GtkFileChooserImplDefault *impl = GTK_FILE_CHOOSER_IMPL_DEFAULT (chooser);
if (impl->preview_path)
return gtk_file_path_copy (impl->preview_path);
else
return NULL;
}
static GtkFileSystem *
gtk_file_chooser_impl_default_get_file_system (GtkFileChooser *chooser)
{
@ -1052,7 +1114,13 @@ update_chooser_entry (GtkFileChooserImplDefault *impl)
GtkTreeIter iter;
GtkTreeIter child_iter;
if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
/* Fixing this for multiple selection involves getting the full
* selection and diffing to find out what the most recently selected
* file is; there is logic in GtkFileSelection that probably can
* be copied; check_preview_change() is similar.
*/
if (impl->select_multiple ||
!gtk_tree_selection_get_selected (selection, NULL, &iter))
return;
gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
@ -1075,6 +1143,49 @@ filter_option_menu_changed (GtkOptionMenu *option_menu,
set_current_filter (impl, new_filter);
}
static void
check_preview_change (GtkFileChooserImplDefault *impl)
{
const GtkFilePath *new_path = NULL;
/* Fixing preview for multiple selection involves getting the full
* selection and diffing to find out what the most recently selected
* file is; there is logic in GtkFileSelection that probably can
* be copied. update_chooser_entry() is similar.
*/
if (impl->sort_model && !impl->select_multiple)
{
GtkTreeSelection *selection;
GtkTreeIter iter;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->list));
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
{
GtkTreeIter child_iter;
gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
&child_iter, &iter);
new_path = _gtk_file_system_model_get_path (impl->list_model, &child_iter);
}
}
if (new_path != impl->preview_path &&
!(new_path && impl->preview_path &&
gtk_file_path_compare (new_path, impl->preview_path) == 0))
{
if (impl->preview_path)
gtk_file_path_free (impl->preview_path);
if (new_path)
impl->preview_path = gtk_file_path_copy (new_path);
else
impl->preview_path = NULL;
g_signal_emit_by_name (impl, "update-preview");
}
}
static void
tree_selection_changed (GtkTreeSelection *selection,
GtkFileChooserImplDefault *impl)
@ -1137,9 +1248,9 @@ tree_selection_changed (GtkTreeSelection *selection,
g_signal_emit_by_name (impl, "current-folder-changed", 0);
update_chooser_entry (impl);
check_preview_change (impl);
g_signal_emit_by_name (impl, "selection-changed", 0);
}
static void
@ -1147,6 +1258,7 @@ list_selection_changed (GtkTreeSelection *selection,
GtkFileChooserImplDefault *impl)
{
update_chooser_entry (impl);
check_preview_change (impl);
g_signal_emit_by_name (impl, "selection-changed", 0);
}

View File

@ -48,6 +48,7 @@ struct _GtkFileChooserIface
void (*select_all) (GtkFileChooser *chooser);
void (*unselect_all) (GtkFileChooser *chooser);
GSList * (*get_paths) (GtkFileChooser *chooser);
GtkFilePath * (*get_preview_path) (GtkFileChooser *chooser);
GtkFileSystem *(*get_file_system) (GtkFileChooser *chooser);
void (*add_filter) (GtkFileChooser *chooser,
GtkFileFilter *filter);
@ -60,8 +61,7 @@ struct _GtkFileChooserIface
*/
void (*current_folder_changed) (GtkFileChooser *chooser);
void (*selection_changed) (GtkFileChooser *chooser);
void (*update_preview) (GtkFileChooser *chooser,
const gchar *uri);
void (*update_preview) (GtkFileChooser *chooser);
};
GtkFileSystem *_gtk_file_chooser_get_file_system (GtkFileChooser *chooser);
@ -73,6 +73,7 @@ void _gtk_file_chooser_select_path (GtkFileChooser *cho
void _gtk_file_chooser_unselect_path (GtkFileChooser *chooser,
const GtkFilePath *path);
GSList * _gtk_file_chooser_get_paths (GtkFileChooser *chooser);
GtkFilePath * _gtk_file_chooser_get_preview_path (GtkFileChooser *chooser);
G_END_DECLS

View File

@ -36,6 +36,7 @@ static void delegate_unselect_path (GtkFileChooser *choose
static void delegate_select_all (GtkFileChooser *chooser);
static void delegate_unselect_all (GtkFileChooser *chooser);
static GSList * delegate_get_paths (GtkFileChooser *chooser);
static GtkFilePath * delegate_get_preview_path (GtkFileChooser *chooser);
static GtkFileSystem *delegate_get_file_system (GtkFileChooser *chooser);
static void delegate_add_filter (GtkFileChooser *chooser,
GtkFileFilter *filter);
@ -49,6 +50,8 @@ static void delegate_current_folder_changed (GtkFileChooser *choose
gpointer data);
static void delegate_selection_changed (GtkFileChooser *chooser,
gpointer data);
static void delegate_update_preview (GtkFileChooser *chooser,
gpointer data);
/**
* _gtk_file_chooser_install_properties:
@ -133,6 +136,7 @@ _gtk_file_chooser_delegate_iface_init (GtkFileChooserIface *iface)
iface->select_all = delegate_select_all;
iface->unselect_all = delegate_unselect_all;
iface->get_paths = delegate_get_paths;
iface->get_preview_path = delegate_get_preview_path;
iface->get_file_system = delegate_get_file_system;
iface->add_filter = delegate_add_filter;
iface->remove_filter = delegate_remove_filter;
@ -165,6 +169,8 @@ _gtk_file_chooser_set_delegate (GtkFileChooser *receiver,
G_CALLBACK (delegate_current_folder_changed), receiver);
g_signal_connect (delegate, "selection-changed",
G_CALLBACK (delegate_selection_changed), receiver);
g_signal_connect (delegate, "update-preview",
G_CALLBACK (delegate_update_preview), receiver);
}
static GtkFileChooser *
@ -205,6 +211,12 @@ delegate_get_paths (GtkFileChooser *chooser)
return _gtk_file_chooser_get_paths (get_delegate (chooser));
}
static GtkFilePath *
delegate_get_preview_path (GtkFileChooser *chooser)
{
return _gtk_file_chooser_get_preview_path (get_delegate (chooser));
}
static GtkFileSystem *
delegate_get_file_system (GtkFileChooser *chooser)
{
@ -267,12 +279,19 @@ static void
delegate_selection_changed (GtkFileChooser *chooser,
gpointer data)
{
g_signal_emit_by_name (data, "selection-changed", 0);
g_signal_emit_by_name (data, "selection-changed");
}
static void
delegate_current_folder_changed (GtkFileChooser *chooser,
gpointer data)
{
g_signal_emit_by_name (data, "current-folder-changed", 0);
g_signal_emit_by_name (data, "current-folder-changed");
}
static void
delegate_update_preview (GtkFileChooser *chooser,
gpointer data)
{
g_signal_emit_by_name (data, "update-preview");
}

View File

@ -1,4 +1,9 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include "gtkfilechooserdialog.h"
@ -11,6 +16,9 @@
#include "gtkfilesystemunix.h"
#endif
static GtkWidget *preview_label;
static GtkWidget *preview_image;
static void
print_current_folder (GtkFileChooser *chooser)
{
@ -56,6 +64,195 @@ no_backup_files_filter (const GtkFileFilterInfo *filter_info,
return 1;
}
static char *
format_time (time_t t)
{
gchar buf[128];
struct tm tm_buf;
time_t now = time (NULL);
const char *format;
if (abs (now - t) < 24*60*60)
format = "%X";
else
format = "%x";
localtime_r (&t, &tm_buf);
if (strftime (buf, sizeof (buf), format, &tm_buf) == 0)
return g_strdup ("<unknown>");
else
return g_strdup (buf);
}
static char *
format_size (gint64 size)
{
if (size < (gint64)1024)
return g_strdup_printf ("%d bytes", (gint)size);
else if (size < (gint64)1024*1024)
return g_strdup_printf ("%.1f K", size / (1024.));
else if (size < (gint64)1024*1024*1024)
return g_strdup_printf ("%.1f M", size / (1024.*1024.));
else
return g_strdup_printf ("%.1f G", size / (1024.*1024.*1024.));
}
#include <stdio.h>
#include <errno.h>
#define _(s) (s)
static void
size_prepared_cb (GdkPixbufLoader *loader,
int width,
int height,
gpointer data)
{
struct {
int width;
int height;
} *info = data;
if ((double)height * (double)info->width >
(double)width * (double)info->height) {
width = 0.5 + (double)width * (double)info->height / (double)height;
height = info->height;
} else {
height = 0.5 + (double)height * (double)info->width / (double)width;
width = info->width;
}
gdk_pixbuf_loader_set_size (loader, width, height);
}
GdkPixbuf *
my_new_from_file_at_size (const char *filename,
int width,
int height,
GError **error)
{
GdkPixbufLoader *loader;
GdkPixbuf *pixbuf;
struct {
int width;
int height;
} info;
guchar buffer [4096];
int length;
FILE *f;
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (width > 0 && height > 0, NULL);
f = fopen (filename, "rb");
if (!f) {
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
_("Failed to open file '%s': %s"),
filename, g_strerror (errno));
return NULL;
}
loader = gdk_pixbuf_loader_new ();
#ifdef DONT_PRESERVE_ASPECT
gdk_pixbuf_loader_set_size (loader, width, height);
#else
info.width = width;
info.height = height;
g_signal_connect (loader, "size-prepared", G_CALLBACK (&size_prepared_cb), &info);
#endif
while (!feof (f)) {
length = fread (buffer, 1, sizeof (buffer), f);
if (length > 0)
if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
gdk_pixbuf_loader_close (loader, NULL);
fclose (f);
g_object_unref (G_OBJECT (loader));
return NULL;
}
}
fclose (f);
if (!gdk_pixbuf_loader_close (loader, error)) {
g_object_unref (G_OBJECT (loader));
return NULL;
}
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
if (!pixbuf) {
g_object_unref (G_OBJECT (loader));
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_FAILED,
_("Failed to load image '%s': reason not known, probably a corrupt image file"),
filename);
return NULL;
}
g_object_ref (pixbuf);
g_object_unref (G_OBJECT (loader));
return pixbuf;
}
static void
update_preview_cb (GtkFileChooser *chooser)
{
gchar *filename = gtk_file_chooser_get_preview_filename (chooser);
gboolean have_preview = FALSE;
if (filename)
{
GdkPixbuf *pixbuf;
GError *error = NULL;
pixbuf = my_new_from_file_at_size (filename, 128, 128, &error);
if (pixbuf)
{
gtk_image_set_from_pixbuf (GTK_IMAGE (preview_image), pixbuf);
g_object_unref (pixbuf);
gtk_widget_show (preview_image);
gtk_widget_hide (preview_label);
have_preview = TRUE;
}
else
{
struct stat buf;
if (stat (filename, &buf) == 0)
{
gchar *preview_text;
gchar *size_str;
gchar *modified_time;
size_str = format_size (buf.st_size);
modified_time = format_time (buf.st_mtime);
preview_text = g_strdup_printf ("<i>Modified:</i>\t%s\n"
"<i>Size:</i>\t%s\n",
modified_time,
size_str);
gtk_label_set_markup (GTK_LABEL (preview_label), preview_text);
g_free (modified_time);
g_free (size_str);
g_free (preview_text);
gtk_widget_hide (preview_image);
gtk_widget_show (preview_label);
have_preview = TRUE;
}
}
g_free (filename);
}
gtk_file_chooser_set_preview_widget_active (chooser, have_preview);
}
int
main (int argc, char **argv)
{
@ -66,6 +263,7 @@ main (int argc, char **argv)
GtkWidget *prop_editor;
GtkFileSystem *file_system;
GtkFileFilter *filter;
GtkWidget *preview_vbox;
gtk_init (&argc, &argv);
@ -116,10 +314,28 @@ main (int argc, char **argv)
gtk_file_filter_add_mime_type (filter, "image/png");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
/* Preview widget */
preview_vbox = gtk_vbox_new (0, FALSE);
gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog), preview_vbox);
preview_label = gtk_label_new (NULL);
gtk_box_pack_start (GTK_BOX (preview_vbox), preview_label, TRUE, TRUE, 0);
gtk_misc_set_padding (GTK_MISC (preview_label), 6, 6);
preview_image = gtk_image_new ();
gtk_box_pack_start (GTK_BOX (preview_vbox), preview_image, TRUE, TRUE, 0);
gtk_misc_set_padding (GTK_MISC (preview_image), 6, 6);
update_preview_cb (GTK_FILE_CHOOSER (dialog));
g_signal_connect (dialog, "update-preview",
G_CALLBACK (update_preview_cb), NULL);
gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
/* show_all() to reveal bugs in composite widget handling */
gtk_widget_show_all (dialog);
/* Extra controls for manipulating the test environment
*/
prop_editor = create_prop_editor (G_OBJECT (dialog), GTK_TYPE_FILE_CHOOSER);
control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);