Mercurial > pidgin
diff finch/gntrequest.c @ 15817:0e3a8505ebbe
renamed gaim-text to finch
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sun, 18 Mar 2007 19:38:15 +0000 |
parents | |
children | 32c366eeeb99 f59cfcce68a8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/gntrequest.c Sun Mar 18 19:38:15 2007 +0000 @@ -0,0 +1,619 @@ +/** + * @file gntrequest.c GNT Request API + * @ingroup gntui + * + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <gnt.h> +#include <gntbox.h> +#include <gntbutton.h> +#include <gntcheckbox.h> +#include <gntcombobox.h> +#include <gntentry.h> +#include <gntlabel.h> +#include <gntline.h> +#include <gnttree.h> + +#include "gntgaim.h" +#include "gntrequest.h" +#include "util.c" + +typedef struct +{ + void *user_data; + GntWidget *entry, *dialog; + GCallback *cbs; +} GaimGntFileRequest; + +static GntWidget * +setup_request_window(const char *title, const char *primary, + const char *secondary, GaimRequestType type) +{ + GntWidget *window; + + window = gnt_vbox_new(FALSE); + gnt_box_set_toplevel(GNT_BOX(window), TRUE); + gnt_box_set_title(GNT_BOX(window), title); + gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); + + if (primary) + gnt_box_add_widget(GNT_BOX(window), + gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD)); + if (secondary) + gnt_box_add_widget(GNT_BOX(window), gnt_label_new(secondary)); + + g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gaim_request_close), + GINT_TO_POINTER(type)); + + return window; +} + +static GntWidget * +setup_button_box(gpointer userdata, gpointer cb, gpointer data, ...) +{ + GntWidget *box, *button; + va_list list; + const char *text; + gpointer callback; + + box = gnt_hbox_new(FALSE); + + va_start(list, data); + + while ((text = va_arg(list, const char *))) + { + callback = va_arg(list, gpointer); + button = gnt_button_new(text); + gnt_box_add_widget(GNT_BOX(box), button); + g_object_set_data(G_OBJECT(button), "activate-callback", callback); + g_object_set_data(G_OBJECT(button), "activate-userdata", userdata); + g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data); + } + + va_end(list); + return box; +} + +static void +notify_input_cb(GntWidget *button, GntWidget *entry) +{ + GaimRequestInputCb callback = g_object_get_data(G_OBJECT(button), "activate-callback"); + gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata"); + const char *text = gnt_entry_get_text(GNT_ENTRY(entry)); + + if (callback) + callback(data, text); + + while (button->parent) + button = button->parent; + + gaim_request_close(GAIM_REQUEST_INPUT, button); +} + +static void * +finch_request_input(const char *title, const char *primary, + const char *secondary, const char *default_value, + gboolean multiline, gboolean masked, gchar *hint, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + void *user_data) +{ + GntWidget *window, *box, *entry; + + window = setup_request_window(title, primary, secondary, GAIM_REQUEST_INPUT); + + entry = gnt_entry_new(default_value); + if (masked) + gnt_entry_set_masked(GNT_ENTRY(entry), TRUE); + gnt_box_add_widget(GNT_BOX(window), entry); + + box = setup_button_box(user_data, notify_input_cb, entry, + ok_text, ok_cb, cancel_text, cancel_cb, NULL); + gnt_box_add_widget(GNT_BOX(window), box); + + gnt_widget_show(window); + + return window; +} + +static void +finch_close_request(GaimRequestType type, gpointer ui_handle) +{ + GntWidget *widget = GNT_WIDGET(ui_handle); + while (widget->parent) + widget = widget->parent; + gnt_widget_destroy(widget); +} + +static void +request_choice_cb(GntWidget *button, GntComboBox *combo) +{ + GaimRequestChoiceCb callback = g_object_get_data(G_OBJECT(button), "activate-callback"); + gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata"); + int choice = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))) - 1; + + if (callback) + callback(data, choice); + + while (button->parent) + button = button->parent; + + gaim_request_close(GAIM_REQUEST_INPUT, button); +} + +static void * +finch_request_choice(const char *title, const char *primary, + const char *secondary, unsigned int default_value, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + void *user_data, va_list choices) +{ + GntWidget *window, *combo, *box; + const char *text; + int val; + + window = setup_request_window(title, primary, secondary, GAIM_REQUEST_CHOICE); + + combo = gnt_combo_box_new(); + gnt_box_add_widget(GNT_BOX(window), combo); + while ((text = va_arg(choices, const char *))) + { + val = va_arg(choices, int); + gnt_combo_box_add_data(GNT_COMBO_BOX(combo), GINT_TO_POINTER(val + 1), text); + } + gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), GINT_TO_POINTER(default_value + 1)); + + box = setup_button_box(user_data, request_choice_cb, combo, + ok_text, ok_cb, cancel_text, cancel_cb, NULL); + gnt_box_add_widget(GNT_BOX(window), box); + + gnt_widget_show(window); + + return window; +} + +static void +request_action_cb(GntWidget *button, GntWidget *window) +{ + GaimRequestActionCb callback = g_object_get_data(G_OBJECT(button), "activate-callback"); + gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata"); + int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "activate-id")); + + if (callback) + callback(data, id); + + gaim_request_close(GAIM_REQUEST_ACTION, window); +} + +static void* +finch_request_action(const char *title, const char *primary, + const char *secondary, unsigned int default_value, + void *user_data, size_t actioncount, + va_list actions) +{ + GntWidget *window, *box, *button; + int i; + + window = setup_request_window(title, primary, secondary, GAIM_REQUEST_ACTION); + + box = gnt_hbox_new(FALSE); + gnt_box_add_widget(GNT_BOX(window), box); + for (i = 0; i < actioncount; i++) + { + const char *text = va_arg(actions, const char *); + GaimRequestActionCb callback = va_arg(actions, GaimRequestActionCb); + + button = gnt_button_new(text); + gnt_box_add_widget(GNT_BOX(box), button); + + g_object_set_data(G_OBJECT(button), "activate-callback", callback); + g_object_set_data(G_OBJECT(button), "activate-userdata", user_data); + g_object_set_data(G_OBJECT(button), "activate-id", GINT_TO_POINTER(i)); + g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(request_action_cb), window); + } + + gnt_widget_show(window); + + return window; +} + +static void +request_fields_cb(GntWidget *button, GaimRequestFields *fields) +{ + GaimRequestFieldsCb callback = g_object_get_data(G_OBJECT(button), "activate-callback"); + gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata"); + GList *list; + + /* Update the data of the fields. GtkGaim does this differently. Instead of + * updating the fields at the end like here, it updates the appropriate field + * instantly whenever a change is made. That allows it to make sure the + * 'required' fields are entered before the user can hit OK. It's not the case + * here, althought it can be done. I am not honouring the 'required' fields + * for the moment. */ + for (list = gaim_request_fields_get_groups(fields); list; list = list->next) + { + GaimRequestFieldGroup *group = list->data; + GList *fields = gaim_request_field_group_get_fields(group); + + for (; fields ; fields = fields->next) + { + GaimRequestField *field = fields->data; + GaimRequestFieldType type = gaim_request_field_get_type(field); + if (type == GAIM_REQUEST_FIELD_BOOLEAN) + { + GntWidget *check = field->ui_data; + gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check)); + gaim_request_field_bool_set_value(field, value); + } + else if (type == GAIM_REQUEST_FIELD_STRING) + { + GntWidget *entry = field->ui_data; + const char *text = gnt_entry_get_text(GNT_ENTRY(entry)); + gaim_request_field_string_set_value(field, (text && *text) ? text : NULL); + } + else if (type == GAIM_REQUEST_FIELD_INTEGER) + { + GntWidget *entry = field->ui_data; + const char *text = gnt_entry_get_text(GNT_ENTRY(entry)); + int value = (text && *text) ? atoi(text) : 0; + gaim_request_field_int_set_value(field, value); + } + else if (type == GAIM_REQUEST_FIELD_CHOICE) + { + GntWidget *combo = field->ui_data; + int id; + id = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))); + gaim_request_field_choice_set_value(field, id); + } + else if (type == GAIM_REQUEST_FIELD_LIST) + { + GList *list = NULL; + if (gaim_request_field_list_get_multi_select(field)) + { + const GList *iter; + GntWidget *tree = field->ui_data; + + iter = gaim_request_field_list_get_items(field); + for (; iter; iter = iter->next) + { + const char *text = iter->data; + gpointer key = gaim_request_field_list_get_data(field, text); + if (gnt_tree_get_choice(GNT_TREE(tree), key)) + list = g_list_prepend(list, key); + } + } + else + { + GntWidget *combo = field->ui_data; + gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)); + list = g_list_append(list, data); + } + + gaim_request_field_list_set_selected(field, list); + g_list_free(list); + } + else if (type == GAIM_REQUEST_FIELD_ACCOUNT) + { + GntWidget *combo = field->ui_data; + GaimAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)); + gaim_request_field_account_set_value(field, acc); + } + } + } + + if (callback) + callback(data, fields); + + while (button->parent) + button = button->parent; + + gaim_request_close(GAIM_REQUEST_FIELDS, button); +} + +static void * +finch_request_fields(const char *title, const char *primary, + const char *secondary, GaimRequestFields *allfields, + const char *ok, GCallback ok_cb, + const char *cancel, GCallback cancel_cb, + void *userdata) +{ + GntWidget *window, *box; + GList *grlist; + + window = setup_request_window(title, primary, secondary, GAIM_REQUEST_FIELDS); + + /* This is how it's going to work: the request-groups are going to be + * stacked vertically one after the other. A GntLine will be separating + * the groups. */ + box = gnt_vbox_new(FALSE); + gnt_box_set_pad(GNT_BOX(box), 0); + gnt_box_set_fill(GNT_BOX(box), TRUE); + for (grlist = gaim_request_fields_get_groups(allfields); grlist; grlist = grlist->next) + { + GaimRequestFieldGroup *group = grlist->data; + GList *fields = gaim_request_field_group_get_fields(group); + GntWidget *hbox; + const char *title = gaim_request_field_group_get_title(group); + + if (title) + gnt_box_add_widget(GNT_BOX(box), + gnt_label_new_with_format(title, GNT_TEXT_FLAG_BOLD)); + + for (; fields ; fields = fields->next) + { + /* XXX: Break each of the fields into a separate function? */ + GaimRequestField *field = fields->data; + GaimRequestFieldType type = gaim_request_field_get_type(field); + const char *label = gaim_request_field_get_label(field); + + hbox = gnt_hbox_new(TRUE); /* hrm */ + gnt_box_add_widget(GNT_BOX(box), hbox); + + if (type != GAIM_REQUEST_FIELD_BOOLEAN && label) + { + GntWidget *l = gnt_label_new(label); + gnt_widget_set_size(l, 0, 1); + gnt_box_add_widget(GNT_BOX(hbox), l); + } + + if (type == GAIM_REQUEST_FIELD_BOOLEAN) + { + GntWidget *check = gnt_check_box_new(label); + gnt_check_box_set_checked(GNT_CHECK_BOX(check), + gaim_request_field_bool_get_default_value(field)); + gnt_box_add_widget(GNT_BOX(hbox), check); + field->ui_data = check; + } + else if (type == GAIM_REQUEST_FIELD_STRING) + { + GntWidget *entry = gnt_entry_new( + gaim_request_field_string_get_default_value(field)); + gnt_entry_set_masked(GNT_ENTRY(entry), + gaim_request_field_string_is_masked(field)); + gnt_box_add_widget(GNT_BOX(hbox), entry); + field->ui_data = entry; + } + else if (type == GAIM_REQUEST_FIELD_INTEGER) + { + char str[256]; + int val = gaim_request_field_int_get_default_value(field); + GntWidget *entry; + + snprintf(str, sizeof(str), "%d", val); + entry = gnt_entry_new(str); + gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT); + gnt_box_add_widget(GNT_BOX(hbox), entry); + field->ui_data = entry; + } + else if (type == GAIM_REQUEST_FIELD_CHOICE) + { + int id; + const GList *list; + GntWidget *combo = gnt_combo_box_new(); + gnt_box_add_widget(GNT_BOX(hbox), combo); + field->ui_data = combo; + + list = gaim_request_field_choice_get_labels(field); + for (id = 1; list; list = list->next, id++) + { + gnt_combo_box_add_data(GNT_COMBO_BOX(combo), + GINT_TO_POINTER(id), list->data); + } + gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), + GINT_TO_POINTER(gaim_request_field_choice_get_default_value(field))); + } + else if (type == GAIM_REQUEST_FIELD_LIST) + { + const GList *list; + gboolean multi = gaim_request_field_list_get_multi_select(field); + if (multi) + { + GntWidget *tree = gnt_tree_new(); + gnt_box_add_widget(GNT_BOX(hbox), tree); + field->ui_data = tree; + + list = gaim_request_field_list_get_items(field); + for (; list; list = list->next) + { + const char *text = list->data; + gpointer key = gaim_request_field_list_get_data(field, text); + gnt_tree_add_choice(GNT_TREE(tree), key, + gnt_tree_create_row(GNT_TREE(tree), text), NULL, NULL); + if (gaim_request_field_list_is_selected(field, text)) + gnt_tree_set_choice(GNT_TREE(tree), key, TRUE); + } + } + else + { + GntWidget *combo = gnt_combo_box_new(); + gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID); + gnt_box_add_widget(GNT_BOX(hbox), combo); + field->ui_data = combo; + + list = gaim_request_field_list_get_items(field); + for (; list; list = list->next) + { + const char *text = list->data; + gpointer key = gaim_request_field_list_get_data(field, text); + gnt_combo_box_add_data(GNT_COMBO_BOX(combo), key, text); + if (gaim_request_field_list_is_selected(field, text)) + gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), key); + } + } + } + else if (type == GAIM_REQUEST_FIELD_ACCOUNT) + { + gboolean all; + GaimAccount *def; + GList *list; + GntWidget *combo = gnt_combo_box_new(); + gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID); + gnt_box_add_widget(GNT_BOX(hbox), combo); + field->ui_data = combo; + + all = gaim_request_field_account_get_show_all(field); + def = gaim_request_field_account_get_default_value(field); + + if (all) + list = gaim_accounts_get_all(); + else + list = gaim_connections_get_all(); + + for (; list; list = list->next) + { + GaimAccount *account; + char *text; + + if (all) + account = list->data; + else + account = gaim_connection_get_account(list->data); + + text = g_strdup_printf("%s (%s)", + gaim_account_get_username(account), + gaim_account_get_protocol_name(account)); + gnt_combo_box_add_data(GNT_COMBO_BOX(combo), account, text); + g_free(text); + if (account == def) + gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), account); + } + gnt_widget_set_size(combo, 20, 3); /* ew */ + } + else + { + gnt_box_add_widget(GNT_BOX(hbox), + gnt_label_new_with_format(_("Not implemented yet."), + GNT_TEXT_FLAG_BOLD)); + } + } + if (grlist->next) + gnt_box_add_widget(GNT_BOX(box), gnt_hline_new()); + } + gnt_box_add_widget(GNT_BOX(window), box); + + box = setup_button_box(userdata, request_fields_cb, allfields, + ok, ok_cb, cancel, cancel_cb, NULL); + gnt_box_add_widget(GNT_BOX(window), box); + + gnt_widget_show(window); + + return window; +} + +static void +file_cancel_cb(GntWidget *wid, gpointer fq) +{ + GaimGntFileRequest *data = fq; + if (data->cbs[1] != NULL) + ((GaimRequestFileCb)data->cbs[1])(data->user_data, NULL); + + gaim_request_close(GAIM_REQUEST_FILE, data->dialog); +} + +static void +file_ok_cb(GntWidget *wid, gpointer fq) +{ + GaimGntFileRequest *data = fq; + if (data->cbs[0] != NULL) + ((GaimRequestFileCb)data->cbs[0])(data->user_data, gnt_entry_get_text(GNT_ENTRY(data->entry))); + + gaim_request_close(GAIM_REQUEST_FILE, data->dialog); +} + +static void +file_request_destroy(GaimGntFileRequest *data) +{ + g_free(data->cbs); + g_free(data); +} + +static void * +finch_request_file(const char *title, const char *filename, + gboolean savedialog, + GCallback ok_cb, GCallback cancel_cb, + void *user_data) +{ + GntWidget *window = gnt_vbox_new(FALSE); + GntWidget *entry, *hbox, *button; + GaimGntFileRequest *data = g_new0(GaimGntFileRequest, 1); + + data->user_data = user_data; + data->cbs = g_new0(GCallback, 2); + data->cbs[0] = ok_cb; + data->cbs[1] = cancel_cb; + data->dialog = window; + data->entry = entry = gnt_entry_new(g_strconcat(gaim_home_dir(), G_DIR_SEPARATOR_S, filename, NULL)); + gnt_widget_set_size(entry, 30, 1); + gnt_box_set_toplevel(GNT_BOX(window), TRUE); + gnt_box_set_title(GNT_BOX(window), title ? title : (savedialog ? _("Save File...") : _("Open File..."))); +#if 0 + /* After the string freeze */ + gnt_box_add_widget(GNT_BOX(window), gnt_label_new(_("Please enter a full path for a file"))); +#endif + gnt_box_add_widget(GNT_BOX(window), entry); + + hbox = gnt_hbox_new(TRUE); + gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID); + + button = gnt_button_new(_("Cancel")); + g_signal_connect(G_OBJECT(button), "activate", + G_CALLBACK(file_cancel_cb), data); + gnt_box_add_widget(GNT_BOX(hbox), button); + + button = gnt_button_new(_("OK")); + g_signal_connect(G_OBJECT(button), "activate", + G_CALLBACK(file_ok_cb), data); + gnt_box_add_widget(GNT_BOX(hbox), button); + + gnt_box_add_widget(GNT_BOX(window), hbox); + + g_signal_connect_swapped(G_OBJECT(window), "destroy", + G_CALLBACK(file_request_destroy), data); + + gnt_widget_show(window); + + return window; +} + +static GaimRequestUiOps uiops = +{ + .request_input = finch_request_input, + .close_request = finch_close_request, + .request_choice = finch_request_choice, + .request_action = finch_request_action, + .request_fields = finch_request_fields, + .request_file = finch_request_file, + .request_folder = NULL /* No plans for this */ +}; + +GaimRequestUiOps *finch_request_get_ui_ops() +{ + return &uiops; +} + +void finch_request_init() +{ +} + +void finch_request_uninit() +{ +} +