From 5779f799ab064d72cf9641aaccdd8107d50c098b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 27 Sep 2013 11:36:06 +0200 Subject: [PATCH] create project file when saving content file --- apps/opencs/editor.cpp | 3 +- apps/opencs/editor.hpp | 2 +- apps/opencs/model/doc/document.cpp | 5 +- apps/opencs/model/doc/document.hpp | 5 +- apps/opencs/model/doc/documentmanager.cpp | 15 +++++- apps/opencs/model/doc/documentmanager.hpp | 4 +- apps/opencs/model/doc/saving.cpp | 16 +++++-- apps/opencs/model/doc/saving.hpp | 4 +- apps/opencs/model/doc/savingstages.cpp | 58 ++++++++++++++--------- apps/opencs/model/doc/savingstages.hpp | 8 +++- apps/opencs/model/doc/savingstate.cpp | 19 ++++++-- apps/opencs/model/doc/savingstate.hpp | 10 +++- components/esm/esmwriter.cpp | 5 ++ components/esm/esmwriter.hpp | 2 + components/esm/loadtes3.cpp | 1 + 15 files changed, 113 insertions(+), 44 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 800f3984e9..ead4d2a982 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -10,7 +10,8 @@ #include "model/world/data.hpp" -CS::Editor::Editor() : mViewManager (mDocumentManager) +CS::Editor::Editor() +: mDocumentManager (mCfgMgr.getUserPath() / "projects"), mViewManager (mDocumentManager) { mIpcServerName = "org.openmw.OpenCS"; diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index abf9496e4b..16f6b9516c 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -26,6 +26,7 @@ namespace CS { Q_OBJECT + Files::ConfigurationManager mCfgMgr; CSMSettings::UserSettings mUserSettings; CSMDoc::DocumentManager mDocumentManager; CSVDoc::ViewManager mViewManager; @@ -34,7 +35,6 @@ namespace CS CSVSettings::UserSettingsDialog mSettings; CSVDoc::FileDialog mFileDialog; - Files::ConfigurationManager mCfgMgr; boost::filesystem::path mLocal; void setupDataFiles(); diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index f496d32ec3..f9aa7dfc0f 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2140,8 +2140,9 @@ void CSMDoc::Document::createBase() } CSMDoc::Document::Document (const std::vector& files, - const boost::filesystem::path& savePath, bool new_) -: mSavePath (savePath), mContentFiles (files), mTools (mData), mSaving (*this) + const boost::filesystem::path& savePath, bool new_, + const boost::filesystem::path& projectPath) +: mSavePath (savePath), mContentFiles (files), mTools (mData), mSaving (*this, projectPath) { if (files.empty()) throw std::runtime_error ("Empty content file sequence"); diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index b1c6a02731..979b47734a 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -65,7 +65,10 @@ namespace CSMDoc public: Document (const std::vector& files, - const boost::filesystem::path& savePath, bool new_); + const boost::filesystem::path& savePath, bool new_, + const boost::filesystem::path& projectPath); + ///< \param projectPath Location of file that can be used to store additional data for + /// this project. ~Document(); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index b079109eae..1978c0e536 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -4,9 +4,16 @@ #include #include +#include + #include "document.hpp" -CSMDoc::DocumentManager::DocumentManager() {} +CSMDoc::DocumentManager::DocumentManager (const boost::filesystem::path& projectPath) +: mProjectPath (projectPath) +{ + if (!boost::filesystem::is_directory (mProjectPath)) + boost::filesystem::create_directories (mProjectPath); +} CSMDoc::DocumentManager::~DocumentManager() { @@ -17,7 +24,11 @@ CSMDoc::DocumentManager::~DocumentManager() CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { - Document *document = new Document (files, savePath, new_); + boost::filesystem::path projectFile (mProjectPath); + + projectFile /= savePath.filename().string() + ".project"; + + Document *document = new Document (files, savePath, new_, projectFile); mDocuments.push_back (document); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index dfded8d5c8..622a135a58 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -13,13 +13,15 @@ namespace CSMDoc class DocumentManager { std::vector mDocuments; + boost::filesystem::path mProjectPath; DocumentManager (const DocumentManager&); DocumentManager& operator= (const DocumentManager&); public: - DocumentManager(); + DocumentManager (const boost::filesystem::path& projectPath); + ///< \param projectPath Directory where additional per-project data will be stored. ~DocumentManager(); diff --git a/apps/opencs/model/doc/saving.cpp b/apps/opencs/model/doc/saving.cpp index 98af661fdf..adcfca5768 100644 --- a/apps/opencs/model/doc/saving.cpp +++ b/apps/opencs/model/doc/saving.cpp @@ -8,12 +8,20 @@ #include "savingstages.hpp" #include "document.hpp" -CSMDoc::Saving::Saving (Document& document) -: Operation (State_Saving, true, true), mDocument (document), mState (*this) +CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& projectPath) +: Operation (State_Saving, true, true), mDocument (document), mState (*this, projectPath) { - appendStage (new OpenSaveStage (mDocument, mState)); + // save project file + appendStage (new OpenSaveStage (mDocument, mState, true)); - appendStage (new WriteHeaderStage (mDocument, mState)); + appendStage (new WriteHeaderStage (mDocument, mState, true)); + + appendStage (new CloseSaveStage (mState)); + + // save content file + appendStage (new OpenSaveStage (mDocument, mState, false)); + + appendStage (new WriteHeaderStage (mDocument, mState, false)); appendStage (new WriteCollectionStage > (mDocument.getData().getGlobals(), mState)); diff --git a/apps/opencs/model/doc/saving.hpp b/apps/opencs/model/doc/saving.hpp index b89ba5f6db..cd1bbef980 100644 --- a/apps/opencs/model/doc/saving.hpp +++ b/apps/opencs/model/doc/saving.hpp @@ -1,6 +1,8 @@ #ifndef CSM_DOC_SAVING_H #define CSM_DOC_SAVING_H +#include + #include "operation.hpp" #include "savingstate.hpp" @@ -17,7 +19,7 @@ namespace CSMDoc public: - Saving (Document& document); + Saving (Document& document, const boost::filesystem::path& projectPath); }; } diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 23a88bc17a..d48e220123 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -10,8 +10,8 @@ #include "document.hpp" #include "savingstate.hpp" -CSMDoc::OpenSaveStage::OpenSaveStage (Document& document, SavingState& state) -: mDocument (document), mState (state) +CSMDoc::OpenSaveStage::OpenSaveStage (Document& document, SavingState& state, bool projectFile) +: mDocument (document), mState (state), mProjectFile (projectFile) {} int CSMDoc::OpenSaveStage::setup() @@ -21,17 +21,17 @@ int CSMDoc::OpenSaveStage::setup() void CSMDoc::OpenSaveStage::perform (int stage, std::vector& messages) { - mState.start (mDocument); + mState.start (mDocument, mProjectFile); - mState.getStream().open (mState.getTmpPath().string().c_str()); + mState.getStream().open ((mProjectFile ? mState.getPath() : mState.getTmpPath()).string().c_str()); if (!mState.getStream().is_open()) throw std::runtime_error ("failed to open stream for saving"); } -CSMDoc::WriteHeaderStage::WriteHeaderStage (Document& document, SavingState& state) -: mDocument (document), mState (state) +CSMDoc::WriteHeaderStage::WriteHeaderStage (Document& document, SavingState& state, bool simple) +: mDocument (document), mState (state), mSimple (simple) {} int CSMDoc::WriteHeaderStage::setup() @@ -43,26 +43,38 @@ void CSMDoc::WriteHeaderStage::perform (int stage, std::vector& mes { mState.getWriter().setVersion(); - mState.getWriter().setFormat (0); + mState.getWriter().clearMaster(); - mState.getWriter().setAuthor (mDocument.getData().getAuthor()); - mState.getWriter().setDescription (mDocument.getData().getDescription()); - mState.getWriter().setRecordCount ( - mDocument.getData().count (CSMWorld::RecordBase::State_Modified) + - mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) + - mDocument.getData().count (CSMWorld::RecordBase::State_Deleted)); - - /// \todo refine dependency list (at least remove redundant dependencies) - std::vector dependencies = mDocument.getContentFiles(); - std::vector::const_iterator end (--dependencies.end()); + mState.getWriter().setFormat (0); - for (std::vector::const_iterator iter (dependencies.begin()); - iter!=end; ++iter) + if (mSimple) { - std::string name = iter->filename().string(); - uint64_t size = boost::filesystem::file_size (*iter); + mState.getWriter().setAuthor (""); + mState.getWriter().setDescription (""); + mState.getWriter().setRecordCount (0); - mState.getWriter().addMaster (name, size); + } + else + { + mState.getWriter().setAuthor (mDocument.getData().getAuthor()); + mState.getWriter().setDescription (mDocument.getData().getDescription()); + mState.getWriter().setRecordCount ( + mDocument.getData().count (CSMWorld::RecordBase::State_Modified) + + mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) + + mDocument.getData().count (CSMWorld::RecordBase::State_Deleted)); + + /// \todo refine dependency list (at least remove redundant dependencies) + std::vector dependencies = mDocument.getContentFiles(); + std::vector::const_iterator end (--dependencies.end()); + + for (std::vector::const_iterator iter (dependencies.begin()); + iter!=end; ++iter) + { + std::string name = iter->filename().string(); + uint64_t size = boost::filesystem::file_size (*iter); + + mState.getWriter().addMaster (name, size); + } } mState.getWriter().save (mState.getStream()); @@ -121,7 +133,7 @@ void CSMDoc::FinalSavingStage::perform (int stage, std::vector& mes if (boost::filesystem::exists (mState.getTmpPath())) boost::filesystem::remove (mState.getTmpPath()); } - else + else if (!mState.isProjectFile()) { if (boost::filesystem::exists (mState.getPath())) boost::filesystem::remove (mState.getPath()); diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index 2d32f38cbd..367431fc12 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -16,10 +16,12 @@ namespace CSMDoc { Document& mDocument; SavingState& mState; + bool mProjectFile; public: - OpenSaveStage (Document& document, SavingState& state); + OpenSaveStage (Document& document, SavingState& state, bool projectFile); + ///< \param projectFile Saving the project file instead of the content file. virtual int setup(); ///< \return number of steps @@ -32,10 +34,12 @@ namespace CSMDoc { Document& mDocument; SavingState& mState; + bool mSimple; public: - WriteHeaderStage (Document& document, SavingState& state); + WriteHeaderStage (Document& document, SavingState& state, bool simple); + ///< \param simple Simplified header (used for project files). virtual int setup(); ///< \return number of steps diff --git a/apps/opencs/model/doc/savingstate.cpp b/apps/opencs/model/doc/savingstate.cpp index a49a0699b2..4a1abb8883 100644 --- a/apps/opencs/model/doc/savingstate.cpp +++ b/apps/opencs/model/doc/savingstate.cpp @@ -4,10 +4,11 @@ #include "operation.hpp" #include "document.hpp" -CSMDoc::SavingState::SavingState (Operation& operation) +CSMDoc::SavingState::SavingState (Operation& operation, const boost::filesystem::path& projectPath) : mOperation (operation), /// \todo set encoding properly, once config implementation has been fixed. - mEncoder (ToUTF8::calculateEncoding ("win1252")) + mEncoder (ToUTF8::calculateEncoding ("win1252")), + mProjectPath (projectPath), mProjectFile (false) { mWriter.setEncoder (&mEncoder); } @@ -17,14 +18,19 @@ bool CSMDoc::SavingState::hasError() const return mOperation.hasError(); } -void CSMDoc::SavingState::start (Document& document) +void CSMDoc::SavingState::start (Document& document, bool project) { + mProjectFile = project; + if (mStream.is_open()) mStream.close(); mStream.clear(); - mPath = document.getSavePath(); + if (project) + mPath = mProjectPath; + else + mPath = document.getSavePath(); boost::filesystem::path file (mPath.filename().string() + ".tmp"); @@ -51,4 +57,9 @@ std::ofstream& CSMDoc::SavingState::getStream() ESM::ESMWriter& CSMDoc::SavingState::getWriter() { return mWriter; +} + +bool CSMDoc::SavingState::isProjectFile() const +{ + return mProjectFile; } \ No newline at end of file diff --git a/apps/opencs/model/doc/savingstate.hpp b/apps/opencs/model/doc/savingstate.hpp index 3f42b4653d..8cf7883e50 100644 --- a/apps/opencs/model/doc/savingstate.hpp +++ b/apps/opencs/model/doc/savingstate.hpp @@ -20,14 +20,17 @@ namespace CSMDoc ToUTF8::Utf8Encoder mEncoder; std::ofstream mStream; ESM::ESMWriter mWriter; + boost::filesystem::path mProjectPath; + bool mProjectFile; public: - SavingState (Operation& operation); + SavingState (Operation& operation, const boost::filesystem::path& projectPath); bool hasError() const; - void start (Document& document); + void start (Document& document, bool project); + ///< \param project Save project file instead of content file. const boost::filesystem::path& getPath() const; @@ -36,6 +39,9 @@ namespace CSMDoc std::ofstream& getStream(); ESM::ESMWriter& getWriter(); + + bool isProjectFile() const; + ///< Currently saving project file? (instead of content file) }; diff --git a/components/esm/esmwriter.cpp b/components/esm/esmwriter.cpp index 95ad44811d..f39aa2b898 100644 --- a/components/esm/esmwriter.cpp +++ b/components/esm/esmwriter.cpp @@ -38,6 +38,11 @@ namespace ESM mHeader.mFormat = format; } + void ESMWriter::clearMaster() + { + mHeader.mMaster.clear(); + } + void ESMWriter::addMaster(const std::string& name, uint64_t size) { Header::MasterData d; diff --git a/components/esm/esmwriter.hpp b/components/esm/esmwriter.hpp index fc64c4a137..104f97f909 100644 --- a/components/esm/esmwriter.hpp +++ b/components/esm/esmwriter.hpp @@ -32,6 +32,8 @@ class ESMWriter void setRecordCount (int count); void setFormat (int format); + void clearMaster(); + void addMaster(const std::string& name, uint64_t size); void save(const std::string& file); diff --git a/components/esm/loadtes3.cpp b/components/esm/loadtes3.cpp index a86c9b6f4f..87a8d1d57e 100644 --- a/components/esm/loadtes3.cpp +++ b/components/esm/loadtes3.cpp @@ -14,6 +14,7 @@ void ESM::Header::blank() mData.desc.assign (""); mData.records = 0; mFormat = CurrentFormat; + mMaster.clear(); } void ESM::Header::load (ESMReader &esm)