2012-12-08 14:25:50 +00:00
|
|
|
#include "operation.hpp"
|
|
|
|
|
2022-10-19 17:02:00 +00:00
|
|
|
#include <algorithm>
|
|
|
|
#include <exception>
|
2012-12-08 17:38:36 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2012-12-08 14:25:50 +00:00
|
|
|
#include <QTimer>
|
|
|
|
|
2023-02-16 22:38:47 +00:00
|
|
|
#include <components/debug/debuglog.hpp>
|
|
|
|
|
2022-10-19 17:02:00 +00:00
|
|
|
#include <apps/opencs/model/doc/messages.hpp>
|
|
|
|
|
2014-05-08 10:42:29 +00:00
|
|
|
#include "../world/universalid.hpp"
|
|
|
|
|
2012-12-08 16:53:45 +00:00
|
|
|
#include "stage.hpp"
|
|
|
|
|
2023-02-16 22:38:47 +00:00
|
|
|
namespace CSMDoc
|
|
|
|
{
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
std::string_view operationToString(State value)
|
|
|
|
{
|
|
|
|
switch (value)
|
|
|
|
{
|
|
|
|
case State_Saving:
|
|
|
|
return "Saving";
|
|
|
|
case State_Merging:
|
|
|
|
return "Merging";
|
|
|
|
case State_Verifying:
|
|
|
|
return "Verifying";
|
|
|
|
case State_Searching:
|
|
|
|
return "Searching";
|
|
|
|
case State_Loading:
|
|
|
|
return "Loading";
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-14 12:56:23 +00:00
|
|
|
void CSMDoc::Operation::prepareStages()
|
2012-12-08 16:53:45 +00:00
|
|
|
{
|
|
|
|
mCurrentStage = mStages.begin();
|
|
|
|
mCurrentStep = 0;
|
|
|
|
mCurrentStepTotal = 0;
|
|
|
|
mTotalSteps = 0;
|
2013-09-15 10:03:36 +00:00
|
|
|
mError = false;
|
2012-12-08 16:53:45 +00:00
|
|
|
|
|
|
|
for (std::vector<std::pair<Stage*, int>>::iterator iter(mStages.begin()); iter != mStages.end(); ++iter)
|
|
|
|
{
|
2012-12-08 22:27:59 +00:00
|
|
|
iter->second = iter->first->setup();
|
|
|
|
mTotalSteps += iter->second;
|
2012-12-08 16:53:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-16 22:38:47 +00:00
|
|
|
CSMDoc::Operation::Operation(State type, bool ordered, bool finalAlways)
|
2014-10-10 22:06:50 +00:00
|
|
|
: mType(type)
|
|
|
|
, mStages(std::vector<std::pair<Stage*, int>>())
|
|
|
|
, mCurrentStage(mStages.begin())
|
|
|
|
, mCurrentStep(0)
|
|
|
|
, mCurrentStepTotal(0)
|
|
|
|
, mTotalSteps(0)
|
|
|
|
, mOrdered(ordered)
|
2015-06-20 17:04:19 +00:00
|
|
|
, mFinalAlways(finalAlways)
|
|
|
|
, mError(false)
|
|
|
|
, mConnected(false)
|
|
|
|
, mPrepared(false)
|
|
|
|
, mDefaultSeverity(Message::Severity_Error)
|
2013-09-15 09:35:12 +00:00
|
|
|
{
|
2015-03-14 11:00:24 +00:00
|
|
|
mTimer = new QTimer(this);
|
2013-09-15 09:35:12 +00:00
|
|
|
}
|
2012-12-08 14:25:50 +00:00
|
|
|
|
2013-09-14 12:56:23 +00:00
|
|
|
CSMDoc::Operation::~Operation()
|
2012-12-08 16:53:45 +00:00
|
|
|
{
|
|
|
|
for (std::vector<std::pair<Stage*, int>>::iterator iter(mStages.begin()); iter != mStages.end(); ++iter)
|
|
|
|
delete iter->first;
|
|
|
|
}
|
|
|
|
|
2013-09-14 12:56:23 +00:00
|
|
|
void CSMDoc::Operation::run()
|
2012-12-08 14:25:50 +00:00
|
|
|
{
|
2015-03-14 11:00:24 +00:00
|
|
|
mTimer->stop();
|
2015-12-15 11:44:04 +00:00
|
|
|
|
2015-03-14 11:00:24 +00:00
|
|
|
if (!mConnected)
|
|
|
|
{
|
2022-08-23 02:28:58 +00:00
|
|
|
connect(mTimer, &QTimer::timeout, this, &Operation::executeStage);
|
2015-03-14 11:00:24 +00:00
|
|
|
mConnected = true;
|
|
|
|
}
|
2015-06-20 12:21:52 +00:00
|
|
|
|
|
|
|
mPrepared = false;
|
2023-02-16 22:38:47 +00:00
|
|
|
mStart = std::chrono::steady_clock::now();
|
2012-12-08 14:25:50 +00:00
|
|
|
|
2015-03-14 11:00:24 +00:00
|
|
|
mTimer->start(0);
|
2012-12-08 14:25:50 +00:00
|
|
|
}
|
|
|
|
|
2013-09-14 12:56:23 +00:00
|
|
|
void CSMDoc::Operation::appendStage(Stage* stage)
|
2012-12-08 16:53:45 +00:00
|
|
|
{
|
2020-10-17 08:26:35 +00:00
|
|
|
mStages.emplace_back(stage, 0);
|
2012-12-08 16:53:45 +00:00
|
|
|
}
|
|
|
|
|
2015-06-20 17:04:19 +00:00
|
|
|
void CSMDoc::Operation::setDefaultSeverity(Message::Severity severity)
|
|
|
|
{
|
|
|
|
mDefaultSeverity = severity;
|
|
|
|
}
|
|
|
|
|
2013-09-15 10:03:36 +00:00
|
|
|
bool CSMDoc::Operation::hasError() const
|
|
|
|
{
|
|
|
|
return mError;
|
|
|
|
}
|
|
|
|
|
2013-09-14 12:56:23 +00:00
|
|
|
void CSMDoc::Operation::abort()
|
2012-12-08 14:25:50 +00:00
|
|
|
{
|
2015-03-14 11:00:24 +00:00
|
|
|
if (!mTimer->isActive())
|
2013-09-15 10:03:36 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
mError = true;
|
|
|
|
|
|
|
|
if (mFinalAlways)
|
|
|
|
{
|
|
|
|
if (mStages.begin() != mStages.end() && mCurrentStage != --mStages.end())
|
|
|
|
{
|
|
|
|
mCurrentStep = 0;
|
|
|
|
mCurrentStage = --mStages.end();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
mCurrentStage = mStages.end();
|
2012-12-08 14:25:50 +00:00
|
|
|
}
|
|
|
|
|
2013-09-15 07:32:20 +00:00
|
|
|
void CSMDoc::Operation::executeStage()
|
2012-12-08 14:25:50 +00:00
|
|
|
{
|
2015-06-20 12:21:52 +00:00
|
|
|
if (!mPrepared)
|
|
|
|
{
|
|
|
|
prepareStages();
|
|
|
|
mPrepared = true;
|
|
|
|
}
|
2015-12-15 11:44:04 +00:00
|
|
|
|
2015-06-20 17:04:19 +00:00
|
|
|
Messages messages(mDefaultSeverity);
|
2012-12-08 17:38:36 +00:00
|
|
|
|
2012-12-08 16:53:45 +00:00
|
|
|
while (mCurrentStage != mStages.end())
|
|
|
|
{
|
|
|
|
if (mCurrentStep >= mCurrentStage->second)
|
|
|
|
{
|
|
|
|
mCurrentStep = 0;
|
|
|
|
++mCurrentStage;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-09-15 10:03:36 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
mCurrentStage->first->perform(mCurrentStep++, messages);
|
|
|
|
}
|
2013-09-27 11:54:51 +00:00
|
|
|
catch (const std::exception& e)
|
2013-09-15 10:03:36 +00:00
|
|
|
{
|
2015-06-20 17:04:19 +00:00
|
|
|
emit reportMessage(
|
|
|
|
Message(CSMWorld::UniversalId(), e.what(), "", Message::Severity_SeriousError), mType);
|
2013-09-15 10:03:36 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2012-12-08 16:53:45 +00:00
|
|
|
++mCurrentStepTotal;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
emit progress(mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType);
|
2012-12-08 14:25:50 +00:00
|
|
|
|
2014-12-07 17:57:47 +00:00
|
|
|
for (Messages::Iterator iter(messages.begin()); iter != messages.end(); ++iter)
|
2015-06-20 15:56:42 +00:00
|
|
|
emit reportMessage(*iter, mType);
|
2012-12-08 17:38:36 +00:00
|
|
|
|
2012-12-08 16:53:45 +00:00
|
|
|
if (mCurrentStage == mStages.end())
|
2023-02-16 22:38:47 +00:00
|
|
|
{
|
|
|
|
if (mStart.has_value())
|
|
|
|
{
|
|
|
|
const auto duration = std::chrono::steady_clock::now() - *mStart;
|
|
|
|
Log(Debug::Verbose) << operationToString(mType) << " operation is completed in "
|
|
|
|
<< std::chrono::duration_cast<std::chrono::duration<double>>(duration).count() << 's';
|
|
|
|
mStart.reset();
|
|
|
|
}
|
|
|
|
|
2015-03-14 11:00:24 +00:00
|
|
|
operationDone();
|
2023-02-16 22:38:47 +00:00
|
|
|
}
|
2013-09-15 09:35:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CSMDoc::Operation::operationDone()
|
|
|
|
{
|
2015-03-14 11:00:24 +00:00
|
|
|
mTimer->stop();
|
2014-09-03 17:14:27 +00:00
|
|
|
emit done(mType, mError);
|
2014-10-10 22:06:50 +00:00
|
|
|
}
|