File indexing completed on 2024-04-21 16:12:11
0001 /* 0002 * SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "DiscoverBackendsFactory.h" 0008 #include "libdiscover_debug.h" 0009 #include "resources/AbstractResourcesBackend.h" 0010 #include "resources/ResourcesModel.h" 0011 #include "utils.h" 0012 #include <KConfigGroup> 0013 #include <KDesktopFile> 0014 #include <KLocalizedString> 0015 #include <KSharedConfig> 0016 #include <QCommandLineParser> 0017 #include <QDir> 0018 #include <QDirIterator> 0019 #include <QPluginLoader> 0020 #include <QStandardPaths> 0021 0022 Q_GLOBAL_STATIC(QStringList, s_requestedBackends) 0023 static bool s_isFeedback = false; 0024 0025 void DiscoverBackendsFactory::setRequestedBackends(const QStringList &backends) 0026 { 0027 *s_requestedBackends = backends; 0028 } 0029 0030 bool DiscoverBackendsFactory::hasRequestedBackends() 0031 { 0032 return !s_requestedBackends->isEmpty(); 0033 } 0034 0035 DiscoverBackendsFactory::DiscoverBackendsFactory() 0036 { 0037 } 0038 0039 QVector<AbstractResourcesBackend *> DiscoverBackendsFactory::backend(const QString &name) const 0040 { 0041 if (QDir::isAbsolutePath(name) && QStandardPaths::isTestModeEnabled()) { 0042 return backendForFile(name, QFileInfo(name).fileName()); 0043 } else { 0044 return backendForFile(name, name); 0045 } 0046 } 0047 0048 QVector<AbstractResourcesBackend *> DiscoverBackendsFactory::backendForFile(const QString &libname, const QString &name) const 0049 { 0050 QPluginLoader *loader = new QPluginLoader(QLatin1String("discover/") + libname, QCoreApplication::instance()); 0051 0052 // qCDebug(LIBDISCOVER_LOG) << "trying to load plugin:" << loader->fileName(); 0053 AbstractResourcesBackendFactory *f = qobject_cast<AbstractResourcesBackendFactory *>(loader->instance()); 0054 if (!f) { 0055 qCWarning(LIBDISCOVER_LOG) << "error loading" << libname << loader->errorString() << loader->metaData(); 0056 return {}; 0057 } 0058 auto instances = f->newInstance(QCoreApplication::instance(), name); 0059 if (instances.isEmpty()) { 0060 qCWarning(LIBDISCOVER_LOG) << "Couldn't find the backend: " << libname << "among" << allBackendNames(false, true); 0061 return instances; 0062 } 0063 0064 return instances; 0065 } 0066 0067 QStringList DiscoverBackendsFactory::allBackendNames(bool whitelist, bool allowDummy) const 0068 { 0069 if (whitelist) { 0070 QStringList whitelistNames = *s_requestedBackends; 0071 if (s_isFeedback || !whitelistNames.isEmpty()) 0072 return whitelistNames; 0073 } 0074 0075 QStringList pluginNames; 0076 const auto libraryPaths = QCoreApplication::libraryPaths(); 0077 for (const QString &dir : libraryPaths) { 0078 QDirIterator it(dir + QStringLiteral("/discover"), QDir::Files); 0079 while (it.hasNext()) { 0080 it.next(); 0081 if (QLibrary::isLibrary(it.fileName()) && (allowDummy || it.fileName() != QLatin1String("dummy-backend.so"))) { 0082 pluginNames += it.fileInfo().baseName(); 0083 } 0084 } 0085 } 0086 0087 pluginNames.removeDuplicates(); // will happen when discover is installed twice on the system 0088 return pluginNames; 0089 } 0090 0091 QVector<AbstractResourcesBackend *> DiscoverBackendsFactory::allBackends() const 0092 { 0093 QStringList names = allBackendNames(); 0094 auto ret = kTransform<QVector<AbstractResourcesBackend *>>(names, [this](const QString &name) { 0095 return backend(name); 0096 }); 0097 ret.removeAll(nullptr); 0098 0099 if (ret.isEmpty()) 0100 qCWarning(LIBDISCOVER_LOG) << "Didn't find any Discover backend!"; 0101 return ret; 0102 } 0103 0104 int DiscoverBackendsFactory::backendsCount() const 0105 { 0106 return allBackendNames().count(); 0107 } 0108 0109 void DiscoverBackendsFactory::setupCommandLine(QCommandLineParser *parser) 0110 { 0111 parser->addOption(QCommandLineOption(QStringLiteral("backends"), 0112 i18n("List all the backends we'll want to have loaded, separated by comma ','."), 0113 QStringLiteral("names"))); 0114 } 0115 0116 void DiscoverBackendsFactory::processCommandLine(QCommandLineParser *parser, bool test) 0117 { 0118 if (parser->isSet(QStringLiteral("feedback"))) { 0119 s_isFeedback = true; 0120 s_requestedBackends->clear(); 0121 return; 0122 } 0123 0124 QStringList backends = test // 0125 ? QStringList{QStringLiteral("dummy-backend")} // 0126 : parser->value(QStringLiteral("backends")).split(QLatin1Char(','), Qt::SkipEmptyParts); 0127 for (auto &backend : backends) { 0128 if (!backend.endsWith(QLatin1String("-backend"))) 0129 backend.append(QLatin1String("-backend")); 0130 } 0131 *s_requestedBackends = backends; 0132 }