| 1 /** |
|
| 2 * @file gtkrequest.c GTK+ Request API |
|
| 3 * @ingroup gtkui |
|
| 4 * |
|
| 5 * gaim |
|
| 6 * |
|
| 7 * Gaim is the legal property of its developers, whose names are too numerous |
|
| 8 * to list here. Please refer to the COPYRIGHT file distributed with this |
|
| 9 * source distribution. |
|
| 10 * |
|
| 11 * This program is free software; you can redistribute it and/or modify |
|
| 12 * it under the terms of the GNU General Public License as published by |
|
| 13 * the Free Software Foundation; either version 2 of the License, or |
|
| 14 * (at your option) any later version. |
|
| 15 * |
|
| 16 * This program is distributed in the hope that it will be useful, |
|
| 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 19 * GNU General Public License for more details. |
|
| 20 * |
|
| 21 * You should have received a copy of the GNU General Public License |
|
| 22 * along with this program; if not, write to the Free Software |
|
| 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
| 24 */ |
|
| 25 #include "internal.h" |
|
| 26 #include "gtkgaim.h" |
|
| 27 |
|
| 28 #include "prefs.h" |
|
| 29 #include "util.h" |
|
| 30 |
|
| 31 #include "gtkimhtml.h" |
|
| 32 #include "gtkimhtmltoolbar.h" |
|
| 33 #include "gtkrequest.h" |
|
| 34 #include "gtkutils.h" |
|
| 35 #include "gtkstock.h" |
|
| 36 |
|
| 37 #include <gdk/gdkkeysyms.h> |
|
| 38 |
|
| 39 static GtkWidget * create_account_field(GaimRequestField *field); |
|
| 40 |
|
| 41 typedef struct |
|
| 42 { |
|
| 43 GaimRequestType type; |
|
| 44 |
|
| 45 void *user_data; |
|
| 46 GtkWidget *dialog; |
|
| 47 |
|
| 48 GtkWidget *ok_button; |
|
| 49 |
|
| 50 size_t cb_count; |
|
| 51 GCallback *cbs; |
|
| 52 |
|
| 53 union |
|
| 54 { |
|
| 55 struct |
|
| 56 { |
|
| 57 GtkWidget *entry; |
|
| 58 |
|
| 59 gboolean multiline; |
|
| 60 gchar *hint; |
|
| 61 |
|
| 62 } input; |
|
| 63 |
|
| 64 struct |
|
| 65 { |
|
| 66 GaimRequestFields *fields; |
|
| 67 |
|
| 68 } multifield; |
|
| 69 |
|
| 70 struct |
|
| 71 { |
|
| 72 gboolean savedialog; |
|
| 73 gchar *name; |
|
| 74 |
|
| 75 } file; |
|
| 76 |
|
| 77 } u; |
|
| 78 |
|
| 79 } GaimGtkRequestData; |
|
| 80 |
|
| 81 static void |
|
| 82 generic_response_start(GaimGtkRequestData *data) |
|
| 83 { |
|
| 84 g_return_if_fail(data != NULL); |
|
| 85 |
|
| 86 /* Tell the user we're doing something. */ |
|
| 87 gaim_gtk_set_cursor(GTK_WIDGET(data->dialog), GDK_WATCH); |
|
| 88 } |
|
| 89 |
|
| 90 static void |
|
| 91 input_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) |
|
| 92 { |
|
| 93 const char *value; |
|
| 94 char *multiline_value = NULL; |
|
| 95 |
|
| 96 generic_response_start(data); |
|
| 97 |
|
| 98 if (data->u.input.multiline) { |
|
| 99 GtkTextIter start_iter, end_iter; |
|
| 100 GtkTextBuffer *buffer = |
|
| 101 gtk_text_view_get_buffer(GTK_TEXT_VIEW(data->u.input.entry)); |
|
| 102 |
|
| 103 gtk_text_buffer_get_start_iter(buffer, &start_iter); |
|
| 104 gtk_text_buffer_get_end_iter(buffer, &end_iter); |
|
| 105 |
|
| 106 if ((data->u.input.hint != NULL) && (!strcmp(data->u.input.hint, "html"))) |
|
| 107 multiline_value = gtk_imhtml_get_markup(GTK_IMHTML(data->u.input.entry)); |
|
| 108 else |
|
| 109 multiline_value = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, |
|
| 110 FALSE); |
|
| 111 |
|
| 112 value = multiline_value; |
|
| 113 } |
|
| 114 else |
|
| 115 value = gtk_entry_get_text(GTK_ENTRY(data->u.input.entry)); |
|
| 116 |
|
| 117 if (id < data->cb_count && data->cbs[id] != NULL) |
|
| 118 ((GaimRequestInputCb)data->cbs[id])(data->user_data, value); |
|
| 119 else if (data->cbs[1] != NULL) |
|
| 120 ((GaimRequestInputCb)data->cbs[1])(data->user_data, value); |
|
| 121 |
|
| 122 if (data->u.input.multiline) |
|
| 123 g_free(multiline_value); |
|
| 124 |
|
| 125 gaim_request_close(GAIM_REQUEST_INPUT, data); |
|
| 126 } |
|
| 127 |
|
| 128 static void |
|
| 129 action_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) |
|
| 130 { |
|
| 131 generic_response_start(data); |
|
| 132 |
|
| 133 if (id < data->cb_count && data->cbs[id] != NULL) |
|
| 134 ((GaimRequestActionCb)data->cbs[id])(data->user_data, id); |
|
| 135 |
|
| 136 gaim_request_close(GAIM_REQUEST_INPUT, data); |
|
| 137 } |
|
| 138 |
|
| 139 |
|
| 140 static void |
|
| 141 choice_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data) |
|
| 142 { |
|
| 143 GtkWidget *radio = g_object_get_data(G_OBJECT(dialog), "radio"); |
|
| 144 GSList *group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); |
|
| 145 |
|
| 146 generic_response_start(data); |
|
| 147 |
|
| 148 if (id < data->cb_count && data->cbs[id] != NULL) |
|
| 149 while (group) { |
|
| 150 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group->data))) { |
|
| 151 ((GaimRequestChoiceCb)data->cbs[id])(data->user_data, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(group->data), "choice_id"))); |
|
| 152 break; |
|
| 153 } |
|
| 154 group = group->next; |
|
| 155 } |
|
| 156 gaim_request_close(GAIM_REQUEST_INPUT, data); |
|
| 157 } |
|
| 158 |
|
| 159 static gboolean |
|
| 160 field_string_focus_out_cb(GtkWidget *entry, GdkEventFocus *event, |
|
| 161 GaimRequestField *field) |
|
| 162 { |
|
| 163 const char *value; |
|
| 164 |
|
| 165 if (gaim_request_field_string_is_multiline(field)) |
|
| 166 { |
|
| 167 GtkTextBuffer *buffer; |
|
| 168 GtkTextIter start_iter, end_iter; |
|
| 169 |
|
| 170 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)); |
|
| 171 |
|
| 172 gtk_text_buffer_get_start_iter(buffer, &start_iter); |
|
| 173 gtk_text_buffer_get_end_iter(buffer, &end_iter); |
|
| 174 |
|
| 175 value = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE); |
|
| 176 } |
|
| 177 else |
|
| 178 value = gtk_entry_get_text(GTK_ENTRY(entry)); |
|
| 179 |
|
| 180 gaim_request_field_string_set_value(field, |
|
| 181 (*value == '\0' ? NULL : value)); |
|
| 182 |
|
| 183 return FALSE; |
|
| 184 } |
|
| 185 |
|
| 186 static gboolean |
|
| 187 field_int_focus_out_cb(GtkEntry *entry, GdkEventFocus *event, |
|
| 188 GaimRequestField *field) |
|
| 189 { |
|
| 190 gaim_request_field_int_set_value(field, |
|
| 191 atoi(gtk_entry_get_text(entry))); |
|
| 192 |
|
| 193 return FALSE; |
|
| 194 } |
|
| 195 |
|
| 196 static void |
|
| 197 field_bool_cb(GtkToggleButton *button, GaimRequestField *field) |
|
| 198 { |
|
| 199 gaim_request_field_bool_set_value(field, |
|
| 200 gtk_toggle_button_get_active(button)); |
|
| 201 } |
|
| 202 |
|
| 203 static void |
|
| 204 field_choice_menu_cb(GtkOptionMenu *menu, GaimRequestField *field) |
|
| 205 { |
|
| 206 gaim_request_field_choice_set_value(field, |
|
| 207 gtk_option_menu_get_history(menu)); |
|
| 208 } |
|
| 209 |
|
| 210 static void |
|
| 211 field_choice_option_cb(GtkRadioButton *button, GaimRequestField *field) |
|
| 212 { |
|
| 213 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) |
|
| 214 gaim_request_field_choice_set_value(field, |
|
| 215 (g_slist_length(gtk_radio_button_get_group(button)) - |
|
| 216 g_slist_index(gtk_radio_button_get_group(button), button)) - 1); |
|
| 217 } |
|
| 218 |
|
| 219 static void |
|
| 220 field_account_cb(GObject *w, GaimAccount *account, GaimRequestField *field) |
|
| 221 { |
|
| 222 gaim_request_field_account_set_value(field, account); |
|
| 223 } |
|
| 224 |
|
| 225 static void |
|
| 226 multifield_ok_cb(GtkWidget *button, GaimGtkRequestData *data) |
|
| 227 { |
|
| 228 generic_response_start(data); |
|
| 229 |
|
| 230 if (!GTK_WIDGET_HAS_FOCUS(button)) |
|
| 231 gtk_widget_grab_focus(button); |
|
| 232 |
|
| 233 if (data->cbs[0] != NULL) |
|
| 234 ((GaimRequestFieldsCb)data->cbs[0])(data->user_data, |
|
| 235 data->u.multifield.fields); |
|
| 236 |
|
| 237 gaim_request_close(GAIM_REQUEST_FIELDS, data); |
|
| 238 } |
|
| 239 |
|
| 240 static void |
|
| 241 multifield_cancel_cb(GtkWidget *button, GaimGtkRequestData *data) |
|
| 242 { |
|
| 243 generic_response_start(data); |
|
| 244 |
|
| 245 if (data->cbs[1] != NULL) |
|
| 246 ((GaimRequestFieldsCb)data->cbs[1])(data->user_data, |
|
| 247 data->u.multifield.fields); |
|
| 248 |
|
| 249 gaim_request_close(GAIM_REQUEST_FIELDS, data); |
|
| 250 } |
|
| 251 |
|
| 252 static void |
|
| 253 destroy_multifield_cb(GtkWidget *dialog, GdkEvent *event, |
|
| 254 GaimGtkRequestData *data) |
|
| 255 { |
|
| 256 multifield_cancel_cb(NULL, data); |
|
| 257 } |
|
| 258 |
|
| 259 |
|
| 260 #define STOCK_ITEMIZE(r, l) \ |
|
| 261 if (!strcmp((r), text)) \ |
|
| 262 return (l); |
|
| 263 |
|
| 264 static const char * |
|
| 265 text_to_stock(const char *text) |
|
| 266 { |
|
| 267 STOCK_ITEMIZE(_("Yes"), GTK_STOCK_YES); |
|
| 268 STOCK_ITEMIZE(_("No"), GTK_STOCK_NO); |
|
| 269 STOCK_ITEMIZE(_("OK"), GTK_STOCK_OK); |
|
| 270 STOCK_ITEMIZE(_("Cancel"), GTK_STOCK_CANCEL); |
|
| 271 STOCK_ITEMIZE(_("Apply"), GTK_STOCK_APPLY); |
|
| 272 STOCK_ITEMIZE(_("Close"), GTK_STOCK_CLOSE); |
|
| 273 STOCK_ITEMIZE(_("Delete"), GTK_STOCK_DELETE); |
|
| 274 STOCK_ITEMIZE(_("Add"), GTK_STOCK_ADD); |
|
| 275 STOCK_ITEMIZE(_("Remove"), GTK_STOCK_REMOVE); |
|
| 276 STOCK_ITEMIZE(_("Save"), GTK_STOCK_SAVE); |
|
| 277 STOCK_ITEMIZE(_("Alias"), GAIM_STOCK_ALIAS); |
|
| 278 |
|
| 279 return text; |
|
| 280 } |
|
| 281 |
|
| 282 static void * |
|
| 283 gaim_gtk_request_input(const char *title, const char *primary, |
|
| 284 const char *secondary, const char *default_value, |
|
| 285 gboolean multiline, gboolean masked, gchar *hint, |
|
| 286 const char *ok_text, GCallback ok_cb, |
|
| 287 const char *cancel_text, GCallback cancel_cb, |
|
| 288 void *user_data) |
|
| 289 { |
|
| 290 GaimGtkRequestData *data; |
|
| 291 GtkWidget *dialog; |
|
| 292 GtkWidget *vbox; |
|
| 293 GtkWidget *hbox; |
|
| 294 GtkWidget *label; |
|
| 295 GtkWidget *entry; |
|
| 296 GtkWidget *img; |
|
| 297 GtkWidget *toolbar; |
|
| 298 char *label_text; |
|
| 299 char *primary_esc, *secondary_esc; |
|
| 300 |
|
| 301 data = g_new0(GaimGtkRequestData, 1); |
|
| 302 data->type = GAIM_REQUEST_INPUT; |
|
| 303 data->user_data = user_data; |
|
| 304 |
|
| 305 data->cb_count = 2; |
|
| 306 data->cbs = g_new0(GCallback, 2); |
|
| 307 |
|
| 308 data->cbs[0] = ok_cb; |
|
| 309 data->cbs[1] = cancel_cb; |
|
| 310 |
|
| 311 /* Create the dialog. */ |
|
| 312 dialog = gtk_dialog_new_with_buttons(title ? title : GAIM_ALERT_TITLE, |
|
| 313 NULL, 0, |
|
| 314 text_to_stock(cancel_text), 1, |
|
| 315 text_to_stock(ok_text), 0, |
|
| 316 NULL); |
|
| 317 data->dialog = dialog; |
|
| 318 |
|
| 319 g_signal_connect(G_OBJECT(dialog), "response", |
|
| 320 G_CALLBACK(input_response_cb), data); |
|
| 321 |
|
| 322 /* Setup the dialog */ |
|
| 323 gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); |
|
| 324 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); |
|
| 325 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); |
|
| 326 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); |
|
| 327 gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0); |
|
| 328 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); |
|
| 329 |
|
| 330 /* Setup the main horizontal box */ |
|
| 331 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
|
| 332 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); |
|
| 333 |
|
| 334 /* Dialog icon. */ |
|
| 335 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
|
| 336 GTK_ICON_SIZE_DIALOG); |
|
| 337 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); |
|
| 338 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); |
|
| 339 |
|
| 340 /* Vertical box */ |
|
| 341 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
|
| 342 |
|
| 343 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); |
|
| 344 |
|
| 345 /* Descriptive label */ |
|
| 346 primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; |
|
| 347 secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; |
|
| 348 label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" |
|
| 349 "%s</span>%s%s" : "%s%s%s"), |
|
| 350 (primary ? primary_esc : ""), |
|
| 351 ((primary && secondary) ? "\n\n" : ""), |
|
| 352 (secondary ? secondary_esc : "")); |
|
| 353 g_free(primary_esc); |
|
| 354 g_free(secondary_esc); |
|
| 355 |
|
| 356 label = gtk_label_new(NULL); |
|
| 357 |
|
| 358 gtk_label_set_markup(GTK_LABEL(label), label_text); |
|
| 359 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
|
| 360 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
|
| 361 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); |
|
| 362 |
|
| 363 g_free(label_text); |
|
| 364 |
|
| 365 /* Entry field. */ |
|
| 366 data->u.input.multiline = multiline; |
|
| 367 data->u.input.hint = (hint == NULL ? NULL : g_strdup(hint)); |
|
| 368 |
|
| 369 if ((data->u.input.hint != NULL) && (!strcmp(data->u.input.hint, "html"))) { |
|
| 370 GtkWidget *frame; |
|
| 371 |
|
| 372 /* imhtml */ |
|
| 373 frame = gaim_gtk_create_imhtml(TRUE, &entry, &toolbar, NULL); |
|
| 374 gtk_widget_set_size_request(entry, 320, 130); |
|
| 375 gtk_widget_set_name(entry, "gaim_gtkrequest_imhtml"); |
|
| 376 if (default_value != NULL) |
|
| 377 gtk_imhtml_append_text(GTK_IMHTML(entry), default_value, GTK_IMHTML_NO_SCROLL); |
|
| 378 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); |
|
| 379 gtk_widget_show(frame); |
|
| 380 } |
|
| 381 else { |
|
| 382 if (multiline) { |
|
| 383 GtkWidget *sw; |
|
| 384 |
|
| 385 sw = gtk_scrolled_window_new(NULL, NULL); |
|
| 386 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), |
|
| 387 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); |
|
| 388 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), |
|
| 389 GTK_SHADOW_IN); |
|
| 390 |
|
| 391 gtk_widget_set_size_request(sw, 320, 130); |
|
| 392 |
|
| 393 /* GtkTextView */ |
|
| 394 entry = gtk_text_view_new(); |
|
| 395 gtk_text_view_set_editable(GTK_TEXT_VIEW(entry), TRUE); |
|
| 396 |
|
| 397 if (default_value != NULL) { |
|
| 398 GtkTextBuffer *buffer; |
|
| 399 |
|
| 400 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)); |
|
| 401 gtk_text_buffer_set_text(buffer, default_value, -1); |
|
| 402 } |
|
| 403 |
|
| 404 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(entry), GTK_WRAP_WORD_CHAR); |
|
| 405 |
|
| 406 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); |
|
| 407 |
|
| 408 if (gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck")) |
|
| 409 gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(entry)); |
|
| 410 |
|
| 411 gtk_container_add(GTK_CONTAINER(sw), entry); |
|
| 412 } |
|
| 413 else { |
|
| 414 entry = gtk_entry_new(); |
|
| 415 |
|
| 416 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); |
|
| 417 |
|
| 418 gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0); |
|
| 419 |
|
| 420 if (default_value != NULL) |
|
| 421 gtk_entry_set_text(GTK_ENTRY(entry), default_value); |
|
| 422 |
|
| 423 if (masked) |
|
| 424 { |
|
| 425 gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); |
|
| 426 gtk_entry_set_invisible_char(GTK_ENTRY(entry), GAIM_INVISIBLE_CHAR); |
|
| 427 } |
|
| 428 } |
|
| 429 } |
|
| 430 |
|
| 431 gaim_set_accessible_label (entry, label); |
|
| 432 data->u.input.entry = entry; |
|
| 433 |
|
| 434 /* Show everything. */ |
|
| 435 gtk_widget_show_all(dialog); |
|
| 436 |
|
| 437 return data; |
|
| 438 } |
|
| 439 |
|
| 440 static void * |
|
| 441 gaim_gtk_request_choice(const char *title, const char *primary, |
|
| 442 const char *secondary, unsigned int default_value, |
|
| 443 const char *ok_text, GCallback ok_cb, |
|
| 444 const char *cancel_text, GCallback cancel_cb, |
|
| 445 void *user_data, va_list args) |
|
| 446 { |
|
| 447 GaimGtkRequestData *data; |
|
| 448 GtkWidget *dialog; |
|
| 449 GtkWidget *vbox, *vbox2; |
|
| 450 GtkWidget *hbox; |
|
| 451 GtkWidget *label; |
|
| 452 GtkWidget *img; |
|
| 453 GtkWidget *radio = NULL; |
|
| 454 char *label_text; |
|
| 455 char *radio_text; |
|
| 456 char *primary_esc, *secondary_esc; |
|
| 457 |
|
| 458 data = g_new0(GaimGtkRequestData, 1); |
|
| 459 data->type = GAIM_REQUEST_ACTION; |
|
| 460 data->user_data = user_data; |
|
| 461 |
|
| 462 data->cb_count = 2; |
|
| 463 data->cbs = g_new0(GCallback, 2); |
|
| 464 data->cbs[0] = cancel_cb; |
|
| 465 data->cbs[1] = ok_cb; |
|
| 466 |
|
| 467 /* Create the dialog. */ |
|
| 468 data->dialog = dialog = gtk_dialog_new(); |
|
| 469 |
|
| 470 if (title != NULL) |
|
| 471 gtk_window_set_title(GTK_WINDOW(dialog), title); |
|
| 472 |
|
| 473 |
|
| 474 gtk_dialog_add_button(GTK_DIALOG(dialog), |
|
| 475 text_to_stock(cancel_text), 0); |
|
| 476 |
|
| 477 gtk_dialog_add_button(GTK_DIALOG(dialog), |
|
| 478 text_to_stock(ok_text), 1); |
|
| 479 |
|
| 480 g_signal_connect(G_OBJECT(dialog), "response", |
|
| 481 G_CALLBACK(choice_response_cb), data); |
|
| 482 |
|
| 483 /* Setup the dialog */ |
|
| 484 gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); |
|
| 485 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); |
|
| 486 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); |
|
| 487 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); |
|
| 488 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); |
|
| 489 |
|
| 490 /* Setup the main horizontal box */ |
|
| 491 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
|
| 492 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); |
|
| 493 |
|
| 494 /* Dialog icon. */ |
|
| 495 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
|
| 496 GTK_ICON_SIZE_DIALOG); |
|
| 497 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); |
|
| 498 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); |
|
| 499 |
|
| 500 /* Vertical box */ |
|
| 501 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
|
| 502 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); |
|
| 503 |
|
| 504 /* Descriptive label */ |
|
| 505 primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; |
|
| 506 secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; |
|
| 507 label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" |
|
| 508 "%s</span>%s%s" : "%s%s%s"), |
|
| 509 (primary ? primary_esc : ""), |
|
| 510 ((primary && secondary) ? "\n\n" : ""), |
|
| 511 (secondary ? secondary_esc : "")); |
|
| 512 g_free(primary_esc); |
|
| 513 g_free(secondary_esc); |
|
| 514 |
|
| 515 label = gtk_label_new(NULL); |
|
| 516 |
|
| 517 gtk_label_set_markup(GTK_LABEL(label), label_text); |
|
| 518 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
|
| 519 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
|
| 520 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); |
|
| 521 |
|
| 522 g_free(label_text); |
|
| 523 |
|
| 524 vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
|
| 525 gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, 0); |
|
| 526 while ((radio_text = va_arg(args, char*))) { |
|
| 527 int resp = va_arg(args, int); |
|
| 528 radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), radio_text); |
|
| 529 gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0); |
|
| 530 g_object_set_data(G_OBJECT(radio), "choice_id", GINT_TO_POINTER(resp)); |
|
| 531 if (resp == default_value) |
|
| 532 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); |
|
| 533 } |
|
| 534 |
|
| 535 g_object_set_data(G_OBJECT(dialog), "radio", radio); |
|
| 536 |
|
| 537 /* Show everything. */ |
|
| 538 gtk_widget_show_all(dialog); |
|
| 539 |
|
| 540 return data; |
|
| 541 } |
|
| 542 |
|
| 543 static void * |
|
| 544 gaim_gtk_request_action(const char *title, const char *primary, |
|
| 545 const char *secondary, unsigned int default_action, |
|
| 546 void *user_data, size_t action_count, va_list actions) |
|
| 547 { |
|
| 548 GaimGtkRequestData *data; |
|
| 549 GtkWidget *dialog; |
|
| 550 GtkWidget *vbox; |
|
| 551 GtkWidget *hbox; |
|
| 552 GtkWidget *label; |
|
| 553 GtkWidget *img; |
|
| 554 void **buttons; |
|
| 555 char *label_text; |
|
| 556 char *primary_esc, *secondary_esc; |
|
| 557 int i; |
|
| 558 |
|
| 559 data = g_new0(GaimGtkRequestData, 1); |
|
| 560 data->type = GAIM_REQUEST_ACTION; |
|
| 561 data->user_data = user_data; |
|
| 562 |
|
| 563 data->cb_count = action_count; |
|
| 564 data->cbs = g_new0(GCallback, action_count); |
|
| 565 |
|
| 566 /* Reverse the buttons */ |
|
| 567 buttons = g_new0(void *, action_count * 2); |
|
| 568 |
|
| 569 for (i = 0; i < action_count * 2; i += 2) { |
|
| 570 buttons[(action_count * 2) - i - 2] = va_arg(actions, char *); |
|
| 571 buttons[(action_count * 2) - i - 1] = va_arg(actions, GCallback); |
|
| 572 } |
|
| 573 |
|
| 574 /* Create the dialog. */ |
|
| 575 data->dialog = dialog = gtk_dialog_new(); |
|
| 576 |
|
| 577 if (title != NULL) |
|
| 578 gtk_window_set_title(GTK_WINDOW(dialog), title); |
|
| 579 |
|
| 580 for (i = 0; i < action_count; i++) { |
|
| 581 gtk_dialog_add_button(GTK_DIALOG(dialog), |
|
| 582 text_to_stock(buttons[2 * i]), i); |
|
| 583 |
|
| 584 data->cbs[i] = buttons[2 * i + 1]; |
|
| 585 } |
|
| 586 |
|
| 587 g_free(buttons); |
|
| 588 |
|
| 589 g_signal_connect(G_OBJECT(dialog), "response", |
|
| 590 G_CALLBACK(action_response_cb), data); |
|
| 591 |
|
| 592 /* Setup the dialog */ |
|
| 593 gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); |
|
| 594 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); |
|
| 595 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); |
|
| 596 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); |
|
| 597 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); |
|
| 598 |
|
| 599 /* Setup the main horizontal box */ |
|
| 600 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
|
| 601 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); |
|
| 602 |
|
| 603 /* Dialog icon. */ |
|
| 604 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
|
| 605 GTK_ICON_SIZE_DIALOG); |
|
| 606 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); |
|
| 607 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); |
|
| 608 |
|
| 609 /* Vertical box */ |
|
| 610 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
|
| 611 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); |
|
| 612 |
|
| 613 /* Descriptive label */ |
|
| 614 primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; |
|
| 615 secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; |
|
| 616 label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" |
|
| 617 "%s</span>%s%s" : "%s%s%s"), |
|
| 618 (primary ? primary_esc : ""), |
|
| 619 ((primary && secondary) ? "\n\n" : ""), |
|
| 620 (secondary ? secondary_esc : "")); |
|
| 621 g_free(primary_esc); |
|
| 622 g_free(secondary_esc); |
|
| 623 |
|
| 624 label = gtk_label_new(NULL); |
|
| 625 |
|
| 626 gtk_label_set_markup(GTK_LABEL(label), label_text); |
|
| 627 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
|
| 628 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
|
| 629 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); |
|
| 630 |
|
| 631 g_free(label_text); |
|
| 632 |
|
| 633 |
|
| 634 if (default_action == GAIM_DEFAULT_ACTION_NONE) { |
|
| 635 GTK_WIDGET_SET_FLAGS(img, GTK_CAN_DEFAULT); |
|
| 636 GTK_WIDGET_SET_FLAGS(img, GTK_CAN_FOCUS); |
|
| 637 gtk_widget_grab_focus(img); |
|
| 638 gtk_widget_grab_default(img); |
|
| 639 } else |
|
| 640 gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_action); |
|
| 641 |
|
| 642 /* Show everything. */ |
|
| 643 gtk_widget_show_all(dialog); |
|
| 644 |
|
| 645 return data; |
|
| 646 } |
|
| 647 |
|
| 648 static void |
|
| 649 req_entry_field_changed_cb(GtkWidget *entry, GaimRequestField *field) |
|
| 650 { |
|
| 651 GaimGtkRequestData *req_data; |
|
| 652 const char *text = gtk_entry_get_text(GTK_ENTRY(entry)); |
|
| 653 |
|
| 654 gaim_request_field_string_set_value(field, (*text == '\0' ? NULL : text)); |
|
| 655 |
|
| 656 req_data = (GaimGtkRequestData *)field->group->fields_list->ui_data; |
|
| 657 |
|
| 658 gtk_widget_set_sensitive(req_data->ok_button, |
|
| 659 gaim_request_fields_all_required_filled(field->group->fields_list)); |
|
| 660 } |
|
| 661 |
|
| 662 static void |
|
| 663 setup_entry_field(GtkWidget *entry, GaimRequestField *field) |
|
| 664 { |
|
| 665 const char *type_hint; |
|
| 666 |
|
| 667 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); |
|
| 668 |
|
| 669 if (gaim_request_field_is_required(field)) |
|
| 670 { |
|
| 671 g_signal_connect(G_OBJECT(entry), "changed", |
|
| 672 G_CALLBACK(req_entry_field_changed_cb), field); |
|
| 673 } |
|
| 674 |
|
| 675 if ((type_hint = gaim_request_field_get_type_hint(field)) != NULL) |
|
| 676 { |
|
| 677 if (gaim_str_has_prefix(type_hint, "screenname")) |
|
| 678 { |
|
| 679 GtkWidget *optmenu = NULL; |
|
| 680 GList *fields = field->group->fields; |
|
| 681 while (fields) |
|
| 682 { |
|
| 683 GaimRequestField *fld = fields->data; |
|
| 684 fields = fields->next; |
|
| 685 |
|
| 686 if (gaim_request_field_get_type(fld) == GAIM_REQUEST_FIELD_ACCOUNT) |
|
| 687 { |
|
| 688 const char *type_hint = gaim_request_field_get_type_hint(fld); |
|
| 689 if (type_hint != NULL && strcmp(type_hint, "account") == 0) |
|
| 690 { |
|
| 691 if (fld->ui_data == NULL) |
|
| 692 fld->ui_data = create_account_field(fld); |
|
| 693 optmenu = GTK_WIDGET(fld->ui_data); |
|
| 694 break; |
|
| 695 } |
|
| 696 } |
|
| 697 } |
|
| 698 gaim_gtk_setup_screenname_autocomplete(entry, optmenu, !strcmp(type_hint, "screenname-all")); |
|
| 699 } |
|
| 700 } |
|
| 701 } |
|
| 702 |
|
| 703 static GtkWidget * |
|
| 704 create_string_field(GaimRequestField *field) |
|
| 705 { |
|
| 706 const char *value; |
|
| 707 GtkWidget *widget; |
|
| 708 |
|
| 709 value = gaim_request_field_string_get_default_value(field); |
|
| 710 |
|
| 711 if (gaim_request_field_string_is_multiline(field)) |
|
| 712 { |
|
| 713 GtkWidget *textview; |
|
| 714 |
|
| 715 widget = gtk_scrolled_window_new(NULL, NULL); |
|
| 716 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(widget), |
|
| 717 GTK_SHADOW_IN); |
|
| 718 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), |
|
| 719 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); |
|
| 720 |
|
| 721 textview = gtk_text_view_new(); |
|
| 722 gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), |
|
| 723 TRUE); |
|
| 724 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), |
|
| 725 GTK_WRAP_WORD_CHAR); |
|
| 726 |
|
| 727 if (gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck")) |
|
| 728 gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(textview)); |
|
| 729 |
|
| 730 gtk_container_add(GTK_CONTAINER(widget), textview); |
|
| 731 gtk_widget_show(textview); |
|
| 732 |
|
| 733 gtk_widget_set_size_request(widget, -1, 75); |
|
| 734 |
|
| 735 if (value != NULL) |
|
| 736 { |
|
| 737 GtkTextBuffer *buffer; |
|
| 738 |
|
| 739 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); |
|
| 740 |
|
| 741 gtk_text_buffer_set_text(buffer, value, -1); |
|
| 742 } |
|
| 743 |
|
| 744 gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), |
|
| 745 gaim_request_field_string_is_editable(field)); |
|
| 746 |
|
| 747 g_signal_connect(G_OBJECT(textview), "focus-out-event", |
|
| 748 G_CALLBACK(field_string_focus_out_cb), field); |
|
| 749 } |
|
| 750 else |
|
| 751 { |
|
| 752 widget = gtk_entry_new(); |
|
| 753 |
|
| 754 setup_entry_field(widget, field); |
|
| 755 |
|
| 756 if (value != NULL) |
|
| 757 gtk_entry_set_text(GTK_ENTRY(widget), value); |
|
| 758 |
|
| 759 if (gaim_request_field_string_is_masked(field)) |
|
| 760 { |
|
| 761 gtk_entry_set_visibility(GTK_ENTRY(widget), FALSE); |
|
| 762 gtk_entry_set_invisible_char(GTK_ENTRY(widget), GAIM_INVISIBLE_CHAR); |
|
| 763 } |
|
| 764 |
|
| 765 gtk_editable_set_editable(GTK_EDITABLE(widget), |
|
| 766 gaim_request_field_string_is_editable(field)); |
|
| 767 |
|
| 768 g_signal_connect(G_OBJECT(widget), "focus-out-event", |
|
| 769 G_CALLBACK(field_string_focus_out_cb), field); |
|
| 770 } |
|
| 771 |
|
| 772 return widget; |
|
| 773 } |
|
| 774 |
|
| 775 static GtkWidget * |
|
| 776 create_int_field(GaimRequestField *field) |
|
| 777 { |
|
| 778 int value; |
|
| 779 GtkWidget *widget; |
|
| 780 |
|
| 781 widget = gtk_entry_new(); |
|
| 782 |
|
| 783 setup_entry_field(widget, field); |
|
| 784 |
|
| 785 value = gaim_request_field_int_get_default_value(field); |
|
| 786 |
|
| 787 if (value != 0) |
|
| 788 { |
|
| 789 char buf[32]; |
|
| 790 |
|
| 791 g_snprintf(buf, sizeof(buf), "%d", value); |
|
| 792 |
|
| 793 gtk_entry_set_text(GTK_ENTRY(widget), buf); |
|
| 794 } |
|
| 795 |
|
| 796 g_signal_connect(G_OBJECT(widget), "focus-out-event", |
|
| 797 G_CALLBACK(field_int_focus_out_cb), field); |
|
| 798 |
|
| 799 return widget; |
|
| 800 } |
|
| 801 |
|
| 802 static GtkWidget * |
|
| 803 create_bool_field(GaimRequestField *field) |
|
| 804 { |
|
| 805 GtkWidget *widget; |
|
| 806 |
|
| 807 widget = gtk_check_button_new_with_label( |
|
| 808 gaim_request_field_get_label(field)); |
|
| 809 |
|
| 810 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), |
|
| 811 gaim_request_field_bool_get_default_value(field)); |
|
| 812 |
|
| 813 g_signal_connect(G_OBJECT(widget), "toggled", |
|
| 814 G_CALLBACK(field_bool_cb), field); |
|
| 815 |
|
| 816 return widget; |
|
| 817 } |
|
| 818 |
|
| 819 static GtkWidget * |
|
| 820 create_choice_field(GaimRequestField *field) |
|
| 821 { |
|
| 822 GtkWidget *widget; |
|
| 823 GList *labels; |
|
| 824 GList *l; |
|
| 825 |
|
| 826 labels = gaim_request_field_choice_get_labels(field); |
|
| 827 |
|
| 828 if (g_list_length(labels) > 5) |
|
| 829 { |
|
| 830 GtkWidget *menu; |
|
| 831 GtkWidget *item; |
|
| 832 |
|
| 833 widget = gtk_option_menu_new(); |
|
| 834 |
|
| 835 menu = gtk_menu_new(); |
|
| 836 |
|
| 837 for (l = labels; l != NULL; l = l->next) |
|
| 838 { |
|
| 839 const char *text = l->data; |
|
| 840 |
|
| 841 item = gtk_menu_item_new_with_label(text); |
|
| 842 gtk_widget_show(item); |
|
| 843 |
|
| 844 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
|
| 845 } |
|
| 846 |
|
| 847 gtk_widget_show(menu); |
|
| 848 gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), menu); |
|
| 849 gtk_option_menu_set_history(GTK_OPTION_MENU(widget), |
|
| 850 gaim_request_field_choice_get_default_value(field)); |
|
| 851 |
|
| 852 g_signal_connect(G_OBJECT(widget), "changed", |
|
| 853 G_CALLBACK(field_choice_menu_cb), field); |
|
| 854 } |
|
| 855 else |
|
| 856 { |
|
| 857 GtkWidget *box; |
|
| 858 GtkWidget *first_radio = NULL; |
|
| 859 GtkWidget *radio; |
|
| 860 gint i; |
|
| 861 |
|
| 862 if (g_list_length(labels) == 2) |
|
| 863 box = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
|
| 864 else |
|
| 865 box = gtk_vbox_new(FALSE, 0); |
|
| 866 |
|
| 867 widget = box; |
|
| 868 |
|
| 869 for (l = labels, i = 0; l != NULL; l = l->next, i++) |
|
| 870 { |
|
| 871 const char *text = l->data; |
|
| 872 |
|
| 873 radio = gtk_radio_button_new_with_label_from_widget( |
|
| 874 GTK_RADIO_BUTTON(first_radio), text); |
|
| 875 |
|
| 876 if (first_radio == NULL) |
|
| 877 first_radio = radio; |
|
| 878 |
|
| 879 if (i == gaim_request_field_choice_get_default_value(field)) |
|
| 880 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); |
|
| 881 |
|
| 882 gtk_box_pack_start(GTK_BOX(box), radio, TRUE, TRUE, 0); |
|
| 883 gtk_widget_show(radio); |
|
| 884 |
|
| 885 g_signal_connect(G_OBJECT(radio), "toggled", |
|
| 886 G_CALLBACK(field_choice_option_cb), field); |
|
| 887 } |
|
| 888 } |
|
| 889 |
|
| 890 return widget; |
|
| 891 } |
|
| 892 |
|
| 893 static GtkWidget * |
|
| 894 create_image_field(GaimRequestField *field) |
|
| 895 { |
|
| 896 GtkWidget *widget; |
|
| 897 GdkPixbuf *buf, *scale; |
|
| 898 GdkPixbufLoader *loader; |
|
| 899 |
|
| 900 loader = gdk_pixbuf_loader_new(); |
|
| 901 gdk_pixbuf_loader_write(loader, |
|
| 902 (const guchar *)gaim_request_field_image_get_buffer(field), |
|
| 903 gaim_request_field_image_get_size(field), |
|
| 904 NULL); |
|
| 905 gdk_pixbuf_loader_close(loader, NULL); |
|
| 906 buf = gdk_pixbuf_loader_get_pixbuf(loader); |
|
| 907 |
|
| 908 scale = gdk_pixbuf_scale_simple(buf, |
|
| 909 gaim_request_field_image_get_scale_x(field) * gdk_pixbuf_get_width(buf), |
|
| 910 gaim_request_field_image_get_scale_y(field) * gdk_pixbuf_get_height(buf), |
|
| 911 GDK_INTERP_BILINEAR); |
|
| 912 widget = gtk_image_new_from_pixbuf(scale); |
|
| 913 g_object_unref(G_OBJECT(buf)); |
|
| 914 g_object_unref(G_OBJECT(scale)); |
|
| 915 |
|
| 916 return widget; |
|
| 917 } |
|
| 918 |
|
| 919 static GtkWidget * |
|
| 920 create_account_field(GaimRequestField *field) |
|
| 921 { |
|
| 922 GtkWidget *widget; |
|
| 923 |
|
| 924 widget = gaim_gtk_account_option_menu_new( |
|
| 925 gaim_request_field_account_get_default_value(field), |
|
| 926 gaim_request_field_account_get_show_all(field), |
|
| 927 G_CALLBACK(field_account_cb), |
|
| 928 gaim_request_field_account_get_filter(field), |
|
| 929 field); |
|
| 930 |
|
| 931 return widget; |
|
| 932 } |
|
| 933 |
|
| 934 static void |
|
| 935 select_field_list_item(GtkTreeModel *model, GtkTreePath *path, |
|
| 936 GtkTreeIter *iter, gpointer data) |
|
| 937 { |
|
| 938 GaimRequestField *field = (GaimRequestField *)data; |
|
| 939 char *text; |
|
| 940 |
|
| 941 gtk_tree_model_get(model, iter, 1, &text, -1); |
|
| 942 |
|
| 943 gaim_request_field_list_add_selected(field, text); |
|
| 944 g_free(text); |
|
| 945 } |
|
| 946 |
|
| 947 static void |
|
| 948 list_field_select_changed_cb(GtkTreeSelection *sel, GaimRequestField *field) |
|
| 949 { |
|
| 950 gaim_request_field_list_clear_selected(field); |
|
| 951 |
|
| 952 gtk_tree_selection_selected_foreach(sel, select_field_list_item, field); |
|
| 953 } |
|
| 954 |
|
| 955 static GtkWidget * |
|
| 956 create_list_field(GaimRequestField *field) |
|
| 957 { |
|
| 958 GtkWidget *sw; |
|
| 959 GtkWidget *treeview; |
|
| 960 GtkListStore *store; |
|
| 961 GtkCellRenderer *renderer; |
|
| 962 GtkTreeSelection *sel; |
|
| 963 GtkTreeViewColumn *column; |
|
| 964 GtkTreeIter iter; |
|
| 965 const GList *l; |
|
| 966 |
|
| 967 /* Create the scrolled window */ |
|
| 968 sw = gtk_scrolled_window_new(NULL, NULL); |
|
| 969 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), |
|
| 970 GTK_POLICY_AUTOMATIC, |
|
| 971 GTK_POLICY_AUTOMATIC); |
|
| 972 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), |
|
| 973 GTK_SHADOW_IN); |
|
| 974 gtk_widget_show(sw); |
|
| 975 |
|
| 976 /* Create the list store */ |
|
| 977 store = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING); |
|
| 978 |
|
| 979 /* Create the tree view */ |
|
| 980 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); |
|
| 981 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); |
|
| 982 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); |
|
| 983 |
|
| 984 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); |
|
| 985 |
|
| 986 if (gaim_request_field_list_get_multi_select(field)) |
|
| 987 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE); |
|
| 988 |
|
| 989 g_signal_connect(G_OBJECT(sel), "changed", |
|
| 990 G_CALLBACK(list_field_select_changed_cb), field); |
|
| 991 |
|
| 992 column = gtk_tree_view_column_new(); |
|
| 993 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1); |
|
| 994 |
|
| 995 renderer = gtk_cell_renderer_text_new(); |
|
| 996 gtk_tree_view_column_pack_start(column, renderer, TRUE); |
|
| 997 gtk_tree_view_column_add_attribute(column, renderer, "text", 1); |
|
| 998 |
|
| 999 for (l = gaim_request_field_list_get_items(field); l != NULL; l = l->next) |
|
| 1000 { |
|
| 1001 const char *text = (const char *)l->data; |
|
| 1002 |
|
| 1003 gtk_list_store_append(store, &iter); |
|
| 1004 |
|
| 1005 gtk_list_store_set(store, &iter, |
|
| 1006 0, gaim_request_field_list_get_data(field, text), |
|
| 1007 1, text, |
|
| 1008 -1); |
|
| 1009 |
|
| 1010 if (gaim_request_field_list_is_selected(field, text)) |
|
| 1011 gtk_tree_selection_select_iter(sel, &iter); |
|
| 1012 } |
|
| 1013 |
|
| 1014 gtk_container_add(GTK_CONTAINER(sw), treeview); |
|
| 1015 gtk_widget_show(treeview); |
|
| 1016 |
|
| 1017 return sw; |
|
| 1018 } |
|
| 1019 |
|
| 1020 static void * |
|
| 1021 gaim_gtk_request_fields(const char *title, const char *primary, |
|
| 1022 const char *secondary, GaimRequestFields *fields, |
|
| 1023 const char *ok_text, GCallback ok_cb, |
|
| 1024 const char *cancel_text, GCallback cancel_cb, |
|
| 1025 void *user_data) |
|
| 1026 { |
|
| 1027 GaimGtkRequestData *data; |
|
| 1028 GtkWidget *win; |
|
| 1029 GtkWidget *vbox; |
|
| 1030 GtkWidget *vbox2; |
|
| 1031 GtkWidget *hbox; |
|
| 1032 GtkWidget *bbox; |
|
| 1033 GtkWidget *frame; |
|
| 1034 GtkWidget *label; |
|
| 1035 GtkWidget *table; |
|
| 1036 GtkWidget *button; |
|
| 1037 GtkWidget *img; |
|
| 1038 GtkWidget *sw; |
|
| 1039 GtkSizeGroup *sg; |
|
| 1040 GList *gl, *fl; |
|
| 1041 GaimRequestFieldGroup *group; |
|
| 1042 GaimRequestField *field; |
|
| 1043 char *label_text; |
|
| 1044 char *primary_esc, *secondary_esc; |
|
| 1045 int total_fields = 0; |
|
| 1046 |
|
| 1047 data = g_new0(GaimGtkRequestData, 1); |
|
| 1048 data->type = GAIM_REQUEST_FIELDS; |
|
| 1049 data->user_data = user_data; |
|
| 1050 data->u.multifield.fields = fields; |
|
| 1051 |
|
| 1052 fields->ui_data = data; |
|
| 1053 |
|
| 1054 data->cb_count = 2; |
|
| 1055 data->cbs = g_new0(GCallback, 2); |
|
| 1056 |
|
| 1057 data->cbs[0] = ok_cb; |
|
| 1058 data->cbs[1] = cancel_cb; |
|
| 1059 |
|
| 1060 data->dialog = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
|
| 1061 |
|
| 1062 if (title != NULL) |
|
| 1063 gtk_window_set_title(GTK_WINDOW(win), title); |
|
| 1064 |
|
| 1065 gtk_window_set_role(GTK_WINDOW(win), "multifield"); |
|
| 1066 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER); |
|
| 1067 gtk_window_set_resizable(GTK_WINDOW(win), FALSE); |
|
| 1068 |
|
| 1069 g_signal_connect(G_OBJECT(win), "delete_event", |
|
| 1070 G_CALLBACK(destroy_multifield_cb), data); |
|
| 1071 |
|
| 1072 /* Setup the main horizontal box */ |
|
| 1073 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
|
| 1074 gtk_container_add(GTK_CONTAINER(win), hbox); |
|
| 1075 gtk_widget_show(hbox); |
|
| 1076 |
|
| 1077 /* Dialog icon. */ |
|
| 1078 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
|
| 1079 GTK_ICON_SIZE_DIALOG); |
|
| 1080 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); |
|
| 1081 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); |
|
| 1082 gtk_widget_show(img); |
|
| 1083 |
|
| 1084 /* Setup the vbox */ |
|
| 1085 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
|
| 1086 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); |
|
| 1087 gtk_widget_show(vbox); |
|
| 1088 |
|
| 1089 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); |
|
| 1090 |
|
| 1091 if(primary) { |
|
| 1092 primary_esc = g_markup_escape_text(primary, -1); |
|
| 1093 label_text = g_strdup_printf( |
|
| 1094 "<span weight=\"bold\" size=\"larger\">%s</span>", primary_esc); |
|
| 1095 g_free(primary_esc); |
|
| 1096 label = gtk_label_new(NULL); |
|
| 1097 |
|
| 1098 gtk_label_set_markup(GTK_LABEL(label), label_text); |
|
| 1099 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
|
| 1100 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
|
| 1101 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); |
|
| 1102 gtk_widget_show(label); |
|
| 1103 g_free(label_text); |
|
| 1104 } |
|
| 1105 |
|
| 1106 for (gl = gaim_request_fields_get_groups(fields); gl != NULL; |
|
| 1107 gl = gl->next) |
|
| 1108 total_fields += g_list_length(gaim_request_field_group_get_fields(gl->data)); |
|
| 1109 |
|
| 1110 if(total_fields > 9) { |
|
| 1111 sw = gtk_scrolled_window_new(NULL, NULL); |
|
| 1112 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), |
|
| 1113 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); |
|
| 1114 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), |
|
| 1115 GTK_SHADOW_NONE); |
|
| 1116 gtk_widget_set_size_request(sw, -1, 200); |
|
| 1117 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); |
|
| 1118 gtk_widget_show(sw); |
|
| 1119 |
|
| 1120 vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
|
| 1121 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), vbox2); |
|
| 1122 gtk_widget_show(vbox2); |
|
| 1123 } else { |
|
| 1124 vbox2 = vbox; |
|
| 1125 } |
|
| 1126 |
|
| 1127 if (secondary) { |
|
| 1128 secondary_esc = g_markup_escape_text(secondary, -1); |
|
| 1129 label = gtk_label_new(NULL); |
|
| 1130 |
|
| 1131 gtk_label_set_markup(GTK_LABEL(label), secondary_esc); |
|
| 1132 g_free(secondary_esc); |
|
| 1133 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
|
| 1134 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
|
| 1135 gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, TRUE, 0); |
|
| 1136 gtk_widget_show(label); |
|
| 1137 } |
|
| 1138 |
|
| 1139 for (gl = gaim_request_fields_get_groups(fields); |
|
| 1140 gl != NULL; |
|
| 1141 gl = gl->next) |
|
| 1142 { |
|
| 1143 GList *field_list; |
|
| 1144 size_t field_count = 0; |
|
| 1145 size_t cols = 1; |
|
| 1146 size_t rows; |
|
| 1147 size_t col_num; |
|
| 1148 size_t row_num = 0; |
|
| 1149 |
|
| 1150 group = gl->data; |
|
| 1151 field_list = gaim_request_field_group_get_fields(group); |
|
| 1152 |
|
| 1153 if (gaim_request_field_group_get_title(group) != NULL) |
|
| 1154 { |
|
| 1155 frame = gaim_gtk_make_frame(vbox2, |
|
| 1156 gaim_request_field_group_get_title(group)); |
|
| 1157 } |
|
| 1158 else |
|
| 1159 frame = vbox2; |
|
| 1160 |
|
| 1161 field_count = g_list_length(field_list); |
|
| 1162 /* |
|
| 1163 if (field_count > 9) |
|
| 1164 { |
|
| 1165 rows = field_count / 2; |
|
| 1166 cols++; |
|
| 1167 } |
|
| 1168 else |
|
| 1169 */ |
|
| 1170 rows = field_count; |
|
| 1171 |
|
| 1172 col_num = 0; |
|
| 1173 |
|
| 1174 for (fl = field_list; fl != NULL; fl = fl->next) |
|
| 1175 { |
|
| 1176 GaimRequestFieldType type; |
|
| 1177 |
|
| 1178 field = (GaimRequestField *)fl->data; |
|
| 1179 |
|
| 1180 type = gaim_request_field_get_type(field); |
|
| 1181 |
|
| 1182 if (type == GAIM_REQUEST_FIELD_LABEL) |
|
| 1183 { |
|
| 1184 if (col_num > 0) |
|
| 1185 rows++; |
|
| 1186 |
|
| 1187 rows++; |
|
| 1188 } |
|
| 1189 else if ((type == GAIM_REQUEST_FIELD_LIST) || |
|
| 1190 (type == GAIM_REQUEST_FIELD_STRING && |
|
| 1191 gaim_request_field_string_is_multiline(field))) |
|
| 1192 { |
|
| 1193 if (col_num > 0) |
|
| 1194 rows++; |
|
| 1195 |
|
| 1196 rows += 2; |
|
| 1197 } |
|
| 1198 |
|
| 1199 col_num++; |
|
| 1200 |
|
| 1201 if (col_num >= cols) |
|
| 1202 col_num = 0; |
|
| 1203 } |
|
| 1204 |
|
| 1205 table = gtk_table_new(rows, 2 * cols, FALSE); |
|
| 1206 gtk_table_set_row_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE); |
|
| 1207 gtk_table_set_col_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE); |
|
| 1208 |
|
| 1209 gtk_container_add(GTK_CONTAINER(frame), table); |
|
| 1210 gtk_widget_show(table); |
|
| 1211 |
|
| 1212 for (row_num = 0, fl = field_list; |
|
| 1213 row_num < rows && fl != NULL; |
|
| 1214 row_num++) |
|
| 1215 { |
|
| 1216 for (col_num = 0; |
|
| 1217 col_num < cols && fl != NULL; |
|
| 1218 col_num++, fl = fl->next) |
|
| 1219 { |
|
| 1220 size_t col_offset = col_num * 2; |
|
| 1221 GaimRequestFieldType type; |
|
| 1222 GtkWidget *widget = NULL; |
|
| 1223 |
|
| 1224 label = NULL; |
|
| 1225 field = fl->data; |
|
| 1226 |
|
| 1227 if (!gaim_request_field_is_visible(field)) { |
|
| 1228 col_num--; |
|
| 1229 continue; |
|
| 1230 } |
|
| 1231 |
|
| 1232 type = gaim_request_field_get_type(field); |
|
| 1233 |
|
| 1234 if (type != GAIM_REQUEST_FIELD_BOOLEAN && |
|
| 1235 gaim_request_field_get_label(field)) |
|
| 1236 { |
|
| 1237 char *text; |
|
| 1238 |
|
| 1239 text = g_strdup_printf("%s:", |
|
| 1240 gaim_request_field_get_label(field)); |
|
| 1241 |
|
| 1242 label = gtk_label_new(NULL); |
|
| 1243 gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), text); |
|
| 1244 g_free(text); |
|
| 1245 |
|
| 1246 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); |
|
| 1247 |
|
| 1248 gtk_size_group_add_widget(sg, label); |
|
| 1249 |
|
| 1250 if (type == GAIM_REQUEST_FIELD_LABEL || |
|
| 1251 type == GAIM_REQUEST_FIELD_LIST || |
|
| 1252 (type == GAIM_REQUEST_FIELD_STRING && |
|
| 1253 gaim_request_field_string_is_multiline(field))) |
|
| 1254 { |
|
| 1255 if(col_num > 0) |
|
| 1256 row_num++; |
|
| 1257 |
|
| 1258 gtk_table_attach_defaults(GTK_TABLE(table), label, |
|
| 1259 0, 2 * cols, |
|
| 1260 row_num, row_num + 1); |
|
| 1261 |
|
| 1262 row_num++; |
|
| 1263 col_num=cols; |
|
| 1264 } |
|
| 1265 else |
|
| 1266 { |
|
| 1267 gtk_table_attach_defaults(GTK_TABLE(table), label, |
|
| 1268 col_offset, col_offset + 1, |
|
| 1269 row_num, row_num + 1); |
|
| 1270 } |
|
| 1271 |
|
| 1272 gtk_widget_show(label); |
|
| 1273 } |
|
| 1274 |
|
| 1275 if (field->ui_data != NULL) |
|
| 1276 widget = GTK_WIDGET(field->ui_data); |
|
| 1277 else if (type == GAIM_REQUEST_FIELD_STRING) |
|
| 1278 widget = create_string_field(field); |
|
| 1279 else if (type == GAIM_REQUEST_FIELD_INTEGER) |
|
| 1280 widget = create_int_field(field); |
|
| 1281 else if (type == GAIM_REQUEST_FIELD_BOOLEAN) |
|
| 1282 widget = create_bool_field(field); |
|
| 1283 else if (type == GAIM_REQUEST_FIELD_CHOICE) |
|
| 1284 widget = create_choice_field(field); |
|
| 1285 else if (type == GAIM_REQUEST_FIELD_LIST) |
|
| 1286 widget = create_list_field(field); |
|
| 1287 else if (type == GAIM_REQUEST_FIELD_IMAGE) |
|
| 1288 widget = create_image_field(field); |
|
| 1289 else if (type == GAIM_REQUEST_FIELD_ACCOUNT) |
|
| 1290 widget = create_account_field(field); |
|
| 1291 else |
|
| 1292 continue; |
|
| 1293 |
|
| 1294 if (label) |
|
| 1295 gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget); |
|
| 1296 |
|
| 1297 if (type == GAIM_REQUEST_FIELD_STRING && |
|
| 1298 gaim_request_field_string_is_multiline(field)) |
|
| 1299 { |
|
| 1300 gtk_table_attach(GTK_TABLE(table), widget, |
|
| 1301 0, 2 * cols, |
|
| 1302 row_num, row_num + 1, |
|
| 1303 GTK_FILL | GTK_EXPAND, |
|
| 1304 GTK_FILL | GTK_EXPAND, |
|
| 1305 5, 0); |
|
| 1306 } |
|
| 1307 else if (type == GAIM_REQUEST_FIELD_LIST) |
|
| 1308 { |
|
| 1309 gtk_table_attach(GTK_TABLE(table), widget, |
|
| 1310 0, 2 * cols, |
|
| 1311 row_num, row_num + 1, |
|
| 1312 GTK_FILL | GTK_EXPAND, |
|
| 1313 GTK_FILL | GTK_EXPAND, |
|
| 1314 5, 0); |
|
| 1315 } |
|
| 1316 else if (type == GAIM_REQUEST_FIELD_BOOLEAN) |
|
| 1317 { |
|
| 1318 gtk_table_attach(GTK_TABLE(table), widget, |
|
| 1319 col_offset, col_offset + 1, |
|
| 1320 row_num, row_num + 1, |
|
| 1321 GTK_FILL | GTK_EXPAND, |
|
| 1322 GTK_FILL | GTK_EXPAND, |
|
| 1323 5, 0); |
|
| 1324 } |
|
| 1325 else |
|
| 1326 { |
|
| 1327 gtk_table_attach(GTK_TABLE(table), widget, |
|
| 1328 1, 2 * cols, |
|
| 1329 row_num, row_num + 1, |
|
| 1330 GTK_FILL | GTK_EXPAND, |
|
| 1331 GTK_FILL | GTK_EXPAND, |
|
| 1332 5, 0); |
|
| 1333 } |
|
| 1334 |
|
| 1335 gtk_widget_show(widget); |
|
| 1336 |
|
| 1337 field->ui_data = widget; |
|
| 1338 } |
|
| 1339 } |
|
| 1340 } |
|
| 1341 |
|
| 1342 g_object_unref(sg); |
|
| 1343 |
|
| 1344 /* Button box. */ |
|
| 1345 bbox = gtk_hbutton_box_new(); |
|
| 1346 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE); |
|
| 1347 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); |
|
| 1348 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); |
|
| 1349 gtk_widget_show(bbox); |
|
| 1350 |
|
| 1351 /* Cancel button */ |
|
| 1352 button = gtk_button_new_from_stock(text_to_stock(cancel_text)); |
|
| 1353 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); |
|
| 1354 gtk_widget_show(button); |
|
| 1355 |
|
| 1356 g_signal_connect(G_OBJECT(button), "clicked", |
|
| 1357 G_CALLBACK(multifield_cancel_cb), data); |
|
| 1358 |
|
| 1359 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); |
|
| 1360 |
|
| 1361 /* OK button */ |
|
| 1362 button = gtk_button_new_from_stock(text_to_stock(ok_text)); |
|
| 1363 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); |
|
| 1364 gtk_widget_show(button); |
|
| 1365 |
|
| 1366 data->ok_button = button; |
|
| 1367 |
|
| 1368 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); |
|
| 1369 gtk_window_set_default(GTK_WINDOW(win), button); |
|
| 1370 |
|
| 1371 g_signal_connect(G_OBJECT(button), "clicked", |
|
| 1372 G_CALLBACK(multifield_ok_cb), data); |
|
| 1373 |
|
| 1374 if (!gaim_request_fields_all_required_filled(fields)) |
|
| 1375 gtk_widget_set_sensitive(button, FALSE); |
|
| 1376 |
|
| 1377 gtk_widget_show(win); |
|
| 1378 |
|
| 1379 return data; |
|
| 1380 } |
|
| 1381 |
|
| 1382 static void |
|
| 1383 file_yes_no_cb(GaimGtkRequestData *data, gint id) |
|
| 1384 { |
|
| 1385 /* Only call the callback if yes was selected, otherwise the request |
|
| 1386 * (eg. file transfer) will be cancelled, then when a new filename is chosen |
|
| 1387 * things go BOOM */ |
|
| 1388 if (id == 1) { |
|
| 1389 if (data->cbs[1] != NULL) |
|
| 1390 ((GaimRequestFileCb)data->cbs[1])(data->user_data, data->u.file.name); |
|
| 1391 gaim_request_close(data->type, data); |
|
| 1392 } else { |
|
| 1393 gaim_gtk_clear_cursor(GTK_WIDGET(data->dialog)); |
|
| 1394 } |
|
| 1395 } |
|
| 1396 |
|
| 1397 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 1398 static void |
|
| 1399 file_ok_check_if_exists_cb(GtkWidget *widget, gint response, GaimGtkRequestData *data) |
|
| 1400 { |
|
| 1401 gchar *current_folder; |
|
| 1402 |
|
| 1403 generic_response_start(data); |
|
| 1404 |
|
| 1405 if (response != GTK_RESPONSE_ACCEPT) { |
|
| 1406 if (data->cbs[0] != NULL) |
|
| 1407 ((GaimRequestFileCb)data->cbs[0])(data->user_data, NULL); |
|
| 1408 gaim_request_close(data->type, data); |
|
| 1409 return; |
|
| 1410 } |
|
| 1411 |
|
| 1412 data->u.file.name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(data->dialog)); |
|
| 1413 current_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(data->dialog)); |
|
| 1414 if (current_folder != NULL) { |
|
| 1415 if (data->u.file.savedialog) { |
|
| 1416 gaim_prefs_set_string("/gaim/gtk/filelocations/last_save_folder", current_folder); |
|
| 1417 } else { |
|
| 1418 gaim_prefs_set_string("/gaim/gtk/filelocations/last_open_folder", current_folder); |
|
| 1419 } |
|
| 1420 g_free(current_folder); |
|
| 1421 } |
|
| 1422 |
|
| 1423 #else /* FILECHOOSER */ |
|
| 1424 |
|
| 1425 static void |
|
| 1426 file_ok_check_if_exists_cb(GtkWidget *button, GaimGtkRequestData *data) |
|
| 1427 { |
|
| 1428 const gchar *name; |
|
| 1429 gchar *current_folder; |
|
| 1430 |
|
| 1431 generic_response_start(data); |
|
| 1432 |
|
| 1433 name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(data->dialog)); |
|
| 1434 |
|
| 1435 /* If name is a directory then change directories */ |
|
| 1436 if (data->type == GAIM_REQUEST_FILE) { |
|
| 1437 if (gaim_gtk_check_if_dir(name, GTK_FILE_SELECTION(data->dialog))) |
|
| 1438 return; |
|
| 1439 } |
|
| 1440 |
|
| 1441 current_folder = g_path_get_dirname(name); |
|
| 1442 |
|
| 1443 g_free(data->u.file.name); |
|
| 1444 if (data->type == GAIM_REQUEST_FILE) |
|
| 1445 data->u.file.name = g_strdup(name); |
|
| 1446 else |
|
| 1447 { |
|
| 1448 if (g_file_test(name, G_FILE_TEST_IS_DIR)) |
|
| 1449 data->u.file.name = g_strdup(name); |
|
| 1450 else |
|
| 1451 data->u.file.name = g_strdup(current_folder); |
|
| 1452 } |
|
| 1453 |
|
| 1454 if (current_folder != NULL) { |
|
| 1455 if (data->u.file.savedialog) { |
|
| 1456 gaim_prefs_set_string("/gaim/gtk/filelocations/last_save_folder", current_folder); |
|
| 1457 } else { |
|
| 1458 gaim_prefs_set_string("/gaim/gtk/filelocations/last_open_folder", current_folder); |
|
| 1459 } |
|
| 1460 g_free(current_folder); |
|
| 1461 } |
|
| 1462 |
|
| 1463 #endif /* FILECHOOSER */ |
|
| 1464 |
|
| 1465 if ((data->u.file.savedialog == TRUE) && |
|
| 1466 (g_file_test(data->u.file.name, G_FILE_TEST_EXISTS))) { |
|
| 1467 gaim_request_action(data, NULL, _("That file already exists"), |
|
| 1468 _("Would you like to overwrite it?"), 0, data, 2, |
|
| 1469 _("Overwrite"), G_CALLBACK(file_yes_no_cb), |
|
| 1470 _("Choose New Name"), G_CALLBACK(file_yes_no_cb)); |
|
| 1471 } else |
|
| 1472 file_yes_no_cb(data, 1); |
|
| 1473 } |
|
| 1474 |
|
| 1475 #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 1476 static void |
|
| 1477 file_cancel_cb(GaimGtkRequestData *data) |
|
| 1478 { |
|
| 1479 generic_response_start(data); |
|
| 1480 |
|
| 1481 if (data->cbs[0] != NULL) |
|
| 1482 ((GaimRequestFileCb)data->cbs[0])(data->user_data, NULL); |
|
| 1483 |
|
| 1484 gaim_request_close(data->type, data); |
|
| 1485 } |
|
| 1486 #endif /* FILECHOOSER */ |
|
| 1487 |
|
| 1488 static void * |
|
| 1489 gaim_gtk_request_file(const char *title, const char *filename, |
|
| 1490 gboolean savedialog, |
|
| 1491 GCallback ok_cb, GCallback cancel_cb, |
|
| 1492 void *user_data) |
|
| 1493 { |
|
| 1494 GaimGtkRequestData *data; |
|
| 1495 GtkWidget *filesel; |
|
| 1496 const gchar *current_folder; |
|
| 1497 #if GTK_CHECK_VERSION(2,4,0) |
|
| 1498 gboolean folder_set = FALSE; |
|
| 1499 #endif |
|
| 1500 |
|
| 1501 data = g_new0(GaimGtkRequestData, 1); |
|
| 1502 data->type = GAIM_REQUEST_FILE; |
|
| 1503 data->user_data = user_data; |
|
| 1504 data->cb_count = 2; |
|
| 1505 data->cbs = g_new0(GCallback, 2); |
|
| 1506 data->cbs[0] = cancel_cb; |
|
| 1507 data->cbs[1] = ok_cb; |
|
| 1508 data->u.file.savedialog = savedialog; |
|
| 1509 |
|
| 1510 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 1511 filesel = gtk_file_chooser_dialog_new( |
|
| 1512 title ? title : (savedialog ? _("Save File...") |
|
| 1513 : _("Open File...")), |
|
| 1514 NULL, |
|
| 1515 savedialog ? GTK_FILE_CHOOSER_ACTION_SAVE |
|
| 1516 : GTK_FILE_CHOOSER_ACTION_OPEN, |
|
| 1517 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
|
| 1518 savedialog ? GTK_STOCK_SAVE |
|
| 1519 : GTK_STOCK_OPEN, |
|
| 1520 GTK_RESPONSE_ACCEPT, |
|
| 1521 NULL); |
|
| 1522 gtk_dialog_set_default_response(GTK_DIALOG(filesel), GTK_RESPONSE_ACCEPT); |
|
| 1523 |
|
| 1524 if (savedialog) { |
|
| 1525 current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_save_folder"); |
|
| 1526 } else { |
|
| 1527 current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_open_folder"); |
|
| 1528 } |
|
| 1529 |
|
| 1530 if (filename != NULL) |
|
| 1531 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(filesel), filename); |
|
| 1532 if ((current_folder != NULL) && (*current_folder != '\0')) { |
|
| 1533 folder_set = gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filesel), current_folder); |
|
| 1534 } |
|
| 1535 |
|
| 1536 #ifdef _WIN32 |
|
| 1537 if (!folder_set) { |
|
| 1538 char *my_documents = wgaim_get_special_folder(CSIDL_PERSONAL); |
|
| 1539 |
|
| 1540 if (my_documents != NULL) { |
|
| 1541 gtk_file_chooser_set_current_folder( |
|
| 1542 GTK_FILE_CHOOSER(filesel), my_documents); |
|
| 1543 |
|
| 1544 g_free(my_documents); |
|
| 1545 } |
|
| 1546 } |
|
| 1547 |
|
| 1548 #endif |
|
| 1549 g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(filesel)), "response", |
|
| 1550 G_CALLBACK(file_ok_check_if_exists_cb), data); |
|
| 1551 #else /* FILECHOOSER */ |
|
| 1552 filesel = gtk_file_selection_new( |
|
| 1553 title ? title : (savedialog ? _("Save File...") |
|
| 1554 : _("Open File..."))); |
|
| 1555 if (savedialog) { |
|
| 1556 current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_save_folder"); |
|
| 1557 } else { |
|
| 1558 current_folder = gaim_prefs_get_string("/gaim/gtk/filelocations/last_open_folder"); |
|
| 1559 } |
|
| 1560 if (current_folder != NULL) { |
|
| 1561 gchar *path = g_strdup_printf("%s%s", current_folder, G_DIR_SEPARATOR_S); |
|
| 1562 gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), path); |
|
| 1563 g_free(path); |
|
| 1564 } |
|
| 1565 if (filename != NULL) |
|
| 1566 gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), filename); |
|
| 1567 |
|
| 1568 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(filesel)), "delete_event", |
|
| 1569 G_CALLBACK(file_cancel_cb), data); |
|
| 1570 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(filesel)->cancel_button), |
|
| 1571 "clicked", G_CALLBACK(file_cancel_cb), data); |
|
| 1572 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked", |
|
| 1573 G_CALLBACK(file_ok_check_if_exists_cb), data); |
|
| 1574 #endif /* FILECHOOSER */ |
|
| 1575 |
|
| 1576 data->dialog = filesel; |
|
| 1577 gtk_widget_show(filesel); |
|
| 1578 |
|
| 1579 return (void *)data; |
|
| 1580 } |
|
| 1581 |
|
| 1582 static void * |
|
| 1583 gaim_gtk_request_folder(const char *title, const char *dirname, |
|
| 1584 GCallback ok_cb, GCallback cancel_cb, |
|
| 1585 void *user_data) |
|
| 1586 { |
|
| 1587 GaimGtkRequestData *data; |
|
| 1588 GtkWidget *dirsel; |
|
| 1589 |
|
| 1590 data = g_new0(GaimGtkRequestData, 1); |
|
| 1591 data->type = GAIM_REQUEST_FOLDER; |
|
| 1592 data->user_data = user_data; |
|
| 1593 data->cb_count = 2; |
|
| 1594 data->cbs = g_new0(GCallback, 2); |
|
| 1595 data->cbs[0] = cancel_cb; |
|
| 1596 data->cbs[1] = ok_cb; |
|
| 1597 data->u.file.savedialog = FALSE; |
|
| 1598 |
|
| 1599 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 1600 dirsel = gtk_file_chooser_dialog_new( |
|
| 1601 title ? title : _("Select Folder..."), |
|
| 1602 NULL, |
|
| 1603 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, |
|
| 1604 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
|
| 1605 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, |
|
| 1606 NULL); |
|
| 1607 gtk_dialog_set_default_response(GTK_DIALOG(dirsel), GTK_RESPONSE_ACCEPT); |
|
| 1608 |
|
| 1609 if ((dirname != NULL) && (*dirname != '\0')) |
|
| 1610 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dirsel), dirname); |
|
| 1611 |
|
| 1612 g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(dirsel)), "response", |
|
| 1613 G_CALLBACK(file_ok_check_if_exists_cb), data); |
|
| 1614 #else |
|
| 1615 dirsel = gtk_file_selection_new(title ? title : _("Select Folder...")); |
|
| 1616 |
|
| 1617 g_signal_connect_swapped(G_OBJECT(dirsel), "delete_event", |
|
| 1618 G_CALLBACK(file_cancel_cb), data); |
|
| 1619 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(dirsel)->cancel_button), |
|
| 1620 "clicked", G_CALLBACK(file_cancel_cb), data); |
|
| 1621 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(dirsel)->ok_button), "clicked", |
|
| 1622 G_CALLBACK(file_ok_check_if_exists_cb), data); |
|
| 1623 #endif |
|
| 1624 |
|
| 1625 data->dialog = dirsel; |
|
| 1626 gtk_widget_show(dirsel); |
|
| 1627 |
|
| 1628 return (void *)data; |
|
| 1629 } |
|
| 1630 |
|
| 1631 static void |
|
| 1632 gaim_gtk_close_request(GaimRequestType type, void *ui_handle) |
|
| 1633 { |
|
| 1634 GaimGtkRequestData *data = (GaimGtkRequestData *)ui_handle; |
|
| 1635 |
|
| 1636 if (data->cbs != NULL) |
|
| 1637 g_free(data->cbs); |
|
| 1638 |
|
| 1639 gtk_widget_destroy(data->dialog); |
|
| 1640 |
|
| 1641 if (type == GAIM_REQUEST_FIELDS) |
|
| 1642 gaim_request_fields_destroy(data->u.multifield.fields); |
|
| 1643 else if (type == GAIM_REQUEST_FILE) |
|
| 1644 g_free(data->u.file.name); |
|
| 1645 |
|
| 1646 g_free(data); |
|
| 1647 } |
|
| 1648 |
|
| 1649 static GaimRequestUiOps ops = |
|
| 1650 { |
|
| 1651 gaim_gtk_request_input, |
|
| 1652 gaim_gtk_request_choice, |
|
| 1653 gaim_gtk_request_action, |
|
| 1654 gaim_gtk_request_fields, |
|
| 1655 gaim_gtk_request_file, |
|
| 1656 gaim_gtk_close_request, |
|
| 1657 gaim_gtk_request_folder |
|
| 1658 }; |
|
| 1659 |
|
| 1660 GaimRequestUiOps * |
|
| 1661 gaim_gtk_request_get_ui_ops(void) |
|
| 1662 { |
|
| 1663 return &ops; |
|
| 1664 } |
|