From 51a7800b9832073f1b1c640d7991e6495b2614e0 Mon Sep 17 00:00:00 2001 From: Jonathan Blandford Date: Fri, 24 Dec 2004 05:50:50 +0000 Subject: * backend/ev-document-bookmarks.h: * pdf/xpdf/Makefile.am: * Fri Dec 24 00:48:44 2004 Jonathan Blandford * backend/ev-document-bookmarks.c: (ev_document_bookmarks_get_child): * backend/ev-document-bookmarks.h: * pdf/xpdf/Makefile.am: * pdf/xpdf/pdf-document.cc: * pdf/xpdf/pdf-document.h: * shell/Makefile.am: * shell/ev-sidebar-bookmarks.c: (ev_sidebar_bookmarks_destroy), (ev_sidebar_bookmarks_class_init), (ev_sidebar_bookmarks_construct), (stack_data_free), (do_one_iteration), (populate_bookmarks_idle), (ev_sidebar_bookmarks_clear_document), (ev_sidebar_bookmarks_set_document): * shell/ev-sidebar-bookmarks.h: * shell/ev-sidebar.c: (ev_sidebar_add_page), (ev_sidebar_set_document): * shell/ev-window.c: (ev_window_open): Initial stab at a bookmarks sidebar. It doesn't navigate yet, but it displays both the topics and the page numbers. --- (limited to 'shell') diff --git a/shell/Makefile.am b/shell/Makefile.am index 33e7483..dee7d1f 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -44,10 +44,10 @@ evince_SOURCES= \ evince_LDADD= \ $(SHELL_LIBS) \ - $(top_builddir)/backend/libevbackend.la \ $(top_builddir)/pdf/xpdf/libpdfdocument.la \ $(top_builddir)/pixbuf/libpixbufdocument.la \ $(top_builddir)/ps/libgtkgs.la \ + $(top_builddir)/backend/libevbackend.la \ $(NULL) BUILT_SOURCES = ev-marshal.h ev-marshal.c diff --git a/shell/ev-sidebar-bookmarks.c b/shell/ev-sidebar-bookmarks.c index e29975a..b215e1e 100644 --- a/shell/ev-sidebar-bookmarks.c +++ b/shell/ev-sidebar-bookmarks.c @@ -28,16 +28,26 @@ #include #include "ev-sidebar-bookmarks.h" +#include "ev-document-bookmarks.h" + +/* Amount of time we devote to each iteration of the idle, in microseconds */ +#define IDLE_WORK_LENGTH 5000 + +typedef struct { + EvDocumentBookmarksIter *bookmarks_iter; + GtkTreeIter *tree_iter; +} IdleStackData; struct _EvSidebarBookmarksPrivate { GtkWidget *tree_view; GtkTreeModel *model; EvDocument *current_document; + GList *idle_stack; + guint idle_id; }; enum { BOOKMARKS_COLUMN_MARKUP, - BOOKMARKS_COLUMN_OUTLINE, BOOKMARKS_COLUMN_PAGE_NUM, BOOKMARKS_COLUMN_PAGE_VALID, BOOKMARKS_COLUMN_NUM_COLUMNS @@ -54,15 +64,28 @@ G_DEFINE_TYPE (EvSidebarBookmarks, ev_sidebar_bookmarks, GTK_TYPE_VBOX) #define EV_SIDEBAR_BOOKMARKS_GET_PRIVATE(object) \ (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_SIDEBAR_BOOKMARKS, EvSidebarBookmarksPrivate)) + +static void +ev_sidebar_bookmarks_destroy (GtkObject *object) +{ + EvSidebarBookmarks *ev_sidebar_bookmarks = (EvSidebarBookmarks *) object; + + g_print ("ev_sidebar_bookmarks_destroy!\n"); + ev_sidebar_bookmarks_clear_document (ev_sidebar_bookmarks); +} + static void ev_sidebar_bookmarks_class_init (EvSidebarBookmarksClass *ev_sidebar_bookmarks_class) { GObjectClass *g_object_class; + GtkObjectClass *gtk_object_class; g_object_class = G_OBJECT_CLASS (ev_sidebar_bookmarks_class); + gtk_object_class = GTK_OBJECT_CLASS (ev_sidebar_bookmarks_class); - g_type_class_add_private (g_object_class, sizeof (EvSidebarBookmarksPrivate)); + gtk_object_class->destroy = ev_sidebar_bookmarks_destroy; + g_type_class_add_private (g_object_class, sizeof (EvSidebarBookmarksPrivate)); } @@ -77,7 +100,6 @@ ev_sidebar_bookmarks_construct (EvSidebarBookmarks *ev_sidebar_bookmarks) priv = ev_sidebar_bookmarks->priv; priv->model = (GtkTreeModel *) gtk_tree_store_new (BOOKMARKS_COLUMN_NUM_COLUMNS, G_TYPE_STRING, - G_TYPE_POINTER, G_TYPE_INT, G_TYPE_BOOLEAN); @@ -89,14 +111,15 @@ ev_sidebar_bookmarks_construct (EvSidebarBookmarks *ev_sidebar_bookmarks) GTK_SHADOW_IN); /* Create tree view */ - priv->tree_view = gtk_tree_view_new (); + priv->tree_view = gtk_tree_view_new_with_model (priv->model); + g_object_unref (priv->model); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE); gtk_container_add (GTK_CONTAINER (swindow), priv->tree_view); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (priv->tree_view), TRUE); gtk_box_pack_start (GTK_BOX (ev_sidebar_bookmarks), swindow, TRUE, TRUE, 0); gtk_widget_show_all (GTK_WIDGET (ev_sidebar_bookmarks)); - + column = gtk_tree_view_column_new (); gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view), column); @@ -109,7 +132,7 @@ ev_sidebar_bookmarks_construct (EvSidebarBookmarks *ev_sidebar_bookmarks) gtk_tree_view_column_set_attributes (GTK_TREE_VIEW_COLUMN (column), renderer, "markup", BOOKMARKS_COLUMN_MARKUP, NULL); - + renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_end (GTK_TREE_VIEW_COLUMN (column), renderer, FALSE); gtk_tree_view_column_set_cell_data_func (GTK_TREE_VIEW_COLUMN (column), renderer, @@ -167,18 +190,166 @@ ev_sidebar_bookmarks_new (void) return ev_sidebar_bookmarks; } +static void +stack_data_free (IdleStackData *stack_data, + EvDocumentBookmarks *document_bookmarks) +{ + g_assert (stack_data); + + if (stack_data->tree_iter) + gtk_tree_iter_free (stack_data->tree_iter); + if (stack_data->bookmarks_iter) + ev_document_bookmarks_free_iter (document_bookmarks, stack_data->bookmarks_iter); + g_free (stack_data); +} + +static gboolean +do_one_iteration (EvSidebarBookmarks *ev_sidebar_bookmarks) +{ + EvSidebarBookmarksPrivate *priv = ev_sidebar_bookmarks->priv; + IdleStackData *stack_data; + GtkTreeIter tree_iter; + gchar *title = NULL; + EvDocumentBookmarksType type; + EvDocumentBookmarksIter *child_iter; + gint page = -1; + + g_assert (priv->idle_stack); + + stack_data = (IdleStackData *) priv->idle_stack->data; + + if (! ev_document_bookmarks_get_values (EV_DOCUMENT_BOOKMARKS (priv->current_document), + stack_data->bookmarks_iter, + &title, + &type, + &page)) { + g_warning ("mismatch in model. No values available at current level.\n"); + return FALSE; + } + + gtk_tree_store_append (GTK_TREE_STORE (priv->model), &tree_iter, stack_data->tree_iter); + gtk_tree_store_set (GTK_TREE_STORE (priv->model), &tree_iter, + BOOKMARKS_COLUMN_MARKUP, title, + BOOKMARKS_COLUMN_PAGE_NUM, page, + /* FIXME: Handle links for real. */ + BOOKMARKS_COLUMN_PAGE_VALID, (page >= 0), + -1); + g_free (title); + + child_iter = ev_document_bookmarks_get_child (EV_DOCUMENT_BOOKMARKS (priv->current_document), + stack_data->bookmarks_iter); + if (child_iter) { + IdleStackData *child_stack_data; + + child_stack_data = g_new0 (IdleStackData, 1); + child_stack_data->tree_iter = gtk_tree_iter_copy (&tree_iter); + child_stack_data->bookmarks_iter = child_iter; + priv->idle_stack = g_list_prepend (priv->idle_stack, child_stack_data); + + return TRUE; + } + + /* We don't have children, so we need to walk to the next node */ + while (TRUE) { + if (ev_document_bookmarks_next (EV_DOCUMENT_BOOKMARKS (priv->current_document), + stack_data->bookmarks_iter)) + return TRUE; + + /* We're done with this level. Pop it off the idle stack and go + * to the next level */ + stack_data_free (stack_data, EV_DOCUMENT_BOOKMARKS (priv->current_document)); + priv->idle_stack = g_list_delete_link (priv->idle_stack, priv->idle_stack); + if (priv->idle_stack == NULL) + return FALSE; + stack_data = priv->idle_stack->data; + } +} + +static gboolean +populate_bookmarks_idle (gpointer data) +{ + GTimer *timer; + gint i; + gulong microseconds = 0; + + EvSidebarBookmarks *ev_sidebar_bookmarks = (EvSidebarBookmarks *)data; + EvSidebarBookmarksPrivate *priv = ev_sidebar_bookmarks->priv; + + if (priv->idle_stack == NULL) { + priv->idle_id = 0; + return FALSE; + } + + /* The amount of time that reading the next bookmark takes is wildly + * inconsistent, so we constrain it to IDLE_WORK_LENGTH microseconds per + * idle iteration. */ + timer = g_timer_new (); + i = 0; + g_timer_start (timer); + while (do_one_iteration (ev_sidebar_bookmarks)) { + i++; + g_timer_elapsed (timer, µseconds); + if (microseconds > IDLE_WORK_LENGTH) + break; + } + g_timer_destroy (timer); +#if 0 + g_print ("%d rows done this idle in %d\n", i, (int)microseconds); +#endif + return TRUE; +} + +void +ev_sidebar_bookmarks_clear_document (EvSidebarBookmarks *sidebar_bookmarks) +{ + EvSidebarBookmarksPrivate *priv; + + g_return_if_fail (EV_IS_SIDEBAR_BOOKMARKS (sidebar_bookmarks)); + + priv = sidebar_bookmarks->priv; + if (priv->current_document) { + g_object_unref (priv->current_document); + priv->current_document = NULL; + } + gtk_tree_store_clear (GTK_TREE_STORE (priv->model)); + + /* Clear the idle */ + if (priv->idle_id != 0) { + g_source_remove (priv->idle_id); + priv->idle_id = 0; + } + g_list_foreach (priv->idle_stack, (GFunc) stack_data_free, priv->current_document); + g_list_free (priv->idle_stack); + priv->idle_stack = NULL; + +} + void ev_sidebar_bookmarks_set_document (EvSidebarBookmarks *sidebar_bookmarks, EvDocument *document) { EvSidebarBookmarksPrivate *priv; + EvDocumentBookmarksIter *bookmarks_iter; g_return_if_fail (EV_IS_SIDEBAR_BOOKMARKS (sidebar_bookmarks)); g_return_if_fail (EV_IS_DOCUMENT (document)); priv = sidebar_bookmarks->priv; - g_assert (priv->current_document == NULL); + g_object_ref (document); + ev_sidebar_bookmarks_clear_document (sidebar_bookmarks); + priv->current_document = document; + bookmarks_iter = ev_document_bookmarks_begin_read (EV_DOCUMENT_BOOKMARKS (document)); + if (bookmarks_iter) { + IdleStackData *stack_data; + + stack_data = g_new0 (IdleStackData, 1); + stack_data->bookmarks_iter = bookmarks_iter; + stack_data->tree_iter = NULL; + + priv->idle_stack = g_list_prepend (priv->idle_stack, stack_data); + priv->idle_id = g_idle_add (populate_bookmarks_idle, sidebar_bookmarks); + } } diff --git a/shell/ev-sidebar-bookmarks.h b/shell/ev-sidebar-bookmarks.h index 92c5d41..e3f3cc6 100644 --- a/shell/ev-sidebar-bookmarks.h +++ b/shell/ev-sidebar-bookmarks.h @@ -50,10 +50,11 @@ struct _EvSidebarBookmarksClass { GtkVBoxClass base_class; }; -GType ev_sidebar_bookmarks_get_type (void); -GtkWidget *ev_sidebar_bookmarks_new (void); -void ev_sidebar_bookmarks_set_document (EvSidebarBookmarks *ev_sidebar_bookmarks, - EvDocument *document); +GType ev_sidebar_bookmarks_get_type (void); +GtkWidget *ev_sidebar_bookmarks_new (void); +void ev_sidebar_bookmarks_set_document (EvSidebarBookmarks *ev_sidebar_bookmarks, + EvDocument *document); +void ev_sidebar_bookmarks_clear_document (EvSidebarBookmarks *sidebar_bookmarks); G_END_DECLS diff --git a/shell/ev-sidebar.c b/shell/ev-sidebar.c index 98beaa5..a1f4178 100644 --- a/shell/ev-sidebar.c +++ b/shell/ev-sidebar.c @@ -29,6 +29,7 @@ #include "ev-sidebar.h" #include "ev-document-thumbnails.h" +#include "ev-document-bookmarks.h" #include "ev-sidebar-bookmarks.h" #include "ev-sidebar-thumbnails.h" @@ -178,7 +179,7 @@ ev_sidebar_add_page (EvSidebar *ev_sidebar, /* Set the first item added as active */ if (gtk_combo_box_get_active (GTK_COMBO_BOX (ev_sidebar->priv->option_menu))) - gtk_combo_box_set_active (GTK_COMBO_BOX (ev_sidebar->priv->option_menu), 0); + gtk_combo_box_set_active (GTK_COMBO_BOX (ev_sidebar->priv->option_menu), 1); } void @@ -206,9 +207,9 @@ ev_sidebar_set_document (EvSidebar *sidebar, PAGE_COLUMN_MAIN_WIDGET, &widget, -1); - if (EV_IS_SIDEBAR_BOOKMARKS (widget)) - /* && EV_IS_BOOKMARKS (document) - && ev_bookmarks_has_bookmarks (document)... */ + if (EV_IS_SIDEBAR_BOOKMARKS (widget) + && EV_IS_DOCUMENT_BOOKMARKS (document) + && ev_document_bookmarks_has_document_bookmarks (EV_DOCUMENT_BOOKMARKS (document))) ev_sidebar_bookmarks_set_document (EV_SIDEBAR_BOOKMARKS (widget), document); else if (EV_IS_SIDEBAR_THUMBNAILS (widget) && diff --git a/shell/ev-window.c b/shell/ev-window.c index 2c7676f..0fa9592 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -257,7 +257,9 @@ ev_window_open (EvWindow *ev_window, const char *uri) mime_type = gnome_vfs_get_mime_type (uri); - if (!strcmp (mime_type, "application/pdf")) + if (mime_type == NULL) + document = NULL; + else if (!strcmp (mime_type, "application/pdf")) document = g_object_new (PDF_TYPE_DOCUMENT, NULL); else if (!strcmp (mime_type, "application/postscript")) document = g_object_new (GTK_GS_TYPE, NULL); @@ -289,7 +291,7 @@ ev_window_open (EvWindow *ev_window, const char *uri) char *error_message; error_message = g_strdup_printf (_("Unhandled MIME type: '%s'"), - mime_type); + mime_type?mime_type:""); unable_to_load (ev_window, error_message); g_free (error_message); } -- cgit v0.9.1