Statistics
| Revision:

root / src / account.c @ 1

History | View | Annotate | Download (24.7 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2004 Hiroyuki Yamamoto
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 */
19

    
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23

    
24
#include "defs.h"
25

    
26
#include <glib.h>
27
#include <gtk/gtk.h>
28
#include <gdk/gdkkeysyms.h>
29
#include <stdio.h>
30
#include <errno.h>
31

    
32
#include "intl.h"
33
#include "main.h"
34
#include "mainwindow.h"
35
#include "folderview.h"
36
#include "folder.h"
37
#include "account.h"
38
#include "prefs.h"
39
#include "prefs_account.h"
40
#include "procmsg.h"
41
#include "procheader.h"
42
#include "compose.h"
43
#include "manage_window.h"
44
#include "stock_pixmap.h"
45
#include "statusbar.h"
46
#include "inc.h"
47
#include "gtkutils.h"
48
#include "utils.h"
49
#include "alertpanel.h"
50

    
51
typedef enum
52
{
53
        COL_DEFAULT        = 0,
54
        COL_GETALL        = 1,
55
        COL_NAME        = 2,
56
        COL_PROTOCOL        = 3,
57
        COL_SERVER        = 4
58
} EditAccountColumnPos;
59

    
60
# define N_EDIT_ACCOUNT_COLS        5
61

    
62
#define PREFSBUFSIZE                1024
63

    
64
PrefsAccount *cur_account;
65

    
66
static GList *account_list = NULL;
67

    
68
static struct EditAccount {
69
        GtkWidget *window;
70
        GtkWidget *clist;
71
        GtkWidget *close_btn;
72
} edit_account;
73

    
74
static GdkPixmap *markxpm;
75
static GdkBitmap *markxpmmask;
76
static GdkPixmap *checkboxonxpm;
77
static GdkPixmap *checkboxonxpmmask;
78
static GdkPixmap *checkboxoffxpm;
79
static GdkPixmap *checkboxoffxpmmask;
80

    
81
static void account_edit_create                (void);
82

    
83
static void account_edit_prefs                (void);
84
static void account_delete                (void);
85

    
86
static void account_up                        (void);
87
static void account_down                (void);
88

    
89
static void account_set_default                (void);
90

    
91
static void account_edit_close                (void);
92
static gint account_delete_event        (GtkWidget        *widget,
93
                                         GdkEventAny        *event,
94
                                         gpointer         data);
95
static void account_selected                (GtkCList        *clist,
96
                                         gint                 row,
97
                                         gint                 column,
98
                                         GdkEvent        *event,
99
                                         gpointer         data);
100
static void account_row_moved                (GtkCList        *clist,
101
                                         gint                 source_row,
102
                                         gint                 dest_row);
103
static gboolean account_key_pressed        (GtkWidget        *widget,
104
                                         GdkEventKey        *event,
105
                                         gpointer         data);
106

    
107
static gint account_clist_set_row        (PrefsAccount        *ac_prefs,
108
                                         gint                 row);
109
static void account_clist_set                (void);
110

    
111
static void account_list_set                (void);
112

    
113
void account_read_config_all(void)
114
{
115
        GSList *ac_label_list = NULL, *cur;
116
        gchar *rcpath;
117
        FILE *fp;
118
        gchar buf[PREFSBUFSIZE];
119
        PrefsAccount *ac_prefs;
120

    
121
        debug_print(_("Reading all config for each account...\n"));
122

    
123
        rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, ACCOUNT_RC, NULL);
124
        if ((fp = fopen(rcpath, "rb")) == NULL) {
125
                if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
126
                g_free(rcpath);
127
                return;
128
        }
129
        g_free(rcpath);
130

    
131
        while (fgets(buf, sizeof(buf), fp) != NULL) {
132
                if (!strncmp(buf, "[Account: ", 10)) {
133
                        strretchomp(buf);
134
                        memmove(buf, buf + 1, strlen(buf));
135
                        buf[strlen(buf) - 1] = '\0';
136
                        debug_print(_("Found label: %s\n"), buf);
137
                        ac_label_list = g_slist_append(ac_label_list,
138
                                                       g_strdup(buf));
139
                }
140
        }
141
        fclose(fp);
142

    
143
        /* read config data from file */
144
        cur_account = NULL;
145
        for (cur = ac_label_list; cur != NULL; cur = cur->next) {
146
                ac_prefs = prefs_account_new();
147
                prefs_account_read_config(ac_prefs, (gchar *)cur->data);
148
                account_list = g_list_append(account_list, ac_prefs);
149
                if (ac_prefs->is_default)
150
                        cur_account = ac_prefs;
151
        }
152
        /* if default is not set, assume first account as default */
153
        if (!cur_account && account_list) {
154
                ac_prefs = (PrefsAccount *)account_list->data;
155
                account_set_as_default(ac_prefs);
156
                cur_account = ac_prefs;
157
        }
158

    
159
        account_set_menu();
160
        main_window_reflect_prefs_all();
161

    
162
        while (ac_label_list) {
163
                g_free(ac_label_list->data);
164
                ac_label_list = g_slist_remove(ac_label_list,
165
                                               ac_label_list->data);
166
        }
167
}
168

    
169
void account_write_config_all(void)
170
{
171
        prefs_account_write_config_all(account_list);
172
}
173

    
174
PrefsAccount *account_find_from_smtp_server(const gchar *address,
175
                                            const gchar *smtp_server)
