KService

kplugininfo.cpp
1 /*
2  This file is part of the KDE project
3  SPDX-FileCopyrightText: 2003, 2007 Matthias Kretz <[email protected]>
4  SPDX-FileCopyrightText: 2013 Sebastian Kügler <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-only
7 */
8 
9 #include "kplugininfo.h"
10 
11 QT_WARNING_PUSH
12 QT_WARNING_DISABLE_DEPRECATED
13 
14 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 90)
15 #include "servicesdebug.h"
16 #include <QDirIterator>
17 #include <QJsonArray>
18 #include <QMimeDatabase>
19 #include <QStandardPaths>
20 
21 #include "ksycoca.h"
22 #include "ksycoca_p.h"
23 #include <KAboutData>
24 #include <KDesktopFile>
25 #include <KPluginMetaData>
26 #include <kservicetypefactory_p.h>
27 #include <kservicetypetrader.h>
28 
29 // clang-format off
30 //#ifndef NDEBUG
31 #define KPLUGININFO_ISVALID_ASSERTION \
32  do { \
33  if (!d) { \
34  qFatal("Accessed invalid KPluginInfo object"); \
35  } \
36  } while (false)
37 //#else
38 //#define KPLUGININFO_ISVALID_ASSERTION
39 //#endif
40 
41 #define GlobalQStringLiteral(name, str) inline QString name() { return QStringLiteral(str); }
42 
43 namespace {
44 
45 GlobalQStringLiteral(s_hiddenKey, "Hidden")
46 GlobalQStringLiteral(s_nameKey, "Name")
47 GlobalQStringLiteral(s_commentKey, "Comment")
48 GlobalQStringLiteral(s_iconKey, "Icon")
49 GlobalQStringLiteral(s_libraryKey, "X-KDE-Library")
50 GlobalQStringLiteral(s_authorKey, "X-KDE-PluginInfo-Author")
51 GlobalQStringLiteral(s_emailKey, "X-KDE-PluginInfo-Email")
52 GlobalQStringLiteral(s_pluginNameKey, "X-KDE-PluginInfo-Name")
53 GlobalQStringLiteral(s_versionKey, "X-KDE-PluginInfo-Version")
54 GlobalQStringLiteral(s_websiteKey, "X-KDE-PluginInfo-Website")
55 GlobalQStringLiteral(s_categoryKey, "X-KDE-PluginInfo-Category")
56 GlobalQStringLiteral(s_licenseKey, "X-KDE-PluginInfo-License")
57 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79)
58 GlobalQStringLiteral(s_dependenciesKey, "X-KDE-PluginInfo-Depends")
59 #endif
60 GlobalQStringLiteral(s_serviceTypesKey, "ServiceTypes")
61 GlobalQStringLiteral(s_xKDEServiceTypes, "X-KDE-ServiceTypes")
62 GlobalQStringLiteral(s_mimeTypeKey, "MimeType")
63 GlobalQStringLiteral(s_formFactorsKey, "X-KDE-FormFactors")
64 GlobalQStringLiteral(s_enabledbyDefaultKey, "X-KDE-PluginInfo-EnabledByDefault")
65 GlobalQStringLiteral(s_enabledKey, "Enabled")
66 
67 // these keys are used in the json metadata
68 GlobalQStringLiteral(s_jsonDescriptionKey, "Description")
69 GlobalQStringLiteral(s_jsonAuthorsKey, "Authors")
70 GlobalQStringLiteral(s_jsonEmailKey, "Email")
71 GlobalQStringLiteral(s_jsonCategoryKey, "Category")
72 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79)
73 GlobalQStringLiteral(s_jsonDependenciesKey, "Dependencies")
74 #endif
75 GlobalQStringLiteral(s_jsonEnabledByDefaultKey, "EnabledByDefault")
76 GlobalQStringLiteral(s_jsonFormFactorsKey, "FormFactors")
77 GlobalQStringLiteral(s_jsonLicenseKey, "License")
78 GlobalQStringLiteral(s_jsonIdKey, "Id")
79 GlobalQStringLiteral(s_jsonVersionKey, "Version")
80 GlobalQStringLiteral(s_jsonWebsiteKey, "Website")
81 GlobalQStringLiteral(s_jsonMimeTypesKey, "MimeTypes")
82 GlobalQStringLiteral(s_jsonKPluginKey, "KPlugin")
83 
84 }
85 // clang-format on
86 
87 class KPluginInfoPrivate : public QSharedData
88 {
89 public:
90  KPluginInfoPrivate()
91  : hidden(false)
92  , pluginenabled(false)
93  , kcmservicesCached(false)
94  {
95  }
96 
97  static QStringList deserializeList(const QString &data);
98 
99  bool hidden : 1;
100  bool pluginenabled : 1;
101  mutable bool kcmservicesCached : 1;
102 
103  KPluginMetaData metaData;
105  KService::Ptr service;
106  mutable QList<KService::Ptr> kcmservices;
107 
108  /** assigns the @p md to @c metaData, but also ensures that compatibility values are handled */
109  void setMetaData(const KPluginMetaData &md, bool warnOnOldStyle);
110 };
111 
112 // This comes from KConfigGroupPrivate::deserializeList()
113 QStringList KPluginInfoPrivate::deserializeList(const QString &data)
114 {
115  if (data.isEmpty()) {
116  return QStringList();
117  }
118  if (data == QLatin1String("\\0")) {
119  return QStringList(QString());
120  }
121  QStringList value;
122  QString val;
123  val.reserve(data.size());
124  bool quoted = false;
125  for (int p = 0; p < data.length(); p++) {
126  if (quoted) {
127  val += data[p];
128  quoted = false;
129  } else if (data[p].unicode() == '\\') {
130  quoted = true;
131  } else if (data[p].unicode() == ',' || data[p].unicode() == ';') {
132  val.squeeze(); // release any unused memory
133  value.append(val);
134  val.clear();
135  val.reserve(data.size() - p);
136  } else {
137  val += data[p];
138  }
139  }
140  value.append(val);
141  return value;
142 }
143 
144 // maps the KService, QVariant and KDesktopFile keys to the new KPluginMetaData keys
145 template<typename T, typename Func>
146 static QJsonObject mapToJsonKPluginKey(const QString &name,
147  const QString &description,
148 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79)
149  const QStringList &dependencies,
150 #endif
151  const QStringList &serviceTypes,
152  const QStringList &formFactors,
153  const T &data,
154  Func accessor)
155 {
156  /* Metadata structure is as follows:
157  "KPlugin": {
158  "Name": "Date and Time",
159  "Description": "Date and time by timezone",
160  "Icon": "preferences-system-time",
161  "Authors": { "Name": "Aaron Seigo", "Email": "[email protected]" },
162  "Category": "Date and Time",
163 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79)
164  "Dependencies": [],
165 #endif
166  "EnabledByDefault": "true",
167  "License": "LGPL",
168  "Id": "time",
169  "Version": "1.0",
170  "Website": "http://plasma.kde.org/",
171  "ServiceTypes": ["Plasma/DataEngine"]
172  "FormFactors": ["tablet", "handset"]
173  }
174  */
175  QJsonObject kplugin;
176  kplugin[s_nameKey()] = name;
177  kplugin[s_jsonDescriptionKey()] = description;
178  kplugin[s_iconKey()] = accessor(data, s_iconKey());
179  QJsonObject authors;
180  authors[s_nameKey()] = accessor(data, s_authorKey());
181  authors[s_jsonEmailKey()] = accessor(data, s_emailKey());
182  kplugin[s_jsonAuthorsKey()] = authors;
183  kplugin[s_jsonCategoryKey()] = accessor(data, s_categoryKey());
184  QJsonValue enabledByDefault = accessor(data, s_enabledbyDefaultKey());
185  // make sure that enabledByDefault is bool and not string
186  if (!enabledByDefault.isBool()) {
187  enabledByDefault = enabledByDefault.toString().compare(QLatin1String("true"), Qt::CaseInsensitive) == 0;
188  }
189  kplugin[s_jsonEnabledByDefaultKey()] = enabledByDefault;
190  kplugin[s_jsonLicenseKey()] = accessor(data, s_licenseKey());
191  kplugin[s_jsonIdKey()] = accessor(data, s_pluginNameKey());
192  kplugin[s_jsonVersionKey()] = accessor(data, s_versionKey());
193  kplugin[s_jsonWebsiteKey()] = accessor(data, s_websiteKey());
194  kplugin[s_jsonFormFactorsKey()] = QJsonArray::fromStringList(formFactors);
195  kplugin[s_serviceTypesKey()] = QJsonArray::fromStringList(serviceTypes);
196 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79)
197  kplugin[s_jsonDependenciesKey()] = QJsonArray::fromStringList(dependencies);
198 #endif
199  QJsonValue mimeTypes = accessor(data, s_mimeTypeKey());
200  if (mimeTypes.isString()) {
201  QStringList mimeList = KPluginInfoPrivate::deserializeList(mimeTypes.toString());
202  if (!mimeList.isEmpty()) {
204  } else {
205  mimeTypes = QJsonValue();
206  }
207  }
208  kplugin[s_jsonMimeTypesKey()] = mimeTypes;
209  return kplugin;
210 }
211 
212 // TODO: KF6 remove
213 static KPluginMetaData fromCompatibilityJson(const QJsonObject &json, const QString &lib, const QString &metaDataFile, bool warnOnOldStyle)
214 {
215  // This is not added to KPluginMetaData(QJsonObject, QString) to ensure that all the compatility code
216  // remains in kservice and does not increase the size of kcoreaddons
217  QStringList serviceTypes = KPluginMetaData::readStringList(json, s_xKDEServiceTypes());
218  if (serviceTypes.isEmpty()) {
219  serviceTypes = KPluginMetaData::readStringList(json, s_serviceTypesKey());
220  }
221  QJsonObject obj = json;
223  if (warnOnOldStyle) {
224  qWarning(
225  "Constructing a KPluginInfo object from old style JSON. Please use"
226  " kcoreaddons_desktop_to_json() for \"%s\" instead of kservice_desktop_to_json()"
227  " in your CMake code.",
228  qPrintable(lib));
229  }
230  QString description = KPluginMetaData::readTranslatedString(json, s_commentKey());
231  QStringList formfactors = KPluginMetaData::readStringList(json, s_jsonFormFactorsKey());
232  QJsonObject kplugin = mapToJsonKPluginKey(name,
233  description,
234 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79)
235  KPluginMetaData::readStringList(json, s_dependenciesKey()),
236 #endif
237  serviceTypes,
238  formfactors,
239  json,
240  [](const QJsonObject &o, const QString &key) {
241  return o.value(key);
242  });
243  obj.insert(s_jsonKPluginKey(), kplugin);
244  return KPluginMetaData(obj, lib, metaDataFile);
245 }
246 
247 void KPluginInfoPrivate::setMetaData(const KPluginMetaData &md, bool warnOnOldStyle)
248 {
249  const QJsonObject json = md.rawData();
250  if (!json.contains(s_jsonKPluginKey())) {
251  // "KPlugin" key does not exists -> convert from compatibility mode
252  metaData = fromCompatibilityJson(json, md.fileName(), md.metaDataFileName(), warnOnOldStyle);
253  } else {
254  metaData = md;
255  }
256 }
257 
259  : d(new KPluginInfoPrivate)
260 {
261  d->setMetaData(md, true);
262  if (!d->metaData.isValid()) {
263  d.reset();
264  }
265 }
266 
267 KPluginInfo::KPluginInfo(const QString &filename /*, QStandardPaths::StandardLocation resource*/)
268  : d(new KPluginInfoPrivate)
269 {
270  KDesktopFile file(/*resource,*/ filename);
271 
272  KConfigGroup cg = file.desktopGroup();
273  if (!cg.exists()) {
274  qCWarning(SERVICES) << filename << "has no desktop group, cannot construct a KPluginInfo object from it.";
275  d.reset();
276  return;
277  }
278  d->hidden = cg.readEntry(s_hiddenKey(), false);
279  if (d->hidden) {
280  return;
281  }
282 
283  if (file.fileName().endsWith(QLatin1String(".desktop"))) {
284  d->setMetaData(KPluginMetaData::fromDesktopFile(file.fileName()), true);
285  } else {
286  d->setMetaData(KPluginMetaData(file.fileName()), true);
287  }
288  if (!d->metaData.isValid()) {
289  qCWarning(SERVICES) << "Failed to read metadata from .desktop file" << file.fileName();
290  d.reset();
291  }
292 }
293 
294 KPluginInfo::KPluginInfo(const QVariantList &args, const QString &libraryPath)
295  : d(new KPluginInfoPrivate)
296 {
297  const QString metaData = QStringLiteral("MetaData");
298  for (const QVariant &v : args) {
299  if (v.canConvert<QVariantMap>()) {
300  const QVariantMap &m = v.toMap();
301  const QVariant &_metadata = m.value(metaData);
302  if (_metadata.canConvert<QVariantMap>()) {
303  const QVariantMap &map = _metadata.toMap();
304  if (map.value(s_hiddenKey()).toBool()) {
305  d->hidden = true;
306  break;
307  }
308  d->setMetaData(KPluginMetaData(QJsonObject::fromVariantMap(map), libraryPath), true);
309  break;
310  }
311  }
312  }
313  if (!d->metaData.isValid()) {
314  d.reset();
315  }
316 }
317 
318 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 88)
320  : d(new KPluginInfoPrivate)
321 {
322  if (!service) {
323  d = nullptr; // isValid() == false
324  return;
325  }
326  d->service = service;
327  if (service->isDeleted()) {
328  d->hidden = true;
329  return;
330  }
331 
333 
334  QJsonObject json;
335  const auto propertyList = service->propertyNames();
336  for (const QString &key : propertyList) {
337  QMetaType::Type t = KSycocaPrivate::self()->serviceTypeFactory()->findPropertyTypeByName(key);
338  if (t == QMetaType::UnknownType) {
339  t = QMetaType::QString; // default to string if the type is not known
340  }
341  QVariant v = service->property(key, t);
342  if (v.isValid()) {
343  json[key] = QJsonValue::fromVariant(v);
344  }
345  }
346  // reintroduce the separation between MimeType= and X-KDE-ServiceTypes=
347  // we could do this by modifying KService and KSyCoCa, but as this is only compatibility
348  // code we just query QMimeDatabase whether a ServiceType is a valid MIME type.
349  const QStringList services = service->serviceTypes();
350  if (!services.isEmpty()) {
351  QMimeDatabase db;
352  QStringList mimeTypes;
353  mimeTypes.reserve(services.size());
354  QStringList newServiceTypes;
355  newServiceTypes.reserve(services.size());
356  for (const QString &s : services) {
357  // If we have a valid mime type of a wildcard, we know it is a mime type and not a service type
358  // this is for example required in the thumbnailers.
359  // Also the conversion code in kcoreaddons does not check the validity.
360  if (db.mimeTypeForName(s).isValid() || s.contains(QLatin1Char('*'))) {
361  mimeTypes << s;
362  } else {
363  newServiceTypes << s;
364  }
365  }
366  json[s_mimeTypeKey()] = QJsonArray::fromStringList(mimeTypes);
367  json[s_xKDEServiceTypes()] = QJsonArray::fromStringList(newServiceTypes);
368  json[s_serviceTypesKey()] = QJsonValue();
369  }
370 
371  d->setMetaData(KPluginMetaData(json, service->library(), service->entryPath()), false);
372  if (!d->metaData.isValid()) {
373  d.reset();
374  }
375 }
376 #endif
377 
379  : d(nullptr) // isValid() == false
380 {
381 }
382 
384 {
385  return d.data() != nullptr;
386 }
387 
389  : d(rhs.d)
390 {
391 }
392 
394 {
395  d = rhs.d;
396  return *this;
397 }
398 
399 bool KPluginInfo::operator==(const KPluginInfo &rhs) const
400 {
401  return d == rhs.d;
402 }
403 
404 bool KPluginInfo::operator!=(const KPluginInfo &rhs) const
405 {
406  return d != rhs.d;
407 }
408 
409 bool KPluginInfo::operator<(const KPluginInfo &rhs) const
410 {
411  if (category() < rhs.category()) {
412  return true;
413  }
414  if (category() == rhs.category()) {
415  return name() < rhs.name();
416  }
417  return false;
418 }
419 
420 bool KPluginInfo::operator>(const KPluginInfo &rhs) const
421 {
422  if (category() > rhs.category()) {
423  return true;
424  }
425  if (category() == rhs.category()) {
426  return name() > rhs.name();
427  }
428  return false;
429 }
430 
431 KPluginInfo::~KPluginInfo()
432 {
433 }
434 
435 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 88)
437 {
438  QList<KPluginInfo> infolist;
439  for (KService::List::ConstIterator it = services.begin(); it != services.end(); ++it) {
440  KPluginInfo info(*it);
441  if (info.isValid()) {
442  info.setConfig(config);
443  infolist += info;
444  }
445  }
446  return infolist;
447 }
448 #endif
449 
451 {
452  QList<KPluginInfo> infolist;
453  infolist.reserve(files.size());
454 
455  std::transform(files.cbegin(), files.cend(), std::back_inserter(infolist), [&config](const QString &file) {
456  KPluginInfo info(file);
457  info.setConfig(config);
458  return info;
459  });
460 
461  return infolist;
462 }
463 
464 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 81)
466 {
467  QStringList files;
468  const QStringList dirs =
470  for (const QString &dir : dirs) {
471  QDirIterator it(dir, QStringList() << QStringLiteral("*.desktop"));
472  while (it.hasNext()) {
473  files.append(it.next());
474  }
475  }
476  return fromFiles(files, config);
477 }
478 #endif
479 
481 {
482  KPLUGININFO_ISVALID_ASSERTION;
483  return d->hidden;
484 }
485 
487 {
488  KPLUGININFO_ISVALID_ASSERTION;
489  // qDebug() << Q_FUNC_INFO;
490  d->pluginenabled = enabled;
491 }
492 
494 {
495  KPLUGININFO_ISVALID_ASSERTION;
496  // qDebug() << Q_FUNC_INFO;
497  return d->pluginenabled;
498 }
499 
501 {
502  KPLUGININFO_ISVALID_ASSERTION;
503  // qDebug() << Q_FUNC_INFO;
504  return d->metaData.isEnabledByDefault();
505 }
506 
508 {
509  KPLUGININFO_ISVALID_ASSERTION;
510  return d->metaData.name();
511 }
512 
514 {
515  KPLUGININFO_ISVALID_ASSERTION;
516  return d->metaData.description();
517 }
518 
520 {
521  KPLUGININFO_ISVALID_ASSERTION;
522  return d->metaData.iconName();
523 }
524 
526 {
527  KPLUGININFO_ISVALID_ASSERTION;
528  return d->metaData.metaDataFileName();
529 }
530 
532 {
533  KPLUGININFO_ISVALID_ASSERTION;
534  const QList<KAboutPerson> &authors = d->metaData.authors();
535  return authors.isEmpty() ? QString() : authors[0].name();
536 }
537 
539 {
540  KPLUGININFO_ISVALID_ASSERTION;
541  const QList<KAboutPerson> &authors = d->metaData.authors();
542  return authors.isEmpty() ? QString() : authors[0].emailAddress();
543 }
544 
546 {
547  KPLUGININFO_ISVALID_ASSERTION;
548  return d->metaData.category();
549 }
550 
552 {
553  KPLUGININFO_ISVALID_ASSERTION;
554  return d->metaData.formFactors();
555 }
556 
558 {
559  KPLUGININFO_ISVALID_ASSERTION;
560  return d->metaData.pluginId();
561 }
562 
564 {
565  KPLUGININFO_ISVALID_ASSERTION;
566  return d->metaData.fileName();
567 }
568 
570 {
571  KPLUGININFO_ISVALID_ASSERTION;
572  return d->metaData.version();
573 }
574 
576 {
577  KPLUGININFO_ISVALID_ASSERTION;
578  return d->metaData.website();
579 }
580 
582 {
583  KPLUGININFO_ISVALID_ASSERTION;
584  return d->metaData.license();
585 }
586 
587 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79)
588 QStringList KPluginInfo::dependencies() const
589 {
590  KPLUGININFO_ISVALID_ASSERTION;
591  return d->metaData.dependencies();
592 }
593 #endif
594 
596 {
597  KPLUGININFO_ISVALID_ASSERTION;
598  // KService/KPluginInfo include the MIME types in serviceTypes()
599  return d->metaData.serviceTypes() + d->metaData.mimeTypes();
600 }
601 
602 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 70)
604 {
605  KPLUGININFO_ISVALID_ASSERTION;
606  return d->service;
607 }
608 #endif
609 
611 {
612  KPLUGININFO_ISVALID_ASSERTION;
613  if (!d->kcmservicesCached) {
614  d->kcmservices =
615  KServiceTypeTrader::self()->query(QStringLiteral("KCModule"), QLatin1Char('\'') + pluginName() + QLatin1String("' in [X-KDE-ParentComponents]"));
616  // qDebug() << "found" << d->kcmservices.count() << "offers for" << d->pluginName;
617 
618  d->kcmservicesCached = true;
619  }
620 
621  return d->kcmservices;
622 }
623 
625 {
626  KPLUGININFO_ISVALID_ASSERTION;
627  d->config = config;
628 }
629 
631 {
632  KPLUGININFO_ISVALID_ASSERTION;
633  return d->config;
634 }
635 
637 {
638  KPLUGININFO_ISVALID_ASSERTION;
639  if (d->service) {
640  return d->service->property(key);
641  }
642  QVariant result = d->metaData.rawData().value(key).toVariant();
643  if (result.isValid()) {
645  const QMetaType::Type t = KSycocaPrivate::self()->serviceTypeFactory()->findPropertyTypeByName(key);
646 
647  // special case if we want a stringlist: split values by ',' or ';' and construct the list
648  if (t == QMetaType::QStringList) {
649  if (result.canConvert<QString>()) {
650  result = KPluginInfoPrivate::deserializeList(result.toString());
651  } else if (result.canConvert<QVariantList>()) {
652  const QVariantList list = result.toList();
653  QStringList newResult;
654  for (const QVariant &value : list) {
655  newResult += value.toString();
656  }
657  result = newResult;
658  } else {
659  qCWarning(SERVICES) << "Cannot interpret" << result << "into a string list";
660  }
661  }
662  return result;
663  }
664 
665  // If the key was not found check compatibility for old key names and print a warning
666  // These warnings should only happen if JSON was generated with kcoreaddons_desktop_to_json
667  // but the application uses KPluginTrader::query() instead of KPluginLoader::findPlugins()
668  // TODO: KF6 remove
669 #define RETURN_WITH_DEPRECATED_WARNING(ret) \
670  qWarning("Calling KPluginInfo::property(\"%s\") is deprecated, use KPluginInfo::" #ret " in \"%s\" instead.", \
671  qPrintable(key), \
672  qPrintable(d->metaData.fileName())); \
673  return ret;
674  if (key == s_authorKey()) {
675  RETURN_WITH_DEPRECATED_WARNING(author());
676  } else if (key == s_categoryKey()) {
677  RETURN_WITH_DEPRECATED_WARNING(category());
678  } else if (key == s_commentKey()) {
679  RETURN_WITH_DEPRECATED_WARNING(comment());
680 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 79) && KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 79)
681  } else if (key == s_dependenciesKey()) {
682  RETURN_WITH_DEPRECATED_WARNING(dependencies());
683 #endif
684  } else if (key == s_emailKey()) {
685  RETURN_WITH_DEPRECATED_WARNING(email());
686  } else if (key == s_enabledbyDefaultKey()) {
687  RETURN_WITH_DEPRECATED_WARNING(isPluginEnabledByDefault());
688  } else if (key == s_libraryKey()) {
689  RETURN_WITH_DEPRECATED_WARNING(libraryPath());
690  } else if (key == s_licenseKey()) {
691  RETURN_WITH_DEPRECATED_WARNING(license());
692  } else if (key == s_nameKey()) {
693  RETURN_WITH_DEPRECATED_WARNING(name());
694  } else if (key == s_pluginNameKey()) {
695  RETURN_WITH_DEPRECATED_WARNING(pluginName());
696  } else if (key == s_serviceTypesKey()) {
697  RETURN_WITH_DEPRECATED_WARNING(serviceTypes());
698  } else if (key == s_versionKey()) {
699  RETURN_WITH_DEPRECATED_WARNING(version());
700  } else if (key == s_websiteKey()) {
701  RETURN_WITH_DEPRECATED_WARNING(website());
702  } else if (key == s_xKDEServiceTypes()) {
703  RETURN_WITH_DEPRECATED_WARNING(serviceTypes());
704  } else if (key == s_formFactorsKey()) {
705  RETURN_WITH_DEPRECATED_WARNING(formFactors());
706  }
707 #undef RETURN_WITH_DEPRECATED_WARNING
708  // not a compatibility key -> return invalid QVariant
709  return result;
710 }
711 
712 QVariantMap KPluginInfo::properties() const
713 {
714  return d->metaData.rawData().toVariantMap();
715 }
716 
718 {
719  KPLUGININFO_ISVALID_ASSERTION;
720  // qDebug() << Q_FUNC_INFO;
721  if (config.isValid()) {
722  config.writeEntry(pluginName() + s_enabledKey(), isPluginEnabled());
723  } else {
724  if (!d->config.isValid()) {
725  qCWarning(SERVICES) << "no KConfigGroup, cannot save";
726  return;
727  }
728  d->config.writeEntry(pluginName() + s_enabledKey(), isPluginEnabled());
729  }
730 }
731 
732 void KPluginInfo::load(const KConfigGroup &config)
733 {
734  KPLUGININFO_ISVALID_ASSERTION;
735  // qDebug() << Q_FUNC_INFO;
736  if (config.isValid()) {
738  } else {
739  if (!d->config.isValid()) {
740  qCWarning(SERVICES) << "no KConfigGroup, cannot load";
741  return;
742  }
743  setPluginEnabled(d->config.readEntry(pluginName() + s_enabledKey(), isPluginEnabledByDefault()));
744  }
745 }
746 
748 {
749  // qDebug() << Q_FUNC_INFO;
751 }
752 
753 uint qHash(const KPluginInfo &p)
754 {
755  return qHash(reinterpret_cast<quint64>(p.d.data()));
756 }
757 
759 {
760  return KPluginInfo(md);
761 }
762 
764 {
765  KPLUGININFO_ISVALID_ASSERTION;
766  return d->metaData;
767 }
768 
770 {
771  return info.toMetaData();
772 }
773 
775 {
776  KPluginInfo::List ret;
777  ret.reserve(list.size());
778  for (const KPluginMetaData &md : list) {
780  }
781  return ret;
782 }
783 
785 {
787  ret.reserve(list.size());
788  for (const KPluginInfo &info : list) {
789  ret.append(info.toMetaData());
790  }
791  return ret;
792 }
793 
794 #undef KPLUGININFO_ISVALID_ASSERTION
795 #endif
static KSycoca * self()
Get or create the only instance of KSycoca (read-only)
Definition: ksycoca.cpp:379
void append(const T &value)
QString readEntry(const char *key, const char *aDefault=nullptr) const
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
QJsonObject rawData() const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
void squeeze()
bool isValid() const const
void ensureCacheValid()
Ensures the ksycoca database is up to date.
Definition: ksycoca.cpp:826
QStringList formFactors() const
static KPluginInfo::List fromServices(const KService::List &services, const KConfigGroup &config=KConfigGroup())
int size() const const
CaseInsensitive
QString libraryPath() const
static KPluginInfo::List fromKPartsInstanceName(const QString &componentName, const KConfigGroup &config=KConfigGroup())
KCOREADDONS_EXPORT void setMetaData(const MetaDataMap &metaData, QMimeData *mimeData)
QString metaDataFileName() const
T value() const const
QString icon() const
bool hasNext() const const
bool operator>(const KPluginInfo &rhs) const
Greater than relation comparing the categories and if they are the same using the names.
void clear()
KPluginInfo()
Creates an invalid plugin.
void append(const T &value)
QJsonObject fromVariantMap(const QVariantMap &map)
bool isValid() const
QString fileName() const
QString toString() const const
void load(const KConfigGroup &config=KConfigGroup())
Load the state of the plugin - enabled or not.
QString author() const
QList< KService::Ptr > kcmServices() const
static QStringList readStringList(const QJsonObject &jo, const QString &key)
static KPluginInfo::List fromFiles(const QStringList &files, const KConfigGroup &config=KConfigGroup())
void reserve(int size)
QString next()
QVariantMap properties() const
bool isHidden() const
static KPluginInfo fromMetaData(const KPluginMetaData &meta)
bool contains(const QString &key) const const
void reserve(int alloc)
bool exists() const
int size() const const
QString fileName() const
QString pluginName() const
void defaults()
Restore defaults (enabled or not).
QJsonObject::iterator insert(const QString &key, const QJsonValue &value)
KService::Ptr service() const
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
bool isEmpty() const const
int length() const const
QString entryPath() const
QString category() const
QJsonArray fromStringList(const QStringList &list)
static QString readTranslatedString(const QJsonObject &jo, const QString &key, const QString &defaultValue=QString())
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
bool isEmpty() const const
QJsonValue value(const QString &key) const const
QList::const_iterator cend() const const
static KServiceTypeTrader * self()
This is a static pointer to the KServiceTypeTrader singleton.
QVariant property(const QString &key) const
bool isValid() const const
KSharedConfigPtr config()
bool operator<(const KPluginInfo &rhs) const
Less than relation comparing the categories and if they are the same using the names.
KDB_EXPORT QStringList deserializeList(const QString &data)
void setPluginEnabled(bool enabled)
Set whether the plugin is currently loaded.
bool isValid() const
Returns whether the object is valid.
void reserve(int size)
bool isBool() const const
QMap< QString, QVariant > toMap() const const
bool canConvert(int targetTypeId) const const
typedef ConstIterator
KConfigGroup config() const
KConfigGroup desktopGroup() const
bool operator==(const KPluginInfo &rhs) const
Compares two objects whether they share the same data.
void setConfig(const KConfigGroup &config)
Set the KConfigGroup to use for load()ing and save()ing the configuration.
void save(KConfigGroup config=KConfigGroup())
Save state of the plugin - enabled or not.
QString name() const
QString name(StandardShortcut id)
KStandardDirs * dirs()
QStringList locateAll(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options)
QList::const_iterator cbegin() const const
QString email() const
QList< QVariant > toList() const const
QStringList mimeTypes(Mode mode=Writing)
QString license() const
QList::iterator begin()
QString website() const
QString comment() const
int compare(const QString &other, Qt::CaseSensitivity cs) const const
static KPluginMetaData fromDesktopFile(const QString &file, const QStringList &serviceTypes=QStringList())
KService::List query(const QString &servicetype, const QString &constraint=QString()) const
The main function in the KServiceTypeTrader class.
QString version() const
KPluginMetaData toMetaData() const
bool operator!=(const KPluginInfo &rhs) const
Compares two objects whether they don't share the same data.
QList::iterator end()
QJsonValue fromVariant(const QVariant &variant)
bool isPluginEnabledByDefault() const
KPluginInfo & operator=(const KPluginInfo &rhs)
Copies the KPluginInfo object to share the data with copy.
QStringList serviceTypes() const
QString toString() const const
bool isPluginEnabled() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Dec 5 2023 03:55:38 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.