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

612 lines
23 KiB
C++

/*
* AddModuleCmd.cpp
*
* Created on: 2012-10-10
* Author: limengzhuo
*/
#include <QDebug>
#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<pai::graphics2d::ModuleGraphicsItem*> (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<workflow::CModuleConnection*> 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<ModuleGraphicsItem *>(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<QGraphicsItem *> 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<ModuleConnectGraphicsItem *>(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;
}
}