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