#include "Pou.h"
#include "WindowAppItemInterface.h"
#include "WindowAppBlockStandard.h"
#include "WindowAppBlockStandardBase.h"
#include "WindowAppBlockGoto.h"
#include "WindowAppVariableTable.h"
#include "GvlManager.h"
#include "TaskManager.h"
#include "../Common/CameraBaseClass/IBaseCamCommon.h"
#include "../Common/CameraBaseClass/IBaseCamera.h"
#include "WindowAppTaskView.h"
POU::POU()
{
m_nExecuteIndex = 0;
// 并行工具线程池支持的最大并行工具数量
m_ParallelThreadPool.setMaxThreadCount(MAX_PARALLEL_TOOL_COUNT);
}
///
/// 2022-2-16,在Pou析构的时候需要释放掉内部变量
///
POU::~POU()
{
g_pGvlManager->removeVariable(m_strPouName, INTERNALVAR_NAME_EXECTIME);
g_pGvlManager->removeVariable(m_strPouName, INTERNALVAR_NAME_EXECCOUNT);
g_pGvlManager->removeVariable(m_strPouName, INTERNALVAR_NAME_ERRORCOUNT);
}
///
/// 重置本Pou中所有的数据结构
///
void POU::reset()
{
// 遍历所有的工具
QHash::iterator iter = m_itemToTools.begin();
while (iter != m_itemToTools.end())
{
// 回收资源
if (iter.value()->pDllPtr != nullptr)
{
delete iter.value()->pDllPtr;
iter.value()->pDllPtr = nullptr;
}
// 从界面中移除此功能块
QString str = iter.value()->strInstanceName;
WindowAppBlockBase* pItem = m_instNameToToolItems[str];
if (pItem != nullptr)
{
pItem->scene()->removeItem(pItem);
}
iter++;
}
m_instNameToTools.clear();
m_fullNameToInterfaces.clear();
m_itemToTools.clear();
m_itemToInterfaces.clear();
m_instNameToToolItems.clear();
m_fullNameToInterfaceItems.clear();
m_AutoToolRenameIndex.clear();
m_Links.clear();
}
///
/// 添加一个运行的Tool功能块到当前Pou中
///
///
void POU::registerTool(WindowAppBlockBase* pBlockItem, TOOL* pRunningTool)
{
// 保存功能块和工具的对应信息
m_itemToTools.insert(pBlockItem, pRunningTool);
m_instNameToTools.insert(pRunningTool->strInstanceName, pRunningTool);
m_instNameToToolItems.insert(pRunningTool->strInstanceName, pBlockItem);
// 重命名计数 + 1
AddRenameRefCount(pRunningTool->strName);
// 2021-8-14 如果是StandardTool,则刷新StandardTools列表
// 2022-3-28 更新 (NOTICE:此处是包含了标准工具和Goto工具一起的)
// 2022-4-28 加入了Parallel工具
// 2022-8-25 加入了ForLoop工具
if (pRunningTool->isIndexedTool() )
{
m_StandardTools.push_back(pRunningTool);
// 2022-3-31更新,此处要保证严格有序,否则反序列化或者其他时候可能会有各种隐患
std::sort(m_StandardTools.begin(), m_StandardTools.end(), TOOL::sort_by_index);
// 2021-8-14 Pou中添加工具后,如果当前Pou被Task选中,则需要向Task同步新增加的Tool信息
if (m_pParentTask != nullptr)
{
g_pTaskManager->addToolToTaskView(m_pParentTask->strName, this, pRunningTool);
}
}
#ifdef QT_NO_DEBUG
#else
// 输出调试信息
// debugAllTools();
#endif
}
///
/// 添加一个运行的接口到当前Pou中
///
///
///
void POU::registerInterface(WindowAppItemInterface* pInfItem, _INTERFACE* pSelInf)
{
if (pInfItem == nullptr || pSelInf == nullptr)
{
qDebug() << "[Error] POU::registerInterface - but pInfItem or pSelInf is nullptr.";
return;
}
QString strInfName = QString(pInfItem->m_infInfo->strFullName);
m_itemToInterfaces.insert(pInfItem, pSelInf);
m_fullNameToInterfaces.insert(strInfName, pSelInf);
m_fullNameToInterfaceItems.insert(strInfName, pInfItem);
// 输出接口信息
// debugAllInterface();
}
///
/// 移除一个运行的Tool功能块
///
///
void POU::removeTool(QGraphicsItem* pBlockItem)
{
Q_UNUSED(pBlockItem);
//for (QVector::iterator it = m_SelTools.begin();it != m_SelTools.end();)
//{
// if (it->item == pRunningBlock)
// {
// it = m_SelTools.erase(it);
// }
// else
// {
// it++;
// }
//}
#ifdef QT_NO_DEBUG
#else
// 输出调试信息
// debugAllTools();
#endif
}
///
/// 显示当前工具对话框
///
///
void POU::ShowToolDialog(WindowAppBlockStandardBase* pBlockItem)
{
m_itemToTools.value(pBlockItem)->pDllPtr->ShowDialog();
}
DebugData POU::GetToolDebugData(WindowAppBlockStandardBase* pBlockItem)
{
if (m_itemToTools.value(pBlockItem) != nullptr && m_itemToTools.value(pBlockItem)->pDllPtr)
{
return m_itemToTools.value(pBlockItem)->pDllPtr->GetDebugData();
}
DebugData data;
return data;
}
///
/// 序号+1
///
///
void POU::ToolMoveDown(WindowAppBlockStandardBase* pBlockItem)
{
TOOL* pMovTool = m_itemToTools.value(pBlockItem);
int nCurIndex = pMovTool->nIndex;
// 如果只剩1个工具或者本身就是最后一个工具的话,则忽略这个操作
if (m_itemToTools.size() <= 1
|| nCurIndex >= m_itemToTools.size() - 1)
{
return;
}
int nAjustIndex = nCurIndex + 1;
// 交换一下邻接的工具序号
QHash::iterator iter = m_itemToTools.begin();
while (iter != m_itemToTools.end())
{
if (iter.value()->nIndex == nAjustIndex)
{
iter.value()->nIndex--;
break;
}
iter++;
}
// 修正自身序号
m_itemToTools.value(pBlockItem)->nIndex++;
// 移动StandardToolList
m_StandardTools.removeOne(pMovTool);
m_StandardTools.insert(nAjustIndex, pMovTool);
// 2022-3-6,检测功能块的变动是否需要向Task同步
this->syncToolMoveToTaskView();
}
///
/// 序号-1
///
///
void POU::ToolMoveUp(WindowAppBlockStandardBase* pBlockItem)
{
TOOL* pMovTool = m_itemToTools.value(pBlockItem);
int nCurIndex = pMovTool->nIndex;
// 如果只剩1个工具或者本身就是第一个工具的话,则忽略这个操作
if (m_itemToTools.size() <= 1 || nCurIndex == 0)
{
return;
}
int nAjustIndex = nCurIndex - 1;
// 交换一下邻接的工具序号
QHash::iterator iter = m_itemToTools.begin();
while (iter != m_itemToTools.end())
{
if (iter.value()->nIndex == nAjustIndex)
{
iter.value()->nIndex++;
break;
}
iter++;
}
// 修正自身序号
m_itemToTools.value(pBlockItem)->nIndex--;
// 移动StandardToolList
m_StandardTools.removeOne(pMovTool);
m_StandardTools.insert(nAjustIndex, pMovTool);
// 2022-3-6,检测功能块的变动是否需要向Task同步
this->syncToolMoveToTaskView();
}
///
/// 执行顺序移动到最前端
///
///
void POU::ToolMoveFirst(WindowAppBlockStandardBase* pBlockItem)
{
TOOL* pMovTool = m_itemToTools.value(pBlockItem);
int& nCurIndex = pMovTool->nIndex;
// 所有工具序号后移
QHash::iterator iter = m_itemToTools.begin();
while (iter != m_itemToTools.end())
{
if (iter.value()->nIndex < nCurIndex)
{
iter.value()->nIndex++;
}
iter++;
}
// 修正自身序号
nCurIndex = 0;
// 移动StandardToolList
m_StandardTools.removeOne(pMovTool);
m_StandardTools.push_front(pMovTool);
// 2022-3-6,检测功能块的变动是否需要向Task同步
this->syncToolMoveToTaskView();
}
///
/// 执行顺序移动到最后端
///
///
void POU::ToolMoveLast(WindowAppBlockStandardBase* pBlockItem)
{
TOOL* pMovTool = m_itemToTools.value(pBlockItem);
int nLastIndex = m_itemToTools.size() - 1;
int& nCurIndex = pMovTool->nIndex;
// 所有工具序号前移
QHash::iterator iter = m_itemToTools.begin();
while (iter != m_itemToTools.end())
{
if (iter.value()->nIndex > nCurIndex)
{
iter.value()->nIndex--;
}
iter++;
}
// 修正自身序号
nCurIndex = nLastIndex;
// 移动StandardTools
m_StandardTools.removeOne(pMovTool);
m_StandardTools.push_back(pMovTool);
// 2022-3-6,检测功能块的变动是否需要向Task同步
this->syncToolMoveToTaskView();
}
///
/// 复制功能块本身
///
///
void POU::ToolCopyBlock(WindowAppBlockStandardBase* pBlockItem)
{
TOOL* pActiveTool = m_itemToTools.value(pBlockItem);
if (pActiveTool)
{
}
}
///
/// 复制功能块的数据
///
///
void POU::ToolCopyData(WindowAppBlockStandardBase* pBlockItem)
{
TOOL* pActiveTool = m_itemToTools.value(pBlockItem);
if (pActiveTool)
{
m_BufferTemp.open(QIODevice::WriteOnly);
QDataStream ar(&m_BufferTemp);
ar << pActiveTool->strName;
pActiveTool->pDllPtr->SerializedToDoc(ar);
}
}
///
/// 粘贴数据
///
///
void POU::ToolPaste(WindowAppBlockStandardBase* pBlockItem)
{
TOOL* pActiveTool = m_itemToTools.value(pBlockItem);
if (pActiveTool)
{
m_BufferTemp.open(QIODevice::ReadOnly);
QDataStream ar(&m_BufferTemp);
QString strName;
ar >> strName;
if (strName == pActiveTool->strName)
{
pActiveTool->pDllPtr->SerializedFromDoc(ar);
}
else
{
qWarning() << "Paste Error Data Source is" << strName;
}
m_BufferTemp.close();
}
}
///
/// 删除指定工具
///
///
void POU::ToolDelete(WindowAppBlockBase* pBlockItem)
{
//// 跳过注释工具
//if (pBlockItem->m_toolInfo->isCommentTool())
//{
// return;
//}
vDebug() << "Delete tool[" << pBlockItem->m_toolInfo->strInstanceName << "].";
// 如果是带序号的工具,需要先调整一下序号
if (pBlockItem->m_toolInfo->isIndexedTool())
{
// 调整其他功能块的序号
int nCurIndex = m_itemToTools.value(pBlockItem)->nIndex;
// 2021-8-14 移除StandardTools列表中的信息
m_StandardTools.removeOne(m_itemToTools.value(pBlockItem));
// 遍历所有的工具
QHash::iterator iter = m_itemToTools.begin();
while (iter != m_itemToTools.end())
{
// 后面的序号前移
if (iter.value()->nIndex > nCurIndex)
{
iter.value()->nIndex--;
}
iter++;
}
// 回收工具的Dll资源(仅标准工具才有)
if (m_itemToTools.value(pBlockItem)->pDllPtr != nullptr)
{
delete m_itemToTools.value(pBlockItem)->pDllPtr;
m_itemToTools.value(pBlockItem)->pDllPtr = nullptr;
}
}
// 先移除工具中的Interface信息
QVectorIterator<_INTERFACE*> it(m_itemToTools.value(pBlockItem)->Interfaces);
while (it.hasNext())
{
_INTERFACE* pInf = it.next();
m_itemToInterfaces.remove(m_fullNameToInterfaceItems.value(pInf->strFullName));
m_fullNameToInterfaces.remove(pInf->strFullName);
m_fullNameToInterfaceItems.remove(pInf->strFullName);
}
// 如果删除的是硬件组态里的工具,需要清理绑定信息
if (pBlockItem->m_toolInfo->isHardwareTool())
{
g_pGvlManager->unbindHdwToolAndDB(pBlockItem->m_toolInfo, pBlockItem->m_toolInfo->strHdwInstName);
}
// 移除此工具
m_itemToTools.remove(pBlockItem);
m_instNameToTools.remove(pBlockItem->m_toolInfo->strInstanceName);
m_instNameToToolItems.remove(pBlockItem->m_toolInfo->strInstanceName);
// 工具的重命名计数减一
m_AutoToolRenameIndex[pBlockItem->m_toolInfo->strName] --;
// 2022-9-4 加入,由于有Wait工具的存在,所以需要到TaskManager中反注册一下
if (pBlockItem->m_toolInfo->isWaitTool())
{
g_pTaskManager->unregisterTool(pBlockItem->m_toolInfo);
}
//#ifdef QT_NO_DEBUG
//#else
// // 输出调试信息
// debugAllTools();
// debugAllInterface();
//#endif
}
///
/// 保存Link信息
///
///
///
void POU::makeLink(
WindowAppItemInterface* srcInfItem,
WindowAppItemInterface* dstInfItem,
WindowAppItemLink* linkItem,
LINK_MODE linkMode
)
{
// 起始接口
_INTERFACE* srcInf = m_itemToInterfaces.value(srcInfItem);
if (srcInf == nullptr)
{
qDebug() << "[POU][LINK] Make link Error: startInf is nullptr.";
return;
}
// 终止接口
_INTERFACE* dstInf = m_itemToInterfaces.value(dstInfItem);
if (dstInf == nullptr)
{
qDebug() << "[POU][LINK] Make link Error: endInf is nullptr.";
return;
}
// 建立Link
dstInf->pUpLinkInterface = srcInf;
srcInf->pDownLinkInterfaces.push_back(dstInf);
// 引用计数 + 1
srcInf->nRefCount++;
dstInf->nRefCount++;
// 2022-8-28去掉,改为运行时实时判定
//// 2022-5-4增加,如果是Parallel模式连接,则还需要把被连接的Tool设置为并行模式
//if (linkMode == LINK_MODE::LINK_PARALLEL)
//{
// dstInf->parent()->bParallelized = true;
//}
// 2022-6-12增加,保存本Link信息用于统一管理
this->registerLink(srcInfItem, dstInfItem, linkItem, linkMode);
//// 2022-9-5增加,此处需要在链接的时候直接启动并行子工具线程(并行工具的新启动机制)
//this->addParallelSubTool(dstInfItem->m_infInfo->parent());
qDebug() << "[POU][LINK] Make link: " << srcInf->parent()->strInstanceName
<< "-" << srcInf->strName << " --> " << dstInf->parent()->strInstanceName << "-" << dstInf->strName;
}
///
/// 清除Link信息
///
///
void POU::removeLink(WindowAppItemInterface* endInfItem)
{
// 从上联接口中移除其下联接口信息
QVector<_INTERFACE*>& pDownInterfaces = m_itemToInterfaces.value(endInfItem)->pUpLinkInterface->pDownLinkInterfaces;
for (QVector<_INTERFACE*>::iterator it = pDownInterfaces.begin(); it != pDownInterfaces.end();)
{
if (*it == m_itemToInterfaces.value(endInfItem))
{
//// 2022-5-6,移除被连接Tool的并行模式标志(删除并行link等于移出了并行组)
//if ((*it)->parent()->bParallelized)
//{
// (*it)->parent()->bParallelized = false;
//}
it = pDownInterfaces.erase(it);
}
else
{
it++;
}
}
// 移除对应接口的上行连接信息
m_itemToInterfaces.value(endInfItem)->pUpLinkInterface = nullptr;
// 2022-6-13 增加,移除Link的注册信息
this->unregisterLink(endInfItem);
}
///
/// 注册新的Link信息
///
///
///
///
void POU::registerLink(
WindowAppItemInterface* startInfItem,
WindowAppItemInterface* endInfItem,
WindowAppItemLink* linkItem,
LINK_MODE linkMode
)
{
LINK newLink;
newLink.linkMode = linkMode;
newLink.pSrcItem = startInfItem;
newLink.pDstItem = endInfItem;
newLink.pLinkItem = linkItem;
m_Links.push_back(newLink);
qDebug() << "POU::registerLink - Inf[" << endInfItem->m_infInfo->strFullName << "]";
}
///
/// 反注册Link信息
///
///
///
void POU::unregisterLink(WindowAppItemInterface* endInfItem)
{
for (auto it = m_Links.begin(); it != m_Links.end();)
{
if (it->pDstItem == endInfItem)
{
it = m_Links.erase(it);
qDebug() << "POU::unregisterLink - Inf[" << endInfItem->m_infInfo->strFullName << "]";
break;
}
else
{
++it;
}
}
}
///
/// 将指定接口绑定到指定Port中
///
///
///
void POU::bindPortAndInterface(WindowAppBlockBase* pPortItem, _INTERFACE* pBindInf, const QString& strInfName)
{
// 2021-6-6 增加,被绑定接口的引用计数需要 + 1
pBindInf->nRefCount++;
_INTERFACE* pPortInf = m_itemToTools.value(pPortItem)->Interfaces[0];
// 将绑定接口的信息复制过来
pPortInf->strName = strInfName;
// TODO:此处这个全名是有问题的,接口名字必须全局唯一,但是这里重复了,strFullName暂时不改了
// pPortInf->strFullName = pBindInf->strFullName;
pPortInf->strComment = pBindInf->strComment;
pPortInf->bSerialized = pBindInf->bSerialized;
// 2021-5-24 修正,由于GVl变量是双向的,此处需要强制设置为和Port方向一致
// pPortInf->InfDirection = pBindInf->InfDirection;
pPortInf->Type = pBindInf->Type;
// 指针直接复制,这样值就可以双方同步了
pPortInf->value = pBindInf->value;
pPortInf->nIndex = pBindInf->nIndex;
pPortInf->strNameWithType= pBindInf->strNameWithType;
//// 2021-6-12 修正port绑定接口的时候造成的崩溃bug
//// 修改连父工具指针一起复制过去
//pPortInf->pParentTool = pBindInf->pParentTool;
// 这三个属性是否需要复制待定
//pPortInf->bShow = pBindInf->bShow;
//pPortInf->bWatch = pBindInf->bWatch;
// 2021-6-5增加,直接复制link信息,并且整理旧接口相关的link关系
// For test
//pPortInf->setValue(50);
//g_pVariablesManager->debugVariable(pPortInf);
//g_pVariablesManager->debugVariable(m_ItemPorts[pPortItem]->Interface);
//g_pVariablesManager->debugAllVariables();
qDebug() << "[POU][PORT]: bind " << pPortInf->strName << " to port.";
}
///
/// 获取指定Item的绝对坐标
///
///
///
QPointF POU::GetToolItemPos(QString strKey)
{
return m_instNameToToolItems.value(strKey)->scenePos();
}
///
/// 2022-3-12,删除指定的接口相关数据结构
///
///
///
void POU::DelInterface(const QString& strFullName, WindowAppItemInterface* pItem, _INTERFACE* pInf)
{
Q_UNUSED(pInf);
m_fullNameToInterfaces.remove(strFullName);
m_itemToInterfaces.remove(pItem);
m_fullNameToInterfaceItems.remove(strFullName);
}
///
/// 根据接口中对应的Dll数值获取接口指针(UIManager中使用)
///
///
///
_INTERFACE* POU::GetInterfaceByValuePtr(void* pValue)
{
QMapIterator iter(m_fullNameToInterfaces);
while (iter.hasNext())
{
_INTERFACE* pInf = iter.next().value();
// 2022-5-18 增加,由于每个Tool多了一个ToolStart接口,所以这里要把ToolStart接口过滤掉,否则会崩溃
if(pInf->nIndex<0)
{
continue;
}
void** pValuePtr = pInf->getValuePtr();
if (pValuePtr == pValue)
{
return pInf;
}
}
return nullptr;
}
///
/// 重命名计数 + 1
///
///
void POU::AddRenameRefCount(const QString& strName)
{
m_AutoToolRenameIndex[strName]++;
}
///
/// 获取所有的Event类型接口(如果有)
///
///
QMap POU::getAllEvents()
{
QMap m_Events;
QMapIterator iter(m_fullNameToInterfaces);
while (iter.hasNext())
{
if (iter.next().value()->Type==INF_TYPE::INF_TYPE_EVENT
//&& iter.value()->eventTrigger !=nullptr
)
{
m_Events.insert(iter.key(), iter.value());
}
}
return m_Events;
}
///
/// 生成工具新的实例名字
///
///
///
QString POU::genToolInstanceName(const QString& strToolName)
{
// 根据引用计数生成工具的实例名字
int nRefCount = m_AutoToolRenameIndex.value(strToolName) + 1;
return QString(strToolName + " " + QString::number(nRefCount));
}
///
/// 设置工具的启用禁用
///
///
///
void POU::setToolEnable(const TOOL* pToolInfo, bool bEnable)
{
m_instNameToTools.value(pToolInfo->strInstanceName)->bEnable = bEnable;
}
///
/// 设置接口的启用禁用
///
///
///
bool POU::setInterfaceEnable(const _INTERFACE* pInfInfo, bool bEnable)
{
// 需要参考引用计数,如果计数错误则不允许切换
if (pInfInfo->nRefCount > 0)
{
return false;
}
m_fullNameToInterfaces.value(pInfInfo->strFullName)->bEnable = bEnable;
return true;
}
///
/// 设置接口的启用禁用(根据接口序号设置)
///
///
///
///
bool POU::setInterfaceEnable(const TOOL* pToolInfo, int nInfIndex, bool bEnable)
{
_INTERFACE* pInf = m_instNameToTools.value(pToolInfo->strInstanceName)->Interfaces[nInfIndex];
// 需要参考引用计数,如果计数错误则不允许切换
if (pInf->nRefCount > 0)
{
return false;
}
pInf->bEnable = bEnable;
return true;
}
///
/// 更新工具的Info
///
///
///
void POU::setToolInfo(const TOOL* pToolInfo, const QString& strInfo)
{
m_instNameToTools.value(pToolInfo->strInstanceName)->strInfo = strInfo;
}
///
/// 设置工具的延时参数
///
///
///
void POU::setToolDelay(const TOOL* pToolInfo, const int inDelay, const int outDelay)
{
m_instNameToTools.value(pToolInfo->strInstanceName)->execParams.nPreDelay = inDelay;
m_instNameToTools.value(pToolInfo->strInstanceName)->execParams.nPostDelay = outDelay;
}
///
/// 设置工具的实例名称
///
///
void POU::setInstanceName(const TOOL* pToolInfo, const QString& strNewInsName, const QString& strOldInsName)
{
Q_UNUSED(pToolInfo);
// 保留一下旧数据
TOOL* tool = m_instNameToTools.value(strOldInsName);
WindowAppBlockBase* pItem = m_instNameToToolItems[strOldInsName];
// 更名,设置别名
m_instNameToTools.value(strOldInsName)->strAliasName = strOldInsName;
m_instNameToTools.value(strOldInsName)->strInstanceName = strNewInsName;
// 删掉旧的数据
m_instNameToTools.remove(strOldInsName);
m_instNameToToolItems.remove(strOldInsName);
// 添加新的数据,保持key一致
m_instNameToTools.insert(strNewInsName, tool);
m_instNameToToolItems.insert(strNewInsName, pItem);
// 设置新的实例化名称到工具
if (tool->pDllPtr)
{
tool->pDllPtr->ModToolInstanceName(strNewInsName);
}
}
///
/// 检查工具的实例名称是否重复(用于在Dialog对话框中判断用户是否可以重命名工具)
///
///
///
bool POU::isInstanceNameDuplicated(const QString& strInsName)
{
QMap::iterator it = m_instNameToTools.find(strInsName);
if (it != m_instNameToTools.end())
{
return true;
}
return false;
}
///
/// 查询可执行SmartLink的接口(找离本接口最近的同类型输出端口,序号小于自己的,当然不一定能够找到)
///
///
///
WindowAppItemInterface* POU::getSmartLinkInterface(const WindowAppItemInterface* pInf)
{
// 查询序号小于本接口的工具
TOOL* pTool = pInf->m_infInfo->parent();
QHash::const_iterator it;
int nCount = m_itemToTools.size();
for (int i = 0; i < nCount; i++)
{
int nTargetIndex = pTool->nIndex - i - 1;
if (nTargetIndex < 0)
{
return nullptr;
}
it = m_itemToTools.constBegin();
// 遍历所有工具
for (; it != m_itemToTools.constEnd(); ++it)
{
// qDebug() << i.key() << ":" << i.value();
// 找到对应的序号
if (it.value()->nIndex == nTargetIndex)
{
// 查找是否有符合的工具
TOOL* pLinkTool = it.value();
for (int m = 0; m < pLinkTool->Interfaces.size(); m++)
{
_INTERFACE* pLinkInf = pLinkTool->Interfaces[m];
// 方向为输出并且类型相同的接口,并且接口处于可用状态
if (pLinkInf->Direction == INF_DIRECTION::INF_DIR_OUT
&& pLinkInf->isSameTypeTo(pInf->m_infInfo)
&& pLinkInf->bEnable)
{
// return pLinkTool->Interfaces[m];
return m_fullNameToInterfaceItems.value(pLinkInf->strFullName);
}
}
// 如果没有找到,则跳出循环,继续查找下一个序号
break;
}
}
}
return nullptr;
}
///
/// 完成Pou的初始化动作
///
///
void POU::init(const QString& strName, WindowAppPouScene* pScene)
{
this->m_strPouName = strName;
this->m_parentScene = pScene;
// 初始化本Pou内部变量
this->initPouInternalVariables();
// 绑定本Pou的内部变量
this->bindPouInternalVariables();
}
///
/// 是否被Task选中
///
///
bool POU::isSelByTask()
{
return (this->m_pParentTask != nullptr);
}
///
/// 是否在Task中运行
///
///
bool POU::isRunningInTask()
{
return (this->m_pParentTask != nullptr && m_pParentTask->isRunning());
}
///
/// 2021-9-15 增加,查找本Pou中指定类型的接口(用于设计界面中的数据链接用)
///
///
///
bool POU::containInterface(VALUE_TYPE type, INF_DIRECTION dir)
{
// 遍历本Pou中所有Tool的所有Interface,查找是否有对应的类型
QMapIterator it(m_fullNameToInterfaces);
while (it.hasNext())
{
if (it.next().value()->value.type == type
&& it.value()->Direction == dir
)
{
return true;
}
}
return false;
}
///
/// 2022-6-21 增加,获取两个Block之间的所有LinkItem(用于进行批量移动)
///
///
///
///
QList POU::getLinkItemsBetweenBlocks(WindowAppBlockBase* srcBlock, WindowAppBlockBase* dstBlock)
{
QList linkItemList;
// 遍历终点功能块的所有输入接口
for (const auto& infItem : dstBlock->m_itemInterfaces)
{
// 输入接口
if (infItem->m_infInfo->isDirInput())
{
// 首先找到这个输入接口对应的LinkItem的序号
int nLinkIndex = this->getLinkIndexByDstInfItem(infItem);
// 如果没有则说明这个接口没有Link,继续查找下一个
if (nLinkIndex < 0)
{
continue;
}
// 如果找到了Link,那么判断这个Link是否是属于srcBlock的
WindowAppItemInterface* srcInfItem = m_Links[nLinkIndex].pSrcItem;
bool bInBlock = srcBlock->isInBlock(srcInfItem);
// 如果这个Item是属于这个Block,则将此两个接口间的LinkItem保存下来
if (bInBlock)
{
linkItemList.push_back(m_Links[nLinkIndex].pLinkItem);
}
}
}
return linkItemList;
}
///
/// 2022-6-21 获取指定接口Item的LinkItem序号
///
///
///
int POU::getLinkIndexByDstInfItem(WindowAppItemInterface* dstItem)
{
for (int i = 0; i < m_Links.size(); i++)
{
if (m_Links[i].pDstItem == dstItem)
{
return i;
}
}
return -1;
}
///
/// 2022-2-15 增加Pou内部变量(仅用于统计,不显示、不序列化)
/// NOTICE:由于不参与序列化,所以每次反序列化完毕之后都需要手工重新创建一下内部变量
///
void POU::initPouInternalVariables()
{
int nIndex = g_pGvlManager->getVariablesCountByGroup(m_strPouName);
// 执行总时长(ms)
VARIABLE* pNewVariable = new VARIABLE(
m_strPouName,
false,
INTERNALVAR_NAME_EXECTIME,
"int",
"0",
INTERNALVAR_CHNAME_EXECTIME,
nIndex,
false // 内部变量标识
);
// 数据结构中添加本变量信息
g_pGvlManager->addNewVariable(
m_strPouName,
pNewVariable
);
// 执行次数
pNewVariable = new VARIABLE(
m_strPouName,
false,
INTERNALVAR_NAME_EXECCOUNT,
"int",
"0",
INTERNALVAR_CHNAME_EXECCOUNT,
nIndex + 1,
false
);
// 数据结构中添加本变量信息
g_pGvlManager->addNewVariable(
m_strPouName,
pNewVariable
);
// 错误次数
pNewVariable = new VARIABLE(
m_strPouName,
false,
INTERNALVAR_NAME_ERRORCOUNT,
"int",
"0",
INTERNALVAR_CHNAME_ERRORCOUNT,
nIndex + 2,
false
);
// 数据结构中添加本变量信息
g_pGvlManager->addNewVariable(
m_strPouName,
pNewVariable
);
}
/// W
/// 2022-2-16 绑定Pou内部变量和EXEC_PARAMS数据结构
/// 为了防止大幅度改动数据结构,将内部变量与EXEC_PARAMS做绑定
///
void POU::bindPouInternalVariables()
{
VARIABLE* pVar = g_pGvlManager->getVariableByName(m_strPouName, INTERNALVAR_NAME_EXECTIME);
pVar->value.setValueByAddress((void**)&this->execParams.nExecTime);
pVar = g_pGvlManager->getVariableByName(m_strPouName, INTERNALVAR_NAME_EXECCOUNT);
pVar->value.setValueByAddress((void**)&this->execParams.nExecCount);
pVar = g_pGvlManager->getVariableByName(m_strPouName, INTERNALVAR_NAME_ERRORCOUNT);
pVar->value.setValueByAddress((void**)&this->execParams.nErrorCount);
}
///
/// 2022-3-6,检测功能块的变动是否需要向Task同步
///
void POU::syncToolMoveToTaskView()
{
if (this->isSelByTask())
{
WindowAppTaskView* pTaskView = g_pTaskManager->getTaskViewByName(this->m_pParentTask->strName);
pTaskView->onMovePouTool(this);
}
}
///
/// 输出所有工具相关的数据结构
///
void POU::debugAllTools()
{
qDebug() << "QMap m_AllTools - size : " << m_instNameToTools.size();
QMapIterator it1(m_instNameToTools);
while (it1.hasNext())
{
it1.next();
qDebug() << it1.key() << " - with " << it1.value()->Interfaces.size() << " interfaces";
}
qDebug() << "QHash m_ItemTools - size : " << m_itemToTools.size();
QHashIterator it2(m_itemToTools);
while (it2.hasNext())
{
it2.next();
qDebug() << it2.key()->m_toolInfo->strInstanceName << " - " << it2.value();
}
qDebug() << "QHash m_ToolItems - size : " << m_instNameToToolItems.size();
QMapIterator it3(m_instNameToToolItems);
while (it3.hasNext())
{
it3.next();
qDebug() << it3.key();
}
}
///
/// 输出所有接口相关的数据结构
///
void POU::debugAllInterface()
{
qDebug() << "QString, _INTERFACE* - size : " << m_fullNameToInterfaces.size();
QMapIterator it1(m_fullNameToInterfaces);
while (it1.hasNext())
{
it1.next();
qDebug() << it1.key() << " - " << it1.value();
}
qDebug() << "QHash m_ItemInterfaces - size : " << m_itemToInterfaces.size();
QHashIterator it2(m_itemToInterfaces);
while (it2.hasNext())
{
it2.next();
qDebug() << it2.key()->m_infInfo->strFullName << " - " << it2.value();
}
qDebug() << "QHash m_InterfaceItems - size : " << m_fullNameToInterfaceItems.size();
QMapIterator it3(m_fullNameToInterfaceItems);
while (it3.hasNext())
{
qDebug() << it3.next().key();
}
}
/////
///// 输出所有引用计数的相关数据结构
/////
//void PouManager::debugAllRefCounter()
//{
// QHashIterator i(m_ItemReferenceCounter);
// while (i.hasNext())
// {
// qDebug() << i.next().key() << ":" << i.value();
// }
//
// //QHash::const_iterator i;
// //for (i = m_ItemReferenceCounter.constBegin(); i != m_ItemReferenceCounter.constEnd(); ++i)
// //{
// // qDebug() << i.key() << ":" << i.value();
// //}
//}