forked from mirror/openmw-tes3mp
Merge branch 'load'
commit
5b9e90744e
@ -0,0 +1,130 @@
|
||||
|
||||
#include "loader.hpp"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "../tools/reportmodel.hpp"
|
||||
|
||||
#include "document.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLeft (false) {}
|
||||
|
||||
|
||||
CSMDoc::Loader::Loader()
|
||||
{
|
||||
QTimer *timer = new QTimer (this);
|
||||
|
||||
connect (timer, SIGNAL (timeout()), this, SLOT (load()));
|
||||
timer->start();
|
||||
}
|
||||
|
||||
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 *, Stage> >::iterator iter = mDocuments.begin();
|
||||
|
||||
Document *document = iter->first;
|
||||
|
||||
int size = static_cast<int> (document->getContentFiles().size());
|
||||
|
||||
if (document->isNew())
|
||||
--size;
|
||||
|
||||
bool done = false;
|
||||
|
||||
const int batchingSize = 100;
|
||||
|
||||
try
|
||||
{
|
||||
if (iter->second.mRecordsLeft)
|
||||
{
|
||||
CSMDoc::Stage::Messages messages;
|
||||
for (int i=0; i<batchingSize; ++i) // do not flood the system with update signals
|
||||
if (document->getData().continueLoading (messages))
|
||||
{
|
||||
iter->second.mRecordsLeft = false;
|
||||
break;
|
||||
}
|
||||
|
||||
CSMWorld::UniversalId log (CSMWorld::UniversalId::Type_LoadErrorLog, 0);
|
||||
|
||||
for (CSMDoc::Stage::Messages::const_iterator iter (messages.begin());
|
||||
iter!=messages.end(); ++iter)
|
||||
{
|
||||
document->getReport (log)->add (iter->first, iter->second);
|
||||
emit loadMessage (document, iter->second);
|
||||
}
|
||||
|
||||
emit nextRecord (document);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (iter->second.mFile<size)
|
||||
{
|
||||
boost::filesystem::path path = document->getContentFiles()[iter->second.mFile];
|
||||
|
||||
int steps = document->getData().startLoading (path, iter->second.mFile<size-1, false);
|
||||
iter->second.mRecordsLeft = true;
|
||||
|
||||
emit nextStage (document, path.filename().string(), steps/batchingSize);
|
||||
}
|
||||
else if (iter->second.mFile==size)
|
||||
{
|
||||
int steps = document->getData().startLoading (document->getProjectPath(), false, true);
|
||||
iter->second.mRecordsLeft = true;
|
||||
|
||||
emit nextStage (document, "Project File", steps/batchingSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
|
||||
++(iter->second.mFile);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
mDocuments.erase (iter);
|
||||
emit documentNotLoaded (document, e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
if (done)
|
||||
{
|
||||
mDocuments.erase (iter);
|
||||
emit documentLoaded (document);
|
||||
}
|
||||
}
|
||||
|
||||
void CSMDoc::Loader::loadDocument (CSMDoc::Document *document)
|
||||
{
|
||||
mDocuments.push_back (std::make_pair (document, Stage()));
|
||||
}
|
||||
|
||||
void CSMDoc::Loader::abortLoading (CSMDoc::Document *document)
|
||||
{
|
||||
for (std::vector<std::pair<Document *, Stage> >::iterator iter = mDocuments.begin();
|
||||
iter!=mDocuments.end(); ++iter)
|
||||
{
|
||||
if (iter->first==document)
|
||||
{
|
||||
mDocuments.erase (iter);
|
||||
emit documentNotLoaded (document, "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
#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
|
||||
|
||||
struct Stage
|
||||
{
|
||||
int mFile;
|
||||
bool mRecordsLeft;
|
||||
|
||||
Stage();
|
||||
};
|
||||
|
||||
QMutex mMutex;
|
||||
QWaitCondition mThingsToDo;
|
||||
std::vector<std::pair<Document *, Stage> > mDocuments;
|
||||
|
||||
public:
|
||||
|
||||
Loader();
|
||||
|
||||
QWaitCondition& hasThingsToDo();
|
||||
|
||||
private slots:
|
||||
|
||||
void load();
|
||||
|
||||
public slots:
|
||||
|
||||
void loadDocument (CSMDoc::Document *document);
|
||||
///< The ownership of \a document is not transferred.
|
||||
|
||||
void abortLoading (CSMDoc::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.
|
||||
|
||||
void nextStage (CSMDoc::Document *document, const std::string& name, int steps);
|
||||
|
||||
void nextRecord (CSMDoc::Document *document);
|
||||
///< \note This signal is only given once per group of records. The group size is
|
||||
/// approximately the total number of records divided by the steps value of the
|
||||
/// previous nextStage signal.
|
||||
|
||||
void loadMessage (CSMDoc::Document *document, const std::string& message);
|
||||
///< Non-critical load error or warning
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,193 @@
|
||||
|
||||
#include "loader.hpp"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QProgressBar>
|
||||
#include <QCursor>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QCloseEvent>
|
||||
#include <QListWidget>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
||||
void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event)
|
||||
{
|
||||
event->ignore();
|
||||
cancel();
|
||||
}
|
||||
|
||||
CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
|
||||
: mDocument (document), mAborted (false), mMessages (0)
|
||||
{
|
||||
setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str());
|
||||
|
||||
setMinimumWidth (400);
|
||||
|
||||
mLayout = new QVBoxLayout (this);
|
||||
|
||||
// file progress
|
||||
mFile = new QLabel (this);
|
||||
|
||||
mLayout->addWidget (mFile);
|
||||
|
||||
mFileProgress = new QProgressBar (this);
|
||||
|
||||
mLayout->addWidget (mFileProgress);
|
||||
|
||||
int size = static_cast<int> (document->getContentFiles().size())+1;
|
||||
if (document->isNew())
|
||||
--size;
|
||||
|
||||
mFileProgress->setMinimum (0);
|
||||
mFileProgress->setMaximum (size);
|
||||
mFileProgress->setTextVisible (true);
|
||||
mFileProgress->setValue (0);
|
||||
|
||||
// record progress
|
||||
mLayout->addWidget (new QLabel ("Records", this));
|
||||
|
||||
mRecordProgress = new QProgressBar (this);
|
||||
|
||||
mLayout->addWidget (mRecordProgress);
|
||||
|
||||
mRecordProgress->setMinimum (0);
|
||||
mRecordProgress->setTextVisible (true);
|
||||
mRecordProgress->setValue (0);
|
||||
|
||||
// error message
|
||||
mError = new QLabel (this);
|
||||
mError->setWordWrap (true);
|
||||
|
||||
mLayout->addWidget (mError);
|
||||
|
||||
// buttons
|
||||
mButtons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this);
|
||||
|
||||
mLayout->addWidget (mButtons);
|
||||
|
||||
setLayout (mLayout);
|
||||
|
||||
move (QCursor::pos());
|
||||
|
||||
show();
|
||||
|
||||
connect (mButtons, SIGNAL (rejected()), this, SLOT (cancel()));
|
||||
}
|
||||
|
||||
void CSVDoc::LoadingDocument::nextStage (const std::string& name, int steps)
|
||||
{
|
||||
mFile->setText (QString::fromUtf8 (("Loading: " + name).c_str()));
|
||||
|
||||
mFileProgress->setValue (mFileProgress->value()+1);
|
||||
|
||||
mRecordProgress->setValue (0);
|
||||
mRecordProgress->setMaximum (steps>0 ? steps : 1);
|
||||
}
|
||||
|
||||
void CSVDoc::LoadingDocument::nextRecord()
|
||||
{
|
||||
int value = mRecordProgress->value()+1;
|
||||
|
||||
if (value<=mRecordProgress->maximum())
|
||||
mRecordProgress->setValue (value);
|
||||
}
|
||||
|
||||
void CSVDoc::LoadingDocument::abort (const std::string& error)
|
||||
{
|
||||
mAborted = true;
|
||||
mError->setText (QString::fromUtf8 (("Loading failed: " + error).c_str()));
|
||||
mButtons->setStandardButtons (QDialogButtonBox::Close);
|
||||
}
|
||||
|
||||
void CSVDoc::LoadingDocument::addMessage (const std::string& message)
|
||||
{
|
||||
if (!mMessages)
|
||||
{
|
||||
mMessages = new QListWidget (this);
|
||||
mLayout->insertWidget (4, mMessages);
|
||||
}
|
||||
|
||||
new QListWidgetItem (QString::fromUtf8 (message.c_str()), mMessages);
|
||||
}
|
||||
|
||||
void CSVDoc::LoadingDocument::cancel()
|
||||
{
|
||||
if (!mAborted)
|
||||
emit cancel (mDocument);
|
||||
else
|
||||
{
|
||||
emit close (mDocument);
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSVDoc::Loader::Loader() {}
|
||||
|
||||
CSVDoc::Loader::~Loader()
|
||||
{
|
||||
for (std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter (mDocuments.begin());
|
||||
iter!=mDocuments.end(); ++iter)
|
||||
delete iter->second;
|
||||
}
|
||||
|
||||
void CSVDoc::Loader::add (CSMDoc::Document *document)
|
||||
{
|
||||
LoadingDocument *loading = new LoadingDocument (document);
|
||||
mDocuments.insert (std::make_pair (document, loading));
|
||||
|
||||
connect (loading, SIGNAL (cancel (CSMDoc::Document *)),
|
||||
this, SIGNAL (cancel (CSMDoc::Document *)));
|
||||
connect (loading, SIGNAL (close (CSMDoc::Document *)),
|
||||
this, SIGNAL (close (CSMDoc::Document *)));
|
||||
}
|
||||
|
||||
void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed,
|
||||
const std::string& error)
|
||||
{
|
||||
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.begin();
|
||||
|
||||
for (; iter!=mDocuments.end(); ++iter)
|
||||
if (iter->first==document)
|
||||
break;
|
||||
|
||||
if (iter==mDocuments.end())
|
||||
return;
|
||||
|
||||
if (completed || error.empty())
|
||||
{
|
||||
delete iter->second;
|
||||
mDocuments.erase (iter);
|
||||
}
|
||||
else if (!completed && !error.empty())
|
||||
{
|
||||
iter->second->abort (error);
|
||||
// Leave the window open for now (wait for the user to close it)
|
||||
mDocuments.erase (iter);
|
||||
}
|
||||
}
|
||||
|
||||
void CSVDoc::Loader::nextStage (CSMDoc::Document *document, const std::string& name, int steps)
|
||||
{
|
||||
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.find (document);
|
||||
|
||||
if (iter!=mDocuments.end())
|
||||
iter->second->nextStage (name, steps);
|
||||
}
|
||||
|
||||
void CSVDoc::Loader::nextRecord (CSMDoc::Document *document)
|
||||
{
|
||||
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.find (document);
|
||||
|
||||
if (iter!=mDocuments.end())
|
||||
iter->second->nextRecord();
|
||||
}
|
||||
|
||||
void CSVDoc::Loader::loadMessage (CSMDoc::Document *document, const std::string& message)
|
||||
{
|
||||
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.find (document);
|
||||
|
||||
if (iter!=mDocuments.end())
|
||||
iter->second->addMessage (message);
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
#ifndef CSV_DOC_LOADER_H
|
||||
#define CSV_DOC_LOADER_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QSignalMapper>
|
||||
|
||||
class QLabel;
|
||||
class QProgressBar;
|
||||
class QDialogButtonBox;
|
||||
class QListWidget;
|
||||
class QVBoxLayout;
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CSVDoc
|
||||
{
|
||||
class LoadingDocument : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
CSMDoc::Document *mDocument;
|
||||
QLabel *mFile;
|
||||
QProgressBar *mFileProgress;
|
||||
QProgressBar *mRecordProgress;
|
||||
bool mAborted;
|
||||
QDialogButtonBox *mButtons;
|
||||
QLabel *mError;
|
||||
QListWidget *mMessages;
|
||||
QVBoxLayout *mLayout;
|
||||
|
||||
private:
|
||||
|
||||
void closeEvent (QCloseEvent *event);
|
||||
|
||||
public:
|
||||
|
||||
LoadingDocument (CSMDoc::Document *document);
|
||||
|
||||
void nextStage (const std::string& name, int steps);
|
||||
|
||||
void nextRecord();
|
||||
|
||||
void abort (const std::string& error);
|
||||
|
||||
void addMessage (const std::string& message);
|
||||
|
||||
private slots:
|
||||
|
||||
void cancel();
|
||||
|
||||
signals:
|
||||
|
||||
void cancel (CSMDoc::Document *document);
|
||||
///< Stop loading process.
|
||||
|
||||
void close (CSMDoc::Document *document);
|
||||
///< Close stopped loading process.
|
||||
};
|
||||
|
||||
class Loader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
std::map<CSMDoc::Document *, LoadingDocument *> mDocuments;
|
||||
|
||||
public:
|
||||
|
||||
Loader();
|
||||
|
||||
virtual ~Loader();
|
||||
|
||||
signals:
|
||||
|
||||
void cancel (CSMDoc::Document *document);
|
||||
|
||||
void close (CSMDoc::Document *document);
|
||||
|
||||
public slots:
|
||||
|
||||
void add (CSMDoc::Document *document);
|
||||
|
||||
void loadingStopped (CSMDoc::Document *document, bool completed,
|
||||
const std::string& error);
|
||||
|
||||
void nextStage (CSMDoc::Document *document, const std::string& name, int steps);
|
||||
|
||||
void nextRecord (CSMDoc::Document *document);
|
||||
|
||||
void loadMessage (CSMDoc::Document *document, const std::string& message);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue