]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/TocWidget.cpp
eb3fc493314bdcff8b4d1af1fdd177632371a736
[lyx.git] / src / frontends / qt4 / TocWidget.cpp
1 /**
2  * \file TocWidget.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Abdelrazak Younes
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "TocWidget.h"
15
16 #include "GuiView.h"
17 #include "qt_helpers.h"
18 #include "TocModel.h"
19
20 #include "FuncRequest.h"
21 #include "LyXFunc.h"
22
23 #include "support/debug.h"
24 #include "support/lassert.h"
25
26 #include <QHeaderView>
27 #include <QTimer>
28
29 #include <vector>
30
31 using namespace std;
32
33 namespace lyx {
34 namespace frontend {
35
36 TocWidget::TocWidget(GuiView & gui_view, QWidget * parent)
37         : QWidget(parent), depth_(0), gui_view_(gui_view)
38 {
39         setupUi(this);
40
41         moveOutTB->setIcon(QIcon(":/images/promote.png"));
42         moveInTB->setIcon(QIcon(":/images/demote.png"));
43         moveUpTB->setIcon(QIcon(":/images/up.png"));
44         moveDownTB->setIcon(QIcon(":/images/down.png"));
45         updateTB->setIcon(QIcon(":/images/reload.png"));
46
47         // avoid flickering
48         tocTV->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
49
50         tocTV->showColumn(0);
51
52         // hide the pointless QHeader for now
53         // in the future, new columns may appear
54         // like labels, bookmarks, etc...
55         // tocTV->header()->hide();
56         tocTV->header()->setVisible(false);
57
58         // Only one item selected at a time.
59         tocTV->setSelectionMode(QAbstractItemView::SingleSelection);
60 }
61
62
63 void TocWidget::on_tocTV_activated(QModelIndex const & index)
64 {
65         goTo(index);
66 }
67
68
69 void TocWidget::on_tocTV_clicked(QModelIndex const & index)
70 {
71         goTo(index);
72         gui_view_.setFocus();
73 }
74
75
76 void TocWidget::goTo(QModelIndex const & index)
77 {
78         LYXERR(Debug::GUI, "goto " << index.row()
79                 << ", " << index.column());
80
81         gui_view_.tocModels().goTo(typeCO->currentIndex(), index);
82 }
83
84
85 void TocWidget::on_updateTB_clicked()
86 {
87         // The backend update can take some time so we disable
88         // the controls while waiting.
89         enableControls(false);
90         gui_view_.tocModels().updateBackend();
91 }
92
93
94 /* FIXME (Ugras 17/11/06):
95 I have implemented a indexDepth function to get the model indices. In my
96 opinion, somebody should derive a new qvariant class for tocModelItem
97 which saves the string data and depth information. That will save the
98 depth calculation.  */
99
100 static int indexDepth(QModelIndex const & index, int depth = -1)
101 {
102         ++depth;
103         return index.parent() == QModelIndex()
104                 ? depth : indexDepth(index.parent(), depth);
105 }
106
107
108 void TocWidget::on_depthSL_valueChanged(int depth)
109 {
110         if (depth == depth_)
111                 return;
112         setTreeDepth(depth);
113         gui_view_.setFocus();
114 }
115
116
117 void TocWidget::setTreeDepth(int depth)
118 {
119         depth_ = depth;
120
121         // expanding and then collapsing is probably better,
122         // but my qt 4.1.2 doesn't have expandAll()..
123         //tocTV->expandAll();
124         QModelIndexList indices = tocTV->model()->match(
125                 tocTV->model()->index(0,0),
126                 Qt::DisplayRole, "*", -1,
127                 Qt::MatchFlags(Qt::MatchWildcard|Qt::MatchRecursive));
128
129         int size = indices.size();
130         for (int i = 0; i < size; i++) {
131                 QModelIndex index = indices[i];
132                 tocTV->setExpanded(index, indexDepth(index) < depth_);
133         }
134 }
135
136
137 void TocWidget::on_typeCO_currentIndexChanged(int)
138 {
139         updateView();
140         gui_view_.setFocus();
141 }
142
143
144 void TocWidget::outline(int func_code)
145 {
146         enableControls(false);
147         QModelIndexList const & list = tocTV->selectionModel()->selectedIndexes();
148         if (list.isEmpty())
149                 return;
150         enableControls(false);
151         goTo(list[0]);
152         dispatch(FuncRequest(static_cast<FuncCode>(func_code)));
153         enableControls(true);
154         gui_view_.setFocus();
155 }
156
157
158 void TocWidget::on_moveUpTB_clicked()
159 {
160         outline(LFUN_OUTLINE_UP);
161 }
162
163
164 void TocWidget::on_moveDownTB_clicked()
165 {
166         outline(LFUN_OUTLINE_DOWN);
167 }
168
169
170 void TocWidget::on_moveInTB_clicked()
171 {
172         outline(LFUN_OUTLINE_IN);
173 }
174
175
176 void TocWidget::on_moveOutTB_clicked()
177 {
178         outline(LFUN_OUTLINE_OUT);
179 }
180
181
182 void TocWidget::select(QModelIndex const & index)
183 {
184         if (!index.isValid()) {
185                 LYXERR(Debug::GUI, "TocWidget::select(): QModelIndex is invalid!");
186                 return;
187         }
188
189         tocTV->scrollTo(index);
190         tocTV->clearSelection();
191         tocTV->setCurrentIndex(index);
192 }
193
194
195 void TocWidget::enableControls(bool enable)
196 {
197         updateTB->setEnabled(enable);
198
199         if (!gui_view_.tocModels().canOutline(typeCO->currentIndex()))
200                 enable = false;
201
202         moveUpTB->setEnabled(enable);
203         moveDownTB->setEnabled(enable);
204         moveInTB->setEnabled(enable);
205         moveOutTB->setEnabled(enable);
206
207         depthSL->setEnabled(enable);
208 }
209
210
211 void TocWidget::updateView()
212 {
213         LYXERR(Debug::GUI, "In TocWidget::updateView()");
214         setTocModel();
215         setTreeDepth(depth_);
216         select(gui_view_.tocModels().currentIndex(typeCO->currentIndex()));
217 }
218
219
220 void TocWidget::init(QString const & str)
221 {
222         QStringList const & type_names = gui_view_.tocModels().typeNames();
223         if (type_names.isEmpty()) {
224                 enableControls(false);
225                 typeCO->setEnabled(false);
226                 tocTV->setModel(new QStandardItemModel);
227                 tocTV->setEnabled(false);
228                 return;
229         }
230
231         typeCO->setEnabled(true);
232         tocTV->setEnabled(true);
233         int selected_type = gui_view_.tocModels().decodeType(str);
234
235         QString const current_text = typeCO->currentText();
236         typeCO->blockSignals(true);
237         typeCO->clear();
238         for (int i = 0; i != type_names.size(); ++i)
239                 typeCO->addItem(type_names[i]);
240         if (!str.isEmpty())
241                 typeCO->setCurrentIndex(selected_type);
242         else {
243                 int const new_index = typeCO->findText(current_text);
244                 if (new_index != -1)
245                         typeCO->setCurrentIndex(new_index);
246                 else
247                         typeCO->setCurrentIndex(selected_type);
248         }
249
250         typeCO->blockSignals(false);
251
252         // setTocModel produce QTreeView reset and setting depth again
253         // is needed. That must be done after all Qt updates are processed.
254         QTimer::singleShot(0, this, SLOT(updateView()));
255 }
256
257
258 void TocWidget::setTocModel()
259 {
260         int const toc_type = typeCO->currentIndex();
261         QStandardItemModel * toc_model = gui_view_.tocModels().model(toc_type);
262         LASSERT(toc_model, return);
263         
264         if (tocTV->model() != toc_model) {
265                 tocTV->setModel(toc_model);
266                 tocTV->setEditTriggers(QAbstractItemView::NoEditTriggers);
267         }
268
269         bool controls_enabled = toc_model->rowCount() > 0;;
270         enableControls(controls_enabled);
271
272         if (controls_enabled) {
273                 depthSL->setMaximum(gui_view_.tocModels().depth(toc_type));
274                 depthSL->setValue(depth_);
275         }
276 }
277
278 } // namespace frontend
279 } // namespace lyx
280
281 #include "TocWidget_moc.cpp"