#include "ev-properties-dialog.h"
#include "ev-sidebar-annotations.h"
#include "ev-sidebar-attachments.h"
+#include "ev-sidebar-bookmarks.h"
#include "ev-sidebar.h"
#include "ev-sidebar-links.h"
#include "ev-sidebar-page.h"
#include "ev-print-operation.h"
#include "ev-progress-message-area.h"
#include "ev-annotation-properties-dialog.h"
+#include "ev-bookmarks.h"
+#include "ev-bookmark-action.h"
#ifdef ENABLE_DBUS
#include "ev-media-player-keys.h"
GtkWidget *sidebar_attachments;
GtkWidget *sidebar_layers;
GtkWidget *sidebar_annots;
+ GtkWidget *sidebar_bookmarks;
/* Settings */
GSettings *settings;
GtkRecentManager *recent_manager;
GtkActionGroup *recent_action_group;
guint recent_ui_id;
+ GtkActionGroup *bookmarks_action_group;
+ guint bookmarks_ui_id;
GtkUIManager *ui_manager;
/* Fullscreen mode */
EvWindowPageMode page_mode;
EvWindowTitle *title;
EvMetadata *metadata;
+ EvBookmarks *bookmarks;
gboolean is_new_doc;
/* Load params */
#define ATTACHMENTS_SIDEBAR_ID "attachments"
#define LAYERS_SIDEBAR_ID "layers"
#define ANNOTS_SIDEBAR_ID "annotations"
+#define BOOKMARKS_SIDEBAR_ID "bookmarks"
#define EV_PRINT_SETTINGS_FILE "print-settings"
#define EV_PRINT_SETTINGS_GROUP "Print Settings"
static void ev_window_emit_closed (EvWindow *window);
static void ev_window_emit_doc_loaded (EvWindow *window);
#endif
+static void ev_window_setup_bookmarks (EvWindow *window);
static guint ev_window_n_copies = 0;
ev_window_set_action_sensitive (ev_window, "ViewAutoscroll", has_pages);
ev_window_set_action_sensitive (ev_window, "ViewInvertedColors", has_pages);
+ /* Bookmarks menu */
+ ev_window_set_action_sensitive (ev_window, "BookmarksAdd",
+ has_pages && ev_window->priv->bookmarks);
+
/* Toolbar-specific actions: */
ev_window_set_action_sensitive (ev_window, PAGE_SELECTOR_ACTION, has_pages);
ev_window_set_action_sensitive (ev_window, ZOOM_CONTROL_ACTION, has_pages);
ev_window_set_message_area (window, area);
}
-typedef struct _FindTask {
+typedef struct _PageTitleData {
const gchar *page_label;
- gchar *chapter;
-} FindTask;
+ gchar *page_title;
+} PageTitleData;
static gboolean
-ev_window_find_chapter (GtkTreeModel *tree_model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
+ev_window_find_page_title (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ PageTitleData *data)
{
- FindTask *task = (FindTask *)data;
gchar *page_string;
gtk_tree_model_get (tree_model, iter,
if (!page_string)
return FALSE;
- if (!strcmp (page_string, task->page_label)) {
+ if (!strcmp (page_string, data->page_label)) {
gtk_tree_model_get (tree_model, iter,
- EV_DOCUMENT_LINKS_COLUMN_MARKUP, &task->chapter,
+ EV_DOCUMENT_LINKS_COLUMN_MARKUP, &data->page_title,
-1);
g_free (page_string);
return TRUE;
return FALSE;
}
+static gchar *
+ev_window_get_page_title (EvWindow *window,
+ const gchar *page_label)
+{
+ if (EV_IS_DOCUMENT_LINKS (window->priv->document) &&
+ ev_document_links_has_document_links (EV_DOCUMENT_LINKS (window->priv->document))) {
+ PageTitleData data;
+ GtkTreeModel *model;
+
+ data.page_label = page_label;
+ data.page_title = NULL;
+
+ g_object_get (G_OBJECT (window->priv->sidebar_links),
+ "model", &model,
+ NULL);
+ if (model) {
+ gtk_tree_model_foreach (model,
+ (GtkTreeModelForeachFunc)ev_window_find_page_title,
+ &data);
+
+ g_object_unref (model);
+ }
+
+ return data.page_title;
+ }
+
+ return NULL;
+}
+
static void
ev_window_add_history (EvWindow *window, gint page, EvLink *link)
{
gchar *page_label = NULL;
+ gchar *page_title;
gchar *link_title;
- FindTask find_task;
EvLink *real_link;
EvLinkAction *action;
EvLinkDest *dest;
if (!page_label)
return;
-
- find_task.page_label = page_label;
- find_task.chapter = NULL;
-
- if (ev_document_links_has_document_links (EV_DOCUMENT_LINKS (window->priv->document))) {
- GtkTreeModel *model;
-
- g_object_get (G_OBJECT (window->priv->sidebar_links), "model", &model, NULL);
-
- if (model) {
- gtk_tree_model_foreach (model,
- ev_window_find_chapter,
- &find_task);
-
- g_object_unref (model);
- }
- }
- if (find_task.chapter)
- link_title = g_strdup_printf (_("Page %s — %s"), page_label, find_task.chapter);
- else
+ page_title = ev_window_get_page_title (window, page_label);
+ if (page_title) {
+ link_title = g_strdup_printf (_("Page %s — %s"), page_label, page_title);
+ g_free (page_title);
+ } else {
link_title = g_strdup_printf (_("Page %s"), page_label);
-
+ }
+
real_link = ev_link_new (link_title, action);
ev_history_add_link (window->priv->history, real_link);
- g_free (find_task.chapter);
g_free (link_title);
g_free (page_label);
g_object_unref (real_link);
id = LAYERS_SIDEBAR_ID;
} else if (current_page == ev_window->priv->sidebar_annots) {
id = ANNOTS_SIDEBAR_ID;
+ } else if (current_page == ev_window->priv->sidebar_bookmarks) {
+ id = BOOKMARKS_SIDEBAR_ID;
} else {
g_assert_not_reached();
}
GtkWidget *attachments = window->priv->sidebar_attachments;
GtkWidget *annots = window->priv->sidebar_annots;
GtkWidget *layers = window->priv->sidebar_layers;
+ GtkWidget *bookmarks = window->priv->sidebar_bookmarks;
if (strcmp (page_id, LINKS_SIDEBAR_ID) == 0 &&
ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (links), document)) {
} else if (strcmp (page_id, ANNOTS_SIDEBAR_ID) == 0 &&
ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (annots), document)) {
ev_sidebar_set_page (sidebar, annots);
+ } else if (strcmp (page_id, BOOKMARKS_SIDEBAR_ID) == 0 &&
+ ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (bookmarks), document)) {
+ ev_sidebar_set_page (sidebar, bookmarks);
}
}
if (ev_window->priv->metadata)
g_object_unref (ev_window->priv->metadata);
+ if (ev_window->priv->bookmarks)
+ g_object_unref (ev_window->priv->bookmarks);
source_file = g_file_new_for_uri (uri);
if (!ev_file_is_temp (source_file) && ev_is_metadata_supported_for_file (source_file)) {
ev_window->priv->metadata = NULL;
}
+ if (ev_window->priv->metadata) {
+ ev_window->priv->bookmarks = ev_bookmarks_new (ev_window->priv->metadata);
+ ev_sidebar_bookmarks_set_bookmarks (EV_SIDEBAR_BOOKMARKS (ev_window->priv->sidebar_bookmarks),
+ ev_window->priv->bookmarks);
+ g_signal_connect_swapped (ev_window->priv->bookmarks, "changed",
+ G_CALLBACK (ev_window_setup_bookmarks),
+ ev_window);
+ } else {
+ ev_window->priv->bookmarks = NULL;
+ }
+
if (ev_window->priv->search_string)
g_free (ev_window->priv->search_string);
ev_window->priv->search_string = search_string ?
setup_size_from_metadata (ev_window);
setup_model_from_metadata (ev_window);
+ ev_window_setup_bookmarks (ev_window);
ev_window->priv->load_job = ev_job_load_new (uri);
g_signal_connect (ev_window->priv->load_job,
static void
fullscreen_toolbar_remove_shadow (GtkWidget *toolbar)
{
- static gboolean done = FALSE;
+ GtkCssProvider *provider;
- if (!done) {
- gtk_rc_parse_string (
- "\n"
- " style \"fullscreen-toolbar-style\"\n"
- " {\n"
- " GtkToolbar::shadow-type=GTK_SHADOW_NONE\n"
- " }\n"
- "\n"
- " widget \"*.fullscreen-toolbar\" style \"fullscreen-toolbar-style\"\n"
- "\n");
- done = TRUE;
- }
-
- gtk_widget_set_name (toolbar, "fullscreen-toolbar");
+ gtk_widget_set_name (toolbar, "ev-fullscreen-toolbar");
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_data (provider,
+ "#ev-fullscreen-toolbar {\n"
+ " -GtkToolbar-shadow-type: none; }",
+ -1, NULL);
+ gtk_style_context_add_provider (gtk_widget_get_style_context (toolbar),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ g_object_unref (provider);
}
static void
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)), 5);
gtk_box_set_spacing (GTK_BOX (content_area), 2);
-#if !GTK_CHECK_VERSION (2, 90, 7)
- gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
-#endif
gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400);
toolbar = EGG_EDITABLE_TOOLBAR (ev_window->priv->toolbar);
}
}
+static void
+ev_window_cmd_bookmark_activate (GtkAction *action,
+ EvWindow *window)
+{
+ guint page = ev_bookmark_action_get_page (EV_BOOKMARK_ACTION (action));
+
+ ev_document_model_set_page (window->priv->model, page);
+}
+
+static gint
+compare_bookmarks (EvBookmark *a,
+ EvBookmark *b)
+{
+ return strcmp (a->title, b->title);
+}
+
+static void
+ev_window_setup_bookmarks (EvWindow *window)
+{
+ GList *items, *l;
+
+ if (!window->priv->bookmarks)
+ return;
+
+ if (window->priv->bookmarks_ui_id > 0) {
+ gtk_ui_manager_remove_ui (window->priv->ui_manager,
+ window->priv->bookmarks_ui_id);
+ gtk_ui_manager_ensure_update (window->priv->ui_manager);
+ }
+ window->priv->bookmarks_ui_id = gtk_ui_manager_new_merge_id (window->priv->ui_manager);
+
+ if (window->priv->bookmarks_action_group) {
+ gtk_ui_manager_remove_action_group (window->priv->ui_manager,
+ window->priv->bookmarks_action_group);
+ g_object_unref (window->priv->bookmarks_action_group);
+ }
+ window->priv->bookmarks_action_group = gtk_action_group_new ("BookmarksActions");
+ gtk_ui_manager_insert_action_group (window->priv->ui_manager,
+ window->priv->bookmarks_action_group, -1);
+
+ items = ev_bookmarks_get_bookmarks (window->priv->bookmarks);
+ items = g_list_sort (items, (GCompareFunc)compare_bookmarks);
+
+ for (l = items; l && l->data; l = g_list_next (l)) {
+ EvBookmark *bm = (EvBookmark *)l->data;
+ GtkAction *action;
+
+ action = ev_bookmark_action_new (bm);
+ g_signal_connect (action, "activate",
+ G_CALLBACK (ev_window_cmd_bookmark_activate),
+ window);
+ gtk_action_group_add_action (window->priv->bookmarks_action_group,
+ action);
+
+ gtk_ui_manager_add_ui (window->priv->ui_manager,
+ window->priv->bookmarks_ui_id,
+ "/MainMenu/BookmarksMenu/BookmarksItems",
+ gtk_action_get_label (action),
+ gtk_action_get_name (action),
+ GTK_UI_MANAGER_MENUITEM,
+ FALSE);
+
+ g_object_unref (action);
+ }
+
+ g_list_free (items);
+}
+
+static void
+ev_window_cmd_bookmarks_add (GtkAction *action,
+ EvWindow *window)
+{
+ EvBookmark bm;
+ gchar *page_label;
+ gchar *page_title;
+
+ bm.page = ev_document_model_get_page (window->priv->model);
+ page_label = ev_document_get_page_label (window->priv->document, bm.page);
+ page_title = ev_window_get_page_title (window, page_label);
+ bm.title = page_title ? page_title : g_strdup_printf (_("Page %s"), page_label);
+ g_free (page_label);
+
+ /* EvBookmarks takes ownership of bookmark */
+ ev_bookmarks_add (window->priv->bookmarks, &bm);
+}
+
static void
ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window)
{
"name", _("Evince"),
"version", VERSION,
"copyright",
- _("© 1996–2009 The Evince authors"),
+ _("© 1996–2010 The Evince authors"),
"license", license_trans,
"website", "http://www.gnome.org/projects/evince",
"comments", comments,
}
#endif /* ENABLE_DBUS */
+ if (priv->bookmarks) {
+ g_object_unref (priv->bookmarks);
+ priv->bookmarks = NULL;
+ }
+
if (priv->metadata) {
g_object_unref (priv->metadata);
priv->metadata = NULL;
priv->recent_action_group = NULL;
}
+ if (priv->bookmarks_action_group) {
+ g_object_unref (priv->bookmarks_action_group);
+ priv->bookmarks_action_group = NULL;
+ }
+
if (priv->recent_manager) {
g_signal_handlers_disconnect_by_func (priv->recent_manager,
ev_window_setup_recent,
{ "Edit", NULL, N_("_Edit") },
{ "View", NULL, N_("_View") },
{ "Go", NULL, N_("_Go") },
+ { "Bookmarks", NULL, N_("_Bookmarks") },
{ "Help", NULL, N_("_Help") },
/* File menu */
N_("Go to the last page"),
G_CALLBACK (ev_window_cmd_go_last_page) },
+ /* Bookmarks menu */
+ { "BookmarksAdd", GTK_STOCK_ADD, N_("_Add Bookmark"), "<control>D",
+ N_("Add a bookmark for the current page"),
+ G_CALLBACK (ev_window_cmd_bookmarks_add) },
+
/* Help menu */
{ "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", NULL,
G_CALLBACK (ev_window_cmd_help_contents) },
ev_view_cancel_add_annotation (EV_VIEW (window->priv->view));
}
+static void
+sidebar_bookmarks_add_bookmark (EvSidebarBookmarks *sidebar_bookmarks,
+ EvWindow *window)
+{
+ ev_window_cmd_bookmarks_add (NULL, window);
+}
+
static void
register_custom_actions (EvWindow *window, GtkActionGroup *group)
{
{
GDBusConnection *connection;
GError *error = NULL;
+ guint32 timestamp;
+ gchar *uri_input;
+ GFile *input_gfile;
if (window->priv->dbus_object_id <= 0)
return;
if (!connection)
return;
+ timestamp = gtk_get_current_event_time ();
+ if (g_path_is_absolute (link->filename)) {
+ input_gfile = g_file_new_for_path (link->filename);
+ } else {
+ GFile *gfile, *parent_gfile;
+
+ gfile = g_file_new_for_uri (window->priv->uri);
+ parent_gfile = g_file_get_parent (gfile);
+
+ /* parent_gfile should never be NULL */
+ if (parent_gfile == NULL) {
+ g_printerr ("Document URI is '/'\n");
+ return;
+ }
+
+ input_gfile = g_file_get_child (parent_gfile, link->filename);
+ g_object_unref (parent_gfile);
+ g_object_unref (gfile);
+ }
+
+ uri_input = g_file_get_uri (input_gfile);
+ g_object_unref (input_gfile);
+
g_dbus_connection_emit_signal (connection,
NULL,
window->priv->dbus_object_path,
EV_WINDOW_DBUS_INTERFACE,
"SyncSource",
- g_variant_new ("(s(ii))",
- link->filename,
+ g_variant_new ("(s(ii)u)",
+ uri_input,
link->line,
- link->col),
+ link->col,
+ timestamp),
&error);
+ g_free (uri_input);
if (error) {
g_printerr ("Failed to emit DBus signal SyncSource: %s\n",
error->message);
if (window->priv->document && ev_document_has_synctex (window->priv->document)) {
EvSourceLink link;
+ guint32 timestamp;
- g_variant_get (parameters, "(&s(ii))", &link.filename, &link.line, &link.col);
+ g_variant_get (parameters, "(&s(ii)u)", &link.filename, &link.line, &link.col, ×tamp);
ev_view_highlight_forward_search (EV_VIEW (window->priv->view), &link);
- gtk_window_present (GTK_WINDOW (window));
+ gtk_window_present_with_time (GTK_WINDOW (window), timestamp);
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
"<method name='SyncView'>"
"<arg type='s' name='source_file' direction='in'/>"
"<arg type='(ii)' name='source_point' direction='in'/>"
+ "<arg type='u' name='timestamp' direction='in'/>"
"</method>"
"<signal name='SyncSource'>"
"<arg type='s' name='source_file' direction='out'/>"
"<arg type='(ii)' name='source_point' direction='out'/>"
+ "<arg type='u' name='timestamp' direction='out'/>"
"</signal>"
"<signal name='Closed'/>"
"<signal name='DocumentLoaded'>"
gtk_widget_show (ev_window->priv->toolbar);
/* Add the main area */
- ev_window->priv->hpaned = gtk_hpaned_new ();
+ ev_window->priv->hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
g_signal_connect (ev_window->priv->hpaned,
"notify::position",
G_CALLBACK (ev_window_sidebar_position_change_cb),
ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
sidebar_widget);
+ sidebar_widget = ev_sidebar_bookmarks_new ();
+ ev_window->priv->sidebar_bookmarks = sidebar_widget;
+ g_signal_connect (sidebar_widget,
+ "add-bookmark",
+ G_CALLBACK (sidebar_bookmarks_add_bookmark),
+ ev_window);
+ gtk_widget_show (sidebar_widget);
+ ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
+ sidebar_widget);
+
ev_window->priv->view_box = gtk_vbox_new (FALSE, 0);
ev_window->priv->scrolled_window =
GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,