]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/TocWidget.cpp
fix critical part of http://bugzilla.lyx.org/show_bug.cgi?id=5082
[lyx.git] / src / frontends / qt4 / TocWidget.cpp
index 823de4de23541690c64c21b14191198141a76dbb..dbf4948aa585d348f430ece9a02f6f73ae67eab2 100644 (file)
 #include "qt_helpers.h"
 #include "TocModel.h"
 
+#include "Buffer.h"
 #include "FuncRequest.h"
 #include "LyXFunc.h"
 
 #include "support/debug.h"
+#include "support/lassert.h"
 
 #include <QHeaderView>
 #include <QTimer>
@@ -56,6 +58,13 @@ 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());
+
+       // Make sure the buttons are disabled when first shown without a loaded
+       // Buffer.
+       enableControls(false);
 }
 
 
@@ -77,7 +86,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);
 }
 
 
@@ -89,17 +98,18 @@ void TocWidget::on_updateTB_clicked()
        gui_view_.tocModels().updateBackend();
 }
 
+
 /* FIXME (Ugras 17/11/06):
-I have implemented a getIndexDepth function to get the model indices. In my
+I have implemented a indexDepth function to get the model indices. In my
 opinion, somebody should derive a new qvariant class for tocModelItem
-which saves the string data and depth information. that will save the
-depth calculation.
-*/
-int TocWidget::getIndexDepth(QModelIndex const & index, int depth)
+which saves the string data and depth information. That will save the
+depth calculation.  */
+
+static int indexDepth(QModelIndex const & index, int depth = -1)
 {
        ++depth;
-       return (index.parent() == QModelIndex())
-               ? depth : getIndexDepth(index.parent(),depth);
+       return index.parent() == QModelIndex()
+               ? depth : indexDepth(index.parent(), depth);
 }
 
 
@@ -108,12 +118,15 @@ void TocWidget::on_depthSL_valueChanged(int depth)
        if (depth == depth_)
                return;
        setTreeDepth(depth);
+       gui_view_.setFocus();
 }
 
 
 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()..
@@ -126,14 +139,16 @@ void TocWidget::setTreeDepth(int depth)
        int size = indices.size();
        for (int i = 0; i < size; i++) {
                QModelIndex index = indices[i];
-               tocTV->setExpanded(index, getIndexDepth(index) < depth_);
+               tocTV->setExpanded(index, indexDepth(index) < depth_);
        }
 }
 
 
-void TocWidget::on_typeCO_currentIndexChanged(int value)
+void TocWidget::on_typeCO_currentIndexChanged(int index)
 {
-       setTocModel(value);
+       current_type_ = typeCO->itemData(index).toString();
+       updateView();
+       gui_view_.setFocus();
 }
 
 
@@ -147,6 +162,7 @@ void TocWidget::outline(int func_code)
        goTo(list[0]);
        dispatch(FuncRequest(static_cast<FuncCode>(func_code)));
        enableControls(true);
+       gui_view_.setFocus();
 }
 
 
@@ -187,88 +203,102 @@ 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);
        moveDownTB->setEnabled(enable);
        moveInTB->setEnabled(enable);
        moveOutTB->setEnabled(enable);
-
-       depthSL->setEnabled(enable);
 }
 
 
-void TocWidget::updateView()
+/// Test if synchronized navigation is possible
+static bool canNavigate(QString const & type)
 {
-       LYXERR(Debug::GUI, "In TocWidget::updateView()");
-       setTreeDepth(depth_);
-       select(gui_view_.tocModels().currentIndex(typeCO->currentIndex()));
+       // It is not possible to have synchronous navigation in a correctl
+       // and efficient way with the label type because Toc::item() do a linear
+       // seatch. Even if fixed, it might even not be desirable to do so if we 
+       // want to support drag&drop of labels and references.
+       return type != "label";
 }
 
 
-void TocWidget::init(QString const & str)
+void TocWidget::updateView()
 {
-       QStringList const & type_names = gui_view_.tocModels().typeNames();
-       if (type_names.isEmpty()) {
+       if (!gui_view_.view()) {
                enableControls(false);
-               typeCO->clear();
-               tocTV->setModel(new QStandardItemModel);
-               tocTV->setEditTriggers(QAbstractItemView::NoEditTriggers);
+               typeCO->setEnabled(false);
+               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);
+       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 && toc_model->rowCount() > 0
+               && !gui_view_.buffer()->isReadonly();
+       enableControls(controls_enabled);
 
-       typeCO->blockSignals(false);
-
-       setTocModel(typeCO->currentIndex());
+       depthSL->setMaximum(gui_view_.tocModels().depth(current_type_));
+       depthSL->setValue(depth_);
+       setTreeDepth(depth_);
+       if (canNavigate(current_type_))
+               select(gui_view_.tocModels().currentIndex(current_type_));
 }
 
 
-void TocWidget::setTocModel(size_t type)
+static QString decodeType(QString const & str)
 {
-       bool controls_enabled = false;
-       QStandardItemModel * toc_model = gui_view_.tocModels().model(type);
-       if (toc_model) {
-               controls_enabled = toc_model->rowCount() > 0;
-               tocTV->setModel(toc_model);
-               tocTV->setEditTriggers(QAbstractItemView::NoEditTriggers);
-               LYXERR(Debug::GUI, "tocModel()->rowCount "
-                       << toc_model->rowCount()
-                       << "\nform_->tocModel()->columnCount "
-                       << toc_model->columnCount());
+       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;
+}
 
-       enableControls(controls_enabled);
 
-       if (controls_enabled) {
-               depthSL->setMaximum(gui_view_.tocModels().depth(type));
-               depthSL->setValue(depth_);
+void TocWidget::init(QString const & str)
+{
+       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_);
        }
 
-       // 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()));
+       typeCO->blockSignals(true);
+       typeCO->setCurrentIndex(new_index);
+       typeCO->blockSignals(false);
 }
 
 } // namespace frontend