add HMI event config structure

This commit is contained in:
baiYue 2026-04-10 17:43:35 +08:00
parent 4203022e3a
commit c08fb50643
24 changed files with 1024 additions and 2 deletions

View File

@ -53,6 +53,7 @@ set(DIAGRAMCAVAS_HEADER_FILES
include/dataSourceDlg.h
include/createHMIdlg.h
include/propertyDialog.h
include/eventPropertyEditor.h
include/graphicsDataModel/baseModel.h
include/graphicsDataModel/fixedPortsModel.h
include/graphicsItem/graphicsItemGroup.h
@ -91,6 +92,7 @@ set(DIAGRAMCAVAS_HEADER_FILES
include/graphicsItem/functionModelItem/graphicsFunctionModelItem.h
include/graphicsItem/functionModelItem/electricFunctionModelSvgItemImage.h
include/graphicsItem/functionModelItem/electricFunctionModelItemText.h
include/graphicsItem/functionModelItem/graphicsEventContext.h
include/baseModelItem/electricBaseModelSvgItem.h
include/baseModelItem/electricBaseModelLineItem.h
@ -113,7 +115,16 @@ set(DIAGRAMCAVAS_HEADER_FILES
include/propertyType/dataSourceType.h
include/propertyType/PropertyTypeCustomization_CustomType.h
include/propertyType/propertyTypeCustomization_DataSourceType.h
include/propertyType/propertyTypeCustomization_ConfigEventData.h
include/propertyType/pannelColorGadget.h
include/propertyType/configEventData.h
include/evetConfig/eventExecutor.h
include/evetConfig/eventHandler.h
include/evetConfig/panelVisibilityEventHandler.h
include/evetConfig/scriptEventHandler.h
include/evetConfig/variableSetEventHandler.h
../common/include/httpInterface.h
../common/include/tools.h
../common/include/baseProperty.h
@ -242,6 +253,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES
source/propertyType/PropertyTypeCustomization_CustomType.cpp
source/propertyType/propertyTypeCustomization_DataSourceType.cpp
source/propertyType/propertyTypeCustomization_ConfigEventData.cpp
source/propertyType/pannelColorGadget.cpp
../common/source/httpInterface.cpp
../common/source/baseProperty.cpp

View File

@ -0,0 +1,132 @@
#pragma once
/*************************HMI事件组态**************************/
#include <QObject>
#include <QJsonObject>
#include <QVariant>
// 事件触发器类型
enum class TriggerType {
Click = 0,
DoubleClick,
RightClick,
HoverEnter,
HoverLeave,
PropertyChange,
Unknown
};
QString triggerTypeToString(TriggerType type) {
switch (type) {
case TriggerType::Click: return "click";
case TriggerType::DoubleClick: return "double_click";
case TriggerType::RightClick: return "right_click";
case TriggerType::HoverEnter: return "hover_enter";
case TriggerType::HoverLeave: return "hover_leave";
case TriggerType::PropertyChange: return "property_change";
default: return "unknown";
}
}
TriggerType stringToTriggerType(const QString& str) {
QMap<QString, TriggerType> mapping = {
{"click", TriggerType::Click},
{"double_click", TriggerType::DoubleClick},
{"right_click", TriggerType::RightClick},
{"hover_enter", TriggerType::HoverEnter},
{"hover_leave", TriggerType::HoverLeave},
{"property_change", TriggerType::PropertyChange}
};
return mapping.value(str, TriggerType::Unknown);
}
// 事件接口
class IConfigEvent {
public:
virtual ~IConfigEvent() = default;
virtual void execute() = 0;
virtual QString type() const = 0;
virtual QJsonObject toJson() const = 0;
virtual void fromJson(const QJsonObject& json) = 0;
virtual IConfigEvent* clone() const = 0;
};
// Panel可见性事件
class PanelVisibilityEvent : public IConfigEvent {
QString panelId;
bool visible = true;
public:
void setPanelId(const QString& id) { panelId = id; }
void setVisible(bool v) { visible = v; }
QString type() const override { return "panel_visibility"; }
void execute() override {
// 实现Panel控制逻辑
emit requestPanelControl(panelId, visible);
}
QJsonObject toJson() const override {
return {
{"type", type()},
{"panelId", panelId},
{"visible", visible}
};
}
void fromJson(const QJsonObject& json) override {
panelId = json["panelId"].toString();
visible = json["visible"].toBool();
}
IConfigEvent* clone() const override {
auto event = new PanelVisibilityEvent();
event->panelId = panelId;
event->visible = visible;
return event;
}
signals:
void requestPanelControl(const QString& panelId, bool visible);
};
// 变量赋值事件
class VariableAssignmentEvent : public IConfigEvent {
QString varName;
QVariant value;
public:
void setVariableName(const QString& name) { varName = name; }
void setValue(const QVariant& val) { value = val; }
QString type() const override { return "variable_assignment"; }
void execute() override {
// 变量赋值逻辑
emit requestVariableAssignment(varName, value);
}
QJsonObject toJson() const override {
return {
{"type", type()},
{"variable", varName},
{"value", value.toString()}
};
}
void fromJson(const QJsonObject& json) override {
varName = json["variable"].toString();
value = json["value"].toString();
}
IConfigEvent* clone() const override {
auto event = new VariableAssignmentEvent();
event->varName = varName;
event->value = value;
return event;
}
signals:
void requestVariableAssignment(const QString& name, const QVariant& value);
};

View File

@ -55,6 +55,8 @@ public:
int getCurMode(){return _curMode;}
void showPropertyDlg(); //加载运行时属性栏
void hidePropertyDlg();
void setHMIVisiblebyName(const QString& str,bool val); //通过名称打开对应HMI
signals:
void prepareUpdateItems(QList<HierarchyItem>,bool refresh);
void prepareSelectItems(QList<HierarchyItem>);

View File

@ -0,0 +1,256 @@
// eventpropertyeditor.h
#pragma once
#include <QDialog>
#include <QVBoxLayout>
#include <QListWidget>
#include <QDialogButtonBox>
#include <QComboBox>
#include <QLineEdit>
#include <QLabel>
#include <QPushButton>
#include <QStackedWidget>
#include <QFormLayout>
#include <QFileDialog>
#include "propertyType/configEventData.h"
class EventPropertyEditor : public QDialog {
Q_OBJECT
public:
EventPropertyEditor(const EventList& initialEvents, QWidget* parent = nullptr)
: QDialog(parent), m_events(initialEvents) {
setupUI();
loadEvents();
}
EventList getEvents() const { return m_events; }
private slots:
void onAddEvent() {
// 简化的事件添加对话框
QDialog dialog(this);
dialog.setWindowTitle("添加事件");
QVBoxLayout* mainLayout = new QVBoxLayout(&dialog);
QGridLayout* gridLayout = new QGridLayout();
mainLayout->addLayout(gridLayout);
int row = 0;
// 触发器选择
QComboBox* triggerCombo = new QComboBox();
triggerCombo->addItems({"click", "doubleClick", "rightClick", "hoverEnter", "hoverLeave"});
gridLayout->addWidget(new QLabel("触发器:"), row, 0);
gridLayout->addWidget(triggerCombo, row, 1);
row++;
// 事件类型选择
QComboBox* typeCombo = new QComboBox();
typeCombo->addItems({"showPanel", "setVariable", "runScript"});
gridLayout->addWidget(new QLabel("事件类型:"), row, 0);
gridLayout->addWidget(typeCombo, row, 1);
row++;
// 动态参数区域
QStackedWidget* paramStack = new QStackedWidget();
gridLayout->addWidget(paramStack, row, 0, 1, 2);
row++;
// 创建不同类型的参数页面
QWidget* showPanelPage = createShowPanelPage();
QWidget* setVariablePage = createSetVariablePage();
QWidget* runScriptPage = createRunScriptPage();
paramStack->addWidget(showPanelPage);
paramStack->setCurrentIndex(0);
paramStack->addWidget(setVariablePage);
paramStack->addWidget(runScriptPage);
// 连接类型变化信号
connect(typeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
paramStack, &QStackedWidget::setCurrentIndex);
QDialogButtonBox* buttons = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
mainLayout->addWidget(buttons);
connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
if (dialog.exec() == QDialog::Accepted) {
EventData event;
event.trigger = triggerCombo->currentText();
event.type = typeCombo->currentText();
// 根据事件类型获取参数
if (event.type == "showPanel") {
QLineEdit* panelIdEdit = showPanelPage->findChild<QLineEdit*>("panelIdEdit");
QComboBox* showCombo = showPanelPage->findChild<QComboBox*>("showCombo");
event.parameters["panelId"] = panelIdEdit->text();
event.parameters["show"] = showCombo->currentText().toLower() == "true";
event.description = QString("显隐面板: %1").arg(panelIdEdit->text());
} else if (event.type == "setVariable") {
QLineEdit* varNameEdit = setVariablePage->findChild<QLineEdit*>("varNameEdit");
QLineEdit* varValueEdit = setVariablePage->findChild<QLineEdit*>("varValueEdit");
event.parameters["variable"] = varNameEdit->text();
event.parameters["value"] = varValueEdit->text();
event.description = QString("设置变量: %1 = %2").arg(varNameEdit->text(), varValueEdit->text());
} else if (event.type == "runScript") {
QLineEdit* scriptPathEdit = runScriptPage->findChild<QLineEdit*>("scriptPathEdit");
QComboBox* scriptTypeCombo = runScriptPage->findChild<QComboBox*>("scriptTypeCombo");
event.parameters["script"] = scriptPathEdit->text();
event.parameters["type"] = scriptTypeCombo->currentText();
event.description = QString("执行脚本: %1").arg(scriptPathEdit->text());
}
m_events.addEvent(event);
updateEventList();
}
}
void onEditEvent() {
int row = m_eventList->currentRow();
if (row < 0 || row >= m_events.events.size()) return;
// 简化的编辑:删除后重新添加
m_events.events.removeAt(row);
onAddEvent();
}
void onDeleteEvent() {
int row = m_eventList->currentRow();
if (row >= 0 && row < m_events.events.size()) {
m_events.events.removeAt(row);
updateEventList();
}
}
private:
void setupUI() {
setWindowTitle("事件编辑器");
resize(500, 400);
QVBoxLayout* mainLayout = new QVBoxLayout(this);
// 事件列表
m_eventList = new QListWidget();
mainLayout->addWidget(m_eventList);
// 按钮
QHBoxLayout* btnLayout = new QHBoxLayout();
QPushButton* addBtn = new QPushButton("添加");
QPushButton* editBtn = new QPushButton("编辑");
QPushButton* deleteBtn = new QPushButton("删除");
btnLayout->addWidget(addBtn);
btnLayout->addWidget(editBtn);
btnLayout->addWidget(deleteBtn);
btnLayout->addStretch();
mainLayout->addLayout(btnLayout);
// 对话框按钮
QDialogButtonBox* dialogBtns = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
mainLayout->addWidget(dialogBtns);
// 连接信号
connect(addBtn, &QPushButton::clicked, this, &EventPropertyEditor::onAddEvent);
connect(editBtn, &QPushButton::clicked, this, &EventPropertyEditor::onEditEvent);
connect(deleteBtn, &QPushButton::clicked, this, &EventPropertyEditor::onDeleteEvent);
connect(dialogBtns, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(dialogBtns, &QDialogButtonBox::rejected, this, &QDialog::reject);
}
void loadEvents() {
updateEventList();
}
void updateEventList() {
m_eventList->clear();
for (const auto& event : m_events.events) {
QString text = QString("%1: %2")
.arg(event.trigger, event.description);
m_eventList->addItem(text);
}
}
// 创建"showPanel"类型参数的页面
QWidget* createShowPanelPage() {
QWidget* page = new QWidget();
QFormLayout* layout = new QFormLayout(page);
QLineEdit* panelIdEdit = new QLineEdit();
panelIdEdit->setObjectName("panelIdEdit");
panelIdEdit->setPlaceholderText("输入面板ID如: panel1");
QComboBox* showCombo = new QComboBox();
showCombo->setObjectName("showCombo");
showCombo->addItems({"true", "false"});
layout->addRow("面板ID:", panelIdEdit);
layout->addRow("显示/隐藏:", showCombo);
return page;
}
// 创建"setVariable"类型参数的页面
QWidget* createSetVariablePage() {
QWidget* page = new QWidget();
QFormLayout* layout = new QFormLayout(page);
QLineEdit* varNameEdit = new QLineEdit();
varNameEdit->setObjectName("varNameEdit");
varNameEdit->setPlaceholderText("输入变量名,如: isVisible");
QLineEdit* varValueEdit = new QLineEdit();
varValueEdit->setObjectName("varValueEdit");
varValueEdit->setPlaceholderText("输入变量值,如: true, false, 123");
layout->addRow("变量名:", varNameEdit);
layout->addRow("变量值:", varValueEdit);
return page;
}
// 创建"runScript"类型参数的页面
QWidget* createRunScriptPage() {
QWidget* page = new QWidget();
QFormLayout* layout = new QFormLayout(page);
QLineEdit* scriptPathEdit = new QLineEdit();
scriptPathEdit->setObjectName("scriptPathEdit");
scriptPathEdit->setPlaceholderText("输入脚本路径,如: scripts/init.js");
QPushButton* browseBtn = new QPushButton("浏览...");
QHBoxLayout* pathLayout = new QHBoxLayout();
pathLayout->addWidget(scriptPathEdit);
pathLayout->addWidget(browseBtn);
QComboBox* scriptTypeCombo = new QComboBox();
scriptTypeCombo->setObjectName("scriptTypeCombo");
scriptTypeCombo->addItems({"js", "py", "lua"});
layout->addRow("脚本路径:", pathLayout);
layout->addRow("脚本类型:", scriptTypeCombo);
// 可选:连接浏览按钮
connect(browseBtn, &QPushButton::clicked, this, [scriptPathEdit]() {
QString path = QFileDialog::getOpenFileName(nullptr, "选择脚本文件",
"", "脚本文件 (*.js *.py *.lua)");
if (!path.isEmpty()) {
scriptPathEdit->setText(path);
}
});
return page;
}
private:
EventList m_events;
QListWidget* m_eventList = nullptr;
};

View File

@ -0,0 +1,55 @@
#pragma once
/****************************
*
* *************************/
#include "eventHandler.h"
#include "propertyType/configEventData.h"
#include "graphicsItem/functionModelItem/graphicsFunctionModelItem.h"
#include "evetConfig/panelVisibilityEventHandler.h"
#include "evetConfig/scriptEventHandler.h"
#include "evetConfig/variableSetEventHandler.h"
class EventExecutor {
private:
QVector<QSharedPointer<EventHandler>> m_handlers;
public:
EventExecutor() {
// 注册默认处理器
registerDefaultHandlers();
}
// 注册处理器
void registerHandler(QSharedPointer<EventHandler> handler) {
m_handlers.append(handler);
}
// 执行事件
void execute(const EventData& event, GraphicsFunctionModelItem* item) {
for (const auto& handler : m_handlers) {
if (handler->canHandle(event.type)) {
handler->handle(event, item);
return;
}
}
// 如果没有找到处理器,使用默认处理
qWarning() << "No handler found for event type:" << event.type;
}
// 获取支持的处理器名称
QStringList supportedHandlers() const {
QStringList names;
for (const auto& handler : m_handlers) {
names.append(handler->handlerName());
}
return names;
}
private:
void registerDefaultHandlers() {
registerHandler(QSharedPointer<EventHandler>(new PanelVisibilityEventHandler()));
registerHandler(QSharedPointer<EventHandler>(new VariableSetEventHandler()));
registerHandler(QSharedPointer<EventHandler>(new ScriptEventHandler()));
}
};

View File

@ -0,0 +1,15 @@
#pragma once
/****************************
*
* *************************/
#include "propertyType/configEventData.h"
#include "graphicsItem/functionModelItem/graphicsFunctionModelItem.h"
#include "graphicsItem/functionModelItem/graphicsEventContext.h"
class EventHandler {
public:
virtual ~EventHandler() = default;
virtual bool canHandle(const QString& eventType) const = 0;
virtual void handle(const EventData& event, GraphicsFunctionModelItem* item) = 0;
virtual QString handlerName() const = 0;
};

View File

@ -0,0 +1,26 @@
#pragma once
/****************************
*
* *************************/
#include "eventHandler.h"
class PanelVisibilityEventHandler : public EventHandler {
public:
bool canHandle(const QString& eventType) const override {
return eventType == "showPanel" || eventType == "hidePanel";
}
void handle(const EventData& event, GraphicsFunctionModelItem* item) override {
QString panelId = event.parameters.value("panelId").toString();
bool show = event.type == "showPanel";
if (event.parameters.contains("show")) {
show = event.parameters.value("show").toBool();
}
if (auto context = item->eventContext()) {
context->emitPanelVisibilityChanged(panelId, show);
}
}
QString handlerName() const override { return "PanelVisibilityHandler"; }
};

View File

@ -0,0 +1,22 @@
#pragma once
/****************************
*
* *************************/
#include "eventHandler.h"
class ScriptEventHandler : public EventHandler {
public:
bool canHandle(const QString& eventType) const override {
return eventType == "runScript";
}
void handle(const EventData& event, GraphicsFunctionModelItem* item) override {
QString script = event.parameters.value("script").toString();
if (auto context = item->eventContext()) {
context->emitScriptExecuted(script);
}
}
QString handlerName() const override { return "ScriptHandler"; }
};

View File

@ -0,0 +1,23 @@
#pragma once
/****************************
*
* *************************/
#include "eventHandler.h"
class VariableSetEventHandler : public EventHandler {
public:
bool canHandle(const QString& eventType) const override {
return eventType == "setVariable";
}
void handle(const EventData& event, GraphicsFunctionModelItem* item) override {
QString varName = event.parameters.value("variable").toString();
QVariant value = event.parameters.value("value");
if (auto context = item->eventContext()) {
context->emitVariableSet(varName, value);
}
}
QString handlerName() const override { return "VariableSetHandler"; }
};

View File

@ -106,6 +106,8 @@ public:
void generateMonitorConfig(MonitorPanel*); //生成监控配置参数结构
void setMonitorPara(QMap<QUuid,QList<MonitorItemAttributeInfo>> map){m_monitorPara = map;}
QMap<QUuid,QList<MonitorItemAttributeInfo>>& getMonitorPara() {return m_monitorPara;}
void setMonitorParaRef(QMap<QUuid,QString> map){m_monitorParaRef = map;}
QMap<QUuid,QString>& getMonitorParaRef(){return m_monitorParaRef;}
void setMonitorRelation(QList<HierarchyItem> lst){m_lstMonitorRelation = lst;}
QList<HierarchyItem> getMonitorRelation() {return m_lstMonitorRelation;}
@ -167,6 +169,10 @@ public Q_SLOTS:
void onSignal_openBayManager();
void onDataTimerOut();
void onSelectionChanged();
void onPanelVisibilityChanged(const QString& panelName, bool show); //组态event 面板显隐
void onVariantSet(QString varName,QVariant val); //组态event 变量赋值
void onScriptExec(QString script); //组态event 脚本执行
private:
void addPortsToItem_json(PortState,QJsonArray,GraphicsBaseItem*); //将json格式的port添加到item
void autoSetModelName(GraphicsBaseModelItem*); //如果此页的工程模已被设置将projectName更新到item
@ -194,6 +200,7 @@ private:
ProjectIconSetting* m_projectIconSettingDlg;
BayManagerDlg* m_pBayManager;
QMap<QUuid,QList<MonitorItemAttributeInfo>> m_monitorPara; //监控参数
QMap<QUuid,QString> m_monitorParaRef; //监控参数的引用关系(文字item等) <itemId,connectPara>
QMap<int,QList<QPair<MonitorItemState,QString>>> m_monitorStateMap; //元件状态对照表 <type,<state,状态名>>
QMap<MonitorItemTypeStruct,QMap<MonitorItemStateStruct,MonitorItemDisplayInfo>> m_monitorDisplaySetting; //元件设置
QList<HierarchyItem> m_lstMonitorRelation; //监控item层级关系

View File

@ -0,0 +1,29 @@
#ifndef GRAPHICSEVENTCONTEXT_H
#define GRAPHICSEVENTCONTEXT_H
/***********组态事件信号**********/
#include <QObject>
// 具体的文实现
class GraphicsEventContext : public QObject {
Q_OBJECT
signals:
void panelVisibilityChanged(const QString& panelId, bool show);
void variableSet(const QString& varName, const QVariant& value);
void scriptExecuted(const QString& script);
public:
void emitPanelVisibilityChanged(const QString& panelId, bool show) {
emit panelVisibilityChanged(panelId, show);
}
void emitVariableSet(const QString& varName, const QVariant& value) {
emit variableSet(varName, value);
}
void emitScriptExecuted(const QString& script) {
emit scriptExecuted(script);
}
};
#endif

View File

@ -2,14 +2,18 @@
#define GRAPHICSFUNCTIONMODELITEM_H
#include "graphicsItem/graphicsBaseItem.h"
#include "propertyType/configEventData.h"
class BaseItemPropertyProxy;
class GraphicsEventContext;
class EventExecutor;
class GraphicsFunctionModelItem : public GraphicsProjectModelItem //功能模item
{
Q_OBJECT
public:
Q_PROPERTY(QMap<QString,bool> PropertyVisible READ getMap WRITE setMap)
Q_PROPERTY(EventList Events READ getEvents WRITE setEvents)
public:
GraphicsFunctionModelItem(QGraphicsItem *parent);
virtual ~GraphicsFunctionModelItem();
@ -19,10 +23,22 @@ public:
void setPropertyProxy(BaseItemPropertyProxy* p) {_pPropertyProxy = p;}
BaseItemPropertyProxy* getPropertyProxy() {return _pPropertyProxy;}
EventList getEvents() const;
void setEvents(const EventList& events);
void triggerEvents(const QString& triggerType);
QSharedPointer<GraphicsEventContext> eventContext() const {
return m_eventContext;
}
protected:
virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
void executeEvent(const EventData& event);
protected:
BaseItemPropertyProxy* _pPropertyProxy; //属性页代理
QVector<EventData> m_events; //HMI组态的事件
QSharedPointer<GraphicsEventContext> m_eventContext;
QSharedPointer<EventExecutor> m_eventExecutor;
};

View File

@ -639,6 +639,7 @@ protected:
virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
signals:
void ifExist(QUuid id,const QString&,int type,GraphicsProjectModelItem*);
void monitorParaRefSetted(QUuid id,QString connectPara); //参数引用被设置 引用者id,查询参数
public slots:
void onEditNameFinish(const QString&);
protected:

View File

@ -44,6 +44,9 @@ public:
//对para的序列化与反序列化
QJsonArray serializeParaToJsonArray(const QMap<QUuid, QList<MonitorItemAttributeInfo>>& data) const;
bool deserializeParaFromJsonArray(const QJsonArray& jsonArray,QMap<QUuid, QList<MonitorItemAttributeInfo>>& result);
//对paraRef的序列化与反序列化
QJsonArray serializeUuidStringMap(const QMap<QUuid, QString>& data);
bool deserializeUuidStringMap(const QJsonArray& jsonArray, QMap<QUuid, QString>& result);
//对displaySetiing的序列化与反序列化
QJsonArray serializeDisplayToJsonArray(const QMap<MonitorItemTypeStruct, QMap<MonitorItemStateStruct, MonitorItemDisplayInfo>>& data) const;
void deserializeDisplayFromJsonArray(const QJsonArray& jsonArray,QMap<MonitorItemTypeStruct, QMap<MonitorItemStateStruct, MonitorItemDisplayInfo>>& result);

View File

@ -0,0 +1,95 @@
#pragma once
#include <QString>
#include <QVariant>
#include <QVector>
#include <QJsonObject>
#include <QJsonArray>
#include <QMetaType>
/****************HMI事件编辑***************/
// 单个事件定义
struct EventData {
QString id; // 事件ID
QString trigger; // 触发器: click, doubleClick, rightClick, hoverEnter, hoverLeave
QString type; // 事件类型: showPanel, hidePanel, setVariable, runScript
QVariantMap parameters; // 事件参数
QString description; // 事件描述
EventData() {
id = QUuid::createUuid().toString(QUuid::WithoutBraces);
}
EventData(const QString& t, const QString& trig, const QVariantMap& params = {})
: trigger(trig), type(t), parameters(params) {
id = QUuid::createUuid().toString(QUuid::WithoutBraces);
}
QJsonObject toJson() const {
return {
{"id", id},
{"trigger", trigger},
{"type", type},
{"parameters", QJsonObject::fromVariantMap(parameters)},
{"description", description}
};
}
void fromJson(const QJsonObject& json) {
id = json["id"].toString();
trigger = json["trigger"].toString();
type = json["type"].toString();
parameters = json["parameters"].toObject().toVariantMap();
description = json["description"].toString();
}
};
static QDebug operator<<(QDebug debug, const EventData& it) {
return debug << it.id <<":"<<it.trigger<<":"<<it.type;
}
Q_DECLARE_METATYPE(EventData)
// 事件列表包装器
struct EventList {
QVector<EventData> events;
EventList() = default;
EventList(const QVector<EventData>& evts) : events(evts) {}
QJsonArray toJson() const {
QJsonArray arr;
for (const auto& event : events) {
arr.append(event.toJson());
}
return arr;
}
void fromJson(const QJsonArray& json) {
events.clear();
for (const auto& val : json) {
EventData event;
event.fromJson(val.toObject());
events.append(event);
}
}
// 添加事件
void addEvent(const EventData& event) {
events.append(event);
}
// 查找事件
EventData* findEvent(const QString& eventId) {
for (auto& event : events) {
if (event.id == eventId) {
return &event;
}
}
return nullptr;
}
};
static QDebug operator<<(QDebug debug, const EventList& it) {
return debug << it.events.size() ;
}
Q_DECLARE_METATYPE(EventList)

View File

@ -0,0 +1,16 @@
#ifndef PROPERTYTYPECUSTOMIZATION_CONFIGEVENTDATA_H
#define PROPERTYTYPECUSTOMIZATION_CONFIGEVENTDATA_H
#include "IPropertyTypeCustomization.h"
class EventPropertyEditor;
class PropertyTypeCustomization_ConfigEventData : public IPropertyTypeCustomization {
protected:
virtual void customizeHeaderRow(QPropertyHandle* inPropertyHandle, QQuickDetailsViewRowBuilder* inBuilder) override;
virtual void customizeChildren(QPropertyHandle* inPropertyHandle, QQuickDetailsViewLayoutBuilder* inBuilder) override;
private:
EventPropertyEditor* _pDlg = nullptr;
};
#endif // PROPERTYTYPECUSTOMIZATION_CONFIGEVENTDATA_H

View File

@ -48,6 +48,7 @@ public:
//==========================组态图拓扑相关===================================
PowerEntity* createDiagram(const QString& id,const QString& name,ModelFunctionType tpe = ModelFunctionType::ProjectModel); //单独创建组态图
PowerEntity* findDiagram(const QString& id,ModelFunctionType tpe = ModelFunctionType::ProjectModel) const;
PowerEntity* findDiagramByName(const QString& name,ModelFunctionType tpe = ModelFunctionType::ProjectModel) const;
bool deleteDiagram(const QString& id,ModelFunctionType tpe = ModelFunctionType::ProjectModel);
public:

View File

@ -30,6 +30,7 @@
#include "QQuickDetailsViewMananger.h"
#include "propertyType/propertyTypeCustomization_DataSourceType.h"
#include "propertyType/PropertyTypeCustomization_ConfigEventData.h"
#include "propertyType/dataSourceType.h"
#include "basePannelPropertyProxy.h"
@ -158,6 +159,7 @@ void DiagramCavas::initial()
_structDataPreviewDlg->loadData();
QQuickDetailsViewManager::Get()->registerPropertyTypeCustomization<DataSourceType, PropertyTypeCustomization_DataSourceType>();
QQuickDetailsViewManager::Get()->registerPropertyTypeCustomization<EventList, PropertyTypeCustomization_ConfigEventData>();
_createHMIDlg = new CreateHMIdlg(this);
connect(_createHMIDlg,&CreateHMIdlg::createHMI,this,&DiagramCavas::onSignal_createHMIClicked);
@ -223,6 +225,20 @@ void DiagramCavas::hidePropertyDlg()
_pPropertyDlg->hide();
}
void DiagramCavas::setHMIVisiblebyName(const QString& str,bool val)
{
PowerEntity* pEntity = TopologyManager::instance().findDiagramByName(str,ModelFunctionType::RuntimeModel);
if(pEntity)
{
if(val) //显示
onSignal_loadMonitor(pEntity);
else{
if(m_mapMonitorPanel.contains(str))
m_mapMonitorPanel[str].first->hide();
}
}
}
void DiagramCavas::onSignal_addDrawingPanel(PowerEntity* pItem,DiagramMode mode,QString parent)
{
if(mode == DM_run){

View File

@ -54,6 +54,7 @@
#include "baseItemPropertyProxy.h"
#include "common/core_model/types.h"
#include "graphicsItem/pluginSvgItemWrapper.h"
#include "graphicsItem/functionModelItem/graphicsEventContext.h"
bool FixedPortsModel::_dataInitialised = false;
@ -241,6 +242,12 @@ GraphicsFunctionModelItem* FixedPortsModel::addGraphicItem(QUuid id,QString name
item->bindProperty(pro); //绑定模型
//item->updateByProperty(); //使用模型更新自身
item->setHandle(this);
connect(item,&GraphicsFunctionModelItem::monitorParaRefSetted,this,[&](QUuid id,QString para){
m_monitorParaRef[id] = para;
});
connect(item->eventContext().data(),&GraphicsEventContext::panelVisibilityChanged,this,&FixedPortsModel::onPanelVisibilityChanged);
connect(item->eventContext().data(),&GraphicsEventContext::variableSet,this,&FixedPortsModel::onVariantSet);
connect(item->eventContext().data(),&GraphicsEventContext::scriptExecuted,this,&FixedPortsModel::onScriptExec);
_graphicItem.insert(id,item);
if(name.isEmpty()){ //如果不给名称则给个默认值
pro->setName("item_"+QString::number(_graphicItem.size()));
@ -789,6 +796,9 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he
}
}
});
connect(item->eventContext().data(),&GraphicsEventContext::panelVisibilityChanged,this,&FixedPortsModel::onPanelVisibilityChanged);
connect(item->eventContext().data(),&GraphicsEventContext::variableSet,this,&FixedPortsModel::onVariantSet);
connect(item->eventContext().data(),&GraphicsEventContext::scriptExecuted,this,&FixedPortsModel::onScriptExec);
}
return pro->name();
}
@ -981,6 +991,9 @@ QString FixedPortsModel::addConnectLline(QUuid lineId,QUuid srcId,QUuid destId,Q
pItem->setPropertyProxy(pProxy);
addNodeItem(pItem->itemId(),pItem);
pItem->bindProperty(pPro);
connect(pItem->eventContext().data(),&GraphicsEventContext::panelVisibilityChanged,this,&FixedPortsModel::onPanelVisibilityChanged);
connect(pItem->eventContext().data(),&GraphicsEventContext::variableSet,this,&FixedPortsModel::onVariantSet);
connect(pItem->eventContext().data(),&GraphicsEventContext::scriptExecuted,this,&FixedPortsModel::onScriptExec);
}
return pPro->name();
@ -1754,6 +1767,21 @@ void FixedPortsModel::onSelectionChanged()
}
}
void FixedPortsModel::onPanelVisibilityChanged(const QString& panelName, bool show)
{
_cavas->setHMIVisiblebyName(panelName,show);
}
void FixedPortsModel::onVariantSet(QString varName,QVariant val)
{
}
void FixedPortsModel::onScriptExec(QString script)
{
}
void FixedPortsModel::startHttpRequest()
{
if(_timer)
@ -1853,6 +1881,27 @@ void FixedPortsModel::updateMonitor(QMap<QString,QMap<quint64,double>> data)
}
}
}
// 构建查找表
QHash<QString, const MonitorItemAttributeInfo*> connectParaLookup;
for (const auto& [uuid, items] : m_monitorPara.asKeyValueRange()) {
for (const MonitorItemAttributeInfo& item : items) {
if (!item.sConnectPara.isEmpty()) {
connectParaLookup.insert(item.sConnectPara, &item);
}
}
}
// 遍历m_monitorParaRef
for (const auto& [uuid, refValue] : m_monitorParaRef.asKeyValueRange()) {
if (auto graphicIt = _graphicItem.find(uuid); graphicIt != _graphicItem.end()) {
if (auto pItem = dynamic_cast<ElectricFunctionModelItemText*>(*graphicIt)) { //如果是文字对象
if (auto itemIt = connectParaLookup.find(refValue); itemIt != connectParaLookup.end()) {
const MonitorItemAttributeInfo& matchedItem = *itemIt.value();
pItem->setText(QString::number(matchedItem.mapValue.size()?matchedItem.mapValue.last():0));
}
}
}
}
}
void FixedPortsModel::assignMeasureSymmetry(QMap<QString, MeasurementInfo>& measurementMap)
@ -2511,6 +2560,11 @@ void FixedPortsModel::startAcceptData()
}
}
for(auto& paraRef:m_monitorParaRef){ //如果normalItem中未选择该属性textItem引用了该属性追加数据请求
if(!lstTarget.contains(paraRef))
lstTarget.append(paraRef);
}
QJsonObject obj; //构建开始请求
obj["action"] = "start";
QJsonArray arrMeasure;

