Abdelrazak Younes wrote:
Richard Heck wrote:

The attached patch builds on Abdel's earlier work and, I think, solves the remaining problems. Whether this is the best way to do it, I'm not sure. Abdel was talking about a more major re-organization of the code, but maybe that could wait.

Maybe yes.


What I've done is add an optional argument to LFUN_BUFFER_CHILD_OPEN indicating whether the file is being auto-loaded. (Contrary to what I said before, this is ok, since we're expecting a valid LyX filename, and one isn't going to end with "|true".) There are also corresponding booleans in LyXView::loadLyXFile and BufferView::loadLyXFile.

At this point BufferView::loadLyXFile() do not need to be a member of BufferView so please put that in buffer_func.cpp along the other loadLyXFile().

Hi Richard,

I've done that and did a bit more simplifications. Patch attached (not tested yet). I hope everything is OK with your daughter.

Cheers,
Abdel.



Index: Buffer.cpp
===================================================================
--- Buffer.cpp  (revision 18822)
+++ Buffer.cpp  (working copy)
@@ -1616,7 +1616,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: buffer_funcs.cpp
===================================================================
--- buffer_funcs.cpp    (revision 18822)
+++ buffer_funcs.cpp    (working copy)
@@ -180,6 +180,47 @@
        return false;
 }
 
