File indexing completed on 2024-12-08 12:23:51
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2003, 2007 Matthias Kretz <kretz@kde.org> 0004 SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #include "kplugininfo.h" 0010 0011 QT_WARNING_PUSH 0012 QT_WARNING_DISABLE_DEPRECATED 0013 0014 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 90) 0015 #include "servicesdebug.h" 0016 #include <QDirIterator> 0017 #include <QJsonArray> 0018 #include <QMimeDatabase> 0019 #include <QStandardPaths> 0020 0021 #include "ksycoca.h" 0022 #include "ksycoca_p.h" 0023 #include <KAboutData> 0024 #include <KDesktopFile> 0025 #include <KPluginMetaData> 0026 #include <kservicetypefactory_p.h> 0027 #include <kservicetypetrader.h> 0028 0029 // clang-format off 0030 //#ifndef NDEBUG 0031 #define KPLUGININFO_ISVALID_ASSERTION \ 0032 do { \ 0033 if (!d) { \ 0034 qFatal("Accessed invalid KPluginInfo object"); \ 0035 } \ 0036 } while (false) 0037 //#else 0038 //#define KPLUGININFO_ISVALID_ASSERTION 0039 //#endif 0040 0041 #define GlobalQStringLiteral(name, str) inline QString name() { return QStringLiteral(str); } 0042 0043 namespace { 0044 0045 GlobalQStringLiteral(s_hiddenKey, "Hidden") 0046 GlobalQStringLiteral(s_nameKey, "Name") 0047 GlobalQStringLiteral(s_commentKey, "Comment") 0048 GlobalQStringLiteral(s_iconKey, "Icon") 0049 GlobalQStringLiteral(s_libraryKey, "X-KDE-Library") 0050 GlobalQStringLiteral(s_authorKey, "X-KDE-PluginInfo-Author") 0051 GlobalQStringLiteral(s_emailKey, "X-KDE-PluginInfo-Email") 0052 GlobalQStringLiteral(s_pluginNameKey, "X-KDE-PluginInfo-Name") 0053 GlobalQStringLiteral(s_versionKey, "X-KDE-PluginInfo-Version") 0054 GlobalQStringLiteral(s_websiteKey, "X-KDE-PluginInfo-Website") 0055 GlobalQStringLiteral(s_categoryKey, "X-KDE-PluginInfo-Category") 0056 GlobalQStringLiteral(s_licenseKey, "X-KDE-PluginInfo-License") 0057 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79) 0058 GlobalQStringLiteral(s_dependenciesKey, "X-KDE-PluginInfo-Depends") 0059 #endif 0060 GlobalQStringLiteral(s_serviceTypesKey, "ServiceTypes") 0061 GlobalQStringLiteral(s_xKDEServiceTypes, "X-KDE-ServiceTypes") 0062 GlobalQStringLiteral(s_mimeTypeKey, "MimeType") 0063 GlobalQStringLiteral(s_formFactorsKey, "X-KDE-FormFactors") 0064 GlobalQStringLiteral(s_enabledbyDefaultKey, "X-KDE-PluginInfo-EnabledByDefault") 0065 GlobalQStringLiteral(s_enabledKey, "Enabled") 0066 0067 // these keys are used in the json metadata 0068 GlobalQStringLiteral(s_jsonDescriptionKey, "Description") 0069 GlobalQStringLiteral(s_jsonAuthorsKey, "Authors") 0070 GlobalQStringLiteral(s_jsonEmailKey, "Email") 0071 GlobalQStringLiteral(s_jsonCategoryKey, "Category") 0072 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79) 0073 GlobalQStringLiteral(s_jsonDependenciesKey, "Dependencies") 0074 #endif 0075 GlobalQStringLiteral(s_jsonEnabledByDefaultKey, "EnabledByDefault") 0076 GlobalQStringLiteral(s_jsonFormFactorsKey, "FormFactors") 0077 GlobalQStringLiteral(s_jsonLicenseKey, "License") 0078 GlobalQStringLiteral(s_jsonIdKey, "Id") 0079 GlobalQStringLiteral(s_jsonVersionKey, "Version") 0080 GlobalQStringLiteral(s_jsonWebsiteKey, "Website") 0081 GlobalQStringLiteral(s_jsonMimeTypesKey, "MimeTypes") 0082 GlobalQStringLiteral(s_jsonKPluginKey, "KPlugin") 0083 0084 } 0085 // clang-format on 0086 0087 class KPluginInfoPrivate : public QSharedData 0088 { 0089 public: 0090 KPluginInfoPrivate() 0091 : hidden(false) 0092 , pluginenabled(false) 0093 , kcmservicesCached(false) 0094 { 0095 } 0096 0097 static QStringList deserializeList(const QString &data); 0098 0099 bool hidden : 1; 0100 bool pluginenabled : 1; 0101 mutable bool kcmservicesCached : 1; 0102 0103 KPluginMetaData metaData; 0104 KConfigGroup config; 0105 KService::Ptr service; 0106 mutable QList<KService::Ptr> kcmservices; 0107 0108 /** assigns the @p md to @c metaData, but also ensures that compatibility values are handled */ 0109 void setMetaData(const KPluginMetaData &md, bool warnOnOldStyle); 0110 }; 0111 0112 // This comes from KConfigGroupPrivate::deserializeList() 0113 QStringList KPluginInfoPrivate::deserializeList(const QString &data) 0114 { 0115 if (data.isEmpty()) { 0116 return QStringList(); 0117 } 0118 if (data == QLatin1String("\\0")) { 0119 return QStringList(QString()); 0120 } 0121 QStringList value; 0122 QString val; 0123 val.reserve(data.size()); 0124 bool quoted = false; 0125 for (int p = 0; p < data.length(); p++) { 0126 if (quoted) { 0127 val += data[p]; 0128 quoted = false; 0129 } else if (data[p].unicode() == '\\') { 0130 quoted = true; 0131 } else if (data[p].unicode() == ',' || data[p].unicode() == ';') { 0132 val.squeeze(); // release any unused memory 0133 value.append(val); 0134 val.clear(); 0135 val.reserve(data.size() - p); 0136 } else { 0137 val += data[p]; 0138 } 0139 } 0140 value.append(val); 0141 return value; 0142 } 0143 0144 // maps the KService, QVariant and KDesktopFile keys to the new KPluginMetaData keys 0145 template<typename T, typename Func> 0146 static QJsonObject mapToJsonKPluginKey(const QString &name, 0147 const QString &description, 0148 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79) 0149 const QStringList &dependencies, 0150 #endif 0151 const QStringList &serviceTypes, 0152 const QStringList &formFactors, 0153 const T &data, 0154 Func accessor) 0155 { 0156 /* Metadata structure is as follows: 0157 "KPlugin": { 0158 "Name": "Date and Time", 0159 "Description": "Date and time by timezone", 0160 "Icon": "preferences-system-time", 0161 "Authors": { "Name": "Aaron Seigo", "Email": "aseigo@kde.org" }, 0162 "Category": "Date and Time", 0163 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79) 0164 "Dependencies": [], 0165 #endif 0166 "EnabledByDefault": "true", 0167 "License": "LGPL", 0168 "Id": "time", 0169 "Version": "1.0", 0170 "Website": "http://plasma.kde.org/", 0171 "ServiceTypes": ["Plasma/DataEngine"] 0172 "FormFactors": ["tablet", "handset"] 0173 } 0174 */ 0175 QJsonObject kplugin; 0176 kplugin[s_nameKey()] = name; 0177 kplugin[s_jsonDescriptionKey()] = description; 0178 kplugin[s_iconKey()] = accessor(data, s_iconKey()); 0179 QJsonObject authors; 0180 authors[s_nameKey()] = accessor(data, s_authorKey()); 0181 authors[s_jsonEmailKey()] = accessor(data, s_emailKey()); 0182 kplugin[s_jsonAuthorsKey()] = authors; 0183 kplugin[s_jsonCategoryKey()] = accessor(data, s_categoryKey()); 0184 QJsonValue enabledByDefault = accessor(data, s_enabledbyDefaultKey()); 0185 // make sure that enabledByDefault is bool and not string 0186 if (!enabledByDefault.isBool()) { 0187 enabledByDefault = enabledByDefault.toString().compare(QLatin1String("true"), Qt::CaseInsensitive) == 0; 0188 } 0189 kplugin[s_jsonEnabledByDefaultKey()] = enabledByDefault; 0190 kplugin[s_jsonLicenseKey()] = accessor(data, s_licenseKey()); 0191 kplugin[s_jsonIdKey()] = accessor(data, s_pluginNameKey()); 0192 kplugin[s_jsonVersionKey()] = accessor(data, s_versionKey()); 0193 kplugin[s_jsonWebsiteKey()] = accessor(data, s_websiteKey()); 0194 kplugin[s_jsonFormFactorsKey()] = QJsonArray::fromStringList(formFactors); 0195 kplugin[s_serviceTypesKey()] = QJsonArray::fromStringList(serviceTypes); 0196 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79) 0197 kplugin[s_jsonDependenciesKey()] = QJsonArray::fromStringList(dependencies); 0198 #endif 0199 QJsonValue mimeTypes = accessor(data, s_mimeTypeKey()); 0200 if (mimeTypes.isString()) { 0201 QStringList mimeList = KPluginInfoPrivate::deserializeList(mimeTypes.toString()); 0202 if (!mimeList.isEmpty()) { 0203 mimeTypes = QJsonArray::fromStringList(mimeList); 0204 } else { 0205 mimeTypes = QJsonValue(); 0206 } 0207 } 0208 kplugin[s_jsonMimeTypesKey()] = mimeTypes; 0209 return kplugin; 0210 } 0211 0212 // TODO: KF6 remove 0213 static KPluginMetaData fromCompatibilityJson(const QJsonObject &json, const QString &lib, const QString &metaDataFile, bool warnOnOldStyle) 0214 { 0215 // This is not added to KPluginMetaData(QJsonObject, QString) to ensure that all the compatility code 0216 // remains in kservice and does not increase the size of kcoreaddons 0217 QStringList serviceTypes = KPluginMetaData::readStringList(json, s_xKDEServiceTypes()); 0218 if (serviceTypes.isEmpty()) { 0219 serviceTypes = KPluginMetaData::readStringList(json, s_serviceTypesKey()); 0220 } 0221 QJsonObject obj = json; 0222 QString name = KPluginMetaData::readTranslatedString(json, s_nameKey()); 0223 if (warnOnOldStyle) { 0224 qWarning( 0225 "Constructing a KPluginInfo object from old style JSON. Please use" 0226 " kcoreaddons_desktop_to_json() for \"%s\" instead of kservice_desktop_to_json()" 0227 " in your CMake code.", 0228 qPrintable(lib)); 0229 } 0230 QString description = KPluginMetaData::readTranslatedString(json, s_commentKey()); 0231 QStringList formfactors = KPluginMetaData::readStringList(json, s_jsonFormFactorsKey()); 0232 QJsonObject kplugin = mapToJsonKPluginKey(name, 0233 description, 0234 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79) 0235 KPluginMetaData::readStringList(json, s_dependenciesKey()), 0236 #endif 0237 serviceTypes, 0238 formfactors, 0239 json, 0240 [](const QJsonObject &o, const QString &key) { 0241 return o.value(key); 0242 }); 0243 obj.insert(s_jsonKPluginKey(), kplugin); 0244 return KPluginMetaData(obj, lib, metaDataFile); 0245 } 0246 0247 void KPluginInfoPrivate::setMetaData(const KPluginMetaData &md, bool warnOnOldStyle) 0248 { 0249 const QJsonObject json = md.rawData(); 0250 if (!json.contains(s_jsonKPluginKey())) { 0251 // "KPlugin" key does not exists -> convert from compatibility mode 0252 metaData = fromCompatibilityJson(json, md.fileName(), md.metaDataFileName(), warnOnOldStyle); 0253 } else { 0254 metaData = md; 0255 } 0256 } 0257 0258 KPluginInfo::KPluginInfo(const KPluginMetaData &md) 0259 : d(new KPluginInfoPrivate) 0260 { 0261 d->setMetaData(md, true); 0262 if (!d->metaData.isValid()) { 0263 d.reset(); 0264 } 0265 } 0266 0267 KPluginInfo::KPluginInfo(const QString &filename /*, QStandardPaths::StandardLocation resource*/) 0268 : d(new KPluginInfoPrivate) 0269 { 0270 KDesktopFile file(/*resource,*/ filename); 0271 0272 KConfigGroup cg = file.desktopGroup(); 0273 if (!cg.exists()) { 0274 qCWarning(SERVICES) << filename << "has no desktop group, cannot construct a KPluginInfo object from it."; 0275 d.reset(); 0276 return; 0277 } 0278 d->hidden = cg.readEntry(s_hiddenKey(), false); 0279 if (d->hidden) { 0280 return; 0281 } 0282 0283 if (file.fileName().endsWith(QLatin1String(".desktop"))) { 0284 d->setMetaData(KPluginMetaData::fromDesktopFile(file.fileName()), true); 0285 } else { 0286 d->setMetaData(KPluginMetaData(file.fileName()), true); 0287 } 0288 if (!d->metaData.isValid()) { 0289 qCWarning(SERVICES) << "Failed to read metadata from .desktop file" << file.fileName(); 0290 d.reset(); 0291 } 0292 } 0293 0294 KPluginInfo::KPluginInfo(const QVariantList &args, const QString &libraryPath) 0295 : d(new KPluginInfoPrivate) 0296 { 0297 const QString metaData = QStringLiteral("MetaData"); 0298 for (const QVariant &v : args) { 0299 if (v.canConvert<QVariantMap>()) { 0300 const QVariantMap &m = v.toMap(); 0301 const QVariant &_metadata = m.value(metaData); 0302 if (_metadata.canConvert<QVariantMap>()) { 0303 const QVariantMap &map = _metadata.toMap(); 0304 if (map.value(s_hiddenKey()).toBool()) { 0305 d->hidden = true; 0306 break; 0307 } 0308 d->setMetaData(KPluginMetaData(QJsonObject::fromVariantMap(map), libraryPath), true); 0309 break; 0310 } 0311 } 0312 } 0313 if (!d->metaData.isValid()) { 0314 d.reset(); 0315 } 0316 } 0317 0318 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 88) 0319 KPluginInfo::KPluginInfo(const KService::Ptr service) 0320 : d(new KPluginInfoPrivate) 0321 { 0322 if (!service) { 0323 d = nullptr; // isValid() == false 0324 return; 0325 } 0326 d->service = service; 0327 if (service->isDeleted()) { 0328 d->hidden = true; 0329 return; 0330 } 0331 0332 KSycoca::self()->ensureCacheValid(); 0333 0334 QJsonObject json; 0335 const auto propertyList = service->propertyNames(); 0336 for (const QString &key : propertyList) { 0337 QMetaType::Type t = KSycocaPrivate::self()->serviceTypeFactory()->findPropertyTypeByName(key); 0338 if (t == QMetaType::UnknownType) { 0339 t = QMetaType::QString; // default to string if the type is not known 0340 } 0341 QVariant v = service->property(key, t); 0342 if (v.isValid()) { 0343 json[key] = QJsonValue::fromVariant(v); 0344 } 0345 } 0346 // reintroduce the separation between MimeType= and X-KDE-ServiceTypes= 0347 // we could do this by modifying KService and KSyCoCa, but as this is only compatibility 0348 // code we just query QMimeDatabase whether a ServiceType is a valid MIME type. 0349 const QStringList services = service->serviceTypes(); 0350 if (!services.isEmpty()) { 0351 QMimeDatabase db; 0352 QStringList mimeTypes; 0353 mimeTypes.reserve(services.size()); 0354 QStringList newServiceTypes; 0355 newServiceTypes.reserve(services.size()); 0356 for (const QString &s : services) { 0357 // If we have a valid mime type of a wildcard, we know it is a mime type and not a service type 0358 // this is for example required in the thumbnailers. 0359 // Also the conversion code in kcoreaddons does not check the validity. 0360 if (db.mimeTypeForName(s).isValid() || s.contains(QLatin1Char('*'))) { 0361 mimeTypes << s; 0362 } else { 0363 newServiceTypes << s; 0364 } 0365 } 0366 json[s_mimeTypeKey()] = QJsonArray::fromStringList(mimeTypes); 0367 json[s_xKDEServiceTypes()] = QJsonArray::fromStringList(newServiceTypes); 0368 json[s_serviceTypesKey()] = QJsonValue(); 0369 } 0370 0371 d->setMetaData(KPluginMetaData(json, service->library(), service->entryPath()), false); 0372 if (!d->metaData.isValid()) { 0373 d.reset(); 0374 } 0375 } 0376 #endif 0377 0378 KPluginInfo::KPluginInfo() 0379 : d(nullptr) // isValid() == false 0380 { 0381 } 0382 0383 bool KPluginInfo::isValid() const 0384 { 0385 return d.data() != nullptr; 0386 } 0387 0388 KPluginInfo::KPluginInfo(const KPluginInfo &rhs) 0389 : d(rhs.d) 0390 { 0391 } 0392 0393 KPluginInfo &KPluginInfo::operator=(const KPluginInfo &rhs) 0394 { 0395 d = rhs.d; 0396 return *this; 0397 } 0398 0399 bool KPluginInfo::operator==(const KPluginInfo &rhs) const 0400 { 0401 return d == rhs.d; 0402 } 0403 0404 bool KPluginInfo::operator!=(const KPluginInfo &rhs) const 0405 { 0406 return d != rhs.d; 0407 } 0408 0409 bool KPluginInfo::operator<(const KPluginInfo &rhs) const 0410 { 0411 if (category() < rhs.category()) { 0412 return true; 0413 } 0414 if (category() == rhs.category()) { 0415 return name() < rhs.name(); 0416 } 0417 return false; 0418 } 0419 0420 bool KPluginInfo::operator>(const KPluginInfo &rhs) const 0421 { 0422 if (category() > rhs.category()) { 0423 return true; 0424 } 0425 if (category() == rhs.category()) { 0426 return name() > rhs.name(); 0427 } 0428 return false; 0429 } 0430 0431 KPluginInfo::~KPluginInfo() 0432 { 0433 } 0434 0435 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 88) 0436 QList<KPluginInfo> KPluginInfo::fromServices(const KService::List &services, const KConfigGroup &config) 0437 { 0438 QList<KPluginInfo> infolist; 0439 for (KService::List::ConstIterator it = services.begin(); it != services.end(); ++it) { 0440 KPluginInfo info(*it); 0441 if (info.isValid()) { 0442 info.setConfig(config); 0443 infolist += info; 0444 } 0445 } 0446 return infolist; 0447 } 0448 #endif 0449 0450 QList<KPluginInfo> KPluginInfo::fromFiles(const QStringList &files, const KConfigGroup &config) 0451 { 0452 QList<KPluginInfo> infolist; 0453 infolist.reserve(files.size()); 0454 0455 std::transform(files.cbegin(), files.cend(), std::back_inserter(infolist), [&config](const QString &file) { 0456 KPluginInfo info(file); 0457 info.setConfig(config); 0458 return info; 0459 }); 0460 0461 return infolist; 0462 } 0463 0464 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 81) 0465 QList<KPluginInfo> KPluginInfo::fromKPartsInstanceName(const QString &name, const KConfigGroup &config) 0466 { 0467 QStringList files; 0468 const QStringList dirs = 0469 QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, name + QLatin1String("/kpartplugins"), QStandardPaths::LocateDirectory); 0470 for (const QString &dir : dirs) { 0471 QDirIterator it(dir, QStringList() << QStringLiteral("*.desktop")); 0472 while (it.hasNext()) { 0473 files.append(it.next()); 0474 } 0475 } 0476 return fromFiles(files, config); 0477 } 0478 #endif 0479 0480 bool KPluginInfo::isHidden() const 0481 { 0482 KPLUGININFO_ISVALID_ASSERTION; 0483 return d->hidden; 0484 } 0485 0486 void KPluginInfo::setPluginEnabled(bool enabled) 0487 { 0488 KPLUGININFO_ISVALID_ASSERTION; 0489 // qDebug() << Q_FUNC_INFO; 0490 d->pluginenabled = enabled; 0491 } 0492 0493 bool KPluginInfo::isPluginEnabled() const 0494 { 0495 KPLUGININFO_ISVALID_ASSERTION; 0496 // qDebug() << Q_FUNC_INFO; 0497 return d->pluginenabled; 0498 } 0499 0500 bool KPluginInfo::isPluginEnabledByDefault() const 0501 { 0502 KPLUGININFO_ISVALID_ASSERTION; 0503 // qDebug() << Q_FUNC_INFO; 0504 return d->metaData.isEnabledByDefault(); 0505 } 0506 0507 QString KPluginInfo::name() const 0508 { 0509 KPLUGININFO_ISVALID_ASSERTION; 0510 return d->metaData.name(); 0511 } 0512 0513 QString KPluginInfo::comment() const 0514 { 0515 KPLUGININFO_ISVALID_ASSERTION; 0516 return d->metaData.description(); 0517 } 0518 0519 QString KPluginInfo::icon() const 0520 { 0521 KPLUGININFO_ISVALID_ASSERTION; 0522 return d->metaData.iconName(); 0523 } 0524 0525 QString KPluginInfo::entryPath() const 0526 { 0527 KPLUGININFO_ISVALID_ASSERTION; 0528 return d->metaData.metaDataFileName(); 0529 } 0530 0531 QString KPluginInfo::author() const 0532 { 0533 KPLUGININFO_ISVALID_ASSERTION; 0534 const QList<KAboutPerson> &authors = d->metaData.authors(); 0535 return authors.isEmpty() ? QString() : authors[0].name(); 0536 } 0537 0538 QString KPluginInfo::email() const 0539 { 0540 KPLUGININFO_ISVALID_ASSERTION; 0541 const QList<KAboutPerson> &authors = d->metaData.authors(); 0542 return authors.isEmpty() ? QString() : authors[0].emailAddress(); 0543 } 0544 0545 QString KPluginInfo::category() const 0546 { 0547 KPLUGININFO_ISVALID_ASSERTION; 0548 return d->metaData.category(); 0549 } 0550 0551 QStringList KPluginInfo::formFactors() const 0552 { 0553 KPLUGININFO_ISVALID_ASSERTION; 0554 return d->metaData.formFactors(); 0555 } 0556 0557 QString KPluginInfo::pluginName() const 0558 { 0559 KPLUGININFO_ISVALID_ASSERTION; 0560 return d->metaData.pluginId(); 0561 } 0562 0563 QString KPluginInfo::libraryPath() const 0564 { 0565 KPLUGININFO_ISVALID_ASSERTION; 0566 return d->metaData.fileName(); 0567 } 0568 0569 QString KPluginInfo::version() const 0570 { 0571 KPLUGININFO_ISVALID_ASSERTION; 0572 return d->metaData.version(); 0573 } 0574 0575 QString KPluginInfo::website() const 0576 { 0577 KPLUGININFO_ISVALID_ASSERTION; 0578 return d->metaData.website(); 0579 } 0580 0581 QString KPluginInfo::license() const 0582 { 0583 KPLUGININFO_ISVALID_ASSERTION; 0584 return d->metaData.license(); 0585 } 0586 0587 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79) 0588 QStringList KPluginInfo::dependencies() const 0589 { 0590 KPLUGININFO_ISVALID_ASSERTION; 0591 return d->metaData.dependencies(); 0592 } 0593 #endif 0594 0595 QStringList KPluginInfo::serviceTypes() const 0596 { 0597 KPLUGININFO_ISVALID_ASSERTION; 0598 // KService/KPluginInfo include the MIME types in serviceTypes() 0599 return d->metaData.serviceTypes() + d->metaData.mimeTypes(); 0600 } 0601 0602 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 70) 0603 KService::Ptr KPluginInfo::service() const 0604 { 0605 KPLUGININFO_ISVALID_ASSERTION; 0606 return d->service; 0607 } 0608 #endif 0609 0610 QList<KService::Ptr> KPluginInfo::kcmServices() const 0611 { 0612 KPLUGININFO_ISVALID_ASSERTION; 0613 if (!d->kcmservicesCached) { 0614 d->kcmservices = 0615 KServiceTypeTrader::self()->query(QStringLiteral("KCModule"), QLatin1Char('\'') + pluginName() + QLatin1String("' in [X-KDE-ParentComponents]")); 0616 // qDebug() << "found" << d->kcmservices.count() << "offers for" << d->pluginName; 0617 0618 d->kcmservicesCached = true; 0619 } 0620 0621 return d->kcmservices; 0622 } 0623 0624 void KPluginInfo::setConfig(const KConfigGroup &config) 0625 { 0626 KPLUGININFO_ISVALID_ASSERTION; 0627 d->config = config; 0628 } 0629 0630 KConfigGroup KPluginInfo::config() const 0631 { 0632 KPLUGININFO_ISVALID_ASSERTION; 0633 return d->config; 0634 } 0635 0636 QVariant KPluginInfo::property(const QString &key) const 0637 { 0638 KPLUGININFO_ISVALID_ASSERTION; 0639 if (d->service) { 0640 return d->service->property(key); 0641 } 0642 QVariant result = d->metaData.rawData().value(key).toVariant(); 0643 if (result.isValid()) { 0644 KSycoca::self()->ensureCacheValid(); 0645 const QMetaType::Type t = KSycocaPrivate::self()->serviceTypeFactory()->findPropertyTypeByName(key); 0646 0647 // special case if we want a stringlist: split values by ',' or ';' and construct the list 0648 if (t == QMetaType::QStringList) { 0649 if (result.canConvert<QString>()) { 0650 result = KPluginInfoPrivate::deserializeList(result.toString()); 0651 } else if (result.canConvert<QVariantList>()) { 0652 const QVariantList list = result.toList(); 0653 QStringList newResult; 0654 for (const QVariant &value : list) { 0655 newResult += value.toString(); 0656 } 0657 result = newResult; 0658 } else { 0659 qCWarning(SERVICES) << "Cannot interpret" << result << "into a string list"; 0660 } 0661 } 0662 return result; 0663 } 0664 0665 // If the key was not found check compatibility for old key names and print a warning 0666 // These warnings should only happen if JSON was generated with kcoreaddons_desktop_to_json 0667 // but the application uses KPluginTrader::query() instead of KPluginLoader::findPlugins() 0668 // TODO: KF6 remove 0669 #define RETURN_WITH_DEPRECATED_WARNING(ret) \ 0670 qWarning("Calling KPluginInfo::property(\"%s\") is deprecated, use KPluginInfo::" #ret " in \"%s\" instead.", \ 0671 qPrintable(key), \ 0672 qPrintable(d->metaData.fileName())); \ 0673 return ret; 0674 if (key == s_authorKey()) { 0675 RETURN_WITH_DEPRECATED_WARNING(author()); 0676 } else if (key == s_categoryKey()) { 0677 RETURN_WITH_DEPRECATED_WARNING(category()); 0678 } else if (key == s_commentKey()) { 0679 RETURN_WITH_DEPRECATED_WARNING(comment()); 0680 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79) 0681 } else if (key == s_dependenciesKey()) { 0682 RETURN_WITH_DEPRECATED_WARNING(dependencies()); 0683 #endif 0684 } else if (key == s_emailKey()) { 0685 RETURN_WITH_DEPRECATED_WARNING(email()); 0686 } else if (key == s_enabledbyDefaultKey()) { 0687 RETURN_WITH_DEPRECATED_WARNING(isPluginEnabledByDefault()); 0688 } else if (key == s_libraryKey()) { 0689 RETURN_WITH_DEPRECATED_WARNING(libraryPath()); 0690 } else if (key == s_licenseKey()) { 0691 RETURN_WITH_DEPRECATED_WARNING(license()); 0692 } else if (key == s_nameKey()) { 0693 RETURN_WITH_DEPRECATED_WARNING(name()); 0694 } else if (key == s_pluginNameKey()) { 0695 RETURN_WITH_DEPRECATED_WARNING(pluginName()); 0696 } else if (key == s_serviceTypesKey()) { 0697 RETURN_WITH_DEPRECATED_WARNING(serviceTypes()); 0698 } else if (key == s_versionKey()) { 0699 RETURN_WITH_DEPRECATED_WARNING(version()); 0700 } else if (key == s_websiteKey()) { 0701 RETURN_WITH_DEPRECATED_WARNING(website()); 0702 } else if (key == s_xKDEServiceTypes()) { 0703 RETURN_WITH_DEPRECATED_WARNING(serviceTypes()); 0704 } else if (key == s_formFactorsKey()) { 0705 RETURN_WITH_DEPRECATED_WARNING(formFactors()); 0706 } 0707 #undef RETURN_WITH_DEPRECATED_WARNING 0708 // not a compatibility key -> return invalid QVariant 0709 return result; 0710 } 0711 0712 QVariantMap KPluginInfo::properties() const 0713 { 0714 return d->metaData.rawData().toVariantMap(); 0715 } 0716 0717 void KPluginInfo::save(KConfigGroup config) 0718 { 0719 KPLUGININFO_ISVALID_ASSERTION; 0720 // qDebug() << Q_FUNC_INFO; 0721 if (config.isValid()) { 0722 config.writeEntry(pluginName() + s_enabledKey(), isPluginEnabled()); 0723 } else { 0724 if (!d->config.isValid()) { 0725 qCWarning(SERVICES) << "no KConfigGroup, cannot save"; 0726 return; 0727 } 0728 d->config.writeEntry(pluginName() + s_enabledKey(), isPluginEnabled()); 0729 } 0730 } 0731 0732 void KPluginInfo::load(const KConfigGroup &config) 0733 { 0734 KPLUGININFO_ISVALID_ASSERTION; 0735 // qDebug() << Q_FUNC_INFO; 0736 if (config.isValid()) { 0737 setPluginEnabled(config.readEntry(pluginName() + s_enabledKey(), isPluginEnabledByDefault())); 0738 } else { 0739 if (!d->config.isValid()) { 0740 qCWarning(SERVICES) << "no KConfigGroup, cannot load"; 0741 return; 0742 } 0743 setPluginEnabled(d->config.readEntry(pluginName() + s_enabledKey(), isPluginEnabledByDefault())); 0744 } 0745 } 0746 0747 void KPluginInfo::defaults() 0748 { 0749 // qDebug() << Q_FUNC_INFO; 0750 setPluginEnabled(isPluginEnabledByDefault()); 0751 } 0752 0753 uint qHash(const KPluginInfo &p) 0754 { 0755 return qHash(reinterpret_cast<quint64>(p.d.data())); 0756 } 0757 0758 KPluginInfo KPluginInfo::fromMetaData(const KPluginMetaData &md) 0759 { 0760 return KPluginInfo(md); 0761 } 0762 0763 KPluginMetaData KPluginInfo::toMetaData() const 0764 { 0765 KPLUGININFO_ISVALID_ASSERTION; 0766 return d->metaData; 0767 } 0768 0769 KPluginMetaData KPluginInfo::toMetaData(const KPluginInfo &info) 0770 { 0771 return info.toMetaData(); 0772 } 0773 0774 KPluginInfo::List KPluginInfo::fromMetaData(const QVector<KPluginMetaData> &list) 0775 { 0776 KPluginInfo::List ret; 0777 ret.reserve(list.size()); 0778 for (const KPluginMetaData &md : list) { 0779 ret.append(KPluginInfo::fromMetaData(md)); 0780 } 0781 return ret; 0782 } 0783 0784 QVector<KPluginMetaData> KPluginInfo::toMetaData(const KPluginInfo::List &list) 0785 { 0786 QVector<KPluginMetaData> ret; 0787 ret.reserve(list.size()); 0788 for (const KPluginInfo &info : list) { 0789 ret.append(info.toMetaData()); 0790 } 0791 return ret; 0792 } 0793 0794 #undef KPLUGININFO_ISVALID_ASSERTION 0795 #endif