Dear LyX Developers, I am writing to request a bit of code review. For the past week, or so, I have been working on the TocModel in LyX so that I can get it to support more than a single column. This modification is important for the specialized views that I would like to create. (For more information on what I'm trying to accomplish, take a look at this webpage: http://blog.oak-tree.us/index.php/2009/03/04/perfect-tool).
After trying several different approaches, I finally found that appears to work with negatively impacting the performance or stability of LyX. The result of that work is attached, and I would greatly appreciate your feedback on it. Briefly, here is what I did: 1.) TocBackend::TocItem - I created a simple vector that can be used to store TocItems. In the addToToc methods of InsetText.cpp, this vector is used to find store TocItems of Note insets that are included in the heading. 2.) TocModel - Code was added that can read the vector from a particular TocItem add any Note information to a second column of the existing model. 3.) InsetText - Code was added to addToToc that recognizes any Note insets that are part of the current heading. These are then added to the TocItem vector referenced above. 4.) TocWidget - Code was added that hides the second column of the model, so that the UI remains unchanged. So far, these modifications appear to be stable. I have been testing them against the most recent SVN of LyX 2 and I have not had any problems with crashes, application freezes or file corruption. I understand that the code may be a bit crude (I am neither a software developer or proficient with C++, though getting better). And for that reason, I would appreciate any thoughts/recommendations that you might have. Cheers, Rob Oakes
=== modified file 'src/insets/InsetText.cpp' --- src/insets/InsetText.cpp 2010-04-26 22:46:21 +0000 +++ src/insets/InsetText.cpp 2010-05-23 23:24:11 +0000 @@ -672,9 +672,9 @@ } - void InsetText::addToToc(DocIterator const & cdit) { + TocItem paragraph_item; DocIterator dit = cdit; dit.push_back(CursorSlice(*this)); Toc & toc = buffer().tocBackend().toc("tableofcontents"); @@ -691,13 +691,37 @@ dit.pit() = pit; // the string that goes to the toc (could be the optarg) docstring tocstring; + + // Create an Entry in the Table of Contents for the Paragraph + int const toclevel = par.layout().toclevel; + if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel) { + dit.pos() = 0; + // insert this into the table of contents + if (tocstring.empty()) + tocstring = par.asString(AS_STR_LABEL | AS_STR_INSETS); + paragraph_item = TocItem(dit, toclevel - min_toclevel, tocstring, tocstring); + } + + // Traverse the Paragraph Insets and allow them to be added to the + // appropriate toc list InsetList::const_iterator it = par.insetList().begin(); InsetList::const_iterator end = par.insetList().end(); for (; it != end; ++it) { Inset & inset = *it->inset; dit.pos() = it->pos; + + // Check whether the inset is a note and add to paragraph_item + if (inset.name()== from_ascii("Note:Note")){ + DocIterator pit = dit; + pit.push_back(CursorSlice(inset)); + docstring str_summary = pit.paragraph().asString(); + paragraph_item.summary_notes.push_back(TocItem(pit, toclevel - min_toclevel, 1, + str_summary, str_summary)); + } + //lyxerr << (void*)&inset << " code: " << inset.lyxCode() << std::endl; inset.addToToc(dit); + switch (inset.lyxCode()) { case OPTARG_CODE: { if (!tocstring.empty()) @@ -714,16 +738,9 @@ break; } } - // now the toc entry for the paragraph - int const toclevel = par.layout().toclevel; - if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel) { - dit.pos() = 0; - // insert this into the table of contents - if (tocstring.empty()) - tocstring = par.asString(AS_STR_LABEL | AS_STR_INSETS); - toc.push_back(TocItem(dit, toclevel - min_toclevel, - tocstring, tocstring)); - } + + if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel) + toc.push_back(paragraph_item); // And now the list of changes. par.addChangesToToc(dit, buffer());
=== modified file 'src/TocBackend.cpp' --- src/TocBackend.cpp 2010-05-18 16:39:42 +0000 +++ src/TocBackend.cpp 2010-05-23 22:00:10 +0000 @@ -47,10 +47,14 @@ /////////////////////////////////////////////////////////////////////////// TocItem::TocItem(DocIterator const & dit, int d, docstring const & s, - docstring const & t) : dit_(dit), depth_(d), str_(s), tooltip_(t) + docstring const & t) : dit_(dit), depth_(d), str_(s), tooltip_(t), column_(0) { } +TocItem::TocItem(DocIterator const & dit, int d, int c, docstring const & s, + docstring const & t) : dit_(dit), depth_(d), str_(s), tooltip_(t), column_(c) +{ +} int TocItem::id() const { @@ -63,13 +67,16 @@ return depth_; } +int TocItem::modelColumn() const +{ + return column_; +} docstring const & TocItem::str() const { return str_; } - docstring const & TocItem::tooltip() const { return tooltip_; @@ -95,7 +102,6 @@ return FuncRequest(LFUN_PARAGRAPH_GOTO, arg); } - /////////////////////////////////////////////////////////////////////////// // // TocBackend implementation
=== modified file 'src/TocBackend.h' --- src/TocBackend.h 2010-04-26 22:46:21 +0000 +++ src/TocBackend.h 2010-05-23 22:00:47 +0000 @@ -45,6 +45,14 @@ docstring const & s, docstring const & t = docstring() ); + + TocItem(DocIterator const & dit, + int depth, + int col, + docstring const & s, + docstring const & t = docstring() + ); + /// ~TocItem() {} /// @@ -63,8 +71,12 @@ /// the action corresponding to the goTo above FuncRequest action() const; - /// Returns the text of the snyopsis associated with the item. - docstring const synopsis() const; + /// returns the model column that the item should add itself to + int modelColumn() const; + + /// summary_notes_, vector of any note TocItems that + /// might be associated with a particular item. + std::vector<TocItem> summary_notes; protected: /// Current position of item. @@ -78,6 +90,10 @@ /// The tooltip string docstring tooltip_; + + /// model column, default = 0 + int column_; + };
=== modified file 'src/frontends/qt4/TocModel.cpp' --- src/frontends/qt4/TocModel.cpp 2010-04-26 22:46:21 +0000 +++ src/frontends/qt4/TocModel.cpp 2010-05-23 23:03:31 +0000 @@ -171,7 +171,7 @@ model_->blockSignals(true); model_->beginResetModel(); - model_->insertColumns(0, 1); + model_->insertColumns(0, 2); maxdepth_ = 0; mindepth_ = INT_MAX; @@ -187,6 +187,15 @@ model_->setData(top_level_item, index, Qt::UserRole); model_->setData(top_level_item, toqstr(item.tooltip()), Qt::ToolTipRole); + size_t notes_size = item.summary_notes.size(); + if (notes_size != 0){ + QModelIndex summary_index = model_->index(current_row, 1); + TocItem const & summary_item = item.summary_notes[0]; + model_->setData(summary_index, toqstr(summary_item.str()), Qt::DisplayRole); + model_->setData(summary_index, index, Qt::UserRole); + model_->setData(summary_index, toqstr(summary_item.tooltip()), Qt::ToolTipRole); + } + LYXERR(Debug::GUI, "Toc: at depth " << item.depth() << ", added item " << item.str()); @@ -210,7 +219,7 @@ int current_row; QModelIndex child_item; - model_->insertColumns(0, 1, parent); + model_->insertColumns(0, 2, parent); size_t end = toc_->size(); ++index; @@ -228,6 +237,17 @@ model_->setData(child_item, toqstr(item.str()), Qt::DisplayRole); model_->setData(child_item, index, Qt::UserRole); model_->setData(child_item, toqstr(item.tooltip()), Qt::ToolTipRole); + + // Check for summary_notes + size_t notes_size = item.summary_notes.size(); + if (notes_size != 0){ + QModelIndex summary_index = model_->index(current_row, 1, parent); + TocItem const & summary_item = item.summary_notes[0]; + model_->setData(summary_index, toqstr(summary_item.str()), Qt::DisplayRole); + model_->setData(summary_index, index, Qt::UserRole); + model_->setData(summary_index, toqstr(summary_item.tooltip()), Qt::ToolTipRole); + } + populate(index, child_item); if (index >= end) break;
=== modified file 'src/frontends/qt4/TocWidget.cpp' --- src/frontends/qt4/TocWidget.cpp 2010-05-13 01:00:52 +0000 +++ src/frontends/qt4/TocWidget.cpp 2010-05-23 05:30:56 +0000 @@ -390,6 +390,8 @@ { if (!gui_view_.documentBufferView()) { tocTV->setModel(0); + tocTV->showColumn(0); + tocTV->hideColumn(1); depthSL->setMaximum(0); depthSL->setValue(0); setEnabled(false); @@ -406,6 +408,8 @@ gui_view_.tocModels().model(current_type_); if (tocTV->model() != toc_model) { tocTV->setModel(toc_model); + tocTV->showColumn(0); + tocTV->hideColumn(1); tocTV->setEditTriggers(QAbstractItemView::NoEditTriggers); if (persistent_) setTreeDepth(depth_);