diff --git a/KF5PlasmaConfig.cmake.in b/KF5PlasmaConfig.cmake.in index dee79cadd..9cc5c7842 100644 --- a/KF5PlasmaConfig.cmake.in +++ b/KF5PlasmaConfig.cmake.in @@ -8,6 +8,11 @@ set(Plasma_INSTALL_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@") set(Plasma_LIBRARIES KF5::Plasma) +set(PLASMA_DATAENGINES_PLUGINDIR ${KDE_INSTALL_PLUGINDIR}/plasma/dataengine) +set(PLASMA_PLASMOIDS_PLUGINDIR ${KDE_INSTALL_PLUGINDIR}/plasma/plasmoids) +set(PLASMA_SCRIPTENGINES_PLUGINDIR ${KDE_INSTALL_PLUGINDIR}/plasma/scriptengines) +set(PLASMA_CONTAINMENTACTIONS_PLUGINDIR ${KDE_INSTALL_PLUGINDIR}/plasma/containmentactions) + find_dependency(KF5Package "@KF5_DEP_VERSION@") find_dependency(KF5Service "@KF5_DEP_VERSION@") diff --git a/src/plasma/applet.cpp b/src/plasma/applet.cpp index 2dda38109..895555c52 100644 --- a/src/plasma/applet.cpp +++ b/src/plasma/applet.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -84,10 +83,13 @@ Applet::Applet(QObject *parent, const QString &serviceID, uint appletId) Applet::Applet(QObject *parentObject, const QVariantList &args) : QObject(0), d(new AppletPrivate( - KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString()), 0, + KService::serviceByStorageId(args.count() > 0 && args.first().canConvert() ? args[0].toString() : QString()), 0, args.count() > 1 ? args[1].toInt() : 0, this)) { setParent(parentObject); + if (args.count() > 0 && args.first().canConvert()) { + d->appletDescription = KPluginInfo(args); + } // WARNING: do not access config() OR globalConfig() in this method! // that requires a scene, which is not available at this point diff --git a/src/plasma/containment.cpp b/src/plasma/containment.cpp index 7eabbb855..fef162483 100644 --- a/src/plasma/containment.cpp +++ b/src/plasma/containment.cpp @@ -37,7 +37,6 @@ #include #include #include -#include #include #include diff --git a/src/plasma/containmentactions.cpp b/src/plasma/containmentactions.cpp index f24bdaca3..f42807f05 100644 --- a/src/plasma/containmentactions.cpp +++ b/src/plasma/containmentactions.cpp @@ -33,7 +33,6 @@ #include #include -#include #include "version.h" diff --git a/src/plasma/dataengine.cpp b/src/plasma/dataengine.cpp index 4b3d6713f..e3a9d4bbd 100644 --- a/src/plasma/dataengine.cpp +++ b/src/plasma/dataengine.cpp @@ -33,7 +33,6 @@ #include #include -#include #include #include "datacontainer.h" diff --git a/src/plasma/package.cpp b/src/plasma/package.cpp index 4e0be88ba..e5a83cbbc 100644 --- a/src/plasma/package.cpp +++ b/src/plasma/package.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/src/plasma/packagestructure.cpp b/src/plasma/packagestructure.cpp index b2686b6fb..aaea44cf9 100644 --- a/src/plasma/packagestructure.cpp +++ b/src/plasma/packagestructure.cpp @@ -129,7 +129,7 @@ void PackageStructurePrivate::installPathChanged(const QString &path) // used by the installing app in any case, and the // package is properly installed - aseigo - //TODO: reduce code duplication with registerPackage below + //TODO: remove installation of the desktop file in kservices5 when possible const QString serviceName = servicePrefix + pluginName + ".desktop"; diff --git a/src/plasma/pluginloader.cpp b/src/plasma/pluginloader.cpp index 0ce349a7e..a5d26ab41 100644 --- a/src/plasma/pluginloader.cpp +++ b/src/plasma/pluginloader.cpp @@ -56,10 +56,13 @@ class PluginLoaderPrivate public: PluginLoaderPrivate() : isDefaultLoader(false), - dataEnginePluginDir("plasma/dataengine"), - packageStructurePluginDir("plasma/packagestructure"), packageRE("[^a-zA-Z0-9\\-_]") { + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/Applet", new PlasmoidPackage()); + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/DataEngine", new DataEnginePackage()); + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/Theme", new ThemePackage()); + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/ContainmentActions", new ContainmentActionsPackage()); + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/Generic", new GenericPackage()); } static QSet knownCategories(); @@ -68,13 +71,23 @@ public: static QSet s_customCategories; QHash > structures; bool isDefaultLoader; - QString dataEnginePluginDir; - QString packageStructurePluginDir; + + static QString s_dataEnginePluginDir; + static QString s_packageStructurePluginDir; + static QString s_plasmoidsPluginDir; + static QString s_servicesPluginDir; + static QString s_containmentActionsPluginDir; QRegExp packageRE; }; QSet PluginLoaderPrivate::s_customCategories; +QString PluginLoaderPrivate::s_dataEnginePluginDir("plasma/dataengine"); +QString PluginLoaderPrivate::s_packageStructurePluginDir("plasma/packagestructure"); +QString PluginLoaderPrivate::s_plasmoidsPluginDir("plasma/applets"); +QString PluginLoaderPrivate::s_servicesPluginDir("plasma/services"); +QString PluginLoaderPrivate::s_containmentActionsPluginDir("plasma/containmentactions"); + QSet PluginLoaderPrivate::knownCategories() { // this is to trick the tranlsation tools into making the correct @@ -167,79 +180,85 @@ Applet *PluginLoader::loadApplet(const QString &name, uint appletId, const QVari return applet; } - // the application-specific appletLoader failed to create an applet, here we try with our own logic. - const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); - - bool isContainment = false; - if (offers.isEmpty()) { - //TODO: what would be -really- cool is offer to try and download the applet - // from the network at this point - offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint); - if (offers.count() > 0) { - isContainment = true; - } - } - - if (offers.isEmpty()) { -#ifndef NDEBUG - // qDebug() << "offers is empty for " << name; -#endif - return 0; - } - -#ifndef NDEBUG - if (offers.count() > 1) { - // qDebug() << "hey! we got more than one! let's blindly take the first one"; - } -#endif - - KService::Ptr offer = offers.first(); - if (appletId == 0) { appletId = ++AppletPrivate::s_maxAppletId; } - QVariantList allArgs; - allArgs << offer->storageId() << appletId << args; - if (!offer->property("X-Plasma-API").toString().isEmpty() && - offer->property("Library").toString().isEmpty()) { -#ifndef NDEBUG - // qDebug() << "we have a script using the" - // << offer->property("X-Plasma-API").toString() << "API"; -#endif - if (isContainment) { - return new Containment(0, allArgs); - } else { - if (offer->serviceTypes().contains("Plasma/Containment")) { - return new Containment(0, allArgs); - } else { - return new Applet(0, allArgs); - } + + + // Look for C++ plugins first + auto filter = [&name](const KPluginMetaData &md) -> bool + { + return md.pluginId() == name; + }; + QVector plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_plasmoidsPluginDir, filter); + + if (plugins.count()) { + KPluginInfo::List lst = KPluginInfo::fromMetaData(plugins); + KPluginLoader loader(lst.first().libraryPath()); + if (!Plasma::isPluginVersionCompatible(loader.pluginVersion())) { + return 0; + } + KPluginFactory *factory = loader.factory(); + if (factory) { + QVariantList allArgs; + allArgs << loader.metaData().toVariantMap() << appletId << args; + applet = factory->create(0, allArgs); + } + } + if (applet) { + return applet; + } + + + KPackage::Package p = KPackage::PackageLoader::self()->loadPackage("Plasma/Applet", name); + if (!p.isValid()) { + //some applets have actually the root path from another package, such as icontasks + //try to do a fallback package with X-Plasma-RootPath root + p.setRequired("mainscript", false); + p.setPath(name); + + KPluginMetaData md(p.filePath("metadata")); + const KPackage::Package fp = KPackage::PackageLoader::self()->loadPackage("Plasma/Applet", md.value("X-Plasma-RootPath")); + p.setFallbackPackage(fp); + + if (!fp.isValid()) { + return 0; } } - KPluginLoader plugin(*offer); - - if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion())) { - return 0; + // backwards compatibility: search in the root plugins directory + // TODO: remove when Plasma 5.4 is released + { + KPluginInfo info = KPluginInfo::fromMetaData(p.metadata()); + KPluginLoader loader(info.libraryPath()); + if (!Plasma::isPluginVersionCompatible(loader.pluginVersion())) { + return 0; + } + KPluginFactory *factory = loader.factory(); + if (factory) { + QVariantList allArgs; + allArgs << loader.metaData().toVariantMap() << appletId << args; + applet = factory->create(0, allArgs); + } + if (applet) { + return applet; + } } - QString error; - applet = offer->createInstance(0, allArgs, &error); if (!applet) { - qWarning() << "Could not load applet" << name << "! reason given:" << error <<"Falling back to an empty one"; + qWarning() << "Could not load applet" << name << "Falling back to an empty one"; - if (isContainment) { + QVariantList allArgs; + allArgs << p.metadata().fileName() << appletId << args; + + if (p.metadata().serviceTypes().contains("Plasma/Containment")) { return new Containment(0, allArgs); } else { - if (offer->serviceTypes().contains("Plasma/Containment")) { - return new Containment(0, allArgs); - } else { - return new Applet(0, allArgs); - } + return new Applet(0, allArgs); } + } return applet; @@ -257,7 +276,7 @@ DataEngine *PluginLoader::loadDataEngine(const QString &name) { return md.pluginId() == name; }; - QVector plugins = KPluginLoader::findPlugins(d->dataEnginePluginDir, filter); + QVector plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_dataEnginePluginDir, filter); if (plugins.count()) { KPluginInfo::List lst = KPluginInfo::fromMetaData(plugins); @@ -272,41 +291,40 @@ DataEngine *PluginLoader::loadDataEngine(const QString &name) return engine; } - // Fall back to querying scripted plugins - QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name); - - // First check with KServiceTypeTrader as that is where scripted engines will be - KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", constraint); - - if (!offers.isEmpty()) { - const QString api = offers.first()->property("X-Plasma-API").toString(); - if (!api.isEmpty()) { - // it is a scripted plugin, load it via a package - engine = new DataEngine(KPluginInfo(offers.first()), 0); - } + const KPackage::Package p = KPackage::PackageLoader::self()->loadPackage("Plasma/DataEngine", name); + if (!p.isValid()) { + return 0; } - return engine; + return new DataEngine(KPluginInfo(p.metadata().fileName()), 0); } QStringList PluginLoader::listAllEngines(const QString &parentApp) { - QString constraint; - - if (parentApp.isEmpty()) { - constraint.append("(not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '')"); - } else { - constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'"); + if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/DataEngine")) { + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/DataEngine", new DataEnginePackage()); } - KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", constraint); - QStringList engines; - foreach (const KService::Ptr &service, offers) { - QString name = service->property("X-KDE-PluginInfo-Name").toString(); - if (!name.isEmpty()) { - engines.append(name); - } + // Look for C++ plugins first + auto filter = [&parentApp](const KPluginMetaData &md) -> bool + { + return md.value("X-KDE-ParentApp") == parentApp; + }; + QVector plugins; + if (parentApp.isEmpty()) { + plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_dataEnginePluginDir); + } else { + plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_dataEnginePluginDir, filter); + } + + for (auto plugin : plugins) { + engines << plugin.pluginId(); + } + + const QList packagePlugins = KPackage::PackageLoader::self()->listPackages("Plasma/DataEngine"); + for (auto plugin : packagePlugins) { + engines << plugin.pluginId(); } return engines; @@ -314,21 +332,44 @@ QStringList PluginLoader::listAllEngines(const QString &parentApp) KPluginInfo::List PluginLoader::listEngineInfo(const QString &parentApp) { + if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/DataEngine")) { + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/DataEngine", new DataEnginePackage()); + } return PluginLoader::self()->listDataEngineInfo(parentApp); } KPluginInfo::List PluginLoader::listEngineInfoByCategory(const QString &category, const QString &parentApp) { - QString constraint = QString("[X-KDE-PluginInfo-Category] == '%1'").arg(category); - - if (parentApp.isEmpty()) { - constraint.append(" and not exist [X-KDE-ParentApp]"); - } else { - constraint.append(" and [X-KDE-ParentApp] == '").append(parentApp).append("'"); + if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/DataEngine")) { + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/DataEngine", new DataEnginePackage()); } - KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", constraint); - return KPluginInfo::fromServices(offers); + KPluginInfo::List list; + + // Look for C++ plugins first + auto filterNormal = [&category](const KPluginMetaData &md) -> bool + { + return md.value("X-KDE-PluginInfo-Category") == category; + }; + auto filterParentApp = [&category, &parentApp](const KPluginMetaData &md) -> bool + { + return md.value("X-KDE-ParentApp") == parentApp && md.value("X-KDE-PluginInfo-Category") == category; + }; + QVector plugins; + if (parentApp.isEmpty()) { + plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_dataEnginePluginDir, filterNormal); + } else { + plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_dataEnginePluginDir, filterParentApp); + } + + list = KPluginInfo::fromMetaData(plugins); + + + //TODO FIXME: PackageLoader needs to have a function to inject packageStructures + const QList packagePlugins = KPackage::PackageLoader::self()->listPackages("Plasma/DataEngine"); + list << KPluginInfo::fromMetaData(packagePlugins.toVector()); + + return list; } Service *PluginLoader::loadService(const QString &name, const QVariantList &args, QObject *parent) @@ -345,35 +386,34 @@ Service *PluginLoader::loadService(const QString &name, const QVariantList &args return new Storage(parent); } - QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Service", constraint); - if (offers.isEmpty()) { -#ifndef NDEBUG - // qDebug() << "offers is empty for " << name; -#endif + // Look for C++ plugins first + auto filter = [&name](const KPluginMetaData &md) -> bool + { + return md.pluginId() == name; + }; + QVector plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_servicesPluginDir, filter); + + if (plugins.count()) { + KPluginInfo::List lst = KPluginInfo::fromMetaData(plugins); + KPluginLoader loader(lst.first().libraryPath()); + if (!Plasma::isPluginVersionCompatible(loader.pluginVersion())) { + return 0; + } + KPluginFactory *factory = loader.factory(); + if (factory) { + service = factory->create(0, args); + } + } + + if (service) { + if (service->name().isEmpty()) { + service->setName(name); + } + return service; + } else { return new NullService(name, parent); } - - KService::Ptr offer = offers.first(); - QString error; - - if (Plasma::isPluginVersionCompatible(KPluginLoader(*offer).pluginVersion())) { - service = offer->createInstance(parent, args, &error); - } - - if (!service) { -#ifndef NDEBUG - // qDebug() << "Couldn't load Service \"" << name << "\"! reason given: " << error; -#endif - return new NullService(name, parent); - } - - if (service->name().isEmpty()) { - service->setName(name); - } - - return service; } ContainmentActions *PluginLoader::loadContainmentActions(Containment *parent, const QString &name, const QVariantList &args) @@ -387,6 +427,29 @@ ContainmentActions *PluginLoader::loadContainmentActions(Containment *parent, co return actions; } + + // Look for C++ plugins first + auto filter = [&name](const KPluginMetaData &md) -> bool + { + return md.pluginId() == name; + }; + QVector plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_containmentActionsPluginDir, filter); + + if (plugins.count()) { + KPluginInfo::List lst = KPluginInfo::fromMetaData(plugins); + KPluginLoader loader(lst.first().libraryPath()); + const QVariantList argsWithMetaData = QVariantList() << loader.metaData().toVariantMap(); + KPluginFactory *factory = loader.factory(); + if (factory) { + actions = factory->create(0, argsWithMetaData); + } + } + if (actions) { + return actions; + } + + //FIXME: this is only for backwards compatibility, but probably will have to stay + //for the time being QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name); KService::List offers = KServiceTypeTrader::self()->query("Plasma/ContainmentActions", constraint); @@ -468,7 +531,7 @@ Package PluginLoader::loadPackage(const QString &packageFormat, const QString &s //fallback to old structures } else { const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(packageFormat); - structure = KPluginTrader::createInstanceFromQuery(d->packageStructurePluginDir, "Plasma/PackageStructure", constraint, 0); + structure = KPluginTrader::createInstanceFromQuery(PluginLoaderPrivate::s_packageStructurePluginDir, "Plasma/PackageStructure", constraint, 0); if (structure) { structure->d->internalStructure = new PackageStructureWrapper(structure); } @@ -495,45 +558,70 @@ KPluginInfo::List PluginLoader::listAppletInfo(const QString &category, const QS list = internalAppletInfo(category); } - QString constraint = PluginLoaderPrivate::parentAppConstraint(parentApp); - - //note: constraint guaranteed non-empty from here down + //FIXME: this assumes we are always use packages.. no pure c++ if (category.isEmpty()) { //use all but the excluded categories KConfigGroup group(KSharedConfig::openConfig(), "General"); QStringList excluded = group.readEntry("ExcludeCategories", QStringList()); - foreach (const QString &category, excluded) { - constraint.append(" and [X-KDE-PluginInfo-Category] != '").append(category).append("'"); + + auto filter = [&excluded, &parentApp](const KPluginMetaData &md) -> bool + { + const QString pa = md.value("X-KDE-ParentApp"); + return (pa.isEmpty() || pa == parentApp) && !excluded.contains(md.category()); + }; + + //NOTE: it still produces kplugininfos from KServices because some user code expects + //info.sevice() to be valid and would crash ohtherwise + for (auto md : KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter)) { + list << KPluginInfo(KService::serviceByStorageId(md.metaDataFileName())); } + return list; + + } else { //specific category (this could be an excluded one - is that bad?) - constraint.append(" and ").append("[X-KDE-PluginInfo-Category] == '").append(category).append("'"); - if (category == "Miscellaneous") { - constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')"); + + auto filter = [&category, &parentApp](const KPluginMetaData &md) -> bool + { + const QString pa = md.value("X-KDE-ParentApp"); + if (category == "Miscellaneous") { + return (pa.isEmpty() || pa == parentApp) && (md.category() == category || md.category().isEmpty()); + } else { + return (pa.isEmpty() || pa == parentApp) && md.category() == category; + } + }; + + //NOTE: it still produces kplugininfos from KServices because some user code expects + //info.sevice() to be valid and would crash ohtherwise + for (auto md : KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter)) { + list << KPluginInfo(KService::serviceByStorageId(md.metaDataFileName())); } + return list; } - - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); - - //qDebug() << "Applet::listAppletInfo constraint was '" << constraint - // << "' which got us " << offers.count() << " matches"; - return KPluginInfo::fromServices(offers); } KPluginInfo::List PluginLoader::listAppletInfoForMimeType(const QString &mimeType) { - QString constraint = PluginLoaderPrivate::parentAppConstraint(); - constraint.append(QString(" and '%1' in [X-Plasma-DropMimeTypes]").arg(mimeType)); - //qDebug() << "listAppletInfoForMimetype with" << mimeType << constraint; - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); - return KPluginInfo::fromServices(offers); + auto filter = [&mimeType](const KPluginMetaData &md) -> bool + { + return md.value("X-Plasma-DropMimeTypes").contains(mimeType); + }; + return KPluginInfo::fromMetaData(KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter).toVector()); } KPluginInfo::List PluginLoader::listAppletInfoForUrl(const QUrl &url) { - QString constraint = PluginLoaderPrivate::parentAppConstraint(); - constraint.append(" and exist [X-Plasma-DropUrlPatterns]"); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); + QString parentApp; + QCoreApplication *app = QCoreApplication::instance(); + if (app) { + parentApp = app->applicationName(); + } + + auto filter = [&parentApp](const KPluginMetaData &md) -> bool + { + const QString pa = md.value("X-KDE-ParentApp"); + return (pa.isEmpty() || pa == parentApp) && !md.value("X-Plasma-DropUrlPatterns").isEmpty(); + }; + KPluginInfo::List allApplets = KPluginInfo::fromMetaData(KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter).toVector()); - KPluginInfo::List allApplets = KPluginInfo::fromServices(offers); KPluginInfo::List filtered; foreach (const KPluginInfo &info, allApplets) { QStringList urlPatterns = info.property("X-Plasma-DropUrlPatterns").toStringList(); @@ -554,44 +642,26 @@ KPluginInfo::List PluginLoader::listAppletInfoForUrl(const QUrl &url) QStringList PluginLoader::listAppletCategories(const QString &parentApp, bool visibleOnly) { - QString constraint = PluginLoaderPrivate::parentAppConstraint(parentApp); - constraint.append(" and exist [X-KDE-PluginInfo-Category]"); - KConfigGroup group(KSharedConfig::openConfig(), "General"); const QStringList excluded = group.readEntry("ExcludeCategories", QStringList()); - foreach (const QString &category, excluded) { - constraint.append(" and [X-KDE-PluginInfo-Category] != '").append(category).append("'"); - } + auto filter = [&parentApp, &excluded, visibleOnly](const KPluginMetaData &md) -> bool + { + const QString pa = md.value("X-KDE-ParentApp"); + return (pa.isEmpty() || pa == parentApp) && (excluded.isEmpty() || excluded.contains(md.value("X-KDE-PluginInfo-Category"))) && (!visibleOnly || !md.isHidden()); + }; + QList allApplets = KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); QStringList categories; - QSet known = PluginLoaderPrivate::knownCategories(); - foreach (const KService::Ptr &applet, offers) { - QString appletCategory = applet->property("X-KDE-PluginInfo-Category").toString(); - if (visibleOnly && applet->noDisplay()) { - // we don't want to show the hidden category - continue; - } - - //qDebug() << " and we have " << appletCategory; - if (!appletCategory.isEmpty() && !known.contains(appletCategory.toLower())) { -#ifndef NDEBUG - // qDebug() << "Unknown category: " << applet->name() << "says it is in the" - // << appletCategory << "category which is unknown to us"; -#endif - appletCategory.clear(); - } - - if (appletCategory.isEmpty()) { + for (auto plugin : allApplets) { + if (plugin.category().isEmpty()) { if (!categories.contains(i18nc("misc category", "Miscellaneous"))) { categories << i18nc("misc category", "Miscellaneous"); } - } else if (!categories.contains(appletCategory)) { - categories << appletCategory; + } else { + categories << plugin.category(); } } - categories.sort(); return categories; } @@ -612,14 +682,12 @@ QString PluginLoader::appletCategory(const QString &appletName) return QString(); } - const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); - - if (offers.isEmpty()) { + const KPackage::Package p = KPackage::PackageLoader::self()->loadPackage("Plasma/Applet", appletName); + if (!p.isValid()) { return QString(); } - return offers.first()->property("X-KDE-PluginInfo-Category").toString(); + return p.metadata().category(); } KPluginInfo::List PluginLoader::listContainments(const QString &category, @@ -632,53 +700,54 @@ KPluginInfo::List PluginLoader::listContainmentsOfType(const QString &type, const QString &category, const QString &parentApp) { - QString constraint; - - if (parentApp.isEmpty()) { - constraint.append("(not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '')"); - } else { - constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'"); + if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/Applet")) { + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/Applet", new DataEnginePackage()); } - if (!type.isEmpty()) { - if (!constraint.isEmpty()) { - constraint.append(" and ("); + KConfigGroup group(KSharedConfig::openConfig(), "General"); + const QStringList excluded = group.readEntry("ExcludeCategories", QStringList()); + auto filter = [&type, &category, &parentApp](const KPluginMetaData &md) -> bool + { + if (!md.serviceTypes().contains("Plasma/Containment")) { + return false; + } + const QString pa = md.value("X-KDE-ParentApp"); + if (!pa.isEmpty() && pa != parentApp) { + return false; } - //constraint.append("'").append(type).append("' == [X-Plasma-ContainmentType]"); - if (type == "Desktop") { - constraint += "not exist [X-Plasma-ContainmentType] or "; - } - constraint += "[X-Plasma-ContainmentType] == '" + type + "')"; - //by default containments are Desktop, so is not mandatory to specify it - } - - if (!category.isEmpty()) { - if (!constraint.isEmpty()) { - constraint.append(" and "); + if (!type.isEmpty() && md.value("X-Plasma-ContainmentType") != type) { + return false; } - constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'"); - if (category == "Miscellaneous") { - constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')"); + if (!category.isEmpty() && md.value("X-KDE-PluginInfo-Category") != category) { + return false; } - } - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint); - // qDebug() << "constraint was" << constraint << "which got us" << offers.count() << "matches"; - return KPluginInfo::fromServices(offers); + return true; + }; + + return KPluginInfo::fromMetaData(KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter).toVector()); } KPluginInfo::List PluginLoader::listContainmentsForMimeType(const QString &mimeType) { - const QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimeType); - //qDebug() << mimeType << constraint; - const KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint); - return KPluginInfo::fromServices(offers); + if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/Applet")) { + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/Applet", new DataEnginePackage()); + } + auto filter = [&mimeType](const KPluginMetaData &md) -> bool + { + return md.value("X-KDE-ServiceTypes").contains("Plasma/Containment") && md.value("X-Plasma-DropMimeTypes").contains(mimeType); + }; + + return KPluginInfo::fromMetaData(KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter).toVector()); } QStringList PluginLoader::listContainmentTypes() { + if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/Applet")) { + KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/Applet", new DataEnginePackage()); + } KPluginInfo::List containmentInfos = listContainments(); QSet types; @@ -707,7 +776,7 @@ KPluginInfo::List PluginLoader::listDataEngineInfo(const QString &parentApp) constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'"); } - list.append(KPluginTrader::self()->query(d->dataEnginePluginDir, "Plasma/DataEngine", constraint)); + list.append(KPluginTrader::self()->query(PluginLoaderPrivate::s_dataEnginePluginDir, "Plasma/DataEngine", constraint)); return list; } @@ -726,8 +795,22 @@ KPluginInfo::List PluginLoader::listContainmentActionsInfo(const QString &parent constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'"); } + list.append(KPluginTrader::self()->query(PluginLoaderPrivate::s_containmentActionsPluginDir, "Plasma/ContainmentActions", constraint)); + + QSet knownPlugins; + foreach (const KPluginInfo &p, list) { + knownPlugins.insert(p.pluginName()); + } + + //FIXME: this is only for backwards compatibility, but probably will have to stay + //for the time being KService::List offers = KServiceTypeTrader::self()->query("Plasma/ContainmentActions", constraint); - return KPluginInfo::fromServices(offers); + foreach (KService::Ptr s, offers) { + if (!knownPlugins.contains(s->pluginKeyword())) { + list.append(KPluginInfo(s)); + } + } + return list; } Applet *PluginLoader::internalLoadApplet(const QString &name, uint appletId, const QVariantList &args) diff --git a/src/plasma/private/applet_p.cpp b/src/plasma/private/applet_p.cpp index 2cbfd0661..e2a15b610 100644 --- a/src/plasma/private/applet_p.cpp +++ b/src/plasma/private/applet_p.cpp @@ -35,7 +35,8 @@ #include #include #include -#include +#include +#include #include "containment.h" #include "corona.h" @@ -176,16 +177,17 @@ void AppletPrivate::init(const QString &packagePath, const QVariantList &args) QString constraint; QStringList provides = q->pluginInfo().property("X-Plasma-Provides").value(); if (!provides.isEmpty()) { - bool first = true; - foreach (const QString &prov, provides) { - if (!first) { - constraint += " or "; + auto filter = [&provides](const KPluginMetaData &md) -> bool + { + foreach (const QString &p, provides) { + if (md.value("X-Plasma-Provides").contains(p)) { + return true; + } } - first = false; - constraint += "'" + prov + "' in [X-Plasma-Provides]"; - } + return false; + }; + QList applets = KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter); - KPluginInfo::List applets = KPluginInfo::fromServices(KServiceTypeTrader::self()->query("Plasma/Applet", constraint)); if (applets.count() > 1) { QAction *a = new QAction(QIcon::fromTheme("preferences-desktop-default-applications"), i18n("Alternatives..."), q); q->actions()->addAction("alternatives", a); @@ -457,7 +459,7 @@ QString AppletPrivate::globalName() const return QString(); } - return appletDescription.service()->library(); + return appletDescription.pluginName(); } void AppletPrivate::scheduleConstraintsUpdate(Plasma::Types::Constraints c) diff --git a/src/plasma/private/dataenginemanager.cpp b/src/plasma/private/dataenginemanager.cpp index b9c5d8efa..48bd0a906 100644 --- a/src/plasma/private/dataenginemanager.cpp +++ b/src/plasma/private/dataenginemanager.cpp @@ -24,7 +24,6 @@ #include -#include #include #include "datacontainer.h" diff --git a/src/plasma/scripting/appletscript.h b/src/plasma/scripting/appletscript.h index 863d70702..ada7bad42 100644 --- a/src/plasma/scripting/appletscript.h +++ b/src/plasma/scripting/appletscript.h @@ -170,6 +170,9 @@ private: #define K_EXPORT_PLASMA_APPLETSCRIPTENGINE(libname, classname) \ K_PLUGIN_FACTORY(factory, registerPlugin();) +#define K_EXPORT_PLASMA_APPLETSCRIPTENGINE_WITH_JSON(libname, classname, jsonFile) \ + K_PLUGIN_FACTORY_WITH_JSON(factory, jsonFile, registerPlugin();) \ + K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION) } //Plasma namespace #endif diff --git a/src/plasma/scripting/dataenginescript.h b/src/plasma/scripting/dataenginescript.h index f7ad3c2f7..3d15381eb 100644 --- a/src/plasma/scripting/dataenginescript.h +++ b/src/plasma/scripting/dataenginescript.h @@ -146,6 +146,9 @@ private: #define K_EXPORT_PLASMA_DATAENGINESCRIPTENGINE(libname, classname) \ K_PLUGIN_FACTORY(factory, registerPlugin();) +#define K_EXPORT_PLASMA_DATAENGINESCRIPTENGINE_WITH_JSON(libname, classname, jsonFile) \ + K_PLUGIN_FACTORY_WITH_JSON(factory, jsonFile, registerPlugin();) \ + K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION) } //Plasma namespace #endif diff --git a/src/plasma/scripting/scriptengine.cpp b/src/plasma/scripting/scriptengine.cpp index cc407e723..5b2cf8404 100644 --- a/src/plasma/scripting/scriptengine.cpp +++ b/src/plasma/scripting/scriptengine.cpp @@ -21,7 +21,6 @@ #include #include -#include #include "applet.h" #include "dataengine.h" @@ -61,119 +60,50 @@ QString ScriptEngine::mainScript() const QStringList knownLanguages(Types::ComponentTypes types) { - QString constraintTemplate = "'%1' in [X-Plasma-ComponentTypes]"; - QString constraint; - - if (types & Types::AppletComponent) { - // currently this if statement is not needed, but this future proofs - // the code against someone initializing constraint to something - // before we get here. - if (!constraint.isEmpty()) { - constraint.append(" or "); - } - - constraint.append(constraintTemplate.arg("Applet")); - } - - if (types & Types::DataEngineComponent) { - if (!constraint.isEmpty()) { - constraint.append(" or "); - } - - constraint.append(constraintTemplate.arg("DataEngine")); - } - - KService::List offers = KServiceTypeTrader::self()->query("Plasma/ScriptEngine", constraint); - //qDebug() << "Applet::knownApplets constraint was '" << constraint - // << "' which got us " << offers.count() << " matches"; - QStringList languages; - foreach (const KService::Ptr &service, offers) { - QString language = service->property("X-Plasma-API").toString(); - if (!languages.contains(language)) { - languages.append(language); + QVector plugins = KPluginLoader::findPlugins("plasma/scriptengines"); + + for (auto plugin : plugins) { + if ((types & Types::AppletComponent) && + plugin.value("X-Plasma-ComponentTypes") == "Applet") { + languages << plugin.value("X-Plasma-API"); + } else if ((types & Types::DataEngineComponent) && + plugin.value("X-Plasma-ComponentTypes") == "DataEngine") { + languages << plugin.value("X-Plasma-API"); } } return languages; } -KService::List engineOffers(const QString &language, Types::ComponentType type) -{ - if (language.isEmpty()) { - return KService::List(); - } - - QRegExp re("[^a-zA-Z0-9\\-_]"); - if (re.indexIn(language) != -1) { -#ifndef NDEBUG - // qDebug() << "invalid language attempted:" << language; -#endif - return KService::List(); - } - - QString component; - switch (type) { - case Types::AppletComponent: - component = "Applet"; - break; - case Types::DataEngineComponent: - component = "DataEngine"; - break; - default: - return KService::List(); - break; - } - - QString constraint = QString("[X-Plasma-API] == '%1' and " - "'%2' in [X-Plasma-ComponentTypes]").arg(language, component); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/ScriptEngine", constraint); - /* // qDebug() << "********************* loadingApplet with Plasma/ScriptEngine" << constraint - << "resulting in" << offers.count() << "results";*/ - if (offers.isEmpty()) { -#ifndef NDEBUG - // qDebug() << "No offers for \"" << language << "\""; -#endif - } - - return offers; -} - ScriptEngine *loadEngine(const QString &language, Types::ComponentType type, QObject *parent, const QVariantList &args = QVariantList()) { - KService::List offers = engineOffers(language, type); - - QString error; - ScriptEngine *engine = 0; - foreach (const KService::Ptr &service, offers) { - switch (type) { - case Types::AppletComponent: - engine = service->createInstance(parent, args, &error); - break; - case Types::DataEngineComponent: - engine = service->createInstance(parent, args, &error); - break; - default: + + auto filter = [&language](const KPluginMetaData &md) -> bool + { + return md.value("X-Plasma-API") == language; + }; + QVector plugins = KPluginLoader::findPlugins("plasma/scriptengines", filter); + + if (plugins.count()) { + if ((type & Types::AppletComponent) && + plugins.first().value("X-Plasma-ComponentTypes") != "Applet") { + return 0; + } else if ((type & Types::DataEngineComponent) && + plugins.first().value("X-Plasma-ComponentTypes") != "DataEngine") { return 0; - break; } - - if (engine) { - return engine; + KPluginInfo::List lst = KPluginInfo::fromMetaData(plugins); + KPluginLoader loader(lst.first().libraryPath()); + KPluginFactory *factory = loader.factory(); + if (factory) { + engine = factory->create(0, args); } - -#ifndef NDEBUG - // qDebug() << "Couldn't load script engine for language " << language - // << "! error reported: " << error; -#endif } - // Try installing the engine. However, it's too late for this request. - ComponentInstaller::self()->installMissingComponent("scriptengine", language); - - return 0; + return engine; } AppletScript *loadScriptEngine(const QString &language, Applet *applet, const QVariantList &args) diff --git a/src/plasma/service.cpp b/src/plasma/service.cpp index 3e9d8529e..9815c71f0 100644 --- a/src/plasma/service.cpp +++ b/src/plasma/service.cpp @@ -27,7 +27,6 @@ #include #include -#include #include #include #include diff --git a/src/plasma/service.h b/src/plasma/service.h index b5d9b5a26..19cc965d2 100644 --- a/src/plasma/service.h +++ b/src/plasma/service.h @@ -232,5 +232,9 @@ Q_DECLARE_METATYPE(Plasma::Service *) K_PLUGIN_FACTORY(factory, registerPlugin();) \ K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION) +#define K_EXPORT_PLASMA_SERVICE_WITH_JSON(libname, classname, jsonFile) \ + K_PLUGIN_FACTORY_WITH_JSON(factory, jsonFile, registerPlugin();) \ + K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION) + #endif // multiple inclusion guard diff --git a/src/plasmapkg/plasmapkg.cpp b/src/plasmapkg/plasmapkg.cpp index d6063657e..cea331ce4 100644 --- a/src/plasmapkg/plasmapkg.cpp +++ b/src/plasmapkg/plasmapkg.cpp @@ -22,15 +22,17 @@ #include #include -#include +#include #include #include #include #include +#include #include #include #include +#include #include #include @@ -254,28 +256,20 @@ void PlasmaPkg::runMain() d->packageRoot = "kwin/scripts/"; d->servicePrefix = "kwin-script-"; d->pluginTypes << "KWin/Script"; - } else { /* if (KSycoca::isAvailable()) */ - const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(type); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/PackageStructure", constraint); - if (offers.isEmpty()) { + + //do it trough normal plugin loading + } else { + Plasma::Package p = Plasma::PluginLoader::self()->loadPackage(type); + if (!p.hasValidStructure()) { d->coutput(i18n("Could not find a suitable installer for package of type %1", type)); exit(5); return; } - qWarning() << "custom PackageStructure plugins not ported"; - KService::Ptr offer = offers.first(); - QString error; - d->installer = new Plasma::Package(offer->createInstance(0, QVariantList(), &error)); - - if (!d->installer) { - d->coutput(i18n("Could not load installer for package of type %1. Error reported was: %2", - d->parser->value("type"), error)); - return; - } + d->installer = new Plasma::Package(p); //d->packageRoot = d->installer->defaultPackageRoot(); - //pluginTypes << d->installer->type(); + d->pluginTypes << type; } if (d->parser->isSet("show")) { const QString pluginName = d->package; @@ -442,9 +436,9 @@ QStringList PlasmaPkgPrivate::packages(const QStringList &types) } } - const KService::List services = KServiceTypeTrader::self()->query(type); - foreach (const KService::Ptr &service, services) { - const QString _plugin = service->property("X-KDE-PluginInfo-Name", QVariant::String).toString(); + const QList plugins = KPackage::PackageLoader::self()->listPackages(type); + for (auto plugin : plugins) { + const QString _plugin = plugin.pluginId(); if (!result.contains(_plugin)) { result << _plugin; } @@ -584,17 +578,14 @@ void PlasmaPkgPrivate::listTypes() builtIns.insert(i18n("KWin Script"), QStringList() << "KWin/Script" << "kwin/scripts/" << "kwinscript"); renderTypeTable(builtIns); - KService::List offers; - //if (KSycoca::isAvailable()) { - offers = KServiceTypeTrader::self()->query("Plasma/PackageStructure"); - //} + const KPluginInfo::List offers = KPluginTrader::self()->query("kpackage/packagestructure", "KPackage/PackageStructure"); + if (!offers.isEmpty()) { std::cout << std::endl; coutput(i18n("Provided by plugins:")); QMap plugins; - foreach (const KService::Ptr service, offers) { - KPluginInfo info(service); + for (auto info : offers) { //const QString proot = ""; //Plasma::PackageStructure* structure = Plasma::PackageStructure::load(info.pluginName()); QString name = info.name(); @@ -602,7 +593,7 @@ void PlasmaPkgPrivate::listTypes() QString plugin = info.pluginName(); //QString path = structure->defaultPackageRoot(); //QString path = defaultPackageRoot; - plugins.insert(name, QStringList() << plugin); + plugins.insert(name, QStringList() << name << plugin << comment); //qDebug() << "KService stuff:" << name << plugin << comment; } diff --git a/src/scriptengines/CMakeLists.txt b/src/scriptengines/CMakeLists.txt index f566406a2..e27b473ce 100644 --- a/src/scriptengines/CMakeLists.txt +++ b/src/scriptengines/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory(qml) -add_subdirectory(ruby) +#add_subdirectory(ruby) # Re-enable when we have Python bindings for libplasma #if (PYTHONLIBRARY_FOUND AND NOT WIN32) diff --git a/src/scriptengines/qml/CMakeLists.txt b/src/scriptengines/qml/CMakeLists.txt index e7130db72..2aedf0b69 100644 --- a/src/scriptengines/qml/CMakeLists.txt +++ b/src/scriptengines/qml/CMakeLists.txt @@ -19,6 +19,8 @@ set(declarative_appletscript_SRCS add_library(plasma_appletscript_declarative MODULE ${declarative_appletscript_SRCS} ) set_target_properties(plasma_appletscript_declarative PROPERTIES PREFIX "") +kcoreaddons_desktop_to_json(plasma_appletscript_declarative data/plasma-scriptengine-applet-declarative.desktop) + target_link_libraries(plasma_appletscript_declarative Qt5::Quick Qt5::Qml @@ -35,7 +37,7 @@ target_link_libraries(plasma_appletscript_declarative ) -install(TARGETS plasma_appletscript_declarative DESTINATION ${KDE_INSTALL_PLUGINDIR}) +install(TARGETS plasma_appletscript_declarative DESTINATION ${KDE_INSTALL_PLUGINDIR}/plasma/scriptengines) install(FILES data/plasma-scriptengine-applet-declarative.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) install(FILES data/plasma-wallpaper.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR}) diff --git a/src/scriptengines/qml/plasmoid/appletinterface.cpp b/src/scriptengines/qml/plasmoid/appletinterface.cpp index db956b3ff..6573d9817 100644 --- a/src/scriptengines/qml/plasmoid/appletinterface.cpp +++ b/src/scriptengines/qml/plasmoid/appletinterface.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -498,13 +497,17 @@ bool AppletInterface::userConfiguring() const int AppletInterface::apiVersion() const { - const QString constraint("[X-Plasma-API] == 'declarative' and 'Applet' in [X-Plasma-ComponentTypes]"); - KService::List offers = KServiceTypeTrader::self()->query("Plasma/ScriptEngine", constraint); - if (offers.isEmpty()) { + // Look for C++ plugins first + auto filter = [](const KPluginMetaData &md) -> bool + { + return md.value("X-Plasma-API") == "declarativeappletscript" && md.value("X-Plasma-ComponentTypes").contains("Applet"); + }; + QVector plugins = KPluginLoader::findPlugins("plasma/scriptengines", filter); + if (plugins.isEmpty()) { return -1; } - - return offers.first()->property("X-KDE-PluginInfo-Version", QVariant::Int).toInt(); + + return plugins.first().value("X-KDE-PluginInfo-Version").toInt(); } void AppletInterface::setAssociatedApplication(const QString &string) diff --git a/src/scriptengines/qml/plasmoid/containmentinterface.cpp b/src/scriptengines/qml/plasmoid/containmentinterface.cpp index c6986f2df..65b7fca4b 100644 --- a/src/scriptengines/qml/plasmoid/containmentinterface.cpp +++ b/src/scriptengines/qml/plasmoid/containmentinterface.cpp @@ -428,10 +428,11 @@ QPointF ContainmentInterface::adjustToAvailableScreenRegion(int x, int y, int w, void ContainmentInterface::processMimeData(QObject *mimeDataProxy, int x, int y) { QMimeData* mime = qobject_cast(mimeDataProxy); - if (mime) + if (mime) { processMimeData(mime, x, y); - else + } else { processMimeData(mimeDataProxy->property("mimeData").value(), x, y); + } } void ContainmentInterface::processMimeData(QMimeData *mimeData, int x, int y) diff --git a/src/scriptengines/qml/plasmoid/declarativeappletscript.cpp b/src/scriptengines/qml/plasmoid/declarativeappletscript.cpp index 24c39dda4..b15695bf4 100644 --- a/src/scriptengines/qml/plasmoid/declarativeappletscript.cpp +++ b/src/scriptengines/qml/plasmoid/declarativeappletscript.cpp @@ -46,17 +46,11 @@ #include #include -K_EXPORT_PLASMA_APPLETSCRIPTENGINE(declarativeappletscript, DeclarativeAppletScript) - DeclarativeAppletScript::DeclarativeAppletScript(QObject *parent, const QVariantList &args) : Plasma::AppletScript(parent), m_interface(0), m_args(args) { - // Chop off list entry added by KService::createInstance() before we - // hand this to the applet via externalData() later. - m_args.removeLast(); - //qmlRegisterType(); //FIXME: use this if/when will be possible to have properties of attached items subclasses on the left hand of expressions /*qmlRegisterUncreatableType("org.kde.plasma.plasmoid", 2, 0, "Plasmoid", @@ -132,5 +126,7 @@ QList DeclarativeAppletScript::contextualActions() return m_interface->contextualActions(); } +K_EXPORT_PLASMA_APPLETSCRIPTENGINE_WITH_JSON(plasma_appletscript_declarative, DeclarativeAppletScript, "plasma-scriptengine-applet-declarative.json") + #include "declarativeappletscript.moc" diff --git a/src/scriptengines/qml/plasmoid/wallpaperinterface.cpp b/src/scriptengines/qml/plasmoid/wallpaperinterface.cpp index a406d452c..fcaca4b58 100644 --- a/src/scriptengines/qml/plasmoid/wallpaperinterface.cpp +++ b/src/scriptengines/qml/plasmoid/wallpaperinterface.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -35,6 +34,7 @@ #include #include +#include QHash WallpaperInterface::s_rootObjects = QHash(); @@ -71,14 +71,14 @@ WallpaperInterface::~WallpaperInterface() KPluginInfo::List WallpaperInterface::listWallpaperInfoForMimetype(const QString &mimetype, const QString &formFactor) { - QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype); - if (!formFactor.isEmpty()) { - constraint.append("[X-Plasma-FormFactors] ~~ '").append(formFactor).append("'"); - } - - KService::List offers = KServiceTypeTrader::self()->query("Plasma/Wallpaper", constraint); - qDebug() << offers.count() << constraint; - return KPluginInfo::fromServices(offers); + auto filter = [&mimetype, &formFactor](const KPluginMetaData &md) -> bool + { + if (!formFactor.isEmpty() && !md.value("X-Plasma-FormFactors").contains(formFactor)) { + return false; + } + return md.value("X-Plasma-DropMimeTypes").contains(mimetype); + }; + return KPluginInfo::fromMetaData(KPackage::PackageLoader::self()->findPackages("Plasma/Wallpaper", QString(), filter).toVector()); } Plasma::Package WallpaperInterface::package() const