Commit a9b25d74 authored by Frederic Peters's avatar Frederic Peters
Browse files

Merge branch 'gb619202-book-manager'

parents 110cf4fc b3068dad
*.[ao]
*.l[ao]
*.pyc
*~
.deps/
.libs/
Makefile
......
Johan Dahlin <johan@gnome.org>
Mikael Hallendal <micke@imendio.com>
Richard Hult <richard@imendio.com>
Ross Burton <ross@burtonini.com>
Johan Dahlin <johan@gnome.org>
Mikael Hallendal <micke@imendio.com>
Richard Hult <richard@imendio.com>
Ross Burton <ross@burtonini.com>
Aleksander Morgado <aleksander@lanedo.com>
......@@ -126,6 +126,18 @@
<long>Which of the tabs is selected: "content" or "search".</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/devhelp/state/main/contents/books_disabled</key>
<applyto>/apps/devhelp/state/main/contents/books_disabled</applyto>
<owner>devhelp</owner>
<type>list</type>
<default></default>
<locale name="C">
<short>Books disabled</short>
<long>List of books disabled by the user.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/devhelp/ui/use_system_fonts</key>
<applyto>/apps/devhelp/ui/use_system_fonts</applyto>
......
This diff is collapsed.
......@@ -52,6 +52,8 @@ INST_H_FILES = \
dh-assistant.h \
dh-assistant-view.h \
dh-base.h \
dh-book-manager.h \
dh-book.h \
dh-book-tree.h \
dh-error.h \
dh-keyword-model.h \
......@@ -70,6 +72,8 @@ libdevhelp_3_la_SOURCES = \
dh-assistant.c \
dh-assistant-view.c \
dh-base.c \
dh-book-manager.c \
dh-book.c \
dh-book-tree.c \
dh-error.c \
dh-keyword-model.c \
......
......@@ -26,6 +26,8 @@
#include "dh-assistant-view.h"
#include "dh-link.h"
#include "dh-util.h"
#include "dh-book-manager.h"
#include "dh-book.h"
#include "dh-window.h"
typedef struct {
......@@ -306,7 +308,7 @@ dh_assistant_view_set_link (DhAssistantView *view,
"assistant",
"assistant.js",
NULL);
html = g_strdup_printf (
"<html>"
"<head>"
......@@ -362,11 +364,12 @@ dh_assistant_view_search (DhAssistantView *view,
const gchar *str)
{
DhAssistantViewPriv *priv;
GList *keywords, *l;
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);
......@@ -384,34 +387,43 @@ dh_assistant_view_search (DhAssistantView *view,
g_free (priv->current_search);
priv->current_search = g_strdup (str);
keywords = dh_base_get_keywords (dh_assistant_view_get_base (view));
book_manager = dh_base_get_book_manager (dh_assistant_view_get_base (view));
prefix_link = NULL;
exact_link = NULL;
for (l = keywords; l && exact_link == NULL; l = l->next) {
DhLinkType type;
link = l->data;
for (books = dh_book_manager_get_books (book_manager);
!exact_link && books;
books = g_list_next (books)) {
GList *l;
type = dh_link_get_link_type (link);
for (l = dh_book_get_keywords (DH_BOOK (books->data));
l && exact_link == NULL;
l = l->next) {
DhLinkType type;
if (type == DH_LINK_TYPE_BOOK ||
type == DH_LINK_TYPE_PAGE ||
type == DH_LINK_TYPE_KEYWORD) {
continue;
}
link = l->data;
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;
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 (strlen (dh_link_get_name (prefix_link)) > strlen (name)) {
prefix_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;
}
}
}
}
......
......@@ -41,69 +41,51 @@
#include "dh-util.h"
#include "ige-conf.h"
#include "dh-base.h"
#include "dh-book-manager.h"
typedef struct {
GSList *windows;
GSList *assistants;
GNode *book_tree;
GList *keywords;
GHashTable *books;
GSList *windows;
GSList *assistants;
DhBookManager *book_manager;
} DhBasePriv;
G_DEFINE_TYPE (DhBase, dh_base, G_TYPE_OBJECT);
#define GET_PRIVATE(instance) G_TYPE_INSTANCE_GET_PRIVATE \
(instance, DH_TYPE_BASE, DhBasePriv);
(instance, DH_TYPE_BASE, DhBasePriv)
static void dh_base_init (DhBase *base);
static void dh_base_class_init (DhBaseClass *klass);
static void base_init_books (DhBase *base);
static void base_add_books (DhBase *base,
const gchar *directory);
#ifdef GDK_WINDOWING_QUARTZ
static void base_add_xcode_docsets (DhBase *base,
const gchar *path);
#endif
static DhBase *base_instance;
static void
unref_node_link (GNode *node, gpointer data)
base_finalize (GObject *object)
{
dh_link_unref (node->data);
dh_link_unref (node->data);
G_OBJECT_CLASS (dh_base_parent_class)->finalize (object);
}
static void
base_finalize (GObject *object)
base_dispose (GObject *object)
{
DhBasePriv *priv;
priv = GET_PRIVATE (object);
/* FIXME: Free things... */
g_hash_table_destroy (priv->books);
g_node_traverse (priv->book_tree,
G_IN_ORDER,
G_TRAVERSE_ALL,
-1,
(GNodeTraverseFunc)unref_node_link,
NULL);
g_node_destroy (priv->book_tree);
g_list_foreach (priv->keywords, (GFunc)dh_link_unref, NULL);
g_list_free (priv->keywords);
G_OBJECT_CLASS (dh_base_parent_class)->finalize (object);
if (priv->book_manager) {
g_object_unref (priv->book_manager);
priv->book_manager = NULL;
}
}
static void
dh_base_class_init (DhBaseClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = base_finalize;
object_class->dispose = base_dispose;
g_type_class_add_private (klass, sizeof (DhBasePriv));
}
......@@ -120,9 +102,8 @@ dh_base_init (DhBase *base)
ige_conf_add_defaults (conf, path);
g_free (path);
priv->book_tree = g_node_new (NULL);
priv->books = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
priv->book_manager = dh_book_manager_new ();
dh_book_manager_populate (priv->book_manager);
#ifdef HAVE_WNCK
{
......@@ -155,284 +136,11 @@ base_window_or_assistant_finalized_cb (DhBase *base,
}
}
static gint
book_sort_func (gconstpointer a,
gconstpointer b)
{
DhLink *link_a;
DhLink *link_b;
link_a = ((GNode *) a)->data;
link_b = ((GNode *) b)->data;
return dh_util_cmp_book (link_a, link_b);
}
static void
base_sort_books (DhBase *base)
{
DhBasePriv *priv = GET_PRIVATE (base);
GNode *n;
DhLink *link;
GList *list = NULL, *l;
if (priv->book_tree) {
n = priv->book_tree->children;
while (n) {
list = g_list_prepend (list, n);
n = n->next;
}
list = g_list_sort (list, book_sort_func);
}
for (l = list; l; l = l->next) {
n = l->data;
link = n->data;
g_node_unlink (n);
}
for (l = list; l; l = l->next) {
n = l->data;
g_node_append (priv->book_tree, n);
}
g_list_free (list);
}
static void
base_add_books_in_data_dir (DhBase *base,
const gchar *data_dir)
{
gchar *dir;
dir = g_build_filename (data_dir, "gtk-doc", "html", NULL);
base_add_books (base, dir);
g_free (dir);
dir = g_build_filename (data_dir, "devhelp", "books", NULL);
base_add_books (base, dir);
g_free (dir);
}
static void
base_init_books (DhBase *base)
{
const gchar * const * system_dirs;
base_add_books_in_data_dir (base, g_get_user_data_dir ());
system_dirs = g_get_system_data_dirs ();
while (*system_dirs) {
base_add_books_in_data_dir (base, *system_dirs);
system_dirs++;
}
#ifdef GDK_WINDOWING_QUARTZ
base_add_xcode_docsets (
base,
"/Library/Developer/Shared/Documentation/DocSets");
#endif
base_sort_books (base);
}
static gchar *
base_get_book_path (DhBase *base,
const gchar *base_path,
const gchar *name,
const gchar *suffix)
{
gchar *tmp;
gchar *book_path;
tmp = g_build_filename (base_path, name, name, NULL);
book_path = g_strconcat (tmp, ".", suffix, NULL);
g_free (tmp);
if (!g_file_test (book_path, G_FILE_TEST_EXISTS)) {
g_free (book_path);
return NULL;
}
return book_path;
}
#ifdef GDK_WINDOWING_QUARTZ
static void
base_add_xcode_docset (DhBase *base,
const gchar *path)
{
DhBasePriv *priv = GET_PRIVATE (base);
gchar *tmp;
gboolean seems_like_devhelp = FALSE;
GDir *dir;
const gchar *name;
/* Do some sanity checking on the directory first so we don't have
* to go through several hundreds of files in every docset.
*/
tmp = g_build_filename (path, "style.css", NULL);
if (g_file_test (tmp, G_FILE_TEST_EXISTS)) {
gchar *tmp;
tmp = g_build_filename (path, "index.sgml", NULL);
if (g_file_test (tmp, G_FILE_TEST_EXISTS)) {
seems_like_devhelp = TRUE;
}
g_free (tmp);
}
g_free (tmp);
if (!seems_like_devhelp) {
return;
}
dir = g_dir_open (path, 0, NULL);
if (!dir) {
return;
}
while ((name = g_dir_read_name (dir)) != NULL) {
gchar *p;
GError *error = NULL;
p = strrchr (name, '.');
if (strcmp (p, ".devhelp2") == 0) {
gchar *book_name;
gchar *book_path;
book_name = g_strdup (name);
p = strrchr (book_name, '.');
p[0] = '\0';
if (g_hash_table_lookup (priv->books, book_name)) {
g_free (book_name);
continue;
}
book_path = g_build_filename (path, name, NULL);
if (!dh_parser_read_file (book_path,
priv->book_tree,
&priv->keywords,
&error)) {
g_warning ("Failed to read '%s': %s",
book_path, error->message);
g_clear_error (&error);
g_free (book_path);
g_free (book_name);
} else {
g_hash_table_insert (priv->books,
book_name,
book_path);
}
}
}
g_dir_close (dir);
}
/* This isn't really -any- Xcode docset, just gtk-doc docs converted to
* docsets.
*
* Path should point to a DocSets directory.
*/
static void
base_add_xcode_docsets (DhBase *base,
const gchar *path)
{
GDir *dir;
const gchar *name;
dir = g_dir_open (path, 0, NULL);
if (!dir) {
return;
}
while ((name = g_dir_read_name (dir)) != NULL) {
gchar *docset_path;
docset_path = g_build_filename (path,
name,
"Contents",
"Resources",
"Documents",
NULL);
base_add_xcode_docset (base, docset_path);
g_free (docset_path);
}
g_dir_close (dir);
}
#endif
static void
base_add_books (DhBase *base,
const gchar *path)
{
DhBasePriv *priv = GET_PRIVATE (base);
GDir *dir;
const gchar *name;
dir = g_dir_open (path, 0, NULL);
if (!dir) {
return;
}
while ((name = g_dir_read_name (dir)) != NULL) {
gchar *book_path;
GError *error = NULL;
if (g_hash_table_lookup (priv->books, name)) {
continue;
}
book_path = base_get_book_path (base, path, name, "devhelp2");
if (!book_path) {
book_path = base_get_book_path (base, path, name, "devhelp2.gz");
}
if (!book_path) {
book_path = base_get_book_path (base, path, name, "devhelp");
}
if (!book_path) {
book_path = base_get_book_path (base, path, name, "devhelp.gz");
}
if (!book_path) {
continue;
}
if (!dh_parser_read_file (book_path,
priv->book_tree,
&priv->keywords,
&error)) {
g_warning ("Failed to read '%s': %s",
book_path, error->message);
g_clear_error (&error);
g_free (book_path);
} else {
g_hash_table_insert (priv->books,
g_strdup (name),
book_path);
}
}
g_dir_close (dir);
}
DhBase *
dh_base_get (void)
{
if (!base_instance) {
base_instance = g_object_new (DH_TYPE_BASE, NULL);
base_init_books (base_instance);
}
return base_instance;
......@@ -490,20 +198,8 @@ dh_base_new_assistant (DhBase *base)
return assistant;
}
GNode *
dh_base_get_book_tree (DhBase *base)
{
DhBasePriv *priv;
g_return_val_if_fail (DH_IS_BASE (base), NULL);
priv = GET_PRIVATE (base);
return priv->book_tree;
}
GList *
dh_base_get_keywords (DhBase *base)
DhBookManager *
dh_base_get_book_manager (DhBase *base)
{
DhBasePriv *priv;
......@@ -511,7 +207,7 @@ dh_base_get_keywords (DhBase *base)
priv = GET_PRIVATE (base);
return priv->keywords;
return priv->book_manager;
}
GtkWidget *
......
......@@ -25,6 +25,8 @@
#include <gtk/gtk.h>
#include <dh-book-manager.h>
G_BEGIN_DECLS
typedef struct _DhBase DhBase;
......@@ -45,16 +47,15 @@ struct _DhBaseClass {
GObjectClass parent_class;
};
GType dh_base_get_type (void) G_GNUC_CONST;
DhBase * dh_base_get (void);
DhBase * dh_base_new (void);
GtkWidget * dh_base_new_window (DhBase *base);
GtkWidget * dh_base_new_assistant (DhBase *base);
GtkWidget * dh_base_get_window (DhBase *base);
GtkWidget * dh_base_get_window_on_current_workspace (DhBase *base);
GNode * dh_base_get_book_tree (DhBase *base);
GList * dh_base_get_keywords (DhBase *base);
void dh_base_quit (DhBase *base);
GType dh_base_get_type (void) G_GNUC_CONST;
DhBase * dh_base_get (void);
DhBase * dh_base_new (void);
GtkWidget * dh_base_new_window (DhBase *base);
GtkWidget * dh_base_new_assistant (DhBase *base);
GtkWidget * dh_base_get_window (DhBase *base);
GtkWidget * dh_base_get_window_on_current_workspace (DhBase *base);
DhBookManager *dh_base_get_book_manager (DhBase *base);
void dh_base_quit (DhBase *base);
G_END_DECLS
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2002 CodeFactory AB
* Copyright (C) 2002 Mikael Hallendal <micke@imendio.com>
* Copyright (C) 2004-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
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include "dh-link.h"
#include "dh-util.h"
#include "dh-book.h"
#include "dh-book-manager.h"