add custom HMI image element

This commit is contained in:
baiYue 2026-03-26 16:22:35 +08:00
parent fadc343c88
commit 742ea36c3d
46 changed files with 2483 additions and 247 deletions

View File

@ -58,9 +58,10 @@ set(H_HEADER_FILES
include/monitorItemsDlg.h
include/monitorPagesDlg.h
include/baseDockWidget.h
include/enhancedToolBar.h
include/toolBarConfig.h
include/enhancedToolBar.h
include/configToolBar.h
include/draggableToolButton.h
common/include/tools.h
common/include/httpInterface.h
@ -71,6 +72,11 @@ set(H_HEADER_FILES
common/include/structDataSource.h
common/include/extraPropertyManager.h
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
common/core_model/diagram.h
@ -95,9 +101,10 @@ set(CPP_SOURCE_FILES
source/monitorItemsDlg.cpp
source/monitorPagesDlg.cpp
source/baseDockWidget.cpp
source/enhancedToolBar.cpp
source/toolBarConfig.cpp
source/enhancedToolBar.cpp
source/configToolBar.cpp
source/draggableToolButton.cpp
common/source/httpInterface.cpp
common/source/tools.cpp
@ -152,6 +159,7 @@ include_directories(${PostgreSQL_INCLUDE_DIRS})
target_include_directories(DiagramDesigner PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_include_directories(DiagramDesigner PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/common")
target_include_directories(DiagramDesigner PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/PropertyEditor/source/include)")
target_include_directories(DiagramDesigner PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/pluginManager/include)")
target_link_libraries(DiagramDesigner PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
@ -178,8 +186,10 @@ add_subdirectory(PropertyEditor)
add_subdirectory(diagramCavas)
add_subdirectory(diagramUtils)
add_subdirectory(diagramCommunication)
add_subdirectory(pluginManager)
target_link_libraries(DiagramDesigner PRIVATE PropertyEditor)
target_link_libraries(DiagramDesigner PRIVATE diagramCavas diagramUtils diagramCommunication)
target_link_libraries(DiagramDesigner PRIVATE diagramCavas diagramUtils diagramCommunication pluginManager)
file(COPY setting.xml DESTINATION "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin")

View File

@ -35,6 +35,11 @@ enum GraphicsItemType
GIT_3wTransformer= QGraphicsItem::UserType + 67,
GIT_node= QGraphicsItem::UserType + 79,
GIT_bay= QGraphicsItem::UserType + 80, //间隔
GIT_Image = QGraphicsItem::UserType + 110, //图形item
GIT_Text = QGraphicsItem::UserType + 111, //文本item
GIT_PluginItem = QGraphicsItem::UserType + 120, //自定义Item
//======================================
GIT_baseNode = QGraphicsItem::UserType + 199,
GIT_baseBus = QGraphicsItem::UserType + 200,

View File

@ -227,6 +227,23 @@ struct HMIImageRef //人机界面中的图片引用
}
};
struct HMICustomImageRef //人机界面中图片item的引用
{
int id = -1;
QUuid hmiId;
QString model;
QUuid itemId;
QByteArray hash256;
bool operator==(const HMICustomImageRef& other) const
{
return hmiId == other.hmiId &&
model == other.model &&
itemId == other.itemId &&
hash256 == other.hash256;
}
};
struct MonitorItemDisplayInfo //监控模式显示信息
{
int nItemType; //设备类型

View File

@ -164,6 +164,22 @@ private:
PropertyModel pm; //工程模的选择状态
};
class GraphicProperty:public ModelProperty //非模型图元属性
{
Q_OBJECT
public:
GraphicProperty(QObject* parent);
virtual ~GraphicProperty();
void setGraphicType(int n) {nGraphicType = n;}
int getGraphicType() {return nGraphicType;}
void setContent(const QString& str) {sContent = str;}
QString getContent() {return sContent;}
protected:
int nGraphicType = -1; //图形类型 0图像1文字
QString sContent;
};
class BaseProperty:public ModelProperty //图像工程模模属性类,存放电路元件属性
{
Q_OBJECT

View File

@ -0,0 +1,32 @@
//ICanvasItem.h
#pragma once
#include <QObject>
#include <QRectF>
#include <QPainter>
class ICanvasItem : public QObject
{
Q_OBJECT
public:
virtual ~ICanvasItem() = default;
// 基本信息
virtual QString typeId() const = 0;
virtual QString displayName() const = 0;
// 几何属性
virtual QRectF bounds() const = 0;
virtual void setBounds(const QRectF &rect) = 0;
// 绘制
virtual void draw(QPainter *painter, const QRectF &rect) = 0;
// 属性管理
virtual QVariant property(const QString &key) const = 0;
virtual void setProperty(const QString &key, const QVariant &value) = 0;
signals:
void boundsChanged(const QRectF &newBounds);
void propertyChanged(const QString &key, const QVariant &value);
};

View File

@ -0,0 +1,51 @@
// include/plugin_manager/IPlugin.h
#pragma once
#include <QtPlugin>
#include <QIcon>
#include "iCanvasItem.h"
// 形状描述
struct ShapeDescriptor {
QString id; // 形状标识符
QString name; // 显示名称
QString category; // 分类
QString iconPath; // 图标路径
QVariantMap defaults; // 默认属性
};
// 插件描述
struct PluginDescriptor {
QString id; // 插件ID
QString name; // 插件名称
QString version; // 版本
QString author; // 作者
QString description; // 描述
};
// 插件接口
class IPlugin : public QObject
{
Q_OBJECT
public:
explicit IPlugin(QObject *parent = nullptr) : QObject(parent) {}
virtual ~IPlugin() = default;
// 插件信息
virtual PluginDescriptor descriptor() const = 0;
// 支持的形状
virtual QList<ShapeDescriptor> shapes() const = 0;
// 创建形状
virtual ICanvasItem* createShape(const QString &shapeId) = 0;
// 插件生命周期
virtual bool initialize() = 0;
virtual void shutdown() = 0;
// 图标获取
virtual QIcon shapeIcon(const QString &shapeId) const = 0;
};
Q_DECLARE_INTERFACE(IPlugin, "com.canvas.plugin/1.0")

View File

@ -0,0 +1,52 @@
//iPluginAdapter.h
#pragma once
#include <QObject>
#include <QPainter>
#include <QRectF>
#include <QPainterPath>
// 插件适配器抽象接口
class IPluginAdapter : public QObject
{
Q_OBJECT
public:
explicit IPluginAdapter(QObject *parent = nullptr) : QObject(parent) {}
virtual ~IPluginAdapter() = default;
// 基本属性
virtual QString adapterType() const = 0;
virtual QString pluginType() const = 0;
// 几何属性
virtual QRectF bounds() const = 0;
virtual void setBounds(const QRectF &bounds) = 0;
// 绘制
virtual void paint(QPainter *painter,
const QRectF &bounds) = 0;
// 形状
virtual QPainterPath shape() const = 0;
// 属性访问
virtual QVariant property(const QString &key) const = 0;
virtual void setProperty(const QString &key, const QVariant &value) = 0;
// 操作
virtual void move(const QPointF &delta) = 0;
virtual void resize(const QRectF &newBounds) = 0;
// 状态
virtual bool isSelected() const = 0;
virtual void setSelected(bool selected) = 0;
// 序列化
virtual QVariantMap saveState() const = 0;
virtual bool loadState(const QVariantMap &state) = 0;
signals:
void boundsChanged(const QRectF &newBounds);
void propertyChanged(const QString &key, const QVariant &value);
void selectionChanged(bool selected);
void adapterChanged();
};

View File

@ -0,0 +1,24 @@
//IShapeFactory.h
#pragma once
#include "iCanvasItem.h"
#include "iPlugin.h"
#include <QMap>
// 形状工厂接口(纯接口,不用于插件)
class IShapeFactory
{
public:
virtual ~IShapeFactory() = default;
// 创建形状
virtual ICanvasItem* create(const QString &shapeId) = 0;
// 查询
virtual QStringList availableShapes() const = 0;
virtual bool contains(const QString &shapeId) const = 0;
// 获取形状信息
virtual ShapeDescriptor shapeDescriptor(const QString &shapeId) const = 0;
virtual QIcon shapeIcon(const QString &shapeId) const = 0;
};

View File

@ -60,6 +60,17 @@ BaseModelProperty::BaseModelProperty(QObject* parent)
BaseModelProperty::~BaseModelProperty()
{
}
/**************************图形类********************************/
GraphicProperty::GraphicProperty(QObject* parent)
: ModelProperty(parent)
{
}
GraphicProperty::~GraphicProperty()
{
}
/****************************工程模****************************/

View File

@ -53,14 +53,17 @@ set(DIAGRAMCAVAS_HEADER_FILES
include/createHMIdlg.h
include/graphicsDataModel/baseModel.h
include/graphicsDataModel/fixedPortsModel.h
include/graphicsItem/graphicsBaseItem.h
include/graphicsItem/graphicsItemGroup.h
#include/graphicsItem/graphicsPolygonItem.h
include/graphicsItem/handleRect.h
include/graphicsItem/handleText.h
include/graphicsItem/itemControlHandle.h
include/graphicsItem/itemPort.h
include/graphicsItem/electricBayItem.h
include/graphicsItem/itemControlHandle.h
include/graphicsItem/graphicsBaseItem.h
include/graphicsItem/pluginItemFactory.h
include/graphicsItem/pluginItemWrapper.h
include/graphicsItem/functionModelItem/electricFunctionModelConnectLineItem.h
include/graphicsItem/functionModelItem/electricFunctionModelPortItem.h
@ -83,6 +86,7 @@ set(DIAGRAMCAVAS_HEADER_FILES
include/graphicsItem/functionModelItem/electricFunctionModelSvgItemPI.h
include/graphicsItem/functionModelItem/electricFunctionModelSvgItemPT.h
include/graphicsItem/functionModelItem/graphicsFunctionModelItem.h
include/graphicsItem/functionModelItem/electricFunctionModelSvgItemImage.h
include/baseModelItem/electricBaseModelSvgItem.h
include/baseModelItem/electricBaseModelLineItem.h
@ -177,14 +181,17 @@ set(DIAGRAMCAVAS_SOURCE_FILES
source/createHMIdlg.cpp
source/graphicsDataModel/baseModel.cpp
source/graphicsDataModel/fixedPortsModel.cpp
source/graphicsItem/graphicsBaseItem.cpp
source/graphicsItem/graphicsItemGroup.cpp
#source/graphicsItem/graphicsPolygonItem.cpp
source/graphicsItem/handleRect.cpp
source/graphicsItem/handleText.cpp
source/graphicsItem/itemControlHandle.cpp
source/graphicsItem/itemPort.cpp
source/graphicsItem/electricBayItem.cpp
source/graphicsItem/itemControlHandle.cpp
source/graphicsItem/graphicsBaseItem.cpp
source/graphicsItem/pluginItemFactory.cpp
source/graphicsItem/pluginItemWrapper.cpp
source/graphicsItem/functionModelItem/electricFunctionModelConnectLineItem.cpp
source/graphicsItem/functionModelItem/electricFunctionModelPortItem.cpp
@ -207,6 +214,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES
source/graphicsItem/functionModelItem/electricFunctionModelSvgItemPI.cpp
source/graphicsItem/functionModelItem/electricFunctionModelSvgItemPT.cpp
source/graphicsItem/functionModelItem/graphicsFunctionModelItem.cpp
source/graphicsItem/functionModelItem/electricFunctionModelSvgItemImage.cpp
source/baseModelItem/electricBaseModelSvgItem.cpp
source/baseModelItem/electricBaseModelLineItem.cpp
@ -291,6 +299,7 @@ target_include_directories(diagramCavas PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inclu
target_link_libraries(diagramCavas PRIVATE diagramUtils)
target_link_libraries(diagramCavas PRIVATE diagramCommunication)
target_link_libraries(diagramCavas PRIVATE pluginManager)
target_link_libraries(diagramCavas PUBLIC PropertyEditor)
target_compile_definitions(diagramCavas

View File

@ -48,15 +48,20 @@ public:
~FixedPortsModel();
public:
QMap<QUuid,ItemPageInfo> allNodePos() const;
QMap<QUuid,ItemPageInfo> allGraphicItemPos() const; //所有图形对象位置
QVector<ModelProperty*> allConnectionProperty();
QMap<QUuid,GraphicsFunctionModelItem*>& allItems();
QMap<QUuid,GraphicsFunctionModelItem*>& allGraphicItems() {return _graphicItem;}
bool addNodeItem(QUuid uuid,GraphicsFunctionModelItem*);
bool addGraphicItem(QUuid uuid,GraphicsFunctionModelItem*);
QString addNodeItem(QUuid id,QPointF pos,double width = 0,double height = 0,double rotate = 0);
QString addGraphicItem(QUuid id,QString name,QPointF pos,int type,QString sContent = "",double width = 0,double height = 0,double rotate = 0); //0图形1文字
GraphicsFunctionModelItem* nodeItem(QUuid uuid);
BaseProperty* addNodeData(QUuid id,int type,QString name,QString modelName); //对应component数据一个data可对应多个itemid,类型,名称,工程模名)
void loadNodeDataFromDataBase(); //从数据库加载数据
QString addConnectLline(QUuid lineId,QUuid srcId,QUuid destId,QUuid srcPort,QUuid destPort);
void deleteNodeItem(GraphicsFunctionModelItem*);
void deleteGraphicItem(GraphicsFunctionModelItem*);
//QJsonObject saveNode(QUuid const) const;
void saveNode(int nPageId);
void setScene(DesignerScene* p){_scene = p;}
@ -79,7 +84,9 @@ public:
void insertProjectModelName(QString,QString); //插入工程模类型(生成工程模时调用)
void showProjectIconSettingDlg(GraphicsFunctionModelItem*); //显示工程模图标设置(设置使用图标)
void updateItemIcon(QString sMeta,QString sModel,QMap<QString,QByteArray>,QString sIndex = "",int type = 0,int slot = 0); //更新指定模型的图标 sIndex:索引下标,为空全部更新 sTemplate模板名 type基础类型 slot HMI资源中的槽位
void updateCustomItemIcon(QUuid itemId,QMap<QString,QByteArray> mapData); //更新graphic对象的图片
void updateModelIcon(QString sMeta,QString sModel,QMap<QString,QByteArray>,QString sIndex = ""); //更新某类模型的所有图标
void updateCustomById(QUuid itemId,QMap<QString,QByteArray>); //更新指定custom对象的图片
/*************************间隔*****************************/
void addBayItem(QUuid,ModelFunctionType = ModelFunctionType::ProjectModel);
bool addBayItem(QUuid,ElectricBayItem*,ModelFunctionType = ModelFunctionType::ProjectModel);
@ -116,8 +123,11 @@ public:
QMap<MonitorItemTypeStruct,QMap<MonitorItemStateStruct,MonitorItemDisplayInfo>>& getMonitorDisplaySetting(){return m_monitorDisplaySetting;}
QList<HMIImageRef>& getHMIimageRef(){return _HMIimageRef;}
QList<HMICustomImageRef>& getHMICustomImageRef(){return _HMICustomImageRef;}
int imageRefExist(QString model,QByteArray hash256);
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 setCurItemPropertyDlg(ItemPropertyDlg* p) {m_curPropertyDlg = p;}
ItemPropertyDlg* getCurItemPropertyDlg() {return m_curPropertyDlg;}
@ -142,6 +152,7 @@ public:
QMap<QUuid,GraphicsFunctionModelItem*> getHMIItems(){return _nodeItem;}
QMap<QUuid,ElectricBayItem*> getProjectBayItems(){return _bayItem;}
QMap<QUuid,GraphicsFunctionModelItem*> getGraphicItems(){return _graphicItem;}
void setPageState(int n) {_pageState = n;}
int getPageState() {return _pageState;}
@ -165,6 +176,7 @@ private:
QMap<QUuid,GraphicsFunctionModelItem*> _nodeItem; //工程模对象
QMap<QUuid,ElectricBayItem*> _bayItem; //间隔对象
QMap<QUuid,GraphicsFunctionModelItem*> _graphicItem; //图形对象(图片,文字等)
QString _pageName;
QPointer<DiagramCavas> _cavas;
@ -193,6 +205,7 @@ private:
QString _lastSaveTime; //页面上次保存时间
QList<HMIImageRef> _HMIimageRef; //当前HMI中图片的引用关系
QList<HMICustomImageRef> _HMICustomImageRef; //当前HMI中图片项的引用
public:
static bool _dataInitialised;
};

View File

@ -1,7 +1,7 @@
#ifndef ELECBAYITEM_H
#define ELECBAYITEM_H
#include "graphicsBaseItem.h"
#include "graphicsItem/graphicsBaseItem.h"
#include "baseProperty.h"
class ElectricBayItem :public GraphicsNonStandardItem

View File

@ -0,0 +1,20 @@
#ifndef ELECTRICFUNCTIONMODELSVGITEMIMAGE_H
#define ELECTRICFUNCTIONMODELSVGITEMIMAGE_H
/*****************自定义图形类*******************/
#include "electricFunctionModelSvgItem.h"
class ElectricFunctionModelSvgItemImage :public ElectricFunctionModelSvgItem
{
Q_OBJECT
public:
ElectricFunctionModelSvgItemImage(const QRect &rect,QGraphicsItem *parent = 0);
virtual ~ElectricFunctionModelSvgItemImage();
virtual void setImage_1(QFileInfo) override;
protected:
virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
private:
void initial();
};
#endif

View File

@ -1,7 +1,7 @@
#ifndef GRAPHICSFUNCTIONMODELITEM_H
#define GRAPHICSFUNCTIONMODELITEM_H
#include "../graphicsBaseItem.h"
#include "graphicsItem/graphicsBaseItem.h"
class GraphicsFunctionModelItem : public GraphicsProjectModelItem //功能模item
{

View File

@ -1,7 +1,7 @@
#ifndef GRAPHICSITEMGROUP_H
#define GRAPHICSITEMGROUP_H
#include "graphicsBaseItem.h"
#include "graphicsItem/graphicsBaseItem.h"
class GraphicsItemGroup : public QObject, public AbstractShapeType<QGraphicsItemGroup>

View File

@ -1,7 +1,7 @@
#ifndef GRAPHICSPOLYGONITEM_H
#define GRAPHICSPOLYGONITEM_H
#include "graphicsBaseItem.h"
#include "graphicsItem/graphicsBaseItem.h"
class GraphicPolygonItem : public GraphicsProjectModelItem
{

View File

@ -0,0 +1,53 @@
// src/canvas/PluginItemFactory.h
#pragma once
#include "export.hpp"
#include "functionModelItem/graphicsFunctionModelItem.h"
#include <QObject>
class PluginManager;
class ICanvasItem;
class DIAGRAM_DESIGNER_PUBLIC PluginItemFactory : public QObject
{
Q_OBJECT
public:
static PluginItemFactory* instance();
// 删除拷贝构造函数和赋值运算符
PluginItemFactory(const PluginItemFactory&) = delete;
PluginItemFactory& operator=(const PluginItemFactory&) = delete;
// 设置插件管理器
void setPluginManager(PluginManager *manager);
PluginManager* pluginManager() const;
// 创建图形项
GraphicsFunctionModelItem* createItem(const QString &shapeId,
QGraphicsItem *parent = nullptr);
// 从插件项创建图形项
GraphicsFunctionModelItem* createItemFromPlugin(ICanvasItem *pluginItem,
QGraphicsItem *parent = nullptr);
signals:
void itemCreated(GraphicsFunctionModelItem *item);
void creationFailed(const QString &shapeId, const QString &error);
private:
// 内联定义Private类
class Private
{
public:
PluginManager *pluginManager = nullptr;
Private() = default;
~Private() = default;
};
explicit PluginItemFactory(QObject *parent = nullptr);
~PluginItemFactory() = default; // QScopedPointer自动管理内存
QScopedPointer<Private> d;
};

View File

@ -0,0 +1,52 @@
//pluginItemWrapper.h
#pragma once
#include "functionModelItem/graphicsFunctionModelItem.h"
#include "pluginCommon/iCanvasItem.h"
#include <QObject>
// 内部包装器,不暴露给外部
class PluginItemWrapper : public GraphicsFunctionModelItem
{
Q_OBJECT
public:
explicit PluginItemWrapper(ICanvasItem *pluginItem, QGraphicsItem *parent = nullptr);
virtual ~PluginItemWrapper();
// 克隆
virtual GraphicsFunctionModelItem* 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 PluginItemWrapper *source);
private slots:
void onPluginBoundsChanged(const QRectF &newBounds);
void onPluginPropertyChanged(const QString &key, const QVariant &value);
};

View File

@ -11,7 +11,7 @@
#include "baseSelector.h"
//#include "global.h"
#include <graphicsItem/graphicsBaseItem.h>
#include "graphicsItem/graphicsBaseItem.h"
class EditingSelector : public BaseSelector

View File

@ -1,5 +1,4 @@
#include "baseModelItem/electricBaseModelSvgItem.h"
#include "graphicsItem/itemControlHandle.h"
#include <QPainter>
#include <QStyleOption>

View File

@ -144,8 +144,6 @@ void DesignerScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
if(m_pDrawingPanel)
{
DiagramMode mode = m_pDrawingPanel->getMode();
if(mode == DM_run)
return;
m_pDrawingPanel->selectorManager()->getWorkingSelector()->dragEnterEvent(event, this,mode);
update();
}
@ -158,8 +156,6 @@ void DesignerScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
if(m_pDrawingPanel)
{
DiagramMode mode = m_pDrawingPanel->getMode();
if(mode == DM_run)
return;
m_pDrawingPanel->selectorManager()->getWorkingSelector()->dragMoveEvent(event, this,mode);
update();
}
@ -172,8 +168,6 @@ void DesignerScene::dropEvent(QGraphicsSceneDragDropEvent *event)
if(m_pDrawingPanel)
{
DiagramMode mode = m_pDrawingPanel->getMode();
if(mode == DM_run)
return;
m_pDrawingPanel->selectorManager()->getWorkingSelector()->dropEvent(event, this,mode);
update();
}

View File

@ -223,6 +223,14 @@ void DiagramCavas::onSignal_savePage()
DataBase::GetInstance()->insertHMIimageRefBatch(imgRefLst); //全部重新插入
}
QList<HMICustomImageRef>& imgCustomRefLst = pMonitor->getModelController()->getHMICustomImageRef(); //获取当前HMI所有custom引用
if(imgCustomRefLst.size()){
auto lstRef = DataBase::GetInstance()->getHMICustomRefAll(imgCustomRefLst.first().hmiId);
if(lstRef.size())
DataBase::GetInstance()->removeHMICustomRefAll(imgCustomRefLst.first().hmiId);
DataBase::GetInstance()->insertHMICustomRefBatch(imgCustomRefLst);
}
if(DataBase::GetInstance()->getHMIdByName(pEntity->name()).isNull()) //不存在,创建
DataBase::GetInstance()->insertHMI(QUuid(pEntity->id()),pEntity->name(),pEntity->name(),pMonitor->getDiagramInfo());
else

View File

@ -19,6 +19,7 @@
#include "graphicsItem/functionModelItem/electricFunctionModelSvgItem2wTransformer.h"
#include "graphicsItem/functionModelItem/electricFunctionModelSvgItem3wTransformer.h"
#include "graphicsItem/functionModelItem/electricFunctionModelConnectLineItem.h"
#include "graphicsItem/functionModelItem/electricFunctionModelSvgItemImage.h"
#include "graphicsItem/itemPort.h"
#include "designerScene.h"
@ -41,7 +42,6 @@
#include "projectModelManager.h"
#include "projectIconSetting.h"
#include "monitorPanel.h"
#include "designerView.h"
#include "uiCommunicationBus.h"
#include "instance/dataAccessor.h"
#include "graphicsItem/handleText.h"
@ -102,6 +102,23 @@ QMap<QUuid,ItemPageInfo> FixedPortsModel::allNodePos() const
return map;
}
QMap<QUuid,ItemPageInfo> FixedPortsModel::allGraphicItemPos() const
{
QMap<QUuid,ItemPageInfo> map;
for(auto pItem:_graphicItem)
{
ItemPageInfo info;
double dWidth = pItem->boundingRect().width();
double dHeight = pItem->boundingRect().height();
info.pos = pItem->scenePos()/*+QPointF(dWidth*0.5,dHeight*0.5)*/;
info.dWidth = dWidth;
info.dHeight = dHeight;
info.dRotate = pItem->rotation();
map.insert(pItem->itemId(),info);
}
return map;
}
QVector<ModelProperty*> FixedPortsModel::allConnectionProperty()
{
QVector<ModelProperty*> vec;
@ -155,9 +172,77 @@ bool FixedPortsModel::addNodeItem(QUuid uuid,GraphicsFunctionModelItem* pItem)
}
}
bool FixedPortsModel::addGraphicItem(QUuid uuid,GraphicsFunctionModelItem* pItem)
{
if(_graphicItem.contains(uuid))
return false;
else
{
pItem->setHandle(this);
_graphicItem.insert(uuid,pItem);
return true;
}
}
QString FixedPortsModel::addGraphicItem(QUuid id,QString name,QPointF pos,int type,QString sContent,double width,double height,double rotate)
{
GraphicProperty* pro = nullptr;
GraphicsFunctionModelItem* item = nullptr;
if(_graphicItem.contains(id))
return "exist";
double dX = 0.0;
double dY = 0.0;
if(type == 0){ //图像
if(width == 0 && height == 0){
dX = 30;
dY = 30;
}
else{
dX = width;
dY = height;
}
item = new ElectricFunctionModelSvgItemImage(QRect(-dX*0.5, -dY*0.5, dX, dY));
item->setItemType(GIT_Image);
pro = new GraphicProperty(item);
pro->setGraphicsType(GIT_Image);
pro->setModelName("customImage");
pro->setGraphicType(0);
//pro->setContent();
}
else if(type == 1){ //文字
//pro = new ModelProperty();
}
if(item)
{
item->setItemId(id);
pro->setUuid(id);
pro->setType(-1);
item->editShape(0, pos);
item->setPos(pos);
item->setRotation(rotate);
_scene->addItem(item);
item->addPoint(pos);
item->setProperty(pro); //绑定模型
//item->updateByProperty(); //使用模型更新自身
item->setHandle(this);
_graphicItem.insert(id,item);
if(name.isEmpty()){ //如果不给名称则给个默认值
pro->setName("item_"+QString::number(_graphicItem.size()));
}
else{
pro->setName(name);
}
}
return pro?pro->name():"err";
}
QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double height,double rotate)
{
//todo:load图形时必有拓扑实体关联到对应的entity
BaseProperty* pro = nullptr;
GraphicsFunctionModelItem* item = nullptr;
QMap<QUuid,BaseProperty*> mapData = BasePropertyManager::instance().getEntityData(); //加载的图形必定关联component(todo:完善判断条件,如判断拓扑节点)
@ -905,6 +990,15 @@ void FixedPortsModel::deleteNodeItem(GraphicsFunctionModelItem* pItem)
}
}
void FixedPortsModel::deleteGraphicItem(GraphicsFunctionModelItem* pItem)
{
for(auto iter = _graphicItem.begin();iter != _graphicItem.end();++iter){
if(iter.value() == pItem){
delete _graphicItem.take(iter.key());
}
}
}
void FixedPortsModel::saveNode(int nPageId)
{
QList<GridInfo> lstGrid = DataBase::GetInstance()->getAllGrid();
@ -1933,6 +2027,24 @@ void FixedPortsModel::updateItemIcon(QString sMeta,QString sModel,QMap<QString,Q
updateModelIcon(sMeta,sModel,mapData,sIndex);
}
void FixedPortsModel::updateCustomItemIcon(QUuid itemId,QMap<QString,QByteArray> mapData)
{
if(mapData.size() == 1){ //单项设置
QByteArray sha256Hash = QCryptographicHash::hash(mapData.first(), QCryptographicHash::Sha256).toHex();
QMap<QByteArray,HMIImageInfo>& mapResource = ProjectModelManager::instance().getHMIimageMap(); //更新总HMI资源
if(!mapResource.contains(sha256Hash)){ //库中不存在则新建
HMIImageInfo imageInfo;
imageInfo.baseType = -1; //未定义类型
imageInfo.imageName = mapData.firstKey();
imageInfo.hash256 = sha256Hash;
imageInfo.svgData = mapData.first();
mapResource.insert(sha256Hash,imageInfo);
}
updateHMICustomRef(QUuid(_widget->getEntity()->id()),"customImage",itemId,sha256Hash); //更新本页的custom引用
}
//updateCustomById(itemId,mapData); //不需要更新其他custom对象
}
void FixedPortsModel::updateModelIcon(QString sMeta,QString sModel,QMap<QString,QByteArray> mapData,QString sIndex)
{
for(auto &pItem:_nodeItem){
@ -1952,6 +2064,24 @@ void FixedPortsModel::updateModelIcon(QString sMeta,QString sModel,QMap<QString,
}
}
void FixedPortsModel::updateCustomById(QUuid itemId,QMap<QString,QByteArray> mapData)
{
for(auto &pItem:_graphicItem){
auto pro = pItem->getProperty();
if(pro->uuid() == itemId){
auto pI = dynamic_cast<ElectricFunctionModelSvgItem*>(pItem);
auto pG = dynamic_cast<ElectricFunctionModelSvgGroup*>(pItem);
if(pI){
pI->updateMapSvg(mapData,"");
}
if(pG){
pG->updateMapSvg(mapData,"");
}
}
}
}
void FixedPortsModel::addBayItem(QUuid id,ModelFunctionType tpe)
{
if(tpe == ModelFunctionType::BaseModel){
@ -2389,6 +2519,16 @@ int FixedPortsModel::imageRefExist(QString model,QByteArray hash256)
return -1;
}
int FixedPortsModel::customImageRefExist(QUuid uid,QByteArray hash256)
{
for(auto& info:_HMICustomImageRef)
{
if(uid == info.itemId && hash256 == info.hash256)
return _HMICustomImageRef.indexOf(info);
}
return -1;
}
void FixedPortsModel::updateHMIRef(QUuid hmiId,QString model,QByteArray hash256,int slot)
{
HMIImageRef ref;
@ -2404,3 +2544,19 @@ void FixedPortsModel::updateHMIRef(QUuid hmiId,QString model,QByteArray hash256,
_HMIimageRef.append(ref);
}
}
void FixedPortsModel::updateHMICustomRef(QUuid hmiId,QString model,QUuid itemId,QByteArray hash256)
{
HMICustomImageRef ref;
ref.hmiId = hmiId;
ref.model = model;
ref.itemId = itemId;
ref.hash256 = hash256;
int index = customImageRefExist(itemId,hash256);
if(index != -1){ //已存在,替换
_HMICustomImageRef[index] = ref;
}
else{ //新建
_HMICustomImageRef.append(ref);
}
}

View File

@ -1,5 +1,4 @@
#include "graphicsItem/functionModelItem/electricFunctionModelSvgItem.h"
#include "graphicsItem/itemControlHandle.h"
#include <QPainter>
#include <QStyleOption>

View File

@ -0,0 +1,71 @@
#include "graphicsItem/functionModelItem/electricFunctionModelSvgItemImage.h"
#include "graphicsDataModel/fixedPortsModel.h"
#include "baseProperty.h"
#include <QPainter>
#include <QStyleOption>
#include <QGraphicsScene>
#include <QGraphicsView>
ElectricFunctionModelSvgItemImage::ElectricFunctionModelSvgItemImage(const QRect &rect, QGraphicsItem *parent)
: ElectricFunctionModelSvgItem(rect,parent)
{
initial();
}
ElectricFunctionModelSvgItemImage::~ElectricFunctionModelSvgItemImage()
{
}
void ElectricFunctionModelSvgItemImage::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<QString,QByteArray> mapData;
if(!svgData.isEmpty()){
mapData["customImage"] = svgData;
updateMapSvg(mapData,"customImage");
loadSvg(svgData);
updateItem();
}
QString sMeta;
QString sModel;
QUuid itemId;
if(_property){
sMeta = _property->metaModelName();
sModel = _property->modelName();
itemId = _property->uuid();
}
if(_pHandle)
_pHandle->updateCustomItemIcon(itemId,mapData);
GraphicsBaseItem::setImage_1(info);
}
void ElectricFunctionModelSvgItemImage::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
ElectricFunctionModelSvgItem::paint(painter,option,widget);
}
void ElectricFunctionModelSvgItemImage::initial()
{
setHandleIfShow(H_textCaption,false);
setHandleVisible(false);
setFunctionHandleIfShow(false);
setFunctionHandleEnaable(false);
if(!_itemImgIndex.contains("es"))
_itemImgIndex.append("es");
}

View File

@ -0,0 +1,71 @@
// src/canvas/PluginItemFactory.cpp
#include "diagramCavas/include/graphicsItem/pluginItemFactory.h"
#include "include/graphicsItem/pluginItemWrapper.h"
#include "pluginManager/include/pluginManager.h"
#include <QDebug>
PluginItemFactory* PluginItemFactory::instance()
{
static PluginItemFactory instance;
return &instance;
}
PluginItemFactory::PluginItemFactory(QObject *parent)
: QObject(parent)
, d(new Private)
{
}
void PluginItemFactory::setPluginManager(PluginManager *manager)
{
d->pluginManager = manager;
}
GraphicsFunctionModelItem* PluginItemFactory::createItem(const QString &shapeId,
QGraphicsItem *parent)
{
if (!d->pluginManager) {
qWarning() << "PluginManager not set";
emit creationFailed(shapeId, "PluginManager not set");
return nullptr;
}
// 1. 通过插件管理器创建原始插件项
ICanvasItem *pluginItem = d->pluginManager->createItem(shapeId);
if (!pluginItem) {
qWarning() << "Failed to create plugin item:" << shapeId;
emit creationFailed(shapeId, "Plugin item creation failed");
return nullptr;
}
// 2. 创建包装器
GraphicsFunctionModelItem *item = createItemFromPlugin(pluginItem, parent);
if (item) {
emit itemCreated(item);
}
return item;
}
GraphicsFunctionModelItem* PluginItemFactory::createItemFromPlugin(
ICanvasItem *pluginItem, QGraphicsItem *parent)
{
if (!pluginItem) {
return nullptr;
}
// 创建包装器
PluginItemWrapper *wrapper = new PluginItemWrapper(pluginItem, parent);
if (!wrapper) {
qWarning() << "PluginItemFactory: Failed to create wrapper";
return nullptr;
}
// 设置基本属性
wrapper->setItemType(GIT_PluginItem);
wrapper->setName(pluginItem->displayName());
return wrapper;
}

View File

@ -0,0 +1,451 @@
// pluginItemWrapper.cpp
#include "graphicsItem/pluginItemWrapper.h"
#include "pluginManager/include/pluginManager.h"
#include <QDebug>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
PluginItemWrapper::PluginItemWrapper(ICanvasItem *pluginItem, QGraphicsItem *parent)
: GraphicsFunctionModelItem(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();
}
PluginItemWrapper::~PluginItemWrapper()
{
// 删除插件项
if (m_pluginItem) {
m_pluginItem->deleteLater();
}
}
GraphicsFunctionModelItem* PluginItemWrapper::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();
// 保存当前状态
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;
}
// 创建新的包装器
PluginItemWrapper *clone = new PluginItemWrapper(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 PluginItemWrapper::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
if (!painter || !m_pluginItem) {
return;
}
painter->save();
// 设置抗锯齿
painter->setRenderHint(QPainter::Antialiasing, true);
// 让插件绘制
m_pluginItem->draw(painter, m_cachedBounds);
// 如果选中,绘制控制框
if (option && (option->state & QStyle::State_Selected)) {
painter->setPen(QPen(QColor(0, 120, 215), 1, Qt::DashLine));
painter->setBrush(Qt::NoBrush);
// 绘制选中框
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);
QBrush handleBrush(QColor(0, 120, 215));
QPen handlePen(Qt::white, 1);
// 绘制8个控制点
QPointF corners[] = {
m_cachedBounds.topLeft(),
m_cachedBounds.topRight(),
m_cachedBounds.bottomRight(),
m_cachedBounds.bottomLeft(),
QPointF(m_cachedBounds.center().x(), m_cachedBounds.top()),
QPointF(m_cachedBounds.right(), m_cachedBounds.center().y()),
QPointF(m_cachedBounds.center().x(), m_cachedBounds.bottom()),
QPointF(m_cachedBounds.left(), m_cachedBounds.center().y())
};
for (const QPointF &corner : corners) {
painter->save();
painter->translate(corner);
painter->setPen(handlePen);
painter->setBrush(handleBrush);
painter->drawEllipse(handleRect);
painter->restore();
}
}
painter->restore();
}
QRectF PluginItemWrapper::boundingRect() const
{
qreal margin = 4.0; // 为控制点留出空间
return m_cachedBounds.adjusted(-margin, -margin, margin, margin);
}
QPainterPath PluginItemWrapper::shape() const
{
QPainterPath path;
if (!m_pluginItem) {
return path;
}
// 创建简单的矩形路径
// 插件可以提供更精确的形状,这里简化处理
path.addRect(m_cachedBounds);
return path;
}
void PluginItemWrapper::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 PluginItemWrapper::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 PluginItemWrapper::move(const QPointF &delta)
{
if (!m_pluginItem || delta.isNull()) {
return;
}
QRectF bounds = m_pluginItem->bounds();
bounds.translate(delta);
m_pluginItem->setBounds(bounds);
}
ICanvasItem* PluginItemWrapper::pluginItem() const
{
return m_pluginItem;
}
QVariant PluginItemWrapper::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 PluginItemWrapper::updateCache()
{
if (m_pluginItem) {
m_cachedBounds = m_pluginItem->bounds();
}
}
void PluginItemWrapper::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 PluginItemWrapper::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->property(key);
if (value.isValid()) {
state[key] = value;
}
}
return state;
}
bool PluginItemWrapper::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 PluginItemWrapper::copyPropertiesFrom(const PluginItemWrapper *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 PluginItemWrapper::onPluginBoundsChanged(const QRectF &newBounds)
{
m_cachedBounds = newBounds;
// 更新坐标
updateCoordinate();
// 通知变化
emit itemChanged();
}
void PluginItemWrapper::onPluginPropertyChanged(const QString &key, const QVariant &value)
{
Q_UNUSED(key);
Q_UNUSED(value);
// 属性变化,需要重绘
update();
// 通知变化
emit itemChanged();
}

View File

@ -48,8 +48,8 @@ void MonitorPanel::initial()
createToolBar();
_sideBar = new MonitorSideBarDlg(this);
_hSplitter->addWidget(_sideBar);
_sideBar->show();
//_hSplitter->addWidget(_sideBar);
//_sideBar->show();
_pConfigDlg = new MonitorConfigDlg(this);
_detailAttributeDlg = new MonitorDetailAttributeDlg(this);
_displaySettingDlg = new MonitorDisplaySettingDlg(this);
@ -151,6 +151,36 @@ QJsonObject MonitorPanel::getDiagramInfo()
}
obj["nodes"] = arr;
QJsonArray arrGraphic;
QMap<QUuid,ItemPageInfo> mapGraphicPos = _pModel->allGraphicItemPos(); //graphic item位置
QMap<QUuid,GraphicsFunctionModelItem*> mapGraphicItem = _pModel->allGraphicItems();
for(auto pItem:_pModel->allGraphicItems())
{
ItemPageInfo info;
double dWidth = pItem->boundingRect().width();
double dHeight = pItem->boundingRect().height();
QPointF pos = pItem->scenePos();
double rotation = pItem->rotation();
QJsonObject node;
node["id"] = pItem->itemId().toString();
node["x"] = pos.x();
node["y"] = pos.y();
node["width"] = dWidth;
node["height"] = dHeight;
node["rotate"] = rotation;
GraphicProperty* pPro = dynamic_cast<GraphicProperty*>(pItem->getProperty());
if(pPro){
node["name"] = pPro->name();
node["type"] = pPro->getGraphicType();
node["modeName"] = pPro->modelName();
node["content"] = pPro->getContent();
}
arrGraphic.append(node);
}
obj["graphicNode"] = arrGraphic;
QJsonArray arrConnect;
QVector<ModelProperty*> vec = _pModel->allConnectionProperty();
for(auto& pPro:vec){
@ -219,6 +249,49 @@ void MonitorPanel::loadNodes(QJsonObject obj)
}
}
QMap<QByteArray,HMIImageInfo> mapHmiSource = ProjectModelManager::instance().getHMIimageMap(); //获取所有hmi资源
QList<HMICustomImageRef> lstRef = DataBase::GetInstance()->getHMICustomRefAll(QUuid(_pEntity->id()));
_pModel->getHMICustomImageRef() = lstRef;
QJsonArray graphicNodesJsonArray = obj["graphicNode"].toArray();
for (QJsonValueRef nodeJson : graphicNodesJsonArray)
{
QJsonObject node = nodeJson.toObject();
QUuid itemId = QUuid(node["id"].toString());
QString sName = node["name"].toString();
int nType = node["type"].toInt(); //图形item的类型 0图像1文字
QString sModeName = node["modeName"].toString(); //模型名,定值
QString sContent = node["content"].toString();
double dX = node["x"].toDouble();
double dY = node["y"].toDouble();
double dWidth = node["width"].toDouble();
double dHeight = node["height"].toDouble();
double dRotate = node["rotate"].toDouble();
if(_pModel)
{
QString res = _pModel->addGraphicItem(itemId,sName,QPointF(dX,dY),nType,sModeName,dWidth,dHeight,dRotate); //创建图形对象
if(res != "err"){
if(nType == 0){ //图片类型
QMap<QString,QByteArray> mapData;
for(auto& customRef:lstRef){
if(customRef.itemId == itemId){
QString sImage = mapHmiSource.value(customRef.hash256).imageName;
QByteArray data = mapHmiSource.value(customRef.hash256).svgData;
mapData.insert(sImage,data);
}
}
if(!mapData.isEmpty())
_pModel->updateCustomById(itemId,mapData); //更新item引用的图片
}
else if(nType == 1){ //文字类型
}
}
}
}
QJsonArray connectArr = obj["connections"].toArray();
for(QJsonValueRef connectJson:connectArr)
@ -341,8 +414,6 @@ void MonitorPanel::loadNodes(QJsonObject obj)
break;
}
QMap<QByteArray,HMIImageInfo> mapHmiSource = ProjectModelManager::instance().getHMIimageMap(); //获取所有hmi资源
QList<HierarchyItem> lstFirst;
for(auto& pOtherItem:_pModel->getProjectBayItems())

