| /* poppler-annotation.cc: qt interface to poppler |
| * Copyright (C) 2006, Albert Astals Cid <aacid@kde.org> |
| * Copyright (C) 2006, 2008 Pino Toscano <pino@kde.org> |
| * Adapting code from |
| * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2, or (at your option) |
| * any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. |
| */ |
| |
| // qt/kde includes |
| #include <QtXml/QDomElement> |
| #include <QtGui/QColor> |
| |
| // local includes |
| #include "poppler-annotation.h" |
| #include "poppler-link.h" |
| #include "poppler-qt4.h" |
| #include "poppler-annotation-private.h" |
| |
| // poppler includes |
| #include <Page.h> |
| #include <Annot.h> |
| |
| namespace Poppler { |
| |
| //BEGIN AnnotationUtils implementation |
| Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement ) |
| { |
| // safety check on annotation element |
| if ( !annElement.hasAttribute( "type" ) ) |
| return 0; |
| |
| // build annotation of given type |
| Annotation * annotation = 0; |
| int typeNumber = annElement.attribute( "type" ).toInt(); |
| switch ( typeNumber ) |
| { |
| case Annotation::AText: |
| annotation = new TextAnnotation( annElement ); |
| break; |
| case Annotation::ALine: |
| annotation = new LineAnnotation( annElement ); |
| break; |
| case Annotation::AGeom: |
| annotation = new GeomAnnotation( annElement ); |
| break; |
| case Annotation::AHighlight: |
| annotation = new HighlightAnnotation( annElement ); |
| break; |
| case Annotation::AStamp: |
| annotation = new StampAnnotation( annElement ); |
| break; |
| case Annotation::AInk: |
| annotation = new InkAnnotation( annElement ); |
| break; |
| case Annotation::ACaret: |
| annotation = new CaretAnnotation( annElement ); |
| break; |
| } |
| |
| // return created annotation |
| return annotation; |
| } |
| |
| void AnnotationUtils::storeAnnotation( const Annotation * ann, QDomElement & annElement, |
| QDomDocument & document ) |
| { |
| // save annotation's type as element's attribute |
| annElement.setAttribute( "type", (uint)ann->subType() ); |
| |
| // append all annotation data as children of this node |
| ann->store( annElement, document ); |
| } |
| |
| QDomElement AnnotationUtils::findChildElement( const QDomNode & parentNode, |
| const QString & name ) |
| { |
| // loop through the whole children and return a 'name' named element |
| QDomNode subNode = parentNode.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement element = subNode.toElement(); |
| if ( element.tagName() == name ) |
| return element; |
| subNode = subNode.nextSibling(); |
| } |
| // if the name can't be found, return a dummy null element |
| return QDomElement(); |
| } |
| //END AnnotationUtils implementation |
| |
| |
| //BEGIN Annotation implementation |
| AnnotationPrivate::AnnotationPrivate() |
| : flags( 0 ) |
| { |
| } |
| |
| AnnotationPrivate::~AnnotationPrivate() |
| { |
| } |
| |
| |
| Annotation::Style::Style() |
| : opacity( 1.0 ), width( 1.0 ), style( Solid ), xCorners( 0.0 ), |
| yCorners( 0.0 ), marks( 3 ), spaces( 0 ), effect( NoEffect ), |
| effectIntensity( 1.0 ) {} |
| |
| Annotation::Window::Window() |
| : flags( -1 ), width( 0 ), height( 0 ) {} |
| |
| Annotation::Revision::Revision() |
| : annotation( 0 ), scope( Reply ), type( None ) {} |
| |
| Annotation::Annotation( AnnotationPrivate &dd ) |
| : d_ptr( &dd ) |
| { |
| } |
| |
| Annotation::~Annotation() |
| { |
| Q_D( Annotation ); |
| // delete all children revisions |
| QLinkedList< Annotation::Revision >::iterator it = d->revisions.begin(), end = d->revisions.end(); |
| for ( ; it != end; ++it ) |
| delete (*it).annotation; |
| |
| delete d_ptr; |
| } |
| |
| Annotation::Annotation( AnnotationPrivate &dd, const QDomNode &annNode ) |
| : d_ptr( &dd ) |
| { |
| Q_D( Annotation ); |
| // get the [base] element of the annotation node |
| QDomElement e = AnnotationUtils::findChildElement( annNode, "base" ); |
| if ( e.isNull() ) |
| return; |
| |
| // parse -contents- attributes |
| if ( e.hasAttribute( "author" ) ) |
| d->author = e.attribute( "author" ); |
| if ( e.hasAttribute( "contents" ) ) |
| d->contents = e.attribute( "contents" ); |
| if ( e.hasAttribute( "uniqueName" ) ) |
| d->uniqueName = e.attribute( "uniqueName" ); |
| if ( e.hasAttribute( "modifyDate" ) ) |
| d->modDate = QDateTime::fromString( e.attribute( "modifyDate" ) ); |
| if ( e.hasAttribute( "creationDate" ) ) |
| d->creationDate = QDateTime::fromString( e.attribute( "creationDate" ) ); |
| |
| // parse -other- attributes |
| if ( e.hasAttribute( "flags" ) ) |
| d->flags = e.attribute( "flags" ).toInt(); |
| if ( e.hasAttribute( "color" ) ) |
| style.color = QColor( e.attribute( "color" ) ); |
| if ( e.hasAttribute( "opacity" ) ) |
| style.opacity = e.attribute( "opacity" ).toDouble(); |
| |
| // parse -the-subnodes- (describing Style, Window, Revision(s) structures) |
| // Note: all subnodes if present must be 'attributes complete' |
| QDomNode eSubNode = e.firstChild(); |
| while ( eSubNode.isElement() ) |
| { |
| QDomElement ee = eSubNode.toElement(); |
| eSubNode = eSubNode.nextSibling(); |
| |
| // parse boundary |
| if ( ee.tagName() == "boundary" ) |
| { |
| d->boundary.setLeft(ee.attribute( "l" ).toDouble()); |
| d->boundary.setTop(ee.attribute( "t" ).toDouble()); |
| d->boundary.setRight(ee.attribute( "r" ).toDouble()); |
| d->boundary.setBottom(ee.attribute( "b" ).toDouble()); |
| } |
| // parse penStyle if not default |
| else if ( ee.tagName() == "penStyle" ) |
| { |
| style.width = ee.attribute( "width" ).toDouble(); |
| style.style = (LineStyle)ee.attribute( "style" ).toInt(); |
| style.xCorners = ee.attribute( "xcr" ).toDouble(); |
| style.yCorners = ee.attribute( "ycr" ).toDouble(); |
| style.marks = ee.attribute( "marks" ).toInt(); |
| style.spaces = ee.attribute( "spaces" ).toInt(); |
| } |
| // parse effectStyle if not default |
| else if ( ee.tagName() == "penEffect" ) |
| { |
| style.effect = (LineEffect)ee.attribute( "effect" ).toInt(); |
| style.effectIntensity = ee.attribute( "intensity" ).toDouble(); |
| } |
| // parse window if present |
| else if ( ee.tagName() == "window" ) |
| { |
| window.flags = ee.attribute( "flags" ).toInt(); |
| window.topLeft.setX(ee.attribute( "top" ).toDouble()); |
| window.topLeft.setY(ee.attribute( "left" ).toDouble()); |
| window.width = ee.attribute( "width" ).toInt(); |
| window.height = ee.attribute( "height" ).toInt(); |
| window.title = ee.attribute( "title" ); |
| window.summary = ee.attribute( "summary" ); |
| // parse window subnodes |
| QDomNode winNode = ee.firstChild(); |
| for ( ; winNode.isElement(); winNode = winNode.nextSibling() ) |
| { |
| QDomElement winElement = winNode.toElement(); |
| if ( winElement.tagName() == "text" ) |
| window.text = winElement.firstChild().toCDATASection().data(); |
| } |
| } |
| } |
| |
| // get the [revisions] element of the annotation node |
| QDomNode revNode = annNode.firstChild(); |
| for ( ; revNode.isElement(); revNode = revNode.nextSibling() ) |
| { |
| QDomElement revElement = revNode.toElement(); |
| if ( revElement.tagName() != "revision" ) |
| continue; |
| |
| // compile the Revision structure crating annotation |
| Revision rev; |
| rev.scope = (RevScope)revElement.attribute( "revScope" ).toInt(); |
| rev.type = (RevType)revElement.attribute( "revType" ).toInt(); |
| rev.annotation = AnnotationUtils::createAnnotation( revElement ); |
| |
| // if annotation is valid, add revision to internal list |
| if ( rev.annotation ); |
| d->revisions.append( rev ); |
| } |
| } |
| |
| void Annotation::store( QDomNode & annNode, QDomDocument & document ) const |
| { |
| Q_D( const Annotation ); |
| // create [base] element of the annotation node |
| QDomElement e = document.createElement( "base" ); |
| annNode.appendChild( e ); |
| |
| // store -contents- attributes |
| if ( !d->author.isEmpty() ) |
| e.setAttribute( "author", d->author ); |
| if ( !d->contents.isEmpty() ) |
| e.setAttribute( "contents", d->contents ); |
| if ( !d->uniqueName.isEmpty() ) |
| e.setAttribute( "uniqueName", d->uniqueName ); |
| if ( d->modDate.isValid() ) |
| e.setAttribute( "modifyDate", d->modDate.toString() ); |
| if ( d->creationDate.isValid() ) |
| e.setAttribute( "creationDate", d->creationDate.toString() ); |
| |
| // store -other- attributes |
| if ( d->flags ) |
| e.setAttribute( "flags", d->flags ); |
| if ( style.color.isValid() && style.color != Qt::black ) |
| e.setAttribute( "color", style.color.name() ); |
| if ( style.opacity != 1.0 ) |
| e.setAttribute( "opacity", style.opacity ); |
| |
| // Sub-Node-1 - boundary |
| QDomElement bE = document.createElement( "boundary" ); |
| e.appendChild( bE ); |
| bE.setAttribute( "l", (double)d->boundary.left() ); |
| bE.setAttribute( "t", (double)d->boundary.top() ); |
| bE.setAttribute( "r", (double)d->boundary.right() ); |
| bE.setAttribute( "b", (double)d->boundary.bottom() ); |
| |
| // Sub-Node-2 - penStyle |
| if ( style.width != 1 || style.style != Solid || style.xCorners != 0 || |
| style.yCorners != 0.0 || style.marks != 3 || style.spaces != 0 ) |
| { |
| QDomElement psE = document.createElement( "penStyle" ); |
| e.appendChild( psE ); |
| psE.setAttribute( "width", style.width ); |
| psE.setAttribute( "style", (int)style.style ); |
| psE.setAttribute( "xcr", style.xCorners ); |
| psE.setAttribute( "ycr", style.yCorners ); |
| psE.setAttribute( "marks", style.marks ); |
| psE.setAttribute( "spaces", style.spaces ); |
| } |
| |
| // Sub-Node-3 - penEffect |
| if ( style.effect != NoEffect || style.effectIntensity != 1.0 ) |
| { |
| QDomElement peE = document.createElement( "penEffect" ); |
| e.appendChild( peE ); |
| peE.setAttribute( "effect", (int)style.effect ); |
| peE.setAttribute( "intensity", style.effectIntensity ); |
| } |
| |
| // Sub-Node-4 - window |
| if ( window.flags != -1 || !window.title.isEmpty() || |
| !window.summary.isEmpty() || !window.text.isEmpty() ) |
| { |
| QDomElement wE = document.createElement( "window" ); |
| e.appendChild( wE ); |
| wE.setAttribute( "flags", window.flags ); |
| wE.setAttribute( "top", window.topLeft.x() ); |
| wE.setAttribute( "left", window.topLeft.y() ); |
| wE.setAttribute( "width", window.width ); |
| wE.setAttribute( "height", window.height ); |
| wE.setAttribute( "title", window.title ); |
| wE.setAttribute( "summary", window.summary ); |
| // store window.text as a subnode, because we need escaped data |
| if ( !window.text.isEmpty() ) |
| { |
| QDomElement escapedText = document.createElement( "text" ); |
| wE.appendChild( escapedText ); |
| QDomCDATASection textCData = document.createCDATASection( window.text ); |
| escapedText.appendChild( textCData ); |
| } |
| } |
| |
| // create [revision] element of the annotation node (if any) |
| if ( d->revisions.isEmpty() ) |
| return; |
| |
| // add all revisions as children of revisions element |
| QLinkedList< Revision >::const_iterator it = d->revisions.begin(), end = d->revisions.end(); |
| for ( ; it != end; ++it ) |
| { |
| // create revision element |
| const Revision & revision = *it; |
| QDomElement r = document.createElement( "revision" ); |
| annNode.appendChild( r ); |
| // set element attributes |
| r.setAttribute( "revScope", (int)revision.scope ); |
| r.setAttribute( "revType", (int)revision.type ); |
| // use revision as the annotation element, so fill it up |
| AnnotationUtils::storeAnnotation( revision.annotation, r, document ); |
| } |
| } |
| |
| QString Annotation::author() const |
| { |
| Q_D( const Annotation ); |
| return d->author; |
| } |
| |
| void Annotation::setAuthor( const QString &author ) |
| { |
| Q_D( Annotation ); |
| d->author = author; |
| } |
| |
| QString Annotation::contents() const |
| { |
| Q_D( const Annotation ); |
| return d->contents; |
| } |
| |
| void Annotation::setContents( const QString &contents ) |
| { |
| Q_D( Annotation ); |
| d->contents = contents; |
| } |
| |
| QString Annotation::uniqueName() const |
| { |
| Q_D( const Annotation ); |
| return d->uniqueName; |
| } |
| |
| void Annotation::setUniqueName( const QString &uniqueName ) |
| { |
| Q_D( Annotation ); |
| d->uniqueName = uniqueName; |
| } |
| |
| QDateTime Annotation::modificationDate() const |
| { |
| Q_D( const Annotation ); |
| return d->modDate; |
| } |
| |
| void Annotation::setModificationDate( const QDateTime &date ) |
| { |
| Q_D( Annotation ); |
| d->modDate = date; |
| } |
| |
| QDateTime Annotation::creationDate() const |
| { |
| Q_D( const Annotation ); |
| return d->creationDate; |
| } |
| |
| void Annotation::setCreationDate( const QDateTime &date ) |
| { |
| Q_D( Annotation ); |
| d->creationDate = date; |
| } |
| |
| int Annotation::flags() const |
| { |
| Q_D( const Annotation ); |
| return d->flags; |
| } |
| |
| void Annotation::setFlags( int flags ) |
| { |
| Q_D( Annotation ); |
| d->flags = flags; |
| } |
| |
| QRectF Annotation::boundary() const |
| { |
| Q_D( const Annotation ); |
| return d->boundary; |
| } |
| |
| void Annotation::setBoundary( const QRectF &boundary ) |
| { |
| Q_D( Annotation ); |
| d->boundary = boundary; |
| } |
| |
| QLinkedList< Annotation::Revision >& Annotation::revisions() |
| { |
| Q_D( Annotation ); |
| return d->revisions; |
| } |
| |
| const QLinkedList< Annotation::Revision >& Annotation::revisions() const |
| { |
| Q_D( const Annotation ); |
| return d->revisions; |
| } |
| |
| //END AnnotationUtils implementation |
| |
| |
| /** TextAnnotation [Annotation] */ |
| class TextAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| TextAnnotationPrivate(); |
| |
| // data fields |
| TextAnnotation::TextType textType; |
| QString textIcon; |
| QFont textFont; |
| int inplaceAlign; // 0:left, 1:center, 2:right |
| QString inplaceText; // overrides contents |
| QPointF inplaceCallout[3]; |
| TextAnnotation::InplaceIntent inplaceIntent; |
| }; |
| |
| TextAnnotationPrivate::TextAnnotationPrivate() |
| : AnnotationPrivate(), textType( TextAnnotation::Linked ), |
| textIcon( "Note" ), inplaceAlign( 0 ), |
| inplaceIntent( TextAnnotation::Unknown ) |
| { |
| } |
| |
| TextAnnotation::TextAnnotation() |
| : Annotation( *new TextAnnotationPrivate() ) |
| {} |
| |
| TextAnnotation::TextAnnotation( const QDomNode & node ) |
| : Annotation( *new TextAnnotationPrivate, node ) |
| { |
| Q_D( TextAnnotation ); |
| |
| // loop through the whole children looking for a 'text' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "text" ) |
| continue; |
| |
| // parse the attributes |
| if ( e.hasAttribute( "type" ) ) |
| d->textType = (TextAnnotation::TextType)e.attribute( "type" ).toInt(); |
| if ( e.hasAttribute( "icon" ) ) |
| d->textIcon = e.attribute( "icon" ); |
| if ( e.hasAttribute( "font" ) ) |
| d->textFont.fromString( e.attribute( "font" ) ); |
| if ( e.hasAttribute( "align" ) ) |
| d->inplaceAlign = e.attribute( "align" ).toInt(); |
| if ( e.hasAttribute( "intent" ) ) |
| d->inplaceIntent = (TextAnnotation::InplaceIntent)e.attribute( "intent" ).toInt(); |
| |
| // parse the subnodes |
| QDomNode eSubNode = e.firstChild(); |
| while ( eSubNode.isElement() ) |
| { |
| QDomElement ee = eSubNode.toElement(); |
| eSubNode = eSubNode.nextSibling(); |
| |
| if ( ee.tagName() == "escapedText" ) |
| { |
| d->inplaceText = ee.firstChild().toCDATASection().data(); |
| } |
| else if ( ee.tagName() == "callout" ) |
| { |
| d->inplaceCallout[0].setX(ee.attribute( "ax" ).toDouble()); |
| d->inplaceCallout[0].setY(ee.attribute( "ay" ).toDouble()); |
| d->inplaceCallout[1].setX(ee.attribute( "bx" ).toDouble()); |
| d->inplaceCallout[1].setY(ee.attribute( "by" ).toDouble()); |
| d->inplaceCallout[2].setX(ee.attribute( "cx" ).toDouble()); |
| d->inplaceCallout[2].setY(ee.attribute( "cy" ).toDouble()); |
| } |
| } |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| TextAnnotation::~TextAnnotation() |
| { |
| } |
| |
| void TextAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| Q_D( const TextAnnotation ); |
| |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [text] element |
| QDomElement textElement = document.createElement( "text" ); |
| node.appendChild( textElement ); |
| |
| // store the optional attributes |
| if ( d->textType != Linked ) |
| textElement.setAttribute( "type", (int)d->textType ); |
| if ( d->textIcon != "Comment" ) |
| textElement.setAttribute( "icon", d->textIcon ); |
| if ( d->inplaceAlign ) |
| textElement.setAttribute( "align", d->inplaceAlign ); |
| if ( d->inplaceIntent != Unknown ) |
| textElement.setAttribute( "intent", (int)d->inplaceIntent ); |
| |
| textElement.setAttribute( "font", d->textFont.toString() ); |
| |
| // Sub-Node-1 - escapedText |
| if ( !d->inplaceText.isEmpty() ) |
| { |
| QDomElement escapedText = document.createElement( "escapedText" ); |
| textElement.appendChild( escapedText ); |
| QDomCDATASection textCData = document.createCDATASection( d->inplaceText ); |
| escapedText.appendChild( textCData ); |
| } |
| |
| // Sub-Node-2 - callout |
| if ( d->inplaceCallout[0].x() != 0.0 ) |
| { |
| QDomElement calloutElement = document.createElement( "callout" ); |
| textElement.appendChild( calloutElement ); |
| calloutElement.setAttribute( "ax", d->inplaceCallout[0].x() ); |
| calloutElement.setAttribute( "ay", d->inplaceCallout[0].y() ); |
| calloutElement.setAttribute( "bx", d->inplaceCallout[1].x() ); |
| calloutElement.setAttribute( "by", d->inplaceCallout[1].y() ); |
| calloutElement.setAttribute( "cx", d->inplaceCallout[2].x() ); |
| calloutElement.setAttribute( "cy", d->inplaceCallout[2].y() ); |
| } |
| } |
| |
| Annotation::SubType TextAnnotation::subType() const |
| { |
| return AText; |
| } |
| |
| TextAnnotation::TextType TextAnnotation::textType() const |
| { |
| Q_D( const TextAnnotation ); |
| return d->textType; |
| } |
| |
| void TextAnnotation::setTextType( TextAnnotation::TextType type ) |
| { |
| Q_D( TextAnnotation ); |
| d->textType = type; |
| } |
| |
| QString TextAnnotation::textIcon() const |
| { |
| Q_D( const TextAnnotation ); |
| return d->textIcon; |
| } |
| |
| void TextAnnotation::setTextIcon( const QString &icon ) |
| { |
| Q_D( TextAnnotation ); |
| d->textIcon = icon; |
| } |
| |
| QFont TextAnnotation::textFont() const |
| { |
| Q_D( const TextAnnotation ); |
| return d->textFont; |
| } |
| |
| void TextAnnotation::setTextFont( const QFont &font ) |
| { |
| Q_D( TextAnnotation ); |
| d->textFont = font; |
| } |
| |
| int TextAnnotation::inplaceAlign() const |
| { |
| Q_D( const TextAnnotation ); |
| return d->inplaceAlign; |
| } |
| |
| void TextAnnotation::setInplaceAlign( int align ) |
| { |
| Q_D( TextAnnotation ); |
| d->inplaceAlign = align; |
| } |
| |
| QString TextAnnotation::inplaceText() const |
| { |
| Q_D( const TextAnnotation ); |
| return d->inplaceText; |
| } |
| |
| void TextAnnotation::setInplaceText( const QString &text ) |
| { |
| Q_D( TextAnnotation ); |
| d->inplaceText = text; |
| } |
| |
| QPointF TextAnnotation::calloutPoint( int id ) const |
| { |
| if ( id < 0 || id >= 3 ) |
| return QPointF(); |
| |
| Q_D( const TextAnnotation ); |
| return d->inplaceCallout[id]; |
| } |
| |
| void TextAnnotation::setCalloutPoint( int id, const QPointF &point ) |
| { |
| if ( id < 0 || id >= 3 ) |
| return; |
| |
| Q_D( TextAnnotation ); |
| d->inplaceCallout[id] = point; |
| } |
| |
| TextAnnotation::InplaceIntent TextAnnotation::inplaceIntent() const |
| { |
| Q_D( const TextAnnotation ); |
| return d->inplaceIntent; |
| } |
| |
| void TextAnnotation::setInplaceIntent( TextAnnotation::InplaceIntent intent ) |
| { |
| Q_D( TextAnnotation ); |
| d->inplaceIntent = intent; |
| } |
| |
| |
| /** LineAnnotation [Annotation] */ |
| class LineAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| LineAnnotationPrivate(); |
| |
| // data fields (note uses border for rendering style) |
| QLinkedList<QPointF> linePoints; |
| LineAnnotation::TermStyle lineStartStyle; |
| LineAnnotation::TermStyle lineEndStyle; |
| bool lineClosed : 1; // (if true draw close shape) |
| bool lineShowCaption : 1; |
| QColor lineInnerColor; |
| double lineLeadingFwdPt; |
| double lineLeadingBackPt; |
| LineAnnotation::LineIntent lineIntent; |
| }; |
| |
| LineAnnotationPrivate::LineAnnotationPrivate() |
| : AnnotationPrivate(), lineStartStyle( LineAnnotation::None ), |
| lineEndStyle( LineAnnotation::None ), lineClosed( false ), |
| lineShowCaption( false ), lineLeadingFwdPt( 0 ), lineLeadingBackPt( 0 ), |
| lineIntent( LineAnnotation::Unknown ) |
| { |
| } |
| |
| LineAnnotation::LineAnnotation() |
| : Annotation( *new LineAnnotationPrivate() ) |
| {} |
| |
| LineAnnotation::LineAnnotation( const QDomNode & node ) |
| : Annotation( *new LineAnnotationPrivate(), node ) |
| { |
| Q_D( LineAnnotation ); |
| |
| // loop through the whole children looking for a 'line' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "line" ) |
| continue; |
| |
| // parse the attributes |
| if ( e.hasAttribute( "startStyle" ) ) |
| d->lineStartStyle = (LineAnnotation::TermStyle)e.attribute( "startStyle" ).toInt(); |
| if ( e.hasAttribute( "endStyle" ) ) |
| d->lineEndStyle = (LineAnnotation::TermStyle)e.attribute( "endStyle" ).toInt(); |
| if ( e.hasAttribute( "closed" ) ) |
| d->lineClosed = e.attribute( "closed" ).toInt(); |
| if ( e.hasAttribute( "innerColor" ) ) |
| d->lineInnerColor = QColor( e.attribute( "innerColor" ) ); |
| if ( e.hasAttribute( "leadFwd" ) ) |
| d->lineLeadingFwdPt = e.attribute( "leadFwd" ).toDouble(); |
| if ( e.hasAttribute( "leadBack" ) ) |
| d->lineLeadingBackPt = e.attribute( "leadBack" ).toDouble(); |
| if ( e.hasAttribute( "showCaption" ) ) |
| d->lineShowCaption = e.attribute( "showCaption" ).toInt(); |
| if ( e.hasAttribute( "intent" ) ) |
| d->lineIntent = (LineAnnotation::LineIntent)e.attribute( "intent" ).toInt(); |
| |
| // parse all 'point' subnodes |
| QDomNode pointNode = e.firstChild(); |
| while ( pointNode.isElement() ) |
| { |
| QDomElement pe = pointNode.toElement(); |
| pointNode = pointNode.nextSibling(); |
| |
| if ( pe.tagName() != "point" ) |
| continue; |
| |
| QPointF p(pe.attribute( "x", "0.0" ).toDouble(), pe.attribute( "y", "0.0" ).toDouble()); |
| d->linePoints.append( p ); |
| } |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| LineAnnotation::~LineAnnotation() |
| { |
| } |
| |
| void LineAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| Q_D( const LineAnnotation ); |
| |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [line] element |
| QDomElement lineElement = document.createElement( "line" ); |
| node.appendChild( lineElement ); |
| |
| // store the attributes |
| if ( d->lineStartStyle != None ) |
| lineElement.setAttribute( "startStyle", (int)d->lineStartStyle ); |
| if ( d->lineEndStyle != None ) |
| lineElement.setAttribute( "endStyle", (int)d->lineEndStyle ); |
| if ( d->lineClosed ) |
| lineElement.setAttribute( "closed", d->lineClosed ); |
| if ( d->lineInnerColor.isValid() ) |
| lineElement.setAttribute( "innerColor", d->lineInnerColor.name() ); |
| if ( d->lineLeadingFwdPt != 0.0 ) |
| lineElement.setAttribute( "leadFwd", d->lineLeadingFwdPt ); |
| if ( d->lineLeadingBackPt != 0.0 ) |
| lineElement.setAttribute( "leadBack", d->lineLeadingBackPt ); |
| if ( d->lineShowCaption ) |
| lineElement.setAttribute( "showCaption", d->lineShowCaption ); |
| if ( d->lineIntent != Unknown ) |
| lineElement.setAttribute( "intent", d->lineIntent ); |
| |
| // append the list of points |
| int points = d->linePoints.count(); |
| if ( points > 1 ) |
| { |
| QLinkedList<QPointF>::const_iterator it = d->linePoints.begin(), end = d->linePoints.end(); |
| while ( it != end ) |
| { |
| const QPointF & p = *it; |
| QDomElement pElement = document.createElement( "point" ); |
| lineElement.appendChild( pElement ); |
| pElement.setAttribute( "x", p.x() ); |
| pElement.setAttribute( "y", p.y() ); |
| ++it; |
| } |
| } |
| } |
| |
| Annotation::SubType LineAnnotation::subType() const |
| { |
| return ALine; |
| } |
| |
| QLinkedList<QPointF> LineAnnotation::linePoints() const |
| { |
| Q_D( const LineAnnotation ); |
| return d->linePoints; |
| } |
| |
| void LineAnnotation::setLinePoints( const QLinkedList<QPointF> &points ) |
| { |
| Q_D( LineAnnotation ); |
| d->linePoints = points; |
| } |
| |
| LineAnnotation::TermStyle LineAnnotation::lineStartStyle() const |
| { |
| Q_D( const LineAnnotation ); |
| return d->lineStartStyle; |
| } |
| |
| void LineAnnotation::setLineStartStyle( LineAnnotation::TermStyle style ) |
| { |
| Q_D( LineAnnotation ); |
| d->lineStartStyle = style; |
| } |
| |
| LineAnnotation::TermStyle LineAnnotation::lineEndStyle() const |
| { |
| Q_D( const LineAnnotation ); |
| return d->lineEndStyle; |
| } |
| |
| void LineAnnotation::setLineEndStyle( LineAnnotation::TermStyle style ) |
| { |
| Q_D( LineAnnotation ); |
| d->lineEndStyle = style; |
| } |
| |
| bool LineAnnotation::isLineClosed() const |
| { |
| Q_D( const LineAnnotation ); |
| return d->lineClosed; |
| } |
| |
| void LineAnnotation::setLineClosed( bool closed ) |
| { |
| Q_D( LineAnnotation ); |
| d->lineClosed = closed; |
| } |
| |
| QColor LineAnnotation::lineInnerColor() const |
| { |
| Q_D( const LineAnnotation ); |
| return d->lineInnerColor; |
| } |
| |
| void LineAnnotation::setLineInnerColor( const QColor &color ) |
| { |
| Q_D( LineAnnotation ); |
| d->lineInnerColor = color; |
| } |
| |
| double LineAnnotation::lineLeadingForwardPoint() const |
| { |
| Q_D( const LineAnnotation ); |
| return d->lineLeadingFwdPt; |
| } |
| |
| void LineAnnotation::setLineLeadingForwardPoint( double point ) |
| { |
| Q_D( LineAnnotation ); |
| d->lineLeadingFwdPt = point; |
| } |
| |
| double LineAnnotation::lineLeadingBackPoint() const |
| { |
| Q_D( const LineAnnotation ); |
| return d->lineLeadingBackPt; |
| } |
| |
| void LineAnnotation::setLineLeadingBackPoint( double point ) |
| { |
| Q_D( LineAnnotation ); |
| d->lineLeadingBackPt = point; |
| } |
| |
| bool LineAnnotation::lineShowCaption() const |
| { |
| Q_D( const LineAnnotation ); |
| return d->lineShowCaption; |
| } |
| |
| void LineAnnotation::setLineShowCaption( bool show ) |
| { |
| Q_D( LineAnnotation ); |
| d->lineShowCaption = show; |
| } |
| |
| LineAnnotation::LineIntent LineAnnotation::lineIntent() const |
| { |
| Q_D( const LineAnnotation ); |
| return d->lineIntent; |
| } |
| |
| void LineAnnotation::setLineIntent( LineAnnotation::LineIntent intent ) |
| { |
| Q_D( LineAnnotation ); |
| d->lineIntent = intent; |
| } |
| |
| |
| /** GeomAnnotation [Annotation] */ |
| class GeomAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| GeomAnnotationPrivate(); |
| |
| // data fields (note uses border for rendering style) |
| GeomAnnotation::GeomType geomType; |
| QColor geomInnerColor; |
| int geomWidthPt; |
| }; |
| |
| GeomAnnotationPrivate::GeomAnnotationPrivate() |
| : AnnotationPrivate(), geomType( GeomAnnotation::InscribedSquare ), |
| geomWidthPt( 18 ) |
| { |
| } |
| |
| GeomAnnotation::GeomAnnotation() |
| : Annotation( *new GeomAnnotationPrivate() ) |
| {} |
| |
| GeomAnnotation::GeomAnnotation( const QDomNode & node ) |
| : Annotation( *new GeomAnnotationPrivate(), node ) |
| { |
| Q_D( GeomAnnotation ); |
| |
| // loop through the whole children looking for a 'geom' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "geom" ) |
| continue; |
| |
| // parse the attributes |
| if ( e.hasAttribute( "type" ) ) |
| d->geomType = (GeomAnnotation::GeomType)e.attribute( "type" ).toInt(); |
| if ( e.hasAttribute( "color" ) ) |
| d->geomInnerColor = QColor( e.attribute( "color" ) ); |
| if ( e.hasAttribute( "width" ) ) |
| d->geomWidthPt = e.attribute( "width" ).toInt(); |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| GeomAnnotation::~GeomAnnotation() |
| { |
| } |
| |
| void GeomAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| Q_D( const GeomAnnotation ); |
| |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [geom] element |
| QDomElement geomElement = document.createElement( "geom" ); |
| node.appendChild( geomElement ); |
| |
| // append the optional attributes |
| if ( d->geomType != InscribedSquare ) |
| geomElement.setAttribute( "type", (int)d->geomType ); |
| if ( d->geomInnerColor.isValid() ) |
| geomElement.setAttribute( "color", d->geomInnerColor.name() ); |
| if ( d->geomWidthPt != 18 ) |
| geomElement.setAttribute( "width", d->geomWidthPt ); |
| } |
| |
| Annotation::SubType GeomAnnotation::subType() const |
| { |
| return AGeom; |
| } |
| |
| GeomAnnotation::GeomType GeomAnnotation::geomType() const |
| { |
| Q_D( const GeomAnnotation ); |
| return d->geomType; |
| } |
| |
| void GeomAnnotation::setGeomType( GeomAnnotation::GeomType type ) |
| { |
| Q_D( GeomAnnotation ); |
| d->geomType = type; |
| } |
| |
| QColor GeomAnnotation::geomInnerColor() const |
| { |
| Q_D( const GeomAnnotation ); |
| return d->geomInnerColor; |
| } |
| |
| void GeomAnnotation::setGeomInnerColor( const QColor &color ) |
| { |
| Q_D( GeomAnnotation ); |
| d->geomInnerColor = color; |
| } |
| |
| int GeomAnnotation::geomPointWidth() const |
| { |
| Q_D( const GeomAnnotation ); |
| return d->geomWidthPt; |
| } |
| |
| void GeomAnnotation::setGeomPointWidth( int width ) |
| { |
| Q_D( GeomAnnotation ); |
| d->geomWidthPt = width; |
| } |
| |
| |
| |
| /** HighlightAnnotation [Annotation] */ |
| class HighlightAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| HighlightAnnotationPrivate(); |
| |
| // data fields |
| HighlightAnnotation::HighlightType highlightType; |
| QList< HighlightAnnotation::Quad > highlightQuads; // not empty |
| }; |
| |
| HighlightAnnotationPrivate::HighlightAnnotationPrivate() |
| : AnnotationPrivate(), highlightType( HighlightAnnotation::Highlight ) |
| { |
| } |
| |
| HighlightAnnotation::HighlightAnnotation() |
| : Annotation( *new HighlightAnnotationPrivate() ) |
| {} |
| |
| HighlightAnnotation::HighlightAnnotation( const QDomNode & node ) |
| : Annotation( *new HighlightAnnotationPrivate(), node ) |
| { |
| Q_D( HighlightAnnotation ); |
| |
| // loop through the whole children looking for a 'hl' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "hl" ) |
| continue; |
| |
| // parse the attributes |
| if ( e.hasAttribute( "type" ) ) |
| d->highlightType = (HighlightAnnotation::HighlightType)e.attribute( "type" ).toInt(); |
| |
| // parse all 'quad' subnodes |
| QDomNode quadNode = e.firstChild(); |
| for ( ; quadNode.isElement(); quadNode = quadNode.nextSibling() ) |
| { |
| QDomElement qe = quadNode.toElement(); |
| if ( qe.tagName() != "quad" ) |
| continue; |
| |
| Quad q; |
| q.points[0].setX(qe.attribute( "ax", "0.0" ).toDouble()); |
| q.points[0].setY(qe.attribute( "ay", "0.0" ).toDouble()); |
| q.points[1].setX(qe.attribute( "bx", "0.0" ).toDouble()); |
| q.points[1].setY(qe.attribute( "by", "0.0" ).toDouble()); |
| q.points[2].setX(qe.attribute( "cx", "0.0" ).toDouble()); |
| q.points[2].setY(qe.attribute( "cy", "0.0" ).toDouble()); |
| q.points[3].setX(qe.attribute( "dx", "0.0" ).toDouble()); |
| q.points[3].setY(qe.attribute( "dy", "0.0" ).toDouble()); |
| q.capStart = qe.hasAttribute( "start" ); |
| q.capEnd = qe.hasAttribute( "end" ); |
| q.feather = qe.attribute( "feather", "0.1" ).toDouble(); |
| d->highlightQuads.append( q ); |
| } |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| HighlightAnnotation::~HighlightAnnotation() |
| { |
| } |
| |
| void HighlightAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| Q_D( const HighlightAnnotation ); |
| |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [hl] element |
| QDomElement hlElement = document.createElement( "hl" ); |
| node.appendChild( hlElement ); |
| |
| // append the optional attributes |
| if ( d->highlightType != Highlight ) |
| hlElement.setAttribute( "type", (int)d->highlightType ); |
| if ( d->highlightQuads.count() < 1 ) |
| return; |
| // append highlight quads, all children describe quads |
| QList< HighlightAnnotation::Quad >::const_iterator it = d->highlightQuads.begin(), end = d->highlightQuads.end(); |
| for ( ; it != end; ++it ) |
| { |
| QDomElement quadElement = document.createElement( "quad" ); |
| hlElement.appendChild( quadElement ); |
| const Quad & q = *it; |
| quadElement.setAttribute( "ax", q.points[0].x() ); |
| quadElement.setAttribute( "ay", q.points[0].y() ); |
| quadElement.setAttribute( "bx", q.points[1].x() ); |
| quadElement.setAttribute( "by", q.points[1].y() ); |
| quadElement.setAttribute( "cx", q.points[2].x() ); |
| quadElement.setAttribute( "cy", q.points[2].y() ); |
| quadElement.setAttribute( "dx", q.points[3].x() ); |
| quadElement.setAttribute( "dy", q.points[3].y() ); |
| if ( q.capStart ) |
| quadElement.setAttribute( "start", 1 ); |
| if ( q.capEnd ) |
| quadElement.setAttribute( "end", 1 ); |
| quadElement.setAttribute( "feather", q.feather ); |
| } |
| } |
| |
| Annotation::SubType HighlightAnnotation::subType() const |
| { |
| return AHighlight; |
| } |
| |
| HighlightAnnotation::HighlightType HighlightAnnotation::highlightType() const |
| { |
| Q_D( const HighlightAnnotation ); |
| return d->highlightType; |
| } |
| |
| void HighlightAnnotation::setHighlightType( HighlightAnnotation::HighlightType type ) |
| { |
| Q_D( HighlightAnnotation ); |
| d->highlightType = type; |
| } |
| |
| QList< HighlightAnnotation::Quad > HighlightAnnotation::highlightQuads() const |
| { |
| Q_D( const HighlightAnnotation ); |
| return d->highlightQuads; |
| } |
| |
| void HighlightAnnotation::setHighlightQuads( const QList< HighlightAnnotation::Quad > &quads ) |
| { |
| Q_D( HighlightAnnotation ); |
| d->highlightQuads = quads; |
| } |
| |
| |
| /** StampAnnotation [Annotation] */ |
| class StampAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| StampAnnotationPrivate(); |
| |
| // data fields |
| QString stampIconName; |
| }; |
| |
| StampAnnotationPrivate::StampAnnotationPrivate() |
| : AnnotationPrivate(), stampIconName( "Draft" ) |
| { |
| } |
| |
| StampAnnotation::StampAnnotation() |
| : Annotation( *new StampAnnotationPrivate() ) |
| {} |
| |
| StampAnnotation::StampAnnotation( const QDomNode & node ) |
| : Annotation( *new StampAnnotationPrivate(), node ) |
| { |
| Q_D( StampAnnotation ); |
| |
| // loop through the whole children looking for a 'stamp' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "stamp" ) |
| continue; |
| |
| // parse the attributes |
| if ( e.hasAttribute( "icon" ) ) |
| d->stampIconName = e.attribute( "icon" ); |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| StampAnnotation::~StampAnnotation() |
| { |
| } |
| |
| void StampAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| Q_D( const StampAnnotation ); |
| |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [stamp] element |
| QDomElement stampElement = document.createElement( "stamp" ); |
| node.appendChild( stampElement ); |
| |
| // append the optional attributes |
| if ( d->stampIconName != "Draft" ) |
| stampElement.setAttribute( "icon", d->stampIconName ); |
| } |
| |
| Annotation::SubType StampAnnotation::subType() const |
| { |
| return AStamp; |
| } |
| |
| QString StampAnnotation::stampIconName() const |
| { |
| Q_D( const StampAnnotation ); |
| return d->stampIconName; |
| } |
| |
| void StampAnnotation::setStampIconName( const QString &name ) |
| { |
| Q_D( StampAnnotation ); |
| d->stampIconName = name; |
| } |
| |
| /** InkAnnotation [Annotation] */ |
| class InkAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| InkAnnotationPrivate(); |
| |
| // data fields |
| QList< QLinkedList<QPointF> > inkPaths; |
| }; |
| |
| InkAnnotationPrivate::InkAnnotationPrivate() |
| : AnnotationPrivate() |
| { |
| } |
| |
| InkAnnotation::InkAnnotation() |
| : Annotation( *new InkAnnotationPrivate() ) |
| {} |
| |
| InkAnnotation::InkAnnotation( const QDomNode & node ) |
| : Annotation( *new InkAnnotationPrivate(), node ) |
| { |
| Q_D( InkAnnotation ); |
| |
| // loop through the whole children looking for a 'ink' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "ink" ) |
| continue; |
| |
| // parse the 'path' subnodes |
| QDomNode pathNode = e.firstChild(); |
| while ( pathNode.isElement() ) |
| { |
| QDomElement pathElement = pathNode.toElement(); |
| pathNode = pathNode.nextSibling(); |
| |
| if ( pathElement.tagName() != "path" ) |
| continue; |
| |
| // build each path parsing 'point' subnodes |
| QLinkedList<QPointF> path; |
| QDomNode pointNode = pathElement.firstChild(); |
| while ( pointNode.isElement() ) |
| { |
| QDomElement pointElement = pointNode.toElement(); |
| pointNode = pointNode.nextSibling(); |
| |
| if ( pointElement.tagName() != "point" ) |
| continue; |
| |
| QPointF p(pointElement.attribute( "x", "0.0" ).toDouble(), pointElement.attribute( "y", "0.0" ).toDouble()); |
| path.append( p ); |
| } |
| |
| // add the path to the path list if it contains at least 2 nodes |
| if ( path.count() >= 2 ) |
| d->inkPaths.append( path ); |
| } |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| InkAnnotation::~InkAnnotation() |
| { |
| } |
| |
| void InkAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| Q_D( const InkAnnotation ); |
| |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [ink] element |
| QDomElement inkElement = document.createElement( "ink" ); |
| node.appendChild( inkElement ); |
| |
| // append the optional attributes |
| if ( d->inkPaths.count() < 1 ) |
| return; |
| QList< QLinkedList<QPointF> >::const_iterator pIt = d->inkPaths.begin(), pEnd = d->inkPaths.end(); |
| for ( ; pIt != pEnd; ++pIt ) |
| { |
| QDomElement pathElement = document.createElement( "path" ); |
| inkElement.appendChild( pathElement ); |
| const QLinkedList<QPointF> & path = *pIt; |
| QLinkedList<QPointF>::const_iterator iIt = path.begin(), iEnd = path.end(); |
| for ( ; iIt != iEnd; ++iIt ) |
| { |
| const QPointF & point = *iIt; |
| QDomElement pointElement = document.createElement( "point" ); |
| pathElement.appendChild( pointElement ); |
| pointElement.setAttribute( "x", point.x() ); |
| pointElement.setAttribute( "y", point.y() ); |
| } |
| } |
| } |
| |
| Annotation::SubType InkAnnotation::subType() const |
| { |
| return AInk; |
| } |
| |
| QList< QLinkedList<QPointF> > InkAnnotation::inkPaths() const |
| { |
| Q_D( const InkAnnotation ); |
| return d->inkPaths; |
| } |
| |
| void InkAnnotation::setInkPaths( const QList< QLinkedList<QPointF> > &paths ) |
| { |
| Q_D( InkAnnotation ); |
| d->inkPaths = paths; |
| } |
| |
| |
| /** LinkAnnotation [Annotation] */ |
| class LinkAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| LinkAnnotationPrivate(); |
| ~LinkAnnotationPrivate(); |
| |
| // data fields |
| Link * linkDestination; |
| LinkAnnotation::HighlightMode linkHLMode; |
| QPointF linkRegion[4]; |
| }; |
| |
| LinkAnnotationPrivate::LinkAnnotationPrivate() |
| : AnnotationPrivate(), linkDestination( 0 ), linkHLMode( LinkAnnotation::Invert ) |
| { |
| } |
| |
| LinkAnnotationPrivate::~LinkAnnotationPrivate() |
| { |
| delete linkDestination; |
| } |
| |
| LinkAnnotation::LinkAnnotation() |
| : Annotation( *new LinkAnnotationPrivate() ) |
| {} |
| |
| LinkAnnotation::LinkAnnotation( const QDomNode & node ) |
| : Annotation( *new LinkAnnotationPrivate(), node ) |
| { |
| Q_D( LinkAnnotation ); |
| |
| // loop through the whole children looking for a 'link' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "link" ) |
| continue; |
| |
| // parse the attributes |
| if ( e.hasAttribute( "hlmode" ) ) |
| d->linkHLMode = (LinkAnnotation::HighlightMode)e.attribute( "hlmode" ).toInt(); |
| |
| // parse all 'quad' subnodes |
| QDomNode quadNode = e.firstChild(); |
| for ( ; quadNode.isElement(); quadNode = quadNode.nextSibling() ) |
| { |
| QDomElement qe = quadNode.toElement(); |
| if ( qe.tagName() == "quad" ) |
| { |
| d->linkRegion[0].setX(qe.attribute( "ax", "0.0" ).toDouble()); |
| d->linkRegion[0].setY(qe.attribute( "ay", "0.0" ).toDouble()); |
| d->linkRegion[1].setX(qe.attribute( "bx", "0.0" ).toDouble()); |
| d->linkRegion[1].setY(qe.attribute( "by", "0.0" ).toDouble()); |
| d->linkRegion[2].setX(qe.attribute( "cx", "0.0" ).toDouble()); |
| d->linkRegion[2].setY(qe.attribute( "cy", "0.0" ).toDouble()); |
| d->linkRegion[3].setX(qe.attribute( "dx", "0.0" ).toDouble()); |
| d->linkRegion[3].setY(qe.attribute( "dy", "0.0" ).toDouble()); |
| } |
| else if ( qe.tagName() == "link" ) |
| { |
| QString type = qe.attribute( "type" ); |
| if ( type == "GoTo" ) |
| { |
| Poppler::LinkGoto * go = new Poppler::LinkGoto( QRect(), qe.attribute( "filename" ), LinkDestination( qe.attribute( "destination" ) ) ); |
| d->linkDestination = go; |
| } |
| else if ( type == "Exec" ) |
| { |
| Poppler::LinkExecute * exec = new Poppler::LinkExecute( QRect(), qe.attribute( "filename" ), qe.attribute( "parameters" ) ); |
| d->linkDestination = exec; |
| } |
| else if ( type == "Browse" ) |
| { |
| Poppler::LinkBrowse * browse = new Poppler::LinkBrowse( QRect(), qe.attribute( "url" ) ); |
| d->linkDestination = browse; |
| } |
| else if ( type == "Action" ) |
| { |
| Poppler::LinkAction::ActionType act; |
| QString actString = qe.attribute( "action" ); |
| bool found = true; |
| if ( actString == "PageFirst" ) |
| act = Poppler::LinkAction::PageFirst; |
| else if ( actString == "PagePrev" ) |
| act = Poppler::LinkAction::PagePrev; |
| else if ( actString == "PageNext" ) |
| act = Poppler::LinkAction::PageNext; |
| else if ( actString == "PageLast" ) |
| act = Poppler::LinkAction::PageLast; |
| else if ( actString == "HistoryBack" ) |
| act = Poppler::LinkAction::HistoryBack; |
| else if ( actString == "HistoryForward" ) |
| act = Poppler::LinkAction::HistoryForward; |
| else if ( actString == "Quit" ) |
| act = Poppler::LinkAction::Quit; |
| else if ( actString == "Presentation" ) |
| act = Poppler::LinkAction::Presentation; |
| else if ( actString == "EndPresentation" ) |
| act = Poppler::LinkAction::EndPresentation; |
| else if ( actString == "Find" ) |
| act = Poppler::LinkAction::Find; |
| else if ( actString == "GoToPage" ) |
| act = Poppler::LinkAction::GoToPage; |
| else if ( actString == "Close" ) |
| act = Poppler::LinkAction::Close; |
| else |
| found = false; |
| if (found) |
| { |
| Poppler::LinkAction * action = new Poppler::LinkAction( QRect(), act ); |
| d->linkDestination = action; |
| } |
| } |
| #if 0 |
| else if ( type == "Movie" ) |
| { |
| Poppler::LinkMovie * movie = new Poppler::LinkMovie( QRect() ); |
| d->linkDestination = movie; |
| } |
| #endif |
| } |
| } |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| LinkAnnotation::~LinkAnnotation() |
| { |
| } |
| |
| void LinkAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| Q_D( const LinkAnnotation ); |
| |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [hl] element |
| QDomElement linkElement = document.createElement( "link" ); |
| node.appendChild( linkElement ); |
| |
| // append the optional attributes |
| if ( d->linkHLMode != Invert ) |
| linkElement.setAttribute( "hlmode", (int)d->linkHLMode ); |
| |
| // saving region |
| QDomElement quadElement = document.createElement( "quad" ); |
| linkElement.appendChild( quadElement ); |
| quadElement.setAttribute( "ax", d->linkRegion[0].x() ); |
| quadElement.setAttribute( "ay", d->linkRegion[0].y() ); |
| quadElement.setAttribute( "bx", d->linkRegion[1].x() ); |
| quadElement.setAttribute( "by", d->linkRegion[1].y() ); |
| quadElement.setAttribute( "cx", d->linkRegion[2].x() ); |
| quadElement.setAttribute( "cy", d->linkRegion[2].y() ); |
| quadElement.setAttribute( "dx", d->linkRegion[3].x() ); |
| quadElement.setAttribute( "dy", d->linkRegion[3].y() ); |
| |
| // saving link |
| QDomElement hyperlinkElement = document.createElement( "link" ); |
| linkElement.appendChild( hyperlinkElement ); |
| if ( d->linkDestination ) |
| { |
| switch( d->linkDestination->linkType() ) |
| { |
| case Poppler::Link::Goto: |
| { |
| Poppler::LinkGoto * go = static_cast< Poppler::LinkGoto * >( d->linkDestination ); |
| hyperlinkElement.setAttribute( "type", "GoTo" ); |
| hyperlinkElement.setAttribute( "filename", go->fileName() ); |
| hyperlinkElement.setAttribute( "destionation", go->destination().toString() ); |
| break; |
| } |
| case Poppler::Link::Execute: |
| { |
| Poppler::LinkExecute * exec = static_cast< Poppler::LinkExecute * >( d->linkDestination ); |
| hyperlinkElement.setAttribute( "type", "Exec" ); |
| hyperlinkElement.setAttribute( "filename", exec->fileName() ); |
| hyperlinkElement.setAttribute( "parameters", exec->parameters() ); |
| break; |
| } |
| case Poppler::Link::Browse: |
| { |
| Poppler::LinkBrowse * browse = static_cast< Poppler::LinkBrowse * >( d->linkDestination ); |
| hyperlinkElement.setAttribute( "type", "Browse" ); |
| hyperlinkElement.setAttribute( "url", browse->url() ); |
| break; |
| } |
| case Poppler::Link::Action: |
| { |
| Poppler::LinkAction * action = static_cast< Poppler::LinkAction * >( d->linkDestination ); |
| hyperlinkElement.setAttribute( "type", "Action" ); |
| switch ( action->actionType() ) |
| { |
| case Poppler::LinkAction::PageFirst: |
| hyperlinkElement.setAttribute( "action", "PageFirst" ); |
| break; |
| case Poppler::LinkAction::PagePrev: |
| hyperlinkElement.setAttribute( "action", "PagePrev" ); |
| break; |
| case Poppler::LinkAction::PageNext: |
| hyperlinkElement.setAttribute( "action", "PageNext" ); |
| break; |
| case Poppler::LinkAction::PageLast: |
| hyperlinkElement.setAttribute( "action", "PageLast" ); |
| break; |
| case Poppler::LinkAction::HistoryBack: |
| hyperlinkElement.setAttribute( "action", "HistoryBack" ); |
| break; |
| case Poppler::LinkAction::HistoryForward: |
| hyperlinkElement.setAttribute( "action", "HistoryForward" ); |
| break; |
| case Poppler::LinkAction::Quit: |
| hyperlinkElement.setAttribute( "action", "Quit" ); |
| break; |
| case Poppler::LinkAction::Presentation: |
| hyperlinkElement.setAttribute( "action", "Presentation" ); |
| break; |
| case Poppler::LinkAction::EndPresentation: |
| hyperlinkElement.setAttribute( "action", "EndPresentation" ); |
| break; |
| case Poppler::LinkAction::Find: |
| hyperlinkElement.setAttribute( "action", "Find" ); |
| break; |
| case Poppler::LinkAction::GoToPage: |
| hyperlinkElement.setAttribute( "action", "GoToPage" ); |
| break; |
| case Poppler::LinkAction::Close: |
| hyperlinkElement.setAttribute( "action", "Close" ); |
| break; |
| } |
| break; |
| } |
| case Poppler::Link::Movie: |
| { |
| hyperlinkElement.setAttribute( "type", "Movie" ); |
| break; |
| } |
| case Poppler::Link::Sound: |
| { |
| // FIXME: implement me |
| break; |
| } |
| case Poppler::Link::None: |
| break; |
| } |
| } |
| } |
| |
| Annotation::SubType LinkAnnotation::subType() const |
| { |
| return ALink; |
| } |
| |
| Link* LinkAnnotation::linkDestionation() const |
| { |
| Q_D( const LinkAnnotation ); |
| return d->linkDestination; |
| } |
| |
| void LinkAnnotation::setLinkDestination( Link *link ) |
| { |
| Q_D( LinkAnnotation ); |
| delete d->linkDestination; |
| d->linkDestination = link; |
| } |
| |
| LinkAnnotation::HighlightMode LinkAnnotation::linkHighlightMode() const |
| { |
| Q_D( const LinkAnnotation ); |
| return d->linkHLMode; |
| } |
| |
| void LinkAnnotation::setLinkHighlightMode( LinkAnnotation::HighlightMode mode ) |
| { |
| Q_D( LinkAnnotation ); |
| d->linkHLMode = mode; |
| } |
| |
| QPointF LinkAnnotation::linkRegionPoint( int id ) const |
| { |
| if ( id < 0 || id >= 4 ) |
| return QPointF(); |
| |
| Q_D( const LinkAnnotation ); |
| return d->linkRegion[id]; |
| } |
| |
| void LinkAnnotation::setLinkRegionPoint( int id, const QPointF &point ) |
| { |
| if ( id < 0 || id >= 4 ) |
| return; |
| |
| Q_D( LinkAnnotation ); |
| d->linkRegion[id] = point; |
| } |
| |
| /** CaretAnnotation [Annotation] */ |
| class CaretAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| CaretAnnotationPrivate(); |
| |
| // data fields |
| CaretAnnotation::CaretSymbol symbol; |
| }; |
| |
| static QString caretSymbolToString( CaretAnnotation::CaretSymbol symbol ) |
| { |
| switch ( symbol ) |
| { |
| case CaretAnnotation::None: |
| return QString::fromLatin1( "None" ); |
| case CaretAnnotation::P: |
| return QString::fromLatin1( "P" ); |
| } |
| return QString(); |
| } |
| |
| static CaretAnnotation::CaretSymbol caretSymbolFromString( const QString &symbol ) |
| { |
| if ( symbol == QLatin1String( "None" ) ) |
| return CaretAnnotation::None; |
| else if ( symbol == QLatin1String( "P" ) ) |
| return CaretAnnotation::P; |
| return CaretAnnotation::None; |
| } |
| |
| CaretAnnotationPrivate::CaretAnnotationPrivate() |
| : AnnotationPrivate(), symbol( CaretAnnotation::None ) |
| { |
| } |
| |
| CaretAnnotation::CaretAnnotation() |
| : Annotation( *new CaretAnnotationPrivate() ) |
| { |
| } |
| |
| CaretAnnotation::CaretAnnotation( const QDomNode & node ) |
| : Annotation( *new CaretAnnotationPrivate(), node ) |
| { |
| Q_D( CaretAnnotation ); |
| |
| // loop through the whole children looking for a 'caret' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "caret" ) |
| continue; |
| |
| // parse the attributes |
| if ( e.hasAttribute( "symbol" ) ) |
| d->symbol = caretSymbolFromString( e.attribute( "symbol" ) ); |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| CaretAnnotation::~CaretAnnotation() |
| { |
| } |
| |
| void CaretAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| Q_D( const CaretAnnotation ); |
| |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [caret] element |
| QDomElement caretElement = document.createElement( "caret" ); |
| node.appendChild( caretElement ); |
| |
| // append the optional attributes |
| if ( d->symbol != CaretAnnotation::None ) |
| caretElement.setAttribute( "symbol", caretSymbolToString( d->symbol ) ); |
| } |
| |
| Annotation::SubType CaretAnnotation::subType() const |
| { |
| return ACaret; |
| } |
| |
| CaretAnnotation::CaretSymbol CaretAnnotation::caretSymbol() const |
| { |
| Q_D( const CaretAnnotation ); |
| return d->symbol; |
| } |
| |
| void CaretAnnotation::setCaretSymbol( CaretAnnotation::CaretSymbol symbol ) |
| { |
| Q_D( CaretAnnotation ); |
| d->symbol = symbol; |
| } |
| |
| /** FileAttachmentAnnotation [Annotation] */ |
| class FileAttachmentAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| FileAttachmentAnnotationPrivate(); |
| ~FileAttachmentAnnotationPrivate(); |
| |
| // data fields |
| QString icon; |
| EmbeddedFile *embfile; |
| }; |
| |
| FileAttachmentAnnotationPrivate::FileAttachmentAnnotationPrivate() |
| : AnnotationPrivate(), icon( "PushPin" ), embfile( 0 ) |
| { |
| } |
| |
| FileAttachmentAnnotationPrivate::~FileAttachmentAnnotationPrivate() |
| { |
| delete embfile; |
| } |
| |
| FileAttachmentAnnotation::FileAttachmentAnnotation() |
| : Annotation( *new FileAttachmentAnnotationPrivate() ) |
| { |
| } |
| |
| FileAttachmentAnnotation::FileAttachmentAnnotation( const QDomNode & node ) |
| : Annotation( *new FileAttachmentAnnotationPrivate(), node ) |
| { |
| // loop through the whole children looking for a 'fileattachment' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "fileattachment" ) |
| continue; |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| FileAttachmentAnnotation::~FileAttachmentAnnotation() |
| { |
| } |
| |
| void FileAttachmentAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [fileattachment] element |
| QDomElement fileAttachmentElement = document.createElement( "fileattachment" ); |
| node.appendChild( fileAttachmentElement ); |
| } |
| |
| Annotation::SubType FileAttachmentAnnotation::subType() const |
| { |
| return AFileAttachment; |
| } |
| |
| QString FileAttachmentAnnotation::fileIconName() const |
| { |
| Q_D( const FileAttachmentAnnotation ); |
| return d->icon; |
| } |
| |
| void FileAttachmentAnnotation::setFileIconName( const QString &icon ) |
| { |
| Q_D( FileAttachmentAnnotation ); |
| d->icon = icon; |
| } |
| |
| EmbeddedFile* FileAttachmentAnnotation::embeddedFile() const |
| { |
| Q_D( const FileAttachmentAnnotation ); |
| return d->embfile; |
| } |
| |
| void FileAttachmentAnnotation::setEmbeddedFile( EmbeddedFile *ef ) |
| { |
| Q_D( FileAttachmentAnnotation ); |
| d->embfile = ef; |
| } |
| |
| /** SoundAnnotation [Annotation] */ |
| class SoundAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| SoundAnnotationPrivate(); |
| ~SoundAnnotationPrivate(); |
| |
| // data fields |
| QString icon; |
| SoundObject *sound; |
| }; |
| |
| SoundAnnotationPrivate::SoundAnnotationPrivate() |
| : AnnotationPrivate(), icon( "Speaker" ), sound( 0 ) |
| { |
| } |
| |
| SoundAnnotationPrivate::~SoundAnnotationPrivate() |
| { |
| delete sound; |
| } |
| |
| SoundAnnotation::SoundAnnotation() |
| : Annotation( *new SoundAnnotationPrivate() ) |
| { |
| } |
| |
| SoundAnnotation::SoundAnnotation( const QDomNode & node ) |
| : Annotation( *new SoundAnnotationPrivate(), node ) |
| { |
| // loop through the whole children looking for a 'sound' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "sound" ) |
| continue; |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| SoundAnnotation::~SoundAnnotation() |
| { |
| } |
| |
| void SoundAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [sound] element |
| QDomElement soundElement = document.createElement( "sound" ); |
| node.appendChild( soundElement ); |
| } |
| |
| Annotation::SubType SoundAnnotation::subType() const |
| { |
| return ASound; |
| } |
| |
| QString SoundAnnotation::soundIconName() const |
| { |
| Q_D( const SoundAnnotation ); |
| return d->icon; |
| } |
| |
| void SoundAnnotation::setSoundIconName( const QString &icon ) |
| { |
| Q_D( SoundAnnotation ); |
| d->icon = icon; |
| } |
| |
| SoundObject* SoundAnnotation::sound() const |
| { |
| Q_D( const SoundAnnotation ); |
| return d->sound; |
| } |
| |
| void SoundAnnotation::setSound( SoundObject *s ) |
| { |
| Q_D( SoundAnnotation ); |
| d->sound = s; |
| } |
| |
| /** MovieAnnotation [Annotation] */ |
| class MovieAnnotationPrivate : public AnnotationPrivate |
| { |
| public: |
| MovieAnnotationPrivate(); |
| ~MovieAnnotationPrivate(); |
| |
| // data fields |
| MovieObject *movie; |
| QString title; |
| }; |
| |
| MovieAnnotationPrivate::MovieAnnotationPrivate() |
| : AnnotationPrivate(), movie( 0 ) |
| { |
| } |
| |
| MovieAnnotationPrivate::~MovieAnnotationPrivate() |
| { |
| delete movie; |
| } |
| |
| MovieAnnotation::MovieAnnotation() |
| : Annotation( *new MovieAnnotationPrivate() ) |
| { |
| } |
| |
| MovieAnnotation::MovieAnnotation( const QDomNode & node ) |
| : Annotation( *new MovieAnnotationPrivate(), node ) |
| { |
| // loop through the whole children looking for a 'movie' element |
| QDomNode subNode = node.firstChild(); |
| while( subNode.isElement() ) |
| { |
| QDomElement e = subNode.toElement(); |
| subNode = subNode.nextSibling(); |
| if ( e.tagName() != "movie" ) |
| continue; |
| |
| // loading complete |
| break; |
| } |
| } |
| |
| MovieAnnotation::~MovieAnnotation() |
| { |
| } |
| |
| void MovieAnnotation::store( QDomNode & node, QDomDocument & document ) const |
| { |
| // recurse to parent objects storing properties |
| Annotation::store( node, document ); |
| |
| // create [movie] element |
| QDomElement movieElement = document.createElement( "movie" ); |
| node.appendChild( movieElement ); |
| } |
| |
| Annotation::SubType MovieAnnotation::subType() const |
| { |
| return AMovie; |
| } |
| |
| MovieObject* MovieAnnotation::movie() const |
| { |
| Q_D( const MovieAnnotation ); |
| return d->movie; |
| } |
| |
| void MovieAnnotation::setMovie( MovieObject *movie ) |
| { |
| Q_D( MovieAnnotation ); |
| d->movie = movie; |
| } |
| |
| QString MovieAnnotation::movieTitle() const |
| { |
| Q_D( const MovieAnnotation ); |
| return d->title; |
| } |
| |
| void MovieAnnotation::setMovieTitle( const QString &title ) |
| { |
| Q_D( MovieAnnotation ); |
| d->title = title; |
| } |
| |
| //BEGIN utility annotation functions |
| QColor convertAnnotColor( AnnotColor *color ) |
| { |
| if ( !color ) |
| return QColor(); |
| |
| QColor newcolor; |
| double *color_data = color->getValues(); |
| switch ( color->getSpace() ) |
| { |
| case AnnotColor::colorTransparent: // = 0, |
| newcolor = Qt::transparent; |
| break; |
| case AnnotColor::colorGray: // = 1, |
| newcolor.setRgbF( color_data[0], color_data[0], color_data[0] ); |
| break; |
| case AnnotColor::colorRGB: // = 3, |
| newcolor.setRgbF( color_data[0], color_data[1], color_data[2] ); |
| break; |
| case AnnotColor::colorCMYK: // = 4 |
| newcolor.setCmykF( color_data[0], color_data[1], color_data[2], color_data[3] ); |
| break; |
| } |
| return newcolor; |
| } |
| //END utility annotation functions |
| |
| } |