Convert Finch plugins to libsoup.
[pidgin-git.git] / finch / gntaccount.c
blob153e8539b7ee8d77491978f9a4399fd88294b763
1 /*
2 * finch
4 * Finch is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 #include <internal.h>
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 #include <gntutils.h>
35 #include <gntwindow.h>
37 #include "finch.h"
39 #include <account.h>
40 #include <connection.h>
41 #include <notify.h>
42 #include <plugins.h>
43 #include <purpleaccountoption.h>
44 #include <request.h>
45 #include <savedstatuses.h>
47 #include "gntaccount.h"
48 #include "gntblist.h"
50 #include <string.h>
52 typedef struct
54 GntWidget *window;
55 GntWidget *tree;
56 } FinchAccountList;
58 static FinchAccountList accounts;
60 typedef struct
62 PurpleAccount *account; /* NULL for a new account */
64 GntWidget *window;
66 GntWidget *protocol;
67 GntWidget *username;
68 GntWidget *password;
69 GntWidget *alias;
71 GntWidget *splits;
72 GList *split_entries;
74 GList *protocol_entries;
75 GntWidget *protocols;
77 GntWidget *newmail;
78 GntWidget *remember;
79 GntWidget *regserver;
80 } AccountEditDialog;
82 /* This is necessary to close an edit-dialog when an account is deleted */
83 static GList *accountdialogs;
85 static void
86 account_add(PurpleAccount *account)
88 gnt_tree_add_choice(GNT_TREE(accounts.tree), account,
89 gnt_tree_create_row(GNT_TREE(accounts.tree),
90 purple_account_get_username(account),
91 purple_account_get_protocol_name(account)),
92 NULL, NULL);
93 gnt_tree_set_choice(GNT_TREE(accounts.tree), account,
94 purple_account_get_enabled(account, FINCH_UI));
97 static void
98 edit_dialog_destroy(AccountEditDialog *dialog)
100 accountdialogs = g_list_remove(accountdialogs, dialog);
101 g_list_free(dialog->protocol_entries);
102 g_list_free(dialog->split_entries);
103 g_free(dialog);
106 static void
107 save_account_cb(AccountEditDialog *dialog)
109 PurpleAccount *account;
110 PurpleProtocol *protocol;
111 const char *value;
112 GString *username;
114 /* XXX: Do some error checking first. */
116 protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
118 /* Username && user-splits */
119 value = gnt_entry_get_text(GNT_ENTRY(dialog->username));
121 if (value == NULL || *value == '\0')
123 purple_notify_error(NULL, _("Error"),
124 dialog->account ? _("Account was not modified") :
125 _("Account was not added"),
126 _("Username of an account must be non-empty."),
127 purple_request_cpar_from_account(dialog->account));
128 return;
131 username = g_string_new(value);
133 if (protocol != NULL)
135 GList *iter, *entries;
136 for (iter = purple_protocol_get_user_splits(protocol), entries = dialog->split_entries;
137 iter && entries; iter = iter->next, entries = entries->next)
139 PurpleAccountUserSplit *split = iter->data;
140 GntWidget *entry = entries->data;
142 value = entry ? gnt_entry_get_text(GNT_ENTRY(entry)) : NULL;
143 if (value == NULL || *value == '\0')
144 value = purple_account_user_split_get_default_value(split);
145 g_string_append_printf(username, "%c%s",
146 purple_account_user_split_get_separator(split),
147 value);
151 if (dialog->account == NULL)
153 account = purple_account_new(username->str, purple_protocol_get_id(protocol));
154 purple_accounts_add(account);
156 else
158 account = dialog->account;
160 /* Protocol */
161 if (purple_account_is_disconnected(account)) {
162 purple_account_set_protocol_id(account, purple_protocol_get_id(protocol));
163 purple_account_set_username(account, username->str);
164 } else {
165 const char *old = purple_account_get_protocol_id(account);
166 char *oldproto;
167 if (!purple_strequal(old, purple_protocol_get_id(protocol))) {
168 purple_notify_error(NULL, _("Error"),
169 _("Account was not modified"),
170 _("The account's protocol cannot be "
171 "changed while it is connected to the "
172 "server."),
173 purple_request_cpar_from_account(
174 account));
175 g_string_free(username, TRUE);
176 return;
179 oldproto = g_strdup(purple_normalize(account, purple_account_get_username(account)));
180 if (g_utf8_collate(oldproto, purple_normalize(account, username->str))) {
181 purple_notify_error(NULL, _("Error"),
182 _("Account was not modified"),
183 _("The account's username cannot be "
184 "changed while it is connected to the "
185 "server."),
186 purple_request_cpar_from_account(
187 account));
188 g_free(oldproto);
189 g_string_free(username, TRUE);
190 return;
192 g_free(oldproto);
193 purple_account_set_username(account, username->str);
196 g_string_free(username, TRUE);
198 /* Alias */
199 value = gnt_entry_get_text(GNT_ENTRY(dialog->alias));
200 purple_account_set_private_alias(account, value);
202 /* Remember password and password */
203 purple_account_set_remember_password(account,
204 gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->remember)));
205 value = gnt_entry_get_text(GNT_ENTRY(dialog->password));
206 if (value && *value)
207 purple_account_set_password(account, value, NULL, NULL);
208 else
209 purple_account_set_password(account, NULL, NULL, NULL);
211 /* Mail notification */
212 purple_account_set_check_mail(account,
213 gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->newmail)));
215 /* Protocol options */
216 if (protocol)
218 GList *iter, *entries;
220 for (iter = purple_protocol_get_account_options(protocol), entries = dialog->protocol_entries;
221 iter && entries; iter = iter->next, entries = entries->next)
223 PurpleAccountOption *option = iter->data;
224 GntWidget *entry = entries->data;
225 PurplePrefType type = purple_account_option_get_pref_type(option);
226 const char *setting = purple_account_option_get_setting(option);
228 if (type == PURPLE_PREF_STRING)
230 const char *value = gnt_entry_get_text(GNT_ENTRY(entry));
231 purple_account_set_string(account, setting, value);
233 else if (type == PURPLE_PREF_INT)
235 const char *str = gnt_entry_get_text(GNT_ENTRY(entry));
236 int value = 0;
237 if (str)
238 value = atoi(str);
239 purple_account_set_int(account, setting, value);
241 else if (type == PURPLE_PREF_BOOLEAN)
243 gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(entry));
244 purple_account_set_bool(account, setting, value);
246 else if (type == PURPLE_PREF_STRING_LIST)
248 gchar *value = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(entry));
249 purple_account_set_string(account, setting, value);
251 else
253 g_assert_not_reached();
258 /* XXX: Proxy options */
260 if (accounts.window && accounts.tree) {
261 gnt_tree_set_selected(GNT_TREE(accounts.tree), account);
262 gnt_box_give_focus_to_child(GNT_BOX(accounts.window), accounts.tree);
265 if (protocol && PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, register_user) &&
266 gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->regserver))) {
267 purple_account_register(account);
268 } else if (dialog->account == NULL) {
269 /* This is a new account. Set it to the current status. */
270 /* Xerox from gtkaccount.c :D */
271 const PurpleSavedStatus *saved_status;
272 saved_status = purple_savedstatus_get_current();
273 if (saved_status != NULL) {
274 purple_savedstatus_activate_for_account(saved_status, account);
275 purple_account_set_enabled(account, FINCH_UI, TRUE);
279 /* In case of a new account, the 'Accounts' window is updated from the account-added
280 * callback. In case of changes in an existing account, we need to explicitly do it
281 * here.
283 if (dialog->account != NULL && accounts.window) {
284 gnt_tree_change_text(GNT_TREE(accounts.tree), dialog->account,
285 0, purple_account_get_username(dialog->account));
286 gnt_tree_change_text(GNT_TREE(accounts.tree), dialog->account,
287 1, purple_account_get_protocol_name(dialog->account));
290 gnt_widget_destroy(dialog->window);
293 static void
294 update_user_splits(AccountEditDialog *dialog)
296 GntWidget *hbox;
297 PurpleProtocol *protocol;
298 GList *iter, *entries;
299 char *username = NULL;
301 if (dialog->splits)
303 gnt_box_remove_all(GNT_BOX(dialog->splits));
304 g_list_free(dialog->split_entries);
306 else
308 dialog->splits = gnt_vbox_new(FALSE);
309 gnt_box_set_pad(GNT_BOX(dialog->splits), 0);
310 gnt_box_set_fill(GNT_BOX(dialog->splits), TRUE);
313 dialog->split_entries = NULL;
315 protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
316 if (!protocol)
317 return;
319 username = dialog->account ? g_strdup(purple_account_get_username(dialog->account)) : NULL;
321 for (iter = purple_protocol_get_user_splits(protocol); iter; iter = iter->next)
323 PurpleAccountUserSplit *split = iter->data;
324 GntWidget *entry = NULL;
325 char *buf = NULL;
327 if (!purple_account_user_split_is_constant(split)) {
328 hbox = gnt_hbox_new(TRUE);
329 gnt_box_add_widget(GNT_BOX(dialog->splits), hbox);
331 buf = g_strdup_printf("%s:", purple_account_user_split_get_text(split));
332 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(buf));
334 entry = gnt_entry_new(NULL);
335 gnt_box_add_widget(GNT_BOX(hbox), entry);
338 dialog->split_entries = g_list_append(dialog->split_entries, entry);
339 g_free(buf);
342 for (iter = g_list_last(purple_protocol_get_user_splits(protocol)), entries = g_list_last(dialog->split_entries);
343 iter && entries; iter = iter->prev, entries = entries->prev)
345 GntWidget *entry = entries->data;
346 PurpleAccountUserSplit *split = iter->data;
347 const char *value = NULL;
348 char *s;
350 if (dialog->account)
352 if(purple_account_user_split_get_reverse(split))
353 s = strrchr(username, purple_account_user_split_get_separator(split));
354 else
355 s = strchr(username, purple_account_user_split_get_separator(split));
357 if (s != NULL)
359 *s = '\0';
360 s++;
361 value = s;
364 if (value == NULL)
365 value = purple_account_user_split_get_default_value(split);
367 if (value != NULL && entry != NULL)
368 gnt_entry_set_text(GNT_ENTRY(entry), value);
371 if (username != NULL)
372 gnt_entry_set_text(GNT_ENTRY(dialog->username), username);
374 g_free(username);
377 static void
378 add_account_options(AccountEditDialog *dialog)
380 PurpleProtocol *protocol;
381 GList *iter;
382 GntWidget *vbox, *box;
383 PurpleAccount *account;
385 if (dialog->protocols)
386 gnt_box_remove_all(GNT_BOX(dialog->protocols));
387 else
389 dialog->protocols = vbox = gnt_vbox_new(FALSE);
390 gnt_box_set_pad(GNT_BOX(vbox), 0);
391 gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_LEFT);
392 gnt_box_set_fill(GNT_BOX(vbox), TRUE);
395 if (dialog->protocol_entries)
397 g_list_free(dialog->protocol_entries);
398 dialog->protocol_entries = NULL;
401 vbox = dialog->protocols;
403 protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
404 if (!protocol)
405 return;
407 account = dialog->account;
409 for (iter = purple_protocol_get_account_options(protocol); iter; iter = iter->next)
411 PurpleAccountOption *option = iter->data;
412 PurplePrefType type = purple_account_option_get_pref_type(option);
414 box = gnt_hbox_new(TRUE);
415 gnt_box_set_pad(GNT_BOX(box), 0);
416 gnt_box_add_widget(GNT_BOX(vbox), box);
418 if (type == PURPLE_PREF_BOOLEAN)
420 GntWidget *widget = gnt_check_box_new(purple_account_option_get_text(option));
421 gnt_box_add_widget(GNT_BOX(box), widget);
422 dialog->protocol_entries = g_list_append(dialog->protocol_entries, widget);
424 if (account)
425 gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
426 purple_account_get_bool(account,
427 purple_account_option_get_setting(option),
428 purple_account_option_get_default_bool(option)));
429 else
430 gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
431 purple_account_option_get_default_bool(option));
433 else
435 gnt_box_add_widget(GNT_BOX(box),
436 gnt_label_new(purple_account_option_get_text(option)));
438 if (type == PURPLE_PREF_STRING_LIST)
440 GntWidget *combo = gnt_combo_box_new();
441 GList *opt_iter = purple_account_option_get_list(option);
442 const char *dv = purple_account_option_get_default_list_value(option);
443 const char *active = dv;
445 if (account)
446 active = purple_account_get_string(account,
447 purple_account_option_get_setting(option), dv);
449 gnt_box_add_widget(GNT_BOX(box), combo);
450 dialog->protocol_entries = g_list_append(dialog->protocol_entries, combo);
452 for ( ; opt_iter; opt_iter = opt_iter->next)
454 PurpleKeyValuePair *kvp = opt_iter->data;
455 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), kvp->value, kvp->key);
457 if (purple_strequal(kvp->value, active))
458 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), kvp->value);
461 else
463 GntWidget *entry = gnt_entry_new(NULL);
464 gnt_box_add_widget(GNT_BOX(box), entry);
465 dialog->protocol_entries = g_list_append(dialog->protocol_entries, entry);
467 if (type == PURPLE_PREF_STRING)
469 const char *dv = purple_account_option_get_default_string(option);
471 if (account)
472 gnt_entry_set_text(GNT_ENTRY(entry),
473 purple_account_get_string(account,
474 purple_account_option_get_setting(option), dv));
475 else
476 gnt_entry_set_text(GNT_ENTRY(entry), dv);
478 else if (type == PURPLE_PREF_INT)
480 char str[32];
481 int value = purple_account_option_get_default_int(option);
482 if (account)
483 value = purple_account_get_int(account,
484 purple_account_option_get_setting(option), value);
485 snprintf(str, sizeof(str), "%d", value);
486 gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
487 gnt_entry_set_text(GNT_ENTRY(entry), str);
489 else
491 g_assert_not_reached();
497 /* Show the registration checkbox only in a new account dialog,
498 * and when the selected protocol has the support for it. */
499 gnt_widget_set_visible(dialog->regserver, account == NULL &&
500 PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, register_user));
503 static void
504 update_user_options(AccountEditDialog *dialog)
506 PurpleProtocol *protocol;
508 protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
509 if (!protocol)
510 return;
512 if (dialog->newmail == NULL)
513 dialog->newmail = gnt_check_box_new(_("New mail notifications"));
514 if (dialog->account)
515 gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->newmail),
516 purple_account_get_check_mail(dialog->account));
517 if (!(purple_protocol_get_options(protocol) & OPT_PROTO_MAIL_CHECK)) {
518 gnt_widget_set_visible(dialog->newmail, FALSE);
519 } else {
520 gnt_widget_set_visible(dialog->newmail, TRUE);
523 if (dialog->remember == NULL)
524 dialog->remember = gnt_check_box_new(_("Remember password"));
525 if (dialog->account)
526 gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->remember),
527 purple_account_get_remember_password(dialog->account));
530 static void
531 protocol_changed_cb(GntWidget *combo, PurpleProtocol *old, PurpleProtocol *new, AccountEditDialog *dialog)
533 update_user_splits(dialog);
534 add_account_options(dialog);
535 update_user_options(dialog); /* This may not be necessary here */
536 gnt_box_readjust(GNT_BOX(dialog->window));
537 gnt_widget_draw(dialog->window);
540 static void
541 edit_account_continue(PurpleAccount *account,
542 const gchar *password, GError *error, gpointer user_data)
544 GntWidget *window, *hbox;
545 GntWidget *combo, *button, *entry;
546 GList *list, *iter;
547 AccountEditDialog *dialog;
548 PurpleProtocol *protocol;
550 if (account)
552 GList *iter;
553 for (iter = accountdialogs; iter; iter = iter->next)
555 AccountEditDialog *dlg = iter->data;
556 if (dlg->account == account)
557 return;
561 list = purple_protocols_get_all();
562 if (list == NULL) {
563 purple_notify_error(NULL, _("Error"),
564 _("There are no protocols installed."),
565 _("(You probably forgot to 'make install'.)"),
566 purple_request_cpar_from_account(account));
567 return;
570 dialog = g_new0(AccountEditDialog, 1);
571 accountdialogs = g_list_prepend(accountdialogs, dialog);
573 dialog->window = window = gnt_vbox_new(FALSE);
574 dialog->account = account;
575 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
576 gnt_box_set_title(GNT_BOX(window), account ? _("Modify Account") : _("New Account"));
577 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
578 gnt_box_set_pad(GNT_BOX(window), 0);
579 gnt_widget_set_name(window, "edit-account");
580 gnt_box_set_fill(GNT_BOX(window), TRUE);
582 hbox = gnt_hbox_new(TRUE);
583 gnt_box_set_pad(GNT_BOX(hbox), 0);
584 gnt_box_add_widget(GNT_BOX(window), hbox);
586 dialog->protocol = combo = gnt_combo_box_new();
587 for (iter = list; iter; iter = iter->next)
589 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), iter->data,
590 purple_protocol_get_name(PURPLE_PROTOCOL(iter->data)));
593 protocol = purple_protocols_find(purple_account_get_protocol_id(account));
595 if (account && protocol)
596 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), protocol);
597 else
598 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), list->data);
600 g_signal_connect(G_OBJECT(combo), "selection-changed", G_CALLBACK(protocol_changed_cb), dialog);
602 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Protocol:")));
603 gnt_box_add_widget(GNT_BOX(hbox), combo);
605 hbox = gnt_hbox_new(TRUE);
606 gnt_box_set_pad(GNT_BOX(hbox), 0);
607 gnt_box_add_widget(GNT_BOX(window), hbox);
609 dialog->username = entry = gnt_entry_new(NULL);
610 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Username:")));
611 gnt_box_add_widget(GNT_BOX(hbox), entry);
613 /* User splits */
614 update_user_splits(dialog);
615 gnt_box_add_widget(GNT_BOX(window), dialog->splits);
617 hbox = gnt_hbox_new(TRUE);
618 gnt_box_set_pad(GNT_BOX(hbox), 0);
619 gnt_box_add_widget(GNT_BOX(window), hbox);
621 dialog->password = entry = gnt_entry_new(NULL);
622 gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
623 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Password:")));
624 gnt_box_add_widget(GNT_BOX(hbox), entry);
625 if (account)
626 gnt_entry_set_text(GNT_ENTRY(entry), password);
628 hbox = gnt_hbox_new(TRUE);
629 gnt_box_set_pad(GNT_BOX(hbox), 0);
630 gnt_box_add_widget(GNT_BOX(window), hbox);
632 dialog->alias = entry = gnt_entry_new(NULL);
633 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Alias:")));
634 gnt_box_add_widget(GNT_BOX(hbox), entry);
635 if (account)
636 gnt_entry_set_text(GNT_ENTRY(entry), purple_account_get_private_alias(account));
638 /* User options */
639 update_user_options(dialog);
640 gnt_box_add_widget(GNT_BOX(window), dialog->remember);
641 gnt_box_add_widget(GNT_BOX(window), dialog->newmail);
643 /* Register checkbox */
644 dialog->regserver = gnt_check_box_new(_("Create this account on the server"));
645 gnt_box_add_widget(GNT_BOX(window), dialog->regserver);
647 gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
649 /* The advanced box */
650 add_account_options(dialog);
651 gnt_box_add_widget(GNT_BOX(window), dialog->protocols);
653 /* TODO: Add proxy options */
655 /* The button box */
656 hbox = gnt_hbox_new(FALSE);
657 gnt_box_add_widget(GNT_BOX(window), hbox);
658 gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
660 button = gnt_button_new(_("Cancel"));
661 gnt_box_add_widget(GNT_BOX(hbox), button);
662 g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window);
664 button = gnt_button_new(_("Save"));
665 gnt_box_add_widget(GNT_BOX(hbox), button);
666 g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(save_account_cb), dialog);
668 g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(edit_dialog_destroy), dialog);
670 gnt_widget_show(window);
671 gnt_box_readjust(GNT_BOX(window));
672 gnt_widget_draw(window);
674 g_list_free(list);
677 static void
678 edit_account(PurpleAccount *account)
680 purple_account_get_password(account, edit_account_continue, account);
683 static void
684 add_account_cb(GntWidget *widget, gpointer null)
686 edit_account(NULL);
689 static void
690 modify_account_cb(GntWidget *widget, GntTree *tree)
692 PurpleAccount *account = gnt_tree_get_selection_data(tree);
693 if (!account)
694 return;
695 edit_account(account);
698 static void
699 really_delete_account(PurpleAccount *account)
701 GList *iter;
702 for (iter = accountdialogs; iter; iter = iter->next)
704 AccountEditDialog *dlg = iter->data;
705 if (dlg->account == account)
707 gnt_widget_destroy(dlg->window);
708 break;
711 purple_request_close_with_handle(account); /* Close any other opened delete window */
712 purple_accounts_delete(account);
715 static void
716 delete_account_cb(GntWidget *widget, GntTree *tree)
718 PurpleAccount *account;
719 char *prompt;
721 account = gnt_tree_get_selection_data(tree);
722 if (!account)
723 return;
725 prompt = g_strdup_printf(_("Are you sure you want to delete %s?"),
726 purple_account_get_username(account));
728 purple_request_action(account, _("Delete Account"), prompt, NULL,
729 PURPLE_DEFAULT_ACTION_NONE,
730 purple_request_cpar_from_account(account), account, 2,
731 _("Delete"), really_delete_account, _("Cancel"), NULL);
732 g_free(prompt);
735 static void
736 account_toggled(GntWidget *widget, void *key, gpointer null)
738 PurpleAccount *account = key;
739 gboolean enabled = gnt_tree_get_choice(GNT_TREE(widget), key);
741 if (enabled)
742 purple_savedstatus_activate_for_account(purple_savedstatus_get_current(),
743 account);
745 purple_account_set_enabled(account, FINCH_UI, enabled);
748 static gboolean
749 account_list_key_pressed_cb(GntWidget *widget, const char *text, gpointer null)
751 GntTree *tree = GNT_TREE(widget);
752 PurpleAccount *account = gnt_tree_get_selection_data(tree);
753 int move, pos, count;
754 GList *accounts;
756 if (!account)
757 return FALSE;
759 switch (text[0]) {
760 case '-':
761 move = -1;
762 break;
763 case '=':
764 move = 2; /* XXX: This seems to be a bug in libpurple */
765 break;
766 default:
767 return FALSE;
770 accounts = purple_accounts_get_all();
771 count = g_list_length(accounts);
772 pos = g_list_index(accounts, account);
773 pos = (move + pos + count + 1) % (count + 1);
774 if (pos >= 0)
775 purple_accounts_reorder(account, pos);
777 /* I don't like this, but recreating the entire list seems to be
778 * the easiest way of doing it */
779 gnt_tree_remove_all(tree);
780 accounts = purple_accounts_get_all();
781 for (; accounts; accounts = accounts->next)
782 account_add(accounts->data);
783 gnt_tree_set_selected(tree, account);
785 return TRUE;
788 static void
789 reset_accounts_win(GntWidget *widget, gpointer null)
791 accounts.window = NULL;
792 accounts.tree = NULL;
795 void finch_accounts_show_all()
797 GList *iter;
798 GntWidget *box, *button;
800 if (accounts.window) {
801 gnt_window_present(accounts.window);
802 return;
805 accounts.window = gnt_vbox_new(FALSE);
806 gnt_box_set_toplevel(GNT_BOX(accounts.window), TRUE);
807 gnt_box_set_title(GNT_BOX(accounts.window), _("Accounts"));
808 gnt_box_set_pad(GNT_BOX(accounts.window), 0);
809 gnt_box_set_alignment(GNT_BOX(accounts.window), GNT_ALIGN_MID);
810 gnt_widget_set_name(accounts.window, "accounts");
812 gnt_box_add_widget(GNT_BOX(accounts.window),
813 gnt_label_new(_("You can enable/disable accounts from the following list.")));
815 gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE));
817 accounts.tree = gnt_tree_new_with_columns(2);
818 gnt_widget_set_has_border(accounts.tree, FALSE);
820 for (iter = purple_accounts_get_all(); iter; iter = iter->next)
822 PurpleAccount *account = iter->data;
823 account_add(account);
826 g_signal_connect(G_OBJECT(accounts.tree), "toggled", G_CALLBACK(account_toggled), NULL);
827 g_signal_connect(G_OBJECT(accounts.tree), "key_pressed", G_CALLBACK(account_list_key_pressed_cb), NULL);
829 gnt_tree_set_col_width(GNT_TREE(accounts.tree), 0, 40);
830 gnt_tree_set_col_width(GNT_TREE(accounts.tree), 1, 10);
831 gnt_box_add_widget(GNT_BOX(accounts.window), accounts.tree);
833 gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE));
835 box = gnt_hbox_new(FALSE);
837 button = gnt_button_new(_("Add"));
838 gnt_box_add_widget(GNT_BOX(box), button);
839 gnt_util_set_trigger_widget(GNT_WIDGET(accounts.tree), GNT_KEY_INS, button);
840 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(add_account_cb), NULL);
842 button = gnt_button_new(_("Modify"));
843 gnt_box_add_widget(GNT_BOX(box), button);
844 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(modify_account_cb), accounts.tree);
846 button = gnt_button_new(_("Delete"));
847 gnt_box_add_widget(GNT_BOX(box), button);
848 gnt_util_set_trigger_widget(GNT_WIDGET(accounts.tree), GNT_KEY_DEL, button);
849 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(delete_account_cb), accounts.tree);
851 gnt_box_add_widget(GNT_BOX(accounts.window), box);
853 g_signal_connect(G_OBJECT(accounts.window), "destroy", G_CALLBACK(reset_accounts_win), NULL);
855 gnt_widget_show(accounts.window);
858 void finch_account_dialog_show(PurpleAccount *account)
860 edit_account(account);
863 static gpointer
864 finch_accounts_get_handle(void)
866 static int handle;
868 return &handle;
871 static void
872 account_added_callback(PurpleAccount *account)
874 if (accounts.window == NULL)
875 return;
876 account_add(account);
877 gnt_widget_draw(accounts.tree);
880 static void
881 account_removed_callback(PurpleAccount *account)
883 if (accounts.window == NULL)
884 return;
886 gnt_tree_remove(GNT_TREE(accounts.tree), account);
889 static void
890 account_abled_cb(PurpleAccount *account, gpointer user_data)
892 if (accounts.window == NULL)
893 return;
894 gnt_tree_set_choice(GNT_TREE(accounts.tree), account,
895 GPOINTER_TO_INT(user_data));
898 void finch_accounts_init()
900 GList *iter;
902 purple_signal_connect(purple_accounts_get_handle(), "account-added",
903 finch_accounts_get_handle(), PURPLE_CALLBACK(account_added_callback),
904 NULL);
905 purple_signal_connect(purple_accounts_get_handle(), "account-removed",
906 finch_accounts_get_handle(), PURPLE_CALLBACK(account_removed_callback),
907 NULL);
908 purple_signal_connect(purple_accounts_get_handle(), "account-disabled",
909 finch_accounts_get_handle(),
910 PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(FALSE));
911 purple_signal_connect(purple_accounts_get_handle(), "account-enabled",
912 finch_accounts_get_handle(),
913 PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE));
915 iter = purple_accounts_get_all();
916 if (iter) {
917 for (; iter; iter = iter->next) {
918 if (purple_account_get_enabled(iter->data, FINCH_UI))
919 break;
921 if (!iter)
922 finch_accounts_show_all();
923 } else {
924 edit_account(NULL);
925 finch_accounts_show_all();
929 void finch_accounts_uninit()
931 if (accounts.window)
932 gnt_widget_destroy(accounts.window);
935 /* The following uiops stuff are copied from gtkaccount.c */
936 typedef struct
938 PurpleAccount *account;
939 char *username;
940 char *alias;
941 } AddUserData;
943 static char *
944 make_info(PurpleAccount *account, PurpleConnection *gc, const char *remote_user,
945 const char *id, const char *alias, const char *msg)
947 if (msg != NULL && *msg == '\0')
948 msg = NULL;
950 return g_strdup_printf(_("%s%s%s%s has made %s his or her buddy%s%s"),
951 remote_user,
952 (alias != NULL ? " (" : ""),
953 (alias != NULL ? alias : ""),
954 (alias != NULL ? ")" : ""),
955 (id != NULL
956 ? id
957 : (purple_connection_get_display_name(gc) != NULL
958 ? purple_connection_get_display_name(gc)
959 : purple_account_get_username(account))),
960 (msg != NULL ? ": " : "."),
961 (msg != NULL ? msg : ""));
964 static void
965 notify_added(PurpleAccount *account, const char *remote_user,
966 const char *id, const char *alias,
967 const char *msg)
969 char *buffer;
970 PurpleConnection *gc;
972 gc = purple_account_get_connection(account);
974 buffer = make_info(account, gc, remote_user, id, alias, msg);
976 purple_notify_info(NULL, NULL, buffer, NULL,
977 purple_request_cpar_from_connection(gc));
979 g_free(buffer);
982 static void
983 free_add_user_data(AddUserData *data)
985 g_free(data->username);
987 g_free(data->alias);
989 g_free(data);
992 static void
993 add_user_cb(AddUserData *data)
995 PurpleConnection *gc = purple_account_get_connection(data->account);
997 if (g_list_find(purple_connections_get_all(), gc))
999 purple_blist_request_add_buddy(data->account, data->username,
1000 NULL, data->alias);
1003 free_add_user_data(data);
1006 static void
1007 request_add(PurpleAccount *account, const char *remote_user,
1008 const char *id, const char *alias,
1009 const char *msg)
1011 char *buffer;
1012 PurpleConnection *gc;
1013 AddUserData *data;
1015 gc = purple_account_get_connection(account);
1017 data = g_new0(AddUserData, 1);
1018 data->account = account;
1019 data->username = g_strdup(remote_user);
1020 data->alias = (alias != NULL ? g_strdup(alias) : NULL);
1022 buffer = make_info(account, gc, remote_user, id, alias, msg);
1023 purple_request_action(NULL, NULL, _("Add buddy to your list?"), buffer,
1024 PURPLE_DEFAULT_ACTION_NONE,
1025 purple_request_cpar_from_account(account), data, 2,
1026 _("Add"), G_CALLBACK(add_user_cb),
1027 _("Cancel"), G_CALLBACK(free_add_user_data));
1028 g_free(buffer);
1031 /* Copied from gtkaccount.c */
1032 typedef struct {
1033 PurpleAccountRequestAuthorizationCb auth_cb;
1034 PurpleAccountRequestAuthorizationCb deny_cb;
1035 void *data;
1036 char *username;
1037 char *alias;
1038 PurpleAccount *account;
1039 } auth_and_add;
1041 static void
1042 free_auth_and_add(auth_and_add *aa)
1044 g_free(aa->username);
1045 g_free(aa->alias);
1046 g_free(aa);
1049 static void
1050 authorize_and_add_cb(auth_and_add *aa)
1052 aa->auth_cb(NULL, aa->data);
1053 purple_blist_request_add_buddy(aa->account, aa->username,
1054 NULL, aa->alias);
1057 static void
1058 deny_no_add_cb(auth_and_add *aa)
1060 aa->deny_cb(NULL, aa->data);
1063 static void *
1064 finch_request_authorize(PurpleAccount *account,
1065 const char *remote_user,
1066 const char *id,
1067 const char *alias,
1068 const char *message,
1069 gboolean on_list,
1070 PurpleAccountRequestAuthorizationCb auth_cb,
1071 PurpleAccountRequestAuthorizationCb deny_cb,
1072 void *user_data)
1074 char *buffer;
1075 PurpleConnection *gc;
1076 void *uihandle;
1078 gc = purple_account_get_connection(account);
1079 if (message != NULL && *message == '\0')
1080 message = NULL;
1082 buffer = g_strdup_printf(_("%s%s%s%s wants to add %s to his or her buddy list%s%s"),
1083 remote_user,
1084 (alias != NULL ? " (" : ""),
1085 (alias != NULL ? alias : ""),
1086 (alias != NULL ? ")" : ""),
1087 (id != NULL
1088 ? id
1089 : (purple_connection_get_display_name(gc) != NULL
1090 ? purple_connection_get_display_name(gc)
1091 : purple_account_get_username(account))),
1092 (message != NULL ? ": " : "."),
1093 (message != NULL ? message : ""));
1094 if (!on_list) {
1095 GntWidget *widget;
1096 GList *iter;
1097 auth_and_add *aa = g_new(auth_and_add, 1);
1099 aa->auth_cb = auth_cb;
1100 aa->deny_cb = deny_cb;
1101 aa->data = user_data;
1102 aa->username = g_strdup(remote_user);
1103 aa->alias = g_strdup(alias);
1104 aa->account = account;
1106 uihandle = gnt_vwindow_new(FALSE);
1107 gnt_box_set_title(GNT_BOX(uihandle), _("Authorize buddy?"));
1108 gnt_box_set_pad(GNT_BOX(uihandle), 0);
1110 widget = purple_request_action(NULL, _("Authorize buddy?"), buffer, NULL,
1111 PURPLE_DEFAULT_ACTION_NONE,
1112 purple_request_cpar_from_account(account),
1113 aa, 2,
1114 _("Authorize"), authorize_and_add_cb,
1115 _("Deny"), deny_no_add_cb);
1116 /* Since GntWindow is a GntBox, hide it so it's unmapped, then
1117 * add it to the outer window, and make it visible again. */
1118 gnt_widget_hide(widget);
1119 gnt_box_set_toplevel(GNT_BOX(widget), FALSE);
1120 gnt_box_add_widget(GNT_BOX(uihandle), widget);
1121 gnt_widget_set_visible(widget, TRUE);
1123 gnt_box_add_widget(GNT_BOX(uihandle), gnt_hline_new());
1125 widget = finch_retrieve_user_info(purple_account_get_connection(account), remote_user);
1126 for (iter = gnt_box_get_children(GNT_BOX(widget)); iter;
1127 iter = g_list_delete_link(iter, iter)) {
1128 if (GNT_IS_BUTTON(iter->data)) {
1129 gnt_widget_destroy(iter->data);
1130 gnt_box_remove(GNT_BOX(widget), iter->data);
1131 g_list_free(iter);
1132 break;
1135 /* Since GntWindow is a GntBox, hide it so it's unmapped, then
1136 * add it to the outer window, and make it visible again. */
1137 gnt_widget_hide(widget);
1138 gnt_box_set_toplevel(GNT_BOX(widget), FALSE);
1139 gnt_box_add_widget(GNT_BOX(uihandle), widget);
1140 gnt_widget_set_visible(widget, TRUE);
1142 gnt_widget_show(uihandle);
1144 g_signal_connect_swapped(G_OBJECT(uihandle), "destroy", G_CALLBACK(free_auth_and_add), aa);
1145 } else {
1146 uihandle = purple_request_action(NULL, _("Authorize buddy?"), buffer, NULL,
1147 PURPLE_DEFAULT_ACTION_NONE,
1148 purple_request_cpar_from_account(account),
1149 user_data, 2,
1150 _("Authorize"), auth_cb,
1151 _("Deny"), deny_cb);
1153 g_signal_connect(G_OBJECT(uihandle), "destroy",
1154 G_CALLBACK(purple_account_request_close), NULL);
1155 g_free(buffer);
1156 return uihandle;
1159 static void
1160 finch_request_close(void *uihandle)
1162 purple_request_close(PURPLE_REQUEST_ACTION, uihandle);
1165 static PurpleAccountUiOps ui_ops =
1167 notify_added,
1168 NULL,
1169 request_add,
1170 finch_request_authorize,
1171 finch_request_close,
1172 NULL,
1173 NULL,
1174 NULL,
1175 NULL,
1176 NULL, NULL, NULL, NULL
1179 PurpleAccountUiOps *finch_accounts_get_ui_ops()
1181 return &ui_ops;