]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/TocWidget.cpp
TocWidget: Small reorg in order to fix http://bugzilla.lyx.org/show_bug.cgi?id=4940
[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 /* FIXME (Ugras 17/11/06):
94 I have implemented a getIndexDepth function to get the model indices. In my
95 opinion, somebody should derive a new qvariant class for tocModelItem
96 which saves the string data and depth information. that will save the
97 depth calculation.
98 */
99 int TocWidget::getIndexDepth(QModelIndex const & index, int depth)
100 {
101         ++depth;
102         return (index.parent() == QModelIndex())
103                 ? depth : getIndexDepth(index.parent(),depth);
104 }
105
106
107 void TocWidget::on_depthSL_valueChanged(int depth)
108 {
109         if (depth == depth_)
110                 return;
111         setTreeDepth(depth);
112         gui_view_.setFocus();
113 }
114
115
116 void TocWidget::setTreeDepth(int depth)
117 {
118         depth_ = depth;
119
120         // expanding and then collapsing is probably better,
121         // but my qt 4.1.2 doesn't have expandAll()..
122         //tocTV->expandAll();
123         QModelIndexList indices = tocTV->model()->match(
124                 tocTV->model()->index(0,0),
125                 Qt::DisplayRole, "*", -1,
126                 Qt::MatchFlags(Qt::MatchWildcard|Qt::MatchRecursive));
127
128         int size = indices.size();
129         for (int i = 0; i < size; i++) {
130                 QModelIndex index = indices[i];
131                 tocTV->setExpanded(index, getIndexDepth(index) < depth_);
132         }
133 }
134
135
136 void TocWidget::on_typeCO_currentIndexChanged(int)
137 {
138         updateView();
139         gui_view_.setFocus();
140 }
141
142
143 void TocWidget::outline(int func_code)
144 {
145         enableControls(false);
146         QModelIndexList const & list = tocTV->selectionModel()->selectedIndexes();
147         if (list.isEmpty())
148                 return;
149         enableControls(false);
150         goTo(list[0]);
151         dispatch(FuncRequest(static_cast<FuncCode>(func_code)));
152         enableControls(true);
153         gui_view_.setFocus();
154 }
155
156
157 void TocWidget::on_moveUpTB_clicked()
158 {
159         outline(LFUN_OUTLINE_UP);
160 }
161
162
163 void TocWidget::on_moveDownTB_clicked()
164 {
165         outline(LFUN_OUTLINE_DOWN);
166 }
167
168
169 void TocWidget::on_moveInTB_clicked()
170 {
171         outline(LFUN_OUTLINE_IN);
172 }
173
174
175 void TocWidget::on_moveOutTB_clicked()
176 {
177         outline(LFUN_OUTLINE_OUT);
178 }
179
180
181 void TocWidget::select(QModelIndex const & index)
182 {
183         if (!index.isValid()) {
184                 LYXERR(Debug::GUI, "TocWidget::select(): QModelIndex is invalid!");
185                 return;
186         }
187
188         tocTV->scrollTo(index);
189         tocTV->clearSelection();
190         tocTV->setCurrentIndex(index);
191 }
192
193
194 void TocWidget::enableControls(bool enable)
195 {
196         updateTB->setEnabled(enable);
197
198         if (!gui_view_.tocModels().canOutline(typeCO->currentIndex()))
199                 enable = false;
200
201         moveUpTB->setEnabled(enable);
202         moveDownTB->setEnabled(enable);
203         moveInTB->setEnabled(enable);
204         moveOutTB->setEnabled(enable);
205
206         depthSL->setEnabled(enable);
207 }
208
209
210 void TocWidget::updateView()
211 {
212         LYXERR(Debug::GUI, "In TocWidget::updateView()");
213         setTocModel();
214         setTreeDepth(depth_);
215         select(gui_view_.tocModels().currentIndex(typeCO->currentIndex()));
216 }
217
218
219 void TocWidget::init(QString const & str)
220 {
221         QStringList const & type_names = gui_view_.tocModels().typeNames();
222         if (type_names.isEmpty()) {
223                 enableControls(false);
224                 typeCO->setEnabled(false);
225                 tocTV->setModel(new QStandardItemModel);
226                 tocTV->setEnabled(false);
227                 return;
228         }
229
230         typeCO->setEnabled(true);
231         tocTV->setEnabled(true);
232         int selected_type = gui_view_.tocModels().decodeType(str);
233
234         QString const current_text = typeCO->currentText();
235         typeCO->blockSignals(true);
236         typeCO->clear();
237         for (int i = 0; i != type_names.size(); ++i)
238                 typeCO->addItem(type_names[i]);
239         if (!str.isEmpty())
240                 typeCO->setCurrentIndex(selected_type);
241         else {
242                 int const new_index = typeCO->findText(current_text);
243                 if (new_index != -1)
244                         typeCO->setCurrentIndex(new_index);
245                 else
246                         typeCO->setCurrentIndex(selected_type);
247         }
248
249         typeCO->blockSignals(false);
250
251         // setTocModel produce QTreeView reset and setting depth again
252         // is needed. That must be done after all Qt updates are processed.
253         QTimer::singleShot(0, this, SLOT(updateView()));
254 }
255
256
257 void TocWidget::setTocModel()
258 {
259         int const toc_type = typeCO->currentIndex();
260         QStandardItemModel * toc_model = gui_view_.tocModels().model(toc_type);
261         LASSERT(toc_model, return);
262         
263         if (tocTV->model() != toc_model) {
264                 tocTV->setModel(toc_model);
265                 tocTV->setEditTriggers(QAbstractItemView::NoEditTriggers);
266         }
267
268         bool controls_enabled = toc_model->rowCount() > 0;;
269         enableControls(controls_enabled);
270
271         if (controls_enabled) {
272                 depthSL->setMaximum(gui_view_.tocModels().depth(toc_type));
273                 depthSL->setValue(depth_);
274         }
275 }
276
277 } // namespace frontend
278 } // namespace lyx
279
280 #include "TocWidget_moc.cpp"