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 * Jeffrey Stedfast <fejj@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 <sys/types.h>
26
27 #include <gtk/gtk.h>
28 #include <glib/gi18n.h>
29 #include <glib/gstdio.h>
30
31 #include "e-alert.h"
32 #include "e-filter-file.h"
33 #include "e-filter-part.h"
34
G_DEFINE_TYPE(EFilterFile,e_filter_file,E_TYPE_FILTER_ELEMENT)35 G_DEFINE_TYPE (
36 EFilterFile,
37 e_filter_file,
38 E_TYPE_FILTER_ELEMENT)
39
40 static void
41 filter_file_filename_changed (GtkFileChooser *file_chooser,
42 EFilterElement *element)
43 {
44 EFilterFile *file = E_FILTER_FILE (element);
45 const gchar *path;
46
47 path = gtk_file_chooser_get_filename (file_chooser);
48
49 g_free (file->path);
50 file->path = g_strdup (path);
51 }
52
53 static void
filter_file_finalize(GObject * object)54 filter_file_finalize (GObject *object)
55 {
56 EFilterFile *file = E_FILTER_FILE (object);
57
58 xmlFree (file->type);
59 g_free (file->path);
60
61 /* Chain up to parent's finalize() method. */
62 G_OBJECT_CLASS (e_filter_file_parent_class)->finalize (object);
63 }
64
65 static gboolean
filter_file_validate(EFilterElement * element,EAlert ** alert)66 filter_file_validate (EFilterElement *element,
67 EAlert **alert)
68 {
69 EFilterFile *file = E_FILTER_FILE (element);
70
71 g_warn_if_fail (alert == NULL || *alert == NULL);
72
73 if (!file->path) {
74 if (alert)
75 *alert = e_alert_new ("filter:no-file", NULL);
76 return FALSE;
77 }
78
79 /* FIXME: do more to validate command-lines? */
80
81 if (g_strcmp0 (file->type, "file") == 0) {
82 if (!g_file_test (file->path, G_FILE_TEST_IS_REGULAR)) {
83 if (alert)
84 *alert = e_alert_new ("filter:bad-file",
85 file->path, NULL);
86 return FALSE;
87 }
88 } else if (g_strcmp0 (file->type, "command") == 0) {
89 /* Only requirements so far is that the
90 * command can't be an empty string. */
91 return (file->path[0] != '\0');
92 }
93
94 return TRUE;
95 }
96
97 static gint
filter_file_eq(EFilterElement * element_a,EFilterElement * element_b)98 filter_file_eq (EFilterElement *element_a,
99 EFilterElement *element_b)
100 {
101 EFilterFile *file_a = E_FILTER_FILE (element_a);
102 EFilterFile *file_b = E_FILTER_FILE (element_b);
103
104 /* Chain up to parent's eq() method. */
105 if (!E_FILTER_ELEMENT_CLASS (e_filter_file_parent_class)->
106 eq (element_a, element_b))
107 return FALSE;
108
109 if (g_strcmp0 (file_a->path, file_b->path) != 0)
110 return FALSE;
111
112 if (g_strcmp0 (file_a->type, file_b->type) != 0)
113 return FALSE;
114
115 return TRUE;
116 }
117
118 static xmlNodePtr
filter_file_xml_encode(EFilterElement * element)119 filter_file_xml_encode (EFilterElement *element)
120 {
121 EFilterFile *file = E_FILTER_FILE (element);
122 xmlNodePtr cur, value;
123 const gchar *type;
124
125 type = file->type ? file->type : "file";
126
127 value = xmlNewNode (NULL, (xmlChar *)"value");
128 xmlSetProp (value, (xmlChar *) "name", (xmlChar *) element->name);
129 xmlSetProp (value, (xmlChar *) "type", (xmlChar *) type);
130
131 cur = xmlNewChild (value, NULL, (xmlChar *) type, NULL);
132 xmlNodeSetContent (cur, (xmlChar *) file->path);
133
134 return value;
135 }
136
137 static gint
filter_file_xml_decode(EFilterElement * element,xmlNodePtr node)138 filter_file_xml_decode (EFilterElement *element,
139 xmlNodePtr node)
140 {
141 EFilterFile *file = E_FILTER_FILE (element);
142 gchar *name, *str, *type;
143 xmlNodePtr child;
144
145 name = (gchar *) xmlGetProp (node, (xmlChar *) "name");
146 type = (gchar *) xmlGetProp (node, (xmlChar *) "type");
147
148 xmlFree (element->name);
149 element->name = name;
150
151 xmlFree (file->type);
152 file->type = type;
153
154 g_free (file->path);
155 file->path = NULL;
156
157 child = node->children;
158 while (child != NULL) {
159 if (!strcmp ((gchar *) child->name, type)) {
160 str = (gchar *) xmlNodeGetContent (child);
161 file->path = g_strdup (str ? str : "");
162 xmlFree (str);
163
164 break;
165 } else if (child->type == XML_ELEMENT_NODE) {
166 g_warning (
167 "Unknown node type '%s' encountered "
168 "decoding a %s\n", child->name, type);
169 }
170
171 child = child->next;
172 }
173
174 return 0;
175 }
176
177 static GtkWidget *
filter_file_get_widget(EFilterElement * element)178 filter_file_get_widget (EFilterElement *element)
179 {
180 EFilterFile *file = E_FILTER_FILE (element);
181 GtkWidget *widget;
182
183 widget = gtk_file_chooser_button_new (
184 _("Choose a File"), GTK_FILE_CHOOSER_ACTION_OPEN);
185 gtk_file_chooser_set_filename (
186 GTK_FILE_CHOOSER (widget), file->path);
187 g_signal_connect (
188 widget, "selection-changed",
189 G_CALLBACK (filter_file_filename_changed), element);
190
191 return widget;
192 }
193
194 static void
filter_file_format_sexp(EFilterElement * element,GString * out)195 filter_file_format_sexp (EFilterElement *element,
196 GString *out)
197 {
198 EFilterFile *file = E_FILTER_FILE (element);
199
200 camel_sexp_encode_string (out, file->path);
201 }
202
203 static void
filter_file_describe(EFilterElement * element,GString * out)204 filter_file_describe (EFilterElement *element,
205 GString *out)
206 {
207 EFilterFile *file = E_FILTER_FILE (element);
208
209 g_string_append_c (out, E_FILTER_ELEMENT_DESCRIPTION_VALUE_START);
210 g_string_append (out, file->path);
211 g_string_append_c (out, E_FILTER_ELEMENT_DESCRIPTION_VALUE_END);
212 }
213
214 static void
e_filter_file_class_init(EFilterFileClass * class)215 e_filter_file_class_init (EFilterFileClass *class)
216 {
217 GObjectClass *object_class;
218 EFilterElementClass *filter_element_class;
219
220 object_class = G_OBJECT_CLASS (class);
221 object_class->finalize = filter_file_finalize;
222
223 filter_element_class = E_FILTER_ELEMENT_CLASS (class);
224 filter_element_class->validate = filter_file_validate;
225 filter_element_class->eq = filter_file_eq;
226 filter_element_class->xml_encode = filter_file_xml_encode;
227 filter_element_class->xml_decode = filter_file_xml_decode;
228 filter_element_class->get_widget = filter_file_get_widget;
229 filter_element_class->format_sexp = filter_file_format_sexp;
230 filter_element_class->describe = filter_file_describe;
231 }
232
233 static void
e_filter_file_init(EFilterFile * filter)234 e_filter_file_init (EFilterFile *filter)
235 {
236 }
237
238 /**
239 * filter_file_new:
240 *
241 * Create a new EFilterFile object.
242 *
243 * Return value: A new #EFilterFile object.
244 **/
245 EFilterFile *
e_filter_file_new(void)246 e_filter_file_new (void)
247 {
248 return g_object_new (E_TYPE_FILTER_FILE, NULL);
249 }
250
251 EFilterFile *
e_filter_file_new_type_name(const gchar * type)252 e_filter_file_new_type_name (const gchar *type)
253 {
254 EFilterFile *file;
255
256 file = e_filter_file_new ();
257 file->type = (gchar *) xmlStrdup ((xmlChar *) type);
258
259 return file;
260 }
261
262 void
e_filter_file_set_path(EFilterFile * file,const gchar * path)263 e_filter_file_set_path (EFilterFile *file,
264 const gchar *path)
265 {
266 g_return_if_fail (E_IS_FILTER_FILE (file));
267
268 g_free (file->path);
269 file->path = g_strdup (path);
270 }
271