#include "pluginmanager.h" #include "providerregistry.h" #include #include #include #include PluginManager::~PluginManager() { UnloadPlugins(); } void PluginManager::LoadPlugins() { // Get the Plugins directory relative to the executable QString appDir = QCoreApplication::applicationDirPath(); QString pluginsDir = appDir + "/Plugins"; QDir dir(pluginsDir); if (!dir.exists()) { qWarning() << "PluginManager: Plugins directory not found:" << pluginsDir; return; } // Find all DLL files QStringList filters; #ifdef _WIN32 filters << "*.dll"; #elif defined(__APPLE__) filters << "*.dylib"; #else filters << "*.so"; #endif dir.setNameFilters(filters); QFileInfoList files = dir.entryInfoList(QDir::Files); qDebug() << "PluginManager: Scanning for plugins in:" << pluginsDir; qDebug() << "PluginManager: Found" << files.count() << "potential plugin(s)"; for (const QFileInfo& fileInfo : files) { LoadPlugin(fileInfo.absoluteFilePath()); } qDebug() << "PluginManager: Loaded" << m_plugins.count() << "plugin(s)"; } bool PluginManager::LoadPlugin(const QString& path) { QLibrary* library = new QLibrary(path); // Load the library if (!library->load()) { qWarning() << "PluginManager: Failed to load plugin:" << path; qWarning() << "PluginManager: Error" << library->errorString(); delete library; return false; } // Resolve the CreatePlugin function CreatePluginFunc CreateFunc = (CreatePluginFunc)library->resolve("CreatePlugin"); if (!CreateFunc) { qWarning() << "PluginManager: Plugin" << path << "does not export CreatePlugin()"; library->unload(); delete library; return false; } // Create plugin instance IPlugin* plugin = CreateFunc(); if (!plugin) { qWarning() << "PluginManager: CreatePlugin() returned nullptr for" << path; library->unload(); delete library; return false; } qDebug() << "PluginManager: Loaded plugin:" << plugin->Name().c_str() << plugin->Version().c_str() << "by" << plugin->Author().c_str(); // Store plugin entry m_entries.append({library, plugin}); m_plugins.append(plugin); // Auto-register providers in global registry if (plugin->Type() == IPlugin::ProviderPlugin) { IProviderPlugin* provider = static_cast(plugin); QString name = QString::fromStdString(plugin->Name()); QString identifier = name.toLower().replace(" ", ""); ProviderRegistry::instance().registerProvider(name, identifier, provider); } return true; } QVector PluginManager::providerPlugins() const { QVector result; for (IPlugin* plugin : m_plugins) { if (plugin->Type() == IPlugin::ProviderPlugin) { result.append(static_cast(plugin)); } } return result; } IPlugin* PluginManager::FindPlugin(const QString& name) const { for (IPlugin* plugin : m_plugins) { if (QString::fromStdString(plugin->Name()) == name) { return plugin; } } return nullptr; } bool PluginManager::LoadPluginFromPath(const QString& path) { // Check if already loaded QFileInfo fileInfo(path); QString fileName = fileInfo.fileName(); for (const auto& entry : m_entries) { if (entry.library->fileName().endsWith(fileName)) { qWarning() << "PluginManager: Plugin already loaded:" << fileName; return false; } } return LoadPlugin(path); } bool PluginManager::UnloadPlugin(const QString& name) { for (int i = 0; i < m_entries.size(); ++i) { if (QString::fromStdString(m_entries[i].plugin->Name()) == name) { qDebug() << "PluginManager: Unloading plugin:" << name; IPlugin* plugin = m_entries[i].plugin; // Unregister provider from global registry if (plugin->Type() == IPlugin::ProviderPlugin) { QString identifier = name.toLower().replace(" ", ""); ProviderRegistry::instance().unregisterProvider(identifier); } // Delete plugin instance delete plugin; // Unload library m_entries[i].library->unload(); delete m_entries[i].library; // Remove from lists m_entries.remove(i); m_plugins.remove(i); return true; } } qWarning() << "PluginManager: Plugin not found:" << name; return false; } void PluginManager::UnloadPlugins() { // Clear provider registry ProviderRegistry::instance().clear(); // Delete plugin instances and unload libraries for (int i = 0; i < m_entries.size(); ++i) { delete m_entries[i].plugin; m_entries[i].library->unload(); delete m_entries[i].library; } m_entries.clear(); m_plugins.clear(); }