From e3244501184f2c0b6e422f6d566f8853fd6d27f1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Apr 2014 09:02:58 +0200 Subject: [PATCH 01/19] replaced return value of DocumentManager::addDocument with a signal --- apps/opencs/CMakeLists.txt | 4 ++-- apps/opencs/editor.cpp | 18 +++++++++------- apps/opencs/editor.hpp | 2 ++ apps/opencs/model/doc/documentmanager.cpp | 4 ++-- apps/opencs/model/doc/documentmanager.hpp | 25 +++++++++++++++-------- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index cbe90b1d3e..1db922afab 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -5,11 +5,11 @@ opencs_units (. editor) set (CMAKE_BUILD_TYPE DEBUG) opencs_units (model/doc - document operation saving + document operation saving documentmanager ) opencs_units_noqt (model/doc - documentmanager stage savingstate savingstages + stage savingstate savingstages ) opencs_hdrs_noqt (model/doc diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 87660a60bc..de68098395 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -37,6 +37,9 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) mNewGame.setLocalData (mLocal); mFileDialog.setLocalData (mLocal); + connect (&mDocumentManager, SIGNAL (documentAdded (CSMDoc::Document *)), + this, SLOT (documentAdded (CSMDoc::Document *))); + connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ())); connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ())); connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ())); @@ -150,9 +153,8 @@ void CS::Editor::openFiles (const boost::filesystem::path &savePath) foreach (const QString &path, mFileDialog.selectedFilePaths()) files.push_back(path.toUtf8().constData()); - CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, false); + mDocumentManager.addDocument (files, savePath, false); - mViewManager.addView (document); mFileDialog.hide(); } @@ -166,9 +168,8 @@ void CS::Editor::createNewFile (const boost::filesystem::path &savePath) files.push_back(mFileDialog.filename().toUtf8().constData()); - CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, true); + mDocumentManager.addDocument (files, savePath, true); - mViewManager.addView (document); mFileDialog.hide(); } @@ -178,9 +179,7 @@ void CS::Editor::createNewGame (const boost::filesystem::path& file) files.push_back (file); - CSMDoc::Document *document = mDocumentManager.addDocument (files, file, true); - - mViewManager.addView (document); + mDocumentManager.addDocument (files, file, true); mNewGame.hide(); } @@ -287,3 +286,8 @@ std::auto_ptr CS::Editor::setupGraphics() return factory; } + +void CS::Editor::documentAdded (CSMDoc::Document *document) +{ + mViewManager.addView (document); +} \ No newline at end of file diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 164398fb73..53afee0484 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -85,6 +85,8 @@ namespace CS void showSettings(); + void documentAdded (CSMDoc::Document *document); + private: QString mIpcServerName; diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 3ff75c9c15..3f19269e7b 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -27,14 +27,14 @@ CSMDoc::DocumentManager::~DocumentManager() delete *iter; } -CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, +void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { Document *document = new Document (mConfiguration, files, savePath, mResDir, new_); mDocuments.push_back (document); - return document; + emit documentAdded (document); } bool CSMDoc::DocumentManager::removeDocument (Document *document) diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index b969862e99..e41c490298 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -6,6 +6,8 @@ #include +#include + namespace Files { class ConfigurationManager; @@ -15,8 +17,10 @@ namespace CSMDoc { class Document; - class DocumentManager + class DocumentManager : public QObject { + Q_OBJECT + std::vector mDocuments; const Files::ConfigurationManager& mConfiguration; @@ -29,20 +33,23 @@ namespace CSMDoc ~DocumentManager(); - Document *addDocument (const std::vector< boost::filesystem::path >& files, - const boost::filesystem::path& savePath, - bool new_); - ///< The ownership of the returned document is not transferred to the caller. - /// - /// \param new_ Do not load the last content file in \a files and instead create in an + void addDocument (const std::vector< boost::filesystem::path >& files, + const boost::filesystem::path& savePath, bool new_); + ///< \param new_ Do not load the last content file in \a files and instead create in an /// appropriate way. bool removeDocument (Document *document); ///< \return last document removed? + void setResourceDir (const boost::filesystem::path& parResDir); - - private: + + private: + boost::filesystem::path mResDir; + + signals: + + void documentAdded (CSMDoc::Document *document); }; } From dbb192f084c53be4ebb475ae63692b5a73a7128f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 Apr 2014 15:09:25 +0200 Subject: [PATCH 02/19] moved loading to a separate thread --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/doc/document.cpp | 86 ++++++++++------------- apps/opencs/model/doc/document.hpp | 7 +- apps/opencs/model/doc/documentmanager.cpp | 32 ++++++++- apps/opencs/model/doc/documentmanager.hpp | 16 +++++ apps/opencs/model/doc/loader.cpp | 66 +++++++++++++++++ apps/opencs/model/doc/loader.hpp | 55 +++++++++++++++ 7 files changed, 210 insertions(+), 54 deletions(-) create mode 100644 apps/opencs/model/doc/loader.cpp create mode 100644 apps/opencs/model/doc/loader.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 1db922afab..f1d50467bd 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -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 diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 3ef14ee7e5..20a355d483 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -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::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::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; diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 201fb4342a..c7d87e16a0 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -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; diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 3f19269e7b..51774e4ffa 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -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::iterator iter (mDocuments.begin()); iter!=mDocuments.end(); ++iter) delete *iter; } @@ -30,11 +44,13 @@ CSMDoc::DocumentManager::~DocumentManager() void CSMDoc::DocumentManager::addDocument (const std::vector& 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 +} \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index e41c490298..c30c83c066 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -7,6 +7,9 @@ #include #include +#include + +#include "loader.hpp" namespace Files { @@ -23,6 +26,8 @@ namespace CSMDoc std::vector 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); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp new file mode 100644 index 0000000000..722e903641 --- /dev/null +++ b/apps/opencs/model/doc/loader.cpp @@ -0,0 +1,66 @@ + +#include "loader.hpp" + +#include + +#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 >::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 >::iterator iter = mDocuments.begin(); + iter!=mDocuments.end(); ++iter) + { + if (iter->first==document) + { + mDocuments.erase (iter); + emit documentNotLoaded (document, ""); + break; + } + } +} \ No newline at end of file diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp new file mode 100644 index 0000000000..eae0c8001a --- /dev/null +++ b/apps/opencs/model/doc/loader.hpp @@ -0,0 +1,55 @@ +#ifndef CSM_DOC_LOADER_H +#define CSM_DOC_LOADER_H + +#include + +#include +#include +#include + +namespace CSMDoc +{ + class Document; + + class Loader : public QObject + { + Q_OBJECT + + QMutex mMutex; + QWaitCondition mThingsToDo; + std::vector > 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 From ddb0496dca76d7aa357f20feabc857abc74dc151 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Apr 2014 13:11:27 +0200 Subject: [PATCH 03/19] replaced return value of removeDocument with a signal --- apps/opencs/editor.cpp | 7 +++++++ apps/opencs/editor.hpp | 2 ++ apps/opencs/model/doc/documentmanager.cpp | 8 ++++---- apps/opencs/model/doc/documentmanager.hpp | 6 ++++-- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index de68098395..f13c85e73e 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -39,6 +39,8 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) connect (&mDocumentManager, SIGNAL (documentAdded (CSMDoc::Document *)), this, SLOT (documentAdded (CSMDoc::Document *))); + connect (&mDocumentManager, SIGNAL (lastDocumentDeleted()), + this, SLOT (lastDocumentDeleted())); connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ())); connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ())); @@ -290,4 +292,9 @@ std::auto_ptr CS::Editor::setupGraphics() void CS::Editor::documentAdded (CSMDoc::Document *document) { mViewManager.addView (document); +} + +void CS::Editor::lastDocumentDeleted() +{ + exit (0); } \ No newline at end of file diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 53afee0484..d1825e5af3 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -87,6 +87,8 @@ namespace CS void documentAdded (CSMDoc::Document *document); + void lastDocumentDeleted(); + private: QString mIpcServerName; diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 51774e4ffa..b8372eb4c5 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -53,17 +53,18 @@ void CSMDoc::DocumentManager::addDocument (const std::vector::iterator iter = std::find (mDocuments.begin(), mDocuments.end(), document); if (iter==mDocuments.end()) - throw std::runtime_error ("removing invalid document"); + throw std::runtime_error ("removing invalid document"); mDocuments.erase (iter); delete document; - return mDocuments.empty(); + if (mDocuments.empty()) + emit lastDocumentDeleted(); } void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& parResDir) @@ -80,5 +81,4 @@ void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std:: { removeDocument (document); /// \todo report error - /// \todo handle removeDocument returning true } \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index c30c83c066..1af18a1484 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -43,8 +43,8 @@ namespace CSMDoc ///< \param new_ Do not load the last content file in \a files and instead create in an /// appropriate way. - bool removeDocument (Document *document); - ///< \return last document removed? + void removeDocument (Document *document); + ///< Emits the lastDocumentDeleted signal, if applicable. void setResourceDir (const boost::filesystem::path& parResDir); @@ -66,6 +66,8 @@ namespace CSMDoc void documentAdded (CSMDoc::Document *document); void loadRequest (Document *document, bool _new); + + void lastDocumentDeleted(); }; } From 5f1d2f72f6bf052f142485ba6cb5c1f7733ab40d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 14:17:25 +0200 Subject: [PATCH 04/19] added basic loading GUI --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/doc/documentmanager.cpp | 7 ++-- apps/opencs/model/doc/documentmanager.hpp | 5 ++- apps/opencs/model/doc/loader.cpp | 2 +- apps/opencs/model/doc/loader.hpp | 2 +- apps/opencs/view/doc/loader.cpp | 44 ++++++++++++++++++++++ apps/opencs/view/doc/loader.hpp | 46 +++++++++++++++++++++++ apps/opencs/view/doc/viewmanager.cpp | 7 ++++ apps/opencs/view/doc/viewmanager.hpp | 3 ++ 9 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 apps/opencs/view/doc/loader.cpp create mode 100644 apps/opencs/view/doc/loader.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f1d50467bd..e19242e092 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -44,7 +44,7 @@ opencs_units_noqt (model/tools opencs_units (view/doc viewmanager view operations operation subview startup filedialog newgame - filewidget adjusterwidget + filewidget adjusterwidget loader ) diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index b8372eb4c5..4658667c3b 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -27,8 +27,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con 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))); + connect (this, SIGNAL (loadRequest (CSMDoc::Document *, bool)), + &mLoader, SLOT (loadDocument (CSMDoc::Document *, bool))); } CSMDoc::DocumentManager::~DocumentManager() @@ -75,10 +75,11 @@ void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& par void CSMDoc::DocumentManager::documentLoaded (Document *document) { emit documentAdded (document); + emit loadingStopped (document, true, ""); } void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::string& error) { +// emit loadingStopped (document, false, error); removeDocument (document); - /// \todo report error } \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 1af18a1484..63ee5eb68d 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -65,9 +65,12 @@ namespace CSMDoc void documentAdded (CSMDoc::Document *document); - void loadRequest (Document *document, bool _new); + void loadRequest (CSMDoc::Document *document, bool _new); void lastDocumentDeleted(); + + void loadingStopped (CSMDoc::Document *document, bool completed, + const std::string& error); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 722e903641..53827deb0b 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -46,7 +46,7 @@ void CSMDoc::Loader::load() } } -void CSMDoc::Loader::loadDocument (Document *document, bool new_) +void CSMDoc::Loader::loadDocument (CSMDoc::Document *document, bool new_) { mDocuments.push_back (std::make_pair (document, new_)); } diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index eae0c8001a..af266d52bf 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -31,7 +31,7 @@ namespace CSMDoc public slots: - void loadDocument (Document *document, bool new_); + void loadDocument (CSMDoc::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. diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp new file mode 100644 index 0000000000..f840ab7175 --- /dev/null +++ b/apps/opencs/view/doc/loader.cpp @@ -0,0 +1,44 @@ + +#include "loader.hpp" + +#include "../../model/doc/document.hpp" + +CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) +{ + setWindowTitle (("Loading " + document->getSavePath().filename().string()).c_str()); + show(); +} + + +CSVDoc::Loader::Loader() +{ + +} + +CSVDoc::Loader::~Loader() +{ + for (std::map::iterator iter (mDocuments.begin()); + iter!=mDocuments.end(); ++iter) + delete iter->second; +} + +void CSVDoc::Loader::add (CSMDoc::Document *document, bool new_) +{ + mDocuments.insert (std::make_pair (document, new LoadingDocument (document))); +} + +void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed, + const std::string& error) +{ + if (completed || error.empty()) + { + for (std::map::iterator iter (mDocuments.begin()); + iter!=mDocuments.end(); ++iter) + if (iter->first==document) + { + delete iter->second; + mDocuments.erase (iter); + break; + } + } +} \ No newline at end of file diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp new file mode 100644 index 0000000000..4aa497482d --- /dev/null +++ b/apps/opencs/view/doc/loader.hpp @@ -0,0 +1,46 @@ +#ifndef CSV_DOC_LOADER_H +#define CSV_DOC_LOADER_H + +#include + +#include +#include + +namespace CSMDoc +{ + class Document; +} + +namespace CSVDoc +{ + class LoadingDocument : public QWidget + { + Q_OBJECT + + public: + + LoadingDocument (CSMDoc::Document *document); + }; + + class Loader : public QObject + { + Q_OBJECT + + std::map mDocuments; + + public: + + Loader(); + + virtual ~Loader(); + + public slots: + + void add (CSMDoc::Document *document, bool new_); + + void loadingStopped (CSMDoc::Document *document, bool completed, + const std::string& error); + }; +} + +#endif diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 4a4dbc1244..3ca52c452a 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -86,6 +86,13 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) connect (&CSMSettings::UserSettings::instance(), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)), this, SLOT (slotUpdateEditorSetting (const QString &, const QString &))); + + connect (&mDocumentManager, SIGNAL (loadRequest (CSMDoc::Document *, bool)), + &mLoader, SLOT (add (CSMDoc::Document *, bool))); + + connect ( + &mDocumentManager, SIGNAL (loadingStopped (CSMDoc::Document *, bool, const std::string&)), + &mLoader, SLOT (loadingStopped (CSMDoc::Document *, bool, const std::string&))); } CSVDoc::ViewManager::~ViewManager() diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 01f4951864..cddc1b2359 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -5,6 +5,8 @@ #include +#include "loader.hpp" + namespace CSMDoc { class Document; @@ -29,6 +31,7 @@ namespace CSVDoc CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories; bool mExitOnSaveStateChange; bool mUserWarned; + Loader mLoader; // not implemented ViewManager (const ViewManager&); From 8dc6ad505937ad3f9aa80ddc405db703d439976e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 14:27:44 +0200 Subject: [PATCH 05/19] moved new flag from setupData function to Document constructor --- apps/opencs/model/doc/document.cpp | 19 ++++++++++++------- apps/opencs/model/doc/document.hpp | 8 ++++++-- apps/opencs/model/doc/documentmanager.cpp | 8 ++++---- apps/opencs/model/doc/documentmanager.hpp | 2 +- apps/opencs/model/doc/loader.cpp | 7 +++---- apps/opencs/model/doc/loader.hpp | 4 +--- apps/opencs/view/doc/loader.cpp | 2 +- apps/opencs/view/doc/loader.hpp | 2 +- apps/opencs/view/doc/viewmanager.cpp | 4 ++-- 9 files changed, 31 insertions(+), 25 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 20a355d483..25b48a3c9a 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2220,9 +2220,9 @@ void CSMDoc::Document::createBase() } CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, - const std::vector< boost::filesystem::path >& files, + const std::vector< boost::filesystem::path >& files, bool new_, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir) -: mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir), +: mSavePath (savePath), mContentFiles (files), mNew (new_), mTools (mData), mResDir(resDir), mProjectPath ((configuration.getUserDataPath() / "projects") / (savePath.filename().string() + ".project")), mSaving (*this, mProjectPath) @@ -2260,21 +2260,21 @@ CSMDoc::Document::~Document() { } -void CSMDoc::Document::setupData (bool new_) +void CSMDoc::Document::setupData() { - if (new_ && mContentFiles.size()==1) + if (mNew && mContentFiles.size()==1) createBase(); else { std::vector::const_iterator end = mContentFiles.end(); - if (new_) + if (mNew) --end; - load (mContentFiles.begin(), end, !new_); + load (mContentFiles.begin(), end, !mNew); } - if (new_) + if (mNew) { mData.setDescription (""); mData.setAuthor (""); @@ -2317,6 +2317,11 @@ const std::vector& CSMDoc::Document::getContentFiles() return mContentFiles; } +bool CSMDoc::Document::isNew() const +{ + return mNew; +} + void CSMDoc::Document::save() { if (mSaving.isRunning()) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index c7d87e16a0..e19efd04ec 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -39,6 +39,7 @@ namespace CSMDoc boost::filesystem::path mSavePath; std::vector mContentFiles; + bool mNew; CSMWorld::Data mData; CSMTools::Tools mTools; boost::filesystem::path mProjectPath; @@ -72,12 +73,12 @@ namespace CSMDoc public: Document (const Files::ConfigurationManager& configuration, - const std::vector< boost::filesystem::path >& files, + const std::vector< boost::filesystem::path >& files, bool new_, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir); ~Document(); - void setupData (bool new_); + void setupData(); QUndoStack& getUndoStack(); @@ -89,6 +90,9 @@ namespace CSMDoc ///< \attention The last element in this collection is the file that is being edited, /// but with its original path instead of the save path. + bool isNew() const; + ///< Is this a newly created content file? + void save(); CSMWorld::UniversalId verify(); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 4658667c3b..ae6f1103fc 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -27,8 +27,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SLOT (documentLoaded (Document *))); connect (&mLoader, SIGNAL (documentNotLoaded (Document *, const std::string&)), this, SLOT (documentNotLoaded (Document *, const std::string&))); - connect (this, SIGNAL (loadRequest (CSMDoc::Document *, bool)), - &mLoader, SLOT (loadDocument (CSMDoc::Document *, bool))); + connect (this, SIGNAL (loadRequest (CSMDoc::Document *)), + &mLoader, SLOT (loadDocument (CSMDoc::Document *))); } CSMDoc::DocumentManager::~DocumentManager() @@ -44,11 +44,11 @@ CSMDoc::DocumentManager::~DocumentManager() void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { - Document *document = new Document (mConfiguration, files, savePath, mResDir); + Document *document = new Document (mConfiguration, files, new_, savePath, mResDir); mDocuments.push_back (document); - emit loadRequest (document, new_); + emit loadRequest (document); mLoader.hasThingsToDo().wakeAll(); } diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 63ee5eb68d..4adc9726ce 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -65,7 +65,7 @@ namespace CSMDoc void documentAdded (CSMDoc::Document *document); - void loadRequest (CSMDoc::Document *document, bool _new); + void loadRequest (CSMDoc::Document *document); void lastDocumentDeleted(); diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 53827deb0b..dbaa2b4d5b 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -31,13 +31,12 @@ void CSMDoc::Loader::load() std::vector >::iterator iter = mDocuments.begin(); Document *document = iter->first; - bool new_ = iter->second; mDocuments.erase (iter); try { - document->setupData (new_); + document->setupData(); emit documentLoaded (document); } catch (const std::exception& e) @@ -46,9 +45,9 @@ void CSMDoc::Loader::load() } } -void CSMDoc::Loader::loadDocument (CSMDoc::Document *document, bool new_) +void CSMDoc::Loader::loadDocument (CSMDoc::Document *document) { - mDocuments.push_back (std::make_pair (document, new_)); + mDocuments.push_back (std::make_pair (document, false)); } void CSMDoc::Loader::abortLoading (Document *document) diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index af266d52bf..4e3db1815c 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -31,10 +31,8 @@ namespace CSMDoc public slots: - void loadDocument (CSMDoc::Document *document, bool new_); + void loadDocument (CSMDoc::Document *document); ///< 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 diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index f840ab7175..15296d616b 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -22,7 +22,7 @@ CSVDoc::Loader::~Loader() delete iter->second; } -void CSVDoc::Loader::add (CSMDoc::Document *document, bool new_) +void CSVDoc::Loader::add (CSMDoc::Document *document) { mDocuments.insert (std::make_pair (document, new LoadingDocument (document))); } diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index 4aa497482d..cb154b13e6 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -36,7 +36,7 @@ namespace CSVDoc public slots: - void add (CSMDoc::Document *document, bool new_); + void add (CSMDoc::Document *document); void loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 3ca52c452a..c18cca8091 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -87,8 +87,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) connect (&CSMSettings::UserSettings::instance(), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)), this, SLOT (slotUpdateEditorSetting (const QString &, const QString &))); - connect (&mDocumentManager, SIGNAL (loadRequest (CSMDoc::Document *, bool)), - &mLoader, SLOT (add (CSMDoc::Document *, bool))); + connect (&mDocumentManager, SIGNAL (loadRequest (CSMDoc::Document *)), + &mLoader, SLOT (add (CSMDoc::Document *))); connect ( &mDocumentManager, SIGNAL (loadingStopped (CSMDoc::Document *, bool, const std::string&)), From ab94e7072459fa513b611cc2c19af8893e6cc41b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 1 May 2014 13:04:48 +0200 Subject: [PATCH 06/19] more cleanup of document setup --- apps/opencs/model/doc/document.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 25b48a3c9a..760c675a02 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2245,6 +2245,18 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, } } + if (mNew) + { + mData.setDescription (""); + mData.setAuthor (""); + + if (mContentFiles.size()==1) + createBase(); + } + + addOptionalGmsts(); + addOptionalGlobals(); + connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); @@ -2262,9 +2274,7 @@ CSMDoc::Document::~Document() void CSMDoc::Document::setupData() { - if (mNew && mContentFiles.size()==1) - createBase(); - else + if (!mNew || mContentFiles.size()>1) { std::vector::const_iterator end = mContentFiles.end(); @@ -2274,16 +2284,7 @@ void CSMDoc::Document::setupData() load (mContentFiles.begin(), end, !mNew); } - if (mNew) - { - mData.setDescription (""); - mData.setAuthor (""); - } - getData().loadFile (mProjectPath, false, true); - - addOptionalGmsts(); - addOptionalGlobals(); } QUndoStack& CSMDoc::Document::getUndoStack() From e09218f164f9f2c52a44dfc4146652e426a987d6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 12:07:05 +0200 Subject: [PATCH 07/19] moved load code from Document to Loader class --- apps/opencs/model/doc/document.cpp | 37 ++++----------------------- apps/opencs/model/doc/document.hpp | 8 ++---- apps/opencs/model/doc/loader.cpp | 41 +++++++++++++++++++++++++----- apps/opencs/model/doc/loader.hpp | 9 ++++++- 4 files changed, 50 insertions(+), 45 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 760c675a02..a441f4ae29 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -8,23 +8,6 @@ #include #endif -void CSMDoc::Document::load (const std::vector::const_iterator& begin, - const std::vector::const_iterator& end, bool lastAsModified) -{ - assert (begin!=end); - - std::vector::const_iterator end2 (end); - - if (lastAsModified) - --end2; - - for (std::vector::const_iterator iter (begin); iter!=end2; ++iter) - getData().loadFile (*iter, true, false); - - if (lastAsModified) - getData().loadFile (*end2, false, false); -} - void CSMDoc::Document::addGmsts() { static const char *gmstFloats[] = @@ -2272,21 +2255,6 @@ CSMDoc::Document::~Document() { } -void CSMDoc::Document::setupData() -{ - if (!mNew || mContentFiles.size()>1) - { - std::vector::const_iterator end = mContentFiles.end(); - - if (mNew) - --end; - - load (mContentFiles.begin(), end, !mNew); - } - - getData().loadFile (mProjectPath, false, true); -} - QUndoStack& CSMDoc::Document::getUndoStack() { return mUndoStack; @@ -2313,6 +2281,11 @@ const boost::filesystem::path& CSMDoc::Document::getSavePath() const return mSavePath; } +const boost::filesystem::path& CSMDoc::Document::getProjectPath() const +{ + return mProjectPath; +} + const std::vector& CSMDoc::Document::getContentFiles() const { return mContentFiles; diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index e19efd04ec..11a4057d14 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -54,10 +54,6 @@ namespace CSMDoc Document (const Document&); Document& operator= (const Document&); - void load (const std::vector::const_iterator& begin, - const std::vector::const_iterator& end, bool lastAsModified); - ///< \param lastAsModified Store the last file in Modified instead of merging it into Base. - void createBase(); void addGmsts(); @@ -78,14 +74,14 @@ namespace CSMDoc ~Document(); - void setupData(); - QUndoStack& getUndoStack(); int getState() const; const boost::filesystem::path& getSavePath() const; + const boost::filesystem::path& getProjectPath() const; + const std::vector& getContentFiles() const; ///< \attention The last element in this collection is the file that is being edited, /// but with its original path instead of the save path. diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index dbaa2b4d5b..5277b08d2b 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -5,6 +5,9 @@ #include "document.hpp" +CSMDoc::Loader::Stage::Stage() : mFile (0) {} + + CSMDoc::Loader::Loader() { QTimer *timer = new QTimer (this); @@ -28,31 +31,57 @@ void CSMDoc::Loader::load() return; } - std::vector >::iterator iter = mDocuments.begin(); + std::vector >::iterator iter = mDocuments.begin(); Document *document = iter->first; - mDocuments.erase (iter); + int size = static_cast (document->getContentFiles().size()); + + if (document->isNew()) + --size; + + bool done = false; try { - document->setupData(); - emit documentLoaded (document); + if (iter->second.mFilegetData().loadFile (document->getContentFiles()[iter->second.mFile], + iter->second.mFilesecond.mFile==size) + { + document->getData().loadFile (document->getProjectPath(), false, true); + } + 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, false)); + mDocuments.push_back (std::make_pair (document, Stage())); } void CSMDoc::Loader::abortLoading (Document *document) { - for (std::vector >::iterator iter = mDocuments.begin(); + for (std::vector >::iterator iter = mDocuments.begin(); iter!=mDocuments.end(); ++iter) { if (iter->first==document) diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index 4e3db1815c..dee7d06cb6 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -15,9 +15,16 @@ namespace CSMDoc { Q_OBJECT + struct Stage + { + int mFile; + + Stage(); + }; + QMutex mMutex; QWaitCondition mThingsToDo; - std::vector > mDocuments; + std::vector > mDocuments; public: From e0e2ad8316eaf097a0191d1b3796ac97ab5e76a8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 13:01:29 +0200 Subject: [PATCH 08/19] content file loading progress bar --- apps/opencs/main.cpp | 6 +++ apps/opencs/model/doc/documentmanager.cpp | 2 + apps/opencs/model/doc/documentmanager.hpp | 2 + apps/opencs/model/doc/loader.cpp | 9 ++++- apps/opencs/model/doc/loader.hpp | 2 + apps/opencs/view/doc/loader.cpp | 46 ++++++++++++++++++++++- apps/opencs/view/doc/loader.hpp | 10 +++++ apps/opencs/view/doc/viewmanager.cpp | 4 ++ 8 files changed, 78 insertions(+), 3 deletions(-) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index eded36394a..1febb16786 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -3,9 +3,11 @@ #include #include +#include #include #include +#include #include @@ -15,6 +17,8 @@ #include #endif +Q_DECLARE_METATYPE (std::string) + class Application : public QApplication { private: @@ -42,6 +46,8 @@ int main(int argc, char *argv[]) { Q_INIT_RESOURCE (resources); + qRegisterMetaType ("std::string"); + OgreInit::OgreInit ogreInit; std::auto_ptr shinyFactory; diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index ae6f1103fc..f102dac702 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -29,6 +29,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SLOT (documentNotLoaded (Document *, const std::string&))); connect (this, SIGNAL (loadRequest (CSMDoc::Document *)), &mLoader, SLOT (loadDocument (CSMDoc::Document *))); + connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&)), + this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&))); } CSMDoc::DocumentManager::~DocumentManager() diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 4adc9726ce..be95286599 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -71,6 +71,8 @@ namespace CSMDoc void loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error); + + void nextStage (CSMDoc::Document *document, const std::string& name); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 5277b08d2b..47cac17133 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -46,11 +46,16 @@ void CSMDoc::Loader::load() { if (iter->second.mFilegetData().loadFile (document->getContentFiles()[iter->second.mFile], - iter->second.mFilegetContentFiles()[iter->second.mFile]; + + emit nextStage (document, path.filename().string()); + + document->getData().loadFile (path, iter->second.mFilesecond.mFile==size) { + emit nextStage (document, "Project File"); + document->getData().loadFile (document->getProjectPath(), false, true); } else diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index dee7d06cb6..270aeeb003 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -54,6 +54,8 @@ namespace CSMDoc 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); }; } diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 15296d616b..50c29eedbb 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -1,14 +1,50 @@ #include "loader.hpp" +#include +#include +#include +#include + #include "../../model/doc/document.hpp" CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) { - setWindowTitle (("Loading " + document->getSavePath().filename().string()).c_str()); + setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str()); + + QVBoxLayout *layout = new QVBoxLayout (this); + + mFileProgress = new QProgressBar (this); + + layout->addWidget (mFileProgress); + + int size = static_cast (document->getContentFiles().size())+1; + if (document->isNew()) + --size; + + mFileProgress->setMinimum (0); + mFileProgress->setMaximum (size); + mFileProgress->setTextVisible (true); + mFileProgress->setValue (0); + + mFile = new QLabel (this); + + layout->addWidget (mFile); + + setLayout (layout); + + move (QCursor::pos()); + show(); } +void CSVDoc::LoadingDocument::nextStage (const std::string& name) +{ + mFile->setText (QString::fromUtf8 (("Loading: " + name).c_str())); + + mFileProgress->setValue (mFileProgress->value()+1); +} + CSVDoc::Loader::Loader() { @@ -41,4 +77,12 @@ void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed, break; } } +} + +void CSVDoc::Loader::nextStage (CSMDoc::Document *document, const std::string& name) +{ + std::map::iterator iter = mDocuments.find (document); + + if (iter!=mDocuments.end()) + iter->second->nextStage (name); } \ No newline at end of file diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index cb154b13e6..ad1e3ffb81 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -6,6 +6,9 @@ #include #include +class QLabel; +class QProgressBar; + namespace CSMDoc { class Document; @@ -17,9 +20,14 @@ namespace CSVDoc { Q_OBJECT + QLabel *mFile; + QProgressBar *mFileProgress; + public: LoadingDocument (CSMDoc::Document *document); + + void nextStage (const std::string& name); }; class Loader : public QObject @@ -40,6 +48,8 @@ namespace CSVDoc void loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error); + + void nextStage (CSMDoc::Document *document, const std::string& name); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index c18cca8091..877bc1dead 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -93,6 +93,10 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) connect ( &mDocumentManager, SIGNAL (loadingStopped (CSMDoc::Document *, bool, const std::string&)), &mLoader, SLOT (loadingStopped (CSMDoc::Document *, bool, const std::string&))); + + connect ( + &mDocumentManager, SIGNAL (nextStage (CSMDoc::Document *, const std::string&)), + &mLoader, SLOT (nextStage (CSMDoc::Document *, const std::string&))); } CSVDoc::ViewManager::~ViewManager() From 6692d2dc724d988a6e3224e0946b8cca53b07df4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 15:05:02 +0200 Subject: [PATCH 09/19] split up load function in a start and continue part --- apps/opencs/model/doc/loader.cpp | 18 +- apps/opencs/model/doc/loader.hpp | 1 + apps/opencs/model/world/data.cpp | 289 ++++++++++++++++--------------- apps/opencs/model/world/data.hpp | 20 ++- 4 files changed, 187 insertions(+), 141 deletions(-) diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 47cac17133..85bfececd5 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -5,7 +5,7 @@ #include "document.hpp" -CSMDoc::Loader::Stage::Stage() : mFile (0) {} +CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLeft (false) {} CSMDoc::Loader::Loader() @@ -13,7 +13,7 @@ CSMDoc::Loader::Loader() QTimer *timer = new QTimer (this); connect (timer, SIGNAL (timeout()), this, SLOT (load())); - timer->start (1000); + timer->start(); } QWaitCondition& CSMDoc::Loader::hasThingsToDo() @@ -44,19 +44,29 @@ void CSMDoc::Loader::load() try { + if (iter->second.mRecordsLeft) + { + if (document->getData().continueLoading()) + iter->second.mRecordsLeft = false; + + return; + } + if (iter->second.mFilegetContentFiles()[iter->second.mFile]; emit nextStage (document, path.filename().string()); - document->getData().loadFile (path, iter->second.mFilegetData().startLoading (path, iter->second.mFilesecond.mRecordsLeft = true; } else if (iter->second.mFile==size) { emit nextStage (document, "Project File"); - document->getData().loadFile (document->getProjectPath(), false, true); + document->getData().startLoading (document->getProjectPath(), false, true); + iter->second.mRecordsLeft = true; } else { diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index 270aeeb003..5e86e4e671 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -18,6 +18,7 @@ namespace CSMDoc struct Stage { int mFile; + bool mRecordsLeft; Stage(); }; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index d60dcae117..93b734e271 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -55,7 +55,10 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec 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); mGlobals.addColumn (new RecordStateColumn); @@ -260,6 +263,8 @@ CSMWorld::Data::~Data() { for (std::vector::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter) delete *iter; + + delete mReader; } const CSMWorld::IdCollection& CSMWorld::Data::getGlobals() const @@ -481,148 +486,162 @@ void CSMWorld::Data::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. - ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding ("win1252")); - reader.setEncoder (&encoder); + mReader = new ESM::ESMReader; + mReader->setEncoder (&mEncoder); + 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(); - mDescription = reader.getDesc(); + return mReader->getRecordCount(); +} - // Note: We do not need to send update signals here, because at this point the model is not connected - // to any view. - while (reader.hasMoreRecs()) +bool CSMWorld::Data::continueLoading() +{ + if (!mReader) + throw std::logic_error ("can't continue loading, because no load has been started"); + + if (!mReader->hasMoreRecs()) { - ESM::NAME n = reader.getRecName(); - reader.getRecHeader(); - - switch (n.val) - { - 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 (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(); - } + delete mReader; + mReader = 0; + mDialogue = 0; + return true; } + + 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 (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 diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 152c3ac419..234069e3a7 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -33,12 +33,19 @@ class QAbstractItemModel; +namespace ESM +{ + class ESMReader; + struct Dialogue; +} + namespace CSMWorld { class Data : public QObject { Q_OBJECT + ToUTF8::Utf8Encoder mEncoder; IdCollection mGlobals; IdCollection mGmsts; IdCollection mSkills; @@ -62,6 +69,10 @@ namespace CSMWorld std::map mModelIndex; std::string mAuthor; std::string mDescription; + ESM::ESMReader *mReader; + const ESM::Dialogue *mDialogue; // last loaded dialogue + bool mBase; + bool mProject; // not implemented Data (const Data&); @@ -167,10 +178,15 @@ namespace CSMWorld void merge(); ///< Merge modified into base. - void loadFile (const boost::filesystem::path& path, bool base, bool project); - ///< Merging content of a file into base or modified. + int startLoading (const boost::filesystem::path& path, bool base, bool project); + ///< Begin merging content of a file into base or modified. /// /// \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; From 6bc58692225073f47117577c0fd8a5f8f8ff1abb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 15:33:35 +0200 Subject: [PATCH 10/19] record loading progress bar --- apps/opencs/model/doc/documentmanager.cpp | 6 ++-- apps/opencs/model/doc/documentmanager.hpp | 4 ++- apps/opencs/model/doc/loader.cpp | 24 ++++++++----- apps/opencs/model/doc/loader.hpp | 7 +++- apps/opencs/view/doc/loader.cpp | 41 +++++++++++++++++++---- apps/opencs/view/doc/loader.hpp | 9 +++-- apps/opencs/view/doc/viewmanager.cpp | 8 +++-- 7 files changed, 77 insertions(+), 22 deletions(-) diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index f102dac702..f9e6bd96ac 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -29,8 +29,10 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SLOT (documentNotLoaded (Document *, const std::string&))); connect (this, SIGNAL (loadRequest (CSMDoc::Document *)), &mLoader, SLOT (loadDocument (CSMDoc::Document *))); - connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&)), - this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&))); + connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)), + this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int))); + connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *)), + this, SIGNAL (nextRecord (CSMDoc::Document *))); } CSMDoc::DocumentManager::~DocumentManager() diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index be95286599..47118a0fba 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -72,7 +72,9 @@ namespace CSMDoc void loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error); - void nextStage (CSMDoc::Document *document, const std::string& name); + void nextStage (CSMDoc::Document *document, const std::string& name, int steps); + + void nextRecord (CSMDoc::Document *document); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 85bfececd5..e2cf6684f2 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -42,12 +42,20 @@ void CSMDoc::Loader::load() bool done = false; + const int batchingSize = 100; + try { if (iter->second.mRecordsLeft) { - if (document->getData().continueLoading()) - iter->second.mRecordsLeft = false; + for (int i=0; igetData().continueLoading()) + { + iter->second.mRecordsLeft = false; + break; + } + + emit nextRecord (document); return; } @@ -56,17 +64,17 @@ void CSMDoc::Loader::load() { boost::filesystem::path path = document->getContentFiles()[iter->second.mFile]; - emit nextStage (document, path.filename().string()); - - document->getData().startLoading (path, iter->second.mFilegetData().startLoading (path, iter->second.mFilesecond.mRecordsLeft = true; + + emit nextStage (document, path.filename().string(), steps/batchingSize); } else if (iter->second.mFile==size) { - emit nextStage (document, "Project File"); - - document->getData().startLoading (document->getProjectPath(), false, true); + int steps = document->getData().startLoading (document->getProjectPath(), false, true); iter->second.mRecordsLeft = true; + + emit nextStage (document, "Project File", steps/batchingSize); } else { diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index 5e86e4e671..f6cfd2a0b1 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -56,7 +56,12 @@ namespace CSMDoc ///< 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); + 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. }; } diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 50c29eedbb..418dc56381 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -14,6 +14,11 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) QVBoxLayout *layout = new QVBoxLayout (this); + // file progress + mFile = new QLabel (this); + + layout->addWidget (mFile); + mFileProgress = new QProgressBar (this); layout->addWidget (mFileProgress); @@ -27,9 +32,16 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) mFileProgress->setTextVisible (true); mFileProgress->setValue (0); - mFile = new QLabel (this); + // record progress + layout->addWidget (new QLabel ("Records", this)); - layout->addWidget (mFile); + mRecordProgress = new QProgressBar (this); + + layout->addWidget (mRecordProgress); + + mRecordProgress->setMinimum (0); + mRecordProgress->setTextVisible (true); + mRecordProgress->setValue (0); setLayout (layout); @@ -38,19 +50,28 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) show(); } -void CSVDoc::LoadingDocument::nextStage (const std::string& name) +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); } -CSVDoc::Loader::Loader() +void CSVDoc::LoadingDocument::nextRecord() { + int value = mRecordProgress->value()+1; + if (value<=mRecordProgress->maximum()) + mRecordProgress->setValue (value); } + +CSVDoc::Loader::Loader() {} + CSVDoc::Loader::~Loader() { for (std::map::iterator iter (mDocuments.begin()); @@ -79,10 +100,18 @@ void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed, } } -void CSVDoc::Loader::nextStage (CSMDoc::Document *document, const std::string& name) +void CSVDoc::Loader::nextStage (CSMDoc::Document *document, const std::string& name, int steps) { std::map::iterator iter = mDocuments.find (document); if (iter!=mDocuments.end()) - iter->second->nextStage (name); + iter->second->nextStage (name, steps); +} + +void CSVDoc::Loader::nextRecord (CSMDoc::Document *document) +{ + std::map::iterator iter = mDocuments.find (document); + + if (iter!=mDocuments.end()) + iter->second->nextRecord(); } \ No newline at end of file diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index ad1e3ffb81..0c85223c66 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -22,12 +22,15 @@ namespace CSVDoc QLabel *mFile; QProgressBar *mFileProgress; + QProgressBar *mRecordProgress; public: LoadingDocument (CSMDoc::Document *document); - void nextStage (const std::string& name); + void nextStage (const std::string& name, int steps); + + void nextRecord(); }; class Loader : public QObject @@ -49,7 +52,9 @@ namespace CSVDoc void loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error); - void nextStage (CSMDoc::Document *document, const std::string& name); + void nextStage (CSMDoc::Document *document, const std::string& name, int steps); + + void nextRecord (CSMDoc::Document *document); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index c7d9ed4705..1c5f51129b 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -93,8 +93,12 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) &mLoader, SLOT (loadingStopped (CSMDoc::Document *, bool, const std::string&))); connect ( - &mDocumentManager, SIGNAL (nextStage (CSMDoc::Document *, const std::string&)), - &mLoader, SLOT (nextStage (CSMDoc::Document *, const std::string&))); + &mDocumentManager, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)), + &mLoader, SLOT (nextStage (CSMDoc::Document *, const std::string&, int))); + + connect ( + &mDocumentManager, SIGNAL (nextRecord (CSMDoc::Document *)), + &mLoader, SLOT (nextRecord (CSMDoc::Document *))); } CSVDoc::ViewManager::~ViewManager() From 3fdd72f2040d5a1c8515bb8ed1033c5be4f0eeb4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 16:44:50 +0200 Subject: [PATCH 11/19] added cancel button to loading window --- apps/opencs/model/doc/documentmanager.cpp | 2 ++ apps/opencs/model/doc/documentmanager.hpp | 2 ++ apps/opencs/model/doc/loader.cpp | 4 ++-- apps/opencs/model/doc/loader.hpp | 2 +- apps/opencs/view/doc/loader.cpp | 20 +++++++++++++++++++- apps/opencs/view/doc/loader.hpp | 14 ++++++++++++++ apps/opencs/view/doc/viewmanager.cpp | 4 ++++ 7 files changed, 44 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index f9e6bd96ac..d44da15c5c 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -33,6 +33,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int))); connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *)), this, SIGNAL (nextRecord (CSMDoc::Document *))); + connect (this, SIGNAL (cancelLoading (CSMDoc::Document *)), + &mLoader, SLOT (abortLoading (CSMDoc::Document *))); } CSMDoc::DocumentManager::~DocumentManager() diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 47118a0fba..d834d85d47 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -75,6 +75,8 @@ namespace CSMDoc void nextStage (CSMDoc::Document *document, const std::string& name, int steps); void nextRecord (CSMDoc::Document *document); + + void cancelLoading (CSMDoc::Document *document); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index e2cf6684f2..2ef808dd60 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -102,7 +102,7 @@ void CSMDoc::Loader::loadDocument (CSMDoc::Document *document) mDocuments.push_back (std::make_pair (document, Stage())); } -void CSMDoc::Loader::abortLoading (Document *document) +void CSMDoc::Loader::abortLoading (CSMDoc::Document *document) { for (std::vector >::iterator iter = mDocuments.begin(); iter!=mDocuments.end(); ++iter) @@ -114,4 +114,4 @@ void CSMDoc::Loader::abortLoading (Document *document) break; } } -} \ No newline at end of file +} diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index f6cfd2a0b1..a6bcb6b87f 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -42,7 +42,7 @@ namespace CSMDoc void loadDocument (CSMDoc::Document *document); ///< The ownership of \a document is not transferred. - void abortLoading (Document *document); + 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. diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 418dc56381..a9206ef2b8 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -5,10 +5,12 @@ #include #include #include +#include #include "../../model/doc/document.hpp" CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) +: mDocument (document) { setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str()); @@ -43,11 +45,18 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) mRecordProgress->setTextVisible (true); mRecordProgress->setValue (0); + QDialogButtonBox *buttonBox = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, + this); + + layout->addWidget (buttonBox); + setLayout (layout); move (QCursor::pos()); show(); + + connect (buttonBox, SIGNAL (rejected()), this, SLOT (cancel())); } void CSVDoc::LoadingDocument::nextStage (const std::string& name, int steps) @@ -69,6 +78,11 @@ void CSVDoc::LoadingDocument::nextRecord() mRecordProgress->setValue (value); } +void CSVDoc::LoadingDocument::cancel() +{ + emit cancel (mDocument); +} + CSVDoc::Loader::Loader() {} @@ -81,7 +95,11 @@ CSVDoc::Loader::~Loader() void CSVDoc::Loader::add (CSMDoc::Document *document) { - mDocuments.insert (std::make_pair (document, new LoadingDocument (document))); + LoadingDocument *loading = new LoadingDocument (document); + mDocuments.insert (std::make_pair (document, loading)); + + connect (loading, SIGNAL (cancel (CSMDoc::Document *)), + this, SIGNAL (cancel (CSMDoc::Document *))); } void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed, diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index 0c85223c66..a251e75d95 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -5,6 +5,7 @@ #include #include +#include class QLabel; class QProgressBar; @@ -20,6 +21,7 @@ namespace CSVDoc { Q_OBJECT + CSMDoc::Document *mDocument; QLabel *mFile; QProgressBar *mFileProgress; QProgressBar *mRecordProgress; @@ -31,6 +33,14 @@ namespace CSVDoc void nextStage (const std::string& name, int steps); void nextRecord(); + + private slots: + + void cancel(); + + signals: + + void cancel (CSMDoc::Document *document); }; class Loader : public QObject @@ -45,6 +55,10 @@ namespace CSVDoc virtual ~Loader(); + signals: + + void cancel (CSMDoc::Document *document); + public slots: void add (CSMDoc::Document *document); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 1c5f51129b..b8971a296a 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -99,6 +99,10 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) connect ( &mDocumentManager, SIGNAL (nextRecord (CSMDoc::Document *)), &mLoader, SLOT (nextRecord (CSMDoc::Document *))); + + connect ( + &mLoader, SIGNAL (cancel (CSMDoc::Document *)), + &mDocumentManager, SIGNAL (cancelLoading (CSMDoc::Document *))); } CSVDoc::ViewManager::~ViewManager() From e9c2f24faaf2838507b52462fa8204020145b946 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 17:14:17 +0200 Subject: [PATCH 12/19] intercept close button clicks in loading window --- apps/opencs/view/doc/loader.cpp | 7 +++++++ apps/opencs/view/doc/loader.hpp | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index a9206ef2b8..3b58904793 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -6,9 +6,16 @@ #include #include #include +#include #include "../../model/doc/document.hpp" +void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event) +{ + event->ignore(); + emit cancel (mDocument); +} + CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) : mDocument (document) { diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index a251e75d95..d1c740011d 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -26,6 +26,10 @@ namespace CSVDoc QProgressBar *mFileProgress; QProgressBar *mRecordProgress; + private: + + void closeEvent (QCloseEvent *event); + public: LoadingDocument (CSMDoc::Document *document); From 492620c8cf0f4436d31f46061bd6f37c82391b91 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 6 May 2014 09:39:39 +0200 Subject: [PATCH 13/19] handle exceptions thrown during loading and report them to the user --- apps/opencs/model/doc/documentmanager.cpp | 8 +-- apps/opencs/model/doc/documentmanager.hpp | 8 +-- apps/opencs/view/doc/loader.cpp | 63 +++++++++++++++++------ apps/opencs/view/doc/loader.hpp | 12 +++++ apps/opencs/view/doc/viewmanager.cpp | 4 ++ 5 files changed, 72 insertions(+), 23 deletions(-) diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index d44da15c5c..fe6aaef279 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -59,7 +59,7 @@ void CSMDoc::DocumentManager::addDocument (const std::vector::iterator iter = std::find (mDocuments.begin(), mDocuments.end(), document); @@ -86,6 +86,8 @@ void CSMDoc::DocumentManager::documentLoaded (Document *document) void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::string& error) { -// emit loadingStopped (document, false, error); - removeDocument (document); + emit loadingStopped (document, false, error); + + if (error.empty()) // do not remove the document yet, if we have an error + removeDocument (document); } \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index d834d85d47..de4a5e94be 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -43,9 +43,6 @@ namespace CSMDoc ///< \param new_ Do not load the last content file in \a files and instead create in an /// appropriate way. - void removeDocument (Document *document); - ///< Emits the lastDocumentDeleted signal, if applicable. - void setResourceDir (const boost::filesystem::path& parResDir); private: @@ -61,6 +58,11 @@ namespace CSMDoc ///< 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. + public slots: + + void removeDocument (CSMDoc::Document *document); + ///< Emits the lastDocumentDeleted signal, if applicable. + signals: void documentAdded (CSMDoc::Document *document); diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 3b58904793..1b2ca8ad5d 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -13,11 +13,11 @@ void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event) { event->ignore(); - emit cancel (mDocument); + cancel(); } CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) -: mDocument (document) +: mDocument (document), mAborted (false) { setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str()); @@ -52,10 +52,16 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) mRecordProgress->setTextVisible (true); mRecordProgress->setValue (0); - QDialogButtonBox *buttonBox = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, - this); + // error message + mError = new QLabel (this); + mError->setWordWrap (true); - layout->addWidget (buttonBox); + layout->addWidget (mError); + + // buttons + mButtons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this); + + layout->addWidget (mButtons); setLayout (layout); @@ -63,7 +69,7 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) show(); - connect (buttonBox, SIGNAL (rejected()), this, SLOT (cancel())); + connect (mButtons, SIGNAL (rejected()), this, SLOT (cancel())); } void CSVDoc::LoadingDocument::nextStage (const std::string& name, int steps) @@ -73,10 +79,9 @@ void CSVDoc::LoadingDocument::nextStage (const std::string& name, int steps) mFileProgress->setValue (mFileProgress->value()+1); mRecordProgress->setValue (0); - mRecordProgress->setMaximum (steps); + mRecordProgress->setMaximum (steps>0 ? steps : 1); } - void CSVDoc::LoadingDocument::nextRecord() { int value = mRecordProgress->value()+1; @@ -85,9 +90,22 @@ void CSVDoc::LoadingDocument::nextRecord() 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::cancel() { - emit cancel (mDocument); + if (!mAborted) + emit cancel (mDocument); + else + { + emit close (mDocument); + deleteLater(); + } } @@ -107,21 +125,32 @@ void CSVDoc::Loader::add (CSMDoc::Document *document) 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::iterator iter = mDocuments.begin(); + + for (; iter!=mDocuments.end(); ++iter) + if (iter->first==document) + break; + + if (iter==mDocuments.end()) + return; + if (completed || error.empty()) { - for (std::map::iterator iter (mDocuments.begin()); - iter!=mDocuments.end(); ++iter) - if (iter->first==document) - { - delete iter->second; - mDocuments.erase (iter); - break; - } + 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); } } diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index d1c740011d..ece071755d 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -9,6 +9,7 @@ class QLabel; class QProgressBar; +class QDialogButtonBox; namespace CSMDoc { @@ -25,6 +26,9 @@ namespace CSVDoc QLabel *mFile; QProgressBar *mFileProgress; QProgressBar *mRecordProgress; + bool mAborted; + QDialogButtonBox *mButtons; + QLabel *mError; private: @@ -38,6 +42,8 @@ namespace CSVDoc void nextRecord(); + void abort (const std::string& error); + private slots: void cancel(); @@ -45,6 +51,10 @@ namespace CSVDoc signals: void cancel (CSMDoc::Document *document); + ///< Stop loading process. + + void close (CSMDoc::Document *document); + ///< Close stopped loading process. }; class Loader : public QObject @@ -63,6 +73,8 @@ namespace CSVDoc void cancel (CSMDoc::Document *document); + void close (CSMDoc::Document *document); + public slots: void add (CSMDoc::Document *document); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index b8971a296a..816eff7917 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -103,6 +103,10 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) connect ( &mLoader, SIGNAL (cancel (CSMDoc::Document *)), &mDocumentManager, SIGNAL (cancelLoading (CSMDoc::Document *))); + + connect ( + &mLoader, SIGNAL (close (CSMDoc::Document *)), + &mDocumentManager, SLOT (removeDocument (CSMDoc::Document *))); } CSVDoc::ViewManager::~ViewManager() From a30d816982f7f8e700661c888c1879bad1adb618 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 6 May 2014 11:44:20 +0200 Subject: [PATCH 14/19] fixed a mixup in CSMTools::Tools constructor/destructor --- apps/opencs/model/tools/tools.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index d3d8f5fadd..8104cc3e66 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -87,13 +87,14 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier() CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0) { - for (std::map::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) - delete iter->second; } CSMTools::Tools::~Tools() { delete mVerifier; + + for (std::map::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) + delete iter->second; } CSMWorld::UniversalId CSMTools::Tools::runVerifier() From aadaf7827ddfe0be49a9e4ca2afe5646b2c1c723 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 12:04:36 +0200 Subject: [PATCH 15/19] added load error log --- apps/opencs/model/doc/loader.cpp | 12 +++++++++++- apps/opencs/model/doc/state.hpp | 21 +++++++++++---------- apps/opencs/model/tools/tools.cpp | 6 +++++- apps/opencs/model/world/data.cpp | 2 +- apps/opencs/model/world/data.hpp | 4 +++- apps/opencs/model/world/universalid.cpp | 1 + apps/opencs/model/world/universalid.hpp | 5 +++-- apps/opencs/view/doc/view.cpp | 16 ++++++++++++++-- apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/tools/subviews.cpp | 2 ++ 10 files changed, 53 insertions(+), 18 deletions(-) diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 2ef808dd60..e2427e62d3 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -3,7 +3,10 @@ #include +#include "../tools/reportmodel.hpp" + #include "document.hpp" +#include "state.hpp" CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLeft (false) {} @@ -48,13 +51,20 @@ void CSMDoc::Loader::load() { if (iter->second.mRecordsLeft) { + CSMDoc::Stage::Messages messages; for (int i=0; igetData().continueLoading()) + 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 nextRecord (document); return; diff --git a/apps/opencs/model/doc/state.hpp b/apps/opencs/model/doc/state.hpp index 04e6fae899..6e1a1c4f41 100644 --- a/apps/opencs/model/doc/state.hpp +++ b/apps/opencs/model/doc/state.hpp @@ -3,17 +3,18 @@ namespace CSMDoc { - enum State - { - State_Modified = 1, - State_Locked = 2, - State_Operation = 4, + enum State + { + State_Modified = 1, + State_Locked = 2, + State_Operation = 4, - State_Saving = 8, - State_Verifying = 16, - State_Compiling = 32, // not implemented yet - State_Searching = 64 // not implemented yet - }; + State_Saving = 8, + State_Verifying = 16, + State_Compiling = 32, // not implemented yet + State_Searching = 64, // not implemented yet + State_Loading = 128 // pseudo-state; can not be encountered in a loaded document + }; } #endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index a11297b45c..2f93db48ea 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -88,6 +88,9 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier() CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0) { + // 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() @@ -134,7 +137,8 @@ int CSMTools::Tools::getRunningOperations() const CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& id) { - if (id.getType()!=CSMWorld::UniversalId::Type_VerificationResults) + if (id.getType()!=CSMWorld::UniversalId::Type_VerificationResults && + id.getType()!=CSMWorld::UniversalId::Type_LoadErrorLog) throw std::logic_error ("invalid request for report model: " + id.toString()); return mReports.at (id.getIndex()); diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 885e230336..2de58675fa 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -505,7 +505,7 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base return mReader->getRecordCount(); } -bool CSMWorld::Data::continueLoading() +bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) { if (!mReader) throw std::logic_error ("can't continue loading, because no load has been started"); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 234069e3a7..4f7c624e68 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -24,6 +24,8 @@ #include "../filter/filter.hpp" +#include "../doc/stage.hpp" + #include "idcollection.hpp" #include "universalid.hpp" #include "cell.hpp" @@ -185,7 +187,7 @@ namespace CSMWorld /// ///< \return estimated number of records - bool continueLoading(); + bool continueLoading (CSMDoc::Stage::Messages& messages); ///< \return Finished? bool hasId (const std::string& id) const; diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 94b042ec5c..7471e5cec1 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -101,6 +101,7 @@ namespace static const TypeData sIndexArg[] = { { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 }, + { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; } diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 24fb543996..22779b2638 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -97,10 +97,11 @@ namespace CSMWorld Type_JournalInfos, Type_JournalInfo, Type_Scene, - Type_Preview + Type_Preview, + Type_LoadErrorLog }; - enum { NumberOfTypes = Type_Scene+1 }; + enum { NumberOfTypes = Type_LoadErrorLog+1 }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 95ab6ca279..e71b8435ab 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -10,9 +10,12 @@ #include #include "../../model/doc/document.hpp" -#include "../world/subviews.hpp" -#include "../tools/subviews.hpp" #include "../../model/settings/usersettings.hpp" + +#include "../world/subviews.hpp" + +#include "../tools/subviews.hpp" + #include "viewmanager.hpp" #include "operations.hpp" #include "subview.hpp" @@ -47,6 +50,10 @@ void CSVDoc::View::setupFileMenu() connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); file->addAction (mVerify); + QAction *loadErrors = new QAction (tr ("Load Error Log"), this); + connect (loadErrors, SIGNAL (triggered()), this, SLOT (loadErrorLog())); + file->addAction (loadErrors); + QAction *close = new QAction (tr ("&Close"), this); connect (close, SIGNAL (triggered()), this, SLOT (close())); file->addAction(close); @@ -502,3 +509,8 @@ void CSVDoc::View::toggleShowStatusBar (bool show) subView->setStatusBar (show); } } + +void CSVDoc::View::loadErrorLog() +{ + addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_LoadErrorLog, 0)); +} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 5e6c9abc4d..686c001dc1 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -179,6 +179,8 @@ namespace CSVDoc void addJournalInfosSubView(); void toggleShowStatusBar (bool show); + + void loadErrorLog(); }; } diff --git a/apps/opencs/view/tools/subviews.cpp b/apps/opencs/view/tools/subviews.cpp index 781cf602e3..8b04aca504 100644 --- a/apps/opencs/view/tools/subviews.cpp +++ b/apps/opencs/view/tools/subviews.cpp @@ -9,4 +9,6 @@ void CSVTools::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { manager.add (CSMWorld::UniversalId::Type_VerificationResults, new CSVDoc::SubViewFactory); + manager.add (CSMWorld::UniversalId::Type_LoadErrorLog, + new CSVDoc::SubViewFactory); } \ No newline at end of file From 95d24492de4f630037202881fa655cb44d4c971c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 13:18:40 +0200 Subject: [PATCH 16/19] display load error messages in loading window --- apps/opencs/model/doc/documentmanager.cpp | 2 ++ apps/opencs/model/doc/documentmanager.hpp | 2 ++ apps/opencs/model/doc/loader.cpp | 3 +++ apps/opencs/model/doc/loader.hpp | 3 +++ apps/opencs/view/doc/loader.cpp | 19 +++++++++++++++++++ apps/opencs/view/doc/loader.hpp | 6 ++++++ apps/opencs/view/doc/viewmanager.cpp | 4 ++++ 7 files changed, 39 insertions(+) diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index fe6aaef279..d4f8eb110c 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -35,6 +35,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SIGNAL (nextRecord (CSMDoc::Document *))); connect (this, SIGNAL (cancelLoading (CSMDoc::Document *)), &mLoader, SLOT (abortLoading (CSMDoc::Document *))); + connect (&mLoader, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)), + this, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&))); } CSMDoc::DocumentManager::~DocumentManager() diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index de4a5e94be..7b3a811fad 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -79,6 +79,8 @@ namespace CSMDoc void nextRecord (CSMDoc::Document *document); void cancelLoading (CSMDoc::Document *document); + + void loadMessage (CSMDoc::Document *document, const std::string& message); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index e2427e62d3..c106c06e82 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -63,7 +63,10 @@ void CSMDoc::Loader::load() 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); diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index a6bcb6b87f..c276e14ff4 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -62,6 +62,9 @@ namespace CSMDoc ///< \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 }; } diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 1b2ca8ad5d..0a99d434a1 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "../../model/doc/document.hpp" @@ -58,6 +59,11 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) layout->addWidget (mError); + // other messages + mMessages = new QListWidget (this); + + layout->addWidget (mMessages); + // buttons mButtons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this); @@ -97,6 +103,11 @@ void CSVDoc::LoadingDocument::abort (const std::string& error) mButtons->setStandardButtons (QDialogButtonBox::Close); } +void CSVDoc::LoadingDocument::addMessage (const std::string& message) +{ + new QListWidgetItem (QString::fromUtf8 (message.c_str()), mMessages); +} + void CSVDoc::LoadingDocument::cancel() { if (!mAborted) @@ -168,4 +179,12 @@ void CSVDoc::Loader::nextRecord (CSMDoc::Document *document) if (iter!=mDocuments.end()) iter->second->nextRecord(); +} + +void CSVDoc::Loader::loadMessage (CSMDoc::Document *document, const std::string& message) +{ + std::map::iterator iter = mDocuments.find (document); + + if (iter!=mDocuments.end()) + iter->second->addMessage (message); } \ No newline at end of file diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index ece071755d..ab2cec548e 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -10,6 +10,7 @@ class QLabel; class QProgressBar; class QDialogButtonBox; +class QListWidget; namespace CSMDoc { @@ -29,6 +30,7 @@ namespace CSVDoc bool mAborted; QDialogButtonBox *mButtons; QLabel *mError; + QListWidget *mMessages; private: @@ -44,6 +46,8 @@ namespace CSVDoc void abort (const std::string& error); + void addMessage (const std::string& message); + private slots: void cancel(); @@ -85,6 +89,8 @@ namespace CSVDoc 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); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 816eff7917..02f6a54679 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -100,6 +100,10 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) &mDocumentManager, SIGNAL (nextRecord (CSMDoc::Document *)), &mLoader, SLOT (nextRecord (CSMDoc::Document *))); + connect ( + &mDocumentManager, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)), + &mLoader, SLOT (loadMessage (CSMDoc::Document *, const std::string&))); + connect ( &mLoader, SIGNAL (cancel (CSMDoc::Document *)), &mDocumentManager, SIGNAL (cancelLoading (CSMDoc::Document *))); From 79d59153c14303a14931a648722cc818731d7c40 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 13:29:28 +0200 Subject: [PATCH 17/19] improved layout of loading window --- apps/opencs/view/doc/loader.cpp | 31 +++++++++++++++++-------------- apps/opencs/view/doc/loader.hpp | 2 ++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 0a99d434a1..7e4754ddf8 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -18,20 +18,22 @@ void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event) } CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) -: mDocument (document), mAborted (false) +: mDocument (document), mAborted (false), mMessages (0) { setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str()); - QVBoxLayout *layout = new QVBoxLayout (this); + setMinimumWidth (400); + + mLayout = new QVBoxLayout (this); // file progress mFile = new QLabel (this); - layout->addWidget (mFile); + mLayout->addWidget (mFile); mFileProgress = new QProgressBar (this); - layout->addWidget (mFileProgress); + mLayout->addWidget (mFileProgress); int size = static_cast (document->getContentFiles().size())+1; if (document->isNew()) @@ -43,11 +45,11 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) mFileProgress->setValue (0); // record progress - layout->addWidget (new QLabel ("Records", this)); + mLayout->addWidget (new QLabel ("Records", this)); mRecordProgress = new QProgressBar (this); - layout->addWidget (mRecordProgress); + mLayout->addWidget (mRecordProgress); mRecordProgress->setMinimum (0); mRecordProgress->setTextVisible (true); @@ -57,19 +59,14 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) mError = new QLabel (this); mError->setWordWrap (true); - layout->addWidget (mError); - - // other messages - mMessages = new QListWidget (this); - - layout->addWidget (mMessages); + mLayout->addWidget (mError); // buttons mButtons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this); - layout->addWidget (mButtons); + mLayout->addWidget (mButtons); - setLayout (layout); + setLayout (mLayout); move (QCursor::pos()); @@ -105,6 +102,12 @@ void CSVDoc::LoadingDocument::abort (const std::string& error) 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); } diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index ab2cec548e..69a8b48ba3 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -11,6 +11,7 @@ class QLabel; class QProgressBar; class QDialogButtonBox; class QListWidget; +class QVBoxLayout; namespace CSMDoc { @@ -31,6 +32,7 @@ namespace CSVDoc QDialogButtonBox *mButtons; QLabel *mError; QListWidget *mMessages; + QVBoxLayout *mLayout; private: From 96ca9500ca1870ee2d6a4ebea8ea19c6dea013eb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 13:47:22 +0200 Subject: [PATCH 18/19] generate error messages when encounting non-critical problems during load --- apps/opencs/model/world/data.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 2de58675fa..3e9fe11eb0 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -592,7 +592,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) } else { - /// \todo report deletion of non-existing record + messages.push_back (std::make_pair (UniversalId::Type_None, + "Trying to delete dialogue record " + id + " which does not exist")); } } else @@ -608,7 +609,9 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) { if (!mDialogue) { - /// \todo INFO record without matching DIAL record -> report to user + messages.push_back (std::make_pair (UniversalId::Type_None, + "Found info record not following a dialogue record")); + mReader->skipRecord(); break; } @@ -636,8 +639,9 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) default: - /// \todo throw an exception instead, once all records are implemented - /// or maybe report error and continue? + messages.push_back (std::make_pair (UniversalId::Type_None, + "Unsupported record type: " + n.toString())); + mReader->skipRecord(); } From 6fdbd4d3f9e54c0c545a89ddbd62f484c45d0f95 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 13:49:19 +0200 Subject: [PATCH 19/19] minor adjustment to UniversalId --- apps/opencs/model/world/universalid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 7471e5cec1..140a410c06 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -18,7 +18,7 @@ namespace static const TypeData sNoArg[] = { - { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty", 0 }, + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "-", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", 0 },