]> git.lyx.org Git - features.git/commitdiff
Clean up quit code.
authorPeter Kümmel <syntheticpp@gmx.net>
Sat, 2 Dec 2006 17:39:31 +0000 (17:39 +0000)
committerPeter Kümmel <syntheticpp@gmx.net>
Sat, 2 Dec 2006 17:39:31 +0000 (17:39 +0000)
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

12 files changed:
src/frontends/Application.C
src/frontends/Application.h
src/frontends/Gui.h
src/frontends/LyXView.C
src/frontends/qt4/GuiApplication.C
src/frontends/qt4/GuiApplication.h
src/frontends/qt4/GuiImplementation.C
src/frontends/qt4/GuiImplementation.h
src/frontends/qt4/GuiView.C
src/lyx_main.C
src/lyx_main.h
src/lyxfunc.C

index e7f64e339e5cea9aaad3662e015d0a4cf938a969..0f3fa8c2d8cac19db706d860f790c20c586e0e7f 100644 (file)
@@ -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);
index 03cdf36c6a43de9d3903de3231a0bfbd886ec9cf..748f1cf7b7a3adb2a3193ad652b7c3ff12e678a2 100644 (file)
@@ -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,
index 442508f7ea0388bc033ec114d90cf35ef7da07fd..0d7ec628abbc17b31550771d9c722dc3ed978e36 100644 (file)
@@ -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 int newWorkArea(unsigned int width, unsigned int height, int view_id) = 0;
+       virtual bool closeAllViews()= 0;
+
        ///
-       virtual WorkArea & workArea(int id) = 0;
+       virtual LyXView& view(int id) const = 0;
        ///
-       virtual bool closeAll() = 0;
+       std::vector<int> const & viewIds() 
+       { 
+               return view_ids_; 
+       }
 
+
+       virtual int newWorkArea(unsigned int width, unsigned int height, int view_id) = 0;
        ///
-       std::vector<int> const & viewIds() { return view_ids_; };
+       virtual WorkArea & workArea(int id) = 0;
 
 protected:
-       /// view of a buffer. Eventually there will be several.
-       std::map<int, boost::shared_ptr<BufferView> > buffer_views_;
 
        std::vector<int> view_ids_;
 };
index 4fd5da524ed359d1a080af0bc4c1a0d6283989be..fee535079d7d5328a21d6532f56c83ccfb9d4326 100644 (file)
@@ -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);
 }
index e41fa106ad5f20f68bcd8da46e06a3832ed68bb1..99b5a78794ce51b2b7b4baf7ac0591d91561c239 100644 (file)
@@ -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);
 }
index ed0fe31b422a7fe980b0f5e7a2769aafedb95052..af495688f01579ce3ada9f9499537d1c98220af8 100644 (file)
@@ -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);
        //@}
 
        ///
index a4ea5833b0925cafcdac45be0df45b2c871b648e..1400fd6e978344b005c3f6049ce0accdbbbde011 100644 (file)
 #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;
+       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];
 }
 
 
-LyXView& GuiImplementation::view(int id)
+bool GuiImplementation::unregisterView(int id)
 {
+       updateIds(views_, view_ids_);
        BOOST_ASSERT(views_.find(id) != views_.end());
+       BOOST_ASSERT(views_[id]);
 
-       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;
+               }
+       }
+       updateIds(views_, view_ids_);
+       return true;
 }
 
 
-bool GuiImplementation::closeAll()
+bool GuiImplementation::closeAllViews()
 {
-       // ATM never used
-       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();
+       updateIds(views_, view_ids_);
+       if (views_.empty())
+       {
+               // quit in CloseEvent will not be triggert
+               qApp->quit();
+               return true;
+       }
 
-       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();
-
+       view_ids_.clear();
+       work_area_ids_.clear();
        return true;
 }
 
 
-void GuiImplementation::unregisterView(GuiView * view)
+LyXView& GuiImplementation::view(int id) const
 {
-       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;
-               }
-       }
-
-       buildViewIds();
-
-       if (views_.empty()) {
-               theLyXFunc().setLyXView(0);
-               dispatch(FuncRequest(LFUN_LYX_QUIT));
-               return;
-       }
-
-       theLyXFunc().setLyXView(views_.begin()->second);
+       BOOST_ASSERT(views_.find(id) != views_.end());
+       return *views_.find(id)->second;
 }
 
 
-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);
+       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];
 }
 
index 221391988c0a163f56c5adb28924276c514df4ad..697bbd6d4d5f3cecf86a29a5911b3c99f56c2874 100644 (file)
@@ -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
index bf8d7002304502ce837371d5ef605a144ecc38cf..df06173e36208cda674ac3607f2a6799073c144c 100644 (file)
@@ -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"));
index 23692a194f8466c217746cef8b46dee6b68199be..a029f52e4162998e0b88feb265c52b5ff6d77cb1 100644 (file)
@@ -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)
 {
index bdbef3b30251f2e70ad0cfb687165542d0abfb28..c79a2c08f7ef295c8118ee091815e2b191f2b79f 100644 (file)
@@ -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;
index e8c7676382c33a09ec6fa2eda405503902092552..5a5e955dd9e375e5fda1b31d8cfccf0aee3611be 100644 (file)
@@ -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: {