*
* 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <config.h>
+#if GTKUNIXPRINT_ENABLED
#include <gtk/gtkunixprint.h>
+#endif
#include <glib/gi18n.h>
#include <evince-view.h>
-#include "ev-stock-icons.h"
#include "ev-page-action.h"
#include "ev-previewer-window.h"
struct _EvPreviewerWindow {
GtkWindow base_instance;
+ EvDocumentModel *model;
EvDocument *document;
GtkActionGroup *action_group;
+ GtkActionGroup *accels_group;
GtkUIManager *ui_manager;
GtkWidget *swindow;
/* Printing */
GtkPrintSettings *print_settings;
GtkPageSetup *print_page_setup;
+#if GTKUNIXPRINT_ENABLED
GtkPrinter *printer;
+#endif
gchar *print_job_title;
gchar *source_file;
};
GtkWindowClass base_class;
};
+enum {
+ PROP_0,
+ PROP_MODEL
+};
+
+#define MIN_SCALE 0.05409
+#define MAX_SCALE 4.0
+
G_DEFINE_TYPE (EvPreviewerWindow, ev_previewer_window, GTK_TYPE_WINDOW)
static gdouble
-get_screen_dpi (GtkWindow *window)
+get_screen_dpi (EvPreviewerWindow *window)
{
GdkScreen *screen;
- gdouble xdpi, ydpi;
-
- screen = gtk_window_get_screen (window);
-
- xdpi = 25.4 * gdk_screen_get_width (screen) / gdk_screen_get_width_mm (screen);
- ydpi = 25.4 * gdk_screen_get_height (screen) / gdk_screen_get_height_mm (screen);
-
- return (xdpi + ydpi) / 2.0;
-}
-
-static void
-ev_previewer_window_set_view_size (EvPreviewerWindow *window)
-{
- gint width, height;
- GtkRequisition vsb_requisition;
- GtkRequisition hsb_requisition;
- gint scrollbar_spacing;
-
- if (!window->view)
- return;
-
- /* Calculate the width available for the content */
- width = window->swindow->allocation.width;
- height = window->swindow->allocation.height;
-
- if (gtk_scrolled_window_get_shadow_type (GTK_SCROLLED_WINDOW (window->swindow)) == GTK_SHADOW_IN) {
- width -= 2 * GTK_WIDGET (window->view)->style->xthickness;
- height -= 2 * GTK_WIDGET (window->view)->style->ythickness;
- }
- gtk_widget_size_request (GTK_SCROLLED_WINDOW (window->swindow)->vscrollbar,
- &vsb_requisition);
- gtk_widget_size_request (GTK_SCROLLED_WINDOW (window->swindow)->hscrollbar,
- &hsb_requisition);
- gtk_widget_style_get (window->swindow,
- "scrollbar_spacing",
- &scrollbar_spacing,
- NULL);
-
- ev_view_set_zoom_for_size (window->view,
- MAX (1, width),
- MAX (1, height),
- vsb_requisition.width + scrollbar_spacing,
- hsb_requisition.height + scrollbar_spacing);
+ screen = gtk_window_get_screen (GTK_WINDOW (window));
+ return ev_document_misc_get_screen_dpi (screen);
}
+#if GTKUNIXPRINT_ENABLED
static void
ev_previewer_window_error_dialog_run (EvPreviewerWindow *window,
GError *error)
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
+#endif
+
+static void
+ev_previewer_window_close (GtkAction *action,
+ EvPreviewerWindow *window)
+{
+ gtk_widget_destroy (GTK_WIDGET (window));
+}
static void
ev_previewer_window_previous_page (GtkAction *action,
ev_previewer_window_zoom_in (GtkAction *action,
EvPreviewerWindow *window)
{
- ev_view_set_sizing_mode (window->view, EV_SIZING_FREE);
+ ev_document_model_set_sizing_mode (window->model, EV_SIZING_FREE);
ev_view_zoom_in (window->view);
}
ev_previewer_window_zoom_out (GtkAction *action,
EvPreviewerWindow *window)
{
- ev_view_set_sizing_mode (window->view, EV_SIZING_FREE);
+ ev_document_model_set_sizing_mode (window->model, EV_SIZING_FREE);
ev_view_zoom_out (window->view);
}
ev_previewer_window_zoom_best_fit (GtkToggleAction *action,
EvPreviewerWindow *window)
{
- if (gtk_toggle_action_get_active (action)) {
- ev_view_set_sizing_mode (window->view, EV_SIZING_BEST_FIT);
- ev_previewer_window_set_view_size (window);
- } else {
- ev_view_set_sizing_mode (window->view, EV_SIZING_FREE);
- }
+ ev_document_model_set_sizing_mode (window->model,
+ gtk_toggle_action_get_active (action) ?
+ EV_SIZING_BEST_FIT : EV_SIZING_FREE);
}
static void
ev_previewer_window_zoom_page_width (GtkToggleAction *action,
EvPreviewerWindow *window)
{
- if (gtk_toggle_action_get_active (action)) {
- ev_view_set_sizing_mode (window->view, EV_SIZING_FIT_WIDTH);
- ev_previewer_window_set_view_size (window);
- } else {
- ev_view_set_sizing_mode (window->view, EV_SIZING_FREE);
- }
+ ev_document_model_set_sizing_mode (window->model,
+ gtk_toggle_action_get_active (action) ?
+ EV_SIZING_FIT_WIDTH : EV_SIZING_FREE);
}
static void
gtk_widget_grab_focus (GTK_WIDGET (window->view));
}
+static void
+ev_previewer_window_focus_page_selector (GtkAction *action,
+ EvPreviewerWindow *window)
+{
+ GtkAction *page_action;
+
+ page_action = gtk_action_group_get_action (window->action_group,
+ "PageSelector");
+ ev_page_action_grab_focus (EV_PAGE_ACTION (page_action));
+}
+
+static void
+ev_previewer_window_scroll_forward (GtkAction *action,
+ EvPreviewerWindow *window)
+{
+ ev_view_scroll (window->view, GTK_SCROLL_PAGE_FORWARD, FALSE);
+}
+
+static void
+ev_previewer_window_scroll_backward (GtkAction *action,
+ EvPreviewerWindow *window)
+{
+ ev_view_scroll (window->view, GTK_SCROLL_PAGE_BACKWARD, FALSE);
+}
+
+#if GTKUNIXPRINT_ENABLED
static void
ev_previewer_window_print_finished (GtkPrintJob *print_job,
EvPreviewerWindow *window,
(GDestroyNotify)ev_previewer_window_enumerate_finished,
FALSE);
}
+#endif
static const GtkActionEntry action_entries[] = {
+ { "FileCloseWindow", GTK_STOCK_CLOSE, NULL, "<control>W",
+ NULL,
+ G_CALLBACK (ev_previewer_window_close) },
{ "GoPreviousPage", GTK_STOCK_GO_UP, N_("_Previous Page"), "<control>Page_Up",
N_("Go to the previous page"),
G_CALLBACK (ev_previewer_window_previous_page) },
{ "ViewZoomOut", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus",
N_("Shrink the document"),
G_CALLBACK (ev_previewer_window_zoom_out) },
+#if GTKUNIXPRINT_ENABLED
{ "PreviewPrint", GTK_STOCK_PRINT, N_("Print"), NULL,
N_("Print this document"),
G_CALLBACK (ev_previewer_window_print) }
+#endif
+};
+
+static const GtkActionEntry accel_entries[] = {
+ { "Space", NULL, "", "space", NULL,
+ G_CALLBACK (ev_previewer_window_scroll_forward) },
+ { "ShiftSpace", NULL, "", "<shift>space", NULL,
+ G_CALLBACK (ev_previewer_window_scroll_backward) },
+ { "BackSpace", NULL, "", "BackSpace", NULL,
+ G_CALLBACK (ev_previewer_window_scroll_backward) },
+ { "ShiftBackSpace", NULL, "", "<shift>BackSpace", NULL,
+ G_CALLBACK (ev_previewer_window_scroll_forward) },
+ { "Return", NULL, "", "Return", NULL,
+ G_CALLBACK (ev_previewer_window_scroll_forward) },
+ { "ShiftReturn", NULL, "", "<shift>Return", NULL,
+ G_CALLBACK (ev_previewer_window_scroll_backward) },
+ { "p", GTK_STOCK_GO_UP, "", "p", NULL,
+ G_CALLBACK (ev_previewer_window_previous_page) },
+ { "n", GTK_STOCK_GO_DOWN, "", "n", NULL,
+ G_CALLBACK (ev_previewer_window_next_page) },
+ { "Plus", GTK_STOCK_ZOOM_IN, NULL, "plus", NULL,
+ G_CALLBACK (ev_previewer_window_zoom_in) },
+ { "CtrlEqual", GTK_STOCK_ZOOM_IN, NULL, "<control>equal", NULL,
+ G_CALLBACK (ev_previewer_window_zoom_in) },
+ { "Equal", GTK_STOCK_ZOOM_IN, NULL, "equal", NULL,
+ G_CALLBACK (ev_previewer_window_zoom_in) },
+ { "Minus", GTK_STOCK_ZOOM_OUT, NULL, "minus", NULL,
+ G_CALLBACK (ev_previewer_window_zoom_out) },
+ { "KpPlus", GTK_STOCK_ZOOM_IN, NULL, "KP_Add", NULL,
+ G_CALLBACK (ev_previewer_window_zoom_in) },
+ { "KpMinus", GTK_STOCK_ZOOM_OUT, NULL, "KP_Subtract", NULL,
+ G_CALLBACK (ev_previewer_window_zoom_out) },
+ { "CtrlKpPlus", GTK_STOCK_ZOOM_IN, NULL, "<control>KP_Add", NULL,
+ G_CALLBACK (ev_previewer_window_zoom_in) },
+ { "CtrlKpMinus", GTK_STOCK_ZOOM_OUT, NULL, "<control>KP_Subtract", NULL,
+ G_CALLBACK (ev_previewer_window_zoom_out) },
+ { "FocusPageSelector", NULL, "", "<control>l", NULL,
+ G_CALLBACK (ev_previewer_window_focus_page_selector) }
+
};
static const GtkToggleActionEntry toggle_action_entries[] = {
G_CALLBACK (ev_previewer_window_zoom_page_width) }
};
-/* EvView callbacks */
+static gboolean
+view_focus_changed (GtkWidget *widget,
+ GdkEventFocus *event,
+ EvPreviewerWindow *window)
+{
+ if (window->accels_group)
+ gtk_action_group_set_sensitive (window->accels_group, event->in);
+
+ return FALSE;
+}
+
static void
-view_sizing_mode_changed (EvView *view,
+view_sizing_mode_changed (EvDocumentModel *model,
GParamSpec *pspec,
EvPreviewerWindow *window)
{
- EvSizingMode sizing_mode;
+ EvSizingMode sizing_mode = ev_document_model_get_sizing_mode (model);
GtkAction *action;
- if (!window->view)
- return;
-
- g_object_get (window->view,
- "sizing_mode", &sizing_mode,
- NULL);
-
action = gtk_action_group_get_action (window->action_group, "ViewBestFit");
g_signal_handlers_block_by_func (action,
G_CALLBACK (ev_previewer_window_zoom_best_fit),
window);
}
+static void
+ev_previewer_window_set_document (EvPreviewerWindow *window,
+ GParamSpec *pspec,
+ EvDocumentModel *model)
+{
+ EvDocument *document = ev_document_model_get_document (model);
+
+ window->document = g_object_ref (document);
+
+ g_signal_connect (model, "notify::sizing-mode",
+ G_CALLBACK (view_sizing_mode_changed),
+ window);
+ ev_view_set_loading (window->view, FALSE);
+ gtk_action_group_set_sensitive (window->action_group, TRUE);
+ gtk_action_group_set_sensitive (window->accels_group, TRUE);
+}
+
+static void
+ev_previewer_window_connect_action_accelerators (EvPreviewerWindow *window)
+{
+ GList *actions;
+
+ gtk_ui_manager_ensure_update (window->ui_manager);
+
+ actions = gtk_action_group_list_actions (window->action_group);
+ g_list_foreach (actions, (GFunc)gtk_action_connect_accelerator, NULL);
+ g_list_free (actions);
+}
+
static void
ev_previewer_window_dispose (GObject *object)
{
EvPreviewerWindow *window = EV_PREVIEWER_WINDOW (object);
+ if (window->model) {
+ g_object_unref (window->model);
+ window->model = NULL;
+ }
+
if (window->document) {
g_object_unref (window->document);
window->document = NULL;
window->action_group = NULL;
}
+ if (window->accels_group) {
+ g_object_unref (window->accels_group);
+ window->accels_group = NULL;
+ }
+
if (window->ui_manager) {
g_object_unref (window->ui_manager);
window->ui_manager = NULL;
window->print_page_setup = NULL;
}
+#if GTKUNIXPRINT_ENABLED
if (window->printer) {
g_object_unref (window->printer);
window->printer = NULL;
}
+#endif
if (window->print_job_title) {
g_free (window->print_job_title);
G_OBJECT_CLASS (ev_previewer_window_parent_class)->dispose (object);
}
+static gchar*
+data_dir (void)
+{
+ gchar *datadir;
+#ifdef G_OS_WIN32
+ gchar *dir;
+
+ dir = g_win32_get_package_installation_directory_of_module (NULL);
+ datadir = g_build_filename (dir, "share", "evince", NULL);
+ g_free (dir);
+#else
+ datadir = g_strdup (EVINCEDATADIR);
+#endif
+
+ return datadir;
+}
+
static void
ev_previewer_window_init (EvPreviewerWindow *window)
{
- GtkWidget *vbox;
- GtkWidget *toolbar;
- GtkAction *action;
- GError *error = NULL;
-
gtk_window_set_default_size (GTK_WINDOW (window), 600, 600);
-
+}
+
+static void
+ev_previewer_window_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EvPreviewerWindow *window = EV_PREVIEWER_WINDOW (object);
+
+ switch (prop_id) {
+ case PROP_MODEL:
+ window->model = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static GObject *
+ev_previewer_window_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ EvPreviewerWindow *window;
+ GtkWidget *vbox;
+ GtkWidget *toolbar;
+ GtkAction *action;
+ GError *error = NULL;
+ gchar *datadir, *ui_path;
+ gdouble dpi;
+
+ object = G_OBJECT_CLASS (ev_previewer_window_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_params);
+ window = EV_PREVIEWER_WINDOW (object);
+
+ dpi = get_screen_dpi (window);
+ ev_document_model_set_min_scale (window->model, MIN_SCALE * dpi / 72.0);
+ ev_document_model_set_max_scale (window->model, MAX_SCALE * dpi / 72.0);
+ ev_document_model_set_sizing_mode (window->model, EV_SIZING_FIT_WIDTH);
+ g_signal_connect_swapped (window->model, "notify::document",
+ G_CALLBACK (ev_previewer_window_set_document),
+ window);
+
window->action_group = gtk_action_group_new ("PreviewerActions");
gtk_action_group_set_translation_domain (window->action_group, NULL);
gtk_action_group_add_actions (window->action_group, action_entries,
"icon_name", "text-x-generic",
"visible_overflown", FALSE,
NULL);
+ ev_page_action_set_model (EV_PAGE_ACTION (action), window->model);
g_signal_connect (action, "activate_link",
G_CALLBACK (ev_previewer_window_action_page_activated),
window);
gtk_action_group_add_action (window->action_group, action);
g_object_unref (action);
+ window->accels_group = gtk_action_group_new ("PreviewerAccelerators");
+ gtk_action_group_add_actions (window->accels_group, accel_entries,
+ G_N_ELEMENTS (accel_entries),
+ window);
+ gtk_action_group_set_sensitive (window->accels_group, FALSE);
+
window->ui_manager = gtk_ui_manager_new ();
gtk_ui_manager_insert_action_group (window->ui_manager,
window->action_group, 0);
+ gtk_ui_manager_insert_action_group (window->ui_manager,
+ window->accels_group, 1);
gtk_window_add_accel_group (GTK_WINDOW (window),
gtk_ui_manager_get_accel_group (window->ui_manager));
- if (!gtk_ui_manager_add_ui_from_file (window->ui_manager,
- DATADIR"/evince-previewer-ui.xml",
- &error)) {
+ datadir = data_dir ();
+ ui_path = g_build_filename (datadir, "evince-previewer-ui.xml", NULL);
+ if (!gtk_ui_manager_add_ui_from_file (window->ui_manager, ui_path, &error)) {
g_warning ("Failed to load ui from evince-previewer-ui.xml: %s", error->message);
g_error_free (error);
}
+ g_free (ui_path);
+ g_free (datadir);
+
+ /* GTKUIManager connects actions accels only for menu items,
+ * but not for tool items. See bug #612972.
+ */
+ ev_previewer_window_connect_action_accelerators (window);
+
+ view_sizing_mode_changed (window->model, NULL, window);
vbox = gtk_vbox_new (FALSE, 0);
toolbar = gtk_ui_manager_get_widget (window->ui_manager, "/PreviewToolbar");
gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
gtk_widget_show (toolbar);
-
+
window->swindow = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (window->swindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
-
+
window->view = EV_VIEW (ev_view_new ());
- g_signal_connect (window->view, "notify::sizing-mode",
- G_CALLBACK (view_sizing_mode_changed),
- window);
- g_signal_connect_swapped (window->view, "zoom_invalid",
- G_CALLBACK (ev_previewer_window_set_view_size),
- window);
-
- ev_view_set_screen_dpi (window->view, get_screen_dpi (GTK_WINDOW (window)));
- ev_view_set_continuous (window->view, FALSE);
- ev_view_set_sizing_mode (window->view, EV_SIZING_FIT_WIDTH);
+ g_signal_connect_object (window->view, "focus_in_event",
+ G_CALLBACK (view_focus_changed),
+ window, 0);
+ g_signal_connect_object (window->view, "focus_out_event",
+ G_CALLBACK (view_focus_changed),
+ window, 0);
+ ev_view_set_model (window->view, window->model);
+ ev_document_model_set_continuous (window->model, FALSE);
ev_view_set_loading (window->view, TRUE);
- view_sizing_mode_changed (window->view, NULL, window);
gtk_container_add (GTK_CONTAINER (window->swindow), GTK_WIDGET (window->view));
gtk_widget_show (GTK_WIDGET (window->view));
gtk_box_pack_start (GTK_BOX (vbox), window->swindow, TRUE, TRUE, 0);
gtk_widget_show (window->swindow);
-
+
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show (vbox);
+
+ return object;
}
+
static void
ev_previewer_window_class_init (EvPreviewerWindowClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->constructor = ev_previewer_window_constructor;
+ gobject_class->set_property = ev_previewer_window_set_property;
gobject_class->dispose = ev_previewer_window_dispose;
+
+ g_object_class_install_property (gobject_class,
+ PROP_MODEL,
+ g_param_spec_object ("model",
+ "Model",
+ "The document model",
+ EV_TYPE_DOCUMENT_MODEL,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY));
}
/* Public methods */
GtkWidget *
-ev_previewer_window_new (void)
+ev_previewer_window_new (EvDocumentModel *model)
{
- return GTK_WIDGET (g_object_new (EV_TYPE_PREVIEWER_WINDOW, NULL));
-}
-
-void
-ev_previewer_window_set_document (EvPreviewerWindow *window,
- EvDocument *document)
-{
- GtkAction *action;
-
- g_return_if_fail (EV_IS_PREVIEWER_WINDOW (window));
- g_return_if_fail (EV_IS_DOCUMENT (document));
-
- if (window->document)
- return;
-
- action = gtk_action_group_get_action (window->action_group, "PageSelector");
- ev_page_action_set_document (EV_PAGE_ACTION (action), document);
- gtk_action_group_set_sensitive (window->action_group, TRUE);
-
- window->document = g_object_ref (document);
- ev_view_set_document (window->view, document);
- ev_view_set_zoom (window->view,
- get_screen_dpi (GTK_WINDOW (window)) / 72.0,
- FALSE);
- ev_view_set_loading (window->view, FALSE);
+ return GTK_WIDGET (g_object_new (EV_TYPE_PREVIEWER_WINDOW, "model", model, NULL));
}
void