I found myself using more and more the two ways toc navigation but, eventually I got annoyed by the slowness of it. So I fixed it :-)

This patch implements a Toc backend (TocBackend.[Ch]) that is used in toc.h. The speed improvement is _very_ very nice on windows.
I guess it should be sensible under mac and linux also. Try to open the
navigate menu on a user guide or any big highly hierarchical document). Maybe this was the cause of the slowness on Mac because of the special menu handling.

This patch impact minimally current code (except for toc.[Ch] and ControlToc.[Ch] of course). The toc cache is implemented as a static variable (static map<Buffer const *, lyx::TocBackend> toc_backend_; in toc.C), this is not very nice but this seems to be the only way with current code structure. Eventually, this toc_backend_ should become a member of the kernel. I use the paragraph text as an universal ID for the Toc item. This could/should eventually change once we have something stable.

Please test and comment. Test especially on other frontends to see if it
doesn't break anything. Tested only with qt4.

Abdel.

Log:
* TocBackend.[Ch]: new files defining class TocBackend. This class contains adapted code from former toc.C

* toc.[Ch]:
        - rewritten to take advantage of new TocBackend class. The toc
        cache is implemented as a static variable:
        static map<Buffer const *, lyx::TocBackend> toc_backend_;

* buffer_funcs.C:
        updateLabels(Buffer const & buf) now calls
        "lyx::toc::updateToc(buf);"

* pariterator.h: added default constructor
        ParConstIterator(): DocIterator() {}

* insetfloat.C: added pit parameter to TocItem construction

* insetwrap.C: added pit parameter to TocItem construction

* MenuBackend.C: use a const ref instead of a copy of TocList

* ControlToc.[Ch]: optimisation of the API by using const reference instead of copy.

* TocPanel.[Ch]:
        - optimisation of the API by using const reference instead of
        copy
        - makes use of TocBackend::Item::uid()

* QToc.C:
        - optimisation of the API by using const reference instead of
        copy
        - makes use of TocBackend::Item::uid()







Index: src/buffer_funcs.C
===================================================================
--- src/buffer_funcs.C  (revision 13695)
+++ src/buffer_funcs.C  (working copy)
@@ -33,6 +33,7 @@
 #include "lyxvc.h"
 #include "texrow.h"
 #include "vc-backend.h"
+#include "toc.h"
 
 #include "frontends/Alert.h"
 
@@ -513,8 +514,11 @@
        ParIterator & it)       
 {
     if (it == par_iterator_end(buf.inset()))
-        return true;
-       
+        return false;
+
+//     if (it.lastpit == 0 && LyXText::isMainText())
+//             return false;
+
        switch (it->layout()->labeltype) {
                
        case LABEL_NO_LABEL:
@@ -582,6 +586,8 @@
                // set the counter for this paragraph
                setLabel(buf, it);
        }
+
+       lyx::toc::updateToc(buf);
 }
 
 
Index: src/frontends/controllers/ControlToc.C
===================================================================
--- src/frontends/controllers/ControlToc.C      (revision 13695)
+++ src/frontends/controllers/ControlToc.C      (working copy)
@@ -52,18 +52,20 @@
 }
 
 
-vector<string> const ControlToc::getTypes() const
+vector<string> const & ControlToc::getTypes() const
 {
        return toc::getTypes(kernel().buffer());
 }
 
 
-toc::TocItem const ControlToc::getCurrentTocItem(
+toc::TocItem const invalid_toc_item;
+
+toc::TocItem const & ControlToc::getCurrentTocItem(
        string const & type) const
 {
        BufferView const * const bv = kernel().bufferview();
        if (!bv)
-               return toc::TocItem(-1, -1, "");
+               return invalid_toc_item;
 
        return toc::getCurrentTocItem(kernel().buffer(), bv->cursor(), type);
 }
@@ -78,22 +80,16 @@
 }
 
 
