* @file gtkrequest.c GTK+ Request API * 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 * 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 "gtkimhtmltoolbar.h" #include <gdk/gdkkeysyms.h> static GtkWidget * create_account_field(GaimRequestField *field); GaimRequestFields *fields; generic_response_start(GaimGtkRequestData *data) g_return_if_fail(data != NULL); /* Tell the user we're doing something. */ gaim_gtk_set_cursor(GTK_WIDGET(data->dialog), GDK_WATCH); input_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) char *multiline_value = NULL; generic_response_start(data); if (data->u.input.multiline) { GtkTextIter start_iter, end_iter; gtk_text_view_get_buffer(GTK_TEXT_VIEW(data->u.input.entry)); gtk_text_buffer_get_start_iter(buffer, &start_iter); gtk_text_buffer_get_end_iter(buffer, &end_iter); if ((data->u.input.hint != NULL) && (!strcmp(data->u.input.hint, "html"))) multiline_value = gtk_imhtml_get_markup(GTK_IMHTML(data->u.input.entry)); multiline_value = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, value = gtk_entry_get_text(GTK_ENTRY(data->u.input.entry)); if (id < data->cb_count && data->cbs[id] != NULL) ((GaimRequestInputCb)data->cbs[id])(data->user_data, value); else if (data->cbs[1] != NULL) ((GaimRequestInputCb)data->cbs[1])(data->user_data, value); if (data->u.input.multiline) gaim_request_close(GAIM_REQUEST_INPUT, data); action_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) generic_response_start(data); if (id < data->cb_count && data->cbs[id] != NULL) ((GaimRequestActionCb)data->cbs[id])(data->user_data, id); gaim_request_close(GAIM_REQUEST_INPUT, data); choice_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) GtkWidget *radio = g_object_get_data(G_OBJECT(dialog), "radio"); GSList *group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); generic_response_start(data); if (id < data->cb_count && data->cbs[id] != NULL) if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group->data))) { ((GaimRequestChoiceCb)data->cbs[id])(data->user_data, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(group->data), "choice_id"))); gaim_request_close(GAIM_REQUEST_INPUT, data); field_string_focus_out_cb(GtkWidget *entry, GdkEventFocus *event, if (gaim_request_field_string_is_multiline(field)) GtkTextIter start_iter, end_iter; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)); gtk_text_buffer_get_start_iter(buffer, &start_iter); gtk_text_buffer_get_end_iter(buffer, &end_iter); value = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE); value = gtk_entry_get_text(GTK_ENTRY(entry)); gaim_request_field_string_set_value(field, (*value == '\0' ? NULL : value)); field_int_focus_out_cb(GtkEntry *entry, GdkEventFocus *event, gaim_request_field_int_set_value(field, atoi(gtk_entry_get_text(entry))); field_bool_cb(GtkToggleButton *button, GaimRequestField *field) gaim_request_field_bool_set_value(field, gtk_toggle_button_get_active(button)); field_choice_menu_cb(GtkOptionMenu *menu, GaimRequestField *field) gaim_request_field_choice_set_value(field, gtk_option_menu_get_history(menu)); field_choice_option_cb(GtkRadioButton *button, GaimRequestField *field) if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) gaim_request_field_choice_set_value(field, (g_slist_length(gtk_radio_button_get_group(button)) - g_slist_index(gtk_radio_button_get_group(button), button)) - 1); field_account_cb(GObject *w, GaimAccount *account, GaimRequestField *field) gaim_request_field_account_set_value(field, account); multifield_ok_cb(GtkWidget *button, GaimGtkRequestData *data) generic_response_start(data); if (!GTK_WIDGET_HAS_FOCUS(button)) gtk_widget_grab_focus(button); if (data->cbs[0] != NULL) ((GaimRequestFieldsCb)data->cbs[0])(data->user_data, data->u.multifield.fields); gaim_request_close(GAIM_REQUEST_FIELDS, data); multifield_cancel_cb(GtkWidget *button, GaimGtkRequestData *data) generic_response_start(data); if (data->cbs[1] != NULL) ((GaimRequestFieldsCb)data->cbs[1])(data->user_data, data->u.multifield.fields); gaim_request_close(GAIM_REQUEST_FIELDS, data); destroy_multifield_cb(GtkWidget *dialog, GdkEvent *event, GaimGtkRequestData *data) multifield_cancel_cb(NULL, data); #define STOCK_ITEMIZE(r, l) \ if (!strcmp((r), text)) \ text_to_stock(const char *text) STOCK_ITEMIZE(_("Yes"), GTK_STOCK_YES); STOCK_ITEMIZE(_("No"), GTK_STOCK_NO); STOCK_ITEMIZE(_("OK"), GTK_STOCK_OK); STOCK_ITEMIZE(_("Cancel"), GTK_STOCK_CANCEL); STOCK_ITEMIZE(_("Apply"), GTK_STOCK_APPLY); STOCK_ITEMIZE(_("Close"), GTK_STOCK_CLOSE); STOCK_ITEMIZE(_("Delete"), GTK_STOCK_DELETE); STOCK_ITEMIZE(_("Add"), GTK_STOCK_ADD); STOCK_ITEMIZE(_("Remove"), GTK_STOCK_REMOVE); STOCK_ITEMIZE(_("Save"), GTK_STOCK_SAVE); STOCK_ITEMIZE(_("Alias"), GAIM_STOCK_ALIAS); gaim_gtk_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, GaimGtkRequestData *data; char *primary_esc, *secondary_esc; data = g_new0(GaimGtkRequestData, 1); data->type = GAIM_REQUEST_INPUT; data->user_data = user_data; data->cbs = g_new0(GCallback, 2); data->cbs[1] = cancel_cb; dialog = gtk_dialog_new_with_buttons(title ? title : GAIM_ALERT_TITLE, text_to_stock(cancel_text), 1, text_to_stock(ok_text), 0, g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(input_response_cb), data); gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0); gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); /* Setup the main horizontal box */ hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, gtk_misc_set_alignment(GTK_MISC(img), 0, 0); gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" "%s</span>%s%s" : "%s%s%s"), (primary ? primary_esc : ""), ((primary && secondary) ? "\n\n" : ""), (secondary ? secondary_esc : "")); label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label), label_text); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); data->u.input.multiline = multiline; data->u.input.hint = (hint == NULL ? NULL : g_strdup(hint)); if ((data->u.input.hint != NULL) && (!strcmp(data->u.input.hint, "html"))) { frame = gaim_gtk_create_imhtml(TRUE, &entry, &toolbar, NULL); gtk_widget_set_size_request(entry, 320, 130); gtk_widget_set_name(entry, "gaim_gtkrequest_imhtml"); if (default_value != NULL) gtk_imhtml_append_text(GTK_IMHTML(entry), default_value, GTK_IMHTML_NO_SCROLL); gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), gtk_widget_set_size_request(sw, 320, 130); entry = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(entry), TRUE); if (default_value != NULL) { buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)); gtk_text_buffer_set_text(buffer, default_value, -1); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(entry), GTK_WRAP_WORD_CHAR); gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); if (gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck")) gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(entry)); gtk_container_add(GTK_CONTAINER(sw), entry); gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0); if (default_value != NULL) gtk_entry_set_text(GTK_ENTRY(entry), default_value); gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); gtk_entry_set_invisible_char(GTK_ENTRY(entry), GAIM_INVISIBLE_CHAR); gaim_set_accessible_label (entry, label); data->u.input.entry = entry; gtk_widget_show_all(dialog); gaim_gtk_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 args) GaimGtkRequestData *data; char *primary_esc, *secondary_esc; data = g_new0(GaimGtkRequestData, 1); data->type = GAIM_REQUEST_ACTION; data->user_data = user_data; data->cbs = g_new0(GCallback, 2); data->cbs[0] = cancel_cb; data->dialog = dialog = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(dialog), title); gtk_dialog_add_button(GTK_DIALOG(dialog), text_to_stock(cancel_text), 0); gtk_dialog_add_button(GTK_DIALOG(dialog), text_to_stock(ok_text), 1); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(choice_response_cb), data); gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); /* Setup the main horizontal box */ hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, gtk_misc_set_alignment(GTK_MISC(img), 0, 0); gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" "%s</span>%s%s" : "%s%s%s"), (primary ? primary_esc : ""), ((primary && secondary) ? "\n\n" : ""), (secondary ? secondary_esc : "")); label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label), label_text); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE); gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, 0); while ((radio_text = va_arg(args, char*))) { int resp = va_arg(args, int); radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), radio_text); gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(radio), "choice_id", GINT_TO_POINTER(resp)); if (resp == default_value) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); g_object_set_data(G_OBJECT(dialog), "radio", radio); gtk_widget_show_all(dialog); gaim_gtk_request_action(const char *title, const char *primary, const char *secondary, unsigned int default_action, void *user_data, size_t action_count, va_list actions) GaimGtkRequestData *data; char *primary_esc, *secondary_esc; data = g_new0(GaimGtkRequestData, 1); data->type = GAIM_REQUEST_ACTION; data->user_data = user_data; data->cb_count = action_count; data->cbs = g_new0(GCallback, action_count); /* Reverse the buttons */ buttons = g_new0(void *, action_count * 2); for (i = 0; i < action_count * 2; i += 2) { buttons[(action_count * 2) - i - 2] = va_arg(actions, char *); buttons[(action_count * 2) - i - 1] = va_arg(actions, GCallback); data->dialog = dialog = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(dialog), title); for (i = 0; i < action_count; i++) { gtk_dialog_add_button(GTK_DIALOG(dialog), text_to_stock(buttons[2 * i]), i); data->cbs[i] = buttons[2 * i + 1]; g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(action_response_cb), data); gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); /* Setup the main horizontal box */ hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, gtk_misc_set_alignment(GTK_MISC(img), 0, 0); gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" "%s</span>%s%s" : "%s%s%s"), (primary ? primary_esc : ""), ((primary && secondary) ? "\n\n" : ""), (secondary ? secondary_esc : "")); label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label), label_text); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); if (default_action == GAIM_DEFAULT_ACTION_NONE) { GTK_WIDGET_SET_FLAGS(img, GTK_CAN_DEFAULT); GTK_WIDGET_SET_FLAGS(img, GTK_CAN_FOCUS); gtk_widget_grab_focus(img); gtk_widget_grab_default(img); gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_action); gtk_widget_show_all(dialog); req_entry_field_changed_cb(GtkWidget *entry, GaimRequestField *field) GaimGtkRequestData *req_data; const char *text = gtk_entry_get_text(GTK_ENTRY(entry)); gaim_request_field_string_set_value(field, (*text == '\0' ? NULL : text)); req_data = (GaimGtkRequestData *)field->group->fields_list->ui_data; gtk_widget_set_sensitive(req_data->ok_button, gaim_request_fields_all_required_filled(field->group->fields_list)); setup_entry_field(GtkWidget *entry, GaimRequestField *field) gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); if (gaim_request_field_is_required(field)) g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(req_entry_field_changed_cb), field); if ((type_hint = gaim_request_field_get_type_hint(field)) != NULL) if (gaim_str_has_prefix(type_hint, "screenname")) GtkWidget *optmenu = NULL; GList *fields = field->group->fields; GaimRequestField *fld = fields->data; if (gaim_request_field_get_type(fld) == GAIM_REQUEST_FIELD_ACCOUNT) const char *type_hint = gaim_request_field_get_type_hint(fld); if (type_hint != NULL && strcmp(type_hint, "account") == 0) if (fld->ui_data == NULL) fld->ui_data = create_account_field(fld); optmenu = GTK_WIDGET(fld->ui_data); gaim_gtk_setup_screenname_autocomplete(entry, optmenu, !strcmp(type_hint, "screenname-all")); create_string_field(GaimRequestField *field) value = gaim_request_field_string_get_default_value(field); if (gaim_request_field_string_is_multiline(field)) widget = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(widget), gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); textview = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), if (gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck")) gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(textview)); gtk_container_add(GTK_CONTAINER(widget), textview); gtk_widget_show(textview); gtk_widget_set_size_request(widget, -1, 75); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); gtk_text_buffer_set_text(buffer, value, -1); gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), gaim_request_field_string_is_editable(field)); g_signal_connect(G_OBJECT(textview), "focus-out-event", G_CALLBACK(field_string_focus_out_cb), field); widget = gtk_entry_new(); setup_entry_field(widget, field); gtk_entry_set_text(GTK_ENTRY(widget), value); if (gaim_request_field_string_is_masked(field)) gtk_entry_set_visibility(GTK_ENTRY(widget), FALSE); gtk_entry_set_invisible_char(GTK_ENTRY(widget), GAIM_INVISIBLE_CHAR); gtk_editable_set_editable(GTK_EDITABLE(widget), gaim_request_field_string_is_editable(field)); g_signal_connect(G_OBJECT(widget), "focus-out-event", G_CALLBACK(field_string_focus_out_cb), field); create_int_field(GaimRequestField *field) widget = gtk_entry_new(); setup_entry_field(widget, field); value = gaim_request_field_int_get_default_value(field); g_snprintf(buf, sizeof(buf), "%d", value); gtk_entry_set_text(GTK_ENTRY(widget), buf); g_signal_connect(G_OBJECT(widget), "focus-out-event", G_CALLBACK(field_int_focus_out_cb), field); create_bool_field(GaimRequestField *field) widget = gtk_check_button_new_with_label( gaim_request_field_get_label(field)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), gaim_request_field_bool_get_default_value(field)); g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(field_bool_cb), field); create_choice_field(GaimRequestField *field) labels = gaim_request_field_choice_get_labels(field); if (g_list_length(labels) > 5) widget = gtk_option_menu_new(); for (l = labels; l != NULL; l = l->next) const char *text = l->data; item = gtk_menu_item_new_with_label(text); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), menu); gtk_option_menu_set_history(GTK_OPTION_MENU(widget), gaim_request_field_choice_get_default_value(field)); g_signal_connect(G_OBJECT(widget), "changed", G_CALLBACK(field_choice_menu_cb), field); GtkWidget *first_radio = NULL; if (g_list_length(labels) == 2) box = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); box = gtk_vbox_new(FALSE, 0); for (l = labels, i = 0; l != NULL; l = l->next, i++) const char *text = l->data; radio = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(first_radio), text); if (i == gaim_request_field_choice_get_default_value(field)) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); gtk_box_pack_start(GTK_BOX(box), radio, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(radio), "toggled", G_CALLBACK(field_choice_option_cb), field); create_image_field(GaimRequestField *field) loader = gdk_pixbuf_loader_new(); gdk_pixbuf_loader_write(loader, (const guchar *)gaim_request_field_image_get_buffer(field), gaim_request_field_image_get_size(field), gdk_pixbuf_loader_close(loader, NULL); buf = gdk_pixbuf_loader_get_pixbuf(loader); scale = gdk_pixbuf_scale_simple(buf, gaim_request_field_image_get_scale_x(field) * gdk_pixbuf_get_width(buf), gaim_request_field_image_get_scale_y(field) * gdk_pixbuf_get_height(buf), widget = gtk_image_new_from_pixbuf(scale); g_object_unref(G_OBJECT(buf)); g_object_unref(G_OBJECT(scale)); create_account_field(GaimRequestField *field) widget = gaim_gtk_account_option_menu_new( gaim_request_field_account_get_default_value(field), gaim_request_field_account_get_show_all(field), G_CALLBACK(field_account_cb), gaim_request_field_account_get_filter(field), select_field_list_item(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) GaimRequestField *field = (GaimRequestField *)data; gtk_tree_model_get(model, iter, 1, &text, -1); gaim_request_field_list_add_selected(field, text); list_field_select_changed_cb(GtkTreeSelection *sel, GaimRequestField *field) gaim_request_field_list_clear_selected(field); gtk_tree_selection_selected_foreach(sel, select_field_list_item, field); create_list_field(GaimRequestField *field) GtkCellRenderer *renderer; GtkTreeViewColumn *column; /* Create the scrolled window */ sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), /* Create the list store */ store = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING); /* Create the tree view */ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); if (gaim_request_field_list_get_multi_select(field)) gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE); g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(list_field_select_changed_cb), field); column = gtk_tree_view_column_new(); gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(column, renderer, TRUE); gtk_tree_view_column_add_attribute(column, renderer, "text", 1); for (l = gaim_request_field_list_get_items(field); l != NULL; l = l->next) const char *text = (const char *)l->data; gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, gaim_request_field_list_get_data(field, text), if (gaim_request_field_list_is_selected(field, text)) gtk_tree_selection_select_iter(sel, &iter); gtk_container_add(GTK_CONTAINER(sw), treeview); gtk_widget_show(treeview); gaim_gtk_request_fields(const char *title, const char *primary, const char *secondary, GaimRequestFields *fields, const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, GaimGtkRequestData *data; GaimRequestFieldGroup *group; char *primary_esc, *secondary_esc; data = g_new0(GaimGtkRequestData, 1); data->type = GAIM_REQUEST_FIELDS; data->user_data = user_data; data->u.multifield.fields = fields; data->cbs = g_new0(GCallback, 2); data->cbs[1] = cancel_cb; data->dialog = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(win), title); gtk_window_set_role(GTK_WINDOW(win), "multifield"); gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER); gtk_window_set_resizable(GTK_WINDOW(win), FALSE); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(destroy_multifield_cb), data); /* Setup the main horizontal box */ hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); gtk_container_add(GTK_CONTAINER(win), hbox); img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, gtk_misc_set_alignment(GTK_MISC(img), 0, 0); gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); primary_esc = g_markup_escape_text(primary, -1); label_text = g_strdup_printf( "<span weight=\"bold\" size=\"larger\">%s</span>", primary_esc); label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label), label_text); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); for (gl = gaim_request_fields_get_groups(fields); gl != NULL; total_fields += g_list_length(gaim_request_field_group_get_fields(gl->data)); sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), gtk_widget_set_size_request(sw, -1, 200); gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), vbox2); secondary_esc = g_markup_escape_text(secondary, -1); label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label), secondary_esc); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, TRUE, 0); for (gl = gaim_request_fields_get_groups(fields); field_list = gaim_request_field_group_get_fields(group); if (gaim_request_field_group_get_title(group) != NULL) frame = gaim_gtk_make_frame(vbox2, gaim_request_field_group_get_title(group)); field_count = g_list_length(field_list); for (fl = field_list; fl != NULL; fl = fl->next) GaimRequestFieldType type; field = (GaimRequestField *)fl->data; type = gaim_request_field_get_type(field); if (type == GAIM_REQUEST_FIELD_LABEL) else if ((type == GAIM_REQUEST_FIELD_LIST) || (type == GAIM_REQUEST_FIELD_STRING && gaim_request_field_string_is_multiline(field))) table = gtk_table_new(rows, 2 * cols, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE); gtk_table_set_col_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE); gtk_container_add(GTK_CONTAINER(frame), table); for (row_num = 0, fl = field_list; row_num < rows && fl != NULL; col_num < cols && fl != NULL; col_num++, fl = fl->next) size_t col_offset = col_num * 2; GaimRequestFieldType type; GtkWidget *widget = NULL; if (!gaim_request_field_is_visible(field)) { type = gaim_request_field_get_type(field); if (type != GAIM_REQUEST_FIELD_BOOLEAN && gaim_request_field_get_label(field)) text = g_strdup_printf("%s:", gaim_request_field_get_label(field)); label = gtk_label_new(NULL); gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), text); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_size_group_add_widget(sg, label); if (type == GAIM_REQUEST_FIELD_LABEL || type == GAIM_REQUEST_FIELD_LIST || (type == GAIM_REQUEST_FIELD_STRING && gaim_request_field_string_is_multiline(field))) gtk_table_attach_defaults(GTK_TABLE(table), label, gtk_table_attach_defaults(GTK_TABLE(table), label, col_offset, col_offset + 1, if (field->ui_data != NULL) widget = GTK_WIDGET(field->ui_data); else if (type == GAIM_REQUEST_FIELD_STRING) widget = create_string_field(field); else if (type == GAIM_REQUEST_FIELD_INTEGER) widget = create_int_field(field); else if (type == GAIM_REQUEST_FIELD_BOOLEAN) widget = create_bool_field(field); else if (type == GAIM_REQUEST_FIELD_CHOICE) widget = create_choice_field(field); else if (type == GAIM_REQUEST_FIELD_LIST) widget = create_list_field(field); else if (type == GAIM_REQUEST_FIELD_IMAGE) widget = create_image_field(field); else if (type == GAIM_REQUEST_FIELD_ACCOUNT) widget = create_account_field(field); gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget); if (type == GAIM_REQUEST_FIELD_STRING && gaim_request_field_string_is_multiline(field)) gtk_table_attach(GTK_TABLE(table), widget, else if (type == GAIM_REQUEST_FIELD_LIST) gtk_table_attach(GTK_TABLE(table), widget, else if (type == GAIM_REQUEST_FIELD_BOOLEAN) gtk_table_attach(GTK_TABLE(table), widget, col_offset, col_offset + 1, gtk_table_attach(GTK_TABLE(table), widget, bbox = gtk_hbutton_box_new(); gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE); gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); button = gtk_button_new_from_stock(text_to_stock(cancel_text)); gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(multifield_cancel_cb), data); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); button = gtk_button_new_from_stock(text_to_stock(ok_text)); gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); data->ok_button = button; GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_window_set_default(GTK_WINDOW(win), button); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(multifield_ok_cb), data); if (!gaim_request_fields_all_required_filled(fields)) gtk_widget_set_sensitive(button, FALSE); file_yes_no_cb(GaimGtkRequestData *data, gint id) /* Only call the callback if yes was selected, otherwise the request * (eg. file transfer) will be cancelled, then when a new filename is chosen if (data->cbs[1] != NULL) ((GaimRequestFileCb)data->cbs[1])(data->user_data, data->u.file.name); gaim_request_close(data->type, data); gaim_gtk_clear_cursor(GTK_WIDGET(data->dialog)); #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ file_ok_check_if_exists_cb(GtkWidget *widget, gint response, GaimGtkRequestData *data) generic_response_start(data); if (response != GTK_RESPONSE_ACCEPT) { if (data->cbs[0] != NULL) ((GaimRequestFileCb)data->cbs[0])(data->user_data, NULL); gaim_request_close(data->type, data); data->u.file.name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(data->dialog)); current_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(data->dialog)); if (current_folder != NULL) { if (data->u.file.savedialog) { gaim_prefs_set_string("/gaim/gtk/filelocations/last_save_folder", current_folder); gaim_prefs_set_string("/gaim/gtk/filelocations/last_open_folder", current_folder); file_ok_check_if_exists_cb(GtkWidget *button, GaimGtkRequestData *data) generic_response_start(data); name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(data->dialog)); /* If name is a directory then change directories */ if (data->type == GAIM_REQUEST_FILE) { if (gaim_gtk_check_if_dir(name, GTK_FILE_SELECTION(data->dialog))) current_folder = g_path_get_dirname(name); g_free(data->u.file.name); if (data->type == GAIM_REQUEST_FILE) data->u.file.name = g_strdup(name); if (g_file_test(name, G_FILE_TEST_IS_DIR)) data->u.file.name = g_strdup(name); data->u.file.name = g_strdup(current_folder); if (current_folder != NULL) { if (data->u.file.savedialog) { gaim_prefs_set_string("/gaim/gtk/filelocations/last_save_folder", current_folder); gaim_prefs_set_string("/gaim/gtk/filelocations/last_open_folder", current_folder); if ((data->u.file.savedialog == TRUE) && (g_file_test(data->u.file.name, G_FILE_TEST_EXISTS))) { gaim_request_action(data, NULL, _("That file already exists"), _("Would you like to overwrite it?"), 0, data, 2, _("Overwrite"), G_CALLBACK(file_yes_no_cb), _("Choose New Name"), G_CALLBACK(file_yes_no_cb)); #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ file_cancel_cb(GaimGtkRequestData *data) generic_response_start(data); if (data->cbs[0] != NULL) ((GaimRequestFileCb)data->cbs[0])(data->user_data, NULL); gaim_request_close(data->type, data); gaim_gtk_request_file(const char *title, const char *filename, GCallback ok_cb, GCallback cancel_cb, GaimGtkRequestData *data; const gchar *current_folder; #if GTK_CHECK_VERSION(2,4,0) gboolean folder_set = FALSE; data = g_new0(GaimGtkRequestData, 1); data->type = GAIM_REQUEST_FILE; data->user_data = user_data; data->cbs = g_new0(GCallback, 2); data->cbs[0] = cancel_cb; data->u.file.savedialog = savedialog; #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ filesel = gtk_file_chooser_dialog_new( title ? title : (savedialog ? _("Save File...") savedialog ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, savedialog ? GTK_STOCK_SAVE gtk_dialog_set_default_response(GTK_DIALOG(filesel), GTK_RESPONSE_ACCEPT); current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_save_folder"); current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_open_folder"); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(filesel), filename); if ((current_folder != NULL) && (*current_folder != '\0')) { folder_set = gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filesel), current_folder); char *my_documents = wgaim_get_special_folder(CSIDL_PERSONAL); if (my_documents != NULL) { gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(filesel), my_documents); g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(filesel)), "response", G_CALLBACK(file_ok_check_if_exists_cb), data); filesel = gtk_file_selection_new( title ? title : (savedialog ? _("Save File...") current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_save_folder"); current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_open_folder"); if (current_folder != NULL) { gchar *path = g_strdup_printf("%s%s", current_folder, G_DIR_SEPARATOR_S); gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), path); gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), filename); g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(filesel)), "delete_event", G_CALLBACK(file_cancel_cb), data); g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(filesel)->cancel_button), "clicked", G_CALLBACK(file_cancel_cb), data); g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked", G_CALLBACK(file_ok_check_if_exists_cb), data); gtk_widget_show(filesel); gaim_gtk_request_folder(const char *title, const char *dirname, GCallback ok_cb, GCallback cancel_cb, GaimGtkRequestData *data; data = g_new0(GaimGtkRequestData, 1); data->type = GAIM_REQUEST_FOLDER; data->user_data = user_data; data->cbs = g_new0(GCallback, 2); data->cbs[0] = cancel_cb; data->u.file.savedialog = FALSE; #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ dirsel = gtk_file_chooser_dialog_new( title ? title : _("Select Folder..."), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, gtk_dialog_set_default_response(GTK_DIALOG(dirsel), GTK_RESPONSE_ACCEPT); if ((dirname != NULL) && (*dirname != '\0')) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dirsel), dirname); g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(dirsel)), "response", G_CALLBACK(file_ok_check_if_exists_cb), data); dirsel = gtk_file_selection_new(title ? title : _("Select Folder...")); g_signal_connect_swapped(G_OBJECT(dirsel), "delete_event", G_CALLBACK(file_cancel_cb), data); g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(dirsel)->cancel_button), "clicked", G_CALLBACK(file_cancel_cb), data); g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(dirsel)->ok_button), "clicked", G_CALLBACK(file_ok_check_if_exists_cb), data); gaim_gtk_close_request(GaimRequestType type, void *ui_handle) GaimGtkRequestData *data = (GaimGtkRequestData *)ui_handle; gtk_widget_destroy(data->dialog); if (type == GAIM_REQUEST_FIELDS) gaim_request_fields_destroy(data->u.multifield.fields); else if (type == GAIM_REQUEST_FILE) g_free(data->u.file.name); static GaimRequestUiOps ops = gaim_gtk_request_get_ui_ops(void)