Abdelrazak Younes wrote:
http://bugzilla.lyx.org/show_bug.cgi?id=3860

SVN Log:

Polish the Toc and labels updating when loading a child document. Fix Bug 3860: Toc crash when loading a child documents.

* BufferView::loadLyXFile(): simplify, transfer last part to LyXView::loadLyXFile()

* LyXView:
- setBuffer(): properly update the labels and the Toc if this is [LOAD Child Document] command. - loadLyXFile(): get some code from BufferView::loadLyXFile() and from LyXFunc::LFUN_BUFFER_CHILD, properly handle the child document case.

* LyXFunc: simplify LFUN_BUFFER_CHILD.

* LyX: adapt to loadLyXFile() API change.


With this in place, the only thing missing for proper multipart document support is to automatically update the parent Buffer when switching from the parent Buffer. This would be very useful when you work with multiple document sharing the same child documents (as I often do).

Seeking two OKs. As this is a critical bug fixing patch I reckon this should go before RC2. Once this is in, I'll look at the automatic updating of LOF, LOT and LOL... LOL!

I won't be able to commit it this week-end so could anyone show a little bit of interest please?

Patch updated to latest svn attached...

Abdel.
Index: Buffer.cpp
===================================================================
--- Buffer.cpp  (revision 18780)
+++ Buffer.cpp  (working copy)
@@ -1613,7 +1613,11 @@
 
 void Buffer::setParentName(string const & name)
 {
-       params().parentname = name;
+       if (name == pimpl_->filename.absFilename())
+               // Avoids recursive include.
+               params().parentname.clear();
+       else
+               params().parentname = name;
 }
 
 
Index: BufferView.cpp
===================================================================
--- BufferView.cpp      (revision 18780)
+++ BufferView.cpp      (working copy)
@@ -233,8 +233,8 @@
                graphics::Previews::get().generateBufferPreviews(*buffer_);
 }
 
-
-bool BufferView::loadLyXFile(FileName const & filename, bool tolastfiles)
+// FIXME: all of this should go in a helper file in buffer_func.
+bool BufferView::loadLyXFile(FileName const & filename)
 {
        // File already open?
        if (theBufferList().exists(filename.absFilename())) {
@@ -280,27 +280,7 @@
        }
 
        setBuffer(b);
-       // Send the "errors" signal in case of parsing errors
-       b->errors("Parse");
 
-       // Update the labels and section numbering.
-       updateLabels(*buffer_);
-       // scroll to the position when the file was last closed
-       if (lyxrc.use_lastfilepos) {
-               pit_type pit;
-               pos_type pos;
-               boost::tie(pit, pos) = 
LyX::ref().session().lastFilePos().load(filename);
-               // if successfully move to pit (returned par_id is not zero), 
update metrics and reset font
-               if (moveToPosition(pit, pos, 0, 0).get<1>()) {
-                       if (fitCursor())
-                               updateMetrics(false);
-                       buffer_->text().setCurrentFont(cursor_);
-               }
-       }
-
-       if (tolastfiles)
-               LyX::ref().session().lastFiles().add(FileName(b->fileName()));
-
        return true;
 }
 
Index: BufferView.h
===================================================================
--- BufferView.h        (revision 18780)
+++ BufferView.h        (working copy)
@@ -94,7 +94,7 @@
        void resize();
 
        /// load a buffer into the view.
