1 /* ev-previewer-window.c:
2 * this file is part of evince, a gnome document viewer
4 * Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
6 * Evince is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Evince is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #if GTKUNIXPRINT_ENABLED
24 #include <gtk/gtkunixprint.h>
26 #include <glib/gi18n.h>
27 #include <evince-view.h>
28 #include "ev-page-action.h"
30 #include "ev-previewer-window.h"
32 struct _EvPreviewerWindow {
33 GtkWindow base_instance;
35 EvDocumentModel *model;
38 GtkActionGroup *action_group;
39 GtkActionGroup *accels_group;
40 GtkUIManager *ui_manager;
47 GtkPrintSettings *print_settings;
48 GtkPageSetup *print_page_setup;
49 #if GTKUNIXPRINT_ENABLED
52 gchar *print_job_title;
56 struct _EvPreviewerWindowClass {
57 GtkWindowClass base_class;
65 #define MIN_SCALE 0.05409
68 G_DEFINE_TYPE (EvPreviewerWindow, ev_previewer_window, GTK_TYPE_WINDOW)
71 get_screen_dpi (EvPreviewerWindow *window)
75 screen = gtk_window_get_screen (GTK_WINDOW (window));
76 return ev_document_misc_get_screen_dpi (screen);
79 #if GTKUNIXPRINT_ENABLED
81 ev_previewer_window_error_dialog_run (EvPreviewerWindow *window,
86 dialog = gtk_message_dialog_new (GTK_WINDOW (window),
88 GTK_DIALOG_DESTROY_WITH_PARENT,
91 "%s", _("Failed to print document"));
92 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
93 "%s", error->message);
94 gtk_dialog_run (GTK_DIALOG (dialog));
95 gtk_widget_destroy (dialog);
100 ev_previewer_window_close (GtkAction *action,
101 EvPreviewerWindow *window)
103 gtk_widget_destroy (GTK_WIDGET (window));
107 ev_previewer_window_previous_page (GtkAction *action,
108 EvPreviewerWindow *window)
110 ev_view_previous_page (window->view);
114 ev_previewer_window_next_page (GtkAction *action,
115 EvPreviewerWindow *window)
117 ev_view_next_page (window->view);
121 ev_previewer_window_zoom_in (GtkAction *action,
122 EvPreviewerWindow *window)
124 ev_document_model_set_sizing_mode (window->model, EV_SIZING_FREE);
125 ev_view_zoom_in (window->view);
129 ev_previewer_window_zoom_out (GtkAction *action,
130 EvPreviewerWindow *window)
132 ev_document_model_set_sizing_mode (window->model, EV_SIZING_FREE);
133 ev_view_zoom_out (window->view);
137 ev_previewer_window_zoom_best_fit (GtkToggleAction *action,
138 EvPreviewerWindow *window)
140 ev_document_model_set_sizing_mode (window->model,
141 gtk_toggle_action_get_active (action) ?
142 EV_SIZING_BEST_FIT : EV_SIZING_FREE);
146 ev_previewer_window_zoom_page_width (GtkToggleAction *action,
147 EvPreviewerWindow *window)
149 ev_document_model_set_sizing_mode (window->model,
150 gtk_toggle_action_get_active (action) ?
151 EV_SIZING_FIT_WIDTH : EV_SIZING_FREE);
155 ev_previewer_window_action_page_activated (GtkAction *action,
157 EvPreviewerWindow *window)
159 ev_view_handle_link (window->view, link);
160 gtk_widget_grab_focus (GTK_WIDGET (window->view));
164 ev_previewer_window_focus_page_selector (GtkAction *action,
165 EvPreviewerWindow *window)
167 GtkAction *page_action;
169 page_action = gtk_action_group_get_action (window->action_group,
171 ev_page_action_grab_focus (EV_PAGE_ACTION (page_action));
175 ev_previewer_window_scroll_forward (GtkAction *action,
176 EvPreviewerWindow *window)
178 ev_view_scroll (window->view, GTK_SCROLL_PAGE_FORWARD, FALSE);
182 ev_previewer_window_scroll_backward (GtkAction *action,
183 EvPreviewerWindow *window)
185 ev_view_scroll (window->view, GTK_SCROLL_PAGE_BACKWARD, FALSE);
188 #if GTKUNIXPRINT_ENABLED
190 ev_previewer_window_print_finished (GtkPrintJob *print_job,
191 EvPreviewerWindow *window,
195 ev_previewer_window_error_dialog_run (window, error);
198 g_object_unref (print_job);
199 gtk_widget_destroy (GTK_WIDGET (window));
203 ev_previewer_window_do_print (EvPreviewerWindow *window)
206 GError *error = NULL;
208 job = gtk_print_job_new (window->print_job_title ?
209 window->print_job_title :
212 window->print_settings,
213 window->print_page_setup);
214 if (gtk_print_job_set_source_file (job, window->source_file, &error)) {
215 gtk_print_job_send (job,
216 (GtkPrintJobCompleteFunc)ev_previewer_window_print_finished,
219 ev_previewer_window_error_dialog_run (window, error);
220 g_error_free (error);
223 gtk_widget_hide (GTK_WIDGET (window));
227 ev_previewer_window_enumerate_finished (EvPreviewerWindow *window)
229 if (window->printer) {
230 ev_previewer_window_do_print (window);
232 GError *error = NULL;
236 GTK_PRINT_ERROR_GENERAL,
237 _("The selected printer '%s' could not be found"),
238 gtk_print_settings_get_printer (window->print_settings));
240 ev_previewer_window_error_dialog_run (window, error);
241 g_error_free (error);
246 ev_previewer_window_enumerate_printers (GtkPrinter *printer,
247 EvPreviewerWindow *window)
249 const gchar *printer_name;
251 printer_name = gtk_print_settings_get_printer (window->print_settings);
253 && strcmp (printer_name, gtk_printer_get_name (printer)) == 0) ||
254 (!printer_name && gtk_printer_is_default (printer))) {
256 g_object_unref (window->printer);
257 window->printer = g_object_ref (printer);
259 return TRUE; /* we're done */
262 return FALSE; /* continue the enumeration */
266 ev_previewer_window_print (GtkAction *action,
267 EvPreviewerWindow *window)
269 if (!window->print_settings)
270 window->print_settings = gtk_print_settings_new ();
271 if (!window->print_page_setup)
272 window->print_page_setup = gtk_page_setup_new ();
273 gtk_enumerate_printers ((GtkPrinterFunc)ev_previewer_window_enumerate_printers,
275 (GDestroyNotify)ev_previewer_window_enumerate_finished,
280 static const GtkActionEntry action_entries[] = {
281 { "FileCloseWindow", GTK_STOCK_CLOSE, NULL, "<control>W",
283 G_CALLBACK (ev_previewer_window_close) },
284 { "GoPreviousPage", GTK_STOCK_GO_UP, N_("_Previous Page"), "<control>Page_Up",
285 N_("Go to the previous page"),
286 G_CALLBACK (ev_previewer_window_previous_page) },
287 { "GoNextPage", GTK_STOCK_GO_DOWN, N_("_Next Page"), "<control>Page_Down",
288 N_("Go to the next page"),
289 G_CALLBACK (ev_previewer_window_next_page) },
290 { "ViewZoomIn", GTK_STOCK_ZOOM_IN, NULL, "<control>plus",
291 N_("Enlarge the document"),
292 G_CALLBACK (ev_previewer_window_zoom_in) },
293 { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus",
294 N_("Shrink the document"),
295 G_CALLBACK (ev_previewer_window_zoom_out) },
296 #if GTKUNIXPRINT_ENABLED
297 { "PreviewPrint", GTK_STOCK_PRINT, N_("Print"), NULL,
298 N_("Print this document"),
299 G_CALLBACK (ev_previewer_window_print) }
303 static const GtkActionEntry accel_entries[] = {
304 { "Space", NULL, "", "space", NULL,
305 G_CALLBACK (ev_previewer_window_scroll_forward) },
306 { "ShiftSpace", NULL, "", "<shift>space", NULL,
307 G_CALLBACK (ev_previewer_window_scroll_backward) },
308 { "BackSpace", NULL, "", "BackSpace", NULL,
309 G_CALLBACK (ev_previewer_window_scroll_backward) },
310 { "ShiftBackSpace", NULL, "", "<shift>BackSpace", NULL,
311 G_CALLBACK (ev_previewer_window_scroll_forward) },
312 { "Return", NULL, "", "Return", NULL,
313 G_CALLBACK (ev_previewer_window_scroll_forward) },
314 { "ShiftReturn", NULL, "", "<shift>Return", NULL,
315 G_CALLBACK (ev_previewer_window_scroll_backward) },
316 { "p", GTK_STOCK_GO_UP, "", "p", NULL,
317 G_CALLBACK (ev_previewer_window_previous_page) },
318 { "n", GTK_STOCK_GO_DOWN, "", "n", NULL,
319 G_CALLBACK (ev_previewer_window_next_page) },
320 { "Plus", GTK_STOCK_ZOOM_IN, NULL, "plus", NULL,
321 G_CALLBACK (ev_previewer_window_zoom_in) },
322 { "CtrlEqual", GTK_STOCK_ZOOM_IN, NULL, "<control>equal", NULL,
323 G_CALLBACK (ev_previewer_window_zoom_in) },
324 { "Equal", GTK_STOCK_ZOOM_IN, NULL, "equal", NULL,
325 G_CALLBACK (ev_previewer_window_zoom_in) },
326 { "Minus", GTK_STOCK_ZOOM_OUT, NULL, "minus", NULL,
327 G_CALLBACK (ev_previewer_window_zoom_out) },
328 { "KpPlus", GTK_STOCK_ZOOM_IN, NULL, "KP_Add", NULL,
329 G_CALLBACK (ev_previewer_window_zoom_in) },
330 { "KpMinus", GTK_STOCK_ZOOM_OUT, NULL, "KP_Subtract", NULL,
331 G_CALLBACK (ev_previewer_window_zoom_out) },
332 { "CtrlKpPlus", GTK_STOCK_ZOOM_IN, NULL, "<control>KP_Add", NULL,
333 G_CALLBACK (ev_previewer_window_zoom_in) },
334 { "CtrlKpMinus", GTK_STOCK_ZOOM_OUT, NULL, "<control>KP_Subtract", NULL,
335 G_CALLBACK (ev_previewer_window_zoom_out) },
336 { "FocusPageSelector", NULL, "", "<control>l", NULL,
337 G_CALLBACK (ev_previewer_window_focus_page_selector) }
341 static const GtkToggleActionEntry toggle_action_entries[] = {
342 { "ViewBestFit", EV_STOCK_ZOOM_PAGE, N_("_Best Fit"), NULL,
343 N_("Make the current document fill the window"),
344 G_CALLBACK (ev_previewer_window_zoom_best_fit) },
345 { "ViewPageWidth", EV_STOCK_ZOOM_WIDTH, N_("Fit Page _Width"), NULL,
346 N_("Make the current document fill the window width"),
347 G_CALLBACK (ev_previewer_window_zoom_page_width) }
351 view_focus_changed (GtkWidget *widget,
352 GdkEventFocus *event,
353 EvPreviewerWindow *window)
355 if (window->accels_group)
356 gtk_action_group_set_sensitive (window->accels_group, event->in);
362 view_sizing_mode_changed (EvDocumentModel *model,
364 EvPreviewerWindow *window)
366 EvSizingMode sizing_mode = ev_document_model_get_sizing_mode (model);
369 action = gtk_action_group_get_action (window->action_group, "ViewBestFit");
370 g_signal_handlers_block_by_func (action,
371 G_CALLBACK (ev_previewer_window_zoom_best_fit),
373 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
374 sizing_mode == EV_SIZING_BEST_FIT);
375 g_signal_handlers_unblock_by_func (action,
376 G_CALLBACK (ev_previewer_window_zoom_best_fit),
379 action = gtk_action_group_get_action (window->action_group, "ViewPageWidth");
380 g_signal_handlers_block_by_func (action,
381 G_CALLBACK (ev_previewer_window_zoom_page_width),
383 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
384 sizing_mode == EV_SIZING_FIT_WIDTH);
385 g_signal_handlers_unblock_by_func (action,
386 G_CALLBACK (ev_previewer_window_zoom_page_width),
391 ev_previewer_window_set_document (EvPreviewerWindow *window,
393 EvDocumentModel *model)
395 EvDocument *document = ev_document_model_get_document (model);
397 window->document = g_object_ref (document);
399 g_signal_connect (model, "notify::sizing-mode",
400 G_CALLBACK (view_sizing_mode_changed),
402 ev_view_set_loading (window->view, FALSE);
403 gtk_action_group_set_sensitive (window->action_group, TRUE);
404 gtk_action_group_set_sensitive (window->accels_group, TRUE);
408 ev_previewer_window_connect_action_accelerators (EvPreviewerWindow *window)
412 gtk_ui_manager_ensure_update (window->ui_manager);
414 actions = gtk_action_group_list_actions (window->action_group);
415 g_list_foreach (actions, (GFunc)gtk_action_connect_accelerator, NULL);
416 g_list_free (actions);
420 ev_previewer_window_dispose (GObject *object)
422 EvPreviewerWindow *window = EV_PREVIEWER_WINDOW (object);
425 g_object_unref (window->model);
426 window->model = NULL;
429 if (window->document) {
430 g_object_unref (window->document);
431 window->document = NULL;
434 if (window->action_group) {
435 g_object_unref (window->action_group);
436 window->action_group = NULL;
439 if (window->accels_group) {
440 g_object_unref (window->accels_group);
441 window->accels_group = NULL;
444 if (window->ui_manager) {
445 g_object_unref (window->ui_manager);
446 window->ui_manager = NULL;
449 if (window->print_settings) {
450 g_object_unref (window->print_settings);
451 window->print_settings = NULL;
454 if (window->print_page_setup) {
455 g_object_unref (window->print_page_setup);
456 window->print_page_setup = NULL;
459 #if GTKUNIXPRINT_ENABLED
460 if (window->printer) {
461 g_object_unref (window->printer);
462 window->printer = NULL;
466 if (window->print_job_title) {
467 g_free (window->print_job_title);
468 window->print_job_title = NULL;
471 if (window->source_file) {
472 g_free (window->source_file);
473 window->source_file = NULL;
476 G_OBJECT_CLASS (ev_previewer_window_parent_class)->dispose (object);
486 dir = g_win32_get_package_installation_directory_of_module (NULL);
487 datadir = g_build_filename (dir, "share", "evince", NULL);
490 datadir = g_strdup (EVINCEDATADIR);
497 ev_previewer_window_init (EvPreviewerWindow *window)
499 gtk_window_set_default_size (GTK_WINDOW (window), 600, 600);
503 ev_previewer_window_set_property (GObject *object,
508 EvPreviewerWindow *window = EV_PREVIEWER_WINDOW (object);
512 window->model = g_value_dup_object (value);
515 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
520 ev_previewer_window_constructor (GType type,
521 guint n_construct_properties,
522 GObjectConstructParam *construct_params)
525 EvPreviewerWindow *window;
529 GError *error = NULL;
530 gchar *datadir, *ui_path;
533 object = G_OBJECT_CLASS (ev_previewer_window_parent_class)->constructor (type,
534 n_construct_properties,
536 window = EV_PREVIEWER_WINDOW (object);
538 dpi = get_screen_dpi (window);
539 ev_document_model_set_min_scale (window->model, MIN_SCALE * dpi / 72.0);
540 ev_document_model_set_max_scale (window->model, MAX_SCALE * dpi / 72.0);
541 ev_document_model_set_sizing_mode (window->model, EV_SIZING_FIT_WIDTH);
542 g_signal_connect_swapped (window->model, "notify::document",
543 G_CALLBACK (ev_previewer_window_set_document),
546 window->action_group = gtk_action_group_new ("PreviewerActions");
547 gtk_action_group_set_translation_domain (window->action_group, NULL);
548 gtk_action_group_add_actions (window->action_group, action_entries,
549 G_N_ELEMENTS (action_entries),
551 gtk_action_group_add_toggle_actions (window->action_group, toggle_action_entries,
552 G_N_ELEMENTS (toggle_action_entries),
554 gtk_action_group_set_sensitive (window->action_group, FALSE);
556 action = g_object_new (EV_TYPE_PAGE_ACTION,
557 "name", "PageSelector",
559 "tooltip", _("Select Page"),
560 "icon_name", "text-x-generic",
561 "visible_overflown", FALSE,
563 ev_page_action_set_model (EV_PAGE_ACTION (action), window->model);
564 g_signal_connect (action, "activate_link",
565 G_CALLBACK (ev_previewer_window_action_page_activated),
567 gtk_action_group_add_action (window->action_group, action);
568 g_object_unref (action);
570 window->accels_group = gtk_action_group_new ("PreviewerAccelerators");
571 gtk_action_group_add_actions (window->accels_group, accel_entries,
572 G_N_ELEMENTS (accel_entries),
574 gtk_action_group_set_sensitive (window->accels_group, FALSE);
576 window->ui_manager = gtk_ui_manager_new ();
577 gtk_ui_manager_insert_action_group (window->ui_manager,
578 window->action_group, 0);
579 gtk_ui_manager_insert_action_group (window->ui_manager,
580 window->accels_group, 1);
581 gtk_window_add_accel_group (GTK_WINDOW (window),
582 gtk_ui_manager_get_accel_group (window->ui_manager));
583 datadir = data_dir ();
584 ui_path = g_build_filename (datadir, "evince-previewer-ui.xml", NULL);
585 if (!gtk_ui_manager_add_ui_from_file (window->ui_manager, ui_path, &error)) {
586 g_warning ("Failed to load ui from evince-previewer-ui.xml: %s", error->message);
587 g_error_free (error);
592 /* GTKUIManager connects actions accels only for menu items,
593 * but not for tool items. See bug #612972.
595 ev_previewer_window_connect_action_accelerators (window);
597 view_sizing_mode_changed (window->model, NULL, window);
599 vbox = gtk_vbox_new (FALSE, 0);
601 toolbar = gtk_ui_manager_get_widget (window->ui_manager, "/PreviewToolbar");
602 gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
603 gtk_widget_show (toolbar);
605 window->swindow = gtk_scrolled_window_new (NULL, NULL);
606 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (window->swindow),
607 GTK_POLICY_AUTOMATIC,
608 GTK_POLICY_AUTOMATIC);
610 window->view = EV_VIEW (ev_view_new ());
611 g_signal_connect_object (window->view, "focus_in_event",
612 G_CALLBACK (view_focus_changed),
614 g_signal_connect_object (window->view, "focus_out_event",
615 G_CALLBACK (view_focus_changed),
617 ev_view_set_model (window->view, window->model);
618 ev_document_model_set_continuous (window->model, FALSE);
619 ev_view_set_loading (window->view, TRUE);
621 gtk_container_add (GTK_CONTAINER (window->swindow), GTK_WIDGET (window->view));
622 gtk_widget_show (GTK_WIDGET (window->view));
624 gtk_box_pack_start (GTK_BOX (vbox), window->swindow, TRUE, TRUE, 0);
625 gtk_widget_show (window->swindow);
627 gtk_container_add (GTK_CONTAINER (window), vbox);
628 gtk_widget_show (vbox);
635 ev_previewer_window_class_init (EvPreviewerWindowClass *klass)
637 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
639 gobject_class->constructor = ev_previewer_window_constructor;
640 gobject_class->set_property = ev_previewer_window_set_property;
641 gobject_class->dispose = ev_previewer_window_dispose;
643 g_object_class_install_property (gobject_class,
645 g_param_spec_object ("model",
647 "The document model",
648 EV_TYPE_DOCUMENT_MODEL,
650 G_PARAM_CONSTRUCT_ONLY));
655 ev_previewer_window_new (EvDocumentModel *model)
657 return GTK_WIDGET (g_object_new (EV_TYPE_PREVIEWER_WINDOW, "model", model, NULL));
661 ev_previewer_window_set_print_settings (EvPreviewerWindow *window,
662 const gchar *print_settings)
664 if (window->print_settings)
665 g_object_unref (window->print_settings);
666 if (window->print_page_setup)
667 g_object_unref (window->print_page_setup);
668 if (window->print_job_title)
669 g_free (window->print_job_title);
671 if (print_settings && g_file_test (print_settings, G_FILE_TEST_IS_REGULAR)) {
673 GError *error = NULL;
675 key_file = g_key_file_new ();
676 g_key_file_load_from_file (key_file,
678 G_KEY_FILE_KEEP_COMMENTS |
679 G_KEY_FILE_KEEP_TRANSLATIONS,
682 GtkPrintSettings *psettings;
683 GtkPageSetup *psetup;
686 psettings = gtk_print_settings_new_from_key_file (key_file,
689 window->print_settings = psettings ? psettings : gtk_print_settings_new ();
691 psetup = gtk_page_setup_new_from_key_file (key_file,
694 window->print_page_setup = psetup ? psetup : gtk_page_setup_new ();
696 job_name = g_key_file_get_string (key_file,
697 "Print Job", "title",
700 window->print_job_title = job_name;
701 gtk_window_set_title (GTK_WINDOW (window), job_name);
704 window->print_settings = gtk_print_settings_new ();
705 window->print_page_setup = gtk_page_setup_new ();
706 g_error_free (error);
709 g_key_file_free (key_file);
711 window->print_settings = gtk_print_settings_new ();
712 window->print_page_setup = gtk_page_setup_new ();
717 ev_previewer_window_set_source_file (EvPreviewerWindow *window,
718 const gchar *source_file)
720 if (window->source_file)
721 g_free (window->source_file);
722 window->source_file = g_strdup (source_file);