UiManager.cpp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809
  1. #include "UiManager.h"
  2. #include "WindowRuntime.h"
  3. #include "PouManager.h"
  4. #include "GvlManager.h"
  5. #include "WindowAppUiScene.h"
  6. #include "VPControls.h"
  7. // 字符串之间的间隔,用于Tip 与 Text 之间的组装
  8. #define STRING_INTERVAL ": "
  9. UiManager::UiManager()
  10. {
  11. m_pMainPage = nullptr;
  12. }
  13. /// <summary>
  14. /// 注册新的UIView
  15. /// </summary>
  16. /// <param name="pView"></param>
  17. void UiManager::registerNewUi(WindowAppUiView* pView)
  18. {
  19. QString strName = pView->m_strPageName;
  20. if (m_pAllPages.contains(strName))
  21. {
  22. m_pAllPages[strName] = pView;
  23. return;
  24. }
  25. m_pAllPages.insert(strName, pView);
  26. }
  27. /// <summary>
  28. /// 删除指定页面(此处需要检查是否删除的是主页)
  29. /// </summary>
  30. /// <param name="strName"></param>
  31. bool UiManager::deleteUi(const QString& strName, bool bForce)
  32. {
  33. // 如果删除的页面是主页,则提示是否确认删除,并且需要指定新的主页
  34. if (m_pMainPage!=nullptr
  35. && strName == m_pMainPage->m_strPageName)
  36. {
  37. // 是否不弹提示强制删除
  38. if (!bForce)
  39. {
  40. QMessageBox::StandardButton ret = Utility::VPQuesitonMessageBox("确定要删除主页[" + strName + "吗? 你需要指定新的主页后,才可以执行发布操作.");
  41. if (ret != QMessageBox::Yes)
  42. {
  43. return false;
  44. }
  45. }
  46. m_pMainPage = nullptr;
  47. }
  48. // 数据结构中删除
  49. m_pAllPages.remove(strName);
  50. qDebug() << "[UiManager] Delete UI " << strName << ".";
  51. return true;
  52. }
  53. /// <summary>
  54. /// 注册新的控件
  55. /// </summary>
  56. /// <param name="pNewControl"></param>
  57. /// <param name="pView"></param>
  58. void UiManager::regiterNewControl(VControlObject* pNewControl, WindowAppUiView* pView)
  59. {
  60. m_AllControls.insert(pNewControl->m_pWidget, pView);
  61. qDebug() << "[UiManager] UiManager::regiterNewControl - " << pNewControl << " in " << pView->m_strPageName;
  62. }
  63. /// <summary>
  64. /// 删除一个控件
  65. /// </summary>
  66. /// <param name="pDelControl"></param>
  67. void UiManager::deleteControl(QWidget* pDelControl)
  68. {
  69. m_AllControls.remove(pDelControl);
  70. // 删除本UI控件和其他的关联关系
  71. m_UiToDllControls.remove(pDelControl);
  72. m_UiToRtControls.remove(pDelControl);
  73. m_UiControlToValues.remove(pDelControl);
  74. QHash<QWidget*, QWidget*>::iterator it = m_DllToUiControls.begin();
  75. for (; it != m_DllToUiControls.end();)
  76. {
  77. if (it.value() == pDelControl)
  78. {
  79. m_DllToUiControls.erase(it);
  80. break;
  81. }
  82. else
  83. {
  84. it++;
  85. }
  86. }
  87. QHash<QWidget*, QWidget*>::iterator it2 = m_RtToUiControls.begin();
  88. for (; it2 != m_RtToUiControls.end();)
  89. {
  90. if (it2.value() == pDelControl)
  91. {
  92. m_RtToUiControls.erase(it2);
  93. break;
  94. }
  95. else
  96. {
  97. it2++;
  98. }
  99. }
  100. QHashIterator<VARIABLE*, QWidget*> it3(m_ValueToUiControls);
  101. while (it3.hasNext())
  102. {
  103. QList<QWidget*> pWidgets = m_ValueToUiControls.values(it3.next().key());
  104. for (QWidget* pWidget : pWidgets)
  105. {
  106. if (pWidget == pDelControl)
  107. {
  108. // 2021-11-9 取消DataLink标识
  109. it3.key()->bDataLink = false;
  110. // 减小引用计数
  111. if (it3.key()->nRefCount > 0)
  112. {
  113. it3.key()->nRefCount--;
  114. }
  115. m_ValueToUiControls.remove(it3.key(), pDelControl);
  116. break;
  117. }
  118. }
  119. }
  120. }
  121. /// <summary>
  122. /// 获取所有的Ui名称
  123. /// </summary>
  124. /// <returns></returns>
  125. QStringList UiManager::getAllUiNames()
  126. {
  127. // return this->m_UiNames;
  128. QStringList listNames;
  129. QMapIterator<QString, WindowAppUiView*> it(m_pAllPages);
  130. while (it.hasNext())
  131. {
  132. listNames.push_back(it.next().key());
  133. }
  134. return listNames;
  135. }
  136. /// <summary>
  137. /// 获取指定名字的页面
  138. /// </summary>
  139. /// <param name="strName"></param>
  140. /// <returns></returns>
  141. WindowAppUiView* UiManager::getPageByName(const QString& strName)
  142. {
  143. if (m_pAllPages.contains(strName))
  144. {
  145. return m_pAllPages[strName];
  146. }
  147. else
  148. {
  149. return nullptr;
  150. }
  151. }
  152. /// <summary>
  153. /// 检查各个页面中携带的属性是否正确有效
  154. /// </summary>
  155. /// <returns></returns>
  156. bool UiManager::checkAll()
  157. {
  158. QMapIterator<QString, WindowAppUiView*> it(m_pAllPages);
  159. while (it.hasNext())
  160. {
  161. // 依次检测每一个UI页面的属性设置
  162. bool bRet = it.next().value()->uiScene()->checkAllProperties();
  163. if (!bRet)
  164. {
  165. return false;
  166. }
  167. }
  168. return true;
  169. }
  170. /// <summary>
  171. /// 发布所有页面到Runtime执行(所有的关于主页的检查都放到这里来执行)
  172. /// </summary>
  173. bool UiManager::publishAll()
  174. {
  175. // 首先检查是否设定了主页
  176. if (m_pMainPage == nullptr)
  177. {
  178. CRITICAL_MESSAGE("Error: 请先设置主页面");
  179. return false;
  180. }
  181. // 检查各个页面中携带的属性是否正确有效(仅检查必填项)
  182. bool bRet = checkAll();
  183. if (!bRet)
  184. {
  185. return false;
  186. }
  187. // 然后将主页和所有页面都传输到Runtime发布
  188. return g_pRuntime->publishAllPages(m_pMainPage, m_pAllPages);
  189. }
  190. /// <summary>
  191. /// 设定主页
  192. /// </summary>
  193. /// <param name="strName"></param>
  194. bool UiManager::setMainPage(const QString& strName)
  195. {
  196. if (m_pAllPages.contains(strName))
  197. {
  198. m_pMainPage = m_pAllPages[strName];
  199. qDebug() << "[UiManager] Set " << strName << " as MainPage.";
  200. return true;
  201. }
  202. else
  203. {
  204. qWarning() << "[UiManager] Set " << strName << " as MainPage failed.";
  205. return false;
  206. }
  207. }
  208. /// <summary>
  209. /// 获取主页
  210. /// </summary>
  211. /// <returns></returns>
  212. WindowAppUiView* UiManager::getMainPage()
  213. {
  214. return this->m_pMainPage;
  215. }
  216. /// <summary>
  217. /// 序列化所有的WindowAppUiView*
  218. /// </summary>
  219. /// <param name="out"></param>
  220. /// <returns></returns>
  221. bool UiManager::serialized(QDataStream& out)
  222. {
  223. // 首先写入UI的总数量
  224. out << m_pAllPages.size();
  225. // 首先写入主页
  226. out << m_pMainPage;
  227. // 遍历所有的UIView,执行序列化
  228. QMapIterator<QString, WindowAppUiView*> it(m_pAllPages);
  229. while (it.hasNext())
  230. {
  231. it.next();
  232. // 跳过主页
  233. if (it.value() != m_pMainPage)
  234. {
  235. out << it.value();
  236. }
  237. }
  238. return true;
  239. }
  240. //=====================================================================
  241. //
  242. // 同步相关代码
  243. //
  244. //=====================================================================
  245. /// <summary>
  246. /// 接收来自其他控件和变量的同步Event
  247. /// </summary>
  248. /// <param name="event"></param>
  249. /// <returns></returns>
  250. void UiManager::customEvent(QEvent* event)
  251. {
  252. // qDebug() << "UiManager::event " << event->type();
  253. // 如果是控件同步消息
  254. if (event->type() == CONTROL_EVENT_TYPEID)
  255. {
  256. qDebug() << "UiManager::event - CONTROL_EVENT";
  257. SyncControlEvent* pValueEvent = dynamic_cast<SyncControlEvent*> (event);
  258. // 取出参数执行同步
  259. syncFromDll(
  260. pValueEvent->m_pSrcControl,
  261. pValueEvent->m_SyncMsg
  262. );
  263. }
  264. // 如果是数值同步消息
  265. else if (event->type() == VALUE_EVENT_TYPEID)
  266. {
  267. vDebug() << "VALUE_EVENT";
  268. SyncValueEvent* pValueEvent = dynamic_cast<SyncValueEvent* > (event);
  269. // 取出参数
  270. QList<VARIABLE*> syncValues = pValueEvent->getSyncValues();
  271. for (VARIABLE* syncVal : syncValues)
  272. {
  273. this->syncFromValue(syncVal);
  274. }
  275. }
  276. // 如果是硬件数值同步消息
  277. else if (event->type() == HDVALUE_EVENT_TYPEID)
  278. {
  279. qDebug() << "UiManager::event - HDVALUE_EVENT";
  280. SyncHdValueEvent* pValueEvent = dynamic_cast<SyncHdValueEvent*> (event);
  281. // 如果当前组不是硬件组态,不继续执行后续代码 ,为了解决硬件工具放在 POU 中时候,主动触发了ui刷新
  282. if (pValueEvent != nullptr && pValueEvent->groupName() != CATEGORY_TOOL_HARDWARE)
  283. {
  284. return;
  285. }
  286. // 首先需要去Pou中取出此接口
  287. POU* pHdPou = g_pPouManager->getHdwPou();
  288. _INTERFACE* pInf = nullptr;
  289. // 第一种方式
  290. if (!pValueEvent->m_strInstanceName.isEmpty() && !pValueEvent->m_strInfName.isEmpty())
  291. {
  292. QString infFullName = pValueEvent->m_strInstanceName + "." + pValueEvent->m_strInfName;
  293. pInf = pHdPou->GetInterface(infFullName);
  294. }
  295. // 第二种方式
  296. else if(pValueEvent->m_pSrcValue!=nullptr)
  297. {
  298. pInf = pHdPou->GetInterfaceByValuePtr(pValueEvent->m_pSrcValue);
  299. }
  300. else
  301. {
  302. qDebug() << "[Error] UiManager::customEvent - but SyncHdValueEvent invalid.";
  303. }
  304. // 如果接口成功取到,则执行同步
  305. if (pInf != nullptr)
  306. {
  307. // 执行同步
  308. this->syncFromValue(pInf);
  309. }
  310. else
  311. {
  312. qWarning() << "UiManager::customEvent - Can't find update interface, may be not a hardward interface.";
  313. }
  314. }
  315. //return QObject::event(event);
  316. }
  317. /// <summary>
  318. /// 绑定dll中的控件与UI控件
  319. /// </summary>
  320. /// <param name="pDllControl"></param>
  321. /// <param name="pUiControl"></param>
  322. void UiManager::bindDllControlWithUiControl(QWidget* pDllControl, VControlObject* pUiControl)
  323. {
  324. m_DllToUiControls.insert(pDllControl, pUiControl->m_pWidget);
  325. m_UiToDllControls.insert(pUiControl->m_pWidget, pDllControl);
  326. // 刚绑定时,从dll向UI做一次同步
  327. this->syncFromDllFirst(pDllControl, pUiControl);
  328. }
  329. /// <summary>
  330. /// 2022-9-13,解除dll中的控件与UI控件的绑定
  331. /// </summary>
  332. /// <param name="pDllControl"></param>
  333. /// <param name="pUiControl"></param>
  334. void UiManager::unbindDllControlWithUiControl(QWidget* pDllControl, VControlObject* pUiControl)
  335. {
  336. m_DllToUiControls.remove(pDllControl);
  337. m_UiToDllControls.remove(pUiControl->m_pWidget);
  338. }
  339. /// <summary>
  340. /// 绑定UI控件与Runtime控件用于同步
  341. /// </summary>
  342. /// <param name="pUiControl"></param>
  343. /// <param name="pRtControl"></param>
  344. void UiManager::bindUiControlWithRtControl(QWidget* pUiControl, QWidget* pRtControl)
  345. {
  346. m_UiToRtControls.insert(pUiControl, pRtControl);
  347. m_RtToUiControls.insert(pRtControl, pUiControl);
  348. }
  349. /// <summary>
  350. /// 2022-9-13,解除UI控件与Runtime控件的绑定
  351. /// </summary>
  352. /// <param name="pUiControl"></param>
  353. /// <param name="pRtControl"></param>
  354. void UiManager::unbindUiControlWithRtControl(QWidget* pUiControl, QWidget* pRtControl)
  355. {
  356. m_UiToRtControls.remove(pUiControl);
  357. m_RtToUiControls.remove(pRtControl);
  358. }
  359. /// <summary>
  360. /// 绑定数值变量与UI控件用于同步
  361. /// </summary>
  362. /// <param name="pValue"></param>
  363. /// <param name="pUiControl"></param>
  364. void UiManager::bindValueWithUiControl(VARIABLE* val, QWidget* pUiControl)
  365. {
  366. //LINK_VALUE lv;
  367. //lv.direction = dir;
  368. //lv.value = value;
  369. m_ValueToUiControls.insertMulti(val, pUiControl);
  370. m_UiControlToValues.insert(pUiControl, val);
  371. //// For Debug
  372. //foreach(const auto & key, m_ValueToUiControls.keys())
  373. //{
  374. // qDebug() << "bindValueWithUiControl: " << key->strFullName << " - " << m_ValueToUiControls.value(key);
  375. //}
  376. // 刚绑定时,从Value向UI做一次同步
  377. this->syncFromValue(val);
  378. }
  379. /// <summary>
  380. /// 2022-9-13,解绑数值变量与UI控件(在控件变更了主索引绑定变量时,需要做解绑动作)
  381. /// </summary>
  382. /// <param name="val"></param>
  383. /// <param name="pUiControl"></param>
  384. void UiManager::unbindValueWithUiControl(VARIABLE* val, QWidget* pUiControl)
  385. {
  386. m_UiControlToValues.remove(pUiControl);
  387. QMutableHashIterator<VARIABLE*, QWidget*> iter(m_ValueToUiControls);
  388. while (iter.hasNext())
  389. {
  390. if (iter.next().key() == val)
  391. {
  392. QList<QWidget*> pWidgets = m_ValueToUiControls.values(iter.key());
  393. for (QWidget* pWidget : pWidgets)
  394. {
  395. if (pWidget == pUiControl)
  396. {
  397. m_ValueToUiControls.remove(iter.key(), pUiControl);
  398. return;
  399. }
  400. }
  401. }
  402. }
  403. }
  404. /// <summary>
  405. /// 绑定DataLink中的信息用于后续同步(仅 UI->Dll)
  406. /// </summary>
  407. bool UiManager::bindDataLinkSyncInformation(const DataLink& dataLink, VControlObject* pVControl)
  408. {
  409. // 2022-2-9 ,解决绑定Button相关数据连接中出现的bug(也不清楚是怎么出现的,先暂时这么处理一下看起来好像没问题)
  410. if (pVControl->m_Type == VALUE_TYPE::Control_Button)
  411. {
  412. pVControl->m_Property.m_DataLink = dataLink;
  413. return true;
  414. }
  415. POU* pPou = nullptr;
  416. TOOL* pTool = nullptr;
  417. _INTERFACE* pInf = nullptr;
  418. // 解析出Tool信息
  419. this->parsePouToolFromDataLink(dataLink, pPou, pTool, pInf);
  420. if (pInf == nullptr)
  421. {
  422. vDebug() << "[Error] Abandon bind Datalink, Reason: Parse datalink failed.";
  423. return false;
  424. }
  425. // 如果是控件类型
  426. if (pInf->Type == INF_TYPE::INF_TYPE_CONTROL)
  427. {
  428. return this->bindSyncByControl(pTool, pInf, pVControl);
  429. }
  430. // 数值类型或者普通数据类型的接口类型
  431. else if (pInf->Type == INF_TYPE::INF_TYPE_VALUE
  432. || pInf->Type == INF_TYPE::INF_TYPE_STANDARD
  433. )
  434. {
  435. // 如果是普通类型控件
  436. if (!pVControl->isComplexControl())
  437. {
  438. this->bindSyncByValue(pTool, pInf, pVControl);
  439. }
  440. // 2021-12-7 复杂类型控件
  441. else
  442. {
  443. // 2022-2-10 绑定dll中的信息用于后续同步(复杂类型,暂未绑定,仅引用计数 + 1)
  444. // 由于不需要执行三方同步,此处不需要绑定
  445. this->bindSyncByComplex(pTool, pInf);
  446. }
  447. }
  448. // 未处理类型
  449. else
  450. {
  451. qWarning() << "DialogDataLink::bindSyncFromDll - Unsupported interface category : " << (int)pInf->Type;
  452. }
  453. return true;
  454. }
  455. /// <summary>
  456. /// 2022-9-13,解绑DataLine信息(在控件变更了主索引绑定变量时,需要做解绑动作)
  457. /// </summary>
  458. /// <param name="val"></param>
  459. /// <param name="pUiControl"></param>
  460. bool UiManager::unbindDataLinkSyncInformation(const DataLink& dataLink, VControlObject* pVControl)
  461. {
  462. if (pVControl->m_Type == VALUE_TYPE::Control_Button)
  463. {
  464. pVControl->m_Property.m_DataLink = dataLink;
  465. return true;
  466. }
  467. POU* pPou = nullptr;
  468. TOOL* pTool = nullptr;
  469. _INTERFACE* pDllInf = nullptr;
  470. // 解析出Tool信息
  471. this->parsePouToolFromDataLink(dataLink, pPou, pTool, pDllInf);
  472. if (pDllInf == nullptr)
  473. {
  474. return false;
  475. }
  476. // 如果是控件类型
  477. if (pDllInf->Type == INF_TYPE::INF_TYPE_CONTROL)
  478. {
  479. return this->unbindSyncByControl(pTool, pDllInf, pVControl);
  480. }
  481. // 数值类型或者普通数据类型的接口类型
  482. else if (pDllInf->Type == INF_TYPE::INF_TYPE_VALUE
  483. || pDllInf->Type == INF_TYPE::INF_TYPE_STANDARD
  484. )
  485. {
  486. // 如果是普通类型控件
  487. if (!pVControl->isComplexControl())
  488. {
  489. this->unbindSyncByValue(pTool, pDllInf, pVControl);
  490. }
  491. // 2021-12-7 复杂类型控件
  492. else
  493. {
  494. this->unbindSyncByComplex(pTool, pDllInf);
  495. }
  496. }
  497. // 未处理类型
  498. else
  499. {
  500. vDebug() << "Unsupported interface category : " << (int)pDllInf->Type;
  501. }
  502. return true;
  503. }
  504. /// <summary>
  505. /// 绑定dll中的信息用于后续同步(控件类型)
  506. /// </summary>
  507. /// <returns></returns>
  508. bool UiManager::bindSyncByControl(TOOL* pTool, _INTERFACE* pDllInf, VControlObject* pVControl)
  509. {
  510. // 因为dll->UI只能是一对一,所以此处需要判断一下引用计数
  511. if (pDllInf->nRefCount > 0)
  512. {
  513. vDebug() << ("Error: Interface[" + pDllInf->strNameWithType + "] ref count >0 : " + pDllInf->nRefCount + ".");
  514. return false;
  515. }
  516. // 引用计数 + 1
  517. pDllInf->nRefCount++;
  518. // TODO:回调函数方式已经废弃(只是暂时留着备用)
  519. // dll->UI同步:给dll设置UI同步回调函数
  520. CONTROL_CALLBACK callBack = std::bind(
  521. &UiManager::syncFromDll,
  522. g_pUiManager,
  523. std::placeholders::_1,
  524. std::placeholders::_2
  525. );
  526. pTool->pDllPtr->setControlCallback(callBack);
  527. // 设置同步event的target(这个为目前统一使用的方式,回调函数的方式已经废弃了)
  528. pTool->pDllPtr->setSyncTarget(g_pUiManager);
  529. // UI->Dll同步:信息存储至UiManager统一处理
  530. QWidget* pDllControl = (QWidget*)pTool->pDllPtr->Interface(pDllInf->nIndex).value.Ptr;
  531. g_pUiManager->bindDllControlWithUiControl(pDllControl, pVControl);
  532. return true;
  533. }
  534. /// <summary>
  535. /// 2022-9-13 解绑dll中的控件信息
  536. /// </summary>
  537. /// <param name="pTool"></param>
  538. /// <param name="pDllInf"></param>
  539. /// <param name="pVControl"></param>
  540. /// <returns></returns>
  541. bool UiManager::unbindSyncByControl(TOOL* pTool, _INTERFACE* pDllInf, VControlObject* pVControl)
  542. {
  543. if (pDllInf->nRefCount > 0)
  544. {
  545. vDebug() << ("Error: Interface[" + pDllInf->strNameWithType + "] ref count >0 : " + pDllInf->nRefCount + ".");
  546. return false;
  547. }
  548. // 引用计数 - 1
  549. pDllInf->nRefCount--;
  550. // 解绑UI->Dll的同步信息
  551. QWidget* pDllControl = (QWidget*)pTool->pDllPtr->Interface(pDllInf->nIndex).value.Ptr;
  552. g_pUiManager->unbindDllControlWithUiControl(pDllControl, pVControl);
  553. return true;
  554. }
  555. /// <summary>
  556. /// 绑定接口信息用于后续同步(有可能是Dll接口,有可能是数值类型,数值可对应多个UI控件)
  557. /// </summary>
  558. /// <param name="pTool"></param>
  559. /// <param name="pDllInf"></param>
  560. /// <returns></returns>
  561. bool UiManager::bindSyncByValue(TOOL* pTool, _INTERFACE* pInf, VControlObject* pVControl)
  562. {
  563. // 输出接口 - Text控件,一对多,输入接口 - Text控件,一对一
  564. // 如果是输入接口,要检查引用计数
  565. if (pInf->Direction == INF_DIRECTION::INF_DIR_IN
  566. && pInf->nRefCount > 0)
  567. {
  568. vDebug() << ("Error: Interface[" + pInf->strNameWithType + "] ref count >0 : " + pInf->nRefCount + ".");
  569. return false;
  570. }
  571. // 引用计数 + 1
  572. pInf->nRefCount++;
  573. // Value->UI同步,给Tool设置同步事件接收对象
  574. // 如果是Tool中的Value接口,需要绑定变更的回调函数(针对dll中的变量接口)
  575. if (pTool->pDllPtr != nullptr)
  576. {
  577. pTool->pDllPtr->setSyncTarget(g_pUiManager);
  578. // UI->Value单向同步:信息存储至UiManager统一处理
  579. // VALUE& value = pTool->pDllPtr->Interface(pDllInf->nIndex).value;
  580. // g_pUiManager->bindValueWithUiControl(pDllInf, m_pControlObject->m_pWidget);
  581. }
  582. else
  583. {
  584. // TODO: 此处缺一个设置event target的位置(针对局部变量和全局变量)
  585. // VALUE& value = pDllInf->value;
  586. }
  587. pInf->bDataLink = true;
  588. g_pUiManager->bindValueWithUiControl(pInf, pVControl->m_pWidget);
  589. vDebug() << "Bind [" << pInf->strFullName << "] " << " - " << pVControl->m_pWidget;
  590. return true;
  591. }
  592. /// <summary>
  593. /// 解绑数值接口的绑定信息(有可能是Dll接口,有可能是数值类型,数值可对应多个UI控件)
  594. /// </summary>
  595. /// <param name="pTool"></param>
  596. /// <param name="pDllInf"></param>
  597. /// <param name="pVControl"></param>
  598. /// <returns></returns>
  599. bool UiManager::unbindSyncByValue(TOOL* pTool, _INTERFACE* pInf, VControlObject* pVControl)
  600. {
  601. Q_UNUSED(pTool);
  602. // 引用计数 - 1
  603. pInf->nRefCount--;
  604. pInf->bDataLink = false;
  605. g_pUiManager->unbindValueWithUiControl(pInf, pVControl->m_pWidget);
  606. vDebug() << "Unbind [" << pInf->strFullName << "] - " << pVControl->m_pWidget;
  607. return true;
  608. }
  609. /// <summary>
  610. /// 绑定dll中的信息用于后续同步(复杂类型,暂未绑定,仅引用计数 + 1)
  611. /// </summary>
  612. /// <param name="pTool"></param>
  613. /// <param name="pDllInf"></param>
  614. /// <returns></returns>
  615. bool UiManager::bindSyncByComplex(TOOL* pTool, _INTERFACE* pDllInf)
  616. {
  617. Q_UNUSED(pTool);
  618. if (pDllInf->Direction == INF_DIRECTION::INF_DIR_IN
  619. && pDllInf->nRefCount > 0)
  620. {
  621. vDebug() << ("Error: Interface[" + pDllInf->strNameWithType + "] ref count >0 : " + pDllInf->nRefCount + ".");
  622. return false;
  623. }
  624. // 引用计数 + 1
  625. pDllInf->nRefCount++;
  626. return true;
  627. }
  628. /// <summary>
  629. /// 2022-9-13 解绑dll中的信息(复杂类型,暂未绑定,仅引用计数 - 1)
  630. /// </summary>
  631. /// <param name="pTool"></param>
  632. /// <param name="pDllInf"></param>
  633. /// <returns></returns>
  634. bool UiManager::unbindSyncByComplex(TOOL* pTool, _INTERFACE* pDllInf)
  635. {
  636. Q_UNUSED(pTool);
  637. if (pDllInf->Direction == INF_DIRECTION::INF_DIR_IN
  638. && pDllInf->nRefCount > 0)
  639. {
  640. vDebug() << ("Error: Interface[" + pDllInf->strNameWithType + "] ref count >0 : " + pDllInf->nRefCount + ".");
  641. return false;
  642. }
  643. // 引用计数 - 1
  644. pDllInf->nRefCount--;
  645. return true;
  646. }
  647. /// <summary>
  648. /// 还原反序列化中控件的DataLink关系(简单控件)
  649. /// </summary>
  650. /// <param name="prop"></param>
  651. /// <returns></returns>
  652. bool UiManager::restoreDataLinks(const CONTROL_PROPERTY& prop, VControlObject* pUiControl)
  653. {
  654. if (prop.m_DataLink.isValid())
  655. {
  656. this->bindDataLinkSyncInformation(prop.m_DataLink, pUiControl);
  657. }
  658. return true;
  659. }
  660. /// <summary>
  661. /// 还原反序列化中控件的DataLink关系(复杂控件)
  662. /// </summary>
  663. /// <param name="propex"></param>
  664. /// <returns></returns>
  665. bool UiManager::restoreDataLinks(const CONTROL_PROPERTY_EX& propex, VControlObject* pUiControl)
  666. {
  667. bool bRet = true;
  668. // 索引链接
  669. this->bindDataLinkSyncInformation(propex.m_refreshLink, pUiControl);
  670. // 主数据链接
  671. for (const DataLink& dataLink : propex.m_mainDataLinks)
  672. {
  673. if (dataLink.isValid())
  674. {
  675. this->bindDataLinkSyncInformation(dataLink, pUiControl);
  676. }
  677. else
  678. {
  679. qDebug() << ("[Error] UiManager::restoreDataLinks - Property datalink[" + dataLink.title + "] invalid.");
  680. bRet = false;
  681. }
  682. }
  683. // 子分组中的数据链接
  684. for (int i = 0; i < propex.m_groups.size(); i++)
  685. {
  686. const PROPERTY_EX_SUBGROUPS& subGroups = propex.m_groups[i].subGroups;
  687. for (int j = 0; j < subGroups.size(); j++)
  688. {
  689. for (const DataLink& dataLink : subGroups[j].dataLinks)
  690. {
  691. if (dataLink.isValid())
  692. {
  693. this->bindDataLinkSyncInformation(dataLink, pUiControl);
  694. }
  695. else
  696. {
  697. qDebug() << ("[Error] UiManager::restoreDataLinks - Property datalink[" + dataLink.title + "] invalid.");
  698. bRet = false;
  699. }
  700. }
  701. }
  702. }
  703. return bRet;
  704. }
  705. /// <summary>
  706. /// 用于Dll中的控件事件触发回调(dll中的控件向UI界面同步)
  707. /// </summary>
  708. /// <param name=""></param>
  709. /// <param name="msg"></param>
  710. void UiManager::syncFromDll(QWidget* pDllControl, UI_SYNC_MSG msg)
  711. {
  712. if (pDllControl == nullptr)
  713. {
  714. qWarning() << "[Error] UiManager::syncFromDll - pDllControl is nullptr.";
  715. return;
  716. }
  717. // 根据不同的消息执行不同的处理
  718. if (m_DllToUiControls.contains(pDllControl))
  719. {
  720. QWidget* pUiWidget = m_DllToUiControls.value(pDllControl);
  721. bool bRet = false;
  722. switch (msg)
  723. {
  724. case UI_SYNC_MSG::EDIT_TEXT_CHANGED:
  725. {
  726. QLineEdit* pDllEdit = qobject_cast<QLineEdit*>(pDllControl);
  727. VLineEdit* pVEdit = qobject_cast<VLineEdit*>(pUiWidget);
  728. bRet = syncEditControl(pDllEdit, pVEdit, SYNC_MODE::FROM_DLL);
  729. if (bRet)
  730. {
  731. qDebug() << "UiManager::syncFromDll - VLineEdit:" << pVEdit->text();
  732. }
  733. }
  734. break;
  735. case UI_SYNC_MSG::COMBO_SEL_CHANGED:
  736. {
  737. QComboBox* pDllCombo = qobject_cast<QComboBox*>(pDllControl);
  738. VComboBox* pVCombo = qobject_cast<VComboBox*>(pUiWidget);
  739. bRet = syncComboControl(pDllCombo, pVCombo, SYNC_MODE::FROM_DLL);
  740. if (bRet)
  741. {
  742. qDebug() << "UiManager::syncFromDll - VComboBox:" << pVCombo->currentIndex();
  743. }
  744. }
  745. break;
  746. case UI_SYNC_MSG::LIST_SEL_CHANGED:
  747. {
  748. QListWidget* pDllList = qobject_cast<QListWidget*>(pDllControl);
  749. VListBox* pVList = qobject_cast<VListBox*>(pUiWidget);
  750. bRet = syncListControl(pDllList, pVList, SYNC_MODE::FROM_DLL);
  751. qDebug() << "UiManager::syncFromDll - VListBox:" << pDllList->currentRow();
  752. }
  753. break;
  754. case UI_SYNC_MSG::RADIOBOX_CHANGED:
  755. {
  756. QRadioButton* pDllRadio= qobject_cast<QRadioButton*>(pDllControl);
  757. VRadioBox* pVRadio = qobject_cast<VRadioBox*>(pUiWidget);
  758. //// 首次同步需要把名字也复制一下
  759. //if (bFirst)
  760. //{
  761. // pVRadio->setText(pDllRadio->text());
  762. //}
  763. pVRadio->setChecked(pDllRadio->isChecked());
  764. qDebug() << "UiManager::syncFromDll - VRadioBox:" << pDllRadio->isChecked();
  765. }
  766. break;
  767. case UI_SYNC_MSG::CHECKBOX_CHANGED:
  768. {
  769. QCheckBox* pDllCheck = qobject_cast<QCheckBox*>(pDllControl);
  770. VCheckBox* pVCheck = qobject_cast<VCheckBox*>(pUiWidget);
  771. //// 首次同步需要把名字也复制一下
  772. //if (bFirst)
  773. //{
  774. // pVCheck->setText(pDllCheck->text());
  775. //}
  776. pVCheck->setCheckState(pDllCheck->checkState());
  777. qDebug() << "UiManager::syncFromDll - VCheckBox:" << pDllCheck->checkState();
  778. }
  779. break;
  780. default:
  781. {
  782. qWarning() << "UiManager::syncFromDll - Unknown sync message : " << (int)msg;
  783. }
  784. break;
  785. }
  786. // 同步完后,通知UI界面刷新此控件(同时更新属性表)
  787. if (m_AllControls.contains(pUiWidget))
  788. {
  789. m_AllControls.value(pUiWidget)->uiScene()->refreshControl(pUiWidget);
  790. }
  791. }
  792. }
  793. /// <summary>
  794. /// 用于UI界面向Dll中的控件同步
  795. /// </summary>
  796. /// <param name="pWidget"></param>
  797. /// <param name="msg"></param>
  798. void UiManager::syncToDll(QWidget* pUiControl, UI_SYNC_MSG msg)
  799. {
  800. // 根据不同的消息执行不同的处理
  801. if (m_UiToDllControls.contains(pUiControl))
  802. {
  803. bool bRet = false;
  804. switch (msg)
  805. {
  806. case UI_SYNC_MSG::EDIT_TEXT_CHANGED:
  807. {
  808. VLineEdit* pVEdit = qobject_cast<VLineEdit*>(pUiControl);
  809. QLineEdit* pDllEdit = qobject_cast<QLineEdit*>(m_UiToDllControls.value(pUiControl));
  810. // pDllEdit->setText(pVEdit->text());
  811. bRet = syncEditControl(pVEdit, pDllEdit, SYNC_MODE::TO_DLL);
  812. if (bRet)
  813. {
  814. qDebug() << "UiManager::syncToDll - QLineEdit:" << pVEdit->text();
  815. }
  816. }
  817. break;
  818. case UI_SYNC_MSG::COMBO_SEL_CHANGED:
  819. {
  820. VComboBox* pUi = qobject_cast<VComboBox*>(pUiControl);
  821. QComboBox* pDll = qobject_cast<QComboBox*>(m_UiToDllControls.value(pUiControl));
  822. bRet = syncComboControl(pUi, pDll, SYNC_MODE::TO_DLL);
  823. if (bRet)
  824. {
  825. qDebug() << "UiManager::syncToDll - QComboBox:" << pDll->currentIndex();
  826. }
  827. }
  828. break;
  829. case UI_SYNC_MSG::LIST_SEL_CHANGED:
  830. {
  831. VListBox* pUi = qobject_cast<VListBox*>(pUiControl);
  832. QListWidget* pDll = qobject_cast<QListWidget*>(m_UiToDllControls.value(pUiControl));
  833. bRet = syncListControl(pUi, pDll, SYNC_MODE::TO_DLL);
  834. if (bRet)
  835. {
  836. qDebug() << "UiManager::syncToDll - QListWidget:" << pDll->currentRow();
  837. }
  838. }
  839. break;
  840. case UI_SYNC_MSG::RADIOBOX_CHANGED:
  841. break;
  842. case UI_SYNC_MSG::CHECKBOX_CHANGED:
  843. break;
  844. default:
  845. {
  846. qWarning() << "UiManager::syncToDll - Unknown sync message : " << (int)msg;
  847. }
  848. break;
  849. }
  850. }
  851. else
  852. {
  853. //qWarning() << "UiManager::syncToDll - Error : Can't find this control - " << pControl->getText();
  854. }
  855. }
  856. /// <summary>
  857. /// 刚绑定时,从dll向UI做一次同步
  858. /// </summary>
  859. /// <param name="pDllControl"></param>
  860. void UiManager::syncFromDllFirst(QWidget* pDllControl, VControlObject* pUiControl)
  861. {
  862. // 根据同步控件的类型执行不同的同步动作
  863. VALUE_TYPE controlType = pUiControl->m_Type;
  864. // 逐步增加如下需要同步的类型
  865. switch (controlType)
  866. {
  867. case VALUE_TYPE::Control_LineEdit:
  868. {
  869. QLineEdit* pDllEdit = qobject_cast<QLineEdit*>(pDllControl);
  870. VLineEdit* pVEdit = qobject_cast<VLineEdit*>(pUiControl->m_pWidget);
  871. bool bRet = syncEditControl(pDllEdit, pVEdit, SYNC_MODE::FROM_DLL, true);
  872. if (bRet)
  873. {
  874. qDebug() << "UiManager::syncFromDllFirst - VLineEdit:" << pVEdit->text();
  875. }
  876. }
  877. //this->syncFromDll(pDllControl, UI_SYNC_MSG::EDIT_TEXT_CHANGED, true);
  878. break;
  879. case VALUE_TYPE::Control_ComboBox:
  880. {
  881. QComboBox* pDll= qobject_cast<QComboBox*>(pDllControl);
  882. VComboBox* pUi = qobject_cast<VComboBox*>(pUiControl->m_pWidget);
  883. bool bRet = syncComboControl(pDll, pUi, SYNC_MODE::FROM_DLL, true);
  884. if (bRet)
  885. {
  886. qDebug() << "UiManager::syncFromDllFirst - VComboBox:" << pUi->currentIndex();
  887. }
  888. }
  889. //this->syncFromDll(pDllControl, UI_SYNC_MSG::COMBO_SEL_CHANGED, true);
  890. break;
  891. case VALUE_TYPE::Control_RadioBox:
  892. {
  893. }
  894. //this->syncFromDll(pDllControl, UI_SYNC_MSG::RADIOBOX_CHANGED, true);
  895. break;
  896. case VALUE_TYPE::Control_CheckBox:
  897. {
  898. }
  899. //this->syncFromDll(pDllControl, UI_SYNC_MSG::CHECKBOX_CHANGED, true);
  900. break;
  901. case VALUE_TYPE::Control_Listbox:
  902. {
  903. QListWidget* pDll = qobject_cast<QListWidget*>(pDllControl);
  904. VListBox* pUi = qobject_cast<VListBox*>(pUiControl->m_pWidget);
  905. bool bRet = syncListControl(pDll, pUi, SYNC_MODE::FROM_DLL, true);
  906. if (bRet)
  907. {
  908. qDebug() << "UiManager::syncFromDllFirst - VListBox:" << pUi->currentIndex();
  909. }
  910. }
  911. //this->syncFromDll(pDllControl, UI_SYNC_MSG::LIST_SEL_CHANGED, true);
  912. break;
  913. default:
  914. break;
  915. }
  916. }
  917. /// <summary>
  918. /// 用于Runtime界面向UI中的控件同步
  919. /// </summary>
  920. /// <param name="pControl"></param>
  921. /// <param name="msg"></param>
  922. void UiManager::syncFromRuntime(QWidget* pRtControl, UI_SYNC_MSG msg)
  923. {
  924. if (m_RtToUiControls.contains(pRtControl))
  925. {
  926. QWidget* pUiWidget = m_RtToUiControls.value(pRtControl);
  927. bool bRet = false;
  928. switch (msg)
  929. {
  930. case UI_SYNC_MSG::EDIT_TEXT_CHANGED:
  931. {
  932. QLineEdit* pRtEdit = qobject_cast<QLineEdit*>(pRtControl);
  933. QLineEdit* pUiEdit = qobject_cast<QLineEdit*>(pUiWidget);
  934. bRet = syncEditControl(pRtEdit, pUiEdit, SYNC_MODE::FROM_RUNTIME, false);
  935. if (bRet)
  936. {
  937. qDebug() << "UiManager::syncFromRuntime - QLineEdit:" << pRtEdit->text();
  938. }
  939. }
  940. break;
  941. case UI_SYNC_MSG::COMBO_SEL_CHANGED:
  942. {
  943. QComboBox* pRt= qobject_cast<QComboBox*>(pRtControl);
  944. QComboBox* pUi = qobject_cast<QComboBox*>(pUiWidget);
  945. bRet = syncComboControl(pRt, pUi, SYNC_MODE::FROM_RUNTIME, false);
  946. if (bRet)
  947. {
  948. qDebug() << "UiManager::syncFromRuntime - QComboBox:" << pUi->currentIndex();
  949. }
  950. }
  951. break;
  952. case UI_SYNC_MSG::LIST_SEL_CHANGED:
  953. {
  954. QListWidget* pRt = qobject_cast<QListWidget*>(pRtControl);
  955. QListWidget* pUi = qobject_cast<QListWidget*>(pUiWidget);
  956. bRet = syncListControl(pRt, pUi, SYNC_MODE::FROM_RUNTIME, false);
  957. if (bRet)
  958. {
  959. qDebug() << "UiManager::syncFromRuntime - QListWidget:" << pUi->currentRow();
  960. }
  961. }
  962. break;
  963. case UI_SYNC_MSG::RADIOBOX_CHANGED:
  964. {
  965. }
  966. break;
  967. case UI_SYNC_MSG::CHECKBOX_CHANGED:
  968. {
  969. }
  970. break;
  971. case UI_SYNC_MSG::VALUE_CHANGED:
  972. {
  973. QLineEdit* pRt = qobject_cast<QLineEdit*>(pRtControl);
  974. QLineEdit* pUi = qobject_cast<QLineEdit*>(pUiWidget);
  975. bRet = syncValueControl(pRt, pUi, SYNC_MODE::TO_RUNTIME);
  976. if (bRet)
  977. {
  978. qDebug() << "UiManager::syncFromRuntime - ValueControl:" << pUi->text();
  979. }
  980. }
  981. break;
  982. default:
  983. {
  984. qWarning() << "UiManager::syncFromRuntime - Unsupported msg : " << (int)msg;
  985. }
  986. break;
  987. }
  988. // 同步完后,通知UI界面刷新此控件(同时更新属性表)
  989. // 2022-9-15,只有数据有变动的时候才需要刷新
  990. if (bRet && m_AllControls.contains(pUiWidget))
  991. {
  992. m_AllControls.value(pUiWidget)->uiScene()->refreshControl(pUiWidget);
  993. }
  994. }
  995. else
  996. {
  997. //qWarning() << "UiManager::syncFromRuntime - Error : Can't find this control.";
  998. }
  999. }
  1000. /// <summary>
  1001. /// 用于UI向Runtime界面中的控件同步
  1002. /// </summary>
  1003. /// <param name="pControl"></param>
  1004. /// <param name="msg"></param>
  1005. void UiManager::syncToRuntime(QWidget* pUiControl, UI_SYNC_MSG msg, bool bFirst)
  1006. {
  1007. // qDebug() << "UiManager::syncToRuntime - msg:" << (int)msg;
  1008. if (m_UiToRtControls.contains(pUiControl))
  1009. {
  1010. bool bRet = false;
  1011. switch (msg)
  1012. {
  1013. case UI_SYNC_MSG::EDIT_TEXT_CHANGED:
  1014. {
  1015. QLineEdit* pUiEdit = qobject_cast<QLineEdit*>(pUiControl);
  1016. QLineEdit* pRtEdit = qobject_cast<QLineEdit*>(m_UiToRtControls.value(pUiControl));
  1017. bRet = syncEditControl(pUiEdit, pRtEdit, SYNC_MODE::TO_RUNTIME, bFirst);
  1018. if (bRet)
  1019. {
  1020. qDebug() << "UiManager::syncToRuntime - QLineEdit:" << pRtEdit->text();
  1021. }
  1022. }
  1023. break;
  1024. case UI_SYNC_MSG::COMBO_SEL_CHANGED:
  1025. {
  1026. QComboBox* pUiCombo = qobject_cast<QComboBox*>(pUiControl);
  1027. QComboBox* pRtCombo = qobject_cast<QComboBox*>(m_UiToRtControls.value(pUiControl));
  1028. bRet = syncComboControl(pUiCombo, pRtCombo, SYNC_MODE::TO_RUNTIME, bFirst);
  1029. if (bRet)
  1030. {
  1031. qDebug() << "UiManager::syncToRuntime - QComboBox:" << pRtCombo->currentIndex();
  1032. }
  1033. }
  1034. break;
  1035. case UI_SYNC_MSG::LIST_SEL_CHANGED:
  1036. {
  1037. QListWidget* pUi = qobject_cast<QListWidget*>(pUiControl);
  1038. QListWidget* pRt= qobject_cast<QListWidget*>(m_UiToRtControls.value(pUiControl));
  1039. // 首次同步需要同步一下所有的选择项
  1040. if (bFirst)
  1041. {
  1042. for (int i = 0; i < pUi->count(); i++)
  1043. {
  1044. pRt->insertItem(i, pUi->item(i)->text());
  1045. }
  1046. }
  1047. pRt->setCurrentRow(pUi->currentRow());
  1048. qDebug() << "UiManager::syncToRuntime - VListBox:" << pRt->currentRow();
  1049. }
  1050. break;
  1051. case UI_SYNC_MSG::RADIOBOX_CHANGED:
  1052. {
  1053. QRadioButton* pUi = qobject_cast<QRadioButton*>(pUiControl);
  1054. QRadioButton* pRt = qobject_cast<QRadioButton*>(m_UiToRtControls.value(pUiControl));
  1055. //// 首次同步需要把名字也复制一下
  1056. //if (bFirst)
  1057. //{
  1058. // pRt->setText(pUi->text());
  1059. //}
  1060. pRt->setChecked(pUi->isChecked());
  1061. qDebug() << "UiManager::syncToRuntime - VRadioBox:" << pRt->isChecked();
  1062. }
  1063. break;
  1064. case UI_SYNC_MSG::CHECKBOX_CHANGED:
  1065. {
  1066. QCheckBox* pUi = qobject_cast<QCheckBox*>(pUiControl);
  1067. QCheckBox* pRt = qobject_cast<QCheckBox*>(m_UiToRtControls.value(pUiControl));
  1068. //// 首次同步需要把名字也复制一下
  1069. //if (bFirst)
  1070. //{
  1071. // pRt->setText(pUi->text());
  1072. //}
  1073. pRt->setCheckState(pUi->checkState());
  1074. qDebug() << "UiManager::syncToRuntime - VCheckBox:" << pRt->checkState();
  1075. }
  1076. break;
  1077. case UI_SYNC_MSG::VALUE_CHANGED:
  1078. {
  1079. QLineEdit* pUi = qobject_cast<QLineEdit*>(pUiControl);
  1080. QLineEdit* pRt = qobject_cast<QLineEdit*>(m_UiToRtControls.value(pUiControl));
  1081. bRet = syncValueControl(pUi, pRt, SYNC_MODE::TO_RUNTIME);
  1082. if (bRet)
  1083. {
  1084. qDebug() << "UiManager::syncToRuntime - ValueControl:" << pRt->text();
  1085. }
  1086. }
  1087. break;
  1088. default:
  1089. break;
  1090. }
  1091. }
  1092. else
  1093. {
  1094. //qWarning() << "UiManager::syncToRuntime - Error : Can't find this control.";
  1095. }
  1096. }
  1097. /// <summary>
  1098. /// 用于数值变更触发回调(只有ValueControl可以关联数值)
  1099. /// </summary>
  1100. /// <param name="pInf"></param>
  1101. void UiManager::syncFromValue(VARIABLE* pInf)
  1102. {
  1103. // 根据不同的数值类型进行不同的转换
  1104. if (m_ValueToUiControls.contains(pInf))
  1105. {
  1106. QList<QWidget*> pWidgets = m_ValueToUiControls.values(pInf);
  1107. // 遍历所有与此Value关联的控件,逐一更新
  1108. for (QWidget* pUiWidget : pWidgets)
  1109. {
  1110. QString strValueText = pInf->getValueString();
  1111. vDebug() << pUiWidget << " - syncFromValue [" << pInf->strName << "](" << strValueText << ").";
  1112. // 同步到ValueControl
  1113. this->syncValueControl(pUiWidget, strValueText, pInf->value.type, SYNC_MODE::FROM_VALUE);
  1114. // 同步完后,通知UI界面刷新此控件(同时更新属性表)
  1115. // 2022-5-22 此处在多个属性表同时高速刷新时,会造成控件多个属性表之间切换,所以临时屏蔽。
  1116. //if (m_AllControls.contains(pUiWidget))
  1117. //{
  1118. // m_AllControls.value(pUiWidget)->refreshControl(pUiWidget);
  1119. //}
  1120. }
  1121. }
  1122. else
  1123. {
  1124. //qWarning() << "UiManager::syncFromValue - Error : Can't find this value.";
  1125. }
  1126. }
  1127. /// <summary>
  1128. /// 用于UI变更向数值单向同步
  1129. /// </summary>
  1130. /// <param name="pControl"></param>
  1131. void UiManager::syncToValue(QWidget* pUiControl)
  1132. {
  1133. if (m_UiControlToValues.contains(pUiControl))
  1134. {
  1135. VARIABLE* linkValue = m_UiControlToValues.value(pUiControl);
  1136. QString className = pUiControl->metaObject()->className();
  1137. QString strValue;
  1138. if (className == CLASS_NAME_VALUECONTROL)
  1139. {
  1140. ValueControl* pVControl = qobject_cast<ValueControl*>(pUiControl);
  1141. if (pVControl != nullptr)
  1142. {
  1143. strValue = pVControl->text();
  1144. }
  1145. }
  1146. else if (className == CLASS_NAME_RESULT)
  1147. {
  1148. VResult* pVControl = qobject_cast<VResult*>(pUiControl);
  1149. if (pVControl != nullptr)
  1150. {
  1151. strValue = pVControl->text();
  1152. }
  1153. }
  1154. // 2021-11-2增加,如果对应的接口是一个输出接口,那么忽略这个赋值(输出接口不允许从UI输入)
  1155. if (linkValue->Direction == INF_DIRECTION::INF_DIR_OUT)
  1156. {
  1157. qDebug() << "UiManager::syncToValue - ignore: this LinkValue is INF_DIR_OUT.";
  1158. return;
  1159. }
  1160. // 直接将字符串拷贝过去
  1161. //QString strValue = pVControl->toPlainText();
  1162. //linkValue->setValue(strValue);
  1163. // 根据不同的数值类型进行不同的转换
  1164. bool bRet = false;
  1165. switch (linkValue->value.type)
  1166. {
  1167. case VALUE_TYPE::Type_Int:
  1168. {
  1169. // 获取控件数值
  1170. int controlValue = strValue.toInt();
  1171. bRet = linkValue->setValue<int>(controlValue);
  1172. if (bRet)
  1173. {
  1174. // vDebug() << "Tpye:" << Utility::getTypeString(VALUE_TYPE::Type_Int) << " value:" << controlValue;
  1175. vDebug() << pUiControl << " - syncToValue [" << linkValue->strName << "](" << controlValue << ").";
  1176. }
  1177. }
  1178. break;
  1179. default:
  1180. {
  1181. vDebug() << "[Error] : " << (int)linkValue->value.type;
  1182. }
  1183. break;
  1184. }
  1185. }
  1186. else
  1187. {
  1188. //qWarning() << "UiManager::syncToValue - Error : Can't find this control.";
  1189. }
  1190. }
  1191. /// <summary>
  1192. /// 同步Edit控件
  1193. /// </summary>
  1194. /// <param name="pSrc"></param>
  1195. /// <param name="pDst"></param>
  1196. /// <param name="mode"></param>
  1197. /// <param name="bFirst"></param>
  1198. /// <returns></returns>
  1199. bool UiManager::syncEditControl(QLineEdit* pSrc, QLineEdit* pDst, SYNC_MODE mode, bool bFirst)
  1200. {
  1201. Q_UNUSED(bFirst);
  1202. QString strSrc = pSrc->text();
  1203. QString strDst = pDst->text();
  1204. if (strDst != strSrc)
  1205. {
  1206. if (mode == SYNC_MODE::TO_DLL)
  1207. {
  1208. pDst->setText(strSrc);
  1209. }
  1210. else
  1211. {
  1212. VLineEdit* vEdit = qobject_cast<VLineEdit*>(pDst);
  1213. vEdit->setText(strSrc);
  1214. }
  1215. return true;
  1216. }
  1217. return false;
  1218. }
  1219. /// <summary>
  1220. /// 同步Combo控件
  1221. /// </summary>
  1222. /// <param name="pSrc"></param>
  1223. /// <param name="pDst"></param>
  1224. /// <param name="mode"></param>
  1225. /// <param name="bFirst"></param>
  1226. /// <returns></returns>
  1227. bool UiManager::syncComboControl(QComboBox* pSrc, QComboBox* pDst, SYNC_MODE mode, bool bFirst /*= false*/)
  1228. {
  1229. Q_UNUSED(mode);
  1230. // 首次同步需要同步Combo列表项
  1231. if (bFirst)
  1232. {
  1233. for (int i = 0; i < pSrc->count(); i++)
  1234. {
  1235. pDst->insertItem(i, pSrc->itemText(i));
  1236. }
  1237. }
  1238. int nIndexSrc = pSrc->currentIndex();
  1239. int nIndexDst = pDst->currentIndex();
  1240. if (nIndexDst != nIndexSrc)
  1241. {
  1242. pDst->setCurrentIndex(pSrc->currentIndex());
  1243. return true;
  1244. }
  1245. return false;
  1246. }
  1247. /// <summary>
  1248. /// 同步list控件
  1249. /// </summary>
  1250. /// <param name="pSrc"></param>
  1251. /// <param name="pDst"></param>
  1252. /// <param name="mode"></param>
  1253. /// <param name="bFirst"></param>
  1254. /// <returns></returns>
  1255. bool UiManager::syncListControl(QListWidget* pSrc, QListWidget* pDst, SYNC_MODE mode, bool bFirst /*= false*/)
  1256. {
  1257. Q_UNUSED(mode);
  1258. // 首次同步需要同步List列表项
  1259. if (bFirst)
  1260. {
  1261. for (int i = 0; i < pSrc->count(); i++)
  1262. {
  1263. pDst->insertItem(i, pSrc->item(i)->text());
  1264. }
  1265. }
  1266. int nIndexSrc = pSrc->currentRow();
  1267. int nIndexDst = pDst->currentRow();
  1268. if (nIndexDst != nIndexSrc)
  1269. {
  1270. pDst->setCurrentRow(nIndexSrc);
  1271. return true;
  1272. }
  1273. return false;
  1274. }
  1275. /// <summary>
  1276. /// 同步Value Control(数值)
  1277. /// </summary>
  1278. /// <param name="pValueControl"></param>
  1279. /// <param name="strNewValue"></param>
  1280. /// <param name="type"></param>
  1281. /// <returns></returns>
  1282. bool UiManager::syncValueControl(QWidget* pValueControl, QString strNewValue, VALUE_TYPE type, SYNC_MODE mode)
  1283. {
  1284. Q_UNUSED(mode);
  1285. Q_UNUSED(type);
  1286. if (pValueControl == nullptr)
  1287. {
  1288. return false;
  1289. }
  1290. QString className = pValueControl->metaObject()->className();
  1291. if (className == CLASS_NAME_VALUECONTROL)
  1292. {
  1293. ValueControl* pControl = qobject_cast<ValueControl*>(pValueControl);
  1294. if (pValueControl == nullptr || pControl == nullptr)
  1295. {
  1296. return false;
  1297. }
  1298. QString strCurrentText = pControl->text();
  1299. // 如果文字相同则不更新了,防止消息死循环
  1300. if (strCurrentText == strNewValue)
  1301. {
  1302. return false;
  1303. }
  1304. // 设置新值
  1305. pControl->setText(strNewValue);
  1306. }
  1307. else if (className == CLASS_NAME_RESULT)
  1308. {
  1309. VResult* pControl = qobject_cast<VResult*>(pValueControl);
  1310. if (pValueControl == nullptr || pControl == nullptr)
  1311. {
  1312. return false;
  1313. }
  1314. QString strCurrentText = pControl->text();
  1315. QString strCurrentTip = pControl->toolTip();
  1316. // 剔除掉 Tip 文本
  1317. strCurrentText = strCurrentText.replace(QRegExp(strCurrentTip + STRING_INTERVAL), "");
  1318. // 如果文字相同则不更新了,防止消息死循环
  1319. if (strCurrentText == strNewValue)
  1320. {
  1321. return false;
  1322. }
  1323. // 设置新值
  1324. pControl->setText(strCurrentTip + STRING_INTERVAL + strNewValue);
  1325. //pControl->setText(strCurrentTip);
  1326. }
  1327. else
  1328. {
  1329. return false;
  1330. }
  1331. //if (mode == SYNC_MODE::FROM_VALUE)
  1332. //{
  1333. // qDebug() << "UiManager::syncFromValue - tpye:" << Utility::getTypeString(type) << " value:"
  1334. // << strNewValue << " toControl:" << pControl->m_pWidget;
  1335. //}
  1336. //else if (mode == SYNC_MODE::TO_VALUE)
  1337. //{
  1338. // qDebug() << "UiManager::syncToValue - tpye:" << Utility::getTypeString(type) << " value:"
  1339. // << strNewValue << " fromControl:" << pControl->m_pWidget;;
  1340. //}
  1341. return true;
  1342. }
  1343. /// <summary>
  1344. /// 同步Value Control(控件)
  1345. /// </summary>
  1346. /// <param name="pSrc"></param>
  1347. /// <param name="pDst"></param>
  1348. /// <param name="mode"></param>
  1349. /// <returns></returns>
  1350. bool UiManager::syncValueControl(QLineEdit* pSrc, QLineEdit* pDst, SYNC_MODE mode)
  1351. {
  1352. Q_UNUSED(mode);
  1353. QString strSrc = pSrc->text();
  1354. QString strDst = pDst->text();
  1355. if (strDst != strSrc)
  1356. {
  1357. if (mode == SYNC_MODE::TO_DLL)
  1358. {
  1359. pDst->setText(strSrc);
  1360. }
  1361. else
  1362. {
  1363. QString className = pDst->metaObject()->className();
  1364. if (className == CLASS_NAME_VALUECONTROL)
  1365. {
  1366. ValueControl* pVControl = qobject_cast<ValueControl*>(pDst);
  1367. if (pVControl != nullptr)
  1368. {
  1369. pVControl->setText(strSrc);
  1370. }
  1371. }
  1372. else if (className == CLASS_NAME_RESULT)
  1373. {
  1374. VResult* pVControl = qobject_cast<VResult*>(pDst);
  1375. if (pVControl != nullptr)
  1376. {
  1377. pVControl->setText(strSrc);
  1378. }
  1379. }
  1380. else
  1381. {
  1382. return false;
  1383. }
  1384. }
  1385. return true;
  1386. }
  1387. return false;
  1388. }
  1389. ///// <summary>
  1390. ///// 删除所有UI
  1391. ///// </summary>
  1392. //void UiManager::deleteAllUIs()
  1393. //{
  1394. //
  1395. //}
  1396. /// <summary>
  1397. /// 重置所有UI页面以及数据结构(用于反序列化使用)
  1398. /// </summary>
  1399. void UiManager::reset()
  1400. {
  1401. m_pMainPage = nullptr;
  1402. m_pAllPages.clear();
  1403. m_AllControls.clear();
  1404. m_DllToUiControls.clear();
  1405. m_UiToDllControls.clear();
  1406. m_UiToRtControls.clear();
  1407. m_RtToUiControls.clear();
  1408. m_UiControlToValues.clear();
  1409. m_ValueToUiControls.clear();
  1410. }
  1411. /// <summary>
  1412. /// 2022-2-12 根据控件指针查找对应的WindowAppUiView指针
  1413. /// </summary>
  1414. /// <param name="pUiControl"></param>
  1415. /// <returns></returns>
  1416. WindowAppUiView* UiManager::getViewByControl(VControlObject* pUiControl)
  1417. {
  1418. return m_AllControls.value(pUiControl->m_pWidget);
  1419. }
  1420. /// <summary>
  1421. /// 刷新指定控件的选中效果(用于适配geometry的实时更新)
  1422. /// </summary>
  1423. /// <param name="pUiControl"></param>
  1424. void UiManager::refreshControlDrawPoint(VControlObject* pUiControl)
  1425. {
  1426. WindowAppUiView* pUiView = m_AllControls.value(pUiControl->m_pWidget);
  1427. if (pUiView)
  1428. {
  1429. pUiView->uiScene()->refreshDrawPoint(pUiControl->m_pWidget);
  1430. }
  1431. }
  1432. /// <summary>
  1433. /// 2022-2-10 从DataLink中解析Tool信息
  1434. /// </summary>
  1435. /// <param name="dataLink"></param>
  1436. /// <param name="pPou"></param>
  1437. /// <param name="pTool"></param>
  1438. /// <param name="pDllInf"></param>
  1439. void UiManager::parsePouToolFromDataLink(
  1440. const DataLink& dataLink,
  1441. POU*& pPou,
  1442. TOOL*& pTool,
  1443. _INTERFACE*& pDllInf
  1444. )
  1445. {
  1446. pPou = nullptr;
  1447. pTool = nullptr;
  1448. pDllInf = nullptr;
  1449. if (dataLink.value.size() < 3)
  1450. {
  1451. return;
  1452. }
  1453. // 从DataLink信息中解析出接口信息
  1454. QString strCategory = dataLink.value.at(0);
  1455. QString strCmd = dataLink.value.at(1);
  1456. QString strDetail = dataLink.value.at(2);
  1457. // 2021-10-28 解析需要处理局部和全局变量
  1458. bool bBindVariables = false;
  1459. if (strCmd.indexOf(GROUP_GLOBAL_VARIABLE) >= 0
  1460. || strCmd.indexOf(GROUP_LOCAL_VARIABLE) >= 0)
  1461. {
  1462. bBindVariables = true;
  1463. }
  1464. // Tool接口
  1465. if (!bBindVariables)
  1466. {
  1467. // 根据名字找到对应的_INTERFACE*
  1468. pPou = g_pPouManager->getPouByName(strCategory);
  1469. if (pPou != nullptr)
  1470. {
  1471. pTool = pPou->GetToolByName(strCmd);
  1472. if (pTool != nullptr)
  1473. {
  1474. pDllInf = pTool->getInterfaceByName(strDetail);
  1475. }
  1476. else
  1477. {
  1478. qWarning() << "GetToolByName " << strCmd << " Error";
  1479. }
  1480. }
  1481. }
  1482. // 局部和全局变量
  1483. else
  1484. {
  1485. strCategory.remove(VAR_SUFFIX);
  1486. strCmd = strCategory;
  1487. pTool = g_pGvlManager->getGvl(strCmd);
  1488. pDllInf = pTool->getInterfaceByName(strDetail);
  1489. }
  1490. }
  1491. /// <summary>
  1492. /// 2022-2-10 从DataLink中解析Interface信息
  1493. /// </summary>
  1494. /// <param name="dataLink"></param>
  1495. /// <param name="pDllInf"></param>
  1496. void UiManager::parseToolInfFromDataLink( const DataLink& dataLink, _INTERFACE*& pDllInf)
  1497. {
  1498. POU* pPou = nullptr;
  1499. TOOL* pTool = nullptr;
  1500. pDllInf = nullptr;
  1501. this->parsePouToolFromDataLink(dataLink, pPou, pTool, pDllInf);
  1502. }