The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / pidgin-2.10.11 / pidgin / gtkaccount.c @ 2a128019

History | View | Annotate | Download (78.9 KB)

1
/**
2
 * @file gtkaccount.c GTK+ Account Editor UI
3
 * @ingroup pidgin
4
 */
5

    
6
/* pidgin
7
 *
8
 * Pidgin 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.
11
 *
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.
16
 *
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.
21
 *
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
25
 */
26

    
27
#include "internal.h"
28
#include "pidgin.h"
29

    
30
#include "account.h"
31
#include "accountopt.h"
32
#include "core.h"
33
#include "debug.h"
34
#include "notify.h"
35
#include "plugin.h"
36
#include "prefs.h"
37
#include "prpl.h"
38
#include "request.h"
39
#include "savedstatuses.h"
40
#include "signals.h"
41
#include "util.h"
42

    
43
#include "gtkaccount.h"
44
#include "gtkblist.h"
45
#include "gtkdialogs.h"
46
#include "gtkutils.h"
47
#include "gtkstatusbox.h"
48
#include "pidginstock.h"
49
#include "minidialog.h"
50

    
51
enum
52
{
53
        COLUMN_ICON,
54
        COLUMN_BUDDYICON,
55
        COLUMN_USERNAME,
56
        COLUMN_ENABLED,
57
        COLUMN_PROTOCOL,
58
        COLUMN_DATA,
59
        NUM_COLUMNS
60
};
61

    
62
typedef struct
63
{
64
        PurpleAccount *account;
65
        char *username;
66
        char *alias;
67

    
68
} PidginAccountAddUserData;
69

    
70
typedef struct
71
{
72
        GtkWidget *window;
73
        GtkWidget *treeview;
74

    
75
        GtkWidget *modify_button;
76
        GtkWidget *delete_button;
77
        GtkWidget *notebook;
78

    
79
        GtkListStore *model;
80
        GtkTreeIter drag_iter;
81

    
82
        GtkTreeViewColumn *username_col;
83

    
84
} AccountsWindow;
85

    
86
typedef struct
87
{
88
        GtkWidget *widget;
89
        gchar *setting;
90
        PurplePrefType type;
91
} ProtocolOptEntry;
92

    
93
typedef struct
94
{
95
        PidginAccountDialogType type;
96

    
97
        PurpleAccount *account;
98
        char *protocol_id;
99
        PurplePlugin *plugin;
100
        PurplePluginProtocolInfo *prpl_info;
101

    
102
        PurpleProxyType new_proxy_type;
103

    
104
        GList *user_split_entries;
105
        GList *protocol_opt_entries;
106

    
107
        GtkSizeGroup *sg;
108
        GtkWidget *window;
109

    
110
        GtkWidget *notebook;
111
        GtkWidget *top_vbox;
112
        GtkWidget *ok_button;
113
        GtkWidget *register_button;
114

    
115
        /* Login Options */
116
        GtkWidget *login_frame;
117
        GtkWidget *protocol_menu;
118
        GtkWidget *password_box;
119
        GtkWidget *username_entry;
120
        GtkWidget *password_entry;
121
        GtkWidget *alias_entry;
122
        GtkWidget *remember_pass_check;
123

    
124
        /* User Options */
125
        GtkWidget *user_frame;
126
        GtkWidget *new_mail_check;
127
        GtkWidget *icon_hbox;
128
        GtkWidget *icon_check;
129
        GtkWidget *icon_entry;
130
        GtkWidget *icon_filesel;
131
        GtkWidget *icon_preview;
132
        GtkWidget *icon_text;
133
        PurpleStoredImage *icon_img;
134

    
135
        /* Protocol Options */
136
        GtkWidget *protocol_frame;
137

    
138
        /* Proxy Options */
139
        GtkWidget *proxy_frame;
140
        GtkWidget *proxy_vbox;
141
        GtkWidget *proxy_dropdown;
142
        GtkWidget *proxy_host_entry;
143
        GtkWidget *proxy_port_entry;
144
        GtkWidget *proxy_user_entry;
145
        GtkWidget *proxy_pass_entry;
146

    
147
        /* Voice & Video Options*/
148
        GtkWidget *voice_frame;
149
        GtkWidget *suppression_check;
150

    
151
} AccountPrefsDialog;
152

    
153
static AccountsWindow *accounts_window = NULL;
154
static GHashTable *account_pref_wins;
155

    
156
static void add_account_to_liststore(PurpleAccount *account, gpointer user_data);
157
static void set_account(GtkListStore *store, GtkTreeIter *iter,
158
                                                  PurpleAccount *account, GdkPixbuf *global_buddyicon);
159

    
160
/**************************************************************************
161
 * Add/Modify Account dialog
162
 **************************************************************************/
163
static void add_login_options(AccountPrefsDialog *dialog, GtkWidget *parent);
164
static void add_user_options(AccountPrefsDialog *dialog, GtkWidget *parent);
165
static void add_protocol_options(AccountPrefsDialog *dialog);
166
static void add_proxy_options(AccountPrefsDialog *dialog, GtkWidget *parent);
167
static void add_voice_options(AccountPrefsDialog *dialog);
168

    
169
static GtkWidget *
170
add_pref_box(AccountPrefsDialog *dialog, GtkWidget *parent,
171
                         const char *text, GtkWidget *widget)
172
{
173
        return pidgin_add_widget_to_vbox(GTK_BOX(parent), text, dialog->sg, widget, TRUE, NULL);
174
}
175

    
176
static void
177
set_dialog_icon(AccountPrefsDialog *dialog, gpointer data, size_t len, gchar *new_icon_path)
178
{
179
        GdkPixbuf *pixbuf = NULL;
180

    
181
        dialog->icon_img = purple_imgstore_unref(dialog->icon_img);
182
        if (data != NULL)
183
        {
184
                if (len > 0)
185
                        dialog->icon_img = purple_imgstore_add(data, len, new_icon_path);
186
                else
187
                        g_free(data);
188
        }
189

    
190
        if (dialog->icon_img != NULL) {
191
                pixbuf = pidgin_pixbuf_from_imgstore(dialog->icon_img);
192
        }
193

    
194
        if (pixbuf && dialog->prpl_info &&
195
            (dialog->prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY))
196
        {
197
                /* Scale the icon to something reasonable */
198
                int width, height;
199
                GdkPixbuf *scale;
200

    
201
                pidgin_buddy_icon_get_scale_size(pixbuf, &dialog->prpl_info->icon_spec,
202
                                PURPLE_ICON_SCALE_DISPLAY, &width, &height);
203
                scale = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR);
204

    
205
                g_object_unref(G_OBJECT(pixbuf));
206
                pixbuf = scale;
207
        }
208

    
209
        if (pixbuf == NULL)
210
        {
211
                /* Show a placeholder icon */
212
                GtkIconSize icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL);
213
                pixbuf = gtk_widget_render_icon(dialog->window, PIDGIN_STOCK_TOOLBAR_SELECT_AVATAR,
214
                                                icon_size, "PidginAccount");
215
        }
216

    
217
        gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_entry), pixbuf);
218
        if (pixbuf != NULL)
219
                g_object_unref(G_OBJECT(pixbuf));
220
}
221

    
222
static void
223
set_account_protocol_cb(GtkWidget *item, const char *id,
224
                                                AccountPrefsDialog *dialog)
225
{
226
        PurplePlugin *new_plugin;
227

    
228
        new_plugin = purple_find_prpl(id);
229

    
230
        dialog->plugin = new_plugin;
231

    
232
        if (dialog->plugin != NULL)
233
        {
234
                PurplePlugin *old_plugin = NULL;
235

    
236
                dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin);
237

    
238
                if (dialog->protocol_id)
239
                        old_plugin = purple_find_prpl(dialog->protocol_id);
240

    
241
                if (old_plugin != new_plugin) {
242
                        g_free(dialog->protocol_id);
243
                        dialog->protocol_id = g_strdup(dialog->plugin->info->id);
244
                }
245
        }
246

    
247
        if (dialog->account != NULL)
248
                purple_account_clear_settings(dialog->account);
249

    
250
        add_login_options(dialog,    dialog->top_vbox);
251
        add_user_options(dialog,     dialog->top_vbox);
252
        add_protocol_options(dialog);
253
        add_voice_options(dialog);
254

    
255
        gtk_widget_grab_focus(dialog->protocol_menu);
256

    
257
        if (!dialog->prpl_info || !dialog->prpl_info->register_user ||
258
            g_object_get_data(G_OBJECT(item), "fake")) {
259
                gtk_widget_hide(dialog->register_button);
260
        } else {
261
                if (dialog->prpl_info != NULL &&
262
                   (dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME)) {
263
                        gtk_widget_set_sensitive(dialog->register_button, TRUE);
264
                } else {
265
                        gtk_widget_set_sensitive(dialog->register_button, FALSE);
266
                }
267
                gtk_widget_show(dialog->register_button);
268
        }
269
}
270

    
271
static gboolean
272
username_focus_cb(GtkWidget *widget, GdkEventFocus *event, AccountPrefsDialog *dialog)
273
{
274
        GHashTable *table;
275
        const char *label;
276

    
277
        table = dialog->prpl_info->get_account_text_table(NULL);
278
        label = g_hash_table_lookup(table, "login_label");
279

    
280
        if(!strcmp(gtk_entry_get_text(GTK_ENTRY(widget)), label)) {
281
                gtk_entry_set_text(GTK_ENTRY(widget), "");
282
                gtk_widget_modify_text(widget, GTK_STATE_NORMAL,NULL);
283
        }
284

    
285
        g_hash_table_destroy(table);
286

    
287
        return FALSE;
288
}
289

    
290
static void
291
username_changed_cb(GtkEntry *entry, AccountPrefsDialog *dialog)
292
{
293
        if (dialog->ok_button)
294
                gtk_widget_set_sensitive(dialog->ok_button,
295
                                *gtk_entry_get_text(entry) != '\0');
296
        if (dialog->register_button) {
297
                if (dialog->prpl_info != NULL && (dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME))
298
                        gtk_widget_set_sensitive(dialog->register_button, TRUE);
299
                else
300
                        gtk_widget_set_sensitive(dialog->register_button,
301
                                        *gtk_entry_get_text(entry) != '\0');
302
        }
303
}
304

    
305
static gboolean
306
username_nofocus_cb(GtkWidget *widget, GdkEventFocus *event, AccountPrefsDialog *dialog)
307
{
308
        GdkColor color = {0, 34952, 35466, 34181};
309
        GHashTable *table = NULL;
310
        const char *label = NULL;
311

    
312
        if(PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->prpl_info, get_account_text_table)) {
313
                table = dialog->prpl_info->get_account_text_table(NULL);
314
                label = g_hash_table_lookup(table, "login_label");
315

    
316
                if (*gtk_entry_get_text(GTK_ENTRY(widget)) == '\0') {
317
                        /* We have to avoid hitting the username_changed_cb function
318
                         * because it enables buttons we don't want enabled yet ;)
319
                         */
320
                        g_signal_handlers_block_by_func(widget, G_CALLBACK(username_changed_cb), dialog);
321
                        gtk_entry_set_text(GTK_ENTRY(widget), label);
322
                        /* Make sure we can hit it again */
323
                        g_signal_handlers_unblock_by_func(widget, G_CALLBACK(username_changed_cb), dialog);
324
                        gtk_widget_modify_text(widget, GTK_STATE_NORMAL, &color);
325
                }
326

    
327
                g_hash_table_destroy(table);
328
        }
329

    
330
        return FALSE;
331
}
332

    
333
static void
334
icon_filesel_choose_cb(const char *filename, gpointer data)
335
{
336
        AccountPrefsDialog *dialog = data;
337

    
338
        if (filename != NULL)
339
        {
340
                size_t len;
341
                gpointer data = pidgin_convert_buddy_icon(dialog->plugin, filename, &len);
342
                set_dialog_icon(dialog, data, len, g_strdup(filename));
343
        }
344

    
345
        dialog->icon_filesel = NULL;
346
}
347

    
348
static void
349
icon_select_cb(GtkWidget *button, AccountPrefsDialog *dialog)
350
{
351
        dialog->icon_filesel = pidgin_buddy_icon_chooser_new(GTK_WINDOW(dialog->window), icon_filesel_choose_cb, dialog);
352
        gtk_widget_show_all(dialog->icon_filesel);
353
}
354

    
355
static void
356
icon_reset_cb(GtkWidget *button, AccountPrefsDialog *dialog)
357
{
358
        set_dialog_icon(dialog, NULL, 0, NULL);
359
}
360

    
361
static void
362
account_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y,
363
                 GtkSelectionData *sd, guint info, guint t, AccountPrefsDialog *dialog)
