1 /* poppler-annotation.cc: qt interface to poppler
2 * Copyright (C) 2006, 2009 Albert Astals Cid <aacid@kde.org>
3 * Copyright (C) 2006, 2008, 2010 Pino Toscano <pino@kde.org>
4 * Adapting code from
5 * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
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.
20 */
21
22 // qt/kde includes
23 #include <QtXml/QDomElement>
24 #include <QtGui/QColor>
25
26 // local includes
27 #include "poppler-annotation.h"
28 #include "poppler-link.h"
29 #include "poppler-qt4.h"
30 #include "poppler-annotation-private.h"
31
32 // poppler includes
33 #include <Page.h>
34 #include <Annot.h>
35
36 namespace Poppler {
37
38 //BEGIN AnnotationUtils implementation
createAnnotation(const QDomElement & annElement)39 Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement )
40 {
41 // safety check on annotation element
42 if ( !annElement.hasAttribute( "type" ) )
43 return 0;
44
45 // build annotation of given type
46 Annotation * annotation = 0;
47 int typeNumber = annElement.attribute( "type" ).toInt();
48 switch ( typeNumber )
49 {
50 case Annotation::AText:
51 annotation = new TextAnnotation( annElement );
52 break;
53 case Annotation::ALine:
54 annotation = new LineAnnotation( annElement );
55 break;
56 case Annotation::AGeom:
57 annotation = new GeomAnnotation( annElement );
58 break;
59 case Annotation::AHighlight:
60 annotation = new HighlightAnnotation( annElement );
61 break;
62 case Annotation::AStamp:
63 annotation = new StampAnnotation( annElement );
64 break;
65 case Annotation::AInk:
66 annotation = new InkAnnotation( annElement );
67 break;
68 case Annotation::ACaret:
69 annotation = new CaretAnnotation( annElement );
70 break;
71 }
72
73 // return created annotation
74 return annotation;
75 }
76
storeAnnotation(const Annotation * ann,QDomElement & annElement,QDomDocument & document)77 void AnnotationUtils::storeAnnotation( const Annotation * ann, QDomElement & annElement,
78 QDomDocument & document )
79 {
80 // save annotation's type as element's attribute
81 annElement.setAttribute( "type", (uint)ann->subType() );
82
83 // append all annotation data as children of this node
84 ann->store( annElement, document );
85 }
86
findChildElement(const QDomNode & parentNode,const QString & name)87 QDomElement AnnotationUtils::findChildElement( const QDomNode & parentNode,
88 const QString & name )
89 {
90 // loop through the whole children and return a 'name' named element
91 QDomNode subNode = parentNode.firstChild();
92 while( subNode.isElement() )
93 {
94 QDomElement element = subNode.toElement();
95 if ( element.tagName() == name )
96 return element;
97 subNode = subNode.nextSibling();
98 }
99 // if the name can't be found, return a dummy null element
100 return QDomElement();
101 }
102 //END AnnotationUtils implementation
103
104
105 //BEGIN Annotation implementation
AnnotationPrivate()106 AnnotationPrivate::AnnotationPrivate()
107 : flags( 0 )
108 {
109 }
110
~AnnotationPrivate()111 AnnotationPrivate::~AnnotationPrivate()
112 {
113 }
114
115
Style()116 Annotation::Style::Style()
117 : opacity( 1.0 ), width( 1.0 ), style( Solid ), xCorners( 0.0 ),
118 yCorners( 0.0 ), marks( 3 ), spaces( 0 ), effect( NoEffect ),
119 effectIntensity( 1.0 ) {}
120
Window()121 Annotation::Window::Window()
122 : flags( -1 ), width( 0 ), height( 0 ) {}
123
Revision()124 Annotation::Revision::Revision()
125 : annotation( 0 ), scope( Reply ), type( None ) {}
126
Annotation(AnnotationPrivate & dd)127 Annotation::Annotation( AnnotationPrivate &dd )
128 : d_ptr( &dd )
129 {
130 }
131
~Annotation()132 Annotation::~Annotation()
133 {
134 Q_D( Annotation );
135 // delete all children revisions
136 QLinkedList< Annotation::Revision >::iterator it = d->revisions.begin(), end = d->revisions.end();
137 for ( ; it != end; ++it )
138 delete (*it).annotation;
139
140 delete d_ptr;
141 }
142
Annotation(AnnotationPrivate & dd,const QDomNode & annNode)143 Annotation::Annotation( AnnotationPrivate &dd, const QDomNode &annNode )
144 : d_ptr( &dd )
145 {
146 Q_D( Annotation );
147 // get the [base] element of the annotation node
148 QDomElement e = AnnotationUtils::findChildElement( annNode, "base" );
149 if ( e.isNull() )
150 return;
151
152 // parse -contents- attributes
153 if ( e.hasAttribute( "author" ) )
154 d->author = e.attribute( "author" );
155 if ( e.hasAttribute( "contents" ) )
156 d->contents = e.attribute( "contents" );
157 if ( e.hasAttribute( "uniqueName" ) )
158 d->uniqueName = e.attribute( "uniqueName" );
159 if ( e.hasAttribute( "modifyDate" ) )
160 d->modDate = QDateTime::fromString( e.attribute( "modifyDate" ) );
161 if ( e.hasAttribute( "creationDate" ) )
162 d->creationDate = QDateTime::fromString( e.attribute( "creationDate" ) );
163
164 // parse -other- attributes
165 if ( e.hasAttribute( "flags" ) )
166 d->flags = e.attribute( "flags" ).toInt();
167 if ( e.hasAttribute( "color" ) )
168 style.color = QColor( e.attribute( "color" ) );
169 if ( e.hasAttribute( "opacity" ) )
170 style.opacity = e.attribute( "opacity" ).toDouble();
171
172 // parse -the-subnodes- (describing Style, Window, Revision(s) structures)
173 // Note: all subnodes if present must be 'attributes complete'
174 QDomNode eSubNode = e.firstChild();
175 while ( eSubNode.isElement() )
176 {
177 QDomElement ee = eSubNode.toElement();
178 eSubNode = eSubNode.nextSibling();
179
180 // parse boundary
181 if ( ee.tagName() == "boundary" )
182 {
183 d->boundary.setLeft(ee.attribute( "l" ).toDouble());
184 d->boundary.setTop(ee.attribute( "t" ).toDouble());
185 d->boundary.setRight(ee.attribute( "r" ).toDouble());
186 d->boundary.setBottom(ee.attribute( "b" ).toDouble());
187 }
188 // parse penStyle if not default
189 else if ( ee.tagName() == "penStyle" )
190 {
191 style.width = ee.attribute( "width" ).toDouble();
192 style.style = (LineStyle)ee.attribute( "style" ).toInt();
193 style.xCorners = ee.attribute( "xcr" ).toDouble();
194 style.yCorners = ee.attribute( "ycr" ).toDouble();
195 style.marks = ee.attribute( "marks" ).toInt();
196 style.spaces = ee.attribute( "spaces" ).toInt();
197 }
198 // parse effectStyle if not default
199 else if ( ee.tagName() == "penEffect" )
200 {
201 style.effect = (LineEffect)ee.attribute( "effect" ).toInt();
202 style.effectIntensity = ee.attribute( "intensity" ).toDouble();
203 }
204 // parse window if present
205 else if ( ee.tagName() == "window" )
206 {
207 window.flags = ee.attribute( "flags" ).toInt();
208 window.topLeft.setX(ee.attribute( "top" ).toDouble());
209 window.topLeft.setY(ee.attribute( "left" ).toDouble());
210 window.width = ee.attribute( "width" ).toInt();
211 window.height = ee.attribute( "height" ).toInt();
212 window.title = ee.attribute( "title" );
213 window.summary = ee.attribute( "summary" );
214 // parse window subnodes
215 QDomNode winNode = ee.firstChild();
216 for ( ; winNode.isElement(); winNode = winNode.nextSibling() )
217 {
218 QDomElement winElement = winNode.toElement();
219 if ( winElement.tagName() == "text" )
220 window.text = winElement.firstChild().toCDATASection().data();
221 }
222 }
223 }
224
225 // get the [revisions] element of the annotation node
226 QDomNode revNode = annNode.firstChild();
227 for ( ; revNode.isElement(); revNode = revNode.nextSibling() )
228 {
229 QDomElement revElement = revNode.toElement();
230 if ( revElement.tagName() != "revision" )
231 continue;
232
233 // compile the Revision structure crating annotation
234 Revision rev;
235 rev.scope = (RevScope)revElement.attribute( "revScope" ).toInt();
236 rev.type = (RevType)revElement.attribute( "revType" ).toInt();
237 rev.annotation = AnnotationUtils::createAnnotation( revElement );
238
239 // if annotation is valid, add revision to internal list
240 if ( rev.annotation )
241 d->revisions.append( rev );
242 }
243 }
244
store(QDomNode & annNode,QDomDocument & document) const245 void Annotation::store( QDomNode & annNode, QDomDocument & document ) const
246 {
247 Q_D( const Annotation );
248 // create [base] element of the annotation node
249 QDomElement e = document.createElement( "base" );
250 annNode.appendChild( e );
251
252 // store -contents- attributes
253 if ( !d->author.isEmpty() )
254 e.setAttribute( "author", d->author );
255 if ( !d->contents.isEmpty() )
256 e.setAttribute( "contents", d->contents );
257 if ( !d->uniqueName.isEmpty() )
258 e.setAttribute( "uniqueName", d->uniqueName );
259 if ( d->modDate.isValid() )
260 e.setAttribute( "modifyDate", d->modDate.toString() );
261 if ( d->creationDate.isValid() )
262 e.setAttribute( "creationDate", d->creationDate.toString() );
263
264 // store -other- attributes
265 if ( d->flags )
266 e.setAttribute( "flags", d->flags );
267 if ( style.color.isValid() && style.color != Qt::black )
268 e.setAttribute( "color", style.color.name() );
269 if ( style.opacity != 1.0 )
270 e.setAttribute( "opacity", QString::number( style.opacity ) );
271
272 // Sub-Node-1 - boundary
273 QDomElement bE = document.createElement( "boundary" );
274 e.appendChild( bE );
275 bE.setAttribute( "l", QString::number( (double)d->boundary.left() ) );
276 bE.setAttribute( "t", QString::number( (double)d->boundary.top() ) );
277 bE.setAttribute( "r", QString::number( (double)d->boundary.right() ) );
278 bE.setAttribute( "b", QString::number( (double)d->boundary.bottom() ) );
279
280 // Sub-Node-2 - penStyle
281 if ( style.width != 1 || style.style != Solid || style.xCorners != 0 ||
282 style.yCorners != 0.0 || style.marks != 3 || style.spaces != 0 )
283 {
284 QDomElement psE = document.createElement( "penStyle" );
285 e.appendChild( psE );
286 psE.setAttribute( "width", QString::number( style.width ) );
287 psE.setAttribute( "style", (int)style.style );
288 psE.setAttribute( "xcr", QString::number( style.xCorners ) );
289 psE.setAttribute( "ycr", QString::number( style.yCorners ) );
290 psE.setAttribute( "marks", style.marks );
291 psE.setAttribute( "spaces", style.spaces );
292 }
293
294 // Sub-Node-3 - penEffect
295 if ( style.effect != NoEffect || style.effectIntensity != 1.0 )
296 {
297 QDomElement peE = document.createElement( "penEffect" );
298 e.appendChild( peE );
299 peE.setAttribute( "effect", (int)style.effect );
300 peE.setAttribute( "intensity", QString::number( style.effectIntensity ) );
301 }
302
303 // Sub-Node-4 - window
304 if ( window.flags != -1 || !window.title.isEmpty() ||
305 !window.summary.isEmpty() || !window.text.isEmpty() )
306 {
307 QDomElement wE = document.createElement( "window" );
308 e.appendChild( wE );
309 wE.setAttribute( "flags", window.flags );
310 wE.setAttribute( "top", QString::number( window.topLeft.x() ) );
311 wE.setAttribute( "left", QString::number( window.topLeft.y() ) );
312 wE.setAttribute( "width", window.width );
313 wE.setAttribute( "height", window.height );
314 wE.setAttribute( "title", window.title );
315 wE.setAttribute( "summary", window.summary );
316 // store window.text as a subnode, because we need escaped data
317 if ( !window.text.isEmpty() )
318 {
319 QDomElement escapedText = document.createElement( "text" );
320 wE.appendChild( escapedText );
321 QDomCDATASection textCData = document.createCDATASection( window.text );
322 escapedText.appendChild( textCData );
323 }
324 }
325
326 // create [revision] element of the annotation node (if any)
327 if ( d->revisions.isEmpty() )
328 return;
329
330 // add all revisions as children of revisions element
331 QLinkedList< Revision >::const_iterator it = d->revisions.begin(), end = d->revisions.end();
332 for ( ; it != end; ++it )
333 {
334 // create revision element
335 const Revision & revision = *it;
336 QDomElement r = document.createElement( "revision" );
337 annNode.appendChild( r );
338 // set element attributes
339 r.setAttribute( "revScope", (int)revision.scope );
340 r.setAttribute( "revType", (int)revision.type );
341 // use revision as the annotation element, so fill it up
342 AnnotationUtils::storeAnnotation( revision.annotation, r, document );
343 }
344 }
345
author() const346 QString Annotation::author() const
347 {
348 Q_D( const Annotation );
349 return d->author;
350 }
351
setAuthor(const QString & author)352 void Annotation::setAuthor( const QString &author )
353 {
354 Q_D( Annotation );
355 d->author = author;
356 }
357
contents() const358 QString Annotation::contents() const
359 {
360 Q_D( const Annotation );
361 return d->contents;
362 }
363
setContents(const QString & contents)364 void Annotation::setContents( const QString &contents )
365 {
366 Q_D( Annotation );
367 d->contents = contents;
368 }
369
uniqueName() const370 QString Annotation::uniqueName() const
371 {
372 Q_D( const Annotation );
373 return d->uniqueName;
374 }
375
setUniqueName(const QString & uniqueName)376 void Annotation::setUniqueName( const QString &uniqueName )
377 {
378 Q_D( Annotation );
379 d->uniqueName = uniqueName;
380 }
381
modificationDate() const382 QDateTime Annotation::modificationDate() const
383 {
384 Q_D( const Annotation );
385 return d->modDate;
386 }
387
setModificationDate(const QDateTime & date)388 void Annotation::setModificationDate( const QDateTime &date )
389 {
390 Q_D( Annotation );
391 d->modDate = date;
392 }
393
creationDate() const394 QDateTime Annotation::creationDate() const
395 {
396 Q_D( const Annotation );
397 return d->creationDate;
398 }
399
setCreationDate(const QDateTime & date)400 void Annotation::setCreationDate( const QDateTime &date )
401 {
402 Q_D( Annotation );
403 d->creationDate = date;
404 }
405
flags() const406 int Annotation::flags() const
407 {
408 Q_D( const Annotation );
409 return d->flags;
410 }
411
setFlags(int flags)412 void Annotation::setFlags( int flags )
413 {
414 Q_D( Annotation );
415 d->flags = flags;
416 }
417
boundary() const418 QRectF Annotation::boundary() const
419 {
420 Q_D( const Annotation );
421 return d->boundary;
422 }
423
setBoundary(const QRectF & boundary)424 void Annotation::setBoundary( const QRectF &boundary )
425 {
426 Q_D( Annotation );
427 d->boundary = boundary;
428 }
429
revisions()430 QLinkedList< Annotation::Revision >& Annotation::revisions()
431 {
432 Q_D( Annotation );
433 return d->revisions;
434 }
435
revisions() const436 const QLinkedList< Annotation::Revision >& Annotation::revisions() const
437 {
438 Q_D( const Annotation );
439 return d->revisions;
440 }
441
442 //END AnnotationUtils implementation
443
444
445 /** TextAnnotation [Annotation] */
446 class TextAnnotationPrivate : public AnnotationPrivate
447 {
448 public:
449 TextAnnotationPrivate();
450
451 // data fields
452 TextAnnotation::TextType textType;
453 QString textIcon;
454 QFont textFont;
455 int inplaceAlign; // 0:left, 1:center, 2:right
456 QString inplaceText; // overrides contents
457 QPointF inplaceCallout[3];
458 TextAnnotation::InplaceIntent inplaceIntent;
459 };
460
TextAnnotationPrivate()461 TextAnnotationPrivate::TextAnnotationPrivate()
462 : AnnotationPrivate(), textType( TextAnnotation::Linked ),
463 textIcon( "Note" ), inplaceAlign( 0 ),
464 inplaceIntent( TextAnnotation::Unknown )
465 {
466 }
467
TextAnnotation()468 TextAnnotation::TextAnnotation()
469 : Annotation( *new TextAnnotationPrivate() )
470 {}
471
TextAnnotation(const QDomNode & node)472 TextAnnotation::TextAnnotation( const QDomNode & node )
473 : Annotation( *new TextAnnotationPrivate, node )
474 {
475 Q_D( TextAnnotation );
476
477 // loop through the whole children looking for a 'text' element
478 QDomNode subNode = node.firstChild();
479 while( subNode.isElement() )
480 {
481 QDomElement e = subNode.toElement();
482 subNode = subNode.nextSibling();
483 if ( e.tagName() != "text" )
484 continue;
485
486 // parse the attributes
487 if ( e.hasAttribute( "type" ) )
488 d->textType = (TextAnnotation::TextType)e.attribute( "type" ).toInt();
489 if ( e.hasAttribute( "icon" ) )
490 d->textIcon = e.attribute( "icon" );
491 if ( e.hasAttribute( "font" ) )
492 d->textFont.fromString( e.attribute( "font" ) );
493 if ( e.hasAttribute( "align" ) )
494 d->inplaceAlign = e.attribute( "align" ).toInt();
495 if ( e.hasAttribute( "intent" ) )
496 d->inplaceIntent = (TextAnnotation::InplaceIntent)e.attribute( "intent" ).toInt();
497
498 // parse the subnodes
499 QDomNode eSubNode = e.firstChild();
500 while ( eSubNode.isElement() )
501 {
502 QDomElement ee = eSubNode.toElement();
503 eSubNode = eSubNode.nextSibling();
504
505 if ( ee.tagName() == "escapedText" )
506 {
507 d->inplaceText = ee.firstChild().toCDATASection().data();
508 }
509 else if ( ee.tagName() == "callout" )
510 {
511 d->inplaceCallout[0].setX(ee.attribute( "ax" ).toDouble());
512 d->inplaceCallout[0].setY(ee.attribute( "ay" ).toDouble());
513 d->inplaceCallout[1].setX(ee.attribute( "bx" ).toDouble());
514 d->inplaceCallout[1].setY(ee.attribute( "by" ).toDouble());
515 d->inplaceCallout[2].setX(ee.attribute( "cx" ).toDouble());
516 d->inplaceCallout[2].setY(ee.attribute( "cy" ).toDouble());
517 }
518 }
519
520 // loading complete
521 break;
522 }
523 }
524
~TextAnnotation()525 TextAnnotation::~TextAnnotation()
526 {
527 }
528
store(QDomNode & node,QDomDocument & document) const529 void TextAnnotation::store( QDomNode & node, QDomDocument & document ) const
530 {
531 Q_D( const TextAnnotation );
532
533 // recurse to parent objects storing properties
534 Annotation::store( node, document );
535
536 // create [text] element
537 QDomElement textElement = document.createElement( "text" );
538 node.appendChild( textElement );
539
540 // store the optional attributes
541 if ( d->textType != Linked )
542 textElement.setAttribute( "type", (int)d->textType );
543 if ( d->textIcon != "Comment" )
544 textElement.setAttribute( "icon", d->textIcon );
545 if ( d->inplaceAlign )
546 textElement.setAttribute( "align", d->inplaceAlign );
547 if ( d->inplaceIntent != Unknown )
548 textElement.setAttribute( "intent", (int)d->inplaceIntent );
549
550 textElement.setAttribute( "font", d->textFont.toString() );
551
552 // Sub-Node-1 - escapedText
553 if ( !d->inplaceText.isEmpty() )
554 {
555 QDomElement escapedText = document.createElement( "escapedText" );
556 textElement.appendChild( escapedText );
557 QDomCDATASection textCData = document.createCDATASection( d->inplaceText );
558 escapedText.appendChild( textCData );
559 }
560
561 // Sub-Node-2 - callout
562 if ( d->inplaceCallout[0].x() != 0.0 )
563 {
564 QDomElement calloutElement = document.createElement( "callout" );
565 textElement.appendChild( calloutElement );
566 calloutElement.setAttribute( "ax", QString::number( d->inplaceCallout[0].x() ) );
567 calloutElement.setAttribute( "ay", QString::number( d->inplaceCallout[0].y() ) );
568 calloutElement.setAttribute( "bx", QString::number( d->inplaceCallout[1].x() ) );
569 calloutElement.setAttribute( "by", QString::number( d->inplaceCallout[1].y() ) );
570 calloutElement.setAttribute( "cx", QString::number( d->inplaceCallout[2].x() ) );
571 calloutElement.setAttribute( "cy", QString::number( d->inplaceCallout[2].y() ) );
572 }
573 }
574
subType() const575 Annotation::SubType TextAnnotation::subType() const
576 {
577 return AText;
578 }
579
textType() const580 TextAnnotation::TextType TextAnnotation::textType() const
581 {
582 Q_D( const TextAnnotation );
583 return d->textType;
584 }
585
setTextType(TextAnnotation::TextType type)586 void TextAnnotation::setTextType( TextAnnotation::TextType type )
587 {
588 Q_D( TextAnnotation );
589 d->textType = type;
590 }
591
textIcon() const592 QString TextAnnotation::textIcon() const
593 {
594 Q_D( const TextAnnotation );
595 return d->textIcon;
596 }
597
setTextIcon(const QString & icon)598 void TextAnnotation::setTextIcon( const QString &icon )
599 {
600 Q_D( TextAnnotation );
601 d->textIcon = icon;
602 }
603
textFont() const604 QFont TextAnnotation::textFont() const
605 {
606 Q_D( const TextAnnotation );
607 return d->textFont;
608 }
609
setTextFont(const QFont & font)610 void TextAnnotation::setTextFont( const QFont &font )
611 {
612 Q_D( TextAnnotation );
613 d->textFont = font;
614 }
615
inplaceAlign() const616 int TextAnnotation::inplaceAlign() const
617 {
618 Q_D( const TextAnnotation );
619 return d->inplaceAlign;
620 }
621
setInplaceAlign(int align)622 void TextAnnotation::setInplaceAlign( int align )
623 {
624 Q_D( TextAnnotation );
625 d->inplaceAlign = align;
626 }
627
inplaceText() const628 QString TextAnnotation::inplaceText() const
629 {
630 Q_D( const TextAnnotation );
631 return d->inplaceText;
632 }
633
setInplaceText(const QString & text)634 void TextAnnotation::setInplaceText( const QString &text )
635 {
636 Q_D( TextAnnotation );
637 d->inplaceText = text;
638 }
639
calloutPoint(int id) const640 QPointF TextAnnotation::calloutPoint( int id ) const
641 {
642 if ( id < 0 || id >= 3 )
643 return QPointF();
644
645 Q_D( const TextAnnotation );
646 return d->inplaceCallout[id];
647 }
648
setCalloutPoint(int id,const QPointF & point)649 void TextAnnotation::setCalloutPoint( int id, const QPointF &point )
650 {
651 if ( id < 0 || id >= 3 )
652 return;
653
654 Q_D( TextAnnotation );
655 d->inplaceCallout[id] = point;
656 }
657
inplaceIntent() const658 TextAnnotation::InplaceIntent TextAnnotation::inplaceIntent() const
659 {
660 Q_D( const TextAnnotation );
661 return d->inplaceIntent;
662 }
663
setInplaceIntent(TextAnnotation::InplaceIntent intent)664 void TextAnnotation::setInplaceIntent( TextAnnotation::InplaceIntent intent )
665 {
666 Q_D( TextAnnotation );
667 d->inplaceIntent = intent;
668 }
669
670
671 /** LineAnnotation [Annotation] */
672 class LineAnnotationPrivate : public AnnotationPrivate
673 {
674 public:
675 LineAnnotationPrivate();
676
677 // data fields (note uses border for rendering style)
678 QLinkedList<QPointF> linePoints;
679 LineAnnotation::TermStyle lineStartStyle;
680 LineAnnotation::TermStyle lineEndStyle;
681 bool lineClosed : 1; // (if true draw close shape)
682 bool lineShowCaption : 1;
683 QColor lineInnerColor;
684 double lineLeadingFwdPt;
685 double lineLeadingBackPt;
686 LineAnnotation::LineIntent lineIntent;
687 };
688
LineAnnotationPrivate()689 LineAnnotationPrivate::LineAnnotationPrivate()
690 : AnnotationPrivate(), lineStartStyle( LineAnnotation::None ),
691 lineEndStyle( LineAnnotation::None ), lineClosed( false ),
692 lineShowCaption( false ), lineLeadingFwdPt( 0 ), lineLeadingBackPt( 0 ),
693 lineIntent( LineAnnotation::Unknown )
694 {
695 }
696
LineAnnotation()697 LineAnnotation::LineAnnotation()
698 : Annotation( *new LineAnnotationPrivate() )
699 {}
700
LineAnnotation(const QDomNode & node)701 LineAnnotation::LineAnnotation( const QDomNode & node )
702 : Annotation( *new LineAnnotationPrivate(), node )
703 {
704 Q_D( LineAnnotation );
705
706 // loop through the whole children looking for a 'line' element
707 QDomNode subNode = node.firstChild();
708 while( subNode.isElement() )
709 {
710 QDomElement e = subNode.toElement();
711 subNode = subNode.nextSibling();
712 if ( e.tagName() != "line" )
713 continue;
714
715 // parse the attributes
716 if ( e.hasAttribute( "startStyle" ) )
717 d->lineStartStyle = (LineAnnotation::TermStyle)e.attribute( "startStyle" ).toInt();
718 if ( e.hasAttribute( "endStyle" ) )
719 d->lineEndStyle = (LineAnnotation::TermStyle)e.attribute( "endStyle" ).toInt();
720 if ( e.hasAttribute( "closed" ) )
721 d->lineClosed = e.attribute( "closed" ).toInt();
722 if ( e.hasAttribute( "innerColor" ) )
723 d->lineInnerColor = QColor( e.attribute( "innerColor" ) );
724 if ( e.hasAttribute( "leadFwd" ) )
725 d->lineLeadingFwdPt = e.attribute( "leadFwd" ).toDouble();
726 if ( e.hasAttribute( "leadBack" ) )
727 d->lineLeadingBackPt = e.attribute( "leadBack" ).toDouble();
728 if ( e.hasAttribute( "showCaption" ) )
729 d->lineShowCaption = e.attribute( "showCaption" ).toInt();
730 if ( e.hasAttribute( "intent" ) )
731 d->lineIntent = (LineAnnotation::LineIntent)e.attribute( "intent" ).toInt();
732
733 // parse all 'point' subnodes
734 QDomNode pointNode = e.firstChild();
735 while ( pointNode.isElement() )
736 {
737 QDomElement pe = pointNode.toElement();
738 pointNode = pointNode.nextSibling();
739
740 if ( pe.tagName() != "point" )
741 continue;
742
743 QPointF p(pe.attribute( "x", "0.0" ).toDouble(), pe.attribute( "y", "0.0" ).toDouble());
744 d->linePoints.append( p );
745 }
746
747 // loading complete
748 break;
749 }
750 }
751
~LineAnnotation()752 LineAnnotation::~LineAnnotation()
753 {
754 }
755
store(QDomNode & node,QDomDocument & document) const756 void LineAnnotation::store( QDomNode & node, QDomDocument & document ) const
757 {
758 Q_D( const LineAnnotation );
759
760 // recurse to parent objects storing properties
761 Annotation::store( node, document );
762
763 // create [line] element
764 QDomElement lineElement = document.createElement( "line" );
765 node.appendChild( lineElement );
766
767 // store the attributes
768 if ( d->lineStartStyle != None )
769 lineElement.setAttribute( "startStyle", (int)d->lineStartStyle );
770 if ( d->lineEndStyle != None )
771 lineElement.setAttribute( "endStyle", (int)d->lineEndStyle );
772 if ( d->lineClosed )
773 lineElement.setAttribute( "closed", d->lineClosed );
774 if ( d->lineInnerColor.isValid() )
775 lineElement.setAttribute( "innerColor", d->lineInnerColor.name() );
776 if ( d->lineLeadingFwdPt != 0.0 )
777 lineElement.setAttribute( "leadFwd", QString::number( d->lineLeadingFwdPt ) );
778 if ( d->lineLeadingBackPt != 0.0 )
779 lineElement.setAttribute( "leadBack", QString::number( d->lineLeadingBackPt ) );
780 if ( d->lineShowCaption )
781 lineElement.setAttribute( "showCaption", d->lineShowCaption );
782 if ( d->lineIntent != Unknown )
783 lineElement.setAttribute( "intent", d->lineIntent );
784
785 // append the list of points
786 int points = d->linePoints.count();
787 if ( points > 1 )
788 {
789 QLinkedList<QPointF>::const_iterator it = d->linePoints.begin(), end = d->linePoints.end();
790 while ( it != end )
791 {
792 const QPointF & p = *it;
793 QDomElement pElement = document.createElement( "point" );
794 lineElement.appendChild( pElement );
795 pElement.setAttribute( "x", QString::number( p.x() ) );
796 pElement.setAttribute( "y", QString::number( p.y() ) );
797 ++it;
798 }
799 }
800 }
801
subType() const802 Annotation::SubType LineAnnotation::subType() const
803 {
804 return ALine;
805 }
806
linePoints() const807 QLinkedList<QPointF> LineAnnotation::linePoints() const
808 {
809 Q_D( const LineAnnotation );
810 return d->linePoints;
811 }
812
setLinePoints(const QLinkedList<QPointF> & points)813 void LineAnnotation::setLinePoints( const QLinkedList<QPointF> &points )
814 {
815 Q_D( LineAnnotation );
816 d->linePoints = points;
817 }
818
lineStartStyle() const819 LineAnnotation::TermStyle LineAnnotation::lineStartStyle() const
820 {
821 Q_D( const LineAnnotation );
822 return d->lineStartStyle;
823 }
824
setLineStartStyle(LineAnnotation::TermStyle style)825 void LineAnnotation::setLineStartStyle( LineAnnotation::TermStyle style )
826 {
827 Q_D( LineAnnotation );
828 d->lineStartStyle = style;
829 }
830
lineEndStyle() const831 LineAnnotation::TermStyle LineAnnotation::lineEndStyle() const
832 {
833 Q_D( const LineAnnotation );
834 return d->lineEndStyle;
835 }
836
setLineEndStyle(LineAnnotation::TermStyle style)837 void LineAnnotation::setLineEndStyle( LineAnnotation::TermStyle style )
838 {
839 Q_D( LineAnnotation );
840 d->lineEndStyle = style;
841 }
842
isLineClosed() const843 bool LineAnnotation::isLineClosed() const
844 {
845 Q_D( const LineAnnotation );
846 return d->lineClosed;
847 }
848
setLineClosed(bool closed)849 void LineAnnotation::setLineClosed( bool closed )
850 {
851 Q_D( LineAnnotation );
852 d->lineClosed = closed;
853 }
854
lineInnerColor() const855 QColor LineAnnotation::lineInnerColor() const
856 {
857 Q_D( const LineAnnotation );
858 return d->lineInnerColor;
859 }
860
setLineInnerColor(const QColor & color)861 void LineAnnotation::setLineInnerColor( const QColor &color )
862 {
863 Q_D( LineAnnotation );
864 d->lineInnerColor = color;
865 }
866
lineLeadingForwardPoint() const867 double LineAnnotation::lineLeadingForwardPoint() const
868 {
869 Q_D( const LineAnnotation );
870 return d->lineLeadingFwdPt;
871 }
872
setLineLeadingForwardPoint(double point)873 void LineAnnotation::setLineLeadingForwardPoint( double point )
874 {
875 Q_D( LineAnnotation );
876 d->lineLeadingFwdPt = point;
877 }
878
lineLeadingBackPoint() const879 double LineAnnotation::lineLeadingBackPoint() const
880 {
881 Q_D( const LineAnnotation );
882 return d->lineLeadingBackPt;
883 }
884
setLineLeadingBackPoint(double point)885 void LineAnnotation::setLineLeadingBackPoint( double point )
886 {
887 Q_D( LineAnnotation );
888 d->lineLeadingBackPt = point;
889 }
890
lineShowCaption() const891 bool LineAnnotation::lineShowCaption() const
892 {
893 Q_D( const LineAnnotation );
894 return d->lineShowCaption;
895 }
896
setLineShowCaption(bool show)897 void LineAnnotation::setLineShowCaption( bool show )
898 {
899 Q_D( LineAnnotation );
900 d->lineShowCaption = show;
901 }
902
lineIntent() const903 LineAnnotation::LineIntent LineAnnotation::lineIntent() const
904 {
905 Q_D( const LineAnnotation );
906 return d->lineIntent;
907 }
908
setLineIntent(LineAnnotation::LineIntent intent)909 void LineAnnotation::setLineIntent( LineAnnotation::LineIntent intent )
910 {
911 Q_D( LineAnnotation );
912 d->lineIntent = intent;
913 }
914
915
916 /** GeomAnnotation [Annotation] */
917 class GeomAnnotationPrivate : public AnnotationPrivate
918 {
919 public:
920 GeomAnnotationPrivate();
921
922 // data fields (note uses border for rendering style)
923 GeomAnnotation::GeomType geomType;
924 QColor geomInnerColor;
925 int geomWidthPt;
926 };
927
GeomAnnotationPrivate()928 GeomAnnotationPrivate::GeomAnnotationPrivate()
929 : AnnotationPrivate(), geomType( GeomAnnotation::InscribedSquare ),
930 geomWidthPt( 18 )
931 {
932 }
933
GeomAnnotation()934 GeomAnnotation::GeomAnnotation()
935 : Annotation( *new GeomAnnotationPrivate() )
936 {}
937
GeomAnnotation(const QDomNode & node)938 GeomAnnotation::GeomAnnotation( const QDomNode & node )
939 : Annotation( *new GeomAnnotationPrivate(), node )
940 {
941 Q_D( GeomAnnotation );
942
943 // loop through the whole children looking for a 'geom' element
944 QDomNode subNode = node.firstChild();
945 while( subNode.isElement() )
946 {
947 QDomElement e = subNode.toElement();
948 subNode = subNode.nextSibling();
949 if ( e.tagName() != "geom" )
950 continue;
951
952 // parse the attributes
953 if ( e.hasAttribute( "type" ) )
954 d->geomType = (GeomAnnotation::GeomType)e.attribute( "type" ).toInt();
955 if ( e.hasAttribute( "color" ) )
956 d->geomInnerColor = QColor( e.attribute( "color" ) );
957 if ( e.hasAttribute( "width" ) )
958 d->geomWidthPt = e.attribute( "width" ).toInt();
959
960 // loading complete
961 break;
962 }
963 }
964
~GeomAnnotation()965 GeomAnnotation::~GeomAnnotation()
966 {
967 }
968
store(QDomNode & node,QDomDocument & document) const969 void GeomAnnotation::store( QDomNode & node, QDomDocument & document ) const
970 {
971 Q_D( const GeomAnnotation );
972
973 // recurse to parent objects storing properties
974 Annotation::store( node, document );
975
976 // create [geom] element
977 QDomElement geomElement = document.createElement( "geom" );
978 node.appendChild( geomElement );
979
980 // append the optional attributes
981 if ( d->geomType != InscribedSquare )
982 geomElement.setAttribute( "type", (int)d->geomType );
983 if ( d->geomInnerColor.isValid() )
984 geomElement.setAttribute( "color", d->geomInnerColor.name() );
985 if ( d->geomWidthPt != 18 )
986 geomElement.setAttribute( "width", d->geomWidthPt );
987 }
988
subType() const989 Annotation::SubType GeomAnnotation::subType() const
990 {
991 return AGeom;
992 }
993
geomType() const994 GeomAnnotation::GeomType GeomAnnotation::geomType() const
995 {
996 Q_D( const GeomAnnotation );
997 return d->geomType;
998 }
999
setGeomType(GeomAnnotation::GeomType type)1000 void GeomAnnotation::setGeomType( GeomAnnotation::GeomType type )
1001 {
1002 Q_D( GeomAnnotation );
1003 d->geomType = type;
1004 }
1005
geomInnerColor() const1006 QColor GeomAnnotation::geomInnerColor() const
1007 {
1008 Q_D( const GeomAnnotation );
1009 return d->geomInnerColor;
1010 }
1011
setGeomInnerColor(const QColor & color)1012 void GeomAnnotation::setGeomInnerColor( const QColor &color )
1013 {
1014 Q_D( GeomAnnotation );
1015 d->geomInnerColor = color;
1016 }
1017
geomPointWidth() const1018 int GeomAnnotation::geomPointWidth() const
1019 {
1020 Q_D( const GeomAnnotation );
1021 return d->geomWidthPt;
1022 }
1023
setGeomPointWidth(int width)1024 void GeomAnnotation::setGeomPointWidth( int width )
1025 {
1026 Q_D( GeomAnnotation );
1027 d->geomWidthPt = width;
1028 }
1029
1030
1031
1032 /** HighlightAnnotation [Annotation] */
1033 class HighlightAnnotationPrivate : public AnnotationPrivate
1034 {
1035 public:
1036 HighlightAnnotationPrivate();
1037
1038 // data fields
1039 HighlightAnnotation::HighlightType highlightType;
1040 QList< HighlightAnnotation::Quad > highlightQuads; // not empty
1041 };
1042
HighlightAnnotationPrivate()1043 HighlightAnnotationPrivate::HighlightAnnotationPrivate()
1044 : AnnotationPrivate(), highlightType( HighlightAnnotation::Highlight )
1045 {
1046 }
1047
HighlightAnnotation()1048 HighlightAnnotation::HighlightAnnotation()
1049 : Annotation( *new HighlightAnnotationPrivate() )
1050 {}
1051
HighlightAnnotation(const QDomNode & node)1052 HighlightAnnotation::HighlightAnnotation( const QDomNode & node )
1053 : Annotation( *new HighlightAnnotationPrivate(), node )
1054 {
1055 Q_D( HighlightAnnotation );
1056
1057 // loop through the whole children looking for a 'hl' element
1058 QDomNode subNode = node.firstChild();
1059 while( subNode.isElement() )
1060 {
1061 QDomElement e = subNode.toElement();
1062 subNode = subNode.nextSibling();
1063 if ( e.tagName() != "hl" )
1064 continue;
1065
1066 // parse the attributes
1067 if ( e.hasAttribute( "type" ) )
1068 d->highlightType = (HighlightAnnotation::HighlightType)e.attribute( "type" ).toInt();
1069
1070 // parse all 'quad' subnodes
1071 QDomNode quadNode = e.firstChild();
1072 for ( ; quadNode.isElement(); quadNode = quadNode.nextSibling() )
1073 {
1074 QDomElement qe = quadNode.toElement();
1075 if ( qe.tagName() != "quad" )
1076 continue;
1077
1078 Quad q;
1079 q.points[0].setX(qe.attribute( "ax", "0.0" ).toDouble());
1080 q.points[0].setY(qe.attribute( "ay", "0.0" ).toDouble());
1081 q.points[1].setX(qe.attribute( "bx", "0.0" ).toDouble());
1082 q.points[1].setY(qe.attribute( "by", "0.0" ).toDouble());
1083 q.points[2].setX(qe.attribute( "cx", "0.0" ).toDouble());
1084 q.points[2].setY(qe.attribute( "cy", "0.0" ).toDouble());
1085 q.points[3].setX(qe.attribute( "dx", "0.0" ).toDouble());
1086 q.points[3].setY(qe.attribute( "dy", "0.0" ).toDouble());
1087 q.capStart = qe.hasAttribute( "start" );
1088 q.capEnd = qe.hasAttribute( "end" );
1089 q.feather = qe.attribute( "feather", "0.1" ).toDouble();
1090 d->highlightQuads.append( q );
1091 }
1092
1093 // loading complete
1094 break;
1095 }
1096 }
1097
~HighlightAnnotation()1098 HighlightAnnotation::~HighlightAnnotation()
1099 {
1100 }
1101
store(QDomNode & node,QDomDocument & document) const1102 void HighlightAnnotation::store( QDomNode & node, QDomDocument & document ) const
1103 {
1104 Q_D( const HighlightAnnotation );
1105
1106 // recurse to parent objects storing properties
1107 Annotation::store( node, document );
1108
1109 // create [hl] element
1110 QDomElement hlElement = document.createElement( "hl" );
1111 node.appendChild( hlElement );
1112
1113 // append the optional attributes
1114 if ( d->highlightType != Highlight )
1115 hlElement.setAttribute( "type", (int)d->highlightType );
1116 if ( d->highlightQuads.count() < 1 )
1117 return;
1118 // append highlight quads, all children describe quads
1119 QList< HighlightAnnotation::Quad >::const_iterator it = d->highlightQuads.begin(), end = d->highlightQuads.end();
1120 for ( ; it != end; ++it )
1121 {
1122 QDomElement quadElement = document.createElement( "quad" );
1123 hlElement.appendChild( quadElement );
1124 const Quad & q = *it;
1125 quadElement.setAttribute( "ax", QString::number( q.points[0].x() ) );
1126 quadElement.setAttribute( "ay", QString::number( q.points[0].y() ) );
1127 quadElement.setAttribute( "bx", QString::number( q.points[1].x() ) );
1128 quadElement.setAttribute( "by", QString::number( q.points[1].y() ) );
1129 quadElement.setAttribute( "cx", QString::number( q.points[2].x() ) );
1130 quadElement.setAttribute( "cy", QString::number( q.points[2].y() ) );
1131 quadElement.setAttribute( "dx", QString::number( q.points[3].x() ) );
1132 quadElement.setAttribute( "dy", QString::number( q.points[3].y() ) );
1133 if ( q.capStart )
1134 quadElement.setAttribute( "start", 1 );
1135 if ( q.capEnd )
1136 quadElement.setAttribute( "end", 1 );
1137 quadElement.setAttribute( "feather", QString::number( q.feather ) );
1138 }
1139 }
1140
subType() const1141 Annotation::SubType HighlightAnnotation::subType() const
1142 {
1143 return AHighlight;
1144 }
1145
highlightType() const1146 HighlightAnnotation::HighlightType HighlightAnnotation::highlightType() const
1147 {
1148 Q_D( const HighlightAnnotation );
1149 return d->highlightType;
1150 }
1151
setHighlightType(HighlightAnnotation::HighlightType type)1152 void HighlightAnnotation::setHighlightType( HighlightAnnotation::HighlightType type )
1153 {
1154 Q_D( HighlightAnnotation );
1155 d->highlightType = type;
1156 }
1157
highlightQuads() const1158 QList< HighlightAnnotation::Quad > HighlightAnnotation::highlightQuads() const
1159 {
1160 Q_D( const HighlightAnnotation );
1161 return d->highlightQuads;
1162 }
1163
setHighlightQuads(const QList<HighlightAnnotation::Quad> & quads)1164 void HighlightAnnotation::setHighlightQuads( const QList< HighlightAnnotation::Quad > &quads )
1165 {
1166 Q_D( HighlightAnnotation );
1167 d->highlightQuads = quads;
1168 }
1169
1170
1171 /** StampAnnotation [Annotation] */
1172 class StampAnnotationPrivate : public AnnotationPrivate
1173 {
1174 public:
1175 StampAnnotationPrivate();
1176
1177 // data fields
1178 QString stampIconName;
1179 };
1180
StampAnnotationPrivate()1181 StampAnnotationPrivate::StampAnnotationPrivate()
1182 : AnnotationPrivate(), stampIconName( "Draft" )
1183 {
1184 }
1185
StampAnnotation()1186 StampAnnotation::StampAnnotation()
1187 : Annotation( *new StampAnnotationPrivate() )
1188 {}
1189
StampAnnotation(const QDomNode & node)1190 StampAnnotation::StampAnnotation( const QDomNode & node )
1191 : Annotation( *new StampAnnotationPrivate(), node )
1192 {
1193 Q_D( StampAnnotation );
1194
1195 // loop through the whole children looking for a 'stamp' element
1196 QDomNode subNode = node.firstChild();
1197 while( subNode.isElement() )
1198 {
1199 QDomElement e = subNode.toElement();
1200 subNode = subNode.nextSibling();
1201 if ( e.tagName() != "stamp" )
1202 continue;
1203
1204 // parse the attributes
1205 if ( e.hasAttribute( "icon" ) )
1206 d->stampIconName = e.attribute( "icon" );
1207
1208 // loading complete
1209 break;
1210 }
1211 }
1212
~StampAnnotation()1213 StampAnnotation::~StampAnnotation()
1214 {
1215 }
1216
store(QDomNode & node,QDomDocument & document) const1217 void StampAnnotation::store( QDomNode & node, QDomDocument & document ) const
1218 {
1219 Q_D( const StampAnnotation );
1220
1221 // recurse to parent objects storing properties
1222 Annotation::store( node, document );
1223
1224 // create [stamp] element
1225 QDomElement stampElement = document.createElement( "stamp" );
1226 node.appendChild( stampElement );
1227
1228 // append the optional attributes
1229 if ( d->stampIconName != "Draft" )
1230 stampElement.setAttribute( "icon", d->stampIconName );
1231 }
1232
subType() const1233 Annotation::SubType StampAnnotation::subType() const
1234 {
1235 return AStamp;
1236 }
1237
stampIconName() const1238 QString StampAnnotation::stampIconName() const
1239 {
1240 Q_D( const StampAnnotation );
1241 return d->stampIconName;
1242 }
1243
setStampIconName(const QString & name)1244 void StampAnnotation::setStampIconName( const QString &name )
1245 {
1246 Q_D( StampAnnotation );
1247 d->stampIconName = name;
1248 }
1249
1250 /** InkAnnotation [Annotation] */
1251 class InkAnnotationPrivate : public AnnotationPrivate
1252 {
1253 public:
1254 InkAnnotationPrivate();
1255
1256 // data fields
1257 QList< QLinkedList<QPointF> > inkPaths;
1258 };
1259
InkAnnotationPrivate()1260 InkAnnotationPrivate::InkAnnotationPrivate()
1261 : AnnotationPrivate()
1262 {
1263 }
1264
InkAnnotation()1265 InkAnnotation::InkAnnotation()
1266 : Annotation( *new InkAnnotationPrivate() )
1267 {}
1268
InkAnnotation(const QDomNode & node)1269 InkAnnotation::InkAnnotation( const QDomNode & node )
1270 : Annotation( *new InkAnnotationPrivate(), node )
1271 {
1272 Q_D( InkAnnotation );
1273
1274 // loop through the whole children looking for a 'ink' element
1275 QDomNode subNode = node.firstChild();
1276 while( subNode.isElement() )
1277 {
1278 QDomElement e = subNode.toElement();
1279 subNode = subNode.nextSibling();
1280 if ( e.tagName() != "ink" )
1281 continue;
1282
1283 // parse the 'path' subnodes
1284 QDomNode pathNode = e.firstChild();
1285 while ( pathNode.isElement() )
1286 {
1287 QDomElement pathElement = pathNode.toElement();
1288 pathNode = pathNode.nextSibling();
1289
1290 if ( pathElement.tagName() != "path" )
1291 continue;
1292
1293 // build each path parsing 'point' subnodes
1294 QLinkedList<QPointF> path;
1295 QDomNode pointNode = pathElement.firstChild();
1296 while ( pointNode.isElement() )
1297 {
1298 QDomElement pointElement = pointNode.toElement();
1299 pointNode = pointNode.nextSibling();
1300
1301 if ( pointElement.tagName() != "point" )
1302 continue;
1303
1304 QPointF p(pointElement.attribute( "x", "0.0" ).toDouble(), pointElement.attribute( "y", "0.0" ).toDouble());
1305 path.append( p );
1306 }
1307
1308 // add the path to the path list if it contains at least 2 nodes
1309 if ( path.count() >= 2 )
1310 d->inkPaths.append( path );
1311 }
1312
1313 // loading complete
1314 break;
1315 }
1316 }
1317
~InkAnnotation()1318 InkAnnotation::~InkAnnotation()
1319 {
1320 }
1321
store(QDomNode & node,QDomDocument & document) const1322 void InkAnnotation::store( QDomNode & node, QDomDocument & document ) const
1323 {
1324 Q_D( const InkAnnotation );
1325
1326 // recurse to parent objects storing properties
1327 Annotation::store( node, document );
1328
1329 // create [ink] element
1330 QDomElement inkElement = document.createElement( "ink" );
1331 node.appendChild( inkElement );
1332
1333 // append the optional attributes
1334 if ( d->inkPaths.count() < 1 )
1335 return;
1336 QList< QLinkedList<QPointF> >::const_iterator pIt = d->inkPaths.begin(), pEnd = d->inkPaths.end();
1337 for ( ; pIt != pEnd; ++pIt )
1338 {
1339 QDomElement pathElement = document.createElement( "path" );
1340 inkElement.appendChild( pathElement );
1341 const QLinkedList<QPointF> & path = *pIt;
1342 QLinkedList<QPointF>::const_iterator iIt = path.begin(), iEnd = path.end();
1343 for ( ; iIt != iEnd; ++iIt )
1344 {
1345 const QPointF & point = *iIt;
1346 QDomElement pointElement = document.createElement( "point" );
1347 pathElement.appendChild( pointElement );
1348 pointElement.setAttribute( "x", QString::number( point.x() ) );
1349 pointElement.setAttribute( "y", QString::number( point.y() ) );
1350 }
1351 }
1352 }
1353
subType() const1354 Annotation::SubType InkAnnotation::subType() const
1355 {
1356 return AInk;
1357 }
1358
inkPaths() const1359 QList< QLinkedList<QPointF> > InkAnnotation::inkPaths() const
1360 {
1361 Q_D( const InkAnnotation );
1362 return d->inkPaths;
1363 }
1364
setInkPaths(const QList<QLinkedList<QPointF>> & paths)1365 void InkAnnotation::setInkPaths( const QList< QLinkedList<QPointF> > &paths )
1366 {
1367 Q_D( InkAnnotation );
1368 d->inkPaths = paths;
1369 }
1370
1371
1372 /** LinkAnnotation [Annotation] */
1373 class LinkAnnotationPrivate : public AnnotationPrivate
1374 {
1375 public:
1376 LinkAnnotationPrivate();
1377 ~LinkAnnotationPrivate();
1378
1379 // data fields
1380 Link * linkDestination;
1381 LinkAnnotation::HighlightMode linkHLMode;
1382 QPointF linkRegion[4];
1383 };
1384
LinkAnnotationPrivate()1385 LinkAnnotationPrivate::LinkAnnotationPrivate()
1386 : AnnotationPrivate(), linkDestination( 0 ), linkHLMode( LinkAnnotation::Invert )
1387 {
1388 }
1389
~LinkAnnotationPrivate()1390 LinkAnnotationPrivate::~LinkAnnotationPrivate()
1391 {
1392 delete linkDestination;
1393 }
1394
LinkAnnotation()1395 LinkAnnotation::LinkAnnotation()
1396 : Annotation( *new LinkAnnotationPrivate() )
1397 {}
1398
LinkAnnotation(const QDomNode & node)1399 LinkAnnotation::LinkAnnotation( const QDomNode & node )
1400 : Annotation( *new LinkAnnotationPrivate(), node )
1401 {
1402 Q_D( LinkAnnotation );
1403
1404 // loop through the whole children looking for a 'link' element
1405 QDomNode subNode = node.firstChild();
1406 while( subNode.isElement() )
1407 {
1408 QDomElement e = subNode.toElement();
1409 subNode = subNode.nextSibling();
1410 if ( e.tagName() != "link" )
1411 continue;
1412
1413 // parse the attributes
1414 if ( e.hasAttribute( "hlmode" ) )
1415 d->linkHLMode = (LinkAnnotation::HighlightMode)e.attribute( "hlmode" ).toInt();
1416
1417 // parse all 'quad' subnodes
1418 QDomNode quadNode = e.firstChild();
1419 for ( ; quadNode.isElement(); quadNode = quadNode.nextSibling() )
1420 {
1421 QDomElement qe = quadNode.toElement();
1422 if ( qe.tagName() == "quad" )
1423 {
1424 d->linkRegion[0].setX(qe.attribute( "ax", "0.0" ).toDouble());
1425 d->linkRegion[0].setY(qe.attribute( "ay", "0.0" ).toDouble());
1426 d->linkRegion[1].setX(qe.attribute( "bx", "0.0" ).toDouble());
1427 d->linkRegion[1].setY(qe.attribute( "by", "0.0" ).toDouble());
1428 d->linkRegion[2].setX(qe.attribute( "cx", "0.0" ).toDouble());
1429 d->linkRegion[2].setY(qe.attribute( "cy", "0.0" ).toDouble());
1430 d->linkRegion[3].setX(qe.attribute( "dx", "0.0" ).toDouble());
1431 d->linkRegion[3].setY(qe.attribute( "dy", "0.0" ).toDouble());
1432 }
1433 else if ( qe.tagName() == "link" )
1434 {
1435 QString type = qe.attribute( "type" );
1436 if ( type == "GoTo" )
1437 {
1438 Poppler::LinkGoto * go = new Poppler::LinkGoto( QRect(), qe.attribute( "filename" ), LinkDestination( qe.attribute( "destination" ) ) );
1439 d->linkDestination = go;
1440 }
1441 else if ( type == "Exec" )
1442 {
1443 Poppler::LinkExecute * exec = new Poppler::LinkExecute( QRect(), qe.attribute( "filename" ), qe.attribute( "parameters" ) );
1444 d->linkDestination = exec;
1445 }
1446 else if ( type == "Browse" )
1447 {
1448 Poppler::LinkBrowse * browse = new Poppler::LinkBrowse( QRect(), qe.attribute( "url" ) );
1449 d->linkDestination = browse;
1450 }
1451 else if ( type == "Action" )
1452 {
1453 Poppler::LinkAction::ActionType act;
1454 QString actString = qe.attribute( "action" );
1455 bool found = true;
1456 if ( actString == "PageFirst" )
1457 act = Poppler::LinkAction::PageFirst;
1458 else if ( actString == "PagePrev" )
1459 act = Poppler::LinkAction::PagePrev;
1460 else if ( actString == "PageNext" )
1461 act = Poppler::LinkAction::PageNext;
1462 else if ( actString == "PageLast" )
1463 act = Poppler::LinkAction::PageLast;
1464 else if ( actString == "HistoryBack" )
1465 act = Poppler::LinkAction::HistoryBack;
1466 else if ( actString == "HistoryForward" )
1467 act = Poppler::LinkAction::HistoryForward;
1468 else if ( actString == "Quit" )
1469 act = Poppler::LinkAction::Quit;
1470 else if ( actString == "Presentation" )
1471 act = Poppler::LinkAction::Presentation;
1472 else if ( actString == "EndPresentation" )
1473 act = Poppler::LinkAction::EndPresentation;
1474 else if ( actString == "Find" )
1475 act = Poppler::LinkAction::Find;
1476 else if ( actString == "GoToPage" )
1477 act = Poppler::LinkAction::GoToPage;
1478 else if ( actString == "Close" )
1479 act = Poppler::LinkAction::Close;
1480 else if ( actString == "Print" )
1481 act = Poppler::LinkAction::Print;
1482 else
1483 found = false;
1484 if (found)
1485 {
1486 Poppler::LinkAction * action = new Poppler::LinkAction( QRect(), act );
1487 d->linkDestination = action;
1488 }
1489 }
1490 #if 0
1491 else if ( type == "Movie" )
1492 {
1493 Poppler::LinkMovie * movie = new Poppler::LinkMovie( QRect() );
1494 d->linkDestination = movie;
1495 }
1496 #endif
1497 }
1498 }
1499
1500 // loading complete
1501 break;
1502 }
1503 }
1504
~LinkAnnotation()1505 LinkAnnotation::~LinkAnnotation()
1506 {
1507 }
1508
store(QDomNode & node,QDomDocument & document) const1509 void LinkAnnotation::store( QDomNode & node, QDomDocument & document ) const
1510 {
1511 Q_D( const LinkAnnotation );
1512
1513 // recurse to parent objects storing properties
1514 Annotation::store( node, document );
1515
1516 // create [hl] element
1517 QDomElement linkElement = document.createElement( "link" );
1518 node.appendChild( linkElement );
1519
1520 // append the optional attributes
1521 if ( d->linkHLMode != Invert )
1522 linkElement.setAttribute( "hlmode", (int)d->linkHLMode );
1523
1524 // saving region
1525 QDomElement quadElement = document.createElement( "quad" );
1526 linkElement.appendChild( quadElement );
1527 quadElement.setAttribute( "ax", QString::number( d->linkRegion[0].x() ) );
1528 quadElement.setAttribute( "ay", QString::number( d->linkRegion[0].y() ) );
1529 quadElement.setAttribute( "bx", QString::number( d->linkRegion[1].x() ) );
1530 quadElement.setAttribute( "by", QString::number( d->linkRegion[1].y() ) );
1531 quadElement.setAttribute( "cx", QString::number( d->linkRegion[2].x() ) );
1532 quadElement.setAttribute( "cy", QString::number( d->linkRegion[2].y() ) );
1533 quadElement.setAttribute( "dx", QString::number( d->linkRegion[3].x() ) );
1534 quadElement.setAttribute( "dy", QString::number( d->linkRegion[3].y() ) );
1535
1536 // saving link
1537 QDomElement hyperlinkElement = document.createElement( "link" );
1538 linkElement.appendChild( hyperlinkElement );
1539 if ( d->linkDestination )
1540 {
1541 switch( d->linkDestination->linkType() )
1542 {
1543 case Poppler::Link::Goto:
1544 {
1545 Poppler::LinkGoto * go = static_cast< Poppler::LinkGoto * >( d->linkDestination );
1546 hyperlinkElement.setAttribute( "type", "GoTo" );
1547 hyperlinkElement.setAttribute( "filename", go->fileName() );
1548 hyperlinkElement.setAttribute( "destionation", go->destination().toString() );
1549 break;
1550 }
1551 case Poppler::Link::Execute:
1552 {
1553 Poppler::LinkExecute * exec = static_cast< Poppler::LinkExecute * >( d->linkDestination );
1554 hyperlinkElement.setAttribute( "type", "Exec" );
1555 hyperlinkElement.setAttribute( "filename", exec->fileName() );
1556 hyperlinkElement.setAttribute( "parameters", exec->parameters() );
1557 break;
1558 }
1559 case Poppler::Link::Browse:
1560 {
1561 Poppler::LinkBrowse * browse = static_cast< Poppler::LinkBrowse * >( d->linkDestination );
1562 hyperlinkElement.setAttribute( "type", "Browse" );
1563 hyperlinkElement.setAttribute( "url", browse->url() );
1564 break;
1565 }
1566 case Poppler::Link::Action:
1567 {
1568 Poppler::LinkAction * action = static_cast< Poppler::LinkAction * >( d->linkDestination );
1569 hyperlinkElement.setAttribute( "type", "Action" );
1570 switch ( action->actionType() )
1571 {
1572 case Poppler::LinkAction::PageFirst:
1573 hyperlinkElement.setAttribute( "action", "PageFirst" );
1574 break;
1575 case Poppler::LinkAction::PagePrev:
1576 hyperlinkElement.setAttribute( "action", "PagePrev" );
1577 break;
1578 case Poppler::LinkAction::PageNext:
1579 hyperlinkElement.setAttribute( "action", "PageNext" );
1580 break;
1581 case Poppler::LinkAction::PageLast:
1582 hyperlinkElement.setAttribute( "action", "PageLast" );
1583 break;
1584 case Poppler::LinkAction::HistoryBack:
1585 hyperlinkElement.setAttribute( "action", "HistoryBack" );
1586 break;
1587 case Poppler::LinkAction::HistoryForward:
1588 hyperlinkElement.setAttribute( "action", "HistoryForward" );
1589 break;
1590 case Poppler::LinkAction::Quit:
1591 hyperlinkElement.setAttribute( "action", "Quit" );
1592 break;
1593 case Poppler::LinkAction::Presentation:
1594 hyperlinkElement.setAttribute( "action", "Presentation" );
1595 break;
1596 case Poppler::LinkAction::EndPresentation:
1597 hyperlinkElement.setAttribute( "action", "EndPresentation" );
1598 break;
1599 case Poppler::LinkAction::Find:
1600 hyperlinkElement.setAttribute( "action", "Find" );
1601 break;
1602 case Poppler::LinkAction::GoToPage:
1603 hyperlinkElement.setAttribute( "action", "GoToPage" );
1604 break;
1605 case Poppler::LinkAction::Close:
1606 hyperlinkElement.setAttribute( "action", "Close" );
1607 break;
1608 case Poppler::LinkAction::Print:
1609 hyperlinkElement.setAttribute( "action", "Print" );
1610 break;
1611 }
1612 break;
1613 }
1614 case Poppler::Link::Movie:
1615 {
1616 hyperlinkElement.setAttribute( "type", "Movie" );
1617 break;
1618 }
1619 case Poppler::Link::Sound:
1620 {
1621 // FIXME: implement me
1622 break;
1623 }
1624 case Poppler::Link::None:
1625 break;
1626 }
1627 }
1628 }
1629
subType() const1630 Annotation::SubType LinkAnnotation::subType() const
1631 {
1632 return ALink;
1633 }
1634
linkDestionation() const1635 Link* LinkAnnotation::linkDestionation() const
1636 {
1637 Q_D( const LinkAnnotation );
1638 return d->linkDestination;
1639 }
1640
setLinkDestination(Link * link)1641 void LinkAnnotation::setLinkDestination( Link *link )
1642 {
1643 Q_D( LinkAnnotation );
1644 delete d->linkDestination;
1645 d->linkDestination = link;
1646 }
1647
linkHighlightMode() const1648 LinkAnnotation::HighlightMode LinkAnnotation::linkHighlightMode() const
1649 {
1650 Q_D( const LinkAnnotation );
1651 return d->linkHLMode;
1652 }
1653
setLinkHighlightMode(LinkAnnotation::HighlightMode mode)1654 void LinkAnnotation::setLinkHighlightMode( LinkAnnotation::HighlightMode mode )
1655 {
1656 Q_D( LinkAnnotation );
1657 d->linkHLMode = mode;
1658 }
1659
linkRegionPoint(int id) const1660 QPointF LinkAnnotation::linkRegionPoint( int id ) const
1661 {
1662 if ( id < 0 || id >= 4 )
1663 return QPointF();
1664
1665 Q_D( const LinkAnnotation );
1666 return d->linkRegion[id];
1667 }
1668
setLinkRegionPoint(int id,const QPointF & point)1669 void LinkAnnotation::setLinkRegionPoint( int id, const QPointF &point )
1670 {
1671 if ( id < 0 || id >= 4 )
1672 return;
1673
1674 Q_D( LinkAnnotation );
1675 d->linkRegion[id] = point;
1676 }
1677
1678 /** CaretAnnotation [Annotation] */
1679 class CaretAnnotationPrivate : public AnnotationPrivate
1680 {
1681 public:
1682 CaretAnnotationPrivate();
1683
1684 // data fields
1685 CaretAnnotation::CaretSymbol symbol;
1686 };
1687
caretSymbolToString(CaretAnnotation::CaretSymbol symbol)1688 static QString caretSymbolToString( CaretAnnotation::CaretSymbol symbol )
1689 {
1690 switch ( symbol )
1691 {
1692 case CaretAnnotation::None:
1693 return QString::fromLatin1( "None" );
1694 case CaretAnnotation::P:
1695 return QString::fromLatin1( "P" );
1696 }
1697 return QString();
1698 }
1699
caretSymbolFromString(const QString & symbol)1700 static CaretAnnotation::CaretSymbol caretSymbolFromString( const QString &symbol )
1701 {
1702 if ( symbol == QLatin1String( "None" ) )
1703 return CaretAnnotation::None;
1704 else if ( symbol == QLatin1String( "P" ) )
1705 return CaretAnnotation::P;
1706 return CaretAnnotation::None;
1707 }
1708
CaretAnnotationPrivate()1709 CaretAnnotationPrivate::CaretAnnotationPrivate()
1710 : AnnotationPrivate(), symbol( CaretAnnotation::None )
1711 {
1712 }
1713
CaretAnnotation()1714 CaretAnnotation::CaretAnnotation()
1715 : Annotation( *new CaretAnnotationPrivate() )
1716 {
1717 }
1718
CaretAnnotation(const QDomNode & node)1719 CaretAnnotation::CaretAnnotation( const QDomNode & node )
1720 : Annotation( *new CaretAnnotationPrivate(), node )
1721 {
1722 Q_D( CaretAnnotation );
1723
1724 // loop through the whole children looking for a 'caret' element
1725 QDomNode subNode = node.firstChild();
1726 while( subNode.isElement() )
1727 {
1728 QDomElement e = subNode.toElement();
1729 subNode = subNode.nextSibling();
1730 if ( e.tagName() != "caret" )
1731 continue;
1732
1733 // parse the attributes
1734 if ( e.hasAttribute( "symbol" ) )
1735 d->symbol = caretSymbolFromString( e.attribute( "symbol" ) );
1736
1737 // loading complete
1738 break;
1739 }
1740 }
1741
~CaretAnnotation()1742 CaretAnnotation::~CaretAnnotation()
1743 {
1744 }
1745
store(QDomNode & node,QDomDocument & document) const1746 void CaretAnnotation::store( QDomNode & node, QDomDocument & document ) const
1747 {
1748 Q_D( const CaretAnnotation );
1749
1750 // recurse to parent objects storing properties
1751 Annotation::store( node, document );
1752
1753 // create [caret] element
1754 QDomElement caretElement = document.createElement( "caret" );
1755 node.appendChild( caretElement );
1756
1757 // append the optional attributes
1758 if ( d->symbol != CaretAnnotation::None )
1759 caretElement.setAttribute( "symbol", caretSymbolToString( d->symbol ) );
1760 }
1761
subType() const1762 Annotation::SubType CaretAnnotation::subType() const
1763 {
1764 return ACaret;
1765 }
1766
caretSymbol() const1767 CaretAnnotation::CaretSymbol CaretAnnotation::caretSymbol() const
1768 {
1769 Q_D( const CaretAnnotation );
1770 return d->symbol;
1771 }
1772
setCaretSymbol(CaretAnnotation::CaretSymbol symbol)1773 void CaretAnnotation::setCaretSymbol( CaretAnnotation::CaretSymbol symbol )
1774 {
1775 Q_D( CaretAnnotation );
1776 d->symbol = symbol;
1777 }
1778
1779 /** FileAttachmentAnnotation [Annotation] */
1780 class FileAttachmentAnnotationPrivate : public AnnotationPrivate
1781 {
1782 public:
1783 FileAttachmentAnnotationPrivate();
1784 ~FileAttachmentAnnotationPrivate();
1785
1786 // data fields
1787 QString icon;
1788 EmbeddedFile *embfile;
1789 };
1790
FileAttachmentAnnotationPrivate()1791 FileAttachmentAnnotationPrivate::FileAttachmentAnnotationPrivate()
1792 : AnnotationPrivate(), icon( "PushPin" ), embfile( 0 )
1793 {
1794 }
1795
~FileAttachmentAnnotationPrivate()1796 FileAttachmentAnnotationPrivate::~FileAttachmentAnnotationPrivate()
1797 {
1798 delete embfile;
1799 }
1800
FileAttachmentAnnotation()1801 FileAttachmentAnnotation::FileAttachmentAnnotation()
1802 : Annotation( *new FileAttachmentAnnotationPrivate() )
1803 {
1804 }
1805
FileAttachmentAnnotation(const QDomNode & node)1806 FileAttachmentAnnotation::FileAttachmentAnnotation( const QDomNode & node )
1807 : Annotation( *new FileAttachmentAnnotationPrivate(), node )
1808 {
1809 // loop through the whole children looking for a 'fileattachment' element
1810 QDomNode subNode = node.firstChild();
1811 while( subNode.isElement() )
1812 {
1813 QDomElement e = subNode.toElement();
1814 subNode = subNode.nextSibling();
1815 if ( e.tagName() != "fileattachment" )
1816 continue;
1817
1818 // loading complete
1819 break;
1820 }
1821 }
1822
~FileAttachmentAnnotation()1823 FileAttachmentAnnotation::~FileAttachmentAnnotation()
1824 {
1825 }
1826
store(QDomNode & node,QDomDocument & document) const1827 void FileAttachmentAnnotation::store( QDomNode & node, QDomDocument & document ) const
1828 {
1829 // recurse to parent objects storing properties
1830 Annotation::store( node, document );
1831
1832 // create [fileattachment] element
1833 QDomElement fileAttachmentElement = document.createElement( "fileattachment" );
1834 node.appendChild( fileAttachmentElement );
1835 }
1836
subType() const1837 Annotation::SubType FileAttachmentAnnotation::subType() const
1838 {
1839 return AFileAttachment;
1840 }
1841
fileIconName() const1842 QString FileAttachmentAnnotation::fileIconName() const
1843 {
1844 Q_D( const FileAttachmentAnnotation );
1845 return d->icon;
1846 }
1847
setFileIconName(const QString & icon)1848 void FileAttachmentAnnotation::setFileIconName( const QString &icon )
1849 {
1850 Q_D( FileAttachmentAnnotation );
1851 d->icon = icon;
1852 }
1853
embeddedFile() const1854 EmbeddedFile* FileAttachmentAnnotation::embeddedFile() const
1855 {
1856 Q_D( const FileAttachmentAnnotation );
1857 return d->embfile;
1858 }
1859
setEmbeddedFile(EmbeddedFile * ef)1860 void FileAttachmentAnnotation::setEmbeddedFile( EmbeddedFile *ef )
1861 {
1862 Q_D( FileAttachmentAnnotation );
1863 d->embfile = ef;
1864 }
1865
1866 /** SoundAnnotation [Annotation] */
1867 class SoundAnnotationPrivate : public AnnotationPrivate
1868 {
1869 public:
1870 SoundAnnotationPrivate();
1871 ~SoundAnnotationPrivate();
1872
1873 // data fields
1874 QString icon;
1875 SoundObject *sound;
1876 };
1877
SoundAnnotationPrivate()1878 SoundAnnotationPrivate::SoundAnnotationPrivate()
1879 : AnnotationPrivate(), icon( "Speaker" ), sound( 0 )
1880 {
1881 }
1882
~SoundAnnotationPrivate()1883 SoundAnnotationPrivate::~SoundAnnotationPrivate()
1884 {
1885 delete sound;
1886 }
1887
SoundAnnotation()1888 SoundAnnotation::SoundAnnotation()
1889 : Annotation( *new SoundAnnotationPrivate() )
1890 {
1891 }
1892
SoundAnnotation(const QDomNode & node)1893 SoundAnnotation::SoundAnnotation( const QDomNode & node )
1894 : Annotation( *new SoundAnnotationPrivate(), node )
1895 {
1896 // loop through the whole children looking for a 'sound' element
1897 QDomNode subNode = node.firstChild();
1898 while( subNode.isElement() )
1899 {
1900 QDomElement e = subNode.toElement();
1901 subNode = subNode.nextSibling();
1902 if ( e.tagName() != "sound" )
1903 continue;
1904
1905 // loading complete
1906 break;
1907 }
1908 }
1909
~SoundAnnotation()1910 SoundAnnotation::~SoundAnnotation()
1911 {
1912 }
1913
store(QDomNode & node,QDomDocument & document) const1914 void SoundAnnotation::store( QDomNode & node, QDomDocument & document ) const
1915 {
1916 // recurse to parent objects storing properties
1917 Annotation::store( node, document );
1918
1919 // create [sound] element
1920 QDomElement soundElement = document.createElement( "sound" );
1921 node.appendChild( soundElement );
1922 }
1923
subType() const1924 Annotation::SubType SoundAnnotation::subType() const
1925 {
1926 return ASound;
1927 }
1928
soundIconName() const1929 QString SoundAnnotation::soundIconName() const
1930 {
1931 Q_D( const SoundAnnotation );
1932 return d->icon;
1933 }
1934
setSoundIconName(const QString & icon)1935 void SoundAnnotation::setSoundIconName( const QString &icon )
1936 {
1937 Q_D( SoundAnnotation );
1938 d->icon = icon;
1939 }
1940
sound() const1941 SoundObject* SoundAnnotation::sound() const
1942 {
1943 Q_D( const SoundAnnotation );
1944 return d->sound;
1945 }
1946
setSound(SoundObject * s)1947 void SoundAnnotation::setSound( SoundObject *s )
1948 {
1949 Q_D( SoundAnnotation );
1950 d->sound = s;
1951 }
1952
1953 /** MovieAnnotation [Annotation] */
1954 class MovieAnnotationPrivate : public AnnotationPrivate
1955 {
1956 public:
1957 MovieAnnotationPrivate();
1958 ~MovieAnnotationPrivate();
1959
1960 // data fields
1961 MovieObject *movie;
1962 QString title;
1963 };
1964
MovieAnnotationPrivate()1965 MovieAnnotationPrivate::MovieAnnotationPrivate()
1966 : AnnotationPrivate(), movie( 0 )
1967 {
1968 }
1969
~MovieAnnotationPrivate()1970 MovieAnnotationPrivate::~MovieAnnotationPrivate()
1971 {
1972 delete movie;
1973 }
1974
MovieAnnotation()1975 MovieAnnotation::MovieAnnotation()
1976 : Annotation( *new MovieAnnotationPrivate() )
1977 {
1978 }
1979
MovieAnnotation(const QDomNode & node)1980 MovieAnnotation::MovieAnnotation( const QDomNode & node )
1981 : Annotation( *new MovieAnnotationPrivate(), node )
1982 {
1983 // loop through the whole children looking for a 'movie' element
1984 QDomNode subNode = node.firstChild();
1985 while( subNode.isElement() )
1986 {
1987 QDomElement e = subNode.toElement();
1988 subNode = subNode.nextSibling();
1989 if ( e.tagName() != "movie" )
1990 continue;
1991
1992 // loading complete
1993 break;
1994 }
1995 }
1996
~MovieAnnotation()1997 MovieAnnotation::~MovieAnnotation()
1998 {
1999 }
2000
store(QDomNode & node,QDomDocument & document) const2001 void MovieAnnotation::store( QDomNode & node, QDomDocument & document ) const
2002 {
2003 // recurse to parent objects storing properties
2004 Annotation::store( node, document );
2005
2006 // create [movie] element
2007 QDomElement movieElement = document.createElement( "movie" );
2008 node.appendChild( movieElement );
2009 }
2010
subType() const2011 Annotation::SubType MovieAnnotation::subType() const
2012 {
2013 return AMovie;
2014 }
2015
movie() const2016 MovieObject* MovieAnnotation::movie() const
2017 {
2018 Q_D( const MovieAnnotation );
2019 return d->movie;
2020 }
2021
setMovie(MovieObject * movie)2022 void MovieAnnotation::setMovie( MovieObject *movie )
2023 {
2024 Q_D( MovieAnnotation );
2025 d->movie = movie;
2026 }
2027
movieTitle() const2028 QString MovieAnnotation::movieTitle() const
2029 {
2030 Q_D( const MovieAnnotation );
2031 return d->title;
2032 }
2033
setMovieTitle(const QString & title)2034 void MovieAnnotation::setMovieTitle( const QString &title )
2035 {
2036 Q_D( MovieAnnotation );
2037 d->title = title;
2038 }
2039
2040 //BEGIN utility annotation functions
convertAnnotColor(AnnotColor * color)2041 QColor convertAnnotColor( AnnotColor *color )
2042 {
2043 if ( !color )
2044 return QColor();
2045
2046 QColor newcolor;
2047 const double *color_data = color->getValues();
2048 switch ( color->getSpace() )
2049 {
2050 case AnnotColor::colorTransparent: // = 0,
2051 newcolor = Qt::transparent;
2052 break;
2053 case AnnotColor::colorGray: // = 1,
2054 newcolor.setRgbF( color_data[0], color_data[0], color_data[0] );
2055 break;
2056 case AnnotColor::colorRGB: // = 3,
2057 newcolor.setRgbF( color_data[0], color_data[1], color_data[2] );
2058 break;
2059 case AnnotColor::colorCMYK: // = 4
2060 newcolor.setCmykF( color_data[0], color_data[1], color_data[2], color_data[3] );
2061 break;
2062 }
2063 return newcolor;
2064 }
2065 //END utility annotation functions
2066
2067 }
2068