[devhelp: 31/36] search: added book and prefix completions, as well as other fixes (GNOME bug 90469)



commit fec4d247efced7238b077a4ed75629d215fbd4ef
Author: Aleksander Morgado <aleksander lanedo com>
Date:   Thu Dec 16 21:50:53 2010 +0100

    search: added book and prefix completions, as well as other fixes (GNOME bug 90469)

 src/dh-book-tree.c     |    1 +
 src/dh-book.c          |   47 +++++++
 src/dh-book.h          |    1 +
 src/dh-keyword-model.c |  311 +++++++++++++++++++++++++++++++++++-------------
 src/dh-link.c          |    5 +-
 src/dh-main.c          |   42 +-------
 src/dh-search.c        |   90 +++-----------
 src/dh-search.h        |    3 +-
 src/dh-window.c        |    5 +-
 src/dh-window.h        |    3 +-
 10 files changed, 304 insertions(+), 204 deletions(-)
---
diff --git a/src/dh-book-tree.c b/src/dh-book-tree.c
index 8d773dd..3bbdb4a 100644
--- a/src/dh-book-tree.c
+++ b/src/dh-book-tree.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2001-2003 Mikael Hallendal <micke imendio com>
  * Copyright (C) 2003      CodeFactory AB
  * Copyright (C) 2008      Imendio AB
+ * Copyright (C) 2010      Lanedo GmbH
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
diff --git a/src/dh-book.c b/src/dh-book.c
index 0c52a06..511a412 100644
--- a/src/dh-book.c
+++ b/src/dh-book.c
@@ -67,6 +67,8 @@ typedef struct {
         GNode        *tree;
         /* Generated list of keywords in the book */
         GList        *keywords;
+        /* Generated list of keyword completions in the book */
+        GList        *completions;
 
         /* Monitor of this specific book */
         GFileMonitor *monitor;
@@ -115,6 +117,11 @@ book_finalize (GObject *object)
                 g_list_free (priv->keywords);
         }
 
+        if (priv->completions) {
+                g_list_foreach (priv->completions, (GFunc)g_free, NULL);
+                g_list_free (priv->completions);
+        }
+
         if (priv->monitor) {
                 g_object_unref (priv->monitor);
         }
@@ -188,6 +195,7 @@ dh_book_init (DhBook *book)
         priv->enabled = TRUE;
         priv->tree = NULL;
         priv->keywords = NULL;
+        priv->completions = NULL;
         priv->monitor = NULL;
         priv->monitor_event = BOOK_MONITOR_EVENT_NONE;
         priv->monitor_event_timeout_id = 0;
@@ -355,6 +363,45 @@ dh_book_get_keywords (DhBook *book)
         return priv->enabled ? priv->keywords : NULL;
 }
 
