From 7970b840492e43db981b840c7a52eb2478dd0305 Mon Sep 17 00:00:00 2001 From: Juergen Spitzmueller Date: Mon, 6 Apr 2015 13:50:32 +0200 Subject: [PATCH] Do not close LyX in the commitData process (#9277) Since the logout process still can be canceled here, we should only check that all dirty buffers are saved and that the session state is recorded. Please test, particularly on Windows and OSX, that logging out with LyX running (both with and without dirty buffers) proceeds sensibly and that the LyX session is correctly restored when you re-login. --- src/frontends/qt4/GuiApplication.cpp | 38 ++++++++++++++++++++++------ src/frontends/qt4/GuiApplication.h | 3 +++ src/frontends/qt4/GuiView.cpp | 26 +++++++++++++++++++ src/frontends/qt4/GuiView.h | 4 +++ 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/frontends/qt4/GuiApplication.cpp b/src/frontends/qt4/GuiApplication.cpp index f858d85c90..9ddb87c8c5 100644 --- a/src/frontends/qt4/GuiApplication.cpp +++ b/src/frontends/qt4/GuiApplication.cpp @@ -2648,13 +2648,18 @@ void GuiApplication::unregisterSocketCallback(int fd) void GuiApplication::commitData(QSessionManager & sm) { - /// The implementation is required to avoid an application exit - /// when session state save is triggered by session manager. - /// The default implementation sends a close event to all - /// visible top level widgets when session managment allows - /// interaction. - /// We are changing that to close all wiew one by one. - /// FIXME: verify if the default implementation is enough now. + /** The implementation is required to avoid an application exit + ** when session state save is triggered by session manager. + ** The default implementation sends a close event to all + ** visible top level widgets when session managment allows + ** interaction. + ** We are changing that to check the state of each buffer in all + ** views and ask the users what to do if buffers are dirty. + ** Furthermore, we save the session state. + ** We do NOT close the views here since the user still can cancel + ** the logout process (see #9277); also, this would hide LyX from + ** an OSes own session handling (application restoration). + **/ #ifdef QT_NO_SESSIONMANAGER #ifndef _MSC_VER #warning Qt is compiled without session manager @@ -2663,8 +2668,10 @@ void GuiApplication::commitData(QSessionManager & sm) #endif (void) sm; #else - if (sm.allowsInteraction() && !closeAllViews()) + if (sm.allowsInteraction() && !prepareAllViewsForLogout()) sm.cancel(); + else + sm.release(); #endif } @@ -2698,6 +2705,21 @@ bool GuiApplication::closeAllViews() } +bool GuiApplication::prepareAllViewsForLogout() +{ + if (d->views_.empty()) + return true; + + QList const views = d->views_.values(); + foreach (GuiView * view, views) { + if (!view->prepareAllBuffersForLogout()) + return false; + } + + return true; +} + + GuiView & GuiApplication::view(int id) const { LAPPERR(d->views_.contains(id)); diff --git a/src/frontends/qt4/GuiApplication.h b/src/frontends/qt4/GuiApplication.h index a5092f3efa..6bf457e00f 100644 --- a/src/frontends/qt4/GuiApplication.h +++ b/src/frontends/qt4/GuiApplication.h @@ -207,6 +207,9 @@ private: void updateCurrentView(FuncRequest const & cmd, DispatchResult & dr); /// bool closeAllViews(); + /// Things that need to be done when the OSes session manager + /// requests a log out. + bool prepareAllViewsForLogout(); /// read the given ui (menu/toolbar) file bool readUIFile(QString const & name, bool include = false); /// diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp index a85ccb1a89..6ac7471876 100644 --- a/src/frontends/qt4/GuiView.cpp +++ b/src/frontends/qt4/GuiView.cpp @@ -884,6 +884,32 @@ bool GuiView::closeScheduled() } +bool GuiView::prepareAllBuffersForLogout() +{ + Buffer * first = theBufferList().first(); + if (!first) + return true; + + // First, iterate over all buffers and ask the users if unsaved + // changes should be saved. + // We cannot use a for loop as the buffer list cycles. + Buffer * b = first; + do { + if (!saveBufferIfNeeded(const_cast(*b), false)) + return false; + b = theBufferList().next(b); + } while (b != first); + + // Next, save session state + // When a view/window was closed before without quitting LyX, there + // are already entries in the lastOpened list. + theSession().lastOpened().clear(); + writeSession(); + + return true; +} + + /** Destroy only all tabbed WorkAreas. Destruction of other WorkAreas ** is responsibility of the container (e.g., dialog) **/ diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h index d07f59a2b6..f7b488b713 100644 --- a/src/frontends/qt4/GuiView.h +++ b/src/frontends/qt4/GuiView.h @@ -75,6 +75,10 @@ public: /// programmatically and not by the user clicking the x. bool closeScheduled(); + /// Things that need to be done when the OSes session manager + /// requests a log out. + bool prepareAllBuffersForLogout(); + int id() const { return id_; } /// are we busy ? -- 2.39.2