176
{
177
        GList *cur;
178
        PrefsAccount *ac;
179

    
180
        g_return_val_if_fail(address != NULL, NULL);
181
        g_return_val_if_fail(smtp_server != NULL, NULL);
182

    
183
        for (cur = account_list; cur != NULL; cur = cur->next) {
184
                ac = (PrefsAccount *)cur->data;
185
                if (!strcmp2(address, ac->address) &&
186
                    !strcmp2(smtp_server, ac->smtp_server))
187
                        return ac;
188
        }
189

    
190
        return NULL;
191
}
192

    
193
/*
194
 * account_find_from_address:
195
 * @address: Email address string.
196
 *
197
 * Find a mail (not news) account with the specified email address.
198
 *
199
 * Return value: The found account, or NULL if not found.
200
 */
201
PrefsAccount *account_find_from_address(const gchar *address)
202
{
203
        GList *cur;
204
        PrefsAccount *ac;
205

    
206
        g_return_val_if_fail(address != NULL, NULL);
207

    
208
        for (cur = account_list; cur != NULL; cur = cur->next) {
209
                ac = (PrefsAccount *)cur->data;
210
                if (ac->protocol != A_NNTP && ac->address &&
211
                    strcasestr(address, ac->address) != NULL)
212
                        return ac;
213
        }
214

    
215
        return NULL;
216
}
217

    
218
PrefsAccount *account_find_from_id(gint id)
219
{
220
        GList *cur;
221
        PrefsAccount *ac;
222

    
223
        for (cur = account_list; cur != NULL; cur = cur->next) {
224
                ac = (PrefsAccount *)cur->data;
225
                if (id == ac->account_id)
226
                        return ac;
227
        }
228

    
229
        return NULL;
230
}
231

    
232
PrefsAccount *account_find_from_item(FolderItem *item)
233
{
234
        PrefsAccount *ac;
235

    
236
        g_return_val_if_fail(item != NULL, NULL);
237

    
238
        ac = item->account;
239
        if (!ac) {
240
                FolderItem *cur_item = item->parent;
241
                while (cur_item != NULL) {
242
                        if (cur_item->account && cur_item->ac_apply_sub) {
243
                                ac = cur_item->account;
244
                                break;
245
                        }
246
                        cur_item = cur_item->parent;
247
                }
248
        }
249
        if (!ac)
250
                ac = item->folder->account;
251

    
252
        return ac;
253
}
254

    
255
PrefsAccount *account_find_from_message_file(const gchar *file)
256
{
257
        static HeaderEntry hentry[] = {{"From:",                  NULL, FALSE},
258
                                       {"X-Sylpheed-Account-Id:", NULL, FALSE},
259
                                       {"AID:",                          NULL, FALSE}};
260

    
261
        enum
262
        {
263
                H_FROM                        = 0,
264
                H_X_SYLPHEED_ACCOUNT_ID = 1,
265
                H_AID                        = 2
266
        };
267

    
268
        PrefsAccount *ac = NULL;
269
        FILE *fp;
270
        gchar *str;
271
        gchar buf[BUFFSIZE];
272
        gint hnum;
273

    
274
        g_return_val_if_fail(file != NULL, NULL);
275

    
276
        if ((fp = fopen(file, "rb")) == NULL) {
277
                FILE_OP_ERROR(file, "fopen");
278
                return NULL;
279
        }
280

    
281
        while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, hentry))
282
               != -1) {
283
                str = buf + strlen(hentry[hnum].name);
284
                if (hnum == H_FROM)
285
                        ac = account_find_from_address(str);
286
                else if (hnum == H_X_SYLPHEED_ACCOUNT_ID || hnum == H_AID) {
287
                        PrefsAccount *tmp_ac;
288

    
289
                        tmp_ac = account_find_from_id(atoi(str));
290
                        if (tmp_ac) {
291
                                ac = tmp_ac;
292
                                break;
293
                        }
294
                }
295
        }
