Peter Kümmel wrote:
In the last patch is a bug for Mac.
Here the corrected.


------------------------------------------------------------------------

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();

What's the difference between this and closeAll()? Can a view be unregistered?

                        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());

I am not sure this signal is caught anywhere. I created it at some point but I did not make use of it at the end. You should maybe check whether it is used or not.

                        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;

Yes, that's definitely better than the template based solution.

/// 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()

I'd rather keep the max_view_id_ vector as this is used quite often in LyX::updateInset(). But this LyX::updateInset() is not good at all so we'd better clean this up at the same time.


-int GuiImplementation::newView()
+LyXView& GuiImplementation::createRegisteredView()

Same question: can a View be unregistered? If not, then newView() is more explicit IMHO.

 {
-       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

This is a bad name :-). It is just a helper function that uses nothing to do with GuiImplementation so just call it extractIds() and put that in the anon namespace.

+ (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();
+       }
+}

I think this could be a good solution but the problem here is that I think there is a bug in QtMac. This is a theory that could well explain Bennett's report about non-saved files on exit:

qApp->exit() seems to always results in killing the application. It seems that the LyX destructor is always called the moment just after that. The execution process in LyX::exec() is thus not properly done and prepareExit() is not called here:

> @@ -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();



Abdel.

Reply via email to