2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>
4 * Released under the terms of the GNU GPL v2.0.
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>
42 static QApplication *configApp;
43 static ConfigSettings *configSettings;
45 QAction *ConfigMainWindow::saveAction;
47 static inline QString qgettext(const char* str)
49 return QString::fromLocal8Bit(gettext(str));
52 static inline QString qgettext(const QString& str)
54 return QString::fromLocal8Bit(gettext(str.toLatin1()));
57 ConfigSettings::ConfigSettings()
58 : QSettings("kernel.org", "qconf")
63 * Reads a list of integer values from the application settings.
65 QList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
68 QStringList entryList = value(key).toStringList();
69 QStringList::Iterator it;
71 for (it = entryList.begin(); it != entryList.end(); ++it)
72 result.push_back((*it).toInt());
78 * Writes a list of integer values to the application settings.
80 bool ConfigSettings::writeSizes(const QString& key, const QList<int>& value)
82 QStringList stringList;
83 QList<int>::ConstIterator it;
85 for (it = value.begin(); it != value.end(); ++it)
86 stringList.push_back(QString::number(*it));
87 setValue(key, stringList);
95 * TODO check the value
97 void ConfigItem::okRename(int col)
102 * update the displayed of a menu entry
104 void ConfigItem::updateMenu(void)
108 struct property *prop;
115 setPixmap(promptColIdx, list->menuBackPix);
122 prompt = _(menu_get_prompt(menu));
124 if (prop) switch (prop->type) {
126 if (list->mode == singleMode || list->mode == symbolMode) {
127 /* a menuconfig entry is displayed differently
128 * depending whether it's at the view root or a child.
130 if (sym && list->rootEntry == menu)
132 setPixmap(promptColIdx, list->menuPix);
136 setPixmap(promptColIdx, QIcon());
140 setPixmap(promptColIdx, QIcon());
148 setText(nameColIdx, QString::fromLocal8Bit(sym->name));
150 type = sym_get_type(sym);
156 if (!sym_is_changable(sym) && list->optMode == normalOpt) {
157 setPixmap(promptColIdx, QIcon());
158 setText(noColIdx, QString::null);
159 setText(modColIdx, QString::null);
160 setText(yesColIdx, QString::null);
163 expr = sym_get_tristate_value(sym);
166 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
167 setPixmap(promptColIdx, list->choiceYesPix);
169 setPixmap(promptColIdx, list->symbolYesPix);
170 setText(yesColIdx, "Y");
174 setPixmap(promptColIdx, list->symbolModPix);
175 setText(modColIdx, "M");
179 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
180 setPixmap(promptColIdx, list->choiceNoPix);
182 setPixmap(promptColIdx, list->symbolNoPix);
183 setText(noColIdx, "N");
188 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
190 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
192 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
194 setText(dataColIdx, QChar(ch));
201 data = sym_get_string_value(sym);
203 setText(dataColIdx, data);
204 if (type == S_STRING)
205 prompt = QString("%1: %2").arg(prompt).arg(data);
207 prompt = QString("(%2) %1").arg(prompt).arg(data);
210 if (!sym_has_value(sym) && visible)
211 prompt += _(" (NEW)");
213 setText(promptColIdx, prompt);
216 void ConfigItem::testUpdateMenu(bool v)
224 sym_calc_value(menu->sym);
225 if (menu->flags & MENU_CHANGED) {
226 /* the menu entry changed, so update all list items */
227 menu->flags &= ~MENU_CHANGED;
228 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
230 } else if (listView()->updateAll)
236 * construct a menu entry
238 void ConfigItem::init(void)
241 ConfigList* list = listView();
242 nextItem = (ConfigItem*)menu->data;
245 if (list->mode != fullMode)
247 sym_calc_value(menu->sym);
253 * destruct a menu entry
255 ConfigItem::~ConfigItem(void)
258 ConfigItem** ip = (ConfigItem**)&menu->data;
259 for (; *ip; ip = &(*ip)->nextItem) {
268 ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
271 connect(this, SIGNAL(editingFinished()), SLOT(hide()));
274 void ConfigLineEdit::show(ConfigItem* i)
277 if (sym_get_string_value(item->menu->sym))
278 setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
280 setText(QString::null);
285 void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
292 sym_set_string_value(item->menu->sym, text().toLatin1());
293 parent()->updateList(item);
296 Parent::keyPressEvent(e);
300 parent()->list->setFocus();
304 ConfigList::ConfigList(ConfigView* p, const char *name)
307 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
308 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
309 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
310 showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt),
311 rootEntry(0), headerPopup(0)
316 setSortingEnabled(false);
317 setRootIsDecorated(true);
319 setVerticalScrollMode(ScrollPerPixel);
320 setHorizontalScrollMode(ScrollPerPixel);
322 setHeaderLabels(QStringList() << _("Option") << _("Name") << "N" << "M" << "Y" << _("Value"));
324 connect(this, SIGNAL(itemSelectionChanged(void)),
325 SLOT(updateSelection(void)));
328 configSettings->beginGroup(name);
329 showName = configSettings->value("/showName", false).toBool();
330 showRange = configSettings->value("/showRange", false).toBool();
331 showData = configSettings->value("/showData", false).toBool();
332 optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt();
333 configSettings->endGroup();
334 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
337 addColumn(promptColIdx);
342 bool ConfigList::menuSkip(struct menu *menu)
344 if (optMode == normalOpt && menu_is_visible(menu))
346 if (optMode == promptOpt && menu_has_prompt(menu))
348 if (optMode == allOpt)
353 void ConfigList::reinit(void)
355 removeColumn(dataColIdx);
356 removeColumn(yesColIdx);
357 removeColumn(modColIdx);
358 removeColumn(noColIdx);
359 removeColumn(nameColIdx);
362 addColumn(nameColIdx);
365 addColumn(modColIdx);
366 addColumn(yesColIdx);
369 addColumn(dataColIdx);
374 void ConfigList::saveSettings(void)
376 if (!objectName().isEmpty()) {
377 configSettings->beginGroup(objectName());
378 configSettings->setValue("/showName", showName);
379 configSettings->setValue("/showRange", showRange);
380 configSettings->setValue("/showData", showData);
381 configSettings->setValue("/optionMode", (int)optMode);
382 configSettings->endGroup();
386 ConfigItem* ConfigList::findConfigItem(struct menu *menu)
388 ConfigItem* item = (ConfigItem*)menu->data;
390 for (; item; item = item->nextItem) {
391 if (this == item->listView())
398 void ConfigList::updateSelection(void)
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 _showDebug = 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>";
1151 debug += prop_get_type_name(prop->type);
1153 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1157 if (sym_is_choice(sym)) {
1158 debug += "choice: ";
1159 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1164 debug += "unknown property: ";
1165 debug += prop_get_type_name(prop->type);
1168 if (prop->visible.expr) {
1169 debug += " dep: ";
1170 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1179 QString ConfigInfoView::print_filter(const QString &str)
1181 QRegExp re("[<>&\"\\n]");
1183 for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
1184 switch (res[i].toLatin1()) {
1186 res.replace(i, 1, "<");
1190 res.replace(i, 1, ">");
1194 res.replace(i, 1, "&");
1198 res.replace(i, 1, """);
1202 res.replace(i, 1, "<br>");
1210 void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
1212 QString* text = reinterpret_cast<QString*>(data);
1213 QString str2 = print_filter(str);
1215 if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1216 *text += QString().sprintf("<a href=\"s%p\">", sym);
1223 QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
1225 QMenu* popup = Parent::createStandardContextMenu(pos);
1226 QAction* action = new QAction(_("Show Debug Info"), popup);
1227 action->setCheckable(true);
1228 connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1229 connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
1230 action->setChecked(showDebug());
1231 popup->addSeparator();
1232 popup->addAction(action);
1236 void ConfigInfoView::contextMenuEvent(QContextMenuEvent *e)
1238 Parent::contextMenuEvent(e);
1241 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
1242 : Parent(parent), result(NULL)
1244 setObjectName(name);
1245 setWindowTitle("Search Config");
1247 QVBoxLayout* layout1 = new QVBoxLayout(this);
1248 layout1->setContentsMargins(11, 11, 11, 11);
1249 layout1->setSpacing(6);
1250 QHBoxLayout* layout2 = new QHBoxLayout(0);
1251 layout2->setContentsMargins(0, 0, 0, 0);
1252 layout2->setSpacing(6);
1253 layout2->addWidget(new QLabel(_("Find:"), this));
1254 editField = new QLineEdit(this);
1255 connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1256 layout2->addWidget(editField);
1257 searchButton = new QPushButton(_("Search"), this);
1258 searchButton->setAutoDefault(false);
1259 connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1260 layout2->addWidget(searchButton);
1261 layout1->addLayout(layout2);
1263 split = new QSplitter(this);
1264 split->setOrientation(Qt::Vertical);
1265 list = new ConfigView(split, name);
1266 list->list->mode = listMode;
1267 info = new ConfigInfoView(split, name);
1268 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1269 info, SLOT(setInfo(struct menu *)));
1270 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1271 parent, SLOT(setMenuLink(struct menu *)));
1273 layout1->addWidget(split);
1280 configSettings->beginGroup(name);
1281 width = configSettings->value("/window width", parent->width() / 2).toInt();
1282 height = configSettings->value("/window height", parent->height() / 2).toInt();
1283 resize(width, height);
1284 x = configSettings->value("/window x");
1285 y = configSettings->value("/window y");
1286 if ((x.isValid())&&(y.isValid()))
1287 move(x.toInt(), y.toInt());
1288 QList<int> sizes = configSettings->readSizes("/split", &ok);
1290 split->setSizes(sizes);
1291 configSettings->endGroup();
1292 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1296 void ConfigSearchWindow::saveSettings(void)
1298 if (!objectName().isEmpty()) {
1299 configSettings->beginGroup(objectName());
1300 configSettings->setValue("/window x", pos().x());
1301 configSettings->setValue("/window y", pos().y());
1302 configSettings->setValue("/window width", size().width());
1303 configSettings->setValue("/window height", size().height());
1304 configSettings->writeSizes("/split", split->sizes());
1305 configSettings->endGroup();
1309 void ConfigSearchWindow::search(void)
1312 struct property *prop;
1313 ConfigItem *lastItem = NULL;
1316 list->list->clear();
1319 result = sym_re_search(editField->text().toLatin1());
1322 for (p = result; *p; p++) {
1323 for_all_prompts((*p), prop)
1324 lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1325 menu_is_visible(prop->menu));
1330 * Construct the complete config widget
1332 ConfigMainWindow::ConfigMainWindow(void)
1341 QDesktopWidget *d = configApp->desktop();
1342 snprintf(title, sizeof(title), "%s%s",
1343 rootmenu.prompt->text,
1346 setWindowTitle(title);
1348 width = configSettings->value("/window width", d->width() - 64).toInt();
1349 height = configSettings->value("/window height", d->height() - 64).toInt();
1350 resize(width, height);
1351 x = configSettings->value("/window x");
1352 y = configSettings->value("/window y");
1353 if ((x.isValid())&&(y.isValid()))
1354 move(x.toInt(), y.toInt());
1356 split1 = new QSplitter(this);
1357 split1->setOrientation(Qt::Horizontal);
1358 setCentralWidget(split1);
1360 menuView = new ConfigView(split1, "menu");
1361 menuList = menuView->list;
1363 split2 = new QSplitter(split1);
1364 split2->setOrientation(Qt::Vertical);
1366 // create config tree
1367 configView = new ConfigView(split2, "config");
1368 configList = configView->list;
1370 helpText = new ConfigInfoView(split2, "help");
1372 setTabOrder(configList, helpText);
1373 configList->setFocus();
1376 toolBar = new QToolBar("Tools", this);
1377 addToolBar(toolBar);
1379 backAction = new QAction(QPixmap(xpm_back), _("Back"), this);
1380 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
1381 backAction->setEnabled(false);
1382 QAction *quitAction = new QAction(_("&Quit"), this);
1383 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
1384 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
1385 QAction *loadAction = new QAction(QPixmap(xpm_load), _("&Load"), this);
1386 loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
1387 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
1388 saveAction = new QAction(QPixmap(xpm_save), _("&Save"), this);
1389 saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
1390 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
1391 conf_set_changed_callback(conf_changed);
1392 // Set saveAction's initial state
1394 QAction *saveAsAction = new QAction(_("Save &As..."), this);
1395 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
1396 QAction *searchAction = new QAction(_("&Find"), this);
1397 searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
1398 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
1399 singleViewAction = new QAction(QPixmap(xpm_single_view), _("Single View"), this);
1400 singleViewAction->setCheckable(true);
1401 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
1402 splitViewAction = new QAction(QPixmap(xpm_split_view), _("Split View"), this);
1403 splitViewAction->setCheckable(true);
1404 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
1405 fullViewAction = new QAction(QPixmap(xpm_tree_view), _("Full View"), this);
1406 fullViewAction->setCheckable(true);
1407 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
1409 QAction *showNameAction = new QAction(_("Show Name"), this);
1410 showNameAction->setCheckable(true);
1411 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1412 showNameAction->setChecked(configView->showName());
1413 QAction *showRangeAction = new QAction(_("Show Range"), this);
1414 showRangeAction->setCheckable(true);
1415 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1416 QAction *showDataAction = new QAction(_("Show Data"), this);
1417 showDataAction->setCheckable(true);
1418 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1420 QActionGroup *optGroup = new QActionGroup(this);
1421 optGroup->setExclusive(true);
1422 connect(optGroup, SIGNAL(triggered(QAction*)), configView,
1423 SLOT(setOptionMode(QAction *)));
1424 connect(optGroup, SIGNAL(triggered(QAction *)), menuView,
1425 SLOT(setOptionMode(QAction *)));
1427 configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup);
1428 configView->showAllAction = new QAction(_("Show All Options"), optGroup);
1429 configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup);
1430 configView->showNormalAction->setCheckable(true);
1431 configView->showAllAction->setCheckable(true);
1432 configView->showPromptAction->setCheckable(true);
1434 QAction *showDebugAction = new QAction( _("Show Debug Info"), this);
1435 showDebugAction->setCheckable(true);
1436 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1437 showDebugAction->setChecked(helpText->showDebug());
1439 QAction *showIntroAction = new QAction( _("Introduction"), this);
1440 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
1441 QAction *showAboutAction = new QAction( _("About"), this);
1442 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
1445 toolBar->addAction(backAction);
1446 toolBar->addSeparator();
1447 toolBar->addAction(loadAction);
1448 toolBar->addAction(saveAction);
1449 toolBar->addSeparator();
1450 toolBar->addAction(singleViewAction);
1451 toolBar->addAction(splitViewAction);
1452 toolBar->addAction(fullViewAction);
1454 // create config menu
1455 QMenu* config = menu->addMenu(_("&File"));
1456 config->addAction(loadAction);
1457 config->addAction(saveAction);
1458 config->addAction(saveAsAction);
1459 config->addSeparator();
1460 config->addAction(quitAction);
1463 QMenu* editMenu = menu->addMenu(_("&Edit"));
1464 editMenu->addAction(searchAction);
1466 // create options menu
1467 QMenu* optionMenu = menu->addMenu(_("&Option"));
1468 optionMenu->addAction(showNameAction);
1469 optionMenu->addAction(showRangeAction);
1470 optionMenu->addAction(showDataAction);
1471 optionMenu->addSeparator();
1472 optionMenu->addActions(optGroup->actions());
1473 optionMenu->addSeparator();
1476 menu->addSeparator();
1477 QMenu* helpMenu = menu->addMenu(_("&Help"));
1478 helpMenu->addAction(showIntroAction);
1479 helpMenu->addAction(showAboutAction);
1481 connect(configList, SIGNAL(menuChanged(struct menu *)),
1482 helpText, SLOT(setInfo(struct menu *)));
1483 connect(configList, SIGNAL(menuSelected(struct menu *)),
1484 SLOT(changeMenu(struct menu *)));
1485 connect(configList, SIGNAL(parentSelected()),
1487 connect(menuList, SIGNAL(menuChanged(struct menu *)),
1488 helpText, SLOT(setInfo(struct menu *)));
1489 connect(menuList, SIGNAL(menuSelected(struct menu *)),
1490 SLOT(changeMenu(struct menu *)));
1492 connect(configList, SIGNAL(gotFocus(struct menu *)),
1493 helpText, SLOT(setInfo(struct menu *)));
1494 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1495 helpText, SLOT(setInfo(struct menu *)));
1496 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1497 SLOT(listFocusChanged(void)));
1498 connect(helpText, SIGNAL(menuSelected(struct menu *)),
1499 SLOT(setMenuLink(struct menu *)));
1501 QString listMode = configSettings->value("/listMode", "symbol").toString();
1502 if (listMode == "single")
1504 else if (listMode == "full")
1506 else /*if (listMode == "split")*/
1509 // UI setup done, restore splitter positions
1510 QList<int> sizes = configSettings->readSizes("/split1", &ok);
1512 split1->setSizes(sizes);
1514 sizes = configSettings->readSizes("/split2", &ok);
1516 split2->setSizes(sizes);
1519 void ConfigMainWindow::loadConfig(void)
1521 QString s = QFileDialog::getOpenFileName(this, "", conf_get_configname());
1524 if (conf_read(QFile::encodeName(s)))
1525 QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
1526 ConfigView::updateListAll();
1529 bool ConfigMainWindow::saveConfig(void)
1531 if (conf_write(NULL)) {
1532 QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
1538 void ConfigMainWindow::saveConfigAs(void)
1540 QString s = QFileDialog::getSaveFileName(this, "", conf_get_configname());
1546 void ConfigMainWindow::searchConfig(void)
1549 searchWindow = new ConfigSearchWindow(this, "search");
1550 searchWindow->show();
1553 void ConfigMainWindow::changeMenu(struct menu *menu)
1555 configList->setRootMenu(menu);
1556 if (configList->rootEntry->parent == &rootmenu)
1557 backAction->setEnabled(false);
1559 backAction->setEnabled(true);
1562 void ConfigMainWindow::setMenuLink(struct menu *menu)
1564 struct menu *parent;
1565 ConfigList* list = NULL;
1568 if (configList->menuSkip(menu))
1571 switch (configList->mode) {
1574 parent = menu_get_parent_menu(menu);
1577 list->setRootMenu(parent);
1580 if (menu->flags & MENU_ROOT) {
1581 configList->setRootMenu(menu);
1582 configList->clearSelection();
1586 parent = menu_get_parent_menu(menu->parent);
1589 item = menuList->findConfigItem(parent);
1591 item->setSelected(true);
1592 menuList->scrollToItem(item);
1594 list->setRootMenu(parent);
1605 item = list->findConfigItem(menu);
1607 item->setSelected(true);
1608 list->scrollToItem(item);
1614 void ConfigMainWindow::listFocusChanged(void)
1616 if (menuList->mode == menuMode)
1617 configList->clearSelection();
1620 void ConfigMainWindow::goBack(void)
1622 ConfigItem* item, *oldSelection;
1624 configList->setParentMenu();
1625 if (configList->rootEntry == &rootmenu)
1626 backAction->setEnabled(false);
1627 item = (ConfigItem*)menuList->selectedItems().first();
1628 oldSelection = item;
1630 if (item->menu == configList->rootEntry) {
1631 oldSelection->setSelected(false);
1632 item->setSelected(true);
1635 item = (ConfigItem*)item->parent();
1639 void ConfigMainWindow::showSingleView(void)
1641 singleViewAction->setEnabled(false);
1642 singleViewAction->setChecked(true);
1643 splitViewAction->setEnabled(true);
1644 splitViewAction->setChecked(false);
1645 fullViewAction->setEnabled(true);
1646 fullViewAction->setChecked(false);
1649 menuList->setRootMenu(0);
1650 configList->mode = singleMode;
1651 if (configList->rootEntry == &rootmenu)
1652 configList->updateListAll();
1654 configList->setRootMenu(&rootmenu);
1655 configList->setFocus();
1658 void ConfigMainWindow::showSplitView(void)
1660 singleViewAction->setEnabled(true);
1661 singleViewAction->setChecked(false);
1662 splitViewAction->setEnabled(false);
1663 splitViewAction->setChecked(true);
1664 fullViewAction->setEnabled(true);
1665 fullViewAction->setChecked(false);
1667 configList->mode = symbolMode;
1668 if (configList->rootEntry == &rootmenu)
1669 configList->updateListAll();
1671 configList->setRootMenu(&rootmenu);
1672 configList->setAllOpen(true);
1673 configApp->processEvents();
1674 menuList->mode = menuMode;
1675 menuList->setRootMenu(&rootmenu);
1676 menuList->setAllOpen(true);
1678 menuList->setFocus();
1681 void ConfigMainWindow::showFullView(void)
1683 singleViewAction->setEnabled(true);
1684 singleViewAction->setChecked(false);
1685 splitViewAction->setEnabled(true);
1686 splitViewAction->setChecked(false);
1687 fullViewAction->setEnabled(false);
1688 fullViewAction->setChecked(true);
1691 menuList->setRootMenu(0);
1692 configList->mode = fullMode;
1693 if (configList->rootEntry == &rootmenu)
1694 configList->updateListAll();
1696 configList->setRootMenu(&rootmenu);
1697 configList->setFocus();
1701 * ask for saving configuration before quitting
1702 * TODO ask only when something changed
1704 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1706 if (!conf_get_changed()) {
1710 QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
1711 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1712 mb.setButtonText(QMessageBox::Yes, _("&Save Changes"));
1713 mb.setButtonText(QMessageBox::No, _("&Discard Changes"));
1714 mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
1715 switch (mb.exec()) {
1716 case QMessageBox::Yes:
1722 case QMessageBox::No:
1725 case QMessageBox::Cancel:
1731 void ConfigMainWindow::showIntro(void)
1733 static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
1734 "For each option, a blank box indicates the feature is disabled, a check\n"
1735 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1736 "as a module. Clicking on the box will cycle through the three states.\n\n"
1737 "If you do not see an option (e.g., a device driver) that you believe\n"
1738 "should be present, try turning on Show All Options under the Options menu.\n"
1739 "Although there is no cross reference yet to help you figure out what other\n"
1740 "options must be enabled to support the option you are interested in, you can\n"
1741 "still view the help of a grayed-out option.\n\n"
1742 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1743 "which you can then match by examining other options.\n\n");
1745 QMessageBox::information(this, "qconf", str);
1748 void ConfigMainWindow::showAbout(void)
1750 static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
1751 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
1752 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
1754 QMessageBox::information(this, "qconf", str);
1757 void ConfigMainWindow::saveSettings(void)
1759 configSettings->setValue("/window x", pos().x());
1760 configSettings->setValue("/window y", pos().y());
1761 configSettings->setValue("/window width", size().width());
1762 configSettings->setValue("/window height", size().height());
1765 switch(configList->mode) {
1781 configSettings->setValue("/listMode", entry);
1783 configSettings->writeSizes("/split1", split1->sizes());
1784 configSettings->writeSizes("/split2", split2->sizes());
1787 void ConfigMainWindow::conf_changed(void)
1790 saveAction->setEnabled(conf_get_changed());
1793 void fixup_rootmenu(struct menu *menu)
1796 static int menu_cnt = 0;
1798 menu->flags |= MENU_ROOT;
1799 for (child = menu->list; child; child = child->next) {
1800 if (child->prompt && child->prompt->type == P_MENU) {
1802 fixup_rootmenu(child);
1804 } else if (!menu_cnt)
1805 fixup_rootmenu(child);
1809 static const char *progname;
1811 static void usage(void)
1813 printf(_("%s [-s] <config>\n").toLatin1().constData(), progname);
1817 int main(int ac, char** av)
1819 ConfigMainWindow* v;
1822 bindtextdomain(PACKAGE, LOCALEDIR);
1823 textdomain(PACKAGE);
1826 configApp = new QApplication(ac, av);
1827 if (ac > 1 && av[1][0] == '-') {
1830 conf_set_message_callback(NULL);
1843 fixup_rootmenu(&rootmenu);
1845 //zconfdump(stdout);
1847 configSettings = new ConfigSettings();
1848 configSettings->beginGroup("/kconfig/qconf");
1849 v = new ConfigMainWindow();
1851 //zconfdump(stdout);
1852 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1853 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1857 configSettings->endGroup();
1858 delete configSettings;