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)
1080 QTextStream stream(&info);
1084 if (_menu->prompt) {
1085 stream << "<big><b>";
1086 stream << print_filter(_menu->prompt->text);
1087 stream << "</b></big>";
1091 stream << "<a href=\"s" << sym->name << "\">";
1092 stream << print_filter(sym->name);
1097 } else if (sym->name) {
1098 stream << "<big><b>";
1100 stream << "<a href=\"s" << sym->name << "\">";
1101 stream << print_filter(sym->name);
1104 stream << "</b></big>";
1106 stream << "<br><br>";
1109 stream << debug_info(sym);
1111 struct gstr help_gstr = str_new();
1113 menu_get_ext_help(_menu, &help_gstr);
1114 stream << print_filter(str_get(&help_gstr));
1115 str_free(&help_gstr);
1116 } else if (_menu->prompt) {
1117 stream << "<big><b>";
1118 stream << print_filter(_menu->prompt->text);
1119 stream << "</b></big><br><br>";
1121 if (_menu->prompt->visible.expr) {
1122 stream << " dep: ";
1123 expr_print(_menu->prompt->visible.expr,
1124 expr_print_help, &stream, E_NONE);
1125 stream << "<br><br>";
1128 stream << "defined at " << _menu->file->name << ":"
1129 << _menu->lineno << "<br><br>";
1136 QString ConfigInfoView::debug_info(struct symbol *sym)
1139 QTextStream stream(&debug);
1142 stream << print_filter(sym_type_name(sym->type));
1143 if (sym_is_choice(sym))
1144 stream << " (choice)";
1146 if (sym->rev_dep.expr) {
1147 stream << "reverse dep: ";
1148 expr_print(sym->rev_dep.expr, expr_print_help, &stream, E_NONE);
1151 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1152 switch (prop->type) {
1155 stream << "prompt: <a href=\"m" << sym->name << "\">";
1156 stream << print_filter(prop->text);
1157 stream << "</a><br>";
1165 stream << prop_get_type_name(prop->type);
1167 expr_print(prop->expr, expr_print_help,
1172 if (sym_is_choice(sym)) {
1173 stream << "choice: ";
1174 expr_print(prop->expr, expr_print_help,
1180 stream << "unknown property: ";
1181 stream << prop_get_type_name(prop->type);
1184 if (prop->visible.expr) {
1185 stream << " dep: ";
1186 expr_print(prop->visible.expr, expr_print_help,
1196 QString ConfigInfoView::print_filter(const QString &str)
1198 QRegExp re("[<>&\"\\n]");
1200 for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
1201 switch (res[i].toLatin1()) {
1203 res.replace(i, 1, "<");
1207 res.replace(i, 1, ">");
1211 res.replace(i, 1, "&");
1215 res.replace(i, 1, """);
1219 res.replace(i, 1, "<br>");
1227 void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
1229 QTextStream *stream = reinterpret_cast<QTextStream *>(data);
1231 if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1232 *stream << "<a href=\"s" << sym->name << "\">";
1233 *stream << print_filter(str);
1236 *stream << print_filter(str);
1240 void ConfigInfoView::clicked(const QUrl &url)
1242 QByteArray str = url.toEncoded();
1243 const std::size_t count = str.size();
1244 char *data = new char[count + 1];
1245 struct symbol **result;
1246 struct menu *m = NULL;
1253 memcpy(data, str.constData(), count);
1256 /* Seek for exact match */
1259 result = sym_re_search(data);
1267 /* Seek for the menu which holds the symbol */
1268 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1269 if (prop->type != P_PROMPT && prop->type != P_MENU)
1276 /* Symbol is not visible as a menu */
1278 emit showDebugChanged(true);
1280 emit menuSelected(m);
1287 void ConfigInfoView::contextMenuEvent(QContextMenuEvent *event)
1289 contextMenu->popup(event->globalPos());
1293 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
1294 : Parent(parent), result(NULL)
1296 setObjectName("search");
1297 setWindowTitle("Search Config");
1299 QVBoxLayout* layout1 = new QVBoxLayout(this);
1300 layout1->setContentsMargins(11, 11, 11, 11);
1301 layout1->setSpacing(6);
1303 QHBoxLayout* layout2 = new QHBoxLayout();
1304 layout2->setContentsMargins(0, 0, 0, 0);
1305 layout2->setSpacing(6);
1306 layout2->addWidget(new QLabel("Find:", this));
1307 editField = new QLineEdit(this);
1308 connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1309 layout2->addWidget(editField);
1310 searchButton = new QPushButton("Search", this);
1311 searchButton->setAutoDefault(false);
1312 connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1313 layout2->addWidget(searchButton);
1314 layout1->addLayout(layout2);
1316 split = new QSplitter(this);
1317 split->setOrientation(Qt::Vertical);
1318 list = new ConfigView(split, "search");
1319 list->list->mode = listMode;
1320 info = new ConfigInfoView(split, "search");
1321 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1322 info, SLOT(setInfo(struct menu *)));
1323 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1324 parent, SLOT(setMenuLink(struct menu *)));
1326 layout1->addWidget(split);
1332 configSettings->beginGroup("search");
1333 width = configSettings->value("/window width", parent->width() / 2).toInt();
1334 height = configSettings->value("/window height", parent->height() / 2).toInt();
1335 resize(width, height);
1336 x = configSettings->value("/window x");
1337 y = configSettings->value("/window y");
1338 if (x.isValid() && y.isValid())
1339 move(x.toInt(), y.toInt());
1340 QList<int> sizes = configSettings->readSizes("/split", &ok);
1342 split->setSizes(sizes);
1343 configSettings->endGroup();
1344 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1347 void ConfigSearchWindow::saveSettings(void)
1349 if (!objectName().isEmpty()) {
1350 configSettings->beginGroup(objectName());
1351 configSettings->setValue("/window x", pos().x());
1352 configSettings->setValue("/window y", pos().y());
1353 configSettings->setValue("/window width", size().width());
1354 configSettings->setValue("/window height", size().height());
1355 configSettings->writeSizes("/split", split->sizes());
1356 configSettings->endGroup();
1360 void ConfigSearchWindow::search(void)
1363 struct property *prop;
1364 ConfigItem *lastItem = NULL;
1367 list->list->clear();
1370 result = sym_re_search(editField->text().toLatin1());
1373 for (p = result; *p; p++) {
1374 for_all_prompts((*p), prop)
1375 lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1376 menu_is_visible(prop->menu));
1381 * Construct the complete config widget
1383 ConfigMainWindow::ConfigMainWindow(void)
1391 QDesktopWidget *d = configApp->desktop();
1392 snprintf(title, sizeof(title), "%s%s",
1393 rootmenu.prompt->text,
1396 setWindowTitle(title);
1398 width = configSettings->value("/window width", d->width() - 64).toInt();
1399 height = configSettings->value("/window height", d->height() - 64).toInt();
1400 resize(width, height);
1401 x = configSettings->value("/window x");
1402 y = configSettings->value("/window y");
1403 if ((x.isValid())&&(y.isValid()))
1404 move(x.toInt(), y.toInt());
1407 ConfigItem::symbolYesIcon = QIcon(QPixmap(xpm_symbol_yes));
1408 ConfigItem::symbolModIcon = QIcon(QPixmap(xpm_symbol_mod));
1409 ConfigItem::symbolNoIcon = QIcon(QPixmap(xpm_symbol_no));
1410 ConfigItem::choiceYesIcon = QIcon(QPixmap(xpm_choice_yes));
1411 ConfigItem::choiceNoIcon = QIcon(QPixmap(xpm_choice_no));
1412 ConfigItem::menuIcon = QIcon(QPixmap(xpm_menu));
1413 ConfigItem::menubackIcon = QIcon(QPixmap(xpm_menuback));
1415 QWidget *widget = new QWidget(this);
1416 QVBoxLayout *layout = new QVBoxLayout(widget);
1417 setCentralWidget(widget);
1419 split1 = new QSplitter(widget);
1420 split1->setOrientation(Qt::Horizontal);
1421 split1->setChildrenCollapsible(false);
1423 menuView = new ConfigView(widget, "menu");
1424 menuList = menuView->list;
1426 split2 = new QSplitter(widget);
1427 split2->setChildrenCollapsible(false);
1428 split2->setOrientation(Qt::Vertical);
1430 // create config tree
1431 configView = new ConfigView(widget, "config");
1432 configList = configView->list;
1434 helpText = new ConfigInfoView(widget, "help");
1436 layout->addWidget(split2);
1437 split2->addWidget(split1);
1438 split1->addWidget(configView);
1439 split1->addWidget(menuView);
1440 split2->addWidget(helpText);
1442 setTabOrder(configList, helpText);
1443 configList->setFocus();
1445 backAction = new QAction(QPixmap(xpm_back), "Back", this);
1446 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
1448 QAction *quitAction = new QAction("&Quit", this);
1449 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
1450 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
1452 QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
1453 loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
1454 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
1456 saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
1457 saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
1458 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
1460 conf_set_changed_callback(conf_changed);
1462 // Set saveAction's initial state
1464 configname = xstrdup(conf_get_configname());
1466 QAction *saveAsAction = new QAction("Save &As...", this);
1467 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
1468 QAction *searchAction = new QAction("&Find", this);
1469 searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
1470 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
1471 singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
1472 singleViewAction->setCheckable(true);
1473 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
1474 splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this);
1475 splitViewAction->setCheckable(true);
1476 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
1477 fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this);
1478 fullViewAction->setCheckable(true);
1479 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
1481 QAction *showNameAction = new QAction("Show Name", this);
1482 showNameAction->setCheckable(true);
1483 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1484 showNameAction->setChecked(configView->showName());
1485 QAction *showRangeAction = new QAction("Show Range", this);
1486 showRangeAction->setCheckable(true);
1487 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1488 QAction *showDataAction = new QAction("Show Data", this);
1489 showDataAction->setCheckable(true);
1490 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1492 QActionGroup *optGroup = new QActionGroup(this);
1493 optGroup->setExclusive(true);
1494 connect(optGroup, SIGNAL(triggered(QAction*)), configList,
1495 SLOT(setOptionMode(QAction *)));
1496 connect(optGroup, SIGNAL(triggered(QAction *)), menuList,
1497 SLOT(setOptionMode(QAction *)));
1499 ConfigList::showNormalAction = new QAction("Show Normal Options", optGroup);
1500 ConfigList::showNormalAction->setCheckable(true);
1501 ConfigList::showAllAction = new QAction("Show All Options", optGroup);
1502 ConfigList::showAllAction->setCheckable(true);
1503 ConfigList::showPromptAction = new QAction("Show Prompt Options", optGroup);
1504 ConfigList::showPromptAction->setCheckable(true);
1506 QAction *showDebugAction = new QAction("Show Debug Info", this);
1507 showDebugAction->setCheckable(true);
1508 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1509 showDebugAction->setChecked(helpText->showDebug());
1511 QAction *showIntroAction = new QAction("Introduction", this);
1512 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
1513 QAction *showAboutAction = new QAction("About", this);
1514 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
1517 QToolBar *toolBar = addToolBar("Tools");
1518 toolBar->addAction(backAction);
1519 toolBar->addSeparator();
1520 toolBar->addAction(loadAction);
1521 toolBar->addAction(saveAction);
1522 toolBar->addSeparator();
1523 toolBar->addAction(singleViewAction);
1524 toolBar->addAction(splitViewAction);
1525 toolBar->addAction(fullViewAction);
1528 QMenu *menu = menuBar()->addMenu("&File");
1529 menu->addAction(loadAction);
1530 menu->addAction(saveAction);
1531 menu->addAction(saveAsAction);
1532 menu->addSeparator();
1533 menu->addAction(quitAction);
1536 menu = menuBar()->addMenu("&Edit");
1537 menu->addAction(searchAction);
1539 // create options menu
1540 menu = menuBar()->addMenu("&Option");
1541 menu->addAction(showNameAction);
1542 menu->addAction(showRangeAction);
1543 menu->addAction(showDataAction);
1544 menu->addSeparator();
1545 menu->addActions(optGroup->actions());
1546 menu->addSeparator();
1547 menu->addAction(showDebugAction);
1550 menu = menuBar()->addMenu("&Help");
1551 menu->addAction(showIntroAction);
1552 menu->addAction(showAboutAction);
1554 connect (helpText, SIGNAL (anchorClicked (const QUrl &)),
1555 helpText, SLOT (clicked (const QUrl &)) );
1557 connect(configList, SIGNAL(menuChanged(struct menu *)),
1558 helpText, SLOT(setInfo(struct menu *)));
1559 connect(configList, SIGNAL(menuSelected(struct menu *)),
1560 SLOT(changeMenu(struct menu *)));
1561 connect(configList, SIGNAL(itemSelected(struct menu *)),
1562 SLOT(changeItens(struct menu *)));
1563 connect(configList, SIGNAL(parentSelected()),
1565 connect(menuList, SIGNAL(menuChanged(struct menu *)),
1566 helpText, SLOT(setInfo(struct menu *)));
1567 connect(menuList, SIGNAL(menuSelected(struct menu *)),
1568 SLOT(changeMenu(struct menu *)));
1570 connect(configList, SIGNAL(gotFocus(struct menu *)),
1571 helpText, SLOT(setInfo(struct menu *)));
1572 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1573 helpText, SLOT(setInfo(struct menu *)));
1574 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1575 SLOT(listFocusChanged(void)));
1576 connect(helpText, SIGNAL(menuSelected(struct menu *)),
1577 SLOT(setMenuLink(struct menu *)));
1579 QString listMode = configSettings->value("/listMode", "symbol").toString();
1580 if (listMode == "single")
1582 else if (listMode == "full")
1584 else /*if (listMode == "split")*/
1587 // UI setup done, restore splitter positions
1588 QList<int> sizes = configSettings->readSizes("/split1", &ok);
1590 split1->setSizes(sizes);
1592 sizes = configSettings->readSizes("/split2", &ok);
1594 split2->setSizes(sizes);
1597 void ConfigMainWindow::loadConfig(void)
1603 str = QFileDialog::getOpenFileName(this, "", configname);
1607 ba = str.toLocal8Bit();
1610 if (conf_read(name))
1611 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1614 configname = xstrdup(name);
1616 ConfigView::updateListAll();
1619 bool ConfigMainWindow::saveConfig(void)
1621 if (conf_write(configname)) {
1622 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1625 conf_write_autoconf(0);
1630 void ConfigMainWindow::saveConfigAs(void)
1636 str = QFileDialog::getSaveFileName(this, "", configname);
1640 ba = str.toLocal8Bit();
1643 if (conf_write(name)) {
1644 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1646 conf_write_autoconf(0);
1649 configname = xstrdup(name);
1652 void ConfigMainWindow::searchConfig(void)
1655 searchWindow = new ConfigSearchWindow(this);
1656 searchWindow->show();
1659 void ConfigMainWindow::changeItens(struct menu *menu)
1661 configList->setRootMenu(menu);
1664 void ConfigMainWindow::changeMenu(struct menu *menu)
1666 menuList->setRootMenu(menu);
1669 void ConfigMainWindow::setMenuLink(struct menu *menu)
1671 struct menu *parent;
1672 ConfigList* list = NULL;
1675 if (configList->menuSkip(menu))
1678 switch (configList->mode) {
1681 parent = menu_get_parent_menu(menu);
1684 list->setRootMenu(parent);
1687 if (menu->flags & MENU_ROOT) {
1688 menuList->setRootMenu(menu);
1689 configList->clearSelection();
1692 parent = menu_get_parent_menu(menu->parent);
1696 /* Select the config view */
1697 item = configList->findConfigItem(parent);
1699 configList->setSelected(item, true);
1700 configList->scrollToItem(item);
1703 menuList->setRootMenu(parent);
1704 menuList->clearSelection();
1716 item = list->findConfigItem(menu);
1718 list->setSelected(item, true);
1719 list->scrollToItem(item);
1721 helpText->setInfo(menu);
1726 void ConfigMainWindow::listFocusChanged(void)
1728 if (menuList->mode == menuMode)
1729 configList->clearSelection();
1732 void ConfigMainWindow::goBack(void)
1734 if (configList->rootEntry == &rootmenu)
1737 configList->setParentMenu();
1740 void ConfigMainWindow::showSingleView(void)
1742 singleViewAction->setEnabled(false);
1743 singleViewAction->setChecked(true);
1744 splitViewAction->setEnabled(true);
1745 splitViewAction->setChecked(false);
1746 fullViewAction->setEnabled(true);
1747 fullViewAction->setChecked(false);
1749 backAction->setEnabled(true);
1752 menuList->setRootMenu(0);
1753 configList->mode = singleMode;
1754 if (configList->rootEntry == &rootmenu)
1755 configList->updateListAll();
1757 configList->setRootMenu(&rootmenu);
1758 configList->setFocus();
1761 void ConfigMainWindow::showSplitView(void)
1763 singleViewAction->setEnabled(true);
1764 singleViewAction->setChecked(false);
1765 splitViewAction->setEnabled(false);
1766 splitViewAction->setChecked(true);
1767 fullViewAction->setEnabled(true);
1768 fullViewAction->setChecked(false);
1770 backAction->setEnabled(false);
1772 configList->mode = menuMode;
1773 if (configList->rootEntry == &rootmenu)
1774 configList->updateListAll();
1776 configList->setRootMenu(&rootmenu);
1777 configList->setAllOpen(true);
1778 configApp->processEvents();
1779 menuList->mode = symbolMode;
1780 menuList->setRootMenu(&rootmenu);
1781 menuList->setAllOpen(true);
1783 menuList->setFocus();
1786 void ConfigMainWindow::showFullView(void)
1788 singleViewAction->setEnabled(true);
1789 singleViewAction->setChecked(false);
1790 splitViewAction->setEnabled(true);
1791 splitViewAction->setChecked(false);
1792 fullViewAction->setEnabled(false);
1793 fullViewAction->setChecked(true);
1795 backAction->setEnabled(false);
1798 menuList->setRootMenu(0);
1799 configList->mode = fullMode;
1800 if (configList->rootEntry == &rootmenu)
1801 configList->updateListAll();
1803 configList->setRootMenu(&rootmenu);
1804 configList->setFocus();
1808 * ask for saving configuration before quitting
1810 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1812 if (!conf_get_changed()) {
1816 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1817 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1818 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1819 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1820 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1821 switch (mb.exec()) {
1822 case QMessageBox::Yes:
1828 case QMessageBox::No:
1831 case QMessageBox::Cancel:
1837 void ConfigMainWindow::showIntro(void)
1839 static const QString str = "Welcome to the qconf graphical configuration tool.\n\n"
1840 "For each option, a blank box indicates the feature is disabled, a check\n"
1841 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1842 "as a module. Clicking on the box will cycle through the three states.\n\n"
1843 "If you do not see an option (e.g., a device driver) that you believe\n"
1844 "should be present, try turning on Show All Options under the Options menu.\n"
1845 "Although there is no cross reference yet to help you figure out what other\n"
1846 "options must be enabled to support the option you are interested in, you can\n"
1847 "still view the help of a grayed-out option.\n\n"
1848 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1849 "which you can then match by examining other options.\n\n";
1851 QMessageBox::information(this, "qconf", str);
1854 void ConfigMainWindow::showAbout(void)
1856 static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
1857 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
1858 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1860 QMessageBox::information(this, "qconf", str);
1863 void ConfigMainWindow::saveSettings(void)
1865 configSettings->setValue("/window x", pos().x());
1866 configSettings->setValue("/window y", pos().y());
1867 configSettings->setValue("/window width", size().width());
1868 configSettings->setValue("/window height", size().height());
1871 switch(configList->mode) {
1887 configSettings->setValue("/listMode", entry);
1889 configSettings->writeSizes("/split1", split1->sizes());
1890 configSettings->writeSizes("/split2", split2->sizes());
1893 void ConfigMainWindow::conf_changed(void)
1896 saveAction->setEnabled(conf_get_changed());
1899 void fixup_rootmenu(struct menu *menu)
1902 static int menu_cnt = 0;
1904 menu->flags |= MENU_ROOT;
1905 for (child = menu->list; child; child = child->next) {
1906 if (child->prompt && child->prompt->type == P_MENU) {
1908 fixup_rootmenu(child);
1910 } else if (!menu_cnt)
1911 fixup_rootmenu(child);
1915 static const char *progname;
1917 static void usage(void)
1919 printf("%s [-s] <config>\n", progname);
1923 int main(int ac, char** av)
1925 ConfigMainWindow* v;
1929 configApp = new QApplication(ac, av);
1930 if (ac > 1 && av[1][0] == '-') {
1933 conf_set_message_callback(NULL);
1946 fixup_rootmenu(&rootmenu);
1948 //zconfdump(stdout);
1950 configSettings = new ConfigSettings();
1951 configSettings->beginGroup("/kconfig/qconf");
1952 v = new ConfigMainWindow();
1954 //zconfdump(stdout);
1955 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1956 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1960 configSettings->endGroup();
1961 delete configSettings;