diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 8d09eb6454..b6de9295de 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 + document operation saving ) opencs_units_noqt (model/doc - documentmanager stage + documentmanager stage savingstate savingstages ) opencs_hdrs_noqt (model/doc diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index d7138f6714..9b22175591 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2141,7 +2141,7 @@ void CSMDoc::Document::createBase() CSMDoc::Document::Document (const std::vector& files, const boost::filesystem::path& savePath, bool new_) -: mSavePath (savePath), mTools (mData) +: mSavePath (savePath), mTools (mData), mSaving (*this) { if (files.empty()) throw std::runtime_error ("Empty content file sequence"); @@ -2166,9 +2166,8 @@ CSMDoc::Document::Document (const std::vector& files, connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); connect (&mTools, SIGNAL (done (int)), this, SLOT (operationDone (int))); - // dummy implementation -> remove when proper save is implemented. - mSaveCount = 0; - connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); + connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); + connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int))); } CSMDoc::Document::~Document() @@ -2187,7 +2186,7 @@ int CSMDoc::Document::getState() const if (!mUndoStack.isClean()) state |= State_Modified; - if (mSaveCount) + if (mSaving.isRunning()) state |= State_Locked | State_Saving | State_Operation; if (int operations = mTools.getRunningOperations()) @@ -2203,10 +2202,13 @@ const boost::filesystem::path& CSMDoc::Document::getSavePath() const void CSMDoc::Document::save() { - mSaveCount = 1; - mSaveTimer.start (500); + if (mSaving.isRunning()) + throw std::logic_error ( + "Failed to initiate save, because a save operation is already running."); + + mSaving.start(); + emit stateChanged (getState(), this); - emit progress (1, 16, State_Saving, 1, this); } CSMWorld::UniversalId CSMDoc::Document::verify() @@ -2218,17 +2220,12 @@ CSMWorld::UniversalId CSMDoc::Document::verify() void CSMDoc::Document::abortOperation (int type) { - mTools.abortOperation (type); - if (type==State_Saving) - { - mSaveCount=0; - mSaveTimer.stop(); - emit stateChanged (getState(), this); - } + mSaving.abort(); + else + mTools.abortOperation (type); } - void CSMDoc::Document::modificationStateChanged (bool clean) { emit stateChanged (getState(), this); @@ -2240,24 +2237,6 @@ void CSMDoc::Document::operationDone (int type) emit stateChanged (getState(), this); } -void CSMDoc::Document::saving() -{ - ++mSaveCount; - - emit progress (mSaveCount, 16, State_Saving, 1, this); - - if (mSaveCount>15) - { - //clear the stack before resetting the save state - //to avoid emitting incorrect states - mUndoStack.setClean(); - - mSaveCount = 0; - mSaveTimer.stop(); - emit stateChanged (getState(), this); - } -} - const CSMWorld::Data& CSMDoc::Document::getData() const { return mData; diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 3532721ead..5a03955105 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -14,6 +14,7 @@ #include "../tools/tools.hpp" #include "state.hpp" +#include "saving.hpp" class QAbstractItemModel; @@ -34,14 +35,12 @@ namespace CSMDoc boost::filesystem::path mSavePath; CSMWorld::Data mData; CSMTools::Tools mTools; + Saving mSaving; // It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is // using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late. QUndoStack mUndoStack; - int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. - QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. - // not implemented Document (const Document&); Document& operator= (const Document&); @@ -100,9 +99,6 @@ namespace CSMDoc void operationDone (int type); - void saving(); - ///< dummy implementation -> remove when proper save is implemented. - public slots: void progress (int current, int max, int type); diff --git a/apps/opencs/model/doc/saving.cpp b/apps/opencs/model/doc/saving.cpp new file mode 100644 index 0000000000..dda4ad12a8 --- /dev/null +++ b/apps/opencs/model/doc/saving.cpp @@ -0,0 +1,14 @@ + +#include "saving.hpp" + +#include "state.hpp" + +#include "savingstages.hpp" + +CSMDoc::Saving::Saving (Document& document) +: Operation (State_Saving, true, true), mDocument (document), mState (*this) +{ + + + appendStage (new FinalSavingStage (mDocument, mState)); +} \ No newline at end of file diff --git a/apps/opencs/model/doc/saving.hpp b/apps/opencs/model/doc/saving.hpp new file mode 100644 index 0000000000..b89ba5f6db --- /dev/null +++ b/apps/opencs/model/doc/saving.hpp @@ -0,0 +1,25 @@ +#ifndef CSM_DOC_SAVING_H +#define CSM_DOC_SAVING_H + +#include "operation.hpp" +#include "savingstate.hpp" + +namespace CSMDoc +{ + class Document; + + class Saving : public Operation + { + Q_OBJECT + + Document& mDocument; + SavingState mState; + + public: + + Saving (Document& document); + + }; +} + +#endif diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp new file mode 100644 index 0000000000..97facf6124 --- /dev/null +++ b/apps/opencs/model/doc/savingstages.cpp @@ -0,0 +1,30 @@ + +#include "savingstages.hpp" + +#include + +#include "document.hpp" +#include "savingstate.hpp" + +CSMDoc::FinalSavingStage::FinalSavingStage (Document& document, SavingState& state) +: mDocument (document), mState (state) +{} + +int CSMDoc::FinalSavingStage::setup() +{ + return 1; +} + +void CSMDoc::FinalSavingStage::perform (int stage, std::vector& messages) +{ + if (mState.hasError()) + { + /// \todo close stream + /// \todo delete tmp file + } + else + { + /// \todo delete file, rename tmp file + mDocument.getUndoStack().setClean(); + } +} \ No newline at end of file diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp new file mode 100644 index 0000000000..1549c9640e --- /dev/null +++ b/apps/opencs/model/doc/savingstages.hpp @@ -0,0 +1,28 @@ +#ifndef CSM_DOC_SAVINGSTAGES_H +#define CSM_DOC_SAVINGSTAGES_H + +#include "stage.hpp" + +namespace CSMDoc +{ + class Document; + class SavingState; + + class FinalSavingStage : public Stage + { + Document& mDocument; + SavingState& mState; + + public: + + FinalSavingStage (Document& document, SavingState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/doc/savingstate.cpp b/apps/opencs/model/doc/savingstate.cpp new file mode 100644 index 0000000000..3798708593 --- /dev/null +++ b/apps/opencs/model/doc/savingstate.cpp @@ -0,0 +1,13 @@ + +#include "savingstate.hpp" + +#include "operation.hpp" + +CSMDoc::SavingState::SavingState (Operation& operation) +: mOperation (operation) +{} + +bool CSMDoc::SavingState::hasError() const +{ + return mOperation.hasError(); +} \ No newline at end of file diff --git a/apps/opencs/model/doc/savingstate.hpp b/apps/opencs/model/doc/savingstate.hpp new file mode 100644 index 0000000000..b8b6f38782 --- /dev/null +++ b/apps/opencs/model/doc/savingstate.hpp @@ -0,0 +1,22 @@ +#ifndef CSM_DOC_SAVINGSTATE_H +#define CSM_DOC_SAVINGSTATE_H + +namespace CSMDoc +{ + class Operation; + + class SavingState + { + Operation& mOperation; + + public: + + SavingState (Operation& operation); + + bool hasError() const; + }; + + +} + +#endif \ No newline at end of file