Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190#include "operation.hpp"
#include <algorithm>#include <exception>#include <vector>
#include <QCoreApplication>
#include <components/debug/debuglog.hpp>
#include <apps/opencs/model/doc/messages.hpp>
#include "../world/universalid.hpp"
#include "stage.hpp"
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"; } }}
void CSMDoc::Operation::prepareStages(){ mCurrentStage = mStages.begin(); mCurrentStep = 0; mCurrentStepTotal = 0; mTotalSteps = 0; mError = false;
for (std::vector<std::pair<Stage*, int>>::iterator iter(mStages.begin()); iter != mStages.end(); ++iter) { iter->second = iter->first->setup(); mTotalSteps += iter->second; }}
CSMDoc::Operation::Operation(State type, bool finalAlways) : mType(type) , mStages(std::vector<std::pair<Stage*, int>>()) , mCurrentStage(mStages.begin()) , mCurrentStep(0) , mCurrentStepTotal(0) , mTotalSteps(0) , mFinalAlways(finalAlways) , mError(false) , mPrepared(false) , mDefaultSeverity(Message::Severity_Error){}
CSMDoc::Operation::~Operation(){ for (std::vector<std::pair<Stage*, int>>::iterator iter(mStages.begin()); iter != mStages.end(); ++iter) delete iter->first;}
void CSMDoc::Operation::run(){ mPrepared = false; mStart = std::chrono::steady_clock::now(); QMetaObject::invokeMethod(this, &Operation::executeStage, Qt::QueuedConnection);}
void CSMDoc::Operation::appendStage(Stage* stage){ mStages.emplace_back(stage, 0);}
void CSMDoc::Operation::setDefaultSeverity(Message::Severity severity){ mDefaultSeverity = severity;}
bool CSMDoc::Operation::hasError() const{ return mError;}
void CSMDoc::Operation::abort(){ if (!mStart.has_value()) return;
mError = true;
if (mFinalAlways) { if (mStages.begin() != mStages.end() && mCurrentStage != --mStages.end()) { mCurrentStep = 0; mCurrentStage = --mStages.end(); } } else mCurrentStage = mStages.end();}
void CSMDoc::Operation::executeStage(){ if (!mPrepared) { prepareStages(); mPrepared = true; }
Messages messages(mDefaultSeverity);
const auto batchStart = std::chrono::steady_clock::now(); static constexpr auto batchBudget = std::chrono::milliseconds(33);
while (mCurrentStage != mStages.end()) { if (mCurrentStep >= mCurrentStage->second) { mCurrentStep = 0; ++mCurrentStage; } else { try { mCurrentStage->first->perform(mCurrentStep++, messages); } catch (const std::exception& e) { emit reportMessage( Message(CSMWorld::UniversalId(), e.what(), "", Message::Severity_SeriousError), mType); abort(); }
++mCurrentStepTotal;
if (std::chrono::steady_clock::now() - batchStart >= batchBudget) break; } }
emit progress(mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType);
for (Messages::Iterator iter(messages.begin()); iter != messages.end(); ++iter) emit reportMessage(*iter, mType);
if (mCurrentStage == mStages.end()) { 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(); }
operationDone(); return; }
QMetaObject::invokeMethod(this, &Operation::executeStage, Qt::QueuedConnection);}
void CSMDoc::Operation::operationDone(){ emit done(mType, mError);}
void CSMDoc::Operation::cleanup(){ moveToThread(QCoreApplication::instance()->thread());}