X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FTocModel.cpp;h=4eaafb4bedda336c6936b6580e447ad800713f1d;hb=425d092204118ea6c24c28e85fdf03fcf2bb51a4;hp=670cb5541dab474d4f626077631397a506db1e10;hpb=ffa722e0b7cefbbdc6f7e387a50fefb889bcb7d9;p=lyx.git diff --git a/src/frontends/qt4/TocModel.cpp b/src/frontends/qt4/TocModel.cpp index 670cb5541d..4eaafb4bed 100644 --- a/src/frontends/qt4/TocModel.cpp +++ b/src/frontends/qt4/TocModel.cpp @@ -14,19 +14,18 @@ #include "TocModel.h" #include "Buffer.h" -#include "BufferParams.h" #include "BufferView.h" #include "Cursor.h" -#include "FloatList.h" +#include "DocIterator.h" #include "FuncRequest.h" #include "LyXFunc.h" -#include "ParIterator.h" -#include "TextClass.h" +#include "TocBackend.h" -#include "support/convert.h" #include "support/debug.h" #include "support/lassert.h" +#include + #include using namespace std; @@ -34,200 +33,284 @@ using namespace std; namespace lyx { namespace frontend { -typedef std::pair TocPair; +/////////////////////////////////////////////////////////////////////////////// +// +// TocTypeModel +// +/////////////////////////////////////////////////////////////////////////////// + +TocTypeModel::TocTypeModel(QObject * parent) + : QStandardItemModel(parent) +{ +} + + +void TocTypeModel::reset() +{ + QStandardItemModel::reset(); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// TocModel +// +/////////////////////////////////////////////////////////////////////////////// -TocIterator TocModel::tocIterator(QModelIndex const & index) const +TocModel::TocModel(QObject * parent) + : model_(new TocTypeModel(parent)), + sorted_model_(new QSortFilterProxyModel(parent)), + is_sorted_(false), maxdepth_(0), mindepth_(0) { - TocMap::const_iterator map_it = toc_map_.find(index); - LASSERT(map_it != toc_map_.end(), /**/); - return map_it->second; +#if QT_VERSION >= 0x040300 + sorted_model_->setSortLocaleAware(true); +#endif + sorted_model_->setSourceModel(model_); } -QModelIndex TocModel::modelIndex(TocIterator const & it) const +QAbstractItemModel * TocModel::model() { - ModelMap::const_iterator map_it = model_map_.find(it); - //LASSERT(it != model_map_.end(), /**/); + if (is_sorted_) + return sorted_model_; + return model_; +} - if (map_it == model_map_.end()) - return QModelIndex(); - return map_it->second; +QAbstractItemModel const * TocModel::model() const +{ + if (is_sorted_) + return sorted_model_; + return model_; } void TocModel::clear() { - QStandardItemModel::clear(); - toc_map_.clear(); - model_map_.clear(); - removeRows(0, rowCount()); - removeColumns(0, columnCount()); + model_->blockSignals(true); + model_->clear(); + model_->blockSignals(false); } -void TocModel::populate(Toc const & toc) +void TocModel::sort(bool sort_it) { - clear(); + is_sorted_ = sort_it; + if (is_sorted_) + sorted_model_->sort(0); +} - if (toc.empty()) - return; - int current_row; - QModelIndex top_level_item; - TocIterator iter = toc.begin(); - TocIterator end = toc.end(); +TocItem const & TocModel::tocItem(QModelIndex const & index) const +{ + return (*toc_)[model()->data(index, Qt::UserRole).toUInt()]; +} - insertColumns(0, 1); - maxdepth_ = 0; - mindepth_ = INT_MAX; - while (iter != end) { - maxdepth_ = max(maxdepth_, iter->depth()); - mindepth_ = min(mindepth_, iter->depth()); - 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); +QModelIndex TocModel::modelIndex(DocIterator const & dit) const +{ + if (toc_->empty()) + return QModelIndex(); + + unsigned int const toc_index = toc_->item(dit) - toc_->begin(); - // This looks like a gcc bug, in principle this should work: - //toc_map_[top_level_item] = iter; - // but it crashes with gcc-4.1 and 4.0.2 - toc_map_.insert( TocPair(top_level_item, iter) ); - model_map_[iter] = top_level_item; + QModelIndexList list = model()->match(model()->index(0, 0), Qt::UserRole, + QVariant(toc_index), 1, + Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive)); - LYXERR(Debug::GUI, "Toc: at depth " << iter->depth() - << ", added item " << toqstr(iter->str())); + LASSERT(!list.isEmpty(), return QModelIndex()); + return list[0]; +} - populate(iter, end, top_level_item); - if (iter == end) - break; +void TocModel::reset() +{ + model_->reset(); +} + + +void TocModel::updateItem(DocIterator const & dit) +{ + QModelIndex index = modelIndex(dit); + TocItem const & toc_item = tocItem(index); + model_->setData(index, toqstr(toc_item.str()), Qt::DisplayRole); +} + - ++iter; +void TocModel::reset(Toc const & toc) +{ + toc_ = &toc; + if (toc_->empty()) { + maxdepth_ = 0; + mindepth_ = 0; + reset(); + return; } - setHeaderData(0, Qt::Horizontal, QVariant("title"), Qt::DisplayRole); + model_->blockSignals(true); + model_->insertColumns(0, 1); + maxdepth_ = 0; + mindepth_ = INT_MAX; + + size_t end = toc_->size(); + for (unsigned int index = 0; index != end; ++index) { + TocItem const & item = (*toc_)[index]; + maxdepth_ = max(maxdepth_, item.depth()); + mindepth_ = min(mindepth_, item.depth()); + int current_row = model_->rowCount(); + model_->insertRows(current_row, 1); + QModelIndex top_level_item = model_->index(current_row, 0); + model_->setData(top_level_item, toqstr(item.str()), Qt::DisplayRole); + model_->setData(top_level_item, index, Qt::UserRole); + + LYXERR(Debug::GUI, "Toc: at depth " << item.depth() + << ", added item " << item.str()); + + populate(index, top_level_item); + if (index >= end) + break; + } + + model_->setHeaderData(0, Qt::Horizontal, QVariant("title"), Qt::DisplayRole); + if (is_sorted_) + sorted_model_->sort(0); + model_->blockSignals(false); + reset(); // emit headerDataChanged(); } -void TocModel::populate(TocIterator & iter, TocIterator const & end, - QModelIndex const & parent) +void TocModel::populate(unsigned int & index, QModelIndex const & parent) { - int curdepth = iter->depth() + 1; + int curdepth = (*toc_)[index].depth() + 1; int current_row; QModelIndex child_item; - insertColumns(0, 1, parent); - - while (iter != end) { - ++iter; - - if (iter == end) - break; - - if (iter->depth() < curdepth) { - --iter; + model_->insertColumns(0, 1, parent); + + size_t end = toc_->size(); + ++index; + for (; index != end; ++index) { + TocItem const & item = (*toc_)[index]; + if (item.depth() < curdepth) { + --index; return; } - - maxdepth_ = max(maxdepth_, iter->depth()); - mindepth_ = min(mindepth_, iter->depth()); - 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); - - // This looks like a gcc bug, in principle this should work: - //toc_map_[child_item] = iter; - // but it crashes with gcc-4.1 and 4.0.2 - toc_map_.insert( TocPair(child_item, iter) ); - model_map_[iter] = child_item; - populate(iter, end, child_item); + maxdepth_ = max(maxdepth_, item.depth()); + mindepth_ = min(mindepth_, item.depth()); + current_row = model_->rowCount(parent); + model_->insertRows(current_row, 1, parent); + child_item = model_->index(current_row, 0, parent); + model_->setData(child_item, toqstr(item.str()), Qt::DisplayRole); + model_->setData(child_item, index, Qt::UserRole); + populate(index, child_item); + if (index >= end) + break; } } int TocModel::modelDepth() const { - return maxdepth_ - mindepth_; + int const d = maxdepth_ - mindepth_; + LASSERT(d >= 0 && d <= 100, return 0); + return d; } /////////////////////////////////////////////////////////////////////////////// -// TocModels implementation. +// +// TocModels +// /////////////////////////////////////////////////////////////////////////////// -void TocModels::clear() + +TocModels::TocModels() + : bv_(0) { - types_.clear(); - type_names_.clear(); - const unsigned int size = models_.size(); - for (unsigned int i = 0; i < size; ++i) { - delete models_[i]; - } - models_.clear(); + names_ = new TocTypeModel(this); + names_sorted_ = new QSortFilterProxyModel(this); + names_sorted_->setSourceModel(names_); +#if QT_VERSION >= 0x040300 + names_sorted_->setSortLocaleAware(true); +#endif + names_sorted_->sort(0); } -int TocModels::depth(int type) +void TocModels::clear() { - if (type < 0) - return 0; - return models_[type]->modelDepth(); + names_->blockSignals(true); + names_->clear(); + names_->blockSignals(false); + iterator end = models_.end(); + for (iterator it = models_.begin(); it != end; ++it) + it.value()->clear(); } -QStandardItemModel * TocModels::model(int type) +int TocModels::depth(QString const & type) { - if (type < 0) + const_iterator it = models_.find(type); + if (!bv_ || it == models_.end()) return 0; + return it.value()->modelDepth(); +} - if (models_.empty()) { - LYXERR(Debug::GUI, "TocModels::tocModel(): no types available "); + +QAbstractItemModel * TocModels::model(QString const & type) +{ + if (!bv_) return 0; - } + iterator it = models_.find(type); + if (it != models_.end()) + return it.value()->model(); + LYXERR0("type not found: " << type); + return 0; +} - LYXERR(Debug::GUI, "TocModels: type " << type - << " models_.size() " << models_.size()); - LASSERT(type >= 0 && type < int(models_.size()), /**/); - return models_[type]; +QAbstractItemModel * TocModels::nameModel() +{ + return names_sorted_; } -QModelIndex TocModels::currentIndex(int type) const +QModelIndex TocModels::currentIndex(QString const & type) const { - if (type < 0 || !bv_) + const_iterator it = models_.find(type); + if (!bv_ || it == models_.end()) return QModelIndex(); - - ParConstIterator it(bv_->cursor()); - return models_[type]->modelIndex(bv_->buffer().masterBuffer()-> - tocBackend().item(fromqstr(types_[type]), it)); + return it.value()->modelIndex(bv_->cursor()); } -void TocModels::goTo(int type, QModelIndex const & index) const +void TocModels::goTo(QString const & type, QModelIndex const & index) const { - if (type < 0 || !index.isValid() - || index.model() != models_[type]) { + const_iterator it = models_.find(type); + if (it == models_.end() || !index.isValid()) { LYXERR(Debug::GUI, "TocModels::goTo(): QModelIndex is invalid!"); return; } + LASSERT(index.model() == it.value()->model(), return); + TocItem const item = it.value()->tocItem(index); + LYXERR(Debug::GUI, "TocModels::goTo " << item.str()); + dispatch(item.action()); +} - LASSERT(type >= 0 && type < int(models_.size()), /**/); - - TocIterator const it = models_[type]->tocIterator(index); - - LYXERR(Debug::GUI, "TocModels::goTo " << it->str()); - string const tmp = convert(it->id()); - dispatch(FuncRequest(LFUN_PARAGRAPH_GOTO, tmp)); +TocItem const TocModels::currentItem(QString const & type, + QModelIndex const & index) const +{ + const_iterator it = models_.find(type); + if (it == models_.end() || !index.isValid()) { + LYXERR(Debug::GUI, "TocModels::currentItem(): QModelIndex is invalid!"); + return TocItem(); + } + LASSERT(index.model() == it.value()->model(), return TocItem()); + + return it.value()->tocItem(index); } - + void TocModels::updateBackend() const { @@ -236,36 +319,9 @@ void TocModels::updateBackend() const } -QString TocModels::guiName(string const & type) const +void TocModels::updateItem(QString const & type, DocIterator const & dit) { - if (type == "tableofcontents") - return qt_("Table of Contents"); - if (type == "child") - return qt_("Child Documents"); - if (type == "graphics") - return qt_("List of Graphics"); - if (type == "equation") - return qt_("List of Equations"); - if (type == "footnote") - return qt_("List of Footnotes"); - if (type == "listing") - return qt_("List of Listings"); - if (type == "index") - return qt_("List of Indexes"); - if (type == "marginalnote") - return qt_("List of Marginal notes"); - if (type == "note") - return qt_("List of Notes"); - if (type == "citation") - return qt_("List of Citations"); - if (type == "label") - return qt_("Labels and References"); - - FloatList const & floats = bv_->buffer().params().documentClass().floats(); - if (floats.typeExist(type)) - return qt_(floats.getType(type).listName()); - - return qt_(type); + models_[type]->updateItem(dit); } @@ -273,50 +329,62 @@ void TocModels::reset(BufferView const * bv) { bv_ = bv; clear(); - if (!bv_) + if (!bv_) { + iterator end = models_.end(); + for (iterator it = models_.begin(); it != end; ++it) + it.value()->reset(); + names_->reset(); return; + } + names_->blockSignals(true); + names_->insertColumns(0, 1); TocList const & tocs = bv_->buffer().masterBuffer()->tocBackend().tocs(); TocList::const_iterator it = tocs.begin(); - TocList::const_iterator end = tocs.end(); - for (; it != end; ++it) { - types_.push_back(toqstr(it->first)); - type_names_.push_back(guiName(it->first)); - models_.push_back(new TocModel(it->second)); + TocList::const_iterator toc_end = tocs.end(); + for (; it != toc_end; ++it) { + QString const type = toqstr(it->first); + + // First, fill in the toc models. + iterator mod_it = models_.find(type); + if (mod_it == models_.end()) + mod_it = models_.insert(type, new TocModel(this)); + mod_it.value()->reset(it->second); + + // Fill in the names_ model. + QString const gui_name = guiName(it->first, bv->buffer().params()); + int const current_row = names_->rowCount(); + names_->insertRows(current_row, 1); + QModelIndex const index = names_->index(current_row, 0); + names_->setData(index, gui_name, Qt::DisplayRole); + names_->setData(index, type, Qt::UserRole); } + names_->blockSignals(false); + names_->reset(); } -bool TocModels::canOutline(int type) const +bool TocModels::isSorted(QString const & type) const { - if (type < 0 || type >= types_.size()) + const_iterator it = models_.find(type); + if (it == models_.end()) { + LYXERR0("type not found: " << type); return false; - return types_[type] == "tableofcontents"; + } + return it.value()->isSorted(); } -int TocModels::decodeType(QString const & str) const +void TocModels::sort(QString const & type, bool sort_it) { - QString new_type; - if (str.contains("tableofcontents")) { - new_type = "tableofcontents"; - } else if (str.contains("floatlist")) { - if (str.contains("\"figure")) - new_type = "figure"; - else if (str.contains("\"table")) - new_type = "table"; - else if (str.contains("\"algorithm")) - new_type = "algorithm"; - } else if (!str.isEmpty()) { - new_type = str; - } else { - // Default to Outliner. - new_type = "tableofcontents"; - } - return types_.indexOf(new_type); + iterator it = models_.find(type); + if (it == models_.end()) + LYXERR0("type not found: " << type); + else + it.value()->sort(sort_it); } } // namespace frontend } // namespace lyx -#include "TocModel_moc.cpp" +#include "moc_TocModel.cpp"