• 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.attribute( "intent" ).toInt();
00891 
00892         // parse the subnodes
00893         QDomNode eSubNode = e.firstChild();
00894         while ( eSubNode.isElement() )
00895         {
00896             QDomElement ee = eSubNode.toElement();
00897             eSubNode = eSubNode.nextSibling();
00898 
00899             if ( ee.tagName() == "escapedText" )
00900             {
00901                 d->m_inplaceText = ee.firstChild().toCDATASection().data();
00902             }
00903             else if ( ee.tagName() == "callout" )
00904             {
00905                 d->m_inplaceCallout[0].x = ee.attribute( "ax" ).toDouble();
00906                 d->m_inplaceCallout[0].y = ee.attribute( "ay" ).toDouble();
00907                 d->m_inplaceCallout[1].x = ee.attribute( "bx" ).toDouble();
00908                 d->m_inplaceCallout[1].y = ee.attribute( "by" ).toDouble();
00909                 d->m_inplaceCallout[2].x = ee.attribute( "cx" ).toDouble();
00910                 d->m_inplaceCallout[2].y = ee.attribute( "cy" ).toDouble();
00911             }
00912         }
00913 
00914         // loading complete
00915         break;
00916     }
00917 
00918     for ( int i = 0; i < 3; ++i )
00919         d->m_transformedInplaceCallout[i] = d->m_inplaceCallout[i];
00920 }
00921 
00922 TextAnnotation::~TextAnnotation()
00923 {
00924 }
00925 
00926 void TextAnnotation::setTextType( TextType textType )
00927 {
00928     Q_D( TextAnnotation );
00929     d->m_textType = textType;
00930 }
00931 
00932 TextAnnotation::TextType TextAnnotation::textType() const
00933 {
00934     Q_D( const TextAnnotation );
00935     return d->m_textType;
00936 }
00937 
00938 void TextAnnotation::setTextIcon( const QString &icon )
00939 {
00940     Q_D( TextAnnotation );
00941     d->m_textIcon = icon;
00942 }
00943 
00944 QString TextAnnotation::textIcon() const
00945 {
00946     Q_D( const TextAnnotation );
00947     return d->m_textIcon;
00948 }
00949 
00950 void TextAnnotation::setTextFont( const QFont &font )
00951 {
00952     Q_D( TextAnnotation );
00953     d->m_textFont = font;
00954 }
00955 
00956 QFont TextAnnotation::textFont() const
00957 {
00958     Q_D( const TextAnnotation );
00959     return d->m_textFont;
00960 }
00961 
00962 void TextAnnotation::setInplaceAlignment( int alignment )
00963 {
00964     Q_D( TextAnnotation );
00965     d->m_inplaceAlign = alignment;
00966 }
00967 
00968 int TextAnnotation::inplaceAlignment() const
00969 {
00970     Q_D( const TextAnnotation );
00971     return d->m_inplaceAlign;
00972 }
00973 
00974 void TextAnnotation::setInplaceText( const QString &text )
00975 {
00976     Q_D( TextAnnotation );
00977     d->m_inplaceText = text;
00978 }
00979 
00980 QString TextAnnotation::inplaceText() const
00981 {
00982     Q_D( const TextAnnotation );
00983     return d->m_inplaceText;
00984 }
00985 
00986 void TextAnnotation::setInplaceCallout( const NormalizedPoint &point, int index )
00987 {
00988     if ( index < 0 || index > 2 )
00989         return;
00990 
00991     Q_D( TextAnnotation );
00992     d->m_inplaceCallout[ index ] = point;
00993 }
00994 
00995 NormalizedPoint TextAnnotation::inplaceCallout( int index ) const
00996 {
00997     if ( index < 0 || index > 2 )
00998         return NormalizedPoint();
00999 
01000     Q_D( const TextAnnotation );
01001     return d->m_inplaceCallout[ index ];
01002 }
01003 
01004 NormalizedPoint TextAnnotation::transformedInplaceCallout( int index ) const
01005 {
01006     if ( index < 0 || index > 2 )
01007         return NormalizedPoint();
01008 
01009     Q_D( const TextAnnotation );
01010     return d->m_transformedInplaceCallout[ index ];
01011 }
01012 
01013 void TextAnnotation::setInplaceIntent( InplaceIntent intent )
01014 {
01015     Q_D( TextAnnotation );
01016     d->m_inplaceIntent = intent;
01017 }
01018 
01019 TextAnnotation::InplaceIntent TextAnnotation::inplaceIntent() const
01020 {
01021     Q_D( const TextAnnotation );
01022     return d->m_inplaceIntent;
01023 }
01024 
01025 Annotation::SubType TextAnnotation::subType() const
01026 {
01027     return AText;
01028 }
01029 
01030 void TextAnnotation::store( QDomNode & node, QDomDocument & document ) const
01031 {
01032     Q_D( const TextAnnotation );
01033     // recurse to parent objects storing properties
01034     Annotation::store( node, document );
01035 
01036     // create [text] element
01037     QDomElement textElement = document.createElement( "text" );
01038     node.appendChild( textElement );
01039 
01040     // store the optional attributes
01041     if ( d->m_textType != Linked )
01042         textElement.setAttribute( "type", (int)d->m_textType );
01043     if ( d->m_textIcon != "Comment" )
01044         textElement.setAttribute( "icon", d->m_textIcon );
01045     if ( d->m_textFont != QApplication::font() )
01046         textElement.setAttribute( "font", d->m_textFont.toString() );
01047     if ( d->m_inplaceAlign )
01048         textElement.setAttribute( "align", d->m_inplaceAlign );
01049     if ( d->m_inplaceIntent != Unknown )
01050         textElement.setAttribute( "intent", (int)d->m_inplaceIntent );
01051 
01052     // Sub-Node-1 - escapedText
01053     if ( !d->m_inplaceText.isEmpty() )
01054     {
01055         QDomElement escapedText = document.createElement( "escapedText" );
01056         textElement.appendChild( escapedText );
01057         QDomCDATASection textCData = document.createCDATASection( d->m_inplaceText );
01058         escapedText.appendChild( textCData );
01059     }
01060 
01061     // Sub-Node-2 - callout
01062     if ( d->m_inplaceCallout[0].x != 0.0 )
01063     {
01064         QDomElement calloutElement = document.createElement( "callout" );
01065         textElement.appendChild( calloutElement );
01066         calloutElement.setAttribute( "ax", d->m_inplaceCallout[0].x );
01067         calloutElement.setAttribute( "ay", d->m_inplaceCallout[0].y );
01068         calloutElement.setAttribute( "bx", d->m_inplaceCallout[1].x );
01069         calloutElement.setAttribute( "by", d->m_inplaceCallout[1].y );
01070         calloutElement.setAttribute( "cx", d->m_inplaceCallout[2].x );
01071         calloutElement.setAttribute( "cy", d->m_inplaceCallout[2].y );
01072     }
01073 }
01074 
01075 void TextAnnotationPrivate::transform( const QMatrix &matrix )
01076 {
01077     AnnotationPrivate::transform( matrix );
01078 
01079     for ( int i = 0; i < 3; ++i ) {
01080        m_transformedInplaceCallout[i].transform( matrix );
01081     }
01082 }
01083 
01084 void TextAnnotationPrivate::baseTransform( const QMatrix &matrix )
01085 {
01086     AnnotationPrivate::baseTransform( matrix );
01087 
01088     for ( int i = 0; i < 3; ++i ) {
01089        m_inplaceCallout[i].transform( matrix );
01090     }
01091 }
01092 
01093 void TextAnnotationPrivate::resetTransformation()
01094 {
01095     AnnotationPrivate::resetTransformation();
01096 
01097     for ( int i = 0; i < 3; ++i ) {
01098        m_transformedInplaceCallout[i] = m_inplaceCallout[i];
01099     }
01100 }
01101 
01102 void TextAnnotationPrivate::translate( const NormalizedPoint &coord )
01103 {
01104     AnnotationPrivate::translate( coord );
01105 
01106 #define ADD_COORD( c1, c2 ) \
01107 { \
01108   c1.x = c1.x + c2.x; \
01109   c1.y = c1.y + c2.y; \
01110 }
01111     ADD_COORD( m_inplaceCallout[0], coord )
01112     ADD_COORD( m_inplaceCallout[1], coord )
01113     ADD_COORD( m_inplaceCallout[2], coord )
01114 #undef ADD_COORD
01115 }
01116 
01119 class Okular::LineAnnotationPrivate : public Okular::AnnotationPrivate
01120 {
01121     public:
01122         LineAnnotationPrivate()
01123             : AnnotationPrivate(),
01124               m_lineStartStyle( LineAnnotation::None ), m_lineEndStyle( LineAnnotation::None ),
01125               m_lineClosed( false ), m_lineShowCaption( false ), m_lineLeadingFwdPt( 0 ),
01126               m_lineLeadingBackPt( 0 ), m_lineIntent( LineAnnotation::Unknown )
01127         {
01128         }
01129 
01130         virtual void transform( const QMatrix &matrix );
01131         virtual void baseTransform( const QMatrix &matrix );
01132         virtual void resetTransformation();
01133         virtual void translate( const NormalizedPoint &coord );
01134 
01135         QLinkedList<NormalizedPoint> m_linePoints;
01136         QLinkedList<NormalizedPoint> m_transformedLinePoints;
01137         LineAnnotation::TermStyle m_lineStartStyle;
01138         LineAnnotation::TermStyle m_lineEndStyle;
01139         bool m_lineClosed : 1;
01140         bool m_lineShowCaption : 1;
01141         QColor m_lineInnerColor;
01142         double m_lineLeadingFwdPt;
01143         double m_lineLeadingBackPt;
01144         LineAnnotation::LineIntent m_lineIntent;
01145 };
01146 
01147 LineAnnotation::LineAnnotation()
01148     : Annotation( *new LineAnnotationPrivate() )
01149 {
01150 }
01151 
01152 LineAnnotation::LineAnnotation( const QDomNode & node )
01153     : Annotation( *new LineAnnotationPrivate(), node )
01154 {
01155     Q_D( LineAnnotation );
01156     // loop through the whole children looking for a 'line' element
01157     QDomNode subNode = node.firstChild();
01158     while( subNode.isElement() )
01159     {
01160         QDomElement e = subNode.toElement();
01161         subNode = subNode.nextSibling();
01162         if ( e.tagName() != "line" )
01163             continue;
01164 
01165         // parse the attributes
01166         if ( e.hasAttribute( "startStyle" ) )
01167             d->m_lineStartStyle = (LineAnnotation::TermStyle)e.attribute( "startStyle" ).toInt();
01168         if ( e.hasAttribute( "endStyle" ) )
01169             d->m_lineEndStyle = (LineAnnotation::TermStyle)e.attribute( "endStyle" ).toInt();
01170         if ( e.hasAttribute( "closed" ) )
01171             d->m_lineClosed = e.attribute( "closed" ).toInt();
01172         if ( e.hasAttribute( "innerColor" ) )
01173             d->m_lineInnerColor = QColor( e.attribute( "innerColor" ) );
01174         if ( e.hasAttribute( "leadFwd" ) )
01175             d->m_lineLeadingFwdPt = e.attribute( "leadFwd" ).toDouble();
01176         if ( e.hasAttribute( "leadBack" ) )
01177             d->m_lineLeadingBackPt = e.attribute( "leadBack" ).toDouble();
01178         if ( e.hasAttribute( "showCaption" ) )
01179             d->m_lineShowCaption = e.attribute( "showCaption" ).toInt();
01180         if ( e.hasAttribute( "intent" ) )
01181             d->m_lineIntent = (LineAnnotation::LineIntent)e.attribute( "intent" ).toInt();
01182 
01183         // parse all 'point' subnodes
01184         QDomNode pointNode = e.firstChild();
01185         while ( pointNode.isElement() )
01186         {
01187             QDomElement pe = pointNode.toElement();
01188             pointNode = pointNode.nextSibling();
01189 
01190             if ( pe.tagName() != "point" )
01191                 continue;
01192 
01193             NormalizedPoint p;
01194             p.x = pe.attribute( "x", "0.0" ).toDouble();
01195             p.y = pe.attribute( "y", "0.0" ).toDouble();
01196             d->m_linePoints.append( p );
01197         }
01198 
01199         // loading complete
01200         break;
01201     }
01202 
01203     d->m_transformedLinePoints = d->m_linePoints;
01204 }
01205 
01206 LineAnnotation::~LineAnnotation()
01207 {
01208 }
01209 
01210 void LineAnnotation::setLinePoints( const QLinkedList<NormalizedPoint> &points )
01211 {
01212     Q_D( LineAnnotation );
01213     d->m_linePoints = points;
01214 }
01215 
01216 QLinkedList<NormalizedPoint> LineAnnotation::linePoints() const
01217 {
01218     Q_D( const LineAnnotation );
01219     return d->m_linePoints;
01220 }
01221 
01222 QLinkedList<NormalizedPoint> LineAnnotation::transformedLinePoints() const
01223 {
01224     Q_D( const LineAnnotation );
01225     return d->m_transformedLinePoints;
01226 }
01227 
01228 void LineAnnotation::setLineStartStyle( TermStyle style )
01229 {
01230     Q_D( LineAnnotation );
01231     d->m_lineStartStyle = style;
01232 }
01233 
01234 LineAnnotation::TermStyle LineAnnotation::lineStartStyle() const
01235 {
01236     Q_D( const LineAnnotation );
01237     return d->m_lineStartStyle;
01238 }
01239 
01240 void LineAnnotation::setLineEndStyle( TermStyle style )
01241 {
01242     Q_D( LineAnnotation );
01243     d->m_lineEndStyle = style;
01244 }
01245 
01246 LineAnnotation::TermStyle LineAnnotation::lineEndStyle() const
01247 {
01248     Q_D( const LineAnnotation );
01249     return d->m_lineEndStyle;
01250 }
01251 
01252 void LineAnnotation::setLineClosed( bool closed )
01253 {
01254     Q_D( LineAnnotation );
01255     d->m_lineClosed = closed;
01256 }
01257 
01258 bool LineAnnotation::lineClosed() const
01259 {
01260     Q_D( const LineAnnotation );
01261     return d->m_lineClosed;
01262 }
01263 
01264 void LineAnnotation::setLineInnerColor( const QColor &color )
01265 {
01266     Q_D( LineAnnotation );
01267     d->m_lineInnerColor = color;
01268 }
01269 
01270 QColor LineAnnotation::lineInnerColor() const
01271 {
01272     Q_D( const LineAnnotation );
01273     return d->m_lineInnerColor;
01274 }
01275 
01276 void LineAnnotation::setLineLeadingForwardPoint( double point )
01277 {
01278     Q_D( LineAnnotation );
01279     d->m_lineLeadingFwdPt = point;
01280 }
01281 
01282 double LineAnnotation::lineLeadingForwardPoint() const
01283 {
01284     Q_D( const LineAnnotation );
01285     return d->m_lineLeadingFwdPt;
01286 }
01287 
01288 void LineAnnotation::setLineLeadingBackwardPoint( double point )
01289 {
01290     Q_D( LineAnnotation );
01291     d->m_lineLeadingBackPt = point;
01292 }
01293 
01294 double LineAnnotation::lineLeadingBackwardPoint() const
01295 {
01296     Q_D( const LineAnnotation );
01297     return d->m_lineLeadingBackPt;
01298 }
01299 
01300 void LineAnnotation::setShowCaption( bool show )
01301 {
01302     Q_D( LineAnnotation );
01303     d->m_lineShowCaption = show;
01304 }
01305 
01306 bool LineAnnotation::showCaption() const
01307 {
01308     Q_D( const LineAnnotation );
01309     return d->m_lineShowCaption;
01310 }
01311 
01312 void LineAnnotation::setLineIntent( LineIntent intent )
01313 {
01314     Q_D( LineAnnotation );
01315     d->m_lineIntent = intent;
01316 }
01317 
01318 LineAnnotation::LineIntent LineAnnotation::lineIntent() const
01319 {
01320     Q_D( const LineAnnotation );
01321     return d->m_lineIntent;
01322 }
01323 
01324 Annotation::SubType LineAnnotation::subType() const
01325 {
01326     return ALine;
01327 }
01328 
01329 void LineAnnotation::store( QDomNode & node, QDomDocument & document ) const
01330 {
01331     Q_D( const LineAnnotation );
01332     // recurse to parent objects storing properties
01333     Annotation::store( node, document );
01334 
01335     // create [line] element
01336     QDomElement lineElement = document.createElement( "line" );
01337     node.appendChild( lineElement );
01338 
01339     // store the attributes
01340     if ( d->m_lineStartStyle != None )
01341         lineElement.setAttribute( "startStyle", (int)d->m_lineStartStyle );
01342     if ( d->m_lineEndStyle != None )
01343         lineElement.setAttribute( "endStyle", (int)d->m_lineEndStyle );
01344     if ( d->m_lineClosed )
01345         lineElement.setAttribute( "closed", d->m_lineClosed );
01346     if ( d->m_lineInnerColor.isValid() )
01347         lineElement.setAttribute( "innerColor", d->m_lineInnerColor.name() );
01348     if ( d->m_lineLeadingFwdPt != 0.0 )
01349         lineElement.setAttribute( "leadFwd", d->m_lineLeadingFwdPt );
01350     if ( d->m_lineLeadingBackPt != 0.0 )
01351         lineElement.setAttribute( "leadBack", d->m_lineLeadingBackPt );
01352     if ( d->m_lineShowCaption )
01353         lineElement.setAttribute( "showCaption", d->m_lineShowCaption );
01354     if ( d->m_lineIntent != Unknown )
01355         lineElement.setAttribute( "intent", d->m_lineIntent );
01356 
01357     // append the list of points
01358     int points = d->m_linePoints.count();
01359     if ( points > 1 )
01360     {
01361         QLinkedList<NormalizedPoint>::const_iterator it = d->m_linePoints.begin(), end = d->m_linePoints.end();
01362         while ( it != end )
01363         {
01364             const NormalizedPoint & p = *it;
01365             QDomElement pElement = document.createElement( "point" );
01366             lineElement.appendChild( pElement );
01367             pElement.setAttribute( "x", p.x );
01368             pElement.setAttribute( "y", p.y );
01369             it++; //to avoid loop
01370         }
01371     }
01372 }
01373 
01374 void LineAnnotationPrivate::transform( const QMatrix &matrix )
01375 {
01376     AnnotationPrivate::transform( matrix );
01377 
01378     QMutableLinkedListIterator<NormalizedPoint> it( m_transformedLinePoints );
01379     while ( it.hasNext() )
01380         it.next().transform( matrix );
01381 }
01382 
01383 void LineAnnotationPrivate::baseTransform( const QMatrix &matrix )
01384 {
01385     AnnotationPrivate::baseTransform( matrix );
01386 
01387     QMutableLinkedListIterator<NormalizedPoint> it( m_linePoints );
01388     while ( it.hasNext() )
01389         it.next().transform( matrix );
01390 }
01391 
01392 void LineAnnotationPrivate::resetTransformation()
01393 {
01394     AnnotationPrivate::resetTransformation();
01395 
01396     m_transformedLinePoints = m_linePoints;
01397 }
01398 
01399 void LineAnnotationPrivate::translate( const NormalizedPoint &coord )
01400 {
01401     AnnotationPrivate::translate( coord );
01402 
01403     QMutableLinkedListIterator<NormalizedPoint> it( m_linePoints );
01404     while ( it.hasNext() )
01405     {
01406         NormalizedPoint& p = it.next();
01407         p.x = p.x + coord.x;
01408         p.y = p.y + coord.y;
01409     }
01410 }
01411 
01414 class Okular::GeomAnnotationPrivate : public Okular::AnnotationPrivate
01415 {
01416     public:
01417         GeomAnnotationPrivate()
01418             : AnnotationPrivate(), m_geomType( GeomAnnotation::InscribedSquare ),
01419               m_geomWidthPt( 18 )
01420         {
01421         }
01422 
01423         GeomAnnotation::GeomType m_geomType;
01424         QColor m_geomInnerColor;
01425         int m_geomWidthPt;
01426 };
01427 
01428 GeomAnnotation::GeomAnnotation()
01429     : Annotation( *new GeomAnnotationPrivate() )
01430 {
01431 }
01432 
01433 GeomAnnotation::GeomAnnotation( const QDomNode & node )
01434     : Annotation( *new GeomAnnotationPrivate(), node )
01435 {
01436     Q_D( GeomAnnotation );
01437     // loop through the whole children looking for a 'geom' element
01438     QDomNode subNode = node.firstChild();
01439     while( subNode.isElement() )
01440     {
01441         QDomElement e = subNode.toElement();
01442         subNode = subNode.nextSibling();
01443         if ( e.tagName() != "geom" )
01444             continue;
01445 
01446         // parse the attributes
01447         if ( e.hasAttribute( "type" ) )
01448             d->m_geomType = (GeomAnnotation::GeomType)e.attribute( "type" ).toInt();
01449         if ( e.hasAttribute( "color" ) )
01450             d->m_geomInnerColor = QColor( e.attribute( "color" ) );
01451         if ( e.hasAttribute( "width" ) )
01452             d->m_geomWidthPt = e.attribute( "width" ).toInt();
01453 
01454         // loading complete
01455         break;
01456     }
01457 }
01458 
01459 GeomAnnotation::~GeomAnnotation()
01460 {
01461 }
01462 
01463 void GeomAnnotation::setGeometricalType( GeomType type )
01464 {
01465     Q_D( GeomAnnotation );
01466     d->m_geomType = type;
01467 }
01468 
01469 GeomAnnotation::GeomType GeomAnnotation::geometricalType() const
01470 {
01471     Q_D( const GeomAnnotation );
01472     return d->m_geomType;
01473 }
01474 
01475 void GeomAnnotation::setGeometricalInnerColor( const QColor &color )
01476 {
01477     Q_D( GeomAnnotation );
01478     d->m_geomInnerColor = color;
01479 }
01480 
01481 QColor GeomAnnotation::geometricalInnerColor() const
01482 {
01483     Q_D( const GeomAnnotation );
01484     return d->m_geomInnerColor;
01485 }
01486 
01487 void GeomAnnotation::setGeometricalPointWidth( int width )
01488 {
01489     Q_D( GeomAnnotation );
01490     d->m_geomWidthPt = width;
01491 }
01492 
01493 int GeomAnnotation::geometricalPointWidth() const
01494 {
01495     Q_D( const GeomAnnotation );
01496     return d->m_geomWidthPt;
01497 }
01498 
01499 Annotation::SubType GeomAnnotation::subType() const
01500 {
01501     return AGeom;
01502 }
01503 
01504 void GeomAnnotation::store( QDomNode & node, QDomDocument & document ) const
01505 {
01506     Q_D( const GeomAnnotation );
01507     // recurse to parent objects storing properties
01508     Annotation::store( node, document );
01509 
01510     // create [geom] element
01511     QDomElement geomElement = document.createElement( "geom" );
01512     node.appendChild( geomElement );
01513 
01514     // append the optional attributes
01515     if ( d->m_geomType != InscribedSquare )
01516         geomElement.setAttribute( "type", (int)d->m_geomType );
01517     if ( d->m_geomInnerColor.isValid() )
01518         geomElement.setAttribute( "color", d->m_geomInnerColor.name() );
01519     if ( d->m_geomWidthPt != 18 )
01520         geomElement.setAttribute( "width", d->m_geomWidthPt );
01521 }
01522 
01525 class HighlightAnnotation::Quad::Private
01526 {
01527     public:
01528         Private()
01529         {
01530         }
01531 
01532         NormalizedPoint m_points[4];
01533         NormalizedPoint m_transformedPoints[4];
01534         bool m_capStart : 1;
01535         bool m_capEnd : 1;
01536         double m_feather;
01537 };
01538 
01539 HighlightAnnotation::Quad::Quad()
01540     : d( new Private )
01541 {
01542 }
01543 
01544 HighlightAnnotation::Quad::~Quad()
01545 {
01546     delete d;
01547 }
01548 
01549 HighlightAnnotation::Quad::Quad( const Quad &other )
01550     : d( new Private )
01551 {
01552     *d = *other.d;
01553 }
01554 
01555 HighlightAnnotation::Quad& HighlightAnnotation::Quad::operator=( const Quad &other )
01556 {
01557     if ( this != &other )
01558         *d = *other.d;
01559 
01560     return *this;
01561 }
01562 
01563 void HighlightAnnotation::Quad::setPoint( const NormalizedPoint &point, int index )
01564 {
01565     if ( index < 0 || index > 3 )
01566         return;
01567 
01568     d->m_points[ index ] = point;
01569 }
01570 
01571 NormalizedPoint HighlightAnnotation::Quad::point( int index ) const
01572 {
01573     if ( index < 0 || index > 3 )
01574         return NormalizedPoint();
01575 
01576     return d->m_points[ index ];
01577 }
01578 
01579 NormalizedPoint HighlightAnnotation::Quad::transformedPoint( int index ) const
01580 {
01581     if ( index < 0 || index > 3 )
01582         return NormalizedPoint();
01583 
01584     return d->m_transformedPoints[ index ];
01585 }
01586 
01587 void HighlightAnnotation::Quad::setCapStart( bool value )
01588 {
01589     d->m_capStart = value;
01590 }
01591 
01592 bool HighlightAnnotation::Quad::capStart() const
01593 {
01594     return d->m_capStart;
01595 }
01596 
01597 void HighlightAnnotation::Quad::setCapEnd( bool value )
01598 {
01599     d->m_capEnd = value;
01600 }
01601 
01602 bool HighlightAnnotation::Quad::capEnd() const
01603 {
01604     return d->m_capEnd;
01605 }
01606 
01607 void HighlightAnnotation::Quad::setFeather( double width )
01608 {
01609     d->m_feather = width;
01610 }
01611 
01612 double HighlightAnnotation::Quad::feather() const
01613 {
01614     return d->m_feather;
01615 }
01616 
01617 void HighlightAnnotation::Quad::transform( const QMatrix &matrix )
01618 {
01619     for ( int i = 0; i < 4; ++i ) {
01620         d->m_transformedPoints[ i ] = d->m_points[ i ];
01621         d->m_transformedPoints[ i ].transform( matrix );
01622     }
01623 }
01624 
01625 
01626 class Okular::HighlightAnnotationPrivate : public Okular::AnnotationPrivate
01627 {
01628     public:
01629         HighlightAnnotationPrivate()
01630             : AnnotationPrivate(), m_highlightType( HighlightAnnotation::Highlight )
01631         {
01632         }
01633 
01634         virtual void transform( const QMatrix &matrix );
01635         virtual void baseTransform( const QMatrix &matrix );
01636 
01637         HighlightAnnotation::HighlightType m_highlightType;
01638         QList< HighlightAnnotation::Quad > m_highlightQuads;
01639 };
01640 
01641 HighlightAnnotation::HighlightAnnotation()
01642     : Annotation( *new HighlightAnnotationPrivate() )
01643 {
01644 }
01645 
01646 HighlightAnnotation::HighlightAnnotation( const QDomNode & node )
01647     : Annotation( *new HighlightAnnotationPrivate(), node )
01648 {
01649     Q_D( HighlightAnnotation );
01650     // loop through the whole children looking for a 'hl' element
01651     QDomNode subNode = node.firstChild();
01652     while( subNode.isElement() )
01653     {
01654         QDomElement e = subNode.toElement();
01655         subNode = subNode.nextSibling();
01656         if ( e.tagName() != "hl" )
01657             continue;
01658 
01659         // parse the attributes
01660         if ( e.hasAttribute( "type" ) )
01661             d->m_highlightType = (HighlightAnnotation::HighlightType)e.attribute( "type" ).toInt();
01662 
01663         // parse all 'quad' subnodes
01664         QDomNode quadNode = e.firstChild();
01665         for ( ; quadNode.isElement(); quadNode = quadNode.nextSibling() )
01666         {
01667             QDomElement qe = quadNode.toElement();
01668             if ( qe.tagName() != "quad" )
01669                 continue;
01670 
01671             HighlightAnnotation::Quad q;
01672             q.setPoint( NormalizedPoint( qe.attribute( "ax", "0.0" ).toDouble(), qe.attribute( "ay", "0.0" ).toDouble() ), 0 );
01673             q.setPoint( NormalizedPoint( qe.attribute( "bx", "0.0" ).toDouble(), qe.attribute( "by", "0.0" ).toDouble() ), 1 );
01674             q.setPoint( NormalizedPoint( qe.attribute( "cx", "0.0" ).toDouble(), qe.attribute( "cy", "0.0" ).toDouble() ), 2 );
01675             q.setPoint( NormalizedPoint( qe.attribute( "dx", "0.0" ).toDouble(), qe.attribute( "dy", "0.0" ).toDouble() ), 3 );
01676             q.setCapStart( qe.hasAttribute( "start" ) );
01677             q.setCapEnd( qe.hasAttribute( "end" ) );
01678             q.setFeather( qe.attribute( "feather", "0.1" ).toDouble() );
01679 
01680             q.transform( QMatrix() );
01681 
01682             d->m_highlightQuads.append( q );
01683         }
01684 
01685         // loading complete
01686         break;
01687     }
01688 }
01689 
01690 HighlightAnnotation::~HighlightAnnotation()
01691 {
01692 }
01693 
01694 void HighlightAnnotation::setHighlightType( HighlightType type )
01695 {
01696     Q_D( HighlightAnnotation );
01697     d->m_highlightType = type;
01698 }
01699 
01700 HighlightAnnotation::HighlightType HighlightAnnotation::highlightType() const
01701 {
01702     Q_D( const HighlightAnnotation );
01703     return d->m_highlightType;
01704 }
01705 
01706 QList< HighlightAnnotation::Quad > & HighlightAnnotation::highlightQuads()
01707 {
01708     Q_D( HighlightAnnotation );
01709     return d->m_highlightQuads;
01710 }
01711 
01712 void HighlightAnnotation::store( QDomNode & node, QDomDocument & document ) const
01713 {
01714     Q_D( const HighlightAnnotation );
01715     // recurse to parent objects storing properties
01716     Annotation::store( node, document );
01717 
01718     // create [hl] element
01719     QDomElement hlElement = document.createElement( "hl" );
01720     node.appendChild( hlElement );
01721 
01722     // append the optional attributes
01723     if ( d->m_highlightType != Highlight )
01724         hlElement.setAttribute( "type", (int)d->m_highlightType );
01725     if ( d->m_highlightQuads.count() < 1 )
01726         return;
01727     // append highlight quads, all children describe quads
01728     QList< Quad >::const_iterator it = d->m_highlightQuads.begin(), end = d->m_highlightQuads.end();
01729     for ( ; it != end; ++it )
01730     {
01731         QDomElement quadElement = document.createElement( "quad" );
01732         hlElement.appendChild( quadElement );
01733         const Quad & q = *it;
01734         quadElement.setAttribute( "ax", q.point( 0 ).x );
01735         quadElement.setAttribute( "ay", q.point( 0 ).y );
01736         quadElement.setAttribute( "bx", q.point( 1 ).x );
01737         quadElement.setAttribute( "by", q.point( 1 ).y );
01738         quadElement.setAttribute( "cx", q.point( 2 ).x );
01739         quadElement.setAttribute( "cy", q.point( 2 ).y );
01740         quadElement.setAttribute( "dx", q.point( 3 ).x );
01741         quadElement.setAttribute( "dy", q.point( 3 ).y );
01742         if ( q.capStart() )
01743             quadElement.setAttribute( "start", 1 );
01744         if ( q.capEnd() )
01745             quadElement.setAttribute( "end", 1 );
01746         quadElement.setAttribute( "feather", q.feather() );
01747     }
01748 }
01749 
01750 Annotation::SubType HighlightAnnotation::subType() const
01751 {
01752     return AHighlight;
01753 }
01754 
01755 void HighlightAnnotationPrivate::transform( const QMatrix &matrix )
01756 {
01757     AnnotationPrivate::transform( matrix );
01758 
01759     QMutableListIterator<HighlightAnnotation::Quad> it( m_highlightQuads );
01760     while ( it.hasNext() )
01761         it.next().transform( matrix );
01762 }
01763 
01764 void HighlightAnnotationPrivate::baseTransform( const QMatrix &matrix )
01765 {
01766     AnnotationPrivate::baseTransform( matrix );
01767 
01768     QMutableListIterator<HighlightAnnotation::Quad> it( m_highlightQuads );
01769     while ( it.hasNext() )
01770         it.next().transform( matrix );
01771 }
01772 
01775 class Okular::StampAnnotationPrivate : public Okular::AnnotationPrivate
01776 {
01777     public:
01778         StampAnnotationPrivate()
01779             : AnnotationPrivate(), m_stampIconName( "Draft" )
01780         {
01781         }
01782 
01783         QString m_stampIconName;
01784 };
01785 
01786 StampAnnotation::StampAnnotation()
01787     : Annotation( *new StampAnnotationPrivate() )
01788 {
01789 }
01790 
01791 StampAnnotation::StampAnnotation( const QDomNode & node )
01792     : Annotation( *new StampAnnotationPrivate(), node )
01793 {
01794     Q_D( StampAnnotation );
01795     // loop through the whole children looking for a 'stamp' element
01796     QDomNode subNode = node.firstChild();
01797     while( subNode.isElement() )
01798     {
01799         QDomElement e = subNode.toElement();
01800         subNode = subNode.nextSibling();
01801         if ( e.tagName() != "stamp" )
01802             continue;
01803 
01804         // parse the attributes
01805         if ( e.hasAttribute( "icon" ) )
01806             d->m_stampIconName = e.attribute( "icon" );
01807 
01808         // loading complete
01809         break;
01810     }
01811 }
01812 
01813 StampAnnotation::~StampAnnotation()
01814 {
01815 }
01816 
01817 void StampAnnotation::setStampIconName( const QString &name )
01818 {
01819     Q_D( StampAnnotation );
01820     d->m_stampIconName = name;
01821 }
01822 
01823 QString StampAnnotation::stampIconName() const
01824 {
01825     Q_D( const StampAnnotation );
01826     return d->m_stampIconName;
01827 }
01828 
01829 Annotation::SubType StampAnnotation::subType() const
01830 {
01831     return AStamp;
01832 }
01833 
01834 void StampAnnotation::store( QDomNode & node, QDomDocument & document ) const
01835 {
01836     Q_D( const StampAnnotation );
01837     // recurse to parent objects storing properties
01838     Annotation::store( node, document );
01839 
01840     // create [stamp] element
01841     QDomElement stampElement = document.createElement( "stamp" );
01842     node.appendChild( stampElement );
01843 
01844     // append the optional attributes
01845     if ( d->m_stampIconName != "Draft" )
01846         stampElement.setAttribute( "icon", d->m_stampIconName );
01847 }
01848 
01851 class Okular::InkAnnotationPrivate : public Okular::AnnotationPrivate
01852 {
01853     public:
01854         InkAnnotationPrivate()
01855             : AnnotationPrivate()
01856         {
01857         }
01858 
01859         virtual void transform( const QMatrix &matrix );
01860         virtual void baseTransform( const QMatrix &matrix );
01861         virtual void resetTransformation();
01862         virtual void translate( const NormalizedPoint &coord );
01863 
01864         QList< QLinkedList<NormalizedPoint> > m_inkPaths;
01865         QList< QLinkedList<NormalizedPoint> > m_transformedInkPaths;
01866 };
01867 
01868 InkAnnotation::InkAnnotation()
01869     : Annotation( *new InkAnnotationPrivate() )
01870 {
01871 }
01872 
01873 InkAnnotation::InkAnnotation( const QDomNode & node )
01874     : Annotation( *new InkAnnotationPrivate(), node )
01875 {
01876     Q_D( InkAnnotation );
01877     // loop through the whole children looking for a 'ink' element
01878     QDomNode subNode = node.firstChild();
01879     while( subNode.isElement() )
01880     {
01881         QDomElement e = subNode.toElement();
01882         subNode = subNode.nextSibling();
01883         if ( e.tagName() != "ink" )
01884             continue;
01885 
01886         // parse the 'path' subnodes
01887         QDomNode pathNode = e.firstChild();
01888         while ( pathNode.isElement() )
01889         {
01890             QDomElement pathElement = pathNode.toElement();
01891             pathNode = pathNode.nextSibling();
01892 
01893             if ( pathElement.tagName() != "path" )
01894                 continue;
01895 
01896             // build each path parsing 'point' subnodes
01897             QLinkedList<NormalizedPoint> path;
01898             QDomNode pointNode = pathElement.firstChild();
01899             while ( pointNode.isElement() )
01900             {
01901                 QDomElement pointElement = pointNode.toElement();
01902                 pointNode = pointNode.nextSibling();
01903 
01904                 if ( pointElement.tagName() != "point" )
01905                     continue;
01906 
01907                 NormalizedPoint p;
01908                 p.x = pointElement.attribute( "x", "0.0" ).toDouble();
01909                 p.y = pointElement.attribute( "y", "0.0" ).toDouble();
01910                 path.append( p );
01911             }
01912 
01913             // add the path to the path list if it contains at least 2 nodes
01914             if ( path.count() >= 2 )
01915                 d->m_inkPaths.append( path );
01916         }
01917 
01918         // loading complete
01919         break;
01920     }
01921 
01922     d->m_transformedInkPaths = d->m_inkPaths;
01923 }
01924 
01925 InkAnnotation::~InkAnnotation()
01926 {
01927 }
01928 
01929 void InkAnnotation::setInkPaths( const QList< QLinkedList<NormalizedPoint> > &paths )
01930 {
01931     Q_D( InkAnnotation );
01932     d->m_inkPaths = paths;
01933 }
01934 
01935 QList< QLinkedList<NormalizedPoint> > InkAnnotation::inkPaths() const
01936 {
01937     Q_D( const InkAnnotation );
01938     return d->m_inkPaths;
01939 }
01940 
01941 QList< QLinkedList<NormalizedPoint> > InkAnnotation::transformedInkPaths() const
01942 {
01943     Q_D( const InkAnnotation );
01944     return d->m_transformedInkPaths;
01945 }
01946 
01947 Annotation::SubType InkAnnotation::subType() const
01948 {
01949     return AInk;
01950 }
01951 
01952 void InkAnnotation::store( QDomNode & node, QDomDocument & document ) const
01953 {
01954     Q_D( const InkAnnotation );
01955     // recurse to parent objects storing properties
01956     Annotation::store( node, document );
01957 
01958     // create [ink] element
01959     QDomElement inkElement = document.createElement( "ink" );
01960     node.appendChild( inkElement );
01961 
01962     // append the optional attributes
01963     if ( d->m_inkPaths.count() < 1 )
01964         return;
01965 
01966     QList< QLinkedList<NormalizedPoint> >::const_iterator pIt = d->m_inkPaths.begin(), pEnd = d->m_inkPaths.end();
01967     for ( ; pIt != pEnd; ++pIt )
01968     {
01969         QDomElement pathElement = document.createElement( "path" );
01970         inkElement.appendChild( pathElement );
01971         const QLinkedList<NormalizedPoint> & path = *pIt;
01972         QLinkedList<NormalizedPoint>::const_iterator iIt = path.begin(), iEnd = path.end();
01973         for ( ; iIt != iEnd; ++iIt )
01974         {
01975             const NormalizedPoint & point = *iIt;
01976             QDomElement pointElement = document.createElement( "point" );
01977             pathElement.appendChild( pointElement );
01978             pointElement.setAttribute( "x", point.x );
01979             pointElement.setAttribute( "y", point.y );
01980         }
01981     }
01982 }
01983 
01984 void InkAnnotationPrivate::transform( const QMatrix &matrix )
01985 {
01986     AnnotationPrivate::transform( matrix );
01987 
01988     for ( int i = 0; i < m_transformedInkPaths.count(); ++i )
01989     {
01990         QMutableLinkedListIterator<NormalizedPoint> it( m_transformedInkPaths[ i ] );
01991         while ( it.hasNext() )
01992             it.next().transform( matrix );
01993     }
01994 }
01995 
01996 void InkAnnotationPrivate::baseTransform( const QMatrix &matrix )
01997 {
01998     AnnotationPrivate::baseTransform( matrix );
01999 
02000     for ( int i = 0; i < m_inkPaths.count(); ++i )
02001     {
02002         QMutableLinkedListIterator<NormalizedPoint> it( m_inkPaths[ i ] );
02003         while ( it.hasNext() )
02004             it.next().transform( matrix );
02005     }
02006 }
02007 
02008 void InkAnnotationPrivate::resetTransformation()
02009 {
02010     AnnotationPrivate::resetTransformation();
02011 
02012     m_transformedInkPaths = m_inkPaths;
02013 }
02014 
02015 void InkAnnotationPrivate::translate( const NormalizedPoint &coord )
02016 {
02017     AnnotationPrivate::translate( coord );
02018 
02019     for ( int i = 0; i < m_inkPaths.count(); ++i )
02020     {
02021         QMutableLinkedListIterator<NormalizedPoint> it( m_inkPaths[ i ] );
02022         while ( it.hasNext() )
02023         {
02024             NormalizedPoint& p = it.next();
02025             p.x = p.x + coord.x;
02026             p.y = p.y + coord.y;
02027         }
02028     }
02029 }

okular

Skip menu "okular"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdegraphics

Skip menu "kdegraphics"
  • okular
Generated for kdegraphics by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal