1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-01 18:15:32 +00:00

Merge remote-tracking branch 'graffy76/saveOnClose' into next

This commit is contained in:
Marc Zinnschlag 2013-03-12 14:47:42 +01:00
commit 170451cb79
10 changed files with 227 additions and 27 deletions

View file

@ -1,4 +1,3 @@
set (OPENCS_SRC main.cpp) set (OPENCS_SRC main.cpp)
opencs_units (. editor) opencs_units (. editor)

View file

@ -113,5 +113,7 @@ int CS::Editor::run()
{ {
mStartup.show(); mStartup.show();
QApplication::setQuitOnLastWindowClosed (true);
return QApplication::exec(); return QApplication::exec();
} }

View file

@ -2,7 +2,7 @@
#include "document.hpp" #include "document.hpp"
#include <cassert> #include <cassert>
#include <QDebug>
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin, void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified) const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
{ {
@ -237,6 +237,11 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, b
connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving()));
} }
CSMDoc::Document::~Document()
{
qDebug() << "document destroyed";
}
QUndoStack& CSMDoc::Document::getUndoStack() QUndoStack& CSMDoc::Document::getUndoStack()
{ {
return mUndoStack; return mUndoStack;
@ -290,11 +295,13 @@ void CSMDoc::Document::abortOperation (int type)
} }
} }
void CSMDoc::Document::modificationStateChanged (bool clean) void CSMDoc::Document::modificationStateChanged (bool clean)
{ {
emit stateChanged (getState(), this); emit stateChanged (getState(), this);
} }
void CSMDoc::Document::operationDone (int type) void CSMDoc::Document::operationDone (int type)
{ {
emit stateChanged (getState(), this); emit stateChanged (getState(), this);
@ -308,9 +315,12 @@ void CSMDoc::Document::saving()
if (mSaveCount>15) if (mSaveCount>15)
{ {
//clear the stack before resetting the save state
//to avoid emitting incorrect states
mUndoStack.setClean();
mSaveCount = 0; mSaveCount = 0;
mSaveTimer.stop(); mSaveTimer.stop();
mUndoStack.setClean();
emit stateChanged (getState(), this); emit stateChanged (getState(), this);
} }
} }

View file

@ -63,6 +63,7 @@ namespace CSMDoc
public: public:
Document (const std::vector<boost::filesystem::path>& files, bool new_); Document (const std::vector<boost::filesystem::path>& files, bool new_);
~Document();
QUndoStack& getUndoStack(); QUndoStack& getUndoStack();

View file

@ -56,7 +56,7 @@ void CSVDoc::Operations::quitOperation (int type)
mLayout->removeItem ((*iter)->getLayout()); mLayout->removeItem ((*iter)->getLayout());
delete *iter; (*iter)->deleteLater();
mOperations.erase (iter); mOperations.erase (iter);
if (oldCount > 1) if (oldCount > 1)

View file

@ -7,6 +7,7 @@
#include <QMenuBar> #include <QMenuBar>
#include <QMdiArea> #include <QMdiArea>
#include <QDockWidget> #include <QDockWidget>
#include <QtGui/QApplication>
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
@ -39,6 +40,16 @@ void CSVDoc::View::setupFileMenu()
mSave = new QAction (tr ("&Save"), this); mSave = new QAction (tr ("&Save"), this);
connect (mSave, SIGNAL (triggered()), this, SLOT (save())); connect (mSave, SIGNAL (triggered()), this, SLOT (save()));
file->addAction (mSave); file->addAction (mSave);
QAction *close = new QAction (tr ("&Close"), this);
connect (close, SIGNAL (triggered()), this, SLOT (close()));
file->addAction(close);
QAction *exit = new QAction (tr ("&Exit"), this);
connect (exit, SIGNAL (triggered()), this, SLOT (exit()));
connect (this, SIGNAL(exitApplicationRequest(CSVDoc::View *)), &mViewManager, SLOT(exitApplication(CSVDoc::View *)));
file->addAction(exit);
} }
void CSVDoc::View::setupEditMenu() void CSVDoc::View::setupEditMenu()
@ -117,15 +128,15 @@ void CSVDoc::View::updateActions()
mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying)); mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying));
} }
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent) CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews)
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews), QMainWindow (viewParent) : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1),
mViewTotal (totalViews)
{ {
setDockOptions (QMainWindow::AllowNestedDocks);
resize (300, 300); /// \todo get default size from settings and set reasonable minimal size resize (300, 300); /// \todo get default size from settings and set reasonable minimal size
mSubViewWindow = new QMainWindow(); mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks);
setCentralWidget (mSubViewWindow);
setCentralWidget (&mSubViewWindow);
mOperations = new Operations; mOperations = new Operations;
addDockWidget (Qt::BottomDockWidgetArea, mOperations); addDockWidget (Qt::BottomDockWidgetArea, mOperations);
@ -200,7 +211,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id)
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) /// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
SubView *view = mSubViewFactory.makeSubView (id, *mDocument); SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
mSubViewWindow->addDockWidget (Qt::TopDockWidgetArea, view); mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view);
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this, connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this,
SLOT (addSubView (const CSMWorld::UniversalId&))); SLOT (addSubView (const CSMWorld::UniversalId&)));
@ -239,7 +250,12 @@ void CSVDoc::View::abortOperation (int type)
updateActions(); updateActions();
} }
QDockWidget *CSVDoc::View::getOperations() const CSVDoc::Operations *CSVDoc::View::getOperations() const
{ {
return mOperations; return mOperations;
} }
void CSVDoc::View::exit()
{
emit exitApplicationRequest (this);
}

View file

@ -41,7 +41,8 @@ namespace CSVDoc
std::vector<QAction *> mEditingActions; std::vector<QAction *> mEditingActions;
Operations *mOperations; Operations *mOperations;
SubViewFactoryManager mSubViewFactory; SubViewFactoryManager mSubViewFactory;
QMainWindow* mSubViewWindow; QMainWindow mSubViewWindow;
// not implemented // not implemented
View (const View&); View (const View&);
@ -65,9 +66,12 @@ namespace CSVDoc
void updateActions(); void updateActions();
void exitApplication();
public: public:
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent); View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews);
///< The ownership of \a document is not transferred to *this. ///< The ownership of \a document is not transferred to *this.
virtual ~View(); virtual ~View();
@ -82,7 +86,7 @@ namespace CSVDoc
void updateProgress (int current, int max, int type, int threads); void updateProgress (int current, int max, int type, int threads);
QDockWidget *getOperations() const; Operations *getOperations() const;
signals: signals:
@ -90,23 +94,28 @@ namespace CSVDoc
void loadDocumentRequest(); void loadDocumentRequest();
void exitApplicationRequest (CSVDoc::View *view);
public slots: public slots:
void addSubView (const CSMWorld::UniversalId& id); void addSubView (const CSMWorld::UniversalId& id);
void abortOperation (int type);
private slots: private slots:
void newView(); void newView();
void save(); void save();
void exit();
void verify(); void verify();
void addGlobalsSubView(); void addGlobalsSubView();
void addGmstsSubView(); void addGmstsSubView();
void abortOperation (int type);
}; };
} }

View file