296

    
297
        fclose(fp);
298
        return ac;
299
}
300

    
301
PrefsAccount *account_find_from_msginfo(MsgInfo *msginfo)
302
{
303
        gchar *file;
304
        PrefsAccount *ac;
305

    
306
        file = procmsg_get_message_file(msginfo);
307
        ac = account_find_from_message_file(file);
308
        g_free(file);
309

    
310
        if (!ac && msginfo->folder)
311
                ac = account_find_from_item(msginfo->folder);
312

    
313
        return ac;
314
}
315

    
316
void account_set_menu(void)
317
{
318
        main_window_set_account_menu(account_list);
319
}
320

    
321
void account_foreach(AccountFunc func, gpointer user_data)
322
{
323
        GList *cur;
324

    
325
        for (cur = account_list; cur != NULL; cur = cur->next)
326
                if (func((PrefsAccount *)cur->data, user_data) != 0)
327
                        return;
328
}
329

    
330
GList *account_get_list(void)
331
{
332
        return account_list;
333
}
334

    
335
void account_edit_open(void)
336
{
337
        inc_lock();
338

    
339
        if (compose_get_compose_list()) {
340
                alertpanel_notice(_("Some composing windows are open.\n"
341
                                    "Please close all the composing windows before editing the accounts."));
342
                inc_unlock();
343
                return;
344
        }
345

    
346
        debug_print(_("Opening account edit window...\n"));
347

    
348
        if (!edit_account.window)
349
                account_edit_create();
350

    
351
        account_clist_set();
352

    
353
        manage_window_set_transient(GTK_WINDOW(edit_account.window));
354
        gtk_widget_grab_focus(edit_account.close_btn);
355
        gtk_widget_show(edit_account.window);
356

    
357
        manage_window_focus_in(edit_account.window, NULL, NULL);
358
}
359

    
360
void account_add(void)
361
{
362
        PrefsAccount *ac_prefs;
363

    
364
        ac_prefs = prefs_account_open(NULL);
365

    
366
        if (!ac_prefs) return;
367

    
368
        account_list = g_list_append(account_list, ac_prefs);
369

    
370
        if (ac_prefs->is_default)
371
                account_set_as_default(ac_prefs);
372

    
373
        account_clist_set();
374

    
375
        if (ac_prefs->protocol == A_IMAP4 || ac_prefs->protocol == A_NNTP) {
376
                Folder *folder;
377

    
378
                if (ac_prefs->protocol == A_IMAP4) {
379
                        folder = folder_new(F_IMAP, ac_prefs->account_name,
380
                                            ac_prefs->recv_server);
381
                } else {
382
                        folder = folder_new(F_NEWS, ac_prefs->account_name,
383
                                            ac_prefs->nntp_server);
384
                }
385

    
386
                folder->account = ac_prefs;
387
                ac_prefs->folder = REMOTE_FOLDER(folder);
388
                folder_add(folder);
389
                if (ac_prefs->protocol == A_IMAP4) {
390
                        if (main_window_toggle_online_if_offline
391
                                (main_window_get())) {
392
                                folder->klass->create_tree(folder);
393
                                statusbar_pop_all();
394
                        }
395
                }
396
                folderview_set_all();
397
        }
398
}
399

    
400
void account_open(PrefsAccount *ac_prefs)
401
{
402
        gboolean prev_default;
403
        gchar *ac_name;
404

    
405
        g_return_if_fail(ac_prefs != NULL);
406

    
407
        prev_default = ac_prefs->is_default;
408
        Xstrdup_a(ac_name, ac_prefs->account_name ? ac_prefs->account_name : "",
409
                  return);
410

    
411
        prefs_account_open(ac_prefs);
412

    
413
        if (!prev_default && ac_prefs->is_default)
414
                account_set_as_default(ac_prefs);
415

    
416
        if (ac_prefs->folder && strcmp2(ac_name, ac_prefs->account_name) != 0) {
417
                folder_set_name(FOLDER(ac_prefs->folder),
418
                                ac_prefs->account_name);
419
                folderview_set_all();
420
        }
421

    
422
        account_write_config_all();
423
        account_set_menu();
424
        main_window_reflect_prefs_all();
425
}
426

    
427
void account_set_as_default(PrefsAccount *ac_prefs)
428
{
429
        PrefsAccount *ap;
430
        GList *cur;
431

    
432
        for (cur = account_list; cur != NULL; cur = cur->next) {
433
                ap = (PrefsAccount *)cur->data;
434
                if (ap->is_default)
435
                        ap->is_default = FALSE;
436
        }
437

    
438
        ac_prefs->is_default = TRUE;
439
}
440

    
441
PrefsAccount *account_get_default(void)
442
{
443
        PrefsAccount *ap;
444
        GList *cur;
445

    
446
        for (cur = account_list; cur != NULL; cur = cur->next) {
447
                ap = (PrefsAccount *)cur->data;
448
                if (ap->is_default)
449
                        return ap;
450
        }
451

    
452
        return NULL;
453
}
454

    
455
void account_set_missing_folder(void)
456
{
457
        PrefsAccount *ap;
458
        GList *cur;
459

    
460
        for (cur = account_list; cur != NULL; cur = cur->next) {
461
                ap = (PrefsAccount *)cur->data;
462
                if ((ap->protocol == A_IMAP4 || ap->protocol == A_NNTP) &&
463
                    !ap->folder) {
464
                        Folder *folder;
465

    
466
                        if (ap->protocol == A_IMAP4) {
467
                                folder = folder_new(F_IMAP, ap->account_name,
468
                                                    ap->recv_server);
469
                        } else {
470
                                folder = folder_new(F_NEWS, ap->account_name,
471
                                                    ap->nntp_server);
472
                        }
473

    
474
                        folder->account = ap;
475
                        ap->folder = REMOTE_FOLDER(folder);
476
                        folder_add(folder);
477
                        if (ap->protocol == A_IMAP4) {
478
                                if (main_window_toggle_online_if_offline
479
                                        (main_window_get())) {
480
                                        folder->klass->create_tree(folder);
481
                                        statusbar_pop_all();
482
                                }
483
                        }
484
                }
485
        }
486
}
487

    
488
FolderItem *account_get_special_folder(PrefsAccount *ac_prefs,
489
                                       SpecialFolderItemType type)