+GList *
+dh_book_get_completions (DhBook *book)
+{
+        DhBookPriv *priv;
+
+        g_return_val_if_fail (DH_IS_BOOK (book), NULL);
+
+        priv = GET_PRIVATE (book);
+
+        if (!priv->enabled)
+                return NULL;
+
+        if (!priv->completions) {
+                GList *l;
+                for (l = priv->keywords; l; l = g_list_next (l)) {
+                        DhLink *link = l->data;
+
+                        /* Add additional "page:" and "book:" completions */
+                        if (dh_link_get_link_type (link) == DH_LINK_TYPE_BOOK) {
+                                priv->completions =
+                                        g_list_prepend (priv->completions,
+                                                        g_strdup_printf ("book:%s",
+                                                                         dh_link_get_name (link)));
+                        }
+                        else if (dh_link_get_link_type (link) == DH_LINK_TYPE_PAGE) {
+                                priv->completions =
+                                        g_list_prepend (priv->completions,
+                                                        g_strdup_printf ("page:%s",
+                                                                         dh_link_get_name (link)));
+                        }
+
+                        priv->completions =  g_list_prepend (priv->completions,
+                                                          g_strdup (dh_link_get_name (link)));
+                }
+        }
+
+        return priv->completions;
+}
+
 GNode *
 dh_book_get_tree (DhBook *book)
 {
diff --git a/src/dh-book.h b/src/dh-book.h
index 3e28276..cd6362c 100644
--- a/src/dh-book.h
+++ b/src/dh-book.h
@@ -49,6 +49,7 @@ struct _DhBookClass {
 GType        dh_book_get_type        (void) G_GNUC_CONST;
 DhBook      *dh_book_new             (const gchar  *book_path);
 GList       *dh_book_get_keywords    (DhBook *book);
+GList       *dh_book_get_completions (DhBook *book);
 GNode       *dh_book_get_tree        (DhBook *book);
 const gchar *dh_book_get_name        (DhBook *book);
 const gchar *dh_book_get_title       (DhBook *book);
diff --git a/src/dh-keyword-model.c b/src/dh-keyword-model.c
index 2d0d47b..84dbb6e 100644
--- a/src/dh-keyword-model.c
+++ b/src/dh-keyword-model.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2002 CodeFactory AB
  * Copyright (C) 2002 Mikael Hallendal <micke imendio com>
  * Copyright (C) 2008 Imendio AB
+ * Copyright (C) 2010 Lanedo GmbH
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -336,11 +337,32 @@ dh_keyword_model_set_words (DhKeywordModel *model,
         model->priv->book_manager = g_object_ref (book_manager);
 }
 
+/* The Search rationale is as follows:
+ *
+ * - If 'book_id' is given, but no 'page_id' or 'keywords', the main page of
+ *   the book will only be shown, giving as exact match this book link.
+ * - If 'book_id' and 'page_id' are given, but no 'keywords', all the items
+ *   in the given page of the given book will be shown.
+ * - If 'book_id' and 'keywords' are given, but no 'page_id', up to MAX_HITS
+ *   items matching the keywords in the given book will be shown.
+ * - If 'book_id' and 'page_id' and 'keywords' are given, all the items
+ *   matching the keywords in the given page of the given book will be shown.
+ *
+ * - If 'page_id' is given, but no 'book_id' or 'keywords', all the items
+ *   in the given page will be shown, giving as exact match the page link.
+ * - If 'page_id' and 'keywords' are given but no 'book_id', all the items
+ *   matching the keywords in the given page will be shown.
+ *
+ * - If 'keywords' only are given, up to MAX_HITS items matching the keywords
+ *   will be shown. If keyword matches both a page link and a non-page one,
+ *   the page link is the one given as exact match.
+ */
 static GList *
 keyword_model_search_books (DhKeywordModel  *model,
                             const gchar     *string,
-                            gchar          **stringv,
+                            const GStrv      keywords,
                             const gchar     *book_id,
+                            const gchar     *page_id,
                             const gchar     *language,
                             gboolean         case_sensitive,
                             gboolean         prefix,
@@ -351,19 +373,18 @@ keyword_model_search_books (DhKeywordModel  *model,
         DhKeywordModelPriv *priv;
         GList              *new_list = NULL, *b;
         gint                hits = 0;
-        gchar              *page_id = NULL;
         gchar              *page_filename_prefix = NULL;
 
         priv = model->priv;
 
-        /* The search string may be prefixed by a page:foobar qualifier, it
-         * will be matched against the filenames of the hits to limit the
-         * search to pages whose filename is prefixed by "foobar.
-         */
-        if (stringv && g_str_has_prefix(stringv[0], "page:")) {
-                page_id = stringv[0] + 5;
+        if (page_id) {
                 page_filename_prefix = g_strdup_printf("%s.", page_id);
-                stringv++;
+                /* If filtering per page, increase the maximum number of
+                 * hits. This is due to the fact that a page may have
+                 * more than MAX_HITS keywords, and the page link may be
+                 * the last one in the list, but we always want to get it.
+                 */
+                max_hits = G_MAXINT;
         }
 
         for (b = dh_book_manager_get_books (priv->book_manager);
@@ -374,11 +395,28 @@ keyword_model_search_books (DhKeywordModel  *model,
 
                 book = DH_BOOK (b->data);
 
-                if (book_id &&
-                    g_strcmp0 (book_id, dh_book_get_name (book)) != 0) {
-                        continue;
+                /* Filtering by book? */
+                if (book_id) {
+                        if (g_strcmp0 (book_id, dh_book_get_name (book)) != 0) {
+                                continue;
+                        }
+
+                        /* Looking only for some specific book, without page or
+                         * keywords? Return only the match of the first book page.
+                         */
+                        if (!page_id && !keywords) {
+                                GNode *node;
+
+                                node = dh_book_get_tree (book);
+                                if (node) {
+                                        if (exact_link)
+                                                *exact_link = node->data;
+                                        return g_list_prepend (NULL, node->data);
+                                }
+                        }
                 }
 
+                /* Filtering by language? */
                 if (language &&
                     g_strcmp0 (language, dh_book_get_language (book)) != 0) {
                         continue;
@@ -389,78 +427,85 @@ keyword_model_search_books (DhKeywordModel  *model,
                      l = g_list_next (l)) {
                         DhLink   *link;
                         gboolean  found;
-                        gchar    *name;
-                        gchar    *file_name;
 
                         link = l->data;
                         found = FALSE;
 
-                        file_name = (case_sensitive ?
-                                     g_strdup (dh_link_get_file_name (link)) :
-                                     g_ascii_strdown (dh_link_get_file_name (link), -1));
+                        /* Filter by page? */
+                        if (page_id) {
+                                gchar *file_name;
+
+                                file_name = (case_sensitive ?
+                                             g_strdup (dh_link_get_file_name (link)) :
+                                             g_ascii_strdown (dh_link_get_file_name (link), -1));
 
-                        if (page_id &&
-                            (dh_link_get_link_type (link) == DH_LINK_TYPE_PAGE ||
-                             !g_str_has_prefix (file_name, page_filename_prefix))) {
+                                /* First, filter out all keywords not belonging
+                                 * to this given page. */
+                                if (!g_str_has_prefix (file_name, page_filename_prefix)) {
+                                        /* No need of this keyword. */
+                                        g_free (file_name);
+                                        continue;
+                                }
                                 g_free (file_name);
-                                continue;
-                        }
 
-                        name = (case_sensitive ?
-                                g_strdup (dh_link_get_name (link)) :
-                                g_ascii_strdown (dh_link_get_name (link), -1));
-
-                        if (stringv[0] == NULL) {
-                                /* means only a page was specified, no keyword */
-                                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;
+                                /* This means we got no keywords to look for. */
+                                if (!keywords) {
+                                        /* Show all in the page */
+                                        found = TRUE;
                                 }
-                        } else {
-                                gboolean all_found;
-                                gboolean prefix_found;
-                                gint     i;
+                        }
 
-                                prefix_found = FALSE;
-                                all_found = TRUE;
+                        if (!found && keywords) {
+                                gboolean  all_found;
+                                gboolean  prefix_found;
+                                gchar    *name;
+                                gint      i;
 
-                                for (i = 0; stringv[i] != NULL; i++) {
-                                        if (g_str_has_prefix (name, stringv[i])) {
+                                name = (case_sensitive ?
+                                        g_strdup (dh_link_get_name (link)) :
+                                        g_ascii_strdown (dh_link_get_name (link), -1));
+
+                                all_found = TRUE;
+                                prefix_found = FALSE;
+                                for (i = 0; keywords[i] != NULL; i++) {
+                                        if (g_str_has_prefix (name, keywords[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])) {
+                                        } else if (!g_strrstr (name, keywords[i])) {
                                                 all_found = FALSE;
                                                 break;
                                         }
                                 }
 
+                                g_free (name);
+
                                 found = (all_found &&
                                          ((prefix && prefix_found) ||
-                                         (!prefix && !prefix_found)) ?
+                                          (!prefix && !prefix_found)) ?
                                          TRUE : FALSE);
                         }
 
-                        g_free (name);
-                        g_free (file_name);
-
                         if (found) {
                                 /* Include in the new list. */
                                 new_list = g_list_prepend (new_list, link);
                                 hits++;
 
-                                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) ||
-                                            (strcmp (dh_link_get_name (link), string) == 0))) {
+                                if (!exact_link || !dh_link_get_name (link))
+                                    continue;
+
+                                /* Look for an exact link match. If the link is a PAGE,
+                                 * we can overwrite any previous exact link set. For
+                                 * example, when looking for GFile, we want the page,
+                                 * not the struct. */
+                                if (dh_link_get_link_type (link) == DH_LINK_TYPE_PAGE &&
+                                    ((page_id && strcmp (dh_link_get_name (link), page_id) == 0) ||
+                                     (strcmp (dh_link_get_name (link), string) == 0))) {
+                                        *exact_link = link;
+                                } else if (!*exact_link &&
+                                           strcmp (dh_link_get_name (link), string) == 0) {
                                         *exact_link = link;
                                 }
                         }
@@ -477,8 +522,9 @@ keyword_model_search_books (DhKeywordModel  *model,
 static GList *
 keyword_model_search (DhKeywordModel  *model,
                       const gchar     *string,
-                      gchar          **stringv,
+                      const GStrv      keywords,
                       const gchar     *book_id,
+                      const gchar     *page_id,
                       const gchar     *language,
                       gboolean         case_sensitive,
                       DhLink         **exact_link)
@@ -490,8 +536,9 @@ keyword_model_search (DhKeywordModel  *model,
         /* First, look for prefixed items */
         list = keyword_model_search_books (model,
                                            string,
-                                           stringv,
+                                           keywords,
                                            book_id,
+                                           page_id,
                                            language,
                                            case_sensitive,
                                            TRUE,
@@ -505,8 +552,9 @@ keyword_model_search (DhKeywordModel  *model,
                 /* If not enough hits, get non-prefixed ones */
                 non_prefixed_list = keyword_model_search_books (model,
                                                                 string,
-                                                                stringv,
+                                                                keywords,
                                                                 book_id,
+                                                                page_id,
                                                                 language,
                                                                 case_sensitive,
                                                                 FALSE,
@@ -519,6 +567,107 @@ keyword_model_search (DhKeywordModel  *model,
         return list;
 }
 
+/* Process the input search string and extract:
+ *  - If "book:" prefix given, a book_id
+ *  - If "page:" prefix given, a page_id
+ *  - All remaining keywords
+ *
+ * Returns TRUE when any of the output parameters are set.
+ */
+static gboolean
+keyword_model_process_search_string (const gchar  *string,
+                                     gchar       **book_id,
+                                     gchar       **page_id,
+                                     GStrv        *keywords)
+{
+        gchar *processed;
+        gchar *aux;
+        GStrv  strv;
+        gint   i;
+        gint   j;
+
+        *book_id = NULL;
+        *page_id = NULL;
+        *keywords = NULL;
+
+        /* First, remove all leading and trailing whitespaces in
+         * the search string */
+        processed = g_strdup (string);
+        g_strstrip (processed);
+
+        /* Also avoid words being separated by more than one whitespace,
+         * or g_strsplit() will give us empty strings. */
+        aux = processed;
+        while ((aux = strchr (aux, ' ')) != NULL) {
+                g_strchug (++aux);
+        }
+
+        /* If after all this we get an empty string, nothing else to do */
+        if (processed[0] == '\0') {
+                g_free (processed);
+                return FALSE;
+        }
+
+        /* Split the input string into tokens */
+        strv = g_strsplit (processed, " ", 0);
+        g_free (processed);
+
+        /* Allocate output keywords */
+        *keywords = g_new0 (gchar *, g_strv_length (strv) + 1);
+
+        for (i = 0, j = 0; strv[i]; i++) {
+                /* Book prefix? */
+                if (g_str_has_prefix (strv[i], "book:")) {
+                        /* If keyword given but no content, skip it. */
+                        if (strv[i][5] == '\0') {
+                                continue;
+                        }
+
+                        /* We got a second request of book, don't allow
+                         * this. */
+                        if (*book_id) {
+                                g_free (*book_id);
+                                g_free (*page_id);
+                                g_strfreev (*keywords);
+                                return FALSE;
+                        }
+
+                        *book_id = g_strdup (&strv[i][5]);
+                        continue;
+                }
+
+                /* Page prefix? */
+                if (g_str_has_prefix (strv[i], "page:")) {
+                        /* If keyword given but no content, skip it. */
+                        if (strv[i][5] == '\0') {
+                                continue;
+                        }
+
+                        /* We got a second request of page, don't allow
+                         * this. */
+                        if (*page_id) {
+                                g_free (*book_id);
+                                g_free (*page_id);
+                                g_strfreev (*keywords);
+                                return FALSE;
+                        }
+
+                        *page_id = g_strdup (&strv[i][5]);
+                        continue;
+                }
+
+                /* Then, a new keyword to look for */
+                (*keywords)[j++] = g_strdup (strv[i]);
+        }
+
+        if (j == 0) {
+                g_free (*keywords);
+                *keywords = NULL;
+        }
+
+        return TRUE;
+}
+
 DhLink *
 dh_keyword_model_filter (DhKeywordModel *model,
                          const gchar    *string,
@@ -533,8 +682,9 @@ dh_keyword_model_filter (DhKeywordModel *model,
         gint                 i;
         GtkTreePath         *path;
         GtkTreeIter          iter;
-        gchar               *processed_string;
-        gchar               *aux_str;
+        gchar               *book_id_in_string = NULL;
+        gchar               *page_id_in_string = NULL;
+        GStrv                keywords = NULL;
 
         g_return_val_if_fail (DH_IS_KEYWORD_MODEL (model), NULL);
         g_return_val_if_fail (string != NULL, NULL);
@@ -548,45 +698,44 @@ dh_keyword_model_filter (DhKeywordModel *model,
         new_list = NULL;
         hits = 0;
 
-        /* Remove all leading and trailing whitespaces in the search string */
-        processed_string = g_strdup (string);
-        g_strstrip (processed_string);
-        /* Avoid words being separated by more than one whitespace */
-        aux_str = processed_string;
-        while ((aux_str = strchr (aux_str, ' ')) != NULL) {
-                g_strchug (++aux_str);
-        }
-
-        if (processed_string[0] != '\0') {
-                gchar    **stringv;
-                gboolean   case_sensitive;
-
-                stringv = g_strsplit (processed_string, " ", -1);
+        /* Parse input search string, and make sure either one of the
+         * book ids is set; or both are set and are equal */
+        if (keyword_model_process_search_string (string,
+                                                 &book_id_in_string,
+                                                 &page_id_in_string,
+                                                 &keywords) &&
+            ((!book_id && book_id_in_string) ||
+             (book_id && !book_id_in_string) ||
+             g_strcmp0 (book_id, book_id_in_string) == 0)) {
+                gboolean case_sensitive;
 
                 /* Searches are case sensitive when any uppercase
                  * letter is used in the search terms, matching vim
                  * smartcase behaviour.
                  */
                 case_sensitive = FALSE;
-                for (i = 0; processed_string[i] != '\0'; i++) {
-                        if (g_ascii_isupper (processed_string[i])) {
+                for (i = 0; string[i] != '\0'; i++) {
+                        if (g_ascii_isupper (string[i])) {
                                 case_sensitive = TRUE;
                                 break;
                         }
                 }
 
                 new_list = keyword_model_search (model,
-                                                 processed_string,
-                                                 stringv,
-                                                 book_id,
+                                                 string,
+                                                 keywords,
+                                                 book_id ? book_id : book_id_in_string,
+                                                 page_id_in_string,
                                                  language,
                                                  case_sensitive,
                                                  &exact_link);
                 hits = g_list_length (new_list);
-
-                g_strfreev (stringv);
         }
 
+        g_free (book_id_in_string);
+        g_free (page_id_in_string);
+        g_strfreev (keywords);
+
         /* Update the list of hits. */
         g_list_free (priv->keyword_words);
         priv->keyword_words = new_list;
@@ -621,8 +770,6 @@ dh_keyword_model_filter (DhKeywordModel *model,
                 }
         }
 
-        g_free (processed_string);
-
         if (hits == 1) {
                 return priv->keyword_words->data;
         }
diff --git a/src/dh-link.c b/src/dh-link.c
index a3493b0..444668a 100644
--- a/src/dh-link.c
+++ b/src/dh-link.c
@@ -200,7 +200,10 @@ dh_link_get_page_name (DhLink *link)
 const gchar *
 dh_link_get_file_name (DhLink *link)
 {
-        if (link->page) {
+        /* Return filename if the link is itself a page
+         * or if the link is within a page */
+        if (link->page ||
+            link->type == DH_LINK_TYPE_PAGE) {
                 return link->filename;
         }
 
diff --git a/src/dh-main.c b/src/dh-main.c
index 29a892e..edba84e 100644
--- a/src/dh-main.c
+++ b/src/dh-main.c
@@ -71,54 +71,14 @@ static GOptionEntry options[] = {
 };
 
 static void
-extract_book_id (const gchar  *str,
-                 gchar       **term,
-                 gchar       **book_id)
-{
-        gchar   **strv;
-        gint      i;
-        GString  *term_string;
-
-        *term = NULL;
-        *book_id = NULL;
-
-        term_string = g_string_new (NULL);
-
-        strv = g_strsplit (str, " ", 0);
-
-        i = 0;
-        while (strv[i]) {
-                if (!*book_id && g_str_has_prefix (strv[i], "book:")) {
-                        *book_id = g_strdup (strv[i] + 5);
-                } else {
-                        if (i > 0 && term_string->len > 0) {
-                                g_string_append_c (term_string, ' ');
-                        }
-                        g_string_append (term_string, strv[i]);
-                }
-
-                i++;
-        }
-
-        g_strfreev (strv);
-
-        *term = g_string_free (term_string, FALSE);
-}
-
-static void
 search_normal (DhWindow    *window,
                const gchar *str)
 {
-        gchar *term, *book_id;
-
         if (str[0] == '\0') {
                 return;
         }
 
-        extract_book_id (str, &term, &book_id);
-        dh_window_search (window, term, book_id);
-        g_free (term);
-        g_free (book_id);
+        dh_window_search (window, str);
 }
 
 static gboolean
diff --git a/src/dh-search.c b/src/dh-search.c
index ea6bd22..b8fa391 100644
--- a/src/dh-search.c
+++ b/src/dh-search.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2001-2003 CodeFactory AB
  * Copyright (C) 2001-2003 Mikael Hallendal <micke imendio com>
  * Copyright (C) 2005-2008 Imendio AB
+ * Copyright (C) 2010 Lanedo GmbH
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -83,7 +84,6 @@ static void         search_entry_text_inserted_cb   (GtkEntry         *entry,
                                                      DhSearch         *search);
 static gboolean     search_complete_idle            (DhSearch         *search);
 static gboolean     search_filter_idle              (DhSearch         *search);
-static const gchar *search_complete_func            (DhLink           *link);
 
 enum {
         LINK_SELECTED,
@@ -98,11 +98,11 @@ enum {
 };
 
 enum {
-	COL_TITLE,
-	COL_BOOK_ID,
+        COL_TITLE,
+        COL_BOOK_ID,
         COL_BOOK,
         COL_ROW_TYPE,
-	N_COLUMNS
+        N_COLUMNS
 };
 
 G_DEFINE_TYPE (DhSearch, dh_search, GTK_TYPE_VBOX);
@@ -283,56 +283,6 @@ search_entry_key_press_event_cb (GtkEntry    *entry,
 }
 
 static void
-search_combo_set_active_book_id (DhSearch    *search,
-                                 const gchar *book_id)
-{
-        DhSearchPriv *priv = GET_PRIVATE (search);
-        GtkTreeIter   iter;
-        GtkTreeModel *model;
-        gboolean      has_next;
-
-        g_signal_handlers_block_by_func (priv->book_combo,
-                                         search_combo_changed_cb,
-                                         search);
-
-        if (book_id != NULL) {
-                model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->book_combo));
-
-                has_next = gtk_tree_model_get_iter_first (model, &iter);
-                while (has_next) {
-                        gchar *id;
-                        gint row_type;
-
-                        gtk_tree_model_get (model,
-                                            &iter,
-                                            COL_BOOK_ID,  &id,
-                                            COL_ROW_TYPE, &row_type,
-                                            -1);
-
-                        if (row_type == ROW_TYPE_BOOK &&
-                            id &&
-                            strcmp (book_id, id) == 0) {
-                                g_free (id);
-
-                                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->book_combo),
-                                                               &iter);
-                                break;
-                        }
-
-                        g_free (id);
-
-                        has_next = gtk_tree_model_iter_next (model, &iter);
-                }
-        } else {
-                gtk_combo_box_set_active (GTK_COMBO_BOX (priv->book_combo), 0);
-        }
-
-        g_signal_handlers_unblock_by_func (priv->book_combo,
-                                           search_combo_changed_cb,
-                                           search);
-}
-
-static void
 search_combo_get_active (DhSearch  *search,
                          gchar    **book_id,
                          gchar    **language)
@@ -485,12 +435,6 @@ search_filter_idle (DhSearch *search)
         return FALSE;
 }
 
-static const gchar *
-search_complete_func (DhLink *link)
-{
-        return dh_link_get_name (link);
-}
-
 static void
 search_cell_data_func (GtkTreeViewColumn *tree_column,
                        GtkCellRenderer   *cell,
@@ -1028,15 +972,15 @@ search_completion_add_book (DhSearch *search,
                             DhBook   *book)
 {
         DhSearchPriv *priv = GET_PRIVATE (search);
-        GList        *keywords;
+        GList        *completions;
 
         if (G_UNLIKELY (!priv->completion)) {
-                priv->completion = g_completion_new ((GCompletionFunc) search_complete_func);
+                priv->completion = g_completion_new (NULL);
         }
 
-        keywords = dh_book_get_keywords (book);
-        if (keywords) {
-                g_completion_add_items (priv->completion, keywords);
+        completions = dh_book_get_completions (book);
+        if (completions) {
+                g_completion_add_items (priv->completion, completions);
         }
 }
 
@@ -1045,15 +989,15 @@ search_completion_delete_book (DhSearch *search,
                                DhBook   *book)
 {
         DhSearchPriv *priv = GET_PRIVATE (search);
-        GList        *keywords;
+        GList        *completions;
 
         if (G_UNLIKELY (!priv->completion)) {
                 return;
         }
 
-        keywords = dh_book_get_keywords (book);
-        if (keywords) {
-                g_completion_remove_items (priv->completion, keywords);
+        completions = dh_book_get_completions (book);
+        if (completions) {
+                g_completion_remove_items (priv->completion, completions);
         }
 }
 
@@ -1246,8 +1190,7 @@ dh_search_new (DhBookManager *book_manager)
 
 void
 dh_search_set_search_string (DhSearch    *search,
-                             const gchar *str,
-                             const gchar *book_id)
+                             const gchar *str)
 {
         DhSearchPriv *priv;
 
@@ -1255,6 +1198,9 @@ dh_search_set_search_string (DhSearch    *search,
 
         priv = GET_PRIVATE (search);
 
+        /* Mark "All books" as active */
+        gtk_combo_box_set_active (GTK_COMBO_BOX (priv->book_combo), 0);
+
         g_signal_handlers_block_by_func (priv->entry,
                                          search_entry_changed_cb,
                                          search);
@@ -1268,8 +1214,6 @@ dh_search_set_search_string (DhSearch    *search,
                                            search_entry_changed_cb,
                                            search);
 
-        search_combo_set_active_book_id (search, book_id);
-
         if (!priv->idle_filter) {
                 priv->idle_filter =
                         g_idle_add ((GSourceFunc) search_filter_idle, search);
diff --git a/src/dh-search.h b/src/dh-search.h
index 33af9cb..35daeb5 100644
--- a/src/dh-search.h
+++ b/src/dh-search.h
@@ -52,8 +52,7 @@ struct _DhSearchClass {
 GType      dh_search_get_type          (void);
 GtkWidget *dh_search_new               (DhBookManager *book_manager);
 void       dh_search_set_search_string (DhSearch      *search,
-                                        const gchar   *str,
-                                        const gchar   *book_id);
+                                        const gchar   *str);
 
 G_END_DECLS
 
diff --git a/src/dh-window.c b/src/dh-window.c
index 54c06a4..34ed8c2 100644
--- a/src/dh-window.c
+++ b/src/dh-window.c
@@ -1954,8 +1954,7 @@ dh_window_new (DhBase *base)
 
 void
 dh_window_search (DhWindow    *window,
-                  const gchar *str,
-                  const gchar *book_id)
+                  const gchar *str)
 {
         DhWindowPriv *priv;
 
@@ -1964,7 +1963,7 @@ dh_window_search (DhWindow    *window,
         priv = window->priv;
 
         gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->control_notebook), 1);
-        dh_search_set_search_string (DH_SEARCH (priv->search), str, book_id);
+        dh_search_set_search_string (DH_SEARCH (priv->search), str);
 }
 
 void
diff --git a/src/dh-window.h b/src/dh-window.h
index 8003806..5b98f48 100644
--- a/src/dh-window.h
+++ b/src/dh-window.h
@@ -62,8 +62,7 @@ struct _DhWindowClass {
 GType      dh_window_get_type     (void) G_GNUC_CONST;
 GtkWidget *dh_window_new          (DhBase      *base);
 void       dh_window_search       (DhWindow    *window,
-                                   const gchar *str,
-                                   const gchar *book_id);
+                                   const gchar *str);
 void       dh_window_focus_search (DhWindow    *window);
 void       _dh_window_display_uri (DhWindow    *window,
                                    const gchar *uri);



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