Commit 34148304 authored by Carlos Garcia Campos's avatar Carlos Garcia Campos

Remove EvPageCache and use EvDocumentModel instead

EvView is now another view for the common model EvDocumentModel. Now
it's possible to have several windows for the same document without the
symlink hack. Every window has its own model, while the document object
is shared.
parent 8f8663bd
......@@ -23,7 +23,7 @@
#include <libview/ev-job-scheduler.h>
#include <libview/ev-jobs.h>
#include <libview/ev-page-cache.h>
#include <libview/ev-document-model.h>
#include <libview/ev-view.h>
#include <libview/ev-view-type-builtins.h>
#include <libview/ev-stock-icons.h>
......
......@@ -10,6 +10,7 @@ libevmisc_la_CFLAGS = \
-DDATADIR=\"$(pkgdatadir)\" \
-I$(top_srcdir) \
-I$(top_srcdir)/libdocument \
-I$(top_srcdir)/libview \
$(SHELL_CORE_CFLAGS) \
$(WARNING_CFLAGS) \
$(DISABLE_DEPRECATED)
......
......@@ -43,7 +43,7 @@ struct _EvPageActionWidget
GtkToolItem parent;
EvDocument *document;
EvPageCache *page_cache;
EvDocumentModel *doc_model;
GtkWidget *entry;
GtkWidget *label;
......@@ -74,9 +74,8 @@ update_pages_label (EvPageActionWidget *action_widget,
}
static void
page_changed_cb (EvPageCache *page_cache,
gint page,
EvPageActionWidget *action_widget)
ev_page_action_widget_set_current_page (EvPageActionWidget *action_widget,
gint page)
{
if (page >= 0) {
gchar *page_label;
......@@ -97,19 +96,28 @@ page_changed_cb (EvPageCache *page_cache,
update_pages_label (action_widget, page);
}
static void
page_changed_cb (EvDocumentModel *model,
gint old_page,
gint new_page,
EvPageActionWidget *action_widget)
{
ev_page_action_widget_set_current_page (action_widget, new_page);
}
static gboolean
page_scroll_cb (EvPageActionWidget *action_widget, GdkEventScroll *event)
{
EvPageCache *page_cache = action_widget->page_cache;
EvDocumentModel *model = action_widget->doc_model;
gint pageno;
pageno = ev_page_cache_get_current_page (page_cache);
pageno = ev_document_model_get_page (model);
if ((event->direction == GDK_SCROLL_DOWN) &&
(pageno < ev_document_get_n_pages (action_widget->document) - 1))
pageno++;
if ((event->direction == GDK_SCROLL_UP) && (pageno > 0))
pageno--;
ev_page_cache_set_current_page (page_cache, pageno);
ev_document_model_set_page (model, pageno);
return TRUE;
}
......@@ -117,7 +125,7 @@ page_scroll_cb (EvPageActionWidget *action_widget, GdkEventScroll *event)
static void
activate_cb (EvPageActionWidget *action_widget)
{
EvPageCache *page_cache;
EvDocumentModel *model;
const char *text;
gchar *page_label;
EvLinkDest *link_dest;
......@@ -139,9 +147,9 @@ activate_cb (EvPageActionWidget *action_widget)
/* rest the entry to the current page if we were unable to
* change it */
page_cache = action_widget->page_cache;
model = action_widget->doc_model;
page_label = ev_document_get_page_label (action_widget->document,
ev_page_cache_get_current_page (page_cache));
ev_document_model_get_page (model));
gtk_entry_set_text (GTK_ENTRY (action_widget->entry), page_label);
gtk_editable_set_position (GTK_EDITABLE (action_widget->entry), -1);
g_free (page_label);
......@@ -187,38 +195,48 @@ ev_page_action_widget_init (EvPageActionWidget *action_widget)
gtk_widget_show (GTK_WIDGET (action_widget));
}
void
ev_page_action_widget_set_document (EvPageActionWidget *action_widget,
EvDocument *document)
static void
ev_page_action_widget_document_changed_cb (EvDocumentModel *model,
GParamSpec *pspec,
EvPageActionWidget *action_widget)
{
EvPageCache *page_cache = ev_page_cache_get (document);
EvDocument *document = ev_document_model_get_document (model);
g_object_ref (document);
if (action_widget->document)
g_object_unref (action_widget->document);
action_widget->document = document;
if (action_widget->page_cache != NULL) {
if (action_widget->signal_id > 0) {
g_signal_handler_disconnect (action_widget->page_cache,
action_widget->signal_id);
action_widget->signal_id = 0;
}
g_object_remove_weak_pointer (G_OBJECT (action_widget->page_cache),
(gpointer)&action_widget->page_cache);
action_widget->page_cache = NULL;
if (action_widget->signal_id > 0) {
g_signal_handler_disconnect (action_widget->doc_model,
action_widget->signal_id);
action_widget->signal_id = 0;
}
action_widget->page_cache = page_cache;
g_object_add_weak_pointer (G_OBJECT (page_cache),
(gpointer)&action_widget->page_cache);
action_widget->signal_id =
g_signal_connect_object (page_cache, "page-changed",
g_signal_connect_object (action_widget->doc_model,
"page-changed",
G_CALLBACK (page_changed_cb),
action_widget, 0);
page_changed_cb (page_cache,
ev_page_cache_get_current_page (page_cache),
action_widget);
ev_page_action_widget_set_current_page (action_widget,
ev_document_model_get_page (model));
}
void
ev_page_action_widget_set_model (EvPageActionWidget *action_widget,
EvDocumentModel *model)
{
if (action_widget->doc_model) {
g_object_remove_weak_pointer (G_OBJECT (action_widget->doc_model),
(gpointer)&action_widget->doc_model);
}
action_widget->doc_model = model;
g_object_add_weak_pointer (G_OBJECT (model),
(gpointer)&action_widget->doc_model);
g_signal_connect (model, "notify::document",
G_CALLBACK (ev_page_action_widget_document_changed_cb),
action_widget);
}
static void
......@@ -226,15 +244,15 @@ ev_page_action_widget_finalize (GObject *object)
{
EvPageActionWidget *action_widget = EV_PAGE_ACTION_WIDGET (object);
if (action_widget->page_cache != NULL) {
if (action_widget->doc_model != NULL) {
if (action_widget->signal_id > 0) {
g_signal_handler_disconnect (action_widget->page_cache,
g_signal_handler_disconnect (action_widget->doc_model,
action_widget->signal_id);
action_widget->signal_id = 0;
}
g_object_remove_weak_pointer (G_OBJECT (action_widget->page_cache),
(gpointer)&action_widget->page_cache);
action_widget->page_cache = NULL;
g_object_remove_weak_pointer (G_OBJECT (action_widget->doc_model),
(gpointer)&action_widget->doc_model);
action_widget->doc_model = NULL;
}
if (action_widget->document) {
......@@ -432,7 +450,7 @@ get_filter_model_from_model (GtkTreeModel *model)
void
ev_page_action_widget_update_model (EvPageActionWidget *proxy, GtkTreeModel *model)
ev_page_action_widget_update_links_model (EvPageActionWidget *proxy, GtkTreeModel *model)
{
GtkTreeModel *filter_model;
GtkEntryCompletion *completion;
......@@ -470,7 +488,6 @@ ev_page_action_widget_update_model (EvPageActionWidget *proxy, GtkTreeModel *mod
gtk_entry_set_completion (GTK_ENTRY (proxy->entry), completion);
g_object_unref (completion);
g_object_unref (model);
}
void
......
......@@ -36,11 +36,11 @@ struct _EvPageActionWidgetClass
EvLink *link);
};
GType ev_page_action_widget_get_type (void) G_GNUC_CONST;
GType ev_page_action_widget_get_type (void) G_GNUC_CONST;
void ev_page_action_widget_update_model (EvPageActionWidget *proxy,
GtkTreeModel *model);
void ev_page_action_widget_update_links_model (EvPageActionWidget *proxy,
GtkTreeModel *model);
void ev_page_action_widget_set_document (EvPageActionWidget *action_widget,
EvDocument *document);
void ev_page_action_widget_grab_focus (EvPageActionWidget *proxy);
void ev_page_action_widget_set_model (EvPageActionWidget *action_widget,
EvDocumentModel *doc_model);
void ev_page_action_widget_grab_focus (EvPageActionWidget *proxy);
......@@ -33,7 +33,7 @@
struct _EvPageActionPrivate
{
EvDocument *document;
EvDocumentModel *doc_model;
GtkTreeModel *model;
};
......@@ -55,8 +55,7 @@ G_DEFINE_TYPE (EvPageAction, ev_page_action, GTK_TYPE_ACTION)
enum {
PROP_0,
PROP_DOCUMENT,
PROP_MODEL,
PROP_MODEL
};
static GtkWidget *
......@@ -69,23 +68,10 @@ create_tool_item (GtkAction *action)
return proxy;
}
static void
update_document (EvPageAction *page, GParamSpec *pspec, EvPageActionWidget *proxy)
{
if (page->priv->document)
ev_page_action_widget_set_document (proxy, page->priv->document);
}
static void
update_model (EvPageAction *page, GParamSpec *pspec, EvPageActionWidget *proxy)
{
GtkTreeModel *model;
g_object_get (G_OBJECT (page),
"model", &model,
NULL);
ev_page_action_widget_update_model (proxy, model);
ev_page_action_widget_update_links_model (proxy, page->priv->model);
}
static void
......@@ -97,10 +83,11 @@ activate_link_cb (EvPageActionWidget *proxy, EvLink *link, EvPageAction *action)
static void
connect_proxy (GtkAction *action, GtkWidget *proxy)
{
EvPageAction *page = EV_PAGE_ACTION (action);
if (GTK_IS_TOOL_ITEM (proxy)) {
g_signal_connect_object (action, "notify::document",
G_CALLBACK (update_document),
proxy, 0);
ev_page_action_widget_set_model (EV_PAGE_ACTION_WIDGET (proxy),
page->priv->doc_model);
g_signal_connect (proxy, "activate_link",
G_CALLBACK (activate_link_cb),
action);
......@@ -117,11 +104,13 @@ ev_page_action_dispose (GObject *object)
{
EvPageAction *page = EV_PAGE_ACTION (object);
if (page->priv->document) {
g_object_unref (page->priv->document);
page->priv->document = NULL;
if (page->priv->model) {
g_object_unref (page->priv->model);
page->priv->model = NULL;
}
page->priv->doc_model = NULL;
G_OBJECT_CLASS (ev_page_action_parent_class)->dispose (object);
}
......@@ -131,25 +120,13 @@ ev_page_action_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
EvPageAction *page;
EvDocument *document;
EvPageAction *page = EV_PAGE_ACTION (object);
GtkTreeModel *model;
page = EV_PAGE_ACTION (object);
switch (prop_id)
{
case PROP_DOCUMENT:
document = page->priv->document;
page->priv->document = EV_DOCUMENT (g_value_dup_object (value));
if (document)
g_object_unref (document);
break;
case PROP_MODEL:
model = page->priv->model;
page->priv->model = GTK_TREE_MODEL (g_value_dup_object (value));
if (model)
g_object_unref (model);
ev_page_action_set_links_model (page, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
......@@ -163,15 +140,10 @@ ev_page_action_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
EvPageAction *page;
page = EV_PAGE_ACTION (object);
EvPageAction *page = EV_PAGE_ACTION (object);
switch (prop_id)
{
case PROP_DOCUMENT:
g_value_set_object (value, page->priv->document);
break;
case PROP_MODEL:
g_value_set_object (value, page->priv->model);
break;
......@@ -182,21 +154,33 @@ ev_page_action_get_property (GObject *object,
}
void
ev_page_action_set_document (EvPageAction *page, EvDocument *document)
ev_page_action_set_model (EvPageAction *page,
EvDocumentModel *model)
{
g_object_set (page,
"document", document,
"model", NULL,
NULL);
g_return_if_fail (EV_IS_PAGE_ACTION (page));
g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
if (page->priv->doc_model == model)
return;
page->priv->doc_model = model;
}
void
ev_page_action_set_model (EvPageAction *page_action,
GtkTreeModel *model)
ev_page_action_set_links_model (EvPageAction *page,
GtkTreeModel *links_model)
{
g_object_set (page_action,
"model", model,
NULL);
g_return_if_fail (EV_IS_PAGE_ACTION (page));
g_return_if_fail (GTK_IS_TREE_MODEL (links_model));
if (page->priv->model == links_model)
return;
if (page->priv->model)
g_object_unref (page->priv->model);
page->priv->model = g_object_ref (links_model);
g_object_notify (G_OBJECT (page), "model");
}
void
......@@ -244,19 +228,11 @@ ev_page_action_class_init (EvPageActionClass *class)
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
g_object_class_install_property (object_class,
PROP_DOCUMENT,
g_param_spec_object ("document",
"Document",
"Current document",
EV_TYPE_DOCUMENT,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_MODEL,
g_param_spec_object ("model",
"Model",
"Current Model",
"Current Links Model",
GTK_TYPE_TREE_MODEL,
G_PARAM_READWRITE));
......
......@@ -24,6 +24,7 @@
#include <gtk/gtk.h>
#include <evince-document.h>
#include <evince-view.h>
G_BEGIN_DECLS
......@@ -54,12 +55,13 @@ struct _EvPageActionClass
EvLink *link);
};
GType ev_page_action_get_type (void);
void ev_page_action_set_document (EvPageAction *page_action,
EvDocument *document);
void ev_page_action_set_model (EvPageAction *page_action,
GtkTreeModel *model);
void ev_page_action_grab_focus (EvPageAction *page_action);
GType ev_page_action_get_type (void) G_GNUC_CONST;
void ev_page_action_set_model (EvPageAction *page_action,
EvDocumentModel *model);
void ev_page_action_set_links_model (EvPageAction *page_action,
GtkTreeModel *links_model);
void ev_page_action_grab_focus (EvPageAction *page_action);
G_END_DECLS
......
......@@ -10,9 +10,9 @@ NOINST_H_FILES = \
ev-view-private.h
INST_H_FILES = \
ev-document-model.h \
ev-jobs.h \
ev-job-scheduler.h \
ev-page-cache.h \
ev-stock-icons.h \
ev-view.h \
ev-view-type-builtins.h
......@@ -22,9 +22,9 @@ header_DATA = $(INST_H_FILES)
libevview_la_SOURCES = \
ev-annotation-window.c \
ev-document-model.c \
ev-jobs.c \
ev-job-scheduler.c \
ev-page-cache.c \
ev-pixbuf-cache.c \
ev-stock-icons.c \
ev-timeline.c \
......
/* this file is part of evince, a gnome document viewer
*
* Copyright (C) 2009 Carlos Garcia Campos
* Copyright (C) 2005 Red Hat, Inc
*
* Evince 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.
*
* Evince 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 "ev-document-model.h"
#include "ev-view-type-builtins.h"
#include "ev-view-marshal.h"
struct _EvDocumentModel
{
GObject base;
EvDocument *document;
gint n_pages;
gint page;
gint rotation;
gdouble scale;
EvSizingMode sizing_mode;
gdouble max_scale;
gdouble min_scale;
};
struct _EvDocumentModelClass
{
GObjectClass base_class;
/* Signals */
void (* page_changed) (EvDocumentModel *model,
gint old_page,
gint new_page);
};
enum {
PROP_0,
PROP_DOCUMENT,
PROP_PAGE,
PROP_ROTATION,
PROP_SCALE,
PROP_SIZING_MODE
};
enum
{
PAGE_CHANGED,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0 };
G_DEFINE_TYPE (EvDocumentModel, ev_document_model, G_TYPE_OBJECT)
static void
ev_document_model_finalize (GObject *object)
{
EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
if (model->document) {
g_object_unref (model->document);
model->document = NULL;
}
G_OBJECT_CLASS (ev_document_model_parent_class)->finalize (object);
}
static void
ev_document_model_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
switch (prop_id) {
case PROP_DOCUMENT:
ev_document_model_set_document (model, (EvDocument *)g_value_get_object (value));
break;
case PROP_PAGE:
ev_document_model_set_page (model, g_value_get_int (value));
break;
case PROP_ROTATION:
ev_document_model_set_rotation (model, g_value_get_int (value));
break;
case PROP_SCALE:
ev_document_model_set_scale (model, g_value_get_double (value));
break;
case PROP_SIZING_MODE:
ev_document_model_set_sizing_mode (model, g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ev_document_model_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
switch (prop_id) {
case PROP_DOCUMENT:
g_value_set_object (value, model->document);
break;
case PROP_PAGE:
g_value_set_int (value, model->page);
break;
case PROP_ROTATION:
g_value_set_int (value, model->rotation);
break;
case PROP_SCALE:
g_value_set_double (value, model->scale);
break;
case PROP_SIZING_MODE:
g_value_set_enum (value, model->sizing_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ev_document_model_class_init (EvDocumentModelClass *klass)
{
GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
g_object_class->get_property = ev_document_model_get_property;
g_object_class->set_property = ev_document_model_set_property;
g_object_class->finalize = ev_document_model_finalize;
/* Properties */
g_object_class_install_property (g_object_class,
PROP_DOCUMENT,
g_param_spec_object ("document",
"Document",
"The current document",
EV_TYPE_DOCUMENT,
G_PARAM_READWRITE));
g_object_class_install_property (g_object_class,
PROP_PAGE,
g_param_spec_int ("page",
"Page",
"Current page",
-1, G_MAXINT, -1,
G_PARAM_READWRITE));
g_object_class_install_property (g_object_class,
PROP_ROTATION,
g_param_spec_int ("rotation",
"Rotation",
"Current rotation angle",
0, 360, 0,
G_PARAM_READWRITE));
g_object_class_install_property (g_object_class,
PROP_SCALE,
g_param_spec_double ("scale",
"Scale",
"Current scale factor",
0., G_MAXDOUBLE, 1.,
G_PARAM_READWRITE));
g_object_class_install_property (g_object_class,
PROP_SIZING_MODE,
g_param_spec_enum ("sizing-mode",
"Sizing Mode",
"Current sizing mode",
EV_TYPE_SIZING_MODE,
EV_SIZING_FIT_WIDTH,
G_PARAM_READWRITE));
/* Signals */
signals [PAGE_CHANGED] =
g_signal_new ("page-changed",
EV_TYPE_DOCUMENT_MODEL,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EvDocumentModelClass, page_changed),
NULL, NULL,
ev_view_marshal_VOID__INT_INT,
G_TYPE_NONE, 2,
G_TYPE_INT, G_TYPE_INT);
}
static void
ev_document_model_init (EvDocumentModel *model)
{
model->page = -1;
model->scale = 1.;
model->sizing_mode = EV_SIZING_FIT_WIDTH;
model->min_scale = 0.;
model->max_scale = G_MAXDOUBLE;
}
EvDocumentModel *
ev_document_model_new (void)
{
return g_object_new (EV_TYPE_DOCUMENT_MODEL, NULL);
}
EvDocumentModel *
ev_document_model_new_with_document (EvDocument *document)
{
g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
return g_object_new (EV_TYPE_DOCUMENT_MODEL, "document", document, NULL);
}
void
ev_document_model_set_document (EvDocumentModel *model,
EvDocument *document)
{
g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
g_return_if_fail (EV_IS_DOCUMENT (document));
if (document == model->document)
return;
if (model->document)
g_object_unref (model->document);
model->document = g_object_ref (document);
model->n_pages = ev_document_get_n_pages (document);
ev_document_model_set_page (model, CLAMP (model->page, 0,
model->n_pages - 1));
g_object_notify (G_OBJECT (model), "document");
}
EvDocument *
ev_document_model_get_document (EvDocumentModel *model)
{
g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), NULL);
return model->document;
}
void
ev_document_model_set_page (EvDocumentModel *model,
gint page)
{
gint old_page;
g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
if (model->page == page)
return;
if (page < 0 || (model->document && page >= model->n_pages))
return;
old_page = model->page;
model->page = page;
g_signal_emit (model, signals[PAGE_CHANGED], 0, old_page, page);
g_object_notify (G_OBJECT (model), "page");
}
void
ev_document_model_set_page_by_label (EvDocumentModel *model,
const gchar *page_label)
{
gint page;
g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
g_return_if_fail (model->document != NULL);
if (ev_document_find_page_by_label (model->document, page_label, &page))
ev_document_model_set_page (model, page);
}