WindowAppUiScene.cpp 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  1. #include "WindowAppUiScene.h"
  2. #include "WindowAppUiFrame.h"
  3. #include "UiManager.h"
  4. #include "WindowRuntime.h"
  5. #include "selectwidget.h"
  6. #include "VPControls.h"
  7. #include "WindowAppItemRefLine.h"
  8. VControlObject* WindowAppUiScene::m_pCurrentObject = nullptr;
  9. WindowAppUiScene::WindowAppUiScene(QGraphicsView* parent /*= nullptr*/)
  10. : QGraphicsScene(parent)
  11. , m_pUiFrame(nullptr)
  12. , m_pUiView((WindowAppUiView*)parent)
  13. {
  14. // For Test
  15. //QLineEdit* newButton = new QLineEdit(nullptr);
  16. //this->addWidget(newButton);
  17. //newButton->resize(130, 20);
  18. //newButton->move(100, 100);
  19. // 为参考线管理器绑定指针
  20. m_RefLineManager.bindScene(this);
  21. // 为等宽线管理器绑定指针
  22. m_IsoLineManager.bindScene(this);
  23. }
  24. /// <summary>
  25. /// 清空所有控件焦点
  26. /// </summary>
  27. void WindowAppUiScene::clearFocus()
  28. {
  29. //将原有焦点窗体全部设置成无焦点
  30. for (SelectWidget* w : m_SelectControls)
  31. {
  32. w->setDrawPoint(false);
  33. }
  34. }
  35. /// <summary>
  36. /// 当控件被按下时
  37. /// </summary>
  38. /// <param name="widget"></param>
  39. void WindowAppUiScene::widgetPressed(QWidget* widget)
  40. {
  41. //清空所有控件的焦点
  42. clearFocus();
  43. // qDebug() << "WindowAppUiScene::widgetPressed";
  44. //设置当前按下的控件选中效果
  45. for (SelectWidget* w : m_SelectControls)
  46. {
  47. if (w->getWidget() == widget)
  48. {
  49. // 设置选中效果
  50. w->setDrawPoint(true);
  51. m_pCurrentWidget = widget;
  52. //设置自动加载该控件的所有属性
  53. // m_pOwner->ui.objectController->setObject(nullptr);
  54. m_pUiFrame->ui.objectController->setObject(widget);
  55. // 获取控件最新的尺寸和位置信息
  56. OBJECT_SYNC_PROPERTY syncInfo;
  57. syncInfo.type = OBJECT_SYNC_TYPE::SYNC_GEOMETRY;
  58. syncInfo.value = widget->geometry();
  59. // 更新到属性表中
  60. m_pUiFrame->ui.objectController->syncToObject(widget, syncInfo);
  61. // 2022-5-22 设置当前用户选择的控件信息,用于后续绑定需要
  62. m_pCurrentObject = m_pUiFrame->ui.objectController->vobject();
  63. // 2022-10-21,按下时记录控件当前位置,用于比较鼠标抬起后是否移动
  64. m_oldPos = m_pCurrentWidget->pos();
  65. // 2022-10-21,按下时记录控件当前尺寸,用于比较鼠标抬起后是否变更了尺寸
  66. m_oldGeometry = m_pCurrentWidget->geometry();
  67. break;
  68. }
  69. }
  70. }
  71. /// <summary>
  72. /// 当控件释放时
  73. /// </summary>
  74. /// <param name="widget"></param>
  75. void WindowAppUiScene::widgetRelease(QWidget* widget)
  76. {
  77. // 首先进行控件的自动对齐
  78. // this->autoAlignToGrid(widget);
  79. // 释放控件时,无论如何都清空所有的参考线
  80. m_RefLineManager.clear();
  81. // 同时清空所有的等宽线
  82. m_IsoLineManager.clear();
  83. //设置自动加载该控件的所有属性
  84. // m_pOwner->ui.objectController->setObject(nullptr);
  85. m_pUiFrame->ui.objectController->setObject(widget);
  86. // 获取控件最新的尺寸和位置信息
  87. OBJECT_SYNC_PROPERTY syncInfo;
  88. syncInfo.type = OBJECT_SYNC_TYPE::SYNC_GEOMETRY;
  89. syncInfo.value = widget->geometry();
  90. // 更新到属性表中
  91. m_pUiFrame->ui.objectController->syncToObject(widget, syncInfo);
  92. // 2022-10-21,抬起时记录控件当前位置,用于比较鼠标抬起后是否移动
  93. this->checkCurrentControlMove();
  94. // 2022-10-21,抬起时记录控件当前尺寸,用于比较鼠标抬起后是否缩放
  95. this->checkCurrentControlZoom();
  96. }
  97. /// <summary>
  98. /// 当控件删除时
  99. /// </summary>
  100. /// <param name="widget"></param>
  101. void WindowAppUiScene::widgetDelete(QWidget* widget)
  102. {
  103. // 从数据结构中删除关联
  104. g_pUiManager->deleteControl(widget);
  105. // 从界面中删除控件
  106. for (int i = 0; i < m_SelectControls.count(); i++)
  107. {
  108. if (m_SelectControls.at(i)->getWidget() == widget)
  109. {
  110. // 需要清空SelectWidget自身,否则会造成崩溃问题
  111. m_SelectControls.at(i)->deleteLater();
  112. m_SelectControls.removeAt(i);
  113. break;
  114. }
  115. }
  116. // 2021-12-26增加,删除本控件相关的属性表数据结构
  117. m_pUiFrame->ui.objectController->delObject(widget);
  118. // 2021-12-28增加,在Runtime中删除控件相关数据结构
  119. g_pRuntime->releaseControl(widget);
  120. }
  121. /// <summary>
  122. /// 当控件移动时
  123. /// </summary>
  124. /// <param name="widget"></param>
  125. void WindowAppUiScene::widgetMove(QWidget* widget)
  126. {
  127. // qDebug() << "WindowAppUiScene::widgetMove - " << widget;
  128. // 检查控件参考线
  129. this->checkRefLine(widget);
  130. }
  131. /// <summary>
  132. /// 2022-9-16,当控件拉伸时(用于绘制等宽线)
  133. /// </summary>
  134. /// <param name="widget"></param>
  135. /// <param name="dir"></param>
  136. void WindowAppUiScene::widgetStretch(QWidget* widget, STRETCH_DIRECTION dir)
  137. {
  138. // qDebug() << "WindowAppUiScene::widgetStretch - " << widget <<" Direction:" << (int)dir;
  139. this->checkIsoLine(widget, dir);
  140. }
  141. /// <summary>
  142. /// 2022-8-14 控件移动时,处理参考线相关
  143. /// </summary>
  144. /// <param name="widget"></param>
  145. void WindowAppUiScene::checkRefLine(QWidget* widget)
  146. {
  147. // 遍历所有的控件,然后通过RefLineManager处理所有控件之间的参考线
  148. for (SelectWidget* w : m_SelectControls)
  149. {
  150. // 排除自身
  151. if (widget == w->m_pWidget)
  152. {
  153. continue;
  154. }
  155. // 当前选中控件、和UI界面中的其他控件
  156. m_RefLineManager.check(widget, w->m_pWidget);
  157. }
  158. }
  159. /// <summary>
  160. /// 2022-9-16 控件被拉伸时,进行等宽线相关的实时计算
  161. /// </summary>
  162. /// <param name="widget"></param>
  163. void WindowAppUiScene::checkIsoLine(QWidget* widget, STRETCH_DIRECTION dir)
  164. {
  165. QList<QWidget*> dstWidgets;
  166. // 遍历所有的控件,选出需要及逆行等宽线判断的其他所有控件
  167. for (SelectWidget* w : m_SelectControls)
  168. {
  169. // 排除自身
  170. if (widget != w->m_pWidget)
  171. {
  172. dstWidgets.push_back(w->m_pWidget);
  173. }
  174. }
  175. // 开始处理等宽线相关事宜
  176. m_IsoLineManager.check(widget, dstWidgets, dir);
  177. }
  178. /// <summary>
  179. /// 2022-10-22,检查当前控件是否移动
  180. /// </summary>
  181. void WindowAppUiScene::checkCurrentControlMove()
  182. {
  183. // 比较鼠标抬起后是否移动
  184. QPoint curPos = m_pCurrentWidget->pos();
  185. // 如果移动了,则记录这次动作,用于执行Redo
  186. if (curPos != m_oldPos)
  187. {
  188. UiControlMoveCommand* controlMoveCommand = new UiControlMoveCommand(
  189. this,
  190. m_pCurrentObject->m_strID,
  191. m_oldPos,
  192. curPos
  193. );
  194. this->m_CommandManager.executeCommand(controlMoveCommand, true);
  195. m_oldPos = curPos;
  196. }
  197. }
  198. /// <summary>
  199. /// 2022-10-22,检查当前控件是否缩放
  200. /// </summary>
  201. void WindowAppUiScene::checkCurrentControlZoom()
  202. {
  203. // 比较鼠标抬起后尺寸是否变化
  204. QRect curGeometry = m_pCurrentWidget->geometry();
  205. // 如果尺寸不同了,则记录这次动作,用于执行Redo
  206. if (curGeometry != m_oldGeometry)
  207. {
  208. UiControlZoomCommand* controlZoomCommand = new UiControlZoomCommand(
  209. this,
  210. m_pCurrentObject->m_strID,
  211. m_oldGeometry,
  212. curGeometry
  213. );
  214. this->m_CommandManager.executeCommand(controlZoomCommand, true);
  215. m_oldGeometry = curGeometry;
  216. }
  217. }
  218. /// <summary>
  219. /// 将生成的控件选入列表中
  220. /// </summary>
  221. /// <param name="widget"></param>
  222. /// <param name="type"></param>
  223. /// <param name="pProperty"></param>
  224. void WindowAppUiScene::addSelection(
  225. VControlObject* pControl,
  226. VALUE_TYPE type,
  227. CONTROL_PROPERTY* pProperty,
  228. CONTROL_PROPERTY_EX* pPropertyEx /* = nullptr */
  229. )
  230. {
  231. SelectWidget* select = new SelectWidget(m_pUiView);
  232. // 绑定控件选中消息
  233. connect(select, SIGNAL(widgetPressed(QWidget*)), this, SLOT(widgetPressed(QWidget*)));
  234. // 绑定控件释放消息
  235. connect(select, SIGNAL(widgetRelease(QWidget*)), this, SLOT(widgetRelease(QWidget*)));
  236. // 绑定控件移动消息
  237. connect(select, SIGNAL(widgetMove(QWidget*)), this, SLOT(widgetMove(QWidget*)));
  238. // 绑定控件拉伸消息
  239. connect(select, SIGNAL(widgetStretch(QWidget*, STRETCH_DIRECTION)), this, SLOT(widgetStretch(QWidget*, STRETCH_DIRECTION)));
  240. //// Delete快捷键的删除消息
  241. //connect(select, SIGNAL(widgetDelete(QWidget*)), this, SLOT(widgetDelete(QWidget*)));
  242. select->setWidget(pControl->m_pWidget);
  243. select->m_Type = type;
  244. // 2022-10-6,控件ID
  245. select->m_strID = pControl->m_strID;
  246. // 2021-10-5增加,绑定控件属性
  247. select->m_pProperty = pProperty;
  248. select->m_pPropertyEx = pPropertyEx;
  249. // this->addWidget(pControl->m_pWidget);
  250. // 加入选择控件列表中
  251. m_SelectControls.append(select);
  252. // 直接选中控件,并且显示对应属性框
  253. widgetPressed(pControl->m_pWidget);
  254. }
  255. ///// <summary>
  256. ///// 新建自定义控件
  257. ///// </summary>
  258. ///// <param name="row"></param>
  259. ///// <param name="point"></param>
  260. //VControlObject* WindowAppUiScene::newControl(
  261. // int row,
  262. // const QPoint& newPt,
  263. // const QString& controlID,
  264. // const QSize& newSize,
  265. // CONTROL_PROPERTY* prop,
  266. // CONTROL_PROPERTY_EX* propex
  267. //)
  268. //{
  269. // // 将界面中用户选择的行数转换成对应的valueType
  270. // VALUE_TYPE controlType = (VALUE_TYPE)(row + (int)VALUE_TYPE::Control_Base + 1);
  271. //
  272. // return this->newControl(controlType, newPt, controlID, newSize, prop, propex);
  273. //}
  274. /// <summary>
  275. /// 新建自定义控件(按类型)
  276. /// </summary>
  277. /// <param name="type"></param>
  278. /// <param name="point"></param>
  279. /// <param name="prop"></param>
  280. /// <param name="propex"></param>
  281. VControlObject* WindowAppUiScene::newControl(
  282. VALUE_TYPE controlType,
  283. const QPoint& newPt,
  284. const QString& controlID,
  285. const QSize& newSize,
  286. CONTROL_PROPERTY* prop /*= nullptr*/,
  287. CONTROL_PROPERTY_EX* propex /*= nullptr */
  288. )
  289. {
  290. VControlObject* pNewControl = nullptr;
  291. switch (controlType)
  292. {
  293. case VALUE_TYPE::Control_Label:
  294. {
  295. pNewControl = new VLabel(nullptr, newPt, newSize, prop);
  296. }
  297. break;
  298. case VALUE_TYPE::Control_Button:
  299. {
  300. pNewControl = new VButton(nullptr, newPt, newSize, prop);
  301. }
  302. break;
  303. case VALUE_TYPE::Control_CheckBox:
  304. {
  305. pNewControl = new VCheckBox(nullptr, newPt, newSize, prop);
  306. // 绑定CheckBox变动信号
  307. connect(pNewControl->m_pWidget, SIGNAL(stateChanged(int)), this, SLOT(onVCheckChanged(int)));
  308. }
  309. break;
  310. case VALUE_TYPE::Control_RadioBox:
  311. {
  312. pNewControl = new VRadioBox(nullptr, newPt, newSize, prop);
  313. // 绑定RadioBox变动信号
  314. connect(pNewControl->m_pWidget, SIGNAL(toggled(bool)), this, SLOT(onVRadioChanged(bool)));
  315. }
  316. break;
  317. case VALUE_TYPE::Control_Groupbox:
  318. {
  319. pNewControl = new VGroupBox(nullptr, newPt, newSize, prop);
  320. }
  321. break;
  322. case VALUE_TYPE::Control_Image:
  323. {
  324. pNewControl = new VImageControl(nullptr, newPt, newSize, prop, propex);
  325. // 2022-9-11 为刷新链接绑定默认值(系统的执行次数)
  326. pNewControl->bindDefaultRefreshDataLink();
  327. //pNewControl->m_pWidget = new HWndUnit(nullptr);
  328. //pNewControl->m_pWidget->resize(DEFAULT_IMAGE_SIZE);
  329. //pNewControl->m_pWidget->move(newPt);
  330. }
  331. break;
  332. case VALUE_TYPE::Control_LineEdit:
  333. {
  334. pNewControl = new VLineEdit(nullptr, newPt, newSize, prop);
  335. //pNewControl->m_pWidget = new QLineEdit(nullptr);
  336. //pNewControl->m_pWidget->resize(DEFAULT_EDIT_SIZE);
  337. //pNewControl->m_pWidget->move(newPt);
  338. // 注册文字变更消息用于同步
  339. connect(pNewControl->m_pWidget, SIGNAL(textChanged(QString)), this, SLOT(onVEditChanged(QString)));
  340. }
  341. break;
  342. case VALUE_TYPE::Control_Listbox:
  343. {
  344. pNewControl = new VListBox(nullptr, newPt, newSize, prop);
  345. // 绑定ListBox变动信号
  346. connect(pNewControl->m_pWidget, SIGNAL(currentRowChanged(int)), this, SLOT(onVListChanged(int)));
  347. }
  348. break;
  349. case VALUE_TYPE::Control_ComboBox:
  350. {
  351. pNewControl = new VComboBox(nullptr, newPt, newSize, prop);
  352. // 绑定ComboBox变动信号
  353. connect(pNewControl->m_pWidget, SIGNAL(currentIndexChanged(int)), this, SLOT(onVComboChanged(int)));
  354. }
  355. break;
  356. case VALUE_TYPE::Control_Value:
  357. {
  358. pNewControl = new ValueControl(nullptr, newPt, newSize, prop);
  359. // 注册文字变更消息用于同步至Value
  360. connect(pNewControl->m_pWidget, SIGNAL(textChanged(QString)), this, SLOT(onValueControlChanged(QString)));
  361. // 2022-9-11 Value控件需要绑定默认的DataLink
  362. pNewControl->bindDefaultDataLink();
  363. }
  364. break;
  365. case VALUE_TYPE::Control_PieChart:
  366. {
  367. pNewControl = new VPieChart(nullptr, newPt, newSize, prop, propex);
  368. // 2022-9-11 为刷新链接绑定默认值(系统的执行次数)
  369. pNewControl->bindDefaultRefreshDataLink();
  370. }
  371. break;
  372. case VALUE_TYPE::Control_CustomPlot:
  373. {
  374. pNewControl = new VCustomPlot(nullptr, newPt, newSize, prop, propex);
  375. // 2022-9-11 为刷新链接绑定默认值(系统的执行次数)
  376. pNewControl->bindDefaultRefreshDataLink();
  377. }
  378. break;
  379. case VALUE_TYPE::Control_Table:
  380. {
  381. pNewControl = new VTableControl(nullptr, newPt, newSize, prop, propex);
  382. }
  383. break;
  384. case VALUE_TYPE::Control_Result:
  385. {
  386. pNewControl = new VResult(nullptr, newPt, newSize, prop);
  387. // 注册文字变更消息用于同步至Value
  388. connect(pNewControl->m_pWidget, SIGNAL(textChanged(QString)), this, SLOT(onResultControlChanged(QString)));
  389. // 2022-9-11 Value控件需要绑定默认的DataLink
  390. pNewControl->bindDefaultDataLink();
  391. }
  392. break;
  393. default:
  394. qWarning() << "[UI] WindowAppUiScene::newControl - invalid control type:" << static_cast<short>(controlType);
  395. return nullptr;
  396. }
  397. // 创建失败,应该不会发生
  398. if (pNewControl == nullptr)
  399. {
  400. qWarning() << "[UI] WindowAppUiScene::newControl - Create control failed, type " << static_cast<short>(controlType);
  401. return nullptr;
  402. }
  403. // 2022-8-10,将控件的位置进行自动对齐
  404. // this->autoAlignToGrid(pNewControl->m_pWidget);
  405. // 将控件加入到界面中
  406. // Scene无法添加有父窗体的控件,只能先设置为nulltpr了,如果这里不设置为nullptr,前面建立的时候设置为nullptr的话,带来的问题更多
  407. // pNewControl->m_pWidget->setParent(nullptr);
  408. // 保存ProxyWidget指针,方便后续操作控件
  409. pNewControl->m_pProxyWidget = this->addWidget(pNewControl->m_pWidget);
  410. // 2022-10-6,如果没有为控件指定ID的话,则为本控件生成新的唯一UUID
  411. if (controlID.isEmpty())
  412. {
  413. pNewControl->m_strID = QUuid::createUuid().toString();
  414. }
  415. // 否则就直接把当前ID赋值
  416. else
  417. {
  418. pNewControl->m_strID = controlID;
  419. }
  420. if (pNewControl->isComplexControl())
  421. {
  422. // 将控件加入到选中列表中
  423. addSelection(
  424. pNewControl,
  425. controlType,
  426. &pNewControl->m_Property,
  427. &pNewControl->m_PropertyEx
  428. );
  429. }
  430. else
  431. {
  432. // 将控件加入到选中列表中
  433. addSelection(
  434. pNewControl,
  435. controlType,
  436. &pNewControl->m_Property,
  437. nullptr
  438. );
  439. }
  440. // 2022-10-7,将向UI Manager注册本控件从WindowAppUiView中移到了这里
  441. g_pUiManager->regiterNewControl(pNewControl, this->m_pUiView);
  442. // 2022-2-4 返回新控件指针
  443. return pNewControl;
  444. }
  445. /// <summary>
  446. /// 获取本界面中的所有控件
  447. /// </summary>
  448. /// <returns></returns>
  449. QList<SelectWidget*> WindowAppUiScene::getAllControls()
  450. {
  451. return this->m_SelectControls;
  452. }
  453. /// <summary>
  454. /// 刷新指定控件(用于更新属性表)
  455. /// </summary>
  456. /// <param name="pControl"></param>
  457. void WindowAppUiScene::refreshControl(QWidget* pControl)
  458. {
  459. // widgetRelease(pControl);
  460. // 2022-9-15 只刷新当前控件的属性表,防止Runtime同步到UI时,属性表乱跳的bug
  461. if (pControl == m_pCurrentWidget)
  462. {
  463. m_pUiFrame->ui.objectController->setObject(pControl);
  464. }
  465. }
  466. /// <summary>
  467. /// 刷新指定控件的选中效果(用于适配属性表更新后的选中效果更新)
  468. /// </summary>
  469. /// <param name="pControl"></param>
  470. void WindowAppUiScene::refreshDrawPoint(QWidget* pControl)
  471. {
  472. //清空所有控件的焦点
  473. clearFocus();
  474. //设置当前按下的控件有焦点
  475. for (SelectWidget* w : m_SelectControls)
  476. {
  477. if (w->getWidget() == pControl)
  478. {
  479. // 需要按照最新的控件形状信息重新设置选中效果
  480. w->setWidget(pControl);
  481. // 设置选中效果
  482. w->setDrawPoint(true);
  483. m_pCurrentWidget = pControl;
  484. break;
  485. }
  486. }
  487. }
  488. /// <summary>
  489. /// 2022-10-21,获取指定ID号的控件SelectWidget
  490. /// </summary>
  491. /// <param name="strID"></param>
  492. /// <returns></returns>
  493. SelectWidget* WindowAppUiScene::getSelectWidgetByID(const QString& strID)
  494. {
  495. for (SelectWidget* w : m_SelectControls)
  496. {
  497. if (w->m_strID == strID)
  498. {
  499. return w;
  500. }
  501. }
  502. return nullptr;
  503. }
  504. /// <summary>
  505. /// 排序到最前
  506. /// </summary>
  507. void WindowAppUiScene::zorderTopCurrentControl()
  508. {
  509. if (getCurrentControl() == nullptr || getCurrentControl()->getItem() == nullptr)
  510. {
  511. return;
  512. }
  513. int nSize = getAllControls().size();
  514. getCurrentControl()->getItem()->setZValue(nSize + 1);
  515. }
  516. /// <summary>
  517. /// 排序到最底
  518. /// </summary>
  519. void WindowAppUiScene::zorderBottomCurrentControl()
  520. {
  521. if (getCurrentControl() == nullptr || getCurrentControl()->getItem() == nullptr)
  522. {
  523. return;
  524. }
  525. getCurrentControl()->getItem()->setZValue(0);
  526. }
  527. /// <summary>
  528. /// 排序到前一个
  529. /// </summary>
  530. void WindowAppUiScene::zorderUpCurrentControl()
  531. {
  532. if (getCurrentControl() == nullptr || getCurrentControl()->getItem() == nullptr)
  533. {
  534. return;
  535. }
  536. qreal zValue = getCurrentControl()->getItem()->zValue();
  537. getCurrentControl()->getItem()->setZValue(zValue + 1);
  538. }
  539. /// <summary>
  540. /// 排序到后一个
  541. /// </summary>
  542. void WindowAppUiScene::zorderDownCurrentControl()
  543. {
  544. if (getCurrentControl() == nullptr || getCurrentControl()->getItem() == nullptr)
  545. {
  546. return;
  547. }
  548. qreal zValue = getCurrentControl()->getItem()->zValue();
  549. getCurrentControl()->getItem()->setZValue(zValue - 1);
  550. }
  551. /// <summary>
  552. /// 删除当前控件
  553. /// </summary>
  554. void WindowAppUiScene::deleteCurrentControl()
  555. {
  556. qDebug() << "WindowAppUiScene::deleteCurrentControl";
  557. if (m_pCurrentWidget != nullptr)
  558. {
  559. // 删除控件
  560. widgetDelete(m_pCurrentWidget);
  561. // 释放控件
  562. m_pCurrentWidget->deleteLater();
  563. m_pCurrentWidget = nullptr;
  564. this->m_pCurrentObject = nullptr;
  565. m_pUiFrame->ui.objectController->setObject(nullptr);
  566. }
  567. }
  568. /// <summary>
  569. /// 2022-10-7 删除指定ID的控件(用于在Undo体系中)
  570. /// </summary>
  571. /// <param name="strID"></param>
  572. void WindowAppUiScene::deleteControlByID(const QString& strID)
  573. {
  574. // 首先根据ID号找到这个控件
  575. QWidget* delWidget = nullptr;
  576. for (SelectWidget* w : m_SelectControls)
  577. {
  578. if (w->m_strID == strID)
  579. {
  580. delWidget = w->m_pWidget;
  581. break;
  582. }
  583. }
  584. bool bIsCurrent = false;
  585. if (delWidget != nullptr)
  586. {
  587. if (delWidget == m_pCurrentWidget)
  588. {
  589. bIsCurrent = true;
  590. }
  591. // 删除控件
  592. widgetDelete(delWidget);
  593. // 释放控件
  594. delWidget->deleteLater();
  595. delWidget = nullptr;
  596. // 如果删掉的控件正好是当前控件,那么需要清空一下当前控件的信息
  597. if (bIsCurrent)
  598. {
  599. this->m_pCurrentObject = nullptr;
  600. this->m_pCurrentWidget = nullptr;
  601. m_pUiFrame->ui.objectController->setObject(nullptr);
  602. }
  603. }
  604. }
  605. /// <summary>
  606. /// 序列化支持
  607. /// </summary>
  608. /// <param name="dataStream"></param>
  609. /// <param name="in"></param>
  610. /// <returns></returns>
  611. bool WindowAppUiScene::serialized(QDataStream& dataStream, bool in /*= true*/)
  612. {
  613. // 输入
  614. if (in)
  615. {
  616. // 读入控件总数量
  617. int nControlCount = 0;
  618. dataStream >> nControlCount;
  619. // 读取所有控件信息并且添加对应的控件
  620. for (int i = 0; i < nControlCount; i++)
  621. {
  622. // 坐标
  623. QPoint pt;
  624. dataStream >> pt;
  625. // 尺寸
  626. QSize size;
  627. dataStream >> size;
  628. // 类型
  629. VALUE_TYPE type;
  630. dataStream >> type;
  631. // 2022-10-6,控件ID
  632. QString strID;
  633. dataStream >> strID;
  634. // Property;
  635. CONTROL_PROPERTY property;
  636. dataStream >> property;
  637. // PropertyEx;
  638. int ex = 0;
  639. dataStream >> ex;
  640. // 复杂控件
  641. if (ex != 0)
  642. {
  643. CONTROL_PROPERTY_EX propertyex;
  644. dataStream >> propertyex;
  645. // 生成新的控件
  646. VControlObject* pNewControl = this->newControl(type, pt, strID, size , &property, &propertyex);
  647. // 还原复杂控件中的DataLink关系
  648. g_pUiManager->restoreDataLinks(propertyex, pNewControl);
  649. }
  650. // 简单控件
  651. else
  652. {
  653. // 生成新的控件
  654. VControlObject* pNewControl = this->newControl(type, pt, strID, size, &property, nullptr);
  655. // 还原简单控件中的DataLink关系
  656. g_pUiManager->restoreDataLinks(property, pNewControl);
  657. }
  658. }
  659. }
  660. // 输出
  661. else
  662. {
  663. // 写入窗体名称
  664. dataStream << m_pUiView->m_strPageName;
  665. // 写入控件总数量
  666. dataStream << this->m_SelectControls.size();
  667. // 遍历本页面所有控件
  668. for (SelectWidget* pControl : this->m_SelectControls)
  669. {
  670. // ----- 写入控件基础信息
  671. // 坐标
  672. dataStream << pControl->m_pWidget->pos();
  673. // 尺寸
  674. dataStream << pControl->m_pWidget->size();
  675. // 类型
  676. dataStream << pControl->m_Type;
  677. // 2022-10-6,控件ID
  678. dataStream << pControl->m_strID;
  679. // ----- 存储Property信息
  680. dataStream << *pControl->m_pProperty;
  681. // ----- 存储PropertyEx信息
  682. if (pControl->m_pPropertyEx != nullptr)
  683. {
  684. dataStream << 1;
  685. dataStream << *pControl->m_pPropertyEx;
  686. }
  687. else
  688. {
  689. dataStream << 0;
  690. }
  691. }
  692. }
  693. return true;
  694. }
  695. //=====================================================================
  696. //
  697. // 子控件同步相关
  698. //
  699. //=====================================================================
  700. /// <summary>
  701. /// 当Edit控件内容变更时
  702. /// </summary>
  703. /// <param name="strText"></param>
  704. void WindowAppUiScene::onVEditChanged(const QString& strText)
  705. {
  706. vDebug() << strText;
  707. VLineEdit* pSender = qobject_cast<VLineEdit*>(sender());
  708. // 向Dll中的Tool同步
  709. g_pUiManager->syncToDll(pSender, UI_SYNC_MSG::EDIT_TEXT_CHANGED);
  710. // 向Runtime同步
  711. g_pUiManager->syncToRuntime(pSender->m_pWidget, UI_SYNC_MSG::EDIT_TEXT_CHANGED);
  712. // 2022-9-14 如果属性表显示的是当前控件,才需要更新,否则不需要更新
  713. if (m_pCurrentWidget == pSender)
  714. {
  715. // 2022-2-14增加,还需要向属性表同步
  716. OBJECT_SYNC_PROPERTY syncInfo;
  717. syncInfo.type = OBJECT_SYNC_TYPE::SYNC_TITLE;
  718. syncInfo.value = strText;
  719. m_pUiFrame->ui.objectController->syncToObject(pSender, syncInfo);
  720. }
  721. }
  722. /// <summary>
  723. /// ComboBox变更消息
  724. /// </summary>
  725. /// <param name="nIndex"></param>
  726. void WindowAppUiScene::onVComboChanged(const int nIndex)
  727. {
  728. Q_UNUSED(nIndex);
  729. vDebug() << nIndex;
  730. VComboBox* pSender = qobject_cast<VComboBox*>(sender());
  731. // 向Dll中的Tool同步
  732. g_pUiManager->syncToDll(pSender, UI_SYNC_MSG::COMBO_SEL_CHANGED);
  733. // 向Runtime同步
  734. g_pUiManager->syncToRuntime(pSender->m_pWidget, UI_SYNC_MSG::COMBO_SEL_CHANGED);
  735. }
  736. /// <summary>
  737. /// ListBox变更消息
  738. /// </summary>
  739. /// <param name="nRow"></param>
  740. void WindowAppUiScene::onVListChanged(const int nRow)
  741. {
  742. Q_UNUSED(nRow);
  743. vDebug() << nRow;
  744. VListBox* pSender = qobject_cast<VListBox*>(sender());
  745. // 向Dll中的Tool同步
  746. g_pUiManager->syncToDll(pSender, UI_SYNC_MSG::LIST_SEL_CHANGED);
  747. // 向Runtime同步
  748. g_pUiManager->syncToRuntime(pSender->m_pWidget, UI_SYNC_MSG::LIST_SEL_CHANGED);
  749. }
  750. /// <summary>
  751. /// RadioBox变更消息
  752. /// </summary>
  753. /// <param name="checked"></param>
  754. void WindowAppUiScene::onVRadioChanged(bool checked)
  755. {
  756. Q_UNUSED(checked);
  757. }
  758. /// <summary>
  759. /// CheckBox变更消息
  760. /// </summary>
  761. /// <param name="state"></param>
  762. void WindowAppUiScene::onVCheckChanged(int state)
  763. {
  764. Q_UNUSED(state);
  765. }
  766. /// <summary>
  767. /// 当ValueControl内容变更时
  768. /// </summary>
  769. /// <param name="strText"></param>
  770. void WindowAppUiScene::onValueControlChanged(const QString& strText)
  771. {
  772. // Q_UNUSED(strText);
  773. ValueControl* pSender = qobject_cast<ValueControl*>(sender());
  774. vDebug() << pSender << " - ChangedTo:" << pSender->getText();
  775. // 向Value同步
  776. g_pUiManager->syncToValue(pSender);
  777. // 向Runtime同步
  778. g_pUiManager->syncToRuntime(pSender->m_pWidget, UI_SYNC_MSG::VALUE_CHANGED);
  779. // 2022-9-14 如果属性表显示的是当前控件,才需要更新,否则不需要更新
  780. if (m_pCurrentWidget == pSender)
  781. {
  782. // 2022-9-8 增加,还需要向属性表同步
  783. OBJECT_SYNC_PROPERTY syncInfo;
  784. syncInfo.type = OBJECT_SYNC_TYPE::SYNC_TITLE;
  785. syncInfo.value = strText;
  786. m_pUiFrame->ui.objectController->syncToObject(pSender, syncInfo);
  787. }
  788. }
  789. /// <summary>
  790. /// 当ValueControl内容变更时
  791. /// </summary>
  792. /// <param name="strText"></param>
  793. void WindowAppUiScene::onResultControlChanged(const QString& strText)
  794. {
  795. // Q_UNUSED(strText);
  796. VResult* pSender = qobject_cast<VResult*>(sender());
  797. vDebug() << pSender << " - ChangedTo:" << pSender->getText();
  798. // 向Value同步
  799. //g_pUiManager->syncToValue(pSender);
  800. // 向Runtime同步
  801. g_pUiManager->syncToRuntime(pSender->m_pWidget, UI_SYNC_MSG::VALUE_CHANGED);
  802. // 2022-9-14 如果属性表显示的是当前控件,才需要更新,否则不需要更新
  803. if (m_pCurrentWidget == pSender)
  804. {
  805. // 2022-9-8 增加,还需要向属性表同步
  806. OBJECT_SYNC_PROPERTY syncInfo;
  807. syncInfo.type = OBJECT_SYNC_TYPE::SYNC_TITLE;
  808. syncInfo.value = strText;
  809. m_pUiFrame->ui.objectController->syncToObject(pSender, syncInfo);
  810. }
  811. }
  812. /// <summary>
  813. /// 检查所有的属性和扩展属性是否有效
  814. /// </summary>
  815. /// <returns></returns>
  816. bool WindowAppUiScene::checkAllProperties()
  817. {
  818. for (SelectWidget* sw : m_SelectControls)
  819. {
  820. //// Property 中的数据连接(仅简单控件需要检查)
  821. //if (!ValueControl::isComplexControl(sw->m_Type))
  822. //{
  823. // const CONTROL_PROPERTY* prop = sw->m_pProperty;
  824. // if (prop == nullptr)
  825. // {
  826. // continue;
  827. // }
  828. // // 检查数据连接
  829. // const DataLink& dl = prop->m_DataLink;
  830. // if (dl.bForce && !dl.isValid())
  831. // {
  832. // CRITICAL_MESSAGE("Property datalink[" + dl.title + \
  833. // "] invalid in page[" + this->m_strPageName + "].");
  834. // return false;
  835. // }
  836. //}
  837. // PropertyEx 中的数据链接(仅复杂控件需要检查)
  838. if (ValueControl::isComplexControl(sw->m_Type))
  839. {
  840. // 检查本页面中的属性设置是否正确(数据链接仅检查必填项)
  841. const CONTROL_PROPERTY_EX* px = sw->m_pPropertyEx;
  842. if (px == nullptr)
  843. {
  844. continue;
  845. }
  846. // 检查索引链接
  847. if (px->m_refreshLink.bForce && !px->m_refreshLink.isValid())
  848. {
  849. CRITICAL_MESSAGE("Property refresh datalink[" + px->m_refreshLink.title + \
  850. "] invalid in page[" + this->m_strPageName + "].");
  851. return false;
  852. }
  853. // 检查主数据链接
  854. for (const DataLink& dataLink : px->m_mainDataLinks)
  855. {
  856. if (dataLink.bForce && !dataLink.isValid())
  857. {
  858. CRITICAL_MESSAGE("Property main datalink[" + dataLink.title + \
  859. "] invalid in page[" + this->m_strPageName + "].");
  860. return false;
  861. }
  862. }
  863. // 检查子分组中的数据链接
  864. for (int i = 0; i < px->m_groups.size(); i++)
  865. {
  866. const PROPERTY_EX_SUBGROUPS& subGroups = px->m_groups[i].subGroups;
  867. for (int j = 0; j < subGroups.size(); j++)
  868. {
  869. for (const DataLink& dataLink : subGroups[j].dataLinks)
  870. {
  871. if (dataLink.bForce && !dataLink.isValid())
  872. {
  873. CRITICAL_MESSAGE("Property datalink[" + dataLink.title + \
  874. "] invalid in page[" + this->m_strPageName + "].");
  875. return false;
  876. }
  877. }
  878. }
  879. }
  880. }
  881. }
  882. return true;
  883. }