And with this yet another updated patch, the dialog will automatically update itself if a new section is created or modified or deleted... Even Microsoft Word doesn't do this correctly :-)

Abdel.

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)
@@ -16,6 +16,7 @@
 #include "funcrequest.h"
 #include "gettext.h"
 #include "BufferView.h"
+#include "debug.h"
 
 using std::vector;
 using std::string;
@@ -52,20 +53,19 @@
 }
 
 
-vector<string> const ControlToc::getTypes() const
+vector<string> const & ControlToc::getTypes() const
 {
        return toc::getTypes(kernel().buffer());
 }
 
 
-toc::TocItem const ControlToc::getCurrentTocItem(
+toc::TocIterator const ControlToc::getCurrentTocItem(
        string const & type) const
 {
-       BufferView const * const bv = kernel().bufferview();
-       if (!bv)
-               return toc::TocItem(-1, -1, "");
+       BOOST_ASSERT(kernel().bufferview());
 
-       return toc::getCurrentTocItem(kernel().buffer(), bv->cursor(), type);
+       return toc::getCurrentTocItem(kernel().buffer(),
+               kernel().bufferview()->cursor(), type);
 }
 
 
@@ -78,22 +78,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::TocIterator 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/qt2/QToc.C
===================================================================
--- src/frontends/qt2/QToc.C    (revision 13707)
+++ src/frontends/qt2/QToc.C    (working copy)
@@ -116,21 +116,21 @@
 
        for (toc::Toc::const_iterator iter = toclist.begin();
             iter != toclist.end(); ++iter) {
-               if (iter->depth == curdepth) {
+               if (iter->depth() == curdepth) {
                        // insert it after the last one we processed
                        if (!parent)
                                item = (last ? new 
QListViewItem(dialog_->tocLV,last) : new QListViewItem(dialog_->tocLV));
                        else
                                item = (last ? new QListViewItem(parent,last) : 
new QListViewItem(parent));
-               } else if (iter->depth > curdepth) {
-                       int diff = iter->depth - curdepth;
+               } else if (iter->depth() > curdepth) {
+                       int diff = iter->depth() - curdepth;
                        // first save old parent and last
                        while (diff--)
                                istack.push(pair< QListViewItem *, 
QListViewItem * >(parent,last));
                        item = (last ? new QListViewItem(last) : new 
QListViewItem(dialog_->tocLV));
                        parent = last;
                } else {
-                       int diff = curdepth - iter->depth;
+                       int diff = curdepth - iter->depth();
                        pair<QListViewItem *, QListViewItem * > top;
                        // restore context
                        while (diff--) {
@@ -148,20 +148,20 @@
 
                lyxerr[Debug::GUI]
                        << "Table of contents\n"
-                       << "Added item " << iter->str
-                       << " at depth " << iter->depth
+                       << "Added item " << iter->str()
+                       << " at depth " << iter->depth()
                        << ", previous sibling \""
                        << (last ? fromqstr(last->text(0)) : "0")
                        << "\", parent \""
                        << (parent ? fromqstr(parent->text(0)) : "0") << '"'
                        << endl;
-               item->setText(0, toqstr(iter->str));
-               item->setOpen(iter->depth < depth_);
-               curdepth = iter->depth;
+               item->setText(0, toqstr(iter->str()));
+               item->setOpen(iter->depth() < depth_);
+               curdepth = iter->depth();
                last = item;
 
                // Recognise part past the counter
-               if (iter->str.substr(iter->str.find(' ') + 1) == text_) {
+               if (iter->str().substr(iter->str().find(' ') + 1) == text_) {
                        if (selected_item == 0)
                                selected_item = item;
                        else
@@ -186,7 +186,7 @@
        toc::Toc::const_iterator iter = toclist.begin();
 
        for (; iter != toclist.end(); ++iter) {
-               if (iter->str == text)
+               if (iter->str() == text)
                        break;
        }
 
Index: src/frontends/qt4/QToc.C
===================================================================
--- src/frontends/qt4/QToc.C    (revision 13695)
+++ src/frontends/qt4/QToc.C    (working copy)
@@ -31,6 +31,7 @@
 namespace lyx {
 namespace frontend {
 
+
 QToc::QToc(Dialog & parent)
        : ControlToc(parent)
 {
@@ -76,17 +77,13 @@
 QModelIndex const QToc::getCurrentIndex()
 {
        vector<string> const & types = getTypes();
-       toc::TocItem const item = getCurrentTocItem(types[type_]);
-       if (item.id_ == -1) {
-               lyxerr[Debug::GUI]
-                       << "QToc::getCurrentIndex(): TocItem is invalid!" << 
endl;
+       TocIterator const it = getCurrentTocItem(types[type_]);
+       if (!it->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_]->modelIndex(it);
 }
 
 
@@ -98,12 +95,14 @@
                        << endl;
                return;
        }
+
+       TocIterator const it = toc_models_[type_]->tocIterator(index);
        
        lyxerr[Debug::GUI]
-               << "QToc::goTo " << toc_models_[type_]->item(index).str
+               << "QToc::goTo " << it->str()
                << endl;
 
-       ControlToc::goTo(toc_models_[type_]->item(index));
+       it->goTo(kernel().lyxview());
 }
 
 
@@ -139,27 +138,15 @@
 
 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)
+void QToc::move(toc::OutlineOp const operation)
 {
-       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);
-
        outline(operation);
-       updateToc(type_);
-
-       lyxerr[Debug::GUI]
-               << "Toc id " << toc_id
-               << "  Toc str " << toc_str
-               << endl;
-
-       index = toc_models_[type_]->index(toc_str);
+//     updateToc(type_);
+       update();
 }
 
 } // namespace frontend
Index: src/frontends/qt4/QToc.h
===================================================================
--- src/frontends/qt4/QToc.h    (revision 13695)
+++ src/frontends/qt4/QToc.h    (working copy)
@@ -48,7 +48,7 @@
        ///
        void goTo(QModelIndex const & index);
 
-       void move(toc::OutlineOp const operation, QModelIndex & index);
+       void move(toc::OutlineOp const operation);
 
 private:
 
Index: src/frontends/qt4/QTocDialog.C
===================================================================
--- src/frontends/qt4/QTocDialog.C      (revision 13695)
+++ src/frontends/qt4/QTocDialog.C      (working copy)
@@ -43,7 +43,7 @@
 {
        setupUi(this);
 
-       update();
+       updateGui();
 
        connect(tocTV->selectionModel(),
                SIGNAL(currentChanged(const QModelIndex &,
@@ -88,7 +88,6 @@
 
 void QTocDialog::on_updatePB_clicked()
 {
-       form_->update();
        update();
 }
 
@@ -103,9 +102,9 @@
 /*
        while (
        tocTv->setExpanded();
-                       if (iter->depth > depth_)
+                       if (iter->depth() > depth_)
                                tocTV->collapseItem(topLevelItem);
-                       else if (iter->depth <= depth_)
+                       else if (iter->depth() <= depth_)
                                tocTV->expandItem(topLevelItem);
 */
 }
@@ -147,14 +146,16 @@
        enableButtons(false);
        QModelIndex index = tocTV->selectionModel()->selectedIndexes()[0];
        form_->goTo(index);
-       form_->move(operation, index);
-       select(index);
-       enableButtons();
+       form_->move(operation);
+       updateGui();
+//     select(index);
+//     enableButtons();
 }
 
+
 void QTocDialog::select(QModelIndex const & index)
 {
-       tocTV->setModel(form_->tocModel());
+//     tocTV->setModel(form_->tocModel());
 
        if (!index.isValid()) {
                lyxerr[Debug::GUI]
@@ -166,6 +167,7 @@
        tocTV->selectionModel()->select(index, QItemSelectionModel::Select);
 }
 
+
 void QTocDialog::enableButtons(bool enable)
 {
        updatePB->setEnabled(enable);
@@ -182,6 +184,13 @@
 
 void QTocDialog::update()
 {
+       form_->update();
+       updateGui();
+}
+
+
+void QTocDialog::updateGui()
+{
        typeCO->setModel(form_->typeModel());
        tocTV->setModel(form_->tocModel());
        tocTV->showColumn(0);
@@ -223,7 +232,6 @@
 
 void QTocDialog::show()
 {
-       form_->update();
        update();
        QDialog::show();
 }
Index: src/frontends/qt4/QTocDialog.h
===================================================================
--- src/frontends/qt4/QTocDialog.h      (revision 13695)
+++ src/frontends/qt4/QTocDialog.h      (working copy)
@@ -46,6 +46,9 @@
        /// Update the display of the dialog whilst it is still visible.
        void update();
 
+       /// Update Gui of the display.
+       void updateGui();
+
        /// \return true if the dialog is visible.
        bool isVisible() const;
 
Index: src/frontends/qt4/TocModel.C
===================================================================
--- src/frontends/qt4/TocModel.C        (revision 13695)
+++ src/frontends/qt4/TocModel.C        (working copy)
@@ -25,80 +25,81 @@
 
 namespace lyx {
 namespace frontend {
+
 
-
-TocModel::TocModel(toc::Toc const & toc_list)
+TocModel::TocModel(TocBackend::Toc const & toc)
 {
-       populate(toc_list);
+       populate(toc);
 }
 
 
-TocModel const & TocModel::operator=(toc::Toc const & toc_list)
+TocModel const & TocModel::operator=(TocBackend::Toc const & toc)
 {
-       populate(toc_list);
+       populate(toc);
        return *this;
 }
+
 
-toc::TocItem const TocModel::item(QModelIndex const & index) const
+TocIterator const TocModel::tocIterator(QModelIndex const & index) const
 {
-       ItemMap::const_iterator it = item_map_.find(index);
-       BOOST_ASSERT(it != item_map_.end());
-       
-       return it->second;
+       TocMap::const_iterator map_it = toc_map_.find(index);
+       BOOST_ASSERT(map_it != toc_map_.end()); 
+       return map_it->second;
 }
+
 
-QModelIndex const TocModel::index(string const & toc_str) const
+QModelIndex const TocModel::modelIndex(TocIterator const & it) const
 {
-       IndexMap::const_iterator it = index_map_.find(toc_str);
-       //BOOST_ASSERT(it != index_map_.end());
+       ModelMap::const_iterator map_it = model_map_.find(it);
+       //BOOST_ASSERT(it != model_map_.end());
 
-       if (it == index_map_.end())
+       if (map_it == model_map_.end())
                return QModelIndex();
        
-       return it->second;
+       return map_it->second;
 }
+
 
 void TocModel::clear()
 {
        QStandardItemModel::clear();
-       item_map_.clear();
-       index_map_.clear();
+       toc_map_.clear();
+       model_map_.clear();
        removeRows(0, rowCount());
        removeColumns(0, columnCount());
 }
 
 
-void TocModel::populate(toc::Toc const & toc_list)
+void TocModel::populate(TocBackend::Toc const & toc)
 {
        clear();
 
-       if (toc_list.empty())
+       if (toc.empty())
                return;
 
        int current_row;
        QModelIndex top_level_item;
 
-       toc::Toc::const_iterator iter = toc_list.begin();
-       toc::Toc::const_iterator end = toc_list.end();
+       TocIterator iter = toc.begin();
+       TocIterator end = toc.end();
 
     insertColumns(0, 1);
 
        while (iter != end) {
 
-               if (iter->depth == 1) {
+               if (iter->depth() >= 1) {
 
                        current_row = rowCount();
                        insertRows(current_row, 1);
                        top_level_item = QStandardItemModel::index(current_row, 
0);
-                       //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));
+                       //setData(top_level_item, toqstr(iter->str()));
+                       setData(top_level_item, toqstr(iter->str()), 
Qt::DisplayRole);
+                       toc_map_.insert(make_pair(top_level_item, iter));
+                       model_map_.insert(make_pair(iter, top_level_item));
 
                        lyxerr[Debug::GUI]
-                               << "Toc: at depth " << iter->depth
-                               << ", added item " << iter->str
+                               << "Toc: at depth " << iter->depth()
+                               << ", added item " << iter->str()
                                << endl;
 
                        populate(iter, end, top_level_item);
@@ -115,11 +116,11 @@
 }
 
 
-void TocModel::populate(toc::Toc::const_iterator & iter,
-                                               toc::Toc::const_iterator const 
& end,
+void TocModel::populate(TocIterator & iter,
+                                               TocIterator const & end,
                                                QModelIndex const & parent)
 {
-       int curdepth = iter->depth + 1;
+       int curdepth = iter->depth() + 1;
        int current_row;
        QModelIndex child_item;
 
@@ -131,31 +132,31 @@
                if (iter == end)
                        break;
 
-               if (iter->depth < curdepth) {
+               if (iter->depth() < curdepth) {
                        --iter;
                        return;
                }
-               if (iter->depth > curdepth) {
+               if (iter->depth() > curdepth) {
                        return;
                }
                
                current_row = rowCount(parent);
                insertRows(current_row, 1, parent);
                child_item = QStandardItemModel::index(current_row, 0, parent);
-               //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));
+               //setData(child_item, toqstr(iter->str()));
+               setData(child_item, toqstr(iter->str()), Qt::DisplayRole);
+               toc_map_.insert(make_pair(child_item, iter));
+               model_map_.insert(make_pair(iter, child_item));
 
 //             lyxerr[Debug::GUI]
-//                     << "Toc: at depth " << iter->depth
-//                     << ", added item " << iter->str 
+//                     << "Toc: at depth " << iter->depth()
+//                     << ", added item " << iter->str()
 //                     << endl;
 
                populate(iter, end, child_item);
        }
 }
+
 
 } // namespace frontend
 } // namespace lyx
Index: src/frontends/qt4/TocModel.h
===================================================================
--- src/frontends/qt4/TocModel.h        (revision 13695)
+++ src/frontends/qt4/TocModel.h        (working copy)
@@ -12,7 +12,7 @@
 #ifndef TOCMODEL_H
 #define TOCMODEL_H
 
-#include "toc.h"
+#include "TocBackend.h"
 
 #include "qt_helpers.h"
 
@@ -24,38 +24,42 @@
 namespace lyx {
 namespace frontend {
 
+typedef TocBackend::Toc::const_iterator TocIterator;
+
 class TocModel: public QStandardItemModel {
        Q_OBJECT
+
 public:
        ///
        TocModel() {}
        ///
-       TocModel(toc::Toc const & toc_list);
+       TocModel(TocBackend::Toc const & toc);
        ///
        ~TocModel() {}
        ///
-       TocModel const & operator=(toc::Toc const & toc_list);
+       TocModel const & operator=(TocBackend::Toc const & toc);
        ///
        void clear();
        ///
-       void populate(toc::Toc const & toc_list);
+       void populate(TocBackend::Toc const & toc);
        ///
-       toc::TocItem const item(QModelIndex const & index) const;
+       TocIterator const tocIterator(QModelIndex const & index) const;
        ///
-       QModelIndex const index(std::string const & toc_str) const;
+       QModelIndex const modelIndex(TocIterator const & it) const;
 
 private:
        ///
-       void populate(toc::Toc::const_iterator & iter,
-               toc::Toc::const_iterator const & end,
-               QModelIndex const & parent);
-
-       typedef std::map<QModelIndex, toc::TocItem> ItemMap;
+       void populate(TocIterator & it,
+               TocIterator const & end,
+               QModelIndex const & parent);
        ///
-       typedef std::map<std::string, QModelIndex> IndexMap;
+       typedef std::map<QModelIndex, TocIterator> TocMap;
        ///
-       ItemMap item_map_;
-       IndexMap index_map_;
+       typedef std::map<TocIterator, QModelIndex> ModelMap;
+       ///
+       TocMap toc_map_;
+       ///
+       ModelMap model_map_;
 };
 
 } // namespace frontend
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, 0 , str);
                        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, 0 , str);
                        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)
@@ -615,16 +615,16 @@
        // check whether depth is smaller than the smallest depth in toc.
        int min_depth = 1000;
        for (lyx::toc::Toc::size_type i = from; i < to; ++i)
-               min_depth = std::min(min_depth, toc_list[i].depth);
+               min_depth = std::min(min_depth, toc_list[i].depth());
        if (min_depth > depth)
                depth = min_depth;
 
 
        if (to - from <= max_number_of_items) {
                for (lyx::toc::Toc::size_type i = from; i < to; ++i) {
-                       string label(4 * max(0, toc_list[i].depth - depth),' ');
-                       label += limit_string_length(toc_list[i].str);
-                       if (toc_list[i].depth == depth
+                       string label(4 * max(0, toc_list[i].depth() - depth),' 
');
+                       label += limit_string_length(toc_list[i].str());
+                       if (toc_list[i].depth() == depth
                            && shortcut_count < 9) {
                                if (label.find(convert<string>(shortcut_count + 
1)) != string::npos)
                                        label += '|' + 
convert<string>(++shortcut_count);
@@ -637,12 +637,12 @@
                while (pos < to) {
                        lyx::toc::Toc::size_type new_pos = pos + 1;
                        while (new_pos < to &&
-                              toc_list[new_pos].depth > depth)
+                              toc_list[new_pos].depth() > depth)
                                ++new_pos;
 
-                       string label(4 * max(0, toc_list[pos].depth - depth), ' 
');
-                       label += limit_string_length(toc_list[pos].str);
-                       if (toc_list[pos].depth == depth &&
+                       string label(4 * max(0, toc_list[pos].depth() - depth), 
' ');
+                       label += limit_string_length(toc_list[pos].str());
+                       if (toc_list[pos].depth() == depth &&
                            shortcut_count < 9) {
                                if (label.find(convert<string>(shortcut_count + 
1)) != string::npos)
                                        label += '|' + 
convert<string>(++shortcut_count);
@@ -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) {
@@ -694,7 +694,7 @@
                lyx::toc::Toc::const_iterator ccit = cit->second.begin();
                lyx::toc::Toc::const_iterator eend = cit->second.end();
                for (; ccit != eend; ++ccit) {
-                       string const label = limit_string_length(ccit->str);
+                       string const label = limit_string_length(ccit->str());
                        menu->add(MenuItem(MenuItem::Command,
                                           label,
                                           FuncRequest(ccit->action())));
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,95 @@
 
 #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)
+TocIterator 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);
-
-       // 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];
+       return toc_backend_[&buf].types();
 }
 
 
-vector<string> const getTypes(Buffer const & buffer)
+void asciiTocList(string const & type, Buffer const & buf, ostream & os)
 {
-       vector<string> types;
+       toc_backend_[&buf].asciiTocList(type, os);
+}
 
-       TocList const tmp = getTocList(buffer);
+///////////////////////////////////////////////////////////////////////////
+// Other functions
 
-       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,55 +15,33 @@
 #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::const_iterator TocIterator;
+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 &,
-                                                               std::string 
const & type);
+TocIterator const getCurrentTocItem(Buffer const &, LCursor const &,
+                                                                         
std::string const & type);
 
 ///
 void asciiTocList(std::string const &, Buffer const &, std::ostream &);
@@ -76,21 +54,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,261 @@
+/**
+ * \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(ParConstIterator const & par_it, int d,
+                                          std::string const & s)
+               : par_it_(par_it), depth_(d), str_(s)
+{
+/*
+       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);
+       */
+}
+
+bool const TocBackend::Item::isValid() const
+{
+       return depth_ != -1;
+}
+
+
+int const TocBackend::Item::id() const
+{
+       return par_it_->id();
+}
+
+
+int const TocBackend::Item::depth() const
+{
+       return depth_;
+}
+
+
+std::string const & TocBackend::Item::str() const
+{
+       return str_;
+}
+
+
+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));
+}
+
+FuncRequest TocBackend::Item::action() const
+{
+       return FuncRequest(LFUN_GOTO_PARAGRAPH, convert<string>(id()));
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+// 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);
+
+       return true;
+}
+
+
+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, toclevel - min_toclevel, 
tocstring);
+                       tocs_["TOC"].push_back(item);
+                       //cout << "item inserted str " << item.str()
+                       //      << "  id " << item.id() << endl;
+               }
+       }
+
+       TocList::iterator it = tocs_.begin();
+       for (; it != tocs_.end(); ++it)
+               types_.push_back(it->first);
+}
+
+
+TocBackend::TocIterator const TocBackend::item(std::string const & type, 
ParConstIterator const & par_it)
+{
+       TocList::iterator toclist_it = tocs_.find(type);
+       // Is the type supported?
+       BOOST_ASSERT(toclist_it != tocs_.end());
+
+       Toc const & toc_vector = toclist_it->second;
+       TocBackend::TocIterator last = toc_vector.begin();
+       TocBackend::TocIterator it = toc_vector.end();
+       --it;
+
+       for (; it != last; --it) {
+               
+               // A good solution for Items inside insets would be to do:
+               //
+               //if (std::distance(it->par_it_, current) <= 0)
+               //      return it;
+               //
+               // But for an unknown reason, std::distance(current, 
it->par_it_) always
+               // returns  a positive value and std::distance(it->par_it_, 
current) takes forever...
+               // So for now, we do:
+               if (it->par_it_.pit() <= par_it.pit())
+                       return it;
+       }
+
+       // We are before the first Toc Item:
+       return last;
+}
+
+
+void TocBackend::asciiTocList(string const & type, ostream & os) const
+{
+       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,145 @@
+// -*- 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(
+                       ParConstIterator const & par_it = ParConstIterator(),
+                       int d = -1,
+                       std::string const & s = std::string());
+               ///
+               ~Item() {}
+               ///
+               bool const isValid() const;
+               ///
+               int const id() const;
+               ///
+               int const depth() const;
+               ///
+               std::string const & str() const;
+               ///
+               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;
+               
+       protected:
+               /// Current position of item.
+               ParConstIterator par_it_;
+
+               /// nesting depth
+               int depth_;
+
+               /// Full item string
+               std::string str_;
+       };
+
+       ///
+       typedef std::vector<Item> Toc;
+       typedef std::vector<Item>::const_iterator TocIterator;
+       ///
+       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
+       TocIterator const item(std::string const & type, ParConstIterator const 
&);
+
+       void asciiTocList(std::string const & type, std::ostream & os) const;
+
+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