diff --git a/lib/ui/stdmenus.inc b/lib/ui/stdmenus.inc index 6758889218..648c91c5b4 100644 --- a/lib/ui/stdmenus.inc +++ b/lib/ui/stdmenus.inc @@ -46,6 +46,7 @@ Menuset Submenu "Open Recent|t" "file_lastfiles" Separator Item "Close|C" "buffer-close" + Item "Close All" "buffer-close-all" Item "Save|S" "buffer-write" Item "Save As...|A" "buffer-write-as" Item "Save All|l" "buffer-write-all" diff --git a/src/FuncCode.h b/src/FuncCode.h index f3a66249f7..52ee7739b9 100644 --- a/src/FuncCode.h +++ b/src/FuncCode.h @@ -439,6 +439,7 @@ enum FuncCode LFUN_BRANCH_ADD_INSERT, // 340 LFUN_BRANCHES_RENAME, // spitz 20090709 + LFUN_BUFFER_CLOSE_ALL, // vfr 20090806 LFUN_LASTACTION // end of the table }; diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp index f8e6498b78..892e5a3ba2 100644 --- a/src/LyXAction.cpp +++ b/src/LyXAction.cpp @@ -2837,6 +2837,15 @@ void LyXAction::init() * \endvar */ { LFUN_BUFFER_CLOSE, "buffer-close", ReadOnly, Buffer }, +/*! + * \var lyx::FuncCode lyx::LFUN_BUFFER_CLOSE_ALL + * \li Action: Closes all buffers. + * \li Notion: Closes all buffers, asking whether to save it, etc, + if a buffer has been modified. + * \li Syntax: buffer-close_all + * \endvar + */ + { LFUN_BUFFER_CLOSE_ALL, "buffer-close-all", ReadOnly, Buffer }, /*! * \var lyx::FuncCode lyx::LFUN_BUFFER_EXPORT * \li Action: Exports the current buffer (document) to the given format. diff --git a/src/LyXFunc.cpp b/src/LyXFunc.cpp index 0c985b35ec..948edbe331 100644 --- a/src/LyXFunc.cpp +++ b/src/LyXFunc.cpp @@ -633,6 +633,7 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const case LFUN_CANCEL: case LFUN_META_PREFIX: case LFUN_BUFFER_CLOSE: + case LFUN_BUFFER_CLOSE_ALL: case LFUN_BUFFER_IMPORT: case LFUN_BUFFER_AUTO_SAVE: case LFUN_RECONFIGURE: @@ -879,6 +880,12 @@ void LyXFunc::dispatch(FuncRequest const & cmd) updateFlags = Update::None; break; + case LFUN_BUFFER_CLOSE_ALL: + lyx_view_->closeBufferAll(); + buffer = 0; + updateFlags = Update::None; + break; + case LFUN_BUFFER_RELOAD: { LASSERT(lyx_view_ && buffer, /**/); docstring const file = makeDisplayPath(buffer->absFileName(), 20); diff --git a/src/frontends/LyXView.h b/src/frontends/LyXView.h index cb183a011b..77297c4b42 100644 --- a/src/frontends/LyXView.h +++ b/src/frontends/LyXView.h @@ -67,6 +67,8 @@ public: /// virtual bool closeBuffer() = 0; /// + virtual bool closeBufferAll(bool tolastopened = false) = 0; + /// virtual bool hasFocus() const = 0; /// load a document into the current workarea. diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp index 73bddd6144..605426be8b 100644 --- a/src/frontends/qt4/GuiView.cpp +++ b/src/frontends/qt4/GuiView.cpp @@ -536,83 +536,12 @@ 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(); - 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 (!closeBuffer(*b, true, is_active_wa)) { - closing_ = false; - close_event->ignore(); - return; - } - continue; - } - - vector clist = b->getChildren(); - for (vector::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 - if (!closeBuffer(*c, false)) { - closing_ = false; - close_event->ignore(); - return; - } - } - - QList const ids = guiApp->viewIds(); - for (int i = 0; i != ids.size(); ++i) { - if (id_ == ids[i]) - continue; - if (guiApp->view(ids[i]).workArea(*b)) { - // FIXME 1: should we put an alert box here - // that the buffer is viewed elsewhere? - // FIXME 2: should we try to save this buffer in any case? - //saveBuffer(b); - - // This buffer is also opened in another view, so - // close the associated work area... - removeWorkArea(wa); - // ... but don't close the buffer. - b = 0; - break; - } - } - // closeBuffer() needs buffer workArea still alive and - // set as currrent one, and destroys it - if (b && !closeBuffer(*b, true, is_active_wa)) { - closing_ = false; - close_event->ignore(); - return; - } - } + if (!closeBufferAll(true)) { + closing_ = false; + close_event->ignore(); + return; } + // Make sure that nothing will use this close to be closed View. guiApp->unregisterView(this); @@ -644,6 +573,80 @@ 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 (!closeBuffer(*b, tolastopened, is_active_wa)) + return false; + continue; + } + + vector clist = b->getChildren(); + for (vector::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 + if (!closeBuffer(*c, false)) + return false; + } + + QList const ids = guiApp->viewIds(); + for (int i = 0; i != ids.size(); ++i) { + if (id_ == ids[i]) + continue; + if (guiApp->view(ids[i]).workArea(*b)) { + // FIXME 1: should we put an alert box here + // that the buffer is viewed elsewhere? + // FIXME 2: should we try to save this buffer in any case? + //saveBuffer(b); + + // This buffer is also opened in another view, so + // close the associated work area... + removeWorkArea(wa); + // ... but don't close the buffer. + b = 0; + break; + } + } + // closeBuffer() needs buffer workArea still alive and + // set as currrent one, and destroys it + if (b && !closeBuffer(*b, tolastopened, is_active_wa)) + return false; + } + } + return true; +} + + void GuiView::dragEnterEvent(QDragEnterEvent * event) { if (event->mimeData()->hasUrls()) diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h index 0ce40726f1..c2fb794d11 100644 --- a/src/frontends/qt4/GuiView.h +++ b/src/frontends/qt4/GuiView.h @@ -297,6 +297,8 @@ private: bool closeBuffer(Buffer & buf, bool tolastopened = false, bool mark_active = false); /// + bool closeBufferAll(bool tolastopened = false); + /// enum NextOrPrevious { NEXTBUFFER, PREVBUFFER