View File

@ -2,12 +2,15 @@
#include "baseProperty.h"
#include "graphicsDataModel/fixedPortsModel.h"
#include "baseItemPropertyProxy.h"
#include "graphicsItem/functionModelItem/graphicsEventContext.h"
#include "evetConfig/eventExecutor.h"
GraphicsFunctionModelItem::GraphicsFunctionModelItem(QGraphicsItem *parent)
: GraphicsProjectModelItem(parent)
,_pPropertyProxy(nullptr)
{
m_eventContext = QSharedPointer<GraphicsEventContext>::create();
m_eventExecutor = QSharedPointer<EventExecutor>(new EventExecutor());
}
GraphicsFunctionModelItem::~GraphicsFunctionModelItem()
@ -43,13 +46,35 @@ void GraphicsFunctionModelItem::setMap(QMap<QString,bool> boolMap)
}
}
EventList GraphicsFunctionModelItem::getEvents() const
{
return EventList(m_events);
}
void GraphicsFunctionModelItem::setEvents(const EventList& events)
{
m_events = events.events;
}
void GraphicsFunctionModelItem::triggerEvents(const QString& triggerType)
{
for (const auto& event : m_events) {
if (event.trigger == triggerType) {
executeEvent(event);
}
}
}
void GraphicsFunctionModelItem::executeEvent(const EventData& event) {
m_eventExecutor->execute(event, this);
}
void GraphicsFunctionModelItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
}
/********************************功能模item组*************************************/
GraphicsFunctionModelGroup::GraphicsFunctionModelGroup(QGraphicsItem *parent)