View File

@ -572,32 +572,34 @@ void BaseSelector::dragMoveEvent(QGraphicsSceneDragDropEvent *event, DesignerSce
void BaseSelector::dropEvent(QGraphicsSceneDragDropEvent *event, DesignerScene*,DiagramMode sceneMode)
{
if(sceneMode == DM_edit)
if(sceneMode == DM_run)
{
if (event->mimeData()->hasText()) {
QString text = event->mimeData()->text();
QString uuid = QString::fromLocal8Bit(event->mimeData()->data("application/id"));
QString sType = QString::fromLocal8Bit(event->mimeData()->data("application/x-tooltype"));
// 根据拖拽的数据创建相应的图形项并添加到场景中
QGraphicsTextItem *textItem = new QGraphicsTextItem(text);
textItem->setPos(event->scenePos());
//QGraphicsTextItem *textItem = new QGraphicsTextItem(text);
//textItem->setPos(event->scenePos());
//addItem(textItem);
event->acceptProposedAction();
//根据data数据新增拖拽的item
QMap<QUuid,GraphicsFunctionModelItem*> items = _model->allItems();
if(items.contains(QUuid(uuid))){
QMessageBox::information(NULL, QString::fromWCharArray(L"提示"), QString::fromWCharArray(L"此对象在当前页已存在"));
return;
int nGraphicType = -1;
if(sType == "image")
nGraphicType = 0;
else if(sType == "text")
nGraphicType = 1;
else
nGraphicType = -1;
if(nGraphicType == 0 || nGraphicType == -1){ //图形类
_model->addGraphicItem(QUuid::createUuid(),"",event->scenePos(),nGraphicType);
}
else{
_model->addNodeItem(QUuid(uuid),event->scenePos());
}
event->acceptProposedAction();
}
}
else if(sceneMode == DM_baseModel)
{
int a = 1;
}
}

View File

@ -2,7 +2,7 @@
#include "graphicsItem/itemPort.h"
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>
#include <graphicsItem/graphicsBaseItem.h>
#include "graphicsItem/graphicsBaseItem.h"
#include "baseProperty.h"
MovingSelector::MovingSelector(FixedPortsModel* model,QObject *parent)

View File

@ -1,7 +1,7 @@
#include "util/rotationSelector.h"
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>
#include <graphicsItem/graphicsBaseItem.h>
#include "graphicsItem/graphicsBaseItem.h"
RotationSelector::RotationSelector(FixedPortsModel* model,QObject *parent)

View File

@ -1,7 +1,7 @@
#include "util/scalingSelector.h"
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>
#include <graphicsItem/graphicsBaseItem.h>
#include "graphicsItem/graphicsBaseItem.h"
ScalingSelector::ScalingSelector(FixedPortsModel* model,QObject *parent)
: BaseSelector(model,parent)

View File

@ -177,6 +177,12 @@ public:
bool removeHMIRef(QUuid hmiId,QString model); //移除hmi中某类模型的图片引用
bool removeHMIRefAll(QUuid hmiId); //移除某个HMI中所有引用关系
bool inserHMICustomRef(QUuid hmiId,QString model,QUuid itemId,QByteArray hash256); //图片item使用的图片
bool insertHMICustomRefBatch(const QList<HMICustomImageRef>& refList);
QList<HMICustomImageRef> getHMICustomRefAll(QUuid hmiId);
QList<HMICustomImageRef> getHMICustomRef(QUuid hmiId,QUuid itemId);
bool removeHMICustomRef(QUuid hmiId,QUuid itemId);
bool removeHMICustomRefAll(QUuid hmiId);
public:
/***********************************editor编辑器**********************************************/
bool insertEditorProject(QUuid,QString,QString);

View File

@ -3408,31 +3408,83 @@ bool DataBase::insertHMIimagesBatch(const QVector<HMIImageInfo>& imageList)
return true;
}
// 准备批量参数
QStringList sqlStatements;
QList<QVariantList> paramsList;
int successCount = 0;
int totalCount = imageList.size();
QString strSQL = "INSERT INTO diagramui_hmi_image(type, svg_name, svg_hash, svg_data) VALUES (?, ?, ?, ?)";
for (const auto& image : imageList) {
sqlStatements.append(strSQL);
QVariantList params;
params.append(image.baseType);
params.append(image.imageName);
params.append(image.hash256);
params.append(image.svgData);
paramsList.append(params);
// 使用单个事务
if (!db.transaction()) {
LOG_ERROR("DB", "Start transaction failed.");
return false;
}
try {
// 使用现有批量执行函数,强制使用事务
executeBatchSQL(sqlStatements, false, paramsList, true);
return true;
// 使用单个准备好的语句
QSqlQuery insertQuery(db);
if (!insertQuery.prepare(
"INSERT INTO diagramui_hmi_image(type, svg_name, svg_hash, svg_data) "
"VALUES (?, ?, ?, ?)")) {
LOG_ERROR("DB", "Prepare insert statement failed.");
db.rollback();
return false;
}
for (const auto& image : imageList) {
// 重新绑定参数
insertQuery.bindValue(0, image.baseType);
insertQuery.bindValue(1, image.imageName);
insertQuery.bindValue(2, image.hash256);
insertQuery.bindValue(3, image.svgData);
if (!insertQuery.exec()) {
QSqlError error = insertQuery.lastError();
QString errorText = error.databaseText();
auto errorType = error.type(); // Qt6: 返回错误类型字符串
// 检查是否唯一约束冲突
if (errorText.contains("重复键违反唯一约束", Qt::CaseInsensitive) ||
errorText.contains("duplicate key", Qt::CaseInsensitive) ||
errorText.contains("already exists", Qt::CaseInsensitive) ||
errorText.contains("unique constraint", Qt::CaseInsensitive) ||
error.driverText().contains("23505")) { // PostgreSQL唯一约束错误码
LOG_WARN("DB", QString("Duplicate image hash skipped: %1")
.arg(QString(image.hash256.toHex())));
continue; // 跳过这条记录,继续下一条
} else {
LOG_ERROR("DB", QString("Insert image failed: %1, error: %2, driver: %3")
.arg(image.imageName, errorText, error.driverText()));
// 非重复错误,回滚整个事务
db.rollback();
return false;
}
}
successCount++;
}
if (successCount > 0) {
if (!db.commit()) {
LOG_ERROR("DB", "Commit transaction failed.");
db.rollback();
return false;
}
if (successCount < totalCount) {
LOG_WARN("DB", QString("Batch insert partially completed. Success: %1, Failed: %2")
.arg(successCount).arg(totalCount - successCount));
}
LOG_INFO("DB", QString("Insert completed: %1/%2 images").arg(successCount).arg(totalCount));
return true;
} else {
db.rollback();
LOG_WARN("DB", "No records were inserted.");
return false;
}
}
catch (const std::exception& e) {
LOG_ERROR("DB", QString("Batch insert HMI images failed: %1").arg(e.what()));
db.rollback();
LOG_ERROR("DB", QString("Insert failed with exception: %1").arg(e.what()));
return false;
}
}
@ -3489,7 +3541,7 @@ QVector<bool> DataBase::batchCheckHMIimagesExists(const QVector<QByteArray>& has
for (const auto& hash : hashList) {
placeholders.append("?");
params.append(QString(hash.toHex())); // 转换为十六进制字符串
params.append(hash); // 转换为十六进制字符串
}
QString sql = QString("SELECT svg_hash FROM diagramui_hmi_image WHERE svg_hash IN (%1)")
@ -3506,7 +3558,7 @@ QVector<bool> DataBase::batchCheckHMIimagesExists(const QVector<QByteArray>& has
// 更新存在性结果
for (int i = 0; i < hashList.size(); ++i) {
QString currentHash = QString(hashList[i].toHex());
QString currentHash = QString(hashList[i]);
if (existingHashes.contains(currentHash)) {
existsResults[i] = true;
}
@ -3704,6 +3756,164 @@ bool DataBase::removeHMIRefAll(QUuid hmiId)
return false;
}
}
bool DataBase::inserHMICustomRef(QUuid hmiId,QString model,QUuid itemId,QByteArray hash256)
{
QString strSQL = "INSERT INTO diagramui_hmi_custom_config(hmi_uuid, model_name, item_id, svg_hash) VALUES ( ?, ?, ?, ?)";
QVariantList params;
params.append(hmiId);
params.append(model);
params.append(itemId);
params.append(hash256);
try
{
executeSQL(strSQL,false,params);
return true;
}
catch (const std::exception& e)
{
LOG_ERROR("DB", QString("Insert diagramui_hmi_custom_config fail"));
return false;
}
}
bool DataBase::insertHMICustomRefBatch(const QList<HMICustomImageRef>& refList)
{
if (refList.isEmpty()) {
return true;
}
// 准备批量参数
QStringList sqlStatements;
QList<QVariantList> paramsList;
// 注意id 是自增主键,不需要插入
QString strSQL = "INSERT INTO diagramui_hmi_custom_config(hmi_uuid, model_name, item_id, svg_hash) VALUES ( ?, ?, ?, ?)";
for (const auto& ref : refList) {
sqlStatements.append(strSQL);
QVariantList params;
params.append(ref.hmiId);
params.append(ref.model);
params.append(ref.itemId);
params.append(ref.hash256);
paramsList.append(params);
}
try {
// 使用现有批量执行函数,强制使用事务
executeBatchSQL(sqlStatements, false, paramsList, true);
return true;
}
catch (const std::exception& e) {
LOG_ERROR("DB", QString("Batch insert HMI custom refs failed: %1").arg(e.what()));
return false;
}
}
QList<HMICustomImageRef> DataBase::getHMICustomRefAll(QUuid hmiId)
{
QList<HMICustomImageRef> lst;
QString strSQL = "SELECT id, hmi_uuid, model_name, item_id, svg_hash FROM diagramui_hmi_custom_config WHERE hmi_uuid = ?";
QVariantList params;
params.append(hmiId);
try
{
QSqlQuery query = executeSQL(strSQL,false,params);
while (query.next())
{
HMICustomImageRef info;
info.id = query.value(0).toInt();
info.hmiId = QUuid(query.value(1).toString());
info.model = query.value(2).toString();
info.itemId = QUuid(query.value(3).toString());
info.hash256 = query.value(4).toByteArray();
lst.append(info);
}
query.clear();
return lst;
}
catch (const std::exception& e)
{
return lst;
}
}
QList<HMICustomImageRef> DataBase::getHMICustomRef(QUuid hmiId,QUuid itemId)
{
QList<HMICustomImageRef> lst;
QString strSQL = "SELECT id, hmi_uuid, model_name, item_id, svg_hash FROM diagramui_hmi_custom_config WHERE hmi_uuid = ? AND item_id = ?";
QVariantList params;
params.append(hmiId);
params.append(itemId);
try
{
QSqlQuery query = executeSQL(strSQL,false,params);
while (query.next())
{
HMICustomImageRef info;
info.id = query.value(0).toInt();
info.hmiId = QUuid(query.value(1).toString());
info.model = query.value(2).toString();
info.itemId = QUuid(query.value(3).toString());
info.hash256 = query.value(4).toByteArray();
lst.append(info);
}
query.clear();
return lst;
}
catch (const std::exception& e)
{
return lst;
}
}
bool DataBase::removeHMICustomRef(QUuid hmiId,QUuid itemId)
{
QString strSQL = "DELETE FROM diagramui_hmi_custom_config WHERE hmi_uuid = ? AND item_id = ?";
QVariantList params;
params.append(hmiId);
params.append(itemId);
try
{
executeSQL(strSQL,false,params);
LOG_INFO("DB", QString("Delete diagramui_hmi_custom_config success"));
return true;
}
catch (const std::exception& e)
{
LOG_ERROR("DB", QString("Delete diagramui_hmi_custom_config failed"));
return false;
}
}
bool DataBase::removeHMICustomRefAll(QUuid hmiId)
{
QString strSQL = "DELETE FROM diagramui_hmi_custom_config WHERE hmi_uuid = ?";
QVariantList params;
params.append(hmiId);
try
{
executeSQL(strSQL,false,params);
LOG_INFO("DB", QString("Delete diagramui_hmi_custom_config success"));
return true;
}
catch (const std::exception& e)
{
LOG_ERROR("DB", QString("Delete diagramui_hmi_custom_config failed"));
return false;
}
}
//===========================================================================
bool DataBase::createDynamicTable(const QString &tableName, const QStringList &fields)
{

View File

@ -9,12 +9,10 @@ class ConfigToolBar : public EnhancedToolBar
Q_OBJECT
public:
explicit ConfigToolBar(const QString &title, QWidget *parent = nullptr);
explicit ConfigToolBar(QWidget *parent = nullptr);
// 从配置加载工具
bool loadToolsFromConfig(const QString &configFile);
private:
void loadDefaultTools();

View File

@ -0,0 +1,35 @@
// draggabletoolbutton.h
#ifndef DRAGGABLETOOLBUTTON_H
#define DRAGGABLETOOLBUTTON_H
#include <QToolButton>
class DraggableToolButton : public QToolButton
{
Q_OBJECT
public:
explicit DraggableToolButton(QWidget *parent = nullptr);
void setDragEnabled(bool enabled);
bool dragEnabled() const;
void setToolData(const QString &data);
QString toolData() const;
signals:
void dragStarted(const QString &toolData, const QPoint &globalPos);
void clicked(); // 自定义点击信号
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
bool m_dragEnabled = true;
bool m_isDragging = false;
QPoint m_pressPos;
QString m_toolData;
};
#endif // DRAGGABLETOOLBUTTON_H

View File

@ -1,54 +1,45 @@
// enhancedtoolbar.h
#ifndef ENHANCEDTOOLBAR_H
#define ENHANCEDTOOLBAR_H
#include <QToolBar>
#include <QActionGroup>
#include <QMap>
class DraggableToolButton;
class EnhancedToolBar : public QToolBar
{
Q_OBJECT
public:
explicit EnhancedToolBar(const QString &title, QWidget *parent = nullptr);
explicit EnhancedToolBar(QWidget *parent = nullptr);
// 工具管理接口
// 添加工具
void addTool(const QString &toolType, const QString &toolName,
const QIcon &icon = QIcon());
void removeTool(const QString &toolType);
void setCurrentTool(const QString &toolType);
// 获取当前选中的工具
QString currentTool() const;
// 获取工具信息
QString toolName(const QString &toolType) const;
QIcon toolIcon(const QString &toolType) const;
QStringList availableTools() const;
// 设置当前工具
void setCurrentTool(const QString &toolType);
// 批量操作
void clearTools();
void addTools(const QList<QPair<QString, QString>> &tools);
// 启用/禁用拖拽
void setDragEnabled(bool enabled);
bool dragEnabled() const;
signals:
void toolSelected(const QString &toolType);
void toolAdded(const QString &toolType);
void toolRemoved(const QString &toolType);
protected:
virtual QAction* createAction(const QString &toolType,
const QString &toolName,
const QIcon &icon);
void toolDragged(const QString &toolType, const QPoint &globalPos);
private slots:
void onActionTriggered(QAction *action);
void onToolButtonClicked();
void onToolButtonDragStarted(const QString &toolData, const QPoint &globalPos);
void startDrag(const QString &toolType, const QPoint &globalPos);
private:
void init();
QActionGroup *m_actionGroup;
QMap<QString, QAction*> m_actions;
QMap<QAction*, QString> m_actionToType; // 反向映射
QMap<QString, DraggableToolButton*> m_buttons;
QString m_currentTool;
bool m_dragEnabled = true;
};
#endif
#endif // ENHANCEDTOOLBAR_H

View File

@ -0,0 +1,54 @@
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
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_library(pluginManager SHARED
MANUAL_FINALIZATION
${PLUGINMANAGER_HEADER_FILES}
${PLUGINMANAGER_SOURCE_FILES}
)
else()
add_library(pluginManager SHARED
${PLUGINMANAGER_HEADER_FILES}
${PLUGINMANAGER_SOURCE_FILES}
)
endif()
target_link_libraries(pluginManager PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
target_link_libraries(pluginManager PRIVATE Qt6::Xml)
target_link_libraries(pluginManager PRIVATE Qt6::Network)
target_link_libraries(pluginManager PRIVATE Qt6::Sql ${PostgreSQL_LIBRARIES})
option(BUILD_SHARED_LIBS "Build as shared library" ON)
target_include_directories(pluginManager PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_compile_definitions(pluginManager
PUBLIC
DIAGRAM_DESIGNER_SHARED
PRIVATE
DIAGRAM_DESIGNER_EXPORTS
#QT_NO_KEYWORDS
)

View File

@ -0,0 +1,60 @@
// genericPluginAdapter.h
#pragma once
#include "pluginCommon/iPluginAdapter.h"
#include <QObject>
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);
};

View File

@ -0,0 +1,57 @@
// pluginManager.h
#pragma once
#include "export.hpp"
#include "../common/include/pluginCommon/iCanvasItem.h"
#include "../common/include/pluginCommon/iPlugin.h"
#include <QObject>
class DIAGRAM_DESIGNER_PUBLIC PluginManager : public QObject
{
Q_OBJECT
public:
explicit PluginManager(QObject *parent = nullptr);
virtual ~PluginManager();
// 单例模式
static PluginManager* instance();
// 插件管理
bool loadPlugin(const QString &filePath);
bool unloadPlugin(const QString &pluginId);
void loadAllPlugins(const QString &directory);
// 插件目录管理
void addPluginDirectory(const QString &dir);
void setPluginDirectories(const QStringList &dirs);
QStringList pluginDirectories() const;
// 创建原始插件项
ICanvasItem* createItem(const QString &shapeId);
// 查询接口
QStringList availableShapes() const;
bool contains(const QString &shapeId) const;
ShapeDescriptor shapeDescriptor(const QString &shapeId) const;
QIcon shapeIcon(const QString &shapeId) const;
// 插件信息
PluginDescriptor pluginDescriptor(const QString &pluginId) const;
QStringList loadedPlugins() const;
// 内置形状注册
void registerBuiltinShape(const QString &shapeId,
const QString &name,
std::function<ICanvasItem*()> creator,
const QString &iconPath = QString());
signals:
void pluginLoaded(const PluginDescriptor &descriptor);
void pluginUnloaded(const QString &pluginId);
void shapesChanged();
private:
class Private;
QScopedPointer<Private> d;
};

View File

@ -0,0 +1,200 @@
// genericPluginAdapter.cpp
#include "genericPluginAdapter.h"
#include "pluginCommon/ICanvasItem.h"
#include <QDebug>
#include <QPainterPath>
#include <QVariantMap>
GenericPluginAdapter::GenericPluginAdapter(ICanvasItem *pluginItem, QObject *parent)
: IPluginAdapter(parent)
, m_pluginItem(pluginItem)
{
if (!m_pluginItem) {
qWarning() << "GenericPluginAdapter: pluginItem is null!";
return;
}
connectSignals();
updateCache();
qDebug() << "GenericPluginAdapter created for plugin:" << m_pluginItem->typeId();
}
GenericPluginAdapter::~GenericPluginAdapter()
{
if (m_pluginItem) {
m_pluginItem->deleteLater();
}
}
QString GenericPluginAdapter::pluginType() const
{
return m_pluginItem ? m_pluginItem->typeId() : QString();
}
QRectF GenericPluginAdapter::bounds() const
{
return m_cachedBounds;
}
void GenericPluginAdapter::setBounds(const QRectF &bounds)
{
if (m_pluginItem && bounds.isValid()) {
m_pluginItem->setBounds(bounds);
}
}
void GenericPluginAdapter::paint(QPainter *painter, const QRectF &bounds)
{
if (m_pluginItem && painter) {
m_pluginItem->draw(painter, bounds);
}
}
QPainterPath GenericPluginAdapter::shape() const
{
// 返回简单的矩形路径
QPainterPath path;
path.addRect(m_cachedBounds);
return path;
}
QVariant GenericPluginAdapter::property(const QString &key) const
{
return m_pluginItem ? m_pluginItem->property(key) : QVariant();
}
void GenericPluginAdapter::setProperty(const QString &key, const QVariant &value)
{
if (m_pluginItem) {
m_pluginItem->setProperty(key, value);
}
}
void GenericPluginAdapter::move(const QPointF &delta)
{
if (m_pluginItem && !delta.isNull()) {
QRectF bounds = m_pluginItem->bounds();
bounds.translate(delta);
m_pluginItem->setBounds(bounds);
}
}
void GenericPluginAdapter::resize(const QRectF &newBounds)
{
setBounds(newBounds);
}
bool GenericPluginAdapter::isSelected() const
{
return m_selected;
}
void GenericPluginAdapter::setSelected(bool selected)
{
if (m_selected != selected) {
m_selected = selected;
emit selectionChanged(selected);
}
}
QVariantMap GenericPluginAdapter::saveState() const
{
QVariantMap state;
if (!m_pluginItem) {
return state;
}
// 保存基本信息
state["type"] = m_pluginItem->typeId();
state["selected"] = m_selected;
// 保存几何信息
QRectF bounds = m_pluginItem->bounds();
state["x"] = bounds.x();
state["y"] = bounds.y();
state["width"] = bounds.width();
state["height"] = bounds.height();
// 保存属性
QVariantMap properties;
// 这里可以保存插件的关键属性
// 例如properties["fillColor"] = m_pluginItem->property("fillColor");
state["properties"] = properties;
return state;
}
bool GenericPluginAdapter::loadState(const QVariantMap &state)
{
if (!m_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()
);
m_pluginItem->setBounds(bounds);
}
// 加载选择状态
if (state.contains("selected")) {
setSelected(state["selected"].toBool());
}
// 加载属性
if (state.contains("properties")) {
QVariantMap properties = state["properties"].toMap();
for (auto it = properties.begin(); it != properties.end(); ++it) {
m_pluginItem->setProperty(it.key(), it.value());
}
}
return true;
}
ICanvasItem* GenericPluginAdapter::pluginItem() const
{
return m_pluginItem;
}
void GenericPluginAdapter::updateCache()
{
if (m_pluginItem) {
m_cachedBounds = m_pluginItem->bounds();
}
}
void GenericPluginAdapter::connectSignals()
{
if (!m_pluginItem) {
return;
}
connect(m_pluginItem, &ICanvasItem::boundsChanged,
this, &GenericPluginAdapter::onPluginBoundsChanged);
connect(m_pluginItem, &ICanvasItem::propertyChanged,
this, &GenericPluginAdapter::onPluginPropertyChanged);
}
void GenericPluginAdapter::onPluginBoundsChanged(const QRectF &newBounds)
{
m_cachedBounds = newBounds;
emit boundsChanged(newBounds);
emit adapterChanged();
}
void GenericPluginAdapter::onPluginPropertyChanged(const QString &key, const QVariant &value)
{
emit propertyChanged(key, value);
emit adapterChanged();
}

View File

@ -0,0 +1,388 @@
//pluginManager.cpp
#include "pluginManager/include/pluginManager.h"
//#include "common/include/pluginCommon/iPlugin.h"
#include <QPluginLoader>
#include <QDir>
#include <QFileInfo>
#include <QDebug>
#include <QMutex>
#include <QMutexLocker>
// 私有实现
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<QString, PluginInfo*> plugins; // pluginId -> PluginInfo*
QMap<QString, QString> shapeToPlugin; // shapeId -> pluginId
QMap<QString, ShapeDescriptor> shapeDescriptors; // shapeId -> descriptor
// 内置形状
QMap<QString, std::function<ICanvasItem*()>> builtinCreators;
QMap<QString, ShapeDescriptor> 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<IPlugin*>(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<ShapeDescriptor> 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<ICanvasItem*()> 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();
}

View File

@ -2,12 +2,6 @@
#include "configToolBar.h"
#include <QDebug>
ConfigToolBar::ConfigToolBar(const QString &title, QWidget *parent)
: EnhancedToolBar(title, parent)
{
loadDefaultTools();
}
ConfigToolBar::ConfigToolBar(QWidget *parent)
: EnhancedToolBar(parent)
{
@ -23,7 +17,7 @@ bool ConfigToolBar::loadToolsFromConfig(const QString &configFile)
}
// 清空现有工具
clearTools();
//clearTools();
// 从配置添加工具
QList<ToolInfo> tools = m_config.getAllTools();
@ -37,8 +31,6 @@ bool ConfigToolBar::loadToolsFromConfig(const QString &configFile)
void ConfigToolBar::loadDefaultTools()
{
// 添加一些基本工具
addTool("select", "选择", QIcon(":/icons/select.png"));
addTool("line", "直线", QIcon(":/icons/line.png"));
addTool("rect", "矩形", QIcon(":/icons/rect.png"));
addTool("circle", "圆形", QIcon(":/icons/circle.png"));
addTool("image", "图像", QIcon(":/images/element/icon_image.png"));
addTool("text", "文本", QIcon(":/images/element/icon_text.png"));
}

View File

@ -0,0 +1,76 @@
// draggabletoolbutton.cpp
#include "draggabletoolbutton.h"
#include <QMouseEvent>
#include <QApplication>
#include <QDebug>
DraggableToolButton::DraggableToolButton(QWidget *parent)
: QToolButton(parent)
, m_dragEnabled(true)
, m_isDragging(false)
{
setMouseTracking(true);
}
void DraggableToolButton::setDragEnabled(bool enabled)
{
m_dragEnabled = enabled;
}
bool DraggableToolButton::dragEnabled() const
{
return m_dragEnabled;
}
void DraggableToolButton::setToolData(const QString &data)
{
m_toolData = data;
}
QString DraggableToolButton::toolData() const
{
return m_toolData;
}
void DraggableToolButton::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && m_dragEnabled) {
m_pressPos = event->pos();
m_isDragging = false;
}
// 不调用基类,完全自己处理
event->accept();
}
void DraggableToolButton::mouseMoveEvent(QMouseEvent *event)
{
if (!m_dragEnabled || !(event->buttons() & Qt::LeftButton)) {
event->ignore();
return;
}
// 检查是否达到拖拽阈值
int moveDist = (event->pos() - m_pressPos).manhattanLength();
if (moveDist >= QApplication::startDragDistance()) {
if (!m_isDragging) {
m_isDragging = true;
emit dragStarted(m_toolData, event->globalPosition().toPoint());
}
}
event->accept();
}
void DraggableToolButton::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
if (!m_isDragging) {
// 没有拖拽,是点击
emit clicked();
}
m_isDragging = false;
}
event->accept();
}

