]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QTocDialog.C
Add outlining functionality to the Qt4 TOC dialog.
[lyx.git] / src / frontends / qt4 / QTocDialog.C
1 /**
2  * \file QTocDialog.C
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 "QTocDialog.h"
15 #include "QToc.h"
16 #include "qt_helpers.h"
17 #include "controllers/ControlToc.h"
18
19 #include "debug.h"
20
21 #include <QTreeWidget>
22 #include <QTreeWidgetItem>
23 #include <QPushButton>
24 #include <QCloseEvent>
25
26 #include <vector>
27 #include <string>
28 #include <stack>
29
30 using std::endl;
31 using std::pair;
32 using std::stack;
33 using std::vector;
34 using std::string;
35
36 namespace lyx {
37 namespace frontend {
38
39 QTocDialog::QTocDialog(QToc * form)
40         : form_(form), depth_(2)
41 {
42         setupUi(this);
43
44         // disable sorting
45         tocTW->setSortingEnabled(false);
46         tocTW->setColumnCount(1);
47         // hide the pointless QHeader
48 //      QWidget * w = static_cast<QWidget*>(tocTW->child("list view header"));
49 //      if (w)
50 //              w->hide();
51
52         connect(closePB, SIGNAL(clicked()),
53                 form, SLOT(slotClose()));
54
55         connect( tocTW, SIGNAL(itemClicked(QTreeWidgetItem*)), this, SLOT(select_adaptor(QTreeWidgetItem*)));
56     connect( typeCO, SIGNAL( activated(int) ), this, SLOT( activate_adaptor(int) ) );
57     connect( updatePB, SIGNAL( clicked() ), this, SLOT( update_adaptor() ) );
58     connect( depthSL, SIGNAL( valueChanged(int) ), this, SLOT( depth_adaptor(int) ) );
59 }
60
61
62 QTocDialog::~QTocDialog()
63 {
64 }
65
66 void QTocDialog::on_moveUpPB_clicked()
67 {
68         enableButtons(false);
69         form_->moveUp();
70         enableButtons();
71 }
72
73 void QTocDialog::on_moveDownPB_clicked()
74 {
75         enableButtons(false);
76         form_->moveDown();
77         enableButtons();
78 }
79
80 void QTocDialog::on_moveInPB_clicked()
81 {
82         enableButtons(false);
83         form_->moveIn();
84         enableButtons();
85 }
86
87 void QTocDialog::on_moveOutPB_clicked()
88 {
89         enableButtons(false);
90         form_->moveOut();
91         enableButtons();
92 }
93
94 void QTocDialog::enableButtons(bool enable)
95 {
96         moveUpPB->setEnabled(enable);
97         moveDownPB->setEnabled(enable);
98         moveInPB->setEnabled(enable);
99         moveOutPB->setEnabled(enable);
100         updatePB->setEnabled(enable);
101 }
102
103 void QTocDialog::updateType()
104 {
105         typeCO->clear();
106
107         vector<string> const & choice = form_->controller().getTypes();
108         string const & type = toc::getType(form_->controller().params().getCmdName());
109
110         for (vector<string>::const_iterator it = choice.begin();
111                 it != choice.end(); ++it) {
112                 string const & guiname = form_->controller().getGuiName(*it);
113                 typeCO->insertItem(toqstr(guiname));
114                 if (*it == type) {
115                         typeCO->setCurrentItem(it - choice.begin());
116                         form_->setTitle(guiname);
117                 }
118         }
119 }
120
121 void QTocDialog::updateToc(bool newdepth)
122 {
123         vector<string> const & choice = form_->controller().getTypes();
124         string type;
125         if (!choice.empty())
126                 type = choice[typeCO->currentItem()];
127
128         toc::Toc const & contents = form_->controller().getContents(type);
129
130         // Check if all elements are the same.
131         if (!newdepth && form_->get_toclist() == contents) {
132                 return;
133         }
134
135         tocTW->clear();
136
137         form_->get_toclist() = contents;
138
139         if (form_->get_toclist().empty())
140                 return;
141
142         tocTW->setUpdatesEnabled(false);
143
144         QTreeWidgetItem * topLevelItem;
145
146         toc::Toc::const_iterator iter = form_->get_toclist().begin();
147
148         while (iter != form_->get_toclist().end()) {
149
150                 if (iter->depth == 1) {
151                         topLevelItem = new QTreeWidgetItem(tocTW);
152 //                      tocTW->addTopLevelItem(topLevelItem);
153                         topLevelItem->setText(0, toqstr(iter->str));
154                         if (iter->depth < depth_) tocTW->collapseItem(topLevelItem);
155
156                         lyxerr[Debug::GUI]
157                                 << "Table of contents\n"
158                                 << "Added Top Level item " << iter->str
159                                 << " at depth " << iter->depth
160                                 << endl;
161
162                         populateItem(topLevelItem, iter);
163                 }
164
165                 if (iter == form_->get_toclist().end())
166                         break;
167
168                 ++iter;
169         }
170
171         tocTW->setUpdatesEnabled(true);
172         tocTW->update();
173         form_->setTitle(fromqstr(typeCO->currentText()));
174         tocTW->show();
175 }
176
177 void QTocDialog::populateItem(QTreeWidgetItem * parentItem, toc::Toc::const_iterator& iter)
178 {
179         int curdepth = iter->depth+1;
180         QTreeWidgetItem * item;
181
182         while (iter != form_->get_toclist().end()) {
183                 
184                 ++iter;
185
186                 if (iter == form_->get_toclist().end())
187                         break;
188
189                 if (iter->depth < curdepth) {
190                         --iter;
191                         return;
192                 }
193                 if (iter->depth > curdepth) {
194 //                      --iter;
195                         return;
196                 }
197
198                 item = new QTreeWidgetItem(parentItem);
199                 item->setText(0, toqstr(iter->str));
200 //              parentItem->addChild(item);
201
202                 if (iter->depth < depth_) tocTW->collapseItem(item);
203 //              else tocTW->expandItem(item);
204                 lyxerr[Debug::GUI]
205                         << "Table of contents: Added item " << iter->str
206                         << " at depth " << iter->depth
207                         << "  \", parent \""
208                         << fromqstr(parentItem->text(0)) << '"'
209                         << endl;
210
211                 populateItem(item, iter);
212         }
213 }
214
215 void QTocDialog::activate_adaptor(int)
216 {
217         updateToc();
218 }
219
220
221 void QTocDialog::depth_adaptor(int depth)
222 {
223         if (depth == depth_)
224                 return;
225
226         depth_ = depth;
227         updateToc(true);
228 }
229
230
231 void QTocDialog::select_adaptor(QTreeWidgetItem * item)
232 {
233         form_->select(fromqstr(item->text(0)));
234 }
235
236
237 void QTocDialog::update_adaptor()
238 {
239         form_->update();
240 }
241
242
243 void QTocDialog::closeEvent(QCloseEvent * e)
244 {
245         form_->slotWMHide();
246         e->accept();
247 }
248
249 } // namespace frontend
250 } // namespace lyx
251
252
253 /*
254         stack<pair<QTreeWidgetItem *, QTreeWidgetItem *> > istack;
255         QTreeWidgetItem * last = 0;
256         QTreeWidgetItem * parent = 0;
257         QTreeWidgetItem * item;
258
259         // Yes, it is this ugly. Two reasons - root items must have
260         // a QListView parent, rather than QListViewItem; and the
261         // TOC can move in and out an arbitrary number of levels
262
263         for (toc::Toc::const_iterator iter = form_->get_toclist().begin();
264              iter != form_->get_toclist().end(); ++iter) {
265
266                 if (iter->depth == 0) {
267                         TocTW
268
269                 if (iter->depth == curdepth) {
270                         // insert it after the last one we processed
271                         if (!parent)
272                                 item = (last ? new QTreeWidgetItem(tocTW,last) : new QTreeWidgetItem(tocTW));
273                         else
274                                 item = (last ? new QTreeWidgetItem(parent,last) : new QTreeWidgetItem(parent));
275                 } else if (iter->depth > curdepth) {
276                         int diff = iter->depth - curdepth;
277                         // first save old parent and last
278                         while (diff--)
279                                 istack.push(pair< QTreeWidgetItem *, QTreeWidgetItem * >(parent,last));
280                         item = (last ? new QTreeWidgetItem(last) : new QTreeWidgetItem(tocTW));
281                         parent = last;
282                 } else {
283                         int diff = curdepth - iter->depth;
284                         pair<QTreeWidgetItem *, QTreeWidgetItem * > top;
285                         // restore context
286                         while (diff--) {
287                                 top = istack.top();
288                                 istack.pop();
289                         }
290                         parent = top.first;
291                         last = top.second;
292                         // insert it after the last one we processed
293                         if (!parent)
294                                 item = (last ? new QTreeWidgetItem(tocTW,last) : new QTreeWidgetItem(tocTW));
295                         else
296                                 item = (last ? new QTreeWidgetItem(parent,last) : new QTreeWidgetItem(parent));
297                 }
298                 item->setText(0, toqstr(iter->str));
299                 item->setOpen(iter->depth < depth_);
300                 curdepth = iter->depth;
301                 last = item;
302         }
303 */