comparison pidgin/gtkaccount.c @ 15374:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children 29e443e0613f
comparison
equal deleted inserted replaced
15373:f79e0f4df793 15374:5fe8042783c1
1 /**
2 * @file gtkaccount.c GTK+ Account Editor UI
3 * @ingroup gtkui
4 *
5 * gaim
6 *
7 * Gaim is the legal property of its developers, whose names are too numerous
8 * to list here. Please refer to the COPYRIGHT file distributed with this
9 * source distribution.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26 #include "internal.h"
27 #include "gtkgaim.h"
28
29 #include "account.h"
30 #include "accountopt.h"
31 #include "core.h"
32 #include "debug.h"
33 #include "notify.h"
34 #include "plugin.h"
35 #include "prefs.h"
36 #include "prpl.h"
37 #include "request.h"
38 #include "savedstatuses.h"
39 #include "signals.h"
40 #include "util.h"
41
42 #include "gtkaccount.h"
43 #include "gtkblist.h"
44 #include "gtkdialogs.h"
45 #include "gtkutils.h"
46 #include "gtkstatusbox.h"
47 #include "gaimstock.h"
48
49 enum
50 {
51 COLUMN_ICON,
52 COLUMN_BUDDYICON,
53 COLUMN_SCREENNAME,
54 COLUMN_ENABLED,
55 COLUMN_PROTOCOL,
56 COLUMN_DATA,
57 COLUMN_PULSE_DATA,
58 NUM_COLUMNS
59 };
60
61 typedef struct
62 {
63 GaimAccount *account;
64 char *username;
65 char *alias;
66
67 } GaimGtkAccountAddUserData;
68
69 typedef struct
70 {
71 GtkWidget *window;
72 GtkWidget *treeview;
73
74 GtkWidget *modify_button;
75 GtkWidget *delete_button;
76 GtkWidget *notebook;
77
78 GtkListStore *model;
79 GtkTreeIter drag_iter;
80
81 GtkTreeViewColumn *screenname_col;
82
83 } AccountsWindow;
84
85 typedef struct
86 {
87 GaimGtkAccountDialogType type;
88
89 GaimAccount *account;
90 char *protocol_id;
91 GaimPlugin *plugin;
92 GaimPluginProtocolInfo *prpl_info;
93
94 GaimProxyType new_proxy_type;
95
96 GList *user_split_entries;
97 GList *protocol_opt_entries;
98
99 GtkSizeGroup *sg;
100 GtkWidget *window;
101
102 GtkWidget *top_vbox;
103 GtkWidget *bottom_vbox;
104 GtkWidget *ok_button;
105 GtkWidget *register_button;
106
107 /* Login Options */
108 GtkWidget *login_frame;
109 GtkWidget *protocol_menu;
110 GtkWidget *password_box;
111 GtkWidget *screenname_entry;
112 GtkWidget *password_entry;
113 GtkWidget *alias_entry;
114 GtkWidget *remember_pass_check;
115
116 /* User Options */
117 GtkWidget *user_frame;
118 GtkWidget *new_mail_check;
119 GtkWidget *icon_hbox;
120 GtkWidget *icon_check;
121 GtkWidget *icon_entry;
122 GtkWidget *icon_filesel;
123 GtkWidget *icon_preview;
124 GtkWidget *icon_text;
125 char *cached_icon_path;
126 char *icon_path;
127
128 /* Protocol Options */
129 GtkWidget *protocol_frame;
130
131 /* Proxy Options */
132 GtkWidget *proxy_frame;
133 GtkWidget *proxy_vbox;
134 GtkWidget *proxy_dropdown;
135 GtkWidget *proxy_host_entry;
136 GtkWidget *proxy_port_entry;
137 GtkWidget *proxy_user_entry;
138 GtkWidget *proxy_pass_entry;
139
140 /* Are we registering? */
141 gboolean registering;
142
143 } AccountPrefsDialog;
144
145 typedef struct
146 {
147 GdkPixbuf *online_pixbuf;
148 gboolean pulse_to_grey;
149 float pulse_value;
150 int timeout;
151 GaimAccount *account;
152 GtkTreeModel *model;
153
154 } GaimGtkPulseData;
155
156
157 static AccountsWindow *accounts_window = NULL;
158 static GHashTable *account_pref_wins;
159
160 static void add_account_to_liststore(GaimAccount *account, gpointer user_data);
161 static void set_account(GtkListStore *store, GtkTreeIter *iter,
162 GaimAccount *account);
163
164 /**************************************************************************
165 * Add/Modify Account dialog
166 **************************************************************************/
167 static void add_login_options(AccountPrefsDialog *dialog, GtkWidget *parent);
168 static void add_user_options(AccountPrefsDialog *dialog, GtkWidget *parent);
169 static void add_protocol_options(AccountPrefsDialog *dialog,
170 GtkWidget *parent);
171 static void add_proxy_options(AccountPrefsDialog *dialog, GtkWidget *parent);
172
173 static GtkWidget *
174 add_pref_box(AccountPrefsDialog *dialog, GtkWidget *parent,
175 const char *text, GtkWidget *widget)
176 {
177 GtkWidget *hbox;
178 GtkWidget *label;
179
180 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE);
181 gtk_box_pack_start(GTK_BOX(parent), hbox, FALSE, FALSE, 0);
182 gtk_widget_show(hbox);
183
184 label = gtk_label_new_with_mnemonic(text);
185 gtk_size_group_add_widget(dialog->sg, label);
186 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
187 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
188 gtk_widget_show(label);
189
190 gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, GAIM_HIG_BORDER);
191 gtk_widget_show(widget);
192 gaim_set_accessible_label (widget, label);
193
194 return hbox;
195 }
196
197 static void
198 set_dialog_icon(AccountPrefsDialog *dialog, gchar *new_cached_icon_path, gchar *new_icon_path)
199 {
200 char *filename;
201 GdkPixbuf *pixbuf = NULL;
202
203 g_free(dialog->cached_icon_path);
204 g_free(dialog->icon_path);
205 dialog->cached_icon_path = new_cached_icon_path;
206 dialog->icon_path = new_icon_path;
207
208 filename = gaim_buddy_icons_get_full_path(dialog->cached_icon_path);
209 if (filename != NULL) {
210 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
211 g_free(filename);
212 }
213
214 if (pixbuf && dialog->prpl_info &&
215 (dialog->prpl_info->icon_spec.scale_rules & GAIM_ICON_SCALE_DISPLAY))
216 {
217 /* Scale the icon to something reasonable */
218 int width, height;
219 GdkPixbuf *scale;
220
221 gaim_gtk_buddy_icon_get_scale_size(pixbuf, &dialog->prpl_info->icon_spec,
222 GAIM_ICON_SCALE_DISPLAY, &width, &height);
223 scale = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR);
224
225 g_object_unref(G_OBJECT(pixbuf));
226 pixbuf = scale;
227 }
228
229 if (pixbuf == NULL)
230 {
231 /* Show a placeholder icon */
232 gchar *filename;
233 filename = g_build_filename(DATADIR, "pixmaps",
234 "gaim", "insert-image.png", NULL);
235 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
236 g_free(filename);
237 }
238
239 gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_entry), pixbuf);
240 if (pixbuf != NULL)
241 g_object_unref(G_OBJECT(pixbuf));
242 }
243
244 static void
245 set_account_protocol_cb(GtkWidget *item, const char *id,
246 AccountPrefsDialog *dialog)
247 {
248 GaimPlugin *new_plugin;
249
250 new_plugin = gaim_find_prpl(id);
251
252 if (new_plugin == dialog->plugin)
253 return;
254
255 dialog->plugin = new_plugin;
256
257 if (dialog->plugin != NULL)
258 {
259 dialog->prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(dialog->plugin);
260
261 g_free(dialog->protocol_id);
262 dialog->protocol_id = g_strdup(dialog->plugin->info->id);
263 }
264
265 if (dialog->account != NULL)
266 gaim_account_clear_settings(dialog->account);
267
268 add_login_options(dialog, dialog->top_vbox);
269 add_user_options(dialog, dialog->top_vbox);
270 add_protocol_options(dialog, dialog->bottom_vbox);
271
272 if (!dialog->prpl_info || !dialog->prpl_info->register_user) {
273 gtk_widget_hide(dialog->register_button);
274 } else {
275 if (dialog->prpl_info != NULL &&
276 (dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME)) {
277 gtk_widget_set_sensitive(dialog->register_button, TRUE);
278 } else {
279 gtk_widget_set_sensitive(dialog->register_button, FALSE);
280 }
281 gtk_widget_show(dialog->register_button);
282 }
283 }
284
285 static void
286 screenname_changed_cb(GtkEntry *entry, AccountPrefsDialog *dialog)
287 {
288 if (dialog->ok_button)
289 gtk_widget_set_sensitive(dialog->ok_button,
290 *gtk_entry_get_text(entry) != '\0');
291 if (dialog->register_button) {
292 if (dialog->prpl_info != NULL && (dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME))
293 gtk_widget_set_sensitive(dialog->register_button, TRUE);
294 else
295 gtk_widget_set_sensitive(dialog->register_button,
296 *gtk_entry_get_text(entry) != '\0');
297 }
298 }
299
300 static void
301 icon_filesel_choose_cb(const char *filename, gpointer data)
302 {
303 AccountPrefsDialog *dialog;
304
305 dialog = data;
306
307 if (filename != NULL)
308 set_dialog_icon(dialog, gaim_gtk_convert_buddy_icon(dialog->plugin, filename), g_strdup(filename));
309
310 dialog->icon_filesel = NULL;
311 }
312
313 static void
314 icon_select_cb(GtkWidget *button, AccountPrefsDialog *dialog)
315 {
316 dialog->icon_filesel = gaim_gtk_buddy_icon_chooser_new(GTK_WINDOW(dialog->window), icon_filesel_choose_cb, dialog);
317 gtk_widget_show_all(dialog->icon_filesel);
318 }
319
320 static void
321 icon_reset_cb(GtkWidget *button, AccountPrefsDialog *dialog)
322 {
323 set_dialog_icon(dialog, NULL, NULL);
324 }
325
326 static void
327 account_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y,
328 GtkSelectionData *sd, guint info, guint t, AccountPrefsDialog *dialog)
329 {
330 gchar *name = (gchar *)sd->data;
331
332 if ((sd->length >= 0) && (sd->format == 8)) {
333 /* Well, it looks like the drag event was cool.
334 * Let's do something with it */
335 if (!g_ascii_strncasecmp(name, "file://", 7)) {
336 GError *converr = NULL;
337 gchar *tmp, *rtmp;
338 /* It looks like we're dealing with a local file. Let's
339 * just untar it in the right place */
340 if(!(tmp = g_filename_from_uri(name, NULL, &converr))) {
341 gaim_debug(GAIM_DEBUG_ERROR, "buddyicon", "%s\n",
342 (converr ? converr->message :
343 "g_filename_from_uri error"));
344 return;
345 }
346 if ((rtmp = strchr(tmp, '\r')) || (rtmp = strchr(tmp, '\n')))
347 *rtmp = '\0';
348 set_dialog_icon(dialog, gaim_gtk_convert_buddy_icon(dialog->plugin, tmp), g_strdup(tmp));
349 g_free(tmp);
350 }
351 gtk_drag_finish(dc, TRUE, FALSE, t);
352 }
353 gtk_drag_finish(dc, FALSE, FALSE, t);
354 }
355
356 static void
357 update_editable(GaimConnection *gc, AccountPrefsDialog *dialog)
358 {
359 gboolean set;
360 GList *l;
361
362 if (dialog->account == NULL)
363 return;
364
365 if (gc != NULL && dialog->account != gaim_connection_get_account(gc))
366 return;
367
368 set = !(gaim_account_is_connected(dialog->account) || gaim_account_is_connecting(dialog->account));
369 gtk_widget_set_sensitive(dialog->protocol_menu, set);
370 gtk_widget_set_sensitive(dialog->screenname_entry, set);
371
372 for (l = dialog->user_split_entries ; l != NULL ; l = l->next)
373 gtk_widget_set_sensitive((GtkWidget *)l->data, set);
374 }
375
376 static void
377 add_login_options(AccountPrefsDialog *dialog, GtkWidget *parent)
378 {
379 GtkWidget *frame;
380 GtkWidget *vbox;
381 GtkWidget *entry;
382 GList *user_splits;
383 GList *l, *l2;
384 char *username = NULL;
385
386 if (dialog->login_frame != NULL)
387 gtk_widget_destroy(dialog->login_frame);
388
389 /* Build the login options frame. */
390 frame = gaim_gtk_make_frame(parent, _("Login Options"));
391
392 /* cringe */
393 dialog->login_frame = gtk_widget_get_parent(gtk_widget_get_parent(frame));
394
395 gtk_box_reorder_child(GTK_BOX(parent), dialog->login_frame, 0);
396 gtk_widget_show(dialog->login_frame);
397
398 /* Main vbox */
399 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE);
400 gtk_container_add(GTK_CONTAINER(frame), vbox);
401 gtk_widget_show(vbox);
402
403 /* Protocol */
404 dialog->protocol_menu = gaim_gtk_protocol_option_menu_new(
405 dialog->protocol_id, G_CALLBACK(set_account_protocol_cb), dialog);
406
407 add_pref_box(dialog, vbox, _("Protocol:"), dialog->protocol_menu);
408
409 /* Screen name */
410 dialog->screenname_entry = gtk_entry_new();
411
412 add_pref_box(dialog, vbox, _("Screen name:"), dialog->screenname_entry);
413
414 g_signal_connect(G_OBJECT(dialog->screenname_entry), "changed",
415 G_CALLBACK(screenname_changed_cb), dialog);
416
417 /* Do the user split thang */
418 if (dialog->plugin == NULL) /* Yeah right. */
419 user_splits = NULL;
420 else
421 user_splits = dialog->prpl_info->user_splits;
422
423 if (dialog->account != NULL)
424 username = g_strdup(gaim_account_get_username(dialog->account));
425
426 if (dialog->user_split_entries != NULL) {
427 g_list_free(dialog->user_split_entries);
428 dialog->user_split_entries = NULL;
429 }
430
431 for (l = user_splits; l != NULL; l = l->next) {
432 GaimAccountUserSplit *split = l->data;
433 char *buf;
434
435 buf = g_strdup_printf("%s:", gaim_account_user_split_get_text(split));
436
437 entry = gtk_entry_new();
438
439 add_pref_box(dialog, vbox, buf, entry);
440
441 g_free(buf);
442
443 dialog->user_split_entries =
444 g_list_append(dialog->user_split_entries, entry);
445 }
446
447 for (l = g_list_last(dialog->user_split_entries),
448 l2 = g_list_last(user_splits);
449 l != NULL && l2 != NULL;
450 l = l->prev, l2 = l2->prev) {
451
452 GtkWidget *entry = l->data;
453 GaimAccountUserSplit *split = l2->data;
454 const char *value = NULL;
455 char *c;
456
457 if (dialog->account != NULL) {
458 c = strrchr(username,
459 gaim_account_user_split_get_separator(split));
460
461 if (c != NULL) {
462 *c = '\0';
463 c++;
464
465 value = c;
466 }
467 }
468
469 if (value == NULL)
470 value = gaim_account_user_split_get_default_value(split);
471
472 if (value != NULL)
473 gtk_entry_set_text(GTK_ENTRY(entry), value);
474 }
475
476 if (username != NULL)
477 gtk_entry_set_text(GTK_ENTRY(dialog->screenname_entry), username);
478
479 g_free(username);
480
481
482 /* Password */
483 dialog->password_entry = gtk_entry_new();
484 gtk_entry_set_visibility(GTK_ENTRY(dialog->password_entry), FALSE);
485 if (gtk_entry_get_invisible_char(GTK_ENTRY(dialog->password_entry)) == '*')
486 gtk_entry_set_invisible_char(GTK_ENTRY(dialog->password_entry), GAIM_INVISIBLE_CHAR);
487 dialog->password_box = add_pref_box(dialog, vbox, _("Password:"),
488 dialog->password_entry);
489
490 /* Alias */
491 dialog->alias_entry = gtk_entry_new();
492 add_pref_box(dialog, vbox, _("Local alias:"), dialog->alias_entry);
493
494 /* Remember Password */
495 dialog->remember_pass_check =
496 gtk_check_button_new_with_label(_("Remember password"));
497 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->remember_pass_check),
498 FALSE);
499 gtk_box_pack_start(GTK_BOX(vbox), dialog->remember_pass_check,
500 FALSE, FALSE, 0);
501 gtk_widget_show(dialog->remember_pass_check);
502
503 /* Set the fields. */
504 if (dialog->account != NULL) {
505 if (gaim_account_get_password(dialog->account))
506 gtk_entry_set_text(GTK_ENTRY(dialog->password_entry),
507 gaim_account_get_password(dialog->account));
508
509 if (gaim_account_get_alias(dialog->account))
510 gtk_entry_set_text(GTK_ENTRY(dialog->alias_entry),
511 gaim_account_get_alias(dialog->account));
512
513 gtk_toggle_button_set_active(
514 GTK_TOGGLE_BUTTON(dialog->remember_pass_check),
515 gaim_account_get_remember_password(dialog->account));
516 }
517
518 if (dialog->prpl_info != NULL &&
519 (dialog->prpl_info->options & OPT_PROTO_NO_PASSWORD)) {
520
521 gtk_widget_hide(dialog->password_box);
522 gtk_widget_hide(dialog->remember_pass_check);
523 }
524
525 /* Do not let the user change the protocol/screenname while connected. */
526 update_editable(NULL, dialog);
527 gaim_signal_connect(gaim_connections_get_handle(), "signing-on", dialog,
528 G_CALLBACK(update_editable), dialog);
529 gaim_signal_connect(gaim_connections_get_handle(), "signed-off", dialog,
530 G_CALLBACK(update_editable), dialog);
531 }
532
533 static void
534 icon_check_cb(GtkWidget *checkbox, AccountPrefsDialog *dialog)
535 {
536 gtk_widget_set_sensitive(dialog->icon_hbox, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check)));
537 }
538
539 static void
540 add_user_options(AccountPrefsDialog *dialog, GtkWidget *parent)
541 {
542 GtkWidget *frame;
543 GtkWidget *vbox;
544 GtkWidget *vbox2;
545 GtkWidget *hbox;
546 GtkWidget *hbox2;
547 GtkWidget *button;
548 GtkWidget *label;
549
550 if (dialog->user_frame != NULL)
551 gtk_widget_destroy(dialog->user_frame);
552
553 /* Build the user options frame. */
554 frame = gaim_gtk_make_frame(parent, _("User Options"));
555 dialog->user_frame = gtk_widget_get_parent(gtk_widget_get_parent(frame));
556
557 gtk_box_reorder_child(GTK_BOX(parent), dialog->user_frame, 1);
558 gtk_widget_show(dialog->user_frame);
559
560 /* Main vbox */
561 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE);
562 gtk_container_add(GTK_CONTAINER(frame), vbox);
563 gtk_widget_show(vbox);
564
565 /* New mail notifications */
566 dialog->new_mail_check =
567 gtk_check_button_new_with_label(_("New mail notifications"));
568 gtk_box_pack_start(GTK_BOX(vbox), dialog->new_mail_check, FALSE, FALSE, 0);
569 gtk_widget_show(dialog->new_mail_check);
570
571 /* Buddy icon */
572 dialog->icon_check = gtk_check_button_new_with_label(_("Use this buddy icon for this account:"));
573 g_signal_connect(G_OBJECT(dialog->icon_check), "toggled", G_CALLBACK(icon_check_cb), dialog);
574 gtk_widget_show(dialog->icon_check);
575 gtk_box_pack_start(GTK_BOX(vbox), dialog->icon_check, FALSE, FALSE, 0);
576
577 dialog->icon_hbox = hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE);
578 gtk_widget_set_sensitive(hbox, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check)));
579 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
580 gtk_widget_show(hbox);
581
582 label = gtk_label_new(" ");
583 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
584 gtk_widget_show(label);
585
586 button = gtk_button_new();
587 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
588 gtk_widget_show(button);
589 g_signal_connect(G_OBJECT(button), "clicked",
590 G_CALLBACK(icon_select_cb), dialog);
591
592 dialog->icon_entry = gtk_image_new();
593 gtk_container_add(GTK_CONTAINER(button), dialog->icon_entry);
594 gtk_widget_show(dialog->icon_entry);
595 /* TODO: Uh, isn't this next line pretty useless? */
596 gaim_set_accessible_label (dialog->icon_entry, label);
597 dialog->cached_icon_path = NULL;
598 dialog->icon_path = NULL;
599
600 vbox2 = gtk_vbox_new(FALSE, 0);
601 gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
602 gtk_widget_show(vbox2);
603
604 hbox2 = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE);
605 gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, GAIM_HIG_BORDER);
606 gtk_widget_show(hbox2);
607
608 button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
609 g_signal_connect(G_OBJECT(button), "clicked",
610 G_CALLBACK(icon_reset_cb), dialog);
611 gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0);
612 gtk_widget_show(button);
613
614 if (dialog->prpl_info != NULL) {
615 if (!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK))
616 gtk_widget_hide(dialog->new_mail_check);
617
618 if (dialog->prpl_info->icon_spec.format == NULL)
619 gtk_widget_hide(dialog->icon_hbox);
620 }
621
622 if (dialog->account != NULL) {
623 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->new_mail_check),
624 gaim_account_get_check_mail(dialog->account));
625
626 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->icon_check),
627 !gaim_account_get_bool(dialog->account, "use-global-buddyicon",
628 TRUE));
629 set_dialog_icon(dialog,
630 g_strdup(gaim_account_get_ui_string(dialog->account,
631 GAIM_GTK_UI, "non-global-buddyicon-cached-path", NULL)),
632 g_strdup(gaim_account_get_ui_string(dialog->account,
633 GAIM_GTK_UI, "non-global-buddyicon-path", NULL)));
634 } else {
635 set_dialog_icon(dialog, NULL, NULL);
636 }
637
638 if (!dialog->prpl_info ||
639 (!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK) &&
640 (dialog->prpl_info->icon_spec.format == NULL))) {
641
642 /* Nothing to see :( aww. */
643 gtk_widget_hide(dialog->user_frame);
644 }
645 }
646
647 static void
648 add_protocol_options(AccountPrefsDialog *dialog, GtkWidget *parent)
649 {
650 GaimAccountOption *option;
651 GaimAccount *account;
652 GtkWidget *frame, *vbox, *check, *entry, *combo;
653 const GList *list, *node;
654 gint i, idx, int_value;
655 GtkListStore *model;
656 GtkTreeIter iter;
657 GtkCellRenderer *renderer;
658 GaimKeyValuePair *kvp;
659 GList *l;
660 char buf[1024];
661 char *title;
662 const char *str_value;
663 gboolean bool_value;
664
665 if (dialog->protocol_frame != NULL) {
666 gtk_widget_destroy(dialog->protocol_frame);
667 dialog->protocol_frame = NULL;
668 }
669
670 if (dialog->protocol_opt_entries != NULL) {
671 g_list_free(dialog->protocol_opt_entries);
672 dialog->protocol_opt_entries = NULL;
673 }
674
675 if (dialog->prpl_info == NULL ||
676 dialog->prpl_info->protocol_options == NULL) {
677
678 return;
679 }
680
681 account = dialog->account;
682
683 /* Build the protocol options frame. */
684 g_snprintf(buf, sizeof(buf), _("%s Options"), dialog->plugin->info->name);
685
686 frame = gaim_gtk_make_frame(parent, buf);
687 dialog->protocol_frame =
688 gtk_widget_get_parent(gtk_widget_get_parent(frame));
689
690 gtk_box_reorder_child(GTK_BOX(parent), dialog->protocol_frame, 0);
691 gtk_widget_show(dialog->protocol_frame);
692
693 /* Main vbox */
694 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE);
695 gtk_container_add(GTK_CONTAINER(frame), vbox);
696 gtk_widget_show(vbox);
697
698 for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next)
699 {
700 option = (GaimAccountOption *)l->data;
701
702 switch (gaim_account_option_get_type(option))
703 {
704 case GAIM_PREF_BOOLEAN:
705 if (account == NULL ||
706 strcmp(gaim_account_get_protocol_id(account),
707 dialog->protocol_id))
708 {
709 bool_value = gaim_account_option_get_default_bool(option);
710 }
711 else
712 {
713 bool_value = gaim_account_get_bool(account,
714 gaim_account_option_get_setting(option),
715 gaim_account_option_get_default_bool(option));
716 }
717
718 check = gtk_check_button_new_with_label(
719 gaim_account_option_get_text(option));
720
721 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check),
722 bool_value);
723
724 gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
725 gtk_widget_show(check);
726
727 dialog->protocol_opt_entries =
728 g_list_append(dialog->protocol_opt_entries, check);
729
730 break;
731
732 case GAIM_PREF_INT:
733 if (account == NULL ||
734 strcmp(gaim_account_get_protocol_id(account),
735 dialog->protocol_id))
736 {
737 int_value = gaim_account_option_get_default_int(option);
738 }
739 else
740 {
741 int_value = gaim_account_get_int(account,
742 gaim_account_option_get_setting(option),
743 gaim_account_option_get_default_int(option));
744 }
745
746 g_snprintf(buf, sizeof(buf), "%d", int_value);
747
748 entry = gtk_entry_new();
749 gtk_entry_set_text(GTK_ENTRY(entry), buf);
750
751 title = g_strdup_printf("%s:",
752 gaim_account_option_get_text(option));
753
754 add_pref_box(dialog, vbox, title, entry);
755
756 g_free(title);
757
758 dialog->protocol_opt_entries =
759 g_list_append(dialog->protocol_opt_entries, entry);
760
761 break;
762
763 case GAIM_PREF_STRING:
764 if (account == NULL ||
765 strcmp(gaim_account_get_protocol_id(account),
766 dialog->protocol_id))
767 {
768 str_value = gaim_account_option_get_default_string(option);
769 }
770 else
771 {
772 str_value = gaim_account_get_string(account,
773 gaim_account_option_get_setting(option),
774 gaim_account_option_get_default_string(option));
775 }
776
777 entry = gtk_entry_new();
778 if (gaim_account_option_get_masked(option))
779 {
780 gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
781 if (gtk_entry_get_invisible_char(GTK_ENTRY(entry)) == '*')
782 gtk_entry_set_invisible_char(GTK_ENTRY(entry), GAIM_INVISIBLE_CHAR);
783 }
784
785 if (str_value != NULL)
786 gtk_entry_set_text(GTK_ENTRY(entry), str_value);
787
788 title = g_strdup_printf("%s:",
789 gaim_account_option_get_text(option));
790
791 add_pref_box(dialog, vbox, title, entry);
792
793 g_free(title);
794
795 dialog->protocol_opt_entries =
796 g_list_append(dialog->protocol_opt_entries, entry);
797
798 break;
799
800 case GAIM_PREF_STRING_LIST:
801 i = 0;
802 idx = 0;
803
804 if (account == NULL ||
805 strcmp(gaim_account_get_protocol_id(account),
806 dialog->protocol_id))
807 {
808 str_value = gaim_account_option_get_default_list_value(option);
809 }
810 else
811 {
812 str_value = gaim_account_get_string(account,
813 gaim_account_option_get_setting(option),
814 gaim_account_option_get_default_list_value(option));
815 }
816
817 list = gaim_account_option_get_list(option);
818 model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
819 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
820
821 /* Loop through list of GaimKeyValuePair items */
822 for (node = list; node != NULL; node = node->next) {
823 if (node->data != NULL) {
824 kvp = (GaimKeyValuePair *) node->data;
825 if ((kvp->value != NULL) && (str_value != NULL) &&
826 !g_utf8_collate(kvp->value, str_value))
827 idx = i;
828
829 gtk_list_store_append(model, &iter);
830 gtk_list_store_set(model, &iter,
831 0, kvp->key,
832 1, kvp->value,
833 -1);
834 }
835
836 i++;
837 }
838
839 /* Set default */
840 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), idx);
841
842 /* Define renderer */
843 renderer = gtk_cell_renderer_text_new();
844 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer,
845 TRUE);
846 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo),
847 renderer, "text", 0, NULL);
848
849 title = g_strdup_printf("%s:",
850 gaim_account_option_get_text(option));
851
852 add_pref_box(dialog, vbox, title, combo);
853
854 g_free(title);
855
856 dialog->protocol_opt_entries =
857 g_list_append(dialog->protocol_opt_entries, combo);
858
859 break;
860
861
862 default:
863 break;
864 }
865 }
866 }
867
868 static GtkWidget *
869 make_proxy_dropdown(void)
870 {
871 GtkWidget *dropdown;
872 GtkListStore *model;
873 GtkTreeIter iter;
874 GtkCellRenderer *renderer;
875
876 model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
877 dropdown = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
878
879 gtk_list_store_append(model, &iter);
880 gtk_list_store_set(model, &iter,
881 0, gaim_running_gnome() ? _("Use GNOME Proxy Settings")
882 :_("Use Global Proxy Settings"),
883 1, GAIM_PROXY_USE_GLOBAL,
884 -1);
885
886 gtk_list_store_append(model, &iter);
887 gtk_list_store_set(model, &iter,
888 0, _("No Proxy"),
889 1, GAIM_PROXY_NONE,
890 -1);
891
892 gtk_list_store_append(model, &iter);
893 gtk_list_store_set(model, &iter,
894 0, _("HTTP"),
895 1, GAIM_PROXY_HTTP,
896 -1);
897
898 gtk_list_store_append(model, &iter);
899 gtk_list_store_set(model, &iter,
900 0, _("SOCKS 4"),
901 1, GAIM_PROXY_SOCKS4,
902 -1);
903
904 gtk_list_store_append(model, &iter);
905 gtk_list_store_set(model, &iter,
906 0, _("SOCKS 5"),
907 1, GAIM_PROXY_SOCKS5,
908 -1);
909
910 gtk_list_store_append(model, &iter);
911 gtk_list_store_set(model, &iter,
912 0, _("Use Environmental Settings"),
913 1, GAIM_PROXY_USE_ENVVAR,
914 -1);
915
916 renderer = gtk_cell_renderer_text_new();
917 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropdown), renderer, TRUE);
918 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropdown), renderer,
919 "text", 0, NULL);
920
921 return dropdown;
922 }
923
924 static void
925 proxy_type_changed_cb(GtkWidget *menu, AccountPrefsDialog *dialog)
926 {
927 dialog->new_proxy_type =
928 gtk_combo_box_get_active(GTK_COMBO_BOX(menu)) - 1;
929
930 if (dialog->new_proxy_type == GAIM_PROXY_USE_GLOBAL ||
931 dialog->new_proxy_type == GAIM_PROXY_NONE ||
932 dialog->new_proxy_type == GAIM_PROXY_USE_ENVVAR) {
933
934 gtk_widget_hide_all(dialog->proxy_vbox);
935 }
936 else
937 gtk_widget_show_all(dialog->proxy_vbox);
938 }
939
940 static void
941 port_popup_cb(GtkWidget *w, GtkMenu *menu, gpointer data)
942 {
943 GtkWidget *item1;
944 GtkWidget *item2;
945
946 /* This is an easter egg.
947 It means one of two things, both intended as humourus:
948 A) your network is really slow and you have nothing better to do than
949 look at butterflies.
950 B)You are looking really closely at something that shouldn't matter. */
951 item1 = gtk_menu_item_new_with_label(_("If you look real closely"));
952
953 /* This is an easter egg. See the comment on the previous line in the source. */
954 item2 = gtk_menu_item_new_with_label(_("you can see the butterflies mating"));
955
956 gtk_widget_show(item1);
957 gtk_widget_show(item2);
958
959 /* Prepend these in reverse order so they appear correctly. */
960 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item2);
961 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item1);
962 }
963
964 static void
965 add_proxy_options(AccountPrefsDialog *dialog, GtkWidget *parent)
966 {
967 GaimProxyInfo *proxy_info;
968 GtkWidget *frame;
969 GtkWidget *vbox;
970 GtkWidget *vbox2;
971
972 if (dialog->proxy_frame != NULL)
973 gtk_widget_destroy(dialog->proxy_frame);
974
975 frame = gaim_gtk_make_frame(parent, _("Proxy Options"));
976 dialog->proxy_frame = gtk_widget_get_parent(gtk_widget_get_parent(frame));
977
978 gtk_box_reorder_child(GTK_BOX(parent), dialog->proxy_frame, 1);
979 gtk_widget_show(dialog->proxy_frame);
980
981 /* Main vbox */
982 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE);
983 gtk_container_add(GTK_CONTAINER(frame), vbox);
984 gtk_widget_show(vbox);
985
986 /* Proxy Type drop-down. */
987 dialog->proxy_dropdown = make_proxy_dropdown();
988
989 add_pref_box(dialog, vbox, _("Proxy _type:"), dialog->proxy_dropdown);
990
991 /* Setup the second vbox, which may be hidden at times. */
992 dialog->proxy_vbox = vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE);
993 gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, GAIM_HIG_BORDER);
994 gtk_widget_show(vbox2);
995
996 /* Host */
997 dialog->proxy_host_entry = gtk_entry_new();
998 add_pref_box(dialog, vbox2, _("_Host:"), dialog->proxy_host_entry);
999
1000 /* Port */
1001 dialog->proxy_port_entry = gtk_entry_new();
1002 add_pref_box(dialog, vbox2, _("_Port:"), dialog->proxy_port_entry);
1003
1004 g_signal_connect(G_OBJECT(dialog->proxy_port_entry), "populate-popup",
1005 G_CALLBACK(port_popup_cb), NULL);
1006
1007 /* User */
1008 dialog->proxy_user_entry = gtk_entry_new();
1009
1010 add_pref_box(dialog, vbox2, _("_Username:"), dialog->proxy_user_entry);
1011
1012 /* Password */
1013 dialog->proxy_pass_entry = gtk_entry_new();
1014 gtk_entry_set_visibility(GTK_ENTRY(dialog->proxy_pass_entry), FALSE);
1015 if (gtk_entry_get_invisible_char(GTK_ENTRY(dialog->proxy_pass_entry)) == '*')
1016 gtk_entry_set_invisible_char(GTK_ENTRY(dialog->proxy_pass_entry), GAIM_INVISIBLE_CHAR);
1017 add_pref_box(dialog, vbox2, _("Pa_ssword:"), dialog->proxy_pass_entry);
1018
1019 if (dialog->account != NULL &&
1020 (proxy_info = gaim_account_get_proxy_info(dialog->account)) != NULL) {
1021
1022 GaimProxyType type = gaim_proxy_info_get_type(proxy_info);
1023 const char *value;
1024 int int_val;
1025
1026 /* Hah! */
1027 /* I dunno what you're laughing about, fuzz ball. */
1028 dialog->new_proxy_type = type;
1029 gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->proxy_dropdown),
1030 type + 1);
1031
1032 if (type == GAIM_PROXY_USE_GLOBAL || type == GAIM_PROXY_NONE ||
1033 type == GAIM_PROXY_USE_ENVVAR)
1034 gtk_widget_hide_all(vbox2);
1035
1036
1037 if ((value = gaim_proxy_info_get_host(proxy_info)) != NULL)
1038 gtk_entry_set_text(GTK_ENTRY(dialog->proxy_host_entry), value);
1039
1040 if ((int_val = gaim_proxy_info_get_port(proxy_info)) != 0) {
1041 char buf[11];
1042
1043 g_snprintf(buf, sizeof(buf), "%d", int_val);
1044
1045 gtk_entry_set_text(GTK_ENTRY(dialog->proxy_port_entry), buf);
1046 }
1047
1048 if ((value = gaim_proxy_info_get_username(proxy_info)) != NULL)
1049 gtk_entry_set_text(GTK_ENTRY(dialog->proxy_user_entry), value);
1050
1051 if ((value = gaim_proxy_info_get_password(proxy_info)) != NULL)
1052 gtk_entry_set_text(GTK_ENTRY(dialog->proxy_pass_entry), value);
1053 }
1054 else {
1055 dialog->new_proxy_type = GAIM_PROXY_USE_GLOBAL;
1056 gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->proxy_dropdown),
1057 dialog->new_proxy_type + 1);
1058 gtk_widget_hide_all(vbox2);
1059 }
1060
1061 /* Connect signals. */
1062 g_signal_connect(G_OBJECT(dialog->proxy_dropdown), "changed",
1063 G_CALLBACK(proxy_type_changed_cb), dialog);
1064 }
1065
1066 static void
1067 account_win_destroy_cb(GtkWidget *w, GdkEvent *event,
1068 AccountPrefsDialog *dialog)
1069 {
1070 g_hash_table_remove(account_pref_wins, dialog->account);
1071
1072 gtk_widget_destroy(dialog->window);
1073
1074 g_list_free(dialog->user_split_entries);
1075 g_list_free(dialog->protocol_opt_entries);
1076 g_free(dialog->protocol_id);
1077
1078 if (dialog->cached_icon_path != NULL)
1079 {
1080 const char *icon = gaim_account_get_ui_string(dialog->account, GAIM_GTK_UI, "non-global-buddyicon-cached-path", NULL);
1081 if (dialog->cached_icon_path != NULL && (icon == NULL || strcmp(dialog->cached_icon_path, icon)))
1082 {
1083 /* The user set an icon, which would've been cached by convert_buddy_icon,
1084 * but didn't save the changes. Delete the cache file. */
1085 char *filename = g_build_filename(gaim_buddy_icons_get_cache_dir(), dialog->cached_icon_path, NULL);
1086 g_unlink(filename);
1087 g_free(filename);
1088 }
1089
1090 g_free(dialog->cached_icon_path);
1091 }
1092
1093 g_free(dialog->icon_path);
1094
1095 if (dialog->icon_filesel)
1096 gtk_widget_destroy(dialog->icon_filesel);
1097
1098 gaim_signals_disconnect_by_handle(dialog);
1099
1100 g_free(dialog);
1101 }
1102
1103 static void
1104 cancel_account_prefs_cb(GtkWidget *w, AccountPrefsDialog *dialog)
1105 {
1106 account_win_destroy_cb(NULL, NULL, dialog);
1107 }
1108
1109 static GaimAccount*
1110 ok_account_prefs_cb(GtkWidget *w, AccountPrefsDialog *dialog)
1111 {
1112 GaimProxyInfo *proxy_info = NULL;
1113 GList *l, *l2;
1114 const char *value;
1115 char *username;
1116 char *tmp;
1117 gboolean new = FALSE, icon_change = FALSE;
1118 GaimAccount *account;
1119 GaimPluginProtocolInfo *prpl_info;
1120
1121 if (dialog->account == NULL)
1122 {
1123 const char *screenname;
1124
1125 screenname = gtk_entry_get_text(GTK_ENTRY(dialog->screenname_entry));
1126 account = gaim_account_new(screenname, dialog->protocol_id);
1127 new = TRUE;
1128 }
1129 else
1130 {
1131 account = dialog->account;
1132
1133 /* Protocol */
1134 gaim_account_set_protocol_id(account, dialog->protocol_id);
1135 }
1136
1137 /* Alias */
1138 value = gtk_entry_get_text(GTK_ENTRY(dialog->alias_entry));
1139
1140 if (*value != '\0')
1141 gaim_account_set_alias(account, value);
1142 else
1143 gaim_account_set_alias(account, NULL);
1144
1145 /* Buddy Icon */
1146 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(dialog->plugin);
1147 if (prpl_info != NULL && prpl_info->icon_spec.format != NULL)
1148 {
1149 if (new || gaim_account_get_bool(account, "use-global-buddyicon", TRUE) ==
1150 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check)))
1151 {
1152 icon_change = TRUE;
1153 }
1154 gaim_account_set_bool(account, "use-global-buddyicon", !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check)));
1155 gaim_account_set_ui_string(account, GAIM_GTK_UI, "non-global-buddyicon-cached-path", dialog->cached_icon_path);
1156 gaim_account_set_ui_string(account, GAIM_GTK_UI, "non-global-buddyicon-path", dialog->icon_path);
1157 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check)))
1158 {
1159 gaim_account_set_buddy_icon_path(account, dialog->icon_path);
1160 gaim_account_set_buddy_icon(account, dialog->cached_icon_path);
1161 }
1162 else if (gaim_prefs_get_path("/gaim/gtk/accounts/buddyicon") && icon_change)
1163 {
1164 const char *filename = gaim_prefs_get_path("/gaim/gtk/accounts/buddyicon");
1165 char *icon = gaim_gtk_convert_buddy_icon(dialog->plugin, filename);
1166 gaim_account_set_buddy_icon_path(account, filename);
1167 gaim_account_set_buddy_icon(account, icon);
1168 g_free(icon);
1169 }
1170 }
1171
1172
1173 /* Remember Password */
1174 gaim_account_set_remember_password(account,
1175 gtk_toggle_button_get_active(
1176 GTK_TOGGLE_BUTTON(dialog->remember_pass_check)));
1177
1178 /* Check Mail */
1179 if (dialog->prpl_info && dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK)
1180 gaim_account_set_check_mail(account,
1181 gtk_toggle_button_get_active(
1182 GTK_TOGGLE_BUTTON(dialog->new_mail_check)));
1183
1184 /* Password */
1185 value = gtk_entry_get_text(GTK_ENTRY(dialog->password_entry));
1186
1187 /*
1188 * We set the password if this is a new account because new accounts
1189 * will be set to online, and if the user has entered a password into
1190 * the account editor (but has not checked the 'save' box), then we
1191 * don't want to prompt them.
1192 */
1193 if ((gaim_account_get_remember_password(account) || new) && (*value != '\0'))
1194 gaim_account_set_password(account, value);
1195 else
1196 gaim_account_set_password(account, NULL);
1197
1198 /* Build the username string. */
1199 username =
1200 g_strdup(gtk_entry_get_text(GTK_ENTRY(dialog->screenname_entry)));
1201
1202 if (dialog->prpl_info != NULL)
1203 {
1204 for (l = dialog->prpl_info->user_splits,
1205 l2 = dialog->user_split_entries;
1206 l != NULL && l2 != NULL;
1207 l = l->next, l2 = l2->next)
1208 {
1209 GaimAccountUserSplit *split = l->data;
1210 GtkEntry *entry = l2->data;
1211 char sep[2] = " ";
1212
1213 value = gtk_entry_get_text(entry);
1214
1215 *sep = gaim_account_user_split_get_separator(split);
1216
1217 tmp = g_strconcat(username, sep,
1218 (*value ? value :
1219 gaim_account_user_split_get_default_value(split)),
1220 NULL);
1221
1222 g_free(username);
1223 username = tmp;
1224 }
1225 }
1226
1227 gaim_account_set_username(account, username);
1228 g_free(username);
1229
1230 /* Add the protocol settings */
1231 if (dialog->prpl_info) {
1232 for (l = dialog->prpl_info->protocol_options,
1233 l2 = dialog->protocol_opt_entries;
1234 l != NULL && l2 != NULL;
1235 l = l->next, l2 = l2->next) {
1236
1237 GaimPrefType type;
1238 GaimAccountOption *option = l->data;
1239 GtkWidget *widget = l2->data;
1240 GtkTreeIter iter;
1241 const char *setting;
1242 char *value2;
1243 int int_value;
1244 gboolean bool_value;
1245
1246 type = gaim_account_option_get_type(option);
1247
1248 setting = gaim_account_option_get_setting(option);
1249
1250 switch (type) {
1251 case GAIM_PREF_STRING:
1252 value = gtk_entry_get_text(GTK_ENTRY(widget));
1253 gaim_account_set_string(account, setting, value);
1254 break;
1255
1256 case GAIM_PREF_INT:
1257 int_value = atoi(gtk_entry_get_text(GTK_ENTRY(widget)));
1258 gaim_account_set_int(account, setting, int_value);
1259 break;
1260
1261 case GAIM_PREF_BOOLEAN:
1262 bool_value =
1263 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1264 gaim_account_set_bool(account, setting, bool_value);
1265 break;
1266
1267 case GAIM_PREF_STRING_LIST:
1268 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter);
1269 gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(widget)), &iter, 1, &value2, -1);
1270 gaim_account_set_string(account, setting, value2);
1271 break;
1272
1273 default:
1274 break;
1275 }
1276 }
1277 }
1278
1279 /* Set the proxy stuff. */
1280 proxy_info = gaim_account_get_proxy_info(account);
1281
1282 /* Create the proxy info if it doesn't exist. */
1283 if (proxy_info == NULL) {
1284 proxy_info = gaim_proxy_info_new();
1285 gaim_account_set_proxy_info(account, proxy_info);
1286 }
1287
1288 /* Set the proxy info type. */
1289 gaim_proxy_info_set_type(proxy_info, dialog->new_proxy_type);
1290
1291 /* Host */
1292 value = gtk_entry_get_text(GTK_ENTRY(dialog->proxy_host_entry));
1293
1294 if (*value != '\0')
1295 gaim_proxy_info_set_host(proxy_info, value);
1296 else
1297 gaim_proxy_info_set_host(proxy_info, NULL);
1298
1299 /* Port */
1300 value = gtk_entry_get_text(GTK_ENTRY(dialog->proxy_port_entry));
1301
1302 if (*value != '\0')
1303 gaim_proxy_info_set_port(proxy_info, atoi(value));
1304 else
1305 gaim_proxy_info_set_port(proxy_info, 0);
1306
1307 /* Username */
1308 value = gtk_entry_get_text(GTK_ENTRY(dialog->proxy_user_entry));
1309
1310 if (*value != '\0')
1311 gaim_proxy_info_set_username(proxy_info, value);
1312 else
1313 gaim_proxy_info_set_username(proxy_info, NULL);
1314
1315 /* Password */
1316 value = gtk_entry_get_text(GTK_ENTRY(dialog->proxy_pass_entry));
1317
1318 if (*value != '\0')
1319 gaim_proxy_info_set_password(proxy_info, value);
1320 else
1321 gaim_proxy_info_set_password(proxy_info, NULL);
1322
1323 /* If there are no values set then proxy_info NULL */
1324 if ((gaim_proxy_info_get_type(proxy_info) == GAIM_PROXY_USE_GLOBAL) &&
1325 (gaim_proxy_info_get_host(proxy_info) == NULL) &&
1326 (gaim_proxy_info_get_port(proxy_info) == 0) &&
1327 (gaim_proxy_info_get_username(proxy_info) == NULL) &&
1328 (gaim_proxy_info_get_password(proxy_info) == NULL))
1329 {
1330 gaim_account_set_proxy_info(account, NULL);
1331 proxy_info = NULL;
1332 }
1333
1334
1335 /* We no longer need the data from the dialog window */
1336 account_win_destroy_cb(NULL, NULL, dialog);
1337
1338 /* If this is a new account, add it to our list */
1339 if (new)
1340 gaim_accounts_add(account);
1341 else
1342 gaim_signal_emit(gaim_gtk_account_get_handle(), "account-modified", account);
1343
1344 /* If this is a new account, then sign on! */
1345 if (new && !dialog->registering) {
1346 const GaimSavedStatus *saved_status;
1347
1348 saved_status = gaim_savedstatus_get_current();
1349 if (saved_status != NULL) {
1350 gaim_savedstatus_activate_for_account(saved_status, account);
1351 gaim_account_set_enabled(account, GAIM_GTK_UI, TRUE);
1352 }
1353 }
1354
1355 return account;
1356 }
1357
1358 static void
1359 register_account_prefs_cb(GtkWidget *w, AccountPrefsDialog *dialog)
1360 {
1361 GaimAccount *account;
1362
1363 dialog->registering = TRUE;
1364
1365 account = ok_account_prefs_cb(NULL, dialog);
1366
1367 gaim_account_register(account);
1368 }
1369
1370
1371 static const GtkTargetEntry dnd_targets[] = {
1372 {"text/plain", 0, 0},
1373 {"text/uri-list", 0, 1},
1374 {"STRING", 0, 2}
1375 };
1376
1377 void
1378 gaim_gtk_account_dialog_show(GaimGtkAccountDialogType type,
1379 GaimAccount *account)
1380 {
1381 AccountPrefsDialog *dialog;
1382 GtkWidget *win;
1383 GtkWidget *main_vbox;
1384 GtkWidget *vbox;
1385 GtkWidget *bbox;
1386 GtkWidget *dbox;
1387 GtkWidget *notebook;
1388 GtkWidget *button;
1389
1390 if (accounts_window != NULL && account != NULL &&
1391 (dialog = g_hash_table_lookup(account_pref_wins, account)) != NULL)
1392 {
1393 gtk_window_present(GTK_WINDOW(dialog->window));
1394 return;
1395 }
1396
1397 dialog = g_new0(AccountPrefsDialog, 1);
1398
1399 if (accounts_window != NULL && account != NULL)
1400 {
1401 g_hash_table_insert(account_pref_wins, account, dialog);
1402 }
1403
1404 dialog->account = account;
1405 dialog->type = type;
1406 dialog->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1407
1408 if (dialog->account == NULL) {
1409 /* Select the first prpl in the list*/
1410 GList *prpl_list = gaim_plugins_get_protocols();
1411 if (prpl_list != NULL)
1412 dialog->protocol_id = g_strdup(((GaimPlugin *) prpl_list->data)->info->id);
1413 }
1414 else
1415 {
1416 dialog->protocol_id =
1417 g_strdup(gaim_account_get_protocol_id(dialog->account));
1418 }
1419
1420 if ((dialog->plugin = gaim_find_prpl(dialog->protocol_id)) != NULL)
1421 dialog->prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(dialog->plugin);
1422
1423
1424 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1425 gtk_window_set_role(GTK_WINDOW(win), "account");
1426
1427 if (type == GAIM_GTK_ADD_ACCOUNT_DIALOG)
1428 gtk_window_set_title(GTK_WINDOW(win), _("Add Account"));
1429 else
1430 gtk_window_set_title(GTK_WINDOW(win), _("Modify Account"));
1431
1432 gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
1433
1434 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER);
1435
1436 g_signal_connect(G_OBJECT(win), "delete_event",
1437 G_CALLBACK(account_win_destroy_cb), dialog);
1438
1439 /* Setup the vbox */
1440 main_vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER);
1441 gtk_container_add(GTK_CONTAINER(win), main_vbox);
1442 gtk_widget_show(main_vbox);
1443
1444 notebook = gtk_notebook_new();
1445 gtk_box_pack_start(GTK_BOX(main_vbox), notebook, FALSE, FALSE, 0);
1446 gtk_widget_show(GTK_WIDGET(notebook));
1447
1448 /* Setup the inner vbox */
1449 dialog->top_vbox = vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER);
1450 gtk_container_set_border_width(GTK_CONTAINER(vbox), GAIM_HIG_BORDER);
1451 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox,
1452 gtk_label_new_with_mnemonic(_("_Basic")));
1453 gtk_widget_show(vbox);
1454
1455 /* Setup the top frames. */
1456 add_login_options(dialog, vbox);
1457 add_user_options(dialog, vbox);
1458
1459 /* Setup the page with 'Advanced'. */
1460 dialog->bottom_vbox = dbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER);
1461 gtk_container_set_border_width(GTK_CONTAINER(dbox), GAIM_HIG_BORDER);
1462 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dbox,
1463 gtk_label_new_with_mnemonic(_("_Advanced")));
1464 gtk_widget_show(dbox);
1465
1466 /** Setup the bottom frames. */
1467 add_protocol_options(dialog, dbox);
1468 add_proxy_options(dialog, dbox);
1469
1470 /* Setup the button box */
1471 bbox = gtk_hbutton_box_new();
1472 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE);
1473 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1474 gtk_box_pack_end(GTK_BOX(main_vbox), bbox, FALSE, TRUE, 0);
1475 gtk_widget_show(bbox);
1476
1477 /* Register button */
1478 button = gtk_button_new_with_label(_("Register"));
1479 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1480 gtk_widget_show(button);
1481
1482 g_signal_connect(G_OBJECT(button), "clicked",
1483 G_CALLBACK(register_account_prefs_cb), dialog);
1484
1485 dialog->register_button = button;
1486
1487 if (dialog->account == NULL)
1488 gtk_widget_set_sensitive(button, FALSE);
1489
1490 if (!dialog->prpl_info || !dialog->prpl_info->register_user)
1491 gtk_widget_hide(button);
1492
1493 /* Cancel button */
1494 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1495 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1496 gtk_widget_show(button);
1497
1498 g_signal_connect(G_OBJECT(button), "clicked",
1499 G_CALLBACK(cancel_account_prefs_cb), dialog);
1500
1501 /* Save button */
1502 button = gtk_button_new_from_stock(GTK_STOCK_SAVE);
1503 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1504
1505 if (dialog->account == NULL)
1506 gtk_widget_set_sensitive(button, FALSE);
1507
1508 gtk_widget_show(button);
1509
1510 dialog->ok_button = button;
1511
1512 /* Set up DND */
1513 gtk_drag_dest_set(dialog->window,
1514 GTK_DEST_DEFAULT_MOTION |
1515 GTK_DEST_DEFAULT_DROP,
1516 dnd_targets,
1517 sizeof(dnd_targets) / sizeof(GtkTargetEntry),
1518 GDK_ACTION_COPY);
1519
1520 g_signal_connect(G_OBJECT(dialog->window), "drag_data_received",
1521 G_CALLBACK(account_dnd_recv), dialog);
1522
1523 g_signal_connect(G_OBJECT(button), "clicked",
1524 G_CALLBACK(ok_account_prefs_cb), dialog);
1525
1526 /* Show the window. */
1527 gtk_widget_show(win);
1528 }
1529
1530 /**************************************************************************
1531 * Accounts Dialog
1532 **************************************************************************/
1533 static void
1534 signed_on_off_cb(GaimConnection *gc, gpointer user_data)
1535 {
1536 GaimAccount *account;
1537 GaimGtkPulseData *pulse_data;
1538 GtkTreeModel *model;
1539 GtkTreeIter iter;
1540 GdkPixbuf *pixbuf;
1541 size_t index;
1542
1543 /* Don't need to do anything if the accounts window is not visible */
1544 if (accounts_window == NULL)
1545 return;
1546
1547 account = gaim_connection_get_account(gc);
1548 model = GTK_TREE_MODEL(accounts_window->model);
1549 index = g_list_index(gaim_accounts_get_all(), account);
1550
1551 if (gtk_tree_model_iter_nth_child(model, &iter, NULL, index))
1552 {
1553 gtk_tree_model_get(GTK_TREE_MODEL(accounts_window->model), &iter,
1554 COLUMN_PULSE_DATA, &pulse_data, -1);
1555
1556 if (pulse_data != NULL)
1557 {
1558 if (pulse_data->timeout > 0)
1559 g_source_remove(pulse_data->timeout);
1560
1561 g_object_unref(G_OBJECT(pulse_data->online_pixbuf));
1562
1563 g_free(pulse_data);
1564 }
1565
1566 pixbuf = gaim_gtk_create_prpl_icon(account, 0.5);
1567 if ((pixbuf != NULL) && gaim_account_is_disconnected(account))
1568 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
1569
1570 gtk_list_store_set(accounts_window->model, &iter,
1571 COLUMN_ICON, pixbuf,
1572 COLUMN_PULSE_DATA, NULL,
1573 -1);
1574
1575
1576 if (pixbuf != NULL)
1577 g_object_unref(G_OBJECT(pixbuf));
1578 }
1579 }
1580
1581 /*
1582 * Get the GtkTreeIter of the specified account in the
1583 * GtkListStore
1584 */
1585 static gboolean
1586 accounts_window_find_account_in_treemodel(GtkTreeIter *iter, GaimAccount *account)
1587 {
1588 GtkTreeModel *model;
1589 GaimAccount *cur;
1590
1591 g_return_val_if_fail(account != NULL, FALSE);
1592 g_return_val_if_fail(accounts_window != NULL, FALSE);
1593
1594 model = GTK_TREE_MODEL(accounts_window->model);
1595
1596 if (!gtk_tree_model_get_iter_first(model, iter))
1597 return FALSE;
1598
1599 gtk_tree_model_get(model, iter, COLUMN_DATA, &cur, -1);
1600 if (cur == account)
1601 return TRUE;
1602
1603 while (gtk_tree_model_iter_next(model, iter))
1604 {
1605 gtk_tree_model_get(model, iter, COLUMN_DATA, &cur, -1);
1606 if (cur == account)
1607 return TRUE;
1608 }
1609
1610 return FALSE;
1611 }
1612
1613 static void
1614 account_removed_cb(GaimAccount *account, gpointer user_data)
1615 {
1616 AccountPrefsDialog *dialog;
1617 GtkTreeIter iter;
1618
1619 /* If the account was being modified, close the edit window */
1620 if ((dialog = g_hash_table_lookup(account_pref_wins, account)) != NULL)
1621 account_win_destroy_cb(NULL, NULL, dialog);
1622
1623 if (accounts_window == NULL)
1624 return;
1625
1626 /* Remove the account from the GtkListStore */
1627 if (accounts_window_find_account_in_treemodel(&iter, account))
1628 gtk_list_store_remove(accounts_window->model, &iter);
1629
1630 if (gaim_accounts_get_all() == NULL)
1631 gtk_notebook_set_current_page(GTK_NOTEBOOK(accounts_window->notebook), 0);
1632 }
1633
1634 static void
1635 account_abled_cb(GaimAccount *account, gpointer user_data)
1636 {
1637 GtkTreeIter iter;
1638
1639 if (accounts_window == NULL)
1640 return;
1641
1642 /* update the account in the GtkListStore */
1643 if (accounts_window_find_account_in_treemodel(&iter, account))
1644 gtk_list_store_set(accounts_window->model, &iter,
1645 COLUMN_ENABLED, GPOINTER_TO_INT(user_data),
1646 -1);
1647 }
1648
1649 static void
1650 drag_data_get_cb(GtkWidget *widget, GdkDragContext *ctx,
1651 GtkSelectionData *data, guint info, guint time,
1652 AccountsWindow *dialog)
1653 {
1654 if (data->target == gdk_atom_intern("GAIM_ACCOUNT", FALSE)) {
1655 GtkTreeRowReference *ref;
1656 GtkTreePath *source_row;
1657 GtkTreeIter iter;
1658 GaimAccount *account = NULL;
1659 GValue val;
1660
1661 ref = g_object_get_data(G_OBJECT(ctx), "gtk-tree-view-source-row");
1662 source_row = gtk_tree_row_reference_get_path(ref);
1663
1664 if (source_row == NULL)
1665 return;
1666
1667 gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter,
1668 source_row);
1669 val.g_type = 0;
1670 gtk_tree_model_get_value(GTK_TREE_MODEL(dialog->model), &iter,
1671 COLUMN_DATA, &val);
1672
1673 dialog->drag_iter = iter;
1674
1675 account = g_value_get_pointer(&val);
1676
1677 gtk_selection_data_set(data, gdk_atom_intern("GAIM_ACCOUNT", FALSE),
1678 8, (void *)&account, sizeof(account));
1679
1680 gtk_tree_path_free(source_row);
1681 }
1682 }
1683
1684 static void
1685 move_account_after(GtkListStore *store, GtkTreeIter *iter,
1686 GtkTreeIter *position)
1687 {
1688 GtkTreeIter new_iter;
1689 GaimAccount *account;
1690
1691 gtk_tree_model_get(GTK_TREE_MODEL(store), iter,
1692 COLUMN_DATA, &account,
1693 -1);
1694
1695 gtk_list_store_insert_after(store, &new_iter, position);
1696
1697 set_account(store, &new_iter, account);
1698
1699 gtk_list_store_remove(store, iter);
1700 }
1701
1702 static void
1703 move_account_before(GtkListStore *store, GtkTreeIter *iter,
1704 GtkTreeIter *position)
1705 {
1706 GtkTreeIter new_iter;
1707 GaimAccount *account;
1708
1709 gtk_tree_model_get(GTK_TREE_MODEL(store), iter,
1710 COLUMN_DATA, &account,
1711 -1);
1712
1713 gtk_list_store_insert_before(store, &new_iter, position);
1714
1715 set_account(store, &new_iter, account);
1716
1717 gtk_list_store_remove(store, iter);
1718 }
1719
1720 static void
1721 drag_data_received_cb(GtkWidget *widget, GdkDragContext *ctx,
1722 guint x, guint y, GtkSelectionData *sd,
1723 guint info, guint t, AccountsWindow *dialog)
1724 {
1725 if (sd->target == gdk_atom_intern("GAIM_ACCOUNT", FALSE) && sd->data) {
1726 gint dest_index;
1727 GaimAccount *a = NULL;
1728 GtkTreePath *path = NULL;
1729 GtkTreeViewDropPosition position;
1730
1731 memcpy(&a, sd->data, sizeof(a));
1732
1733 if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y,
1734 &path, &position)) {
1735
1736 GtkTreeIter iter;
1737 GaimAccount *account;
1738 GValue val;
1739
1740 gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, path);
1741 val.g_type = 0;
1742 gtk_tree_model_get_value(GTK_TREE_MODEL(dialog->model), &iter,
1743 COLUMN_DATA, &val);
1744
1745 account = g_value_get_pointer(&val);
1746
1747 switch (position) {
1748 case GTK_TREE_VIEW_DROP_AFTER:
1749 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
1750 move_account_after(dialog->model, &dialog->drag_iter,
1751 &iter);
1752 dest_index = g_list_index(gaim_accounts_get_all(),
1753 account) + 1;
1754 break;
1755
1756 case GTK_TREE_VIEW_DROP_BEFORE:
1757 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
1758 dest_index = g_list_index(gaim_accounts_get_all(),
1759 account);
1760
1761 move_account_before(dialog->model, &dialog->drag_iter,
1762 &iter);
1763 break;
1764
1765 default:
1766 return;
1767 }
1768
1769 gaim_accounts_reorder(a, dest_index);
1770 }
1771 }
1772 }
1773
1774 static gint
1775 accedit_win_destroy_cb(GtkWidget *w, GdkEvent *event, AccountsWindow *dialog)
1776 {
1777 gaim_gtk_accounts_window_hide();
1778
1779 return 0;
1780 }
1781
1782 static gboolean
1783 configure_cb(GtkWidget *w, GdkEventConfigure *event, AccountsWindow *dialog)
1784 {
1785 if (GTK_WIDGET_VISIBLE(w)) {
1786 int old_width = gaim_prefs_get_int("/gaim/gtk/accounts/dialog/width");
1787 int col_width;
1788 int difference;
1789
1790 gaim_prefs_set_int("/gaim/gtk/accounts/dialog/width", event->width);
1791 gaim_prefs_set_int("/gaim/gtk/accounts/dialog/height", event->height);
1792
1793 col_width = gtk_tree_view_column_get_width(dialog->screenname_col);
1794
1795 if (col_width == 0)
1796 return FALSE;
1797
1798 difference = (MAX(old_width, event->width) -
1799 MIN(old_width, event->width));
1800
1801 if (difference == 0)
1802 return FALSE;
1803
1804 if (old_width < event->width)
1805 gtk_tree_view_column_set_min_width(dialog->screenname_col,
1806 col_width + difference);
1807 else
1808 gtk_tree_view_column_set_max_width(dialog->screenname_col,
1809 col_width - difference);
1810 }
1811
1812 return FALSE;
1813 }
1814
1815 static void
1816 add_account_cb(GtkWidget *w, AccountsWindow *dialog)
1817 {
1818 gaim_gtk_account_dialog_show(GAIM_GTK_ADD_ACCOUNT_DIALOG, NULL);
1819 }
1820
1821 static void
1822 modify_account_sel(GtkTreeModel *model, GtkTreePath *path,
1823 GtkTreeIter *iter, gpointer data)
1824 {
1825 GaimAccount *account;
1826
1827 gtk_tree_model_get(model, iter, COLUMN_DATA, &account, -1);
1828
1829 if (account != NULL)
1830 gaim_gtk_account_dialog_show(GAIM_GTK_MODIFY_ACCOUNT_DIALOG, account);
1831 }
1832
1833 static void
1834 modify_account_cb(GtkWidget *w, AccountsWindow *dialog)
1835 {
1836 GtkTreeSelection *selection;
1837
1838 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
1839
1840 gtk_tree_selection_selected_foreach(selection, modify_account_sel, dialog);
1841 }
1842
1843 static void
1844 delete_account_cb(GaimAccount *account)
1845 {
1846 gaim_accounts_delete(account);
1847 }
1848
1849 static void
1850 ask_delete_account_sel(GtkTreeModel *model, GtkTreePath *path,
1851 GtkTreeIter *iter, gpointer data)
1852 {
1853 GaimAccount *account;
1854
1855 gtk_tree_model_get(model, iter, COLUMN_DATA, &account, -1);
1856
1857 if (account != NULL) {
1858 char *buf;
1859
1860 buf = g_strdup_printf(_("Are you sure you want to delete %s?"),
1861 gaim_account_get_username(account));
1862
1863 gaim_request_close_with_handle(account);
1864 gaim_request_action(account, NULL, buf, NULL, 0, account, 2,
1865 _("Delete"), delete_account_cb,
1866 _("Cancel"), NULL);
1867 g_free(buf);
1868 }
1869 }
1870
1871 static void
1872 ask_delete_account_cb(GtkWidget *w, AccountsWindow *dialog)
1873 {
1874 GtkTreeSelection *selection;
1875
1876 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
1877
1878 gtk_tree_selection_selected_foreach(selection, ask_delete_account_sel,
1879 dialog);
1880 }
1881
1882 static void
1883 close_accounts_cb(GtkWidget *w, AccountsWindow *dialog)
1884 {
1885 gtk_widget_destroy(dialog->window);
1886
1887 gaim_gtk_accounts_window_hide();
1888 }
1889
1890
1891 static void
1892 enabled_cb(GtkCellRendererToggle *renderer, gchar *path_str,
1893 gpointer data)
1894 {
1895 AccountsWindow *dialog = (AccountsWindow *)data;
1896 GaimAccount *account;
1897 GtkTreeModel *model = GTK_TREE_MODEL(dialog->model);
1898 GtkTreeIter iter;
1899 gboolean enabled;
1900 const GaimSavedStatus *saved_status;
1901
1902 gtk_tree_model_get_iter_from_string(model, &iter, path_str);
1903 gtk_tree_model_get(model, &iter,
1904 COLUMN_DATA, &account,
1905 COLUMN_ENABLED, &enabled,
1906 -1);
1907
1908 /*
1909 * If we just enabled the account, then set the statuses
1910 * to the current status.
1911 */
1912 if (!enabled)
1913 {
1914 saved_status = gaim_savedstatus_get_current();
1915 gaim_savedstatus_activate_for_account(saved_status, account);
1916 }
1917
1918 gaim_account_set_enabled(account, GAIM_GTK_UI, !enabled);
1919 }
1920
1921 static void
1922 add_columns(GtkWidget *treeview, AccountsWindow *dialog)
1923 {
1924 GtkCellRenderer *renderer;
1925 GtkTreeViewColumn *column;
1926
1927 /* Enabled */
1928 renderer = gtk_cell_renderer_toggle_new();
1929
1930 g_signal_connect(G_OBJECT(renderer), "toggled",
1931 G_CALLBACK(enabled_cb), dialog);
1932
1933 column = gtk_tree_view_column_new_with_attributes(_("Enabled"),
1934 renderer, "active", COLUMN_ENABLED, NULL);
1935
1936 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1);
1937 gtk_tree_view_column_set_resizable(column, TRUE);
1938
1939 /* Screen Name column */
1940 column = gtk_tree_view_column_new();
1941 gtk_tree_view_column_set_title(column, _("Screen Name"));
1942 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1);
1943 gtk_tree_view_column_set_resizable(column, TRUE);
1944
1945 /* Status Icon */
1946 renderer = gtk_cell_renderer_pixbuf_new();
1947 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1948 gtk_tree_view_column_add_attribute(column, renderer,
1949 "pixbuf", COLUMN_BUDDYICON);
1950
1951 /* Screen Name */
1952 renderer = gtk_cell_renderer_text_new();
1953 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1954 gtk_tree_view_column_add_attribute(column, renderer,
1955 "text", COLUMN_SCREENNAME);
1956 dialog->screenname_col = column;
1957
1958
1959 /* Protocol name */
1960 column = gtk_tree_view_column_new();
1961 gtk_tree_view_column_set_title(column, _("Protocol"));
1962 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1);
1963 gtk_tree_view_column_set_resizable(column, TRUE);
1964
1965 /* Icon */
1966 renderer = gtk_cell_renderer_pixbuf_new();
1967 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1968 gtk_tree_view_column_add_attribute(column, renderer,
1969 "pixbuf", COLUMN_ICON);
1970
1971 renderer = gtk_cell_renderer_text_new();
1972 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1973 gtk_tree_view_column_add_attribute(column, renderer,
1974 "text", COLUMN_PROTOCOL);
1975 }
1976
1977 static void
1978 set_account(GtkListStore *store, GtkTreeIter *iter, GaimAccount *account)
1979 {
1980 const char *path;
1981 GdkPixbuf *pixbuf;
1982 GdkPixbuf *statusicon_pixbuf;
1983 GdkPixbuf *statusicon_pixbuf_scaled;
1984
1985 pixbuf = gaim_gtk_create_prpl_icon(account, 0.5);
1986 if ((pixbuf != NULL) && gaim_account_is_disconnected(account))
1987 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
1988
1989 if (gaim_account_get_bool(account, "use-global-buddyicon", TRUE))
1990 path = gaim_prefs_get_path("/gaim/gtk/accounts/buddyicon");
1991 else
1992 path = gaim_account_get_ui_string(account, GAIM_GTK_UI, "non-global-buddyicon-path", NULL);
1993 if (path != NULL)
1994 statusicon_pixbuf = gdk_pixbuf_new_from_file(path, NULL);
1995 else
1996 statusicon_pixbuf = NULL;
1997
1998 if (statusicon_pixbuf) {
1999 statusicon_pixbuf_scaled = gdk_pixbuf_scale_simple(statusicon_pixbuf, 16, 16, GDK_INTERP_HYPER);
2000 } else {
2001 statusicon_pixbuf_scaled = NULL;
2002 }
2003
2004 gtk_list_store_set(store, iter,
2005 COLUMN_ICON, pixbuf,
2006 COLUMN_BUDDYICON, statusicon_pixbuf_scaled,
2007 COLUMN_SCREENNAME, gaim_account_get_username(account),
2008 COLUMN_ENABLED, gaim_account_get_enabled(account, GAIM_GTK_UI),
2009 COLUMN_PROTOCOL, gaim_account_get_protocol_name(account),
2010 COLUMN_DATA, account,
2011 -1);
2012
2013 if (pixbuf != NULL)
2014 g_object_unref(G_OBJECT(pixbuf));
2015 if (statusicon_pixbuf != NULL)
2016 g_object_unref(G_OBJECT(statusicon_pixbuf));
2017 if (statusicon_pixbuf_scaled != NULL)
2018 g_object_unref(G_OBJECT(statusicon_pixbuf_scaled));
2019 }
2020
2021 static void
2022 add_account_to_liststore(GaimAccount *account, gpointer user_data)
2023 {
2024 GtkTreeIter iter;
2025
2026 if (accounts_window == NULL)
2027 return;
2028
2029 gtk_list_store_append(accounts_window->model, &iter);
2030 gtk_notebook_set_current_page(GTK_NOTEBOOK(accounts_window->notebook),1);
2031
2032 set_account(accounts_window->model, &iter, account);
2033 }
2034
2035 static gboolean
2036 populate_accounts_list(AccountsWindow *dialog)
2037 {
2038 GList *l;
2039 gboolean ret = FALSE;
2040
2041 gtk_list_store_clear(dialog->model);
2042
2043 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) {
2044 ret = TRUE;
2045 add_account_to_liststore((GaimAccount *)l->data, NULL);
2046 }
2047
2048 return ret;
2049 }
2050
2051 #if !GTK_CHECK_VERSION(2,2,0)
2052 static void
2053 get_selected_helper(GtkTreeModel *model, GtkTreePath *path,
2054 GtkTreeIter *iter, gpointer user_data)
2055 {
2056 *((gboolean *)user_data) = TRUE;
2057 }
2058 #endif
2059
2060 static void
2061 account_selected_cb(GtkTreeSelection *sel, AccountsWindow *dialog)
2062 {
2063 gboolean selected = FALSE;
2064
2065 #if GTK_CHECK_VERSION(2,2,0)
2066 selected = (gtk_tree_selection_count_selected_rows(sel) > 0);
2067 #else
2068 gtk_tree_selection_selected_foreach(sel, get_selected_helper, &selected);
2069 #endif
2070
2071 gtk_widget_set_sensitive(dialog->modify_button, selected);
2072 gtk_widget_set_sensitive(dialog->delete_button, selected);
2073 }
2074
2075 static gboolean
2076 account_treeview_double_click_cb(GtkTreeView *treeview, GdkEventButton *event, gpointer user_data)
2077 {
2078 AccountsWindow *dialog;
2079 GtkTreePath *path;
2080 GtkTreeViewColumn *column;
2081 GtkTreeIter iter;
2082 GaimAccount *account;
2083 const gchar *title;
2084
2085 dialog = (AccountsWindow *)user_data;
2086
2087 /* Figure out which node was clicked */
2088 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(dialog->treeview), event->x, event->y, &path, &column, NULL, NULL))
2089 return FALSE;
2090 title = gtk_tree_view_column_get_title(column);
2091 /* The -1 is required because the first two columns of the list
2092 * store are displayed as only one column in the tree view. */
2093 column = gtk_tree_view_get_column(treeview, COLUMN_ENABLED-1);
2094 gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, path);
2095 gtk_tree_path_free(path);
2096 gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter, COLUMN_DATA, &account, -1);
2097
2098 if ((account != NULL) && (event->button == 1) &&
2099 (event->type == GDK_2BUTTON_PRESS) &&
2100 (strcmp(gtk_tree_view_column_get_title(column), title)))
2101 {
2102 gaim_gtk_account_dialog_show(GAIM_GTK_MODIFY_ACCOUNT_DIALOG, account);
2103 return TRUE;
2104 }
2105
2106 return FALSE;
2107 }
2108
2109 static GtkWidget *
2110 create_accounts_list(AccountsWindow *dialog)
2111 {
2112 GtkWidget *frame;
2113 GtkWidget *sw;
2114 GtkWidget *label;
2115 GtkWidget *treeview;
2116 GtkTreeSelection *sel;
2117 GtkTargetEntry gte[] = {{"GAIM_ACCOUNT", GTK_TARGET_SAME_APP, 0}};
2118 char *pretty;
2119
2120 frame = gtk_frame_new(NULL);
2121 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
2122
2123 accounts_window->notebook = gtk_notebook_new();
2124 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(accounts_window->notebook), FALSE);
2125 gtk_notebook_set_show_border(GTK_NOTEBOOK(accounts_window->notebook), FALSE);
2126 gtk_container_add(GTK_CONTAINER(frame), accounts_window->notebook);
2127
2128
2129 /* Create a helpful first-time-use label */
2130 label = gtk_label_new(NULL);
2131 /* Translators: Please maintain the use of -> or <- to represent the menu heirarchy */
2132 pretty = gaim_gtk_make_pretty_arrows(_(
2133 "<span size='larger' weight='bold'>Welcome to Gaim!</span>\n\n"
2134
2135 "You have no IM accounts configured. To start connecting with Gaim "
2136 "press the <b>Add</b> button below and configure your first "
2137 "account. If you want Gaim to connect to multiple IM accounts, "
2138 "press <b>Add</b> again to configure them all.\n\n"
2139
2140 "You can come back to this window to add, edit, or remove "
2141 "accounts from <b>Accounts->Add/Edit</b> in the Buddy "
2142 "List window"));
2143 gtk_label_set_markup(GTK_LABEL(label), pretty);
2144 g_free(pretty);
2145
2146 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
2147 gtk_widget_show(label);
2148
2149 gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
2150 gtk_notebook_append_page(GTK_NOTEBOOK(accounts_window->notebook), label, NULL);
2151
2152 /* Create the scrolled window. */
2153 sw = gtk_scrolled_window_new(0, 0);
2154 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
2155 GTK_POLICY_AUTOMATIC,
2156 GTK_POLICY_AUTOMATIC);
2157 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
2158 GTK_SHADOW_NONE);
2159 gtk_notebook_append_page(GTK_NOTEBOOK(accounts_window->notebook), sw, NULL);
2160 gtk_widget_show(sw);
2161
2162 /* Create the list model. */
2163 dialog->model = gtk_list_store_new(NUM_COLUMNS,
2164 GDK_TYPE_PIXBUF, /* COLUMN_ICON */
2165 GDK_TYPE_PIXBUF, /* COLUMN_BUDDYICON */
2166 G_TYPE_STRING, /* COLUMN_SCREENNAME */
2167 G_TYPE_BOOLEAN, /* COLUMN_ENABLED */
2168 G_TYPE_STRING, /* COLUMN_PROTOCOL */
2169 G_TYPE_POINTER, /* COLUMN_DATA */
2170 G_TYPE_POINTER /* COLUMN_PULSE_DATA */
2171 );
2172
2173 /* And now the actual treeview */
2174 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
2175 dialog->treeview = treeview;
2176 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
2177
2178 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
2179 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
2180 g_signal_connect(G_OBJECT(sel), "changed",
2181 G_CALLBACK(account_selected_cb), dialog);
2182
2183 /* Handle double-clicking */
2184 g_signal_connect(G_OBJECT(treeview), "button_press_event",
2185 G_CALLBACK(account_treeview_double_click_cb), dialog);
2186
2187 gtk_container_add(GTK_CONTAINER(sw), treeview);
2188
2189 add_columns(treeview, dialog);
2190
2191 if (populate_accounts_list(dialog))
2192 gtk_notebook_set_current_page(GTK_NOTEBOOK(accounts_window->notebook), 1);
2193 else
2194 gtk_notebook_set_current_page(GTK_NOTEBOOK(accounts_window->notebook), 0);
2195
2196 /* Setup DND. I wanna be an orc! */
2197 gtk_tree_view_enable_model_drag_source(
2198 GTK_TREE_VIEW(treeview), GDK_BUTTON1_MASK, gte,
2199 1, GDK_ACTION_COPY);
2200 gtk_tree_view_enable_model_drag_dest(
2201 GTK_TREE_VIEW(treeview), gte, 1,
2202 GDK_ACTION_COPY | GDK_ACTION_MOVE);
2203
2204 g_signal_connect(G_OBJECT(treeview), "drag-data-received",
2205 G_CALLBACK(drag_data_received_cb), dialog);
2206 g_signal_connect(G_OBJECT(treeview), "drag-data-get",
2207 G_CALLBACK(drag_data_get_cb), dialog);
2208
2209 gtk_widget_show_all(frame);
2210 return frame;
2211 }
2212
2213 static void
2214 account_modified_cb(GaimAccount *account, AccountsWindow *window)
2215 {
2216 GtkTreeIter iter;
2217
2218 if (!accounts_window_find_account_in_treemodel(&iter, account))
2219 return;
2220
2221 set_account(window->model, &iter, account);
2222 }
2223
2224 static void
2225 global_buddyicon_changed(const char *name, GaimPrefType type,
2226 gconstpointer value, gpointer window)
2227 {
2228 GList *list;
2229 for (list = gaim_accounts_get_all(); list; list = list->next) {
2230 account_modified_cb(list->data, window);
2231 }
2232 }
2233
2234 void
2235 gaim_gtk_accounts_window_show(void)
2236 {
2237 AccountsWindow *dialog;
2238 GtkWidget *win;
2239 GtkWidget *vbox;
2240 GtkWidget *bbox;
2241 GtkWidget *sw;
2242 GtkWidget *button;
2243 int width, height;
2244
2245
2246 if (accounts_window != NULL) {
2247 gtk_window_present(GTK_WINDOW(accounts_window->window));
2248 return;
2249 }
2250
2251 accounts_window = dialog = g_new0(AccountsWindow, 1);
2252
2253 width = gaim_prefs_get_int("/gaim/gtk/accounts/dialog/width");
2254 height = gaim_prefs_get_int("/gaim/gtk/accounts/dialog/height");
2255
2256 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2257 gtk_window_set_default_size(GTK_WINDOW(win), width, height);
2258 gtk_window_set_role(GTK_WINDOW(win), "accounts");
2259 gtk_window_set_title(GTK_WINDOW(win), _("Accounts"));
2260 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER);
2261
2262 g_signal_connect(G_OBJECT(win), "delete_event",
2263 G_CALLBACK(accedit_win_destroy_cb), accounts_window);
2264 g_signal_connect(G_OBJECT(win), "configure_event",
2265 G_CALLBACK(configure_cb), accounts_window);
2266
2267 /* Setup the vbox */
2268 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER);
2269 gtk_container_add(GTK_CONTAINER(win), vbox);
2270 gtk_widget_show(vbox);
2271
2272 /* Setup the scrolled window that will contain the list of accounts. */
2273 sw = create_accounts_list(dialog);
2274 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
2275 gtk_widget_show(sw);
2276
2277 /* Button box. */
2278 bbox = gtk_hbutton_box_new();
2279 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE);
2280 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
2281 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
2282 gtk_widget_show(bbox);
2283
2284 /* Add button */
2285 button = gtk_button_new_from_stock(GTK_STOCK_ADD);
2286 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
2287 gtk_widget_show(button);
2288
2289 g_signal_connect(G_OBJECT(button), "clicked",
2290 G_CALLBACK(add_account_cb), dialog);
2291
2292 /* Modify button */
2293 button = gtk_button_new_from_stock(GAIM_STOCK_MODIFY);
2294 dialog->modify_button = button;
2295 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
2296 gtk_widget_set_sensitive(button, FALSE);
2297 gtk_widget_show(button);
2298
2299 g_signal_connect(G_OBJECT(button), "clicked",
2300 G_CALLBACK(modify_account_cb), dialog);
2301
2302 /* Delete button */
2303 button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
2304 dialog->delete_button = button;
2305 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
2306 gtk_widget_set_sensitive(button, FALSE);
2307 gtk_widget_show(button);
2308
2309 g_signal_connect(G_OBJECT(button), "clicked",
2310 G_CALLBACK(ask_delete_account_cb), dialog);
2311
2312 /* Close button */
2313 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
2314 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
2315 gtk_widget_show(button);
2316
2317 g_signal_connect(G_OBJECT(button), "clicked",
2318 G_CALLBACK(close_accounts_cb), dialog);
2319
2320 gaim_signal_connect(gaim_gtk_account_get_handle(), "account-modified",
2321 accounts_window,
2322 GAIM_CALLBACK(account_modified_cb), accounts_window);
2323 gaim_prefs_connect_callback(accounts_window,
2324 "/gaim/gtk/accounts/buddyicon",
2325 global_buddyicon_changed, accounts_window);
2326
2327 gtk_widget_show(win);
2328 }
2329
2330 void
2331 gaim_gtk_accounts_window_hide(void)
2332 {
2333 if (accounts_window == NULL)
2334 return;
2335
2336 gaim_signals_disconnect_by_handle(accounts_window);
2337 gaim_prefs_disconnect_by_handle(accounts_window);
2338
2339 g_free(accounts_window);
2340 accounts_window = NULL;
2341
2342 /* See if we're the main window here. */
2343 if (GAIM_GTK_BLIST(gaim_get_blist())->window == NULL &&
2344 gaim_connections_get_all() == NULL) {
2345
2346 gaim_core_quit();
2347 }
2348 }
2349
2350 static void
2351 free_add_user_data(GaimGtkAccountAddUserData *data)
2352 {
2353 g_free(data->username);
2354 g_free(data->alias);
2355 g_free(data);
2356 }
2357
2358 static void
2359 add_user_cb(GaimGtkAccountAddUserData *data)
2360 {
2361 GaimConnection *gc = gaim_account_get_connection(data->account);
2362
2363 if (g_list_find(gaim_connections_get_all(), gc))
2364 {
2365 gaim_blist_request_add_buddy(data->account, data->username,
2366 NULL, data->alias);
2367 }
2368
2369 free_add_user_data(data);
2370 }
2371
2372 static char *
2373 make_info(GaimAccount *account, GaimConnection *gc, const char *remote_user,
2374 const char *id, const char *alias, const char *msg)
2375 {
2376 if (msg != NULL && *msg == '\0')
2377 msg = NULL;
2378
2379 return g_strdup_printf(_("%s%s%s%s has made %s his or her buddy%s%s"),
2380 remote_user,
2381 (alias != NULL ? " (" : ""),
2382 (alias != NULL ? alias : ""),
2383 (alias != NULL ? ")" : ""),
2384 (id != NULL
2385 ? id
2386 : (gaim_connection_get_display_name(gc) != NULL
2387 ? gaim_connection_get_display_name(gc)
2388 : gaim_account_get_username(account))),
2389 (msg != NULL ? ": " : "."),
2390 (msg != NULL ? msg : ""));
2391 }
2392
2393 static void
2394 gaim_gtk_accounts_notify_added(GaimAccount *account, const char *remote_user,
2395 const char *id, const char *alias,
2396 const char *msg)
2397 {
2398 char *buffer;
2399 GaimConnection *gc;
2400 GtkWidget *alert;
2401
2402 gc = gaim_account_get_connection(account);
2403
2404 buffer = make_info(account, gc, remote_user, id, alias, msg);
2405 alert = gaim_gtk_make_mini_dialog(gc, GAIM_STOCK_DIALOG_INFO, buffer,
2406 NULL, NULL, _("Close"), NULL, NULL);
2407 gaim_gtk_blist_add_alert(alert);
2408
2409 g_free(buffer);
2410 }
2411
2412 static void
2413 gaim_gtk_accounts_request_add(GaimAccount *account, const char *remote_user,
2414 const char *id, const char *alias,
2415 const char *msg)
2416 {
2417 char *buffer;
2418 GaimConnection *gc;
2419 GaimGtkAccountAddUserData *data;
2420 GtkWidget *alert;
2421
2422 gc = gaim_account_get_connection(account);
2423
2424 data = g_new0(GaimGtkAccountAddUserData, 1);
2425 data->account = account;
2426 data->username = g_strdup(remote_user);
2427 data->alias = g_strdup(alias);
2428
2429 buffer = make_info(account, gc, remote_user, id, alias, msg);
2430 alert = gaim_gtk_make_mini_dialog(gc, GAIM_STOCK_DIALOG_QUESTION,
2431 _("Add buddy to your list?"), buffer, data,
2432 _("Add"), G_CALLBACK(add_user_cb),
2433 _("Cancel"), G_CALLBACK(free_add_user_data), NULL);
2434 gaim_gtk_blist_add_alert(alert);
2435
2436 g_free(buffer);
2437 }
2438
2439 struct auth_and_add {
2440 GaimAccountRequestAuthorizationCb auth_cb;
2441 GaimAccountRequestAuthorizationCb deny_cb;
2442 void *data;
2443 char *username;
2444 char *alias;
2445 GaimAccount *account;
2446 };
2447
2448 static void
2449 authorize_and_add_cb(struct auth_and_add *aa)
2450 {
2451 aa->auth_cb(aa->data);
2452 gaim_blist_request_add_buddy(aa->account, aa->username,
2453 NULL, aa->alias);
2454
2455 g_free(aa->username);
2456 g_free(aa->alias);
2457 g_free(aa);
2458 }
2459
2460 static void
2461 deny_no_add_cb(struct auth_and_add *aa)
2462 {
2463 aa->deny_cb(aa->data);
2464
2465 g_free(aa->username);
2466 g_free(aa->alias);
2467 g_free(aa);
2468 }
2469
2470 static void
2471 gaim_gtk_accounts_request_authorization(GaimAccount *account, const char *remote_user,
2472 const char *id, const char *alias, const char *message, gboolean on_list,
2473 GCallback auth_cb, GCallback deny_cb, void *user_data)
2474 {
2475 char *buffer;
2476 GaimConnection *gc;
2477 GtkWidget *alert;
2478
2479 gc = gaim_account_get_connection(account);
2480 if (message != NULL && *message == '\0')
2481 message = NULL;
2482
2483 buffer = g_strdup_printf(_("%s%s%s%s wants to add %s to his or her buddy list%s%s"),
2484 remote_user,
2485 (alias != NULL ? " (" : ""),
2486 (alias != NULL ? alias : ""),
2487 (alias != NULL ? ")" : ""),
2488 (id != NULL
2489 ? id
2490 : (gaim_connection_get_display_name(gc) != NULL
2491 ? gaim_connection_get_display_name(gc)
2492 : gaim_account_get_username(account))),
2493 (message != NULL ? ": " : "."),
2494 (message != NULL ? message : ""));
2495
2496
2497 if (!on_list) {
2498 struct auth_and_add *aa = g_new0(struct auth_and_add, 1);
2499 aa->auth_cb = (GaimAccountRequestAuthorizationCb)auth_cb;
2500 aa->deny_cb = (GaimAccountRequestAuthorizationCb)deny_cb;
2501 aa->data = user_data;
2502 aa->username = g_strdup(remote_user);
2503 aa->alias = g_strdup(alias);
2504 aa->account = account;
2505 alert = gaim_gtk_make_mini_dialog(gc, GAIM_STOCK_DIALOG_QUESTION,
2506 _("Authorize buddy?"), buffer, aa,
2507 _("Authorize"), authorize_and_add_cb,
2508 _("Deny"), deny_no_add_cb,
2509 NULL);
2510 } else {
2511 alert = gaim_gtk_make_mini_dialog(gc, GAIM_STOCK_DIALOG_QUESTION,
2512 _("Authorize buddy?"), buffer, user_data,
2513 _("Authorize"), auth_cb,
2514 _("Deny"), deny_cb,
2515 NULL);
2516 }
2517 gaim_gtk_blist_add_alert(alert);
2518
2519 g_free(buffer);
2520 }
2521
2522 static GaimAccountUiOps ui_ops =
2523 {
2524 gaim_gtk_accounts_notify_added,
2525 NULL,
2526 gaim_gtk_accounts_request_add,
2527 gaim_gtk_accounts_request_authorization
2528 };
2529
2530 GaimAccountUiOps *
2531 gaim_gtk_accounts_get_ui_ops(void)
2532 {
2533 return &ui_ops;
2534 }
2535
2536 void *
2537 gaim_gtk_account_get_handle(void) {
2538 static int handle;
2539
2540 return &handle;
2541 }
2542
2543 void
2544 gaim_gtk_account_init(void)
2545 {
2546 gaim_prefs_add_none("/gaim/gtk/accounts");
2547 gaim_prefs_add_none("/gaim/gtk/accounts/dialog");
2548 gaim_prefs_add_int("/gaim/gtk/accounts/dialog/width", 520);
2549 gaim_prefs_add_int("/gaim/gtk/accounts/dialog/height", 321);
2550 gaim_prefs_add_path("/gaim/gtk/accounts/buddyicon", NULL);
2551
2552 gaim_signal_register(gaim_gtk_account_get_handle(), "account-modified",
2553 gaim_marshal_VOID__POINTER, NULL, 1,
2554 gaim_value_new(GAIM_TYPE_SUBTYPE,
2555 GAIM_SUBTYPE_ACCOUNT));
2556
2557 /* Setup some gaim signal handlers. */
2558 gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
2559 gaim_gtk_account_get_handle(),
2560 GAIM_CALLBACK(signed_on_off_cb), NULL);
2561 gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
2562 gaim_gtk_account_get_handle(),
2563 GAIM_CALLBACK(signed_on_off_cb), NULL);
2564 gaim_signal_connect(gaim_accounts_get_handle(), "account-added",
2565 gaim_gtk_account_get_handle(),
2566 GAIM_CALLBACK(add_account_to_liststore), NULL);
2567 gaim_signal_connect(gaim_accounts_get_handle(), "account-removed",
2568 gaim_gtk_account_get_handle(),
2569 GAIM_CALLBACK(account_removed_cb), NULL);
2570 gaim_signal_connect(gaim_accounts_get_handle(), "account-disabled",
2571 gaim_gtk_account_get_handle(),
2572 GAIM_CALLBACK(account_abled_cb), GINT_TO_POINTER(FALSE));
2573 gaim_signal_connect(gaim_accounts_get_handle(), "account-enabled",
2574 gaim_gtk_account_get_handle(),
2575 GAIM_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE));
2576
2577 account_pref_wins =
2578 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
2579 }
2580
2581 void
2582 gaim_gtk_account_uninit(void)
2583 {
2584 /*
2585 * TODO: Need to free all the dialogs in here. Could probably create
2586 * a callback function to use for the free-some-data-function
2587 * parameter of g_hash_table_new_full, above.
2588 */
2589 g_hash_table_destroy(account_pref_wins);
2590
2591 gaim_signals_disconnect_by_handle(gaim_gtk_account_get_handle());
2592 gaim_signals_unregister_by_instance(gaim_gtk_account_get_handle());
2593 }
2594