Here a patch which cleans up the quitting code.
All leaving the event loop no starts here:
+void GuiView::closeEvent(QCloseEvent * close_event)
+{
+ theApp()->gui().unregisterView(id());
+ if (theApp()->gui().viewIds().empty())
+ {
+ // this is the place were we leave the frontend
+ // and is the only point were we begin to quit
+ saveGeometry();
+ close_event->accept();
+ // quit the event loop
+ qApp->quit();
+ }
+}
I've tested it on Windows and Linux, and hope it also works for
the Mac.
Saving now also works for 'Exit'.
We only come back to lyx_main.C by leaving the event loop, so
no 'quit()' is required any more.
Please test or comment it.
Peter
Index: src/lyxfunc.C
===================================================================
--- src/lyxfunc.C (Revision 16123)
+++ src/lyxfunc.C (Arbeitskopie)
@@ -1034,12 +1034,6 @@
break;
case LFUN_LYX_QUIT:
- if (argument == "closeOnly") {
- 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.
@@ -1048,8 +1042,9 @@
LyX::ref().session().lastFilePos().save(lyx_view_->buffer()->fileName(),
boost::tie(view()->cursor().pit(),
view()->cursor().pos()) );
}
-
- LyX::ref().quit();
+
+ // quitting is trigged by the gui code (leaving the
event loop)
+ theApp()->gui().closeAllRegisteredViews();
break;
case LFUN_TOC_VIEW: {
@@ -1670,7 +1665,7 @@
BOOST_ASSERT(lyx_view_);
BOOST_ASSERT(theApp());
lyx_view_->close();
- // We return here because lyx_view does not exists
anymore.
+ lyx_view_->closed(lyx_view_->id());
return;
case LFUN_BOOKMARK_GOTO: {
Index: src/frontends/Application.h
===================================================================
--- src/frontends/Application.h (Revision 16123)
+++ src/frontends/Application.h (Arbeitskopie)
@@ -168,8 +168,7 @@
* remove a I/O read callback
* @param fd socket descriptor (file/socket/etc)
*/
- template<class T>
- void unregisterSocketCallback(T fd);
+ virtual void unregisterSocketCallback(int fd) = 0;
/// Create the main window with given geometry settings.
LyXView & createView(unsigned int width, unsigned int height,
Index: src/frontends/qt4/GuiImplementation.C
===================================================================
--- src/frontends/qt4/GuiImplementation.C (Revision 16123)
+++ src/frontends/qt4/GuiImplementation.C (Arbeitskopie)
@@ -30,103 +30,91 @@
namespace frontend {
-GuiImplementation::GuiImplementation(): max_view_id_(0), max_wa_id_(0)
+GuiImplementation::GuiImplementation()
{
}
-int GuiImplementation::newView()
+LyXView& GuiImplementation::createRegisteredView()
{
- size_t const id = max_view_id_;
- ++max_view_id_;
-
- views_[id] = new GuiView(id);
- view_ids_.push_back(id);
-
- return id;
+ size_t const id = viewIds().size();
+ views_.insert(std::pair<int, GuiView *>(id, new GuiView(id)));
+ return *views_[id];
}
-LyXView& GuiImplementation::view(int id)
+bool GuiImplementation::unregisterView(int id)
{
- BOOST_ASSERT(views_.find(id) != views_.end());
+ if (id < 0 && id >= viewIds().size())
+ return false;
+ if (!views_[id])
+ return false;
- return *views_[id];
+ std::map<int, GuiView *>::iterator it;
+ for (it = views_.begin(); it != views_.end(); ++it) {
+ if (it->first == id) {
+ std::vector<int> const & wa_ids =
it->second->workAreaIds();
+ for (size_t i = 0; i < wa_ids.size(); ++i)
+ work_areas_.erase(wa_ids[i]);
+ views_.erase(id);
+ break;
+ }
+ }
+ return true;
}
-bool GuiImplementation::closeAll()
+bool GuiImplementation::closeAllRegisteredViews()
{
- // ATM never used
- if (!theBufferList().quitWriteAll())
- return false;
+ if (views_.empty())
+ return true;
- // 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();
+ std::map<int, GuiView*> const cmap = views_;
+ std::map<int, GuiView*>::const_iterator it;
+ for (it = cmap.begin(); it != cmap.end(); ++it)
+ {
+ it->second->close();
+ // unregisterd by the CloseEvent
}
-
views_.clear();
- view_ids_.clear();
work_areas_.clear();
-
return true;
}
-
-void GuiImplementation::unregisterView(GuiView * view)
+LyXView& GuiImplementation::view(int id) const
{
- std::map<int, GuiView *>::iterator I;
+ BOOST_ASSERT(views_.find(id) != views_.end());
+ return *views_.find(id)->second;
+}
- for (I = views_.begin(); I != views_.end(); ++I) {
- if (I->second == view) {
- std::vector<int> const & wa_ids = view->workAreaIds();
- for (size_t i = 0; i < wa_ids.size(); ++i)
- work_areas_.erase(wa_ids[i]);
- views_.erase(I->first);
- break;
- }
- }
+template<class T>
+ std::vector<int> const & GuiImplementation_Ids
+ (std::map<int, T*> const & stdmap, std::vector<int> & ids)
+{
+ ids.clear();
+ typename std::map<int, T*>::const_iterator it;
+ for (it = stdmap.begin(); it != stdmap.end(); ++it)
+ ids.push_back(it->first);
+ return ids;
+}
- buildViewIds();
- if (views_.empty()) {
- theLyXFunc().setLyXView(0);
- dispatch(FuncRequest(LFUN_LYX_QUIT));
- return;
- }
-
- theLyXFunc().setLyXView(views_.begin()->second);
+std::vector<int> const & GuiImplementation::viewIds()
+{
+ return GuiImplementation_Ids(views_, view_ids_);
}
-void GuiImplementation::buildViewIds()
+std::vector<int> const & GuiImplementation::workAreaIds()
{
- view_ids_.clear();
- std::map<int, GuiView *>::const_iterator I;
- for (I = views_.begin(); I != views_.end(); ++I)
- view_ids_.push_back(I->first);
+ return GuiImplementation_Ids(work_areas_, work_area_ids_);
}
int GuiImplementation::newWorkArea(unsigned int w, unsigned int h, int view_id)
{
- size_t const id = max_wa_id_;
- ++max_wa_id_;
+ size_t const id = workAreaIds().size();
GuiView * view = views_[view_id];
@@ -147,7 +135,6 @@
WorkArea& GuiImplementation::workArea(int id)
{
BOOST_ASSERT(work_areas_.find(id) != work_areas_.end());
-
return *work_areas_[id];
}
Index: src/frontends/qt4/GuiImplementation.h
===================================================================
--- src/frontends/qt4/GuiImplementation.h (Revision 16123)
+++ src/frontends/qt4/GuiImplementation.h (Arbeitskopie)
@@ -38,19 +38,18 @@
GuiImplementation();
virtual ~GuiImplementation() {}
- virtual int newView();
- virtual LyXView& view(int id);
+
+ virtual LyXView& createRegisteredView();
+ virtual bool closeAllRegisteredViews();
+ virtual bool unregisterView(int id);
+
+ virtual LyXView& view(int id) const;
+ virtual std::vector<int> const & viewIds();
+
virtual int newWorkArea(unsigned int width, unsigned int height, int
view_id);
virtual WorkArea& workArea(int id);
- virtual bool closeAll();
-public Q_SLOTS:
- ///
- void unregisterView(GuiView * view);
-
private:
- ///
- void buildViewIds();
/// Multiple views container.
/**
@@ -67,9 +66,9 @@
*/
std::map<int, GuiWorkArea *> work_areas_;
///
- size_t max_view_id_;
- ///
- size_t max_wa_id_;
+ std::vector<int> const & workAreaIds();
+
+ std::vector<int> work_area_ids_;
};
} // namespace frontend
Index: src/frontends/qt4/GuiApplication.C
===================================================================
--- src/frontends/qt4/GuiApplication.C (Revision 16123)
+++ src/frontends/qt4/GuiApplication.C (Arbeitskopie)
@@ -277,14 +277,8 @@
boost::shared_ptr<socket_callback>(new socket_callback(fd,
func));
}
-template<>
-void Application::unregisterSocketCallback<int>(int fd)
-{
- GuiApplication* ptr = static_cast<GuiApplication*>(this);
- ptr->unregisterSocketCallbackImpl(fd);
-}
-void GuiApplication::unregisterSocketCallbackImpl(int fd)
+void GuiApplication::unregisterSocketCallback(int fd)
{
socket_callbacks_.erase(fd);
}
Index: src/frontends/qt4/GuiApplication.h
===================================================================
--- src/frontends/qt4/GuiApplication.h (Revision 16123)
+++ src/frontends/qt4/GuiApplication.h (Arbeitskopie)
@@ -75,7 +75,7 @@
virtual void updateColor(LColor_color col);
virtual void registerSocketCallback(
int fd, boost::function<void()> func);
- void unregisterSocketCallbackImpl(int fd);
+ void unregisterSocketCallback(int fd);
//@}
///
Index: src/frontends/qt4/GuiView.C
===================================================================
--- src/frontends/qt4/GuiView.C (Revision 16123)
+++ src/frontends/qt4/GuiView.C (Arbeitskopie)
@@ -155,6 +155,9 @@
GuiView::GuiView(int id)
: QMainWindow(), LyXView(id), commandbuffer_(0), d(*new GuiViewPrivate)
{
+ setAttribute(Qt::WA_QuitOnClose, false);
+ //setAttribute(Qt::WA_DeleteOnClose, false);
+
// hardcode here the platform specific icon size
d.smallIconSize = 14; // scaling problems
d.normalIconSize = 20; // ok, default
@@ -210,6 +213,19 @@
updateMenubar();
}
+void GuiView::closeEvent(QCloseEvent * close_event)
+{
+ theApp()->gui().unregisterView(id());
+ if (theApp()->gui().viewIds().empty())
+ {
+ // this is the place were we leave the frontend
+ // and is the only point were we begin to quit
+ saveGeometry();
+ close_event->accept();
+ // quit the event loop
+ qApp->quit();
+ }
+}
void GuiView::saveGeometry()
{
@@ -552,24 +568,6 @@
}
-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();
- hide(); // don't remove this hide, it prevents a crash on exit
- gui.unregisterView(this);
-}
-
-
void GuiView::show()
{
QMainWindow::setWindowTitle(qt_("LyX"));
Index: src/frontends/Gui.h
===================================================================
--- src/frontends/Gui.h (Revision 16123)
+++ src/frontends/Gui.h (Arbeitskopie)
@@ -38,19 +38,22 @@
virtual ~Gui() {}
///
- virtual int newView() = 0;
+ virtual LyXView& createRegisteredView() = 0;
///
- virtual LyXView & view(int id) = 0;
+ virtual bool closeAllRegisteredViews()= 0;
+ ///
+ virtual bool unregisterView(int id) = 0;
///
+ virtual LyXView& view(int id) const = 0;
+ ///
+ virtual std::vector<int> const & viewIds() = 0;
+
+
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_; };
protected:
/// view of a buffer. Eventually there will be several.
Index: src/frontends/Application.C
===================================================================
--- src/frontends/Application.C (Revision 16123)
+++ src/frontends/Application.C (Arbeitskopie)
@@ -55,9 +55,9 @@
unsigned int
iconSizeXY,
const
std::string & geometryArg)
{
- int view_id = gui().newView();
- LyXView & view = gui().view(view_id);
-
+ LyXView & view = gui().createRegisteredView();
+ int view_id = view.id();
+
theLyXFunc().setLyXView(&view);
/*int workArea_id_ =*/ gui().newWorkArea(width, height, view_id);
Index: src/frontends/LyXView.C
===================================================================
--- src/frontends/LyXView.C (Revision 16123)
+++ src/frontends/LyXView.C (Arbeitskopie)
@@ -17,6 +17,7 @@
#include "Toolbars.h"
#include "Menubar.h"
#include "WorkArea.h"
+#include "Gui.h"
#include "buffer.h"
#include "bufferparams.h"
@@ -398,12 +399,6 @@
void LyXView::dispatch(FuncRequest const & cmd)
{
- if (cmd.action == LFUN_WINDOW_CLOSE) {
- close();
- closed(id_);
- return;
- }
-
theLyXFunc().setLyXView(this);
lyx::dispatch(cmd);
}
Index: src/lyx_main.C
===================================================================
--- src/lyx_main.C (Revision 16123)
+++ src/lyx_main.C (Arbeitskopie)
@@ -177,13 +177,6 @@
LyX::~LyX()
{
- // Static data are not treated in the same way at all on the Mac (and
- // the LyX singleton has static methods). This is the reason why the
- // exit command on the Mac bypasses our dispatch machinery altogether.
- // On Linux and Windows we won't pass a second time through quit()
- // because quitting will already be set to true.
- if (!quitting)
- quit();
}
@@ -402,12 +395,7 @@
exit_status = pimpl_->application_->exec();
- // FIXME: Do we still need this reset?
- // I assume it is the reason for strange Mac crashs
- // Test by reverting rev 16110 (Peter)
- // Kill the application object before exiting. This avoid crash
- // on exit on Linux.
- pimpl_->application_.reset();
+ prepareExit();
// Restore original font resources after Application is destroyed.
support::restoreFontResources();
@@ -442,6 +430,19 @@
from_utf8(package().temp_dir()));
Alert::warning(_("Unable to remove temporary directory"), msg);
}
+
+ // Kill the application object before exiting. This avoid crash
+ // on exit on Linux.
+ if (pimpl_->application_)
+ pimpl_->application_.reset();
+
+ if (use_gui) {
+ if (pimpl_->session_)
+ pimpl_->session_->writeFile();
+ pimpl_->session_.reset();
+ pimpl_->lyx_server_.reset();
+ pimpl_->lyx_socket_.reset();
+ }
}
@@ -455,22 +456,6 @@
}
-void LyX::quit()
-{
- lyxerr[Debug::INFO] << "Running QuitLyX." << endl;
-
- prepareExit();
- if (use_gui) {
- if (pimpl_->session_)
- pimpl_->session_->writeFile();
- pimpl_->lyx_server_.reset();
- pimpl_->lyx_socket_.reset();
- if (pimpl_->application_)
- pimpl_->application_->exit(0);
- }
-}
-
-
int LyX::loadFiles(int & argc, char * argv[],
vector<string> & files)
{
Index: src/lyx_main.h
===================================================================
--- src/lyx_main.h (Revision 16123)
+++ src/lyx_main.h (Arbeitskopie)
@@ -64,13 +64,6 @@
/// in the case of failure
void emergencyCleanup() const;
- /// Ask the LyX class to exit.
- /**
- In GUI mode, after this function has been called, application_ leaves
- the main event loop and returns from the call to Application::start().
- */
- void quit();
-
///
BufferList & bufferList();
BufferList const & bufferList() const;