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