490
{
491
        FolderItem *item = NULL;
492

    
493
        g_return_val_if_fail(ac_prefs != NULL, NULL);
494

    
495
        switch (type) {
496
        case F_INBOX:
497
                if (ac_prefs->folder)
498
                        item = FOLDER(ac_prefs->folder)->inbox;
499
                if (!item)
500
                        item = folder_get_default_inbox();
501
                break;
502
        case F_OUTBOX:
503
                if (ac_prefs->set_sent_folder && ac_prefs->sent_folder) {
504
                        item = folder_find_item_from_identifier
505
                                (ac_prefs->sent_folder);
506
                }
507
                if (!item) {
508
                        if (ac_prefs->folder)
509
                                item = FOLDER(ac_prefs->folder)->outbox;
510
                        if (!item)
511
                                item = folder_get_default_outbox();
512
                }
513
                break;
514
        case F_DRAFT:
515
                if (ac_prefs->set_draft_folder && ac_prefs->draft_folder) {
516
                        item = folder_find_item_from_identifier
517
                                (ac_prefs->draft_folder);
518
                }
519
                if (!item) {
520
                        if (ac_prefs->folder)
521
                                item = FOLDER(ac_prefs->folder)->draft;
522
                        if (!item)
523
                                item = folder_get_default_draft();
524
                }
525
                break;
526
        case F_QUEUE:
527
                if (ac_prefs->folder)
528
                        item = FOLDER(ac_prefs->folder)->queue;
529
                if (!item)
530
                        item = folder_get_default_queue();
531
                break;
532
        case F_TRASH:
533
                if (ac_prefs->set_trash_folder && ac_prefs->trash_folder) {
534
                        item = folder_find_item_from_identifier
535
                                (ac_prefs->trash_folder);
536
                }
537
                if (!item) {
538
                        if (ac_prefs->folder)
539
                                item = FOLDER(ac_prefs->folder)->trash;
540
                        if (!item)
541
                                item = folder_get_default_trash();
542
                }
543
                break;
544
        default:
545
                break;
546
        }
547

    
548
        return item;
549
}
550

    
551
void account_destroy(PrefsAccount *ac_prefs)
552
{
553
        g_return_if_fail(ac_prefs != NULL);
554

    
555
        folder_unref_account_all(ac_prefs);
556

    
557
        prefs_account_free(ac_prefs);
558
        account_list = g_list_remove(account_list, ac_prefs);
559

    
560
        if (cur_account == ac_prefs) cur_account = NULL;
561
        if (!cur_account && account_list) {
562
                cur_account = account_get_default();
563
                if (!cur_account) {
564
                        ac_prefs = (PrefsAccount *)account_list->data;
565
                        account_set_as_default(ac_prefs);
566
                        cur_account = ac_prefs;
567
                }
568
        }
569
}
570

    
571

    
572
static void account_edit_create(void)
573
{
574
        GtkWidget *window;
575
        GtkWidget *vbox;
576
        GtkWidget *label;
577
        GtkWidget *hbox;
578
        GtkWidget *scrolledwin;
579
        GtkWidget *clist;
580
        gchar *titles[N_EDIT_ACCOUNT_COLS];
581
        gint i;
582

    
583
        GtkWidget *vbox2;
584
        GtkWidget *add_btn;
585
        GtkWidget *edit_btn;
586
        GtkWidget *del_btn;
587
        GtkWidget *up_btn;
588
        GtkWidget *down_btn;
589

    
590
        GtkWidget *default_btn;
591

    
592
        GtkWidget *hbbox;
593
        GtkWidget *close_btn;
594

    
595
        debug_print(_("Creating account edit window...\n"));
596

    
597
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
598
        gtk_widget_set_size_request (window, 500, 320);
599
        gtk_container_set_border_width (GTK_CONTAINER (window), 8);
600
        gtk_window_set_title (GTK_WINDOW (window), _("Edit accounts"));
601
        gtk_window_set_modal (GTK_WINDOW (window), TRUE);
602
        g_signal_connect (G_OBJECT (window), "delete_event",
603
                          G_CALLBACK (account_delete_event), NULL);
604
        g_signal_connect (G_OBJECT (window), "key_press_event",
605
                          G_CALLBACK (account_key_pressed), NULL);
606
        MANAGE_WINDOW_SIGNALS_CONNECT (window);
607
        gtk_widget_realize(window);
608

    
609
        vbox = gtk_vbox_new (FALSE, 10);
610
        gtk_widget_show (vbox);
611
        gtk_container_add (GTK_CONTAINER (window), vbox);
612

    
613
        hbox = gtk_hbox_new (FALSE, 0);
614
        gtk_widget_show (hbox);
615
        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
616

    
617
        label = gtk_label_new
618
                (_("New messages will be checked in this order. Check the boxes\n"
619
                   "on the `G' column to enable message retrieval by `Get all'."));
620
        gtk_widget_show (label);
621
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
622
        gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
623

    
624
        hbox = gtk_hbox_new (FALSE, 8);
625
        gtk_widget_show (hbox);
626
        gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
627
        gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
628

    
629
        scrolledwin = gtk_scrolled_window_new (NULL, NULL);
630
        gtk_widget_show (scrolledwin);
631
        gtk_box_pack_start (GTK_BOX (hbox), scrolledwin, TRUE, TRUE, 0);
632
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwin),
633
                                        GTK_POLICY_AUTOMATIC,
