1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
4 * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>
8 #include <QApplication>
11 #include <QDesktopWidget>
12 #include <QFileDialog>
18 #include <QMessageBox>
29 static QApplication *configApp;
30 static ConfigSettings *configSettings;
32 QAction *ConfigMainWindow::saveAction;
34 ConfigSettings::ConfigSettings()
35 : QSettings("kernel.org", "qconf")
40 * Reads a list of integer values from the application settings.
42 QList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
48 QStringList entryList = value(key).toStringList();
49 QStringList::Iterator it;
51 for (it = entryList.begin(); it != entryList.end(); ++it)
52 result.push_back((*it).toInt());
63 * Writes a list of integer values to the application settings.
65 bool ConfigSettings::writeSizes(const QString& key, const QList<int>& value)
67 QStringList stringList;
68 QList<int>::ConstIterator it;
70 for (it = value.begin(); it != value.end(); ++it)
71 stringList.push_back(QString::number(*it));
72 setValue(key, stringList);
77 QIcon ConfigItem::symbolYesIcon;
78 QIcon ConfigItem::symbolModIcon;
79 QIcon ConfigItem::symbolNoIcon;
80 QIcon ConfigItem::choiceYesIcon;
81 QIcon ConfigItem::choiceNoIcon;
82 QIcon ConfigItem::menuIcon;
83 QIcon ConfigItem::menubackIcon;
87 * TODO check the value
89 void ConfigItem::okRename(int col)
94 * update the displayed of a menu entry
96 void ConfigItem::updateMenu(void)
100 struct property *prop;
107 setIcon(promptColIdx, menubackIcon);
114 prompt = menu_get_prompt(menu);
116 if (prop) switch (prop->type) {
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.
122 if (sym && list->rootEntry == menu)
124 setIcon(promptColIdx, menuIcon);
128 setIcon(promptColIdx, QIcon());
132 setIcon(promptColIdx, QIcon());
140 setText(nameColIdx, sym->name);
142 type = sym_get_type(sym);
148 if (!sym_is_changeable(sym) && list->optMode == normalOpt) {
149 setIcon(promptColIdx, QIcon());
150 setText(noColIdx, QString());
151 setText(modColIdx, QString());
152 setText(yesColIdx, QString());
155 expr = sym_get_tristate_value(sym);
158 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
159 setIcon(promptColIdx, choiceYesIcon);
161 setIcon(promptColIdx, symbolYesIcon);
162 setText(yesColIdx, "Y");
166 setIcon(promptColIdx, symbolModIcon);
167 setText(modColIdx, "M");
171 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
172 setIcon(promptColIdx, choiceNoIcon);
174 setIcon(promptColIdx, symbolNoIcon);
175 setText(noColIdx, "N");
180 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
182 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
184 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
186 setText(dataColIdx, QChar(ch));
193 data = sym_get_string_value(sym);
195 setText(dataColIdx, data);
196 if (type == S_STRING)
197 prompt = QString("%1: %2").arg(prompt).arg(data);
199 prompt = QString("(%2) %1").arg(prompt).arg(data);
202 if (!sym_has_value(sym) && visible)
205 setText(promptColIdx, prompt);
208 void ConfigItem::testUpdateMenu(bool v)
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)
222 } else if (listView()->updateAll)
228 * construct a menu entry
230 void ConfigItem::init(void)
233 ConfigList* list = listView();
234 nextItem = (ConfigItem*)menu->data;
237 if (list->mode != fullMode)
239 sym_calc_value(menu->sym);
245 * destruct a menu entry
247 ConfigItem::~ConfigItem(void)
250 ConfigItem** ip = (ConfigItem**)&menu->data;
251 for (; *ip; ip = &(*ip)->nextItem) {
260 ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
263 connect(this, SIGNAL(editingFinished()), SLOT(hide()));
266 void ConfigLineEdit::show(ConfigItem* i)
269 if (sym_get_string_value(item->menu->sym))
270 setText(sym_get_string_value(item->menu->sym));
277 void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
284 sym_set_string_value(item->menu->sym, text().toLatin1());
285 parent()->updateList();
288 Parent::keyPressEvent(e);
292 parent()->list->setFocus();
296 ConfigList::ConfigList(ConfigView* p, const char *name)
299 showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt),
300 rootEntry(0), headerPopup(0)
303 setSortingEnabled(false);
304 setRootIsDecorated(true);
306 setVerticalScrollMode(ScrollPerPixel);
307 setHorizontalScrollMode(ScrollPerPixel);
309 setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value");
311 connect(this, SIGNAL(itemSelectionChanged(void)),
312 SLOT(updateSelection(void)));
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()));
324 showColumn(promptColIdx);
329 bool ConfigList::menuSkip(struct menu *menu)
331 if (optMode == normalOpt && menu_is_visible(menu))
333 if (optMode == promptOpt && menu_has_prompt(menu))
335 if (optMode == allOpt)
340 void ConfigList::reinit(void)
342 hideColumn(dataColIdx);
343 hideColumn(yesColIdx);
344 hideColumn(modColIdx);
345 hideColumn(noColIdx);
346 hideColumn(nameColIdx);
349 showColumn(nameColIdx);
351 showColumn(noColIdx);
352 showColumn(modColIdx);
353 showColumn(yesColIdx);
356 showColumn(dataColIdx);
361 void ConfigList::setOptionMode(QAction *action)
363 if (action == showNormalAction)
365 else if (action == showAllAction)
373 void ConfigList::saveSettings(void)
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();
385 ConfigItem* ConfigList::findConfigItem(struct menu *menu)
387 ConfigItem* item = (ConfigItem*)menu->data;
389 for (; item; item = item->nextItem) {
390 if (this == item->listView())
397 void ConfigList::updateSelection(void)
402 if (selectedItems().count() == 0)
405 ConfigItem* item = (ConfigItem*)selectedItems().first();
410 emit menuChanged(menu);
413 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
414 if (mode == menuMode && type == P_MENU)
415 emit menuSelected(menu);
418 void ConfigList::updateList()
420 ConfigItem* last = 0;
424 if (mode != listMode)
426 QTreeWidgetItemIterator it(this);
429 item = (ConfigItem*)(*it);
432 item->testUpdateMenu(menu_is_visible(item->menu));
439 if (rootEntry != &rootmenu && (mode == singleMode ||
440 (mode == symbolMode && rootEntry->parent != &rootmenu))) {
441 item = (ConfigItem *)topLevelItem(0);
443 item = new ConfigItem(this, 0, true);
446 if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
447 rootEntry->sym && rootEntry->prompt) {
448 item = last ? last->nextSibling() : nullptr;
450 item = new ConfigItem(this, last, rootEntry, true);
452 item->testUpdateMenu(true);
454 updateMenuList(item, rootEntry);
456 resizeColumnToContents(0);
460 updateMenuList(rootEntry);
462 resizeColumnToContents(0);
465 void ConfigList::setValue(ConfigItem* item, tristate val)
471 sym = item->menu ? item->menu->sym : 0;
475 type = sym_get_type(sym);
479 oldval = sym_get_tristate_value(sym);
481 if (!sym_set_tristate_value(sym, val))
483 if (oldval == no && item->menu->list)
484 item->setExpanded(true);
485 parent()->updateList();
490 void ConfigList::changeValue(ConfigItem* item)
494 int type, oldexpr, newexpr;
501 if (item->menu->list)
502 item->setExpanded(!item->isExpanded());
506 type = sym_get_type(sym);
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);
518 if (oldexpr != newexpr)
519 parent()->updateList();
524 parent()->lineEdit->show(item);
529 void ConfigList::setRootMenu(struct menu *menu)
533 if (rootEntry == menu)
535 type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
542 setSelected(currentItem(), hasFocus());
543 scrollToItem(currentItem());
547 void ConfigList::setParentMenu(void)
550 struct menu *oldroot;
553 if (rootEntry == &rootmenu)
555 setRootMenu(menu_get_parent_menu(rootEntry->parent));
557 QTreeWidgetItemIterator it(this);
559 item = (ConfigItem *)(*it);
560 if (item->menu == oldroot) {
561 setCurrentItem(item);
571 * update all the children of a menu entry
572 * removes/adds the entries from the parent widget as necessary
574 * parent: either the menu list widget or a menu entry widget
575 * menu: entry to be updated
577 void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
586 while (parent->childCount() > 0)
588 delete parent->takeChild(0);
594 last = parent->firstChild();
595 if (last && !last->goParent)
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;
603 if (!(child->flags & MENU_ROOT))
607 if (child->flags & MENU_ROOT)
614 visible = menu_is_visible(child);
615 if (!menuSkip(child)) {
616 if (!child->sym && !child->list && !child->prompt)
618 if (!item || item->menu != child)
619 item = new ConfigItem(parent, last, child, visible);
621 item->testUpdateMenu(visible);
623 if (mode == fullMode || mode == menuMode || type != P_MENU)
624 updateMenuList(item, child);
626 updateMenuList(item, 0);
631 if (item && item->menu == child) {
632 last = parent->firstChild();
635 else while (last->nextSibling() != item)
636 last = last->nextSibling();
642 void ConfigList::updateMenuList(struct menu *menu)
651 while (topLevelItemCount() > 0)
653 delete takeTopLevelItem(0);
659 last = (ConfigItem *)topLevelItem(0);
660 if (last && !last->goParent)
662 for (child = menu->list; child; child = child->next) {
663 item = last ? last->nextSibling() : (ConfigItem *)topLevelItem(0);
664 type = child->prompt ? child->prompt->type : P_UNKNOWN;
668 if (!(child->flags & MENU_ROOT))
672 if (child->flags & MENU_ROOT)
679 visible = menu_is_visible(child);
680 if (!menuSkip(child)) {
681 if (!child->sym && !child->list && !child->prompt)
683 if (!item || item->menu != child)
684 item = new ConfigItem(this, last, child, visible);
686 item->testUpdateMenu(visible);
688 if (mode == fullMode || mode == menuMode || type != P_MENU)
689 updateMenuList(item, child);
691 updateMenuList(item, 0);
696 if (item && item->menu == child) {
697 last = (ConfigItem *)topLevelItem(0);
700 else while (last->nextSibling() != item)
701 last = last->nextSibling();
707 void ConfigList::keyPressEvent(QKeyEvent* ev)
709 QTreeWidgetItem* i = currentItem();
714 if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
715 emit parentSelected();
721 Parent::keyPressEvent(ev);
724 item = (ConfigItem*)i;
729 if (item->goParent) {
730 emit parentSelected();
736 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
737 if (type == P_MENU && rootEntry != menu &&
738 mode != fullMode && mode != menuMode) {
739 if (mode == menuMode)
740 emit menuSelected(menu);
742 emit itemSelected(menu);
758 Parent::keyPressEvent(ev);
764 void ConfigList::mousePressEvent(QMouseEvent* e)
766 //QPoint p(contentsToViewport(e->pos()));
767 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
768 Parent::mousePressEvent(e);
771 void ConfigList::mouseReleaseEvent(QMouseEvent* e)
774 ConfigItem* item = (ConfigItem*)itemAt(p);
776 enum prop_type ptype;
784 x = header()->offset() + p.x();
785 idx = header()->logicalIndexAt(x);
788 icon = item->icon(promptColIdx);
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();
797 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
798 if (ptype == P_MENU && rootEntry != menu &&
799 mode != fullMode && mode != menuMode &&
801 emit menuSelected(menu);
822 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
823 Parent::mouseReleaseEvent(e);
826 void ConfigList::mouseMoveEvent(QMouseEvent* e)
828 //QPoint p(contentsToViewport(e->pos()));
829 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
830 Parent::mouseMoveEvent(e);
833 void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
836 ConfigItem* item = (ConfigItem*)itemAt(p);
838 enum prop_type ptype;
842 if (item->goParent) {
843 emit parentSelected();
849 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
850 if (ptype == P_MENU && mode != listMode) {
851 if (mode == singleMode)
852 emit itemSelected(menu);
853 else if (mode == symbolMode)
854 emit menuSelected(menu);
855 } else if (menu->sym)
859 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
860 Parent::mouseDoubleClickEvent(e);
863 void ConfigList::focusInEvent(QFocusEvent *e)
865 struct menu *menu = NULL;
867 Parent::focusInEvent(e);
869 ConfigItem* item = (ConfigItem *)currentItem();
871 setSelected(item, true);
877 void ConfigList::contextMenuEvent(QContextMenuEvent *e)
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);
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);
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);
911 headerPopup->exec(e->globalPos());
915 ConfigView*ConfigView::viewList;
916 QAction *ConfigList::showNormalAction;
917 QAction *ConfigList::showAllAction;
918 QAction *ConfigList::showPromptAction;
920 ConfigView::ConfigView(QWidget* parent, const char *name)
924 QVBoxLayout *verticalLayout = new QVBoxLayout(this);
925 verticalLayout->setContentsMargins(0, 0, 0, 0);
927 list = new ConfigList(this);
928 verticalLayout->addWidget(list);
929 lineEdit = new ConfigLineEdit(this);
931 verticalLayout->addWidget(lineEdit);
933 this->nextView = viewList;
937 ConfigView::~ConfigView(void)
941 for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
949 void ConfigView::setShowName(bool b)
951 if (list->showName != b) {
954 emit showNameChanged(b);
958 void ConfigView::setShowRange(bool b)
960 if (list->showRange != b) {
963 emit showRangeChanged(b);
967 void ConfigView::setShowData(bool b)
969 if (list->showData != b) {
972 emit showDataChanged(b);
976 void ConfigList::setAllOpen(bool open)
978 QTreeWidgetItemIterator it(this);
981 (*it)->setExpanded(open);
987 void ConfigView::updateList()
991 for (v = viewList; v; v = v->nextView)
992 v->list->updateList();
995 void ConfigView::updateListAll(void)
999 for (v = viewList; v; v = v->nextView)
1000 v->list->updateListAll();
1003 ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
1004 : Parent(parent), sym(0), _menu(0)
1006 setObjectName(name);
1007 setOpenLinks(false);
1009 if (!objectName().isEmpty()) {
1010 configSettings->beginGroup(objectName());
1011 setShowDebug(configSettings->value("/showDebug", false).toBool());
1012 configSettings->endGroup();
1013 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1017 void ConfigInfoView::saveSettings(void)
1019 if (!objectName().isEmpty()) {
1020 configSettings->beginGroup(objectName());
1021 configSettings->setValue("/showDebug", showDebug());
1022 configSettings->endGroup();
1026 void ConfigInfoView::setShowDebug(bool b)
1028 if (_showDebug != b) {
1034 emit showDebugChanged(b);
1038 void ConfigInfoView::setInfo(struct menu *m)
1050 void ConfigInfoView::symbolInfo(void)
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";
1061 str += debug_info(sym);
1066 void ConfigInfoView::menuInfo(void)
1069 QString head, debug, help;
1073 if (_menu->prompt) {
1075 head += print_filter(_menu->prompt->text);
1076 head += "</b></big>";
1080 head += QString().sprintf("<a href=\"s%s\">", sym->name);
1081 head += print_filter(sym->name);
1086 } else if (sym->name) {
1089 head += QString().sprintf("<a href=\"s%s\">", sym->name);
1090 head += print_filter(sym->name);
1093 head += "</b></big>";
1098 debug = debug_info(sym);
1100 struct gstr help_gstr = str_new();
1101 menu_get_ext_help(_menu, &help_gstr);
1102 help = print_filter(str_get(&help_gstr));
1103 str_free(&help_gstr);
1104 } else if (_menu->prompt) {
1106 head += print_filter(_menu->prompt->text);
1107 head += "</b></big><br><br>";
1109 if (_menu->prompt->visible.expr) {
1110 debug += " dep: ";
1111 expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
1112 debug += "<br><br>";
1117 debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
1119 setText(head + debug + help);
1122 QString ConfigInfoView::debug_info(struct symbol *sym)
1127 debug += print_filter(sym_type_name(sym->type));
1128 if (sym_is_choice(sym))
1129 debug += " (choice)";
1131 if (sym->rev_dep.expr) {
1132 debug += "reverse dep: ";
1133 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1136 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1137 switch (prop->type) {
1140 debug += QString().sprintf("prompt: <a href=\"m%s\">", sym->name);
1141 debug += print_filter(prop->text);
1142 debug += "</a><br>";
1150 debug += prop_get_type_name(prop->type);
1152 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1156 if (sym_is_choice(sym)) {
1157 debug += "choice: ";
1158 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1163 debug += "unknown property: ";
1164 debug += prop_get_type_name(prop->type);
1167 if (prop->visible.expr) {
1168 debug += " dep: ";
1169 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1178 QString ConfigInfoView::print_filter(const QString &str)
1180 QRegExp re("[<>&\"\\n]");
1182 for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
1183 switch (res[i].toLatin1()) {
1185 res.replace(i, 1, "<");
1189 res.replace(i, 1, ">");
1193 res.replace(i, 1, "&");
1197 res.replace(i, 1, """);
1201 res.replace(i, 1, "<br>");
1209 void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
1211 QString* text = reinterpret_cast<QString*>(data);
1212 QString str2 = print_filter(str);
1214 if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1215 *text += QString().sprintf("<a href=\"s%s\">", sym->name);
1222 void ConfigInfoView::clicked(const QUrl &url)
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;
1231 qInfo() << "Clicked link is empty";
1236 memcpy(data, str.constData(), count);
1239 /* Seek for exact match */
1242 result = sym_re_search(data);
1244 qInfo() << "Clicked symbol is invalid:" << data;
1251 /* Seek for the menu which holds the symbol */
1252 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1253 if (prop->type != P_PROMPT && prop->type != P_MENU)
1260 /* Symbol is not visible as a menu */
1262 emit showDebugChanged(true);
1264 emit menuSelected(m);
1271 QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
1273 QMenu* popup = Parent::createStandardContextMenu(pos);
1274 QAction* action = new QAction("Show Debug Info", popup);
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());
1280 popup->addSeparator();
1281 popup->addAction(action);
1285 void ConfigInfoView::contextMenuEvent(QContextMenuEvent *e)
1287 Parent::contextMenuEvent(e);
1290 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
1291 : Parent(parent), result(NULL)
1293 setObjectName("search");
1294 setWindowTitle("Search Config");
1296 QVBoxLayout* layout1 = new QVBoxLayout(this);
1297 layout1->setContentsMargins(11, 11, 11, 11);
1298 layout1->setSpacing(6);
1300 QHBoxLayout* layout2 = new QHBoxLayout();
1301 layout2->setContentsMargins(0, 0, 0, 0);
1302 layout2->setSpacing(6);
1303 layout2->addWidget(new QLabel("Find:", this));
1304 editField = new QLineEdit(this);
1305 connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1306 layout2->addWidget(editField);
1307 searchButton = new QPushButton("Search", this);
1308 searchButton->setAutoDefault(false);
1309 connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1310 layout2->addWidget(searchButton);
1311 layout1->addLayout(layout2);
1313 split = new QSplitter(this);
1314 split->setOrientation(Qt::Vertical);
1315 list = new ConfigView(split, "search");
1316 list->list->mode = listMode;
1317 info = new ConfigInfoView(split, "search");
1318 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1319 info, SLOT(setInfo(struct menu *)));
1320 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1321 parent, SLOT(setMenuLink(struct menu *)));
1323 layout1->addWidget(split);
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);
1339 split->setSizes(sizes);
1340 configSettings->endGroup();
1341 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1344 void ConfigSearchWindow::saveSettings(void)
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();
1357 void ConfigSearchWindow::search(void)
1360 struct property *prop;
1361 ConfigItem *lastItem = NULL;
1364 list->list->clear();
1367 result = sym_re_search(editField->text().toLatin1());
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));
1378 * Construct the complete config widget
1380 ConfigMainWindow::ConfigMainWindow(void)
1388 QDesktopWidget *d = configApp->desktop();
1389 snprintf(title, sizeof(title), "%s%s",
1390 rootmenu.prompt->text,
1393 setWindowTitle(title);
1395 width = configSettings->value("/window width", d->width() - 64).toInt();
1396 height = configSettings->value("/window height", d->height() - 64).toInt();
1397 resize(width, height);
1398 x = configSettings->value("/window x");
1399 y = configSettings->value("/window y");
1400 if ((x.isValid())&&(y.isValid()))
1401 move(x.toInt(), y.toInt());
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));
1412 QWidget *widget = new QWidget(this);
1413 QVBoxLayout *layout = new QVBoxLayout(widget);
1414 setCentralWidget(widget);
1416 split1 = new QSplitter(widget);
1417 split1->setOrientation(Qt::Horizontal);
1418 split1->setChildrenCollapsible(false);
1420 menuView = new ConfigView(widget, "menu");
1421 menuList = menuView->list;
1423 split2 = new QSplitter(widget);
1424 split2->setChildrenCollapsible(false);
1425 split2->setOrientation(Qt::Vertical);
1427 // create config tree
1428 configView = new ConfigView(widget, "config");
1429 configList = configView->list;
1431 helpText = new ConfigInfoView(widget, "help");
1433 layout->addWidget(split2);
1434 split2->addWidget(split1);
1435 split1->addWidget(configView);
1436 split1->addWidget(menuView);
1437 split2->addWidget(helpText);
1439 setTabOrder(configList, helpText);
1440 configList->setFocus();
1442 backAction = new QAction(QPixmap(xpm_back), "Back", this);
1443 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
1445 QAction *quitAction = new QAction("&Quit", this);
1446 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
1447 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
1449 QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
1450 loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
1451 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
1453 saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
1454 saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
1455 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
1457 conf_set_changed_callback(conf_changed);
1459 // Set saveAction's initial state
1461 configname = xstrdup(conf_get_configname());
1463 QAction *saveAsAction = new QAction("Save &As...", this);
1464 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
1465 QAction *searchAction = new QAction("&Find", this);
1466 searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
1467 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
1468 singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
1469 singleViewAction->setCheckable(true);
1470 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
1471 splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this);
1472 splitViewAction->setCheckable(true);
1473 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
1474 fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this);
1475 fullViewAction->setCheckable(true);
1476 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
1478 QAction *showNameAction = new QAction("Show Name", this);
1479 showNameAction->setCheckable(true);
1480 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1481 showNameAction->setChecked(configView->showName());
1482 QAction *showRangeAction = new QAction("Show Range", this);
1483 showRangeAction->setCheckable(true);
1484 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1485 QAction *showDataAction = new QAction("Show Data", this);
1486 showDataAction->setCheckable(true);
1487 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1489 QActionGroup *optGroup = new QActionGroup(this);
1490 optGroup->setExclusive(true);
1491 connect(optGroup, SIGNAL(triggered(QAction*)), configList,
1492 SLOT(setOptionMode(QAction *)));
1493 connect(optGroup, SIGNAL(triggered(QAction *)), menuList,
1494 SLOT(setOptionMode(QAction *)));
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);
1503 QAction *showDebugAction = new QAction("Show Debug Info", this);
1504 showDebugAction->setCheckable(true);
1505 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1506 showDebugAction->setChecked(helpText->showDebug());
1508 QAction *showIntroAction = new QAction("Introduction", this);
1509 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
1510 QAction *showAboutAction = new QAction("About", this);
1511 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
1514 QToolBar *toolBar = addToolBar("Tools");
1515 toolBar->addAction(backAction);
1516 toolBar->addSeparator();
1517 toolBar->addAction(loadAction);
1518 toolBar->addAction(saveAction);
1519 toolBar->addSeparator();
1520 toolBar->addAction(singleViewAction);
1521 toolBar->addAction(splitViewAction);
1522 toolBar->addAction(fullViewAction);
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);
1533 menu = menuBar()->addMenu("&Edit");
1534 menu->addAction(searchAction);
1536 // create options menu
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);
1547 menu = menuBar()->addMenu("&Help");
1548 menu->addAction(showIntroAction);
1549 menu->addAction(showAboutAction);
1551 connect (helpText, SIGNAL (anchorClicked (const QUrl &)),
1552 helpText, SLOT (clicked (const QUrl &)) );
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 *)));
1558 connect(configList, SIGNAL(itemSelected(struct menu *)),
1559 SLOT(changeItens(struct menu *)));
1560 connect(configList, SIGNAL(parentSelected()),
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 *)));
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)));
1573 connect(helpText, SIGNAL(menuSelected(struct menu *)),
1574 SLOT(setMenuLink(struct menu *)));
1576 QString listMode = configSettings->value("/listMode", "symbol").toString();
1577 if (listMode == "single")
1579 else if (listMode == "full")
1581 else /*if (listMode == "split")*/
1584 // UI setup done, restore splitter positions
1585 QList<int> sizes = configSettings->readSizes("/split1", &ok);
1587 split1->setSizes(sizes);
1589 sizes = configSettings->readSizes("/split2", &ok);
1591 split2->setSizes(sizes);
1594 void ConfigMainWindow::loadConfig(void)
1600 str = QFileDialog::getOpenFileName(this, "", configname);
1604 ba = str.toLocal8Bit();
1607 if (conf_read(name))
1608 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1611 configname = xstrdup(name);
1613 ConfigView::updateListAll();
1616 bool ConfigMainWindow::saveConfig(void)
1618 if (conf_write(configname)) {
1619 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1622 conf_write_autoconf(0);
1627 void ConfigMainWindow::saveConfigAs(void)
1633 str = QFileDialog::getSaveFileName(this, "", configname);
1637 ba = str.toLocal8Bit();
1640 if (conf_write(name)) {
1641 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1643 conf_write_autoconf(0);
1646 configname = xstrdup(name);
1649 void ConfigMainWindow::searchConfig(void)
1652 searchWindow = new ConfigSearchWindow(this);
1653 searchWindow->show();
1656 void ConfigMainWindow::changeItens(struct menu *menu)
1658 configList->setRootMenu(menu);
1661 void ConfigMainWindow::changeMenu(struct menu *menu)
1663 menuList->setRootMenu(menu);
1666 void ConfigMainWindow::setMenuLink(struct menu *menu)
1668 struct menu *parent;
1669 ConfigList* list = NULL;
1672 if (configList->menuSkip(menu))
1675 switch (configList->mode) {
1678 parent = menu_get_parent_menu(menu);
1681 list->setRootMenu(parent);
1684 if (menu->flags & MENU_ROOT) {
1685 menuList->setRootMenu(menu);
1686 configList->clearSelection();
1689 parent = menu_get_parent_menu(menu->parent);
1693 /* Select the config view */
1694 item = configList->findConfigItem(parent);
1696 configList->setSelected(item, true);
1697 configList->scrollToItem(item);
1700 menuList->setRootMenu(parent);
1701 menuList->clearSelection();
1713 item = list->findConfigItem(menu);
1715 list->setSelected(item, true);
1716 list->scrollToItem(item);
1718 helpText->setInfo(menu);
1723 void ConfigMainWindow::listFocusChanged(void)
1725 if (menuList->mode == menuMode)
1726 configList->clearSelection();
1729 void ConfigMainWindow::goBack(void)
1731 if (configList->rootEntry == &rootmenu)
1734 configList->setParentMenu();
1737 void ConfigMainWindow::showSingleView(void)
1739 singleViewAction->setEnabled(false);
1740 singleViewAction->setChecked(true);
1741 splitViewAction->setEnabled(true);
1742 splitViewAction->setChecked(false);
1743 fullViewAction->setEnabled(true);
1744 fullViewAction->setChecked(false);
1746 backAction->setEnabled(true);
1749 menuList->setRootMenu(0);
1750 configList->mode = singleMode;
1751 if (configList->rootEntry == &rootmenu)
1752 configList->updateListAll();
1754 configList->setRootMenu(&rootmenu);
1755 configList->setFocus();
1758 void ConfigMainWindow::showSplitView(void)
1760 singleViewAction->setEnabled(true);
1761 singleViewAction->setChecked(false);
1762 splitViewAction->setEnabled(false);
1763 splitViewAction->setChecked(true);
1764 fullViewAction->setEnabled(true);
1765 fullViewAction->setChecked(false);
1767 backAction->setEnabled(false);
1769 configList->mode = menuMode;
1770 if (configList->rootEntry == &rootmenu)
1771 configList->updateListAll();
1773 configList->setRootMenu(&rootmenu);
1774 configList->setAllOpen(true);
1775 configApp->processEvents();
1776 menuList->mode = symbolMode;
1777 menuList->setRootMenu(&rootmenu);
1778 menuList->setAllOpen(true);
1780 menuList->setFocus();
1783 void ConfigMainWindow::showFullView(void)
1785 singleViewAction->setEnabled(true);
1786 singleViewAction->setChecked(false);
1787 splitViewAction->setEnabled(true);
1788 splitViewAction->setChecked(false);
1789 fullViewAction->setEnabled(false);
1790 fullViewAction->setChecked(true);
1792 backAction->setEnabled(false);
1795 menuList->setRootMenu(0);
1796 configList->mode = fullMode;
1797 if (configList->rootEntry == &rootmenu)
1798 configList->updateListAll();
1800 configList->setRootMenu(&rootmenu);
1801 configList->setFocus();
1805 * ask for saving configuration before quitting
1807 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1809 if (!conf_get_changed()) {
1813 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1814 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1815 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1816 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1817 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1818 switch (mb.exec()) {
1819 case QMessageBox::Yes:
1825 case QMessageBox::No:
1828 case QMessageBox::Cancel:
1834 void ConfigMainWindow::showIntro(void)
1836 static const QString str = "Welcome to the qconf graphical configuration tool.\n\n"
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"
1846 "which you can then match by examining other options.\n\n";
1848 QMessageBox::information(this, "qconf", str);
1851 void ConfigMainWindow::showAbout(void)
1853 static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
1854 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
1855 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1857 QMessageBox::information(this, "qconf", str);
1860 void ConfigMainWindow::saveSettings(void)
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());
1868 switch(configList->mode) {
1884 configSettings->setValue("/listMode", entry);
1886 configSettings->writeSizes("/split1", split1->sizes());
1887 configSettings->writeSizes("/split2", split2->sizes());
1890 void ConfigMainWindow::conf_changed(void)
1893 saveAction->setEnabled(conf_get_changed());
1896 void fixup_rootmenu(struct menu *menu)
1899 static int menu_cnt = 0;
1901 menu->flags |= MENU_ROOT;
1902 for (child = menu->list; child; child = child->next) {
1903 if (child->prompt && child->prompt->type == P_MENU) {
1905 fixup_rootmenu(child);
1907 } else if (!menu_cnt)
1908 fixup_rootmenu(child);
1912 static const char *progname;
1914 static void usage(void)
1916 printf("%s [-s] <config>\n", progname);
1920 int main(int ac, char** av)
1922 ConfigMainWindow* v;
1926 configApp = new QApplication(ac, av);
1927 if (ac > 1 && av[1][0] == '-') {
1930 conf_set_message_callback(NULL);
1943 fixup_rootmenu(&rootmenu);
1945 //zconfdump(stdout);
1947 configSettings = new ConfigSettings();
1948 configSettings->beginGroup("/kconfig/qconf");
1949 v = new ConfigMainWindow();
1951 //zconfdump(stdout);
1952 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1953 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1957 configSettings->endGroup();
1958 delete configSettings;