logplus/Workflow/WFEngine/Component/WorkflowWidget/src/SaveHelper.cpp
2026-01-16 17:18:41 +08:00

504 lines
19 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file SaveHelper.cpp
* @date 2012-10-17
* @author liujunxia
*/
#include <QDir>
#include <QtDebug>
#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<PaiWorkflowDataModel*>(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<PaiObject*> (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;
}