* 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.

* 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
This commit is contained in:
Abdelrazak Younes 2006-04-22 18:48:28 +00:00
parent 39de58c7a7
commit 8c0bd3a77b
19 changed files with 612 additions and 322 deletions

View File

@ -280,6 +280,8 @@ lyx_SOURCES = \
text.C \
text2.C \
text3.C \
TocBackend.C \
TocBackend.h \
toc.C \
toc.h \
trans.C \

View File

@ -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<string>(shortcut_count + 1)) != string::npos)
label += '|' + convert<string>(++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<string>(shortcut_count + 1)) != string::npos)
label += '|' + convert<string>(++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())));

261
src/TocBackend.C Normal file
View File

@ -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

145
src/TocBackend.h Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -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<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 @@ 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

View File

@ -31,17 +31,17 @@ public:
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);

View File

@ -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<QListViewItem *, QListViewItem * > 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;
}

View File

@ -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<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 @@ 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<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

View File

@ -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:

View File

@ -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();
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -438,7 +438,7 @@ void InsetFloat::addToToc(lyx::toc::TocList & toclist, Buffer const & buf) const
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);
}
}

View File

@ -246,7 +246,7 @@ void InsetWrap::addToToc(lyx::toc::TocList & toclist, Buffer const & buf) const
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);
}
}

View File

@ -92,6 +92,8 @@ class ParConstIterator : public std::iterator<std::forward_iterator_tag,
public DocIterator
{
public:
///
ParConstIterator(): DocIterator() {}
///
ParConstIterator(ParConstIterator const &);
///

188
src/toc.C
View File

@ -31,33 +31,77 @@
#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
typedef map<Buffer const *, lyx::TocBackend> TocMap;
static TocMap toc_backend_;
///////////////////////////////////////////////////////////////////////////
// Interface to toc_backend_
void updateToc(Buffer const & buf)
{
return string(4 * depth, ' ') + str;
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;
}
it->second.update();
}
void TocItem::goTo(LyXView & lv_) const
TocList const & getTocList(Buffer const & buf)
{
string const tmp = convert<string>(id_);
lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp));
return toc_backend_[&buf].tocs();
}
FuncRequest TocItem::action() const
Toc const & getToc(Buffer const & buf, std::string const & type)
{
return FuncRequest(LFUN_GOTO_PARAGRAPH, convert<string>(id_));
return toc_backend_[&buf].toc(type);
}
TocIterator const getCurrentTocItem(Buffer const & buf, LCursor const & cur,
std::string const & type)
{
return toc_backend_[&buf].item(type, ParConstIterator(cur));
}
vector<string> const & getTypes(Buffer const & buf)
{
return toc_backend_[&buf].types();
}
void asciiTocList(string const & type, Buffer const & buf, ostream & os)
{
toc_backend_[&buf].asciiTocList(type, os);
}
///////////////////////////////////////////////////////////////////////////
// Other functions
string const getType(string const & cmdName)
{
// special case
@ -79,136 +123,6 @@ string const getGuiName(string const & type, Buffer const & buffer)
}
TocList const getTocList(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<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;
}
TocItem const getCurrentTocItem(Buffer const & buf, LCursor const & cur,
std::string const & type)
{
// 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];
}
vector<string> const getTypes(Buffer const & buffer)
{
vector<string> 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;
}
void asciiTocList(string const & type, Buffer const & buffer, ostream & os)
{
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';
}
}
void outline(OutlineOp mode, Buffer * buf, pit_type & pit)
{
ParagraphList & pars = buf->text().paragraphs();

View File

@ -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 {
///
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<TocItem> Toc;
///
typedef std::map<std::string, Toc> TocList;
void updateToc(Buffer const &);
///
TocList const getTocList(Buffer const &);
TocList const & getTocList(Buffer const &);
///
std::vector<std::string> const getTypes(Buffer const &);
Toc const & getToc(Buffer const & buf, std::string const & type);
///
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 @@ 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