View File

@ -705,6 +705,7 @@ DataSourceType GraphicsProjectModelItem::getDataSourceType() const
void GraphicsProjectModelItem::setDataSourceType(DataSourceType type)
{
_sourceType = type;
emit monitorParaRefSetted(getProperty()->uuid(),_sourceType.sPara);
}
QVariant GraphicsProjectModelItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value)

View File

@ -22,6 +22,7 @@
#include "dataBase.h"
#include "projectModelManager.h"
#include "diagramCavas.h"
#include "extraPropertyManager.h"
MonitorPanel::MonitorPanel(PowerEntity* pEntity,QWidget *parent,DiagramMode mode)
: BaseDrawingPanel(pEntity,parent,mode)
@ -225,6 +226,9 @@ QJsonObject MonitorPanel::getDiagramInfo()
auto para = serializeParaToJsonArray(_pModel->getMonitorPara()); //设定参数
obj["para"] = para;
auto paraRef = serializeUuidStringMap(_pModel->getMonitorParaRef());
obj["paraRef"] = paraRef;
auto settingArr = serializeDisplayToJsonArray(_pModel->getMonitorDisplaySetting()); //显示参数
obj["displaySetting"] = settingArr;
@ -372,6 +376,37 @@ void MonitorPanel::loadNodes(QJsonObject obj)
}
}
QMap<QString, ExtraProperty> mapExtra;
ExtraPropertyManager* pExtra = _pModel->getCavas()->getExtraPropertyManager();
if(pExtra){
mapExtra = pExtra->geAlltProperty();
}
QJsonArray paraRefArr = obj["paraRef"].toArray();
QMap<QUuid, QString> mapParaRef;
bool resParaRef = deserializeUuidStringMap(paraRefArr,mapParaRef);
if(resParaRef){
if(_pModel){
_pModel->setMonitorParaRef(mapParaRef);
auto pItems = _pModel->getGraphicItems();
for(auto& p:pItems){
auto pPro = p->getProperty();
if(pPro){
QString sConnectPara = mapParaRef.value(pPro->uuid());
for(auto& extra:mapExtra){
if(extra.connect_para == sConnectPara){
DataSourceType data;
data.sPara = sConnectPara;
data.sCode = extra.code;
p->setDataSourceType(data); //手动置回dataSource选中
break;
}
}
}
}
}
}
_pModel->updateItemPropertyVisibleLst(); //更新item属性visible引用列表
QJsonArray displayArr = obj["displaySetting"].toArray();
@ -958,6 +993,34 @@ bool MonitorPanel::deserializeParaFromJsonArray(const QJsonArray& jsonArray,
return true;
}
QJsonArray MonitorPanel::serializeUuidStringMap(const QMap<QUuid, QString>& data)
{
QJsonArray array;
for (auto it = data.constBegin(); it != data.constEnd(); ++it) {
QJsonObject obj;
obj["k"] = it.key().toString(); // k 表示 key
obj["v"] = it.value(); // v 表示 value
array.append(obj);
}
return array;
}
bool MonitorPanel::deserializeUuidStringMap(const QJsonArray& jsonArray, QMap<QUuid, QString>& result)
{
result.clear();
for (const QJsonValue& val : jsonArray) {
if (!val.isObject()) continue;
QJsonObject obj = val.toObject();
QUuid uuid = QUuid::fromString(obj["k"].toString());
if (!uuid.isNull()) {
result[uuid] = obj["v"].toString();
}
}
return true;
}
QJsonArray MonitorPanel::serializeDisplayToJsonArray(const QMap<MonitorItemTypeStruct, QMap<MonitorItemStateStruct, MonitorItemDisplayInfo>>& data) const
{

View File

@ -0,0 +1,128 @@
#include "propertyType/propertyTypeCustomization_ConfigEventData.h"
#include "QQuickDetailsViewLayoutBuilder.h"
#include "QPropertyHandle.h"
#include <QMetaType>
#include <QObject>
#include "propertyType/configEventData.h"
#include "QQuickFunctionLibrary.h"
#include "eventPropertyEditor.h"
void PropertyTypeCustomization_ConfigEventData::customizeHeaderRow(QPropertyHandle* inPropertyHandle, QQuickDetailsViewRowBuilder* inBuilder)
{
auto editorSlot = inBuilder->makeNameValueSlot();
inPropertyHandle->setupNameEditor(editorSlot.first);
auto buttonItem = inBuilder->setupItem(editorSlot.second, R"(
import QtQuick
import QtQuick.Controls
Item {
// 仅设置隐式大小
implicitWidth: 180
implicitHeight: 25
// 自定义信号
signal customButtonClicked()
// 让父容器控制宽度
anchors.left: parent ? parent.left : undefined
anchors.right: parent ? parent.right : undefined
// 设置文本的函数
function setDisplayText(newText) {
displayText.text = newText;
}
// 获取当前文本的函数
function getDisplayText() {
return displayText.text;
}
// 右侧功能按钮
Button {
id: button
width: 25
height: 25
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
}
text: "..."
font.pixelSize: 9
font.bold: true
// 自定义按钮样式
background: Rectangle {
color: button.down ? "#d0d0d0" :
button.hovered ? "#e0e0e0" : "#f0f0f0"
border.color: "#888"
border.width: 1
radius: 4
}
// 点击时触发自定义信号
onClicked: {
parent.customButtonClicked()
}
}
// 文字显示区域
Rectangle {
id: textArea
anchors {
left: parent.left
right: button.left
rightMargin: 5
verticalCenter: parent.verticalCenter
}
height: 25
border.color: "#ccc"
border.width: 1
radius: 4
Text {
id: displayText
anchors.fill: parent
anchors.margins: 5
text: "datasource"
color: "#333"
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
}
}
)");
EventList curVal = inPropertyHandle->getVar().value<EventList>();
QStringList lstEvent;
for(auto& data:curVal.events){
lstEvent.append(data.trigger);
}
QVariant curStr = QVariant(lstEvent.join(";"));
QMetaObject::invokeMethod(buttonItem, "setDisplayText",
Q_ARG(QVariant, curStr));
QQuickFunctionLibrary::connect(buttonItem, SIGNAL(customButtonClicked()), inPropertyHandle, [inPropertyHandle,buttonItem]() {
EventList customType = inPropertyHandle->getVar().value<EventList>();
EventPropertyEditor dlg(customType);
if (dlg.exec() == QDialog::Accepted) {
EventList curData = dlg.getEvents();
inPropertyHandle->setVar(QVariant::fromValue(curData));
QStringList lstEvent;
for(auto& data:curData.events){
lstEvent.append(data.trigger);
}
QVariant curStr = QVariant(lstEvent.join(";"));
QMetaObject::invokeMethod(buttonItem, "setDisplayText",
Q_ARG(QVariant, curStr));
}
});
}
void PropertyTypeCustomization_ConfigEventData::customizeChildren(QPropertyHandle* inPropertyHandle, QQuickDetailsViewLayoutBuilder* inBuilder)
{
}

View File

@ -771,6 +771,30 @@ PowerEntity* TopologyManager::findDiagram(const QString& id,ModelFunctionType fu
return nullptr;
}
PowerEntity* TopologyManager::findDiagramByName(const QString& name,ModelFunctionType funType) const
{
if(funType == ModelFunctionType::ProjectModel){
for(auto& pEntity:m_diagrams){
if(pEntity->name() == name)
return pEntity;
}
}
else if(funType == ModelFunctionType::BaseModel){
for(auto& pEntity:m_baseDiagrams){
if(pEntity->name() == name)
return pEntity;
}
}
else if(funType == ModelFunctionType::RuntimeModel){
for(auto& pEntity:m_monitorDiagrams){
if(pEntity->name() == name)
return pEntity;
}
}
return nullptr;
}
bool TopologyManager::deleteDiagram(const QString& id,ModelFunctionType funType)
{
if(funType == ModelFunctionType::ProjectModel){