[devhelp: 26/36] search: Sort first results prefixed with the search key (GNOME bug 601201)



commit 699c6d8d744b70ca068dab8b715154ac62478d16
Author: Aleksander Morgado <aleksander lanedo com>
Date:   Mon Dec 13 23:26:08 2010 +0100

    search: Sort first results prefixed with the search key (GNOME bug 601201)

 src/dh-keyword-model.c |  107 +++++++++++++++++++++++++++++++++++++++++-------
 src/dh-link.c          |   21 +++++++---
 2 files changed, 107 insertions(+), 21 deletions(-)
---
diff --git a/src/dh-keyword-model.c b/src/dh-keyword-model.c
index 0d219b2..94b74a2 100644
--- a/src/dh-keyword-model.c
+++ b/src/dh-keyword-model.c
@@ -337,12 +337,15 @@ dh_keyword_model_set_words (DhKeywordModel *model,
 }
 
 static GList *
-keyword_model_search (DhKeywordModel  *model,
-                      const gchar     *string,
-                      gchar          **stringv,
-                      const gchar     *book_id,
-                      gboolean         case_sensitive,
-                      DhLink         **exact_link)
+keyword_model_search_books (DhKeywordModel  *model,
+                            const gchar     *string,
+                            gchar          **stringv,
+                            const gchar     *book_id,
+                            gboolean         case_sensitive,
+                            gboolean         prefix,
+                            guint            max_hits,
+                            guint           *n_hits,
+                            DhLink         **exact_link)
 {
         DhKeywordModelPriv *priv;
         GList              *new_list = NULL, *b;
@@ -363,7 +366,7 @@ keyword_model_search (DhKeywordModel  *model,
         }
 
         for (b = dh_book_manager_get_books (priv->book_manager);
-             b && hits < MAX_HITS;
+             b && hits < max_hits;
              b = g_list_next (b)) {
                 DhBook *book;
                 GList *l;
@@ -376,7 +379,7 @@ keyword_model_search (DhKeywordModel  *model,
                 }
 
                 for (l = dh_book_get_keywords (book);
-                     l && hits < MAX_HITS;
+                     l && hits < max_hits;
                      l = g_list_next (l)) {
                         DhLink   *link;
                         gboolean  found;
@@ -403,18 +406,39 @@ keyword_model_search (DhKeywordModel  *model,
 
                         if (stringv[0] == NULL) {
                                 /* means only a page was specified, no keyword */
-                                if (g_strrstr (file_name, page_id))
-                                        found = TRUE;
+                                if (prefix) {
+                                        if (g_str_has_prefix (file_name, page_id))
+                                                found = TRUE;
+                                } else {
+                                        if (!g_str_has_prefix (file_name, page_id) &&
+                                            g_strrstr (file_name, page_id))
+                                                found = TRUE;
+                                }
                         } else {
-                                gint i;
+                                gboolean all_found;
+                                gboolean prefix_found;
+                                gint     i;
+
+                                prefix_found = FALSE;
+                                all_found = TRUE;
 
-                                found = TRUE;
                                 for (i = 0; stringv[i] != NULL; i++) {
-                                        if (!g_strrstr (name, stringv[i])) {
-                                                found = FALSE;
+                                        if (g_str_has_prefix (name, stringv[i])) {
+                                                prefix_found = TRUE;
+                                                /* If we get a prefix match and we're not
+                                                 * looking for prefix, stop. */
+                                                if (!prefix)
+                                                        break;
+                                        } else if (!g_strrstr (name, stringv[i])) {
+                                                all_found = FALSE;
                                                 break;
                                         }
                                 }
+
+                                found = (all_found &&
+                                         ((prefix && prefix_found) ||
+                                         (!prefix && !prefix_found)) ?
+                                         TRUE : FALSE);
                         }
 
                         g_free (name);
@@ -425,7 +449,8 @@ keyword_model_search (DhKeywordModel  *model,
                                 new_list = g_list_prepend (new_list, link);
                                 hits++;
 
-                                if (!*exact_link &&
+                                if (exact_link &&
+                                    !*exact_link &&
                                     dh_link_get_name (link) && (
                                             (dh_link_get_link_type (link) == DH_LINK_TYPE_PAGE &&
                                              page_id && strcmp (dh_link_get_name (link), page_id) == 0) ||
@@ -438,9 +463,61 @@ keyword_model_search (DhKeywordModel  *model,
 
         g_free (page_filename_prefix);
 
+        if (n_hits)
+                *n_hits = hits;
         return g_list_sort (new_list, dh_link_compare);
 }
 
+static GList *
+keyword_model_search (DhKeywordModel  *model,
+                      const gchar     *string,
+                      gchar          **stringv,
+                      const gchar     *book_id,
+                      gboolean         case_sensitive,
+                      DhLink         **exact_link)
+{
+        guint max_hits = MAX_HITS;
+        guint n_hits;
+        GList *list;
+        gint i;
+
+        g_debug ("-------------------");
+        g_debug ("string: %s", string);
+        g_debug ("book_id: %s", book_id);
+        for (i = 0; stringv[i]; i++) {
+                g_debug ("stringv[%d]: '%s'", i, stringv[i]);
+        }
+
+        /* First, look for prefixed items */
+        list = keyword_model_search_books (model,
+                                           string,
+                                           stringv,
+                                           book_id,
+                                           case_sensitive,
+                                           TRUE,
+                                           max_hits,
+                                           &n_hits,
+                                           exact_link);
+
+        if (n_hits < max_hits) {
+                GList *non_prefixed_list;
+
+                /* If not enough hits, get non-prefixed ones */
+                non_prefixed_list = keyword_model_search_books (model,
+                                                                string,
+                                                                stringv,
+                                                                book_id,
+                                                                case_sensitive,
+                                                                FALSE,
+                                                                max_hits - n_hits,
+                                                                NULL,
+                                                                NULL);
+                list = g_list_concat (list, non_prefixed_list);
+        }
+
+        return list;
+}
+
 DhLink *
 dh_keyword_model_filter (DhKeywordModel *model,
                          const gchar    *string,
diff --git a/src/dh-link.c b/src/dh-link.c
index a93b052..a3493b0 100644
--- a/src/dh-link.c
+++ b/src/dh-link.c
@@ -33,6 +33,7 @@ struct _DhLink {
         gchar       *base;
 
         gchar       *name;
+        gchar       *name_collation_key;
         gchar       *filename;
 
         DhLink      *book;
@@ -61,10 +62,11 @@ dh_link_get_type (void)
 static void
 link_free (DhLink *link)
 {
-	g_free (link->base);
-	g_free (link->id);
-	g_free (link->name);
-	g_free (link->filename);
+        g_free (link->base);
+        g_free (link->id);
+        g_free (link->name);
+        g_free (link->filename);
+        g_free (link->name_collation_key);
 
         if (link->book) {
                 dh_link_unref (link->book);
@@ -131,13 +133,20 @@ dh_link_compare (gconstpointer a,
 	gint    flags_diff;
 
         /* Sort deprecated hits last. */
-        flags_diff = (la->flags & DH_LINK_FLAGS_DEPRECATED) - 
+        flags_diff = (la->flags & DH_LINK_FLAGS_DEPRECATED) -
                 (lb->flags & DH_LINK_FLAGS_DEPRECATED);
         if (flags_diff != 0) {
                 return flags_diff;
         }
 
-        return strcmp (la->name, lb->name);
+        /* Collation-based sorting */
+        if (G_UNLIKELY (!la->name_collation_key))
+                la->name_collation_key = g_utf8_collate_key (la->name, -1);
+        if (G_UNLIKELY (!lb->name_collation_key))
+                lb->name_collation_key = g_utf8_collate_key (lb->name, -1);
+
+        return strcmp (la->name_collation_key,
+                       lb->name_collation_key);
 }
 
 DhLink *



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]