+// FIXME: all of this should go in a helper file in buffer_func.
+Buffer * checkAndLoadLyXFile(FileName const & filename)
+{
+       // File already open?
+       if (theBufferList().exists(filename.absFilename())) {
+               docstring const file = makeDisplayPath(filename.absFilename(), 
20);
+               docstring text = bformat(_("The document %1$s is already "
+                                                    "loaded.\n\nDo you want to 
revert "
+                                                    "to the saved version?"), 
file);
+               if (Alert::prompt(_("Revert to saved document?"),
+                               text, 0, 1,  _("&Revert"), _("&Switch to 
document")))
+                       return 
theBufferList().getBuffer(filename.absFilename());
+
+               // FIXME: should be LFUN_REVERT
+               if 
(theBufferList().close(theBufferList().getBuffer(filename.absFilename()), 
false))
+                       // Load it again.
+                       return checkAndLoadLyXFile(filename);
+               else
+                       // The file could not be closed.
+                       return 0;
+       }
+
+       if (isFileReadable(filename)) {
+               Buffer * b = theBufferList().newBuffer(filename.absFilename());
+               if (!lyx::loadLyXFile(b, filename)) {
+                       theBufferList().release(b);
+                       return 0;
+               }
+               return b;
+       }
+
+       docstring text = bformat(_("The document %1$s does not yet "
+               "exist.\n\nDo you want to create a new document?"),
+               from_utf8(filename.absFilename()));
+       if (Alert::prompt(_("Create new document?"),
+                       text, 0, 1, _("&Create"), _("Cancel"))
+               return newFile(filename.absFilename(), string(), true);
+
+       return 0;
+}
+
 // FIXME newFile() should probably be a member method of Application...
 Buffer * newFile(string const & filename, string const & templatename,
                 bool const isNamed)
Index: buffer_funcs.h
===================================================================
--- buffer_funcs.h      (revision 18822)
+++ buffer_funcs.h      (working copy)
@@ -34,6 +34,13 @@
  */
 bool loadLyXFile(Buffer *, support::FileName const & filename);
 
+/**
+ *  Checks and loads a LyX file \param filename.
+ *  \retval the newly created \c Buffer pointer if successful or 0.
+ *  \retval 0 if the \c Buffer could not be created.
+ */
+Buffer * checkAndLoadLyXFile(support::FileName const & filename);
+
 /* Make a new file (buffer) with name \c filename based on a template
  * named \c templatename
  */
Index: BufferView.cpp
===================================================================
--- BufferView.cpp      (revision 18822)
+++ BufferView.cpp      (working copy)
@@ -233,78 +233,6 @@
                graphics::Previews::get().generateBufferPreviews(*buffer_);
 }
 
-
-bool BufferView::loadLyXFile(FileName const & filename, bool tolastfiles)
-{
-       // File already open?
-       if (theBufferList().exists(filename.absFilename())) {
-               docstring const file = makeDisplayPath(filename.absFilename(), 
20);
-               docstring text = bformat(_("The document %1$s is already "
-                                                    "loaded.\n\nDo you want to 
revert "
-                                                    "to the saved version?"), 
file);
-               int const ret = Alert::prompt(_("Revert to saved document?"),
-                       text, 0, 1,  _("&Revert"), _("&Switch to document"));
-
-               if (ret != 0) {
-                       
setBuffer(theBufferList().getBuffer(filename.absFilename()));
-                       return true;
-               }
-               // FIXME: should be LFUN_REVERT
-               if 
(!theBufferList().close(theBufferList().getBuffer(filename.absFilename()), 
false))
-                       return false;
-               // Fall through to new load. (Asger)
-               buffer_ = 0;
-       }
-
-       Buffer * b = 0;
-
-       if (isFileReadable(filename)) {
-               b = theBufferList().newBuffer(filename.absFilename());
-               if (!lyx::loadLyXFile(b, filename)) {
-                       theBufferList().release(b);
-                       return false;
-               }
-       } else {
-               docstring text = bformat(_("The document %1$s does not yet "
-                                                    "exist.\n\nDo you want to 
create "
-                                                    "a new document?"), 
from_utf8(filename.absFilename()));
-               int const ret = Alert::prompt(_("Create new document?"),
-                        text, 0, 1, _("&Create"), _("Cancel"));
-
-               if (ret == 0) {
-                       b = newFile(filename.absFilename(), string(), true);
-                       if (!b)
-                               return false;
-               } else
-                       return false;
-       }
-
-       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;
-}
-
-
 void BufferView::resize()
 {
        if (!buffer_)
Index: BufferView.h
===================================================================
--- BufferView.h        (revision 18822)
+++ BufferView.h        (working copy)
@@ -93,9 +93,6 @@
        /// resize the BufferView.
        void resize();
 
-       /// load a buffer into the view.
-       bool loadLyXFile(support::FileName const & name, bool tolastfiles = 
true);
-
        /// perform pending metrics updates.
        /** \c Update::FitCursor means first to do a FitCursor, and to
         * force an update if screen position changes.
Index: frontends/LyXView.cpp
===================================================================
--- frontends/LyXView.cpp       (revision 18822)
+++ 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,34 +178,62 @@
 }
 
 
-bool LyXView::loadLyXFile(FileName const & filename, bool tolastfiles)
+bool LyXView::loadLyXFile(FileName const & filename, bool tolastfiles,
+               bool child_document, bool auto_open)
 {
        busy(true);
 
        BOOST_ASSERT(work_area_);
-       bool const hadBuffer = work_area_->bufferView().buffer();
-       if (hadBuffer)
-               disconnectBuffer();
+       string parentfilename;
+       Buffer * oldBuffer = work_area_->bufferView().buffer();
+       if (oldBuffer)
+               parentfilename = oldBuffer->fileName();
 
-       bool const loaded =
-               work_area_->bufferView().loadLyXFile(filename, tolastfiles);
+       Buffer * newBuffer = checkAndLoadLyXFile(filename);
 
-       updateToc();
-       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();
-       return loaded;
+       if (!newBuffer) {
+               message(_("Document not loaded."));
+               updateStatusBar();
+               busy(false);
+               work_area_->redraw();
+               return false;
+       }
+
+       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())));
+       }
+
+       if (!auto_open)
+               setBuffer(newBuffer, child_document);
+
+       // Update the labels and section numbering.
+       updateLabels(*newBuffer->getMasterBuffer());
+
+       // scroll to the position when the file was last closed
+       if (!auto_open && 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);
+
+       return true;
 }
 
 
@@ -230,7 +277,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 18822)
+++ frontends/LyXView.h (working copy)
@@ -142,11 +142,15 @@
 
        //@}
 
-       /// 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?
+    bool auto_open = false); ///< Is this being opened by LyX itself?
 
-       /// 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: insets/InsetInclude.cpp
===================================================================
--- insets/InsetInclude.cpp     (revision 18822)
+++ insets/InsetInclude.cpp     (working copy)
@@ -52,6 +52,9 @@
 
 
 namespace lyx {
+  
+// Implementation is in LyX.cpp
+extern void dispatch(FuncRequest const & action);
 
 using support::addName;
 using support::absolutePath;
@@ -400,12 +403,10 @@
                // the readonly flag can/will be wrong, not anymore I think.
                if (!fs::exists(included_file.toFilesystemEncoding()))
                        return false;
-               buf = theBufferList().newBuffer(included_file.absFilename());
-               if (!loadLyXFile(buf, included_file)) {
-                       //close the buffer we just opened
-                       theBufferList().close(buf, false);
-                       return false;
-               }
+               lyx::dispatch(FuncRequest(LFUN_BUFFER_CHILD_OPEN,
+                       included_file.absFilename() + "|true"));
+               buf = theBufferList().getBuffer(included_file.absFilename());
+               return buf;
        }
        buf->setParentName(parentFilename(buffer));
        return true;
Index: LyX.cpp
===================================================================
--- LyX.cpp     (revision 18822)
+++ 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, 
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, false));
 
        // clear this list to save a few bytes of RAM
        pimpl_->session_->lastOpened().clear();
Index: LyXFunc.cpp
===================================================================
--- LyXFunc.cpp (revision 18822)
+++ LyXFunc.cpp (working copy)
@@ -1410,23 +1410,34 @@
                }
 
                case LFUN_BUFFER_CHILD_OPEN: {
+                       // takes an optional argument, "|bool", at the end
+                       // indicating whether this file is being opened 
automatically
+                       // by LyX itself, in which case we will not want to 
switch
+                       // buffers after opening. The default is false, so in 
practice
+                       // it is used only when true.
                        BOOST_ASSERT(lyx_view_);
-                       FileName const filename =
+                       int const arglength = argument.length();
+                       FileName filename;
+                       bool autoOpen = false;
+                       if (argument.substr(arglength - 5, 5) == "|true") {
+                               autoOpen = true;
+                               filename = makeAbsPath(argument.substr(0, 
arglength - 5), 
+                                       lyx_view_->buffer()->filePath());
+                       } else if (argument.substr(arglength - 6, 6) == 
"|false") {
+                               filename = makeAbsPath(argument.substr(0, 
arglength - 6), 
+                                       lyx_view_->buffer()->filePath());
+                       } else 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()));
-                       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."));
+                       if (theBufferList().exists(filename.absFilename())) {
+                               Buffer * buf = 
theBufferList().getBuffer(filename.absFilename());
+                               if (!autoOpen)
+                                       lyx_view_->setBuffer(buf, true);
+                               else
+                                       
buf->setParentName(lyx_view_->buffer()->fileName());
+                       } else
+                               lyx_view_->loadLyXFile(filename, true, true, 
autoOpen);
+
                        break;
                }
 

Reply via email to