/* * Copyright 2009 by Alan Alpert * Copyright 2010 by Ménard Alexis * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "plasmoid/declarativeappletscript.h" #include "plasmoid/appletinterface.h" #include "common/scriptenv.h" #include "declarative/qmlobject.h" //#include "declarative/declarativeitemcontainer_p.h" #include "declarative/packageaccessmanagerfactory.h" K_EXPORT_PLASMA_APPLETSCRIPTENGINE(declarativeappletscript, DeclarativeAppletScript) QScriptValue constructIconClass(QScriptEngine *engine); QScriptValue constructKUrlClass(QScriptEngine *engine); QScriptValue constructQPointClass(QScriptEngine *engine); void registerSimpleAppletMetaTypes(QScriptEngine *engine); DeclarativeAppletScript::DeclarativeAppletScript(QObject *parent, const QVariantList &args) : AbstractJsAppletScript(parent, args), m_qmlObject(0), m_toolBoxObject(0), m_interface(0), m_env(0), m_auth(this) { Q_UNUSED(args); } DeclarativeAppletScript::~DeclarativeAppletScript() { } bool DeclarativeAppletScript::init() { m_qmlObject = new QmlObject(applet()); m_qmlObject->setInitializationDelayed(true); connect(m_qmlObject, SIGNAL(finished()), this, SLOT(qmlCreationFinished())); //FIXME: what replaced this? //KGlobal::locale()->insertCatalog("plasma_applet_" % description().pluginName()); //make possible to import extensions from the package //FIXME: probably to be removed, would make possible to use native code from within the package :/ //m_qmlObject->engine()->addImportPath(package()->path()+"/contents/imports"); //use our own custom network access manager that will access Plasma packages and to manage security (i.e. deny access to remote stuff when the proper extension isn't enabled QQmlEngine *engine = m_qmlObject->engine(); QQmlNetworkAccessManagerFactory *factory = engine->networkAccessManagerFactory(); engine->setNetworkAccessManagerFactory(0); delete factory; engine->setNetworkAccessManagerFactory(new PackageAccessManagerFactory(package(), &m_auth)); m_qmlObject->setQmlPath(mainScript()); if (!m_qmlObject->engine() || !m_qmlObject->engine()->rootContext() || !m_qmlObject->engine()->rootContext()->isValid() || m_qmlObject->mainComponent()->isError()) { QString reason; foreach (QQmlError error, m_qmlObject->mainComponent()->errors()) { reason += error.toString()+'\n'; } setFailedToLaunch(true, reason); return false; } Plasma::Applet *a = applet(); Plasma::Containment *cont = qobject_cast(a); if (cont) { m_interface = new ContainmentInterface(this); //fail? so it's a normal Applet } else { m_interface = new AppletInterface(this); } connect(applet(), SIGNAL(activate()), this, SLOT(activate())); setupObjects(); m_qmlObject->completeInitialization(); a->setProperty("graphicObject", QVariant::fromValue(m_qmlObject->rootObject())); qDebug() << "Graphic object created:" << a << a->property("graphicObject"); return true; } void DeclarativeAppletScript::qmlCreationFinished() { //If it's a popupapplet and the root object has a "compactRepresentation" component, use that instead of the icon Plasma::Applet *a = applet(); //TODO: access rootItem from m_interface //m_self->setProperty("rootItem", QVariant::fromValue(m_qmlObject->rootObject())); /*TODO: all applets must become pa if (pa) { QQmlComponent *iconComponent = m_qmlObject->rootObject()->property("compactRepresentation").value(); if (iconComponent) { QDeclarativeItem *declarativeIcon = qobject_cast(iconComponent->create(iconComponent->creationContext())); if (declarativeIcon) { pa->setPopupIcon(QIcon()); QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(a); lay->setContentsMargins(0, 0, 0, 0); DeclarativeItemContainer *declarativeItemContainer = new DeclarativeItemContainer(a); lay->addItem(declarativeItemContainer); declarativeItemContainer->setDeclarativeItem(declarativeIcon, true); } else { pa->setPopupIcon(a->icon()); } } else { pa->setPopupIcon(a->icon()); } }*/ Plasma::Containment *pc = qobject_cast(a); if (pc) { Plasma::Package pkg = Plasma::PluginLoader::self()->loadPackage("Plasma/Generic"); pkg.setPath("org.kde.toolbox"); if (pkg.isValid()) { const QString qmlPath = pkg.filePath("mainscript"); m_toolBoxObject = new QmlObject(pc); m_toolBoxObject->setInitializationDelayed(true); m_toolBoxObject->setQmlPath(qmlPath); if (m_toolBoxObject->rootObject()) { m_toolBoxObject->rootObject()->setProperty("plasmoid", QVariant::fromValue(m_interface)); } m_toolBoxObject->completeInitialization(); QObject *containmentGraphicObject = pc->property("graphicObject").value(); if (containmentGraphicObject && m_toolBoxObject->rootObject()) { m_toolBoxObject->rootObject()->setProperty("parent", QVariant::fromValue(containmentGraphicObject)); containmentGraphicObject->setProperty("toolBox", QVariant::fromValue(m_toolBoxObject->rootObject())); } } else { kWarning() << "Could not load org.kde.toolbox package."; } } } QString DeclarativeAppletScript::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); } void DeclarativeAppletScript::configChanged() { if (!m_env) { return; } m_env->callEventListeners("configchanged"); } QObject *DeclarativeAppletScript::loadui(const QString &filename) { QFile f(filename); if (!f.open(QIODevice::ReadOnly)) { kWarning() << i18n("Unable to open '%1'",filename); return 0; } QUiLoader loader; QWidget *w = loader.load(&f); f.close(); return w; } void DeclarativeAppletScript::constraintsEvent(Plasma::Constraints constraints) { if (constraints & Plasma::FormFactorConstraint) { emit formFactorChanged(); } if (constraints & Plasma::LocationConstraint) { emit locationChanged(); } if (constraints & Plasma::ContextConstraint) { emit contextChanged(); } } void DeclarativeAppletScript::popupEvent(bool popped) { if (!m_env) { return; } QScriptValueList args; args << popped; m_env->callEventListeners("popupEvent", args); } void DeclarativeAppletScript::dataUpdated(const QString &name, const Plasma::DataEngine::Data &data) { #if 0 TODO: callEventListeners is broken without qscriptengine if (!m_engine) { return; } QScriptValueList args; args << m_engine->toScriptValue(name) << m_engine->toScriptValue(data); m_env->callEventListeners("dataUpdated", args); #endif } void DeclarativeAppletScript::activate() { #if 0 TODO: callEventListeners is broken without qscriptengine if (!m_env) { return; } m_env->callEventListeners("activate"); #endif } void DeclarativeAppletScript::executeAction(const QString &name) { if (!m_env) { return; } if (m_qmlObject->rootObject()) { QMetaObject::invokeMethod(m_qmlObject->rootObject(), QString("action_" + name).toLatin1(), Qt::DirectConnection); } } bool DeclarativeAppletScript::include(const QString &path) { return m_env->include(path); } ScriptEnv *DeclarativeAppletScript::scriptEnv() { return m_env; } void DeclarativeAppletScript::setupObjects() { m_qmlObject->engine()->rootContext()->setContextProperty("plasmoid", m_interface); #if 0 TODO: make this work with QQmlEngine m_engine = m_qmlObject->scriptEngine(); if (!m_engine) { return; } connect(m_engine, SIGNAL(signalHandlerException(const QScriptValue &)), this, SLOT(signalHandlerException(const QScriptValue &))); delete m_env; m_env = new ScriptEnv(this, m_engine); QScriptValue global = m_engine->globalObject(); QScriptValue v = m_engine->newVariant(QVariant::fromValue(*applet()->package())); global.setProperty("__plasma_package", v, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); m_self = m_engine->newQObject(m_interface); m_self.setScope(global); global.setProperty("plasmoid", m_self); m_env->addMainObjectProperties(m_self); 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); // Add a global loadui method for ui files QScriptValue fun = m_engine->newFunction(DeclarativeAppletScript::loadui); global.setProperty("loadui", fun); ScriptEnv::registerEnums(global, AppletInterface::staticMetaObject); //Make enum values accessible also as plasmoid.Planar etc ScriptEnv::registerEnums(m_self, AppletInterface::staticMetaObject); global.setProperty("dataEngine", m_engine->newFunction(DeclarativeAppletScript::dataEngine)); global.setProperty("service", m_engine->newFunction(DeclarativeAppletScript::service)); global.setProperty("loadService", m_engine->newFunction(DeclarativeAppletScript::loadService)); //Add stuff from Qt //TODO: move to libkdeclarative? ByteArrayClass *baClass = new ByteArrayClass(m_engine); global.setProperty("ByteArray", baClass->constructor()); global.setProperty("QPoint", constructQPointClass(m_engine)); // Add stuff from KDE libs qScriptRegisterSequenceMetaType(m_engine); global.setProperty("Url", constructKUrlClass(m_engine)); // Add stuff from Plasma global.setProperty("Svg", m_engine->newFunction(DeclarativeAppletScript::newPlasmaSvg)); global.setProperty("FrameSvg", m_engine->newFunction(DeclarativeAppletScript::newPlasmaFrameSvg)); if (!m_env->importExtensions(description(), m_self, m_auth)) { return; } registerSimpleAppletMetaTypes(m_engine); QTimer::singleShot(0, this, SLOT(configChanged())); #endif } QObject *DeclarativeAppletScript::dataEngine(const QString &dataEngineName) { return applet()->dataEngine(dataEngineName); } QObject *DeclarativeAppletScript::service(const QString &dataEngine, const QString &source) { Plasma::DataEngine *data = applet()->dataEngine(dataEngine); return data->serviceForSource(source); } QObject *DeclarativeAppletScript::loadService(const QString &pluginName) { return Plasma::PluginLoader::self()->loadService(pluginName, QVariantList(), applet()); } QList DeclarativeAppletScript::contextualActions() { if (!m_interface) { return QList(); } return m_interface->contextualActions(); } QQmlEngine *DeclarativeAppletScript::engine() const { return m_qmlObject->engine(); } #include "declarativeappletscript.moc"