WindowRuntimeView.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. #include "WindowRuntimeView.h"
  2. #include "WindowAppUiView.h"
  3. #include "WindowAppUiScene.h"
  4. #include "WindowRuntime.h"
  5. #include "selectwidget.h"
  6. #include "PouManager.h"
  7. #include "UiManager.h"
  8. #include "GvlManager.h"
  9. #include "VPControls.h"
  10. WindowRuntimeView::WindowRuntimeView(QWidget *parent)
  11. : QWidget(parent)
  12. {
  13. // 初始化Logo贴图
  14. this->initLogoImage();
  15. }
  16. WindowRuntimeView::~WindowRuntimeView()
  17. {
  18. }
  19. /// <summary>
  20. /// 从设计页面中拷贝,并且建立Runtime和UI、Dll的三方消息同步
  21. /// </summary>
  22. /// <param name="pDesignView"></param>
  23. /// <returns></returns>
  24. bool WindowRuntimeView::copyFrom(WindowAppUiView* pDesignView)
  25. {
  26. m_pControls = pDesignView->uiScene()->getAllControls();
  27. // 枚举该UI页面中的所有的控件,照着复制一份到Runtime窗体中
  28. // 创建控件时,要留出左侧的基础宽度 APP_RM_WIDTH
  29. for (SelectWidget* pUiWidget : m_pControls)
  30. {
  31. QWidget* pNewControl = nullptr;
  32. // 获取控件位置和尺寸
  33. QPoint ptPos = pUiWidget->pos();
  34. //ptPos.setX(ptPos.x());
  35. //int nWidth = pUiWidget->width();
  36. //int nHeight = pUiWidget->height();
  37. QSize controlSize = pUiWidget->size();
  38. // 解析扩展属性是否成功(仅用于复杂控件)
  39. bool bPasrseOk = true;
  40. if (pUiWidget->m_pProperty == nullptr)
  41. {
  42. qWarning() << "[Error] in WindowRuntimeView::copyFrom() - m_pProperty in selectWidget is nullptr.";
  43. continue;
  44. }
  45. // 根据不同类型创建不同的控件实例
  46. switch (pUiWidget->m_Type)
  47. {
  48. case VALUE_TYPE::Control_Label:
  49. {
  50. pNewControl = new VLabel(this, ptPos, controlSize, pUiWidget->m_pProperty);
  51. }
  52. break;
  53. case VALUE_TYPE::Control_Button:
  54. {
  55. pNewControl = new VButton(this, ptPos, controlSize, pUiWidget->m_pProperty);
  56. // 绑定点击信号
  57. // 绑定信号的目的是为了做控件的三方同步
  58. connect(pNewControl, SIGNAL(clicked()), this, SLOT(slotControlClickedDispatcher()));
  59. }
  60. break;
  61. case VALUE_TYPE::Control_CheckBox:
  62. {
  63. pNewControl = new VCheckBox(this, ptPos, controlSize, pUiWidget->m_pProperty);
  64. // 绑定CheckBox变动信号
  65. connect(pNewControl, SIGNAL(stateChanged(int)), this, SLOT(onVCheckChanged(int)));
  66. }
  67. break;
  68. case VALUE_TYPE::Control_RadioBox:
  69. {
  70. pNewControl = new VRadioBox(this, ptPos, controlSize, pUiWidget->m_pProperty);
  71. // 绑定RadioBox变动信号
  72. connect(pNewControl, SIGNAL(toggled(bool)), this, SLOT(onVRadioChanged(bool)));
  73. }
  74. break;
  75. case VALUE_TYPE::Control_Groupbox:
  76. {
  77. pNewControl = new VGroupBox(this, ptPos, controlSize, pUiWidget->m_pProperty);
  78. }
  79. break;
  80. case VALUE_TYPE::Control_LineEdit:
  81. {
  82. pNewControl = new VLineEdit(this, ptPos, controlSize, pUiWidget->m_pProperty);
  83. // 注册文字变更消息用于反向同步
  84. connect(pNewControl, SIGNAL(textChanged(QString)), this, SLOT(onVEditChanged(QString)));
  85. }
  86. break;
  87. case VALUE_TYPE::Control_Listbox:
  88. {
  89. pNewControl = new VListBox(this, ptPos, controlSize, pUiWidget->m_pProperty);
  90. // 绑定ListBox变动信号
  91. connect(pNewControl, SIGNAL(currentRowChanged(int)), this, SLOT(onVListChanged(int)));
  92. }
  93. break;
  94. case VALUE_TYPE::Control_ComboBox:
  95. {
  96. pNewControl = new VComboBox(this, ptPos, controlSize, pUiWidget->m_pProperty);
  97. // 绑定ComboBox变动信号
  98. connect(pNewControl, SIGNAL(currentIndexChanged(int)), this, SLOT(onVComboChanged(int)));
  99. }
  100. break;
  101. case VALUE_TYPE::Control_Value:
  102. {
  103. pNewControl = new ValueControl(this, ptPos, controlSize, pUiWidget->m_pProperty);
  104. // 注册文字变更消息用于反向同步
  105. connect(pNewControl, SIGNAL(textChanged(QString)), this, SLOT(onValueControlChanged(QString)));
  106. }
  107. break;
  108. case VALUE_TYPE::Control_Result:
  109. {
  110. pNewControl = new VResult(this, ptPos, controlSize, pUiWidget->m_pProperty);
  111. }
  112. break;
  113. case VALUE_TYPE::Control_PieChart:
  114. {
  115. if (pUiWidget->m_pPropertyEx == nullptr)
  116. {
  117. qWarning() << "[Error] in WindowRuntimeView::copyFrom() - Control_PieChart m_pPropertyEx in selectWidget is nullptr.";
  118. continue;
  119. }
  120. pNewControl = new VPieChart(
  121. this,
  122. ptPos,
  123. controlSize,
  124. pUiWidget->m_pProperty,
  125. pUiWidget->m_pPropertyEx
  126. );
  127. // 解析传入的复杂控件属性
  128. bPasrseOk = this->parseComplexPropertyEx(pNewControl, pUiWidget->m_pPropertyEx);
  129. }
  130. break;
  131. case VALUE_TYPE::Control_CustomPlot:
  132. {
  133. if (pUiWidget->m_pPropertyEx == nullptr)
  134. {
  135. qWarning() << "[Error] in WindowRuntimeView::copyFrom() - Control_PieChart m_pPropertyEx in selectWidget is nullptr.";
  136. continue;
  137. }
  138. pNewControl = new VCustomPlot(
  139. this,
  140. ptPos,
  141. controlSize,
  142. pUiWidget->m_pProperty,
  143. pUiWidget->m_pPropertyEx
  144. );
  145. // 2021-12-15 对于复杂控件还需要额外解析扩展属性
  146. bPasrseOk = this->parseComplexPropertyEx(pNewControl, pUiWidget->m_pPropertyEx);
  147. }
  148. break;
  149. case VALUE_TYPE::Control_Table:
  150. {
  151. if (pUiWidget->m_pPropertyEx == nullptr)
  152. {
  153. qWarning() << "[Error] in WindowRuntimeView::copyFrom() - Control_Table m_pPropertyEx in selectWidget is nullptr.";
  154. continue;
  155. }
  156. pNewControl = new VTableControl(
  157. this,
  158. ptPos,
  159. controlSize,
  160. pUiWidget->m_pProperty,
  161. pUiWidget->m_pPropertyEx
  162. );
  163. // 2021-12-15 对于复杂控件还需要额外解析扩展属性
  164. bPasrseOk = this->parseComplexPropertyEx(pNewControl, pUiWidget->m_pPropertyEx);
  165. }
  166. break;
  167. case VALUE_TYPE::Control_Image:
  168. {
  169. if (pUiWidget->m_pPropertyEx == nullptr)
  170. {
  171. qWarning() << "[Error] in WindowRuntimeView::copyFrom() - Control_Image m_pPropertyEx in selectWidget is nullptr.";
  172. continue;
  173. }
  174. pNewControl = new VImageControl(
  175. this,
  176. ptPos,
  177. controlSize,
  178. pUiWidget->m_pProperty,
  179. pUiWidget->m_pPropertyEx,
  180. true
  181. );
  182. // 解析传入的复杂控件属性
  183. bPasrseOk = this->parseComplexPropertyEx(pNewControl, pUiWidget->m_pPropertyEx);
  184. }
  185. break;
  186. default:
  187. {
  188. qWarning() << "[Runtime] WindowRuntime::runPage - invalid control type:" << static_cast<short>(pUiWidget->m_Type);
  189. continue;
  190. }
  191. // return false;
  192. }
  193. // 创建控件失败
  194. if (pNewControl == nullptr)
  195. {
  196. qWarning() << "[Error] WindowRuntimeView::copyFrom - New control failed.";
  197. continue;
  198. }
  199. // 解析扩展属性失败(仅用于复杂控件)
  200. if (!bPasrseOk)
  201. {
  202. QString str = pUiWidget->m_pPropertyEx->m_strTitle + "[" + pUiWidget->m_pProperty->m_strText + "]";
  203. qWarning() << "[Error] WindowRuntimeView::copyFrom - " << str << "parseComplexPropertyEx() failed.";
  204. continue;
  205. }
  206. // 绑定UI控件和Runtime控件对应关系用于同步
  207. // MEMO:此处对于复杂控件也进行了绑定,但是此处暂时是不需要的
  208. // 因为复杂控件不需要UI向Runtime设计中实时同步,而是直接从数据源触发更新
  209. g_pUiManager->bindUiControlWithRtControl(pUiWidget->m_pWidget, pNewControl);
  210. // 执行控件的首次同步
  211. // 简单控件
  212. if (pUiWidget->m_pPropertyEx == nullptr)
  213. {
  214. this->doFirstSync(pUiWidget->m_pWidget, pUiWidget->m_Type, nullptr);
  215. }
  216. // 复杂控件
  217. else
  218. {
  219. VARIABLE* pVariable = pUiWidget->m_pPropertyEx->m_refreshLink.linkValue;
  220. this->doFirstSync(
  221. pUiWidget->m_pWidget,
  222. pUiWidget->m_Type,
  223. pVariable
  224. );
  225. }
  226. //pNewControl->resize(controlSize);
  227. //pNewControl->move(ptPos);
  228. }
  229. return true;
  230. }
  231. /// <summary>
  232. /// 初始化Logo贴图
  233. /// </summary>
  234. void WindowRuntimeView::initLogoImage()
  235. {
  236. m_pLogoImage = new QPixmap(64, 64);
  237. QString strPath = QCoreApplication::applicationDirPath() + "/Logo.png";
  238. QFileInfo info(strPath);
  239. if (info.exists() != true)
  240. {
  241. strPath = "./image/logo64.png";
  242. }
  243. m_pLogoImage->load(strPath);
  244. }
  245. /// <summary>
  246. /// 绘制界面背景
  247. /// </summary>
  248. /// <param name=""></param>
  249. void WindowRuntimeView::paintEvent(QPaintEvent*)
  250. {
  251. QRect rc = this->geometry();
  252. if (m_pControls.size() == 0)
  253. {
  254. // 绘制背景图片
  255. QString path = ":/image/background.png";
  256. QString strPath = QCoreApplication::applicationDirPath() + "/Desktop.bmp";
  257. QFileInfo info(strPath);
  258. if (info.exists() != true)
  259. {
  260. strPath = path;
  261. }
  262. QPixmap pixmap = QPixmap(strPath).scaled(this->size());
  263. QPalette palette(this->palette());
  264. //palette.setBrush(QPalette::Window, QBrush(pixmap));
  265. //this->setPalette(palette);
  266. QPainter painter(this);
  267. painter.drawImage(QRect(0, 0, this->width(), this->height()), pixmap.toImage());
  268. }
  269. // 在当前界面的右上角显示logo
  270. QPainter painter(this);
  271. painter.drawPixmap(rc.right() - 100, rc.top(), 64, 64, *m_pLogoImage);
  272. }
  273. /// <summary>
  274. /// 控件点击事件的总体调度
  275. /// </summary>
  276. void WindowRuntimeView::slotControlClickedDispatcher()
  277. {
  278. QObject* pSender = sender();
  279. QString strSenderClassName = pSender->metaObject()->className();
  280. qDebug() << "WindowRuntimeView::slotControlClicked()" << strSenderClassName;
  281. // 通过sender的类型来判断具体是哪个控件触发
  282. // 如果是Button类型
  283. if (strSenderClassName == CLASS_NAME_BUTTON)
  284. {
  285. onButtonClicked(qobject_cast<VButton*>(pSender));
  286. }
  287. else
  288. {
  289. qDebug() << "WindowRuntimeView::slotControlClickedDispatcher - Unknow sender class: " << strSenderClassName;
  290. }
  291. }
  292. /// <summary>
  293. /// VButton的点击处理
  294. /// </summary>
  295. /// <param name="pClickButton"></param>
  296. void WindowRuntimeView::onButtonClicked(VButton* pClickButton)
  297. {
  298. // 根据按钮的DataLink信息进行相应的处理
  299. const DataLink& dataLink = pClickButton->getDataLink();
  300. // 如果DataLink是空的则说明没设置数据连接
  301. if (dataLink.value.size() <= 0)
  302. {
  303. qDebug() << "WindowRuntimeView::onButtonClicked - dataLink is nullptr.";
  304. return;
  305. }
  306. // 解析按钮链接信息
  307. QString strCategory = dataLink.value.at(0);
  308. QString strCmd = dataLink.value.at(1);
  309. QString strDetail = dataLink.value.at(2);
  310. // 如果是系统命令
  311. if (strCategory == SYS_CMD_GROUP_NAME)
  312. {
  313. // 直接执行
  314. g_pRuntime->runCmd(strCmd, strDetail);
  315. }
  316. // 如果没有选择第三层级的内容,那么可能是选择了TOOL本身
  317. else if (strDetail.trimmed().isEmpty())
  318. {
  319. // 根据名字找到对应的TOOL*
  320. POU* pPou = g_pPouManager->getPouByName(strCategory);
  321. TOOL* pTool = pPou->GetToolByName(strCmd);
  322. if (pTool != nullptr)
  323. {
  324. // 弹出Tool中的对话框
  325. pTool->pDllPtr->ShowDialog();
  326. }
  327. else
  328. {
  329. QString strMsg = strCategory + "." + strCmd;
  330. qWarning() << strMsg << " is NULL";
  331. }
  332. }
  333. // 否则应该是Tool导出的Button接口
  334. else
  335. {
  336. // 交给父级统一处理
  337. g_pRuntime->runDllInterface(
  338. strCategory,
  339. strCmd,
  340. strDetail,
  341. pClickButton->m_Type
  342. );
  343. }
  344. }
  345. //=====================================================================
  346. //
  347. // 子控件同步相关
  348. //
  349. //=====================================================================
  350. /// <summary>
  351. /// 当Edit控件内容变更时
  352. /// </summary>
  353. /// <param name="strText"></param>
  354. void WindowRuntimeView::onVEditChanged(const QString& strText)
  355. {
  356. Q_UNUSED(strText);
  357. qDebug() << "WindowRuntimeView::onVEditChanged - " << strText;
  358. VLineEdit* pSender = qobject_cast<VLineEdit*>(sender());
  359. // 向UI同步
  360. g_pUiManager->syncFromRuntime(pSender, UI_SYNC_MSG::EDIT_TEXT_CHANGED);
  361. }
  362. /// <summary>
  363. /// ComboBox变更消息
  364. /// </summary>
  365. /// <param name="nIndex"></param>
  366. void WindowRuntimeView::onVComboChanged(const int nIndex)
  367. {
  368. Q_UNUSED(nIndex);
  369. qDebug() << "WindowRuntimeView::onVComboChanged - " << nIndex;
  370. VComboBox* pSender = qobject_cast<VComboBox*>(sender());
  371. // 向UI同步
  372. g_pUiManager->syncFromRuntime(pSender, UI_SYNC_MSG::COMBO_SEL_CHANGED);
  373. }
  374. /// <summary>
  375. /// ListBox变更消息
  376. /// </summary>
  377. /// <param name="nRow"></param>
  378. void WindowRuntimeView::onVListChanged(const int nRow)
  379. {
  380. Q_UNUSED(nRow);
  381. qDebug() << "WindowRuntimeView::onVListChanged - " << nRow;
  382. VListBox* pSender = qobject_cast<VListBox*>(sender());
  383. // 向UI同步
  384. g_pUiManager->syncFromRuntime(pSender, UI_SYNC_MSG::LIST_SEL_CHANGED);
  385. }
  386. /// <summary>
  387. /// RadioBox变更消息
  388. /// </summary>
  389. /// <param name="checked"></param>
  390. void WindowRuntimeView::onVRadioChanged(bool checked)
  391. {
  392. Q_UNUSED(checked);
  393. }
  394. /// <summary>
  395. /// CheckBox变更消息
  396. /// </summary>
  397. /// <param name="state"></param>
  398. void WindowRuntimeView::onVCheckChanged(int state)
  399. {
  400. Q_UNUSED(state);
  401. }
  402. /// <summary>
  403. /// 当Value控件内容变更时
  404. /// </summary>
  405. void WindowRuntimeView::onValueControlChanged(const QString& strText)
  406. {
  407. Q_UNUSED(strText);
  408. vDebug() << strText;
  409. ValueControl* pEdit = qobject_cast<ValueControl*>(sender());
  410. // 向UI同步
  411. g_pUiManager->syncFromRuntime(pEdit, UI_SYNC_MSG::VALUE_CHANGED);
  412. }
  413. /// <summary>
  414. /// 执行控件的首次同步
  415. /// </summary>
  416. /// <param name="pRtControl"></param>
  417. /// <param name="type"></param>
  418. void WindowRuntimeView::doFirstSync(QWidget* pUiControl, VALUE_TYPE controlType, const VARIABLE* pVariable)
  419. {
  420. if (pUiControl == nullptr)
  421. {
  422. return;
  423. }
  424. // 根据不同的类型执行首次同步
  425. switch (controlType)
  426. {
  427. case VALUE_TYPE::Control_ComboBox:
  428. g_pUiManager->syncToRuntime(pUiControl, UI_SYNC_MSG::COMBO_SEL_CHANGED, true);
  429. break;
  430. case VALUE_TYPE::Control_RadioBox:
  431. g_pUiManager->syncToRuntime(pUiControl, UI_SYNC_MSG::RADIOBOX_CHANGED, true);
  432. break;
  433. case VALUE_TYPE::Control_CheckBox:
  434. g_pUiManager->syncToRuntime(pUiControl, UI_SYNC_MSG::CHECKBOX_CHANGED, true);
  435. break;
  436. case VALUE_TYPE::Control_Listbox:
  437. g_pUiManager->syncToRuntime(pUiControl, UI_SYNC_MSG::LIST_SEL_CHANGED, true);
  438. break;
  439. case VALUE_TYPE::Control_LineEdit:
  440. g_pUiManager->syncToRuntime(pUiControl, UI_SYNC_MSG::EDIT_TEXT_CHANGED, true);
  441. break;
  442. // 2022-9-14 加入了ValueControl的首次同步
  443. case VALUE_TYPE::Control_Value:
  444. g_pUiManager->syncToRuntime(pUiControl, UI_SYNC_MSG::VALUE_CHANGED, true);
  445. break;
  446. case VALUE_TYPE::Control_Result:
  447. g_pUiManager->syncToRuntime(pUiControl, UI_SYNC_MSG::VALUE_CHANGED, true);
  448. break;
  449. case VALUE_TYPE::Control_Image:
  450. g_pRuntime->syncFromComplexSource(pVariable);
  451. break;
  452. default:
  453. break;
  454. }
  455. }
  456. //=====================================================================
  457. //
  458. // 复杂控件同步相关
  459. //
  460. //=====================================================================
  461. /// <summary>
  462. /// 解析复杂控件传入的扩展属性(用于执行扩展属性中的数值链接同步)
  463. /// </summary>
  464. /// <param name="propertyEx"></param>
  465. bool WindowRuntimeView::parseComplexPropertyEx(QWidget* pWidget, CONTROL_PROPERTY_EX* propertyEx)
  466. {
  467. VARIABLE* pValue = nullptr;
  468. DataLink dataLink;
  469. // 解析刷新索引值(索引值不允许defaultValue,所以此处如果刷新索引解析失败了则报错退出)
  470. bool bRet = this->parseDatalink(propertyEx->m_refreshLink, pValue);
  471. if (bRet)
  472. {
  473. g_pRuntime->registerNewIndex(pValue, pWidget);
  474. propertyEx->m_refreshLink.linkValue = pValue;
  475. vDebug() << "Bind refreshLink to [" << propertyEx->m_refreshLink.toString() << "].";
  476. }
  477. else
  478. {
  479. // TODO:这个默认值指针如果不传送出去的话,在execute的时候就触发不了(暂未启用)
  480. // g_pRuntime->registerNewIndex(propertyEx->m_refreshLink.defaultValue, pWidget);
  481. QString str = propertyEx->m_strTitle + "." + propertyEx->m_refreshLink.title;
  482. qWarning() << "[Error] WindowRuntimeView::parseComplexPropertyEx() -" << str << "Parse refreshLink failed.";
  483. return false;
  484. }
  485. // 解析主索引值(可能会有0个或者多个)
  486. for ( DataLink& dataLink : propertyEx->m_mainDataLinks )
  487. {
  488. bool bRet = this->parseDatalink(dataLink, pValue);
  489. if (bRet)
  490. {
  491. // 注册新的变量
  492. g_pRuntime->registerNewVariable(pWidget, dataLink.title, pValue);
  493. }
  494. // 错误
  495. else
  496. {
  497. qDebug() << "[Error] WindowRuntimeView::parseComplexPropertyEx() - Parse mainLink failed.";
  498. return false;
  499. }
  500. }
  501. // 解析其他数据链接数值(如果解析失败,直接用默认值)
  502. for (int i = 0; i < propertyEx->m_groups.size(); i++)
  503. {
  504. PROPERTY_EX_SUBGROUPS& subGroups = propertyEx->m_groups[i].subGroups;
  505. for (int j = 0; j < subGroups.size(); j++)
  506. {
  507. for (DataLink& dataLink : subGroups[j].dataLinks)
  508. {
  509. bool bRet = this->parseDatalink(dataLink, pValue);
  510. // 2022-1-18,如果没有解析成功,那么直接用默认值
  511. if (bRet)
  512. {
  513. // 在Runtime中保存 控件-接口 对应关系
  514. g_pRuntime->registerNewVariable(pWidget, dataLink.title, pValue);
  515. }
  516. // 默认值
  517. else
  518. {
  519. // 在Runtime中保存 控件-接口 对应关系
  520. g_pRuntime->registerNewVariable(pWidget, dataLink.title, dataLink.defaultValue);
  521. }
  522. }
  523. }
  524. }
  525. return true;
  526. }
  527. /// <summary>
  528. /// 解析Datalink信息
  529. /// </summary>
  530. /// <param name="dataLink"></param>
  531. /// <param name="pVar"></param>
  532. /// <returns></returns>
  533. bool WindowRuntimeView::parseDatalink(
  534. DataLink& dataLink,
  535. VARIABLE*& pVar
  536. )
  537. {
  538. // 2022-1-18,首先判断数据连接是否有效,因为有的数据链接不是强制赋值的
  539. // 到了这里可能会有直接录入数字的,或者留空的
  540. if (dataLink.value.size() != 3)
  541. {
  542. return false;
  543. }
  544. POU* pPou = nullptr;
  545. TOOL* pTool = nullptr;
  546. // 从DataLink信息中解析出接口信息
  547. QString strCategory = dataLink.value.at(0);
  548. QString strType = dataLink.value.at(1);
  549. QString strDetail = dataLink.value.at(2);
  550. // 判断变量源是来自于Tool还是来自于全局变量
  551. bool bVariables = false;
  552. if (strType.indexOf(GROUP_GLOBAL_VARIABLE) >= 0
  553. || strType.indexOf(GROUP_LOCAL_VARIABLE) >= 0)
  554. {
  555. bVariables = true;
  556. }
  557. // Tool接口
  558. if (!bVariables)
  559. {
  560. // 根据名字找到对应的_INTERFACE*
  561. pPou = g_pPouManager->getPouByName(strCategory);
  562. pTool = pPou->GetToolByName(strType);
  563. if (pTool)
  564. {
  565. pVar = pTool->getInterfaceByName(strDetail);
  566. if (pVar == nullptr)
  567. {
  568. QString str = strCategory + "." + strType;
  569. qWarning() << "[Error] Link To [" << str << "] Interface failed.";
  570. return false;
  571. }
  572. }
  573. else
  574. {
  575. return false;
  576. }
  577. }
  578. // 局部和全局变量
  579. else
  580. {
  581. strCategory.remove(VAR_SUFFIX);
  582. strType = strCategory;
  583. pTool = g_pGvlManager->getGvl(strType);
  584. pVar = pTool->getInterfaceByName(strDetail);
  585. if (pVar == nullptr)
  586. {
  587. QString str = strCategory + VAR_SUFFIX + "." + strDetail ;
  588. qWarning() << "[Error] Link To [" << str << "] Interface failed.";
  589. return false;
  590. }
  591. }
  592. //// 2022-1-18,变量在属性表中的属性名字(用于后续更新使用)
  593. //pVar->strPropertyName = dataLink.title;
  594. // 在dataLink中保存对应的VARIABLE*指针
  595. dataLink.linkValue = pVar;
  596. return true;
  597. }