-       bool loadLyXFile(support::FileName const & name, bool tolastfiles = 
true);
+       bool loadLyXFile(support::FileName const & name);
 
        /// perform pending metrics updates.
        /** \c Update::FitCursor means first to do a FitCursor, and to
Index: frontends/LyXView.cpp
===================================================================
--- frontends/LyXView.cpp       (revision 18780)
+++ frontends/LyXView.cpp       (working copy)
@@ -20,6 +20,7 @@
 #include "Gui.h"
 
 #include "Buffer.h"
+#include "buffer_funcs.h"
 #include "BufferList.h"
 #include "BufferParams.h"
 #include "BufferView.h"
@@ -31,6 +32,7 @@
 #include "gettext.h"
 #include "Intl.h"
 #include "callback.h"
+#include "LyX.h"
 #include "LyXFunc.h"
 #include "LyXRC.h"
 #include "Text.h"
@@ -122,27 +124,44 @@
 }
 
 
-void LyXView::setBuffer(Buffer * b)
+void LyXView::setBuffer(Buffer * b, bool child_document)
 {
        busy(true);
 
        BOOST_ASSERT(work_area_);
-       if (work_area_->bufferView().buffer())
+       Buffer * oldBuffer = work_area_->bufferView().buffer();
+       // parentfilename will be used in case when we switch to a child
+       // document (hence when child_document is true)
+       string parentfilename;
+       if (oldBuffer) {
+               parentfilename = oldBuffer->fileName();
                disconnectBuffer();
+       }
 
        if (!b && theBufferList().empty())
                getDialogs().hideBufferDependent();
 
        work_area_->bufferView().setBuffer(b);
-       // Make sure the TOC is updated before anything else.
-       updateToc();
 
-       if (work_area_->bufferView().buffer()) {
+       Buffer * newBuffer = work_area_->bufferView().buffer();
+       if (newBuffer) {
+               if (child_document && newBuffer != oldBuffer) {
+                       // Set the parent name of the child document.
+                       // This makes insertion of citations and references in 
the child work,
+                       // when the target is in the parent or another child 
document.
+                       newBuffer->setParentName(parentfilename);
+                       // updateLabels() will emit Buffer::structureChanged() 
so better
+                       // connect it before.
+                       connectBuffer(*newBuffer);
+                       // Update the labels and section numbering.
+                       updateLabels(*newBuffer->getMasterBuffer());
+               } else
+                       connectBuffer(*newBuffer);
+
                // Buffer-dependent dialogs should be updated or
                // hidden. This should go here because some dialogs (eg ToC)
                // require bv_->text.
                getDialogs().updateBufferDependent(true);
-               connectBuffer(*work_area_->bufferView().buffer());
        }
 
        if (quitting)
@@ -159,30 +178,69 @@
 }
 
 
-bool LyXView::loadLyXFile(FileName const & filename, bool tolastfiles)
+bool LyXView::loadLyXFile(FileName const & filename, bool tolastfiles,
+               bool child_document)
 {
        busy(true);
 
        BOOST_ASSERT(work_area_);
-       bool const hadBuffer = work_area_->bufferView().buffer();
-       if (hadBuffer)
+       string parentfilename;
+       Buffer * oldBuffer = work_area_->bufferView().buffer();
+       if (oldBuffer) {
+               parentfilename = oldBuffer->fileName();
                disconnectBuffer();
+       }
 
        bool const loaded =
-               work_area_->bufferView().loadLyXFile(filename, tolastfiles);
+               work_area_->bufferView().loadLyXFile(filename);
 
-       updateToc();
+       if (loaded) {
+               Buffer * newBuffer = work_area_->bufferView().buffer();
+               showErrorList("Parse");
+
+               if (child_document && newBuffer != oldBuffer) {
+                       // Set the parent name of the child document.
+                       // This makes insertion of citations and references in 
the child work,
+                       // when the target is in the parent or another child 
document.
+                       newBuffer->setParentName(parentfilename);
+                       message(bformat(_("Opening child document %1$s..."),
+                               makeDisplayPath(filename.absFilename())));
+               }
+               // updateLabels() will emit Buffer::structureChanged() so better
+               // connect it before.
+               connectBuffer(*newBuffer);
+               // Update the labels and section numbering.
+               updateLabels(*newBuffer->getMasterBuffer());
+
+               // scroll to the position when the file was last closed
+               if (lyxrc.use_lastfilepos) {
+                       pit_type pit;
+                       pos_type pos;
+                       boost::tie(pit, pos) = 
LyX::ref().session().lastFilePos().load(filename);
+                       // if successfully move to pit (returned par_id is not 
zero),
+                       // update metrics and reset font
+                       if (work_area_->bufferView().moveToPosition(pit, pos, 
0, 0).get<1>()) {
+                               if (work_area_->bufferView().fitCursor())
+                                       
work_area_->bufferView().updateMetrics(false);
+                               
newBuffer->text().setCurrentFont(work_area_->bufferView().cursor());
+                       }
+               }
+
+               if (tolastfiles)
+                       LyX::ref().session().lastFiles().add(filename);
+
+       } else {
+               message(_("Document not loaded."));
+               if (oldBuffer)
+                       //Need to reconnect the buffer if the load failed
+                       connectBuffer(*oldBuffer);
+       }
+
        updateMenubar();
        updateToolbars();
        updateLayoutChoice();
        updateWindowTitle();
        updateTab();
-       if (loaded) {
-               connectBuffer(*work_area_->bufferView().buffer());
-               showErrorList("Parse");
-       } else if (hadBuffer)
-               //Need to reconnect the buffer if the load failed
-               connectBuffer(*work_area_->bufferView().buffer());
        updateStatusBar();
        busy(false);
        work_area_->redraw();
@@ -230,7 +288,7 @@
 
        closingConnection_ =
                buf.closing.connect(
-                       boost::bind(&LyXView::setBuffer, this, (Buffer *)0));
+                       boost::bind(&LyXView::setBuffer, this, (Buffer *)0, 
false));
 }
 
 
Index: frontends/LyXView.h
===================================================================
--- frontends/LyXView.h (revision 18780)
+++ frontends/LyXView.h (working copy)
@@ -142,11 +142,14 @@
 
        //@}
 
-       /// load a buffer into the current workarea
-       bool loadLyXFile(support::FileName const &  name, bool tolastfiles = 
true);
+       /// load a buffer into the current workarea.
+       bool loadLyXFile(support::FileName const &  name, ///< File to load.
+               bool tolastfiles = true,  ///< append to the "Open recent" menu?
+               bool child_document = false); ///< Is this a child document?
 
-       /// set a buffer to the current workarea
-       void setBuffer(Buffer * b);
+       /// set a buffer to the current workarea.
+       void setBuffer(Buffer * b, ///< \c Buffer to set.
+               bool child_document = false);  ///< Is this a child document?
 
        /// updates the possible layouts selectable
        void updateLayoutChoice();
Index: LyX.cpp
===================================================================
--- LyX.cpp     (revision 18780)
+++ LyX.cpp     (working copy)
@@ -613,7 +613,7 @@
        if (!pimpl_->files_to_load_.empty()) {
                for_each(pimpl_->files_to_load_.begin(),
                        pimpl_->files_to_load_.end(),
-                       bind(&LyXView::loadLyXFile, view, _1, true));
+                       bind(&LyXView::loadLyXFile, view, _1, true, false));
                // clear this list to save a few bytes of RAM
                pimpl_->files_to_load_.clear();
                pimpl_->session_->lastOpened().clear();
@@ -628,7 +628,7 @@
        // last session, and should be already there (regular files), or should
        // not be added at all (help files).
        for_each(lastopened.begin(), lastopened.end(),
-               bind(&LyXView::loadLyXFile, view, _1, false));
+               bind(&LyXView::loadLyXFile, view, _1, false, false));
 
        // clear this list to save a few bytes of RAM
        pimpl_->session_->lastOpened().clear();
Index: LyXFunc.cpp
===================================================================
--- LyXFunc.cpp (revision 18780)
+++ LyXFunc.cpp (working copy)
@@ -1414,19 +1414,11 @@
                        FileName const filename =
                                makeAbsPath(argument, 
lyx_view_->buffer()->filePath());
                        view()->saveBookmark(false);
-                       string const parentfilename = 
lyx_view_->buffer()->fileName();
-                       if (theBufferList().exists(filename.absFilename()))
-                               
lyx_view_->setBuffer(theBufferList().getBuffer(filename.absFilename()));
+                       if (theBufferList().exists(filename.absFilename())) {
+                               
lyx_view_->setBuffer(theBufferList().getBuffer(filename.absFilename()), true);
+                       }
                        else
-                               if (lyx_view_->loadLyXFile(filename)) {
-                                       // Set the parent name of the child 
document.
-                                       // This makes insertion of citations 
and references in the child work,
-                                       // when the target is in the parent or 
another child document.
-                                       
lyx_view_->buffer()->setParentName(parentfilename);
-                                       setMessage(bformat(_("Opening child 
document %1$s..."),
-                                                
makeDisplayPath(filename.absFilename())));
-                               } else
-                                       setMessage(_("Document not loaded."));
+                               lyx_view_->loadLyXFile(filename, true, true);
                        break;
                }
 

Reply via email to