pidgin/pidgin

Make libpurple depend on its schemas

11 months ago, Gary Kramlich
d039c29040d3
Make libpurple depend on its schemas

In certain situations you could build libpurple but not the schemas which would
cause runtime failures.

Testing Done:
Built

Reviewed at https://reviews.imfreedom.org/r/2452/
/*
* finch
*
* Finch 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include <glib/gi18n-lib.h>
#include <purple.h>
#include <gnt.h>
#include "gntrequest.h"
typedef struct
{
void *user_data;
GntWidget *dialog;
GCallback *cbs;
gboolean save;
} FinchFileRequest;
static GntWidget *
setup_request_window(const char *title, const char *primary,
const char *secondary, PurpleRequestType 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(purple_request_close),
GINT_TO_POINTER(type));
return window;
}
/*
* If the window is closed by the wm (ie, without triggering any of
* the buttons, then do some default callback.
*/
static void
setup_default_callback(GntWidget *window, gpointer default_cb, gpointer data)
{
if (default_cb == NULL)
return;
g_object_set_data(G_OBJECT(window), "default-callback", default_cb);
g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(default_cb), data);
}
static void
action_performed(G_GNUC_UNUSED GntWidget *button, gpointer data)
{
g_signal_handlers_disconnect_matched(data, G_SIGNAL_MATCH_FUNC,
0, 0, NULL,
g_object_get_data(data, "default-callback"),
NULL);
}
/*
* setup_button_box:
* @win: this is the window
* @userdata: the userdata to pass to the primary callbacks
* @cb: the callback
* @data: data for the callback
* @...: (text, primary-callback) pairs, ended by a NULL
*
* The cancellation callback should be the last callback sent.
*/
static GntWidget *
setup_button_box(GntWidget *win, gpointer userdata, gpointer cb, gpointer data, ...)
{
GntWidget *box;
GntWidget *button = NULL;
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(action_performed), win);
g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data);
}
if (button)
g_object_set_data(G_OBJECT(button), "cancellation-function", GINT_TO_POINTER(TRUE));
va_end(list);
return box;
}
static void
notify_input_cb(GntWidget *button, GntWidget *entry)
{
PurpleRequestInputCb 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));
GntWidget *window;
if (callback)
callback(data, text);
window = gnt_widget_get_toplevel(button);
purple_request_close(PURPLE_REQUEST_INPUT, window);
}
static void *
finch_request_input(const char *title, const char *primary,
const char *secondary, const char *default_value,
G_GNUC_UNUSED gboolean multiline, gboolean masked,
G_GNUC_UNUSED gchar *hint, const char *ok_text,
GCallback ok_cb, const char *cancel_text,
GCallback cancel_cb,
G_GNUC_UNUSED PurpleRequestCommonParameters *cpar,
void *user_data)
{
GntWidget *window, *box, *entry;
window = setup_request_window(title, primary, secondary, PURPLE_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(window, user_data, notify_input_cb, entry,
ok_text, ok_cb, cancel_text, cancel_cb, NULL);
gnt_box_add_widget(GNT_BOX(window), box);
setup_default_callback(window, cancel_cb, user_data);
gnt_widget_show(window);
return window;
}
static void
finch_close_request(G_GNUC_UNUSED PurpleRequestType type, gpointer ui_handle) {
GntWidget *widget = GNT_WIDGET(ui_handle);
widget = gnt_widget_get_toplevel(widget);
gnt_widget_destroy(widget);
}
static void
request_choice_cb(GntWidget *button, GntComboBox *combo)
{
PurpleRequestChoiceCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
gpointer choice = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
GntWidget *window;
if (callback)
callback(data, choice);
window = gnt_widget_get_toplevel(button);
purple_request_close(PURPLE_REQUEST_INPUT, window);
}
static void *
finch_request_choice(const char *title, const char *primary,
const char *secondary, gpointer default_value,
const char *ok_text, GCallback ok_cb,
const char *cancel_text, GCallback cancel_cb,
G_GNUC_UNUSED PurpleRequestCommonParameters *cpar,
void *user_data, va_list choices)
{
GntWidget *window, *combo, *box;
const char *text;
int val;
window = setup_request_window(title, primary, secondary, PURPLE_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), default_value);
box = setup_button_box(window, user_data, request_choice_cb, combo,
ok_text, ok_cb, cancel_text, cancel_cb, NULL);
gnt_box_add_widget(GNT_BOX(window), box);
setup_default_callback(window, cancel_cb, user_data);
gnt_widget_show(window);
return window;
}
static void
request_action_cb(GntWidget *button, GntWidget *window)
{
PurpleRequestActionCb 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);
purple_request_close(PURPLE_REQUEST_ACTION, window);
}
static void*
finch_request_action(const char *title, const char *primary,
const char *secondary, int default_value,
G_GNUC_UNUSED PurpleRequestCommonParameters *cpar,
void *user_data, size_t actioncount, va_list actions)
{
GntWidget *window, *box, *button, *focus = NULL;
gsize i;
window = setup_request_window(title, primary, secondary, PURPLE_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 *);
PurpleRequestActionCb callback = va_arg(actions, PurpleRequestActionCb);
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);
if (default_value >= 0 && i == (gsize)default_value)
focus = button;
}
gnt_widget_show(window);
if (focus)
gnt_box_give_focus_to_child(GNT_BOX(window), focus);
return window;
}
static void
request_fields_cb(GntWidget *button, PurpleRequestPage *page) {
PurpleRequestFieldsCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
GntWidget *window;
guint n_groups;
/* Update the data of the fields. Pidgin 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, although it can be done. */
n_groups = g_list_model_get_n_items(G_LIST_MODEL(page));
for(guint group_index = 0; group_index < n_groups; group_index++) {
GListModel *group = NULL;
guint n_fields;
group = g_list_model_get_item(G_LIST_MODEL(page), group_index);
n_fields = g_list_model_get_n_items(group);
for(guint field_index = 0; field_index < n_fields; field_index++) {
PurpleRequestField *field = NULL;
field = g_list_model_get_item(group, field_index);
if(!purple_request_field_is_visible(field)) {
g_object_unref(field);
continue;
}
if(PURPLE_IS_REQUEST_FIELD_BOOL(field)) {
GntWidget *check = g_object_get_data(G_OBJECT(field),
"finch-ui-data");
gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check));
purple_request_field_bool_set_value(PURPLE_REQUEST_FIELD_BOOL(field),
value);
} else if(PURPLE_IS_REQUEST_FIELD_STRING(field)) {
GntWidget *entry = g_object_get_data(G_OBJECT(field),
"finch-ui-data");
const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
if(purple_strempty(text)) {
text = NULL;
}
purple_request_field_string_set_value(PURPLE_REQUEST_FIELD_STRING(field),
text);
} else if(PURPLE_IS_REQUEST_FIELD_INT(field)) {
GntWidget *entry = g_object_get_data(G_OBJECT(field),
"finch-ui-data");
const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
int value = (text && *text) ? atoi(text) : 0;
purple_request_field_int_set_value(PURPLE_REQUEST_FIELD_INT(field),
value);
} else if(PURPLE_IS_REQUEST_FIELD_CHOICE(field)) {
GntWidget *combo = g_object_get_data(G_OBJECT(field),
"finch-ui-data");
gpointer value = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
purple_request_field_choice_set_value(PURPLE_REQUEST_FIELD_CHOICE(field),
value);
} else if(PURPLE_IS_REQUEST_FIELD_LIST(field)) {
PurpleRequestFieldList *lfield = PURPLE_REQUEST_FIELD_LIST(field);
GList *selected = NULL;
GList *list = purple_request_field_list_get_items(lfield);
if(purple_request_field_list_get_multi_select(lfield)) {
GntWidget *tree = g_object_get_data(G_OBJECT(field),
"finch-ui-data");
for (; list; list = list->next)
{
PurpleKeyValuePair *item = list->data;
const char *text = item->key;
gpointer key = NULL;
key = purple_request_field_list_get_data(lfield, text);
if (gnt_tree_get_choice(GNT_TREE(tree), key)) {
selected = g_list_prepend(selected, (gpointer)text);
}
}
}
else
{
GntWidget *combo = g_object_get_data(G_OBJECT(field),
"finch-ui-data");
gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
for (; list; list = list->next) {
PurpleKeyValuePair *item = list->data;
const char *text = item->key;
gpointer key = NULL;
key = purple_request_field_list_get_data(lfield, text);
if (key == data) {
selected = g_list_prepend(selected, (gpointer)text);
break;
}
}
}
purple_request_field_list_set_selected(lfield, selected);
g_list_free(selected);
} else if (PURPLE_IS_REQUEST_FIELD_ACCOUNT(field)) {
GntWidget *combo = NULL;
PurpleAccount *acc = NULL;
PurpleRequestFieldAccount *afield = NULL;
combo = g_object_get_data(G_OBJECT(field), "finch-ui-data");
acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
afield = PURPLE_REQUEST_FIELD_ACCOUNT(field);
purple_request_field_account_set_value(afield, acc);
}
g_object_unref(field);
}
g_object_unref(group);
}
purple_notify_close_with_handle(button);
if(!g_object_get_data(G_OBJECT(button), "cancellation-function") &&
!purple_request_page_is_valid(page))
{
purple_notify_error(button, _("Error"),
_("You must properly fill all the required fields."),
_("The required fields are underlined."), NULL);
return;
}
if(callback) {
callback(data, page);
}
window = gnt_widget_get_toplevel(button);
purple_request_close(PURPLE_REQUEST_FIELDS, window);
}
static void
update_selected_account(GntEntry *username, G_GNUC_UNUSED const char *start,
G_GNUC_UNUSED const char *end,
GntComboBox *accountlist)
{
GList *accounts =
gnt_tree_get_rows(GNT_TREE(gnt_combo_box_get_dropdown(accountlist)));
const char *name = gnt_entry_get_text(username);
while (accounts) {
if (purple_blist_find_buddy(accounts->data, name)) {
gnt_combo_box_set_selected(accountlist, accounts->data);
gnt_widget_draw(GNT_WIDGET(accountlist));
break;
}
accounts = accounts->next;
}
}
static GntWidget*
create_boolean_field(PurpleRequestField *field)
{
PurpleRequestFieldBool *boolfield = PURPLE_REQUEST_FIELD_BOOL(field);
const char *label = purple_request_field_get_label(field);
GntWidget *check = gnt_check_box_new(label);
gnt_check_box_set_checked(GNT_CHECK_BOX(check),
purple_request_field_bool_get_default_value(boolfield));
return check;
}
static GntWidget*
create_string_field(PurpleRequestField *field, GntWidget **username)
{
PurpleRequestFieldString *strfield = PURPLE_REQUEST_FIELD_STRING(field);
const char *hint = purple_request_field_get_type_hint(field);
GntWidget *entry = gnt_entry_new(
purple_request_field_string_get_default_value(strfield));
gnt_entry_set_masked(GNT_ENTRY(entry),
purple_request_field_string_is_masked(strfield));
if (hint && g_str_has_prefix(hint, "screenname")) {
PurpleBlistNode *node = purple_blist_get_default_root();
gboolean offline = g_str_has_suffix(hint, "all");
for (; node; node = purple_blist_node_next(node, offline)) {
if (!PURPLE_IS_BUDDY(node))
continue;
gnt_entry_add_suggest(GNT_ENTRY(entry), purple_buddy_get_name((PurpleBuddy*)node));
}
gnt_entry_set_always_suggest(GNT_ENTRY(entry), TRUE);
if (username)
*username = entry;
} else if (purple_strequal(hint, "group")) {
PurpleBlistNode *node;
for (node = purple_blist_get_default_root(); node;
node = purple_blist_node_get_sibling_next(node)) {
if (PURPLE_IS_GROUP(node))
gnt_entry_add_suggest(GNT_ENTRY(entry), purple_group_get_name((PurpleGroup *)node));
}
}
return entry;
}
static GntWidget*
create_integer_field(PurpleRequestField *field)
{
PurpleRequestFieldInt *intfield = PURPLE_REQUEST_FIELD_INT(field);
char str[256];
int val = purple_request_field_int_get_default_value(intfield);
GntWidget *entry;
g_snprintf(str, sizeof(str), "%d", val);
entry = gnt_entry_new(str);
gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
return entry;
}
static GntWidget*
create_choice_field(PurpleRequestField *field)
{
PurpleRequestFieldChoice *cfield = PURPLE_REQUEST_FIELD_CHOICE(field);
GntWidget *combo = gnt_combo_box_new();
for(GList *it = purple_request_field_choice_get_elements(cfield);
it != NULL; it = g_list_next(it))
{
PurpleKeyValuePair *choice = it->data;
gnt_combo_box_add_data(GNT_COMBO_BOX(combo), choice->value, choice->key);
}
gnt_combo_box_set_selected(GNT_COMBO_BOX(combo),
purple_request_field_choice_get_default_value(cfield));
return combo;
}
static GntWidget*
create_list_field(PurpleRequestField *field)
{
PurpleRequestFieldList *lfield = PURPLE_REQUEST_FIELD_LIST(field);
GntWidget *ret = NULL;
GList *list = purple_request_field_list_get_items(lfield);
if(purple_request_field_list_get_multi_select(lfield)) {
GntWidget *tree = gnt_tree_new();
for (; list; list = list->next)
{
PurpleKeyValuePair *item = list->data;
const char *text = item->key;
gpointer key = purple_request_field_list_get_data(lfield, text);
gnt_tree_add_choice(GNT_TREE(tree), key,
gnt_tree_create_row(GNT_TREE(tree), text), NULL, NULL);
if(purple_request_field_list_is_selected(lfield, text)) {
gnt_tree_set_choice(GNT_TREE(tree), key, TRUE);
}
}
ret = tree;
}
else
{
GntWidget *combo = gnt_combo_box_new();
for (; list; list = list->next)
{
PurpleKeyValuePair *item = list->data;
const char *text = item->key;
gpointer key = purple_request_field_list_get_data(lfield, text);
gnt_combo_box_add_data(GNT_COMBO_BOX(combo), key, text);
if(purple_request_field_list_is_selected(lfield, text)) {
gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), key);
}
}
ret = combo;
}
return ret;
}
static void
add_account_to_combo(GntWidget *combo, PurpleAccount *account) {
PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
char *text = NULL;
text = g_strdup_printf("%s (%s)",
purple_contact_info_get_username(info),
purple_account_get_protocol_name(account));
gnt_combo_box_add_data(GNT_COMBO_BOX(combo), account, text);
g_free(text);
}
static GntWidget*
create_account_field(PurpleRequestField *field)
{
PurpleRequestFieldAccount *afield = PURPLE_REQUEST_FIELD_ACCOUNT(field);
gboolean all;
PurpleAccount *def;
GntWidget *combo = gnt_combo_box_new();
all = purple_request_field_account_get_show_all(afield);
def = purple_request_field_account_get_value(afield);
if(!PURPLE_IS_ACCOUNT(def)) {
def = purple_request_field_account_get_default_value(afield);
}
if(all) {
GListModel *manager_model = NULL;
guint n_items = 0;
manager_model = purple_account_manager_get_default_as_model();
n_items = g_list_model_get_n_items(manager_model);
for(guint index = 0; index < n_items; index++) {
PurpleAccount *account;
account = g_list_model_get_item(manager_model, index);
add_account_to_combo(combo, account);
if(account == def) {
gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), account);
}
g_object_unref(account);
}
} else {
GList *list = purple_connections_get_all();
for(; list; list = list->next) {
PurpleAccount *account = NULL;
account = purple_connection_get_account(list->data);
add_account_to_combo(combo, account);
if(account == def) {
gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), account);
}
}
}
gnt_widget_set_size(combo, 20, 3); /* ew */
return combo;
}
static void
multifield_extra_cb(GntWidget *button, PurpleRequestPage *page) {
PurpleRequestFieldsCb cb;
gpointer cb_data;
gpointer handle;
handle = g_object_get_data(G_OBJECT(button), "ui-handle");
cb = g_object_get_data(G_OBJECT(button), "extra-cb");
cb_data = g_object_get_data(G_OBJECT(button), "extra-cb-data");
if(cb != NULL) {
cb(cb_data, page);
}
action_performed(button, handle);
purple_request_close(PURPLE_REQUEST_FIELDS, handle);
}
static void *
finch_request_fields(const char *title, const char *primary,
const char *secondary, PurpleRequestPage *page,
const char *ok, GCallback ok_cb,
const char *cancel, GCallback cancel_cb,
PurpleRequestCommonParameters *cpar,
void *userdata)
{
GntWidget *window, *box;
GntWidget *username = NULL, *accountlist = NULL;
PurpleRequestHelpCb help_cb;
gpointer help_data;
GSList *extra_actions;
guint n_groups;
window = setup_request_window(title, primary, secondary, PURPLE_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);
n_groups = g_list_model_get_n_items(G_LIST_MODEL(page));
for(guint group_index = 0; group_index < n_groups; group_index++) {
PurpleRequestGroup *group = NULL;
GntWidget *hbox;
const char *title = NULL;
guint n_fields;
group = g_list_model_get_item(G_LIST_MODEL(page), group_index);
title = purple_request_group_get_title(group);
if (title)
gnt_box_add_widget(GNT_BOX(box),
gnt_label_new_with_format(title, GNT_TEXT_FLAG_BOLD));
n_fields = g_list_model_get_n_items(G_LIST_MODEL(group));
for(guint field_index = 0; field_index < n_fields; field_index++) {
PurpleRequestField *field = NULL;
const char *label = NULL;
GntWidget *widget = NULL;
field = g_list_model_get_item(G_LIST_MODEL(group), field_index);
label = purple_request_field_get_label(field);
if(!purple_request_field_is_visible(field)) {
g_object_unref(field);
continue;
}
hbox = gnt_hbox_new(TRUE); /* hrm */
gnt_box_add_widget(GNT_BOX(box), hbox);
if(!PURPLE_IS_REQUEST_FIELD_BOOL(field) && label) {
GntWidget *l;
if (purple_request_field_is_required(field))
l = gnt_label_new_with_format(label, GNT_TEXT_FLAG_UNDERLINE);
else
l = gnt_label_new(label);
gnt_widget_set_size(l, 0, 1);
gnt_box_add_widget(GNT_BOX(hbox), l);
}
if(PURPLE_IS_REQUEST_FIELD_BOOL(field)) {
widget = create_boolean_field(field);
} else if(PURPLE_IS_REQUEST_FIELD_STRING(field)) {
widget = create_string_field(field, &username);
} else if(PURPLE_IS_REQUEST_FIELD_INT(field)) {
widget = create_integer_field(field);
} else if(PURPLE_IS_REQUEST_FIELD_CHOICE(field)) {
widget = create_choice_field(field);
} else if(PURPLE_IS_REQUEST_FIELD_LIST(field)) {
widget = create_list_field(field);
} else if(PURPLE_IS_REQUEST_FIELD_ACCOUNT(field)) {
accountlist = create_account_field(field);
widget = accountlist;
} else {
widget = gnt_label_new_with_format(_("Not implemented yet."),
GNT_TEXT_FLAG_BOLD);
}
gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
gnt_box_add_widget(GNT_BOX(hbox), widget);
g_object_set_data(G_OBJECT(field), "finch-ui-data", widget);
g_object_unref(field);
}
if(group_index < n_groups - 1) {
gnt_box_add_widget(GNT_BOX(box), gnt_hline_new());
}
g_object_unref(group);
}
gnt_box_add_widget(GNT_BOX(window), box);
box = setup_button_box(window, userdata, request_fields_cb, page,
ok, ok_cb, cancel, cancel_cb, NULL);
extra_actions = purple_request_cpar_get_extra_actions(cpar);
for (GSList *it = extra_actions; it; it = it->next) {
PurpleKeyValuePair *extra_action = it->data;
GntWidget *button = gnt_button_new(extra_action->key);
gnt_box_add_widget_in_front(GNT_BOX(box), button);
g_object_set_data(G_OBJECT(button), "ui-handle", window);
g_object_set_data(G_OBJECT(button), "extra-cb", extra_action->value);
g_object_set_data(G_OBJECT(button), "extra-cb-data", userdata);
g_signal_connect(G_OBJECT(button), "activate",
G_CALLBACK(multifield_extra_cb), page);
}
help_cb = purple_request_cpar_get_help_cb(cpar, &help_data);
if (help_cb) {
GntWidget *button = gnt_button_new(_("Help"));
gnt_box_add_widget_in_front(GNT_BOX(box), button);
g_signal_connect_swapped(G_OBJECT(button), "activate",
G_CALLBACK(help_cb), help_data);
}
gnt_box_add_widget(GNT_BOX(window), box);
setup_default_callback(window, cancel_cb, userdata);
gnt_widget_show(window);
if (username && accountlist) {
g_signal_connect(username, "completion", G_CALLBACK(update_selected_account), accountlist);
}
g_object_set_data_full(G_OBJECT(window), "fields", page, g_object_unref);
return window;
}
static void
file_cancel_cb(G_GNUC_UNUSED GntWidget *wid, gpointer fq)
{
FinchFileRequest *data = fq;
if (data->dialog == NULL) {
/* We've already handled this request, and are in the destroy handler. */
return;
}
if (data->cbs[1] != NULL)
((PurpleRequestFileCb)data->cbs[1])(data->user_data, NULL);
purple_request_close(PURPLE_REQUEST_FILE, data->dialog);
data->dialog = NULL;
}
static void
file_ok_cb(G_GNUC_UNUSED GntWidget *widget, const char *path, const char *file,
gpointer fq)
{
FinchFileRequest *data = fq;
char *dir = g_path_get_dirname(path);
if (data->cbs[0] != NULL)
((PurpleRequestFileCb)data->cbs[0])(data->user_data, file);
purple_prefs_set_path(data->save ? "/finch/filelocations/last_save_folder" :
"/finch/filelocations/last_open_folder", dir);
g_free(dir);
purple_request_close(PURPLE_REQUEST_FILE, data->dialog);
data->dialog = NULL;
}
static void
file_request_destroy(FinchFileRequest *data)
{
g_free(data->cbs);
g_free(data);
}
static FinchFileRequest *
finch_file_request_window(const char *title, const char *path,
GCallback ok_cb, GCallback cancel_cb,
void *user_data)
{
GntWidget *window = gnt_file_sel_new();
GntFileSel *sel = GNT_FILE_SEL(window);
FinchFileRequest *data = g_new0(FinchFileRequest, 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;
gnt_box_set_title(GNT_BOX(window), title);
gnt_file_sel_set_current_location(sel, (path && *path) ? path : purple_home_dir());
g_signal_connect(G_OBJECT(sel), "destroy",
G_CALLBACK(file_cancel_cb), data);
g_signal_connect(G_OBJECT(sel), "cancelled",
G_CALLBACK(file_cancel_cb), data);
g_signal_connect(G_OBJECT(sel), "file_selected",
G_CALLBACK(file_ok_cb), data);
g_object_set_data_full(G_OBJECT(window), "filerequestdata", data,
(GDestroyNotify)file_request_destroy);
return data;
}
static void *
finch_request_file(const char *title, const char *filename, gboolean savedialog,
GCallback ok_cb, GCallback cancel_cb,
G_GNUC_UNUSED PurpleRequestCommonParameters *cpar,
void *user_data)
{
FinchFileRequest *data;
const char *path;
path = purple_prefs_get_path(savedialog ? "/finch/filelocations/last_save_folder" : "/finch/filelocations/last_open_folder");
data = finch_file_request_window(title ? title : (savedialog ? _("Save File...") : _("Open File...")), path,
ok_cb, cancel_cb, user_data);
data->save = savedialog;
if (savedialog)
gnt_file_sel_set_suggested_filename(GNT_FILE_SEL(data->dialog), filename);
gnt_widget_show(data->dialog);
return data->dialog;
}
static void *
finch_request_folder(const char *title, const char *dirname, GCallback ok_cb,
GCallback cancel_cb,
G_GNUC_UNUSED PurpleRequestCommonParameters *cpar,
gpointer user_data)
{
FinchFileRequest *data;
data = finch_file_request_window(title ? title : _("Choose Location..."), dirname,
ok_cb, cancel_cb, user_data);
data->save = TRUE;
gnt_file_sel_set_dirs_only(GNT_FILE_SEL(data->dialog), TRUE);
gnt_widget_show(data->dialog);
return data->dialog;
}
static PurpleRequestUiOps uiops = {
.request_input = finch_request_input,
.request_choice = finch_request_choice,
.request_action = finch_request_action,
.request_fields = finch_request_fields,
.request_file = finch_request_file,
.request_folder = finch_request_folder,
.close_request = finch_close_request,
};
PurpleRequestUiOps *
finch_request_get_ui_ops(void)
{
return &uiops;
}
void
finch_request_init(void)
{
}
void
finch_request_uninit(void)
{
}
void
finch_request_save_in_prefs(G_GNUC_UNUSED gpointer data,
PurpleRequestPage *page)
{
guint n_groups;
n_groups = g_list_model_get_n_items(G_LIST_MODEL(page));
for(guint group_index = 0; group_index < n_groups; group_index++) {
GListModel *group = NULL;
guint n_fields;
group = g_list_model_get_item(G_LIST_MODEL(page), group_index);
n_fields = g_list_model_get_n_items(group);
for(guint field_index = 0; field_index < n_fields; field_index++) {
PurpleRequestField *field = NULL;
PurplePrefType pt;
gpointer val = NULL;
const char *id = NULL;
field = g_list_model_get_item(group, field_index);
id = purple_request_field_get_id(field);
if(PURPLE_IS_REQUEST_FIELD_CHOICE(field)) {
PurpleRequestFieldChoice *choice = PURPLE_REQUEST_FIELD_CHOICE(field);
val = purple_request_field_choice_get_value(choice);
} else if(PURPLE_IS_REQUEST_FIELD_LIST(field)) {
PurpleRequestFieldList *lfield = PURPLE_REQUEST_FIELD_LIST(field);
val = purple_request_field_list_get_selected(lfield)->data;
val = purple_request_field_list_get_data(lfield, val);
} else if(PURPLE_IS_REQUEST_FIELD_BOOL(field)) {
PurpleRequestFieldBool *bfield = PURPLE_REQUEST_FIELD_BOOL(field);
val = GINT_TO_POINTER(purple_request_field_bool_get_value(bfield));
} else if(PURPLE_IS_REQUEST_FIELD_INT(field)) {
PurpleRequestFieldInt *ifield = PURPLE_REQUEST_FIELD_INT(field);
val = GINT_TO_POINTER(purple_request_field_int_get_value(ifield));
} else if(PURPLE_IS_REQUEST_FIELD_STRING(field)) {
PurpleRequestFieldString *sfield = PURPLE_REQUEST_FIELD_STRING(field);
val = (gpointer)purple_request_field_string_get_value(sfield);
}
pt = purple_prefs_get_pref_type(id);
switch (pt) {
case PURPLE_PREF_INT:
{
long int tmp = GPOINTER_TO_INT(val);
if(PURPLE_IS_REQUEST_FIELD_LIST(field)) {
/* Lists always return string */
if (sscanf(val, "%ld", &tmp) != 1)
tmp = 0;
}
purple_prefs_set_int(id, (gint)tmp);
break;
}
case PURPLE_PREF_BOOLEAN:
purple_prefs_set_bool(id, GPOINTER_TO_INT(val));
break;
case PURPLE_PREF_STRING:
purple_prefs_set_string(id, val);
break;
default:
break;
}
g_object_unref(field);
}
g_object_unref(group);
}
}
GntWidget *finch_request_field_get_widget(PurpleRequestField *field)
{
GntWidget *ret = NULL;
if(PURPLE_IS_REQUEST_FIELD_BOOL(field)) {
ret = create_boolean_field(field);
} else if(PURPLE_IS_REQUEST_FIELD_STRING(field)) {
ret = create_string_field(field, NULL);
} else if(PURPLE_IS_REQUEST_FIELD_INT(field)) {
ret = create_integer_field(field);
} else if(PURPLE_IS_REQUEST_FIELD_CHOICE(field)) {
ret = create_choice_field(field);
} else if(PURPLE_IS_REQUEST_FIELD_ACCOUNT(field)) {
ret = create_account_field(field);
} else if(PURPLE_IS_REQUEST_FIELD_LIST(field)) {
ret = create_list_field(field);
} else {
purple_debug_error("GntRequest", "Unimplemented request-field %s",
G_OBJECT_TYPE_NAME(field));
}
return ret;
}