Linux v2.6.13
[linux-2.6/next.git] / scripts / kconfig / qconf.cc
blob4590cd31623fd89791cd213eeb9ab15ca499753b
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 #ifdef _
30 # undef _
31 # define _ qgettext
32 #endif
34 static QApplication *configApp;
36 static inline QString qgettext(const char* str)
38 return QString::fromLocal8Bit(gettext(str));
41 static inline QString qgettext(const QString& str)
43 return QString::fromLocal8Bit(gettext(str.latin1()));
46 ConfigSettings::ConfigSettings()
47 : showAll(false), showName(false), showRange(false), showData(false)
51 #if QT_VERSION >= 300
52 /**
53 * Reads the list column settings from the application settings.
55 void ConfigSettings::readListSettings()
57 showAll = readBoolEntry("/kconfig/qconf/showAll", false);
58 showName = readBoolEntry("/kconfig/qconf/showName", false);
59 showRange = readBoolEntry("/kconfig/qconf/showRange", false);
60 showData = readBoolEntry("/kconfig/qconf/showData", false);
63 /**
64 * Reads a list of integer values from the application settings.
66 QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
68 QValueList<int> result;
69 QStringList entryList = readListEntry(key, ok);
70 if (ok) {
71 QStringList::Iterator it;
72 for (it = entryList.begin(); it != entryList.end(); ++it)
73 result.push_back((*it).toInt());
76 return result;
79 /**
80 * Writes a list of integer values to the application settings.
82 bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
84 QStringList stringList;
85 QValueList<int>::ConstIterator it;
87 for (it = value.begin(); it != value.end(); ++it)
88 stringList.push_back(QString::number(*it));
89 return writeEntry(key, stringList);
91 #endif
95 * update all the children of a menu entry
96 * removes/adds the entries from the parent widget as necessary
98 * parent: either the menu list widget or a menu entry widget
99 * menu: entry to be updated
101 template <class P>
102 void ConfigList::updateMenuList(P* parent, struct menu* menu)
104 struct menu* child;
105 ConfigItem* item;
106 ConfigItem* last;
107 bool visible;
108 enum prop_type type;
110 if (!menu) {
111 while ((item = parent->firstChild()))
112 delete item;
113 return;
116 last = parent->firstChild();
117 if (last && !last->goParent)
118 last = 0;
119 for (child = menu->list; child; child = child->next) {
120 item = last ? last->nextSibling() : parent->firstChild();
121 type = child->prompt ? child->prompt->type : P_UNKNOWN;
123 switch (mode) {
124 case menuMode:
125 if (!(child->flags & MENU_ROOT))
126 goto hide;
127 break;
128 case symbolMode:
129 if (child->flags & MENU_ROOT)
130 goto hide;
131 break;
132 default:
133 break;
136 visible = menu_is_visible(child);
137 if (showAll || visible) {
138 if (!item || item->menu != child)
139 item = new ConfigItem(parent, last, child, visible);
140 else
141 item->testUpdateMenu(visible);
143 if (mode == fullMode || mode == menuMode || type != P_MENU)
144 updateMenuList(item, child);
145 else
146 updateMenuList(item, 0);
147 last = item;
148 continue;
150 hide:
151 if (item && item->menu == child) {
152 last = parent->firstChild();
153 if (last == item)
154 last = 0;
155 else while (last->nextSibling() != item)
156 last = last->nextSibling();
157 delete item;
162 #if QT_VERSION >= 300
164 * set the new data
165 * TODO check the value
167 void ConfigItem::okRename(int col)
169 Parent::okRename(col);
170 sym_set_string_value(menu->sym, text(dataColIdx).latin1());
172 #endif
175 * update the displayed of a menu entry
177 void ConfigItem::updateMenu(void)
179 ConfigList* list;
180 struct symbol* sym;
181 struct property *prop;
182 QString prompt;
183 int type;
184 tristate expr;
186 list = listView();
187 if (goParent) {
188 setPixmap(promptColIdx, list->menuBackPix);
189 prompt = "..";
190 goto set_prompt;
193 sym = menu->sym;
194 prop = menu->prompt;
195 prompt = QString::fromLocal8Bit(menu_get_prompt(menu));
197 if (prop) switch (prop->type) {
198 case P_MENU:
199 if (list->mode == singleMode || list->mode == symbolMode) {
200 /* a menuconfig entry is displayed differently
201 * depending whether it's at the view root or a child.
203 if (sym && list->rootEntry == menu)
204 break;
205 setPixmap(promptColIdx, list->menuPix);
206 } else {
207 if (sym)
208 break;
209 setPixmap(promptColIdx, 0);
211 goto set_prompt;
212 case P_COMMENT:
213 setPixmap(promptColIdx, 0);
214 goto set_prompt;
215 default:
218 if (!sym)
219 goto set_prompt;
221 setText(nameColIdx, QString::fromLocal8Bit(sym->name));
223 type = sym_get_type(sym);
224 switch (type) {
225 case S_BOOLEAN:
226 case S_TRISTATE:
227 char ch;
229 if (!sym_is_changable(sym) && !list->showAll) {
230 setPixmap(promptColIdx, 0);
231 setText(noColIdx, QString::null);
232 setText(modColIdx, QString::null);
233 setText(yesColIdx, QString::null);
234 break;
236 expr = sym_get_tristate_value(sym);
237 switch (expr) {
238 case yes:
239 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
240 setPixmap(promptColIdx, list->choiceYesPix);
241 else
242 setPixmap(promptColIdx, list->symbolYesPix);
243 setText(yesColIdx, "Y");
244 ch = 'Y';
245 break;
246 case mod:
247 setPixmap(promptColIdx, list->symbolModPix);
248 setText(modColIdx, "M");
249 ch = 'M';
250 break;
251 default:
252 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
253 setPixmap(promptColIdx, list->choiceNoPix);
254 else
255 setPixmap(promptColIdx, list->symbolNoPix);
256 setText(noColIdx, "N");
257 ch = 'N';
258 break;
260 if (expr != no)
261 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
262 if (expr != mod)
263 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
264 if (expr != yes)
265 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
267 setText(dataColIdx, QChar(ch));
268 break;
269 case S_INT:
270 case S_HEX:
271 case S_STRING:
272 const char* data;
274 data = sym_get_string_value(sym);
276 #if QT_VERSION >= 300
277 int i = list->mapIdx(dataColIdx);
278 if (i >= 0)
279 setRenameEnabled(i, TRUE);
280 #endif
281 setText(dataColIdx, data);
282 if (type == S_STRING)
283 prompt = QString("%1: %2").arg(prompt).arg(data);
284 else
285 prompt = QString("(%2) %1").arg(prompt).arg(data);
286 break;
288 if (!sym_has_value(sym) && visible)
289 prompt += " (NEW)";
290 set_prompt:
291 setText(promptColIdx, prompt);
294 void ConfigItem::testUpdateMenu(bool v)
296 ConfigItem* i;
298 visible = v;
299 if (!menu)
300 return;
302 sym_calc_value(menu->sym);
303 if (menu->flags & MENU_CHANGED) {
304 /* the menu entry changed, so update all list items */
305 menu->flags &= ~MENU_CHANGED;
306 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
307 i->updateMenu();
308 } else if (listView()->updateAll)
309 updateMenu();
312 void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
314 ConfigList* list = listView();
316 if (visible) {
317 if (isSelected() && !list->hasFocus() && list->mode == menuMode)
318 Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
319 else
320 Parent::paintCell(p, cg, column, width, align);
321 } else
322 Parent::paintCell(p, list->disabledColorGroup, column, width, align);
326 * construct a menu entry
328 void ConfigItem::init(void)
330 if (menu) {
331 ConfigList* list = listView();
332 nextItem = (ConfigItem*)menu->data;
333 menu->data = this;
335 if (list->mode != fullMode)
336 setOpen(TRUE);
337 sym_calc_value(menu->sym);
339 updateMenu();
343 * destruct a menu entry
345 ConfigItem::~ConfigItem(void)
347 if (menu) {
348 ConfigItem** ip = (ConfigItem**)&menu->data;
349 for (; *ip; ip = &(*ip)->nextItem) {
350 if (*ip == this) {
351 *ip = nextItem;
352 break;
358 void ConfigLineEdit::show(ConfigItem* i)
360 item = i;
361 if (sym_get_string_value(item->menu->sym))
362 setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
363 else
364 setText(QString::null);
365 Parent::show();
366 setFocus();
369 void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
371 switch (e->key()) {
372 case Key_Escape:
373 break;
374 case Key_Return:
375 case Key_Enter:
376 sym_set_string_value(item->menu->sym, text().latin1());
377 parent()->updateList(item);
378 break;
379 default:
380 Parent::keyPressEvent(e);
381 return;
383 e->accept();
384 parent()->list->setFocus();
385 hide();
388 ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv, ConfigSettings* configSettings)
389 : Parent(p), cview(cv),
390 updateAll(false),
391 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
392 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
393 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
394 showAll(false), showName(false), showRange(false), showData(false),
395 rootEntry(0)
397 int i;
399 setSorting(-1);
400 setRootIsDecorated(TRUE);
401 disabledColorGroup = palette().active();
402 disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
403 inactivedColorGroup = palette().active();
404 inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
406 connect(this, SIGNAL(selectionChanged(void)),
407 SLOT(updateSelection(void)));
409 if (configSettings) {
410 showAll = configSettings->showAll;
411 showName = configSettings->showName;
412 showRange = configSettings->showRange;
413 showData = configSettings->showData;
416 for (i = 0; i < colNr; i++)
417 colMap[i] = colRevMap[i] = -1;
418 addColumn(promptColIdx, "Option");
420 reinit();
423 void ConfigList::reinit(void)
425 removeColumn(dataColIdx);
426 removeColumn(yesColIdx);
427 removeColumn(modColIdx);
428 removeColumn(noColIdx);
429 removeColumn(nameColIdx);
431 if (showName)
432 addColumn(nameColIdx, "Name");
433 if (showRange) {
434 addColumn(noColIdx, "N");
435 addColumn(modColIdx, "M");
436 addColumn(yesColIdx, "Y");
438 if (showData)
439 addColumn(dataColIdx, "Value");
441 updateListAll();
444 void ConfigList::updateSelection(void)
446 struct menu *menu;
447 enum prop_type type;
449 ConfigItem* item = (ConfigItem*)selectedItem();
450 if (!item)
451 return;
453 cview->setHelp(item);
455 menu = item->menu;
456 if (!menu)
457 return;
458 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
459 if (mode == menuMode && type == P_MENU)
460 emit menuSelected(menu);
463 void ConfigList::updateList(ConfigItem* item)
465 ConfigItem* last = 0;
467 if (!rootEntry)
468 goto update;
470 if (rootEntry != &rootmenu && (mode == singleMode ||
471 (mode == symbolMode && rootEntry->parent != &rootmenu))) {
472 item = firstChild();
473 if (!item)
474 item = new ConfigItem(this, 0, true);
475 last = item;
477 if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
478 rootEntry->sym && rootEntry->prompt) {
479 item = last ? last->nextSibling() : firstChild();
480 if (!item)
481 item = new ConfigItem(this, last, rootEntry, true);
482 else
483 item->testUpdateMenu(true);
485 updateMenuList(item, rootEntry);
486 triggerUpdate();
487 return;
489 update:
490 updateMenuList(this, rootEntry);
491 triggerUpdate();
494 void ConfigList::setAllOpen(bool open)
496 QListViewItemIterator it(this);
498 for (; it.current(); it++)
499 it.current()->setOpen(open);
502 void ConfigList::setValue(ConfigItem* item, tristate val)
504 struct symbol* sym;
505 int type;
506 tristate oldval;
508 sym = item->menu ? item->menu->sym : 0;
509 if (!sym)
510 return;
512 type = sym_get_type(sym);
513 switch (type) {
514 case S_BOOLEAN:
515 case S_TRISTATE:
516 oldval = sym_get_tristate_value(sym);
518 if (!sym_set_tristate_value(sym, val))
519 return;
520 if (oldval == no && item->menu->list)
521 item->setOpen(TRUE);
522 parent()->updateList(item);
523 break;
527 void ConfigList::changeValue(ConfigItem* item)
529 struct symbol* sym;
530 struct menu* menu;
531 int type, oldexpr, newexpr;
533 menu = item->menu;
534 if (!menu)
535 return;
536 sym = menu->sym;
537 if (!sym) {
538 if (item->menu->list)
539 item->setOpen(!item->isOpen());
540 return;
543 type = sym_get_type(sym);
544 switch (type) {
545 case S_BOOLEAN:
546 case S_TRISTATE:
547 oldexpr = sym_get_tristate_value(sym);
548 newexpr = sym_toggle_tristate_value(sym);
549 if (item->menu->list) {
550 if (oldexpr == newexpr)
551 item->setOpen(!item->isOpen());
552 else if (oldexpr == no)
553 item->setOpen(TRUE);
555 if (oldexpr != newexpr)
556 parent()->updateList(item);
557 break;
558 case S_INT:
559 case S_HEX:
560 case S_STRING:
561 #if QT_VERSION >= 300
562 if (colMap[dataColIdx] >= 0)
563 item->startRename(colMap[dataColIdx]);
564 else
565 #endif
566 parent()->lineEdit->show(item);
567 break;
571 void ConfigList::setRootMenu(struct menu *menu)
573 enum prop_type type;
575 if (rootEntry == menu)
576 return;
577 type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
578 if (type != P_MENU)
579 return;
580 updateMenuList(this, 0);
581 rootEntry = menu;
582 updateListAll();
583 setSelected(currentItem(), hasFocus());
586 void ConfigList::setParentMenu(void)
588 ConfigItem* item;
589 struct menu *oldroot;
591 oldroot = rootEntry;
592 if (rootEntry == &rootmenu)
593 return;
594 setRootMenu(menu_get_parent_menu(rootEntry->parent));
596 QListViewItemIterator it(this);
597 for (; (item = (ConfigItem*)it.current()); it++) {
598 if (item->menu == oldroot) {
599 setCurrentItem(item);
600 ensureItemVisible(item);
601 break;
606 void ConfigList::keyPressEvent(QKeyEvent* ev)
608 QListViewItem* i = currentItem();
609 ConfigItem* item;
610 struct menu *menu;
611 enum prop_type type;
613 if (ev->key() == Key_Escape && mode != fullMode) {
614 emit parentSelected();
615 ev->accept();
616 return;
619 if (!i) {
620 Parent::keyPressEvent(ev);
621 return;
623 item = (ConfigItem*)i;
625 switch (ev->key()) {
626 case Key_Return:
627 case Key_Enter:
628 if (item->goParent) {
629 emit parentSelected();
630 break;
632 menu = item->menu;
633 if (!menu)
634 break;
635 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
636 if (type == P_MENU && rootEntry != menu &&
637 mode != fullMode && mode != menuMode) {
638 emit menuSelected(menu);
639 break;
641 case Key_Space:
642 changeValue(item);
643 break;
644 case Key_N:
645 setValue(item, no);
646 break;
647 case Key_M:
648 setValue(item, mod);
649 break;
650 case Key_Y:
651 setValue(item, yes);
652 break;
653 default:
654 Parent::keyPressEvent(ev);
655 return;
657 ev->accept();
660 void ConfigList::contentsMousePressEvent(QMouseEvent* e)
662 //QPoint p(contentsToViewport(e->pos()));
663 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
664 Parent::contentsMousePressEvent(e);
667 void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
669 QPoint p(contentsToViewport(e->pos()));
670 ConfigItem* item = (ConfigItem*)itemAt(p);
671 struct menu *menu;
672 enum prop_type ptype;
673 const QPixmap* pm;
674 int idx, x;
676 if (!item)
677 goto skip;
679 menu = item->menu;
680 x = header()->offset() + p.x();
681 idx = colRevMap[header()->sectionAt(x)];
682 switch (idx) {
683 case promptColIdx:
684 pm = item->pixmap(promptColIdx);
685 if (pm) {
686 int off = header()->sectionPos(0) + itemMargin() +
687 treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
688 if (x >= off && x < off + pm->width()) {
689 if (item->goParent) {
690 emit parentSelected();
691 break;
692 } else if (!menu)
693 break;
694 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
695 if (ptype == P_MENU && rootEntry != menu &&
696 mode != fullMode && mode != menuMode)
697 emit menuSelected(menu);
698 else
699 changeValue(item);
702 break;
703 case noColIdx:
704 setValue(item, no);
705 break;
706 case modColIdx:
707 setValue(item, mod);
708 break;
709 case yesColIdx:
710 setValue(item, yes);
711 break;
712 case dataColIdx:
713 changeValue(item);
714 break;
717 skip:
718 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
719 Parent::contentsMouseReleaseEvent(e);
722 void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
724 //QPoint p(contentsToViewport(e->pos()));
725 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
726 Parent::contentsMouseMoveEvent(e);
729 void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
731 QPoint p(contentsToViewport(e->pos()));
732 ConfigItem* item = (ConfigItem*)itemAt(p);
733 struct menu *menu;
734 enum prop_type ptype;
736 if (!item)
737 goto skip;
738 if (item->goParent) {
739 emit parentSelected();
740 goto skip;
742 menu = item->menu;
743 if (!menu)
744 goto skip;
745 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
746 if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
747 emit menuSelected(menu);
748 else if (menu->sym)
749 changeValue(item);
751 skip:
752 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
753 Parent::contentsMouseDoubleClickEvent(e);
756 void ConfigList::focusInEvent(QFocusEvent *e)
758 Parent::focusInEvent(e);
760 QListViewItem* item = currentItem();
761 if (!item)
762 return;
764 setSelected(item, TRUE);
765 emit gotFocus();
768 ConfigView* ConfigView::viewList;
770 ConfigView::ConfigView(QWidget* parent, ConfigMainWindow* cview,
771 ConfigSettings *configSettings)
772 : Parent(parent)
774 list = new ConfigList(this, cview, configSettings);
775 lineEdit = new ConfigLineEdit(this);
776 lineEdit->hide();
778 this->nextView = viewList;
779 viewList = this;
782 ConfigView::~ConfigView(void)
784 ConfigView** vp;
786 for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
787 if (*vp == this) {
788 *vp = nextView;
789 break;
794 void ConfigView::updateList(ConfigItem* item)
796 ConfigView* v;
798 for (v = viewList; v; v = v->nextView)
799 v->list->updateList(item);
802 void ConfigView::updateListAll(void)
804 ConfigView* v;
806 for (v = viewList; v; v = v->nextView)
807 v->list->updateListAll();
811 * Construct the complete config widget
813 ConfigMainWindow::ConfigMainWindow(void)
815 QMenuBar* menu;
816 bool ok;
817 int x, y, width, height;
819 QWidget *d = configApp->desktop();
821 ConfigSettings* configSettings = new ConfigSettings();
822 #if QT_VERSION >= 300
823 width = configSettings->readNumEntry("/kconfig/qconf/window width", d->width() - 64);
824 height = configSettings->readNumEntry("/kconfig/qconf/window height", d->height() - 64);
825 resize(width, height);
826 x = configSettings->readNumEntry("/kconfig/qconf/window x", 0, &ok);
827 if (ok)
828 y = configSettings->readNumEntry("/kconfig/qconf/window y", 0, &ok);
829 if (ok)
830 move(x, y);
831 showDebug = configSettings->readBoolEntry("/kconfig/qconf/showDebug", false);
833 // read list settings into configSettings, will be used later for ConfigList setup
834 configSettings->readListSettings();
835 #else
836 width = d->width() - 64;
837 height = d->height() - 64;
838 resize(width, height);
839 showDebug = false;
840 #endif
842 split1 = new QSplitter(this);
843 split1->setOrientation(QSplitter::Horizontal);
844 setCentralWidget(split1);
846 menuView = new ConfigView(split1, this, configSettings);
847 menuList = menuView->list;
849 split2 = new QSplitter(split1);
850 split2->setOrientation(QSplitter::Vertical);
852 // create config tree
853 configView = new ConfigView(split2, this, configSettings);
854 configList = configView->list;
856 helpText = new QTextView(split2);
857 helpText->setTextFormat(Qt::RichText);
859 setTabOrder(configList, helpText);
860 configList->setFocus();
862 menu = menuBar();
863 toolBar = new QToolBar("Tools", this);
865 backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this);
866 connect(backAction, SIGNAL(activated()), SLOT(goBack()));
867 backAction->setEnabled(FALSE);
868 QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this);
869 connect(quitAction, SIGNAL(activated()), SLOT(close()));
870 QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
871 connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
872 QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
873 connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
874 QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
875 connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
876 QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
877 connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
878 QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this);
879 connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
880 QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this);
881 connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
883 QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
884 showNameAction->setToggleAction(TRUE);
885 showNameAction->setOn(configList->showName);
886 connect(showNameAction, SIGNAL(toggled(bool)), SLOT(setShowName(bool)));
887 QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this);
888 showRangeAction->setToggleAction(TRUE);
889 showRangeAction->setOn(configList->showRange);
890 connect(showRangeAction, SIGNAL(toggled(bool)), SLOT(setShowRange(bool)));
891 QAction *showDataAction = new QAction(NULL, "Show Data", 0, this);
892 showDataAction->setToggleAction(TRUE);
893 showDataAction->setOn(configList->showData);
894 connect(showDataAction, SIGNAL(toggled(bool)), SLOT(setShowData(bool)));
895 QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this);
896 showAllAction->setToggleAction(TRUE);
897 showAllAction->setOn(configList->showAll);
898 connect(showAllAction, SIGNAL(toggled(bool)), SLOT(setShowAll(bool)));
899 QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
900 showDebugAction->setToggleAction(TRUE);
901 showDebugAction->setOn(showDebug);
902 connect(showDebugAction, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
904 QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this);
905 connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
906 QAction *showAboutAction = new QAction(NULL, "About", 0, this);
907 connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
909 // init tool bar
910 backAction->addTo(toolBar);
911 toolBar->addSeparator();
912 loadAction->addTo(toolBar);
913 saveAction->addTo(toolBar);
914 toolBar->addSeparator();
915 singleViewAction->addTo(toolBar);
916 splitViewAction->addTo(toolBar);
917 fullViewAction->addTo(toolBar);
919 // create config menu
920 QPopupMenu* config = new QPopupMenu(this);
921 menu->insertItem("&File", config);
922 loadAction->addTo(config);
923 saveAction->addTo(config);
924 saveAsAction->addTo(config);
925 config->insertSeparator();
926 quitAction->addTo(config);
928 // create options menu
929 QPopupMenu* optionMenu = new QPopupMenu(this);
930 menu->insertItem("&Option", optionMenu);
931 showNameAction->addTo(optionMenu);
932 showRangeAction->addTo(optionMenu);
933 showDataAction->addTo(optionMenu);
934 optionMenu->insertSeparator();
935 showAllAction->addTo(optionMenu);
936 showDebugAction->addTo(optionMenu);
938 // create help menu
939 QPopupMenu* helpMenu = new QPopupMenu(this);
940 menu->insertSeparator();
941 menu->insertItem("&Help", helpMenu);
942 showIntroAction->addTo(helpMenu);
943 showAboutAction->addTo(helpMenu);
945 connect(configList, SIGNAL(menuSelected(struct menu *)),
946 SLOT(changeMenu(struct menu *)));
947 connect(configList, SIGNAL(parentSelected()),
948 SLOT(goBack()));
949 connect(menuList, SIGNAL(menuSelected(struct menu *)),
950 SLOT(changeMenu(struct menu *)));
952 connect(configList, SIGNAL(gotFocus(void)),
953 SLOT(listFocusChanged(void)));
954 connect(menuList, SIGNAL(gotFocus(void)),
955 SLOT(listFocusChanged(void)));
957 #if QT_VERSION >= 300
958 QString listMode = configSettings->readEntry("/kconfig/qconf/listMode", "symbol");
959 if (listMode == "single")
960 showSingleView();
961 else if (listMode == "full")
962 showFullView();
963 else /*if (listMode == "split")*/
964 showSplitView();
966 // UI setup done, restore splitter positions
967 QValueList<int> sizes = configSettings->readSizes("/kconfig/qconf/split1", &ok);
968 if (ok)
969 split1->setSizes(sizes);
971 sizes = configSettings->readSizes("/kconfig/qconf/split2", &ok);
972 if (ok)
973 split2->setSizes(sizes);
974 #else
975 showSplitView();
976 #endif
977 delete configSettings;
980 static QString print_filter(const QString &str)
982 QRegExp re("[<>&\"\\n]");
983 QString res = str;
984 for (int i = 0; (i = res.find(re, i)) >= 0;) {
985 switch (res[i].latin1()) {
986 case '<':
987 res.replace(i, 1, "&lt;");
988 i += 4;
989 break;
990 case '>':
991 res.replace(i, 1, "&gt;");
992 i += 4;
993 break;
994 case '&':
995 res.replace(i, 1, "&amp;");
996 i += 5;
997 break;
998 case '"':
999 res.replace(i, 1, "&quot;");
1000 i += 6;
1001 break;
1002 case '\n':
1003 res.replace(i, 1, "<br>");
1004 i += 4;
1005 break;
1008 return res;
1011 static void expr_print_help(void *data, const char *str)
1013 reinterpret_cast<QString*>(data)->append(print_filter(str));
1017 * display a new help entry as soon as a new menu entry is selected
1019 void ConfigMainWindow::setHelp(QListViewItem* item)
1021 struct symbol* sym;
1022 struct menu* menu = 0;
1024 configList->parent()->lineEdit->hide();
1025 if (item)
1026 menu = ((ConfigItem*)item)->menu;
1027 if (!menu) {
1028 helpText->setText(QString::null);
1029 return;
1032 QString head, debug, help;
1033 menu = ((ConfigItem*)item)->menu;
1034 sym = menu->sym;
1035 if (sym) {
1036 if (menu->prompt) {
1037 head += "<big><b>";
1038 head += print_filter(_(menu->prompt->text));
1039 head += "</b></big>";
1040 if (sym->name) {
1041 head += " (";
1042 head += print_filter(_(sym->name));
1043 head += ")";
1045 } else if (sym->name) {
1046 head += "<big><b>";
1047 head += print_filter(_(sym->name));
1048 head += "</b></big>";
1050 head += "<br><br>";
1052 if (showDebug) {
1053 debug += "type: ";
1054 debug += print_filter(sym_type_name(sym->type));
1055 if (sym_is_choice(sym))
1056 debug += " (choice)";
1057 debug += "<br>";
1058 if (sym->rev_dep.expr) {
1059 debug += "reverse dep: ";
1060 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1061 debug += "<br>";
1063 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1064 switch (prop->type) {
1065 case P_PROMPT:
1066 case P_MENU:
1067 debug += "prompt: ";
1068 debug += print_filter(_(prop->text));
1069 debug += "<br>";
1070 break;
1071 case P_DEFAULT:
1072 debug += "default: ";
1073 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1074 debug += "<br>";
1075 break;
1076 case P_CHOICE:
1077 if (sym_is_choice(sym)) {
1078 debug += "choice: ";
1079 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1080 debug += "<br>";
1082 break;
1083 case P_SELECT:
1084 debug += "select: ";
1085 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1086 debug += "<br>";
1087 break;
1088 case P_RANGE:
1089 debug += "range: ";
1090 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1091 debug += "<br>";
1092 break;
1093 default:
1094 debug += "unknown property: ";
1095 debug += prop_get_type_name(prop->type);
1096 debug += "<br>";
1098 if (prop->visible.expr) {
1099 debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
1100 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1101 debug += "<br>";
1104 debug += "<br>";
1107 help = print_filter(_(sym->help));
1108 } else if (menu->prompt) {
1109 head += "<big><b>";
1110 head += print_filter(_(menu->prompt->text));
1111 head += "</b></big><br><br>";
1112 if (showDebug) {
1113 if (menu->prompt->visible.expr) {
1114 debug += "&nbsp;&nbsp;dep: ";
1115 expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
1116 debug += "<br><br>";
1120 if (showDebug)
1121 debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
1122 helpText->setText(head + debug + help);
1125 void ConfigMainWindow::loadConfig(void)
1127 QString s = QFileDialog::getOpenFileName(".config", NULL, this);
1128 if (s.isNull())
1129 return;
1130 if (conf_read(QFile::encodeName(s)))
1131 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1132 ConfigView::updateListAll();
1135 void ConfigMainWindow::saveConfig(void)
1137 if (conf_write(NULL))
1138 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1141 void ConfigMainWindow::saveConfigAs(void)
1143 QString s = QFileDialog::getSaveFileName(".config", NULL, this);
1144 if (s.isNull())
1145 return;
1146 if (conf_write(QFile::encodeName(s)))
1147 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1150 void ConfigMainWindow::changeMenu(struct menu *menu)
1152 configList->setRootMenu(menu);
1153 backAction->setEnabled(TRUE);
1156 void ConfigMainWindow::listFocusChanged(void)
1158 if (menuList->hasFocus()) {
1159 if (menuList->mode == menuMode)
1160 configList->clearSelection();
1161 setHelp(menuList->selectedItem());
1162 } else if (configList->hasFocus()) {
1163 setHelp(configList->selectedItem());
1167 void ConfigMainWindow::goBack(void)
1169 ConfigItem* item;
1171 configList->setParentMenu();
1172 if (configList->rootEntry == &rootmenu)
1173 backAction->setEnabled(FALSE);
1174 item = (ConfigItem*)menuList->selectedItem();
1175 while (item) {
1176 if (item->menu == configList->rootEntry) {
1177 menuList->setSelected(item, TRUE);
1178 break;
1180 item = (ConfigItem*)item->parent();
1184 void ConfigMainWindow::showSingleView(void)
1186 menuView->hide();
1187 menuList->setRootMenu(0);
1188 configList->mode = singleMode;
1189 if (configList->rootEntry == &rootmenu)
1190 configList->updateListAll();
1191 else
1192 configList->setRootMenu(&rootmenu);
1193 configList->setAllOpen(TRUE);
1194 configList->setFocus();
1197 void ConfigMainWindow::showSplitView(void)
1199 configList->mode = symbolMode;
1200 if (configList->rootEntry == &rootmenu)
1201 configList->updateListAll();
1202 else
1203 configList->setRootMenu(&rootmenu);
1204 configList->setAllOpen(TRUE);
1205 configApp->processEvents();
1206 menuList->mode = menuMode;
1207 menuList->setRootMenu(&rootmenu);
1208 menuList->setAllOpen(TRUE);
1209 menuView->show();
1210 menuList->setFocus();
1213 void ConfigMainWindow::showFullView(void)
1215 menuView->hide();
1216 menuList->setRootMenu(0);
1217 configList->mode = fullMode;
1218 if (configList->rootEntry == &rootmenu)
1219 configList->updateListAll();
1220 else
1221 configList->setRootMenu(&rootmenu);
1222 configList->setAllOpen(FALSE);
1223 configList->setFocus();
1226 void ConfigMainWindow::setShowAll(bool b)
1228 if (configList->showAll == b)
1229 return;
1230 configList->showAll = b;
1231 configList->updateListAll();
1232 menuList->showAll = b;
1233 menuList->updateListAll();
1236 void ConfigMainWindow::setShowDebug(bool b)
1238 if (showDebug == b)
1239 return;
1240 showDebug = b;
1243 void ConfigMainWindow::setShowName(bool b)
1245 if (configList->showName == b)
1246 return;
1247 configList->showName = b;
1248 configList->reinit();
1249 menuList->showName = b;
1250 menuList->reinit();
1253 void ConfigMainWindow::setShowRange(bool b)
1255 if (configList->showRange == b)
1256 return;
1257 configList->showRange = b;
1258 configList->reinit();
1259 menuList->showRange = b;
1260 menuList->reinit();
1263 void ConfigMainWindow::setShowData(bool b)
1265 if (configList->showData == b)
1266 return;
1267 configList->showData = b;
1268 configList->reinit();
1269 menuList->showData = b;
1270 menuList->reinit();
1274 * ask for saving configuration before quitting
1275 * TODO ask only when something changed
1277 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1279 if (!sym_change_count) {
1280 e->accept();
1281 return;
1283 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1284 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1285 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1286 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1287 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1288 switch (mb.exec()) {
1289 case QMessageBox::Yes:
1290 conf_write(NULL);
1291 case QMessageBox::No:
1292 e->accept();
1293 break;
1294 case QMessageBox::Cancel:
1295 e->ignore();
1296 break;
1300 void ConfigMainWindow::showIntro(void)
1302 static char str[] = "Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
1303 "For each option, a blank box indicates the feature is disabled, a check\n"
1304 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1305 "as a module. Clicking on the box will cycle through the three states.\n\n"
1306 "If you do not see an option (e.g., a device driver) that you believe\n"
1307 "should be present, try turning on Show All Options under the Options menu.\n"
1308 "Although there is no cross reference yet to help you figure out what other\n"
1309 "options must be enabled to support the option you are interested in, you can\n"
1310 "still view the help of a grayed-out option.\n\n"
1311 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1312 "which you can then match by examining other options.\n\n";
1314 QMessageBox::information(this, "qconf", str);
1317 void ConfigMainWindow::showAbout(void)
1319 static char str[] = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
1320 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1322 QMessageBox::information(this, "qconf", str);
1325 void ConfigMainWindow::saveSettings(void)
1327 #if QT_VERSION >= 300
1328 ConfigSettings *configSettings = new ConfigSettings;
1329 configSettings->writeEntry("/kconfig/qconf/window x", pos().x());
1330 configSettings->writeEntry("/kconfig/qconf/window y", pos().y());
1331 configSettings->writeEntry("/kconfig/qconf/window width", size().width());
1332 configSettings->writeEntry("/kconfig/qconf/window height", size().height());
1333 configSettings->writeEntry("/kconfig/qconf/showName", configList->showName);
1334 configSettings->writeEntry("/kconfig/qconf/showRange", configList->showRange);
1335 configSettings->writeEntry("/kconfig/qconf/showData", configList->showData);
1336 configSettings->writeEntry("/kconfig/qconf/showAll", configList->showAll);
1337 configSettings->writeEntry("/kconfig/qconf/showDebug", showDebug);
1339 QString entry;
1340 switch(configList->mode) {
1341 case singleMode :
1342 entry = "single";
1343 break;
1345 case symbolMode :
1346 entry = "split";
1347 break;
1349 case fullMode :
1350 entry = "full";
1351 break;
1353 configSettings->writeEntry("/kconfig/qconf/listMode", entry);
1355 configSettings->writeSizes("/kconfig/qconf/split1", split1->sizes());
1356 configSettings->writeSizes("/kconfig/qconf/split2", split2->sizes());
1358 delete configSettings;
1359 #endif
1362 void fixup_rootmenu(struct menu *menu)
1364 struct menu *child;
1365 static int menu_cnt = 0;
1367 menu->flags |= MENU_ROOT;
1368 for (child = menu->list; child; child = child->next) {
1369 if (child->prompt && child->prompt->type == P_MENU) {
1370 menu_cnt++;
1371 fixup_rootmenu(child);
1372 menu_cnt--;
1373 } else if (!menu_cnt)
1374 fixup_rootmenu(child);
1378 static const char *progname;
1380 static void usage(void)
1382 printf("%s <config>\n", progname);
1383 exit(0);
1386 int main(int ac, char** av)
1388 ConfigMainWindow* v;
1389 const char *name;
1391 bindtextdomain(PACKAGE, LOCALEDIR);
1392 textdomain(PACKAGE);
1394 #ifndef LKC_DIRECT_LINK
1395 kconfig_load();
1396 #endif
1398 progname = av[0];
1399 configApp = new QApplication(ac, av);
1400 if (ac > 1 && av[1][0] == '-') {
1401 switch (av[1][1]) {
1402 case 'h':
1403 case '?':
1404 usage();
1406 name = av[2];
1407 } else
1408 name = av[1];
1409 if (!name)
1410 usage();
1412 conf_parse(name);
1413 fixup_rootmenu(&rootmenu);
1414 conf_read(NULL);
1415 //zconfdump(stdout);
1417 v = new ConfigMainWindow();
1419 //zconfdump(stdout);
1420 v->show();
1421 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1422 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1423 configApp->exec();
1425 return 0;