1 /*
2  * This program is free software; you can redistribute it and/or modify it
3  * under the terms of the GNU Lesser General Public License as published by
4  * the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful, but
7  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
9  * for more details.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, see <http://www.gnu.org/licenses/>.
13  *
14  *
15  * Authors:
16  *		Michael Zucchi <notzed@ximian.com>
17  *
18  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19  *
20  */
21 
22 #include "evolution-config.h"
23 
24 #include <string.h>
25 #include <glib/gi18n.h>
26 
27 #include "e-util/e-util-private.h"
28 
29 #include "e-mail-backend.h"
30 #include "em-folder-tree-model.h"
31 #include "em-utils.h"
32 #include "em-vfolder-editor-context.h"
33 #include "em-vfolder-editor.h"
34 #include "em-vfolder-editor-rule.h"
35 #include "mail-autofilter.h"
36 #include "e-mail-ui-session.h"
37 
38 #include "mail-vfolder-ui.h"
39 
40 #define d(x)  /* (printf("%s:%s: ",  G_STRLOC, G_STRFUNC), (x))*/
41 
42 /* NOTE: Once mail is moved to EDS, this context needs to be created ofr Mail UI. */
43 extern EMVFolderContext *context;	/* context remains open all time */
44 
45 void
vfolder_edit(EMailBackend * backend,GtkWindow * parent_window)46 vfolder_edit (EMailBackend *backend,
47               GtkWindow *parent_window)
48 {
49 	EShellBackend *shell_backend;
50 	GtkWidget *dialog;
51 	const gchar *config_dir;
52 	gchar *filename;
53 	EMailSession *session;
54 
55 	g_return_if_fail (E_IS_MAIL_BACKEND (backend));
56 	g_return_if_fail (GTK_IS_WINDOW (parent_window));
57 
58 	shell_backend = E_SHELL_BACKEND (backend);
59 	config_dir = e_shell_backend_get_config_dir (shell_backend);
60 	filename = g_build_filename (config_dir, "vfolders.xml", NULL);
61 	session = e_mail_backend_get_session (backend);
62 
63 	vfolder_load_storage (session);
64 
65 	dialog = em_vfolder_editor_new (context);
66 	gtk_window_set_title (
67 		GTK_WINDOW (dialog), _("Search Folders"));
68 	gtk_window_set_transient_for (
69 		GTK_WINDOW (dialog), parent_window);
70 
71 	switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
72 		case GTK_RESPONSE_OK:
73 			e_rule_context_save ((ERuleContext *) context, filename);
74 			break;
75 		default:
76 			e_rule_context_revert ((ERuleContext *) context, filename);
77 			break;
78 	}
79 
80 	gtk_widget_destroy (dialog);
81 }
82 
83 static void
vfolder_edit_response_cb(GtkWidget * dialog,gint response_id,gpointer user_data)84 vfolder_edit_response_cb (GtkWidget *dialog,
85                           gint response_id,
86                           gpointer user_data)
87 {
88 	if (response_id == GTK_RESPONSE_OK) {
89 		GObject *object;
90 		EFilterRule *rule;
91 		EFilterRule *newrule;
92 		const gchar *config_dir;
93 		gchar *user;
94 
95 		object = G_OBJECT (dialog);
96 		rule = g_object_get_data (object, "vfolder-rule");
97 		newrule = g_object_get_data (object, "vfolder-newrule");
98 
99 		e_filter_rule_copy (rule, newrule);
100 		config_dir = mail_session_get_config_dir ();
101 		user = g_build_filename (config_dir, "vfolders.xml", NULL);
102 		e_rule_context_save ((ERuleContext *) context, user);
103 		g_free (user);
104 	}
105 
106 	gtk_widget_destroy (dialog);
107 }
108 
109 void
vfolder_edit_rule(EMailSession * session,const gchar * folder_uri,EAlertSink * alert_sink)110 vfolder_edit_rule (EMailSession *session,
111                    const gchar *folder_uri,
112                    EAlertSink *alert_sink)
113 {
114 	GtkWidget *dialog;
115 	GtkWidget *widget;
116 	GtkWidget *container;
117 	EFilterRule *rule = NULL;
118 	EFilterRule *newrule;
119 	gchar *folder_name = NULL;
120 
121 	g_return_if_fail (E_IS_MAIL_SESSION (session));
122 	g_return_if_fail (folder_uri != NULL);
123 	g_return_if_fail (E_IS_ALERT_SINK (alert_sink));
124 
125 	e_mail_folder_uri_parse (
126 		CAMEL_SESSION (session), folder_uri,
127 		NULL, &folder_name, NULL);
128 
129 	if (folder_name != NULL) {
130 		rule = e_rule_context_find_rule (
131 			(ERuleContext *) context, folder_name, NULL);
132 		g_free (folder_name);
133 	}
134 
135 	if (rule == NULL) {
136 		/* TODO: we should probably just create it ... */
137 		e_alert_submit (
138 			alert_sink, "mail:vfolder-notexist",
139 			folder_uri, NULL);
140 		return;
141 	}
142 
143 	g_object_ref (rule);
144 	newrule = e_filter_rule_clone (rule);
145 
146 	dialog = gtk_dialog_new_with_buttons (
147 		_("Edit Search Folder"), NULL,
148 		GTK_DIALOG_DESTROY_WITH_PARENT,
149 		_("_Cancel"), GTK_RESPONSE_CANCEL,
150 		_("_OK"), GTK_RESPONSE_OK, NULL);
151 
152 	gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
153 	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
154 
155 	gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 500);
156 	gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
157 
158 	container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
159 	gtk_box_set_spacing (GTK_BOX (container), 6);
160 
161 	widget = e_filter_rule_get_widget (
162 		(EFilterRule *) newrule, (ERuleContext *) context);
163 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
164 	gtk_widget_show (widget);
165 
166 	g_object_set_data_full (
167 		G_OBJECT (dialog), "vfolder-rule",
168 		rule, (GDestroyNotify) g_object_unref);
169 	g_object_set_data_full (
170 		G_OBJECT (dialog), "vfolder-newrule",
171 		newrule, (GDestroyNotify) g_object_unref);
172 
173 	g_signal_connect (
174 		dialog, "response",
175 		G_CALLBACK (vfolder_edit_response_cb), NULL);
176 
177 	gtk_widget_show (dialog);
178 }
179 
180 static void
new_rule_clicked(GtkWidget * w,gint button,gpointer data)181 new_rule_clicked (GtkWidget *w,
182                   gint button,
183                   gpointer data)
184 {
185 	if (button == GTK_RESPONSE_OK) {
186 		const gchar *config_dir;
187 		gchar *user;
188 		EFilterRule *rule = g_object_get_data ((GObject *) w, "rule");
189 		EAlert *alert = NULL;
190 
191 		if (!e_filter_rule_validate (rule, &alert)) {
192 			e_alert_run_dialog (GTK_WINDOW (w), alert);
193 			g_object_unref (alert);
194 			return;
195 		}
196 
197 		if (e_rule_context_find_rule (
198 			(ERuleContext *) context, rule->name, rule->source)) {
199 			e_alert_run_dialog_for_args (
200 				GTK_WINDOW (w), "mail:vfolder-notunique",
201 				rule->name, NULL);
202 			return;
203 		}
204 
205 		g_object_ref (rule);
206 		e_rule_context_add_rule ((ERuleContext *) context, rule);
207 		config_dir = mail_session_get_config_dir ();
208 		user = g_build_filename (config_dir, "vfolders.xml", NULL);
209 		e_rule_context_save ((ERuleContext *) context, user);
210 		g_free (user);
211 	}
212 
213 	gtk_widget_destroy (w);
214 }
215 
216 static void
new_rule_changed_cb(EFilterRule * rule,GtkDialog * dialog)217 new_rule_changed_cb (EFilterRule *rule,
218                      GtkDialog *dialog)
219 {
220 	g_return_if_fail (rule != NULL);
221 	g_return_if_fail (dialog != NULL);
222 
223 	gtk_dialog_set_response_sensitive (
224 		dialog, GTK_RESPONSE_OK, rule->parts != NULL);
225 }
226 
227 /* clones a filter/search rule into a matching vfolder rule
228  * (assuming the same system definitions) */
229 EFilterRule *
vfolder_clone_rule(EMailSession * session,EFilterRule * in)230 vfolder_clone_rule (EMailSession *session,
231                     EFilterRule *in)
232 {
233 	EFilterRule *rule;
234 	xmlNodePtr xml;
235 
236 	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
237 
238 	rule = em_vfolder_editor_rule_new (session);
239 
240 	xml = e_filter_rule_xml_encode (in);
241 	e_filter_rule_xml_decode (rule, xml, (ERuleContext *) context);
242 	xmlFreeNodeList (xml);
243 
244 	return rule;
245 }
246 
247 static void
release_rule_notify_cb(gpointer rule)248 release_rule_notify_cb (gpointer rule)
249 {
250 	/* disconnect the "changed" signal */
251 	g_signal_handlers_disconnect_by_data (
252 		rule, g_object_get_data (rule, "editor-dlg"));
253 	g_object_set_data (rule, "editor-dlg", NULL);
254 	g_object_unref (rule);
255 }
256 
257 /* adds a rule with a gui */
258 void
vfolder_gui_add_rule(EMVFolderRule * rule)259 vfolder_gui_add_rule (EMVFolderRule *rule)
260 {
261 	GtkWidget *w;
262 	GtkDialog *gd;
263 	GtkWidget *container;
264 
265 	w = e_filter_rule_get_widget ((EFilterRule *) rule, (ERuleContext *) context);
266 
267 	gd = (GtkDialog *) gtk_dialog_new_with_buttons (
268 		_("New Search Folder"),
269 		NULL,
270 		GTK_DIALOG_DESTROY_WITH_PARENT,
271 		_("_Cancel"), GTK_RESPONSE_CANCEL,
272 		_("_OK"), GTK_RESPONSE_OK, NULL);
273 
274 	gtk_dialog_set_default_response (gd, GTK_RESPONSE_OK);
275 	gtk_container_set_border_width (GTK_CONTAINER (gd), 6);
276 
277 	container = gtk_dialog_get_content_area (gd);
278 	gtk_box_set_spacing (GTK_BOX (container), 6);
279 
280 	g_object_set (gd, "resizable", TRUE, NULL);
281 	gtk_window_set_default_size (GTK_WINDOW (gd), 500, 500);
282 	gtk_box_pack_start (GTK_BOX (container), w, TRUE, TRUE, 0);
283 	gtk_widget_show ((GtkWidget *) gd);
284 	g_object_set_data (G_OBJECT (rule), "editor-dlg", gd);
285 	g_object_set_data_full (
286 		G_OBJECT (gd), "rule", rule,
287 		release_rule_notify_cb);
288 	g_signal_connect (
289 		rule, "changed",
290 		G_CALLBACK (new_rule_changed_cb), gd);
291 	new_rule_changed_cb ((EFilterRule *) rule, gd);
292 	g_signal_connect (
293 		gd, "response",
294 		G_CALLBACK (new_rule_clicked), NULL);
295 	gtk_widget_show ((GtkWidget *) gd);
296 }
297 
298 void
vfolder_gui_add_from_message(EMailSession * session,CamelMimeMessage * message,gint flags,CamelFolder * folder)299 vfolder_gui_add_from_message (EMailSession *session,
300                               CamelMimeMessage *message,
301                               gint flags,
302                               CamelFolder *folder)
303 {
304 	EMVFolderRule *rule;
305 
306 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
307 
308 	rule = (EMVFolderRule *) em_vfolder_rule_from_message (
309 		context, message, flags, folder);
310 	vfolder_gui_add_rule (rule);
311 }
312 
313 void
vfolder_gui_add_from_address(EMailSession * session,CamelInternetAddress * addr,gint flags,CamelFolder * folder)314 vfolder_gui_add_from_address (EMailSession *session,
315                               CamelInternetAddress *addr,
316                               gint flags,
317                               CamelFolder *folder)
318 {
319 	EMVFolderRule *rule;
320 
321 	g_return_if_fail (addr != NULL);
322 
323 	rule = (EMVFolderRule *) em_vfolder_rule_from_address (
324 		context, addr, flags, folder);
325 	vfolder_gui_add_rule (rule);
326 }
327