port libplasma away from sycoca as much as possible

this ports most of libplasma away from sycoca, using instead
a combination of KPluginLoader and KPackage::PackageLoader instead
(so eventually using their own little caches instead of the
global sycoca cache)
a kservicetypetrader call is left in the loading of
containmentactions since is the only way to make an older
workspace still work, but is only a fallback, so containmentactions
in plasma-workspace can be ported eventually as well

Change-Id: Ie9579c3e01284f6d97043e22d01bbe63d3c3f45a
REVIEW:123626
This commit is contained in:
Marco Martin 2015-05-07 16:26:37 +02:00
parent 02f124b120
commit ea924b1469
22 changed files with 400 additions and 381 deletions

View File

@ -8,6 +8,11 @@ set(Plasma_INSTALL_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@")
set(Plasma_LIBRARIES KF5::Plasma) 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(KF5Package "@KF5_DEP_VERSION@")
find_dependency(KF5Service "@KF5_DEP_VERSION@") find_dependency(KF5Service "@KF5_DEP_VERSION@")

View File

@ -42,7 +42,6 @@
#include <kplugininfo.h> #include <kplugininfo.h>
#include <klocalizedstring.h> #include <klocalizedstring.h>
#include <kservice.h> #include <kservice.h>
#include <kservicetypetrader.h>
#include <KConfigLoader> #include <KConfigLoader>
#include <kwindowsystem.h> #include <kwindowsystem.h>
@ -84,10 +83,13 @@ Applet::Applet(QObject *parent, const QString &serviceID, uint appletId)
Applet::Applet(QObject *parentObject, const QVariantList &args) Applet::Applet(QObject *parentObject, const QVariantList &args)
: QObject(0), : QObject(0),
d(new AppletPrivate( d(new AppletPrivate(
KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString()), 0, KService::serviceByStorageId(args.count() > 0 && args.first().canConvert<QString>() ? args[0].toString() : QString()), 0,
args.count() > 1 ? args[1].toInt() : 0, this)) args.count() > 1 ? args[1].toInt() : 0, this))
{ {
setParent(parentObject); setParent(parentObject);
if (args.count() > 0 && args.first().canConvert<QVariantMap>()) {
d->appletDescription = KPluginInfo(args);
}
// WARNING: do not access config() OR globalConfig() in this method! // WARNING: do not access config() OR globalConfig() in this method!
// that requires a scene, which is not available at this point // that requires a scene, which is not available at this point

View File

@ -37,7 +37,6 @@
#include <QDebug> #include <QDebug>
#include <kauthorized.h> #include <kauthorized.h>
#include <klocalizedstring.h> #include <klocalizedstring.h>
#include <kservicetypetrader.h>
#include <KConfigSkeleton> #include <KConfigSkeleton>
#include <KConfigLoader> #include <KConfigLoader>

View File

@ -33,7 +33,6 @@
#include <QDebug> #include <QDebug>
#include <klocalizedstring.h> #include <klocalizedstring.h>
#include <kservicetypetrader.h>
#include "version.h" #include "version.h"

View File

@ -33,7 +33,6 @@
#include <kplugininfo.h> #include <kplugininfo.h>
#include <kservice.h> #include <kservice.h>
#include <kservicetypetrader.h>
#include <klocalizedstring.h> #include <klocalizedstring.h>
#include "datacontainer.h" #include "datacontainer.h"

View File

@ -27,7 +27,6 @@
#include <karchive.h> #include <karchive.h>
#include <QDebug> #include <QDebug>
#include <kdesktopfile.h> #include <kdesktopfile.h>
#include <kservicetypetrader.h>
#include <ktar.h> #include <ktar.h>
#include <kzip.h> #include <kzip.h>
#include <KJob> #include <KJob>

View File

@ -129,7 +129,7 @@ void PackageStructurePrivate::installPathChanged(const QString &path)
// used by the installing app in any case, and the // used by the installing app in any case, and the
// package is properly installed - aseigo // 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"; const QString serviceName = servicePrefix + pluginName + ".desktop";

View File

@ -56,10 +56,13 @@ class PluginLoaderPrivate
public: public:
PluginLoaderPrivate() PluginLoaderPrivate()
: isDefaultLoader(false), : isDefaultLoader(false),
dataEnginePluginDir("plasma/dataengine"),
packageStructurePluginDir("plasma/packagestructure"),
packageRE("[^a-zA-Z0-9\\-_]") 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<QString> knownCategories(); static QSet<QString> knownCategories();
@ -68,13 +71,23 @@ public:
static QSet<QString> s_customCategories; static QSet<QString> s_customCategories;
QHash<QString, QWeakPointer<PackageStructure> > structures; QHash<QString, QWeakPointer<PackageStructure> > structures;
bool isDefaultLoader; 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; QRegExp packageRE;
}; };
QSet<QString> PluginLoaderPrivate::s_customCategories; QSet<QString> 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<QString> PluginLoaderPrivate::knownCategories() QSet<QString> PluginLoaderPrivate::knownCategories()
{ {
// this is to trick the tranlsation tools into making the correct // 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; 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) { if (appletId == 0) {
appletId = ++AppletPrivate::s_maxAppletId; 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);
}
}
}
KPluginLoader plugin(*offer);
if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion())) { // Look for C++ plugins first
auto filter = [&name](const KPluginMetaData &md) -> bool
{
return md.pluginId() == name;
};
QVector<KPluginMetaData> 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; return 0;
} }
KPluginFactory *factory = loader.factory();
if (factory) {
QVariantList allArgs;
allArgs << loader.metaData().toVariantMap() << appletId << args;
applet = factory->create<Plasma::Applet>(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;
}
}
// 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<Plasma::Applet>(0, allArgs);
}
if (applet) {
return applet;
}
}
QString error;
applet = offer->createInstance<Plasma::Applet>(0, allArgs, &error);
if (!applet) { 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;
return new Containment(0, allArgs); allArgs << p.metadata().fileName() << appletId << args;
} else {
if (offer->serviceTypes().contains("Plasma/Containment")) { if (p.metadata().serviceTypes().contains("Plasma/Containment")) {
return new Containment(0, allArgs); return new Containment(0, allArgs);
} else { } else {
return new Applet(0, allArgs); return new Applet(0, allArgs);
} }
}
} }
return applet; return applet;
@ -257,7 +276,7 @@ DataEngine *PluginLoader::loadDataEngine(const QString &name)
{ {
return md.pluginId() == name; return md.pluginId() == name;
}; };
QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(d->dataEnginePluginDir, filter); QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_dataEnginePluginDir, filter);
if (plugins.count()) { if (plugins.count()) {
KPluginInfo::List lst = KPluginInfo::fromMetaData(plugins); KPluginInfo::List lst = KPluginInfo::fromMetaData(plugins);
@ -272,41 +291,40 @@ DataEngine *PluginLoader::loadDataEngine(const QString &name)
return engine; return engine;
} }
// Fall back to querying scripted plugins const KPackage::Package p = KPackage::PackageLoader::self()->loadPackage("Plasma/DataEngine", name);
QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name); if (!p.isValid()) {
return 0;
// 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);
}
} }
return engine; return new DataEngine(KPluginInfo(p.metadata().fileName()), 0);
} }
QStringList PluginLoader::listAllEngines(const QString &parentApp) QStringList PluginLoader::listAllEngines(const QString &parentApp)
{ {
QString constraint; if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/DataEngine")) {
KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/DataEngine", new DataEnginePackage());
if (parentApp.isEmpty()) {
constraint.append("(not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '')");
} else {
constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
} }
KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", constraint);
QStringList engines; QStringList engines;
foreach (const KService::Ptr &service, offers) { // Look for C++ plugins first
QString name = service->property("X-KDE-PluginInfo-Name").toString(); auto filter = [&parentApp](const KPluginMetaData &md) -> bool
if (!name.isEmpty()) { {
engines.append(name); return md.value("X-KDE-ParentApp") == parentApp;
};
QVector<KPluginMetaData> 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<KPluginMetaData> packagePlugins = KPackage::PackageLoader::self()->listPackages("Plasma/DataEngine");
for (auto plugin : packagePlugins) {
engines << plugin.pluginId();
} }
return engines; return engines;
@ -314,21 +332,44 @@ QStringList PluginLoader::listAllEngines(const QString &parentApp)
KPluginInfo::List PluginLoader::listEngineInfo(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); return PluginLoader::self()->listDataEngineInfo(parentApp);
} }
KPluginInfo::List PluginLoader::listEngineInfoByCategory(const QString &category, const QString &parentApp) KPluginInfo::List PluginLoader::listEngineInfoByCategory(const QString &category, const QString &parentApp)
{ {
QString constraint = QString("[X-KDE-PluginInfo-Category] == '%1'").arg(category); if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/DataEngine")) {
KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/DataEngine", new DataEnginePackage());
if (parentApp.isEmpty()) {
constraint.append(" and not exist [X-KDE-ParentApp]");
} else {
constraint.append(" and [X-KDE-ParentApp] == '").append(parentApp).append("'");
} }
KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", constraint); KPluginInfo::List list;
return KPluginInfo::fromServices(offers);
// 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<KPluginMetaData> 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<KPluginMetaData> 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) 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); 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()) { // Look for C++ plugins first
#ifndef NDEBUG auto filter = [&name](const KPluginMetaData &md) -> bool
// qDebug() << "offers is empty for " << name; {
#endif return md.pluginId() == name;
return new NullService(name, parent); };
} QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_servicesPluginDir, filter);
KService::Ptr offer = offers.first(); if (plugins.count()) {
QString error; KPluginInfo::List lst = KPluginInfo::fromMetaData(plugins);
KPluginLoader loader(lst.first().libraryPath());
if (Plasma::isPluginVersionCompatible(KPluginLoader(*offer).pluginVersion())) { if (!Plasma::isPluginVersionCompatible(loader.pluginVersion())) {
service = offer->createInstance<Plasma::Service>(parent, args, &error); return 0;
} }
KPluginFactory *factory = loader.factory();
if (!service) { if (factory) {
#ifndef NDEBUG service = factory->create<Plasma::Service>(0, args);
// qDebug() << "Couldn't load Service \"" << name << "\"! reason given: " << error; }
#endif
return new NullService(name, parent);
} }
if (service) {
if (service->name().isEmpty()) { if (service->name().isEmpty()) {
service->setName(name); service->setName(name);
} }
return service; return service;
} else {
return new NullService(name, parent);
}
} }
ContainmentActions *PluginLoader::loadContainmentActions(Containment *parent, const QString &name, const QVariantList &args) ContainmentActions *PluginLoader::loadContainmentActions(Containment *parent, const QString &name, const QVariantList &args)
@ -387,6 +427,29 @@ ContainmentActions *PluginLoader::loadContainmentActions(Containment *parent, co
return actions; return actions;
} }
// Look for C++ plugins first
auto filter = [&name](const KPluginMetaData &md) -> bool
{
return md.pluginId() == name;
};
QVector<KPluginMetaData> 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<Plasma::ContainmentActions>(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); QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name);
KService::List offers = KServiceTypeTrader::self()->query("Plasma/ContainmentActions", constraint); 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 //fallback to old structures
} else { } else {
const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(packageFormat); const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(packageFormat);
structure = KPluginTrader::createInstanceFromQuery<Plasma::PackageStructure>(d->packageStructurePluginDir, "Plasma/PackageStructure", constraint, 0); structure = KPluginTrader::createInstanceFromQuery<Plasma::PackageStructure>(PluginLoaderPrivate::s_packageStructurePluginDir, "Plasma/PackageStructure", constraint, 0);
if (structure) { if (structure) {
structure->d->internalStructure = new PackageStructureWrapper(structure); structure->d->internalStructure = new PackageStructureWrapper(structure);
} }
@ -495,45 +558,70 @@ KPluginInfo::List PluginLoader::listAppletInfo(const QString &category, const QS
list = internalAppletInfo(category); list = internalAppletInfo(category);
} }
QString constraint = PluginLoaderPrivate::parentAppConstraint(parentApp); //FIXME: this assumes we are always use packages.. no pure c++
//note: constraint guaranteed non-empty from here down
if (category.isEmpty()) { //use all but the excluded categories if (category.isEmpty()) { //use all but the excluded categories
KConfigGroup group(KSharedConfig::openConfig(), "General"); KConfigGroup group(KSharedConfig::openConfig(), "General");
QStringList excluded = group.readEntry("ExcludeCategories", QStringList()); 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?) } else { //specific category (this could be an excluded one - is that bad?)
constraint.append(" and ").append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
auto filter = [&category, &parentApp](const KPluginMetaData &md) -> bool
{
const QString pa = md.value("X-KDE-ParentApp");
if (category == "Miscellaneous") { if (category == "Miscellaneous") {
constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')"); 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) KPluginInfo::List PluginLoader::listAppletInfoForMimeType(const QString &mimeType)
{ {
QString constraint = PluginLoaderPrivate::parentAppConstraint(); auto filter = [&mimeType](const KPluginMetaData &md) -> bool
constraint.append(QString(" and '%1' in [X-Plasma-DropMimeTypes]").arg(mimeType)); {
//qDebug() << "listAppletInfoForMimetype with" << mimeType << constraint; return md.value("X-Plasma-DropMimeTypes").contains(mimeType);
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); };
return KPluginInfo::fromServices(offers); return KPluginInfo::fromMetaData(KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter).toVector());
} }
KPluginInfo::List PluginLoader::listAppletInfoForUrl(const QUrl &url) KPluginInfo::List PluginLoader::listAppletInfoForUrl(const QUrl &url)
{ {
QString constraint = PluginLoaderPrivate::parentAppConstraint(); QString parentApp;
constraint.append(" and exist [X-Plasma-DropUrlPatterns]"); QCoreApplication *app = QCoreApplication::instance();
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); 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; KPluginInfo::List filtered;
foreach (const KPluginInfo &info, allApplets) { foreach (const KPluginInfo &info, allApplets) {
QStringList urlPatterns = info.property("X-Plasma-DropUrlPatterns").toStringList(); 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) 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"); KConfigGroup group(KSharedConfig::openConfig(), "General");
const QStringList excluded = group.readEntry("ExcludeCategories", QStringList()); const QStringList excluded = group.readEntry("ExcludeCategories", QStringList());
foreach (const QString &category, excluded) { auto filter = [&parentApp, &excluded, visibleOnly](const KPluginMetaData &md) -> bool
constraint.append(" and [X-KDE-PluginInfo-Category] != '").append(category).append("'"); {
} 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<KPluginMetaData> allApplets = KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter);
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
QStringList categories; QStringList categories;
QSet<QString> known = PluginLoaderPrivate::knownCategories(); for (auto plugin : allApplets) {
foreach (const KService::Ptr &applet, offers) { if (plugin.category().isEmpty()) {
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()) {
if (!categories.contains(i18nc("misc category", "Miscellaneous"))) { if (!categories.contains(i18nc("misc category", "Miscellaneous"))) {
categories << i18nc("misc category", "Miscellaneous"); categories << i18nc("misc category", "Miscellaneous");
} }
} else if (!categories.contains(appletCategory)) { } else {
categories << appletCategory; categories << plugin.category();
} }
} }
categories.sort(); categories.sort();
return categories; return categories;
} }
@ -612,14 +682,12 @@ QString PluginLoader::appletCategory(const QString &appletName)
return QString(); return QString();
} }
const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName); const KPackage::Package p = KPackage::PackageLoader::self()->loadPackage("Plasma/Applet", appletName);
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); if (!p.isValid()) {
if (offers.isEmpty()) {
return QString(); return QString();
} }
return offers.first()->property("X-KDE-PluginInfo-Category").toString(); return p.metadata().category();
} }
KPluginInfo::List PluginLoader::listContainments(const QString &category, KPluginInfo::List PluginLoader::listContainments(const QString &category,
@ -632,53 +700,54 @@ KPluginInfo::List PluginLoader::listContainmentsOfType(const QString &type,
const QString &category, const QString &category,
const QString &parentApp) const QString &parentApp)
{ {
QString constraint; if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/Applet")) {
KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/Applet", new DataEnginePackage());
if (parentApp.isEmpty()) {
constraint.append("(not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '')");
} else {
constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
} }
if (!type.isEmpty()) { KConfigGroup group(KSharedConfig::openConfig(), "General");
if (!constraint.isEmpty()) { const QStringList excluded = group.readEntry("ExcludeCategories", QStringList());
constraint.append(" and ("); 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.isEmpty() && md.value("X-Plasma-ContainmentType") != type) {
if (type == "Desktop") { return false;
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 (!category.isEmpty() && md.value("X-KDE-PluginInfo-Category") != category) {
if (!constraint.isEmpty()) { return false;
constraint.append(" and ");
} }
constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'"); return true;
if (category == "Miscellaneous") { };
constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
}
}
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint); return KPluginInfo::fromMetaData(KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter).toVector());
// qDebug() << "constraint was" << constraint << "which got us" << offers.count() << "matches";
return KPluginInfo::fromServices(offers);
} }
KPluginInfo::List PluginLoader::listContainmentsForMimeType(const QString &mimeType) KPluginInfo::List PluginLoader::listContainmentsForMimeType(const QString &mimeType)
{ {
const QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimeType); if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/Applet")) {
//qDebug() << mimeType << constraint; KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/Applet", new DataEnginePackage());
const KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint); }
return KPluginInfo::fromServices(offers); 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() QStringList PluginLoader::listContainmentTypes()
{ {
if (!KPackage::PackageLoader::self()->loadPackageStructure("Plasma/Applet")) {
KPackage::PackageLoader::self()->addKnownPackageStructure("Plasma/Applet", new DataEnginePackage());
}
KPluginInfo::List containmentInfos = listContainments(); KPluginInfo::List containmentInfos = listContainments();
QSet<QString> types; QSet<QString> types;
@ -707,7 +776,7 @@ KPluginInfo::List PluginLoader::listDataEngineInfo(const QString &parentApp)
constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'"); 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; return list;
} }
@ -726,8 +795,22 @@ KPluginInfo::List PluginLoader::listContainmentActionsInfo(const QString &parent
constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'"); constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
} }
list.append(KPluginTrader::self()->query(PluginLoaderPrivate::s_containmentActionsPluginDir, "Plasma/ContainmentActions", constraint));
QSet<QString> 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); 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) Applet *PluginLoader::internalLoadApplet(const QString &name, uint appletId, const QVariantList &args)

