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