[PATCH] multiple device *read* opens support
[linux-2.6/history.git] / scripts / kconfig / qconf.cc
blob9ae9c321662fa1a5c07e7497564bc380bc70baef
1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
6 #include <qapplication.h>
7 #include <qmainwindow.h>
8 #include <qtoolbar.h>
9 #include <qvbox.h>
10 #include <qsplitter.h>
11 #include <qlistview.h>
12 #include <qtextview.h>
13 #include <qlineedit.h>
14 #include <qmenubar.h>
15 #include <qmessagebox.h>
16 #include <qaction.h>
17 #include <qheader.h>
18 #include <qfiledialog.h>
19 #include <qregexp.h>
20 #if QT_VERSION >= 300
21 #include <qsettings.h>
22 #endif
24 #include <stdlib.h>
26 #include "lkc.h"
27 #include "qconf.h"
29 #include "qconf.moc"
30 #include "images.c"
32 static QApplication *configApp;
33 #if QT_VERSION >= 300
34 static QSettings *configSettings;
35 #endif
38 * update all the children of a menu entry
39 * removes/adds the entries from the parent widget as necessary
41 * parent: either the menu list widget or a menu entry widget
42 * menu: entry to be updated
44 template <class P>
45 void ConfigList::updateMenuList(P* parent, struct menu* menu)
47 struct menu* child;
48 ConfigItem* item;
49 ConfigItem* last;
50 bool visible;
51 enum prop_type type;
53 if (!menu) {
54 while ((item = parent->firstChild()))
55 delete item;
56 return;
59 last = parent->firstChild();
60 if (last && !last->goParent)
61 last = 0;
62 for (child = menu->list; child; child = child->next) {
63 item = last ? last->nextSibling() : parent->firstChild();
64 type = child->prompt ? child->prompt->type : P_UNKNOWN;
66 switch (mode) {
67 case menuMode:
68 if (!(child->flags & MENU_ROOT))
69 goto hide;
70 break;
71 case symbolMode:
72 if (child->flags & MENU_ROOT)
73 goto hide;
74 break;
75 default:
76 break;
79 visible = menu_is_visible(child);
80 if (showAll || visible) {
81 if (!item || item->menu != child)
82 item = new ConfigItem(parent, last, child, visible);
83 else
84 item->testUpdateMenu(visible);
86 if (mode == fullMode || mode == menuMode || type != P_MENU)
87 updateMenuList(item, child);
88 else
89 updateMenuList(item, 0);
90 last = item;
91 continue;
93 hide:
94 if (item && item->menu == child) {
95 last = parent->firstChild();
96 if (last == item)
97 last = 0;
98 else while (last->nextSibling() != item)
99 last = last->nextSibling();
100 delete item;
105 #if QT_VERSION >= 300
107 * set the new data
108 * TODO check the value
110 void ConfigItem::okRename(int col)
112 Parent::okRename(col);
113 sym_set_string_value(menu->sym, text(dataColIdx).latin1());
115 #endif
118 * update the displayed of a menu entry
120 void ConfigItem::updateMenu(void)
122 ConfigList* list;
123 struct symbol* sym;
124 struct property *prop;
125 QString prompt;
126 int type;
127 tristate expr;
129 list = listView();
130 if (goParent) {
131 setPixmap(promptColIdx, list->menuBackPix);
132 prompt = "..";
133 goto set_prompt;
136 sym = menu->sym;
137 prop = menu->prompt;
138 prompt = menu_get_prompt(menu);
140 if (prop) switch (prop->type) {
141 case P_MENU:
142 if (list->mode == singleMode || list->mode == symbolMode) {
143 /* a menuconfig entry is displayed differently
144 * depending whether it's at the view root or a child.
146 if (sym && list->rootEntry == menu)
147 break;
148 setPixmap(promptColIdx, list->menuPix);
149 } else {
150 if (sym)
151 break;
152 setPixmap(promptColIdx, 0);
154 goto set_prompt;
155 case P_COMMENT:
156 setPixmap(promptColIdx, 0);
157 goto set_prompt;
158 default:
161 if (!sym)
162 goto set_prompt;
164 setText(nameColIdx, sym->name);
166 type = sym_get_type(sym);
167 switch (type) {
168 case S_BOOLEAN:
169 case S_TRISTATE:
170 char ch;
172 if (!sym_is_changable(sym) && !list->showAll) {
173 setPixmap(promptColIdx, 0);
174 setText(noColIdx, 0);
175 setText(modColIdx, 0);
176 setText(yesColIdx, 0);
177 break;
179 expr = sym_get_tristate_value(sym);
180 switch (expr) {
181 case yes:
182 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
183 setPixmap(promptColIdx, list->choiceYesPix);
184 else
185 setPixmap(promptColIdx, list->symbolYesPix);
186 setText(yesColIdx, "Y");
187 ch = 'Y';
188 break;
189 case mod:
190 setPixmap(promptColIdx, list->symbolModPix);
191 setText(modColIdx, "M");
192 ch = 'M';
193 break;
194 default:
195 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
196 setPixmap(promptColIdx, list->choiceNoPix);
197 else
198 setPixmap(promptColIdx, list->symbolNoPix);
199 setText(noColIdx, "N");
200 ch = 'N';
201 break;
203 if (expr != no)
204 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
205 if (expr != mod)
206 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
207 if (expr != yes)
208 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
210 setText(dataColIdx, QChar(ch));
211 break;
212 case S_INT:
213 case S_HEX:
214 case S_STRING:
215 const char* data;
217 data = sym_get_string_value(sym);
218 #if QT_VERSION >= 300
219 int i = list->mapIdx(dataColIdx);
220 if (i >= 0)
221 setRenameEnabled(i, TRUE);
222 #endif
223 setText(dataColIdx, data);
224 if (type == S_STRING)
225 prompt.sprintf("%s: %s", prompt.latin1(), data);
226 else
227 prompt.sprintf("(%s) %s", data, prompt.latin1());
228 break;
230 if (!sym_has_value(sym) && visible)
231 prompt += " (NEW)";
232 set_prompt:
233 setText(promptColIdx, prompt);
236 void ConfigItem::testUpdateMenu(bool v)
238 ConfigItem* i;
240 visible = v;
241 if (!menu)
242 return;
244 sym_calc_value(menu->sym);
245 if (menu->flags & MENU_CHANGED) {
246 /* the menu entry changed, so update all list items */
247 menu->flags &= ~MENU_CHANGED;
248 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
249 i->updateMenu();
250 } else if (listView()->updateAll)
251 updateMenu();
254 void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
256 ConfigList* list = listView();
258 if (visible) {
259 if (isSelected() && !list->hasFocus() && list->mode == menuMode)
260 Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
261 else
262 Parent::paintCell(p, cg, column, width, align);
263 } else
264 Parent::paintCell(p, list->disabledColorGroup, column, width, align);
268 * construct a menu entry
270 void ConfigItem::init(void)
272 if (menu) {
273 ConfigList* list = listView();
274 nextItem = (ConfigItem*)menu->data;
275 menu->data = this;
277 if (list->mode != fullMode)
278 setOpen(TRUE);
279 sym_calc_value(menu->sym);
281 updateMenu();
285 * destruct a menu entry
287 ConfigItem::~ConfigItem(void)
289 if (menu) {
290 ConfigItem** ip = (ConfigItem**)&menu->data;
291 for (; *ip; ip = &(*ip)->nextItem) {
292 if (*ip == this) {
293 *ip = nextItem;
294 break;
300 void ConfigLineEdit::show(ConfigItem* i)
302 item = i;
303 if (sym_get_string_value(item->menu->sym))
304 setText(sym_get_string_value(item->menu->sym));
305 else
306 setText(0);
307 Parent::show();
308 setFocus();
311 void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
313 switch (e->key()) {
314 case Key_Escape:
315 break;
316 case Key_Return:
317 case Key_Enter:
318 sym_set_string_value(item->menu->sym, text().latin1());
319 parent()->updateList(item);
320 break;
321 default:
322 Parent::keyPressEvent(e);
323 return;
325 e->accept();
326 parent()->list->setFocus();
327 hide();
330 ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv)
331 : Parent(p), cview(cv),
332 updateAll(false),
333 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
334 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
335 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
336 showAll(false), showName(false), showRange(false), showData(false),
337 rootEntry(0)
339 int i;
341 setSorting(-1);
342 setRootIsDecorated(TRUE);
343 disabledColorGroup = palette().active();
344 disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
345 inactivedColorGroup = palette().active();
346 inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
348 connect(this, SIGNAL(selectionChanged(void)),
349 SLOT(updateSelection(void)));
351 for (i = 0; i < colNr; i++)
352 colMap[i] = colRevMap[i] = -1;
353 addColumn(promptColIdx, "Option");
355 reinit();
358 void ConfigList::reinit(void)
360 removeColumn(dataColIdx);
361 removeColumn(yesColIdx);
362 removeColumn(modColIdx);
363 removeColumn(noColIdx);
364 removeColumn(nameColIdx);
366 if (showName)
367 addColumn(nameColIdx, "Name");
368 if (showRange) {
369 addColumn(noColIdx, "N");
370 addColumn(modColIdx, "M");
371 addColumn(yesColIdx, "Y");
373 if (showData)
374 addColumn(dataColIdx, "Value");
376 updateListAll();
379 void ConfigList::updateSelection(void)
381 struct menu *menu;
382 enum prop_type type;
384 ConfigItem* item = (ConfigItem*)selectedItem();
385 if (!item)
386 return;
388 cview->setHelp(item);
390 menu = item->menu;
391 if (!menu)
392 return;
393 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
394 if (mode == menuMode && type == P_MENU)
395 emit menuSelected(menu);
398 void ConfigList::updateList(ConfigItem* item)
400 ConfigItem* last = 0;
402 if (!rootEntry)
403 goto update;
405 if (rootEntry != &rootmenu && (mode == singleMode ||
406 (mode == symbolMode && rootEntry->parent != &rootmenu))) {
407 item = firstChild();
408 if (!item)
409 item = new ConfigItem(this, 0, true);
410 last = item;
412 if ((mode == singleMode || mode == symbolMode) &&
413 rootEntry->sym && rootEntry->prompt) {
414 item = last ? last->nextSibling() : firstChild();
415 if (!item)
416 item = new ConfigItem(this, last, rootEntry, true);
417 else
418 item->testUpdateMenu(true);
420 updateMenuList(item, rootEntry);
421 triggerUpdate();
422 return;
424 update:
425 updateMenuList(this, rootEntry);
426 triggerUpdate();
429 void ConfigList::setAllOpen(bool open)
431 QListViewItemIterator it(this);
433 for (; it.current(); it++)
434 it.current()->setOpen(open);
437 void ConfigList::setValue(ConfigItem* item, tristate val)
439 struct symbol* sym;
440 int type;
441 tristate oldval;
443 sym = item->menu ? item->menu->sym : 0;
444 if (!sym)
445 return;
447 type = sym_get_type(sym);
448 switch (type) {
449 case S_BOOLEAN:
450 case S_TRISTATE:
451 oldval = sym_get_tristate_value(sym);
453 if (!sym_set_tristate_value(sym, val))
454 return;
455 if (oldval == no && item->menu->list)
456 item->setOpen(TRUE);
457 parent()->updateList(item);
458 break;
462 void ConfigList::changeValue(ConfigItem* item)
464 struct symbol* sym;
465 struct menu* menu;
466 int type, oldexpr, newexpr;
468 menu = item->menu;
469 if (!menu)
470 return;
471 sym = menu->sym;
472 if (!sym) {
473 if (item->menu->list)
474 item->setOpen(!item->isOpen());
475 return;
478 type = sym_get_type(sym);
479 switch (type) {
480 case S_BOOLEAN:
481 case S_TRISTATE:
482 oldexpr = sym_get_tristate_value(sym);
483 newexpr = sym_toggle_tristate_value(sym);
484 if (item->menu->list) {
485 if (oldexpr == newexpr)
486 item->setOpen(!item->isOpen());
487 else if (oldexpr == no)
488 item->setOpen(TRUE);
490 if (oldexpr != newexpr)
491 parent()->updateList(item);
492 break;
493 case S_INT:
494 case S_HEX:
495 case S_STRING:
496 #if QT_VERSION >= 300
497 if (colMap[dataColIdx] >= 0)
498 item->startRename(colMap[dataColIdx]);
499 else
500 #endif
501 parent()->lineEdit->show(item);
502 break;
506 void ConfigList::setRootMenu(struct menu *menu)
508 enum prop_type type;
510 if (rootEntry == menu)
511 return;
512 type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
513 if (type != P_MENU)
514 return;
515 updateMenuList(this, 0);
516 rootEntry = menu;
517 updateListAll();
518 setSelected(currentItem(), hasFocus());
521 void ConfigList::setParentMenu(void)
523 ConfigItem* item;
524 struct menu *oldroot;
526 oldroot = rootEntry;
527 if (rootEntry == &rootmenu)
528 return;
529 setRootMenu(menu_get_parent_menu(rootEntry->parent));
531 QListViewItemIterator it(this);
532 for (; (item = (ConfigItem*)it.current()); it++) {
533 if (item->menu == oldroot) {
534 setCurrentItem(item);
535 ensureItemVisible(item);
536 break;
541 void ConfigList::keyPressEvent(QKeyEvent* ev)
543 QListViewItem* i = currentItem();
544 ConfigItem* item;
545 struct menu *menu;
546 enum prop_type type;
548 if (ev->key() == Key_Escape && mode != fullMode) {
549 emit parentSelected();
550 ev->accept();
551 return;
554 if (!i) {
555 Parent::keyPressEvent(ev);
556 return;
558 item = (ConfigItem*)i;
560 switch (ev->key()) {
561 case Key_Return:
562 case Key_Enter:
563 if (item->goParent) {
564 emit parentSelected();
565 break;
567 menu = item->menu;
568 if (!menu)
569 break;
570 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
571 if (type == P_MENU && rootEntry != menu &&
572 mode != fullMode && mode != menuMode) {
573 emit menuSelected(menu);
574 break;
576 case Key_Space:
577 changeValue(item);
578 break;
579 case Key_N:
580 setValue(item, no);
581 break;
582 case Key_M:
583 setValue(item, mod);
584 break;
585 case Key_Y:
586 setValue(item, yes);
587 break;
588 default:
589 Parent::keyPressEvent(ev);
590 return;
592 ev->accept();
595 void ConfigList::contentsMousePressEvent(QMouseEvent* e)
597 //QPoint p(contentsToViewport(e->pos()));
598 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
599 Parent::contentsMousePressEvent(e);
602 void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
604 QPoint p(contentsToViewport(e->pos()));
605 ConfigItem* item = (ConfigItem*)itemAt(p);
606 struct menu *menu;
607 enum prop_type ptype;
608 const QPixmap* pm;
609 int idx, x;
611 if (!item)
612 goto skip;
614 menu = item->menu;
615 x = header()->offset() + p.x();
616 idx = colRevMap[header()->sectionAt(x)];
617 switch (idx) {
618 case promptColIdx:
619 pm = item->pixmap(promptColIdx);
620 if (pm) {
621 int off = header()->sectionPos(0) + itemMargin() +
622 treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
623 if (x >= off && x < off + pm->width()) {
624 if (item->goParent) {
625 emit parentSelected();
626 break;
627 } else if (!menu)
628 break;
629 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
630 if (ptype == P_MENU && rootEntry != menu &&
631 mode != fullMode && mode != menuMode)
632 emit menuSelected(menu);
633 else
634 changeValue(item);
637 break;
638 case noColIdx:
639 setValue(item, no);
640 break;
641 case modColIdx:
642 setValue(item, mod);
643 break;
644 case yesColIdx:
645 setValue(item, yes);
646 break;
647 case dataColIdx:
648 changeValue(item);
649 break;
652 skip:
653 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
654 Parent::contentsMouseReleaseEvent(e);
657 void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
659 //QPoint p(contentsToViewport(e->pos()));
660 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
661 Parent::contentsMouseMoveEvent(e);
664 void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
666 QPoint p(contentsToViewport(e->pos()));
667 ConfigItem* item = (ConfigItem*)itemAt(p);
668 struct menu *menu;
669 enum prop_type ptype;
671 if (!item)
672 goto skip;
673 if (item->goParent) {
674 emit parentSelected();
675 goto skip;
677 menu = item->menu;
678 if (!menu)
679 goto skip;
680 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
681 if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
682 emit menuSelected(menu);
683 else if (menu->sym)
684 changeValue(item);
686 skip:
687 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
688 Parent::contentsMouseDoubleClickEvent(e);
691 void ConfigList::focusInEvent(QFocusEvent *e)
693 Parent::focusInEvent(e);
695 QListViewItem* item = currentItem();
696 if (!item)
697 return;
699 setSelected(item, TRUE);
700 emit gotFocus();
703 ConfigView* ConfigView::viewList;
705 ConfigView::ConfigView(QWidget* parent, ConfigMainWindow* cview)
706 : Parent(parent)
708 list = new ConfigList(this, cview);
709 lineEdit = new ConfigLineEdit(this);
710 lineEdit->hide();
712 this->nextView = viewList;
713 viewList = this;
716 ConfigView::~ConfigView(void)
718 ConfigView** vp;
720 for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
721 if (*vp == this) {
722 *vp = nextView;
723 break;
728 void ConfigView::updateList(ConfigItem* item)
730 ConfigView* v;
732 for (v = viewList; v; v = v->nextView)
733 v->list->updateList(item);
736 void ConfigView::updateListAll(void)
738 ConfigView* v;
740 for (v = viewList; v; v = v->nextView)
741 v->list->updateListAll();
745 * Construct the complete config widget
747 ConfigMainWindow::ConfigMainWindow(void)
749 QMenuBar* menu;
750 QSplitter* split1;
751 QSplitter* split2;
752 bool ok;
753 int x, y, width, height;
755 QWidget *d = configApp->desktop();
757 #if QT_VERSION >= 300
758 width = configSettings->readNumEntry("/kconfig/qconf/window width", d->width() - 64);
759 height = configSettings->readNumEntry("/kconfig/qconf/window height", d->height() - 64);
760 resize(width, height);
761 x = configSettings->readNumEntry("/kconfig/qconf/window x", 0, &ok);
762 if (ok)
763 y = configSettings->readNumEntry("/kconfig/qconf/window y", 0, &ok);
764 if (ok)
765 move(x, y);
766 #else
767 width = d->width() - 64;
768 height = d->height() - 64;
769 resize(width, height);
770 #endif
772 showDebug = false;
774 split1 = new QSplitter(this);
775 split1->setOrientation(QSplitter::Horizontal);
776 setCentralWidget(split1);
778 menuView = new ConfigView(split1, this);
779 menuList = menuView->list;
781 split2 = new QSplitter(split1);
782 split2->setOrientation(QSplitter::Vertical);
784 // create config tree
785 configView = new ConfigView(split2, this);
786 configList = configView->list;
788 helpText = new QTextView(split2);
789 helpText->setTextFormat(Qt::RichText);
791 setTabOrder(configList, helpText);
792 configList->setFocus();
794 menu = menuBar();
795 toolBar = new QToolBar("Tools", this);
797 backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this);
798 connect(backAction, SIGNAL(activated()), SLOT(goBack()));
799 backAction->setEnabled(FALSE);
800 QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this);
801 connect(quitAction, SIGNAL(activated()), SLOT(close()));
802 QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
803 connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
804 QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
805 connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
806 QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
807 connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
808 QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
809 connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
810 QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this);
811 connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
812 QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this);
813 connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
815 QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
816 showNameAction->setToggleAction(TRUE);
817 showNameAction->setOn(configList->showName);
818 connect(showNameAction, SIGNAL(toggled(bool)), SLOT(setShowName(bool)));
819 QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this);
820 showRangeAction->setToggleAction(TRUE);
821 showRangeAction->setOn(configList->showRange);
822 connect(showRangeAction, SIGNAL(toggled(bool)), SLOT(setShowRange(bool)));
823 QAction *showDataAction = new QAction(NULL, "Show Data", 0, this);
824 showDataAction->setToggleAction(TRUE);
825 showDataAction->setOn(configList->showData);
826 connect(showDataAction, SIGNAL(toggled(bool)), SLOT(setShowData(bool)));
827 QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this);
828 showAllAction->setToggleAction(TRUE);
829 showAllAction->setOn(configList->showAll);
830 connect(showAllAction, SIGNAL(toggled(bool)), SLOT(setShowAll(bool)));
831 QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
832 showDebugAction->setToggleAction(TRUE);
833 showDebugAction->setOn(showDebug);
834 connect(showDebugAction, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
836 QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this);
837 connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
838 QAction *showAboutAction = new QAction(NULL, "About", 0, this);
839 connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
841 // init tool bar
842 backAction->addTo(toolBar);
843 toolBar->addSeparator();
844 loadAction->addTo(toolBar);
845 saveAction->addTo(toolBar);
846 toolBar->addSeparator();
847 singleViewAction->addTo(toolBar);
848 splitViewAction->addTo(toolBar);
849 fullViewAction->addTo(toolBar);
851 // create config menu
852 QPopupMenu* config = new QPopupMenu(this);
853 menu->insertItem("&File", config);
854 loadAction->addTo(config);
855 saveAction->addTo(config);
856 saveAsAction->addTo(config);
857 config->insertSeparator();
858 quitAction->addTo(config);
860 // create options menu
861 QPopupMenu* optionMenu = new QPopupMenu(this);
862 menu->insertItem("&Option", optionMenu);
863 showNameAction->addTo(optionMenu);
864 showRangeAction->addTo(optionMenu);
865 showDataAction->addTo(optionMenu);
866 optionMenu->insertSeparator();
867 showAllAction->addTo(optionMenu);
868 showDebugAction->addTo(optionMenu);
870 // create help menu
871 QPopupMenu* helpMenu = new QPopupMenu(this);
872 menu->insertSeparator();
873 menu->insertItem("&Help", helpMenu);
874 showIntroAction->addTo(helpMenu);
875 showAboutAction->addTo(helpMenu);
877 connect(configList, SIGNAL(menuSelected(struct menu *)),
878 SLOT(changeMenu(struct menu *)));
879 connect(configList, SIGNAL(parentSelected()),
880 SLOT(goBack()));
881 connect(menuList, SIGNAL(menuSelected(struct menu *)),
882 SLOT(changeMenu(struct menu *)));
884 connect(configList, SIGNAL(gotFocus(void)),
885 SLOT(listFocusChanged(void)));
886 connect(menuList, SIGNAL(gotFocus(void)),
887 SLOT(listFocusChanged(void)));
889 showSplitView();
892 static QString print_filter(const char *str)
894 QRegExp re("[<>&\"\\n]");
895 QString res = str;
896 for (int i = 0; (i = res.find(re, i)) >= 0;) {
897 switch (res[i].latin1()) {
898 case '<':
899 res.replace(i, 1, "&lt;");
900 i += 4;
901 break;
902 case '>':
903 res.replace(i, 1, "&gt;");
904 i += 4;
905 break;
906 case '&':
907 res.replace(i, 1, "&amp;");
908 i += 5;
909 break;
910 case '"':
911 res.replace(i, 1, "&quot;");
912 i += 6;
913 break;
914 case '\n':
915 res.replace(i, 1, "<br>");
916 i += 4;
917 break;
920 return res;
923 static void expr_print_help(void *data, const char *str)
925 ((QString*)data)->append(print_filter(str));
929 * display a new help entry as soon as a new menu entry is selected
931 void ConfigMainWindow::setHelp(QListViewItem* item)
933 struct symbol* sym;
934 struct menu* menu = 0;
936 configList->parent()->lineEdit->hide();
937 if (item)
938 menu = ((ConfigItem*)item)->menu;
939 if (!menu) {
940 helpText->setText(NULL);
941 return;
944 QString head, debug, help;
945 menu = ((ConfigItem*)item)->menu;
946 sym = menu->sym;
947 if (sym) {
948 if (menu->prompt) {
949 head += "<big><b>";
950 head += print_filter(menu->prompt->text);
951 head += "</b></big>";
952 if (sym->name) {
953 head += " (";
954 head += print_filter(sym->name);
955 head += ")";
957 } else if (sym->name) {
958 head += "<big><b>";
959 head += print_filter(sym->name);
960 head += "</b></big>";
962 head += "<br><br>";
964 if (showDebug) {
965 debug += "type: ";
966 debug += print_filter(sym_type_name(sym->type));
967 if (sym_is_choice(sym))
968 debug += " (choice)";
969 debug += "<br>";
970 if (sym->rev_dep.expr) {
971 debug += "reverse dep: ";
972 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
973 debug += "<br>";
975 for (struct property *prop = sym->prop; prop; prop = prop->next) {
976 switch (prop->type) {
977 case P_PROMPT:
978 case P_MENU:
979 debug += "prompt: ";
980 debug += print_filter(prop->text);
981 debug += "<br>";
982 break;
983 case P_DEFAULT:
984 debug += "default: ";
985 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
986 debug += "<br>";
987 break;
988 case P_CHOICE:
989 if (sym_is_choice(sym)) {
990 debug += "choice: ";
991 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
992 debug += "<br>";
994 break;
995 case P_SELECT:
996 debug += "select: ";
997 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
998 debug += "<br>";
999 break;
1000 case P_RANGE:
1001 debug += "range: ";
1002 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1003 debug += "<br>";
1004 break;
1005 default:
1006 debug += "unknown property: ";
1007 debug += prop_get_type_name(prop->type);
1008 debug += "<br>";
1010 if (prop->visible.expr) {
1011 debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
1012 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1013 debug += "<br>";
1016 debug += "<br>";
1019 help = print_filter(sym->help);
1020 } else if (menu->prompt) {
1021 head += "<big><b>";
1022 head += print_filter(menu->prompt->text);
1023 head += "</b></big><br><br>";
1024 if (showDebug) {
1025 if (menu->prompt->visible.expr) {
1026 debug += "&nbsp;&nbsp;dep: ";
1027 expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
1028 debug += "<br><br>";
1032 if (showDebug)
1033 debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
1034 helpText->setText(head + debug + help);
1037 void ConfigMainWindow::loadConfig(void)
1039 QString s = QFileDialog::getOpenFileName(".config", NULL, this);
1040 if (s.isNull())
1041 return;
1042 if (conf_read(s.latin1()))
1043 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1044 ConfigView::updateListAll();
1047 void ConfigMainWindow::saveConfig(void)
1049 if (conf_write(NULL))
1050 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1053 void ConfigMainWindow::saveConfigAs(void)
1055 QString s = QFileDialog::getSaveFileName(".config", NULL, this);
1056 if (s.isNull())
1057 return;
1058 if (conf_write(s.latin1()))
1059 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1062 void ConfigMainWindow::changeMenu(struct menu *menu)
1064 configList->setRootMenu(menu);
1065 backAction->setEnabled(TRUE);
1068 void ConfigMainWindow::listFocusChanged(void)
1070 if (menuList->hasFocus()) {
1071 if (menuList->mode == menuMode)
1072 configList->clearSelection();
1073 setHelp(menuList->selectedItem());
1074 } else if (configList->hasFocus()) {
1075 setHelp(configList->selectedItem());
1079 void ConfigMainWindow::goBack(void)
1081 ConfigItem* item;
1083 configList->setParentMenu();
1084 if (configList->rootEntry == &rootmenu)
1085 backAction->setEnabled(FALSE);
1086 item = (ConfigItem*)menuList->selectedItem();
1087 while (item) {
1088 if (item->menu == configList->rootEntry) {
1089 menuList->setSelected(item, TRUE);
1090 break;
1092 item = (ConfigItem*)item->parent();
1096 void ConfigMainWindow::showSingleView(void)
1098 menuView->hide();
1099 menuList->setRootMenu(0);
1100 configList->mode = singleMode;
1101 if (configList->rootEntry == &rootmenu)
1102 configList->updateListAll();
1103 else
1104 configList->setRootMenu(&rootmenu);
1105 configList->setAllOpen(TRUE);
1106 configList->setFocus();
1109 void ConfigMainWindow::showSplitView(void)
1111 configList->mode = symbolMode;
1112 if (configList->rootEntry == &rootmenu)
1113 configList->updateListAll();
1114 else
1115 configList->setRootMenu(&rootmenu);
1116 configList->setAllOpen(TRUE);
1117 configApp->processEvents();
1118 menuList->mode = menuMode;
1119 menuList->setRootMenu(&rootmenu);
1120 menuList->setAllOpen(TRUE);
1121 menuView->show();
1122 menuList->setFocus();
1125 void ConfigMainWindow::showFullView(void)
1127 menuView->hide();
1128 menuList->setRootMenu(0);
1129 configList->mode = fullMode;
1130 if (configList->rootEntry == &rootmenu)
1131 configList->updateListAll();
1132 else
1133 configList->setRootMenu(&rootmenu);
1134 configList->setAllOpen(FALSE);
1135 configList->setFocus();
1138 void ConfigMainWindow::setShowAll(bool b)
1140 if (configList->showAll == b)
1141 return;
1142 configList->showAll = b;
1143 configList->updateListAll();
1144 menuList->showAll = b;
1145 menuList->updateListAll();
1148 void ConfigMainWindow::setShowDebug(bool b)
1150 if (showDebug == b)
1151 return;
1152 showDebug = b;
1155 void ConfigMainWindow::setShowName(bool b)
1157 if (configList->showName == b)
1158 return;
1159 configList->showName = b;
1160 configList->reinit();
1161 menuList->showName = b;
1162 menuList->reinit();
1165 void ConfigMainWindow::setShowRange(bool b)
1167 if (configList->showRange == b)
1168 return;
1169 configList->showRange = b;
1170 configList->reinit();
1171 menuList->showRange = b;
1172 menuList->reinit();
1175 void ConfigMainWindow::setShowData(bool b)
1177 if (configList->showData == b)
1178 return;
1179 configList->showData = b;
1180 configList->reinit();
1181 menuList->showData = b;
1182 menuList->reinit();
1186 * ask for saving configuration before quitting
1187 * TODO ask only when something changed
1189 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1191 if (!sym_change_count) {
1192 e->accept();
1193 return;
1195 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1196 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1197 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1198 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1199 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1200 switch (mb.exec()) {
1201 case QMessageBox::Yes:
1202 conf_write(NULL);
1203 case QMessageBox::No:
1204 e->accept();
1205 break;
1206 case QMessageBox::Cancel:
1207 e->ignore();
1208 break;
1212 void ConfigMainWindow::showIntro(void)
1214 static char str[] = "Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
1215 "For each option, a blank box indicates the feature is disabled, a check\n"
1216 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1217 "as a module. Clicking on the box will cycle through the three states.\n\n"
1218 "If you do not see an option (e.g., a device driver) that you believe\n"
1219 "should be present, try turning on Show All Options under the Options menu.\n"
1220 "Although there is no cross reference yet to help you figure out what other\n"
1221 "options must be enabled to support the option you are interested in, you can\n"
1222 "still view the help of a grayed-out option.\n\n"
1223 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1224 "which you can then match by examining other options.\n\n";
1226 QMessageBox::information(this, "qconf", str);
1229 void ConfigMainWindow::showAbout(void)
1231 static char str[] = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
1232 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1234 QMessageBox::information(this, "qconf", str);
1237 void fixup_rootmenu(struct menu *menu)
1239 struct menu *child;
1240 static int menu_cnt = 0;
1242 menu->flags |= MENU_ROOT;
1243 for (child = menu->list; child; child = child->next) {
1244 if (child->prompt && child->prompt->type == P_MENU) {
1245 menu_cnt++;
1246 fixup_rootmenu(child);
1247 menu_cnt--;
1248 } else if (!menu_cnt)
1249 fixup_rootmenu(child);
1253 static const char *progname;
1255 static void usage(void)
1257 printf("%s <config>\n", progname);
1258 exit(0);
1261 int main(int ac, char** av)
1263 ConfigMainWindow* v;
1264 const char *name;
1266 #ifndef LKC_DIRECT_LINK
1267 kconfig_load();
1268 #endif
1270 progname = av[0];
1271 configApp = new QApplication(ac, av);
1272 #if QT_VERSION >= 300
1273 configSettings = new QSettings;
1274 #endif
1275 if (ac > 1 && av[1][0] == '-') {
1276 switch (av[1][1]) {
1277 case 'h':
1278 case '?':
1279 usage();
1281 name = av[2];
1282 } else
1283 name = av[1];
1284 if (!name)
1285 usage();
1287 conf_parse(name);
1288 fixup_rootmenu(&rootmenu);
1289 conf_read(NULL);
1290 //zconfdump(stdout);
1292 v = new ConfigMainWindow();
1294 //zconfdump(stdout);
1295 v->show();
1296 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1297 configApp->exec();
1299 #if QT_VERSION >= 300
1300 configSettings->writeEntry("/kconfig/qconf/window x", v->pos().x());
1301 configSettings->writeEntry("/kconfig/qconf/window y", v->pos().y());
1302 configSettings->writeEntry("/kconfig/qconf/window width", v->size().width());
1303 configSettings->writeEntry("/kconfig/qconf/window height", v->size().height());
1304 delete configSettings;
1305 #endif
1306 return 0;