mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 21:23:52 +00:00
Fixes for save-on-close message boxes
This commit is contained in:
parent
6911868f2a
commit
03c7f18112
6 changed files with 141 additions and 69 deletions
|
@ -1,4 +1,3 @@
|
|||
|
||||
set (OPENCS_SRC main.cpp)
|
||||
|
||||
opencs_units (. editor)
|
||||
|
|
|
@ -287,11 +287,13 @@ void CSMDoc::Document::abortOperation (int type)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void CSMDoc::Document::modificationStateChanged (bool clean)
|
||||
{
|
||||
emit stateChanged (getState(), this);
|
||||
}
|
||||
|
||||
|
||||
void CSMDoc::Document::operationDone (int type)
|
||||
{
|
||||
emit stateChanged (getState(), this);
|
||||
|
@ -305,9 +307,12 @@ void CSMDoc::Document::saving()
|
|||
|
||||
if (mSaveCount>15)
|
||||
{
|
||||
//clear the stack before resetting the save state
|
||||
//to avoid emitting incorrect states
|
||||
mUndoStack.setClean();
|
||||
|
||||
mSaveCount = 0;
|
||||
mSaveTimer.stop();
|
||||
mUndoStack.setClean();
|
||||
emit stateChanged (getState(), this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,10 +46,10 @@ void CSVDoc::View::setupFileMenu()
|
|||
file->addAction(close);
|
||||
|
||||
QAction *exit = new QAction (tr ("&Exit"), this);
|
||||
connect (exit, SIGNAL (triggered()), QApplication::instance(), SLOT (closeAllWindows()));
|
||||
connect (exit, SIGNAL (triggered()), this, SLOT (exitApplication()));
|
||||
connect (this, SIGNAL (closeAllViews(View *)), &mViewManager, SLOT (closeAllViews(View *)));
|
||||
|
||||
file->addAction(exit);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CSVDoc::View::setupEditMenu()
|
||||
|
@ -132,13 +132,11 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to
|
|||
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1),
|
||||
mViewTotal (totalViews)
|
||||
{
|
||||
setAttribute (Qt::WA_DeleteOnClose, true);
|
||||
setDockOptions (QMainWindow::AllowNestedDocks);
|
||||
|
||||
resize (300, 300); /// \todo get default size from settings and set reasonable minimal size
|
||||
|
||||
mSubViewWindow = new QMainWindow();
|
||||
setCentralWidget (mSubViewWindow);
|
||||
setCentralWidget (&mSubViewWindow);
|
||||
|
||||
mOperations = new Operations;
|
||||
addDockWidget (Qt::BottomDockWidgetArea, mOperations);
|
||||
|
@ -213,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)
|
||||
|
||||
SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
|
||||
mSubViewWindow->addDockWidget (Qt::TopDockWidgetArea, view);
|
||||
mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view);
|
||||
|
||||
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this,
|
||||
SLOT (addSubView (const CSMWorld::UniversalId&)));
|
||||
|
@ -252,7 +250,12 @@ void CSVDoc::View::abortOperation (int type)
|
|||
updateActions();
|
||||
}
|
||||
|
||||
QDockWidget *CSVDoc::View::getOperations() const
|
||||
CSVDoc::Operations *CSVDoc::View::getOperations() const
|
||||
{
|
||||
return mOperations;
|
||||
}
|
||||
|
||||
void CSVDoc::View::exitApplication()
|
||||
{
|
||||
emit closeAllViews (this);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,8 @@ namespace CSVDoc
|
|||
std::vector<QAction *> mEditingActions;
|
||||
Operations *mOperations;
|
||||
SubViewFactoryManager mSubViewFactory;
|
||||
QMainWindow* mSubViewWindow;
|
||||
QMainWindow mSubViewWindow;
|
||||
|
||||
|
||||
// not implemented
|
||||
View (const View&);
|
||||
|
@ -68,6 +69,7 @@ namespace CSVDoc
|
|||
public:
|
||||
|
||||
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews);
|
||||
|
||||
///< The ownership of \a document is not transferred to *this.
|
||||
|
||||
virtual ~View();
|
||||
|
@ -82,7 +84,7 @@ namespace CSVDoc
|
|||
|
||||
void updateProgress (int current, int max, int type, int threads);
|
||||
|
||||
QDockWidget *getOperations() const;
|
||||
Operations *getOperations() const;
|
||||
|
||||
signals:
|
||||
|
||||
|
@ -90,6 +92,8 @@ namespace CSVDoc
|
|||
|
||||
void loadDocumentRequest();
|
||||
|
||||
void closeAllViews (View *);
|
||||
|
||||
public slots:
|
||||
|
||||
void addSubView (const CSMWorld::UniversalId& id);
|
||||
|
@ -108,6 +112,8 @@ namespace CSVDoc
|
|||
|
||||
void addGmstsSubView();
|
||||
|
||||
void exitApplication();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "view.hpp"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
void CSVDoc::ViewManager::updateIndices()
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ void CSVDoc::ViewManager::updateIndices()
|
|||
}
|
||||
|
||||
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
||||
: mDocumentManager (documentManager), mCloseMeOnSaveStateChange(0)
|
||||
: mDocumentManager (documentManager), mCloseMeOnSaveStateChange(0), mUserWarned(false)
|
||||
{
|
||||
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
|
||||
|
||||
|
@ -46,6 +46,7 @@ CSVDoc::ViewManager::~ViewManager()
|
|||
{
|
||||
delete mDelegateFactories;
|
||||
|
||||
//not needed due to deletion in ViewManager::closeRequest?
|
||||
for (std::vector<View *>::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter)
|
||||
delete *iter;
|
||||
}
|
||||
|
@ -64,6 +65,7 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
|
|||
|
||||
View *view = new View (*this, document, countViews (document)+1);
|
||||
|
||||
|
||||
mViews.push_back (view);
|
||||
|
||||
view->show();
|
||||
|
@ -106,17 +108,18 @@ bool CSVDoc::ViewManager::closeRequest (View *view)
|
|||
{
|
||||
//notify user of saving in progress
|
||||
if ( (document->getState() & CSMDoc::State_Saving) )
|
||||
continueWithClose = showSaveInProgressMessageBox (view);
|
||||
else
|
||||
//notify user of unsaved changes and process response
|
||||
if ( document->getState() & CSMDoc::State_Modified)
|
||||
continueWithClose = showModifiedDocumentMessageBox (view);
|
||||
}
|
||||
continueWithClose = showSaveInProgressMessageBox (iter);
|
||||
|
||||
mViews.erase (iter);
|
||||
//notify user of unsaved changes and process response
|
||||
else if ( document->getState() & CSMDoc::State_Modified)
|
||||
continueWithClose = showModifiedDocumentMessageBox (iter);
|
||||
}
|
||||
|
||||
if (continueWithClose)
|
||||
{
|
||||
(*iter)->deleteLater();
|
||||
mViews.erase (iter);
|
||||
|
||||
if (last)
|
||||
mDocumentManager.removeDocument (document);
|
||||
else
|
||||
|
@ -127,7 +130,7 @@ bool CSVDoc::ViewManager::closeRequest (View *view)
|
|||
return continueWithClose;
|
||||
}
|
||||
|
||||
bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (View* view)
|
||||
bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (std::vector<View *>::iterator viewIter)
|
||||
{
|
||||
QMessageBox messageBox;
|
||||
|
||||
|
@ -138,23 +141,32 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (View* view)
|
|||
|
||||
bool retVal = true;
|
||||
|
||||
switch (messageBox.exec())
|
||||
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
|
||||
connect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onCloseWarningHandler(int, CSMDoc::Document *)));
|
||||
mUserWarned = true;
|
||||
|
||||
int response = messageBox.exec();
|
||||
|
||||
mUserWarned = false;
|
||||
|
||||
switch (response)
|
||||
{
|
||||
case QMessageBox::Save:
|
||||
view->getDocument()->save();
|
||||
|
||||
retVal = !(view->getDocument()->getState() & CSMDoc::State_Saving);
|
||||
|
||||
if (!retVal)
|
||||
mCloseMeOnSaveStateChange = view;
|
||||
else
|
||||
mCloseMeOnSaveStateChange = 0;
|
||||
(*viewIter)->getDocument()->save();
|
||||
mCloseMeOnSaveStateChange = viewIter;
|
||||
retVal = false;
|
||||
break;
|
||||
|
||||
case QMessageBox::Discard:
|
||||
|
||||
disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onCloseWarningHandler(int, CSMDoc::Document *)));
|
||||
break;
|
||||
|
||||
case QMessageBox::Cancel:
|
||||
|
||||
//disconnect to prevent unintended view closures
|
||||
disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onCloseWarningHandler(int, CSMDoc::Document *)));
|
||||
retVal = false;
|
||||
break;
|
||||
|
||||
|
@ -166,43 +178,55 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (View* view)
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool CSVDoc::ViewManager::showSaveInProgressMessageBox (View* view)
|
||||
bool CSVDoc::ViewManager::showSaveInProgressMessageBox (std::vector<View *>::iterator viewIter)
|
||||
{
|
||||
QMessageBox messageBox;
|
||||
|
||||
messageBox.setText ("The document is currently being saved.");
|
||||
messageBox.setInformativeText("Do you want to abort the save?");
|
||||
messageBox.setStandardButtons (QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
||||
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;
|
||||
|
||||
switch (messageBox.exec())
|
||||
//Connections shut down message box if operation ends before user makes a decision.
|
||||
connect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onCloseWarningHandler(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)
|
||||
{
|
||||
case QMessageBox::Yes: //immediate shutdown
|
||||
mCloseMeOnSaveStateChange = 0;
|
||||
view->abortOperation(CSMDoc::State_Saving);
|
||||
break;
|
||||
//save the View iterator for shutdown after the save operation ends
|
||||
mCloseMeOnSaveStateChange = viewIter;
|
||||
retVal = false;
|
||||
}
|
||||
|
||||
case QMessageBox::No: //shutdown after save completes
|
||||
else if (messageBox.clickedButton() == closeButton)
|
||||
{
|
||||
//disconnect to avoid segmentation fault
|
||||
disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onCloseWarningHandler(int, CSMDoc::Document *)));
|
||||
(*viewIter)->abortOperation(CSMDoc::State_Saving);
|
||||
mCloseMeOnSaveStateChange = mViews.end();
|
||||
}
|
||||
|
||||
//return true (continue with close) if the save operation ended before the
|
||||
//user clicked "No"
|
||||
retVal = !(view->getDocument()->getState() & CSMDoc::State_Saving);
|
||||
|
||||
if (!retVal)
|
||||
mCloseMeOnSaveStateChange = view;
|
||||
else
|
||||
mCloseMeOnSaveStateChange = 0;
|
||||
|
||||
break;
|
||||
|
||||
case QMessageBox::Cancel: //abort shutdown, allow save to complete
|
||||
mCloseMeOnSaveStateChange = 0;
|
||||
retVal = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
else if (messageBox.clickedButton() == cancelButton)
|
||||
{
|
||||
//abort shutdown, allow save to complete
|
||||
//disconnection to prevent unintended view closures
|
||||
mCloseMeOnSaveStateChange = mViews.end();
|
||||
disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onCloseWarningHandler(int, CSMDoc::Document *)));
|
||||
retVal = false;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
@ -213,13 +237,6 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc
|
|||
for (std::vector<View *>::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter)
|
||||
if ((*iter)->getDocument()==document)
|
||||
(*iter)->updateDocumentState();
|
||||
|
||||
//mechanism to shutdown main window after saving operation completes
|
||||
if (mCloseMeOnSaveStateChange && (mPreviousDocumentState & CSMDoc::State_Saving))
|
||||
if (mCloseMeOnSaveStateChange->close())
|
||||
mCloseMeOnSaveStateChange = 0;
|
||||
|
||||
mPreviousDocumentState = state;
|
||||
}
|
||||
|
||||
void CSVDoc::ViewManager::progress (int current, int max, int type, int threads, CSMDoc::Document *document)
|
||||
|
@ -228,3 +245,38 @@ void CSVDoc::ViewManager::progress (int current, int max, int type, int threads,
|
|||
if ((*iter)->getDocument()==document)
|
||||
(*iter)->updateProgress (current, max, type, threads);
|
||||
}
|
||||
|
||||
void CSVDoc::ViewManager::onCloseWarningHandler (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.
|
||||
//close the view
|
||||
else if (mCloseMeOnSaveStateChange!=mViews.end())
|
||||
{
|
||||
(*mCloseMeOnSaveStateChange)->close();
|
||||
mCloseMeOnSaveStateChange = mViews.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSVDoc::ViewManager::closeAllViews (View *lastView)
|
||||
{
|
||||
//forces document views to close in an orderly manner
|
||||
// the last view closed is the view from which the "Exit" action was triggered
|
||||
while (mViews.size() > 1)
|
||||
{
|
||||
std::vector<View *>::iterator iter = mViews.begin();
|
||||
|
||||
if ((*iter) != lastView)
|
||||
(*iter)->close();
|
||||
else (*(++iter))->close();
|
||||
}
|
||||
|
||||
lastView->close();
|
||||
}
|
||||
|
|
|
@ -27,17 +27,16 @@ namespace CSVDoc
|
|||
CSMDoc::DocumentManager& mDocumentManager;
|
||||
std::vector<View *> mViews;
|
||||
CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories;
|
||||
View *mCloseMeOnSaveStateChange;
|
||||
int mPreviousDocumentState;
|
||||
std::vector<View *>::iterator mCloseMeOnSaveStateChange;
|
||||
bool mUserWarned;
|
||||
|
||||
// not implemented
|
||||
ViewManager (const ViewManager&);
|
||||
ViewManager& operator= (const ViewManager&);
|
||||
|
||||
void updateIndices();
|
||||
bool showModifiedDocumentMessageBox (View* view);
|
||||
bool showSaveInProgressMessageBox (View* view);
|
||||
|
||||
bool showModifiedDocumentMessageBox (std::vector<View*>::iterator view);
|
||||
bool showSaveInProgressMessageBox (std::vector<View*>::iterator view);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -59,11 +58,19 @@ namespace CSVDoc
|
|||
|
||||
void loadDocumentRequest();
|
||||
|
||||
void closeMessageBox();
|
||||
|
||||
public slots:
|
||||
|
||||
void closeAllViews (View *lastView);
|
||||
|
||||
private slots:
|
||||
|
||||
void documentStateChanged (int state, CSMDoc::Document *document);
|
||||
|
||||
void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
|
||||
|
||||
void onCloseWarningHandler(int state, CSMDoc::Document* document);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue