#include "UiManager.h"
#include "WindowRuntime.h"
#include "PouManager.h"
#include "GvlManager.h"
#include "WindowAppUiScene.h"
#include "VPControls.h"
// 字符串之间的间隔,用于Tip 与 Text 之间的组装
#define STRING_INTERVAL ": "
UiManager::UiManager()
{
m_pMainPage = nullptr;
}
///
/// 注册新的UIView
///
///
void UiManager::registerNewUi(WindowAppUiView* pView)
{
QString strName = pView->m_strPageName;
if (m_pAllPages.contains(strName))
{
m_pAllPages[strName] = pView;
return;
}
m_pAllPages.insert(strName, pView);
}
///
/// 删除指定页面(此处需要检查是否删除的是主页)
///
///
bool UiManager::deleteUi(const QString& strName, bool bForce)
{
// 如果删除的页面是主页,则提示是否确认删除,并且需要指定新的主页
if (m_pMainPage!=nullptr
&& strName == m_pMainPage->m_strPageName)
{
// 是否不弹提示强制删除
if (!bForce)
{
QMessageBox::StandardButton ret = Utility::VPQuesitonMessageBox("确定要删除主页[" + strName + "吗? 你需要指定新的主页后,才可以执行发布操作.");
if (ret != QMessageBox::Yes)
{
return false;
}
}
m_pMainPage = nullptr;
}
// 数据结构中删除
m_pAllPages.remove(strName);
qDebug() << "[UiManager] Delete UI " << strName << ".";
return true;
}
///
/// 注册新的控件
///
///
///
void UiManager::regiterNewControl(VControlObject* pNewControl, WindowAppUiView* pView)
{
m_AllControls.insert(pNewControl->m_pWidget, pView);
qDebug() << "[UiManager] UiManager::regiterNewControl - " << pNewControl << " in " << pView->m_strPageName;
}
///
/// 删除一个控件
///
///
void UiManager::deleteControl(QWidget* pDelControl)
{
m_AllControls.remove(pDelControl);
// 删除本UI控件和其他的关联关系
m_UiToDllControls.remove(pDelControl);
m_UiToRtControls.remove(pDelControl);
m_UiControlToValues.remove(pDelControl);
QHash::iterator it = m_DllToUiControls.begin();
for (; it != m_DllToUiControls.end();)
{
if (it.value() == pDelControl)
{
m_DllToUiControls.erase(it);
break;
}
else
{
it++;
}
}
QHash::iterator it2 = m_RtToUiControls.begin();
for (; it2 != m_RtToUiControls.end();)
{
if (it2.value() == pDelControl)
{
m_RtToUiControls.erase(it2);
break;
}
else
{
it2++;
}
}
QHashIterator it3(m_ValueToUiControls);
while (it3.hasNext())
{
QList pWidgets = m_ValueToUiControls.values(it3.next().key());
for (QWidget* pWidget : pWidgets)
{
if (pWidget == pDelControl)
{
// 2021-11-9 取消DataLink标识
it3.key()->bDataLink = false;
// 减小引用计数
if (it3.key()->nRefCount > 0)
{
it3.key()->nRefCount--;
}
m_ValueToUiControls.remove(it3.key(), pDelControl);
break;
}
}
}
}
///
/// 获取所有的Ui名称
///
///
QStringList UiManager::getAllUiNames()
{
// return this->m_UiNames;
QStringList listNames;
QMapIterator it(m_pAllPages);
while (it.hasNext())
{
listNames.push_back(it.next().key());
}
return listNames;
}
///
/// 获取指定名字的页面
///
///
///
WindowAppUiView* UiManager::getPageByName(const QString& strName)
{
if (m_pAllPages.contains(strName))
{
return m_pAllPages[strName];
}
else
{
return nullptr;
}
}
///
/// 检查各个页面中携带的属性是否正确有效
///
///
bool UiManager::checkAll()
{
QMapIterator it(m_pAllPages);
while (it.hasNext())
{
// 依次检测每一个UI页面的属性设置
bool bRet = it.next().value()->uiScene()->checkAllProperties();
if (!bRet)
{
return false;
}
}
return true;
}
///
/// 发布所有页面到Runtime执行(所有的关于主页的检查都放到这里来执行)
///
bool UiManager::publishAll()
{
// 首先检查是否设定了主页
if (m_pMainPage == nullptr)
{
CRITICAL_MESSAGE("Error: 请先设置主页面");
return false;
}
// 检查各个页面中携带的属性是否正确有效(仅检查必填项)
bool bRet = checkAll();
if (!bRet)
{
return false;
}
// 然后将主页和所有页面都传输到Runtime发布
return g_pRuntime->publishAllPages(m_pMainPage, m_pAllPages);
}
///
/// 设定主页
///
///
bool UiManager::setMainPage(const QString& strName)
{
if (m_pAllPages.contains(strName))
{
m_pMainPage = m_pAllPages[strName];
qDebug() << "[UiManager] Set " << strName << " as MainPage.";
return true;
}
else
{
qWarning() << "[UiManager] Set " << strName << " as MainPage failed.";
return false;
}
}
///
/// 获取主页
///
///
WindowAppUiView* UiManager::getMainPage()
{
return this->m_pMainPage;
}
///
/// 序列化所有的WindowAppUiView*
///
///
///
bool UiManager::serialized(QDataStream& out)
{
// 首先写入UI的总数量
out << m_pAllPages.size();
// 首先写入主页
out << m_pMainPage;
// 遍历所有的UIView,执行序列化
QMapIterator it(m_pAllPages);
while (it.hasNext())
{
it.next();
// 跳过主页
if (it.value() != m_pMainPage)
{
out << it.value();
}
}
return true;
}
//=====================================================================
//
// 同步相关代码
//
//=====================================================================
///
/// 接收来自其他控件和变量的同步Event
///
///
///
void UiManager::customEvent(QEvent* event)
{
// qDebug() << "UiManager::event " << event->type();
// 如果是控件同步消息
if (event->type() == CONTROL_EVENT_TYPEID)
{
qDebug() << "UiManager::event - CONTROL_EVENT";
SyncControlEvent* pValueEvent = dynamic_cast (event);
// 取出参数执行同步
syncFromDll(
pValueEvent->m_pSrcControl,
pValueEvent->m_SyncMsg
);
}
// 如果是数值同步消息
else if (event->type() == VALUE_EVENT_TYPEID)
{
vDebug() << "VALUE_EVENT";
SyncValueEvent* pValueEvent = dynamic_cast (event);
// 取出参数
QList syncValues = pValueEvent->getSyncValues();
for (VARIABLE* syncVal : syncValues)
{
this->syncFromValue(syncVal);
}
}
// 如果是硬件数值同步消息
else if (event->type() == HDVALUE_EVENT_TYPEID)
{
qDebug() << "UiManager::event - HDVALUE_EVENT";
SyncHdValueEvent* pValueEvent = dynamic_cast (event);
// 如果当前组不是硬件组态,不继续执行后续代码 ,为了解决硬件工具放在 POU 中时候,主动触发了ui刷新
if (pValueEvent != nullptr && pValueEvent->groupName() != CATEGORY_TOOL_HARDWARE)
{
return;
}
// 首先需要去Pou中取出此接口
POU* pHdPou = g_pPouManager->getHdwPou();
_INTERFACE* pInf = nullptr;
// 第一种方式
if (!pValueEvent->m_strInstanceName.isEmpty() && !pValueEvent->m_strInfName.isEmpty())
{
QString infFullName = pValueEvent->m_strInstanceName + "." + pValueEvent->m_strInfName;
pInf = pHdPou->GetInterface(infFullName);
}
// 第二种方式
else if(pValueEvent->m_pSrcValue!=nullptr)
{
pInf = pHdPou->GetInterfaceByValuePtr(pValueEvent->m_pSrcValue);
}
else
{
qDebug() << "[Error] UiManager::customEvent - but SyncHdValueEvent invalid.";
}
// 如果接口成功取到,则执行同步
if (pInf != nullptr)
{
// 执行同步
this->syncFromValue(pInf);
}
else
{
qWarning() << "UiManager::customEvent - Can't find update interface, may be not a hardward interface.";
}
}
//return QObject::event(event);
}
///
/// 绑定dll中的控件与UI控件
///
///
///
void UiManager::bindDllControlWithUiControl(QWidget* pDllControl, VControlObject* pUiControl)
{
m_DllToUiControls.insert(pDllControl, pUiControl->m_pWidget);
m_UiToDllControls.insert(pUiControl->m_pWidget, pDllControl);
// 刚绑定时,从dll向UI做一次同步
this->syncFromDllFirst(pDllControl, pUiControl);
}
///
/// 2022-9-13,解除dll中的控件与UI控件的绑定
///
///
///
void UiManager::unbindDllControlWithUiControl(QWidget* pDllControl, VControlObject* pUiControl)
{
m_DllToUiControls.remove(pDllControl);
m_UiToDllControls.remove(pUiControl->m_pWidget);
}
///
/// 绑定UI控件与Runtime控件用于同步
///
///
///
void UiManager::bindUiControlWithRtControl(QWidget* pUiControl, QWidget* pRtControl)
{
m_UiToRtControls.insert(pUiControl, pRtControl);
m_RtToUiControls.insert(pRtControl, pUiControl);
}
///
/// 2022-9-13,解除UI控件与Runtime控件的绑定
///
///
///
void UiManager::unbindUiControlWithRtControl(QWidget* pUiControl, QWidget* pRtControl)
{
m_UiToRtControls.remove(pUiControl);
m_RtToUiControls.remove(pRtControl);
}
///
/// 绑定数值变量与UI控件用于同步
///
///
///
void UiManager::bindValueWithUiControl(VARIABLE* val, QWidget* pUiControl)
{
//LINK_VALUE lv;
//lv.direction = dir;
//lv.value = value;
m_ValueToUiControls.insertMulti(val, pUiControl);
m_UiControlToValues.insert(pUiControl, val);
//// For Debug
//foreach(const auto & key, m_ValueToUiControls.keys())
//{
// qDebug() << "bindValueWithUiControl: " << key->strFullName << " - " << m_ValueToUiControls.value(key);
//}
// 刚绑定时,从Value向UI做一次同步
this->syncFromValue(val);
}
///
/// 2022-9-13,解绑数值变量与UI控件(在控件变更了主索引绑定变量时,需要做解绑动作)
///
///
///
void UiManager::unbindValueWithUiControl(VARIABLE* val, QWidget* pUiControl)
{
m_UiControlToValues.remove(pUiControl);
QMutableHashIterator iter(m_ValueToUiControls);
while (iter.hasNext())
{
if (iter.next().key() == val)
{
QList pWidgets = m_ValueToUiControls.values(iter.key());
for (QWidget* pWidget : pWidgets)
{
if (pWidget == pUiControl)
{
m_ValueToUiControls.remove(iter.key(), pUiControl);
return;
}
}
}
}
}
///
/// 绑定DataLink中的信息用于后续同步(仅 UI->Dll)
///
bool UiManager::bindDataLinkSyncInformation(const DataLink& dataLink, VControlObject* pVControl)
{
// 2022-2-9 ,解决绑定Button相关数据连接中出现的bug(也不清楚是怎么出现的,先暂时这么处理一下看起来好像没问题)
if (pVControl->m_Type == VALUE_TYPE::Control_Button)
{
pVControl->m_Property.m_DataLink = dataLink;
return true;
}
POU* pPou = nullptr;
TOOL* pTool = nullptr;
_INTERFACE* pInf = nullptr;
// 解析出Tool信息
this->parsePouToolFromDataLink(dataLink, pPou, pTool, pInf);
if (pInf == nullptr)
{
vDebug() << "[Error] Abandon bind Datalink, Reason: Parse datalink failed.";
return false;
}
// 如果是控件类型
if (pInf->Type == INF_TYPE::INF_TYPE_CONTROL)
{
return this->bindSyncByControl(pTool, pInf, pVControl);
}
// 数值类型或者普通数据类型的接口类型
else if (pInf->Type == INF_TYPE::INF_TYPE_VALUE
|| pInf->Type == INF_TYPE::INF_TYPE_STANDARD
)
{
// 如果是普通类型控件
if (!pVControl->isComplexControl())
{
this->bindSyncByValue(pTool, pInf, pVControl);
}
// 2021-12-7 复杂类型控件
else
{
// 2022-2-10 绑定dll中的信息用于后续同步(复杂类型,暂未绑定,仅引用计数 + 1)
// 由于不需要执行三方同步,此处不需要绑定
this->bindSyncByComplex(pTool, pInf);
}
}
// 未处理类型
else
{
qWarning() << "DialogDataLink::bindSyncFromDll - Unsupported interface category : " << (int)pInf->Type;
}
return true;
}
///
/// 2022-9-13,解绑DataLine信息(在控件变更了主索引绑定变量时,需要做解绑动作)
///
///
///
bool UiManager::unbindDataLinkSyncInformation(const DataLink& dataLink, VControlObject* pVControl)
{
if (pVControl->m_Type == VALUE_TYPE::Control_Button)
{
pVControl->m_Property.m_DataLink = dataLink;
return true;
}
POU* pPou = nullptr;
TOOL* pTool = nullptr;
_INTERFACE* pDllInf = nullptr;
// 解析出Tool信息
this->parsePouToolFromDataLink(dataLink, pPou, pTool, pDllInf);
if (pDllInf == nullptr)
{
return false;
}
// 如果是控件类型
if (pDllInf->Type == INF_TYPE::INF_TYPE_CONTROL)
{
return this->unbindSyncByControl(pTool, pDllInf, pVControl);
}
// 数值类型或者普通数据类型的接口类型
else if (pDllInf->Type == INF_TYPE::INF_TYPE_VALUE
|| pDllInf->Type == INF_TYPE::INF_TYPE_STANDARD
)
{
// 如果是普通类型控件
if (!pVControl->isComplexControl())
{
this->unbindSyncByValue(pTool, pDllInf, pVControl);
}
// 2021-12-7 复杂类型控件
else
{
this->unbindSyncByComplex(pTool, pDllInf);
}
}
// 未处理类型
else
{
vDebug() << "Unsupported interface category : " << (int)pDllInf->Type;
}
return true;
}
///
/// 绑定dll中的信息用于后续同步(控件类型)
///
///
bool UiManager::bindSyncByControl(TOOL* pTool, _INTERFACE* pDllInf, VControlObject* pVControl)
{
// 因为dll->UI只能是一对一,所以此处需要判断一下引用计数
if (pDllInf->nRefCount > 0)
{
vDebug() << ("Error: Interface[" + pDllInf->strNameWithType + "] ref count >0 : " + pDllInf->nRefCount + ".");
return false;
}
// 引用计数 + 1
pDllInf->nRefCount++;
// TODO:回调函数方式已经废弃(只是暂时留着备用)
// dll->UI同步:给dll设置UI同步回调函数
CONTROL_CALLBACK callBack = std::bind(
&UiManager::syncFromDll,
g_pUiManager,
std::placeholders::_1,
std::placeholders::_2
);
pTool->pDllPtr->setControlCallback(callBack);
// 设置同步event的target(这个为目前统一使用的方式,回调函数的方式已经废弃了)
pTool->pDllPtr->setSyncTarget(g_pUiManager);
// UI->Dll同步:信息存储至UiManager统一处理
QWidget* pDllControl = (QWidget*)pTool->pDllPtr->Interface(pDllInf->nIndex).value.Ptr;
g_pUiManager->bindDllControlWithUiControl(pDllControl, pVControl);
return true;
}
///
/// 2022-9-13 解绑dll中的控件信息
///
///
///
///
///
bool UiManager::unbindSyncByControl(TOOL* pTool, _INTERFACE* pDllInf, VControlObject* pVControl)
{
if (pDllInf->nRefCount > 0)
{
vDebug() << ("Error: Interface[" + pDllInf->strNameWithType + "] ref count >0 : " + pDllInf->nRefCount + ".");
return false;
}
// 引用计数 - 1
pDllInf->nRefCount--;
// 解绑UI->Dll的同步信息
QWidget* pDllControl = (QWidget*)pTool->pDllPtr->Interface(pDllInf->nIndex).value.Ptr;
g_pUiManager->unbindDllControlWithUiControl(pDllControl, pVControl);
return true;
}
///
/// 绑定接口信息用于后续同步(有可能是Dll接口,有可能是数值类型,数值可对应多个UI控件)
///
///
///
///
bool UiManager::bindSyncByValue(TOOL* pTool, _INTERFACE* pInf, VControlObject* pVControl)
{
// 输出接口 - Text控件,一对多,输入接口 - Text控件,一对一
// 如果是输入接口,要检查引用计数
if (pInf->Direction == INF_DIRECTION::INF_DIR_IN
&& pInf->nRefCount > 0)
{
vDebug() << ("Error: Interface[" + pInf->strNameWithType + "] ref count >0 : " + pInf->nRefCount + ".");
return false;
}
// 引用计数 + 1
pInf->nRefCount++;
// Value->UI同步,给Tool设置同步事件接收对象
// 如果是Tool中的Value接口,需要绑定变更的回调函数(针对dll中的变量接口)
if (pTool->pDllPtr != nullptr)
{
pTool->pDllPtr->setSyncTarget(g_pUiManager);
// UI->Value单向同步:信息存储至UiManager统一处理
// VALUE& value = pTool->pDllPtr->Interface(pDllInf->nIndex).value;
// g_pUiManager->bindValueWithUiControl(pDllInf, m_pControlObject->m_pWidget);
}
else
{
// TODO: 此处缺一个设置event target的位置(针对局部变量和全局变量)
// VALUE& value = pDllInf->value;
}
pInf->bDataLink = true;
g_pUiManager->bindValueWithUiControl(pInf, pVControl->m_pWidget);
vDebug() << "Bind [" << pInf->strFullName << "] " << " - " << pVControl->m_pWidget;
return true;
}
///
/// 解绑数值接口的绑定信息(有可能是Dll接口,有可能是数值类型,数值可对应多个UI控件)
///
///
///
///
///
bool UiManager::unbindSyncByValue(TOOL* pTool, _INTERFACE* pInf, VControlObject* pVControl)
{
Q_UNUSED(pTool);
// 引用计数 - 1
pInf->nRefCount--;
pInf->bDataLink = false;
g_pUiManager->unbindValueWithUiControl(pInf, pVControl->m_pWidget);
vDebug() << "Unbind [" << pInf->strFullName << "] - " << pVControl->m_pWidget;
return true;
}
///
/// 绑定dll中的信息用于后续同步(复杂类型,暂未绑定,仅引用计数 + 1)
///
///
///
///
bool UiManager::bindSyncByComplex(TOOL* pTool, _INTERFACE* pDllInf)
{
Q_UNUSED(pTool);
if (pDllInf->Direction == INF_DIRECTION::INF_DIR_IN
&& pDllInf->nRefCount > 0)
{
vDebug() << ("Error: Interface[" + pDllInf->strNameWithType + "] ref count >0 : " + pDllInf->nRefCount + ".");
return false;
}
// 引用计数 + 1
pDllInf->nRefCount++;
return true;
}
///
/// 2022-9-13 解绑dll中的信息(复杂类型,暂未绑定,仅引用计数 - 1)
///
///
///
///
bool UiManager::unbindSyncByComplex(TOOL* pTool, _INTERFACE* pDllInf)
{
Q_UNUSED(pTool);
if (pDllInf->Direction == INF_DIRECTION::INF_DIR_IN
&& pDllInf->nRefCount > 0)
{
vDebug() << ("Error: Interface[" + pDllInf->strNameWithType + "] ref count >0 : " + pDllInf->nRefCount + ".");
return false;
}
// 引用计数 - 1
pDllInf->nRefCount--;
return true;
}
///
/// 还原反序列化中控件的DataLink关系(简单控件)
///
///
///
bool UiManager::restoreDataLinks(const CONTROL_PROPERTY& prop, VControlObject* pUiControl)
{
if (prop.m_DataLink.isValid())
{
this->bindDataLinkSyncInformation(prop.m_DataLink, pUiControl);
}
return true;
}
///
/// 还原反序列化中控件的DataLink关系(复杂控件)
///
///
///
bool UiManager::restoreDataLinks(const CONTROL_PROPERTY_EX& propex, VControlObject* pUiControl)
{
bool bRet = true;
// 索引链接
this->bindDataLinkSyncInformation(propex.m_refreshLink, pUiControl);
// 主数据链接
for (const DataLink& dataLink : propex.m_mainDataLinks)
{
if (dataLink.isValid())
{
this->bindDataLinkSyncInformation(dataLink, pUiControl);
}
else
{
qDebug() << ("[Error] UiManager::restoreDataLinks - Property datalink[" + dataLink.title + "] invalid.");
bRet = false;
}
}
// 子分组中的数据链接
for (int i = 0; i < propex.m_groups.size(); i++)
{
const PROPERTY_EX_SUBGROUPS& subGroups = propex.m_groups[i].subGroups;
for (int j = 0; j < subGroups.size(); j++)
{
for (const DataLink& dataLink : subGroups[j].dataLinks)
{
if (dataLink.isValid())
{
this->bindDataLinkSyncInformation(dataLink, pUiControl);
}
else
{
qDebug() << ("[Error] UiManager::restoreDataLinks - Property datalink[" + dataLink.title + "] invalid.");
bRet = false;
}
}
}
}
return bRet;
}
///
/// 用于Dll中的控件事件触发回调(dll中的控件向UI界面同步)
///
///
///
void UiManager::syncFromDll(QWidget* pDllControl, UI_SYNC_MSG msg)
{
if (pDllControl == nullptr)
{
qWarning() << "[Error] UiManager::syncFromDll - pDllControl is nullptr.";
return;
}
// 根据不同的消息执行不同的处理
if (m_DllToUiControls.contains(pDllControl))
{
QWidget* pUiWidget = m_DllToUiControls.value(pDllControl);
bool bRet = false;
switch (msg)
{
case UI_SYNC_MSG::EDIT_TEXT_CHANGED:
{
QLineEdit* pDllEdit = qobject_cast(pDllControl);
VLineEdit* pVEdit = qobject_cast(pUiWidget);
bRet = syncEditControl(pDllEdit, pVEdit, SYNC_MODE::FROM_DLL);
if (bRet)
{
qDebug() << "UiManager::syncFromDll - VLineEdit:" << pVEdit->text();
}
}
break;
case UI_SYNC_MSG::COMBO_SEL_CHANGED:
{
QComboBox* pDllCombo = qobject_cast(pDllControl);
VComboBox* pVCombo = qobject_cast(pUiWidget);
bRet = syncComboControl(pDllCombo, pVCombo, SYNC_MODE::FROM_DLL);
if (bRet)
{
qDebug() << "UiManager::syncFromDll - VComboBox:" << pVCombo->currentIndex();
}
}
break;
case UI_SYNC_MSG::LIST_SEL_CHANGED:
{
QListWidget* pDllList = qobject_cast(pDllControl);
VListBox* pVList = qobject_cast(pUiWidget);
bRet = syncListControl(pDllList, pVList, SYNC_MODE::FROM_DLL);
qDebug() << "UiManager::syncFromDll - VListBox:" << pDllList->currentRow();
}
break;
case UI_SYNC_MSG::RADIOBOX_CHANGED:
{
QRadioButton* pDllRadio= qobject_cast(pDllControl);
VRadioBox* pVRadio = qobject_cast(pUiWidget);
//// 首次同步需要把名字也复制一下
//if (bFirst)
//{
// pVRadio->setText(pDllRadio->text());
//}
pVRadio->setChecked(pDllRadio->isChecked());
qDebug() << "UiManager::syncFromDll - VRadioBox:" << pDllRadio->isChecked();
}
break;
case UI_SYNC_MSG::CHECKBOX_CHANGED:
{
QCheckBox* pDllCheck = qobject_cast(pDllControl);
VCheckBox* pVCheck = qobject_cast(pUiWidget);
//// 首次同步需要把名字也复制一下
//if (bFirst)
//{
// pVCheck->setText(pDllCheck->text());
//}
pVCheck->setCheckState(pDllCheck->checkState());
qDebug() << "UiManager::syncFromDll - VCheckBox:" << pDllCheck->checkState();
}
break;
default:
{
qWarning() << "UiManager::syncFromDll - Unknown sync message : " << (int)msg;
}
break;
}
// 同步完后,通知UI界面刷新此控件(同时更新属性表)
if (m_AllControls.contains(pUiWidget))
{
m_AllControls.value(pUiWidget)->uiScene()->refreshControl(pUiWidget);
}
}
}
///
/// 用于UI界面向Dll中的控件同步
///
///
///
void UiManager::syncToDll(QWidget* pUiControl, UI_SYNC_MSG msg)
{
// 根据不同的消息执行不同的处理
if (m_UiToDllControls.contains(pUiControl))
{
bool bRet = false;
switch (msg)
{
case UI_SYNC_MSG::EDIT_TEXT_CHANGED:
{
VLineEdit* pVEdit = qobject_cast(pUiControl);
QLineEdit* pDllEdit = qobject_cast(m_UiToDllControls.value(pUiControl));
// pDllEdit->setText(pVEdit->text());
bRet = syncEditControl(pVEdit, pDllEdit, SYNC_MODE::TO_DLL);
if (bRet)
{
qDebug() << "UiManager::syncToDll - QLineEdit:" << pVEdit->text();
}
}
break;
case UI_SYNC_MSG::COMBO_SEL_CHANGED:
{
VComboBox* pUi = qobject_cast(pUiControl);
QComboBox* pDll = qobject_cast(m_UiToDllControls.value(pUiControl));
bRet = syncComboControl(pUi, pDll, SYNC_MODE::TO_DLL);
if (bRet)
{
qDebug() << "UiManager::syncToDll - QComboBox:" << pDll->currentIndex();
}
}
break;
case UI_SYNC_MSG::LIST_SEL_CHANGED:
{
VListBox* pUi = qobject_cast(pUiControl);
QListWidget* pDll = qobject_cast(m_UiToDllControls.value(pUiControl));
bRet = syncListControl(pUi, pDll, SYNC_MODE::TO_DLL);
if (bRet)
{
qDebug() << "UiManager::syncToDll - QListWidget:" << pDll->currentRow();
}
}
break;
case UI_SYNC_MSG::RADIOBOX_CHANGED:
break;
case UI_SYNC_MSG::CHECKBOX_CHANGED:
break;
default:
{
qWarning() << "UiManager::syncToDll - Unknown sync message : " << (int)msg;
}
break;
}
}
else
{
//qWarning() << "UiManager::syncToDll - Error : Can't find this control - " << pControl->getText();
}
}
///
/// 刚绑定时,从dll向UI做一次同步
///
///
void UiManager::syncFromDllFirst(QWidget* pDllControl, VControlObject* pUiControl)
{
// 根据同步控件的类型执行不同的同步动作
VALUE_TYPE controlType = pUiControl->m_Type;
// 逐步增加如下需要同步的类型
switch (controlType)
{
case VALUE_TYPE::Control_LineEdit:
{
QLineEdit* pDllEdit = qobject_cast(pDllControl);
VLineEdit* pVEdit = qobject_cast(pUiControl->m_pWidget);
bool bRet = syncEditControl(pDllEdit, pVEdit, SYNC_MODE::FROM_DLL, true);
if (bRet)
{
qDebug() << "UiManager::syncFromDllFirst - VLineEdit:" << pVEdit->text();
}
}
//this->syncFromDll(pDllControl, UI_SYNC_MSG::EDIT_TEXT_CHANGED, true);
break;
case VALUE_TYPE::Control_ComboBox:
{
QComboBox* pDll= qobject_cast(pDllControl);
VComboBox* pUi = qobject_cast(pUiControl->m_pWidget);
bool bRet = syncComboControl(pDll, pUi, SYNC_MODE::FROM_DLL, true);
if (bRet)
{
qDebug() << "UiManager::syncFromDllFirst - VComboBox:" << pUi->currentIndex();
}
}
//this->syncFromDll(pDllControl, UI_SYNC_MSG::COMBO_SEL_CHANGED, true);
break;
case VALUE_TYPE::Control_RadioBox:
{
}
//this->syncFromDll(pDllControl, UI_SYNC_MSG::RADIOBOX_CHANGED, true);
break;
case VALUE_TYPE::Control_CheckBox:
{
}
//this->syncFromDll(pDllControl, UI_SYNC_MSG::CHECKBOX_CHANGED, true);
break;
case VALUE_TYPE::Control_Listbox:
{
QListWidget* pDll = qobject_cast(pDllControl);
VListBox* pUi = qobject_cast(pUiControl->m_pWidget);
bool bRet = syncListControl(pDll, pUi, SYNC_MODE::FROM_DLL, true);
if (bRet)
{
qDebug() << "UiManager::syncFromDllFirst - VListBox:" << pUi->currentIndex();
}
}
//this->syncFromDll(pDllControl, UI_SYNC_MSG::LIST_SEL_CHANGED, true);
break;
default:
break;
}
}
///
/// 用于Runtime界面向UI中的控件同步
///
///
///
void UiManager::syncFromRuntime(QWidget* pRtControl, UI_SYNC_MSG msg)
{
if (m_RtToUiControls.contains(pRtControl))
{
QWidget* pUiWidget = m_RtToUiControls.value(pRtControl);
bool bRet = false;
switch (msg)
{
case UI_SYNC_MSG::EDIT_TEXT_CHANGED:
{
QLineEdit* pRtEdit = qobject_cast(pRtControl);
QLineEdit* pUiEdit = qobject_cast(pUiWidget);
bRet = syncEditControl(pRtEdit, pUiEdit, SYNC_MODE::FROM_RUNTIME, false);
if (bRet)
{
qDebug() << "UiManager::syncFromRuntime - QLineEdit:" << pRtEdit->text();
}
}
break;
case UI_SYNC_MSG::COMBO_SEL_CHANGED:
{
QComboBox* pRt= qobject_cast(pRtControl);
QComboBox* pUi = qobject_cast(pUiWidget);
bRet = syncComboControl(pRt, pUi, SYNC_MODE::FROM_RUNTIME, false);
if (bRet)
{
qDebug() << "UiManager::syncFromRuntime - QComboBox:" << pUi->currentIndex();
}
}
break;
case UI_SYNC_MSG::LIST_SEL_CHANGED:
{
QListWidget* pRt = qobject_cast(pRtControl);
QListWidget* pUi = qobject_cast(pUiWidget);
bRet = syncListControl(pRt, pUi, SYNC_MODE::FROM_RUNTIME, false);
if (bRet)
{
qDebug() << "UiManager::syncFromRuntime - QListWidget:" << pUi->currentRow();
}
}
break;
case UI_SYNC_MSG::RADIOBOX_CHANGED:
{
}
break;
case UI_SYNC_MSG::CHECKBOX_CHANGED:
{
}
break;
case UI_SYNC_MSG::VALUE_CHANGED:
{
QLineEdit* pRt = qobject_cast(pRtControl);
QLineEdit* pUi = qobject_cast(pUiWidget);
bRet = syncValueControl(pRt, pUi, SYNC_MODE::TO_RUNTIME);
if (bRet)
{
qDebug() << "UiManager::syncFromRuntime - ValueControl:" << pUi->text();
}
}
break;
default:
{
qWarning() << "UiManager::syncFromRuntime - Unsupported msg : " << (int)msg;
}
break;
}
// 同步完后,通知UI界面刷新此控件(同时更新属性表)
// 2022-9-15,只有数据有变动的时候才需要刷新
if (bRet && m_AllControls.contains(pUiWidget))
{
m_AllControls.value(pUiWidget)->uiScene()->refreshControl(pUiWidget);
}
}
else
{
//qWarning() << "UiManager::syncFromRuntime - Error : Can't find this control.";
}
}
///
/// 用于UI向Runtime界面中的控件同步
///
///
///
void UiManager::syncToRuntime(QWidget* pUiControl, UI_SYNC_MSG msg, bool bFirst)
{
// qDebug() << "UiManager::syncToRuntime - msg:" << (int)msg;
if (m_UiToRtControls.contains(pUiControl))
{
bool bRet = false;
switch (msg)
{
case UI_SYNC_MSG::EDIT_TEXT_CHANGED:
{
QLineEdit* pUiEdit = qobject_cast(pUiControl);
QLineEdit* pRtEdit = qobject_cast(m_UiToRtControls.value(pUiControl));
bRet = syncEditControl(pUiEdit, pRtEdit, SYNC_MODE::TO_RUNTIME, bFirst);
if (bRet)
{
qDebug() << "UiManager::syncToRuntime - QLineEdit:" << pRtEdit->text();
}
}
break;
case UI_SYNC_MSG::COMBO_SEL_CHANGED:
{
QComboBox* pUiCombo = qobject_cast(pUiControl);
QComboBox* pRtCombo = qobject_cast(m_UiToRtControls.value(pUiControl));
bRet = syncComboControl(pUiCombo, pRtCombo, SYNC_MODE::TO_RUNTIME, bFirst);
if (bRet)
{
qDebug() << "UiManager::syncToRuntime - QComboBox:" << pRtCombo->currentIndex();
}
}
break;
case UI_SYNC_MSG::LIST_SEL_CHANGED:
{
QListWidget* pUi = qobject_cast(pUiControl);
QListWidget* pRt= qobject_cast(m_UiToRtControls.value(pUiControl));
// 首次同步需要同步一下所有的选择项
if (bFirst)
{
for (int i = 0; i < pUi->count(); i++)
{
pRt->insertItem(i, pUi->item(i)->text());
}
}
pRt->setCurrentRow(pUi->currentRow());
qDebug() << "UiManager::syncToRuntime - VListBox:" << pRt->currentRow();
}
break;
case UI_SYNC_MSG::RADIOBOX_CHANGED:
{
QRadioButton* pUi = qobject_cast(pUiControl);
QRadioButton* pRt = qobject_cast(m_UiToRtControls.value(pUiControl));
//// 首次同步需要把名字也复制一下
//if (bFirst)
//{
// pRt->setText(pUi->text());
//}
pRt->setChecked(pUi->isChecked());
qDebug() << "UiManager::syncToRuntime - VRadioBox:" << pRt->isChecked();
}
break;
case UI_SYNC_MSG::CHECKBOX_CHANGED:
{
QCheckBox* pUi = qobject_cast(pUiControl);
QCheckBox* pRt = qobject_cast(m_UiToRtControls.value(pUiControl));
//// 首次同步需要把名字也复制一下
//if (bFirst)
//{
// pRt->setText(pUi->text());
//}
pRt->setCheckState(pUi->checkState());
qDebug() << "UiManager::syncToRuntime - VCheckBox:" << pRt->checkState();
}
break;
case UI_SYNC_MSG::VALUE_CHANGED:
{
QLineEdit* pUi = qobject_cast(pUiControl);
QLineEdit* pRt = qobject_cast(m_UiToRtControls.value(pUiControl));
bRet = syncValueControl(pUi, pRt, SYNC_MODE::TO_RUNTIME);
if (bRet)
{
qDebug() << "UiManager::syncToRuntime - ValueControl:" << pRt->text();
}
}
break;
default:
break;
}
}
else
{
//qWarning() << "UiManager::syncToRuntime - Error : Can't find this control.";
}
}
///
/// 用于数值变更触发回调(只有ValueControl可以关联数值)
///
///
void UiManager::syncFromValue(VARIABLE* pInf)
{
// 根据不同的数值类型进行不同的转换
if (m_ValueToUiControls.contains(pInf))
{
QList pWidgets = m_ValueToUiControls.values(pInf);
// 遍历所有与此Value关联的控件,逐一更新
for (QWidget* pUiWidget : pWidgets)
{
QString strValueText = pInf->getValueString();
vDebug() << pUiWidget << " - syncFromValue [" << pInf->strName << "](" << strValueText << ").";
// 同步到ValueControl
this->syncValueControl(pUiWidget, strValueText, pInf->value.type, SYNC_MODE::FROM_VALUE);
// 同步完后,通知UI界面刷新此控件(同时更新属性表)
// 2022-5-22 此处在多个属性表同时高速刷新时,会造成控件多个属性表之间切换,所以临时屏蔽。
//if (m_AllControls.contains(pUiWidget))
//{
// m_AllControls.value(pUiWidget)->refreshControl(pUiWidget);
//}
}
}
else
{
//qWarning() << "UiManager::syncFromValue - Error : Can't find this value.";
}
}
///
/// 用于UI变更向数值单向同步
///
///
void UiManager::syncToValue(QWidget* pUiControl)
{
if (m_UiControlToValues.contains(pUiControl))
{
VARIABLE* linkValue = m_UiControlToValues.value(pUiControl);
QString className = pUiControl->metaObject()->className();
QString strValue;
if (className == CLASS_NAME_VALUECONTROL)
{
ValueControl* pVControl = qobject_cast(pUiControl);
if (pVControl != nullptr)
{
strValue = pVControl->text();
}
}
else if (className == CLASS_NAME_RESULT)
{
VResult* pVControl = qobject_cast(pUiControl);
if (pVControl != nullptr)
{
strValue = pVControl->text();
}
}
// 2021-11-2增加,如果对应的接口是一个输出接口,那么忽略这个赋值(输出接口不允许从UI输入)
if (linkValue->Direction == INF_DIRECTION::INF_DIR_OUT)
{
qDebug() << "UiManager::syncToValue - ignore: this LinkValue is INF_DIR_OUT.";
return;
}
// 直接将字符串拷贝过去
//QString strValue = pVControl->toPlainText();
//linkValue->setValue(strValue);
// 根据不同的数值类型进行不同的转换
bool bRet = false;
switch (linkValue->value.type)
{
case VALUE_TYPE::Type_Int:
{
// 获取控件数值
int controlValue = strValue.toInt();
bRet = linkValue->setValue(controlValue);
if (bRet)
{
// vDebug() << "Tpye:" << Utility::getTypeString(VALUE_TYPE::Type_Int) << " value:" << controlValue;
vDebug() << pUiControl << " - syncToValue [" << linkValue->strName << "](" << controlValue << ").";
}
}
break;
default:
{
vDebug() << "[Error] : " << (int)linkValue->value.type;
}
break;
}
}
else
{
//qWarning() << "UiManager::syncToValue - Error : Can't find this control.";
}
}
///
/// 同步Edit控件
///
///
///
///
///
///
bool UiManager::syncEditControl(QLineEdit* pSrc, QLineEdit* pDst, SYNC_MODE mode, bool bFirst)
{
Q_UNUSED(bFirst);
QString strSrc = pSrc->text();
QString strDst = pDst->text();
if (strDst != strSrc)
{
if (mode == SYNC_MODE::TO_DLL)
{
pDst->setText(strSrc);
}
else
{
VLineEdit* vEdit = qobject_cast(pDst);
vEdit->setText(strSrc);
}
return true;
}
return false;
}
///
/// 同步Combo控件
///
///
///
///
///
///
bool UiManager::syncComboControl(QComboBox* pSrc, QComboBox* pDst, SYNC_MODE mode, bool bFirst /*= false*/)
{
Q_UNUSED(mode);
// 首次同步需要同步Combo列表项
if (bFirst)
{
for (int i = 0; i < pSrc->count(); i++)
{
pDst->insertItem(i, pSrc->itemText(i));
}
}
int nIndexSrc = pSrc->currentIndex();
int nIndexDst = pDst->currentIndex();
if (nIndexDst != nIndexSrc)
{
pDst->setCurrentIndex(pSrc->currentIndex());
return true;
}
return false;
}
///
/// 同步list控件
///
///
///
///
///
///
bool UiManager::syncListControl(QListWidget* pSrc, QListWidget* pDst, SYNC_MODE mode, bool bFirst /*= false*/)
{
Q_UNUSED(mode);
// 首次同步需要同步List列表项
if (bFirst)
{
for (int i = 0; i < pSrc->count(); i++)
{
pDst->insertItem(i, pSrc->item(i)->text());
}
}
int nIndexSrc = pSrc->currentRow();
int nIndexDst = pDst->currentRow();
if (nIndexDst != nIndexSrc)
{
pDst->setCurrentRow(nIndexSrc);
return true;
}
return false;
}
///
/// 同步Value Control(数值)
///
///
///
///
///
bool UiManager::syncValueControl(QWidget* pValueControl, QString strNewValue, VALUE_TYPE type, SYNC_MODE mode)
{
Q_UNUSED(mode);
Q_UNUSED(type);
if (pValueControl == nullptr)
{
return false;
}
QString className = pValueControl->metaObject()->className();
if (className == CLASS_NAME_VALUECONTROL)
{
ValueControl* pControl = qobject_cast(pValueControl);
if (pValueControl == nullptr || pControl == nullptr)
{
return false;
}
QString strCurrentText = pControl->text();
// 如果文字相同则不更新了,防止消息死循环
if (strCurrentText == strNewValue)
{
return false;
}
// 设置新值
pControl->setText(strNewValue);
}
else if (className == CLASS_NAME_RESULT)
{
VResult* pControl = qobject_cast(pValueControl);
if (pValueControl == nullptr || pControl == nullptr)
{
return false;
}
QString strCurrentText = pControl->text();
QString strCurrentTip = pControl->toolTip();
// 剔除掉 Tip 文本
strCurrentText = strCurrentText.replace(QRegExp(strCurrentTip + STRING_INTERVAL), "");
// 如果文字相同则不更新了,防止消息死循环
if (strCurrentText == strNewValue)
{
return false;
}
// 设置新值
pControl->setText(strCurrentTip + STRING_INTERVAL + strNewValue);
//pControl->setText(strCurrentTip);
}
else
{
return false;
}
//if (mode == SYNC_MODE::FROM_VALUE)
//{
// qDebug() << "UiManager::syncFromValue - tpye:" << Utility::getTypeString(type) << " value:"
// << strNewValue << " toControl:" << pControl->m_pWidget;
//}
//else if (mode == SYNC_MODE::TO_VALUE)
//{
// qDebug() << "UiManager::syncToValue - tpye:" << Utility::getTypeString(type) << " value:"
// << strNewValue << " fromControl:" << pControl->m_pWidget;;
//}
return true;
}
///
/// 同步Value Control(控件)
///
///
///
///
///
bool UiManager::syncValueControl(QLineEdit* pSrc, QLineEdit* pDst, SYNC_MODE mode)
{
Q_UNUSED(mode);
QString strSrc = pSrc->text();
QString strDst = pDst->text();
if (strDst != strSrc)
{
if (mode == SYNC_MODE::TO_DLL)
{
pDst->setText(strSrc);
}
else
{
QString className = pDst->metaObject()->className();
if (className == CLASS_NAME_VALUECONTROL)
{
ValueControl* pVControl = qobject_cast(pDst);
if (pVControl != nullptr)
{
pVControl->setText(strSrc);
}
}
else if (className == CLASS_NAME_RESULT)
{
VResult* pVControl = qobject_cast(pDst);
if (pVControl != nullptr)
{
pVControl->setText(strSrc);
}
}
else
{
return false;
}
}
return true;
}
return false;
}
/////
///// 删除所有UI
/////
//void UiManager::deleteAllUIs()
//{
//
//}
///
/// 重置所有UI页面以及数据结构(用于反序列化使用)
///
void UiManager::reset()
{
m_pMainPage = nullptr;
m_pAllPages.clear();
m_AllControls.clear();
m_DllToUiControls.clear();
m_UiToDllControls.clear();
m_UiToRtControls.clear();
m_RtToUiControls.clear();
m_UiControlToValues.clear();
m_ValueToUiControls.clear();
}
///
/// 2022-2-12 根据控件指针查找对应的WindowAppUiView指针
///
///
///
WindowAppUiView* UiManager::getViewByControl(VControlObject* pUiControl)
{
return m_AllControls.value(pUiControl->m_pWidget);
}
///
/// 刷新指定控件的选中效果(用于适配geometry的实时更新)
///
///
void UiManager::refreshControlDrawPoint(VControlObject* pUiControl)
{
WindowAppUiView* pUiView = m_AllControls.value(pUiControl->m_pWidget);
if (pUiView)
{
pUiView->uiScene()->refreshDrawPoint(pUiControl->m_pWidget);
}
}
///
/// 2022-2-10 从DataLink中解析Tool信息
///
///
///
///
///
void UiManager::parsePouToolFromDataLink(
const DataLink& dataLink,
POU*& pPou,
TOOL*& pTool,
_INTERFACE*& pDllInf
)
{
pPou = nullptr;
pTool = nullptr;
pDllInf = nullptr;
if (dataLink.value.size() < 3)
{
return;
}
// 从DataLink信息中解析出接口信息
QString strCategory = dataLink.value.at(0);
QString strCmd = dataLink.value.at(1);
QString strDetail = dataLink.value.at(2);
// 2021-10-28 解析需要处理局部和全局变量
bool bBindVariables = false;
if (strCmd.indexOf(GROUP_GLOBAL_VARIABLE) >= 0
|| strCmd.indexOf(GROUP_LOCAL_VARIABLE) >= 0)
{
bBindVariables = true;
}
// Tool接口
if (!bBindVariables)
{
// 根据名字找到对应的_INTERFACE*
pPou = g_pPouManager->getPouByName(strCategory);
if (pPou != nullptr)
{
pTool = pPou->GetToolByName(strCmd);
if (pTool != nullptr)
{
pDllInf = pTool->getInterfaceByName(strDetail);
}
else
{
qWarning() << "GetToolByName " << strCmd << " Error";
}
}
}
// 局部和全局变量
else
{
strCategory.remove(VAR_SUFFIX);
strCmd = strCategory;
pTool = g_pGvlManager->getGvl(strCmd);
pDllInf = pTool->getInterfaceByName(strDetail);
}
}
///
/// 2022-2-10 从DataLink中解析Interface信息
///
///
///
void UiManager::parseToolInfFromDataLink( const DataLink& dataLink, _INTERFACE*& pDllInf)
{
POU* pPou = nullptr;
TOOL* pTool = nullptr;
pDllInf = nullptr;
this->parsePouToolFromDataLink(dataLink, pPou, pTool, pDllInf);
}