//pluginManager.cpp #include "pluginManager/include/pluginManager.h" //#include "common/include/pluginCommon/iPlugin.h" #include #include #include #include #include #include // 私有实现 class PluginManager::Private { public: struct PluginInfo { QPluginLoader *loader = nullptr; IPlugin *plugin = nullptr; PluginDescriptor descriptor; QString filePath; ~PluginInfo() { if (plugin) { plugin->shutdown(); } if (loader) { loader->unload(); delete loader; } } }; QMutex mutex; QMap plugins; // pluginId -> PluginInfo* QMap shapeToPlugin; // shapeId -> pluginId QMap shapeDescriptors; // shapeId -> descriptor // 内置形状 QMap> builtinCreators; QMap builtinDescriptors; QStringList pluginDirs; bool loadPluginInternal(const QString &filePath, QString *error = nullptr); void unloadPluginInternal(const QString &pluginId); }; PluginManager::PluginManager(QObject *parent) : QObject(parent) , d(new Private) { // 注册一些内置形状 //registerBuiltinShapes(); } PluginManager::~PluginManager() { QMutexLocker locker(&d->mutex); // 卸载所有插件 auto pluginIds = d->plugins.keys(); for (const QString &pluginId : pluginIds) { d->unloadPluginInternal(pluginId); } } PluginManager* PluginManager::instance() { static PluginManager instance; return &instance; } bool PluginManager::loadPlugin(const QString &filePath) { QMutexLocker locker(&d->mutex); return d->loadPluginInternal(filePath); } bool PluginManager::unloadPlugin(const QString &pluginId) { QMutexLocker locker(&d->mutex); if (!d->plugins.contains(pluginId)) { qWarning() << "Plugin not found:" << pluginId; return false; } d->unloadPluginInternal(pluginId); emit pluginUnloaded(pluginId); emit shapesChanged(); return true; } void PluginManager::loadAllPlugins(const QString &directory) { QDir dir(directory); if (!dir.exists()) { qWarning() << "Plugin directory does not exist:" << directory; return; } QStringList filters; #ifdef Q_OS_WIN filters << "*.dll"; #elif defined(Q_OS_MAC) filters << "*.dylib" << "*.so"; #else filters << "*.so"; #endif QStringList pluginFiles = dir.entryList(filters, QDir::Files); for (const QString &file : pluginFiles) { QString filePath = dir.absoluteFilePath(file); if (!loadPlugin(filePath)) { qWarning() << "Failed to load plugin:" << filePath; } } } bool PluginManager::Private::loadPluginInternal(const QString &filePath, QString *error) { QFileInfo fileInfo(filePath); if (!fileInfo.exists()) { if (error) *error = "File does not exist"; return false; } QPluginLoader *loader = new QPluginLoader(filePath); if (!loader->load()) { if (error) *error = loader->errorString(); delete loader; return false; } QObject *pluginInstance = loader->instance(); if (!pluginInstance) { if (error) *error = "Failed to get plugin instance"; loader->unload(); delete loader; return false; } IPlugin *plugin = qobject_cast(pluginInstance); if (!plugin) { if (error) *error = "Plugin does not implement IPlugin interface"; loader->unload(); delete loader; return false; } if (!plugin->initialize()) { if (error) *error = "Plugin initialization failed"; loader->unload(); delete loader; return false; } PluginDescriptor descriptor = plugin->descriptor(); if (plugins.contains(descriptor.id)) { if (error) *error = "Plugin already loaded: " + descriptor.id; loader->unload(); delete loader; return false; } PluginInfo *info = new PluginInfo; info->loader = loader; info->plugin = plugin; info->descriptor = descriptor; info->filePath = filePath; plugins[descriptor.id] = info; // 注册形状 QList shapes = plugin->shapes(); for (const ShapeDescriptor &shape : shapes) { shapeDescriptors[shape.id] = shape; shapeToPlugin[shape.id] = descriptor.id; } qInfo() << "Plugin loaded:" << descriptor.name << "(" << descriptor.id << ")"; return true; } void PluginManager::Private::unloadPluginInternal(const QString &pluginId) { if (!plugins.contains(pluginId)) { return; } PluginInfo *info = plugins.take(pluginId); if (!info) { return; } // 移除关联的形状 auto shapeIds = shapeToPlugin.keys(); for (const QString &shapeId : shapeIds) { if (shapeToPlugin[shapeId] == pluginId) { shapeDescriptors.remove(shapeId); shapeToPlugin.remove(shapeId); } } delete info; } QStringList PluginManager::availableShapes() const { QMutexLocker locker(&d->mutex); QStringList shapes = d->shapeDescriptors.keys(); shapes.append(d->builtinDescriptors.keys()); return shapes; } bool PluginManager::contains(const QString &shapeId) const { QMutexLocker locker(&d->mutex); return d->shapeDescriptors.contains(shapeId) || d->builtinDescriptors.contains(shapeId); } ShapeDescriptor PluginManager::shapeDescriptor(const QString &shapeId) const { QMutexLocker locker(&d->mutex); if (d->shapeDescriptors.contains(shapeId)) { return d->shapeDescriptors[shapeId]; } if (d->builtinDescriptors.contains(shapeId)) { return d->builtinDescriptors[shapeId]; } return ShapeDescriptor(); } void PluginManager::registerBuiltinShape(const QString &shapeId, const QString &name, std::function creator, const QString &iconPath) { QMutexLocker locker(&d->mutex); ShapeDescriptor desc; desc.id = shapeId; desc.name = name; desc.category = "内置形状"; desc.iconPath = iconPath; d->builtinDescriptors[shapeId] = desc; d->builtinCreators[shapeId] = creator; emit shapesChanged(); } QIcon PluginManager::shapeIcon(const QString &shapeId) const { QMutexLocker locker(&d->mutex); ShapeDescriptor desc = shapeDescriptor(shapeId); if (desc.id.isEmpty()) { return QIcon(); } // 首先尝试从资源文件加载 if (desc.iconPath.startsWith(":/")) { if (QFile::exists(desc.iconPath)) { return QIcon(desc.iconPath); } } // 尝试从文件系统加载 if (QFile::exists(desc.iconPath)) { return QIcon(desc.iconPath); } // 尝试从插件目录查找 if (d->shapeToPlugin.contains(shapeId)) { QString pluginId = d->shapeToPlugin[shapeId]; if (d->plugins.contains(pluginId)) { QString pluginDir = QFileInfo(d->plugins[pluginId]->filePath).absolutePath(); // 尝试相对路径 QString relativePath = pluginDir + "/" + desc.iconPath; if (QFile::exists(relativePath)) { return QIcon(relativePath); } // 尝试在icons子目录中查找 QString iconName = QFileInfo(desc.iconPath).fileName(); QString iconDirPath = pluginDir + "/icons/" + iconName; if (QFile::exists(iconDirPath)) { return QIcon(iconDirPath); } } } // 返回默认图标 return QIcon(":/shapes/default.png"); } void PluginManager::addPluginDirectory(const QString &dir) { QMutexLocker locker(&d->mutex); if (!d->pluginDirs.contains(dir)) { d->pluginDirs.append(dir); } } void PluginManager::setPluginDirectories(const QStringList &dirs) { QMutexLocker locker(&d->mutex); d->pluginDirs = dirs; // 重新扫描所有目录 for (const QString &dir : dirs) { loadAllPlugins(dir); } } QStringList PluginManager::pluginDirectories() const { QMutexLocker locker(&d->mutex); return d->pluginDirs; } ICanvasItem* PluginManager::createItem(const QString &shapeId) { QMutexLocker locker(&d->mutex); // 1. 首先检查内置形状 if (d->builtinCreators.contains(shapeId)) { ICanvasItem *item = d->builtinCreators[shapeId](); if (item) { qDebug() << "Created builtin shape:" << shapeId; return item; } } // 2. 检查插件形状 if (!d->shapeToPlugin.contains(shapeId)) { qWarning() << "Shape not found:" << shapeId; return nullptr; } QString pluginId = d->shapeToPlugin[shapeId]; if (!d->plugins.contains(pluginId)) { qWarning() << "Plugin not loaded for shape:" << shapeId; return nullptr; } // 3. 通过插件创建形状 IPlugin *plugin = d->plugins[pluginId]->plugin; if (!plugin) { qWarning() << "Plugin interface is null for:" << pluginId; return nullptr; } ICanvasItem *item = plugin->createShape(shapeId); if (item) { qDebug() << "Created plugin shape:" << shapeId << "from plugin:" << pluginId; } else { qWarning() << "Plugin failed to create shape:" << shapeId; } return item; } PluginDescriptor PluginManager::pluginDescriptor(const QString &pluginId) const { QMutexLocker locker(&d->mutex); if (d->plugins.contains(pluginId)) { return d->plugins[pluginId]->descriptor; } return PluginDescriptor(); } QStringList PluginManager::loadedPlugins() const { QMutexLocker locker(&d->mutex); return d->plugins.keys(); }