Change Finch to use Pidgin's clientkey/devid when connecting to ICQ.
[pidgin-git.git] / finch / gntaccount.c
blob4464b548c62476251bf4b5ad65cb496ff0330afe
1 /**
2 * @file gntaccount.c GNT Account API
3 * @ingroup finch
4 */
6 /* finch
8 * Finch is the legal property of its developers, whose names are too numerous
9 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * source distribution.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 #include <internal.h>
28 #include <gnt.h>
29 #include <gntbox.h>
30 #include <gntbutton.h>
31 #include <gntcheckbox.h>
32 #include <gntcombobox.h>
33 #include <gntentry.h>
34 #include <gntlabel.h>
35 #include <gntline.h>
36 #include <gnttree.h>
37 #include <gntutils.h>
38 #include <gntwindow.h>
40 #include "finch.h"
42 #include <account.h>
43 #include <accountopt.h>
44 #include <connection.h>
45 #include <notify.h>
46 #include <plugin.h>
47 #include <request.h>
48 #include <savedstatuses.h>
50 #include "gntaccount.h"
51 #include "gntblist.h"
53 #include <string.h>
55 typedef struct
57 GntWidget *window;
58 GntWidget *tree;
59 } FinchAccountList;
61 static FinchAccountList accounts;
63 typedef struct
65 PurpleAccount *account; /* NULL for a new account */
67 GntWidget *window;
69 GntWidget *protocol;
70 GntWidget *username;
71 GntWidget *password;
72 GntWidget *alias;
74 GntWidget *splits;
75 GList *split_entries;
77 GList *prpl_entries;
78 GntWidget *prpls;
80 GntWidget *newmail;
81 GntWidget *remember;
82 GntWidget *regserver;
83 } AccountEditDialog;
85 /* This is necessary to close an edit-dialog when an account is deleted */
86 static GList *accountdialogs;
88 static void
89 account_add(PurpleAccount *account)
91 gnt_tree_add_choice(GNT_TREE(accounts.tree), account,
92 gnt_tree_create_row(GNT_TREE(accounts.tree),
93 purple_account_get_username(account),
94 purple_account_get_protocol_name(account)),
95 NULL, NULL);
96 gnt_tree_set_choice(GNT_TREE(accounts.tree), account,
97 purple_account_get_enabled(account, FINCH_UI));
100 static void
101 edit_dialog_destroy(AccountEditDialog *dialog)
103 accountdialogs = g_list_remove(accountdialogs, dialog);
104 g_list_free(dialog->prpl_entries);
105 g_list_free(dialog->split_entries);
106 g_free(dialog);
109 static void
110 save_account_cb(AccountEditDialog *dialog)
112 PurpleAccount *account;
113 PurplePlugin *plugin;
114 PurplePluginProtocolInfo *prplinfo;
115 const char *value;
116 GString *username;
118 /* XXX: Do some error checking first. */
120 plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
121 prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
123 /* Username && user-splits */
124 value = gnt_entry_get_text(GNT_ENTRY(dialog->username));
126 if (value == NULL || *value == '\0')
128 purple_notify_error(NULL, _("Error"),
129 dialog->account ? _("Account was not modified") : _("Account was not added"),
130 _("Username of an account must be non-empty."));
131 return;
134 username = g_string_new(value);
136 if (prplinfo != NULL)
138 GList *iter, *entries;
139 for (iter = prplinfo->user_splits, entries = dialog->split_entries;
140 iter && entries; iter = iter->next, entries = entries->next)
142 PurpleAccountUserSplit *split = iter->data;
143 GntWidget *entry = entries->data;
145 value = gnt_entry_get_text(GNT_ENTRY(entry));
146 if (value == NULL || *value == '\0')
147 value = purple_account_user_split_get_default_value(split);
148 g_string_append_printf(username, "%c%s",
149 purple_account_user_split_get_separator(split),
150 value);
154 if (dialog->account == NULL)
156 account = purple_account_new(username->str, purple_plugin_get_id(plugin));
157 purple_accounts_add(account);
159 else
161 account = dialog->account;
163 /* Protocol */
164 if (purple_account_is_disconnected(account)) {
165 purple_account_set_protocol_id(account, purple_plugin_get_id(plugin));
166 purple_account_set_username(account, username->str);
167 } else {
168 const char *old = purple_account_get_protocol_id(account);
169 char *oldprpl;
170 if (strcmp(old, purple_plugin_get_id(plugin))) {
171 purple_notify_error(NULL, _("Error"), _("Account was not modified"),
172 _("The account's protocol cannot be changed while it is connected to the server."));
173 return;
176 oldprpl = g_strdup(purple_normalize(account, purple_account_get_username(account)));
177 if (g_utf8_collate(oldprpl, purple_normalize(account, username->str))) {
178 purple_notify_error(NULL, _("Error"), _("Account was not modified"),
179 _("The account's username cannot be changed while it is connected to the server."));
180 g_free(oldprpl);
181 return;
183 g_free(oldprpl);
184 purple_account_set_username(account, username->str);
187 g_string_free(username, TRUE);
189 /* Alias */
190 value = gnt_entry_get_text(GNT_ENTRY(dialog->alias));
191 purple_account_set_alias(account, value);
193 /* Remember password and password */
194 purple_account_set_remember_password(account,
195 gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->remember)));
196 value = gnt_entry_get_text(GNT_ENTRY(dialog->password));
197 if (value && *value)
198 purple_account_set_password(account, value);
199 else
200 purple_account_set_password(account, NULL);
202 /* Mail notification */
203 purple_account_set_check_mail(account,
204 gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->newmail)));
206 /* Protocol options */
207 if (prplinfo)
209 GList *iter, *entries;
211 for (iter = prplinfo->protocol_options, entries = dialog->prpl_entries;
212 iter && entries; iter = iter->next, entries = entries->next)
214 PurpleAccountOption *option = iter->data;
215 GntWidget *entry = entries->data;
216 PurplePrefType type = purple_account_option_get_type(option);
217 const char *setting = purple_account_option_get_setting(option);
219 if (type == PURPLE_PREF_STRING)
221 const char *value = gnt_entry_get_text(GNT_ENTRY(entry));
222 purple_account_set_string(account, setting, value);
224 else if (type == PURPLE_PREF_INT)
226 const char *str = gnt_entry_get_text(GNT_ENTRY(entry));
227 int value = 0;
228 if (str)
229 value = atoi(str);
230 purple_account_set_int(account, setting, value);
232 else if (type == PURPLE_PREF_BOOLEAN)
234 gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(entry));
235 purple_account_set_bool(account, setting, value);
237 else if (type == PURPLE_PREF_STRING_LIST)
239 gchar *value = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(entry));
240 purple_account_set_string(account, setting, value);
242 else
244 g_assert_not_reached();
249 /* XXX: Proxy options */
251 if (accounts.window && accounts.tree) {
252 gnt_tree_set_selected(GNT_TREE(accounts.tree), account);
253 gnt_box_give_focus_to_child(GNT_BOX(accounts.window), accounts.tree);
256 if (prplinfo && prplinfo->register_user &&
257 gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->regserver))) {
258 purple_account_register(account);
259 } else if (dialog->account == NULL) {
260 /* This is a new account. Set it to the current status. */
261 /* Xerox from gtkaccount.c :D */
262 const PurpleSavedStatus *saved_status;
263 saved_status = purple_savedstatus_get_current();
264 if (saved_status != NULL) {
265 purple_savedstatus_activate_for_account(saved_status, account);
266 purple_account_set_enabled(account, FINCH_UI, TRUE);
270 /* In case of a new account, the 'Accounts' window is updated from the account-added
271 * callback. In case of changes in an existing account, we need to explicitly do it
272 * here.
274 if (dialog->account != NULL && accounts.window) {
275 gnt_tree_change_text(GNT_TREE(accounts.tree), dialog->account,
276 0, purple_account_get_username(dialog->account));
277 gnt_tree_change_text(GNT_TREE(accounts.tree), dialog->account,
278 1, purple_account_get_protocol_name(dialog->account));
281 gnt_widget_destroy(dialog->window);
284 static void
285 update_user_splits(AccountEditDialog *dialog)
287 GntWidget *hbox;
288 PurplePlugin *plugin;
289 PurplePluginProtocolInfo *prplinfo;
290 GList *iter, *entries;
291 char *username = NULL;
293 if (dialog->splits)
295 gnt_box_remove_all(GNT_BOX(dialog->splits));
296 g_list_free(dialog->split_entries);
298 else
300 dialog->splits = gnt_vbox_new(FALSE);
301 gnt_box_set_pad(GNT_BOX(dialog->splits), 0);
302 gnt_box_set_fill(GNT_BOX(dialog->splits), TRUE);
305 dialog->split_entries = NULL;
307 plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
308 if (!plugin)
309 return;
310 prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
312 username = dialog->account ? g_strdup(purple_account_get_username(dialog->account)) : NULL;
314 for (iter = prplinfo->user_splits; iter; iter = iter->next)
316 PurpleAccountUserSplit *split = iter->data;
317 GntWidget *entry;
318 char *buf;
320 hbox = gnt_hbox_new(TRUE);
321 gnt_box_add_widget(GNT_BOX(dialog->splits), hbox);
323 buf = g_strdup_printf("%s:", purple_account_user_split_get_text(split));
324 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(buf));
326 entry = gnt_entry_new(NULL);
327 gnt_box_add_widget(GNT_BOX(hbox), entry);
329 dialog->split_entries = g_list_append(dialog->split_entries, entry);
330 g_free(buf);
333 for (iter = g_list_last(prplinfo->user_splits), entries = g_list_last(dialog->split_entries);
334 iter && entries; iter = iter->prev, entries = entries->prev)
336 GntWidget *entry = entries->data;
337 PurpleAccountUserSplit *split = iter->data;
338 const char *value = NULL;
339 char *s;
341 if (dialog->account)
343 if(purple_account_user_split_get_reverse(split))
344 s = strrchr(username, purple_account_user_split_get_separator(split));
345 else
346 s = strchr(username, purple_account_user_split_get_separator(split));
348 if (s != NULL)
350 *s = '\0';
351 s++;
352 value = s;
355 if (value == NULL)
356 value = purple_account_user_split_get_default_value(split);
358 if (value != NULL)
359 gnt_entry_set_text(GNT_ENTRY(entry), value);
362 if (username != NULL)
363 gnt_entry_set_text(GNT_ENTRY(dialog->username), username);
365 g_free(username);
368 static void
369 add_protocol_options(AccountEditDialog *dialog)
371 PurplePlugin *plugin;
372 PurplePluginProtocolInfo *prplinfo;
373 GList *iter;
374 GntWidget *vbox, *box;
375 PurpleAccount *account;
377 if (dialog->prpls)
378 gnt_box_remove_all(GNT_BOX(dialog->prpls));
379 else
381 dialog->prpls = vbox = gnt_vbox_new(FALSE);
382 gnt_box_set_pad(GNT_BOX(vbox), 0);
383 gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_LEFT);
384 gnt_box_set_fill(GNT_BOX(vbox), TRUE);
387 if (dialog->prpl_entries)
389 g_list_free(dialog->prpl_entries);
390 dialog->prpl_entries = NULL;
393 vbox = dialog->prpls;
395 plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
396 if (!plugin)
397 return;
399 prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
401 account = dialog->account;
403 for (iter = prplinfo->protocol_options; iter; iter = iter->next)
405 PurpleAccountOption *option = iter->data;
406 PurplePrefType type = purple_account_option_get_type(option);
408 box = gnt_hbox_new(TRUE);
409 gnt_box_set_pad(GNT_BOX(box), 0);
410 gnt_box_add_widget(GNT_BOX(vbox), box);
412 if (type == PURPLE_PREF_BOOLEAN)
414 GntWidget *widget = gnt_check_box_new(purple_account_option_get_text(option));
415 gnt_box_add_widget(GNT_BOX(box), widget);
416 dialog->prpl_entries = g_list_append(dialog->prpl_entries, widget);
418 if (account)
419 gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
420 purple_account_get_bool(account,
421 purple_account_option_get_setting(option),
422 purple_account_option_get_default_bool(option)));
423 else
424 gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
425 purple_account_option_get_default_bool(option));
427 else
429 gnt_box_add_widget(GNT_BOX(box),
430 gnt_label_new(purple_account_option_get_text(option)));
432 if (type == PURPLE_PREF_STRING_LIST)
434 GntWidget *combo = gnt_combo_box_new();
435 GList *opt_iter = purple_account_option_get_list(option);
436 const char *dv = purple_account_option_get_default_list_value(option);
437 const char *active = dv;
439 if (account)
440 active = purple_account_get_string(account,
441 purple_account_option_get_setting(option), dv);
443 gnt_box_add_widget(GNT_BOX(box), combo);
444 dialog->prpl_entries = g_list_append(dialog->prpl_entries, combo);
446 for ( ; opt_iter; opt_iter = opt_iter->next)
448 PurpleKeyValuePair *kvp = opt_iter->data;
449 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), kvp->value, kvp->key);
451 if (g_str_equal(kvp->value, active))
452 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), kvp->value);
455 else
457 GntWidget *entry = gnt_entry_new(NULL);
458 gnt_box_add_widget(GNT_BOX(box), entry);
459 dialog->prpl_entries = g_list_append(dialog->prpl_entries, entry);
461 if (type == PURPLE_PREF_STRING)
463 const char *dv = purple_account_option_get_default_string(option);
465 if (account)
466 gnt_entry_set_text(GNT_ENTRY(entry),
467 purple_account_get_string(account,
468 purple_account_option_get_setting(option), dv));
469 else
470 gnt_entry_set_text(GNT_ENTRY(entry), dv);
472 else if (type == PURPLE_PREF_INT)
474 char str[32];
475 int value = purple_account_option_get_default_int(option);
476 if (account)
477 value = purple_account_get_int(account,
478 purple_account_option_get_setting(option), value);
479 snprintf(str, sizeof(str), "%d", value);
480 gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
481 gnt_entry_set_text(GNT_ENTRY(entry), str);
483 else
485 g_assert_not_reached();
491 /* Show the registration checkbox only in a new account dialog,
492 * and when the selected prpl has the support for it. */
493 gnt_widget_set_visible(dialog->regserver, account == NULL &&
494 prplinfo->register_user != NULL);
497 static void
498 update_user_options(AccountEditDialog *dialog)
500 PurplePlugin *plugin;
501 PurplePluginProtocolInfo *prplinfo;
503 plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
504 if (!plugin)
505 return;
507 prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
509 if (dialog->newmail == NULL)
510 dialog->newmail = gnt_check_box_new(_("New mail notifications"));
511 if (dialog->account)
512 gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->newmail),
513 purple_account_get_check_mail(dialog->account));
514 if (!prplinfo || !(prplinfo->options & OPT_PROTO_MAIL_CHECK))
515 gnt_widget_set_visible(dialog->newmail, FALSE);
516 else
517 gnt_widget_set_visible(dialog->newmail, TRUE);
519 if (dialog->remember == NULL)
520 dialog->remember = gnt_check_box_new(_("Remember password"));
521 if (dialog->account)
522 gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->remember),
523 purple_account_get_remember_password(dialog->account));
526 static void
527 prpl_changed_cb(GntWidget *combo, PurplePlugin *old, PurplePlugin *new, AccountEditDialog *dialog)
529 update_user_splits(dialog);
530 add_protocol_options(dialog);
531 update_user_options(dialog); /* This may not be necessary here */
532 gnt_box_readjust(GNT_BOX(dialog->window));
533 gnt_widget_draw(dialog->window);
536 static void
537 edit_account(PurpleAccount *account)
539 GntWidget *window, *hbox;
540 GntWidget *combo, *button, *entry;
541 GList *list, *iter;
542 AccountEditDialog *dialog;
543 PurplePlugin *plugin;
545 if (account)
547 GList *iter;
548 for (iter = accountdialogs; iter; iter = iter->next)
550 AccountEditDialog *dlg = iter->data;
551 if (dlg->account == account)
552 return;
556 list = purple_plugins_get_protocols();
557 if (list == NULL) {
558 purple_notify_error(NULL, _("Error"),
559 _("There are no protocol plugins installed."),
560 _("(You probably forgot to 'make install'.)"));
561 return;
564 dialog = g_new0(AccountEditDialog, 1);
565 accountdialogs = g_list_prepend(accountdialogs, dialog);
567 dialog->window = window = gnt_vbox_new(FALSE);
568 dialog->account = account;
569 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
570 gnt_box_set_title(GNT_BOX(window), account ? _("Modify Account") : _("New Account"));
571 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
572 gnt_box_set_pad(GNT_BOX(window), 0);
573 gnt_widget_set_name(window, "edit-account");
574 gnt_box_set_fill(GNT_BOX(window), TRUE);
576 hbox = gnt_hbox_new(TRUE);
577 gnt_box_set_pad(GNT_BOX(hbox), 0);
578 gnt_box_add_widget(GNT_BOX(window), hbox);
580 dialog->protocol = combo = gnt_combo_box_new();
581 for (iter = list; iter; iter = iter->next)
583 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), iter->data,
584 ((PurplePlugin*)iter->data)->info->name);
587 plugin = purple_plugins_find_with_id(purple_account_get_protocol_id(account));
589 if (account && plugin)
590 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), plugin);
591 else
592 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), list->data);
594 g_signal_connect(G_OBJECT(combo), "selection-changed", G_CALLBACK(prpl_changed_cb), dialog);
596 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Protocol:")));
597 gnt_box_add_widget(GNT_BOX(hbox), combo);
599 hbox = gnt_hbox_new(TRUE);
600 gnt_box_set_pad(GNT_BOX(hbox), 0);
601 gnt_box_add_widget(GNT_BOX(window), hbox);
603 dialog->username = entry = gnt_entry_new(NULL);
604 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Username:")));
605 gnt_box_add_widget(GNT_BOX(hbox), entry);
607 /* User splits */
608 update_user_splits(dialog);
609 gnt_box_add_widget(GNT_BOX(window), dialog->splits);
611 hbox = gnt_hbox_new(TRUE);
612 gnt_box_set_pad(GNT_BOX(hbox), 0);
613 gnt_box_add_widget(GNT_BOX(window), hbox);
615 dialog->password = entry = gnt_entry_new(NULL);
616 gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
617 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Password:")));
618 gnt_box_add_widget(GNT_BOX(hbox), entry);
619 if (account)
620 gnt_entry_set_text(GNT_ENTRY(entry), purple_account_get_password(account));
622 hbox = gnt_hbox_new(TRUE);
623 gnt_box_set_pad(GNT_BOX(hbox), 0);
624 gnt_box_add_widget(GNT_BOX(window), hbox);
626 dialog->alias = entry = gnt_entry_new(NULL);
627 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Alias:")));
628 gnt_box_add_widget(GNT_BOX(hbox), entry);
629 if (account)
630 gnt_entry_set_text(GNT_ENTRY(entry), purple_account_get_alias(account));
632 /* User options */
633 update_user_options(dialog);
634 gnt_box_add_widget(GNT_BOX(window), dialog->remember);
635 gnt_box_add_widget(GNT_BOX(window), dialog->newmail);
637 /* Register checkbox */
638 dialog->regserver = gnt_check_box_new(_("Create this account on the server"));
639 gnt_box_add_widget(GNT_BOX(window), dialog->regserver);
641 gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
643 /* The advanced box */
644 add_protocol_options(dialog);
645 gnt_box_add_widget(GNT_BOX(window), dialog->prpls);
647 /* TODO: Add proxy options */
649 /* The button box */
650 hbox = gnt_hbox_new(FALSE);
651 gnt_box_add_widget(GNT_BOX(window), hbox);
652 gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
654 button = gnt_button_new(_("Cancel"));
655 gnt_box_add_widget(GNT_BOX(hbox), button);
656 g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window);
658 button = gnt_button_new(_("Save"));
659 gnt_box_add_widget(GNT_BOX(hbox), button);
660 g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(save_account_cb), dialog);
662 g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(edit_dialog_destroy), dialog);
664 gnt_widget_show(window);
665 gnt_box_readjust(GNT_BOX(window));
666 gnt_widget_draw(window);
669 static void
670 add_account_cb(GntWidget *widget, gpointer null)
672 edit_account(NULL);
675 static void
676 modify_account_cb(GntWidget *widget, GntTree *tree)
678 PurpleAccount *account = gnt_tree_get_selection_data(tree);
679 if (!account)
680 return;
681 edit_account(account);
684 static void
685 really_delete_account(PurpleAccount *account)
687 GList *iter;
688 for (iter = accountdialogs; iter; iter = iter->next)
690 AccountEditDialog *dlg = iter->data;
691 if (dlg->account == account)
693 gnt_widget_destroy(dlg->window);
694 break;
697 purple_request_close_with_handle(account); /* Close any other opened delete window */
698 purple_accounts_delete(account);
701 static void
702 delete_account_cb(GntWidget *widget, GntTree *tree)
704 PurpleAccount *account;
705 char *prompt;
707 account = gnt_tree_get_selection_data(tree);
708 if (!account)
709 return;
711 prompt = g_strdup_printf(_("Are you sure you want to delete %s?"),
712 purple_account_get_username(account));
714 purple_request_action(account, _("Delete Account"), prompt, NULL,
715 PURPLE_DEFAULT_ACTION_NONE,
716 account, NULL, NULL, account, 2,
717 _("Delete"), really_delete_account,
718 _("Cancel"), NULL);
719 g_free(prompt);
722 static void
723 account_toggled(GntWidget *widget, void *key, gpointer null)
725 PurpleAccount *account = key;
726 gboolean enabled = gnt_tree_get_choice(GNT_TREE(widget), key);
728 if (enabled)
729 purple_savedstatus_activate_for_account(purple_savedstatus_get_current(),
730 account);
732 purple_account_set_enabled(account, FINCH_UI, enabled);
735 static gboolean
736 account_list_key_pressed_cb(GntWidget *widget, const char *text, gpointer null)
738 GntTree *tree = GNT_TREE(widget);
739 PurpleAccount *account = gnt_tree_get_selection_data(tree);
740 int move, pos, count;
741 GList *accounts;
743 if (!account)
744 return FALSE;
746 switch (text[0]) {
747 case '-':
748 move = -1;
749 break;
750 case '=':
751 move = 2; /* XXX: This seems to be a bug in libpurple */
752 break;
753 default:
754 return FALSE;
757 accounts = purple_accounts_get_all();
758 count = g_list_length(accounts);
759 pos = g_list_index(accounts, account);
760 pos = (move + pos + count + 1) % (count + 1);
761 purple_accounts_reorder(account, pos);
763 /* I don't like this, but recreating the entire list seems to be
764 * the easiest way of doing it */
765 gnt_tree_remove_all(tree);
766 accounts = purple_accounts_get_all();
767 for (; accounts; accounts = accounts->next)
768 account_add(accounts->data);
769 gnt_tree_set_selected(tree, account);
771 return TRUE;
774 static void
775 reset_accounts_win(GntWidget *widget, gpointer null)
777 accounts.window = NULL;
778 accounts.tree = NULL;
781 void finch_accounts_show_all()
783 GList *iter;
784 GntWidget *box, *button;
786 if (accounts.window) {
787 gnt_window_present(accounts.window);
788 return;
791 accounts.window = gnt_vbox_new(FALSE);
792 gnt_box_set_toplevel(GNT_BOX(accounts.window), TRUE);
793 gnt_box_set_title(GNT_BOX(accounts.window), _("Accounts"));
794 gnt_box_set_pad(GNT_BOX(accounts.window), 0);
795 gnt_box_set_alignment(GNT_BOX(accounts.window), GNT_ALIGN_MID);
796 gnt_widget_set_name(accounts.window, "accounts");
798 gnt_box_add_widget(GNT_BOX(accounts.window),
799 gnt_label_new(_("You can enable/disable accounts from the following list.")));
801 gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE));
803 accounts.tree = gnt_tree_new_with_columns(2);
804 GNT_WIDGET_SET_FLAGS(accounts.tree, GNT_WIDGET_NO_BORDER);
806 for (iter = purple_accounts_get_all(); iter; iter = iter->next)
808 PurpleAccount *account = iter->data;
809 account_add(account);
812 g_signal_connect(G_OBJECT(accounts.tree), "toggled", G_CALLBACK(account_toggled), NULL);
813 g_signal_connect(G_OBJECT(accounts.tree), "key_pressed", G_CALLBACK(account_list_key_pressed_cb), NULL);
815 gnt_tree_set_col_width(GNT_TREE(accounts.tree), 0, 40);
816 gnt_tree_set_col_width(GNT_TREE(accounts.tree), 1, 10);
817 gnt_box_add_widget(GNT_BOX(accounts.window), accounts.tree);
819 gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE));
821 box = gnt_hbox_new(FALSE);
823 button = gnt_button_new(_("Add"));
824 gnt_box_add_widget(GNT_BOX(box), button);
825 gnt_util_set_trigger_widget(GNT_WIDGET(accounts.tree), GNT_KEY_INS, button);
826 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(add_account_cb), NULL);
828 button = gnt_button_new(_("Modify"));
829 gnt_box_add_widget(GNT_BOX(box), button);
830 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(modify_account_cb), accounts.tree);
832 button = gnt_button_new(_("Delete"));
833 gnt_box_add_widget(GNT_BOX(box), button);
834 gnt_util_set_trigger_widget(GNT_WIDGET(accounts.tree), GNT_KEY_DEL, button);
835 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(delete_account_cb), accounts.tree);
837 gnt_box_add_widget(GNT_BOX(accounts.window), box);
839 g_signal_connect(G_OBJECT(accounts.window), "destroy", G_CALLBACK(reset_accounts_win), NULL);
841 gnt_widget_show(accounts.window);
844 void finch_account_dialog_show(PurpleAccount *account)
846 edit_account(account);
849 static gpointer
850 finch_accounts_get_handle(void)
852 static int handle;
854 return &handle;
857 static void
858 account_added_callback(PurpleAccount *account)
860 if (accounts.window == NULL)
861 return;
862 account_add(account);
863 gnt_widget_draw(accounts.tree);
866 static void
867 account_removed_callback(PurpleAccount *account)
869 if (accounts.window == NULL)
870 return;
872 gnt_tree_remove(GNT_TREE(accounts.tree), account);
875 static void
876 account_abled_cb(PurpleAccount *account, gpointer user_data)
878 if (accounts.window == NULL)
879 return;
880 gnt_tree_set_choice(GNT_TREE(accounts.tree), account,
881 GPOINTER_TO_INT(user_data));
884 void finch_accounts_init()
886 GList *iter;
888 purple_signal_connect(purple_accounts_get_handle(), "account-added",
889 finch_accounts_get_handle(), PURPLE_CALLBACK(account_added_callback),
890 NULL);
891 purple_signal_connect(purple_accounts_get_handle(), "account-removed",
892 finch_accounts_get_handle(), PURPLE_CALLBACK(account_removed_callback),
893 NULL);
894 purple_signal_connect(purple_accounts_get_handle(), "account-disabled",
895 finch_accounts_get_handle(),
896 PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(FALSE));
897 purple_signal_connect(purple_accounts_get_handle(), "account-enabled",
898 finch_accounts_get_handle(),
899 PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE));
901 iter = purple_accounts_get_all();
902 if (iter) {
903 for (; iter; iter = iter->next) {
904 if (purple_account_get_enabled(iter->data, FINCH_UI))
905 break;
907 if (!iter)
908 finch_accounts_show_all();
909 } else {
910 edit_account(NULL);
911 finch_accounts_show_all();
915 void finch_accounts_uninit()
917 if (accounts.window)
918 gnt_widget_destroy(accounts.window);
921 /* The following uiops stuff are copied from gtkaccount.c */
922 typedef struct
924 PurpleAccount *account;
925 char *username;
926 char *alias;
927 } AddUserData;
929 static char *
930 make_info(PurpleAccount *account, PurpleConnection *gc, const char *remote_user,
931 const char *id, const char *alias, const char *msg)
933 if (msg != NULL && *msg == '\0')
934 msg = NULL;
936 return g_strdup_printf(_("%s%s%s%s has made %s his or her buddy%s%s"),
937 remote_user,
938 (alias != NULL ? " (" : ""),
939 (alias != NULL ? alias : ""),
940 (alias != NULL ? ")" : ""),
941 (id != NULL
942 ? id
943 : (purple_connection_get_display_name(gc) != NULL
944 ? purple_connection_get_display_name(gc)
945 : purple_account_get_username(account))),
946 (msg != NULL ? ": " : "."),
947 (msg != NULL ? msg : ""));
950 static void
951 notify_added(PurpleAccount *account, const char *remote_user,
952 const char *id, const char *alias,
953 const char *msg)
955 char *buffer;
956 PurpleConnection *gc;
958 gc = purple_account_get_connection(account);
960 buffer = make_info(account, gc, remote_user, id, alias, msg);
962 purple_notify_info(NULL, NULL, buffer, NULL);
964 g_free(buffer);
967 static void
968 free_add_user_data(AddUserData *data)
970 g_free(data->username);
972 if (data->alias != NULL)
973 g_free(data->alias);
975 g_free(data);
978 static void
979 add_user_cb(AddUserData *data)
981 PurpleConnection *gc = purple_account_get_connection(data->account);
983 if (g_list_find(purple_connections_get_all(), gc))
985 purple_blist_request_add_buddy(data->account, data->username,
986 NULL, data->alias);
989 free_add_user_data(data);
992 static void
993 request_add(PurpleAccount *account, const char *remote_user,
994 const char *id, const char *alias,
995 const char *msg)
997 char *buffer;
998 PurpleConnection *gc;
999 AddUserData *data;
1001 gc = purple_account_get_connection(account);
1003 data = g_new0(AddUserData, 1);
1004 data->account = account;
1005 data->username = g_strdup(remote_user);
1006 data->alias = (alias != NULL ? g_strdup(alias) : NULL);
1008 buffer = make_info(account, gc, remote_user, id, alias, msg);
1009 purple_request_action(NULL, NULL, _("Add buddy to your list?"),
1010 buffer, PURPLE_DEFAULT_ACTION_NONE,
1011 account, remote_user, NULL,
1012 data, 2,
1013 _("Add"), G_CALLBACK(add_user_cb),
1014 _("Cancel"), G_CALLBACK(free_add_user_data));
1015 g_free(buffer);
1018 /* Copied from gtkaccount.c */
1019 typedef struct {
1020 PurpleAccountRequestAuthorizationCb auth_cb;
1021 PurpleAccountRequestAuthorizationCb deny_cb;
1022 void *data;
1023 char *username;
1024 char *alias;
1025 PurpleAccount *account;
1026 } auth_and_add;
1028 static void
1029 free_auth_and_add(auth_and_add *aa)
1031 g_free(aa->username);
1032 g_free(aa->alias);
1033 g_free(aa);
1036 static void
1037 authorize_and_add_cb(auth_and_add *aa)
1039 aa->auth_cb(aa->data);
1040 purple_blist_request_add_buddy(aa->account, aa->username,
1041 NULL, aa->alias);
1044 static void
1045 deny_no_add_cb(auth_and_add *aa)
1047 aa->deny_cb(aa->data);
1050 static void *
1051 finch_request_authorize(PurpleAccount *account,
1052 const char *remote_user,
1053 const char *id,
1054 const char *alias,
1055 const char *message,
1056 gboolean on_list,
1057 PurpleAccountRequestAuthorizationCb auth_cb,
1058 PurpleAccountRequestAuthorizationCb deny_cb,
1059 void *user_data)
1061 char *buffer;
1062 PurpleConnection *gc;
1063 void *uihandle;
1065 gc = purple_account_get_connection(account);
1066 if (message != NULL && *message == '\0')
1067 message = NULL;
1069 buffer = g_strdup_printf(_("%s%s%s%s wants to add %s to his or her buddy list%s%s"),
1070 remote_user,
1071 (alias != NULL ? " (" : ""),
1072 (alias != NULL ? alias : ""),
1073 (alias != NULL ? ")" : ""),
1074 (id != NULL
1075 ? id
1076 : (purple_connection_get_display_name(gc) != NULL
1077 ? purple_connection_get_display_name(gc)
1078 : purple_account_get_username(account))),
1079 (message != NULL ? ": " : "."),
1080 (message != NULL ? message : ""));
1081 if (!on_list) {
1082 GntWidget *widget;
1083 GList *iter;
1084 auth_and_add *aa = g_new(auth_and_add, 1);
1086 aa->auth_cb = auth_cb;
1087 aa->deny_cb = deny_cb;
1088 aa->data = user_data;
1089 aa->username = g_strdup(remote_user);
1090 aa->alias = g_strdup(alias);
1091 aa->account = account;
1093 uihandle = gnt_vwindow_new(FALSE);
1094 gnt_box_set_title(GNT_BOX(uihandle), _("Authorize buddy?"));
1095 gnt_box_set_pad(GNT_BOX(uihandle), 0);
1097 widget = purple_request_action(NULL, _("Authorize buddy?"), buffer, NULL,
1098 PURPLE_DEFAULT_ACTION_NONE,
1099 account, remote_user, NULL,
1100 aa, 2,
1101 _("Authorize"), authorize_and_add_cb,
1102 _("Deny"), deny_no_add_cb);
1103 gnt_screen_release(widget);
1104 gnt_box_set_toplevel(GNT_BOX(widget), FALSE);
1105 gnt_box_add_widget(GNT_BOX(uihandle), widget);
1107 gnt_box_add_widget(GNT_BOX(uihandle), gnt_hline_new());
1109 widget = finch_retrieve_user_info(purple_account_get_connection(account), remote_user);
1110 for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) {
1111 if (GNT_IS_BUTTON(iter->data)) {
1112 gnt_widget_destroy(iter->data);
1113 gnt_box_remove(GNT_BOX(widget), iter->data);
1114 break;
1117 gnt_box_set_toplevel(GNT_BOX(widget), FALSE);
1118 gnt_screen_release(widget);
1119 gnt_box_add_widget(GNT_BOX(uihandle), widget);
1120 gnt_widget_show(uihandle);
1122 g_signal_connect_swapped(G_OBJECT(uihandle), "destroy", G_CALLBACK(free_auth_and_add), aa);
1123 } else {
1124 uihandle = purple_request_action(NULL, _("Authorize buddy?"), buffer, NULL,
1125 PURPLE_DEFAULT_ACTION_NONE,
1126 account, remote_user, NULL,
1127 user_data, 2,
1128 _("Authorize"), auth_cb,
1129 _("Deny"), deny_cb);
1131 g_signal_connect(G_OBJECT(uihandle), "destroy",
1132 G_CALLBACK(purple_account_request_close), NULL);
1133 g_free(buffer);
1134 return uihandle;
1137 static void
1138 finch_request_close(void *uihandle)
1140 purple_request_close(PURPLE_REQUEST_ACTION, uihandle);
1143 static PurpleAccountUiOps ui_ops =
1145 notify_added,
1146 NULL,
1147 request_add,
1148 finch_request_authorize,
1149 finch_request_close,
1150 NULL,
1151 NULL,
1152 NULL,
1153 NULL
1156 PurpleAccountUiOps *finch_accounts_get_ui_ops()
1158 return &ui_ops;