]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/TocModel.cpp
f432d3c1f3c5a517bddde08d37cdc823adc04867
[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 <climits>
29
30 using namespace std;
31
32 namespace lyx {
33 namespace frontend {
34
35
36 TocItem const & TocModel::tocItem(QModelIndex const & index) const
37 {
38         return toc_[data(index, Qt::UserRole).toUInt()];
39 }
40
41
42 QModelIndex TocModel::modelIndex(DocIterator const & dit) const
43 {
44         size_t const toc_index = toc_.item(dit) - toc_.begin();
45
46         QModelIndexList list = match(index(0, 0), Qt::UserRole,
47                 QVariant(toc_index), 1,
48                 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive));
49
50         LASSERT(!list.isEmpty(), return QModelIndex());
51         return list[0];
52 }
53
54
55 void TocModel::clear()
56 {
57         QStandardItemModel::clear();
58         removeRows(0, rowCount());
59         removeColumns(0, columnCount());
60 }
61
62
63 TocModel::TocModel(Toc const & toc): toc_(toc)
64 {
65         if (toc_.empty())
66                 return;
67         int current_row;
68         QModelIndex top_level_item;
69         insertColumns(0, 1);
70         maxdepth_ = 0;
71         mindepth_ = INT_MAX;
72
73         size_t end = toc.size();
74         for (size_t index = 0; index != end; ++index) {
75                 TocItem const & item = toc_[index];
76                 maxdepth_ = max(maxdepth_, item.depth());
77                 mindepth_ = min(mindepth_, item.depth());
78                 current_row = rowCount();
79                 insertRows(current_row, 1);
80                 top_level_item = QStandardItemModel::index(current_row, 0);
81                 setData(top_level_item, toqstr(item.str()), Qt::DisplayRole);
82                 setData(top_level_item, index, Qt::UserRole);
83
84                 LYXERR(Debug::GUI, "Toc: at depth " << item.depth()
85                         << ", added item " << item.str());
86
87                 populate(index, top_level_item);
88                 if (index >= end)
89                         break;
90         }
91
92         setHeaderData(0, Qt::Horizontal, QVariant("title"), Qt::DisplayRole);
93 //      emit headerDataChanged();
94 }
95
96
97 void TocModel::populate(size_t & index, QModelIndex const & parent)
98 {
99         int curdepth = toc_[index].depth() + 1;
100
101         int current_row;
102         QModelIndex child_item;
103         insertColumns(0, 1, parent);
104
105         size_t end = toc_.size();
106         ++index;
107         for (; index != end; ++index) {
108                 TocItem const & item = toc_[index];
109                 if (item.depth() < curdepth) {
110                         --index;
111                         return;
112                 }
113                 maxdepth_ = max(maxdepth_, item.depth());
114                 mindepth_ = min(mindepth_, item.depth());
115                 current_row = rowCount(parent);
116                 insertRows(current_row, 1, parent);
117                 child_item = QStandardItemModel::index(current_row, 0, parent);
118                 setData(child_item, toqstr(item.str()), Qt::DisplayRole);
119                 setData(child_item, index, Qt::UserRole);
120                 populate(index, child_item);
121                 if (index >= end)
122                         break;
123         }
124 }
125
126
127 int TocModel::modelDepth() const
128 {
129         return maxdepth_ - mindepth_;
130 }
131
132
133 ///////////////////////////////////////////////////////////////////////////////
134 // TocModels implementation.
135 ///////////////////////////////////////////////////////////////////////////////
136 void TocModels::clear() 
137 {
138         types_.clear();
139         type_names_.clear();
140         const unsigned int size = models_.size();
141         for (unsigned int i = 0; i < size; ++i) {
142                 delete models_[i];
143         }
144         models_.clear();
145 }
146
147
148 int TocModels::depth(int type)
149 {
150         if (type < 0)
151                 return 0;
152         return models_[type]->modelDepth();
153 }
154
155
156 QStandardItemModel * TocModels::model(int type)
157 {
158         if (type < 0)
159                 return 0;
160
161         if (models_.empty()) {
162                 LYXERR(Debug::GUI, "TocModels::tocModel(): no types available ");
163                 return 0;
164         }
165
166         LYXERR(Debug::GUI, "TocModels: type " << type
167                 << "  models_.size() " << models_.size());
168
169         LASSERT(type >= 0 && type < int(models_.size()), /**/);
170         return models_[type];
171 }
172
173
174 QModelIndex TocModels::currentIndex(int type) const
175 {
176         if (type < 0 || !bv_)
177                 return QModelIndex();
178         return models_[type]->modelIndex(bv_->cursor());
179 }
180
181
182 void TocModels::goTo(int type, QModelIndex const & index) const
183 {
184         if (type < 0 || !index.isValid()
185                 || index.model() != models_[type]) {
186                 LYXERR(Debug::GUI, "TocModels::goTo(): QModelIndex is invalid!");
187                 return;
188         }
189
190         LASSERT(type >= 0 && type < int(models_.size()), /**/);
191         TocItem const item = models_[type]->tocItem(index);
192         LYXERR(Debug::GUI, "TocModels::goTo " << item.str());
193         dispatch(item.action());
194 }
195
196
197 void TocModels::updateBackend() const
198 {
199         bv_->buffer().masterBuffer()->tocBackend().update();
200         bv_->buffer().structureChanged();
201 }
202
203
204 void TocModels::reset(BufferView const * bv)
205 {
206         bv_ = bv;
207         clear();
208         if (!bv_)
209                 return;
210
211         TocList const & tocs = bv_->buffer().masterBuffer()->tocBackend().tocs();
212         TocList::const_iterator it = tocs.begin();
213         TocList::const_iterator end = tocs.end();
214         for (; it != end; ++it) {
215                 types_.push_back(toqstr(it->first));
216                 type_names_.push_back(guiName(it->first, bv->buffer().params()));
217                 models_.push_back(new TocModel(it->second));
218         }
219 }
220
221
222 bool TocModels::canOutline(int type) const
223 {
224         if (type < 0 || type >= types_.size())
225                 return false;
226         return types_[type] == "tableofcontents";
227 }
228
229
230 int TocModels::decodeType(QString const & str) const
231 {
232         QString new_type;
233         if (str.contains("tableofcontents")) {
234                 new_type = "tableofcontents";
235         } else if (str.contains("floatlist")) {
236                 if (str.contains("\"figure"))
237                         new_type = "figure";
238                 else if (str.contains("\"table"))
239                         new_type = "table";
240                 else if (str.contains("\"algorithm"))
241                         new_type = "algorithm";
242         } else if (!str.isEmpty()) {
243                 new_type = str;
244         } else {
245                 // Default to Outliner.
246                 new_type = "tableofcontents";
247         }
248         int const type = types_.indexOf(new_type);
249         if (type != -1)
250                 return type;
251         // If everything else fails, settle on the table of contents which is
252         // guaranted to exist.
253         return types_.indexOf("tableofcontents");
254 }
255
256 } // namespace frontend
257 } // namespace lyx
258
259 #include "TocModel_moc.cpp"