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>
11 #include <qtextbrowser.h>
13 #include <QFileDialog>
16 #include <qapplication.h>
17 #include <qdesktopwidget.h>
20 #include <qsplitter.h>
21 #include <qlineedit.h>
23 #include <qpushbutton.h>
25 #include <qmessagebox.h>
38 static QApplication *configApp;
39 static ConfigSettings *configSettings;
41 QAction *ConfigMainWindow::saveAction;
43 static inline QString qgettext(const char* str)
45 return QString::fromLocal8Bit(str);
48 ConfigSettings::ConfigSettings()
49 : QSettings("kernel.org", "qconf")
54 * Reads a list of integer values from the application settings.
56 QList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
62 QStringList entryList = value(key).toStringList();
63 QStringList::Iterator it;
65 for (it = entryList.begin(); it != entryList.end(); ++it)
66 result.push_back((*it).toInt());
77 * Writes a list of integer values to the application settings.
79 bool ConfigSettings::writeSizes(const QString& key, const QList<int>& value)
81 QStringList stringList;
82 QList<int>::ConstIterator it;
84 for (it = value.begin(); it != value.end(); ++it)
85 stringList.push_back(QString::number(*it));
86 setValue(key, stringList);
94 * TODO check the value
96 void ConfigItem::okRename(int col)
101 * update the displayed of a menu entry
103 void ConfigItem::updateMenu(void)
107 struct property *prop;
114 setPixmap(promptColIdx, list->menuBackPix);
121 prompt = qgettext(menu_get_prompt(menu));
123 if (prop) switch (prop->type) {
125 if (list->mode == singleMode || list->mode == symbolMode) {
126 /* a menuconfig entry is displayed differently
127 * depending whether it's at the view root or a child.
129 if (sym && list->rootEntry == menu)
131 setPixmap(promptColIdx, list->menuPix);
135 setPixmap(promptColIdx, QIcon());
139 setPixmap(promptColIdx, QIcon());
147 setText(nameColIdx, QString::fromLocal8Bit(sym->name));
149 type = sym_get_type(sym);
155 if (!sym_is_changeable(sym) && list->optMode == normalOpt) {
156 setPixmap(promptColIdx, QIcon());
157 setText(noColIdx, QString::null);
158 setText(modColIdx, QString::null);
159 setText(yesColIdx, QString::null);
162 expr = sym_get_tristate_value(sym);
165 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
166 setPixmap(promptColIdx, list->choiceYesPix);
168 setPixmap(promptColIdx, list->symbolYesPix);
169 setText(yesColIdx, "Y");
173 setPixmap(promptColIdx, list->symbolModPix);
174 setText(modColIdx, "M");
178 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
179 setPixmap(promptColIdx, list->choiceNoPix);
181 setPixmap(promptColIdx, list->symbolNoPix);
182 setText(noColIdx, "N");
187 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
189 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
191 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
193 setText(dataColIdx, QChar(ch));
200 data = sym_get_string_value(sym);
202 setText(dataColIdx, data);
203 if (type == S_STRING)
204 prompt = QString("%1: %2").arg(prompt).arg(data);
206 prompt = QString("(%2) %1").arg(prompt).arg(data);
209 if (!sym_has_value(sym) && visible)
212 setText(promptColIdx, prompt);
215 void ConfigItem::testUpdateMenu(bool v)
223 sym_calc_value(menu->sym);
224 if (menu->flags & MENU_CHANGED) {
225 /* the menu entry changed, so update all list items */
226 menu->flags &= ~MENU_CHANGED;
227 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
229 } else if (listView()->updateAll)
235 * construct a menu entry
237 void ConfigItem::init(void)
240 ConfigList* list = listView();
241 nextItem = (ConfigItem*)menu->data;
244 if (list->mode != fullMode)
246 sym_calc_value(menu->sym);
252 * destruct a menu entry
254 ConfigItem::~ConfigItem(void)
257 ConfigItem** ip = (ConfigItem**)&menu->data;
258 for (; *ip; ip = &(*ip)->nextItem) {
267 ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
270 connect(this, SIGNAL(editingFinished()), SLOT(hide()));
273 void ConfigLineEdit::show(ConfigItem* i)
276 if (sym_get_string_value(item->menu->sym))
277 setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
279 setText(QString::null);
284 void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
291 sym_set_string_value(item->menu->sym, text().toLatin1());
292 parent()->updateList(item);
295 Parent::keyPressEvent(e);
299 parent()->list->setFocus();
303 ConfigList::ConfigList(ConfigView* p, const char *name)
306 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
307 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
308 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
309 showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt),
310 rootEntry(0), headerPopup(0)
313 setSortingEnabled(false);
314 setRootIsDecorated(true);
316 setVerticalScrollMode(ScrollPerPixel);
317 setHorizontalScrollMode(ScrollPerPixel);
319 setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value");
321 connect(this, SIGNAL(itemSelectionChanged(void)),
322 SLOT(updateSelection(void)));
325 configSettings->beginGroup(name);
326 showName = configSettings->value("/showName", false).toBool();
327 showRange = configSettings->value("/showRange", false).toBool();
328 showData = configSettings->value("/showData", false).toBool();
329 optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt();
330 configSettings->endGroup();
331 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
334 addColumn(promptColIdx);
339 bool ConfigList::menuSkip(struct menu *menu)
341 if (optMode == normalOpt && menu_is_visible(menu))
343 if (optMode == promptOpt && menu_has_prompt(menu))
345 if (optMode == allOpt)
350 void ConfigList::reinit(void)
352 removeColumn(dataColIdx);
353 removeColumn(yesColIdx);
354 removeColumn(modColIdx);
355 removeColumn(noColIdx);
356 removeColumn(nameColIdx);
359 addColumn(nameColIdx);
362 addColumn(modColIdx);
363 addColumn(yesColIdx);
366 addColumn(dataColIdx);
371 void ConfigList::saveSettings(void)
373 if (!objectName().isEmpty()) {
374 configSettings->beginGroup(objectName());
375 configSettings->setValue("/showName", showName);
376 configSettings->setValue("/showRange", showRange);
377 configSettings->setValue("/showData", showData);
378 configSettings->setValue("/optionMode", (int)optMode);
379 configSettings->endGroup();
383 ConfigItem* ConfigList::findConfigItem(struct menu *menu)
385 ConfigItem* item = (ConfigItem*)menu->data;
387 for (; item; item = item->nextItem) {
388 if (this == item->listView())
395 void ConfigList::updateSelection(void)
400 if (selectedItems().count() == 0)
403 ConfigItem* item = (ConfigItem*)selectedItems().first();
408 emit menuChanged(menu);
411 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
412 if (mode == menuMode && type == P_MENU)
413 emit menuSelected(menu);
416 void ConfigList::updateList(ConfigItem* item)
418 ConfigItem* last = 0;
421 if (mode != listMode)
423 QTreeWidgetItemIterator it(this);
427 item = (ConfigItem*)(*it);
430 item->testUpdateMenu(menu_is_visible(item->menu));
437 if (rootEntry != &rootmenu && (mode == singleMode ||
438 (mode == symbolMode && rootEntry->parent != &rootmenu))) {
439 item = (ConfigItem *)topLevelItem(0);
441 item = new ConfigItem(this, 0, true);
444 if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
445 rootEntry->sym && rootEntry->prompt) {
446 item = last ? last->nextSibling() : firstChild();
448 item = new ConfigItem(this, last, rootEntry, true);
450 item->testUpdateMenu(true);
452 updateMenuList(item, rootEntry);
454 resizeColumnToContents(0);
458 updateMenuList(this, rootEntry);
460 resizeColumnToContents(0);
463 void ConfigList::setValue(ConfigItem* item, tristate val)
469 sym = item->menu ? item->menu->sym : 0;
473 type = sym_get_type(sym);
477 oldval = sym_get_tristate_value(sym);
479 if (!sym_set_tristate_value(sym, val))
481 if (oldval == no && item->menu->list)
482 item->setExpanded(true);
483 parent()->updateList(item);
488 void ConfigList::changeValue(ConfigItem* item)
492 int type, oldexpr, newexpr;
499 if (item->menu->list)
500 item->setExpanded(!item->isExpanded());
504 type = sym_get_type(sym);
508 oldexpr = sym_get_tristate_value(sym);
509 newexpr = sym_toggle_tristate_value(sym);
510 if (item->menu->list) {
511 if (oldexpr == newexpr)
512 item->setExpanded(!item->isExpanded());
513 else if (oldexpr == no)
514 item->setExpanded(true);
516 if (oldexpr != newexpr)
517 parent()->updateList(item);
522 parent()->lineEdit->show(item);
527 void ConfigList::setRootMenu(struct menu *menu)
531 if (rootEntry == menu)
533 type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
536 updateMenuList(this, 0);
540 currentItem()->setSelected(hasFocus());
541 scrollToItem(currentItem());
545 void ConfigList::setParentMenu(void)
548 struct menu *oldroot;
551 if (rootEntry == &rootmenu)
553 setRootMenu(menu_get_parent_menu(rootEntry->parent));
555 QTreeWidgetItemIterator it(this);
557 item = (ConfigItem *)(*it);
558 if (item->menu == oldroot) {
559 setCurrentItem(item);
569 * update all the children of a menu entry
570 * removes/adds the entries from the parent widget as necessary
572 * parent: either the menu list widget or a menu entry widget
573 * menu: entry to be updated
575 void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
584 while (parent->childCount() > 0)
586 delete parent->takeChild(0);
592 last = parent->firstChild();
593 if (last && !last->goParent)
595 for (child = menu->list; child; child = child->next) {
596 item = last ? last->nextSibling() : parent->firstChild();
597 type = child->prompt ? child->prompt->type : P_UNKNOWN;
601 if (!(child->flags & MENU_ROOT))
605 if (child->flags & MENU_ROOT)
612 visible = menu_is_visible(child);
613 if (!menuSkip(child)) {
614 if (!child->sym && !child->list && !child->prompt)
616 if (!item || item->menu != child)
617 item = new ConfigItem(parent, last, child, visible);
619 item->testUpdateMenu(visible);
621 if (mode == fullMode || mode == menuMode || type != P_MENU)
622 updateMenuList(item, child);
624 updateMenuList(item, 0);
629 if (item && item->menu == child) {
630 last = parent->firstChild();
633 else while (last->nextSibling() != item)
634 last = last->nextSibling();
640 void ConfigList::updateMenuList(ConfigList *parent, struct menu* menu)
649 while (parent->topLevelItemCount() > 0)
651 delete parent->takeTopLevelItem(0);
657 last = (ConfigItem*)parent->topLevelItem(0);
658 if (last && !last->goParent)
660 for (child = menu->list; child; child = child->next) {
661 item = last ? last->nextSibling() : (ConfigItem*)parent->topLevelItem(0);
662 type = child->prompt ? child->prompt->type : P_UNKNOWN;
666 if (!(child->flags & MENU_ROOT))
670 if (child->flags & MENU_ROOT)
677 visible = menu_is_visible(child);
678 if (!menuSkip(child)) {
679 if (!child->sym && !child->list && !child->prompt)
681 if (!item || item->menu != child)
682 item = new ConfigItem(parent, last, child, visible);
684 item->testUpdateMenu(visible);
686 if (mode == fullMode || mode == menuMode || type != P_MENU)
687 updateMenuList(item, child);
689 updateMenuList(item, 0);
694 if (item && item->menu == child) {
695 last = (ConfigItem*)parent->topLevelItem(0);
698 else while (last->nextSibling() != item)
699 last = last->nextSibling();
705 void ConfigList::keyPressEvent(QKeyEvent* ev)
707 QTreeWidgetItem* i = currentItem();
712 if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
713 emit parentSelected();
719 Parent::keyPressEvent(ev);
722 item = (ConfigItem*)i;
727 if (item->goParent) {
728 emit parentSelected();
734 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
735 if (type == P_MENU && rootEntry != menu &&
736 mode != fullMode && mode != menuMode) {
737 emit menuSelected(menu);
753 Parent::keyPressEvent(ev);
759 void ConfigList::mousePressEvent(QMouseEvent* e)
761 //QPoint p(contentsToViewport(e->pos()));
762 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
763 Parent::mousePressEvent(e);
766 void ConfigList::mouseReleaseEvent(QMouseEvent* e)
769 ConfigItem* item = (ConfigItem*)itemAt(p);
771 enum prop_type ptype;
779 x = header()->offset() + p.x();
780 idx = header()->logicalIndexAt(x);
783 icon = item->pixmap(promptColIdx);
784 if (!icon.isNull()) {
785 int off = header()->sectionPosition(0) + visualRect(indexAt(p)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly.
786 if (x >= off && x < off + icon.availableSizes().first().width()) {
787 if (item->goParent) {
788 emit parentSelected();
792 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
793 if (ptype == P_MENU && rootEntry != menu &&
794 mode != fullMode && mode != menuMode)
795 emit menuSelected(menu);
816 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
817 Parent::mouseReleaseEvent(e);
820 void ConfigList::mouseMoveEvent(QMouseEvent* e)
822 //QPoint p(contentsToViewport(e->pos()));
823 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
824 Parent::mouseMoveEvent(e);
827 void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
829 QPoint p = e->pos(); // TODO: Check if this works(was contentsToViewport).
830 ConfigItem* item = (ConfigItem*)itemAt(p);
832 enum prop_type ptype;
836 if (item->goParent) {
837 emit parentSelected();
843 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
844 if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
845 emit menuSelected(menu);
850 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
851 Parent::mouseDoubleClickEvent(e);
854 void ConfigList::focusInEvent(QFocusEvent *e)
856 struct menu *menu = NULL;
858 Parent::focusInEvent(e);
860 ConfigItem* item = (ConfigItem *)currentItem();
862 item->setSelected(true);
868 void ConfigList::contextMenuEvent(QContextMenuEvent *e)
870 if (e->y() <= header()->geometry().bottom()) {
874 headerPopup = new QMenu(this);
875 action = new QAction("Show Name", this);
876 action->setCheckable(true);
877 connect(action, SIGNAL(toggled(bool)),
878 parent(), SLOT(setShowName(bool)));
879 connect(parent(), SIGNAL(showNameChanged(bool)),
880 action, SLOT(setOn(bool)));
881 action->setChecked(showName);
882 headerPopup->addAction(action);
883 action = new QAction("Show Range", this);
884 action->setCheckable(true);
885 connect(action, SIGNAL(toggled(bool)),
886 parent(), SLOT(setShowRange(bool)));
887 connect(parent(), SIGNAL(showRangeChanged(bool)),
888 action, SLOT(setOn(bool)));
889 action->setChecked(showRange);
890 headerPopup->addAction(action);
891 action = new QAction("Show Data", this);
892 action->setCheckable(true);
893 connect(action, SIGNAL(toggled(bool)),
894 parent(), SLOT(setShowData(bool)));
895 connect(parent(), SIGNAL(showDataChanged(bool)),
896 action, SLOT(setOn(bool)));
897 action->setChecked(showData);
898 headerPopup->addAction(action);
900 headerPopup->exec(e->globalPos());
906 ConfigView*ConfigView::viewList;
907 QAction *ConfigView::showNormalAction;
908 QAction *ConfigView::showAllAction;
909 QAction *ConfigView::showPromptAction;
911 ConfigView::ConfigView(QWidget* parent, const char *name)
915 QVBoxLayout *verticalLayout = new QVBoxLayout(this);
916 verticalLayout->setContentsMargins(0, 0, 0, 0);
918 list = new ConfigList(this);
919 verticalLayout->addWidget(list);
920 lineEdit = new ConfigLineEdit(this);
922 verticalLayout->addWidget(lineEdit);
924 this->nextView = viewList;
928 ConfigView::~ConfigView(void)
932 for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
940 void ConfigView::setOptionMode(QAction *act)
942 if (act == showNormalAction)
943 list->optMode = normalOpt;
944 else if (act == showAllAction)
945 list->optMode = allOpt;
947 list->optMode = promptOpt;
949 list->updateListAll();
952 void ConfigView::setShowName(bool b)
954 if (list->showName != b) {
957 emit showNameChanged(b);
961 void ConfigView::setShowRange(bool b)
963 if (list->showRange != b) {
966 emit showRangeChanged(b);
970 void ConfigView::setShowData(bool b)
972 if (list->showData != b) {
975 emit showDataChanged(b);
979 void ConfigList::setAllOpen(bool open)
981 QTreeWidgetItemIterator it(this);
984 (*it)->setExpanded(open);
990 void ConfigView::updateList(ConfigItem* item)
994 for (v = viewList; v; v = v->nextView)
995 v->list->updateList(item);
998 void ConfigView::updateListAll(void)
1002 for (v = viewList; v; v = v->nextView)
1003 v->list->updateListAll();
1006 ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
1007 : Parent(parent), sym(0), _menu(0)
1009 setObjectName(name);
1012 if (!objectName().isEmpty()) {
1013 configSettings->beginGroup(objectName());
1014 setShowDebug(configSettings->value("/showDebug", false).toBool());
1015 configSettings->endGroup();
1016 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1020 void ConfigInfoView::saveSettings(void)
1022 if (!objectName().isEmpty()) {
1023 configSettings->beginGroup(objectName());
1024 configSettings->setValue("/showDebug", showDebug());
1025 configSettings->endGroup();
1029 void ConfigInfoView::setShowDebug(bool b)
1031 if (_showDebug != b) {
1037 emit showDebugChanged(b);
1041 void ConfigInfoView::setInfo(struct menu *m)
1053 void ConfigInfoView::symbolInfo(void)
1057 str += "<big>Symbol: <b>";
1058 str += print_filter(sym->name);
1059 str += "</b></big><br><br>value: ";
1060 str += print_filter(sym_get_string_value(sym));
1061 str += "<br>visibility: ";
1062 str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
1064 str += debug_info(sym);
1069 void ConfigInfoView::menuInfo(void)
1072 QString head, debug, help;
1076 if (_menu->prompt) {
1078 head += print_filter(_menu->prompt->text);
1079 head += "</b></big>";
1083 head += QString().sprintf("<a href=\"s%p\">", sym);
1084 head += print_filter(sym->name);
1089 } else if (sym->name) {
1092 head += QString().sprintf("<a href=\"s%p\">", sym);
1093 head += print_filter(sym->name);
1096 head += "</b></big>";
1101 debug = debug_info(sym);
1103 struct gstr help_gstr = str_new();
1104 menu_get_ext_help(_menu, &help_gstr);
1105 help = print_filter(str_get(&help_gstr));
1106 str_free(&help_gstr);
1107 } else if (_menu->prompt) {
1109 head += print_filter(_menu->prompt->text);
1110 head += "</b></big><br><br>";
1112 if (_menu->prompt->visible.expr) {
1113 debug += " dep: ";
1114 expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
1115 debug += "<br><br>";
1120 debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
1122 setText(head + debug + help);
1125 QString ConfigInfoView::debug_info(struct symbol *sym)
1130 debug += print_filter(sym_type_name(sym->type));
1131 if (sym_is_choice(sym))
1132 debug += " (choice)";
1134 if (sym->rev_dep.expr) {
1135 debug += "reverse dep: ";
1136 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1139 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1140 switch (prop->type) {
1143 debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
1144 debug += print_filter(prop->text);
1145 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%p\">", sym);
1222 QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
1224 QMenu* popup = Parent::createStandardContextMenu(pos);
1225 QAction* action = new QAction("Show Debug Info", popup);
1226 action->setCheckable(true);
1227 connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1228 connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
1229 action->setChecked(showDebug());
1230 popup->addSeparator();
1231 popup->addAction(action);
1235 void ConfigInfoView::contextMenuEvent(QContextMenuEvent *e)
1237 Parent::contextMenuEvent(e);
1240 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
1241 : Parent(parent), result(NULL)
1243 setObjectName(name);
1244 setWindowTitle("Search Config");
1246 QVBoxLayout* layout1 = new QVBoxLayout(this);
1247 layout1->setContentsMargins(11, 11, 11, 11);
1248 layout1->setSpacing(6);
1249 QHBoxLayout* layout2 = new QHBoxLayout(0);
1250 layout2->setContentsMargins(0, 0, 0, 0);
1251 layout2->setSpacing(6);
1252 layout2->addWidget(new QLabel("Find:", this));
1253 editField = new QLineEdit(this);
1254 connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1255 layout2->addWidget(editField);
1256 searchButton = new QPushButton("Search", this);
1257 searchButton->setAutoDefault(false);
1258 connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1259 layout2->addWidget(searchButton);
1260 layout1->addLayout(layout2);
1262 split = new QSplitter(this);
1263 split->setOrientation(Qt::Vertical);
1264 list = new ConfigView(split, name);
1265 list->list->mode = listMode;
1266 info = new ConfigInfoView(split, name);
1267 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1268 info, SLOT(setInfo(struct menu *)));
1269 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1270 parent, SLOT(setMenuLink(struct menu *)));
1272 layout1->addWidget(split);
1279 configSettings->beginGroup(name);
1280 width = configSettings->value("/window width", parent->width() / 2).toInt();
1281 height = configSettings->value("/window height", parent->height() / 2).toInt();
1282 resize(width, height);
1283 x = configSettings->value("/window x");
1284 y = configSettings->value("/window y");
1285 if ((x.isValid())&&(y.isValid()))
1286 move(x.toInt(), y.toInt());
1287 QList<int> sizes = configSettings->readSizes("/split", &ok);
1289 split->setSizes(sizes);
1290 configSettings->endGroup();
1291 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1295 void ConfigSearchWindow::saveSettings(void)
1297 if (!objectName().isEmpty()) {
1298 configSettings->beginGroup(objectName());
1299 configSettings->setValue("/window x", pos().x());
1300 configSettings->setValue("/window y", pos().y());
1301 configSettings->setValue("/window width", size().width());
1302 configSettings->setValue("/window height", size().height());
1303 configSettings->writeSizes("/split", split->sizes());
1304 configSettings->endGroup();
1308 void ConfigSearchWindow::search(void)
1311 struct property *prop;
1312 ConfigItem *lastItem = NULL;
1315 list->list->clear();
1318 result = sym_re_search(editField->text().toLatin1());
1321 for (p = result; *p; p++) {
1322 for_all_prompts((*p), prop)
1323 lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1324 menu_is_visible(prop->menu));
1329 * Construct the complete config widget
1331 ConfigMainWindow::ConfigMainWindow(void)
1340 QDesktopWidget *d = configApp->desktop();
1341 snprintf(title, sizeof(title), "%s%s",
1342 rootmenu.prompt->text,
1345 setWindowTitle(title);
1347 width = configSettings->value("/window width", d->width() - 64).toInt();
1348 height = configSettings->value("/window height", d->height() - 64).toInt();
1349 resize(width, height);
1350 x = configSettings->value("/window x");
1351 y = configSettings->value("/window y");
1352 if ((x.isValid())&&(y.isValid()))
1353 move(x.toInt(), y.toInt());
1355 split1 = new QSplitter(this);
1356 split1->setOrientation(Qt::Horizontal);
1357 setCentralWidget(split1);
1359 menuView = new ConfigView(split1, "menu");
1360 menuList = menuView->list;
1362 split2 = new QSplitter(split1);
1363 split2->setOrientation(Qt::Vertical);
1365 // create config tree
1366 configView = new ConfigView(split2, "config");
1367 configList = configView->list;
1369 helpText = new ConfigInfoView(split2, "help");
1371 setTabOrder(configList, helpText);
1372 configList->setFocus();
1375 toolBar = new QToolBar("Tools", this);
1376 addToolBar(toolBar);
1378 backAction = new QAction(QPixmap(xpm_back), "Back", this);
1379 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
1380 backAction->setEnabled(false);
1381 QAction *quitAction = new QAction("&Quit", this);
1382 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
1383 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
1384 QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
1385 loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
1386 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
1387 saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
1388 saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
1389 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
1390 conf_set_changed_callback(conf_changed);
1391 // Set saveAction's initial state
1393 configname = xstrdup(conf_get_configname());
1395 QAction *saveAsAction = new QAction("Save &As...", this);
1396 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
1397 QAction *searchAction = new QAction("&Find", this);
1398 searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
1399 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
1400 singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
1401 singleViewAction->setCheckable(true);
1402 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
1403 splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this);
1404 splitViewAction->setCheckable(true);
1405 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
1406 fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this);
1407 fullViewAction->setCheckable(true);
1408 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
1410 QAction *showNameAction = new QAction("Show Name", this);
1411 showNameAction->setCheckable(true);
1412 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1413 showNameAction->setChecked(configView->showName());
1414 QAction *showRangeAction = new QAction("Show Range", this);
1415 showRangeAction->setCheckable(true);
1416 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1417 QAction *showDataAction = new QAction("Show Data", this);
1418 showDataAction->setCheckable(true);
1419 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1421 QActionGroup *optGroup = new QActionGroup(this);
1422 optGroup->setExclusive(true);
1423 connect(optGroup, SIGNAL(triggered(QAction*)), configView,
1424 SLOT(setOptionMode(QAction *)));
1425 connect(optGroup, SIGNAL(triggered(QAction *)), menuView,
1426 SLOT(setOptionMode(QAction *)));
1428 configView->showNormalAction = new QAction("Show Normal Options", optGroup);
1429 configView->showAllAction = new QAction("Show All Options", optGroup);
1430 configView->showPromptAction = new QAction("Show Prompt Options", optGroup);
1431 configView->showNormalAction->setCheckable(true);
1432 configView->showAllAction->setCheckable(true);
1433 configView->showPromptAction->setCheckable(true);
1435 QAction *showDebugAction = new QAction("Show Debug Info", this);
1436 showDebugAction->setCheckable(true);
1437 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1438 showDebugAction->setChecked(helpText->showDebug());
1440 QAction *showIntroAction = new QAction("Introduction", this);
1441 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
1442 QAction *showAboutAction = new QAction("About", this);
1443 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
1446 toolBar->addAction(backAction);
1447 toolBar->addSeparator();
1448 toolBar->addAction(loadAction);
1449 toolBar->addAction(saveAction);
1450 toolBar->addSeparator();
1451 toolBar->addAction(singleViewAction);
1452 toolBar->addAction(splitViewAction);
1453 toolBar->addAction(fullViewAction);
1455 // create config menu
1456 QMenu* config = menu->addMenu("&File");
1457 config->addAction(loadAction);
1458 config->addAction(saveAction);
1459 config->addAction(saveAsAction);
1460 config->addSeparator();
1461 config->addAction(quitAction);
1464 QMenu* editMenu = menu->addMenu("&Edit");
1465 editMenu->addAction(searchAction);
1467 // create options menu
1468 QMenu* optionMenu = menu->addMenu("&Option");
1469 optionMenu->addAction(showNameAction);
1470 optionMenu->addAction(showRangeAction);
1471 optionMenu->addAction(showDataAction);
1472 optionMenu->addSeparator();
1473 optionMenu->addActions(optGroup->actions());
1474 optionMenu->addSeparator();
1475 optionMenu->addAction(showDebugAction);
1478 menu->addSeparator();
1479 QMenu* helpMenu = menu->addMenu("&Help");
1480 helpMenu->addAction(showIntroAction);
1481 helpMenu->addAction(showAboutAction);
1483 connect(configList, SIGNAL(menuChanged(struct menu *)),
1484 helpText, SLOT(setInfo(struct menu *)));
1485 connect(configList, SIGNAL(menuSelected(struct menu *)),
1486 SLOT(changeMenu(struct menu *)));
1487 connect(configList, SIGNAL(parentSelected()),
1489 connect(menuList, SIGNAL(menuChanged(struct menu *)),
1490 helpText, SLOT(setInfo(struct menu *)));
1491 connect(menuList, SIGNAL(menuSelected(struct menu *)),
1492 SLOT(changeMenu(struct menu *)));
1494 connect(configList, SIGNAL(gotFocus(struct menu *)),
1495 helpText, SLOT(setInfo(struct menu *)));
1496 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1497 helpText, SLOT(setInfo(struct menu *)));
1498 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1499 SLOT(listFocusChanged(void)));
1500 connect(helpText, SIGNAL(menuSelected(struct menu *)),
1501 SLOT(setMenuLink(struct menu *)));
1503 QString listMode = configSettings->value("/listMode", "symbol").toString();
1504 if (listMode == "single")
1506 else if (listMode == "full")
1508 else /*if (listMode == "split")*/
1511 // UI setup done, restore splitter positions
1512 QList<int> sizes = configSettings->readSizes("/split1", &ok);
1514 split1->setSizes(sizes);
1516 sizes = configSettings->readSizes("/split2", &ok);
1518 split2->setSizes(sizes);
1521 void ConfigMainWindow::loadConfig(void)
1527 str = QFileDialog::getOpenFileName(this, "", configname);
1531 ba = str.toLocal8Bit();
1534 if (conf_read(name))
1535 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1538 configname = xstrdup(name);
1540 ConfigView::updateListAll();
1543 bool ConfigMainWindow::saveConfig(void)
1545 if (conf_write(configname)) {
1546 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1549 conf_write_autoconf(0);
1554 void ConfigMainWindow::saveConfigAs(void)
1560 str = QFileDialog::getSaveFileName(this, "", configname);
1564 ba = str.toLocal8Bit();
1567 if (conf_write(name)) {
1568 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1570 conf_write_autoconf(0);
1573 configname = xstrdup(name);
1576 void ConfigMainWindow::searchConfig(void)
1579 searchWindow = new ConfigSearchWindow(this, "search");
1580 searchWindow->show();
1583 void ConfigMainWindow::changeMenu(struct menu *menu)
1585 configList->setRootMenu(menu);
1586 if (configList->rootEntry->parent == &rootmenu)
1587 backAction->setEnabled(false);
1589 backAction->setEnabled(true);
1592 void ConfigMainWindow::setMenuLink(struct menu *menu)
1594 struct menu *parent;
1595 ConfigList* list = NULL;
1598 if (configList->menuSkip(menu))
1601 switch (configList->mode) {
1604 parent = menu_get_parent_menu(menu);
1607 list->setRootMenu(parent);
1610 if (menu->flags & MENU_ROOT) {
1611 configList->setRootMenu(menu);
1612 configList->clearSelection();
1616 parent = menu_get_parent_menu(menu->parent);
1619 item = menuList->findConfigItem(parent);
1621 item->setSelected(true);
1622 menuList->scrollToItem(item);
1624 list->setRootMenu(parent);
1635 item = list->findConfigItem(menu);
1637 item->setSelected(true);
1638 list->scrollToItem(item);
1644 void ConfigMainWindow::listFocusChanged(void)
1646 if (menuList->mode == menuMode)
1647 configList->clearSelection();
1650 void ConfigMainWindow::goBack(void)
1652 ConfigItem* item, *oldSelection;
1654 configList->setParentMenu();
1655 if (configList->rootEntry == &rootmenu)
1656 backAction->setEnabled(false);
1658 if (menuList->selectedItems().count() == 0)
1661 item = (ConfigItem*)menuList->selectedItems().first();
1662 oldSelection = item;
1664 if (item->menu == configList->rootEntry) {
1665 oldSelection->setSelected(false);
1666 item->setSelected(true);
1669 item = (ConfigItem*)item->parent();
1673 void ConfigMainWindow::showSingleView(void)
1675 singleViewAction->setEnabled(false);
1676 singleViewAction->setChecked(true);
1677 splitViewAction->setEnabled(true);
1678 splitViewAction->setChecked(false);
1679 fullViewAction->setEnabled(true);
1680 fullViewAction->setChecked(false);
1683 menuList->setRootMenu(0);
1684 configList->mode = singleMode;
1685 if (configList->rootEntry == &rootmenu)
1686 configList->updateListAll();
1688 configList->setRootMenu(&rootmenu);
1689 configList->setFocus();
1692 void ConfigMainWindow::showSplitView(void)
1694 singleViewAction->setEnabled(true);
1695 singleViewAction->setChecked(false);
1696 splitViewAction->setEnabled(false);
1697 splitViewAction->setChecked(true);
1698 fullViewAction->setEnabled(true);
1699 fullViewAction->setChecked(false);
1701 configList->mode = symbolMode;
1702 if (configList->rootEntry == &rootmenu)
1703 configList->updateListAll();
1705 configList->setRootMenu(&rootmenu);
1706 configList->setAllOpen(true);
1707 configApp->processEvents();
1708 menuList->mode = menuMode;
1709 menuList->setRootMenu(&rootmenu);
1710 menuList->setAllOpen(true);
1712 menuList->setFocus();
1715 void ConfigMainWindow::showFullView(void)
1717 singleViewAction->setEnabled(true);
1718 singleViewAction->setChecked(false);
1719 splitViewAction->setEnabled(true);
1720 splitViewAction->setChecked(false);
1721 fullViewAction->setEnabled(false);
1722 fullViewAction->setChecked(true);
1725 menuList->setRootMenu(0);
1726 configList->mode = fullMode;
1727 if (configList->rootEntry == &rootmenu)
1728 configList->updateListAll();
1730 configList->setRootMenu(&rootmenu);
1731 configList->setFocus();
1735 * ask for saving configuration before quitting
1736 * TODO ask only when something changed
1738 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1740 if (!conf_get_changed()) {
1744 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1745 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1746 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1747 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1748 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1749 switch (mb.exec()) {
1750 case QMessageBox::Yes:
1756 case QMessageBox::No:
1759 case QMessageBox::Cancel:
1765 void ConfigMainWindow::showIntro(void)
1767 static const QString str = "Welcome to the qconf graphical configuration tool.\n\n"
1768 "For each option, a blank box indicates the feature is disabled, a check\n"
1769 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1770 "as a module. Clicking on the box will cycle through the three states.\n\n"
1771 "If you do not see an option (e.g., a device driver) that you believe\n"
1772 "should be present, try turning on Show All Options under the Options menu.\n"
1773 "Although there is no cross reference yet to help you figure out what other\n"
1774 "options must be enabled to support the option you are interested in, you can\n"
1775 "still view the help of a grayed-out option.\n\n"
1776 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1777 "which you can then match by examining other options.\n\n";
1779 QMessageBox::information(this, "qconf", str);
1782 void ConfigMainWindow::showAbout(void)
1784 static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
1785 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
1786 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1788 QMessageBox::information(this, "qconf", str);
1791 void ConfigMainWindow::saveSettings(void)
1793 configSettings->setValue("/window x", pos().x());
1794 configSettings->setValue("/window y", pos().y());
1795 configSettings->setValue("/window width", size().width());
1796 configSettings->setValue("/window height", size().height());
1799 switch(configList->mode) {
1815 configSettings->setValue("/listMode", entry);
1817 configSettings->writeSizes("/split1", split1->sizes());
1818 configSettings->writeSizes("/split2", split2->sizes());
1821 void ConfigMainWindow::conf_changed(void)
1824 saveAction->setEnabled(conf_get_changed());
1827 void fixup_rootmenu(struct menu *menu)
1830 static int menu_cnt = 0;
1832 menu->flags |= MENU_ROOT;
1833 for (child = menu->list; child; child = child->next) {
1834 if (child->prompt && child->prompt->type == P_MENU) {
1836 fixup_rootmenu(child);
1838 } else if (!menu_cnt)
1839 fixup_rootmenu(child);
1843 static const char *progname;
1845 static void usage(void)
1847 printf("%s [-s] <config>\n", progname);
1851 int main(int ac, char** av)
1853 ConfigMainWindow* v;
1857 configApp = new QApplication(ac, av);
1858 if (ac > 1 && av[1][0] == '-') {
1861 conf_set_message_callback(NULL);
1874 fixup_rootmenu(&rootmenu);
1876 //zconfdump(stdout);
1878 configSettings = new ConfigSettings();
1879 configSettings->beginGroup("/kconfig/qconf");
1880 v = new ConfigMainWindow();
1882 //zconfdump(stdout);
1883 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1884 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1888 configSettings->endGroup();
1889 delete configSettings;