File indexing completed on 2024-05-05 03:56:26
0001 /* 0002 * SPDX-FileCopyrightText: 2017 by Marco Martin <mart@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "platformpluginfactory.h" 0008 0009 #include <QCoreApplication> 0010 #include <QDebug> 0011 #include <QDir> 0012 #include <QPluginLoader> 0013 #include <QQuickStyle> 0014 0015 #include "kirigamiplatform_logging.h" 0016 0017 namespace Kirigami 0018 { 0019 namespace Platform 0020 { 0021 0022 PlatformPluginFactory::PlatformPluginFactory(QObject *parent) 0023 : QObject(parent) 0024 { 0025 } 0026 0027 PlatformPluginFactory::~PlatformPluginFactory() = default; 0028 0029 PlatformPluginFactory *PlatformPluginFactory::findPlugin(const QString &preferredName) 0030 { 0031 static QHash<QString, PlatformPluginFactory *> factories = QHash<QString, PlatformPluginFactory *>(); 0032 0033 QString pluginName = preferredName.isEmpty() ? QQuickStyle::name() : preferredName; 0034 // check for the plugin only once: it's an heavy operation 0035 if (auto it = factories.constFind(pluginName); it != factories.constEnd()) { 0036 return it.value(); 0037 } 0038 0039 // Even plugins that aren't found are in the map, so we know we shouldn't check again withthis expensive operation 0040 factories[pluginName] = nullptr; 0041 0042 #ifdef KIRIGAMI_BUILD_TYPE_STATIC 0043 for (QObject *staticPlugin : QPluginLoader::staticInstances()) { 0044 PlatformPluginFactory *factory = qobject_cast<PlatformPluginFactory *>(staticPlugin); 0045 if (factory) { 0046 factories[pluginName] = factory; 0047 break; 0048 } 0049 } 0050 #else 0051 const auto libraryPaths = QCoreApplication::libraryPaths(); 0052 for (const QString &path : libraryPaths) { 0053 0054 #ifdef Q_OS_ANDROID 0055 const QDir dir(path); 0056 #else 0057 const QDir dir(path + QStringLiteral("/kf6/kirigami/platform")); 0058 #endif 0059 0060 const auto fileNames = dir.entryList(QDir::Files); 0061 0062 for (const QString &fileName : fileNames) { 0063 0064 #ifdef Q_OS_ANDROID 0065 if (fileName.startsWith(QStringLiteral("libplugins_kf6_kirigami_platform_")) && QLibrary::isLibrary(fileName)) { 0066 #endif 0067 if (!pluginName.isEmpty() && fileName.contains(pluginName)) { 0068 // TODO: env variable too? 0069 QPluginLoader loader(dir.absoluteFilePath(fileName)); 0070 QObject *plugin = loader.instance(); 0071 // TODO: load actually a factory as plugin 0072 0073 qCDebug(KirigamiPlatform) << "Loading style plugin from" << dir.absoluteFilePath(fileName); 0074 0075 if (auto factory = qobject_cast<PlatformPluginFactory *>(plugin)) { 0076 factories[pluginName] = factory; 0077 break; 0078 } 0079 } 0080 #ifdef Q_OS_ANDROID 0081 } 0082 #endif 0083 } 0084 0085 // Ensure we only load the first plugin from the first plugin location. 0086 // If we do not break here, we may end up loading a different plugin 0087 // in place of the first one. 0088 if (factories.value(pluginName) != nullptr) { 0089 break; 0090 } 0091 } 0092 #endif 0093 0094 PlatformPluginFactory *factory = factories.value(pluginName); 0095 0096 if (factory == nullptr) { 0097 qWarning(KirigamiPlatform) << "Failed to find a Kirigami platform plugin for style" << QQuickStyle::name(); 0098 } 0099 0100 return factory; 0101 } 0102 0103 } 0104 } 0105 0106 #include "moc_platformpluginfactory.cpp"