/** * @file SaveHelper.cpp * @date 2012-10-17 * @author liujunxia */ #include #include #include "SaveHelper.h" #include "PaiObject.h" #include "PaiProject.h" #include "PaiWorkflowDataModel.h" #include "WorkflowConst.h" #include "PaiSaveAsWorkflowDialog.h" #include "ConsoleGUIService.h" #include "PaiInputDialog.h" #include "WorkflowWidget.h" #include "PaiWorkflowMaster.h" #include "PaiMessageBox.h" #include "Log.h" #include "GlobalModuleBackup.h" #include "PAIConst.h" #include "ViewExtension.h" #include "WorkflowWidget.h" #include "PaiPermissionChecker.h" #include "PaiTextEdit.h" #include "PaiSurvey.h" using namespace pai; using namespace pai::objectmodel; using namespace pai::gui; using namespace pai::graphics2d; #define PROPERTIES_VIEW_ID "Properties" pai::graphics2d::WorkflowWidget* SaveHelper::m_pActiveWorkflowWidget = NULL; QString SaveHelper::m_ExceptionWhat = ""; int SaveHelper::m_ExceptionWhich = pai::error::ERR_SUCCESS; SaveHelper::SaveHelper() { } SaveHelper::~SaveHelper() { } void SaveHelper::SetSaveException(const QString & what, const int which) { m_ExceptionWhat = what; m_ExceptionWhich = which; } QString SaveHelper::GetSaveExceptionWhat() { return m_ExceptionWhat; } int SaveHelper::GetSaveExceptionWhich() { return m_ExceptionWhich; } int SaveHelper::OpenSaveDialog(QString &workflowName, PaiSurvey** ppSurvey, pai::objectmodel::PaiWorkflowDataModel*pActiveWorkflow) { return OpenSaveDialog(true, workflowName, ppSurvey, pActiveWorkflow); } int SaveHelper::OpenSaveAsDialog(QString &workflowName, PaiSurvey** ppSurvey, pai::objectmodel::PaiWorkflowDataModel*pActiveWorkflow) { return OpenSaveDialog(false, workflowName, ppSurvey, pActiveWorkflow); } bool SaveHelper::SaveWorkflow(pai::objectmodel::PaiWorkflowDataModel* pWorkflow, bool isTemplate) { bool ret = false; QCursor oldCursor = ::GetConsoleGUIService()->GetMainWindow()->cursor(); ::GetConsoleGUIService()->GetMainWindow()->setCursor(Qt::WaitCursor); //为提交而保存成json文件 QString strJsonFileName("/tmp/"); if(isTemplate) { strJsonFileName = "/tmp/template/"; } strJsonFileName += pWorkflow->GetName(); QString strID = pWorkflow->GetID().toString();//这里取ID来保证/tmp/下的工作流文件名唯一 strID.remove('{').remove('-').remove('}'); strJsonFileName += strID; strJsonFileName += ".json"; pWorkflow->SetAsTemplate(isTemplate); if(SaveWorkflowJson(pWorkflow, strJsonFileName) == true) { //保存到数据库(包括刚才保存的文件) try { QString strErrMsg; ret = true; long long wfDBID = pWorkflow->GetDBID(); if(!(pWorkflow->HasFlag(PaiObject::Loaded))) { if(!pWorkflow->SaveToDB(&strErrMsg, isTemplate)) { pai::log::Debug(_FLF(strErrMsg.toStdString())); ret = false; } else if(!isTemplate) { bool locked = GetObjectModelService()->GetObjectLockManager()->IsObjectLocked(wfDBID); if (locked && m_pActiveWorkflowWidget && (pWorkflow == m_pActiveWorkflowWidget->GetWorkflow())) { // after saving a new workflow, we need to update the object lock // because the object DBID will change. m_pActiveWorkflowWidget->UpdateWorkflowLock(wfDBID); } } } else { if(!pWorkflow->UpdateToDB(&strErrMsg, isTemplate)) { pai::log::Debug(_FLF(strErrMsg.toStdString())); ret = false; } } if(!isTemplate) { //获取数据树上虚拟工作流 PaiObject *pDataTreeWorkflow = GetObjectModelService()->GetObject(wfDBID); if(pDataTreeWorkflow) { PaiWorkflowDataModel *pTmpWorkflow = dynamic_cast(pDataTreeWorkflow); if(pTmpWorkflow && pWorkflow->GetWorkflowPtr()) { pTmpWorkflow->SetDBWorkflow(pWorkflow->GetWorkflowPtr()->GetWorkflwoPtr()); pTmpWorkflow->SetDBID(pWorkflow->GetDBID()); //做删除操作时,会用到这个id pTmpWorkflow->GetWorkflowPtr()->SetID(pWorkflow->GetWorkflowPtr()->GetID()); pTmpWorkflow->SetIgnoreSyncDB(false); pTmpWorkflow->SetSyncabled(true); } } } } catch(pai::error::generic_error & e) { SetSaveException(e.what(), e.which()); pai::log::Info(_FLF(pWorkflow->GetName().toStdString() + " save workflow caught an exception. " + e.what())); ret = false; } } GlobalModuleBackup *pModuleBack = ::GetGlobalModuleBackup(); pModuleBack->UpDateBackupModule(pWorkflow->GetID()); ::GetConsoleGUIService()->GetMainWindow()->setCursor(oldCursor); return ret; } bool SaveHelper::SaveWorkflowJson(pai::objectmodel::PaiWorkflowDataModel* pWorkflow, const QString& jsonFilePath) { if(jsonFilePath == "") { ShowMessage(PAI_NAME, "Save failure for empty workflow file name."); return false; } if(pWorkflow != NULL) { try { if(pWorkflow->IsTemplate())//判断是否为模板 { //判断模板的保存目录是否存在,不存在则创建该目录 QDir templateDir("/tmp/template"); if(!templateDir.exists("/tmp/template")) { templateDir.mkdir("/tmp/template"); QFile::setPermissions("/tmp/template", QFile::ReadUser | QFile::WriteUser | QFile::ExeUser | QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup | QFile::ReadOther | QFile::WriteOther | QFile::ExeOther); } } if(!pWorkflow->Save(jsonFilePath.toStdString())) { if(pWorkflow->IsTemplate()) { ShowMessage(PAI_NAME, "Save template failure"); } else { ShowMessage(PAI_NAME, "Save workflow failure"); } return false; } return true; } catch(std::exception &ex) { if(::GetConsoleGUIService()) { pai::gui::PaiMessageBox::Critical(::GetConsoleGUIService()->GetMainWindow(), PAI_NAME, QObject::tr("Save workflow %1 caught an exception. ").arg(pWorkflow->GetName()).append(ex.what())); } pai::log::Error(_FLF(pWorkflow->GetName().toStdString() + " save workflow caught an exception. " + ex.what())); } } return false; } PaiTextEdit* SaveHelper::GetPropertiesTextEdit() { ViewExtension * pViewExtension = dynamic_cast< ViewExtension* > (GetConsoleGUIService()->GetUtilityTabService()->GetExtension(PROPERTIES_VIEW_ID)); if(pViewExtension) { return dynamic_cast< PaiTextEdit* > (pViewExtension->GetView()); } return NULL; } void SaveHelper::SetActiveWorkflowView(WorkflowWidget* pWorkflowWidget) { m_pActiveWorkflowWidget = pWorkflowWidget; } WorkflowWidget* SaveHelper::GetActiveWorkflowView() { return m_pActiveWorkflowWidget; } void SaveHelper::ShowMessage(const QString& title, const QString& message) { ConsoleGUIService* pServer = ::GetConsoleGUIService(); if(pServer) { pai::gui::PaiMessageBox::Information(pServer->GetMainWindow(), title, message); } pai::log::Info(_FLF(QObject::tr("ControlExtension::ShowMessage").toStdString() + message.toStdString())); } /* * OpenSaveDialog 实现保存工作流时打开对话框设置工作流名称的操作,ValidateSaveWorkflowName 实现对工作流同名的验证。这两个函数根据不同情况返回不同的整数 * 值,供保存函数使用。保存函数包括Save和SaveAs两种情况。 * 对于Save操作,只有当当前工作流为新建的且未保存的工作流时,才应该使用OpenSaveDialog。 * 对于SaveAs操作,无论当前工作流为新建的且未保存的工作流还是已经存过的工作流,都应该使用OpenSaveDialog,让用户输入要保存的工作流名称。 * * 对于返回值,有以下几种情况。 * 1.取消操作,SaveType_DoCancel * 2.当前工作流为新建的且未保存的工作流new,同名的为已经保存过的工作流old。弹出同名对话框,确认后保存当前工作流名称为old,并删除原来的old工作流。(SaveType_DoSave | SaveType_DoReplace) * 3.当前工作流为新建的且未保存的工作流new,同名的为创建时默认的名称new。直接保存当前工作流名称为new。(SaveType_DoSave) * 4.当前工作流为新建的且未保存的工作流new,保存为一个新名称new2。直接保存当前工作流为new2。(SaveType_DoSave) * 5.当前工作流为保存过的工作流old,同名的为已经保存过的工作流old2。应该是出现在另存为的情况中。弹出同名对话框,确认后创建一个新工作流,拷贝当前工作流,保存为 * old2,删除原来的old2工作流。(SaveType_DoCopy | SaveType_DoSave | SaveType_DoReplace) * 6.当前工作流为保存过的工作流old,保存的和当前工作流原名称一致,即old。应该是出现在另存为的情况中。弹出同名对话框,确认后保存当前工作流为old。(SaveType_DoSave) * 7.当前工作流为保存过的工作流old,保存为一个新名称new。应该是出现在另存为的情况中。确认后创建一个新工作流,拷贝当前工作流,保存工作流名称为new。(SaveType_DoCopy | SaveType_DoSave); * 8.发生同名后,弹出同名对话框,但不想替换。会重新打开保存对话框。(SaveType_DoOpenDialog) */ int SaveHelper::OpenSaveDialog(bool save, QString &workflowName, pai::objectmodel::PaiSurvey** ppSurvey, pai::objectmodel::PaiWorkflowDataModel*pActiveWorkflow) { PaiWorkflowDataModel *pCurrentWorkflow = pActiveWorkflow; if(!pCurrentWorkflow) { return (SaveType_DoCancel); } if(!save) { long long projectID = 0; long long surveyID = 0; if(*ppSurvey) { pai::objectmodel::PaiProject *pProject = (*ppSurvey)->GetForebear< pai::objectmodel::PaiProject > (); if(pProject) { projectID = (*ppSurvey)->GetForebear< pai::objectmodel::PaiProject > ()->GetDBID(); } surveyID = (*ppSurvey)->GetDBID(); } pai::gui::PaiSaveAsWorkflowDialog iDlg(projectID, surveyID, pActiveWorkflow->GetName(), ::GetConsoleGUIService()->GetMainWindow()); int result = QDialog::Rejected; while((result = iDlg.exec()) != QDialog::Rejected) { workflowName = iDlg.GetSaveAsWorkflowName(); //获取选中的工区 PaiSurvey* pSelectSurvey = iDlg.GetSelectedSurvey(); *ppSurvey = pSelectSurvey; if(result == QDialog::Accepted && "" != workflowName) { bool permission = true; try { //添加指针为空的判断,防止为空的情况还获取DBID 导致的系统崩溃 if(pSelectSurvey) { permission = PaiPermissionChecker::HasPermission(dynamic_cast (pSelectSurvey), PaiAction::PaiPermissionTypes(PaiAction::UPDATE)); } else { permission = false; } } catch(pai::error::generic_error & e) { permission = false; } catch(...) { permission = false; } if(!permission) { PaiMessageBox::Critical(&iDlg, QObject::tr("π-Frame Workflow"), QObject::tr("You don't have permission to save Workflow into this Survey, please select another one."), PaiMessageBox::Ok, PaiMessageBox::Ok); iDlg.ResetValidateNameEdit(); continue; } int findResult = ValidateSaveWorkflowName(save, workflowName, pActiveWorkflow, pSelectSurvey); if(findResult & SaveType_DoOpenDialog) { iDlg.ResetValidateNameEdit(); continue; } else { return findResult; } } else { //1.取消操作 return (SaveType_DoCancel); } } } else { //在左保存之前,先把数据树上的workflow同步一下 PaiSurvey *pSurvey = GetSurveyByWfDBID(pCurrentWorkflow->GetDBID()); PaiObject *pWorkflowMaster = NULL; if(pSurvey) { pWorkflowMaster = pSurvey->GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString())); } if(pWorkflowMaster && pWorkflowMaster->HasFlag(PaiObject::ChildrenLoaded)) { pWorkflowMaster->SyncDB(pai::Children | pai::Force); } //打开对话框设置工作流的名字 PaiInputDialog dlgNameWorkflow(::GetConsoleGUIService()->GetMainWindow()); dlgNameWorkflow.SetOkButtonText("&Save"); if(save) { dlgNameWorkflow.setWindowTitle(g_szSave); } else { dlgNameWorkflow.setWindowTitle(g_szSaveAs); } dlgNameWorkflow.SetLabelText("Please enter the workflow name:"); dlgNameWorkflow.SetText(pCurrentWorkflow->GetName()); dlgNameWorkflow.UseValidateNameEdit(g_iMaxWorkflowNameLength); int result = QDialog::Rejected; while((result = dlgNameWorkflow.exec()) != QDialog::Rejected) { workflowName = dlgNameWorkflow.TextValue(); if((result == QDialog::Accepted) && ("" != workflowName)) { int findResult = ValidateSaveWorkflowName(save, workflowName, pActiveWorkflow); if(findResult & SaveType_DoOpenDialog) { dlgNameWorkflow.ResetValidateNameEdit(); continue; } else { return findResult; } } else { //1.取消操作 return (SaveType_DoCancel); } } } //1.取消操作 return (SaveType_DoCancel); } int SaveHelper::ValidateSaveWorkflowName(bool save, const QString& workflowName, pai::objectmodel::PaiWorkflowDataModel*pActiveWorkflow, pai::objectmodel::PaiSurvey* pSurvey) { int ret = SaveType_IsWorkOpen; PaiWorkflowDataModel *pCurrentWorkflow = pActiveWorkflow; if(!pCurrentWorkflow) { return ret; } QList< PaiObject* > lstChildren; //获取数据树上虚拟工作流 PaiObject *pDataTreeWorkflow = GetObjectModelService()->GetObject(pActiveWorkflow->GetDBID()); //当前工作流有父节点的使用父节点获得工作流子节点列表,没有的如果参数指定了工区,使用工区获得工作流管理器进而得到工作流字节点列表。 if(save && pDataTreeWorkflow && (pDataTreeWorkflow->GetParent())) { pDataTreeWorkflow->GetParent()->GetChildren(lstChildren); } else if(pSurvey != NULL && pSurvey->GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString())) != NULL) { PaiWorkflowMaster* pMaster = dynamic_cast< PaiWorkflowMaster* > (pSurvey->GetMaster(QUuid(PaiWorkflowMaster::GetTypeIDString()))); pMaster->SyncDB(pai::Children | pai::Force); pMaster->GetChildren(lstChildren); } if(!(pCurrentWorkflow->HasFlag(PaiObject::Loaded)) && pDataTreeWorkflow && (pDataTreeWorkflow->GetParent())) { ret |= SaveType_IsNewWorkflow; } for(int i = 0; i < lstChildren.size(); ++i) { PaiObject* pModel = lstChildren.at(i); if(pModel->GetName() == workflowName) { if((dynamic_cast< PaiWorkflowDataModel* > (pModel) == pDataTreeWorkflow) && (ret & SaveType_IsNewWorkflow)) { ret |= SaveType_IsCurrentWorkflow; continue; } ret |= SaveType_ExistSameName; QWidget* pMainWindow = ::GetConsoleGUIService()->GetMainWindow(); QString body = QObject::tr("workflow %1 exists. Do you want to replace it?").arg(workflowName); int r = PaiMessageBox::Warning(pMainWindow, "π-Frame Workflow", body, PaiMessageBox::Yes | PaiMessageBox::No, PaiMessageBox::Yes); if(r == PaiMessageBox::No) { ret = SaveType_DoOpenDialog; return ret; } return ret; } } return ret; } QList< PaiWorkflowDataModel* > SaveHelper::GetModifiedWorkflows(QUuid viewID) { QList< PaiWorkflowDataModel* > lstWorkflows; PageService* pPageService = GetConsoleGUIService()->GetViewTabService()->GetPageService(viewID); if(pPageService != NULL) { QWidget* pWorkflowTabs = pPageService->GetWidgetView("A"); if(pWorkflowTabs != NULL) { QList< WorkflowWidget* > lstWorkflowWidgets = pWorkflowTabs->findChildren< WorkflowWidget* > (); foreach(WorkflowWidget* pWorkflowWidget, lstWorkflowWidgets) { PaiWorkflowDataModel* pWorkflow = pWorkflowWidget->GetWorkflow(); if (pWorkflow != NULL && pWorkflow->HasDataModified()) { lstWorkflows.prepend(pWorkflow); } } } } return lstWorkflows; } pai::objectmodel::PaiSurvey* SaveHelper::GetSurveyByWfDBID(long long workflowDBID) { //获取数据树上虚拟工作流 PaiObject *pDataTreeWorkflow = GetObjectModelService()->GetObject(workflowDBID); //获取工作流所在工区 if(!pDataTreeWorkflow) { return NULL; } PaiSurvey *pSurvey = pDataTreeWorkflow->GetForebear< PaiSurvey > (); return pSurvey; }