| |
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 "gaimstock.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 = 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 if (gtk_entry_get_invisible_char(GTK_ENTRY(entry)) == '*') |
| |
427 gtk_entry_set_invisible_char(GTK_ENTRY(entry), GAIM_INVISIBLE_CHAR); |
| |
428 } |
| |
429 } |
| |
430 } |
| |
431 |
| |
432 gaim_set_accessible_label (entry, label); |
| |
433 data->u.input.entry = entry; |
| |
434 |
| |
435 /* Show everything. */ |
| |
436 gtk_widget_show_all(dialog); |
| |
437 |
| |
438 return data; |
| |
439 } |
| |
440 |
| |
441 static void * |
| |
442 gaim_gtk_request_choice(const char *title, const char *primary, |
| |
443 const char *secondary, unsigned int default_value, |
| |
444 const char *ok_text, GCallback ok_cb, |
| |
445 const char *cancel_text, GCallback cancel_cb, |
| |
446 void *user_data, va_list args) |
| |
447 { |
| |
448 GaimGtkRequestData *data; |
| |
449 GtkWidget *dialog; |
| |
450 GtkWidget *vbox, *vbox2; |
| |
451 GtkWidget *hbox; |
| |
452 GtkWidget *label; |
| |
453 GtkWidget *img; |
| |
454 GtkWidget *radio = NULL; |
| |
455 char *label_text; |
| |
456 char *radio_text; |
| |
457 char *primary_esc, *secondary_esc; |
| |
458 |
| |
459 data = g_new0(GaimGtkRequestData, 1); |
| |
460 data->type = GAIM_REQUEST_ACTION; |
| |
461 data->user_data = user_data; |
| |
462 |
| |
463 data->cb_count = 2; |
| |
464 data->cbs = g_new0(GCallback, 2); |
| |
465 data->cbs[0] = cancel_cb; |
| |
466 data->cbs[1] = ok_cb; |
| |
467 |
| |
468 /* Create the dialog. */ |
| |
469 data->dialog = dialog = gtk_dialog_new(); |
| |
470 |
| |
471 if (title != NULL) |
| |
472 gtk_window_set_title(GTK_WINDOW(dialog), title); |
| |
473 |
| |
474 |
| |
475 gtk_dialog_add_button(GTK_DIALOG(dialog), |
| |
476 text_to_stock(cancel_text), 0); |
| |
477 |
| |
478 gtk_dialog_add_button(GTK_DIALOG(dialog), |
| |
479 text_to_stock(ok_text), 1); |
| |
480 |
| |
481 g_signal_connect(G_OBJECT(dialog), "response", |
| |
482 G_CALLBACK(choice_response_cb), data); |
| |
483 |
| |
484 /* Setup the dialog */ |
| |
485 gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); |
| |
486 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); |
| |
487 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); |
| |
488 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); |
| |
489 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); |
| |
490 |
| |
491 /* Setup the main horizontal box */ |
| |
492 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
| |
493 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); |
| |
494 |
| |
495 /* Dialog icon. */ |
| |
496 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
| |
497 GTK_ICON_SIZE_DIALOG); |
| |
498 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); |
| |
499 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); |
| |
500 |
| |
501 /* Vertical box */ |
| |
502 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
| |
503 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); |
| |
504 |
| |
505 /* Descriptive label */ |
| |
506 primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; |
| |
507 secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; |
| |
508 label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" |
| |
509 "%s</span>%s%s" : "%s%s%s"), |
| |
510 (primary ? primary_esc : ""), |
| |
511 ((primary && secondary) ? "\n\n" : ""), |
| |
512 (secondary ? secondary_esc : "")); |
| |
513 g_free(primary_esc); |
| |
514 g_free(secondary_esc); |
| |
515 |
| |
516 label = gtk_label_new(NULL); |
| |
517 |
| |
518 gtk_label_set_markup(GTK_LABEL(label), label_text); |
| |
519 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
| |
520 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
| |
521 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); |
| |
522 |
| |
523 g_free(label_text); |
| |
524 |
| |
525 vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
| |
526 gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, 0); |
| |
527 while ((radio_text = va_arg(args, char*))) { |
| |
528 int resp = va_arg(args, int); |
| |
529 radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), radio_text); |
| |
530 gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0); |
| |
531 g_object_set_data(G_OBJECT(radio), "choice_id", GINT_TO_POINTER(resp)); |
| |
532 if (resp == default_value) |
| |
533 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); |
| |
534 } |
| |
535 |
| |
536 g_object_set_data(G_OBJECT(dialog), "radio", radio); |
| |
537 |
| |
538 /* Show everything. */ |
| |
539 gtk_widget_show_all(dialog); |
| |
540 |
| |
541 return data; |
| |
542 } |
| |
543 |
| |
544 static void * |
| |
545 gaim_gtk_request_action(const char *title, const char *primary, |
| |
546 const char *secondary, unsigned int default_action, |
| |
547 void *user_data, size_t action_count, va_list actions) |
| |
548 { |
| |
549 GaimGtkRequestData *data; |
| |
550 GtkWidget *dialog; |
| |
551 GtkWidget *vbox; |
| |
552 GtkWidget *hbox; |
| |
553 GtkWidget *label; |
| |
554 GtkWidget *img; |
| |
555 void **buttons; |
| |
556 char *label_text; |
| |
557 char *primary_esc, *secondary_esc; |
| |
558 int i; |
| |
559 |
| |
560 data = g_new0(GaimGtkRequestData, 1); |
| |
561 data->type = GAIM_REQUEST_ACTION; |
| |
562 data->user_data = user_data; |
| |
563 |
| |
564 data->cb_count = action_count; |
| |
565 data->cbs = g_new0(GCallback, action_count); |
| |
566 |
| |
567 /* Reverse the buttons */ |
| |
568 buttons = g_new0(void *, action_count * 2); |
| |
569 |
| |
570 for (i = 0; i < action_count * 2; i += 2) { |
| |
571 buttons[(action_count * 2) - i - 2] = va_arg(actions, char *); |
| |
572 buttons[(action_count * 2) - i - 1] = va_arg(actions, GCallback); |
| |
573 } |
| |
574 |
| |
575 /* Create the dialog. */ |
| |
576 data->dialog = dialog = gtk_dialog_new(); |
| |
577 |
| |
578 if (title != NULL) |
| |
579 gtk_window_set_title(GTK_WINDOW(dialog), title); |
| |
580 |
| |
581 for (i = 0; i < action_count; i++) { |
| |
582 gtk_dialog_add_button(GTK_DIALOG(dialog), |
| |
583 text_to_stock(buttons[2 * i]), i); |
| |
584 |
| |
585 data->cbs[i] = buttons[2 * i + 1]; |
| |
586 } |
| |
587 |
| |
588 g_free(buttons); |
| |
589 |
| |
590 g_signal_connect(G_OBJECT(dialog), "response", |
| |
591 G_CALLBACK(action_response_cb), data); |
| |
592 |
| |
593 /* Setup the dialog */ |
| |
594 gtk_container_set_border_width(GTK_CONTAINER(dialog), GAIM_HIG_BORDER/2); |
| |
595 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER/2); |
| |
596 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); |
| |
597 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); |
| |
598 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); |
| |
599 |
| |
600 /* Setup the main horizontal box */ |
| |
601 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
| |
602 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); |
| |
603 |
| |
604 /* Dialog icon. */ |
| |
605 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
| |
606 GTK_ICON_SIZE_DIALOG); |
| |
607 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); |
| |
608 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); |
| |
609 |
| |
610 /* Vertical box */ |
| |
611 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
| |
612 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); |
| |
613 |
| |
614 /* Descriptive label */ |
| |
615 primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; |
| |
616 secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; |
| |
617 label_text = g_strdup_printf((primary ? "<span weight=\"bold\" size=\"larger\">" |
| |
618 "%s</span>%s%s" : "%s%s%s"), |
| |
619 (primary ? primary_esc : ""), |
| |
620 ((primary && secondary) ? "\n\n" : ""), |
| |
621 (secondary ? secondary_esc : "")); |
| |
622 g_free(primary_esc); |
| |
623 g_free(secondary_esc); |
| |
624 |
| |
625 label = gtk_label_new(NULL); |
| |
626 |
| |
627 gtk_label_set_markup(GTK_LABEL(label), label_text); |
| |
628 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
| |
629 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
| |
630 gtk_label_set_selectable(GTK_LABEL(label), TRUE); |
| |
631 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); |
| |
632 |
| |
633 g_free(label_text); |
| |
634 |
| |
635 |
| |
636 if (default_action == GAIM_DEFAULT_ACTION_NONE) { |
| |
637 GTK_WIDGET_SET_FLAGS(img, GTK_CAN_DEFAULT); |
| |
638 GTK_WIDGET_SET_FLAGS(img, GTK_CAN_FOCUS); |
| |
639 gtk_widget_grab_focus(img); |
| |
640 gtk_widget_grab_default(img); |
| |
641 } else |
| |
642 gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_action); |
| |
643 |
| |
644 /* Show everything. */ |
| |
645 gtk_widget_show_all(dialog); |
| |
646 |
| |
647 return data; |
| |
648 } |
| |
649 |
| |
650 static void |
| |
651 req_entry_field_changed_cb(GtkWidget *entry, GaimRequestField *field) |
| |
652 { |
| |
653 GaimGtkRequestData *req_data; |
| |
654 const char *text = gtk_entry_get_text(GTK_ENTRY(entry)); |
| |
655 |
| |
656 gaim_request_field_string_set_value(field, (*text == '\0' ? NULL : text)); |
| |
657 |
| |
658 req_data = (GaimGtkRequestData *)field->group->fields_list->ui_data; |
| |
659 |
| |
660 gtk_widget_set_sensitive(req_data->ok_button, |
| |
661 gaim_request_fields_all_required_filled(field->group->fields_list)); |
| |
662 } |
| |
663 |
| |
664 static void |
| |
665 setup_entry_field(GtkWidget *entry, GaimRequestField *field) |
| |
666 { |
| |
667 const char *type_hint; |
| |
668 |
| |
669 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); |
| |
670 |
| |
671 if (gaim_request_field_is_required(field)) |
| |
672 { |
| |
673 g_signal_connect(G_OBJECT(entry), "changed", |
| |
674 G_CALLBACK(req_entry_field_changed_cb), field); |
| |
675 } |
| |
676 |
| |
677 if ((type_hint = gaim_request_field_get_type_hint(field)) != NULL) |
| |
678 { |
| |
679 if (gaim_str_has_prefix(type_hint, "screenname")) |
| |
680 { |
| |
681 GtkWidget *optmenu = NULL; |
| |
682 GList *fields = field->group->fields; |
| |
683 while (fields) |
| |
684 { |
| |
685 GaimRequestField *fld = fields->data; |
| |
686 fields = fields->next; |
| |
687 |
| |
688 if (gaim_request_field_get_type(fld) == GAIM_REQUEST_FIELD_ACCOUNT) |
| |
689 { |
| |
690 const char *type_hint = gaim_request_field_get_type_hint(fld); |
| |
691 if (type_hint != NULL && strcmp(type_hint, "account") == 0) |
| |
692 { |
| |
693 if (fld->ui_data == NULL) |
| |
694 fld->ui_data = create_account_field(fld); |
| |
695 optmenu = GTK_WIDGET(fld->ui_data); |
| |
696 break; |
| |
697 } |
| |
698 } |
| |
699 } |
| |
700 gaim_gtk_setup_screenname_autocomplete(entry, optmenu, !strcmp(type_hint, "screenname-all")); |
| |
701 } |
| |
702 } |
| |
703 } |
| |
704 |
| |
705 static GtkWidget * |
| |
706 create_string_field(GaimRequestField *field) |
| |
707 { |
| |
708 const char *value; |
| |
709 GtkWidget *widget; |
| |
710 |
| |
711 value = gaim_request_field_string_get_default_value(field); |
| |
712 |
| |
713 if (gaim_request_field_string_is_multiline(field)) |
| |
714 { |
| |
715 GtkWidget *textview; |
| |
716 |
| |
717 widget = gtk_scrolled_window_new(NULL, NULL); |
| |
718 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(widget), |
| |
719 GTK_SHADOW_IN); |
| |
720 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), |
| |
721 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); |
| |
722 |
| |
723 textview = gtk_text_view_new(); |
| |
724 gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), |
| |
725 TRUE); |
| |
726 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), |
| |
727 GTK_WRAP_WORD_CHAR); |
| |
728 |
| |
729 if (gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck")) |
| |
730 gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(textview)); |
| |
731 |
| |
732 gtk_container_add(GTK_CONTAINER(widget), textview); |
| |
733 gtk_widget_show(textview); |
| |
734 |
| |
735 gtk_widget_set_size_request(widget, -1, 75); |
| |
736 |
| |
737 if (value != NULL) |
| |
738 { |
| |
739 GtkTextBuffer *buffer; |
| |
740 |
| |
741 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); |
| |
742 |
| |
743 gtk_text_buffer_set_text(buffer, value, -1); |
| |
744 } |
| |
745 |
| |
746 gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), |
| |
747 gaim_request_field_string_is_editable(field)); |
| |
748 |
| |
749 g_signal_connect(G_OBJECT(textview), "focus-out-event", |
| |
750 G_CALLBACK(field_string_focus_out_cb), field); |
| |
751 } |
| |
752 else |
| |
753 { |
| |
754 widget = gtk_entry_new(); |
| |
755 |
| |
756 setup_entry_field(widget, field); |
| |
757 |
| |
758 if (value != NULL) |
| |
759 gtk_entry_set_text(GTK_ENTRY(widget), value); |
| |
760 |
| |
761 if (gaim_request_field_string_is_masked(field)) |
| |
762 { |
| |
763 gtk_entry_set_visibility(GTK_ENTRY(widget), FALSE); |
| |
764 if (gtk_entry_get_invisible_char(GTK_ENTRY(widget)) == '*') |
| |
765 gtk_entry_set_invisible_char(GTK_ENTRY(widget), GAIM_INVISIBLE_CHAR); |
| |
766 } |
| |
767 |
| |
768 gtk_editable_set_editable(GTK_EDITABLE(widget), |
| |
769 gaim_request_field_string_is_editable(field)); |
| |
770 |
| |
771 g_signal_connect(G_OBJECT(widget), "focus-out-event", |
| |
772 G_CALLBACK(field_string_focus_out_cb), field); |
| |
773 } |
| |
774 |
| |
775 return widget; |
| |
776 } |
| |
777 |
| |
778 static GtkWidget * |
| |
779 create_int_field(GaimRequestField *field) |
| |
780 { |
| |
781 int value; |
| |
782 GtkWidget *widget; |
| |
783 |
| |
784 widget = gtk_entry_new(); |
| |
785 |
| |
786 setup_entry_field(widget, field); |
| |
787 |
| |
788 value = gaim_request_field_int_get_default_value(field); |
| |
789 |
| |
790 if (value != 0) |
| |
791 { |
| |
792 char buf[32]; |
| |
793 |
| |
794 g_snprintf(buf, sizeof(buf), "%d", value); |
| |
795 |
| |
796 gtk_entry_set_text(GTK_ENTRY(widget), buf); |
| |
797 } |
| |
798 |
| |
799 g_signal_connect(G_OBJECT(widget), "focus-out-event", |
| |
800 G_CALLBACK(field_int_focus_out_cb), field); |
| |
801 |
| |
802 return widget; |
| |
803 } |
| |
804 |
| |
805 static GtkWidget * |
| |
806 create_bool_field(GaimRequestField *field) |
| |
807 { |
| |
808 GtkWidget *widget; |
| |
809 |
| |
810 widget = gtk_check_button_new_with_label( |
| |
811 gaim_request_field_get_label(field)); |
| |
812 |
| |
813 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), |
| |
814 gaim_request_field_bool_get_default_value(field)); |
| |
815 |
| |
816 g_signal_connect(G_OBJECT(widget), "toggled", |
| |
817 G_CALLBACK(field_bool_cb), field); |
| |
818 |
| |
819 return widget; |
| |
820 } |
| |
821 |
| |
822 static GtkWidget * |
| |
823 create_choice_field(GaimRequestField *field) |
| |
824 { |
| |
825 GtkWidget *widget; |
| |
826 GList *labels; |
| |
827 GList *l; |
| |
828 |
| |
829 labels = gaim_request_field_choice_get_labels(field); |
| |
830 |
| |
831 if (g_list_length(labels) > 5) |
| |
832 { |
| |
833 GtkWidget *menu; |
| |
834 GtkWidget *item; |
| |
835 |
| |
836 widget = gtk_option_menu_new(); |
| |
837 |
| |
838 menu = gtk_menu_new(); |
| |
839 |
| |
840 for (l = labels; l != NULL; l = l->next) |
| |
841 { |
| |
842 const char *text = l->data; |
| |
843 |
| |
844 item = gtk_menu_item_new_with_label(text); |
| |
845 gtk_widget_show(item); |
| |
846 |
| |
847 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
| |
848 } |
| |
849 |
| |
850 gtk_widget_show(menu); |
| |
851 gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), menu); |
| |
852 gtk_option_menu_set_history(GTK_OPTION_MENU(widget), |
| |
853 gaim_request_field_choice_get_default_value(field)); |
| |
854 |
| |
855 g_signal_connect(G_OBJECT(widget), "changed", |
| |
856 G_CALLBACK(field_choice_menu_cb), field); |
| |
857 } |
| |
858 else |
| |
859 { |
| |
860 GtkWidget *box; |
| |
861 GtkWidget *first_radio = NULL; |
| |
862 GtkWidget *radio; |
| |
863 gint i; |
| |
864 |
| |
865 if (g_list_length(labels) == 2) |
| |
866 box = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
| |
867 else |
| |
868 box = gtk_vbox_new(FALSE, 0); |
| |
869 |
| |
870 widget = box; |
| |
871 |
| |
872 for (l = labels, i = 0; l != NULL; l = l->next, i++) |
| |
873 { |
| |
874 const char *text = l->data; |
| |
875 |
| |
876 radio = gtk_radio_button_new_with_label_from_widget( |
| |
877 GTK_RADIO_BUTTON(first_radio), text); |
| |
878 |
| |
879 if (first_radio == NULL) |
| |
880 first_radio = radio; |
| |
881 |
| |
882 if (i == gaim_request_field_choice_get_default_value(field)) |
| |
883 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); |
| |
884 |
| |
885 gtk_box_pack_start(GTK_BOX(box), radio, TRUE, TRUE, 0); |
| |
886 gtk_widget_show(radio); |
| |
887 |
| |
888 g_signal_connect(G_OBJECT(radio), "toggled", |
| |
889 G_CALLBACK(field_choice_option_cb), field); |
| |
890 } |
| |
891 } |
| |
892 |
| |
893 return widget; |
| |
894 } |
| |
895 |
| |
896 static GtkWidget * |
| |
897 create_image_field(GaimRequestField *field) |
| |
898 { |
| |
899 GtkWidget *widget; |
| |
900 GdkPixbuf *buf, *scale; |
| |
901 GdkPixbufLoader *loader; |
| |
902 |
| |
903 loader = gdk_pixbuf_loader_new(); |
| |
904 gdk_pixbuf_loader_write(loader, |
| |
905 (const guchar *)gaim_request_field_image_get_buffer(field), |
| |
906 gaim_request_field_image_get_size(field), |
| |
907 NULL); |
| |
908 gdk_pixbuf_loader_close(loader, NULL); |
| |
909 buf = gdk_pixbuf_loader_get_pixbuf(loader); |
| |
910 |
| |
911 scale = gdk_pixbuf_scale_simple(buf, |
| |
912 gaim_request_field_image_get_scale_x(field) * gdk_pixbuf_get_width(buf), |
| |
913 gaim_request_field_image_get_scale_y(field) * gdk_pixbuf_get_height(buf), |
| |
914 GDK_INTERP_BILINEAR); |
| |
915 widget = gtk_image_new_from_pixbuf(scale); |
| |
916 g_object_unref(G_OBJECT(buf)); |
| |
917 g_object_unref(G_OBJECT(scale)); |
| |
918 |
| |
919 return widget; |
| |
920 } |
| |
921 |
| |
922 static GtkWidget * |
| |
923 create_account_field(GaimRequestField *field) |
| |
924 { |
| |
925 GtkWidget *widget; |
| |
926 |
| |
927 widget = gaim_gtk_account_option_menu_new( |
| |
928 gaim_request_field_account_get_default_value(field), |
| |
929 gaim_request_field_account_get_show_all(field), |
| |
930 G_CALLBACK(field_account_cb), |
| |
931 gaim_request_field_account_get_filter(field), |
| |
932 field); |
| |
933 |
| |
934 return widget; |
| |
935 } |
| |
936 |
| |
937 static void |
| |
938 select_field_list_item(GtkTreeModel *model, GtkTreePath *path, |
| |
939 GtkTreeIter *iter, gpointer data) |
| |
940 { |
| |
941 GaimRequestField *field = (GaimRequestField *)data; |
| |
942 char *text; |
| |
943 |
| |
944 gtk_tree_model_get(model, iter, 1, &text, -1); |
| |
945 |
| |
946 gaim_request_field_list_add_selected(field, text); |
| |
947 g_free(text); |
| |
948 } |
| |
949 |
| |
950 static void |
| |
951 list_field_select_changed_cb(GtkTreeSelection *sel, GaimRequestField *field) |
| |
952 { |
| |
953 gaim_request_field_list_clear_selected(field); |
| |
954 |
| |
955 gtk_tree_selection_selected_foreach(sel, select_field_list_item, field); |
| |
956 } |
| |
957 |
| |
958 static GtkWidget * |
| |
959 create_list_field(GaimRequestField *field) |
| |
960 { |
| |
961 GtkWidget *sw; |
| |
962 GtkWidget *treeview; |
| |
963 GtkListStore *store; |
| |
964 GtkCellRenderer *renderer; |
| |
965 GtkTreeSelection *sel; |
| |
966 GtkTreeViewColumn *column; |
| |
967 GtkTreeIter iter; |
| |
968 const GList *l; |
| |
969 |
| |
970 /* Create the scrolled window */ |
| |
971 sw = gtk_scrolled_window_new(NULL, NULL); |
| |
972 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), |
| |
973 GTK_POLICY_AUTOMATIC, |
| |
974 GTK_POLICY_AUTOMATIC); |
| |
975 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), |
| |
976 GTK_SHADOW_IN); |
| |
977 gtk_widget_show(sw); |
| |
978 |
| |
979 /* Create the list store */ |
| |
980 store = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING); |
| |
981 |
| |
982 /* Create the tree view */ |
| |
983 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); |
| |
984 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); |
| |
985 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); |
| |
986 |
| |
987 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); |
| |
988 |
| |
989 if (gaim_request_field_list_get_multi_select(field)) |
| |
990 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE); |
| |
991 |
| |
992 g_signal_connect(G_OBJECT(sel), "changed", |
| |
993 G_CALLBACK(list_field_select_changed_cb), field); |
| |
994 |
| |
995 column = gtk_tree_view_column_new(); |
| |
996 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1); |
| |
997 |
| |
998 renderer = gtk_cell_renderer_text_new(); |
| |
999 gtk_tree_view_column_pack_start(column, renderer, TRUE); |
| |
1000 gtk_tree_view_column_add_attribute(column, renderer, "text", 1); |
| |
1001 |
| |
1002 for (l = gaim_request_field_list_get_items(field); l != NULL; l = l->next) |
| |
1003 { |
| |
1004 const char *text = (const char *)l->data; |
| |
1005 |
| |
1006 gtk_list_store_append(store, &iter); |
| |
1007 |
| |
1008 gtk_list_store_set(store, &iter, |
| |
1009 0, gaim_request_field_list_get_data(field, text), |
| |
1010 1, text, |
| |
1011 -1); |
| |
1012 |
| |
1013 if (gaim_request_field_list_is_selected(field, text)) |
| |
1014 gtk_tree_selection_select_iter(sel, &iter); |
| |
1015 } |
| |
1016 |
| |
1017 gtk_container_add(GTK_CONTAINER(sw), treeview); |
| |
1018 gtk_widget_show(treeview); |
| |
1019 |
| |
1020 return sw; |
| |
1021 } |
| |
1022 |
| |
1023 static void * |
| |
1024 gaim_gtk_request_fields(const char *title, const char *primary, |
| |
1025 const char *secondary, GaimRequestFields *fields, |
| |
1026 const char *ok_text, GCallback ok_cb, |
| |
1027 const char *cancel_text, GCallback cancel_cb, |
| |
1028 void *user_data) |
| |
1029 { |
| |
1030 GaimGtkRequestData *data; |
| |
1031 GtkWidget *win; |
| |
1032 GtkWidget *vbox; |
| |
1033 GtkWidget *vbox2; |
| |
1034 GtkWidget *hbox; |
| |
1035 GtkWidget *bbox; |
| |
1036 GtkWidget *frame; |
| |
1037 GtkWidget *label; |
| |
1038 GtkWidget *table; |
| |
1039 GtkWidget *button; |
| |
1040 GtkWidget *img; |
| |
1041 GtkWidget *sw; |
| |
1042 GtkSizeGroup *sg; |
| |
1043 GList *gl, *fl; |
| |
1044 GaimRequestFieldGroup *group; |
| |
1045 GaimRequestField *field; |
| |
1046 char *label_text; |
| |
1047 char *primary_esc, *secondary_esc; |
| |
1048 int total_fields = 0; |
| |
1049 |
| |
1050 data = g_new0(GaimGtkRequestData, 1); |
| |
1051 data->type = GAIM_REQUEST_FIELDS; |
| |
1052 data->user_data = user_data; |
| |
1053 data->u.multifield.fields = fields; |
| |
1054 |
| |
1055 fields->ui_data = data; |
| |
1056 |
| |
1057 data->cb_count = 2; |
| |
1058 data->cbs = g_new0(GCallback, 2); |
| |
1059 |
| |
1060 data->cbs[0] = ok_cb; |
| |
1061 data->cbs[1] = cancel_cb; |
| |
1062 |
| |
1063 data->dialog = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
| |
1064 |
| |
1065 if (title != NULL) |
| |
1066 gtk_window_set_title(GTK_WINDOW(win), title); |
| |
1067 |
| |
1068 gtk_window_set_role(GTK_WINDOW(win), "multifield"); |
| |
1069 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER); |
| |
1070 |
| |
1071 g_signal_connect(G_OBJECT(win), "delete_event", |
| |
1072 G_CALLBACK(destroy_multifield_cb), data); |
| |
1073 |
| |
1074 /* Setup the main horizontal box */ |
| |
1075 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
| |
1076 gtk_container_add(GTK_CONTAINER(win), hbox); |
| |
1077 gtk_widget_show(hbox); |
| |
1078 |
| |
1079 /* Dialog icon. */ |
| |
1080 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
| |
1081 GTK_ICON_SIZE_DIALOG); |
| |
1082 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); |
| |
1083 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); |
| |
1084 gtk_widget_show(img); |
| |
1085 |
| |
1086 /* Setup the vbox */ |
| |
1087 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
| |
1088 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); |
| |
1089 gtk_widget_show(vbox); |
| |
1090 |
| |
1091 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); |
| |
1092 |
| |
1093 if(primary) { |
| |
1094 primary_esc = g_markup_escape_text(primary, -1); |
| |
1095 label_text = g_strdup_printf( |
| |
1096 "<span weight=\"bold\" size=\"larger\">%s</span>", primary_esc); |
| |
1097 g_free(primary_esc); |
| |
1098 label = gtk_label_new(NULL); |
| |
1099 |
| |
1100 gtk_label_set_markup(GTK_LABEL(label), label_text); |
| |
1101 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
| |
1102 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
| |
1103 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); |
| |
1104 gtk_widget_show(label); |
| |
1105 g_free(label_text); |
| |
1106 } |
| |
1107 |
| |
1108 for (gl = gaim_request_fields_get_groups(fields); gl != NULL; |
| |
1109 gl = gl->next) |
| |
1110 total_fields += g_list_length(gaim_request_field_group_get_fields(gl->data)); |
| |
1111 |
| |
1112 if(total_fields > 9) { |
| |
1113 sw = gtk_scrolled_window_new(NULL, NULL); |
| |
1114 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), |
| |
1115 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); |
| |
1116 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), |
| |
1117 GTK_SHADOW_NONE); |
| |
1118 gtk_widget_set_size_request(sw, -1, 200); |
| |
1119 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); |
| |
1120 gtk_widget_show(sw); |
| |
1121 |
| |
1122 vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
| |
1123 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), vbox2); |
| |
1124 gtk_widget_show(vbox2); |
| |
1125 } else { |
| |
1126 vbox2 = vbox; |
| |
1127 } |
| |
1128 |
| |
1129 if (secondary) { |
| |
1130 secondary_esc = g_markup_escape_text(secondary, -1); |
| |
1131 label = gtk_label_new(NULL); |
| |
1132 |
| |
1133 gtk_label_set_markup(GTK_LABEL(label), secondary_esc); |
| |
1134 g_free(secondary_esc); |
| |
1135 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
| |
1136 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
| |
1137 gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, TRUE, 0); |
| |
1138 gtk_widget_show(label); |
| |
1139 } |
| |
1140 |
| |
1141 for (gl = gaim_request_fields_get_groups(fields); |
| |
1142 gl != NULL; |
| |
1143 gl = gl->next) |
| |
1144 { |
| |
1145 GList *field_list; |
| |
1146 size_t field_count = 0; |
| |
1147 size_t cols = 1; |
| |
1148 size_t rows; |
| |
1149 size_t col_num; |
| |
1150 size_t row_num = 0; |
| |
1151 |
| |
1152 group = gl->data; |
| |
1153 field_list = gaim_request_field_group_get_fields(group); |
| |
1154 |
| |
1155 if (gaim_request_field_group_get_title(group) != NULL) |
| |
1156 { |
| |
1157 frame = gaim_gtk_make_frame(vbox2, |
| |
1158 gaim_request_field_group_get_title(group)); |
| |
1159 } |
| |
1160 else |
| |
1161 frame = vbox2; |
| |
1162 |
| |
1163 field_count = g_list_length(field_list); |
| |
1164 /* |
| |
1165 if (field_count > 9) |
| |
1166 { |
| |
1167 rows = field_count / 2; |
| |
1168 cols++; |
| |
1169 } |
| |
1170 else |
| |
1171 */ |
| |
1172 rows = field_count; |
| |
1173 |
| |
1174 col_num = 0; |
| |
1175 |
| |
1176 for (fl = field_list; fl != NULL; fl = fl->next) |
| |
1177 { |
| |
1178 GaimRequestFieldType type; |
| |
1179 |
| |
1180 field = (GaimRequestField *)fl->data; |
| |
1181 |
| |
1182 type = gaim_request_field_get_type(field); |
| |
1183 |
| |
1184 if (type == GAIM_REQUEST_FIELD_LABEL) |
| |
1185 { |
| |
1186 if (col_num > 0) |
| |
1187 rows++; |
| |
1188 |
| |
1189 rows++; |
| |
1190 } |
| |
1191 else if ((type == GAIM_REQUEST_FIELD_LIST) || |
| |
1192 (type == GAIM_REQUEST_FIELD_STRING && |
| |
1193 gaim_request_field_string_is_multiline(field))) |
| |
1194 { |
| |
1195 if (col_num > 0) |
| |
1196 rows++; |
| |
1197 |
| |
1198 rows += 2; |
| |
1199 } |
| |
1200 |
| |
1201 col_num++; |
| |
1202 |
| |
1203 if (col_num >= cols) |
| |
1204 col_num = 0; |
| |
1205 } |
| |
1206 |
| |
1207 table = gtk_table_new(rows, 2 * cols, FALSE); |
| |
1208 gtk_table_set_row_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE); |
| |
1209 gtk_table_set_col_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE); |
| |
1210 |
| |
1211 gtk_container_add(GTK_CONTAINER(frame), table); |
| |
1212 gtk_widget_show(table); |
| |
1213 |
| |
1214 for (row_num = 0, fl = field_list; |
| |
1215 row_num < rows && fl != NULL; |
| |
1216 row_num++) |
| |
1217 { |
| |
1218 for (col_num = 0; |
| |
1219 col_num < cols && fl != NULL; |
| |
1220 col_num++, fl = fl->next) |
| |
1221 { |
| |
1222 size_t col_offset = col_num * 2; |
| |
1223 GaimRequestFieldType type; |
| |
1224 GtkWidget *widget = NULL; |
| |
1225 |
| |
1226 label = NULL; |
| |
1227 field = fl->data; |
| |
1228 |
| |
1229 if (!gaim_request_field_is_visible(field)) { |
| |
1230 col_num--; |
| |
1231 continue; |
| |
1232 } |
| |
1233 |
| |
1234 type = gaim_request_field_get_type(field); |
| |
1235 |
| |
1236 if (type != GAIM_REQUEST_FIELD_BOOLEAN && |
| |
1237 gaim_request_field_get_label(field)) |
| |
1238 { |
| |
1239 char *text; |
| |
1240 |
| |
1241 text = g_strdup_printf("%s:", |
| |
1242 gaim_request_field_get_label(field)); |
| |
1243 |
| |
1244 label = gtk_label_new(NULL); |
| |
1245 gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), text); |
| |
1246 g_free(text); |
| |
1247 |
| |
1248 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); |
| |
1249 |
| |
1250 gtk_size_group_add_widget(sg, label); |
| |
1251 |
| |
1252 if (type == GAIM_REQUEST_FIELD_LABEL || |
| |
1253 type == GAIM_REQUEST_FIELD_LIST || |
| |
1254 (type == GAIM_REQUEST_FIELD_STRING && |
| |
1255 gaim_request_field_string_is_multiline(field))) |
| |
1256 { |
| |
1257 if(col_num > 0) |
| |
1258 row_num++; |
| |
1259 |
| |
1260 gtk_table_attach_defaults(GTK_TABLE(table), label, |
| |
1261 0, 2 * cols, |
| |
1262 row_num, row_num + 1); |
| |
1263 |
| |
1264 row_num++; |
| |
1265 col_num=cols; |
| |
1266 } |
| |
1267 else |
| |
1268 { |
| |
1269 gtk_table_attach_defaults(GTK_TABLE(table), label, |
| |
1270 col_offset, col_offset + 1, |
| |
1271 row_num, row_num + 1); |
| |
1272 } |
| |
1273 |
| |
1274 gtk_widget_show(label); |
| |
1275 } |
| |
1276 |
| |
1277 if (field->ui_data != NULL) |
| |
1278 widget = GTK_WIDGET(field->ui_data); |
| |
1279 else if (type == GAIM_REQUEST_FIELD_STRING) |
| |
1280 widget = create_string_field(field); |
| |
1281 else if (type == GAIM_REQUEST_FIELD_INTEGER) |
| |
1282 widget = create_int_field(field); |
| |
1283 else if (type == GAIM_REQUEST_FIELD_BOOLEAN) |
| |
1284 widget = create_bool_field(field); |
| |
1285 else if (type == GAIM_REQUEST_FIELD_CHOICE) |
| |
1286 widget = create_choice_field(field); |
| |
1287 else if (type == GAIM_REQUEST_FIELD_LIST) |
| |
1288 widget = create_list_field(field); |
| |
1289 else if (type == GAIM_REQUEST_FIELD_IMAGE) |
| |
1290 widget = create_image_field(field); |
| |
1291 else if (type == GAIM_REQUEST_FIELD_ACCOUNT) |
| |
1292 widget = create_account_field(field); |
| |
1293 else |
| |
1294 continue; |
| |
1295 |
| |
1296 if (label) |
| |
1297 gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget); |
| |
1298 |
| |
1299 if (type == GAIM_REQUEST_FIELD_STRING && |
| |
1300 gaim_request_field_string_is_multiline(field)) |
| |
1301 { |
| |
1302 gtk_table_attach(GTK_TABLE(table), widget, |
| |
1303 0, 2 * cols, |
| |
1304 row_num, row_num + 1, |
| |
1305 GTK_FILL | GTK_EXPAND, |
| |
1306 GTK_FILL | GTK_EXPAND, |
| |
1307 5, 0); |
| |
1308 } |
| |
1309 else if (type == GAIM_REQUEST_FIELD_LIST) |
| |
1310 { |
| |
1311 gtk_table_attach(GTK_TABLE(table), widget, |
| |
1312 0, 2 * cols, |
| |
1313 row_num, row_num + 1, |
| |
1314 GTK_FILL | GTK_EXPAND, |
| |
1315 GTK_FILL | GTK_EXPAND, |
| |
1316 5, 0); |
| |
1317 } |
| |
1318 else if (type == GAIM_REQUEST_FIELD_BOOLEAN) |
| |
1319 { |
| |
1320 gtk_table_attach(GTK_TABLE(table), widget, |
| |
1321 col_offset, col_offset + 1, |
| |
1322 row_num, row_num + 1, |
| |
1323 GTK_FILL | GTK_EXPAND, |
| |
1324 GTK_FILL | GTK_EXPAND, |
| |
1325 5, 0); |
| |
1326 } |
| |
1327 else |
| |
1328 { |
| |
1329 gtk_table_attach(GTK_TABLE(table), widget, |
| |
1330 1, 2 * cols, |
| |
1331 row_num, row_num + 1, |
| |
1332 GTK_FILL | GTK_EXPAND, |
| |
1333 GTK_FILL | GTK_EXPAND, |
| |
1334 5, 0); |
| |
1335 } |
| |
1336 |
| |
1337 gtk_widget_show(widget); |
| |
1338 |
| |
1339 field->ui_data = widget; |
| |
1340 } |
| |
1341 } |
| |
1342 } |
| |
1343 |
| |
1344 g_object_unref(sg); |
| |
1345 |
| |
1346 /* Button box. */ |
| |
1347 bbox = gtk_hbutton_box_new(); |
| |
1348 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE); |
| |
1349 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); |
| |
1350 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); |
| |
1351 gtk_widget_show(bbox); |
| |
1352 |
| |
1353 /* Cancel button */ |
| |
1354 button = gtk_button_new_from_stock(text_to_stock(cancel_text)); |
| |
1355 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); |
| |
1356 gtk_widget_show(button); |
| |
1357 |
| |
1358 g_signal_connect(G_OBJECT(button), "clicked", |
| |
1359 G_CALLBACK(multifield_cancel_cb), data); |
| |
1360 |
| |
1361 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); |
| |
1362 |
| |
1363 /* OK button */ |
| |
1364 button = gtk_button_new_from_stock(text_to_stock(ok_text)); |
| |
1365 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); |
| |
1366 gtk_widget_show(button); |
| |
1367 |
| |
1368 data->ok_button = button; |
| |
1369 |
| |
1370 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); |
| |
1371 gtk_window_set_default(GTK_WINDOW(win), button); |
| |
1372 |
| |
1373 g_signal_connect(G_OBJECT(button), "clicked", |
| |
1374 G_CALLBACK(multifield_ok_cb), data); |
| |
1375 |
| |
1376 if (!gaim_request_fields_all_required_filled(fields)) |
| |
1377 gtk_widget_set_sensitive(button, FALSE); |
| |
1378 |
| |
1379 gtk_widget_show(win); |
| |
1380 |
| |
1381 return data; |
| |
1382 } |
| |
1383 |
| |
1384 static void |
| |
1385 file_yes_no_cb(GaimGtkRequestData *data, gint id) |
| |
1386 { |
| |
1387 /* Only call the callback if yes was selected, otherwise the request |
| |
1388 * (eg. file transfer) will be cancelled, then when a new filename is chosen |
| |
1389 * things go BOOM */ |
| |
1390 if (id == 1) { |
| |
1391 if (data->cbs[1] != NULL) |
| |
1392 ((GaimRequestFileCb)data->cbs[1])(data->user_data, data->u.file.name); |
| |
1393 gaim_request_close(data->type, data); |
| |
1394 } else { |
| |
1395 gaim_gtk_clear_cursor(GTK_WIDGET(data->dialog)); |
| |
1396 } |
| |
1397 } |
| |
1398 |
| |
1399 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
| |
1400 static void |
| |
1401 file_ok_check_if_exists_cb(GtkWidget *widget, gint response, GaimGtkRequestData *data) |
| |
1402 { |
| |
1403 gchar *current_folder; |
| |
1404 |
| |
1405 generic_response_start(data); |
| |
1406 |
| |
1407 if (response != GTK_RESPONSE_ACCEPT) { |
| |
1408 if (data->cbs[0] != NULL) |
| |
1409 ((GaimRequestFileCb)data->cbs[0])(data->user_data, NULL); |
| |
1410 gaim_request_close(data->type, data); |
| |
1411 return; |
| |
1412 } |
| |
1413 |
| |
1414 data->u.file.name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(data->dialog)); |
| |
1415 current_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(data->dialog)); |
| |
1416 if (current_folder != NULL) { |
| |
1417 if (data->u.file.savedialog) { |
| |
1418 gaim_prefs_set_path("/gaim/gtk/filelocations/last_save_folder", current_folder); |
| |
1419 } else { |
| |
1420 gaim_prefs_set_path("/gaim/gtk/filelocations/last_open_folder", current_folder); |
| |
1421 } |
| |
1422 g_free(current_folder); |
| |
1423 } |
| |
1424 |
| |
1425 #else /* FILECHOOSER */ |
| |
1426 |
| |
1427 static void |
| |
1428 file_ok_check_if_exists_cb(GtkWidget *button, GaimGtkRequestData *data) |
| |
1429 { |
| |
1430 const gchar *name; |
| |
1431 gchar *current_folder; |
| |
1432 |
| |
1433 generic_response_start(data); |
| |
1434 |
| |
1435 name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(data->dialog)); |
| |
1436 |
| |
1437 /* If name is a directory then change directories */ |
| |
1438 if (data->type == GAIM_REQUEST_FILE) { |
| |
1439 if (gaim_gtk_check_if_dir(name, GTK_FILE_SELECTION(data->dialog))) |
| |
1440 return; |
| |
1441 } |
| |
1442 |
| |
1443 current_folder = g_path_get_dirname(name); |
| |
1444 |
| |
1445 g_free(data->u.file.name); |
| |
1446 if (data->type == GAIM_REQUEST_FILE) |
| |
1447 data->u.file.name = g_strdup(name); |
| |
1448 else |
| |
1449 { |
| |
1450 if (g_file_test(name, G_FILE_TEST_IS_DIR)) |
| |
1451 data->u.file.name = g_strdup(name); |
| |
1452 else |
| |
1453 data->u.file.name = g_strdup(current_folder); |
| |
1454 } |
| |
1455 |
| |
1456 if (current_folder != NULL) { |
| |
1457 if (data->u.file.savedialog) { |
| |
1458 gaim_prefs_set_path("/gaim/gtk/filelocations/last_save_folder", current_folder); |
| |
1459 } else { |
| |
1460 gaim_prefs_set_path("/gaim/gtk/filelocations/last_open_folder", current_folder); |
| |
1461 } |
| |
1462 g_free(current_folder); |
| |
1463 } |
| |
1464 |
| |
1465 #endif /* FILECHOOSER */ |
| |
1466 |
| |
1467 if ((data->u.file.savedialog == TRUE) && |
| |
1468 (g_file_test(data->u.file.name, G_FILE_TEST_EXISTS))) { |
| |
1469 gaim_request_action(data, NULL, _("That file already exists"), |
| |
1470 _("Would you like to overwrite it?"), 0, data, 2, |
| |
1471 _("Overwrite"), G_CALLBACK(file_yes_no_cb), |
| |
1472 _("Choose New Name"), G_CALLBACK(file_yes_no_cb)); |
| |
1473 } else |
| |
1474 file_yes_no_cb(data, 1); |
| |
1475 } |
| |
1476 |
| |
1477 #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
| |
1478 static void |
| |
1479 file_cancel_cb(GaimGtkRequestData *data) |
| |
1480 { |
| |
1481 generic_response_start(data); |
| |
1482 |
| |
1483 if (data->cbs[0] != NULL) |
| |
1484 ((GaimRequestFileCb)data->cbs[0])(data->user_data, NULL); |
| |
1485 |
| |
1486 gaim_request_close(data->type, data); |
| |
1487 } |
| |
1488 #endif /* FILECHOOSER */ |
| |
1489 |
| |
1490 static void * |
| |
1491 gaim_gtk_request_file(const char *title, const char *filename, |
| |
1492 gboolean savedialog, |
| |
1493 GCallback ok_cb, GCallback cancel_cb, |
| |
1494 void *user_data) |
| |
1495 { |
| |
1496 GaimGtkRequestData *data; |
| |
1497 GtkWidget *filesel; |
| |
1498 const gchar *current_folder; |
| |
1499 #if GTK_CHECK_VERSION(2,4,0) |
| |
1500 gboolean folder_set = FALSE; |
| |
1501 #endif |
| |
1502 |
| |
1503 data = g_new0(GaimGtkRequestData, 1); |
| |
1504 data->type = GAIM_REQUEST_FILE; |
| |
1505 data->user_data = user_data; |
| |
1506 data->cb_count = 2; |
| |
1507 data->cbs = g_new0(GCallback, 2); |
| |
1508 data->cbs[0] = cancel_cb; |
| |
1509 data->cbs[1] = ok_cb; |
| |
1510 data->u.file.savedialog = savedialog; |
| |
1511 |
| |
1512 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
| |
1513 filesel = gtk_file_chooser_dialog_new( |
| |
1514 title ? title : (savedialog ? _("Save File...") |
| |
1515 : _("Open File...")), |
| |
1516 NULL, |
| |
1517 savedialog ? GTK_FILE_CHOOSER_ACTION_SAVE |
| |
1518 : GTK_FILE_CHOOSER_ACTION_OPEN, |
| |
1519 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| |
1520 savedialog ? GTK_STOCK_SAVE |
| |
1521 : GTK_STOCK_OPEN, |
| |
1522 GTK_RESPONSE_ACCEPT, |
| |
1523 NULL); |
| |
1524 gtk_dialog_set_default_response(GTK_DIALOG(filesel), GTK_RESPONSE_ACCEPT); |
| |
1525 |
| |
1526 if (savedialog) { |
| |
1527 current_folder = gaim_prefs_get_path("/gaim/gtk/filelocations/last_save_folder"); |
| |
1528 } else { |
| |
1529 current_folder = gaim_prefs_get_path("/gaim/gtk/filelocations/last_open_folder"); |
| |
1530 } |
| |
1531 |
| |
1532 if ((filename != NULL) && (*filename != '\0')) { |
| |
1533 if (savedialog) |
| |
1534 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(filesel), filename); |
| |
1535 else |
| |
1536 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(filesel), filename); |
| |
1537 } |
| |
1538 if ((current_folder != NULL) && (*current_folder != '\0')) { |
| |
1539 folder_set = gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filesel), current_folder); |
| |
1540 } |
| |
1541 |
| |
1542 #ifdef _WIN32 |
| |
1543 if (!folder_set) { |
| |
1544 char *my_documents = wgaim_get_special_folder(CSIDL_PERSONAL); |
| |
1545 |
| |
1546 if (my_documents != NULL) { |
| |
1547 gtk_file_chooser_set_current_folder( |
| |
1548 GTK_FILE_CHOOSER(filesel), my_documents); |
| |
1549 |
| |
1550 g_free(my_documents); |
| |
1551 } |
| |
1552 } |
| |
1553 |
| |
1554 #endif |
| |
1555 g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(filesel)), "response", |
| |
1556 G_CALLBACK(file_ok_check_if_exists_cb), data); |
| |
1557 #else /* FILECHOOSER */ |
| |
1558 filesel = gtk_file_selection_new( |
| |
1559 title ? title : (savedialog ? _("Save File...") |
| |
1560 : _("Open File..."))); |
| |
1561 if (savedialog) { |
| |
1562 current_folder = gaim_prefs_get_path("/gaim/gtk/filelocations/last_save_folder"); |
| |
1563 } else { |
| |
1564 current_folder = gaim_prefs_get_path("/gaim/gtk/filelocations/last_open_folder"); |
| |
1565 } |
| |
1566 if (current_folder != NULL) { |
| |
1567 gchar *path = g_strdup_printf("%s%s", current_folder, G_DIR_SEPARATOR_S); |
| |
1568 gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), path); |
| |
1569 g_free(path); |
| |
1570 } |
| |
1571 if (filename != NULL) |
| |
1572 gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), filename); |
| |
1573 |
| |
1574 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(filesel)), "delete_event", |
| |
1575 G_CALLBACK(file_cancel_cb), data); |
| |
1576 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(filesel)->cancel_button), |
| |
1577 "clicked", G_CALLBACK(file_cancel_cb), data); |
| |
1578 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked", |
| |
1579 G_CALLBACK(file_ok_check_if_exists_cb), data); |
| |
1580 #endif /* FILECHOOSER */ |
| |
1581 |
| |
1582 data->dialog = filesel; |
| |
1583 gtk_widget_show(filesel); |
| |
1584 |
| |
1585 return (void *)data; |
| |
1586 } |
| |
1587 |
| |
1588 static void * |
| |
1589 gaim_gtk_request_folder(const char *title, const char *dirname, |
| |
1590 GCallback ok_cb, GCallback cancel_cb, |
| |
1591 void *user_data) |
| |
1592 { |
| |
1593 GaimGtkRequestData *data; |
| |
1594 GtkWidget *dirsel; |
| |
1595 |
| |
1596 data = g_new0(GaimGtkRequestData, 1); |
| |
1597 data->type = GAIM_REQUEST_FOLDER; |
| |
1598 data->user_data = user_data; |
| |
1599 data->cb_count = 2; |
| |
1600 data->cbs = g_new0(GCallback, 2); |
| |
1601 data->cbs[0] = cancel_cb; |
| |
1602 data->cbs[1] = ok_cb; |
| |
1603 data->u.file.savedialog = FALSE; |
| |
1604 |
| |
1605 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
| |
1606 dirsel = gtk_file_chooser_dialog_new( |
| |
1607 title ? title : _("Select Folder..."), |
| |
1608 NULL, |
| |
1609 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, |
| |
1610 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| |
1611 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, |
| |
1612 NULL); |
| |
1613 gtk_dialog_set_default_response(GTK_DIALOG(dirsel), GTK_RESPONSE_ACCEPT); |
| |
1614 |
| |
1615 if ((dirname != NULL) && (*dirname != '\0')) |
| |
1616 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dirsel), dirname); |
| |
1617 |
| |
1618 g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(dirsel)), "response", |
| |
1619 G_CALLBACK(file_ok_check_if_exists_cb), data); |
| |
1620 #else |
| |
1621 dirsel = gtk_file_selection_new(title ? title : _("Select Folder...")); |
| |
1622 |
| |
1623 g_signal_connect_swapped(G_OBJECT(dirsel), "delete_event", |
| |
1624 G_CALLBACK(file_cancel_cb), data); |
| |
1625 g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(dirsel)->cancel_button), |
| |
1626 "clicked", G_CALLBACK(file_cancel_cb), data); |
| |
1627 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(dirsel)->ok_button), "clicked", |
| |
1628 G_CALLBACK(file_ok_check_if_exists_cb), data); |
| |
1629 #endif |
| |
1630 |
| |
1631 data->dialog = dirsel; |
| |
1632 gtk_widget_show(dirsel); |
| |
1633 |
| |
1634 return (void *)data; |
| |
1635 } |
| |
1636 |
| |
1637 static void |
| |
1638 gaim_gtk_close_request(GaimRequestType type, void *ui_handle) |
| |
1639 { |
| |
1640 GaimGtkRequestData *data = (GaimGtkRequestData *)ui_handle; |
| |
1641 |
| |
1642 g_free(data->cbs); |
| |
1643 |
| |
1644 gtk_widget_destroy(data->dialog); |
| |
1645 |
| |
1646 if (type == GAIM_REQUEST_FIELDS) |
| |
1647 gaim_request_fields_destroy(data->u.multifield.fields); |
| |
1648 else if (type == GAIM_REQUEST_FILE) |
| |
1649 g_free(data->u.file.name); |
| |
1650 |
| |
1651 g_free(data); |
| |
1652 } |
| |
1653 |
| |
1654 static GaimRequestUiOps ops = |
| |
1655 { |
| |
1656 gaim_gtk_request_input, |
| |
1657 gaim_gtk_request_choice, |
| |
1658 gaim_gtk_request_action, |
| |
1659 gaim_gtk_request_fields, |
| |
1660 gaim_gtk_request_file, |
| |
1661 gaim_gtk_close_request, |
| |
1662 gaim_gtk_request_folder |
| |
1663 }; |
| |
1664 |
| |
1665 GaimRequestUiOps * |
| |
1666 gaim_gtk_request_get_ui_ops(void) |
| |
1667 { |
| |
1668 return &ops; |
| |
1669 } |