]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/TocModel.cpp
73e20c65901c3167e1c1579feb1e557e2107e06d
[lyx.git] / src / frontends / qt4 / TocModel.cpp
1 /**
2  * \file TocModel.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 "TocModel.h"
15
16 #include "Buffer.h"
17 #include "BufferView.h"
18 #include "Cursor.h"
19 #include "DocIterator.h"
20 #include "FuncRequest.h"
21 #include "LyXFunc.h"
22 #include "TocBackend.h"
23
24 #include "support/convert.h"
25 #include "support/debug.h"
26 #include "support/lassert.h"
27
28 #include <QSortFilterProxyModel>
29
30 #include <climits>
31
32 using namespace std;
33
34 namespace lyx {
35 namespace frontend {
36
37 ///////////////////////////////////////////////////////////////////////////////
38 //
39 // TocTypeModel
40 //
41 ///////////////////////////////////////////////////////////////////////////////
42
43 TocTypeModel::TocTypeModel(QObject * parent)
44         : QStandardItemModel(parent)
45 {
46 }
47
48
49 void TocTypeModel::reset()
50 {
51         QStandardItemModel::reset();
52 }
53
54
55 ///////////////////////////////////////////////////////////////////////////////
56 //
57 // TocModel
58 //
59 ///////////////////////////////////////////////////////////////////////////////
60
61 TocModel::TocModel(QObject * parent)
62         : model_(new TocTypeModel(parent)),
63         sorted_model_(new QSortFilterProxyModel(parent)),
64         is_sorted_(false), maxdepth_(0), mindepth_(0)
65 {
66 #if QT_VERSION >= 0x040300
67         sorted_model_->setSortLocaleAware(true);
68 #endif
69         sorted_model_->setSourceModel(model_);
70 }
71
72
73 QAbstractItemModel * TocModel::model()
74 {
75         if (is_sorted_)
76                 return sorted_model_;
77         return model_;
78 }
79
80
81 QAbstractItemModel const * TocModel::model() const
82 {
83         if (is_sorted_)
84                 return sorted_model_;
85         return model_;
86 }
87
88
89 void TocModel::clear()
90 {
91         model_->blockSignals(true);
92         model_->clear();
93         model_->blockSignals(false);
94 }
95
96
97 void TocModel::sort(bool sort_it)
98 {
99         is_sorted_ = sort_it;
100         if (is_sorted_)
101                 sorted_model_->sort(0);
102 }
103
104
105 TocItem const & TocModel::tocItem(QModelIndex const & index) const
106 {
107         return (*toc_)[model()->data(index, Qt::UserRole).toUInt()];
108 }
109
110
111 QModelIndex TocModel::modelIndex(DocIterator const & dit) const
112 {
113         if (toc_->empty())
114                 return QModelIndex();
115
116         unsigned int const toc_index = toc_->item(dit) - toc_->begin();
117
118         QModelIndexList list = model()->match(model()->index(0, 0), Qt::UserRole,
119                 QVariant(toc_index), 1,
120                 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive));
121
122         LASSERT(!list.isEmpty(), return QModelIndex());
123         return list[0];
124 }
125
126
127 void TocModel::reset()
128 {
129         model_->reset();
130 }
131
132
133 void TocModel::reset(Toc const & toc)
134 {
135         toc_ = &toc;
136         if (toc_->empty()) {
137                 maxdepth_ = 0;
138                 mindepth_ = 0;
139                 reset();
140                 return;
141         }
142
143         model_->blockSignals(true);
144         model_->insertColumns(0, 1);
145         maxdepth_ = 0;
146         mindepth_ = INT_MAX;
147
148         size_t end = toc_->size();
149         for (unsigned int index = 0; index != end; ++index) {
150                 TocItem const & item = (*toc_)[index];
151                 maxdepth_ = max(maxdepth_, item.depth());
152                 mindepth_ = min(mindepth_, item.depth());
153                 int current_row = model_->rowCount();
154                 model_->insertRows(current_row, 1);
155                 QModelIndex top_level_item = model_->index(current_row, 0);
156                 model_->setData(top_level_item, toqstr(item.str()), Qt::DisplayRole);
157                 model_->setData(top_level_item, index, Qt::UserRole);
158
159                 LYXERR(Debug::GUI, "Toc: at depth " << item.depth()
160                         << ", added item " << item.str());
161
162                 populate(index, top_level_item);
163                 if (index >= end)
164                         break;
165         }
166
167         model_->setHeaderData(0, Qt::Horizontal, QVariant("title"), Qt::DisplayRole);
168         if (is_sorted_)
169                 sorted_model_->sort(0);
170         model_->blockSignals(false);
171         reset();
172 //      emit headerDataChanged();
173 }
174
175
176 void TocModel::populate(unsigned int & index, QModelIndex const & parent)
177 {
178         int curdepth = (*toc_)[index].depth() + 1;
179
180         int current_row;
181         QModelIndex child_item;
182         model_->insertColumns(0, 1, parent);
183
184         size_t end = toc_->size();
185         ++index;
186         for (; index != end; ++index) {
187                 TocItem const & item = (*toc_)[index];
188                 if (item.depth() < curdepth) {
189                         --index;
190                         return;
191                 }
192                 maxdepth_ = max(maxdepth_, item.depth());
193                 mindepth_ = min(mindepth_, item.depth());
194                 current_row = model_->rowCount(parent);
195                 model_->insertRows(current_row, 1, parent);
196                 child_item = model_->index(current_row, 0, parent);
197                 model_->setData(child_item, toqstr(item.str()), Qt::DisplayRole);
198                 model_->setData(child_item, index, Qt::UserRole);
199                 populate(index, child_item);
200                 if (index >= end)
201                         break;
202         }
203 }
204
205
206 int TocModel::modelDepth() const
207 {
208         int const d = maxdepth_ - mindepth_;
209         LASSERT(d >= 0 && d <= 100, return 0);
210         return d;
211 }
212
213
214 ///////////////////////////////////////////////////////////////////////////////
215 //
216 // TocModels
217 //
218 ///////////////////////////////////////////////////////////////////////////////
219
220 TocModels::TocModels()
221         : bv_(0)
222 {
223         names_ = new TocTypeModel(this);
224         names_sorted_ = new QSortFilterProxyModel(this);
225         names_sorted_->setSourceModel(names_);
226 #if QT_VERSION >= 0x040300
227         names_sorted_->setSortLocaleAware(true);
228 #endif
229         names_sorted_->sort(0);
230 }
231
232
233 void TocModels::clear() 
234 {
235         names_->blockSignals(true);
236         names_->clear();
237         names_->blockSignals(false);
238         iterator end = models_.end();
239         for (iterator it = models_.begin(); it != end;  ++it)
240                 it.value()->clear();
241 }
242
243
244 int TocModels::depth(QString const & type)
245 {
246         const_iterator it = models_.find(type);
247         if (!bv_ || it == models_.end())
248                 return 0;
249         return it.value()->modelDepth();
250 }
251
252
253 QAbstractItemModel * TocModels::model(QString const & type)
254 {
255         if (!bv_)
256                 return 0;
257         iterator it = models_.find(type);
258         if (it != models_.end())
259                 return it.value()->model();
260         LYXERR0("type not found: " << type);
261         return 0;
262 }
263
264
265 QAbstractItemModel * TocModels::nameModel()
266 {
267         return names_sorted_;
268 }
269
270
271 QModelIndex TocModels::currentIndex(QString const & type) const
272 {
273         const_iterator it = models_.find(type);
274         if (!bv_ || it == models_.end())
275                 return QModelIndex();
276         return it.value()->modelIndex(bv_->cursor());
277 }
278
279
280 void TocModels::goTo(QString const & type, QModelIndex const & index) const
281 {
282         const_iterator it = models_.find(type);
283         if (it == models_.end() || !index.isValid()) {
284                 LYXERR(Debug::GUI, "TocModels::goTo(): QModelIndex is invalid!");
285                 return;
286         }
287         LASSERT(index.model() == it.value()->model(), return);
288         TocItem const item = it.value()->tocItem(index);
289         LYXERR(Debug::GUI, "TocModels::goTo " << item.str());
290         dispatch(item.action());
291 }
292
293
294 void TocModels::updateBackend() const
295 {
296         bv_->buffer().masterBuffer()->tocBackend().update();
297         bv_->buffer().structureChanged();
298 }
299
300
301 void TocModels::reset(BufferView const * bv)
302 {
303         bv_ = bv;
304         clear();
305         if (!bv_) {
306                 iterator end = models_.end();
307                 for (iterator it = models_.begin(); it != end;  ++it)
308                         it.value()->reset();
309                 names_->reset();
310                 return;
311         }
312
313         names_->blockSignals(true);
314         names_->insertColumns(0, 1);
315         TocList const & tocs = bv_->buffer().masterBuffer()->tocBackend().tocs();
316         TocList::const_iterator it = tocs.begin();
317         TocList::const_iterator toc_end = tocs.end();
318         for (; it != toc_end; ++it) {
319                 QString const type = toqstr(it->first);
320
321                 // First, fill in the toc models.
322                 iterator mod_it = models_.find(type);
323                 if (mod_it == models_.end())
324                         mod_it = models_.insert(type, new TocModel(this));
325                 mod_it.value()->reset(it->second);
326
327                 // Fill in the names_ model.
328                 QString const gui_name = guiName(it->first, bv->buffer().params());
329                 int const current_row = names_->rowCount();
330                 names_->insertRows(current_row, 1);
331                 QModelIndex const index = names_->index(current_row, 0);
332                 names_->setData(index, gui_name, Qt::DisplayRole);
333                 names_->setData(index, type, Qt::UserRole);
334         }
335         names_->blockSignals(false);
336         names_->reset();
337 }
338
339
340 bool TocModels::isSorted(QString const & type) const
341 {
342         const_iterator it = models_.find(type);
343         if (it == models_.end()) {
344                 LYXERR0("type not found: " << type);
345                 return false;
346         }
347         return it.value()->isSorted();
348 }
349
350
351 void TocModels::sort(QString const & type, bool sort_it)
352 {
353         iterator it = models_.find(type);
354         if (it == models_.end())
355                 LYXERR0("type not found: " << type);
356         else
357                 it.value()->sort(sort_it);
358 }
359
360 } // namespace frontend
361 } // namespace lyx
362
363 #include "TocModel_moc.cpp"