]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - scripts/kconfig/qconf.cc
Port xconfig to Qt5 - on Back clicked, deselect old item.
[mirror_ubuntu-bionic-kernel.git] / scripts / kconfig / qconf.cc
CommitLineData
1da177e4
LT
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
133c5f7c
AS
6#include <qglobal.h>
7
b1f8a45b 8#include <QMainWindow>
041fbdc2 9#include <QList>
924bbb53 10#include <qtextbrowser.h>
85eaf28a 11#include <QAction>
bea00771 12#include <QFileDialog>
76bede87 13#include <QMenu>
133c5f7c
AS
14
15#include <qapplication.h>
8d90c97e 16#include <qdesktopwidget.h>
1da177e4 17#include <qtoolbar.h>
43bf612a 18#include <qlayout.h>
1da177e4 19#include <qsplitter.h>
1da177e4 20#include <qlineedit.h>
43bf612a
RZ
21#include <qlabel.h>
22#include <qpushbutton.h>
1da177e4
LT
23#include <qmenubar.h>
24#include <qmessagebox.h>
1da177e4 25#include <qregexp.h>
133c5f7c 26#include <qevent.h>
1da177e4
LT
27
28#include <stdlib.h>
29
30#include "lkc.h"
31#include "qconf.h"
32
33#include "qconf.moc"
34#include "images.c"
35
3b9fa093
ACM
36#ifdef _
37# undef _
38# define _ qgettext
39#endif
40
1da177e4 41static QApplication *configApp;
7fc925fd 42static ConfigSettings *configSettings;
1da177e4 43
85eaf28a 44QAction *ConfigMainWindow::saveAction;
3b354c55 45
3b9fa093
ACM
46static inline QString qgettext(const char* str)
47{
43bf612a 48 return QString::fromLocal8Bit(gettext(str));
3b9fa093
ACM
49}
50
51static inline QString qgettext(const QString& str)
52{
68ccb7ef 53 return QString::fromLocal8Bit(gettext(str.toLatin1()));
3b9fa093
ACM
54}
55
00d4f8fc
BH
56ConfigSettings::ConfigSettings()
57 : QSettings("kernel.org", "qconf")
58{
59}
60
1da177e4
LT
61/**
62 * Reads a list of integer values from the application settings.
63 */
041fbdc2 64QList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
1da177e4 65{
041fbdc2 66 QList<int> result;
68ccb7ef 67 QStringList entryList = value(key).toStringList();
c1f96f09
LZ
68 QStringList::Iterator it;
69
70 for (it = entryList.begin(); it != entryList.end(); ++it)
71 result.push_back((*it).toInt());
1da177e4
LT
72
73 return result;
74}
75
76/**
77 * Writes a list of integer values to the application settings.
78 */
041fbdc2 79bool ConfigSettings::writeSizes(const QString& key, const QList<int>& value)
1da177e4
LT
80{
81 QStringList stringList;
041fbdc2 82 QList<int>::ConstIterator it;
1da177e4
LT
83
84 for (it = value.begin(); it != value.end(); ++it)
85 stringList.push_back(QString::number(*it));
68ccb7ef 86 setValue(key, stringList);
59e56440 87
68ccb7ef 88 return true;
1da177e4 89}
1da177e4 90
59e56440
BB
91
92/*
93 * set the new data
94 * TODO check the value
95 */
96void ConfigItem::okRename(int col)
97{
98}
99
100/*
101 * update the displayed of a menu entry
102 */
103void ConfigItem::updateMenu(void)
104{
d5d973c3
BB
105 ConfigList* list;
106 struct symbol* sym;
107 struct property *prop;
108 QString prompt;
109 int type;
110 tristate expr;
111
112 list = listView();
113 if (goParent) {
114 setPixmap(promptColIdx, list->menuBackPix);
115 prompt = "..";
116 goto set_prompt;
117 }
118
119 sym = menu->sym;
120 prop = menu->prompt;
121 prompt = _(menu_get_prompt(menu));
122
123 if (prop) switch (prop->type) {
124 case P_MENU:
125 if (list->mode == singleMode || list->mode == symbolMode) {
126 /* a menuconfig entry is displayed differently
127 * depending whether it's at the view root or a child.
128 */
129 if (sym && list->rootEntry == menu)
130 break;
131 setPixmap(promptColIdx, list->menuPix);
132 } else {
133 if (sym)
134 break;
135 setPixmap(promptColIdx, QIcon());
136 }
137 goto set_prompt;
138 case P_COMMENT:
139 setPixmap(promptColIdx, QIcon());
140 goto set_prompt;
141 default:
142 ;
143 }
144 if (!sym)
145 goto set_prompt;
146
147 setText(nameColIdx, QString::fromLocal8Bit(sym->name));
148
149 type = sym_get_type(sym);
150 switch (type) {
151 case S_BOOLEAN:
152 case S_TRISTATE:
153 char ch;
154
155 if (!sym_is_changable(sym) && list->optMode == normalOpt) {
156 setPixmap(promptColIdx, QIcon());
157 setText(noColIdx, QString::null);
158 setText(modColIdx, QString::null);
159 setText(yesColIdx, QString::null);
160 break;
161 }
162 expr = sym_get_tristate_value(sym);
163 switch (expr) {
164 case yes:
165 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
166 setPixmap(promptColIdx, list->choiceYesPix);
167 else
168 setPixmap(promptColIdx, list->symbolYesPix);
169 setText(yesColIdx, "Y");
170 ch = 'Y';
171 break;
172 case mod:
173 setPixmap(promptColIdx, list->symbolModPix);
174 setText(modColIdx, "M");
175 ch = 'M';
176 break;
177 default:
178 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
179 setPixmap(promptColIdx, list->choiceNoPix);
180 else
181 setPixmap(promptColIdx, list->symbolNoPix);
182 setText(noColIdx, "N");
183 ch = 'N';
184 break;
185 }
186 if (expr != no)
187 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
188 if (expr != mod)
189 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
190 if (expr != yes)
191 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
192
193 setText(dataColIdx, QChar(ch));
194 break;
195 case S_INT:
196 case S_HEX:
197 case S_STRING:
198 const char* data;
199
200 data = sym_get_string_value(sym);
201
d5d973c3
BB
202 setText(dataColIdx, data);
203 if (type == S_STRING)
204 prompt = QString("%1: %2").arg(prompt).arg(data);
205 else
206 prompt = QString("(%2) %1").arg(prompt).arg(data);
207 break;
208 }
209 if (!sym_has_value(sym) && visible)
210 prompt += _(" (NEW)");
211set_prompt:
212 setText(promptColIdx, prompt);
59e56440
BB
213}
214
215void ConfigItem::testUpdateMenu(bool v)
216{
d5d973c3
BB
217 ConfigItem* i;
218
219 visible = v;
220 if (!menu)
221 return;
222
223 sym_calc_value(menu->sym);
224 if (menu->flags & MENU_CHANGED) {
225 /* the menu entry changed, so update all list items */
226 menu->flags &= ~MENU_CHANGED;
227 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
228 i->updateMenu();
229 } else if (listView()->updateAll)
230 updateMenu();
59e56440
BB
231}
232
233
1019f1a5
BB
234/*
235 * construct a menu entry
236 */
237void ConfigItem::init(void)
238{
d5d973c3
BB
239 if (menu) {
240 ConfigList* list = listView();
241 nextItem = (ConfigItem*)menu->data;
242 menu->data = this;
243
244 if (list->mode != fullMode)
245 setExpanded(true);
246 sym_calc_value(menu->sym);
247 }
248 updateMenu();
1019f1a5
BB
249}
250
251/*
252 * destruct a menu entry
253 */
254ConfigItem::~ConfigItem(void)
255{
d5d973c3
BB
256 if (menu) {
257 ConfigItem** ip = (ConfigItem**)&menu->data;
258 for (; *ip; ip = &(*ip)->nextItem) {
259 if (*ip == this) {
260 *ip = nextItem;
261 break;
262 }
263 }
264 }
1019f1a5
BB
265}
266
43bf612a
RZ
267ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
268 : Parent(parent)
269{
c14fa5e1 270 connect(this, SIGNAL(editingFinished()), SLOT(hide()));
43bf612a
RZ
271}
272
1019f1a5 273void ConfigLineEdit::show(ConfigItem* i)
1da177e4
LT
274{
275 item = i;
d5d973c3
BB
276 if (sym_get_string_value(item->menu->sym))
277 setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
278 else
279 setText(QString::null);
1da177e4
LT
280 Parent::show();
281 setFocus();
282}
283
284void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
285{
286 switch (e->key()) {
fbb86374 287 case Qt::Key_Escape:
1da177e4 288 break;
fbb86374
MH
289 case Qt::Key_Return:
290 case Qt::Key_Enter:
d5d973c3 291 sym_set_string_value(item->menu->sym, text().toLatin1());
1da177e4
LT
292 parent()->updateList(item);
293 break;
294 default:
295 Parent::keyPressEvent(e);
296 return;
297 }
298 e->accept();
299 parent()->list->setFocus();
300 hide();
301}
302
1019f1a5 303ConfigList::ConfigList(ConfigView* p, const char *name)
59e56440
BB
304 : Parent(p),
305 updateAll(false),
306 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
307 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
308 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
dbf62933 309 showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt),
59e56440
BB
310 rootEntry(0), headerPopup(0)
311{
d5d973c3
BB
312 int i;
313
314 setObjectName(name);
a5225e9b 315 setSortingEnabled(false);
d5d973c3
BB
316 setRootIsDecorated(true);
317
f999cc06
BB
318 setVerticalScrollMode(ScrollPerPixel);
319 setHorizontalScrollMode(ScrollPerPixel);
320
a52cb321
BB
321 setHeaderLabels(QStringList() << _("Option") << _("Name") << "N" << "M" << "Y" << _("Value"));
322
c14fa5e1 323 connect(this, SIGNAL(itemSelectionChanged(void)),
d5d973c3
BB
324 SLOT(updateSelection(void)));
325
326 if (name) {
327 configSettings->beginGroup(name);
328 showName = configSettings->value("/showName", false).toBool();
329 showRange = configSettings->value("/showRange", false).toBool();
330 showData = configSettings->value("/showData", false).toBool();
331 optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt();
332 configSettings->endGroup();
333 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
334 }
335
336 addColumn(promptColIdx);
337
338 reinit();
339}
340
341bool ConfigList::menuSkip(struct menu *menu)
342{
343 if (optMode == normalOpt && menu_is_visible(menu))
344 return false;
345 if (optMode == promptOpt && menu_has_prompt(menu))
346 return false;
347 if (optMode == allOpt)
348 return false;
349 return true;
59e56440
BB
350}
351
352void ConfigList::reinit(void)
353{
d5d973c3
BB
354 removeColumn(dataColIdx);
355 removeColumn(yesColIdx);
356 removeColumn(modColIdx);
357 removeColumn(noColIdx);
358 removeColumn(nameColIdx);
359
360 if (showName)
361 addColumn(nameColIdx);
362 if (showRange) {
363 addColumn(noColIdx);
364 addColumn(modColIdx);
365 addColumn(yesColIdx);
366 }
367 if (showData)
368 addColumn(dataColIdx);
369
370 updateListAll();
59e56440
BB
371}
372
373void ConfigList::saveSettings(void)
374{
d5d973c3
BB
375 if (!objectName().isEmpty()) {
376 configSettings->beginGroup(objectName());
377 configSettings->setValue("/showName", showName);
378 configSettings->setValue("/showRange", showRange);
379 configSettings->setValue("/showData", showData);
380 configSettings->setValue("/optionMode", (int)optMode);
381 configSettings->endGroup();
382 }
59e56440
BB
383}
384
385ConfigItem* ConfigList::findConfigItem(struct menu *menu)
386{
d5d973c3
BB
387 ConfigItem* item = (ConfigItem*)menu->data;
388
389 for (; item; item = item->nextItem) {
390 if (this == item->listView())
391 break;
392 }
393
394 return item;
59e56440
BB
395}
396
397void ConfigList::updateSelection(void)
398{
d5d973c3
BB
399 struct menu *menu;
400 enum prop_type type;
401
402 ConfigItem* item = (ConfigItem*)selectedItems().first();
403 if (!item)
404 return;
405
406 menu = item->menu;
407 emit menuChanged(menu);
408 if (!menu)
409 return;
410 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
411 if (mode == menuMode && type == P_MENU)
412 emit menuSelected(menu);
59e56440
BB
413}
414
415void ConfigList::updateList(ConfigItem* item)
416{
d5d973c3
BB
417 ConfigItem* last = 0;
418
419 if (!rootEntry) {
420 if (mode != listMode)
421 goto update;
422 QTreeWidgetItemIterator it(this);
423 ConfigItem* item;
424
425 while (*it) {
426 item = (ConfigItem*)(*it);
427 if (!item->menu)
428 continue;
429 item->testUpdateMenu(menu_is_visible(item->menu));
430
431 ++it;
432 }
433 return;
434 }
435
436 if (rootEntry != &rootmenu && (mode == singleMode ||
437 (mode == symbolMode && rootEntry->parent != &rootmenu))) {
438 item = firstChild();
439 if (!item)
440 item = new ConfigItem(this, 0, true);
441 last = item;
442 }
443 if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
444 rootEntry->sym && rootEntry->prompt) {
445 item = last ? last->nextSibling() : firstChild();
446 if (!item)
447 item = new ConfigItem(this, last, rootEntry, true);
448 else
449 item->testUpdateMenu(true);
450
451 updateMenuList(item, rootEntry);
452 update();
f999cc06 453 resizeColumnToContents(0);
d5d973c3
BB
454 return;
455 }
456update:
457 updateMenuList(this, rootEntry);
458 update();
f999cc06 459 resizeColumnToContents(0);
59e56440
BB
460}
461
462void ConfigList::setValue(ConfigItem* item, tristate val)
463{
d5d973c3
BB
464 struct symbol* sym;
465 int type;
466 tristate oldval;
467
468 sym = item->menu ? item->menu->sym : 0;
469 if (!sym)
470 return;
471
472 type = sym_get_type(sym);
473 switch (type) {
474 case S_BOOLEAN:
475 case S_TRISTATE:
476 oldval = sym_get_tristate_value(sym);
477
478 if (!sym_set_tristate_value(sym, val))
479 return;
480 if (oldval == no && item->menu->list)
481 item->setExpanded(true);
482 parent()->updateList(item);
483 break;
484 }
59e56440
BB
485}
486
487void ConfigList::changeValue(ConfigItem* item)
488{
d5d973c3
BB
489 struct symbol* sym;
490 struct menu* menu;
491 int type, oldexpr, newexpr;
492
493 menu = item->menu;
494 if (!menu)
495 return;
496 sym = menu->sym;
497 if (!sym) {
498 if (item->menu->list)
499 item->setExpanded(!item->isExpanded());
500 return;
501 }
502
503 type = sym_get_type(sym);
504 switch (type) {
505 case S_BOOLEAN:
506 case S_TRISTATE:
507 oldexpr = sym_get_tristate_value(sym);
508 newexpr = sym_toggle_tristate_value(sym);
509 if (item->menu->list) {
510 if (oldexpr == newexpr)
511 item->setExpanded(!item->isExpanded());
512 else if (oldexpr == no)
513 item->setExpanded(true);
514 }
515 if (oldexpr != newexpr)
516 parent()->updateList(item);
517 break;
518 case S_INT:
519 case S_HEX:
520 case S_STRING:
e336b9f1 521 parent()->lineEdit->show(item);
d5d973c3
BB
522 break;
523 }
59e56440
BB
524}
525
526void ConfigList::setRootMenu(struct menu *menu)
527{
d5d973c3
BB
528 enum prop_type type;
529
530 if (rootEntry == menu)
531 return;
532 type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
533 if (type != P_MENU)
534 return;
535 updateMenuList(this, 0);
536 rootEntry = menu;
537 updateListAll();
538 if (currentItem()) {
539 currentItem()->setSelected(hasFocus());
540 scrollToItem(currentItem());
541 }
59e56440
BB
542}
543
544void ConfigList::setParentMenu(void)
545{
d5d973c3
BB
546 ConfigItem* item;
547 struct menu *oldroot;
548
549 oldroot = rootEntry;
550 if (rootEntry == &rootmenu)
551 return;
552 setRootMenu(menu_get_parent_menu(rootEntry->parent));
553
554 QTreeWidgetItemIterator it(this);
555 while (*it) {
556 item = (ConfigItem *)(*it);
557 if (item->menu == oldroot) {
558 setCurrentItem(item);
559 scrollToItem(item);
560 break;
561 }
562
563 ++it;
564 }
59e56440
BB
565}
566
567/*
568 * update all the children of a menu entry
569 * removes/adds the entries from the parent widget as necessary
570 *
571 * parent: either the menu list widget or a menu entry widget
572 * menu: entry to be updated
573 */
5c6f1554 574void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
59e56440 575{
d5d973c3
BB
576 struct menu* child;
577 ConfigItem* item;
578 ConfigItem* last;
579 bool visible;
580 enum prop_type type;
581
582 if (!menu) {
5c6f1554
BB
583 while (parent->childCount() > 0)
584 {
585 delete parent->takeChild(0);
586 }
587
d5d973c3
BB
588 return;
589 }
590
591 last = parent->firstChild();
592 if (last && !last->goParent)
593 last = 0;
594 for (child = menu->list; child; child = child->next) {
595 item = last ? last->nextSibling() : parent->firstChild();
596 type = child->prompt ? child->prompt->type : P_UNKNOWN;
597
598 switch (mode) {
599 case menuMode:
600 if (!(child->flags & MENU_ROOT))
601 goto hide;
602 break;
603 case symbolMode:
604 if (child->flags & MENU_ROOT)
605 goto hide;
606 break;
607 default:
608 break;
609 }
610
611 visible = menu_is_visible(child);
612 if (!menuSkip(child)) {
613 if (!child->sym && !child->list && !child->prompt)
614 continue;
615 if (!item || item->menu != child)
616 item = new ConfigItem(parent, last, child, visible);
617 else
618 item->testUpdateMenu(visible);
619
620 if (mode == fullMode || mode == menuMode || type != P_MENU)
621 updateMenuList(item, child);
622 else
623 updateMenuList(item, 0);
624 last = item;
625 continue;
626 }
627 hide:
628 if (item && item->menu == child) {
629 last = parent->firstChild();
630 if (last == item)
631 last = 0;
632 else while (last->nextSibling() != item)
633 last = last->nextSibling();
634 delete item;
635 }
636 }
59e56440
BB
637}
638
5c6f1554
BB
639void ConfigList::updateMenuList(ConfigList *parent, struct menu* menu)
640{
641 struct menu* child;
642 ConfigItem* item;
643 ConfigItem* last;
644 bool visible;
645 enum prop_type type;
646
647 if (!menu) {
648 while (parent->topLevelItemCount() > 0)
649 {
650 delete parent->takeTopLevelItem(0);
651 }
652
653 return;
654 }
655
656 last = (ConfigItem*)parent->topLevelItem(0);
657 if (last && !last->goParent)
658 last = 0;
659 for (child = menu->list; child; child = child->next) {
660 item = last ? last->nextSibling() : (ConfigItem*)parent->topLevelItem(0);
661 type = child->prompt ? child->prompt->type : P_UNKNOWN;
662
663 switch (mode) {
664 case menuMode:
665 if (!(child->flags & MENU_ROOT))
666 goto hide;
667 break;
668 case symbolMode:
669 if (child->flags & MENU_ROOT)
670 goto hide;
671 break;
672 default:
673 break;
674 }
675
676 visible = menu_is_visible(child);
677 if (!menuSkip(child)) {
678 if (!child->sym && !child->list && !child->prompt)
679 continue;
680 if (!item || item->menu != child)
681 item = new ConfigItem(parent, last, child, visible);
682 else
683 item->testUpdateMenu(visible);
684
685 if (mode == fullMode || mode == menuMode || type != P_MENU)
686 updateMenuList(item, child);
687 else
688 updateMenuList(item, 0);
689 last = item;
690 continue;
691 }
692 hide:
693 if (item && item->menu == child) {
694 last = (ConfigItem*)parent->topLevelItem(0);
695 if (last == item)
696 last = 0;
697 else while (last->nextSibling() != item)
698 last = last->nextSibling();
699 delete item;
700 }
701 }
702}
703
59e56440
BB
704void ConfigList::keyPressEvent(QKeyEvent* ev)
705{
d5d973c3
BB
706 QTreeWidgetItem* i = currentItem();
707 ConfigItem* item;
708 struct menu *menu;
709 enum prop_type type;
710
711 if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
712 emit parentSelected();
713 ev->accept();
714 return;
715 }
716
717 if (!i) {
718 Parent::keyPressEvent(ev);
719 return;
720 }
721 item = (ConfigItem*)i;
722
723 switch (ev->key()) {
724 case Qt::Key_Return:
725 case Qt::Key_Enter:
726 if (item->goParent) {
727 emit parentSelected();
728 break;
729 }
730 menu = item->menu;
731 if (!menu)
732 break;
733 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
734 if (type == P_MENU && rootEntry != menu &&
735 mode != fullMode && mode != menuMode) {
736 emit menuSelected(menu);
737 break;
738 }
739 case Qt::Key_Space:
740 changeValue(item);
741 break;
742 case Qt::Key_N:
743 setValue(item, no);
744 break;
745 case Qt::Key_M:
746 setValue(item, mod);
747 break;
748 case Qt::Key_Y:
749 setValue(item, yes);
750 break;
751 default:
752 Parent::keyPressEvent(ev);
753 return;
754 }
755 ev->accept();
59e56440
BB
756}
757
d5d973c3 758void ConfigList::mousePressEvent(QMouseEvent* e)
1019f1a5 759{
d5d973c3
BB
760 //QPoint p(contentsToViewport(e->pos()));
761 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
762 Parent::mousePressEvent(e);
1019f1a5 763}
59e56440 764
d5d973c3 765void ConfigList::mouseReleaseEvent(QMouseEvent* e)
59e56440 766{
d5d973c3
BB
767 QPoint p = e->pos();
768 ConfigItem* item = (ConfigItem*)itemAt(p);
769 struct menu *menu;
770 enum prop_type ptype;
771 QIcon icon;
772 int idx, x;
773
774 if (!item)
775 goto skip;
776
777 menu = item->menu;
778 x = header()->offset() + p.x();
76d53cbb 779 idx = header()->logicalIndexAt(x);
d5d973c3
BB
780 switch (idx) {
781 case promptColIdx:
782 icon = item->pixmap(promptColIdx);
76d53cbb
BB
783 if (!icon.isNull()) {
784 int off = header()->sectionPosition(0) + visualRect(indexAt(p)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly.
785 if (x >= off && x < off + icon.availableSizes().first().width()) {
786 if (item->goParent) {
787 emit parentSelected();
788 break;
789 } else if (!menu)
790 break;
791 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
792 if (ptype == P_MENU && rootEntry != menu &&
793 mode != fullMode && mode != menuMode)
794 emit menuSelected(menu);
795 else
796 changeValue(item);
797 }
798 }
d5d973c3
BB
799 break;
800 case noColIdx:
801 setValue(item, no);
802 break;
803 case modColIdx:
804 setValue(item, mod);
805 break;
806 case yesColIdx:
807 setValue(item, yes);
808 break;
809 case dataColIdx:
810 changeValue(item);
811 break;
812 }
813
814skip:
815 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
816 Parent::mouseReleaseEvent(e);
59e56440
BB
817}
818
d5d973c3 819void ConfigList::mouseMoveEvent(QMouseEvent* e)
59e56440 820{
d5d973c3
BB
821 //QPoint p(contentsToViewport(e->pos()));
822 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
823 Parent::mouseMoveEvent(e);
59e56440
BB
824}
825
d5d973c3 826void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
59e56440 827{
d5d973c3
BB
828 QPoint p = e->pos(); // TODO: Check if this works(was contentsToViewport).
829 ConfigItem* item = (ConfigItem*)itemAt(p);
830 struct menu *menu;
831 enum prop_type ptype;
832
833 if (!item)
834 goto skip;
835 if (item->goParent) {
836 emit parentSelected();
837 goto skip;
838 }
839 menu = item->menu;
840 if (!menu)
841 goto skip;
842 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
843 if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
844 emit menuSelected(menu);
845 else if (menu->sym)
846 changeValue(item);
847
848skip:
849 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
850 Parent::mouseDoubleClickEvent(e);
59e56440
BB
851}
852
853void ConfigList::focusInEvent(QFocusEvent *e)
854{
d5d973c3
BB
855 struct menu *menu = NULL;
856
857 Parent::focusInEvent(e);
858
859 ConfigItem* item = (ConfigItem *)currentItem();
860 if (item) {
861 item->setSelected(true);
862 menu = item->menu;
863 }
864 emit gotFocus(menu);
59e56440
BB
865}
866
867void ConfigList::contextMenuEvent(QContextMenuEvent *e)
868{
d5d973c3
BB
869 if (e->y() <= header()->geometry().bottom()) {
870 if (!headerPopup) {
871 QAction *action;
872
873 headerPopup = new QMenu(this);
874 action = new QAction(_("Show Name"), this);
875 action->setCheckable(true);
876 connect(action, SIGNAL(toggled(bool)),
877 parent(), SLOT(setShowName(bool)));
878 connect(parent(), SIGNAL(showNameChanged(bool)),
879 action, SLOT(setOn(bool)));
880 action->setChecked(showName);
881 headerPopup->addAction(action);
882 action = new QAction(_("Show Range"), this);
883 action->setCheckable(true);
884 connect(action, SIGNAL(toggled(bool)),
885 parent(), SLOT(setShowRange(bool)));
886 connect(parent(), SIGNAL(showRangeChanged(bool)),
887 action, SLOT(setOn(bool)));
888 action->setChecked(showRange);
889 headerPopup->addAction(action);
890 action = new QAction(_("Show Data"), this);
891 action->setCheckable(true);
892 connect(action, SIGNAL(toggled(bool)),
893 parent(), SLOT(setShowData(bool)));
894 connect(parent(), SIGNAL(showDataChanged(bool)),
895 action, SLOT(setOn(bool)));
896 action->setChecked(showData);
897 headerPopup->addAction(action);
898 }
899 headerPopup->exec(e->globalPos());
900 e->accept();
901 } else
902 e->ignore();
59e56440
BB
903}
904
39a4897c
LZ
905ConfigView*ConfigView::viewList;
906QAction *ConfigView::showNormalAction;
907QAction *ConfigView::showAllAction;
908QAction *ConfigView::showPromptAction;
1da177e4 909
7fc925fd 910ConfigView::ConfigView(QWidget* parent, const char *name)
68ccb7ef 911 : Parent(parent)
1da177e4 912{
9bd36ed3 913 setObjectName(name);
29a70168 914 QVBoxLayout *verticalLayout = new QVBoxLayout(this);
92298b49 915 verticalLayout->setContentsMargins(0, 0, 0, 0);
29a70168 916
1019f1a5 917 list = new ConfigList(this);
29a70168 918 verticalLayout->addWidget(list);
1da177e4
LT
919 lineEdit = new ConfigLineEdit(this);
920 lineEdit->hide();
29a70168 921 verticalLayout->addWidget(lineEdit);
1da177e4
LT
922
923 this->nextView = viewList;
924 viewList = this;
925}
926
927ConfigView::~ConfigView(void)
928{
929 ConfigView** vp;
930
931 for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
932 if (*vp == this) {
933 *vp = nextView;
934 break;
935 }
936 }
937}
938
39a4897c 939void ConfigView::setOptionMode(QAction *act)
7fc925fd 940{
d5d973c3
BB
941 if (act == showNormalAction)
942 list->optMode = normalOpt;
943 else if (act == showAllAction)
944 list->optMode = allOpt;
945 else
946 list->optMode = promptOpt;
947
948 list->updateListAll();
7fc925fd
RZ
949}
950
951void ConfigView::setShowName(bool b)
952{
d5d973c3
BB
953 if (list->showName != b) {
954 list->showName = b;
955 list->reinit();
956 emit showNameChanged(b);
957 }
7fc925fd
RZ
958}
959
960void ConfigView::setShowRange(bool b)
961{
d5d973c3
BB
962 if (list->showRange != b) {
963 list->showRange = b;
964 list->reinit();
965 emit showRangeChanged(b);
966 }
7fc925fd
RZ
967}
968
969void ConfigView::setShowData(bool b)
970{
d5d973c3
BB
971 if (list->showData != b) {
972 list->showData = b;
973 list->reinit();
974 emit showDataChanged(b);
975 }
976}
977
978void ConfigList::setAllOpen(bool open)
979{
980 QTreeWidgetItemIterator it(this);
981
982 while (*it) {
983 (*it)->setExpanded(open);
984
985 ++it;
986 }
7fc925fd
RZ
987}
988
1019f1a5 989void ConfigView::updateList(ConfigItem* item)
1da177e4 990{
d5d973c3
BB
991 ConfigView* v;
992
993 for (v = viewList; v; v = v->nextView)
994 v->list->updateList(item);
1da177e4
LT
995}
996
997void ConfigView::updateListAll(void)
998{
d5d973c3
BB
999 ConfigView* v;
1000
1001 for (v = viewList; v; v = v->nextView)
1002 v->list->updateListAll();
1da177e4
LT
1003}
1004
43bf612a 1005ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
68ccb7ef 1006 : Parent(parent), sym(0), _menu(0)
43bf612a 1007{
d5d973c3
BB
1008 setObjectName(name);
1009
1010
1011 if (!objectName().isEmpty()) {
1012 configSettings->beginGroup(objectName());
68ccb7ef 1013 _showDebug = configSettings->value("/showDebug", false).toBool();
7fc925fd
RZ
1014 configSettings->endGroup();
1015 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1016 }
1017}
1018
1019void ConfigInfoView::saveSettings(void)
1020{
d5d973c3
BB
1021 if (!objectName().isEmpty()) {
1022 configSettings->beginGroup(objectName());
1023 configSettings->setValue("/showDebug", showDebug());
1024 configSettings->endGroup();
1025 }
43bf612a
RZ
1026}
1027
1028void ConfigInfoView::setShowDebug(bool b)
1029{
1030 if (_showDebug != b) {
1031 _showDebug = b;
133c5f7c 1032 if (_menu)
43bf612a 1033 menuInfo();
ab45d190
RZ
1034 else if (sym)
1035 symbolInfo();
43bf612a
RZ
1036 emit showDebugChanged(b);
1037 }
1038}
1039
1040void ConfigInfoView::setInfo(struct menu *m)
1041{
133c5f7c 1042 if (_menu == m)
b65a47e1 1043 return;
133c5f7c 1044 _menu = m;
6fa1da8e 1045 sym = NULL;
133c5f7c 1046 if (!_menu)
43bf612a 1047 clear();
6fa1da8e 1048 else
43bf612a
RZ
1049 menuInfo();
1050}
1051
ab45d190
RZ
1052void ConfigInfoView::symbolInfo(void)
1053{
1054 QString str;
1055
1056 str += "<big>Symbol: <b>";
1057 str += print_filter(sym->name);
1058 str += "</b></big><br><br>value: ";
1059 str += print_filter(sym_get_string_value(sym));
1060 str += "<br>visibility: ";
1061 str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
1062 str += "<br>";
1063 str += debug_info(sym);
1064
1065 setText(str);
1066}
1067
43bf612a
RZ
1068void ConfigInfoView::menuInfo(void)
1069{
1070 struct symbol* sym;
1071 QString head, debug, help;
1072
133c5f7c 1073 sym = _menu->sym;
43bf612a 1074 if (sym) {
133c5f7c 1075 if (_menu->prompt) {
43bf612a 1076 head += "<big><b>";
133c5f7c 1077 head += print_filter(_(_menu->prompt->text));
43bf612a
RZ
1078 head += "</b></big>";
1079 if (sym->name) {
1080 head += " (";
ab45d190
RZ
1081 if (showDebug())
1082 head += QString().sprintf("<a href=\"s%p\">", sym);
43bf612a 1083 head += print_filter(sym->name);
ab45d190
RZ
1084 if (showDebug())
1085 head += "</a>";
43bf612a
RZ
1086 head += ")";
1087 }
1088 } else if (sym->name) {
1089 head += "<big><b>";
ab45d190
RZ
1090 if (showDebug())
1091 head += QString().sprintf("<a href=\"s%p\">", sym);
43bf612a 1092 head += print_filter(sym->name);
ab45d190
RZ
1093 if (showDebug())
1094 head += "</a>";
43bf612a
RZ
1095 head += "</b></big>";
1096 }
1097 head += "<br><br>";
1098
1099 if (showDebug())
1100 debug = debug_info(sym);
1101
d74c15f3 1102 struct gstr help_gstr = str_new();
133c5f7c 1103 menu_get_ext_help(_menu, &help_gstr);
d74c15f3
CR
1104 help = print_filter(str_get(&help_gstr));
1105 str_free(&help_gstr);
133c5f7c 1106 } else if (_menu->prompt) {
43bf612a 1107 head += "<big><b>";
133c5f7c 1108 head += print_filter(_(_menu->prompt->text));
43bf612a
RZ
1109 head += "</b></big><br><br>";
1110 if (showDebug()) {
133c5f7c 1111 if (_menu->prompt->visible.expr) {
43bf612a 1112 debug += "&nbsp;&nbsp;dep: ";
133c5f7c 1113 expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
43bf612a
RZ
1114 debug += "<br><br>";
1115 }
1116 }
1117 }
1118 if (showDebug())
133c5f7c 1119 debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
43bf612a
RZ
1120
1121 setText(head + debug + help);
1122}
1123
1124QString ConfigInfoView::debug_info(struct symbol *sym)
1125{
1126 QString debug;
1127
1128 debug += "type: ";
1129 debug += print_filter(sym_type_name(sym->type));
1130 if (sym_is_choice(sym))
1131 debug += " (choice)";
1132 debug += "<br>";
1133 if (sym->rev_dep.expr) {
1134 debug += "reverse dep: ";
1135 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1136 debug += "<br>";
1137 }
1138 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1139 switch (prop->type) {
1140 case P_PROMPT:
1141 case P_MENU:
ab45d190 1142 debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
43bf612a 1143 debug += print_filter(_(prop->text));
ab45d190 1144 debug += "</a><br>";
43bf612a
RZ
1145 break;
1146 case P_DEFAULT:
93449082
RZ
1147 case P_SELECT:
1148 case P_RANGE:
1149 case P_ENV:
1150 debug += prop_get_type_name(prop->type);
1151 debug += ": ";
43bf612a
RZ
1152 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1153 debug += "<br>";
1154 break;
1155 case P_CHOICE:
1156 if (sym_is_choice(sym)) {
1157 debug += "choice: ";
1158 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1159 debug += "<br>";
1160 }
1161 break;
43bf612a
RZ
1162 default:
1163 debug += "unknown property: ";
1164 debug += prop_get_type_name(prop->type);
1165 debug += "<br>";
1166 }
1167 if (prop->visible.expr) {
1168 debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
1169 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1170 debug += "<br>";
1171 }
1172 }
1173 debug += "<br>";
1174
1175 return debug;
1176}
1177
1178QString ConfigInfoView::print_filter(const QString &str)
1179{
1180 QRegExp re("[<>&\"\\n]");
1181 QString res = str;
68ccb7ef
BB
1182 for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
1183 switch (res[i].toLatin1()) {
43bf612a
RZ
1184 case '<':
1185 res.replace(i, 1, "&lt;");
1186 i += 4;
1187 break;
1188 case '>':
1189 res.replace(i, 1, "&gt;");
1190 i += 4;
1191 break;
1192 case '&':
1193 res.replace(i, 1, "&amp;");
1194 i += 5;
1195 break;
1196 case '"':
1197 res.replace(i, 1, "&quot;");
1198 i += 6;
1199 break;
1200 case '\n':
1201 res.replace(i, 1, "<br>");
1202 i += 4;
1203 break;
1204 }
1205 }
1206 return res;
1207}
1208
ab45d190 1209void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
43bf612a 1210{
ab45d190
RZ
1211 QString* text = reinterpret_cast<QString*>(data);
1212 QString str2 = print_filter(str);
1213
1214 if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1215 *text += QString().sprintf("<a href=\"s%p\">", sym);
1216 *text += str2;
1217 *text += "</a>";
1218 } else
1219 *text += str2;
43bf612a
RZ
1220}
1221
924bbb53 1222QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
7fc925fd 1223{
924bbb53 1224 QMenu* popup = Parent::createStandardContextMenu(pos);
85eaf28a 1225 QAction* action = new QAction(_("Show Debug Info"), popup);
68ccb7ef 1226 action->setCheckable(true);
7fc925fd
RZ
1227 connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1228 connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
9c86235a 1229 action->setChecked(showDebug());
924bbb53 1230 popup->addSeparator();
68ccb7ef 1231 popup->addAction(action);
7fc925fd
RZ
1232 return popup;
1233}
1234
924bbb53 1235void ConfigInfoView::contextMenuEvent(QContextMenuEvent *e)
7fc925fd 1236{
924bbb53 1237 Parent::contextMenuEvent(e);
7fc925fd
RZ
1238}
1239
63431e75 1240ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
68ccb7ef 1241 : Parent(parent), result(NULL)
43bf612a 1242{
d5d973c3 1243 setObjectName(name);
68ccb7ef 1244 setWindowTitle("Search Config");
43bf612a 1245
68ccb7ef
BB
1246 QVBoxLayout* layout1 = new QVBoxLayout(this);
1247 layout1->setContentsMargins(11, 11, 11, 11);
1248 layout1->setSpacing(6);
1249 QHBoxLayout* layout2 = new QHBoxLayout(0);
1250 layout2->setContentsMargins(0, 0, 0, 0);
1251 layout2->setSpacing(6);
c21a2d95 1252 layout2->addWidget(new QLabel(_("Find:"), this));
43bf612a
RZ
1253 editField = new QLineEdit(this);
1254 connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1255 layout2->addWidget(editField);
c21a2d95 1256 searchButton = new QPushButton(_("Search"), this);
68ccb7ef 1257 searchButton->setAutoDefault(false);
43bf612a
RZ
1258 connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1259 layout2->addWidget(searchButton);
1260 layout1->addLayout(layout2);
1261
7fc925fd 1262 split = new QSplitter(this);
7298b936 1263 split->setOrientation(Qt::Vertical);
7fc925fd 1264 list = new ConfigView(split, name);
d5d973c3 1265 list->list->mode = listMode;
7fc925fd 1266 info = new ConfigInfoView(split, name);
43bf612a
RZ
1267 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1268 info, SLOT(setInfo(struct menu *)));
63431e75
MC
1269 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1270 parent, SLOT(setMenuLink(struct menu *)));
1271
43bf612a 1272 layout1->addWidget(split);
7fc925fd
RZ
1273
1274 if (name) {
68ccb7ef
BB
1275 QVariant x, y;
1276 int width, height;
7fc925fd
RZ
1277 bool ok;
1278
1279 configSettings->beginGroup(name);
68ccb7ef
BB
1280 width = configSettings->value("/window width", parent->width() / 2).toInt();
1281 height = configSettings->value("/window height", parent->height() / 2).toInt();
7fc925fd 1282 resize(width, height);
68ccb7ef
BB
1283 x = configSettings->value("/window x");
1284 y = configSettings->value("/window y");
1285 if ((x.isValid())&&(y.isValid()))
1286 move(x.toInt(), y.toInt());
041fbdc2 1287 QList<int> sizes = configSettings->readSizes("/split", &ok);
7fc925fd
RZ
1288 if (ok)
1289 split->setSizes(sizes);
1290 configSettings->endGroup();
1291 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1292 }
1293}
1294
1295void ConfigSearchWindow::saveSettings(void)
1296{
d5d973c3
BB
1297 if (!objectName().isEmpty()) {
1298 configSettings->beginGroup(objectName());
1299 configSettings->setValue("/window x", pos().x());
1300 configSettings->setValue("/window y", pos().y());
1301 configSettings->setValue("/window width", size().width());
1302 configSettings->setValue("/window height", size().height());
1303 configSettings->writeSizes("/split", split->sizes());
1304 configSettings->endGroup();
1305 }
43bf612a
RZ
1306}
1307
1308void ConfigSearchWindow::search(void)
1309{
d5d973c3
BB
1310 struct symbol **p;
1311 struct property *prop;
1312 ConfigItem *lastItem = NULL;
1313
1314 free(result);
1315 list->list->clear();
1316 info->clear();
1317
1318 result = sym_re_search(editField->text().toLatin1());
1319 if (!result)
1320 return;
1321 for (p = result; *p; p++) {
1322 for_all_prompts((*p), prop)
1323 lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1324 menu_is_visible(prop->menu));
1325 }
43bf612a
RZ
1326}
1327
1da177e4
LT
1328/*
1329 * Construct the complete config widget
1330 */
1331ConfigMainWindow::ConfigMainWindow(void)
f12aa704 1332 : searchWindow(0)
1da177e4
LT
1333{
1334 QMenuBar* menu;
92119937 1335 bool ok = true;
68ccb7ef
BB
1336 QVariant x, y;
1337 int width, height;
a54bb701 1338 char title[256];
1da177e4 1339
8d90c97e 1340 QDesktopWidget *d = configApp->desktop();
0954828f
AL
1341 snprintf(title, sizeof(title), "%s%s",
1342 rootmenu.prompt->text,
76a136c4 1343 ""
76a136c4 1344 );
68ccb7ef 1345 setWindowTitle(title);
1da177e4 1346
68ccb7ef
BB
1347 width = configSettings->value("/window width", d->width() - 64).toInt();
1348 height = configSettings->value("/window height", d->height() - 64).toInt();
1da177e4 1349 resize(width, height);
68ccb7ef
BB
1350 x = configSettings->value("/window x");
1351 y = configSettings->value("/window y");
1352 if ((x.isValid())&&(y.isValid()))
1353 move(x.toInt(), y.toInt());
1da177e4
LT
1354
1355 split1 = new QSplitter(this);
7298b936 1356 split1->setOrientation(Qt::Horizontal);
1da177e4
LT
1357 setCentralWidget(split1);
1358
7fc925fd 1359 menuView = new ConfigView(split1, "menu");
1da177e4
LT
1360 menuList = menuView->list;
1361
1362 split2 = new QSplitter(split1);
7298b936 1363 split2->setOrientation(Qt::Vertical);
1da177e4
LT
1364
1365 // create config tree
7fc925fd 1366 configView = new ConfigView(split2, "config");
1da177e4
LT
1367 configList = configView->list;
1368
7fc925fd 1369 helpText = new ConfigInfoView(split2, "help");
1da177e4
LT
1370
1371 setTabOrder(configList, helpText);
1372 configList->setFocus();
1373
1374 menu = menuBar();
b1f8a45b 1375 toolBar = new QToolBar("Tools", this);
29a70168 1376 addToolBar(toolBar);
1da177e4 1377
85eaf28a 1378 backAction = new QAction(QPixmap(xpm_back), _("Back"), this);
92119937 1379 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
68ccb7ef 1380 backAction->setEnabled(false);
85eaf28a
BB
1381 QAction *quitAction = new QAction(_("&Quit"), this);
1382 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
92119937 1383 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
85eaf28a
BB
1384 QAction *loadAction = new QAction(QPixmap(xpm_load), _("&Load"), this);
1385 loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
92119937 1386 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
85eaf28a
BB
1387 saveAction = new QAction(QPixmap(xpm_save), _("&Save"), this);
1388 saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
92119937 1389 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
3b354c55
KW
1390 conf_set_changed_callback(conf_changed);
1391 // Set saveAction's initial state
1392 conf_changed();
85eaf28a 1393 QAction *saveAsAction = new QAction(_("Save &As..."), this);
92119937 1394 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
85eaf28a
BB
1395 QAction *searchAction = new QAction(_("&Find"), this);
1396 searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
92119937 1397 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
780505e3 1398 singleViewAction = new QAction(QPixmap(xpm_single_view), _("Single View"), this);
68ccb7ef 1399 singleViewAction->setCheckable(true);
92119937 1400 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
780505e3 1401 splitViewAction = new QAction(QPixmap(xpm_split_view), _("Split View"), this);
68ccb7ef 1402 splitViewAction->setCheckable(true);
92119937 1403 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
780505e3 1404 fullViewAction = new QAction(QPixmap(xpm_tree_view), _("Full View"), this);
68ccb7ef 1405 fullViewAction->setCheckable(true);
92119937 1406 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
1da177e4 1407
85eaf28a 1408 QAction *showNameAction = new QAction(_("Show Name"), this);
68ccb7ef 1409 showNameAction->setCheckable(true);
7fc925fd 1410 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
9c86235a 1411 showNameAction->setChecked(configView->showName());
85eaf28a 1412 QAction *showRangeAction = new QAction(_("Show Range"), this);
68ccb7ef 1413 showRangeAction->setCheckable(true);
7fc925fd 1414 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
85eaf28a 1415 QAction *showDataAction = new QAction(_("Show Data"), this);
68ccb7ef 1416 showDataAction->setCheckable(true);
7fc925fd 1417 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
39a4897c
LZ
1418
1419 QActionGroup *optGroup = new QActionGroup(this);
68ccb7ef 1420 optGroup->setExclusive(true);
92119937 1421 connect(optGroup, SIGNAL(triggered(QAction*)), configView,
39a4897c 1422 SLOT(setOptionMode(QAction *)));
92119937 1423 connect(optGroup, SIGNAL(triggered(QAction *)), menuView,
39a4897c
LZ
1424 SLOT(setOptionMode(QAction *)));
1425
133c5f7c
AS
1426 configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup);
1427 configView->showAllAction = new QAction(_("Show All Options"), optGroup);
1428 configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup);
68ccb7ef
BB
1429 configView->showNormalAction->setCheckable(true);
1430 configView->showAllAction->setCheckable(true);
1431 configView->showPromptAction->setCheckable(true);
39a4897c 1432
85eaf28a 1433 QAction *showDebugAction = new QAction( _("Show Debug Info"), this);
68ccb7ef 1434 showDebugAction->setCheckable(true);
43bf612a 1435 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
9c86235a 1436 showDebugAction->setChecked(helpText->showDebug());
1da177e4 1437
85eaf28a 1438 QAction *showIntroAction = new QAction( _("Introduction"), this);
92119937 1439 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
85eaf28a 1440 QAction *showAboutAction = new QAction( _("About"), this);
92119937 1441 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
1da177e4
LT
1442
1443 // init tool bar
68ccb7ef 1444 toolBar->addAction(backAction);
1da177e4 1445 toolBar->addSeparator();
68ccb7ef
BB
1446 toolBar->addAction(loadAction);
1447 toolBar->addAction(saveAction);
1da177e4 1448 toolBar->addSeparator();
68ccb7ef
BB
1449 toolBar->addAction(singleViewAction);
1450 toolBar->addAction(splitViewAction);
1451 toolBar->addAction(fullViewAction);
1da177e4
LT
1452
1453 // create config menu
68ccb7ef
BB
1454 QMenu* config = menu->addMenu(_("&File"));
1455 config->addAction(loadAction);
1456 config->addAction(saveAction);
1457 config->addAction(saveAsAction);
76bede87 1458 config->addSeparator();
68ccb7ef 1459 config->addAction(quitAction);
1da177e4 1460
66e7c723 1461 // create edit menu
68ccb7ef
BB
1462 QMenu* editMenu = menu->addMenu(_("&Edit"));
1463 editMenu->addAction(searchAction);
66e7c723 1464
1da177e4 1465 // create options menu
68ccb7ef
BB
1466 QMenu* optionMenu = menu->addMenu(_("&Option"));
1467 optionMenu->addAction(showNameAction);
1468 optionMenu->addAction(showRangeAction);
1469 optionMenu->addAction(showDataAction);
76bede87 1470 optionMenu->addSeparator();
68ccb7ef 1471 optionMenu->addActions(optGroup->actions());
76bede87 1472 optionMenu->addSeparator();
1da177e4
LT
1473
1474 // create help menu
76bede87 1475 menu->addSeparator();
68ccb7ef
BB
1476 QMenu* helpMenu = menu->addMenu(_("&Help"));
1477 helpMenu->addAction(showIntroAction);
1478 helpMenu->addAction(showAboutAction);
1da177e4 1479
d5d973c3
BB
1480 connect(configList, SIGNAL(menuChanged(struct menu *)),
1481 helpText, SLOT(setInfo(struct menu *)));
1482 connect(configList, SIGNAL(menuSelected(struct menu *)),
1483 SLOT(changeMenu(struct menu *)));
1484 connect(configList, SIGNAL(parentSelected()),
1485 SLOT(goBack()));
1486 connect(menuList, SIGNAL(menuChanged(struct menu *)),
1487 helpText, SLOT(setInfo(struct menu *)));
1488 connect(menuList, SIGNAL(menuSelected(struct menu *)),
1489 SLOT(changeMenu(struct menu *)));
1490
1491 connect(configList, SIGNAL(gotFocus(struct menu *)),
1492 helpText, SLOT(setInfo(struct menu *)));
1493 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1494 helpText, SLOT(setInfo(struct menu *)));
1495 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1496 SLOT(listFocusChanged(void)));
b65a47e1
RZ
1497 connect(helpText, SIGNAL(menuSelected(struct menu *)),
1498 SLOT(setMenuLink(struct menu *)));
1da177e4 1499
68ccb7ef 1500 QString listMode = configSettings->value("/listMode", "symbol").toString();
1da177e4
LT
1501 if (listMode == "single")
1502 showSingleView();
1503 else if (listMode == "full")
1504 showFullView();
1505 else /*if (listMode == "split")*/
1506 showSplitView();
1507
1508 // UI setup done, restore splitter positions
041fbdc2 1509 QList<int> sizes = configSettings->readSizes("/split1", &ok);
1da177e4
LT
1510 if (ok)
1511 split1->setSizes(sizes);
1512
7fc925fd 1513 sizes = configSettings->readSizes("/split2", &ok);
1da177e4
LT
1514 if (ok)
1515 split2->setSizes(sizes);
1da177e4
LT
1516}
1517
1da177e4
LT
1518void ConfigMainWindow::loadConfig(void)
1519{
68ccb7ef 1520 QString s = QFileDialog::getOpenFileName(this, "", conf_get_configname());
1da177e4
LT
1521 if (s.isNull())
1522 return;
3b9fa093 1523 if (conf_read(QFile::encodeName(s)))
c21a2d95 1524 QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
1da177e4
LT
1525 ConfigView::updateListAll();
1526}
1527
bac6aa86 1528bool ConfigMainWindow::saveConfig(void)
1da177e4 1529{
bac6aa86 1530 if (conf_write(NULL)) {
c21a2d95 1531 QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
bac6aa86
MM
1532 return false;
1533 }
1534 return true;
1da177e4
LT
1535}
1536
1537void ConfigMainWindow::saveConfigAs(void)
1538{
68ccb7ef 1539 QString s = QFileDialog::getSaveFileName(this, "", conf_get_configname());
1da177e4
LT
1540 if (s.isNull())
1541 return;
d49e4687 1542 saveConfig();
1da177e4
LT
1543}
1544
43bf612a
RZ
1545void ConfigMainWindow::searchConfig(void)
1546{
1547 if (!searchWindow)
7fc925fd 1548 searchWindow = new ConfigSearchWindow(this, "search");
43bf612a
RZ
1549 searchWindow->show();
1550}
1551
1da177e4
LT
1552void ConfigMainWindow::changeMenu(struct menu *menu)
1553{
d5d973c3
BB
1554 configList->setRootMenu(menu);
1555 if (configList->rootEntry->parent == &rootmenu)
1556 backAction->setEnabled(false);
1557 else
1558 backAction->setEnabled(true);
1da177e4
LT
1559}
1560
b65a47e1 1561void ConfigMainWindow::setMenuLink(struct menu *menu)
1da177e4 1562{
d5d973c3
BB
1563 struct menu *parent;
1564 ConfigList* list = NULL;
1565 ConfigItem* item;
1566
1567 if (configList->menuSkip(menu))
1568 return;
1569
1570 switch (configList->mode) {
1571 case singleMode:
1572 list = configList;
1573 parent = menu_get_parent_menu(menu);
1574 if (!parent)
1575 return;
1576 list->setRootMenu(parent);
1577 break;
1578 case symbolMode:
1579 if (menu->flags & MENU_ROOT) {
1580 configList->setRootMenu(menu);
1581 configList->clearSelection();
1582 list = menuList;
1583 } else {
1584 list = configList;
1585 parent = menu_get_parent_menu(menu->parent);
1586 if (!parent)
1587 return;
1588 item = menuList->findConfigItem(parent);
1589 if (item) {
1590 item->setSelected(true);
1591 menuList->scrollToItem(item);
1592 }
1593 list->setRootMenu(parent);
1594 }
1595 break;
1596 case fullMode:
1597 list = configList;
1598 break;
1599 default:
1600 break;
1601 }
1602
1603 if (list) {
1604 item = list->findConfigItem(menu);
1605 if (item) {
1606 item->setSelected(true);
1607 list->scrollToItem(item);
1608 list->setFocus();
1609 }
1610 }
1da177e4
LT
1611}
1612
b65a47e1
RZ
1613void ConfigMainWindow::listFocusChanged(void)
1614{
d5d973c3
BB
1615 if (menuList->mode == menuMode)
1616 configList->clearSelection();
b65a47e1
RZ
1617}
1618
1da177e4
LT
1619void ConfigMainWindow::goBack(void)
1620{
5df9da9d 1621 ConfigItem* item, *oldSelection;
d5d973c3
BB
1622
1623 configList->setParentMenu();
1624 if (configList->rootEntry == &rootmenu)
1625 backAction->setEnabled(false);
1626 item = (ConfigItem*)menuList->selectedItems().first();
5df9da9d 1627 oldSelection = item;
d5d973c3
BB
1628 while (item) {
1629 if (item->menu == configList->rootEntry) {
5df9da9d 1630 oldSelection->setSelected(false);
d5d973c3
BB
1631 item->setSelected(true);
1632 break;
1633 }
1634 item = (ConfigItem*)item->parent();
1635 }
1da177e4
LT
1636}
1637
1638void ConfigMainWindow::showSingleView(void)
1639{
780505e3
BB
1640 singleViewAction->setEnabled(false);
1641 singleViewAction->setChecked(true);
1642 splitViewAction->setEnabled(true);
1643 splitViewAction->setChecked(false);
1644 fullViewAction->setEnabled(true);
1645 fullViewAction->setChecked(false);
1646
1da177e4 1647 menuView->hide();
d5d973c3
BB
1648 menuList->setRootMenu(0);
1649 configList->mode = singleMode;
1650 if (configList->rootEntry == &rootmenu)
1651 configList->updateListAll();
1652 else
1653 configList->setRootMenu(&rootmenu);
1da177e4
LT
1654 configList->setFocus();
1655}
1656
1657void ConfigMainWindow::showSplitView(void)
1658{
780505e3
BB
1659 singleViewAction->setEnabled(true);
1660 singleViewAction->setChecked(false);
1661 splitViewAction->setEnabled(false);
1662 splitViewAction->setChecked(true);
1663 fullViewAction->setEnabled(true);
1664 fullViewAction->setChecked(false);
1665
d5d973c3
BB
1666 configList->mode = symbolMode;
1667 if (configList->rootEntry == &rootmenu)
1668 configList->updateListAll();
1669 else
1670 configList->setRootMenu(&rootmenu);
1671 configList->setAllOpen(true);
1672 configApp->processEvents();
1673 menuList->mode = menuMode;
1674 menuList->setRootMenu(&rootmenu);
1675 menuList->setAllOpen(true);
1da177e4
LT
1676 menuView->show();
1677 menuList->setFocus();
1678}
1679
1680void ConfigMainWindow::showFullView(void)
1681{
780505e3
BB
1682 singleViewAction->setEnabled(true);
1683 singleViewAction->setChecked(false);
1684 splitViewAction->setEnabled(true);
1685 splitViewAction->setChecked(false);
1686 fullViewAction->setEnabled(false);
1687 fullViewAction->setChecked(true);
1688
1da177e4 1689 menuView->hide();
d5d973c3
BB
1690 menuList->setRootMenu(0);
1691 configList->mode = fullMode;
1692 if (configList->rootEntry == &rootmenu)
1693 configList->updateListAll();
1694 else
1695 configList->setRootMenu(&rootmenu);
1da177e4
LT
1696 configList->setFocus();
1697}
1698
1da177e4
LT
1699/*
1700 * ask for saving configuration before quitting
1701 * TODO ask only when something changed
1702 */
1703void ConfigMainWindow::closeEvent(QCloseEvent* e)
1704{
b3214293 1705 if (!conf_get_changed()) {
1da177e4
LT
1706 e->accept();
1707 return;
1708 }
c21a2d95 1709 QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
1da177e4 1710 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
c21a2d95
EG
1711 mb.setButtonText(QMessageBox::Yes, _("&Save Changes"));
1712 mb.setButtonText(QMessageBox::No, _("&Discard Changes"));
1713 mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
1da177e4
LT
1714 switch (mb.exec()) {
1715 case QMessageBox::Yes:
bac6aa86
MM
1716 if (saveConfig())
1717 e->accept();
1718 else
1719 e->ignore();
1720 break;
1da177e4
LT
1721 case QMessageBox::No:
1722 e->accept();
1723 break;
1724 case QMessageBox::Cancel:
1725 e->ignore();
1726 break;
1727 }
1728}
1729
1730void ConfigMainWindow::showIntro(void)
1731{
652cf982 1732 static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
1da177e4
LT
1733 "For each option, a blank box indicates the feature is disabled, a check\n"
1734 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1735 "as a module. Clicking on the box will cycle through the three states.\n\n"
1736 "If you do not see an option (e.g., a device driver) that you believe\n"
1737 "should be present, try turning on Show All Options under the Options menu.\n"
1738 "Although there is no cross reference yet to help you figure out what other\n"
1739 "options must be enabled to support the option you are interested in, you can\n"
1740 "still view the help of a grayed-out option.\n\n"
1741 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
c21a2d95 1742 "which you can then match by examining other options.\n\n");
1da177e4
LT
1743
1744 QMessageBox::information(this, "qconf", str);
1745}
1746
1747void ConfigMainWindow::showAbout(void)
1748{
c21a2d95
EG
1749 static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
1750 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
1da177e4
LT
1751
1752 QMessageBox::information(this, "qconf", str);
1753}
1754
1755void ConfigMainWindow::saveSettings(void)
1756{
68ccb7ef
BB
1757 configSettings->setValue("/window x", pos().x());
1758 configSettings->setValue("/window y", pos().y());
1759 configSettings->setValue("/window width", size().width());
1760 configSettings->setValue("/window height", size().height());
1da177e4
LT
1761
1762 QString entry;
d5d973c3
BB
1763 switch(configList->mode) {
1764 case singleMode :
1765 entry = "single";
1766 break;
1767
1768 case symbolMode :
1769 entry = "split";
1770 break;
1771
1772 case fullMode :
1773 entry = "full";
1774 break;
98403a91 1775
d5d973c3
BB
1776 default:
1777 break;
1778 }
68ccb7ef 1779 configSettings->setValue("/listMode", entry);
1da177e4 1780
7fc925fd
RZ
1781 configSettings->writeSizes("/split1", split1->sizes());
1782 configSettings->writeSizes("/split2", split2->sizes());
1da177e4
LT
1783}
1784
3b354c55
KW
1785void ConfigMainWindow::conf_changed(void)
1786{
1787 if (saveAction)
1788 saveAction->setEnabled(conf_get_changed());
1789}
1790
1da177e4
LT
1791void fixup_rootmenu(struct menu *menu)
1792{
1793 struct menu *child;
1794 static int menu_cnt = 0;
1795
1796 menu->flags |= MENU_ROOT;
1797 for (child = menu->list; child; child = child->next) {
1798 if (child->prompt && child->prompt->type == P_MENU) {
1799 menu_cnt++;
1800 fixup_rootmenu(child);
1801 menu_cnt--;
1802 } else if (!menu_cnt)
1803 fixup_rootmenu(child);
1804 }
1805}
1806
1807static const char *progname;
1808
1809static void usage(void)
1810{
68ccb7ef 1811 printf(_("%s [-s] <config>\n").toLatin1().constData(), progname);
1da177e4
LT
1812 exit(0);
1813}
1814
1815int main(int ac, char** av)
1816{
1817 ConfigMainWindow* v;
1818 const char *name;
1819
3b9fa093
ACM
1820 bindtextdomain(PACKAGE, LOCALEDIR);
1821 textdomain(PACKAGE);
1822
1da177e4
LT
1823 progname = av[0];
1824 configApp = new QApplication(ac, av);
1825 if (ac > 1 && av[1][0] == '-') {
1826 switch (av[1][1]) {
0a1f00a1
MM
1827 case 's':
1828 conf_set_message_callback(NULL);
1829 break;
1da177e4
LT
1830 case 'h':
1831 case '?':
1832 usage();
1833 }
1834 name = av[2];
1835 } else
1836 name = av[1];
1837 if (!name)
1838 usage();
1839
1840 conf_parse(name);
1841 fixup_rootmenu(&rootmenu);
1842 conf_read(NULL);
1843 //zconfdump(stdout);
1844
7fc925fd
RZ
1845 configSettings = new ConfigSettings();
1846 configSettings->beginGroup("/kconfig/qconf");
1da177e4
LT
1847 v = new ConfigMainWindow();
1848
1849 //zconfdump(stdout);
1da177e4
LT
1850 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1851 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
43bf612a 1852 v->show();
1da177e4
LT
1853 configApp->exec();
1854
7fc925fd
RZ
1855 configSettings->endGroup();
1856 delete configSettings;
1857
1da177e4
LT
1858 return 0;
1859}