634
                                        GTK_POLICY_AUTOMATIC);
635

    
636
        titles[COL_DEFAULT]  = "D";
637
        titles[COL_GETALL]   = "G";
638
        titles[COL_NAME]     = _("Name");
639
        titles[COL_PROTOCOL] = _("Protocol");
640
        titles[COL_SERVER]   = _("Server");
641

    
642
        clist = gtk_clist_new_with_titles (N_EDIT_ACCOUNT_COLS, titles);
643
        gtk_widget_show (clist);
644
        gtk_container_add (GTK_CONTAINER (scrolledwin), clist);
645
        gtk_clist_set_column_width (GTK_CLIST(clist), COL_DEFAULT , 10);
646
        gtk_clist_set_column_width (GTK_CLIST(clist), COL_GETALL  , 11);
647
        gtk_clist_set_column_width (GTK_CLIST(clist), COL_NAME    , 100);
648
        gtk_clist_set_column_width (GTK_CLIST(clist), COL_PROTOCOL, 100);
649
        gtk_clist_set_column_width (GTK_CLIST(clist), COL_SERVER  , 100);
650
        gtk_clist_set_column_justification (GTK_CLIST(clist), COL_DEFAULT,
651
                                            GTK_JUSTIFY_CENTER);
652
        gtk_clist_set_column_justification (GTK_CLIST(clist), COL_GETALL,
653
                                            GTK_JUSTIFY_CENTER);
654
        gtk_clist_set_selection_mode (GTK_CLIST(clist), GTK_SELECTION_BROWSE);
655

    
656
        for (i = 0; i < N_EDIT_ACCOUNT_COLS; i++)
657
                GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button,
658
                                       GTK_CAN_FOCUS);
659

    
660
        g_signal_connect (G_OBJECT (clist), "select_row",
661
                          G_CALLBACK (account_selected), NULL);
662
        g_signal_connect_after (G_OBJECT (clist), "row_move",
663
                                G_CALLBACK (account_row_moved), NULL);
664

    
665
        vbox2 = gtk_vbox_new (FALSE, 0);
666
        gtk_widget_show (vbox2);
667
        gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
