Remove inclusion of sys/socket.h from nntp-thread.c
[claws.git] / src / plugins / managesieve / sieve_manager.c
blobeabeb825f4c349fa5189ea9a0777898a667ed9cd
1 /*
2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 2004-2022 the Claws Mail team
4 * Copyright (C) 2014-2015 Charles Lehner
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; withouNULL, t even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #include "claws-features.h"
24 #endif
26 #include <gtk/gtk.h>
27 #include <gdk/gdkkeysyms.h>
28 #include <glib.h>
29 #include <glib/gi18n.h>
31 #include "defs.h"
32 #include "gtk/gtkutils.h"
33 #include "gtk/combobox.h"
34 #include "gtk/inputdialog.h"
35 #include "gtk/manage_window.h"
36 #include "alertpanel.h"
37 #include "utils.h"
38 #include "prefs.h"
39 #include "account.h"
40 #include "mainwindow.h"
41 #include "managesieve.h"
42 #include "sieve_editor.h"
43 #include "sieve_prefs.h"
44 #include "sieve_manager.h"
46 enum {
47 FILTER_NAME,
48 FILTER_ACTIVE,
49 N_FILTER_COLUMNS
52 typedef struct {
53 SieveManagerPage *page;
54 gchar *name_old;
55 gchar *name_new;
56 } CommandDataRename;
58 typedef struct {
59 SieveManagerPage *page;
60 gchar *filter_name;
61 } CommandDataName;
63 static void filter_got_load_error(SieveSession *session, gpointer data);
64 static void account_changed(GtkWidget *widget, SieveManagerPage *page);
65 static void sieve_manager_close(GtkWidget *widget, SieveManagerPage *page);
66 static gboolean sieve_manager_deleted(GtkWidget *widget, GdkEvent *event,
67 SieveManagerPage *page);
68 static void filter_set_active(SieveManagerPage *page, gchar *filter_name);
69 gboolean filter_find_by_name (GtkTreeModel *model, GtkTreeIter *iter,
70 gchar *filter_name);
71 static void got_session_error(SieveSession *session, const gchar *msg,
72 SieveManagerPage *page);
74 static GSList *manager_pages = NULL;
77 * Perform a command on all manager pages for a given session
79 #define manager_sessions_foreach(cur, session, page) \
80 for(cur = manager_pages; cur != NULL; cur = cur->next) \
81 if ((page = (SieveManagerPage *)cur->data) && \
82 page->active_session == session)
84 void sieve_managers_done()
86 GSList *list = manager_pages;
87 manager_pages = NULL;
88 g_slist_free_full(list, (GDestroyNotify)sieve_manager_done);
91 static void filters_list_clear(SieveManagerPage *page)
93 GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(page->filters_list)));
94 gtk_list_store_clear(list_store);
95 page->got_list = FALSE;
98 static void filters_list_delete_filter(SieveManagerPage *page, gchar *name)
100 GtkTreeIter iter;
101 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(page->filters_list));
103 if (!filter_find_by_name(model, &iter, name))
104 return;
106 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
110 static void filters_list_rename_filter(SieveManagerPage *page,
111 gchar *name_old, char *name_new)
113 GtkTreeIter iter;
114 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(page->filters_list));
116 if (!filter_find_by_name(model, &iter, name_old))
117 return;
119 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
120 FILTER_NAME, name_new,
121 -1);
124 static void filters_list_insert_filter(SieveManagerPage *page,
125 SieveScript *filter)
127 GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(page->filters_list)));
128 GtkTreeIter iter;
130 gtk_list_store_append(list_store, &iter);
131 gtk_list_store_set(list_store, &iter,
132 FILTER_NAME, filter->name,
133 FILTER_ACTIVE, filter->active,
134 -1);
137 static gchar *filters_list_get_selected_filter(GtkWidget *list_view)
139 GtkTreeSelection *selector;
140 GtkTreeModel *model;
141 GtkTreeIter iter;
142 gchar *res = NULL;
144 selector = gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view));
146 if (!gtk_tree_selection_get_selected(selector, &model, &iter))
147 return NULL;
149 gtk_tree_model_get(model, &iter, FILTER_NAME, &res, -1);
151 return res;
154 static void filter_add(GtkWidget *widget, SieveManagerPage *page)
156 SieveSession *session = page->active_session;
157 SieveEditorPage *editor;
158 if (!session)
159 return;
160 gchar *filter_name = input_dialog(_("Add Sieve script"),
161 _("Enter name for a new Sieve filter script."), "");
162 if (!filter_name || !filter_name[0])
163 return;
165 editor = sieve_editor_get(session, filter_name);
166 if (editor) {
167 /* TODO: show error that filter already exists */
168 sieve_editor_present(editor);
169 g_free(filter_name);
170 sieve_editor_load(editor,
171 (sieve_session_cb_fn)filter_got_load_error, page);
172 } else {
173 editor = sieve_editor_new(session, filter_name);
174 editor->is_new = TRUE;
175 sieve_editor_show(editor);
179 static void filter_got_load_error(SieveSession *session, gpointer data)
181 SieveManagerPage *page = data;
183 got_session_error(session, _("Unable to get script contents"), page);
186 static void filter_edit(GtkWidget *widget, SieveManagerPage *page)
188 SieveEditorPage *editor;
189 SieveSession *session = page->active_session;
190 gchar *filter_name;
192 if (!session)
193 return;
195 filter_name = filters_list_get_selected_filter(page->filters_list);
196 if (!filter_name)
197 return;
199 editor = sieve_editor_get(session, filter_name);
200 if (editor) {
201 sieve_editor_present(editor);
202 g_free(filter_name);
203 } else {
204 editor = sieve_editor_new(session, filter_name);
205 /* filter_name becomes ownership of newly created
206 * SieveEditorPage, so we do not need to free it here. */
207 sieve_editor_load(editor,
208 (sieve_session_cb_fn)filter_got_load_error, page);
212 static void filter_renamed(SieveSession *session, gboolean abort,
213 gboolean success, CommandDataRename *data)
215 SieveManagerPage *page = data->page;
216 GSList *cur;
218 if (abort) {
219 } else if (!success) {
220 got_session_error(session, "Unable to rename script", page);
221 } else {
222 manager_sessions_foreach(cur, session, page) {
223 filters_list_rename_filter(page, data->name_old,
224 data->name_new);
227 g_free(data->name_old);
228 g_free(data->name_new);
229 g_free(data);
232 static void filter_rename(GtkWidget *widget, SieveManagerPage *page)
234 CommandDataRename *cmd_data;
235 gchar *name_old, *name_new;
236 SieveSession *session;
238 name_old = filters_list_get_selected_filter(page->filters_list);
239 if (!name_old)
240 return;
242 session = page->active_session;
243 if (!session)
244 return;
246 name_new = input_dialog(_("Add Sieve script"),
247 _("Enter new name for the script."), name_old);
248 if (!name_new)
249 return;
251 cmd_data = g_new(CommandDataRename, 1);
252 cmd_data->name_new = name_new;
253 cmd_data->name_old = name_old;
254 cmd_data->page = page;
255 sieve_session_rename_script(session, name_old, name_new,
256 (sieve_session_data_cb_fn)filter_renamed, (gpointer)cmd_data);
259 static void filter_activated(SieveSession *session, gboolean abort,
260 const gchar *err, CommandDataName *cmd_data)
262 SieveManagerPage *page = cmd_data->page;
263 GSList *cur;
265 if (abort) {
266 } else if (err) {
267 got_session_error(session, err, page);
268 } else {
269 manager_sessions_foreach(cur, session, page) {
270 filter_set_active(page, cmd_data->filter_name);
273 g_free(cmd_data->filter_name);
274 g_free(cmd_data);
277 static void sieve_set_active_filter(SieveManagerPage *page, gchar *filter_name)
279 SieveSession *session;
280 CommandDataName *cmd_data;
282 session = page->active_session;
283 cmd_data = g_new(CommandDataName, 1);
284 cmd_data->filter_name = filter_name;
285 cmd_data->page = page;
287 sieve_session_set_active_script(session, filter_name,
288 (sieve_session_data_cb_fn)filter_activated, cmd_data);
291 static void filter_deleted(SieveSession *session, gboolean abort,
292 const gchar *err_msg,
293 CommandDataName *cmd_data)
295 SieveManagerPage *page = cmd_data->page;
296 GSList *cur;
298 if (abort) {
299 } else if (err_msg) {
300 got_session_error(session, err_msg, page);
301 } else {
302 manager_sessions_foreach(cur, session, page) {
303 filters_list_delete_filter(page,
304 cmd_data->filter_name);
307 g_free(cmd_data->filter_name);
308 g_free(cmd_data);
312 static void filter_delete(GtkWidget *widget, SieveManagerPage *page)
314 gchar buf[256];
315 gchar *filter_name;
316 SieveSession *session;
317 CommandDataName *cmd_data;
319 filter_name = filters_list_get_selected_filter(page->filters_list);
320 if (filter_name == NULL)
321 return;
323 session = page->active_session;
324 if (!session)
325 return;
327 g_snprintf(buf, sizeof(buf),
328 _("Do you really want to delete the filter '%s'?"), filter_name);
329 if (alertpanel_full(_("Delete filter"), buf,
330 NULL, _("_Cancel"), "edit-delete", _("_Delete"), NULL, NULL,
331 ALERTFOCUS_FIRST, FALSE, NULL, ALERT_WARNING) != G_ALERTALTERNATE)
332 return;
334 cmd_data = g_new(CommandDataName, 1);
335 cmd_data->filter_name = filter_name;
336 cmd_data->page = page;
338 sieve_session_delete_script(session, filter_name,
339 (sieve_session_data_cb_fn)filter_deleted, cmd_data);
343 * select a filter in the list
345 * return TRUE is successfully selected, FALSE otherwise
348 static gboolean filter_select (GtkWidget *list_view, GtkTreeModel *model,
349 GtkTreeIter *iter)
351 GtkTreeSelection *selection;
352 GtkTreePath* path;
354 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view));
355 gtk_tree_selection_select_iter(selection, iter);
356 path = gtk_tree_model_get_path(model, iter);
357 if (path == NULL) return FALSE;
358 gtk_tree_view_set_cursor(GTK_TREE_VIEW(list_view), path, NULL, FALSE);
359 gtk_tree_path_free(path);
360 return TRUE;
364 * find matching filter. return FALSE on match
366 static gboolean filter_search_equal_fn (GtkTreeModel *model, gint column,
367 const gchar *key, GtkTreeIter *iter, gpointer search_data)
369 SieveManagerPage *page = (SieveManagerPage *)search_data;
370 gchar *filter_name;
372 if (!key) return TRUE;
374 gtk_tree_model_get (model, iter, FILTER_NAME, &filter_name, -1);
376 if (strncmp (key, filter_name, strlen(key)) != 0) return TRUE;
377 return !filter_select(page->filters_list, model, iter);
381 * search for a filter row by its name. return true if found.
383 gboolean filter_find_by_name (GtkTreeModel *model, GtkTreeIter *iter,
384 gchar *filter_name)
386 gchar *name;
388 if (!gtk_tree_model_get_iter_first (model, iter))
389 return FALSE;
391 do {
392 gtk_tree_model_get (model, iter, FILTER_NAME, &name, -1);
393 if (strcmp(filter_name, name) == 0) {
394 return TRUE;
396 } while (gtk_tree_model_iter_next (model, iter));
397 return FALSE;
400 static gboolean filter_set_inactive(GtkTreeModel *model,
401 GtkTreePath *path, GtkTreeIter *iter, gpointer data)
403 gtk_list_store_set(GTK_LIST_STORE(model), iter,
404 FILTER_ACTIVE, FALSE,
405 -1);
406 return FALSE;
410 * Set the active filter in the table.
411 * @param filter_name The filter to make active (may be null)
413 static void filter_set_active(SieveManagerPage *page, gchar *filter_name)
415 GtkTreeIter iter;
416 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(page->filters_list));
418 /* Deactivate all filters */
419 gtk_tree_model_foreach(model, filter_set_inactive, NULL);
421 /* Set active filter */
422 if (filter_name) {
423 if (!filter_find_by_name (model, &iter, filter_name))
424 return;
426 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
427 FILTER_ACTIVE, TRUE,
428 -1);
432 static void filter_active_toggled(GtkCellRendererToggle *widget,
433 gchar *path,
434 SieveManagerPage *page)
436 GtkTreeIter iter;
437 gchar *filter_name;
438 gboolean active;
439 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(page->filters_list));
441 if (!gtk_tree_model_get_iter_from_string(model, &iter, path))
442 return;
444 /* get existing value */
445 gtk_tree_model_get(model, &iter,
446 FILTER_NAME, &filter_name,
447 FILTER_ACTIVE, &active,
448 -1);
450 sieve_set_active_filter(page, active ? NULL : filter_name);
453 static void filter_double_clicked(GtkTreeView *list_view,
454 GtkTreePath *path, GtkTreeViewColumn *column,
455 SieveManagerPage *page)
457 filter_edit(GTK_WIDGET(list_view), page);
460 static void filters_create_list_view_columns(SieveManagerPage *page,
461 GtkWidget *list_view)
463 GtkTreeViewColumn *column;
464 GtkCellRenderer *renderer;
465 GtkWidget *label;
467 /* Name */
468 renderer = gtk_cell_renderer_text_new();
469 column = gtk_tree_view_column_new_with_attributes
470 (_("Name"), renderer,
471 "text", FILTER_NAME,
472 NULL);
473 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
474 gtk_tree_view_column_set_expand(column, TRUE);
476 /* Active */
477 renderer = gtk_cell_renderer_toggle_new();
478 g_object_set(renderer,
479 "radio", TRUE,
480 "activatable", TRUE,
481 NULL);
482 column = gtk_tree_view_column_new_with_attributes
483 (_("Active"), renderer,
484 "active", FILTER_ACTIVE,
485 NULL);
486 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
487 gtk_tree_view_column_set_alignment (column, 0.5);
489 /* the column header needs a widget to have a tooltip */
490 label = gtk_label_new(gtk_tree_view_column_get_title(column));
491 gtk_widget_show(label);
492 gtk_tree_view_column_set_widget(column, label);
493 CLAWS_SET_TIP(label,
494 _("An account can only have one active script at a time."));
496 g_signal_connect(G_OBJECT(renderer), "toggled",
497 G_CALLBACK(filter_active_toggled), page);
499 gtk_tree_view_set_search_column(GTK_TREE_VIEW(list_view), FILTER_NAME);
500 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(list_view),
501 filter_search_equal_fn, page, NULL);
505 static GtkListStore* filters_create_data_store(void)
507 return gtk_list_store_new(N_FILTER_COLUMNS,
508 G_TYPE_STRING, /* FILTER_NAME */
509 G_TYPE_BOOLEAN, /* FILTER_ACTIVE */
510 -1);
513 static GtkWidget *filters_list_view_create(SieveManagerPage *page)
515 GtkTreeView *list_view;
516 GtkTreeSelection *selector;
517 GtkListStore *store = filters_create_data_store();
519 list_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)));
520 g_object_unref(G_OBJECT(store));
522 selector = gtk_tree_view_get_selection(list_view);
523 gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
525 /* create the columns */
526 filters_create_list_view_columns(page, GTK_WIDGET(list_view));
528 /* set a double click listener */
529 g_signal_connect(G_OBJECT(list_view), "row_activated",
530 G_CALLBACK(filter_double_clicked),
531 page);
533 return GTK_WIDGET(list_view);
536 static gboolean manager_key_pressed(GtkWidget *widget, GdkEventKey *event,
537 gpointer data)
539 SieveManagerPage* page = (SieveManagerPage *) data;
541 if (event && event->keyval == GDK_KEY_Escape)
542 sieve_manager_done(page);
544 return FALSE;
547 static void size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation)
549 cm_return_if_fail(allocation != NULL);
551 gtk_window_get_size(GTK_WINDOW(widget),
552 &sieve_config.manager_win_width, &sieve_config.manager_win_height);
555 static void got_session_error(SieveSession *session, const gchar *msg,
556 SieveManagerPage *page)
558 if (!g_slist_find(manager_pages, page))
559 return;
560 if (page->active_session != session)
561 return;
562 gtk_label_set_text(GTK_LABEL(page->status_text), msg);
565 static void sieve_manager_on_error(SieveSession *session,
566 const gchar *msg, gpointer user_data)
568 SieveManagerPage *page = (SieveManagerPage *)user_data;
569 got_session_error(session, msg, page);
572 static void sieve_manager_on_connected(SieveSession *session,
573 gboolean connected, gpointer user_data)
575 SieveManagerPage *page = (SieveManagerPage *)user_data;
576 if (page->active_session != session)
577 return;
578 if (!connected) {
579 gtk_widget_set_sensitive(GTK_WIDGET(page->vbox_buttons), FALSE);
580 gtk_label_set_text(GTK_LABEL(page->status_text),
581 _("Unable to connect"));
585 static void got_filter_listed(SieveSession *session, gboolean abort,
586 SieveScript *script, SieveManagerPage *page)
588 if (abort)
589 return;
590 if (!script) {
591 got_session_error(session, "Unable to list scripts", page);
592 return;
594 if (!script->name) {
595 /* done receiving list */
596 page->got_list = TRUE;
597 gtk_widget_set_sensitive(GTK_WIDGET(page->vbox_buttons), TRUE);
598 gtk_label_set_text(GTK_LABEL(page->status_text), "");
599 return;
601 filters_list_insert_filter(page, script);
605 * An account was selected from the menu. Get its list of scripts.
607 static void account_changed(GtkWidget *widget, SieveManagerPage *page)
609 gint account_id;
610 PrefsAccount *account;
611 SieveSession *session;
613 if (page->accounts_menu == NULL)
614 return;
616 account_id = combobox_get_active_data(GTK_COMBO_BOX(page->accounts_menu));
617 account = account_find_from_id(account_id);
618 if (!account)
619 return;
620 session = page->active_session = sieve_session_get_for_account(account);
621 sieve_session_handle_status(session,
622 sieve_manager_on_error,
623 sieve_manager_on_connected,
624 page);
625 filters_list_clear(page);
626 if (session_is_connected(SESSION(session))) {
627 gtk_label_set_text(GTK_LABEL(page->status_text),
628 _("Listing scripts..."));
629 } else {
630 gtk_label_set_text(GTK_LABEL(page->status_text),
631 _("Connecting..."));
633 sieve_session_list_scripts(session,
634 (sieve_session_data_cb_fn)got_filter_listed, (gpointer)page);
637 static SieveManagerPage *sieve_manager_page_new()
639 SieveManagerPage *page;
640 GtkWidget *window;
641 GtkWidget *hbox, *vbox, *vbox_allbuttons, *vbox_buttons;
642 GtkWidget *accounts_menu;
643 GtkWidget *label;
644 GtkWidget *scrolledwin;
645 GtkWidget *list_view;
646 GtkWidget *btn;
647 GtkWidget *status_text;
648 GtkTreeIter iter;
649 GtkListStore *menu;
650 GList *account_list, *cur;
651 PrefsAccount *ap;
652 SieveAccountConfig *config;
653 PrefsAccount *default_account = NULL;
655 static GdkGeometry geometry;
657 page = g_new0(SieveManagerPage, 1);
659 /* Manage Window */
661 window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "sievemanager");
662 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
663 gtk_window_set_title (GTK_WINDOW (window), _("Manage Sieve Filters"));
664 gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG);
665 MANAGE_WINDOW_SIGNALS_CONNECT (window);
667 g_signal_connect (G_OBJECT (window), "key_press_event",
668 G_CALLBACK (manager_key_pressed), page);
669 g_signal_connect (G_OBJECT(window), "size_allocate",
670 G_CALLBACK (size_allocate_cb), NULL);
671 g_signal_connect (G_OBJECT(window), "delete_event",
672 G_CALLBACK (sieve_manager_deleted), page);
674 if (!geometry.min_height) {
675 geometry.min_width = 350;
676 geometry.min_height = 280;
679 gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
680 GDK_HINT_MIN_SIZE);
681 gtk_window_set_default_size(GTK_WINDOW(window), sieve_config.manager_win_width,
682 sieve_config.manager_win_height);
683 gtk_window_set_type_hint(GTK_WINDOW(window),
684 GDK_WINDOW_TYPE_HINT_DIALOG);
686 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
687 gtk_container_add (GTK_CONTAINER (window), vbox);
689 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
690 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
692 /* Accounts list */
694 label = gtk_label_new (_("Account"));
695 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
697 accounts_menu = gtkut_sc_combobox_create(NULL, FALSE);
698 menu = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(accounts_menu)));
699 gtk_box_pack_start (GTK_BOX (hbox), accounts_menu, FALSE, FALSE, 0);
700 g_signal_connect (G_OBJECT(accounts_menu), "changed",
701 G_CALLBACK (account_changed), page);
703 account_list = account_get_list();
704 for (cur = account_list; cur != NULL; cur = cur->next) {
705 ap = (PrefsAccount *)cur->data;
706 config = sieve_prefs_account_get_config(ap);
707 if (config->enable) {
708 COMBOBOX_ADD (menu, ap->account_name, ap->account_id);
709 if (!default_account || ap->is_default)
710 default_account = ap;
712 sieve_prefs_account_free_config(config);
715 if (!default_account) {
716 gtk_widget_destroy(label);
717 gtk_widget_destroy(accounts_menu);
718 accounts_menu = NULL;
721 /* status */
722 status_text = gtk_label_new ("");
723 gtk_box_pack_start (GTK_BOX (hbox), status_text, FALSE, FALSE, 0);
724 gtk_label_set_justify (GTK_LABEL (status_text), GTK_JUSTIFY_LEFT);
726 /* Filters list */
728 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
729 gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
730 gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
732 /* Table */
734 scrolledwin = gtk_scrolled_window_new (NULL, NULL);
735 gtk_box_pack_start (GTK_BOX (hbox), scrolledwin, TRUE, TRUE, 0);
736 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwin),
737 GTK_POLICY_AUTOMATIC,
738 GTK_POLICY_AUTOMATIC);
740 list_view = filters_list_view_create(page);
741 gtk_container_add(GTK_CONTAINER(scrolledwin), list_view);
743 /* Buttons */
745 vbox_allbuttons = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
746 gtk_box_pack_start (GTK_BOX (hbox), vbox_allbuttons, FALSE, FALSE, 0);
748 /* buttons that depend on there being a connection */
749 vbox_buttons = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
750 gtk_widget_set_sensitive(vbox_buttons, FALSE);
751 gtk_box_pack_start (GTK_BOX (vbox_allbuttons), vbox_buttons, FALSE, FALSE, 0);
753 /* new */
754 btn = gtk_button_new_with_mnemonic("_New");
755 gtk_box_pack_start (GTK_BOX (vbox_buttons), btn, FALSE, FALSE, 0);
756 g_signal_connect (G_OBJECT(btn), "clicked",
757 G_CALLBACK (filter_add), page);
759 /* edit */
760 btn = gtk_button_new_with_mnemonic("_Edit");
761 gtk_box_pack_start (GTK_BOX (vbox_buttons), btn, FALSE, FALSE, 0);
762 g_signal_connect (G_OBJECT(btn), "clicked",
763 G_CALLBACK (filter_edit), page);
765 /* delete */
766 btn = gtkut_stock_button("edit-delete", _("D_elete"));
767 gtk_box_pack_start (GTK_BOX (vbox_buttons), btn, FALSE, FALSE, 0);
768 g_signal_connect (G_OBJECT(btn), "clicked",
769 G_CALLBACK (filter_delete), page);
771 /* rename */
772 btn = gtk_button_new_with_mnemonic(_("_Rename"));
773 gtk_box_pack_start (GTK_BOX (vbox_buttons), btn, FALSE, FALSE, 0);
774 g_signal_connect (G_OBJECT(btn), "clicked",
775 G_CALLBACK (filter_rename), page);
777 /* refresh */
778 btn = gtkut_stock_button("view-refresh", "_Refresh");
779 gtk_box_pack_end (GTK_BOX (vbox_allbuttons), btn, FALSE, FALSE, 0);
780 g_signal_connect (G_OBJECT(btn), "clicked",
781 G_CALLBACK (account_changed), page);
783 /* bottom area stuff */
785 gtkut_stock_button_set_create(&hbox,
786 &btn, "window-close", _("_Close"),
787 NULL, NULL, NULL, NULL, NULL, NULL);
789 /* close */
790 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
791 gtk_widget_grab_default (btn);
792 g_signal_connect (G_OBJECT (btn), "clicked",
793 G_CALLBACK (sieve_manager_close), page);
795 page->window = window;
796 page->accounts_menu = accounts_menu;
797 page->filters_list = list_view;
798 page->status_text = status_text;
799 page->vbox_buttons = vbox_buttons;
801 /* select default (first) account */
802 if (default_account) {
803 combobox_select_by_data(GTK_COMBO_BOX(accounts_menu),
804 default_account->account_id);
805 } else {
806 gtk_label_set_text(GTK_LABEL(status_text),
807 _("To use Sieve, enable it in an account's preferences."));
810 return page;
813 static gboolean sieve_manager_deleted(GtkWidget *widget, GdkEvent *event,
814 SieveManagerPage *page)
816 sieve_manager_done(page);
817 return FALSE;
820 static void sieve_manager_close(GtkWidget *widget, SieveManagerPage *page)
822 sieve_manager_done(page);
825 void sieve_manager_done(SieveManagerPage *page)
827 manager_pages = g_slist_remove(manager_pages, page);
828 sieve_sessions_discard_callbacks(page);
829 gtk_widget_destroy(page->window);
830 g_free(page);
833 void sieve_manager_show()
835 SieveManagerPage *page = sieve_manager_page_new();
836 manager_pages = g_slist_prepend(manager_pages, page);
837 gtk_widget_show_all(page->window);
840 void sieve_manager_script_created(SieveSession *session, const gchar *name)
842 SieveManagerPage *page;
843 SieveScript script = {.name = (gchar *)name};
844 GSList *cur;
846 manager_sessions_foreach(cur, session, page) {
847 filters_list_insert_filter(page, &script);