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.
This commit is contained in:
Juergen Spitzmueller 2015-04-06 13:50:32 +02:00
parent c46162db23
commit 7970b84049
4 changed files with 63 additions and 8 deletions

View File

@ -2648,13 +2648,18 @@ void GuiApplication::unregisterSocketCallback(int fd)
void GuiApplication::commitData(QSessionManager & sm) void GuiApplication::commitData(QSessionManager & sm)
{ {
/// The implementation is required to avoid an application exit /** The implementation is required to avoid an application exit
/// when session state save is triggered by session manager. ** when session state save is triggered by session manager.
/// The default implementation sends a close event to all ** The default implementation sends a close event to all
/// visible top level widgets when session managment allows ** visible top level widgets when session managment allows
/// interaction. ** interaction.
/// We are changing that to close all wiew one by one. ** We are changing that to check the state of each buffer in all
/// FIXME: verify if the default implementation is enough now. ** 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 #ifdef QT_NO_SESSIONMANAGER
#ifndef _MSC_VER #ifndef _MSC_VER
#warning Qt is compiled without session manager #warning Qt is compiled without session manager
@ -2663,8 +2668,10 @@ void GuiApplication::commitData(QSessionManager & sm)
#endif #endif
(void) sm; (void) sm;
#else #else
if (sm.allowsInteraction() && !closeAllViews()) if (sm.allowsInteraction() && !prepareAllViewsForLogout())
sm.cancel(); sm.cancel();
else
sm.release();
#endif #endif
} }
@ -2698,6 +2705,21 @@ bool GuiApplication::closeAllViews()
} }
bool GuiApplication::prepareAllViewsForLogout()
{
if (d->views_.empty())
return true;
QList<GuiView *> const views = d->views_.values();
foreach (GuiView * view, views) {
if (!view->prepareAllBuffersForLogout())
return false;
}
return true;
}
GuiView & GuiApplication::view(int id) const GuiView & GuiApplication::view(int id) const
{ {
LAPPERR(d->views_.contains(id)); LAPPERR(d->views_.contains(id));

View File

@ -207,6 +207,9 @@ private:
void updateCurrentView(FuncRequest const & cmd, DispatchResult & dr); void updateCurrentView(FuncRequest const & cmd, DispatchResult & dr);
/// ///
bool closeAllViews(); 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 /// read the given ui (menu/toolbar) file
bool readUIFile(QString const & name, bool include = false); bool readUIFile(QString const & name, bool include = false);
/// ///

View File

@ -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<Buffer &>(*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 /** Destroy only all tabbed WorkAreas. Destruction of other WorkAreas
** is responsibility of the container (e.g., dialog) ** is responsibility of the container (e.g., dialog)
**/ **/

View File

@ -75,6 +75,10 @@ public:
/// programmatically and not by the user clicking the x. /// programmatically and not by the user clicking the x.
bool closeScheduled(); bool closeScheduled();
/// Things that need to be done when the OSes session manager
/// requests a log out.
bool prepareAllBuffersForLogout();
int id() const { return id_; } int id() const { return id_; }
/// are we busy ? /// are we busy ?