1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * Copyright (C) 2005 Novell, Inc.
4 *
5 * Nemo is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * Nemo 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 GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; see the file COPYING. If not,
17 * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
18 * Boston, MA 02110-1335, USA.
19 *
20 * Author: Anders Carlsson <andersca@imendio.com>
21 *
22 */
23
24 #include <config.h>
25 #include <string.h>
26
27 #include "nemo-query.h"
28 #include <eel/eel-glib-extensions.h>
29 #include <glib/gi18n.h>
30 #include <libnemo-private/nemo-file-utilities.h>
31
32 struct NemoQueryDetails {
33 char *text;
34 char *location_uri;
35 GList *mime_types;
36 gboolean show_hidden;
37 };
38
39 G_DEFINE_TYPE (NemoQuery, nemo_query, G_TYPE_OBJECT);
40
41 static void
finalize(GObject * object)42 finalize (GObject *object)
43 {
44 NemoQuery *query;
45
46 query = NEMO_QUERY (object);
47 g_free (query->details->text);
48 g_free (query->details->location_uri);
49
50 G_OBJECT_CLASS (nemo_query_parent_class)->finalize (object);
51 }
52
53 static void
nemo_query_class_init(NemoQueryClass * class)54 nemo_query_class_init (NemoQueryClass *class)
55 {
56 GObjectClass *gobject_class;
57
58 gobject_class = G_OBJECT_CLASS (class);
59 gobject_class->finalize = finalize;
60
61 g_type_class_add_private (class, sizeof (NemoQueryDetails));
62 }
63
64 static void
nemo_query_init(NemoQuery * query)65 nemo_query_init (NemoQuery *query)
66 {
67 query->details = G_TYPE_INSTANCE_GET_PRIVATE (query, NEMO_TYPE_QUERY,
68 NemoQueryDetails);
69 }
70
71 NemoQuery *
nemo_query_new(void)72 nemo_query_new (void)
73 {
74 return g_object_new (NEMO_TYPE_QUERY, NULL);
75 }
76
77 char *
nemo_query_get_text(NemoQuery * query)78 nemo_query_get_text (NemoQuery *query)
79 {
80 g_return_val_if_fail (NEMO_IS_QUERY (query), NULL);
81
82 return g_strdup (query->details->text);
83 }
84
85 void
nemo_query_set_text(NemoQuery * query,const char * text)86 nemo_query_set_text (NemoQuery *query, const char *text)
87 {
88 g_return_if_fail (NEMO_IS_QUERY (query));
89
90 g_free (query->details->text);
91 query->details->text = g_strstrip (g_strdup (text));
92 }
93
94 char *
nemo_query_get_location(NemoQuery * query)95 nemo_query_get_location (NemoQuery *query)
96 {
97 g_return_val_if_fail (NEMO_IS_QUERY (query), NULL);
98
99 return g_strdup (query->details->location_uri);
100 }
101
102 void
nemo_query_set_location(NemoQuery * query,const char * uri)103 nemo_query_set_location (NemoQuery *query, const char *uri)
104 {
105 g_return_if_fail (NEMO_IS_QUERY (query));
106
107 g_free (query->details->location_uri);
108 query->details->location_uri = g_strdup (uri);
109 }
110
111 GList *
nemo_query_get_mime_types(NemoQuery * query)112 nemo_query_get_mime_types (NemoQuery *query)
113 {
114 g_return_val_if_fail (NEMO_IS_QUERY (query), NULL);
115
116 return eel_g_str_list_copy (query->details->mime_types);
117 }
118
119 void
nemo_query_set_mime_types(NemoQuery * query,GList * mime_types)120 nemo_query_set_mime_types (NemoQuery *query, GList *mime_types)
121 {
122 g_return_if_fail (NEMO_IS_QUERY (query));
123
124 g_list_free_full (query->details->mime_types, g_free);
125 query->details->mime_types = eel_g_str_list_copy (mime_types);
126 }
127
128 void
nemo_query_add_mime_type(NemoQuery * query,const char * mime_type)129 nemo_query_add_mime_type (NemoQuery *query, const char *mime_type)
130 {
131 g_return_if_fail (NEMO_IS_QUERY (query));
132
133 query->details->mime_types = g_list_append (query->details->mime_types,
134 g_strdup (mime_type));
135 }
136
137 void
nemo_query_set_show_hidden(NemoQuery * query,gboolean hidden)138 nemo_query_set_show_hidden (NemoQuery *query, gboolean hidden)
139 {
140 g_return_if_fail (NEMO_IS_QUERY (query));
141
142 query->details->show_hidden = hidden;
143 }
144
145 gboolean
nemo_query_get_show_hidden(NemoQuery * query)146 nemo_query_get_show_hidden (NemoQuery *query)
147 {
148 g_return_val_if_fail (NEMO_IS_QUERY (query), FALSE);
149
150 return query->details->show_hidden;
151 }
152
153 char *
nemo_query_to_readable_string(NemoQuery * query)154 nemo_query_to_readable_string (NemoQuery *query)
155 {
156 g_return_val_if_fail (NEMO_IS_QUERY (query), NULL);
157
158 GFile *file;
159 gchar *location_title, *readable;
160
161 if (!query || !query->details->text || query->details->text[0] == '\0') {
162 return g_strdup (_("Search"));
163 }
164
165 file = g_file_new_for_uri (query->details->location_uri);
166 location_title = nemo_compute_search_title_for_location (file);
167
168 g_object_unref (file);
169
170 readable = g_strdup_printf (_("Search for \"%s\" in \"%s\""), query->details->text, location_title);
171
172 g_free (location_title);
173
174 return readable;
175 }
176
177 static char *
encode_home_uri(const char * uri)178 encode_home_uri (const char *uri)
179 {
180 char *home_uri;
181 const char *encoded_uri;
182
183 home_uri = nemo_get_home_directory_uri ();
184
185 if (g_str_has_prefix (uri, home_uri)) {
186 encoded_uri = uri + strlen (home_uri);
187 if (*encoded_uri == '/') {
188 encoded_uri++;
189 }
190 } else {
191 encoded_uri = uri;
192 }
193
194 g_free (home_uri);
195
196 return g_markup_escape_text (encoded_uri, -1);
197 }
198
199 static char *
decode_home_uri(const char * uri)200 decode_home_uri (const char *uri)
201 {
202 char *home_uri;
203 char *decoded_uri;
204
205 if (g_str_has_prefix (uri, "file:")) {
206 decoded_uri = g_strdup (uri);
207 } else {
208 home_uri = nemo_get_home_directory_uri ();
209
210 decoded_uri = g_strconcat (home_uri, "/", uri, NULL);
211
212 g_free (home_uri);
213 }
214
215 return decoded_uri;
216 }
217
218
219 typedef struct {
220 NemoQuery *query;
221 gboolean in_text;
222 gboolean in_location;
223 gboolean in_mimetypes;
224 gboolean in_mimetype;
225 gboolean error;
226 } ParserInfo;
227
228 static void
start_element_cb(GMarkupParseContext * ctx,const char * element_name,const char ** attribute_names,const char ** attribute_values,gpointer user_data,GError ** err)229 start_element_cb (GMarkupParseContext *ctx,
230 const char *element_name,
231 const char **attribute_names,
232 const char **attribute_values,
233 gpointer user_data,
234 GError **err)
235 {
236 ParserInfo *info;
237
238 info = (ParserInfo *) user_data;
239
240 if (strcmp (element_name, "text") == 0)
241 info->in_text = TRUE;
242 else if (strcmp (element_name, "location") == 0)
243 info->in_location = TRUE;
244 else if (strcmp (element_name, "mimetypes") == 0)
245 info->in_mimetypes = TRUE;
246 else if (strcmp (element_name, "mimetype") == 0)
247 info->in_mimetype = TRUE;
248 }
249
250 static void
end_element_cb(GMarkupParseContext * ctx,const char * element_name,gpointer user_data,GError ** err)251 end_element_cb (GMarkupParseContext *ctx,
252 const char *element_name,
253 gpointer user_data,
254 GError **err)
255 {
256 ParserInfo *info;
257
258 info = (ParserInfo *) user_data;
259
260 if (strcmp (element_name, "text") == 0)
261 info->in_text = FALSE;
262 else if (strcmp (element_name, "location") == 0)
263 info->in_location = FALSE;
264 else if (strcmp (element_name, "mimetypes") == 0)
265 info->in_mimetypes = FALSE;
266 else if (strcmp (element_name, "mimetype") == 0)
267 info->in_mimetype = FALSE;
268 }
269
270 static void
text_cb(GMarkupParseContext * ctx,const char * text,gsize text_len,gpointer user_data,GError ** err)271 text_cb (GMarkupParseContext *ctx,
272 const char *text,
273 gsize text_len,
274 gpointer user_data,
275 GError **err)
276 {
277 ParserInfo *info;
278 char *t, *uri;
279
280 info = (ParserInfo *) user_data;
281
282 t = g_strndup (text, text_len);
283
284 if (info->in_text) {
285 nemo_query_set_text (info->query, t);
286 } else if (info->in_location) {
287 uri = decode_home_uri (t);
288 nemo_query_set_location (info->query, uri);
289 g_free (uri);
290 } else if (info->in_mimetypes && info->in_mimetype) {
291 nemo_query_add_mime_type (info->query, t);
292 }
293
294 g_free (t);
295
296 }
297
298 static void
error_cb(GMarkupParseContext * ctx,GError * err,gpointer user_data)299 error_cb (GMarkupParseContext *ctx,
300 GError *err,
301 gpointer user_data)
302 {
303 ParserInfo *info;
304
305 info = (ParserInfo *) user_data;
306
307 info->error = TRUE;
308 }
309
310 static GMarkupParser parser = {
311 start_element_cb,
312 end_element_cb,
313 text_cb,
314 NULL,
315 error_cb
316 };
317
318
319 static NemoQuery *
nemo_query_parse_xml(char * xml,gsize xml_len)320 nemo_query_parse_xml (char *xml, gsize xml_len)
321 {
322 ParserInfo info = { NULL };
323 GMarkupParseContext *ctx;
324
325 info.query = nemo_query_new ();
326 info.in_text = FALSE;
327 info.error = FALSE;
328
329 ctx = g_markup_parse_context_new (&parser, 0, &info, NULL);
330 g_markup_parse_context_parse (ctx, xml, xml_len, NULL);
331 g_markup_parse_context_free (ctx);
332
333 if (info.error) {
334 g_object_unref (info.query);
335 return NULL;
336 }
337
338 return info.query;
339 }
340
341
342 NemoQuery *
nemo_query_load(char * file)343 nemo_query_load (char *file)
344 {
345 NemoQuery *query;
346 char *xml;
347 gsize xml_len;
348
349 if (!g_file_test (file, G_FILE_TEST_EXISTS)) {
350 return NULL;
351 }
352
353
354 g_file_get_contents (file, &xml, &xml_len, NULL);
355
356 if (xml_len == 0) {
357 return NULL;
358 }
359
360 query = nemo_query_parse_xml (xml, xml_len);
361 g_free (xml);
362
363 return query;
364 }
365
366 static char *
nemo_query_to_xml(NemoQuery * query)367 nemo_query_to_xml (NemoQuery *query)
368 {
369 GString *xml;
370 char *text;
371 char *uri;
372 char *mimetype;
373 GList *l;
374
375 xml = g_string_new ("");
376 g_string_append (xml,
377 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
378 "<query version=\"1.0\">\n");
379
380 text = g_markup_escape_text (query->details->text, -1);
381 g_string_append_printf (xml, " <text>%s</text>\n", text);
382 g_free (text);
383
384 if (query->details->location_uri) {
385 uri = encode_home_uri (query->details->location_uri);
386 g_string_append_printf (xml, " <location>%s</location>\n", uri);
387 g_free (uri);
388 }
389
390 if (query->details->mime_types) {
391 g_string_append (xml, " <mimetypes>\n");
392 for (l = query->details->mime_types; l != NULL; l = l->next) {
393 mimetype = g_markup_escape_text (l->data, -1);
394 g_string_append_printf (xml, " <mimetype>%s</mimetype>\n", mimetype);
395 g_free (mimetype);
396 }
397 g_string_append (xml, " </mimetypes>\n");
398 }
399
400 g_string_append (xml, "</query>\n");
401
402 return g_string_free (xml, FALSE);
403 }
404
405 gboolean
nemo_query_save(NemoQuery * query,char * file)406 nemo_query_save (NemoQuery *query, char *file)
407 {
408 char *xml;
409 GError *err = NULL;
410 gboolean res;
411
412
413 res = TRUE;
414 xml = nemo_query_to_xml (query);
415 g_file_set_contents (file, xml, strlen (xml), &err);
416 g_free (xml);
417
418 if (err != NULL) {
419 res = FALSE;
420 g_error_free (err);
421 }
422 return res;
423 }
424