2010-07-15 21:06:21 +00:00
|
|
|
/*
|
2020-08-13 19:08:54 +00:00
|
|
|
SPDX-FileCopyrightText: 2010 Ryan Rix <ry@n.rix.si>
|
|
|
|
|
|
|
|
SPDX-License-Identifier: LGPL-2.0-or-later
|
|
|
|
*/
|
2010-07-15 21:06:21 +00:00
|
|
|
|
|
|
|
#include "pluginloader.h"
|
2010-07-15 21:38:56 +00:00
|
|
|
|
2018-08-17 15:43:31 +02:00
|
|
|
#include <QPointer>
|
2013-07-10 03:27:19 +02:00
|
|
|
#include <QStandardPaths>
|
|
|
|
|
2013-07-29 19:05:59 +02:00
|
|
|
#include <QDebug>
|
2020-07-08 07:44:43 +02:00
|
|
|
#include <KService>
|
|
|
|
#include <KServiceTypeTrader>
|
|
|
|
#include <KPluginTrader>
|
2015-04-08 04:21:09 +02:00
|
|
|
#include <KPluginLoader>
|
2014-11-11 16:44:48 +01:00
|
|
|
#include <kpackage/packageloader.h>
|
2020-07-21 16:06:13 +02:00
|
|
|
#include <kdeclarative/kdeclarative.h>
|
2010-07-15 21:38:56 +00:00
|
|
|
|
2011-09-02 10:50:04 +02:00
|
|
|
#include "config-plasma.h"
|
|
|
|
|
2010-07-15 21:38:56 +00:00
|
|
|
#include "applet.h"
|
|
|
|
#include "containment.h"
|
2011-07-19 21:39:51 +02:00
|
|
|
#include "containmentactions.h"
|
2012-09-24 15:51:14 +02:00
|
|
|
#include "dataengine.h"
|
2011-07-15 13:34:10 +02:00
|
|
|
#include "package.h"
|
2010-07-15 21:38:56 +00:00
|
|
|
#include "private/applet_p.h"
|
|
|
|
#include "private/service_p.h" // for NullService
|
2010-10-23 17:02:49 +00:00
|
|
|
#include "private/storage_p.h"
|
2014-11-11 16:44:48 +01:00
|
|
|
#include "private/package_p.h"
|
|
|
|
#include "private/packagestructure_p.h"
|
2016-06-12 15:35:17 +02:00
|
|
|
#include <plasma/version.h>
|
2015-12-15 16:56:40 -05:00
|
|
|
#include "debug_p.h"
|
2010-07-15 21:06:21 +00:00
|
|
|
|
2014-04-26 01:45:47 +02:00
|
|
|
namespace Plasma
|
|
|
|
{
|
2010-07-15 21:06:21 +00:00
|
|
|
|
2018-04-13 13:58:44 +02:00
|
|
|
static PluginLoader *s_pluginLoader = nullptr;
|
2010-07-15 21:06:21 +00:00
|
|
|
|
2011-04-21 16:25:10 +02:00
|
|
|
class PluginLoaderPrivate
|
|
|
|
{
|
2011-07-19 21:40:12 +02:00
|
|
|
public:
|
2013-09-12 15:15:59 +02:00
|
|
|
PluginLoaderPrivate()
|
2016-10-05 01:56:07 +01:00
|
|
|
: isDefaultLoader(false)
|
2013-09-12 15:15:59 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-02-12 22:05:14 +01:00
|
|
|
static QSet<QString> knownCategories();
|
|
|
|
|
|
|
|
static QSet<QString> s_customCategories;
|
2018-08-17 15:43:31 +02:00
|
|
|
QHash<QString, QPointer<PackageStructure> > structures;
|
2011-07-19 21:40:12 +02:00
|
|
|
bool isDefaultLoader;
|
2015-05-07 16:26:37 +02:00
|
|
|
|
|
|
|
static QString s_dataEnginePluginDir;
|
|
|
|
static QString s_packageStructurePluginDir;
|
|
|
|
static QString s_plasmoidsPluginDir;
|
|
|
|
static QString s_servicesPluginDir;
|
|
|
|
static QString s_containmentActionsPluginDir;
|
2018-07-23 16:24:27 +02:00
|
|
|
|
2019-07-08 13:47:27 +02:00
|
|
|
class Cache {
|
|
|
|
// We only use this cache during start of the process to speed up many consecutive calls
|
|
|
|
// After that, we're too afraid to produce race conditions and it's not that time-critical anyway
|
|
|
|
// the 20 seconds here means that the cache is only used within 20sec during startup, after that,
|
|
|
|
// complexity goes up and we'd have to update the cache in order to avoid subtle bugs
|
|
|
|
// just not using the cache is way easier then, since it doesn't make *that* much of a difference,
|
|
|
|
// anyway
|
|
|
|
int maxCacheAge = 20;
|
|
|
|
qint64 pluginCacheAge = 0;
|
|
|
|
QHash<QString, QVector<KPluginMetaData>> plugins;
|
|
|
|
|
|
|
|
public:
|
|
|
|
QVector<KPluginMetaData> findPluginsById(const QString& name, const QStringList &dirs);
|
|
|
|
};
|
|
|
|
Cache plasmoidCache;
|
|
|
|
Cache dataengineCache;
|
|
|
|
Cache containmentactionCache;
|
2011-04-21 16:25:10 +02:00
|
|
|
};
|
|
|
|
|
2013-02-12 22:05:14 +01:00
|
|
|
QSet<QString> PluginLoaderPrivate::s_customCategories;
|
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
QString PluginLoaderPrivate::s_dataEnginePluginDir = QStringLiteral("plasma/dataengine");
|
|
|
|
QString PluginLoaderPrivate::s_packageStructurePluginDir = QStringLiteral("plasma/packagestructure");
|
|
|
|
QString PluginLoaderPrivate::s_plasmoidsPluginDir = QStringLiteral("plasma/applets");
|
|
|
|
QString PluginLoaderPrivate::s_servicesPluginDir = QStringLiteral("plasma/services");
|
|
|
|
QString PluginLoaderPrivate::s_containmentActionsPluginDir = QStringLiteral("plasma/containmentactions");
|
2015-05-07 16:26:37 +02:00
|
|
|
|
2013-02-12 22:05:14 +01:00
|
|
|
QSet<QString> PluginLoaderPrivate::knownCategories()
|
|
|
|
{
|
2018-10-22 21:05:29 +03:00
|
|
|
// this is to trick the translation tools into making the correct
|
2013-02-12 22:05:14 +01:00
|
|
|
// strings for translation
|
|
|
|
QSet<QString> categories = s_customCategories;
|
2016-02-29 00:08:05 +01:00
|
|
|
categories << QStringLiteral(I18N_NOOP("Accessibility")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Application Launchers")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Astronomy")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Date and Time")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Development Tools")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Education")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Environment and Weather")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Examples")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("File System")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Fun and Games")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Graphics")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Language")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Mapping")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Miscellaneous")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Multimedia")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Online Services")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Productivity")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("System Information")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Utilities")).toLower()
|
2016-03-09 12:44:00 +01:00
|
|
|
<< QStringLiteral(I18N_NOOP("Windows and Tasks")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Clipboard")).toLower()
|
|
|
|
<< QStringLiteral(I18N_NOOP("Tasks")).toLower();
|
2013-02-12 22:05:14 +01:00
|
|
|
return categories;
|
|
|
|
}
|
|
|
|
|
2010-07-15 21:11:20 +00:00
|
|
|
PluginLoader::PluginLoader()
|
2011-07-19 21:40:12 +02:00
|
|
|
: d(new PluginLoaderPrivate)
|
2010-07-15 21:11:20 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-07-15 21:06:21 +00:00
|
|
|
PluginLoader::~PluginLoader()
|
|
|
|
{
|
2018-08-17 15:43:31 +02:00
|
|
|
typedef QPointer<PackageStructure> pswp;
|
2019-03-20 07:12:03 +01:00
|
|
|
for (pswp wp : qAsConst(d->structures)) {
|
2011-07-19 21:40:12 +02:00
|
|
|
delete wp.data();
|
|
|
|
}
|
2011-04-20 18:37:07 +02:00
|
|
|
delete d;
|
2010-07-15 21:06:21 +00:00
|
|
|
}
|
|
|
|
|
2014-04-26 01:45:47 +02:00
|
|
|
void PluginLoader::setPluginLoader(PluginLoader *loader)
|
2010-07-15 21:06:21 +00:00
|
|
|
{
|
2010-07-15 21:38:56 +00:00
|
|
|
if (!s_pluginLoader) {
|
2010-07-15 21:06:21 +00:00
|
|
|
s_pluginLoader = loader;
|
|
|
|
} else {
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2015-12-15 16:56:40 -05:00
|
|
|
// qCDebug(LOG_PLASMA) << "Cannot set pluginLoader, already set!" << s_pluginLoader;
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2010-07-15 21:06:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-19 21:40:12 +02:00
|
|
|
PluginLoader *PluginLoader::self()
|
2010-07-15 21:06:21 +00:00
|
|
|
{
|
2010-07-15 21:38:56 +00:00
|
|
|
if (!s_pluginLoader) {
|
|
|
|
// we have been called before any PluginLoader was set, so just use the default
|
|
|
|
// implementation. this prevents plugins from nefariously injecting their own
|
|
|
|
// plugin loader if the app doesn't
|
|
|
|
s_pluginLoader = new PluginLoader;
|
2011-07-19 21:40:12 +02:00
|
|
|
s_pluginLoader->d->isDefaultLoader = true;
|
2010-07-15 21:38:56 +00:00
|
|
|
}
|
|
|
|
|
2010-07-15 21:06:21 +00:00
|
|
|
return s_pluginLoader;
|
|
|
|
}
|
|
|
|
|
2010-07-15 21:38:56 +00:00
|
|
|
Applet *PluginLoader::loadApplet(const QString &name, uint appletId, const QVariantList &args)
|
2011-07-19 21:40:12 +02:00
|
|
|
{
|
2010-07-15 21:38:56 +00:00
|
|
|
if (name.isEmpty()) {
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2010-07-15 21:38:56 +00:00
|
|
|
}
|
|
|
|
|
2018-04-13 13:58:44 +02:00
|
|
|
Applet *applet = d->isDefaultLoader ? nullptr : internalLoadApplet(name, appletId, args);
|
2010-07-15 21:38:56 +00:00
|
|
|
if (applet) {
|
|
|
|
return applet;
|
|
|
|
}
|
|
|
|
|
2015-05-07 16:26:37 +02:00
|
|
|
if (appletId == 0) {
|
|
|
|
appletId = ++AppletPrivate::s_maxAppletId;
|
|
|
|
}
|
2010-07-15 21:38:56 +00:00
|
|
|
|
2019-07-08 13:47:27 +02:00
|
|
|
// Need to pass the empty directory because it's where plasmoids used to be
|
2019-07-23 10:47:33 +02:00
|
|
|
auto plugins = d->plasmoidCache.findPluginsById(name, { PluginLoaderPrivate::s_plasmoidsPluginDir, {} });
|
2015-05-07 16:26:37 +02:00
|
|
|
|
2017-12-09 10:37:02 +01:00
|
|
|
const KPackage::Package p = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Applet"), name);
|
|
|
|
|
2019-07-23 10:47:33 +02:00
|
|
|
// If the applet is using another applet package, search for the plugin of the other applet
|
|
|
|
if (plugins.isEmpty()) {
|
|
|
|
const QString parentPlugin = p.metadata().value(QStringLiteral("X-Plasma-RootPath"));
|
|
|
|
if (!parentPlugin.isEmpty()) {
|
|
|
|
plugins = d->plasmoidCache.findPluginsById(parentPlugin, { PluginLoaderPrivate::s_plasmoidsPluginDir, {} });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 00:08:05 +01:00
|
|
|
if (!plugins.isEmpty()) {
|
2016-09-14 13:38:56 +01:00
|
|
|
KPluginLoader loader(plugins.first().fileName());
|
2016-06-12 15:35:17 +02:00
|
|
|
if (!isPluginVersionCompatible(loader)) {
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2015-05-07 16:26:37 +02:00
|
|
|
}
|
|
|
|
KPluginFactory *factory = loader.factory();
|
|
|
|
if (factory) {
|
|
|
|
QVariantList allArgs;
|
2017-12-09 10:37:02 +01:00
|
|
|
allArgs << QVariant::fromValue(p) << loader.metaData().toVariantMap() << appletId << args;
|
2018-04-13 13:58:44 +02:00
|
|
|
applet = factory->create<Plasma::Applet>(nullptr, allArgs);
|
2010-07-15 21:38:56 +00:00
|
|
|
}
|
|
|
|
}
|
2015-05-07 16:26:37 +02:00
|
|
|
if (applet) {
|
|
|
|
return applet;
|
2010-07-15 21:38:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!applet) {
|
2015-12-15 16:56:40 -05:00
|
|
|
//qCDebug(LOG_PLASMA) << name << "not a C++ applet: Falling back to an empty one";
|
2015-05-07 16:26:37 +02:00
|
|
|
|
2016-10-13 10:18:06 +02:00
|
|
|
QVariantList allArgs;
|
2017-12-09 10:37:02 +01:00
|
|
|
allArgs << QVariant::fromValue(p) << p.metadata().fileName() << appletId << args;
|
2015-02-20 13:35:30 +01:00
|
|
|
|
2019-08-29 07:23:49 +02:00
|
|
|
if (p.metadata().serviceTypes().contains(QLatin1String("Plasma/Containment"))) {
|
2018-04-13 13:58:44 +02:00
|
|
|
applet = new Containment(nullptr, allArgs);
|
2015-02-20 13:35:30 +01:00
|
|
|
} else {
|
2018-04-13 13:58:44 +02:00
|
|
|
applet = new Applet(nullptr, allArgs);
|
2015-02-20 13:35:30 +01:00
|
|
|
}
|
2015-05-07 16:26:37 +02:00
|
|
|
|
2010-07-15 21:38:56 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 13:18:31 +01:00
|
|
|
const QString localePath = p.filePath("translations");
|
|
|
|
if (!localePath.isEmpty()) {
|
|
|
|
KLocalizedString::addDomainLocaleDir(QByteArray("plasma_applet_") + name.toLatin1(), localePath);
|
|
|
|
}
|
2010-07-15 21:38:56 +00:00
|
|
|
return applet;
|
2010-07-15 21:06:21 +00:00
|
|
|
}
|
|
|
|
|
2010-07-15 21:38:56 +00:00
|
|
|
DataEngine *PluginLoader::loadDataEngine(const QString &name)
|
2011-10-04 16:50:44 +02:00
|
|
|
{
|
2018-04-13 13:58:44 +02:00
|
|
|
DataEngine *engine = d->isDefaultLoader ? nullptr : internalLoadDataEngine(name);
|
2010-07-15 21:38:56 +00:00
|
|
|
if (engine) {
|
|
|
|
return engine;
|
|
|
|
}
|
|
|
|
|
2015-04-08 04:21:09 +02:00
|
|
|
// Look for C++ plugins first
|
2019-07-08 13:47:27 +02:00
|
|
|
const QVector<KPluginMetaData> plugins = d->dataengineCache.findPluginsById(name, {PluginLoaderPrivate::s_dataEnginePluginDir});
|
2016-02-29 00:08:05 +01:00
|
|
|
if (!plugins.isEmpty()) {
|
2019-07-08 13:47:27 +02:00
|
|
|
KPluginLoader loader(plugins.constFirst().fileName());
|
2015-04-08 04:21:09 +02:00
|
|
|
const QVariantList argsWithMetaData = QVariantList() << loader.metaData().toVariantMap();
|
|
|
|
KPluginFactory *factory = loader.factory();
|
2019-07-08 13:47:27 +02:00
|
|
|
return factory ? factory->create<Plasma::DataEngine>(nullptr, argsWithMetaData) : nullptr;
|
2015-04-08 04:21:09 +02:00
|
|
|
}
|
|
|
|
if (engine) {
|
|
|
|
return engine;
|
|
|
|
}
|
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
const KPackage::Package p = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/DataEngine"), name);
|
2015-05-07 16:26:37 +02:00
|
|
|
if (!p.isValid()) {
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2010-07-15 21:38:56 +00:00
|
|
|
}
|
|
|
|
|
2018-04-13 13:58:44 +02:00
|
|
|
return new DataEngine(KPluginInfo(p.metadata().fileName()), nullptr);
|
2010-07-15 21:38:56 +00:00
|
|
|
}
|
|
|
|
|
2013-04-04 17:33:55 +02:00
|
|
|
QStringList PluginLoader::listAllEngines(const QString &parentApp)
|
|
|
|
{
|
2015-05-07 16:26:37 +02:00
|
|
|
QStringList engines;
|
|
|
|
// Look for C++ plugins first
|
|
|
|
auto filter = [&parentApp](const KPluginMetaData &md) -> bool
|
|
|
|
{
|
2015-11-27 20:03:48 +00:00
|
|
|
return md.value(QStringLiteral("X-KDE-ParentApp")) == parentApp;
|
2015-05-07 16:26:37 +02:00
|
|
|
};
|
|
|
|
QVector<KPluginMetaData> plugins;
|
2013-04-04 17:33:55 +02:00
|
|
|
if (parentApp.isEmpty()) {
|
2015-05-07 16:26:37 +02:00
|
|
|
plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_dataEnginePluginDir);
|
2013-04-04 17:33:55 +02:00
|
|
|
} else {
|
2015-05-07 16:26:37 +02:00
|
|
|
plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_dataEnginePluginDir, filter);
|
2013-04-04 17:33:55 +02:00
|
|
|
}
|
|
|
|
|
2019-03-20 07:12:03 +01:00
|
|
|
for (auto& plugin : qAsConst(plugins)) {
|
2015-05-07 16:26:37 +02:00
|
|
|
engines << plugin.pluginId();
|
|
|
|
}
|
2013-04-04 17:33:55 +02:00
|
|
|
|
2016-02-29 00:08:05 +01:00
|
|
|
const QList<KPluginMetaData> packagePlugins = KPackage::PackageLoader::self()->listPackages(QStringLiteral("Plasma/DataEngine"));
|
2019-03-20 07:12:03 +01:00
|
|
|
for (const auto &plugin : packagePlugins) {
|
2015-05-07 16:26:37 +02:00
|
|
|
engines << plugin.pluginId();
|
2013-04-04 17:33:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return engines;
|
|
|
|
}
|
|
|
|
|
|
|
|
KPluginInfo::List PluginLoader::listEngineInfo(const QString &parentApp)
|
|
|
|
{
|
|
|
|
return PluginLoader::self()->listDataEngineInfo(parentApp);
|
|
|
|
}
|
|
|
|
|
|
|
|
KPluginInfo::List PluginLoader::listEngineInfoByCategory(const QString &category, const QString &parentApp)
|
|
|
|
{
|
2015-05-07 16:26:37 +02:00
|
|
|
KPluginInfo::List list;
|
2013-04-04 17:33:55 +02:00
|
|
|
|
2015-05-07 16:26:37 +02:00
|
|
|
// Look for C++ plugins first
|
|
|
|
auto filterNormal = [&category](const KPluginMetaData &md) -> bool
|
|
|
|
{
|
2015-11-27 20:03:48 +00:00
|
|
|
return md.value(QStringLiteral("X-KDE-PluginInfo-Category")) == category;
|
2015-05-07 16:26:37 +02:00
|
|
|
};
|
|
|
|
auto filterParentApp = [&category, &parentApp](const KPluginMetaData &md) -> bool
|
|
|
|
{
|
2015-11-27 20:03:48 +00:00
|
|
|
return md.value(QStringLiteral("X-KDE-ParentApp")) == parentApp
|
|
|
|
&& md.value(QStringLiteral("X-KDE-PluginInfo-Category")) == category;
|
2015-05-07 16:26:37 +02:00
|
|
|
};
|
|
|
|
QVector<KPluginMetaData> plugins;
|
2013-04-04 17:33:55 +02:00
|
|
|
if (parentApp.isEmpty()) {
|
2015-05-07 16:26:37 +02:00
|
|
|
plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_dataEnginePluginDir, filterNormal);
|
2013-04-04 17:33:55 +02:00
|
|
|
} else {
|
2015-05-07 16:26:37 +02:00
|
|
|
plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_dataEnginePluginDir, filterParentApp);
|
2013-04-04 17:33:55 +02:00
|
|
|
}
|
|
|
|
|
2015-05-07 16:26:37 +02:00
|
|
|
list = KPluginInfo::fromMetaData(plugins);
|
|
|
|
|
|
|
|
|
|
|
|
//TODO FIXME: PackageLoader needs to have a function to inject packageStructures
|
2016-02-29 00:08:05 +01:00
|
|
|
const QList<KPluginMetaData> packagePlugins = KPackage::PackageLoader::self()->listPackages(QStringLiteral("Plasma/DataEngine"));
|
2015-05-07 16:26:37 +02:00
|
|
|
list << KPluginInfo::fromMetaData(packagePlugins.toVector());
|
|
|
|
|
|
|
|
return list;
|
2013-04-04 17:33:55 +02:00
|
|
|
}
|
|
|
|
|
2010-07-15 21:38:56 +00:00
|
|
|
Service *PluginLoader::loadService(const QString &name, const QVariantList &args, QObject *parent)
|
2011-07-13 20:20:36 +02:00
|
|
|
{
|
2018-04-13 13:58:44 +02:00
|
|
|
Service *service = d->isDefaultLoader ? nullptr : internalLoadService(name, args, parent);
|
2010-07-15 21:38:56 +00:00
|
|
|
if (service) {
|
|
|
|
return service;
|
|
|
|
}
|
|
|
|
|
|
|
|
//TODO: scripting API support
|
|
|
|
if (name.isEmpty()) {
|
|
|
|
return new NullService(QString(), parent);
|
2015-11-27 20:03:48 +00:00
|
|
|
} else if (name == QLatin1String("org.kde.servicestorage")) {
|
2010-10-23 17:02:49 +00:00
|
|
|
return new Storage(parent);
|
2010-07-15 21:38:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-07 16:26:37 +02:00
|
|
|
// Look for C++ plugins first
|
|
|
|
auto filter = [&name](const KPluginMetaData &md) -> bool
|
|
|
|
{
|
|
|
|
return md.pluginId() == name;
|
|
|
|
};
|
|
|
|
QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(PluginLoaderPrivate::s_servicesPluginDir, filter);
|
2010-07-15 21:38:56 +00:00
|
|
|
|
2016-02-29 00:08:05 +01:00
|
|
|
if (!plugins.isEmpty()) {
|
2016-09-14 13:38:56 +01:00
|
|
|
KPluginLoader loader(plugins.first().fileName());
|
2016-06-12 15:35:17 +02:00
|
|
|
if (!isPluginVersionCompatible(loader)) {
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2015-05-07 16:26:37 +02:00
|
|
|
}
|
|
|
|
KPluginFactory *factory = loader.factory();
|
|
|
|
if (factory) {
|
2018-04-13 13:58:44 +02:00
|
|
|
service = factory->create<Plasma::Service>(nullptr, args);
|
2015-05-07 16:26:37 +02:00
|
|
|
}
|
2010-07-15 21:38:56 +00:00
|
|
|
}
|
|
|
|
|
2015-05-07 16:26:37 +02:00
|
|
|
if (service) {
|
|
|
|
if (service->name().isEmpty()) {
|
|
|
|
service->setName(name);
|
|
|
|
}
|
|
|
|
return service;
|
|
|
|
} else {
|
2010-07-15 21:38:56 +00:00
|
|
|
return new NullService(name, parent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-19 21:39:51 +02:00
|
|
|
ContainmentActions *PluginLoader::loadContainmentActions(Containment *parent, const QString &name, const QVariantList &args)
|
|
|
|
{
|
|
|
|
if (name.isEmpty()) {
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2011-07-19 21:39:51 +02:00
|
|
|
}
|
|
|
|
|
2018-04-13 13:58:44 +02:00
|
|
|
ContainmentActions *actions = d->isDefaultLoader ? nullptr : internalLoadContainmentActions(parent, name, args);
|
2011-07-19 21:39:51 +02:00
|
|
|
if (actions) {
|
|
|
|
return actions;
|
|
|
|
}
|
|
|
|
|
2019-07-08 13:47:27 +02:00
|
|
|
const QVector<KPluginMetaData> plugins = d->containmentactionCache.findPluginsById(name, {PluginLoaderPrivate::s_containmentActionsPluginDir});
|
2015-05-07 16:26:37 +02:00
|
|
|
|
2016-02-29 00:08:05 +01:00
|
|
|
if (!plugins.isEmpty()) {
|
2016-09-14 13:38:56 +01:00
|
|
|
KPluginLoader loader(plugins.first().fileName());
|
2015-05-07 16:26:37 +02:00
|
|
|
KPluginFactory *factory = loader.factory();
|
|
|
|
if (factory) {
|
2019-07-05 01:03:51 +02:00
|
|
|
actions = factory->create<Plasma::ContainmentActions>(nullptr, {QVariant::fromValue(plugins.first())});
|
2015-05-07 16:26:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (actions) {
|
|
|
|
return actions;
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME: this is only for backwards compatibility, but probably will have to stay
|
|
|
|
//for the time being
|
2015-11-27 20:03:48 +00:00
|
|
|
QString constraint = QStringLiteral("[X-KDE-PluginInfo-Name] == '%1'").arg(name);
|
|
|
|
KService::List offers = KServiceTypeTrader::self()->query(QStringLiteral("Plasma/ContainmentActions"), constraint);
|
2011-07-19 21:39:51 +02:00
|
|
|
|
|
|
|
if (offers.isEmpty()) {
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2015-12-15 16:56:40 -05:00
|
|
|
qCDebug(LOG_PLASMA) << "offers is empty for " << name;
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2011-07-19 21:39:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
KService::Ptr offer = offers.first();
|
|
|
|
KPluginLoader plugin(*offer);
|
|
|
|
|
2016-06-12 15:35:17 +02:00
|
|
|
if (!isPluginVersionCompatible(plugin)) {
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2011-07-19 21:39:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QVariantList allArgs;
|
|
|
|
allArgs << offer->storageId() << args;
|
|
|
|
QString error;
|
|
|
|
actions = offer->createInstance<Plasma::ContainmentActions>(parent, allArgs, &error);
|
|
|
|
|
|
|
|
if (!actions) {
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2015-12-15 16:56:40 -05:00
|
|
|
// qCDebug(LOG_PLASMA) << "Couldn't load containmentActions \"" << name << "\"! reason given: " << error;
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2011-07-19 21:39:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return actions;
|
|
|
|
}
|
|
|
|
|
2011-07-15 13:34:10 +02:00
|
|
|
Package PluginLoader::loadPackage(const QString &packageFormat, const QString &specialization)
|
2011-07-13 20:20:36 +02:00
|
|
|
{
|
2011-07-19 21:39:51 +02:00
|
|
|
if (!d->isDefaultLoader) {
|
2011-07-15 13:34:10 +02:00
|
|
|
Package p = internalLoadPackage(packageFormat, specialization);
|
2014-08-08 14:11:50 +02:00
|
|
|
if (p.hasValidStructure()) {
|
2011-07-13 20:25:47 +02:00
|
|
|
return p;
|
|
|
|
}
|
2011-07-13 20:20:36 +02:00
|
|
|
}
|
|
|
|
|
2011-07-15 13:34:10 +02:00
|
|
|
if (packageFormat.isEmpty()) {
|
|
|
|
return Package();
|
|
|
|
}
|
|
|
|
|
2017-12-02 15:12:40 +01:00
|
|
|
const QString hashkey = packageFormat + QLatin1Char('%') + specialization;
|
2011-07-19 21:40:12 +02:00
|
|
|
PackageStructure *structure = d->structures.value(hashkey).data();
|
2014-11-11 16:44:48 +01:00
|
|
|
|
2011-07-19 21:40:12 +02:00
|
|
|
if (structure) {
|
|
|
|
return Package(structure);
|
|
|
|
}
|
|
|
|
|
2016-08-04 19:23:59 +02:00
|
|
|
KPackage::PackageStructure *internalStructure = KPackage::PackageLoader::self()->loadPackageStructure(packageFormat);
|
2014-11-11 16:44:48 +01:00
|
|
|
|
|
|
|
if (internalStructure) {
|
|
|
|
structure = new PackageStructure();
|
|
|
|
structure->d->internalStructure = internalStructure;
|
|
|
|
//fallback to old structures
|
|
|
|
} else {
|
2016-02-29 00:08:05 +01:00
|
|
|
const QString constraint = QStringLiteral("[X-KDE-PluginInfo-Name] == '%1'").arg(packageFormat);
|
2018-04-13 13:58:44 +02:00
|
|
|
structure = KPluginTrader::createInstanceFromQuery<Plasma::PackageStructure>(PluginLoaderPrivate::s_packageStructurePluginDir, QStringLiteral("Plasma/PackageStructure"), constraint, nullptr);
|
2014-11-11 16:44:48 +01:00
|
|
|
if (structure) {
|
|
|
|
structure->d->internalStructure = new PackageStructureWrapper(structure);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-29 12:19:08 +02:00
|
|
|
if (structure) {
|
|
|
|
d->structures.insert(hashkey, structure);
|
|
|
|
return Package(structure);
|
|
|
|
}
|
2011-07-15 13:34:10 +02:00
|
|
|
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2015-12-15 16:56:40 -05:00
|
|
|
// qCDebug(LOG_PLASMA) << "Couldn't load Package for" << packageFormat << "! reason given: " << error;
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2011-07-15 13:34:10 +02:00
|
|
|
|
2011-07-19 21:40:12 +02:00
|
|
|
return Package();
|
2011-07-13 20:20:36 +02:00
|
|
|
}
|
|
|
|
|
2016-10-10 16:27:50 +02:00
|
|
|
QList<KPluginMetaData> PluginLoader::listAppletMetaData(const QString &category, const QString &parentApp)
|
Moving Plasma::Applet::listAppletInfo into the PluginLoader logic. Also implemented internalAppletNames which, if implemented, will return a QStringList of the available applets' names. PluginLoader::listAppletInfo will then search for .desktop files in $APPDATA/plasma/applets/ which match the applets' names (ie. $APPDATA/plasma/applets/org.skrooge.report.desktop), and add them to the KPluginInfo::List returned by PluginLoader::listAppletInfo and subsequently Plasma::Applet::listAppletInfo.
Since the applets are dynamically loaded, the .desktop files don't need an X-KDE-Library entries, but the others will be used, for example X-KDE-PluginInfo-Name (which will be the value given to PluginLoader::internalAppletLoad, so it is really important), Icon, Type, ServiceTypes...
svn path=/trunk/KDE/kdelibs/; revision=1154551
2010-07-25 20:56:03 +00:00
|
|
|
{
|
2020-07-21 16:06:13 +02:00
|
|
|
auto platforms = KDeclarative::KDeclarative::runtimePlatform();
|
|
|
|
// For now desktop always lists everything
|
|
|
|
if (platforms.contains(QStringLiteral("desktop"))) {
|
|
|
|
platforms.clear();
|
|
|
|
}
|
|
|
|
|
2015-05-07 16:26:37 +02:00
|
|
|
//FIXME: this assumes we are always use packages.. no pure c++
|
2016-10-10 16:27:50 +02:00
|
|
|
std::function<bool(const KPluginMetaData&)> filter;
|
Moving Plasma::Applet::listAppletInfo into the PluginLoader logic. Also implemented internalAppletNames which, if implemented, will return a QStringList of the available applets' names. PluginLoader::listAppletInfo will then search for .desktop files in $APPDATA/plasma/applets/ which match the applets' names (ie. $APPDATA/plasma/applets/org.skrooge.report.desktop), and add them to the KPluginInfo::List returned by PluginLoader::listAppletInfo and subsequently Plasma::Applet::listAppletInfo.
Since the applets are dynamically loaded, the .desktop files don't need an X-KDE-Library entries, but the others will be used, for example X-KDE-PluginInfo-Name (which will be the value given to PluginLoader::internalAppletLoad, so it is really important), Icon, Type, ServiceTypes...
svn path=/trunk/KDE/kdelibs/; revision=1154551
2010-07-25 20:56:03 +00:00
|
|
|
if (category.isEmpty()) { //use all but the excluded categories
|
2012-03-24 19:33:54 +01:00
|
|
|
KConfigGroup group(KSharedConfig::openConfig(), "General");
|
Moving Plasma::Applet::listAppletInfo into the PluginLoader logic. Also implemented internalAppletNames which, if implemented, will return a QStringList of the available applets' names. PluginLoader::listAppletInfo will then search for .desktop files in $APPDATA/plasma/applets/ which match the applets' names (ie. $APPDATA/plasma/applets/org.skrooge.report.desktop), and add them to the KPluginInfo::List returned by PluginLoader::listAppletInfo and subsequently Plasma::Applet::listAppletInfo.
Since the applets are dynamically loaded, the .desktop files don't need an X-KDE-Library entries, but the others will be used, for example X-KDE-PluginInfo-Name (which will be the value given to PluginLoader::internalAppletLoad, so it is really important), Icon, Type, ServiceTypes...
svn path=/trunk/KDE/kdelibs/; revision=1154551
2010-07-25 20:56:03 +00:00
|
|
|
QStringList excluded = group.readEntry("ExcludeCategories", QStringList());
|
2015-05-07 16:26:37 +02:00
|
|
|
|
2020-07-21 16:06:13 +02:00
|
|
|
filter = [excluded, parentApp, platforms](const KPluginMetaData &md) -> bool
|
2015-05-07 16:26:37 +02:00
|
|
|
{
|
2020-07-21 16:06:13 +02:00
|
|
|
if (!platforms.isEmpty() && !md.formFactors().isEmpty()) {
|
|
|
|
bool found = false;
|
|
|
|
for (const auto &plat : platforms) {
|
|
|
|
if (md.formFactors().contains(plat)) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
const QString pa = md.value(QStringLiteral("X-KDE-ParentApp"));
|
pluginloader: Change behavior of X-KDE-ParentApp
Summary:
X-KDE-ParentApp is the key in desktop file to display that given service
or application is part of the another application or extension of other
application. In KDE4 this key was used to mark applets to be used in the
specific application like plasma-desktop, kdevelop, amarok etc.
In KF5 world, none of this applications have applet loading mechanism
apart from plasma*, and there are likely only Plasma applet, containment
or dataengines.
Previous API, when no/empty parentApp was passed would filter out every
application which had something as parentApp. This was to ensure only
compatible plugins are loaded in Plasma. This resulted in applets
getting excluded if they suggested that org.kde.plasmashell is their
parent application. Refine this API to,
- If no/empty parentApp is provided, provide all applets
- If parentApp is provided, filter by applet
This behavior is more filter like instead of other way around.
CHANGELOG: Applet, DataEngine and containment listing methods in
Plasma::PluginLoader no longer filters the plugins with X-KDE-ParentApp
provided when empty string is passed.
Test Plan:
tested that plasma loads properly, plasmaengineexplorer lists
all engines and plasmawindowed works fine. Neverthless requires more testing
Reviewers: mart, apol
Subscribers: kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D22049
2019-06-23 20:25:28 +05:30
|
|
|
return (parentApp.isEmpty() || pa == parentApp) && !excluded.contains(md.category());
|
2015-05-07 16:26:37 +02:00
|
|
|
};
|
Moving Plasma::Applet::listAppletInfo into the PluginLoader logic. Also implemented internalAppletNames which, if implemented, will return a QStringList of the available applets' names. PluginLoader::listAppletInfo will then search for .desktop files in $APPDATA/plasma/applets/ which match the applets' names (ie. $APPDATA/plasma/applets/org.skrooge.report.desktop), and add them to the KPluginInfo::List returned by PluginLoader::listAppletInfo and subsequently Plasma::Applet::listAppletInfo.
Since the applets are dynamically loaded, the .desktop files don't need an X-KDE-Library entries, but the others will be used, for example X-KDE-PluginInfo-Name (which will be the value given to PluginLoader::internalAppletLoad, so it is really important), Icon, Type, ServiceTypes...
svn path=/trunk/KDE/kdelibs/; revision=1154551
2010-07-25 20:56:03 +00:00
|
|
|
} else { //specific category (this could be an excluded one - is that bad?)
|
|
|
|
|
2020-07-21 16:06:13 +02:00
|
|
|
filter = [category, parentApp, platforms](const KPluginMetaData &md) -> bool
|
2015-05-07 16:26:37 +02:00
|
|
|
{
|
2020-07-21 16:06:13 +02:00
|
|
|
if (!platforms.isEmpty() && !md.formFactors().isEmpty()) {
|
|
|
|
bool found = false;
|
|
|
|
for (const auto &plat : platforms) {
|
|
|
|
if (md.formFactors().contains(plat)) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
const QString pa = md.value(QStringLiteral("X-KDE-ParentApp"));
|
2020-07-21 16:06:13 +02:00
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
if (category == QLatin1String("Miscellaneous")) {
|
pluginloader: Change behavior of X-KDE-ParentApp
Summary:
X-KDE-ParentApp is the key in desktop file to display that given service
or application is part of the another application or extension of other
application. In KDE4 this key was used to mark applets to be used in the
specific application like plasma-desktop, kdevelop, amarok etc.
In KF5 world, none of this applications have applet loading mechanism
apart from plasma*, and there are likely only Plasma applet, containment
or dataengines.
Previous API, when no/empty parentApp was passed would filter out every
application which had something as parentApp. This was to ensure only
compatible plugins are loaded in Plasma. This resulted in applets
getting excluded if they suggested that org.kde.plasmashell is their
parent application. Refine this API to,
- If no/empty parentApp is provided, provide all applets
- If parentApp is provided, filter by applet
This behavior is more filter like instead of other way around.
CHANGELOG: Applet, DataEngine and containment listing methods in
Plasma::PluginLoader no longer filters the plugins with X-KDE-ParentApp
provided when empty string is passed.
Test Plan:
tested that plasma loads properly, plasmaengineexplorer lists
all engines and plasmawindowed works fine. Neverthless requires more testing
Reviewers: mart, apol
Subscribers: kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D22049
2019-06-23 20:25:28 +05:30
|
|
|
return (parentApp.isEmpty() || pa == parentApp) && (md.category() == category || md.category().isEmpty());
|
2015-05-07 16:26:37 +02:00
|
|
|
} else {
|
pluginloader: Change behavior of X-KDE-ParentApp
Summary:
X-KDE-ParentApp is the key in desktop file to display that given service
or application is part of the another application or extension of other
application. In KDE4 this key was used to mark applets to be used in the
specific application like plasma-desktop, kdevelop, amarok etc.
In KF5 world, none of this applications have applet loading mechanism
apart from plasma*, and there are likely only Plasma applet, containment
or dataengines.
Previous API, when no/empty parentApp was passed would filter out every
application which had something as parentApp. This was to ensure only
compatible plugins are loaded in Plasma. This resulted in applets
getting excluded if they suggested that org.kde.plasmashell is their
parent application. Refine this API to,
- If no/empty parentApp is provided, provide all applets
- If parentApp is provided, filter by applet
This behavior is more filter like instead of other way around.
CHANGELOG: Applet, DataEngine and containment listing methods in
Plasma::PluginLoader no longer filters the plugins with X-KDE-ParentApp
provided when empty string is passed.
Test Plan:
tested that plasma loads properly, plasmaengineexplorer lists
all engines and plasmawindowed works fine. Neverthless requires more testing
Reviewers: mart, apol
Subscribers: kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D22049
2019-06-23 20:25:28 +05:30
|
|
|
return (parentApp.isEmpty() || pa == parentApp) && md.category() == category;
|
2015-05-07 16:26:37 +02:00
|
|
|
}
|
|
|
|
};
|
2016-10-10 16:27:50 +02:00
|
|
|
}
|
Moving Plasma::Applet::listAppletInfo into the PluginLoader logic. Also implemented internalAppletNames which, if implemented, will return a QStringList of the available applets' names. PluginLoader::listAppletInfo will then search for .desktop files in $APPDATA/plasma/applets/ which match the applets' names (ie. $APPDATA/plasma/applets/org.skrooge.report.desktop), and add them to the KPluginInfo::List returned by PluginLoader::listAppletInfo and subsequently Plasma::Applet::listAppletInfo.
Since the applets are dynamically loaded, the .desktop files don't need an X-KDE-Library entries, but the others will be used, for example X-KDE-PluginInfo-Name (which will be the value given to PluginLoader::internalAppletLoad, so it is really important), Icon, Type, ServiceTypes...
svn path=/trunk/KDE/kdelibs/; revision=1154551
2010-07-25 20:56:03 +00:00
|
|
|
|
2016-10-10 16:27:50 +02:00
|
|
|
QList<KPluginMetaData> list;
|
|
|
|
if (!d->isDefaultLoader && (parentApp.isEmpty() || parentApp == QCoreApplication::instance()->applicationName())) {
|
|
|
|
list = KPluginInfo::toMetaData(internalAppletInfo(category)).toList();
|
|
|
|
}
|
|
|
|
return KPackage::PackageLoader::self()->findPackages(QStringLiteral("Plasma/Applet"), QString(), filter);
|
|
|
|
}
|
2015-06-10 09:35:21 -07:00
|
|
|
|
2016-10-10 16:27:50 +02:00
|
|
|
KPluginInfo::List PluginLoader::listAppletInfo(const QString &category, const QString &parentApp)
|
|
|
|
{
|
|
|
|
const auto plugins = listAppletMetaData(category, parentApp);
|
|
|
|
|
2020-05-10 17:03:56 +02:00
|
|
|
#if KSERVICE_BUILD_DEPRECATED_SINCE(5, 0)
|
|
|
|
KPluginInfo::List list;
|
2016-10-10 16:27:50 +02:00
|
|
|
//NOTE: it still produces kplugininfos from KServices because some user code expects
|
2018-10-22 21:05:29 +03:00
|
|
|
//info.service() to be valid and would crash otherwise
|
2019-03-20 07:12:03 +01:00
|
|
|
for (const auto &md : plugins) {
|
2020-05-10 17:03:56 +02:00
|
|
|
QT_WARNING_PUSH
|
|
|
|
QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
|
|
|
|
QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
|
2017-12-02 15:12:40 +01:00
|
|
|
auto pi = md.metaDataFileName().endsWith(QLatin1String(".json")) ? KPluginInfo(md) : KPluginInfo(KService::serviceByStorageId(md.metaDataFileName()));
|
2020-05-10 17:03:56 +02:00
|
|
|
QT_WARNING_POP
|
2016-10-10 16:27:50 +02:00
|
|
|
if (!pi.isValid()) {
|
|
|
|
qCWarning(LOG_PLASMA) << "Could not load plugin info for plugin :" << md.pluginId() << "skipping plugin";
|
|
|
|
continue;
|
2015-05-07 16:26:37 +02:00
|
|
|
}
|
2016-10-10 16:27:50 +02:00
|
|
|
list << pi;
|
2015-05-07 16:26:37 +02:00
|
|
|
}
|
2016-10-10 16:27:50 +02:00
|
|
|
return list;
|
2020-05-10 17:03:56 +02:00
|
|
|
#else
|
|
|
|
return KPluginInfo::fromMetaData(plugins.toVector());
|
|
|
|
#endif
|
Moving Plasma::Applet::listAppletInfo into the PluginLoader logic. Also implemented internalAppletNames which, if implemented, will return a QStringList of the available applets' names. PluginLoader::listAppletInfo will then search for .desktop files in $APPDATA/plasma/applets/ which match the applets' names (ie. $APPDATA/plasma/applets/org.skrooge.report.desktop), and add them to the KPluginInfo::List returned by PluginLoader::listAppletInfo and subsequently Plasma::Applet::listAppletInfo.
Since the applets are dynamically loaded, the .desktop files don't need an X-KDE-Library entries, but the others will be used, for example X-KDE-PluginInfo-Name (which will be the value given to PluginLoader::internalAppletLoad, so it is really important), Icon, Type, ServiceTypes...
svn path=/trunk/KDE/kdelibs/; revision=1154551
2010-07-25 20:56:03 +00:00
|
|
|
}
|
|
|
|
|
2017-05-31 02:15:16 +02:00
|
|
|
QList<KPluginMetaData> PluginLoader::listAppletMetaDataForMimeType(const QString &mimeType)
|
2013-02-12 21:34:24 +01:00
|
|
|
{
|
2015-05-07 16:26:37 +02:00
|
|
|
auto filter = [&mimeType](const KPluginMetaData &md) -> bool
|
|
|
|
{
|
2017-01-03 09:31:21 +01:00
|
|
|
return KPluginMetaData::readStringList(md.rawData(), QStringLiteral("X-Plasma-DropMimeTypes")).contains(mimeType);
|
2015-05-07 16:26:37 +02:00
|
|
|
};
|
2017-05-31 02:15:16 +02:00
|
|
|
return KPackage::PackageLoader::self()->findPackages(QStringLiteral("Plasma/Applet"), QString(), filter);
|
2013-02-12 21:34:24 +01:00
|
|
|
}
|
|
|
|
|
2017-05-31 02:15:16 +02:00
|
|
|
KPluginInfo::List PluginLoader::listAppletInfoForMimeType(const QString &mimeType)
|
|
|
|
{
|
|
|
|
return KPluginInfo::fromMetaData(listAppletMetaDataForMimeType(mimeType).toVector());
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<KPluginMetaData> PluginLoader::listAppletMetaDataForUrl(const QUrl &url)
|
2013-02-12 21:34:24 +01:00
|
|
|
{
|
2015-05-07 16:26:37 +02:00
|
|
|
QString parentApp;
|
|
|
|
QCoreApplication *app = QCoreApplication::instance();
|
|
|
|
if (app) {
|
|
|
|
parentApp = app->applicationName();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto filter = [&parentApp](const KPluginMetaData &md) -> bool
|
|
|
|
{
|
2015-11-27 20:03:48 +00:00
|
|
|
const QString pa = md.value(QStringLiteral("X-KDE-ParentApp"));
|
pluginloader: Change behavior of X-KDE-ParentApp
Summary:
X-KDE-ParentApp is the key in desktop file to display that given service
or application is part of the another application or extension of other
application. In KDE4 this key was used to mark applets to be used in the
specific application like plasma-desktop, kdevelop, amarok etc.
In KF5 world, none of this applications have applet loading mechanism
apart from plasma*, and there are likely only Plasma applet, containment
or dataengines.
Previous API, when no/empty parentApp was passed would filter out every
application which had something as parentApp. This was to ensure only
compatible plugins are loaded in Plasma. This resulted in applets
getting excluded if they suggested that org.kde.plasmashell is their
parent application. Refine this API to,
- If no/empty parentApp is provided, provide all applets
- If parentApp is provided, filter by applet
This behavior is more filter like instead of other way around.
CHANGELOG: Applet, DataEngine and containment listing methods in
Plasma::PluginLoader no longer filters the plugins with X-KDE-ParentApp
provided when empty string is passed.
Test Plan:
tested that plasma loads properly, plasmaengineexplorer lists
all engines and plasmawindowed works fine. Neverthless requires more testing
Reviewers: mart, apol
Subscribers: kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D22049
2019-06-23 20:25:28 +05:30
|
|
|
return (parentApp.isEmpty() || pa == parentApp) && !KPluginMetaData::readStringList(md.rawData(), QStringLiteral("X-Plasma-DropUrlPatterns")).isEmpty();
|
2015-05-07 16:26:37 +02:00
|
|
|
};
|
2017-05-31 02:15:16 +02:00
|
|
|
const QList<KPluginMetaData> allApplets = KPackage::PackageLoader::self()->findPackages(QStringLiteral("Plasma/Applet"), QString(), filter);
|
2013-02-12 21:34:24 +01:00
|
|
|
|
2017-05-31 02:15:16 +02:00
|
|
|
QList<KPluginMetaData> filtered;
|
2019-03-20 07:12:03 +01:00
|
|
|
for (const KPluginMetaData &md : allApplets) {
|
|
|
|
const QStringList urlPatterns = KPluginMetaData::readStringList(md.rawData(), QStringLiteral("X-Plasma-DropUrlPatterns"));
|
|
|
|
for (const QString &glob : urlPatterns) {
|
2013-02-12 21:34:24 +01:00
|
|
|
QRegExp rx(glob);
|
|
|
|
rx.setPatternSyntax(QRegExp::Wildcard);
|
|
|
|
if (rx.exactMatch(url.toString())) {
|
|
|
|
#ifndef NDEBUG
|
2017-01-03 16:46:02 +01:00
|
|
|
// qCDebug(LOG_PLASMA) << md.name() << "matches" << glob << url;
|
2013-02-12 21:34:24 +01:00
|
|
|
#endif
|
2017-05-31 02:15:16 +02:00
|
|
|
filtered << md;
|
2013-02-12 21:34:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return filtered;
|
|
|
|
}
|
|
|
|
|
2017-05-31 02:15:16 +02:00
|
|
|
KPluginInfo::List PluginLoader::listAppletInfoForUrl(const QUrl &url)
|
|
|
|
{
|
|
|
|
return KPluginInfo::fromMetaData(listAppletMetaDataForUrl(url).toVector());
|
|
|
|
}
|
|
|
|
|
2013-02-12 21:40:59 +01:00
|
|
|
QStringList PluginLoader::listAppletCategories(const QString &parentApp, bool visibleOnly)
|
|
|
|
{
|
|
|
|
KConfigGroup group(KSharedConfig::openConfig(), "General");
|
|
|
|
const QStringList excluded = group.readEntry("ExcludeCategories", QStringList());
|
2015-05-07 16:26:37 +02:00
|
|
|
auto filter = [&parentApp, &excluded, visibleOnly](const KPluginMetaData &md) -> bool
|
|
|
|
{
|
2015-11-27 20:03:48 +00:00
|
|
|
const QString pa = md.value(QStringLiteral("X-KDE-ParentApp"));
|
pluginloader: Change behavior of X-KDE-ParentApp
Summary:
X-KDE-ParentApp is the key in desktop file to display that given service
or application is part of the another application or extension of other
application. In KDE4 this key was used to mark applets to be used in the
specific application like plasma-desktop, kdevelop, amarok etc.
In KF5 world, none of this applications have applet loading mechanism
apart from plasma*, and there are likely only Plasma applet, containment
or dataengines.
Previous API, when no/empty parentApp was passed would filter out every
application which had something as parentApp. This was to ensure only
compatible plugins are loaded in Plasma. This resulted in applets
getting excluded if they suggested that org.kde.plasmashell is their
parent application. Refine this API to,
- If no/empty parentApp is provided, provide all applets
- If parentApp is provided, filter by applet
This behavior is more filter like instead of other way around.
CHANGELOG: Applet, DataEngine and containment listing methods in
Plasma::PluginLoader no longer filters the plugins with X-KDE-ParentApp
provided when empty string is passed.
Test Plan:
tested that plasma loads properly, plasmaengineexplorer lists
all engines and plasmawindowed works fine. Neverthless requires more testing
Reviewers: mart, apol
Subscribers: kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D22049
2019-06-23 20:25:28 +05:30
|
|
|
return (parentApp.isEmpty() || pa == parentApp)
|
2015-11-27 20:03:48 +00:00
|
|
|
&& (excluded.isEmpty() || excluded.contains(md.value(QStringLiteral("X-KDE-PluginInfo-Category"))))
|
|
|
|
&& (!visibleOnly || !md.isHidden());
|
2015-05-07 16:26:37 +02:00
|
|
|
};
|
2015-11-27 20:03:48 +00:00
|
|
|
const QList<KPluginMetaData> allApplets = KPackage::PackageLoader::self()->findPackages(QStringLiteral("Plasma/Applet"), QString(), filter);
|
2013-02-12 21:40:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
QStringList categories;
|
2019-03-20 07:12:03 +01:00
|
|
|
for (auto &plugin : allApplets) {
|
2015-05-07 16:26:37 +02:00
|
|
|
if (plugin.category().isEmpty()) {
|
2013-02-12 21:40:59 +01:00
|
|
|
if (!categories.contains(i18nc("misc category", "Miscellaneous"))) {
|
|
|
|
categories << i18nc("misc category", "Miscellaneous");
|
|
|
|
}
|
2015-05-07 16:26:37 +02:00
|
|
|
} else {
|
|
|
|
categories << plugin.category();
|
2013-02-12 21:40:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
categories.sort();
|
|
|
|
return categories;
|
|
|
|
}
|
|
|
|
|
2013-02-12 21:45:18 +01:00
|
|
|
void PluginLoader::setCustomAppletCategories(const QStringList &categories)
|
|
|
|
{
|
2020-06-26 06:03:24 +02:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
|
|
|
PluginLoaderPrivate::s_customCategories = QSet<QString>(categories.begin(), categories.end());
|
|
|
|
#else
|
2013-02-12 22:05:14 +01:00
|
|
|
PluginLoaderPrivate::s_customCategories = QSet<QString>::fromList(categories);
|
2020-06-26 06:03:24 +02:00
|
|
|
#endif
|
2013-02-12 21:45:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QStringList PluginLoader::customAppletCategories() const
|
|
|
|
{
|
2019-12-19 13:55:07 +01:00
|
|
|
return PluginLoaderPrivate::s_customCategories.values();
|
2013-02-12 21:45:18 +01:00
|
|
|
}
|
|
|
|
|
2014-04-26 01:45:47 +02:00
|
|
|
QString PluginLoader::appletCategory(const QString &appletName)
|
2013-02-12 21:54:08 +01:00
|
|
|
{
|
|
|
|
if (appletName.isEmpty()) {
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
const KPackage::Package p = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Applet"), appletName);
|
2015-05-07 16:26:37 +02:00
|
|
|
if (!p.isValid()) {
|
2013-02-12 21:54:08 +01:00
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2015-05-07 16:26:37 +02:00
|
|
|
return p.metadata().category();
|
2013-02-12 21:54:08 +01:00
|
|
|
}
|
|
|
|
|
2013-02-19 13:09:33 +01:00
|
|
|
KPluginInfo::List PluginLoader::listContainments(const QString &category,
|
2014-04-26 01:45:47 +02:00
|
|
|
const QString &parentApp)
|
2013-02-19 13:09:33 +01:00
|
|
|
{
|
|
|
|
return listContainmentsOfType(QString(), category, parentApp);
|
|
|
|
}
|
|
|
|
|
|
|
|
KPluginInfo::List PluginLoader::listContainmentsOfType(const QString &type,
|
2014-04-26 01:45:47 +02:00
|
|
|
const QString &category,
|
|
|
|
const QString &parentApp)
|
2013-02-19 13:09:33 +01:00
|
|
|
{
|
2015-05-07 16:26:37 +02:00
|
|
|
KConfigGroup group(KSharedConfig::openConfig(), "General");
|
|
|
|
auto filter = [&type, &category, &parentApp](const KPluginMetaData &md) -> bool
|
|
|
|
{
|
2019-08-29 07:23:49 +02:00
|
|
|
if (!md.serviceTypes().contains(QLatin1String("Plasma/Containment"))) {
|
2015-05-07 16:26:37 +02:00
|
|
|
return false;
|
2013-02-19 13:09:33 +01:00
|
|
|
}
|
pluginloader: Change behavior of X-KDE-ParentApp
Summary:
X-KDE-ParentApp is the key in desktop file to display that given service
or application is part of the another application or extension of other
application. In KDE4 this key was used to mark applets to be used in the
specific application like plasma-desktop, kdevelop, amarok etc.
In KF5 world, none of this applications have applet loading mechanism
apart from plasma*, and there are likely only Plasma applet, containment
or dataengines.
Previous API, when no/empty parentApp was passed would filter out every
application which had something as parentApp. This was to ensure only
compatible plugins are loaded in Plasma. This resulted in applets
getting excluded if they suggested that org.kde.plasmashell is their
parent application. Refine this API to,
- If no/empty parentApp is provided, provide all applets
- If parentApp is provided, filter by applet
This behavior is more filter like instead of other way around.
CHANGELOG: Applet, DataEngine and containment listing methods in
Plasma::PluginLoader no longer filters the plugins with X-KDE-ParentApp
provided when empty string is passed.
Test Plan:
tested that plasma loads properly, plasmaengineexplorer lists
all engines and plasmawindowed works fine. Neverthless requires more testing
Reviewers: mart, apol
Subscribers: kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D22049
2019-06-23 20:25:28 +05:30
|
|
|
if (!parentApp.isEmpty() && md.value(QStringLiteral("X-KDE-ParentApp")) != parentApp) {
|
2015-05-07 16:26:37 +02:00
|
|
|
return false;
|
2013-03-07 19:55:45 +01:00
|
|
|
}
|
2013-02-19 13:09:33 +01:00
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
if (!type.isEmpty() && md.value(QStringLiteral("X-Plasma-ContainmentType")) != type) {
|
2015-05-07 16:26:37 +02:00
|
|
|
return false;
|
2013-02-19 13:09:33 +01:00
|
|
|
}
|
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
if (!category.isEmpty() && md.value(QStringLiteral("X-KDE-PluginInfo-Category")) != category) {
|
2015-05-07 16:26:37 +02:00
|
|
|
return false;
|
2013-02-19 13:09:33 +01:00
|
|
|
}
|
|
|
|
|
2015-05-07 16:26:37 +02:00
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
return KPluginInfo::fromMetaData(KPackage::PackageLoader::self()->findPackages(QStringLiteral("Plasma/Applet"), QString(), filter).toVector());
|
2013-02-19 13:09:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
KPluginInfo::List PluginLoader::listContainmentsForMimeType(const QString &mimeType)
|
|
|
|
{
|
2015-05-07 16:26:37 +02:00
|
|
|
auto filter = [&mimeType](const KPluginMetaData &md) -> bool
|
|
|
|
{
|
2017-01-03 09:31:21 +01:00
|
|
|
return md.serviceTypes().contains(QLatin1String("Plasma/Containment"))
|
|
|
|
&& KPluginMetaData::readStringList(md.rawData(), QStringLiteral("X-Plasma-DropMimeTypes")).contains(mimeType);
|
2015-05-07 16:26:37 +02:00
|
|
|
};
|
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
return KPluginInfo::fromMetaData(KPackage::PackageLoader::self()->findPackages(QStringLiteral("Plasma/Applet"), QString(), filter).toVector());
|
2013-02-19 13:09:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QStringList PluginLoader::listContainmentTypes()
|
|
|
|
{
|
2019-03-20 07:12:03 +01:00
|
|
|
const KPluginInfo::List containmentInfos = listContainments();
|
2013-02-19 13:09:33 +01:00
|
|
|
QSet<QString> types;
|
|
|
|
|
2019-03-20 07:12:03 +01:00
|
|
|
for (const KPluginInfo &containmentInfo : containmentInfos) {
|
2020-05-10 17:03:56 +02:00
|
|
|
const QStringList theseTypes = containmentInfo.property(QStringLiteral("X-Plasma-ContainmentType")).toStringList();
|
2019-03-20 07:12:03 +01:00
|
|
|
for (const QString &type : theseTypes) {
|
2013-02-19 13:09:33 +01:00
|
|
|
types.insert(type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-19 13:55:07 +01:00
|
|
|
return types.values();
|
2013-02-19 13:09:33 +01:00
|
|
|
}
|
|
|
|
|
2010-07-27 22:07:53 +00:00
|
|
|
KPluginInfo::List PluginLoader::listDataEngineInfo(const QString &parentApp)
|
|
|
|
{
|
|
|
|
KPluginInfo::List list;
|
|
|
|
|
2012-06-18 13:11:26 +05:30
|
|
|
if (!d->isDefaultLoader && (parentApp.isEmpty() || parentApp == QCoreApplication::instance()->applicationName())) {
|
2010-07-27 22:07:53 +00:00
|
|
|
list = internalDataEngineInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString constraint;
|
pluginloader: Change behavior of X-KDE-ParentApp
Summary:
X-KDE-ParentApp is the key in desktop file to display that given service
or application is part of the another application or extension of other
application. In KDE4 this key was used to mark applets to be used in the
specific application like plasma-desktop, kdevelop, amarok etc.
In KF5 world, none of this applications have applet loading mechanism
apart from plasma*, and there are likely only Plasma applet, containment
or dataengines.
Previous API, when no/empty parentApp was passed would filter out every
application which had something as parentApp. This was to ensure only
compatible plugins are loaded in Plasma. This resulted in applets
getting excluded if they suggested that org.kde.plasmashell is their
parent application. Refine this API to,
- If no/empty parentApp is provided, provide all applets
- If parentApp is provided, filter by applet
This behavior is more filter like instead of other way around.
CHANGELOG: Applet, DataEngine and containment listing methods in
Plasma::PluginLoader no longer filters the plugins with X-KDE-ParentApp
provided when empty string is passed.
Test Plan:
tested that plasma loads properly, plasmaengineexplorer lists
all engines and plasmawindowed works fine. Neverthless requires more testing
Reviewers: mart, apol
Subscribers: kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D22049
2019-06-23 20:25:28 +05:30
|
|
|
if (!parentApp.isEmpty()) {
|
2017-12-02 15:12:40 +01:00
|
|
|
constraint = QLatin1String("[X-KDE-ParentApp] == '") + parentApp + QLatin1Char('\'');
|
2010-07-27 22:07:53 +00:00
|
|
|
}
|
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
list.append(KPluginTrader::self()->query(PluginLoaderPrivate::s_dataEnginePluginDir, QStringLiteral("Plasma/DataEngine"), constraint));
|
2013-09-12 02:03:52 +02:00
|
|
|
return list;
|
2010-07-27 22:07:53 +00:00
|
|
|
}
|
|
|
|
|
2011-07-19 21:39:51 +02:00
|
|
|
KPluginInfo::List PluginLoader::listContainmentActionsInfo(const QString &parentApp)
|
|
|
|
{
|
|
|
|
KPluginInfo::List list;
|
|
|
|
|
2012-06-18 13:11:26 +05:30
|
|
|
if (!d->isDefaultLoader && (parentApp.isEmpty() || parentApp == QCoreApplication::instance()->applicationName())) {
|
2011-07-19 21:39:51 +02:00
|
|
|
list = internalContainmentActionsInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString constraint;
|
pluginloader: Change behavior of X-KDE-ParentApp
Summary:
X-KDE-ParentApp is the key in desktop file to display that given service
or application is part of the another application or extension of other
application. In KDE4 this key was used to mark applets to be used in the
specific application like plasma-desktop, kdevelop, amarok etc.
In KF5 world, none of this applications have applet loading mechanism
apart from plasma*, and there are likely only Plasma applet, containment
or dataengines.
Previous API, when no/empty parentApp was passed would filter out every
application which had something as parentApp. This was to ensure only
compatible plugins are loaded in Plasma. This resulted in applets
getting excluded if they suggested that org.kde.plasmashell is their
parent application. Refine this API to,
- If no/empty parentApp is provided, provide all applets
- If parentApp is provided, filter by applet
This behavior is more filter like instead of other way around.
CHANGELOG: Applet, DataEngine and containment listing methods in
Plasma::PluginLoader no longer filters the plugins with X-KDE-ParentApp
provided when empty string is passed.
Test Plan:
tested that plasma loads properly, plasmaengineexplorer lists
all engines and plasmawindowed works fine. Neverthless requires more testing
Reviewers: mart, apol
Subscribers: kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D22049
2019-06-23 20:25:28 +05:30
|
|
|
if (!parentApp.isEmpty()) {
|
2017-12-02 15:12:40 +01:00
|
|
|
constraint = QLatin1String("[X-KDE-ParentApp] == '") + parentApp + QLatin1Char('\'');
|
2011-07-19 21:39:51 +02:00
|
|
|
}
|
|
|
|
|
2015-11-27 20:03:48 +00:00
|
|
|
list.append(KPluginTrader::self()->query(PluginLoaderPrivate::s_containmentActionsPluginDir, QStringLiteral("Plasma/ContainmentActions"), constraint));
|
2015-05-07 16:26:37 +02:00
|
|
|
|
|
|
|
QSet<QString> knownPlugins;
|
2019-03-20 07:12:03 +01:00
|
|
|
for (const KPluginInfo &p : qAsConst(list)) {
|
2015-05-07 16:26:37 +02:00
|
|
|
knownPlugins.insert(p.pluginName());
|
|
|
|
}
|
|
|
|
|
2020-05-10 17:03:56 +02:00
|
|
|
#if KSERVICE_BUILD_DEPRECATED_SINCE(5, 0)
|
2015-05-07 16:26:37 +02:00
|
|
|
//FIXME: this is only for backwards compatibility, but probably will have to stay
|
|
|
|
//for the time being
|
2019-03-20 07:12:03 +01:00
|
|
|
const KService::List offers = KServiceTypeTrader::self()->query(QStringLiteral("Plasma/ContainmentActions"), constraint);
|
|
|
|
for (KService::Ptr s : offers) {
|
2015-05-07 16:26:37 +02:00
|
|
|
if (!knownPlugins.contains(s->pluginKeyword())) {
|
2020-05-10 17:03:56 +02:00
|
|
|
QT_WARNING_PUSH
|
|
|
|
QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
|
|
|
|
QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
|
2015-05-07 16:26:37 +02:00
|
|
|
list.append(KPluginInfo(s));
|
2020-05-10 17:03:56 +02:00
|
|
|
QT_WARNING_POP
|
2015-05-07 16:26:37 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-10 17:03:56 +02:00
|
|
|
#endif
|
2015-05-07 16:26:37 +02:00
|
|
|
return list;
|
2011-07-19 21:39:51 +02:00
|
|
|
}
|
|
|
|
|
2014-04-26 01:45:47 +02:00
|
|
|
Applet *PluginLoader::internalLoadApplet(const QString &name, uint appletId, const QVariantList &args)
|
2011-10-04 16:50:44 +02:00
|
|
|
{
|
2010-07-15 21:38:56 +00:00
|
|
|
Q_UNUSED(name)
|
|
|
|
Q_UNUSED(appletId)
|
|
|
|
Q_UNUSED(args)
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2010-07-15 21:38:56 +00:00
|
|
|
}
|
|
|
|
|
2011-07-21 14:38:44 +02:00
|
|
|
DataEngine *PluginLoader::internalLoadDataEngine(const QString &name)
|
2010-07-15 21:38:56 +00:00
|
|
|
{
|
|
|
|
Q_UNUSED(name)
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2010-07-15 21:06:21 +00:00
|
|
|
}
|
|
|
|
|
2011-07-21 14:38:44 +02:00
|
|
|
ContainmentActions *PluginLoader::internalLoadContainmentActions(Containment *containment, const QString &name, const QVariantList &args)
|
|
|
|
{
|
|
|
|
Q_UNUSED(containment)
|
|
|
|
Q_UNUSED(name)
|
|
|
|
Q_UNUSED(args)
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2011-07-21 14:38:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Service *PluginLoader::internalLoadService(const QString &name, const QVariantList &args, QObject *parent)
|
2011-07-13 20:20:36 +02:00
|
|
|
{
|
2010-07-15 21:38:56 +00:00
|
|
|
Q_UNUSED(name)
|
|
|
|
Q_UNUSED(args)
|
|
|
|
Q_UNUSED(parent)
|
2018-04-13 13:58:44 +02:00
|
|
|
return nullptr;
|
2010-07-15 21:06:21 +00:00
|
|
|
}
|
|
|
|
|
2016-12-26 17:06:09 +01:00
|
|
|
|
2011-07-15 13:34:10 +02:00
|
|
|
Package PluginLoader::internalLoadPackage(const QString &name, const QString &specialization)
|
2011-07-13 20:20:36 +02:00
|
|
|
{
|
|
|
|
Q_UNUSED(name);
|
2011-07-15 13:34:10 +02:00
|
|
|
Q_UNUSED(specialization);
|
2011-07-13 20:20:36 +02:00
|
|
|
return Package();
|
|
|
|
}
|
|
|
|
|
2010-07-27 22:07:53 +00:00
|
|
|
KPluginInfo::List PluginLoader::internalAppletInfo(const QString &category) const
|
Moving Plasma::Applet::listAppletInfo into the PluginLoader logic. Also implemented internalAppletNames which, if implemented, will return a QStringList of the available applets' names. PluginLoader::listAppletInfo will then search for .desktop files in $APPDATA/plasma/applets/ which match the applets' names (ie. $APPDATA/plasma/applets/org.skrooge.report.desktop), and add them to the KPluginInfo::List returned by PluginLoader::listAppletInfo and subsequently Plasma::Applet::listAppletInfo.
Since the applets are dynamically loaded, the .desktop files don't need an X-KDE-Library entries, but the others will be used, for example X-KDE-PluginInfo-Name (which will be the value given to PluginLoader::internalAppletLoad, so it is really important), Icon, Type, ServiceTypes...
svn path=/trunk/KDE/kdelibs/; revision=1154551
2010-07-25 20:56:03 +00:00
|
|
|
{
|
|
|
|
Q_UNUSED(category)
|
2010-07-27 22:07:53 +00:00
|
|
|
return KPluginInfo::List();
|
|
|
|
}
|
Moving Plasma::Applet::listAppletInfo into the PluginLoader logic. Also implemented internalAppletNames which, if implemented, will return a QStringList of the available applets' names. PluginLoader::listAppletInfo will then search for .desktop files in $APPDATA/plasma/applets/ which match the applets' names (ie. $APPDATA/plasma/applets/org.skrooge.report.desktop), and add them to the KPluginInfo::List returned by PluginLoader::listAppletInfo and subsequently Plasma::Applet::listAppletInfo.
Since the applets are dynamically loaded, the .desktop files don't need an X-KDE-Library entries, but the others will be used, for example X-KDE-PluginInfo-Name (which will be the value given to PluginLoader::internalAppletLoad, so it is really important), Icon, Type, ServiceTypes...
svn path=/trunk/KDE/kdelibs/; revision=1154551
2010-07-25 20:56:03 +00:00
|
|
|
|
2010-07-27 22:07:53 +00:00
|
|
|
KPluginInfo::List PluginLoader::internalDataEngineInfo() const
|
|
|
|
{
|
|
|
|
return KPluginInfo::List();
|
|
|
|
}
|
|
|
|
|
2010-07-28 18:17:58 +00:00
|
|
|
KPluginInfo::List PluginLoader::internalServiceInfo() const
|
|
|
|
{
|
|
|
|
return KPluginInfo::List();
|
|
|
|
}
|
|
|
|
|
2011-07-19 21:39:51 +02:00
|
|
|
KPluginInfo::List PluginLoader::internalContainmentActionsInfo() const
|
|
|
|
{
|
|
|
|
return KPluginInfo::List();
|
|
|
|
}
|
|
|
|
|
2010-10-13 21:21:30 +00:00
|
|
|
static KPluginInfo::List standardInternalInfo(const QString &type, const QString &category = QString())
|
2010-07-27 22:07:53 +00:00
|
|
|
{
|
2013-07-10 03:27:19 +02:00
|
|
|
QStringList files = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation,
|
2015-11-27 20:03:48 +00:00
|
|
|
QLatin1String(PLASMA_RELATIVE_DATA_INSTALL_DIR "/internal/") + type + QLatin1String("/*.desktop"),
|
2014-04-26 01:45:47 +02:00
|
|
|
QStandardPaths::LocateFile);
|
2010-07-27 22:07:53 +00:00
|
|
|
|
2019-03-20 07:12:03 +01:00
|
|
|
const KPluginInfo::List allInfo = KPluginInfo::fromFiles(files);
|
2010-07-27 22:07:53 +00:00
|
|
|
|
|
|
|
if (category.isEmpty() || allInfo.isEmpty()) {
|
|
|
|
return allInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
KPluginInfo::List matchingInfo;
|
2019-03-20 07:12:03 +01:00
|
|
|
for (const KPluginInfo &info : allInfo) {
|
2010-07-27 22:07:53 +00:00
|
|
|
if (info.category().compare(category, Qt::CaseInsensitive) == 0) {
|
|
|
|
matchingInfo << info;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return matchingInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
KPluginInfo::List PluginLoader::standardInternalAppletInfo(const QString &category) const
|
|
|
|
{
|
2015-11-27 20:03:48 +00:00
|
|
|
return standardInternalInfo(QStringLiteral("applets"), category);
|
2010-07-27 22:07:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
KPluginInfo::List PluginLoader::standardInternalDataEngineInfo() const
|
|
|
|
{
|
2015-11-27 20:03:48 +00:00
|
|
|
return standardInternalInfo(QStringLiteral("dataengines"));
|
2010-07-27 22:07:53 +00:00
|
|
|
}
|
|
|
|
|
2010-07-28 18:17:58 +00:00
|
|
|
KPluginInfo::List PluginLoader::standardInternalServiceInfo() const
|
|
|
|
{
|
2015-11-27 20:03:48 +00:00
|
|
|
return standardInternalInfo(QStringLiteral("services"));
|
2010-07-28 18:17:58 +00:00
|
|
|
}
|
|
|
|
|
2016-06-12 15:35:17 +02:00
|
|
|
bool PluginLoader::isPluginVersionCompatible(KPluginLoader &loader)
|
|
|
|
{
|
|
|
|
const quint32 version = loader.pluginVersion();
|
|
|
|
if (version == quint32(-1)) {
|
|
|
|
// unversioned, just let it through
|
|
|
|
qCWarning(LOG_PLASMA) << loader.fileName() << "unversioned plugin detected, may result in instability";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we require PLASMA_VERSION_MAJOR and PLASMA_VERSION_MINOR
|
|
|
|
const quint32 minVersion = PLASMA_MAKE_VERSION(PLASMA_VERSION_MAJOR, 0, 0);
|
|
|
|
const quint32 maxVersion = PLASMA_MAKE_VERSION(PLASMA_VERSION_MAJOR, PLASMA_VERSION_MINOR, 60);
|
|
|
|
|
|
|
|
if (version < minVersion || version > maxVersion) {
|
2019-02-27 18:51:07 +01:00
|
|
|
qCWarning(LOG_PLASMA) << loader.fileName() << ": this plugin is compiled against incompatible Plasma version" << version
|
2016-06-12 15:35:17 +02:00
|
|
|
<< "This build is compatible with" << PLASMA_VERSION_MAJOR << ".0.0 (" << minVersion
|
|
|
|
<< ") to" << PLASMA_VERSION_STRING << "(" << maxVersion << ")";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-07-08 13:47:27 +02:00
|
|
|
QVector<KPluginMetaData> PluginLoaderPrivate::Cache::findPluginsById(const QString& name, const QStringList &dirs)
|
|
|
|
{
|
|
|
|
const qint64 now = qRound64(QDateTime::currentMSecsSinceEpoch() / 1000.0);
|
|
|
|
bool useRuntimeCache = true;
|
2010-07-15 21:06:21 +00:00
|
|
|
|
2019-07-08 13:47:27 +02:00
|
|
|
if (pluginCacheAge == 0) {
|
|
|
|
// Find all the plugins now, but only once
|
|
|
|
pluginCacheAge = now;
|
|
|
|
|
|
|
|
auto insertIntoCache = [this](const QString &pluginPath) {
|
|
|
|
KPluginMetaData metadata(pluginPath);
|
|
|
|
if (!metadata.isValid()) {
|
2020-01-31 15:52:56 -07:00
|
|
|
qCDebug(LOG_PLASMA) << "invalid metadata" << pluginPath;
|
2019-07-08 13:47:27 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
plugins[metadata.pluginId()].append(metadata);
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const QString &dir : dirs)
|
|
|
|
KPluginLoader::forEachPlugin(dir, insertIntoCache);
|
|
|
|
} else if (now - pluginCacheAge > maxCacheAge) {
|
|
|
|
// cache is old and we're not within a few seconds of startup anymore
|
|
|
|
useRuntimeCache = false;
|
|
|
|
plugins.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
//if name wasn't a path, pluginName == name
|
|
|
|
const QString pluginName = name.section(QLatin1Char('/'), -1);
|
|
|
|
|
|
|
|
QVector<KPluginMetaData> ret;
|
|
|
|
|
|
|
|
if (useRuntimeCache) {
|
|
|
|
auto it = plugins.constFind(pluginName);
|
|
|
|
if (it != plugins.constEnd()) {
|
|
|
|
ret = *it;
|
|
|
|
}
|
|
|
|
qCDebug(LOG_PLASMA) << "loading applet by name" << name << useRuntimeCache << ret.size();
|
|
|
|
} else {
|
|
|
|
|
|
|
|
for (const auto& dir : dirs) {
|
|
|
|
ret = KPluginLoader::findPluginsById(dir, pluginName);
|
|
|
|
if (!ret.isEmpty())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // Plasma Namespace
|