]> git.lyx.org Git - lyx.git/blob - src/frontends/qt2/FormToc.C
implement getLabelList
[lyx.git] / src / frontends / qt2 / FormToc.C
1 /*
2  * FormToc.C
3  * (C) 2000 LyX Team
4  * John Levon, moz@compsoc.man.ac.uk
5  */
6
7 /***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15
16 #include <config.h>
17
18 #include <stack>
19
20 #include <qslider.h>
21 #include "FormTocDialog.h"
22 #undef emit
23
24 #include "Dialogs.h"
25 #include "FormToc.h"
26 #include "gettext.h"
27 #include "buffer.h"
28 #include "support/lstrings.h"
29 #include "QtLyXView.h"
30 #include "lyxfunc.h"
31 #include "debug.h"
32
33 using std::vector;
34 using std::pair;
35 using std::stack;
36 using std::endl;
37
38 #include <qlistview.h>
39 #include <qcombobox.h>
40  
41 FormToc::FormToc(LyXView *v, Dialogs *d)
42         : dialog_(0), lv_(v), d_(d), inset_(0), h_(0), u_(0), ih_(0),
43         toclist(0), type(Buffer::TOC_TOC), depth(1)
44 {
45         // let the dialog be shown
46         // This is a permanent connection so we won't bother
47         // storing a copy because we won't be disconnecting.
48         d->showTOC.connect(slot(this, &FormToc::showTOC));
49         d->createTOC.connect(slot(this, &FormToc::createTOC));
50 }
51
52 FormToc::~FormToc()
53 {
54         delete dialog_;
55 }
56
57 void FormToc::showTOC(InsetCommand * const inset)
58 {
59         // FIXME: when could inset be 0 here ?
60         if (inset==0)
61                 return;
62
63         inset_ = inset;
64         ih_ = inset_->hide.connect(slot(this,&FormToc::hide));
65         params = inset->params();
66         
67         show();
68 }
69
70 void FormToc::createTOC(string const & arg)
71 {
72         if (inset_)
73                 close();
74
75         params.setFromString(arg);
76         show();
77 }
78
79 void FormToc::updateToc(int newdepth)
80 {
81         if (!lv_->view()->available()) {
82                 toclist.clear();
83                 dialog_->tocLV->clear();
84                 return;
85         }
86
87         vector< vector<Buffer::TocItem> > tmp =
88                 lv_->view()->buffer()->getTocList();
89
90         // Check if all elements are the same.
91         if (newdepth==depth && toclist.size() == tmp[type].size()) {
92                 unsigned int i = 0;
93                 for (; i < toclist.size(); ++i) {
94                         if (toclist[i] !=  tmp[type][i])
95                                 break;
96                 }
97                 if (i >= toclist.size())
98                         return;
99         }
100
101         depth=newdepth;
102
103         toclist = tmp[type];
104
105         dialog_->tocLV->clear();
106         if (toclist.empty()) 
107                 return;
108
109         dialog_->tocLV->setUpdatesEnabled(false);
110
111         int curdepth = 0;
112         stack< pair< QListViewItem *, QListViewItem *> > istack;
113         QListViewItem *last = 0;
114         QListViewItem *parent = 0;
115         QListViewItem *item;
116
117         // Yes, it is this ugly. Two reasons - root items must have a QListView parent,
118         // rather than QListViewItem; and the TOC can move in and out an arbitrary number
119         // of levels
120
121         for (vector< Buffer::TocItem >::const_iterator iter = toclist.begin();
122                 iter != toclist.end(); ++iter) {
123                 if (iter->depth == curdepth) {
124                         // insert it after the last one we processed
125                         if (!parent)
126                                 item = (last) ? (new QListViewItem(dialog_->tocLV,last)) : (new QListViewItem(dialog_->tocLV));
127                         else
128                                 item = (last) ? (new QListViewItem(parent,last)) : (new QListViewItem(parent));
129                 } else if (iter->depth > curdepth) {
130                         int diff = iter->depth - curdepth;
131                         // first save old parent and last
132                         while (diff--)
133                                 istack.push(pair< QListViewItem *, QListViewItem * >(parent,last));
134                         item = (last) ? (new QListViewItem(last)) : (new QListViewItem(dialog_->tocLV));
135                         parent = last;
136                 } else {
137                         int diff = curdepth - iter->depth;
138                         pair< QListViewItem *, QListViewItem * > top;
139                         // restore context
140                         while (diff--) {
141                                 top = istack.top();
142                                 istack.pop();
143                         }
144                         parent = top.first;
145                         last = top.second;
146                         // insert it after the last one we processed
147                         if (!parent)
148                                 item = (last) ? (new QListViewItem(dialog_->tocLV,last)) : (new QListViewItem(dialog_->tocLV));
149                         else
150                                 item = (last) ? (new QListViewItem(parent,last)) : (new QListViewItem(parent));
151                 }
152                 lyxerr[Debug::GUI] << "Table of contents" << endl << "Added item " << iter->str.c_str()
153                         << " at depth " << iter->depth << ", previous sibling \"" << (last ? last->text(0).latin1() : "0")
154                         << "\", parent \"" << (parent ? parent->text(0).latin1() : "0") << "\"" << endl;
155                 item->setText(0,iter->str.c_str());
156                 item->setOpen(iter->depth < depth);
157                 curdepth = iter->depth;
158                 last = item;
159         }
160
161         dialog_->tocLV->setUpdatesEnabled(true);
162         dialog_->tocLV->update();
163 }
164
165 void FormToc::setType(Buffer::TocType toctype)
166 {
167         type = toctype;
168         switch (type) {
169                 case Buffer::TOC_TOC:
170                         dialog_->setCaption(_("Table of Contents"));
171                         dialog_->tocLV->setColumnText(0,_("Table of Contents"));
172                         dialog_->depthSL->setEnabled(true);
173                         break;
174                 case Buffer::TOC_LOF:
175                         dialog_->setCaption(_("List of Figures"));
176                         dialog_->tocLV->setColumnText(0,_("List of Figures"));
177                         dialog_->depthSL->setEnabled(false);
178                         break;
179                 case Buffer::TOC_LOT:
180                         dialog_->setCaption(_("List of Tables"));
181                         dialog_->tocLV->setColumnText(0,_("List of Tables"));
182                         dialog_->depthSL->setEnabled(false);
183                         break;
184                 case Buffer::TOC_LOA:
185                         dialog_->setCaption(_("List of Algorithms"));
186                         dialog_->tocLV->setColumnText(0,_("List of Algorithms"));
187                         dialog_->depthSL->setEnabled(false);
188                         break;
189         }
190 }
191
192 void FormToc::set_depth(int newdepth)
193 {
194         if (newdepth!=depth)
195                 updateToc(newdepth);
196 }
197
198 void FormToc::update()
199 {
200         if (params.getCmdName()=="tableofcontents") {
201                 setType(Buffer::TOC_TOC);
202                 dialog_->typeCO->setCurrentItem(0);
203         } else if (params.getCmdName()=="listoffigures") {
204                 setType(Buffer::TOC_LOF);
205                 dialog_->typeCO->setCurrentItem(1);
206         } else if (params.getCmdName()=="listoftables") {
207                 setType(Buffer::TOC_LOT);
208                 dialog_->typeCO->setCurrentItem(2);
209         } else {
210                 setType(Buffer::TOC_LOA);
211                 dialog_->typeCO->setCurrentItem(3);
212         }
213
214         updateToc(depth);
215 }
216
217 void FormToc::select(const char *text)
218 {
219         if (!lv_->view()->available())
220                 return;
221
222         vector <Buffer::TocItem>::const_iterator iter = toclist.begin();
223         for (; iter != toclist.end(); ++iter) {
224                 if (iter->str==text)
225                         break;
226         }
227         
228         if (iter==toclist.end()) {
229                 lyxerr[Debug::GUI] << "Couldn't find highlighted TOC entry : " << text << endl;
230                 return;
231         }
232
233         lv_->getLyXFunc()->Dispatch(LFUN_GOTO_PARAGRAPH, tostr(iter->par->id()).c_str());
234 }
235
236 void FormToc::set_type(Buffer::TocType toctype)
237 {
238         if (toctype==type)
239                 return;
240
241         setType(toctype);
242         updateToc(depth);
243 }
244
245 void FormToc::show()
246 {
247         if (!dialog_)
248                 dialog_ = new FormTocDialog(this, 0, _("LyX: Table of Contents"), false);
249
250         if (!dialog_->isVisible()) {
251                 h_ = d_->hideBufferDependent.connect(slot(this, &FormToc::hide));
252                 u_ = d_->updateBufferDependent.connect(slot(this, &FormToc::update));
253         }
254
255         dialog_->raise();
256         dialog_->setActiveWindow();
257
258         update();
259         dialog_->show();
260 }
261
262 void FormToc::close()
263 {
264         h_.disconnect();
265         u_.disconnect();
266         ih_.disconnect();
267         inset_ = 0;
268 }
269
270 void FormToc::hide()
271 {
272         dialog_->hide();
273         close();
274 }