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