Commit ad858267 authored by Joao Oliveira's avatar Joao Oliveira Committed by Albert Astals Cid

Implemented display support and updated dependencies to Poppler > 0.79

Moved executeScript to document private and support to display options for JavaScript
parent 552e4a39
......@@ -15,6 +15,7 @@
#include <QMimeDatabase>
#include <QThread>
#include "../settings_core.h"
#include "core/action.h"
#include "core/document.h"
#include "core/scripter.h"
#include <core/script/event_p.h>
......@@ -28,21 +29,22 @@ class KJSFunctionsTest: public QObject
Q_OBJECT
private slots:
#ifdef HAVE_POPPLER_0_79
void initTestCase();
void testNumFields();
void testNthFieldName();
void testDisplay();
void testSetClearInterval();
void testSetClearTimeOut();
void testGetOCGs();
void testOCGSetState();
void cleanupTestCase();
#endif
private:
Okular::Document *m_document;
QMap<QString, Okular::FormField*> m_fields;
};
#ifdef HAVE_POPPLER_0_79
void KJSFunctionsTest::initTestCase()
{
Okular::SettingsCore::instance( QStringLiteral("kjsfunctionstest") );
......@@ -60,42 +62,60 @@ void KJSFunctionsTest::initTestCase()
}
}
void KJSFunctionsTest::testNumFields()
{
QString result = m_document->executeScript( "Doc.numFields" );
QCOMPARE( "31", result );
}
void KJSFunctionsTest::testNthFieldName()
{
for(int i = 0;i < 21;++i)
{
QString result = m_document->executeScript( QString( "Doc.getNthFieldName(%1)" ).arg( i ) );
QCOMPARE( result, QString( "0.%1" ).arg(i) );
Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript, QStringLiteral( "var field = Doc.getField( Doc.getNthFieldName(%1) );\
field.display = display.visible;" ).arg( i ) );
m_document->processAction( action );
QCOMPARE( true, m_fields[QString( "0.%1" ).arg(i)]->isVisible() );
m_fields[QString( "0.%1" ).arg(i)]->setVisible( false );
delete action;
}
}
void KJSFunctionsTest::testDisplay()
{
m_document->executeScript( "field = Doc.getField(\"0.0\");field.display=display.hidden;\
field = Doc.getField(\"0.10\");field.display=display.visible;" );
Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "field = Doc.getField(\"0.0\");field.display=display.hidden;\
field = Doc.getField(\"0.10\");field.display=display.visible;" ) );
m_document->processAction( action );
QCOMPARE( false, m_fields["0.0"]->isVisible() );
QCOMPARE( false, m_fields["0.0"]->isPrintable() );
QCOMPARE( true, m_fields["0.10"]->isVisible() );
QCOMPARE( true, m_fields["0.10"]->isPrintable() );
delete action;
m_document->executeScript( "field = Doc.getField(\"0.10\");field.display=display.hidden;\
field = Doc.getField(\"0.15\");field.display=display.visible;" );
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "field = Doc.getField(\"0.10\");field.display=display.noView;\
field = Doc.getField(\"0.15\");field.display=display.noPrint;" ) );
m_document->processAction( action );
QCOMPARE( false, m_fields["0.10"]->isVisible() );
QCOMPARE( true, m_fields["0.10"]->isPrintable() );
QCOMPARE( true, m_fields["0.15"]->isVisible() );
QCOMPARE( false, m_fields["0.15"]->isPrintable() );
delete action;
m_document->executeScript( "field = Doc.getField(\"0.15\");field.display=display.hidden;\
field = Doc.getField(\"0.20\");field.display=display.visible;" );
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "field = Doc.getField(\"0.15\");field.display=display.hidden;\
field = Doc.getField(\"0.20\");field.display=display.visible;" ) );
m_document->processAction( action );
QCOMPARE( false, m_fields["0.15"]->isVisible() );
QCOMPARE( false, m_fields["0.15"]->isPrintable() );
QCOMPARE( true, m_fields["0.20"]->isVisible() );
QCOMPARE( true, m_fields["0.20"]->isPrintable() );
delete action;
m_document->executeScript( "field = Doc.getField(\"0.20\");field.display=display.hidden;\
field = Doc.getField(\"0.0\");field.display=display.visible;" );
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "field = Doc.getField(\"0.20\");field.display=display.hidden;\
field = Doc.getField(\"0.0\");field.display=display.visible;" ) );
m_document->processAction( action );
QCOMPARE( false, m_fields["0.20"]->isVisible() );
QCOMPARE( false, m_fields["0.20"]->isPrintable() );
QCOMPARE( true, m_fields["0.0"]->isVisible() );
QCOMPARE( true, m_fields["0.0"]->isPrintable() );
delete action;
}
void delay()
......@@ -107,96 +127,106 @@ void delay()
void KJSFunctionsTest::testSetClearInterval()
{
QString result = m_document->executeScript( "obj = new Object();obj.idx=0;\
obj.inc=function(){obj.idx = obj.idx + 1;};\
intv = app.setInterval('obj.inc()', 450);obj.idx;" );
QCOMPARE( "0", result );
Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "obj = new Object();obj.idx=0;\
obj.inc=function(){field = Doc.getField(Doc.getNthFieldName(obj.idx));\
field.display = display.visible;\
obj.idx = obj.idx + 1;};\
intv = app.setInterval('obj.inc()', 450);obj.idx;" ) );
m_document->processAction( action );
QCOMPARE( m_fields["0.0"]->isVisible() , true );
QCOMPARE( m_fields["0.3"]->isVisible() , false );
delete action;
delay();
result = m_document->executeScript( "app.clearInterval(intv);obj.idx;");
QCOMPARE( "4", result );
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "app.clearInterval(intv);obj.idx;" ) );
m_document->processAction( action );
QCOMPARE( m_fields["0.3"]->isVisible() , true );
delete action;
}
void KJSFunctionsTest::testSetClearTimeOut()
{
QString result = m_document->executeScript( "intv = app.setTimeOut('obj.inc()', 1);obj.idx;" );
QCOMPARE( "4", result );
Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "intv = app.setTimeOut('obj.inc()', 1);obj.idx;" ) );
m_document->processAction( action );
QCOMPARE( m_fields["0.3"]->isVisible() , true);
QCOMPARE( m_fields["0.4"]->isVisible() , false );
delay();
delete action;
result = m_document->executeScript( "obj.idx;" );
QCOMPARE( "5", result );
QCOMPARE( m_fields["0.4"]->isVisible() , true );
result = m_document->executeScript( "intv = app.setTimeOut('obj.inc()', 2000);obj.idx;" );
QCOMPARE( "5", result );
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "intv = app.setTimeOut('obj.inc()', 2000);obj.idx;" ) );
m_document->processAction( action );
QCOMPARE( m_fields["0.4"]->isVisible() , true );
delete action;
result = m_document->executeScript( "app.clearTimeOut(intv);obj.idx;" );
QCOMPARE( "5", result );
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "app.clearTimeOut(intv);obj.idx;" ) );
m_document->processAction( action );
QCOMPARE( m_fields["0.4"]->isVisible() , true );
delay();
QCOMPARE( "5", result );
QCOMPARE( m_fields["0.4"]->isVisible() , true );
delete action;
}
void KJSFunctionsTest::testGetOCGs()
{
QAbstractItemModel *model = m_document->layersModel();
QString result = m_document->executeScript( "var ocg = this.getOCGs(this.pageNum);\
ocgName = ocg[0].name;" );
QCOMPARE( model->data( model->index( 0, 0 ), Qt::DisplayRole ).toString() , result );
result = m_document->executeScript( "ocgName = ocg[1].name;" );
QCOMPARE( model->data( model->index( 1, 0 ), Qt::DisplayRole ).toString() , result );
Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "var ocg = this.getOCGs(this.pageNum);\
ocg[0].state = false;" ) );
m_document->processAction( action );
QCOMPARE( model->data( model->index( 0, 0 ), Qt::CheckStateRole ).toBool() , false );
delete action;
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "ocg[0].state = true;" ) );
m_document->processAction( action );
QCOMPARE( model->data( model->index( 0, 0 ), Qt::CheckStateRole ).toBool() , true );
delete action;
result = m_document->executeScript( "ocgName = ocg[2].name;" );
QCOMPARE( model->data( model->index( 2, 0 ), Qt::DisplayRole ).toString() , result );
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "ocg[1].state = false;" ) );
m_document->processAction( action );
QCOMPARE( model->data( model->index( 1, 0 ), Qt::CheckStateRole ).toBool() , false );
delete action;
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "ocg[1].state = true;" ) );
m_document->processAction( action );
QCOMPARE( model->data( model->index( 1, 0 ), Qt::CheckStateRole ).toBool() , true );
delete action;
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "ocg[2].state = false;" ) );
m_document->processAction( action );
QCOMPARE( model->data( model->index( 2, 0 ), Qt::CheckStateRole ).toBool() , false );
delete action;
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "ocg[2].state = true;" ) );
m_document->processAction( action );
QCOMPARE( model->data( model->index( 2, 0 ), Qt::CheckStateRole ).toBool() , true );
delete action;
result = m_document->executeScript( "ocgName = ocg[3].name;" );
QCOMPARE( model->data( model->index( 3, 0 ), Qt::DisplayRole ).toString() , result );
result = m_document->executeScript( "ocgName = ocg[0].initState;" );
QCOMPARE( model->data( model->index( 0, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false"
, result );
result = m_document->executeScript( "ocgName = ocg[1].initState;" );
QCOMPARE( model->data( model->index( 1, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false"
, result );
result = m_document->executeScript( "ocgName = ocg[2].initState;" );
QCOMPARE( model->data( model->index( 2, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false"
, result );
result = m_document->executeScript( "ocgName = ocg[3].initState;" );
QCOMPARE( model->data( model->index( 3, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false"
, result );
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "ocg[3].state = false;" ) );
m_document->processAction( action );
QCOMPARE( model->data( model->index( 3, 0 ), Qt::CheckStateRole ).toBool() , false );
delete action;
action = new Okular::ScriptAction( Okular::JavaScript,
QStringLiteral( "ocg[3].state = true;" ) );
m_document->processAction( action );
QCOMPARE( model->data( model->index( 3, 0 ), Qt::CheckStateRole ).toBool() , true );
delete action;
}
void KJSFunctionsTest::testOCGSetState()
{
QAbstractItemModel *model = m_document->layersModel();
QString result = m_document->executeScript( "ocgName = ocg[0].state;" );
QCOMPARE( model->data( model->index( 0, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false", result );
result = m_document->executeScript( "ocg[0].state = false;ocgName = ocg[0].state;");
QCOMPARE( model->data( model->index( 0, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false", result );
result = m_document->executeScript( "ocgName = ocg[1].state;" );
QCOMPARE( model->data( model->index( 1, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false", result );
result = m_document->executeScript( "ocg[1].state = false;ocgName = ocg[1].state;");
QCOMPARE( model->data( model->index( 1, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false", result );
result = m_document->executeScript( "ocgName = ocg[2].state;" );
QCOMPARE( model->data( model->index( 2, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false", result );
result = m_document->executeScript( "ocg[2].state = true;ocgName = ocg[2].state;");
QCOMPARE( model->data( model->index( 2, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false", result );
result = m_document->executeScript( "ocgName = ocg[3].state;" );
QCOMPARE( model->data( model->index( 3, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false", result );
result = m_document->executeScript( "ocg[3].state = true;ocgName = ocg[3].state;");
QCOMPARE( model->data( model->index( 3, 0 ), Qt::CheckStateRole ).toBool() ? "true" : "false", result );
}
void KJSFunctionsTest::cleanupTestCase()
{
......@@ -204,6 +234,7 @@ void KJSFunctionsTest::cleanupTestCase()
delete m_document;
}
#endif
QTEST_MAIN( KJSFunctionsTest )
#include "kjsfunctionstest.moc"
......@@ -5115,11 +5115,11 @@ QByteArray Document::requestSignedRevisionData( const Okular::SignatureInfo &inf
return data;
}
QString Document::executeScript( QString function )
void DocumentPrivate::executeScript( const QString &function )
{
if( !d->m_scripter )
d->m_scripter = new Scripter( d );
return d->m_scripter->execute( JavaScript, function );
if( !m_scripter )
m_scripter = new Scripter( this );
m_scripter->execute( JavaScript, function );
}
void DocumentPrivate::requestDone( PixmapRequest * req )
......
......@@ -1038,13 +1038,6 @@ class OKULARCORE_EXPORT Document : public QObject
*/
QByteArray requestSignedRevisionData( const Okular::SignatureInfo &info );
/**
* Executes a JavaScript script from the setInterval function.
*
* @since 1.7
*/
QString executeScript( QString function );
Q_SIGNALS:
/**
* This signal is emitted whenever the document is about to close.
......
......@@ -191,6 +191,13 @@ class DocumentPrivate
void doProcessSearchMatch( RegularAreaRect *match, RunningSearch *search, QSet< int > *pagesToNotify, int currentPage, int searchID, bool moveViewport, const QColor & color );
/**
* Executes a JavaScript script from the setInterval function.
*
* @since 1.7
*/
void executeScript( const QString &function );
// generators stuff
/**
* This method is used by the generators to signal the finish of
......
......@@ -70,6 +70,15 @@ void FormField::setVisible( bool )
{
}
bool FormField::isPrintable() const
{
return true;
}
void FormField::setPrintable( bool )
{
}
Action* FormField::activationAction() const
{
Q_D( const FormField );
......
......@@ -57,6 +57,17 @@ class OKULARCORE_EXPORT FormField
FormSignature ///< A signature.
};
/**
* The display types of the field.
*/
enum FieldDisplay
{
FormVisible,
FormHidden,
FormNoPrint,
FormNoView
};
virtual ~FormField();
/**
......@@ -110,6 +121,20 @@ class OKULARCORE_EXPORT FormField
*/
virtual void setVisible( bool value );
/**
Whether this field is printable.
@since 1.7
*/
virtual bool isPrintable() const;
/**
Set this field printable
@since 1.7
*/
virtual void setPrintable( bool value );
Action* activationAction() const;
/**
......
......@@ -116,8 +116,6 @@ void ExecutorKJS::execute( const QString &script, Event *event )
KJSResult result = d->m_interpreter->evaluate( QStringLiteral("okular.js"), 1,
script, &d->m_docObject );
resultValue = new QString( result.value().toString( ctx ) );
if ( result.isException() || ctx->hasException() )
{
qCDebug(OkularCoreDebug) << "JS exception" << result.errorMessage();
......@@ -133,8 +131,3 @@ void ExecutorKJS::execute( const QString &script, Event *event )
}
}
}
QString ExecutorKJS::getResult()
{
return *resultValue;
}
......@@ -28,12 +28,10 @@ class ExecutorKJS
ExecutorKJS &operator=(const ExecutorKJS &) = delete;
void execute( const QString &script, Event *event );
QString getResult();
private:
friend class ExecutorKJSPrivate;
ExecutorKJSPrivate* d;
QString* resultValue;
};
}
......
......@@ -207,12 +207,12 @@ static KJSObject appSetInterval( KJSContext *ctx, void *object,
const KJSArguments &arguments )
{
DocumentPrivate *doc = reinterpret_cast< DocumentPrivate * >( object );
QString function = arguments.at( 0 ).toString( ctx ) + ';';
int interval = arguments.at( 1 ).toInt32( ctx );
const QString function = arguments.at( 0 ).toString( ctx ) + ';';
const int interval = arguments.at( 1 ).toInt32( ctx );
QTimer *timer = new QTimer();
QObject::connect( timer, &QTimer::timeout, [=](){ doc->m_parent->executeScript( function ); } );
QObject::connect( timer, &QTimer::timeout, [=](){ doc->executeScript( function ); } );
timer->start( interval );
......@@ -224,7 +224,7 @@ static KJSObject appClearInterval( KJSContext *ctx, void *object,
const KJSArguments &arguments )
{
KJSObject timerObject = arguments.at( 0 );
int timerId = timerObject.property( ctx, QStringLiteral( "timerID" ).toLatin1().toBase64() ).toInt32( ctx );
const int timerId = timerObject.property( ctx, QStringLiteral( "timerID" ).toLatin1().toBase64() ).toInt32( ctx );
QTimer *timer = g_timerCache->value( timerId );
if( timer != nullptr )
{
......@@ -241,13 +241,13 @@ static KJSObject appSetTimeOut( KJSContext *ctx, void *object,
const KJSArguments &arguments )
{
DocumentPrivate *doc = reinterpret_cast< DocumentPrivate * >( object );
QString function = arguments.at( 0 ).toString( ctx ) + ';';
int interval = arguments.at( 1 ).toInt32( ctx );
const QString function = arguments.at( 0 ).toString( ctx ) + ';';
const int interval = arguments.at( 1 ).toInt32( ctx );
QTimer *timer = new QTimer();
timer->setSingleShot( true );
QObject::connect( timer, &QTimer::timeout, [=](){ doc->m_parent->executeScript( function ); } );
QObject::connect( timer, &QTimer::timeout, [=](){ doc->executeScript( function ); } );
timer->start( interval );
......@@ -259,7 +259,7 @@ static KJSObject appClearTimeOut( KJSContext *ctx, void *object,
const KJSArguments &arguments )
{
KJSObject timerObject = arguments.at( 0 );
int timerId = timerObject.property( ctx, QStringLiteral( "timerID" ).toLatin1().toBase64() ).toInt32( ctx );
const int timerId = timerObject.property( ctx, QStringLiteral( "timerID" ).toLatin1().toBase64() ).toInt32( ctx );
QTimer *timer = g_timerCache->value( timerId );
if( timer != nullptr )
......@@ -322,15 +322,7 @@ void JSApp::clearCachedFields()
{
if ( g_timerCache )
{
for( auto it = g_timerCache->begin(); it != g_timerCache->end(); ++it )
{
QTimer *timer = it.value();
if(timer == nullptr)
continue;
delete timer;
}
qDeleteAll( g_timerCache->begin(), g_timerCache->end() );
g_timerCache->clear();
}
}
......@@ -8,6 +8,7 @@
***************************************************************************/
#include "kjs_display_p.h"
#include "../form.h"
#include <kjs/kjsobject.h>
#include <kjs/kjsprototype.h>
......@@ -23,13 +24,25 @@ std::unique_ptr < KJSPrototype > g_displayProto;
// display.hidden
static KJSObject displayGetHidden( KJSContext *, void * )
{
return KJSBoolean( false );
return KJSNumber( FormField::FormHidden );
}
// display.visible
static KJSObject displayGetVisible( KJSContext *, void * )
{
return KJSBoolean( true );
return KJSNumber( FormField::FormVisible );
}
// display.noView
static KJSObject displayGetNoView( KJSContext *, void * )
{
return KJSNumber( FormField::FormNoView );
}
// display.noPrint
static KJSObject displayGetNoPrint( KJSContext *, void * )
{
return KJSNumber( FormField::FormNoPrint );
}
void JSDisplay::initType( KJSContext *ctx )
......@@ -41,6 +54,8 @@ void JSDisplay::initType( KJSContext *ctx )
g_displayProto->defineProperty( ctx, QStringLiteral("hidden"), displayGetHidden );
g_displayProto->defineProperty( ctx, QStringLiteral("visible"), displayGetVisible );
g_displayProto->defineProperty( ctx, QStringLiteral("noView"), displayGetNoView );
g_displayProto->defineProperty( ctx, QStringLiteral("noPrint"), displayGetNoPrint );
}
KJSObject JSDisplay::object( KJSContext *ctx )
......
......@@ -133,7 +133,7 @@ static KJSObject docGetExternal( KJSContext *, void *object )
// Document.numFields
static KJSObject docGetNumFields( KJSContext *, void *object )
{
DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object );
const DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object );
unsigned int numFields = 0;
......@@ -268,7 +268,7 @@ static KJSObject docSyncAnnotScan( KJSContext *, void *,
static KJSObject docGetNthFieldName( KJSContext *ctx, void *object,
const KJSArguments &arguments )
{
DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object );
const DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object );
int numField = arguments.at( 0 ).toInt32( ctx );
......@@ -278,8 +278,7 @@ static KJSObject docGetNthFieldName( KJSContext *ctx, void *object,
if(numField < pageFields.size())
{
auto ffIt = pageFields.begin();
ffIt += numField;
const auto ffIt = pageFields.begin() + numField;
return KJSString( (*ffIt)->name() );
}
......@@ -293,7 +292,7 @@ static KJSObject docGetNthFieldName( KJSContext *ctx, void *object,
static KJSObject docGetOCGs( KJSContext *ctx, void *object,
const KJSArguments &arguments )
{
DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object );
const DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object );
QAbstractItemModel * model = doc->m_parent->layersModel();
......@@ -301,7 +300,7 @@ static KJSObject docGetOCGs( KJSContext *ctx, void *object,
for(int i = 0;i < model->rowCount();++i){
for(int j = 0;j < model->columnCount();++j){
QModelIndex index = model->index( i, j );
const QModelIndex index = model->index( i, j );
KJSObject item = JSOCG::wrapOCGObject( ctx, model, i, j );
item.setProperty( ctx, QStringLiteral("name"), model->data( index , Qt::DisplayRole ).toString() );
......
......@@ -231,16 +231,38 @@ static void fieldSetHidden( KJSContext *context, void *object, KJSObject value )
static KJSObject fieldGetDisplay( KJSContext *, void *object )
{
const FormField *field = reinterpret_cast< FormField * >( object );
return KJSBoolean( field->isVisible() );
bool visible = field->isVisible();
if( visible )
{
return KJSNumber( field->isPrintable() ? FormField::FormVisible : FormField::FormNoPrint );
}
return KJSNumber( field->isPrintable() ? FormField::FormNoView : FormField::FormHidden );
}
// Field.display (setter)
static void fieldSetDisplay( KJSContext *context, void *object, KJSObject value )
{