diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ebe843..2b07ad1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,7 +75,6 @@ set(H_HEADER_FILES common/include/pluginCommon/iCanvasItem.h common/include/pluginCommon/iPlugin.h common/include/pluginCommon/iShapeFactory.h - common/include/pluginCommon/iPluginAdapter.h common/core_model/types.h common/core_model/topology.h @@ -113,6 +112,8 @@ set(CPP_SOURCE_FILES common/source/extraPropertyManager.cpp common/core_model/types.cpp + + common/source/iPlugin.cpp ) set(UI_FILES ui/mainwindow.ui @@ -193,3 +194,4 @@ target_link_libraries(DiagramDesigner PRIVATE diagramCavas diagramUtils diagramC file(COPY setting.xml DESTINATION "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin") +add_subdirectory(customTypePlugin) diff --git a/common/frontend/monitor_item.h b/common/frontend/monitor_item.h index 6ac17f2..90d7ba1 100644 --- a/common/frontend/monitor_item.h +++ b/common/frontend/monitor_item.h @@ -286,4 +286,12 @@ struct MonitorItemDisplayInfo //监控模式显示信息 sModel = json["sModel"].toString(); } }; + +struct PluginTypeInfo //插件的类型信息 +{ + QString shapeName; //插件中的类型名 + int baseType; //基础类型 + QString modelName; //工程模名 +}; + #endif diff --git a/common/include/pluginCommon/iCanvasItem.h b/common/include/pluginCommon/iCanvasItem.h index d1342f1..1f47b46 100644 --- a/common/include/pluginCommon/iCanvasItem.h +++ b/common/include/pluginCommon/iCanvasItem.h @@ -14,6 +14,8 @@ public: // 基本信息 virtual QString typeId() const = 0; virtual QString displayName() const = 0; + virtual int baseType() const = 0; //基础分类 + virtual bool containSvg() const = 0; // 几何属性 virtual QRectF bounds() const = 0; @@ -23,7 +25,7 @@ public: virtual void draw(QPainter *painter, const QRectF &rect) = 0; // 属性管理 - virtual QVariant property(const QString &key) const = 0; + virtual QVariant getProperty(const QString &key) const = 0; virtual void setProperty(const QString &key, const QVariant &value) = 0; signals: diff --git a/common/include/pluginCommon/iPlugin.h b/common/include/pluginCommon/iPlugin.h index 9b65d3c..99f8fe6 100644 --- a/common/include/pluginCommon/iPlugin.h +++ b/common/include/pluginCommon/iPlugin.h @@ -4,18 +4,19 @@ #include #include #include "iCanvasItem.h" +//#include "export.hpp" // 形状描述 struct ShapeDescriptor { QString id; // 形状标识符 QString name; // 显示名称 - QString category; // 分类 + int category; // 分类(基础类型) QString iconPath; // 图标路径 QVariantMap defaults; // 默认属性 }; // 插件描述 -struct PluginDescriptor { +struct PluginDescriptor { QString id; // 插件ID QString name; // 插件名称 QString version; // 版本 @@ -48,4 +49,4 @@ public: virtual QIcon shapeIcon(const QString &shapeId) const = 0; }; -Q_DECLARE_INTERFACE(IPlugin, "com.canvas.plugin/1.0") +Q_DECLARE_INTERFACE(IPlugin, "com.diagramDesigner.plugin/1.0") diff --git a/common/source/iPlugin.cpp b/common/source/iPlugin.cpp new file mode 100644 index 0000000..5cbf7d8 --- /dev/null +++ b/common/source/iPlugin.cpp @@ -0,0 +1 @@ +#include "pluginCommon/iPlugin.h" diff --git a/customTypePlugin/CMakeLists.txt b/customTypePlugin/CMakeLists.txt new file mode 100644 index 0000000..8ed343a --- /dev/null +++ b/customTypePlugin/CMakeLists.txt @@ -0,0 +1,59 @@ +project(customTypePlugin) + +set(CUSTOMTYPEPLUGIN_HEADER_FILES + + include/customTypePlugin.h + include/reactorItem.h + ../common/include/compiler.hpp + ../common/include/export.hpp + ../common/include/operatingSystem.hpp + + ../common/include/pluginCommon/iPlugin.h + ../common/include/pluginCommon/iCanvasItem.h +) + +set(CUSTOMTYPEPLUGIN_SOURCE_FILES + source/customTypePlugin.cpp + source/reactorItem.cpp +) + + +if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) + qt_add_library(customTypePlugin SHARED + MANUAL_FINALIZATION + ${CUSTOMTYPEPLUGIN_HEADER_FILES} + ${CUSTOMTYPEPLUGIN_SOURCE_FILES} + ) +else() + add_library(customTypePlugin SHARED + ${CUSTOMTYPEPLUGIN_HEADER_FILES} + ${CUSTOMTYPEPLUGIN_SOURCE_FILES} + ) +endif() + +target_link_libraries(customTypePlugin PUBLIC Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Gui + Qt${QT_VERSION_MAJOR}::Widgets) + +target_link_libraries(customTypePlugin PRIVATE Qt6::Xml) +target_link_libraries(customTypePlugin PRIVATE Qt6::Network) +#target_link_libraries(customTypePlugin PRIVATE Qt6::Sql ${PostgreSQL_LIBRARIES}) + +option(BUILD_SHARED_LIBS "Build as shared library" ON) + + + +target_include_directories(customTypePlugin PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) + +target_compile_definitions(customTypePlugin + PUBLIC + DIAGRAM_DESIGNER_SHARED + PRIVATE + DIAGRAM_DESIGNER_EXPORTS + QT_PLUGIN +) + +set_target_properties(customTypePlugin PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin/plugins" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin/plugins" +) diff --git a/customTypePlugin/include/customType.json b/customTypePlugin/include/customType.json new file mode 100644 index 0000000..de6c302 --- /dev/null +++ b/customTypePlugin/include/customType.json @@ -0,0 +1,10 @@ +{ + "pluginId": "com.diagramDesigner.plugin/1.0", + "name": "电抗器插件", + "version": "1.0.0", + "author": "by", + "description": "自定义电抗器类型", + "license": "MIT", + "minApiVersion": "1.0.0", + "dependencies": [] +} diff --git a/customTypePlugin/include/customTypePlugin.h b/customTypePlugin/include/customTypePlugin.h new file mode 100644 index 0000000..502f7d6 --- /dev/null +++ b/customTypePlugin/include/customTypePlugin.h @@ -0,0 +1,32 @@ +// customTypePlugin.h +#pragma once + +#include "pluginCommon/iPlugin.h" +#include "reactorItem.h" +#include "export.hpp" +#include + +class DIAGRAM_DESIGNER_PUBLIC CustomTypePlugin : public IPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "com.diagramDesigner.plugin/1.0" FILE "customType.json") + Q_INTERFACES(IPlugin) + +public: + explicit CustomTypePlugin(QObject *parent = nullptr); + virtual ~CustomTypePlugin(); + + // IPlugin接口实现 + PluginDescriptor descriptor() const override; + QList shapes() const override; + ICanvasItem* createShape(const QString &shapeId) override; + bool initialize() override; + void shutdown() override; + QIcon shapeIcon(const QString &shapeId) const override; + +private: + QIcon m_reactorIcon; + + QIcon loadIcon(const QString &path) const; + QIcon createDefaultIcon() const; +}; diff --git a/customTypePlugin/include/reactorItem.h b/customTypePlugin/include/reactorItem.h new file mode 100644 index 0000000..df2e3d8 --- /dev/null +++ b/customTypePlugin/include/reactorItem.h @@ -0,0 +1,34 @@ +// reactorItem.h +#pragma once + +#include "pluginCommon/iCanvasItem.h" +#include + +class ReactorItem : public ICanvasItem +{ + Q_OBJECT + +public: + explicit ReactorItem(QObject *parent = nullptr); + + // ICanvasItem接口 + QString typeId() const override { return "reactor"; } + QString displayName() const override { return "电抗器"; } + int baseType() const override {return 18;} + bool containSvg() const override {return true;} + + QRectF bounds() const override; + void setBounds(const QRectF &rect) override; + + void draw(QPainter *painter, const QRectF &rect) override; + + QVariant getProperty(const QString &key) const override; + void setProperty(const QString &key, const QVariant &value) override; + +private: + QRectF m_bounds = QRectF(-30, -30, 60, 60); + QColor m_fillColor = QColor(100, 150, 255, 200); + QColor m_borderColor = Qt::black; + int m_borderWidth = 2; + int m_cornerRadius = 0; +}; diff --git a/customTypePlugin/source/customTypePlugin.cpp b/customTypePlugin/source/customTypePlugin.cpp new file mode 100644 index 0000000..6a530a9 --- /dev/null +++ b/customTypePlugin/source/customTypePlugin.cpp @@ -0,0 +1,145 @@ +// customTypePlugin.cpp +#include "customTypePlugin/include/customTypePlugin.h" +#include "customTypePlugin/include/reactorItem.h" +#include +#include +#include +#include +#include + + +CustomTypePlugin::CustomTypePlugin(QObject *parent) + : IPlugin(parent) +{ + qDebug() << "CustomTypePlugin constructor"; +} + +CustomTypePlugin::~CustomTypePlugin() +{ + qDebug() << "CustomTypePlugin destructor"; +} + +PluginDescriptor CustomTypePlugin::descriptor() const +{ + PluginDescriptor desc; + desc.id = "com.diagramDesigner.plugin.customType"; + desc.name = "自定义类型"; + desc.version = "1.0.0"; + desc.author = "by"; + desc.description = "自定义类型插件"; + return desc; +} + +QList CustomTypePlugin::shapes() const +{ + ShapeDescriptor reactor; + reactor.id = "reactor"; + reactor.name = "电抗器"; + reactor.category = 18; //电抗器临时定为18 + reactor.iconPath = ":/rectangle/rectangle.png"; + reactor.defaults = { + {"width", 100.0}, + {"height", 60.0}, + {"fillColor", QColor(100, 150, 255, 180)}, + {"borderColor", QColor(0, 0, 0, 200)}, + {"borderWidth", 2.0}, + {"cornerRadius", 0.0} + }; + + return {reactor}; +} + +ICanvasItem* CustomTypePlugin::createShape(const QString &shapeId) +{ + if (shapeId == "reactor") { + ReactorItem *item = new ReactorItem; + + // 应用默认属性 + ShapeDescriptor desc = shapes().first(); // 电抗器描述 + for (auto it = desc.defaults.begin(); it != desc.defaults.end(); ++it) { + item->setProperty(it.key(), it.value()); + } + + return item; + } + + qWarning() << "Unknown shape ID:" << shapeId; + return nullptr; +} + +bool CustomTypePlugin::initialize() +{ + qDebug() << "Rectangle plugin initializing..."; + + // 每个实例加载自己的图标 + m_reactorIcon = loadIcon(":/rectangle/rectangle.png"); + + // 如果资源中没有,创建默认图标 + if (m_reactorIcon.isNull()) { + m_reactorIcon = createDefaultIcon(); + } + + qDebug() << "Rectangle plugin initialized successfully"; + return true; +} + +void CustomTypePlugin::shutdown() +{ + qDebug() << "Rectangle plugin shutting down..."; + + // 清理资源 + m_reactorIcon = QIcon(); + + qDebug() << "Rectangle plugin shutdown complete"; +} + +QIcon CustomTypePlugin::shapeIcon(const QString &shapeId) const +{ + QString iconPath; + + if (shapeId == "reactor") { + iconPath = ":/custom/reactor.png"; + } else { + return QIcon(); + } + + // 尝试加载图标 + QIcon icon = loadIcon(iconPath); + if (!icon.isNull()) { + return icon; + } + + return createDefaultIcon(); +} + +QIcon CustomTypePlugin::loadIcon(const QString &path) const +{ + if (QFile::exists(path)) { + return QIcon(path); + } + return QIcon(); +} + +QIcon CustomTypePlugin::createDefaultIcon() const +{ + QPixmap pixmap(32, 32); + pixmap.fill(Qt::transparent); + + QPainter painter(&pixmap); + painter.setRenderHint(QPainter::Antialiasing, true); + + // 绘制背景 + painter.setBrush(QBrush(QColor(240, 240, 240))); + painter.setPen(Qt::NoPen); + painter.drawRoundedRect(1, 1, 30, 30, 4, 4); + + // 绘制矩形 + QRectF rect(6, 6, 20, 20); + + painter.setBrush(QBrush(QColor(100, 150, 255, 180))); + painter.setPen(QPen(QColor(0, 0, 0, 200), 1.5)); + + painter.drawRect(rect); + + return QIcon(pixmap); +} diff --git a/customTypePlugin/source/reactorItem.cpp b/customTypePlugin/source/reactorItem.cpp new file mode 100644 index 0000000..0adf629 --- /dev/null +++ b/customTypePlugin/source/reactorItem.cpp @@ -0,0 +1,150 @@ +// plugins/rectangle/RectangleItem.cpp +#include "customTypePlugin/include/reactorItem.h" +#include +#include + +ReactorItem::ReactorItem(QObject *parent) +{ +} + +QRectF ReactorItem::bounds() const +{ + return m_bounds; +} + +void ReactorItem::setBounds(const QRectF &rect) +{ + if (m_bounds != rect && rect.isValid()) { + m_bounds = rect; + emit boundsChanged(rect); + } +} + +void ReactorItem::draw(QPainter *painter, const QRectF &rect) +{ + if (!painter) return; + + painter->save(); + painter->setRenderHint(QPainter::Antialiasing, true); + + // 创建画笔 + QPen pen; + if (m_borderWidth > 0) { + pen.setColor(m_borderColor); + pen.setWidthF(m_borderWidth); + pen.setStyle(Qt::SolidLine); + } else { + pen.setStyle(Qt::NoPen); + } + + // 创建画刷 + QBrush brush(m_fillColor); + + painter->setPen(pen); + painter->setBrush(brush); + + // 绘制矩形 + if (m_cornerRadius > 0) { + painter->drawRoundedRect(rect, m_cornerRadius, m_cornerRadius); + } else { + painter->drawRect(rect); + } + + // 绘制尺寸标签(可选) + if (rect.width() > 40 && rect.height() > 30) { + painter->save(); + painter->setPen(Qt::darkGray); + QFont font = painter->font(); + font.setPointSize(8); + painter->setFont(font); + + QString sizeText = QString("%1×%2").arg(rect.width()).arg(rect.height()); + painter->drawText(rect.adjusted(2, 2, -2, -2), + Qt::AlignLeft | Qt::AlignTop, + sizeText); + painter->restore(); + } + + painter->restore(); +} + +QVariant ReactorItem::getProperty(const QString &key) const +{ + if (key == "width") return m_bounds.width(); + if (key == "height") return m_bounds.height(); + if (key == "x") return m_bounds.x(); + if (key == "y") return m_bounds.y(); + if (key == "fillColor") return m_fillColor; + if (key == "borderColor") return m_borderColor; + if (key == "borderWidth") return m_borderWidth; + if (key == "cornerRadius") return m_cornerRadius; + + return QVariant(); +} + +void ReactorItem::setProperty(const QString &key, const QVariant &value) +{ + bool geometryChanged = false; + QRectF newBounds = m_bounds; + + if (key == "width" && value.canConvert()) { + double w = value.toDouble(); + if (w > 0 && w != newBounds.width()) { + newBounds.setWidth(w); + geometryChanged = true; + } + } + else if (key == "height" && value.canConvert()) { + double h = value.toDouble(); + if (h > 0 && h != newBounds.height()) { + newBounds.setHeight(h); + geometryChanged = true; + } + } + else if (key == "x" && value.canConvert()) { + double x = value.toDouble(); + if (x != newBounds.x()) { + newBounds.moveLeft(x); + geometryChanged = true; + } + } + else if (key == "y" && value.canConvert()) { + double y = value.toDouble(); + if (y != newBounds.y()) { + newBounds.moveTop(y); + geometryChanged = true; + } + } + else if (key == "fillColor" && value.canConvert()) { + QColor color = value.value(); + if (color != m_fillColor) { + m_fillColor = color; + emit propertyChanged(key, value); + } + } + else if (key == "borderColor" && value.canConvert()) { + QColor color = value.value(); + if (color != m_borderColor) { + m_borderColor = color; + emit propertyChanged(key, value); + } + } + else if (key == "borderWidth" && value.canConvert()) { + double width = value.toDouble(); + if (width >= 0 && width != m_borderWidth) { + m_borderWidth = width; + emit propertyChanged(key, value); + } + } + else if (key == "cornerRadius" && value.canConvert()) { + double radius = value.toDouble(); + if (radius >= 0 && radius != m_cornerRadius) { + m_cornerRadius = radius; + emit propertyChanged(key, value); + } + } + + if (geometryChanged && newBounds.isValid()) { + m_bounds = newBounds; + } +} diff --git a/diagramCavas/CMakeLists.txt b/diagramCavas/CMakeLists.txt index 5a751b6..a76e4b4 100644 --- a/diagramCavas/CMakeLists.txt +++ b/diagramCavas/CMakeLists.txt @@ -64,6 +64,7 @@ set(DIAGRAMCAVAS_HEADER_FILES include/graphicsItem/pluginItemFactory.h include/graphicsItem/pluginItemWrapper.h + include/graphicsItem/pluginSvgItemWrapper.h include/graphicsItem/functionModelItem/electricFunctionModelConnectLineItem.h include/graphicsItem/functionModelItem/electricFunctionModelPortItem.h @@ -193,6 +194,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES source/graphicsItem/pluginItemFactory.cpp source/graphicsItem/pluginItemWrapper.cpp + source/graphicsItem/pluginSvgItemWrapper.cpp source/graphicsItem/functionModelItem/electricFunctionModelConnectLineItem.cpp source/graphicsItem/functionModelItem/electricFunctionModelPortItem.cpp diff --git a/diagramCavas/include/diagramCavas.h b/diagramCavas/include/diagramCavas.h index 582b577..a08d335 100644 --- a/diagramCavas/include/diagramCavas.h +++ b/diagramCavas/include/diagramCavas.h @@ -7,6 +7,7 @@ #include "common/core_model/topology.h" #include "common/core_model/types.h" #include "common/core_model/diagram.h" +#include "common/frontend/monitor_item.h" #include "export.hpp" QT_BEGIN_NAMESPACE @@ -27,6 +28,8 @@ class StructDataPreviewDlg; class ExtraPropertyManager; class DataSourceDlg; class CreateHMIdlg; +class PluginManager; +class PluginItemFactory; class DIAGRAM_DESIGNER_PUBLIC DiagramCavas : public QMdiArea { @@ -43,6 +46,7 @@ public: void passRecommmandHttpData(HttpRecommandInfo); //传递推荐列表数据 DiagramConnectSetting* getConnectSettingDlg() {return _connectSetting;} ExtraPropertyManager* getExtraPropertyManager() {return _extraPropertyManager;} + QMap getPluginShapeInfo() {return m_pluginInfo;} public: void initial(); signals: @@ -115,6 +119,9 @@ protected: private: void removePanel(PowerEntity*); void calculateLauncherVisible(); + + bool loadPluginConfig(const QString&); //载入插件配置文件 + bool parsePluginConfig(const QJsonObject& root); //解析插件配置文件 private: QMap> m_mapMonitorPanel; //监控时panel int _pageIndex; @@ -126,6 +133,10 @@ private: StructDataPreviewDlg* _structDataPreviewDlg; ExtraPropertyManager* _extraPropertyManager; CreateHMIdlg* _createHMIDlg; + + PluginManager* m_pluginManager; //插件管理类 + PluginItemFactory* m_itemFactory; //插件图元工厂类 + QMap m_pluginInfo; //插件对照信息 }; #endif diff --git a/diagramCavas/include/graphicsDataModel/fixedPortsModel.h b/diagramCavas/include/graphicsDataModel/fixedPortsModel.h index 8690854..460aa92 100644 --- a/diagramCavas/include/graphicsDataModel/fixedPortsModel.h +++ b/diagramCavas/include/graphicsDataModel/fixedPortsModel.h @@ -128,6 +128,8 @@ public: int customImageRefExist(QUuid uid,QByteArray hash256); void updateHMIRef(QUuid hmiId,QString model,QByteArray hash256,int slot); //更新img引用 void updateHMICustomRef(QUuid hmiId,QString model,QUuid itemId,QByteArray hash256); //更新customImg引用 + + void updatePannelProperty(); //更新界面的属性信息 /************************数据显示*************************/ void setCurItemPropertyDlg(ItemPropertyDlg* p) {m_curPropertyDlg = p;} ItemPropertyDlg* getCurItemPropertyDlg() {return m_curPropertyDlg;} diff --git a/diagramCavas/include/graphicsItem/functionModelItem/electricFunctionModelSvgItem.h b/diagramCavas/include/graphicsItem/functionModelItem/electricFunctionModelSvgItem.h index 1ccd4f9..83ae1cc 100644 --- a/diagramCavas/include/graphicsItem/functionModelItem/electricFunctionModelSvgItem.h +++ b/diagramCavas/include/graphicsItem/functionModelItem/electricFunctionModelSvgItem.h @@ -9,9 +9,8 @@ class ElectricFunctionModelSvgItem :public GraphicsFunctionModelItem public: Q_PROPERTY(QFileInfo Image READ getImage_1 WRITE setImage_1) public: - ElectricFunctionModelSvgItem(const QRect &rect, bool genNewPort = true,QGraphicsItem *parent = 0); //genNewPort生成新接线点 + ElectricFunctionModelSvgItem(const QRect &rect,QGraphicsItem *parent = 0); virtual ~ElectricFunctionModelSvgItem(); - void resize(int,double, double, const QPointF&) override; void updateCoordinate() override; void move(const QPointF&) override; virtual void loadSvg(){}; diff --git a/diagramCavas/include/graphicsItem/pluginSvgItemWrapper.h b/diagramCavas/include/graphicsItem/pluginSvgItemWrapper.h new file mode 100644 index 0000000..fb61bd9 --- /dev/null +++ b/diagramCavas/include/graphicsItem/pluginSvgItemWrapper.h @@ -0,0 +1,53 @@ +//pluginSvgItemWrapper.h +#pragma once + +#include "functionModelItem/electricFunctionModelSvgItem.h" +#include "pluginCommon/iCanvasItem.h" +#include + +// 内部包装器,不暴露给外部 +class PluginSvgItemWrapper : public ElectricFunctionModelSvgItem +{ + Q_OBJECT + +public: + explicit PluginSvgItemWrapper(ICanvasItem *pluginItem, QGraphicsItem *parent = nullptr); + virtual ~PluginSvgItemWrapper(); + + virtual void setImage_1(QFileInfo) override; + // 克隆 + virtual ElectricFunctionModelSvgItem* clone() const override; + + // 绘图 + virtual void paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget = nullptr) override; + + virtual QRectF boundingRect() const override; + virtual QPainterPath shape() const override; + + // 几何操作 + virtual void updateCoordinate() override; + virtual void resize(int handle, double dx, double dy, const QPointF &pos) override; + virtual void move(const QPointF &delta) override; + + // 获取插件项 + ICanvasItem* pluginItem() const; + +protected: + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + +private: + ICanvasItem *m_pluginItem = nullptr; + QRectF m_cachedBounds; + + void updateCache(); + void connectSignals(); + QVariantMap saveState() const; + bool loadStateIntoPluginItem(ICanvasItem *pluginItem, const QVariantMap &state) const; + void copyPropertiesFrom(const PluginSvgItemWrapper *source); + +private slots: + void onPluginBoundsChanged(const QRectF &newBounds); + void onPluginPropertyChanged(const QString &key, const QVariant &value); +}; diff --git a/diagramCavas/source/diagramCavas.cpp b/diagramCavas/source/diagramCavas.cpp index 172b4cf..577c2bb 100644 --- a/diagramCavas/source/diagramCavas.cpp +++ b/diagramCavas/source/diagramCavas.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "monitorPanel.h" #include "diagramCavas.h" #include "dataBase.h" @@ -23,11 +24,15 @@ #include "structDataPreviewDlg.h" #include "extraPropertyManager.h" #include "createHMIdlg.h" +#include "pluginManager.h" +#include "graphicsItem/pluginItemFactory.h" #include "QQuickDetailsViewMananger.h" #include "propertyType/propertyTypeCustomization_DataSourceType.h" #include "propertyType/dataSourceType.h" +#include "basePannelPropertyProxy.h" + DiagramCavas::DiagramCavas(QWidget *parent) : QMdiArea(parent) ,_cornerButton(nullptr) @@ -37,6 +42,8 @@ DiagramCavas::DiagramCavas(QWidget *parent) ,_structDataPreviewDlg(nullptr) ,_extraPropertyManager(nullptr) ,_createHMIDlg(nullptr) + ,m_pluginManager(nullptr) + ,m_itemFactory(nullptr) { _pageIndex = 0; } @@ -155,6 +162,17 @@ void DiagramCavas::initial() _createHMIDlg = new CreateHMIdlg(this); connect(_createHMIDlg,&CreateHMIdlg::createHMI,this,&DiagramCavas::onSignal_createHMIClicked); updateHMIlstFromDB(); + + loadPluginConfig(QCoreApplication::applicationDirPath()+"/pluginConfig.json"); //加载plugin关联信息 + + m_pluginManager = PluginManager::instance(); + //创建Canvas项工厂 + m_itemFactory = PluginItemFactory::instance(); + m_itemFactory->setPluginManager(m_pluginManager); + //加载插件 + QString pluginsDir = QApplication::applicationDirPath() + "/plugins"; + m_pluginManager->addPluginDirectory(pluginsDir); + m_pluginManager->loadAllPlugins(pluginsDir); } void DiagramCavas::onSignal_addDrawingPanel(PowerEntity* pItem,DiagramMode mode,QString parent) @@ -257,6 +275,7 @@ void DiagramCavas::onSignal_loadMonitor(PowerEntity* p) { m_mapMonitorPanel[p->name()].first->show(); } + onTargetSelected(m_mapMonitorPanel[p->name()].first->getPropertyProxy()); } void DiagramCavas::runPage(const QString sName) @@ -477,6 +496,51 @@ void DiagramCavas::calculateLauncherVisible() } } +bool DiagramCavas::loadPluginConfig(const QString& configPath) +{ + QFile file(configPath); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Cannot open config file:" << configPath; + return false; + } + + QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + if (doc.isNull() || !doc.isObject()) { + qWarning() << "Invalid JSON config"; + return false; + } + + return parsePluginConfig(doc.object()); +} + +bool DiagramCavas::parsePluginConfig(const QJsonObject& root) +{ + if (!root.contains("shapes")) { + qWarning() << "Missing 'shapes' key"; + return false; + } + + QJsonArray items = root["shapes"].toArray(); + + for (const QJsonValue& itemVal : items) { + QJsonObject itemObj = itemVal.toObject(); + + int type = itemObj["type"].toInt(); + QString shapeName = itemObj["shapeName"].toString(); + QString modelName = itemObj["modelName"].toString(); + + // 解析枚举类型 + PluginTypeInfo info; + info.baseType = type; + info.shapeName = shapeName; + info.modelName = modelName; + m_pluginInfo[shapeName] = info; + } + + qDebug() << "Loaded" << m_pluginInfo.size() << "shapes types from config"; + return true; +} + void DiagramCavas::resizeEvent(QResizeEvent* event) { if(_cornerButton) @@ -527,6 +591,7 @@ void DiagramCavas::onSignal_createHMIClicked(QString sHMI,QString sStructPage,in QJsonObject context = DataBase::GetInstance()->getMonitorContextByTag(sStructPage); m_mapMonitorPanel[sHMI].first->loadNodes(context); //加载系统图结构 onSignal_createHMI(sHMI,id); + onTargetSelected(m_mapMonitorPanel[sHMI].first->getPropertyProxy()); } void DiagramCavas::onSignal_updateCurItems(QList lst,bool refresh) diff --git a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp index 7a335a6..8e6810c 100644 --- a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp +++ b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp @@ -22,6 +22,9 @@ #include "graphicsItem/functionModelItem/electricFunctionModelSvgItemImage.h" #include "graphicsItem/functionModelItem/electricFunctionModelItemText.h" +#include "pluginManager.h" +#include "graphicsItem/pluginItemFactory.h" + #include "graphicsItem/itemPort.h" #include "designerScene.h" #include "dataBase.h" @@ -261,8 +264,9 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he pro = mapData.value(id); if(pro) { - int type = pro->graphicsType(); - if(type == GIT_link) //连线对象外部处理 + int type = pro->type(); + //int type = pro->graphicsType(); + if(type == 8) //GIT_link 电缆对象外部处理 return QString("err"); QString sMeta = pro->metaModelName(); QString sProModel = pro->modelName(); @@ -276,7 +280,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he double dX = 0.0; double dY = 0.0; - if(type == GIT_itemRect) + if(type == 3) //GIT_itemRect断路器 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -303,7 +307,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he QJsonArray portArr = pro->context()["port"].toArray(); addPortsToItem_json(P_const,portArr,item); } - else if(type == GIT_node) + else if(type == 0) //GIT_node 节点(暂定为0) { auto pNode = new ElectricFunctionModelPortItem(); pNode->setItemType(GIT_node); @@ -312,7 +316,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he QJsonArray portArr = pro->context()["port"].toArray(); addPortsToItem_json(p_movable,portArr,item); } - else if(type == GIT_bus) + else if(type == 1) //GIT_bus 母线 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -340,7 +344,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he QJsonArray portArr = pro->context()["port"].toArray(); addPortsToItem_json(p_movable,portArr,item); } - else if(type == GIT_ctGroup) + else if(type == 4) //GIT_ctGroup ct组 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -393,7 +397,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he } } - else if(type == GIT_ptGroup) + else if(type == 5) //GIT_ptGroup pt组 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -447,7 +451,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he } } } - else if(type == GIT_DS) + else if(type == 9) //GIT_DS 隔离开关 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -475,7 +479,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } - else if(type == GIT_ES) + else if(type == 6) //GIT_ES 接地开关 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -503,7 +507,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } - else if(type == GIT_FES) + else if(type == 7) //GIT_FES 快速接地开关 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -531,7 +535,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } - else if(type == GIT_DTEDS) + else if(type == 10) //GIT_DTEDS 双掷接地隔离开关 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -559,7 +563,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } - else if(type == GIT_PI) + else if(type == 11) //GIT_PI 带点指示器 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -587,7 +591,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } - else if(type == GIT_LA) + else if(type == 12) //GIT_LA 避雷器 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -615,7 +619,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } - else if(type == GIT_cableTer) + else if(type == 13) //GIT_cableTer 电缆出线套筒 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -643,7 +647,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } - else if(type == GIT_cableEnd) + else if(type == 14) //GIT_cableEnd 电缆端 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -671,7 +675,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } - else if(type == GIT_2wTransformer) + else if(type == 15) //GIT_2wTransformer 两绕组变压器 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -699,7 +703,7 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } - else if(type == GIT_3wTransformer) + else if(type == 16) //GIT_3wTransformer 三绕组变压器 { PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; QByteArray svg; @@ -727,6 +731,30 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } + else{ //其他基础类型,自定义 + bool shapeExist = false; + PluginTypeInfo shapeInfo; //类型对照关系 + auto mapPluginShapes = _cavas->getPluginShapeInfo(); + for(auto& info:mapPluginShapes){ + if(info.baseType == type){ + shapeExist = true; + shapeInfo = info; + break; + } + } + if(shapeExist){ + QStringList shapes = PluginManager::instance()->availableShapes(); + if(shapes.contains(shapeInfo.shapeName)){ //实际插件中存在该类型 + auto pluginItem = PluginItemFactory::instance()->createItem(shapeInfo.shapeName); + if(pluginItem){ + item = pluginItem; + QJsonArray portArr = pro->context()["port"].toArray(); + addPortsToItem_json(P_const,portArr,item); + } + } + } + } + if(item) { item->setItemId(id); @@ -2569,3 +2597,8 @@ void FixedPortsModel::updateHMICustomRef(QUuid hmiId,QString model,QUuid itemId, _HMICustomImageRef.append(ref); } } + +void FixedPortsModel::updatePannelProperty() +{ + _cavas->onTargetSelected(_widget->getPropertyProxy()); +} diff --git a/diagramCavas/source/graphicsItem/functionModelItem/electricFunctionModelSvgItem.cpp b/diagramCavas/source/graphicsItem/functionModelItem/electricFunctionModelSvgItem.cpp index 06ca625..d6d0f9c 100644 --- a/diagramCavas/source/graphicsItem/functionModelItem/electricFunctionModelSvgItem.cpp +++ b/diagramCavas/source/graphicsItem/functionModelItem/electricFunctionModelSvgItem.cpp @@ -5,7 +5,7 @@ #include #include -ElectricFunctionModelSvgItem::ElectricFunctionModelSvgItem(const QRect &rect, bool autoGenPort,QGraphicsItem *parent) +ElectricFunctionModelSvgItem::ElectricFunctionModelSvgItem(const QRect &rect,QGraphicsItem *parent) : GraphicsFunctionModelItem(parent),m_pRender(nullptr),m_pCustomRender(nullptr) { m_lastBoudingRect = rect; @@ -114,35 +114,6 @@ void ElectricFunctionModelSvgItem::paint(QPainter* painter, const QStyleOptionGr } } -void ElectricFunctionModelSvgItem::resize(int nHandle,double dSX, double dSY, const QPointF& basePoint) -{ - switch (nHandle) - { - case H_left: - case H_right: - dSY = 1; //拖拽的是左点右点,为水平缩放,忽略垂直变化 - break; - case H_top: - case H_bottom: - dSX = 1; //拖拽的是顶点底点,为垂直缩放,忽略水平变化 - break; - default: - break; - } - - QTransform trans; - //缩放是以图元原点(中心)位置为基准,所以每帧都先移动移动到想要的基准点,缩放之后再移回 - trans.translate(basePoint.x(), basePoint.y()); - trans.scale(dSX, dSY); - trans.translate(-basePoint.x(), -basePoint.y()); - - prepareGeometryChange(); - m_boundingRect = trans.mapRect(m_lastBoudingRect); - m_dWidth = m_boundingRect.width(); - m_dHeight = m_boundingRect.height(); - updateHandles(); -} - void ElectricFunctionModelSvgItem::move(const QPointF& point) { moveBy(point.x(), point.y()); diff --git a/diagramCavas/source/graphicsItem/pluginItemFactory.cpp b/diagramCavas/source/graphicsItem/pluginItemFactory.cpp index 2572534..3b7477d 100644 --- a/diagramCavas/source/graphicsItem/pluginItemFactory.cpp +++ b/diagramCavas/source/graphicsItem/pluginItemFactory.cpp @@ -1,6 +1,7 @@ // src/canvas/PluginItemFactory.cpp #include "diagramCavas/include/graphicsItem/pluginItemFactory.h" #include "include/graphicsItem/pluginItemWrapper.h" +#include "include/graphicsItem/pluginSvgItemWrapper.h" #include "pluginManager/include/pluginManager.h" #include @@ -55,14 +56,19 @@ GraphicsFunctionModelItem* PluginItemFactory::createItemFromPlugin( return nullptr; } - // 创建包装器 - PluginItemWrapper *wrapper = new PluginItemWrapper(pluginItem, parent); - - if (!wrapper) { - qWarning() << "PluginItemFactory: Failed to create wrapper"; - return nullptr; + bool bSvg = pluginItem->containSvg(); + GraphicsFunctionModelItem* wrapper = nullptr; + if(bSvg){ //包含Svg + wrapper = new PluginSvgItemWrapper(pluginItem, parent); + } + else{ + // 创建包装器 + wrapper = new PluginItemWrapper(pluginItem, parent); } + if (!wrapper) { + return nullptr; + } // 设置基本属性 wrapper->setItemType(GIT_PluginItem); wrapper->setName(pluginItem->displayName()); diff --git a/diagramCavas/source/graphicsItem/pluginItemWrapper.cpp b/diagramCavas/source/graphicsItem/pluginItemWrapper.cpp index 6abaf2a..027887a 100644 --- a/diagramCavas/source/graphicsItem/pluginItemWrapper.cpp +++ b/diagramCavas/source/graphicsItem/pluginItemWrapper.cpp @@ -55,6 +55,7 @@ GraphicsFunctionModelItem* PluginItemWrapper::clone() const // 获取插件类型 QString pluginType = m_pluginItem->typeId(); + int nBaseType = m_pluginItem->baseType(); // 保存当前状态 QVariantMap state = saveState(); @@ -114,7 +115,7 @@ void PluginItemWrapper::paint(QPainter *painter, QRectF selectRect = m_cachedBounds.adjusted(-2, -2, 2, 2); painter->drawRect(selectRect); - // 绘制控制点 + /*// 绘制控制点 const qreal handleSize = 6.0; QRectF handleRect(-handleSize/2, -handleSize/2, handleSize, handleSize); @@ -140,7 +141,7 @@ void PluginItemWrapper::paint(QPainter *painter, painter->setBrush(handleBrush); painter->drawEllipse(handleRect); painter->restore(); - } + }*/ } painter->restore(); @@ -357,7 +358,7 @@ QVariantMap PluginItemWrapper::saveState() const // 这里可以保存插件的关键属性 QStringList propertyKeys = {"fillColor", "borderColor", "borderWidth", "cornerRadius"}; for (const QString &key : propertyKeys) { - QVariant value = m_pluginItem->property(key); + QVariant value = m_pluginItem->getProperty(key); if (value.isValid()) { state[key] = value; } diff --git a/diagramCavas/source/graphicsItem/pluginSvgItemWrapper.cpp b/diagramCavas/source/graphicsItem/pluginSvgItemWrapper.cpp new file mode 100644 index 0000000..75dfe9b --- /dev/null +++ b/diagramCavas/source/graphicsItem/pluginSvgItemWrapper.cpp @@ -0,0 +1,449 @@ +// pluginItemWrapper.cpp +#include "graphicsItem/pluginSvgItemWrapper.h" +#include "pluginManager/include/pluginManager.h" +#include "baseProperty.h" +#include "graphicsDataModel/fixedPortsModel.h" +#include +#include +#include + +PluginSvgItemWrapper::PluginSvgItemWrapper(ICanvasItem *pluginItem, QGraphicsItem *parent) + : ElectricFunctionModelSvgItem(pluginItem->bounds().toRect(),parent) + , m_pluginItem(pluginItem) +{ + if (!m_pluginItem) { + qWarning() << "PluginItemWrapper: pluginItem is null!"; + return; + } + + // 设置类型 + m_Itemtype = GIT_PluginItem; + + // 设置初始名称 + setName(m_pluginItem->displayName()); + + // 连接信号 + connectSignals(); + + // 初始化缓存 + updateCache(); + + // 更新坐标 + updateCoordinate(); + + qDebug() << "PluginItemWrapper created for:" << m_pluginItem->typeId(); +} + +PluginSvgItemWrapper::~PluginSvgItemWrapper() +{ + // 删除插件项 + if (m_pluginItem) { + m_pluginItem->deleteLater(); + } +} + +void PluginSvgItemWrapper::setImage_1(QFileInfo info) +{ + QByteArray svgData; + QFile svgFile(info.absoluteFilePath()); + + if (svgFile.open(QIODevice::ReadOnly)) { + svgData = svgFile.readAll(); + svgFile.close(); + } else { + qDebug() << "can't open imgfile" << svgFile.errorString(); + } + + QMap mapData; + if(!svgData.isEmpty()){ + mapData["custom"] = svgData; + updateMapSvg(mapData,"custom"); + loadSvg(svgData); + updateItem(); + } + + QString sMeta; + QString sModel; + int nType = -1; + if(_property){ + sMeta = _property->metaModelName(); + sModel = _property->modelName(); + nType = _property->type(); + } + + if(_pHandle && !sMeta.isEmpty() && !sModel.isEmpty()) + _pHandle->updateItemIcon(sMeta,sModel,mapData,"custom",nType,0); + + ElectricFunctionModelSvgItem::setImage_1(info); +} + +ElectricFunctionModelSvgItem* PluginSvgItemWrapper::clone() const +{ + if (!m_pluginItem) { + return nullptr; + } + + // 获取场景中的PluginManager + PluginManager *manager = PluginManager::instance(); + if (!manager) { + qWarning() << "PluginManager not available for cloning"; + return nullptr; + } + + // 获取插件类型 + QString pluginType = m_pluginItem->typeId(); + int nBaseType = m_pluginItem->baseType(); + + // 保存当前状态 + QVariantMap state = saveState(); + + // 创建新的插件项 + ICanvasItem *newPluginItem = manager->createItem(pluginType); + if (!newPluginItem) { + qWarning() << "Failed to create plugin item for cloning:" << pluginType; + return nullptr; + } + + // 恢复状态 + if (!loadStateIntoPluginItem(newPluginItem, state)) { + qWarning() << "Failed to restore state for cloned item"; + delete newPluginItem; + return nullptr; + } + + // 创建新的包装器 + PluginSvgItemWrapper *clone = new PluginSvgItemWrapper(newPluginItem, parentItem()); + + // 复制变换属性 + clone->setPos(pos()); + clone->setRotation(rotation()); + clone->setScale(scale()); + clone->setZValue(zValue()); + + // 复制其他属性 + clone->copyPropertiesFrom(this); + + qDebug() << "Cloned plugin item:" << pluginType; + return clone; +} + +void PluginSvgItemWrapper::paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + if (!painter || !m_pluginItem) { + return; + } + + painter->save(); + // 让插件绘制 + m_pluginItem->draw(painter, m_cachedBounds); + + ElectricFunctionModelSvgItem::paint(painter,option,widget); //调用默认绘制 + + painter->restore(); +} + +QRectF PluginSvgItemWrapper::boundingRect() const +{ + qreal margin = 4.0; // 为控制点留出空间 + return m_cachedBounds.adjusted(-margin, -margin, margin, margin); +} + +QPainterPath PluginSvgItemWrapper::shape() const +{ + QPainterPath path; + + if (!m_pluginItem) { + return path; + } + + // 创建简单的矩形路径 + // 插件可以提供更精确的形状,这里简化处理 + path.addRect(m_cachedBounds); + + return path; +} + +void PluginSvgItemWrapper::updateCoordinate() +{ + if (!m_pluginItem) { + return; + } + + // 更新基类属性 + QRectF bounds = m_pluginItem->bounds(); + m_dWidth = bounds.width(); + m_dHeight = bounds.height(); + + // 更新包围框 + m_boundingRect = bounds; + + // 更新变换 + setTransformOriginPoint(bounds.center()); + + // 调用基类更新 + GraphicsFunctionModelItem::updateCoordinate(); + + // 更新句柄位置 + updateHandles(); +} + +void PluginSvgItemWrapper::resize(int handle, double dx, double dy, const QPointF &pos) +{ + if (!m_pluginItem) { + return; + } + + QRectF bounds = m_pluginItem->bounds(); + QRectF newBounds = bounds; + + // 根据控制点调整大小 + switch (handle) { + case H_leftTop: + newBounds.setTopLeft(newBounds.topLeft() + QPointF(dx, dy)); + break; + case H_top: + newBounds.setTop(newBounds.top() + dy); + break; + case H_rightTop: + newBounds.setTopRight(newBounds.topRight() + QPointF(dx, dy)); + break; + case H_right: + newBounds.setRight(newBounds.right() + dx); + break; + case H_rightBottom: + newBounds.setBottomRight(newBounds.bottomRight() + QPointF(dx, dy)); + break; + case H_bottom: + newBounds.setBottom(newBounds.bottom() + dy); + break; + case H_leftBottom: + newBounds.setBottomLeft(newBounds.bottomLeft() + QPointF(dx, dy)); + break; + case H_left: + newBounds.setLeft(newBounds.left() + dx); + break; + default: + // 不是控制点,直接移动 + move(QPointF(dx, dy)); + return; + } + + // 确保大小有效 + if (newBounds.width() < 10) { + newBounds.setWidth(10); + } + if (newBounds.height() < 10) { + newBounds.setHeight(10); + } + + if (newBounds.isValid() && newBounds != bounds) { + m_pluginItem->setBounds(newBounds); + } +} + +void PluginSvgItemWrapper::move(const QPointF &delta) +{ + if (!m_pluginItem || delta.isNull()) { + return; + } + + QRectF bounds = m_pluginItem->bounds(); + bounds.translate(delta); + m_pluginItem->setBounds(bounds); +} + +ICanvasItem* PluginSvgItemWrapper::pluginItem() const +{ + return m_pluginItem; +} + +QVariant PluginSvgItemWrapper::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if (!m_pluginItem) { + return GraphicsFunctionModelItem::itemChange(change, value); + } + + switch (change) { + case ItemSelectedChange: + // 选中状态变化 + if (value.toBool()) { + // 选中时的处理 + setHandleVisible(true); + } else { + // 取消选中的处理 + setHandleVisible(false); + } + break; + + case ItemPositionChange: { + // 位置变化 + QPointF newPos = value.toPointF(); + QPointF delta = newPos - pos(); + + // 更新插件项的位置 + QRectF bounds = m_pluginItem->bounds(); + bounds.translate(delta); + m_pluginItem->setBounds(bounds); + + return newPos; + } + + case ItemRotationChange: + // 旋转变化 + // 插件项可能需要处理旋转 + break; + + case ItemScaleChange: + // 缩放变化 + // 插件项可能需要处理缩放 + break; + + case ItemZValueChange: + // Z值变化 + break; + + default: + break; + } + + return GraphicsFunctionModelItem::itemChange(change, value); +} + +void PluginSvgItemWrapper::updateCache() +{ + if (m_pluginItem) { + m_cachedBounds = m_pluginItem->bounds(); + } +} + +void PluginSvgItemWrapper::connectSignals() +{ + if (!m_pluginItem) { + return; + } + + // 使用旧式语法连接 + connect(m_pluginItem, SIGNAL(boundsChanged(QRectF)), + this, SLOT(onPluginBoundsChanged(QRectF))); + + connect(m_pluginItem, SIGNAL(propertyChanged(QString, QVariant)), + this, SLOT(onPluginPropertyChanged(QString, QVariant))); +} + +QVariantMap PluginSvgItemWrapper::saveState() const +{ + QVariantMap state; + + if (!m_pluginItem) { + return state; + } + + // 保存基本属性 + state["type"] = m_pluginItem->typeId(); + state["displayName"] = m_pluginItem->displayName(); + + // 保存几何信息 + QRectF bounds = m_pluginItem->bounds(); + state["x"] = bounds.x(); + state["y"] = bounds.y(); + state["width"] = bounds.width(); + state["height"] = bounds.height(); + + // 保存插件特定属性 + // 这里可以保存插件的关键属性 + QStringList propertyKeys = {"fillColor", "borderColor", "borderWidth", "cornerRadius"}; + for (const QString &key : propertyKeys) { + QVariant value = m_pluginItem->getProperty(key); + if (value.isValid()) { + state[key] = value; + } + } + + return state; +} + +bool PluginSvgItemWrapper::loadStateIntoPluginItem(ICanvasItem *pluginItem, const QVariantMap &state) const +{ + if (!pluginItem) { + return false; + } + + // 设置几何信息 + if (state.contains("x") && state.contains("y") && + state.contains("width") && state.contains("height")) { + QRectF bounds( + state["x"].toReal(), + state["y"].toReal(), + state["width"].toReal(), + state["height"].toReal() + ); + + if (bounds.isValid()) { + pluginItem->setBounds(bounds); + } + } + + // 设置插件属性 + QStringList propertyKeys = {"fillColor", "borderColor", "borderWidth", "cornerRadius"}; + for (const QString &key : propertyKeys) { + if (state.contains(key)) { + pluginItem->setProperty(key, state[key]); + } + } + + return true; +} + +void PluginSvgItemWrapper::copyPropertiesFrom(const PluginSvgItemWrapper *source) +{ + if (!source) { + return; + } + + // 复制基类属性 + m_type = source->m_type; + m_pen = source->m_pen; + m_brush = source->m_brush; + m_dWidth = source->m_dWidth; + m_dHeight = source->m_dHeight; + m_boundingRect = source->m_boundingRect; + m_Itemtype = source->m_Itemtype; + + // 复制可见性和使能状态 + setVisible(source->isVisible()); + setEnabled(source->isEnabled()); + + // 复制工具提示 + setToolTip(source->toolTip()); + + // 复制自定义数据 + setData(0, source->data(0)); + + // 生成新的ID + setItemId(QUuid::createUuid()); +} + +void PluginSvgItemWrapper::onPluginBoundsChanged(const QRectF &newBounds) +{ + m_cachedBounds = newBounds; + + // 更新坐标 + updateCoordinate(); + + // 通知变化 + emit itemChanged(); +} + +void PluginSvgItemWrapper::onPluginPropertyChanged(const QString &key, const QVariant &value) +{ + Q_UNUSED(key); + Q_UNUSED(value); + + // 属性变化,需要重绘 + update(); + + // 通知变化 + emit itemChanged(); +} diff --git a/diagramCavas/source/util/baseSelector.cpp b/diagramCavas/source/util/baseSelector.cpp index 4b211c5..793e8e1 100644 --- a/diagramCavas/source/util/baseSelector.cpp +++ b/diagramCavas/source/util/baseSelector.cpp @@ -590,12 +590,15 @@ void BaseSelector::dropEvent(QGraphicsSceneDragDropEvent *event, DesignerScene*, else nGraphicType = -1; - if(nGraphicType == 0 || nGraphicType == -1){ //图形类 + if(nGraphicType == 0){ //图形类 _model->addGraphicItem(QUuid::createUuid(),"",event->scenePos(),nGraphicType); } - else{ + else if(nGraphicType == 1){ //文字 _model->addGraphicItem(QUuid::createUuid(),"",event->scenePos(),nGraphicType,"文本对象"); } + else{ + + } event->acceptProposedAction(); } diff --git a/include/mainwindow.h b/include/mainwindow.h index 1ddee6c..c09dfd1 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -72,6 +72,7 @@ private: MonitorPagesDlg* m_pMonitorPagesDlg; QDockWidget* m_pMonitorItemsDock; QDockWidget* m_pMonitorPagesDock; + QDockWidget* m_pPropertyEditorDock; QDetailsView* m_pPropertiesEditorView; QAction* _pActMonitor; }; diff --git a/pluginManager/CMakeLists.txt b/pluginManager/CMakeLists.txt index 47b19bc..5b4273d 100644 --- a/pluginManager/CMakeLists.txt +++ b/pluginManager/CMakeLists.txt @@ -3,18 +3,15 @@ project(pluginManager) set(PLUGINMANAGER_HEADER_FILES include/pluginManager.h - include/genericPluginAdapter.h ../common/include/compiler.hpp ../common/include/export.hpp ../common/include/operatingSystem.hpp - ../common/include/pluginCommon/iPluginAdapter.h ../common/include/pluginCommon/iCanvasItem.h ) set(PLUGINMANAGER_SOURCE_FILES source/pluginManager.cpp - source/genericPluginAdapter.cpp ) diff --git a/pluginManager/include/genericPluginAdapter.h b/pluginManager/include/genericPluginAdapter.h deleted file mode 100644 index d0ff8e9..0000000 --- a/pluginManager/include/genericPluginAdapter.h +++ /dev/null @@ -1,60 +0,0 @@ -// genericPluginAdapter.h -#pragma once - -#include "pluginCommon/iPluginAdapter.h" -#include - -class ICanvasItem; - -// 通用适配器实现 -class GenericPluginAdapter :public IPluginAdapter -{ - Q_OBJECT - -public: - explicit GenericPluginAdapter(ICanvasItem *pluginItem, QObject *parent = nullptr); - virtual ~GenericPluginAdapter(); - - // IPluginAdapter接口 - QString adapterType() const override { return "generic"; } - QString pluginType() const override; - - QRectF bounds() const override; - void setBounds(const QRectF &bounds) override; - - void paint(QPainter *painter, const QRectF &bounds) override; - QPainterPath shape() const override; - - QVariant property(const QString &key) const override; - void setProperty(const QString &key, const QVariant &value) override; - - void move(const QPointF &delta) override; - void resize(const QRectF &newBounds) override; - - bool isSelected() const override; - void setSelected(bool selected) override; - - QVariantMap saveState() const override; - bool loadState(const QVariantMap &state) override; - - // 获取原始插件项 - ICanvasItem* pluginItem() const; - -signals: - void boundsChanged(const QRectF &newBounds); - void propertyChanged(const QString &key, const QVariant &value); - void selectionChanged(bool selected); - void adapterChanged(); - -private: - ICanvasItem *m_pluginItem = nullptr; - bool m_selected = false; - QRectF m_cachedBounds; - - void updateCache(); - void connectSignals(); - -private slots: - void onPluginBoundsChanged(const QRectF &newBounds); - void onPluginPropertyChanged(const QString &key, const QVariant &value); -}; diff --git a/pluginManager/source/genericPluginAdapter.cpp b/pluginManager/source/genericPluginAdapter.cpp index 354de58..1c0a223 100644 --- a/pluginManager/source/genericPluginAdapter.cpp +++ b/pluginManager/source/genericPluginAdapter.cpp @@ -61,7 +61,7 @@ QPainterPath GenericPluginAdapter::shape() const QVariant GenericPluginAdapter::property(const QString &key) const { - return m_pluginItem ? m_pluginItem->property(key) : QVariant(); + return m_pluginItem ? m_pluginItem->getProperty(key) : QVariant(); } void GenericPluginAdapter::setProperty(const QString &key, const QVariant &value) diff --git a/pluginManager/source/pluginManager.cpp b/pluginManager/source/pluginManager.cpp index 128741f..d68f2c4 100644 --- a/pluginManager/source/pluginManager.cpp +++ b/pluginManager/source/pluginManager.cpp @@ -248,7 +248,7 @@ void PluginManager::registerBuiltinShape(const QString &shapeId, ShapeDescriptor desc; desc.id = shapeId; desc.name = name; - desc.category = "内置形状"; + desc.category = -1; desc.iconPath = iconPath; d->builtinDescriptors[shapeId] = desc; diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index cd8f045..a415d92 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -43,6 +43,7 @@ CMainWindow::CMainWindow(QWidget *parent) m_pMonitorPagesDock = nullptr; m_pPropertiesEditorView = nullptr; _pActMonitor = nullptr; + m_pPropertyEditorDock = nullptr; qRegisterMetaType("PropertyStateInfo"); initializeDockUi(); @@ -136,12 +137,13 @@ void CMainWindow::initializeDockUi() connect(&ProjectModelManager::instance(),&ProjectModelManager::modelChange,m_pElectricElementsBox,&ElectricElementsBox::onSignal_modelChanged); m_pPropertiesEditorView = new QDetailsView(); - BaseDockWidget* PropertyEditorDock = new BaseDockWidget(QString::fromWCharArray(L"属性面板"),this); - PropertyEditorDock->setWidget(m_pPropertiesEditorView); - PropertyEditorDock->setMinimumSize(350,150); - m_pPropertiesEditorView->setObject(m_pDiagramCavas); - PropertyEditorDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); - this->addDockWidget(Qt::RightDockWidgetArea,PropertyEditorDock); + m_pPropertyEditorDock = new BaseDockWidget(QString::fromWCharArray(L"属性面板"),this); + m_pPropertyEditorDock->setWidget(m_pPropertiesEditorView); + m_pPropertyEditorDock->setMinimumSize(350,150); + m_pPropertyEditorDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); + this->addDockWidget(Qt::RightDockWidgetArea,m_pPropertyEditorDock); + m_pPropertiesEditorView->setObject(new QObject(this)); + m_pPropertyEditorDock->hide(); connect(m_pDiagramCavas,&DiagramCavas::selectTarget,this,&CMainWindow::onCavasItemSelected); } @@ -309,8 +311,9 @@ void CMainWindow::onSignal_deleteItem() void CMainWindow::onCavasItemSelected(QObject* obj) { - if(m_pPropertiesEditorView) - m_pPropertiesEditorView->setObject(obj); + m_pPropertyEditorDock->show(); + m_pPropertiesEditorView->setObject(obj); + } GraphicElementsPanel* CMainWindow::graphicsElementsPanel() const