Mercurial > pidgin
comparison gtk/gtkrequest.c @ 14191:009db0b357b5
This is a hand-crafted commit to migrate across subversion revisions
16854:16861, due to some vagaries of the way the original renames were
done. Witness that monotone can do in one revision what svn had to
spread across several.
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Sat, 16 Dec 2006 04:59:55 +0000 |
parents | |
children | 50f5099daab1 |
comparison
equal
deleted
inserted
replaced
14190:366be2ce35a7 | 14191:009db0b357b5 |
---|---|
1 /** | |
2 * @file gtkrequest.c GTK+ Request API | |
3 * @ingroup gtkui | |
4 * | |
5 * gaim | |
6 * | |
7 * Gaim is the legal property of its developers, whose names are too numerous | |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
10 * | |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
25 #include "internal.h" | |
26 #include "gtkgaim.h" | |
27 | |
28 #include "prefs.h" | |
29 #include "util.h" | |
30 | |
31 #include "gtkimhtml.h" | |
32 #include "gtkimhtmltoolbar.h" | |
33 #include "gtkrequest.h" | |
34 #include "gtkutils.h" | |
35 #include "gaimstock.h" | |
36 | |
37 #include <gdk/gdkkeysyms.h> | |
38 | |
39 static GtkWidget * create_account_field(GaimRequestField *field); | |
40 | |
41 typedef struct | |
42 { | |
43 GaimRequestType type; | |
44 | |
45 void *user_data; | |
46 GtkWidget *dialog; | |
47 | |
48 GtkWidget *ok_button; | |
49 | |
50 size_t cb_count; | |
51 GCallback *cbs; | |
52 | |
53 union | |
54 { | |
55 struct | |
56 { | |
57 GtkWidget *entry; | |
58 | |
59 gboolean multiline; | |
60 gchar *hint; | |
61 | |
62 } input; | |
63 | |
64 struct | |
65 { | |
66 GaimRequestFields *fields; | |
67 | |
68 } multifield; | |
69 | |
70 struct | |
71 { | |
72 gboolean savedialog; | |
73 gchar *name; | |
74 | |
75 } file; | |
76 | |
77 } u; | |
78 | |
79 } GaimGtkRequestData; | |
80 | |
81 static void | |
82 generic_response_start(GaimGtkRequestData *data) | |
83 { | |
84 g_return_if_fail(data != NULL); | |
85 | |
86 /* Tell the user we're doing something. */ | |
87 gaim_gtk_set_cursor(GTK_WIDGET(data->dialog), GDK_WATCH); | |
88 } | |
89 | |
90 static void | |
91 input_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) | |
92 { | |
93 const char *value; | |
94 char *multiline_value = NULL; | |
95 | |
96 generic_response_start(data); | |
97 | |
98 if (data->u.input.multiline) { | |
99 GtkTextIter start_iter, end_iter; | |
100 GtkTextBuffer *buffer = | |
101 gtk_text_view_get_buffer(GTK_TEXT_VIEW(data->u.input.entry)); | |
102 | |
103 gtk_text_buffer_get_start_iter(buffer, &start_iter); | |
104 gtk_text_buffer_get_end_iter(buffer, &end_iter); | |
105 | |
106 if ((data->u.input.hint != NULL) && (!strcmp(data->u.input.hint, "html"))) | |
107 multiline_value = gtk_imhtml_get_markup(GTK_IMHTML(data->u.input.entry)); | |
108 else | |
109 multiline_value = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, | |
110 FALSE); | |
111 | |
112 value = multiline_value; | |
113 } | |
114 else | |
115 value = gtk_entry_get_text(GTK_ENTRY(data->u.input.entry)); | |
116 | |
117 if (id < data->cb_count && data->cbs[id] != NULL) | |
118 ((GaimRequestInputCb)data->cbs[id])(data->user_data, value); | |
119 else if (data->cbs[1] != NULL) | |
120 ((GaimRequestInputCb)data->cbs[1])(data->user_data, value); | |
121 | |
122 if (data->u.input.multiline) | |
123 g_free(multiline_value); | |
124 | |
125 gaim_request_close(GAIM_REQUEST_INPUT, data); | |
126 } | |
127 | |
128 static void | |
129 action_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) | |
130 { | |
131 generic_response_start(data); | |
132 | |
133 if (id < data->cb_count && data->cbs[id] != NULL) | |
134 ((GaimRequestActionCb)data->cbs[id])(data->user_data, id); | |
135 | |
136 gaim_request_close(GAIM_REQUEST_INPUT, data); | |
137 } | |
138 | |
139 | |
140 static void | |
141 choice_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) | |
142 { | |
143 GtkWidget *radio = g_object_get_data(G_OBJECT(dialog), "radio"); | |
144 GSList *group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); | |
145 | |
146 generic_response_start(data); | |
147 | |
148 if (id < data->cb_count && data->cbs[id] != NULL) | |
149 while (group) { | |
150 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group->data))) { | |
151 ((GaimRequestChoiceCb)data->cbs[id])(data->user_data, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(group->data), "choice_id"))); | |
152 break; | |
153 } | |
154 group = group->next; | |
155 } | |
156 gaim_request_close(GAIM_REQUEST_INPUT, data); | |
157 } | |
158 | |
159 static gboolean | |
160 field_string_focus_out_cb(GtkWidget *entry, GdkEventFocus *event, | |
161 GaimRequestField *field) | |
162 { | |
163 const char *value; | |
164 | |
165 if (gaim_request_field_string_is_multiline(field)) | |
166 { | |
167 GtkTextBuffer *buffer; | |
168 GtkTextIter start_iter, end_iter; | |
169 | |
170 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)); | |
171 | |
172 gtk_text_buffer_get_start_iter(buffer, &start_iter); | |
173 gtk_text_buffer_get_end_iter(buffer, &end_iter); | |
174 | |
175 value = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE); | |
176 } | |
177 else | |
178 value = gtk_entry_get_text(GTK_ENTRY(entry)); | |
179 | |
180 gaim_request_field_string_set_value(field, | |
181 (*value == '\0' ? NULL : value)); | |
182 | |
183 return FALSE; | |
184 } | |
185 | |
186 static gboolean | |
187 field_int_focus_out_cb(GtkEntry *entry, GdkEventFocus *event, | |
188 GaimRequestField *field) | |
189 { | |
190 gaim_request_field_int_set_value(field, | |
191 atoi(gtk_entry_get_text(entry))); | |
192 | |
193 return FALSE; | |
194 } | |
195 | |
196 static void | |
197 field_bool_cb(GtkToggleButton *button, GaimRequestField *field) | |
198 { | |
199 gaim_request_field_bool_set_value(field, | |
200 gtk_toggle_button_get_active(button)); | |
201 } | |
202 | |
203 static void | |
204 field_choice_menu_cb(GtkOptionMenu *menu, GaimRequestField *field) | |
205 { | |
206 gaim_request_field_choice_set_value(field, | |
207 gtk_option_menu_get_history(menu)); | |
208 } | |
209 | |
210 static void | |
211 field_choice_option_cb(GtkRadioButton *button, GaimRequestField *field) | |
212 { | |
213 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) | |
214 gaim_request_field_choice_set_value(field, | |
215 (g_slist_length(gtk_radio_button_get_group(button)) - | |
216 g_slist_index(gtk_radio_button_get_group(button), button)) - 1); | |
217 } | |
218 | |
219 static void | |
220 field_account_cb(GObject *w, GaimAccount *account, GaimRequestField *field) | |
221 { | |
222 gaim_request_field_account_set_value(field, account); | |
223 } | |
224 | |
225 static void | |
226 multifield_ok_cb(GtkWidget *button, GaimGtkRequestData *data) | |
227 { | |
228 generic_response_start(data); | |
229 | |
230 if (!GTK_WIDGET_HAS_FOCUS(button)) | |
231 gtk_widget_grab_focus(button); | |
232 | |
233 if (data->cbs[0] != NULL) | |
234 ((GaimRequestFieldsCb)data->cbs[0])(data->user_data, | |
235 data->u.multifield.fields); | |
236 | |
237 gaim_request_close(GAIM_REQUEST_FIELDS, data); | |
238 } | |
239 | |
240 static void | |
241 multifield_cancel_cb(GtkWidget *button, GaimGtkRequestData *data) | |
242 { | |
243 generic_response_start(data); | |
244 | |
245 if (data->cbs[1] != NULL) | |
246 ((GaimRequestFieldsCb)data->cbs[1])(data->user_data, | |
247 data->u.multifield.fields); | |
248 | |
249 gaim_request_close(GAIM_REQUEST_FIELDS, data); | |
250 } | |
251 | |
252 static void | |
253 destroy_multifield_cb(GtkWidget *dialog, GdkEvent *event, | |
254 GaimGtkRequestData *data) | |
255 { | |
256 multifield_cancel_cb(NULL, data); | |
257 } | |
258 | |
259 | |
260 #define STOCK_ITEMIZE(r, l) \ | |
261 if (!strcmp((r), text)) \ | |
262 return (l); | |
263 | |
264 static const char * | |
265 text_to_stock(const char *text) | |
266 { | |
267 STOCK_ITEMIZE(_("Yes"), GTK_STOCK_YES); | |
268 STOCK_ITEMIZE(_("No"), GTK_STOCK_NO); | |
269 STOCK_ITEMIZE(_("OK"), GTK_STOCK_OK); | |
270 STOCK_ITEMIZE(_("Cancel"), GTK_STOCK_CANCEL); | |
271 STOCK_ITEMIZE(_("Apply"), GTK_STOCK_APPLY); | |
272 STOCK_ITEMIZE(_("Close"), GTK_STOCK_CLOSE); | |
273 STOCK_ITEMIZE(_("Delete"), GTK_STOCK_DELETE); | |
274 STOCK_ITEMIZE(_("Add"), GTK_STOCK_ADD); | |
275 STOCK_ITEMIZE(_("Remove"), GTK_STOCK_REMOVE); | |
276 STOCK_ITEMIZE(_("Save"), GTK_STOCK_SAVE); | |
277 STOCK_ITEMIZE(_("Alias"), GAIM_STOCK_ALIAS); | |
278 | |
279 return text; | |
280 } | |
281 | |
282 static void * | |
283 gaim_gtk_request_input(const char *title, const char *primary, | |
284 const char *secondary, const char *default_value, | |
285 gboolean multiline, gboolean masked, gchar *hint, | |
286 const char *ok_text, GCallback ok_cb, | |
287 const char *cancel_text, GCallback cancel_cb, | |
288 void *user_data) | |
289 { | |
290 GaimGtkRequestData *data; | |
291 GtkWidget *dialog; | |
292 GtkWidget *vbox; | |
293 GtkWidget *hbox; | |
294 GtkWidget *label; | |
295 GtkWidget *entry; | |
296 GtkWidget *img; | |
297 GtkWidget *toolbar; | |
298 char *label_text; | |
299 char *primary_esc, *secondary_esc; | |
300 | |
301 data = g_new0(GaimGtkRequestData, 1); | |
302 data->type = GAIM_REQUEST_INPUT; | |
303 data->user_data = user_data; | |
304 | |
305 data->cb_count = 2; | |
306 data->cbs = g_new0(GCallback, 2); | |
307 | |
308 data->cbs[0] = ok_cb; | |
309 data->cbs[1] = cancel_cb; | |
310 | |
311 /* Create the dialog. */ | |
312 dialog = gtk_dialog_new_with_buttons(title ? title : GAIM_ALERT_TITLE, | |
313 NULL, 0, | |
314 text_to_stock(cancel_text), 1, | |
315 text_to_stock(ok_text), 0, | |
316 NULL); | |
317 data->dialog = dialog; | |
318 | |
319 g_signal_connect(G_OBJECT(dialog), "response", | |
320 G_CALLBACK(input_response_cb), data); | |
321 | |
322 /* Setup the dialog */ | |
323 gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); | |
324 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); | |
325 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); | |
326 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); | |
327 gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0); | |
328 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); | |
329 | |
330 /* Setup the main horizontal box */ | |
331 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); | |
332 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); | |
333 | |
334 /* Dialog icon. */ | |
335 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | |
336 GTK_ICON_SIZE_DIALOG); | |
337 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
338 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
339 | |
340 /* Vertical box */ | |
341 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); | |
342 | |
343 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); | |
344 | |
345 /* Descriptive label */ | |
346 primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; | |
347 secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; | |
348 label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" | |
349 "%s</span>%s%s" : "%s%s%s"), | |
350 (primary ? primary_esc : ""), | |
351 ((primary && secondary) ? "\n\n" : ""), | |
352 (secondary ? secondary_esc : "")); | |
353 g_free(primary_esc); | |
354 g_free(secondary_esc); | |
355 | |
356 label = gtk_label_new(NULL); | |
357 | |
358 gtk_label_set_markup(GTK_LABEL(label), label_text); | |
359 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
360 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
361 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); | |
362 | |
363 g_free(label_text); | |
364 | |
365 /* Entry field. */ | |
366 data->u.input.multiline = multiline; | |
367 data->u.input.hint = g_strdup(hint); | |
368 | |
369 if ((data->u.input.hint != NULL) && (!strcmp(data->u.input.hint, "html"))) { | |
370 GtkWidget *frame; | |
371 | |
372 /* imhtml */ | |
373 frame = gaim_gtk_create_imhtml(TRUE, &entry, &toolbar, NULL); | |
374 gtk_widget_set_size_request(entry, 320, 130); | |
375 gtk_widget_set_name(entry, "gaim_gtkrequest_imhtml"); | |
376 if (default_value != NULL) | |
377 gtk_imhtml_append_text(GTK_IMHTML(entry), default_value, GTK_IMHTML_NO_SCROLL); | |
378 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); | |
379 gtk_widget_show(frame); | |
380 } | |
381 else { | |
382 if (multiline) { | |
383 GtkWidget *sw; | |
384 | |
385 sw = gtk_scrolled_window_new(NULL, NULL); | |
386 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
387 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); | |
388 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
389 GTK_SHADOW_IN); | |
390 | |
391 gtk_widget_set_size_request(sw, 320, 130); | |
392 | |
393 /* GtkTextView */ | |
394 entry = gtk_text_view_new(); | |
395 gtk_text_view_set_editable(GTK_TEXT_VIEW(entry), TRUE); | |
396 | |
397 if (default_value != NULL) { | |
398 GtkTextBuffer *buffer; | |
399 | |
400 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)); | |
401 gtk_text_buffer_set_text(buffer, default_value, -1); | |
402 } | |
403 | |
404 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(entry), GTK_WRAP_WORD_CHAR); | |
405 | |
406 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); | |
407 | |
408 if (gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck")) | |
409 gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(entry)); | |
410 | |
411 gtk_container_add(GTK_CONTAINER(sw), entry); | |
412 } | |
413 else { | |
414 entry = gtk_entry_new(); | |
415 | |
416 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); | |
417 | |
418 gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0); | |
419 | |
420 if (default_value != NULL) | |
421 gtk_entry_set_text(GTK_ENTRY(entry), default_value); | |
422 | |
423 if (masked) | |
424 { | |
425 gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); | |
426 gtk_entry_set_invisible_char(GTK_ENTRY(entry), GAIM_INVISIBLE_CHAR); | |
427 } | |
428 } | |
429 } | |
430 | |
431 gaim_set_accessible_label (entry, label); | |
432 data->u.input.entry = entry; | |
433 | |
434 /* Show everything. */ | |
435 gtk_widget_show_all(dialog); | |
436 | |
437 return data; | |
438 } | |
439 | |
440 static void * | |
441 gaim_gtk_request_choice(const char *title, const char *primary, | |
442 const char *secondary, unsigned int default_value, | |
443 const char *ok_text, GCallback ok_cb, | |
444 const char *cancel_text, GCallback cancel_cb, | |
445 void *user_data, va_list args) | |
446 { | |
447 GaimGtkRequestData *data; | |
448 GtkWidget *dialog; | |
449 GtkWidget *vbox, *vbox2; | |
450 GtkWidget *hbox; | |
451 GtkWidget *label; | |
452 GtkWidget *img; | |
453 GtkWidget *radio = NULL; | |
454 char *label_text; | |
455 char *radio_text; | |
456 char *primary_esc, *secondary_esc; | |
457 | |
458 data = g_new0(GaimGtkRequestData, 1); | |
459 data->type = GAIM_REQUEST_ACTION; | |
460 data->user_data = user_data; | |
461 | |
462 data->cb_count = 2; | |
463 data->cbs = g_new0(GCallback, 2); | |
464 data->cbs[0] = cancel_cb; | |
465 data->cbs[1] = ok_cb; | |
466 | |
467 /* Create the dialog. */ | |
468 data->dialog = dialog = gtk_dialog_new(); | |
469 | |
470 if (title != NULL) | |
471 gtk_window_set_title(GTK_WINDOW(dialog), title); | |
472 | |
473 | |
474 gtk_dialog_add_button(GTK_DIALOG(dialog), | |
475 text_to_stock(cancel_text), 0); | |
476 | |
477 gtk_dialog_add_button(GTK_DIALOG(dialog), | |
478 text_to_stock(ok_text), 1); | |
479 | |
480 g_signal_connect(G_OBJECT(dialog), "response", | |
481 G_CALLBACK(choice_response_cb), data); | |
482 | |
483 /* Setup the dialog */ | |
484 gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); | |
485 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); | |
486 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); | |
487 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); | |
488 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); | |
489 | |
490 /* Setup the main horizontal box */ | |
491 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); | |
492 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); | |
493 | |
494 /* Dialog icon. */ | |
495 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | |
496 GTK_ICON_SIZE_DIALOG); | |
497 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
498 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
499 | |
500 /* Vertical box */ | |
501 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); | |
502 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); | |
503 | |
504 /* Descriptive label */ | |
505 primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; | |
506 secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; | |
507 label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" | |
508 "%s</span>%s%s" : "%s%s%s"), | |
509 (primary ? primary_esc : ""), | |
510 ((primary && secondary) ? "\n\n" : ""), | |
511 (secondary ? secondary_esc : "")); | |
512 g_free(primary_esc); | |
513 g_free(secondary_esc); | |
514 | |
515 label = gtk_label_new(NULL); | |
516 | |
517 gtk_label_set_markup(GTK_LABEL(label), label_text); | |
518 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
519 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
520 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); | |
521 | |
522 g_free(label_text); | |
523 | |
524 vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
525 gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, 0); | |
526 while ((radio_text = va_arg(args, char*))) { | |
527 int resp = va_arg(args, int); | |
528 radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), radio_text); | |
529 gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0); | |
530 g_object_set_data(G_OBJECT(radio), "choice_id", GINT_TO_POINTER(resp)); | |
531 if (resp == default_value) | |
532 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); | |
533 } | |
534 | |
535 g_object_set_data(G_OBJECT(dialog), "radio", radio); | |
536 | |
537 /* Show everything. */ | |
538 gtk_widget_show_all(dialog); | |
539 | |
540 return data; | |
541 } | |
542 | |
543 static void * | |
544 gaim_gtk_request_action(const char *title, const char *primary, | |
545 const char *secondary, unsigned int default_action, | |
546 void *user_data, size_t action_count, va_list actions) | |
547 { | |
548 GaimGtkRequestData *data; | |
549 GtkWidget *dialog; | |
550 GtkWidget *vbox; | |
551 GtkWidget *hbox; | |
552 GtkWidget *label; | |
553 GtkWidget *img; | |
554 void **buttons; | |
555 char *label_text; | |
556 char *primary_esc, *secondary_esc; | |
557 int i; | |
558 | |
559 data = g_new0(GaimGtkRequestData, 1); | |
560 data->type = GAIM_REQUEST_ACTION; | |
561 data->user_data = user_data; | |
562 | |
563 data->cb_count = action_count; | |
564 data->cbs = g_new0(GCallback, action_count); | |
565 | |
566 /* Reverse the buttons */ | |
567 buttons = g_new0(void *, action_count * 2); | |
568 | |
569 for (i = 0; i < action_count * 2; i += 2) { | |
570 buttons[(action_count * 2) - i - 2] = va_arg(actions, char *); | |
571 buttons[(action_count * 2) - i - 1] = va_arg(actions, GCallback); | |
572 } | |
573 | |
574 /* Create the dialog. */ | |
575 data->dialog = dialog = gtk_dialog_new(); | |
576 | |
577 if (title != NULL) | |
578 gtk_window_set_title(GTK_WINDOW(dialog), title); | |
579 | |
580 for (i = 0; i < action_count; i++) { | |
581 gtk_dialog_add_button(GTK_DIALOG(dialog), | |
582 text_to_stock(buttons[2 * i]), i); | |
583 | |
584 data->cbs[i] = buttons[2 * i + 1]; | |
585 } | |
586 | |
587 g_free(buttons); | |
588 | |
589 g_signal_connect(G_OBJECT(dialog), "response", | |
590 G_CALLBACK(action_response_cb), data); | |
591 | |
592 /* Setup the dialog */ | |
593 gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); | |
594 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); | |
595 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); | |
596 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); | |
597 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); | |
598 | |
599 /* Setup the main horizontal box */ | |
600 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); | |
601 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); | |
602 | |
603 /* Dialog icon. */ | |
604 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | |
605 GTK_ICON_SIZE_DIALOG); | |
606 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
607 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
608 | |
609 /* Vertical box */ | |
610 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); | |
611 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); | |
612 | |
613 /* Descriptive label */ | |
614 primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; | |
615 secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; | |
616 label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" | |
617 "%s</span>%s%s" : "%s%s%s"), | |
618 (primary ? primary_esc : ""), | |
619 ((primary && secondary) ? "\n\n" : ""), | |
620 (secondary ? secondary_esc : "")); | |
621 g_free(primary_esc); | |
622 g_free(secondary_esc); | |
623 | |
624 label = gtk_label_new(NULL); | |
625 | |
626 gtk_label_set_markup(GTK_LABEL(label), label_text); | |
627 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
628 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
629 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); | |
630 | |
631 g_free(label_text); | |
632 | |
633 | |
634 if (default_action == GAIM_DEFAULT_ACTION_NONE) { | |
635 GTK_WIDGET_SET_FLAGS(img, GTK_CAN_DEFAULT); | |
636 GTK_WIDGET_SET_FLAGS(img, GTK_CAN_FOCUS); | |
637 gtk_widget_grab_focus(img); | |
638 gtk_widget_grab_default(img); | |
639 } else | |
640 gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_action); | |
641 | |
642 /* Show everything. */ | |
643 gtk_widget_show_all(dialog); | |
644 | |
645 return data; | |
646 } | |
647 | |
648 static void | |
649 req_entry_field_changed_cb(GtkWidget *entry, GaimRequestField *field) | |
650 { | |
651 GaimGtkRequestData *req_data; | |
652 const char *text = gtk_entry_get_text(GTK_ENTRY(entry)); | |
653 | |
654 gaim_request_field_string_set_value(field, (*text == '\0' ? NULL : text)); | |
655 | |
656 req_data = (GaimGtkRequestData *)field->group->fields_list->ui_data; | |
657 | |
658 gtk_widget_set_sensitive(req_data->ok_button, | |
659 gaim_request_fields_all_required_filled(field->group->fields_list)); | |
660 } | |
661 | |
662 static void | |
663 setup_entry_field(GtkWidget *entry, GaimRequestField *field) | |
664 { | |
665 const char *type_hint; | |
666 | |
667 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); | |
668 | |
669 if (gaim_request_field_is_required(field)) | |
670 { | |
671 g_signal_connect(G_OBJECT(entry), "changed", | |
672 G_CALLBACK(req_entry_field_changed_cb), field); | |
673 } | |
674 | |
675 if ((type_hint = gaim_request_field_get_type_hint(field)) != NULL) | |
676 { | |
677 if (gaim_str_has_prefix(type_hint, "screenname")) | |
678 { | |
679 GtkWidget *optmenu = NULL; | |
680 GList *fields = field->group->fields; | |
681 while (fields) | |
682 { | |
683 GaimRequestField *fld = fields->data; | |
684 fields = fields->next; | |
685 | |
686 if (gaim_request_field_get_type(fld) == GAIM_REQUEST_FIELD_ACCOUNT) | |
687 { | |
688 const char *type_hint = gaim_request_field_get_type_hint(fld); | |
689 if (type_hint != NULL && strcmp(type_hint, "account") == 0) | |
690 { | |
691 if (fld->ui_data == NULL) | |
692 fld->ui_data = create_account_field(fld); | |
693 optmenu = GTK_WIDGET(fld->ui_data); | |
694 break; | |
695 } | |
696 } | |
697 } | |
698 gaim_gtk_setup_screenname_autocomplete(entry, optmenu, !strcmp(type_hint, "screenname-all")); | |
699 } | |
700 } | |
701 } | |
702 | |
703 static GtkWidget * | |
704 create_string_field(GaimRequestField *field) | |
705 { | |
706 const char *value; | |
707 GtkWidget *widget; | |
708 | |
709 value = gaim_request_field_string_get_default_value(field); | |
710 | |
711 if (gaim_request_field_string_is_multiline(field)) | |
712 { | |
713 GtkWidget *textview; | |
714 | |
715 widget = gtk_scrolled_window_new(NULL, NULL); | |
716 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(widget), | |
717 GTK_SHADOW_IN); | |
718 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), | |
719 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); | |
720 | |
721 textview = gtk_text_view_new(); | |
722 gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), | |
723 TRUE); | |
724 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), | |
725 GTK_WRAP_WORD_CHAR); | |
726 | |
727 if (gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck")) | |
728 gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(textview)); | |
729 | |
730 gtk_container_add(GTK_CONTAINER(widget), textview); | |
731 gtk_widget_show(textview); | |
732 | |
733 gtk_widget_set_size_request(widget, -1, 75); | |
734 | |
735 if (value != NULL) | |
736 { | |
737 GtkTextBuffer *buffer; | |
738 | |
739 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); | |
740 | |
741 gtk_text_buffer_set_text(buffer, value, -1); | |
742 } | |
743 | |
744 gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), | |
745 gaim_request_field_string_is_editable(field)); | |
746 | |
747 g_signal_connect(G_OBJECT(textview), "focus-out-event", | |
748 G_CALLBACK(field_string_focus_out_cb), field); | |
749 } | |
750 else | |
751 { | |
752 widget = gtk_entry_new(); | |
753 | |
754 setup_entry_field(widget, field); | |
755 | |
756 if (value != NULL) | |
757 gtk_entry_set_text(GTK_ENTRY(widget), value); | |
758 | |
759 if (gaim_request_field_string_is_masked(field)) | |
760 { | |
761 gtk_entry_set_visibility(GTK_ENTRY(widget), FALSE); | |
762 gtk_entry_set_invisible_char(GTK_ENTRY(widget), GAIM_INVISIBLE_CHAR); | |
763 } | |
764 | |
765 gtk_editable_set_editable(GTK_EDITABLE(widget), | |
766 gaim_request_field_string_is_editable(field)); | |
767 | |
768 g_signal_connect(G_OBJECT(widget), "focus-out-event", | |
769 G_CALLBACK(field_string_focus_out_cb), field); | |
770 } | |
771 | |
772 return widget; | |
773 } | |
774 | |
775 static GtkWidget * | |
776 create_int_field(GaimRequestField *field) | |
777 { | |
778 int value; | |
779 GtkWidget *widget; | |
780 | |
781 widget = gtk_entry_new(); | |
782 | |
783 setup_entry_field(widget, field); | |
784 | |
785 value = gaim_request_field_int_get_default_value(field); | |
786 | |
787 if (value != 0) | |
788 { | |
789 char buf[32]; | |
790 | |
791 g_snprintf(buf, sizeof(buf), "%d", value); | |
792 | |
793 gtk_entry_set_text(GTK_ENTRY(widget), buf); | |
794 } | |
795 | |
796 g_signal_connect(G_OBJECT(widget), "focus-out-event", | |
797 G_CALLBACK(field_int_focus_out_cb), field); | |
798 | |
799 return widget; | |
800 } | |
801 | |
802 static GtkWidget * | |
803 create_bool_field(GaimRequestField *field) | |
804 { | |
805 GtkWidget *widget; | |
806 | |
807 widget = gtk_check_button_new_with_label( | |
808 gaim_request_field_get_label(field)); | |
809 | |
810 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), | |
811 gaim_request_field_bool_get_default_value(field)); | |
812 | |
813 g_signal_connect(G_OBJECT(widget), "toggled", | |
814 G_CALLBACK(field_bool_cb), field); | |
815 | |
816 return widget; | |
817 } | |
818 | |
819 static GtkWidget * | |
820 create_choice_field(GaimRequestField *field) | |
821 { | |
822 GtkWidget *widget; | |
823 GList *labels; | |
824 GList *l; | |
825 | |
826 labels = gaim_request_field_choice_get_labels(field); | |
827 | |
828 if (g_list_length(labels) > 5) | |
829 { | |
830 GtkWidget *menu; | |
831 GtkWidget *item; | |
832 | |
833 widget = gtk_option_menu_new(); | |
834 | |
835 menu = gtk_menu_new(); | |
836 | |
837 for (l = labels; l != NULL; l = l->next) | |
838 { | |
839 const char *text = l->data; | |
840 | |
841 item = gtk_menu_item_new_with_label(text); | |
842 gtk_widget_show(item); | |
843 | |
844 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
845 } | |
846 | |
847 gtk_widget_show(menu); | |
848 gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), menu); | |
849 gtk_option_menu_set_history(GTK_OPTION_MENU(widget), | |
850 gaim_request_field_choice_get_default_value(field)); | |
851 | |
852 g_signal_connect(G_OBJECT(widget), "changed", | |
853 G_CALLBACK(field_choice_menu_cb), field); | |
854 } | |
855 else | |
856 { | |
857 GtkWidget *box; | |
858 GtkWidget *first_radio = NULL; | |
859 GtkWidget *radio; | |
860 gint i; | |
861 | |
862 if (g_list_length(labels) == 2) | |
863 box = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
864 else | |
865 box = gtk_vbox_new(FALSE, 0); | |
866 | |
867 widget = box; | |
868 | |
869 for (l = labels, i = 0; l != NULL; l = l->next, i++) | |
870 { | |
871 const char *text = l->data; | |
872 | |
873 radio = gtk_radio_button_new_with_label_from_widget( | |
874 GTK_RADIO_BUTTON(first_radio), text); | |
875 | |
876 if (first_radio == NULL) | |
877 first_radio = radio; | |
878 | |
879 if (i == gaim_request_field_choice_get_default_value(field)) | |
880 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); | |
881 | |
882 gtk_box_pack_start(GTK_BOX(box), radio, TRUE, TRUE, 0); | |
883 gtk_widget_show(radio); | |
884 | |
885 g_signal_connect(G_OBJECT(radio), "toggled", | |
886 G_CALLBACK(field_choice_option_cb), field); | |
887 } | |
888 } | |
889 | |
890 return widget; | |
891 } | |
892 | |
893 static GtkWidget * | |
894 create_image_field(GaimRequestField *field) | |
895 { | |
896 GtkWidget *widget; | |
897 GdkPixbuf *buf, *scale; | |
898 GdkPixbufLoader *loader; | |
899 | |
900 loader = gdk_pixbuf_loader_new(); | |
901 gdk_pixbuf_loader_write(loader, | |
902 (const guchar *)gaim_request_field_image_get_buffer(field), | |
903 gaim_request_field_image_get_size(field), | |
904 NULL); | |
905 gdk_pixbuf_loader_close(loader, NULL); | |
906 buf = gdk_pixbuf_loader_get_pixbuf(loader); | |
907 | |
908 scale = gdk_pixbuf_scale_simple(buf, | |
909 gaim_request_field_image_get_scale_x(field) * gdk_pixbuf_get_width(buf), | |
910 gaim_request_field_image_get_scale_y(field) * gdk_pixbuf_get_height(buf), | |
911 GDK_INTERP_BILINEAR); | |
912 widget = gtk_image_new_from_pixbuf(scale); | |
913 g_object_unref(G_OBJECT(buf)); | |
914 g_object_unref(G_OBJECT(scale)); | |
915 | |
916 return widget; | |
917 } | |
918 | |
919 static GtkWidget * | |
920 create_account_field(GaimRequestField *field) | |
921 { | |
922 GtkWidget *widget; | |
923 | |
924 widget = gaim_gtk_account_option_menu_new( | |
925 gaim_request_field_account_get_default_value(field), | |
926 gaim_request_field_account_get_show_all(field), | |
927 G_CALLBACK(field_account_cb), | |
928 gaim_request_field_account_get_filter(field), | |
929 field); | |
930 | |
931 return widget; | |
932 } | |
933 | |
934 static void | |
935 select_field_list_item(GtkTreeModel *model, GtkTreePath *path, | |
936 GtkTreeIter *iter, gpointer data) | |
937 { | |
938 GaimRequestField *field = (GaimRequestField *)data; | |
939 char *text; | |
940 | |
941 gtk_tree_model_get(model, iter, 1, &text, -1); | |
942 | |
943 gaim_request_field_list_add_selected(field, text); | |
944 g_free(text); | |
945 } | |
946 | |
947 static void | |
948 list_field_select_changed_cb(GtkTreeSelection *sel, GaimRequestField *field) | |
949 { | |
950 gaim_request_field_list_clear_selected(field); | |
951 | |
952 gtk_tree_selection_selected_foreach(sel, select_field_list_item, field); | |
953 } | |
954 | |
955 static GtkWidget * | |
956 create_list_field(GaimRequestField *field) | |
957 { | |
958 GtkWidget *sw; | |
959 GtkWidget *treeview; | |
960 GtkListStore *store; | |
961 GtkCellRenderer *renderer; | |
962 GtkTreeSelection *sel; | |
963 GtkTreeViewColumn *column; | |
964 GtkTreeIter iter; | |
965 const GList *l; | |
966 | |
967 /* Create the scrolled window */ | |
968 sw = gtk_scrolled_window_new(NULL, NULL); | |
969 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
970 GTK_POLICY_AUTOMATIC, | |
971 GTK_POLICY_AUTOMATIC); | |
972 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
973 GTK_SHADOW_IN); | |
974 gtk_widget_show(sw); | |
975 | |
976 /* Create the list store */ | |
977 store = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING); | |
978 | |
979 /* Create the tree view */ | |
980 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
981 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); | |
982 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); | |
983 | |
984 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); | |
985 | |
986 if (gaim_request_field_list_get_multi_select(field)) | |
987 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE); | |
988 | |
989 g_signal_connect(G_OBJECT(sel), "changed", | |
990 G_CALLBACK(list_field_select_changed_cb), field); | |
991 | |
992 column = gtk_tree_view_column_new(); | |
993 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1); | |
994 | |
995 renderer = gtk_cell_renderer_text_new(); | |
996 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
997 gtk_tree_view_column_add_attribute(column, renderer, "text", 1); | |
998 | |
999 for (l = gaim_request_field_list_get_items(field); l != NULL; l = l->next) | |
1000 { | |
1001 const char *text = (const char *)l->data; | |
1002 | |
1003 gtk_list_store_append(store, &iter); | |
1004 | |
1005 gtk_list_store_set(store, &iter, | |
1006 0, gaim_request_field_list_get_data(field, text), | |
1007 1, text, | |
1008 -1); | |
1009 | |
1010 if (gaim_request_field_list_is_selected(field, text)) | |
1011 gtk_tree_selection_select_iter(sel, &iter); | |
1012 } | |
1013 | |
1014 gtk_container_add(GTK_CONTAINER(sw), treeview); | |
1015 gtk_widget_show(treeview); | |
1016 | |
1017 return sw; | |
1018 } | |
1019 | |
1020 static void * | |
1021 gaim_gtk_request_fields(const char *title, const char *primary, | |
1022 const char *secondary, GaimRequestFields *fields, | |
1023 const char *ok_text, GCallback ok_cb, | |
1024 const char *cancel_text, GCallback cancel_cb, | |
1025 void *user_data) | |
1026 { | |
1027 GaimGtkRequestData *data; | |
1028 GtkWidget *win; | |
1029 GtkWidget *vbox; | |
1030 GtkWidget *vbox2; | |
1031 GtkWidget *hbox; | |
1032 GtkWidget *bbox; | |
1033 GtkWidget *frame; | |
1034 GtkWidget *label; | |
1035 GtkWidget *table; | |
1036 GtkWidget *button; | |
1037 GtkWidget *img; | |
1038 GtkWidget *sw; | |
1039 GtkSizeGroup *sg; | |
1040 GList *gl, *fl; | |
1041 GaimRequestFieldGroup *group; | |
1042 GaimRequestField *field; | |
1043 char *label_text; | |
1044 char *primary_esc, *secondary_esc; | |
1045 int total_fields = 0; | |
1046 | |
1047 data = g_new0(GaimGtkRequestData, 1); | |
1048 data->type = GAIM_REQUEST_FIELDS; | |
1049 data->user_data = user_data; | |
1050 data->u.multifield.fields = fields; | |
1051 | |
1052 fields->ui_data = data; | |
1053 | |
1054 data->cb_count = 2; | |
1055 data->cbs = g_new0(GCallback, 2); | |
1056 | |
1057 data->cbs[0] = ok_cb; | |
1058 data->cbs[1] = cancel_cb; | |
1059 | |
1060 data->dialog = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
1061 | |
1062 if (title != NULL) | |
1063 gtk_window_set_title(GTK_WINDOW(win), title); | |
1064 | |
1065 gtk_window_set_role(GTK_WINDOW(win), "multifield"); | |
1066 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER); | |
1067 gtk_window_set_resizable(GTK_WINDOW(win), FALSE); | |
1068 | |
1069 g_signal_connect(G_OBJECT(win), "delete_event", | |
1070 G_CALLBACK(destroy_multifield_cb), data); | |
1071 | |
1072 /* Setup the main horizontal box */ | |
1073 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); | |
1074 gtk_container_add(GTK_CONTAINER(win), hbox); | |
1075 gtk_widget_show(hbox); | |
1076 | |
1077 /* Dialog icon. */ | |
1078 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | |
1079 GTK_ICON_SIZE_DIALOG); | |
1080 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
1081 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
1082 gtk_widget_show(img); | |
1083 | |
1084 /* Setup the vbox */ | |
1085 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); | |
1086 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); | |
1087 gtk_widget_show(vbox); | |
1088 | |
1089 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | |
1090 | |
1091 if(primary) { | |
1092 primary_esc = g_markup_escape_text(primary, -1); | |
1093 label_text = g_strdup_printf( | |
1094 "<span weight=\"bold\" size=\"larger\">%s</span>", primary_esc); | |
1095 g_free(primary_esc); | |
1096 label = gtk_label_new(NULL); | |
1097 | |
1098 gtk_label_set_markup(GTK_LABEL(label), label_text); | |
1099 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
1100 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
1101 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); | |
1102 gtk_widget_show(label); | |
1103 g_free(label_text); | |
1104 } | |
1105 | |
1106 for (gl = gaim_request_fields_get_groups(fields); gl != NULL; | |
1107 gl = gl->next) | |
1108 total_fields += g_list_length(gaim_request_field_group_get_fields(gl->data)); | |
1109 | |
1110 if(total_fields > 9) { | |
1111 sw = gtk_scrolled_window_new(NULL, NULL); | |
1112 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
1113 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); | |
1114 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
1115 GTK_SHADOW_NONE); | |
1116 gtk_widget_set_size_request(sw, -1, 200); | |
1117 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); | |
1118 gtk_widget_show(sw); | |
1119 | |
1120 vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); | |
1121 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), vbox2); | |
1122 gtk_widget_show(vbox2); | |
1123 } else { | |
1124 vbox2 = vbox; | |
1125 } | |
1126 | |
1127 if (secondary) { | |
1128 secondary_esc = g_markup_escape_text(secondary, -1); | |
1129 label = gtk_label_new(NULL); | |
1130 | |
1131 gtk_label_set_markup(GTK_LABEL(label), secondary_esc); | |
1132 g_free(secondary_esc); | |
1133 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
1134 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
1135 gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, TRUE, 0); | |
1136 gtk_widget_show(label); | |
1137 } | |
1138 | |
1139 for (gl = gaim_request_fields_get_groups(fields); | |
1140 gl != NULL; | |
1141 gl = gl->next) | |
1142 { | |
1143 GList *field_list; | |
1144 size_t field_count = 0; | |
1145 size_t cols = 1; | |
1146 size_t rows; | |
1147 size_t col_num; | |
1148 size_t row_num = 0; | |
1149 | |
1150 group = gl->data; | |
1151 field_list = gaim_request_field_group_get_fields(group); | |
1152 | |
1153 if (gaim_request_field_group_get_title(group) != NULL) | |
1154 { | |
1155 frame = gaim_gtk_make_frame(vbox2, | |
1156 gaim_request_field_group_get_title(group)); | |
1157 } | |
1158 else | |
1159 frame = vbox2; | |
1160 | |
1161 field_count = g_list_length(field_list); | |
1162 /* | |
1163 if (field_count > 9) | |
1164 { | |
1165 rows = field_count / 2; | |
1166 cols++; | |
1167 } | |
1168 else | |
1169 */ | |
1170 rows = field_count; | |
1171 | |
1172 col_num = 0; | |
1173 | |
1174 for (fl = field_list; fl != NULL; fl = fl->next) | |
1175 { | |
1176 GaimRequestFieldType type; | |
1177 | |
1178 field = (GaimRequestField *)fl->data; | |
1179 | |
1180 type = gaim_request_field_get_type(field); | |
1181 | |
1182 if (type == GAIM_REQUEST_FIELD_LABEL) | |
1183 { | |
1184 if (col_num > 0) | |
1185 rows++; | |
1186 | |
1187 rows++; | |
1188 } | |
1189 else if ((type == GAIM_REQUEST_FIELD_LIST) || | |
1190 (type == GAIM_REQUEST_FIELD_STRING && | |
1191 gaim_request_field_string_is_multiline(field))) | |
1192 { | |
1193 if (col_num > 0) | |
1194 rows++; | |
1195 | |
1196 rows += 2; | |
1197 } | |
1198 | |
1199 col_num++; | |
1200 | |
1201 if (col_num >= cols) | |
1202 col_num = 0; | |
1203 } | |
1204 | |
1205 table = gtk_table_new(rows, 2 * cols, FALSE); | |
1206 gtk_table_set_row_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE); | |
1207 gtk_table_set_col_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE); | |
1208 | |
1209 gtk_container_add(GTK_CONTAINER(frame), table); | |
1210 gtk_widget_show(table); | |
1211 | |
1212 for (row_num = 0, fl = field_list; | |
1213 row_num < rows && fl != NULL; | |
1214 row_num++) | |
1215 { | |
1216 for (col_num = 0; | |
1217 col_num < cols && fl != NULL; | |
1218 col_num++, fl = fl->next) | |
1219 { | |
1220 size_t col_offset = col_num * 2; | |
1221 GaimRequestFieldType type; | |
1222 GtkWidget *widget = NULL; | |
1223 | |
1224 label = NULL; | |
1225 field = fl->data; | |
1226 | |
1227 if (!gaim_request_field_is_visible(field)) { | |
1228 col_num--; | |
1229 continue; | |
1230 } | |
1231 | |
1232 type = gaim_request_field_get_type(field); | |
1233 | |
1234 if (type != GAIM_REQUEST_FIELD_BOOLEAN && | |
1235 gaim_request_field_get_label(field)) | |
1236 { | |
1237 char *text; | |
1238 | |
1239 text = g_strdup_printf("%s:", | |
1240 gaim_request_field_get_label(field)); | |
1241 | |
1242 label = gtk_label_new(NULL); | |
1243 gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), text); | |
1244 g_free(text); | |
1245 | |
1246 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
1247 | |
1248 gtk_size_group_add_widget(sg, label); | |
1249 | |
1250 if (type == GAIM_REQUEST_FIELD_LABEL || | |
1251 type == GAIM_REQUEST_FIELD_LIST || | |
1252 (type == GAIM_REQUEST_FIELD_STRING && | |
1253 gaim_request_field_string_is_multiline(field))) | |
1254 { | |
1255 if(col_num > 0) | |
1256 row_num++; | |
1257 | |
1258 gtk_table_attach_defaults(GTK_TABLE(table), label, | |
1259 0, 2 * cols, | |
1260 row_num, row_num + 1); | |
1261 | |
1262 row_num++; | |
1263 col_num=cols; | |
1264 } | |
1265 else | |
1266 { | |
1267 gtk_table_attach_defaults(GTK_TABLE(table), label, | |
1268 col_offset, col_offset + 1, | |
1269 row_num, row_num + 1); | |
1270 } | |
1271 | |
1272 gtk_widget_show(label); | |
1273 } | |
1274 | |
1275 if (field->ui_data != NULL) | |
1276 widget = GTK_WIDGET(field->ui_data); | |
1277 else if (type == GAIM_REQUEST_FIELD_STRING) | |
1278 widget = create_string_field(field); | |
1279 else if (type == GAIM_REQUEST_FIELD_INTEGER) | |
1280 widget = create_int_field(field); | |
1281 else if (type == GAIM_REQUEST_FIELD_BOOLEAN) | |
1282 widget = create_bool_field(field); | |
1283 else if (type == GAIM_REQUEST_FIELD_CHOICE) | |
1284 widget = create_choice_field(field); | |
1285 else if (type == GAIM_REQUEST_FIELD_LIST) | |
1286 widget = create_list_field(field); | |
1287 else if (type == GAIM_REQUEST_FIELD_IMAGE) | |
1288 widget = create_image_field(field); | |
1289 else if (type == GAIM_REQUEST_FIELD_ACCOUNT) | |
1290 widget = create_account_field(field); | |
1291 else | |
1292 continue; | |
1293 | |
1294 if (label) | |
1295 gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget); | |
1296 | |
1297 if (type == GAIM_REQUEST_FIELD_STRING && | |
1298 gaim_request_field_string_is_multiline(field)) | |
1299 { | |
1300 gtk_table_attach(GTK_TABLE(table), widget, | |
1301 0, 2 * cols, | |
1302 row_num, row_num + 1, | |
1303 GTK_FILL | GTK_EXPAND, | |
1304 GTK_FILL | GTK_EXPAND, | |
1305 5, 0); | |
1306 } | |
1307 else if (type == GAIM_REQUEST_FIELD_LIST) | |
1308 { | |
1309 gtk_table_attach(GTK_TABLE(table), widget, | |
1310 0, 2 * cols, | |
1311 row_num, row_num + 1, | |
1312 GTK_FILL | GTK_EXPAND, | |
1313 GTK_FILL | GTK_EXPAND, | |
1314 5, 0); | |
1315 } | |
1316 else if (type == GAIM_REQUEST_FIELD_BOOLEAN) | |
1317 { | |
1318 gtk_table_attach(GTK_TABLE(table), widget, | |
1319 col_offset, col_offset + 1, | |
1320 row_num, row_num + 1, | |
1321 GTK_FILL | GTK_EXPAND, | |
1322 GTK_FILL | GTK_EXPAND, | |
1323 5, 0); | |
1324 } | |
1325 else | |
1326 { | |
1327 gtk_table_attach(GTK_TABLE(table), widget, | |
1328 1, 2 * cols, | |
1329 row_num, row_num + 1, | |
1330 GTK_FILL | GTK_EXPAND, | |
1331 GTK_FILL | GTK_EXPAND, | |
1332 5, 0); | |
1333 } | |
1334 | |
1335 gtk_widget_show(widget); | |
1336 | |
1337 field->ui_data = widget; | |
1338 } | |
1339 } | |
1340 } | |
1341 | |
1342 g_object_unref(sg); | |
1343 | |
1344 /* Button box. */ | |
1345 bbox = gtk_hbutton_box_new(); | |
1346 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE); | |
1347 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); | |
1348 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); | |
1349 gtk_widget_show(bbox); | |
1350 | |
1351 /* Cancel button */ | |
1352 button = gtk_button_new_from_stock(text_to_stock(cancel_text)); | |
1353 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
1354 gtk_widget_show(button); | |
1355 | |
1356 g_signal_connect(G_OBJECT(button), "clicked", | |
1357 G_CALLBACK(multifield_cancel_cb), data); | |
1358 | |
1359 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); | |
1360 | |
1361 /* OK button */ | |
1362 button = gtk_button_new_from_stock(text_to_stock(ok_text)); | |
1363 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
1364 gtk_widget_show(button); | |
1365 | |
1366 data->ok_button = button; | |
1367 | |
1368 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); | |
1369 gtk_window_set_default(GTK_WINDOW(win), button); | |
1370 | |
1371 g_signal_connect(G_OBJECT(button), "clicked", | |
1372 G_CALLBACK(multifield_ok_cb), data); | |
1373 | |
1374 if (!gaim_request_fields_all_required_filled(fields)) | |
1375 gtk_widget_set_sensitive(button, FALSE); | |
1376 | |
1377 gtk_widget_show(win); | |
1378 | |
1379 return data; | |
1380 } | |
1381 | |
1382 static void | |
1383 file_yes_no_cb(GaimGtkRequestData *data, gint id) | |
1384 { | |
1385 /* Only call the callback if yes was selected, otherwise the request | |
1386 * (eg. file transfer) will be cancelled, then when a new filename is chosen | |
1387 * things go BOOM */ | |
1388 if (id == 1) { | |
1389 if (data->cbs[1] != NULL) | |
1390 ((GaimRequestFileCb)data->cbs[1])(data->user_data, data->u.file.name); | |
1391 gaim_request_close(data->type, data); | |
1392 } else { | |
1393 gaim_gtk_clear_cursor(GTK_WIDGET(data->dialog)); | |
1394 } | |
1395 } | |
1396 | |
1397 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ | |
1398 static void | |
1399 file_ok_check_if_exists_cb(GtkWidget *widget, gint response, GaimGtkRequestData *data) | |
1400 { | |
1401 gchar *current_folder; | |
1402 | |
1403 generic_response_start(data); | |
1404 | |
1405 if (response != GTK_RESPONSE_ACCEPT) { | |
1406 if (data->cbs[0] != NULL) | |
1407 ((GaimRequestFileCb)data->cbs[0])(data->user_data, NULL); | |
1408 gaim_request_close(data->type, data); | |
1409 return; | |
1410 } | |
1411 | |
1412 data->u.file.name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(data->dialog)); | |
1413 current_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(data->dialog)); | |
1414 if (current_folder != NULL) { | |
1415 if (data->u.file.savedialog) { | |
1416 gaim_prefs_set_string("/gaim/gtk/filelocations/last_save_folder", current_folder); | |
1417 } else { | |
1418 gaim_prefs_set_string("/gaim/gtk/filelocations/last_open_folder", current_folder); | |
1419 } | |
1420 g_free(current_folder); | |
1421 } | |
1422 | |
1423 #else /* FILECHOOSER */ | |
1424 | |
1425 static void | |
1426 file_ok_check_if_exists_cb(GtkWidget *button, GaimGtkRequestData *data) | |
1427 { | |
1428 const gchar *name; | |
1429 gchar *current_folder; | |
1430 | |
1431 generic_response_start(data); | |
1432 | |
1433 name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(data->dialog)); | |
1434 | |
1435 /* If name is a directory then change directories */ | |
1436 if (data->type == GAIM_REQUEST_FILE) { | |
1437 if (gaim_gtk_check_if_dir(name, GTK_FILE_SELECTION(data->dialog))) | |
1438 return; | |
1439 } | |
1440 | |
1441 current_folder = g_path_get_dirname(name); | |
1442 | |
1443 g_free(data->u.file.name); | |
1444 if (data->type == GAIM_REQUEST_FILE) | |
1445 data->u.file.name = g_strdup(name); | |
1446 else | |
1447 { | |
1448 if (g_file_test(name, G_FILE_TEST_IS_DIR)) | |
1449 data->u.file.name = g_strdup(name); | |
1450 else | |
1451 data->u.file.name = g_strdup(current_folder); | |
1452 } | |
1453 | |
1454 if (current_folder != NULL) { | |
1455 if (data->u.file.savedialog) { | |
1456 gaim_prefs_set_string("/gaim/gtk/filelocations/last_save_folder", current_folder); | |
1457 } else { | |
1458 gaim_prefs_set_string("/gaim/gtk/filelocations/last_open_folder", current_folder); | |
1459 } | |
1460 g_free(current_folder); | |
1461 } | |
1462 | |
1463 #endif /* FILECHOOSER */ | |
1464 | |
1465 if ((data->u.file.savedialog == TRUE) && | |
1466 (g_file_test(data->u.file.name, G_FILE_TEST_EXISTS))) { | |
1467 gaim_request_action(data, NULL, _("That file already exists"), | |
1468 _("Would you like to overwrite it?"), 0, data, 2, | |
1469 _("Overwrite"), G_CALLBACK(file_yes_no_cb), | |
1470 _("Choose New Name"), G_CALLBACK(file_yes_no_cb)); | |
1471 } else | |
1472 file_yes_no_cb(data, 1); | |
1473 } | |
1474 | |
1475 #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ | |
1476 static void | |
1477 file_cancel_cb(GaimGtkRequestData *data) | |
1478 { | |
1479 generic_response_start(data); | |
1480 | |
1481 if (data->cbs[0] != NULL) | |
1482 ((GaimRequestFileCb)data->cbs[0])(data->user_data, NULL); | |
1483 | |
1484 gaim_request_close(data->type, data); | |
1485 } | |
1486 #endif /* FILECHOOSER */ | |
1487 | |
1488 static void * | |
1489 gaim_gtk_request_file(const char *title, const char *filename, | |
1490 gboolean savedialog, | |
1491 GCallback ok_cb, GCallback cancel_cb, | |
1492 void *user_data) | |
1493 { | |
1494 GaimGtkRequestData *data; | |
1495 GtkWidget *filesel; | |
1496 const gchar *current_folder; | |
1497 #if GTK_CHECK_VERSION(2,4,0) | |
1498 gboolean folder_set = FALSE; | |
1499 #endif | |
1500 | |
1501 data = g_new0(GaimGtkRequestData, 1); | |
1502 data->type = GAIM_REQUEST_FILE; | |
1503 data->user_data = user_data; | |
1504 data->cb_count = 2; | |
1505 data->cbs = g_new0(GCallback, 2); | |
1506 data->cbs[0] = cancel_cb; | |
1507 data->cbs[1] = ok_cb; | |
1508 data->u.file.savedialog = savedialog; | |
1509 | |
1510 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ | |
1511 filesel = gtk_file_chooser_dialog_new( | |
1512 title ? title : (savedialog ? _("Save File...") | |
1513 : _("Open File...")), | |
1514 NULL, | |
1515 savedialog ? GTK_FILE_CHOOSER_ACTION_SAVE | |
1516 : GTK_FILE_CHOOSER_ACTION_OPEN, | |
1517 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
1518 savedialog ? GTK_STOCK_SAVE | |
1519 : GTK_STOCK_OPEN, | |
1520 GTK_RESPONSE_ACCEPT, | |
1521 NULL); | |
1522 gtk_dialog_set_default_response(GTK_DIALOG(filesel), GTK_RESPONSE_ACCEPT); | |
1523 | |
1524 if (savedialog) { | |
1525 current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_save_folder"); | |
1526 } else { | |
1527 current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_open_folder"); | |
1528 } | |
1529 | |
1530 if (filename != NULL) | |
1531 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(filesel), filename); | |
1532 if ((current_folder != NULL) && (*current_folder != '\0')) { | |
1533 folder_set = gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filesel), current_folder); | |
1534 } | |
1535 | |
1536 #ifdef _WIN32 | |
1537 if (!folder_set) { | |
1538 char *my_documents = wgaim_get_special_folder(CSIDL_PERSONAL); | |
1539 | |
1540 if (my_documents != NULL) { | |
1541 gtk_file_chooser_set_current_folder( | |
1542 GTK_FILE_CHOOSER(filesel), my_documents); | |
1543 | |
1544 g_free(my_documents); | |
1545 } | |
1546 } | |
1547 | |
1548 #endif | |
1549 g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(filesel)), "response", | |
1550 G_CALLBACK(file_ok_check_if_exists_cb), data); | |
1551 #else /* FILECHOOSER */ | |
1552 filesel = gtk_file_selection_new( | |
1553 title ? title : (savedialog ? _("Save File...") | |
1554 : _("Open File..."))); | |
1555 if (savedialog) { | |
1556 current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_save_folder"); | |
1557 } else { | |
1558 current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_open_folder"); | |
1559 } | |
1560 if (current_folder != NULL) { | |
1561 gchar *path = g_strdup_printf("%s%s", current_folder, G_DIR_SEPARATOR_S); | |
1562 gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), path); | |
1563 g_free(path); | |
1564 } | |
1565 if (filename != NULL) | |
1566 gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), filename); | |
1567 | |
1568 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(filesel)), "delete_event", | |
1569 G_CALLBACK(file_cancel_cb), data); | |
1570 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(filesel)->cancel_button), | |
1571 "clicked", G_CALLBACK(file_cancel_cb), data); | |
1572 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked", | |
1573 G_CALLBACK(file_ok_check_if_exists_cb), data); | |
1574 #endif /* FILECHOOSER */ | |
1575 | |
1576 data->dialog = filesel; | |
1577 gtk_widget_show(filesel); | |
1578 | |
1579 return (void *)data; | |
1580 } | |
1581 | |
1582 static void * | |
1583 gaim_gtk_request_folder(const char *title, const char *dirname, | |
1584 GCallback ok_cb, GCallback cancel_cb, | |
1585 void *user_data) | |
1586 { | |
1587 GaimGtkRequestData *data; | |
1588 GtkWidget *dirsel; | |
1589 | |
1590 data = g_new0(GaimGtkRequestData, 1); | |
1591 data->type = GAIM_REQUEST_FOLDER; | |
1592 data->user_data = user_data; | |
1593 data->cb_count = 2; | |
1594 data->cbs = g_new0(GCallback, 2); | |
1595 data->cbs[0] = cancel_cb; | |
1596 data->cbs[1] = ok_cb; | |
1597 data->u.file.savedialog = FALSE; | |
1598 | |
1599 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ | |
1600 dirsel = gtk_file_chooser_dialog_new( | |
1601 title ? title : _("Select Folder..."), | |
1602 NULL, | |
1603 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, | |
1604 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
1605 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, | |
1606 NULL); | |
1607 gtk_dialog_set_default_response(GTK_DIALOG(dirsel), GTK_RESPONSE_ACCEPT); | |
1608 | |
1609 if ((dirname != NULL) && (*dirname != '\0')) | |
1610 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dirsel), dirname); | |
1611 | |
1612 g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(dirsel)), "response", | |
1613 G_CALLBACK(file_ok_check_if_exists_cb), data); | |
1614 #else | |
1615 dirsel = gtk_file_selection_new(title ? title : _("Select Folder...")); | |
1616 | |
1617 g_signal_connect_swapped(G_OBJECT(dirsel), "delete_event", | |
1618 G_CALLBACK(file_cancel_cb), data); | |
1619 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(dirsel)->cancel_button), | |
1620 "clicked", G_CALLBACK(file_cancel_cb), data); | |
1621 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(dirsel)->ok_button), "clicked", | |
1622 G_CALLBACK(file_ok_check_if_exists_cb), data); | |
1623 #endif | |
1624 | |
1625 data->dialog = dirsel; | |
1626 gtk_widget_show(dirsel); | |
1627 | |
1628 return (void *)data; | |
1629 } | |
1630 | |
1631 static void | |
1632 gaim_gtk_close_request(GaimRequestType type, void *ui_handle) | |
1633 { | |
1634 GaimGtkRequestData *data = (GaimGtkRequestData *)ui_handle; | |
1635 | |
1636 g_free(data->cbs); | |
1637 | |
1638 gtk_widget_destroy(data->dialog); | |
1639 | |
1640 if (type == GAIM_REQUEST_FIELDS) | |
1641 gaim_request_fields_destroy(data->u.multifield.fields); | |
1642 else if (type == GAIM_REQUEST_FILE) | |
1643 g_free(data->u.file.name); | |
1644 | |
1645 g_free(data); | |
1646 } | |
1647 | |
1648 static GaimRequestUiOps ops = | |
1649 { | |
1650 gaim_gtk_request_input, | |
1651 gaim_gtk_request_choice, | |
1652 gaim_gtk_request_action, | |
1653 gaim_gtk_request_fields, | |
1654 gaim_gtk_request_file, | |
1655 gaim_gtk_close_request, | |
1656 gaim_gtk_request_folder | |
1657 }; | |
1658 | |
1659 GaimRequestUiOps * | |
1660 gaim_gtk_request_get_ui_ops(void) | |
1661 { | |
1662 return &ops; | |
1663 } |