From 8c0bd3a77b521f356a406ffef056e518869f19bc Mon Sep 17 00:00:00 2001 From: Abdelrazak Younes Date: Sat, 22 Apr 2006 18:48:28 +0000 Subject: [PATCH] * 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 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. * qt4/TocPanel.[Ch]: - optimisation of the API by using const reference instead of copy - directly use of TocBackend::TocIterator instead of identification by paragraph contents. * qt4/QToc.C: - optimisation of the API by using const reference instead of copy - makes use of TocBackend::Item::uid() * qt2/QToc.C: - use TocItem::depth() and TocItem::str() instead of public member access. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@13713 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Makefile.am | 2 + src/MenuBackend.C | 20 +- src/TocBackend.C | 261 +++++++++++++++++++++++++ src/TocBackend.h | 145 ++++++++++++++ src/buffer_funcs.C | 10 +- src/frontends/controllers/ControlToc.C | 26 +-- src/frontends/controllers/ControlToc.h | 6 +- src/frontends/qt2/QToc.C | 22 +-- src/frontends/qt4/QToc.C | 39 ++-- src/frontends/qt4/QToc.h | 2 +- src/frontends/qt4/QTocDialog.C | 26 ++- src/frontends/qt4/QTocDialog.h | 3 + src/frontends/qt4/TocModel.C | 83 ++++---- src/frontends/qt4/TocModel.h | 32 +-- src/insets/insetfloat.C | 2 +- src/insets/insetwrap.C | 2 +- src/pariterator.h | 2 + src/toc.C | 186 +++++------------- src/toc.h | 61 ++---- 19 files changed, 610 insertions(+), 320 deletions(-) create mode 100644 src/TocBackend.C create mode 100644 src/TocBackend.h diff --git a/src/Makefile.am b/src/Makefile.am index 76d8526de3..8920c7320b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -280,6 +280,8 @@ lyx_SOURCES = \ text.C \ text2.C \ text3.C \ + TocBackend.C \ + TocBackend.h \ toc.C \ toc.h \ trans.C \ diff --git a/src/MenuBackend.C b/src/MenuBackend.C index 22ea282f91..18dd074323 100644 --- a/src/MenuBackend.C +++ b/src/MenuBackend.C @@ -615,16 +615,16 @@ void expandToc2(Menu & tomenu, // 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(shortcut_count + 1)) != string::npos) label += '|' + convert(++shortcut_count); @@ -637,12 +637,12 @@ void expandToc2(Menu & tomenu, 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(shortcut_count + 1)) != string::npos) label += '|' + convert(++shortcut_count); @@ -681,7 +681,7 @@ void expandToc(Menu & tomenu, LyXView const * view) } 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 @@ void expandToc(Menu & tomenu, LyXView const * view) 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()))); diff --git a/src/TocBackend.C b/src/TocBackend.C new file mode 100644 index 0000000000..39af8532a9 --- /dev/null +++ b/src/TocBackend.C @@ -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 + +#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 + +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(id()); + lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp)); +} + +FuncRequest TocBackend::Item::action() const +{ + return FuncRequest(LFUN_GOTO_PARAGRAPH, convert(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(it->inset) + ->addToToc(tocs_, *buffer_); + break; + case InsetBase::WRAP_CODE: + static_cast(it->inset) + ->addToToc(tocs_, *buffer_); + break; + case InsetBase::OPTARG_CODE: { + if (!tocstring.empty()) + break; + Paragraph const & par = *static_cast(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 diff --git a/src/TocBackend.h b/src/TocBackend.h new file mode 100644 index 0000000000..dcaae49376 --- /dev/null +++ b/src/TocBackend.h @@ -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 +#include +#include +#include + +#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 Toc; + typedef std::vector::const_iterator TocIterator; + /// + typedef std::map 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 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 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 diff --git a/src/buffer_funcs.C b/src/buffer_funcs.C index b4f4bf7bf7..5c545cbcdd 100644 --- a/src/buffer_funcs.C +++ b/src/buffer_funcs.C @@ -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 @@ bool updateCurrentLabel(Buffer const & buf, 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 @@ void updateLabels(Buffer const & buf) // set the counter for this paragraph setLabel(buf, it); } + + lyx::toc::updateToc(buf); } diff --git a/src/frontends/controllers/ControlToc.C b/src/frontends/controllers/ControlToc.C index e2e861456b..146c411e16 100644 --- a/src/frontends/controllers/ControlToc.C +++ b/src/frontends/controllers/ControlToc.C @@ -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 @@ void ControlToc::outline(toc::OutlineOp op) } -vector const ControlToc::getTypes() const +vector 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 @@ string const ControlToc::getGuiName(string const & type) const } -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 diff --git a/src/frontends/controllers/ControlToc.h b/src/frontends/controllers/ControlToc.h index 501efda287..a5eef748d2 100644 --- a/src/frontends/controllers/ControlToc.h +++ b/src/frontends/controllers/ControlToc.h @@ -31,17 +31,17 @@ public: void goTo(toc::TocItem const &); /// Return the list of types available - std::vector const getTypes() const; + std::vector 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); diff --git a/src/frontends/qt2/QToc.C b/src/frontends/qt2/QToc.C index d8898e2c9d..929d2bf085 100644 --- a/src/frontends/qt2/QToc.C +++ b/src/frontends/qt2/QToc.C @@ -122,21 +122,21 @@ void QToc::updateToc(int newdepth) 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 top; // restore context while (diff--) { @@ -154,20 +154,20 @@ void QToc::updateToc(int newdepth) 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 @@ -198,7 +198,7 @@ void QToc::select(string const & text) toc::Toc::const_iterator iter = toclist.begin(); for (; iter != toclist.end(); ++iter) { - if (iter->str == text) + if (iter->str() == text) break; } diff --git a/src/frontends/qt4/QToc.C b/src/frontends/qt4/QToc.C index cb3ae3e7f8..0d45e7ade8 100644 --- a/src/frontends/qt4/QToc.C +++ b/src/frontends/qt4/QToc.C @@ -31,6 +31,7 @@ using std::string; namespace lyx { namespace frontend { + QToc::QToc(Dialog & parent) : ControlToc(parent) { @@ -76,17 +77,13 @@ QStandardItemModel * QToc::setTocModel(int type) QModelIndex const QToc::getCurrentIndex() { vector 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 @@ void QToc::goTo(QModelIndex const & index) << 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::update() void QToc::updateToc(int type) { - vector 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 diff --git a/src/frontends/qt4/QToc.h b/src/frontends/qt4/QToc.h index 1aa496544b..6acc5c6209 100644 --- a/src/frontends/qt4/QToc.h +++ b/src/frontends/qt4/QToc.h @@ -48,7 +48,7 @@ public: /// void goTo(QModelIndex const & index); - void move(toc::OutlineOp const operation, QModelIndex & index); + void move(toc::OutlineOp const operation); private: diff --git a/src/frontends/qt4/QTocDialog.C b/src/frontends/qt4/QTocDialog.C index c60589ab00..1e74c39730 100644 --- a/src/frontends/qt4/QTocDialog.C +++ b/src/frontends/qt4/QTocDialog.C @@ -43,7 +43,7 @@ QTocDialog::QTocDialog(Dialog & dialog, QToc * form) { setupUi(this); - update(); + updateGui(); connect(tocTV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, @@ -88,7 +88,6 @@ void QTocDialog::on_closePB_clicked() void QTocDialog::on_updatePB_clicked() { - form_->update(); update(); } @@ -103,9 +102,9 @@ void QTocDialog::on_depthSL_valueChanged(int depth) /* 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 @@ void QTocDialog::move(toc::OutlineOp const operation) 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 @@ void QTocDialog::select(QModelIndex const & index) tocTV->selectionModel()->select(index, QItemSelectionModel::Select); } + void QTocDialog::enableButtons(bool enable) { updatePB->setEnabled(enable); @@ -181,6 +183,13 @@ void QTocDialog::enableButtons(bool enable) void QTocDialog::update() +{ + form_->update(); + updateGui(); +} + + +void QTocDialog::updateGui() { typeCO->setModel(form_->typeModel()); tocTV->setModel(form_->tocModel()); @@ -223,7 +232,6 @@ void QTocDialog::hide() void QTocDialog::show() { - form_->update(); update(); QDialog::show(); } diff --git a/src/frontends/qt4/QTocDialog.h b/src/frontends/qt4/QTocDialog.h index 1a5ab8574c..b20f4843c9 100644 --- a/src/frontends/qt4/QTocDialog.h +++ b/src/frontends/qt4/QTocDialog.h @@ -46,6 +46,9 @@ public: /// 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; diff --git a/src/frontends/qt4/TocModel.C b/src/frontends/qt4/TocModel.C index 2bd212bc28..a3a4ccb238 100644 --- a/src/frontends/qt4/TocModel.C +++ b/src/frontends/qt4/TocModel.C @@ -25,80 +25,81 @@ using std::make_pair; 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 & toc_list) } -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 @@ void TocModel::populate(toc::Toc::const_iterator & iter, 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 diff --git a/src/frontends/qt4/TocModel.h b/src/frontends/qt4/TocModel.h index 7e2a8fb813..265999b165 100644 --- a/src/frontends/qt4/TocModel.h +++ b/src/frontends/qt4/TocModel.h @@ -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 ItemMap; + void populate(TocIterator & it, + TocIterator const & end, + QModelIndex const & parent); + /// + typedef std::map TocMap; + /// + typedef std::map ModelMap; /// - typedef std::map IndexMap; + TocMap toc_map_; /// - ItemMap item_map_; - IndexMap index_map_; + ModelMap model_map_; }; } // namespace frontend diff --git a/src/insets/insetfloat.C b/src/insets/insetfloat.C index e2121a3402..f5fdae343e 100644 --- a/src/insets/insetfloat.C +++ b/src/insets/insetfloat.C @@ -438,7 +438,7 @@ void InsetFloat::addToToc(lyx::toc::TocList & toclist, Buffer const & buf) const string const str = convert(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); } } diff --git a/src/insets/insetwrap.C b/src/insets/insetwrap.C index 7d41b6df86..f5a1d804f0 100644 --- a/src/insets/insetwrap.C +++ b/src/insets/insetwrap.C @@ -246,7 +246,7 @@ void InsetWrap::addToToc(lyx::toc::TocList & toclist, Buffer const & buf) const string const str = convert(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); } } diff --git a/src/pariterator.h b/src/pariterator.h index dac6626b5b..4e721d85aa 100644 --- a/src/pariterator.h +++ b/src/pariterator.h @@ -92,6 +92,8 @@ class ParConstIterator : public std::iterator +#include + +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 TocMap; +static TocMap toc_backend_; +/////////////////////////////////////////////////////////////////////////// +// Interface to toc_backend_ -void TocItem::goTo(LyXView & lv_) const +void updateToc(Buffer const & buf) { - string const tmp = convert(id_); - lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp)); + TocMap::iterator it = toc_backend_.find(&buf); + if (it == toc_backend_.end()) { + pair result + = toc_backend_.insert(make_pair(&buf, TocBackend(&buf))); + if (!result.second) + return; + + it = result.first; + } + + it->second.update(); } -FuncRequest TocItem::action() const +TocList const & getTocList(Buffer const & buf) { - return FuncRequest(LFUN_GOTO_PARAGRAPH, convert(id_)); + return toc_backend_[&buf].tocs(); } -string const getType(string const & cmdName) +Toc const & getToc(Buffer const & buf, std::string const & type) { - // special case - if (cmdName == "tableofcontents") - return "TOC"; - else - return cmdName; + return toc_backend_[&buf].toc(type); } -string const getGuiName(string const & type, Buffer const & buffer) +TocIterator const getCurrentTocItem(Buffer const & buf, LCursor const & cur, + 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].item(type, ParConstIterator(cur)); } -TocList const getTocList(Buffer const & buf) +vector const & getTypes(Buffer const & buf) { - 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(it->inset) - ->addToToc(toclist, buf); - break; - case InsetBase::WRAP_CODE: - static_cast(it->inset) - ->addToToc(toclist, buf); - break; - case InsetBase::OPTARG_CODE: { - if (!tocstring.empty()) - break; - Paragraph const & par = *static_cast(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].types(); } -TocItem const getCurrentTocItem(Buffer const & buf, LCursor const & cur, - std::string const & type) +void asciiTocList(string const & type, Buffer const & buf, ostream & os) { - // 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]; + toc_backend_[&buf].asciiTocList(type, os); } +/////////////////////////////////////////////////////////////////////////// +// Other functions -vector const getTypes(Buffer const & buffer) +string const getType(string const & cmdName) { - vector types; - - 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; + // 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; } diff --git a/src/toc.h b/src/toc.h index abf7c4b41f..2006f6f0d0 100644 --- a/src/toc.h +++ b/src/toc.h @@ -15,55 +15,33 @@ #ifndef TOC_H #define TOC_H -#include -#include -#include -#include +#include "TocBackend.h" -#include "pariterator.h" - -class Buffer; -class LyXView; -class Paragraph; -class FuncRequest; class LCursor; namespace lyx { namespace toc { -/// -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; -}; +typedef TocBackend::Item TocItem; +typedef TocBackend::Toc::const_iterator TocIterator; +typedef TocBackend::Toc Toc; +typedef TocBackend::TocList TocList; /// -typedef std::vector Toc; +void updateToc(Buffer const &); + /// -typedef std::map TocList; +TocList const & getTocList(Buffer const &); /// -TocList const getTocList(Buffer const &); +Toc const & getToc(Buffer const & buf, std::string const & type); /// -std::vector const getTypes(Buffer const &); +std::vector 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 @@ std::string const getType(std::string const & cmdName); 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 -- 2.39.5