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