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