static void
preferences_bookshelf_book_created_cb (DhBookManager *book_manager,
                                       GObject       *book_object,
                                       DhPreferences *prefs)
{
        DhPreferencesPrivate *priv = dh_preferences_get_instance_private (prefs);

        preferences_bookshelf_add_book_to_store (prefs,
                                                 DH_BOOK (book_object),
                                                 dh_book_manager_get_group_by_language (priv->book_manager));
}
static void
preferences_bookshelf_populate_store (DhPreferences *prefs)
{
        DhPreferencesPrivate *priv = dh_preferences_get_instance_private (prefs);
        GList *l;
        gboolean group_by_language;

        group_by_language = dh_book_manager_get_group_by_language (priv->book_manager);

        /* This list already comes ordered, but we don't care */
        for (l = dh_book_manager_get_books (priv->book_manager);
             l;
             l = g_list_next (l)) {
                preferences_bookshelf_add_book_to_store (prefs,
                                                         DH_BOOK (l->data),
                                                         group_by_language);
        }
}
static void
preferences_bookshelf_book_deleted_cb (DhBookManager *book_manager,
                                       GObject       *book_object,
                                       DhPreferences *prefs)
{
        DhPreferencesPrivate *priv = dh_preferences_get_instance_private (prefs);
        DhBook      *book = DH_BOOK (book_object);
        GtkTreeIter  exact_iter;
        gboolean     exact_iter_found;

        preferences_bookshelf_find_book (prefs,
                                         book,
                                         NULL,
                                         &exact_iter,
                                         &exact_iter_found,
                                         NULL,
                                         NULL);
        if (exact_iter_found) {
                gtk_list_store_remove (priv->bookshelf_store, &exact_iter);
                preferences_bookshelf_set_language_inconsistent (prefs, dh_book_get_language (book));
        }
}
gboolean
dh_assistant_view_search (DhAssistantView *view,
                          const gchar     *str)
{
        DhAssistantViewPriv *priv;
        const gchar         *name;
        DhLink              *link;
        DhLink              *exact_link;
        DhLink              *prefix_link;
        DhBookManager       *book_manager;
        GList               *books;

        g_return_val_if_fail (DH_IS_ASSISTANT_VIEW (view), FALSE);
        g_return_val_if_fail (str, FALSE);

        priv = GET_PRIVATE (view);

        /* Filter out very short strings. */
        if (strlen (str) < 4) {
                return FALSE;
        }

        if (priv->current_search && strcmp (priv->current_search, str) == 0) {
                return FALSE;
        }
        g_free (priv->current_search);
        priv->current_search = g_strdup (str);

        book_manager = dh_base_get_book_manager (dh_assistant_view_get_base (view));

        prefix_link = NULL;
        exact_link = NULL;

        for (books = dh_book_manager_get_books (book_manager);
             !exact_link && books;
             books = g_list_next (books)) {
                GList *l;

                for (l = dh_book_get_keywords (DH_BOOK (books->data));
                     l && exact_link == NULL;
                     l = l->next) {
                        DhLinkType type;

                        link = l->data;

                        type = dh_link_get_link_type (link);

                        if (type == DH_LINK_TYPE_BOOK ||
                            type == DH_LINK_TYPE_PAGE ||
                            type == DH_LINK_TYPE_KEYWORD) {
                                continue;
                        }

                        name = dh_link_get_name (link);
                        if (strcmp (name, str) == 0) {
                                exact_link = link;
                        }
                        else if (g_str_has_prefix (name, str)) {
                                /* Prefer shorter prefix matches. */
                                if (!prefix_link) {
                                        prefix_link = link;
                                }
                                else if (strlen (dh_link_get_name (prefix_link)) > strlen (name)) {
                                        prefix_link = link;
                                }
                        }
                }
        }

        if (exact_link) {
                /*g_print ("exact hit: '%s' '%s'\n", exact_link->name, str);*/
                dh_assistant_view_set_link (view, exact_link);
        }
        else if (prefix_link) {
                /*g_print ("prefix hit: '%s' '%s'\n", prefix_link->name, str);*/
                dh_assistant_view_set_link (view, prefix_link);
        } else {
                /*g_print ("no hit\n");*/
                /*assistant_view_set_link (view, NULL);*/
                return FALSE;
        }

        return TRUE;
}