KIO

kurifilter.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2000 Yves Arrouye <[email protected]>
4  SPDX-FileCopyrightText: 2000, 2010 Dawit Alemayehu <adawit at kde.org>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "kurifilter.h"
10 
11 #include "hostinfo.h"
12 
13 #include <KIconLoader>
14 #include <KService>
15 #include <kio/global.h>
16 
17 #include <KPluginMetaData>
18 
19 #include <QHashIterator>
20 #include <QHostInfo>
21 #include <QHostAddress>
22 
25 
26 static QString lookupIconNameFor(const QUrl &url, KUriFilterData::UriTypes type)
27 {
28  QString iconName;
29 
30  switch (type) {
31  case KUriFilterData::NetProtocol:
32  iconName = KIO::iconNameForUrl(url);
33  break;
34  case KUriFilterData::Executable: {
35  QString exeName = url.path();
36  exeName.remove(0, exeName.lastIndexOf(QLatin1Char('/')) + 1); // strip path if given
38  if (service && service->icon() != QLatin1String("unknown")) {
39  iconName = service->icon();
40  }
41  // Try to find an icon with the same name as the binary (useful for non-kde apps)
42  // Use iconPath rather than loadIcon() as the latter uses QPixmap (not threadsafe)
43  else if (!KIconLoader::global()->iconPath(exeName, KIconLoader::NoGroup, true).isNull()) {
44  iconName = exeName;
45  } else
46  // not found, use default
47  {
48  iconName = QStringLiteral("system-run");
49  }
50  break;
51  }
52  case KUriFilterData::Help: {
53  iconName = QStringLiteral("khelpcenter");
54  break;
55  }
56  case KUriFilterData::Shell: {
57  iconName = QStringLiteral("konsole");
58  break;
59  }
60  case KUriFilterData::Error:
61  case KUriFilterData::Blocked: {
62  iconName = QStringLiteral("error");
63  break;
64  }
65  default:
66  break;
67  }
68 
69  return iconName;
70 }
71 
72 class Q_DECL_HIDDEN KUriFilterSearchProvider::KUriFilterSearchProviderPrivate
73 {
74 public:
75  KUriFilterSearchProviderPrivate() {}
76  KUriFilterSearchProviderPrivate(const KUriFilterSearchProviderPrivate &other)
77  : desktopEntryName(other.desktopEntryName),
78  iconName(other.iconName),
79  name(other.name),
80  keys(other.keys) {}
81 
82  QString desktopEntryName;
83  QString iconName;
84  QString name;
85  QStringList keys;
86 };
87 
89  : d(new KUriFilterSearchProvider::KUriFilterSearchProviderPrivate)
90 {
91 }
92 
94  : d(new KUriFilterSearchProvider::KUriFilterSearchProviderPrivate(*(other.d)))
95 {
96 }
97 
99 {
100  delete d;
101 }
102 
104 {
105  return d->desktopEntryName;
106 }
107 
109 {
110  return d->iconName;
111 }
112 
114 {
115  return d->name;
116 }
117 
119 {
120  return d->keys;
121 }
122 
124 {
125  if (d->keys.isEmpty()) {
126  return QString();
127  }
128 
129  return d->keys.first();
130 }
131 
133 {
134  d->desktopEntryName = other.d->desktopEntryName;
135  d->iconName = other.d->iconName;
136  d->keys = other.d->keys;
137  d->name = other.d->name;
138  return *this;
139 }
140 
141 void KUriFilterSearchProvider::setDesktopEntryName(const QString &desktopEntryName)
142 {
143  d->desktopEntryName = desktopEntryName;
144 }
145 
146 void KUriFilterSearchProvider::setIconName(const QString &iconName)
147 {
148  d->iconName = iconName;
149 }
150 
151 void KUriFilterSearchProvider::setName(const QString &name)
152 {
153  d->name = name;
154 }
155 
156 void KUriFilterSearchProvider::setKeys(const QStringList &keys)
157 {
158  d->keys = keys;
159 }
160 
161 class KUriFilterDataPrivate
162 {
163 public:
164  explicit KUriFilterDataPrivate(const QUrl &u, const QString &typedUrl)
165  : checkForExecs(true),
166  wasModified(true),
167  uriType(KUriFilterData::Unknown),
168  searchFilterOptions(KUriFilterData::SearchFilterOptionNone),
170  typedString(typedUrl)
171  {
172  }
173 
174  ~KUriFilterDataPrivate()
175  {
176  }
177 
178  void setData(const QUrl &u, const QString &typedUrl)
179  {
180  checkForExecs = true;
181  wasModified = true;
182  uriType = KUriFilterData::Unknown;
183  searchFilterOptions = KUriFilterData::SearchFilterOptionNone;
184 
186  typedString = typedUrl;
187 
188  errMsg.clear();
189  iconName.clear();
190  absPath.clear();
191  args.clear();
192  searchTerm.clear();
193  searchProvider.clear();
194  searchTermSeparator = QChar();
195  alternateDefaultSearchProvider.clear();
196  alternateSearchProviders.clear();
197  searchProviderMap.clear();
198  defaultUrlScheme.clear();
199  }
200 
201  KUriFilterDataPrivate(KUriFilterDataPrivate *data)
202  {
203  wasModified = data->wasModified;
204  checkForExecs = data->checkForExecs;
205  uriType = data->uriType;
206  searchFilterOptions = data->searchFilterOptions;
207 
208  url = data->url;
209  typedString = data->typedString;
210 
211  errMsg = data->errMsg;
212  iconName = data->iconName;
213  absPath = data->absPath;
214  args = data->args;
215  searchTerm = data->searchTerm;
216  searchTermSeparator = data->searchTermSeparator;
217  searchProvider = data->searchProvider;
218  alternateDefaultSearchProvider = data->alternateDefaultSearchProvider;
219  alternateSearchProviders = data->alternateSearchProviders;
220  searchProviderMap = data->searchProviderMap;
221  defaultUrlScheme = data->defaultUrlScheme;
222  }
223 
224  bool checkForExecs;
225  bool wasModified;
226  KUriFilterData::UriTypes uriType;
227  KUriFilterData::SearchFilterOptions searchFilterOptions;
228 
229  QUrl url;
230  QString typedString;
231  QString errMsg;
233  QString absPath;
234  QString args;
235  QString searchTerm;
236  QString searchProvider;
237  QString alternateDefaultSearchProvider;
238  QString defaultUrlScheme;
239  QChar searchTermSeparator;
240 
241  QStringList alternateSearchProviders;
242  QStringList searchProviderList;
243  SearchProviderMap searchProviderMap;
244 };
245 
247  : d(new KUriFilterDataPrivate(QUrl(), QString()))
248 {
249 }
250 
252  : d(new KUriFilterDataPrivate(url, url.toString()))
253 {
254 }
255 
257  : d(new KUriFilterDataPrivate(QUrl::fromUserInput(url), url))
258 {
259 }
260 
262  : d(new KUriFilterDataPrivate(other.d))
263 {
264 }
265 
267 {
268  delete d;
269 }
270 
272 {
273  return d->url;
274 }
275 
277 {
278  return d->errMsg;
279 }
280 
282 {
283  return d->uriType;
284 }
285 
287 {
288  return d->absPath;
289 }
290 
292 {
293  return !d->absPath.isEmpty();
294 }
295 
297 {
298  return d->args;
299 }
300 
302 {
303  return !d->args.isEmpty();
304 }
305 
307 {
308  return d->checkForExecs;
309 }
310 
312 {
313  return d->typedString;
314 }
315 
317 {
318  return d->searchTerm;
319 }
320 
322 {
323  return d->searchTermSeparator;
324 }
325 
327 {
328  return d->searchProvider;
329 }
330 
332 {
333  return d->searchProviderList;
334 }
335 
337 {
338  const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(provider);
339 
340  if (searchProvider) {
341  return *(searchProvider);
342  }
343 
344  return KUriFilterSearchProvider();
345 }
346 
348 {
349  const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(provider);
350  if (searchProvider) {
351  return (searchProvider->defaultKey() % searchTermSeparator() % searchTerm());
352  }
353  return QString();
354 }
355 
357 {
358  const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(provider);
359  if (searchProvider) {
360  return searchProvider->keys();
361  }
362  return QStringList();
363 }
364 
366 {
367  const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(provider);
368  if (searchProvider) {
369  return searchProvider->iconName();
370  }
371  return QString();
372 }
373 
375 {
376  return d->alternateSearchProviders;
377 }
378 
380 {
381  return d->alternateDefaultSearchProvider;
382 }
383 
385 {
386  return d->defaultUrlScheme;
387 }
388 
390 {
391  return d->searchFilterOptions;
392 }
393 
395 {
396  if (d->wasModified) {
397  d->iconName = lookupIconNameFor(d->url, d->uriType);
398  d->wasModified = false;
399  }
400 
401  return d->iconName;
402 }
403 
405 {
406  d->setData(url, url.toString());
407 }
408 
410 {
411  d->setData(QUrl(url), url);
412 }
413 
415 {
416  // Since a malformed URL could possibly be a relative
417  // URL we tag it as a possible local resource...
418  if ((d->url.scheme().isEmpty() || d->url.isLocalFile())) {
419  d->absPath = absPath;
420  return true;
421  }
422  return false;
423 }
424 
426 {
427  d->checkForExecs = check;
428 }
429 
431 {
432  d->alternateSearchProviders = providers;
433 }
434 
436 {
437  d->alternateDefaultSearchProvider = provider;
438 }
439 
441 {
442  d->defaultUrlScheme = scheme;
443 }
444 
446 {
447  d->searchFilterOptions = options;
448 }
449 
451 {
452  d->setData(url, url.toString());
453  return *this;
454 }
455 
457 {
458  d->setData(QUrl(url), url);
459  return *this;
460 }
461 
462 /************************* KUriFilterPlugin ******************************/
463 
465  : QObject(parent), d(nullptr)
466 {
467  setObjectName(name);
468 }
469 
470 // KF6 TODO
471 //KUriFilterPlugin::~KUriFilterPlugin()
472 //{
473 //}
474 
476 {
477  return nullptr;
478 }
479 
481 {
482  return objectName();
483 }
484 
486 {
487  data.d->url = uri.adjusted(QUrl::NormalizePathSegments);
488  data.d->wasModified = true;
489  //qDebug() << "Got filtered to:" << uri;
490 }
491 
493  const QString &errmsg) const
494 {
495  data.d->errMsg = errmsg;
496 }
497 
499  KUriFilterData::UriTypes type) const
500 {
501  data.d->uriType = type;
502  data.d->wasModified = true;
503 }
504 
506  const QString &args) const
507 {
508  data.d->args = args;
509 }
510 
512  const QString &term, const QChar &separator) const
513 {
514  data.d->searchProvider = provider;
515  data.d->searchTerm = term;
516  data.d->searchTermSeparator = separator;
517 }
518 
520 {
521  data.d->searchProviderList.reserve(data.d->searchProviderList.size() + providers.size());
522  for (KUriFilterSearchProvider *searchProvider : providers) {
523  data.d->searchProviderList << searchProvider->name();
524  data.d->searchProviderMap.insert(searchProvider->name(), searchProvider);
525  }
526 }
527 
529 {
530  return lookupIconNameFor(url, type);
531 }
532 
533 QHostInfo KUriFilterPlugin::resolveName(const QString &hostname, unsigned long timeout) const
534 {
535  return KIO::HostInfo::lookupHost(hostname, timeout);
536 }
537 
538 /******************************* KUriFilter ******************************/
539 
540 class KUriFilterPrivate
541 {
542 public:
543  KUriFilterPrivate() {}
544  ~KUriFilterPrivate()
545  {
546  qDeleteAll(pluginList);
547  pluginList.clear();
548  }
549  QVector<KUriFilterPlugin *> pluginList;
550 };
551 
552 class KUriFilterSingleton
553 {
554 public:
555  KUriFilter instance;
556 };
557 
558 Q_GLOBAL_STATIC(KUriFilterSingleton, m_self)
559 
561 {
562  return &m_self()->instance;
563 }
564 
566  : d(new KUriFilterPrivate())
567 {
568  loadPlugins();
569 }
570 
572 {
573  delete d;
574 }
575 
577 {
578  bool filtered = false;
579 
580  for (KUriFilterPlugin *plugin : qAsConst(d->pluginList)) {
581  // If no specific filters were requested, iterate through all the plugins.
582  // Otherwise, only use available filters.
583  if (filters.isEmpty() || filters.contains(plugin->objectName())) {
584  if (plugin->filterUri(data)) {
585  filtered = true;
586  }
587  }
588  }
589 
590  return filtered;
591 }
592 
593 bool KUriFilter::filterUri(QUrl &uri, const QStringList &filters)
594 {
595  KUriFilterData data(uri);
596  bool filtered = filterUri(data, filters);
597  if (filtered) {
598  uri = data.uri();
599  }
600  return filtered;
601 }
602 
603 bool KUriFilter::filterUri(QString &uri, const QStringList &filters)
604 {
605  KUriFilterData data(uri);
606  bool filtered = filterUri(data, filters);
607  if (filtered) {
608  uri = data.uri().toString();
609  }
610  return filtered;
611 }
612 
613 QUrl KUriFilter::filteredUri(const QUrl &uri, const QStringList &filters)
614 {
615  KUriFilterData data(uri);
616  filterUri(data, filters);
617  return data.uri();
618 }
619 
621 {
622  KUriFilterData data(uri);
623  filterUri(data, filters);
624  return data.uri().toString();
625 }
626 
627 #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(4, 6)
629 {
630  return filterSearchUri(data, (NormalTextFilter | WebShortcutFilter));
631 }
632 #endif
633 
635 {
636  QStringList filters;
637 
638  if (types & WebShortcutFilter) {
639  filters << QStringLiteral("kurisearchfilter");
640  }
641 
642  if (types & NormalTextFilter) {
643  filters << QStringLiteral("kuriikwsfilter");
644  }
645 
646  return filterUri(data, filters);
647 }
648 
650 {
651  QStringList res;
652  res.reserve(d->pluginList.size());
653  std::transform(d->pluginList.constBegin(), d->pluginList.constEnd(), std::back_inserter(res), [](const KUriFilterPlugin *plugin) { return plugin->objectName(); });
654  return res;
655 }
656 
658 {
659  QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(QStringLiteral("kf5/urifilters"));
660  const QString prefKey = QStringLiteral("X-KDE-InitialPreference");
661  // Sort the plugins by order of priority
662  std::sort(plugins.begin(), plugins.end(), [prefKey](const KPluginMetaData &a, const KPluginMetaData &b) {
663  return a.rawData().value(prefKey).toInt() > b.rawData().value(prefKey).toInt();
664  });
665 
667  pluginNames.reserve(plugins.count());
668 
669  for (const KPluginMetaData &pluginMetaData : qAsConst(plugins)) {
670  const QString fileName = pluginMetaData.fileName().section(QLatin1Char('/'), -1);
671  if (!pluginNames.contains(fileName)) {
672  pluginNames << fileName;
673  KPluginFactory *factory = qobject_cast<KPluginFactory *>(pluginMetaData.instantiate());
674  if (factory) {
675  KUriFilterPlugin *plugin = factory->create<KUriFilterPlugin>(nullptr);
676  if (plugin) {
677  d->pluginList << plugin;
678  }
679  }
680  }
681  }
682 }
683 
QString searchProvider() const
Returns the name of the search service provider, e.g.
Definition: kurifilter.cpp:326
NormalizePathSegments
Base class for URI filter plugins.
Definition: kurifilter.h:632
bool checkForExecutables() const
Definition: kurifilter.cpp:306
QString errorMsg() const
Returns an error message.
Definition: kurifilter.cpp:276
QString queryForPreferredSearchProvider(const QString &provider) const
Returns the web shortcut url for the given preferred search provider.
Definition: kurifilter.cpp:347
void setAlternateSearchProviders(const QStringList &providers)
Sets a list of search providers to use in case no preferred search providers are available.
Definition: kurifilter.cpp:430
QString name(const QVariant &location)
QChar searchTermSeparator() const
Returns the character that is used to separate the search term from the keyword.
Definition: kurifilter.cpp:321
KUriFilterSearchProvider & operator=(const KUriFilterSearchProvider &)
Assignment operator.
Definition: kurifilter.cpp:132
bool hasAbsolutePath() const
Checks whether the supplied data had an absolute path.
Definition: kurifilter.cpp:291
void setAlternateDefaultSearchProvider(const QString &provider)
Sets the search provider to use in case no default provider is available.
Definition: kurifilter.cpp:435
QVector::iterator begin()
static Ptr serviceByDesktopName(const QString &_name)
QString desktopEntryName() const
Returns the desktop filename of the search provider without any extension.
Definition: kurifilter.cpp:103
T * create(QObject *parent=nullptr, const QVariantList &args=QVariantList())
void reserve(int alloc)
QString argsAndOptions() const
Returns the command line options and arguments for a local resource when present. ...
Definition: kurifilter.cpp:296
QString name() const
Returns the descriptive name of the search provider, e.g.
Definition: kurifilter.cpp:113
QHostInfo resolveName(const QString &hostname, unsigned long timeout) const
Performs a DNS lookup for hostname and returns the result.
Definition: kurifilter.cpp:533
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
KUriFilterSearchProvider()
Default constructor.
Definition: kurifilter.cpp:88
QString searchTerm() const
Returns the search term portion of the typed string.
Definition: kurifilter.cpp:316
QStringList keys() const
Returns all the web shortcut keys associated with this search provider.
Definition: kurifilter.cpp:118
QString alternateDefaultSearchProvider() const
Returns the search provider to use when a default provider is not available.
Definition: kurifilter.cpp:379
KIOCORE_EXPORT void lookupHost(const QString &hostName, QObject *receiver, const char *member)
Definition: hostinfo.cpp:234
void setArguments(KUriFilterData &data, const QString &args) const
Sets the arguments and options string in data to args if any were found during filtering.
Definition: kurifilter.cpp:505
KUriFilterPlugin(const QString &name, QObject *parent=nullptr)
Constructs a filter plugin with a given name.
Definition: kurifilter.cpp:464
QString & remove(int position, int n)
QString iconName()
The name of the icon that matches the current filtered URL.
Definition: kurifilter.cpp:394
QString toString(QUrl::FormattingOptions options) const const
void setDefaultUrlScheme(const QString &)
Sets the default scheme used when filtering potentially valid url inputs.
Definition: kurifilter.cpp:440
QStringList allQueriesForSearchProvider(const QString &provider) const
Returns all the query urls for the given search provider.
Definition: kurifilter.cpp:356
QString iconNameForPreferredSearchProvider(const QString &provider) const
Returns the icon associated with the given preferred search provider.
Definition: kurifilter.cpp:365
KUriFilter()
Constructor.
Definition: kurifilter.cpp:565
int size() const const
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
void clear()
int toInt(int defaultValue) const const
QString defaultKey() const
Returns the default web shortcut key for this search provider.
Definition: kurifilter.cpp:123
bool filterUri(KUriFilterData &data, const QStringList &filters=QStringList())
Filters data using the specified filters.
Definition: kurifilter.cpp:576
QUrl filteredUri(const QUrl &uri, const QStringList &filters=QStringList())
Returns the filtered URI.
Definition: kurifilter.cpp:613
Class that holds information about a search provider.
Definition: kurifilter.h:38
void setSearchProviders(KUriFilterData &data, const QList< KUriFilterSearchProvider * > &providers) const
Sets the information about the search providers in data.
Definition: kurifilter.cpp:519
bool isEmpty() const const
void setObjectName(const QString &name)
void loadPlugins()
Loads all allowed plugins.
Definition: kurifilter.cpp:657
QUrl uri() const
Returns the filtered or the original URL.
Definition: kurifilter.cpp:271
QString path(QUrl::ComponentFormattingOptions options) const const
virtual QString configName() const
Returns the name of the configuration module for the filter.
Definition: kurifilter.cpp:480
QJsonObject rawData() const
UriTypes
Describes the type of the URI that was filtered.
Definition: kurifilter.h:171
void setFilteredUri(KUriFilterData &data, const QUrl &uri) const
Sets the URL in data to uri.
Definition: kurifilter.cpp:485
static KIconLoader * global()
KUriFilter applies a number of filters to a URI and returns a filtered version if any filter matches...
Definition: kurifilter.h:853
This class is a basic messaging class used to exchange filtering information between the filter plugi...
Definition: kurifilter.h:152
QString icon() const
~KUriFilter()
Destructor.
Definition: kurifilter.cpp:571
QStringList pluginNames() const
Return a list of the names of all loaded plugins.
Definition: kurifilter.cpp:649
void setData(const QUrl &url)
Same as above except the argument is a URL.
Definition: kurifilter.cpp:404
QString absolutePath() const
Returns the absolute path if one has already been set.
Definition: kurifilter.cpp:286
QStringList preferredSearchProviders() const
Returns a list of the names of preferred or available search providers.
Definition: kurifilter.cpp:331
QStringList alternateSearchProviders() const
Returns the list of alternate search providers.
Definition: kurifilter.cpp:374
KUriFilterSearchProvider queryForSearchProvider(const QString &provider) const
Returns information about provider.
Definition: kurifilter.cpp:336
virtual ~KUriFilterSearchProvider()
Destructor.
Definition: kurifilter.cpp:98
~KUriFilterData()
Destructor.
Definition: kurifilter.cpp:266
SearchFilterOptions searchFilteringOptions() const
Returns the specified search filter options.
Definition: kurifilter.cpp:389
void setSearchProvider(KUriFilterData &data, const QString &provider, const QString &term, const QChar &separator) const
Sets the name of the search provider, the search term and keyword/term separator in data...
Definition: kurifilter.cpp:511
virtual QString iconName() const
Returns the icon name associated with the search provider when available.
Definition: kurifilter.cpp:108
QUrl adjusted(QUrl::FormattingOptions options) const const
KUriFilterData()
Default constructor.
Definition: kurifilter.cpp:246
int count(const T &value) const const
bool hasArgsAndOptions() const
Checks whether the current data is a local resource with command line options and arguments...
Definition: kurifilter.cpp:301
QString section(QChar sep, int start, int end, QString::SectionFlags flags) const const
QJsonValue value(const QString &key) const const
virtual KCModule * configModule(QWidget *, const char *) const
Creates a configuration module for the filter.
Definition: kurifilter.cpp:475
bool filterSearchUri(KUriFilterData &data)
See filterSearchUri(KUriFilterData&, SearchFilterTypes)
Definition: kurifilter.cpp:628
void setSearchFilteringOptions(SearchFilterOptions options)
Sets the options used by search filter plugins to filter requests.
Definition: kurifilter.cpp:445
static QVector< KPluginMetaData > findPlugins(const QString &directory, std::function< bool(const KPluginMetaData &)> filter=std::function< bool(const KPluginMetaData &)>())
UriTypes uriType() const
Returns the URI type.
Definition: kurifilter.cpp:281
QString iconNameFor(const QUrl &url, KUriFilterData::UriTypes type) const
Returns the icon name for the given url and URI type.
Definition: kurifilter.cpp:528
void setErrorMsg(KUriFilterData &data, const QString &errmsg) const
Sets the error message in data to errormsg.
Definition: kurifilter.cpp:492
QVector::iterator end()
void setCheckForExecutables(bool check)
Check whether the provided uri is executable or not.
Definition: kurifilter.cpp:425
void setUriType(KUriFilterData &data, KUriFilterData::UriTypes type) const
Sets the URI type in data to type.
Definition: kurifilter.cpp:498
KUriFilterData & operator=(const QUrl &url)
Overloaded assignment operator.
Definition: kurifilter.cpp:450
QString typedString() const
The string as typed by the user, before any URL processing is done.
Definition: kurifilter.cpp:311
bool setAbsolutePath(const QString &abs_path)
Sets the absolute path to be used whenever the supplied data is a relative local URL.
Definition: kurifilter.cpp:414
QString defaultUrlScheme() const
Returns the default protocol to use when filtering potentially valid url inputs.
Definition: kurifilter.cpp:384
KIOCORE_EXPORT QString iconNameForUrl(const QUrl &url)
Return the icon name for a URL.
Definition: global.cpp:215
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Tue Sep 29 2020 23:08:34 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.