2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #include <glib/gi18n.h>
29 #include <gdk/gdkkeysyms.h>
34 #include "mainwindow.h"
35 #include "folderview.h"
38 #include "prefs_gtk.h"
39 #include "prefs_account.h"
40 #include "prefs_common.h"
41 #include "folder_item_prefs.h"
43 #include "manage_window.h"
44 #include "stock_pixmap.h"
48 #include "alertpanel.h"
49 #include "procheader.h"
50 #include "customheader.h"
51 #include "remotefolder.h"
53 #include "filtering.h"
56 ACCOUNT_IS_DEFAULT
, /* GDK_TYPE_PIXMAP! */
57 ACCOUNT_ENABLE_GET_ALL
,
73 } EditAccountColumnPos
;
75 # define N_EDIT_ACCOUNT_COLS 5
77 #define PREFSBUFSIZE 1024
79 PrefsAccount
*cur_account
;
81 static GList
*account_list
= NULL
;
82 static gboolean account_list_dirty
= FALSE
;
84 static struct EditAccount
{
90 static GdkPixbuf
*mark_pixbuf
;
92 static void account_edit_create (void);
93 static void account_destroy (PrefsAccount
*ac_prefs
);
94 static void account_set_as_default (PrefsAccount
*ac_prefs
);
95 static void account_set_menu (void);
97 static void account_edit_prefs (GtkWidget
*widget
, gpointer data
);
98 static void account_delete (GtkWidget
*widget
, gpointer data
);
99 static void account_clone (GtkWidget
*widget
, gpointer data
);
101 static void account_up (GtkWidget
*widget
, gpointer data
);
102 static void account_down (GtkWidget
*widget
, gpointer data
);
104 static void account_set_default (GtkWidget
*widget
, gpointer data
);
106 static void account_edit_close (GtkWidget
*widget
, gpointer data
);
108 static gint
account_delete_event (GtkWidget
*widget
,
111 static void account_size_allocate_cb(GtkWidget
*widget
,
112 GtkAllocation
*allocation
);
113 static gboolean
account_key_pressed (GtkWidget
*widget
,
117 static void account_list_view_add (PrefsAccount
*ac_prefs
);
118 static void account_list_view_set (void);
120 static void account_list_set (void);
122 typedef struct FindAccountInStore
{
126 } FindAccountInStore
;
128 static GtkListStore
* account_create_data_store (void);
130 static void account_list_view_insert_account_item (GtkListStore
*list_store
,
131 const gchar
*account_name
,
132 const gchar
*protocol
,
133 const gchar
*server_name
,
136 PrefsAccount
*account_data
);
138 static GtkWidget
*account_list_view_create (void);
139 static void account_create_list_view_images (GtkWidget
*list_view
);
140 static void account_create_list_view_columns (GtkWidget
*list_view
);
142 static gint
account_list_view_get_selected_account_id (GtkWidget
*list_view
);
143 static GtkTreePath
*account_list_view_get_selected_account_path (GtkWidget
*list_view
);
144 static PrefsAccount
*account_list_view_get_selected_account (GtkWidget
*list_view
);
145 static gboolean
account_list_view_select_account (GtkWidget
*list_view
,
148 static void account_list_view_set_default_by_id(GtkWidget
*list_view
,
151 static gboolean
set_new_default_account (GtkTreeModel
*model
,
156 static gboolean
find_account_in_store (GtkTreeModel
*model
,
159 FindAccountInStore
*data
);
161 static void account_get_all_toggled (GtkCellRendererToggle
*widget
,
163 GtkWidget
*list_view
);
165 static void account_double_clicked (GtkTreeView
*list_view
,
167 GtkTreeViewColumn
*column
,
170 static void drag_begin (GtkTreeView
*list_view
,
171 GdkDragContext
*context
,
174 static void drag_end (GtkTreeView
*list_view
,
175 GdkDragContext
*context
,
178 static void account_row_changed_while_drag_drop (GtkTreeModel
*model
,
182 GtkTreeView
*list_view
);
184 void account_flush_state(void)
187 main_window_reflect_prefs_all();
189 account_list_dirty
= FALSE
;
192 void account_read_config_all(void)
194 GSList
*ac_label_list
= NULL
, *cur
;
197 gchar buf
[PREFSBUFSIZE
];
198 PrefsAccount
*ac_prefs
;
200 debug_print("Reading all config for each account...\n");
202 rcpath
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
, ACCOUNT_RC
, NULL
);
203 if ((fp
= g_fopen(rcpath
, "rb")) == NULL
) {
204 if (ENOENT
!= errno
) FILE_OP_ERROR(rcpath
, "fopen");
210 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
211 if (!strncmp(buf
, "[Account: ", 10)) {
213 memmove(buf
, buf
+ 1, strlen(buf
));
214 buf
[strlen(buf
) - 1] = '\0';
215 debug_print("Found label: %s\n", buf
);
216 ac_label_list
= g_slist_append(ac_label_list
,
222 /* read config data from file */
224 for (cur
= ac_label_list
; cur
!= NULL
; cur
= cur
->next
) {
225 ac_prefs
= prefs_account_new();
226 prefs_account_read_config(ac_prefs
, (gchar
*)cur
->data
);
227 account_list
= g_list_append(account_list
, ac_prefs
);
228 if (ac_prefs
->is_default
)
229 cur_account
= ac_prefs
;
231 /* if default is not set, assume first account as default */
232 if (!cur_account
&& account_list
) {
233 ac_prefs
= (PrefsAccount
*)account_list
->data
;
234 account_set_as_default(ac_prefs
);
235 cur_account
= ac_prefs
;
239 main_window_reflect_prefs_all_now();
241 while (ac_label_list
) {
242 g_free(ac_label_list
->data
);
243 ac_label_list
= g_slist_remove(ac_label_list
,
244 ac_label_list
->data
);
248 void account_write_config_all(void)
250 prefs_account_write_config_all(account_list
);
254 * account_find_all_from_address:
255 * @ac_list: initial list of accounts. NULL to create a new one.
256 * Accounts found in the @address will be appended to this list.
257 * @address: Email address string.
259 * Find all the mail (not news) accounts within the specified address.
261 * Return value: the original accounts list with the found accounts appended.
263 GList
*account_find_all_from_address(GList
*ac_list
, const gchar
*address
)
271 for (cur
= account_list
; cur
!= NULL
; cur
= cur
->next
) {
272 ac
= (PrefsAccount
*)cur
->data
;
273 if (ac
->protocol
!= A_NNTP
&& ac
->address
&&
274 strcasestr(address
, ac
->address
) != NULL
)
275 ac_list
= g_list_append(ac_list
, ac
);
280 PrefsAccount
*account_find_from_smtp_server(const gchar
*address
,
281 const gchar
*smtp_server
)
286 g_return_val_if_fail(address
!= NULL
, NULL
);
287 g_return_val_if_fail(smtp_server
!= NULL
, NULL
);
289 for (cur
= account_list
; cur
!= NULL
; cur
= cur
->next
) {
290 ac
= (PrefsAccount
*)cur
->data
;
291 if (!strcmp2(address
, ac
->address
) &&
292 !strcmp2(smtp_server
, ac
->smtp_server
))
300 * account_find_from_address:
301 * @address: Email address string.
303 * Find a mail (not news) account with the specified email address.
305 * Return value: The found account, or NULL if not found.
307 PrefsAccount
*account_find_from_address(const gchar
*address
)
312 g_return_val_if_fail(address
!= NULL
, NULL
);
314 for (cur
= account_list
; cur
!= NULL
; cur
= cur
->next
) {
315 ac
= (PrefsAccount
*)cur
->data
;
316 if (ac
->protocol
!= A_NNTP
&& ac
->address
&&
317 g_ascii_strcasecmp(address
, ac
->address
) == 0)
324 PrefsAccount
*account_find_from_id(gint id
)
329 for (cur
= account_list
; cur
!= NULL
; cur
= cur
->next
) {
330 ac
= (PrefsAccount
*)cur
->data
;
331 if (id
== ac
->account_id
)
338 PrefsAccount
*account_find_from_item(FolderItem
*item
)
342 g_return_val_if_fail(item
!= NULL
, NULL
);
346 FolderItem
*cur_item
= folder_item_parent(item
);
347 while (cur_item
!= NULL
) {
348 if (cur_item
->account
&& cur_item
->apply_sub
) {
349 ac
= cur_item
->account
;
352 cur_item
= folder_item_parent(cur_item
);
356 ac
= item
->folder
->account
;
361 static void account_set_menu(void)
363 main_window_set_account_menu(account_list
);
366 void account_set_menu_only_toolbar(void)
368 main_window_set_account_menu_only_toolbar(account_list
);
371 GList
*account_get_list(void)
376 void account_edit_open(void)
380 account_list_dirty
= FALSE
;
382 if (compose_get_compose_list()) {
383 alertpanel_error(_("Some composing windows are open.\n"
384 "Please close all the composing "
385 "windows before editing the accounts."));
390 debug_print("Opening account edit window...\n");
392 if (!edit_account
.window
)
393 account_edit_create();
395 account_list_view_set();
397 manage_window_set_transient(GTK_WINDOW(edit_account
.window
));
398 gtk_widget_grab_focus(edit_account
.close_btn
);
399 gtk_widget_show(edit_account
.window
);
401 manage_window_focus_in(edit_account
.window
, NULL
, NULL
);
404 void account_add(void)
406 PrefsAccount
*ac_prefs
;
408 ac_prefs
= prefs_account_open(NULL
, &account_list_dirty
);
410 if (!ac_prefs
) return;
412 account_list
= g_list_append(account_list
, ac_prefs
);
414 if (ac_prefs
->is_default
)
415 account_set_as_default(ac_prefs
);
417 account_list_view_set();
419 if (ac_prefs
->protocol
== A_IMAP4
|| ac_prefs
->protocol
== A_NNTP
) {
422 if (ac_prefs
->protocol
== A_IMAP4
) {
423 folder
= folder_new(folder_get_class_from_string("imap"), ac_prefs
->account_name
,
424 ac_prefs
->recv_server
);
426 folder
= folder_new(folder_get_class_from_string("news"), ac_prefs
->account_name
,
427 ac_prefs
->nntp_server
);
429 if (folder
== NULL
) {
430 alertpanel_error(_("Can't create folder."));
433 folder
->account
= ac_prefs
;
434 ac_prefs
->folder
= folder
;
436 if (ac_prefs
->protocol
== A_IMAP4
)
437 folder
->klass
->create_tree(folder
);
438 folderview_set_all();
443 void account_open(PrefsAccount
*ac_prefs
)
445 gboolean prev_default
;
447 gboolean account_dirty
= FALSE
;
449 g_return_if_fail(ac_prefs
!= NULL
);
451 prev_default
= ac_prefs
->is_default
;
452 Xstrdup_a(ac_name
, ac_prefs
->account_name
? ac_prefs
->account_name
: "",
455 prefs_account_open(ac_prefs
, &account_dirty
);
458 if (!prev_default
&& ac_prefs
->is_default
)
459 account_set_as_default(ac_prefs
);
461 if (ac_prefs
->folder
&& strcmp2(ac_name
, ac_prefs
->account_name
) != 0) {
462 folder_set_name(FOLDER(ac_prefs
->folder
),
463 ac_prefs
->account_name
);
464 folderview_set_all();
467 account_write_config_all();
469 account_flush_state();
473 static void account_set_as_default(PrefsAccount
*ac_prefs
)
478 for (cur
= account_list
; cur
!= NULL
; cur
= cur
->next
) {
479 ap
= (PrefsAccount
*)cur
->data
;
481 ap
->is_default
= FALSE
;
484 ac_prefs
->is_default
= TRUE
;
487 PrefsAccount
*account_get_default(void)
492 for (cur
= account_list
; cur
!= NULL
; cur
= cur
->next
) {
493 ap
= (PrefsAccount
*)cur
->data
;
501 void account_set_missing_folder(void)
506 for (cur
= account_list
; cur
!= NULL
; cur
= cur
->next
) {
507 ap
= (PrefsAccount
*)cur
->data
;
508 if ((ap
->protocol
== A_IMAP4
|| ap
->protocol
== A_NNTP
) &&
512 if (ap
->protocol
== A_IMAP4
) {
513 folder
= folder_new(folder_get_class_from_string("imap"), ap
->account_name
,
516 folder
= folder_new(folder_get_class_from_string("news"), ap
->account_name
,
521 folder
->account
= ap
;
524 if (ap
->protocol
== A_IMAP4
)
525 folder
->klass
->create_tree(folder
);
532 #define CHECK_CHANGE_FOLDER(folder) { \
533 if (folder && !strncmp(folder, old_id, strlen(old_id))) { \
534 if (strlen(folder) == strlen(old_id)) { \
536 folder = g_strdup(new_id); \
537 } else if (strlen(folder) > strlen(old_id) \
538 && folder[strlen(old_id)] == G_DIR_SEPARATOR) { \
539 gchar *new_path = g_strdup_printf("%s%s", \
540 new_id, (folder + strlen(old_id))); \
547 void account_rename_path(const gchar
*old_id
, const gchar
*new_id
)
549 GList
*cur
= account_list
;
550 for (; cur
!= NULL
; cur
= g_list_next(cur
)) {
551 PrefsAccount
*ap
= (PrefsAccount
*)cur
->data
;
552 CHECK_CHANGE_FOLDER(ap
->inbox
);
553 CHECK_CHANGE_FOLDER(ap
->local_inbox
);
554 CHECK_CHANGE_FOLDER(ap
->queue_folder
);
555 CHECK_CHANGE_FOLDER(ap
->sent_folder
);
556 CHECK_CHANGE_FOLDER(ap
->draft_folder
);
557 CHECK_CHANGE_FOLDER(ap
->trash_folder
);
561 #undef CHECK_CHANGE_FOLDER
563 FolderItem
*account_get_special_folder(PrefsAccount
*ac_prefs
,
564 SpecialFolderItemType type
)
566 FolderItem
*item
= NULL
;
568 g_return_val_if_fail(ac_prefs
!= NULL
, NULL
);
572 if (ac_prefs
->folder
)
573 item
= FOLDER(ac_prefs
->folder
)->inbox
;
575 item
= folder_get_default_inbox();
578 if (ac_prefs
->set_sent_folder
&& ac_prefs
->sent_folder
) {
579 item
= folder_find_item_from_identifier
580 (ac_prefs
->sent_folder
);
583 if (ac_prefs
->folder
)
584 item
= FOLDER(ac_prefs
->folder
)->outbox
;
586 item
= folder_get_default_outbox();
590 if (ac_prefs
->set_draft_folder
&& ac_prefs
->draft_folder
) {
591 item
= folder_find_item_from_identifier
592 (ac_prefs
->draft_folder
);
595 if (ac_prefs
->folder
)
596 item
= FOLDER(ac_prefs
->folder
)->draft
;
598 item
= folder_get_default_draft();
602 if (ac_prefs
->set_queue_folder
&& ac_prefs
->queue_folder
) {
603 item
= folder_find_item_from_identifier
604 (ac_prefs
->queue_folder
);
607 if (ac_prefs
->folder
)
608 item
= FOLDER(ac_prefs
->folder
)->queue
;
610 item
= folder_get_default_queue();
614 if (ac_prefs
->set_trash_folder
&& ac_prefs
->trash_folder
) {
615 item
= folder_find_item_from_identifier
616 (ac_prefs
->trash_folder
);
619 if (ac_prefs
->folder
)
620 item
= FOLDER(ac_prefs
->folder
)->trash
;
622 item
= folder_get_default_trash();
632 void account_destroy(PrefsAccount
*ac_prefs
)
634 g_return_if_fail(ac_prefs
!= NULL
);
636 folder_unref_account_all(ac_prefs
);
638 prefs_account_free(ac_prefs
);
639 account_list
= g_list_remove(account_list
, ac_prefs
);
641 if (cur_account
== ac_prefs
) cur_account
= NULL
;
642 if (!cur_account
&& account_list
) {
643 cur_account
= account_get_default();
645 ac_prefs
= (PrefsAccount
*)account_list
->data
;
646 account_set_as_default(ac_prefs
);
647 cur_account
= ac_prefs
;
653 *\brief Save Gtk object size to prefs dataset
655 static void account_size_allocate_cb(GtkWidget
*widget
,
656 GtkAllocation
*allocation
)
658 g_return_if_fail(allocation
!= NULL
);
660 prefs_common
.accountswin_width
= allocation
->width
;
661 prefs_common
.accountswin_height
= allocation
->height
;
664 static void account_edit_create(void)
670 GtkWidget
*scrolledwin
;
671 GtkWidget
*list_view
;
677 GtkWidget
*clone_btn
;
681 GtkWidget
*default_btn
;
685 GtkWidget
*close_btn
;
687 static GdkGeometry geometry
;
689 debug_print("Creating account edit window...\n");
691 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "account");
692 gtk_container_set_border_width (GTK_CONTAINER (window
), 8);
693 gtk_window_set_title (GTK_WINDOW (window
), _("Edit accounts"));
694 gtk_window_set_modal (GTK_WINDOW (window
), TRUE
);
695 g_signal_connect (G_OBJECT (window
), "delete_event",
696 G_CALLBACK (account_delete_event
), NULL
);
698 maemo_connect_key_press_to_mainwindow(GTK_WINDOW(window
));
700 g_signal_connect (G_OBJECT (window
), "key_press_event",
701 G_CALLBACK (account_key_pressed
), NULL
);
703 MANAGE_WINDOW_SIGNALS_CONNECT (window
);
704 gtk_widget_realize(window
);
706 vbox
= gtk_vbox_new (FALSE
, 10);
707 gtk_widget_show (vbox
);
708 gtk_container_add (GTK_CONTAINER (window
), vbox
);
710 hbox
= gtk_hbox_new (FALSE
, 0);
711 gtk_widget_show (hbox
);
712 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
714 label
= gtk_label_new
715 (_("Using 'Get Mail' will retrieve messages from your Accounts "
716 "in the order given, the checkbox in the 'G' column indicates "
717 "which accounts will be included."));
718 gtk_widget_show (label
);
719 gtk_box_pack_start (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 4);
720 gtk_label_set_justify(GTK_LABEL(label
), GTK_JUSTIFY_LEFT
);
721 gtk_label_set_line_wrap(GTK_LABEL(label
), TRUE
);
723 hbox
= gtk_hbox_new (FALSE
, 8);
724 gtk_widget_show (hbox
);
725 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, TRUE
, TRUE
, 0);
726 gtk_container_set_border_width (GTK_CONTAINER (hbox
), 2);
728 scrolledwin
= gtk_scrolled_window_new (NULL
, NULL
);
729 gtk_widget_show (scrolledwin
);
730 gtk_box_pack_start (GTK_BOX (hbox
), scrolledwin
, TRUE
, TRUE
, 0);
731 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwin
),
732 GTK_POLICY_AUTOMATIC
,
733 GTK_POLICY_AUTOMATIC
);
735 list_view
= account_list_view_create();
736 gtk_widget_show(list_view
);
737 gtk_container_add(GTK_CONTAINER(scrolledwin
), list_view
);
739 vbox2
= gtk_vbox_new (FALSE
, 0);
740 gtk_widget_show (vbox2
);
741 gtk_box_pack_start (GTK_BOX (hbox
), vbox2
, FALSE
, FALSE
, 0);
743 add_btn
= gtk_button_new_from_stock(GTK_STOCK_NEW
);
744 gtk_widget_show (add_btn
);
745 gtk_box_pack_start (GTK_BOX (vbox2
), add_btn
, FALSE
, FALSE
, 4);
746 g_signal_connect (G_OBJECT(add_btn
), "clicked",
747 G_CALLBACK (account_add
), NULL
);
749 edit_btn
= gtk_button_new_from_stock (GTK_STOCK_EDIT
);
750 gtk_widget_show (edit_btn
);
751 gtk_box_pack_start (GTK_BOX (vbox2
), edit_btn
, FALSE
, FALSE
, 4);
752 g_signal_connect (G_OBJECT(edit_btn
), "clicked",
753 G_CALLBACK (account_edit_prefs
), NULL
);
755 del_btn
= gtk_button_new_from_stock(GTK_STOCK_DELETE
);
756 gtk_widget_show (del_btn
);
757 gtk_box_pack_start (GTK_BOX (vbox2
), del_btn
, FALSE
, FALSE
, 4);
758 g_signal_connect (G_OBJECT(del_btn
), "clicked",
759 G_CALLBACK (account_delete
), NULL
);
761 clone_btn
= gtk_button_new_from_stock(GTK_STOCK_COPY
);
762 gtk_widget_show (clone_btn
);
763 gtk_box_pack_start (GTK_BOX (vbox2
), clone_btn
, FALSE
, FALSE
, 4);
764 g_signal_connect(G_OBJECT(clone_btn
), "clicked",
765 G_CALLBACK(account_clone
), NULL
);
767 down_btn
= gtk_button_new_from_stock(GTK_STOCK_GO_DOWN
);
768 gtk_widget_show (down_btn
);
769 gtk_box_pack_end (GTK_BOX (vbox2
), down_btn
, FALSE
, FALSE
, 4);
770 g_signal_connect (G_OBJECT(down_btn
), "clicked",
771 G_CALLBACK (account_down
), NULL
);
773 up_btn
= gtk_button_new_from_stock(GTK_STOCK_GO_UP
);
774 gtk_widget_show (up_btn
);
775 gtk_box_pack_end (GTK_BOX (vbox2
), up_btn
, FALSE
, FALSE
, 4);
776 g_signal_connect (G_OBJECT(up_btn
), "clicked",
777 G_CALLBACK (account_up
), NULL
);
779 hbox
= gtk_hbox_new (FALSE
, 8);
780 gtk_widget_show (hbox
);
781 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
783 vbox2
= gtk_vbox_new(FALSE
, 0);
784 gtk_widget_show (vbox2
);
785 gtk_box_pack_start (GTK_BOX (hbox
), vbox2
, FALSE
, FALSE
, 0);
787 default_btn
= gtk_button_new_with_mnemonic
788 (_(" _Set as default account "));
789 gtk_widget_show (default_btn
);
790 gtk_box_pack_start (GTK_BOX (vbox2
), default_btn
, TRUE
, FALSE
, 0);
791 g_signal_connect (G_OBJECT(default_btn
), "clicked",
792 G_CALLBACK (account_set_default
), NULL
);
794 hbbox
= gtk_hbutton_box_new();
795 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox
), GTK_BUTTONBOX_END
);
796 gtk_box_set_spacing(GTK_BOX(hbbox
), 5);
798 gtkut_stock_button_set_create_with_help(&hbbox
, &help_btn
,
799 &close_btn
, GTK_STOCK_CLOSE
,
800 NULL
, NULL
, NULL
, NULL
);
801 gtk_widget_show(hbbox
);
803 gtk_box_pack_end (GTK_BOX (hbox
), hbbox
, FALSE
, FALSE
, 0);
804 gtk_widget_grab_default (close_btn
);
806 g_signal_connect (G_OBJECT (close_btn
), "clicked",
807 G_CALLBACK (account_edit_close
),
809 g_signal_connect(G_OBJECT(help_btn
), "clicked",
810 G_CALLBACK(manual_open_with_anchor_cb
),
811 MANUAL_ANCHOR_ACCOUNTPREFS
);
813 account_create_list_view_images(list_view
);
815 g_signal_connect(G_OBJECT(window
), "size_allocate",
816 G_CALLBACK(account_size_allocate_cb
), NULL
);
818 if (!geometry
.min_height
) {
819 geometry
.min_width
= 500;
820 geometry
.min_height
= 380;
823 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &geometry
,
825 gtk_widget_set_size_request(window
, prefs_common
.accountswin_width
,
826 prefs_common
.accountswin_height
);
828 edit_account
.window
= window
;
829 edit_account
.list_view
= list_view
;
830 edit_account
.close_btn
= close_btn
;
832 maemo_window_full_screen_if_needed(GTK_WINDOW(edit_account
.window
));
836 static void account_edit_prefs(GtkWidget
*widget
, gpointer data
)
838 PrefsAccount
*ac_prefs
;
840 ac_prefs
= account_list_view_get_selected_account(edit_account
.list_view
);
843 account_open(ac_prefs
);
844 account_list_view_set();
848 static gboolean
account_delete_references_func(GNode
*node
, gpointer data
)
853 g_return_val_if_fail(node
->data
!= NULL
, FALSE
);
855 item
= FOLDER_ITEM(node
->data
);
856 account
= GPOINTER_TO_INT(data
);
858 if(!item
->prefs
) /* && item->prefs->stype == F_NORMAL */
860 if(item
->prefs
->default_account
!= account
)
863 item
->prefs
->enable_default_account
= FALSE
;
864 item
->prefs
->default_account
= 0;
865 folder_item_prefs_save_config(item
);
871 #define ACP_FDUP(fld) ac_clon->fld = ((ac_prefs->fld) != NULL)?\
872 g_strdup(ac_prefs->fld): NULL
873 #define ACP_FASSIGN(fld) ac_clon->fld = ac_prefs->fld
874 static void account_clone(GtkWidget
*widget
, gpointer data
)
876 PrefsAccount
*ac_prefs
, *ac_clon
;
878 CustomHeader
*cch
= NULL
, *ch
= NULL
;
880 ac_prefs
= account_list_view_get_selected_account(edit_account
.list_view
);
881 if (ac_prefs
== NULL
)
884 if (ac_prefs
->protocol
== A_IMAP4
|| ac_prefs
->protocol
== A_NNTP
) {
885 alertpanel_error(_("Accounts with remote folders cannot be copied."));
888 account_list_dirty
= TRUE
;
890 ac_clon
= prefs_account_new();
892 ac_clon
->account_name
= g_strdup_printf(_("Copy of %s"),
893 ac_prefs
->account_name
);
897 ACP_FDUP(organization
);
900 ACP_FASSIGN(protocol
);
901 ACP_FDUP(recv_server
);
902 ACP_FDUP(smtp_server
);
903 ACP_FDUP(nntp_server
);
904 ACP_FASSIGN(use_nntp_auth
);
905 ACP_FASSIGN(use_nntp_auth_onconnect
);
909 ACP_FDUP(local_mbox
);
910 ACP_FASSIGN(use_mail_command
);
911 ACP_FDUP(mail_command
);
914 ACP_FASSIGN(ssl_pop
);
915 ACP_FASSIGN(ssl_imap
);
916 ACP_FASSIGN(ssl_nntp
);
917 ACP_FASSIGN(ssl_smtp
);
918 ACP_FASSIGN(use_nonblocking_ssl
);
919 #endif /* USE_OPENSSL */
921 ac_clon
->tmp_pass
= NULL
;
925 ACP_FASSIGN(msg_leave_time
);
926 ACP_FASSIGN(recv_at_getall
);
927 ACP_FASSIGN(sd_rmmail_on_download
);
928 ACP_FASSIGN(enable_size_limit
);
929 ACP_FASSIGN(size_limit
);
930 ACP_FASSIGN(filter_on_recv
);
931 ACP_FASSIGN(filterhook_on_recv
);
933 ACP_FASSIGN(max_articles
);
935 ACP_FASSIGN(imap_auth_type
);
938 ACP_FASSIGN(gen_msgid
);
939 ACP_FASSIGN(add_customhdr
);
940 ACP_FASSIGN(use_smtp_auth
);
941 ACP_FASSIGN(smtp_auth_type
);
942 ACP_FDUP(smtp_userid
);
943 ACP_FDUP(smtp_passwd
);
945 ac_clon
->tmp_smtp_pass
= NULL
;
947 ACP_FASSIGN(pop_before_smtp
);
948 ACP_FASSIGN(pop_before_smtp_timeout
);
949 ACP_FASSIGN(last_pop_login_time
);
951 ac_clon
->customhdr_list
= NULL
;
952 hdrs
= ac_prefs
->customhdr_list
;
953 while (hdrs
!= NULL
) {
954 ch
= (CustomHeader
*)hdrs
->data
;
956 cch
= g_new0(CustomHeader
, 1);
957 cch
->account_id
= ac_clon
->account_id
;
958 cch
->name
= (ch
->name
!= NULL
) ? g_strdup(ch
->name
) : NULL
;
959 cch
->value
= (ch
->value
!= NULL
) ? g_strdup(ch
->value
) : NULL
;
961 ac_clon
->customhdr_list
= g_slist_append(ac_clon
->customhdr_list
, cch
);
963 hdrs
= g_slist_next(hdrs
);
967 ACP_FASSIGN(sig_type
);
969 ACP_FASSIGN(auto_sig
);
971 ACP_FASSIGN(set_autocc
);
973 ACP_FASSIGN(set_autobcc
);
975 ACP_FASSIGN(set_autoreplyto
);
976 ACP_FDUP(auto_replyto
);
979 ACP_FASSIGN(default_encrypt
);
980 ACP_FASSIGN(default_sign
);
983 ACP_FASSIGN(set_smtpport
);
984 ACP_FASSIGN(smtpport
);
985 ACP_FASSIGN(set_popport
);
986 ACP_FASSIGN(popport
);
987 ACP_FASSIGN(set_imapport
);
988 ACP_FASSIGN(imapport
);
989 ACP_FASSIGN(set_nntpport
);
990 ACP_FASSIGN(nntpport
);
991 ACP_FASSIGN(set_domain
);
993 ACP_FASSIGN(mark_crosspost_read
);
994 ACP_FASSIGN(crosspost_col
);
996 ACP_FASSIGN(set_tunnelcmd
);
1001 ACP_FASSIGN(set_sent_folder
);
1002 ACP_FDUP(sent_folder
);
1003 ACP_FASSIGN(set_draft_folder
);
1004 ACP_FDUP(draft_folder
);
1005 ACP_FASSIGN(set_trash_folder
);
1006 ACP_FDUP(trash_folder
);
1007 /* don't want two default accounts */
1008 ac_clon
->is_default
= FALSE
;
1009 ACP_FASSIGN(folder
);
1011 account_list
= g_list_append(account_list
, ac_clon
);
1012 account_list_view_set();
1017 static void account_delete(GtkWidget
*widget
, gpointer data
)
1019 PrefsAccount
*ac_prefs
;
1020 gchar buf
[BUFFSIZE
];
1025 ac_prefs
= account_list_view_get_selected_account(edit_account
.list_view
);
1026 if (ac_prefs
== NULL
)
1029 g_snprintf(buf
, sizeof(buf
),
1030 _("Do you really want to delete the account '%s'?"),
1031 ac_prefs
->account_name
? ac_prefs
->account_name
:
1033 if (alertpanel_full(_("Delete account"), buf
,
1034 GTK_STOCK_CANCEL
, GTK_STOCK_DELETE
, NULL
, FALSE
,
1035 NULL
, ALERT_WARNING
, G_ALERTDEFAULT
) != G_ALERTALTERNATE
)
1037 account_list_dirty
= TRUE
;
1039 if (ac_prefs
->folder
) {
1042 item
= mainwindow_get_mainwindow()->summaryview
->folder_item
;
1043 if (item
&& item
->folder
== FOLDER(ac_prefs
->folder
))
1044 summary_clear_all(mainwindow_get_mainwindow()->summaryview
);
1045 folder_destroy(FOLDER(ac_prefs
->folder
));
1046 folderview_set_all();
1048 account_destroy(ac_prefs
);
1049 account_list_view_set();
1051 debug_print("Removing deleted account references for all the folders...\n");
1052 list
= folder_get_list();
1053 for (; list
!= NULL
; list
= list
->next
) {
1054 folder
= FOLDER(list
->data
);
1055 if (folder
->node
) /* && folder->type == F_? */
1056 g_node_traverse(folder
->node
, G_PRE_ORDER
,
1058 account_delete_references_func
,
1059 GINT_TO_POINTER(ac_prefs
->account_id
));
1062 debug_print("Removing filter rules relative to this account...\n");
1063 for(cur
= filtering_rules
; cur
!= NULL
;) {
1064 FilteringProp
* prop
= (FilteringProp
*) cur
->data
;
1066 if (prop
&& (prop
->account_id
== ac_prefs
->account_id
)) {
1067 /* get next item before we kill the current one */
1068 cur
= g_slist_next(cur
);
1070 /* unallocate filteringprop and unchain it from the list */
1071 filteringprop_free(prop
);
1072 filtering_rules
= g_slist_remove(filtering_rules
, prop
);
1074 cur
= g_slist_next(cur
);
1077 folder_write_list();
1080 static void account_up(GtkWidget
*widget
, gpointer data
)
1082 GtkTreePath
*sel
= account_list_view_get_selected_account_path
1083 (edit_account
.list_view
),
1085 GtkTreeIter isel
, iup
;
1086 GtkTreeModel
*model
= gtk_tree_view_get_model
1087 (GTK_TREE_VIEW(edit_account
.list_view
));
1091 account_list_dirty
= TRUE
;
1093 up
= gtk_tree_path_copy(sel
);
1095 gtk_tree_path_free(sel
);
1099 if (!gtk_tree_path_prev(up
)) {
1100 gtk_tree_path_free(up
);
1101 gtk_tree_path_free(sel
);
1105 if (!gtk_tree_model_get_iter(model
, &isel
, sel
)
1106 || !gtk_tree_model_get_iter(model
, &iup
, up
)) {
1107 gtk_tree_path_free(up
);
1108 gtk_tree_path_free(sel
);
1112 gtk_list_store_swap(GTK_LIST_STORE(model
), &isel
, &iup
);
1116 gtk_tree_path_free(up
);
1117 gtk_tree_path_free(sel
);
1120 static void account_down(GtkWidget
*widget
, gpointer data
)
1122 GtkTreePath
*sel
= account_list_view_get_selected_account_path
1123 (edit_account
.list_view
),
1125 GtkTreeIter isel
, idn
;
1126 GtkTreeModel
*model
= gtk_tree_view_get_model
1127 (GTK_TREE_VIEW(edit_account
.list_view
));
1131 account_list_dirty
= TRUE
;
1133 dn
= gtk_tree_path_copy(sel
);
1135 gtk_tree_path_free(sel
);
1139 /* XXX no check possible??? however, if down but at bottom, then
1140 * nothing seems to happen much anyway, so the following seems to
1142 gtk_tree_path_next(dn
);
1144 if (!gtk_tree_model_get_iter(model
, &isel
, sel
)
1145 || !gtk_tree_model_get_iter(model
, &idn
, dn
)) {
1146 gtk_tree_path_free(dn
);
1147 gtk_tree_path_free(sel
);
1151 gtk_list_store_swap(GTK_LIST_STORE(model
), &isel
, &idn
);
1155 gtk_tree_path_free(dn
);
1156 gtk_tree_path_free(sel
);
1159 static void account_set_default(GtkWidget
*widget
, gpointer data
)
1161 PrefsAccount
*ac_prefs
;
1163 if (NULL
== (ac_prefs
= account_list_view_get_selected_account
1164 (edit_account
.list_view
)))
1167 /* we need to change the store variables by resetting everything
1168 * and setting the new default one */
1169 account_list_view_set_default_by_id(edit_account
.list_view
,
1170 ac_prefs
->account_id
);
1172 account_set_as_default(ac_prefs
);
1173 account_list_view_set();
1175 cur_account
= ac_prefs
;
1176 account_flush_state();
1179 static void account_edit_close(GtkWidget
*widget
, gpointer data
)
1182 account_write_config_all();
1184 if (!cur_account
&& account_list
) {
1185 PrefsAccount
*ac_prefs
= (PrefsAccount
*)account_list
->data
;
1186 account_set_as_default(ac_prefs
);
1187 cur_account
= ac_prefs
;
1190 if (account_list_dirty
)
1191 account_flush_state();
1193 gtk_widget_hide(edit_account
.window
);
1198 static gint
account_delete_event(GtkWidget
*widget
, GdkEventAny
*event
,
1201 account_edit_close(NULL
, NULL
);
1205 static gboolean
account_key_pressed(GtkWidget
*widget
, GdkEventKey
*event
,
1208 if (event
&& event
->keyval
== GDK_Escape
)
1209 account_edit_close(NULL
, NULL
);
1213 static void account_list_view_add(PrefsAccount
*ac_prefs
)
1215 GtkTreeView
*list_view
= GTK_TREE_VIEW(edit_account
.list_view
);
1216 GtkListStore
*list_store
= GTK_LIST_STORE(gtk_tree_view_get_model(list_view
));
1217 gchar
*name
, *protocol
, *server
;
1218 gboolean has_getallbox
;
1221 name
= ac_prefs
->account_name
;
1223 protocol
= ac_prefs
->protocol
== A_POP3
?
1224 (ac_prefs
->ssl_pop
== SSL_TUNNEL
?
1226 ac_prefs
->ssl_pop
== SSL_STARTTLS
?
1227 "POP3 (TLS)" : "POP3") :
1228 ac_prefs
->protocol
== A_IMAP4
?
1229 (ac_prefs
->ssl_imap
== SSL_TUNNEL
?
1231 ac_prefs
->ssl_imap
== SSL_STARTTLS
?
1232 "IMAP4 (TLS)" : "IMAP4") :
1233 ac_prefs
->protocol
== A_NNTP
?
1234 (ac_prefs
->ssl_nntp
== SSL_TUNNEL
?
1235 "NNTP (SSL)" : "NNTP") :
1238 protocol
= ac_prefs
->protocol
== A_POP3
? "POP3" :
1239 ac_prefs
->protocol
== A_IMAP4
? "IMAP4" :
1240 ac_prefs
->protocol
== A_LOCAL
? "Local" :
1241 ac_prefs
->protocol
== A_NNTP
? "NNTP" : "";
1243 server
= ac_prefs
->protocol
== A_NNTP
1244 ? ac_prefs
->nntp_server
: ac_prefs
->recv_server
;
1246 has_getallbox
= (ac_prefs
->protocol
== A_POP3
||
1247 ac_prefs
->protocol
== A_IMAP4
||
1248 ac_prefs
->protocol
== A_NNTP
||
1249 ac_prefs
->protocol
== A_LOCAL
);
1250 getall
= has_getallbox
&& ac_prefs
->recv_at_getall
;
1252 account_list_view_insert_account_item(list_store
,
1253 name
, protocol
, server
,
1254 ac_prefs
->is_default
,
1259 static void account_list_view_set(void)
1262 gint prev_sel_account
;
1263 GtkListStore
*store
;
1265 store
= GTK_LIST_STORE(gtk_tree_view_get_model
1266 (GTK_TREE_VIEW(edit_account
.list_view
)));
1268 prev_sel_account
= account_list_view_get_selected_account_id
1269 (edit_account
.list_view
);
1271 gtk_list_store_clear(store
);
1273 for (cur
= account_list
; cur
!= NULL
; cur
= cur
->next
) {
1274 account_list_view_add((PrefsAccount
*)cur
->data
);
1275 if ((PrefsAccount
*)cur
->data
== cur_account
)
1276 account_list_view_select_account
1277 (edit_account
.list_view
,
1278 cur_account
->account_id
);
1281 if (prev_sel_account
>= 0)
1282 account_list_view_select_account(edit_account
.list_view
,
1286 /* set account list from CList */
1287 static void account_list_set(void)
1289 /* want to make sure we iterate *IN ORDER*, so therefore using
1290 * gtk_tree_model_XXXX_nth_child() */
1292 PrefsAccount
*ac_prefs
;
1293 GtkTreeModel
*model
= gtk_tree_view_get_model
1294 (GTK_TREE_VIEW(edit_account
.list_view
));
1296 while (account_list
)
1297 account_list
= g_list_remove(account_list
, account_list
->data
);
1299 n_rows
= gtk_tree_model_iter_n_children(model
, NULL
);
1301 for (row
= 0; row
< n_rows
; row
++) {
1304 if (!gtk_tree_model_iter_nth_child(model
, &iter
, NULL
, row
)) {
1305 g_warning("%s(%d) - no iter found???\n", __FILE__
, __LINE__
);
1310 gtk_tree_model_get(model
, &iter
,
1311 ACCOUNT_DATA
, &ac_prefs
,
1314 account_list
= g_list_append(account_list
, ac_prefs
);
1319 *\brief finds the PrefsAccounts which should be used to answer a mail
1321 *\param msginfo The message to be answered
1322 *\param reply_autosel Indicates whether reply account autoselection is on
1324 *\return PrefsAccount * the correct account, NULL if not found
1326 PrefsAccount
*account_get_reply_account(MsgInfo
*msginfo
, gboolean reply_autosel
)
1328 PrefsAccount
*account
= NULL
;
1329 /* select the account set in folderitem's property (if enabled) */
1330 if (msginfo
->folder
->prefs
&& msginfo
->folder
->prefs
->enable_default_account
)
1331 account
= account_find_from_id(msginfo
->folder
->prefs
->default_account
);
1333 /* select account by to: and cc: header if enabled */
1334 if (reply_autosel
) {
1335 gchar
* field
= NULL
;
1337 for (field
= msginfo
->to
; fieldno
++ < 2; field
= msginfo
->cc
) {
1338 if (!account
&& field
) {
1340 if (!strchr(field
, ',')) {
1341 Xstrdup_a(to
, field
, return NULL
);
1342 extract_address(to
);
1343 account
= account_find_from_address(to
);
1345 gchar
**split
= g_strsplit(field
, ",", -1);
1351 Xstrdup_a(to
, split
[i
], return NULL
);
1352 extract_address(to
);
1353 account
= account_find_from_address(to
);
1360 gchar deliveredto
[BUFFSIZE
];
1361 if (!procheader_get_header_from_msginfo
1362 (msginfo
, deliveredto
,sizeof deliveredto
, "Delivered-To:")) {
1363 gchar
*buf
= deliveredto
+ strlen("Delivered-To:");
1364 extract_address(buf
);
1365 account
= account_find_from_address(buf
);
1370 /* select the account for the whole folder (IMAP / NNTP) */
1372 /* FIXME: this is not right, because folder may be nested. we should
1373 * ascend the tree until we find a parent with proper account
1375 account
= msginfo
->folder
->folder
->account
;
1377 /* select current account */
1378 if (!account
) account
= cur_account
;
1384 *\brief Create data store
1386 static GtkListStore
* account_create_data_store(void)
1388 return gtk_list_store_new(N_ACCOUNT_COLUMNS
,
1389 GDK_TYPE_PIXBUF
, /* ACCOUNT_IS_DEFAULT */
1390 G_TYPE_BOOLEAN
, /* ACCOUNT_ENABLE_GET_ALL */
1391 G_TYPE_STRING
, /* ACCOUNT_NAME */
1392 G_TYPE_STRING
, /* ACCOUNT_PROTOCOL */
1393 G_TYPE_STRING
, /* ACCOUNT_SERVER */
1394 G_TYPE_POINTER
, /* ACCOUNT_DATA */
1399 *\brief Insert an account item in the list.
1401 *\return GtkTreeRowReference * A tree row reference, which is guaranteed to
1402 * stable whatever operations are performed on the list.
1404 static void account_list_view_insert_account_item(GtkListStore
*list_store
,
1405 const gchar
*account_name
,
1406 const gchar
*protocol
,
1407 const gchar
*server_name
,
1408 gboolean is_default
,
1409 gboolean is_get_all
,
1410 PrefsAccount
*account_data
)
1414 gtk_list_store_append(list_store
, &iter
);
1415 gtk_list_store_set(list_store
, &iter
,
1416 ACCOUNT_IS_DEFAULT
, is_default
? mark_pixbuf
: NULL
,
1417 ACCOUNT_ENABLE_GET_ALL
, is_get_all
,
1418 ACCOUNT_NAME
, account_name
,
1419 ACCOUNT_PROTOCOL
, protocol
,
1420 ACCOUNT_SERVER
, server_name
,
1421 ACCOUNT_DATA
, account_data
,
1426 *\brief Create and set up account list view, including tasks like
1427 * creating the data store (\ref account_create_data_store()),
1428 * creating images for the list view (\ref account_create_list_view_images()),
1429 * and setting up the account list's individual columns (\ref
1430 * account_create_list_view_columns()).
1432 *\return GtkWidget * The created list view widget.
1434 static GtkWidget
*account_list_view_create(void)
1436 GtkTreeView
*list_view
;
1437 GtkTreeSelection
*selector
;
1438 GtkListStore
*store
= account_create_data_store();
1440 list_view
= GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store
)));
1441 g_object_unref(G_OBJECT(store
));
1443 gtk_tree_view_set_rules_hint(list_view
, prefs_common
.use_stripes_everywhere
);
1444 gtk_tree_view_set_reorderable(list_view
, TRUE
);
1446 selector
= gtk_tree_view_get_selection(list_view
);
1447 gtk_tree_selection_set_mode(selector
, GTK_SELECTION_BROWSE
);
1449 /* create the columns */
1450 account_create_list_view_columns(GTK_WIDGET(list_view
));
1452 /* set a double click listener */
1453 g_signal_connect(G_OBJECT(list_view
), "row_activated",
1454 G_CALLBACK(account_double_clicked
),
1457 g_signal_connect(G_OBJECT(list_view
), "drag_begin",
1458 G_CALLBACK(drag_begin
),
1461 g_signal_connect(G_OBJECT(list_view
), "drag_end",
1462 G_CALLBACK(drag_end
),
1465 gtk_tree_view_set_reorderable(list_view
, TRUE
);
1466 return GTK_WIDGET(list_view
);
1469 static void account_create_list_view_images(GtkWidget
*list_view
)
1471 stock_pixbuf_gdk(list_view
, STOCK_PIXMAP_MARK
, &mark_pixbuf
);
1474 static void account_create_list_view_columns(GtkWidget
*list_view
)
1476 GtkTreeViewColumn
*column
;
1477 GtkCellRenderer
*renderer
;
1478 GtkTooltips
*tooltips
= gtk_tooltips_new();
1480 renderer
= gtk_cell_renderer_pixbuf_new();
1481 column
= gtk_tree_view_column_new_with_attributes
1482 (Q_("Accounts List Default Column Name|D"), renderer
,
1483 "pixbuf", ACCOUNT_IS_DEFAULT
,
1485 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
1486 gtk_tree_view_column_set_alignment (column
, 0.5);
1487 gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips
), column
->button
,
1488 _("Default account"), NULL
);
1490 renderer
= gtk_cell_renderer_toggle_new();
1491 g_object_set(renderer
,
1493 "activatable", TRUE
,
1495 column
= gtk_tree_view_column_new_with_attributes
1496 (Q_("Accounts List Get Column Name|G"), renderer
,
1497 "active", ACCOUNT_ENABLE_GET_ALL
,
1499 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
1500 gtk_tree_view_column_set_alignment (column
, 0.5);
1501 gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips
), column
->button
,
1502 _("'Get Mail' retrieves mail from the checked accounts"), NULL
);
1503 g_signal_connect(G_OBJECT(renderer
), "toggled",
1504 G_CALLBACK(account_get_all_toggled
),
1507 renderer
= gtk_cell_renderer_text_new();
1508 column
= gtk_tree_view_column_new_with_attributes
1509 (_("Name"), renderer
,
1510 "text", ACCOUNT_NAME
,
1512 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
1514 renderer
= gtk_cell_renderer_text_new();
1515 column
= gtk_tree_view_column_new_with_attributes
1516 (_("Protocol"), renderer
,
1517 "text", ACCOUNT_PROTOCOL
,
1519 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
1521 renderer
= gtk_cell_renderer_text_new();
1522 column
= gtk_tree_view_column_new_with_attributes
1523 (_("Server"), renderer
,
1524 "text", ACCOUNT_SERVER
,
1526 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
1530 *\brief Get currently selected account (by its unique ID)
1532 static gint
account_list_view_get_selected_account_id(GtkWidget
*list_view
)
1534 GtkTreeSelection
*selector
;
1535 GtkTreeModel
*model
;
1537 PrefsAccount
*res
= NULL
;
1539 selector
= gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view
));
1541 if (!gtk_tree_selection_get_selected(selector
, &model
, &iter
))
1544 gtk_tree_model_get(model
, &iter
, ACCOUNT_DATA
, &res
, -1);
1546 return res
->account_id
;
1550 *\brief Get the tree path of the currently selected account
1552 static GtkTreePath
*account_list_view_get_selected_account_path(GtkWidget
*list_view
)
1554 GtkTreeSelection
*selector
;
1555 GtkTreeModel
*model
;
1558 selector
= gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view
));
1560 if (!gtk_tree_selection_get_selected(selector
, &model
, &iter
))
1563 return gtk_tree_model_get_path(gtk_tree_view_get_model
1564 (GTK_TREE_VIEW(list_view
)), &iter
);
1568 *\brief Get the account data of the currently selected account
1570 static PrefsAccount
*account_list_view_get_selected_account(GtkWidget
*list_view
)
1572 GtkTreeSelection
*selector
;
1573 GtkTreeModel
*model
;
1575 PrefsAccount
*res
= NULL
;
1577 selector
= gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view
));
1579 if (!gtk_tree_selection_get_selected(selector
, &model
, &iter
))
1582 gtk_tree_model_get(model
, &iter
, ACCOUNT_DATA
, &res
, -1);
1588 *\brief Select a row by the account it represents
1590 *\return gboolean TRUE if found and selected, FALSE if not.
1592 static gboolean
account_list_view_select_account(GtkWidget
*list_view
, gint account_id
)
1594 FindAccountInStore fis
;
1595 GtkTreeModel
*model
;
1597 fis
.account_id
= account_id
;
1600 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(list_view
));
1602 gtk_tree_model_foreach(model
, (GtkTreeModelForeachFunc
) find_account_in_store
,
1606 GtkTreeSelection
*selection
;
1609 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view
));
1610 gtk_tree_selection_select_iter(selection
, &fis
.iter
);
1611 path
= gtk_tree_model_get_path(model
, &fis
.iter
);
1612 /* XXX returned path may not be valid??? create new one to be sure */
1613 gtk_tree_view_set_cursor(GTK_TREE_VIEW(list_view
), path
, NULL
, FALSE
);
1614 gtk_tree_path_free(path
);
1617 return fis
.path
!= NULL
;
1621 *\brief Set a new default account by its ID. (There is only one
1624 static void account_list_view_set_default_by_id(GtkWidget
*list_view
,
1627 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(list_view
));
1629 gtk_tree_model_foreach
1630 (model
, (GtkTreeModelForeachFunc
) set_new_default_account
,
1634 static gboolean
set_new_default_account(GtkTreeModel
*model
,
1639 PrefsAccount
*account
= NULL
;
1642 gtk_tree_model_get(model
, iter
,
1643 ACCOUNT_DATA
, &account
,
1646 if (*account_id
== account
->account_id
)
1649 pixbuf
= mark_pixbuf
;
1651 gtk_list_store_set(GTK_LIST_STORE(model
), iter
,
1652 ACCOUNT_IS_DEFAULT
, pixbuf
,
1658 static gboolean
find_account_in_store(GtkTreeModel
*model
,
1661 FindAccountInStore
*data
)
1663 PrefsAccount
*account
= NULL
;
1664 gtk_tree_model_get(model
, iter
, ACCOUNT_DATA
, &account
, -1);
1666 if (data
->account_id
== account
->account_id
) {
1667 data
->path
= path
; /* signal we found it */
1676 *\brief Triggered when "get all" column is activated or de-activated
1678 static void account_get_all_toggled(GtkCellRendererToggle
*widget
,
1680 GtkWidget
*list_view
)
1683 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(list_view
));
1684 PrefsAccount
*ac
= NULL
;
1687 if (!gtk_tree_model_get_iter_from_string(model
, &iter
, path
))
1690 gtk_tree_model_get(model
, &iter
,
1692 ACCOUNT_ENABLE_GET_ALL
, &get_all
,
1695 /* check if the account has a selectable get all checkbox anyway... */
1696 if (!(ac
->protocol
== A_POP3
||
1697 ac
->protocol
== A_IMAP4
||
1698 ac
->protocol
== A_NNTP
||
1699 ac
->protocol
== A_LOCAL
))
1702 /* set value in store */
1703 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
,
1704 ACCOUNT_ENABLE_GET_ALL
, !get_all
,
1707 /* set value in account */
1708 ac
->recv_at_getall
^= TRUE
;
1711 static void account_double_clicked(GtkTreeView
*list_view
,
1713 GtkTreeViewColumn
*column
,
1716 account_edit_prefs(NULL
, NULL
);
1719 static void drag_begin(GtkTreeView
*list_view
,
1720 GdkDragContext
*context
,
1723 /* XXX unfortunately a completed drag & drop does not emit
1724 * a "rows_reordered" signal, but a "row_changed" signal.
1725 * So during drag and drop, listen to "row_changed", and
1726 * update the account list accordingly */
1728 GtkTreeModel
*model
= gtk_tree_view_get_model(list_view
);
1729 g_signal_connect(G_OBJECT(model
), "row_changed",
1730 G_CALLBACK(account_row_changed_while_drag_drop
),
1734 static void drag_end(GtkTreeView
*list_view
,
1735 GdkDragContext
*context
,
1738 GtkTreeModel
*model
= gtk_tree_view_get_model(list_view
);
1739 g_signal_handlers_disconnect_by_func(G_OBJECT(model
),
1740 G_CALLBACK(account_row_changed_while_drag_drop
),
1744 static void account_row_changed_while_drag_drop(GtkTreeModel
*model
,
1748 GtkTreeView
*list_view
)