Plasma
animationscriptengine.cpp
Go to the documentation of this file.
00001 /* 00002 * Copyright 2010 Aaron Seigo <aseigo@kde.org> 00003 * Copyright 2010 Adenilson Cavalcanti <cavalcantii@gmail.com> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU Library General Public License as 00007 * published by the Free Software Foundation; either version 2, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details 00014 * 00015 * You should have received a copy of the GNU Library General Public 00016 * License along with this program; if not, write to the 00017 * Free Software Foundation, Inc., 00018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 */ 00020 00021 /* TODO: 00022 * 00023 * - cleanup debug messages 00024 */ 00025 00026 #include "animationscriptengine_p.h" 00027 00028 #include <QFile> 00029 #include <QMetaEnum> 00030 #include <QParallelAnimationGroup> 00031 #include <QPauseAnimation> 00032 #include <QSequentialAnimationGroup> 00033 #include <QTextStream> 00034 00035 #include <kdebug.h> 00036 #include <klocale.h> 00037 00038 #include "animator.h" 00039 #include "javascriptanimation_p.h" 00040 #include "bindings/animationgroup_p.h" 00041 00042 namespace Plasma 00043 { 00044 00045 QScriptValue constructEasingCurveClass(QScriptEngine *engine); 00046 00047 namespace AnimationScriptEngine 00048 { 00049 00050 QScriptEngine* inst = 0; 00051 QHash<QString, QScriptValue> s_animFuncs; 00052 QSet<QString> s_animFailures; 00053 QString s_prefix; 00054 00055 QScriptValue animation(const QString &anim) 00056 { 00057 return s_animFuncs.value(anim); 00058 } 00059 00060 bool isAnimationRegistered(const QString &anim) 00061 { 00062 return s_animFuncs.contains(anim); 00063 } 00064 00065 void addToLoadFailures(const QString &anim) 00066 { 00067 s_animFailures.insert(anim); 00068 } 00069 00070 bool animationFailedToLoad(const QString &anim) 00071 { 00072 return s_animFailures.contains(anim); 00073 } 00074 00075 void clearAnimations() 00076 { 00077 s_animFuncs.clear(); 00078 s_animFailures.clear(); 00079 delete inst; 00080 inst = 0; 00081 } 00082 00083 QScriptValue registerAnimation(QScriptContext *context, QScriptEngine *engine) 00084 { 00085 if (context->argumentCount() > 1) { 00086 const QString name = s_prefix + context->argument(0).toString(); 00087 00088 if (!s_animFuncs.contains(name)) { 00089 const QScriptValue func = context->argument(1); 00090 if (func.isFunction()) { 00091 s_animFuncs.insert(name, func); 00092 } 00093 } 00094 } 00095 00096 return engine->undefinedValue(); 00097 } 00098 00099 QObject *extractParent(QScriptContext *context, QScriptEngine *engine) 00100 { 00101 Q_UNUSED(engine) 00102 return context->thisObject().property("__plasma_javascriptanimation").toQObject(); 00103 } 00104 00105 QScriptValue animationGroup(QScriptContext *context, QScriptEngine *engine) 00106 { 00107 QObject *parent = extractParent(context, engine); 00108 if (!parent) { 00109 return engine->undefinedValue(); 00110 } 00111 00112 QSequentialAnimationGroup *group = new SequentialAnimationGroup(parent); 00113 return engine->newQObject(group); 00114 } 00115 00116 QScriptValue parallelAnimationGroup(QScriptContext *context, QScriptEngine *engine) 00117 { 00118 QObject *parent = extractParent(context, engine); 00119 if (!parent) { 00120 return engine->undefinedValue(); 00121 } 00122 00123 ParallelAnimationGroup *group = new ParallelAnimationGroup(parent); 00124 return engine->newQObject(group); 00125 } 00126 00127 void registerEnums(QScriptValue &scriptValue, const QMetaObject &meta) 00128 { 00129 //manually create enum values. ugh 00130 QScriptEngine *engine = scriptValue.engine(); 00131 for (int i = 0; i < meta.enumeratorCount(); ++i) { 00132 QMetaEnum e = meta.enumerator(i); 00133 //kDebug() << e.name(); 00134 for (int i=0; i < e.keyCount(); ++i) { 00135 //kDebug() << e.key(i) << e.value(i); 00136 scriptValue.setProperty(e.key(i), QScriptValue(engine, e.value(i))); 00137 } 00138 } 00139 } 00140 00141 QScriptValue animation(QScriptContext *context, QScriptEngine *engine) 00142 { 00143 if (context->argumentCount() != 1) { 00144 return context->throwError(i18n("animation() takes one argument")); 00145 } 00146 00147 QObject *parent = extractParent(context, engine); 00148 QAbstractAnimation *anim = 0; 00149 if (context->argument(0).isString()) { 00150 const QString animName = context->argument(0).toString(); 00151 anim = Plasma::Animator::create(animName, parent); 00152 } else { 00153 int animId = context->argument(0).toInt32(); 00154 if (animId == JavascriptAnimation::PauseAnimation) { 00155 anim = new QPauseAnimation(parent); 00156 } else if (animId == JavascriptAnimation::PropertyAnimation) { 00157 anim = new QPropertyAnimation(parent); 00158 } else { 00159 anim = Plasma::Animator::create(static_cast<Animator::Animation>(animId), parent); 00160 } 00161 } 00162 00163 if (anim) { 00164 QScriptValue value = engine->newQObject(anim); 00165 registerEnums(value, *anim->metaObject()); 00166 return value; 00167 } 00168 00169 return context->throwError(i18n("%1 is not a known animation type", context->argument(0).isString())); 00170 } 00171 00172 QScriptEngine *globalEngine() 00173 { 00174 if (!inst) { 00175 inst = new QScriptEngine; 00176 QScriptValue global = inst->globalObject(); 00177 global.setProperty("registerAnimation", inst->newFunction(AnimationScriptEngine::registerAnimation)); 00178 global.setProperty("AnimationGroup", inst->newFunction(AnimationScriptEngine::animationGroup)); 00179 global.setProperty("ParallelAnimationGroup", inst->newFunction(AnimationScriptEngine::parallelAnimationGroup)); 00180 global.setProperty("QEasingCurve", constructEasingCurveClass(inst)); 00181 kDebug() << "........... first js animation, creating the engine!"; 00182 } 00183 00184 return inst; 00185 } 00186 00187 bool loadScript(const QString &path, const QString &prefix) 00188 { 00189 QFile file(path); 00190 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { 00191 kError() << "failed to open script file" << path; 00192 return false; 00193 } 00194 00195 QTextStream buffer(&file); 00196 QString tmp(buffer.readAll()); 00197 00198 QScriptEngine *engine = AnimationScriptEngine::globalEngine(); 00199 engine->pushContext(); 00200 s_prefix = prefix; 00201 QScriptValue def(engine->evaluate(tmp, path)); 00202 s_prefix.clear(); 00203 engine->popContext(); 00204 if (engine->hasUncaughtException()) { 00205 const QScriptValue error = engine->uncaughtException(); 00206 QString file = error.property("fileName").toString(); 00207 const QString failureMsg = QString("Error in %1 on line %2.\n%3") 00208 .arg(file) 00209 .arg(error.property("lineNumber").toString()) 00210 .arg(error.toString()); 00211 kError() << failureMsg; 00212 return false; 00213 } 00214 00215 return true; 00216 } 00217 00218 } // namespace AnimationEngine 00219 } // namespace Plasma 00220
KDE 4.6 API Reference