]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiView.cpp
If we are in a closeEvent, we don't want to close all buffers, because these may...
[lyx.git] / src / frontends / qt4 / GuiView.cpp
index 3bbc8c6e4b30f0926e696b24be501286a88f57fa..8986f7dfbccd4b8a6e958403977c6c5f64c30ec8 100644 (file)
@@ -547,7 +547,7 @@ void GuiView::closeEvent(QCloseEvent * close_event)
        // it can happen that this event arrives without selecting the view,
        // e.g. when clicking the close button on a background window.
        setFocus();
-       if (!closeBufferAll(true)) {
+       if (!closeWorkAreaAll(true)) {
                closing_ = false;
                close_event->ignore();
                return;
@@ -584,67 +584,6 @@ void GuiView::closeEvent(QCloseEvent * close_event)
 }
 
 
-bool GuiView::closeBufferAll(bool tolastopened)
-{
-       GuiWorkArea * active_wa = currentMainWorkArea();
-       setCurrentWorkArea(active_wa);
-
-       // We might be in a situation that there is still a tabWorkArea, but
-       // there are no tabs anymore. This can happen when we get here after a 
-       // TabWorkArea::lastWorkAreaRemoved() signal. Therefore we count how
-       // many TabWorkArea's have no documents anymore.
-       int empty_twa = 0;
-
-       // We have to call count() each time, because it can happen that
-       // more than one splitter will disappear in one iteration (bug 5998).
-       for (; d.splitter_->count() > empty_twa; ) {
-               TabWorkArea * twa = d.tabWorkArea(empty_twa);
-                               
-               int twa_count = twa->count();
-               if (twa->count() == 0)
-                       ++empty_twa;
-
-               for (; twa_count; --twa_count) {
-                       twa->setCurrentIndex(twa_count-1);
-
-                       GuiWorkArea * wa = twa->currentWorkArea();
-                       bool const is_active_wa = active_wa == wa;
-                       Buffer * b = &wa->bufferView().buffer();
-                       if (b->parent()) {
-                               // This is a child document, just close the tab
-                               // after saving but keep the file loaded.
-                               if (!closeWorkArea(wa, false, tolastopened, is_active_wa))
-                                       return false;
-                               continue;
-                       }
-
-                       vector<Buffer *> clist = b->getChildren();
-                       for (vector<Buffer *>::const_iterator it = clist.begin();
-                                it != clist.end(); ++it) {
-                               if ((*it)->isClean())
-                                       continue;
-                               Buffer * c = *it;
-                               // If a child is dirty, do not close
-                               // without user intervention
-                               //FIXME: should buffers be closed or not?
-                               if (!closeWorkArea(workArea(*c), false, false))
-                                       return false;
-                       }
-
-                       // We only want to close the buffer if the same buffer is not in
-                       // another view.
-                       bool const close_buffer = !inMultiViews(wa);
-
-                       // closeBuffer() needs buffer workArea still alive and
-                       // set as currrent one, and destroys it
-                       if (b && !closeWorkArea(wa, close_buffer, tolastopened, is_active_wa))
-                               return false;
-               }
-       }
-       return true;
-}
-
-
 void GuiView::dragEnterEvent(QDragEnterEvent * event)
 {
        if (event->mimeData()->hasUrls())
@@ -1921,6 +1860,13 @@ bool GuiView::hideWorkArea(GuiWorkArea * wa)
 }
 
 
+bool GuiView::closeWorkArea(GuiWorkArea * wa)
+{
+       Buffer & buf = wa->bufferView().buffer();
+       return closeWorkArea(wa, !buf.parent());
+}
+
+
 bool GuiView::closeBuffer()
 {
        GuiWorkArea * wa = currentMainWorkArea();
@@ -1929,21 +1875,81 @@ bool GuiView::closeBuffer()
 }
 
 
+bool GuiView::closeBufferAll(bool in_close_event)
+{
+       // First close all workareas. This will make
+       // sure that dirty buffers are saved.
+       if (!closeWorkAreaAll(in_close_event))
+               return false;
+
+       // Now close the hidden buffers. We prevent hidden 
+       // buffers from being dirty, so we can just close them.
+       theBufferList().closeAll();
+       return true;
+}
+
+
+bool GuiView::closeWorkAreaAll(bool in_close_event)
+{
+       GuiWorkArea * active_wa = currentMainWorkArea();
+       setCurrentWorkArea(active_wa);
+
+       // We might be in a situation that there is still a tabWorkArea, but
+       // there are no tabs anymore. This can happen when we get here after a 
+       // TabWorkArea::lastWorkAreaRemoved() signal. Therefore we count how
+       // many TabWorkArea's have no documents anymore.
+       int empty_twa = 0;
+
+       // We have to call count() each time, because it can happen that
+       // more than one splitter will disappear in one iteration (bug 5998).
+       for (; d.splitter_->count() > empty_twa; ) {
+               TabWorkArea * twa = d.tabWorkArea(empty_twa);
+                               
+               if (twa->count() == 0)
+                       ++empty_twa;
+               else {
+                       setCurrentWorkArea(twa->currentWorkArea());
+                       if (!closeTabWorkArea(twa, true, active_wa))
+                               return false;
+               }
+       }
+       return true;
+}
+
+
 bool GuiView::closeWorkArea(GuiWorkArea * wa, bool close_buffer,
-       bool tolastopened, bool mark_active)
+       bool in_close_event, bool mark_active)
 {
+       Buffer & buf = wa->bufferView().buffer();
+
+       if (close_buffer && !in_close_event) {
+               vector<Buffer *> clist = buf.getChildren();
+               for (vector<Buffer *>::const_iterator it = clist.begin();
+                        it != clist.end(); ++it) {
+                       // If a child is dirty, do not close
+                       // without user intervention
+                       //FIXME: should buffers be closed or not?
+                       //FIXME: should we look in other tabworkareas?
+                       GuiWorkArea * child_wa = workArea(**it);
+                       if (child_wa && !closeWorkArea(child_wa, !close_buffer, false))
+                               return false;
+               }
+       }
        // goto bookmark to update bookmark pit.
        //FIXME: we should update only the bookmarks related to this buffer!
        LYXERR(Debug::DEBUG, "GuiView::closeBuffer()");
        for (size_t i = 0; i < theSession().bookmarks().size(); ++i)
                theLyXFunc().gotoBookmark(i+1, false, false);
 
-       Buffer & buf = wa->bufferView().buffer();
-       if (saveBufferIfNeeded(buf, !close_buffer)) {
+       // if we are only hiding the buffer and there are multiple views
+       // of the buffer, then we do not need to ensure a clean buffer.
+       bool const allow_dirty = inMultiTabs(wa) && !close_buffer;
+
+       if (allow_dirty || saveBufferIfNeeded(buf, !close_buffer)) {
                // save in sessions if requested
                // do not save childs if their master
                // is opened as well
-               if (tolastopened)
+               if (in_close_event)
                        theSession().lastOpened().add(buf.fileName(), mark_active);
                if (!close_buffer)
                        removeWorkArea(wa);
@@ -1955,6 +1961,31 @@ bool GuiView::closeWorkArea(GuiWorkArea * wa, bool close_buffer,
 }
 
 
+bool GuiView::closeTabWorkArea(TabWorkArea * twa, bool in_close_event,
+                                                          GuiWorkArea * main_work_area)
+{
+       while (twa == d.currentTabWorkArea()) {
+               twa->setCurrentIndex(twa->count()-1);
+
+               GuiWorkArea * wa = twa->currentWorkArea();
+               bool const is_active_wa = main_work_area == wa;
+               Buffer & b = wa->bufferView().buffer();
+
+               // We only want to close the buffer if the same buffer is not visible
+               // in another view, and if this is not a child and if we are closing
+               // a view (not a tabgroup).
+               bool const close_buffer = 
+                       !inMultiViews(wa) && !b.parent() && in_close_event;
+
+               // closeBuffer() needs buffer workArea still alive and
+               // set as currrent one, and destroys it
+               if (!closeWorkArea(wa, close_buffer, true, is_active_wa))
+                       return false;
+       }
+       return true;
+}
+
+
 bool GuiView::saveBufferIfNeeded(Buffer & buf, bool hiding)
 {
        if (buf.isClean() || buf.paragraphs().empty())
@@ -2000,11 +2031,10 @@ bool GuiView::saveBufferIfNeeded(Buffer & buf, bool hiding)
                // have no autosave file but I guess
                // this is really improbable (Jug)
                buf.removeAutosaveFile();
-               if (hiding) {
+               if (hiding)
                        // revert all changes
                        buf.loadLyXFile(buf.fileName());
-                       buf.markClean();
-               }
+               buf.markClean();
                break;
        case 2:
                return false;
@@ -2013,6 +2043,19 @@ bool GuiView::saveBufferIfNeeded(Buffer & buf, bool hiding)
 }
 
 
+bool GuiView::inMultiTabs(GuiWorkArea * wa)
+{
+       Buffer & buf = wa->bufferView().buffer();
+
+       for (int i = 0; i != d.splitter_->count(); ++i) {
+               GuiWorkArea * wa_ = d.tabWorkArea(i)->workArea(buf);
+               if (wa_ && wa_ != wa)
+                       return true;
+       }
+       return inMultiViews(wa);
+}
+
+
 bool GuiView::inMultiViews(GuiWorkArea * wa)
 {
        QList<int> const ids = guiApp->viewIds();
@@ -2268,7 +2311,7 @@ bool GuiView::dispatch(FuncRequest const & cmd)
 
                case LFUN_CLOSE_TAB_GROUP:
                        if (TabWorkArea * twa = d.currentTabWorkArea()) {
-                               delete twa;
+                               closeTabWorkArea(twa, false);
                                d.current_work_area_ = 0;
                                twa = d.currentTabWorkArea();
                                // Switch to the next GuiWorkArea in the found TabWorkArea.