2 * gtkhtml-image-chooser-dialog.c
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU Lesser General Public
6 * License as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 02111-1307, USA.
19 #include "gtkhtml-image-chooser-dialog.h"
21 #define PREVIEW_WIDTH 256
22 #define PREVIEW_HEIGHT 256
24 typedef struct _Context Context
;
26 struct _GtkhtmlImageChooserDialogPrivate
{
27 GCancellable
*cancellable
;
31 GtkFileChooser
*file_chooser
;
32 GCancellable
*cancellable
;
36 GtkhtmlImageChooserDialog
,
37 gtkhtml_image_chooser_dialog
,
38 GTK_TYPE_FILE_CHOOSER_DIALOG
)
41 context_free (Context
*context
)
43 g_object_unref (context
->file_chooser
);
44 g_object_unref (context
->cancellable
);
46 g_slice_free (Context
, context
);
50 image_chooser_dialog_read_cb (GFile
*preview_file
,
55 GtkWidget
*preview_widget
;
56 GFileInputStream
*input_stream
;
58 input_stream
= g_file_read_finish (preview_file
, result
, NULL
);
60 /* FIXME Handle errors better, but remember
61 * to ignore G_IO_ERROR_CANCELLED. */
62 if (input_stream
== NULL
)
65 /* XXX This blocks, but GDK-PixBuf offers no asynchronous
66 * alternative and I don't want to deal with making GDK
67 * calls from threads and all the crap that goes with it. */
68 pixbuf
= gdk_pixbuf_new_from_stream_at_scale (
69 G_INPUT_STREAM (input_stream
),
70 PREVIEW_WIDTH
, PREVIEW_HEIGHT
, TRUE
,
71 context
->cancellable
, NULL
);
73 preview_widget
= gtk_file_chooser_get_preview_widget (
74 context
->file_chooser
);
76 gtk_file_chooser_set_preview_widget_active (
77 context
->file_chooser
, pixbuf
!= NULL
);
79 gtk_image_set_from_pixbuf (GTK_IMAGE (preview_widget
), pixbuf
);
82 g_object_unref (pixbuf
);
84 g_object_unref (input_stream
);
87 context_free (context
);
91 image_chooser_dialog_update_preview (GtkFileChooser
*file_chooser
)
93 GtkhtmlImageChooserDialogPrivate
*priv
;
94 GtkWidget
*preview_widget
;
98 priv
= GTKHTML_IMAGE_CHOOSER_DIALOG (file_chooser
)->priv
;
99 preview_file
= gtk_file_chooser_get_preview_file (file_chooser
);
100 preview_widget
= gtk_file_chooser_get_preview_widget (file_chooser
);
102 if (priv
->cancellable
!= NULL
) {
103 g_cancellable_cancel (priv
->cancellable
);
104 g_object_unref (priv
->cancellable
);
105 priv
->cancellable
= NULL
;
108 gtk_image_clear (GTK_IMAGE (preview_widget
));
109 gtk_file_chooser_set_preview_widget_active (file_chooser
, FALSE
);
111 if (preview_file
== NULL
)
114 priv
->cancellable
= g_cancellable_new ();
116 context
= g_slice_new0 (Context
);
117 context
->file_chooser
= g_object_ref (file_chooser
);
118 context
->cancellable
= g_object_ref (priv
->cancellable
);
121 preview_file
, G_PRIORITY_LOW
,
122 priv
->cancellable
, (GAsyncReadyCallback
)
123 image_chooser_dialog_read_cb
, context
);
125 g_object_unref (preview_file
);
129 image_chooser_dialog_dispose (GObject
*object
)
131 GtkhtmlImageChooserDialogPrivate
*priv
;
133 priv
= GTKHTML_IMAGE_CHOOSER_DIALOG (object
)->priv
;
135 if (priv
->cancellable
!= NULL
) {
136 g_cancellable_cancel (priv
->cancellable
);
137 g_object_unref (priv
->cancellable
);
138 priv
->cancellable
= NULL
;
141 /* Chain up to parent's dispose() method. */
142 G_OBJECT_CLASS (gtkhtml_image_chooser_dialog_parent_class
)->
147 image_chooser_dialog_constructed (GObject
*object
)
149 GtkFileChooser
*file_chooser
;
150 GtkFileFilter
*file_filter
;
152 /* Chain up to parent's method. */
153 G_OBJECT_CLASS (gtkhtml_image_chooser_dialog_parent_class
)->constructed (object
);
155 file_chooser
= GTK_FILE_CHOOSER (object
);
156 gtk_file_chooser_set_local_only (file_chooser
, FALSE
);
158 gtk_dialog_add_button (
159 GTK_DIALOG (file_chooser
),
160 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
);
161 gtk_dialog_add_button (
162 GTK_DIALOG (file_chooser
),
163 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
);
164 gtk_dialog_set_default_response (
165 GTK_DIALOG (file_chooser
), GTK_RESPONSE_ACCEPT
);
167 file_filter
= gtk_file_filter_new ();
168 gtk_file_filter_add_pixbuf_formats (file_filter
);
169 gtk_file_chooser_set_filter (file_chooser
, file_filter
);
171 gtk_file_chooser_set_preview_widget (file_chooser
, gtk_image_new ());
175 gtkhtml_image_chooser_dialog_class_init (GtkhtmlImageChooserDialogClass
*class)
177 GObjectClass
*object_class
;
179 g_type_class_add_private (
180 class, sizeof (GtkhtmlImageChooserDialogPrivate
));
182 object_class
= G_OBJECT_CLASS (class);
183 object_class
->dispose
= image_chooser_dialog_dispose
;
184 object_class
->constructed
= image_chooser_dialog_constructed
;
188 gtkhtml_image_chooser_dialog_init (GtkhtmlImageChooserDialog
*dialog
)
190 dialog
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (
191 dialog
, GTKHTML_TYPE_IMAGE_CHOOSER_DIALOG
,
192 GtkhtmlImageChooserDialogPrivate
);
195 dialog
, "update-preview",
196 G_CALLBACK (image_chooser_dialog_update_preview
), NULL
);
200 gtkhtml_image_chooser_dialog_new (const gchar
*title
,
203 return g_object_new (
204 GTKHTML_TYPE_IMAGE_CHOOSER_DIALOG
,
205 "action", GTK_FILE_CHOOSER_ACTION_OPEN
,
207 "transient-for", parent
, NULL
);
211 gtkhtml_image_chooser_dialog_run (GtkhtmlImageChooserDialog
*dialog
)
213 GtkFileChooser
*file_chooser
;
215 g_return_val_if_fail (GTKHTML_IS_IMAGE_CHOOSER_DIALOG (dialog
), NULL
);
217 file_chooser
= GTK_FILE_CHOOSER (dialog
);
219 if (gtk_dialog_run (GTK_DIALOG (dialog
)) != GTK_RESPONSE_ACCEPT
)
222 return gtk_file_chooser_get_file (file_chooser
);