// GuiToolbars *must* be initialised before the menu bar.
normalSizedIcons(); // at least on Mac the default is 32 otherwise, which is huge
constructToolbars();
- d.layout_ = new LayoutBox(*this);
- d.stack_widget_->addWidget(d.layout_);
// set ourself as the current view. This is needed for the menu bar
// filling, at least for the static special menu item on Mac. Otherwise
delete it->second;
d.toolbars_.clear();
+ // I don't like doing this here, but the standard toolbar
+ // destroys this object when it's destroyed itself (vfr)
+ d.layout_ = new LayoutBox(*this);
+ d.stack_widget_->addWidget(d.layout_);
+ d.layout_->move(0,0);
+
// extracts the toolbars from the backend
Toolbars::Infos::iterator cit = guiApp->toolbars().begin();
Toolbars::Infos::iterator end = guiApp->toolbars().end();
LYXERR(Debug::DEBUG, "GuiView::closeEvent()");
closing_ = true;
+ writeSession();
+
// 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()) {
closing_ = false;
close_event->ignore();
return;
}
- // Make sure that nothing will use this close to be closed View.
+ // Make sure that nothing will use this to be closed View.
guiApp->unregisterView(this);
if (isFullScreen()) {
}
-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, 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 (!closeBuffer(*c, false, false))
- return false;
- }
-
- QList<int> 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, tolastopened, is_active_wa))
- return false;
- }
- }
- return true;
-}
-
-
void GuiView::dragEnterEvent(QDragEnterEvent * event)
{
if (event->mimeData()->hasUrls())
void GuiView::disconnectBuffer()
{
if (d.current_work_area_)
- d.current_work_area_->bufferView().setGuiDelegate(0);
+ d.current_work_area_->bufferView().buffer().setGuiDelegate(0);
}
enable = buf;
break;
- case LFUN_BUFFER_CLOSE_ALL: {
- enable = false;
- BufferList::iterator it = theBufferList().begin();
- BufferList::iterator end = theBufferList().end();
- int visible_buffers = 0;
- for (; it != end; ++it) {
- if (workArea(**it))
- ++visible_buffers;
- if (visible_buffers > 1) {
- enable = true;
- break;
- }
- }
+ case LFUN_BUFFER_CLOSE_ALL:
+ enable = theBufferList().last() != theBufferList().first();
break;
- }
case LFUN_SPLIT_VIEW:
if (cmd.getArg(0) == "vertical")
}
-bool GuiView::hideBuffer()
+bool GuiView::hideWorkArea(GuiWorkArea * wa)
{
- Buffer * buf = buffer();
- return buf && closeBuffer(*buf, false);
+ return closeWorkArea(wa, false);
+}
+
+
+bool GuiView::closeWorkArea(GuiWorkArea * wa)
+{
+ Buffer & buf = wa->bufferView().buffer();
+ return closeWorkArea(wa, !buf.parent());
}
bool GuiView::closeBuffer()
{
- Buffer * buf = buffer();
- return buf && closeBuffer(*buf, !buf->parent());
+ GuiWorkArea * wa = currentMainWorkArea();
+ Buffer & buf = wa->bufferView().buffer();
+ return wa && closeWorkArea(wa, !buf.parent());
}
-bool GuiView::closeBuffer(Buffer & buf, bool close_buffer,
- bool tolastopened, bool mark_active)
+void GuiView::writeSession() const {
+ GuiWorkArea const * active_wa = currentMainWorkArea();
+ for (int i = 0; i < d.splitter_->count(); ++i) {
+ TabWorkArea * twa = d.tabWorkArea(i);
+ for (int j = 0; j < twa->count(); ++j) {
+ GuiWorkArea * wa = static_cast<GuiWorkArea *>(twa->widget(j));
+ Buffer & buf = wa->bufferView().buffer();
+ theSession().lastOpened().add(buf.fileName(), wa == active_wa);
+ }
+ }
+}
+
+
+bool GuiView::closeBufferAll()
{
+ // Close the workareas in all other views
+ QList<int> const ids = guiApp->viewIds();
+ for (int i = 0; i != ids.size(); ++i) {
+ if (id_ != ids[i] && !guiApp->view(ids[i]).closeWorkAreaAll())
+ return false;
+ }
+
+ // Close our own workareas
+ if (!closeWorkAreaAll())
+ 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()
+{
+ // To write in the session file which workarea was active.
+ 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, active_wa))
+ return false;
+ }
+ }
+ return true;
+}
+
+
+bool GuiView::closeWorkArea(GuiWorkArea * wa, bool close_buffer,
+ bool is_active)
+{
+ Buffer & buf = wa->bufferView().buffer();
+
+ // If we are in a close_event all children will be closed in some time,
+ // so no need to do it here. This will ensure that the children end up
+ // in the session file in the correct order. If we close the master
+ // buffer, we can close or release the child buffers here too.
+ if (close_buffer && !closing_) {
+ 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 we look in other tabworkareas?
+ Buffer * child_buf = *it;
+ GuiWorkArea * child_wa = workArea(*child_buf);
+ if (child_wa) {
+ if (!closeWorkArea(child_wa, true))
+ return false;
+ } else
+ theBufferList().releaseChild(&buf, child_buf);
+ }
+ }
// 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);
- 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)
- theSession().lastOpened().add(buf.fileName(), mark_active);
+ if (closing_)
+ theSession().lastOpened().add(buf.fileName(), is_active);
if (!close_buffer)
- removeWorkArea(currentMainWorkArea());
+ removeWorkArea(wa);
else
theBufferList().release(&buf);
return true;
}
+bool GuiView::closeTabWorkArea(TabWorkArea * twa, 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() && closing_;
+
+ if (!closeWorkArea(wa, close_buffer, is_active_wa))
+ return false;
+ }
+ return true;
+}
+
+
bool GuiView::saveBufferIfNeeded(Buffer & buf, bool hiding)
{
if (buf.isClean() || buf.paragraphs().empty())
// 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;
}
+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();
+ Buffer & buf = wa->bufferView().buffer();
+
+ int found_twa = 0;
+ for (int i = 0; i != ids.size() && found_twa <= 1; ++i) {
+ if (id_ == ids[i])
+ continue;
+
+ if (guiApp->view(ids[i]).workArea(buf))
+ return true;
+ }
+ return false;
+}
+
+
void GuiView::gotoNextOrPreviousBuffer(NextOrPrevious np)
{
Buffer * const curbuf = buffer();
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.
if (twa) {