504 lines
19 KiB
C++
504 lines
19 KiB
C++
/**
|
||
* @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;
|
||
}
|