mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-25 10:58:52 +00:00
General cleanup of the Outline/Navigator:
- Make use the Qt Model/View separation concept, TocWidget is now really just a view of the current toc model. - the toc type combo now use a model defined in TocModels. - the models are not deleted at each reset, they are now just cleared out. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@25289 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
b5252b737f
commit
6ad1b1cd09
@ -83,8 +83,8 @@ void GuiToc::dispatchParams()
|
||||
|
||||
void GuiToc::enableView(bool enable)
|
||||
{
|
||||
widget_->init(QString());
|
||||
widget_->setEnabled(enable);
|
||||
if (!enable)
|
||||
widget_->init(QString());
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,19 +32,29 @@ using namespace std;
|
||||
namespace lyx {
|
||||
namespace frontend {
|
||||
|
||||
TocTypeModel::TocTypeModel(QObject * parent): QStandardItemModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void TocTypeModel::reset()
|
||||
{
|
||||
QStandardItemModel::reset();
|
||||
}
|
||||
|
||||
|
||||
TocItem const & TocModel::tocItem(QModelIndex const & index) const
|
||||
{
|
||||
return toc_[data(index, Qt::UserRole).toUInt()];
|
||||
return (*toc_)[data(index, Qt::UserRole).toUInt()];
|
||||
}
|
||||
|
||||
|
||||
QModelIndex TocModel::modelIndex(DocIterator const & dit) const
|
||||
{
|
||||
if (toc_.empty())
|
||||
if (toc_->empty())
|
||||
return QModelIndex();
|
||||
|
||||
unsigned int const toc_index = toc_.item(dit) - toc_.begin();
|
||||
unsigned int const toc_index = toc_->item(dit) - toc_->begin();
|
||||
|
||||
QModelIndexList list = match(index(0, 0), Qt::UserRole,
|
||||
QVariant(toc_index), 1,
|
||||
@ -55,19 +65,35 @@ QModelIndex TocModel::modelIndex(DocIterator const & dit) const
|
||||
}
|
||||
|
||||
|
||||
TocModel::TocModel(Toc const & toc): toc_(toc)
|
||||
TocModel::TocModel(QObject * parent): QStandardItemModel(parent)
|
||||
{
|
||||
if (toc_.empty())
|
||||
}
|
||||
|
||||
|
||||
void TocModel::reset()
|
||||
{
|
||||
QStandardItemModel::reset();
|
||||
}
|
||||
|
||||
|
||||
void TocModel::reset(Toc const & toc)
|
||||
{
|
||||
toc_ = &toc;
|
||||
if (toc_->empty()) {
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
blockSignals(true);
|
||||
int current_row;
|
||||
QModelIndex top_level_item;
|
||||
insertColumns(0, 1);
|
||||
maxdepth_ = 0;
|
||||
mindepth_ = INT_MAX;
|
||||
|
||||
size_t end = toc.size();
|
||||
size_t end = toc_->size();
|
||||
for (unsigned int index = 0; index != end; ++index) {
|
||||
TocItem const & item = toc_[index];
|
||||
TocItem const & item = (*toc_)[index];
|
||||
maxdepth_ = max(maxdepth_, item.depth());
|
||||
mindepth_ = min(mindepth_, item.depth());
|
||||
current_row = rowCount();
|
||||
@ -85,22 +111,24 @@ TocModel::TocModel(Toc const & toc): toc_(toc)
|
||||
}
|
||||
|
||||
setHeaderData(0, Qt::Horizontal, QVariant("title"), Qt::DisplayRole);
|
||||
blockSignals(false);
|
||||
reset();
|
||||
// emit headerDataChanged();
|
||||
}
|
||||
|
||||
|
||||
void TocModel::populate(unsigned int & index, QModelIndex const & parent)
|
||||
{
|
||||
int curdepth = toc_[index].depth() + 1;
|
||||
int curdepth = (*toc_)[index].depth() + 1;
|
||||
|
||||
int current_row;
|
||||
QModelIndex child_item;
|
||||
insertColumns(0, 1, parent);
|
||||
|
||||
size_t end = toc_.size();
|
||||
size_t end = toc_->size();
|
||||
++index;
|
||||
for (; index != end; ++index) {
|
||||
TocItem const & item = toc_[index];
|
||||
TocItem const & item = (*toc_)[index];
|
||||
if (item.depth() < curdepth) {
|
||||
--index;
|
||||
return;
|
||||
@ -128,62 +156,66 @@ int TocModel::modelDepth() const
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// TocModels implementation.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TocModels::TocModels(): bv_(0)
|
||||
{
|
||||
names_ = new TocTypeModel(this);
|
||||
}
|
||||
|
||||
|
||||
void TocModels::clear()
|
||||
{
|
||||
types_.clear();
|
||||
type_names_.clear();
|
||||
const unsigned int size = models_.size();
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
delete models_[i];
|
||||
names_->blockSignals(true);
|
||||
names_->clear();
|
||||
names_->blockSignals(false);
|
||||
iterator end = models_.end();
|
||||
for (iterator it = models_.begin(); it != end; ++it) {
|
||||
it.value()->blockSignals(true);
|
||||
it.value()->clear();
|
||||
it.value()->blockSignals(false);
|
||||
}
|
||||
models_.clear();
|
||||
}
|
||||
|
||||
|
||||
int TocModels::depth(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 models_[type]->modelDepth();
|
||||
return it.value()->modelDepth();
|
||||
}
|
||||
|
||||
|
||||
QStandardItemModel * TocModels::model(int type)
|
||||
QStandardItemModel * TocModels::model(QString const & type)
|
||||
{
|
||||
if (type < 0)
|
||||
if (!bv_)
|
||||
return 0;
|
||||
|
||||
if (models_.empty()) {
|
||||
LYXERR(Debug::GUI, "TocModels::tocModel(): no types available ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LYXERR(Debug::GUI, "TocModels: type " << type
|
||||
<< " models_.size() " << models_.size());
|
||||
|
||||
LASSERT(type >= 0 && type < int(models_.size()), /**/);
|
||||
return models_[type];
|
||||
iterator it = models_.find(type);
|
||||
if (it != models_.end())
|
||||
return it.value();
|
||||
LYXERR0("type not found: " << type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
return models_[type]->modelIndex(bv_->cursor());
|
||||
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(type >= 0 && type < int(models_.size()), /**/);
|
||||
TocItem const item = models_[type]->tocItem(index);
|
||||
LASSERT(index.model() == it.value(), return);
|
||||
TocItem const item = it.value()->tocItem(index);
|
||||
LYXERR(Debug::GUI, "TocModels::goTo " << item.str());
|
||||
dispatch(item.action());
|
||||
}
|
||||
@ -200,54 +232,41 @@ 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, bv->buffer().params()));
|
||||
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
|
||||
{
|
||||
if (type < 0 || type >= types_.size())
|
||||
return false;
|
||||
return types_[type] == "tableofcontents";
|
||||
}
|
||||
|
||||
|
||||
int TocModels::decodeType(QString const & str) const
|
||||
{
|
||||
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";
|
||||
}
|
||||
int const type = types_.indexOf(new_type);
|
||||
if (type != -1)
|
||||
return type;
|
||||
// If everything else fails, settle on the table of contents which is
|
||||
// guaranted to exist.
|
||||
return types_.indexOf("tableofcontents");
|
||||
}
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace lyx
|
||||
|
||||
|
@ -28,11 +28,25 @@ class TocItem;
|
||||
|
||||
namespace frontend {
|
||||
|
||||
class TocTypeModel : public QStandardItemModel
|
||||
{
|
||||
public:
|
||||
///
|
||||
TocTypeModel(QObject * parent = 0);
|
||||
///
|
||||
void reset();
|
||||
};
|
||||
|
||||
|
||||
class TocModel : public QStandardItemModel
|
||||
{
|
||||
public:
|
||||
///
|
||||
TocModel(Toc const & toc);
|
||||
TocModel(QObject * parent = 0);
|
||||
///
|
||||
void reset(Toc const & toc);
|
||||
///
|
||||
void reset();
|
||||
///
|
||||
TocItem const & tocItem(QModelIndex const & index) const;
|
||||
///
|
||||
@ -46,7 +60,7 @@ private:
|
||||
///
|
||||
QList<QModelIndex> toc_indexes_;
|
||||
///
|
||||
Toc const & toc_;
|
||||
Toc const * toc_;
|
||||
///
|
||||
int maxdepth_;
|
||||
int mindepth_;
|
||||
@ -58,45 +72,44 @@ class TocModels: public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
///
|
||||
TocModels(): bv_(0) {}
|
||||
TocModels();
|
||||
///
|
||||
~TocModels() { clear(); }
|
||||
typedef QHash<QString, TocModel *>::const_iterator const_iterator;
|
||||
const_iterator begin() const { return models_.begin(); }
|
||||
const_iterator end() const { return models_.end(); }
|
||||
///
|
||||
void reset(BufferView const * bv);
|
||||
///
|
||||
int depth(int type);
|
||||
int depth(QString const & type);
|
||||
///
|
||||
QStandardItemModel * model(int type);
|
||||
QStandardItemModel * model(QString const & type);
|
||||
///
|
||||
QModelIndex currentIndex(int type) const;
|
||||
QStandardItemModel * nameModel() { return names_; }
|
||||
///
|
||||
void goTo(int type, QModelIndex const & index) const;
|
||||
QModelIndex currentIndex(QString const & type) const;
|
||||
///
|
||||
void goTo(QString const & type, QModelIndex const & index) const;
|
||||
///
|
||||
void init(Buffer const & buffer);
|
||||
/// Test if outlining operation is possible
|
||||
bool canOutline(int type) const;
|
||||
/// Return the list of types available
|
||||
QStringList const & typeNames() const { return type_names_; }
|
||||
///
|
||||
void updateBackend() const;
|
||||
///
|
||||
int decodeType(QString const & str) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/// Signal that the internal toc_models_ has been reset.
|
||||
void modelReset();
|
||||
|
||||
private:
|
||||
typedef QHash<QString, TocModel *>::iterator iterator;
|
||||
///
|
||||
void clear();
|
||||
///
|
||||
void deleteAll();
|
||||
///
|
||||
BufferView const * bv_;
|
||||
///
|
||||
QList<TocModel *> models_;
|
||||
QHash<QString, TocModel *> models_;
|
||||
///
|
||||
QStringList types_;
|
||||
///
|
||||
QStringList type_names_;
|
||||
TocTypeModel * names_;
|
||||
};
|
||||
|
||||
} // namespace frontend
|
||||
|
@ -57,6 +57,9 @@ TocWidget::TocWidget(GuiView & gui_view, QWidget * parent)
|
||||
|
||||
// Only one item selected at a time.
|
||||
tocTV->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
// The toc types combo won't change its model.
|
||||
typeCO->setModel(gui_view_.tocModels().nameModel());
|
||||
}
|
||||
|
||||
|
||||
@ -78,7 +81,7 @@ void TocWidget::goTo(QModelIndex const & index)
|
||||
LYXERR(Debug::GUI, "goto " << index.row()
|
||||
<< ", " << index.column());
|
||||
|
||||
gui_view_.tocModels().goTo(typeCO->currentIndex(), index);
|
||||
gui_view_.tocModels().goTo(current_type_, index);
|
||||
}
|
||||
|
||||
|
||||
@ -117,6 +120,8 @@ void TocWidget::on_depthSL_valueChanged(int depth)
|
||||
void TocWidget::setTreeDepth(int depth)
|
||||
{
|
||||
depth_ = depth;
|
||||
if (!tocTV->model())
|
||||
return;
|
||||
|
||||
// expanding and then collapsing is probably better,
|
||||
// but my qt 4.1.2 doesn't have expandAll()..
|
||||
@ -134,8 +139,9 @@ void TocWidget::setTreeDepth(int depth)
|
||||
}
|
||||
|
||||
|
||||
void TocWidget::on_typeCO_currentIndexChanged(int)
|
||||
void TocWidget::on_typeCO_currentIndexChanged(int index)
|
||||
{
|
||||
current_type_ = typeCO->itemData(index).toString();
|
||||
updateView();
|
||||
gui_view_.setFocus();
|
||||
}
|
||||
@ -192,11 +198,18 @@ void TocWidget::select(QModelIndex const & index)
|
||||
}
|
||||
|
||||
|
||||
/// Test if outlining operation is possible
|
||||
static bool canOutline(QString const & type)
|
||||
{
|
||||
return type == "tableofcontents";
|
||||
}
|
||||
|
||||
|
||||
void TocWidget::enableControls(bool enable)
|
||||
{
|
||||
updateTB->setEnabled(enable);
|
||||
|
||||
if (!gui_view_.tocModels().canOutline(typeCO->currentIndex()))
|
||||
if (!canOutline(current_type_))
|
||||
enable = false;
|
||||
|
||||
moveUpTB->setEnabled(enable);
|
||||
@ -213,64 +226,74 @@ void TocWidget::updateView()
|
||||
LYXERR(Debug::GUI, "In TocWidget::updateView()");
|
||||
setTocModel();
|
||||
setTreeDepth(depth_);
|
||||
select(gui_view_.tocModels().currentIndex(typeCO->currentIndex()));
|
||||
select(gui_view_.tocModels().currentIndex(current_type_));
|
||||
}
|
||||
|
||||
|
||||
static QString decodeType(QString const & str)
|
||||
{
|
||||
QString type = str;
|
||||
if (type.contains("tableofcontents")) {
|
||||
type = "tableofcontents";
|
||||
} else if (type.contains("floatlist")) {
|
||||
if (type.contains("\"figure"))
|
||||
type = "figure";
|
||||
else if (type.contains("\"table"))
|
||||
type = "table";
|
||||
else if (type.contains("\"algorithm"))
|
||||
type = "algorithm";
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
void TocWidget::init(QString const & str)
|
||||
{
|
||||
QStringList const & type_names = gui_view_.tocModels().typeNames();
|
||||
if (type_names.isEmpty()) {
|
||||
if (!gui_view_.view()) {
|
||||
enableControls(false);
|
||||
typeCO->setEnabled(false);
|
||||
tocTV->setModel(new QStandardItemModel);
|
||||
tocTV->setModel(0);
|
||||
tocTV->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
typeCO->setEnabled(true);
|
||||
tocTV->setEnabled(true);
|
||||
int selected_type = gui_view_.tocModels().decodeType(str);
|
||||
|
||||
QString const current_text = typeCO->currentText();
|
||||
typeCO->blockSignals(true);
|
||||
typeCO->clear();
|
||||
for (int i = 0; i != type_names.size(); ++i)
|
||||
typeCO->addItem(type_names[i]);
|
||||
if (!str.isEmpty())
|
||||
typeCO->setCurrentIndex(selected_type);
|
||||
else {
|
||||
int const new_index = typeCO->findText(current_text);
|
||||
if (new_index != -1)
|
||||
typeCO->setCurrentIndex(new_index);
|
||||
else
|
||||
typeCO->setCurrentIndex(selected_type);
|
||||
|
||||
int new_index;
|
||||
if (str.isEmpty())
|
||||
new_index = typeCO->findData(current_type_);
|
||||
else
|
||||
new_index = typeCO->findData(decodeType(str));
|
||||
|
||||
// If everything else fails, settle on the table of contents which is
|
||||
// guaranted to exist.
|
||||
if (new_index == -1) {
|
||||
current_type_ = "tableofcontents";
|
||||
new_index = typeCO->findData(current_type_);
|
||||
}
|
||||
|
||||
typeCO->setCurrentIndex(new_index);
|
||||
typeCO->blockSignals(false);
|
||||
|
||||
// setTocModel produce QTreeView reset and setting depth again
|
||||
// is needed. That must be done after all Qt updates are processed.
|
||||
QTimer::singleShot(0, this, SLOT(updateView()));
|
||||
}
|
||||
|
||||
|
||||
void TocWidget::setTocModel()
|
||||
{
|
||||
int const toc_type = typeCO->currentIndex();
|
||||
QStandardItemModel * toc_model = gui_view_.tocModels().model(toc_type);
|
||||
LASSERT(toc_model, return);
|
||||
QStandardItemModel * toc_model = gui_view_.tocModels().model(current_type_);
|
||||
|
||||
if (tocTV->model() != toc_model) {
|
||||
tocTV->setModel(toc_model);
|
||||
tocTV->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
}
|
||||
|
||||
bool controls_enabled = toc_model->rowCount() > 0;;
|
||||
bool controls_enabled = toc_model && toc_model->rowCount() > 0;;
|
||||
enableControls(controls_enabled);
|
||||
|
||||
if (controls_enabled) {
|
||||
depthSL->setMaximum(gui_view_.tocModels().depth(toc_type));
|
||||
depthSL->setMaximum(gui_view_.tocModels().depth(current_type_));
|
||||
depthSL->setValue(depth_);
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,8 @@ private:
|
||||
void setTreeDepth(int depth);
|
||||
///
|
||||
void outline(int func_code);
|
||||
///
|
||||
QString current_type_;
|
||||
|
||||
/// depth of list shown
|
||||
int depth_;
|
||||
|
Loading…
Reference in New Issue
Block a user