Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ev-document-model.c
Go to the documentation of this file.
1 /* this file is part of evince, a gnome document viewer
2  *
3  * Copyright (C) 2009 Carlos Garcia Campos
4  * Copyright (C) 2005 Red Hat, Inc
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 #include "config.h"
22 
23 #include "ev-document-model.h"
24 #include "ev-view-type-builtins.h"
25 #include "ev-view-marshal.h"
26 
28 {
29  GObject base;
30 
32  gint n_pages;
33 
34  gint page;
35  gint rotation;
36  gdouble scale;
39  guint continuous : 1;
40  guint dual_page : 1;
41  guint dual_page_odd_left : 1;
42  guint fullscreen : 1;
43  guint inverted_colors : 1;
44 
45  gdouble max_scale;
46  gdouble min_scale;
47 };
48 
50 {
51  GObjectClass base_class;
52 
53  /* Signals */
54  void (* page_changed) (EvDocumentModel *model,
55  gint old_page,
56  gint new_page);
57 };
58 
59 enum {
74 };
75 
76 enum
77 {
80 };
81 
82 static guint signals[N_SIGNALS] = { 0 };
83 
84 G_DEFINE_TYPE (EvDocumentModel, ev_document_model, G_TYPE_OBJECT)
85 
86 #define DEFAULT_MIN_SCALE 0.25
87 #define DEFAULT_MAX_SCALE 5.0
88 
89 static void
90 ev_document_model_finalize (GObject *object)
91 {
92  EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
93 
94  if (model->document) {
95  g_object_unref (model->document);
96  model->document = NULL;
97  }
98 
99  G_OBJECT_CLASS (ev_document_model_parent_class)->finalize (object);
100 }
101 
102 static void
104  guint prop_id,
105  const GValue *value,
106  GParamSpec *pspec)
107 {
108  EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
109 
110  switch (prop_id) {
111  case PROP_DOCUMENT:
112  ev_document_model_set_document (model, (EvDocument *)g_value_get_object (value));
113  break;
114  case PROP_PAGE:
115  ev_document_model_set_page (model, g_value_get_int (value));
116  break;
117  case PROP_ROTATION:
118  ev_document_model_set_rotation (model, g_value_get_int (value));
119  break;
121  ev_document_model_set_inverted_colors (model, g_value_get_boolean (value));
122  break;
123  case PROP_SCALE:
124  ev_document_model_set_scale (model, g_value_get_double (value));
125  break;
126  case PROP_MIN_SCALE:
127  ev_document_model_set_min_scale (model, g_value_get_double (value));
128  break;
129  case PROP_MAX_SCALE:
130  ev_document_model_set_max_scale (model, g_value_get_double (value));
131  break;
132  case PROP_SIZING_MODE:
133  ev_document_model_set_sizing_mode (model, g_value_get_enum (value));
134  break;
135  case PROP_CONTINUOUS:
136  ev_document_model_set_continuous (model, g_value_get_boolean (value));
137  break;
138  case PROP_PAGE_LAYOUT:
139  ev_document_model_set_page_layout (model, g_value_get_enum (value));
140  break;
141  case PROP_DUAL_PAGE:
142  ev_document_model_set_dual_page (model, g_value_get_boolean (value));
143  break;
145  ev_document_model_set_dual_page_odd_pages_left (model, g_value_get_boolean (value));
146  break;
147  case PROP_FULLSCREEN:
148  ev_document_model_set_fullscreen (model, g_value_get_boolean (value));
149  break;
150  default:
151  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
152  }
153 }
154 
155 static void
157  guint prop_id,
158  GValue *value,
159  GParamSpec *pspec)
160 {
161  EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
162 
163  switch (prop_id) {
164  case PROP_DOCUMENT:
165  g_value_set_object (value, model->document);
166  break;
167  case PROP_PAGE:
168  g_value_set_int (value, model->page);
169  break;
170  case PROP_ROTATION:
171  g_value_set_int (value, model->rotation);
172  break;
174  g_value_set_boolean (value, model->inverted_colors);
175  break;
176  case PROP_SCALE:
177  g_value_set_double (value, model->scale);
178  break;
179  case PROP_MIN_SCALE:
180  g_value_set_double (value, model->min_scale);
181  break;
182  case PROP_MAX_SCALE:
183  g_value_set_double (value, model->max_scale);
184  break;
185  case PROP_SIZING_MODE:
186  g_value_set_enum (value, model->sizing_mode);
187  break;
188  case PROP_CONTINUOUS:
189  g_value_set_boolean (value, ev_document_model_get_continuous (model));
190  break;
191  case PROP_PAGE_LAYOUT:
192  g_value_set_enum (value, model->page_layout);
193  break;
194  case PROP_DUAL_PAGE:
195  g_value_set_boolean (value, ev_document_model_get_dual_page (model));
196  break;
198  g_value_set_boolean (value, ev_document_model_get_dual_page_odd_pages_left (model));
199  break;
200  case PROP_FULLSCREEN:
201  g_value_set_boolean (value, ev_document_model_get_fullscreen (model));
202  break;
203  default:
204  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
205  }
206 }
207 
208 static void
210 {
211  GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
212 
213  g_object_class->get_property = ev_document_model_get_property;
214  g_object_class->set_property = ev_document_model_set_property;
215  g_object_class->finalize = ev_document_model_finalize;
216 
217  /* Properties */
218  g_object_class_install_property (g_object_class,
220  g_param_spec_object ("document",
221  "Document",
222  "The current document",
224  G_PARAM_READWRITE |
225  G_PARAM_STATIC_STRINGS));
226  g_object_class_install_property (g_object_class,
227  PROP_PAGE,
228  g_param_spec_int ("page",
229  "Page",
230  "Current page",
231  -1, G_MAXINT, -1,
232  G_PARAM_READWRITE |
233  G_PARAM_STATIC_STRINGS));
234  g_object_class_install_property (g_object_class,
236  g_param_spec_int ("rotation",
237  "Rotation",
238  "Current rotation angle",
239  0, 360, 0,
240  G_PARAM_READWRITE |
241  G_PARAM_STATIC_STRINGS));
242  g_object_class_install_property (g_object_class,
244  g_param_spec_boolean ("inverted-colors",
245  "Inverted Colors",
246  "Whether document is displayed with inverted colors",
247  FALSE,
248  G_PARAM_READWRITE |
249  G_PARAM_STATIC_STRINGS));
250  g_object_class_install_property (g_object_class,
251  PROP_SCALE,
252  g_param_spec_double ("scale",
253  "Scale",
254  "Current scale factor",
255  0., G_MAXDOUBLE, 1.,
256  G_PARAM_READWRITE |
257  G_PARAM_STATIC_STRINGS));
258  g_object_class_install_property (g_object_class,
259  PROP_SCALE,
260  g_param_spec_double ("min-scale",
261  "Minimum Scale",
262  "Minium scale factor",
263  0., G_MAXDOUBLE, DEFAULT_MIN_SCALE,
264  G_PARAM_READWRITE |
265  G_PARAM_STATIC_STRINGS));
266  g_object_class_install_property (g_object_class,
267  PROP_SCALE,
268  g_param_spec_double ("max-scale",
269  "Maximum Scale",
270  "Maximum scale factor",
271  0., G_MAXDOUBLE, DEFAULT_MAX_SCALE,
272  G_PARAM_READWRITE |
273  G_PARAM_STATIC_STRINGS));
274  g_object_class_install_property (g_object_class,
276  g_param_spec_enum ("sizing-mode",
277  "Sizing Mode",
278  "Current sizing mode",
279  EV_TYPE_SIZING_MODE,
281  G_PARAM_READWRITE |
282  G_PARAM_STATIC_STRINGS));
283  g_object_class_install_property (g_object_class,
285  g_param_spec_enum ("page-layout",
286  "Page Layout",
287  "Current page layout",
288  EV_TYPE_PAGE_LAYOUT,
290  G_PARAM_READWRITE |
291  G_PARAM_STATIC_STRINGS));
292  g_object_class_install_property (g_object_class,
294  g_param_spec_boolean ("continuous",
295  "Continuous",
296  "Whether document is displayed in continuous mode",
297  TRUE,
298  G_PARAM_READWRITE |
299  G_PARAM_STATIC_STRINGS));
300  g_object_class_install_property (g_object_class,
302  g_param_spec_boolean ("dual-page",
303  "Dual Page",
304  "Whether document is displayed in dual page mode",
305  FALSE,
306  G_PARAM_READWRITE |
307  G_PARAM_STATIC_STRINGS));
308  g_object_class_install_property (g_object_class,
310  g_param_spec_boolean ("dual-odd-left",
311  "Odd Pages Left",
312  "Whether odd pages are displayed on left side in dual mode",
313  FALSE,
314  G_PARAM_READWRITE |
315  G_PARAM_STATIC_STRINGS));
316  g_object_class_install_property (g_object_class,
318  g_param_spec_boolean ("fullscreen",
319  "Fullscreen",
320  "Whether document is displayed in fullscreen mode",
321  FALSE,
322  G_PARAM_READWRITE |
323  G_PARAM_STATIC_STRINGS));
324 
325  /* Signals */
327  g_signal_new ("page-changed",
329  G_SIGNAL_RUN_LAST,
330  G_STRUCT_OFFSET (EvDocumentModelClass, page_changed),
331  NULL, NULL,
332  ev_view_marshal_VOID__INT_INT,
333  G_TYPE_NONE, 2,
334  G_TYPE_INT, G_TYPE_INT);
335 }
336 
337 static void
339 {
340  model->page = -1;
341  model->scale = 1.;
343  model->continuous = TRUE;
344  model->inverted_colors = FALSE;
345  model->min_scale = DEFAULT_MIN_SCALE;
346  model->max_scale = DEFAULT_MAX_SCALE;
347 }
348 
351 {
352  return g_object_new (EV_TYPE_DOCUMENT_MODEL, NULL);
353 }
354 
357 {
358  g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
359 
360  return g_object_new (EV_TYPE_DOCUMENT_MODEL, "document", document, NULL);
361 }
362 
363 void
365  EvDocument *document)
366 {
367  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
368  g_return_if_fail (EV_IS_DOCUMENT (document));
369 
370  if (document == model->document)
371  return;
372 
373  if (model->document)
374  g_object_unref (model->document);
375  model->document = g_object_ref (document);
376 
377  model->n_pages = ev_document_get_n_pages (document);
378  ev_document_model_set_page (model, CLAMP (model->page, 0,
379  model->n_pages - 1));
380 
381  g_object_notify (G_OBJECT (model), "document");
382 }
383 
392 EvDocument *
394 {
395  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), NULL);
396 
397  return model->document;
398 }
399 
400 void
402  gint page)
403 {
404  gint old_page;
405 
406  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
407 
408  if (model->page == page)
409  return;
410  if (page < 0 || (model->document && page >= model->n_pages))
411  return;
412 
413  old_page = model->page;
414  model->page = page;
415  g_signal_emit (model, signals[PAGE_CHANGED], 0, old_page, page);
416 
417  g_object_notify (G_OBJECT (model), "page");
418 }
419 
420 void
422  const gchar *page_label)
423 {
424  gint page;
425 
426  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
427  g_return_if_fail (model->document != NULL);
428 
429  if (ev_document_find_page_by_label (model->document, page_label, &page))
430  ev_document_model_set_page (model, page);
431 }
432 
433 gint
435 {
436  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), -1);
437 
438  return model->page;
439 }
440 
441 void
443  gdouble scale)
444 {
445  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
446 
447  scale = CLAMP (scale,
448  model->sizing_mode == EV_SIZING_FREE ?
449  model->min_scale : 0, model->max_scale);
450 
451  if (scale == model->scale)
452  return;
453 
454  model->scale = scale;
455 
456  g_object_notify (G_OBJECT (model), "scale");
457 }
458 
459 gdouble
461 {
462  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 1.0);
463 
464  return model->scale;
465 }
466 
467 void
469  gdouble max_scale)
470 {
471  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
472 
473  if (max_scale == model->max_scale)
474  return;
475 
476  model->max_scale = max_scale;
477 
478  if (model->scale > max_scale)
479  ev_document_model_set_scale (model, max_scale);
480 
481  g_object_notify (G_OBJECT (model), "max-scale");
482 }
483 
484 gdouble
486 {
487  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 1.0);
488 
489  return model->max_scale;
490 }
491 
492 void
494  gdouble min_scale)
495 {
496  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
497 
498  if (min_scale == model->min_scale)
499  return;
500 
501  model->min_scale = min_scale;
502 
503  if (model->scale < min_scale)
504  ev_document_model_set_scale (model, min_scale);
505 
506  g_object_notify (G_OBJECT (model), "min-scale");
507 }
508 
509 gdouble
511 {
512  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 0.);
513 
514  return model->min_scale;
515 }
516 
517 void
519  EvSizingMode mode)
520 {
521  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
522 
523  if (mode == model->sizing_mode)
524  return;
525 
526  model->sizing_mode = mode;
527 
528  g_object_notify (G_OBJECT (model), "sizing-mode");
529 }
530 
533 {
534  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), EV_SIZING_FIT_WIDTH);
535 
536  return model->sizing_mode;
537 }
538 
539 static void
541  gboolean dual_page)
542 {
543  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
544 
545  dual_page = dual_page != FALSE;
546 
547  if (dual_page == model->dual_page)
548  return;
549 
550  model->dual_page = dual_page;
551 
552  g_object_notify (G_OBJECT (model), "dual-page");
553 }
554 
564 void
566  EvPageLayout layout)
567 {
568  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
569 
570  if (layout == model->page_layout)
571  return;
572 
573  model->page_layout = layout;
574 
575  g_object_notify (G_OBJECT (model), "page-layout");
576 
577  /* set deprecated property as well */
579 }
580 
591 {
592  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), EV_PAGE_LAYOUT_SINGLE);
593 
594  return model->page_layout;
595 }
596 
597 void
599  gint rotation)
600 {
601  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
602 
603  if (rotation >= 360)
604  rotation -= 360;
605  else if (rotation < 0)
606  rotation += 360;
607 
608  if (rotation == model->rotation)
609  return;
610 
611  model->rotation = rotation;
612 
613  g_object_notify (G_OBJECT (model), "rotation");
614 }
615 
616 gint
618 {
619  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 0);
620 
621  return model->rotation;
622 }
623 
624 void
626  gboolean inverted_colors)
627 {
628  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
629 
630  if (inverted_colors == model->inverted_colors)
631  return;
632 
633  model->inverted_colors = inverted_colors;
634 
635  g_object_notify (G_OBJECT (model), "inverted-colors");
636 }
637 
638 gboolean
640 {
641  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), FALSE);
642 
643  return model->inverted_colors;
644 }
645 
646 void
648  gboolean continuous)
649 {
650  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
651 
652  continuous = continuous != FALSE;
653 
654  if (continuous == model->continuous)
655  return;
656 
657  model->continuous = continuous;
658 
659  g_object_notify (G_OBJECT (model), "continuous");
660 }
661 
662 gboolean
664 {
665  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), TRUE);
666 
667  return model->continuous;
668 }
669 
680 void
682  gboolean dual_page)
683 {
684  EvPageLayout layout;
685 
686  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
687 
688  layout = dual_page ? EV_PAGE_LAYOUT_DUAL : EV_PAGE_LAYOUT_SINGLE;
689  ev_document_model_set_page_layout (model, layout);
690 }
691 
701 gboolean
703 {
704  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), FALSE);
705 
706  return model->dual_page;
707 }
708 
709 void
711  gboolean odd_left)
712 {
713  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
714 
715  odd_left = odd_left != FALSE;
716 
717  if (odd_left == model->dual_page_odd_left)
718  return;
719 
720  model->dual_page_odd_left = odd_left;
721 
722  g_object_notify (G_OBJECT (model), "dual-odd-left");
723 }
724 
725 gboolean
727 {
728  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), FALSE);
729 
730  return model->dual_page_odd_left;
731 }
732 
733 void
735  gboolean fullscreen)
736 {
737  g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
738 
739  fullscreen = fullscreen != FALSE;
740 
741  if (fullscreen == model->fullscreen)
742  return;
743 
744  model->fullscreen = fullscreen;
745 
746  g_object_notify (G_OBJECT (model), "fullscreen");
747 }
748 
749 gboolean
751 {
752  g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), FALSE);
753 
754  return model->fullscreen;
755 }