nautilus-3.6.3/libnautilus-private/nautilus-query.c

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 }