Add support for chained / next actions

Summary:
This adds support for multiple actions following each
other through the "Next" value of Action dictionaries.

Test Plan: Activates the corresponding part of the visibilitytest.

Reviewers: #okular

Subscribers: sander, aacid

Tags: #okular

Maniphest Tasks: T8278

Differential Revision: https://phabricator.kde.org/D11609
This commit is contained in:
Andre Heinecke 2018-04-30 13:41:55 +02:00 committed by Albert Astals Cid
parent cc052577a4
commit 1de0f5465b
7 changed files with 75 additions and 19 deletions

View file

@ -166,15 +166,7 @@ void VisibilityTest::testActionVisibility()
m_document->processAction( hideBtn->activationAction() );
// XXX For now poppler only provides the first action
// in a chain. So only the first hide action is executed.
// The first hide action targets the Button. So for now
// only check this.
//
// This should work in principle:
// verifyTargetStates( false );
QCOMPARE( m_fields[QStringLiteral( "TargetButton" )]->isVisible(), false );
verifyTargetStates( false );
m_document->processAction( showBtn->activationAction() );

View file

@ -29,9 +29,11 @@ class Okular::ActionPrivate
virtual ~ActionPrivate()
{
qDeleteAll( m_nextActions );
}
QVariant m_nativeId;
QVector< Action * > m_nextActions;
};
Action::Action( ActionPrivate &dd )
@ -61,6 +63,18 @@ QVariant Action::nativeId() const
return d->m_nativeId;
}
QVector< Action * > Action::nextActions() const
{
Q_D( const Action );
return d->m_nextActions;
}
void Action::setNextActions( const QVector< Action * > &actions )
{
Q_D( Action );
d->m_nextActions = actions;
}
// GotoAction
class Okular::GotoActionPrivate : public Okular::ActionPrivate

View file

@ -97,6 +97,21 @@ class OKULARCORE_EXPORT Action
*/
QVariant nativeId() const;
/**
* Returns the next actions to be executed after.
*
* @since 1.5
*/
QVector< Action * > nextActions() const;
/**
* Sets the next actions.
*
* Takes ownership of the objects in the actions vector.
* @since 1.5
*/
void setNextActions( const QVector< Action * > &actions );
protected:
/// @cond PRIVATE
Action( ActionPrivate &dd );

View file

@ -4074,14 +4074,14 @@ void Document::processAction( const Action * action )
if ( go->isExternal() && !d->openRelativeFile( go->fileName() ) )
{
qCWarning(OkularCoreDebug).nospace() << "Action: Error opening '" << go->fileName() << "'.";
return;
break;
}
else
{
const DocumentViewport nextViewport = d->nextDocumentViewport();
// skip local links that point to nowhere (broken ones)
if ( !nextViewport.isValid() )
return;
break;
setViewport( nextViewport, nullptr, true );
d->m_nextDocumentViewport = DocumentViewport();
@ -4096,7 +4096,7 @@ void Document::processAction( const Action * action )
if ( fileName.endsWith( QLatin1String(".pdf"), Qt::CaseInsensitive ) )
{
d->openRelativeFile( fileName );
return;
break;
}
// Albert: the only pdf i have that has that kind of link don't define
@ -4118,7 +4118,7 @@ void Document::processAction( const Action * action )
// this case is a link pointing to an executable with a parameter
// that also is an executable, possibly a hand-crafted pdf
KMessageBox::information( d->m_widget, i18n("The document is trying to execute an external application and, for your safety, Okular does not allow that.") );
return;
break;
}
}
else
@ -4126,7 +4126,7 @@ void Document::processAction( const Action * action )
// this case is a link pointing to an executable with no parameters
// core developers find unacceptable executing it even after asking the user
KMessageBox::information( d->m_widget, i18n("The document is trying to execute an external application and, for your safety, Okular does not allow that.") );
return;
break;
}
}
@ -4208,7 +4208,7 @@ void Document::processAction( const Action * action )
if ((url.scheme() == "http") && url.host().isEmpty() && url.fileName().endsWith("pdf"))
{
d->openRelativeFile(url.fileName());
return;
break;
}
// handle documents with relative path
@ -4252,6 +4252,11 @@ void Document::processAction( const Action * action )
} break;
}
for ( const Action *a : action->nextActions() )
{
processAction( a );
}
}
void Document::processSourceReference( const SourceReference * ref )