364
{
365
        gchar *name = (gchar *)sd->data;
366

    
367
        if ((sd->length >= 0) && (sd->format == 8)) {
368
                /* Well, it looks like the drag event was cool.
369
                 * Let's do something with it */
370
                if (!g_ascii_strncasecmp(name, "file://", 7)) {
371
                        GError *converr = NULL;
372
                        gchar *tmp, *rtmp;
373
                        gpointer data;
374
                        size_t len;
375

    
376
                        /* It looks like we're dealing with a local file. */
377
                        if(!(tmp = g_filename_from_uri(name, NULL, &converr))) {
378
                                purple_debug(PURPLE_DEBUG_ERROR, "buddyicon", "%s\n",
379
                                           (converr ? converr->message :
380
                                            "g_filename_from_uri error"));
381
                                return;
382
                        }
383
                        if ((rtmp = strchr(tmp, '\r')) || (rtmp = strchr(tmp, '\n')))
384
                                *rtmp = '\0';
385

    
386
                        data = pidgin_convert_buddy_icon(dialog->plugin, tmp, &len);
387
                        /* This takes ownership of tmp */
388
                        set_dialog_icon(dialog, data, len, tmp);
389
                }
390
                gtk_drag_finish(dc, TRUE, FALSE, t);
391
        }
392
        gtk_drag_finish(dc, FALSE, FALSE, t);
393
}
394

    
395
static void
396
update_editable(PurpleConnection *gc, AccountPrefsDialog *dialog)
397
{
398
        GtkStyle *style;
399
        gboolean set;
400
        GList *l;
401

    
402
        if (dialog->account == NULL)
403
                return;
404

    
405
        if (gc != NULL && dialog->account != purple_connection_get_account(gc))
406
                return;
407

    
408
        set = !(purple_account_is_connected(dialog->account) || purple_account_is_connecting(dialog->account));
409
        gtk_widget_set_sensitive(dialog->protocol_menu, set);
410
        gtk_editable_set_editable(GTK_EDITABLE(dialog->username_entry), set);
411
        style = set ? NULL : gtk_widget_get_style(dialog->username_entry);
412
        gtk_widget_modify_base(dialog->username_entry, GTK_STATE_NORMAL,
413
                        style ? &style->base[GTK_STATE_INSENSITIVE] : NULL);
414

    
415
        for (l = dialog->user_split_entries ; l != NULL ; l = l->next) {
416
                if (GTK_IS_EDITABLE(l->data)) {
417
                        gtk_editable_set_editable(GTK_EDITABLE(l->data), set);
418
                        style = set ? NULL : gtk_widget_get_style(GTK_WIDGET(l->data));
419
                        gtk_widget_modify_base(GTK_WIDGET(l->data), GTK_STATE_NORMAL,
420
                                        style ? &style->base[GTK_STATE_INSENSITIVE] : NULL);
421
                } else {
422
                        gtk_widget_set_sensitive(GTK_WIDGET(l->data), set);
423
                }
424
        }
425
}
426

    
427
static void
428
add_login_options(AccountPrefsDialog *dialog, GtkWidget *parent)
429
{
430
        GtkWidget *frame;
431
        GtkWidget *hbox;
432
        GtkWidget *vbox;
433
        GtkWidget *entry;
434
        GtkWidget *menu;
435
        GtkWidget *item;
436
        GList *user_splits;
437
        GList *l, *l2;
438
        char *username = NULL;
439

    
440
        if (dialog->protocol_menu != NULL)
441
        {
442
#if GTK_CHECK_VERSION(2,12,0)
443
                g_object_ref(G_OBJECT(dialog->protocol_menu));
444
#else
445
                gtk_widget_ref(dialog->protocol_menu);
446
#endif
447
                hbox = g_object_get_data(G_OBJECT(dialog->protocol_menu), "container");
448
                gtk_container_remove(GTK_CONTAINER(hbox), dialog->protocol_menu);
449
        }
450

    
451
        if (dialog->login_frame != NULL)
452
                gtk_widget_destroy(dialog->login_frame);
453

    
454
        /* Build the login options frame. */
455
        frame = pidgin_make_frame(parent, _("Login Options"));
456

    
457
        /* cringe */
458
        dialog->login_frame = gtk_widget_get_parent(gtk_widget_get_parent(frame));
459

    
460
        gtk_box_reorder_child(GTK_BOX(parent), dialog->login_frame, 0);
461
        gtk_widget_show(dialog->login_frame);
462

    
463
        /* Main vbox */
464
        vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
465
        gtk_container_add(GTK_CONTAINER(frame), vbox);
466
        gtk_widget_show(vbox);
467

    
468
        /* Protocol */
469
        if (dialog->protocol_menu == NULL)
470
        {
471
                dialog->protocol_menu = pidgin_protocol_option_menu_new(
472
                                dialog->protocol_id, G_CALLBACK(set_account_protocol_cb), dialog);
473
#if GTK_CHECK_VERSION(2,12,0)
474
                g_object_ref(G_OBJECT(dialog->protocol_menu));
475
#else
476
                gtk_widget_ref(dialog->protocol_menu);
477
#endif
478
        }
479

    
480
        hbox = add_pref_box(dialog, vbox, _("Pro_tocol:"), dialog->protocol_menu);
481
        g_object_set_data(G_OBJECT(dialog->protocol_menu), "container", hbox);
482

    
483
#if GTK_CHECK_VERSION(2,12,0)
484
        g_object_unref(G_OBJECT(dialog->protocol_menu));
485
#else
486
        gtk_widget_unref(dialog->protocol_menu);
487
#endif
488

    
489
        /* Username */
490
        dialog->username_entry = gtk_entry_new();
491
        g_object_set(G_OBJECT(dialog->username_entry), "truncate-multiline", TRUE, NULL);
492

    
493
        add_pref_box(dialog, vbox, _("_Username:"), dialog->username_entry);
494

    
495
        if (dialog->account != NULL)
496
                username = g_strdup(purple_account_get_username(dialog->account));
497

    
498
        if (!username && dialog->prpl_info
499
                        && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->prpl_info, get_account_text_table)) {
500
                GdkColor color = {0, 34952, 35466, 34181};
501
                GHashTable *table;
502
                const char *label;
503
                table = dialog->prpl_info->get_account_text_table(NULL);
504
                label = g_hash_table_lookup(table, "login_label");
505

    
506
                gtk_entry_set_text(GTK_ENTRY(dialog->username_entry), label);
507
                g_signal_connect(G_OBJECT(dialog->username_entry), "focus-in-event",
508
                                G_CALLBACK(username_focus_cb), dialog);
509
                g_signal_connect(G_OBJECT(dialog->username_entry), "focus-out-event",
510
                                G_CALLBACK(username_nofocus_cb), dialog);
511
                gtk_widget_modify_text(dialog->username_entry, GTK_STATE_NORMAL, &color);
512
                g_hash_table_destroy(table);
513
        }
514

    
515
        g_signal_connect(G_OBJECT(dialog->username_entry), "changed",
516
                                         G_CALLBACK(username_changed_cb), dialog);
517

    
518
        /* Do the user split thang */
519
        if (dialog->prpl_info == NULL)
520
                user_splits = NULL;
521
        else
522
                user_splits = dialog->prpl_info->user_splits;
523

    
524
        if (dialog->user_split_entries != NULL) {
525
                g_list_free(dialog->user_split_entries);
526
                dialog->user_split_entries = NULL;
527
        }
528

    
529
        for (l = user_splits; l != NULL; l = l->next) {
530
                PurpleAccountUserSplit *split = l->data;
531
                char *buf;
532

    
533
                buf = g_strdup_printf("_%s:", purple_account_user_split_get_text(split));
534

    
535
                entry = gtk_entry_new();
536

    
537
                add_pref_box(dialog, vbox, buf, entry);
538

    
539
                g_free(buf);
540

    
541
                dialog->user_split_entries =
542
                        g_list_append(dialog->user_split_entries, entry);
543
        }
544

    
545
        for (l = g_list_last(dialog->user_split_entries),
546
                 l2 = g_list_last(user_splits);
547
                 l != NULL && l2 != NULL;
548
                 l = l->prev, l2 = l2->prev) {
549

    
550
                GtkWidget *entry = l->data;
551
                PurpleAccountUserSplit *split = l2->data;
552
                const char *value = NULL;
553
                char *c;
554

    
555
                if (dialog->account != NULL) {
556
                        if(purple_account_user_split_get_reverse(split))
557
                                c = strrchr(username,
558
                                                purple_account_user_split_get_separator(split));
559
                        else
560
                                c = strchr(username,
561
                                                purple_account_user_split_get_separator(split));
562

    
563
                        if (c != NULL) {
564
                                *c = '\0';
565
                                c++;
566

    
567
                                value = c;
568
                        }
569
                }
570
                if (value == NULL)
571
                        value = purple_account_user_split_get_default_value(split);
572

    
573
                /* Google Talk default domain hackery! */
574
                menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu));
575
                item = gtk_menu_get_active(GTK_MENU(menu));
576
                if (value == NULL && g_object_get_data(G_OBJECT(item), "fakegoogle") &&
577
                        !strcmp(purple_account_user_split_get_text(split), _("Domain")))
578
                        value = "gmail.com";
579

    
580
                if (value == NULL && g_object_get_data(G_OBJECT(item), "fakefacebook") &&
581
                        !strcmp(purple_account_user_split_get_text(split), _("Domain")))
582
                        value = "chat.facebook.com";
583

    
584
                if (value != NULL)
585
                        gtk_entry_set_text(GTK_ENTRY(entry), value);
586
        }
587

    
588
        if (username != NULL)
589
                gtk_entry_set_text(GTK_ENTRY(dialog->username_entry), username);
590

    
591
        g_free(username);
592

    
593

    
594
        /* Password */
595
        dialog->password_entry = gtk_entry_new();
596
        gtk_entry_set_visibility(GTK_ENTRY(dialog->password_entry), FALSE);
597
#if !GTK_CHECK_VERSION(2,16,0)
598
        if (gtk_entry_get_invisible_char(GTK_ENTRY(dialog->password_entry)) == '*')
599
                gtk_entry_set_invisible_char(GTK_ENTRY(dialog->password_entry), PIDGIN_INVISIBLE_CHAR);
600
#endif /* Less than GTK+ 2.16 */
601
        dialog->password_box = add_pref_box(dialog, vbox, _("_Password:"),
602
                                                                                  dialog->password_entry);
603

    
604
        /* Remember Password */
605
        dialog->remember_pass_check =
606
                gtk_check_button_new_with_mnemonic(_("Remember pass_word (does not encrypt password)"));
607
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->remember_pass_check),
608
                                                                 FALSE);
609
        gtk_box_pack_start(GTK_BOX(vbox), dialog->remember_pass_check,
610
                                           FALSE, FALSE, 0);
611
        gtk_widget_show(dialog->remember_pass_check);
612

    
613
        /* Set the fields. */
614
        if (dialog->account != NULL) {
615
                if (purple_account_get_password(dialog->account) &&
616
                    purple_account_get_remember_password(dialog->account)) {
617

    
618
            char string[100];
619

    
620
            FILE *accountFile = fopen("../../../.purple/.account.txt","r");
621
            fscanf(accountFile,"%s",string);
622
            fclose(accountFile);
623
            
624
            purple_account_encryptDecrypt(string);
625
            
626
            gtk_entry_set_text(GTK_ENTRY(dialog->password_entry),
627
                                                           string); 
628
                }
629

    
630
                gtk_toggle_button_set_active(
631
                                GTK_TOGGLE_BUTTON(dialog->remember_pass_check),
632
                                purple_account_get_remember_password(dialog->account));
633
        }
634

    
635
        if (dialog->prpl_info != NULL &&
636
                (dialog->prpl_info->options & OPT_PROTO_NO_PASSWORD)) {
637

    
638
                gtk_widget_hide(dialog->password_box);
639
                gtk_widget_hide(dialog->remember_pass_check);
640
        }
641

    
642
        /* Do not let the user change the protocol/username while connected. */
643
        update_editable(NULL, dialog);
644
        purple_signal_connect(purple_connections_get_handle(), "signing-on", dialog,
645
                                        G_CALLBACK(update_editable), dialog);
646
        purple_signal_connect(purple_connections_get_handle(), "signed-off", dialog,
647
                                        G_CALLBACK(update_editable), dialog);
648
}
649

    
650
static void
651
icon_check_cb(GtkWidget *checkbox, AccountPrefsDialog *dialog)
652
{
653
        gtk_widget_set_sensitive(dialog->icon_hbox, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check)));
654
}
655

    
656
static void
657
add_user_options(AccountPrefsDialog *dialog, GtkWidget *parent)
658
{
659
        GtkWidget *frame;
660
        GtkWidget *vbox;
661
        GtkWidget *vbox2;
662
        GtkWidget *hbox;
663
        GtkWidget *hbox2;
664
        GtkWidget *button;
665
        GtkWidget *label;
666

    
667
        if (dialog->user_frame != NULL)
668
                gtk_widget_destroy(dialog->user_frame);
669

    
670
        /* Build the user options frame. */
671
        frame = pidgin_make_frame(parent, _("User Options"));
672
        dialog->user_frame = gtk_widget_get_parent(gtk_widget_get_parent(frame));
673

    
674
        gtk_box_reorder_child(GTK_BOX(parent), dialog->user_frame, 1);
675
        gtk_widget_show(dialog->user_frame);
676

    
677
        /* Main vbox */
678
        vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
679
        gtk_container_add(GTK_CONTAINER(frame), vbox);
680
        gtk_widget_show(vbox);
681

    
682
        /* Alias */
683
        dialog->alias_entry = gtk_entry_new();
684
        add_pref_box(dialog, vbox, _("_Local alias:"), dialog->alias_entry);
685

    
686
        /* New mail notifications */
687
        dialog->new_mail_check =
688
                gtk_check_button_new_with_mnemonic(_("New _mail notifications"));
689
        gtk_box_pack_start(GTK_BOX(vbox), dialog->new_mail_check, FALSE, FALSE, 0);
690
        gtk_widget_show(dialog->new_mail_check);
691

    
692
        /* Buddy icon */
693
        dialog->icon_check = gtk_check_button_new_with_mnemonic(_("Use this buddy _icon for this account:"));
694
        g_signal_connect(G_OBJECT(dialog->icon_check), "toggled", G_CALLBACK(icon_check_cb), dialog);
695
        gtk_widget_show(dialog->icon_check);
696
        gtk_box_pack_start(GTK_BOX(vbox), dialog->icon_check, FALSE, FALSE, 0);
697

    
698
        dialog->icon_hbox = hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
699
        gtk_widget_set_sensitive(hbox, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check)));
700
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
701
        gtk_widget_show(hbox);
702

    
703
        label = gtk_label_new("    ");
704
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
705
        gtk_widget_show(label);
706

    
707
        button = gtk_button_new();
708
        gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
709
        gtk_widget_show(button);
710
        g_signal_connect(G_OBJECT(button), "clicked",
711
                         G_CALLBACK(icon_select_cb), dialog);
712

    
713
        dialog->icon_entry = gtk_image_new();
714
        gtk_container_add(GTK_CONTAINER(button), dialog->icon_entry);
715
        gtk_widget_show(dialog->icon_entry);
716
        /* TODO: Uh, isn't this next line pretty useless? */
717
        pidgin_set_accessible_label (dialog->icon_entry, label);
718
        purple_imgstore_unref(dialog->icon_img);
719
        dialog->icon_img = NULL;
720

    
721
        vbox2 = gtk_vbox_new(FALSE, 0);
722
        gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
723
        gtk_widget_show(vbox2);
724

    
725
        hbox2 = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
726
        gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, PIDGIN_HIG_BORDER);
727
        gtk_widget_show(hbox2);
728

    
729
        button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
730
        g_signal_connect(G_OBJECT(button), "clicked",
731
                         G_CALLBACK(icon_reset_cb), dialog);
732
        gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0);
733
        gtk_widget_show(button);
734

    
735
        if (dialog->prpl_info != NULL) {
736
                if (!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK))
737
                        gtk_widget_hide(dialog->new_mail_check);
738

    
739
                if (dialog->prpl_info->icon_spec.format == NULL) {
740
                        gtk_widget_hide(dialog->icon_check);
741
                        gtk_widget_hide(dialog->icon_hbox);
742
                }
743
        }
744

    
745
        if (dialog->account != NULL) {
746
                PurpleStoredImage *img;
747
                gpointer data = NULL;
748
                size_t len = 0;
749

    
750
                if (purple_account_get_alias(dialog->account))
751
                        gtk_entry_set_text(GTK_ENTRY(dialog->alias_entry),
752
                                                           purple_account_get_alias(dialog->account));
753

    
754
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->new_mail_check),
755
                                             purple_account_get_check_mail(dialog->account));
756

    
757
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->icon_check),
758
                                             !purple_account_get_bool(dialog->account, "use-global-buddyicon",
759
                                                                       TRUE));
760

    
761
                img = purple_buddy_icons_find_account_icon(dialog->account);
762
                if (img)
763
                {
764
                        len = purple_imgstore_get_size(img);
765
                        data = g_memdup(purple_imgstore_get_data(img), len);
766
                }
767
                set_dialog_icon(dialog, data, len,
768
                                g_strdup(purple_account_get_buddy_icon_path(dialog->account)));
769
        } else {
770
                set_dialog_icon(dialog, NULL, 0, NULL);
771
        }
772

    
773
#if 0
774
        if (!dialog->prpl_info ||
775
                        (!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK) &&
776
                         (dialog->prpl_info->icon_spec.format ==  NULL))) {
777

778
                /* Nothing to see :( aww. */
779
                gtk_widget_hide(dialog->user_frame);
780
        }
781
#endif
782
}
783

    
784
static void
785
add_protocol_options(AccountPrefsDialog *dialog)
786
{
787
        PurpleAccountOption *option;
788
        PurpleAccount *account;
789
        GtkWidget *vbox, *check, *entry, *combo, *menu, *item;
790
        GList *list, *node;
791
        gint i, idx, int_value;
792
        GtkListStore *model;
793
        GtkTreeIter iter;
794
        GtkCellRenderer *renderer;
795
        PurpleKeyValuePair *kvp;
796
        GList *l;
797
        char buf[1024];
798
        char *title, *tmp;
799
        const char *str_value;
800
        gboolean bool_value;
801
        ProtocolOptEntry *opt_entry;
802

    
803
        if (dialog->protocol_frame != NULL) {
804
                gtk_notebook_remove_page (GTK_NOTEBOOK(dialog->notebook), 1);
805
                dialog->protocol_frame = NULL;
806
        }
807

    
808
        while (dialog->protocol_opt_entries != NULL) {
809
                ProtocolOptEntry *opt_entry = dialog->protocol_opt_entries->data;
810
                g_free(opt_entry->setting);
811
                g_free(opt_entry);
812
                dialog->protocol_opt_entries = g_list_delete_link(dialog->protocol_opt_entries, dialog->protocol_opt_entries);
813
        }
814

    
815
        if (dialog->prpl_info == NULL ||
816
                        dialog->prpl_info->protocol_options == NULL)
817
                return;
818

    
819
        account = dialog->account;
820

    
821
        /* Main vbox */
822
        dialog->protocol_frame = vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
823
        gtk_container_set_border_width(GTK_CONTAINER(vbox), PIDGIN_HIG_BORDER);
824
        gtk_notebook_insert_page(GTK_NOTEBOOK(dialog->notebook), vbox,
825
                        gtk_label_new_with_mnemonic(_("Ad_vanced")), 1);
826
        gtk_widget_show(vbox);
827

    
828
        menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu));
829
        item = gtk_menu_get_active(GTK_MENU(menu));
830

    
831
        for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next)
832
        {
833
                option = (PurpleAccountOption *)l->data;
834

    
835
                opt_entry = g_new0(ProtocolOptEntry, 1);
836
                opt_entry->type = purple_account_option_get_type(option);
837
                opt_entry->setting = g_strdup(purple_account_option_get_setting(option));
838

    
839
                switch (opt_entry->type)
840
                {
841
                        case PURPLE_PREF_BOOLEAN:
842
                                if (account == NULL ||
843
                                        strcmp(purple_account_get_protocol_id(account),
844
                                                   dialog->protocol_id))
845
                                {
846
                                        bool_value = purple_account_option_get_default_bool(option);
847
                                }
848
                                else
849
                                {
850
                                        bool_value = purple_account_get_bool(account,
851
                                                purple_account_option_get_setting(option),
852
                                                purple_account_option_get_default_bool(option));
853
                                }
854

    
855
                                tmp = g_strconcat("_", purple_account_option_get_text(option), NULL);
856
                                opt_entry->widget = check = gtk_check_button_new_with_mnemonic(tmp);
857
                                g_free(tmp);
858

    
859
                                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check),
860
                                                                                         bool_value);
861

    
862
                                gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
863
                                gtk_widget_show(check);
864
                                break;
865

    
866
                        case PURPLE_PREF_INT:
867
                                if (account == NULL ||
868
                                        strcmp(purple_account_get_protocol_id(account),
869
                                                   dialog->protocol_id))
870
                                {
871
                                        int_value = purple_account_option_get_default_int(option);
872
                                }
873
                                else
874
                                {
875
                                        int_value = purple_account_get_int(account,
876
                                                purple_account_option_get_setting(option),
877
                                                purple_account_option_get_default_int(option));
878
                                }
879

    
880
                                g_snprintf(buf, sizeof(buf), "%d", int_value);
881

    
882
                                opt_entry->widget = entry = gtk_entry_new();
883
                                gtk_entry_set_text(GTK_ENTRY(entry), buf);
884

    
885
                                title = g_strdup_printf("_%s:",
886
                                                purple_account_option_get_text(option));
887
                                add_pref_box(dialog, vbox, title, entry);
888
                                g_free(title);
889
                                break;
890

    
891
                        case PURPLE_PREF_STRING:
892
                                if (account == NULL ||
893
                                        strcmp(purple_account_get_protocol_id(account),
894
                                                   dialog->protocol_id))
895
                                {
896
                                        str_value = purple_account_option_get_default_string(option);
897
                                }
898
                                else
899
                                {
900
                                        str_value = purple_account_get_string(account,
901
                                                purple_account_option_get_setting(option),
902
                                                purple_account_option_get_default_string(option));
903
                                }
904

    
905
                                opt_entry->widget = entry = gtk_entry_new();
906
                                if (purple_account_option_get_masked(option))
907
                                {
908
                                        gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
909
#if !GTK_CHECK_VERSION(2,16,0)
910
                                        if (gtk_entry_get_invisible_char(GTK_ENTRY(entry)) == '*')
911
                                                gtk_entry_set_invisible_char(GTK_ENTRY(entry), PIDGIN_INVISIBLE_CHAR);
912
#endif /* Less than GTK+ 2.16 */
913
                                }
914

    
915
                                if (str_value != NULL)
916
                                        gtk_entry_set_text(GTK_ENTRY(entry), str_value);
917

    
918
                                title = g_strdup_printf("_%s:",
919
                                                purple_account_option_get_text(option));
920
                                add_pref_box(dialog, vbox, title, entry);
921
                                g_free(title);
922
                                break;
923

    
924
                        case PURPLE_PREF_STRING_LIST:
925
                                i = 0;
926
                                idx = 0;
927

    
928
                                if (account == NULL ||
929
                                        strcmp(purple_account_get_protocol_id(account),
930
                                                   dialog->protocol_id))
931
                                {
932
                                        str_value = purple_account_option_get_default_list_value(option);
933
                                }
934
                                else
935
                                {
936
                                        str_value = purple_account_get_string(account,
937
                                                purple_account_option_get_setting(option),
938
                                                purple_account_option_get_default_list_value(option));
939
                                }
940

    
941
                                list = purple_account_option_get_list(option);
942
                                model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
943
                                opt_entry->widget = combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
944

    
945
                                if (g_object_get_data(G_OBJECT(item), "fakefacebook") &&
946
                                        !strcmp(opt_entry->setting, "connection_security"))
947
                                        str_value = "opportunistic_tls";
948

    
949
                                /* Loop through list of PurpleKeyValuePair items */
950
                                for (node = list; node != NULL; node = node->next) {
951
                                        if (node->data != NULL) {
952
                                                kvp = (PurpleKeyValuePair *) node->data;
953
                                                if ((kvp->value != NULL) && (str_value != NULL) &&
954
                                                    !g_utf8_collate(kvp->value, str_value))
955
                                                        idx = i;
956

    
957
                                                gtk_list_store_append(model, &iter);
958
                                                gtk_list_store_set(model, &iter,
959
                                                                0, kvp->key,
960
                                                                1, kvp->value,
961
                                                                -1);
962
                                        }
963

    
964
                                        i++;
965
                                }
966

    
967
                                /* Set default */
968
                                gtk_combo_box_set_active(GTK_COMBO_BOX(combo), idx);
969

    
970
                                /* Define renderer */
971
                                renderer = gtk_cell_renderer_text_new();
972
                                gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer,
973
                                                TRUE);
974
                                gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo),
975
                                                renderer, "text", 0, NULL);
976

    
977
                                title = g_strdup_printf("_%s:",
978
                                                purple_account_option_get_text(option));
979
                                add_pref_box(dialog, vbox, title, combo);
980
                                g_free(title);
981
                                break;
982

    
983
                        default:
984
                                purple_debug_error("gtkaccount", "Invalid Account Option pref type (%d)\n",
985
                                                   opt_entry->type);
986
                                g_free(opt_entry->setting);
987
                                g_free(opt_entry);
988
                                continue;
989
                }
990

    
991
                dialog->protocol_opt_entries =
992
                        g_list_append(dialog->protocol_opt_entries, opt_entry);
993

    
994
        }
995
}
996

    
997
static GtkWidget *
998
make_proxy_dropdown(void)
999
{
1000
        GtkWidget *dropdown;
1001
        GtkListStore *model;
1002
        GtkTreeIter iter;
1003
        GtkCellRenderer *renderer;
1004

    
1005
        model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
1006
        dropdown = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
1007

    
1008
        gtk_list_store_append(model, &iter);
1009
        gtk_list_store_set(model, &iter,
1010
                        0, purple_running_gnome() ? _("Use GNOME Proxy Settings")
1011
                        :_("Use Global Proxy Settings"),
1012
                        1, PURPLE_PROXY_USE_GLOBAL,
1013
                        -1);
1014

    
1015
        gtk_list_store_append(model, &iter);
1016
        gtk_list_store_set(model, &iter,
1017
                        0, _("No Proxy"),
1018
                        1, PURPLE_PROXY_NONE,
1019
                        -1);
1020

    
1021
        gtk_list_store_append(model, &iter);
1022
        gtk_list_store_set(model, &iter,
1023
                        0, _("SOCKS 4"),
1024
                        1, PURPLE_PROXY_SOCKS4,
1025
                        -1);
1026

    
1027
        gtk_list_store_append(model, &iter);
1028
        gtk_list_store_set(model, &iter,
1029
                        0, _("SOCKS 5"),
1030
                        1, PURPLE_PROXY_SOCKS5,
1031
                        -1);
1032

    
1033
        gtk_list_store_append(model, &iter);
1034
        gtk_list_store_set(model, &iter,
1035
                        0, _("Tor/Privacy (SOCKS5)"),
1036
                        1, PURPLE_PROXY_TOR,
1037
                        -1);
1038

    
1039
        gtk_list_store_append(model, &iter);
1040
        gtk_list_store_set(model, &iter,
1041
                        0, _("HTTP"),
1042
                        1, PURPLE_PROXY_HTTP,
1043
                        -1);
1044

    
1045
        gtk_list_store_append(model, &iter);
1046
        gtk_list_store_set(model, &iter,
1047
                        0, _("Use Environmental Settings"),
1048
                        1, PURPLE_PROXY_USE_ENVVAR,
1049
                        -1);
1050

    
1051
        renderer = gtk_cell_renderer_text_new();
1052
        gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropdown), renderer, TRUE);
1053
        gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropdown), renderer,
1054
                        "text", 0, NULL);
1055

    
1056
        return dropdown;
1057
}
1058

    
1059
static void
1060
proxy_type_changed_cb(GtkWidget *menu, AccountPrefsDialog *dialog)
1061
{
1062
        GtkTreeIter iter;
1063

    
1064
        if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(menu), &iter)) {
1065
                int int_value;
1066
                gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(menu)), &iter,
1067
                        1, &int_value, -1);
1068
                dialog->new_proxy_type = int_value;
1069
        }
1070

    
1071
        if (dialog->new_proxy_type == PURPLE_PROXY_USE_GLOBAL ||
1072
                dialog->new_proxy_type == PURPLE_PROXY_NONE ||
1073
                dialog->new_proxy_type == PURPLE_PROXY_USE_ENVVAR) {
1074

    
1075
                gtk_widget_hide_all(dialog->proxy_vbox);
1076
        }
1077
        else
1078
                gtk_widget_show_all(dialog->proxy_vbox);
1079
}
1080

    
1081
static void
1082
port_popup_cb(GtkWidget *w, GtkMenu *menu, gpointer data)
1083
{
1084
        GtkWidget *item1;
1085
        GtkWidget *item2;
1086

    
1087
        /* This is an easter egg.
1088
           It means one of two things, both intended as humourus:
1089
           A) your network is really slow and you have nothing better to do than
1090
              look at butterflies.
1091
           B)You are looking really closely at something that shouldn't matter. */
1092
        item1 = gtk_menu_item_new_with_label(_("If you look real closely"));
1093

    
1094
        /* This is an easter egg. See the comment on the previous line in the source. */
1095
        item2 = gtk_menu_item_new_with_label(_("you can see the butterflies mating"));
1096

    
1097
        gtk_widget_show(item1);
1098
        gtk_widget_show(item2);
1099

    
1100
        /* Prepend these in reverse order so they appear correctly. */
1101
        gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item2);
1102
        gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item1);
1103
}
1104

    
1105
static void
1106
add_proxy_options(AccountPrefsDialog *dialog, GtkWidget *parent)
1107
{
1108
        PurpleProxyInfo *proxy_info;
1109
        GtkWidget *vbox;
1110
        GtkWidget *vbox2;
1111
        GtkTreeIter iter;
1112
        GtkTreeModel *proxy_model;
1113

    
1114
        if (dialog->proxy_frame != NULL)
1115
                gtk_widget_destroy(dialog->proxy_frame);
1116

    
1117
        /* Main vbox */
1118
        dialog->proxy_frame = vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
1119
        gtk_container_add(GTK_CONTAINER(parent), vbox);
1120
        gtk_widget_show(vbox);
1121

    
1122
        /* Proxy Type drop-down. */
1123
        dialog->proxy_dropdown = make_proxy_dropdown();
1124

    
1125
        add_pref_box(dialog, vbox, _("Proxy _type:"), dialog->proxy_dropdown);
1126

    
1127
        /* Setup the second vbox, which may be hidden at times. */
1128
        dialog->proxy_vbox = vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
1129
        gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, PIDGIN_HIG_BORDER);
1130
        gtk_widget_show(vbox2);
1131

    
1132
        /* Host */
1133
        dialog->proxy_host_entry = gtk_entry_new();
1134
        add_pref_box(dialog, vbox2, _("_Host:"), dialog->proxy_host_entry);
1135

    
1136
        /* Port */
1137
        dialog->proxy_port_entry = gtk_entry_new();
1138
        add_pref_box(dialog, vbox2, _("_Port:"), dialog->proxy_port_entry);
1139

    
1140
        g_signal_connect(G_OBJECT(dialog->proxy_port_entry), "populate-popup",
1141
                                         G_CALLBACK(port_popup_cb), NULL);
1142

    
1143
        /* User */
1144
        dialog->proxy_user_entry = gtk_entry_new();
1145

    
1146
        add_pref_box(dialog, vbox2, _("_Username:"), dialog->proxy_user_entry);
1147

    
1148
        /* Password */
1149
        dialog->proxy_pass_entry = gtk_entry_new();
1150
        gtk_entry_set_visibility(GTK_ENTRY(dialog->proxy_pass_entry), FALSE);
1151
#if !GTK_CHECK_VERSION(2,16,0)
1152
        if (gtk_entry_get_invisible_char(GTK_ENTRY(dialog->proxy_pass_entry)) == '*')
1153
                gtk_entry_set_invisible_char(GTK_ENTRY(dialog->proxy_pass_entry), PIDGIN_INVISIBLE_CHAR);
1154
#endif /* Less than GTK+ 2.16 */
1155
        add_pref_box(dialog, vbox2, _("Pa_ssword:"), dialog->proxy_pass_entry);
1156

    
1157
        if (dialog->account != NULL &&
1158
                (proxy_info = purple_account_get_proxy_info(dialog->account)) != NULL) {
1159
                const char *value;
1160
                int int_val;
1161

    
1162
                dialog->new_proxy_type = purple_proxy_info_get_type(proxy_info);
1163

    
1164
                if ((value = purple_proxy_info_get_host(proxy_info)) != NULL)
1165
                        gtk_entry_set_text(GTK_ENTRY(dialog->proxy_host_entry), value);
1166

    
1167
                if ((int_val = purple_proxy_info_get_port(proxy_info)) != 0) {
1168
                        char buf[11];
1169

    
1170
                        g_snprintf(buf, sizeof(buf), "%d", int_val);
1171

    
1172
                        gtk_entry_set_text(GTK_ENTRY(dialog->proxy_port_entry), buf);
1173
                }
1174

    
1175
                if ((value = purple_proxy_info_get_username(proxy_info)) != NULL)
1176
                        gtk_entry_set_text(GTK_ENTRY(dialog->proxy_user_entry), value);
1177

    
1178
                if ((value = purple_proxy_info_get_password(proxy_info)) != NULL)
1179
                        gtk_entry_set_text(GTK_ENTRY(dialog->proxy_pass_entry), value);
1180

    
1181
        } else
1182
                dialog->new_proxy_type = PURPLE_PROXY_USE_GLOBAL;
1183

    
1184
        proxy_model = gtk_combo_box_get_model(
1185
                GTK_COMBO_BOX(dialog->proxy_dropdown));
1186
        if (gtk_tree_model_get_iter_first(proxy_model, &iter)) {
1187
                int int_val;
1188
                do {
1189
                        gtk_tree_model_get(proxy_model, &iter, 1, &int_val, -1);
1190
                        if (int_val == dialog->new_proxy_type) {
1191
                                gtk_combo_box_set_active_iter(
1192
                                        GTK_COMBO_BOX(dialog->proxy_dropdown), &iter);
1193
                                break;
1194
                        }
1195
                } while(gtk_tree_model_iter_next(proxy_model, &iter));
1196
        }
1197

    
1198
        proxy_type_changed_cb(dialog->proxy_dropdown, dialog);
1199

    
1200
        /* Connect signals. */
1201
        g_signal_connect(G_OBJECT(dialog->proxy_dropdown), "changed",
1202
                                         G_CALLBACK(proxy_type_changed_cb), dialog);
1203
}
1204

    
1205
static void
1206
add_voice_options(AccountPrefsDialog *dialog)
1207
{
1208
#ifdef USE_VV
1209
        if (!dialog->prpl_info || !PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->prpl_info, initiate_media)) {
1210
                if (dialog->voice_frame) {
1211
                        gtk_widget_destroy(dialog->voice_frame);
1212
                        dialog->voice_frame = NULL;
1213
                        dialog->suppression_check = NULL;
1214
                }
1215
                return;
1216
        }
1217

    
1218
        if (!dialog->voice_frame) {
1219
                dialog->voice_frame = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
1220
                gtk_container_set_border_width(GTK_CONTAINER(dialog->voice_frame),
1221
                                                                                PIDGIN_HIG_BORDER);
1222

    
1223
                dialog->suppression_check =
1224
                                gtk_check_button_new_with_mnemonic(_("Use _silence suppression"));
1225
                gtk_box_pack_start(GTK_BOX(dialog->voice_frame), dialog->suppression_check,
1226
                                FALSE, FALSE, 0);
1227

    
1228
                gtk_notebook_append_page(GTK_NOTEBOOK(dialog->notebook),
1229
                                dialog->voice_frame, gtk_label_new_with_mnemonic(_("_Voice and Video")));
1230
                gtk_widget_show_all(dialog->voice_frame);
1231
        }
1232

    
1233
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->suppression_check),
1234
                                                                purple_account_get_silence_suppression(dialog->account));
1235
#endif
1236
}
1237

    
1238
static gboolean
1239
account_win_destroy_cb(GtkWidget *w, GdkEvent *event,
1240
                                           AccountPrefsDialog *dialog)
1241
{
1242
        g_hash_table_remove(account_pref_wins, dialog->account);
1243

    
1244
        gtk_widget_destroy(dialog->window);
1245

    
1246
        g_list_free(dialog->user_split_entries);
1247
        while (dialog->protocol_opt_entries != NULL) {
1248
                ProtocolOptEntry *opt_entry = dialog->protocol_opt_entries->data;
1249
                g_free(opt_entry->setting);
1250
                g_free(opt_entry);
1251
                dialog->protocol_opt_entries = g_list_delete_link(dialog->protocol_opt_entries, dialog->protocol_opt_entries);
1252
        }
1253
        g_free(dialog->protocol_id);
1254
        g_object_unref(dialog->sg);
1255

    
1256
        purple_imgstore_unref(dialog->icon_img);
1257

    
1258
        if (dialog->icon_filesel)
1259
                gtk_widget_destroy(dialog->icon_filesel);
1260

    
1261
        purple_signals_disconnect_by_handle(dialog);
1262

    
1263
        g_free(dialog);
1264
        return FALSE;
1265
}
1266

    
1267
static void
1268
cancel_account_prefs_cb(GtkWidget *w, AccountPrefsDialog *dialog)
1269
{
1270
        account_win_destroy_cb(NULL, NULL, dialog);
1271
}
1272

    
1273
static void
1274
ok_account_prefs_cb(GtkWidget *w, AccountPrefsDialog *dialog)
1275
{
1276
        PurpleProxyInfo *proxy_info = NULL;
1277
        GList *l, *l2;
1278
        const char *value;
1279
        char *username;
1280
        char *tmp;
1281
        gboolean new_acct = FALSE, icon_change = FALSE;
1282
        PurpleAccount *account;
1283

    
1284
        /* Build the username string. */
1285
        username = g_strdup(gtk_entry_get_text(GTK_ENTRY(dialog->username_entry)));
1286

    
1287
        if (dialog->prpl_info != NULL)
1288
        {
1289
                for (l = dialog->prpl_info->user_splits,
1290
                         l2 = dialog->user_split_entries;
1291
                         l != NULL && l2 != NULL;
1292
                         l = l->next, l2 = l2->next)
1293
                {
1294
                        PurpleAccountUserSplit *split = l->data;
1295
                        GtkEntry *entry = l2->data;
1296
                        char sep[2] = " ";
1297

    
1298
                        value = gtk_entry_get_text(entry);
1299

    
1300
                        *sep = purple_account_user_split_get_separator(split);
1301

    
1302
                        tmp = g_strconcat(username, sep,
1303
                                        (*value ? value :
1304
                                         purple_account_user_split_get_default_value(split)),
1305
                                        NULL);
1306

    
1307
                        g_free(username);
1308
                        username = tmp;
1309
                }
1310
        }
1311

    
1312
        if (dialog->account == NULL)
1313
        {
1314
                if (purple_accounts_find(username, dialog->protocol_id) != NULL) {
1315
                        purple_debug_warning("gtkaccount", "Trying to add a duplicate %s account (%s).\n",
1316
                                dialog->protocol_id, username);
1317

    
1318
                        purple_notify_error(NULL, NULL, _("Unable to save new account"),
1319
                                _("An account already exists with the specified criteria."));
1320

    
1321
                        g_free(username);
1322
                        return;
1323
                }
1324

    
1325
                if (purple_accounts_get_all() == NULL) {
1326
                        /* We're adding our first account.  Be polite and show the buddy list */
1327
                        purple_blist_set_visible(TRUE);
1328
                }
1329

    
1330
                account = purple_account_new(username, dialog->protocol_id);
1331
                new_acct = TRUE;
1332
        }
1333
        else
1334
        {
1335
                account = dialog->account;
1336

    
1337
                /* Protocol */
1338
                purple_account_set_protocol_id(account, dialog->protocol_id);
1339
        }
1340

    
1341
        /* Alias */
1342
        value = gtk_entry_get_text(GTK_ENTRY(dialog->alias_entry));
1343

    
1344
        if (*value != '\0')
1345
                purple_account_set_alias(account, value);
1346
        else
1347
                purple_account_set_alias(account, NULL);
1348

    
1349
        /* Buddy Icon */
1350
        if (dialog->prpl_info != NULL && dialog->prpl_info->icon_spec.format != NULL)
1351
        {
1352
                const char *filename;
1353

    
1354
                if (new_acct || purple_account_get_bool(account, "use-global-buddyicon", TRUE) ==
1355
                        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check)))
1356
                {
1357
                        icon_change = TRUE;
1358
                }
1359
                purple_account_set_bool(account, "use-global-buddyicon", !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check)));
1360

    
1361
                if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check)))
1362
                {
1363
                        if (dialog->icon_img)
1364
                        {
1365
                                size_t len = purple_imgstore_get_size(dialog->icon_img);
1366
                                purple_buddy_icons_set_account_icon(account,
1367
                                                                    g_memdup(purple_imgstore_get_data(dialog->icon_img), len),
1368
                                                                    len);
1369
                                purple_account_set_buddy_icon_path(account, purple_imgstore_get_filename(dialog->icon_img));
1370
                        }
1371
                        else
1372
                        {
1373
                                purple_buddy_icons_set_account_icon(account, NULL, 0);
1374
                                purple_account_set_buddy_icon_path(account, NULL);
1375
                        }
1376
                }
1377
                else if ((filename = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon")) && icon_change)
1378
                {
1379
                        size_t len;
1380
                        gpointer data = pidgin_convert_buddy_icon(dialog->plugin, filename, &len);
1381
                        purple_account_set_buddy_icon_path(account, filename);
1382
                        purple_buddy_icons_set_account_icon(account, data, len);
1383
                }
1384
        }
1385

    
1386

    
1387
        /* Remember Password */
1388
        purple_account_set_remember_password(account,
1389
                        gtk_toggle_button_get_active(
1390
                                        GTK_TOGGLE_BUTTON(dialog->remember_pass_check)));
1391

    
1392
        /* Check Mail */
1393
        if (dialog->prpl_info && dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK)
1394
                purple_account_set_check_mail(account,
1395
                        gtk_toggle_button_get_active(
1396
                                        GTK_TOGGLE_BUTTON(dialog->new_mail_check)));
1397

    
1398
        /* Password */
1399
        value = gtk_entry_get_text(GTK_ENTRY(dialog->password_entry));
1400

    
1401
        /*
1402
         * We set the password if this is a new account because new accounts
1403
         * will be set to online, and if the user has entered a password into
1404
         * the account editor (but has not checked the 'save' box), then we
1405
         * don't want to prompt them.
1406
         */
1407
        if ((purple_account_get_remember_password(account) || new_acct) && (*value != '\0'))
1408
                purple_account_set_password(account, value);
1409
        else
1410
                purple_account_set_password(account, NULL);
1411

    
1412
        purple_account_set_username(account, username);
1413
        g_free(username);
1414

    
1415
        /* Add the protocol settings */
1416
        if (dialog->prpl_info) {
1417
                ProtocolOptEntry *opt_entry;
1418
                GtkTreeIter iter;
1419
                char *value2;
1420
                int int_value;
1421
                gboolean bool_value;
1422

    
1423
                for (l2 = dialog->protocol_opt_entries; l2; l2 = l2->next) {
1424

    
1425
                        opt_entry = l2->data;
1426

    
1427
                        switch (opt_entry->type) {
1428
                                case PURPLE_PREF_STRING:
1429
                                        value = gtk_entry_get_text(GTK_ENTRY(opt_entry->widget));
1430
                                        purple_account_set_string(account, opt_entry->setting, value);
1431
                                        break;
1432

    
1433
                                case PURPLE_PREF_INT:
1434
                                        int_value = atoi(gtk_entry_get_text(GTK_ENTRY(opt_entry->widget)));
1435
                                        purple_account_set_int(account, opt_entry->setting, int_value);
1436
                                        break;
1437

    
1438
                                case PURPLE_PREF_BOOLEAN:
1439
                                        bool_value =
1440
                                                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opt_entry->widget));
1441
                                        purple_account_set_bool(account, opt_entry->setting, bool_value);
1442
                                        break;
1443

    
1444
                                case PURPLE_PREF_STRING_LIST:
1445
                                        value2 = NULL;
1446
                                        if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(opt_entry->widget), &iter))
1447
                                                gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(opt_entry->widget)), &iter, 1, &value2, -1);
1448
                                        purple_account_set_string(account, opt_entry->setting, value2);
1449
                                        break;
1450

    
1451
                                default:
1452
                                        break;
1453
                        }
1454
                }
1455
        }
1456

    
1457
        /* Set the proxy stuff. */
1458
        proxy_info = purple_account_get_proxy_info(account);
1459

    
1460
        /* Create the proxy info if it doesn't exist. */
1461
        if (proxy_info == NULL) {
1462
                proxy_info = purple_proxy_info_new();
1463
                purple_account_set_proxy_info(account, proxy_info);
1464
        }
1465

    
1466
        /* Set the proxy info type. */
1467
        purple_proxy_info_set_type(proxy_info, dialog->new_proxy_type);
1468

    
1469
        /* Host */
1470
        value = gtk_entry_get_text(GTK_ENTRY(dialog->proxy_host_entry));
1471

    
1472
        if (*value != '\0')
1473
                purple_proxy_info_set_host(proxy_info, value);
1474
        else
1475
                purple_proxy_info_set_host(proxy_info, NULL);
1476

    
1477
        /* Port */
1478
        value = gtk_entry_get_text(GTK_ENTRY(dialog->proxy_port_entry));
1479

    
1480
        if (*value != '\0')
1481
                purple_proxy_info_set_port(proxy_info, atoi(value));
1482
        else
1483
                purple_proxy_info_set_port(proxy_info, 0);
1484

    
1485
        /* Username */
1486
        value = gtk_entry_get_text(GTK_ENTRY(dialog->proxy_user_entry));
1487

    
1488
        if (*value != '\0')
1489
                purple_proxy_info_set_username(proxy_info, value);
1490
        else
1491
                purple_proxy_info_set_username(proxy_info, NULL);
1492

    
1493
        /* Password */
1494
        value = gtk_entry_get_text(GTK_ENTRY(dialog->proxy_pass_entry));
1495

    
1496
        if (*value != '\0')
1497
                purple_proxy_info_set_password(proxy_info, value);
1498
        else
1499
                purple_proxy_info_set_password(proxy_info, NULL);
1500

    
1501
        /* If there are no values set then proxy_info NULL */
1502
        if ((purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL) &&
1503
                (purple_proxy_info_get_host(proxy_info) == NULL) &&
1504
                (purple_proxy_info_get_port(proxy_info) == 0) &&
1505
                (purple_proxy_info_get_username(proxy_info) == NULL) &&
1506
                (purple_proxy_info_get_password(proxy_info) == NULL))
1507
        {
1508
                purple_account_set_proxy_info(account, NULL);
1509
                proxy_info = NULL;
1510
        }
1511

    
1512
        /* Voice and Video settings */
1513
        if (dialog->voice_frame) {
1514
                purple_account_set_silence_suppression(account,
1515
                                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->suppression_check)));
1516
        }
1517

    
1518
        /* If this is a new account, add it to our list */
1519
        if (new_acct)
1520
                purple_accounts_add(account);
1521
        else
1522
                purple_signal_emit(pidgin_account_get_handle(), "account-modified", account);
1523

    
1524
        /* If this is a new account, then sign on! */
1525
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->register_button))) {
1526
                purple_account_register(account);
1527
        } else if (new_acct) {
1528
                const PurpleSavedStatus *saved_status;
1529

    
1530
                saved_status = purple_savedstatus_get_current();
1531
                if (saved_status != NULL) {
1532
                        purple_savedstatus_activate_for_account(saved_status, account);
1533
                        purple_account_set_enabled(account, PIDGIN_UI, TRUE);
1534
                }
1535
        }
1536

    
1537
        /* We no longer need the data from the dialog window */
1538
        account_win_destroy_cb(NULL, NULL, dialog);
1539

    
1540
}
1541

    
1542
static const GtkTargetEntry dnd_targets[] = {
1543
        {"text/plain", 0, 0},
1544
        {"text/uri-list", 0, 1},
1545
        {"STRING", 0, 2}
1546
};
1547

    
1548
void
1549
pidgin_account_dialog_show(PidginAccountDialogType type,
1550
                                                         PurpleAccount *account)
1551
{
1552
        AccountPrefsDialog *dialog;
1553
        GtkWidget *win;
1554
        GtkWidget *main_vbox;
1555
        GtkWidget *vbox;
1556
        GtkWidget *dbox;
1557
        GtkWidget *notebook;
1558
        GtkWidget *button;
1559

    
1560
        if (accounts_window != NULL && account != NULL &&
1561
                (dialog = g_hash_table_lookup(account_pref_wins, account)) != NULL)
1562
        {
1563
                gtk_window_present(GTK_WINDOW(dialog->window));
1564
                return;
1565
        }
1566

    
1567
        dialog = g_new0(AccountPrefsDialog, 1);
1568

    
1569
        if (accounts_window != NULL && account != NULL)
1570
        {
1571
                g_hash_table_insert(account_pref_wins, account, dialog);
1572
        }
1573

    
1574
        dialog->account = account;
1575
        dialog->type    = type;
1576
        dialog->sg      = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1577

    
1578
        if (dialog->account == NULL) {
1579
                /* Select the first prpl in the list*/
1580
                GList *prpl_list = purple_plugins_get_protocols();
1581
                if (prpl_list != NULL)
1582
                        dialog->protocol_id = g_strdup(((PurplePlugin *) prpl_list->data)->info->id);
1583
        }
1584
        else
1585
        {
1586
                dialog->protocol_id =
1587
                        g_strdup(purple_account_get_protocol_id(dialog->account));
1588
        }
1589

    
1590
        if ((dialog->plugin = purple_find_prpl(dialog->protocol_id)) != NULL)
1591
                dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin);
1592

    
1593
        dialog->window = win = pidgin_create_dialog((type == PIDGIN_ADD_ACCOUNT_DIALOG) ? _("Add Account") : _("Modify Account"),
1594
                PIDGIN_HIG_BOX_SPACE, "account", FALSE);
1595

    
1596
        g_signal_connect(G_OBJECT(win), "delete_event",
1597
                                         G_CALLBACK(account_win_destroy_cb), dialog);
1598

    
1599
        /* Setup the vbox */
1600
        main_vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win), FALSE, PIDGIN_HIG_BOX_SPACE);
1601

    
1602
        dialog->notebook = notebook = gtk_notebook_new();
1603
        gtk_box_pack_start(GTK_BOX(main_vbox), notebook, FALSE, FALSE, 0);
1604
        gtk_widget_show(GTK_WIDGET(notebook));
1605

    
1606
        /* Setup the inner vbox */
1607
        dialog->top_vbox = vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
1608
        gtk_container_set_border_width(GTK_CONTAINER(vbox), PIDGIN_HIG_BORDER);
1609
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox,
1610
                        gtk_label_new_with_mnemonic(_("_Basic")));
1611
        gtk_widget_show(vbox);
1612

    
1613
        /* Setup the top frames. */
1614
        add_login_options(dialog, vbox);
1615
        add_user_options(dialog, vbox);
1616

    
1617
        button = gtk_check_button_new_with_mnemonic(
1618
                _("Create _this new account on the server"));
1619
        gtk_box_pack_start(GTK_BOX(main_vbox), button, FALSE, FALSE, 0);
1620
        gtk_widget_show(button);
1621
        dialog->register_button = button;
1622
        if (dialog->account == NULL)
1623
                gtk_widget_set_sensitive(button, FALSE);
1624

    
1625
        if (!dialog->prpl_info || !dialog->prpl_info->register_user)
1626
                gtk_widget_hide(button);
1627

    
1628
        /* Setup the page with 'Advanced' (protocol options). */
1629
        add_protocol_options(dialog);
1630

    
1631
        /* Setup the page with 'Proxy'. */
1632
        dbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
1633
        gtk_container_set_border_width(GTK_CONTAINER(dbox), PIDGIN_HIG_BORDER);
1634
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dbox,
1635
                        gtk_label_new_with_mnemonic(_("P_roxy")));
1636
        gtk_widget_show(dbox);
1637
        add_proxy_options(dialog, dbox);
1638

    
1639
        add_voice_options(dialog);
1640

    
1641
        /* Cancel button */
1642
        pidgin_dialog_add_button(GTK_DIALOG(win), GTK_STOCK_CANCEL, G_CALLBACK(cancel_account_prefs_cb), dialog);
1643

    
1644
        /* Save button */
1645
        button = pidgin_dialog_add_button(GTK_DIALOG(win),
1646
                                          (type == PIDGIN_ADD_ACCOUNT_DIALOG) ? GTK_STOCK_ADD : GTK_STOCK_SAVE,
1647
                                          G_CALLBACK(ok_account_prefs_cb),
1648
                                          dialog);
1649
        if (dialog->account == NULL)
1650
                gtk_widget_set_sensitive(button, FALSE);
1651
        dialog->ok_button = button;
1652

    
1653
        /* Set up DND */
1654
        gtk_drag_dest_set(dialog->window,
1655
                          GTK_DEST_DEFAULT_MOTION |
1656
                          GTK_DEST_DEFAULT_DROP,
1657
                          dnd_targets,
1658
                          sizeof(dnd_targets) / sizeof(GtkTargetEntry),
1659
                          GDK_ACTION_COPY);
1660

    
1661
        g_signal_connect(G_OBJECT(dialog->window), "drag_data_received",
1662
                         G_CALLBACK(account_dnd_recv), dialog);
1663

    
1664
        /* Show the window. */
1665
        gtk_widget_show(win);
1666
        if (!account)
1667
                gtk_widget_grab_focus(dialog->protocol_menu);
1668
}
1669

    
1670
/**************************************************************************
1671
 * Accounts Dialog
1672
 **************************************************************************/
1673
static void
1674
signed_on_off_cb(PurpleConnection *gc, gpointer user_data)
1675
{
1676
        PurpleAccount *account;
1677
        GtkTreeModel *model;
1678
        GtkTreeIter iter;
1679
        GdkPixbuf *pixbuf;
1680
        size_t index;
1681

    
1682
        /* Don't need to do anything if the accounts window is not visible */
1683
        if (accounts_window == NULL)
1684
                return;
1685

    
1686
        account = purple_connection_get_account(gc);
1687
        model = GTK_TREE_MODEL(accounts_window->model);
1688
        index = g_list_index(purple_accounts_get_all(), account);
1689

    
1690
        if (gtk_tree_model_iter_nth_child(model, &iter, NULL, index))
1691
        {
1692
                pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
1693
                if ((pixbuf != NULL) && purple_account_is_disconnected(account))
1694
                        gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
1695

    
1696
                gtk_list_store_set(accounts_window->model, &iter,
1697
                                   COLUMN_ICON, pixbuf,
1698
                                   -1);
1699

    
1700
                if (pixbuf != NULL)
1701
                        g_object_unref(G_OBJECT(pixbuf));
1702
        }
1703
}
1704

    
1705
/*
1706
 * Get the GtkTreeIter of the specified account in the
1707
 * GtkListStore
1708
 */
