]> www.fi.muni.cz Git - evince.git/blob - previewer/ev-previewer-window.c
[build] Include git.mk in all Makefiles
[evince.git] / previewer / ev-previewer-window.c
1 /* ev-previewer-window.c: 
2  *  this file is part of evince, a gnome document viewer
3  *
4  * Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
5  *
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.
10  *
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.
15  *
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22
23 #if GTKUNIXPRINT_ENABLED
24 #include <gtk/gtkunixprint.h>
25 #endif
26 #include <glib/gi18n.h>
27 #include <evince-view.h>
28 #include "ev-page-action.h"
29
30 #include "ev-previewer-window.h"
31
32 struct _EvPreviewerWindow {
33         GtkWindow         base_instance;
34
35         EvDocumentModel  *model;
36         EvDocument       *document;
37
38         GtkActionGroup   *action_group;
39         GtkUIManager     *ui_manager;
40
41         GtkWidget        *swindow;
42         EvView           *view;
43         gdouble           dpi;
44
45         /* Printing */
46         GtkPrintSettings *print_settings;
47         GtkPageSetup     *print_page_setup;
48 #if GTKUNIXPRINT_ENABLED
49         GtkPrinter       *printer;
50 #endif
51         gchar            *print_job_title;
52         gchar            *source_file;
53 };
54
55 struct _EvPreviewerWindowClass {
56         GtkWindowClass base_class;
57 };
58
59 enum {
60         PROP_0,
61         PROP_MODEL
62 };
63
64 #define MIN_SCALE 0.05409
65 #define MAX_SCALE 4.0
66
67 G_DEFINE_TYPE (EvPreviewerWindow, ev_previewer_window, GTK_TYPE_WINDOW)
68
69 static gdouble
70 get_screen_dpi (GtkWindow *window)
71 {
72         GdkScreen *screen;
73         gdouble    xdpi, ydpi;
74
75         screen = gtk_window_get_screen (window);
76
77         xdpi = 25.4 * gdk_screen_get_width (screen) / gdk_screen_get_width_mm (screen);
78         ydpi = 25.4 * gdk_screen_get_height (screen) / gdk_screen_get_height_mm (screen);
79
80         return (xdpi + ydpi) / 2.0;
81 }
82
83 #if GTKUNIXPRINT_ENABLED
84 static void
85 ev_previewer_window_error_dialog_run (EvPreviewerWindow *window,
86                                       GError            *error)
87 {
88         GtkWidget *dialog;
89
90         dialog = gtk_message_dialog_new (GTK_WINDOW (window),
91                                          GTK_DIALOG_MODAL |
92                                          GTK_DIALOG_DESTROY_WITH_PARENT,
93                                          GTK_MESSAGE_ERROR,
94                                          GTK_BUTTONS_CLOSE,
95                                          "%s", _("Failed to print document"));
96         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
97                                                   "%s", error->message);
98         gtk_dialog_run (GTK_DIALOG (dialog));
99         gtk_widget_destroy (dialog);
100 }
101 #endif
102
103 static void
104 ev_previewer_window_previous_page (GtkAction         *action,
105                                    EvPreviewerWindow *window)
106 {
107         ev_view_previous_page (window->view);
108 }
109
110 static void
111 ev_previewer_window_next_page (GtkAction         *action,
112                                EvPreviewerWindow *window)
113 {
114         ev_view_next_page (window->view);
115 }
116
117 static void
118 ev_previewer_window_zoom_in (GtkAction         *action,
119                              EvPreviewerWindow *window)
120 {
121         ev_document_model_set_sizing_mode (window->model, EV_SIZING_FREE);
122         ev_view_zoom_in (window->view);
123 }
124
125 static void
126 ev_previewer_window_zoom_out (GtkAction         *action,
127                               EvPreviewerWindow *window)
128 {
129         ev_document_model_set_sizing_mode (window->model, EV_SIZING_FREE);
130         ev_view_zoom_out (window->view);
131 }
132
133 static void
134 ev_previewer_window_zoom_best_fit (GtkToggleAction   *action,
135                                    EvPreviewerWindow *window)
136 {
137         ev_document_model_set_sizing_mode (window->model,
138                                            gtk_toggle_action_get_active (action) ?
139                                            EV_SIZING_BEST_FIT : EV_SIZING_FREE);
140 }
141
142 static void
143 ev_previewer_window_zoom_page_width (GtkToggleAction   *action,
144                                      EvPreviewerWindow *window)
145 {
146         ev_document_model_set_sizing_mode (window->model,
147                                            gtk_toggle_action_get_active (action) ?
148                                            EV_SIZING_FIT_WIDTH : EV_SIZING_FREE);
149 }
150
151 static void
152 ev_previewer_window_action_page_activated (GtkAction         *action,
153                                            EvLink            *link,
154                                            EvPreviewerWindow *window)
155 {
156         ev_view_handle_link (window->view, link);
157         gtk_widget_grab_focus (GTK_WIDGET (window->view));
158 }
159
160 #if GTKUNIXPRINT_ENABLED
161 static void
162 ev_previewer_window_print_finished (GtkPrintJob       *print_job,
163                                     EvPreviewerWindow *window,
164                                     GError            *error)
165 {
166         if (error) {
167                 ev_previewer_window_error_dialog_run (window, error);
168         }
169
170         g_object_unref (print_job);
171         gtk_widget_destroy (GTK_WIDGET (window));
172 }
173
174 static void
175 ev_previewer_window_do_print (EvPreviewerWindow *window)
176 {
177         GtkPrintJob *job;
178         GError      *error = NULL;
179
180         job = gtk_print_job_new (window->print_job_title ?
181                                  window->print_job_title :
182                                  window->source_file,
183                                  window->printer,
184                                  window->print_settings,
185                                  window->print_page_setup);
186         if (gtk_print_job_set_source_file (job, window->source_file, &error)) {
187                 gtk_print_job_send (job,
188                                     (GtkPrintJobCompleteFunc)ev_previewer_window_print_finished,
189                                     window, NULL);
190         } else {
191                 ev_previewer_window_error_dialog_run (window, error);
192                 g_error_free (error);
193         }
194
195         gtk_widget_hide (GTK_WIDGET (window));
196 }
197
198 static void
199 ev_previewer_window_enumerate_finished (EvPreviewerWindow *window)
200 {
201         if (window->printer) {
202                 ev_previewer_window_do_print (window);
203         } else {
204                 GError *error = NULL;
205
206                 g_set_error (&error,
207                              GTK_PRINT_ERROR,
208                              GTK_PRINT_ERROR_GENERAL,
209                              _("The selected printer '%s' could not be found"),
210                              gtk_print_settings_get_printer (window->print_settings));
211                                      
212                 ev_previewer_window_error_dialog_run (window, error);
213                 g_error_free (error);
214         }
215 }
216
217 static gboolean
218 ev_previewer_window_enumerate_printers (GtkPrinter        *printer,
219                                         EvPreviewerWindow *window)
220 {
221         const gchar *printer_name;
222
223         printer_name = gtk_print_settings_get_printer (window->print_settings);
224         if ((printer_name
225              && strcmp (printer_name, gtk_printer_get_name (printer)) == 0) ||
226             (!printer_name && gtk_printer_is_default (printer))) {
227                 if (window->printer)
228                         g_object_unref (window->printer);
229                 window->printer = g_object_ref (printer);
230
231                 return TRUE; /* we're done */
232         }
233
234         return FALSE; /* continue the enumeration */
235 }
236
237 static void
238 ev_previewer_window_print (GtkAction         *action,
239                            EvPreviewerWindow *window)
240 {
241         if (!window->print_settings)
242                 window->print_settings = gtk_print_settings_new ();
243         if (!window->print_page_setup)
244                 window->print_page_setup = gtk_page_setup_new ();
245         gtk_enumerate_printers ((GtkPrinterFunc)ev_previewer_window_enumerate_printers,
246                                 window,
247                                 (GDestroyNotify)ev_previewer_window_enumerate_finished,
248                                 FALSE);
249 }
250 #endif
251
252 static const GtkActionEntry action_entries[] = {
253         { "GoPreviousPage", GTK_STOCK_GO_UP, N_("_Previous Page"), "<control>Page_Up",
254           N_("Go to the previous page"),
255           G_CALLBACK (ev_previewer_window_previous_page) },
256         { "GoNextPage", GTK_STOCK_GO_DOWN, N_("_Next Page"), "<control>Page_Down",
257           N_("Go to the next page"),
258           G_CALLBACK (ev_previewer_window_next_page) },
259         { "ViewZoomIn", GTK_STOCK_ZOOM_IN, NULL, "<control>plus",
260           N_("Enlarge the document"),
261           G_CALLBACK (ev_previewer_window_zoom_in) },
262         { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus",
263           N_("Shrink the document"),
264           G_CALLBACK (ev_previewer_window_zoom_out) },
265 #if GTKUNIXPRINT_ENABLED
266         { "PreviewPrint", GTK_STOCK_PRINT, N_("Print"), NULL,
267           N_("Print this document"),
268           G_CALLBACK (ev_previewer_window_print) }
269 #endif
270 };
271
272 static const GtkToggleActionEntry toggle_action_entries[] = {
273         { "ViewBestFit", EV_STOCK_ZOOM_PAGE, N_("_Best Fit"), NULL,
274           N_("Make the current document fill the window"),
275           G_CALLBACK (ev_previewer_window_zoom_best_fit) },
276         { "ViewPageWidth", EV_STOCK_ZOOM_WIDTH, N_("Fit Page _Width"), NULL,
277           N_("Make the current document fill the window width"),
278           G_CALLBACK (ev_previewer_window_zoom_page_width) }
279 };
280
281 static void
282 view_sizing_mode_changed (EvDocumentModel   *model,
283                           GParamSpec        *pspec,
284                           EvPreviewerWindow *window)
285 {
286         EvSizingMode sizing_mode = ev_document_model_get_sizing_mode (model);
287         GtkAction   *action;
288
289         action = gtk_action_group_get_action (window->action_group, "ViewBestFit");
290         g_signal_handlers_block_by_func (action,
291                                          G_CALLBACK (ev_previewer_window_zoom_best_fit),
292                                          window);
293         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
294                                       sizing_mode == EV_SIZING_BEST_FIT);
295         g_signal_handlers_unblock_by_func (action,
296                                            G_CALLBACK (ev_previewer_window_zoom_best_fit),
297                                            window);
298
299         action = gtk_action_group_get_action (window->action_group, "ViewPageWidth");
300         g_signal_handlers_block_by_func (action,
301                                          G_CALLBACK (ev_previewer_window_zoom_page_width),
302                                          window);
303         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
304                                       sizing_mode == EV_SIZING_FIT_WIDTH);
305         g_signal_handlers_unblock_by_func (action,
306                                            G_CALLBACK (ev_previewer_window_zoom_page_width),
307                                            window);
308 }
309
310 static void
311 ev_previewer_window_set_document (EvPreviewerWindow *window,
312                                   GParamSpec        *pspec,
313                                   EvDocumentModel   *model)
314 {
315         EvDocument *document = ev_document_model_get_document (model);
316
317         window->document = g_object_ref (document);
318
319         g_signal_connect (model, "notify::sizing-mode",
320                           G_CALLBACK (view_sizing_mode_changed),
321                           window);
322         ev_view_set_loading (window->view, FALSE);
323         gtk_action_group_set_sensitive (window->action_group, TRUE);
324 }
325
326 static void
327 ev_previewer_window_dispose (GObject *object)
328 {
329         EvPreviewerWindow *window = EV_PREVIEWER_WINDOW (object);
330
331         if (window->model) {
332                 g_object_unref (window->model);
333                 window->model = NULL;
334         }
335
336         if (window->document) {
337                 g_object_unref (window->document);
338                 window->document = NULL;
339         }
340
341         if (window->action_group) {
342                 g_object_unref (window->action_group);
343                 window->action_group = NULL;
344         }
345
346         if (window->ui_manager) {
347                 g_object_unref (window->ui_manager);
348                 window->ui_manager = NULL;
349         }
350
351         if (window->print_settings) {
352                 g_object_unref (window->print_settings);
353                 window->print_settings = NULL;
354         }
355
356         if (window->print_page_setup) {
357                 g_object_unref (window->print_page_setup);
358                 window->print_page_setup = NULL;
359         }
360
361 #if GTKUNIXPRINT_ENABLED
362         if (window->printer) {
363                 g_object_unref (window->printer);
364                 window->printer = NULL;
365         }
366 #endif
367
368         if (window->print_job_title) {
369                 g_free (window->print_job_title);
370                 window->print_job_title = NULL;
371         }
372
373         if (window->source_file) {
374                 g_free (window->source_file);
375                 window->source_file = NULL;
376         }
377
378         G_OBJECT_CLASS (ev_previewer_window_parent_class)->dispose (object);
379 }
380
381 static gchar*
382 data_dir (void)
383 {
384         gchar *datadir;
385 #ifdef G_OS_WIN32
386         gchar *dir;
387
388         dir = g_win32_get_package_installation_directory_of_module (NULL);
389         datadir = g_build_filename (dir, "share", "evince", NULL);
390         g_free (dir);
391 #else
392         datadir = g_strdup (DATADIR);
393 #endif
394
395        return datadir;
396 }
397
398 static void
399 ev_previewer_window_init (EvPreviewerWindow *window)
400 {
401         gtk_window_set_default_size (GTK_WINDOW (window), 600, 600);
402 }
403
404 static void
405 ev_previewer_window_set_property (GObject      *object,
406                                   guint         prop_id,
407                                   const GValue *value,
408                                   GParamSpec   *pspec)
409 {
410         EvPreviewerWindow *window = EV_PREVIEWER_WINDOW (object);
411
412         switch (prop_id) {
413         case PROP_MODEL:
414                 window->model = g_value_dup_object (value);
415                 break;
416         default:
417                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
418         }
419 }
420
421 static GObject *
422 ev_previewer_window_constructor (GType                  type,
423                                  guint                  n_construct_properties,
424                                  GObjectConstructParam *construct_params)
425 {
426         GObject           *object;
427         EvPreviewerWindow *window;
428         GtkWidget         *vbox;
429         GtkWidget         *toolbar;
430         GtkAction         *action;
431         GError            *error = NULL;
432         gchar             *datadir, *ui_path;
433         gdouble            dpi;
434
435         g_print ("DBG: constructor\n");
436
437         object = G_OBJECT_CLASS (ev_previewer_window_parent_class)->constructor (type,
438                                                                                  n_construct_properties,
439                                                                                  construct_params);
440         window = EV_PREVIEWER_WINDOW (object);
441
442         dpi = get_screen_dpi (GTK_WINDOW (window));
443         ev_document_model_set_min_scale (window->model, MIN_SCALE * dpi / 72.0);
444         ev_document_model_set_max_scale (window->model, MAX_SCALE * dpi / 72.0);
445         ev_document_model_set_sizing_mode (window->model, EV_SIZING_FIT_WIDTH);
446         g_signal_connect_swapped (window->model, "notify::document",
447                                   G_CALLBACK (ev_previewer_window_set_document),
448                                   window);
449
450         window->action_group = gtk_action_group_new ("PreviewerActions");
451         gtk_action_group_set_translation_domain (window->action_group, NULL);
452         gtk_action_group_add_actions (window->action_group, action_entries,
453                                       G_N_ELEMENTS (action_entries),
454                                       window);
455         gtk_action_group_add_toggle_actions (window->action_group, toggle_action_entries,
456                                              G_N_ELEMENTS (toggle_action_entries),
457                                              window);
458         gtk_action_group_set_sensitive (window->action_group, FALSE);
459
460         action = g_object_new (EV_TYPE_PAGE_ACTION,
461                                "name", "PageSelector",
462                                "label", _("Page"),
463                                "tooltip", _("Select Page"),
464                                "icon_name", "text-x-generic",
465                                "visible_overflown", FALSE,
466                                NULL);
467         ev_page_action_set_model (EV_PAGE_ACTION (action), window->model);
468         g_signal_connect (action, "activate_link",
469                           G_CALLBACK (ev_previewer_window_action_page_activated),
470                           window);
471         gtk_action_group_add_action (window->action_group, action);
472         g_object_unref (action);
473
474         window->ui_manager = gtk_ui_manager_new ();
475         gtk_ui_manager_insert_action_group (window->ui_manager,
476                                             window->action_group, 0);
477         gtk_window_add_accel_group (GTK_WINDOW (window),
478                                     gtk_ui_manager_get_accel_group (window->ui_manager));
479         datadir = data_dir ();
480         ui_path = g_build_filename (datadir, "evince-previewer-ui.xml", NULL);
481         if (!gtk_ui_manager_add_ui_from_file (window->ui_manager, ui_path, &error)) {
482                 g_warning ("Failed to load ui from evince-previewer-ui.xml: %s", error->message);
483                 g_error_free (error);
484         }
485         g_free (ui_path);
486         g_free (datadir);
487
488         view_sizing_mode_changed (window->model, NULL, window);
489
490         vbox = gtk_vbox_new (FALSE, 0);
491
492         toolbar = gtk_ui_manager_get_widget (window->ui_manager, "/PreviewToolbar");
493         gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
494         gtk_widget_show (toolbar);
495
496         window->swindow = gtk_scrolled_window_new (NULL, NULL);
497         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (window->swindow),
498                                         GTK_POLICY_AUTOMATIC,
499                                         GTK_POLICY_AUTOMATIC);
500
501         window->view = EV_VIEW (ev_view_new ());
502         ev_view_set_model (window->view, window->model);
503         ev_view_set_continuous (window->view, FALSE);
504         ev_view_set_loading (window->view, TRUE);
505
506         gtk_container_add (GTK_CONTAINER (window->swindow), GTK_WIDGET (window->view));
507         gtk_widget_show (GTK_WIDGET (window->view));
508
509         gtk_box_pack_start (GTK_BOX (vbox), window->swindow, TRUE, TRUE, 0);
510         gtk_widget_show (window->swindow);
511
512         gtk_container_add (GTK_CONTAINER (window), vbox);
513         gtk_widget_show (vbox);
514
515         return object;
516 }
517
518
519 static void
520 ev_previewer_window_class_init (EvPreviewerWindowClass *klass)
521 {
522         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
523
524         gobject_class->constructor = ev_previewer_window_constructor;
525         gobject_class->set_property = ev_previewer_window_set_property;
526         gobject_class->dispose = ev_previewer_window_dispose;
527
528         g_object_class_install_property (gobject_class,
529                                          PROP_MODEL,
530                                          g_param_spec_object ("model",
531                                                               "Model",
532                                                               "The document model",
533                                                               EV_TYPE_DOCUMENT_MODEL,
534                                                               G_PARAM_WRITABLE |
535                                                               G_PARAM_CONSTRUCT_ONLY));
536 }
537
538 /* Public methods */
539 GtkWidget *
540 ev_previewer_window_new (EvDocumentModel *model)
541 {
542         return GTK_WIDGET (g_object_new (EV_TYPE_PREVIEWER_WINDOW, "model", model, NULL));
543 }
544
545 void
546 ev_previewer_window_set_print_settings (EvPreviewerWindow *window,
547                                         const gchar       *print_settings)
548 {
549         if (window->print_settings)
550                 g_object_unref (window->print_settings);
551         if (window->print_page_setup)
552                 g_object_unref (window->print_page_setup);
553         if (window->print_job_title)
554                 g_free (window->print_job_title);
555
556         if (print_settings && g_file_test (print_settings, G_FILE_TEST_IS_REGULAR)) {
557                 GKeyFile *key_file;
558                 GError   *error = NULL;
559
560                 key_file = g_key_file_new ();
561                 g_key_file_load_from_file (key_file,
562                                            print_settings,
563                                            G_KEY_FILE_KEEP_COMMENTS |
564                                            G_KEY_FILE_KEEP_TRANSLATIONS,
565                                            &error);
566                 if (!error) {
567                         GtkPrintSettings *psettings;
568                         GtkPageSetup     *psetup;
569                         gchar            *job_name;
570
571                         psettings = gtk_print_settings_new_from_key_file (key_file,
572                                                                           "Print Settings",
573                                                                           NULL);
574                         window->print_settings = psettings ? psettings : gtk_print_settings_new ();
575
576                         psetup = gtk_page_setup_new_from_key_file (key_file,
577                                                                    "Page Setup",
578                                                                    NULL);
579                         window->print_page_setup = psetup ? psetup : gtk_page_setup_new ();
580
581                         job_name = g_key_file_get_string (key_file,
582                                                           "Print Job", "title",
583                                                           NULL);
584                         if (job_name) {
585                                 window->print_job_title = job_name;
586                                 gtk_window_set_title (GTK_WINDOW (window), job_name);
587                         }
588                 } else {
589                         window->print_settings = gtk_print_settings_new ();
590                         window->print_page_setup = gtk_page_setup_new ();
591                         g_error_free (error);
592                 }
593
594                 g_key_file_free (key_file);
595         } else {
596                 window->print_settings = gtk_print_settings_new ();
597                 window->print_page_setup = gtk_page_setup_new ();
598         }
599 }
600
601 void
602 ev_previewer_window_set_source_file (EvPreviewerWindow *window,
603                                      const gchar       *source_file)
604 {
605         if (window->source_file)
606                 g_free (window->source_file);
607         window->source_file = g_strdup (source_file);
608 }