• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdegraphics
  • Sitemap
  • Contact Us
 

okular

annotations.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Enrico Ros <eros.kde@email.it>                  *
00003  *                                                                         *
00004  *   This program is free software; you can redistribute it and/or modify  *
00005  *   it under the terms of the GNU General Public License as published by  *
00006  *   the Free Software Foundation; either version 2 of the License, or     *
00007  *   (at your option) any later version.                                   *
00008  ***************************************************************************/
00009 
00010 #include "annotations.h"
00011 #include "annotations_p.h"
00012 
00013 // qt/kde includes
00014 #include <QtGui/QApplication>
00015 #include <QtGui/QColor>
00016 
00017 // local includes
00018 #include "page_p.h"
00019 
00020 using namespace Okular;
00021 
00022 //BEGIN AnnotationUtils implementation
00023 Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement )
00024 {
00025     // safety check on annotation element
00026     if ( !annElement.hasAttribute( "type" ) )
00027         return 0;
00028 
00029     // build annotation of given type
00030     Annotation * annotation = 0;
00031     int typeNumber = annElement.attribute( "type" ).toInt();
00032     switch ( typeNumber )
00033     {
00034         case Annotation::AText:
00035             annotation = new TextAnnotation( annElement );
00036             break;
00037         case Annotation::ALine:
00038             annotation = new LineAnnotation( annElement );
00039             break;
00040         case Annotation::AGeom:
00041             annotation = new GeomAnnotation( annElement );
00042             break;
00043         case Annotation::AHighlight:
00044             annotation = new HighlightAnnotation( annElement );
00045             break;
00046         case Annotation::AStamp:
00047             annotation = new StampAnnotation( annElement );
00048             break;
00049         case Annotation::AInk:
00050             annotation = new InkAnnotation( annElement );
00051             break;
00052     }
00053 
00054     // return created annotation
00055     return annotation;
00056 }
00057 
00058 void AnnotationUtils::storeAnnotation( const Annotation * ann, QDomElement & annElement,
00059     QDomDocument & document )
00060 {
00061     // save annotation's type as element's attribute
00062     annElement.setAttribute( "type", (uint)ann->subType() );
00063 
00064     // append all annotation data as children of this node
00065     ann->store( annElement, document );
00066 }
00067 
00068 QDomElement AnnotationUtils::findChildElement( const QDomNode & parentNode,
00069     const QString & name )
00070 {
00071     // loop through the whole children and return a 'name' named element
00072     QDomNode subNode = parentNode.firstChild();
00073     while( subNode.isElement() )
00074     {
00075         QDomElement element = subNode.toElement();
00076         if ( element.tagName() == name )
00077             return element;
00078         subNode = subNode.nextSibling();
00079     }
00080     // if the name can't be found, return a dummy null element
00081     return QDomElement();
00082 }
00083 
00084 QRect AnnotationUtils::annotationGeometry( const Annotation * ann,
00085     double scaledWidth, double scaledHeight )
00086 {
00087     if ( ann->subType() == Annotation::AText && ( ( (TextAnnotation*)ann )->textType() == TextAnnotation::Linked ) )
00088     {
00089         return QRect( (int)( ann->transformedBoundingRectangle().left * scaledWidth ),
00090                       (int)( ann->transformedBoundingRectangle().top * scaledHeight ), 24, 24 );
00091     }
00092 
00093     return ann->transformedBoundingRectangle().geometry( (int)scaledWidth, (int)scaledHeight );
00094 }
00095 //END AnnotationUtils implementation
00096 
00097 
00098 //BEGIN Annotation implementation
00099 
00100 class Annotation::Style::Private
00101 {
00102     public:
00103         Private()
00104             : m_opacity( 1.0 ), m_width( 1.0 ), m_style( Solid ), m_xCorners( 0.0 ),
00105               m_yCorners( 0.0 ), m_marks( 3 ), m_spaces( 0 ), m_effect( NoEffect ),
00106               m_effectIntensity( 1.0 )
00107         {
00108         }
00109 
00110         QColor m_color;
00111         double m_opacity;
00112         double m_width;
00113         LineStyle m_style;
00114         double m_xCorners;
00115         double m_yCorners;
00116         int m_marks;
00117         int m_spaces;
00118         LineEffect m_effect;
00119         double m_effectIntensity;
00120 };
00121 
00122 Annotation::Style::Style()
00123     : d( new Private )
00124 {
00125 }
00126 
00127 Annotation::Style::~Style()
00128 {
00129     delete d;
00130 }
00131 
00132 Annotation::Style::Style( const Style &other )
00133     : d( new Private )
00134 {
00135     *d = *other.d;
00136 }
00137 
00138 Annotation::Style& Annotation::Style::operator=( const Style &other )
00139 {
00140     if ( this != &other )
00141         *d = *other.d;
00142 
00143     return *this;
00144 }
00145 
00146 void Annotation::Style::setColor( const QColor &color )
00147 {
00148     d->m_color = color;
00149 }
00150 
00151 QColor Annotation::Style::color() const
00152 {
00153     return d->m_color;
00154 }
00155 
00156 void Annotation::Style::setOpacity( double opacity )
00157 {
00158     d->m_opacity = opacity;
00159 }
00160 
00161 double Annotation::Style::opacity() const
00162 {
00163     return d->m_opacity;
00164 }
00165 
00166 void Annotation::Style::setWidth( double width )
00167 {
00168     d->m_width = width;
00169 }
00170 
00171 double Annotation::Style::width() const
00172 {
00173     return d->m_width;
00174 }
00175 
00176 void Annotation::Style::setLineStyle( LineStyle style )
00177 {
00178     d->m_style = style;
00179 }
00180 
00181 Annotation::LineStyle Annotation::Style::lineStyle() const
00182 {
00183     return d->m_style;
00184 }
00185 
00186 void Annotation::Style::setXCorners( double xCorners )
00187 {
00188     d->m_xCorners = xCorners;
00189 }
00190 
00191 double Annotation::Style::xCorners() const
00192 {
00193     return d->m_xCorners;
00194 }
00195 
00196 void Annotation::Style::setYCorners( double yCorners )
00197 {
00198     d->m_yCorners = yCorners;
00199 }
00200 
00201 double Annotation::Style::yCorners() const
00202 {
00203     return d->m_yCorners;
00204 }
00205 
00206 void Annotation::Style::setMarks( int marks )
00207 {
00208     d->m_marks = marks;
00209 }
00210 
00211 int Annotation::Style::marks() const
00212 {
00213     return d->m_marks;
00214 }
00215 
00216 void Annotation::Style::setSpaces( int spaces )
00217 {
00218     d->m_spaces = spaces;
00219 }
00220 
00221 int Annotation::Style::spaces() const
00222 {
00223     return d->m_spaces;
00224 }
00225 
00226 void Annotation::Style::setLineEffect( LineEffect effect )
00227 {
00228     d->m_effect = effect;
00229 }
00230 
00231 Annotation::LineEffect Annotation::Style::lineEffect() const
00232 {
00233     return d->m_effect;
00234 }
00235 
00236 void Annotation::Style::setEffectIntensity( double intensity )
00237 {
00238     d->m_effectIntensity = intensity;
00239 }
00240 
00241 double Annotation::Style::effectIntensity() const
00242 {
00243     return d->m_effectIntensity;
00244 }
00245 
00246 
00247 class Annotation::Window::Private
00248 {
00249     public:
00250         Private()
00251             : m_flags( -1 ), m_width( 0 ), m_height( 0 )
00252         {
00253         }
00254 
00255         int m_flags;
00256         NormalizedPoint m_topLeft;
00257         int m_width;
00258         int m_height;
00259         QString m_title;
00260         QString m_summary;
00261         QString m_text;
00262 };
00263 
00264 Annotation::Window::Window()
00265     : d( new Private )
00266 {
00267 }
00268 
00269 Annotation::Window::~Window()
00270 {
00271     delete d;
00272 }
00273 
00274 Annotation::Window::Window( const Window &other )
00275     : d( new Private )
00276 {
00277     *d = *other.d;
00278 }
00279 
00280 Annotation::Window& Annotation::Window::operator=( const Window &other )
00281 {
00282     if ( this != &other )
00283         *d = *other.d;
00284 
00285     return *this;
00286 }
00287 
00288 void Annotation::Window::setFlags( int flags )
00289 {
00290     d->m_flags = flags;
00291 }
00292 
00293 int Annotation::Window::flags() const
00294 {
00295     return d->m_flags;
00296 }
00297 
00298 void Annotation::Window::setTopLeft( const NormalizedPoint &point )
00299 {
00300     d->m_topLeft = point;
00301 }
00302 
00303 NormalizedPoint Annotation::Window::topLeft() const
00304 {
00305     return d->m_topLeft;
00306 }
00307 
00308 void Annotation::Window::setWidth( int width )
00309 {
00310     d->m_width = width;
00311 }
00312 
00313 int Annotation::Window::width() const
00314 {
00315     return d->m_width;
00316 }
00317 
00318 void Annotation::Window::setHeight( int height )
00319 {
00320     d->m_height = height;
00321 }
00322 
00323 int Annotation::Window::height() const
00324 {
00325     return d->m_height;
00326 }
00327 
00328 void Annotation::Window::setTitle( const QString &title )
00329 {
00330     d->m_title = title;
00331 }
00332 
00333 QString Annotation::Window::title() const
00334 {
00335     return d->m_title;
00336 }
00337 
00338 void Annotation::Window::setSummary( const QString &summary )
00339 {
00340     d->m_summary = summary;
00341 }
00342 
00343 QString Annotation::Window::summary() const
00344 {
00345     return d->m_summary;
00346 }
00347 
00348 void Annotation::Window::setText( const QString &text )
00349 {
00350     d->m_text = text;
00351 }
00352 
00353 QString Annotation::Window::text() const
00354 {
00355     return d->m_text;
00356 }
00357 
00358 
00359 class Annotation::Revision::Private
00360 {
00361     public:
00362         Private()
00363             : m_annotation( 0 ), m_scope( Reply ), m_type( None )
00364         {
00365         }
00366 
00367         Annotation *m_annotation;
00368         RevisionScope m_scope;
00369         RevisionType m_type;
00370 };
00371 
00372 Annotation::Revision::Revision()
00373     : d( new Private )
00374 {
00375 }
00376 
00377 Annotation::Revision::~Revision()
00378 {
00379     delete d;
00380 }
00381 
00382 Annotation::Revision::Revision( const Revision &other )
00383     : d( new Private )
00384 {
00385     *d = *other.d;
00386 }
00387 
00388 Annotation::Revision& Annotation::Revision::operator=( const Revision &other )
00389 {
00390     if ( this != &other )
00391         *d = *other.d;
00392 
00393     return *this;
00394 }
00395 
00396 void Annotation::Revision::setAnnotation( Annotation *annotation )
00397 {
00398     d->m_annotation = annotation;
00399 }
00400 
00401 Annotation *Annotation::Revision::annotation() const
00402 {
00403     return d->m_annotation;
00404 }
00405 
00406 void Annotation::Revision::setScope( RevisionScope scope )
00407 {
00408     d->m_scope = scope;
00409 }
00410 
00411 Annotation::RevisionScope Annotation::Revision::scope() const
00412 {
00413     return d->m_scope;
00414 }
00415 
00416 void Annotation::Revision::setType( RevisionType type )
00417 {
00418     d->m_type = type;
00419 }
00420 
00421 Annotation::RevisionType Annotation::Revision::type() const
00422 {
00423     return d->m_type;
00424 }
00425 
00426 
00427 AnnotationPrivate::AnnotationPrivate()
00428     : m_page( 0 ), m_flags( 0 )
00429 {
00430 }
00431 
00432 AnnotationPrivate::~AnnotationPrivate()
00433 {
00434     // delete all children revisions
00435     if ( m_revisions.isEmpty() )
00436         return;
00437 
00438     QLinkedList< Annotation::Revision >::iterator it = m_revisions.begin(), end = m_revisions.end();
00439     for ( ; it != end; ++it )
00440         delete (*it).annotation();
00441 }
00442 
00443 Annotation::Annotation( AnnotationPrivate &dd )
00444     : d_ptr( &dd )
00445 {
00446 }
00447 
00448 Annotation::Annotation( AnnotationPrivate &dd, const QDomNode & annNode )
00449     : d_ptr( &dd )
00450 {
00451     Q_D( Annotation );
00452     // get the [base] element of the annotation node
00453     QDomElement e = AnnotationUtils::findChildElement( annNode, "base" );
00454     if ( e.isNull() )
00455         return;
00456 
00457     // parse -contents- attributes
00458     if ( e.hasAttribute( "author" ) )
00459         d->m_author = e.attribute( "author" );
00460     if ( e.hasAttribute( "contents" ) )
00461         d->m_contents = e.attribute( "contents" );
00462     if ( e.hasAttribute( "uniqueName" ) )
00463         d->m_uniqueName = e.attribute( "uniqueName" );
00464     if ( e.hasAttribute( "modifyDate" ) )
00465         d->m_modifyDate = QDateTime::fromString( e.attribute("modifyDate"), Qt::ISODate );
00466     if ( e.hasAttribute( "creationDate" ) )
00467         d->m_creationDate = QDateTime::fromString( e.attribute("creationDate"), Qt::ISODate );
00468 
00469     // parse -other- attributes
00470     if ( e.hasAttribute( "flags" ) )
00471         d->m_flags = e.attribute( "flags" ).toInt();
00472     if ( e.hasAttribute( "color" ) )
00473         d->m_style.setColor( QColor( e.attribute( "color" ) ) );
00474     if ( e.hasAttribute( "opacity" ) )
00475         d->m_style.setOpacity( e.attribute( "opacity" ).toDouble() );
00476 
00477     // parse -the-subnodes- (describing Style, Window, Revision(s) structures)
00478     // Note: all subnodes if present must be 'attributes complete'
00479     QDomNode eSubNode = e.firstChild();
00480     while ( eSubNode.isElement() )
00481     {
00482         QDomElement ee = eSubNode.toElement();
00483         eSubNode = eSubNode.nextSibling();
00484 
00485         // parse boundary
00486         if ( ee.tagName() == "boundary" )
00487         {
00488             d->m_boundary=NormalizedRect(ee.attribute( "l" ).toDouble(),
00489                 ee.attribute( "t" ).toDouble(),
00490                 ee.attribute( "r" ).toDouble(),
00491                 ee.attribute( "b" ).toDouble());
00492         }
00493         // parse penStyle if not default
00494         else if ( ee.tagName() == "penStyle" )
00495         {
00496             d->m_style.setWidth( ee.attribute( "width" ).toDouble() );
00497             d->m_style.setLineStyle( (LineStyle)ee.attribute( "style" ).toInt() );
00498             d->m_style.setXCorners( ee.attribute( "xcr" ).toDouble() );
00499             d->m_style.setYCorners( ee.attribute( "ycr" ).toDouble() );
00500             d->m_style.setMarks( ee.attribute( "marks" ).toInt() );
00501             d->m_style.setSpaces( ee.attribute( "spaces" ).toInt() );
00502         }
00503         // parse effectStyle if not default
00504         else if ( ee.tagName() == "penEffect" )
00505         {
00506             d->m_style.setLineEffect( (LineEffect)ee.attribute( "effect" ).toInt() );
00507             d->m_style.setEffectIntensity( ee.attribute( "intensity" ).toDouble() );
00508         }
00509         // parse window if present
00510         else if ( ee.tagName() == "window" )
00511         {
00512             d->m_window.setFlags( ee.attribute( "flags" ).toInt() );
00513             d->m_window.setTopLeft( NormalizedPoint( ee.attribute( "top" ).toDouble(),
00514                                                   ee.attribute( "left" ).toDouble() ) );
00515             d->m_window.setWidth( ee.attribute( "width" ).toInt() );
00516             d->m_window.setHeight( ee.attribute( "height" ).toInt() );
00517             d->m_window.setTitle( ee.attribute( "title" ) );
00518             d->m_window.setSummary( ee.attribute( "summary" ) );
00519             // parse window subnodes
00520             QDomNode winNode = ee.firstChild();
00521             for ( ; winNode.isElement(); winNode = winNode.nextSibling() )
00522             {
00523                 QDomElement winElement = winNode.toElement();
00524                 if ( winElement.tagName() == "text" )
00525                     d->m_window.setText( winElement.firstChild().toCDATASection().data() );
00526             }
00527         }
00528     }
00529 
00530     // get the [revisions] element of the annotation node
00531     QDomNode revNode = annNode.firstChild();
00532     for ( ; revNode.isElement(); revNode = revNode.nextSibling() )
00533     {
00534         QDomElement revElement = revNode.toElement();
00535         if ( revElement.tagName() != "revision" )
00536             continue;
00537 
00538         // compile the Revision structure crating annotation
00539         Revision revision;
00540         revision.setScope( (RevisionScope)revElement.attribute( "revScope" ).toInt() );
00541         revision.setType( (RevisionType)revElement.attribute( "revType" ).toInt() );
00542         revision.setAnnotation( AnnotationUtils::createAnnotation( revElement ) );
00543 
00544         // if annotation is valid, add revision to internal list
00545         if ( revision.annotation() )
00546             d->m_revisions.append( revision );
00547     }
00548 
00549     d->m_transformedBoundary = d->m_boundary;
00550 }
00551 
00552 Annotation::~Annotation()
00553 {
00554     delete d_ptr;
00555 }
00556 
00557 void Annotation::setAuthor( const QString &author )
00558 {
00559     Q_D( Annotation );
00560     d->m_author = author;
00561 }
00562 
00563 QString Annotation::author() const
00564 {
00565     Q_D( const Annotation );
00566     return d->m_author;
00567 }
00568 
00569 void Annotation::setContents( const QString &contents )
00570 {
00571     Q_D( Annotation );
00572     d->m_contents = contents;
00573 }
00574 
00575 QString Annotation::contents() const
00576 {
00577     Q_D( const Annotation );
00578     return d->m_contents;
00579 }
00580 
00581 void Annotation::setUniqueName( const QString &name )
00582 {
00583     Q_D( Annotation );
00584     d->m_uniqueName = name;
00585 }
00586 
00587 QString Annotation::uniqueName() const
00588 {
00589     Q_D( const Annotation );
00590     return d->m_uniqueName;
00591 }
00592 
00593 void Annotation::setModificationDate( const QDateTime &date )
00594 {
00595     Q_D( Annotation );
00596     d->m_modifyDate = date;
00597 }
00598 
00599 QDateTime Annotation::modificationDate() const
00600 {
00601     Q_D( const Annotation );
00602     return d->m_modifyDate;
00603 }
00604 
00605 void Annotation::setCreationDate( const QDateTime &date )
00606 {
00607     Q_D( Annotation );
00608     d->m_creationDate = date;
00609 }
00610 
00611 QDateTime Annotation::creationDate() const
00612 {
00613     Q_D( const Annotation );
00614     return d->m_creationDate;
00615 }
00616 
00617 void Annotation::setFlags( int flags )
00618 {
00619     Q_D( Annotation );
00620     d->m_flags = flags;
00621 }
00622 
00623 int Annotation::flags() const
00624 {
00625     Q_D( const Annotation );
00626     return d->m_flags;
00627 }
00628 
00629 void Annotation::setBoundingRectangle( const NormalizedRect &rectangle )
00630 {
00631     Q_D( Annotation );
00632     d->m_boundary = rectangle;
00633     d->resetTransformation();
00634     if ( d->m_page )
00635     {
00636         d->transform( d->m_page->rotationMatrix() );
00637     }
00638 }
00639 
00640 NormalizedRect Annotation::boundingRectangle() const
00641 {
00642     Q_D( const Annotation );
00643     return d->m_boundary;
00644 }
00645 
00646 NormalizedRect Annotation::transformedBoundingRectangle() const
00647 {
00648     Q_D( const Annotation );
00649     return d->m_transformedBoundary;
00650 }
00651 
00652 void Annotation::translate( const NormalizedPoint &coord )
00653 {
00654     Q_D( Annotation );
00655     d->translate( coord );
00656     d->resetTransformation();
00657     if ( d->m_page )
00658     {
00659         d->transform( d->m_page->rotationMatrix() );
00660     }
00661 }
00662 
00663 Annotation::Style & Annotation::style()
00664 {
00665     Q_D( Annotation );
00666     return d->m_style;
00667 }
00668 
00669 const Annotation::Style & Annotation::style() const
00670 {
00671     Q_D( const Annotation );
00672     return d->m_style;
00673 }
00674 
00675 Annotation::Window & Annotation::window()
00676 {
00677     Q_D( Annotation );
00678     return d->m_window;
00679 }
00680 
00681 const Annotation::Window & Annotation::window() const
00682 {
00683     Q_D( const Annotation );
00684     return d->m_window;
00685 }
00686 
00687 QLinkedList< Annotation::Revision > & Annotation::revisions()
00688 {
00689     Q_D( Annotation );
00690     return d->m_revisions;
00691 }
00692 
00693 const QLinkedList< Annotation::Revision > & Annotation::revisions() const
00694 {
00695     Q_D( const Annotation );
00696     return d->m_revisions;
00697 }
00698 
00699 void Annotation::store( QDomNode & annNode, QDomDocument & document ) const
00700 {
00701     Q_D( const Annotation );
00702     // create [base] element of the annotation node
00703     QDomElement e = document.createElement( "base" );
00704     annNode.appendChild( e );
00705 
00706     // store -contents- attributes
00707     if ( !d->m_author.isEmpty() )
00708         e.setAttribute( "author", d->m_author );
00709     if ( !d->m_contents.isEmpty() )
00710         e.setAttribute( "contents", d->m_contents );
00711     if ( !d->m_uniqueName.isEmpty() )
00712         e.setAttribute( "uniqueName", d->m_uniqueName );
00713     if ( d->m_modifyDate.isValid() )
00714         e.setAttribute( "modifyDate", d->m_modifyDate.toString(Qt::ISODate) );
00715     if ( d->m_creationDate.isValid() )
00716         e.setAttribute( "creationDate", d->m_creationDate.toString(Qt::ISODate) );
00717 
00718     // store -other- attributes
00719     if ( d->m_flags )
00720         e.setAttribute( "flags", d->m_flags );
00721     if ( d->m_style.color().isValid() )
00722         e.setAttribute( "color", d->m_style.color().name() );
00723     if ( d->m_style.opacity() != 1.0 )
00724         e.setAttribute( "opacity", d->m_style.opacity() );
00725 
00726     // Sub-Node-1 - boundary
00727     QDomElement bE = document.createElement( "boundary" );
00728     e.appendChild( bE );
00729     bE.setAttribute( "l", (double)d->m_boundary.left );
00730     bE.setAttribute( "t", (double)d->m_boundary.top );
00731     bE.setAttribute( "r", (double)d->m_boundary.right );
00732     bE.setAttribute( "b", (double)d->m_boundary.bottom );
00733 
00734     // Sub-Node-2 - penStyle
00735     if ( d->m_style.width() != 1 || d->m_style.lineStyle() != Solid || d->m_style.xCorners() != 0 ||
00736          d->m_style.yCorners() != 0.0 || d->m_style.marks() != 3 || d->m_style.spaces() != 0 )
00737     {
00738         QDomElement psE = document.createElement( "penStyle" );
00739         e.appendChild( psE );
00740         psE.setAttribute( "width", d->m_style.width() );
00741         psE.setAttribute( "style", (int)d->m_style.lineStyle() );
00742         psE.setAttribute( "xcr", d->m_style.xCorners() );
00743         psE.setAttribute( "ycr", d->m_style.yCorners() );
00744         psE.setAttribute( "marks", d->m_style.marks() );
00745         psE.setAttribute( "spaces", d->m_style.spaces() );
00746     }
00747 
00748     // Sub-Node-3 - penEffect
00749     if ( d->m_style.lineEffect() != NoEffect || d->m_style.effectIntensity() != 1.0 )
00750     {
00751         QDomElement peE = document.createElement( "penEffect" );
00752         e.appendChild( peE );
00753         peE.setAttribute( "effect", (int)d->m_style.lineEffect() );
00754         peE.setAttribute( "intensity", d->m_style.effectIntensity() );
00755     }
00756 
00757     // Sub-Node-4 - window
00758     if ( d->m_window.flags() != -1 || !d->m_window.title().isEmpty() ||
00759          !d->m_window.summary().isEmpty() || !d->m_window.text().isEmpty() )
00760     {
00761         QDomElement wE = document.createElement( "window" );
00762         e.appendChild( wE );
00763         wE.setAttribute( "flags", d->m_window.flags() );
00764         wE.setAttribute( "top", d->m_window.topLeft().x );
00765         wE.setAttribute( "left", d->m_window.topLeft().y );
00766         wE.setAttribute( "width", d->m_window.width() );
00767         wE.setAttribute( "height", d->m_window.height() );
00768         wE.setAttribute( "title", d->m_window.title() );
00769         wE.setAttribute( "summary", d->m_window.summary() );
00770         // store window.text as a subnode, because we need escaped data
00771         if ( !d->m_window.text().isEmpty() )
00772         {
00773             QDomElement escapedText = document.createElement( "text" );
00774             wE.appendChild( escapedText );
00775             QDomCDATASection textCData = document.createCDATASection( d->m_window.text() );
00776             escapedText.appendChild( textCData );
00777         }
00778     }
00779 
00780     // create [revision] element of the annotation node (if any)
00781     if ( d->m_revisions.isEmpty() )
00782         return;
00783 
00784     // add all revisions as children of revisions element
00785     QLinkedList< Revision >::const_iterator it = d->m_revisions.begin(), end = d->m_revisions.end();
00786     for ( ; it != end; ++it )
00787     {
00788         // create revision element
00789         const Revision & revision = *it;
00790         QDomElement r = document.createElement( "revision" );
00791         annNode.appendChild( r );
00792         // set element attributes
00793         r.setAttribute( "revScope", (int)revision.scope() );
00794         r.setAttribute( "revType", (int)revision.type() );
00795         // use revision as the annotation element, so fill it up
00796         AnnotationUtils::storeAnnotation( revision.annotation(), r, document );
00797     }
00798 }
00799 
00800 void AnnotationPrivate::annotationTransform( const QMatrix &matrix )
00801 {
00802     resetTransformation();
00803     transform( matrix );
00804 }
00805 
00806 void AnnotationPrivate::transform( const QMatrix &matrix )
00807 {
00808     m_transformedBoundary.transform( matrix );
00809 }
00810 
00811 void AnnotationPrivate::baseTransform( const QMatrix &matrix )
00812 {
00813     m_boundary.transform( matrix );
00814 }
00815 
00816 void AnnotationPrivate::resetTransformation()
00817 {
00818     m_transformedBoundary = m_boundary;
00819 }
00820 
00821 void AnnotationPrivate::translate( const NormalizedPoint &coord )
00822 {
00823     m_boundary.left = m_boundary.left + coord.x;
00824     m_boundary.right = m_boundary.right + coord.x;
00825     m_boundary.top = m_boundary.top + coord.y;
00826     m_boundary.bottom = m_boundary.bottom + coord.y;
00827 }
00828 
00829 //END Annotation implementation
00830 
00831 
00834 class Okular::TextAnnotationPrivate : public Okular::AnnotationPrivate
00835 {
00836     public:
00837         TextAnnotationPrivate()
00838             : AnnotationPrivate(), m_textType( TextAnnotation::Linked ),
00839               m_textIcon( "Note" ), m_inplaceAlign( 0 ),
00840               m_inplaceIntent( TextAnnotation::Unknown )
00841         {
00842         }
00843 
00844         virtual void transform( const QMatrix &matrix );
00845         virtual void baseTransform( const QMatrix &matrix );
00846         virtual void resetTransformation();
00847         virtual void translate( const NormalizedPoint &coord );
00848 
00849         TextAnnotation::TextType m_textType;
00850         QString m_textIcon;
00851         QFont m_textFont;
00852         int m_inplaceAlign;
00853         QString m_inplaceText;
00854         NormalizedPoint m_inplaceCallout[3];
00855         NormalizedPoint m_transformedInplaceCallout[3];
00856         TextAnnotation::InplaceIntent m_inplaceIntent;
00857 };
00858 
00859 /*
00860   The default textIcon for text annotation is Note as the PDF Reference says
00861 */
00862 TextAnnotation::TextAnnotation()
00863     : Annotation( *new TextAnnotationPrivate() )
00864 {
00865 }
00866 
00867 TextAnnotation::TextAnnotation( const QDomNode & node )
00868     : Annotation( *new TextAnnotationPrivate(), node )
00869 {
00870     Q_D( TextAnnotation );
00871     // loop through the whole children looking for a 'text' element
00872     QDomNode subNode = node.firstChild();
00873     while( subNode.isElement() )
00874     {
00875         QDomElement e = subNode.toElement();
00876         subNode = subNode.nextSibling();
00877         if ( e.tagName() != "text" )
00878             continue;
00879 
00880         // parse the attributes
00881         if ( e.hasAttribute( "type" ) )
00882             d->m_textType = (TextAnnotation::TextType)e.attribute( "type" ).toInt();
00883         if ( e.hasAttribute( "icon" ) )
00884             d->m_textIcon = e.attribute( "icon" );
00885         if ( e.hasAttribute( "font" ) )
00886             d->m_textFont.fromString( e.attribute( "font" ) );
00887         if ( e.hasAttribute( "align" ) )
00888             d->m_inplaceAlign = e.attribute( "align" ).toInt();
00889         if ( e.hasAttribute( "intent" ) )
00890             d->m_inplaceIntent = (TextAnnotation::InplaceIntent)e.