668

    
669
        add_btn = gtk_button_new_with_label (_("Add"));
670
        gtk_widget_show (add_btn);
671
        gtk_box_pack_start (GTK_BOX (vbox2), add_btn, FALSE, FALSE, 4);
672
        g_signal_connect (G_OBJECT(add_btn), "clicked",
673
                          G_CALLBACK (account_add), NULL);
674

    
675
        edit_btn = gtk_button_new_with_label (_("Edit"));
676
        gtk_widget_show (edit_btn);
677
        gtk_box_pack_start (GTK_BOX (vbox2), edit_btn, FALSE, FALSE, 4);
678
        g_signal_connect (G_OBJECT(edit_btn), "clicked",
679
                          G_CALLBACK (account_edit_prefs), NULL);
680

    
681
        del_btn = gtk_button_new_with_label (_(" Delete "));
682
        gtk_widget_show (del_btn);
683
        gtk_box_pack_start (GTK_BOX (vbox2), del_btn, FALSE, FALSE, 4);
684
        g_signal_connect (G_OBJECT(del_btn), "clicked",
685
                          G_CALLBACK (account_delete), NULL);
686

    
687
        down_btn = gtk_button_new_with_label (_("Down"));
688
        gtk_widget_show (down_btn);
689
        gtk_box_pack_end (GTK_BOX (vbox2), down_btn, FALSE, FALSE, 4);
690
        g_signal_connect (G_OBJECT(down_btn), "clicked",
691
                          G_CALLBACK (account_down), NULL);
692

    
693
        up_btn = gtk_button_new_with_label (_("Up"));
694
        gtk_widget_show (up_btn);
695
        gtk_box_pack_end (GTK_BOX (vbox2), up_btn, FALSE, FALSE, 4);
696
        g_signal_connect (G_OBJECT(up_btn), "clicked",
697
                          G_CALLBACK (account_up), NULL);
698

    
699
        hbox = gtk_hbox_new (FALSE, 8);
700
        gtk_widget_show (hbox);
701
        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
702

    
703
        vbox2 = gtk_vbox_new(FALSE, 0);
704
        gtk_widget_show (vbox2);
705
        gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
706

    
707
        default_btn = gtk_button_new_with_label (_(" Set as default account "));
708
        gtk_widget_show (default_btn);
709
        gtk_box_pack_start (GTK_BOX (vbox2), default_btn, TRUE, FALSE, 0);
710
        g_signal_connect (G_OBJECT(default_btn), "clicked",
711
                          G_CALLBACK (account_set_default), NULL);
712

    
713
        gtkut_button_set_create(&hbbox, &close_btn, _("Close"),
714
                                NULL, NULL, NULL, NULL);
715
        gtk_widget_show(hbbox);
716
        gtk_box_pack_end (GTK_BOX (hbox), hbbox, FALSE, FALSE, 0);
717
        gtk_widget_grab_default (close_btn);
718

    
719
        g_signal_connect (G_OBJECT (close_btn), "clicked",
720
                          G_CALLBACK (account_edit_close), NULL);
721

    
722
        stock_pixmap_gdk(clist, STOCK_PIXMAP_MARK, &markxpm, &markxpmmask);
723
        stock_pixmap_gdk(clist, STOCK_PIXMAP_CHECKBOX_ON,
724
                         &checkboxonxpm, &checkboxonxpmmask);
725
        stock_pixmap_gdk(clist, STOCK_PIXMAP_CHECKBOX_OFF,
726
                         &checkboxoffxpm, &checkboxoffxpmmask);
727

    
728
        edit_account.window    = window;
729
        edit_account.clist     = clist;
730
        edit_account.close_btn = close_btn;
