/* * LayoutModuleCmd.cpp * * Created on: 2012-10-10 * Author: limengzhuo */ #include #include #include #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 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; QListmoduleList = 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 &stepIdListAdjusted, QList stepIdList) { QList 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 LayoutModuleCmd::GetModuleGraphicsItemsFromStepId(QList stepIdList) { QList 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 &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 itemListSameSrc; itemListSameSrc.clear(); itemListSameSrc.push_back(step); FindModulesWithSameSource(step, itemListSameSrc, stepIdList); m_moduleRelationMap[++level]= itemListSameSrc; foreach(int stepSameSrc, itemListSameSrc) { QList 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 itemListDest; itemListDest.clear(); foreach(int stepId, m_moduleRelationMap[level]) { QList 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 LayoutModuleCmd::GetDestModules(int stepId, QList stepIdList) { QList 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 LayoutModuleCmd::GetSourceModules(int destStepId, QList stepIdListSameLevel) { QList 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 &sameSourceList, QList stepIdList) { QList 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 &sameDestList, QList stepIdList) { QList 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 itemList) { for (int i = 0; i < itemList.count(); i++) { if (itemList.at(i)->GetModule()->GetStepID() == stepId) { return itemList.at(i); } } return NULL; } QList LayoutModuleCmd::GetModuleGraphicsItems(QList stepIdList) { QList moduleList; moduleList.clear(); foreach (int step, stepIdList) { ModuleGraphicsItem *pModule = GlobalWorkflowItems::GetInstance()->FindModule(m_pSceneManager, step); if (pModule) { moduleList << pModule; } } return moduleList; } QList LayoutModuleCmd::GetModuleStepIdList(QList moduleList) { QList 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 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 (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 (m_list.at(j)); if (pConnectItem) { CModuleConnection *pConnect = new CModuleConnection(); pConnectItem->GetConnection()->CopyTo(*pConnect); m_connectionList.push_back(pConnect); } } } } } QList LayoutModuleCmd::GetRootModule() { //定义一个QHash,来存放层级关系 QHash > moduleItemHush; //循环遍历m_moduleList foreach(pai::graphics2d::ModuleGraphicsItem* pItem,m_moduleList) { //获取pItem的孩子 int stepItem = pItem->GetModule()->GetStepID(); QList relationStepID = GetDestModules(stepItem,m_stepIdList); QList itemLst = GetModuleGraphicsItems(relationStepID); moduleItemHush.insert(pItem,itemLst); } QHash >::iterator it_start = moduleItemHush.begin(); QHash >::iterator it_end = moduleItemHush.end(); QList > values = moduleItemHush.values(); QList 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 topStepId; //获取第二层的module的stepID和mudule QList 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 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 keys = tmpMap.keys(); qSort(keys.begin(),keys.end(),qLess()); 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 topID) { //树的先根遍历 QList stepIdListAdjusted; stepIdListAdjusted = topID; if(!stepIdListAdjusted.isEmpty()) { GetDestModulesRecursive(stepIdListAdjusted.at(0),stepIdListAdjusted,m_stepIdList); } //放入模块分层信息表 m_moduleRelationMap.clear(); int level = 0; QList stepIdSrc; if(!stepIdListAdjusted.isEmpty()) { stepIdSrc = topID; } QList 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 > coordinates; QList 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 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); } } } } } }