View File

@ -35,7 +35,8 @@
#include <kkeysequencewidget.h> #include <kkeysequencewidget.h>
#include <kglobalaccel.h> #include <kglobalaccel.h>
#include <KConfigLoader> #include <KConfigLoader>
#include <KServiceTypeTrader> #include <KPluginTrader>
#include <kpackage/packageloader.h>
#include "containment.h" #include "containment.h"
#include "corona.h" #include "corona.h"
@ -176,16 +177,17 @@ void AppletPrivate::init(const QString &packagePath, const QVariantList &args)
QString constraint; QString constraint;
QStringList provides = q->pluginInfo().property("X-Plasma-Provides").value<QStringList>(); QStringList provides = q->pluginInfo().property("X-Plasma-Provides").value<QStringList>();
if (!provides.isEmpty()) { if (!provides.isEmpty()) {
bool first = true; auto filter = [&provides](const KPluginMetaData &md) -> bool
foreach (const QString &prov, provides) { {
if (!first) { foreach (const QString &p, provides) {
constraint += " or "; if (md.value("X-Plasma-Provides").contains(p)) {
return true;
} }
first = false;
constraint += "'" + prov + "' in [X-Plasma-Provides]";
} }
return false;
};
QList<KPluginMetaData> applets = KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter);
KPluginInfo::List applets = KPluginInfo::fromServices(KServiceTypeTrader::self()->query("Plasma/Applet", constraint));
if (applets.count() > 1) { if (applets.count() > 1) {
QAction *a = new QAction(QIcon::fromTheme("preferences-desktop-default-applications"), i18n("Alternatives..."), q); QAction *a = new QAction(QIcon::fromTheme("preferences-desktop-default-applications"), i18n("Alternatives..."), q);
q->actions()->addAction("alternatives", a); q->actions()->addAction("alternatives", a);
@ -457,7 +459,7 @@ QString AppletPrivate::globalName() const
return QString(); return QString();
} }
return appletDescription.service()->library(); return appletDescription.pluginName();
} }
void AppletPrivate::scheduleConstraintsUpdate(Plasma::Types::Constraints c) void AppletPrivate::scheduleConstraintsUpdate(Plasma::Types::Constraints c)

