2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
6 #include <qapplication.h>
7 #include <qmainwindow.h>
11 #include <qsplitter.h>
12 #include <qlistview.h>
13 #include <qtextbrowser.h>
14 #include <qlineedit.h>
16 #include <qpushbutton.h>
18 #include <qmessagebox.h>
21 #include <qfiledialog.h>
22 #include <qdragobject.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(gettext(str));
48 static inline QString qgettext(const QString& str)
50 return QString::fromLocal8Bit(gettext(str.latin1()));
54 * Reads a list of integer values from the application settings.
56 QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
58 QValueList<int> result;
59 QStringList entryList = readListEntry(key, ok);
61 QStringList::Iterator it;
62 for (it = entryList.begin(); it != entryList.end(); ++it)
63 result.push_back((*it).toInt());
70 * Writes a list of integer values to the application settings.
72 bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
74 QStringList stringList;
75 QValueList<int>::ConstIterator it;
77 for (it = value.begin(); it != value.end(); ++it)
78 stringList.push_back(QString::number(*it));
79 return writeEntry(key, stringList);
86 * TODO check the value
88 void ConfigItem::okRename(int col)
90 Parent::okRename(col);
91 sym_set_string_value(menu->sym, text(dataColIdx).latin1());
92 listView()->updateList(this);
97 * update the displayed of a menu entry
99 void ConfigItem::updateMenu(void)
103 struct property *prop;
110 setPixmap(promptColIdx, list->menuBackPix);
117 prompt = QString::fromLocal8Bit(menu_get_prompt(menu));
119 if (prop) switch (prop->type) {
121 if (list->mode == singleMode || list->mode == symbolMode) {
122 /* a menuconfig entry is displayed differently
123 * depending whether it's at the view root or a child.
125 if (sym && list->rootEntry == menu)
127 setPixmap(promptColIdx, list->menuPix);
131 setPixmap(promptColIdx, 0);
135 setPixmap(promptColIdx, 0);
143 setText(nameColIdx, QString::fromLocal8Bit(sym->name));
145 type = sym_get_type(sym);
151 if (!sym_is_changable(sym) && !list->showAll) {
152 setPixmap(promptColIdx, 0);
153 setText(noColIdx, QString::null);
154 setText(modColIdx, QString::null);
155 setText(yesColIdx, QString::null);
158 expr = sym_get_tristate_value(sym);
161 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
162 setPixmap(promptColIdx, list->choiceYesPix);
164 setPixmap(promptColIdx, list->symbolYesPix);
165 setText(yesColIdx, "Y");
169 setPixmap(promptColIdx, list->symbolModPix);
170 setText(modColIdx, "M");
174 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
175 setPixmap(promptColIdx, list->choiceNoPix);
177 setPixmap(promptColIdx, list->symbolNoPix);
178 setText(noColIdx, "N");
183 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
185 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
187 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
189 setText(dataColIdx, QChar(ch));
196 data = sym_get_string_value(sym);
198 #if QT_VERSION >= 300
199 int i = list->mapIdx(dataColIdx);
201 setRenameEnabled(i, TRUE);
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)
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)
234 void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
236 ConfigList* list = listView();
239 if (isSelected() && !list->hasFocus() && list->mode == menuMode)
240 Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
242 Parent::paintCell(p, cg, column, width, align);
244 Parent::paintCell(p, list->disabledColorGroup, column, width, align);
248 * construct a menu entry
250 void ConfigItem::init(void)
253 ConfigList* list = listView();
254 nextItem = (ConfigItem*)menu->data;
257 if (list->mode != fullMode)
259 sym_calc_value(menu->sym);
265 * destruct a menu entry
267 ConfigItem::~ConfigItem(void)
270 ConfigItem** ip = (ConfigItem**)&menu->data;
271 for (; *ip; ip = &(*ip)->nextItem) {
280 ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
283 connect(this, SIGNAL(lostFocus()), SLOT(hide()));
286 void ConfigLineEdit::show(ConfigItem* i)
289 if (sym_get_string_value(item->menu->sym))
290 setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
292 setText(QString::null);
297 void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
304 sym_set_string_value(item->menu->sym, text().latin1());
305 parent()->updateList(item);
308 Parent::keyPressEvent(e);
312 parent()->list->setFocus();
316 ConfigList::ConfigList(ConfigView* p, const char *name)
319 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
320 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
321 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
322 showAll(false), showName(false), showRange(false), showData(false),
323 rootEntry(0), headerPopup(0)
328 setRootIsDecorated(TRUE);
329 disabledColorGroup = palette().active();
330 disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
331 inactivedColorGroup = palette().active();
332 inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
334 connect(this, SIGNAL(selectionChanged(void)),
335 SLOT(updateSelection(void)));
338 configSettings->beginGroup(name);
339 showAll = configSettings->readBoolEntry("/showAll", false);
340 showName = configSettings->readBoolEntry("/showName", false);
341 showRange = configSettings->readBoolEntry("/showRange", false);
342 showData = configSettings->readBoolEntry("/showData", false);
343 configSettings->endGroup();
344 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
347 for (i = 0; i < colNr; i++)
348 colMap[i] = colRevMap[i] = -1;
349 addColumn(promptColIdx, "Option");
354 void ConfigList::reinit(void)
356 removeColumn(dataColIdx);
357 removeColumn(yesColIdx);
358 removeColumn(modColIdx);
359 removeColumn(noColIdx);
360 removeColumn(nameColIdx);
363 addColumn(nameColIdx, "Name");
365 addColumn(noColIdx, "N");
366 addColumn(modColIdx, "M");
367 addColumn(yesColIdx, "Y");
370 addColumn(dataColIdx, "Value");
375 void ConfigList::saveSettings(void)
378 configSettings->beginGroup(name());
379 configSettings->writeEntry("/showName", showName);
380 configSettings->writeEntry("/showRange", showRange);
381 configSettings->writeEntry("/showData", showData);
382 configSettings->writeEntry("/showAll", showAll);
383 configSettings->endGroup();
387 ConfigItem* ConfigList::findConfigItem(struct menu *menu)
389 ConfigItem* item = (ConfigItem*)menu->data;
391 for (; item; item = item->nextItem) {
392 if (this == item->listView())
399 void ConfigList::updateSelection(void)
404 ConfigItem* item = (ConfigItem*)selectedItem();
409 emit menuChanged(menu);
412 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
413 if (mode == menuMode && type == P_MENU)
414 emit menuSelected(menu);
417 void ConfigList::updateList(ConfigItem* item)
419 ConfigItem* last = 0;
422 if (mode != listMode)
424 QListViewItemIterator it(this);
427 for (; it.current(); ++it) {
428 item = (ConfigItem*)it.current();
431 item->testUpdateMenu(menu_is_visible(item->menu));
436 if (rootEntry != &rootmenu && (mode == singleMode ||
437 (mode == symbolMode && rootEntry->parent != &rootmenu))) {
440 item = new ConfigItem(this, 0, true);
443 if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
444 rootEntry->sym && rootEntry->prompt) {
445 item = last ? last->nextSibling() : firstChild();
447 item = new ConfigItem(this, last, rootEntry, true);
449 item->testUpdateMenu(true);
451 updateMenuList(item, rootEntry);
456 updateMenuList(this, rootEntry);
460 void ConfigList::setValue(ConfigItem* item, tristate val)
466 sym = item->menu ? item->menu->sym : 0;
470 type = sym_get_type(sym);
474 oldval = sym_get_tristate_value(sym);
476 if (!sym_set_tristate_value(sym, val))
478 if (oldval == no && item->menu->list)
480 parent()->updateList(item);
485 void ConfigList::changeValue(ConfigItem* item)
489 int type, oldexpr, newexpr;
496 if (item->menu->list)
497 item->setOpen(!item->isOpen());
501 type = sym_get_type(sym);
505 oldexpr = sym_get_tristate_value(sym);
506 newexpr = sym_toggle_tristate_value(sym);
507 if (item->menu->list) {
508 if (oldexpr == newexpr)
509 item->setOpen(!item->isOpen());
510 else if (oldexpr == no)
513 if (oldexpr != newexpr)
514 parent()->updateList(item);
519 #if QT_VERSION >= 300
520 if (colMap[dataColIdx] >= 0)
521 item->startRename(colMap[dataColIdx]);
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;
538 updateMenuList(this, 0);
541 setSelected(currentItem(), hasFocus());
542 ensureItemVisible(currentItem());
545 void ConfigList::setParentMenu(void)
548 struct menu *oldroot;
551 if (rootEntry == &rootmenu)
553 setRootMenu(menu_get_parent_menu(rootEntry->parent));
555 QListViewItemIterator it(this);
556 for (; (item = (ConfigItem*)it.current()); it++) {
557 if (item->menu == oldroot) {
558 setCurrentItem(item);
559 ensureItemVisible(item);
566 * update all the children of a menu entry
567 * removes/adds the entries from the parent widget as necessary
569 * parent: either the menu list widget or a menu entry widget
570 * menu: entry to be updated
573 void ConfigList::updateMenuList(P* parent, struct menu* menu)
582 while ((item = parent->firstChild()))
587 last = parent->firstChild();
588 if (last && !last->goParent)
590 for (child = menu->list; child; child = child->next) {
591 item = last ? last->nextSibling() : parent->firstChild();
592 type = child->prompt ? child->prompt->type : P_UNKNOWN;
596 if (!(child->flags & MENU_ROOT))
600 if (child->flags & MENU_ROOT)
607 visible = menu_is_visible(child);
608 if (showAll || visible) {
609 if (!child->sym && !child->list && !child->prompt)
611 if (!item || item->menu != child)
612 item = new ConfigItem(parent, last, child, visible);
614 item->testUpdateMenu(visible);
616 if (mode == fullMode || mode == menuMode || type != P_MENU)
617 updateMenuList(item, child);
619 updateMenuList(item, 0);
624 if (item && item->menu == child) {
625 last = parent->firstChild();
628 else while (last->nextSibling() != item)
629 last = last->nextSibling();
635 void ConfigList::keyPressEvent(QKeyEvent* ev)
637 QListViewItem* i = currentItem();
642 if (ev->key() == Key_Escape && mode != fullMode && mode != listMode) {
643 emit parentSelected();
649 Parent::keyPressEvent(ev);
652 item = (ConfigItem*)i;
657 if (item->goParent) {
658 emit parentSelected();
664 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
665 if (type == P_MENU && rootEntry != menu &&
666 mode != fullMode && mode != menuMode) {
667 emit menuSelected(menu);
683 Parent::keyPressEvent(ev);
689 void ConfigList::contentsMousePressEvent(QMouseEvent* e)
691 //QPoint p(contentsToViewport(e->pos()));
692 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
693 Parent::contentsMousePressEvent(e);
696 void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
698 QPoint p(contentsToViewport(e->pos()));
699 ConfigItem* item = (ConfigItem*)itemAt(p);
701 enum prop_type ptype;
709 x = header()->offset() + p.x();
710 idx = colRevMap[header()->sectionAt(x)];
713 pm = item->pixmap(promptColIdx);
715 int off = header()->sectionPos(0) + itemMargin() +
716 treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
717 if (x >= off && x < off + pm->width()) {
718 if (item->goParent) {
719 emit parentSelected();
723 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
724 if (ptype == P_MENU && rootEntry != menu &&
725 mode != fullMode && mode != menuMode)
726 emit menuSelected(menu);
747 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
748 Parent::contentsMouseReleaseEvent(e);
751 void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
753 //QPoint p(contentsToViewport(e->pos()));
754 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
755 Parent::contentsMouseMoveEvent(e);
758 void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
760 QPoint p(contentsToViewport(e->pos()));
761 ConfigItem* item = (ConfigItem*)itemAt(p);
763 enum prop_type ptype;
767 if (item->goParent) {
768 emit parentSelected();
774 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
775 if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
776 emit menuSelected(menu);
781 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
782 Parent::contentsMouseDoubleClickEvent(e);
785 void ConfigList::focusInEvent(QFocusEvent *e)
787 struct menu *menu = NULL;
789 Parent::focusInEvent(e);
791 ConfigItem* item = (ConfigItem *)currentItem();
793 setSelected(item, TRUE);
799 void ConfigList::contextMenuEvent(QContextMenuEvent *e)
801 if (e->y() <= header()->geometry().bottom()) {
805 headerPopup = new QPopupMenu(this);
806 action = new QAction(NULL, "Show Name", 0, this);
807 action->setToggleAction(TRUE);
808 connect(action, SIGNAL(toggled(bool)),
809 parent(), SLOT(setShowName(bool)));
810 connect(parent(), SIGNAL(showNameChanged(bool)),
811 action, SLOT(setOn(bool)));
812 action->setOn(showName);
813 action->addTo(headerPopup);
814 action = new QAction(NULL, "Show Range", 0, this);
815 action->setToggleAction(TRUE);
816 connect(action, SIGNAL(toggled(bool)),
817 parent(), SLOT(setShowRange(bool)));
818 connect(parent(), SIGNAL(showRangeChanged(bool)),
819 action, SLOT(setOn(bool)));
820 action->setOn(showRange);
821 action->addTo(headerPopup);
822 action = new QAction(NULL, "Show Data", 0, this);
823 action->setToggleAction(TRUE);
824 connect(action, SIGNAL(toggled(bool)),
825 parent(), SLOT(setShowData(bool)));
826 connect(parent(), SIGNAL(showDataChanged(bool)),
827 action, SLOT(setOn(bool)));
828 action->setOn(showData);
829 action->addTo(headerPopup);
831 headerPopup->exec(e->globalPos());
837 ConfigView* ConfigView::viewList;
839 ConfigView::ConfigView(QWidget* parent, const char *name)
840 : Parent(parent, name)
842 list = new ConfigList(this, name);
843 lineEdit = new ConfigLineEdit(this);
846 this->nextView = viewList;
850 ConfigView::~ConfigView(void)
854 for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
862 void ConfigView::setShowAll(bool b)
864 if (list->showAll != b) {
866 list->updateListAll();
867 emit showAllChanged(b);
871 void ConfigView::setShowName(bool b)
873 if (list->showName != b) {
876 emit showNameChanged(b);
880 void ConfigView::setShowRange(bool b)
882 if (list->showRange != b) {
885 emit showRangeChanged(b);
889 void ConfigView::setShowData(bool b)
891 if (list->showData != b) {
894 emit showDataChanged(b);
898 void ConfigList::setAllOpen(bool open)
900 QListViewItemIterator it(this);
902 for (; it.current(); it++)
903 it.current()->setOpen(open);
906 void ConfigView::updateList(ConfigItem* item)
910 for (v = viewList; v; v = v->nextView)
911 v->list->updateList(item);
914 void ConfigView::updateListAll(void)
918 for (v = viewList; v; v = v->nextView)
919 v->list->updateListAll();
922 ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
923 : Parent(parent, name), menu(0), sym(0)
926 configSettings->beginGroup(name);
927 _showDebug = configSettings->readBoolEntry("/showDebug", false);
928 configSettings->endGroup();
929 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
933 void ConfigInfoView::saveSettings(void)
936 configSettings->beginGroup(name());
937 configSettings->writeEntry("/showDebug", showDebug());
938 configSettings->endGroup();
942 void ConfigInfoView::setShowDebug(bool b)
944 if (_showDebug != b) {
950 emit showDebugChanged(b);
954 void ConfigInfoView::setInfo(struct menu *m)
966 void ConfigInfoView::setSource(const QString& name)
968 const char *p = name.latin1();
977 if (sscanf(p, "m%p", &m) == 1 && menu != m) {
980 emit menuSelected(menu);
986 if (sscanf(p, "s%p", &s) == 1 && sym != s) {
994 void ConfigInfoView::symbolInfo(void)
998 str += "<big>Symbol: <b>";
999 str += print_filter(sym->name);
1000 str += "</b></big><br><br>value: ";
1001 str += print_filter(sym_get_string_value(sym));
1002 str += "<br>visibility: ";
1003 str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
1005 str += debug_info(sym);
1010 void ConfigInfoView::menuInfo(void)
1013 QString head, debug, help;
1019 head += print_filter(_(menu->prompt->text));
1020 head += "</b></big>";
1024 head += QString().sprintf("<a href=\"s%p\">", sym);
1025 head += print_filter(sym->name);
1030 } else if (sym->name) {
1033 head += QString().sprintf("<a href=\"s%p\">", sym);
1034 head += print_filter(sym->name);
1037 head += "</b></big>";
1042 debug = debug_info(sym);
1044 help = print_filter(_(menu_get_help(menu)));
1045 } else if (menu->prompt) {
1047 head += print_filter(_(menu->prompt->text));
1048 head += "</b></big><br><br>";
1050 if (menu->prompt->visible.expr) {
1051 debug += " dep: ";
1052 expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
1053 debug += "<br><br>";
1058 debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
1060 setText(head + debug + help);
1063 QString ConfigInfoView::debug_info(struct symbol *sym)
1068 debug += print_filter(sym_type_name(sym->type));
1069 if (sym_is_choice(sym))
1070 debug += " (choice)";
1072 if (sym->rev_dep.expr) {
1073 debug += "reverse dep: ";
1074 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1077 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1078 switch (prop->type) {
1081 debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
1082 debug += print_filter(_(prop->text));
1083 debug += "</a><br>";
1086 debug += "default: ";
1087 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1091 if (sym_is_choice(sym)) {
1092 debug += "choice: ";
1093 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1098 debug += "select: ";
1099 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1104 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1108 debug += "unknown property: ";
1109 debug += prop_get_type_name(prop->type);
1112 if (prop->visible.expr) {
1113 debug += " dep: ";
1114 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1123 QString ConfigInfoView::print_filter(const QString &str)
1125 QRegExp re("[<>&\"\\n]");
1127 for (int i = 0; (i = res.find(re, i)) >= 0;) {
1128 switch (res[i].latin1()) {
1130 res.replace(i, 1, "<");
1134 res.replace(i, 1, ">");
1138 res.replace(i, 1, "&");
1142 res.replace(i, 1, """);
1146 res.replace(i, 1, "<br>");
1154 void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
1156 QString* text = reinterpret_cast<QString*>(data);
1157 QString str2 = print_filter(str);
1159 if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1160 *text += QString().sprintf("<a href=\"s%p\">", sym);
1167 QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
1169 QPopupMenu* popup = Parent::createPopupMenu(pos);
1170 QAction* action = new QAction(NULL,"Show Debug Info", 0, popup);
1171 action->setToggleAction(TRUE);
1172 connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1173 connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
1174 action->setOn(showDebug());
1175 popup->insertSeparator();
1176 action->addTo(popup);
1180 void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
1182 Parent::contentsContextMenuEvent(e);
1185 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
1186 : Parent(parent, name), result(NULL)
1188 setCaption("Search Config");
1190 QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);
1191 QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);
1192 layout2->addWidget(new QLabel("Find:", this));
1193 editField = new QLineEdit(this);
1194 connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1195 layout2->addWidget(editField);
1196 searchButton = new QPushButton("Search", this);
1197 searchButton->setAutoDefault(FALSE);
1198 connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1199 layout2->addWidget(searchButton);
1200 layout1->addLayout(layout2);
1202 split = new QSplitter(this);
1203 split->setOrientation(QSplitter::Vertical);
1204 list = new ConfigView(split, name);
1205 list->list->mode = listMode;
1206 info = new ConfigInfoView(split, name);
1207 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1208 info, SLOT(setInfo(struct menu *)));
1209 connect(list->list, SIGNAL(menuChanged(struct menu *)),
1210 parent, SLOT(setMenuLink(struct menu *)));
1212 layout1->addWidget(split);
1215 int x, y, width, height;
1218 configSettings->beginGroup(name);
1219 width = configSettings->readNumEntry("/window width", parent->width() / 2);
1220 height = configSettings->readNumEntry("/window height", parent->height() / 2);
1221 resize(width, height);
1222 x = configSettings->readNumEntry("/window x", 0, &ok);
1224 y = configSettings->readNumEntry("/window y", 0, &ok);
1227 QValueList<int> sizes = configSettings->readSizes("/split", &ok);
1229 split->setSizes(sizes);
1230 configSettings->endGroup();
1231 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1235 void ConfigSearchWindow::saveSettings(void)
1238 configSettings->beginGroup(name());
1239 configSettings->writeEntry("/window x", pos().x());
1240 configSettings->writeEntry("/window y", pos().y());
1241 configSettings->writeEntry("/window width", size().width());
1242 configSettings->writeEntry("/window height", size().height());
1243 configSettings->writeSizes("/split", split->sizes());
1244 configSettings->endGroup();
1248 void ConfigSearchWindow::search(void)
1251 struct property *prop;
1252 ConfigItem *lastItem = NULL;
1255 list->list->clear();
1258 result = sym_re_search(editField->text().latin1());
1261 for (p = result; *p; p++) {
1262 for_all_prompts((*p), prop)
1263 lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1264 menu_is_visible(prop->menu));
1269 * Construct the complete config widget
1271 ConfigMainWindow::ConfigMainWindow(void)
1276 int x, y, width, height;
1279 QWidget *d = configApp->desktop();
1280 snprintf(title, sizeof(title), _("Linux Kernel v%s Configuration"),
1281 getenv("KERNELVERSION"));
1284 width = configSettings->readNumEntry("/window width", d->width() - 64);
1285 height = configSettings->readNumEntry("/window height", d->height() - 64);
1286 resize(width, height);
1287 x = configSettings->readNumEntry("/window x", 0, &ok);
1289 y = configSettings->readNumEntry("/window y", 0, &ok);
1293 split1 = new QSplitter(this);
1294 split1->setOrientation(QSplitter::Horizontal);
1295 setCentralWidget(split1);
1297 menuView = new ConfigView(split1, "menu");
1298 menuList = menuView->list;
1300 split2 = new QSplitter(split1);
1301 split2->setOrientation(QSplitter::Vertical);
1303 // create config tree
1304 configView = new ConfigView(split2, "config");
1305 configList = configView->list;
1307 helpText = new ConfigInfoView(split2, "help");
1308 helpText->setTextFormat(Qt::RichText);
1310 setTabOrder(configList, helpText);
1311 configList->setFocus();
1314 toolBar = new QToolBar("Tools", this);
1316 backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this);
1317 connect(backAction, SIGNAL(activated()), SLOT(goBack()));
1318 backAction->setEnabled(FALSE);
1319 QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this);
1320 connect(quitAction, SIGNAL(activated()), SLOT(close()));
1321 QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
1322 connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
1323 saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
1324 connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
1325 conf_set_changed_callback(conf_changed);
1326 // Set saveAction's initial state
1328 QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
1329 connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
1330 QAction *searchAction = new QAction("Find", "&Find", CTRL+Key_F, this);
1331 connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
1332 QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
1333 connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
1334 QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this);
1335 connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
1336 QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this);
1337 connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
1339 QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
1340 showNameAction->setToggleAction(TRUE);
1341 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1342 connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
1343 showNameAction->setOn(configView->showName());
1344 QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this);
1345 showRangeAction->setToggleAction(TRUE);
1346 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1347 connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
1348 showRangeAction->setOn(configList->showRange);
1349 QAction *showDataAction = new QAction(NULL, "Show Data", 0, this);
1350 showDataAction->setToggleAction(TRUE);
1351 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1352 connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
1353 showDataAction->setOn(configList->showData);
1354 QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this);
1355 showAllAction->setToggleAction(TRUE);
1356 connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool)));
1357 connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool)));
1358 showAllAction->setOn(configList->showAll);
1359 QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
1360 showDebugAction->setToggleAction(TRUE);
1361 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1362 connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
1363 showDebugAction->setOn(helpText->showDebug());
1365 QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this);
1366 connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
1367 QAction *showAboutAction = new QAction(NULL, "About", 0, this);
1368 connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
1371 backAction->addTo(toolBar);
1372 toolBar->addSeparator();
1373 loadAction->addTo(toolBar);
1374 saveAction->addTo(toolBar);
1375 toolBar->addSeparator();
1376 singleViewAction->addTo(toolBar);
1377 splitViewAction->addTo(toolBar);
1378 fullViewAction->addTo(toolBar);
1380 // create config menu
1381 QPopupMenu* config = new QPopupMenu(this);
1382 menu->insertItem("&File", config);
1383 loadAction->addTo(config);
1384 saveAction->addTo(config);
1385 saveAsAction->addTo(config);
1386 config->insertSeparator();
1387 quitAction->addTo(config);
1390 QPopupMenu* editMenu = new QPopupMenu(this);
1391 menu->insertItem("&Edit", editMenu);
1392 searchAction->addTo(editMenu);
1394 // create options menu
1395 QPopupMenu* optionMenu = new QPopupMenu(this);
1396 menu->insertItem("&Option", optionMenu);
1397 showNameAction->addTo(optionMenu);
1398 showRangeAction->addTo(optionMenu);
1399 showDataAction->addTo(optionMenu);
1400 optionMenu->insertSeparator();
1401 showAllAction->addTo(optionMenu);
1402 showDebugAction->addTo(optionMenu);
1405 QPopupMenu* helpMenu = new QPopupMenu(this);
1406 menu->insertSeparator();
1407 menu->insertItem("&Help", helpMenu);
1408 showIntroAction->addTo(helpMenu);
1409 showAboutAction->addTo(helpMenu);
1411 connect(configList, SIGNAL(menuChanged(struct menu *)),
1412 helpText, SLOT(setInfo(struct menu *)));
1413 connect(configList, SIGNAL(menuSelected(struct menu *)),
1414 SLOT(changeMenu(struct menu *)));
1415 connect(configList, SIGNAL(parentSelected()),
1417 connect(menuList, SIGNAL(menuChanged(struct menu *)),
1418 helpText, SLOT(setInfo(struct menu *)));
1419 connect(menuList, SIGNAL(menuSelected(struct menu *)),
1420 SLOT(changeMenu(struct menu *)));
1422 connect(configList, SIGNAL(gotFocus(struct menu *)),
1423 helpText, SLOT(setInfo(struct menu *)));
1424 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1425 helpText, SLOT(setInfo(struct menu *)));
1426 connect(menuList, SIGNAL(gotFocus(struct menu *)),
1427 SLOT(listFocusChanged(void)));
1428 connect(helpText, SIGNAL(menuSelected(struct menu *)),
1429 SLOT(setMenuLink(struct menu *)));
1431 QString listMode = configSettings->readEntry("/listMode", "symbol");
1432 if (listMode == "single")
1434 else if (listMode == "full")
1436 else /*if (listMode == "split")*/
1439 // UI setup done, restore splitter positions
1440 QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
1442 split1->setSizes(sizes);
1444 sizes = configSettings->readSizes("/split2", &ok);
1446 split2->setSizes(sizes);
1449 void ConfigMainWindow::loadConfig(void)
1451 QString s = QFileDialog::getOpenFileName(".config", NULL, this);
1454 if (conf_read(QFile::encodeName(s)))
1455 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1456 ConfigView::updateListAll();
1459 void ConfigMainWindow::saveConfig(void)
1461 if (conf_write(NULL))
1462 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1465 void ConfigMainWindow::saveConfigAs(void)
1467 QString s = QFileDialog::getSaveFileName(".config", NULL, this);
1470 if (conf_write(QFile::encodeName(s)))
1471 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1474 void ConfigMainWindow::searchConfig(void)
1477 searchWindow = new ConfigSearchWindow(this, "search");
1478 searchWindow->show();
1481 void ConfigMainWindow::changeMenu(struct menu *menu)
1483 configList->setRootMenu(menu);
1484 if (configList->rootEntry->parent == &rootmenu)
1485 backAction->setEnabled(FALSE);
1487 backAction->setEnabled(TRUE);
1490 void ConfigMainWindow::setMenuLink(struct menu *menu)
1492 struct menu *parent;
1493 ConfigList* list = NULL;
1496 if (!menu_is_visible(menu) && !configView->showAll())
1499 switch (configList->mode) {
1502 parent = menu_get_parent_menu(menu);
1505 list->setRootMenu(parent);
1508 if (menu->flags & MENU_ROOT) {
1509 configList->setRootMenu(menu);
1510 configList->clearSelection();
1514 parent = menu_get_parent_menu(menu->parent);
1517 item = menuList->findConfigItem(parent);
1519 menuList->setSelected(item, TRUE);
1520 menuList->ensureItemVisible(item);
1522 list->setRootMenu(parent);
1531 item = list->findConfigItem(menu);
1533 list->setSelected(item, TRUE);
1534 list->ensureItemVisible(item);
1540 void ConfigMainWindow::listFocusChanged(void)
1542 if (menuList->mode == menuMode)
1543 configList->clearSelection();
1546 void ConfigMainWindow::goBack(void)
1550 configList->setParentMenu();
1551 if (configList->rootEntry == &rootmenu)
1552 backAction->setEnabled(FALSE);
1553 item = (ConfigItem*)menuList->selectedItem();
1555 if (item->menu == configList->rootEntry) {
1556 menuList->setSelected(item, TRUE);
1559 item = (ConfigItem*)item->parent();
1563 void ConfigMainWindow::showSingleView(void)
1566 menuList->setRootMenu(0);
1567 configList->mode = singleMode;
1568 if (configList->rootEntry == &rootmenu)
1569 configList->updateListAll();
1571 configList->setRootMenu(&rootmenu);
1572 configList->setAllOpen(TRUE);
1573 configList->setFocus();
1576 void ConfigMainWindow::showSplitView(void)
1578 configList->mode = symbolMode;
1579 if (configList->rootEntry == &rootmenu)
1580 configList->updateListAll();
1582 configList->setRootMenu(&rootmenu);
1583 configList->setAllOpen(TRUE);
1584 configApp->processEvents();
1585 menuList->mode = menuMode;
1586 menuList->setRootMenu(&rootmenu);
1587 menuList->setAllOpen(TRUE);
1589 menuList->setFocus();
1592 void ConfigMainWindow::showFullView(void)
1595 menuList->setRootMenu(0);
1596 configList->mode = fullMode;
1597 if (configList->rootEntry == &rootmenu)
1598 configList->updateListAll();
1600 configList->setRootMenu(&rootmenu);
1601 configList->setAllOpen(FALSE);
1602 configList->setFocus();
1606 * ask for saving configuration before quitting
1607 * TODO ask only when something changed
1609 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1611 if (!conf_get_changed()) {
1615 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1616 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1617 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1618 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1619 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1620 switch (mb.exec()) {
1621 case QMessageBox::Yes:
1623 case QMessageBox::No:
1626 case QMessageBox::Cancel:
1632 void ConfigMainWindow::showIntro(void)
1634 static char str[] = "Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
1635 "For each option, a blank box indicates the feature is disabled, a check\n"
1636 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1637 "as a module. Clicking on the box will cycle through the three states.\n\n"
1638 "If you do not see an option (e.g., a device driver) that you believe\n"
1639 "should be present, try turning on Show All Options under the Options menu.\n"
1640 "Although there is no cross reference yet to help you figure out what other\n"
1641 "options must be enabled to support the option you are interested in, you can\n"
1642 "still view the help of a grayed-out option.\n\n"
1643 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1644 "which you can then match by examining other options.\n\n";
1646 QMessageBox::information(this, "qconf", str);
1649 void ConfigMainWindow::showAbout(void)
1651 static char str[] = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
1652 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1654 QMessageBox::information(this, "qconf", str);
1657 void ConfigMainWindow::saveSettings(void)
1659 configSettings->writeEntry("/window x", pos().x());
1660 configSettings->writeEntry("/window y", pos().y());
1661 configSettings->writeEntry("/window width", size().width());
1662 configSettings->writeEntry("/window height", size().height());
1665 switch(configList->mode) {
1678 configSettings->writeEntry("/listMode", entry);
1680 configSettings->writeSizes("/split1", split1->sizes());
1681 configSettings->writeSizes("/split2", split2->sizes());
1684 void ConfigMainWindow::conf_changed(void)
1687 saveAction->setEnabled(conf_get_changed());
1690 void fixup_rootmenu(struct menu *menu)
1693 static int menu_cnt = 0;
1695 menu->flags |= MENU_ROOT;
1696 for (child = menu->list; child; child = child->next) {
1697 if (child->prompt && child->prompt->type == P_MENU) {
1699 fixup_rootmenu(child);
1701 } else if (!menu_cnt)
1702 fixup_rootmenu(child);
1706 static const char *progname;
1708 static void usage(void)
1710 printf("%s <config>\n", progname);
1714 int main(int ac, char** av)
1716 ConfigMainWindow* v;
1719 bindtextdomain(PACKAGE, LOCALEDIR);
1720 textdomain(PACKAGE);
1722 #ifndef LKC_DIRECT_LINK
1727 configApp = new QApplication(ac, av);
1728 if (ac > 1 && av[1][0] == '-') {
1741 fixup_rootmenu(&rootmenu);
1743 //zconfdump(stdout);
1745 configSettings = new ConfigSettings();
1746 configSettings->beginGroup("/kconfig/qconf");
1747 v = new ConfigMainWindow();
1749 //zconfdump(stdout);
1750 configApp->setMainWidget(v);
1751 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1752 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1756 configSettings->endGroup();
1757 delete configSettings;