blob: 0e06afa08908b66377a9896083be7863d74b0140 [file] [log] [blame]
Masahiro Yamada0c874102018-12-18 21:13:35 +09001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
Boris Barbulovskib4ff1de2015-09-22 11:36:38 -07004 * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 */
6
Boris Barbulovski85eaf282015-09-22 11:36:03 -07007#include <QAction>
Mauro Carvalho Chehabcf81dfa2020-06-30 08:26:35 +02008#include <QApplication>
9#include <QCloseEvent>
10#include <QDesktopWidget>
Boris Barbulovskibea00772015-09-22 11:36:04 -070011#include <QFileDialog>
Mauro Carvalho Chehabcf81dfa2020-06-30 08:26:35 +020012#include <QLabel>
13#include <QLayout>
14#include <QList>
Boris Barbulovski76bede82015-09-22 11:36:07 -070015#include <QMenu>
Mauro Carvalho Chehabcf81dfa2020-06-30 08:26:35 +020016#include <QMenuBar>
17#include <QMessageBox>
18#include <QToolBar>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019
20#include <stdlib.h>
21
22#include "lkc.h"
23#include "qconf.h"
24
25#include "qconf.moc"
Masahiro Yamada3b541978562018-12-21 17:33:07 +090026#include "images.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029static QApplication *configApp;
Roman Zippel7fc925f2006-06-08 22:12:46 -070030static ConfigSettings *configSettings;
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
Boris Barbulovski85eaf282015-09-22 11:36:03 -070032QAction *ConfigMainWindow::saveAction;
Karsten Wiese3b354c52006-12-13 00:34:08 -080033
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -070034static inline QString qgettext(const char* str)
35{
Sam Ravnborg694c49a2018-05-22 21:36:12 +020036 return QString::fromLocal8Bit(str);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -070037}
38
Ben Hutchings00d4f8f2013-10-06 19:21:31 +010039ConfigSettings::ConfigSettings()
40 : QSettings("kernel.org", "qconf")
41{
42}
43
Linus Torvalds1da177e2005-04-16 15:20:36 -070044/**
45 * Reads a list of integer values from the application settings.
46 */
Boris Barbulovski041fbdc2015-09-22 11:36:05 -070047QList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
Linus Torvalds1da177e2005-04-16 15:20:36 -070048{
Boris Barbulovski041fbdc2015-09-22 11:36:05 -070049 QList<int> result;
Li Zefanc1f96f02010-05-07 13:58:04 +080050
Boris Barbulovski83c3a1b2016-11-30 14:57:55 -080051 if (contains(key))
52 {
53 QStringList entryList = value(key).toStringList();
54 QStringList::Iterator it;
55
56 for (it = entryList.begin(); it != entryList.end(); ++it)
57 result.push_back((*it).toInt());
58
59 *ok = true;
60 }
61 else
62 *ok = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
64 return result;
65}
66
67/**
68 * Writes a list of integer values to the application settings.
69 */
Boris Barbulovski041fbdc2015-09-22 11:36:05 -070070bool ConfigSettings::writeSizes(const QString& key, const QList<int>& value)
Linus Torvalds1da177e2005-04-16 15:20:36 -070071{
72 QStringList stringList;
Boris Barbulovski041fbdc2015-09-22 11:36:05 -070073 QList<int>::ConstIterator it;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
75 for (it = value.begin(); it != value.end(); ++it)
76 stringList.push_back(QString::number(*it));
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -070077 setValue(key, stringList);
Boris Barbulovski59e56442015-09-22 11:36:18 -070078
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -070079 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070080}
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
Boris Barbulovski59e56442015-09-22 11:36:18 -070082
83/*
84 * set the new data
85 * TODO check the value
86 */
87void ConfigItem::okRename(int col)
88{
89}
90
91/*
92 * update the displayed of a menu entry
93 */
94void ConfigItem::updateMenu(void)
95{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -070096 ConfigList* list;
97 struct symbol* sym;
98 struct property *prop;
99 QString prompt;
100 int type;
101 tristate expr;
102
103 list = listView();
104 if (goParent) {
105 setPixmap(promptColIdx, list->menuBackPix);
106 prompt = "..";
107 goto set_prompt;
108 }
109
110 sym = menu->sym;
111 prop = menu->prompt;
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200112 prompt = qgettext(menu_get_prompt(menu));
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700113
114 if (prop) switch (prop->type) {
115 case P_MENU:
116 if (list->mode == singleMode || list->mode == symbolMode) {
117 /* a menuconfig entry is displayed differently
118 * depending whether it's at the view root or a child.
119 */
120 if (sym && list->rootEntry == menu)
121 break;
122 setPixmap(promptColIdx, list->menuPix);
123 } else {
124 if (sym)
125 break;
126 setPixmap(promptColIdx, QIcon());
127 }
128 goto set_prompt;
129 case P_COMMENT:
130 setPixmap(promptColIdx, QIcon());
131 goto set_prompt;
132 default:
133 ;
134 }
135 if (!sym)
136 goto set_prompt;
137
138 setText(nameColIdx, QString::fromLocal8Bit(sym->name));
139
140 type = sym_get_type(sym);
141 switch (type) {
142 case S_BOOLEAN:
143 case S_TRISTATE:
144 char ch;
145
Marco Ammonbaa23ec2019-07-04 12:50:41 +0200146 if (!sym_is_changeable(sym) && list->optMode == normalOpt) {
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700147 setPixmap(promptColIdx, QIcon());
Mauro Carvalho Chehabcf497b92020-04-02 11:27:58 +0200148 setText(noColIdx, QString());
149 setText(modColIdx, QString());
150 setText(yesColIdx, QString());
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700151 break;
152 }
153 expr = sym_get_tristate_value(sym);
154 switch (expr) {
155 case yes:
156 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
157 setPixmap(promptColIdx, list->choiceYesPix);
158 else
159 setPixmap(promptColIdx, list->symbolYesPix);
160 setText(yesColIdx, "Y");
161 ch = 'Y';
162 break;
163 case mod:
164 setPixmap(promptColIdx, list->symbolModPix);
165 setText(modColIdx, "M");
166 ch = 'M';
167 break;
168 default:
169 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
170 setPixmap(promptColIdx, list->choiceNoPix);
171 else
172 setPixmap(promptColIdx, list->symbolNoPix);
173 setText(noColIdx, "N");
174 ch = 'N';
175 break;
176 }
177 if (expr != no)
178 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
179 if (expr != mod)
180 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
181 if (expr != yes)
182 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
183
184 setText(dataColIdx, QChar(ch));
185 break;
186 case S_INT:
187 case S_HEX:
188 case S_STRING:
189 const char* data;
190
191 data = sym_get_string_value(sym);
192
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700193 setText(dataColIdx, data);
194 if (type == S_STRING)
195 prompt = QString("%1: %2").arg(prompt).arg(data);
196 else
197 prompt = QString("(%2) %1").arg(prompt).arg(data);
198 break;
199 }
200 if (!sym_has_value(sym) && visible)
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200201 prompt += " (NEW)";
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700202set_prompt:
203 setText(promptColIdx, prompt);
Boris Barbulovski59e56442015-09-22 11:36:18 -0700204}
205
206void ConfigItem::testUpdateMenu(bool v)
207{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700208 ConfigItem* i;
209
210 visible = v;
211 if (!menu)
212 return;
213
214 sym_calc_value(menu->sym);
215 if (menu->flags & MENU_CHANGED) {
216 /* the menu entry changed, so update all list items */
217 menu->flags &= ~MENU_CHANGED;
218 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
219 i->updateMenu();
220 } else if (listView()->updateAll)
221 updateMenu();
Boris Barbulovski59e56442015-09-22 11:36:18 -0700222}
223
224
Boris Barbulovski1019f1a2015-09-22 11:36:17 -0700225/*
226 * construct a menu entry
227 */
228void ConfigItem::init(void)
229{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700230 if (menu) {
231 ConfigList* list = listView();
232 nextItem = (ConfigItem*)menu->data;
233 menu->data = this;
234
235 if (list->mode != fullMode)
236 setExpanded(true);
237 sym_calc_value(menu->sym);
238 }
239 updateMenu();
Boris Barbulovski1019f1a2015-09-22 11:36:17 -0700240}
241
242/*
243 * destruct a menu entry
244 */
245ConfigItem::~ConfigItem(void)
246{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700247 if (menu) {
248 ConfigItem** ip = (ConfigItem**)&menu->data;
249 for (; *ip; ip = &(*ip)->nextItem) {
250 if (*ip == this) {
251 *ip = nextItem;
252 break;
253 }
254 }
255 }
Boris Barbulovski1019f1a2015-09-22 11:36:17 -0700256}
257
Roman Zippel43bf6122006-06-08 22:12:45 -0700258ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
259 : Parent(parent)
260{
Boris Barbulovskic14fa5e2015-09-22 11:36:21 -0700261 connect(this, SIGNAL(editingFinished()), SLOT(hide()));
Roman Zippel43bf6122006-06-08 22:12:45 -0700262}
263
Boris Barbulovski1019f1a2015-09-22 11:36:17 -0700264void ConfigLineEdit::show(ConfigItem* i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265{
266 item = i;
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700267 if (sym_get_string_value(item->menu->sym))
268 setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
269 else
Mauro Carvalho Chehabcf497b92020-04-02 11:27:58 +0200270 setText(QString());
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 Parent::show();
272 setFocus();
273}
274
275void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
276{
277 switch (e->key()) {
Markus Heidelbergfbb86372009-05-18 01:36:51 +0200278 case Qt::Key_Escape:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 break;
Markus Heidelbergfbb86372009-05-18 01:36:51 +0200280 case Qt::Key_Return:
281 case Qt::Key_Enter:
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700282 sym_set_string_value(item->menu->sym, text().toLatin1());
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 parent()->updateList(item);
284 break;
285 default:
286 Parent::keyPressEvent(e);
287 return;
288 }
289 e->accept();
290 parent()->list->setFocus();
291 hide();
292}
293
Boris Barbulovski1019f1a2015-09-22 11:36:17 -0700294ConfigList::ConfigList(ConfigView* p, const char *name)
Boris Barbulovski59e56442015-09-22 11:36:18 -0700295 : Parent(p),
296 updateAll(false),
297 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
298 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
299 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
Boris Barbulovskidbf62932015-09-22 11:36:26 -0700300 showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt),
Boris Barbulovski59e56442015-09-22 11:36:18 -0700301 rootEntry(0), headerPopup(0)
Boris Barbulovski1019f1a2015-09-22 11:36:17 -0700302{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700303 setObjectName(name);
Boris Barbulovskia5225e92015-09-22 11:36:29 -0700304 setSortingEnabled(false);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700305 setRootIsDecorated(true);
306
Boris Barbulovskif999cc02015-09-22 11:36:31 -0700307 setVerticalScrollMode(ScrollPerPixel);
308 setHorizontalScrollMode(ScrollPerPixel);
309
Mauro Carvalho Chehab5752ff02020-04-02 11:27:59 +0200310 if (mode == symbolMode)
311 setHeaderLabels(QStringList() << "Item" << "Name" << "N" << "M" << "Y" << "Value");
312 else
313 setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value");
Boris Barbulovskia52cb322015-09-22 11:36:24 -0700314
Boris Barbulovskic14fa5e2015-09-22 11:36:21 -0700315 connect(this, SIGNAL(itemSelectionChanged(void)),
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700316 SLOT(updateSelection(void)));
317
318 if (name) {
319 configSettings->beginGroup(name);
320 showName = configSettings->value("/showName", false).toBool();
321 showRange = configSettings->value("/showRange", false).toBool();
322 showData = configSettings->value("/showData", false).toBool();
323 optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt();
324 configSettings->endGroup();
325 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
326 }
327
328 addColumn(promptColIdx);
329
330 reinit();
331}
332
333bool ConfigList::menuSkip(struct menu *menu)
334{
335 if (optMode == normalOpt && menu_is_visible(menu))
336 return false;
337 if (optMode == promptOpt && menu_has_prompt(menu))
338 return false;
339 if (optMode == allOpt)
340 return false;
341 return true;
Boris Barbulovski1019f1a2015-09-22 11:36:17 -0700342}
Boris Barbulovski59e56442015-09-22 11:36:18 -0700343
344void ConfigList::reinit(void)
345{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700346 removeColumn(dataColIdx);
347 removeColumn(yesColIdx);
348 removeColumn(modColIdx);
349 removeColumn(noColIdx);
350 removeColumn(nameColIdx);
351
352 if (showName)
353 addColumn(nameColIdx);
354 if (showRange) {
355 addColumn(noColIdx);
356 addColumn(modColIdx);
357 addColumn(yesColIdx);
358 }
359 if (showData)
360 addColumn(dataColIdx);
361
362 updateListAll();
Boris Barbulovski59e56442015-09-22 11:36:18 -0700363}
364
365void ConfigList::saveSettings(void)
366{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700367 if (!objectName().isEmpty()) {
368 configSettings->beginGroup(objectName());
369 configSettings->setValue("/showName", showName);
370 configSettings->setValue("/showRange", showRange);
371 configSettings->setValue("/showData", showData);
372 configSettings->setValue("/optionMode", (int)optMode);
373 configSettings->endGroup();
374 }
Boris Barbulovski59e56442015-09-22 11:36:18 -0700375}
376
377ConfigItem* ConfigList::findConfigItem(struct menu *menu)
378{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700379 ConfigItem* item = (ConfigItem*)menu->data;
380
381 for (; item; item = item->nextItem) {
382 if (this == item->listView())
383 break;
384 }
385
386 return item;
Boris Barbulovski59e56442015-09-22 11:36:18 -0700387}
388
389void ConfigList::updateSelection(void)
390{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700391 struct menu *menu;
392 enum prop_type type;
393
Mauro Carvalho Chehab5752ff02020-04-02 11:27:59 +0200394 if (mode == symbolMode)
395 setHeaderLabels(QStringList() << "Item" << "Name" << "N" << "M" << "Y" << "Value");
396 else
397 setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value");
398
Boris Barbulovskibe596aa2015-09-22 11:36:28 -0700399 if (selectedItems().count() == 0)
400 return;
401
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700402 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);
Boris Barbulovski59e56442015-09-22 11:36:18 -0700413}
414
415void ConfigList::updateList(ConfigItem* item)
416{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700417 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))) {
Boris Barbulovskiee7298f2015-09-22 11:36:37 -0700438 item = (ConfigItem *)topLevelItem(0);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700439 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();
Boris Barbulovskif999cc02015-09-22 11:36:31 -0700453 resizeColumnToContents(0);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700454 return;
455 }
456update:
457 updateMenuList(this, rootEntry);
458 update();
Boris Barbulovskif999cc02015-09-22 11:36:31 -0700459 resizeColumnToContents(0);
Boris Barbulovski59e56442015-09-22 11:36:18 -0700460}
461
462void ConfigList::setValue(ConfigItem* item, tristate val)
463{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700464 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 }
Boris Barbulovski59e56442015-09-22 11:36:18 -0700485}
486
487void ConfigList::changeValue(ConfigItem* item)
488{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700489 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:
Boris Barbulovskie336b9f2015-09-22 11:36:34 -0700521 parent()->lineEdit->show(item);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700522 break;
523 }
Boris Barbulovski59e56442015-09-22 11:36:18 -0700524}
525
526void ConfigList::setRootMenu(struct menu *menu)
527{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700528 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 }
Boris Barbulovski59e56442015-09-22 11:36:18 -0700542}
543
544void ConfigList::setParentMenu(void)
545{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700546 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 }
Boris Barbulovski59e56442015-09-22 11:36:18 -0700565}
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 */
Boris Barbulovski5c6f1552015-09-22 11:36:27 -0700574void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
Boris Barbulovski59e56442015-09-22 11:36:18 -0700575{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700576 struct menu* child;
577 ConfigItem* item;
578 ConfigItem* last;
579 bool visible;
580 enum prop_type type;
581
582 if (!menu) {
Boris Barbulovski5c6f1552015-09-22 11:36:27 -0700583 while (parent->childCount() > 0)
584 {
585 delete parent->takeChild(0);
586 }
587
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700588 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 }
Mauro Carvalho Chehab60969f02020-04-02 11:28:03 +0200627hide:
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700628 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 }
Boris Barbulovski59e56442015-09-22 11:36:18 -0700637}
638
Boris Barbulovski5c6f1552015-09-22 11:36:27 -0700639void 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 }
Mauro Carvalho Chehab60969f02020-04-02 11:28:03 +0200692hide:
Boris Barbulovski5c6f1552015-09-22 11:36:27 -0700693 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
Boris Barbulovski59e56442015-09-22 11:36:18 -0700704void ConfigList::keyPressEvent(QKeyEvent* ev)
705{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700706 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) {
Mauro Carvalho Chehabb3111422020-04-02 11:28:01 +0200736 if (mode == menuMode)
737 emit menuSelected(menu);
738 else
739 emit itemSelected(menu);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700740 break;
741 }
742 case Qt::Key_Space:
743 changeValue(item);
744 break;
745 case Qt::Key_N:
746 setValue(item, no);
747 break;
748 case Qt::Key_M:
749 setValue(item, mod);
750 break;
751 case Qt::Key_Y:
752 setValue(item, yes);
753 break;
754 default:
755 Parent::keyPressEvent(ev);
756 return;
757 }
758 ev->accept();
Boris Barbulovski59e56442015-09-22 11:36:18 -0700759}
760
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700761void ConfigList::mousePressEvent(QMouseEvent* e)
Boris Barbulovski59e56442015-09-22 11:36:18 -0700762{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700763 //QPoint p(contentsToViewport(e->pos()));
764 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
765 Parent::mousePressEvent(e);
Boris Barbulovski59e56442015-09-22 11:36:18 -0700766}
767
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700768void ConfigList::mouseReleaseEvent(QMouseEvent* e)
Boris Barbulovski59e56442015-09-22 11:36:18 -0700769{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700770 QPoint p = e->pos();
771 ConfigItem* item = (ConfigItem*)itemAt(p);
772 struct menu *menu;
773 enum prop_type ptype;
774 QIcon icon;
775 int idx, x;
776
777 if (!item)
778 goto skip;
779
780 menu = item->menu;
781 x = header()->offset() + p.x();
Boris Barbulovski76d53cb2015-09-22 11:36:35 -0700782 idx = header()->logicalIndexAt(x);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700783 switch (idx) {
784 case promptColIdx:
785 icon = item->pixmap(promptColIdx);
Boris Barbulovski76d53cb2015-09-22 11:36:35 -0700786 if (!icon.isNull()) {
787 int off = header()->sectionPosition(0) + visualRect(indexAt(p)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly.
788 if (x >= off && x < off + icon.availableSizes().first().width()) {
789 if (item->goParent) {
790 emit parentSelected();
791 break;
792 } else if (!menu)
793 break;
794 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
795 if (ptype == P_MENU && rootEntry != menu &&
796 mode != fullMode && mode != menuMode)
797 emit menuSelected(menu);
798 else
799 changeValue(item);
800 }
801 }
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700802 break;
803 case noColIdx:
804 setValue(item, no);
805 break;
806 case modColIdx:
807 setValue(item, mod);
808 break;
809 case yesColIdx:
810 setValue(item, yes);
811 break;
812 case dataColIdx:
813 changeValue(item);
814 break;
815 }
816
817skip:
818 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
819 Parent::mouseReleaseEvent(e);
Boris Barbulovski59e56442015-09-22 11:36:18 -0700820}
821
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700822void ConfigList::mouseMoveEvent(QMouseEvent* e)
Boris Barbulovski59e56442015-09-22 11:36:18 -0700823{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700824 //QPoint p(contentsToViewport(e->pos()));
825 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
826 Parent::mouseMoveEvent(e);
Boris Barbulovski59e56442015-09-22 11:36:18 -0700827}
828
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700829void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
Boris Barbulovski59e56442015-09-22 11:36:18 -0700830{
Mauro Carvalho Chehabe1f77692020-04-02 11:28:02 +0200831 QPoint p = e->pos();
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700832 ConfigItem* item = (ConfigItem*)itemAt(p);
833 struct menu *menu;
834 enum prop_type ptype;
835
836 if (!item)
837 goto skip;
838 if (item->goParent) {
839 emit parentSelected();
840 goto skip;
841 }
842 menu = item->menu;
843 if (!menu)
844 goto skip;
845 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
Mauro Carvalho Chehabb3111422020-04-02 11:28:01 +0200846 if (ptype == P_MENU) {
847 if (mode == singleMode)
848 emit itemSelected(menu);
849 else if (mode == symbolMode)
850 emit menuSelected(menu);
851 } else if (menu->sym)
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700852 changeValue(item);
853
854skip:
855 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
856 Parent::mouseDoubleClickEvent(e);
Boris Barbulovski59e56442015-09-22 11:36:18 -0700857}
858
859void ConfigList::focusInEvent(QFocusEvent *e)
860{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700861 struct menu *menu = NULL;
862
863 Parent::focusInEvent(e);
864
865 ConfigItem* item = (ConfigItem *)currentItem();
866 if (item) {
867 item->setSelected(true);
868 menu = item->menu;
869 }
870 emit gotFocus(menu);
Boris Barbulovski59e56442015-09-22 11:36:18 -0700871}
872
873void ConfigList::contextMenuEvent(QContextMenuEvent *e)
874{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700875 if (e->y() <= header()->geometry().bottom()) {
876 if (!headerPopup) {
877 QAction *action;
878
879 headerPopup = new QMenu(this);
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200880 action = new QAction("Show Name", this);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700881 action->setCheckable(true);
882 connect(action, SIGNAL(toggled(bool)),
883 parent(), SLOT(setShowName(bool)));
884 connect(parent(), SIGNAL(showNameChanged(bool)),
885 action, SLOT(setOn(bool)));
886 action->setChecked(showName);
887 headerPopup->addAction(action);
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200888 action = new QAction("Show Range", this);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700889 action->setCheckable(true);
890 connect(action, SIGNAL(toggled(bool)),
891 parent(), SLOT(setShowRange(bool)));
892 connect(parent(), SIGNAL(showRangeChanged(bool)),
893 action, SLOT(setOn(bool)));
894 action->setChecked(showRange);
895 headerPopup->addAction(action);
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200896 action = new QAction("Show Data", this);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700897 action->setCheckable(true);
898 connect(action, SIGNAL(toggled(bool)),
899 parent(), SLOT(setShowData(bool)));
900 connect(parent(), SIGNAL(showDataChanged(bool)),
901 action, SLOT(setOn(bool)));
902 action->setChecked(showData);
903 headerPopup->addAction(action);
904 }
905 headerPopup->exec(e->globalPos());
906 e->accept();
907 } else
908 e->ignore();
Boris Barbulovski59e56442015-09-22 11:36:18 -0700909}
910
Li Zefan39a48972010-05-10 16:33:41 +0800911ConfigView*ConfigView::viewList;
912QAction *ConfigView::showNormalAction;
913QAction *ConfigView::showAllAction;
914QAction *ConfigView::showPromptAction;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915
Roman Zippel7fc925f2006-06-08 22:12:46 -0700916ConfigView::ConfigView(QWidget* parent, const char *name)
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -0700917 : Parent(parent)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918{
Boris Barbulovski9bd36ed2015-09-22 11:36:22 -0700919 setObjectName(name);
Boris Barbulovski29a70162015-09-22 11:36:10 -0700920 QVBoxLayout *verticalLayout = new QVBoxLayout(this);
Boris Barbulovski92298b42015-09-22 11:36:11 -0700921 verticalLayout->setContentsMargins(0, 0, 0, 0);
Boris Barbulovski29a70162015-09-22 11:36:10 -0700922
Boris Barbulovski1019f1a2015-09-22 11:36:17 -0700923 list = new ConfigList(this);
Boris Barbulovski29a70162015-09-22 11:36:10 -0700924 verticalLayout->addWidget(list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 lineEdit = new ConfigLineEdit(this);
926 lineEdit->hide();
Boris Barbulovski29a70162015-09-22 11:36:10 -0700927 verticalLayout->addWidget(lineEdit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928
929 this->nextView = viewList;
930 viewList = this;
931}
932
933ConfigView::~ConfigView(void)
934{
935 ConfigView** vp;
936
937 for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
938 if (*vp == this) {
939 *vp = nextView;
940 break;
941 }
942 }
943}
944
Li Zefan39a48972010-05-10 16:33:41 +0800945void ConfigView::setOptionMode(QAction *act)
Roman Zippel7fc925f2006-06-08 22:12:46 -0700946{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700947 if (act == showNormalAction)
948 list->optMode = normalOpt;
949 else if (act == showAllAction)
950 list->optMode = allOpt;
951 else
952 list->optMode = promptOpt;
953
954 list->updateListAll();
Roman Zippel7fc925f2006-06-08 22:12:46 -0700955}
956
957void ConfigView::setShowName(bool b)
958{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700959 if (list->showName != b) {
960 list->showName = b;
961 list->reinit();
962 emit showNameChanged(b);
963 }
Roman Zippel7fc925f2006-06-08 22:12:46 -0700964}
965
966void ConfigView::setShowRange(bool b)
967{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700968 if (list->showRange != b) {
969 list->showRange = b;
970 list->reinit();
971 emit showRangeChanged(b);
972 }
Roman Zippel7fc925f2006-06-08 22:12:46 -0700973}
974
975void ConfigView::setShowData(bool b)
976{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700977 if (list->showData != b) {
978 list->showData = b;
979 list->reinit();
980 emit showDataChanged(b);
981 }
982}
983
984void ConfigList::setAllOpen(bool open)
985{
986 QTreeWidgetItemIterator it(this);
987
988 while (*it) {
989 (*it)->setExpanded(open);
990
991 ++it;
992 }
Roman Zippel7fc925f2006-06-08 22:12:46 -0700993}
994
Boris Barbulovski1019f1a2015-09-22 11:36:17 -0700995void ConfigView::updateList(ConfigItem* item)
Roman Zippel7fc925f2006-06-08 22:12:46 -0700996{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -0700997 ConfigView* v;
998
999 for (v = viewList; v; v = v->nextView)
1000 v->list->updateList(item);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001}
1002
1003void ConfigView::updateListAll(void)
1004{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001005 ConfigView* v;
1006
1007 for (v = viewList; v; v = v->nextView)
1008 v->list->updateListAll();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009}
1010
Roman Zippel43bf6122006-06-08 22:12:45 -07001011ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001012 : Parent(parent), sym(0), _menu(0)
Roman Zippel43bf6122006-06-08 22:12:45 -07001013{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001014 setObjectName(name);
1015
1016
1017 if (!objectName().isEmpty()) {
1018 configSettings->beginGroup(objectName());
Boris Barbulovskie0393032016-11-30 14:57:52 -08001019 setShowDebug(configSettings->value("/showDebug", false).toBool());
Roman Zippel7fc925f2006-06-08 22:12:46 -07001020 configSettings->endGroup();
1021 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1022 }
1023}
1024
1025void ConfigInfoView::saveSettings(void)
1026{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001027 if (!objectName().isEmpty()) {
1028 configSettings->beginGroup(objectName());
1029 configSettings->setValue("/showDebug", showDebug());
1030 configSettings->endGroup();
1031 }
Roman Zippel43bf6122006-06-08 22:12:45 -07001032}
1033
1034void ConfigInfoView::setShowDebug(bool b)
1035{
1036 if (_showDebug != b) {
1037 _showDebug = b;
Alexander Stein133c5f72010-08-31 17:34:37 +02001038 if (_menu)
Roman Zippel43bf6122006-06-08 22:12:45 -07001039 menuInfo();
Roman Zippelab45d192006-06-08 22:12:47 -07001040 else if (sym)
1041 symbolInfo();
Roman Zippel43bf6122006-06-08 22:12:45 -07001042 emit showDebugChanged(b);
1043 }
1044}
1045
1046void ConfigInfoView::setInfo(struct menu *m)
1047{
Alexander Stein133c5f72010-08-31 17:34:37 +02001048 if (_menu == m)
Roman Zippelb65a47e2006-06-08 22:12:47 -07001049 return;
Alexander Stein133c5f72010-08-31 17:34:37 +02001050 _menu = m;
Roman Zippel6fa1da82007-01-10 23:15:31 -08001051 sym = NULL;
Alexander Stein133c5f72010-08-31 17:34:37 +02001052 if (!_menu)
Roman Zippel43bf6122006-06-08 22:12:45 -07001053 clear();
Roman Zippel6fa1da82007-01-10 23:15:31 -08001054 else
Roman Zippel43bf6122006-06-08 22:12:45 -07001055 menuInfo();
1056}
1057
Roman Zippelab45d192006-06-08 22:12:47 -07001058void ConfigInfoView::symbolInfo(void)
1059{
1060 QString str;
1061
1062 str += "<big>Symbol: <b>";
1063 str += print_filter(sym->name);
1064 str += "</b></big><br><br>value: ";
1065 str += print_filter(sym_get_string_value(sym));
1066 str += "<br>visibility: ";
1067 str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
1068 str += "<br>";
1069 str += debug_info(sym);
1070
1071 setText(str);
1072}
1073
Roman Zippel43bf6122006-06-08 22:12:45 -07001074void ConfigInfoView::menuInfo(void)
1075{
1076 struct symbol* sym;
1077 QString head, debug, help;
1078
Alexander Stein133c5f72010-08-31 17:34:37 +02001079 sym = _menu->sym;
Roman Zippel43bf6122006-06-08 22:12:45 -07001080 if (sym) {
Alexander Stein133c5f72010-08-31 17:34:37 +02001081 if (_menu->prompt) {
Roman Zippel43bf6122006-06-08 22:12:45 -07001082 head += "<big><b>";
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001083 head += print_filter(_menu->prompt->text);
Roman Zippel43bf6122006-06-08 22:12:45 -07001084 head += "</b></big>";
1085 if (sym->name) {
1086 head += " (";
Roman Zippelab45d192006-06-08 22:12:47 -07001087 if (showDebug())
1088 head += QString().sprintf("<a href=\"s%p\">", sym);
Roman Zippel43bf6122006-06-08 22:12:45 -07001089 head += print_filter(sym->name);
Roman Zippelab45d192006-06-08 22:12:47 -07001090 if (showDebug())
1091 head += "</a>";
Roman Zippel43bf6122006-06-08 22:12:45 -07001092 head += ")";
1093 }
1094 } else if (sym->name) {
1095 head += "<big><b>";
Roman Zippelab45d192006-06-08 22:12:47 -07001096 if (showDebug())
1097 head += QString().sprintf("<a href=\"s%p\">", sym);
Roman Zippel43bf6122006-06-08 22:12:45 -07001098 head += print_filter(sym->name);
Roman Zippelab45d192006-06-08 22:12:47 -07001099 if (showDebug())
1100 head += "</a>";
Roman Zippel43bf6122006-06-08 22:12:45 -07001101 head += "</b></big>";
1102 }
1103 head += "<br><br>";
1104
1105 if (showDebug())
1106 debug = debug_info(sym);
1107
Cheng Renquand74c15f2009-07-12 16:11:47 +08001108 struct gstr help_gstr = str_new();
Alexander Stein133c5f72010-08-31 17:34:37 +02001109 menu_get_ext_help(_menu, &help_gstr);
Cheng Renquand74c15f2009-07-12 16:11:47 +08001110 help = print_filter(str_get(&help_gstr));
1111 str_free(&help_gstr);
Alexander Stein133c5f72010-08-31 17:34:37 +02001112 } else if (_menu->prompt) {
Roman Zippel43bf6122006-06-08 22:12:45 -07001113 head += "<big><b>";
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001114 head += print_filter(_menu->prompt->text);
Roman Zippel43bf6122006-06-08 22:12:45 -07001115 head += "</b></big><br><br>";
1116 if (showDebug()) {
Alexander Stein133c5f72010-08-31 17:34:37 +02001117 if (_menu->prompt->visible.expr) {
Roman Zippel43bf6122006-06-08 22:12:45 -07001118 debug += "&nbsp;&nbsp;dep: ";
Alexander Stein133c5f72010-08-31 17:34:37 +02001119 expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
Roman Zippel43bf6122006-06-08 22:12:45 -07001120 debug += "<br><br>";
1121 }
1122 }
1123 }
1124 if (showDebug())
Alexander Stein133c5f72010-08-31 17:34:37 +02001125 debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
Roman Zippel43bf6122006-06-08 22:12:45 -07001126
1127 setText(head + debug + help);
1128}
1129
1130QString ConfigInfoView::debug_info(struct symbol *sym)
1131{
1132 QString debug;
1133
1134 debug += "type: ";
1135 debug += print_filter(sym_type_name(sym->type));
1136 if (sym_is_choice(sym))
1137 debug += " (choice)";
1138 debug += "<br>";
1139 if (sym->rev_dep.expr) {
1140 debug += "reverse dep: ";
1141 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1142 debug += "<br>";
1143 }
1144 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1145 switch (prop->type) {
1146 case P_PROMPT:
1147 case P_MENU:
Roman Zippelab45d192006-06-08 22:12:47 -07001148 debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001149 debug += print_filter(prop->text);
Roman Zippelab45d192006-06-08 22:12:47 -07001150 debug += "</a><br>";
Roman Zippel43bf6122006-06-08 22:12:45 -07001151 break;
1152 case P_DEFAULT:
Roman Zippel93449082008-01-14 04:50:54 +01001153 case P_SELECT:
1154 case P_RANGE:
Roman Zippel93449082008-01-14 04:50:54 +01001155 debug += prop_get_type_name(prop->type);
1156 debug += ": ";
Roman Zippel43bf6122006-06-08 22:12:45 -07001157 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1158 debug += "<br>";
1159 break;
1160 case P_CHOICE:
1161 if (sym_is_choice(sym)) {
1162 debug += "choice: ";
1163 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1164 debug += "<br>";
1165 }
1166 break;
Roman Zippel43bf6122006-06-08 22:12:45 -07001167 default:
1168 debug += "unknown property: ";
1169 debug += prop_get_type_name(prop->type);
1170 debug += "<br>";
1171 }
1172 if (prop->visible.expr) {
1173 debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
1174 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1175 debug += "<br>";
1176 }
1177 }
1178 debug += "<br>";
1179
1180 return debug;
1181}
1182
1183QString ConfigInfoView::print_filter(const QString &str)
1184{
1185 QRegExp re("[<>&\"\\n]");
1186 QString res = str;
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001187 for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
1188 switch (res[i].toLatin1()) {
Roman Zippel43bf6122006-06-08 22:12:45 -07001189 case '<':
1190 res.replace(i, 1, "&lt;");
1191 i += 4;
1192 break;
1193 case '>':
1194 res.replace(i, 1, "&gt;");
1195 i += 4;
1196 break;
1197 case '&':
1198 res.replace(i, 1, "&amp;");
1199 i += 5;
1200 break;
1201 case '"':
1202 res.replace(i, 1, "&quot;");
1203 i += 6;
1204 break;
1205 case '\n':
1206 res.replace(i, 1, "<br>");
1207 i += 4;
1208 break;
1209 }
1210 }
1211 return res;
1212}
1213
Roman Zippelab45d192006-06-08 22:12:47 -07001214void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
Roman Zippel43bf6122006-06-08 22:12:45 -07001215{
Roman Zippelab45d192006-06-08 22:12:47 -07001216 QString* text = reinterpret_cast<QString*>(data);
1217 QString str2 = print_filter(str);
1218
1219 if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1220 *text += QString().sprintf("<a href=\"s%p\">", sym);
1221 *text += str2;
1222 *text += "</a>";
1223 } else
1224 *text += str2;
Roman Zippel43bf6122006-06-08 22:12:45 -07001225}
1226
Boris Barbulovski924bbb52015-09-22 11:36:06 -07001227QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
Roman Zippel7fc925f2006-06-08 22:12:46 -07001228{
Boris Barbulovski924bbb52015-09-22 11:36:06 -07001229 QMenu* popup = Parent::createStandardContextMenu(pos);
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001230 QAction* action = new QAction("Show Debug Info", popup);
Mauro Carvalho Chehab60969f02020-04-02 11:28:03 +02001231
1232 action->setCheckable(true);
1233 connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1234 connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
1235 action->setChecked(showDebug());
Boris Barbulovski924bbb52015-09-22 11:36:06 -07001236 popup->addSeparator();
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001237 popup->addAction(action);
Roman Zippel7fc925f2006-06-08 22:12:46 -07001238 return popup;
1239}
1240
Boris Barbulovski924bbb52015-09-22 11:36:06 -07001241void ConfigInfoView::contextMenuEvent(QContextMenuEvent *e)
Roman Zippel7fc925f2006-06-08 22:12:46 -07001242{
Boris Barbulovski924bbb52015-09-22 11:36:06 -07001243 Parent::contextMenuEvent(e);
Roman Zippel7fc925f2006-06-08 22:12:46 -07001244}
1245
Marco Costalba63431e72006-10-05 19:12:59 +02001246ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001247 : Parent(parent), result(NULL)
Roman Zippel43bf6122006-06-08 22:12:45 -07001248{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001249 setObjectName(name);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001250 setWindowTitle("Search Config");
Roman Zippel43bf6122006-06-08 22:12:45 -07001251
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001252 QVBoxLayout* layout1 = new QVBoxLayout(this);
1253 layout1->setContentsMargins(11, 11, 11, 11);
1254 layout1->setSpacing(6);
1255 QHBoxLayout* layout2 = new QHBoxLayout(0);
1256 layout2->setContentsMargins(0, 0, 0, 0);
1257 layout2->setSpacing(6);
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001258 layout2->addWidget(new QLabel("Find:", this));
Roman Zippel43bf6122006-06-08 22:12:45 -07001259 editField = new QLineEdit(this);
1260 connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1261 layout2->addWidget(editField);
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001262 searchButton = new QPushButton("Search", this);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001263 searchButton->setAutoDefault(false);
Roman Zippel43bf6122006-06-08 22:12:45 -07001264 connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1265 layout2->addWidget(searchButton);
1266 layout1->addLayout(layout2);
1267
Roman Zippel7fc925f2006-06-08 22:12:46 -07001268 split = new QSplitter(this);
Markus Heidelberg7298b932009-05-18 01:36:50 +02001269 split->setOrientation(Qt::Vertical);
Roman Zippel7fc925f2006-06-08 22:12:46 -07001270 list = new ConfigView(split, name);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001271 list->list->mode = listMode;
Roman Zippel7fc925f2006-06-08 22:12:46 -07001272 info = new ConfigInfoView(split, name);
Roman Zippel43bf6122006-06-08 22:12:45 -07001273 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1274 info, SLOT(setInfo(struct menu *)));
Marco Costalba63431e72006-10-05 19:12:59 +02001275 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1276 parent, SLOT(setMenuLink(struct menu *)));
1277
Roman Zippel43bf6122006-06-08 22:12:45 -07001278 layout1->addWidget(split);
Roman Zippel7fc925f2006-06-08 22:12:46 -07001279
1280 if (name) {
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001281 QVariant x, y;
1282 int width, height;
Roman Zippel7fc925f2006-06-08 22:12:46 -07001283 bool ok;
1284
1285 configSettings->beginGroup(name);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001286 width = configSettings->value("/window width", parent->width() / 2).toInt();
1287 height = configSettings->value("/window height", parent->height() / 2).toInt();
Roman Zippel7fc925f2006-06-08 22:12:46 -07001288 resize(width, height);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001289 x = configSettings->value("/window x");
1290 y = configSettings->value("/window y");
1291 if ((x.isValid())&&(y.isValid()))
1292 move(x.toInt(), y.toInt());
Boris Barbulovski041fbdc2015-09-22 11:36:05 -07001293 QList<int> sizes = configSettings->readSizes("/split", &ok);
Roman Zippel7fc925f2006-06-08 22:12:46 -07001294 if (ok)
1295 split->setSizes(sizes);
1296 configSettings->endGroup();
1297 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1298 }
1299}
1300
1301void ConfigSearchWindow::saveSettings(void)
1302{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001303 if (!objectName().isEmpty()) {
1304 configSettings->beginGroup(objectName());
1305 configSettings->setValue("/window x", pos().x());
1306 configSettings->setValue("/window y", pos().y());
1307 configSettings->setValue("/window width", size().width());
1308 configSettings->setValue("/window height", size().height());
1309 configSettings->writeSizes("/split", split->sizes());
1310 configSettings->endGroup();
1311 }
Roman Zippel43bf6122006-06-08 22:12:45 -07001312}
1313
1314void ConfigSearchWindow::search(void)
1315{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001316 struct symbol **p;
1317 struct property *prop;
1318 ConfigItem *lastItem = NULL;
1319
1320 free(result);
1321 list->list->clear();
1322 info->clear();
1323
1324 result = sym_re_search(editField->text().toLatin1());
1325 if (!result)
1326 return;
1327 for (p = result; *p; p++) {
1328 for_all_prompts((*p), prop)
1329 lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1330 menu_is_visible(prop->menu));
1331 }
Roman Zippel43bf6122006-06-08 22:12:45 -07001332}
1333
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334/*
1335 * Construct the complete config widget
1336 */
1337ConfigMainWindow::ConfigMainWindow(void)
Roman Zippelf12aa702006-11-25 11:09:31 -08001338 : searchWindow(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339{
1340 QMenuBar* menu;
Boris Barbulovski92119932015-09-22 11:36:16 -07001341 bool ok = true;
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001342 QVariant x, y;
1343 int width, height;
Randy Dunlapa54bb702007-10-20 11:18:47 -07001344 char title[256];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
Markus Heidelberg8d90c972009-05-18 01:36:52 +02001346 QDesktopWidget *d = configApp->desktop();
Arnaud Lacombe09548282010-08-18 01:57:13 -04001347 snprintf(title, sizeof(title), "%s%s",
1348 rootmenu.prompt->text,
Michal Marek76a136c2010-09-01 17:39:27 +02001349 ""
Michal Marek76a136c2010-09-01 17:39:27 +02001350 );
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001351 setWindowTitle(title);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001353 width = configSettings->value("/window width", d->width() - 64).toInt();
1354 height = configSettings->value("/window height", d->height() - 64).toInt();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 resize(width, height);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001356 x = configSettings->value("/window x");
1357 y = configSettings->value("/window y");
1358 if ((x.isValid())&&(y.isValid()))
1359 move(x.toInt(), y.toInt());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Mauro Carvalho Chehabcce1fab2020-04-02 11:28:00 +02001361 QWidget *widget = new QWidget(this);
1362 QVBoxLayout *layout = new QVBoxLayout(widget);
1363 setCentralWidget(widget);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
Mauro Carvalho Chehabcce1fab2020-04-02 11:28:00 +02001365 split1 = new QSplitter(widget);
1366 split1->setOrientation(Qt::Horizontal);
1367 split1->setChildrenCollapsible(false);
1368
1369 menuView = new ConfigView(widget, "menu");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 menuList = menuView->list;
1371
Mauro Carvalho Chehabcce1fab2020-04-02 11:28:00 +02001372 split2 = new QSplitter(widget);
1373 split2->setChildrenCollapsible(false);
Markus Heidelberg7298b932009-05-18 01:36:50 +02001374 split2->setOrientation(Qt::Vertical);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
1376 // create config tree
Mauro Carvalho Chehabcce1fab2020-04-02 11:28:00 +02001377 configView = new ConfigView(widget, "config");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 configList = configView->list;
1379
Mauro Carvalho Chehabcce1fab2020-04-02 11:28:00 +02001380 helpText = new ConfigInfoView(widget, "help");
1381
1382 layout->addWidget(split2);
1383 split2->addWidget(split1);
1384 split1->addWidget(configView);
1385 split1->addWidget(menuView);
1386 split2->addWidget(helpText);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
1388 setTabOrder(configList, helpText);
1389 configList->setFocus();
1390
1391 menu = menuBar();
Boris Barbulovskib1f8a452015-09-22 11:36:02 -07001392 toolBar = new QToolBar("Tools", this);
Boris Barbulovski29a70162015-09-22 11:36:10 -07001393 addToolBar(toolBar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001395 backAction = new QAction(QPixmap(xpm_back), "Back", this);
Boris Barbulovski92119932015-09-22 11:36:16 -07001396 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001397 backAction->setEnabled(false);
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001398 QAction *quitAction = new QAction("&Quit", this);
Boris Barbulovski85eaf282015-09-22 11:36:03 -07001399 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
Boris Barbulovski92119932015-09-22 11:36:16 -07001400 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001401 QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
Boris Barbulovski85eaf282015-09-22 11:36:03 -07001402 loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
Boris Barbulovski92119932015-09-22 11:36:16 -07001403 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001404 saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
Boris Barbulovski85eaf282015-09-22 11:36:03 -07001405 saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
Boris Barbulovski92119932015-09-22 11:36:16 -07001406 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
Karsten Wiese3b354c52006-12-13 00:34:08 -08001407 conf_set_changed_callback(conf_changed);
1408 // Set saveAction's initial state
1409 conf_changed();
Masahiro Yamada87419082019-03-11 01:13:15 +09001410 configname = xstrdup(conf_get_configname());
1411
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001412 QAction *saveAsAction = new QAction("Save &As...", this);
Boris Barbulovski92119932015-09-22 11:36:16 -07001413 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001414 QAction *searchAction = new QAction("&Find", this);
Boris Barbulovski85eaf282015-09-22 11:36:03 -07001415 searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
Boris Barbulovski92119932015-09-22 11:36:16 -07001416 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001417 singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001418 singleViewAction->setCheckable(true);
Boris Barbulovski92119932015-09-22 11:36:16 -07001419 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001420 splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001421 splitViewAction->setCheckable(true);
Boris Barbulovski92119932015-09-22 11:36:16 -07001422 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001423 fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001424 fullViewAction->setCheckable(true);
Boris Barbulovski92119932015-09-22 11:36:16 -07001425 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001427 QAction *showNameAction = new QAction("Show Name", this);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001428 showNameAction->setCheckable(true);
Roman Zippel7fc925f2006-06-08 22:12:46 -07001429 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
Boris Barbulovski9c862352015-09-22 11:36:12 -07001430 showNameAction->setChecked(configView->showName());
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001431 QAction *showRangeAction = new QAction("Show Range", this);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001432 showRangeAction->setCheckable(true);
Roman Zippel7fc925f2006-06-08 22:12:46 -07001433 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001434 QAction *showDataAction = new QAction("Show Data", this);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001435 showDataAction->setCheckable(true);
Roman Zippel7fc925f2006-06-08 22:12:46 -07001436 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
Li Zefan39a48972010-05-10 16:33:41 +08001437
1438 QActionGroup *optGroup = new QActionGroup(this);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001439 optGroup->setExclusive(true);
Boris Barbulovski92119932015-09-22 11:36:16 -07001440 connect(optGroup, SIGNAL(triggered(QAction*)), configView,
Li Zefan39a48972010-05-10 16:33:41 +08001441 SLOT(setOptionMode(QAction *)));
Boris Barbulovski92119932015-09-22 11:36:16 -07001442 connect(optGroup, SIGNAL(triggered(QAction *)), menuView,
Li Zefan39a48972010-05-10 16:33:41 +08001443 SLOT(setOptionMode(QAction *)));
1444
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001445 configView->showNormalAction = new QAction("Show Normal Options", optGroup);
1446 configView->showAllAction = new QAction("Show All Options", optGroup);
1447 configView->showPromptAction = new QAction("Show Prompt Options", optGroup);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001448 configView->showNormalAction->setCheckable(true);
1449 configView->showAllAction->setCheckable(true);
1450 configView->showPromptAction->setCheckable(true);
Li Zefan39a48972010-05-10 16:33:41 +08001451
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001452 QAction *showDebugAction = new QAction("Show Debug Info", this);
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001453 showDebugAction->setCheckable(true);
Roman Zippel43bf6122006-06-08 22:12:45 -07001454 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
Boris Barbulovski9c862352015-09-22 11:36:12 -07001455 showDebugAction->setChecked(helpText->showDebug());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001457 QAction *showIntroAction = new QAction("Introduction", this);
Boris Barbulovski92119932015-09-22 11:36:16 -07001458 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001459 QAction *showAboutAction = new QAction("About", this);
Boris Barbulovski92119932015-09-22 11:36:16 -07001460 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
1462 // init tool bar
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001463 toolBar->addAction(backAction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 toolBar->addSeparator();
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001465 toolBar->addAction(loadAction);
1466 toolBar->addAction(saveAction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 toolBar->addSeparator();
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001468 toolBar->addAction(singleViewAction);
1469 toolBar->addAction(splitViewAction);
1470 toolBar->addAction(fullViewAction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472 // create config menu
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001473 QMenu* config = menu->addMenu("&File");
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001474 config->addAction(loadAction);
1475 config->addAction(saveAction);
1476 config->addAction(saveAsAction);
Boris Barbulovski76bede82015-09-22 11:36:07 -07001477 config->addSeparator();
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001478 config->addAction(quitAction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479
Shlomi Fish66e7c722007-02-14 00:32:58 -08001480 // create edit menu
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001481 QMenu* editMenu = menu->addMenu("&Edit");
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001482 editMenu->addAction(searchAction);
Shlomi Fish66e7c722007-02-14 00:32:58 -08001483
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 // create options menu
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001485 QMenu* optionMenu = menu->addMenu("&Option");
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001486 optionMenu->addAction(showNameAction);
1487 optionMenu->addAction(showRangeAction);
1488 optionMenu->addAction(showDataAction);
Boris Barbulovski76bede82015-09-22 11:36:07 -07001489 optionMenu->addSeparator();
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001490 optionMenu->addActions(optGroup->actions());
Boris Barbulovski76bede82015-09-22 11:36:07 -07001491 optionMenu->addSeparator();
Boris Barbulovskie0393032016-11-30 14:57:52 -08001492 optionMenu->addAction(showDebugAction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493
1494 // create help menu
Boris Barbulovski76bede82015-09-22 11:36:07 -07001495 menu->addSeparator();
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001496 QMenu* helpMenu = menu->addMenu("&Help");
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001497 helpMenu->addAction(showIntroAction);
1498 helpMenu->addAction(showAboutAction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001500 connect(configList, SIGNAL(menuChanged(struct menu *)),
1501 helpText, SLOT(setInfo(struct menu *)));
1502 connect(configList, SIGNAL(menuSelected(struct menu *)),
1503 SLOT(changeMenu(struct menu *)));
Mauro Carvalho Chehabb3111422020-04-02 11:28:01 +02001504 connect(configList, SIGNAL(itemSelected(struct menu *)),
1505 SLOT(changeItens(struct menu *)));
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001506 connect(configList, SIGNAL(parentSelected()),
1507 SLOT(goBack()));
1508 connect(menuList, SIGNAL(menuChanged(struct menu *)),
1509 helpText, SLOT(setInfo(struct menu *)));
1510 connect(menuList, SIGNAL(menuSelected(struct menu *)),
1511 SLOT(changeMenu(struct menu *)));
1512
1513 connect(configList, SIGNAL(gotFocus(struct menu *)),
1514 helpText, SLOT(setInfo(struct menu *)));
1515 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1516 helpText, SLOT(setInfo(struct menu *)));
1517 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1518 SLOT(listFocusChanged(void)));
Roman Zippelb65a47e2006-06-08 22:12:47 -07001519 connect(helpText, SIGNAL(menuSelected(struct menu *)),
1520 SLOT(setMenuLink(struct menu *)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001522 QString listMode = configSettings->value("/listMode", "symbol").toString();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 if (listMode == "single")
1524 showSingleView();
1525 else if (listMode == "full")
1526 showFullView();
1527 else /*if (listMode == "split")*/
1528 showSplitView();
1529
1530 // UI setup done, restore splitter positions
Boris Barbulovski041fbdc2015-09-22 11:36:05 -07001531 QList<int> sizes = configSettings->readSizes("/split1", &ok);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 if (ok)
1533 split1->setSizes(sizes);
1534
Roman Zippel7fc925f2006-06-08 22:12:46 -07001535 sizes = configSettings->readSizes("/split2", &ok);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 if (ok)
1537 split2->setSizes(sizes);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538}
1539
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540void ConfigMainWindow::loadConfig(void)
1541{
Masahiro Yamada87419082019-03-11 01:13:15 +09001542 QString str;
1543 QByteArray ba;
1544 const char *name;
1545
1546 str = QFileDialog::getOpenFileName(this, "", configname);
1547 if (str.isNull())
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 return;
Masahiro Yamada87419082019-03-11 01:13:15 +09001549
1550 ba = str.toLocal8Bit();
1551 name = ba.data();
1552
1553 if (conf_read(name))
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001554 QMessageBox::information(this, "qconf", "Unable to load configuration!");
Masahiro Yamada87419082019-03-11 01:13:15 +09001555
1556 free(configname);
1557 configname = xstrdup(name);
1558
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 ConfigView::updateListAll();
1560}
1561
Michal Marekbac6aa82011-05-25 15:10:25 +02001562bool ConfigMainWindow::saveConfig(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563{
Masahiro Yamada87419082019-03-11 01:13:15 +09001564 if (conf_write(configname)) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001565 QMessageBox::information(this, "qconf", "Unable to save configuration!");
Michal Marekbac6aa82011-05-25 15:10:25 +02001566 return false;
1567 }
Masahiro Yamada00c864f2018-07-20 16:46:31 +09001568 conf_write_autoconf(0);
1569
Michal Marekbac6aa82011-05-25 15:10:25 +02001570 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571}
1572
1573void ConfigMainWindow::saveConfigAs(void)
1574{
Masahiro Yamada87419082019-03-11 01:13:15 +09001575 QString str;
1576 QByteArray ba;
1577 const char *name;
1578
1579 str = QFileDialog::getSaveFileName(this, "", configname);
1580 if (str.isNull())
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 return;
Masahiro Yamada87419082019-03-11 01:13:15 +09001582
1583 ba = str.toLocal8Bit();
1584 name = ba.data();
1585
1586 if (conf_write(name)) {
1587 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1588 }
1589 conf_write_autoconf(0);
1590
1591 free(configname);
1592 configname = xstrdup(name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593}
1594
Roman Zippel43bf6122006-06-08 22:12:45 -07001595void ConfigMainWindow::searchConfig(void)
1596{
1597 if (!searchWindow)
Roman Zippel7fc925f2006-06-08 22:12:46 -07001598 searchWindow = new ConfigSearchWindow(this, "search");
Roman Zippel43bf6122006-06-08 22:12:45 -07001599 searchWindow->show();
1600}
1601
Mauro Carvalho Chehabb3111422020-04-02 11:28:01 +02001602void ConfigMainWindow::changeItens(struct menu *menu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001604 configList->setRootMenu(menu);
Mauro Carvalho Chehabb3111422020-04-02 11:28:01 +02001605
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001606 if (configList->rootEntry->parent == &rootmenu)
1607 backAction->setEnabled(false);
1608 else
1609 backAction->setEnabled(true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610}
1611
Mauro Carvalho Chehabb3111422020-04-02 11:28:01 +02001612void ConfigMainWindow::changeMenu(struct menu *menu)
1613{
1614 menuList->setRootMenu(menu);
1615
1616 if (menuList->rootEntry->parent == &rootmenu)
1617 backAction->setEnabled(false);
1618 else
1619 backAction->setEnabled(true);
1620}
1621
Roman Zippelb65a47e2006-06-08 22:12:47 -07001622void ConfigMainWindow::setMenuLink(struct menu *menu)
1623{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001624 struct menu *parent;
1625 ConfigList* list = NULL;
1626 ConfigItem* item;
1627
1628 if (configList->menuSkip(menu))
1629 return;
1630
1631 switch (configList->mode) {
1632 case singleMode:
1633 list = configList;
1634 parent = menu_get_parent_menu(menu);
1635 if (!parent)
1636 return;
1637 list->setRootMenu(parent);
1638 break;
1639 case symbolMode:
1640 if (menu->flags & MENU_ROOT) {
1641 configList->setRootMenu(menu);
1642 configList->clearSelection();
1643 list = menuList;
1644 } else {
1645 list = configList;
1646 parent = menu_get_parent_menu(menu->parent);
1647 if (!parent)
1648 return;
1649 item = menuList->findConfigItem(parent);
1650 if (item) {
1651 item->setSelected(true);
1652 menuList->scrollToItem(item);
1653 }
1654 list->setRootMenu(parent);
1655 }
1656 break;
1657 case fullMode:
1658 list = configList;
1659 break;
1660 default:
1661 break;
1662 }
1663
1664 if (list) {
1665 item = list->findConfigItem(menu);
1666 if (item) {
1667 item->setSelected(true);
1668 list->scrollToItem(item);
1669 list->setFocus();
1670 }
1671 }
Roman Zippelb65a47e2006-06-08 22:12:47 -07001672}
1673
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674void ConfigMainWindow::listFocusChanged(void)
1675{
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001676 if (menuList->mode == menuMode)
1677 configList->clearSelection();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678}
1679
1680void ConfigMainWindow::goBack(void)
1681{
Boris Barbulovski5df9da92015-09-22 11:36:36 -07001682 ConfigItem* item, *oldSelection;
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001683
1684 configList->setParentMenu();
1685 if (configList->rootEntry == &rootmenu)
1686 backAction->setEnabled(false);
Boris Barbulovskibe596aa2015-09-22 11:36:28 -07001687
1688 if (menuList->selectedItems().count() == 0)
1689 return;
1690
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001691 item = (ConfigItem*)menuList->selectedItems().first();
Boris Barbulovski5df9da92015-09-22 11:36:36 -07001692 oldSelection = item;
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001693 while (item) {
1694 if (item->menu == configList->rootEntry) {
Boris Barbulovski5df9da92015-09-22 11:36:36 -07001695 oldSelection->setSelected(false);
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001696 item->setSelected(true);
1697 break;
1698 }
1699 item = (ConfigItem*)item->parent();
1700 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701}
1702
1703void ConfigMainWindow::showSingleView(void)
1704{
Boris Barbulovski780505e2015-09-22 11:36:13 -07001705 singleViewAction->setEnabled(false);
1706 singleViewAction->setChecked(true);
1707 splitViewAction->setEnabled(true);
1708 splitViewAction->setChecked(false);
1709 fullViewAction->setEnabled(true);
1710 fullViewAction->setChecked(false);
1711
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 menuView->hide();
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001713 menuList->setRootMenu(0);
1714 configList->mode = singleMode;
1715 if (configList->rootEntry == &rootmenu)
1716 configList->updateListAll();
1717 else
1718 configList->setRootMenu(&rootmenu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 configList->setFocus();
1720}
1721
1722void ConfigMainWindow::showSplitView(void)
1723{
Boris Barbulovski780505e2015-09-22 11:36:13 -07001724 singleViewAction->setEnabled(true);
1725 singleViewAction->setChecked(false);
1726 splitViewAction->setEnabled(false);
1727 splitViewAction->setChecked(true);
1728 fullViewAction->setEnabled(true);
1729 fullViewAction->setChecked(false);
1730
Mauro Carvalho Chehabb3111422020-04-02 11:28:01 +02001731 configList->mode = menuMode;
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001732 if (configList->rootEntry == &rootmenu)
1733 configList->updateListAll();
1734 else
1735 configList->setRootMenu(&rootmenu);
1736 configList->setAllOpen(true);
1737 configApp->processEvents();
Mauro Carvalho Chehabb3111422020-04-02 11:28:01 +02001738 menuList->mode = symbolMode;
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001739 menuList->setRootMenu(&rootmenu);
1740 menuList->setAllOpen(true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 menuView->show();
1742 menuList->setFocus();
1743}
1744
1745void ConfigMainWindow::showFullView(void)
1746{
Boris Barbulovski780505e2015-09-22 11:36:13 -07001747 singleViewAction->setEnabled(true);
1748 singleViewAction->setChecked(false);
1749 splitViewAction->setEnabled(true);
1750 splitViewAction->setChecked(false);
1751 fullViewAction->setEnabled(false);
1752 fullViewAction->setChecked(true);
1753
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 menuView->hide();
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001755 menuList->setRootMenu(0);
1756 configList->mode = fullMode;
1757 if (configList->rootEntry == &rootmenu)
1758 configList->updateListAll();
1759 else
1760 configList->setRootMenu(&rootmenu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 configList->setFocus();
1762}
1763
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764/*
1765 * ask for saving configuration before quitting
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 */
1767void ConfigMainWindow::closeEvent(QCloseEvent* e)
1768{
Karsten Wieseb3214292006-12-13 00:34:06 -08001769 if (!conf_get_changed()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 e->accept();
1771 return;
1772 }
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001773 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001775 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1776 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1777 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 switch (mb.exec()) {
1779 case QMessageBox::Yes:
Michal Marekbac6aa82011-05-25 15:10:25 +02001780 if (saveConfig())
1781 e->accept();
1782 else
1783 e->ignore();
1784 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 case QMessageBox::No:
1786 e->accept();
1787 break;
1788 case QMessageBox::Cancel:
1789 e->ignore();
1790 break;
1791 }
1792}
1793
1794void ConfigMainWindow::showIntro(void)
1795{
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001796 static const QString str = "Welcome to the qconf graphical configuration tool.\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 "For each option, a blank box indicates the feature is disabled, a check\n"
1798 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1799 "as a module. Clicking on the box will cycle through the three states.\n\n"
1800 "If you do not see an option (e.g., a device driver) that you believe\n"
1801 "should be present, try turning on Show All Options under the Options menu.\n"
1802 "Although there is no cross reference yet to help you figure out what other\n"
1803 "options must be enabled to support the option you are interested in, you can\n"
1804 "still view the help of a grayed-out option.\n\n"
1805 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001806 "which you can then match by examining other options.\n\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
1808 QMessageBox::information(this, "qconf", str);
1809}
1810
1811void ConfigMainWindow::showAbout(void)
1812{
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001813 static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
Boris Barbulovskib4ff1de2015-09-22 11:36:38 -07001814 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001815 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816
1817 QMessageBox::information(this, "qconf", str);
1818}
1819
1820void ConfigMainWindow::saveSettings(void)
1821{
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001822 configSettings->setValue("/window x", pos().x());
1823 configSettings->setValue("/window y", pos().y());
1824 configSettings->setValue("/window width", size().width());
1825 configSettings->setValue("/window height", size().height());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
1827 QString entry;
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001828 switch(configList->mode) {
1829 case singleMode :
1830 entry = "single";
1831 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832
Boris Barbulovskid5d973c2015-09-22 11:36:19 -07001833 case symbolMode :
1834 entry = "split";
1835 break;
1836
1837 case fullMode :
1838 entry = "full";
1839 break;
1840
1841 default:
1842 break;
1843 }
Boris Barbulovski68ccb7e2015-09-22 11:36:15 -07001844 configSettings->setValue("/listMode", entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
Roman Zippel7fc925f2006-06-08 22:12:46 -07001846 configSettings->writeSizes("/split1", split1->sizes());
1847 configSettings->writeSizes("/split2", split2->sizes());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848}
1849
Karsten Wiese3b354c52006-12-13 00:34:08 -08001850void ConfigMainWindow::conf_changed(void)
1851{
1852 if (saveAction)
1853 saveAction->setEnabled(conf_get_changed());
1854}
1855
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856void fixup_rootmenu(struct menu *menu)
1857{
1858 struct menu *child;
1859 static int menu_cnt = 0;
1860
1861 menu->flags |= MENU_ROOT;
1862 for (child = menu->list; child; child = child->next) {
1863 if (child->prompt && child->prompt->type == P_MENU) {
1864 menu_cnt++;
1865 fixup_rootmenu(child);
1866 menu_cnt--;
1867 } else if (!menu_cnt)
1868 fixup_rootmenu(child);
1869 }
1870}
1871
1872static const char *progname;
1873
1874static void usage(void)
1875{
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001876 printf("%s [-s] <config>\n", progname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 exit(0);
1878}
1879
1880int main(int ac, char** av)
1881{
1882 ConfigMainWindow* v;
1883 const char *name;
1884
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 progname = av[0];
1886 configApp = new QApplication(ac, av);
1887 if (ac > 1 && av[1][0] == '-') {
1888 switch (av[1][1]) {
Michal Marek0a1f00a2015-04-08 13:30:42 +02001889 case 's':
1890 conf_set_message_callback(NULL);
1891 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 case 'h':
1893 case '?':
1894 usage();
1895 }
1896 name = av[2];
1897 } else
1898 name = av[1];
1899 if (!name)
1900 usage();
1901
1902 conf_parse(name);
1903 fixup_rootmenu(&rootmenu);
1904 conf_read(NULL);
1905 //zconfdump(stdout);
1906
Roman Zippel7fc925f2006-06-08 22:12:46 -07001907 configSettings = new ConfigSettings();
1908 configSettings->beginGroup("/kconfig/qconf");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 v = new ConfigMainWindow();
1910
1911 //zconfdump(stdout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1913 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
Roman Zippel43bf6122006-06-08 22:12:45 -07001914 v->show();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 configApp->exec();
1916
Roman Zippel7fc925f2006-06-08 22:12:46 -07001917 configSettings->endGroup();
1918 delete configSettings;
Chris Bainbridge5b61c7b2016-01-08 20:44:04 +00001919 delete v;
1920 delete configApp;
Roman Zippel7fc925f2006-06-08 22:12:46 -07001921
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 return 0;
1923}