731
}
732

    
733
static void account_edit_prefs(void)
734
{
735
        GtkCList *clist = GTK_CLIST(edit_account.clist);
736
        PrefsAccount *ac_prefs;
737
        gint row;
738

    
739
        if (!clist->selection) return;
740

    
741
        row = GPOINTER_TO_INT(clist->selection->data);
742
        ac_prefs = gtk_clist_get_row_data(clist, row);
743
        account_open(ac_prefs);
744

    
745
        account_clist_set();
746
}
747

    
748
static void account_delete(void)
749
{
750
        GtkCList *clist = GTK_CLIST(edit_account.clist);
751
        PrefsAccount *ac_prefs;
752
        gint row;
753

    
754
        if (!clist->selection) return;
755

    
756
        if (alertpanel(_("Delete account"),
757
                       _("Do you really want to delete this account?"),
758
                       _("Yes"), _("+No"), NULL) != G_ALERTDEFAULT)
759
                return;
760

    
761
        row = GPOINTER_TO_INT(clist->selection->data);
762
        ac_prefs = gtk_clist_get_row_data(clist, row);
763
        if (ac_prefs->folder) {
764
                FolderItem *item;
765

    
766
                item = main_window_get()->summaryview->folder_item;
767
                if (item && item->folder == FOLDER(ac_prefs->folder))
768
                        summary_clear_all(main_window_get()->summaryview);
769
                folder_destroy(FOLDER(ac_prefs->folder));
770
                folderview_set_all();
771
        }
772
        account_destroy(ac_prefs);
773
        account_clist_set();
774
}
775

    
776
static void account_up(void)
777
{
778
        GtkCList *clist = GTK_CLIST(edit_account.clist);
779
        gint row;
780

    
781
        if (!clist->selection) return;
782

    
783
        row = GPOINTER_TO_INT(clist->selection->data);
784
        if (row > 0)
785
                gtk_clist_row_move(clist, row, row - 1);
786
}
787

    
788
static void account_down(void)
789
{
790
        GtkCList *clist = GTK_CLIST(edit_account.clist);
791
        gint row;
792

    
793
        if (!clist->selection) return;
794

    
795
        row = GPOINTER_TO_INT(clist->selection->data);
796
        if (row < clist->rows - 1)
797
                gtk_clist_row_move(clist, row, row + 1);
798
}
799

    
800
static void account_set_default(void)
801
{
802
        GtkCList *clist = GTK_CLIST(edit_account.clist);
803
        gint row;
804
        PrefsAccount *ac_prefs;
805

    
806
        if (!clist->selection) return;
807

    
808
        row = GPOINTER_TO_INT(clist->selection->data);
809
        ac_prefs = gtk_clist_get_row_data(clist, row);
810
        account_set_as_default(ac_prefs);
811
        account_clist_set();
812

    
813
        cur_account = ac_prefs;
814
        account_set_menu();
815
        main_window_reflect_prefs_all();
816
}
817

    
818
static void account_edit_close(void)
819
{
820
        account_list_set();
821
        account_write_config_all();
822

    
823
        if (!cur_account && account_list) {
824
                PrefsAccount *ac_prefs = (PrefsAccount *)account_list->data;
825
                account_set_as_default(ac_prefs);
826
                cur_account = ac_prefs;
827
        }
828

    
829
        account_set_menu();
830
        main_window_reflect_prefs_all();
831

    
832
        gtk_widget_hide(edit_account.window);
833

    
834
        inc_unlock();
835
}
836

    
837
static gint account_delete_event(GtkWidget *widget, GdkEventAny *event,
838
                                 gpointer data)
839
{
840
        account_edit_close();
841
        return TRUE;
842
}
843

    
844
static void account_selected(GtkCList *clist, gint row, gint column,
845
                             GdkEvent *event, gpointer data)
846
{
847
        if (event && event->type == GDK_2BUTTON_PRESS) {
848
                account_edit_prefs();
849
                return;
850
        }
851

    
852
        if (column == COL_GETALL) {
853
                PrefsAccount *ac;
854

    
855
                ac = gtk_clist_get_row_data(clist, row);
856
                if (ac->protocol == A_POP3 || ac->protocol == A_IMAP4 ||
857
                    ac->protocol == A_NNTP) {
858
                        ac->recv_at_getall ^= TRUE;
859
                        account_clist_set_row(ac, row);
860
                }
861
        }
862
}
863

    
864
static void account_row_moved(GtkCList *clist, gint source_row, gint dest_row)
865
{
866
        account_list_set();
867
        if (gtk_clist_row_is_visible(clist, dest_row) != GTK_VISIBILITY_FULL)
868
                gtk_clist_moveto(clist, dest_row, -1, 0.5, 0.0);
869
}
870

    
871
static gboolean account_key_pressed(GtkWidget *widget, GdkEventKey *event,
872
                                    gpointer data)
