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 }