diff --git a/CMakeLists.txt b/CMakeLists.txt index ca85d2a52..fe1724343 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,14 @@ set(okularcore_SRCS core/utils.cpp core/view.cpp core/fileprinter.cpp + core/script/executor_kjs.cpp + core/script/kjs_console.cpp + core/script/kjs_data.cpp + core/script/kjs_document.cpp + core/script/kjs_fullscreen.cpp + core/script/kjs_field.cpp + core/script/kjs_spell.cpp + core/script/kjs_util.cpp ) install( FILES @@ -90,7 +98,7 @@ IF(APPLE) SET(OKULAR_IOKIT "-framework IOKit" CACHE STRING "Apple IOKit framework") ENDIF(APPLE) -target_link_libraries(okularcore ${OKULAR_IOKIT} ${KDE4_KIO_LIBS} ${KDE4_PHONON_LIBRARY} ${MATH_LIB} ${KDE4_THREADWEAVER_LIBRARY} ) +target_link_libraries(okularcore ${OKULAR_IOKIT} ${KDE4_KIO_LIBS} ${KDE4_PHONON_LIBRARY} ${KDE4_KJSAPI_LIBRARY} ${MATH_LIB} ${KDE4_THREADWEAVER_LIBRARY} ) set_target_properties(okularcore PROPERTIES VERSION 1.1.0 SOVERSION 1 ) diff --git a/core/script/executor_kjs.cpp b/core/script/executor_kjs.cpp new file mode 100644 index 000000000..61b2e63c6 --- /dev/null +++ b/core/script/executor_kjs.cpp @@ -0,0 +1,110 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "executor_kjs_p.h" + +#include +#include +#include +#include + +#include + +#include "../debug_p.h" +#include "../document_p.h" + +#include "kjs_console_p.h" +#include "kjs_data_p.h" +#include "kjs_document_p.h" +#include "kjs_field_p.h" +#include "kjs_fullscreen_p.h" +#include "kjs_spell_p.h" +#include "kjs_util_p.h" + +using namespace Okular; + +class Okular::ExecutorKJSPrivate +{ + public: + ExecutorKJSPrivate( DocumentPrivate *doc ) + : m_doc( doc ) + { + initTypes(); + } + ~ExecutorKJSPrivate() + { + JSField::clearCachedFields(); + + delete m_interpreter; + } + + void initTypes(); + + DocumentPrivate *m_doc; + KJSInterpreter *m_interpreter; + KJSObject m_docObject; +}; + +void ExecutorKJSPrivate::initTypes() +{ + m_docObject = JSDocument::wrapDocument( m_doc ); + m_interpreter = new KJSInterpreter( m_docObject ); + + KJSContext *ctx = m_interpreter->globalContext(); + + JSFullscreen::initType( ctx ); + JSConsole::initType( ctx ); + JSData::initType( ctx ); + JSDocument::initType( ctx ); + JSField::initType( ctx ); + JSSpell::initType( ctx ); + JSUtil::initType( ctx ); + + m_docObject.setProperty( ctx, "console", JSConsole::object( ctx ) ); + m_docObject.setProperty( ctx, "Doc", m_docObject ); + m_docObject.setProperty( ctx, "spell", JSSpell::object( ctx ) ); + m_docObject.setProperty( ctx, "util", JSUtil::object( ctx ) ); +} + +ExecutorKJS::ExecutorKJS( DocumentPrivate *doc ) + : d( new ExecutorKJSPrivate( doc ) ) +{ +} + +ExecutorKJS::~ExecutorKJS() +{ + delete d; +} + +void ExecutorKJS::execute( const QString &script ) +{ +#if 0 + QString script2; + QString errMsg; + int errLine; + if ( !KJSInterpreter::normalizeCode( script, &script2, &errLine, &errMsg ) ) + { + kWarning(OkularDebug) << "Parse error during normalization!"; + script2 = script; + } +#endif + + KJSResult result = d->m_interpreter->evaluate( "okular.js", 1, + script, &d->m_docObject ); + KJSContext* ctx = d->m_interpreter->globalContext(); + if ( result.isException() || ctx->hasException() ) + { + kDebug(OkularDebug) << "JS exception" << result.errorMessage(); + } + else + { + kDebug(OkularDebug) << "result:" << result.value().toString( ctx ); + } +} diff --git a/core/script/executor_kjs_p.h b/core/script/executor_kjs_p.h new file mode 100644 index 000000000..12a6304db --- /dev/null +++ b/core/script/executor_kjs_p.h @@ -0,0 +1,35 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef OKULAR_SCRIPT_EXECUTOR_KJS_P_H +#define OKULAR_SCRIPT_EXECUTOR_KJS_P_H + +class QString; + +namespace Okular { + +class DocumentPrivate; +class ExecutorKJSPrivate; + +class ExecutorKJS +{ + public: + ExecutorKJS( DocumentPrivate *doc ); + ~ExecutorKJS(); + + void execute( const QString &script ); + + private: + friend class ExecutorKJSPrivate; + ExecutorKJSPrivate* d; +}; + +} + +#endif diff --git a/core/script/kjs_console.cpp b/core/script/kjs_console.cpp new file mode 100644 index 000000000..e8bb3a3fc --- /dev/null +++ b/core/script/kjs_console.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "kjs_console_p.h" + +#include +#include +#include + +#include + +#include "../debug_p.h" + +using namespace Okular; + +static KJSPrototype *g_consoleProto; + +static KJSObject consoleClear( KJSContext *, void *, const KJSArguments & ) +{ + return KJSUndefined(); +} + +static KJSObject consoleHide( KJSContext *, void *, const KJSArguments & ) +{ + return KJSUndefined(); +} + +static KJSObject consolePrintln( KJSContext *ctx, void *, + const KJSArguments &arguments ) +{ + QString cMessage = arguments.at( 0 ).toString( ctx ); + kDebug(OkularDebug) << "CONSOLE:" << cMessage; + + return KJSUndefined(); +} + +static KJSObject consoleShow( KJSContext *, void *, const KJSArguments & ) +{ + return KJSUndefined(); +} + +void JSConsole::initType( KJSContext *ctx ) +{ + static bool initialized = false; + if ( initialized ) + return; + initialized = true; + + g_consoleProto = new KJSPrototype(); + + g_consoleProto->defineFunction( ctx, "clear", consoleClear ); + g_consoleProto->defineFunction( ctx, "hide", consoleHide ); + g_consoleProto->defineFunction( ctx, "println", consolePrintln ); + g_consoleProto->defineFunction( ctx, "hide", consoleShow ); +} + +KJSObject JSConsole::object( KJSContext *ctx ) +{ + return g_consoleProto->constructObject( ctx, 0 ); +} diff --git a/core/script/kjs_console_p.h b/core/script/kjs_console_p.h new file mode 100644 index 000000000..0b9096b7d --- /dev/null +++ b/core/script/kjs_console_p.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef OKULAR_SCRIPT_KJS_CONSOLE_P_H +#define OKULAR_SCRIPT_KJS_CONSOLE_P_H + +class KJSContext; +class KJSObject; + +namespace Okular { + +class JSConsole +{ + public: + static void initType( KJSContext *ctx ); + static KJSObject object( KJSContext *ctx ); +}; + +} + +#endif diff --git a/core/script/kjs_data.cpp b/core/script/kjs_data.cpp new file mode 100644 index 000000000..5c76d94e6 --- /dev/null +++ b/core/script/kjs_data.cpp @@ -0,0 +1,90 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "kjs_data_p.h" + +#include +#include + +#include + +#include "../document.h" + +using namespace Okular; + +static KJSPrototype *g_dataProto; + +static KJSObject dataGetCreationDate( KJSContext *ctx, void *object ) +{ + const EmbeddedFile *file = reinterpret_cast< EmbeddedFile * >( object ); + + return KJSDate( ctx, file->creationDate() ); +} + +static KJSObject dataGetDescription( KJSContext *, void *object ) +{ + const EmbeddedFile *file = reinterpret_cast< EmbeddedFile * >( object ); + + return KJSString( file->description() ); +} + +static KJSObject dataGetMIMEType( KJSContext *, void *object ) +{ + return KJSString( "" ); +} + +static KJSObject dataGetModDate( KJSContext *ctx, void *object ) +{ + const EmbeddedFile *file = reinterpret_cast< EmbeddedFile * >( object ); + + return KJSDate( ctx, file->modificationDate() ); +} + +static KJSObject dataGetName( KJSContext *, void *object ) +{ + const EmbeddedFile *file = reinterpret_cast< EmbeddedFile * >( object ); + + return KJSString( file->name() ); +} + +static KJSObject dataGetPath( KJSContext *, void *object ) +{ + return KJSString( "" ); +} + +static KJSObject dataGetSize( KJSContext *, void *object ) +{ + const EmbeddedFile *file = reinterpret_cast< EmbeddedFile * >( object ); + return KJSNumber( file->size() ); +} + +void JSData::initType( KJSContext *ctx ) +{ + static bool initialized = false; + if ( initialized ) + return; + initialized = true; + + if ( !g_dataProto ) + g_dataProto = new KJSPrototype(); + + g_dataProto->defineProperty( ctx, "creationDate", dataGetCreationDate ); + g_dataProto->defineProperty( ctx, "description", dataGetDescription ); + g_dataProto->defineProperty( ctx, "MIMEType", dataGetMIMEType ); + g_dataProto->defineProperty( ctx, "modDate", dataGetModDate ); + g_dataProto->defineProperty( ctx, "name", dataGetName ); + g_dataProto->defineProperty( ctx, "path", dataGetPath ); + g_dataProto->defineProperty( ctx, "size", dataGetSize ); +} + +KJSObject JSData::wrapFile( KJSContext *ctx, EmbeddedFile *f ) +{ + return g_dataProto->constructObject( ctx, f ); +} diff --git a/core/script/kjs_data_p.h b/core/script/kjs_data_p.h new file mode 100644 index 000000000..e8652343e --- /dev/null +++ b/core/script/kjs_data_p.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef OKULAR_SCRIPT_KJS_DATA_P_H +#define OKULAR_SCRIPT_KJS_DATA_P_H + +class KJSContext; +class KJSObject; + +namespace Okular { + +class EmbeddedFile; + +class JSData +{ + public: + static void initType( KJSContext *ctx ); + static KJSObject wrapFile( KJSContext *ctx, EmbeddedFile *f ); +}; + +} + +#endif diff --git a/core/script/kjs_document.cpp b/core/script/kjs_document.cpp new file mode 100644 index 000000000..077117a38 --- /dev/null +++ b/core/script/kjs_document.cpp @@ -0,0 +1,287 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "kjs_document_p.h" + +#include + +#include +#include +#include + +#include +#include + +#include "../document_p.h" +#include "../page.h" +#include "../form.h" +#include "kjs_data_p.h" +#include "kjs_field_p.h" + +using namespace Okular; + +static KJSPrototype *g_docProto; + +// Document.numPages +static KJSObject docGetNumPages( KJSContext *, void *object ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + return KJSNumber( doc->m_pagesVector.count() ); +} + +// Document.pageNum (getter) +static KJSObject docGetPageNum( KJSContext *, void *object ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + return KJSNumber( doc->m_parent->currentPage() ); +} + +// Document.pageNum (setter) +static void docSetPageNum( KJSContext* ctx, void* object, + KJSObject value ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + int page = value.toInt32( ctx ); + + if ( page == (int)doc->m_parent->currentPage() ) + return; + + doc->m_parent->setViewportPage( page ); +} + +// Document.documentFileName +static KJSObject docGetDocumentFileName( KJSContext *, void *object ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + return KJSString( doc->m_url.fileName() ); +} + +// Document.filesize +static KJSObject docGetFilesize( KJSContext *, void *object ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + return KJSNumber( doc->m_docSize ); +} + +// Document.path +static KJSObject docGetPath( KJSContext *, void *object ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + return KJSString( doc->m_url.pathOrUrl() ); +} + +// Document.URL +static KJSObject docGetURL( KJSContext *, void *object ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + return KJSString( doc->m_url.prettyUrl() ); +} + +// Document.permStatusReady +static KJSObject docGetPermStatusReady( KJSContext *, void * ) +{ + return KJSBoolean( true ); +} + +// Document.dataObjects +static KJSObject docGetDataObjects( KJSContext *ctx, void *object ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + const QList< EmbeddedFile * > *files = doc->m_generator->embeddedFiles(); + + KJSArray dataObjects( ctx, files ? files->count() : 0 ); + if ( files ) + { + QList< EmbeddedFile * >::ConstIterator it = files->begin(), itEnd = files->end(); + for ( int i = 0; it != itEnd; ++it, ++i ) + { + KJSObject newdata = JSData::wrapFile( ctx, *it ); + dataObjects.setProperty( ctx, QString::number( i ), newdata ); + } + } + return dataObjects; +} + +// Document.external +static KJSObject docGetExternal( KJSContext *, void *object ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + QWidget *widget = doc->m_parent->widget(); + + const bool isShell = ( widget + && widget->parentWidget() + && widget->parentWidget()->objectName() == QLatin1String( "okular::Shell" ) ); + return KJSBoolean( !isShell ); +} + + +static KJSObject docGetInfo( KJSContext *ctx, void *object ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + KJSObject obj; + const DocumentInfo *docinfo = doc->m_generator->generateDocumentInfo(); + if ( docinfo ) + { +#define KEY_GET( key, property ) \ +do { \ + const QString data = docinfo->get( key ); \ + if ( !data.isEmpty() ) \ + { \ + const KJSString newval( data ); \ + obj.setProperty( ctx, property, newval ); \ + obj.setProperty( ctx, QString( property ).toLower(), newval ); \ + } \ +} while ( 0 ); + KEY_GET( "title", "Title" ); + KEY_GET( "author", "Author" ); + KEY_GET( "subject", "Subject" ); + KEY_GET( "keywords", "Keywords" ); + KEY_GET( "creator", "Creator" ); + KEY_GET( "producer", "Producer" ); +#undef KEY_GET + } + return obj; +} + +#define DOCINFO_GET_METHOD( key, name ) \ +static KJSObject docGet ## name( KJSContext *, void *object ) \ +{ \ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); \ + const DocumentInfo *docinfo = doc->m_generator->generateDocumentInfo(); \ + return KJSString( docinfo->get( key ) ); \ +} + +DOCINFO_GET_METHOD( "author", Author ) +DOCINFO_GET_METHOD( "creator", Creator ) +DOCINFO_GET_METHOD( "keywords", Keywords ) +DOCINFO_GET_METHOD( "producer", Producer ) +DOCINFO_GET_METHOD( "title", Title ) +DOCINFO_GET_METHOD( "subject", Subject ) + +#undef DOCINFO_GET_METHOD + +// Document.getField() +static KJSObject docGetField( KJSContext *context, void *object, + const KJSArguments &arguments ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + QString cName = arguments.at( 0 ).toString( context ); + + QVector< Page * >::const_iterator pIt = doc->m_pagesVector.begin(), pEnd = doc->m_pagesVector.end(); + for ( ; pIt != pEnd; ++pIt ) + { + const QLinkedList< Okular::FormField * > pageFields = (*pIt)->formFields(); + QLinkedList< Okular::FormField * >::const_iterator ffIt = pageFields.begin(), ffEnd = pageFields.end(); + for ( ; ffIt != ffEnd; ++ffIt ) + { + if ( (*ffIt)->name() == cName ) + { + return JSField::wrapField( context, *ffIt, *pIt ); + } + } + } + return KJSUndefined(); +} + +// Document.getPageLabel() +static KJSObject docGetPageLabel( KJSContext *ctx,void *object, + const KJSArguments &arguments ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + int nPage = arguments.at( 0 ).toInt32( ctx ); + Page *p = doc->m_pagesVector.value( nPage ); + return KJSString( p ? p->label() : QString() ); +} + +// Document.getPageRotation() +static KJSObject docGetPageRotation( KJSContext *ctx, void *object, + const KJSArguments &arguments ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + int nPage = arguments.at( 0 ).toInt32( ctx ); + Page *p = doc->m_pagesVector.value( nPage ); + return KJSNumber( p ? p->orientation() * 90 : 0 ); +} + +// Document.gotoNamedDest() +static KJSObject docGotoNamedDest( KJSContext *ctx, void *object, + const KJSArguments &arguments ) +{ + DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); + + QString dest = arguments.at( 0 ).toString( ctx ); + + DocumentViewport viewport( doc->m_generator->metaData( "NamedViewport", dest ).toString() ); + if ( !viewport.isValid() ) + return KJSUndefined(); + + doc->m_parent->setViewport( viewport ); + + return KJSUndefined(); +} + +// Document.syncAnnotScan() +static KJSObject docSyncAnnotScan( KJSContext *, void *, + const KJSArguments & ) +{ + return KJSUndefined(); +} + +void JSDocument::initType( KJSContext *ctx ) +{ + assert( g_docProto ); + + static bool initialized = false; + if ( initialized ) + return; + initialized = true; + + g_docProto->defineProperty( ctx, "numPages", docGetNumPages ); + g_docProto->defineProperty( ctx, "pageNum", docGetPageNum, docSetPageNum ); + g_docProto->defineProperty( ctx, "documentFileName", docGetDocumentFileName ); + g_docProto->defineProperty( ctx, "filesize", docGetFilesize ); + g_docProto->defineProperty( ctx, "path", docGetPath ); + g_docProto->defineProperty( ctx, "URL", docGetURL ); + g_docProto->defineProperty( ctx, "permStatusReady", docGetPermStatusReady ); + g_docProto->defineProperty( ctx, "dataObjects", docGetDataObjects ); + g_docProto->defineProperty( ctx, "external", docGetExternal ); + + // info properties + g_docProto->defineProperty( ctx, "info", docGetInfo ); + g_docProto->defineProperty( ctx, "author", docGetAuthor ); + g_docProto->defineProperty( ctx, "creator", docGetCreator ); + g_docProto->defineProperty( ctx, "keywords", docGetKeywords ); + g_docProto->defineProperty( ctx, "producer", docGetProducer ); + g_docProto->defineProperty( ctx, "title", docGetTitle ); + g_docProto->defineProperty( ctx, "subject", docGetSubject ); + + g_docProto->defineFunction( ctx, "getField", docGetField ); + g_docProto->defineFunction( ctx, "getPageLabel", docGetPageLabel ); + g_docProto->defineFunction( ctx, "getPageRotation", docGetPageRotation ); + g_docProto->defineFunction( ctx, "gotoNamedDest", docGotoNamedDest ); + g_docProto->defineFunction( ctx, "syncAnnotScan", docSyncAnnotScan ); +} + +KJSObject JSDocument::wrapDocument( DocumentPrivate *doc ) +{ + if ( !g_docProto ) + g_docProto = new KJSPrototype(); + return g_docProto->constructObject( 0, doc ); +} diff --git a/core/script/kjs_document_p.h b/core/script/kjs_document_p.h new file mode 100644 index 000000000..05326e9c3 --- /dev/null +++ b/core/script/kjs_document_p.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef OKULAR_SCRIPT_KJS_DOCUMENT_P_H +#define OKULAR_SCRIPT_KJS_DOCUMENT_P_H + +class KJSContext; +class KJSObject; + +namespace Okular { + +class DocumentPrivate; + +class JSDocument +{ + public: + static void initType( KJSContext *ctx ); + static KJSObject wrapDocument( DocumentPrivate *doc ); +}; + +} + +#endif diff --git a/core/script/kjs_field.cpp b/core/script/kjs_field.cpp new file mode 100644 index 000000000..9bdb73b1d --- /dev/null +++ b/core/script/kjs_field.cpp @@ -0,0 +1,230 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "kjs_field_p.h" + +#include +#include +#include + +#include + +#include +#include + +#include "../debug_p.h" +#include "../document_p.h" +#include "../form.h" +#include "../page.h" + +using namespace Okular; + +static KJSPrototype *g_fieldProto; + +typedef QHash< FormField *, KJSObject > FormCache; +K_GLOBAL_STATIC( FormCache, g_fieldCache ) + +// Field.doc +static KJSObject fieldGetDoc( KJSContext *context, void * ) +{ + return context->interpreter().globalObject(); +} + +// Field.name +static KJSObject fieldGetName( KJSContext *, void *object ) +{ + const FormField *field = reinterpret_cast< FormField * >( object ); + return KJSString( field->name() ); +} + +// Field.readonly (getter) +static KJSObject fieldGetReadOnly( KJSContext *, void *object ) +{ + const FormField *field = reinterpret_cast< FormField * >( object ); + return KJSBoolean( field->isReadOnly() ); +} + +// Field.readonly (setter) +static void fieldSetReadOnly( KJSContext *context, void *object, KJSObject value ) +{ +#if 0 + FormField *field = reinterpret_cast< FormField * >( object ); + bool b = value.toBoolean( context ); + field->setReadOnly( b ); +#else + Q_UNUSED( context ); + Q_UNUSED( object ); + Q_UNUSED( value ); + kDebug(OkularDebug) << "Not implemented: setting readonly property"; +#endif +} + +static QString fieldGetTypeHelper( const FormField *field ) +{ + switch ( field->type() ) + { + case FormField::FormButton: + { + const FormFieldButton *button = static_cast< const FormFieldButton * >( field ); + switch ( button->buttonType() ) + { + case FormFieldButton::Push: + return "button"; + case FormFieldButton::CheckBox: + return "checkbox"; + case FormFieldButton::Radio: + return "radiobutton"; + } + break; + } + case FormField::FormText: + return "text"; + case FormField::FormChoice: + { + const FormFieldChoice *choice = static_cast< const FormFieldChoice * >( field ); + switch ( choice->choiceType() ) + { + case FormFieldChoice::ComboBox: + return "combobox"; + case FormFieldChoice::ListBox: + return "listbox"; + } + break; + } + case FormField::FormSignature: + return "signature"; + } + return QString(); +} + +// Field.type +static KJSObject fieldGetType( KJSContext *, void *object ) +{ + const FormField *field = reinterpret_cast< FormField * >( object ); + + return KJSString( fieldGetTypeHelper( field ) ); +} + +// Field.value (getter) +static KJSObject fieldGetValue( KJSContext *context, void *object ) +{ + FormField *field = reinterpret_cast< FormField * >( object ); + if ( field->isReadOnly() ) + { + KJSObject value = g_fieldCache->value( field ); + if ( g_fieldCache.exists() && g_fieldCache->contains( field ) ) + value = g_fieldCache->value( field ); + else + value = KJSString(""); + kDebug(OkularDebug) << "Getting the value of a readonly field" << field->name() << ":" << value.toString( context ); + return value; + } + + switch ( field->type() ) + { + case FormField::FormButton: + { + const FormFieldButton *button = static_cast< const FormFieldButton * >( field ); + Q_UNUSED( button ); // ### + break; + } + case FormField::FormText: + { + const FormFieldText *text = static_cast< const FormFieldText * >( field ); + return KJSString( text->text() ); + } + case FormField::FormChoice: + { + const FormFieldChoice *choice = static_cast< const FormFieldChoice * >( field ); + Q_UNUSED( choice ); // ### + break; + } + case FormField::FormSignature: + { + break; + } + } + + return KJSUndefined(); +} + +// Field.value (setter) +static void fieldSetValue( KJSContext *context, void *object, KJSObject value ) +{ + FormField *field = reinterpret_cast< FormField * >( object ); + + if ( field->isReadOnly() ) + { + // ### throw exception? + kDebug(OkularDebug) << "Trying to change the readonly field" << field->name() << "to" << value.toString( context ); + g_fieldCache->insert( field, value ); + return; + } + + switch ( field->type() ) + { + case FormField::FormButton: + { + FormFieldButton *button = static_cast< FormFieldButton * >( field ); + Q_UNUSED( button ); // ### + break; + } + case FormField::FormText: + { + FormFieldText *text = static_cast< FormFieldText * >( field ); + text->setText( value.toString( context ) ); + break; + } + case FormField::FormChoice: + { + FormFieldChoice *choice = static_cast< FormFieldChoice * >( field ); + Q_UNUSED( choice ); // ### + break; + } + case FormField::FormSignature: + { + break; + } + } +} + +void JSField::initType( KJSContext *ctx ) +{ + static bool initialized = false; + if ( initialized ) + return; + initialized = true; + + if ( !g_fieldProto ) + g_fieldProto = new KJSPrototype(); + + g_fieldProto->defineProperty( ctx, "doc", fieldGetDoc ); + g_fieldProto->defineProperty( ctx, "name", fieldGetName ); + g_fieldProto->defineProperty( ctx, "readonly", + fieldGetReadOnly, fieldSetReadOnly ); + g_fieldProto->defineProperty( ctx, "type", fieldGetType ); + g_fieldProto->defineProperty( ctx, "value", fieldGetValue, fieldSetValue ); +} + +KJSObject JSField::wrapField( KJSContext *ctx, FormField *field, Page *page ) +{ + // ### cache unique wrapper + KJSObject f = g_fieldProto->constructObject( ctx, field ); + f.setProperty( ctx, "page", page->number() ); + return f; +} + +void JSField::clearCachedFields() +{ + if ( g_fieldCache.exists() ) + { + g_fieldCache->clear(); + } +} diff --git a/core/script/kjs_field_p.h b/core/script/kjs_field_p.h new file mode 100644 index 000000000..bc0a4628f --- /dev/null +++ b/core/script/kjs_field_p.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef OKULAR_SCRIPT_KJS_FIELD_P_H +#define OKULAR_SCRIPT_KJS_FIELD_P_H + +class KJSContext; +class KJSObject; + +namespace Okular { + +class FormField; +class Page; + +class JSField +{ + public: + static void initType( KJSContext *ctx ); + static KJSObject wrapField( KJSContext *ctx, FormField *field, Page *page ); + static void clearCachedFields(); +}; + +} + +#endif diff --git a/core/script/kjs_fullscreen.cpp b/core/script/kjs_fullscreen.cpp new file mode 100644 index 000000000..c07ac4e23 --- /dev/null +++ b/core/script/kjs_fullscreen.cpp @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "kjs_fullscreen_p.h" + +#include + +#include +#include + +#include "settings.h" + +using namespace Okular; + +static KJSPrototype *g_fsProto; + +static KJSObject fsGetLoop( KJSContext *, void * ) +{ + return KJSBoolean( Settings::slidesLoop() ); +} + +static void fsSetLoop( KJSContext *ctx, void *, KJSObject value ) +{ + bool loop = value.toBoolean( ctx ); + Settings::setSlidesLoop( loop ); +} + +static KJSObject fsGetUseTimer( KJSContext *, void * ) +{ + return KJSBoolean( Settings::slidesAdvance() ); +} + +static void fsSetUseTimer( KJSContext *ctx, void *, KJSObject value ) +{ + bool use = value.toBoolean( ctx ); + Settings::setSlidesAdvance( use ); +} + +static KJSObject fsGetTimeDelay( KJSContext *, void * ) +{ + return KJSNumber( Settings::slidesAdvanceTime() ); +} + +static void fsSetTimeDelay( KJSContext *ctx, void *, KJSObject value ) +{ + int time = static_cast( value.toNumber( ctx ) ); + Settings::setSlidesAdvanceTime( time ); +} + +void JSFullscreen::initType( KJSContext *ctx ) +{ + static bool initialized = false; + if ( initialized ) + return; + initialized = true; + + if ( !g_fsProto ) + g_fsProto = new KJSPrototype(); + + g_fsProto->defineProperty( ctx, "loop", fsGetLoop, fsSetLoop ); + g_fsProto->defineProperty( ctx, "useTimer", + fsGetUseTimer, fsSetUseTimer ); + g_fsProto->defineProperty( ctx, "timeDelay", + fsGetTimeDelay, fsSetTimeDelay ); +} + +KJSObject JSFullscreen::object( KJSContext *ctx ) +{ + assert( g_fsProto ); + return g_fsProto->constructObject( ctx ); +} diff --git a/core/script/kjs_fullscreen_p.h b/core/script/kjs_fullscreen_p.h new file mode 100644 index 000000000..e0f437f94 --- /dev/null +++ b/core/script/kjs_fullscreen_p.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef OKULAR_SCRIPT_KJS_FULLSCREEN_P_H +#define OKULAR_SCRIPT_KJS_FULLSCREEN_P_H + +class KJSContext; +class KJSObject; + +namespace Okular { + +class JSFullscreen +{ + public: + static void initType( KJSContext *ctx ); + static KJSObject object( KJSContext *ctx ); +}; + +} + +#endif diff --git a/core/script/kjs_spell.cpp b/core/script/kjs_spell.cpp new file mode 100644 index 000000000..ea21d26a4 --- /dev/null +++ b/core/script/kjs_spell.cpp @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "kjs_spell_p.h" + +#include +#include + +#include + +using namespace Okular; + +static KJSPrototype *g_spellProto; + +// Spell.available +static KJSObject spellGetAvailable( KJSContext *, void * ) +{ + return KJSBoolean( false ); +} + +void JSSpell::initType( KJSContext *ctx ) +{ + static bool initialized = false; + if ( initialized ) + return; + initialized = true; + + g_spellProto = new KJSPrototype(); + g_spellProto->defineProperty( ctx, QString( "available" ), spellGetAvailable ); +} + +KJSObject JSSpell::object( KJSContext *ctx ) +{ + return g_spellProto->constructObject( ctx, 0 ); +} diff --git a/core/script/kjs_spell_p.h b/core/script/kjs_spell_p.h new file mode 100644 index 000000000..f255fd1f7 --- /dev/null +++ b/core/script/kjs_spell_p.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef OKULAR_SCRIPT_KJS_SPELL_P_H +#define OKULAR_SCRIPT_KJS_SPELL_P_H + +class KJSContext; +class KJSObject; + +namespace Okular { + +class JSSpell +{ + public: + static void initType( KJSContext *ctx ); + static KJSObject object( KJSContext *ctx ); +}; + +} + +#endif diff --git a/core/script/kjs_util.cpp b/core/script/kjs_util.cpp new file mode 100644 index 000000000..99d329bb8 --- /dev/null +++ b/core/script/kjs_util.cpp @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "kjs_util_p.h" + +#include +#include +#include + +#include + +using namespace Okular; + +static KJSPrototype *g_utilProto; + +static KJSObject crackURL( KJSContext *context, void *, + const KJSArguments &arguments ) +{ + if ( arguments.count() < 1 ) + { + return context->throwException( "Missing URL argument" ); + } + QString cURL = arguments.at( 0 ).toString( context ); + KUrl url( cURL ); + if ( !url.isValid() ) + { + return context->throwException( "Invalid URL" ); + } + if ( url.protocol() != QLatin1String( "file" ) + || url.protocol() != QLatin1String( "http" ) + || url.protocol() != QLatin1String( "https" ) ) + { + return context->throwException( "Protocol not valid: '" + url.protocol() + '\'' ); + } + + KJSObject obj; + obj.setProperty( context, "cScheme", url.protocol() ); + if ( url.hasUser() ) + obj.setProperty( context, "cUser", url.user() ); + if ( url.hasPass() ) + obj.setProperty( context, "cPassword", url.password() ); + obj.setProperty( context, "cHost", url.host() ); + obj.setProperty( context, "nPort", url.port( 80 ) ); + // TODO cPath (Optional) The path portion of the URL. + // TODO cParameters (Optional) The parameter string portion of the URL. + if ( url.hasRef() ) + obj.setProperty( context, "cFragments", url.ref() ); + + return obj; +} + +void JSUtil::initType( KJSContext *ctx ) +{ + static bool initialized = false; + if ( initialized ) + return; + initialized = true; + + g_utilProto = new KJSPrototype(); + g_utilProto->defineFunction( ctx, "crackURL", crackURL ); +} + +KJSObject JSUtil::object( KJSContext *ctx ) +{ + return g_utilProto->constructObject( ctx, 0 ); +} + diff --git a/core/script/kjs_util_p.h b/core/script/kjs_util_p.h new file mode 100644 index 000000000..8acfd7fc1 --- /dev/null +++ b/core/script/kjs_util_p.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * Copyright (C) 2008 by Pino Toscano * + * Copyright (C) 2008 by Harri Porten * + * * + * 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 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef OKULAR_SCRIPT_KJS_UTIL_P_H +#define OKULAR_SCRIPT_KJS_UTIL_P_H + +class KJSContext; +class KJSObject; + +namespace Okular { + +class JSUtil +{ + public: + static void initType( KJSContext *ctx ); + static KJSObject object( KJSContext *ctx ); +}; + +} + +#endif diff --git a/core/scripter.cpp b/core/scripter.cpp index 2fd77013d..328503525 100644 --- a/core/scripter.cpp +++ b/core/scripter.cpp @@ -12,6 +12,7 @@ #include #include "debug_p.h" +#include "script/executor_kjs_p.h" using namespace Okular; @@ -19,15 +20,17 @@ class Okular::ScripterPrivate { public: ScripterPrivate( DocumentPrivate *doc ) - : m_doc( doc ) + : m_doc( doc ), m_kjs( 0 ) { } ~ScripterPrivate() { + delete m_kjs; } DocumentPrivate *m_doc; + ExecutorKJS *m_kjs; }; Scripter::Scripter( DocumentPrivate *doc ) @@ -52,6 +55,11 @@ QString Scripter::execute( ScriptType type, const QString &script ) switch ( type ) { case JavaScript: + if ( !d->m_kjs ) + { + d->m_kjs = new ExecutorKJS( d->m_doc ); + } + d->m_kjs->execute( script ); break; } return QString();