logplus/ModuleConsole/command/src/LayoutModuleCmd.cpp
2026-01-16 17:18:41 +08:00

703 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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);
}
}
}
}
}
}