]> www.fi.muni.cz Git - evince.git/blob - libview/ev-document-model.c
[dualscreen] fix crash on ctrl+w and fix control window closing
[evince.git] / libview / ev-document-model.c
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
27 struct _EvDocumentModel
28 {
29         GObject base;
30
31         EvDocument *document;
32         gint n_pages;
33
34         gint page;
35         gint rotation;
36         gdouble scale;
37         EvSizingMode sizing_mode;
38         guint continuous : 1;
39         guint dual_page  : 1;
40         guint fullscreen : 1;
41         guint inverted_colors : 1;
42
43         gdouble max_scale;
44         gdouble min_scale;
45 };
46
47 struct _EvDocumentModelClass
48 {
49         GObjectClass base_class;
50
51         /* Signals  */
52         void (* page_changed) (EvDocumentModel *model,
53                                gint             old_page,
54                                gint             new_page);
55 };
56
57 enum {
58         PROP_0,
59         PROP_DOCUMENT,
60         PROP_PAGE,
61         PROP_ROTATION,
62         PROP_INVERTED_COLORS,
63         PROP_SCALE,
64         PROP_SIZING_MODE,
65         PROP_CONTINUOUS,
66         PROP_DUAL_PAGE,
67         PROP_FULLSCREEN
68 };
69
70 enum
71 {
72         PAGE_CHANGED,
73         N_SIGNALS
74 };
75
76 static guint signals[N_SIGNALS] = { 0 };
77
78 G_DEFINE_TYPE (EvDocumentModel, ev_document_model, G_TYPE_OBJECT)
79
80 static void
81 ev_document_model_finalize (GObject *object)
82 {
83         EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
84
85         if (model->document) {
86                 g_object_unref (model->document);
87                 model->document = NULL;
88         }
89
90         G_OBJECT_CLASS (ev_document_model_parent_class)->finalize (object);
91 }
92
93 static void
94 ev_document_model_set_property (GObject      *object,
95                                 guint         prop_id,
96                                 const GValue *value,
97                                 GParamSpec   *pspec)
98 {
99         EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
100
101         switch (prop_id) {
102         case PROP_DOCUMENT:
103                 ev_document_model_set_document (model, (EvDocument *)g_value_get_object (value));
104                 break;
105         case PROP_PAGE:
106                 ev_document_model_set_page (model, g_value_get_int (value));
107                 break;
108         case PROP_ROTATION:
109                 ev_document_model_set_rotation (model, g_value_get_int (value));
110                 break;
111         case PROP_INVERTED_COLORS:
112                 ev_document_model_set_inverted_colors (model, g_value_get_boolean (value));
113                 break;
114         case PROP_SCALE:
115                 ev_document_model_set_scale (model, g_value_get_double (value));
116                 break;
117         case PROP_SIZING_MODE:
118                 ev_document_model_set_sizing_mode (model, g_value_get_enum (value));
119                 break;
120         case PROP_CONTINUOUS:
121                 ev_document_model_set_continuous (model, g_value_get_boolean (value));
122                 break;
123         case PROP_DUAL_PAGE:
124                 ev_document_model_set_dual_page (model, g_value_get_boolean (value));
125                 break;
126         case PROP_FULLSCREEN:
127                 ev_document_model_set_fullscreen (model, g_value_get_boolean (value));
128                 break;
129         default:
130                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
131         }
132 }
133
134 static void
135 ev_document_model_get_property (GObject    *object,
136                                 guint       prop_id,
137                                 GValue     *value,
138                                 GParamSpec *pspec)
139 {
140         EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
141
142         switch (prop_id) {
143         case PROP_DOCUMENT:
144                 g_value_set_object (value, model->document);
145                 break;
146         case PROP_PAGE:
147                 g_value_set_int (value, model->page);
148                 break;
149         case PROP_ROTATION:
150                 g_value_set_int (value, model->rotation);
151                 break;
152         case PROP_INVERTED_COLORS:
153                 g_value_set_boolean (value, model->inverted_colors);
154                 break;
155         case PROP_SCALE:
156                 g_value_set_double (value, model->scale);
157                 break;
158         case PROP_SIZING_MODE:
159                 g_value_set_enum (value, model->sizing_mode);
160                 break;
161         case PROP_CONTINUOUS:
162                 g_value_set_boolean (value, ev_document_model_get_continuous (model));
163                 break;
164         case PROP_DUAL_PAGE:
165                 g_value_set_boolean (value, ev_document_model_get_dual_page (model));
166                 break;
167         case PROP_FULLSCREEN:
168                 g_value_set_boolean (value, ev_document_model_get_fullscreen (model));
169                 break;
170         default:
171                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
172         }
173 }
174
175 static void
176 ev_document_model_class_init (EvDocumentModelClass *klass)
177 {
178         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
179
180         g_object_class->get_property = ev_document_model_get_property;
181         g_object_class->set_property = ev_document_model_set_property;
182         g_object_class->finalize = ev_document_model_finalize;
183
184         /* Properties */
185         g_object_class_install_property (g_object_class,
186                                          PROP_DOCUMENT,
187                                          g_param_spec_object ("document",
188                                                               "Document",
189                                                               "The current document",
190                                                               EV_TYPE_DOCUMENT,
191                                                               G_PARAM_READWRITE));
192         g_object_class_install_property (g_object_class,
193                                          PROP_PAGE,
194                                          g_param_spec_int ("page",
195                                                            "Page",
196                                                            "Current page",
197                                                            -1, G_MAXINT, -1,
198                                                            G_PARAM_READWRITE));
199         g_object_class_install_property (g_object_class,
200                                          PROP_ROTATION,
201                                          g_param_spec_int ("rotation",
202                                                            "Rotation",
203                                                            "Current rotation angle",
204                                                            0, 360, 0,
205                                                            G_PARAM_READWRITE));
206         g_object_class_install_property (g_object_class,
207                                          PROP_INVERTED_COLORS,
208                                          g_param_spec_boolean ("inverted-colors",
209                                                                "Inverted Colors",
210                                                                "Whether document is displayed with inverted colors",
211                                                                FALSE,
212                                                                G_PARAM_READWRITE));
213         g_object_class_install_property (g_object_class,
214                                          PROP_SCALE,
215                                          g_param_spec_double ("scale",
216                                                               "Scale",
217                                                               "Current scale factor",
218                                                               0., G_MAXDOUBLE, 1.,
219                                                               G_PARAM_READWRITE));
220         g_object_class_install_property (g_object_class,
221                                          PROP_SIZING_MODE,
222                                          g_param_spec_enum ("sizing-mode",
223                                                             "Sizing Mode",
224                                                             "Current sizing mode",
225                                                             EV_TYPE_SIZING_MODE,
226                                                             EV_SIZING_FIT_WIDTH,
227                                                             G_PARAM_READWRITE));
228         g_object_class_install_property (g_object_class,
229                                          PROP_CONTINUOUS,
230                                          g_param_spec_boolean ("continuous",
231                                                                "Continuous",
232                                                                "Whether document is displayed in continuous mode",
233                                                                TRUE,
234                                                                G_PARAM_READWRITE));
235         g_object_class_install_property (g_object_class,
236                                          PROP_DUAL_PAGE,
237                                          g_param_spec_boolean ("dual-page",
238                                                                "Dual Page",
239                                                                "Whether document is displayed in dual page mode",
240                                                                FALSE,
241                                                                G_PARAM_READWRITE));
242         g_object_class_install_property (g_object_class,
243                                          PROP_FULLSCREEN,
244                                          g_param_spec_boolean ("fullscreen",
245                                                                "Fullscreen",
246                                                                "Whether document is displayed in fullscreen mode",
247                                                                FALSE,
248                                                                G_PARAM_READWRITE));
249
250         /* Signals */
251         signals [PAGE_CHANGED] =
252                 g_signal_new ("page-changed",
253                               EV_TYPE_DOCUMENT_MODEL,
254                               G_SIGNAL_RUN_LAST,
255                               G_STRUCT_OFFSET (EvDocumentModelClass, page_changed),
256                               NULL, NULL,
257                               ev_view_marshal_VOID__INT_INT,
258                               G_TYPE_NONE, 2,
259                               G_TYPE_INT, G_TYPE_INT);
260 }
261
262 static void
263 ev_document_model_init (EvDocumentModel *model)
264 {
265         model->page = -1;
266         model->scale = 1.;
267         model->sizing_mode = EV_SIZING_FIT_WIDTH;
268         model->continuous = TRUE;
269         model->inverted_colors = FALSE;
270         model->min_scale = 0.;
271         model->max_scale = G_MAXDOUBLE;
272 }
273
274 EvDocumentModel *
275 ev_document_model_new (void)
276 {
277         return g_object_new (EV_TYPE_DOCUMENT_MODEL, NULL);
278 }
279
280 EvDocumentModel *
281 ev_document_model_new_with_document (EvDocument *document)
282 {
283         g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
284
285         return g_object_new (EV_TYPE_DOCUMENT_MODEL, "document", document, NULL);
286 }
287
288 void
289 ev_document_model_set_document (EvDocumentModel *model,
290                                 EvDocument      *document)
291 {
292         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
293         g_return_if_fail (EV_IS_DOCUMENT (document));
294
295         if (document == model->document)
296                 return;
297
298         if (model->document)
299                 g_object_unref (model->document);
300         model->document = g_object_ref (document);
301
302         model->n_pages = ev_document_get_n_pages (document);
303         ev_document_model_set_page (model, CLAMP (model->page, 0,
304                                                   model->n_pages - 1));
305
306         g_object_notify (G_OBJECT (model), "document");
307 }
308
309 EvDocument *
310 ev_document_model_get_document (EvDocumentModel *model)
311 {
312         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), NULL);
313
314         return model->document;
315 }
316
317 void
318 ev_document_model_set_page (EvDocumentModel *model,
319                             gint             page)
320 {
321         gint old_page;
322
323         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
324
325         if (model->page == page)
326                 return;
327         if (page < 0 || (model->document && page >= model->n_pages))
328                 return;
329
330         old_page = model->page;
331         model->page = page;
332         g_signal_emit (model, signals[PAGE_CHANGED], 0, old_page, page);
333
334         g_object_notify (G_OBJECT (model), "page");
335 }
336
337 void
338 ev_document_model_set_page_by_label (EvDocumentModel *model,
339                                      const gchar     *page_label)
340 {
341         gint page;
342
343         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
344         g_return_if_fail (model->document != NULL);
345
346         if (ev_document_find_page_by_label (model->document, page_label, &page))
347                 ev_document_model_set_page (model, page);
348 }
349
350 gint
351 ev_document_model_get_page (EvDocumentModel *model)
352 {
353         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), -1);
354
355         return model->page;
356 }
357
358 void
359 ev_document_model_set_scale (EvDocumentModel *model,
360                              gdouble          scale)
361 {
362         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
363
364         scale = CLAMP (scale,
365                        model->sizing_mode == EV_SIZING_FREE ?
366                        model->min_scale : 0, model->max_scale);
367
368         if (scale == model->scale)
369                 return;
370
371         model->scale = scale;
372
373         g_object_notify (G_OBJECT (model), "scale");
374 }
375
376 gdouble
377 ev_document_model_get_scale (EvDocumentModel *model)
378 {
379         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 1.0);
380
381         return model->scale;
382 }
383
384 void
385 ev_document_model_set_max_scale (EvDocumentModel *model,
386                                  gdouble          max_scale)
387 {
388         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
389
390         if (max_scale == model->max_scale)
391                 return;
392
393         model->max_scale = max_scale;
394
395         if (model->scale > max_scale)
396                 ev_document_model_set_scale (model, max_scale);
397 }
398
399 gdouble
400 ev_document_model_get_max_scale (EvDocumentModel *model)
401 {
402         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 1.0);
403
404         return model->max_scale;
405 }
406
407 void
408 ev_document_model_set_min_scale (EvDocumentModel *model,
409                                  gdouble          min_scale)
410 {
411         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
412
413         if (min_scale == model->min_scale)
414                 return;
415
416         model->min_scale = min_scale;
417
418         if (model->scale < min_scale)
419                 ev_document_model_set_scale (model, min_scale);
420 }
421
422 gdouble
423 ev_document_model_get_min_scale (EvDocumentModel *model)
424 {
425         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 0.);
426
427         return model->min_scale;
428 }
429
430 void
431 ev_document_model_set_sizing_mode (EvDocumentModel *model,
432                                    EvSizingMode     mode)
433 {
434         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
435
436         if (mode == model->sizing_mode)
437                 return;
438
439         model->sizing_mode = mode;
440
441         g_object_notify (G_OBJECT (model), "sizing-mode");
442 }
443
444 EvSizingMode
445 ev_document_model_get_sizing_mode (EvDocumentModel *model)
446 {
447         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), EV_SIZING_FIT_WIDTH);
448
449         return model->sizing_mode;
450 }
451
452 void
453 ev_document_model_set_rotation (EvDocumentModel *model,
454                                 gint             rotation)
455 {
456         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
457
458         if (rotation >= 360)
459                 rotation -= 360;
460         else if (rotation < 0)
461                 rotation += 360;
462
463         if (rotation == model->rotation)
464                 return;
465
466         model->rotation = rotation;
467
468         g_object_notify (G_OBJECT (model), "rotation");
469 }
470
471 gint
472 ev_document_model_get_rotation (EvDocumentModel *model)
473 {
474         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 0);
475
476         return model->rotation;
477 }
478
479 void
480 ev_document_model_set_inverted_colors (EvDocumentModel *model,
481                                        gboolean         inverted_colors)
482 {
483         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
484
485         if (inverted_colors == model->inverted_colors)
486                 return;
487
488         model->inverted_colors = inverted_colors;
489
490         g_object_notify (G_OBJECT (model), "inverted-colors");
491 }
492
493 gboolean
494 ev_document_model_get_inverted_colors (EvDocumentModel *model)
495 {
496         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), FALSE);
497
498         return model->inverted_colors;
499 }
500
501 void
502 ev_document_model_set_continuous (EvDocumentModel *model,
503                                   gboolean         continuous)
504 {
505         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
506
507         continuous = continuous != FALSE;
508
509         if (continuous == model->continuous)
510                 return;
511
512         model->continuous = continuous;
513
514         g_object_notify (G_OBJECT (model), "continuous");
515 }
516
517 gboolean
518 ev_document_model_get_continuous (EvDocumentModel *model)
519 {
520         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), TRUE);
521
522         return model->continuous;
523 }
524
525 void
526 ev_document_model_set_dual_page (EvDocumentModel *model,
527                                  gboolean         dual_page)
528 {
529         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
530
531         dual_page = dual_page != FALSE;
532
533         if (dual_page == model->dual_page)
534                 return;
535
536         model->dual_page = dual_page;
537
538         g_object_notify (G_OBJECT (model), "dual-page");
539 }
540
541 gboolean
542 ev_document_model_get_dual_page (EvDocumentModel *model)
543 {
544         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), FALSE);
545
546         return model->dual_page;
547 }
548
549 void
550 ev_document_model_set_fullscreen (EvDocumentModel *model,
551                                   gboolean         fullscreen)
552 {
553         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
554
555         fullscreen = fullscreen != FALSE;
556
557         if (fullscreen == model->fullscreen)
558                 return;
559
560         model->fullscreen = fullscreen;
561
562         g_object_notify (G_OBJECT (model), "fullscreen");
563 }
564
565 gboolean
566 ev_document_model_get_fullscreen (EvDocumentModel *model)
567 {
568         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), FALSE);
569
570         return model->fullscreen;
571 }