[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [okular] /: Evaluate additional actions of screen and widget annotations
From:       Tobias Koenig <tokoe () kde ! org>
Date:       2012-09-21 8:51:10
Message-ID: 20120921085110.044BBA6094 () git ! kde ! org
[Download RAW message or body]

Git commit 770e2818bb149211330ddbc35877c20624a71862 by Tobias Koenig.
Committed on 16/08/2012 at 11:53.
Pushed by tokoe into branch 'master'.

Evaluate additional actions of screen and widget annotations

This fixes the auto-start feature of PDFs generated with the LaTeX movie
package, which uses the additional action of a widget annotation to start
the movie when entering the page.

BUG: 300051
REVIEW: 106430
FIXED-IN: 4.10

M  +4    -0    cmake/modules/FindPoppler.cmake
M  +147  -0    core/annotations.cpp
M  +127  -0    core/annotations.h
M  +7    -0    generators/poppler/annots.cpp
M  +47   -0    generators/poppler/generator_pdf.cpp
M  +6    -0    ui/guiutils.cpp
M  +28   -0    ui/presentationwidget.cpp

http://commits.kde.org/okular/770e2818bb149211330ddbc35877c20624a71862

diff --git a/cmake/modules/FindPoppler.cmake b/cmake/modules/FindPoppler.cmake
index 06e7117..1763ee9 100644
--- a/cmake/modules/FindPoppler.cmake
+++ b/cmake/modules/FindPoppler.cmake
@@ -99,11 +99,15 @@ int main()
 
 check_cxx_source_compiles("
 #include <poppler-qt4.h>
+#include <poppler-annotation.h>
 
 int main()
 {
   Poppler::MovieObject *movie = 0;
   movie->showPosterImage();
+
+  const Poppler::Annotation::AdditionalActionType type = \
Poppler::Annotation::PageOpeningAction; +
   return 0;
 }
 " HAVE_POPPLER_0_22)
diff --git a/core/annotations.cpp b/core/annotations.cpp
index ceb571c..21114af 100644
--- a/core/annotations.cpp
+++ b/core/annotations.cpp
@@ -15,6 +15,7 @@
 #include <QtGui/QColor>
 
 // local includes
+#include "action.h"
 #include "document.h"
 #include "document_p.h"
 #include "movie.h"
@@ -2411,3 +2412,149 @@ void MovieAnnotation::setMovie( Movie *movie )
     Q_D( MovieAnnotation );
     d->movie = movie;
 }
+
+/** ScreenAnnotation [Annotation] */
+
+class Okular::ScreenAnnotationPrivate : public Okular::AnnotationPrivate
+{
+    public:
+        ~ScreenAnnotationPrivate();
+        QMap< Okular::Annotation::AdditionalActionType, Okular::Action* > \
m_additionalActions; +};
+
+ScreenAnnotationPrivate::~ScreenAnnotationPrivate()
+{
+    qDeleteAll( m_additionalActions );
+}
+
+ScreenAnnotation::ScreenAnnotation()
+    : Annotation( *new ScreenAnnotationPrivate() )
+{
+}
+
+ScreenAnnotation::ScreenAnnotation( const QDomNode & node )
+    : Annotation( *new ScreenAnnotationPrivate(), node )
+{
+    // loop through the whole children looking for a 'screen' element
+    QDomNode subNode = node.firstChild();
+    while( subNode.isElement() )
+    {
+        QDomElement e = subNode.toElement();
+        subNode = subNode.nextSibling();
+        if ( e.tagName() != "screen" )
+            continue;
+
+        // loading complete
+        break;
+    }
+}
+
+ScreenAnnotation::~ScreenAnnotation()
+{
+}
+
+void ScreenAnnotation::store( QDomNode & node, QDomDocument & document ) const
+{
+    // recurse to parent objects storing properties
+    Annotation::store( node, document );
+
+    // create [screen] element
+    QDomElement movieElement = document.createElement( "screen" );
+    node.appendChild( movieElement );
+}
+
+Annotation::SubType ScreenAnnotation::subType() const
+{
+    return AScreen;
+}
+
+void ScreenAnnotation::setAdditionalAction( AdditionalActionType type, Action \
*action ) +{
+    Q_D( ScreenAnnotation );
+    if ( d->m_additionalActions.contains( type ) )
+        delete d->m_additionalActions.value( type );
+
+    d->m_additionalActions.insert( type, action );
+}
+
+Action* ScreenAnnotation::additionalAction( AdditionalActionType type ) const
+{
+    Q_D( const ScreenAnnotation );
+    if ( !d->m_additionalActions.contains( type ) )
+        return 0;
+    else
+        return d->m_additionalActions.value( type );
+}
+
+/** WidgetAnnotation [Annotation] */
+
+class Okular::WidgetAnnotationPrivate : public Okular::AnnotationPrivate
+{
+    public:
+        ~WidgetAnnotationPrivate();
+        QMap< Okular::Annotation::AdditionalActionType, Okular::Action* > \
m_additionalActions; +};
+
+WidgetAnnotationPrivate::~WidgetAnnotationPrivate()
+{
+    qDeleteAll( m_additionalActions );
+}
+
+WidgetAnnotation::WidgetAnnotation()
+    : Annotation( *new WidgetAnnotationPrivate() )
+{
+}
+
+WidgetAnnotation::WidgetAnnotation( const QDomNode & node )
+    : Annotation( *new WidgetAnnotationPrivate(), node )
+{
+    // loop through the whole children looking for a 'widget' element
+    QDomNode subNode = node.firstChild();
+    while( subNode.isElement() )
+    {
+        QDomElement e = subNode.toElement();
+        subNode = subNode.nextSibling();
+        if ( e.tagName() != "widget" )
+            continue;
+
+        // loading complete
+        break;
+    }
+}
+
+WidgetAnnotation::~WidgetAnnotation()
+{
+}
+
+void WidgetAnnotation::store( QDomNode & node, QDomDocument & document ) const
+{
+    // recurse to parent objects storing properties
+    Annotation::store( node, document );
+
+    // create [widget] element
+    QDomElement movieElement = document.createElement( "widget" );
+    node.appendChild( movieElement );
+}
+
+Annotation::SubType WidgetAnnotation::subType() const
+{
+    return AWidget;
+}
+
+void WidgetAnnotation::setAdditionalAction( AdditionalActionType type, Action \
*action ) +{
+    Q_D( WidgetAnnotation );
+    if ( d->m_additionalActions.contains( type ) )
+        delete d->m_additionalActions.value( type );
+
+    d->m_additionalActions.insert( type, action );
+}
+
+Action* WidgetAnnotation::additionalAction( AdditionalActionType type ) const
+{
+    Q_D( const WidgetAnnotation );
+    if ( !d->m_additionalActions.contains( type ) )
+        return 0;
+    else
+        return d->m_additionalActions.value( type );
+}
diff --git a/core/annotations.h b/core/annotations.h
index e2b04bc..5fefb29 100644
--- a/core/annotations.h
+++ b/core/annotations.h
@@ -23,6 +23,7 @@
 
 namespace Okular {
 
+class Action;
 class Annotation;
 class AnnotationObjectRect;
 class AnnotationPrivate;
@@ -42,6 +43,8 @@ class CaretAnnotationPrivate;
 class FileAttachmentAnnotationPrivate;
 class SoundAnnotationPrivate;
 class MovieAnnotationPrivate;
+class ScreenAnnotationPrivate;
+class WidgetAnnotationPrivate;
 
 /**
  * @short Helper class for (recursive) annotation retrieval/storage.
@@ -109,6 +112,8 @@ class OKULAR_EXPORT Annotation
             AFileAttachment = 9, ///< A file attachment annotation
             ASound = 10,    ///< A sound annotation
             AMovie = 11,    ///< A movie annotation
+            AScreen = 12,   ///< A screen annotation
+            AWidget = 13,   ///< A widget annotation
             A_BASE = 0      ///< The annotation base class
         };
 
@@ -175,6 +180,17 @@ class OKULAR_EXPORT Annotation
         };
 
         /**
+         * Describes the type of additional actions.
+         *
+         * @since 0.16 (KDE 4.10)
+         */
+        enum AdditionalActionType
+        {
+            PageOpening, ///< Performed when the page containing the annotation is \
opened. +            PageClosing  ///< Performed when the page containing the \
annotation is closed. +        };
+
+        /**
          * A function to be called when the annotation is destroyed.
          *
          * @warning the function must *not* call any virtual function,
@@ -1511,6 +1527,117 @@ class OKULAR_EXPORT MovieAnnotation : public Annotation
         Q_DISABLE_COPY( MovieAnnotation )
 };
 
+/**
+ * \short Screen annotation.
+ *
+ * The screen annotation specifies a region of a page upon which media clips
+ * may be played. It also serves as an object from which actions can be triggered.
+ *
+ * @since 0.16 (KDE 4.10)
+ */
+class OKULAR_EXPORT ScreenAnnotation : public Annotation
+{
+    public:
+        /**
+         * Creates a new screen annotation.
+         */
+        ScreenAnnotation();
+
+        /**
+         * Creates a new screen annotation from the xml @p description
+         */
+        ScreenAnnotation( const QDomNode &description );
+
+        /**
+         * Destroys the screen annotation.
+         */
+        virtual ~ScreenAnnotation();
+
+        /**
+         * Returns the sub type of the screen annotation.
+         */
+        SubType subType() const;
+
+        /**
+         * Stores the screen annotation as xml in @p document
+         * under the given @p parentNode.
+         */
+        void store( QDomNode &parentNode, QDomDocument &document ) const;
+
+        /**
+         * Sets the additional @p action of the given @p type.
+         *
+         * @since 0.16 (KDE 4.10)
+         */
+        void setAdditionalAction( AdditionalActionType type, Action *action );
+
+        /**
+         * Returns the additional action of the given @p type or @c 0 if no action \
has been defined. +         *
+         * @since 0.16 (KDE 4.10)
+         */
+        Action* additionalAction( AdditionalActionType type ) const;
+
+    private:
+        Q_DECLARE_PRIVATE( ScreenAnnotation )
+        Q_DISABLE_COPY( ScreenAnnotation )
+};
+
+/**
+ * \short Widget annotation.
+ *
+ * The widget annotation represents a widget on a page.
+ *
+ * @since 0.16 (KDE 4.10)
+ */
+class OKULAR_EXPORT WidgetAnnotation : public Annotation
+{
+    public:
+        /**
+         * Creates a new widget annotation.
+         */
+        WidgetAnnotation();
+
+        /**
+         * Creates a new widget annotation from the xml @p description
+         */
+        WidgetAnnotation( const QDomNode &description );
+
+        /**
+         * Destroys the widget annotation.
+         */
+        virtual ~WidgetAnnotation();
+
+        /**
+         * Returns the sub type of the widget annotation.
+         */
+        SubType subType() const;
+
+        /**
+         * Stores the widget annotation as xml in @p document
+         * under the given @p parentNode.
+         */
+        void store( QDomNode &parentNode, QDomDocument &document ) const;
+
+        /**
+         * Sets the additional @p action of the given @p type.
+         *
+         * @since 0.16 (KDE 4.10)
+         */
+        void setAdditionalAction( AdditionalActionType type, Action *action );
+
+        /**
+         * Returns the additional action of the given @p type or @c 0 if no action \
has been defined. +         *
+         * @since 0.16 (KDE 4.10)
+         */
+        Action* additionalAction( AdditionalActionType type ) const;
+
+    private:
+        Q_DECLARE_PRIVATE( WidgetAnnotation )
+        Q_DISABLE_COPY( WidgetAnnotation )
+};
+
 }
 
 #endif
diff --git a/generators/poppler/annots.cpp b/generators/poppler/annots.cpp
index 06128c5..02813a1 100644
--- a/generators/poppler/annots.cpp
+++ b/generators/poppler/annots.cpp
@@ -310,6 +310,13 @@ Okular::Annotation* createAnnotationFromPopplerAnnotation( \
Poppler::Annotation *  
             break;
         }
+#ifdef HAVE_POPPLER_0_22
+        case Poppler::Annotation::AWidget:
+        {
+            annotation = new Okular::WidgetAnnotation();
+            break;
+        }
+#endif
 #ifdef HAVE_POPPLER_0_20
         case Poppler::Annotation::AScreen:
         {
diff --git a/generators/poppler/generator_pdf.cpp \
b/generators/poppler/generator_pdf.cpp index c63753e..9462195 100644
--- a/generators/poppler/generator_pdf.cpp
+++ b/generators/poppler/generator_pdf.cpp
@@ -945,6 +945,23 @@ void PDFGenerator::resolveMovieLinkReferences( Okular::Page \
                *page )
     resolveMovieLinkReference( const_cast<Okular::Action*>( page->pageAction( \
                Okular::Page::Opening ) ), page );
     resolveMovieLinkReference( const_cast<Okular::Action*>( page->pageAction( \
Okular::Page::Closing ) ), page );  
+    foreach ( Okular::Annotation *annotation, page->annotations() )
+    {
+        if ( annotation->subType() == Okular::Annotation::AScreen )
+        {
+            Okular::ScreenAnnotation *screenAnnotation = \
static_cast<Okular::ScreenAnnotation*>( annotation ); +            \
resolveMovieLinkReference( screenAnnotation->additionalAction( \
Okular::Annotation::PageOpening ), page ); +            resolveMovieLinkReference( \
screenAnnotation->additionalAction( Okular::Annotation::PageClosing ), page ); +      \
} +
+        if ( annotation->subType() == Okular::Annotation::AWidget )
+        {
+            Okular::WidgetAnnotation *widgetAnnotation = \
static_cast<Okular::WidgetAnnotation*>( annotation ); +            \
resolveMovieLinkReference( widgetAnnotation->additionalAction( \
Okular::Annotation::PageOpening ), page ); +            resolveMovieLinkReference( \
widgetAnnotation->additionalAction( Okular::Annotation::PageClosing ), page ); +      \
} +    }
+
     foreach ( Okular::FormField *field, page->formFields() )
         resolveMovieLinkReference( field->activationAction(), page );
 }
@@ -1376,6 +1393,36 @@ void PDFGenerator::addAnnotations( Poppler::Page * \
popplerPage, Okular::Page * p  {
             page->addAnnotation(newann);
 
+#ifdef HAVE_POPPLER_0_22
+            if ( a->subType() == Poppler::Annotation::AScreen )
+            {
+                Poppler::ScreenAnnotation *annotScreen = \
static_cast<Poppler::ScreenAnnotation*>( a ); +                \
Okular::ScreenAnnotation *screenAnnotation = static_cast<Okular::ScreenAnnotation*>( \
newann ); +
+                const Poppler::Link *pageOpeningLink = \
annotScreen->additionalAction( Poppler::Annotation::PageOpeningAction ); +            \
if ( pageOpeningLink ) +                    screenAnnotation->setAdditionalAction( \
Okular::Annotation::PageOpening, createLinkFromPopplerLink( pageOpeningLink ) ); +
+                const Poppler::Link *pageClosingLink = \
annotScreen->additionalAction( Poppler::Annotation::PageClosingAction ); +            \
if ( pageClosingLink ) +                    screenAnnotation->setAdditionalAction( \
Okular::Annotation::PageClosing, createLinkFromPopplerLink( pageClosingLink ) ); +    \
} +
+            if ( a->subType() == Poppler::Annotation::AWidget )
+            {
+                Poppler::WidgetAnnotation *annotWidget = \
static_cast<Poppler::WidgetAnnotation*>( a ); +                \
Okular::WidgetAnnotation *widgetAnnotation = static_cast<Okular::WidgetAnnotation*>( \
newann ); +
+                const Poppler::Link *pageOpeningLink = \
annotWidget->additionalAction( Poppler::Annotation::PageOpeningAction ); +            \
if ( pageOpeningLink ) +                    widgetAnnotation->setAdditionalAction( \
Okular::Annotation::PageOpening, createLinkFromPopplerLink( pageOpeningLink ) ); +
+                const Poppler::Link *pageClosingLink = \
annotWidget->additionalAction( Poppler::Annotation::PageClosingAction ); +            \
if ( pageClosingLink ) +                    widgetAnnotation->setAdditionalAction( \
Okular::Annotation::PageClosing, createLinkFromPopplerLink( pageClosingLink ) ); +    \
} +#endif
+
             if ( !doDelete )
                 annotationsHash.insert( newann, a );
         }
diff --git a/ui/guiutils.cpp b/ui/guiutils.cpp
index f66dc47..30be525 100644
--- a/ui/guiutils.cpp
+++ b/ui/guiutils.cpp
@@ -99,6 +99,12 @@ QString captionForAnnotation( const Okular::Annotation * ann )
         case Okular::Annotation::AMovie:
             ret = i18n( "Movie" );
             break;
+        case Okular::Annotation::AScreen:
+            ret = i18nc( "Caption for a screen annotation", "Screen" );
+            break;
+        case Okular::Annotation::AWidget:
+            ret = i18nc( "Caption for a widget annotation", "Widget" );
+            break;
         case Okular::Annotation::A_BASE:
             break;
     }
diff --git a/ui/presentationwidget.cpp b/ui/presentationwidget.cpp
index 3f3796b..95e78d4 100644
--- a/ui/presentationwidget.cpp
+++ b/ui/presentationwidget.cpp
@@ -379,6 +379,20 @@ void PresentationWidget::notifyCurrentPageChanged( int \
previousPage, int current  // perform the page closing action, if any
         if ( m_document->page( previousPage )->pageAction( Okular::Page::Closing ) )
             m_document->processAction( m_document->page( previousPage )->pageAction( \
Okular::Page::Closing ) ); +
+        // perform the additional actions of the page's annotations, if any
+        Q_FOREACH ( const Okular::Annotation *annotation, m_document->page( \
m_frameIndex )->annotations() ) +        {
+            Okular::Action *action = 0;
+
+            if ( annotation->subType() == Okular::Annotation::AScreen )
+                action = static_cast<const Okular::ScreenAnnotation*>( annotation \
)->additionalAction( Okular::Annotation::PageClosing ); +            else if ( \
annotation->subType() == Okular::Annotation::AWidget ) +                action = \
static_cast<const Okular::WidgetAnnotation*>( annotation )->additionalAction( \
Okular::Annotation::PageClosing ); +
+            if ( action )
+                m_document->processAction( action );
+        }
     }
 
     if ( currentPage != -1 )
@@ -411,6 +425,20 @@ void PresentationWidget::notifyCurrentPageChanged( int \
                previousPage, int current
         if ( m_document->page( m_frameIndex )->pageAction( Okular::Page::Opening ) )
             m_document->processAction( m_document->page( m_frameIndex )->pageAction( \
Okular::Page::Opening ) );  
+        // perform the additional actions of the page's annotations, if any
+        Q_FOREACH ( const Okular::Annotation *annotation, m_document->page( \
m_frameIndex )->annotations() ) +        {
+            Okular::Action *action = 0;
+
+            if ( annotation->subType() == Okular::Annotation::AScreen )
+                action = static_cast<const Okular::ScreenAnnotation*>( annotation \
)->additionalAction( Okular::Annotation::PageOpening ); +            else if ( \
annotation->subType() == Okular::Annotation::AWidget ) +                action = \
static_cast<const Okular::WidgetAnnotation*>( annotation )->additionalAction( \
Okular::Annotation::PageOpening ); +
+            if ( action )
+                m_document->processAction( action );
+        }
+
         // start autoplay video playback
         Q_FOREACH ( VideoWidget *vw, m_frames[ m_frameIndex ]->videoWidgets )
             vw->pageEntered();


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic