comparison finch/gntrequest.c @ 15818:0e3a8505ebbe

renamed gaim-text to finch
author Sean Egan <seanegan@gmail.com>
date Sun, 18 Mar 2007 19:38:15 +0000
parents
children 32c366eeeb99 f59cfcce68a8
comparison
equal deleted inserted replaced
15817:317e7613e581 15818:0e3a8505ebbe
1 /**
2 * @file gntrequest.c GNT Request API
3 * @ingroup gntui
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 <gnt.h>
26 #include <gntbox.h>
27 #include <gntbutton.h>
28 #include <gntcheckbox.h>
29 #include <gntcombobox.h>
30 #include <gntentry.h>
31 #include <gntlabel.h>
32 #include <gntline.h>
33 #include <gnttree.h>
34
35 #include "gntgaim.h"
36 #include "gntrequest.h"
37 #include "util.c"
38
39 typedef struct
40 {
41 void *user_data;
42 GntWidget *entry, *dialog;
43 GCallback *cbs;
44 } GaimGntFileRequest;
45
46 static GntWidget *
47 setup_request_window(const char *title, const char *primary,
48 const char *secondary, GaimRequestType type)
49 {
50 GntWidget *window;
51
52 window = gnt_vbox_new(FALSE);
53 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
54 gnt_box_set_title(GNT_BOX(window), title);
55 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
56
57 if (primary)
58 gnt_box_add_widget(GNT_BOX(window),
59 gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD));
60 if (secondary)
61 gnt_box_add_widget(GNT_BOX(window), gnt_label_new(secondary));
62
63 g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gaim_request_close),
64 GINT_TO_POINTER(type));
65
66 return window;
67 }
68
69 static GntWidget *
70 setup_button_box(gpointer userdata, gpointer cb, gpointer data, ...)
71 {
72 GntWidget *box, *button;
73 va_list list;
74 const char *text;
75 gpointer callback;
76
77 box = gnt_hbox_new(FALSE);
78
79 va_start(list, data);
80
81 while ((text = va_arg(list, const char *)))
82 {
83 callback = va_arg(list, gpointer);
84 button = gnt_button_new(text);
85 gnt_box_add_widget(GNT_BOX(box), button);
86 g_object_set_data(G_OBJECT(button), "activate-callback", callback);
87 g_object_set_data(G_OBJECT(button), "activate-userdata", userdata);
88 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data);
89 }
90
91 va_end(list);
92 return box;
93 }
94
95 static void
96 notify_input_cb(GntWidget *button, GntWidget *entry)
97 {
98 GaimRequestInputCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
99 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
100 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
101
102 if (callback)
103 callback(data, text);
104
105 while (button->parent)
106 button = button->parent;
107
108 gaim_request_close(GAIM_REQUEST_INPUT, button);
109 }
110
111 static void *
112 finch_request_input(const char *title, const char *primary,
113 const char *secondary, const char *default_value,
114 gboolean multiline, gboolean masked, gchar *hint,
115 const char *ok_text, GCallback ok_cb,
116 const char *cancel_text, GCallback cancel_cb,
117 void *user_data)
118 {
119 GntWidget *window, *box, *entry;
120
121 window = setup_request_window(title, primary, secondary, GAIM_REQUEST_INPUT);
122
123 entry = gnt_entry_new(default_value);
124 if (masked)
125 gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
126 gnt_box_add_widget(GNT_BOX(window), entry);
127
128 box = setup_button_box(user_data, notify_input_cb, entry,
129 ok_text, ok_cb, cancel_text, cancel_cb, NULL);
130 gnt_box_add_widget(GNT_BOX(window), box);
131
132 gnt_widget_show(window);
133
134 return window;
135 }
136
137 static void
138 finch_close_request(GaimRequestType type, gpointer ui_handle)
139 {
140 GntWidget *widget = GNT_WIDGET(ui_handle);
141 while (widget->parent)
142 widget = widget->parent;
143 gnt_widget_destroy(widget);
144 }
145
146 static void
147 request_choice_cb(GntWidget *button, GntComboBox *combo)
148 {
149 GaimRequestChoiceCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
150 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
151 int choice = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))) - 1;
152
153 if (callback)
154 callback(data, choice);
155
156 while (button->parent)
157 button = button->parent;
158
159 gaim_request_close(GAIM_REQUEST_INPUT, button);
160 }
161
162 static void *
163 finch_request_choice(const char *title, const char *primary,
164 const char *secondary, unsigned int default_value,
165 const char *ok_text, GCallback ok_cb,
166 const char *cancel_text, GCallback cancel_cb,
167 void *user_data, va_list choices)
168 {
169 GntWidget *window, *combo, *box;
170 const char *text;
171 int val;
172
173 window = setup_request_window(title, primary, secondary, GAIM_REQUEST_CHOICE);
174
175 combo = gnt_combo_box_new();
176 gnt_box_add_widget(GNT_BOX(window), combo);
177 while ((text = va_arg(choices, const char *)))
178 {
179 val = va_arg(choices, int);
180 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), GINT_TO_POINTER(val + 1), text);
181 }
182 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), GINT_TO_POINTER(default_value + 1));
183
184 box = setup_button_box(user_data, request_choice_cb, combo,
185 ok_text, ok_cb, cancel_text, cancel_cb, NULL);
186 gnt_box_add_widget(GNT_BOX(window), box);
187
188 gnt_widget_show(window);
189
190 return window;
191 }
192
193 static void
194 request_action_cb(GntWidget *button, GntWidget *window)
195 {
196 GaimRequestActionCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
197 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
198 int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "activate-id"));
199
200 if (callback)
201 callback(data, id);
202
203 gaim_request_close(GAIM_REQUEST_ACTION, window);
204 }
205
206 static void*
207 finch_request_action(const char *title, const char *primary,
208 const char *secondary, unsigned int default_value,
209 void *user_data, size_t actioncount,
210 va_list actions)
211 {
212 GntWidget *window, *box, *button;
213 int i;
214
215 window = setup_request_window(title, primary, secondary, GAIM_REQUEST_ACTION);
216
217 box = gnt_hbox_new(FALSE);
218 gnt_box_add_widget(GNT_BOX(window), box);
219 for (i = 0; i < actioncount; i++)
220 {
221 const char *text = va_arg(actions, const char *);
222 GaimRequestActionCb callback = va_arg(actions, GaimRequestActionCb);
223
224 button = gnt_button_new(text);
225 gnt_box_add_widget(GNT_BOX(box), button);
226
227 g_object_set_data(G_OBJECT(button), "activate-callback", callback);
228 g_object_set_data(G_OBJECT(button), "activate-userdata", user_data);
229 g_object_set_data(G_OBJECT(button), "activate-id", GINT_TO_POINTER(i));
230 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(request_action_cb), window);
231 }
232
233 gnt_widget_show(window);
234
235 return window;
236 }
237
238 static void
239 request_fields_cb(GntWidget *button, GaimRequestFields *fields)
240 {
241 GaimRequestFieldsCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
242 gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
243 GList *list;
244
245 /* Update the data of the fields. GtkGaim does this differently. Instead of
246 * updating the fields at the end like here, it updates the appropriate field
247 * instantly whenever a change is made. That allows it to make sure the
248 * 'required' fields are entered before the user can hit OK. It's not the case
249 * here, althought it can be done. I am not honouring the 'required' fields
250 * for the moment. */
251 for (list = gaim_request_fields_get_groups(fields); list; list = list->next)
252 {
253 GaimRequestFieldGroup *group = list->data;
254 GList *fields = gaim_request_field_group_get_fields(group);
255
256 for (; fields ; fields = fields->next)
257 {
258 GaimRequestField *field = fields->data;
259 GaimRequestFieldType type = gaim_request_field_get_type(field);
260 if (type == GAIM_REQUEST_FIELD_BOOLEAN)
261 {
262 GntWidget *check = field->ui_data;
263 gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check));
264 gaim_request_field_bool_set_value(field, value);
265 }
266 else if (type == GAIM_REQUEST_FIELD_STRING)
267 {
268 GntWidget *entry = field->ui_data;
269 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
270 gaim_request_field_string_set_value(field, (text && *text) ? text : NULL);
271 }
272 else if (type == GAIM_REQUEST_FIELD_INTEGER)
273 {
274 GntWidget *entry = field->ui_data;
275 const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
276 int value = (text && *text) ? atoi(text) : 0;
277 gaim_request_field_int_set_value(field, value);
278 }
279 else if (type == GAIM_REQUEST_FIELD_CHOICE)
280 {
281 GntWidget *combo = field->ui_data;
282 int id;
283 id = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)));
284 gaim_request_field_choice_set_value(field, id);
285 }
286 else if (type == GAIM_REQUEST_FIELD_LIST)
287 {
288 GList *list = NULL;
289 if (gaim_request_field_list_get_multi_select(field))
290 {
291 const GList *iter;
292 GntWidget *tree = field->ui_data;
293
294 iter = gaim_request_field_list_get_items(field);
295 for (; iter; iter = iter->next)
296 {
297 const char *text = iter->data;
298 gpointer key = gaim_request_field_list_get_data(field, text);
299 if (gnt_tree_get_choice(GNT_TREE(tree), key))
300 list = g_list_prepend(list, key);
301 }
302 }
303 else
304 {
305 GntWidget *combo = field->ui_data;
306 gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
307 list = g_list_append(list, data);
308 }
309
310 gaim_request_field_list_set_selected(field, list);
311 g_list_free(list);
312 }
313 else if (type == GAIM_REQUEST_FIELD_ACCOUNT)
314 {
315 GntWidget *combo = field->ui_data;
316 GaimAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
317 gaim_request_field_account_set_value(field, acc);
318 }
319 }
320 }
321
322 if (callback)
323 callback(data, fields);
324
325 while (button->parent)
326 button = button->parent;
327
328 gaim_request_close(GAIM_REQUEST_FIELDS, button);
329 }
330
331 static void *
332 finch_request_fields(const char *title, const char *primary,
333 const char *secondary, GaimRequestFields *allfields,
334 const char *ok, GCallback ok_cb,
335 const char *cancel, GCallback cancel_cb,
336 void *userdata)
337 {
338 GntWidget *window, *box;
339 GList *grlist;
340
341 window = setup_request_window(title, primary, secondary, GAIM_REQUEST_FIELDS);
342
343 /* This is how it's going to work: the request-groups are going to be
344 * stacked vertically one after the other. A GntLine will be separating
345 * the groups. */
346 box = gnt_vbox_new(FALSE);
347 gnt_box_set_pad(GNT_BOX(box), 0);
348 gnt_box_set_fill(GNT_BOX(box), TRUE);
349 for (grlist = gaim_request_fields_get_groups(allfields); grlist; grlist = grlist->next)
350 {
351 GaimRequestFieldGroup *group = grlist->data;
352 GList *fields = gaim_request_field_group_get_fields(group);
353 GntWidget *hbox;
354 const char *title = gaim_request_field_group_get_title(group);
355
356 if (title)
357 gnt_box_add_widget(GNT_BOX(box),
358 gnt_label_new_with_format(title, GNT_TEXT_FLAG_BOLD));
359
360 for (; fields ; fields = fields->next)
361 {
362 /* XXX: Break each of the fields into a separate function? */
363 GaimRequestField *field = fields->data;
364 GaimRequestFieldType type = gaim_request_field_get_type(field);
365 const char *label = gaim_request_field_get_label(field);
366
367 hbox = gnt_hbox_new(TRUE); /* hrm */
368 gnt_box_add_widget(GNT_BOX(box), hbox);
369
370 if (type != GAIM_REQUEST_FIELD_BOOLEAN && label)
371 {
372 GntWidget *l = gnt_label_new(label);
373 gnt_widget_set_size(l, 0, 1);
374 gnt_box_add_widget(GNT_BOX(hbox), l);
375 }
376
377 if (type == GAIM_REQUEST_FIELD_BOOLEAN)
378 {
379 GntWidget *check = gnt_check_box_new(label);
380 gnt_check_box_set_checked(GNT_CHECK_BOX(check),
381 gaim_request_field_bool_get_default_value(field));
382 gnt_box_add_widget(GNT_BOX(hbox), check);
383 field->ui_data = check;
384 }
385 else if (type == GAIM_REQUEST_FIELD_STRING)
386 {
387 GntWidget *entry = gnt_entry_new(
388 gaim_request_field_string_get_default_value(field));
389 gnt_entry_set_masked(GNT_ENTRY(entry),
390 gaim_request_field_string_is_masked(field));
391 gnt_box_add_widget(GNT_BOX(hbox), entry);
392 field->ui_data = entry;
393 }
394 else if (type == GAIM_REQUEST_FIELD_INTEGER)
395 {
396 char str[256];
397 int val = gaim_request_field_int_get_default_value(field);
398 GntWidget *entry;
399
400 snprintf(str, sizeof(str), "%d", val);
401 entry = gnt_entry_new(str);
402 gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
403 gnt_box_add_widget(GNT_BOX(hbox), entry);
404 field->ui_data = entry;
405 }
406 else if (type == GAIM_REQUEST_FIELD_CHOICE)
407 {
408 int id;
409 const GList *list;
410 GntWidget *combo = gnt_combo_box_new();
411 gnt_box_add_widget(GNT_BOX(hbox), combo);
412 field->ui_data = combo;
413
414 list = gaim_request_field_choice_get_labels(field);
415 for (id = 1; list; list = list->next, id++)
416 {
417 gnt_combo_box_add_data(GNT_COMBO_BOX(combo),
418 GINT_TO_POINTER(id), list->data);
419 }
420 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo),
421 GINT_TO_POINTER(gaim_request_field_choice_get_default_value(field)));
422 }
423 else if (type == GAIM_REQUEST_FIELD_LIST)
424 {
425 const GList *list;
426 gboolean multi = gaim_request_field_list_get_multi_select(field);
427 if (multi)
428 {
429 GntWidget *tree = gnt_tree_new();
430 gnt_box_add_widget(GNT_BOX(hbox), tree);
431 field->ui_data = tree;
432
433 list = gaim_request_field_list_get_items(field);
434 for (; list; list = list->next)
435 {
436 const char *text = list->data;
437 gpointer key = gaim_request_field_list_get_data(field, text);
438 gnt_tree_add_choice(GNT_TREE(tree), key,
439 gnt_tree_create_row(GNT_TREE(tree), text), NULL, NULL);
440 if (gaim_request_field_list_is_selected(field, text))
441 gnt_tree_set_choice(GNT_TREE(tree), key, TRUE);
442 }
443 }
444 else
445 {
446 GntWidget *combo = gnt_combo_box_new();
447 gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
448 gnt_box_add_widget(GNT_BOX(hbox), combo);
449 field->ui_data = combo;
450
451 list = gaim_request_field_list_get_items(field);
452 for (; list; list = list->next)
453 {
454 const char *text = list->data;
455 gpointer key = gaim_request_field_list_get_data(field, text);
456 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), key, text);
457 if (gaim_request_field_list_is_selected(field, text))
458 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), key);
459 }
460 }
461 }
462 else if (type == GAIM_REQUEST_FIELD_ACCOUNT)
463 {
464 gboolean all;
465 GaimAccount *def;
466 GList *list;
467 GntWidget *combo = gnt_combo_box_new();
468 gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
469 gnt_box_add_widget(GNT_BOX(hbox), combo);
470 field->ui_data = combo;
471
472 all = gaim_request_field_account_get_show_all(field);
473 def = gaim_request_field_account_get_default_value(field);
474
475 if (all)
476 list = gaim_accounts_get_all();
477 else
478 list = gaim_connections_get_all();
479
480 for (; list; list = list->next)
481 {
482 GaimAccount *account;
483 char *text;
484
485 if (all)
486 account = list->data;
487 else
488 account = gaim_connection_get_account(list->data);
489
490 text = g_strdup_printf("%s (%s)",
491 gaim_account_get_username(account),
492 gaim_account_get_protocol_name(account));
493 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), account, text);
494 g_free(text);
495 if (account == def)
496 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), account);
497 }
498 gnt_widget_set_size(combo, 20, 3); /* ew */
499 }
500 else
501 {
502 gnt_box_add_widget(GNT_BOX(hbox),
503 gnt_label_new_with_format(_("Not implemented yet."),
504 GNT_TEXT_FLAG_BOLD));
505 }
506 }
507 if (grlist->next)
508 gnt_box_add_widget(GNT_BOX(box), gnt_hline_new());
509 }
510 gnt_box_add_widget(GNT_BOX(window), box);
511
512 box = setup_button_box(userdata, request_fields_cb, allfields,
513 ok, ok_cb, cancel, cancel_cb, NULL);
514 gnt_box_add_widget(GNT_BOX(window), box);
515
516 gnt_widget_show(window);
517
518 return window;
519 }
520
521 static void
522 file_cancel_cb(GntWidget *wid, gpointer fq)
523 {
524 GaimGntFileRequest *data = fq;
525 if (data->cbs[1] != NULL)
526 ((GaimRequestFileCb)data->cbs[1])(data->user_data, NULL);
527
528 gaim_request_close(GAIM_REQUEST_FILE, data->dialog);
529 }
530
531 static void
532 file_ok_cb(GntWidget *wid, gpointer fq)
533 {
534 GaimGntFileRequest *data = fq;
535 if (data->cbs[0] != NULL)
536 ((GaimRequestFileCb)data->cbs[0])(data->user_data, gnt_entry_get_text(GNT_ENTRY(data->entry)));
537
538 gaim_request_close(GAIM_REQUEST_FILE, data->dialog);
539 }
540
541 static void
542 file_request_destroy(GaimGntFileRequest *data)
543 {
544 g_free(data->cbs);
545 g_free(data);
546 }
547
548 static void *
549 finch_request_file(const char *title, const char *filename,
550 gboolean savedialog,
551 GCallback ok_cb, GCallback cancel_cb,
552 void *user_data)
553 {
554 GntWidget *window = gnt_vbox_new(FALSE);
555 GntWidget *entry, *hbox, *button;
556 GaimGntFileRequest *data = g_new0(GaimGntFileRequest, 1);
557
558 data->user_data = user_data;
559 data->cbs = g_new0(GCallback, 2);
560 data->cbs[0] = ok_cb;
561 data->cbs[1] = cancel_cb;
562 data->dialog = window;
563 data->entry = entry = gnt_entry_new(g_strconcat(gaim_home_dir(), G_DIR_SEPARATOR_S, filename, NULL));
564 gnt_widget_set_size(entry, 30, 1);
565 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
566 gnt_box_set_title(GNT_BOX(window), title ? title : (savedialog ? _("Save File...") : _("Open File...")));
567 #if 0
568 /* After the string freeze */
569 gnt_box_add_widget(GNT_BOX(window), gnt_label_new(_("Please enter a full path for a file")));
570 #endif
571 gnt_box_add_widget(GNT_BOX(window), entry);
572
573 hbox = gnt_hbox_new(TRUE);
574 gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
575
576 button = gnt_button_new(_("Cancel"));
577 g_signal_connect(G_OBJECT(button), "activate",
578 G_CALLBACK(file_cancel_cb), data);
579 gnt_box_add_widget(GNT_BOX(hbox), button);
580
581 button = gnt_button_new(_("OK"));
582 g_signal_connect(G_OBJECT(button), "activate",
583 G_CALLBACK(file_ok_cb), data);
584 gnt_box_add_widget(GNT_BOX(hbox), button);
585
586 gnt_box_add_widget(GNT_BOX(window), hbox);
587
588 g_signal_connect_swapped(G_OBJECT(window), "destroy",
589 G_CALLBACK(file_request_destroy), data);
590
591 gnt_widget_show(window);
592
593 return window;
594 }
595
596 static GaimRequestUiOps uiops =
597 {
598 .request_input = finch_request_input,
599 .close_request = finch_close_request,
600 .request_choice = finch_request_choice,
601 .request_action = finch_request_action,
602 .request_fields = finch_request_fields,
603 .request_file = finch_request_file,
604 .request_folder = NULL /* No plans for this */
605 };
606
607 GaimRequestUiOps *finch_request_get_ui_ops()
608 {
609 return &uiops;
610 }
611
612 void finch_request_init()
613 {
614 }
615
616 void finch_request_uninit()
617 {
618 }
619