mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-21 14:09:39 +00:00
split up load function in a start and continue part
This commit is contained in:
parent
0b309d9ef4
commit
6692d2dc72
4 changed files with 187 additions and 141 deletions
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
CSMDoc::Loader::Stage::Stage() : mFile (0) {}
|
CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLeft (false) {}
|
||||||
|
|
||||||
|
|
||||||
CSMDoc::Loader::Loader()
|
CSMDoc::Loader::Loader()
|
||||||
|
@ -13,7 +13,7 @@ CSMDoc::Loader::Loader()
|
||||||
QTimer *timer = new QTimer (this);
|
QTimer *timer = new QTimer (this);
|
||||||
|
|
||||||
connect (timer, SIGNAL (timeout()), this, SLOT (load()));
|
connect (timer, SIGNAL (timeout()), this, SLOT (load()));
|
||||||
timer->start (1000);
|
timer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
QWaitCondition& CSMDoc::Loader::hasThingsToDo()
|
QWaitCondition& CSMDoc::Loader::hasThingsToDo()
|
||||||
|
@ -44,19 +44,29 @@ void CSMDoc::Loader::load()
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (iter->second.mRecordsLeft)
|
||||||
|
{
|
||||||
|
if (document->getData().continueLoading())
|
||||||
|
iter->second.mRecordsLeft = false;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (iter->second.mFile<size)
|
if (iter->second.mFile<size)
|
||||||
{
|
{
|
||||||
boost::filesystem::path path = document->getContentFiles()[iter->second.mFile];
|
boost::filesystem::path path = document->getContentFiles()[iter->second.mFile];
|
||||||
|
|
||||||
emit nextStage (document, path.filename().string());
|
emit nextStage (document, path.filename().string());
|
||||||
|
|
||||||
document->getData().loadFile (path, iter->second.mFile<size-1, false);
|
document->getData().startLoading (path, iter->second.mFile<size-1, false);
|
||||||
|
iter->second.mRecordsLeft = true;
|
||||||
}
|
}
|
||||||
else if (iter->second.mFile==size)
|
else if (iter->second.mFile==size)
|
||||||
{
|
{
|
||||||
emit nextStage (document, "Project File");
|
emit nextStage (document, "Project File");
|
||||||
|
|
||||||
document->getData().loadFile (document->getProjectPath(), false, true);
|
document->getData().startLoading (document->getProjectPath(), false, true);
|
||||||
|
iter->second.mRecordsLeft = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace CSMDoc
|
||||||
struct Stage
|
struct Stage
|
||||||
{
|
{
|
||||||
int mFile;
|
int mFile;
|
||||||
|
bool mRecordsLeft;
|
||||||
|
|
||||||
Stage();
|
Stage();
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,7 +55,10 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::Data::Data() : mRefs (mCells)
|
CSMWorld::Data::Data()
|
||||||
|
/// \todo set encoding properly, once config implementation has been fixed.
|
||||||
|
: mEncoder (ToUTF8::calculateEncoding ("win1252")),
|
||||||
|
mRefs (mCells), mReader (0), mDialogue (0)
|
||||||
{
|
{
|
||||||
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
||||||
mGlobals.addColumn (new RecordStateColumn<ESM::Global>);
|
mGlobals.addColumn (new RecordStateColumn<ESM::Global>);
|
||||||
|
@ -260,6 +263,8 @@ CSMWorld::Data::~Data()
|
||||||
{
|
{
|
||||||
for (std::vector<QAbstractItemModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
|
for (std::vector<QAbstractItemModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
|
||||||
delete *iter;
|
delete *iter;
|
||||||
|
|
||||||
|
delete mReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals() const
|
const CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals() const
|
||||||
|
@ -481,148 +486,162 @@ void CSMWorld::Data::merge()
|
||||||
mGlobals.merge();
|
mGlobals.merge();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base, bool project)
|
int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base, bool project)
|
||||||
{
|
{
|
||||||
ESM::ESMReader reader;
|
delete mReader;
|
||||||
|
mReader = 0;
|
||||||
|
mDialogue = 0;
|
||||||
|
|
||||||
/// \todo set encoding properly, once config implementation has been fixed.
|
mReader = new ESM::ESMReader;
|
||||||
ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding ("win1252"));
|
mReader->setEncoder (&mEncoder);
|
||||||
reader.setEncoder (&encoder);
|
mReader->open (path.string());
|
||||||
|
|
||||||
reader.open (path.string());
|
mBase = base;
|
||||||
|
mProject = project;
|
||||||
|
|
||||||
const ESM::Dialogue *dialogue = 0;
|
mAuthor = mReader->getAuthor();
|
||||||
|
mDescription = mReader->getDesc();
|
||||||
|
|
||||||
mAuthor = reader.getAuthor();
|
return mReader->getRecordCount();
|
||||||
mDescription = reader.getDesc();
|
}
|
||||||
|
|
||||||
// Note: We do not need to send update signals here, because at this point the model is not connected
|
bool CSMWorld::Data::continueLoading()
|
||||||
// to any view.
|
{
|
||||||
while (reader.hasMoreRecs())
|
if (!mReader)
|
||||||
|
throw std::logic_error ("can't continue loading, because no load has been started");
|
||||||
|
|
||||||
|
if (!mReader->hasMoreRecs())
|
||||||
{
|
{
|
||||||
ESM::NAME n = reader.getRecName();
|
delete mReader;
|
||||||
reader.getRecHeader();
|
mReader = 0;
|
||||||
|
mDialogue = 0;
|
||||||
switch (n.val)
|
return true;
|
||||||
{
|
|
||||||
case ESM::REC_GLOB: mGlobals.load (reader, base); break;
|
|
||||||
case ESM::REC_GMST: mGmsts.load (reader, base); break;
|
|
||||||
case ESM::REC_SKIL: mSkills.load (reader, base); break;
|
|
||||||
case ESM::REC_CLAS: mClasses.load (reader, base); break;
|
|
||||||
case ESM::REC_FACT: mFactions.load (reader, base); break;
|
|
||||||
case ESM::REC_RACE: mRaces.load (reader, base); break;
|
|
||||||
case ESM::REC_SOUN: mSounds.load (reader, base); break;
|
|
||||||
case ESM::REC_SCPT: mScripts.load (reader, base); break;
|
|
||||||
case ESM::REC_REGN: mRegions.load (reader, base); break;
|
|
||||||
case ESM::REC_BSGN: mBirthsigns.load (reader, base); break;
|
|
||||||
case ESM::REC_SPEL: mSpells.load (reader, base); break;
|
|
||||||
|
|
||||||
case ESM::REC_CELL:
|
|
||||||
mCells.load (reader, base);
|
|
||||||
mRefs.load (reader, mCells.getSize()-1, base);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ESM::REC_ACTI: mReferenceables.load (reader, base, UniversalId::Type_Activator); break;
|
|
||||||
case ESM::REC_ALCH: mReferenceables.load (reader, base, UniversalId::Type_Potion); break;
|
|
||||||
case ESM::REC_APPA: mReferenceables.load (reader, base, UniversalId::Type_Apparatus); break;
|
|
||||||
case ESM::REC_ARMO: mReferenceables.load (reader, base, UniversalId::Type_Armor); break;
|
|
||||||
case ESM::REC_BOOK: mReferenceables.load (reader, base, UniversalId::Type_Book); break;
|
|
||||||
case ESM::REC_CLOT: mReferenceables.load (reader, base, UniversalId::Type_Clothing); break;
|
|
||||||
case ESM::REC_CONT: mReferenceables.load (reader, base, UniversalId::Type_Container); break;
|
|
||||||
case ESM::REC_CREA: mReferenceables.load (reader, base, UniversalId::Type_Creature); break;
|
|
||||||
case ESM::REC_DOOR: mReferenceables.load (reader, base, UniversalId::Type_Door); break;
|
|
||||||
case ESM::REC_INGR: mReferenceables.load (reader, base, UniversalId::Type_Ingredient); break;
|
|
||||||
case ESM::REC_LEVC:
|
|
||||||
mReferenceables.load (reader, base, UniversalId::Type_CreatureLevelledList); break;
|
|
||||||
case ESM::REC_LEVI:
|
|
||||||
mReferenceables.load (reader, base, UniversalId::Type_ItemLevelledList); break;
|
|
||||||
case ESM::REC_LIGH: mReferenceables.load (reader, base, UniversalId::Type_Light); break;
|
|
||||||
case ESM::REC_LOCK: mReferenceables.load (reader, base, UniversalId::Type_Lockpick); break;
|
|
||||||
case ESM::REC_MISC:
|
|
||||||
mReferenceables.load (reader, base, UniversalId::Type_Miscellaneous); break;
|
|
||||||
case ESM::REC_NPC_: mReferenceables.load (reader, base, UniversalId::Type_Npc); break;
|
|
||||||
case ESM::REC_PROB: mReferenceables.load (reader, base, UniversalId::Type_Probe); break;
|
|
||||||
case ESM::REC_REPA: mReferenceables.load (reader, base, UniversalId::Type_Repair); break;
|
|
||||||
case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break;
|
|
||||||
case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break;
|
|
||||||
|
|
||||||
case ESM::REC_DIAL:
|
|
||||||
{
|
|
||||||
std::string id = reader.getHNOString ("NAME");
|
|
||||||
|
|
||||||
ESM::Dialogue record;
|
|
||||||
record.mId = id;
|
|
||||||
record.load (reader);
|
|
||||||
|
|
||||||
if (record.mType==ESM::Dialogue::Journal)
|
|
||||||
{
|
|
||||||
mJournals.load (record, base);
|
|
||||||
dialogue = &mJournals.getRecord (id).get();
|
|
||||||
}
|
|
||||||
else if (record.mType==ESM::Dialogue::Deleted)
|
|
||||||
{
|
|
||||||
dialogue = 0; // record vector can be shuffled around which would make pointer
|
|
||||||
// to record invalid
|
|
||||||
|
|
||||||
if (mJournals.tryDelete (id))
|
|
||||||
{
|
|
||||||
/// \todo handle info records
|
|
||||||
}
|
|
||||||
else if (mTopics.tryDelete (id))
|
|
||||||
{
|
|
||||||
/// \todo handle info records
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/// \todo report deletion of non-existing record
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mTopics.load (record, base);
|
|
||||||
dialogue = &mTopics.getRecord (id).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ESM::REC_INFO:
|
|
||||||
{
|
|
||||||
if (!dialogue)
|
|
||||||
{
|
|
||||||
/// \todo INFO record without matching DIAL record -> report to user
|
|
||||||
reader.skipRecord();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dialogue->mType==ESM::Dialogue::Journal)
|
|
||||||
mJournalInfos.load (reader, base, *dialogue);
|
|
||||||
else
|
|
||||||
mTopicInfos.load (reader, base, *dialogue);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ESM::REC_FILT:
|
|
||||||
|
|
||||||
if (project)
|
|
||||||
{
|
|
||||||
mFilters.load (reader, base);
|
|
||||||
mFilters.setData (mFilters.getSize()-1,
|
|
||||||
mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope),
|
|
||||||
static_cast<int> (CSMFilter::Filter::Scope_Project));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fall through (filter record in a content file is an error with format 0)
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
/// \todo throw an exception instead, once all records are implemented
|
|
||||||
/// or maybe report error and continue?
|
|
||||||
reader.skipRecord();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESM::NAME n = mReader->getRecName();
|
||||||
|
mReader->getRecHeader();
|
||||||
|
|
||||||
|
switch (n.val)
|
||||||
|
{
|
||||||
|
case ESM::REC_GLOB: mGlobals.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_GMST: mGmsts.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_SKIL: mSkills.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_CLAS: mClasses.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_FACT: mFactions.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_RACE: mRaces.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_SOUN: mSounds.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_SCPT: mScripts.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_REGN: mRegions.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_BSGN: mBirthsigns.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_SPEL: mSpells.load (*mReader, mBase); break;
|
||||||
|
|
||||||
|
case ESM::REC_CELL:
|
||||||
|
mCells.load (*mReader, mBase);
|
||||||
|
mRefs.load (*mReader, mCells.getSize()-1, mBase);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESM::REC_ACTI: mReferenceables.load (*mReader, mBase, UniversalId::Type_Activator); break;
|
||||||
|
case ESM::REC_ALCH: mReferenceables.load (*mReader, mBase, UniversalId::Type_Potion); break;
|
||||||
|
case ESM::REC_APPA: mReferenceables.load (*mReader, mBase, UniversalId::Type_Apparatus); break;
|
||||||
|
case ESM::REC_ARMO: mReferenceables.load (*mReader, mBase, UniversalId::Type_Armor); break;
|
||||||
|
case ESM::REC_BOOK: mReferenceables.load (*mReader, mBase, UniversalId::Type_Book); break;
|
||||||
|
case ESM::REC_CLOT: mReferenceables.load (*mReader, mBase, UniversalId::Type_Clothing); break;
|
||||||
|
case ESM::REC_CONT: mReferenceables.load (*mReader, mBase, UniversalId::Type_Container); break;
|
||||||
|
case ESM::REC_CREA: mReferenceables.load (*mReader, mBase, UniversalId::Type_Creature); break;
|
||||||
|
case ESM::REC_DOOR: mReferenceables.load (*mReader, mBase, UniversalId::Type_Door); break;
|
||||||
|
case ESM::REC_INGR: mReferenceables.load (*mReader, mBase, UniversalId::Type_Ingredient); break;
|
||||||
|
case ESM::REC_LEVC:
|
||||||
|
mReferenceables.load (*mReader, mBase, UniversalId::Type_CreatureLevelledList); break;
|
||||||
|
case ESM::REC_LEVI:
|
||||||
|
mReferenceables.load (*mReader, mBase, UniversalId::Type_ItemLevelledList); break;
|
||||||
|
case ESM::REC_LIGH: mReferenceables.load (*mReader, mBase, UniversalId::Type_Light); break;
|
||||||
|
case ESM::REC_LOCK: mReferenceables.load (*mReader, mBase, UniversalId::Type_Lockpick); break;
|
||||||
|
case ESM::REC_MISC:
|
||||||
|
mReferenceables.load (*mReader, mBase, UniversalId::Type_Miscellaneous); break;
|
||||||
|
case ESM::REC_NPC_: mReferenceables.load (*mReader, mBase, UniversalId::Type_Npc); break;
|
||||||
|
case ESM::REC_PROB: mReferenceables.load (*mReader, mBase, UniversalId::Type_Probe); break;
|
||||||
|
case ESM::REC_REPA: mReferenceables.load (*mReader, mBase, UniversalId::Type_Repair); break;
|
||||||
|
case ESM::REC_STAT: mReferenceables.load (*mReader, mBase, UniversalId::Type_Static); break;
|
||||||
|
case ESM::REC_WEAP: mReferenceables.load (*mReader, mBase, UniversalId::Type_Weapon); break;
|
||||||
|
|
||||||
|
case ESM::REC_DIAL:
|
||||||
|
{
|
||||||
|
std::string id = mReader->getHNOString ("NAME");
|
||||||
|
|
||||||
|
ESM::Dialogue record;
|
||||||
|
record.mId = id;
|
||||||
|
record.load (*mReader);
|
||||||
|
|
||||||
|
if (record.mType==ESM::Dialogue::Journal)
|
||||||
|
{
|
||||||
|
mJournals.load (record, mBase);
|
||||||
|
mDialogue = &mJournals.getRecord (id).get();
|
||||||
|
}
|
||||||
|
else if (record.mType==ESM::Dialogue::Deleted)
|
||||||
|
{
|
||||||
|
mDialogue = 0; // record vector can be shuffled around which would make pointer
|
||||||
|
// to record invalid
|
||||||
|
|
||||||
|
if (mJournals.tryDelete (id))
|
||||||
|
{
|
||||||
|
/// \todo handle info records
|
||||||
|
}
|
||||||
|
else if (mTopics.tryDelete (id))
|
||||||
|
{
|
||||||
|
/// \todo handle info records
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// \todo report deletion of non-existing record
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mTopics.load (record, mBase);
|
||||||
|
mDialogue = &mTopics.getRecord (id).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ESM::REC_INFO:
|
||||||
|
{
|
||||||
|
if (!mDialogue)
|
||||||
|
{
|
||||||
|
/// \todo INFO record without matching DIAL record -> report to user
|
||||||
|
mReader->skipRecord();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDialogue->mType==ESM::Dialogue::Journal)
|
||||||
|
mJournalInfos.load (*mReader, mBase, *mDialogue);
|
||||||
|
else
|
||||||
|
mTopicInfos.load (*mReader, mBase, *mDialogue);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ESM::REC_FILT:
|
||||||
|
|
||||||
|
if (mProject)
|
||||||
|
{
|
||||||
|
mFilters.load (*mReader, mBase);
|
||||||
|
mFilters.setData (mFilters.getSize()-1,
|
||||||
|
mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope),
|
||||||
|
static_cast<int> (CSMFilter::Filter::Scope_Project));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall through (filter record in a content file is an error with format 0)
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
/// \todo throw an exception instead, once all records are implemented
|
||||||
|
/// or maybe report error and continue?
|
||||||
|
mReader->skipRecord();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMWorld::Data::hasId (const std::string& id) const
|
bool CSMWorld::Data::hasId (const std::string& id) const
|
||||||
|
|
|
@ -33,12 +33,19 @@
|
||||||
|
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
struct Dialogue;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
class Data : public QObject
|
class Data : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
ToUTF8::Utf8Encoder mEncoder;
|
||||||
IdCollection<ESM::Global> mGlobals;
|
IdCollection<ESM::Global> mGlobals;
|
||||||
IdCollection<ESM::GameSetting> mGmsts;
|
IdCollection<ESM::GameSetting> mGmsts;
|
||||||
IdCollection<ESM::Skill> mSkills;
|
IdCollection<ESM::Skill> mSkills;
|
||||||
|
@ -62,6 +69,10 @@ namespace CSMWorld
|
||||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||||
std::string mAuthor;
|
std::string mAuthor;
|
||||||
std::string mDescription;
|
std::string mDescription;
|
||||||
|
ESM::ESMReader *mReader;
|
||||||
|
const ESM::Dialogue *mDialogue; // last loaded dialogue
|
||||||
|
bool mBase;
|
||||||
|
bool mProject;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Data (const Data&);
|
Data (const Data&);
|
||||||
|
@ -167,10 +178,15 @@ namespace CSMWorld
|
||||||
void merge();
|
void merge();
|
||||||
///< Merge modified into base.
|
///< Merge modified into base.
|
||||||
|
|
||||||
void loadFile (const boost::filesystem::path& path, bool base, bool project);
|
int startLoading (const boost::filesystem::path& path, bool base, bool project);
|
||||||
///< Merging content of a file into base or modified.
|
///< Begin merging content of a file into base or modified.
|
||||||
///
|
///
|
||||||
/// \param project load project file instead of content file
|
/// \param project load project file instead of content file
|
||||||
|
///
|
||||||
|
///< \return estimated number of records
|
||||||
|
|
||||||
|
bool continueLoading();
|
||||||
|
///< \return Finished?
|
||||||
|
|
||||||
bool hasId (const std::string& id) const;
|
bool hasId (const std::string& id) const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue