commit 6bae6e29816be171462ae028a9adc1dcaab778d6 Author: Tomas Touceda chiiph@torproject.org Date: Mon Jun 13 01:56:37 2011 -0300
Improve the engine
- Add include and importExtension functions from qtscriptgenerator. - Improve the ADD_CLASS macro - Add a way to access the settings that belong to a tab from inside a plugin. --- src/vidalia/plugin/PluginEngine.cpp | 86 +++++++++++++++++++- src/vidalia/plugin/PluginEngine.h | 15 ++-- .../plugin/prototypes/VidaliaTabPrototype.cpp | 52 +++++++++++- .../plugin/prototypes/VidaliaTabPrototype.h | 6 ++ 4 files changed, 149 insertions(+), 10 deletions(-)
diff --git a/src/vidalia/plugin/PluginEngine.cpp b/src/vidalia/plugin/PluginEngine.cpp index 883dc24..9604b8d 100644 --- a/src/vidalia/plugin/PluginEngine.cpp +++ b/src/vidalia/plugin/PluginEngine.cpp @@ -6,8 +6,14 @@ PluginEngine::PluginEngine(QObject *parent) : QScriptEngine(parent) { - ADD_CLASS("VidaliaTab", VidaliaTabPrototype, VidaliaTab *, - VidaliaTabPrototype::constructor) + ADD_CLASS(VidaliaTabPrototype) + + globalObject().setProperty("include", newFunction(includeScript)); + globalObject().setProperty("importExtension", newFunction(importExtension)); + + DebugDialog::outputDebug("Available extensions:"); + foreach(QString ext, availableExtensions()) + DebugDialog::outputDebug(QString(" %1").arg(ext));
loadAllPlugins(); } @@ -74,3 +80,79 @@ PluginEngine::getAllActions()
return actions; } + +QScriptValue +PluginEngine::importExtension(QScriptContext *context, QScriptEngine *engine) +{ + return engine->importExtension(context->argument(0).toString()); +} + +QScriptValue +PluginEngine::includeScript(QScriptContext *context, QScriptEngine *engine) +{ + QString currentFileName = engine->globalObject().property("qs").property("script").property("absoluteFilePath").toString(); + QFileInfo currentFileInfo(currentFileName); + QString path = currentFileInfo.path(); + QString importFile = context->argument(0).toString(); + QFileInfo importInfo(importFile); + if (importInfo.isRelative()) { + importFile = path + "/" + importInfo.filePath(); + } + if (!loadFile(importFile, engine)) { + return context->throwError(QString("Failed to resolve include: %1").arg(importFile)); + } + return engine->toScriptValue(true); +} + +bool +PluginEngine::loadFile(QString fileName, QScriptEngine *engine) +{ + // avoid loading files more than once + static QSet<QString> loadedFiles; + QFileInfo fileInfo(fileName); + QString absoluteFileName = fileInfo.absoluteFilePath(); + QString absolutePath = fileInfo.absolutePath(); + QString canonicalFileName = fileInfo.canonicalFilePath(); + if (loadedFiles.contains(canonicalFileName)) { + return true; + } + loadedFiles.insert(canonicalFileName); + QString path = fileInfo.path(); + + // load the file + QFile file(fileName); + if (file.open(QFile::ReadOnly)) { + QTextStream stream(&file); + QString contents = stream.readAll(); + file.close(); + + int endlineIndex = contents.indexOf('\n'); + QString line = contents.left(endlineIndex); + int lineNumber = 1; + + // strip off #!/usr/bin/env qscript line + if (line.startsWith("#!")) { + contents.remove(0, endlineIndex+1); + ++lineNumber; + } + + // set qt.script.absoluteFilePath + QScriptValue script = engine->globalObject().property("qs").property("script"); + QScriptValue oldFilePathValue = script.property("absoluteFilePath"); + QScriptValue oldPathValue = script.property("absolutePath"); + script.setProperty("absoluteFilePath", engine->toScriptValue(absoluteFileName)); + script.setProperty("absolutePath", engine->toScriptValue(absolutePath)); + + QScriptValue r = engine->evaluate(contents, fileName, lineNumber); + if (engine->hasUncaughtException()) { + QStringList backtrace = engine->uncaughtExceptionBacktrace(); + qDebug() << QString(" %1\n%2\n\n").arg(r.toString()).arg(backtrace.join("\n")); + return true; + } + script.setProperty("absoluteFilePath", oldFilePathValue); // if we come from includeScript(), or whereever + script.setProperty("absolutePath", oldPathValue); // if we come from includeScript(), or whereever + } else { + return false; + } + return true; +} diff --git a/src/vidalia/plugin/PluginEngine.h b/src/vidalia/plugin/PluginEngine.h index 7876803..6496ca6 100644 --- a/src/vidalia/plugin/PluginEngine.h +++ b/src/vidalia/plugin/PluginEngine.h @@ -8,12 +8,11 @@
class PluginWrapper;
-#define ADD_CLASS(name, protoType, absType, ctor) \ - protoType __proto; \ - QScriptValue __script = newQObject(&__proto, QScriptEngine::ScriptOwnership); \ - setDefaultPrototype(qMetaTypeId<absType>(), __script); \ - QScriptValue __ctor = newFunction(ctor, __script); \ - globalObject().setProperty(name, __ctor); +#define ADD_CLASS(protoType) \ + QScriptValue __script##protoType = newQObject(new protoType); \ + setDefaultPrototype(protoType::metaTypeId(), __script##protoType); \ + globalObject().setProperty(protoType::name(), newFunction(protoType::constructor, __script##protoType)); +
class PluginEngine : public QScriptEngine { Q_OBJECT @@ -28,6 +27,10 @@ class PluginEngine : public QScriptEngine { void pluginTab(VidaliaTab *);
protected: + static QScriptValue importExtension(QScriptContext *context, QScriptEngine *engine); + static bool loadFile(QString fileName, QScriptEngine *engine); + static QScriptValue includeScript(QScriptContext *context, QScriptEngine *engine); + void loadAllPlugins(); void tryLoadPlugin(QDir path);
diff --git a/src/vidalia/plugin/prototypes/VidaliaTabPrototype.cpp b/src/vidalia/plugin/prototypes/VidaliaTabPrototype.cpp index 58170ef..52b8fef 100644 --- a/src/vidalia/plugin/prototypes/VidaliaTabPrototype.cpp +++ b/src/vidalia/plugin/prototypes/VidaliaTabPrototype.cpp @@ -4,7 +4,55 @@ VidaliaTabPrototype::VidaliaTabPrototype(QObject *parent) : QObject(parent) {}
-QScriptValue VidaliaTabPrototype::constructor(QScriptContext *context, QScriptEngine *engine) +QScriptValue +VidaliaTabPrototype::constructor(QScriptContext *context, QScriptEngine *engine) { - return engine->newQObject(new VidaliaTab(QString("titulooo"), QString("nombreee")), QScriptEngine::ScriptOwnership); + if((context->argumentCount() > 2) or (context->argumentCount() < 1)) + return QScriptValue(QScriptValue::NullValue); + + QString title = ""; + QString name = ""; + + title = qscriptvalue_cast<QString>(context->argument(0)); + if(context->argumentCount() > 1) + name = qscriptvalue_cast<QString>(context->argument(1)); + + return engine->newQObject(new VidaliaTab(title, name), QScriptEngine::ScriptOwnership); +} + +int +VidaliaTabPrototype::metaTypeId() { + return qMetaTypeId<VidaliaTab *>(); +} + +QString +VidaliaTabPrototype::name() { + return QString("VidaliaTab"); +} + +void +VidaliaTabPrototype::setLayout(QLayout *layout) +{ + VidaliaTab *obj = qscriptvalue_cast<VidaliaTab *>(thisObject()); + + if(obj) + obj->setLayout(layout); +} + +QVariant +VidaliaTabPrototype::getSetting(QString name, QVariant defaultValue) +{ + VidaliaTab *obj = qscriptvalue_cast<VidaliaTab *>(thisObject()); + + if(obj) + return obj->getSetting(name, defaultValue); +} + +void +VidaliaTabPrototype::saveSetting(QString name, QVariant value) +{ + VidaliaTab *obj = qscriptvalue_cast<VidaliaTab *>(thisObject()); + + if(obj) + obj->saveSetting(name, value); } diff --git a/src/vidalia/plugin/prototypes/VidaliaTabPrototype.h b/src/vidalia/plugin/prototypes/VidaliaTabPrototype.h index dbd89cd..59d640d 100644 --- a/src/vidalia/plugin/prototypes/VidaliaTabPrototype.h +++ b/src/vidalia/plugin/prototypes/VidaliaTabPrototype.h @@ -13,6 +13,12 @@ class VidaliaTabPrototype : public QObject, public QScriptable public: VidaliaTabPrototype(QObject *parent = 0); static QScriptValue constructor(QScriptContext *context, QScriptEngine *engine); + static int metaTypeId(); + static QString name(); + + Q_INVOKABLE void setLayout(QLayout *layout); + Q_INVOKABLE QVariant getSetting(QString name, QVariant defaultValue); + Q_INVOKABLE void saveSetting(QString name, QVariant value); };
Q_DECLARE_METATYPE(VidaliaTab *);
tor-commits@lists.torproject.org