]> git.lyx.org Git - lyx.git/commitdiff
General cleanup of the Outline/Navigator:
authorAbdelrazak Younes <younes@lyx.org>
Tue, 17 Jun 2008 15:10:03 +0000 (15:10 +0000)
committerAbdelrazak Younes <younes@lyx.org>
Tue, 17 Jun 2008 15:10:03 +0000 (15:10 +0000)
- 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

src/frontends/qt4/GuiToc.cpp
src/frontends/qt4/TocModel.cpp
src/frontends/qt4/TocModel.h
src/frontends/qt4/TocWidget.cpp
src/frontends/qt4/TocWidget.h

index f130f878c567ec52a62535930e8938b9c393d8fc..3ab8cee212ecdbb03b3af1a10a4efe4baf702afb 100644 (file)
@@ -83,8 +83,8 @@ void GuiToc::dispatchParams()
 
 void GuiToc::enableView(bool enable)
 {
-       widget_->init(QString());
-       widget_->setEnabled(enable);
+       if (!enable)
+               widget_->init(QString());
 }
 
 
index cd6cd7058e235dd1e9a9cb95ba5e6d8e0fe9e65b..6b115c8390bd92b0ee84427bbe00be0cbf20dc74 100644 (file)
@@ -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)
+{
+}
+
+
+void TocModel::reset()
+{
+       QStandardItemModel::reset();
+}
+
+
+void TocModel::reset(Toc const & toc)
 {
-       if (toc_.empty())
+       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)
-               return 0;
-
-       if (models_.empty()) {
-               LYXERR(Debug::GUI, "TocModels::tocModel(): no types available ");
+       if (!bv_)
                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
 
index efa4e56e1035bcd2dc3b5377c7ebb267f53ddc06..59e83a999c39fc92b424008802e5082525534dd0 100644 (file)
@@ -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(QString const & type);
        ///
-       QStandardItemModel * model(int type);
+       QStandardItemModel * nameModel() { return names_; }
        ///
-       QModelIndex currentIndex(int type) const;
+       QModelIndex currentIndex(QString const & type) const;
        ///
-       void goTo(int type, QModelIndex const & index) 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();
        ///
-       BufferView const * bv_;
+       void deleteAll();
        ///
-       QList<TocModel *> models_;
+       BufferView const * bv_;
        ///
-       QStringList types_;
+       QHash<QString, TocModel *> models_;
        ///
-       QStringList type_names_;
+       TocTypeModel * names_;
 };
 
 } // namespace frontend
index eb3fc493314bdcff8b4d1af1fdd177632371a736..3be6aeb220c1572214128ccec1d41784dde1c826 100644 (file)
@@ -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_);
        }
 }
index ea145539e98b61ce5928079a9c7cbdad245cb44e..a9dc03f5727557a019f7cce91e0b14df9de5fddf 100644 (file)
@@ -64,6 +64,8 @@ private:
        void setTreeDepth(int depth);
        ///
        void outline(int func_code);
+       ///
+       QString current_type_;
 
        /// depth of list shown
        int depth_;