logplus/ModuleConsole/command/src/LayoutModuleCmd.cpp

703 lines
18 KiB
C++
Raw Normal View History

2026-01-16 17:18:41 +08:00
/*
* LayoutModuleCmd.cpp
*
* Created on: 2012-10-10
* Author: limengzhuo
*/
#include <QDebug>
#include <QHash>
#include <iostream>
#include "LayoutModuleCmd.h"
#include "ModuleGraphicsItem.h"
#include "ModuleConnectGraphicsItem.h"
#include "PaiWorkflowDataModel.h"
#include "ModuleInformation.h"
#include "WorkFlowFile.h"
#include "PaiModuleStyle.h"
#include "ModuleConnection.h"
#include "GlobalWorkflowItems.h"
#include "WorkflowSceneManager.h"
using namespace pai::graphics2d;
using namespace pai::workflow;
const int DEFAULT_XPOSITION = 50;
namespace pai
{
LayoutModuleCmd::LayoutModuleCmd(pai::graphics2d::WorkflowSceneManager *pSceneManager,
pai::objectmodel::PaiWorkflowDataModel *pWorkflow, QList<QGraphicsItem*> list, QUndoCommand *parent)
:QUndoCommand(parent)
{
m_pSceneManager = pSceneManager;
m_pWorkflow = pWorkflow;
m_list = list;
m_stepIdList.clear();
}
LayoutModuleCmd::~LayoutModuleCmd()
{
for (int i = 1; i <= m_moduleRelationMap.count(); ++i)
{
m_moduleRelationMap[i].clear();
}
m_moduleRelationMap.clear();
qDeleteAll(m_connectionList);
m_connectionList.clear();
}
void LayoutModuleCmd::undo()
{
recoveryLayout();
}
void LayoutModuleCmd::redo()
{
LayoutWorkflow();
}
void LayoutModuleCmd::recoveryLayout()
{
if (m_stepIdList.count() < 2)
return;
// The loop value for m_ModuleItemPosList
int j = 0;
QList<ModuleGraphicsItem*>moduleList = GetModuleGraphicsItems(m_stepIdList);
for (int i = 0; i < moduleList.count(); i++)
{
if (moduleList.at(i))
{
m_pWorkflow->GetModuleStyle(moduleList.at(i)->GetModule()->GetStepID())->SetPosition(m_ModuleItemPosList.at(j), moduleList.at(i));
j++;
}
}
updateConnectionLine();
}
void LayoutModuleCmd::updateConnectionLine()
{
for (int j = 0; j < m_connectionList.count(); j++)
{
ModuleConnectGraphicsItem *connectItem = GlobalWorkflowItems::GetInstance()->FindConnectionItem(m_pSceneManager, m_connectionList.at(j));
if (connectItem)
{
connectItem->UpdatePosition();
}
}
}
void LayoutModuleCmd::PrintMap()
{
if (m_moduleRelationMap.count() > 0)
{
for (int i = 0; i < m_moduleRelationMap.count(); ++i)
{
std::cout << "Level " << i + 1 << "items: ";
for (int j = 0; j < m_moduleRelationMap[i + 1].count(); ++j)
{
std::cout << m_moduleRelationMap[i + 1].at(j) << " ,";
}
std::cout << std::endl;
}
}
else
{
std::cout << "Relation map is empty!" << std::endl;
}
}
void LayoutModuleCmd::GetDestModulesRecursive(int stepId, QList<int> &stepIdListAdjusted, QList<int> stepIdList)
{
QList<int> destStepIdList = GetDestModules(stepId, stepIdList);
foreach (int step, destStepIdList)
{
if (!stepIdListAdjusted.contains(step))
{
stepIdListAdjusted.push_back(step);
stepIdList.removeOne(step);
}
}
foreach(int step, destStepIdList)
{
GetDestModulesRecursive(step, stepIdListAdjusted, stepIdList);
}
}
QList<ModuleGraphicsItem*> LayoutModuleCmd::GetModuleGraphicsItemsFromStepId(QList<int> stepIdList)
{
QList<ModuleGraphicsItem*> itemList;
itemList.clear();
foreach(int step, stepIdList)
{
ModuleGraphicsItem *pItem = FindModule(step, m_moduleList);
itemList << pItem;
}
return itemList;
}
int LayoutModuleCmd::GetMaxWidth()
{
int maxWidth = 1;
for (int i = 1; i <= m_moduleRelationMap.count(); ++i)
{
if (m_moduleRelationMap[i].count() > maxWidth)
{
maxWidth = m_moduleRelationMap[i].count();
}
}
return maxWidth;
}
void LayoutModuleCmd::GetModuleRelationMap(QList<int> &stepIdList)
{
m_moduleRelationMap.clear();
int level = 0;
int stepIndex = 0;
while((stepIdList.count() > 0) && (stepIndex < stepIdList.count()))
{
int step = stepIdList.at(stepIndex);
bool bStepPushed = false;
for (int i = 1; i <= m_moduleRelationMap.count(); ++i)
{
if (m_moduleRelationMap[i].contains(step))
{
bStepPushed = true;
break;
}
}
if (bStepPushed)
{
++stepIndex;
continue;
}
QList<int> itemListSameSrc;
itemListSameSrc.clear();
itemListSameSrc.push_back(step);
FindModulesWithSameSource(step, itemListSameSrc, stepIdList);
m_moduleRelationMap[++level]= itemListSameSrc;
foreach(int stepSameSrc, itemListSameSrc)
{
QList<int> itemListSameDest;
itemListSameDest.clear();
FindModulesWithSameDest(stepSameSrc, itemListSameDest, stepIdList);
foreach(int stepSameDest, itemListSameDest)
{
if (!m_moduleRelationMap[level].contains(stepSameDest))
{
m_moduleRelationMap[level].push_back(stepSameDest);
}
}
itemListSameDest.clear();
}
QList<int> itemListDest;
itemListDest.clear();
foreach(int stepId, m_moduleRelationMap[level])
{
QList<int> itemListTemp = GetDestModules(stepId, stepIdList);
foreach(int stepTemp, itemListTemp)
{
if (!itemListDest.contains(stepTemp))
{
itemListDest.push_back(stepTemp);
}
}
itemListTemp.clear();
}
foreach (int stepId, m_moduleRelationMap[level])
{
stepIdList.removeOne(stepId);
}
if (itemListDest.count() > 0)
{
++level;
foreach(int stepId, itemListDest)
{
m_moduleRelationMap[level].push_back(stepId);
}
itemListDest.clear();
}
stepIndex = 0;
}
}
QList<int> LayoutModuleCmd::GetDestModules(int stepId, QList<int> stepIdList)
{
QList<int> itemListDest;
itemListDest.clear();
CWorkFlowFile* pWorkflowFile = m_pWorkflow->GetWorkflowFile();
for (unsigned int j = 0; j < pWorkflowFile->GetModuleConnections()->size(); j++)
{
if (pWorkflowFile->GetModuleConnections()->at(j)->GetSourceId() == stepId)
{
int destStepId = pWorkflowFile->GetModuleConnections()->at(j)->GetDestId();
if (!itemListDest.contains(destStepId) && stepIdList.contains(destStepId))
{
itemListDest.push_back(destStepId);
}
}
}
return itemListDest;
}
QList<int> LayoutModuleCmd::GetSourceModules(int destStepId, QList<int> stepIdListSameLevel)
{
QList<int> itemListSource;
itemListSource.clear();
CWorkFlowFile* pWorkflowFile = m_pWorkflow->GetWorkflowFile();
for (unsigned int j = 0; j < pWorkflowFile->GetModuleConnections()->size(); j++)
{
if (pWorkflowFile->GetModuleConnections()->at(j)->GetDestId() == destStepId)
{
int srcStepId = pWorkflowFile->GetModuleConnections()->at(j)->GetSourceId();
if (stepIdListSameLevel.contains(srcStepId) && !itemListSource.contains(srcStepId))
{
itemListSource.push_back(srcStepId);
}
}
}
return itemListSource;
}
void LayoutModuleCmd::FindModulesWithSameSource(int stepId, QList<int> &sameSourceList, QList<int> stepIdList)
{
QList<int> sameSourceListTemp;
sameSourceListTemp.clear();
CWorkFlowFile* pWorkflowFile = m_pWorkflow->GetWorkflowFile();
for (unsigned int j = 0; j < pWorkflowFile->GetModuleConnections()->size(); j++)
{
if (pWorkflowFile->GetModuleConnections()->at(j)->GetDestId() == stepId)
{
int srcStepId = pWorkflowFile->GetModuleConnections()->at(j)->GetSourceId();
for(unsigned int k = 0; k < pWorkflowFile->GetModuleConnections()->size(); k++)
{
if (pWorkflowFile->GetModuleConnections()->at(k)->GetSourceId() == srcStepId)
{
if (pWorkflowFile->GetModuleConnections()->at(k)->GetDestId() != stepId)
{
int destId = pWorkflowFile->GetModuleConnections()->at(k)->GetDestId();
if (!sameSourceList.contains(destId) && stepIdList.contains(destId))
{
sameSourceListTemp.push_back(destId);
}
}
}
}
}
}
if (sameSourceListTemp.count() > 0)
{
foreach (int step, sameSourceListTemp)
{
if (!sameSourceList.contains(step))
{
sameSourceList.push_back(step);
stepIdList.removeOne(step);
}
}
for (int i = 0; i < sameSourceListTemp.count(); ++i)
{
FindModulesWithSameDest(sameSourceListTemp.at(i), sameSourceList, stepIdList);
}
}
}
void LayoutModuleCmd::FindModulesWithSameDest(int stepId, QList<int> &sameDestList, QList<int> stepIdList)
{
QList<int> sameDestListTemp;
sameDestListTemp.clear();
CWorkFlowFile* pWorkflowFile = m_pWorkflow->GetWorkflowFile();
for (unsigned int j = 0; j < pWorkflowFile->GetModuleConnections()->size(); j++)
{
if (pWorkflowFile->GetModuleConnections()->at(j)->GetSourceId() == stepId)
{
int destStepId = pWorkflowFile->GetModuleConnections()->at(j)->GetDestId();
for(unsigned int k = 0; k < pWorkflowFile->GetModuleConnections()->size(); k++)
{
if (pWorkflowFile->GetModuleConnections()->at(k)->GetDestId() == destStepId)
{
if (pWorkflowFile->GetModuleConnections()->at(k)->GetSourceId() != stepId)
{
int sourceId = pWorkflowFile->GetModuleConnections()->at(k)->GetSourceId();
if (!sameDestList.contains(sourceId) && stepIdList.contains(sourceId))
{
sameDestListTemp.push_back(sourceId);
}
}
}
}
}
}
if (sameDestListTemp.count() > 0)
{
foreach (int step, sameDestListTemp)
{
if (!sameDestList.contains(step))
{
sameDestList.push_back(step);
stepIdList.removeOne(step);
}
}
for (int i = 0; i < sameDestListTemp.count(); ++i)
{
FindModulesWithSameDest(sameDestListTemp.at(i), sameDestList, stepIdList);
}
}
}
ModuleGraphicsItem* LayoutModuleCmd::FindModule(int stepId, QList<ModuleGraphicsItem*> itemList)
{
for (int i = 0; i < itemList.count(); i++)
{
if (itemList.at(i)->GetModule()->GetStepID() == stepId)
{
return itemList.at(i);
}
}
return NULL;
}
QList<pai::graphics2d::ModuleGraphicsItem*> LayoutModuleCmd::GetModuleGraphicsItems(QList<int> stepIdList)
{
QList<ModuleGraphicsItem*> moduleList;
moduleList.clear();
foreach (int step, stepIdList)
{
ModuleGraphicsItem *pModule = GlobalWorkflowItems::GetInstance()->FindModule(m_pSceneManager, step);
if (pModule)
{
moduleList << pModule;
}
}
return moduleList;
}
QList<int> LayoutModuleCmd::GetModuleStepIdList(QList<pai::graphics2d::ModuleGraphicsItem*> moduleList)
{
QList<int> stepIdList;
stepIdList.clear();
foreach (ModuleGraphicsItem *pItem, moduleList)
{
stepIdList.push_back(pItem->GetModule()->GetStepID());
}
return stepIdList;
}
void LayoutModuleCmd::LayoutWorkflow()
{
//把item分类存储
CategorizedModule();
//获取模块item的链表
m_moduleList = GetModuleGraphicsItems(m_stepIdList);
//获取根Item的stepID
QList<int> topID = GetRootModule();
//分层存储Item
SetRelationMap(topID);
//布局module
LayoutModule();
// update the connection line position
updateConnectionLine();
}
void LayoutModuleCmd::CategorizedModule()
{
//目前本算法不支持部分排序,只支持全部item排序
m_list.clear();
m_list = m_pSceneManager->items();
//有被选中的item和workflow
if ( (0 == m_ModuleItemPosList.count()) && (0 == m_stepIdList.count()))
{
//m_list被选中的的item
if (m_list.count() < 2)
return;
// get top items position
for (int j = 0; j < m_list.count(); j++)
{
if (m_list.at(j)->type() == ModuleGraphicsItem::Type) // module item
{
QPointF pp = m_list.at(j)->pos();
m_ModuleItemPosList.append(pp);
ModuleGraphicsItem *moduleItem = dynamic_cast<ModuleGraphicsItem *> (m_list.at(j));
if (moduleItem)
{
m_stepIdList.push_back(moduleItem->GetModule()->GetStepID());
}
}
else if (m_list.at(j)->type() == ModuleConnectGraphicsItem::Type)
{
ModuleConnectGraphicsItem *pConnectItem = dynamic_cast<ModuleConnectGraphicsItem *> (m_list.at(j));
if (pConnectItem)
{
CModuleConnection *pConnect = new CModuleConnection();
pConnectItem->GetConnection()->CopyTo(*pConnect);
m_connectionList.push_back(pConnect);
}
}
}
}
}
QList<int> LayoutModuleCmd::GetRootModule()
{
//定义一个QHash,来存放层级关系
QHash<pai::graphics2d::ModuleGraphicsItem*,QList<pai::graphics2d::ModuleGraphicsItem*> > moduleItemHush;
//循环遍历m_moduleList
foreach(pai::graphics2d::ModuleGraphicsItem* pItem,m_moduleList)
{
//获取pItem的孩子
int stepItem = pItem->GetModule()->GetStepID();
QList<int> relationStepID = GetDestModules(stepItem,m_stepIdList);
QList<pai::graphics2d::ModuleGraphicsItem*> itemLst = GetModuleGraphicsItems(relationStepID);
moduleItemHush.insert(pItem,itemLst);
}
QHash<pai::graphics2d::ModuleGraphicsItem*,QList<pai::graphics2d::ModuleGraphicsItem*> >::iterator it_start = moduleItemHush.begin();
QHash<pai::graphics2d::ModuleGraphicsItem*,QList<pai::graphics2d::ModuleGraphicsItem*> >::iterator it_end = moduleItemHush.end();
QList<QList<pai::graphics2d::ModuleGraphicsItem*> > values = moduleItemHush.values();
QList<ModuleGraphicsItem *> topModule;
//获取最顶层的Item
bool flag = false;
while(it_start != it_end)
{
flag = false;
for(int i = 0; i < values.count();++i)
{
if(values.at(i).contains(it_start.key()))
{
flag = true;
}
}
if(!flag)
{
topModule.push_back(it_start.key());
}
++it_start;
}
//最后排序完成的stepID的容器
QList<int> topStepId;
//获取第二层的module的stepID和mudule
QList<int> destID;
pai::graphics2d::ModuleGraphicsItem *destModule = NULL;
if(!topModule.isEmpty())
{
destID = GetDestModules(topModule.at(0)->GetModule()->GetStepID(),m_stepIdList);
if(!destID.isEmpty())
{
destModule = FindModule(destID.at(0),m_moduleList);
}
}
//获取第二层的module的输入端口数量
int inputPortCount = 0;
if(destModule)
{
inputPortCount = destModule->GetInputPortCount();
}
//端口号对应的源stepID的容器
QMap<int,int> tmpMap;
if(inputPortCount > 1)
{
//获取第二层moudule每个输入端口对应的源
if(m_pWorkflow)
{
CWorkFlowFile* pWorkflowFile = m_pWorkflow->GetWorkflowFile();
if(pWorkflowFile)
{
for (unsigned int j = 0; j < pWorkflowFile->GetModuleConnections()->size(); j++)
{
if ((!destID.isEmpty()) && (pWorkflowFile->GetModuleConnections()->at(j)->GetDestId() == destID.at(0)))
{
std::string inputPort = pWorkflowFile->GetModuleConnections()->at(j)->GetInPort();
QString str(inputPort.c_str());
bool ok;
int num = str.toInt(&ok);
if(ok)
{
tmpMap[num] = pWorkflowFile->GetModuleConnections()->at(j)->GetSourceId();
}
}
}
}
}
//排序stepID
QList<int> keys = tmpMap.keys();
qSort(keys.begin(),keys.end(),qLess<int>());
for(int i = 0; i < keys.count(); ++i)
{
topStepId.push_back(tmpMap[keys.at(i)]);
}
}
else
{
//这里处理只有一个输入时的情况
if(!topModule.isEmpty())
{
topStepId.push_back(topModule.at(0)->GetModule()->GetStepID());
}
}
return topStepId;
}
void LayoutModuleCmd::SetRelationMap(QList<int> topID)
{
//树的先根遍历
QList<int> stepIdListAdjusted;
stepIdListAdjusted = topID;
if(!stepIdListAdjusted.isEmpty())
{
GetDestModulesRecursive(stepIdListAdjusted.at(0),stepIdListAdjusted,m_stepIdList);
}
//放入模块分层信息表
m_moduleRelationMap.clear();
int level = 0;
QList<int> stepIdSrc;
if(!stepIdListAdjusted.isEmpty())
{
stepIdSrc = topID;
}
QList<int> stepIdTemp;
while(stepIdListAdjusted.count() > 0)
{
stepIdTemp.clear();
//删除重复
for(int i = 1; i <= m_moduleRelationMap.count(); ++i)
{
foreach(int j,stepIdSrc)
{
if(m_moduleRelationMap[i].contains(j))
{
stepIdSrc.removeOne(j);
}
}
}
//源item
m_moduleRelationMap[++level] = stepIdSrc;
foreach(int st, stepIdSrc)
{
stepIdTemp += GetDestModules(st, stepIdListAdjusted);
}
//同目标去除重复
if(!stepIdTemp.isEmpty())
{
for(int i = 0; i < stepIdTemp.count(); ++i)
{
for(int j = 0; j < stepIdTemp.count(); ++j)
{
if(i != j && stepIdTemp[i] == stepIdTemp[j])
{
stepIdTemp.removeOne(stepIdTemp[j]);
--j;
}
}
}
}
//如果没有目标了,说明到结尾了
if(stepIdTemp.isEmpty())
{
if(!stepIdListAdjusted.isEmpty())
{
stepIdListAdjusted.clear();
}
break;
}
//删除用完的源
foreach(int stID,stepIdSrc)
{
if(stepIdListAdjusted.contains(stID))
{
stepIdListAdjusted.removeOne(stID);
}
}
//下一次的源是这一次的目标
stepIdSrc.clear();
stepIdSrc = stepIdTemp;
}
}
void LayoutModuleCmd::LayoutModule()
{
//模块的高度和宽度
m_moduleSceneRectWidth = m_moduleList.at(0)->sceneBoundingRect().width();
m_moduleSceneRectHeight = m_moduleList.at(0)->sceneBoundingRect().height();
//所有模块中某一层最大item的数量
m_maxWidth = GetMaxWidth();
//建立网格图,准备计算存放坐标
int GridWidth =m_maxWidth*m_moduleSceneRectWidth + nDefaultIntervalX*(m_maxWidth-1);
QMap<int,QList<int> > coordinates;
QList<int> tmp;
for (int i = 0; i < coordinates.count(); ++i)
{
coordinates[i].clear();
}
coordinates.clear();
for (int i = 1; i <= m_maxWidth; ++i)
{
tmp.clear();
for(int j = 1; j <= i;++j)
{
tmp.append(DEFAULT_XPOSITION + (j-1)*(GridWidth/i) + GridWidth/(2*i));
}
coordinates[i] = tmp;
}
//调整item位置
QList<int> id;
for(int i = 1; i <= m_moduleRelationMap.count(); ++i)
{
id.clear();
id = m_moduleRelationMap[i];
int count = m_moduleRelationMap[i].count();
for(int j = 1; j <= count; ++j)
{
int dest = m_moduleRelationMap[i].at(j-1);
ModuleGraphicsItem *pModule = FindModule(dest, m_moduleList);
if(pModule)
{
qreal posX = coordinates[count].at(j-1);
qreal posY = nDefaultIntervalY*i + m_moduleSceneRectHeight*(i-1);
QPointF pos(posX,posY);
PaiModuleStyle *pStyle = pModule->GetModuleStyle();
if(pStyle)
{
pStyle->SetPosition(pos, pModule);
}
}
}
}
}
}