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;
1241 qInfo() << "Clicked link is empty";
1246 memcpy(data, str.constData(), count);
1249 /* Seek for exact match */
1252 result = sym_re_search(data);
1254 qInfo() << "Clicked symbol is invalid:" << data;
1261 /* Seek for the menu which holds the symbol */
1262 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1263 if (prop->type != P_PROMPT && prop->type != P_MENU)
1270 /* Symbol is not visible as a menu */
1272 emit showDebugChanged(true);
1274 emit menuSelected(m);
1281 void ConfigInfoView::contextMenuEvent(QContextMenuEvent *event)
1283 contextMenu->popup(event->globalPos());
1287 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
1288 : Parent(parent), result(NULL)
1290 setObjectName("search");
1291 setWindowTitle("Search Config");
1293 QVBoxLayout* layout1 = new QVBoxLayout(this);
1294 layout1->setContentsMargins(11, 11, 11, 11);
1295 layout1->setSpacing(6);
1297 QHBoxLayout* layout2 = new QHBoxLayout();
1298 layout2->setContentsMargins(0, 0, 0, 0);
1299 layout2->setSpacing(6);
1300 layout2->addWidget(new QLabel("Find:", this));
1301 editField = new QLineEdit(this);
1302 connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1303 layout2->addWidget(editField);
1304 searchButton = new QPushButton("Search", this);
1305 searchButton->setAutoDefault(false);
1306 connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1307 layout2->addWidget(searchButton);
1308 layout1->addLayout(layout2);
1310 split = new QSplitter(this);
1311 split->setOrientation(Qt::Vertical);
1312 list = new ConfigView(split, "search");
1313 list->list->mode = listMode;
1314 info = new ConfigInfoView(split, "search");
1315 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1316 info, SLOT(setInfo(struct menu *)));
1317 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1318 parent, SLOT(setMenuLink(struct menu *)));
1320 layout1->addWidget(split);
1326 configSettings->beginGroup("search");
1327 width = configSettings->value("/window width", parent->width() / 2).toInt();
1328 height = configSettings->value("/window height", parent->height() / 2).toInt();
1329 resize(width, height);
1330 x = configSettings->value("/window x");
1331 y = configSettings->value("/window y");
1332 if (x.isValid() && y.isValid())
1333 move(x.toInt(), y.toInt());
1334 QList<int> sizes = configSettings->readSizes("/split", &ok);
1336 split->setSizes(sizes);
1337 configSettings->endGroup();
1338 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1341 void ConfigSearchWindow::saveSettings(void)
1343 if (!objectName().isEmpty()) {
1344 configSettings->beginGroup(objectName());
1345 configSettings->setValue("/window x", pos().x());
1346 configSettings->setValue("/window y", pos().y());
1347 configSettings->setValue("/window width", size().width());
1348 configSettings->setValue("/window height", size().height());
1349 configSettings->writeSizes("/split", split->sizes());
1350 configSettings->endGroup();
1354 void ConfigSearchWindow::search(void)
1357 struct property *prop;
1358 ConfigItem *lastItem = NULL;
1361 list->list->clear();
1364 result = sym_re_search(editField->text().toLatin1());
1367 for (p = result; *p; p++) {
1368 for_all_prompts((*p), prop)
1369 lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1370 menu_is_visible(prop->menu));
1375 * Construct the complete config widget
1377 ConfigMainWindow::ConfigMainWindow(void)
1385 QDesktopWidget *d = configApp->desktop();
1386 snprintf(title, sizeof(title), "%s%s",
1387 rootmenu.prompt->text,
1390 setWindowTitle(title);
1392 width = configSettings->value("/window width", d->width() - 64).toInt();
1393 height = configSettings->value("/window height", d->height() - 64).toInt();
1394 resize(width, height);
1395 x = configSettings->value("/window x");
1396 y = configSettings->value("/window y");
1397 if ((x.isValid())&&(y.isValid()))
1398 move(x.toInt(), y.toInt());
1401 ConfigItem::symbolYesIcon = QIcon(QPixmap(xpm_symbol_yes));
1402 ConfigItem::symbolModIcon = QIcon(QPixmap(xpm_symbol_mod));
1403 ConfigItem::symbolNoIcon = QIcon(QPixmap(xpm_symbol_no));
1404 ConfigItem::choiceYesIcon = QIcon(QPixmap(xpm_choice_yes));
1405 ConfigItem::choiceNoIcon = QIcon(QPixmap(xpm_choice_no));
1406 ConfigItem::menuIcon = QIcon(QPixmap(xpm_menu));
1407 ConfigItem::menubackIcon = QIcon(QPixmap(xpm_menuback));
1409 QWidget *widget = new QWidget(this);
1410 QVBoxLayout *layout = new QVBoxLayout(widget);
1411 setCentralWidget(widget);
1413 split1 = new QSplitter(widget);
1414 split1->setOrientation(Qt::Horizontal);
1415 split1->setChildrenCollapsible(false);
1417 menuView = new ConfigView(widget, "menu");
1418 menuList = menuView->list;
1420 split2 = new QSplitter(widget);
1421 split2->setChildrenCollapsible(false);
1422 split2->setOrientation(Qt::Vertical);
1424 // create config tree
1425 configView = new ConfigView(widget, "config");
1426 configList = configView->list;
1428 helpText = new ConfigInfoView(widget, "help");
1430 layout->addWidget(split2);
1431 split2->addWidget(split1);
1432 split1->addWidget(configView);
1433 split1->addWidget(menuView);
1434 split2->addWidget(helpText);
1436 setTabOrder(configList, helpText);
1437 configList->setFocus();
1439 backAction = new QAction(QPixmap(xpm_back), "Back", this);
1440 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
1442 QAction *quitAction = new QAction("&Quit", this);
1443 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
1444 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
1446 QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
1447 loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
1448 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
1450 saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
1451 saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
1452 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
1454 conf_set_changed_callback(conf_changed);
1456 // Set saveAction's initial state
1458 configname = xstrdup(conf_get_configname());
1460 QAction *saveAsAction = new QAction("Save &As...", this);
1461 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
1462 QAction *searchAction = new QAction("&Find", this);
1463 searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
1464 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
1465 singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
1466 singleViewAction->setCheckable(true);
1467 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
1468 splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this);
1469 splitViewAction->setCheckable(true);
1470 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
1471 fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this);
1472 fullViewAction->setCheckable(true);
1473 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
1475 QAction *showNameAction = new QAction("Show Name", this);
1476 showNameAction->setCheckable(true);
1477 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1478 showNameAction->setChecked(configView->showName());
1479 QAction *showRangeAction = new QAction("Show Range", this);
1480 showRangeAction->setCheckable(true);
1481 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1482 QAction *showDataAction = new QAction("Show Data", this);
1483 showDataAction->setCheckable(true);
1484 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1486 QActionGroup *optGroup = new QActionGroup(this);
1487 optGroup->setExclusive(true);
1488 connect(optGroup, SIGNAL(triggered(QAction*)), configList,
1489 SLOT(setOptionMode(QAction *)));
1490 connect(optGroup, SIGNAL(triggered(QAction *)), menuList,
1491 SLOT(setOptionMode(QAction *)));
1493 ConfigList::showNormalAction = new QAction("Show Normal Options", optGroup);
1494 ConfigList::showNormalAction->setCheckable(true);
1495 ConfigList::showAllAction = new QAction("Show All Options", optGroup);
1496 ConfigList::showAllAction->setCheckable(true);
1497 ConfigList::showPromptAction = new QAction("Show Prompt Options", optGroup);
1498 ConfigList::showPromptAction->setCheckable(true);
1500 QAction *showDebugAction = new QAction("Show Debug Info", this);
1501 showDebugAction->setCheckable(true);
1502 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1503 showDebugAction->setChecked(helpText->showDebug());
1505 QAction *showIntroAction = new QAction("Introduction", this);
1506 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
1507 QAction *showAboutAction = new QAction("About", this);
1508 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
1511 QToolBar *toolBar = addToolBar("Tools");
1512 toolBar->addAction(backAction);
1513 toolBar->addSeparator();
1514 toolBar->addAction(loadAction);
1515 toolBar->addAction(saveAction);
1516 toolBar->addSeparator();
1517 toolBar->addAction(singleViewAction);
1518 toolBar->addAction(splitViewAction);
1519 toolBar->addAction(fullViewAction);
1522 QMenu *menu = menuBar()->addMenu("&File");
1523 menu->addAction(loadAction);
1524 menu->addAction(saveAction);
1525 menu->addAction(saveAsAction);
1526 menu->addSeparator();
1527 menu->addAction(quitAction);
1530 menu = menuBar()->addMenu("&Edit");
1531 menu->addAction(searchAction);
1533 // create options menu
1534 menu = menuBar()->addMenu("&Option");
1535 menu->addAction(showNameAction);
1536 menu->addAction(showRangeAction);
1537 menu->addAction(showDataAction);
1538 menu->addSeparator();
1539 menu->addActions(optGroup->actions());
1540 menu->addSeparator();
1541 menu->addAction(showDebugAction);
1544 menu = menuBar()->addMenu("&Help");
1545 menu->addAction(showIntroAction);
1546 menu->addAction(showAboutAction);
1548 connect (helpText, SIGNAL (anchorClicked (const QUrl &)),
1549 helpText, SLOT (clicked (const QUrl &)) );
1551 connect(configList, SIGNAL(menuChanged(struct menu *)),
1552 helpText, SLOT(setInfo(struct menu *)));
1553 connect(configList, SIGNAL(menuSelected(struct menu *)),
1554 SLOT(changeMenu(struct menu *)));
1555 connect(configList, SIGNAL(itemSelected(struct menu *)),
1556 SLOT(changeItens(struct menu *)));
1557 connect(configList, SIGNAL(parentSelected()),
1559 connect(menuList, SIGNAL(menuChanged(struct menu *)),
1560 helpText, SLOT(setInfo(struct menu *)));
1561 connect(menuList, SIGNAL(menuSelected(struct menu *)),
1562 SLOT(changeMenu(struct menu *)));
1564 connect(configList, SIGNAL(gotFocus(struct menu *)),
1565 helpText, SLOT(setInfo(struct menu *)));
1566 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1567 helpText, SLOT(setInfo(struct menu *)));
1568 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1569 SLOT(listFocusChanged(void)));
1570 connect(helpText, SIGNAL(menuSelected(struct menu *)),
1571 SLOT(setMenuLink(struct menu *)));
1573 QString listMode = configSettings->value("/listMode", "symbol").toString();
1574 if (listMode == "single")
1576 else if (listMode == "full")
1578 else /*if (listMode == "split")*/
1581 // UI setup done, restore splitter positions
1582 QList<int> sizes = configSettings->readSizes("/split1", &ok);
1584 split1->setSizes(sizes);
1586 sizes = configSettings->readSizes("/split2", &ok);
1588 split2->setSizes(sizes);
1591 void ConfigMainWindow::loadConfig(void)
1597 str = QFileDialog::getOpenFileName(this, "", configname);
1601 ba = str.toLocal8Bit();
1604 if (conf_read(name))
1605 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1608 configname = xstrdup(name);
1610 ConfigView::updateListAll();
1613 bool ConfigMainWindow::saveConfig(void)
1615 if (conf_write(configname)) {
1616 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1619 conf_write_autoconf(0);
1624 void ConfigMainWindow::saveConfigAs(void)
1630 str = QFileDialog::getSaveFileName(this, "", configname);
1634 ba = str.toLocal8Bit();
1637 if (conf_write(name)) {
1638 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1640 conf_write_autoconf(0);
1643 configname = xstrdup(name);
1646 void ConfigMainWindow::searchConfig(void)
1649 searchWindow = new ConfigSearchWindow(this);
1650 searchWindow->show();
1653 void ConfigMainWindow::changeItens(struct menu *menu)
1655 configList->setRootMenu(menu);
1658 void ConfigMainWindow::changeMenu(struct menu *menu)
1660 menuList->setRootMenu(menu);
1663 void ConfigMainWindow::setMenuLink(struct menu *menu)
1665 struct menu *parent;
1666 ConfigList* list = NULL;
1669 if (configList->menuSkip(menu))
1672 switch (configList->mode) {
1675 parent = menu_get_parent_menu(menu);
1678 list->setRootMenu(parent);
1681 if (menu->flags & MENU_ROOT) {
1682 menuList->setRootMenu(menu);
1683 configList->clearSelection();
1686 parent = menu_get_parent_menu(menu->parent);
1690 /* Select the config view */
1691 item = configList->findConfigItem(parent);
1693 configList->setSelected(item, true);
1694 configList->scrollToItem(item);
1697 menuList->setRootMenu(parent);
1698 menuList->clearSelection();
1710 item = list->findConfigItem(menu);
1712 list->setSelected(item, true);
1713 list->scrollToItem(item);
1715 helpText->setInfo(menu);
1720 void ConfigMainWindow::listFocusChanged(void)
1722 if (menuList->mode == menuMode)
1723 configList->clearSelection();
1726 void ConfigMainWindow::goBack(void)
1728 if (configList->rootEntry == &rootmenu)
1731 configList->setParentMenu();
1734 void ConfigMainWindow::showSingleView(void)
1736 singleViewAction->setEnabled(false);
1737 singleViewAction->setChecked(true);
1738 splitViewAction->setEnabled(true);
1739 splitViewAction->setChecked(false);
1740 fullViewAction->setEnabled(true);
1741 fullViewAction->setChecked(false);
1743 backAction->setEnabled(true);
1746 menuList->setRootMenu(0);
1747 configList->mode = singleMode;
1748 if (configList->rootEntry == &rootmenu)
1749 configList->updateListAll();
1751 configList->setRootMenu(&rootmenu);
1752 configList->setFocus();
1755 void ConfigMainWindow::showSplitView(void)
1757 singleViewAction->setEnabled(true);
1758 singleViewAction->setChecked(false);
1759 splitViewAction->setEnabled(false);
1760 splitViewAction->setChecked(true);
1761 fullViewAction->setEnabled(true);
1762 fullViewAction->setChecked(false);
1764 backAction->setEnabled(false);
1766 configList->mode = menuMode;
1767 if (configList->rootEntry == &rootmenu)
1768 configList->updateListAll();
1770 configList->setRootMenu(&rootmenu);
1771 configList->setAllOpen(true);
1772 configApp->processEvents();
1773 menuList->mode = symbolMode;
1774 menuList->setRootMenu(&rootmenu);
1775 menuList->setAllOpen(true);
1777 menuList->setFocus();
1780 void ConfigMainWindow::showFullView(void)
1782 singleViewAction->setEnabled(true);
1783 singleViewAction->setChecked(false);
1784 splitViewAction->setEnabled(true);
1785 splitViewAction->setChecked(false);
1786 fullViewAction->setEnabled(false);
1787 fullViewAction->setChecked(true);
1789 backAction->setEnabled(false);
1792 menuList->setRootMenu(0);
1793 configList->mode = fullMode;
1794 if (configList->rootEntry == &rootmenu)
1795 configList->updateListAll();
1797 configList->setRootMenu(&rootmenu);
1798 configList->setFocus();
1802 * ask for saving configuration before quitting
1804 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1806 if (!conf_get_changed()) {
1810 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1811 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1812 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1813 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1814 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1815 switch (mb.exec()) {
1816 case QMessageBox::Yes:
1822 case QMessageBox::No:
1825 case QMessageBox::Cancel:
1831 void ConfigMainWindow::showIntro(void)
1833 static const QString str = "Welcome to the qconf graphical configuration tool.\n\n"
1834 "For each option, a blank box indicates the feature is disabled, a check\n"
1835 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1836 "as a module. Clicking on the box will cycle through the three states.\n\n"
1837 "If you do not see an option (e.g., a device driver) that you believe\n"
1838 "should be present, try turning on Show All Options under the Options menu.\n"
1839 "Although there is no cross reference yet to help you figure out what other\n"
1840 "options must be enabled to support the option you are interested in, you can\n"
1841 "still view the help of a grayed-out option.\n\n"
1842 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1843 "which you can then match by examining other options.\n\n";
1845 QMessageBox::information(this, "qconf", str);
1848 void ConfigMainWindow::showAbout(void)
1850 static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
1851 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
1852 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1854 QMessageBox::information(this, "qconf", str);
1857 void ConfigMainWindow::saveSettings(void)
1859 configSettings->setValue("/window x", pos().x());
1860 configSettings->setValue("/window y", pos().y());
1861 configSettings->setValue("/window width", size().width());
1862 configSettings->setValue("/window height", size().height());
1865 switch(configList->mode) {
1881 configSettings->setValue("/listMode", entry);
1883 configSettings->writeSizes("/split1", split1->sizes());
1884 configSettings->writeSizes("/split2", split2->sizes());
1887 void ConfigMainWindow::conf_changed(void)
1890 saveAction->setEnabled(conf_get_changed());
1893 void fixup_rootmenu(struct menu *menu)
1896 static int menu_cnt = 0;
1898 menu->flags |= MENU_ROOT;
1899 for (child = menu->list; child; child = child->next) {
1900 if (child->prompt && child->prompt->type == P_MENU) {
1902 fixup_rootmenu(child);
1904 } else if (!menu_cnt)
1905 fixup_rootmenu(child);
1909 static const char *progname;
1911 static void usage(void)
1913 printf("%s [-s] <config>\n", progname);
1917 int main(int ac, char** av)
1919 ConfigMainWindow* v;
1923 configApp = new QApplication(ac, av);
1924 if (ac > 1 && av[1][0] == '-') {
1927 conf_set_message_callback(NULL);
1940 fixup_rootmenu(&rootmenu);
1942 //zconfdump(stdout);
1944 configSettings = new ConfigSettings();
1945 configSettings->beginGroup("/kconfig/qconf");
1946 v = new ConfigMainWindow();
1948 //zconfdump(stdout);
1949 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1950 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1954 configSettings->endGroup();
1955 delete configSettings;