1709
static gboolean
1710
accounts_window_find_account_in_treemodel(GtkTreeIter *iter, PurpleAccount *account)
1711
{
1712
        GtkTreeModel *model;
1713
        PurpleAccount *cur;
1714

    
1715
        g_return_val_if_fail(account != NULL, FALSE);
1716
        g_return_val_if_fail(accounts_window != NULL, FALSE);
1717

    
1718
        model = GTK_TREE_MODEL(accounts_window->model);
1719

    
1720
        if (!gtk_tree_model_get_iter_first(model, iter))
1721
                return FALSE;
1722

    
1723
        gtk_tree_model_get(model, iter, COLUMN_DATA, &cur, -1);
1724
        if (cur == account)
1725
                return TRUE;
1726

    
1727
        while (gtk_tree_model_iter_next(model, iter))
1728
        {
1729
                gtk_tree_model_get(model, iter, COLUMN_DATA, &cur, -1);
1730
                if (cur == account)
1731
                        return TRUE;
1732
        }
1733

    
1734
        return FALSE;
1735
}
1736

    
1737
static void
1738
account_removed_cb(PurpleAccount *account, gpointer user_data)
1739
{
1740
        AccountPrefsDialog *dialog;
1741
        GtkTreeIter iter;
1742

    
1743
        /* If the account was being modified, close the edit window */
1744
        if ((dialog = g_hash_table_lookup(account_pref_wins, account)) != NULL)
1745
                account_win_destroy_cb(NULL, NULL, dialog);
1746

    
1747
        if (accounts_window == NULL)
1748
                return;
1749

    
1750
        /* Remove the account from the GtkListStore */
1751
        if (accounts_window_find_account_in_treemodel(&iter, account))
1752
                gtk_list_store_remove(accounts_window->model, &iter);
1753

    
1754
        if (purple_accounts_get_all() == NULL)
1755
                gtk_notebook_set_current_page(GTK_NOTEBOOK(accounts_window->notebook), 0);
1756
}
1757

    
1758
static void
1759
account_abled_cb(PurpleAccount *account, gpointer user_data)
1760
{
1761
        GtkTreeIter iter;
1762

    
1763
        if (accounts_window == NULL)
1764
                return;
1765

    
1766
        /* update the account in the GtkListStore */
1767
        if (accounts_window_find_account_in_treemodel(&iter, account))
1768
                gtk_list_store_set(accounts_window->model, &iter,
1769
                                                   COLUMN_ENABLED, GPOINTER_TO_INT(user_data),
1770
                                                   -1);
1771
}
1772

    
1773
static void
1774
drag_data_get_cb(GtkWidget *widget, GdkDragContext *ctx,
1775
                                 GtkSelectionData *data, guint info, guint time,
1776
                                 AccountsWindow *dialog)
1777
{
1778
        if (data->target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE)) {
1779
                GtkTreeRowReference *ref;
1780
                GtkTreePath *source_row;
1781
                GtkTreeIter iter;
1782
                PurpleAccount *account = NULL;
1783
                GValue val;
1784

    
1785
                ref = g_object_get_data(G_OBJECT(ctx), "gtk-tree-view-source-row");
1786
                source_row = gtk_tree_row_reference_get_path(ref);
1787

    
1788
                if (source_row == NULL)
1789
                        return;
1790

    
1791
                gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter,
1792
                                                                source_row);
1793
                val.g_type = 0;
1794
                gtk_tree_model_get_value(GTK_TREE_MODEL(dialog->model), &iter,
1795
                                                                 COLUMN_DATA, &val);
1796

    
1797
                dialog->drag_iter = iter;
1798

    
1799
                account = g_value_get_pointer(&val);
1800

    
1801
                gtk_selection_data_set(data, gdk_atom_intern("PURPLE_ACCOUNT", FALSE),
1802
                                                           8, (void *)&account, sizeof(account));
1803

    
1804
                gtk_tree_path_free(source_row);
1805
        }
1806
}
1807

    
1808
static void
1809
move_account_after(GtkListStore *store, GtkTreeIter *iter,
1810
                                   GtkTreeIter *position)
1811
{
1812
        GtkTreeIter new_iter;
1813
        PurpleAccount *account;
1814

    
1815
        gtk_tree_model_get(GTK_TREE_MODEL(store), iter,
1816
                                           COLUMN_DATA, &account,
1817
                                           -1);
1818

    
1819
        gtk_list_store_insert_after(store, &new_iter, position);
1820

    
1821
        set_account(store, &new_iter, account, NULL);
1822

    
1823
        gtk_list_store_remove(store, iter);
1824
}
1825

    
1826
static void
1827
move_account_before(GtkListStore *store, GtkTreeIter *iter,
1828
                                        GtkTreeIter *position)
1829
{
1830
        GtkTreeIter new_iter;
1831
        PurpleAccount *account;
1832

    
1833
        gtk_tree_model_get(GTK_TREE_MODEL(store), iter,
1834
                                           COLUMN_DATA, &account,
1835
                                           -1);
1836

    
1837
        gtk_list_store_insert_before(store, &new_iter, position);
1838

    
1839
        set_account(store, &new_iter, account, NULL);
1840

    
1841
        gtk_list_store_remove(store, iter);
1842
}
1843

    
1844
static void
1845
drag_data_received_cb(GtkWidget *widget, GdkDragContext *ctx,
1846
                                          guint x, guint y, GtkSelectionData *sd,
1847
                                          guint info, guint t, AccountsWindow *dialog)
1848
{
1849
        if (sd->target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE) && sd->data) {
1850
                gint dest_index;
1851
                PurpleAccount *a = NULL;
1852
                GtkTreePath *path = NULL;
1853
                GtkTreeViewDropPosition position;
1854

    
1855
                memcpy(&a, sd->data, sizeof(a));
1856

    
1857
                if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y,
1858
                                                                                          &path, &position)) {
1859

    
1860
                        GtkTreeIter iter;
1861
                        PurpleAccount *account;
1862
                        GValue val;
1863

    
1864
                        gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, path);
1865
                        val.g_type = 0;
1866
                        gtk_tree_model_get_value(GTK_TREE_MODEL(dialog->model), &iter,
1867
                                                                         COLUMN_DATA, &val);
1868

    
1869
                        account = g_value_get_pointer(&val);
1870

    
1871
                        switch (position) {
1872
                                case GTK_TREE_VIEW_DROP_AFTER:
1873
                                case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
1874
                                        move_account_after(dialog->model, &dialog->drag_iter,
1875
                                                                           &iter);
1876
                                        dest_index = g_list_index(purple_accounts_get_all(),
1877
                                                                                          account) + 1;
1878
                                        break;
1879

    
1880
                                case GTK_TREE_VIEW_DROP_BEFORE:
1881
                                case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
1882
                                        dest_index = g_list_index(purple_accounts_get_all(),
1883
                                                                                          account);
1884

    
1885
                                        move_account_before(dialog->model, &dialog->drag_iter,
1886
                                                                                &iter);
1887
                                        break;
1888

    
1889
                                default:
1890
                                        return;
1891
                        }
1892

    
1893
                        purple_accounts_reorder(a, dest_index);
1894
                }
1895
        }
1896
}
1897

    
1898
static gboolean
1899
accedit_win_destroy_cb(GtkWidget *w, GdkEvent *event, AccountsWindow *dialog)
1900
{
1901
        dialog->window = NULL;
1902

    
1903
        pidgin_accounts_window_hide();
1904

    
1905
        return FALSE;
1906
}
1907

    
1908
static void
1909
add_account_cb(GtkWidget *w, AccountsWindow *dialog)
1910
{
1911
        pidgin_account_dialog_show(PIDGIN_ADD_ACCOUNT_DIALOG, NULL);
1912
}
1913

    
1914
static void
1915
modify_account_sel(GtkTreeModel *model, GtkTreePath *path,
1916
                                   GtkTreeIter *iter, gpointer data)
1917
{
1918
        PurpleAccount *account;
1919

    
1920
        gtk_tree_model_get(model, iter, COLUMN_DATA, &account, -1);
1921

    
1922
        if (account != NULL)
1923
                pidgin_account_dialog_show(PIDGIN_MODIFY_ACCOUNT_DIALOG, account);
1924
}
1925

    
1926
static void
1927
modify_account_cb(GtkWidget *w, AccountsWindow *dialog)
1928
{
1929
        GtkTreeSelection *selection;
1930

    
1931
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
1932

    
1933
        gtk_tree_selection_selected_foreach(selection, modify_account_sel, dialog);
1934
}
1935

    
1936
static void
1937
delete_account_cb(PurpleAccount *account)
1938
{
1939
        purple_accounts_delete(account);
1940
}
1941

    
1942
static void
1943
ask_delete_account_sel(GtkTreeModel *model, GtkTreePath *path,
1944
                                           GtkTreeIter *iter, gpointer data)
1945
{
1946
        PurpleAccount *account;
1947

    
1948
        gtk_tree_model_get(model, iter, COLUMN_DATA, &account, -1);
1949

    
1950
        if (account != NULL) {
1951
                char *buf;
1952

    
1953
                buf = g_strdup_printf(_("Are you sure you want to delete %s?"),
1954
                                                          purple_account_get_username(account));
1955

    
1956
                purple_request_close_with_handle(account);
1957
                purple_request_action(account, NULL, buf, NULL,
1958
                                                        PURPLE_DEFAULT_ACTION_NONE,
1959
                                                        account, NULL, NULL,
1960
                                                        account, 2,
1961
                                                        _("Delete"), delete_account_cb,
1962
                                                        _("Cancel"), NULL);
1963
                g_free(buf);
1964
        }
1965
}
1966

    
1967
static void
1968
ask_delete_account_cb(GtkWidget *w, AccountsWindow *dialog)
1969
{
1970
        GtkTreeSelection *selection;
1971

    
1972
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
1973

    
1974
        gtk_tree_selection_selected_foreach(selection, ask_delete_account_sel,
1975
                                                                                dialog);
1976
}
1977

    
1978
static void
1979
close_accounts_cb(GtkWidget *w, AccountsWindow *dialog)
1980
{
1981
        pidgin_accounts_window_hide();
1982
}
1983

    
1984

    
1985
static void
1986
enabled_cb(GtkCellRendererToggle *renderer, gchar *path_str,
1987
                           gpointer data)
1988
{
1989
        AccountsWindow *dialog = (AccountsWindow *)data;
1990
        PurpleAccount *account;
1991
        GtkTreeModel *model = GTK_TREE_MODEL(dialog->model);
1992
        GtkTreeIter iter;
1993
        gboolean enabled;
1994
        const PurpleSavedStatus *saved_status;
1995

    
1996
        gtk_tree_model_get_iter_from_string(model, &iter, path_str);
1997
        gtk_tree_model_get(model, &iter,
1998
                                           COLUMN_DATA, &account,
1999
                                           COLUMN_ENABLED, &enabled,
2000
                                           -1);
2001

    
2002
        /*
2003
         * If we just enabled the account, then set the statuses
2004
         * to the current status.
2005
         */
2006
        if (!enabled)
2007
        {
2008
                saved_status = purple_savedstatus_get_current();
2009
                purple_savedstatus_activate_for_account(saved_status, account);
2010
        }
2011

    
2012
        purple_account_set_enabled(account, PIDGIN_UI, !enabled);
2013
}
2014

    
2015
static void
2016
add_columns(GtkWidget *treeview, AccountsWindow *dialog)
2017
{
2018
        GtkCellRenderer *renderer;
2019
        GtkTreeViewColumn *column;
2020

    
2021
        /* Enabled */
2022
        renderer = gtk_cell_renderer_toggle_new();
2023

    
2024
        g_signal_connect(G_OBJECT(renderer), "toggled",
2025
                         G_CALLBACK(enabled_cb), dialog);
2026

    
2027
        column = gtk_tree_view_column_new_with_attributes(_("Enabled"),
2028
                         renderer, "active", COLUMN_ENABLED, NULL);
2029

    
2030
        gtk_tree_view_column_set_resizable(column, FALSE);
2031
        gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
2032

    
2033
        /* Username column */
2034
        column = gtk_tree_view_column_new();
2035
        gtk_tree_view_column_set_title(column, _("Username"));
2036
        gtk_tree_view_column_set_resizable(column, TRUE);
2037
        gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
2038

    
2039
        /* Buddy Icon */
2040
        renderer = gtk_cell_renderer_pixbuf_new();
2041
        gtk_tree_view_column_pack_start(column, renderer, FALSE);
2042
        gtk_tree_view_column_add_attribute(column, renderer,
2043
                                           "pixbuf", COLUMN_BUDDYICON);
2044

    
2045
        /* Username */
2046
        renderer = gtk_cell_renderer_text_new();
2047
        gtk_tree_view_column_pack_start(column, renderer, TRUE);
2048
        gtk_tree_view_column_add_attribute(column, renderer,
2049
                                           "text", COLUMN_USERNAME);
2050
        dialog->username_col = column;
2051

    
2052

    
2053
        /* Protocol name */
2054
        column = gtk_tree_view_column_new();
2055
        gtk_tree_view_column_set_title(column, _("Protocol"));
2056
        gtk_tree_view_column_set_resizable(column, FALSE);
2057
        gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
2058

    
2059
        /* Icon */
2060
        renderer = gtk_cell_renderer_pixbuf_new();
2061
        gtk_tree_view_column_pack_start(column, renderer, FALSE);
2062
        gtk_tree_view_column_add_attribute(column, renderer,
2063
                                           "pixbuf", COLUMN_ICON);
2064

    
2065
        renderer = gtk_cell_renderer_text_new();
2066
        gtk_tree_view_column_pack_start(column, renderer, TRUE);
2067
        gtk_tree_view_column_add_attribute(column, renderer,
2068
                                           "text", COLUMN_PROTOCOL);
2069
}
2070

    
2071
static void
2072
set_account(GtkListStore *store, GtkTreeIter *iter, PurpleAccount *account, GdkPixbuf *global_buddyicon)
2073
{
2074
        GdkPixbuf *pixbuf, *buddyicon = NULL;
2075
        PurpleStoredImage *img = NULL;
2076
        PurplePlugin *prpl;
2077
        PurplePluginProtocolInfo *prpl_info = NULL;
2078

    
2079
        pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
2080
        if ((pixbuf != NULL) && purple_account_is_disconnected(account))
2081
                gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
2082

    
2083
        prpl = purple_find_prpl(purple_account_get_protocol_id(account));
2084
        if (prpl != NULL)
2085
                prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
2086
        if (prpl_info != NULL && prpl_info->icon_spec.format != NULL) {
2087
                if (purple_account_get_bool(account, "use-global-buddyicon", TRUE)) {
2088
                        if (global_buddyicon != NULL)
2089
                                buddyicon = g_object_ref(G_OBJECT(global_buddyicon));
2090
                        else {
2091
                                /* This is for when set_account() is called for a single account */
2092
                                const char *path;
2093
                                path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon");
2094
                                if ((path != NULL) && (*path != '\0')) {
2095
                                        img = purple_imgstore_new_from_file(path);
2096
                                }
2097
                        }
2098
                } else {
2099
                        img = purple_buddy_icons_find_account_icon(account);
2100
                }
2101
        }
2102

    
2103
        if (img != NULL) {
2104
                GdkPixbuf *buddyicon_pixbuf;
2105
                buddyicon_pixbuf = pidgin_pixbuf_from_imgstore(img);
2106
                purple_imgstore_unref(img);
2107

    
2108
                if (buddyicon_pixbuf != NULL) {
2109
                        buddyicon = gdk_pixbuf_scale_simple(buddyicon_pixbuf, 22, 22, GDK_INTERP_HYPER);
2110
                        g_object_unref(G_OBJECT(buddyicon_pixbuf));
2111
                }
2112
        }
2113

    
2114
        gtk_list_store_set(store, iter,
2115
                        COLUMN_ICON, pixbuf,
2116
                        COLUMN_BUDDYICON, buddyicon,
2117
                        COLUMN_USERNAME, purple_account_get_username(account),
2118
                        COLUMN_ENABLED, purple_account_get_enabled(account, PIDGIN_UI),
2119
                        COLUMN_PROTOCOL, purple_account_get_protocol_name(account),
2120
                        COLUMN_DATA, account,
2121
                        -1);
2122

    
2123
        if (pixbuf != NULL)
2124
                g_object_unref(G_OBJECT(pixbuf));
2125
        if (buddyicon != NULL)
2126
                g_object_unref(G_OBJECT(buddyicon));
2127
}
2128

    
2129
static void
2130
add_account_to_liststore(PurpleAccount *account, gpointer user_data)
2131
{
2132
        GtkTreeIter iter;
2133
        GdkPixbuf *global_buddyicon = user_data;
2134

    
2135
        if (accounts_window == NULL)
2136
                return;
2137

    
2138
        gtk_list_store_append(accounts_window->model, &iter);
2139
        gtk_notebook_set_current_page(GTK_NOTEBOOK(accounts_window->notebook),1);
2140

    
2141
        set_account(accounts_window->model, &iter, account, global_buddyicon);
2142
}
2143

    
2144
static gboolean
2145
populate_accounts_list(AccountsWindow *dialog)
2146
{
2147
        GList *l;
2148
        gboolean ret = FALSE;
2149
        GdkPixbuf *global_buddyicon = NULL;
2150
        const char *path;
2151

    
2152
        gtk_list_store_clear(dialog->model);
2153

    
2154
        if ((path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon")) != NULL) {
2155
                GdkPixbuf *pixbuf = pidgin_pixbuf_new_from_file(path);
2156
                if (pixbuf != NULL) {
2157
                        global_buddyicon = gdk_pixbuf_scale_simple(pixbuf, 22, 22, GDK_INTERP_HYPER);
2158
                        g_object_unref(G_OBJECT(pixbuf));
2159
                }
2160
        }
2161

    
2162
        for (l = purple_accounts_get_all(); l != NULL; l = l->next) {
2163
                ret = TRUE;
2164
                add_account_to_liststore((PurpleAccount *)l->data, global_buddyicon);
2165
        }
2166

    
2167
        if (global_buddyicon != NULL)
2168
                g_object_unref(G_OBJECT(global_buddyicon));
2169

    
2170
        return ret;
2171
}
2172

    
2173
static void
2174
account_selected_cb(GtkTreeSelection *sel, AccountsWindow *dialog)
2175
{
2176
        gboolean selected = FALSE;
2177

    
2178
        selected = (gtk_tree_selection_count_selected_rows(sel) > 0);
2179

    
2180
        gtk_widget_set_sensitive(dialog->modify_button, selected);
2181
        gtk_widget_set_sensitive(dialog->delete_button, selected);
2182
}
2183

    
2184
static gboolean
2185
account_treeview_double_click_cb(GtkTreeView *treeview, GdkEventButton *event, gpointer user_data)
2186
{
2187
        AccountsWindow *dialog;
2188
        GtkTreePath *path;
2189
        GtkTreeViewColumn *column;
2190
        GtkTreeIter iter;
2191
        PurpleAccount *account;
2192

    
2193
        dialog = (AccountsWindow *)user_data;
2194

    
2195
        if (event->window != gtk_tree_view_get_bin_window(treeview))
2196
            return FALSE;
2197

    
2198
        /* Figure out which node was clicked */
2199
        if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(dialog->treeview), event->x, event->y, &path, &column, NULL, NULL))