View file

@ -75,11 +75,14 @@ int main()
check_cxx_source_compiles("
#include <poppler-qt5.h>
#include <poppler-form.h>
#include <poppler-link.h>
int main()
{
Poppler::FormField *f;
f->setReadOnly(true);
f->setVisible(true);
Poppler::Link *l;
l->nextLinks();
}
" HAVE_POPPLER_0_64)

View file

@ -15,7 +15,7 @@
#include <config-okular-poppler.h>
extern Okular::Action* createLinkFromPopplerLink(const Poppler::Link *popplerLink);
extern Okular::Action* createLinkFromPopplerLink(const Poppler::Link *popplerLink, bool deletePopplerLink = true);
#ifdef HAVE_POPPLER_0_53
#define SET_ACTIONS \

View file

@ -311,7 +311,7 @@ QPair<Okular::Movie*, Okular::EmbeddedFile*> createMovieFromPopplerRichMedia( co
/**
* Note: the function will take ownership of the popplerLink object.
*/
Okular::Action* createLinkFromPopplerLink(const Poppler::Link *popplerLink)
Okular::Action* createLinkFromPopplerLink(const Poppler::Link *popplerLink, bool deletePopplerLink = true)
{
if (!popplerLink)
return nullptr;
@ -327,8 +327,6 @@ Okular::Action* createLinkFromPopplerLink(const Poppler::Link *popplerLink)
const Poppler::LinkRendition *popplerLinkRendition;
Okular::DocumentViewport viewport;
bool deletePopplerLink = true;
switch(popplerLink->linkType())
{
case Poppler::Link::None:
@ -384,6 +382,17 @@ Okular::Action* createLinkFromPopplerLink(const Poppler::Link *popplerLink)
case Poppler::Link::Rendition:
{
if (!deletePopplerLink)
{
// If links should not be deleted it probably means that they
// are part of a nextActions chain. There is no support
// to resolveMediaLinkReferences on nextActions. It would also
// be neccessary to ensure that resolveMediaLinkReferences does
// not delete the Links which are part of a nextActions list
// to avoid a double deletion.
qCDebug(OkularPdfDebug) << "parsing rendition link without deletion is not supported. Action chain might be broken.";
break;
}
deletePopplerLink = false; // we'll delete it inside resolveMediaLinkReferences() after we have resolved all references
popplerLinkRendition = static_cast<const Poppler::LinkRendition *>( popplerLink );
@ -420,6 +429,12 @@ Okular::Action* createLinkFromPopplerLink(const Poppler::Link *popplerLink)
case Poppler::Link::Movie:
{
if (!deletePopplerLink)
{
// See comment above in Link::Rendition
qCDebug(OkularPdfDebug) << "parsing movie link without deletion is not supported. Action chain might be broken.";
break;
}
deletePopplerLink = false; // we'll delete it inside resolveMediaLinkReferences() after we have resolved all references
popplerLinkMovie = static_cast<const Poppler::LinkMovie *>( popplerLink );
@ -462,6 +477,18 @@ Okular::Action* createLinkFromPopplerLink(const Poppler::Link *popplerLink)
#endif
}
#ifdef HAVE_POPPLER_0_64
if (link)
{
QVector< Okular::Action * > nextActions;
for ( const Poppler::Link *nl : popplerLink->nextLinks() )
{
nextActions << createLinkFromPopplerLink( nl, false );
}
link->setNextActions( nextActions );
}
#endif
if ( deletePopplerLink )
delete popplerLink;