No issues found
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * Copyright (C) 2005 Novell, Inc.
4 *
5 * Nautilus 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 * Nautilus 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., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Author: Anders Carlsson <andersca@imendio.com>
21 *
22 */
23
24 #include <config.h>
25 #include <string.h>
26
27 #include <eel/eel-glib-extensions.h>
28 #include <glib/gi18n.h>
29
30 #include "nautilus-file-utilities.h"
31 #include "nautilus-query.h"
32
33 struct NautilusQueryDetails {
34 char *text;
35 char *location_uri;
36 GList *mime_types;
37 gboolean show_hidden;
38
39 char **prepared_words;
40 };
41
42 static void nautilus_query_class_init (NautilusQueryClass *class);
43 static void nautilus_query_init (NautilusQuery *query);
44
45 G_DEFINE_TYPE (NautilusQuery, nautilus_query, G_TYPE_OBJECT);
46
47 static void
48 finalize (GObject *object)
49 {
50 NautilusQuery *query;
51
52 query = NAUTILUS_QUERY (object);
53 g_free (query->details->text);
54 g_strfreev (query->details->prepared_words);
55 g_free (query->details->location_uri);
56
57 G_OBJECT_CLASS (nautilus_query_parent_class)->finalize (object);
58 }
59
60 static void
61 nautilus_query_class_init (NautilusQueryClass *class)
62 {
63 GObjectClass *gobject_class;
64
65 gobject_class = G_OBJECT_CLASS (class);
66 gobject_class->finalize = finalize;
67
68 g_type_class_add_private (class, sizeof (NautilusQueryDetails));
69 }
70
71 static void
72 nautilus_query_init (NautilusQuery *query)
73 {
74 query->details = G_TYPE_INSTANCE_GET_PRIVATE (query, NAUTILUS_TYPE_QUERY,
75 NautilusQueryDetails);
76 query->details->show_hidden = TRUE;
77 query->details->location_uri = nautilus_get_home_directory_uri ();
78 }
79
80 static gchar *
81 prepare_string_for_compare (const gchar *string)
82 {
83 gchar *normalized, *res;
84
85 normalized = g_utf8_normalize (string, -1, G_NORMALIZE_NFD);
86 res = g_utf8_strdown (normalized, -1);
87 g_free (normalized);
88
89 return res;
90 }
91
92 gdouble
93 nautilus_query_matches_string (NautilusQuery *query,
94 const gchar *string)
95 {
96 gchar *prepared_string, *ptr;
97 gboolean found;
98 gdouble retval;
99 gint idx;
100
101 if (!query->details->text) {
102 return -1;
103 }
104
105 if (!query->details->prepared_words) {
106 prepared_string = prepare_string_for_compare (query->details->text);
107 query->details->prepared_words = g_strsplit (prepared_string, " ", -1);
108 g_free (prepared_string);
109 }
110
111 prepared_string = prepare_string_for_compare (string);
112 found = TRUE;
113 ptr = NULL;
114
115 for (idx = 0; query->details->prepared_words[idx] != NULL; idx++) {
116 if ((ptr = strstr (prepared_string, query->details->prepared_words[idx])) == NULL) {
117 found = FALSE;
118 break;
119 }
120 }
121
122 if (!found) {
123 g_free (prepared_string);
124 return -1;
125 }
126
127 retval = MAX (10.0, (50.0 / idx) - (gdouble) (ptr - prepared_string));
128 g_free (prepared_string);
129
130 return retval;
131 }
132
133 NautilusQuery *
134 nautilus_query_new (void)
135 {
136 return g_object_new (NAUTILUS_TYPE_QUERY, NULL);
137 }
138
139
140 char *
141 nautilus_query_get_text (NautilusQuery *query)
142 {
143 return g_strdup (query->details->text);
144 }
145
146 void
147 nautilus_query_set_text (NautilusQuery *query, const char *text)
148 {
149 g_free (query->details->text);
150 query->details->text = g_strstrip (g_strdup (text));
151
152 g_strfreev (query->details->prepared_words);
153 query->details->prepared_words = NULL;
154 }
155
156 char *
157 nautilus_query_get_location (NautilusQuery *query)
158 {
159 return g_strdup (query->details->location_uri);
160 }
161
162 void
163 nautilus_query_set_location (NautilusQuery *query, const char *uri)
164 {
165 g_free (query->details->location_uri);
166 query->details->location_uri = g_strdup (uri);
167 }
168
169 GList *
170 nautilus_query_get_mime_types (NautilusQuery *query)
171 {
172 return eel_g_str_list_copy (query->details->mime_types);
173 }
174
175 void
176 nautilus_query_set_mime_types (NautilusQuery *query, GList *mime_types)
177 {
178 g_list_free_full (query->details->mime_types, g_free);
179 query->details->mime_types = eel_g_str_list_copy (mime_types);
180 }
181
182 void
183 nautilus_query_add_mime_type (NautilusQuery *query, const char *mime_type)
184 {
185 query->details->mime_types = g_list_append (query->details->mime_types,
186 g_strdup (mime_type));
187 }
188
189 gboolean
190 nautilus_query_get_show_hidden_files (NautilusQuery *query)
191 {
192 return query->details->show_hidden;
193 }
194
195 void
196 nautilus_query_set_show_hidden_files (NautilusQuery *query, gboolean show_hidden)
197 {
198 query->details->show_hidden = show_hidden;
199 }
200
201 char *
202 nautilus_query_to_readable_string (NautilusQuery *query)
203 {
204 if (!query || !query->details->text || query->details->text[0] == '\0') {
205 return g_strdup (_("Search"));
206 }
207
208 return g_strdup_printf (_("Search for â%sâ"), query->details->text);
209 }
210
211 static char *
212 encode_home_uri (const char *uri)
213 {
214 char *home_uri;
215 const char *encoded_uri;
216
217 home_uri = nautilus_get_home_directory_uri ();
218
219 if (g_str_has_prefix (uri, home_uri)) {
220 encoded_uri = uri + strlen (home_uri);
221 if (*encoded_uri == '/') {
222 encoded_uri++;
223 }
224 } else {
225 encoded_uri = uri;
226 }
227
228 g_free (home_uri);
229
230 return g_markup_escape_text (encoded_uri, -1);
231 }
232
233 static char *
234 decode_home_uri (const char *uri)
235 {
236 char *home_uri;
237 char *decoded_uri;
238
239 if (g_str_has_prefix (uri, "file:")) {
240 decoded_uri = g_strdup (uri);
241 } else {
242 home_uri = nautilus_get_home_directory_uri ();
243
244 decoded_uri = g_strconcat (home_uri, "/", uri, NULL);
245
246 g_free (home_uri);
247 }
248
249 return decoded_uri;
250 }
251
252
253 typedef struct {
254 NautilusQuery *query;
255 gboolean in_text;
256 gboolean in_location;
257 gboolean in_mimetypes;
258 gboolean in_mimetype;
259 gboolean error;
260 } ParserInfo;
261
262 static void
263 start_element_cb (GMarkupParseContext *ctx,
264 const char *element_name,
265 const char **attribute_names,
266 const char **attribute_values,
267 gpointer user_data,
268 GError **err)
269 {
270 ParserInfo *info;
271
272 info = (ParserInfo *) user_data;
273
274 if (strcmp (element_name, "text") == 0)
275 info->in_text = TRUE;
276 else if (strcmp (element_name, "location") == 0)
277 info->in_location = TRUE;
278 else if (strcmp (element_name, "mimetypes") == 0)
279 info->in_mimetypes = TRUE;
280 else if (strcmp (element_name, "mimetype") == 0)
281 info->in_mimetype = TRUE;
282 }
283
284 static void
285 end_element_cb (GMarkupParseContext *ctx,
286 const char *element_name,
287 gpointer user_data,
288 GError **err)
289 {
290 ParserInfo *info;
291
292 info = (ParserInfo *) user_data;
293
294 if (strcmp (element_name, "text") == 0)
295 info->in_text = FALSE;
296 else if (strcmp (element_name, "location") == 0)
297 info->in_location = FALSE;
298 else if (strcmp (element_name, "mimetypes") == 0)
299 info->in_mimetypes = FALSE;
300 else if (strcmp (element_name, "mimetype") == 0)
301 info->in_mimetype = FALSE;
302 }
303
304 static void
305 text_cb (GMarkupParseContext *ctx,
306 const char *text,
307 gsize text_len,
308 gpointer user_data,
309 GError **err)
310 {
311 ParserInfo *info;
312 char *t, *uri;
313
314 info = (ParserInfo *) user_data;
315
316 t = g_strndup (text, text_len);
317
318 if (info->in_text) {
319 nautilus_query_set_text (info->query, t);
320 } else if (info->in_location) {
321 uri = decode_home_uri (t);
322 nautilus_query_set_location (info->query, uri);
323 g_free (uri);
324 } else if (info->in_mimetypes && info->in_mimetype) {
325 nautilus_query_add_mime_type (info->query, t);
326 }
327
328 g_free (t);
329
330 }
331
332 static void
333 error_cb (GMarkupParseContext *ctx,
334 GError *err,
335 gpointer user_data)
336 {
337 ParserInfo *info;
338
339 info = (ParserInfo *) user_data;
340
341 info->error = TRUE;
342 }
343
344 static GMarkupParser parser = {
345 start_element_cb,
346 end_element_cb,
347 text_cb,
348 NULL,
349 error_cb
350 };
351
352
353 static NautilusQuery *
354 nautilus_query_parse_xml (char *xml, gsize xml_len)
355 {
356 ParserInfo info = { NULL };
357 GMarkupParseContext *ctx;
358
359 if (xml_len == -1) {
360 xml_len = strlen (xml);
361 }
362
363 info.query = nautilus_query_new ();
364 info.in_text = FALSE;
365 info.error = FALSE;
366
367 ctx = g_markup_parse_context_new (&parser, 0, &info, NULL);
368 g_markup_parse_context_parse (ctx, xml, xml_len, NULL);
369
370 if (info.error) {
371 g_object_unref (info.query);
372 return NULL;
373 }
374
375 return info.query;
376 }
377
378
379 NautilusQuery *
380 nautilus_query_load (char *file)
381 {
382 NautilusQuery *query;
383 char *xml;
384 gsize xml_len;
385
386 if (!g_file_test (file, G_FILE_TEST_EXISTS)) {
387 return NULL;
388 }
389
390
391 g_file_get_contents (file, &xml, &xml_len, NULL);
392
393 if (xml_len == 0) {
394 return NULL;
395 }
396
397 query = nautilus_query_parse_xml (xml, xml_len);
398 g_free (xml);
399
400 return query;
401 }
402
403 static char *
404 nautilus_query_to_xml (NautilusQuery *query)
405 {
406 GString *xml;
407 char *text;
408 char *uri;
409 char *mimetype;
410 GList *l;
411
412 xml = g_string_new ("");
413 g_string_append (xml,
414 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
415 "<query version=\"1.0\">\n");
416
417 text = g_markup_escape_text (query->details->text, -1);
418 g_string_append_printf (xml, " <text>%s</text>\n", text);
419 g_free (text);
420
421 uri = encode_home_uri (query->details->location_uri);
422 g_string_append_printf (xml, " <location>%s</location>\n", uri);
423 g_free (uri);
424
425 if (query->details->mime_types) {
426 g_string_append (xml, " <mimetypes>\n");
427 for (l = query->details->mime_types; l != NULL; l = l->next) {
428 mimetype = g_markup_escape_text (l->data, -1);
429 g_string_append_printf (xml, " <mimetype>%s</mimetype>\n", mimetype);
430 g_free (mimetype);
431 }
432 g_string_append (xml, " </mimetypes>\n");
433 }
434
435 g_string_append (xml, "</query>\n");
436
437 return g_string_free (xml, FALSE);
438 }
439
440 gboolean
441 nautilus_query_save (NautilusQuery *query, char *file)
442 {
443 char *xml;
444 GError *err = NULL;
445 gboolean res;
446
447
448 res = TRUE;
449 xml = nautilus_query_to_xml (query);
450 g_file_set_contents (file, xml, strlen (xml), &err);
451 g_free (xml);
452
453 if (err != NULL) {
454 res = FALSE;
455 g_error_free (err);
456 }
457 return res;
458 }