View File

@ -24,7 +24,6 @@
#include <QDebug> #include <QDebug>
#include <kservicetypetrader.h>
#include <qstandardpaths.h> #include <qstandardpaths.h>
#include "datacontainer.h" #include "datacontainer.h"

View File

@ -170,6 +170,9 @@ private:
#define K_EXPORT_PLASMA_APPLETSCRIPTENGINE(libname, classname) \ #define K_EXPORT_PLASMA_APPLETSCRIPTENGINE(libname, classname) \
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) K_PLUGIN_FACTORY(factory, registerPlugin<classname>();)
#define K_EXPORT_PLASMA_APPLETSCRIPTENGINE_WITH_JSON(libname, classname, jsonFile) \
K_PLUGIN_FACTORY_WITH_JSON(factory, jsonFile, registerPlugin<classname>();) \
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
} //Plasma namespace } //Plasma namespace
#endif #endif

View File

@ -146,6 +146,9 @@ private:
#define K_EXPORT_PLASMA_DATAENGINESCRIPTENGINE(libname, classname) \ #define K_EXPORT_PLASMA_DATAENGINESCRIPTENGINE(libname, classname) \
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) K_PLUGIN_FACTORY(factory, registerPlugin<classname>();)
#define K_EXPORT_PLASMA_DATAENGINESCRIPTENGINE_WITH_JSON(libname, classname, jsonFile) \
K_PLUGIN_FACTORY_WITH_JSON(factory, jsonFile, registerPlugin<classname>();) \
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
} //Plasma namespace } //Plasma namespace
#endif #endif

