]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/TocModel.cpp
reverse Toc searching: use DocIterator instead of ParconsIterator.
[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 "BufferParams.h"
18 #include "BufferView.h"
19 #include "DocIterator.h"
20 #include "Cursor.h"
21 #include "FloatList.h"
22 #include "FuncRequest.h"
23 #include "LyXFunc.h"
24 #include "TextClass.h"
25
26 #include "support/convert.h"
27 #include "support/debug.h"
28 #include "support/lassert.h"
29
30 #include <climits>
31
32 using namespace std;
33
34 namespace lyx {
35 namespace frontend {
36
37 typedef std::pair<QModelIndex, TocIterator> TocPair;
38
39
40 TocIterator TocModel::tocIterator(QModelIndex const & index) const
41 {
42         TocMap::const_iterator map_it = toc_map_.find(index);
43         LASSERT(map_it != toc_map_.end(), /**/);
44         return map_it->second;
45 }
46
47
48 QModelIndex TocModel::modelIndex(TocIterator const & it) const
49 {
50         ModelMap::const_iterator map_it = model_map_.find(it);
51         //LASSERT(it != model_map_.end(), /**/);
52
53         if (map_it == model_map_.end())
54                 return QModelIndex();
55
56         return map_it->second;
57 }
58
59
60 void TocModel::clear()
61 {
62         QStandardItemModel::clear();
63         toc_map_.clear();
64         model_map_.clear();
65         removeRows(0, rowCount());
66         removeColumns(0, columnCount());
67 }
68
69
70 void TocModel::populate(Toc const & toc)
71 {
72         clear();
73
74         if (toc.empty())
75                 return;
76         int current_row;
77         QModelIndex top_level_item;
78
79         TocIterator iter = toc.begin();
80         TocIterator end = toc.end();
81
82         insertColumns(0, 1);
83         maxdepth_ = 0;
84         mindepth_ = INT_MAX;
85
86         while (iter != end) {
87                 maxdepth_ = max(maxdepth_, iter->depth());
88                 mindepth_ = min(mindepth_, iter->depth());
89                 current_row = rowCount();
90                 insertRows(current_row, 1);
91                 top_level_item = QStandardItemModel::index(current_row, 0);
92                 //setData(top_level_item, toqstr(iter->str()));
93                 setData(top_level_item, toqstr(iter->str()), Qt::DisplayRole);
94
95                 // This looks like a gcc bug, in principle this should work:
96                 //toc_map_[top_level_item] = iter;
97                 // but it crashes with gcc-4.1 and 4.0.2
98                 toc_map_.insert( TocPair(top_level_item, iter) );
99                 model_map_[iter] = top_level_item;
100
101                 LYXERR(Debug::GUI, "Toc: at depth " << iter->depth()
102                         << ", added item " << toqstr(iter->str()));
103
104                 populate(iter, end, top_level_item);
105
106                 if (iter == end)
107                         break;
108
109                 ++iter;
110         }
111
112         setHeaderData(0, Qt::Horizontal, QVariant("title"), Qt::DisplayRole);
113 //      emit headerDataChanged();
114 }
115
116
117 void TocModel::populate(TocIterator & iter, TocIterator const & end,
118         QModelIndex const & parent)
119 {
120         int curdepth = iter->depth() + 1;
121
122         int current_row;
123         QModelIndex child_item;
124         insertColumns(0, 1, parent);
125
126         while (iter != end) {
127                 ++iter;
128
129                 if (iter == end)
130                         break;
131
132                 if (iter->depth() < curdepth) {
133                         --iter;
134                         return;
135                 }
136
137                 maxdepth_ = max(maxdepth_, iter->depth());
138                 mindepth_ = min(mindepth_, iter->depth());
139                 current_row = rowCount(parent);
140                 insertRows(current_row, 1, parent);
141                 child_item = QStandardItemModel::index(current_row, 0, parent);
142                 //setData(child_item, toqstr(iter->str()));
143                 setData(child_item, toqstr(iter->str()), Qt::DisplayRole);
144
145                 // This looks like a gcc bug, in principle this should work:
146                 //toc_map_[child_item] = iter;
147                 // but it crashes with gcc-4.1 and 4.0.2
148                 toc_map_.insert( TocPair(child_item, iter) );
149                 model_map_[iter] = child_item;
150                 populate(iter, end, child_item);
151         }
152 }
153
154
155 int TocModel::modelDepth() const
156 {
157         return maxdepth_ - mindepth_;
158 }
159
160
161 ///////////////////////////////////////////////////////////////////////////////
162 // TocModels implementation.
163 ///////////////////////////////////////////////////////////////////////////////
164 void TocModels::clear() 
165 {
166         types_.clear();
167         type_names_.clear();
168         const unsigned int size = models_.size();
169         for (unsigned int i = 0; i < size; ++i) {
170                 delete models_[i];
171         }
172         models_.clear();
173 }
174
175
176 int TocModels::depth(int type)
177 {
178         if (type < 0)
179                 return 0;
180         return models_[type]->modelDepth();
181 }
182
183
184 QStandardItemModel * TocModels::model(int type)
185 {
186         if (type < 0)
187                 return 0;
188
189         if (models_.empty()) {
190                 LYXERR(Debug::GUI, "TocModels::tocModel(): no types available ");
191                 return 0;
192         }
193
194         LYXERR(Debug::GUI, "TocModels: type " << type
195                 << "  models_.size() " << models_.size());
196
197         LASSERT(type >= 0 && type < int(models_.size()), /**/);
198         return models_[type];
199 }
200
201
202 QModelIndex TocModels::currentIndex(int type) const
203 {
204         if (type < 0 || !bv_)
205                 return QModelIndex();
206
207         TocIterator const it = bv_->buffer().masterBuffer()->tocBackend().item(
208                 fromqstr(types_[type]), bv_->cursor());
209         return models_[type]->modelIndex(it);
210 }
211
212
213 void TocModels::goTo(int type, QModelIndex const & index) const
214 {
215         if (type < 0 || !index.isValid()
216                 || index.model() != models_[type]) {
217                 LYXERR(Debug::GUI, "TocModels::goTo(): QModelIndex is invalid!");
218                 return;
219         }
220
221         LASSERT(type >= 0 && type < int(models_.size()), /**/);
222         TocIterator const it = models_[type]->tocIterator(index);
223         LYXERR(Debug::GUI, "TocModels::goTo " << it->str());
224         dispatch(it->action());
225 }
226
227
228 void TocModels::updateBackend() const
229 {
230         bv_->buffer().masterBuffer()->tocBackend().update();
231         bv_->buffer().structureChanged();
232 }
233
234
235 QString TocModels::guiName(string const & type) const
236 {
237         if (type == "tableofcontents")
238                 return qt_("Table of Contents");
239         if (type == "child")
240                 return qt_("Child Documents");
241         if (type == "graphics")
242                 return qt_("List of Graphics");
243         if (type == "equation")
244                 return qt_("List of Equations");
245         if (type == "footnote")
246                 return qt_("List of Footnotes");
247         if (type == "listing")
248                 return qt_("List of Listings");
249         if (type == "index")
250                 return qt_("List of Indexes");
251         if (type == "marginalnote")
252                 return qt_("List of Marginal notes");
253         if (type == "note")
254                 return qt_("List of Notes");
255         if (type == "citation")
256                 return qt_("List of Citations");
257         if (type == "label")
258                 return qt_("Labels and References");
259
260         FloatList const & floats = bv_->buffer().params().documentClass().floats();
261         if (floats.typeExist(type))
262                 return qt_(floats.getType(type).listName());
263
264         return qt_(type);
265 }
266
267
268 void TocModels::reset(BufferView const * bv)
269 {
270         bv_ = bv;
271         clear();
272         if (!bv_)
273                 return;
274
275         TocList const & tocs = bv_->buffer().masterBuffer()->tocBackend().tocs();
276         TocList::const_iterator it = tocs.begin();
277         TocList::const_iterator end = tocs.end();
278         for (; it != end; ++it) {
279                 types_.push_back(toqstr(it->first));
280                 type_names_.push_back(guiName(it->first));
281                 models_.push_back(new TocModel(it->second));
282         }
283 }
284
285
286 bool TocModels::canOutline(int type) const
287 {
288         if (type < 0 || type >= types_.size())
289                 return false;
290         return types_[type] == "tableofcontents";
291 }
292
293
294 int TocModels::decodeType(QString const & str) const
295 {
296         QString new_type;
297         if (str.contains("tableofcontents")) {
298                 new_type = "tableofcontents";
299         } else if (str.contains("floatlist")) {
300                 if (str.contains("\"figure"))
301                         new_type = "figure";
302                 else if (str.contains("\"table"))
303                         new_type = "table";
304                 else if (str.contains("\"algorithm"))
305                         new_type = "algorithm";
306         } else if (!str.isEmpty()) {
307                 new_type = str;
308         } else {
309                 // Default to Outliner.
310                 new_type = "tableofcontents";
311         }
312         return types_.indexOf(new_type);
313 }
314
315 } // namespace frontend
316 } // namespace lyx
317
318 #include "TocModel_moc.cpp"