propagate from branch 'im.pidgin.pidgin.mxit' (head 2629bf405a36a13177423301925120fe8...
[pidgin-git.git] / finch / gntrequest.c
blob4ba5a279de08fe5d6a0375bc32fe4f8361664b1e
1 /**
2 * @file gntrequest.c GNT Request API
3 * @ingroup finch
4 */
6 /* finch
8 * Finch is the legal property of its developers, whose names are too numerous
9 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * source distribution.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 #include <internal.h>
28 #include <gnt.h>
29 #include <gntbox.h>
30 #include <gntbutton.h>
31 #include <gntcheckbox.h>
32 #include <gntcombobox.h>
33 #include <gntentry.h>
34 #include <gntfilesel.h>
35 #include <gntlabel.h>
36 #include <gntline.h>
37 #include <gnttree.h>
39 #include "finch.h"
40 #include "gntrequest.h"
41 #include "debug.h"
42 #include "util.h"
44 /* XXX: Until gobjectification ... */
45 #undef FINCH_GET_DATA
46 #undef FINCH_SET_DATA
47 #define FINCH_GET_DATA(obj) purple_request_field_get_ui_data(obj)
48 #define FINCH_SET_DATA(obj, data) purple_request_field_set_ui_data(obj, data)
50 typedef struct
52 void *user_data;
53 GntWidget *dialog;
54 GCallback *cbs;
55 gboolean save;
56 } FinchFileRequest;
58 static GntWidget *
59 setup_request_window(const char *title, const char *primary,
60 const char *secondary, PurpleRequestType type)
62 GntWidget *window;
64 window = gnt_vbox_new(FALSE);
65 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
66 gnt_box_set_title(GNT_BOX(window), title);
67 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
69 if (primary)
70 gnt_box_add_widget(GNT_BOX(window),
71 gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD));
72 if (secondary)
73 gnt_box_add_widget(GNT_BOX(window), gnt_label_new(secondary));
75 g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(purple_request_close),
76 GINT_TO_POINTER(type));
78 return window;
81 /**
82 * If the window is closed by the wm (ie, without triggering any of
83 * the buttons, then do some default callback.
85 static void
86 setup_default_callback(GntWidget *window, gpointer default_cb, gpointer data)
88 if (default_cb == NULL)
89 return;
90 g_object_set_data(G_OBJECT(window), "default-callback", default_cb);
91 g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(default_cb), data);
94 static void
95 action_performed(GntWidget *button, gpointer data)
97 g_signal_handlers_disconnect_matched(data, G_SIGNAL_MATCH_FUNC,
98 0, 0, NULL,
99 g_object_get_data(data, "default-callback"),
100 NULL);
104 * window: this is the window
105 * userdata: the userdata to pass to the primary callbacks
106 * cb: the callback
107 * data: data for the callback
108 * (text, primary-callback) pairs, ended by a NULL
110 * The cancellation callback should be the last callback sent.
112 static GntWidget *
113 setup_button_box(GntWidget *win, gpointer userdata, gpointer cb, gpointer data, ...)
115 GntWidget *box;
116 GntWidget *button = NULL;
117 va_list list;
118 const char *text;
119 gpointer callback;
121 box = gnt_hbox_new(FALSE);
123 va_start(list, data);
125 while ((text = va_arg(list, const char *)))
127 callback = va_arg(list, gpointer);
128 button = gnt_button_new(text);
129 gnt_box_add_widget(GNT_BOX(box), button);
130 g_object_set_data(G_OBJECT(button), "activate-callback", callback);
131 g_object_set_data(G_OBJECT(button), "activate-userdata", userdata);
132 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(action_performed), win);
133 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data);
136 if (button)
137 g_object_set_data(G_OBJECT(button), "cancellation-function", GINT_TO_POINTER(TRUE));
139 va_end(list);
140 return box;
143 static void
144 notify_input_cb(GntWidget *button, GntWidget *entry)
146 PurpleRequestInputCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
147 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
148 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
150 if (callback)
151 callback(data, text);
153 while (button->parent)
154 button = button->parent;
156 purple_request_close(PURPLE_REQUEST_INPUT, button);
159 static void *
160 finch_request_input(const char *title, const char *primary,
161 const char *secondary, const char *default_value,
162 gboolean multiline, gboolean masked, gchar *hint,
163 const char *ok_text, GCallback ok_cb,
164 const char *cancel_text, GCallback cancel_cb,
165 PurpleAccount *account, const char *who, PurpleConversation *conv,
166 void *user_data)
168 GntWidget *window, *box, *entry;
170 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_INPUT);
172 entry = gnt_entry_new(default_value);
173 if (masked)
174 gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
175 gnt_box_add_widget(GNT_BOX(window), entry);
177 box = setup_button_box(window, user_data, notify_input_cb, entry,
178 ok_text, ok_cb, cancel_text, cancel_cb, NULL);
179 gnt_box_add_widget(GNT_BOX(window), box);
181 setup_default_callback(window, cancel_cb, user_data);
182 gnt_widget_show(window);
184 return window;
187 static void
188 finch_close_request(PurpleRequestType type, gpointer ui_handle)
190 GntWidget *widget = GNT_WIDGET(ui_handle);
191 if (type == PURPLE_REQUEST_FIELDS) {
192 PurpleRequestFields *fields = g_object_get_data(G_OBJECT(widget), "fields");
193 purple_request_fields_destroy(fields);
196 while (widget->parent)
197 widget = widget->parent;
198 gnt_widget_destroy(widget);
201 static void
202 request_choice_cb(GntWidget *button, GntComboBox *combo)
204 PurpleRequestChoiceCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
205 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
206 int choice = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))) - 1;
208 if (callback)
209 callback(data, choice);
211 while (button->parent)
212 button = button->parent;
214 purple_request_close(PURPLE_REQUEST_INPUT, button);
217 static void *
218 finch_request_choice(const char *title, const char *primary,
219 const char *secondary, int default_value,
220 const char *ok_text, GCallback ok_cb,
221 const char *cancel_text, GCallback cancel_cb,
222 PurpleAccount *account, const char *who, PurpleConversation *conv,
223 void *user_data, va_list choices)
225 GntWidget *window, *combo, *box;
226 const char *text;
227 int val;
229 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_CHOICE);
231 combo = gnt_combo_box_new();
232 gnt_box_add_widget(GNT_BOX(window), combo);
233 while ((text = va_arg(choices, const char *)))
235 val = va_arg(choices, int);
236 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), GINT_TO_POINTER(val + 1), text);
238 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), GINT_TO_POINTER(default_value + 1));
240 box = setup_button_box(window, user_data, request_choice_cb, combo,
241 ok_text, ok_cb, cancel_text, cancel_cb, NULL);
242 gnt_box_add_widget(GNT_BOX(window), box);
244 setup_default_callback(window, cancel_cb, user_data);
245 gnt_widget_show(window);
247 return window;
250 static void
251 request_action_cb(GntWidget *button, GntWidget *window)
253 PurpleRequestActionCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
254 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
255 int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "activate-id"));
257 if (callback)
258 callback(data, id);
260 purple_request_close(PURPLE_REQUEST_ACTION, window);
263 static void*
264 finch_request_action(const char *title, const char *primary,
265 const char *secondary, int default_value,
266 PurpleAccount *account, const char *who, PurpleConversation *conv,
267 void *user_data, size_t actioncount,
268 va_list actions)
270 GntWidget *window, *box, *button, *focus = NULL;
271 int i;
273 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_ACTION);
275 box = gnt_hbox_new(FALSE);
276 gnt_box_add_widget(GNT_BOX(window), box);
277 for (i = 0; i < actioncount; i++)
279 const char *text = va_arg(actions, const char *);
280 PurpleRequestActionCb callback = va_arg(actions, PurpleRequestActionCb);
282 button = gnt_button_new(text);
283 gnt_box_add_widget(GNT_BOX(box), button);
285 g_object_set_data(G_OBJECT(button), "activate-callback", callback);
286 g_object_set_data(G_OBJECT(button), "activate-userdata", user_data);
287 g_object_set_data(G_OBJECT(button), "activate-id", GINT_TO_POINTER(i));
288 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(request_action_cb), window);
290 if (i == default_value)
291 focus = button;
294 gnt_widget_show(window);
295 if (focus)
296 gnt_box_give_focus_to_child(GNT_BOX(window), focus);
298 return window;
301 static void
302 request_fields_cb(GntWidget *button, PurpleRequestFields *fields)
304 PurpleRequestFieldsCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
305 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
306 GList *list;
308 /* Update the data of the fields. Pidgin does this differently. Instead of
309 * updating the fields at the end like here, it updates the appropriate field
310 * instantly whenever a change is made. That allows it to make sure the
311 * 'required' fields are entered before the user can hit OK. It's not the case
312 * here, althought it can be done. */
313 for (list = purple_request_fields_get_groups(fields); list; list = list->next)
315 PurpleRequestFieldGroup *group = list->data;
316 GList *fields = purple_request_field_group_get_fields(group);
318 for (; fields ; fields = fields->next)
320 PurpleRequestField *field = fields->data;
321 PurpleRequestFieldType type = purple_request_field_get_type(field);
322 if (!purple_request_field_is_visible(field))
323 continue;
324 if (type == PURPLE_REQUEST_FIELD_BOOLEAN)
326 GntWidget *check = FINCH_GET_DATA(field);
327 gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check));
328 purple_request_field_bool_set_value(field, value);
330 else if (type == PURPLE_REQUEST_FIELD_STRING)
332 GntWidget *entry = FINCH_GET_DATA(field);
333 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
334 purple_request_field_string_set_value(field, (text && *text) ? text : NULL);
336 else if (type == PURPLE_REQUEST_FIELD_INTEGER)
338 GntWidget *entry = FINCH_GET_DATA(field);
339 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
340 int value = (text && *text) ? atoi(text) : 0;
341 purple_request_field_int_set_value(field, value);
343 else if (type == PURPLE_REQUEST_FIELD_CHOICE)
345 GntWidget *combo = FINCH_GET_DATA(field);
346 int id;
347 id = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)));
348 purple_request_field_choice_set_value(field, id);
350 else if (type == PURPLE_REQUEST_FIELD_LIST)
352 GList *list = NULL, *iter;
353 if (purple_request_field_list_get_multi_select(field))
355 GntWidget *tree = FINCH_GET_DATA(field);
357 iter = purple_request_field_list_get_items(field);
358 for (; iter; iter = iter->next)
360 const char *text = iter->data;
361 gpointer key = purple_request_field_list_get_data(field, text);
362 if (gnt_tree_get_choice(GNT_TREE(tree), key))
363 list = g_list_prepend(list, (gpointer)text);
366 else
368 GntWidget *combo = FINCH_GET_DATA(field);
369 gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
371 iter = purple_request_field_list_get_items(field);
372 for (; iter; iter = iter->next) {
373 const char *text = iter->data;
374 gpointer key = purple_request_field_list_get_data(field, text);
375 if (key == data) {
376 list = g_list_prepend(list, (gpointer)text);
377 break;
382 purple_request_field_list_set_selected(field, list);
383 g_list_free(list);
385 else if (type == PURPLE_REQUEST_FIELD_ACCOUNT)
387 GntWidget *combo = FINCH_GET_DATA(field);
388 PurpleAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
389 purple_request_field_account_set_value(field, acc);
394 purple_notify_close_with_handle(button);
396 if (!g_object_get_data(G_OBJECT(button), "cancellation-function") &&
397 !purple_request_fields_all_required_filled(fields)) {
398 purple_notify_error(button, _("Error"),
399 _("You must fill all the required fields."),
400 _("The required fields are underlined."));
401 return;
404 if (callback)
405 callback(data, fields);
407 while (button->parent)
408 button = button->parent;
410 purple_request_close(PURPLE_REQUEST_FIELDS, button);
413 static void
414 update_selected_account(GntEntry *username, const char *start, const char *end,
415 GntComboBox *accountlist)
417 GList *accounts = gnt_tree_get_rows(GNT_TREE(accountlist->dropdown));
418 const char *name = gnt_entry_get_text(username);
419 while (accounts) {
420 if (purple_find_buddy(accounts->data, name)) {
421 gnt_combo_box_set_selected(accountlist, accounts->data);
422 gnt_widget_draw(GNT_WIDGET(accountlist));
423 break;
425 accounts = accounts->next;
429 static GntWidget*
430 create_boolean_field(PurpleRequestField *field)
432 const char *label = purple_request_field_get_label(field);
433 GntWidget *check = gnt_check_box_new(label);
434 gnt_check_box_set_checked(GNT_CHECK_BOX(check),
435 purple_request_field_bool_get_default_value(field));
436 return check;
439 static GntWidget*
440 create_string_field(PurpleRequestField *field, GntWidget **username)
442 const char *hint = purple_request_field_get_type_hint(field);
443 GntWidget *entry = gnt_entry_new(
444 purple_request_field_string_get_default_value(field));
445 gnt_entry_set_masked(GNT_ENTRY(entry),
446 purple_request_field_string_is_masked(field));
447 if (hint && purple_str_has_prefix(hint, "screenname")) {
448 PurpleBlistNode *node = purple_blist_get_root();
449 gboolean offline = purple_str_has_suffix(hint, "all");
450 for (; node; node = purple_blist_node_next(node, offline)) {
451 if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
452 continue;
453 gnt_entry_add_suggest(GNT_ENTRY(entry), purple_buddy_get_name((PurpleBuddy*)node));
455 gnt_entry_set_always_suggest(GNT_ENTRY(entry), TRUE);
456 if (username)
457 *username = entry;
458 } else if (hint && !strcmp(hint, "group")) {
459 PurpleBlistNode *node;
460 for (node = purple_blist_get_root(); node;
461 node = purple_blist_node_get_sibling_next(node)) {
462 if (PURPLE_BLIST_NODE_IS_GROUP(node))
463 gnt_entry_add_suggest(GNT_ENTRY(entry), purple_group_get_name((PurpleGroup *)node));
466 return entry;
469 static GntWidget*
470 create_integer_field(PurpleRequestField *field)
472 char str[256];
473 int val = purple_request_field_int_get_default_value(field);
474 GntWidget *entry;
476 snprintf(str, sizeof(str), "%d", val);
477 entry = gnt_entry_new(str);
478 gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
479 return entry;
482 static GntWidget*
483 create_choice_field(PurpleRequestField *field)
485 int id;
486 GList *list;
487 GntWidget *combo = gnt_combo_box_new();
489 list = purple_request_field_choice_get_labels(field);
490 for (id = 1; list; list = list->next, id++)
492 gnt_combo_box_add_data(GNT_COMBO_BOX(combo),
493 GINT_TO_POINTER(id), list->data);
495 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo),
496 GINT_TO_POINTER(purple_request_field_choice_get_default_value(field)));
497 return combo;
500 static GntWidget*
501 create_list_field(PurpleRequestField *field)
503 GntWidget *ret = NULL;
504 GList *list;
505 gboolean multi = purple_request_field_list_get_multi_select(field);
506 if (multi)
508 GntWidget *tree = gnt_tree_new();
510 list = purple_request_field_list_get_items(field);
511 for (; list; list = list->next)
513 const char *text = list->data;
514 gpointer key = purple_request_field_list_get_data(field, text);
515 gnt_tree_add_choice(GNT_TREE(tree), key,
516 gnt_tree_create_row(GNT_TREE(tree), text), NULL, NULL);
517 if (purple_request_field_list_is_selected(field, text))
518 gnt_tree_set_choice(GNT_TREE(tree), key, TRUE);
520 ret = tree;
522 else
524 GntWidget *combo = gnt_combo_box_new();
526 list = purple_request_field_list_get_items(field);
527 for (; list; list = list->next)
529 const char *text = list->data;
530 gpointer key = purple_request_field_list_get_data(field, text);
531 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), key, text);
532 if (purple_request_field_list_is_selected(field, text))
533 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), key);
535 ret = combo;
537 return ret;
540 static GntWidget*
541 create_account_field(PurpleRequestField *field)
543 gboolean all;
544 PurpleAccount *def;
545 GList *list;
546 GntWidget *combo = gnt_combo_box_new();
548 all = purple_request_field_account_get_show_all(field);
549 def = purple_request_field_account_get_value(field);
550 if (!def)
551 def = purple_request_field_account_get_default_value(field);
553 if (all)
554 list = purple_accounts_get_all();
555 else
556 list = purple_connections_get_all();
558 for (; list; list = list->next)
560 PurpleAccount *account;
561 char *text;
563 if (all)
564 account = list->data;
565 else
566 account = purple_connection_get_account(list->data);
568 text = g_strdup_printf("%s (%s)",
569 purple_account_get_username(account),
570 purple_account_get_protocol_name(account));
571 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), account, text);
572 g_free(text);
573 if (account == def)
574 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), account);
576 gnt_widget_set_size(combo, 20, 3); /* ew */
577 return combo;
580 static void *
581 finch_request_fields(const char *title, const char *primary,
582 const char *secondary, PurpleRequestFields *allfields,
583 const char *ok, GCallback ok_cb,
584 const char *cancel, GCallback cancel_cb,
585 PurpleAccount *account, const char *who, PurpleConversation *conv,
586 void *userdata)
588 GntWidget *window, *box;
589 GList *grlist;
590 GntWidget *username = NULL, *accountlist = NULL;
592 window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_FIELDS);
594 /* This is how it's going to work: the request-groups are going to be
595 * stacked vertically one after the other. A GntLine will be separating
596 * the groups. */
597 box = gnt_vbox_new(FALSE);
598 gnt_box_set_pad(GNT_BOX(box), 0);
599 gnt_box_set_fill(GNT_BOX(box), TRUE);
600 for (grlist = purple_request_fields_get_groups(allfields); grlist; grlist = grlist->next)
602 PurpleRequestFieldGroup *group = grlist->data;
603 GList *fields = purple_request_field_group_get_fields(group);
604 GntWidget *hbox;
605 const char *title = purple_request_field_group_get_title(group);
607 if (title)
608 gnt_box_add_widget(GNT_BOX(box),
609 gnt_label_new_with_format(title, GNT_TEXT_FLAG_BOLD));
611 for (; fields ; fields = fields->next)
613 PurpleRequestField *field = fields->data;
614 PurpleRequestFieldType type = purple_request_field_get_type(field);
615 const char *label = purple_request_field_get_label(field);
617 if (!purple_request_field_is_visible(field))
618 continue;
620 hbox = gnt_hbox_new(TRUE); /* hrm */
621 gnt_box_add_widget(GNT_BOX(box), hbox);
623 if (type != PURPLE_REQUEST_FIELD_BOOLEAN && label)
625 GntWidget *l;
626 if (purple_request_field_is_required(field))
627 l = gnt_label_new_with_format(label, GNT_TEXT_FLAG_UNDERLINE);
628 else
629 l = gnt_label_new(label);
630 gnt_widget_set_size(l, 0, 1);
631 gnt_box_add_widget(GNT_BOX(hbox), l);
634 if (type == PURPLE_REQUEST_FIELD_BOOLEAN)
636 FINCH_SET_DATA(field, create_boolean_field(field));
638 else if (type == PURPLE_REQUEST_FIELD_STRING)
640 FINCH_SET_DATA(field, create_string_field(field, &username));
642 else if (type == PURPLE_REQUEST_FIELD_INTEGER)
644 FINCH_SET_DATA(field, create_integer_field(field));
646 else if (type == PURPLE_REQUEST_FIELD_CHOICE)
648 FINCH_SET_DATA(field, create_choice_field(field));
650 else if (type == PURPLE_REQUEST_FIELD_LIST)
652 FINCH_SET_DATA(field, create_list_field(field));
654 else if (type == PURPLE_REQUEST_FIELD_ACCOUNT)
656 accountlist = create_account_field(field);
657 FINCH_SET_DATA(field, accountlist);
659 else
661 FINCH_SET_DATA(field, gnt_label_new_with_format(_("Not implemented yet."),
662 GNT_TEXT_FLAG_BOLD));
664 gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
665 gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(FINCH_GET_DATA(field)));
667 if (grlist->next)
668 gnt_box_add_widget(GNT_BOX(box), gnt_hline_new());
670 gnt_box_add_widget(GNT_BOX(window), box);
672 box = setup_button_box(window, userdata, request_fields_cb, allfields,
673 ok, ok_cb, cancel, cancel_cb, NULL);
674 gnt_box_add_widget(GNT_BOX(window), box);
676 setup_default_callback(window, cancel_cb, userdata);
677 gnt_widget_show(window);
679 if (username && accountlist) {
680 g_signal_connect(username, "completion", G_CALLBACK(update_selected_account), accountlist);
683 g_object_set_data(G_OBJECT(window), "fields", allfields);
685 return window;
688 static void
689 file_cancel_cb(gpointer fq, GntWidget *wid)
691 FinchFileRequest *data = fq;
692 if (data->cbs[1] != NULL)
693 ((PurpleRequestFileCb)data->cbs[1])(data->user_data, NULL);
695 purple_request_close(PURPLE_REQUEST_FILE, data->dialog);
698 static void
699 file_ok_cb(gpointer fq, GntWidget *widget)
701 FinchFileRequest *data = fq;
702 char *file = gnt_file_sel_get_selected_file(GNT_FILE_SEL(data->dialog));
703 char *dir = g_path_get_dirname(file);
704 if (data->cbs[0] != NULL)
705 ((PurpleRequestFileCb)data->cbs[0])(data->user_data, file);
706 g_free(file);
707 purple_prefs_set_path(data->save ? "/finch/filelocations/last_save_folder" :
708 "/finch/filelocations/last_open_folder", dir);
709 g_free(dir);
711 purple_request_close(PURPLE_REQUEST_FILE, data->dialog);
714 static void
715 file_request_destroy(FinchFileRequest *data)
717 g_free(data->cbs);
718 g_free(data);
721 static FinchFileRequest *
722 finch_file_request_window(const char *title, const char *path,
723 GCallback ok_cb, GCallback cancel_cb,
724 void *user_data)
726 GntWidget *window = gnt_file_sel_new();
727 GntFileSel *sel = GNT_FILE_SEL(window);
728 FinchFileRequest *data = g_new0(FinchFileRequest, 1);
730 data->user_data = user_data;
731 data->cbs = g_new0(GCallback, 2);
732 data->cbs[0] = ok_cb;
733 data->cbs[1] = cancel_cb;
734 data->dialog = window;
735 gnt_box_set_title(GNT_BOX(window), title);
737 gnt_file_sel_set_current_location(sel, (path && *path) ? path : purple_home_dir());
739 g_signal_connect(G_OBJECT(sel->cancel), "activate",
740 G_CALLBACK(action_performed), window);
741 g_signal_connect(G_OBJECT(sel->select), "activate",
742 G_CALLBACK(action_performed), window);
743 g_signal_connect_swapped(G_OBJECT(sel->cancel), "activate",
744 G_CALLBACK(file_cancel_cb), data);
745 g_signal_connect_swapped(G_OBJECT(sel->select), "activate",
746 G_CALLBACK(file_ok_cb), data);
748 setup_default_callback(window, file_cancel_cb, data);
749 g_object_set_data_full(G_OBJECT(window), "filerequestdata", data,
750 (GDestroyNotify)file_request_destroy);
752 return data;
755 static void *
756 finch_request_file(const char *title, const char *filename,
757 gboolean savedialog,
758 GCallback ok_cb, GCallback cancel_cb,
759 PurpleAccount *account, const char *who, PurpleConversation *conv,
760 void *user_data)
762 FinchFileRequest *data;
763 const char *path;
765 path = purple_prefs_get_path(savedialog ? "/finch/filelocations/last_save_folder" : "/finch/filelocations/last_open_folder");
766 data = finch_file_request_window(title ? title : (savedialog ? _("Save File...") : _("Open File...")), path,
767 ok_cb, cancel_cb, user_data);
768 data->save = savedialog;
769 if (savedialog)
770 gnt_file_sel_set_suggested_filename(GNT_FILE_SEL(data->dialog), filename);
772 gnt_widget_show(data->dialog);
773 return data->dialog;
776 static void *
777 finch_request_folder(const char *title, const char *dirname, GCallback ok_cb,
778 GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv,
779 void *user_data)
781 FinchFileRequest *data;
783 data = finch_file_request_window(title ? title : _("Choose Location..."), dirname,
784 ok_cb, cancel_cb, user_data);
785 data->save = TRUE;
786 gnt_file_sel_set_dirs_only(GNT_FILE_SEL(data->dialog), TRUE);
788 gnt_widget_show(data->dialog);
789 return data->dialog;
792 static PurpleRequestUiOps uiops =
794 finch_request_input,
795 finch_request_choice,
796 finch_request_action,
797 finch_request_fields,
798 finch_request_file,
799 finch_close_request,
800 finch_request_folder,
801 NULL,
802 NULL,
803 NULL,
804 NULL
807 PurpleRequestUiOps *finch_request_get_ui_ops()
809 return &uiops;
812 void finch_request_init()
816 void finch_request_uninit()
820 void finch_request_save_in_prefs(gpointer null, PurpleRequestFields *allfields)
822 GList *list;
823 for (list = purple_request_fields_get_groups(allfields); list; list = list->next) {
824 PurpleRequestFieldGroup *group = list->data;
825 GList *fields = purple_request_field_group_get_fields(group);
827 for (; fields ; fields = fields->next) {
828 PurpleRequestField *field = fields->data;
829 PurpleRequestFieldType type = purple_request_field_get_type(field);
830 PurplePrefType pt;
831 gpointer val = NULL;
832 const char *id = purple_request_field_get_id(field);
834 switch (type) {
835 case PURPLE_REQUEST_FIELD_LIST:
836 val = purple_request_field_list_get_selected(field)->data;
837 val = purple_request_field_list_get_data(field, val);
838 break;
839 case PURPLE_REQUEST_FIELD_BOOLEAN:
840 val = GINT_TO_POINTER(purple_request_field_bool_get_value(field));
841 break;
842 case PURPLE_REQUEST_FIELD_INTEGER:
843 val = GINT_TO_POINTER(purple_request_field_int_get_value(field));
844 break;
845 case PURPLE_REQUEST_FIELD_STRING:
846 val = (gpointer)purple_request_field_string_get_value(field);
847 break;
848 default:
849 break;
852 pt = purple_prefs_get_type(id);
853 switch (pt) {
854 case PURPLE_PREF_INT:
856 long int tmp = GPOINTER_TO_INT(val);
857 if (type == PURPLE_REQUEST_FIELD_LIST) /* Lists always return string */
858 sscanf(val, "%ld", &tmp);
859 purple_prefs_set_int(id, (gint)tmp);
860 break;
862 case PURPLE_PREF_BOOLEAN:
863 purple_prefs_set_bool(id, GPOINTER_TO_INT(val));
864 break;
865 case PURPLE_PREF_STRING:
866 purple_prefs_set_string(id, val);
867 break;
868 default:
869 break;
875 GntWidget *finch_request_field_get_widget(PurpleRequestField *field)
877 GntWidget *ret = NULL;
878 switch (purple_request_field_get_type(field)) {
879 case PURPLE_REQUEST_FIELD_BOOLEAN:
880 ret = create_boolean_field(field);
881 break;
882 case PURPLE_REQUEST_FIELD_STRING:
883 ret = create_string_field(field, NULL);
884 break;
885 case PURPLE_REQUEST_FIELD_INTEGER:
886 ret = create_integer_field(field);
887 break;
888 case PURPLE_REQUEST_FIELD_CHOICE:
889 ret = create_choice_field(field);
890 break;
891 case PURPLE_REQUEST_FIELD_LIST:
892 ret = create_list_field(field);
893 break;
894 case PURPLE_REQUEST_FIELD_ACCOUNT:
895 ret = create_account_field(field);
896 break;
897 default:
898 purple_debug_error("GntRequest", "Unimplemented request-field %d\n", purple_request_field_get_type(field));
899 break;
901 return ret;