View File

@ -1,108 +1,106 @@
// EnhancedToolBar.cpp
#include "enhancedToolBar.h"
#include <QAction>
#include "enhancedtoolbar.h"
#include "draggabletoolbutton.h"
#include <QHBoxLayout>
#include <QMimeData>
#include <QDrag>
#include <QPainter>
#include <QApplication>
#include <QDebug>
EnhancedToolBar::EnhancedToolBar(const QString &title, QWidget *parent)
: QToolBar(title, parent)
, m_currentTool("")
{
init();
}
EnhancedToolBar::EnhancedToolBar(QWidget *parent)
: QToolBar(parent)
, m_currentTool("")
, m_dragEnabled(true)
{
init();
}
void EnhancedToolBar::init()
{
// 设置工具栏属性
setIconSize(QSize(32, 32));
setToolButtonStyle(Qt::ToolButtonIconOnly);
setMovable(true);
setFloatable(true);
setAllowedAreas(Qt::AllToolBarAreas);
// 创建互斥的动作组
m_actionGroup = new QActionGroup(this);
m_actionGroup->setExclusive(true);
// 连接信号
connect(this, &QToolBar::actionTriggered,
this, &EnhancedToolBar::onActionTriggered);
}
QAction* EnhancedToolBar::createAction(const QString &toolType,
const QString &toolName,
const QIcon &icon)
{
QAction *action = new QAction(icon, toolName, this);
action->setCheckable(true);
action->setData(toolType);
action->setToolTip(toolName);
return action;
}
void EnhancedToolBar::addTool(const QString &toolType, const QString &toolName,
const QIcon &icon)
{
if (m_actions.contains(toolType)) {
return; // 已存在
if (m_buttons.contains(toolType)) {
return;
}
QAction *action = createAction(toolType, toolName, icon);
// 创建自定义按钮
DraggableToolButton *button = new DraggableToolButton(this);
button->setIcon(icon);
button->setIconSize(iconSize());
button->setText(toolName);
button->setToolTip(toolName);
button->setCheckable(true);
button->setToolData(toolType);
button->setDragEnabled(m_dragEnabled);
m_actionGroup->addAction(action);
addAction(action);
m_actions[toolType] = action;
m_actionToType[action] = toolType;
// 连接信号
connect(button, &DraggableToolButton::clicked,
this, &EnhancedToolBar::onToolButtonClicked);
connect(button, &DraggableToolButton::dragStarted,
this, &EnhancedToolBar::onToolButtonDragStarted);
// 如果没有当前工具,自动选择第一个工具
// 添加到工具栏
addWidget(button);
m_buttons[toolType] = button;
// 如果没有当前工具,设置第一个为当前
if (m_currentTool.isEmpty()) {
setCurrentTool(toolType);
}
emit toolAdded(toolType);
}
void EnhancedToolBar::removeTool(const QString &toolType)
void EnhancedToolBar::onToolButtonClicked()
{
if (m_actions.contains(toolType)) {
QAction *action = m_actions[toolType];
removeAction(action);
m_actionGroup->removeAction(action);
m_actions.remove(toolType);
m_actionToType.remove(action);
action->deleteLater();
if (m_currentTool == toolType) {
m_currentTool = "";
}
emit toolRemoved(toolType);
DraggableToolButton *button = qobject_cast<DraggableToolButton*>(sender());
if (button) {
QString toolType = button->toolData();
setCurrentTool(toolType);
}
}
void EnhancedToolBar::setCurrentTool(const QString &toolType)
void EnhancedToolBar::onToolButtonDragStarted(const QString &toolData, const QPoint &globalPos)
{
if (toolType.isEmpty()) {
// 清除当前选择
if (m_actionGroup->checkedAction()) {
m_actionGroup->checkedAction()->setChecked(false);
}
m_currentTool = "";
emit toolSelected("");
if (m_dragEnabled) {
startDrag(toolData, globalPos);
}
else if (m_actions.contains(toolType)) {
m_actions[toolType]->setChecked(true);
m_currentTool = toolType;
emit toolSelected(toolType);
}
void EnhancedToolBar::startDrag(const QString &toolType, const QPoint &globalPos)
{
DraggableToolButton *button = m_buttons.value(toolType);
if (!button) {
return;
}
QString toolName = button->text();
QIcon icon = button->icon();
qDebug() << "开始拖拽:" << toolType << toolName;
// 创建MIME数据
QMimeData *mimeData = new QMimeData();
mimeData->setText(toolName);
mimeData->setData("application/x-tooltype", toolType.toUtf8());
// 创建拖拽对象
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
// 创建预览图像
if (!icon.isNull()) {
QPixmap pixmap = icon.pixmap(32, 32);
drag->setPixmap(pixmap);
drag->setHotSpot(QPoint(16, 16));
}
// 发出信号
emit toolDragged(toolType, globalPos);
// 执行拖拽
Qt::DropAction result = drag->exec(Qt::CopyAction);
qDebug() << "拖拽完成,结果:" << result;
}
QString EnhancedToolBar::currentTool() const
@ -110,52 +108,38 @@ QString EnhancedToolBar::currentTool() const
return m_currentTool;
}
QString EnhancedToolBar::toolName(const QString &toolType) const
void EnhancedToolBar::setCurrentTool(const QString &toolType)
{
if (m_actions.contains(toolType)) {
return m_actions[toolType]->text();
}
return QString();
}
QIcon EnhancedToolBar::toolIcon(const QString &toolType) const
{
if (m_actions.contains(toolType)) {
return m_actions[toolType]->icon();
}
return QIcon();
}
QStringList EnhancedToolBar::availableTools() const
{
return m_actions.keys();
}
void EnhancedToolBar::clearTools()
{
for (auto it = m_actions.begin(); it != m_actions.end(); ++it) {
removeAction(it.value());
m_actionGroup->removeAction(it.value());
it.value()->deleteLater();
if (m_currentTool == toolType) {
return;
}
m_actions.clear();
m_actionToType.clear();
m_currentTool = "";
}
void EnhancedToolBar::addTools(const QList<QPair<QString, QString>> &tools)
{
for (const auto &tool : tools) {
addTool(tool.first, tool.second);
// 取消之前的选择
if (!m_currentTool.isEmpty() && m_buttons.contains(m_currentTool)) {
m_buttons[m_currentTool]->setChecked(false);
}
}
void EnhancedToolBar::onActionTriggered(QAction *action)
{
if (m_actionToType.contains(action)) {
QString toolType = m_actionToType[action];
// 设置新的选择
if (m_buttons.contains(toolType)) {
m_buttons[toolType]->setChecked(true);
m_currentTool = toolType;
emit toolSelected(toolType);
} else {
m_currentTool = "";
}
}
void EnhancedToolBar::setDragEnabled(bool enabled)
{
m_dragEnabled = enabled;
// 更新所有按钮
for (DraggableToolButton *button : m_buttons.values()) {
button->setDragEnabled(enabled);
}
}
bool EnhancedToolBar::dragEnabled() const
{
return m_dragEnabled;
}

View File

@ -25,7 +25,7 @@
#include "monitorPagesDlg.h"
#include "QDetailsView.h"
#include "baseDockWidget.h"
#include "enhancedToolBar.h"
#include "configToolBar.h"
#include "QDetailsView.h"
@ -83,12 +83,10 @@ void CMainWindow::moveEvent(QMoveEvent *event)
void CMainWindow::initializeDockUi()
{
EnhancedToolBar *toolBar = new EnhancedToolBar("绘图工具", this);
ConfigToolBar* toolBar = new ConfigToolBar(this);
addToolBar(Qt::TopToolBarArea, toolBar);
toolBar->addTool("image", "图像", QIcon(":/images/element/icon_image.png"));
toolBar->addTool("text", "文本", QIcon(":/images/element/icon_text.png"));
toolBar->setIconSize(QSize(24, 24));
toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
//toolBar->setIconSize(QSize(24, 24));
//toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
m_pElectricElementsBox = new ElectricElementsBox();
/*m_pElectricElementsBox->initial();
@ -114,21 +112,21 @@ void CMainWindow::initializeDockUi()
diagramDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea);
this->addDockWidget(Qt::LeftDockWidgetArea,diagramDock);
m_pMonitorItemsDlg = new MonitorItemsDlg(this);
m_pMonitorItemsDock = new BaseDockWidget(QString::fromWCharArray(L"当前设备列表"),this);
m_pMonitorItemsDock->setWidget(m_pMonitorItemsDlg);
m_pMonitorItemsDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea);
this->addDockWidget(Qt::RightDockWidgetArea,m_pMonitorItemsDock);
//m_pMonitorItemsDlg = new MonitorItemsDlg(this);
//m_pMonitorItemsDock = new BaseDockWidget(QString::fromWCharArray(L"当前设备列表"),this);
//m_pMonitorItemsDock->setWidget(m_pMonitorItemsDlg);
//m_pMonitorItemsDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea);
//this->addDockWidget(Qt::RightDockWidgetArea,m_pMonitorItemsDock);
m_pMonitorPagesDlg = new MonitorPagesDlg(this);
m_pMonitorPagesDock = new BaseDockWidget(QString::fromWCharArray(L"监控列表"),this);
m_pMonitorPagesDock->setWidget(m_pMonitorPagesDlg);
m_pMonitorPagesDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea);
m_pMonitorPagesDock->setMinimumSize(120,550);
this->addDockWidget(Qt::RightDockWidgetArea,m_pMonitorPagesDock);
//m_pMonitorPagesDlg = new MonitorPagesDlg(this);
//m_pMonitorPagesDock = new BaseDockWidget(QString::fromWCharArray(L"监控列表"),this);
//m_pMonitorPagesDock->setWidget(m_pMonitorPagesDlg);
//m_pMonitorPagesDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea);
//m_pMonitorPagesDock->setMinimumSize(120,550);
//this->addDockWidget(Qt::RightDockWidgetArea,m_pMonitorPagesDock);
m_pMonitorItemsDock->hide();
m_pMonitorPagesDock->hide();
//m_pMonitorItemsDock->hide();
//m_pMonitorPagesDock->hide();
m_pDiagramCavas = new DiagramCavas(this);
m_pDiagramCavas->initial();
@ -186,13 +184,13 @@ void CMainWindow::initializeAction()
connect(m_pDiagramCavas,&DiagramCavas::createHMI,m_pDiagramView,&DiagramView::onNewHMICreated);
connect(m_pDiagramCavas,&DiagramCavas::updateHMI,m_pDiagramView,&DiagramView::onHMIUpdated);
connect(m_pDiagramCavas,&DiagramCavas::prepareUpdateItems,m_pMonitorItemsDlg,&MonitorItemsDlg::onUpdateItems);
connect(m_pDiagramCavas,&DiagramCavas::prepareSelectItems,m_pMonitorItemsDlg,&MonitorItemsDlg::onSelectItems);
connect(m_pDiagramCavas,&DiagramCavas::updateMonitorList,m_pMonitorPagesDlg,&MonitorPagesDlg::onMonitorCreated);
//connect(m_pDiagramCavas,&DiagramCavas::prepareUpdateItems,m_pMonitorItemsDlg,&MonitorItemsDlg::onUpdateItems);
//connect(m_pDiagramCavas,&DiagramCavas::prepareSelectItems,m_pMonitorItemsDlg,&MonitorItemsDlg::onSelectItems);
//connect(m_pDiagramCavas,&DiagramCavas::updateMonitorList,m_pMonitorPagesDlg,&MonitorPagesDlg::onMonitorCreated);
connect(m_pDiagramCavas,&DiagramCavas::createdMonitorItems,m_pMonitorItemsDlg,&MonitorItemsDlg::onMonitorCreated);
connect(m_pDiagramCavas,&DiagramCavas::updateMonitorTopology,m_pTopologyView,&TopologyView::onMonitorUpdate);
//connect(m_pDiagramCavas,&DiagramCavas::updateMonitorTopology,m_pTopologyView,&TopologyView::onMonitorUpdate);
connect(m_pMonitorPagesDlg,&MonitorPagesDlg::monitorSelected,m_pDiagramCavas,&DiagramCavas::onSignal_monitorSelected);
//connect(m_pMonitorPagesDlg,&MonitorPagesDlg::monitorSelected,m_pDiagramCavas,&DiagramCavas::onSignal_monitorSelected);
//connect(m_pMonitorPagesDlg,&MonitorPagesDlg::prepareSaveMonitor,m_pDiagramCavas,&DiagramCavas::onSignal_saveMonitor);
connect(ui->actionNew,&QAction::triggered,m_pDiagramCavas,&DiagramCavas::onSignal_addPage);
@ -217,13 +215,13 @@ void CMainWindow::initializeAction()
connect(_pActMonitor,&QAction::triggered,this,[&](){
if(!_pActMonitor->isChecked()){
_pActMonitor->setChecked(false);
m_pMonitorItemsDock->hide();
m_pMonitorPagesDock->hide();
//m_pMonitorItemsDock->hide();
//m_pMonitorPagesDock->hide();
}
else{
_pActMonitor->setChecked(true);
m_pMonitorItemsDock->show();
m_pMonitorPagesDock->show();
//m_pMonitorItemsDock->show();
//m_pMonitorPagesDock->show();
if(m_pDiagramCavas)
m_pDiagramCavas->updateMonitorListFromDB();