MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / scripts / kconfig / qconf.cc
blob0cdbf9dbbd510b27d419a25ab29589515489c794
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>
21 #include <stdlib.h>
23 #include "lkc.h"
24 #include "qconf.h"
26 #include "qconf.moc"
27 #include "images.c"
29 static QApplication *configApp;
31 ConfigSettings::ConfigSettings()
32 : showAll(false), showName(false), showRange(false), showData(false)
36 #if QT_VERSION >= 300
37 /**
38 * Reads the list column settings from the application settings.
40 void ConfigSettings::readListSettings()
42 showAll = readBoolEntry("/kconfig/qconf/showAll", false);
43 showName = readBoolEntry("/kconfig/qconf/showName", false);
44 showRange = readBoolEntry("/kconfig/qconf/showRange", false);
45 showData = readBoolEntry("/kconfig/qconf/showData", false);
48 /**
49 * Reads a list of integer values from the application settings.
51 QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
53 QValueList<int> result;
54 QStringList entryList = readListEntry(key, ok);
55 if (ok) {
56 QStringList::Iterator it;
57 for (it = entryList.begin(); it != entryList.end(); ++it)
58 result.push_back((*it).toInt());
61 return result;
64 /**
65 * Writes a list of integer values to the application settings.
67 bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
69 QStringList stringList;
70 QValueList<int>::ConstIterator it;
72 for (it = value.begin(); it != value.end(); ++it)
73 stringList.push_back(QString::number(*it));
74 return writeEntry(key, stringList);
76 #endif
80 * update all the children of a menu entry
81 * removes/adds the entries from the parent widget as necessary
83 * parent: either the menu list widget or a menu entry widget
84 * menu: entry to be updated
86 template <class P>
87 void ConfigList::updateMenuList(P* parent, struct menu* menu)
89 struct menu* child;
90 ConfigItem* item;
91 ConfigItem* last;
92 bool visible;
93 enum prop_type type;
95 if (!menu) {
96 while ((item = parent->firstChild()))
97 delete item;
98 return;
101 last = parent->firstChild();
102 if (last && !last->goParent)
103 last = 0;
104 for (child = menu->list; child; child = child->next) {
105 item = last ? last->nextSibling() : parent->firstChild();
106 type = child->prompt ? child->prompt->type : P_UNKNOWN;
108 switch (mode) {
109 case menuMode:
110 if (!(child->flags & MENU_ROOT))
111 goto hide;
112 break;
113 case symbolMode:
114 if (child->flags & MENU_ROOT)
115 goto hide;
116 break;
117 default:
118 break;
121 visible = menu_is_visible(child);
122 if (showAll || visible) {
123 if (!item || item->menu != child)
124 item = new ConfigItem(parent, last, child, visible);
125 else
126 item->testUpdateMenu(visible);
128 if (mode == fullMode || mode == menuMode || type != P_MENU)
129 updateMenuList(item, child);
130 else
131 updateMenuList(item, 0);
132 last = item;
133 continue;
135 hide:
136 if (item && item->menu == child) {
137 last = parent->firstChild();
138 if (last == item)
139 last = 0;
140 else while (last->nextSibling() != item)
141 last = last->nextSibling();
142 delete item;
147 #if QT_VERSION >= 300
149 * set the new data
150 * TODO check the value
152 void ConfigItem::okRename(int col)
154 Parent::okRename(col);
155 sym_set_string_value(menu->sym, text(dataColIdx).latin1());
157 #endif
160 * update the displayed of a menu entry
162 void ConfigItem::updateMenu(void)
164 ConfigList* list;
165 struct symbol* sym;
166 struct property *prop;
167 QString prompt;
168 int type;
169 tristate expr;
171 list = listView();
172 if (goParent) {
173 setPixmap(promptColIdx, list->menuBackPix);
174 prompt = "..";
175 goto set_prompt;
178 sym = menu->sym;
179 prop = menu->prompt;
180 prompt = menu_get_prompt(menu);
182 if (prop) switch (prop->type) {
183 case P_MENU:
184 if (list->mode == singleMode || list->mode == symbolMode) {
185 /* a menuconfig entry is displayed differently
186 * depending whether it's at the view root or a child.
188 if (sym && list->rootEntry == menu)
189 break;
190 setPixmap(promptColIdx, list->menuPix);
191 } else {
192 if (sym)
193 break;
194 setPixmap(promptColIdx, 0);
196 goto set_prompt;
197 case P_COMMENT:
198 setPixmap(promptColIdx, 0);
199 goto set_prompt;
200 default:
203 if (!sym)
204 goto set_prompt;
206 setText(nameColIdx, sym->name);
208 type = sym_get_type(sym);
209 switch (type) {
210 case S_BOOLEAN:
211 case S_TRISTATE:
212 char ch;
214 if (!sym_is_changable(sym) && !list->showAll) {
215 setPixmap(promptColIdx, 0);
216 setText(noColIdx, 0);
217 setText(modColIdx, 0);
218 setText(yesColIdx, 0);
219 break;
221 expr = sym_get_tristate_value(sym);
222 switch (expr) {
223 case yes:
224 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
225 setPixmap(promptColIdx, list->choiceYesPix);
226 else
227 setPixmap(promptColIdx, list->symbolYesPix);
228 setText(yesColIdx, "Y");
229 ch = 'Y';
230 break;
231 case mod:
232 setPixmap(promptColIdx, list->symbolModPix);
233 setText(modColIdx, "M");
234 ch = 'M';
235 break;
236 default:
237 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
238 setPixmap(promptColIdx, list->choiceNoPix);
239 else
240 setPixmap(promptColIdx, list->symbolNoPix);
241 setText(noColIdx, "N");
242 ch = 'N';
243 break;
245 if (expr != no)
246 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
247 if (expr != mod)
248 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
249 if (expr != yes)
250 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
252 setText(dataColIdx, QChar(ch));
253 break;
254 case S_INT:
255 case S_HEX:
256 case S_STRING:
257 const char* data;
259 data = sym_get_string_value(sym);
260 #if QT_VERSION >= 300
261 int i = list->mapIdx(dataColIdx);
262 if (i >= 0)
263 setRenameEnabled(i, TRUE);
264 #endif
265 setText(dataColIdx, data);
266 if (type == S_STRING)
267 prompt.sprintf("%s: %s", prompt.latin1(), data);
268 else
269 prompt.sprintf("(%s) %s", data, prompt.latin1());
270 break;
272 if (!sym_has_value(sym) && visible)
273 prompt += " (NEW)";
274 set_prompt:
275 setText(promptColIdx, prompt);
278 void ConfigItem::testUpdateMenu(bool v)
280 ConfigItem* i;
282 visible = v;
283 if (!menu)
284 return;
286 sym_calc_value(menu->sym);
287 if (menu->flags & MENU_CHANGED) {
288 /* the menu entry changed, so update all list items */
289 menu->flags &= ~MENU_CHANGED;
290 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
291 i->updateMenu();
292 } else if (listView()->updateAll)
293 updateMenu();
296 void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
298 ConfigList* list = listView();
300 if (visible) {
301 if (isSelected() && !list->hasFocus() && list->mode == menuMode)
302 Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
303 else
304 Parent::paintCell(p, cg, column, width, align);
305 } else
306 Parent::paintCell(p, list->disabledColorGroup, column, width, align);
310 * construct a menu entry
312 void ConfigItem::init(void)
314 if (menu) {
315 ConfigList* list = listView();
316 nextItem = (ConfigItem*)menu->data;
317 menu->data = this;
319 if (list->mode != fullMode)
320 setOpen(TRUE);
321 sym_calc_value(menu->sym);
323 updateMenu();
327 * destruct a menu entry
329 ConfigItem::~ConfigItem(void)
331 if (menu) {
332 ConfigItem** ip = (ConfigItem**)&menu->data;
333 for (; *ip; ip = &(*ip)->nextItem) {
334 if (*ip == this) {
335 *ip = nextItem;
336 break;
342 void ConfigLineEdit::show(ConfigItem* i)
344 item = i;
345 if (sym_get_string_value(item->menu->sym))
346 setText(sym_get_string_value(item->menu->sym));
347 else
348 setText(0);
349 Parent::show();
350 setFocus();
353 void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
355 switch (e->key()) {
356 case Key_Escape:
357 break;
358 case Key_Return:
359 case Key_Enter:
360 sym_set_string_value(item->menu->sym, text().latin1());
361 parent()->updateList(item);
362 break;
363 default:
364 Parent::keyPressEvent(e);
365 return;
367 e->accept();
368 parent()->list->setFocus();
369 hide();
372 ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv, ConfigSettings* configSettings)
373 : Parent(p), cview(cv),
374 updateAll(false),
375 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
376 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
377 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
378 showAll(false), showName(false), showRange(false), showData(false),
379 rootEntry(0)
381 int i;
383 setSorting(-1);
384 setRootIsDecorated(TRUE);
385 disabledColorGroup = palette().active();
386 disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
387 inactivedColorGroup = palette().active();
388 inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
390 connect(this, SIGNAL(selectionChanged(void)),
391 SLOT(updateSelection(void)));
393 if (configSettings) {
394 showAll = configSettings->showAll;
395 showName = configSettings->showName;
396 showRange = configSettings->showRange;
397 showData = configSettings->showData;
400 for (i = 0; i < colNr; i++)
401 colMap[i] = colRevMap[i] = -1;
402 addColumn(promptColIdx, "Option");
404 reinit();
407 void ConfigList::reinit(void)
409 removeColumn(dataColIdx);
410 removeColumn(yesColIdx);
411 removeColumn(modColIdx);
412 removeColumn(noColIdx);
413 removeColumn(nameColIdx);
415 if (showName)
416 addColumn(nameColIdx, "Name");
417 if (showRange) {
418 addColumn(noColIdx, "N");
419 addColumn(modColIdx, "M");
420 addColumn(yesColIdx, "Y");
422 if (showData)
423 addColumn(dataColIdx, "Value");
425 updateListAll();
428 void ConfigList::updateSelection(void)
430 struct menu *menu;
431 enum prop_type type;
433 ConfigItem* item = (ConfigItem*)selectedItem();
434 if (!item)
435 return;
437 cview->setHelp(item);
439 menu = item->menu;
440 if (!menu)
441 return;
442 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
443 if (mode == menuMode && type == P_MENU)
444 emit menuSelected(menu);
447 void ConfigList::updateList(ConfigItem* item)
449 ConfigItem* last = 0;
451 if (!rootEntry)
452 goto update;
454 if (rootEntry != &rootmenu && (mode == singleMode ||
455 (mode == symbolMode && rootEntry->parent != &rootmenu))) {
456 item = firstChild();
457 if (!item)
458 item = new ConfigItem(this, 0, true);
459 last = item;
461 if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
462 rootEntry->sym && rootEntry->prompt) {
463 item = last ? last->nextSibling() : firstChild();
464 if (!item)
465 item = new ConfigItem(this, last, rootEntry, true);
466 else
467 item->testUpdateMenu(true);
469 updateMenuList(item, rootEntry);
470 triggerUpdate();
471 return;
473 update:
474 updateMenuList(this, rootEntry);
475 triggerUpdate();
478 void ConfigList::setAllOpen(bool open)
480 QListViewItemIterator it(this);
482 for (; it.current(); it++)
483 it.current()->setOpen(open);
486 void ConfigList::setValue(ConfigItem* item, tristate val)
488 struct symbol* sym;
489 int type;
490 tristate oldval;
492 sym = item->menu ? item->menu->sym : 0;
493 if (!sym)
494 return;
496 type = sym_get_type(sym);
497 switch (type) {
498 case S_BOOLEAN:
499 case S_TRISTATE:
500 oldval = sym_get_tristate_value(sym);
502 if (!sym_set_tristate_value(sym, val))
503 return;
504 if (oldval == no && item->menu->list)
505 item->setOpen(TRUE);
506 parent()->updateList(item);
507 break;
511 void ConfigList::changeValue(ConfigItem* item)
513 struct symbol* sym;
514 struct menu* menu;
515 int type, oldexpr, newexpr;
517 menu = item->menu;
518 if (!menu)
519 return;
520 sym = menu->sym;
521 if (!sym) {
522 if (item->menu->list)
523 item->setOpen(!item->isOpen());
524 return;
527 type = sym_get_type(sym);
528 switch (type) {
529 case S_BOOLEAN:
530 case S_TRISTATE:
531 oldexpr = sym_get_tristate_value(sym);
532 newexpr = sym_toggle_tristate_value(sym);
533 if (item->menu->list) {
534 if (oldexpr == newexpr)
535 item->setOpen(!item->isOpen());
536 else if (oldexpr == no)
537 item->setOpen(TRUE);
539 if (oldexpr != newexpr)
540 parent()->updateList(item);
541 break;
542 case S_INT:
543 case S_HEX:
544 case S_STRING:
545 #if QT_VERSION >= 300
546 if (colMap[dataColIdx] >= 0)
547 item->startRename(colMap[dataColIdx]);
548 else
549 #endif
550 parent()->lineEdit->show(item);
551 break;
555 void ConfigList::setRootMenu(struct menu *menu)
557 enum prop_type type;
559 if (rootEntry == menu)
560 return;
561 type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
562 if (type != P_MENU)
563 return;
564 updateMenuList(this, 0);
565 rootEntry = menu;
566 updateListAll();
567 setSelected(currentItem(), hasFocus());
570 void ConfigList::setParentMenu(void)
572 ConfigItem* item;
573 struct menu *oldroot;
575 oldroot = rootEntry;
576 if (rootEntry == &rootmenu)
577 return;
578 setRootMenu(menu_get_parent_menu(rootEntry->parent));
580 QListViewItemIterator it(this);
581 for (; (item = (ConfigItem*)it.current()); it++) {
582 if (item->menu == oldroot) {
583 setCurrentItem(item);
584 ensureItemVisible(item);
585 break;
590 void ConfigList::keyPressEvent(QKeyEvent* ev)
592 QListViewItem* i = currentItem();
593 ConfigItem* item;
594 struct menu *menu;
595 enum prop_type type;
597 if (ev->key() == Key_Escape && mode != fullMode) {
598 emit parentSelected();
599 ev->accept();
600 return;
603 if (!i) {
604 Parent::keyPressEvent(ev);
605 return;
607 item = (ConfigItem*)i;
609 switch (ev->key()) {
610 case Key_Return:
611 case Key_Enter:
612 if (item->goParent) {
613 emit parentSelected();
614 break;
616 menu = item->menu;
617 if (!menu)
618 break;
619 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
620 if (type == P_MENU && rootEntry != menu &&
621 mode != fullMode && mode != menuMode) {
622 emit menuSelected(menu);
623 break;
625 case Key_Space:
626 changeValue(item);
627 break;
628 case Key_N:
629 setValue(item, no);
630 break;
631 case Key_M:
632 setValue(item, mod);
633 break;
634 case Key_Y:
635 setValue(item, yes);
636 break;
637 default:
638 Parent::keyPressEvent(ev);
639 return;
641 ev->accept();
644 void ConfigList::contentsMousePressEvent(QMouseEvent* e)
646 //QPoint p(contentsToViewport(e->pos()));
647 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
648 Parent::contentsMousePressEvent(e);
651 void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
653 QPoint p(contentsToViewport(e->pos()));
654 ConfigItem* item = (ConfigItem*)itemAt(p);
655 struct menu *menu;
656 enum prop_type ptype;
657 const QPixmap* pm;
658 int idx, x;
660 if (!item)
661 goto skip;
663 menu = item->menu;
664 x = header()->offset() + p.x();
665 idx = colRevMap[header()->sectionAt(x)];
666 switch (idx) {
667 case promptColIdx:
668 pm = item->pixmap(promptColIdx);
669 if (pm) {
670 int off = header()->sectionPos(0) + itemMargin() +
671 treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
672 if (x >= off && x < off + pm->width()) {
673 if (item->goParent) {
674 emit parentSelected();
675 break;
676 } else if (!menu)
677 break;
678 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
679 if (ptype == P_MENU && rootEntry != menu &&
680 mode != fullMode && mode != menuMode)
681 emit menuSelected(menu);
682 else
683 changeValue(item);
686 break;
687 case noColIdx:
688 setValue(item, no);
689 break;
690 case modColIdx:
691 setValue(item, mod);
692 break;
693 case yesColIdx:
694 setValue(item, yes);
695 break;
696 case dataColIdx:
697 changeValue(item);
698 break;
701 skip:
702 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
703 Parent::contentsMouseReleaseEvent(e);
706 void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
708 //QPoint p(contentsToViewport(e->pos()));
709 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
710 Parent::contentsMouseMoveEvent(e);
713 void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
715 QPoint p(contentsToViewport(e->pos()));
716 ConfigItem* item = (ConfigItem*)itemAt(p);
717 struct menu *menu;
718 enum prop_type ptype;
720 if (!item)
721 goto skip;
722 if (item->goParent) {
723 emit parentSelected();
724 goto skip;
726 menu = item->menu;
727 if (!menu)
728 goto skip;
729 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
730 if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
731 emit menuSelected(menu);
732 else if (menu->sym)
733 changeValue(item);
735 skip:
736 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
737 Parent::contentsMouseDoubleClickEvent(e);
740 void ConfigList::focusInEvent(QFocusEvent *e)
742 Parent::focusInEvent(e);
744 QListViewItem* item = currentItem();
745 if (!item)
746 return;
748 setSelected(item, TRUE);
749 emit gotFocus();
752 ConfigView* ConfigView::viewList;
754 ConfigView::ConfigView(QWidget* parent, ConfigMainWindow* cview,
755 ConfigSettings *configSettings)
756 : Parent(parent)
758 list = new ConfigList(this, cview, configSettings);
759 lineEdit = new ConfigLineEdit(this);
760 lineEdit->hide();
762 this->nextView = viewList;
763 viewList = this;
766 ConfigView::~ConfigView(void)
768 ConfigView** vp;
770 for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
771 if (*vp == this) {
772 *vp = nextView;
773 break;
778 void ConfigView::updateList(ConfigItem* item)
780 ConfigView* v;
782 for (v = viewList; v; v = v->nextView)
783 v->list->updateList(item);
786 void ConfigView::updateListAll(void)
788 ConfigView* v;
790 for (v = viewList; v; v = v->nextView)
791 v->list->updateListAll();
795 * Construct the complete config widget
797 ConfigMainWindow::ConfigMainWindow(void)
799 QMenuBar* menu;
800 bool ok;
801 int x, y, width, height;
803 QWidget *d = configApp->desktop();
805 ConfigSettings* configSettings = new ConfigSettings();
806 #if QT_VERSION >= 300
807 width = configSettings->readNumEntry("/kconfig/qconf/window width", d->width() - 64);
808 height = configSettings->readNumEntry("/kconfig/qconf/window height", d->height() - 64);
809 resize(width, height);
810 x = configSettings->readNumEntry("/kconfig/qconf/window x", 0, &ok);
811 if (ok)
812 y = configSettings->readNumEntry("/kconfig/qconf/window y", 0, &ok);
813 if (ok)
814 move(x, y);
815 showDebug = configSettings->readBoolEntry("/kconfig/qconf/showDebug", false);
817 // read list settings into configSettings, will be used later for ConfigList setup
818 configSettings->readListSettings();
819 #else
820 width = d->width() - 64;
821 height = d->height() - 64;
822 resize(width, height);
823 showDebug = false;
824 #endif
826 split1 = new QSplitter(this);
827 split1->setOrientation(QSplitter::Horizontal);
828 setCentralWidget(split1);
830 menuView = new ConfigView(split1, this, configSettings);
831 menuList = menuView->list;
833 split2 = new QSplitter(split1);
834 split2->setOrientation(QSplitter::Vertical);
836 // create config tree
837 configView = new ConfigView(split2, this, configSettings);
838 configList = configView->list;
840 helpText = new QTextView(split2);
841 helpText->setTextFormat(Qt::RichText);
843 setTabOrder(configList, helpText);
844 configList->setFocus();
846 menu = menuBar();
847 toolBar = new QToolBar("Tools", this);
849 backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this);
850 connect(backAction, SIGNAL(activated()), SLOT(goBack()));
851 backAction->setEnabled(FALSE);
852 QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this);
853 connect(quitAction, SIGNAL(activated()), SLOT(close()));
854 QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
855 connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
856 QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
857 connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
858 QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
859 connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
860 QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
861 connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
862 QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this);
863 connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
864 QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this);
865 connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
867 QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
868 showNameAction->setToggleAction(TRUE);
869 showNameAction->setOn(configList->showName);
870 connect(showNameAction, SIGNAL(toggled(bool)), SLOT(setShowName(bool)));
871 QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this);
872 showRangeAction->setToggleAction(TRUE);
873 showRangeAction->setOn(configList->showRange);
874 connect(showRangeAction, SIGNAL(toggled(bool)), SLOT(setShowRange(bool)));
875 QAction *showDataAction = new QAction(NULL, "Show Data", 0, this);
876 showDataAction->setToggleAction(TRUE);
877 showDataAction->setOn(configList->showData);
878 connect(showDataAction, SIGNAL(toggled(bool)), SLOT(setShowData(bool)));
879 QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this);
880 showAllAction->setToggleAction(TRUE);
881 showAllAction->setOn(configList->showAll);
882 connect(showAllAction, SIGNAL(toggled(bool)), SLOT(setShowAll(bool)));
883 QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
884 showDebugAction->setToggleAction(TRUE);
885 showDebugAction->setOn(showDebug);
886 connect(showDebugAction, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
888 QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this);
889 connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
890 QAction *showAboutAction = new QAction(NULL, "About", 0, this);
891 connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
893 // init tool bar
894 backAction->addTo(toolBar);
895 toolBar->addSeparator();
896 loadAction->addTo(toolBar);
897 saveAction->addTo(toolBar);
898 toolBar->addSeparator();
899 singleViewAction->addTo(toolBar);
900 splitViewAction->addTo(toolBar);
901 fullViewAction->addTo(toolBar);
903 // create config menu
904 QPopupMenu* config = new QPopupMenu(this);
905 menu->insertItem("&File", config);
906 loadAction->addTo(config);
907 saveAction->addTo(config);
908 saveAsAction->addTo(config);
909 config->insertSeparator();
910 quitAction->addTo(config);
912 // create options menu
913 QPopupMenu* optionMenu = new QPopupMenu(this);
914 menu->insertItem("&Option", optionMenu);
915 showNameAction->addTo(optionMenu);
916 showRangeAction->addTo(optionMenu);
917 showDataAction->addTo(optionMenu);
918 optionMenu->insertSeparator();
919 showAllAction->addTo(optionMenu);
920 showDebugAction->addTo(optionMenu);
922 // create help menu
923 QPopupMenu* helpMenu = new QPopupMenu(this);
924 menu->insertSeparator();
925 menu->insertItem("&Help", helpMenu);
926 showIntroAction->addTo(helpMenu);
927 showAboutAction->addTo(helpMenu);
929 connect(configList, SIGNAL(menuSelected(struct menu *)),
930 SLOT(changeMenu(struct menu *)));
931 connect(configList, SIGNAL(parentSelected()),
932 SLOT(goBack()));
933 connect(menuList, SIGNAL(menuSelected(struct menu *)),
934 SLOT(changeMenu(struct menu *)));
936 connect(configList, SIGNAL(gotFocus(void)),
937 SLOT(listFocusChanged(void)));
938 connect(menuList, SIGNAL(gotFocus(void)),
939 SLOT(listFocusChanged(void)));
941 #if QT_VERSION >= 300
942 QString listMode = configSettings->readEntry("/kconfig/qconf/listMode", "symbol");
943 if (listMode == "single")
944 showSingleView();
945 else if (listMode == "full")
946 showFullView();
947 else /*if (listMode == "split")*/
948 showSplitView();
950 // UI setup done, restore splitter positions
951 QValueList<int> sizes = configSettings->readSizes("/kconfig/qconf/split1", &ok);
952 if (ok)
953 split1->setSizes(sizes);
955 sizes = configSettings->readSizes("/kconfig/qconf/split2", &ok);
956 if (ok)
957 split2->setSizes(sizes);
958 #else
959 showSplitView();
960 #endif
961 delete configSettings;
964 static QString print_filter(const char *str)
966 QRegExp re("[<>&\"\\n]");
967 QString res = str;
968 for (int i = 0; (i = res.find(re, i)) >= 0;) {
969 switch (res[i].latin1()) {
970 case '<':
971 res.replace(i, 1, "&lt;");
972 i += 4;
973 break;
974 case '>':
975 res.replace(i, 1, "&gt;");
976 i += 4;
977 break;
978 case '&':
979 res.replace(i, 1, "&amp;");
980 i += 5;
981 break;
982 case '"':
983 res.replace(i, 1, "&quot;");
984 i += 6;
985 break;
986 case '\n':
987 res.replace(i, 1, "<br>");
988 i += 4;
989 break;
992 return res;
995 static void expr_print_help(void *data, const char *str)
997 ((QString*)data)->append(print_filter(str));
1001 * display a new help entry as soon as a new menu entry is selected
1003 void ConfigMainWindow::setHelp(QListViewItem* item)
1005 struct symbol* sym;
1006 struct menu* menu = 0;
1008 configList->parent()->lineEdit->hide();
1009 if (item)
1010 menu = ((ConfigItem*)item)->menu;
1011 if (!menu) {
1012 helpText->setText(NULL);
1013 return;
1016 QString head, debug, help;
1017 menu = ((ConfigItem*)item)->menu;
1018 sym = menu->sym;
1019 if (sym) {
1020 if (menu->prompt) {
1021 head += "<big><b>";
1022 head += print_filter(menu->prompt->text);
1023 head += "</b></big>";
1024 if (sym->name) {
1025 head += " (";
1026 head += print_filter(sym->name);
1027 head += ")";
1029 } else if (sym->name) {
1030 head += "<big><b>";
1031 head += print_filter(sym->name);
1032 head += "</b></big>";
1034 head += "<br><br>";
1036 if (showDebug) {
1037 debug += "type: ";
1038 debug += print_filter(sym_type_name(sym->type));
1039 if (sym_is_choice(sym))
1040 debug += " (choice)";
1041 debug += "<br>";
1042 if (sym->rev_dep.expr) {
1043 debug += "reverse dep: ";
1044 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1045 debug += "<br>";
1047 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1048 switch (prop->type) {
1049 case P_PROMPT:
1050 case P_MENU:
1051 debug += "prompt: ";
1052 debug += print_filter(prop->text);
1053 debug += "<br>";
1054 break;
1055 case P_DEFAULT:
1056 debug += "default: ";
1057 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1058 debug += "<br>";
1059 break;
1060 case P_CHOICE:
1061 if (sym_is_choice(sym)) {
1062 debug += "choice: ";
1063 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1064 debug += "<br>";
1066 break;
1067 case P_SELECT:
1068 debug += "select: ";
1069 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1070 debug += "<br>";
1071 break;
1072 case P_RANGE:
1073 debug += "range: ";
1074 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1075 debug += "<br>";
1076 break;
1077 default:
1078 debug += "unknown property: ";
1079 debug += prop_get_type_name(prop->type);
1080 debug += "<br>";
1082 if (prop->visible.expr) {
1083 debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
1084 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1085 debug += "<br>";
1088 debug += "<br>";
1091 help = print_filter(sym->help);
1092 } else if (menu->prompt) {
1093 head += "<big><b>";
1094 head += print_filter(menu->prompt->text);
1095 head += "</b></big><br><br>";
1096 if (showDebug) {
1097 if (menu->prompt->visible.expr) {
1098 debug += "&nbsp;&nbsp;dep: ";
1099 expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
1100 debug += "<br><br>";
1104 if (showDebug)
1105 debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
1106 helpText->setText(head + debug + help);
1109 void ConfigMainWindow::loadConfig(void)
1111 QString s = QFileDialog::getOpenFileName(".config", NULL, this);
1112 if (s.isNull())
1113 return;
1114 if (conf_read(s.latin1()))
1115 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1116 ConfigView::updateListAll();
1119 void ConfigMainWindow::saveConfig(void)
1121 if (conf_write(NULL))
1122 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1125 void ConfigMainWindow::saveConfigAs(void)
1127 QString s = QFileDialog::getSaveFileName(".config", NULL, this);
1128 if (s.isNull())
1129 return;
1130 if (conf_write(s.latin1()))
1131 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1134 void ConfigMainWindow::changeMenu(struct menu *menu)
1136 configList->setRootMenu(menu);
1137 backAction->setEnabled(TRUE);
1140 void ConfigMainWindow::listFocusChanged(void)
1142 if (menuList->hasFocus()) {
1143 if (menuList->mode == menuMode)
1144 configList->clearSelection();
1145 setHelp(menuList->selectedItem());
1146 } else if (configList->hasFocus()) {
1147 setHelp(configList->selectedItem());
1151 void ConfigMainWindow::goBack(void)
1153 ConfigItem* item;
1155 configList->setParentMenu();
1156 if (configList->rootEntry == &rootmenu)
1157 backAction->setEnabled(FALSE);
1158 item = (ConfigItem*)menuList->selectedItem();
1159 while (item) {
1160 if (item->menu == configList->rootEntry) {
1161 menuList->setSelected(item, TRUE);
1162 break;
1164 item = (ConfigItem*)item->parent();
1168 void ConfigMainWindow::showSingleView(void)
1170 menuView->hide();
1171 menuList->setRootMenu(0);
1172 configList->mode = singleMode;
1173 if (configList->rootEntry == &rootmenu)
1174 configList->updateListAll();
1175 else
1176 configList->setRootMenu(&rootmenu);
1177 configList->setAllOpen(TRUE);
1178 configList->setFocus();
1181 void ConfigMainWindow::showSplitView(void)
1183 configList->mode = symbolMode;
1184 if (configList->rootEntry == &rootmenu)
1185 configList->updateListAll();
1186 else
1187 configList->setRootMenu(&rootmenu);
1188 configList->setAllOpen(TRUE);
1189 configApp->processEvents();
1190 menuList->mode = menuMode;
1191 menuList->setRootMenu(&rootmenu);
1192 menuList->setAllOpen(TRUE);
1193 menuView->show();
1194 menuList->setFocus();
1197 void ConfigMainWindow::showFullView(void)
1199 menuView->hide();
1200 menuList->setRootMenu(0);
1201 configList->mode = fullMode;
1202 if (configList->rootEntry == &rootmenu)
1203 configList->updateListAll();
1204 else
1205 configList->setRootMenu(&rootmenu);
1206 configList->setAllOpen(FALSE);
1207 configList->setFocus();
1210 void ConfigMainWindow::setShowAll(bool b)
1212 if (configList->showAll == b)
1213 return;
1214 configList->showAll = b;
1215 configList->updateListAll();
1216 menuList->showAll = b;
1217 menuList->updateListAll();
1220 void ConfigMainWindow::setShowDebug(bool b)
1222 if (showDebug == b)
1223 return;
1224 showDebug = b;
1227 void ConfigMainWindow::setShowName(bool b)
1229 if (configList->showName == b)
1230 return;
1231 configList->showName = b;
1232 configList->reinit();
1233 menuList->showName = b;
1234 menuList->reinit();
1237 void ConfigMainWindow::setShowRange(bool b)
1239 if (configList->showRange == b)
1240 return;
1241 configList->showRange = b;
1242 configList->reinit();
1243 menuList->showRange = b;
1244 menuList->reinit();
1247 void ConfigMainWindow::setShowData(bool b)
1249 if (configList->showData == b)
1250 return;
1251 configList->showData = b;
1252 configList->reinit();
1253 menuList->showData = b;
1254 menuList->reinit();
1258 * ask for saving configuration before quitting
1259 * TODO ask only when something changed
1261 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1263 if (!sym_change_count) {
1264 e->accept();
1265 return;
1267 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1268 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1269 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1270 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1271 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1272 switch (mb.exec()) {
1273 case QMessageBox::Yes:
1274 conf_write(NULL);
1275 case QMessageBox::No:
1276 e->accept();
1277 break;
1278 case QMessageBox::Cancel:
1279 e->ignore();
1280 break;
1284 void ConfigMainWindow::showIntro(void)
1286 static char str[] = "Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
1287 "For each option, a blank box indicates the feature is disabled, a check\n"
1288 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1289 "as a module. Clicking on the box will cycle through the three states.\n\n"
1290 "If you do not see an option (e.g., a device driver) that you believe\n"
1291 "should be present, try turning on Show All Options under the Options menu.\n"
1292 "Although there is no cross reference yet to help you figure out what other\n"
1293 "options must be enabled to support the option you are interested in, you can\n"
1294 "still view the help of a grayed-out option.\n\n"
1295 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1296 "which you can then match by examining other options.\n\n";
1298 QMessageBox::information(this, "qconf", str);
1301 void ConfigMainWindow::showAbout(void)
1303 static char str[] = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
1304 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1306 QMessageBox::information(this, "qconf", str);
1309 void ConfigMainWindow::saveSettings(void)
1311 #if QT_VERSION >= 300
1312 ConfigSettings *configSettings = new ConfigSettings;
1313 configSettings->writeEntry("/kconfig/qconf/window x", pos().x());
1314 configSettings->writeEntry("/kconfig/qconf/window y", pos().y());
1315 configSettings->writeEntry("/kconfig/qconf/window width", size().width());
1316 configSettings->writeEntry("/kconfig/qconf/window height", size().height());
1317 configSettings->writeEntry("/kconfig/qconf/showName", configList->showName);
1318 configSettings->writeEntry("/kconfig/qconf/showRange", configList->showRange);
1319 configSettings->writeEntry("/kconfig/qconf/showData", configList->showData);
1320 configSettings->writeEntry("/kconfig/qconf/showAll", configList->showAll);
1321 configSettings->writeEntry("/kconfig/qconf/showDebug", showDebug);
1323 QString entry;
1324 switch(configList->mode) {
1325 case singleMode :
1326 entry = "single";
1327 break;
1329 case symbolMode :
1330 entry = "split";
1331 break;
1333 case fullMode :
1334 entry = "full";
1335 break;
1337 configSettings->writeEntry("/kconfig/qconf/listMode", entry);
1339 configSettings->writeSizes("/kconfig/qconf/split1", split1->sizes());
1340 configSettings->writeSizes("/kconfig/qconf/split2", split2->sizes());
1342 delete configSettings;
1343 #endif
1346 void fixup_rootmenu(struct menu *menu)
1348 struct menu *child;
1349 static int menu_cnt = 0;
1351 menu->flags |= MENU_ROOT;
1352 for (child = menu->list; child; child = child->next) {
1353 if (child->prompt && child->prompt->type == P_MENU) {
1354 menu_cnt++;
1355 fixup_rootmenu(child);
1356 menu_cnt--;
1357 } else if (!menu_cnt)
1358 fixup_rootmenu(child);
1362 static const char *progname;
1364 static void usage(void)
1366 printf("%s <config>\n", progname);
1367 exit(0);
1370 int main(int ac, char** av)
1372 ConfigMainWindow* v;
1373 const char *name;
1375 #ifndef LKC_DIRECT_LINK
1376 kconfig_load();
1377 #endif
1379 progname = av[0];
1380 configApp = new QApplication(ac, av);
1381 if (ac > 1 && av[1][0] == '-') {
1382 switch (av[1][1]) {
1383 case 'h':
1384 case '?':
1385 usage();
1387 name = av[2];
1388 } else
1389 name = av[1];
1390 if (!name)
1391 usage();
1393 conf_parse(name);
1394 fixup_rootmenu(&rootmenu);
1395 conf_read(NULL);
1396 //zconfdump(stdout);
1398 v = new ConfigMainWindow();
1400 //zconfdump(stdout);
1401 v->show();
1402 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1403 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1404 configApp->exec();
1406 return 0;