2 * this file is part of evince, a gnome document viewer
4 * Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
5 * Copyright (C) 2007 IƱigo Martinez <inigomartinez@gmail.com>
7 * Evince is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * Evince is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include "ev-annotation.h"
25 #include "ev-document-misc.h"
26 #include "ev-document-type-builtins.h"
28 struct _EvAnnotation {
31 EvAnnotationType type;
41 struct _EvAnnotationClass {
42 GObjectClass parent_class;
45 struct _EvAnnotationMarkupInterface {
46 GTypeInterface base_iface;
49 struct _EvAnnotationText {
53 EvAnnotationTextIcon icon;
56 struct _EvAnnotationTextClass {
57 EvAnnotationClass parent_class;
60 struct _EvAnnotationAttachment {
63 EvAttachment *attachment;
66 struct _EvAnnotationAttachmentClass {
67 EvAnnotationClass parent_class;
70 static void ev_annotation_markup_default_init (EvAnnotationMarkupInterface *iface);
71 static void ev_annotation_text_markup_iface_init (EvAnnotationMarkupInterface *iface);
72 static void ev_annotation_attachment_markup_iface_init (EvAnnotationMarkupInterface *iface);
84 /* EvAnnotationMarkup */
89 PROP_MARKUP_HAS_POPUP,
90 PROP_MARKUP_RECTANGLE,
91 PROP_MARKUP_POPUP_IS_OPEN
94 /* EvAnnotationText */
101 /* EvAnnotationAttachment */
104 PROP_ATTACHMENT_ATTACHMENT
107 G_DEFINE_ABSTRACT_TYPE (EvAnnotation, ev_annotation, G_TYPE_OBJECT)
108 G_DEFINE_INTERFACE (EvAnnotationMarkup, ev_annotation_markup, EV_TYPE_ANNOTATION)
109 G_DEFINE_TYPE_WITH_CODE (EvAnnotationText, ev_annotation_text, EV_TYPE_ANNOTATION,
111 G_IMPLEMENT_INTERFACE (EV_TYPE_ANNOTATION_MARKUP,
112 ev_annotation_text_markup_iface_init);
114 G_DEFINE_TYPE_WITH_CODE (EvAnnotationAttachment, ev_annotation_attachment, EV_TYPE_ANNOTATION,
116 G_IMPLEMENT_INTERFACE (EV_TYPE_ANNOTATION_MARKUP,
117 ev_annotation_attachment_markup_iface_init);
122 ev_annotation_finalize (GObject *object)
124 EvAnnotation *annot = EV_ANNOTATION (object);
127 g_object_unref (annot->page);
131 if (annot->contents) {
132 g_free (annot->contents);
133 annot->contents = NULL;
137 g_free (annot->name);
141 if (annot->modified) {
142 g_free (annot->modified);
143 annot->modified = NULL;
146 G_OBJECT_CLASS (ev_annotation_parent_class)->finalize (object);
150 ev_annotation_init (EvAnnotation *annot)
152 annot->type = EV_ANNOTATION_TYPE_UNKNOWN;
156 ev_annotation_set_property (GObject *object,
161 EvAnnotation *annot = EV_ANNOTATION (object);
164 case PROP_ANNOT_PAGE:
165 annot->page = g_value_dup_object (value);
167 case PROP_ANNOT_CONTENTS:
168 ev_annotation_set_contents (annot, g_value_get_string (value));
170 case PROP_ANNOT_NAME:
171 ev_annotation_set_name (annot, g_value_get_string (value));
173 case PROP_ANNOT_MODIFIED:
174 ev_annotation_set_modified (annot, g_value_get_string (value));
176 case PROP_ANNOT_COLOR:
177 ev_annotation_set_color (annot, g_value_get_pointer (value));
180 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
185 ev_annotation_get_property (GObject *object,
190 EvAnnotation *annot = EV_ANNOTATION (object);
193 case PROP_ANNOT_CONTENTS:
194 g_value_set_string (value, ev_annotation_get_contents (annot));
196 case PROP_ANNOT_NAME:
197 g_value_set_string (value, ev_annotation_get_name (annot));
199 case PROP_ANNOT_MODIFIED:
200 g_value_set_string (value, ev_annotation_get_modified (annot));
202 case PROP_ANNOT_COLOR:
203 g_value_set_pointer (value, &annot->color);
206 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
211 ev_annotation_class_init (EvAnnotationClass *klass)
213 GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
215 g_object_class->finalize = ev_annotation_finalize;
216 g_object_class->set_property = ev_annotation_set_property;
217 g_object_class->get_property = ev_annotation_get_property;
219 g_object_class_install_property (g_object_class,
221 g_param_spec_object ("page",
223 "The page wehere the annotation is",
225 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
226 g_object_class_install_property (g_object_class,
228 g_param_spec_string ("contents",
230 "The annotation contents",
233 g_object_class_install_property (g_object_class,
235 g_param_spec_string ("name",
237 "The annotation unique name",
240 g_object_class_install_property (g_object_class,
242 g_param_spec_string ("modified",
244 "Last modified date as string",
247 g_object_class_install_property (g_object_class,
249 g_param_spec_pointer ("color",
251 "The annotation color",
256 ev_annotation_get_annotation_type (EvAnnotation *annot)
258 g_return_val_if_fail (EV_IS_ANNOTATION (annot), 0);
264 ev_annotation_get_page (EvAnnotation *annot)
266 g_return_val_if_fail (EV_IS_ANNOTATION (annot), NULL);
272 ev_annotation_get_page_index (EvAnnotation *annot)
274 g_return_val_if_fail (EV_IS_ANNOTATION (annot), 0);
276 return annot->page->index;
280 ev_annotation_equal (EvAnnotation *annot,
283 g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
284 g_return_val_if_fail (EV_IS_ANNOTATION (other), FALSE);
286 return (annot == other || g_strcmp0 (annot->name, other->name) == 0);
290 ev_annotation_get_contents (EvAnnotation *annot)
292 g_return_val_if_fail (EV_IS_ANNOTATION (annot), NULL);
294 return annot->contents;
298 ev_annotation_set_contents (EvAnnotation *annot,
299 const gchar *contents)
301 g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
303 if (g_strcmp0 (annot->contents, contents) == 0)
307 g_free (annot->contents);
308 annot->contents = contents ? g_strdup (contents) : NULL;
310 g_object_notify (G_OBJECT (annot), "contents");
316 ev_annotation_get_name (EvAnnotation *annot)
318 g_return_val_if_fail (EV_IS_ANNOTATION (annot), NULL);
324 ev_annotation_set_name (EvAnnotation *annot,
327 g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
329 if (g_strcmp0 (annot->name, name) == 0)
333 g_free (annot->name);
334 annot->name = name ? g_strdup (name) : NULL;
336 g_object_notify (G_OBJECT (annot), "name");
342 ev_annotation_get_modified (EvAnnotation *annot)
344 g_return_val_if_fail (EV_IS_ANNOTATION (annot), NULL);
346 return annot->modified;
350 ev_annotation_set_modified (EvAnnotation *annot,
351 const gchar *modified)
353 g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
355 if (g_strcmp0 (annot->modified, modified) == 0)
359 g_free (annot->modified);
360 annot->modified = modified ? g_strdup (modified) : NULL;
362 g_object_notify (G_OBJECT (annot), "modified");
368 ev_annotation_set_modified_from_time (EvAnnotation *annot,
373 g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
375 modified = ev_document_misc_format_date (utime);
377 if (g_strcmp0 (annot->modified, modified) == 0) {
383 g_free (annot->modified);
384 annot->modified = modified;
386 g_object_notify (G_OBJECT (annot), "modified");
392 ev_annotation_get_color (EvAnnotation *annot,
395 g_return_if_fail (EV_IS_ANNOTATION (annot));
398 *color = annot->color;
402 ev_annotation_set_color (EvAnnotation *annot,
403 const GdkColor *color)
405 g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
407 if (annot->color.red == color->red &&
408 annot->color.green == color->green &&
409 annot->color.blue == color->blue)
413 annot->color = *color;
415 g_object_notify (G_OBJECT (annot), "color");
420 /* EvAnnotationMarkup */
425 gboolean popup_is_open;
426 EvRectangle rectangle;
427 } EvAnnotationMarkupProps;
430 ev_annotation_markup_default_init (EvAnnotationMarkupInterface *iface)
432 static gboolean initialized = FALSE;
435 g_object_interface_install_property (iface,
436 g_param_spec_string ("label",
438 "Label of the markup annotation",
441 g_object_interface_install_property (iface,
442 g_param_spec_double ("opacity",
444 "Opacity of the markup annotation",
449 g_object_interface_install_property (iface,
450 g_param_spec_boolean ("has_popup",
452 "Whether the markup annotation has "
453 "a popup window associated",
456 g_object_interface_install_property (iface,
457 g_param_spec_boxed ("rectangle",
459 "The Rectangle of the popup associated "
460 "to the markup annotation",
463 g_object_interface_install_property (iface,
464 g_param_spec_boolean ("popup_is_open",
466 "Whether the popup associated to "
467 "the markup annotation is open",
475 ev_annotation_markup_props_free (EvAnnotationMarkupProps *props)
477 g_free (props->label);
478 g_slice_free (EvAnnotationMarkupProps, props);
481 static EvAnnotationMarkupProps *
482 ev_annotation_markup_get_properties (EvAnnotationMarkup *markup)
484 EvAnnotationMarkupProps *props;
485 static GQuark props_key = 0;
488 props_key = g_quark_from_static_string ("ev-annotation-markup-props");
490 props = g_object_get_qdata (G_OBJECT (markup), props_key);
492 props = g_slice_new0 (EvAnnotationMarkupProps);
493 g_object_set_qdata_full (G_OBJECT (markup),
495 (GDestroyNotify) ev_annotation_markup_props_free);
502 ev_annotation_markup_set_property (GObject *object,
507 EvAnnotationMarkup *markup = EV_ANNOTATION_MARKUP (object);
510 case PROP_MARKUP_LABEL:
511 ev_annotation_markup_set_label (markup, g_value_get_string (value));
513 case PROP_MARKUP_OPACITY:
514 ev_annotation_markup_set_opacity (markup, g_value_get_double (value));
516 case PROP_MARKUP_HAS_POPUP:
517 ev_annotation_markup_set_has_popup (markup, g_value_get_boolean (value));
519 case PROP_MARKUP_RECTANGLE:
520 ev_annotation_markup_set_rectangle (markup, g_value_get_boxed (value));
522 case PROP_MARKUP_POPUP_IS_OPEN:
523 ev_annotation_markup_set_popup_is_open (markup, g_value_get_boolean (value));
526 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
531 ev_annotation_markup_get_property (GObject *object,
536 EvAnnotationMarkupProps *props;
538 props = ev_annotation_markup_get_properties (EV_ANNOTATION_MARKUP (object));
541 case PROP_MARKUP_LABEL:
542 g_value_set_string (value, props->label);
544 case PROP_MARKUP_OPACITY:
545 g_value_set_double (value, props->opacity);
547 case PROP_MARKUP_HAS_POPUP:
548 g_value_set_boolean (value, props->has_popup);
550 case PROP_MARKUP_RECTANGLE:
551 g_value_set_boxed (value, &props->rectangle);
553 case PROP_MARKUP_POPUP_IS_OPEN:
554 g_value_set_boolean (value, props->popup_is_open);
557 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
562 ev_annotation_markup_class_install_properties (GObjectClass *klass)
564 klass->set_property = ev_annotation_markup_set_property;
565 klass->get_property = ev_annotation_markup_get_property;
567 g_object_class_override_property (klass, PROP_MARKUP_LABEL, "label");
568 g_object_class_override_property (klass, PROP_MARKUP_OPACITY, "opacity");
569 g_object_class_override_property (klass, PROP_MARKUP_HAS_POPUP, "has_popup");
570 g_object_class_override_property (klass, PROP_MARKUP_RECTANGLE, "rectangle");
571 g_object_class_override_property (klass, PROP_MARKUP_POPUP_IS_OPEN, "popup_is_open");
575 ev_annotation_markup_get_label (EvAnnotationMarkup *markup)
577 EvAnnotationMarkupProps *props;
579 g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), NULL);
581 props = ev_annotation_markup_get_properties (markup);
586 ev_annotation_markup_set_label (EvAnnotationMarkup *markup,
589 EvAnnotationMarkupProps *props;
591 g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
592 g_return_val_if_fail (label != NULL, FALSE);
594 props = ev_annotation_markup_get_properties (markup);
595 if (g_strcmp0 (props->label, label) == 0)
599 g_free (props->label);
600 props->label = g_strdup (label);
602 g_object_notify (G_OBJECT (markup), "label");
608 ev_annotation_markup_get_opacity (EvAnnotationMarkup *markup)
610 EvAnnotationMarkupProps *props;
612 g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), 1.0);
614 props = ev_annotation_markup_get_properties (markup);
615 return props->opacity;
619 ev_annotation_markup_set_opacity (EvAnnotationMarkup *markup,
622 EvAnnotationMarkupProps *props;
624 g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
626 props = ev_annotation_markup_get_properties (markup);
627 if (props->opacity == opacity)
630 props->opacity = opacity;
632 g_object_notify (G_OBJECT (markup), "opacity");
638 ev_annotation_markup_has_popup (EvAnnotationMarkup *markup)
640 EvAnnotationMarkupProps *props;
642 g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
644 props = ev_annotation_markup_get_properties (markup);
645 return props->has_popup;
649 ev_annotation_markup_set_has_popup (EvAnnotationMarkup *markup,
652 EvAnnotationMarkupProps *props;
654 g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
656 props = ev_annotation_markup_get_properties (markup);
657 if (props->has_popup == has_popup)
660 props->has_popup = has_popup;
662 g_object_notify (G_OBJECT (markup), "has-popup");
668 ev_annotation_markup_get_rectangle (EvAnnotationMarkup *markup,
669 EvRectangle *ev_rect)
671 EvAnnotationMarkupProps *props;
673 g_return_if_fail (EV_IS_ANNOTATION_MARKUP (markup));
674 g_return_if_fail (ev_rect != NULL);
676 props = ev_annotation_markup_get_properties (markup);
677 *ev_rect = props->rectangle;
681 ev_annotation_markup_set_rectangle (EvAnnotationMarkup *markup,
682 const EvRectangle *ev_rect)
684 EvAnnotationMarkupProps *props;
686 g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
687 g_return_val_if_fail (ev_rect != NULL, FALSE);
689 props = ev_annotation_markup_get_properties (markup);
690 if (props->rectangle.x1 == ev_rect->x1 &&
691 props->rectangle.y1 == ev_rect->y1 &&
692 props->rectangle.x2 == ev_rect->x2 &&
693 props->rectangle.y2 == ev_rect->y2)
696 props->rectangle = *ev_rect;
698 g_object_notify (G_OBJECT (markup), "rectangle");
704 ev_annotation_markup_get_popup_is_open (EvAnnotationMarkup *markup)
706 EvAnnotationMarkupProps *props;
708 g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
710 props = ev_annotation_markup_get_properties (markup);
711 return props->popup_is_open;
715 ev_annotation_markup_set_popup_is_open (EvAnnotationMarkup *markup,
718 EvAnnotationMarkupProps *props;
720 g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
722 props = ev_annotation_markup_get_properties (markup);
723 if (props->popup_is_open == is_open)
726 props->popup_is_open = is_open;
728 g_object_notify (G_OBJECT (markup), "popup_is_open");
733 /* EvAnnotationText */
735 ev_annotation_text_init (EvAnnotationText *annot)
737 EV_ANNOTATION (annot)->type = EV_ANNOTATION_TYPE_TEXT;
741 ev_annotation_text_set_property (GObject *object,
746 EvAnnotationText *annot = EV_ANNOTATION_TEXT (object);
750 ev_annotation_text_set_icon (annot, g_value_get_enum (value));
752 case PROP_TEXT_IS_OPEN:
753 ev_annotation_text_set_is_open (annot, g_value_get_boolean (value));
756 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
761 ev_annotation_text_get_property (GObject *object,
766 EvAnnotationText *annot = EV_ANNOTATION_TEXT (object);
770 g_value_set_enum (value, annot->icon);
772 case PROP_TEXT_IS_OPEN:
773 g_value_set_boolean (value, annot->is_open);
776 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
781 ev_annotation_text_class_init (EvAnnotationTextClass *klass)
783 GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
785 g_object_class->set_property = ev_annotation_text_set_property;
786 g_object_class->get_property = ev_annotation_text_get_property;
788 ev_annotation_markup_class_install_properties (g_object_class);
790 g_object_class_install_property (g_object_class,
792 g_param_spec_enum ("icon",
794 "The icon fo the text annotation",
795 EV_TYPE_ANNOTATION_TEXT_ICON,
796 EV_ANNOTATION_TEXT_ICON_NOTE,
798 g_object_class_install_property (g_object_class,
800 g_param_spec_boolean ("is_open",
802 "Whether text annot is initially open",
808 ev_annotation_text_markup_iface_init (EvAnnotationMarkupInterface *iface)
813 ev_annotation_text_new (EvPage *page)
815 return EV_ANNOTATION (g_object_new (EV_TYPE_ANNOTATION_TEXT,
821 ev_annotation_text_get_icon (EvAnnotationText *text)
823 g_return_val_if_fail (EV_IS_ANNOTATION_TEXT (text), 0);
829 ev_annotation_text_set_icon (EvAnnotationText *text,
830 EvAnnotationTextIcon icon)
832 g_return_val_if_fail (EV_IS_ANNOTATION_TEXT (text), FALSE);
834 if (text->icon == icon)
839 g_object_notify (G_OBJECT (text), "icon");
845 ev_annotation_text_get_is_open (EvAnnotationText *text)
847 g_return_val_if_fail (EV_IS_ANNOTATION_TEXT (text), FALSE);
849 return text->is_open;
853 ev_annotation_text_set_is_open (EvAnnotationText *text,
856 g_return_val_if_fail (EV_IS_ANNOTATION_TEXT (text), FALSE);
858 if (text->is_open == is_open)
861 text->is_open = is_open;
863 g_object_notify (G_OBJECT (text), "is_open");
868 /* EvAnnotationAttachment */
870 ev_annotation_attachment_finalize (GObject *object)
872 EvAnnotationAttachment *annot = EV_ANNOTATION_ATTACHMENT (object);
874 if (annot->attachment) {
875 g_object_unref (annot->attachment);
876 annot->attachment = NULL;
879 G_OBJECT_CLASS (ev_annotation_attachment_parent_class)->finalize (object);
883 ev_annotation_attachment_init (EvAnnotationAttachment *annot)
885 EV_ANNOTATION (annot)->type = EV_ANNOTATION_TYPE_ATTACHMENT;
889 ev_annotation_attachment_set_property (GObject *object,
894 EvAnnotationAttachment *annot = EV_ANNOTATION_ATTACHMENT (object);
897 case PROP_ATTACHMENT_ATTACHMENT:
898 ev_annotation_attachment_set_attachment (annot, g_value_get_object (value));
901 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
906 ev_annotation_attachment_get_property (GObject *object,
911 EvAnnotationAttachment *annot = EV_ANNOTATION_ATTACHMENT (object);
914 case PROP_ATTACHMENT_ATTACHMENT:
915 g_value_set_object (value, annot->attachment);
918 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
923 ev_annotation_attachment_class_init (EvAnnotationAttachmentClass *klass)
925 GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
927 g_object_class->set_property = ev_annotation_attachment_set_property;
928 g_object_class->get_property = ev_annotation_attachment_get_property;
929 g_object_class->finalize = ev_annotation_attachment_finalize;
931 ev_annotation_markup_class_install_properties (g_object_class);
933 g_object_class_install_property (g_object_class,
934 PROP_ATTACHMENT_ATTACHMENT,
935 g_param_spec_object ("attachment",
937 "The attachment of the annotation",
944 ev_annotation_attachment_markup_iface_init (EvAnnotationMarkupInterface *iface)
949 ev_annotation_attachment_new (EvPage *page,
950 EvAttachment *attachment)
952 g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
954 return EV_ANNOTATION (g_object_new (EV_TYPE_ANNOTATION_ATTACHMENT,
956 "attachment", attachment,
961 ev_annotation_attachment_get_attachment (EvAnnotationAttachment *annot)
963 g_return_val_if_fail (EV_IS_ANNOTATION_ATTACHMENT (annot), NULL);
965 return annot->attachment;
969 ev_annotation_attachment_set_attachment (EvAnnotationAttachment *annot,
970 EvAttachment *attachment)
972 g_return_val_if_fail (EV_IS_ANNOTATION_ATTACHMENT (annot), FALSE);
974 if (annot->attachment == attachment)
977 if (annot->attachment)
978 g_object_unref (annot->attachment);
979 annot->attachment = attachment ? g_object_ref (attachment) : NULL;
981 g_object_notify (G_OBJECT (annot), "attachment");