]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/TocModel.cpp
e50ca368a5a6222851a6a84633da43484e787378
[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 TocTypeModel::TocTypeModel(QObject * parent): QStandardItemModel(parent)
38 {
39 }
40
41
42 void TocTypeModel::reset()
43 {
44         QStandardItemModel::reset();
45 }
46
47
48 TocItem const & TocModel::tocItem(QModelIndex const & index) const
49 {
50         return (*toc_)[data(index, Qt::UserRole).toUInt()];
51 }
52
53
54 QModelIndex TocModel::modelIndex(DocIterator const & dit) const
55 {
56         if (toc_->empty())
57                 return QModelIndex();
58
59         unsigned int const toc_index = toc_->item(dit) - toc_->begin();
60
61         QModelIndexList list = match(index(0, 0), Qt::UserRole,
62                 QVariant(toc_index), 1,
63                 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive));
64
65         LASSERT(!list.isEmpty(), return QModelIndex());
66         return list[0];
67 }
68
69
70 TocModel::TocModel(QObject * parent): QStandardItemModel(parent)
71 {
72 }
73
74
75 void TocModel::reset()
76 {
77         QStandardItemModel::reset();
78 }
79
80
81 void TocModel::reset(Toc const & toc)
82 {
83         toc_ = &toc;
84         if (toc_->empty()) {
85                 reset();
86                 return;
87         }
88
89         blockSignals(true);
90         int current_row;
91         QModelIndex top_level_item;
92         insertColumns(0, 1);
93         maxdepth_ = 0;
94         mindepth_ = INT_MAX;
95
96         size_t end = toc_->size();
97         for (unsigned int index = 0; index != end; ++index) {
98                 TocItem const & item = (*toc_)[index];
99                 maxdepth_ = max(maxdepth_, item.depth());
100                 mindepth_ = min(mindepth_, item.depth());
101                 current_row = rowCount();
102                 insertRows(current_row, 1);
103                 top_level_item = QStandardItemModel::index(current_row, 0);
104                 setData(top_level_item, toqstr(item.str()), Qt::DisplayRole);
105                 setData(top_level_item, index, Qt::UserRole);
106
107                 LYXERR(Debug::GUI, "Toc: at depth " << item.depth()
108                         << ", added item " << item.str());
109
110                 populate(index, top_level_item);
111                 if (index >= end)
112                         break;
113         }
114
115         setHeaderData(0, Qt::Horizontal, QVariant("title"), Qt::DisplayRole);
116         blockSignals(false);
117         reset();
118 //      emit headerDataChanged();
119 }
120
121
122 void TocModel::populate(unsigned int & index, QModelIndex const & parent)
123 {
124         int curdepth = (*toc_)[index].depth() + 1;
125
126         int current_row;
127         QModelIndex child_item;
128         insertColumns(0, 1, parent);
129
130         size_t end = toc_->size();
131         ++index;
132         for (; index != end; ++index) {
133                 TocItem const & item = (*toc_)[index];
134                 if (item.depth() < curdepth) {
135                         --index;
136                         return;
137                 }
138                 maxdepth_ = max(maxdepth_, item.depth());
139                 mindepth_ = min(mindepth_, item.depth());
140                 current_row = rowCount(parent);
141                 insertRows(current_row, 1, parent);
142                 child_item = QStandardItemModel::index(current_row, 0, parent);
143                 setData(child_item, toqstr(item.str()), Qt::DisplayRole);
144                 setData(child_item, index, Qt::UserRole);
145                 populate(index, child_item);
146                 if (index >= end)
147                         break;
148         }
149 }
150
151
152 int TocModel::modelDepth() const
153 {
154         return maxdepth_ - mindepth_;
155 }
156
157
158 ///////////////////////////////////////////////////////////////////////////////
159 // TocModels implementation.
160 ///////////////////////////////////////////////////////////////////////////////
161
162 TocModels::TocModels(): bv_(0)
163 {
164         names_ = new TocTypeModel(this);
165         names_sorted_ = new QSortFilterProxyModel(this);
166         names_sorted_->setSourceModel(names_);
167 #if QT_VERSION >= 0x040300
168         names_sorted_->setSortLocaleAware(true);
169 #endif
170         names_sorted_->sort(0);
171 }
172
173
174 void TocModels::clear() 
175 {
176         names_->blockSignals(true);
177         names_->clear();
178         names_->blockSignals(false);
179         iterator end = models_.end();
180         for (iterator it = models_.begin(); it != end;  ++it) {
181                 it.value()->blockSignals(true);
182                 it.value()->clear();
183                 it.value()->blockSignals(false);
184         }
185 }
186
187
188 int TocModels::depth(QString const & type)
189 {
190         const_iterator it = models_.find(type);
191         if (!bv_ || it == models_.end())
192                 return 0;
193         return it.value()->modelDepth();
194 }
195
196
197 QStandardItemModel * TocModels::model(QString const & type)
198 {
199         if (!bv_)
200                 return 0;
201         iterator it = models_.find(type);
202         if (it != models_.end())
203                 return it.value();
204         LYXERR0("type not found: " << type);
205         return 0;
206 }
207
208
209 QAbstractItemModel * TocModels::nameModel()
210 {
211         return names_sorted_;
212 }
213
214
215 QModelIndex TocModels::currentIndex(QString const & type) const
216 {
217         const_iterator it = models_.find(type);
218         if (!bv_ || it == models_.end())
219                 return QModelIndex();
220         return it.value()->modelIndex(bv_->cursor());
221 }
222
223
224 void TocModels::goTo(QString const & type, QModelIndex const & index) const
225 {
226         const_iterator it = models_.find(type);
227         if (it == models_.end() || !index.isValid()) {
228                 LYXERR(Debug::GUI, "TocModels::goTo(): QModelIndex is invalid!");
229                 return;
230         }
231         LASSERT(index.model() == it.value(), return);
232         TocItem const item = it.value()->tocItem(index);
233         LYXERR(Debug::GUI, "TocModels::goTo " << item.str());
234         dispatch(item.action());
235 }
236
237
238 void TocModels::updateBackend() const
239 {
240         bv_->buffer().masterBuffer()->tocBackend().update();
241         bv_->buffer().structureChanged();
242 }
243
244
245 void TocModels::reset(BufferView const * bv)
246 {
247         bv_ = bv;
248         clear();
249         if (!bv_) {
250                 iterator end = models_.end();
251                 for (iterator it = models_.begin(); it != end;  ++it)
252                         it.value()->reset();
253                 names_->reset();
254                 return;
255         }
256
257         names_->blockSignals(true);
258         names_->insertColumns(0, 1);
259         TocList const & tocs = bv_->buffer().masterBuffer()->tocBackend().tocs();
260         TocList::const_iterator it = tocs.begin();
261         TocList::const_iterator toc_end = tocs.end();
262         for (; it != toc_end; ++it) {
263                 QString const type = toqstr(it->first);
264
265                 // First, fill in the toc models.
266                 iterator mod_it = models_.find(type);
267                 if (mod_it == models_.end())
268                         mod_it = models_.insert(type, new TocModel(this));
269                 mod_it.value()->reset(it->second);
270
271                 // Fill in the names_ model.
272                 QString const gui_name = guiName(it->first, bv->buffer().params());
273                 int const current_row = names_->rowCount();
274                 names_->insertRows(current_row, 1);
275                 QModelIndex const index = names_->index(current_row, 0);
276                 names_->setData(index, gui_name, Qt::DisplayRole);
277                 names_->setData(index, type, Qt::UserRole);
278         }
279         names_->blockSignals(false);
280         names_->reset();
281 }
282
283
284 } // namespace frontend
285 } // namespace lyx
286
287 #include "TocModel_moc.cpp"