873
{
874
        if (event && event->keyval == GDK_Escape)
875
                account_edit_close();
876
        return FALSE;
877
}
878

    
879
/* set one CList row or add new row */
880
static gint account_clist_set_row(PrefsAccount *ac_prefs, gint row)
881
{
882
        GtkCList *clist = GTK_CLIST(edit_account.clist);
883
        gchar *text[N_EDIT_ACCOUNT_COLS];
884
        gboolean has_getallbox;
885
        gboolean getall;
886

    
887
        text[COL_DEFAULT] = "";
888
        text[COL_GETALL]  = "";
889
        text[COL_NAME]    = ac_prefs->account_name;
890
#if USE_SSL
891
        text[COL_PROTOCOL] = ac_prefs->protocol == A_POP3 ?
892
                             (ac_prefs->ssl_pop == SSL_TUNNEL ?
893
                              "POP3 (SSL)" :
894
                              ac_prefs->ssl_pop == SSL_STARTTLS ?
895
                              "POP3 (TLS)" : "POP3") :
896
                             ac_prefs->protocol == A_IMAP4 ?
897
                             (ac_prefs->ssl_imap == SSL_TUNNEL ?
898
                              "IMAP4 (SSL)" :
899
                              ac_prefs->ssl_imap == SSL_STARTTLS ?
900
                              "IMAP4 (TLS)" : "IMAP4") :
901
                             ac_prefs->protocol == A_NNTP ?
902
                             (ac_prefs->ssl_nntp == SSL_TUNNEL ?
903
                              "NNTP (SSL)" : "NNTP") :
904
                             "";
905
#else
906
        text[COL_PROTOCOL] = ac_prefs->protocol == A_POP3  ? "POP3" :
907
                             ac_prefs->protocol == A_IMAP4 ? "IMAP4" :
908
                             ac_prefs->protocol == A_NNTP  ? "NNTP" : "";
909
#endif
910
        text[COL_SERVER] = ac_prefs->protocol == A_NNTP
911
                ? ac_prefs->nntp_server : ac_prefs->recv_server;
912

    
913
        if (row < 0)
914
                row = gtk_clist_append(clist, text);
915
        else {
916
                gtk_clist_set_text(clist, row, COL_DEFAULT, text[COL_DEFAULT]);
917
                gtk_clist_set_text(clist, row, COL_GETALL, text[COL_GETALL]);
918
                gtk_clist_set_text(clist, row, COL_NAME, text[COL_NAME]);
919
                gtk_clist_set_text(clist, row, COL_PROTOCOL, text[COL_PROTOCOL]);
920
                gtk_clist_set_text(clist, row, COL_SERVER, text[COL_SERVER]);
921
        }
922

    
923
        has_getallbox = (ac_prefs->protocol == A_POP3  ||
924
                         ac_prefs->protocol == A_IMAP4 ||
925
                         ac_prefs->protocol == A_NNTP);
926
        getall = has_getallbox && ac_prefs->recv_at_getall;
927

    
928
        if (ac_prefs->is_default)
929
                gtk_clist_set_pixmap(clist, row, COL_DEFAULT,
930
                                     markxpm, markxpmmask);
931
        if (getall)
932
                gtk_clist_set_pixmap(clist, row, COL_GETALL,
933
                                     checkboxonxpm, checkboxonxpmmask);
934
        else if (has_getallbox)
935
                gtk_clist_set_pixmap(clist, row, COL_GETALL,
936
                                     checkboxoffxpm, checkboxoffxpmmask);
937

    
938
        gtk_clist_set_row_data(clist, row, ac_prefs);
939

    
940
        return row;
941
}
942

    
943
/* set CList from account list */
944
static void account_clist_set(void)
945
{
946
        GtkCList *clist = GTK_CLIST(edit_account.clist);
947
        GList *cur;
948
        gint row = -1, prev_row = -1;
949

    
950
        if (clist->selection)
951
                prev_row = GPOINTER_TO_INT(clist->selection->data);
952

    
953
        gtk_clist_freeze(clist);
954
        gtk_clist_clear(clist);
955

    
956
        for (cur = account_list; cur != NULL; cur = cur->next) {
957
                row = account_clist_set_row((PrefsAccount *)cur->data, -1);
958
                if ((PrefsAccount *)cur->data == cur_account) {
959
                        gtk_clist_select_row(clist, row, -1);
960
                        gtkut_clist_set_focus_row(clist, row);
961
                }
962
        }
963

    
964
        if (prev_row >= 0) {
965
                row = prev_row;
966
                gtk_clist_select_row(clist, row, -1);
967
                gtkut_clist_set_focus_row(clist, row);
968
        }
969

    
970
        if (row >= 0 &&
971
            gtk_clist_row_is_visible(clist, row) != GTK_VISIBILITY_FULL)
972
                gtk_clist_moveto(clist, row, -1, 0.5, 0);
973

    
974
        gtk_clist_thaw(clist);
975
}
976

    
977
/* set account list from CList */
978
static void account_list_set(void)
979
{
980
        GtkCList *clist = GTK_CLIST(edit_account.clist);
981
        gint row;
982
        PrefsAccount *ac_prefs;
983

    
984
        while (account_list)
985
                account_list = g_list_remove(account_list, account_list->data);
986

    
987
        for (row = 0; (ac_prefs = gtk_clist_get_row_data(clist, row)) != NULL;
988
             row++)
989
                account_list = g_list_append(account_list, ac_prefs);
990
}