de4fa09a6d
setFailedToLaunch has a weird asymmetric api: now launchErrorMessage is a string property. failedToLaunch remains and is internally set true the first time a message is set (is not posssible to set it back to false) the message is in turn used by the scriptengine for the user visible error message. It is done in 2 places: if the applet package is invalid (applet not found) the message is created by the containment if the applet package is valid, but there is a parse error in the qml file the error message is generated by the scriptengine of the applet itself. I'm still really not happy about how the error ui is generated.
899 lines
32 KiB
C++
899 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 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),
|
|
m_interface(0)
|
|
{
|
|
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) {
|
|
setLaunchErrorMessage(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()
|
|
{
|
|
if (!m_interface) {
|
|
return QList<QAction *>();
|
|
}
|
|
|
|
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()));
|
|
KGlobal::locale()->insertCatalog("plasma_applet_" % description().pluginName());
|
|
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));
|
|
|
|
QScriptValue v = m_engine->newVariant(QVariant::fromValue(*applet()->package()));
|
|
global.setProperty("__plasma_package", v,
|
|
QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
|
|
|
|
// 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));
|
|
|
|
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)
|
|
|