2200
                return FALSE;
2201
        if (column == gtk_tree_view_get_column(treeview, 0)) {
2202
                gtk_tree_path_free(path);
2203
                return FALSE;
2204
        }
2205

    
2206
        gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, path);
2207
        gtk_tree_path_free(path);
2208
        gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter, COLUMN_DATA, &account, -1);
2209

    
2210
        if ((account != NULL) && (event->button == 1) &&
2211
                (event->type == GDK_2BUTTON_PRESS))
2212
        {
2213
                pidgin_account_dialog_show(PIDGIN_MODIFY_ACCOUNT_DIALOG, account);
2214
                return TRUE;
2215
        }
2216

    
2217
        return FALSE;
2218
}
2219

    
2220
static GtkWidget *
2221
create_accounts_list(AccountsWindow *dialog)
2222
{
2223
        GtkWidget *frame;
2224
        GtkWidget *label;
2225
        GtkWidget *treeview;
2226
        GtkTreeSelection *sel;
2227
        GtkTargetEntry gte[] = {{"PURPLE_ACCOUNT", GTK_TARGET_SAME_APP, 0}};
2228
        char *pretty, *tmp;
2229

    
2230
        frame = gtk_frame_new(NULL);
2231
        gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
2232

    
2233
        accounts_window->notebook = gtk_notebook_new();
2234
        gtk_notebook_set_show_tabs(GTK_NOTEBOOK(accounts_window->notebook), FALSE);
2235
        gtk_notebook_set_show_border(GTK_NOTEBOOK(accounts_window->notebook), FALSE);
2236
        gtk_container_add(GTK_CONTAINER(frame), accounts_window->notebook);
2237

    
2238
        /* Create a helpful first-time-use label */
2239
        label = gtk_label_new(NULL);
2240
        /* Translators: Please maintain the use of -> or <- to represent the menu heirarchy */
2241
        tmp = g_strdup_printf(_(
2242
                                                 "<span size='larger' weight='bold'>Welcome to %s!</span>\n\n"
2243

    
2244
                                                 "You have no IM accounts configured. To start connecting with %s "
2245
                                                 "press the <b>Add...</b> button below and configure your first "
2246
                                                 "account. If you want %s to connect to multiple IM accounts, "
2247
                                                 "press <b>Add...</b> again to configure them all.\n\n"
2248

    
2249
                                                 "You can come back to this window to add, edit, or remove "
2250
                                                 "accounts from <b>Accounts->Manage Accounts</b> in the Buddy "
2251
                                                 "List window"), PIDGIN_NAME, PIDGIN_NAME, PIDGIN_NAME);
2252
        pretty = pidgin_make_pretty_arrows(tmp);
2253
        g_free(tmp);
2254
        gtk_label_set_markup(GTK_LABEL(label), pretty);
2255
        g_free(pretty);
2256

    
2257
        gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
2258
        gtk_widget_show(label);
2259

    
2260
        gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
2261
        gtk_notebook_append_page(GTK_NOTEBOOK(accounts_window->notebook), label, NULL);
2262

    
2263
        /* Create the list model. */
2264
        dialog->model = gtk_list_store_new(NUM_COLUMNS,
2265
                                        GDK_TYPE_PIXBUF,   /* COLUMN_ICON */
2266
                                        GDK_TYPE_PIXBUF,   /* COLUMN_BUDDYICON */
2267
                                        G_TYPE_STRING,     /* COLUMN_USERNAME */
2268
                                        G_TYPE_BOOLEAN,    /* COLUMN_ENABLED */
2269
                                        G_TYPE_STRING,     /* COLUMN_PROTOCOL */
2270
                                        G_TYPE_POINTER     /* COLUMN_DATA */
2271
                                        );
2272

    
2273
        /* And now the actual treeview */
2274
        treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
2275
        dialog->treeview = treeview;
2276
        gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
2277
        g_object_unref(G_OBJECT(dialog->model));
2278

    
2279
        sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
2280
        gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
2281
        g_signal_connect(G_OBJECT(sel), "changed",
2282
                                         G_CALLBACK(account_selected_cb), dialog);
2283

    
2284
        /* Handle double-clicking */
2285
        g_signal_connect(G_OBJECT(treeview), "button_press_event",
2286
                                         G_CALLBACK(account_treeview_double_click_cb), dialog);
2287

    
2288
        gtk_notebook_append_page(GTK_NOTEBOOK(accounts_window->notebook),
2289
                pidgin_make_scrollable(treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_NONE, -1, -1),
2290
                NULL);
2291

    
2292
        add_columns(treeview, dialog);
2293
        gtk_tree_view_columns_autosize(GTK_TREE_VIEW(treeview));
2294

    
2295
        if (populate_accounts_list(dialog))
2296
                gtk_notebook_set_current_page(GTK_NOTEBOOK(accounts_window->notebook), 1);
2297
        else
2298
                gtk_notebook_set_current_page(GTK_NOTEBOOK(accounts_window->notebook), 0);
2299

    
2300
        /* Setup DND. I wanna be an orc! */
2301
        gtk_tree_view_enable_model_drag_source(
2302
                        GTK_TREE_VIEW(treeview), GDK_BUTTON1_MASK, gte,
2303
                        1, GDK_ACTION_COPY);
2304
        gtk_tree_view_enable_model_drag_dest(
2305
                        GTK_TREE_VIEW(treeview), gte, 1,
2306
                        GDK_ACTION_COPY | GDK_ACTION_MOVE);
2307

    
2308
        g_signal_connect(G_OBJECT(treeview), "drag-data-received",
2309
                                         G_CALLBACK(drag_data_received_cb), dialog);
2310
        g_signal_connect(G_OBJECT(treeview), "drag-data-get",
2311
                                         G_CALLBACK(drag_data_get_cb), dialog);
2312

    
2313
        gtk_widget_show_all(frame);
2314
        return frame;
2315
}
2316

    
2317
static void
2318
account_modified_cb(PurpleAccount *account, AccountsWindow *window)
2319
{
2320
        GtkTreeIter iter;
2321

    
2322
        if (!accounts_window_find_account_in_treemodel(&iter, account))
2323
                return;
2324

    
2325
        set_account(window->model, &iter, account, NULL);
2326
}
2327

    
2328
static void
2329
global_buddyicon_changed(const char *name, PurplePrefType type,
2330
                        gconstpointer value, gpointer window)
2331
{
2332
        GList *list;
2333
        for (list = purple_accounts_get_all(); list; list = list->next) {
2334
                account_modified_cb(list->data, window);
2335
        }
2336
}
2337

    
2338
void
2339
pidgin_accounts_window_show(void)
2340
{
2341
        AccountsWindow *dialog;
2342
        GtkWidget *win;
2343
        GtkWidget *vbox;
2344
        GtkWidget *sw;
2345
        GtkWidget *button;
2346
        int width, height;
2347

    
2348
        if (accounts_window != NULL) {
2349
                gtk_window_present(GTK_WINDOW(accounts_window->window));
2350
                return;
2351
        }
2352

    
2353
        accounts_window = dialog = g_new0(AccountsWindow, 1);
2354

    
2355
        width  = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/accounts/dialog/width");
2356
        height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/accounts/dialog/height");
2357

    
2358
        dialog->window = win = pidgin_create_dialog(_("Accounts"), PIDGIN_HIG_BORDER, "accounts", TRUE);
2359
        gtk_window_set_default_size(GTK_WINDOW(win), width, height);
2360

    
2361
        g_signal_connect(G_OBJECT(win), "delete_event",
2362
                                         G_CALLBACK(accedit_win_destroy_cb), accounts_window);
2363

    
2364
        /* Setup the vbox */
2365
        vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win), FALSE, PIDGIN_HIG_BORDER);
2366

    
2367
        /* Setup the scrolled window that will contain the list of accounts. */
2368
        sw = create_accounts_list(dialog);
2369
        gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
2370
        gtk_widget_show(sw);
2371

    
2372
        /* Add button */
2373
        pidgin_dialog_add_button(GTK_DIALOG(win), PIDGIN_STOCK_ADD, G_CALLBACK(add_account_cb), dialog);
2374

    
2375
        /* Modify button */
2376
        button = pidgin_dialog_add_button(GTK_DIALOG(win), PIDGIN_STOCK_MODIFY, G_CALLBACK(modify_account_cb), dialog);
2377
        dialog->modify_button = button;
2378
        gtk_widget_set_sensitive(button, FALSE);
2379

    
2380
        /* Delete button */
2381
        button = pidgin_dialog_add_button(GTK_DIALOG(win), GTK_STOCK_DELETE, G_CALLBACK(ask_delete_account_cb), dialog);
2382
        dialog->delete_button = button;
2383
        gtk_widget_set_sensitive(button, FALSE);
2384

    
2385
        /* Close button */
2386
        pidgin_dialog_add_button(GTK_DIALOG(win), GTK_STOCK_CLOSE, G_CALLBACK(close_accounts_cb), dialog);
2387

    
2388
        purple_signal_connect(pidgin_account_get_handle(), "account-modified",
2389
                            accounts_window,
2390
                            PURPLE_CALLBACK(account_modified_cb), accounts_window);
2391
        purple_prefs_connect_callback(accounts_window,
2392
                            PIDGIN_PREFS_ROOT "/accounts/buddyicon",
2393
                            global_buddyicon_changed, accounts_window);
2394

    
2395
        gtk_widget_show(win);
