QList<KPluginMetaData> PluginLoader::listAppletMetaData(const QString &category, const QString &parentApp)
{
    //FIXME: this assumes we are always use packages.. no pure c++
    std::function<bool(const KPluginMetaData&)> filter;
    if (category.isEmpty()) { //use all but the excluded categories
        KConfigGroup group(KSharedConfig::openConfig(), "General");
        QStringList excluded = group.readEntry("ExcludeCategories", QStringList());

        filter = [excluded, parentApp](const KPluginMetaData &md) -> bool
        {
            const QString pa = md.value(QStringLiteral("X-KDE-ParentApp"));
            return (pa.isEmpty() || pa == parentApp) && !excluded.contains(md.category());
        };
    } else { //specific category (this could be an excluded one - is that bad?)

        filter = [category, parentApp](const KPluginMetaData &md) -> bool
        {
            const QString pa = md.value(QStringLiteral("X-KDE-ParentApp"));
            if (category == QLatin1String("Miscellaneous")) {
                return (pa.isEmpty() || pa == parentApp) && (md.category() == category || md.category().isEmpty());
            } else {
                return (pa.isEmpty() || pa == parentApp) && md.category() == category;
            }
        };
    }

    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);
}
KPluginInfo::List PluginLoader::listAppletInfo(const QString &category, const QString &parentApp)
{
    KPluginInfo::List list;

    if (!d->isDefaultLoader && (parentApp.isEmpty() || parentApp == QCoreApplication::instance()->applicationName())) {
        list = internalAppletInfo(category);
    }

    //FIXME: this assumes we are always use packages.. no pure c++
    if (category.isEmpty()) { //use all but the excluded categories
        KConfigGroup group(KSharedConfig::openConfig(), "General");
        QStringList excluded = group.readEntry("ExcludeCategories", QStringList());

        auto filter = [&excluded, &parentApp](const KPluginMetaData &md) -> bool
        {
            const QString pa = md.value(QStringLiteral("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)) {
            auto pi = KPluginInfo(KService::serviceByStorageId(md.metaDataFileName()));
            if (!pi.isValid()) {
                qCWarning(LOG_PLASMA) << "Could not load plugin info for plugin :" << md.pluginId() << "skipping plugin";
                continue;
            }
            list << pi;
        }
        return list;


    } else { //specific category (this could be an excluded one - is that bad?)

        auto filter = [&category, &parentApp](const KPluginMetaData &md) -> bool
        {
            const QString pa = md.value(QStringLiteral("X-KDE-ParentApp"));
            if (category == QLatin1String("Miscellaneous")) {
                return (pa.isEmpty() || pa == parentApp) && (md.category() == category || md.category().isEmpty());
            } else {
                return (pa.isEmpty() || pa == parentApp) && md.category() == category;
            }
        };


        //NOTE: it still produces kplugininfos from KServices because some user code expects
        //info.sevice() to be valid and would crash ohtherwise
        for (auto md : KPackage::PackageLoader::self()->findPackages("Plasma/Applet", QString(), filter)) {
            auto pi =  KPluginInfo(KService::serviceByStorageId(md.metaDataFileName()));
            if (!pi.isValid()) {
                qCWarning(LOG_PLASMA) << "Could not load plugin info for plugin :" << md.pluginId() << "skipping plugin";
                continue;
            }
            list << pi;
        }
        return list;
    }
}