1 /***************************************************************************
2 * Copyright (C) 2005 by Enrico Ros <eros.kde@email.it> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 ***************************************************************************/
10 #include "annotations.h"
11 #include "annotations_p.h"
14 #include <QtGui/QApplication>
15 #include <QtGui/QColor>
23 using namespace Okular
;
25 //BEGIN AnnotationUtils implementation
26 Annotation
* AnnotationUtils::createAnnotation( const QDomElement
& annElement
)
28 // safety check on annotation element
29 if ( !annElement
.hasAttribute( "type" ) )
32 // build annotation of given type
33 Annotation
* annotation
= 0;
34 int typeNumber
= annElement
.attribute( "type" ).toInt();
37 case Annotation::AText
:
38 annotation
= new TextAnnotation( annElement
);
40 case Annotation::ALine
:
41 annotation
= new LineAnnotation( annElement
);
43 case Annotation::AGeom
:
44 annotation
= new GeomAnnotation( annElement
);
46 case Annotation::AHighlight
:
47 annotation
= new HighlightAnnotation( annElement
);
49 case Annotation::AStamp
:
50 annotation
= new StampAnnotation( annElement
);
52 case Annotation::AInk
:
53 annotation
= new InkAnnotation( annElement
);
55 case Annotation::ACaret
:
56 annotation
= new CaretAnnotation( annElement
);
60 // return created annotation
64 void AnnotationUtils::storeAnnotation( const Annotation
* ann
, QDomElement
& annElement
,
65 QDomDocument
& document
)
67 // save annotation's type as element's attribute
68 annElement
.setAttribute( "type", (uint
)ann
->subType() );
70 // append all annotation data as children of this node
71 ann
->store( annElement
, document
);
74 QDomElement
AnnotationUtils::findChildElement( const QDomNode
& parentNode
,
75 const QString
& name
)
77 // loop through the whole children and return a 'name' named element
78 QDomNode subNode
= parentNode
.firstChild();
79 while( subNode
.isElement() )
81 QDomElement element
= subNode
.toElement();
82 if ( element
.tagName() == name
)
84 subNode
= subNode
.nextSibling();
86 // if the name can't be found, return a dummy null element
90 QRect
AnnotationUtils::annotationGeometry( const Annotation
* ann
,
91 double scaledWidth
, double scaledHeight
)
93 if ( ann
->subType() == Annotation::AText
&& ( ( (TextAnnotation
*)ann
)->textType() == TextAnnotation::Linked
) )
95 return QRect( (int)( ann
->transformedBoundingRectangle().left
* scaledWidth
),
96 (int)( ann
->transformedBoundingRectangle().top
* scaledHeight
), 24, 24 );
99 return ann
->transformedBoundingRectangle().geometry( (int)scaledWidth
, (int)scaledHeight
);
101 //END AnnotationUtils implementation
104 //BEGIN Annotation implementation
106 class Annotation::Style::Private
110 : m_opacity( 1.0 ), m_width( 1.0 ), m_style( Solid
), m_xCorners( 0.0 ),
111 m_yCorners( 0.0 ), m_marks( 3 ), m_spaces( 0 ), m_effect( NoEffect
),
112 m_effectIntensity( 1.0 )
125 double m_effectIntensity
;
128 Annotation::Style::Style()
133 Annotation::Style::~Style()
138 Annotation::Style::Style( const Style
&other
)
144 Annotation::Style
& Annotation::Style::operator=( const Style
&other
)
146 if ( this != &other
)
152 void Annotation::Style::setColor( const QColor
&color
)
157 QColor
Annotation::Style::color() const
162 void Annotation::Style::setOpacity( double opacity
)
164 d
->m_opacity
= opacity
;
167 double Annotation::Style::opacity() const
172 void Annotation::Style::setWidth( double width
)
177 double Annotation::Style::width() const
182 void Annotation::Style::setLineStyle( LineStyle style
)
187 Annotation::LineStyle
Annotation::Style::lineStyle() const
192 void Annotation::Style::setXCorners( double xCorners
)
194 d
->m_xCorners
= xCorners
;
197 double Annotation::Style::xCorners() const
199 return d
->m_xCorners
;
202 void Annotation::Style::setYCorners( double yCorners
)
204 d
->m_yCorners
= yCorners
;
207 double Annotation::Style::yCorners() const
209 return d
->m_yCorners
;
212 void Annotation::Style::setMarks( int marks
)
217 int Annotation::Style::marks() const
222 void Annotation::Style::setSpaces( int spaces
)
224 d
->m_spaces
= spaces
;
227 int Annotation::Style::spaces() const
232 void Annotation::Style::setLineEffect( LineEffect effect
)
234 d
->m_effect
= effect
;
237 Annotation::LineEffect
Annotation::Style::lineEffect() const
242 void Annotation::Style::setEffectIntensity( double intensity
)
244 d
->m_effectIntensity
= intensity
;
247 double Annotation::Style::effectIntensity() const
249 return d
->m_effectIntensity
;
253 class Annotation::Window::Private
257 : m_flags( -1 ), m_width( 0 ), m_height( 0 )
262 NormalizedPoint m_topLeft
;
270 Annotation::Window::Window()
275 Annotation::Window::~Window()
280 Annotation::Window::Window( const Window
&other
)
286 Annotation::Window
& Annotation::Window::operator=( const Window
&other
)
288 if ( this != &other
)
294 void Annotation::Window::setFlags( int flags
)
299 int Annotation::Window::flags() const
304 void Annotation::Window::setTopLeft( const NormalizedPoint
&point
)
306 d
->m_topLeft
= point
;
309 NormalizedPoint
Annotation::Window::topLeft() const
314 void Annotation::Window::setWidth( int width
)
319 int Annotation::Window::width() const
324 void Annotation::Window::setHeight( int height
)
326 d
->m_height
= height
;
329 int Annotation::Window::height() const
334 void Annotation::Window::setTitle( const QString
&title
)
339 QString
Annotation::Window::title() const
344 void Annotation::Window::setSummary( const QString
&summary
)
346 d
->m_summary
= summary
;
349 QString
Annotation::Window::summary() const
354 void Annotation::Window::setText( const QString
&text
)
359 QString
Annotation::Window::text() const
365 class Annotation::Revision::Private
369 : m_annotation( 0 ), m_scope( Reply
), m_type( None
)
373 Annotation
*m_annotation
;
374 RevisionScope m_scope
;
378 Annotation::Revision::Revision()
383 Annotation::Revision::~Revision()
388 Annotation::Revision::Revision( const Revision
&other
)
394 Annotation::Revision
& Annotation::Revision::operator=( const Revision
&other
)
396 if ( this != &other
)
402 void Annotation::Revision::setAnnotation( Annotation
*annotation
)
404 d
->m_annotation
= annotation
;
407 Annotation
*Annotation::Revision::annotation() const
409 return d
->m_annotation
;
412 void Annotation::Revision::setScope( RevisionScope scope
)
417 Annotation::RevisionScope
Annotation::Revision::scope() const
422 void Annotation::Revision::setType( RevisionType type
)
427 Annotation::RevisionType
Annotation::Revision::type() const
433 AnnotationPrivate::AnnotationPrivate()
434 : m_page( 0 ), m_flags( 0 ), m_disposeFunc( 0 )
438 AnnotationPrivate::~AnnotationPrivate()
440 // delete all children revisions
441 if ( m_revisions
.isEmpty() )
444 QLinkedList
< Annotation::Revision
>::iterator it
= m_revisions
.begin(), end
= m_revisions
.end();
445 for ( ; it
!= end
; ++it
)
446 delete (*it
).annotation();
449 Annotation::Annotation( AnnotationPrivate
&dd
)
454 Annotation::Annotation( AnnotationPrivate
&dd
, const QDomNode
& annNode
)
458 // get the [base] element of the annotation node
459 QDomElement e
= AnnotationUtils::findChildElement( annNode
, "base" );
463 // parse -contents- attributes
464 if ( e
.hasAttribute( "author" ) )
465 d
->m_author
= e
.attribute( "author" );
466 if ( e
.hasAttribute( "contents" ) )
467 d
->m_contents
= e
.attribute( "contents" );
468 if ( e
.hasAttribute( "uniqueName" ) )
469 d
->m_uniqueName
= e
.attribute( "uniqueName" );
470 if ( e
.hasAttribute( "modifyDate" ) )
471 d
->m_modifyDate
= QDateTime::fromString( e
.attribute("modifyDate"), Qt::ISODate
);
472 if ( e
.hasAttribute( "creationDate" ) )
473 d
->m_creationDate
= QDateTime::fromString( e
.attribute("creationDate"), Qt::ISODate
);
475 // parse -other- attributes
476 if ( e
.hasAttribute( "flags" ) )
477 d
->m_flags
= e
.attribute( "flags" ).toInt();
478 if ( e
.hasAttribute( "color" ) )
479 d
->m_style
.setColor( QColor( e
.attribute( "color" ) ) );
480 if ( e
.hasAttribute( "opacity" ) )
481 d
->m_style
.setOpacity( e
.attribute( "opacity" ).toDouble() );
483 // parse -the-subnodes- (describing Style, Window, Revision(s) structures)
484 // Note: all subnodes if present must be 'attributes complete'
485 QDomNode eSubNode
= e
.firstChild();
486 while ( eSubNode
.isElement() )
488 QDomElement ee
= eSubNode
.toElement();
489 eSubNode
= eSubNode
.nextSibling();
492 if ( ee
.tagName() == "boundary" )
494 d
->m_boundary
=NormalizedRect(ee
.attribute( "l" ).toDouble(),
495 ee
.attribute( "t" ).toDouble(),
496 ee
.attribute( "r" ).toDouble(),
497 ee
.attribute( "b" ).toDouble());
499 // parse penStyle if not default
500 else if ( ee
.tagName() == "penStyle" )
502 d
->m_style
.setWidth( ee
.attribute( "width" ).toDouble() );
503 d
->m_style
.setLineStyle( (LineStyle
)ee
.attribute( "style" ).toInt() );
504 d
->m_style
.setXCorners( ee
.attribute( "xcr" ).toDouble() );
505 d
->m_style
.setYCorners( ee
.attribute( "ycr" ).toDouble() );
506 d
->m_style
.setMarks( ee
.attribute( "marks" ).toInt() );
507 d
->m_style
.setSpaces( ee
.attribute( "spaces" ).toInt() );
509 // parse effectStyle if not default
510 else if ( ee
.tagName() == "penEffect" )
512 d
->m_style
.setLineEffect( (LineEffect
)ee
.attribute( "effect" ).toInt() );
513 d
->m_style
.setEffectIntensity( ee
.attribute( "intensity" ).toDouble() );
515 // parse window if present
516 else if ( ee
.tagName() == "window" )
518 d
->m_window
.setFlags( ee
.attribute( "flags" ).toInt() );
519 d
->m_window
.setTopLeft( NormalizedPoint( ee
.attribute( "top" ).toDouble(),
520 ee
.attribute( "left" ).toDouble() ) );
521 d
->m_window
.setWidth( ee
.attribute( "width" ).toInt() );
522 d
->m_window
.setHeight( ee
.attribute( "height" ).toInt() );
523 d
->m_window
.setTitle( ee
.attribute( "title" ) );
524 d
->m_window
.setSummary( ee
.attribute( "summary" ) );
525 // parse window subnodes
526 QDomNode winNode
= ee
.firstChild();
527 for ( ; winNode
.isElement(); winNode
= winNode
.nextSibling() )
529 QDomElement winElement
= winNode
.toElement();
530 if ( winElement
.tagName() == "text" )
531 d
->m_window
.setText( winElement
.firstChild().toCDATASection().data() );
536 // get the [revisions] element of the annotation node
537 QDomNode revNode
= annNode
.firstChild();
538 for ( ; revNode
.isElement(); revNode
= revNode
.nextSibling() )
540 QDomElement revElement
= revNode
.toElement();
541 if ( revElement
.tagName() != "revision" )
544 // compile the Revision structure crating annotation
546 revision
.setScope( (RevisionScope
)revElement
.attribute( "revScope" ).toInt() );
547 revision
.setType( (RevisionType
)revElement
.attribute( "revType" ).toInt() );
548 revision
.setAnnotation( AnnotationUtils::createAnnotation( revElement
) );
550 // if annotation is valid, add revision to internal list
551 if ( revision
.annotation() )
552 d
->m_revisions
.append( revision
);
555 d
->m_transformedBoundary
= d
->m_boundary
;
558 Annotation::~Annotation()
560 if ( d_ptr
->m_disposeFunc
)
561 d_ptr
->m_disposeFunc( this );
566 void Annotation::setAuthor( const QString
&author
)
569 d
->m_author
= author
;
572 QString
Annotation::author() const
574 Q_D( const Annotation
);
578 void Annotation::setContents( const QString
&contents
)
581 d
->m_contents
= contents
;
584 QString
Annotation::contents() const
586 Q_D( const Annotation
);
587 return d
->m_contents
;
590 void Annotation::setUniqueName( const QString
&name
)
593 d
->m_uniqueName
= name
;
596 QString
Annotation::uniqueName() const
598 Q_D( const Annotation
);
599 return d
->m_uniqueName
;
602 void Annotation::setModificationDate( const QDateTime
&date
)
605 d
->m_modifyDate
= date
;
608 QDateTime
Annotation::modificationDate() const
610 Q_D( const Annotation
);
611 return d
->m_modifyDate
;
614 void Annotation::setCreationDate( const QDateTime
&date
)
617 d
->m_creationDate
= date
;
620 QDateTime
Annotation::creationDate() const
622 Q_D( const Annotation
);
623 return d
->m_creationDate
;
626 void Annotation::setFlags( int flags
)
632 int Annotation::flags() const
634 Q_D( const Annotation
);
638 void Annotation::setBoundingRectangle( const NormalizedRect
&rectangle
)
641 d
->m_boundary
= rectangle
;
642 d
->resetTransformation();
645 d
->transform( d
->m_page
->rotationMatrix() );
649 NormalizedRect
Annotation::boundingRectangle() const
651 Q_D( const Annotation
);
652 return d
->m_boundary
;
655 NormalizedRect
Annotation::transformedBoundingRectangle() const
657 Q_D( const Annotation
);
658 return d
->m_transformedBoundary
;
661 void Annotation::translate( const NormalizedPoint
&coord
)
664 d
->translate( coord
);
665 d
->resetTransformation();
668 d
->transform( d
->m_page
->rotationMatrix() );
672 Annotation::Style
& Annotation::style()
678 const Annotation::Style
& Annotation::style() const
680 Q_D( const Annotation
);
684 Annotation::Window
& Annotation::window()
690 const Annotation::Window
& Annotation::window() const
692 Q_D( const Annotation
);
696 QLinkedList
< Annotation::Revision
> & Annotation::revisions()
699 return d
->m_revisions
;
702 const QLinkedList
< Annotation::Revision
> & Annotation::revisions() const
704 Q_D( const Annotation
);
705 return d
->m_revisions
;
708 void Annotation::setNativeId( const QVariant
&id
)
714 QVariant
Annotation::nativeId() const
716 Q_D( const Annotation
);
717 return d
->m_nativeId
;
720 void Annotation::setDisposeDataFunction( DisposeDataFunction func
)
723 d
->m_disposeFunc
= func
;
726 bool Annotation::canBeMoved() const
728 Q_D( const Annotation
);
729 // for now, it is pointless moving external annotations
730 // as we cannot change them anyway
731 if ( d
->m_flags
& External
)
734 // highlight "requires" to be "bounded" to text, and that's tricky for now
735 if ( subType() == AHighlight
)
741 void Annotation::store( QDomNode
& annNode
, QDomDocument
& document
) const
743 Q_D( const Annotation
);
744 // create [base] element of the annotation node
745 QDomElement e
= document
.createElement( "base" );
746 annNode
.appendChild( e
);
748 // store -contents- attributes
749 if ( !d
->m_author
.isEmpty() )
750 e
.setAttribute( "author", d
->m_author
);
751 if ( !d
->m_contents
.isEmpty() )
752 e
.setAttribute( "contents", d
->m_contents
);
753 if ( !d
->m_uniqueName
.isEmpty() )
754 e
.setAttribute( "uniqueName", d
->m_uniqueName
);
755 if ( d
->m_modifyDate
.isValid() )
756 e
.setAttribute( "modifyDate", d
->m_modifyDate
.toString(Qt::ISODate
) );
757 if ( d
->m_creationDate
.isValid() )
758 e
.setAttribute( "creationDate", d
->m_creationDate
.toString(Qt::ISODate
) );
760 // store -other- attributes
762 e
.setAttribute( "flags", d
->m_flags
);
763 if ( d
->m_style
.color().isValid() )
764 e
.setAttribute( "color", d
->m_style
.color().name() );
765 if ( d
->m_style
.opacity() != 1.0 )
766 e
.setAttribute( "opacity", d
->m_style
.opacity() );
768 // Sub-Node-1 - boundary
769 QDomElement bE
= document
.createElement( "boundary" );
771 bE
.setAttribute( "l", (double)d
->m_boundary
.left
);
772 bE
.setAttribute( "t", (double)d
->m_boundary
.top
);
773 bE
.setAttribute( "r", (double)d
->m_boundary
.right
);
774 bE
.setAttribute( "b", (double)d
->m_boundary
.bottom
);
776 // Sub-Node-2 - penStyle
777 if ( d
->m_style
.width() != 1 || d
->m_style
.lineStyle() != Solid
|| d
->m_style
.xCorners() != 0 ||
778 d
->m_style
.yCorners() != 0.0 || d
->m_style
.marks() != 3 || d
->m_style
.spaces() != 0 )
780 QDomElement psE
= document
.createElement( "penStyle" );
781 e
.appendChild( psE
);
782 psE
.setAttribute( "width", d
->m_style
.width() );
783 psE
.setAttribute( "style", (int)d
->m_style
.lineStyle() );
784 psE
.setAttribute( "xcr", d
->m_style
.xCorners() );
785 psE
.setAttribute( "ycr", d
->m_style
.yCorners() );
786 psE
.setAttribute( "marks", d
->m_style
.marks() );
787 psE
.setAttribute( "spaces", d
->m_style
.spaces() );
790 // Sub-Node-3 - penEffect
791 if ( d
->m_style
.lineEffect() != NoEffect
|| d
->m_style
.effectIntensity() != 1.0 )
793 QDomElement peE
= document
.createElement( "penEffect" );
794 e
.appendChild( peE
);
795 peE
.setAttribute( "effect", (int)d
->m_style
.lineEffect() );
796 peE
.setAttribute( "intensity", d
->m_style
.effectIntensity() );
799 // Sub-Node-4 - window
800 if ( d
->m_window
.flags() != -1 || !d
->m_window
.title().isEmpty() ||
801 !d
->m_window
.summary().isEmpty() || !d
->m_window
.text().isEmpty() )
803 QDomElement wE
= document
.createElement( "window" );
805 wE
.setAttribute( "flags", d
->m_window
.flags() );
806 wE
.setAttribute( "top", d
->m_window
.topLeft().x
);
807 wE
.setAttribute( "left", d
->m_window
.topLeft().y
);
808 wE
.setAttribute( "width", d
->m_window
.width() );
809 wE
.setAttribute( "height", d
->m_window
.height() );
810 wE
.setAttribute( "title", d
->m_window
.title() );
811 wE
.setAttribute( "summary", d
->m_window
.summary() );
812 // store window.text as a subnode, because we need escaped data
813 if ( !d
->m_window
.text().isEmpty() )
815 QDomElement escapedText
= document
.createElement( "text" );
816 wE
.appendChild( escapedText
);
817 QDomCDATASection textCData
= document
.createCDATASection( d
->m_window
.text() );
818 escapedText
.appendChild( textCData
);
822 // create [revision] element of the annotation node (if any)
823 if ( d
->m_revisions
.isEmpty() )
826 // add all revisions as children of revisions element
827 QLinkedList
< Revision
>::const_iterator it
= d
->m_revisions
.begin(), end
= d
->m_revisions
.end();
828 for ( ; it
!= end
; ++it
)
830 // create revision element
831 const Revision
& revision
= *it
;
832 QDomElement r
= document
.createElement( "revision" );
833 annNode
.appendChild( r
);
834 // set element attributes
835 r
.setAttribute( "revScope", (int)revision
.scope() );
836 r
.setAttribute( "revType", (int)revision
.type() );
837 // use revision as the annotation element, so fill it up
838 AnnotationUtils::storeAnnotation( revision
.annotation(), r
, document
);
842 void AnnotationPrivate::annotationTransform( const QMatrix
&matrix
)
844 resetTransformation();
848 void AnnotationPrivate::transform( const QMatrix
&matrix
)
850 m_transformedBoundary
.transform( matrix
);
853 void AnnotationPrivate::baseTransform( const QMatrix
&matrix
)
855 m_boundary
.transform( matrix
);
858 void AnnotationPrivate::resetTransformation()
860 m_transformedBoundary
= m_boundary
;
863 void AnnotationPrivate::translate( const NormalizedPoint
&coord
)
865 m_boundary
.left
= m_boundary
.left
+ coord
.x
;
866 m_boundary
.right
= m_boundary
.right
+ coord
.x
;
867 m_boundary
.top
= m_boundary
.top
+ coord
.y
;
868 m_boundary
.bottom
= m_boundary
.bottom
+ coord
.y
;
871 //END Annotation implementation
874 /** TextAnnotation [Annotation] */
876 class Okular::TextAnnotationPrivate
: public Okular::AnnotationPrivate
879 TextAnnotationPrivate()
880 : AnnotationPrivate(), m_textType( TextAnnotation::Linked
),
881 m_textIcon( "Note" ), m_inplaceAlign( 0 ),
882 m_inplaceIntent( TextAnnotation::Unknown
)
886 virtual void transform( const QMatrix
&matrix
);
887 virtual void baseTransform( const QMatrix
&matrix
);
888 virtual void resetTransformation();
889 virtual void translate( const NormalizedPoint
&coord
);
891 TextAnnotation::TextType m_textType
;
895 QString m_inplaceText
;
896 NormalizedPoint m_inplaceCallout
[3];
897 NormalizedPoint m_transformedInplaceCallout
[3];
898 TextAnnotation::InplaceIntent m_inplaceIntent
;
902 The default textIcon for text annotation is Note as the PDF Reference says
904 TextAnnotation::TextAnnotation()
905 : Annotation( *new TextAnnotationPrivate() )
909 TextAnnotation::TextAnnotation( const QDomNode
& node
)
910 : Annotation( *new TextAnnotationPrivate(), node
)
912 Q_D( TextAnnotation
);
913 // loop through the whole children looking for a 'text' element
914 QDomNode subNode
= node
.firstChild();
915 while( subNode
.isElement() )
917 QDomElement e
= subNode
.toElement();
918 subNode
= subNode
.nextSibling();
919 if ( e
.tagName() != "text" )
922 // parse the attributes
923 if ( e
.hasAttribute( "type" ) )
924 d
->m_textType
= (TextAnnotation::TextType
)e
.attribute( "type" ).toInt();
925 if ( e
.hasAttribute( "icon" ) )
926 d
->m_textIcon
= e
.attribute( "icon" );
927 if ( e
.hasAttribute( "font" ) )
928 d
->m_textFont
.fromString( e
.attribute( "font" ) );
929 if ( e
.hasAttribute( "align" ) )
930 d
->m_inplaceAlign
= e
.attribute( "align" ).toInt();
931 if ( e
.hasAttribute( "intent" ) )
932 d
->m_inplaceIntent
= (TextAnnotation::InplaceIntent
)e
.attribute( "intent" ).toInt();
934 // parse the subnodes
935 QDomNode eSubNode
= e
.firstChild();
936 while ( eSubNode
.isElement() )
938 QDomElement ee
= eSubNode
.toElement();
939 eSubNode
= eSubNode
.nextSibling();
941 if ( ee
.tagName() == "escapedText" )
943 d
->m_inplaceText
= ee
.firstChild().toCDATASection().data();
945 else if ( ee
.tagName() == "callout" )
947 d
->m_inplaceCallout
[0].x
= ee
.attribute( "ax" ).toDouble();
948 d
->m_inplaceCallout
[0].y
= ee
.attribute( "ay" ).toDouble();
949 d
->m_inplaceCallout
[1].x
= ee
.attribute( "bx" ).toDouble();
950 d
->m_inplaceCallout
[1].y
= ee
.attribute( "by" ).toDouble();
951 d
->m_inplaceCallout
[2].x
= ee
.attribute( "cx" ).toDouble();
952 d
->m_inplaceCallout
[2].y
= ee
.attribute( "cy" ).toDouble();
960 for ( int i
= 0; i
< 3; ++i
)
961 d
->m_transformedInplaceCallout
[i
] = d
->m_inplaceCallout
[i
];
964 TextAnnotation::~TextAnnotation()
968 void TextAnnotation::setTextType( TextType textType
)
970 Q_D( TextAnnotation
);
971 d
->m_textType
= textType
;
974 TextAnnotation::TextType
TextAnnotation::textType() const
976 Q_D( const TextAnnotation
);
977 return d
->m_textType
;
980 void TextAnnotation::setTextIcon( const QString
&icon
)
982 Q_D( TextAnnotation
);
983 d
->m_textIcon
= icon
;
986 QString
TextAnnotation::textIcon() const
988 Q_D( const TextAnnotation
);
989 return d
->m_textIcon
;
992 void TextAnnotation::setTextFont( const QFont
&font
)
994 Q_D( TextAnnotation
);
995 d
->m_textFont
= font
;
998 QFont
TextAnnotation::textFont() const
1000 Q_D( const TextAnnotation
);
1001 return d
->m_textFont
;
1004 void TextAnnotation::setInplaceAlignment( int alignment
)
1006 Q_D( TextAnnotation
);
1007 d
->m_inplaceAlign
= alignment
;
1010 int TextAnnotation::inplaceAlignment() const
1012 Q_D( const TextAnnotation
);
1013 return d
->m_inplaceAlign
;
1016 void TextAnnotation::setInplaceText( const QString
&text
)
1018 Q_D( TextAnnotation
);
1019 d
->m_inplaceText
= text
;
1022 QString
TextAnnotation::inplaceText() const
1024 Q_D( const TextAnnotation
);
1025 return d
->m_inplaceText
;
1028 void TextAnnotation::setInplaceCallout( const NormalizedPoint
&point
, int index
)
1030 if ( index
< 0 || index
> 2 )
1033 Q_D( TextAnnotation
);
1034 d
->m_inplaceCallout
[ index
] = point
;
1037 NormalizedPoint
TextAnnotation::inplaceCallout( int index
) const
1039 if ( index
< 0 || index
> 2 )
1040 return NormalizedPoint();
1042 Q_D( const TextAnnotation
);
1043 return d
->m_inplaceCallout
[ index
];
1046 NormalizedPoint
TextAnnotation::transformedInplaceCallout( int index
) const
1048 if ( index
< 0 || index
> 2 )
1049 return NormalizedPoint();
1051 Q_D( const TextAnnotation
);
1052 return d
->m_transformedInplaceCallout
[ index
];
1055 void TextAnnotation::setInplaceIntent( InplaceIntent intent
)
1057 Q_D( TextAnnotation
);
1058 d
->m_inplaceIntent
= intent
;
1061 TextAnnotation::InplaceIntent
TextAnnotation::inplaceIntent() const
1063 Q_D( const TextAnnotation
);
1064 return d
->m_inplaceIntent
;
1067 Annotation::SubType
TextAnnotation::subType() const
1072 void TextAnnotation::store( QDomNode
& node
, QDomDocument
& document
) const
1074 Q_D( const TextAnnotation
);
1075 // recurse to parent objects storing properties
1076 Annotation::store( node
, document
);
1078 // create [text] element
1079 QDomElement textElement
= document
.createElement( "text" );
1080 node
.appendChild( textElement
);
1082 // store the optional attributes
1083 if ( d
->m_textType
!= Linked
)
1084 textElement
.setAttribute( "type", (int)d
->m_textType
);
1085 if ( d
->m_textIcon
!= "Comment" )
1086 textElement
.setAttribute( "icon", d
->m_textIcon
);
1087 if ( d
->m_textFont
!= QApplication::font() )
1088 textElement
.setAttribute( "font", d
->m_textFont
.toString() );
1089 if ( d
->m_inplaceAlign
)
1090 textElement
.setAttribute( "align", d
->m_inplaceAlign
);
1091 if ( d
->m_inplaceIntent
!= Unknown
)
1092 textElement
.setAttribute( "intent", (int)d
->m_inplaceIntent
);
1094 // Sub-Node-1 - escapedText
1095 if ( !d
->m_inplaceText
.isEmpty() )
1097 QDomElement escapedText
= document
.createElement( "escapedText" );
1098 textElement
.appendChild( escapedText
);
1099 QDomCDATASection textCData
= document
.createCDATASection( d
->m_inplaceText
);
1100 escapedText
.appendChild( textCData
);
1103 // Sub-Node-2 - callout
1104 if ( d
->m_inplaceCallout
[0].x
!= 0.0 )
1106 QDomElement calloutElement
= document
.createElement( "callout" );
1107 textElement
.appendChild( calloutElement
);
1108 calloutElement
.setAttribute( "ax", d
->m_inplaceCallout
[0].x
);
1109 calloutElement
.setAttribute( "ay", d
->m_inplaceCallout
[0].y
);
1110 calloutElement
.setAttribute( "bx", d
->m_inplaceCallout
[1].x
);
1111 calloutElement
.setAttribute( "by", d
->m_inplaceCallout
[1].y
);
1112 calloutElement
.setAttribute( "cx", d
->m_inplaceCallout
[2].x
);
1113 calloutElement
.setAttribute( "cy", d
->m_inplaceCallout
[2].y
);
1117 void TextAnnotationPrivate::transform( const QMatrix
&matrix
)
1119 AnnotationPrivate::transform( matrix
);
1121 for ( int i
= 0; i
< 3; ++i
) {
1122 m_transformedInplaceCallout
[i
].transform( matrix
);
1126 void TextAnnotationPrivate::baseTransform( const QMatrix
&matrix
)
1128 AnnotationPrivate::baseTransform( matrix
);
1130 for ( int i
= 0; i
< 3; ++i
) {
1131 m_inplaceCallout
[i
].transform( matrix
);
1135 void TextAnnotationPrivate::resetTransformation()
1137 AnnotationPrivate::resetTransformation();
1139 for ( int i
= 0; i
< 3; ++i
) {
1140 m_transformedInplaceCallout
[i
] = m_inplaceCallout
[i
];
1144 void TextAnnotationPrivate::translate( const NormalizedPoint
&coord
)
1146 AnnotationPrivate::translate( coord
);
1148 #define ADD_COORD( c1, c2 ) \
1150 c1.x = c1.x + c2.x; \
1151 c1.y = c1.y + c2.y; \
1153 ADD_COORD( m_inplaceCallout
[0], coord
)
1154 ADD_COORD( m_inplaceCallout
[1], coord
)
1155 ADD_COORD( m_inplaceCallout
[2], coord
)
1159 /** LineAnnotation [Annotation] */
1161 class Okular::LineAnnotationPrivate
: public Okular::AnnotationPrivate
1164 LineAnnotationPrivate()
1165 : AnnotationPrivate(),
1166 m_lineStartStyle( LineAnnotation::None
), m_lineEndStyle( LineAnnotation::None
),
1167 m_lineClosed( false ), m_lineShowCaption( false ), m_lineLeadingFwdPt( 0 ),
1168 m_lineLeadingBackPt( 0 ), m_lineIntent( LineAnnotation::Unknown
)
1172 virtual void transform( const QMatrix
&matrix
);
1173 virtual void baseTransform( const QMatrix
&matrix
);
1174 virtual void resetTransformation();
1175 virtual void translate( const NormalizedPoint
&coord
);
1177 QLinkedList
<NormalizedPoint
> m_linePoints
;
1178 QLinkedList
<NormalizedPoint
> m_transformedLinePoints
;
1179 LineAnnotation::TermStyle m_lineStartStyle
;
1180 LineAnnotation::TermStyle m_lineEndStyle
;
1181 bool m_lineClosed
: 1;
1182 bool m_lineShowCaption
: 1;
1183 QColor m_lineInnerColor
;
1184 double m_lineLeadingFwdPt
;
1185 double m_lineLeadingBackPt
;
1186 LineAnnotation::LineIntent m_lineIntent
;
1189 LineAnnotation::LineAnnotation()
1190 : Annotation( *new LineAnnotationPrivate() )
1194 LineAnnotation::LineAnnotation( const QDomNode
& node
)
1195 : Annotation( *new LineAnnotationPrivate(), node
)
1197 Q_D( LineAnnotation
);
1198 // loop through the whole children looking for a 'line' element
1199 QDomNode subNode
= node
.firstChild();
1200 while( subNode
.isElement() )
1202 QDomElement e
= subNode
.toElement();
1203 subNode
= subNode
.nextSibling();
1204 if ( e
.tagName() != "line" )
1207 // parse the attributes
1208 if ( e
.hasAttribute( "startStyle" ) )
1209 d
->m_lineStartStyle
= (LineAnnotation::TermStyle
)e
.attribute( "startStyle" ).toInt();
1210 if ( e
.hasAttribute( "endStyle" ) )
1211 d
->m_lineEndStyle
= (LineAnnotation::TermStyle
)e
.attribute( "endStyle" ).toInt();
1212 if ( e
.hasAttribute( "closed" ) )
1213 d
->m_lineClosed
= e
.attribute( "closed" ).toInt();
1214 if ( e
.hasAttribute( "innerColor" ) )
1215 d
->m_lineInnerColor
= QColor( e
.attribute( "innerColor" ) );
1216 if ( e
.hasAttribute( "leadFwd" ) )
1217 d
->m_lineLeadingFwdPt
= e
.attribute( "leadFwd" ).toDouble();
1218 if ( e
.hasAttribute( "leadBack" ) )
1219 d
->m_lineLeadingBackPt
= e
.attribute( "leadBack" ).toDouble();
1220 if ( e
.hasAttribute( "showCaption" ) )
1221 d
->m_lineShowCaption
= e
.attribute( "showCaption" ).toInt();
1222 if ( e
.hasAttribute( "intent" ) )
1223 d
->m_lineIntent
= (LineAnnotation::LineIntent
)e
.attribute( "intent" ).toInt();
1225 // parse all 'point' subnodes
1226 QDomNode pointNode
= e
.firstChild();
1227 while ( pointNode
.isElement() )
1229 QDomElement pe
= pointNode
.toElement();
1230 pointNode
= pointNode
.nextSibling();
1232 if ( pe
.tagName() != "point" )
1236 p
.x
= pe
.attribute( "x", "0.0" ).toDouble();
1237 p
.y
= pe
.attribute( "y", "0.0" ).toDouble();
1238 d
->m_linePoints
.append( p
);
1245 d
->m_transformedLinePoints
= d
->m_linePoints
;
1248 LineAnnotation::~LineAnnotation()
1252 void LineAnnotation::setLinePoints( const QLinkedList
<NormalizedPoint
> &points
)
1254 Q_D( LineAnnotation
);
1255 d
->m_linePoints
= points
;
1258 QLinkedList
<NormalizedPoint
> LineAnnotation::linePoints() const
1260 Q_D( const LineAnnotation
);
1261 return d
->m_linePoints
;
1264 QLinkedList
<NormalizedPoint
> LineAnnotation::transformedLinePoints() const
1266 Q_D( const LineAnnotation
);
1267 return d
->m_transformedLinePoints
;
1270 void LineAnnotation::setLineStartStyle( TermStyle style
)
1272 Q_D( LineAnnotation
);
1273 d
->m_lineStartStyle
= style
;
1276 LineAnnotation::TermStyle
LineAnnotation::lineStartStyle() const
1278 Q_D( const LineAnnotation
);
1279 return d
->m_lineStartStyle
;
1282 void LineAnnotation::setLineEndStyle( TermStyle style
)
1284 Q_D( LineAnnotation
);
1285 d
->m_lineEndStyle
= style
;
1288 LineAnnotation::TermStyle
LineAnnotation::lineEndStyle() const
1290 Q_D( const LineAnnotation
);
1291 return d
->m_lineEndStyle
;
1294 void LineAnnotation::setLineClosed( bool closed
)
1296 Q_D( LineAnnotation
);
1297 d
->m_lineClosed
= closed
;
1300 bool LineAnnotation::lineClosed() const
1302 Q_D( const LineAnnotation
);
1303 return d
->m_lineClosed
;
1306 void LineAnnotation::setLineInnerColor( const QColor
&color
)
1308 Q_D( LineAnnotation
);
1309 d
->m_lineInnerColor
= color
;
1312 QColor
LineAnnotation::lineInnerColor() const
1314 Q_D( const LineAnnotation
);
1315 return d
->m_lineInnerColor
;
1318 void LineAnnotation::setLineLeadingForwardPoint( double point
)
1320 Q_D( LineAnnotation
);
1321 d
->m_lineLeadingFwdPt
= point
;
1324 double LineAnnotation::lineLeadingForwardPoint() const
1326 Q_D( const LineAnnotation
);
1327 return d
->m_lineLeadingFwdPt
;
1330 void LineAnnotation::setLineLeadingBackwardPoint( double point
)
1332 Q_D( LineAnnotation
);
1333 d
->m_lineLeadingBackPt
= point
;
1336 double LineAnnotation::lineLeadingBackwardPoint() const
1338 Q_D( const LineAnnotation
);
1339 return d
->m_lineLeadingBackPt
;
1342 void LineAnnotation::setShowCaption( bool show
)
1344 Q_D( LineAnnotation
);
1345 d
->m_lineShowCaption
= show
;
1348 bool LineAnnotation::showCaption() const
1350 Q_D( const LineAnnotation
);
1351 return d
->m_lineShowCaption
;
1354 void LineAnnotation::setLineIntent( LineIntent intent
)
1356 Q_D( LineAnnotation
);
1357 d
->m_lineIntent
= intent
;
1360 LineAnnotation::LineIntent
LineAnnotation::lineIntent() const
1362 Q_D( const LineAnnotation
);
1363 return d
->m_lineIntent
;
1366 Annotation::SubType
LineAnnotation::subType() const
1371 void LineAnnotation::store( QDomNode
& node
, QDomDocument
& document
) const
1373 Q_D( const LineAnnotation
);
1374 // recurse to parent objects storing properties
1375 Annotation::store( node
, document
);
1377 // create [line] element
1378 QDomElement lineElement
= document
.createElement( "line" );
1379 node
.appendChild( lineElement
);
1381 // store the attributes
1382 if ( d
->m_lineStartStyle
!= None
)
1383 lineElement
.setAttribute( "startStyle", (int)d
->m_lineStartStyle
);
1384 if ( d
->m_lineEndStyle
!= None
)
1385 lineElement
.setAttribute( "endStyle", (int)d
->m_lineEndStyle
);
1386 if ( d
->m_lineClosed
)
1387 lineElement
.setAttribute( "closed", d
->m_lineClosed
);
1388 if ( d
->m_lineInnerColor
.isValid() )
1389 lineElement
.setAttribute( "innerColor", d
->m_lineInnerColor
.name() );
1390 if ( d
->m_lineLeadingFwdPt
!= 0.0 )
1391 lineElement
.setAttribute( "leadFwd", d
->m_lineLeadingFwdPt
);
1392 if ( d
->m_lineLeadingBackPt
!= 0.0 )
1393 lineElement
.setAttribute( "leadBack", d
->m_lineLeadingBackPt
);
1394 if ( d
->m_lineShowCaption
)
1395 lineElement
.setAttribute( "showCaption", d
->m_lineShowCaption
);
1396 if ( d
->m_lineIntent
!= Unknown
)
1397 lineElement
.setAttribute( "intent", d
->m_lineIntent
);
1399 // append the list of points
1400 int points
= d
->m_linePoints
.count();
1403 QLinkedList
<NormalizedPoint
>::const_iterator it
= d
->m_linePoints
.begin(), end
= d
->m_linePoints
.end();
1406 const NormalizedPoint
& p
= *it
;
1407 QDomElement pElement
= document
.createElement( "point" );
1408 lineElement
.appendChild( pElement
);
1409 pElement
.setAttribute( "x", p
.x
);
1410 pElement
.setAttribute( "y", p
.y
);
1411 it
++; //to avoid loop
1416 void LineAnnotationPrivate::transform( const QMatrix
&matrix
)
1418 AnnotationPrivate::transform( matrix
);
1420 QMutableLinkedListIterator
<NormalizedPoint
> it( m_transformedLinePoints
);
1421 while ( it
.hasNext() )
1422 it
.next().transform( matrix
);
1425 void LineAnnotationPrivate::baseTransform( const QMatrix
&matrix
)
1427 AnnotationPrivate::baseTransform( matrix
);
1429 QMutableLinkedListIterator
<NormalizedPoint
> it( m_linePoints
);
1430 while ( it
.hasNext() )
1431 it
.next().transform( matrix
);
1434 void LineAnnotationPrivate::resetTransformation()
1436 AnnotationPrivate::resetTransformation();
1438 m_transformedLinePoints
= m_linePoints
;
1441 void LineAnnotationPrivate::translate( const NormalizedPoint
&coord
)
1443 AnnotationPrivate::translate( coord
);
1445 QMutableLinkedListIterator
<NormalizedPoint
> it( m_linePoints
);
1446 while ( it
.hasNext() )
1448 NormalizedPoint
& p
= it
.next();
1449 p
.x
= p
.x
+ coord
.x
;
1450 p
.y
= p
.y
+ coord
.y
;
1454 /** GeomAnnotation [Annotation] */
1456 class Okular::GeomAnnotationPrivate
: public Okular::AnnotationPrivate
1459 GeomAnnotationPrivate()
1460 : AnnotationPrivate(), m_geomType( GeomAnnotation::InscribedSquare
)
1464 GeomAnnotation::GeomType m_geomType
;
1465 QColor m_geomInnerColor
;
1468 GeomAnnotation::GeomAnnotation()
1469 : Annotation( *new GeomAnnotationPrivate() )
1473 GeomAnnotation::GeomAnnotation( const QDomNode
& node
)
1474 : Annotation( *new GeomAnnotationPrivate(), node
)
1476 Q_D( GeomAnnotation
);
1477 // loop through the whole children looking for a 'geom' element
1478 QDomNode subNode
= node
.firstChild();
1479 while( subNode
.isElement() )
1481 QDomElement e
= subNode
.toElement();
1482 subNode
= subNode
.nextSibling();
1483 if ( e
.tagName() != "geom" )
1486 // parse the attributes
1487 if ( e
.hasAttribute( "type" ) )
1488 d
->m_geomType
= (GeomAnnotation::GeomType
)e
.attribute( "type" ).toInt();
1489 if ( e
.hasAttribute( "color" ) )
1490 d
->m_geomInnerColor
= QColor( e
.attribute( "color" ) );
1492 if ( e
.hasAttribute( "width" ) )
1493 d
->m_style
.setWidth( e
.attribute( "width" ).toInt() );
1500 GeomAnnotation::~GeomAnnotation()
1504 void GeomAnnotation::setGeometricalType( GeomType type
)
1506 Q_D( GeomAnnotation
);
1507 d
->m_geomType
= type
;
1510 GeomAnnotation::GeomType
GeomAnnotation::geometricalType() const
1512 Q_D( const GeomAnnotation
);
1513 return d
->m_geomType
;
1516 void GeomAnnotation::setGeometricalInnerColor( const QColor
&color
)
1518 Q_D( GeomAnnotation
);
1519 d
->m_geomInnerColor
= color
;
1522 QColor
GeomAnnotation::geometricalInnerColor() const
1524 Q_D( const GeomAnnotation
);
1525 return d
->m_geomInnerColor
;
1528 void GeomAnnotation::setGeometricalPointWidth( int width
)
1530 Q_D( GeomAnnotation
);
1531 d
->m_style
.setWidth( width
);
1534 int GeomAnnotation::geometricalPointWidth() const
1536 Q_D( const GeomAnnotation
);
1537 return static_cast< int >( d
->m_style
.width() );
1540 Annotation::SubType
GeomAnnotation::subType() const
1545 void GeomAnnotation::store( QDomNode
& node
, QDomDocument
& document
) const
1547 Q_D( const GeomAnnotation
);
1548 // recurse to parent objects storing properties
1549 Annotation::store( node
, document
);
1551 // create [geom] element
1552 QDomElement geomElement
= document
.createElement( "geom" );
1553 node
.appendChild( geomElement
);
1555 // append the optional attributes
1556 if ( d
->m_geomType
!= InscribedSquare
)
1557 geomElement
.setAttribute( "type", (int)d
->m_geomType
);
1558 if ( d
->m_geomInnerColor
.isValid() )
1559 geomElement
.setAttribute( "color", d
->m_geomInnerColor
.name() );
1562 /** HighlightAnnotation [Annotation] */
1564 class HighlightAnnotation::Quad::Private
1571 NormalizedPoint m_points
[4];
1572 NormalizedPoint m_transformedPoints
[4];
1573 bool m_capStart
: 1;
1578 HighlightAnnotation::Quad::Quad()
1583 HighlightAnnotation::Quad::~Quad()
1588 HighlightAnnotation::Quad::Quad( const Quad
&other
)
1594 HighlightAnnotation::Quad
& HighlightAnnotation::Quad::operator=( const Quad
&other
)
1596 if ( this != &other
)
1602 void HighlightAnnotation::Quad::setPoint( const NormalizedPoint
&point
, int index
)
1604 if ( index
< 0 || index
> 3 )
1607 d
->m_points
[ index
] = point
;
1610 NormalizedPoint
HighlightAnnotation::Quad::point( int index
) const
1612 if ( index
< 0 || index
> 3 )
1613 return NormalizedPoint();
1615 return d
->m_points
[ index
];
1618 NormalizedPoint
HighlightAnnotation::Quad::transformedPoint( int index
) const
1620 if ( index
< 0 || index
> 3 )
1621 return NormalizedPoint();
1623 return d
->m_transformedPoints
[ index
];
1626 void HighlightAnnotation::Quad::setCapStart( bool value
)
1628 d
->m_capStart
= value
;
1631 bool HighlightAnnotation::Quad::capStart() const
1633 return d
->m_capStart
;
1636 void HighlightAnnotation::Quad::setCapEnd( bool value
)
1638 d
->m_capEnd
= value
;
1641 bool HighlightAnnotation::Quad::capEnd() const
1646 void HighlightAnnotation::Quad::setFeather( double width
)
1648 d
->m_feather
= width
;
1651 double HighlightAnnotation::Quad::feather() const
1653 return d
->m_feather
;
1656 void HighlightAnnotation::Quad::transform( const QMatrix
&matrix
)
1658 for ( int i
= 0; i
< 4; ++i
) {
1659 d
->m_transformedPoints
[ i
] = d
->m_points
[ i
];
1660 d
->m_transformedPoints
[ i
].transform( matrix
);
1665 class Okular::HighlightAnnotationPrivate
: public Okular::AnnotationPrivate
1668 HighlightAnnotationPrivate()
1669 : AnnotationPrivate(), m_highlightType( HighlightAnnotation::Highlight
)
1673 virtual void transform( const QMatrix
&matrix
);
1674 virtual void baseTransform( const QMatrix
&matrix
);
1676 HighlightAnnotation::HighlightType m_highlightType
;
1677 QList
< HighlightAnnotation::Quad
> m_highlightQuads
;
1680 HighlightAnnotation::HighlightAnnotation()
1681 : Annotation( *new HighlightAnnotationPrivate() )
1685 HighlightAnnotation::HighlightAnnotation( const QDomNode
& node
)
1686 : Annotation( *new HighlightAnnotationPrivate(), node
)
1688 Q_D( HighlightAnnotation
);
1689 // loop through the whole children looking for a 'hl' element
1690 QDomNode subNode
= node
.firstChild();
1691 while( subNode
.isElement() )
1693 QDomElement e
= subNode
.toElement();
1694 subNode
= subNode
.nextSibling();
1695 if ( e
.tagName() != "hl" )
1698 // parse the attributes
1699 if ( e
.hasAttribute( "type" ) )
1700 d
->m_highlightType
= (HighlightAnnotation::HighlightType
)e
.attribute( "type" ).toInt();
1702 // parse all 'quad' subnodes
1703 QDomNode quadNode
= e
.firstChild();
1704 for ( ; quadNode
.isElement(); quadNode
= quadNode
.nextSibling() )
1706 QDomElement qe
= quadNode
.toElement();
1707 if ( qe
.tagName() != "quad" )
1710 HighlightAnnotation::Quad q
;
1711 q
.setPoint( NormalizedPoint( qe
.attribute( "ax", "0.0" ).toDouble(), qe
.attribute( "ay", "0.0" ).toDouble() ), 0 );
1712 q
.setPoint( NormalizedPoint( qe
.attribute( "bx", "0.0" ).toDouble(), qe
.attribute( "by", "0.0" ).toDouble() ), 1 );
1713 q
.setPoint( NormalizedPoint( qe
.attribute( "cx", "0.0" ).toDouble(), qe
.attribute( "cy", "0.0" ).toDouble() ), 2 );
1714 q
.setPoint( NormalizedPoint( qe
.attribute( "dx", "0.0" ).toDouble(), qe
.attribute( "dy", "0.0" ).toDouble() ), 3 );
1715 q
.setCapStart( qe
.hasAttribute( "start" ) );
1716 q
.setCapEnd( qe
.hasAttribute( "end" ) );
1717 q
.setFeather( qe
.attribute( "feather", "0.1" ).toDouble() );
1719 q
.transform( QMatrix() );
1721 d
->m_highlightQuads
.append( q
);
1729 HighlightAnnotation::~HighlightAnnotation()
1733 void HighlightAnnotation::setHighlightType( HighlightType type
)
1735 Q_D( HighlightAnnotation
);
1736 d
->m_highlightType
= type
;
1739 HighlightAnnotation::HighlightType
HighlightAnnotation::highlightType() const
1741 Q_D( const HighlightAnnotation
);
1742 return d
->m_highlightType
;
1745 QList
< HighlightAnnotation::Quad
> & HighlightAnnotation::highlightQuads()
1747 Q_D( HighlightAnnotation
);
1748 return d
->m_highlightQuads
;
1751 void HighlightAnnotation::store( QDomNode
& node
, QDomDocument
& document
) const
1753 Q_D( const HighlightAnnotation
);
1754 // recurse to parent objects storing properties
1755 Annotation::store( node
, document
);
1757 // create [hl] element
1758 QDomElement hlElement
= document
.createElement( "hl" );
1759 node
.appendChild( hlElement
);
1761 // append the optional attributes
1762 if ( d
->m_highlightType
!= Highlight
)
1763 hlElement
.setAttribute( "type", (int)d
->m_highlightType
);
1764 if ( d
->m_highlightQuads
.count() < 1 )
1766 // append highlight quads, all children describe quads
1767 QList
< Quad
>::const_iterator it
= d
->m_highlightQuads
.begin(), end
= d
->m_highlightQuads
.end();
1768 for ( ; it
!= end
; ++it
)
1770 QDomElement quadElement
= document
.createElement( "quad" );
1771 hlElement
.appendChild( quadElement
);
1772 const Quad
& q
= *it
;
1773 quadElement
.setAttribute( "ax", q
.point( 0 ).x
);
1774 quadElement
.setAttribute( "ay", q
.point( 0 ).y
);
1775 quadElement
.setAttribute( "bx", q
.point( 1 ).x
);
1776 quadElement
.setAttribute( "by", q
.point( 1 ).y
);
1777 quadElement
.setAttribute( "cx", q
.point( 2 ).x
);
1778 quadElement
.setAttribute( "cy", q
.point( 2 ).y
);
1779 quadElement
.setAttribute( "dx", q
.point( 3 ).x
);
1780 quadElement
.setAttribute( "dy", q
.point( 3 ).y
);
1782 quadElement
.setAttribute( "start", 1 );
1784 quadElement
.setAttribute( "end", 1 );
1785 quadElement
.setAttribute( "feather", q
.feather() );
1789 Annotation::SubType
HighlightAnnotation::subType() const
1794 void HighlightAnnotationPrivate::transform( const QMatrix
&matrix
)
1796 AnnotationPrivate::transform( matrix
);
1798 QMutableListIterator
<HighlightAnnotation::Quad
> it( m_highlightQuads
);
1799 while ( it
.hasNext() )
1800 it
.next().transform( matrix
);
1803 void HighlightAnnotationPrivate::baseTransform( const QMatrix
&matrix
)
1805 AnnotationPrivate::baseTransform( matrix
);
1807 QMutableListIterator
<HighlightAnnotation::Quad
> it( m_highlightQuads
);
1808 while ( it
.hasNext() )
1809 it
.next().transform( matrix
);
1812 /** StampAnnotation [Annotation] */
1814 class Okular::StampAnnotationPrivate
: public Okular::AnnotationPrivate
1817 StampAnnotationPrivate()
1818 : AnnotationPrivate(), m_stampIconName( "Draft" )
1822 QString m_stampIconName
;
1825 StampAnnotation::StampAnnotation()
1826 : Annotation( *new StampAnnotationPrivate() )
1830 StampAnnotation::StampAnnotation( const QDomNode
& node
)
1831 : Annotation( *new StampAnnotationPrivate(), node
)
1833 Q_D( StampAnnotation
);
1834 // loop through the whole children looking for a 'stamp' element
1835 QDomNode subNode
= node
.firstChild();
1836 while( subNode
.isElement() )
1838 QDomElement e
= subNode
.toElement();
1839 subNode
= subNode
.nextSibling();
1840 if ( e
.tagName() != "stamp" )
1843 // parse the attributes
1844 if ( e
.hasAttribute( "icon" ) )
1845 d
->m_stampIconName
= e
.attribute( "icon" );
1852 StampAnnotation::~StampAnnotation()
1856 void StampAnnotation::setStampIconName( const QString
&name
)
1858 Q_D( StampAnnotation
);
1859 d
->m_stampIconName
= name
;
1862 QString
StampAnnotation::stampIconName() const
1864 Q_D( const StampAnnotation
);
1865 return d
->m_stampIconName
;
1868 Annotation::SubType
StampAnnotation::subType() const
1873 void StampAnnotation::store( QDomNode
& node
, QDomDocument
& document
) const
1875 Q_D( const StampAnnotation
);
1876 // recurse to parent objects storing properties
1877 Annotation::store( node
, document
);
1879 // create [stamp] element
1880 QDomElement stampElement
= document
.createElement( "stamp" );
1881 node
.appendChild( stampElement
);
1883 // append the optional attributes
1884 if ( d
->m_stampIconName
!= "Draft" )
1885 stampElement
.setAttribute( "icon", d
->m_stampIconName
);
1888 /** InkAnnotation [Annotation] */
1890 class Okular::InkAnnotationPrivate
: public Okular::AnnotationPrivate
1893 InkAnnotationPrivate()
1894 : AnnotationPrivate()
1898 virtual void transform( const QMatrix
&matrix
);
1899 virtual void baseTransform( const QMatrix
&matrix
);
1900 virtual void resetTransformation();
1901 virtual void translate( const NormalizedPoint
&coord
);
1903 QList
< QLinkedList
<NormalizedPoint
> > m_inkPaths
;
1904 QList
< QLinkedList
<NormalizedPoint
> > m_transformedInkPaths
;
1907 InkAnnotation::InkAnnotation()
1908 : Annotation( *new InkAnnotationPrivate() )
1912 InkAnnotation::InkAnnotation( const QDomNode
& node
)
1913 : Annotation( *new InkAnnotationPrivate(), node
)
1915 Q_D( InkAnnotation
);
1916 // loop through the whole children looking for a 'ink' element
1917 QDomNode subNode
= node
.firstChild();
1918 while( subNode
.isElement() )
1920 QDomElement e
= subNode
.toElement();
1921 subNode
= subNode
.nextSibling();
1922 if ( e
.tagName() != "ink" )
1925 // parse the 'path' subnodes
1926 QDomNode pathNode
= e
.firstChild();
1927 while ( pathNode
.isElement() )
1929 QDomElement pathElement
= pathNode
.toElement();
1930 pathNode
= pathNode
.nextSibling();
1932 if ( pathElement
.tagName() != "path" )
1935 // build each path parsing 'point' subnodes
1936 QLinkedList
<NormalizedPoint
> path
;
1937 QDomNode pointNode
= pathElement
.firstChild();
1938 while ( pointNode
.isElement() )
1940 QDomElement pointElement
= pointNode
.toElement();
1941 pointNode
= pointNode
.nextSibling();
1943 if ( pointElement
.tagName() != "point" )
1947 p
.x
= pointElement
.attribute( "x", "0.0" ).toDouble();
1948 p
.y
= pointElement
.attribute( "y", "0.0" ).toDouble();
1952 // add the path to the path list if it contains at least 2 nodes
1953 if ( path
.count() >= 2 )
1954 d
->m_inkPaths
.append( path
);
1961 d
->m_transformedInkPaths
= d
->m_inkPaths
;
1964 InkAnnotation::~InkAnnotation()
1968 void InkAnnotation::setInkPaths( const QList
< QLinkedList
<NormalizedPoint
> > &paths
)
1970 Q_D( InkAnnotation
);
1971 d
->m_inkPaths
= paths
;
1974 QList
< QLinkedList
<NormalizedPoint
> > InkAnnotation::inkPaths() const
1976 Q_D( const InkAnnotation
);
1977 return d
->m_inkPaths
;
1980 QList
< QLinkedList
<NormalizedPoint
> > InkAnnotation::transformedInkPaths() const
1982 Q_D( const InkAnnotation
);
1983 return d
->m_transformedInkPaths
;
1986 Annotation::SubType
InkAnnotation::subType() const
1991 void InkAnnotation::store( QDomNode
& node
, QDomDocument
& document
) const
1993 Q_D( const InkAnnotation
);
1994 // recurse to parent objects storing properties
1995 Annotation::store( node
, document
);
1997 // create [ink] element
1998 QDomElement inkElement
= document
.createElement( "ink" );
1999 node
.appendChild( inkElement
);
2001 // append the optional attributes
2002 if ( d
->m_inkPaths
.count() < 1 )
2005 QList
< QLinkedList
<NormalizedPoint
> >::const_iterator pIt
= d
->m_inkPaths
.begin(), pEnd
= d
->m_inkPaths
.end();
2006 for ( ; pIt
!= pEnd
; ++pIt
)
2008 QDomElement pathElement
= document
.createElement( "path" );
2009 inkElement
.appendChild( pathElement
);
2010 const QLinkedList
<NormalizedPoint
> & path
= *pIt
;
2011 QLinkedList
<NormalizedPoint
>::const_iterator iIt
= path
.begin(), iEnd
= path
.end();
2012 for ( ; iIt
!= iEnd
; ++iIt
)
2014 const NormalizedPoint
& point
= *iIt
;
2015 QDomElement pointElement
= document
.createElement( "point" );
2016 pathElement
.appendChild( pointElement
);
2017 pointElement
.setAttribute( "x", point
.x
);
2018 pointElement
.setAttribute( "y", point
.y
);
2023 void InkAnnotationPrivate::transform( const QMatrix
&matrix
)
2025 AnnotationPrivate::transform( matrix
);
2027 for ( int i
= 0; i
< m_transformedInkPaths
.count(); ++i
)
2029 QMutableLinkedListIterator
<NormalizedPoint
> it( m_transformedInkPaths
[ i
] );
2030 while ( it
.hasNext() )
2031 it
.next().transform( matrix
);
2035 void InkAnnotationPrivate::baseTransform( const QMatrix
&matrix
)
2037 AnnotationPrivate::baseTransform( matrix
);
2039 for ( int i
= 0; i
< m_inkPaths
.count(); ++i
)
2041 QMutableLinkedListIterator
<NormalizedPoint
> it( m_inkPaths
[ i
] );
2042 while ( it
.hasNext() )
2043 it
.next().transform( matrix
);
2047 void InkAnnotationPrivate::resetTransformation()
2049 AnnotationPrivate::resetTransformation();
2051 m_transformedInkPaths
= m_inkPaths
;
2054 void InkAnnotationPrivate::translate( const NormalizedPoint
&coord
)
2056 AnnotationPrivate::translate( coord
);
2058 for ( int i
= 0; i
< m_inkPaths
.count(); ++i
)
2060 QMutableLinkedListIterator
<NormalizedPoint
> it( m_inkPaths
[ i
] );
2061 while ( it
.hasNext() )
2063 NormalizedPoint
& p
= it
.next();
2064 p
.x
= p
.x
+ coord
.x
;
2065 p
.y
= p
.y
+ coord
.y
;
2070 /** CaretAnnotation [Annotation] */
2072 class Okular::CaretAnnotationPrivate
: public Okular::AnnotationPrivate
2075 CaretAnnotationPrivate()
2076 : AnnotationPrivate(), m_symbol( CaretAnnotation::None
)
2080 CaretAnnotation::CaretSymbol m_symbol
;
2083 static QString
caretSymbolToString( CaretAnnotation::CaretSymbol symbol
)
2087 case CaretAnnotation::None
:
2088 return QString::fromLatin1( "None" );
2089 case CaretAnnotation::P
:
2090 return QString::fromLatin1( "P" );
2095 static CaretAnnotation::CaretSymbol
caretSymbolFromString( const QString
&symbol
)
2097 if ( symbol
== QLatin1String( "None" ) )
2098 return CaretAnnotation::None
;
2099 else if ( symbol
== QLatin1String( "P" ) )
2100 return CaretAnnotation::P
;
2101 return CaretAnnotation::None
;
2104 CaretAnnotation::CaretAnnotation()
2105 : Annotation( *new CaretAnnotationPrivate() )
2109 CaretAnnotation::CaretAnnotation( const QDomNode
& node
)
2110 : Annotation( *new CaretAnnotationPrivate(), node
)
2112 Q_D( CaretAnnotation
);
2113 // loop through the whole children looking for a 'caret' element
2114 QDomNode subNode
= node
.firstChild();
2115 while( subNode
.isElement() )
2117 QDomElement e
= subNode
.toElement();
2118 subNode
= subNode
.nextSibling();
2119 if ( e
.tagName() != "caret" )
2122 // parse the attributes
2123 if ( e
.hasAttribute( "symbol" ) )
2124 d
->m_symbol
= caretSymbolFromString( e
.attribute( "symbol" ) );
2131 CaretAnnotation::~CaretAnnotation()
2135 void CaretAnnotation::setCaretSymbol( CaretAnnotation::CaretSymbol symbol
)
2137 Q_D( CaretAnnotation
);
2138 d
->m_symbol
= symbol
;
2141 CaretAnnotation::CaretSymbol
CaretAnnotation::caretSymbol() const
2143 Q_D( const CaretAnnotation
);
2147 Annotation::SubType
CaretAnnotation::subType() const
2152 void CaretAnnotation::store( QDomNode
& node
, QDomDocument
& document
) const
2154 Q_D( const CaretAnnotation
);
2155 // recurse to parent objects storing properties
2156 Annotation::store( node
, document
);
2158 // create [caret] element
2159 QDomElement caretElement
= document
.createElement( "caret" );
2160 node
.appendChild( caretElement
);
2162 // append the optional attributes
2163 if ( d
->m_symbol
!= None
)
2164 caretElement
.setAttribute( "symbol", caretSymbolToString( d
->m_symbol
) );
2167 /** FileAttachmentAnnotation [Annotation] */
2169 class Okular::FileAttachmentAnnotationPrivate
: public Okular::AnnotationPrivate
2172 FileAttachmentAnnotationPrivate()
2173 : AnnotationPrivate(), icon( "PushPin" ), embfile( 0 )
2176 ~FileAttachmentAnnotationPrivate()
2183 EmbeddedFile
*embfile
;
2186 FileAttachmentAnnotation::FileAttachmentAnnotation()
2187 : Annotation( *new FileAttachmentAnnotationPrivate() )
2191 FileAttachmentAnnotation::FileAttachmentAnnotation( const QDomNode
& node
)
2192 : Annotation( *new FileAttachmentAnnotationPrivate(), node
)
2194 // loop through the whole children looking for a 'fileattachment' element
2195 QDomNode subNode
= node
.firstChild();
2196 while( subNode
.isElement() )
2198 QDomElement e
= subNode
.toElement();
2199 subNode
= subNode
.nextSibling();
2200 if ( e
.tagName() != "fileattachment" )
2208 FileAttachmentAnnotation::~FileAttachmentAnnotation()
2212 void FileAttachmentAnnotation::store( QDomNode
& node
, QDomDocument
& document
) const
2214 // recurse to parent objects storing properties
2215 Annotation::store( node
, document
);
2217 // create [fileattachment] element
2218 QDomElement fileAttachmentElement
= document
.createElement( "fileattachment" );
2219 node
.appendChild( fileAttachmentElement
);
2222 Annotation::SubType
FileAttachmentAnnotation::subType() const
2224 return AFileAttachment
;
2227 QString
FileAttachmentAnnotation::fileIconName() const
2229 Q_D( const FileAttachmentAnnotation
);
2233 void FileAttachmentAnnotation::setFileIconName( const QString
&icon
)
2235 Q_D( FileAttachmentAnnotation
);
2239 EmbeddedFile
* FileAttachmentAnnotation::embeddedFile() const
2241 Q_D( const FileAttachmentAnnotation
);
2245 void FileAttachmentAnnotation::setEmbeddedFile( EmbeddedFile
*ef
)
2247 Q_D( FileAttachmentAnnotation
);
2251 /** SoundAnnotation [Annotation] */
2253 class Okular::SoundAnnotationPrivate
: public Okular::AnnotationPrivate
2256 SoundAnnotationPrivate()
2257 : AnnotationPrivate(), icon( "Speaker" ), sound( 0 )
2260 ~SoundAnnotationPrivate()
2270 SoundAnnotation::SoundAnnotation()
2271 : Annotation( *new SoundAnnotationPrivate() )
2275 SoundAnnotation::SoundAnnotation( const QDomNode
& node
)
2276 : Annotation( *new SoundAnnotationPrivate(), node
)
2278 // loop through the whole children looking for a 'sound' element
2279 QDomNode subNode
= node
.firstChild();
2280 while( subNode
.isElement() )
2282 QDomElement e
= subNode
.toElement();
2283 subNode
= subNode
.nextSibling();
2284 if ( e
.tagName() != "sound" )
2292 SoundAnnotation::~SoundAnnotation()
2296 void SoundAnnotation::store( QDomNode
& node
, QDomDocument
& document
) const
2298 // recurse to parent objects storing properties
2299 Annotation::store( node
, document
);
2301 // create [sound] element
2302 QDomElement soundElement
= document
.createElement( "sound" );
2303 node
.appendChild( soundElement
);
2306 Annotation::SubType
SoundAnnotation::subType() const
2311 QString
SoundAnnotation::soundIconName() const
2313 Q_D( const SoundAnnotation
);
2317 void SoundAnnotation::setSoundIconName( const QString
&icon
)
2319 Q_D( SoundAnnotation
);
2323 Sound
* SoundAnnotation::sound() const
2325 Q_D( const SoundAnnotation
);
2329 void SoundAnnotation::setSound( Sound
*s
)
2331 Q_D( SoundAnnotation
);
2335 /** MovieAnnotation [Annotation] */
2337 class Okular::MovieAnnotationPrivate
: public Okular::AnnotationPrivate
2340 MovieAnnotationPrivate()
2341 : AnnotationPrivate(), movie( 0 )
2344 ~MovieAnnotationPrivate()
2353 MovieAnnotation::MovieAnnotation()
2354 : Annotation( *new MovieAnnotationPrivate() )
2358 MovieAnnotation::MovieAnnotation( const QDomNode
& node
)
2359 : Annotation( *new MovieAnnotationPrivate(), node
)
2361 // loop through the whole children looking for a 'movie' element
2362 QDomNode subNode
= node
.firstChild();
2363 while( subNode
.isElement() )
2365 QDomElement e
= subNode
.toElement();
2366 subNode
= subNode
.nextSibling();
2367 if ( e
.tagName() != "movie" )
2375 MovieAnnotation::~MovieAnnotation()
2379 void MovieAnnotation::store( QDomNode
& node
, QDomDocument
& document
) const
2381 // recurse to parent objects storing properties
2382 Annotation::store( node
, document
);
2384 // create [movie] element
2385 QDomElement movieElement
= document
.createElement( "movie" );
2386 node
.appendChild( movieElement
);
2389 Annotation::SubType
MovieAnnotation::subType() const
2394 Movie
* MovieAnnotation::movie() const
2396 Q_D( const MovieAnnotation
);
2400 void MovieAnnotation::setMovie( Movie
*movie
)
2402 Q_D( MovieAnnotation
);