View File

@ -21,7 +21,6 @@
#include <QDebug> #include <QDebug>
#include <kservice.h> #include <kservice.h>
#include <kservicetypetrader.h>
#include "applet.h" #include "applet.h"
#include "dataengine.h" #include "dataengine.h"
@ -61,119 +60,50 @@ QString ScriptEngine::mainScript() const
QStringList knownLanguages(Types::ComponentTypes types) 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; QStringList languages;
foreach (const KService::Ptr &service, offers) { QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins("plasma/scriptengines");
QString language = service->property("X-Plasma-API").toString();
if (!languages.contains(language)) { for (auto plugin : plugins) {
languages.append(language); 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; 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, ScriptEngine *loadEngine(const QString &language, Types::ComponentType type, QObject *parent,
const QVariantList &args = QVariantList()) const QVariantList &args = QVariantList())
{ {
KService::List offers = engineOffers(language, type);
QString error;
ScriptEngine *engine = 0; ScriptEngine *engine = 0;
foreach (const KService::Ptr &service, offers) {
switch (type) { auto filter = [&language](const KPluginMetaData &md) -> bool
case Types::AppletComponent: {
engine = service->createInstance<Plasma::AppletScript>(parent, args, &error); return md.value("X-Plasma-API") == language;
break; };
case Types::DataEngineComponent: QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins("plasma/scriptengines", filter);
engine = service->createInstance<Plasma::DataEngineScript>(parent, args, &error);
break; if (plugins.count()) {
default: if ((type & Types::AppletComponent) &&
plugins.first().value("X-Plasma-ComponentTypes") != "Applet") {
return 0; return 0;
break; } else if ((type & Types::DataEngineComponent) &&
plugins.first().value("X-Plasma-ComponentTypes") != "DataEngine") {
return 0;
}
KPluginInfo::List lst = KPluginInfo::fromMetaData(plugins);
KPluginLoader loader(lst.first().libraryPath());
KPluginFactory *factory = loader.factory();
if (factory) {
engine = factory->create<Plasma::ScriptEngine>(0, args);
}
} }
if (engine) {
return engine; return engine;
}
#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;
} }
AppletScript *loadScriptEngine(const QString &language, Applet *applet, const QVariantList &args) AppletScript *loadScriptEngine(const QString &language, Applet *applet, const QVariantList &args)

View File

@ -27,7 +27,6 @@
#include <QDebug> #include <QDebug>
#include <kservice.h> #include <kservice.h>
#include <kservicetypetrader.h>
#include <ksharedconfig.h> #include <ksharedconfig.h>
#include <KConfigLoader> #include <KConfigLoader>
#include <KConfigSkeleton> #include <KConfigSkeleton>

View File

@ -232,5 +232,9 @@ Q_DECLARE_METATYPE(Plasma::Service *)
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \ K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION) K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
#define K_EXPORT_PLASMA_SERVICE_WITH_JSON(libname, classname, jsonFile) \
K_PLUGIN_FACTORY_WITH_JSON(factory, jsonFile, registerPlugin<classname>();) \
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
#endif // multiple inclusion guard #endif // multiple inclusion guard

View File

@ -22,15 +22,17 @@
#include <QDebug> #include <QDebug>
#include <kservice.h> #include <kservice.h>
#include <kservicetypetrader.h> #include <kplugintrader.h>
#include <kshell.h> #include <kshell.h>
#include <kconfig.h> #include <kconfig.h>
#include <ksycoca.h> #include <ksycoca.h>
#include <klocalizedstring.h> #include <klocalizedstring.h>
#include <KPluginMetaData>
#include <plasma/packagestructure.h> #include <plasma/packagestructure.h>
#include <plasma/package.h> #include <plasma/package.h>
#include <plasma/pluginloader.h> #include <plasma/pluginloader.h>
#include <kpackage/packageloader.h>
#include <kjob.h> #include <kjob.h>
#include <qcommandlineparser.h> #include <qcommandlineparser.h>
@ -254,28 +256,20 @@ void PlasmaPkg::runMain()
d->packageRoot = "kwin/scripts/"; d->packageRoot = "kwin/scripts/";
d->servicePrefix = "kwin-script-"; d->servicePrefix = "kwin-script-";
d->pluginTypes << "KWin/Script"; d->pluginTypes << "KWin/Script";
} else { /* if (KSycoca::isAvailable()) */
const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(type); //do it trough normal plugin loading
KService::List offers = KServiceTypeTrader::self()->query("Plasma/PackageStructure", constraint); } else {
if (offers.isEmpty()) { 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)); d->coutput(i18n("Could not find a suitable installer for package of type %1", type));
exit(5); exit(5);
return; return;
} }
qWarning() << "custom PackageStructure plugins not ported";
KService::Ptr offer = offers.first();
QString error;
d->installer = new Plasma::Package(offer->createInstance<Plasma::PackageStructure>(0, QVariantList(), &error)); d->installer = new Plasma::Package(p);
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->packageRoot = d->installer->defaultPackageRoot(); //d->packageRoot = d->installer->defaultPackageRoot();
//pluginTypes << d->installer->type(); d->pluginTypes << type;
} }
if (d->parser->isSet("show")) { if (d->parser->isSet("show")) {
const QString pluginName = d->package; const QString pluginName = d->package;
@ -442,9 +436,9 @@ QStringList PlasmaPkgPrivate::packages(const QStringList &types)
} }
} }
const KService::List services = KServiceTypeTrader::self()->query(type); const QList<KPluginMetaData> plugins = KPackage::PackageLoader::self()->listPackages(type);
foreach (const KService::Ptr &service, services) { for (auto plugin : plugins) {
const QString _plugin = service->property("X-KDE-PluginInfo-Name", QVariant::String).toString(); const QString _plugin = plugin.pluginId();
if (!result.contains(_plugin)) { if (!result.contains(_plugin)) {
result << _plugin; result << _plugin;
} }
@ -584,17 +578,14 @@ void PlasmaPkgPrivate::listTypes()
builtIns.insert(i18n("KWin Script"), QStringList() << "KWin/Script" << "kwin/scripts/" << "kwinscript"); builtIns.insert(i18n("KWin Script"), QStringList() << "KWin/Script" << "kwin/scripts/" << "kwinscript");
renderTypeTable(builtIns); renderTypeTable(builtIns);
KService::List offers; const KPluginInfo::List offers = KPluginTrader::self()->query("kpackage/packagestructure", "KPackage/PackageStructure");
//if (KSycoca::isAvailable()) {
offers = KServiceTypeTrader::self()->query("Plasma/PackageStructure");
//}
if (!offers.isEmpty()) { if (!offers.isEmpty()) {
std::cout << std::endl; std::cout << std::endl;
coutput(i18n("Provided by plugins:")); coutput(i18n("Provided by plugins:"));
QMap<QString, QStringList> plugins; QMap<QString, QStringList> plugins;
foreach (const KService::Ptr service, offers) { for (auto info : offers) {
KPluginInfo info(service);
//const QString proot = ""; //const QString proot = "";
//Plasma::PackageStructure* structure = Plasma::PackageStructure::load(info.pluginName()); //Plasma::PackageStructure* structure = Plasma::PackageStructure::load(info.pluginName());
QString name = info.name(); QString name = info.name();
@ -602,7 +593,7 @@ void PlasmaPkgPrivate::listTypes()
QString plugin = info.pluginName(); QString plugin = info.pluginName();
//QString path = structure->defaultPackageRoot(); //QString path = structure->defaultPackageRoot();
//QString path = defaultPackageRoot; //QString path = defaultPackageRoot;
plugins.insert(name, QStringList() << plugin); plugins.insert(name, QStringList() << name << plugin << comment);
//qDebug() << "KService stuff:" << name << plugin << comment; //qDebug() << "KService stuff:" << name << plugin << comment;
} }

View File

@ -1,6 +1,6 @@
add_subdirectory(qml) add_subdirectory(qml)
add_subdirectory(ruby) #add_subdirectory(ruby)
# Re-enable when we have Python bindings for libplasma # Re-enable when we have Python bindings for libplasma
#if (PYTHONLIBRARY_FOUND AND NOT WIN32) #if (PYTHONLIBRARY_FOUND AND NOT WIN32)

View File

@ -19,6 +19,8 @@ set(declarative_appletscript_SRCS
add_library(plasma_appletscript_declarative MODULE ${declarative_appletscript_SRCS} ) add_library(plasma_appletscript_declarative MODULE ${declarative_appletscript_SRCS} )
set_target_properties(plasma_appletscript_declarative PROPERTIES PREFIX "") 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 target_link_libraries(plasma_appletscript_declarative
Qt5::Quick Qt5::Quick
Qt5::Qml 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-scriptengine-applet-declarative.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
install(FILES data/plasma-wallpaper.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR}) install(FILES data/plasma-wallpaper.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR})

View File

@ -30,7 +30,6 @@
#include <kactioncollection.h> #include <kactioncollection.h>
#include <QDebug> #include <QDebug>
#include <kservice.h> #include <kservice.h>
#include <kservicetypetrader.h>
#include <klocalizedstring.h> #include <klocalizedstring.h>
#include <KConfigLoader> #include <KConfigLoader>
@ -498,13 +497,17 @@ bool AppletInterface::userConfiguring() const
int AppletInterface::apiVersion() const int AppletInterface::apiVersion() const
{ {
const QString constraint("[X-Plasma-API] == 'declarative' and 'Applet' in [X-Plasma-ComponentTypes]"); // Look for C++ plugins first
KService::List offers = KServiceTypeTrader::self()->query("Plasma/ScriptEngine", constraint); auto filter = [](const KPluginMetaData &md) -> bool
if (offers.isEmpty()) { {
return md.value("X-Plasma-API") == "declarativeappletscript" && md.value("X-Plasma-ComponentTypes").contains("Applet");
};
QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins("plasma/scriptengines", filter);
if (plugins.isEmpty()) {
return -1; 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) void AppletInterface::setAssociatedApplication(const QString &string)

View File

@ -428,10 +428,11 @@ QPointF ContainmentInterface::adjustToAvailableScreenRegion(int x, int y, int w,
void ContainmentInterface::processMimeData(QObject *mimeDataProxy, int x, int y) void ContainmentInterface::processMimeData(QObject *mimeDataProxy, int x, int y)
{ {
QMimeData* mime = qobject_cast<QMimeData*>(mimeDataProxy); QMimeData* mime = qobject_cast<QMimeData*>(mimeDataProxy);
if (mime) if (mime) {
processMimeData(mime, x, y); processMimeData(mime, x, y);
else } else {
processMimeData(mimeDataProxy->property("mimeData").value<QMimeData*>(), x, y); processMimeData(mimeDataProxy->property("mimeData").value<QMimeData*>(), x, y);
}
} }
void ContainmentInterface::processMimeData(QMimeData *mimeData, int x, int y) void ContainmentInterface::processMimeData(QMimeData *mimeData, int x, int y)

View File

@ -46,17 +46,11 @@
#include <kdeclarative/qmlobject.h> #include <kdeclarative/qmlobject.h>
#include <kdeclarative/configpropertymap.h> #include <kdeclarative/configpropertymap.h>
K_EXPORT_PLASMA_APPLETSCRIPTENGINE(declarativeappletscript, DeclarativeAppletScript)
DeclarativeAppletScript::DeclarativeAppletScript(QObject *parent, const QVariantList &args) DeclarativeAppletScript::DeclarativeAppletScript(QObject *parent, const QVariantList &args)
: Plasma::AppletScript(parent), : Plasma::AppletScript(parent),
m_interface(0), m_interface(0),
m_args(args) 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<AppletInterface>(); //qmlRegisterType<AppletInterface>();
//FIXME: use this if/when will be possible to have properties of attached items subclasses on the left hand of expressions //FIXME: use this if/when will be possible to have properties of attached items subclasses on the left hand of expressions
/*qmlRegisterUncreatableType<AppletLoader>("org.kde.plasma.plasmoid", 2, 0, "Plasmoid", /*qmlRegisterUncreatableType<AppletLoader>("org.kde.plasma.plasmoid", 2, 0, "Plasmoid",
@ -132,5 +126,7 @@ QList<QAction *> DeclarativeAppletScript::contextualActions()
return m_interface->contextualActions(); return m_interface->contextualActions();
} }
K_EXPORT_PLASMA_APPLETSCRIPTENGINE_WITH_JSON(plasma_appletscript_declarative, DeclarativeAppletScript, "plasma-scriptengine-applet-declarative.json")
#include "declarativeappletscript.moc" #include "declarativeappletscript.moc"

View File

@ -24,7 +24,6 @@
#include <kdeclarative/qmlobject.h> #include <kdeclarative/qmlobject.h>
#include <kactioncollection.h> #include <kactioncollection.h>
#include <kservicetypetrader.h>
#include <kdesktopfile.h> #include <kdesktopfile.h>
#include <KConfigLoader> #include <KConfigLoader>
@ -35,6 +34,7 @@
#include <QSignalMapper> #include <QSignalMapper>
#include <Plasma/PluginLoader> #include <Plasma/PluginLoader>
#include <kpackage/packageloader.h>
QHash<QObject *, WallpaperInterface *> WallpaperInterface::s_rootObjects = QHash<QObject *, WallpaperInterface *>(); QHash<QObject *, WallpaperInterface *> WallpaperInterface::s_rootObjects = QHash<QObject *, WallpaperInterface *>();
@ -71,14 +71,14 @@ WallpaperInterface::~WallpaperInterface()
KPluginInfo::List WallpaperInterface::listWallpaperInfoForMimetype(const QString &mimetype, const QString &formFactor) KPluginInfo::List WallpaperInterface::listWallpaperInfoForMimetype(const QString &mimetype, const QString &formFactor)
{ {
QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype); auto filter = [&mimetype, &formFactor](const KPluginMetaData &md) -> bool
if (!formFactor.isEmpty()) { {
constraint.append("[X-Plasma-FormFactors] ~~ '").append(formFactor).append("'"); if (!formFactor.isEmpty() && !md.value("X-Plasma-FormFactors").contains(formFactor)) {
return false;
} }
return md.value("X-Plasma-DropMimeTypes").contains(mimetype);
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Wallpaper", constraint); };
qDebug() << offers.count() << constraint; return KPluginInfo::fromMetaData(KPackage::PackageLoader::self()->findPackages("Plasma/Wallpaper", QString(), filter).toVector());
return KPluginInfo::fromServices(offers);
} }
Plasma::Package WallpaperInterface::package() const Plasma::Package WallpaperInterface::package() const