File indexing completed on 2024-05-05 09:45:37
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 qDebug() << "libs" << libraryPaths; 0078 for (const QString &dir : libraryPaths) { 0079 QDirIterator it(dir + QStringLiteral("/discover"), QDir::Files); 0080 while (it.hasNext()) { 0081 it.next(); 0082 if (QLibrary::isLibrary(it.fileName()) && (allowDummy || it.fileName() != QLatin1String("dummy-backend.so"))) { 0083 pluginNames += it.fileInfo().baseName(); 0084 } 0085 } 0086 } 0087 0088 pluginNames.removeDuplicates(); // will happen when discover is installed twice on the system 0089 return pluginNames; 0090 } 0091 0092 QVector<AbstractResourcesBackend *> DiscoverBackendsFactory::allBackends() const 0093 { 0094 QStringList names = allBackendNames(); 0095 auto ret = kTransform<QVector<AbstractResourcesBackend *>>(names, [this](const QString &name) { 0096 return backend(name); 0097 }); 0098 ret.removeAll(nullptr); 0099 0100 if (ret.isEmpty()) 0101 qCWarning(LIBDISCOVER_LOG) << "Didn't find any Discover backend!"; 0102 return ret; 0103 } 0104 0105 int DiscoverBackendsFactory::backendsCount() const 0106 { 0107 return allBackendNames().count(); 0108 } 0109 0110 void DiscoverBackendsFactory::setupCommandLine(QCommandLineParser *parser) 0111 { 0112 parser->addOption(QCommandLineOption(QStringLiteral("backends"), 0113 i18n("List all the backends we'll want to have loaded, separated by comma ','."), 0114 QStringLiteral("names"))); 0115 } 0116 0117 void DiscoverBackendsFactory::processCommandLine(QCommandLineParser *parser, bool test) 0118 { 0119 if (parser->isSet(QStringLiteral("feedback"))) { 0120 s_isFeedback = true; 0121 s_requestedBackends->clear(); 0122 return; 0123 } 0124 0125 QStringList backends = test // 0126 ? QStringList{QStringLiteral("dummy-backend")} // 0127 : parser->value(QStringLiteral("backends")).split(QLatin1Char(','), Qt::SkipEmptyParts); 0128 for (auto &backend : backends) { 0129 if (!backend.endsWith(QLatin1String("-backend"))) 0130 backend.append(QLatin1String("-backend")); 0131 } 0132 *s_requestedBackends = backends; 0133 }