#include "WindowAppPouFrame.h" #include "WindowAppPouScene.h" #include "DialogNewVariable.h" #include "GvlManager.h" #include "PouManager.h" #include "VPCommand.h" //template //void SetValue(VALUE& value, T& t) //{ // value.Ptr = (void**)&t; // // qDebug() << "ForTest valueIn: " << *(int*)value.Ptr; // // For Test // *(int*)value.Ptr = 40; // // 此时valueIn的值变为40 // qDebug() << "ForTest valueIn: " << *(int*)value.Ptr; //} WindowAppPouFrame::WindowAppPouFrame(const QString& strTitle, QWidget* parent) : QWidget(parent) , m_strTitle(strTitle) , actionUndo(nullptr) , actionRedo(nullptr) { ui.setupUi(this); // 2022-3-2增加,创建变量表格的同时就顺便创建对应的局部变量组(空) g_pGvlManager->addNewGroup(m_strTitle, TOOL_TYPE::TOOL_TYPE_LOCAL_VARIABLE, GVL_MODE::GVL_BASIC); // 初始化图像子界面工具栏 this->initPouToolbar(); // 初始化局部变量子界面工具栏 this->initGvlToolbar(); // 初始化变量表格 ui.tableVariable->initTable(m_strTitle, GVL_MODE::GVL_BASIC); ui.graphicsView->initView(m_strTitle, this); // 初始化UI this->initUI(); // 避免在硬件组态中创建局部变量表和调试页面 if (m_strTitle == GROUP_NAME_HARDWARE) { // 隐藏调试页面 ui.pouDebugView->hide(); // 既可以删除Tab ui.tabWidget->removeTab(0); // 也可以隐藏Tab //ui.tabWidget->setTabEnabled(0, false); //ui.tabWidget->setStyleSheet("QTabBar::tab:disabled {width: 0; color: transparent;}"); // 隐藏工具条 ui.toolbarPouFrame->hide(); } // 生成鸟瞰图 m_pNavView = new WindowAppPouNavView(this); m_pNavView->setFixedSize(220, 165); // 将当前Scene绑定到鸟瞰图中进行同步 m_pNavView->setScene((QGraphicsScene*)ui.graphicsView->getScene()); // 将View也绑定到鸟瞰图中同步 m_pNavView->setMainView(ui.graphicsView); // 调整VIew m_pNavView->fitInView(m_pNavView->sceneRect(), Qt::KeepAspectRatio); // 设置透明度 m_pNavView->setOpacity(0, false); // 绑定鸟瞰图缩放时的同步刷新动作 connect(ui.graphicsView, &WindowAppPouView::navigatorViewRequired, this, [=](bool required, const QTransform& tf) { Q_UNUSED(required); Q_UNUSED(tf); //m_pNavView->setTransform(WindowAppPouView::resetScale(tf)); m_pNavView->fitInView(m_pNavView->sceneRect(), Qt::KeepAspectRatio); m_pNavView->setVisible(required); m_pNavView->updateMainViewportRegion(); } ); // 矩形区域变动时的响应动作 connect(ui.graphicsView, &WindowAppPouView::viewportRectChanged, m_pNavView, &WindowAppPouNavView::updateMainViewportRegion); // 调整分割线 connect(ui.splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(slotSplitterMoved(int, int))); #ifdef DEBUG_ON_GVL VARIABLE* pNewVariable = new VARIABLE( m_strTitle, true, "int_lvl_test1", "int", "-30", "Comment1" ); this->addNewVariable(pNewVariable); pNewVariable = new VARIABLE( m_strTitle, true, "int_lvl_test2", "int", "150", "Comment2" ); this->addNewVariable(pNewVariable); pNewVariable = new VARIABLE( m_strTitle, true, "int_lvl_test3", "int", "300", "This value is 300." ); this->addNewVariable(pNewVariable); pNewVariable = new VARIABLE( m_strTitle, false, "double_lvl_test3", "double", "3.1415926", "This is a double variable" ); this->addNewVariable(pNewVariable); #endif } WindowAppPouFrame::~WindowAppPouFrame() { } /// /// UI元素初始化 /// void WindowAppPouFrame::initUI() { ui.splitter->setOpaqueResize(false); } /// /// 初始化局部变量子界面工具栏 /// void WindowAppPouFrame::initGvlToolbar() { m_GvlToolbar = new QToolBar(ui.toolbarVariable); m_GvlToolbar->setToolButtonStyle(Qt::ToolButtonIconOnly); m_GvlToolbar->setIconSize(QSize(14, 14)); QAction* actionNew = new QAction(QIcon(":/image/New.png"), ("New")); QAction* actionMoveUp = new QAction(QIcon(":/image/Up.png"), ("Move up")); QAction* actionMoveDown = new QAction(QIcon(":/image/Down.png"), ("Move down")); QAction* actionDel = new QAction(QIcon(":/image/Del.png"), ("Delete")); m_GvlToolbar->addAction(actionNew); m_GvlToolbar->addSeparator(); m_GvlToolbar->addAction(actionMoveUp); m_GvlToolbar->addAction(actionMoveDown); m_GvlToolbar->addSeparator(); m_GvlToolbar->addAction(actionDel); // 增加工具栏的消息响应 connect(actionNew, &QAction::triggered, this, &WindowAppPouFrame::onToolGvlNew); connect(actionMoveUp, &QAction::triggered, this, &WindowAppPouFrame::onToolGvlMoveUp); connect(actionMoveDown, &QAction::triggered, this, &WindowAppPouFrame::onToolGvlMoveDown); connect(actionDel, &QAction::triggered, this, &WindowAppPouFrame::onToolGvlDelete); // 设置为白色背景色 // m_LvlToolbar->setStyleSheet("background-color:rgb(255,255,255)"); } /// /// 初始化图形子界面工具栏 /// void WindowAppPouFrame::initPouToolbar() { // CAUTION: 这里调试了好久,如果QToolBar的父窗体是QMdiSubWindow的话,这里的工具栏会变成那种弹出式的 // 只有父窗体是View的时候才会是那种正常工具栏 m_PouToolbar = new QToolBar(ui.toolbarPouFrame); m_PouToolbar->setToolButtonStyle(Qt::ToolButtonIconOnly); actionMoveUp = new QAction(QIcon(":/image/ZorderTop.png"), ("MoveUp")); actionMoveDown = new QAction(QIcon(":/image/ZorderBottom.png"), ("MoveDown")); actionMoveFirst = new QAction(QIcon(":/image/ZorderUp.png"), ("MoveFirst")); actionMoveLast = new QAction(QIcon(":/image/ZorderDown.png"), ("MoveLast")); actionAlignLeft = new QAction(QIcon(":/image/AlignLeft.png"), ("Align Left")); actionAlignTop = new QAction(QIcon(":/image/AlignTop.png"), ("Align Top")); actionAlignRight = new QAction(QIcon(":/image/AlignRight.png"), ("Align Right")); actionAlignBottom = new QAction(QIcon(":/image/AlignBottom.png"), ("Align Bottom")); // 2022-9-29,增加了Undo和Redo按钮 actionUndo = new QAction(QIcon(":/image/Undo.png"), ("Undo")); actionRedo = new QAction(QIcon(":/image/Redo.png"), ("Redo")); actionOption = new QAction(QIcon(":/image/Option.png"), ("Options")); actionRunOnce = new QAction(QIcon(":/image/RunOnce.png"), ("Run Once")); actionSingleStep = new QAction(QIcon(":/image/RunOnce.png"), ("Single Step")); m_PouToolbar->addAction(actionMoveUp); m_PouToolbar->addAction(actionMoveDown); m_PouToolbar->addAction(actionMoveFirst); m_PouToolbar->addAction(actionMoveLast); m_PouToolbar->addSeparator(); m_PouToolbar->addAction(actionAlignLeft); m_PouToolbar->addAction(actionAlignTop); m_PouToolbar->addAction(actionAlignRight); m_PouToolbar->addAction(actionAlignBottom); m_PouToolbar->addSeparator(); // 2022-9-29,增加了Undo和Redo按钮 m_PouToolbar->addAction(actionUndo); m_PouToolbar->addAction(actionRedo); m_PouToolbar->addSeparator(); m_PouToolbar->addAction(actionOption); m_PouToolbar->addAction(actionRunOnce); m_PouToolbar->addAction(actionSingleStep); m_PouToolbar->setIconSize(QSize(14, 14)); connect(actionMoveUp, &QAction::triggered, this, &WindowAppPouFrame::onToolMoveUp); connect(actionMoveDown, &QAction::triggered, this, &WindowAppPouFrame::onToolMoveDown); connect(actionMoveFirst, &QAction::triggered, this, &WindowAppPouFrame::onToolMoveFirst); connect(actionMoveLast, &QAction::triggered, this, &WindowAppPouFrame::onToolMoveLast); connect(actionAlignLeft, &QAction::triggered, this, &WindowAppPouFrame::onToolAlignLeft); connect(actionAlignTop, &QAction::triggered, this, &WindowAppPouFrame::onToolAlignTop); connect(actionAlignRight, &QAction::triggered, this, &WindowAppPouFrame::onToolAlignRight); connect(actionAlignBottom, &QAction::triggered, this, &WindowAppPouFrame::onToolAlignBottom); connect(actionUndo, &QAction::triggered, this, &WindowAppPouFrame::onToolUndo); connect(actionRedo, &QAction::triggered, this, &WindowAppPouFrame::onToolRedo); connect(actionOption, &QAction::triggered, this, &WindowAppPouFrame::onToolOption); connect(actionRunOnce, &QAction::triggered, this, &WindowAppPouFrame::onToolRunOnce); connect(actionSingleStep, &QAction::triggered, this, &WindowAppPouFrame::onToolSingleStep); } /// /// Toolbar - New /// void WindowAppPouFrame::onToolGvlNew() { // qDebug() << "WindowAppGvlView::onToolNew"; // 弹出新增变量对话框 DialogNewVariable dlgNewVar(GVL_MODE::GVL_BASIC, this); dlgNewVar.setWindowModality(Qt::WindowModal); dlgNewVar.setGroup(this->m_strTitle); dlgNewVar.setTagNumber(ui.tableVariable->rowCount()); int res = dlgNewVar.exec(); if (res != QDialog::Accepted) { return; } // 根据用户输入构造新的变量 VARIABLE* pNewVariable = new VARIABLE( m_strTitle, dlgNewVar.m_bSerialized, dlgNewVar.m_strName, dlgNewVar.m_strType, dlgNewVar.m_strValue, dlgNewVar.m_strComment, g_pGvlManager->getVariablesCountByGroup(m_strTitle), true ); // 在界面和数据结构中添加新的变量 this->addNewVariable(pNewVariable); // 数据结构中添加本变量信息 g_pGvlManager->addNewVariable( m_strTitle, pNewVariable ); //// 表格中添加一行 //ui.tableVariable->addLocalVariable( // dlgNewVar.m_bSerialized, // dlgNewVar.m_strName, // dlgNewVar.m_strType, // dlgNewVar.m_strValue, // dlgNewVar.m_strComment //); } /// /// Toolbar - Gvl MoveUp /// void WindowAppPouFrame::onToolGvlMoveUp() { ui.tableVariable->onVariableMoveUp(); } /// /// Toolbar - Gvl MoveDown /// void WindowAppPouFrame::onToolGvlMoveDown() { ui.tableVariable->onVariableMoveDown(); } /// /// Toolbar - Gvl Delete /// void WindowAppPouFrame::onToolGvlDelete() { ui.tableVariable->onVariableDelete(); } /// /// 工具序号 减 1 /// void WindowAppPouFrame::onToolMoveUp() { ui.graphicsView->getScene()->BlockMoveUp(); } /// /// 工具序号 加 1 /// void WindowAppPouFrame::onToolMoveDown() { ui.graphicsView->getScene()->BlockMoveDown(); } /// /// 工具序号 置顶 /// void WindowAppPouFrame::onToolMoveFirst() { ui.graphicsView->getScene()->BlockMoveFirst(); } /// /// 工具序号 置底 /// void WindowAppPouFrame::onToolMoveLast() { ui.graphicsView->getScene()->BlockMoveLast(); } /// /// 工具左对齐 /// void WindowAppPouFrame::onToolAlignLeft() { ui.graphicsView->getScene()->BlockAlignLeft(); } /// /// 功能块顶对齐 /// void WindowAppPouFrame::onToolAlignTop() { ui.graphicsView->getScene()->BlockAlignTop(); } /// /// 功能块右对齐 /// void WindowAppPouFrame::onToolAlignRight() { ui.graphicsView->getScene()->BlockAlignRight(); } /// /// 功能块底对齐 /// void WindowAppPouFrame::onToolAlignBottom() { ui.graphicsView->getScene()->BlockAlignBottom(); } /// /// Undo /// void WindowAppPouFrame::onToolUndo() { // vDebug() << "WindowAppPouFrame::onToolUndo"; ((WindowAppPouScene*)ui.graphicsView->getScene())->m_CommandManager.undo(); } /// /// Redo /// void WindowAppPouFrame::onToolRedo() { // vDebug() << "WindowAppPouFrame::onToolRedo"; ((WindowAppPouScene*)ui.graphicsView->getScene())->m_CommandManager.redo(); } /// /// Option /// void WindowAppPouFrame::onToolOption() { vDebug() << "WindowAppPouFrame::onToolOption"; } /// /// 执行一轮 /// void WindowAppPouFrame::onToolRunOnce() { QFuture Future = QtConcurrent::run(this, &WindowAppPouFrame::ToolRunOnce); } /// /// 单步执行 /// void WindowAppPouFrame::onToolSingleStep() { QFuture Future = QtConcurrent::run(this, &WindowAppPouFrame::ToolSingleStep); } /// /// 线程函数 - 执行一轮 /// void WindowAppPouFrame::ToolRunOnce() { // 通过名字找到对应的Pou POU* pou = g_pPouManager->getPouByName(m_strTitle); // 执行所有工具,执行一轮 pou->ToolExecuteAll(); } /// /// 线程函数 - 单步执行 /// void WindowAppPouFrame::ToolSingleStep() { // 通过名字找到对应的Pou POU* pou = g_pPouManager->getPouByName(m_strTitle); // 单步执行 pou->ToolExecuteSingleStep(); } /// /// 接收键盘消息 /// /// void WindowAppPouFrame::keyPressEvent(QKeyEvent* event) { //先检测Ctrl键是否按下 if (QApplication::keyboardModifiers() == Qt::ControlModifier) { WindowAppPouScene* pScene = (WindowAppPouScene*)ui.graphicsView->getScene(); if (pScene == nullptr) { return; } //检测 Z 键,并执行撤销动作 if (event->key() == Qt::Key_Z) { if (pScene->m_CommandManager.canUndo()) { pScene->m_CommandManager.undo(); } } // 检测 Y 键,并执行反撤销动作 if (event->key() == Qt::Key_Y) { if (pScene->m_CommandManager.canRedo()) { pScene->m_CommandManager.redo(); } } } } /// /// 在界面中添加新的变量(from序列化文件) /// /// void WindowAppPouFrame::addNewVariable(VARIABLE* pNewVariable) { // 2022-2-15增加,Pou内部变量不需要显示在界面中 if (pNewVariable->bShow) { // 界面中添加新的一行 ui.tableVariable->insertTableLine( pNewVariable->bSerialized, pNewVariable->strName, pNewVariable->strFullName, Utility::getTypeString(pNewVariable->value.type), Utility::getValueString(pNewVariable->value.Ptr, pNewVariable->value.type), pNewVariable->strComment ); // 绑定新的变量和界面对应关系,方便变更之后及时发送通知 g_pGvlManager->bindUIAndVariable(ui.tableVariable, pNewVariable->strFullName); } } ///// ///// 在界面和数据结构中添加新的TOOL(from序列化文件) ///// ///// //void WindowAppPouFrame::addNewTool(TOOL* pNewTool, QPointF pos) //{ // ui.graphicsView->addToolDirectly(pNewTool, pos); //} ///// ///// 在界面中添加新的Link(from序列化文件) ///// ///// ///// //void WindowAppPouFrame::addNewLink(const QString& strStartInf, const QString& strEndInf, LINK_MODE linkMode) //{ // ui.graphicsView->addLinkDirectly(strStartInf, strEndInf, linkMode); //} /// /// 将功能块的Debug 数据写入UI /// /// void WindowAppPouFrame::UpdataDebugData(DebugData data) { ui.pouDebugView->UpdataDebugData(data); } /// /// /// /// void WindowAppPouFrame::resizeEvent(QResizeEvent* event) { Q_UNUSED(event); if (m_pNavView) { m_pNavView->move(ui.graphicsView->width() - m_pNavView->width() - 12, ui.graphicsView->height() - m_pNavView->height() + 12); } } /// /// 拖动伸缩滑块的时候,调整鸟瞰图窗口位置 /// /// /// void WindowAppPouFrame::slotSplitterMoved(int pos, int indext) { Q_UNUSED(pos); Q_UNUSED(indext); if (m_pNavView) { m_pNavView->move(ui.graphicsView->width() - m_pNavView->width() - 12, ui.graphicsView->height() - m_pNavView->height() + 12); } } /// /// 鼠标移入的时候,显示鸟瞰图 /// /// void WindowAppPouFrame::enterEvent(QEvent* event) { Q_UNUSED(event); if (m_pNavView) { m_pNavView->setOpacity(1); } } /// /// 鼠标移出的时候,隐藏鸟瞰图 /// /// void WindowAppPouFrame::leaveEvent(QEvent* event) { Q_UNUSED(event); if (m_pNavView) { m_pNavView->setOpacity(0); } } /// /// 序列化 /// /// /// /// QDataStream& operator<<(QDataStream& out, const WindowAppPouFrame* pFrame) { if (pFrame != nullptr) { int paranum;//参数数量 paranum = 2; out << paranum;//先保存参数数量 out << (int)1 << pFrame->ui.splitter->sizes(); out << (int)2 << pFrame->ui.pouDebugView->getSplitter()->sizes(); } // Error else { vDebug() << "[Error] WindowAppPouFrame - operator<< failed, pFrame == nullptr"; } return out; } /// /// 反序列化 /// /// /// /// QDataStream& operator>>(QDataStream& in, WindowAppPouFrame* pFrame) { if (pFrame != nullptr) { QList splitters; QList splittersDdebugView; int paranum;//参数数量 int para; in >> paranum;//读取参数数量 for (int i = 0; i < paranum; i++) { in >> para; switch (para) { case 1: in >> splitters; break; case 2: in >> splittersDdebugView; break; default: { vWarning() << "Serialized(In) Error"; } break; } } // 界面中设置Splitter pFrame->ui.splitter->setSizes(splitters); pFrame->ui.pouDebugView->getSplitter()->setSizes(splittersDdebugView); } // Error else { vDebug() << "[Error] WindowAppPouFrame - operator>> failed, pFrame == nullptr"; } return in; } /// /// 响应Paint事件为了刷新Undo菜单启用禁用(TODO:暂时没有找到更好的位置) /// void WindowAppPouFrame::paintEvent(QPaintEvent* event) { Q_UNUSED(event); // 刷新Undo菜单 this->refreshUndoMenu(); } /// /// 刷新Undo/Redo按钮 /// void WindowAppPouFrame::refreshUndoMenu() { if (actionUndo != nullptr) { WindowAppPouScene* pScene = (WindowAppPouScene*)ui.graphicsView->getScene(); actionUndo->setEnabled(pScene->m_CommandManager.canUndo()); actionRedo->setEnabled(pScene->m_CommandManager.canRedo()); } }