Pou.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264
  1. #include "Pou.h"
  2. #include "WindowAppItemInterface.h"
  3. #include "WindowAppBlockStandard.h"
  4. #include "WindowAppBlockStandardBase.h"
  5. #include "WindowAppBlockGoto.h"
  6. #include "WindowAppVariableTable.h"
  7. #include "GvlManager.h"
  8. #include "TaskManager.h"
  9. #include "../Common/CameraBaseClass/IBaseCamCommon.h"
  10. #include "../Common/CameraBaseClass/IBaseCamera.h"
  11. #include "WindowAppTaskView.h"
  12. POU::POU()
  13. {
  14. m_nExecuteIndex = 0;
  15. // 并行工具线程池支持的最大并行工具数量
  16. m_ParallelThreadPool.setMaxThreadCount(MAX_PARALLEL_TOOL_COUNT);
  17. }
  18. /// <summary>
  19. /// 2022-2-16,在Pou析构的时候需要释放掉内部变量
  20. /// </summary>
  21. POU::~POU()
  22. {
  23. g_pGvlManager->removeVariable(m_strPouName, INTERNALVAR_NAME_EXECTIME);
  24. g_pGvlManager->removeVariable(m_strPouName, INTERNALVAR_NAME_EXECCOUNT);
  25. g_pGvlManager->removeVariable(m_strPouName, INTERNALVAR_NAME_ERRORCOUNT);
  26. }
  27. /// <summary>
  28. /// 重置本Pou中所有的数据结构
  29. /// </summary>
  30. void POU::reset()
  31. {
  32. // 遍历所有的工具
  33. QHash<WindowAppBlockBase*, TOOL*>::iterator iter = m_itemToTools.begin();
  34. while (iter != m_itemToTools.end())
  35. {
  36. // 回收资源
  37. if (iter.value()->pDllPtr != nullptr)
  38. {
  39. delete iter.value()->pDllPtr;
  40. iter.value()->pDllPtr = nullptr;
  41. }
  42. // 从界面中移除此功能块
  43. QString str = iter.value()->strInstanceName;
  44. WindowAppBlockBase* pItem = m_instNameToToolItems[str];
  45. if (pItem != nullptr)
  46. {
  47. pItem->scene()->removeItem(pItem);
  48. }
  49. iter++;
  50. }
  51. m_instNameToTools.clear();
  52. m_fullNameToInterfaces.clear();
  53. m_itemToTools.clear();
  54. m_itemToInterfaces.clear();
  55. m_instNameToToolItems.clear();
  56. m_fullNameToInterfaceItems.clear();
  57. m_AutoToolRenameIndex.clear();
  58. m_Links.clear();
  59. }
  60. /// <summary>
  61. /// 添加一个运行的Tool功能块到当前Pou中
  62. /// </summary>
  63. /// <param name="pRunningBlock"></param>
  64. void POU::registerTool(WindowAppBlockBase* pBlockItem, TOOL* pRunningTool)
  65. {
  66. // 保存功能块和工具的对应信息
  67. m_itemToTools.insert(pBlockItem, pRunningTool);
  68. m_instNameToTools.insert(pRunningTool->strInstanceName, pRunningTool);
  69. m_instNameToToolItems.insert(pRunningTool->strInstanceName, pBlockItem);
  70. // 重命名计数 + 1
  71. AddRenameRefCount(pRunningTool->strName);
  72. // 2021-8-14 如果是StandardTool,则刷新StandardTools列表
  73. // 2022-3-28 更新 (NOTICE:此处是包含了标准工具和Goto工具一起的)
  74. // 2022-4-28 加入了Parallel工具
  75. // 2022-8-25 加入了ForLoop工具
  76. if (pRunningTool->isIndexedTool() )
  77. {
  78. m_StandardTools.push_back(pRunningTool);
  79. // 2022-3-31更新,此处要保证严格有序,否则反序列化或者其他时候可能会有各种隐患
  80. std::sort(m_StandardTools.begin(), m_StandardTools.end(), TOOL::sort_by_index);
  81. // 2021-8-14 Pou中添加工具后,如果当前Pou被Task选中,则需要向Task同步新增加的Tool信息
  82. if (m_pParentTask != nullptr)
  83. {
  84. g_pTaskManager->addToolToTaskView(m_pParentTask->strName, this, pRunningTool);
  85. }
  86. }
  87. #ifdef QT_NO_DEBUG
  88. #else
  89. // 输出调试信息
  90. // debugAllTools();
  91. #endif
  92. }
  93. /// <summary>
  94. /// 添加一个运行的接口到当前Pou中
  95. /// </summary>
  96. /// <param name="pActiveInf"></param>
  97. /// <param name="pSelInf"></param>
  98. void POU::registerInterface(WindowAppItemInterface* pInfItem, _INTERFACE* pSelInf)
  99. {
  100. if (pInfItem == nullptr || pSelInf == nullptr)
  101. {
  102. qDebug() << "[Error] POU::registerInterface - but pInfItem or pSelInf is nullptr.";
  103. return;
  104. }
  105. QString strInfName = QString(pInfItem->m_infInfo->strFullName);
  106. m_itemToInterfaces.insert(pInfItem, pSelInf);
  107. m_fullNameToInterfaces.insert(strInfName, pSelInf);
  108. m_fullNameToInterfaceItems.insert(strInfName, pInfItem);
  109. // 输出接口信息
  110. // debugAllInterface();
  111. }
  112. /// <summary>
  113. /// 移除一个运行的Tool功能块
  114. /// </summary>
  115. /// <param name="pRunningBlock"></param>
  116. void POU::removeTool(QGraphicsItem* pBlockItem)
  117. {
  118. Q_UNUSED(pBlockItem);
  119. //for (QVector<SEL_TOOL>::iterator it = m_SelTools.begin();it != m_SelTools.end();)
  120. //{
  121. // if (it->item == pRunningBlock)
  122. // {
  123. // it = m_SelTools.erase(it);
  124. // }
  125. // else
  126. // {
  127. // it++;
  128. // }
  129. //}
  130. #ifdef QT_NO_DEBUG
  131. #else
  132. // 输出调试信息
  133. // debugAllTools();
  134. #endif
  135. }
  136. /// <summary>
  137. /// 显示当前工具对话框
  138. /// </summary>
  139. /// <param name="pBlockItem"></param>
  140. void POU::ShowToolDialog(WindowAppBlockStandardBase* pBlockItem)
  141. {
  142. m_itemToTools.value(pBlockItem)->pDllPtr->ShowDialog();
  143. }
  144. DebugData POU::GetToolDebugData(WindowAppBlockStandardBase* pBlockItem)
  145. {
  146. if (m_itemToTools.value(pBlockItem) != nullptr && m_itemToTools.value(pBlockItem)->pDllPtr)
  147. {
  148. return m_itemToTools.value(pBlockItem)->pDllPtr->GetDebugData();
  149. }
  150. DebugData data;
  151. return data;
  152. }
  153. /// <summary>
  154. /// 序号+1
  155. /// </summary>
  156. /// <param name="pBlockItem"></param>
  157. void POU::ToolMoveDown(WindowAppBlockStandardBase* pBlockItem)
  158. {
  159. TOOL* pMovTool = m_itemToTools.value(pBlockItem);
  160. int nCurIndex = pMovTool->nIndex;
  161. // 如果只剩1个工具或者本身就是最后一个工具的话,则忽略这个操作
  162. if (m_itemToTools.size() <= 1
  163. || nCurIndex >= m_itemToTools.size() - 1)
  164. {
  165. return;
  166. }
  167. int nAjustIndex = nCurIndex + 1;
  168. // 交换一下邻接的工具序号
  169. QHash<WindowAppBlockBase*, TOOL*>::iterator iter = m_itemToTools.begin();
  170. while (iter != m_itemToTools.end())
  171. {
  172. if (iter.value()->nIndex == nAjustIndex)
  173. {
  174. iter.value()->nIndex--;
  175. break;
  176. }
  177. iter++;
  178. }
  179. // 修正自身序号
  180. m_itemToTools.value(pBlockItem)->nIndex++;
  181. // 移动StandardToolList
  182. m_StandardTools.removeOne(pMovTool);
  183. m_StandardTools.insert(nAjustIndex, pMovTool);
  184. // 2022-3-6,检测功能块的变动是否需要向Task同步
  185. this->syncToolMoveToTaskView();
  186. }
  187. /// <summary>
  188. /// 序号-1
  189. /// </summary>
  190. /// <param name="pBlockItem"></param>
  191. void POU::ToolMoveUp(WindowAppBlockStandardBase* pBlockItem)
  192. {
  193. TOOL* pMovTool = m_itemToTools.value(pBlockItem);
  194. int nCurIndex = pMovTool->nIndex;
  195. // 如果只剩1个工具或者本身就是第一个工具的话,则忽略这个操作
  196. if (m_itemToTools.size() <= 1 || nCurIndex == 0)
  197. {
  198. return;
  199. }
  200. int nAjustIndex = nCurIndex - 1;
  201. // 交换一下邻接的工具序号
  202. QHash<WindowAppBlockBase*, TOOL*>::iterator iter = m_itemToTools.begin();
  203. while (iter != m_itemToTools.end())
  204. {
  205. if (iter.value()->nIndex == nAjustIndex)
  206. {
  207. iter.value()->nIndex++;
  208. break;
  209. }
  210. iter++;
  211. }
  212. // 修正自身序号
  213. m_itemToTools.value(pBlockItem)->nIndex--;
  214. // 移动StandardToolList
  215. m_StandardTools.removeOne(pMovTool);
  216. m_StandardTools.insert(nAjustIndex, pMovTool);
  217. // 2022-3-6,检测功能块的变动是否需要向Task同步
  218. this->syncToolMoveToTaskView();
  219. }
  220. /// <summary>
  221. /// 执行顺序移动到最前端
  222. /// </summary>
  223. /// <param name="pBlockItem"></param>
  224. void POU::ToolMoveFirst(WindowAppBlockStandardBase* pBlockItem)
  225. {
  226. TOOL* pMovTool = m_itemToTools.value(pBlockItem);
  227. int& nCurIndex = pMovTool->nIndex;
  228. // 所有工具序号后移
  229. QHash<WindowAppBlockBase*, TOOL*>::iterator iter = m_itemToTools.begin();
  230. while (iter != m_itemToTools.end())
  231. {
  232. if (iter.value()->nIndex < nCurIndex)
  233. {
  234. iter.value()->nIndex++;
  235. }
  236. iter++;
  237. }
  238. // 修正自身序号
  239. nCurIndex = 0;
  240. // 移动StandardToolList
  241. m_StandardTools.removeOne(pMovTool);
  242. m_StandardTools.push_front(pMovTool);
  243. // 2022-3-6,检测功能块的变动是否需要向Task同步
  244. this->syncToolMoveToTaskView();
  245. }
  246. /// <summary>
  247. /// 执行顺序移动到最后端
  248. /// </summary>
  249. /// <param name="pBlockItem"></param>
  250. void POU::ToolMoveLast(WindowAppBlockStandardBase* pBlockItem)
  251. {
  252. TOOL* pMovTool = m_itemToTools.value(pBlockItem);
  253. int nLastIndex = m_itemToTools.size() - 1;
  254. int& nCurIndex = pMovTool->nIndex;
  255. // 所有工具序号前移
  256. QHash<WindowAppBlockBase*, TOOL*>::iterator iter = m_itemToTools.begin();
  257. while (iter != m_itemToTools.end())
  258. {
  259. if (iter.value()->nIndex > nCurIndex)
  260. {
  261. iter.value()->nIndex--;
  262. }
  263. iter++;
  264. }
  265. // 修正自身序号
  266. nCurIndex = nLastIndex;
  267. // 移动StandardTools
  268. m_StandardTools.removeOne(pMovTool);
  269. m_StandardTools.push_back(pMovTool);
  270. // 2022-3-6,检测功能块的变动是否需要向Task同步
  271. this->syncToolMoveToTaskView();
  272. }
  273. /// <summary>
  274. /// 复制功能块本身
  275. /// </summary>
  276. /// <param name="pBlockItem"></param>
  277. void POU::ToolCopyBlock(WindowAppBlockStandardBase* pBlockItem)
  278. {
  279. TOOL* pActiveTool = m_itemToTools.value(pBlockItem);
  280. if (pActiveTool)
  281. {
  282. }
  283. }
  284. /// <summary>
  285. /// 复制功能块的数据
  286. /// </summary>
  287. /// <param name="pBlockItem"></param>
  288. void POU::ToolCopyData(WindowAppBlockStandardBase* pBlockItem)
  289. {
  290. TOOL* pActiveTool = m_itemToTools.value(pBlockItem);
  291. if (pActiveTool)
  292. {
  293. m_BufferTemp.open(QIODevice::WriteOnly);
  294. QDataStream ar(&m_BufferTemp);
  295. ar << pActiveTool->strName;
  296. pActiveTool->pDllPtr->SerializedToDoc(ar);
  297. }
  298. }
  299. /// <summary>
  300. /// 粘贴数据
  301. /// </summary>
  302. /// <param name="pBlockItem"></param>
  303. void POU::ToolPaste(WindowAppBlockStandardBase* pBlockItem)
  304. {
  305. TOOL* pActiveTool = m_itemToTools.value(pBlockItem);
  306. if (pActiveTool)
  307. {
  308. m_BufferTemp.open(QIODevice::ReadOnly);
  309. QDataStream ar(&m_BufferTemp);
  310. QString strName;
  311. ar >> strName;
  312. if (strName == pActiveTool->strName)
  313. {
  314. pActiveTool->pDllPtr->SerializedFromDoc(ar);
  315. }
  316. else
  317. {
  318. qWarning() << "Paste Error Data Source is" << strName;
  319. }
  320. m_BufferTemp.close();
  321. }
  322. }
  323. /// <summary>
  324. /// 删除指定工具
  325. /// </summary>
  326. /// <param name="pBlockItem"></param>
  327. void POU::ToolDelete(WindowAppBlockBase* pBlockItem)
  328. {
  329. //// 跳过注释工具
  330. //if (pBlockItem->m_toolInfo->isCommentTool())
  331. //{
  332. // return;
  333. //}
  334. vDebug() << "Delete tool[" << pBlockItem->m_toolInfo->strInstanceName << "].";
  335. // 如果是带序号的工具,需要先调整一下序号
  336. if (pBlockItem->m_toolInfo->isIndexedTool())
  337. {
  338. // 调整其他功能块的序号
  339. int nCurIndex = m_itemToTools.value(pBlockItem)->nIndex;
  340. // 2021-8-14 移除StandardTools列表中的信息
  341. m_StandardTools.removeOne(m_itemToTools.value(pBlockItem));
  342. // 遍历所有的工具
  343. QHash<WindowAppBlockBase*, TOOL*>::iterator iter = m_itemToTools.begin();
  344. while (iter != m_itemToTools.end())
  345. {
  346. // 后面的序号前移
  347. if (iter.value()->nIndex > nCurIndex)
  348. {
  349. iter.value()->nIndex--;
  350. }
  351. iter++;
  352. }
  353. // 回收工具的Dll资源(仅标准工具才有)
  354. if (m_itemToTools.value(pBlockItem)->pDllPtr != nullptr)
  355. {
  356. delete m_itemToTools.value(pBlockItem)->pDllPtr;
  357. m_itemToTools.value(pBlockItem)->pDllPtr = nullptr;
  358. }
  359. }
  360. // 先移除工具中的Interface信息
  361. QVectorIterator<_INTERFACE*> it(m_itemToTools.value(pBlockItem)->Interfaces);
  362. while (it.hasNext())
  363. {
  364. _INTERFACE* pInf = it.next();
  365. m_itemToInterfaces.remove(m_fullNameToInterfaceItems.value(pInf->strFullName));
  366. m_fullNameToInterfaces.remove(pInf->strFullName);
  367. m_fullNameToInterfaceItems.remove(pInf->strFullName);
  368. }
  369. // 如果删除的是硬件组态里的工具,需要清理绑定信息
  370. if (pBlockItem->m_toolInfo->isHardwareTool())
  371. {
  372. g_pGvlManager->unbindHdwToolAndDB(pBlockItem->m_toolInfo, pBlockItem->m_toolInfo->strHdwInstName);
  373. }
  374. // 移除此工具
  375. m_itemToTools.remove(pBlockItem);
  376. m_instNameToTools.remove(pBlockItem->m_toolInfo->strInstanceName);
  377. m_instNameToToolItems.remove(pBlockItem->m_toolInfo->strInstanceName);
  378. // 工具的重命名计数减一
  379. m_AutoToolRenameIndex[pBlockItem->m_toolInfo->strName] --;
  380. // 2022-9-4 加入,由于有Wait工具的存在,所以需要到TaskManager中反注册一下
  381. if (pBlockItem->m_toolInfo->isWaitTool())
  382. {
  383. g_pTaskManager->unregisterTool(pBlockItem->m_toolInfo);
  384. }
  385. //#ifdef QT_NO_DEBUG
  386. //#else
  387. // // 输出调试信息
  388. // debugAllTools();
  389. // debugAllInterface();
  390. //#endif
  391. }
  392. /// <summary>
  393. /// 保存Link信息
  394. /// </summary>
  395. /// <param name="startInf"></param>
  396. /// <param name="endInf"></param>
  397. void POU::makeLink(
  398. WindowAppItemInterface* srcInfItem,
  399. WindowAppItemInterface* dstInfItem,
  400. WindowAppItemLink* linkItem,
  401. LINK_MODE linkMode
  402. )
  403. {
  404. // 起始接口
  405. _INTERFACE* srcInf = m_itemToInterfaces.value(srcInfItem);
  406. if (srcInf == nullptr)
  407. {
  408. qDebug() << "[POU][LINK] Make link Error: startInf is nullptr.";
  409. return;
  410. }
  411. // 终止接口
  412. _INTERFACE* dstInf = m_itemToInterfaces.value(dstInfItem);
  413. if (dstInf == nullptr)
  414. {
  415. qDebug() << "[POU][LINK] Make link Error: endInf is nullptr.";
  416. return;
  417. }
  418. // 建立Link
  419. dstInf->pUpLinkInterface = srcInf;
  420. srcInf->pDownLinkInterfaces.push_back(dstInf);
  421. // 引用计数 + 1
  422. srcInf->nRefCount++;
  423. dstInf->nRefCount++;
  424. // 2022-8-28去掉,改为运行时实时判定
  425. //// 2022-5-4增加,如果是Parallel模式连接,则还需要把被连接的Tool设置为并行模式
  426. //if (linkMode == LINK_MODE::LINK_PARALLEL)
  427. //{
  428. // dstInf->parent()->bParallelized = true;
  429. //}
  430. // 2022-6-12增加,保存本Link信息用于统一管理
  431. this->registerLink(srcInfItem, dstInfItem, linkItem, linkMode);
  432. //// 2022-9-5增加,此处需要在链接的时候直接启动并行子工具线程(并行工具的新启动机制)
  433. //this->addParallelSubTool(dstInfItem->m_infInfo->parent());
  434. qDebug() << "[POU][LINK] Make link: " << srcInf->parent()->strInstanceName
  435. << "-" << srcInf->strName << " --> " << dstInf->parent()->strInstanceName << "-" << dstInf->strName;
  436. }
  437. /// <summary>
  438. /// 清除Link信息
  439. /// </summary>
  440. /// <param name="endInf"></param>
  441. void POU::removeLink(WindowAppItemInterface* endInfItem)
  442. {
  443. // 从上联接口中移除其下联接口信息
  444. QVector<_INTERFACE*>& pDownInterfaces = m_itemToInterfaces.value(endInfItem)->pUpLinkInterface->pDownLinkInterfaces;
  445. for (QVector<_INTERFACE*>::iterator it = pDownInterfaces.begin(); it != pDownInterfaces.end();)
  446. {
  447. if (*it == m_itemToInterfaces.value(endInfItem))
  448. {
  449. //// 2022-5-6,移除被连接Tool的并行模式标志(删除并行link等于移出了并行组)
  450. //if ((*it)->parent()->bParallelized)
  451. //{
  452. // (*it)->parent()->bParallelized = false;
  453. //}
  454. it = pDownInterfaces.erase(it);
  455. }
  456. else
  457. {
  458. it++;
  459. }
  460. }
  461. // 移除对应接口的上行连接信息
  462. m_itemToInterfaces.value(endInfItem)->pUpLinkInterface = nullptr;
  463. // 2022-6-13 增加,移除Link的注册信息
  464. this->unregisterLink(endInfItem);
  465. }
  466. /// <summary>
  467. /// 注册新的Link信息
  468. /// </summary>
  469. /// <param name="strSrcInfFullName"></param>
  470. /// <param name="strDstInfFullName"></param>
  471. /// <param name="linkMode"></param>
  472. void POU::registerLink(
  473. WindowAppItemInterface* startInfItem,
  474. WindowAppItemInterface* endInfItem,
  475. WindowAppItemLink* linkItem,
  476. LINK_MODE linkMode
  477. )
  478. {
  479. LINK newLink;
  480. newLink.linkMode = linkMode;
  481. newLink.pSrcItem = startInfItem;
  482. newLink.pDstItem = endInfItem;
  483. newLink.pLinkItem = linkItem;
  484. m_Links.push_back(newLink);
  485. qDebug() << "POU::registerLink - Inf[" << endInfItem->m_infInfo->strFullName << "]";
  486. }
  487. /// <summary>
  488. /// 反注册Link信息
  489. /// </summary>
  490. /// <param name="strSrcInfFullName"></param>
  491. /// <param name="strDstInfFullName"></param>
  492. void POU::unregisterLink(WindowAppItemInterface* endInfItem)
  493. {
  494. for (auto it = m_Links.begin(); it != m_Links.end();)
  495. {
  496. if (it->pDstItem == endInfItem)
  497. {
  498. it = m_Links.erase(it);
  499. qDebug() << "POU::unregisterLink - Inf[" << endInfItem->m_infInfo->strFullName << "]";
  500. break;
  501. }
  502. else
  503. {
  504. ++it;
  505. }
  506. }
  507. }
  508. /// <summary>
  509. /// 将指定接口绑定到指定Port中
  510. /// </summary>
  511. /// <param name="pPort"></param>
  512. /// <param name="pInf"></param>
  513. void POU::bindPortAndInterface(WindowAppBlockBase* pPortItem, _INTERFACE* pBindInf, const QString& strInfName)
  514. {
  515. // 2021-6-6 增加,被绑定接口的引用计数需要 + 1
  516. pBindInf->nRefCount++;
  517. _INTERFACE* pPortInf = m_itemToTools.value(pPortItem)->Interfaces[0];
  518. // 将绑定接口的信息复制过来
  519. pPortInf->strName = strInfName;
  520. // TODO:此处这个全名是有问题的,接口名字必须全局唯一,但是这里重复了,strFullName暂时不改了
  521. // pPortInf->strFullName = pBindInf->strFullName;
  522. pPortInf->strComment = pBindInf->strComment;
  523. pPortInf->bSerialized = pBindInf->bSerialized;
  524. // 2021-5-24 修正,由于GVl变量是双向的,此处需要强制设置为和Port方向一致
  525. // pPortInf->InfDirection = pBindInf->InfDirection;
  526. pPortInf->Type = pBindInf->Type;
  527. // 指针直接复制,这样值就可以双方同步了
  528. pPortInf->value = pBindInf->value;
  529. pPortInf->nIndex = pBindInf->nIndex;
  530. pPortInf->strNameWithType= pBindInf->strNameWithType;
  531. //// 2021-6-12 修正port绑定接口的时候造成的崩溃bug
  532. //// 修改连父工具指针一起复制过去
  533. //pPortInf->pParentTool = pBindInf->pParentTool;
  534. // 这三个属性是否需要复制待定
  535. //pPortInf->bShow = pBindInf->bShow;
  536. //pPortInf->bWatch = pBindInf->bWatch;
  537. // 2021-6-5增加,直接复制link信息,并且整理旧接口相关的link关系
  538. // For test
  539. //pPortInf->setValue<int>(50);
  540. //g_pVariablesManager->debugVariable(pPortInf);
  541. //g_pVariablesManager->debugVariable(m_ItemPorts[pPortItem]->Interface);
  542. //g_pVariablesManager->debugAllVariables();
  543. qDebug() << "[POU][PORT]: bind " << pPortInf->strName << " to port.";
  544. }
  545. /// <summary>
  546. /// 获取指定Item的绝对坐标
  547. /// </summary>
  548. /// <param name="strKey"></param>
  549. /// <returns></returns>
  550. QPointF POU::GetToolItemPos(QString strKey)
  551. {
  552. return m_instNameToToolItems.value(strKey)->scenePos();
  553. }
  554. /// <summary>
  555. /// 2022-3-12,删除指定的接口相关数据结构
  556. /// </summary>
  557. /// <param name="pItem"></param>
  558. /// <param name="strFullName"></param>
  559. void POU::DelInterface(const QString& strFullName, WindowAppItemInterface* pItem, _INTERFACE* pInf)
  560. {
  561. Q_UNUSED(pInf);
  562. m_fullNameToInterfaces.remove(strFullName);
  563. m_itemToInterfaces.remove(pItem);
  564. m_fullNameToInterfaceItems.remove(strFullName);
  565. }
  566. /// <summary>
  567. /// 根据接口中对应的Dll数值获取接口指针(UIManager中使用)
  568. /// </summary>
  569. /// <param name="pValue"></param>
  570. /// <returns></returns>
  571. _INTERFACE* POU::GetInterfaceByValuePtr(void* pValue)
  572. {
  573. QMapIterator<QString, _INTERFACE*> iter(m_fullNameToInterfaces);
  574. while (iter.hasNext())
  575. {
  576. _INTERFACE* pInf = iter.next().value();
  577. // 2022-5-18 增加,由于每个Tool多了一个ToolStart接口,所以这里要把ToolStart接口过滤掉,否则会崩溃
  578. if(pInf->nIndex<0)
  579. {
  580. continue;
  581. }
  582. void** pValuePtr = pInf->getValuePtr();
  583. if (pValuePtr == pValue)
  584. {
  585. return pInf;
  586. }
  587. }
  588. return nullptr;
  589. }
  590. /// <summary>
  591. /// 重命名计数 + 1
  592. /// </summary>
  593. /// <param name="strName"></param>
  594. void POU::AddRenameRefCount(const QString& strName)
  595. {
  596. m_AutoToolRenameIndex[strName]++;
  597. }
  598. /// <summary>
  599. /// 获取所有的Event类型接口(如果有)
  600. /// </summary>
  601. /// <returns></returns>
  602. QMap<QString, EVENT*> POU::getAllEvents()
  603. {
  604. QMap<QString, EVENT*> m_Events;
  605. QMapIterator<QString, EVENT*> iter(m_fullNameToInterfaces);
  606. while (iter.hasNext())
  607. {
  608. if (iter.next().value()->Type==INF_TYPE::INF_TYPE_EVENT
  609. //&& iter.value()->eventTrigger !=nullptr
  610. )
  611. {
  612. m_Events.insert(iter.key(), iter.value());
  613. }
  614. }
  615. return m_Events;
  616. }
  617. /// <summary>
  618. /// 生成工具新的实例名字
  619. /// </summary>
  620. /// <param name="strToolName"></param>
  621. /// <returns></returns>
  622. QString POU::genToolInstanceName(const QString& strToolName)
  623. {
  624. // 根据引用计数生成工具的实例名字
  625. int nRefCount = m_AutoToolRenameIndex.value(strToolName) + 1;
  626. return QString(strToolName + " " + QString::number(nRefCount));
  627. }
  628. /// <summary>
  629. /// 设置工具的启用禁用
  630. /// </summary>
  631. /// <param name="pToolInfo"></param>
  632. /// <param name="bEnable"></param>
  633. void POU::setToolEnable(const TOOL* pToolInfo, bool bEnable)
  634. {
  635. m_instNameToTools.value(pToolInfo->strInstanceName)->bEnable = bEnable;
  636. }
  637. /// <summary>
  638. /// 设置接口的启用禁用
  639. /// </summary>
  640. /// <param name="pInfInfo"></param>
  641. /// <param name="bEnable"></param>
  642. bool POU::setInterfaceEnable(const _INTERFACE* pInfInfo, bool bEnable)
  643. {
  644. // 需要参考引用计数,如果计数错误则不允许切换
  645. if (pInfInfo->nRefCount > 0)
  646. {
  647. return false;
  648. }
  649. m_fullNameToInterfaces.value(pInfInfo->strFullName)->bEnable = bEnable;
  650. return true;
  651. }
  652. /// <summary>
  653. /// 设置接口的启用禁用(根据接口序号设置)
  654. /// </summary>
  655. /// <param name="pToolInfo"></param>
  656. /// <param name="nInfIndex"></param>
  657. /// <param name="bEnable"></param>
  658. bool POU::setInterfaceEnable(const TOOL* pToolInfo, int nInfIndex, bool bEnable)
  659. {
  660. _INTERFACE* pInf = m_instNameToTools.value(pToolInfo->strInstanceName)->Interfaces[nInfIndex];
  661. // 需要参考引用计数,如果计数错误则不允许切换
  662. if (pInf->nRefCount > 0)
  663. {
  664. return false;
  665. }
  666. pInf->bEnable = bEnable;
  667. return true;
  668. }
  669. /// <summary>
  670. /// 更新工具的Info
  671. /// </summary>
  672. /// <param name="pToolInfo"></param>
  673. /// <param name="strInfo"></param>
  674. void POU::setToolInfo(const TOOL* pToolInfo, const QString& strInfo)
  675. {
  676. m_instNameToTools.value(pToolInfo->strInstanceName)->strInfo = strInfo;
  677. }
  678. /// <summary>
  679. /// 设置工具的延时参数
  680. /// </summary>
  681. /// <param name="inDelay"></param>
  682. /// <param name="outDelay"></param>
  683. void POU::setToolDelay(const TOOL* pToolInfo, const int inDelay, const int outDelay)
  684. {
  685. m_instNameToTools.value(pToolInfo->strInstanceName)->execParams.nPreDelay = inDelay;
  686. m_instNameToTools.value(pToolInfo->strInstanceName)->execParams.nPostDelay = outDelay;
  687. }
  688. /// <summary>
  689. /// 设置工具的实例名称
  690. /// </summary>
  691. /// <param name="strInsName"></param>
  692. void POU::setInstanceName(const TOOL* pToolInfo, const QString& strNewInsName, const QString& strOldInsName)
  693. {
  694. Q_UNUSED(pToolInfo);
  695. // 保留一下旧数据
  696. TOOL* tool = m_instNameToTools.value(strOldInsName);
  697. WindowAppBlockBase* pItem = m_instNameToToolItems[strOldInsName];
  698. // 更名,设置别名
  699. m_instNameToTools.value(strOldInsName)->strAliasName = strOldInsName;
  700. m_instNameToTools.value(strOldInsName)->strInstanceName = strNewInsName;
  701. // 删掉旧的数据
  702. m_instNameToTools.remove(strOldInsName);
  703. m_instNameToToolItems.remove(strOldInsName);
  704. // 添加新的数据,保持key一致
  705. m_instNameToTools.insert(strNewInsName, tool);
  706. m_instNameToToolItems.insert(strNewInsName, pItem);
  707. // 设置新的实例化名称到工具
  708. if (tool->pDllPtr)
  709. {
  710. tool->pDllPtr->ModToolInstanceName(strNewInsName);
  711. }
  712. }
  713. /// <summary>
  714. /// 检查工具的实例名称是否重复(用于在Dialog对话框中判断用户是否可以重命名工具)
  715. /// </summary>
  716. /// <param name="strInsName"></param>
  717. /// <returns></returns>
  718. bool POU::isInstanceNameDuplicated(const QString& strInsName)
  719. {
  720. QMap<QString, TOOL*>::iterator it = m_instNameToTools.find(strInsName);
  721. if (it != m_instNameToTools.end())
  722. {
  723. return true;
  724. }
  725. return false;
  726. }
  727. /// <summary>
  728. /// 查询可执行SmartLink的接口(找离本接口最近的同类型输出端口,序号小于自己的,当然不一定能够找到)
  729. /// </summary>
  730. /// <param name="pInf"></param>
  731. /// <returns></returns>
  732. WindowAppItemInterface* POU::getSmartLinkInterface(const WindowAppItemInterface* pInf)
  733. {
  734. // 查询序号小于本接口的工具
  735. TOOL* pTool = pInf->m_infInfo->parent();
  736. QHash<WindowAppBlockBase*, TOOL*>::const_iterator it;
  737. int nCount = m_itemToTools.size();
  738. for (int i = 0; i < nCount; i++)
  739. {
  740. int nTargetIndex = pTool->nIndex - i - 1;
  741. if (nTargetIndex < 0)
  742. {
  743. return nullptr;
  744. }
  745. it = m_itemToTools.constBegin();
  746. // 遍历所有工具
  747. for (; it != m_itemToTools.constEnd(); ++it)
  748. {
  749. // qDebug() << i.key() << ":" << i.value();
  750. // 找到对应的序号
  751. if (it.value()->nIndex == nTargetIndex)
  752. {
  753. // 查找是否有符合的工具
  754. TOOL* pLinkTool = it.value();
  755. for (int m = 0; m < pLinkTool->Interfaces.size(); m++)
  756. {
  757. _INTERFACE* pLinkInf = pLinkTool->Interfaces[m];
  758. // 方向为输出并且类型相同的接口,并且接口处于可用状态
  759. if (pLinkInf->Direction == INF_DIRECTION::INF_DIR_OUT
  760. && pLinkInf->isSameTypeTo(pInf->m_infInfo)
  761. && pLinkInf->bEnable)
  762. {
  763. // return pLinkTool->Interfaces[m];
  764. return m_fullNameToInterfaceItems.value(pLinkInf->strFullName);
  765. }
  766. }
  767. // 如果没有找到,则跳出循环,继续查找下一个序号
  768. break;
  769. }
  770. }
  771. }
  772. return nullptr;
  773. }
  774. /// <summary>
  775. /// 完成Pou的初始化动作
  776. /// </summary>
  777. /// <param name="strGroup"></param>
  778. void POU::init(const QString& strName, WindowAppPouScene* pScene)
  779. {
  780. this->m_strPouName = strName;
  781. this->m_parentScene = pScene;
  782. // 初始化本Pou内部变量
  783. this->initPouInternalVariables();
  784. // 绑定本Pou的内部变量
  785. this->bindPouInternalVariables();
  786. }
  787. /// <summary>
  788. /// 是否被Task选中
  789. /// </summary>
  790. /// <returns></returns>
  791. bool POU::isSelByTask()
  792. {
  793. return (this->m_pParentTask != nullptr);
  794. }
  795. /// <summary>
  796. /// 是否在Task中运行
  797. /// </summary>
  798. /// <returns></returns>
  799. bool POU::isRunningInTask()
  800. {
  801. return (this->m_pParentTask != nullptr && m_pParentTask->isRunning());
  802. }
  803. /// <summary>
  804. /// 2021-9-15 增加,查找本Pou中指定类型的接口(用于设计界面中的数据链接用)
  805. /// </summary>
  806. /// <param name="type"></param>
  807. /// <returns></returns>
  808. bool POU::containInterface(VALUE_TYPE type, INF_DIRECTION dir)
  809. {
  810. // 遍历本Pou中所有Tool的所有Interface,查找是否有对应的类型
  811. QMapIterator<QString, _INTERFACE*> it(m_fullNameToInterfaces);
  812. while (it.hasNext())
  813. {
  814. if (it.next().value()->value.type == type
  815. && it.value()->Direction == dir
  816. )
  817. {
  818. return true;
  819. }
  820. }
  821. return false;
  822. }
  823. /// <summary>
  824. /// 2022-6-21 增加,获取两个Block之间的所有LinkItem(用于进行批量移动)
  825. /// </summary>
  826. /// <param name="srcBlock"></param>
  827. /// <param name="dstBlock"></param>
  828. /// <returns></returns>
  829. QList<WindowAppItemLink*> POU::getLinkItemsBetweenBlocks(WindowAppBlockBase* srcBlock, WindowAppBlockBase* dstBlock)
  830. {
  831. QList<WindowAppItemLink*> linkItemList;
  832. // 遍历终点功能块的所有输入接口
  833. for (const auto& infItem : dstBlock->m_itemInterfaces)
  834. {
  835. // 输入接口
  836. if (infItem->m_infInfo->isDirInput())
  837. {
  838. // 首先找到这个输入接口对应的LinkItem的序号
  839. int nLinkIndex = this->getLinkIndexByDstInfItem(infItem);
  840. // 如果没有则说明这个接口没有Link,继续查找下一个
  841. if (nLinkIndex < 0)
  842. {
  843. continue;
  844. }
  845. // 如果找到了Link,那么判断这个Link是否是属于srcBlock的
  846. WindowAppItemInterface* srcInfItem = m_Links[nLinkIndex].pSrcItem;
  847. bool bInBlock = srcBlock->isInBlock(srcInfItem);
  848. // 如果这个Item是属于这个Block,则将此两个接口间的LinkItem保存下来
  849. if (bInBlock)
  850. {
  851. linkItemList.push_back(m_Links[nLinkIndex].pLinkItem);
  852. }
  853. }
  854. }
  855. return linkItemList;
  856. }
  857. /// <summary>
  858. /// 2022-6-21 获取指定接口Item的LinkItem序号
  859. /// </summary>
  860. /// <param name="dstItem"></param>
  861. /// <returns></returns>
  862. int POU::getLinkIndexByDstInfItem(WindowAppItemInterface* dstItem)
  863. {
  864. for (int i = 0; i < m_Links.size(); i++)
  865. {
  866. if (m_Links[i].pDstItem == dstItem)
  867. {
  868. return i;
  869. }
  870. }
  871. return -1;
  872. }
  873. /// <summary>
  874. /// 2022-2-15 增加Pou内部变量(仅用于统计,不显示、不序列化)
  875. /// NOTICE:由于不参与序列化,所以每次反序列化完毕之后都需要手工重新创建一下内部变量
  876. /// </summary>
  877. void POU::initPouInternalVariables()
  878. {
  879. int nIndex = g_pGvlManager->getVariablesCountByGroup(m_strPouName);
  880. // 执行总时长(ms)
  881. VARIABLE* pNewVariable = new VARIABLE(
  882. m_strPouName,
  883. false,
  884. INTERNALVAR_NAME_EXECTIME,
  885. "int",
  886. "0",
  887. INTERNALVAR_CHNAME_EXECTIME,
  888. nIndex,
  889. false // 内部变量标识
  890. );
  891. // 数据结构中添加本变量信息
  892. g_pGvlManager->addNewVariable(
  893. m_strPouName,
  894. pNewVariable
  895. );
  896. // 执行次数
  897. pNewVariable = new VARIABLE(
  898. m_strPouName,
  899. false,
  900. INTERNALVAR_NAME_EXECCOUNT,
  901. "int",
  902. "0",
  903. INTERNALVAR_CHNAME_EXECCOUNT,
  904. nIndex + 1,
  905. false
  906. );
  907. // 数据结构中添加本变量信息
  908. g_pGvlManager->addNewVariable(
  909. m_strPouName,
  910. pNewVariable
  911. );
  912. // 错误次数
  913. pNewVariable = new VARIABLE(
  914. m_strPouName,
  915. false,
  916. INTERNALVAR_NAME_ERRORCOUNT,
  917. "int",
  918. "0",
  919. INTERNALVAR_CHNAME_ERRORCOUNT,
  920. nIndex + 2,
  921. false
  922. );
  923. // 数据结构中添加本变量信息
  924. g_pGvlManager->addNewVariable(
  925. m_strPouName,
  926. pNewVariable
  927. );
  928. }
  929. /// <summary>W
  930. /// 2022-2-16 绑定Pou内部变量和EXEC_PARAMS数据结构
  931. /// 为了防止大幅度改动数据结构,将内部变量与EXEC_PARAMS做绑定
  932. /// </summary>
  933. void POU::bindPouInternalVariables()
  934. {
  935. VARIABLE* pVar = g_pGvlManager->getVariableByName(m_strPouName, INTERNALVAR_NAME_EXECTIME);
  936. pVar->value.setValueByAddress((void**)&this->execParams.nExecTime);
  937. pVar = g_pGvlManager->getVariableByName(m_strPouName, INTERNALVAR_NAME_EXECCOUNT);
  938. pVar->value.setValueByAddress((void**)&this->execParams.nExecCount);
  939. pVar = g_pGvlManager->getVariableByName(m_strPouName, INTERNALVAR_NAME_ERRORCOUNT);
  940. pVar->value.setValueByAddress((void**)&this->execParams.nErrorCount);
  941. }
  942. /// <summary>
  943. /// 2022-3-6,检测功能块的变动是否需要向Task同步
  944. /// </summary>
  945. void POU::syncToolMoveToTaskView()
  946. {
  947. if (this->isSelByTask())
  948. {
  949. WindowAppTaskView* pTaskView = g_pTaskManager->getTaskViewByName(this->m_pParentTask->strName);
  950. pTaskView->onMovePouTool(this);
  951. }
  952. }
  953. /// <summary>
  954. /// 输出所有工具相关的数据结构
  955. /// </summary>
  956. void POU::debugAllTools()
  957. {
  958. qDebug() << "QMap<QString, TOOL*> m_AllTools - size : " << m_instNameToTools.size();
  959. QMapIterator<QString, TOOL*> it1(m_instNameToTools);
  960. while (it1.hasNext())
  961. {
  962. it1.next();
  963. qDebug() << it1.key() << " - with " << it1.value()->Interfaces.size() << " interfaces";
  964. }
  965. qDebug() << "QHash<WindowAppBlockBase*, TOOL*> m_ItemTools - size : " << m_itemToTools.size();
  966. QHashIterator<WindowAppBlockBase*, TOOL*> it2(m_itemToTools);
  967. while (it2.hasNext())
  968. {
  969. it2.next();
  970. qDebug() << it2.key()->m_toolInfo->strInstanceName << " - " << it2.value();
  971. }
  972. qDebug() << "QHash<QString, WindowAppBlockBase*> m_ToolItems - size : " << m_instNameToToolItems.size();
  973. QMapIterator<QString, WindowAppBlockBase*> it3(m_instNameToToolItems);
  974. while (it3.hasNext())
  975. {
  976. it3.next();
  977. qDebug() << it3.key();
  978. }
  979. }
  980. /// <summary>
  981. /// 输出所有接口相关的数据结构
  982. /// </summary>
  983. void POU::debugAllInterface()
  984. {
  985. qDebug() << "QString, _INTERFACE* - size : " << m_fullNameToInterfaces.size();
  986. QMapIterator<QString, _INTERFACE*> it1(m_fullNameToInterfaces);
  987. while (it1.hasNext())
  988. {
  989. it1.next();
  990. qDebug() << it1.key() << " - " << it1.value();
  991. }
  992. qDebug() << "QHash<WindowAppItemInterface*, _INTERFACE*> m_ItemInterfaces - size : " << m_itemToInterfaces.size();
  993. QHashIterator<WindowAppItemInterface*, _INTERFACE*> it2(m_itemToInterfaces);
  994. while (it2.hasNext())
  995. {
  996. it2.next();
  997. qDebug() << it2.key()->m_infInfo->strFullName << " - " << it2.value();
  998. }
  999. qDebug() << "QHash<QString, WindowAppItemInterface*> m_InterfaceItems - size : " << m_fullNameToInterfaceItems.size();
  1000. QMapIterator<QString, WindowAppItemInterface*> it3(m_fullNameToInterfaceItems);
  1001. while (it3.hasNext())
  1002. {
  1003. qDebug() << it3.next().key();
  1004. }
  1005. }
  1006. ///// <summary>
  1007. ///// 输出所有引用计数的相关数据结构
  1008. ///// </summary>
  1009. //void PouManager::debugAllRefCounter()
  1010. //{
  1011. // QHashIterator<const QGraphicsItem*, int> i(m_ItemReferenceCounter);
  1012. // while (i.hasNext())
  1013. // {
  1014. // qDebug() << i.next().key() << ":" << i.value();
  1015. // }
  1016. //
  1017. // //QHash<const QGraphicsItem*, int>::const_iterator i;
  1018. // //for (i = m_ItemReferenceCounter.constBegin(); i != m_ItemReferenceCounter.constEnd(); ++i)
  1019. // //{
  1020. // // qDebug() << i.key() << ":" << i.value();
  1021. // //}
  1022. //}