/* * Copyright 2010 Aaron J. Seigo * * 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 "dataenginereceiver.h" #include #include "dataengine.h" #include "scriptenv.h" QSet DataEngineReceiver::s_receivers; DataEngineReceiver::DataEngineReceiver(const Plasma::DataEngine *engine, const QString &source, const QScriptValue &func, QObject *parent) : QObject(parent), m_engine(engine), m_source(source), m_func(func), m_obj(m_func) { s_receivers.insert(this); if (!m_func.isFunction()) { QScriptValue func = m_func.property("dataUpdated"); if (func.isFunction()) { m_func = func; } else { m_obj = QScriptValue(); } } } DataEngineReceiver::~DataEngineReceiver() { s_receivers.remove(this); //kDebug() << s_receivers.count(); } bool DataEngineReceiver::isValid() const { return m_obj.isValid(); } bool DataEngineReceiver::matches(const Plasma::DataEngine *engine, const QString &source, const QScriptValue &v) { return engine == m_engine && m_source == source && v.equals(m_obj); } void DataEngineReceiver::dataUpdated(const QString &source, const Plasma::DataEngine::Data &data) { QScriptEngine *engine = m_func.engine(); // QScriptValue appletValue = engine->globalObject().property("plasmoid"); QScriptValueList args; args << source; args << qScriptValueFromMap(engine, data); m_func.call(m_obj, args); if (engine->hasUncaughtException()) { ScriptEnv *env = ScriptEnv::findScriptEnv(engine); env->checkForErrors(false); } } DataEngineReceiver *DataEngineReceiver::getReceiver(Plasma::DataEngine *dataEngine, const QString &source, const QScriptValue &v) { foreach (DataEngineReceiver *receiver, DataEngineReceiver::s_receivers) { if (receiver->matches(dataEngine, source, v)) { return receiver; } } return 0; } QObject *DataEngineReceiver::extractTargetQObject(QScriptEngine *engine, const QString &source, const QScriptValue &v, Plasma::DataEngine *dataEngine) { QObject *obj = 0; // if it's a function we get, then use that directly // next see if it is a qobject with a good slot; if it is then use that directly // otherwise, try to use the object with a dataUpdated method call if (v.isFunction()) { obj = getReceiver(dataEngine, source, v); if (!obj) { obj = new DataEngineReceiver(dataEngine, source, v, ScriptEnv::findScriptEnv(engine)); } } else if (v.isObject()) { obj = v.toQObject(); if (!obj || obj->metaObject()->indexOfSlot("dataUpdated(QString,Plasma::DataEngine::Data)") == -1) { obj = getReceiver(dataEngine, source, v); if (!obj) { DataEngineReceiver *receiver = new DataEngineReceiver(dataEngine, source, v, ScriptEnv::findScriptEnv(engine)); if (receiver->isValid()) { obj = receiver; } else { delete receiver; } } } } return obj; } QScriptValue DataEngineReceiver::connectAllSources(QScriptContext *context, QScriptEngine *engine) { if (context->argumentCount() < 1) { return engine->undefinedValue(); } DataEngine *dataEngine = qobject_cast(context->thisObject().toQObject()); if (!dataEngine) { return engine->undefinedValue(); } int pollingInterval = 0; Plasma::IntervalAlignment intervalAlignment = Plasma::NoAlignment; if (context->argumentCount() > 1) { pollingInterval = context->argument(2).toInt32(); if (context->argumentCount() > 2) { intervalAlignment = static_cast(context->argument(4).toInt32()); } } QObject *obj = extractTargetQObject(engine, QString(), context->argument(0), dataEngine); if (!obj) { return engine->undefinedValue(); } dataEngine->connectAllSources(obj, pollingInterval, intervalAlignment); return true; } QScriptValue DataEngineReceiver::connectSource(QScriptContext *context, QScriptEngine *engine) { if (context->argumentCount() < 2) { return engine->undefinedValue(); } DataEngine *dataEngine = qobject_cast(context->thisObject().toQObject()); if (!dataEngine) { return engine->undefinedValue(); } const QString source = context->argument(0).toString(); if (source.isEmpty()) { return engine->undefinedValue(); } QObject *obj = extractTargetQObject(engine, source, context->argument(1), dataEngine); if (!obj) { return engine->undefinedValue(); } int pollingInterval = 0; Plasma::IntervalAlignment intervalAlignment = Plasma::NoAlignment; if (context->argumentCount() > 2) { pollingInterval = context->argument(2).toInt32(); if (context->argumentCount() > 3) { intervalAlignment = static_cast(context->argument(4).toInt32()); } } dataEngine->connectSource(source, obj, pollingInterval, intervalAlignment); return true; } QScriptValue DataEngineReceiver::disconnectSource(QScriptContext *context, QScriptEngine *engine) { if (context->argumentCount() < 2) { return engine->undefinedValue(); } DataEngine *dataEngine = qobject_cast(context->thisObject().toQObject()); if (!dataEngine) { //kDebug() << "no engine!"; return engine->undefinedValue(); } const QString source = context->argument(0).toString(); if (source.isEmpty()) { //kDebug() << "no source!"; return engine->undefinedValue(); } QObject *obj = 0; QScriptValue v = context->argument(1); if (v.isQObject()) { obj = v.toQObject(); } else if (v.isObject() || v.isFunction()) { foreach (DataEngineReceiver *receiver, DataEngineReceiver::s_receivers) { if (receiver->matches(dataEngine, source, v)) { obj = receiver; receiver->deleteLater(); break; } } } if (!obj) { //kDebug() << "no object!"; return engine->undefinedValue(); } dataEngine->disconnectSource(source, obj); return true; } #include "dataenginereceiver.moc"