/** * @file SaveAsWorkflowCmd.cpp * @date 2012-10-17 */ #include #include #include "PaiObject.h" #include "PaiSurvey.h" #include "PaiWorkflowDataModel.h" #include "WorkflowConst.h" #include "PaiBalloonTipSettings.h" #include "PaiBalloonTip.h" #include "ObjectModelService.h" #include "PaiMessageBox.h" #include "PAIConst.h" #include "ViewExtension.h" #include "PaiWorkflowMaster.h" #include "SaveAsWorkflowCmd.h" #include "SaveHelper.h" #include "WorkflowWidget.h" #include "ConsoleGUIService.h" #include "PaiGUIService.h" #include "PaiActionsHistory.h" #include "WorkFlowFile.h" #include "PaiObjectSelection.h" #include "GlobalUtility.h" using namespace pai::workflow; using namespace pai; using namespace pai::objectmodel; using namespace pai::gui; using namespace pai::graphics2d; SaveAsWorkflowCmd::SaveAsWorkflowCmd(QUuid viewID, PaiWorkflowDataModel *pActiveWorkflow, QUndoCommand *pParent) : QUndoCommand(pParent), m_ViewID(viewID), m_pSurvey(NULL), m_pOldWorkflow(NULL), m_pOldSameNameWorkflow(NULL), m_SaveType(SaveType_DoCancel), m_SaveSuccess(true), m_pActiveWorkflow(pActiveWorkflow) { } SaveAsWorkflowCmd::~SaveAsWorkflowCmd() { } void SaveAsWorkflowCmd::undo() { } void SaveAsWorkflowCmd::redo() { if(!m_pActiveWorkflow) { return; } m_SaveSuccess = HandleSaveAsWorkflow(); // 如果保存工作流成功,则为其再添加一条“Edit”历史记录 if(m_SaveSuccess) { PaiWorkflowDataModel *pWorkflow = m_pActiveWorkflow; if(pWorkflow) { PageService* pPageService = GetConsoleGUIService()->GetViewTabService()->GetPageService(m_ViewID); // 获取数据树上工作流并且设置新名称 PaiObject *pDataTreeWorkflow = GetObjectModelService()->GetObject(pWorkflow->GetDBID()); if(pPageService && pDataTreeWorkflow) { pPageService->SetSubtilte(pDataTreeWorkflow->GetVisibleFile()); } ActionHistroy history; history.node = pWorkflow->GetVisibleFile(); history.icon = pWorkflow->GetIconName().section('/', -1); history.action = QObject::tr("Edit..."); GetPaiGUIService()->GetActionsHistory()->AppendExtraHistory(history); } } } bool SaveAsWorkflowCmd::GetSaveAsResult() const { return m_SaveSuccess; } void SaveAsWorkflowCmd::CopyWorkflow() { if(m_pOldWorkflow == NULL) { return; } // 创建新工作流模型 PaiWorkflowDataModel *pNewWorkflow = new PaiWorkflowDataModel(); // 拷贝当前工作流模型到新工作流模型 pNewWorkflow->Copy(*m_pOldWorkflow); pNewWorkflow->SetEventEnabled(true); // 设置新的工作流模型为ActiveWorkflow m_pActiveWorkflow = pNewWorkflow; // 数据树上的虚拟的PaiObject,现在先这么做,后边再整改 PaiWorkflowDataModel *pDataTreeWorkflow = new PaiWorkflowDataModel(); // 新建的工作流不用和数据库同步 pDataTreeWorkflow->SetIgnoreSyncDB(true); pDataTreeWorkflow->SetSyncabled(false); pDataTreeWorkflow->SetDBID(pNewWorkflow->GetDBID()); pDataTreeWorkflow->SetID(pNewWorkflow->GetID()); pDataTreeWorkflow->SetName(m_NewWorkflowName); if(m_pSurvey && m_pSurvey->GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString()))) { m_pSurvey->GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString()))->AddChild(pDataTreeWorkflow); } } void SaveAsWorkflowCmd::RestoreWorkflow() { if(!m_pActiveWorkflow) { return; } // 如果另存为同一工作流,则无需restore if((m_pOldWorkflow == NULL) || (m_pOldWorkflow == m_pActiveWorkflow)) { return; } // save failed restore if(!(m_SaveType & SaveType_IsNewWorkflow) && !(m_SaveType & SaveType_IsCurrentWorkflow)) { PaiWorkflowDataModel *pNewWorkflow = m_pActiveWorkflow; if(m_pOldWorkflow->GetParent()) { m_pOldWorkflow->GetParent()->RemoveChild(pNewWorkflow, true); } else if(m_pSurvey && m_pSurvey->GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString()))) { m_pSurvey->GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString()))->RemoveChild(pNewWorkflow, true); } delete pNewWorkflow; } } PaiObject* SaveAsWorkflowCmd::GetOldSameNameWorkflow() const { if(m_pSurvey && m_pSurvey->GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString()))) { return m_pSurvey->GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString()))->GetObjectByName(m_NewWorkflowName); } return NULL; } bool SaveAsWorkflowCmd::HandleExtensionTabAndNodeSelection() { if(!m_pActiveWorkflow) { return false; } PageService *pPageService = GetConsoleGUIService()->GetViewTabService()->GetPageService(m_ViewID); if(pPageService) { std::string oldWorkflowID = m_pOldWorkflow->GetID().toString().toStdString(); // 找到要重设工作流模型的Extension ViewExtension *pViewExtension = dynamic_cast< ViewExtension* > (pPageService->GetExtension(oldWorkflowID)); // 备份的当前工作流并没有打开编辑界面,即作业界面的SaveAs if(NULL == pViewExtension) { delete m_pActiveWorkflow; m_pActiveWorkflow = NULL; } else { // 备份的当前工作流有打开编辑界面 选中保存后的工作流左侧节点 GetObjectModelService()->GetObjectSelection()->Select(m_pActiveWorkflow->GetID(), true); } // 为当前工作流编辑界面或者SaveType_IsJobSave情况下打开了同名的工作流编辑界面重设工作流模型 if(pViewExtension) { WorkflowWidget *pFindWorkflowWidget = GetFirstChildObject< WorkflowWidget > (dynamic_cast< QWidget* > (pViewExtension->GetView())); if(pFindWorkflowWidget) { pFindWorkflowWidget->SetWorkflow(m_pActiveWorkflow); } std::string workflowID = m_pActiveWorkflow->GetID().toString().toStdString(); try { // 修改tab页的名字,重新注册 pPageService->CService::Unregister(oldWorkflowID); pViewExtension->SetViewID(workflowID); pPageService->CService::Register(pViewExtension, ILocation()); pPageService->SetTabText("A", workflowID, m_pActiveWorkflow->GetName()); } catch(pai::error::generic_error & e) { QString errorMsg = QString("SaveAs Workflow caught an exception. ").append(e.what()); PaiMessageBox::Critical(::GetConsoleGUIService()->GetMainWindow(), PAI_NAME, errorMsg); pai::log::Error(_FLF(QObject::tr("QUndoCommand::ShowMessage ").toStdString() + errorMsg.toStdString())); return false; } } } else { delete m_pActiveWorkflow; m_pActiveWorkflow = NULL; } return true; } bool SaveAsWorkflowCmd::HandleSaveAsWorkflow() { // 如果当前工作流为空直接返回 if(!m_pActiveWorkflow) { return false; } // 保存当前个工作流指针 m_pOldWorkflow = m_pActiveWorkflow; if(!m_pOldWorkflow) { return false; } // 打开对话框设置另存工作流的名字 m_NewWorkflowName = ""; // 获取数据树上虚拟工作流对应工区 m_pSurvey = SaveHelper::GetSurveyByWfDBID(m_pOldWorkflow->GetDBID()); m_SaveType = SaveHelper::OpenSaveAsDialog(m_NewWorkflowName, &m_pSurvey, m_pOldWorkflow); // 如果点击取消或者新工作流名称为空直接返回false if(m_SaveType == SaveType_DoCancel || m_NewWorkflowName.isEmpty()) { return false; } // 获取同名工作流,不存在同名则m_pOldSameNameWorkflow = NULL m_pOldSameNameWorkflow = GetOldSameNameWorkflow(); // 当旧工作流和同名工作流相同时,即SaveAs为自己,不需要拷贝; // 新工作流SaveAs为另外一个名的工作流,也不需要拷贝,但是另存到别的工区需要copy,之后将保留copy并删除所谓新工作流 bool bSameWorkflow = false; if(SaveHelper::GetSurveyByWfDBID(m_pOldWorkflow->GetDBID())) { PaiBaseMaster *pWorkflowMaster = SaveHelper::GetSurveyByWfDBID(m_pOldWorkflow->GetDBID())-> GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString())); if(pWorkflowMaster && (m_pOldSameNameWorkflow == pWorkflowMaster->GetObject(m_pOldWorkflow->GetDBID()))) { bSameWorkflow = true; } } //如果存在同名工作流并且不是Save As自己 if(m_pOldSameNameWorkflow && !bSameWorkflow) { //尝试删除同名工作流,看是否能够正常删除 QString errMsg; if(!m_pOldSameNameWorkflow->TryDelete(errMsg)) { PaiMessageBox::Critical(::GetConsoleGUIService()->GetMainWindow(), QObject::tr("Error"), QObject::tr("Cannot save as \"%1\":\n").arg(m_pOldSameNameWorkflow->GetName()) + errMsg, PaiMessageBox::Ok, PaiMessageBox::Ok); return false; } } // Save As不是自己 if(!bSameWorkflow) { CopyWorkflow(); } // 设置新工作流名称 m_pActiveWorkflow->SetName(m_NewWorkflowName); CWorkFlowFile *pWorkflowFile = m_pActiveWorkflow->GetWorkflowFile(); QString surveyPath; if(m_pSurvey && pWorkflowFile) { surveyPath.append(m_pSurvey->GetPhysicalFile()); std::vector < std::string > outPutfiles; pWorkflowFile->GetOutPutFilePaths(outPutfiles); std::vector < std::string > updatedOutPutfiles; foreach(std::string file, outPutfiles) { if (!file.empty()) { int pos = file.find_last_of("/"); file.replace(0, pos, surveyPath.toStdString()); } updatedOutPutfiles.push_back(file); } pWorkflowFile->SetOutPutFilePaths(updatedOutPutfiles); } // 如果存在同名工作流并且不是Save As自己 if(m_pOldSameNameWorkflow && !bSameWorkflow) { // 做删除操作 QString errorMsg; if(m_pOldSameNameWorkflow->Erase(&errorMsg))//从数据库删除 { if(SaveHelper::GetSurveyByWfDBID(m_pOldSameNameWorkflow->GetDBID())) { pai::objectmodel::PaiObject *pParent = SaveHelper::GetSurveyByWfDBID(m_pOldSameNameWorkflow->GetDBID())-> GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString())); if(pParent) { // 从内存树删除并通知数据树 pParent->RemoveChild(m_pOldSameNameWorkflow, true); PaiObject *pShadowObject = GetObjectModelService()->GetObject(m_pOldSameNameWorkflow->GetDBID()); if(pShadowObject) { pParent = pShadowObject->GetParent(); if(pParent) { // 从内存树删除并通知数据树 pParent->RemoveChild(pShadowObject, true); } } } } } else { PaiMessageBox::Critical(::GetConsoleGUIService()->GetMainWindow(), QObject::tr("Error!"), errorMsg); pai::log::Error(_FLF(QObject::tr("QUndoCommand::ShowMessage ").toStdString() + errorMsg.toStdString())); } } // 保存工作流模型 if(SaveHelper::SaveWorkflow(m_pActiveWorkflow) == false) { RestoreWorkflow(); return false; } // 工作流有修改,并且非Save As自己 if(m_pOldWorkflow->HasDataModified() && !bSameWorkflow) { if(SaveHelper::GetSurveyByWfDBID(m_pOldWorkflow->GetDBID()) && SaveHelper::GetSurveyByWfDBID( m_pOldWorkflow->GetDBID())->GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString())) && !(m_SaveType & SaveType_IsNewWorkflow)) { // 刷新原来的工作流,保持原来未编辑的状态,但不能是从作业打开的工作流 // 作业打开的工作流这么刷新界面是空的 m_pOldWorkflow->ReloadDataModuel(); } } // 跨工区另存新工作流,则将前工区下新建的工作流删除 if(!bSameWorkflow && m_SaveType & SaveType_IsNewWorkflow) { if(SaveHelper::GetSurveyByWfDBID(m_pOldWorkflow->GetDBID())) { PaiObject *pParent = SaveHelper::GetSurveyByWfDBID(m_pOldWorkflow->GetDBID())-> GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString())); if(pParent) { // 从内存树删除并通知数据树 pParent->RemoveChild(GetObjectModelService()->GetObject(m_pOldWorkflow->GetDBID()), true); PaiObject *pShadowObject = GetObjectModelService()->GetObject(m_pOldWorkflow->GetDBID()); if(pShadowObject) { pParent = pShadowObject->GetParent(); if(pParent) { // 从内存树删除并通知数据树 pParent->RemoveChild(pShadowObject, true); } } } } } m_pActiveWorkflow->SetModify(false); GetObjectModelService()->GetObjectSelection()->Select(m_pActiveWorkflow->GetID(), true); QString text = QObject::tr("Workflow \"") + m_NewWorkflowName + QObject::tr("\"") + " saved." + "
    Double click to open it or right click to open menu."; PaiBalloonGuide::GetInstance()->ShowInstantTip(m_pActiveWorkflow->GetID(), text, QObject::tr("SaveAsWorkflow")); if(HandleExtensionTabAndNodeSelection() == false) { return false; } return true; }