plasma-framework/scriptengines/javascript/plasmoid/simplejavascriptapplet.cpp
Aaron Seigo da186219ae give connectAllSources the same magic sauce connectSource does
thanks to emilsedgh for having the special super power of using precisely
what hasn't been properly implemented ... and then reporting it with
nice simple examples we can test with! THAT, my friends, is how it is done.
2011-04-04 14:43:40 +02:00

891 lines
32 KiB
C++

/*
* Copyright 2007-2008,2010 Richard J. Moore <rich@kde.org>
* Copyright 2009 Aaron J. Seigo <aseigo@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* 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 Library 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.
*/
#include "simplejavascriptapplet.h"
#include <iostream>
#include <QFile>
#include <QKeyEvent>
#include <QGraphicsLayout>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneWheelEvent>
#include <QParallelAnimationGroup>
#include <QPauseAnimation>
#include <QSequentialAnimationGroup>
#include <QUiLoader>
#include <QWidget>
#include <QScriptEngine>
#include <KConfigGroup>
#include <KDebug>
#include <KFileDialog>
#include <KIcon>
#include <KIO/Job>
#include <KMimeType>
#include <KShell>
#include <KStandardDirs>
#include <KLocale>
#include <KRun>
#include <Plasma/Animation>
#include <Plasma/Applet>
#include <Plasma/Extender>
#include <Plasma/ExtenderItem>
#include <Plasma/FrameSvg>
#include <Plasma/Package>
#include <Plasma/PopupApplet>
#include <Plasma/Svg>
#include <Plasma/VideoWidget>
#define USE_JS_SCRIPTENGINE
#include "appletauthorization.h"
#include "appletinterface.h"
#include "scriptenv.h"
#include "simplebindings/animationgroup.h"
#include "simplebindings/bytearrayclass.h"
#include "simplebindings/dataengine.h"
#include "simplebindings/dataenginereceiver.h"
#include "simplebindings/i18n.h"
#include "themedsvg.h"
using namespace Plasma;
Q_DECLARE_METATYPE(QKeyEvent*)
Q_DECLARE_METATYPE(QPainter*)
Q_DECLARE_METATYPE(QStyleOptionGraphicsItem*)
Q_DECLARE_METATYPE(QGraphicsSceneHoverEvent *)
Q_DECLARE_METATYPE(QGraphicsSceneMouseEvent *)
Q_DECLARE_METATYPE(QGraphicsSceneWheelEvent *)
QScriptValue constructColorClass(QScriptEngine *engine);
QScriptValue constructEasingCurveClass(QScriptEngine *engine);
QScriptValue constructFontClass(QScriptEngine *engine);
QScriptValue constructGraphicsItemClass(QScriptEngine *engine);
QScriptValue constructIconClass(QScriptEngine *engine);
QScriptValue constructKUrlClass(QScriptEngine *engine);
QScriptValue constructLinearLayoutClass(QScriptEngine *engine);
QScriptValue constructGridLayoutClass(QScriptEngine *engine);
QScriptValue constructAnchorLayoutClass(QScriptEngine *engine);
QScriptValue constructPainterClass(QScriptEngine *engine);
QScriptValue constructPenClass(QScriptEngine *engine);
QScriptValue constructQPixmapClass(QScriptEngine *engine);
QScriptValue constructQPointClass(QScriptEngine *engine);
QScriptValue constructQRectFClass(QScriptEngine *engine);
QScriptValue constructQSizeFClass(QScriptEngine *engine);
QScriptValue constructQSizePolicyClass(QScriptEngine *engine);
QScriptValue constructTimerClass(QScriptEngine *engine);
void registerNonGuiMetaTypes(QScriptEngine *engine);
void registerSimpleAppletMetaTypes(QScriptEngine *engine);
KSharedPtr<UiLoader> SimpleJavaScriptApplet::s_widgetLoader;
QHash<QString, Plasma::Animator::Animation> SimpleJavaScriptApplet::s_animationDefs;
SimpleJavaScriptApplet::SimpleJavaScriptApplet(QObject *parent, const QVariantList &args)
: AbstractJsAppletScript(parent)
{
Q_UNUSED(args);
// kDebug() << "Script applet launched, args" << applet()->startupArguments();
// TODO this will be set to the engine we get from QML
m_engine = new QScriptEngine(this);
m_env = new ScriptEnv(this, m_engine);
connect(m_env, SIGNAL(reportError(ScriptEnv*,bool)), this, SLOT(reportError(ScriptEnv*,bool)));
}
SimpleJavaScriptApplet::~SimpleJavaScriptApplet()
{
delete m_interface;
if (s_widgetLoader.count() == 1) {
s_widgetLoader.clear();
}
}
void SimpleJavaScriptApplet::reportError(ScriptEnv *env, bool fatal)
{
const QScriptValue error = env->engine()->uncaughtException();
QString file = error.property("fileName").toString();
file.remove(package()->path());
const QString failureMsg = i18n("Error in %1 on line %2.<br><br>%3",
file, error.property("lineNumber").toString(),
error.toString());
if (fatal) {
setFailedToLaunch(true, failureMsg);
} else {
showMessage(KIcon("dialog-error"), failureMsg, Plasma::ButtonOk);
}
kDebug() << failureMsg;
kDebug() << env->engine()->uncaughtExceptionBacktrace();
}
void SimpleJavaScriptApplet::configChanged()
{
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (!env || !env->callEventListeners("configchanged")) {
callPlasmoidFunction("configChanged", QScriptValueList(), env);
}
}
void SimpleJavaScriptApplet::dataUpdated(const QString &name, const DataEngine::Data &data)
{
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (!env) {
return;
}
QScriptValueList args;
args << m_engine->toScriptValue(name) << m_engine->toScriptValue(data);
if (!env->callEventListeners("dataUpdated", args)) {
callPlasmoidFunction("dataUpdated", args, env);
}
}
void SimpleJavaScriptApplet::extenderItemRestored(Plasma::ExtenderItem* item)
{
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (!env) {
return;
}
QScriptValueList args;
args << m_engine->newQObject(item, QScriptEngine::AutoOwnership, QScriptEngine::PreferExistingWrapperObject);
if (!env->callEventListeners("initExtenderItem", args)) {
callPlasmoidFunction("initExtenderItem", args, env);
}
}
void SimpleJavaScriptApplet::activate()
{
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (!env || !env->callEventListeners("activate")) {
callPlasmoidFunction("activate", QScriptValueList(), env);
}
}
void SimpleJavaScriptApplet::popupEvent(bool popped)
{
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (!env) {
return;
}
QScriptValueList args;
args << popped;
if (!env->callEventListeners("popupEvent", args)) {
callPlasmoidFunction("popupEvent", args, env);
}
}
void SimpleJavaScriptApplet::executeAction(const QString &name)
{
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (!env) {
return;
}
const QString func("action_" + name);
if (!env->callEventListeners(func)) {
callPlasmoidFunction(func, QScriptValueList(), env);
}
}
void SimpleJavaScriptApplet::paintInterface(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
{
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (!env) {
return;
}
QScriptValueList args;
args << m_engine->toScriptValue(p);
args << m_engine->toScriptValue(const_cast<QStyleOptionGraphicsItem*>(option));
args << m_engine->toScriptValue(QRectF(contentsRect));
if (!env->callEventListeners("paintInterface")) {
callPlasmoidFunction("paintInterface", args, env);
}
}
QList<QAction*> SimpleJavaScriptApplet::contextualActions()
{
return m_interface->contextualActions();
}
void SimpleJavaScriptApplet::callPlasmoidFunction(const QString &functionName, const QScriptValueList &args, ScriptEnv *env)
{
if (!env) {
env = ScriptEnv::findScriptEnv(m_engine);
}
if (env) {
QScriptValue func = m_self.property(functionName);
env->callFunction(func, args, m_self);
}
}
void SimpleJavaScriptApplet::constraintsEvent(Plasma::Constraints constraints)
{
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (!env) {
return;
}
if (constraints & Plasma::FormFactorConstraint) {
if (!env->callEventListeners("formFactorChanged")) {
callPlasmoidFunction("formFactorChanged", QScriptValueList(), env);
}
}
if (constraints & Plasma::LocationConstraint) {
if (!env->callEventListeners("locationChanged")) {
callPlasmoidFunction("locationChanged", QScriptValueList(), env);
}
}
if (constraints & Plasma::ContextConstraint) {
if (!env->callEventListeners("currentActivityChanged")) {
callPlasmoidFunction("currentActivityChanged", QScriptValueList(), env);
}
}
if (constraints & Plasma::SizeConstraint) {
if (!env || !env->callEventListeners("sizeChanged")) {
callPlasmoidFunction("sizeChanged", QScriptValueList(), env);
}
}
if (constraints & Plasma::ImmutableConstraint) {
if (!env->callEventListeners("immutabilityChanged")) {
callPlasmoidFunction("immutabilityChanged", QScriptValueList(), env);
}
}
}
bool SimpleJavaScriptApplet::include(const QString &path)
{
return m_env->include(path);
}
void SimpleJavaScriptApplet::populateAnimationsHash()
{
if (s_animationDefs.isEmpty()) {
s_animationDefs.insert("fade", Plasma::Animator::FadeAnimation);
s_animationDefs.insert("geometry", Plasma::Animator::GeometryAnimation);
s_animationDefs.insert("grow", Plasma::Animator::GrowAnimation);
s_animationDefs.insert("pulse", Plasma::Animator::PulseAnimation);
s_animationDefs.insert("rotate", Plasma::Animator::RotationAnimation);
s_animationDefs.insert("rotateStacked", Plasma::Animator::RotationStackedAnimation);
s_animationDefs.insert("slide", Plasma::Animator::SlideAnimation);
s_animationDefs.insert("zoom", Plasma::Animator::ZoomAnimation);
}
}
bool SimpleJavaScriptApplet::init()
{
connect(applet(), SIGNAL(extenderItemRestored(Plasma::ExtenderItem*)),
this, SLOT(extenderItemRestored(Plasma::ExtenderItem*)));
connect(applet(), SIGNAL(activate()),
this, SLOT(activate()));
setupObjects();
AppletAuthorization auth(this);
if (!m_env->importExtensions(description(), m_self, auth)) {
return false;
}
kDebug() << "ScriptName:" << applet()->name();
kDebug() << "ScriptCategory:" << applet()->category();
applet()->installEventFilter(this);
return m_env->include(mainScript());
}
QScriptValue SimpleJavaScriptApplet::createKeyEventObject(QKeyEvent *event)
{
QScriptValue v = m_env->engine()->newObject();
v.setProperty("count", event->count());
v.setProperty("key", event->key());
v.setProperty("modifiers", static_cast<int>(event->modifiers()));
v.setProperty("text", event->text());
return v;
}
QScriptValue SimpleJavaScriptApplet::createHoverEventObject(QGraphicsSceneHoverEvent *event)
{
QScriptEngine *engine = m_env->engine();
QScriptValue v = engine->newObject();
v.setProperty("pos", engine->toScriptValue<QPoint>(event->pos().toPoint()));
v.setProperty("scenePos", engine->toScriptValue<QPoint>(event->scenePos().toPoint()));
v.setProperty("screenPos", engine->toScriptValue<QPoint>(event->screenPos()));
v.setProperty("lastPos", engine->toScriptValue<QPoint>(event->lastPos().toPoint()));
v.setProperty("lastScenePos", engine->toScriptValue<QPoint>(event->lastScenePos().toPoint()));
v.setProperty("lastScreenPos", engine->toScriptValue<QPoint>(event->lastScreenPos()));
v.setProperty("modifiers", static_cast<int>(event->modifiers()));
return v;
}
QScriptValue SimpleJavaScriptApplet::createMouseEventObject(QGraphicsSceneMouseEvent *event)
{
QScriptEngine *engine = m_env->engine();
QScriptValue v = engine->newObject();
v.setProperty("button", static_cast<int>(event->button()));
v.setProperty("buttons", static_cast<int>(event->buttons()));
v.setProperty("modifiers", static_cast<int>(event->modifiers()));
v.setProperty("pos", engine->toScriptValue<QPoint>(event->pos().toPoint()));
v.setProperty("scenePos", engine->toScriptValue<QPoint>(event->scenePos().toPoint()));
v.setProperty("screenPos", engine->toScriptValue<QPoint>(event->screenPos()));
v.setProperty("lastPos", engine->toScriptValue<QPoint>(event->lastPos().toPoint()));
v.setProperty("lastScenePos", engine->toScriptValue<QPoint>(event->lastScenePos().toPoint()));
v.setProperty("lastScreenPos", engine->toScriptValue<QPoint>(event->lastScreenPos()));
return v;
}
QScriptValue SimpleJavaScriptApplet::createWheelEventObject(QGraphicsSceneWheelEvent *event)
{
QScriptEngine *engine = m_env->engine();
QScriptValue v = engine->newObject();
v.setProperty("delta", event->delta());
v.setProperty("buttons", static_cast<int>(event->buttons()));
v.setProperty("modifiers", static_cast<int>(event->modifiers()));
v.setProperty("orientation", static_cast<int>(event->orientation()));
v.setProperty("pos", engine->toScriptValue<QPoint>(event->pos().toPoint()));
v.setProperty("scenePos", engine->toScriptValue<QPoint>(event->scenePos().toPoint()));
v.setProperty("screenPos", engine->toScriptValue<QPoint>(event->screenPos()));
return v;
}
bool SimpleJavaScriptApplet::eventFilter(QObject *watched, QEvent *event)
{
switch (event->type()) {
case QEvent::KeyPress: {
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (env && env->hasEventListeners("keypress")) {
QScriptValueList args;
args << createKeyEventObject(static_cast<QKeyEvent *>(event));
env->callEventListeners("keypress", args);
return true;
}
}
case QEvent::KeyRelease: {
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (env && env->hasEventListeners("keyrelease")) {
QScriptValueList args;
args << createKeyEventObject(static_cast<QKeyEvent *>(event));
env->callEventListeners("keyrelease", args);
return true;
}
}
break;
case QEvent::GraphicsSceneHoverEnter: {
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (env && env->hasEventListeners("hoverenter")) {
QScriptValueList args;
args << createHoverEventObject(static_cast<QGraphicsSceneHoverEvent *>(event));
env->callEventListeners("hoverenter", args);
return true;
}
}
break;
case QEvent::GraphicsSceneHoverLeave: {
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (env && env->hasEventListeners("hoverleave")) {
QScriptValueList args;
args << createHoverEventObject(static_cast<QGraphicsSceneHoverEvent *>(event));
env->callEventListeners("hoverleave", args);
return true;
}
}
break;
case QEvent::GraphicsSceneHoverMove: {
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (env && env->hasEventListeners("hovermove")) {
QScriptValueList args;
args << createHoverEventObject(static_cast<QGraphicsSceneHoverEvent *>(event));
env->callEventListeners("hovermove", args);
return true;
}
}
break;
case QEvent::GraphicsSceneMousePress: {
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (env && env->hasEventListeners("mousepress")) {
QScriptValueList args;
args << createMouseEventObject(static_cast<QGraphicsSceneMouseEvent *>(event));
env->callEventListeners("mousepress", args);
return true;
}
}
break;
case QEvent::GraphicsSceneMouseRelease: {
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (env && env->hasEventListeners("mouserelease")) {
QScriptValueList args;
args << createMouseEventObject(static_cast<QGraphicsSceneMouseEvent *>(event));
env->callEventListeners("mouserelease", args);
return true;
}
}
break;
case QEvent::GraphicsSceneMouseMove: {
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (env && env->hasEventListeners("mousemove")) {
QScriptValueList args;
args << createMouseEventObject(static_cast<QGraphicsSceneMouseEvent *>(event));
env->callEventListeners("mousemove", args);
return true;
}
}
break;
case QEvent::GraphicsSceneMouseDoubleClick: {
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (env && env->hasEventListeners("mousedoubleclick")) {
QScriptValueList args;
args << createMouseEventObject(static_cast<QGraphicsSceneMouseEvent *>(event));
env->callEventListeners("mousedoubleclick", args);
return true;
}
}
break;
case QEvent::GraphicsSceneWheel: {
ScriptEnv *env = ScriptEnv::findScriptEnv(m_engine);
if (env && env->hasEventListeners("wheel")) {
QScriptValueList args;
args << createWheelEventObject(static_cast<QGraphicsSceneWheelEvent *>(event));
env->callEventListeners("wheel", args);
return true;
}
}
break;
default:
break;
}
return Plasma::AppletScript::eventFilter(watched, event);
}
void SimpleJavaScriptApplet::setupObjects()
{
QScriptValue global = m_engine->globalObject();
// Bindings for animations
global.setProperty("animation", m_engine->newFunction(SimpleJavaScriptApplet::animation));
global.setProperty("AnimationGroup", m_engine->newFunction(SimpleJavaScriptApplet::animationGroup));
global.setProperty("ParallelAnimationGroup", m_engine->newFunction(SimpleJavaScriptApplet::parallelAnimationGroup));
// Bindings for data engine
bindI18N(m_engine);
global.setProperty("dataEngine", m_engine->newFunction(SimpleJavaScriptApplet::dataEngine));
global.setProperty("service", m_engine->newFunction(SimpleJavaScriptApplet::service));
global.setProperty("loadService", m_engine->newFunction(SimpleJavaScriptApplet::loadService));
// Expose applet interface
const bool isPopupApplet = qobject_cast<Plasma::PopupApplet *>(applet());
m_interface = isPopupApplet ? new PopupAppletInterface(this) : new JsAppletInterface(this);
m_self = m_engine->newQObject(m_interface, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater);
m_env->addMainObjectProperties(m_self);
m_self.setScope(global);
global.setProperty("plasmoid", m_self);
if (isPopupApplet) {
connect(applet(), SIGNAL(popupEvent(bool)), this, SLOT(popupEvent(bool)));
}
QScriptValue args = m_engine->newArray();
int i = 0;
foreach (const QVariant &arg, applet()->startupArguments()) {
args.setProperty(i, m_engine->newVariant(arg));
++i;
}
global.setProperty("startupArguments", args);
ScriptEnv::registerEnums(global, AppletInterface::staticMetaObject);
// Add a global loadui method for ui files
QScriptValue fun = m_engine->newFunction(SimpleJavaScriptApplet::loadui);
global.setProperty("loadui", fun);
// Work around bug in 4.3.0
qMetaTypeId<QVariant>();
// Add stuff from Qt
global.setProperty("QPainter", constructPainterClass(m_engine));
global.setProperty("QGraphicsItem", constructGraphicsItemClass(m_engine));
global.setProperty("QIcon", constructIconClass(m_engine));
global.setProperty("QTimer", constructTimerClass(m_engine));
global.setProperty("QFont", constructFontClass(m_engine));
global.setProperty("QColor", constructColorClass(m_engine));
global.setProperty("QEasingCurve", constructEasingCurveClass(m_engine));
global.setProperty("QRectF", constructQRectFClass(m_engine));
global.setProperty("QPen", constructPenClass(m_engine));
global.setProperty("QPixmap", constructQPixmapClass(m_engine));
global.setProperty("QSizeF", constructQSizeFClass(m_engine));
global.setProperty("QSizePolicy", constructQSizePolicyClass(m_engine));
global.setProperty("QPoint", constructQPointClass(m_engine));
global.setProperty("LinearLayout", constructLinearLayoutClass(m_engine));
global.setProperty("GridLayout", constructGridLayoutClass(m_engine));
global.setProperty("AnchorLayout", constructAnchorLayoutClass(m_engine));
ByteArrayClass *baClass = new ByteArrayClass(m_engine);
global.setProperty("ByteArray", baClass->constructor());
// Add stuff from KDE libs
qScriptRegisterSequenceMetaType<KUrl::List>(m_engine);
global.setProperty("Url", constructKUrlClass(m_engine));
// Add stuff from Plasma
global.setProperty("PlasmaSvg", m_engine->newFunction(SimpleJavaScriptApplet::newPlasmaSvg));
global.setProperty("PlasmaFrameSvg", m_engine->newFunction(SimpleJavaScriptApplet::newPlasmaFrameSvg));
global.setProperty("Svg", m_engine->newFunction(SimpleJavaScriptApplet::newPlasmaSvg));
global.setProperty("FrameSvg", m_engine->newFunction(SimpleJavaScriptApplet::newPlasmaFrameSvg));
global.setProperty("ExtenderItem", m_engine->newFunction(SimpleJavaScriptApplet::newPlasmaExtenderItem));
registerNonGuiMetaTypes(m_engine);
registerSimpleAppletMetaTypes(m_engine);
installWidgets(m_engine);
}
QScriptValue SimpleJavaScriptApplet::dataEngine(QScriptContext *context, QScriptEngine *engine)
{
if (context->argumentCount() != 1) {
return context->throwError(i18n("dataEngine() takes one argument"));
}
AppletInterface *interface = AppletInterface::extract(engine);
if (!interface) {
return context->throwError(i18n("Could not extract the Applet"));
}
const QString dataEngineName = context->argument(0).toString();
DataEngine *dataEngine = interface->dataEngine(dataEngineName);
QScriptValue v = engine->newQObject(dataEngine, QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);
v.setProperty("connectSource", engine->newFunction(DataEngineReceiver::connectSource));
v.setProperty("connectAllSources", engine->newFunction(DataEngineReceiver::connectAllSources));
v.setProperty("disconnectSource", engine->newFunction(DataEngineReceiver::disconnectSource));
return v;
}
QScriptValue SimpleJavaScriptApplet::service(QScriptContext *context, QScriptEngine *engine)
{
if (context->argumentCount() != 2) {
return context->throwError(i18n("service() takes two arguments"));
}
QString dataEngine = context->argument(0).toString();
AppletInterface *interface = AppletInterface::extract(engine);
if (!interface) {
return context->throwError(i18n("Could not extract the Applet"));
}
DataEngine *data = interface->dataEngine(dataEngine);
QString source = context->argument(1).toString();
Service *service = data->serviceForSource(source);
//kDebug( )<< "lets try to get" << source << "from" << dataEngine;
return engine->newQObject(service, QScriptEngine::AutoOwnership);
}
QScriptValue SimpleJavaScriptApplet::loadService(QScriptContext *context, QScriptEngine *engine)
{
if (context->argumentCount() != 1) {
return context->throwError(i18n("service() takes one argument"));
}
QString pluginName = context->argument(0).toString();
AppletInterface *interface = AppletInterface::extract(engine);
if (!interface) {
return context->throwError(i18n("Could not extract the Applet"));
}
Plasma::Service *service = Plasma::Service::load(pluginName, interface);
//kDebug( )<< "lets try to get" << source << "from" << dataEngine;
return engine->newQObject(service, QScriptEngine::AutoOwnership);
}
QScriptValue SimpleJavaScriptApplet::animation(QScriptContext *context, QScriptEngine *engine)
{
if (context->argumentCount() != 1) {
return context->throwError(i18n("animation() takes one argument"));
}
populateAnimationsHash();
QString name = context->argument(0).toString();
QString animName = name.toLower();
const bool isPause = animName == "pause";
const bool isProperty = animName == "property";
bool parentIsApplet = false;
QGraphicsWidget *parent = extractParent(context, engine, 0, &parentIsApplet);
QAbstractAnimation *anim = 0;
Plasma::Animation *plasmaAnim = 0;
if (isPause) {
anim = new QPauseAnimation(parent);
} else if (isProperty) {
anim = new QPropertyAnimation(parent);
} else if (s_animationDefs.contains(animName)) {
plasmaAnim = Plasma::Animator::create(s_animationDefs.value(animName), parent);
} else {
SimpleJavaScriptApplet *jsApplet = qobject_cast<SimpleJavaScriptApplet *>(engine->parent());
if (jsApplet) {
//kDebug() << "trying to load it from the package";
plasmaAnim = jsApplet->loadAnimationFromPackage(name, parent);
}
if (!plasmaAnim) {
plasmaAnim = Plasma::Animator::create(animName, parent);
}
}
if (plasmaAnim) {
if (!parentIsApplet) {
plasmaAnim->setTargetWidget(parent);
}
anim = plasmaAnim;
}
if (anim) {
QScriptValue value = engine->newQObject(anim);
ScriptEnv::registerEnums(value, *anim->metaObject());
return value;
}
context->throwError(i18n("%1 is not a known animation type", animName));
ScriptEnv *env = ScriptEnv::findScriptEnv(engine);
if (env) {
env->checkForErrors(false);
}
return engine->undefinedValue();
}
QScriptValue SimpleJavaScriptApplet::animationGroup(QScriptContext *context, QScriptEngine *engine)
{
QGraphicsWidget *parent = extractParent(context, engine);
SequentialAnimationGroup *group = new SequentialAnimationGroup(parent);
return engine->newQObject(group);
}
QScriptValue SimpleJavaScriptApplet::parallelAnimationGroup(QScriptContext *context, QScriptEngine *engine)
{
QGraphicsWidget *parent = extractParent(context, engine);
ParallelAnimationGroup *group = new ParallelAnimationGroup(parent);
return engine->newQObject(group);
}
QScriptValue SimpleJavaScriptApplet::loadui(QScriptContext *context, QScriptEngine *engine)
{
if (context->argumentCount() != 1) {
return context->throwError(i18n("loadui() takes one argument"));
}
QString filename = context->argument(0).toString();
QFile f(filename);
if (!f.open(QIODevice::ReadOnly)) {
return context->throwError(i18n("Unable to open '%1'",filename));
}
QUiLoader loader;
QWidget *w = loader.load(&f);
f.close();
return engine->newQObject(w, QScriptEngine::AutoOwnership);
}
QScriptValue SimpleJavaScriptApplet::newPlasmaSvg(QScriptContext *context, QScriptEngine *engine)
{
if (context->argumentCount() == 0) {
return context->throwError(i18n("Constructor takes at least 1 argument"));
}
const QString filename = context->argument(0).toString();
bool parentedToApplet = false;
QGraphicsWidget *parent = extractParent(context, engine, 1, &parentedToApplet);
Svg *svg = new ThemedSvg(parent);
svg->setImagePath(ThemedSvg::findSvg(engine, filename));
QScriptValue obj = engine->newQObject(svg);
ScriptEnv::registerEnums(obj, *svg->metaObject());
return obj;
}
QScriptValue SimpleJavaScriptApplet::newPlasmaFrameSvg(QScriptContext *context, QScriptEngine *engine)
{
if (context->argumentCount() == 0) {
return context->throwError(i18n("Constructor takes at least 1 argument"));
}
QString filename = context->argument(0).toString();
bool parentedToApplet = false;
QGraphicsWidget *parent = extractParent(context, engine, 1, &parentedToApplet);
FrameSvg *frameSvg = new ThemedFrameSvg(parent);
frameSvg->setImagePath(ThemedSvg::findSvg(engine, filename));
QScriptValue obj = engine->newQObject(frameSvg);
ScriptEnv::registerEnums(obj, *frameSvg->metaObject());
return obj;
}
QScriptValue SimpleJavaScriptApplet::newPlasmaExtenderItem(QScriptContext *context, QScriptEngine *engine)
{
Plasma::Extender *extender = 0;
if (context->argumentCount() > 0) {
extender = qobject_cast<Plasma::Extender *>(context->argument(0).toQObject());
}
if (!extender) {
AppletInterface *interface = AppletInterface::extract(engine);
if (!interface) {
engine->undefinedValue();
}
extender = interface->extender();
}
Plasma::ExtenderItem *extenderItem = new Plasma::ExtenderItem(extender);
QScriptValue fun = engine->newQObject(extenderItem);
ScriptEnv::registerEnums(fun, *extenderItem->metaObject());
return fun;
}
QScriptValue SimpleJavaScriptApplet::widgetAdjustSize(QScriptContext *context, QScriptEngine *engine)
{
QGraphicsWidget *widget = qobject_cast<QGraphicsWidget*>(context->thisObject().toQObject());
if (widget) {
widget->adjustSize();
}
return engine->undefinedValue();
}
void SimpleJavaScriptApplet::installWidgets(QScriptEngine *engine)
{
QScriptValue globalObject = engine->globalObject();
if (!s_widgetLoader) {
s_widgetLoader = new UiLoader;
}
foreach (const QString &widget, s_widgetLoader->availableWidgets()) {
QScriptValue fun = engine->newFunction(createWidget);
QScriptValue name = engine->toScriptValue(widget);
fun.setProperty(QString("functionName"), name,
QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
fun.setProperty(QString("prototype"), engine->newObject());
globalObject.setProperty(widget, fun);
}
}
QScriptEngine *SimpleJavaScriptApplet::engine() const
{
return m_engine;
}
QGraphicsWidget *SimpleJavaScriptApplet::extractParent(QScriptContext *context, QScriptEngine *engine,
int argIndex, bool *parentedToApplet)
{
if (parentedToApplet) {
*parentedToApplet = false;
}
QGraphicsWidget *parent = 0;
if (context->argumentCount() >= argIndex) {
parent = qobject_cast<QGraphicsWidget*>(context->argument(argIndex).toQObject());
}
if (!parent) {
AppletInterface *interface = AppletInterface::extract(engine);
if (!interface) {
return 0;
}
//kDebug() << "got the applet!";
parent = interface->applet();
if (parentedToApplet) {
*parentedToApplet = true;
}
}
return parent;
}
QScriptValue SimpleJavaScriptApplet::createWidget(QScriptContext *context, QScriptEngine *engine)
{
QGraphicsWidget *parent = extractParent(context, engine);
QString self = context->callee().property("functionName").toString();
if (!s_widgetLoader) {
s_widgetLoader = new UiLoader;
}
QGraphicsWidget *w = s_widgetLoader->createWidget(self, parent);
if (!w) {
return QScriptValue();
}
QScriptValue fun = engine->newQObject(w);
fun.setPrototype(context->callee().property("prototype"));
fun.setProperty("adjustSize", engine->newFunction(widgetAdjustSize));
//register enums will be accessed for instance as frame.Sunken for Frame shadow...
ScriptEnv::registerEnums(fun, *w->metaObject());
return fun;
}
void SimpleJavaScriptApplet::collectGarbage()
{
m_engine->collectGarbage();
}
QString SimpleJavaScriptApplet::filePath(const QString &type, const QString &file) const
{
const QString path = m_env->filePathFromScriptContext(type.toLocal8Bit().constData(), file);
if (!path.isEmpty()) {
return path;
}
return package()->filePath(type.toLocal8Bit().constData(), file);
}
QScriptValue SimpleJavaScriptApplet::variantToScriptValue(QVariant var)
{
return m_engine->newVariant(var);
}
K_EXPORT_PLASMA_APPLETSCRIPTENGINE(qscriptapplet, SimpleJavaScriptApplet)