File indexing completed on 2024-04-28 05:26:46
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 } 0103 return ret; 0104 } 0105 0106 int DiscoverBackendsFactory::backendsCount() const 0107 { 0108 return allBackendNames().count(); 0109 } 0110 0111 void DiscoverBackendsFactory::setupCommandLine(QCommandLineParser *parser) 0112 { 0113 parser->addOption(QCommandLineOption(QStringLiteral("backends"), 0114 i18n("List all the backends we'll want to have loaded, separated by comma ','."), 0115 QStringLiteral("names"))); 0116 } 0117 0118 void DiscoverBackendsFactory::processCommandLine(QCommandLineParser *parser, bool test) 0119 { 0120 if (parser->isSet(QStringLiteral("feedback"))) { 0121 s_isFeedback = true; 0122 s_requestedBackends->clear(); 0123 return; 0124 } 0125 0126 QStringList backends = test // 0127 ? QStringList{QStringLiteral("dummy-backend")} // 0128 : parser->value(QStringLiteral("backends")).split(QLatin1Char(','), Qt::SkipEmptyParts); 0129 for (auto &backend : backends) { 0130 if (!backend.endsWith(QLatin1String("-backend"))) { 0131 backend.append(QLatin1String("-backend")); 0132 } 0133 } 0134 *s_requestedBackends = backends; 0135 }