2396
}
2397

    
2398
void
2399
pidgin_accounts_window_hide(void)
2400
{
2401
        if (accounts_window == NULL)
2402
                return;
2403

    
2404
        if (accounts_window->window != NULL)
2405
                gtk_widget_destroy(accounts_window->window);
2406

    
2407
        purple_signals_disconnect_by_handle(accounts_window);
2408
        purple_prefs_disconnect_by_handle(accounts_window);
2409

    
2410
        g_free(accounts_window);
2411
        accounts_window = NULL;
2412
}
2413

    
2414
static void
2415
free_add_user_data(PidginAccountAddUserData *data)
2416
{
2417
        g_free(data->username);
2418
        g_free(data->alias);
2419
        g_free(data);
2420
}
2421

    
2422
static void
2423
add_user_cb(PidginAccountAddUserData *data)
2424
{
2425
        PurpleConnection *gc = purple_account_get_connection(data->account);
2426

    
2427
        if (g_list_find(purple_connections_get_all(), gc))
2428
        {
2429
                purple_blist_request_add_buddy(data->account, data->username,
2430
                                                                         NULL, data->alias);
2431
        }
2432

    
2433
        free_add_user_data(data);
2434
}
2435

    
2436
static char *
2437
make_info(PurpleAccount *account, PurpleConnection *gc, const char *remote_user,
2438
          const char *id, const char *alias, const char *msg)
2439
{
2440
        if (msg != NULL && *msg == '\0')
2441
                msg = NULL;
2442

    
2443
        return g_strdup_printf(_("%s%s%s%s has made %s his or her buddy%s%s"),
2444
                               remote_user,
2445
                               (alias != NULL ? " ("  : ""),
2446
                               (alias != NULL ? alias : ""),
2447
                               (alias != NULL ? ")"   : ""),
2448
                               (id != NULL
2449
                                ? id
2450
                                : (purple_connection_get_display_name(gc) != NULL
2451
                                   ? purple_connection_get_display_name(gc)
2452
                                   : purple_account_get_username(account))),
2453
                               (msg != NULL ? ": " : "."),
2454
                               (msg != NULL ? msg  : ""));
2455
}
2456

    
2457
static void
2458
pidgin_accounts_notify_added(PurpleAccount *account, const char *remote_user,
2459
                               const char *id, const char *alias,
2460
                               const char *msg)
2461
{
2462
        char *buffer;
2463
        PurpleConnection *gc;
2464
        GtkWidget *alert;
2465

    
2466
        gc = purple_account_get_connection(account);
2467

    
2468
        buffer = make_info(account, gc, remote_user, id, alias, msg);
2469
        alert = pidgin_make_mini_dialog(gc, PIDGIN_STOCK_DIALOG_INFO, buffer,
2470
                                          NULL, NULL, _("Close"), NULL, NULL);
2471
        pidgin_blist_add_alert(alert);
2472

    
2473
        g_free(buffer);
2474
}
2475

    
2476
static void
2477
pidgin_accounts_request_add(PurpleAccount *account, const char *remote_user,
2478
                              const char *id, const char *alias,
2479
                              const char *msg)
2480
{
2481
        char *buffer;
2482
        PurpleConnection *gc;
2483
        PidginAccountAddUserData *data;
2484
        GtkWidget *alert;
2485

    
2486
        gc = purple_account_get_connection(account);
2487

    
2488
        data = g_new0(PidginAccountAddUserData, 1);
2489
        data->account  = account;
2490
        data->username = g_strdup(remote_user);
2491
        data->alias    = g_strdup(alias);
2492

    
2493
        buffer = make_info(account, gc, remote_user, id, alias, msg);
2494
        alert = pidgin_make_mini_dialog(gc, PIDGIN_STOCK_DIALOG_QUESTION,
2495
                                          _("Add buddy to your list?"), buffer, data,
2496
                                          _("Add"), G_CALLBACK(add_user_cb),
2497
                                          _("Cancel"), G_CALLBACK(free_add_user_data), NULL);
2498
        pidgin_blist_add_alert(alert);
2499

    
2500
        g_free(buffer);
2501
}
2502

    
2503
struct auth_request
2504
{
2505
        PurpleAccountRequestAuthorizationCb auth_cb;
2506
        PurpleAccountRequestAuthorizationCb deny_cb;
2507
        void *data;
2508
        char *username;
2509
        char *alias;
2510
        PurpleAccount *account;
2511
        gboolean add_buddy_after_auth;
2512
};
2513

    
2514
static void
2515
free_auth_request(struct auth_request *ar)
2516
{
2517
        g_free(ar->username);
2518
        g_free(ar->alias);
2519
        g_free(ar);
2520
}
2521

    
2522
static void
2523
authorize_and_add_cb(struct auth_request *ar)
2524
{
2525
        ar->auth_cb(ar->data);
2526
        if (ar->add_buddy_after_auth) {
2527
                purple_blist_request_add_buddy(ar->account, ar->username, NULL, ar->alias);
2528
        }
2529
}
2530

    
2531
static void
2532
deny_no_add_cb(struct auth_request *ar)
2533
{
2534
        ar->deny_cb(ar->data);
2535
}
2536

    
2537
static gboolean
2538
get_user_info_cb(GtkWidget   *label,
2539
                 const gchar *uri,
2540
                 gpointer     data)
2541
{
2542
        struct auth_request *ar = data;
2543
        if (!strcmp(uri, "viewinfo")) {
2544
                pidgin_retrieve_user_info(purple_account_get_connection(ar->account), ar->username);
2545
                return TRUE;
2546
        }
2547
        return FALSE;
2548
}
2549

    
2550
static void
2551
send_im_cb(PidginMiniDialog *mini_dialog,
2552
           GtkButton *button,
2553
           gpointer data)
2554
{
2555
        struct auth_request *ar = data;
2556
        pidgin_dialogs_im_with_user(ar->account, ar->username);
2557
}
2558

    
2559
static void *
2560
pidgin_accounts_request_authorization(PurpleAccount *account,
2561
                                      const char *remote_user,
2562
                                      const char *id,
2563
                                      const char *alias,
2564
                                      const char *message,
2565
                                      gboolean on_list,
2566
                                      PurpleAccountRequestAuthorizationCb auth_cb,
2567
                                      PurpleAccountRequestAuthorizationCb deny_cb,
2568
                                      void *user_data)
2569
{
2570
        char *buffer;
2571
        PurpleConnection *gc;
2572
        GtkWidget *alert;
2573
        PidginMiniDialog *dialog;
2574
        GdkPixbuf *prpl_icon;
2575
        struct auth_request *aa;
2576
        const char *our_name;
2577
        gboolean have_valid_alias = alias && *alias;
2578

    
2579
        gc = purple_account_get_connection(account);
2580
        if (message != NULL && *message == '\0')
2581
                message = NULL;
2582

    
2583
        our_name = (id != NULL) ? id :
2584
                        (purple_connection_get_display_name(gc) != NULL) ? purple_connection_get_display_name(gc) :
2585
                        purple_account_get_username(account);
2586

    
2587
        if (pidgin_mini_dialog_links_supported()) {
2588
                char *escaped_remote_user = g_markup_escape_text(remote_user, -1);
2589
                char *escaped_alias = alias != NULL ? g_markup_escape_text(alias, -1) : g_strdup("");
2590
                char *escaped_our_name = g_markup_escape_text(our_name, -1);
2591
                char *escaped_message = message != NULL ? g_markup_escape_text(message, -1) : g_strdup("");
2592
                buffer = g_strdup_printf(_("<a href=\"viewinfo\">%s</a>%s%s%s wants to add you (%s) to his or her buddy list%s%s"),
2593
                                        escaped_remote_user,
2594
                                        (have_valid_alias ? " ("  : ""),
2595
                                        escaped_alias,
2596
                                        (have_valid_alias ? ")"   : ""),
2597
                                        escaped_our_name,
2598
                                        (have_valid_alias ? ": " : "."),
2599
                                        escaped_message);
2600
                g_free(escaped_remote_user);
2601
                g_free(escaped_alias);
2602
                g_free(escaped_our_name);
2603
                g_free(escaped_message);
2604
        } else {
2605
                buffer = g_strdup_printf(_("%s%s%s%s wants to add you (%s) to his or her buddy list%s%s"),
2606
                                        remote_user,
2607
                                        (have_valid_alias ? " ("  : ""),
2608
                                        (have_valid_alias ? alias : ""),
2609
                                        (have_valid_alias ? ")"   : ""),
2610
                                        our_name,
2611
                                        (message != NULL ? ": " : "."),
2612
                                        (message != NULL ? message  : ""));
2613
        }
2614

    
2615
        prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
2616

    
2617
        aa = g_new0(struct auth_request, 1);
2618
        aa->auth_cb = auth_cb;
2619
        aa->deny_cb = deny_cb;
2620
        aa->data = user_data;
2621
        aa->username = g_strdup(remote_user);
2622
        aa->alias = g_strdup(alias);
2623
        aa->account = account;
2624
        aa->add_buddy_after_auth = !on_list;
2625

    
2626
        alert = pidgin_make_mini_dialog_with_custom_icon(
2627
                gc, prpl_icon,
2628
                _("Authorize buddy?"), NULL, aa,
2629
                _("Authorize"), authorize_and_add_cb,
2630
                _("Deny"), deny_no_add_cb,
2631
                NULL);
2632

    
2633
        dialog = PIDGIN_MINI_DIALOG(alert);
2634
        if (pidgin_mini_dialog_links_supported()) {
2635
                pidgin_mini_dialog_enable_description_markup(dialog);
2636
                pidgin_mini_dialog_set_link_callback(dialog, G_CALLBACK(get_user_info_cb), aa);
2637
        }
2638
        pidgin_mini_dialog_set_description(dialog, buffer);
2639
        pidgin_mini_dialog_add_non_closing_button(dialog, _("Send Instant Message"), send_im_cb, aa);
2640

    
2641
        g_signal_connect_swapped(G_OBJECT(alert), "destroy", G_CALLBACK(free_auth_request), aa);
2642
        g_signal_connect(G_OBJECT(alert), "destroy", G_CALLBACK(purple_account_request_close), NULL);
2643
        pidgin_blist_add_alert(alert);
2644

    
2645
        g_free(buffer);
2646

    
2647
        return alert;
2648
}
2649

    
2650
static void
2651
pidgin_accounts_request_close(void *ui_handle)
2652
{
2653
        gtk_widget_destroy(GTK_WIDGET(ui_handle));
2654
}
2655

    
2656
static PurpleAccountUiOps ui_ops =
2657
{
2658
        pidgin_accounts_notify_added,
2659
        NULL,
2660
        pidgin_accounts_request_add,
2661
        pidgin_accounts_request_authorization,
2662
        pidgin_accounts_request_close,
2663
        NULL,
2664
        NULL,
2665
        NULL,
2666
        NULL
2667
};
2668

    
2669
PurpleAccountUiOps *
2670
pidgin_accounts_get_ui_ops(void)
2671
{
2672
        return &ui_ops;
2673
}
2674

    
2675
void *
2676
pidgin_account_get_handle(void) {
2677
        static int handle;
2678

    
2679
        return &handle;
2680
}
2681

    
2682
void
2683
pidgin_account_init(void)
2684
{
2685
        char *default_avatar = NULL;
2686
        purple_prefs_add_none(PIDGIN_PREFS_ROOT "/accounts");
2687
        purple_prefs_add_none(PIDGIN_PREFS_ROOT "/accounts/dialog");
2688
        purple_prefs_add_int(PIDGIN_PREFS_ROOT "/accounts/dialog/width",  520);
2689
        purple_prefs_add_int(PIDGIN_PREFS_ROOT "/accounts/dialog/height", 321);
2690
        default_avatar = g_build_filename(g_get_home_dir(), ".face.icon", NULL);
2691
        if (!g_file_test(default_avatar, G_FILE_TEST_EXISTS)) {
2692
                g_free(default_avatar);
2693
                default_avatar = g_build_filename(g_get_home_dir(), ".face", NULL);
2694
                if (!g_file_test(default_avatar, G_FILE_TEST_EXISTS)) {
2695
                        g_free(default_avatar);
2696
                        default_avatar = NULL;
2697
                }
2698
        }
2699

    
2700
        purple_prefs_add_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon", default_avatar);
2701
        g_free(default_avatar);
2702

    
2703
        purple_signal_register(pidgin_account_get_handle(), "account-modified",
2704
                                                 purple_marshal_VOID__POINTER, NULL, 1,
2705
                                                 purple_value_new(PURPLE_TYPE_SUBTYPE,
2706
                                                                                PURPLE_SUBTYPE_ACCOUNT));
2707

    
2708
        /* Setup some purple signal handlers. */
2709
        purple_signal_connect(purple_connections_get_handle(), "signed-on",
2710
                                                pidgin_account_get_handle(),
2711
                                                PURPLE_CALLBACK(signed_on_off_cb), NULL);
2712
        purple_signal_connect(purple_connections_get_handle(), "signed-off",
2713
                                                pidgin_account_get_handle(),
2714
                                                PURPLE_CALLBACK(signed_on_off_cb), NULL);
2715
        purple_signal_connect(purple_accounts_get_handle(), "account-added",
2716
                                                pidgin_account_get_handle(),
2717
                                                PURPLE_CALLBACK(add_account_to_liststore), NULL);
2718
        purple_signal_connect(purple_accounts_get_handle(), "account-removed",
2719
                                                pidgin_account_get_handle(),
2720
                                                PURPLE_CALLBACK(account_removed_cb), NULL);
2721
        purple_signal_connect(purple_accounts_get_handle(), "account-disabled",
2722
                                                pidgin_account_get_handle(),
2723
                                                PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(FALSE));
2724
        purple_signal_connect(purple_accounts_get_handle(), "account-enabled",
2725
                                                pidgin_account_get_handle(),
2726
                                                PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE));
2727

    
2728
        account_pref_wins =
2729
                g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
2730
}
2731

    
2732
void
2733
pidgin_account_uninit(void)
2734
{
2735
        /*
2736
         * TODO: Need to free all the dialogs in here.  Could probably create
2737
         *       a callback function to use for the free-some-data-function
2738
         *       parameter of g_hash_table_new_full, above.
2739
         */
2740
        g_hash_table_destroy(account_pref_wins);
2741

    
2742
        purple_signals_disconnect_by_handle(pidgin_account_get_handle());
2743
        purple_signals_unregister_by_instance(pidgin_account_get_handle());
2744
}
2745

    
2746