Change the "length of bstream" data type to be a gsize, since it represents
[pidgin-git.git] / finch / gntaccount.c
blob4f94cfa6e63e3bd5a24c8346cc3383dcf98d2ada
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 /* TODO: */
241 else
243 g_assert_not_reached();
248 /* XXX: Proxy options */
250 if (accounts.window && accounts.tree) {
251 gnt_tree_set_selected(GNT_TREE(accounts.tree), account);
252 gnt_box_give_focus_to_child(GNT_BOX(accounts.window), accounts.tree);
255 if (prplinfo && prplinfo->register_user &&
256 gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->regserver))) {
257 purple_account_register(account);
258 } else if (dialog->account == NULL) {
259 /* This is a new account. Set it to the current status. */
260 /* Xerox from gtkaccount.c :D */
261 const PurpleSavedStatus *saved_status;
262 saved_status = purple_savedstatus_get_current();
263 if (saved_status != NULL) {
264 purple_savedstatus_activate_for_account(saved_status, account);
265 purple_account_set_enabled(account, FINCH_UI, TRUE);
269 /* In case of a new account, the 'Accounts' window is updated from the account-added
270 * callback. In case of changes in an existing account, we need to explicitly do it
271 * here.
273 if (dialog->account != NULL && accounts.window) {
274 gnt_tree_change_text(GNT_TREE(accounts.tree), dialog->account,
275 0, purple_account_get_username(dialog->account));
276 gnt_tree_change_text(GNT_TREE(accounts.tree), dialog->account,
277 1, purple_account_get_protocol_name(dialog->account));
280 gnt_widget_destroy(dialog->window);
283 static void
284 update_user_splits(AccountEditDialog *dialog)
286 GntWidget *hbox;
287 PurplePlugin *plugin;
288 PurplePluginProtocolInfo *prplinfo;
289 GList *iter, *entries;
290 char *username = NULL;
292 if (dialog->splits)
294 gnt_box_remove_all(GNT_BOX(dialog->splits));
295 g_list_free(dialog->split_entries);
297 else
299 dialog->splits = gnt_vbox_new(FALSE);
300 gnt_box_set_pad(GNT_BOX(dialog->splits), 0);
301 gnt_box_set_fill(GNT_BOX(dialog->splits), TRUE);
304 dialog->split_entries = NULL;
306 plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
307 if (!plugin)
308 return;
309 prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
311 username = dialog->account ? g_strdup(purple_account_get_username(dialog->account)) : NULL;
313 for (iter = prplinfo->user_splits; iter; iter = iter->next)
315 PurpleAccountUserSplit *split = iter->data;
316 GntWidget *entry;
317 char *buf;
319 hbox = gnt_hbox_new(TRUE);
320 gnt_box_add_widget(GNT_BOX(dialog->splits), hbox);
322 buf = g_strdup_printf("%s:", purple_account_user_split_get_text(split));
323 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(buf));
325 entry = gnt_entry_new(NULL);
326 gnt_box_add_widget(GNT_BOX(hbox), entry);
328 dialog->split_entries = g_list_append(dialog->split_entries, entry);
329 g_free(buf);
332 for (iter = g_list_last(prplinfo->user_splits), entries = g_list_last(dialog->split_entries);
333 iter && entries; iter = iter->prev, entries = entries->prev)
335 GntWidget *entry = entries->data;
336 PurpleAccountUserSplit *split = iter->data;
337 const char *value = NULL;
338 char *s;
340 if (dialog->account)
342 if(purple_account_user_split_get_reverse(split))
343 s = strrchr(username, purple_account_user_split_get_separator(split));
344 else
345 s = strchr(username, purple_account_user_split_get_separator(split));
347 if (s != NULL)
349 *s = '\0';
350 s++;
351 value = s;
354 if (value == NULL)
355 value = purple_account_user_split_get_default_value(split);
357 if (value != NULL)
358 gnt_entry_set_text(GNT_ENTRY(entry), value);
361 if (username != NULL)
362 gnt_entry_set_text(GNT_ENTRY(dialog->username), username);
364 g_free(username);
367 static void
368 add_protocol_options(AccountEditDialog *dialog)
370 PurplePlugin *plugin;
371 PurplePluginProtocolInfo *prplinfo;
372 GList *iter;
373 GntWidget *vbox, *box;
374 PurpleAccount *account;
376 if (dialog->prpls)
377 gnt_box_remove_all(GNT_BOX(dialog->prpls));
378 else
380 dialog->prpls = vbox = gnt_vbox_new(FALSE);
381 gnt_box_set_pad(GNT_BOX(vbox), 0);
382 gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_LEFT);
383 gnt_box_set_fill(GNT_BOX(vbox), TRUE);
386 if (dialog->prpl_entries)
388 g_list_free(dialog->prpl_entries);
389 dialog->prpl_entries = NULL;
392 vbox = dialog->prpls;
394 plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
395 if (!plugin)
396 return;
398 prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
400 account = dialog->account;
402 for (iter = prplinfo->protocol_options; iter; iter = iter->next)
404 PurpleAccountOption *option = iter->data;
405 PurplePrefType type = purple_account_option_get_type(option);
407 box = gnt_hbox_new(TRUE);
408 gnt_box_set_pad(GNT_BOX(box), 0);
409 gnt_box_add_widget(GNT_BOX(vbox), box);
411 if (type == PURPLE_PREF_BOOLEAN)
413 GntWidget *widget = gnt_check_box_new(purple_account_option_get_text(option));
414 gnt_box_add_widget(GNT_BOX(box), widget);
415 dialog->prpl_entries = g_list_append(dialog->prpl_entries, widget);
417 if (account)
418 gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
419 purple_account_get_bool(account,
420 purple_account_option_get_setting(option),
421 purple_account_option_get_default_bool(option)));
422 else
423 gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
424 purple_account_option_get_default_bool(option));
426 else
428 gnt_box_add_widget(GNT_BOX(box),
429 gnt_label_new(purple_account_option_get_text(option)));
431 if (type == PURPLE_PREF_STRING_LIST)
433 /* TODO: Use a combobox */
434 /* Don't forget to append the widget to prpl_entries */
436 else
438 GntWidget *entry = gnt_entry_new(NULL);
439 gnt_box_add_widget(GNT_BOX(box), entry);
440 dialog->prpl_entries = g_list_append(dialog->prpl_entries, entry);
442 if (type == PURPLE_PREF_STRING)
444 const char *dv = purple_account_option_get_default_string(option);
446 if (account)
447 gnt_entry_set_text(GNT_ENTRY(entry),
448 purple_account_get_string(account,
449 purple_account_option_get_setting(option), dv));
450 else
451 gnt_entry_set_text(GNT_ENTRY(entry), dv);
453 else if (type == PURPLE_PREF_INT)
455 char str[32];
456 int value = purple_account_option_get_default_int(option);
457 if (account)
458 value = purple_account_get_int(account,
459 purple_account_option_get_setting(option), value);
460 snprintf(str, sizeof(str), "%d", value);
461 gnt_entry_set_flag(GNT_ENTRY(entry), GNT_ENTRY_FLAG_INT);
462 gnt_entry_set_text(GNT_ENTRY(entry), str);
464 else
466 g_assert_not_reached();
472 /* Show the registration checkbox only in a new account dialog,
473 * and when the selected prpl has the support for it. */
474 gnt_widget_set_visible(dialog->regserver, account == NULL &&
475 prplinfo->register_user != NULL);
478 static void
479 update_user_options(AccountEditDialog *dialog)
481 PurplePlugin *plugin;
482 PurplePluginProtocolInfo *prplinfo;
484 plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
485 if (!plugin)
486 return;
488 prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
490 if (dialog->newmail == NULL)
491 dialog->newmail = gnt_check_box_new(_("New mail notifications"));
492 if (dialog->account)
493 gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->newmail),
494 purple_account_get_check_mail(dialog->account));
495 if (!prplinfo || !(prplinfo->options & OPT_PROTO_MAIL_CHECK))
496 gnt_widget_set_visible(dialog->newmail, FALSE);
497 else
498 gnt_widget_set_visible(dialog->newmail, TRUE);
500 if (dialog->remember == NULL)
501 dialog->remember = gnt_check_box_new(_("Remember password"));
502 if (dialog->account)
503 gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->remember),
504 purple_account_get_remember_password(dialog->account));
507 static void
508 prpl_changed_cb(GntWidget *combo, PurplePlugin *old, PurplePlugin *new, AccountEditDialog *dialog)
510 update_user_splits(dialog);
511 add_protocol_options(dialog);
512 update_user_options(dialog); /* This may not be necessary here */
513 gnt_box_readjust(GNT_BOX(dialog->window));
514 gnt_widget_draw(dialog->window);
517 static void
518 edit_account(PurpleAccount *account)
520 GntWidget *window, *hbox;
521 GntWidget *combo, *button, *entry;
522 GList *list, *iter;
523 AccountEditDialog *dialog;
524 PurplePlugin *plugin;
526 if (account)
528 GList *iter;
529 for (iter = accountdialogs; iter; iter = iter->next)
531 AccountEditDialog *dlg = iter->data;
532 if (dlg->account == account)
533 return;
537 list = purple_plugins_get_protocols();
538 if (list == NULL) {
539 purple_notify_error(NULL, _("Error"),
540 _("There are no protocol plugins installed."),
541 _("(You probably forgot to 'make install'.)"));
542 return;
545 dialog = g_new0(AccountEditDialog, 1);
546 accountdialogs = g_list_prepend(accountdialogs, dialog);
548 dialog->window = window = gnt_vbox_new(FALSE);
549 dialog->account = account;
550 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
551 gnt_box_set_title(GNT_BOX(window), account ? _("Modify Account") : _("New Account"));
552 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
553 gnt_box_set_pad(GNT_BOX(window), 0);
554 gnt_widget_set_name(window, "edit-account");
555 gnt_box_set_fill(GNT_BOX(window), TRUE);
557 hbox = gnt_hbox_new(TRUE);
558 gnt_box_set_pad(GNT_BOX(hbox), 0);
559 gnt_box_add_widget(GNT_BOX(window), hbox);
561 dialog->protocol = combo = gnt_combo_box_new();
562 for (iter = list; iter; iter = iter->next)
564 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), iter->data,
565 ((PurplePlugin*)iter->data)->info->name);
568 plugin = purple_plugins_find_with_id(purple_account_get_protocol_id(account));
570 if (account && plugin)
571 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), plugin);
572 else
573 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), list->data);
575 g_signal_connect(G_OBJECT(combo), "selection-changed", G_CALLBACK(prpl_changed_cb), dialog);
577 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Protocol:")));
578 gnt_box_add_widget(GNT_BOX(hbox), combo);
580 hbox = gnt_hbox_new(TRUE);
581 gnt_box_set_pad(GNT_BOX(hbox), 0);
582 gnt_box_add_widget(GNT_BOX(window), hbox);
584 dialog->username = entry = gnt_entry_new(NULL);
585 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Username:")));
586 gnt_box_add_widget(GNT_BOX(hbox), entry);
588 /* User splits */
589 update_user_splits(dialog);
590 gnt_box_add_widget(GNT_BOX(window), dialog->splits);
592 hbox = gnt_hbox_new(TRUE);
593 gnt_box_set_pad(GNT_BOX(hbox), 0);
594 gnt_box_add_widget(GNT_BOX(window), hbox);
596 dialog->password = entry = gnt_entry_new(NULL);
597 gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
598 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Password:")));
599 gnt_box_add_widget(GNT_BOX(hbox), entry);
600 if (account)
601 gnt_entry_set_text(GNT_ENTRY(entry), purple_account_get_password(account));
603 hbox = gnt_hbox_new(TRUE);
604 gnt_box_set_pad(GNT_BOX(hbox), 0);
605 gnt_box_add_widget(GNT_BOX(window), hbox);
607 dialog->alias = entry = gnt_entry_new(NULL);
608 gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Alias:")));
609 gnt_box_add_widget(GNT_BOX(hbox), entry);
610 if (account)
611 gnt_entry_set_text(GNT_ENTRY(entry), purple_account_get_alias(account));
613 /* User options */
614 update_user_options(dialog);
615 gnt_box_add_widget(GNT_BOX(window), dialog->remember);
616 gnt_box_add_widget(GNT_BOX(window), dialog->newmail);
618 /* Register checkbox */
619 dialog->regserver = gnt_check_box_new(_("Create this account on the server"));
620 gnt_box_add_widget(GNT_BOX(window), dialog->regserver);
622 gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
624 /* The advanced box */
625 add_protocol_options(dialog);
626 gnt_box_add_widget(GNT_BOX(window), dialog->prpls);
628 /* TODO: Add proxy options */
630 /* The button box */
631 hbox = gnt_hbox_new(FALSE);
632 gnt_box_add_widget(GNT_BOX(window), hbox);
633 gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
635 button = gnt_button_new(_("Cancel"));
636 gnt_box_add_widget(GNT_BOX(hbox), button);
637 g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window);
639 button = gnt_button_new(_("Save"));
640 gnt_box_add_widget(GNT_BOX(hbox), button);
641 g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(save_account_cb), dialog);
643 g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(edit_dialog_destroy), dialog);
645 gnt_widget_show(window);
646 gnt_box_readjust(GNT_BOX(window));
647 gnt_widget_draw(window);
650 static void
651 add_account_cb(GntWidget *widget, gpointer null)
653 edit_account(NULL);
656 static void
657 modify_account_cb(GntWidget *widget, GntTree *tree)
659 PurpleAccount *account = gnt_tree_get_selection_data(tree);
660 if (!account)
661 return;
662 edit_account(account);
665 static void
666 really_delete_account(PurpleAccount *account)
668 GList *iter;
669 for (iter = accountdialogs; iter; iter = iter->next)
671 AccountEditDialog *dlg = iter->data;
672 if (dlg->account == account)
674 gnt_widget_destroy(dlg->window);
675 break;
678 purple_request_close_with_handle(account); /* Close any other opened delete window */
679 purple_accounts_delete(account);
682 static void
683 delete_account_cb(GntWidget *widget, GntTree *tree)
685 PurpleAccount *account;
686 char *prompt;
688 account = gnt_tree_get_selection_data(tree);
689 if (!account)
690 return;
692 prompt = g_strdup_printf(_("Are you sure you want to delete %s?"),
693 purple_account_get_username(account));
695 purple_request_action(account, _("Delete Account"), prompt, NULL,
696 PURPLE_DEFAULT_ACTION_NONE,
697 account, NULL, NULL, account, 2,
698 _("Delete"), really_delete_account,
699 _("Cancel"), NULL);
700 g_free(prompt);
703 static void
704 account_toggled(GntWidget *widget, void *key, gpointer null)
706 PurpleAccount *account = key;
707 gboolean enabled = gnt_tree_get_choice(GNT_TREE(widget), key);
709 if (enabled)
710 purple_savedstatus_activate_for_account(purple_savedstatus_get_current(),
711 account);
713 purple_account_set_enabled(account, FINCH_UI, enabled);
716 static gboolean
717 account_list_key_pressed_cb(GntWidget *widget, const char *text, gpointer null)
719 GntTree *tree = GNT_TREE(widget);
720 PurpleAccount *account = gnt_tree_get_selection_data(tree);
721 int move, pos, count;
722 GList *accounts;
724 if (!account)
725 return FALSE;
727 switch (text[0]) {
728 case '-':
729 move = -1;
730 break;
731 case '=':
732 move = 2; /* XXX: This seems to be a bug in libpurple */
733 break;
734 default:
735 return FALSE;
738 accounts = purple_accounts_get_all();
739 count = g_list_length(accounts);
740 pos = g_list_index(accounts, account);
741 pos = (move + pos + count + 1) % (count + 1);
742 purple_accounts_reorder(account, pos);
744 /* I don't like this, but recreating the entire list seems to be
745 * the easiest way of doing it */
746 gnt_tree_remove_all(tree);
747 accounts = purple_accounts_get_all();
748 for (; accounts; accounts = accounts->next)
749 account_add(accounts->data);
750 gnt_tree_set_selected(tree, account);
752 return TRUE;
755 static void
756 reset_accounts_win(GntWidget *widget, gpointer null)
758 accounts.window = NULL;
759 accounts.tree = NULL;
762 void finch_accounts_show_all()
764 GList *iter;
765 GntWidget *box, *button;
767 if (accounts.window) {
768 gnt_window_present(accounts.window);
769 return;
772 accounts.window = gnt_vbox_new(FALSE);
773 gnt_box_set_toplevel(GNT_BOX(accounts.window), TRUE);
774 gnt_box_set_title(GNT_BOX(accounts.window), _("Accounts"));
775 gnt_box_set_pad(GNT_BOX(accounts.window), 0);
776 gnt_box_set_alignment(GNT_BOX(accounts.window), GNT_ALIGN_MID);
777 gnt_widget_set_name(accounts.window, "accounts");
779 gnt_box_add_widget(GNT_BOX(accounts.window),
780 gnt_label_new(_("You can enable/disable accounts from the following list.")));
782 gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE));
784 accounts.tree = gnt_tree_new_with_columns(2);
785 GNT_WIDGET_SET_FLAGS(accounts.tree, GNT_WIDGET_NO_BORDER);
787 for (iter = purple_accounts_get_all(); iter; iter = iter->next)
789 PurpleAccount *account = iter->data;
790 account_add(account);
793 g_signal_connect(G_OBJECT(accounts.tree), "toggled", G_CALLBACK(account_toggled), NULL);
794 g_signal_connect(G_OBJECT(accounts.tree), "key_pressed", G_CALLBACK(account_list_key_pressed_cb), NULL);
796 gnt_tree_set_col_width(GNT_TREE(accounts.tree), 0, 40);
797 gnt_tree_set_col_width(GNT_TREE(accounts.tree), 1, 10);
798 gnt_box_add_widget(GNT_BOX(accounts.window), accounts.tree);
800 gnt_box_add_widget(GNT_BOX(accounts.window), gnt_line_new(FALSE));
802 box = gnt_hbox_new(FALSE);
804 button = gnt_button_new(_("Add"));
805 gnt_box_add_widget(GNT_BOX(box), button);
806 gnt_util_set_trigger_widget(GNT_WIDGET(accounts.tree), GNT_KEY_INS, button);
807 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(add_account_cb), NULL);
809 button = gnt_button_new(_("Modify"));
810 gnt_box_add_widget(GNT_BOX(box), button);
811 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(modify_account_cb), accounts.tree);
813 button = gnt_button_new(_("Delete"));
814 gnt_box_add_widget(GNT_BOX(box), button);
815 gnt_util_set_trigger_widget(GNT_WIDGET(accounts.tree), GNT_KEY_DEL, button);
816 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(delete_account_cb), accounts.tree);
818 gnt_box_add_widget(GNT_BOX(accounts.window), box);
820 g_signal_connect(G_OBJECT(accounts.window), "destroy", G_CALLBACK(reset_accounts_win), NULL);
822 gnt_widget_show(accounts.window);
825 void finch_account_dialog_show(PurpleAccount *account)
827 edit_account(account);
830 static gpointer
831 finch_accounts_get_handle(void)
833 static int handle;
835 return &handle;
838 static void
839 account_added_callback(PurpleAccount *account)
841 if (accounts.window == NULL)
842 return;
843 account_add(account);
844 gnt_widget_draw(accounts.tree);
847 static void
848 account_removed_callback(PurpleAccount *account)
850 if (accounts.window == NULL)
851 return;
853 gnt_tree_remove(GNT_TREE(accounts.tree), account);
856 static void
857 account_abled_cb(PurpleAccount *account, gpointer user_data)
859 if (accounts.window == NULL)
860 return;
861 gnt_tree_set_choice(GNT_TREE(accounts.tree), account,
862 GPOINTER_TO_INT(user_data));
865 void finch_accounts_init()
867 GList *iter;
869 purple_signal_connect(purple_accounts_get_handle(), "account-added",
870 finch_accounts_get_handle(), PURPLE_CALLBACK(account_added_callback),
871 NULL);
872 purple_signal_connect(purple_accounts_get_handle(), "account-removed",
873 finch_accounts_get_handle(), PURPLE_CALLBACK(account_removed_callback),
874 NULL);
875 purple_signal_connect(purple_accounts_get_handle(), "account-disabled",
876 finch_accounts_get_handle(),
877 PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(FALSE));
878 purple_signal_connect(purple_accounts_get_handle(), "account-enabled",
879 finch_accounts_get_handle(),
880 PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE));
882 iter = purple_accounts_get_all();
883 if (iter) {
884 for (; iter; iter = iter->next) {
885 if (purple_account_get_enabled(iter->data, FINCH_UI))
886 break;
888 if (!iter)
889 finch_accounts_show_all();
890 } else {
891 edit_account(NULL);
892 finch_accounts_show_all();
896 void finch_accounts_uninit()
898 if (accounts.window)
899 gnt_widget_destroy(accounts.window);
902 /* The following uiops stuff are copied from gtkaccount.c */
903 typedef struct
905 PurpleAccount *account;
906 char *username;
907 char *alias;
908 } AddUserData;
910 static char *
911 make_info(PurpleAccount *account, PurpleConnection *gc, const char *remote_user,
912 const char *id, const char *alias, const char *msg)
914 if (msg != NULL && *msg == '\0')
915 msg = NULL;
917 return g_strdup_printf(_("%s%s%s%s has made %s his or her buddy%s%s"),
918 remote_user,
919 (alias != NULL ? " (" : ""),
920 (alias != NULL ? alias : ""),
921 (alias != NULL ? ")" : ""),
922 (id != NULL
923 ? id
924 : (purple_connection_get_display_name(gc) != NULL
925 ? purple_connection_get_display_name(gc)
926 : purple_account_get_username(account))),
927 (msg != NULL ? ": " : "."),
928 (msg != NULL ? msg : ""));
931 static void
932 notify_added(PurpleAccount *account, const char *remote_user,
933 const char *id, const char *alias,
934 const char *msg)
936 char *buffer;
937 PurpleConnection *gc;
939 gc = purple_account_get_connection(account);
941 buffer = make_info(account, gc, remote_user, id, alias, msg);
943 purple_notify_info(NULL, NULL, buffer, NULL);
945 g_free(buffer);
948 static void
949 free_add_user_data(AddUserData *data)
951 g_free(data->username);
953 if (data->alias != NULL)
954 g_free(data->alias);
956 g_free(data);
959 static void
960 add_user_cb(AddUserData *data)
962 PurpleConnection *gc = purple_account_get_connection(data->account);
964 if (g_list_find(purple_connections_get_all(), gc))
966 purple_blist_request_add_buddy(data->account, data->username,
967 NULL, data->alias);
970 free_add_user_data(data);
973 static void
974 request_add(PurpleAccount *account, const char *remote_user,
975 const char *id, const char *alias,
976 const char *msg)
978 char *buffer;
979 PurpleConnection *gc;
980 AddUserData *data;
982 gc = purple_account_get_connection(account);
984 data = g_new0(AddUserData, 1);
985 data->account = account;
986 data->username = g_strdup(remote_user);
987 data->alias = (alias != NULL ? g_strdup(alias) : NULL);
989 buffer = make_info(account, gc, remote_user, id, alias, msg);
990 purple_request_action(NULL, NULL, _("Add buddy to your list?"),
991 buffer, PURPLE_DEFAULT_ACTION_NONE,
992 account, remote_user, NULL,
993 data, 2,
994 _("Add"), G_CALLBACK(add_user_cb),
995 _("Cancel"), G_CALLBACK(free_add_user_data));
996 g_free(buffer);
999 /* Copied from gtkaccount.c */
1000 typedef struct {
1001 PurpleAccountRequestAuthorizationCb auth_cb;
1002 PurpleAccountRequestAuthorizationCb deny_cb;
1003 void *data;
1004 char *username;
1005 char *alias;
1006 PurpleAccount *account;
1007 } auth_and_add;
1009 static void
1010 free_auth_and_add(auth_and_add *aa)
1012 g_free(aa->username);
1013 g_free(aa->alias);
1014 g_free(aa);
1017 static void
1018 authorize_and_add_cb(auth_and_add *aa)
1020 aa->auth_cb(aa->data);
1021 purple_blist_request_add_buddy(aa->account, aa->username,
1022 NULL, aa->alias);
1025 static void
1026 deny_no_add_cb(auth_and_add *aa)
1028 aa->deny_cb(aa->data);
1031 static void *
1032 finch_request_authorize(PurpleAccount *account,
1033 const char *remote_user,
1034 const char *id,
1035 const char *alias,
1036 const char *message,
1037 gboolean on_list,
1038 PurpleAccountRequestAuthorizationCb auth_cb,
1039 PurpleAccountRequestAuthorizationCb deny_cb,
1040 void *user_data)
1042 char *buffer;
1043 PurpleConnection *gc;
1044 void *uihandle;
1046 gc = purple_account_get_connection(account);
1047 if (message != NULL && *message == '\0')
1048 message = NULL;
1050 buffer = g_strdup_printf(_("%s%s%s%s wants to add %s to his or her buddy list%s%s"),
1051 remote_user,
1052 (alias != NULL ? " (" : ""),
1053 (alias != NULL ? alias : ""),
1054 (alias != NULL ? ")" : ""),
1055 (id != NULL
1056 ? id
1057 : (purple_connection_get_display_name(gc) != NULL
1058 ? purple_connection_get_display_name(gc)
1059 : purple_account_get_username(account))),
1060 (message != NULL ? ": " : "."),
1061 (message != NULL ? message : ""));
1062 if (!on_list) {
1063 GntWidget *widget;
1064 GList *iter;
1065 auth_and_add *aa = g_new(auth_and_add, 1);
1067 aa->auth_cb = auth_cb;
1068 aa->deny_cb = deny_cb;
1069 aa->data = user_data;
1070 aa->username = g_strdup(remote_user);
1071 aa->alias = g_strdup(alias);
1072 aa->account = account;
1074 uihandle = gnt_vwindow_new(FALSE);
1075 gnt_box_set_title(GNT_BOX(uihandle), _("Authorize buddy?"));
1076 gnt_box_set_pad(GNT_BOX(uihandle), 0);
1078 widget = purple_request_action(NULL, _("Authorize buddy?"), buffer, NULL,
1079 PURPLE_DEFAULT_ACTION_NONE,
1080 account, remote_user, NULL,
1081 aa, 2,
1082 _("Authorize"), authorize_and_add_cb,
1083 _("Deny"), deny_no_add_cb);
1084 gnt_screen_release(widget);
1085 gnt_box_set_toplevel(GNT_BOX(widget), FALSE);
1086 gnt_box_add_widget(GNT_BOX(uihandle), widget);
1088 gnt_box_add_widget(GNT_BOX(uihandle), gnt_hline_new());
1090 widget = finch_retrieve_user_info(purple_account_get_connection(account), remote_user);
1091 for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) {
1092 if (GNT_IS_BUTTON(iter->data)) {
1093 gnt_widget_destroy(iter->data);
1094 gnt_box_remove(GNT_BOX(widget), iter->data);
1095 break;
1098 gnt_box_set_toplevel(GNT_BOX(widget), FALSE);
1099 gnt_screen_release(widget);
1100 gnt_box_add_widget(GNT_BOX(uihandle), widget);
1101 gnt_widget_show(uihandle);
1103 g_signal_connect_swapped(G_OBJECT(uihandle), "destroy", G_CALLBACK(free_auth_and_add), aa);
1104 } else {
1105 uihandle = purple_request_action(NULL, _("Authorize buddy?"), buffer, NULL,
1106 PURPLE_DEFAULT_ACTION_NONE,
1107 account, remote_user, NULL,
1108 user_data, 2,
1109 _("Authorize"), auth_cb,
1110 _("Deny"), deny_cb);
1112 g_signal_connect(G_OBJECT(uihandle), "destroy",
1113 G_CALLBACK(purple_account_request_close), NULL);
1114 g_free(buffer);
1115 return uihandle;
1118 static void
1119 finch_request_close(void *uihandle)
1121 purple_request_close(PURPLE_REQUEST_ACTION, uihandle);
1124 static PurpleAccountUiOps ui_ops =
1126 notify_added,
1127 NULL,
1128 request_add,
1129 finch_request_authorize,
1130 finch_request_close,
1131 NULL,
1132 NULL,
1133 NULL,
1134 NULL
1137 PurpleAccountUiOps *finch_accounts_get_ui_ops()
1139 return &ui_ops;