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(setChecked(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(setChecked(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(setChecked(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()));
1016 contextMenu = createStandardContextMenu();
1017 QAction *action = new QAction("Show Debug Info", contextMenu);
1019 action->setCheckable(true);
1020 connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1021 connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setChecked(bool)));
1022 action->setChecked(showDebug());
1023 contextMenu->addSeparator();
1024 contextMenu->addAction(action);
1027 void ConfigInfoView::saveSettings(void)
1029 if (!objectName().isEmpty()) {
1030 configSettings->beginGroup(objectName());
1031 configSettings->setValue("/showDebug", showDebug());
1032 configSettings->endGroup();
1036 void ConfigInfoView::setShowDebug(bool b)
1038 if (_showDebug != b) {
1044 emit showDebugChanged(b);
1048 void ConfigInfoView::setInfo(struct menu *m)
1060 void ConfigInfoView::symbolInfo(void)
1064 str += "<big>Symbol: <b>";
1065 str += print_filter(sym->name);
1066 str += "</b></big><br><br>value: ";
1067 str += print_filter(sym_get_string_value(sym));
1068 str += "<br>visibility: ";
1069 str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
1071 str += debug_info(sym);
1076 void ConfigInfoView::menuInfo(void)
1079 QString head, debug, help;
1083 if (_menu->prompt) {
1085 head += print_filter(_menu->prompt->text);
1086 head += "</b></big>";
1090 head += QString().sprintf("<a href=\"s%s\">", sym->name);
1091 head += print_filter(sym->name);
1096 } else if (sym->name) {
1099 head += QString().sprintf("<a href=\"s%s\">", sym->name);
1100 head += print_filter(sym->name);
1103 head += "</b></big>";
1108 debug = debug_info(sym);
1110 struct gstr help_gstr = str_new();
1111 menu_get_ext_help(_menu, &help_gstr);
1112 help = print_filter(str_get(&help_gstr));
1113 str_free(&help_gstr);
1114 } else if (_menu->prompt) {
1116 head += print_filter(_menu->prompt->text);
1117 head += "</b></big><br><br>";
1119 if (_menu->prompt->visible.expr) {
1120 debug += " dep: ";
1121 expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
1122 debug += "<br><br>";
1127 debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
1129 setText(head + debug + help);
1132 QString ConfigInfoView::debug_info(struct symbol *sym)
1137 debug += print_filter(sym_type_name(sym->type));
1138 if (sym_is_choice(sym))
1139 debug += " (choice)";
1141 if (sym->rev_dep.expr) {
1142 debug += "reverse dep: ";
1143 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1146 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1147 switch (prop->type) {
1150 debug += QString().sprintf("prompt: <a href=\"m%s\">", sym->name);
1151 debug += print_filter(prop->text);
1152 debug += "</a><br>";
1160 debug += prop_get_type_name(prop->type);
1162 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1166 if (sym_is_choice(sym)) {
1167 debug += "choice: ";
1168 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1173 debug += "unknown property: ";
1174 debug += prop_get_type_name(prop->type);
1177 if (prop->visible.expr) {
1178 debug += " dep: ";
1179 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1188 QString ConfigInfoView::print_filter(const QString &str)
1190 QRegExp re("[<>&\"\\n]");
1192 for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
1193 switch (res[i].toLatin1()) {
1195 res.replace(i, 1, "<");
1199 res.replace(i, 1, ">");
1203 res.replace(i, 1, "&");
1207 res.replace(i, 1, """);
1211 res.replace(i, 1, "<br>");
1219 void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
1221 QString* text = reinterpret_cast<QString*>(data);
1222 QString str2 = print_filter(str);
1224 if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1225 *text += QString().sprintf("<a href=\"s%s\">", sym->name);
1232 void ConfigInfoView::clicked(const QUrl &url)
1234 QByteArray str = url.toEncoded();
1235 const std::size_t count = str.size();
1236 char *data = new char[count + 1];
1237 struct symbol **result;
1238 struct menu *m = NULL;
1245 memcpy(data, str.constData(), count);
1248 /* Seek for exact match */
1251 result = sym_re_search(data);
1259 /* Seek for the menu which holds the symbol */
1260 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1261 if (prop->type != P_PROMPT && prop->type != P_MENU)
1268 /* Symbol is not visible as a menu */
1270 emit showDebugChanged(true);
1272 emit menuSelected(m);
1279 void ConfigInfoView::contextMenuEvent(QContextMenuEvent *event)
1281 contextMenu->popup(event->globalPos());
1285 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
1286 : Parent(parent), result(NULL)
1288 setObjectName("search");
1289 setWindowTitle("Search Config");
1291 QVBoxLayout* layout1 = new QVBoxLayout(this);
1292 layout1->setContentsMargins(11, 11, 11, 11);
1293 layout1->setSpacing(6);
1295 QHBoxLayout* layout2 = new QHBoxLayout();
1296 layout2->setContentsMargins(0, 0, 0, 0);
1297 layout2->setSpacing(6);
1298 layout2->addWidget(new QLabel("Find:", this));
1299 editField = new QLineEdit(this);
1300 connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1301 layout2->addWidget(editField);
1302 searchButton = new QPushButton("Search", this);
1303 searchButton->setAutoDefault(false);
1304 connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1305 layout2->addWidget(searchButton);
1306 layout1->addLayout(layout2);
1308 split = new QSplitter(this);
1309 split->setOrientation(Qt::Vertical);
1310 list = new ConfigView(split, "search");
1311 list->list->mode = listMode;
1312 info = new ConfigInfoView(split, "search");
1313 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1314 info, SLOT(setInfo(struct menu *)));
1315 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1316 parent, SLOT(setMenuLink(struct menu *)));
1318 layout1->addWidget(split);
1324 configSettings->beginGroup("search");
1325 width = configSettings->value("/window width", parent->width() / 2).toInt();
1326 height = configSettings->value("/window height", parent->height() / 2).toInt();
1327 resize(width, height);
1328 x = configSettings->value("/window x");
1329 y = configSettings->value("/window y");
1330 if (x.isValid() && y.isValid())
1331 move(x.toInt(), y.toInt());
1332 QList<int> sizes = configSettings->readSizes("/split", &ok);
1334 split->setSizes(sizes);
1335 configSettings->endGroup();
1336 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1339 void ConfigSearchWindow::saveSettings(void)
1341 if (!objectName().isEmpty()) {
1342 configSettings->beginGroup(objectName());
1343 configSettings->setValue("/window x", pos().x());
1344 configSettings->setValue("/window y", pos().y());
1345 configSettings->setValue("/window width", size().width());
1346 configSettings->setValue("/window height", size().height());
1347 configSettings->writeSizes("/split", split->sizes());
1348 configSettings->endGroup();
1352 void ConfigSearchWindow::search(void)
1355 struct property *prop;
1356 ConfigItem *lastItem = NULL;
1359 list->list->clear();
1362 result = sym_re_search(editField->text().toLatin1());
1365 for (p = result; *p; p++) {
1366 for_all_prompts((*p), prop)
1367 lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1368 menu_is_visible(prop->menu));
1373 * Construct the complete config widget
1375 ConfigMainWindow::ConfigMainWindow(void)
1383 QDesktopWidget *d = configApp->desktop();
1384 snprintf(title, sizeof(title), "%s%s",
1385 rootmenu.prompt->text,
1388 setWindowTitle(title);
1390 width = configSettings->value("/window width", d->width() - 64).toInt();
1391 height = configSettings->value("/window height", d->height() - 64).toInt();
1392 resize(width, height);
1393 x = configSettings->value("/window x");
1394 y = configSettings->value("/window y");
1395 if ((x.isValid())&&(y.isValid()))
1396 move(x.toInt(), y.toInt());
1399 ConfigItem::symbolYesIcon = QIcon(QPixmap(xpm_symbol_yes));
1400 ConfigItem::symbolModIcon = QIcon(QPixmap(xpm_symbol_mod));
1401 ConfigItem::symbolNoIcon = QIcon(QPixmap(xpm_symbol_no));
1402 ConfigItem::choiceYesIcon = QIcon(QPixmap(xpm_choice_yes));
1403 ConfigItem::choiceNoIcon = QIcon(QPixmap(xpm_choice_no));
1404 ConfigItem::menuIcon = QIcon(QPixmap(xpm_menu));
1405 ConfigItem::menubackIcon = QIcon(QPixmap(xpm_menuback));
1407 QWidget *widget = new QWidget(this);
1408 QVBoxLayout *layout = new QVBoxLayout(widget);
1409 setCentralWidget(widget);
1411 split1 = new QSplitter(widget);
1412 split1->setOrientation(Qt::Horizontal);
1413 split1->setChildrenCollapsible(false);
1415 menuView = new ConfigView(widget, "menu");
1416 menuList = menuView->list;
1418 split2 = new QSplitter(widget);
1419 split2->setChildrenCollapsible(false);
1420 split2->setOrientation(Qt::Vertical);
1422 // create config tree
1423 configView = new ConfigView(widget, "config");
1424 configList = configView->list;
1426 helpText = new ConfigInfoView(widget, "help");
1428 layout->addWidget(split2);
1429 split2->addWidget(split1);
1430 split1->addWidget(configView);
1431 split1->addWidget(menuView);
1432 split2->addWidget(helpText);
1434 setTabOrder(configList, helpText);
1435 configList->setFocus();
1437 backAction = new QAction(QPixmap(xpm_back), "Back", this);
1438 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
1440 QAction *quitAction = new QAction("&Quit", this);
1441 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
1442 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
1444 QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
1445 loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
1446 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
1448 saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
1449 saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
1450 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
1452 conf_set_changed_callback(conf_changed);
1454 // Set saveAction's initial state
1456 configname = xstrdup(conf_get_configname());
1458 QAction *saveAsAction = new QAction("Save &As...", this);
1459 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
1460 QAction *searchAction = new QAction("&Find", this);
1461 searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
1462 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
1463 singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
1464 singleViewAction->setCheckable(true);
1465 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
1466 splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this);
1467 splitViewAction->setCheckable(true);
1468 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
1469 fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this);
1470 fullViewAction->setCheckable(true);
1471 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
1473 QAction *showNameAction = new QAction("Show Name", this);
1474 showNameAction->setCheckable(true);
1475 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1476 showNameAction->setChecked(configView->showName());
1477 QAction *showRangeAction = new QAction("Show Range", this);
1478 showRangeAction->setCheckable(true);
1479 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1480 QAction *showDataAction = new QAction("Show Data", this);
1481 showDataAction->setCheckable(true);
1482 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1484 QActionGroup *optGroup = new QActionGroup(this);
1485 optGroup->setExclusive(true);
1486 connect(optGroup, SIGNAL(triggered(QAction*)), configList,
1487 SLOT(setOptionMode(QAction *)));
1488 connect(optGroup, SIGNAL(triggered(QAction *)), menuList,
1489 SLOT(setOptionMode(QAction *)));
1491 ConfigList::showNormalAction = new QAction("Show Normal Options", optGroup);
1492 ConfigList::showNormalAction->setCheckable(true);
1493 ConfigList::showAllAction = new QAction("Show All Options", optGroup);
1494 ConfigList::showAllAction->setCheckable(true);
1495 ConfigList::showPromptAction = new QAction("Show Prompt Options", optGroup);
1496 ConfigList::showPromptAction->setCheckable(true);
1498 QAction *showDebugAction = new QAction("Show Debug Info", this);
1499 showDebugAction->setCheckable(true);
1500 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1501 showDebugAction->setChecked(helpText->showDebug());
1503 QAction *showIntroAction = new QAction("Introduction", this);
1504 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
1505 QAction *showAboutAction = new QAction("About", this);
1506 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
1509 QToolBar *toolBar = addToolBar("Tools");
1510 toolBar->addAction(backAction);
1511 toolBar->addSeparator();
1512 toolBar->addAction(loadAction);
1513 toolBar->addAction(saveAction);
1514 toolBar->addSeparator();
1515 toolBar->addAction(singleViewAction);
1516 toolBar->addAction(splitViewAction);
1517 toolBar->addAction(fullViewAction);
1520 QMenu *menu = menuBar()->addMenu("&File");
1521 menu->addAction(loadAction);
1522 menu->addAction(saveAction);
1523 menu->addAction(saveAsAction);
1524 menu->addSeparator();
1525 menu->addAction(quitAction);
1528 menu = menuBar()->addMenu("&Edit");
1529 menu->addAction(searchAction);
1531 // create options menu
1532 menu = menuBar()->addMenu("&Option");
1533 menu->addAction(showNameAction);
1534 menu->addAction(showRangeAction);
1535 menu->addAction(showDataAction);
1536 menu->addSeparator();
1537 menu->addActions(optGroup->actions());
1538 menu->addSeparator();
1539 menu->addAction(showDebugAction);
1542 menu = menuBar()->addMenu("&Help");
1543 menu->addAction(showIntroAction);
1544 menu->addAction(showAboutAction);
1546 connect (helpText, SIGNAL (anchorClicked (const QUrl &)),
1547 helpText, SLOT (clicked (const QUrl &)) );
1549 connect(configList, SIGNAL(menuChanged(struct menu *)),
1550 helpText, SLOT(setInfo(struct menu *)));
1551 connect(configList, SIGNAL(menuSelected(struct menu *)),
1552 SLOT(changeMenu(struct menu *)));
1553 connect(configList, SIGNAL(itemSelected(struct menu *)),
1554 SLOT(changeItens(struct menu *)));
1555 connect(configList, SIGNAL(parentSelected()),
1557 connect(menuList, SIGNAL(menuChanged(struct menu *)),
1558 helpText, SLOT(setInfo(struct menu *)));
1559 connect(menuList, SIGNAL(menuSelected(struct menu *)),
1560 SLOT(changeMenu(struct menu *)));
1562 connect(configList, SIGNAL(gotFocus(struct menu *)),
1563 helpText, SLOT(setInfo(struct menu *)));
1564 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1565 helpText, SLOT(setInfo(struct menu *)));
1566 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1567 SLOT(listFocusChanged(void)));
1568 connect(helpText, SIGNAL(menuSelected(struct menu *)),
1569 SLOT(setMenuLink(struct menu *)));
1571 QString listMode = configSettings->value("/listMode", "symbol").toString();
1572 if (listMode == "single")
1574 else if (listMode == "full")
1576 else /*if (listMode == "split")*/
1579 // UI setup done, restore splitter positions
1580 QList<int> sizes = configSettings->readSizes("/split1", &ok);
1582 split1->setSizes(sizes);
1584 sizes = configSettings->readSizes("/split2", &ok);
1586 split2->setSizes(sizes);
1589 void ConfigMainWindow::loadConfig(void)
1595 str = QFileDialog::getOpenFileName(this, "", configname);
1599 ba = str.toLocal8Bit();
1602 if (conf_read(name))
1603 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1606 configname = xstrdup(name);
1608 ConfigView::updateListAll();
1611 bool ConfigMainWindow::saveConfig(void)
1613 if (conf_write(configname)) {
1614 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1617 conf_write_autoconf(0);
1622 void ConfigMainWindow::saveConfigAs(void)
1628 str = QFileDialog::getSaveFileName(this, "", configname);
1632 ba = str.toLocal8Bit();
1635 if (conf_write(name)) {
1636 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1638 conf_write_autoconf(0);
1641 configname = xstrdup(name);
1644 void ConfigMainWindow::searchConfig(void)
1647 searchWindow = new ConfigSearchWindow(this);
1648 searchWindow->show();
1651 void ConfigMainWindow::changeItens(struct menu *menu)
1653 configList->setRootMenu(menu);
1656 void ConfigMainWindow::changeMenu(struct menu *menu)
1658 menuList->setRootMenu(menu);
1661 void ConfigMainWindow::setMenuLink(struct menu *menu)
1663 struct menu *parent;
1664 ConfigList* list = NULL;
1667 if (configList->menuSkip(menu))
1670 switch (configList->mode) {
1673 parent = menu_get_parent_menu(menu);
1676 list->setRootMenu(parent);
1679 if (menu->flags & MENU_ROOT) {
1680 menuList->setRootMenu(menu);
1681 configList->clearSelection();
1684 parent = menu_get_parent_menu(menu->parent);
1688 /* Select the config view */
1689 item = configList->findConfigItem(parent);
1691 configList->setSelected(item, true);
1692 configList->scrollToItem(item);
1695 menuList->setRootMenu(parent);
1696 menuList->clearSelection();
1708 item = list->findConfigItem(menu);
1710 list->setSelected(item, true);
1711 list->scrollToItem(item);
1713 helpText->setInfo(menu);
1718 void ConfigMainWindow::listFocusChanged(void)
1720 if (menuList->mode == menuMode)
1721 configList->clearSelection();
1724 void ConfigMainWindow::goBack(void)
1726 if (configList->rootEntry == &rootmenu)
1729 configList->setParentMenu();
1732 void ConfigMainWindow::showSingleView(void)
1734 singleViewAction->setEnabled(false);
1735 singleViewAction->setChecked(true);
1736 splitViewAction->setEnabled(true);
1737 splitViewAction->setChecked(false);
1738 fullViewAction->setEnabled(true);
1739 fullViewAction->setChecked(false);
1741 backAction->setEnabled(true);
1744 menuList->setRootMenu(0);
1745 configList->mode = singleMode;
1746 if (configList->rootEntry == &rootmenu)
1747 configList->updateListAll();
1749 configList->setRootMenu(&rootmenu);
1750 configList->setFocus();
1753 void ConfigMainWindow::showSplitView(void)
1755 singleViewAction->setEnabled(true);
1756 singleViewAction->setChecked(false);
1757 splitViewAction->setEnabled(false);
1758 splitViewAction->setChecked(true);
1759 fullViewAction->setEnabled(true);
1760 fullViewAction->setChecked(false);
1762 backAction->setEnabled(false);
1764 configList->mode = menuMode;
1765 if (configList->rootEntry == &rootmenu)
1766 configList->updateListAll();
1768 configList->setRootMenu(&rootmenu);
1769 configList->setAllOpen(true);
1770 configApp->processEvents();
1771 menuList->mode = symbolMode;
1772 menuList->setRootMenu(&rootmenu);
1773 menuList->setAllOpen(true);
1775 menuList->setFocus();
1778 void ConfigMainWindow::showFullView(void)
1780 singleViewAction->setEnabled(true);
1781 singleViewAction->setChecked(false);
1782 splitViewAction->setEnabled(true);
1783 splitViewAction->setChecked(false);
1784 fullViewAction->setEnabled(false);
1785 fullViewAction->setChecked(true);
1787 backAction->setEnabled(false);
1790 menuList->setRootMenu(0);
1791 configList->mode = fullMode;
1792 if (configList->rootEntry == &rootmenu)
1793 configList->updateListAll();
1795 configList->setRootMenu(&rootmenu);
1796 configList->setFocus();
1800 * ask for saving configuration before quitting
1802 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1804 if (!conf_get_changed()) {
1808 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1809 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1810 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1811 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1812 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1813 switch (mb.exec()) {
1814 case QMessageBox::Yes:
1820 case QMessageBox::No:
1823 case QMessageBox::Cancel:
1829 void ConfigMainWindow::showIntro(void)
1831 static const QString str = "Welcome to the qconf graphical configuration tool.\n\n"
1832 "For each option, a blank box indicates the feature is disabled, a check\n"
1833 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1834 "as a module. Clicking on the box will cycle through the three states.\n\n"
1835 "If you do not see an option (e.g., a device driver) that you believe\n"
1836 "should be present, try turning on Show All Options under the Options menu.\n"
1837 "Although there is no cross reference yet to help you figure out what other\n"
1838 "options must be enabled to support the option you are interested in, you can\n"
1839 "still view the help of a grayed-out option.\n\n"
1840 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1841 "which you can then match by examining other options.\n\n";
1843 QMessageBox::information(this, "qconf", str);
1846 void ConfigMainWindow::showAbout(void)
1848 static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
1849 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
1850 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1852 QMessageBox::information(this, "qconf", str);
1855 void ConfigMainWindow::saveSettings(void)
1857 configSettings->setValue("/window x", pos().x());
1858 configSettings->setValue("/window y", pos().y());
1859 configSettings->setValue("/window width", size().width());
1860 configSettings->setValue("/window height", size().height());
1863 switch(configList->mode) {
1879 configSettings->setValue("/listMode", entry);
1881 configSettings->writeSizes("/split1", split1->sizes());
1882 configSettings->writeSizes("/split2", split2->sizes());
1885 void ConfigMainWindow::conf_changed(void)
1888 saveAction->setEnabled(conf_get_changed());
1891 void fixup_rootmenu(struct menu *menu)
1894 static int menu_cnt = 0;
1896 menu->flags |= MENU_ROOT;
1897 for (child = menu->list; child; child = child->next) {
1898 if (child->prompt && child->prompt->type == P_MENU) {
1900 fixup_rootmenu(child);
1902 } else if (!menu_cnt)
1903 fixup_rootmenu(child);
1907 static const char *progname;
1909 static void usage(void)
1911 printf("%s [-s] <config>\n", progname);
1915 int main(int ac, char** av)
1917 ConfigMainWindow* v;
1921 configApp = new QApplication(ac, av);
1922 if (ac > 1 && av[1][0] == '-') {
1925 conf_set_message_callback(NULL);
1938 fixup_rootmenu(&rootmenu);
1940 //zconfdump(stdout);
1942 configSettings = new ConfigSettings();
1943 configSettings->beginGroup("/kconfig/qconf");
1944 v = new ConfigMainWindow();
1946 //zconfdump(stdout);
1947 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1948 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1952 configSettings->endGroup();
1953 delete configSettings;