123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- #include "WindowRuntime.h"
- #include "WindowRuntimeView.h"
- #include "TaskManager.h"
- #include "PouManager.h"
- #include "vpControls/VTableControl.h"
- #include "vpControls/VPieChart.h"
- #include "vpControls/VCustomPlot.h"
- #include "vpControls/VImageControl.h"
- #define MAINPAGE_INDEX 0
- WindowRuntime::WindowRuntime(QWidget *parent)
- : QMainWindow(parent)
- , m_pRuntimeViews(nullptr)
- {
- ui.setupUi(this);
- // 界面初始化
- this->initUI();
- // 注册本窗体
- VPGlobal::Register(this);
- }
- WindowRuntime::~WindowRuntime()
- {
- }
- /// <summary>
- /// 界面初始化
- /// </summary>
- void WindowRuntime::initUI()
- {
- this->setWindowFlags(Qt::Widget);
- if (1)
- {
- // 创建Stack式页面栈
- m_pRuntimeViews = new QStackedWidget();
- // 创建对应的发布页面
- WindowRuntimeView* pNew = new WindowRuntimeView(m_pRuntimeViews);
- m_pRuntimeViews->addWidget(pNew);
- // 设置布局
- QGridLayout* layout = new QGridLayout();
- layout->setMargin(0);
- layout->setSpacing(0);
- layout->addWidget(m_pRuntimeViews);
- ui.centralWidget->setLayout(layout);
-
- }
- else
- {
- // TODO: RunTime 超过 UI的尺寸时,需要显示滚动条。
- // TODO: RunTime 小于 UI的尺寸时,需要显示边框
- //////////////////////////////////////////////////////////////////////////
- QGridLayout* gridLayout = new QGridLayout(ui.centralWidget);
- m_pRuntimeViews = new QStackedWidget(ui.centralWidget);
- QWidget* page = new QWidget();
- QGridLayout* gridLayout_3 = new QGridLayout(page);
- QScrollArea* scrollArea = new QScrollArea(page);
- // scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
- // scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
- scrollArea->setWidgetResizable(true);
- QWidget* scrollAreaWidgetContents = new QWidget();
- QGridLayout* gridLayout_2 = new QGridLayout(scrollAreaWidgetContents);
- WindowRuntimeView* pNew = new WindowRuntimeView(scrollAreaWidgetContents); ;
- gridLayout_2->addWidget(pNew, 0, 0, 1, 1);
- scrollArea->setWidget(scrollAreaWidgetContents);
- gridLayout_3->addWidget(scrollArea, 0, 0, 1, 1);
- m_pRuntimeViews->addWidget(page);
- gridLayout->addWidget(m_pRuntimeViews, 0, 0, 1, 1);
- pNew->setMinimumSize(QSize(80, 80));
- }
-
- }
- /// <summary>
- /// 发布对应的页面
- /// </summary>
- /// <param name="pPage"></param>
- /// <param name="bMainPage">标记当前页面是否是主页</param>
- /// <returns></returns>
- bool WindowRuntime::publishPage(WindowAppUiView* pPage, bool bMainPage /* = false */)
- {
- // 确保首页是一定是第一个页面
- if (bMainPage)
- {
- if (m_pRuntimeViews!=nullptr && m_pRuntimeViews->count() > 0)
- {
- CRITICAL_MESSAGE("Run main page [" + pPage->m_strPageName + "] error!");
- return false;
- }
- // 新建StackWidget
- m_pRuntimeViews = new QStackedWidget();
- ui.centralWidget->layout()->addWidget(m_pRuntimeViews);
- }
- // 创建新的Runtime页面添加到Stack中
- WindowRuntimeView* pNewView = new WindowRuntimeView(m_pRuntimeViews);
- m_pRuntimeViews->addWidget(pNewView);
- // 保存页面序号
- m_AllViews.insert(pPage->m_strPageName, m_pRuntimeViews->count() - 1);
- // 发布本页面中的所有控件
- // 此处需要检查是否所有的控件都拷贝成功
- bool bRet = pNewView->copyFrom(pPage);
- Q_UNUSED(bRet);
- return true;
- }
- /// <summary>
- /// 启动所有的UI界面(目前先只支持启动所有页面的方式)
- /// </summary>
- bool WindowRuntime::publishAllPages(
- WindowAppUiView* pMainPage,
- QMap<QString, WindowAppUiView*> allPages
- )
- {
- // 首先执行数据结构重置
- this->reset();
- // 首先发布主页
- bool bRet = publishPage(pMainPage, true);
- // 如果首页发布失败,则退出
- if (!bRet)
- {
- return false;
- }
- // 根据每一个 WindowAppUiView 生成对应的页面,并且把所有的控件都分布上去
- QMapIterator<QString, WindowAppUiView*> it(allPages);
- while (it.hasNext())
- {
- WindowAppUiView* pPage = it.next().value();
- if (pPage != pMainPage)
- {
- // 其余子页面暂时不检查返回值,如果发布失败则继续发布下一个页面
- bRet = publishPage(pPage);
- }
- }
- // 页面全部发布完毕后,默认显示主页
- if (m_pRuntimeViews!=nullptr &&
- m_pRuntimeViews->count() > 0)
- {
- m_pRuntimeViews->setCurrentIndex(MAINPAGE_INDEX);
- }
- return true;
- }
- /// <summary>
- /// 执行指令
- /// </summary>
- /// <param name="strCmd">命令名字</param>
- /// <param name="strParam">命令参数</param>
- /// <returns></returns>
- bool WindowRuntime::runCmd(const QString& strCmd, const QString& strParam /*= ""*/)
- {
- // 启动所有Task的执行
- if (strCmd == SYS_CMD_TASK_RUN)
- {
- qDebug() << "[Command] runCmd - " << SYS_CMD_TASK_RUN;
-
- g_pTaskManager->executeAllTasks(false);
- }
- // 启动所有Task的执行一次
- else if (strCmd == SYS_CMD_TASK_RUNONCE)
- {
- qDebug() << "[Command] runCmd - " << SYS_CMD_TASK_RUNONCE;
-
- g_pTaskManager->executeAllTasks(true);
- }
- // 停止所有任务
- else if (strCmd == SYS_CMD_TASK_STOP)
- {
- qDebug() << "[Command] runCmd - " << SYS_CMD_TASK_STOP;
-
- g_pTaskManager->stopAllTask(false);
- }
- // 切换UI
- else if (strCmd == SYS_CMD_UI_SWITCH)
- {
- qDebug() << "[Command] runCmd - " << SYS_CMD_UI_SWITCH << " - " << strParam;
-
- g_pRuntime->switchToPage(strParam);
- }
- // 不应该执行到这里
- else
- {
- qWarning() << "SystemCommand::runCmd - unknown command : " << strCmd;
- return false;
- }
- return true;
- }
- /// <summary>
- /// 执行Dll中的Tool Interface
- /// </summary>
- /// <param name="strPouName"></param>
- /// <param name="strToolName"></param>
- /// <param name="strInfName"></param>
- /// <returns></returns>
- bool WindowRuntime::runDllInterface(
- const QString& strPouName,
- const QString& strToolName,
- const QString& strInfName,
- VALUE_TYPE controlType
- )
- {
- // 首先根据名字找到Pou
- POU* pPou = g_pPouManager->getPouByName(strPouName);
-
- if (pPou == nullptr)
- {
- qWarning() << "[Error] in WindowRuntime::runDllInterface() - Invalid pou name : " << strPouName;
- return false;
- }
- // 然后找到对应的接口
- QString strInfFullname = strToolName + "." + strInfName;
- _INTERFACE* pInf = pPou->GetInterface(strInfFullname);
- if (pInf == nullptr)
- {
- qWarning() << "[Error] in WindowRuntime::runDllInterface() - Invalid interface name : " << strInfFullname;
- return false;
- }
- // 根据不同的Runtime控件类型进行不同的处理
- if (controlType == VALUE_TYPE::Control_Button)
- {
- // 获取dll中导出的控件指针
- QPushButton* pInfButton = (QPushButton*)pInf->getValuePtr();
- // 发送clicked信号
- emit pInfButton->clicked();
- return true;
- }
- else
- {
- qWarning() << "[Error] in WindowRuntime::runDllInterface() - Control type is not support : " << static_cast<short>(controlType);
- return false;
- }
- }
- /// <summary>
- /// 系统命令,切换到指定页面
- /// </summary>
- /// <param name="strPageName"></param>2121
- /// <returns></returns>
- bool WindowRuntime::switchToPage(const QString& strPageName)
- {
- // 执行界面的切换
- if (m_AllViews.contains(strPageName))
- {
- int nPageIndex = m_AllViews[strPageName];
- // 找到指定页面,并切换
- m_pRuntimeViews->setCurrentIndex(nPageIndex);
- qDebug() << "WindowRuntime::switchToPage() - " << strPageName << " index: " << nPageIndex;
- return true;
- }
- // Error: 不应该执行到这里
- else
- {
- qDebug() << "[Error] in WindowRuntime::switchToPage() - " << strPageName << ", but can;t find this page";
- return false;
- }
-
- }
- //========================================================================
- //
- // 变量同步相关代码
- //
- //========================================================================
- /// <summary>
- /// 接收来自变量到复杂控件单向同步的Event
- /// 备注:复杂控件是根据索引值绑定变量主动发起的event来触发更新的
- /// </summary>
- /// <param name="event"></param>
- void WindowRuntime::customEvent(QEvent* event)
- {
- // 如果是数值同步消息
- if (event->type() == VALUE_EVENT_TYPEID)
- {
- qDebug() << "WindowRuntime::customEvent - VALUE_EVENT_TYPEID";
- SyncValueEvent* pValueEvent = dynamic_cast<SyncValueEvent*> (event);
- // 取出参数
- QList<VARIABLE*> syncValues = pValueEvent->getSyncValues();
- for (VARIABLE* syncVal : syncValues)
- {
- // 从变量中同步
- this->syncFromComplexSource(syncVal);
- }
- }
- else
- {
- QEvent::Type type = event->type();
- qWarning() << "WindowRuntime::customEvent Type:" <<type;
- }
- }
- /// <summary>
- /// 添加一个新的索引和控件对应关系
- /// </summary>
- /// <param name="pIndex"></param>
- /// <param name="pControl"></param>
- void WindowRuntime::registerNewIndex(VARIABLE* pIndex, QWidget* pControl)
- {
- if (pIndex == nullptr || pControl == nullptr)
- {
- return;
- }
- // 为接口设置索引标识
- pIndex->bComplexLinkIndex = true;
- // 加入数据结构中
- m_IndexToComplexControls.insertMulti(pIndex, pControl);
- }
- /// <summary>
- /// 为控件添加一个变量
- /// </summary>
- /// <param name="pControl"></param>
- /// <param name="pVariable"></param>
- void WindowRuntime::registerNewVariable(QWidget* pControl, const QString& strPropertyName, const VARIABLE* pVariable)
- {
- if (pVariable == nullptr || pControl == nullptr)
- {
- return;
- }
- RUNTIME_SYNC_VAR newVar(strPropertyName, pVariable);
- // 如果找到了本Control对应的变量,则直接添加变量
- if (m_ComplexControlToVariables.contains(pControl))
- {
- RUNTIME_SYNC_VARS& vars = m_ComplexControlToVariables[pControl];
- vars.push_back(newVar);
- }
- // 如果没有找到,则新建此变量
- else
- {
- RUNTIME_SYNC_VARS vars;
- vars.push_back(newVar);
- m_ComplexControlToVariables.insert(pControl, vars);
- }
- }
- /// <summary>
- /// 释放对应控件关系
- /// </summary>
- /// <param name="pWidget"></param>
- void WindowRuntime::releaseControl(QWidget* pWidget)
- {
- m_ComplexControlToVariables.remove(pWidget);
- // QMutableHashIterator<const VARIABLE*, QWidget*> iter(m_IndexToComplexControls);
- // while (iter.hasNext())
- // {
- // // 更新了删除元素的方式
- // const QList<QWidget*>& listWidgets = m_IndexToComplexControls.values(iter.next().key());
- for (const VARIABLE* pVar : m_IndexToComplexControls.uniqueKeys())
- {
- // 更新了删除元素的方式
- const QList<QWidget*>& listWidgets = m_IndexToComplexControls.values(pVar);
- for (int i = 0; i < listWidgets.count(); i++)
- {
- if (listWidgets.at(i) == pWidget)
- {
- // m_IndexToComplexControls.remove(iter.key(), pWidget);
- m_IndexToComplexControls.remove(pVar, pWidget);
- return;
- }
- }
- }
- }
- /// <summary>
- /// 从复杂控件的触发源头同步(一般都是Pou中的Execute,每轮执行会触发更新一遍Runtime)
- /// </summary>
- /// <param name="syncVal"></param>
- void WindowRuntime::syncFromComplexSource(const VARIABLE* syncVal)
- {
- // 如果本轮需要同步的Value的不是索引所在的pou,那么就不更新,等着索引所在的pou执行后再统一更新
- // (MEMO:这个判断放在Pou中了,只有索引变量才会被推送过来)
- // 所以这个判断不可能命中
- if (syncVal == nullptr || !syncVal->bComplexLinkIndex)
- {
- return;
- }
- // 如果本轮执行的是索引所在的pou则更新其他所有pou中的关联值
- // 首先找到这个索引变量对应的控件指针
- if (m_IndexToComplexControls.contains(syncVal))
- {
- // 2021-12-28 修改,此处改为一个索引源触发多个控件刷新
- QList<QWidget*> pControls = m_IndexToComplexControls.values(syncVal);
- for (QWidget* pControl : pControls)
- {
- // 根据控件类型的不同,单独进行处理
- QString strClassName = pControl->metaObject()->className();
- // 如果是Table类型
- if (strClassName == CLASS_NAME_TABLECONTROL)
- {
- // 传递Table指针以及对应的列索引数据
- int nRowIndex = syncVal->getValueString().toInt();
- this->syncToTableControl(pControl, nRowIndex);
- }
- // 如果是VCustomPlot类型
- else if (strClassName == CLASS_NAME_CUSTOMPLOT)
- {
- // 传递VCustomPlot指针以及对应的分块索引数据
- int nRowIndex = syncVal->getValueString().toInt();
- this->syncToCustomPlot(pControl, nRowIndex);
- }
- // 如果是Pie类型
- else if (strClassName == CLASS_NAME_PIECHART)
- {
- // 传递Pie指针以及对应的分块索引数据
- int nRowIndex = syncVal->getValueString().toInt();
- this->syncToPieChart(pControl, nRowIndex);
- }
- // 如果是Image类型
- else if (strClassName == CLASS_NAME_IMAGECONTROL)
- {
- this->syncToImageControl(pControl);
- }
- }
- }
- // 不应该走到这里
- else
- {
- qDebug() << "WindowRuntime::syncFromComplexSource - Critical error : can't find correct relation from syncvalue["
- << syncVal->strFullName << "].";
- }
- }
- /// <summary>
- /// 同步到Table控件中
- /// </summary>
- /// <param name="pTable"></param>
- void WindowRuntime::syncToTableControl(QWidget* pControl, int nRowIndex)
- {
- VTableControl* pTableWidget = qobject_cast<VTableControl*>(pControl);
- // 如果给定的Index数值超出了Table的最大范围,则忽略
- if (nRowIndex >= pTableWidget->rowCount())
- {
- //qDebug() << "WindowRuntime::syncToTableControl - nRowIndex > table row count, ignore : " << nRowIndex;
- nRowIndex = 0;
- //return;
- }
- // 找到Table对应的各个数值信息
- if (m_ComplexControlToVariables.contains(pControl))
- {
- RUNTIME_SYNC_VARS sync_vars = m_ComplexControlToVariables[pControl];
- // 刷新对应的表格
- // this->updateTableControl(pTableWidget, vars, nRowIndex);
- // 刷新这一行
- pTableWidget->updateRowFromVariables(sync_vars, nRowIndex);
- }
- // 不应该走到这里
- else
- {
- qDebug() << "WindowRuntime::syncToTableControl - Critical error : can't find correct relation from m_ComplexControlToVariables.";
- }
- }
- ///// <summary>
- ///// 刷新Table控件中的值
- ///// </summary>
- ///// <param name="pTableWidget"></param>
- ///// <param name="vars"></param>
- //void WindowRuntime::updateTableControl(QTableWidget* pTableWidget, const RUNTIME_SYNC_VARS& vars, int nRowIndex)
- //{
- // // 将最新的值都更新到Table控件中(一次更新一整列)
- // int nColCount = pTableWidget->columnCount();
- //
- // for (int i = 0; i < nColCount; i++)
- // {
- // QString strValue = vars[i]->getValueString();
- //
- // pTableWidget->setItem(
- // nRowIndex,
- // i,
- // new QTableWidgetItem(strValue)
- // );
- // }
- //}
- /// <summary>
- /// 同步到CustomPlot控件中
- /// </summary>
- /// <param name="pPie"></param>
- /// <param name="nSliceIndex"></param>
- void WindowRuntime::syncToCustomPlot(QWidget* pControl, int nSliceIndex)
- {
- Q_UNUSED(nSliceIndex);
- VCustomPlot* pCustomPlot = qobject_cast<VCustomPlot*>(pControl);
- if (pCustomPlot != nullptr)
- {
- // 找到对应的各个数值信息
- if (m_ComplexControlToVariables.contains(pControl))
- {
- RUNTIME_SYNC_VARS sync_vars = m_ComplexControlToVariables[pControl];
- for (int i = 0; i < sync_vars.size(); i++)
- {
- int nValue = sync_vars[i].pVariable->getValueString().toInt();
- // 防止数据越界
- if (pCustomPlot->getCustomPlotCount() > i)
- {
- pCustomPlot->updateCustomPlotValue(nValue, i);
- }
- }
- }
- // 不应该走到这里
- else
- {
- qWarning() << "WindowRuntime::syncToPieChart - Critical error : can't find correct relation from m_ComplexControlToVariables.";
- }
- }
- }
- /// <summary>
- /// 同步到Pie控件中
- /// </summary>
- /// <param name="pPie"></param>
- /// <param name="nSliceIndex"></param>
- void WindowRuntime::syncToPieChart(QWidget* pControl, int nSliceIndex)
- {
- Q_UNUSED(nSliceIndex);
- VPieChart* pPieChart = qobject_cast<VPieChart*>(pControl);
- if (pPieChart != nullptr)
- {
- // 找到对应的各个数值信息
- if (m_ComplexControlToVariables.contains(pControl))
- {
- RUNTIME_SYNC_VARS sync_vars = m_ComplexControlToVariables[pControl];
- for (int i = 0; i < sync_vars.size(); i++)
- {
- int nValue = sync_vars[i].pVariable->getValueString().toInt();
- // 防止数据越界
- if (pPieChart->getSliceCount() > i )
- {
- pPieChart->updateSliceValue(nValue, i);
- }
-
- }
- }
- // 不应该走到这里
- else
- {
- qWarning() << "WindowRuntime::syncToPieChart - Critical error : can't find correct relation from m_ComplexControlToVariables.";
- }
- }
- }
- /// <summary>
- /// 同步到Image控件中
- /// </summary>
- /// <param name="pControl"></param>
- void WindowRuntime::syncToImageControl(QWidget* pControl)
- {
- VImageControl* pImageControl = qobject_cast<VImageControl*>(pControl);
- // 找到对应的各个数值信息
- if (m_ComplexControlToVariables.contains(pControl))
- {
- RUNTIME_SYNC_VARS sync_vars = m_ComplexControlToVariables[pControl];
- // 刷新本图像
- pImageControl->updateImageFromVariables(sync_vars);
- }
- // 不应该走到这里
- else
- {
- qDebug() << "WindowRuntime::syncToImageControl - Critical error : can't find correct relation from m_ComplexControlToVariables.";
- }
- }
- /// <summary>
- /// 重置所有数据结构,准备执行新的发布动作
- /// </summary>
- void WindowRuntime::reset()
- {
- // 首先清空当前所有页面
- RELEASE(m_pRuntimeViews);
- m_AllViews.clear();
- m_IndexToComplexControls.clear();
- m_ComplexControlToVariables.clear();
- }
|