2006-04-18 09:57:47 +00:00
|
|
|
/**
|
2007-11-14 00:21:31 +00:00
|
|
|
* \file TocModel.cpp
|
2006-04-18 09:57:47 +00:00
|
|
|
* This file is part of LyX, the document processor.
|
|
|
|
* Licence details can be found in the file COPYING.
|
|
|
|
*
|
|
|
|
* \author John Levon
|
|
|
|
* \author Abdelrazak Younes
|
|
|
|
*
|
|
|
|
* Full author contact details are available in file CREDITS.
|
|
|
|
*/
|
|
|
|
|
2006-07-08 13:27:43 +00:00
|
|
|
#include <config.h>
|
|
|
|
|
2006-04-18 09:57:47 +00:00
|
|
|
#include "TocModel.h"
|
|
|
|
|
2008-05-02 12:09:51 +00:00
|
|
|
#include "Buffer.h"
|
|
|
|
#include "BufferView.h"
|
|
|
|
#include "Cursor.h"
|
2008-05-16 13:49:49 +00:00
|
|
|
#include "DocIterator.h"
|
2008-05-02 12:09:51 +00:00
|
|
|
#include "FuncRequest.h"
|
2010-02-09 16:11:13 +00:00
|
|
|
#include "LyX.h"
|
2008-06-12 15:31:10 +00:00
|
|
|
#include "TocBackend.h"
|
2008-05-02 12:09:51 +00:00
|
|
|
|
2007-11-29 07:04:28 +00:00
|
|
|
#include "support/debug.h"
|
2008-04-30 08:26:40 +00:00
|
|
|
#include "support/lassert.h"
|
2008-05-02 12:09:51 +00:00
|
|
|
|
2008-06-18 11:35:24 +00:00
|
|
|
#include <QSortFilterProxyModel>
|
|
|
|
|
2008-02-07 17:04:06 +00:00
|
|
|
#include <climits>
|
2007-09-16 10:36:57 +00:00
|
|
|
|
2007-12-12 10:16:00 +00:00
|
|
|
using namespace std;
|
2006-04-18 09:57:47 +00:00
|
|
|
|
|
|
|
namespace lyx {
|
|
|
|
namespace frontend {
|
2006-04-28 09:16:48 +00:00
|
|
|
|
2008-09-29 21:53:24 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2008-09-30 07:38:34 +00:00
|
|
|
// TocTypeModel
|
2008-09-29 21:53:24 +00:00
|
|
|
//
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
TocTypeModel::TocTypeModel(QObject * parent)
|
|
|
|
: QStandardItemModel(parent)
|
2008-06-17 15:10:03 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TocTypeModel::reset()
|
|
|
|
{
|
|
|
|
QStandardItemModel::reset();
|
|
|
|
}
|
|
|
|
|
2006-04-28 09:16:48 +00:00
|
|
|
|
2008-09-30 07:38:34 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// TocModel
|
|
|
|
//
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2008-09-28 17:14:29 +00:00
|
|
|
TocModel::TocModel(QObject * parent)
|
|
|
|
: model_(new TocTypeModel(parent)),
|
|
|
|
sorted_model_(new QSortFilterProxyModel(parent)),
|
|
|
|
is_sorted_(false), maxdepth_(0), mindepth_(0)
|
|
|
|
{
|
|
|
|
#if QT_VERSION >= 0x040300
|
|
|
|
sorted_model_->setSortLocaleAware(true);
|
|
|
|
#endif
|
|
|
|
sorted_model_->setSourceModel(model_);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QAbstractItemModel * TocModel::model()
|
|
|
|
{
|
|
|
|
if (is_sorted_)
|
|
|
|
return sorted_model_;
|
|
|
|
return model_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QAbstractItemModel const * TocModel::model() const
|
|
|
|
{
|
|
|
|
if (is_sorted_)
|
|
|
|
return sorted_model_;
|
|
|
|
return model_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TocModel::clear()
|
|
|
|
{
|
|
|
|
model_->blockSignals(true);
|
|
|
|
model_->clear();
|
|
|
|
model_->blockSignals(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TocModel::sort(bool sort_it)
|
|
|
|
{
|
|
|
|
is_sorted_ = sort_it;
|
|
|
|
if (is_sorted_)
|
|
|
|
sorted_model_->sort(0);
|
|
|
|
}
|
|
|
|
|
2008-09-30 07:38:34 +00:00
|
|
|
|
2008-06-12 15:31:10 +00:00
|
|
|
TocItem const & TocModel::tocItem(QModelIndex const & index) const
|
2006-04-18 09:57:47 +00:00
|
|
|
{
|
2008-09-28 17:14:29 +00:00
|
|
|
return (*toc_)[model()->data(index, Qt::UserRole).toUInt()];
|
2006-04-18 09:57:47 +00:00
|
|
|
}
|
2006-04-28 09:16:48 +00:00
|
|
|
|
2006-04-18 09:57:47 +00:00
|
|
|
|
2008-06-12 15:31:10 +00:00
|
|
|
QModelIndex TocModel::modelIndex(DocIterator const & dit) const
|
2006-04-18 09:57:47 +00:00
|
|
|
{
|
2008-06-17 15:10:03 +00:00
|
|
|
if (toc_->empty())
|
2008-06-12 15:43:31 +00:00
|
|
|
return QModelIndex();
|
|
|
|
|
2008-06-17 15:10:03 +00:00
|
|
|
unsigned int const toc_index = toc_->item(dit) - toc_->begin();
|
2006-04-18 09:57:47 +00:00
|
|
|
|
2008-09-28 17:14:29 +00:00
|
|
|
QModelIndexList list = model()->match(model()->index(0, 0), Qt::UserRole,
|
2008-06-12 15:31:10 +00:00
|
|
|
QVariant(toc_index), 1,
|
|
|
|
Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive));
|
2007-05-28 22:27:45 +00:00
|
|
|
|
2008-06-12 15:31:10 +00:00
|
|
|
LASSERT(!list.isEmpty(), return QModelIndex());
|
|
|
|
return list[0];
|
2006-04-18 09:57:47 +00:00
|
|
|
}
|
2006-04-28 09:16:48 +00:00
|
|
|
|
2006-04-18 09:57:47 +00:00
|
|
|
|
2008-06-17 15:10:03 +00:00
|
|
|
void TocModel::reset()
|
|
|
|
{
|
2008-09-28 17:14:29 +00:00
|
|
|
model_->reset();
|
2008-06-17 15:10:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-30 09:50:54 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-17 15:10:03 +00:00
|
|
|
void TocModel::reset(Toc const & toc)
|
2006-04-18 09:57:47 +00:00
|
|
|
{
|
2008-06-17 15:10:03 +00:00
|
|
|
toc_ = &toc;
|
|
|
|
if (toc_->empty()) {
|
2008-09-11 21:15:45 +00:00
|
|
|
maxdepth_ = 0;
|
|
|
|
mindepth_ = 0;
|
2008-06-17 15:10:03 +00:00
|
|
|
reset();
|
2006-04-18 09:57:47 +00:00
|
|
|
return;
|
2008-06-17 15:10:03 +00:00
|
|
|
}
|
|
|
|
|
2008-09-28 17:14:29 +00:00
|
|
|
model_->blockSignals(true);
|
|
|
|
model_->insertColumns(0, 1);
|
2006-11-25 22:16:22 +00:00
|
|
|
maxdepth_ = 0;
|
|
|
|
mindepth_ = INT_MAX;
|
2006-04-18 09:57:47 +00:00
|
|
|
|
2008-06-17 15:10:03 +00:00
|
|
|
size_t end = toc_->size();
|
2008-06-12 17:34:01 +00:00
|
|
|
for (unsigned int index = 0; index != end; ++index) {
|
2008-06-17 15:10:03 +00:00
|
|
|
TocItem const & item = (*toc_)[index];
|
2008-06-12 15:31:10 +00:00
|
|
|
maxdepth_ = max(maxdepth_, item.depth());
|
|
|
|
mindepth_ = min(mindepth_, item.depth());
|
2008-09-29 21:53:24 +00:00
|
|
|
int current_row = model_->rowCount();
|
2008-09-28 17:14:29 +00:00
|
|
|
model_->insertRows(current_row, 1);
|
2008-09-29 21:53:24 +00:00
|
|
|
QModelIndex top_level_item = model_->index(current_row, 0);
|
2008-09-28 17:14:29 +00:00
|
|
|
model_->setData(top_level_item, toqstr(item.str()), Qt::DisplayRole);
|
|
|
|
model_->setData(top_level_item, index, Qt::UserRole);
|
2007-06-12 12:29:19 +00:00
|
|
|
|
2008-06-12 15:31:10 +00:00
|
|
|
LYXERR(Debug::GUI, "Toc: at depth " << item.depth()
|
|
|
|
<< ", added item " << item.str());
|
2006-04-18 09:57:47 +00:00
|
|
|
|
2008-06-12 15:31:10 +00:00
|
|
|
populate(index, top_level_item);
|
|
|
|
if (index >= end)
|
2006-04-18 09:57:47 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-05-28 22:27:45 +00:00
|
|
|
|
2008-09-28 17:14:29 +00:00
|
|
|
model_->setHeaderData(0, Qt::Horizontal, QVariant("title"), Qt::DisplayRole);
|
|
|
|
if (is_sorted_)
|
|
|
|
sorted_model_->sort(0);
|
|
|
|
model_->blockSignals(false);
|
2008-06-17 15:10:03 +00:00
|
|
|
reset();
|
2006-04-18 09:57:47 +00:00
|
|
|
// emit headerDataChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-12 17:34:01 +00:00
|
|
|
void TocModel::populate(unsigned int & index, QModelIndex const & parent)
|
2006-04-18 09:57:47 +00:00
|
|
|
{
|
2008-06-17 15:10:03 +00:00
|
|
|
int curdepth = (*toc_)[index].depth() + 1;
|
2007-05-28 22:27:45 +00:00
|
|
|
|
2006-04-18 09:57:47 +00:00
|
|
|
int current_row;
|
|
|
|
QModelIndex child_item;
|
2008-09-28 17:14:29 +00:00
|
|
|
model_->insertColumns(0, 1, parent);
|
2006-04-18 09:57:47 +00:00
|
|
|
|
2008-06-17 15:10:03 +00:00
|
|
|
size_t end = toc_->size();
|
2008-06-12 15:31:10 +00:00
|
|
|
++index;
|
|
|
|
for (; index != end; ++index) {
|
2008-06-17 15:10:03 +00:00
|
|
|
TocItem const & item = (*toc_)[index];
|
2008-06-12 15:31:10 +00:00
|
|
|
if (item.depth() < curdepth) {
|
|
|
|
--index;
|
2006-04-18 09:57:47 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-06-12 15:31:10 +00:00
|
|
|
maxdepth_ = max(maxdepth_, item.depth());
|
|
|
|
mindepth_ = min(mindepth_, item.depth());
|
2008-09-28 17:14:29 +00:00
|
|
|
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);
|
2008-06-12 15:31:10 +00:00
|
|
|
populate(index, child_item);
|
|
|
|
if (index >= end)
|
|
|
|
break;
|
2006-04-18 09:57:47 +00:00
|
|
|
}
|
|
|
|
}
|
2006-04-28 09:16:48 +00:00
|
|
|
|
2006-04-18 09:57:47 +00:00
|
|
|
|
2007-11-14 00:21:31 +00:00
|
|
|
int TocModel::modelDepth() const
|
2006-11-25 22:16:22 +00:00
|
|
|
{
|
2008-09-11 21:02:18 +00:00
|
|
|
int const d = maxdepth_ - mindepth_;
|
2008-09-30 07:38:34 +00:00
|
|
|
LASSERT(d >= 0 && d <= 100, return 0);
|
2008-09-11 21:02:18 +00:00
|
|
|
return d;
|
2006-11-25 22:16:22 +00:00
|
|
|
}
|
|
|
|
|
2008-05-02 12:09:51 +00:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2008-09-29 21:53:24 +00:00
|
|
|
//
|
|
|
|
// TocModels
|
|
|
|
//
|
2008-05-02 12:09:51 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2008-06-17 15:10:03 +00:00
|
|
|
|
2008-09-29 21:53:24 +00:00
|
|
|
TocModels::TocModels()
|
|
|
|
: bv_(0)
|
2008-06-17 15:10:03 +00:00
|
|
|
{
|
|
|
|
names_ = new TocTypeModel(this);
|
2008-06-18 11:35:24 +00:00
|
|
|
names_sorted_ = new QSortFilterProxyModel(this);
|
|
|
|
names_sorted_->setSourceModel(names_);
|
|
|
|
#if QT_VERSION >= 0x040300
|
|
|
|
names_sorted_->setSortLocaleAware(true);
|
|
|
|
#endif
|
|
|
|
names_sorted_->sort(0);
|
2008-06-17 15:10:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-24 13:58:02 +00:00
|
|
|
void TocModels::clear()
|
2008-05-02 12:09:51 +00:00
|
|
|
{
|
2008-06-17 15:10:03 +00:00
|
|
|
names_->blockSignals(true);
|
|
|
|
names_->clear();
|
|
|
|
names_->blockSignals(false);
|
|
|
|
iterator end = models_.end();
|
2008-09-28 17:14:29 +00:00
|
|
|
for (iterator it = models_.begin(); it != end; ++it)
|
2008-06-17 15:10:03 +00:00
|
|
|
it.value()->clear();
|
2008-05-02 12:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-17 15:10:03 +00:00
|
|
|
int TocModels::depth(QString const & type)
|
2008-05-02 12:09:51 +00:00
|
|
|
{
|
2008-06-17 15:10:03 +00:00
|
|
|
const_iterator it = models_.find(type);
|
|
|
|
if (!bv_ || it == models_.end())
|
2008-05-02 12:09:51 +00:00
|
|
|
return 0;
|
2008-06-17 15:10:03 +00:00
|
|
|
return it.value()->modelDepth();
|
2008-05-02 12:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-28 17:14:29 +00:00
|
|
|
QAbstractItemModel * TocModels::model(QString const & type)
|
2008-05-02 12:09:51 +00:00
|
|
|
{
|
2008-06-17 15:10:03 +00:00
|
|
|
if (!bv_)
|
2008-05-02 12:09:51 +00:00
|
|
|
return 0;
|
2008-06-17 15:10:03 +00:00
|
|
|
iterator it = models_.find(type);
|
|
|
|
if (it != models_.end())
|
2008-09-28 17:14:29 +00:00
|
|
|
return it.value()->model();
|
2008-06-17 15:10:03 +00:00
|
|
|
LYXERR0("type not found: " << type);
|
|
|
|
return 0;
|
2008-05-02 12:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-18 11:35:24 +00:00
|
|
|
QAbstractItemModel * TocModels::nameModel()
|
|
|
|
{
|
|
|
|
return names_sorted_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-17 15:10:03 +00:00
|
|
|
QModelIndex TocModels::currentIndex(QString const & type) const
|
2008-05-02 12:09:51 +00:00
|
|
|
{
|
2008-06-17 15:10:03 +00:00
|
|
|
const_iterator it = models_.find(type);
|
|
|
|
if (!bv_ || it == models_.end())
|
2008-05-02 12:09:51 +00:00
|
|
|
return QModelIndex();
|
2008-06-17 15:10:03 +00:00
|
|
|
return it.value()->modelIndex(bv_->cursor());
|
2008-05-02 12:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-17 15:10:03 +00:00
|
|
|
void TocModels::goTo(QString const & type, QModelIndex const & index) const
|
2008-05-02 12:09:51 +00:00
|
|
|
{
|
2008-06-17 15:10:03 +00:00
|
|
|
const_iterator it = models_.find(type);
|
|
|
|
if (it == models_.end() || !index.isValid()) {
|
2008-05-02 12:09:51 +00:00
|
|
|
LYXERR(Debug::GUI, "TocModels::goTo(): QModelIndex is invalid!");
|
|
|
|
return;
|
|
|
|
}
|
2008-09-28 17:14:29 +00:00
|
|
|
LASSERT(index.model() == it.value()->model(), return);
|
2008-06-17 15:10:03 +00:00
|
|
|
TocItem const item = it.value()->tocItem(index);
|
2008-06-12 15:31:10 +00:00
|
|
|
LYXERR(Debug::GUI, "TocModels::goTo " << item.str());
|
|
|
|
dispatch(item.action());
|
2008-05-02 12:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-08 21:40:42 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-02 12:09:51 +00:00
|
|
|
void TocModels::updateBackend() const
|
|
|
|
{
|
|
|
|
bv_->buffer().masterBuffer()->tocBackend().update();
|
|
|
|
bv_->buffer().structureChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-30 09:50:54 +00:00
|
|
|
void TocModels::updateItem(QString const & type, DocIterator const & dit)
|
|
|
|
{
|
|
|
|
models_[type]->updateItem(dit);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-02 12:09:51 +00:00
|
|
|
void TocModels::reset(BufferView const * bv)
|
|
|
|
{
|
|
|
|
bv_ = bv;
|
|
|
|
clear();
|
2008-06-17 15:10:03 +00:00
|
|
|
if (!bv_) {
|
|
|
|
iterator end = models_.end();
|
|
|
|
for (iterator it = models_.begin(); it != end; ++it)
|
|
|
|
it.value()->reset();
|
|
|
|
names_->reset();
|
2008-05-02 12:09:51 +00:00
|
|
|
return;
|
2008-06-17 15:10:03 +00:00
|
|
|
}
|
2008-05-02 12:09:51 +00:00
|
|
|
|
2008-06-17 15:10:03 +00:00
|
|
|
names_->blockSignals(true);
|
|
|
|
names_->insertColumns(0, 1);
|
2008-05-02 12:09:51 +00:00
|
|
|
TocList const & tocs = bv_->buffer().masterBuffer()->tocBackend().tocs();
|
|
|
|
TocList::const_iterator it = tocs.begin();
|
2008-06-17 15:10:03 +00:00
|
|
|
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);
|
2008-05-02 12:09:51 +00:00
|
|
|
}
|
2008-06-17 15:10:03 +00:00
|
|
|
names_->reset();
|
Fix bug 6522 and its relatives in trunk. I am not absolutely sure this
is right, though. Someone please check.
The problem, in branch, was that (in Qt 4.6.x, anyway) the call to
reset() eventually triggers the on_typeCO_currentIndexChanged() method,
which eventually leads to GuiView::setFocus(), which leads to
GuiWorkArea::focusInEvent(), which tries to start the cursor, whose
position hasn't been updated yet, from what I can see.
The problem in trunk is similar. The crash happens, I think, because,
while we are in the middle of resetting the model, the same method is
triggered, which leads us to try to access the model while we are in the
middle of resetting it.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@33630 a592a061-630c-0410-9148-cb99ea01b6c8
2010-03-05 20:47:50 +00:00
|
|
|
names_->blockSignals(false);
|
2008-05-02 12:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-28 17:14:29 +00:00
|
|
|
bool TocModels::isSorted(QString const & type) const
|
|
|
|
{
|
|
|
|
const_iterator it = models_.find(type);
|
|
|
|
if (it == models_.end()) {
|
|
|
|
LYXERR0("type not found: " << type);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return it.value()->isSorted();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TocModels::sort(QString const & type, bool sort_it)
|
|
|
|
{
|
|
|
|
iterator it = models_.find(type);
|
|
|
|
if (it == models_.end())
|
|
|
|
LYXERR0("type not found: " << type);
|
|
|
|
else
|
|
|
|
it.value()->sort(sort_it);
|
|
|
|
}
|
|
|
|
|
2006-04-18 09:57:47 +00:00
|
|
|
} // namespace frontend
|
|
|
|
} // namespace lyx
|
2006-05-18 08:51:12 +00:00
|
|
|
|
2008-11-14 14:28:50 +00:00
|
|
|
#include "moc_TocModel.cpp"
|