From f85be6a7441d9dfb8b49d40b52a012088c636600 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 2 Mar 2013 07:57:41 -0600 Subject: [PATCH 1/9] 80% complete save-on-close feature --- apps/opencs/view/doc/operations.cpp | 2 +- apps/opencs/view/doc/view.cpp | 10 ++- apps/opencs/view/doc/view.hpp | 5 +- apps/opencs/view/doc/viewmanager.cpp | 121 ++++++++++++++++++++++++--- apps/opencs/view/doc/viewmanager.hpp | 7 +- 5 files changed, 129 insertions(+), 16 deletions(-) diff --git a/apps/opencs/view/doc/operations.cpp b/apps/opencs/view/doc/operations.cpp index 71cacbe17e..58cef13430 100644 --- a/apps/opencs/view/doc/operations.cpp +++ b/apps/opencs/view/doc/operations.cpp @@ -54,7 +54,7 @@ void CSVDoc::Operations::quitOperation (int type) mLayout->removeItem ((*iter)->getLayout()); - delete *iter; + (*iter)->deleteLater(); mOperations.erase (iter); if (oldCount > 1) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 6aafef4ed0..49dd2fc8a9 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -18,10 +18,14 @@ #include "operations.hpp" #include "subview.hpp" +#include void CSVDoc::View::closeEvent (QCloseEvent *event) { if (!mViewManager.closeRequest (this)) + { + qDebug() << "ignoring event"; event->ignore(); + } } void CSVDoc::View::setupFileMenu() @@ -117,9 +121,11 @@ void CSVDoc::View::updateActions() mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying)); } -CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent) - : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews), QMainWindow (viewParent) +CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) //, QMainWindow *viewParent) + : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), + mViewTotal (totalViews) //, QMainWindow (viewParent) { + setAttribute (Qt::WA_DeleteOnClose, true); setDockOptions (QMainWindow::AllowNestedDocks); resize (300, 300); /// \todo get default size from settings and set reasonable minimal size diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 28ab24b744..f50a0550ee 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -67,7 +67,7 @@ namespace CSVDoc public: - View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent); + View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews); //, QMainWindow *viewParent); ///< The ownership of \a document is not transferred to *this. virtual ~View(); @@ -94,6 +94,8 @@ namespace CSVDoc void addSubView (const CSMWorld::UniversalId& id); + void abortOperation (int type); + private slots: void newView(); @@ -106,7 +108,6 @@ namespace CSVDoc void addGmstsSubView(); - void abortOperation (int type); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index a8faefb970..59e53dfe07 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -12,6 +12,10 @@ #include "view.hpp" +#include +#include + + void CSVDoc::ViewManager::updateIndices() { std::map > documents; @@ -31,7 +35,7 @@ void CSVDoc::ViewManager::updateIndices() } CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) -: mDocumentManager (documentManager) + : mDocumentManager (documentManager), mCloseMeOnSaveStateChange(0) { mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; @@ -59,9 +63,9 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) this, SLOT (progress (int, int, int, int, CSMDoc::Document *))); } - QMainWindow *mainWindow = new QMainWindow; + // QMainWindow *mainWindow = new QMainWindow; - View *view = new View (*this, document, countViews (document)+1, mainWindow); + View *view = new View (*this, document, countViews (document)+1); //, mainWindow); mViews.push_back (view); @@ -90,6 +94,8 @@ bool CSVDoc::ViewManager::closeRequest (View *view) { std::vector::iterator iter = std::find (mViews.begin(), mViews.end(), view); + bool continueWithClose = true; + if (iter!=mViews.end()) { bool last = countViews (view->getDocument())<=1; @@ -97,16 +103,98 @@ bool CSVDoc::ViewManager::closeRequest (View *view) /// \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 - mViews.erase (iter); - view->deleteLater(); + CSMDoc::Document *document = view->getDocument(); - if (last) - mDocumentManager.removeDocument (view->getDocument()); - else - updateIndices(); + //notify user of unsaved changes and process response + if ( document->getState() & CSMDoc::State_Modified) + continueWithClose = showModifiedDocumentMessageBox (view); + + //notify user of saving in progress + if ( document->getState() & CSMDoc::State_Saving ) + continueWithClose = showSaveInProgressMessageBox (view); + + qDebug() << "Continue with close? " << continueWithClose; + + if (continueWithClose) + { + mViews.erase (iter); + + if (last) + mDocumentManager.removeDocument (document); + else + updateIndices(); + } } - return true; + return continueWithClose; +} + +bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (View* view) +{ + QMessageBox messageBox; + + 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; + + switch (messageBox.exec()) + { + case QMessageBox::Save: + view->getDocument()->save(); + mCloseMeOnSaveStateChange = view; + retVal = false; + break; + + case QMessageBox::Discard: + break; + + case QMessageBox::Cancel: + retVal = false; + break; + + default: + break; + + } + + return retVal; +} + +bool CSVDoc::ViewManager::showSaveInProgressMessageBox (View* view) +{ + 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); + + bool retVal = false; + + switch (messageBox.exec()) + { + case QMessageBox::Yes: + view->abortOperation(CSMDoc::State_Saving); + // mCloseMeOnSaveStateChange = view; + retVal = false; + break; + + case QMessageBox::No: + //mCloseMeOnSaveStateChange = view; + retVal = false; + break; + + case QMessageBox::Cancel: + retVal = false; + break; + + default: + break; + } + + return retVal; } void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document) @@ -114,6 +202,19 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) if ((*iter)->getDocument()==document) (*iter)->updateDocumentState(); + + if (mPreviousDocumentState & CSMDoc::State_Saving) + qDebug() << "Last state was saving"; + else + qDebug() << "Last state was something else"; +/* + if (mCloseMeOnSaveStateChange && (mPreviousDocumentState & CSMDoc::State_Saving)) + { + mCloseMeOnSaveStateChange->close(); + mCloseMeOnSaveStateChange = 0; + } +*/ + mPreviousDocumentState = state; } void CSVDoc::ViewManager::progress (int current, int max, int type, int threads, CSMDoc::Document *document) diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 72e7a3e1a1..2517f8ccbe 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -27,12 +27,17 @@ namespace CSVDoc CSMDoc::DocumentManager& mDocumentManager; std::vector mViews; CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories; + View *mCloseMeOnSaveStateChange; + int mPreviousDocumentState; // not implemented ViewManager (const ViewManager&); ViewManager& operator= (const ViewManager&); void updateIndices(); + bool showModifiedDocumentMessageBox (View* view); + bool showSaveInProgressMessageBox (View* view); + public: @@ -63,4 +68,4 @@ namespace CSVDoc } -#endif \ No newline at end of file +#endif From a2e36594c97eface26fabeee13c27e1f84ff8351 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 2 Mar 2013 09:22:44 -0600 Subject: [PATCH 2/9] Completed "abort save on close" feature --- apps/opencs/view/doc/view.cpp | 4 ++-- apps/opencs/view/doc/view.hpp | 2 +- apps/opencs/view/doc/viewmanager.cpp | 23 ++++++++++++----------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 49dd2fc8a9..b4d137be2e 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -121,9 +121,9 @@ void CSVDoc::View::updateActions() 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) + mViewTotal (totalViews) { setAttribute (Qt::WA_DeleteOnClose, true); setDockOptions (QMainWindow::AllowNestedDocks); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index f50a0550ee..d436aebe76 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -67,7 +67,7 @@ namespace CSVDoc 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. virtual ~View(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 59e53dfe07..02407dfcde 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -171,22 +171,22 @@ bool CSVDoc::ViewManager::showSaveInProgressMessageBox (View* view) messageBox.setInformativeText("Do you want to abort the save?"); messageBox.setStandardButtons (QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - bool retVal = false; + bool retVal = true; switch (messageBox.exec()) { - case QMessageBox::Yes: + case QMessageBox::Yes: //immediate shutdown + mCloseMeOnSaveStateChange = 0; view->abortOperation(CSMDoc::State_Saving); - // mCloseMeOnSaveStateChange = view; + break; + + case QMessageBox::No: //shutdown after save completes + mCloseMeOnSaveStateChange = view; retVal = false; break; - case QMessageBox::No: - //mCloseMeOnSaveStateChange = view; - retVal = false; - break; - - case QMessageBox::Cancel: + case QMessageBox::Cancel: //abort shutdown, allow save to complete + mCloseMeOnSaveStateChange = 0; retVal = false; break; @@ -207,13 +207,14 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc qDebug() << "Last state was saving"; else qDebug() << "Last state was something else"; -/* + + //mechanism to shutdown main window after saving operation completes if (mCloseMeOnSaveStateChange && (mPreviousDocumentState & CSMDoc::State_Saving)) { mCloseMeOnSaveStateChange->close(); mCloseMeOnSaveStateChange = 0; } -*/ + mPreviousDocumentState = state; } From bf6c855e6d829ca2f54abc380f6653cb0a5e3626 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 2 Mar 2013 12:49:26 -0600 Subject: [PATCH 3/9] Final changes to implement save-on-close features --- apps/opencs/view/doc/view.cpp | 9 +++--- apps/opencs/view/doc/viewmanager.cpp | 41 +++++++++++++++------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index fea121aa0d..0a8759fa1f 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -18,14 +18,10 @@ #include "operations.hpp" #include "subview.hpp" -#include void CSVDoc::View::closeEvent (QCloseEvent *event) { if (!mViewManager.closeRequest (this)) - { - qDebug() << "ignoring event"; event->ignore(); - } } void CSVDoc::View::setupFileMenu() @@ -43,6 +39,11 @@ void CSVDoc::View::setupFileMenu() mSave = new QAction (tr ("&Save"), this); connect (mSave, SIGNAL (triggered()), this, SLOT (save())); file->addAction (mSave); + + QAction *exit = new QAction (tr ("&Exit"), this); + connect (exit, SIGNAL (triggered()), this, SLOT (close())); + file->addAction(exit); + } void CSVDoc::View::setupEditMenu() diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 02407dfcde..a5c7910c0f 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -12,7 +12,6 @@ #include "view.hpp" -#include #include @@ -105,15 +104,13 @@ bool CSVDoc::ViewManager::closeRequest (View *view) CSMDoc::Document *document = view->getDocument(); - //notify user of unsaved changes and process response - if ( document->getState() & CSMDoc::State_Modified) - continueWithClose = showModifiedDocumentMessageBox (view); - //notify user of saving in progress if ( document->getState() & CSMDoc::State_Saving ) continueWithClose = showSaveInProgressMessageBox (view); - - qDebug() << "Continue with close? " << continueWithClose; + else + //notify user of unsaved changes and process response + if ( document->getState() & CSMDoc::State_Modified) + continueWithClose = showModifiedDocumentMessageBox (view); if (continueWithClose) { @@ -144,8 +141,13 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (View* view) { case QMessageBox::Save: view->getDocument()->save(); - mCloseMeOnSaveStateChange = view; - retVal = false; + + retVal = !(view->getDocument()->getState() & CSMDoc::State_Saving); + + if (!retVal) + mCloseMeOnSaveStateChange = view; + else + mCloseMeOnSaveStateChange = 0; break; case QMessageBox::Discard: @@ -181,8 +183,16 @@ bool CSVDoc::ViewManager::showSaveInProgressMessageBox (View* view) break; case QMessageBox::No: //shutdown after save completes + + //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; - retVal = false; + else + mCloseMeOnSaveStateChange = 0; + break; case QMessageBox::Cancel: //abort shutdown, allow save to complete @@ -203,17 +213,10 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc if ((*iter)->getDocument()==document) (*iter)->updateDocumentState(); - if (mPreviousDocumentState & CSMDoc::State_Saving) - qDebug() << "Last state was saving"; - else - qDebug() << "Last state was something else"; - //mechanism to shutdown main window after saving operation completes if (mCloseMeOnSaveStateChange && (mPreviousDocumentState & CSMDoc::State_Saving)) - { - mCloseMeOnSaveStateChange->close(); - mCloseMeOnSaveStateChange = 0; - } + if (mCloseMeOnSaveStateChange->close()) + mCloseMeOnSaveStateChange = 0; mPreviousDocumentState = state; } From eb90bd71badf66f7368f2c936c3b844ab7b3076a Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 2 Mar 2013 21:34:55 -0600 Subject: [PATCH 4/9] Fixed triggering confirmation messages boxes when more than one view is open. --- apps/opencs/view/doc/viewmanager.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index a5c7910c0f..63dd18291c 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -62,9 +62,7 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) this, SLOT (progress (int, int, int, int, CSMDoc::Document *))); } - // QMainWindow *mainWindow = new QMainWindow; - - View *view = new View (*this, document, countViews (document)+1); //, mainWindow); + View *view = new View (*this, document, countViews (document)+1); mViews.push_back (view); @@ -104,18 +102,21 @@ bool CSVDoc::ViewManager::closeRequest (View *view) CSMDoc::Document *document = view->getDocument(); - //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); + if (last) + { + //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); + } + + mViews.erase (iter); if (continueWithClose) { - mViews.erase (iter); - if (last) mDocumentManager.removeDocument (document); else From 6911868f2af56b48f2884e65092e0bbb52e14f56 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sun, 3 Mar 2013 15:58:26 -0600 Subject: [PATCH 5/9] File->close and File->exit menu items added. Exit uses closeAllWindows() to ensure ViewManager::closeRequest is called on the last open window. Exit will close all open windows but the last one in cases of active save operation or modified file. --- apps/opencs/editor.cpp | 4 +++- apps/opencs/view/doc/view.cpp | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index e2df365a29..98b67142a5 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -58,5 +58,7 @@ int CS::Editor::run() { mStartup.show(); + QApplication::setQuitOnLastWindowClosed (true); + return QApplication::exec(); -} \ No newline at end of file +} diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 0a8759fa1f..78eba78801 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "../../model/doc/document.hpp" @@ -40,10 +41,15 @@ void CSVDoc::View::setupFileMenu() connect (mSave, SIGNAL (triggered()), this, SLOT (save())); 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 (close())); + connect (exit, SIGNAL (triggered()), QApplication::instance(), SLOT (closeAllWindows())); file->addAction(exit); + } void CSVDoc::View::setupEditMenu() From 03c7f181125e05ebf8a46818f9e616db9a267db7 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Wed, 6 Mar 2013 06:41:33 -0600 Subject: [PATCH 6/9] Fixes for save-on-close message boxes --- apps/opencs/CMakeLists.txt | 1 - apps/opencs/model/doc/document.cpp | 7 +- apps/opencs/view/doc/view.cpp | 19 ++-- apps/opencs/view/doc/view.hpp | 10 +- apps/opencs/view/doc/viewmanager.cpp | 156 ++++++++++++++++++--------- apps/opencs/view/doc/viewmanager.hpp | 17 ++- 6 files changed, 141 insertions(+), 69 deletions(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d5d389a141..0446d921ff 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -1,4 +1,3 @@ - set (OPENCS_SRC main.cpp) opencs_units (. editor) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index b361577bec..2cdd1f5383 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -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); } } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 78eba78801..29aa471fdf 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -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); +} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index d436aebe76..d6b6ad4601 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -41,7 +41,8 @@ namespace CSVDoc std::vector 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(); + }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 63dd18291c..9bb96167d9 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -13,7 +13,7 @@ #include "view.hpp" #include - +#include 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::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::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::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::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::iterator iter = mViews.begin(); + + if ((*iter) != lastView) + (*iter)->close(); + else (*(++iter))->close(); + } + + lastView->close(); +} diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 2517f8ccbe..92df13785f 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -27,17 +27,16 @@ namespace CSVDoc CSMDoc::DocumentManager& mDocumentManager; std::vector mViews; CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories; - View *mCloseMeOnSaveStateChange; - int mPreviousDocumentState; + std::vector::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::iterator view); + bool showSaveInProgressMessageBox (std::vector::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); }; } From ce91ef36ead190d6e038f75feee31b2ce1f9db56 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sun, 10 Mar 2013 07:49:43 -0500 Subject: [PATCH 7/9] Fix for warnings on close, leaves all views open until a decision is made --- apps/opencs/view/doc/view.cpp | 8 +------ apps/opencs/view/doc/view.hpp | 2 -- apps/opencs/view/doc/viewmanager.cpp | 31 ++++++---------------------- apps/opencs/view/doc/viewmanager.hpp | 4 ---- 4 files changed, 7 insertions(+), 38 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 29aa471fdf..51d4a5135c 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -46,8 +46,7 @@ void CSVDoc::View::setupFileMenu() file->addAction(close); QAction *exit = new QAction (tr ("&Exit"), this); - connect (exit, SIGNAL (triggered()), this, SLOT (exitApplication())); - connect (this, SIGNAL (closeAllViews(View *)), &mViewManager, SLOT (closeAllViews(View *))); + connect (exit, SIGNAL (triggered()), QApplication::instance(), SLOT (closeAllWindows())); file->addAction(exit); } @@ -254,8 +253,3 @@ CSVDoc::Operations *CSVDoc::View::getOperations() const { return mOperations; } - -void CSVDoc::View::exitApplication() -{ - emit closeAllViews (this); -} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index d6b6ad4601..92c57fe9ec 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -112,8 +112,6 @@ namespace CSVDoc void addGmstsSubView(); - void exitApplication(); - }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index eb9744c11c..5614aeda44 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -108,16 +108,13 @@ bool CSVDoc::ViewManager::closeRequest (View *view) CSMDoc::Document *document = view->getDocument(); - if (last) - { - //notify user of saving in progress - if ( (document->getState() & CSMDoc::State_Saving) ) - continueWithClose = showSaveInProgressMessageBox (iter); + //notify user of saving in progress + if ( (document->getState() & CSMDoc::State_Saving) ) + continueWithClose = showSaveInProgressMessageBox (iter); - //notify user of unsaved changes and process response - else if ( document->getState() & CSMDoc::State_Modified) - continueWithClose = showModifiedDocumentMessageBox (iter); - } + //notify user of unsaved changes and process response + else if ( document->getState() & CSMDoc::State_Modified) + continueWithClose = showModifiedDocumentMessageBox (iter); if (continueWithClose) { @@ -268,19 +265,3 @@ void CSVDoc::ViewManager::onCloseWarningHandler (int state, CSMDoc::Document *do } } } - -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::iterator iter = mViews.begin(); - - if ((*iter) != lastView) - (*iter)->close(); - else (*(++iter))->close(); - } - - lastView->close(); -} diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 92df13785f..82a8b57330 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -60,10 +60,6 @@ namespace CSVDoc void closeMessageBox(); - public slots: - - void closeAllViews (View *lastView); - private slots: void documentStateChanged (int state, CSMDoc::Document *document); From 96b62940b399e4f88fb9c415d923a8506e3581af Mon Sep 17 00:00:00 2001 From: graffy76 Date: Mon, 11 Mar 2013 06:38:27 -0500 Subject: [PATCH 8/9] Fixes docked subviews becoming tabbed and application closure when closing one of several views. --- apps/opencs/view/doc/view.cpp | 4 +++- apps/opencs/view/doc/viewmanager.cpp | 22 +++++++++++++--------- apps/opencs/view/doc/viewmanager.hpp | 4 +++- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 51d4a5135c..dfbd92a609 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -131,10 +131,12 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews) { - setDockOptions (QMainWindow::AllowNestedDocks); + // setDockOptions (QMainWindow::AllowNestedDocks); resize (300, 300); /// \todo get default size from settings and set reasonable minimal size + mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks); + setCentralWidget (&mSubViewWindow); mOperations = new Operations; diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 5614aeda44..83ace49387 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -14,6 +14,8 @@ #include #include +#include +#include void CSVDoc::ViewManager::updateIndices() { @@ -44,6 +46,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType, new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float)); + connect (this, SIGNAL (exitApplication()), QApplication::instance(), SLOT (closeAllWindows())); + } CSVDoc::ViewManager::~ViewManager() @@ -143,7 +147,7 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (std::vector::i bool retVal = true; connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close())); - connect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onCloseWarningHandler(int, CSMDoc::Document *))); + connect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); mUserWarned = true; int response = messageBox.exec(); @@ -161,13 +165,13 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (std::vector::i case QMessageBox::Discard: - disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onCloseWarningHandler(int, CSMDoc::Document *))); + disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(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 *))); + disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); retVal = false; break; @@ -195,7 +199,7 @@ bool CSVDoc::ViewManager::showSaveInProgressMessageBox (std::vector::ite bool retVal = true; //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 ((*viewIter)->getDocument(), 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. @@ -216,7 +220,7 @@ bool CSVDoc::ViewManager::showSaveInProgressMessageBox (std::vector::ite else if (messageBox.clickedButton() == closeButton) { //disconnect to avoid segmentation fault - disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onCloseWarningHandler(int, CSMDoc::Document *))); + disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); (*viewIter)->abortOperation(CSMDoc::State_Saving); mCloseMeOnSaveStateChange = mViews.end(); } @@ -226,7 +230,7 @@ bool CSVDoc::ViewManager::showSaveInProgressMessageBox (std::vector::ite //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 *))); + disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); retVal = false; } @@ -247,7 +251,7 @@ void CSVDoc::ViewManager::progress (int current, int max, int type, int threads, (*iter)->updateProgress (current, max, type, threads); } -void CSVDoc::ViewManager::onCloseWarningHandler (int state, CSMDoc::Document *document) +void CSVDoc::ViewManager::onExitWarningHandler (int state, CSMDoc::Document *document) { if ( !(state & CSMDoc::State_Saving) ) { @@ -257,10 +261,10 @@ void CSVDoc::ViewManager::onCloseWarningHandler (int state, CSMDoc::Document *do emit closeMessageBox(); //otherwise, the user has closed the message box before the save operation ended. - //close the view + //exit the application else if (mCloseMeOnSaveStateChange!=mViews.end()) { - (*mCloseMeOnSaveStateChange)->close(); + emit exitApplication(); mCloseMeOnSaveStateChange = mViews.end(); } } diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 82a8b57330..b77e5f5758 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -60,13 +60,15 @@ namespace CSVDoc void closeMessageBox(); + void exitApplication(); + 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); + void onExitWarningHandler(int state, CSMDoc::Document* document); }; } From 50abb221625625ae6b448b65ccf74626f3f61437 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Tue, 12 Mar 2013 06:28:13 -0500 Subject: [PATCH 9/9] Fix to allow application closing from multiple views and a single view. --- apps/opencs/model/doc/document.cpp | 7 +- apps/opencs/model/doc/document.hpp | 3 +- apps/opencs/view/doc/view.cpp | 10 ++- apps/opencs/view/doc/view.hpp | 6 +- apps/opencs/view/doc/viewmanager.cpp | 89 ++++++++++--------- apps/opencs/view/doc/viewmanager.hpp | 11 ++- .../fileorderlist/model/datafilesmodel.cpp | 2 +- 7 files changed, 76 insertions(+), 52 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 3d8f961121..af34aeedf4 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2,7 +2,7 @@ #include "document.hpp" #include - +#include void CSMDoc::Document::load (const std::vector::const_iterator& begin, const std::vector::const_iterator& end, bool lastAsModified) { @@ -237,6 +237,11 @@ CSMDoc::Document::Document (const std::vector& files, b connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); } +CSMDoc::Document::~Document() +{ + qDebug() << "document destroyed"; +} + QUndoStack& CSMDoc::Document::getUndoStack() { return mUndoStack; diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index a7b198689e..94d5fe85cc 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -63,6 +63,7 @@ namespace CSMDoc public: Document (const std::vector& files, bool new_); + ~Document(); QUndoStack& getUndoStack(); @@ -105,4 +106,4 @@ namespace CSMDoc }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index dfbd92a609..995d3ca2e2 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -46,7 +46,8 @@ 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 (exit())); + connect (this, SIGNAL(exitApplicationRequest(CSVDoc::View *)), &mViewManager, SLOT(exitApplication(CSVDoc::View *))); file->addAction(exit); } @@ -131,8 +132,6 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to : 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 mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks); @@ -255,3 +254,8 @@ CSVDoc::Operations *CSVDoc::View::getOperations() const { return mOperations; } + +void CSVDoc::View::exit() +{ + emit exitApplicationRequest (this); +} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 92c57fe9ec..e91a4d4a80 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -66,6 +66,8 @@ namespace CSVDoc void updateActions(); + void exitApplication(); + public: View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews); @@ -92,7 +94,7 @@ namespace CSVDoc void loadDocumentRequest(); - void closeAllViews (View *); + void exitApplicationRequest (CSVDoc::View *view); public slots: @@ -106,6 +108,8 @@ namespace CSVDoc void save(); + void exit(); + void verify(); void addGlobalsSubView(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 83ace49387..527e3b2044 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -36,7 +36,7 @@ void CSVDoc::ViewManager::updateIndices() } CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) - : mDocumentManager (documentManager), mCloseMeOnSaveStateChange(0), mUserWarned(false) + : mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false) { mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; @@ -45,16 +45,12 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType, new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float)); - - connect (this, SIGNAL (exitApplication()), QApplication::instance(), SLOT (closeAllWindows())); - } CSVDoc::ViewManager::~ViewManager() { delete mDelegateFactories; - //not needed due to deletion in ViewManager::closeRequest? for (std::vector::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) delete *iter; } @@ -112,32 +108,40 @@ bool CSVDoc::ViewManager::closeRequest (View *view) CSMDoc::Document *document = view->getDocument(); - //notify user of saving in progress - if ( (document->getState() & CSMDoc::State_Saving) ) - continueWithClose = showSaveInProgressMessageBox (iter); - - //notify user of unsaved changes and process response - else if ( document->getState() & CSMDoc::State_Modified) - continueWithClose = showModifiedDocumentMessageBox (iter); - - if (continueWithClose) + if (last) + continueWithClose = notifySaveOnClose (view); + else { (*iter)->deleteLater(); mViews.erase (iter); - if (last) - mDocumentManager.removeDocument (document); - else - updateIndices(); + updateIndices(); } } return continueWithClose; } -bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (std::vector::iterator viewIter) +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?"); @@ -147,31 +151,31 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (std::vector::i bool retVal = true; connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close())); - connect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); + + 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: - (*viewIter)->getDocument()->save(); - mCloseMeOnSaveStateChange = viewIter; + document->save(); + mExitOnSaveStateChange = true; retVal = false; break; case QMessageBox::Discard: - disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); + disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); break; case QMessageBox::Cancel: //disconnect to prevent unintended view closures - disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); + disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); retVal = false; break; @@ -183,9 +187,10 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (std::vector::i return retVal; } -bool CSVDoc::ViewManager::showSaveInProgressMessageBox (std::vector::iterator viewIter) +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?"); @@ -199,38 +204,37 @@ bool CSVDoc::ViewManager::showSaveInProgressMessageBox (std::vector::ite bool retVal = true; //Connections shut down message box if operation ends before user makes a decision. - connect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); + 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 - mCloseMeOnSaveStateChange = viewIter; + mExitOnSaveStateChange = true; retVal = false; } else if (messageBox.clickedButton() == closeButton) { //disconnect to avoid segmentation fault - disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); - (*viewIter)->abortOperation(CSMDoc::State_Saving); - mCloseMeOnSaveStateChange = mViews.end(); + 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 - mCloseMeOnSaveStateChange = mViews.end(); - disconnect ((*viewIter)->getDocument(), SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); + mExitOnSaveStateChange = false; + disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *))); retVal = false; } @@ -262,10 +266,13 @@ void CSVDoc::ViewManager::onExitWarningHandler (int state, CSMDoc::Document *doc //otherwise, the user has closed the message box before the save operation ended. //exit the application - else if (mCloseMeOnSaveStateChange!=mViews.end()) - { - emit exitApplication(); - mCloseMeOnSaveStateChange = mViews.end(); - } + else if (mExitOnSaveStateChange) + QApplication::instance()->exit(); } } + +void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view) +{ + if (notifySaveOnClose (view)) + QApplication::instance()->exit(); +} diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index b77e5f5758..90f23eaa11 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -27,7 +27,7 @@ namespace CSVDoc CSMDoc::DocumentManager& mDocumentManager; std::vector mViews; CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories; - std::vector::iterator mCloseMeOnSaveStateChange; + bool mExitOnSaveStateChange; bool mUserWarned; // not implemented @@ -35,8 +35,9 @@ namespace CSVDoc ViewManager& operator= (const ViewManager&); void updateIndices(); - bool showModifiedDocumentMessageBox (std::vector::iterator view); - bool showSaveInProgressMessageBox (std::vector::iterator view); + bool notifySaveOnClose (View *view = 0); + bool showModifiedDocumentMessageBox (View *view); + bool showSaveInProgressMessageBox (View *view); public: @@ -60,7 +61,9 @@ namespace CSVDoc void closeMessageBox(); - void exitApplication(); + public slots: + + void exitApplication (CSVDoc::View *view); private slots: diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index b33e2e12ab..25286e2f85 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -1,6 +1,6 @@ -#include #include #include +#include #include