1 /* gtkam-cancel.c
2 *
3 * Copyright 2001-2002 Lutz Mueller <lutz@users.sf.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "config.h"
20 #include "gtkam-cancel.h"
21 #include "i18n.h"
22
23 #include <string.h>
24
25 #include <gtk/gtkbutton.h>
26 #include <gtk/gtkmain.h>
27 #include <gtk/gtklabel.h>
28 #include <gtk/gtksignal.h>
29 #include <gtk/gtkhbox.h>
30 #include <gtk/gtkprogressbar.h>
31 #include <gtk/gtkpixmap.h>
32 #include <gtk/gtkmarshal.h>
33 #include <gtk/gtkimage.h>
34 #include <gtk/gtkstock.h>
35
36 #include <gphoto2/gphoto2-result.h>
37
38 #include "gtkam-close.h"
39
40 struct _GtkamCancelPrivate
41 {
42 GPtrArray *array_hbox, *array_progress;
43 GArray *target;
44
45 gboolean cancelled;
46 };
47
48 #define PARENT_TYPE GTKAM_TYPE_DIALOG
49 static GtkamDialogClass *parent_class;
50
51 enum {
52 CANCEL,
53 LAST_SIGNAL
54 };
55
56 static guint signals[LAST_SIGNAL] = {0};
57
58 static void
gtkam_cancel_destroy(GtkObject * object)59 gtkam_cancel_destroy (GtkObject *object)
60 {
61 GtkamCancel *cancel = GTKAM_CANCEL (object);
62
63 if (cancel->context) {
64 g_object_unref (G_OBJECT (cancel->context));
65 cancel->context = NULL;
66 }
67
68 g_ptr_array_set_size (cancel->priv->array_hbox, 0);
69 g_ptr_array_set_size (cancel->priv->array_progress, 0);
70 g_array_set_size (cancel->priv->target, 0);
71
72 GTK_OBJECT_CLASS (parent_class)->destroy (object);
73 }
74
75 static void
gtkam_cancel_finalize(GObject * object)76 gtkam_cancel_finalize (GObject *object)
77 {
78 GtkamCancel *cancel = GTKAM_CANCEL (object);
79
80 g_array_free (cancel->priv->target, TRUE);
81 g_ptr_array_free (cancel->priv->array_hbox, TRUE);
82 g_ptr_array_free (cancel->priv->array_progress, TRUE);
83 g_free (cancel->priv);
84
85 G_OBJECT_CLASS (parent_class)->finalize (object);
86 }
87
88 static void
gtkam_cancel_class_init(gpointer g_class,gpointer class_data)89 gtkam_cancel_class_init (gpointer g_class, gpointer class_data)
90 {
91 GtkObjectClass *object_class;
92 GObjectClass *gobject_class;
93
94 object_class = GTK_OBJECT_CLASS (g_class);
95 object_class->destroy = gtkam_cancel_destroy;
96
97 gobject_class = G_OBJECT_CLASS (g_class);
98 gobject_class->finalize = gtkam_cancel_finalize;
99
100 signals[CANCEL] = g_signal_new ("cancel",
101 G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST,
102 G_STRUCT_OFFSET (GtkamCancelClass, cancel), NULL, NULL,
103 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
104
105 parent_class = g_type_class_peek_parent (g_class);
106 }
107
108 static void
gtkam_cancel_init(GTypeInstance * instance,gpointer g_class)109 gtkam_cancel_init (GTypeInstance *instance, gpointer g_class)
110 {
111 GtkamCancel *cancel = GTKAM_CANCEL (instance);
112
113 cancel->context = gtkam_context_new ();
114
115 cancel->priv = g_new0 (GtkamCancelPrivate, 1);
116 cancel->priv->array_hbox = g_ptr_array_new ();
117 cancel->priv->array_progress = g_ptr_array_new ();
118 cancel->priv->target = g_array_new (FALSE, TRUE, sizeof (float));
119 }
120
121 GType
gtkam_cancel_get_type(void)122 gtkam_cancel_get_type (void)
123 {
124 static GType type = 0;
125
126 if (!type) {
127 GTypeInfo ti;
128
129 memset (&ti, 0, sizeof (GTypeInfo));
130 ti.class_size = sizeof (GtkamCancelClass);
131 ti.class_init = gtkam_cancel_class_init;
132 ti.instance_size = sizeof (GtkamCancel);
133 ti.instance_init = gtkam_cancel_init;
134
135 type = g_type_register_static (PARENT_TYPE, "GtkamCancel",
136 &ti, 0);
137 }
138
139 return (type);
140 }
141
142 static void
on_cancel_clicked(GtkButton * button,GtkamCancel * cancel)143 on_cancel_clicked (GtkButton *button, GtkamCancel *cancel)
144 {
145 cancel->priv->cancelled = TRUE;
146 g_signal_emit (GTK_OBJECT (cancel), signals[CANCEL], 0);
147 }
148
149 static GPContextFeedback
cancel_func(GPContext * c,void * data)150 cancel_func (GPContext *c, void *data)
151 {
152 GtkamCancel *cancel = GTKAM_CANCEL (data);
153
154 return (cancel->priv->cancelled ? GP_CONTEXT_FEEDBACK_CANCEL :
155 GP_CONTEXT_FEEDBACK_OK);
156 }
157
158 static void
message_func(GPContext * context,const char * msg,void * data)159 message_func (GPContext *context, const char *msg, void *data)
160 {
161 GtkamCancel *cancel = GTKAM_CANCEL (data);
162 GtkWidget *d;
163
164 cancel = NULL;
165 d = gtkam_close_new (msg);
166 gtk_widget_show (d);
167 }
168
169 static unsigned int
start_func(GPContext * c,float target,const char * msg,void * data)170 start_func (GPContext *c, float target, const char *msg, void *data)
171 {
172 GtkamCancel *cancel = GTKAM_CANCEL (data);
173 GtkWidget *p, *label, *hbox;
174 unsigned int i;
175
176 hbox = gtk_hbox_new (FALSE, 5);
177 gtk_widget_show (hbox);
178 gtk_box_pack_start (GTK_BOX (GTKAM_DIALOG (cancel)->vbox), hbox,
179 TRUE, TRUE, 0);
180
181 label = gtk_label_new (msg);
182 gtk_widget_show (label);
183 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
184
185 p = gtk_progress_bar_new ();
186 gtk_widget_show (p);
187 gtk_box_pack_start (GTK_BOX (hbox), p, TRUE, TRUE, 0);
188
189 for (i = 0; i < cancel->priv->array_progress->len; i++)
190 if (!cancel->priv->array_progress->pdata[i])
191 break;
192 if (i == cancel->priv->array_progress->len) {
193 g_ptr_array_add (cancel->priv->array_hbox, hbox);
194 g_ptr_array_add (cancel->priv->array_progress, p);
195 g_array_append_val (cancel->priv->target, target);
196 } else {
197 cancel->priv->array_hbox->pdata[i] = hbox;
198 cancel->priv->array_progress->pdata[i] = p;
199 g_array_index (cancel->priv->target, gfloat, i) = target;
200 }
201
202 return (cancel->priv->array_progress->len - 1);
203 }
204
205 static void
update_func(GPContext * c,unsigned int id,float current,void * data)206 update_func (GPContext *c, unsigned int id, float current, void *data)
207 {
208 GtkamCancel *cancel = GTKAM_CANCEL (data);
209 GtkProgressBar *p;
210
211 g_return_if_fail (id < cancel->priv->array_progress->len);
212
213 p = cancel->priv->array_progress->pdata[id];
214 gtk_progress_bar_set_fraction (p,
215 current / g_array_index (cancel->priv->target, float, id));
216
217 while (gtk_events_pending ())
218 gtk_main_iteration ();
219 }
220
221 static void
stop_func(GPContext * c,unsigned int id,void * data)222 stop_func (GPContext *c, unsigned int id, void *data)
223 {
224 GtkamCancel *cancel = GTKAM_CANCEL (data);
225
226 g_return_if_fail (id < cancel->priv->array_progress->len);
227
228 gtk_object_destroy (GTK_OBJECT (cancel->priv->array_hbox->pdata[id]));
229
230 cancel->priv->array_hbox->pdata[id] = NULL;
231 cancel->priv->array_progress->pdata[id] = NULL;
232 g_array_index (cancel->priv->target, gfloat, id) = 0.;
233 }
234
235 static void
idle_func(GPContext * context,void * data)236 idle_func (GPContext *context, void *data)
237 {
238 while (gtk_events_pending ())
239 gtk_main_iteration ();
240 }
241
242 GtkWidget *
gtkam_cancel_new(const gchar * format,...)243 gtkam_cancel_new (const gchar *format, ...)
244 {
245 GtkamCancel *cancel;
246 GtkWidget *label, *button;
247 va_list args;
248 gchar *msg;
249
250 cancel = g_object_new (GTKAM_TYPE_CANCEL, NULL);
251
252 va_start (args, format);
253 msg = g_strdup_vprintf (format, args);
254 va_end (args);
255 label = gtk_label_new (msg);
256 g_free (msg);
257 gtk_widget_show (label);
258 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
259 gtk_misc_set_alignment (GTK_MISC (label), 0., 0.);
260 gtk_box_pack_start (GTK_BOX (GTKAM_DIALOG (cancel)->vbox),
261 label, TRUE, TRUE, 0);
262
263 button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
264 gtk_widget_show (button);
265 g_signal_connect (GTK_OBJECT (button), "clicked",
266 GTK_SIGNAL_FUNC (on_cancel_clicked), cancel);
267 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (cancel)->action_area),
268 button);
269 gtk_widget_grab_focus (button);
270
271 gp_context_set_progress_funcs (cancel->context->context, start_func,
272 update_func, stop_func, cancel);
273 gp_context_set_idle_func (cancel->context->context, idle_func, cancel);
274 gp_context_set_cancel_func (cancel->context->context,
275 cancel_func, cancel);
276 gp_context_set_message_func (cancel->context->context,
277 message_func, cancel);
278
279 return (GTK_WIDGET (cancel));
280 }
281