Merged in default (pull request #594)
[pidgin-git.git] / finch / gntrequest.c
blob1cc874345859a1b3dae2ec894957eda010365bfe
1 /*
2 * finch
4 * Finch is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 #include <internal.h>
25 #include <gnt.h>
26 #include <gntbox.h>
27 #include <gntbutton.h>
28 #include <gntcheckbox.h>
29 #include <gntcombobox.h>
30 #include <gntentry.h>
31 #include <gntfilesel.h>
32 #include <gntlabel.h>
33 #include <gntline.h>
34 #include <gnttree.h>
36 #include "finch.h"
37 #include "gntrequest.h"
38 #include "debug.h"
39 #include "util.h"
41 typedef struct
43 void *user_data;
44 GntWidget *dialog;
45 GCallback *cbs;
46 gboolean save;
47 } FinchFileRequest;
49 static GntWidget *
50 setup_request_window(const char *title, const char *primary,
51 const char *secondary, PurpleRequestType type)
53 GntWidget *window;
55 window = gnt_vbox_new(FALSE);
56 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
57 gnt_box_set_title(GNT_BOX(window), title);
58 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
60 if (primary)
61 gnt_box_add_widget(GNT_BOX(window),
62 gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD));
63 if (secondary)
64 gnt_box_add_widget(GNT_BOX(window), gnt_label_new(secondary));
66 g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(purple_request_close),
67 GINT_TO_POINTER(type));
69 return window;
73 * If the window is closed by the wm (ie, without triggering any of
74 * the buttons, then do some default callback.
76 static void
77 setup_default_callback(GntWidget *window, gpointer default_cb, gpointer data)
79 if (default_cb == NULL)
80 return;
81 g_object_set_data(G_OBJECT(window), "default-callback", default_cb);
82 g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(default_cb), data);
85 static void
86 action_performed(GntWidget *button, gpointer data)
88 g_signal_handlers_disconnect_matched(data, G_SIGNAL_MATCH_FUNC,
89 0, 0, NULL,
90 g_object_get_data(data, "default-callback"),
91 NULL);
95 * setup_button_box:
96 * @win: this is the window
97 * @userdata: the userdata to pass to the primary callbacks
98 * @cb: the callback
99 * @data: data for the callback
100 * @...: (text, primary-callback) pairs, ended by a NULL
102 * The cancellation callback should be the last callback sent.
104 static GntWidget *
105 setup_button_box(GntWidget *win, gpointer userdata, gpointer cb, gpointer data, ...)
107 GntWidget *box;
108 GntWidget *button = NULL;
109 va_list list;
110 const char *text;
111 gpointer callback;
113 box = gnt_hbox_new(FALSE);
115 va_start(list, data);
117 while ((text = va_arg(list, const char *)))
119 callback = va_arg(list, gpointer);
120 button = gnt_button_new(text);
121 gnt_box_add_widget(GNT_BOX(box), button);
122 g_object_set_data(G_OBJECT(button), "activate-callback", callback);
123 g_object_set_data(G_OBJECT(button), "activate-userdata", userdata);
124 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(action_performed), win);
125 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data);
128 if (button)
129 g_object_set_data(G_OBJECT(button), "cancellation-function", GINT_TO_POINTER(TRUE));
131 va_end(list);
132 return box;
135 static void
136 notify_input_cb(GntWidget *button, GntWidget *entry)
138 PurpleRequestInputCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
139 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
140 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
141 GntWidget *window;
143 if (callback)
144 callback(data, text);
146 window = gnt_widget_get_toplevel(button);
147 purple_request_close(PURPLE_REQUEST_INPUT, window);
150 static void *
151 finch_request_input(const char *title, const char *primary,
152 const char *secondary, const char *default_value,
153 gboolean multiline, gboolean masked, gchar *hint,
154 const char *ok_text, GCallback ok_cb,
155 const char *cancel_text, GCallback cancel_cb,
156 PurpleRequestCommonParameters *cpar,
157 void *user_data)
159 GntWidget *window, *box, *entry;
161 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_INPUT);
163 entry = gnt_entry_new(default_value);
164 if (masked)
165 gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
166 gnt_box_add_widget(GNT_BOX(window), entry);
168 box = setup_button_box(window, user_data, notify_input_cb, entry,
169 ok_text, ok_cb, cancel_text, cancel_cb, NULL);
170 gnt_box_add_widget(GNT_BOX(window), box);
172 setup_default_callback(window, cancel_cb, user_data);
173 gnt_widget_show(window);
175 return window;
178 static void
179 finch_close_request(PurpleRequestType type, gpointer ui_handle)
181 GntWidget *widget = GNT_WIDGET(ui_handle);
182 if (type == PURPLE_REQUEST_FIELDS) {
183 PurpleRequestFields *fields = g_object_get_data(G_OBJECT(widget), "fields");
184 purple_request_fields_destroy(fields);
187 widget = gnt_widget_get_toplevel(widget);
188 gnt_widget_destroy(widget);
191 static void
192 request_choice_cb(GntWidget *button, GntComboBox *combo)
194 PurpleRequestChoiceCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
195 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
196 gpointer choice = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
197 GntWidget *window;
199 if (callback)
200 callback(data, choice);
202 window = gnt_widget_get_toplevel(button);
203 purple_request_close(PURPLE_REQUEST_INPUT, window);
206 static void *
207 finch_request_choice(const char *title, const char *primary,
208 const char *secondary, gpointer default_value,
209 const char *ok_text, GCallback ok_cb,
210 const char *cancel_text, GCallback cancel_cb,
211 PurpleRequestCommonParameters *cpar,
212 void *user_data, va_list choices)
214 GntWidget *window, *combo, *box;
215 const char *text;
216 int val;
218 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_CHOICE);
220 combo = gnt_combo_box_new();
221 gnt_box_add_widget(GNT_BOX(window), combo);
222 while ((text = va_arg(choices, const char *)))
224 val = va_arg(choices, int);
225 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), GINT_TO_POINTER(val + 1), text);
227 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), default_value);
229 box = setup_button_box(window, user_data, request_choice_cb, combo,
230 ok_text, ok_cb, cancel_text, cancel_cb, NULL);
231 gnt_box_add_widget(GNT_BOX(window), box);
233 setup_default_callback(window, cancel_cb, user_data);
234 gnt_widget_show(window);
236 return window;
239 static void
240 request_action_cb(GntWidget *button, GntWidget *window)
242 PurpleRequestActionCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
243 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
244 int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "activate-id"));
246 if (callback)
247 callback(data, id);
249 purple_request_close(PURPLE_REQUEST_ACTION, window);
252 static void*
253 finch_request_action(const char *title, const char *primary,
254 const char *secondary, int default_value,
255 PurpleRequestCommonParameters *cpar,
256 void *user_data, size_t actioncount,
257 va_list actions)
259 GntWidget *window, *box, *button, *focus = NULL;
260 gsize i;
262 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_ACTION);
264 box = gnt_hbox_new(FALSE);
265 gnt_box_add_widget(GNT_BOX(window), box);
266 for (i = 0; i < actioncount; i++)
268 const char *text = va_arg(actions, const char *);
269 PurpleRequestActionCb callback = va_arg(actions, PurpleRequestActionCb);
271 button = gnt_button_new(text);
272 gnt_box_add_widget(GNT_BOX(box), button);
274 g_object_set_data(G_OBJECT(button), "activate-callback", callback);
275 g_object_set_data(G_OBJECT(button), "activate-userdata", user_data);
276 g_object_set_data(G_OBJECT(button), "activate-id", GINT_TO_POINTER(i));
277 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(request_action_cb), window);
279 if (default_value >= 0 && i == (gsize)default_value)
280 focus = button;
283 gnt_widget_show(window);
284 if (focus)
285 gnt_box_give_focus_to_child(GNT_BOX(window), focus);
287 return window;
290 static void
291 request_fields_cb(GntWidget *button, PurpleRequestFields *fields)
293 PurpleRequestFieldsCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
294 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
295 GList *list;
296 GntWidget *window;
298 /* Update the data of the fields. Pidgin does this differently. Instead of
299 * updating the fields at the end like here, it updates the appropriate field
300 * instantly whenever a change is made. That allows it to make sure the
301 * 'required' fields are entered before the user can hit OK. It's not the case
302 * here, althought it can be done. */
303 for (list = purple_request_fields_get_groups(fields); list; list = list->next)
305 PurpleRequestFieldGroup *group = list->data;
306 GList *fields = purple_request_field_group_get_fields(group);
308 for (; fields ; fields = fields->next)
310 PurpleRequestField *field = fields->data;
311 PurpleRequestFieldType type = purple_request_field_get_field_type(field);
312 if (!purple_request_field_is_visible(field))
313 continue;
314 if (type == PURPLE_REQUEST_FIELD_BOOLEAN)
316 GntWidget *check = purple_request_field_get_ui_data(field);
317 gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check));
318 purple_request_field_bool_set_value(field, value);
320 else if (type == PURPLE_REQUEST_FIELD_STRING)
322 GntWidget *entry = purple_request_field_get_ui_data(field);
323 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
324 purple_request_field_string_set_value(field, (text && *text) ? text : NULL);
326 else if (type == PURPLE_REQUEST_FIELD_INTEGER)
328 GntWidget *entry = purple_request_field_get_ui_data(field);
329 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
330 int value = (text && *text) ? atoi(text) : 0;
331 purple_request_field_int_set_value(field, value);
333 else if (type == PURPLE_REQUEST_FIELD_CHOICE)
335 GntWidget *combo = purple_request_field_get_ui_data(field);
336 gpointer value = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
337 purple_request_field_choice_set_value(field, value);
339 else if (type == PURPLE_REQUEST_FIELD_LIST)
341 GList *list = NULL, *iter;
342 if (purple_request_field_list_get_multi_select(field))
344 GntWidget *tree = purple_request_field_get_ui_data(field);
346 iter = purple_request_field_list_get_items(field);
347 for (; iter; iter = iter->next)
349 const char *text = iter->data;
350 gpointer key = purple_request_field_list_get_data(field, text);
351 if (gnt_tree_get_choice(GNT_TREE(tree), key))
352 list = g_list_prepend(list, (gpointer)text);
355 else
357 GntWidget *combo = purple_request_field_get_ui_data(field);
358 gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
360 iter = purple_request_field_list_get_items(field);
361 for (; iter; iter = iter->next) {
362 const char *text = iter->data;
363 gpointer key = purple_request_field_list_get_data(field, text);
364 if (key == data) {
365 list = g_list_prepend(list, (gpointer)text);
366 break;
371 purple_request_field_list_set_selected(field, list);
372 g_list_free(list);
374 else if (type == PURPLE_REQUEST_FIELD_ACCOUNT)
376 GntWidget *combo = purple_request_field_get_ui_data(field);
377 PurpleAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
378 purple_request_field_account_set_value(field, acc);
383 purple_notify_close_with_handle(button);
385 if (!g_object_get_data(G_OBJECT(button), "cancellation-function") &&
386 (!purple_request_fields_all_required_filled(fields) ||
387 !purple_request_fields_all_valid(fields))) {
388 purple_notify_error(button, _("Error"),
389 _("You must properly fill all the required fields."),
390 _("The required fields are underlined."), NULL);
391 return;
394 if (callback)
395 callback(data, fields);
397 window = gnt_widget_get_toplevel(button);
398 purple_request_close(PURPLE_REQUEST_FIELDS, window);
401 static void
402 update_selected_account(GntEntry *username, const char *start, const char *end,
403 GntComboBox *accountlist)
405 GList *accounts =
406 gnt_tree_get_rows(GNT_TREE(gnt_combo_box_get_dropdown(accountlist)));
407 const char *name = gnt_entry_get_text(username);
408 while (accounts) {
409 if (purple_blist_find_buddy(accounts->data, name)) {
410 gnt_combo_box_set_selected(accountlist, accounts->data);
411 gnt_widget_draw(GNT_WIDGET(accountlist));
412 break;
414 accounts = accounts->next;
418 static GntWidget*
419 create_boolean_field(PurpleRequestField *field)
421 const char *label = purple_request_field_get_label(field);
422 GntWidget *check = gnt_check_box_new(label);
423 gnt_check_box_set_checked(GNT_CHECK_BOX(check),
424 purple_request_field_bool_get_default_value(field));
425 return check;
428 static GntWidget*
429 create_string_field(PurpleRequestField *field, GntWidget **username)
431 const char *hint = purple_request_field_get_field_type_hint(field);
432 GntWidget *entry = gnt_entry_new(
433 purple_request_field_string_get_default_value(field));
434 gnt_entry_set_masked(GNT_ENTRY(entry),
435 purple_request_field_string_is_masked(field));
436 if (hint && purple_str_has_prefix(hint, "screenname")) {
437 PurpleBlistNode *node = purple_blist_get_default_root();
438 gboolean offline = purple_str_has_suffix(hint, "all");
439 for (; node; node = purple_blist_node_next(node, offline)) {
440 if (!PURPLE_IS_BUDDY(node))
441 continue;
442 gnt_entry_add_suggest(GNT_ENTRY(entry), purple_buddy_get_name((PurpleBuddy*)node));
444 gnt_entry_set_always_suggest(GNT_ENTRY(entry), TRUE);
445 if (username)
446 *username = entry;
447 } else if (purple_strequal(hint, "group")) {
448 PurpleBlistNode *node;
449 for (node = purple_blist_get_default_root(); node;
450 node = purple_blist_node_get_sibling_next(node)) {
451 if (PURPLE_IS_GROUP(node))
452 gnt_entry_add_suggest(GNT_ENTRY(entry), purple_group_get_name((PurpleGroup *)node));
455 return entry;
458 static GntWidget*
459 create_integer_field(PurpleRequestField *field)
461 char str[256];
462 int val = purple_request_field_int_get_default_value(field);
463 GntWidget *entry;
465 snprintf(str, sizeof(str), "%d", val);
466 entry = gnt_entry_new(str);
467 gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
468 return entry;
471 static GntWidget*
472 create_choice_field(PurpleRequestField *field)
474 GList *it;
475 GntWidget *combo = gnt_combo_box_new();
477 it = purple_request_field_choice_get_elements(field);
478 while (it != NULL)
480 const gchar *text;
481 gpointer value;
483 text = it->data;
484 it = g_list_next(it);
485 g_assert(it != NULL);
486 value = it->data;
487 it = g_list_next(it);
489 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), value, text);
491 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo),
492 purple_request_field_choice_get_default_value(field));
493 return combo;
496 static GntWidget*
497 create_list_field(PurpleRequestField *field)
499 GntWidget *ret = NULL;
500 GList *list;
501 gboolean multi = purple_request_field_list_get_multi_select(field);
502 if (multi)
504 GntWidget *tree = gnt_tree_new();
506 list = purple_request_field_list_get_items(field);
507 for (; list; list = list->next)
509 const char *text = list->data;
510 gpointer key = purple_request_field_list_get_data(field, text);
511 gnt_tree_add_choice(GNT_TREE(tree), key,
512 gnt_tree_create_row(GNT_TREE(tree), text), NULL, NULL);
513 if (purple_request_field_list_is_selected(field, text))
514 gnt_tree_set_choice(GNT_TREE(tree), key, TRUE);
516 ret = tree;
518 else
520 GntWidget *combo = gnt_combo_box_new();
522 list = purple_request_field_list_get_items(field);
523 for (; list; list = list->next)
525 const char *text = list->data;
526 gpointer key = purple_request_field_list_get_data(field, text);
527 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), key, text);
528 if (purple_request_field_list_is_selected(field, text))
529 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), key);
531 ret = combo;
533 return ret;
536 static GntWidget*
537 create_account_field(PurpleRequestField *field)
539 gboolean all;
540 PurpleAccount *def;
541 GList *list;
542 GntWidget *combo = gnt_combo_box_new();
544 all = purple_request_field_account_get_show_all(field);
545 def = purple_request_field_account_get_value(field);
546 if (!def)
547 def = purple_request_field_account_get_default_value(field);
549 if (all)
550 list = purple_accounts_get_all();
551 else
552 list = purple_connections_get_all();
554 for (; list; list = list->next)
556 PurpleAccount *account;
557 char *text;
559 if (all)
560 account = list->data;
561 else
562 account = purple_connection_get_account(list->data);
564 text = g_strdup_printf("%s (%s)",
565 purple_account_get_username(account),
566 purple_account_get_protocol_name(account));
567 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), account, text);
568 g_free(text);
569 if (account == def)
570 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), account);
572 gnt_widget_set_size(combo, 20, 3); /* ew */
573 return combo;
576 static void
577 multifield_extra_cb(GntWidget *button, PurpleRequestFields *allfields)
579 PurpleRequestFieldsCb cb;
580 gpointer cb_data;
581 gpointer handle;
583 handle = g_object_get_data(G_OBJECT(button), "ui-handle");
584 cb = g_object_get_data(G_OBJECT(button), "extra-cb");
585 cb_data = g_object_get_data(G_OBJECT(button), "extra-cb-data");
587 if (cb != NULL)
588 cb(cb_data, allfields);
590 action_performed(button, handle);
591 purple_request_close(PURPLE_REQUEST_FIELDS, handle);
594 static void *
595 finch_request_fields(const char *title, const char *primary,
596 const char *secondary, PurpleRequestFields *allfields,
597 const char *ok, GCallback ok_cb,
598 const char *cancel, GCallback cancel_cb,
599 PurpleRequestCommonParameters *cpar,
600 void *userdata)
602 GntWidget *window, *box;
603 GList *grlist;
604 GntWidget *username = NULL, *accountlist = NULL;
605 PurpleRequestHelpCb help_cb;
606 gpointer help_data;
607 GSList *extra_actions, *it;
609 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_FIELDS);
611 /* This is how it's going to work: the request-groups are going to be
612 * stacked vertically one after the other. A GntLine will be separating
613 * the groups. */
614 box = gnt_vbox_new(FALSE);
615 gnt_box_set_pad(GNT_BOX(box), 0);
616 gnt_box_set_fill(GNT_BOX(box), TRUE);
617 for (grlist = purple_request_fields_get_groups(allfields); grlist; grlist = grlist->next)
619 PurpleRequestFieldGroup *group = grlist->data;
620 GList *fields = purple_request_field_group_get_fields(group);
621 GntWidget *hbox;
622 const char *title = purple_request_field_group_get_title(group);
624 if (title)
625 gnt_box_add_widget(GNT_BOX(box),
626 gnt_label_new_with_format(title, GNT_TEXT_FLAG_BOLD));
628 for (; fields ; fields = fields->next)
630 PurpleRequestField *field = fields->data;
631 PurpleRequestFieldType type = purple_request_field_get_field_type(field);
632 const char *label = purple_request_field_get_label(field);
634 if (!purple_request_field_is_visible(field))
635 continue;
637 hbox = gnt_hbox_new(TRUE); /* hrm */
638 gnt_box_add_widget(GNT_BOX(box), hbox);
640 if (type != PURPLE_REQUEST_FIELD_BOOLEAN && label)
642 GntWidget *l;
643 if (purple_request_field_is_required(field))
644 l = gnt_label_new_with_format(label, GNT_TEXT_FLAG_UNDERLINE);
645 else
646 l = gnt_label_new(label);
647 gnt_widget_set_size(l, 0, 1);
648 gnt_box_add_widget(GNT_BOX(hbox), l);
651 if (type == PURPLE_REQUEST_FIELD_BOOLEAN)
653 purple_request_field_set_ui_data(field, create_boolean_field(field));
655 else if (type == PURPLE_REQUEST_FIELD_STRING)
657 purple_request_field_set_ui_data(field, create_string_field(field, &username));
659 else if (type == PURPLE_REQUEST_FIELD_INTEGER)
661 purple_request_field_set_ui_data(field, create_integer_field(field));
663 else if (type == PURPLE_REQUEST_FIELD_CHOICE)
665 purple_request_field_set_ui_data(field, create_choice_field(field));
667 else if (type == PURPLE_REQUEST_FIELD_LIST)
669 purple_request_field_set_ui_data(field, create_list_field(field));
671 else if (type == PURPLE_REQUEST_FIELD_ACCOUNT)
673 accountlist = create_account_field(field);
674 purple_request_field_set_ui_data(field, accountlist);
676 else
678 purple_request_field_set_ui_data(field, gnt_label_new_with_format(_("Not implemented yet."),
679 GNT_TEXT_FLAG_BOLD));
681 gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
682 gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(purple_request_field_get_ui_data(field)));
684 if (grlist->next)
685 gnt_box_add_widget(GNT_BOX(box), gnt_hline_new());
687 gnt_box_add_widget(GNT_BOX(window), box);
689 box = setup_button_box(window, userdata, request_fields_cb, allfields,
690 ok, ok_cb, cancel, cancel_cb, NULL);
692 extra_actions = purple_request_cpar_get_extra_actions(cpar);
693 for (it = extra_actions; it; it = it->next->next) {
694 const gchar *label = it->data;
695 PurpleRequestFieldsCb *cb = it->next->data;
697 GntWidget *button = gnt_button_new(label);
698 gnt_box_add_widget_in_front(GNT_BOX(box), button);
699 g_object_set_data(G_OBJECT(button), "ui-handle", window);
700 g_object_set_data(G_OBJECT(button), "extra-cb", cb);
701 g_object_set_data(G_OBJECT(button), "extra-cb-data", userdata);
702 g_signal_connect(G_OBJECT(button), "activate",
703 G_CALLBACK(multifield_extra_cb), allfields);
706 help_cb = purple_request_cpar_get_help_cb(cpar, &help_data);
707 if (help_cb) {
708 GntWidget *button = gnt_button_new(_("Help"));
709 gnt_box_add_widget_in_front(GNT_BOX(box), button);
710 g_signal_connect_swapped(G_OBJECT(button), "activate",
711 G_CALLBACK(help_cb), help_data);
714 gnt_box_add_widget(GNT_BOX(window), box);
716 setup_default_callback(window, cancel_cb, userdata);
717 gnt_widget_show(window);
719 if (username && accountlist) {
720 g_signal_connect(username, "completion", G_CALLBACK(update_selected_account), accountlist);
723 g_object_set_data(G_OBJECT(window), "fields", allfields);
725 return window;
728 static void
729 file_cancel_cb(GntWidget *wid, gpointer fq)
731 FinchFileRequest *data = fq;
732 if (data->dialog == NULL) {
733 /* We've already handled this request, and are in the destroy handler. */
734 return;
737 if (data->cbs[1] != NULL)
738 ((PurpleRequestFileCb)data->cbs[1])(data->user_data, NULL);
740 purple_request_close(PURPLE_REQUEST_FILE, data->dialog);
741 data->dialog = NULL;
744 static void
745 file_ok_cb(GntWidget *widget, const char *path, const char *file, gpointer fq)
747 FinchFileRequest *data = fq;
748 char *dir = g_path_get_dirname(path);
749 if (data->cbs[0] != NULL)
750 ((PurpleRequestFileCb)data->cbs[0])(data->user_data, file);
751 purple_prefs_set_path(data->save ? "/finch/filelocations/last_save_folder" :
752 "/finch/filelocations/last_open_folder", dir);
753 g_free(dir);
755 purple_request_close(PURPLE_REQUEST_FILE, data->dialog);
756 data->dialog = NULL;
759 static void
760 file_request_destroy(FinchFileRequest *data)
762 g_free(data->cbs);
763 g_free(data);
766 static FinchFileRequest *
767 finch_file_request_window(const char *title, const char *path,
768 GCallback ok_cb, GCallback cancel_cb,
769 void *user_data)
771 GntWidget *window = gnt_file_sel_new();
772 GntFileSel *sel = GNT_FILE_SEL(window);
773 FinchFileRequest *data = g_new0(FinchFileRequest, 1);
775 data->user_data = user_data;
776 data->cbs = g_new0(GCallback, 2);
777 data->cbs[0] = ok_cb;
778 data->cbs[1] = cancel_cb;
779 data->dialog = window;
780 gnt_box_set_title(GNT_BOX(window), title);
782 gnt_file_sel_set_current_location(sel, (path && *path) ? path : purple_home_dir());
784 g_signal_connect(G_OBJECT(sel), "destroy",
785 G_CALLBACK(file_cancel_cb), data);
786 g_signal_connect(G_OBJECT(sel), "cancelled",
787 G_CALLBACK(file_cancel_cb), data);
788 g_signal_connect(G_OBJECT(sel), "file_selected",
789 G_CALLBACK(file_ok_cb), data);
791 g_object_set_data_full(G_OBJECT(window), "filerequestdata", data,
792 (GDestroyNotify)file_request_destroy);
794 return data;
797 static void *
798 finch_request_file(const char *title, const char *filename, gboolean savedialog,
799 GCallback ok_cb, GCallback cancel_cb,
800 PurpleRequestCommonParameters *cpar, void *user_data)
802 FinchFileRequest *data;
803 const char *path;
805 path = purple_prefs_get_path(savedialog ? "/finch/filelocations/last_save_folder" : "/finch/filelocations/last_open_folder");
806 data = finch_file_request_window(title ? title : (savedialog ? _("Save File...") : _("Open File...")), path,
807 ok_cb, cancel_cb, user_data);
808 data->save = savedialog;
809 if (savedialog)
810 gnt_file_sel_set_suggested_filename(GNT_FILE_SEL(data->dialog), filename);
812 gnt_widget_show(data->dialog);
813 return data->dialog;
816 static void *
817 finch_request_folder(const char *title, const char *dirname, GCallback ok_cb,
818 GCallback cancel_cb, PurpleRequestCommonParameters *cpar,
819 void *user_data)
821 FinchFileRequest *data;
823 data = finch_file_request_window(title ? title : _("Choose Location..."), dirname,
824 ok_cb, cancel_cb, user_data);
825 data->save = TRUE;
826 gnt_file_sel_set_dirs_only(GNT_FILE_SEL(data->dialog), TRUE);
828 gnt_widget_show(data->dialog);
829 return data->dialog;
832 static PurpleRequestUiOps uiops =
835 finch_request_input,
836 finch_request_choice,
837 finch_request_action,
838 NULL,
839 NULL,
840 finch_request_fields,
841 finch_request_file,
842 finch_request_folder,
843 finch_close_request,
844 NULL,
845 NULL,
846 NULL,
847 NULL
850 PurpleRequestUiOps *finch_request_get_ui_ops()
852 return &uiops;
855 void finch_request_init()
859 void finch_request_uninit()
863 void finch_request_save_in_prefs(gpointer data, PurpleRequestFields *allfields)
865 GList *list;
866 for (list = purple_request_fields_get_groups(allfields); list; list = list->next) {
867 PurpleRequestFieldGroup *group = list->data;
868 GList *fields = purple_request_field_group_get_fields(group);
870 for (; fields ; fields = fields->next) {
871 PurpleRequestField *field = fields->data;
872 PurpleRequestFieldType type = purple_request_field_get_field_type(field);
873 PurplePrefType pt;
874 gpointer val = NULL;
875 const char *id = purple_request_field_get_id(field);
877 switch (type) {
878 case PURPLE_REQUEST_FIELD_LIST:
879 val = purple_request_field_list_get_selected(field)->data;
880 val = purple_request_field_list_get_data(field, val);
881 break;
882 case PURPLE_REQUEST_FIELD_BOOLEAN:
883 val = GINT_TO_POINTER(purple_request_field_bool_get_value(field));
884 break;
885 case PURPLE_REQUEST_FIELD_INTEGER:
886 val = GINT_TO_POINTER(purple_request_field_int_get_value(field));
887 break;
888 case PURPLE_REQUEST_FIELD_STRING:
889 val = (gpointer)purple_request_field_string_get_value(field);
890 break;
891 default:
892 break;
895 pt = purple_prefs_get_pref_type(id);
896 switch (pt) {
897 case PURPLE_PREF_INT:
899 long int tmp = GPOINTER_TO_INT(val);
900 if (type == PURPLE_REQUEST_FIELD_LIST) {
901 /* Lists always return string */
902 if (sscanf(val, "%ld", &tmp) != 1)
903 tmp = 0;
905 purple_prefs_set_int(id, (gint)tmp);
906 break;
908 case PURPLE_PREF_BOOLEAN:
909 purple_prefs_set_bool(id, GPOINTER_TO_INT(val));
910 break;
911 case PURPLE_PREF_STRING:
912 purple_prefs_set_string(id, val);
913 break;
914 default:
915 break;
921 GntWidget *finch_request_field_get_widget(PurpleRequestField *field)
923 GntWidget *ret = NULL;
924 switch (purple_request_field_get_field_type(field)) {
925 case PURPLE_REQUEST_FIELD_BOOLEAN:
926 ret = create_boolean_field(field);
927 break;
928 case PURPLE_REQUEST_FIELD_STRING:
929 ret = create_string_field(field, NULL);
930 break;
931 case PURPLE_REQUEST_FIELD_INTEGER:
932 ret = create_integer_field(field);
933 break;
934 case PURPLE_REQUEST_FIELD_CHOICE:
935 ret = create_choice_field(field);
936 break;
937 case PURPLE_REQUEST_FIELD_LIST:
938 ret = create_list_field(field);
939 break;
940 case PURPLE_REQUEST_FIELD_ACCOUNT:
941 ret = create_account_field(field);
942 break;
943 default:
944 purple_debug_error("GntRequest", "Unimplemented request-field %d\n",
945 purple_request_field_get_field_type(field));
946 break;
948 return ret;