nautilus-3.6.3/libnautilus-private/nautilus-search-hit.c

No issues found

  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
  2  *
  3  * Copyright (C) 2012 Red Hat, 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  */
 21 
 22 #include <config.h>
 23 
 24 #include <string.h>
 25 #include <gio/gio.h>
 26 
 27 #include "nautilus-search-hit.h"
 28 #include "nautilus-query.h"
 29 #define DEBUG_FLAG NAUTILUS_DEBUG_SEARCH_HIT
 30 #include "nautilus-debug.h"
 31 
 32 struct NautilusSearchHitDetails
 33 {
 34 	char      *uri;
 35 
 36 	GDateTime *modification_time;
 37 	GDateTime *access_time;
 38 	gdouble    fts_rank;
 39 
 40 	gdouble    relevance;
 41 };
 42 
 43 enum {
 44 	PROP_URI = 1,
 45 	PROP_RELEVANCE,
 46 	PROP_MODIFICATION_TIME,
 47 	PROP_ACCESS_TIME,
 48 	PROP_FTS_RANK,
 49 	NUM_PROPERTIES
 50 };
 51 
 52 G_DEFINE_TYPE (NautilusSearchHit, nautilus_search_hit, G_TYPE_OBJECT)
 53 
 54 void
 55 nautilus_search_hit_compute_scores (NautilusSearchHit *hit,
 56 				    NautilusQuery     *query)
 57 {
 58 	GDateTime *now;
 59 	char *query_uri;
 60 	GFile *query_location;
 61 	GFile *hit_location;
 62 	GTimeSpan m_diff = G_MAXINT64;
 63 	GTimeSpan a_diff = G_MAXINT64;
 64 	GTimeSpan t_diff = G_MAXINT64;
 65 	gdouble recent_bonus = 0.0;
 66 	gdouble proximity_bonus = 0.0;
 67 	gdouble match_bonus = 0.0;
 68 
 69 	query_uri = nautilus_query_get_location (query);
 70 	query_location = g_file_new_for_uri (query_uri);
 71 	hit_location = g_file_new_for_uri (hit->details->uri);
 72 
 73 	if (g_file_has_prefix (hit_location, query_location)) {
 74 		GFile *parent, *location;
 75 		guint dir_count = 0;
 76 
 77 		parent = g_file_get_parent (hit_location);
 78 
 79 		while (!g_file_equal (parent, query_location)) {
 80 			dir_count++;
 81 			location = parent;
 82 			parent = g_file_get_parent (location);
 83 			g_object_unref (location);
 84 		}
 85 		g_object_unref (parent);
 86 
 87 		if (dir_count < 10) {
 88 			proximity_bonus = 10000.0 - 1000.0 * dir_count;
 89 		}
 90 	}
 91 	g_object_unref (hit_location);
 92 
 93 	now = g_date_time_new_now_local ();
 94 	if (hit->details->modification_time != NULL)
 95 		m_diff = g_date_time_difference (now, hit->details->modification_time);
 96 	if (hit->details->access_time != NULL)
 97 		a_diff = g_date_time_difference (now, hit->details->access_time);
 98 	m_diff /= G_TIME_SPAN_DAY;
 99 	a_diff /= G_TIME_SPAN_DAY;
100 	t_diff = MIN (m_diff, a_diff);
101 	if (t_diff > 90) {
102 		recent_bonus = 0.0;
103 	} else if (t_diff > 30) {
104 		recent_bonus = 10.0;
105 	} else if (t_diff > 14) {
106 		recent_bonus = 30.0;
107 	} else if (t_diff > 7) {
108 		recent_bonus = 50.0;
109 	} else if (t_diff > 1) {
110 		recent_bonus = 70.0;
111 	} else {
112 		recent_bonus = 100.0;
113 	}
114 
115 	if (hit->details->fts_rank > 0) {
116 		match_bonus = MIN (500, 10.0 * hit->details->fts_rank);
117 	} else {
118 		match_bonus = 0.0;
119 	}
120 
121 	hit->details->relevance = recent_bonus + proximity_bonus + match_bonus;
122 	DEBUG ("Hit %s computed relevance %.2f (%.2f + %.2f + %.2f)", hit->details->uri, hit->details->relevance,
123 	       proximity_bonus, recent_bonus, match_bonus);
124 
125 	g_date_time_unref (now);
126 }
127 
128 const char *
129 nautilus_search_hit_get_uri (NautilusSearchHit *hit)
130 {
131 	return hit->details->uri;
132 }
133 
134 gdouble
135 nautilus_search_hit_get_relevance (NautilusSearchHit *hit)
136 {
137 	return hit->details->relevance;
138 }
139 
140 static void
141 nautilus_search_hit_set_uri (NautilusSearchHit *hit,
142 			     const char        *uri)
143 {
144 	g_free (hit->details->uri);
145 	hit->details->uri = g_strdup (uri);
146 }
147 
148 void
149 nautilus_search_hit_set_fts_rank (NautilusSearchHit *hit,
150 				  gdouble            rank)
151 {
152 	hit->details->fts_rank = rank;
153 }
154 
155 void
156 nautilus_search_hit_set_modification_time (NautilusSearchHit *hit,
157 					   GDateTime         *date)
158 {
159 	if (hit->details->modification_time != NULL)
160 		g_date_time_unref (hit->details->modification_time);
161 	if (date != NULL)
162 		hit->details->modification_time = g_date_time_ref (date);
163 	else
164 		hit->details->modification_time = NULL;
165 }
166 
167 void
168 nautilus_search_hit_set_access_time (NautilusSearchHit *hit,
169 				     GDateTime         *date)
170 {
171 	if (hit->details->access_time != NULL)
172 		g_date_time_unref (hit->details->access_time);
173 	if (date != NULL)
174 		hit->details->access_time = g_date_time_ref (date);
175 	else
176 		hit->details->access_time = NULL;
177 }
178 
179 static void
180 nautilus_search_hit_set_property (GObject *object,
181 				  guint arg_id,
182 				  const GValue *value,
183 				  GParamSpec *pspec)
184 {
185 	NautilusSearchHit *hit;
186 
187 	hit = NAUTILUS_SEARCH_HIT (object);
188 
189 	switch (arg_id) {
190 	case PROP_RELEVANCE:
191 		hit->details->relevance = g_value_get_double (value);
192 	case PROP_FTS_RANK:
193 		nautilus_search_hit_set_fts_rank (hit, g_value_get_double (value));
194 		break;
195 	case PROP_URI:
196 		nautilus_search_hit_set_uri (hit, g_value_get_string (value));
197 		break;
198 	case PROP_MODIFICATION_TIME:
199 		nautilus_search_hit_set_modification_time (hit, g_value_get_boxed (value));
200 		break;
201 	case PROP_ACCESS_TIME:
202 		nautilus_search_hit_set_access_time (hit, g_value_get_boxed (value));
203 		break;
204 	default:
205 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
206 		break;
207 	}
208 }
209 
210 static void
211 nautilus_search_hit_get_property (GObject *object,
212 				  guint arg_id,
213 				  GValue *value,
214 				  GParamSpec *pspec)
215 {
216 	NautilusSearchHit *hit;
217 
218 	hit = NAUTILUS_SEARCH_HIT (object);
219 
220 	switch (arg_id) {
221 	case PROP_RELEVANCE:
222 		g_value_set_double (value, hit->details->relevance);
223 		break;
224 	case PROP_FTS_RANK:
225 		g_value_set_double (value, hit->details->fts_rank);
226 		break;
227 	case PROP_URI:
228 		g_value_set_string (value, hit->details->uri);
229 		break;
230 	case PROP_MODIFICATION_TIME:
231 		g_value_set_boxed (value, hit->details->modification_time);
232 		break;
233 	case PROP_ACCESS_TIME:
234 		g_value_set_boxed (value, hit->details->access_time);
235 		break;
236 	default:
237 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
238 		break;
239 	}
240 }
241 
242 static void
243 nautilus_search_hit_finalize (GObject *object)
244 {
245 	NautilusSearchHit *hit = NAUTILUS_SEARCH_HIT (object);
246 
247 	g_free (hit->details->uri);
248 
249 	if (hit->details->access_time != NULL) {
250 		g_date_time_unref (hit->details->access_time);
251 	}
252 	if (hit->details->modification_time != NULL) {
253 		g_date_time_unref (hit->details->modification_time);
254 	}
255 
256 	G_OBJECT_CLASS (nautilus_search_hit_parent_class)->finalize (object);
257 }
258 
259 static void
260 nautilus_search_hit_class_init (NautilusSearchHitClass *class)
261 {
262 	GObjectClass *object_class;
263 
264 	object_class = (GObjectClass *) class;
265 
266 	object_class->finalize = nautilus_search_hit_finalize;
267 	object_class->get_property = nautilus_search_hit_get_property;
268 	object_class->set_property = nautilus_search_hit_set_property;
269 
270 	g_object_class_install_property (object_class,
271 					 PROP_URI,
272 					 g_param_spec_string ("uri",
273 							      "URI",
274 							      "URI",
275 							      NULL,
276 							      G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_READABLE));
277 	g_object_class_install_property (object_class,
278 					 PROP_MODIFICATION_TIME,
279 					 g_param_spec_boxed ("modification-time",
280 							     "Modification time",
281 							     "Modification time",
282 							     G_TYPE_DATE_TIME,
283 							     G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
284 	g_object_class_install_property (object_class,
285 					 PROP_ACCESS_TIME,
286 					 g_param_spec_boxed ("access-time",
287 							     "acess time",
288 							     "access time",
289 							     G_TYPE_DATE_TIME,
290 							     G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
291 	g_object_class_install_property (object_class,
292 					 PROP_RELEVANCE,
293 					 g_param_spec_double ("relevance",
294 							      NULL,
295 							      NULL,
296 							      -G_MAXDOUBLE, G_MAXDOUBLE,
297 							      0,
298 							      G_PARAM_READWRITE));
299 	g_object_class_install_property (object_class,
300 					 PROP_FTS_RANK,
301 					 g_param_spec_double ("fts-rank",
302 							      NULL,
303 							      NULL,
304 							      -G_MAXDOUBLE, G_MAXDOUBLE,
305 							      0,
306 							      G_PARAM_READWRITE));
307 
308 	g_type_class_add_private (class, sizeof (NautilusSearchHitDetails));
309 }
310 
311 static void
312 nautilus_search_hit_init (NautilusSearchHit *hit)
313 {
314 	hit->details = G_TYPE_INSTANCE_GET_PRIVATE (hit,
315 						    NAUTILUS_TYPE_SEARCH_HIT,
316 						    NautilusSearchHitDetails);
317 }
318 
319 NautilusSearchHit *
320 nautilus_search_hit_new (const char *uri)
321 {
322 	NautilusSearchHit *hit;
323 
324 	hit = g_object_new (NAUTILUS_TYPE_SEARCH_HIT,
325 			    "uri", uri,
326 			    NULL);
327 
328 	return hit;
329 }