@ -12,6 +12,11 @@
#include "view.hpp" #include "view.hpp"
#include <QMessageBox>
#include <QPushButton>
#include <QtGui/QApplication>
#include <QDebug>
void CSVDoc::ViewManager::updateIndices() void CSVDoc::ViewManager::updateIndices()
{ {
std::map<CSMDoc::Document *, std::pair<int, int> > documents; std::map<CSMDoc::Document *, std::pair<int, int> > documents;
@ -31,7 +36,7 @@ void CSVDoc::ViewManager::updateIndices()
} }
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
: mDocumentManager (documentManager) : mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false)
{ {
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
@ -40,7 +45,6 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType, mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float)); new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
} }
CSVDoc::ViewManager::~ViewManager() CSVDoc::ViewManager::~ViewManager()
@ -63,9 +67,8 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
this, SLOT (progress (int, int, int, int, CSMDoc::Document *))); this, SLOT (progress (int, int, int, int, CSMDoc::Document *)));
} }
QMainWindow *mainWindow = new QMainWindow; View *view = new View (*this, document, countViews (document)+1);
View *view = new View (*this, document, countViews (document)+1, mainWindow);
mViews.push_back (view); mViews.push_back (view);
@ -94,6 +97,8 @@ bool CSVDoc::ViewManager::closeRequest (View *view)
{ {
std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view); std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view);
bool continueWithClose = true;
if (iter!=mViews.end()) if (iter!=mViews.end())
{ {
bool last = countViews (view->getDocument())<=1; bool last = countViews (view->getDocument())<=1;
@ -101,16 +106,139 @@ bool CSVDoc::ViewManager::closeRequest (View *view)
/// \todo check if save is in progress -> warn user about possible data loss /// \todo check if save is in progress -> warn user about possible data loss
/// \todo check if document has not been saved -> return false and start close dialogue /// \todo check if document has not been saved -> return false and start close dialogue
mViews.erase (iter); CSMDoc::Document *document = view->getDocument();
view->deleteLater();
if (last) if (last)
mDocumentManager.removeDocument (view->getDocument()); continueWithClose = notifySaveOnClose (view);
else else
{
(*iter)->deleteLater();
mViews.erase (iter);
updateIndices(); updateIndices();
} }
}
return true; return continueWithClose;
}
bool CSVDoc::ViewManager::notifySaveOnClose (CSVDoc::View *view)
{
bool result = true;
CSMDoc::Document *document = view->getDocument();
//notify user of saving in progress
if ( (document->getState() & CSMDoc::State_Saving) )
result = showSaveInProgressMessageBox (view);
//notify user of unsaved changes and process response
else if ( document->getState() & CSMDoc::State_Modified)
result = showModifiedDocumentMessageBox (view);
return result;
}
bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view)
{
QMessageBox messageBox;
CSMDoc::Document *document = view->getDocument();
messageBox.setText ("The document has been modified.");
messageBox.setInformativeText ("Do you want to save your changes?");
messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
messageBox.setDefaultButton (QMessageBox::Save);
bool retVal = true;
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
mUserWarned = true;
int response = messageBox.exec();
mUserWarned = false;
switch (response)
{
case QMessageBox::Save:
document->save();
mExitOnSaveStateChange = true;
retVal = false;
break;
case QMessageBox::Discard:
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
break;
case QMessageBox::Cancel:
//disconnect to prevent unintended view closures
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
retVal = false;
break;
default:
break;
}
return retVal;
}
bool CSVDoc::ViewManager::showSaveInProgressMessageBox (CSVDoc::View *view)
{
QMessageBox messageBox;
CSMDoc::Document *document = view->getDocument();
messageBox.setText ("The document is currently being saved.");
messageBox.setInformativeText("Do you want to close now and abort saving, or wait until saving has completed?");
QPushButton* waitButton = messageBox.addButton (tr("Wait"), QMessageBox::YesRole);
QPushButton* closeButton = messageBox.addButton (tr("Close Now"), QMessageBox::RejectRole);
QPushButton* cancelButton = messageBox.addButton (tr("Cancel"), QMessageBox::NoRole);
messageBox.setDefaultButton (waitButton);
bool retVal = true;
//Connections shut down message box if operation ends before user makes a decision.
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
//set / clear the user warned flag to indicate whether or not the message box is currently active.
mUserWarned = true;
messageBox.exec();
mUserWarned = false;
//if closed by the warning handler, defaults to the RejectRole button (closeButton)
if (messageBox.clickedButton() == waitButton)
{
//save the View iterator for shutdown after the save operation ends
mExitOnSaveStateChange = true;
retVal = false;
}
else if (messageBox.clickedButton() == closeButton)
{
//disconnect to avoid segmentation fault
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
view->abortOperation(CSMDoc::State_Saving);
mExitOnSaveStateChange = true;
}
else if (messageBox.clickedButton() == cancelButton)
{
//abort shutdown, allow save to complete
//disconnection to prevent unintended view closures
mExitOnSaveStateChange = false;
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
retVal = false;
}
return retVal;
} }
void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document) void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document)
@ -126,3 +254,25 @@ void CSVDoc::ViewManager::progress (int current, int max, int type, int threads,
if ((*iter)->getDocument()==document) if ((*iter)->getDocument()==document)
(*iter)->updateProgress (current, max, type, threads); (*iter)->updateProgress (current, max, type, threads);
} }
void CSVDoc::ViewManager::onExitWarningHandler (int state, CSMDoc::Document *document)
{
if ( !(state & CSMDoc::State_Saving) )
{
//if the user is being warned (message box is active), shut down the message box,
//as there is no save operation currently running
if ( mUserWarned )
emit closeMessageBox();
//otherwise, the user has closed the message box before the save operation ended.
//exit the application
else if (mExitOnSaveStateChange)
QApplication::instance()->exit();
}
}
void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view)
{
if (notifySaveOnClose (view))
QApplication::instance()->exit();
}

View file

@ -27,12 +27,17 @@ namespace CSVDoc
CSMDoc::DocumentManager& mDocumentManager; CSMDoc::DocumentManager& mDocumentManager;
std::vector<View *> mViews; std::vector<View *> mViews;
CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories; CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories;
bool mExitOnSaveStateChange;
bool mUserWarned;
// not implemented // not implemented
ViewManager (const ViewManager&); ViewManager (const ViewManager&);
ViewManager& operator= (const ViewManager&); ViewManager& operator= (const ViewManager&);
void updateIndices(); void updateIndices();
bool notifySaveOnClose (View *view = 0);
bool showModifiedDocumentMessageBox (View *view);
bool showSaveInProgressMessageBox (View *view);
public: public:
@ -54,11 +59,19 @@ namespace CSVDoc
void loadDocumentRequest(); void loadDocumentRequest();
void closeMessageBox();
public slots:
void exitApplication (CSVDoc::View *view);
private slots: private slots:
void documentStateChanged (int state, CSMDoc::Document *document); void documentStateChanged (int state, CSMDoc::Document *document);
void progress (int current, int max, int type, int threads, CSMDoc::Document *document); void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
void onExitWarningHandler(int state, CSMDoc::Document* document);
}; };
} }

View file

@ -1,6 +1,6 @@
#include <QDebug>
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include <QDebug>
#include <stdexcept> #include <stdexcept>