Convert prefs to a GtkStack.
[pidgin-git.git] / finch / gntrequest.c
blob71edab5f9e78969e3938c61b196a75f194c748fa
1 /* finch
3 * Finch is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 #include <internal.h>
23 #include <gnt.h>
24 #include <gntbox.h>
25 #include <gntbutton.h>
26 #include <gntcheckbox.h>
27 #include <gntcombobox.h>
28 #include <gntentry.h>
29 #include <gntfilesel.h>
30 #include <gntlabel.h>
31 #include <gntline.h>
32 #include <gnttree.h>
34 #include "finch.h"
35 #include "gntrequest.h"
36 #include "debug.h"
37 #include "util.h"
39 typedef struct
41 void *user_data;
42 GntWidget *dialog;
43 GCallback *cbs;
44 gboolean save;
45 } FinchFileRequest;
47 static GntWidget *
48 setup_request_window(const char *title, const char *primary,
49 const char *secondary, PurpleRequestType type)
51 GntWidget *window;
53 window = gnt_vbox_new(FALSE);
54 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
55 gnt_box_set_title(GNT_BOX(window), title);
56 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
58 if (primary)
59 gnt_box_add_widget(GNT_BOX(window),
60 gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD));
61 if (secondary)
62 gnt_box_add_widget(GNT_BOX(window), gnt_label_new(secondary));
64 g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(purple_request_close),
65 GINT_TO_POINTER(type));
67 return window;
71 * If the window is closed by the wm (ie, without triggering any of
72 * the buttons, then do some default callback.
74 static void
75 setup_default_callback(GntWidget *window, gpointer default_cb, gpointer data)
77 if (default_cb == NULL)
78 return;
79 g_object_set_data(G_OBJECT(window), "default-callback", default_cb);
80 g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(default_cb), data);
83 static void
84 action_performed(GntWidget *button, gpointer data)
86 g_signal_handlers_disconnect_matched(data, G_SIGNAL_MATCH_FUNC,
87 0, 0, NULL,
88 g_object_get_data(data, "default-callback"),
89 NULL);
93 * setup_button_box:
94 * @win: this is the window
95 * @userdata: the userdata to pass to the primary callbacks
96 * @cb: the callback
97 * @data: data for the callback
98 * @...: (text, primary-callback) pairs, ended by a NULL
100 * The cancellation callback should be the last callback sent.
102 static GntWidget *
103 setup_button_box(GntWidget *win, gpointer userdata, gpointer cb, gpointer data, ...)
105 GntWidget *box;
106 GntWidget *button = NULL;
107 va_list list;
108 const char *text;
109 gpointer callback;
111 box = gnt_hbox_new(FALSE);
113 va_start(list, data);
115 while ((text = va_arg(list, const char *)))
117 callback = va_arg(list, gpointer);
118 button = gnt_button_new(text);
119 gnt_box_add_widget(GNT_BOX(box), button);
120 g_object_set_data(G_OBJECT(button), "activate-callback", callback);
121 g_object_set_data(G_OBJECT(button), "activate-userdata", userdata);
122 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(action_performed), win);
123 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data);
126 if (button)
127 g_object_set_data(G_OBJECT(button), "cancellation-function", GINT_TO_POINTER(TRUE));
129 va_end(list);
130 return box;
133 static void
134 notify_input_cb(GntWidget *button, GntWidget *entry)
136 PurpleRequestInputCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
137 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
138 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
139 GntWidget *window;
141 if (callback)
142 callback(data, text);
144 window = gnt_widget_get_toplevel(button);
145 purple_request_close(PURPLE_REQUEST_INPUT, window);
148 static void *
149 finch_request_input(const char *title, const char *primary,
150 const char *secondary, const char *default_value,
151 gboolean multiline, gboolean masked, gchar *hint,
152 const char *ok_text, GCallback ok_cb,
153 const char *cancel_text, GCallback cancel_cb,
154 PurpleRequestCommonParameters *cpar,
155 void *user_data)
157 GntWidget *window, *box, *entry;
159 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_INPUT);
161 entry = gnt_entry_new(default_value);
162 if (masked)
163 gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
164 gnt_box_add_widget(GNT_BOX(window), entry);
166 box = setup_button_box(window, user_data, notify_input_cb, entry,
167 ok_text, ok_cb, cancel_text, cancel_cb, NULL);
168 gnt_box_add_widget(GNT_BOX(window), box);
170 setup_default_callback(window, cancel_cb, user_data);
171 gnt_widget_show(window);
173 return window;
176 static void
177 finch_close_request(PurpleRequestType type, gpointer ui_handle)
179 GntWidget *widget = GNT_WIDGET(ui_handle);
180 if (type == PURPLE_REQUEST_FIELDS) {
181 PurpleRequestFields *fields = g_object_get_data(G_OBJECT(widget), "fields");
182 purple_request_fields_destroy(fields);
185 widget = gnt_widget_get_toplevel(widget);
186 gnt_widget_destroy(widget);
189 static void
190 request_choice_cb(GntWidget *button, GntComboBox *combo)
192 PurpleRequestChoiceCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
193 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
194 gpointer choice = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
195 GntWidget *window;
197 if (callback)
198 callback(data, choice);
200 window = gnt_widget_get_toplevel(button);
201 purple_request_close(PURPLE_REQUEST_INPUT, window);
204 static void *
205 finch_request_choice(const char *title, const char *primary,
206 const char *secondary, gpointer default_value,
207 const char *ok_text, GCallback ok_cb,
208 const char *cancel_text, GCallback cancel_cb,
209 PurpleRequestCommonParameters *cpar,
210 void *user_data, va_list choices)
212 GntWidget *window, *combo, *box;
213 const char *text;
214 int val;
216 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_CHOICE);
218 combo = gnt_combo_box_new();
219 gnt_box_add_widget(GNT_BOX(window), combo);
220 while ((text = va_arg(choices, const char *)))
222 val = va_arg(choices, int);
223 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), GINT_TO_POINTER(val + 1), text);
225 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), default_value);
227 box = setup_button_box(window, user_data, request_choice_cb, combo,
228 ok_text, ok_cb, cancel_text, cancel_cb, NULL);
229 gnt_box_add_widget(GNT_BOX(window), box);
231 setup_default_callback(window, cancel_cb, user_data);
232 gnt_widget_show(window);
234 return window;
237 static void
238 request_action_cb(GntWidget *button, GntWidget *window)
240 PurpleRequestActionCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
241 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
242 int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "activate-id"));
244 if (callback)
245 callback(data, id);
247 purple_request_close(PURPLE_REQUEST_ACTION, window);
250 static void*
251 finch_request_action(const char *title, const char *primary,
252 const char *secondary, int default_value,
253 PurpleRequestCommonParameters *cpar,
254 void *user_data, size_t actioncount,
255 va_list actions)
257 GntWidget *window, *box, *button, *focus = NULL;
258 gsize i;
260 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_ACTION);
262 box = gnt_hbox_new(FALSE);
263 gnt_box_add_widget(GNT_BOX(window), box);
264 for (i = 0; i < actioncount; i++)
266 const char *text = va_arg(actions, const char *);
267 PurpleRequestActionCb callback = va_arg(actions, PurpleRequestActionCb);
269 button = gnt_button_new(text);
270 gnt_box_add_widget(GNT_BOX(box), button);
272 g_object_set_data(G_OBJECT(button), "activate-callback", callback);
273 g_object_set_data(G_OBJECT(button), "activate-userdata", user_data);
274 g_object_set_data(G_OBJECT(button), "activate-id", GINT_TO_POINTER(i));
275 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(request_action_cb), window);
277 if (default_value >= 0 && i == (gsize)default_value)
278 focus = button;
281 gnt_widget_show(window);
282 if (focus)
283 gnt_box_give_focus_to_child(GNT_BOX(window), focus);
285 return window;
288 static void
289 request_fields_cb(GntWidget *button, PurpleRequestFields *fields)
291 PurpleRequestFieldsCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
292 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
293 GList *list;
294 GntWidget *window;
296 /* Update the data of the fields. Pidgin does this differently. Instead of
297 * updating the fields at the end like here, it updates the appropriate field
298 * instantly whenever a change is made. That allows it to make sure the
299 * 'required' fields are entered before the user can hit OK. It's not the case
300 * here, althought it can be done. */
301 for (list = purple_request_fields_get_groups(fields); list; list = list->next)
303 PurpleRequestFieldGroup *group = list->data;
304 GList *fields = purple_request_field_group_get_fields(group);
306 for (; fields ; fields = fields->next)
308 PurpleRequestField *field = fields->data;
309 PurpleRequestFieldType type = purple_request_field_get_field_type(field);
310 if (!purple_request_field_is_visible(field))
311 continue;
312 if (type == PURPLE_REQUEST_FIELD_BOOLEAN)
314 GntWidget *check = purple_request_field_get_ui_data(field);
315 gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check));
316 purple_request_field_bool_set_value(field, value);
318 else if (type == PURPLE_REQUEST_FIELD_STRING)
320 GntWidget *entry = purple_request_field_get_ui_data(field);
321 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
322 purple_request_field_string_set_value(field, (text && *text) ? text : NULL);
324 else if (type == PURPLE_REQUEST_FIELD_INTEGER)
326 GntWidget *entry = purple_request_field_get_ui_data(field);
327 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
328 int value = (text && *text) ? atoi(text) : 0;
329 purple_request_field_int_set_value(field, value);
331 else if (type == PURPLE_REQUEST_FIELD_CHOICE)
333 GntWidget *combo = purple_request_field_get_ui_data(field);
334 gpointer value = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
335 purple_request_field_choice_set_value(field, value);
337 else if (type == PURPLE_REQUEST_FIELD_LIST)
339 GList *list = NULL, *iter;
340 if (purple_request_field_list_get_multi_select(field))
342 GntWidget *tree = purple_request_field_get_ui_data(field);
344 iter = purple_request_field_list_get_items(field);
345 for (; iter; iter = iter->next)
347 const char *text = iter->data;
348 gpointer key = purple_request_field_list_get_data(field, text);
349 if (gnt_tree_get_choice(GNT_TREE(tree), key))
350 list = g_list_prepend(list, (gpointer)text);
353 else
355 GntWidget *combo = purple_request_field_get_ui_data(field);
356 gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
358 iter = purple_request_field_list_get_items(field);
359 for (; iter; iter = iter->next) {
360 const char *text = iter->data;
361 gpointer key = purple_request_field_list_get_data(field, text);
362 if (key == data) {
363 list = g_list_prepend(list, (gpointer)text);
364 break;
369 purple_request_field_list_set_selected(field, list);
370 g_list_free(list);
372 else if (type == PURPLE_REQUEST_FIELD_ACCOUNT)
374 GntWidget *combo = purple_request_field_get_ui_data(field);
375 PurpleAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
376 purple_request_field_account_set_value(field, acc);
381 purple_notify_close_with_handle(button);
383 if (!g_object_get_data(G_OBJECT(button), "cancellation-function") &&
384 (!purple_request_fields_all_required_filled(fields) ||
385 !purple_request_fields_all_valid(fields))) {
386 purple_notify_error(button, _("Error"),
387 _("You must properly fill all the required fields."),
388 _("The required fields are underlined."), NULL);
389 return;
392 if (callback)
393 callback(data, fields);
395 window = gnt_widget_get_toplevel(button);
396 purple_request_close(PURPLE_REQUEST_FIELDS, window);
399 static void
400 update_selected_account(GntEntry *username, const char *start, const char *end,
401 GntComboBox *accountlist)
403 GList *accounts =
404 gnt_tree_get_rows(GNT_TREE(gnt_combo_box_get_dropdown(accountlist)));
405 const char *name = gnt_entry_get_text(username);
406 while (accounts) {
407 if (purple_blist_find_buddy(accounts->data, name)) {
408 gnt_combo_box_set_selected(accountlist, accounts->data);
409 gnt_widget_draw(GNT_WIDGET(accountlist));
410 break;
412 accounts = accounts->next;
416 static GntWidget*
417 create_boolean_field(PurpleRequestField *field)
419 const char *label = purple_request_field_get_label(field);
420 GntWidget *check = gnt_check_box_new(label);
421 gnt_check_box_set_checked(GNT_CHECK_BOX(check),
422 purple_request_field_bool_get_default_value(field));
423 return check;
426 static GntWidget*
427 create_string_field(PurpleRequestField *field, GntWidget **username)
429 const char *hint = purple_request_field_get_field_type_hint(field);
430 GntWidget *entry = gnt_entry_new(
431 purple_request_field_string_get_default_value(field));
432 gnt_entry_set_masked(GNT_ENTRY(entry),
433 purple_request_field_string_is_masked(field));
434 if (hint && purple_str_has_prefix(hint, "screenname")) {
435 PurpleBlistNode *node = purple_blist_get_default_root();
436 gboolean offline = purple_str_has_suffix(hint, "all");
437 for (; node; node = purple_blist_node_next(node, offline)) {
438 if (!PURPLE_IS_BUDDY(node))
439 continue;
440 gnt_entry_add_suggest(GNT_ENTRY(entry), purple_buddy_get_name((PurpleBuddy*)node));
442 gnt_entry_set_always_suggest(GNT_ENTRY(entry), TRUE);
443 if (username)
444 *username = entry;
445 } else if (purple_strequal(hint, "group")) {
446 PurpleBlistNode *node;
447 for (node = purple_blist_get_default_root(); node;
448 node = purple_blist_node_get_sibling_next(node)) {
449 if (PURPLE_IS_GROUP(node))
450 gnt_entry_add_suggest(GNT_ENTRY(entry), purple_group_get_name((PurpleGroup *)node));
453 return entry;
456 static GntWidget*
457 create_integer_field(PurpleRequestField *field)
459 char str[256];
460 int val = purple_request_field_int_get_default_value(field);
461 GntWidget *entry;
463 snprintf(str, sizeof(str), "%d", val);
464 entry = gnt_entry_new(str);
465 gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
466 return entry;
469 static GntWidget*
470 create_choice_field(PurpleRequestField *field)
472 GList *it;
473 GntWidget *combo = gnt_combo_box_new();
475 it = purple_request_field_choice_get_elements(field);
476 while (it != NULL)
478 const gchar *text;
479 gpointer value;
481 text = it->data;
482 it = g_list_next(it);
483 g_assert(it != NULL);
484 value = it->data;
485 it = g_list_next(it);
487 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), value, text);
489 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo),
490 purple_request_field_choice_get_default_value(field));
491 return combo;
494 static GntWidget*
495 create_list_field(PurpleRequestField *field)
497 GntWidget *ret = NULL;
498 GList *list;
499 gboolean multi = purple_request_field_list_get_multi_select(field);
500 if (multi)
502 GntWidget *tree = gnt_tree_new();
504 list = purple_request_field_list_get_items(field);
505 for (; list; list = list->next)
507 const char *text = list->data;
508 gpointer key = purple_request_field_list_get_data(field, text);
509 gnt_tree_add_choice(GNT_TREE(tree), key,
510 gnt_tree_create_row(GNT_TREE(tree), text), NULL, NULL);
511 if (purple_request_field_list_is_selected(field, text))
512 gnt_tree_set_choice(GNT_TREE(tree), key, TRUE);
514 ret = tree;
516 else
518 GntWidget *combo = gnt_combo_box_new();
520 list = purple_request_field_list_get_items(field);
521 for (; list; list = list->next)
523 const char *text = list->data;
524 gpointer key = purple_request_field_list_get_data(field, text);
525 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), key, text);
526 if (purple_request_field_list_is_selected(field, text))
527 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), key);
529 ret = combo;
531 return ret;
534 static GntWidget*
535 create_account_field(PurpleRequestField *field)
537 gboolean all;
538 PurpleAccount *def;
539 GList *list;
540 GntWidget *combo = gnt_combo_box_new();
542 all = purple_request_field_account_get_show_all(field);
543 def = purple_request_field_account_get_value(field);
544 if (!def)
545 def = purple_request_field_account_get_default_value(field);
547 if (all)
548 list = purple_accounts_get_all();
549 else
550 list = purple_connections_get_all();
552 for (; list; list = list->next)
554 PurpleAccount *account;
555 char *text;
557 if (all)
558 account = list->data;
559 else
560 account = purple_connection_get_account(list->data);
562 text = g_strdup_printf("%s (%s)",
563 purple_account_get_username(account),
564 purple_account_get_protocol_name(account));
565 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), account, text);
566 g_free(text);
567 if (account == def)
568 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), account);
570 gnt_widget_set_size(combo, 20, 3); /* ew */
571 return combo;
574 static void
575 multifield_extra_cb(GntWidget *button, PurpleRequestFields *allfields)
577 PurpleRequestFieldsCb cb;
578 gpointer cb_data;
579 gpointer handle;
581 handle = g_object_get_data(G_OBJECT(button), "ui-handle");
582 cb = g_object_get_data(G_OBJECT(button), "extra-cb");
583 cb_data = g_object_get_data(G_OBJECT(button), "extra-cb-data");
585 if (cb != NULL)
586 cb(cb_data, allfields);
588 action_performed(button, handle);
589 purple_request_close(PURPLE_REQUEST_FIELDS, handle);
592 static void *
593 finch_request_fields(const char *title, const char *primary,
594 const char *secondary, PurpleRequestFields *allfields,
595 const char *ok, GCallback ok_cb,
596 const char *cancel, GCallback cancel_cb,
597 PurpleRequestCommonParameters *cpar,
598 void *userdata)
600 GntWidget *window, *box;
601 GList *grlist;
602 GntWidget *username = NULL, *accountlist = NULL;
603 PurpleRequestHelpCb help_cb;
604 gpointer help_data;
605 GSList *extra_actions, *it;
607 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_FIELDS);
609 /* This is how it's going to work: the request-groups are going to be
610 * stacked vertically one after the other. A GntLine will be separating
611 * the groups. */
612 box = gnt_vbox_new(FALSE);
613 gnt_box_set_pad(GNT_BOX(box), 0);
614 gnt_box_set_fill(GNT_BOX(box), TRUE);
615 for (grlist = purple_request_fields_get_groups(allfields); grlist; grlist = grlist->next)
617 PurpleRequestFieldGroup *group = grlist->data;
618 GList *fields = purple_request_field_group_get_fields(group);
619 GntWidget *hbox;
620 const char *title = purple_request_field_group_get_title(group);
622 if (title)
623 gnt_box_add_widget(GNT_BOX(box),
624 gnt_label_new_with_format(title, GNT_TEXT_FLAG_BOLD));
626 for (; fields ; fields = fields->next)
628 PurpleRequestField *field = fields->data;
629 PurpleRequestFieldType type = purple_request_field_get_field_type(field);
630 const char *label = purple_request_field_get_label(field);
632 if (!purple_request_field_is_visible(field))
633 continue;
635 hbox = gnt_hbox_new(TRUE); /* hrm */
636 gnt_box_add_widget(GNT_BOX(box), hbox);
638 if (type != PURPLE_REQUEST_FIELD_BOOLEAN && label)
640 GntWidget *l;
641 if (purple_request_field_is_required(field))
642 l = gnt_label_new_with_format(label, GNT_TEXT_FLAG_UNDERLINE);
643 else
644 l = gnt_label_new(label);
645 gnt_widget_set_size(l, 0, 1);
646 gnt_box_add_widget(GNT_BOX(hbox), l);
649 if (type == PURPLE_REQUEST_FIELD_BOOLEAN)
651 purple_request_field_set_ui_data(field, create_boolean_field(field));
653 else if (type == PURPLE_REQUEST_FIELD_STRING)
655 purple_request_field_set_ui_data(field, create_string_field(field, &username));
657 else if (type == PURPLE_REQUEST_FIELD_INTEGER)
659 purple_request_field_set_ui_data(field, create_integer_field(field));
661 else if (type == PURPLE_REQUEST_FIELD_CHOICE)
663 purple_request_field_set_ui_data(field, create_choice_field(field));
665 else if (type == PURPLE_REQUEST_FIELD_LIST)
667 purple_request_field_set_ui_data(field, create_list_field(field));
669 else if (type == PURPLE_REQUEST_FIELD_ACCOUNT)
671 accountlist = create_account_field(field);
672 purple_request_field_set_ui_data(field, accountlist);
674 else
676 purple_request_field_set_ui_data(field, gnt_label_new_with_format(_("Not implemented yet."),
677 GNT_TEXT_FLAG_BOLD));
679 gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
680 gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(purple_request_field_get_ui_data(field)));
682 if (grlist->next)
683 gnt_box_add_widget(GNT_BOX(box), gnt_hline_new());
685 gnt_box_add_widget(GNT_BOX(window), box);
687 box = setup_button_box(window, userdata, request_fields_cb, allfields,
688 ok, ok_cb, cancel, cancel_cb, NULL);
690 extra_actions = purple_request_cpar_get_extra_actions(cpar);
691 for (it = extra_actions; it; it = it->next->next) {
692 const gchar *label = it->data;
693 PurpleRequestFieldsCb *cb = it->next->data;
695 GntWidget *button = gnt_button_new(label);
696 gnt_box_add_widget_in_front(GNT_BOX(box), button);
697 g_object_set_data(G_OBJECT(button), "ui-handle", window);
698 g_object_set_data(G_OBJECT(button), "extra-cb", cb);
699 g_object_set_data(G_OBJECT(button), "extra-cb-data", userdata);
700 g_signal_connect(G_OBJECT(button), "activate",
701 G_CALLBACK(multifield_extra_cb), allfields);
704 help_cb = purple_request_cpar_get_help_cb(cpar, &help_data);
705 if (help_cb) {
706 GntWidget *button = gnt_button_new(_("Help"));
707 gnt_box_add_widget_in_front(GNT_BOX(box), button);
708 g_signal_connect_swapped(G_OBJECT(button), "activate",
709 G_CALLBACK(help_cb), help_data);
712 gnt_box_add_widget(GNT_BOX(window), box);
714 setup_default_callback(window, cancel_cb, userdata);
715 gnt_widget_show(window);
717 if (username && accountlist) {
718 g_signal_connect(username, "completion", G_CALLBACK(update_selected_account), accountlist);
721 g_object_set_data(G_OBJECT(window), "fields", allfields);
723 return window;
726 static void
727 file_cancel_cb(GntWidget *wid, gpointer fq)
729 FinchFileRequest *data = fq;
730 if (data->dialog == NULL) {
731 /* We've already handled this request, and are in the destroy handler. */
732 return;
735 if (data->cbs[1] != NULL)
736 ((PurpleRequestFileCb)data->cbs[1])(data->user_data, NULL);
738 purple_request_close(PURPLE_REQUEST_FILE, data->dialog);
739 data->dialog = NULL;
742 static void
743 file_ok_cb(GntWidget *widget, const char *path, const char *file, gpointer fq)
745 FinchFileRequest *data = fq;
746 char *dir = g_path_get_dirname(path);
747 if (data->cbs[0] != NULL)
748 ((PurpleRequestFileCb)data->cbs[0])(data->user_data, file);
749 purple_prefs_set_path(data->save ? "/finch/filelocations/last_save_folder" :
750 "/finch/filelocations/last_open_folder", dir);
751 g_free(dir);
753 purple_request_close(PURPLE_REQUEST_FILE, data->dialog);
754 data->dialog = NULL;
757 static void
758 file_request_destroy(FinchFileRequest *data)
760 g_free(data->cbs);
761 g_free(data);
764 static FinchFileRequest *
765 finch_file_request_window(const char *title, const char *path,
766 GCallback ok_cb, GCallback cancel_cb,
767 void *user_data)
769 GntWidget *window = gnt_file_sel_new();
770 GntFileSel *sel = GNT_FILE_SEL(window);
771 FinchFileRequest *data = g_new0(FinchFileRequest, 1);
773 data->user_data = user_data;
774 data->cbs = g_new0(GCallback, 2);
775 data->cbs[0] = ok_cb;
776 data->cbs[1] = cancel_cb;
777 data->dialog = window;
778 gnt_box_set_title(GNT_BOX(window), title);
780 gnt_file_sel_set_current_location(sel, (path && *path) ? path : purple_home_dir());
782 g_signal_connect(G_OBJECT(sel), "destroy",
783 G_CALLBACK(file_cancel_cb), data);
784 g_signal_connect(G_OBJECT(sel), "cancelled",
785 G_CALLBACK(file_cancel_cb), data);
786 g_signal_connect(G_OBJECT(sel), "file_selected",
787 G_CALLBACK(file_ok_cb), data);
789 g_object_set_data_full(G_OBJECT(window), "filerequestdata", data,
790 (GDestroyNotify)file_request_destroy);
792 return data;
795 static void *
796 finch_request_file(const char *title, const char *filename, gboolean savedialog,
797 GCallback ok_cb, GCallback cancel_cb,
798 PurpleRequestCommonParameters *cpar, void *user_data)
800 FinchFileRequest *data;
801 const char *path;
803 path = purple_prefs_get_path(savedialog ? "/finch/filelocations/last_save_folder" : "/finch/filelocations/last_open_folder");
804 data = finch_file_request_window(title ? title : (savedialog ? _("Save File...") : _("Open File...")), path,
805 ok_cb, cancel_cb, user_data);
806 data->save = savedialog;
807 if (savedialog)
808 gnt_file_sel_set_suggested_filename(GNT_FILE_SEL(data->dialog), filename);
810 gnt_widget_show(data->dialog);
811 return data->dialog;
814 static void *
815 finch_request_folder(const char *title, const char *dirname, GCallback ok_cb,
816 GCallback cancel_cb, PurpleRequestCommonParameters *cpar,
817 void *user_data)
819 FinchFileRequest *data;
821 data = finch_file_request_window(title ? title : _("Choose Location..."), dirname,
822 ok_cb, cancel_cb, user_data);
823 data->save = TRUE;
824 gnt_file_sel_set_dirs_only(GNT_FILE_SEL(data->dialog), TRUE);
826 gnt_widget_show(data->dialog);
827 return data->dialog;
830 static PurpleRequestUiOps uiops =
833 finch_request_input,
834 finch_request_choice,
835 finch_request_action,
836 NULL,
837 NULL,
838 finch_request_fields,
839 finch_request_file,
840 finch_request_folder,
841 finch_close_request,
842 NULL,
843 NULL,
844 NULL,
845 NULL
848 PurpleRequestUiOps *finch_request_get_ui_ops()
850 return &uiops;
853 void finch_request_init()
857 void finch_request_uninit()
861 void finch_request_save_in_prefs(gpointer null, PurpleRequestFields *allfields)
863 GList *list;
864 for (list = purple_request_fields_get_groups(allfields); list; list = list->next) {
865 PurpleRequestFieldGroup *group = list->data;
866 GList *fields = purple_request_field_group_get_fields(group);
868 for (; fields ; fields = fields->next) {
869 PurpleRequestField *field = fields->data;
870 PurpleRequestFieldType type = purple_request_field_get_field_type(field);
871 PurplePrefType pt;
872 gpointer val = NULL;
873 const char *id = purple_request_field_get_id(field);
875 switch (type) {
876 case PURPLE_REQUEST_FIELD_LIST:
877 val = purple_request_field_list_get_selected(field)->data;
878 val = purple_request_field_list_get_data(field, val);
879 break;
880 case PURPLE_REQUEST_FIELD_BOOLEAN:
881 val = GINT_TO_POINTER(purple_request_field_bool_get_value(field));
882 break;
883 case PURPLE_REQUEST_FIELD_INTEGER:
884 val = GINT_TO_POINTER(purple_request_field_int_get_value(field));
885 break;
886 case PURPLE_REQUEST_FIELD_STRING:
887 val = (gpointer)purple_request_field_string_get_value(field);
888 break;
889 default:
890 break;
893 pt = purple_prefs_get_pref_type(id);
894 switch (pt) {
895 case PURPLE_PREF_INT:
897 long int tmp = GPOINTER_TO_INT(val);
898 if (type == PURPLE_REQUEST_FIELD_LIST) {
899 /* Lists always return string */
900 if (sscanf(val, "%ld", &tmp) != 1)
901 tmp = 0;
903 purple_prefs_set_int(id, (gint)tmp);
904 break;
906 case PURPLE_PREF_BOOLEAN:
907 purple_prefs_set_bool(id, GPOINTER_TO_INT(val));
908 break;
909 case PURPLE_PREF_STRING:
910 purple_prefs_set_string(id, val);
911 break;
912 default:
913 break;
919 GntWidget *finch_request_field_get_widget(PurpleRequestField *field)
921 GntWidget *ret = NULL;
922 switch (purple_request_field_get_field_type(field)) {
923 case PURPLE_REQUEST_FIELD_BOOLEAN:
924 ret = create_boolean_field(field);
925 break;
926 case PURPLE_REQUEST_FIELD_STRING:
927 ret = create_string_field(field, NULL);
928 break;
929 case PURPLE_REQUEST_FIELD_INTEGER:
930 ret = create_integer_field(field);
931 break;
932 case PURPLE_REQUEST_FIELD_CHOICE:
933 ret = create_choice_field(field);
934 break;
935 case PURPLE_REQUEST_FIELD_LIST:
936 ret = create_list_field(field);
937 break;
938 case PURPLE_REQUEST_FIELD_ACCOUNT:
939 ret = create_account_field(field);
940 break;
941 default:
942 purple_debug_error("GntRequest", "Unimplemented request-field %d\n",
943 purple_request_field_get_field_type(field));
944 break;
946 return ret;