-toc::Toc const ControlToc::getContents(string const & type) const
-{
-       toc::Toc empty_list;
+toc::Toc const empty_list;
 
+toc::Toc const & ControlToc::getContents(string const & type) const
+{
        // This shouldn't be possible...
        if (!kernel().isBufferAvailable()) {
                return empty_list;
        }
 
-       toc::TocList tmp = toc::getTocList(kernel().buffer());
-       toc::TocList::iterator it = tmp.find(type);
-       if (it == tmp.end()) {
-               return empty_list;
-       }
-
-       return it->second;
+       return toc::getToc(kernel().buffer(), type);
 }
 
 } // namespace frontend
Index: src/frontends/controllers/ControlToc.h
===================================================================
--- src/frontends/controllers/ControlToc.h      (revision 13695)
+++ src/frontends/controllers/ControlToc.h      (working copy)
@@ -31,17 +31,17 @@
        void goTo(toc::TocItem const &);
 
        /// Return the list of types available
-       std::vector<std::string> const getTypes() const;
+       std::vector<std::string> const & getTypes() const;
 
        /// Return the guiname from a given cmdName of the TOC param
        std::string const getGuiName(std::string const & type) const;
 
        /// Return the first TocItem before the cursor
-       toc::TocItem const getCurrentTocItem(
+       toc::TocItem const & getCurrentTocItem(
                std::string const & type) const;
 
        /// Given a type, returns the contents
-       toc::Toc const getContents(std::string const & type) const;
+       toc::Toc const & getContents(std::string const & type) const;
 
        /// Apply the selected outlining operation
        void outline(toc::OutlineOp op);
Index: src/frontends/qt4/QToc.C
===================================================================
--- src/frontends/qt4/QToc.C    (revision 13695)
+++ src/frontends/qt4/QToc.C    (working copy)
@@ -76,17 +76,14 @@
 QModelIndex const QToc::getCurrentIndex()
 {
        vector<string> const & types = getTypes();
-       toc::TocItem const item = getCurrentTocItem(types[type_]);
-       if (item.id_ == -1) {
+       toc::TocItem const & item = getCurrentTocItem(types[type_]);
+       if (!item.isValid()) {
                lyxerr[Debug::GUI]
                        << "QToc::getCurrentIndex(): TocItem is invalid!" << 
endl;
                return QModelIndex();
        }
 
-       string toc_str = item.str;
-       toc_str.erase(0, toc_str.find(' ') + 1);
-
-       return toc_models_[type_]->index(toc_str);
+       return toc_models_[type_]->index(item.uid());
 }
 
 
@@ -139,27 +136,22 @@
 
 void QToc::updateToc(int type)
 {
-       vector<string> const & choice = getTypes();
-
-       toc_models_[type] = new TocModel(getContents(choice[type]));
+       toc_models_[type] = new TocModel(getContents(getTypes()[type]));
 }
 
 
 void QToc::move(toc::OutlineOp const operation, QModelIndex & index)
 {
-       int toc_id = toc_models_[type_]->item(index).id_;
-       string toc_str = toc_models_[type_]->item(index).str;
-       toc_str.erase(0, toc_str.find(' ') + 1);
+       string item_id = toc_models_[type_]->item(index).uid();
 
        outline(operation);
        updateToc(type_);
 
        lyxerr[Debug::GUI]
-               << "Toc id " << toc_id
-               << "  Toc str " << toc_str
+               << "Toc uid " << item_id
                << endl;
 
-       index = toc_models_[type_]->index(toc_str);
+       index = toc_models_[type_]->index(item_id);
 }
 
 } // namespace frontend
Index: src/frontends/qt4/TocModel.C
===================================================================
--- src/frontends/qt4/TocModel.C        (revision 13695)
+++ src/frontends/qt4/TocModel.C        (working copy)
@@ -26,7 +26,6 @@
 namespace lyx {
 namespace frontend {
 
-
 TocModel::TocModel(toc::Toc const & toc_list)
 {
        populate(toc_list);
@@ -42,7 +41,8 @@
 toc::TocItem const TocModel::item(QModelIndex const & index) const
 {
        ItemMap::const_iterator it = item_map_.find(index);
-       BOOST_ASSERT(it != item_map_.end());
+       if (it == item_map_.end())
+               return toc::TocItem();
        
        return it->second;
 }
@@ -85,7 +85,7 @@
 
        while (iter != end) {
 
-               if (iter->depth == 1) {
+               if (iter->depth >= 1) {
 
                        current_row = rowCount();
                        insertRows(current_row, 1);
@@ -93,8 +93,7 @@
                        //setData(top_level_item, toqstr(iter->str));
                        setData(top_level_item, toqstr(iter->str), 
Qt::DisplayRole);
                        item_map_.insert(make_pair(top_level_item, *iter));
-                       index_map_.insert(make_pair(
-                               iter->str.substr(iter->str.find(' ') + 1), 
top_level_item));
+                       index_map_.insert(make_pair(iter->uid(), 
top_level_item));
 
                        lyxerr[Debug::GUI]
                                << "Toc: at depth " << iter->depth
@@ -145,8 +144,7 @@
                //setData(child_item, toqstr(iter->str));
                setData(child_item, toqstr(iter->str), Qt::DisplayRole);
                item_map_.insert(make_pair(child_item, *iter));
-               index_map_.insert(make_pair(
-                       iter->str.substr(iter->str.find(' ') + 1), child_item));
+               index_map_.insert(make_pair(iter->uid(), child_item));
 
 //             lyxerr[Debug::GUI]
 //                     << "Toc: at depth " << iter->depth
Index: src/insets/insetfloat.C
===================================================================
--- src/insets/insetfloat.C     (revision 13695)
+++ src/insets/insetfloat.C     (working copy)
@@ -438,7 +438,7 @@
                        string const str =
                                convert<string>(toclist[type].size() + 1)
                                + ". " + pit->asString(buf, false);
-                       lyx::toc::TocItem const item(pit->id(), 0 , str);
+                       lyx::toc::TocItem const item(pit->id(), 0 , str, pit);
                        toclist[type].push_back(item);
                }
        }
Index: src/insets/insetwrap.C
===================================================================
--- src/insets/insetwrap.C      (revision 13695)
+++ src/insets/insetwrap.C      (working copy)
@@ -246,7 +246,7 @@
                        string const str =
                                convert<string>(toclist[type].size() + 1)
                                + ". " + pit->asString(buf, false);
-                       lyx::toc::TocItem const item(pit->id(), 0 , str);
+                       lyx::toc::TocItem const item(pit->id(), 0 , str, pit);
                        toclist[type].push_back(item);
                }
        }
Index: src/Makefile.am
===================================================================
--- src/Makefile.am     (revision 13695)
+++ src/Makefile.am     (working copy)
@@ -280,6 +280,8 @@
        text.C \
        text2.C \
        text3.C \
+       TocBackend.C \
+       TocBackend.h \
        toc.C \
        toc.h \
        trans.C \
Index: src/MenuBackend.C
===================================================================
--- src/MenuBackend.C   (revision 13695)
+++ src/MenuBackend.C   (working copy)
@@ -681,7 +681,7 @@
        }
 
        FloatList const & floatlist = buf->params().getLyXTextClass().floats();
-       lyx::toc::TocList toc_list = lyx::toc::getTocList(*buf);
+       lyx::toc::TocList const & toc_list = lyx::toc::getTocList(*buf);
        lyx::toc::TocList::const_iterator cit = toc_list.begin();
        lyx::toc::TocList::const_iterator end = toc_list.end();
        for (; cit != end; ++cit) {
Index: src/pariterator.h
===================================================================
--- src/pariterator.h   (revision 13695)
+++ src/pariterator.h   (working copy)
@@ -93,6 +93,8 @@
 {
 public:
        ///
+       ParConstIterator(): DocIterator() {}
+       ///
        ParConstIterator(ParConstIterator const &);
        ///
        ParConstIterator(DocIterator const &);
Index: src/toc.C
===================================================================
--- src/toc.C   (revision 13695)
+++ src/toc.C   (working copy)
@@ -31,181 +31,101 @@
 
 #include "support/convert.h"
 
+#include <iostream>
+#include <map>
+
+using std::map;
+using std::pair;
+using std::make_pair;
 using std::vector;
 using std::max;
 using std::ostream;
 using std::string;
+using std::cout;
+using std::endl;
 
 namespace lyx {
 namespace toc {
 
-string const TocItem::asString() const
-{
-       return string(4 * depth, ' ') + str;
-}
+typedef map<Buffer const *, lyx::TocBackend> TocMap;
+static TocMap toc_backend_;
 
+///////////////////////////////////////////////////////////////////////////
+// Interface to toc_backend_
 
-void TocItem::goTo(LyXView & lv_) const
+void updateToc(Buffer const & buf)
 {
-       string const tmp = convert<string>(id_);
-       lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp));
-}
+       TocMap::iterator it = toc_backend_.find(&buf);
+       if (it == toc_backend_.end()) {
+               pair<TocMap::iterator, bool> result
+                       = toc_backend_.insert(make_pair(&buf, 
TocBackend(&buf)));
+               if (!result.second)
+                       return;
 
+               it = result.first;
+       }
 
-FuncRequest TocItem::action() const
-{
-       return FuncRequest(LFUN_GOTO_PARAGRAPH, convert<string>(id_));
+       it->second.update();
 }
 
 
-string const getType(string const & cmdName)
+TocList const & getTocList(Buffer const & buf)
 {
-       // special case
-       if (cmdName == "tableofcontents")
-               return "TOC";
-       else
-               return cmdName;
+       return toc_backend_[&buf].tocs();
 }
 
 
-string const getGuiName(string const & type, Buffer const & buffer)
+Toc const & getToc(Buffer const & buf, std::string const & type)
 {
-       FloatList const & floats =
-               buffer.params().getLyXTextClass().floats();
-       if (floats.typeExist(type))
-               return floats.getType(type).name();
-       else
-               return type;
+       return toc_backend_[&buf].toc(type);
 }
 
 
-TocList const getTocList(Buffer const & buf)
+TocItem const & getCurrentTocItem(Buffer const & buf, LCursor const & cur,
+                                                               std::string 
const & type)
 {
-       TocList toclist;
-
-       BufferParams const & bufparams = buf.params();
-       const int min_toclevel = bufparams.getLyXTextClass().min_toclevel();
-
-       ParConstIterator pit = buf.par_iterator_begin();
-       ParConstIterator end = buf.par_iterator_end();
-       for (; pit != end; ++pit) {
-
-               // the string that goes to the toc (could be the optarg)
-               string tocstring;
-
-               // For each paragraph, traverse its insets and look for
-               // FLOAT_CODE or WRAP_CODE
-               InsetList::const_iterator it = pit->insetlist.begin();
-               InsetList::const_iterator end = pit->insetlist.end();
-               for (; it != end; ++it) {
-                       switch (it->inset->lyxCode()) {
-                       case InsetBase::FLOAT_CODE:
-                               static_cast<InsetFloat*>(it->inset)
-                                       ->addToToc(toclist, buf);
-                               break;
-                       case InsetBase::WRAP_CODE:
-                               static_cast<InsetWrap*>(it->inset)
-                                       ->addToToc(toclist, buf);
-                               break;
-                       case InsetBase::OPTARG_CODE: {
-                               if (!tocstring.empty())
-                                       break;
-                               Paragraph const & par = 
*static_cast<InsetOptArg*>(it->inset)->paragraphs().begin();
-                               if (!pit->getLabelstring().empty())
-                                       tocstring = pit->getLabelstring()
-                                               + ' ';
-                               tocstring += par.asString(buf, false);
-                               break;
-                       }
-                       default:
-                               break;
-                       }
-               }
-
-               /// now the toc entry for the paragraph
-               int const toclevel = pit->layout()->toclevel;
-               if (toclevel != LyXLayout::NOT_IN_TOC
-                   && toclevel >= min_toclevel
-                   && toclevel <= bufparams.tocdepth) {
-                       // insert this into the table of contents
-                       if (tocstring.empty())
-                               tocstring = pit->asString(buf, true);
-                       TocItem const item(pit->id(), toclevel - min_toclevel,
-                                          tocstring);
-                       toclist["TOC"].push_back(item);
-               }
-       }
-       return toclist;
+       return toc_backend_[&buf].item(type, ParConstIterator(cur));
 }
 
 
-TocItem const getCurrentTocItem(Buffer const & buf, LCursor const & cur,
-                                                               std::string 
const & type)
+vector<string> const & getTypes(Buffer const & buf)
 {
-       // This should be cached:
-       TocList tmp = getTocList(buf);
+       return toc_backend_[&buf].types();
+}
 
-       // Is the type supported?
-       /// \todo TocItem() should create an invalid TocItem()
-       /// \todo create TocItem::isValid()
-       TocList::iterator toclist_it = tmp.find(type);
-       if (toclist_it == tmp.end())
-               return TocItem(-1, -1, string());
 
-       Toc const toc_vector = toclist_it->second;
-       ParConstIterator const current(cur);
-       int start = toc_vector.size() - 1;
-
-       /// \todo cache the ParConstIterator values inside TocItem
-       for (int i = start; i >= 0; --i) {
-               
-               ParConstIterator const it 
-                       = buf.getParFromID(toc_vector[i].id_);
-
-               // A good solution for TocItems inside insets would be to do:
-               //
-               //if (std::distance(it, current) <= 0)
-               //      return toc_vector[i];
-               //
-               // But for an unknown reason, std::distance(current, it) always
-               // returns  a positive value and std::distance(it, current) 
takes forever...
-               // So for now, we do:
-               if (it.pit() <= current.pit())
-                       return toc_vector[i];
-       }
-
-       // We are before the first TocItem:
-       return toc_vector[0];
+void asciiTocList(string const & type, Buffer const & buf, ostream & os)
+{
+       toc_backend_[&buf].asciiTocList(type, os);
 }
 
+///////////////////////////////////////////////////////////////////////////
+// Other functions
 
-vector<string> const getTypes(Buffer const & buffer)
+FuncRequest TocItem::action() const
 {
-       vector<string> types;
+       return FuncRequest(LFUN_GOTO_PARAGRAPH, convert<string>(id_));
+}
 
-       TocList const tmp = getTocList(buffer);
 
-       TocList::const_iterator cit = tmp.begin();
-       TocList::const_iterator end = tmp.end();
-
-       for (; cit != end; ++cit) {
-               types.push_back(cit->first);
-       }
-
-       return types;
+string const getType(string const & cmdName)
+{
+       // special case
+       if (cmdName == "tableofcontents")
+               return "TOC";
+       else
+               return cmdName;
 }
 
 
-void asciiTocList(string const & type, Buffer const & buffer, ostream & os)
+string const getGuiName(string const & type, Buffer const & buffer)
 {
-       TocList const toc_list = getTocList(buffer);
-       TocList::const_iterator cit = toc_list.find(type);
-       if (cit != toc_list.end()) {
-               Toc::const_iterator ccit = cit->second.begin();
-               Toc::const_iterator end = cit->second.end();
-               for (; ccit != end; ++ccit)
-                       os << ccit->asString() << '\n';
-       }
+       FloatList const & floats =
+               buffer.params().getLyXTextClass().floats();
+       if (floats.typeExist(type))
+               return floats.getType(type).name();
+       else
+               return type;
 }
 
 
Index: src/toc.h
===================================================================
--- src/toc.h   (revision 13695)
+++ src/toc.h   (working copy)
@@ -15,54 +15,31 @@
 #ifndef TOC_H
 #define TOC_H
 
-#include <map>
-#include <iosfwd>
-#include <vector>
-#include <string>
+#include "TocBackend.h"
 
-#include "pariterator.h"
-
-class Buffer;
-class LyXView;
-class Paragraph;
-class FuncRequest;
 class LCursor;
 
 namespace lyx {
 namespace toc {
 
+typedef TocBackend::Item TocItem;
+typedef TocBackend::Toc Toc;
+typedef TocBackend::TocList TocList;
+
 ///
-class TocItem {
-public:
-       TocItem(int par_id, int d, std::string const & s)
-               : id_(par_id), depth(d), str(s) {}
-       ///
-       std::string const asString() const;
-       /// set cursor in LyXView to this TocItem
-       void goTo(LyXView & lv_) const;
-       /// the action corresponding to the goTo above
-       FuncRequest action() const;
-       /// Paragraph ID containing this item
-       int id_;
-       /// nesting depth
-       int depth;
-       ///
-       std::string str;
-};
+void updateToc(Buffer const &);
 
 ///
-typedef std::vector<TocItem> Toc;
-///
-typedef std::map<std::string, Toc> TocList;
+TocList const & getTocList(Buffer const &);
 
 ///
-TocList const getTocList(Buffer const &);
+Toc const & getToc(Buffer const & buf, std::string const & type);
 
 ///
-std::vector<std::string> const getTypes(Buffer const &);
+std::vector<std::string> const & getTypes(Buffer const &);
 
 /// Return the first TocItem before the cursor
-TocItem const getCurrentTocItem(Buffer const &, LCursor const &,
+TocItem const & getCurrentTocItem(Buffer const &, LCursor const &,
                                                                std::string 
const & type);
 
 ///
@@ -76,21 +53,6 @@
     The localization of the names will be done in the frontends */
 std::string const getGuiName(std::string const & type, Buffer const &);
 
-inline
-bool operator==(TocItem const & a, TocItem const & b)
-{
-       return a.id_ == b.id_ && a.str == b.str;
-       // No need to compare depth.
-}
-
-
-inline
-bool operator!=(TocItem const & a, TocItem const & b)
-{
-       return !(a == b);
-}
-
-
 /// the type of outline operation
 enum OutlineOp {
        UP, // Move this header with text down
Index: src/TocBackend.C
===================================================================
--- src/TocBackend.C    (revision 0)
+++ src/TocBackend.C    (revision 0)
@@ -0,0 +1,227 @@
+/**
+ * \file TocBackend.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Jean-Marc Lasgouttes
+ * \author Angus Leeming
+ * \author Abdelrazak Younes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "toc.h"
+
+#include "buffer.h"
+#include "bufferparams.h"
+#include "FloatList.h"
+#include "funcrequest.h"
+#include "LyXAction.h"
+#include "paragraph.h"
+#include "cursor.h"
+#include "debug.h"
+
+#include "frontends/LyXView.h"
+
+#include "insets/insetfloat.h"
+#include "insets/insetoptarg.h"
+#include "insets/insetwrap.h"
+
+#include "support/convert.h"
+
+#include <iostream>
+
+using std::vector;
+using std::max;
+using std::ostream;
+using std::string;
+using std::cout;
+using std::endl;
+
+namespace lyx {
+
+///////////////////////////////////////////////////////////////////////////
+// TocBackend::Item implementation
+
+TocBackend::Item::Item(int par_id,     int d, std::string const & s,
+                                          ParConstIterator const & par_it,
+                                          std::string const & uid)
+               : depth(d), str(s), id_(par_id), par_it_(par_it), uid_(uid)
+{
+       if (!uid_.empty())
+               return;
+
+       size_t pos = s.find(" ");
+       if (pos == string::npos) {
+               // Non labelled item
+               uid_ = s;
+               return;
+       }
+
+       string s2 = s.substr(0, pos);
+
+       if (s2 == "Chapter" || s2 == "Part") {
+               size_t pos2 = s.find(" ", pos + 1);
+               if (pos2 == string::npos) {
+                       // Unnumbered Chapter?? This should not happen.
+                       uid_ = s.substr(pos + 1);
+                       return;
+               }
+               // Chapter or Part
+               uid_ = s.substr(pos2 + 1);
+               return;
+       }
+       // Numbered Item.
+       uid_ = s.substr(pos + 1);
+}
+
+
+string const TocBackend::Item::asString() const
+{
+       return string(4 * depth, ' ') + str;
+}
+
+
+void TocBackend::Item::goTo(LyXView & lv_) const
+{
+       string const tmp = convert<string>(id_);
+       lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp));
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+// TocBackend implementation
+
+TocBackend::Toc const & TocBackend::toc(std::string const & type)
+{
+       // Is the type already supported?
+       TocList::const_iterator it = tocs_.find(type);
+       if (it == tocs_.end())
+               return empty_toc_;
+
+       return it->second;
+}
+
+
+bool TocBackend::addType(std::string const & type)
+{
+       // Is the type already supported?
+       TocList::iterator toclist_it = tocs_.find(type);
+       if (toclist_it != tocs_.end())
+               return false;
+
+       tocs_.insert(make_pair(type, Toc()));
+       types_.push_back(type);
+}
+
+
+void TocBackend::update()
+{
+       tocs_.clear();
+       types_.clear();
+
+       BufferParams const & bufparams = buffer_->params();
+       const int min_toclevel = bufparams.getLyXTextClass().min_toclevel();
+
+       ParConstIterator pit = buffer_->par_iterator_begin();
+       ParConstIterator end = buffer_->par_iterator_end();
+       for (; pit != end; ++pit) {
+
+               // the string that goes to the toc (could be the optarg)
+               string tocstring;
+
+               // For each paragraph, traverse its insets and look for
+               // FLOAT_CODE or WRAP_CODE
+               InsetList::const_iterator it = pit->insetlist.begin();
+               InsetList::const_iterator end = pit->insetlist.end();
+               for (; it != end; ++it) {
+                       switch (it->inset->lyxCode()) {
+                       case InsetBase::FLOAT_CODE:
+                               static_cast<InsetFloat*>(it->inset)
+                                       ->addToToc(tocs_, *buffer_);
+                               break;
+                       case InsetBase::WRAP_CODE:
+                               static_cast<InsetWrap*>(it->inset)
+                                       ->addToToc(tocs_, *buffer_);
+                               break;
+                       case InsetBase::OPTARG_CODE: {
+                               if (!tocstring.empty())
+                                       break;
+                               Paragraph const & par = 
*static_cast<InsetOptArg*>(it->inset)->paragraphs().begin();
+                               if (!pit->getLabelstring().empty())
+                                       tocstring = pit->getLabelstring()
+                                               + ' ';
+                               tocstring += par.asString(*buffer_, false);
+                               break;
+                       }
+                       default:
+                               break;
+                       }
+               }
+
+               /// now the toc entry for the paragraph
+               int const toclevel = pit->layout()->toclevel;
+               if (toclevel != LyXLayout::NOT_IN_TOC
+                   && toclevel >= min_toclevel
+                   && toclevel <= bufparams.tocdepth) {
+                       // insert this into the table of contents
+                       if (tocstring.empty())
+                               tocstring = pit->asString(*buffer_, true);
+                       Item const item(pit->id(), toclevel - min_toclevel,
+                                          tocstring, pit, 
pit->asString(*buffer_, false));
+                       tocs_["TOC"].push_back(item);
+                       cout << "item inserted str " << item.str
+                               << "  uid " << item.uid_ << endl;
+               }
+       }
+
+       TocList::iterator it = tocs_.begin();
+       for (; it != tocs_.end(); ++it)
+               types_.push_back(it->first);
+}
+
+
+TocBackend::Item const & TocBackend::item(std::string const & type, 
ParConstIterator const & par_it)
+{
+       // Is the type supported?
+       TocList::iterator toclist_it = tocs_.find(type);
+       if (toclist_it == tocs_.end())
+               return invalid_item_;
+
+       Toc const & toc_vector = toclist_it->second;
+       int start = toc_vector.size() - 1;
+
+       for (int i = start; i >= 0; --i) {
+               
+               // A good solution for Items inside insets would be to do:
+               //
+               //if (std::distance(it, current) <= 0)
+               //      return toc_vector[i];
+               //
+               // But for an unknown reason, std::distance(current, it) always
+               // returns  a positive value and std::distance(it, current) 
takes forever...
+               // So for now, we do:
+               if (toc_vector[i].par_it_.pit() <= par_it.pit())
+                       return toc_vector[i];
+       }
+
+       // We are before the first Toc Item:
+       return toc_vector[0];
+}
+
+
+void TocBackend::asciiTocList(std::string const & type, ostream & os)
+{
+       TocList::const_iterator cit = tocs_.find(type);
+       if (cit != tocs_.end()) {
+               Toc::const_iterator ccit = cit->second.begin();
+               Toc::const_iterator end = cit->second.end();
+               for (; ccit != end; ++ccit)
+                       os << ccit->asString() << '\n';
+       }
+}
+
+
+} // namespace lyx
Index: src/TocBackend.h
===================================================================
--- src/TocBackend.h    (revision 0)
+++ src/TocBackend.h    (revision 0)
@@ -0,0 +1,146 @@
+// -*- C++ -*-
+/**
+ * \file TocBackend.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Jean-Marc Lasgouttes
+ * \author Angus Leeming
+ * \author Abdelrazak Younes
+ *
+ * Full author contact details are available in file CREDITS.
+ *
+ * TocBackend mainly used in toc.[Ch]
+ */
+
+#ifndef TOC_BACKEND_H
+#define TOC_BACKEND_H
+
+#include <map>
+#include <iosfwd>
+#include <vector>
+#include <string>
+
+#include "pariterator.h"
+
+class Buffer;
+class LyXView;
+class Paragraph;
+class FuncRequest;
+class LCursor;
+
+namespace lyx {
+
+///
+/**
+*/
+class TocBackend
+{
+public:
+
+       ///
+       /**
+       */
+       class Item
+       {
+               friend class TocBackend;
+               friend bool operator==(Item const & a, Item const & b);
+
+       public:
+               ///
+               Item(
+                       int par_id = -1, 
+                       int d = -1,
+                       std::string const & s = std::string(),
+                       ParConstIterator const & par_it = ParConstIterator(),
+                       std::string const & uid = std::string());
+               ///
+               ~Item() {}
+               ///
+               bool isValid() const
+               { return id_ != -1; }
+               ///
+               std::string const & uid() const
+               { return uid_; }
+               ///
+               std::string const asString() const;
+               /// set cursor in LyXView to this Item
+               void goTo(LyXView & lv_) const;
+               /// the action corresponding to the goTo above
+               FuncRequest action() const;
+               /// nesting depth
+               int depth;
+               /// Full item string
+               std::string str;
+               
+       protected:
+               /// Paragraph ID containing this item
+               int id_;
+               /// Unique identifier.
+               std::string uid_;
+               /// Current position of item.
+               ParConstIterator par_it_;
+       }; // Item
+
+       ///
+       typedef std::vector<Item> Toc;
+       ///
+       typedef std::map<std::string, Toc> TocList;
+
+public:
+       ///
+       TocBackend(Buffer const * buffer = NULL): buffer_(buffer) {}
+       ///
+       ~TocBackend() {}
+       ///
+       void setBuffer(Buffer const * buffer)
+       { buffer_ = buffer; }
+       ///
+       bool addType(std::string const & type);
+       ///
+       void update();
+       ///
+       TocList const & tocs()
+       { return tocs_; }
+       ///
+       std::vector<std::string> const & types()
+       { return types_; }
+       ///
+       Toc const & toc(std::string const & type);
+       /// Return the first Toc Item before the cursor
+       Item const & item(std::string const & type, ParConstIterator const &);
+
+       void asciiTocList(std::string const & type, std::ostream & os);
+
+private:
+       /// 
+       TocList tocs_;
+       ///
+       std::vector<std::string> types_;
+       ///
+       Item const invalid_item_;
+       ///
+       Toc const empty_toc_;
+       ///
+       Buffer const * buffer_;
+
+}; // TocBackend
+
+inline
+bool operator==(TocBackend::Item const & a, TocBackend::Item const & b)
+{
+       return a.id_ == b.id_ && a.str == b.str;
+       // No need to compare depth.
+}
+
+
+inline
+bool operator!=(TocBackend::Item const & a, TocBackend::Item const & b)
+{
+       return !(a == b);
+}
+
+
+} // namespace lyx
+
+#endif // TOC_BACKEND_H

Reply via email to