Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272#include "tools.hpp"
#include <stdexcept>#include <string>#include <type_traits>#include <utility>#include <vector>
#include "../doc/document.hpp"
#include "birthsigncheck.hpp"#include "bodypartcheck.hpp"#include "classcheck.hpp"#include "enchantmentcheck.hpp"#include "factioncheck.hpp"#include "gmstcheck.hpp"#include "journalcheck.hpp"#include "magiceffectcheck.hpp"#include "mandatoryid.hpp"#include "mergeoperation.hpp"#include "pathgridcheck.hpp"#include "racecheck.hpp"#include "referenceablecheck.hpp"#include "referencecheck.hpp"#include "regioncheck.hpp"#include "reportmodel.hpp"#include "scriptcheck.hpp"#include "searchoperation.hpp"#include "skillcheck.hpp"#include "soundcheck.hpp"#include "soundgencheck.hpp"#include "spellcheck.hpp"#include "startscriptcheck.hpp"#include "topicinfocheck.hpp"
#include <apps/opencs/model/doc/operationholder.hpp>#include <apps/opencs/model/world/idcollection.hpp>#include <apps/opencs/model/world/refidcollection.hpp>
namespace CSMDoc{ struct Message;}
CSMDoc::OperationHolder* CSMTools::Tools::get(int type){ switch (type) { case CSMDoc::State_Verifying: return mVerifier; case CSMDoc::State_Searching: return mSearch; case CSMDoc::State_Merging: return mMerge; }
return nullptr;}
const CSMDoc::OperationHolder* CSMTools::Tools::get(int type) const{ return const_cast<Tools*>(this)->get(type);}
CSMDoc::OperationHolder* CSMTools::Tools::getVerifier(){ if (!mVerifier) { mVerifierOperation = new CSMDoc::Operation(CSMDoc::State_Verifying);
std::vector<ESM::RefId> mandatoryRefIds; { auto mandatoryIds = { "Day", "DaysPassed", "GameHour", "Month", "PCRace" }; for (auto& id : mandatoryIds) mandatoryRefIds.push_back(ESM::RefId::stringRefId(id)); }
mVerifierOperation->appendStage(new MandatoryIdStage( mData.getGlobals(), CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Globals), mandatoryRefIds));
mVerifierOperation->appendStage(new SkillCheckStage(mData.getSkills()));
mVerifierOperation->appendStage(new ClassCheckStage(mData.getClasses()));
mVerifierOperation->appendStage(new FactionCheckStage(mData.getFactions()));
mVerifierOperation->appendStage(new RaceCheckStage(mData.getRaces()));
mVerifierOperation->appendStage( new SoundCheckStage(mData.getSounds(), mData.getResources(CSMWorld::UniversalId::Type_SoundsRes)));
mVerifierOperation->appendStage(new RegionCheckStage(mData.getRegions()));
mVerifierOperation->appendStage( new BirthsignCheckStage(mData.getBirthsigns(), mData.getResources(CSMWorld::UniversalId::Type_Textures)));
mVerifierOperation->appendStage(new SpellCheckStage(mData.getSpells()));
mVerifierOperation->appendStage( new ReferenceableCheckStage(mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions(), mData.getScripts(), mData.getResources(CSMWorld::UniversalId::Type_Meshes), mData.getResources(CSMWorld::UniversalId::Type_Icons), mData.getBodyParts()));
mVerifierOperation->appendStage(new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions(), mData.getBodyParts()));
mVerifierOperation->appendStage(new ScriptCheckStage(mDocument));
mVerifierOperation->appendStage(new StartScriptCheckStage(mData.getStartScripts(), mData.getScripts()));
mVerifierOperation->appendStage(new BodyPartCheckStage(mData.getBodyParts(), mData.getResources(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Meshes)), mData.getRaces()));
mVerifierOperation->appendStage(new PathgridCheckStage(mData.getPathgrids()));
mVerifierOperation->appendStage( new SoundGenCheckStage(mData.getSoundGens(), mData.getSounds(), mData.getReferenceables()));
mVerifierOperation->appendStage(new MagicEffectCheckStage(mData.getMagicEffects(), mData.getSounds(), mData.getReferenceables(), mData.getResources(CSMWorld::UniversalId::Type_Icons), mData.getResources(CSMWorld::UniversalId::Type_Textures)));
mVerifierOperation->appendStage(new GmstCheckStage(mData.getGmsts()));
mVerifierOperation->appendStage(new TopicInfoCheckStage(mData.getTopicInfos(), mData.getCells(), mData.getClasses(), mData.getFactions(), mData.getGmsts(), mData.getGlobals(), mData.getJournals(), mData.getRaces(), mData.getRegions(), mData.getTopics(), mData.getReferenceables().getDataSet(), mData.getResources(CSMWorld::UniversalId::Type_SoundsRes)));
mVerifierOperation->appendStage(new JournalCheckStage(mData.getJournals(), mData.getJournalInfos()));
mVerifierOperation->appendStage(new EnchantmentCheckStage(mData.getEnchantments()));
mVerifier = new CSMDoc::OperationHolder(this, mVerifierOperation); connect(mVerifier, &CSMDoc::OperationHolder::progress, this, &Tools::progress); connect(mVerifier, &CSMDoc::OperationHolder::done, this, &Tools::done); connect(mVerifier, &CSMDoc::OperationHolder::reportMessage, this, &Tools::verifierMessage); }
return mVerifier;}
CSMTools::Tools::Tools(CSMDoc::Document& document, ToUTF8::FromType encoding) : mDocument(document) , mData(document.getData()) , mVerifierOperation(nullptr) , mVerifier(nullptr) , mSearchOperation(nullptr) , mSearch(nullptr) , mMergeOperation(nullptr) , mMerge(nullptr) , mNextReportNumber(0) , mEncoding(encoding){ // index 0: load error log mReports.insert(std::make_pair(mNextReportNumber++, new ReportModel)); mActiveReports.insert(std::make_pair(CSMDoc::State_Loading, 0));}
CSMTools::Tools::~Tools(){ // OperationHolder destructors call quit(), which aborts the operation, waits // for the thread to finish, and deletes the operation. The holders are // QObject children of Tools and are destroyed automatically.
for (std::map<int, ReportModel*>::iterator iter(mReports.begin()); iter != mReports.end(); ++iter) delete iter->second;}
CSMWorld::UniversalId CSMTools::Tools::runVerifier(const CSMWorld::UniversalId& reportId){ int reportNumber = reportId.getType() == CSMWorld::UniversalId::Type_VerificationResults ? reportId.getIndex() : mNextReportNumber++;
if (mReports.find(reportNumber) == mReports.end()) mReports.insert(std::make_pair(reportNumber, new ReportModel));
mActiveReports[CSMDoc::State_Verifying] = reportNumber;
getVerifier()->start();
return CSMWorld::UniversalId(CSMWorld::UniversalId::Type_VerificationResults, reportNumber);}
CSMWorld::UniversalId CSMTools::Tools::newSearch(){ mReports.insert(std::make_pair(mNextReportNumber++, new ReportModel(true, false)));
return CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Search, mNextReportNumber - 1);}
void CSMTools::Tools::runSearch(const CSMWorld::UniversalId& searchId, const Search& search){ mActiveReports[CSMDoc::State_Searching] = searchId.getIndex();
if (!mSearch) { mSearchOperation = new SearchOperation(mDocument); mSearch = new CSMDoc::OperationHolder(this, mSearchOperation); connect(mSearch, &CSMDoc::OperationHolder::progress, this, &Tools::progress); connect(mSearch, &CSMDoc::OperationHolder::done, this, &Tools::done); connect(mSearch, &CSMDoc::OperationHolder::reportMessage, this, &Tools::verifierMessage); }
mSearchOperation->configure(search);
mSearch->start();}
void CSMTools::Tools::runMerge(std::unique_ptr<CSMDoc::Document> target){ // not setting an active report, because merge does not produce messages
if (!mMerge) { mMergeOperation = new MergeOperation(mDocument, mEncoding); mMerge = new CSMDoc::OperationHolder(this, mMergeOperation); connect(mMerge, &CSMDoc::OperationHolder::progress, this, &Tools::progress); connect(mMerge, &CSMDoc::OperationHolder::done, this, &Tools::done); connect(mMergeOperation, &MergeOperation::mergeDone, this, &Tools::mergeDone); }
target->flagAsDirty();
mMergeOperation->setTarget(std::move(target));
mMerge->start();}
void CSMTools::Tools::abortOperation(int type){ if (CSMDoc::OperationHolder* operation = get(type)) operation->abort();}
int CSMTools::Tools::getRunningOperations() const{ static const int sOperations[] = { CSMDoc::State_Verifying, CSMDoc::State_Searching, CSMDoc::State_Merging, -1, };
int result = 0;
for (int i = 0; sOperations[i] != -1; ++i) if (const CSMDoc::OperationHolder* operation = get(sOperations[i])) if (operation->isRunning()) result |= sOperations[i];
return result;}
CSMTools::ReportModel* CSMTools::Tools::getReport(const CSMWorld::UniversalId& id){ if (id.getType() != CSMWorld::UniversalId::Type_VerificationResults && id.getType() != CSMWorld::UniversalId::Type_LoadErrorLog && id.getType() != CSMWorld::UniversalId::Type_Search) throw std::logic_error("invalid request for report model: " + id.toString());
return mReports.at(id.getIndex());}
void CSMTools::Tools::verifierMessage(const CSMDoc::Message& message, int type){ std::map<int, int>::iterator iter = mActiveReports.find(type);
if (iter != mActiveReports.end()) mReports[iter->second]->add(message);}