mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 07:53:53 +00:00
moved loading to a separate thread
This commit is contained in:
parent
e324450118
commit
dbb192f084
7 changed files with 210 additions and 54 deletions
|
@ -5,7 +5,7 @@ opencs_units (. editor)
|
|||
set (CMAKE_BUILD_TYPE DEBUG)
|
||||
|
||||
opencs_units (model/doc
|
||||
document operation saving documentmanager
|
||||
document operation saving documentmanager loader
|
||||
)
|
||||
|
||||
opencs_units_noqt (model/doc
|
||||
|
|
|
@ -2219,68 +2219,32 @@ void CSMDoc::Document::createBase()
|
|||
}
|
||||
}
|
||||
|
||||
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_)
|
||||
: mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir),
|
||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||
(savePath.filename().string() + ".project")),
|
||||
mSaving (*this, mProjectPath)
|
||||
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||
const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir)
|
||||
: mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir),
|
||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||
(savePath.filename().string() + ".project")),
|
||||
mSaving (*this, mProjectPath)
|
||||
{
|
||||
if (files.empty())
|
||||
if (mContentFiles.empty())
|
||||
throw std::runtime_error ("Empty content file sequence");
|
||||
|
||||
if (new_ && files.size()==1)
|
||||
createBase();
|
||||
else
|
||||
{
|
||||
std::vector<boost::filesystem::path>::const_iterator end = files.end();
|
||||
|
||||
if (new_)
|
||||
--end;
|
||||
|
||||
load (files.begin(), end, !new_);
|
||||
}
|
||||
|
||||
if (new_)
|
||||
{
|
||||
mData.setDescription ("");
|
||||
mData.setAuthor ("");
|
||||
}
|
||||
|
||||
bool filtersFound = false;
|
||||
|
||||
if (boost::filesystem::exists (mProjectPath))
|
||||
{
|
||||
filtersFound = true;
|
||||
}
|
||||
else
|
||||
if (!boost::filesystem::exists (mProjectPath))
|
||||
{
|
||||
boost::filesystem::path locCustomFiltersPath (configuration.getUserDataPath());
|
||||
locCustomFiltersPath /= "defaultfilters";
|
||||
|
||||
if (boost::filesystem::exists(locCustomFiltersPath))
|
||||
if (boost::filesystem::exists (locCustomFiltersPath))
|
||||
{
|
||||
boost::filesystem::copy_file (locCustomFiltersPath, mProjectPath);
|
||||
filtersFound = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::filesystem::path filters(mResDir);
|
||||
filters /= "defaultfilters";
|
||||
|
||||
if (boost::filesystem::exists(filters))
|
||||
{
|
||||
boost::filesystem::copy_file(filters, mProjectPath);
|
||||
filtersFound = true;
|
||||
}
|
||||
boost::filesystem::copy_file (mResDir / "defaultfilters", mProjectPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (filtersFound)
|
||||
getData().loadFile (mProjectPath, false, true);
|
||||
|
||||
addOptionalGmsts();
|
||||
addOptionalGlobals();
|
||||
|
||||
connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));
|
||||
|
||||
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||
|
@ -2289,13 +2253,39 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, co
|
|||
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||
connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int)));
|
||||
connect (&mSaving, SIGNAL (reportMessage (const QString&, int)),
|
||||
this, SLOT (reportMessage (const QString&, int)));
|
||||
this, SLOT (reportMessage (const QString&, int)));
|
||||
}
|
||||
|
||||
CSMDoc::Document::~Document()
|
||||
{
|
||||
}
|
||||
|
||||
void CSMDoc::Document::setupData (bool new_)
|
||||
{
|
||||
if (new_ && mContentFiles.size()==1)
|
||||
createBase();
|
||||
else
|
||||
{
|
||||
std::vector<boost::filesystem::path>::const_iterator end = mContentFiles.end();
|
||||
|
||||
if (new_)
|
||||
--end;
|
||||
|
||||
load (mContentFiles.begin(), end, !new_);
|
||||
}
|
||||
|
||||
if (new_)
|
||||
{
|
||||
mData.setDescription ("");
|
||||
mData.setAuthor ("");
|
||||
}
|
||||
|
||||
getData().loadFile (mProjectPath, false, true);
|
||||
|
||||
addOptionalGmsts();
|
||||
addOptionalGlobals();
|
||||
}
|
||||
|
||||
QUndoStack& CSMDoc::Document::getUndoStack()
|
||||
{
|
||||
return mUndoStack;
|
||||
|
|
|
@ -72,12 +72,13 @@ namespace CSMDoc
|
|||
public:
|
||||
|
||||
Document (const Files::ConfigurationManager& configuration,
|
||||
const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath,
|
||||
const boost::filesystem::path& resDir, bool new_);
|
||||
const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir);
|
||||
|
||||
~Document();
|
||||
|
||||
void setupData (bool new_);
|
||||
|
||||
QUndoStack& getUndoStack();
|
||||
|
||||
int getState() const;
|
||||
|
|
|
@ -19,10 +19,24 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con
|
|||
|
||||
if (!boost::filesystem::is_directory (projectPath))
|
||||
boost::filesystem::create_directories (projectPath);
|
||||
|
||||
mLoader.moveToThread (&mLoaderThread);
|
||||
mLoaderThread.start();
|
||||
|
||||
connect (&mLoader, SIGNAL (documentLoaded (Document *)),
|
||||
this, SLOT (documentLoaded (Document *)));
|
||||
connect (&mLoader, SIGNAL (documentNotLoaded (Document *, const std::string&)),
|
||||
this, SLOT (documentNotLoaded (Document *, const std::string&)));
|
||||
connect (this, SIGNAL (loadRequest (Document *, bool)),
|
||||
&mLoader, SLOT (loadDocument (Document *, bool)));
|
||||
}
|
||||
|
||||
CSMDoc::DocumentManager::~DocumentManager()
|
||||
{
|
||||
mLoaderThread.quit();
|
||||
mLoader.hasThingsToDo().wakeAll();
|
||||
mLoaderThread.wait();
|
||||
|
||||
for (std::vector<Document *>::iterator iter (mDocuments.begin()); iter!=mDocuments.end(); ++iter)
|
||||
delete *iter;
|
||||
}
|
||||
|
@ -30,11 +44,13 @@ CSMDoc::DocumentManager::~DocumentManager()
|
|||
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
||||
bool new_)
|
||||
{
|
||||
Document *document = new Document (mConfiguration, files, savePath, mResDir, new_);
|
||||
Document *document = new Document (mConfiguration, files, savePath, mResDir);
|
||||
|
||||
mDocuments.push_back (document);
|
||||
|
||||
emit documentAdded (document);
|
||||
emit loadRequest (document, new_);
|
||||
|
||||
mLoader.hasThingsToDo().wakeAll();
|
||||
}
|
||||
|
||||
bool CSMDoc::DocumentManager::removeDocument (Document *document)
|
||||
|
@ -54,3 +70,15 @@ void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& par
|
|||
{
|
||||
mResDir = boost::filesystem::system_complete(parResDir);
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::documentLoaded (Document *document)
|
||||
{
|
||||
emit documentAdded (document);
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::string& error)
|
||||
{
|
||||
removeDocument (document);
|
||||
/// \todo report error
|
||||
/// \todo handle removeDocument returning true
|
||||
}
|
|
@ -7,6 +7,9 @@
|
|||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
|
||||
#include "loader.hpp"
|
||||
|
||||
namespace Files
|
||||
{
|
||||
|
@ -23,6 +26,8 @@ namespace CSMDoc
|
|||
|
||||
std::vector<Document *> mDocuments;
|
||||
const Files::ConfigurationManager& mConfiguration;
|
||||
QThread mLoaderThread;
|
||||
Loader mLoader;
|
||||
|
||||
DocumentManager (const DocumentManager&);
|
||||
DocumentManager& operator= (const DocumentManager&);
|
||||
|
@ -47,9 +52,20 @@ namespace CSMDoc
|
|||
|
||||
boost::filesystem::path mResDir;
|
||||
|
||||
private slots:
|
||||
|
||||
void documentLoaded (Document *document);
|
||||
///< The ownership of \a document is not transferred.
|
||||
|
||||
void documentNotLoaded (Document *document, const std::string& error);
|
||||
///< Document load has been interrupted either because of a call to abortLoading
|
||||
/// or a problem during loading). In the former case error will be an empty string.
|
||||
|
||||
signals:
|
||||
|
||||
void documentAdded (CSMDoc::Document *document);
|
||||
|
||||
void loadRequest (Document *document, bool _new);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
66
apps/opencs/model/doc/loader.cpp
Normal file
66
apps/opencs/model/doc/loader.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
|
||||
#include "loader.hpp"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "document.hpp"
|
||||
|
||||
CSMDoc::Loader::Loader()
|
||||
{
|
||||
QTimer *timer = new QTimer (this);
|
||||
|
||||
connect (timer, SIGNAL (timeout()), this, SLOT (load()));
|
||||
timer->start (1000);
|
||||
}
|
||||
|
||||
QWaitCondition& CSMDoc::Loader::hasThingsToDo()
|
||||
{
|
||||
return mThingsToDo;
|
||||
}
|
||||
|
||||
void CSMDoc::Loader::load()
|
||||
{
|
||||
if (mDocuments.empty())
|
||||
{
|
||||
mMutex.lock();
|
||||
mThingsToDo.wait (&mMutex);
|
||||
mMutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::pair<Document *, bool> >::iterator iter = mDocuments.begin();
|
||||
|
||||
Document *document = iter->first;
|
||||
bool new_ = iter->second;
|
||||
|
||||
mDocuments.erase (iter);
|
||||
|
||||
try
|
||||
{
|
||||
document->setupData (new_);
|
||||
emit documentLoaded (document);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
emit documentNotLoaded (document, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void CSMDoc::Loader::loadDocument (Document *document, bool new_)
|
||||
{
|
||||
mDocuments.push_back (std::make_pair (document, new_));
|
||||
}
|
||||
|
||||
void CSMDoc::Loader::abortLoading (Document *document)
|
||||
{
|
||||
for (std::vector<std::pair<Document *, bool> >::iterator iter = mDocuments.begin();
|
||||
iter!=mDocuments.end(); ++iter)
|
||||
{
|
||||
if (iter->first==document)
|
||||
{
|
||||
mDocuments.erase (iter);
|
||||
emit documentNotLoaded (document, "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
55
apps/opencs/model/doc/loader.hpp
Normal file
55
apps/opencs/model/doc/loader.hpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#ifndef CSM_DOC_LOADER_H
|
||||
#define CSM_DOC_LOADER_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Document;
|
||||
|
||||
class Loader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QMutex mMutex;
|
||||
QWaitCondition mThingsToDo;
|
||||
std::vector<std::pair<Document *, bool> > mDocuments;
|
||||
|
||||
public:
|
||||
|
||||
Loader();
|
||||
|
||||
QWaitCondition& hasThingsToDo();
|
||||
|
||||
private slots:
|
||||
|
||||
void load();
|
||||
|
||||
public slots:
|
||||
|
||||
void loadDocument (Document *document, bool new_);
|
||||
///< The ownership of \a document is not transferred.
|
||||
/// \param new_ Do not load the last content file in the files list specified in
|
||||
/// \a document and instead create it in an appropriate way.
|
||||
|
||||
void abortLoading (Document *document);
|
||||
///< Abort loading \a docuemnt (ignored if \a document has already finished being
|
||||
/// loaded). Will result in a documentNotLoaded signal, once the Loader has finished
|
||||
/// cleaning up.
|
||||
|
||||
signals:
|
||||
|
||||
void documentLoaded (Document *document);
|
||||
///< The ownership of \a document is not transferred.
|
||||
|
||||
void documentNotLoaded (Document *document, const std::string& error);
|
||||
///< Document load has been interrupted either because of a call to abortLoading
|
||||
/// or a problem during loading). In the former case error will be an empty string.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue