Hello,
This patch sanitize the different way to exit from lyx:
1) exit request with a direct call to LFUN_WINDOW_CLOSE: user menu.
2) automatic exit when the last window is closed.
I needed some more small changes to the LFUN in order to make this work
properly for all tested use cases.
Bo, concerning session stuff, I had to change things a bit again. So
now, the geometry saving is ensured to be done because LyXView::close()
is _always_ called on exit.
I am all ears WRT comments to the code and bug reports. But I can't work
on this in the short term so I am going going to commit this now as this
a clear improvement over the current situation.
Abdel.
Index: src/frontends/Gui.h
===================================================================
--- src/frontends/Gui.h (revision 15520)
+++ src/frontends/Gui.h (working copy)
@@ -46,6 +46,8 @@
virtual int newWorkArea(unsigned int width, unsigned int height, int
view_id) = 0;
///
virtual WorkArea & workArea(int id) = 0;
+ ///
+ virtual bool closeAll() = 0;
///
std::vector<int> const & viewIds() { return view_ids_; };
Index: src/frontends/qt4/Alert_pimpl.C
===================================================================
--- src/frontends/qt4/Alert_pimpl.C (revision 15520)
+++ src/frontends/qt4/Alert_pimpl.C (working copy)
@@ -28,24 +28,39 @@
#include <algorithm>
+using std::pair;
+using std::make_pair;
namespace lyx {
using lyx::support::bformat;
using lyx::docstring;
-using std::pair;
-using std::make_pair;
+namespace {
+class MessageBox: public QMessageBox
+{
+public:
+ MessageBox(QWidget * parent = 0): QMessageBox(parent)
+ {
+ setAttribute(Qt::WA_DeleteOnClose, true);
+ setAttribute(Qt::WA_QuitOnClose, false);
+ }
+};
+} // anonymous namespace
+
+
int prompt_pimpl(docstring const & tit, docstring const & question,
int default_button, int cancel_button,
docstring const & b1, docstring const & b2, docstring const &
b3)
{
docstring const title = bformat(_("LyX: %1$s"), tit);
+ MessageBox mb;
+
// FIXME replace that with theApp->gui()->currentView()
- int res = QMessageBox::information(qApp->focusWidget(),
+ int res = mb.information(qApp->focusWidget(),
toqstr(title),
toqstr(formatted(question)),
toqstr(b1),
@@ -63,7 +78,9 @@
void warning_pimpl(docstring const & tit, docstring const & message)
{
docstring const title = bformat(_("LyX: %1$s"), tit);
- QMessageBox::warning(qApp->focusWidget(),
+
+ MessageBox mb;
+ mb.warning(qApp->focusWidget(),
toqstr(title),
toqstr(formatted(message)));
}
@@ -72,7 +89,8 @@
void error_pimpl(docstring const & tit, docstring const & message)
{
docstring const title = bformat(_("LyX: %1$s"), tit);
- QMessageBox::critical(qApp->focusWidget(),
+ MessageBox mb;
+ mb.critical(qApp->focusWidget(),
toqstr(title),
toqstr(formatted(message)));
}
@@ -81,7 +99,8 @@
void information_pimpl(docstring const & tit, docstring const & message)
{
docstring const title = bformat(_("LyX: %1$s"), tit);
- QMessageBox::information(qApp->focusWidget(),
+ MessageBox mb;
+ mb.information(qApp->focusWidget(),
toqstr(title),
toqstr(formatted(message)));
}
Index: src/frontends/qt4/GuiApplication.C
===================================================================
--- src/frontends/qt4/GuiApplication.C (revision 15520)
+++ src/frontends/qt4/GuiApplication.C (working copy)
@@ -165,7 +165,7 @@
// trigger LFUN_LYX_QUIT instead of QApplication::quit() directly
// since LFUN_LYX_QUIT may have more cleanup stuff
- dispatch(FuncRequest(LFUN_LYX_QUIT));
+ dispatch(FuncRequest(LFUN_LYX_QUIT, "force"));
}
Index: src/frontends/qt4/GuiImplementation.C
===================================================================
--- src/frontends/qt4/GuiImplementation.C (revision 15520)
+++ src/frontends/qt4/GuiImplementation.C (working copy)
@@ -20,6 +20,7 @@
#include "GuiWorkArea.h"
#include "BufferView.h"
+#include "bufferlist.h"
#include "funcrequest.h"
#include "lyxfunc.h"
@@ -42,9 +43,6 @@
views_[id] = new GuiView(id);
view_ids_.push_back(id);
- QObject::connect(views_[id], SIGNAL(destroyed(QObject *)),
- this, SLOT(cleanupViews(QObject *)));
-
return id;
}
@@ -57,9 +55,39 @@
}
-void GuiImplementation::cleanupViews(QObject * qobj)
+bool GuiImplementation::closeAll()
{
- GuiView * view = static_cast<GuiView *>(qobj);
+ if (!theBufferList().quitWriteAll())
+ return false;
+
+ // In order to know if it is the last opened window,
+ // GuiView::closeEvent() check for (view_ids_.size() == 1)
+ // We deny this check by setting the vector size to zero.
+ // But we still need the vector, hence the temporary copy.
+ std::vector<int> view_ids_tmp = view_ids_;
+ view_ids_.clear();
+
+ for (size_t i = 0; i < view_ids_tmp.size(); ++i) {
+ // LFUN_LYX_QUIT has already been triggered so we need
+ // to disable the lastWindowClosed() signal before closing
+ // the last window.
+ views_[view_ids_tmp[i]]->setAttribute(Qt::WA_QuitOnClose,
false);
+ views_[view_ids_tmp[i]]->close();
+ // The view_ids_ vector is reconstructed in the closeEvent; so
+ // let's clear that out again!
+ view_ids_.clear();
+ }
+
+ views_.clear();
+ view_ids_.clear();
+ work_areas_.clear();
+
+ return true;
+}
+
+
+void GuiImplementation::unregisterView(GuiView * view)
+{
std::map<int, GuiView *>::iterator I;
for (I = views_.begin(); I != views_.end(); ++I) {
@@ -76,6 +104,7 @@
// dispatch(FuncRequest(LFUN_LYX_QUIT));
return;
}
+
theLyXFunc().setLyXView(views_.begin()->second);
}
Index: src/frontends/qt4/GuiImplementation.h
===================================================================
--- src/frontends/qt4/GuiImplementation.h (revision 15520)
+++ src/frontends/qt4/GuiImplementation.h (working copy)
@@ -38,14 +38,15 @@
GuiImplementation();
virtual ~GuiImplementation() {}
- int newView();
- LyXView& view(int id);
- int newWorkArea(unsigned int width, unsigned int height, int view_id);
- WorkArea& workArea(int id);
+ virtual int newView();
+ virtual LyXView& view(int id);
+ virtual int newWorkArea(unsigned int width, unsigned int height, int
view_id);
+ virtual WorkArea& workArea(int id);
+ virtual bool closeAll();
-private Q_SLOTS:
+public Q_SLOTS:
///
- void cleanupViews(QObject * view);
+ void unregisterView(GuiView * view);
private:
///
Index: src/frontends/qt4/GuiView.C
===================================================================
--- src/frontends/qt4/GuiView.C (revision 15520)
+++ src/frontends/qt4/GuiView.C (working copy)
@@ -12,33 +12,33 @@
#include <config.h>
+#include "GuiImplementation.h"
+
+#include "GuiView.h"
+#include "QLMenubar.h"
+#include "QLToolbar.h"
+#include "QCommandBuffer.h"
+#include "qt_helpers.h"
+
+#include "frontends/Application.h"
+#include "frontends/Gui.h"
+#include "frontends/WorkArea.h"
+
+#include "support/filetools.h"
+#include "support/convert.h"
+#include "support/lstrings.h"
+
#include "BufferView.h"
+#include "bufferlist.h"
+#include "debug.h"
+#include "funcrequest.h"
#include "lyx_cb.h"
#include "lyxrc.h"
#include "lyx_main.h"
#include "session.h"
#include "lyxfunc.h"
#include "MenuBackend.h"
-#include "funcrequest.h"
-#include "funcrequest.h"
-#include "debug.h"
-
-#include "frontends/WorkArea.h"
-#include "support/filetools.h"
-#include "support/convert.h"
-#include "support/lstrings.h"
-
-// This include must be declared before everything else because
-// of boost/Qt/LyX clash...
-#include "GuiImplementation.h"
-
-#include "GuiView.h"
-#include "QLMenubar.h"
-#include "QLToolbar.h"
-#include "QCommandBuffer.h"
-#include "qt_helpers.h"
-
#include <QAction>
#include <QApplication>
#include <QCloseEvent>
@@ -46,12 +46,11 @@
#include <QStatusBar>
#include <QToolBar>
-
#include <boost/bind.hpp>
-
+using std::endl;
using std::string;
-using std::endl;
+using std::vector;
namespace lyx {
@@ -264,9 +263,20 @@
}
-void GuiView::closeEvent(QCloseEvent *)
+void GuiView::closeEvent(QCloseEvent * close_event)
{
+ GuiImplementation & gui
+ = static_cast<GuiImplementation &>(theApp->gui());
+
+ vector<int> const & view_ids = gui.viewIds();
+
+ if (view_ids.size() == 1 && !theBufferList().quitWriteAll()) {
+ close_event->ignore();
+ return;
+ }
+
saveGeometry();
+ gui.unregisterView(this);
}
Index: src/frontends/qt4/GuiView.h
===================================================================
--- src/frontends/qt4/GuiView.h (revision 15520)
+++ src/frontends/qt4/GuiView.h (working copy)
@@ -42,6 +42,10 @@
* GuiView - Qt4 implementation of LyXView
*
* qt4-private implementation of the main LyX window.
+ *
+ * Note: any QObject emits a destroyed(QObject *) Qt signal when it
+ * is deleted.This might be useful for closing other dialogs
+ * depending on a given GuiView.
*/
class GuiView : public QMainWindow, public LyXView {
Q_OBJECT
Index: src/lyx_main.C
===================================================================
--- src/lyx_main.C (revision 15520)
+++ src/lyx_main.C (working copy)
@@ -397,23 +397,10 @@
{
lyxerr[Debug::INFO] << "Running QuitLyX." << endl;
- if (use_gui) {
- if (!noask && !pimpl_->buffer_list_.quitWriteAll())
- return;
-
- // The LyXView Geometry settings are stored when LyXView::close
- // is called explicitely but a straight quit() command would not
- // guarante that. So we make sure this is done here:
- vector<int> const & view_ids =
pimpl_->application_->gui().viewIds();
- for (size_t i = 0; i < view_ids.size(); ++i)
-
pimpl_->application_->gui().view(view_ids[i]).saveGeometry();
-
- pimpl_->session_->writeFile();
- }
-
prepareExit();
if (use_gui) {
+ pimpl_->session_->writeFile();
pimpl_->lyx_server_.reset();
pimpl_->lyx_socket_.reset();
pimpl_->application_->exit(0);
Index: src/lyxfunc.C
===================================================================
--- src/lyxfunc.C (revision 15520)
+++ src/lyxfunc.C (working copy)
@@ -1022,13 +1022,23 @@
break;
case LFUN_LYX_QUIT:
+ if (argument != "force") {
+ if (!theApp->gui().closeAll())
+ break;
+ lyx_view_ = 0;
+ }
+
+ // FIXME: this code needs to be transfered somewhere
else
+ // as lyx_view_ will most certainly be null and a same
buffer
+ // might be visible in more than one LyXView.
if (lyx_view_ && lyx_view_->view()->buffer()) {
// save cursor Position for opened files to
.lyx/session
LyX::ref().session().saveFilePosition(lyx_view_->buffer()->fileName(),
boost::tie(view()->cursor().pit(),
view()->cursor().pos()) );
// save bookmarks to .lyx/session
view()->saveSavedPositions();
- }
+ }
+
LyX::ref().quit(argument == "force");
break;