mirror of
https://git.lyx.org/repos/lyx.git
synced 2025-01-11 11:08:41 +00:00
Clean up quit code.
We still need a solution for the Mac. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@16135 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
19df31aa0a
commit
7b2cce9d5d
@ -55,9 +55,9 @@ LyXView & Application::createView(unsigned int width,
|
||||
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);
|
||||
|
@ -168,8 +168,7 @@ public:
|
||||
* 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,
|
||||
|
@ -38,23 +38,26 @@ public:
|
||||
virtual ~Gui() {}
|
||||
|
||||
///
|
||||
virtual int newView() = 0;
|
||||
virtual LyXView& createRegisteredView() = 0;
|
||||
///
|
||||
virtual LyXView & view(int id) = 0;
|
||||
virtual bool unregisterView(int id) = 0;
|
||||
///
|
||||
virtual bool closeAllViews()= 0;
|
||||
|
||||
///
|
||||
virtual LyXView& view(int id) const = 0;
|
||||
///
|
||||
std::vector<int> const & viewIds()
|
||||
{
|
||||
return view_ids_;
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
std::map<int, boost::shared_ptr<BufferView> > buffer_views_;
|
||||
|
||||
std::vector<int> view_ids_;
|
||||
};
|
||||
|
@ -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::updateWindowTitle()
|
||||
|
||||
void LyXView::dispatch(FuncRequest const & cmd)
|
||||
{
|
||||
if (cmd.action == LFUN_WINDOW_CLOSE) {
|
||||
close();
|
||||
closed(id_);
|
||||
return;
|
||||
}
|
||||
|
||||
theLyXFunc().setLyXView(this);
|
||||
lyx::dispatch(cmd);
|
||||
}
|
||||
|
@ -95,6 +95,9 @@ GuiApplication::~GuiApplication()
|
||||
GuiApplication::GuiApplication(int & argc, char ** argv)
|
||||
: QApplication(argc, argv), Application(argc, argv)
|
||||
{
|
||||
// Qt bug? setQuitOnLastWindowClosed(true); does not work
|
||||
setQuitOnLastWindowClosed(false);
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
// doubleClickInterval() is 400 ms on X11 which is just too long.
|
||||
// On Windows and Mac OS X, the operating system's value is used.
|
||||
@ -277,14 +280,8 @@ void GuiApplication::registerSocketCallback(int fd, boost::function<void()> func
|
||||
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);
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ public:
|
||||
virtual void updateColor(LColor_color col);
|
||||
virtual void registerSocketCallback(
|
||||
int fd, boost::function<void()> func);
|
||||
void unregisterSocketCallbackImpl(int fd);
|
||||
void unregisterSocketCallback(int fd);
|
||||
//@}
|
||||
|
||||
///
|
||||
|
@ -24,113 +24,119 @@
|
||||
#include "funcrequest.h"
|
||||
#include "lyxfunc.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
using boost::shared_ptr;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template<class T>
|
||||
void updateIds(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace lyx {
|
||||
namespace frontend {
|
||||
|
||||
|
||||
GuiImplementation::GuiImplementation(): max_view_id_(0), max_wa_id_(0)
|
||||
GuiImplementation::GuiImplementation()
|
||||
{
|
||||
view_ids_.clear();
|
||||
work_area_ids_.clear();
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
LyXView& GuiImplementation::view(int id)
|
||||
{
|
||||
BOOST_ASSERT(views_.find(id) != views_.end());
|
||||
|
||||
updateIds(views_, view_ids_);
|
||||
int id = 0;
|
||||
while (views_.find(id) != views_.end())
|
||||
id++;
|
||||
views_.insert(std::pair<int, GuiView *>(id, new GuiView(id)));
|
||||
updateIds(views_, view_ids_);
|
||||
return *views_[id];
|
||||
}
|
||||
|
||||
|
||||
bool GuiImplementation::closeAll()
|
||||
bool GuiImplementation::unregisterView(int id)
|
||||
{
|
||||
// ATM never used
|
||||
if (!theBufferList().quitWriteAll())
|
||||
return false;
|
||||
updateIds(views_, view_ids_);
|
||||
BOOST_ASSERT(views_.find(id) != views_.end());
|
||||
BOOST_ASSERT(views_[id]);
|
||||
|
||||
// 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 *>::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;
|
||||
}
|
||||
}
|
||||
|
||||
views_.clear();
|
||||
view_ids_.clear();
|
||||
work_areas_.clear();
|
||||
|
||||
updateIds(views_, view_ids_);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GuiImplementation::unregisterView(GuiView * view)
|
||||
bool GuiImplementation::closeAllViews()
|
||||
{
|
||||
std::map<int, GuiView *>::iterator I;
|
||||
|
||||
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;
|
||||
}
|
||||
updateIds(views_, view_ids_);
|
||||
if (views_.empty())
|
||||
{
|
||||
// quit in CloseEvent will not be triggert
|
||||
qApp->quit();
|
||||
return true;
|
||||
}
|
||||
|
||||
buildViewIds();
|
||||
|
||||
if (views_.empty()) {
|
||||
theLyXFunc().setLyXView(0);
|
||||
dispatch(FuncRequest(LFUN_LYX_QUIT));
|
||||
return;
|
||||
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
|
||||
}
|
||||
|
||||
theLyXFunc().setLyXView(views_.begin()->second);
|
||||
views_.clear();
|
||||
work_areas_.clear();
|
||||
view_ids_.clear();
|
||||
work_area_ids_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GuiImplementation::buildViewIds()
|
||||
LyXView& GuiImplementation::view(int id) const
|
||||
{
|
||||
view_ids_.clear();
|
||||
std::map<int, GuiView *>::const_iterator I;
|
||||
for (I = views_.begin(); I != views_.end(); ++I)
|
||||
view_ids_.push_back(I->first);
|
||||
BOOST_ASSERT(views_.find(id) != views_.end());
|
||||
return *views_.find(id)->second;
|
||||
}
|
||||
|
||||
|
||||
std::vector<int> const & GuiImplementation::workAreaIds()
|
||||
{
|
||||
updateIds(work_areas_, work_area_ids_);
|
||||
return 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_;
|
||||
updateIds(views_, view_ids_);
|
||||
int id = 0;
|
||||
while (work_areas_.find(id) != work_areas_.end())
|
||||
id++;
|
||||
|
||||
GuiView * view = views_[view_id];
|
||||
|
||||
work_areas_[id] = new GuiWorkArea(w, h, id, *view);
|
||||
work_areas_.insert(std::pair<int, GuiWorkArea *>
|
||||
(id, new GuiWorkArea(w, h, id, *view)));
|
||||
|
||||
// FIXME BufferView creation should be independant of WorkArea creation
|
||||
buffer_views_[id].reset(new BufferView);
|
||||
@ -147,7 +153,6 @@ int GuiImplementation::newWorkArea(unsigned int w, unsigned int h, int view_id)
|
||||
WorkArea& GuiImplementation::workArea(int id)
|
||||
{
|
||||
BOOST_ASSERT(work_areas_.find(id) != work_areas_.end());
|
||||
|
||||
return *work_areas_[id];
|
||||
}
|
||||
|
||||
|
@ -38,19 +38,17 @@ public:
|
||||
GuiImplementation();
|
||||
virtual ~GuiImplementation() {}
|
||||
|
||||
virtual int newView();
|
||||
virtual LyXView& view(int id);
|
||||
|
||||
virtual LyXView& createRegisteredView();
|
||||
virtual bool closeAllViews();
|
||||
virtual bool unregisterView(int id);
|
||||
|
||||
virtual LyXView& view(int id) const;
|
||||
|
||||
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 +65,14 @@ private:
|
||||
*/
|
||||
std::map<int, GuiWorkArea *> work_areas_;
|
||||
///
|
||||
size_t max_view_id_;
|
||||
///
|
||||
size_t max_wa_id_;
|
||||
|
||||
/// view of a buffer. Eventually there will be several.
|
||||
std::map<int, boost::shared_ptr<BufferView> > buffer_views_;
|
||||
|
||||
|
||||
std::vector<int> const & workAreaIds();
|
||||
|
||||
std::vector<int> work_area_ids_;
|
||||
};
|
||||
|
||||
} // namespace frontend
|
||||
|
@ -155,6 +155,12 @@ unsigned int GuiView::GuiViewPrivate::lastIconSize = 0;
|
||||
GuiView::GuiView(int id)
|
||||
: QMainWindow(), LyXView(id), commandbuffer_(0), d(*new GuiViewPrivate)
|
||||
{
|
||||
// Qt bug? signal lastWindowClosed does not work
|
||||
setAttribute(Qt::WA_QuitOnClose, false);
|
||||
// FIXME: enable to avoid memory leaks but it prduces a crash
|
||||
// after a new window has been close (click into the menu)
|
||||
//setAttribute(Qt::WA_DeleteOnClose, false);
|
||||
|
||||
// hardcode here the platform specific icon size
|
||||
d.smallIconSize = 14; // scaling problems
|
||||
d.normalIconSize = 20; // ok, default
|
||||
@ -210,9 +216,30 @@ void GuiView::init()
|
||||
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();
|
||||
theBufferList().quitWriteAll();
|
||||
close_event->accept();
|
||||
// quit the event loop
|
||||
qApp->quit();
|
||||
}
|
||||
close_event->accept();
|
||||
}
|
||||
|
||||
void GuiView::saveGeometry()
|
||||
{
|
||||
static bool done = false;
|
||||
if (done)
|
||||
return;
|
||||
else
|
||||
done = true;
|
||||
|
||||
// FIXME:
|
||||
// change the ifdef to 'geometry = normalGeometry();' only
|
||||
// when Trolltech has fixed the broken normalGeometry on X11:
|
||||
@ -552,24 +579,6 @@ void GuiView::moveEvent(QMoveEvent *)
|
||||
}
|
||||
|
||||
|
||||
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"));
|
||||
|
@ -177,13 +177,6 @@ frontend::Application * theApp()
|
||||
|
||||
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 @@ int LyX::exec(int & argc, char * argv[])
|
||||
|
||||
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 @@ void LyX::prepareExit()
|
||||
from_utf8(package().temp_dir()));
|
||||
Alert::warning(_("Unable to remove temporary directory"), msg);
|
||||
}
|
||||
|
||||
if (use_gui) {
|
||||
if (pimpl_->session_)
|
||||
pimpl_->session_->writeFile();
|
||||
pimpl_->session_.reset();
|
||||
pimpl_->lyx_server_.reset();
|
||||
pimpl_->lyx_socket_.reset();
|
||||
}
|
||||
|
||||
// Kill the application object before exiting. This avoid crash
|
||||
// on exit on Linux.
|
||||
if (pimpl_->application_)
|
||||
pimpl_->application_.reset();
|
||||
}
|
||||
|
||||
|
||||
@ -455,22 +456,6 @@ void LyX::earlyExit(int status)
|
||||
}
|
||||
|
||||
|
||||
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<FileName> & files)
|
||||
{
|
||||
|
@ -66,13 +66,6 @@ public:
|
||||
/// 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;
|
||||
|
@ -1034,12 +1034,6 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
|
||||
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,11 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
|
||||
LyX::ref().session().lastFilePos().save(FileName(lyx_view_->buffer()->fileName()),
|
||||
boost::tie(view()->cursor().pit(), view()->cursor().pos()) );
|
||||
}
|
||||
|
||||
LyX::ref().quit();
|
||||
|
||||
// save the geometry of the current view
|
||||
lyx_view_->saveGeometry();
|
||||
// quitting is trigged by the gui code (leaving the event loop)
|
||||
theApp()->gui().closeAllViews();
|
||||
break;
|
||||
|
||||
case LFUN_TOC_VIEW: {
|
||||
@ -1670,7 +1667,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
|
||||
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: {
|
||||
|
Loading…
Reference in New Issue
Block a user