#include "WindowAppUiScene.h" #include "WindowAppUiFrame.h" #include "UiManager.h" #include "WindowRuntime.h" #include "selectwidget.h" #include "VPControls.h" #include "WindowAppItemRefLine.h" VControlObject* WindowAppUiScene::m_pCurrentObject = nullptr; WindowAppUiScene::WindowAppUiScene(QGraphicsView* parent /*= nullptr*/) : QGraphicsScene(parent) , m_pUiFrame(nullptr) , m_pUiView((WindowAppUiView*)parent) { // For Test //QLineEdit* newButton = new QLineEdit(nullptr); //this->addWidget(newButton); //newButton->resize(130, 20); //newButton->move(100, 100); // 为参考线管理器绑定指针 m_RefLineManager.bindScene(this); // 为等宽线管理器绑定指针 m_IsoLineManager.bindScene(this); } /// /// 清空所有控件焦点 /// void WindowAppUiScene::clearFocus() { //将原有焦点窗体全部设置成无焦点 for (SelectWidget* w : m_SelectControls) { w->setDrawPoint(false); } } /// /// 当控件被按下时 /// /// void WindowAppUiScene::widgetPressed(QWidget* widget) { //清空所有控件的焦点 clearFocus(); // qDebug() << "WindowAppUiScene::widgetPressed"; //设置当前按下的控件选中效果 for (SelectWidget* w : m_SelectControls) { if (w->getWidget() == widget) { // 设置选中效果 w->setDrawPoint(true); m_pCurrentWidget = widget; //设置自动加载该控件的所有属性 // m_pOwner->ui.objectController->setObject(nullptr); m_pUiFrame->ui.objectController->setObject(widget); // 获取控件最新的尺寸和位置信息 OBJECT_SYNC_PROPERTY syncInfo; syncInfo.type = OBJECT_SYNC_TYPE::SYNC_GEOMETRY; syncInfo.value = widget->geometry(); // 更新到属性表中 m_pUiFrame->ui.objectController->syncToObject(widget, syncInfo); // 2022-5-22 设置当前用户选择的控件信息,用于后续绑定需要 m_pCurrentObject = m_pUiFrame->ui.objectController->vobject(); // 2022-10-21,按下时记录控件当前位置,用于比较鼠标抬起后是否移动 m_oldPos = m_pCurrentWidget->pos(); // 2022-10-21,按下时记录控件当前尺寸,用于比较鼠标抬起后是否变更了尺寸 m_oldGeometry = m_pCurrentWidget->geometry(); break; } } } /// /// 当控件释放时 /// /// void WindowAppUiScene::widgetRelease(QWidget* widget) { // 首先进行控件的自动对齐 // this->autoAlignToGrid(widget); // 释放控件时,无论如何都清空所有的参考线 m_RefLineManager.clear(); // 同时清空所有的等宽线 m_IsoLineManager.clear(); //设置自动加载该控件的所有属性 // m_pOwner->ui.objectController->setObject(nullptr); m_pUiFrame->ui.objectController->setObject(widget); // 获取控件最新的尺寸和位置信息 OBJECT_SYNC_PROPERTY syncInfo; syncInfo.type = OBJECT_SYNC_TYPE::SYNC_GEOMETRY; syncInfo.value = widget->geometry(); // 更新到属性表中 m_pUiFrame->ui.objectController->syncToObject(widget, syncInfo); // 2022-10-21,抬起时记录控件当前位置,用于比较鼠标抬起后是否移动 this->checkCurrentControlMove(); // 2022-10-21,抬起时记录控件当前尺寸,用于比较鼠标抬起后是否缩放 this->checkCurrentControlZoom(); } /// /// 当控件删除时 /// /// void WindowAppUiScene::widgetDelete(QWidget* widget) { // 从数据结构中删除关联 g_pUiManager->deleteControl(widget); // 从界面中删除控件 for (int i = 0; i < m_SelectControls.count(); i++) { if (m_SelectControls.at(i)->getWidget() == widget) { // 需要清空SelectWidget自身,否则会造成崩溃问题 m_SelectControls.at(i)->deleteLater(); m_SelectControls.removeAt(i); break; } } // 2021-12-26增加,删除本控件相关的属性表数据结构 m_pUiFrame->ui.objectController->delObject(widget); // 2021-12-28增加,在Runtime中删除控件相关数据结构 g_pRuntime->releaseControl(widget); } /// /// 当控件移动时 /// /// void WindowAppUiScene::widgetMove(QWidget* widget) { // qDebug() << "WindowAppUiScene::widgetMove - " << widget; // 检查控件参考线 this->checkRefLine(widget); } /// /// 2022-9-16,当控件拉伸时(用于绘制等宽线) /// /// /// void WindowAppUiScene::widgetStretch(QWidget* widget, STRETCH_DIRECTION dir) { // qDebug() << "WindowAppUiScene::widgetStretch - " << widget <<" Direction:" << (int)dir; this->checkIsoLine(widget, dir); } /// /// 2022-8-14 控件移动时,处理参考线相关 /// /// void WindowAppUiScene::checkRefLine(QWidget* widget) { // 遍历所有的控件,然后通过RefLineManager处理所有控件之间的参考线 for (SelectWidget* w : m_SelectControls) { // 排除自身 if (widget == w->m_pWidget) { continue; } // 当前选中控件、和UI界面中的其他控件 m_RefLineManager.check(widget, w->m_pWidget); } } /// /// 2022-9-16 控件被拉伸时,进行等宽线相关的实时计算 /// /// void WindowAppUiScene::checkIsoLine(QWidget* widget, STRETCH_DIRECTION dir) { QList dstWidgets; // 遍历所有的控件,选出需要及逆行等宽线判断的其他所有控件 for (SelectWidget* w : m_SelectControls) { // 排除自身 if (widget != w->m_pWidget) { dstWidgets.push_back(w->m_pWidget); } } // 开始处理等宽线相关事宜 m_IsoLineManager.check(widget, dstWidgets, dir); } /// /// 2022-10-22,检查当前控件是否移动 /// void WindowAppUiScene::checkCurrentControlMove() { // 比较鼠标抬起后是否移动 QPoint curPos = m_pCurrentWidget->pos(); // 如果移动了,则记录这次动作,用于执行Redo if (curPos != m_oldPos) { UiControlMoveCommand* controlMoveCommand = new UiControlMoveCommand( this, m_pCurrentObject->m_strID, m_oldPos, curPos ); this->m_CommandManager.executeCommand(controlMoveCommand, true); m_oldPos = curPos; } } /// /// 2022-10-22,检查当前控件是否缩放 /// void WindowAppUiScene::checkCurrentControlZoom() { // 比较鼠标抬起后尺寸是否变化 QRect curGeometry = m_pCurrentWidget->geometry(); // 如果尺寸不同了,则记录这次动作,用于执行Redo if (curGeometry != m_oldGeometry) { UiControlZoomCommand* controlZoomCommand = new UiControlZoomCommand( this, m_pCurrentObject->m_strID, m_oldGeometry, curGeometry ); this->m_CommandManager.executeCommand(controlZoomCommand, true); m_oldGeometry = curGeometry; } } /// /// 将生成的控件选入列表中 /// /// /// /// void WindowAppUiScene::addSelection( VControlObject* pControl, VALUE_TYPE type, CONTROL_PROPERTY* pProperty, CONTROL_PROPERTY_EX* pPropertyEx /* = nullptr */ ) { SelectWidget* select = new SelectWidget(m_pUiView); // 绑定控件选中消息 connect(select, SIGNAL(widgetPressed(QWidget*)), this, SLOT(widgetPressed(QWidget*))); // 绑定控件释放消息 connect(select, SIGNAL(widgetRelease(QWidget*)), this, SLOT(widgetRelease(QWidget*))); // 绑定控件移动消息 connect(select, SIGNAL(widgetMove(QWidget*)), this, SLOT(widgetMove(QWidget*))); // 绑定控件拉伸消息 connect(select, SIGNAL(widgetStretch(QWidget*, STRETCH_DIRECTION)), this, SLOT(widgetStretch(QWidget*, STRETCH_DIRECTION))); //// Delete快捷键的删除消息 //connect(select, SIGNAL(widgetDelete(QWidget*)), this, SLOT(widgetDelete(QWidget*))); select->setWidget(pControl->m_pWidget); select->m_Type = type; // 2022-10-6,控件ID select->m_strID = pControl->m_strID; // 2021-10-5增加,绑定控件属性 select->m_pProperty = pProperty; select->m_pPropertyEx = pPropertyEx; // this->addWidget(pControl->m_pWidget); // 加入选择控件列表中 m_SelectControls.append(select); // 直接选中控件,并且显示对应属性框 widgetPressed(pControl->m_pWidget); } ///// ///// 新建自定义控件 ///// ///// ///// //VControlObject* WindowAppUiScene::newControl( // int row, // const QPoint& newPt, // const QString& controlID, // const QSize& newSize, // CONTROL_PROPERTY* prop, // CONTROL_PROPERTY_EX* propex //) //{ // // 将界面中用户选择的行数转换成对应的valueType // VALUE_TYPE controlType = (VALUE_TYPE)(row + (int)VALUE_TYPE::Control_Base + 1); // // return this->newControl(controlType, newPt, controlID, newSize, prop, propex); //} /// /// 新建自定义控件(按类型) /// /// /// /// /// VControlObject* WindowAppUiScene::newControl( VALUE_TYPE controlType, const QPoint& newPt, const QString& controlID, const QSize& newSize, CONTROL_PROPERTY* prop /*= nullptr*/, CONTROL_PROPERTY_EX* propex /*= nullptr */ ) { VControlObject* pNewControl = nullptr; switch (controlType) { case VALUE_TYPE::Control_Label: { pNewControl = new VLabel(nullptr, newPt, newSize, prop); } break; case VALUE_TYPE::Control_Button: { pNewControl = new VButton(nullptr, newPt, newSize, prop); } break; case VALUE_TYPE::Control_CheckBox: { pNewControl = new VCheckBox(nullptr, newPt, newSize, prop); // 绑定CheckBox变动信号 connect(pNewControl->m_pWidget, SIGNAL(stateChanged(int)), this, SLOT(onVCheckChanged(int))); } break; case VALUE_TYPE::Control_RadioBox: { pNewControl = new VRadioBox(nullptr, newPt, newSize, prop); // 绑定RadioBox变动信号 connect(pNewControl->m_pWidget, SIGNAL(toggled(bool)), this, SLOT(onVRadioChanged(bool))); } break; case VALUE_TYPE::Control_Groupbox: { pNewControl = new VGroupBox(nullptr, newPt, newSize, prop); } break; case VALUE_TYPE::Control_Image: { pNewControl = new VImageControl(nullptr, newPt, newSize, prop, propex); // 2022-9-11 为刷新链接绑定默认值(系统的执行次数) pNewControl->bindDefaultRefreshDataLink(); //pNewControl->m_pWidget = new HWndUnit(nullptr); //pNewControl->m_pWidget->resize(DEFAULT_IMAGE_SIZE); //pNewControl->m_pWidget->move(newPt); } break; case VALUE_TYPE::Control_LineEdit: { pNewControl = new VLineEdit(nullptr, newPt, newSize, prop); //pNewControl->m_pWidget = new QLineEdit(nullptr); //pNewControl->m_pWidget->resize(DEFAULT_EDIT_SIZE); //pNewControl->m_pWidget->move(newPt); // 注册文字变更消息用于同步 connect(pNewControl->m_pWidget, SIGNAL(textChanged(QString)), this, SLOT(onVEditChanged(QString))); } break; case VALUE_TYPE::Control_Listbox: { pNewControl = new VListBox(nullptr, newPt, newSize, prop); // 绑定ListBox变动信号 connect(pNewControl->m_pWidget, SIGNAL(currentRowChanged(int)), this, SLOT(onVListChanged(int))); } break; case VALUE_TYPE::Control_ComboBox: { pNewControl = new VComboBox(nullptr, newPt, newSize, prop); // 绑定ComboBox变动信号 connect(pNewControl->m_pWidget, SIGNAL(currentIndexChanged(int)), this, SLOT(onVComboChanged(int))); } break; case VALUE_TYPE::Control_Value: { pNewControl = new ValueControl(nullptr, newPt, newSize, prop); // 注册文字变更消息用于同步至Value connect(pNewControl->m_pWidget, SIGNAL(textChanged(QString)), this, SLOT(onValueControlChanged(QString))); // 2022-9-11 Value控件需要绑定默认的DataLink pNewControl->bindDefaultDataLink(); } break; case VALUE_TYPE::Control_PieChart: { pNewControl = new VPieChart(nullptr, newPt, newSize, prop, propex); // 2022-9-11 为刷新链接绑定默认值(系统的执行次数) pNewControl->bindDefaultRefreshDataLink(); } break; case VALUE_TYPE::Control_CustomPlot: { pNewControl = new VCustomPlot(nullptr, newPt, newSize, prop, propex); // 2022-9-11 为刷新链接绑定默认值(系统的执行次数) pNewControl->bindDefaultRefreshDataLink(); } break; case VALUE_TYPE::Control_Table: { pNewControl = new VTableControl(nullptr, newPt, newSize, prop, propex); } break; case VALUE_TYPE::Control_Result: { pNewControl = new VResult(nullptr, newPt, newSize, prop); // 注册文字变更消息用于同步至Value connect(pNewControl->m_pWidget, SIGNAL(textChanged(QString)), this, SLOT(onResultControlChanged(QString))); // 2022-9-11 Value控件需要绑定默认的DataLink pNewControl->bindDefaultDataLink(); } break; default: qWarning() << "[UI] WindowAppUiScene::newControl - invalid control type:" << static_cast(controlType); return nullptr; } // 创建失败,应该不会发生 if (pNewControl == nullptr) { qWarning() << "[UI] WindowAppUiScene::newControl - Create control failed, type " << static_cast(controlType); return nullptr; } // 2022-8-10,将控件的位置进行自动对齐 // this->autoAlignToGrid(pNewControl->m_pWidget); // 将控件加入到界面中 // Scene无法添加有父窗体的控件,只能先设置为nulltpr了,如果这里不设置为nullptr,前面建立的时候设置为nullptr的话,带来的问题更多 // pNewControl->m_pWidget->setParent(nullptr); // 保存ProxyWidget指针,方便后续操作控件 pNewControl->m_pProxyWidget = this->addWidget(pNewControl->m_pWidget); // 2022-10-6,如果没有为控件指定ID的话,则为本控件生成新的唯一UUID if (controlID.isEmpty()) { pNewControl->m_strID = QUuid::createUuid().toString(); } // 否则就直接把当前ID赋值 else { pNewControl->m_strID = controlID; } if (pNewControl->isComplexControl()) { // 将控件加入到选中列表中 addSelection( pNewControl, controlType, &pNewControl->m_Property, &pNewControl->m_PropertyEx ); } else { // 将控件加入到选中列表中 addSelection( pNewControl, controlType, &pNewControl->m_Property, nullptr ); } // 2022-10-7,将向UI Manager注册本控件从WindowAppUiView中移到了这里 g_pUiManager->regiterNewControl(pNewControl, this->m_pUiView); // 2022-2-4 返回新控件指针 return pNewControl; } /// /// 获取本界面中的所有控件 /// /// QList WindowAppUiScene::getAllControls() { return this->m_SelectControls; } /// /// 刷新指定控件(用于更新属性表) /// /// void WindowAppUiScene::refreshControl(QWidget* pControl) { // widgetRelease(pControl); // 2022-9-15 只刷新当前控件的属性表,防止Runtime同步到UI时,属性表乱跳的bug if (pControl == m_pCurrentWidget) { m_pUiFrame->ui.objectController->setObject(pControl); } } /// /// 刷新指定控件的选中效果(用于适配属性表更新后的选中效果更新) /// /// void WindowAppUiScene::refreshDrawPoint(QWidget* pControl) { //清空所有控件的焦点 clearFocus(); //设置当前按下的控件有焦点 for (SelectWidget* w : m_SelectControls) { if (w->getWidget() == pControl) { // 需要按照最新的控件形状信息重新设置选中效果 w->setWidget(pControl); // 设置选中效果 w->setDrawPoint(true); m_pCurrentWidget = pControl; break; } } } /// /// 2022-10-21,获取指定ID号的控件SelectWidget /// /// /// SelectWidget* WindowAppUiScene::getSelectWidgetByID(const QString& strID) { for (SelectWidget* w : m_SelectControls) { if (w->m_strID == strID) { return w; } } return nullptr; } /// /// 排序到最前 /// void WindowAppUiScene::zorderTopCurrentControl() { if (getCurrentControl() == nullptr || getCurrentControl()->getItem() == nullptr) { return; } int nSize = getAllControls().size(); getCurrentControl()->getItem()->setZValue(nSize + 1); } /// /// 排序到最底 /// void WindowAppUiScene::zorderBottomCurrentControl() { if (getCurrentControl() == nullptr || getCurrentControl()->getItem() == nullptr) { return; } getCurrentControl()->getItem()->setZValue(0); } /// /// 排序到前一个 /// void WindowAppUiScene::zorderUpCurrentControl() { if (getCurrentControl() == nullptr || getCurrentControl()->getItem() == nullptr) { return; } qreal zValue = getCurrentControl()->getItem()->zValue(); getCurrentControl()->getItem()->setZValue(zValue + 1); } /// /// 排序到后一个 /// void WindowAppUiScene::zorderDownCurrentControl() { if (getCurrentControl() == nullptr || getCurrentControl()->getItem() == nullptr) { return; } qreal zValue = getCurrentControl()->getItem()->zValue(); getCurrentControl()->getItem()->setZValue(zValue - 1); } /// /// 删除当前控件 /// void WindowAppUiScene::deleteCurrentControl() { qDebug() << "WindowAppUiScene::deleteCurrentControl"; if (m_pCurrentWidget != nullptr) { // 删除控件 widgetDelete(m_pCurrentWidget); // 释放控件 m_pCurrentWidget->deleteLater(); m_pCurrentWidget = nullptr; this->m_pCurrentObject = nullptr; m_pUiFrame->ui.objectController->setObject(nullptr); } } /// /// 2022-10-7 删除指定ID的控件(用于在Undo体系中) /// /// void WindowAppUiScene::deleteControlByID(const QString& strID) { // 首先根据ID号找到这个控件 QWidget* delWidget = nullptr; for (SelectWidget* w : m_SelectControls) { if (w->m_strID == strID) { delWidget = w->m_pWidget; break; } } bool bIsCurrent = false; if (delWidget != nullptr) { if (delWidget == m_pCurrentWidget) { bIsCurrent = true; } // 删除控件 widgetDelete(delWidget); // 释放控件 delWidget->deleteLater(); delWidget = nullptr; // 如果删掉的控件正好是当前控件,那么需要清空一下当前控件的信息 if (bIsCurrent) { this->m_pCurrentObject = nullptr; this->m_pCurrentWidget = nullptr; m_pUiFrame->ui.objectController->setObject(nullptr); } } } /// /// 序列化支持 /// /// /// /// bool WindowAppUiScene::serialized(QDataStream& dataStream, bool in /*= true*/) { // 输入 if (in) { // 读入控件总数量 int nControlCount = 0; dataStream >> nControlCount; // 读取所有控件信息并且添加对应的控件 for (int i = 0; i < nControlCount; i++) { // 坐标 QPoint pt; dataStream >> pt; // 尺寸 QSize size; dataStream >> size; // 类型 VALUE_TYPE type; dataStream >> type; // 2022-10-6,控件ID QString strID; dataStream >> strID; // Property; CONTROL_PROPERTY property; dataStream >> property; // PropertyEx; int ex = 0; dataStream >> ex; // 复杂控件 if (ex != 0) { CONTROL_PROPERTY_EX propertyex; dataStream >> propertyex; // 生成新的控件 VControlObject* pNewControl = this->newControl(type, pt, strID, size , &property, &propertyex); // 还原复杂控件中的DataLink关系 g_pUiManager->restoreDataLinks(propertyex, pNewControl); } // 简单控件 else { // 生成新的控件 VControlObject* pNewControl = this->newControl(type, pt, strID, size, &property, nullptr); // 还原简单控件中的DataLink关系 g_pUiManager->restoreDataLinks(property, pNewControl); } } } // 输出 else { // 写入窗体名称 dataStream << m_pUiView->m_strPageName; // 写入控件总数量 dataStream << this->m_SelectControls.size(); // 遍历本页面所有控件 for (SelectWidget* pControl : this->m_SelectControls) { // ----- 写入控件基础信息 // 坐标 dataStream << pControl->m_pWidget->pos(); // 尺寸 dataStream << pControl->m_pWidget->size(); // 类型 dataStream << pControl->m_Type; // 2022-10-6,控件ID dataStream << pControl->m_strID; // ----- 存储Property信息 dataStream << *pControl->m_pProperty; // ----- 存储PropertyEx信息 if (pControl->m_pPropertyEx != nullptr) { dataStream << 1; dataStream << *pControl->m_pPropertyEx; } else { dataStream << 0; } } } return true; } //===================================================================== // // 子控件同步相关 // //===================================================================== /// /// 当Edit控件内容变更时 /// /// void WindowAppUiScene::onVEditChanged(const QString& strText) { vDebug() << strText; VLineEdit* pSender = qobject_cast(sender()); // 向Dll中的Tool同步 g_pUiManager->syncToDll(pSender, UI_SYNC_MSG::EDIT_TEXT_CHANGED); // 向Runtime同步 g_pUiManager->syncToRuntime(pSender->m_pWidget, UI_SYNC_MSG::EDIT_TEXT_CHANGED); // 2022-9-14 如果属性表显示的是当前控件,才需要更新,否则不需要更新 if (m_pCurrentWidget == pSender) { // 2022-2-14增加,还需要向属性表同步 OBJECT_SYNC_PROPERTY syncInfo; syncInfo.type = OBJECT_SYNC_TYPE::SYNC_TITLE; syncInfo.value = strText; m_pUiFrame->ui.objectController->syncToObject(pSender, syncInfo); } } /// /// ComboBox变更消息 /// /// void WindowAppUiScene::onVComboChanged(const int nIndex) { Q_UNUSED(nIndex); vDebug() << nIndex; VComboBox* pSender = qobject_cast(sender()); // 向Dll中的Tool同步 g_pUiManager->syncToDll(pSender, UI_SYNC_MSG::COMBO_SEL_CHANGED); // 向Runtime同步 g_pUiManager->syncToRuntime(pSender->m_pWidget, UI_SYNC_MSG::COMBO_SEL_CHANGED); } /// /// ListBox变更消息 /// /// void WindowAppUiScene::onVListChanged(const int nRow) { Q_UNUSED(nRow); vDebug() << nRow; VListBox* pSender = qobject_cast(sender()); // 向Dll中的Tool同步 g_pUiManager->syncToDll(pSender, UI_SYNC_MSG::LIST_SEL_CHANGED); // 向Runtime同步 g_pUiManager->syncToRuntime(pSender->m_pWidget, UI_SYNC_MSG::LIST_SEL_CHANGED); } /// /// RadioBox变更消息 /// /// void WindowAppUiScene::onVRadioChanged(bool checked) { Q_UNUSED(checked); } /// /// CheckBox变更消息 /// /// void WindowAppUiScene::onVCheckChanged(int state) { Q_UNUSED(state); } /// /// 当ValueControl内容变更时 /// /// void WindowAppUiScene::onValueControlChanged(const QString& strText) { // Q_UNUSED(strText); ValueControl* pSender = qobject_cast(sender()); vDebug() << pSender << " - ChangedTo:" << pSender->getText(); // 向Value同步 g_pUiManager->syncToValue(pSender); // 向Runtime同步 g_pUiManager->syncToRuntime(pSender->m_pWidget, UI_SYNC_MSG::VALUE_CHANGED); // 2022-9-14 如果属性表显示的是当前控件,才需要更新,否则不需要更新 if (m_pCurrentWidget == pSender) { // 2022-9-8 增加,还需要向属性表同步 OBJECT_SYNC_PROPERTY syncInfo; syncInfo.type = OBJECT_SYNC_TYPE::SYNC_TITLE; syncInfo.value = strText; m_pUiFrame->ui.objectController->syncToObject(pSender, syncInfo); } } /// /// 当ValueControl内容变更时 /// /// void WindowAppUiScene::onResultControlChanged(const QString& strText) { // Q_UNUSED(strText); VResult* pSender = qobject_cast(sender()); vDebug() << pSender << " - ChangedTo:" << pSender->getText(); // 向Value同步 //g_pUiManager->syncToValue(pSender); // 向Runtime同步 g_pUiManager->syncToRuntime(pSender->m_pWidget, UI_SYNC_MSG::VALUE_CHANGED); // 2022-9-14 如果属性表显示的是当前控件,才需要更新,否则不需要更新 if (m_pCurrentWidget == pSender) { // 2022-9-8 增加,还需要向属性表同步 OBJECT_SYNC_PROPERTY syncInfo; syncInfo.type = OBJECT_SYNC_TYPE::SYNC_TITLE; syncInfo.value = strText; m_pUiFrame->ui.objectController->syncToObject(pSender, syncInfo); } } /// /// 检查所有的属性和扩展属性是否有效 /// /// bool WindowAppUiScene::checkAllProperties() { for (SelectWidget* sw : m_SelectControls) { //// Property 中的数据连接(仅简单控件需要检查) //if (!ValueControl::isComplexControl(sw->m_Type)) //{ // const CONTROL_PROPERTY* prop = sw->m_pProperty; // if (prop == nullptr) // { // continue; // } // // 检查数据连接 // const DataLink& dl = prop->m_DataLink; // if (dl.bForce && !dl.isValid()) // { // CRITICAL_MESSAGE("Property datalink[" + dl.title + \ // "] invalid in page[" + this->m_strPageName + "]."); // return false; // } //} // PropertyEx 中的数据链接(仅复杂控件需要检查) if (ValueControl::isComplexControl(sw->m_Type)) { // 检查本页面中的属性设置是否正确(数据链接仅检查必填项) const CONTROL_PROPERTY_EX* px = sw->m_pPropertyEx; if (px == nullptr) { continue; } // 检查索引链接 if (px->m_refreshLink.bForce && !px->m_refreshLink.isValid()) { CRITICAL_MESSAGE("Property refresh datalink[" + px->m_refreshLink.title + \ "] invalid in page[" + this->m_strPageName + "]."); return false; } // 检查主数据链接 for (const DataLink& dataLink : px->m_mainDataLinks) { if (dataLink.bForce && !dataLink.isValid()) { CRITICAL_MESSAGE("Property main datalink[" + dataLink.title + \ "] invalid in page[" + this->m_strPageName + "]."); return false; } } // 检查子分组中的数据链接 for (int i = 0; i < px->m_groups.size(); i++) { const PROPERTY_EX_SUBGROUPS& subGroups = px->m_groups[i].subGroups; for (int j = 0; j < subGroups.size(); j++) { for (const DataLink& dataLink : subGroups[j].dataLinks) { if (dataLink.bForce && !dataLink.isValid()) { CRITICAL_MESSAGE("Property datalink[" + dataLink.title + \ "] invalid in page[" + this->m_strPageName + "]."); return false; } } } } } } return true; }