/* * AddModuleCmd.cpp * * Created on: 2012-10-10 * Author: limengzhuo */ #include #include "PELibraryModule.h" #include "AddModuleCmd.h" #include "WellLogWorkflowDataModel.h" #include "ModuleGraphicsItem.h" #include "ModuleConnectGraphicsItem.h" #include "PaiWorkflowDataModel.h" #include "WorkflowConst.h" #include "WorkflowSceneManager.h" #include "ModuleConnection.h" #include "ModuleInformation.h" #include "ConsoleGUIService.h" #include "DeleteModuleCmd.h" #include "Log.h" #include "PAIConst.h" #include "GlobalWorkflowItems.h" #include "AddLineCmd.h" #include "TimeStampLogger.h" #include "GlobalModuleBackup.h" #include "AddLineCmd.h" #include "BreakLineCmd.h" #include "AddLineCmd.h" #include "PaiMessageBox.h" #include "ConsoleGUIService.h" #include "LogModuleConsole.h" //向上或者向下或者拖拽添加模块时,模块间默认距离 const int DEFAULTSTEP = 40; using namespace pai; using namespace pai::graphics2d; using namespace pai::workflow; namespace pai { AddModuleCmd::AddModuleCmd(WorkflowSceneManager *pSceneManager, pai::objectmodel::PaiWorkflowDataModel *pWorkflow, QString moduleName, QUndoCommand *parent) :QUndoCommand(parent) { m_type = AddModuleType_General; m_pWorkflow = pWorkflow; m_pScene = pSceneManager; m_moduleClassName = moduleName; m_selectedModuleStepId = 0; m_bModuleSelected = true; m_bFirstRedo = true; } AddModuleCmd::AddModuleCmd(WorkflowSceneManager *pSceneManager, pai::objectmodel::PaiWorkflowDataModel *pWorkflow, QString moduleName, ModuleGraphicsItem *pSelectedItem, bool before, QUndoCommand *parent) :QUndoCommand(parent) { if (before) { m_type = AddModuleType_Before; } else { m_type = AddModuleType_After; } m_pWorkflow = pWorkflow; m_pScene = pSceneManager; m_moduleClassName = moduleName; m_selectedModuleStepId = pSelectedItem->GetModule()->GetStepID(); m_addedModuleStepId = 0; m_bModuleSelected = true; m_bFirstRedo = true; } AddModuleCmd::AddModuleCmd(WorkflowSceneManager *pSceneManager, pai::objectmodel::PaiWorkflowDataModel *pWorkflow, QString moduleName, QPointF pos, QUndoCommand *parent) :QUndoCommand(parent) { m_type = AddModuleType_Drop; m_pWorkflow = pWorkflow; m_pScene = pSceneManager; m_moduleClassName = moduleName; m_selectedModuleStepId = 0; m_eventPos = pos; m_bModuleSelected = true; m_bFirstRedo = true; } AddModuleCmd::~AddModuleCmd() { if(m_AddLineLst.size() > 0) { qDeleteAll(m_AddLineLst); m_AddLineLst.clear(); } if(m_BreakLineLst.size() > 0) { qDeleteAll(m_BreakLineLst); m_BreakLineLst.clear(); } } void AddModuleCmd::undo() { if(!m_pScene) { return; } m_pScene->SetFocusViewport(); DeleteModule(); } void AddModuleCmd::redo() { pai::gui::TimeStampLogger::GetInstance().WriteGUIBenchMarkLog("Workflow", true, "Add module to scene"); if(!m_pScene) { return; } m_pScene->SetFocusViewport(); AddModule(); pai::gui::TimeStampLogger::GetInstance().WriteGUIBenchMarkLog("Workflow", false, "Add module to scene"); } ModuleGraphicsItem* AddModuleCmd::GetMostBottomItem(QGraphicsItem *pModuleItem) { ModuleGraphicsItem* pMostBottomItem = NULL; foreach(QGraphicsItem* pItem, m_pScene->items()) { if (pItem->type() == pai::graphics2d::ModuleGraphicsItem::Type) { pai::graphics2d::ModuleGraphicsItem* pLoopModuleItem = dynamic_cast (pItem); if (pLoopModuleItem && pItem != pModuleItem ) { if (NULL == pMostBottomItem) { pMostBottomItem = pLoopModuleItem; } else { if(pLoopModuleItem->pos().y() > pMostBottomItem->pos().y()) { pMostBottomItem = pLoopModuleItem; } } } } } return pMostBottomItem; } void AddModuleCmd::HandleMostBottomItem(ModuleGraphicsItem *pModuleItem, ModuleGraphicsItem *pMostBottomItem) { //在场景中最下方模块的下方添加模块 if( pMostBottomItem && pMostBottomItem != pModuleItem ) { // if the source module item is no output port return if( pMostBottomItem->GetOutputPortCount() == 0||pModuleItem->GetInputPortCount() == 0) { return; } AddLine(pMostBottomItem,pModuleItem); } } void AddModuleCmd::DeleteConnectLineAndAddNew(ModuleGraphicsItem* pModuleItem,ModuleConnectGraphicsItem *pItem, ModuleGraphicsItem *pStartModuleItem, ModuleGraphicsItem *pEndModuleItem) { // 删除被拖拽的模块图元所覆盖的连接线,同时填加其上下连接线(如果需要的话) if(!pItem) { return; } // get connection item's start module,end module ,start port index and end port index // remove the connection if(0 == m_BreakLineLst.size()) { QList connection; connection << (pItem->GetConnection()); pai::BreakLineCmd *pBreakLineCmd = new pai::BreakLineCmd(m_pWorkflow,m_pScene,connection); m_BreakLineLst.push_back(pBreakLineCmd); } if(m_BreakLineLst.size()>0) { m_BreakLineLst.at(0)->redo(); } // build the new connection if ((pModuleItem->GetInputPortCount() >= 1) && (pModuleItem != pStartModuleItem)) // the added module input port exist { AddLine(pStartModuleItem,pModuleItem); } if ((pModuleItem->GetOutputPortCount() >= 1) && (pModuleItem != pEndModuleItem)) // the added module output port exist { AddLine(pModuleItem,pEndModuleItem); } } void AddModuleCmd::MoveGraphicItems(ModuleGraphicsItem *pModuleItem, ModuleGraphicsItem *pStartModuleItem, ModuleGraphicsItem *pEndModuleItem) { if (pStartModuleItem == NULL || pEndModuleItem == NULL) { return; } // determine move step qreal move_step = (DEFAULTSTEP + pStartModuleItem->GetSize().height()); // need move the workflow item if (move_step > 0.0) { //首先把开始和结束item的位置调整好 if (m_type == AddModuleType_Before) { MoveAddedModulePosition(pEndModuleItem,pStartModuleItem,-move_step); } if (m_type == AddModuleType_After) { MoveAddedModulePosition(pStartModuleItem,pEndModuleItem,move_step); } if(m_type == AddModuleType_Drop) { //如果开始模块和被添加模块碰撞 if(pStartModuleItem->sceneBoundingRect().bottomLeft().y() >= pModuleItem->sceneBoundingRect().topLeft().y()) { MoveAddedModulePosition(pStartModuleItem,pModuleItem,move_step); } //如果被添加模块和结束模块碰撞 if(pModuleItem->sceneBoundingRect().bottomLeft().y() >= pEndModuleItem->sceneBoundingRect().topLeft().y()) { MoveAddedModulePosition(pModuleItem,pEndModuleItem,move_step); } } //调整水平方向可能和被添加模块碰撞的模块 if(m_type == AddModuleType_After || m_type == AddModuleType_Before) { //确定被添加模块以及位置信息 ModuleGraphicsItem *pItem = (m_type == AddModuleType_Before)?pStartModuleItem:pEndModuleItem; QPointF pos = pItem->pos(); qreal topRightY = pItem->sceneBoundingRect().topRight().y(); qreal bottomRightY = pItem->sceneBoundingRect().bottomRight().y(); qreal horizontalStep = pEndModuleItem->GetSize().width() + 10; //循环遍历所有模块 for (int j = 0; j < m_pScene->items().count(); j++) { //当前模块的位置和sceneBoundingRect QPointF currentModulePos = m_pScene->items().at(j)->pos(); QRectF currentModuleRect = m_pScene->items().at(j)->sceneBoundingRect(); //如果当前模块不是开始和结束模块 if (m_pScene->items().at(j)->type() == ModuleGraphicsItem::Type && m_pScene->items().at(j) != pStartModuleItem && m_pScene->items().at(j) != pEndModuleItem && m_pScene->items().at(j) != pModuleItem) { //在X轴方向可能碰撞的条件 if((topRightY >= currentModuleRect.topLeft().y() && topRightY <= currentModuleRect.bottomLeft().y()) || (bottomRightY >= currentModuleRect.topLeft().y() && bottomRightY <= currentModuleRect.bottomLeft().y())) { if(pos.x() <= currentModulePos.x()) { pos.setX(currentModulePos.x()+horizontalStep); pItem->setPos(pos); m_pWorkflow->GetModuleStyle(pItem->GetModule()->GetStepID())->SetPosition(pos); } if(pos.x() > currentModulePos.x() && m_pScene->items().at(j)->collidesWithItem(pItem)) { pos.setX(pos.x()+horizontalStep); pItem->setPos(pos); m_pWorkflow->GetModuleStyle(pItem->GetModule()->GetStepID())->SetPosition(pos); } } } } } //调整场景中其它的item位置,只有当被添加模块与已经存在的模块可能碰撞时,才调整已经存在模块位置(垂直方向) for (int j = 0; j < m_pScene->items().count(); j++) { if (m_pScene->items().at(j)->type() == ModuleGraphicsItem::Type && m_pScene->items().at(j) != pStartModuleItem && m_pScene->items().at(j) != pEndModuleItem && m_pScene->items().at(j) != pModuleItem) { ModuleGraphicsItem *pItem = (m_type == AddModuleType_Before)?pStartModuleItem:pEndModuleItem; QPointF currentModulePos = m_pScene->items().at(j)->pos(); QRectF currentModuleRect = m_pScene->items().at(j)->sceneBoundingRect(); qreal currentTopLeftX = currentModuleRect.topLeft().x(); qreal currentTopRightX = currentModuleRect.topRight().x(); QPointF startOrEndItemPos = pItem->pos(); QRectF startOrEndItemRect = pItem->sceneBoundingRect(); qreal topLeftX = startOrEndItemRect.topLeft().x(); qreal topRightX = startOrEndItemRect.topRight().x(); //可能碰撞的条件 if((currentTopLeftX >= topLeftX && currentTopLeftX <= topRightX) || (currentTopRightX >= topLeftX && currentTopRightX <= topRightX)) { if((currentModulePos.y() >= startOrEndItemPos.y()) && (m_type == AddModuleType_After ||m_type == AddModuleType_Drop)) { currentModulePos.setY(currentModulePos.y() + move_step); } else if((currentModulePos.y() <= startOrEndItemPos.y()) && m_type == AddModuleType_Before) { currentModulePos.setY(currentModulePos.y() - move_step); } // reset the item position(must do that) m_pScene->items().at(j)->setPos(currentModulePos); ModuleGraphicsItem *moduleItem = dynamic_cast(m_pScene->items().at(j)); if (moduleItem && moduleItem->GetModule()) { // reset the item style position in workflow data model m_pWorkflow->GetModuleStyle(moduleItem->GetModule()->GetStepID())->SetPosition(currentModulePos); m_pScene->ExpandSceneRectIfNeeded(moduleItem->GetModule()->GetStepID()); } } } } } } void AddModuleCmd::HandleCollidingItems(ModuleGraphicsItem *pModuleItem) { if (!pModuleItem) { return; } //被添加模块的碰撞Item QList CollidingItems = pModuleItem->collidingItems(); ModuleGraphicsItem *pStartModuleItem = NULL; ModuleGraphicsItem *pEndModuleItem = NULL; if(m_type == AddModuleType_Drop) { for (int i = 0; i < CollidingItems.count(); i++) { if (CollidingItems.at(i)->type() == ModuleConnectGraphicsItem::Type) { pai::graphics2d::ModuleConnectGraphicsItem *pItem = dynamic_cast(CollidingItems.at(i)); pStartModuleItem = pItem->GetStartItem(); pEndModuleItem = pItem->GetEndItem(); DeleteConnectLineAndAddNew(pModuleItem, pItem, pStartModuleItem, pEndModuleItem); break; // break the for loop } } } MoveGraphicItems(pModuleItem, pStartModuleItem, pEndModuleItem); } void AddModuleCmd::SetPosition(ModuleGraphicsItem *pModuleItem, QPointF pos) { if (pModuleItem && pModuleItem->GetModule()) { // 设置加入模块的位置 pai::graphics2d::PaiModuleStyle* pStyle = m_pWorkflow->GetModuleStyle(pModuleItem->GetModule()->GetStepID()); if (pStyle != NULL) { pStyle->SetPosition(pos, pModuleItem); } } } void AddModuleCmd::AddModule() { try { //根据模块名称构造模块信息 CModuleInformation* pCloneModule = new CModuleInformation(m_moduleClassName.toStdString()); if (!pCloneModule) { return; } CWellLogWorkflowDataModel *p=(CWellLogWorkflowDataModel *)m_pWorkflow; //工作流中添加模块信息 if(p) { p->m_pModule=pCloneModule->GetModule(); } m_pWorkflow->AddModule(pCloneModule); //在场景中添加模块 m_pScene->AddModule(pCloneModule,m_pWorkflow->GetModuleStyle(pCloneModule->GetStepID())); //被添加模块的StepID m_addedModuleStepId = pCloneModule->GetStepID(); //获取被添加的模块并隐藏 ModuleGraphicsItem* pModuleItem = m_pScene->FindModule(m_addedModuleStepId); pModuleItem->hide(); //获取场景中被选择的模块 ModuleGraphicsItem* pSelectedItem = m_pScene->FindModule(m_selectedModuleStepId); switch(m_type) { case AddModuleType_Before: case AddModuleType_After: { if (m_type == AddModuleType_Before) { if(!AddLine(pModuleItem,pSelectedItem)) { undo(); m_bFirstRedo = false; return; } } else { if(!AddLine(pSelectedItem,pModuleItem)) { undo(); m_bFirstRedo = false; return; } } //调整所有模块的位置 LayoutAllModules(pModuleItem,pSelectedItem); } break; case AddModuleType_Drop: { LayoutAllModules(pModuleItem,NULL); // 调整工作流中其他模块的位置 if (!m_moduleClassName.isEmpty()) //No need to delete line and add new lines while the new added item is a blank module. { HandleCollidingItems(pModuleItem); } } break; case AddModuleType_General: default: { //获取y坐标值最大的模块 ModuleGraphicsItem* pMostBottomItem = GetMostBottomItem(pModuleItem); LayoutAllModules(pModuleItem,pMostBottomItem); HandleMostBottomItem(pModuleItem, pMostBottomItem); } break; } //显示模块 pModuleItem->show(); m_pScene->clearSelection(); m_pScene->ExpandSceneRectIfNeeded(pModuleItem->GetModule()->GetStepID()); pModuleItem->setFocus(); pModuleItem->setSelected(true); pModuleItem->update(); pModuleItem->ensureVisible();//确保新加模块可见 //添加模块成功以后,打开模块参数信息 if(pModuleItem) { m_pScene->OpenModuleParam(pModuleItem->GetModule()); } //处理双击添加模块 if (pCloneModule->IsBlankModule()) { pai::graphics2d::ModuleGraphicsItem::m_EventAgent.ItemSetName(pModuleItem); } } catch (pai::error::generic_error &exeption) { QString strMessage = QString("Paste connect line caught an exception. ").append(exeption.what()); pai::gui::PaiMessageBox::Critical(NULL, PAI_NAME, strMessage); pai::log::Error(_FLF(QObject::tr("QUndoCommand::ShowMessage ").toStdString()+strMessage.toStdString())); } m_bFirstRedo = false; } void AddModuleCmd::DeleteModule() { pai::graphics2d::ModuleGraphicsItem* pModuleItem = GlobalWorkflowItems::GetInstance()->FindModule(m_pScene, m_addedModuleStepId); if (pModuleItem) { m_bModuleSelected = pModuleItem->isSelected(); } workflow::CModuleInformation *pAddedModule = m_pWorkflow->GetModuleByStepID(m_addedModuleStepId); if (pAddedModule) { foreach(pai::AddLineCmd *pAddLineCmd,m_AddLineLst) { pAddLineCmd->undo(); } GetGlobalModuleBackup()->RemoveBackupModule(m_pWorkflow->GetID(), pAddedModule); m_pScene->DeleteModule(pAddedModule->GetStepID()); m_pWorkflow->RemoveModule(pAddedModule); GetGlobalModuleBackup()->UpdateBackupModuleStepIDs(m_pWorkflow->GetID()); foreach(pai::BreakLineCmd *pBreakLineCmd,m_BreakLineLst) { pBreakLineCmd->undo(); } } } void AddModuleCmd::MoveAddedModulePosition(pai::graphics2d::ModuleGraphicsItem *pRelativeItem, pai::graphics2d::ModuleGraphicsItem *pAddedItem,qreal step) { if(pRelativeItem && pAddedItem) { //获取相对模块位置 QPointF modulePos = pRelativeItem->pos(); modulePos.setY(modulePos.y() + step); // 设置被移动模块的y坐标 pAddedItem->setPos(modulePos); if (pAddedItem && pAddedItem->GetModule()) { //设置被移动模块的坐标和根据实际情况扩充场景 m_pWorkflow->GetModuleStyle(pAddedItem->GetModule()->GetStepID())->SetPosition(modulePos); } } } void AddModuleCmd::LayoutAllModules(ModuleGraphicsItem *pAddedModule,ModuleGraphicsItem *pSelectedModule) { if(!pAddedModule) { return; } QPointF AddedModulePos; if(pSelectedModule) { AddedModulePos = pSelectedModule->pos(); } switch(m_type) { case AddModuleType_Before: { //确定模块在工作流中的位置 qreal ypos = AddedModulePos.y() - pSelectedModule->GetSize().height() - DEFAULTSTEP; AddedModulePos.setY(ypos); SetPosition(pAddedModule, AddedModulePos); // 调整工作流中其他模块的位置 MoveGraphicItems(NULL,pAddedModule, pSelectedModule); } break; case AddModuleType_After: { // 确定模块在工作流中的位置 qreal ypos = AddedModulePos.y() + pSelectedModule->GetSize().height() + DEFAULTSTEP; AddedModulePos.setY(ypos); SetPosition(pAddedModule, AddedModulePos); // 调整工作流中其他模块的位置 MoveGraphicItems(NULL,pSelectedModule, pAddedModule); } break; case AddModuleType_Drop: { SetPosition(pAddedModule, m_eventPos); } break; case AddModuleType_General: { //如果场景中不存在其它模块,被添加模块的默认位置 QPointF pos(280, 110); if(pSelectedModule) { pos.setX(pSelectedModule->pos().x()); pos.setY(pSelectedModule->pos().y() + pAddedModule->GetSize().height() + DEFAULTSTEP); } SetPosition(pAddedModule, pos); } break; default: { //do nothing } } } bool AddModuleCmd::AddLine(ModuleGraphicsItem *pBeginModule, ModuleGraphicsItem *pEndModule) { if(!pBeginModule || !pEndModule) { return false; } bool result = true; //添加连线 if(m_bFirstRedo) { AddLineCmd *pAddLineCmd = new AddLineCmd(m_pScene, m_pWorkflow, pBeginModule, pEndModule); m_AddLineLst.push_back(pAddLineCmd); } if(m_AddLineLst.size() > 0) { //设置连线的开始和结束模块的stepID if(pBeginModule->GetModule() && pEndModule->GetModule()) { m_AddLineLst.last()->SetFirstStepID(pBeginModule->GetModule()->GetStepID()); m_AddLineLst.last()->SetSecondStepID(pEndModule->GetModule()->GetStepID()); } //添加连线命令的redo操作 m_AddLineLst.last()->redo(); if (m_AddLineLst.last()->GetPortHasbeenLined()) { result = false; } } return result; } }