/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- * * Copyright (C) 2012 Red Hat, Inc. * * Nautilus is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nautilus is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; see the file COPYING. If not, * see . * */ #include #include #include #include "nautilus-search-hit.h" #include "nautilus-query.h" #define DEBUG_FLAG NAUTILUS_DEBUG_SEARCH_HIT #include "nautilus-debug.h" struct NautilusSearchHitDetails { char *uri; GDateTime *modification_time; GDateTime *access_time; gdouble fts_rank; gdouble relevance; }; enum { PROP_URI = 1, PROP_RELEVANCE, PROP_MODIFICATION_TIME, PROP_ACCESS_TIME, PROP_FTS_RANK, NUM_PROPERTIES }; G_DEFINE_TYPE (NautilusSearchHit, nautilus_search_hit, G_TYPE_OBJECT) void nautilus_search_hit_compute_scores (NautilusSearchHit *hit, NautilusQuery *query) { GDateTime *now; GFile *query_location; GFile *hit_location; GTimeSpan m_diff = G_MAXINT64; GTimeSpan a_diff = G_MAXINT64; GTimeSpan t_diff = G_MAXINT64; gdouble recent_bonus = 0.0; gdouble proximity_bonus = 0.0; gdouble match_bonus = 0.0; query_location = nautilus_query_get_location (query); hit_location = g_file_new_for_uri (hit->details->uri); if (g_file_has_prefix (hit_location, query_location)) { GFile *parent, *location; guint dir_count = 0; parent = g_file_get_parent (hit_location); while (!g_file_equal (parent, query_location)) { dir_count++; location = parent; parent = g_file_get_parent (location); g_object_unref (location); } g_object_unref (parent); if (dir_count < 10) { proximity_bonus = 10000.0 - 1000.0 * dir_count; } } g_object_unref (hit_location); now = g_date_time_new_now_local (); if (hit->details->modification_time != NULL) m_diff = g_date_time_difference (now, hit->details->modification_time); if (hit->details->access_time != NULL) a_diff = g_date_time_difference (now, hit->details->access_time); m_diff /= G_TIME_SPAN_DAY; a_diff /= G_TIME_SPAN_DAY; t_diff = MIN (m_diff, a_diff); if (t_diff > 90) { recent_bonus = 0.0; } else if (t_diff > 30) { recent_bonus = 10.0; } else if (t_diff > 14) { recent_bonus = 30.0; } else if (t_diff > 7) { recent_bonus = 50.0; } else if (t_diff > 1) { recent_bonus = 70.0; } else { recent_bonus = 100.0; } if (hit->details->fts_rank > 0) { match_bonus = MIN (500, 10.0 * hit->details->fts_rank); } else { match_bonus = 0.0; } hit->details->relevance = recent_bonus + proximity_bonus + match_bonus; DEBUG ("Hit %s computed relevance %.2f (%.2f + %.2f + %.2f)", hit->details->uri, hit->details->relevance, proximity_bonus, recent_bonus, match_bonus); g_date_time_unref (now); g_object_unref (query_location); } const char * nautilus_search_hit_get_uri (NautilusSearchHit *hit) { return hit->details->uri; } gdouble nautilus_search_hit_get_relevance (NautilusSearchHit *hit) { return hit->details->relevance; } static void nautilus_search_hit_set_uri (NautilusSearchHit *hit, const char *uri) { g_free (hit->details->uri); hit->details->uri = g_strdup (uri); } void nautilus_search_hit_set_fts_rank (NautilusSearchHit *hit, gdouble rank) { hit->details->fts_rank = rank; } void nautilus_search_hit_set_modification_time (NautilusSearchHit *hit, GDateTime *date) { if (hit->details->modification_time != NULL) g_date_time_unref (hit->details->modification_time); if (date != NULL) hit->details->modification_time = g_date_time_ref (date); else hit->details->modification_time = NULL; } void nautilus_search_hit_set_access_time (NautilusSearchHit *hit, GDateTime *date) { if (hit->details->access_time != NULL) g_date_time_unref (hit->details->access_time); if (date != NULL) hit->details->access_time = g_date_time_ref (date); else hit->details->access_time = NULL; } static void nautilus_search_hit_set_property (GObject *object, guint arg_id, const GValue *value, GParamSpec *pspec) { NautilusSearchHit *hit; hit = NAUTILUS_SEARCH_HIT (object); switch (arg_id) { case PROP_RELEVANCE: hit->details->relevance = g_value_get_double (value); break; case PROP_FTS_RANK: nautilus_search_hit_set_fts_rank (hit, g_value_get_double (value)); break; case PROP_URI: nautilus_search_hit_set_uri (hit, g_value_get_string (value)); break; case PROP_MODIFICATION_TIME: nautilus_search_hit_set_modification_time (hit, g_value_get_boxed (value)); break; case PROP_ACCESS_TIME: nautilus_search_hit_set_access_time (hit, g_value_get_boxed (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec); break; } } static void nautilus_search_hit_get_property (GObject *object, guint arg_id, GValue *value, GParamSpec *pspec) { NautilusSearchHit *hit; hit = NAUTILUS_SEARCH_HIT (object); switch (arg_id) { case PROP_RELEVANCE: g_value_set_double (value, hit->details->relevance); break; case PROP_FTS_RANK: g_value_set_double (value, hit->details->fts_rank); break; case PROP_URI: g_value_set_string (value, hit->details->uri); break; case PROP_MODIFICATION_TIME: g_value_set_boxed (value, hit->details->modification_time); break; case PROP_ACCESS_TIME: g_value_set_boxed (value, hit->details->access_time); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec); break; } } static void nautilus_search_hit_finalize (GObject *object) { NautilusSearchHit *hit = NAUTILUS_SEARCH_HIT (object); g_free (hit->details->uri); if (hit->details->access_time != NULL) { g_date_time_unref (hit->details->access_time); } if (hit->details->modification_time != NULL) { g_date_time_unref (hit->details->modification_time); } G_OBJECT_CLASS (nautilus_search_hit_parent_class)->finalize (object); } static void nautilus_search_hit_class_init (NautilusSearchHitClass *class) { GObjectClass *object_class; object_class = (GObjectClass *) class; object_class->finalize = nautilus_search_hit_finalize; object_class->get_property = nautilus_search_hit_get_property; object_class->set_property = nautilus_search_hit_set_property; g_object_class_install_property (object_class, PROP_URI, g_param_spec_string ("uri", "URI", "URI", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_MODIFICATION_TIME, g_param_spec_boxed ("modification-time", "Modification time", "Modification time", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_ACCESS_TIME, g_param_spec_boxed ("access-time", "acess time", "access time", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_RELEVANCE, g_param_spec_double ("relevance", NULL, NULL, -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_FTS_RANK, g_param_spec_double ("fts-rank", NULL, NULL, -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE)); g_type_class_add_private (class, sizeof (NautilusSearchHitDetails)); } static void nautilus_search_hit_init (NautilusSearchHit *hit) { hit->details = G_TYPE_INSTANCE_GET_PRIVATE (hit, NAUTILUS_TYPE_SEARCH_HIT, NautilusSearchHitDetails); } NautilusSearchHit * nautilus_search_hit_new (const char *uri) { NautilusSearchHit *hit; hit = g_object_new (NAUTILUS_TYPE_SEARCH_HIT, "uri", uri, NULL); return hit; }