xconfig: remove unused function
[linux-2.6.git] / scripts / kconfig / qconf.cc
1 /*
2  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3  * Released under the terms of the GNU GPL v2.0.
4  */
5
6 #include <qapplication.h>
7 #include <qmainwindow.h>
8 #include <qdesktopwidget.h>
9 #include <qtoolbar.h>
10 #include <qlayout.h>
11 #include <qvbox.h>
12 #include <qsplitter.h>
13 #include <qlistview.h>
14 #include <qtextbrowser.h>
15 #include <qlineedit.h>
16 #include <qlabel.h>
17 #include <qpushbutton.h>
18 #include <qmenubar.h>
19 #include <qmessagebox.h>
20 #include <qaction.h>
21 #include <qheader.h>
22 #include <qfiledialog.h>
23 #include <qdragobject.h>
24 #include <qregexp.h>
25
26 #include <stdlib.h>
27
28 #include "lkc.h"
29 #include "qconf.h"
30
31 #include "qconf.moc"
32 #include "images.c"
33
34 #ifdef _
35 # undef _
36 # define _ qgettext
37 #endif
38
39 static QApplication *configApp;
40 static ConfigSettings *configSettings;
41
42 QAction *ConfigMainWindow::saveAction;
43
44 static inline QString qgettext(const char* str)
45 {
46         return QString::fromLocal8Bit(gettext(str));
47 }
48
49 static inline QString qgettext(const QString& str)
50 {
51         return QString::fromLocal8Bit(gettext(str.latin1()));
52 }
53
54 /**
55  * Reads a list of integer values from the application settings.
56  */
57 QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
58 {
59         QValueList<int> result;
60         QStringList entryList = readListEntry(key, ok);
61         QStringList::Iterator it;
62
63         for (it = entryList.begin(); it != entryList.end(); ++it)
64                 result.push_back((*it).toInt());
65
66         return result;
67 }
68
69 /**
70  * Writes a list of integer values to the application settings.
71  */
72 bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
73 {
74         QStringList stringList;
75         QValueList<int>::ConstIterator it;
76
77         for (it = value.begin(); it != value.end(); ++it)
78                 stringList.push_back(QString::number(*it));
79         return writeEntry(key, stringList);
80 }
81
82
83 #if QT_VERSION >= 300
84 /*
85  * set the new data
86  * TODO check the value
87  */
88 void ConfigItem::okRename(int col)
89 {
90         Parent::okRename(col);
91         sym_set_string_value(menu->sym, text(dataColIdx).latin1());
92         listView()->updateList(this);
93 }
94 #endif
95
96 /*
97  * update the displayed of a menu entry
98  */
99 void ConfigItem::updateMenu(void)
100 {
101         ConfigList* list;
102         struct symbol* sym;
103         struct property *prop;
104         QString prompt;
105         int type;
106         tristate expr;
107
108         list = listView();
109         if (goParent) {
110                 setPixmap(promptColIdx, list->menuBackPix);
111                 prompt = "..";
112                 goto set_prompt;
113         }
114
115         sym = menu->sym;
116         prop = menu->prompt;
117         prompt = _(menu_get_prompt(menu));
118
119         if (prop) switch (prop->type) {
120         case P_MENU:
121                 if (list->mode == singleMode || list->mode == symbolMode) {
122                         /* a menuconfig entry is displayed differently
123                          * depending whether it's at the view root or a child.
124                          */
125                         if (sym && list->rootEntry == menu)
126                                 break;
127                         setPixmap(promptColIdx, list->menuPix);
128                 } else {
129                         if (sym)
130                                 break;
131                         setPixmap(promptColIdx, 0);
132                 }
133                 goto set_prompt;
134         case P_COMMENT:
135                 setPixmap(promptColIdx, 0);
136                 goto set_prompt;
137         default:
138                 ;
139         }
140         if (!sym)
141                 goto set_prompt;
142
143         setText(nameColIdx, QString::fromLocal8Bit(sym->name));
144
145         type = sym_get_type(sym);
146         switch (type) {
147         case S_BOOLEAN:
148         case S_TRISTATE:
149                 char ch;
150
151                 if (!sym_is_changable(sym) && !list->showAll) {
152                         setPixmap(promptColIdx, 0);
153                         setText(noColIdx, QString::null);
154                         setText(modColIdx, QString::null);
155                         setText(yesColIdx, QString::null);
156                         break;
157                 }
158                 expr = sym_get_tristate_value(sym);
159                 switch (expr) {
160                 case yes:
161                         if (sym_is_choice_value(sym) && type == S_BOOLEAN)
162                                 setPixmap(promptColIdx, list->choiceYesPix);
163                         else
164                                 setPixmap(promptColIdx, list->symbolYesPix);
165                         setText(yesColIdx, "Y");
166                         ch = 'Y';
167                         break;
168                 case mod:
169                         setPixmap(promptColIdx, list->symbolModPix);
170                         setText(modColIdx, "M");
171                         ch = 'M';
172                         break;
173                 default:
174                         if (sym_is_choice_value(sym) && type == S_BOOLEAN)
175                                 setPixmap(promptColIdx, list->choiceNoPix);
176                         else
177                                 setPixmap(promptColIdx, list->symbolNoPix);
178                         setText(noColIdx, "N");
179                         ch = 'N';
180                         break;
181                 }
182                 if (expr != no)
183                         setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
184                 if (expr != mod)
185                         setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
186                 if (expr != yes)
187                         setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
188
189                 setText(dataColIdx, QChar(ch));
190                 break;
191         case S_INT:
192         case S_HEX:
193         case S_STRING:
194                 const char* data;
195
196                 data = sym_get_string_value(sym);
197
198 #if QT_VERSION >= 300
199                 int i = list->mapIdx(dataColIdx);
200                 if (i >= 0)
201                         setRenameEnabled(i, TRUE);
202 #endif
203                 setText(dataColIdx, data);
204                 if (type == S_STRING)
205                         prompt = QString("%1: %2").arg(prompt).arg(data);
206                 else
207                         prompt = QString("(%2) %1").arg(prompt).arg(data);
208                 break;
209         }
210         if (!sym_has_value(sym) && visible)
211                 prompt += _(" (NEW)");
212 set_prompt:
213         setText(promptColIdx, prompt);
214 }
215
216 void ConfigItem::testUpdateMenu(bool v)
217 {
218         ConfigItem* i;
219
220         visible = v;
221         if (!menu)
222                 return;
223
224         sym_calc_value(menu->sym);
225         if (menu->flags & MENU_CHANGED) {
226                 /* the menu entry changed, so update all list items */
227                 menu->flags &= ~MENU_CHANGED;
228                 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
229                         i->updateMenu();
230         } else if (listView()->updateAll)
231                 updateMenu();
232 }
233
234 void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
235 {
236         ConfigList* list = listView();
237
238         if (visible) {
239                 if (isSelected() && !list->hasFocus() && list->mode == menuMode)
240                         Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
241                 else
242                         Parent::paintCell(p, cg, column, width, align);
243         } else
244                 Parent::paintCell(p, list->disabledColorGroup, column, width, align);
245 }
246
247 /*
248  * construct a menu entry
249  */
250 void ConfigItem::init(void)
251 {
252         if (menu) {
253                 ConfigList* list = listView();
254                 nextItem = (ConfigItem*)menu->data;
255                 menu->data = this;
256
257                 if (list->mode != fullMode)
258                         setOpen(TRUE);
259                 sym_calc_value(menu->sym);
260         }
261         updateMenu();
262 }
263
264 /*
265  * destruct a menu entry
266  */
267 ConfigItem::~ConfigItem(void)
268 {
269         if (menu) {
270                 ConfigItem** ip = (ConfigItem**)&menu->data;
271                 for (; *ip; ip = &(*ip)->nextItem) {
272                         if (*ip == this) {
273                                 *ip = nextItem;
274                                 break;
275                         }
276                 }
277         }
278 }
279
280 ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
281         : Parent(parent)
282 {
283         connect(this, SIGNAL(lostFocus()), SLOT(hide()));
284 }
285
286 void ConfigLineEdit::show(ConfigItem* i)
287 {
288         item = i;
289         if (sym_get_string_value(item->menu->sym))
290                 setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
291         else
292                 setText(QString::null);
293         Parent::show();
294         setFocus();
295 }
296
297 void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
298 {
299         switch (e->key()) {
300         case Qt::Key_Escape:
301                 break;
302         case Qt::Key_Return:
303         case Qt::Key_Enter:
304                 sym_set_string_value(item->menu->sym, text().latin1());
305                 parent()->updateList(item);
306                 break;
307         default:
308                 Parent::keyPressEvent(e);
309                 return;
310         }
311         e->accept();
312         parent()->list->setFocus();
313         hide();
314 }
315
316 ConfigList::ConfigList(ConfigView* p, const char *name)
317         : Parent(p, name),
318           updateAll(false),
319           symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
320           choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
321           menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
322           showAll(false), showName(false), showRange(false), showData(false),
323           rootEntry(0), headerPopup(0)
324 {
325         int i;
326
327         setSorting(-1);
328         setRootIsDecorated(TRUE);
329         disabledColorGroup = palette().active();
330         disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
331         inactivedColorGroup = palette().active();
332         inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
333
334         connect(this, SIGNAL(selectionChanged(void)),
335                 SLOT(updateSelection(void)));
336
337         if (name) {
338                 configSettings->beginGroup(name);
339                 showAll = configSettings->readBoolEntry("/showAll", false);
340                 showName = configSettings->readBoolEntry("/showName", false);
341                 showRange = configSettings->readBoolEntry("/showRange", false);
342                 showData = configSettings->readBoolEntry("/showData", false);
343                 configSettings->endGroup();
344                 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
345         }
346
347         for (i = 0; i < colNr; i++)
348                 colMap[i] = colRevMap[i] = -1;
349         addColumn(promptColIdx, _("Option"));
350
351         reinit();
352 }
353
354 void ConfigList::reinit(void)
355 {
356         removeColumn(dataColIdx);
357         removeColumn(yesColIdx);
358         removeColumn(modColIdx);
359         removeColumn(noColIdx);
360         removeColumn(nameColIdx);
361
362         if (showName)
363                 addColumn(nameColIdx, _("Name"));
364         if (showRange) {
365                 addColumn(noColIdx, "N");
366                 addColumn(modColIdx, "M");
367                 addColumn(yesColIdx, "Y");
368         }
369         if (showData)
370                 addColumn(dataColIdx, _("Value"));
371
372         updateListAll();
373 }
374
375 void ConfigList::saveSettings(void)
376 {
377         if (name()) {
378                 configSettings->beginGroup(name());
379                 configSettings->writeEntry("/showName", showName);
380                 configSettings->writeEntry("/showRange", showRange);
381                 configSettings->writeEntry("/showData", showData);
382                 configSettings->writeEntry("/showAll", showAll);
383                 configSettings->endGroup();
384         }
385 }
386
387 ConfigItem* ConfigList::findConfigItem(struct menu *menu)
388 {
389         ConfigItem* item = (ConfigItem*)menu->data;
390
391         for (; item; item = item->nextItem) {
392                 if (this == item->listView())
393                         break;
394         }
395
396         return item;
397 }
398
399 void ConfigList::updateSelection(void)
400 {
401         struct menu *menu;
402         enum prop_type type;
403
404         ConfigItem* item = (ConfigItem*)selectedItem();
405         if (!item)
406                 return;
407
408         menu = item->menu;
409         emit menuChanged(menu);
410         if (!menu)
411                 return;
412         type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
413         if (mode == menuMode && type == P_MENU)
414                 emit menuSelected(menu);
415 }
416
417 void ConfigList::updateList(ConfigItem* item)
418 {
419         ConfigItem* last = 0;
420
421         if (!rootEntry) {
422                 if (mode != listMode)
423                         goto update;
424                 QListViewItemIterator it(this);
425                 ConfigItem* item;
426
427                 for (; it.current(); ++it) {
428                         item = (ConfigItem*)it.current();
429                         if (!item->menu)
430                                 continue;
431                         item->testUpdateMenu(menu_is_visible(item->menu));
432                 }
433                 return;
434         }
435
436         if (rootEntry != &rootmenu && (mode == singleMode ||
437             (mode == symbolMode && rootEntry->parent != &rootmenu))) {
438                 item = firstChild();
439                 if (!item)
440                         item = new ConfigItem(this, 0, true);
441                 last = item;
442         }
443         if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
444             rootEntry->sym && rootEntry->prompt) {
445                 item = last ? last->nextSibling() : firstChild();
446                 if (!item)
447                         item = new ConfigItem(this, last, rootEntry, true);
448                 else
449                         item->testUpdateMenu(true);
450
451                 updateMenuList(item, rootEntry);
452                 triggerUpdate();
453                 return;
454         }
455 update:
456         updateMenuList(this, rootEntry);
457         triggerUpdate();
458 }
459
460 void ConfigList::setValue(ConfigItem* item, tristate val)
461 {
462         struct symbol* sym;
463         int type;
464         tristate oldval;
465
466         sym = item->menu ? item->menu->sym : 0;
467         if (!sym)
468                 return;
469
470         type = sym_get_type(sym);
471         switch (type) {
472         case S_BOOLEAN:
473         case S_TRISTATE:
474                 oldval = sym_get_tristate_value(sym);
475
476                 if (!sym_set_tristate_value(sym, val))
477                         return;
478                 if (oldval == no && item->menu->list)
479                         item->setOpen(TRUE);
480                 parent()->updateList(item);
481                 break;
482         }
483 }
484
485 void ConfigList::changeValue(ConfigItem* item)
486 {
487         struct symbol* sym;
488         struct menu* menu;
489         int type, oldexpr, newexpr;
490
491         menu = item->menu;
492         if (!menu)
493                 return;
494         sym = menu->sym;
495         if (!sym) {
496                 if (item->menu->list)
497                         item->setOpen(!item->isOpen());
498                 return;
499         }
500
501         type = sym_get_type(sym);
502         switch (type) {
503         case S_BOOLEAN:
504         case S_TRISTATE:
505                 oldexpr = sym_get_tristate_value(sym);
506                 newexpr = sym_toggle_tristate_value(sym);
507                 if (item->menu->list) {
508                         if (oldexpr == newexpr)
509                                 item->setOpen(!item->isOpen());
510                         else if (oldexpr == no)
511                                 item->setOpen(TRUE);
512                 }
513                 if (oldexpr != newexpr)
514                         parent()->updateList(item);
515                 break;
516         case S_INT:
517         case S_HEX:
518         case S_STRING:
519 #if QT_VERSION >= 300
520                 if (colMap[dataColIdx] >= 0)
521                         item->startRename(colMap[dataColIdx]);
522                 else
523 #endif
524                         parent()->lineEdit->show(item);
525                 break;
526         }
527 }
528
529 void ConfigList::setRootMenu(struct menu *menu)
530 {
531         enum prop_type type;
532
533         if (rootEntry == menu)
534                 return;
535         type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
536         if (type != P_MENU)
537                 return;
538         updateMenuList(this, 0);
539         rootEntry = menu;
540         updateListAll();
541         setSelected(currentItem(), hasFocus());
542         ensureItemVisible(currentItem());
543 }
544
545 void ConfigList::setParentMenu(void)
546 {
547         ConfigItem* item;
548         struct menu *oldroot;
549
550         oldroot = rootEntry;
551         if (rootEntry == &rootmenu)
552                 return;
553         setRootMenu(menu_get_parent_menu(rootEntry->parent));
554
555         QListViewItemIterator it(this);
556         for (; (item = (ConfigItem*)it.current()); it++) {
557                 if (item->menu == oldroot) {
558                         setCurrentItem(item);
559                         ensureItemVisible(item);
560                         break;
561                 }
562         }
563 }
564
565 /*
566  * update all the children of a menu entry
567  *   removes/adds the entries from the parent widget as necessary
568  *
569  * parent: either the menu list widget or a menu entry widget
570  * menu: entry to be updated
571  */
572 template <class P>
573 void ConfigList::updateMenuList(P* parent, struct menu* menu)
574 {
575         struct menu* child;
576         ConfigItem* item;
577         ConfigItem* last;
578         bool visible;
579         enum prop_type type;
580
581         if (!menu) {
582                 while ((item = parent->firstChild()))
583                         delete item;
584                 return;
585         }
586
587         last = parent->firstChild();
588         if (last && !last->goParent)
589                 last = 0;
590         for (child = menu->list; child; child = child->next) {
591                 item = last ? last->nextSibling() : parent->firstChild();
592                 type = child->prompt ? child->prompt->type : P_UNKNOWN;
593
594                 switch (mode) {
595                 case menuMode:
596                         if (!(child->flags & MENU_ROOT))
597                                 goto hide;
598                         break;
599                 case symbolMode:
600                         if (child->flags & MENU_ROOT)
601                                 goto hide;
602                         break;
603                 default:
604                         break;
605                 }
606
607                 visible = menu_is_visible(child);
608                 if (showAll || visible) {
609                         if (!child->sym && !child->list && !child->prompt)
610                                 continue;
611                         if (!item || item->menu != child)
612                                 item = new ConfigItem(parent, last, child, visible);
613                         else
614                                 item->testUpdateMenu(visible);
615
616                         if (mode == fullMode || mode == menuMode || type != P_MENU)
617                                 updateMenuList(item, child);
618                         else
619                                 updateMenuList(item, 0);
620                         last = item;
621                         continue;
622                 }
623         hide:
624                 if (item && item->menu == child) {
625                         last = parent->firstChild();
626                         if (last == item)
627                                 last = 0;
628                         else while (last->nextSibling() != item)
629                                 last = last->nextSibling();
630                         delete item;
631                 }
632         }
633 }
634
635 void ConfigList::keyPressEvent(QKeyEvent* ev)
636 {
637         QListViewItem* i = currentItem();
638         ConfigItem* item;
639         struct menu *menu;
640         enum prop_type type;
641
642         if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
643                 emit parentSelected();
644                 ev->accept();
645                 return;
646         }
647
648         if (!i) {
649                 Parent::keyPressEvent(ev);
650                 return;
651         }
652         item = (ConfigItem*)i;
653
654         switch (ev->key()) {
655         case Qt::Key_Return:
656         case Qt::Key_Enter:
657                 if (item->goParent) {
658                         emit parentSelected();
659                         break;
660                 }
661                 menu = item->menu;
662                 if (!menu)
663                         break;
664                 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
665                 if (type == P_MENU && rootEntry != menu &&
666                     mode != fullMode && mode != menuMode) {
667                         emit menuSelected(menu);
668                         break;
669                 }
670         case Qt::Key_Space:
671                 changeValue(item);
672                 break;
673         case Qt::Key_N:
674                 setValue(item, no);
675                 break;
676         case Qt::Key_M:
677                 setValue(item, mod);
678                 break;
679         case Qt::Key_Y:
680                 setValue(item, yes);
681                 break;
682         default:
683                 Parent::keyPressEvent(ev);
684                 return;
685         }
686         ev->accept();
687 }
688
689 void ConfigList::contentsMousePressEvent(QMouseEvent* e)
690 {
691         //QPoint p(contentsToViewport(e->pos()));
692         //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
693         Parent::contentsMousePressEvent(e);
694 }
695
696 void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
697 {
698         QPoint p(contentsToViewport(e->pos()));
699         ConfigItem* item = (ConfigItem*)itemAt(p);
700         struct menu *menu;
701         enum prop_type ptype;
702         const QPixmap* pm;
703         int idx, x;
704
705         if (!item)
706                 goto skip;
707
708         menu = item->menu;
709         x = header()->offset() + p.x();
710         idx = colRevMap[header()->sectionAt(x)];
711         switch (idx) {
712         case promptColIdx:
713                 pm = item->pixmap(promptColIdx);
714                 if (pm) {
715                         int off = header()->sectionPos(0) + itemMargin() +
716                                 treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
717                         if (x >= off && x < off + pm->width()) {
718                                 if (item->goParent) {
719                                         emit parentSelected();
720                                         break;
721                                 } else if (!menu)
722                                         break;
723                                 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
724                                 if (ptype == P_MENU && rootEntry != menu &&
725                                     mode != fullMode && mode != menuMode)
726                                         emit menuSelected(menu);
727                                 else
728                                         changeValue(item);
729                         }
730                 }
731                 break;
732         case noColIdx:
733                 setValue(item, no);
734                 break;
735         case modColIdx:
736                 setValue(item, mod);
737                 break;
738         case yesColIdx:
739                 setValue(item, yes);
740                 break;
741         case dataColIdx:
742                 changeValue(item);
743                 break;
744         }
745
746 skip:
747         //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
748         Parent::contentsMouseReleaseEvent(e);
749 }
750
751 void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
752 {
753         //QPoint p(contentsToViewport(e->pos()));
754         //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
755         Parent::contentsMouseMoveEvent(e);
756 }
757
758 void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
759 {
760         QPoint p(contentsToViewport(e->pos()));
761         ConfigItem* item = (ConfigItem*)itemAt(p);
762         struct menu *menu;
763         enum prop_type ptype;
764
765         if (!item)
766                 goto skip;
767         if (item->goParent) {
768                 emit parentSelected();
769                 goto skip;
770         }
771         menu = item->menu;
772         if (!menu)
773                 goto skip;
774         ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
775         if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
776                 emit menuSelected(menu);
777         else if (menu->sym)
778                 changeValue(item);
779
780 skip:
781         //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
782         Parent::contentsMouseDoubleClickEvent(e);
783 }
784
785 void ConfigList::focusInEvent(QFocusEvent *e)
786 {
787         struct menu *menu = NULL;
788
789         Parent::focusInEvent(e);
790
791         ConfigItem* item = (ConfigItem *)currentItem();
792         if (item) {
793                 setSelected(item, TRUE);
794                 menu = item->menu;
795         }
796         emit gotFocus(menu);
797 }
798
799 void ConfigList::contextMenuEvent(QContextMenuEvent *e)
800 {
801         if (e->y() <= header()->geometry().bottom()) {
802                 if (!headerPopup) {
803                         QAction *action;
804
805                         headerPopup = new QPopupMenu(this);
806                         action = new QAction(NULL, _("Show Name"), 0, this);
807                           action->setToggleAction(TRUE);
808                           connect(action, SIGNAL(toggled(bool)),
809                                   parent(), SLOT(setShowName(bool)));
810                           connect(parent(), SIGNAL(showNameChanged(bool)),
811                                   action, SLOT(setOn(bool)));
812                           action->setOn(showName);
813                           action->addTo(headerPopup);
814                         action = new QAction(NULL, _("Show Range"), 0, this);
815                           action->setToggleAction(TRUE);
816                           connect(action, SIGNAL(toggled(bool)),
817                                   parent(), SLOT(setShowRange(bool)));
818                           connect(parent(), SIGNAL(showRangeChanged(bool)),
819                                   action, SLOT(setOn(bool)));
820                           action->setOn(showRange);
821                           action->addTo(headerPopup);
822                         action = new QAction(NULL, _("Show Data"), 0, this);
823                           action->setToggleAction(TRUE);
824                           connect(action, SIGNAL(toggled(bool)),
825                                   parent(), SLOT(setShowData(bool)));
826                           connect(parent(), SIGNAL(showDataChanged(bool)),
827                                   action, SLOT(setOn(bool)));
828                           action->setOn(showData);
829                           action->addTo(headerPopup);
830                 }
831                 headerPopup->exec(e->globalPos());
832                 e->accept();
833         } else
834                 e->ignore();
835 }
836
837 ConfigView* ConfigView::viewList;
838
839 ConfigView::ConfigView(QWidget* parent, const char *name)
840         : Parent(parent, name)
841 {
842         list = new ConfigList(this, name);
843         lineEdit = new ConfigLineEdit(this);
844         lineEdit->hide();
845
846         this->nextView = viewList;
847         viewList = this;
848 }
849
850 ConfigView::~ConfigView(void)
851 {
852         ConfigView** vp;
853
854         for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
855                 if (*vp == this) {
856                         *vp = nextView;
857                         break;
858                 }
859         }
860 }
861
862 void ConfigView::setShowAll(bool b)
863 {
864         if (list->showAll != b) {
865                 list->showAll = b;
866                 list->updateListAll();
867                 emit showAllChanged(b);
868         }
869 }
870
871 void ConfigView::setShowName(bool b)
872 {
873         if (list->showName != b) {
874                 list->showName = b;
875                 list->reinit();
876                 emit showNameChanged(b);
877         }
878 }
879
880 void ConfigView::setShowRange(bool b)
881 {
882         if (list->showRange != b) {
883                 list->showRange = b;
884                 list->reinit();
885                 emit showRangeChanged(b);
886         }
887 }
888
889 void ConfigView::setShowData(bool b)
890 {
891         if (list->showData != b) {
892                 list->showData = b;
893                 list->reinit();
894                 emit showDataChanged(b);
895         }
896 }
897
898 void ConfigList::setAllOpen(bool open)
899 {
900         QListViewItemIterator it(this);
901
902         for (; it.current(); it++)
903                 it.current()->setOpen(open);
904 }
905
906 void ConfigView::updateList(ConfigItem* item)
907 {
908         ConfigView* v;
909
910         for (v = viewList; v; v = v->nextView)
911                 v->list->updateList(item);
912 }
913
914 void ConfigView::updateListAll(void)
915 {
916         ConfigView* v;
917
918         for (v = viewList; v; v = v->nextView)
919                 v->list->updateListAll();
920 }
921
922 ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
923         : Parent(parent, name), sym(0), menu(0)
924 {
925         if (name) {
926                 configSettings->beginGroup(name);
927                 _showDebug = configSettings->readBoolEntry("/showDebug", false);
928                 configSettings->endGroup();
929                 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
930         }
931 }
932
933 void ConfigInfoView::saveSettings(void)
934 {
935         if (name()) {
936                 configSettings->beginGroup(name());
937                 configSettings->writeEntry("/showDebug", showDebug());
938                 configSettings->endGroup();
939         }
940 }
941
942 void ConfigInfoView::setShowDebug(bool b)
943 {
944         if (_showDebug != b) {
945                 _showDebug = b;
946                 if (menu)
947                         menuInfo();
948                 else if (sym)
949                         symbolInfo();
950                 emit showDebugChanged(b);
951         }
952 }
953
954 void ConfigInfoView::setInfo(struct menu *m)
955 {
956         if (menu == m)
957                 return;
958         menu = m;
959         sym = NULL;
960         if (!menu)
961                 clear();
962         else
963                 menuInfo();
964 }
965
966 void ConfigInfoView::symbolInfo(void)
967 {
968         QString str;
969
970         str += "<big>Symbol: <b>";
971         str += print_filter(sym->name);
972         str += "</b></big><br><br>value: ";
973         str += print_filter(sym_get_string_value(sym));
974         str += "<br>visibility: ";
975         str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
976         str += "<br>";
977         str += debug_info(sym);
978
979         setText(str);
980 }
981
982 void ConfigInfoView::menuInfo(void)
983 {
984         struct symbol* sym;
985         QString head, debug, help;
986
987         sym = menu->sym;
988         if (sym) {
989                 if (menu->prompt) {
990                         head += "<big><b>";
991                         head += print_filter(_(menu->prompt->text));
992                         head += "</b></big>";
993                         if (sym->name) {
994                                 head += " (";
995                                 if (showDebug())
996                                         head += QString().sprintf("<a href=\"s%p\">", sym);
997                                 head += print_filter(sym->name);
998                                 if (showDebug())
999                                         head += "</a>";
1000                                 head += ")";
1001                         }
1002                 } else if (sym->name) {
1003                         head += "<big><b>";
1004                         if (showDebug())
1005                                 head += QString().sprintf("<a href=\"s%p\">", sym);
1006                         head += print_filter(sym->name);
1007                         if (showDebug())
1008                                 head += "</a>";
1009                         head += "</b></big>";
1010                 }
1011                 head += "<br><br>";
1012
1013                 if (showDebug())
1014                         debug = debug_info(sym);
1015
1016                 struct gstr help_gstr = str_new();
1017                 menu_get_ext_help(menu, &help_gstr);
1018                 help = print_filter(str_get(&help_gstr));
1019                 str_free(&help_gstr);
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>";
1029                         }
1030                 }
1031         }
1032         if (showDebug())
1033                 debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
1034
1035         setText(head + debug + help);
1036 }
1037
1038 QString ConfigInfoView::debug_info(struct symbol *sym)
1039 {
1040         QString debug;
1041
1042         debug += "type: ";
1043         debug += print_filter(sym_type_name(sym->type));
1044         if (sym_is_choice(sym))
1045                 debug += " (choice)";
1046         debug += "<br>";
1047         if (sym->rev_dep.expr) {
1048                 debug += "reverse dep: ";
1049                 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1050                 debug += "<br>";
1051         }
1052         for (struct property *prop = sym->prop; prop; prop = prop->next) {
1053                 switch (prop->type) {
1054                 case P_PROMPT:
1055                 case P_MENU:
1056                         debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
1057                         debug += print_filter(_(prop->text));
1058                         debug += "</a><br>";
1059                         break;
1060                 case P_DEFAULT:
1061                 case P_SELECT:
1062                 case P_RANGE:
1063                 case P_ENV:
1064                         debug += prop_get_type_name(prop->type);
1065                         debug += ": ";
1066                         expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1067                         debug += "<br>";
1068                         break;
1069                 case P_CHOICE:
1070                         if (sym_is_choice(sym)) {
1071                                 debug += "choice: ";
1072                                 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1073                                 debug += "<br>";
1074                         }
1075                         break;
1076                 default:
1077                         debug += "unknown property: ";
1078                         debug += prop_get_type_name(prop->type);
1079                         debug += "<br>";
1080                 }
1081                 if (prop->visible.expr) {
1082                         debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
1083                         expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1084                         debug += "<br>";
1085                 }
1086         }
1087         debug += "<br>";
1088
1089         return debug;
1090 }
1091
1092 QString ConfigInfoView::print_filter(const QString &str)
1093 {
1094         QRegExp re("[<>&\"\\n]");
1095         QString res = str;
1096         for (int i = 0; (i = res.find(re, i)) >= 0;) {
1097                 switch (res[i].latin1()) {
1098                 case '<':
1099                         res.replace(i, 1, "&lt;");
1100                         i += 4;
1101                         break;
1102                 case '>':
1103                         res.replace(i, 1, "&gt;");
1104                         i += 4;
1105                         break;
1106                 case '&':
1107                         res.replace(i, 1, "&amp;");
1108                         i += 5;
1109                         break;
1110                 case '"':
1111                         res.replace(i, 1, "&quot;");
1112                         i += 6;
1113                         break;
1114                 case '\n':
1115                         res.replace(i, 1, "<br>");
1116                         i += 4;
1117                         break;
1118                 }
1119         }
1120         return res;
1121 }
1122
1123 void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
1124 {
1125         QString* text = reinterpret_cast<QString*>(data);
1126         QString str2 = print_filter(str);
1127
1128         if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1129                 *text += QString().sprintf("<a href=\"s%p\">", sym);
1130                 *text += str2;
1131                 *text += "</a>";
1132         } else
1133                 *text += str2;
1134 }
1135
1136 QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
1137 {
1138         QPopupMenu* popup = Parent::createPopupMenu(pos);
1139         QAction* action = new QAction(NULL, _("Show Debug Info"), 0, popup);
1140           action->setToggleAction(TRUE);
1141           connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1142           connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
1143           action->setOn(showDebug());
1144         popup->insertSeparator();
1145         action->addTo(popup);
1146         return popup;
1147 }
1148
1149 void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
1150 {
1151         Parent::contentsContextMenuEvent(e);
1152 }
1153
1154 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
1155         : Parent(parent, name), result(NULL)
1156 {
1157         setCaption("Search Config");
1158
1159         QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);
1160         QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);
1161         layout2->addWidget(new QLabel(_("Find:"), this));
1162         editField = new QLineEdit(this);
1163         connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1164         layout2->addWidget(editField);
1165         searchButton = new QPushButton(_("Search"), this);
1166         searchButton->setAutoDefault(FALSE);
1167         connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1168         layout2->addWidget(searchButton);
1169         layout1->addLayout(layout2);
1170
1171         split = new QSplitter(this);
1172         split->setOrientation(Qt::Vertical);
1173         list = new ConfigView(split, name);
1174         list->list->mode = listMode;
1175         info = new ConfigInfoView(split, name);
1176         connect(list->list, SIGNAL(menuChanged(struct menu *)),
1177                 info, SLOT(setInfo(struct menu *)));
1178         connect(list->list, SIGNAL(menuChanged(struct menu *)),
1179                 parent, SLOT(setMenuLink(struct menu *)));
1180
1181         layout1->addWidget(split);
1182
1183         if (name) {
1184                 int x, y, width, height;
1185                 bool ok;
1186
1187                 configSettings->beginGroup(name);
1188                 width = configSettings->readNumEntry("/window width", parent->width() / 2);
1189                 height = configSettings->readNumEntry("/window height", parent->height() / 2);
1190                 resize(width, height);
1191                 x = configSettings->readNumEntry("/window x", 0, &ok);
1192                 if (ok)
1193                         y = configSettings->readNumEntry("/window y", 0, &ok);
1194                 if (ok)
1195                         move(x, y);
1196                 QValueList<int> sizes = configSettings->readSizes("/split", &ok);
1197                 if (ok)
1198                         split->setSizes(sizes);
1199                 configSettings->endGroup();
1200                 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1201         }
1202 }
1203
1204 void ConfigSearchWindow::saveSettings(void)
1205 {
1206         if (name()) {
1207                 configSettings->beginGroup(name());
1208                 configSettings->writeEntry("/window x", pos().x());
1209                 configSettings->writeEntry("/window y", pos().y());
1210                 configSettings->writeEntry("/window width", size().width());
1211                 configSettings->writeEntry("/window height", size().height());
1212                 configSettings->writeSizes("/split", split->sizes());
1213                 configSettings->endGroup();
1214         }
1215 }
1216
1217 void ConfigSearchWindow::search(void)
1218 {
1219         struct symbol **p;
1220         struct property *prop;
1221         ConfigItem *lastItem = NULL;
1222
1223         free(result);
1224         list->list->clear();
1225         info->clear();
1226
1227         result = sym_re_search(editField->text().latin1());
1228         if (!result)
1229                 return;
1230         for (p = result; *p; p++) {
1231                 for_all_prompts((*p), prop)
1232                         lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1233                                                   menu_is_visible(prop->menu));
1234         }
1235 }
1236
1237 /*
1238  * Construct the complete config widget
1239  */
1240 ConfigMainWindow::ConfigMainWindow(void)
1241         : searchWindow(0)
1242 {
1243         QMenuBar* menu;
1244         bool ok;
1245         int x, y, width, height;
1246         char title[256];
1247
1248         QDesktopWidget *d = configApp->desktop();
1249         snprintf(title, sizeof(title), _("Linux Kernel v%s Configuration"),
1250                 getenv("KERNELVERSION"));
1251         setCaption(title);
1252
1253         width = configSettings->readNumEntry("/window width", d->width() - 64);
1254         height = configSettings->readNumEntry("/window height", d->height() - 64);
1255         resize(width, height);
1256         x = configSettings->readNumEntry("/window x", 0, &ok);
1257         if (ok)
1258                 y = configSettings->readNumEntry("/window y", 0, &ok);
1259         if (ok)
1260                 move(x, y);
1261
1262         split1 = new QSplitter(this);
1263         split1->setOrientation(Qt::Horizontal);
1264         setCentralWidget(split1);
1265
1266         menuView = new ConfigView(split1, "menu");
1267         menuList = menuView->list;
1268
1269         split2 = new QSplitter(split1);
1270         split2->setOrientation(Qt::Vertical);
1271
1272         // create config tree
1273         configView = new ConfigView(split2, "config");
1274         configList = configView->list;
1275
1276         helpText = new ConfigInfoView(split2, "help");
1277         helpText->setTextFormat(Qt::RichText);
1278
1279         setTabOrder(configList, helpText);
1280         configList->setFocus();
1281
1282         menu = menuBar();
1283         toolBar = new QToolBar("Tools", this);
1284
1285         backAction = new QAction("Back", QPixmap(xpm_back), _("Back"), 0, this);
1286           connect(backAction, SIGNAL(activated()), SLOT(goBack()));
1287           backAction->setEnabled(FALSE);
1288         QAction *quitAction = new QAction("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
1289           connect(quitAction, SIGNAL(activated()), SLOT(close()));
1290         QAction *loadAction = new QAction("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
1291           connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
1292         saveAction = new QAction("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
1293           connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
1294         conf_set_changed_callback(conf_changed);
1295         // Set saveAction's initial state
1296         conf_changed();
1297         QAction *saveAsAction = new QAction("Save As...", _("Save &As..."), 0, this);
1298           connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
1299         QAction *searchAction = new QAction("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
1300           connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
1301         QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
1302           connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
1303         QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
1304           connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
1305         QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
1306           connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
1307
1308         QAction *showNameAction = new QAction(NULL, _("Show Name"), 0, this);
1309           showNameAction->setToggleAction(TRUE);
1310           connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1311           connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
1312           showNameAction->setOn(configView->showName());
1313         QAction *showRangeAction = new QAction(NULL, _("Show Range"), 0, this);
1314           showRangeAction->setToggleAction(TRUE);
1315           connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1316           connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
1317           showRangeAction->setOn(configList->showRange);
1318         QAction *showDataAction = new QAction(NULL, _("Show Data"), 0, this);
1319           showDataAction->setToggleAction(TRUE);
1320           connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1321           connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
1322           showDataAction->setOn(configList->showData);
1323         QAction *showAllAction = new QAction(NULL, _("Show All Options"), 0, this);
1324           showAllAction->setToggleAction(TRUE);
1325           connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool)));
1326           connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool)));
1327           showAllAction->setOn(configList->showAll);
1328         QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this);
1329           showDebugAction->setToggleAction(TRUE);
1330           connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1331           connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
1332           showDebugAction->setOn(helpText->showDebug());
1333
1334         QAction *showIntroAction = new QAction(NULL, _("Introduction"), 0, this);
1335           connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
1336         QAction *showAboutAction = new QAction(NULL, _("About"), 0, this);
1337           connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
1338
1339         // init tool bar
1340         backAction->addTo(toolBar);
1341         toolBar->addSeparator();
1342         loadAction->addTo(toolBar);
1343         saveAction->addTo(toolBar);
1344         toolBar->addSeparator();
1345         singleViewAction->addTo(toolBar);
1346         splitViewAction->addTo(toolBar);
1347         fullViewAction->addTo(toolBar);
1348
1349         // create config menu
1350         QPopupMenu* config = new QPopupMenu(this);
1351         menu->insertItem(_("&File"), config);
1352         loadAction->addTo(config);
1353         saveAction->addTo(config);
1354         saveAsAction->addTo(config);
1355         config->insertSeparator();
1356         quitAction->addTo(config);
1357
1358         // create edit menu
1359         QPopupMenu* editMenu = new QPopupMenu(this);
1360         menu->insertItem(_("&Edit"), editMenu);
1361         searchAction->addTo(editMenu);
1362
1363         // create options menu
1364         QPopupMenu* optionMenu = new QPopupMenu(this);
1365         menu->insertItem(_("&Option"), optionMenu);
1366         showNameAction->addTo(optionMenu);
1367         showRangeAction->addTo(optionMenu);
1368         showDataAction->addTo(optionMenu);
1369         optionMenu->insertSeparator();
1370         showAllAction->addTo(optionMenu);
1371         showDebugAction->addTo(optionMenu);
1372
1373         // create help menu
1374         QPopupMenu* helpMenu = new QPopupMenu(this);
1375         menu->insertSeparator();
1376         menu->insertItem(_("&Help"), helpMenu);
1377         showIntroAction->addTo(helpMenu);
1378         showAboutAction->addTo(helpMenu);
1379
1380         connect(configList, SIGNAL(menuChanged(struct menu *)),
1381                 helpText, SLOT(setInfo(struct menu *)));
1382         connect(configList, SIGNAL(menuSelected(struct menu *)),
1383                 SLOT(changeMenu(struct menu *)));
1384         connect(configList, SIGNAL(parentSelected()),
1385                 SLOT(goBack()));
1386         connect(menuList, SIGNAL(menuChanged(struct menu *)),
1387                 helpText, SLOT(setInfo(struct menu *)));
1388         connect(menuList, SIGNAL(menuSelected(struct menu *)),
1389                 SLOT(changeMenu(struct menu *)));
1390
1391         connect(configList, SIGNAL(gotFocus(struct menu *)),
1392                 helpText, SLOT(setInfo(struct menu *)));
1393         connect(menuList, SIGNAL(gotFocus(struct menu *)),
1394                 helpText, SLOT(setInfo(struct menu *)));
1395         connect(menuList, SIGNAL(gotFocus(struct menu *)),
1396                 SLOT(listFocusChanged(void)));
1397         connect(helpText, SIGNAL(menuSelected(struct menu *)),
1398                 SLOT(setMenuLink(struct menu *)));
1399
1400         QString listMode = configSettings->readEntry("/listMode", "symbol");
1401         if (listMode == "single")
1402                 showSingleView();
1403         else if (listMode == "full")
1404                 showFullView();
1405         else /*if (listMode == "split")*/
1406                 showSplitView();
1407
1408         // UI setup done, restore splitter positions
1409         QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
1410         if (ok)
1411                 split1->setSizes(sizes);
1412
1413         sizes = configSettings->readSizes("/split2", &ok);
1414         if (ok)
1415                 split2->setSizes(sizes);
1416 }
1417
1418 void ConfigMainWindow::loadConfig(void)
1419 {
1420         QString s = QFileDialog::getOpenFileName(conf_get_configname(), NULL, this);
1421         if (s.isNull())
1422                 return;
1423         if (conf_read(QFile::encodeName(s)))
1424                 QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
1425         ConfigView::updateListAll();
1426 }
1427
1428 void ConfigMainWindow::saveConfig(void)
1429 {
1430         if (conf_write(NULL))
1431                 QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
1432 }
1433
1434 void ConfigMainWindow::saveConfigAs(void)
1435 {
1436         QString s = QFileDialog::getSaveFileName(conf_get_configname(), NULL, this);
1437         if (s.isNull())
1438                 return;
1439         if (conf_write(QFile::encodeName(s)))
1440                 QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
1441 }
1442
1443 void ConfigMainWindow::searchConfig(void)
1444 {
1445         if (!searchWindow)
1446                 searchWindow = new ConfigSearchWindow(this, "search");
1447         searchWindow->show();
1448 }
1449
1450 void ConfigMainWindow::changeMenu(struct menu *menu)
1451 {
1452         configList->setRootMenu(menu);
1453         if (configList->rootEntry->parent == &rootmenu)
1454                 backAction->setEnabled(FALSE);
1455         else
1456                 backAction->setEnabled(TRUE);
1457 }
1458
1459 void ConfigMainWindow::setMenuLink(struct menu *menu)
1460 {
1461         struct menu *parent;
1462         ConfigList* list = NULL;
1463         ConfigItem* item;
1464
1465         if (!menu_is_visible(menu) && !configView->showAll())
1466                 return;
1467
1468         switch (configList->mode) {
1469         case singleMode:
1470                 list = configList;
1471                 parent = menu_get_parent_menu(menu);
1472                 if (!parent)
1473                         return;
1474                 list->setRootMenu(parent);
1475                 break;
1476         case symbolMode:
1477                 if (menu->flags & MENU_ROOT) {
1478                         configList->setRootMenu(menu);
1479                         configList->clearSelection();
1480                         list = menuList;
1481                 } else {
1482                         list = configList;
1483                         parent = menu_get_parent_menu(menu->parent);
1484                         if (!parent)
1485                                 return;
1486                         item = menuList->findConfigItem(parent);
1487                         if (item) {
1488                                 menuList->setSelected(item, TRUE);
1489                                 menuList->ensureItemVisible(item);
1490                         }
1491                         list->setRootMenu(parent);
1492                 }
1493                 break;
1494         case fullMode:
1495                 list = configList;
1496                 break;
1497         default:
1498                 break;
1499         }
1500
1501         if (list) {
1502                 item = list->findConfigItem(menu);
1503                 if (item) {
1504                         list->setSelected(item, TRUE);
1505                         list->ensureItemVisible(item);
1506                         list->setFocus();
1507                 }
1508         }
1509 }
1510
1511 void ConfigMainWindow::listFocusChanged(void)
1512 {
1513         if (menuList->mode == menuMode)
1514                 configList->clearSelection();
1515 }
1516
1517 void ConfigMainWindow::goBack(void)
1518 {
1519         ConfigItem* item;
1520
1521         configList->setParentMenu();
1522         if (configList->rootEntry == &rootmenu)
1523                 backAction->setEnabled(FALSE);
1524         item = (ConfigItem*)menuList->selectedItem();
1525         while (item) {
1526                 if (item->menu == configList->rootEntry) {
1527                         menuList->setSelected(item, TRUE);
1528                         break;
1529                 }
1530                 item = (ConfigItem*)item->parent();
1531         }
1532 }
1533
1534 void ConfigMainWindow::showSingleView(void)
1535 {
1536         menuView->hide();
1537         menuList->setRootMenu(0);
1538         configList->mode = singleMode;
1539         if (configList->rootEntry == &rootmenu)
1540                 configList->updateListAll();
1541         else
1542                 configList->setRootMenu(&rootmenu);
1543         configList->setAllOpen(TRUE);
1544         configList->setFocus();
1545 }
1546
1547 void ConfigMainWindow::showSplitView(void)
1548 {
1549         configList->mode = symbolMode;
1550         if (configList->rootEntry == &rootmenu)
1551                 configList->updateListAll();
1552         else
1553                 configList->setRootMenu(&rootmenu);
1554         configList->setAllOpen(TRUE);
1555         configApp->processEvents();
1556         menuList->mode = menuMode;
1557         menuList->setRootMenu(&rootmenu);
1558         menuList->setAllOpen(TRUE);
1559         menuView->show();
1560         menuList->setFocus();
1561 }
1562
1563 void ConfigMainWindow::showFullView(void)
1564 {
1565         menuView->hide();
1566         menuList->setRootMenu(0);
1567         configList->mode = fullMode;
1568         if (configList->rootEntry == &rootmenu)
1569                 configList->updateListAll();
1570         else
1571                 configList->setRootMenu(&rootmenu);
1572         configList->setAllOpen(FALSE);
1573         configList->setFocus();
1574 }
1575
1576 /*
1577  * ask for saving configuration before quitting
1578  * TODO ask only when something changed
1579  */
1580 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1581 {
1582         if (!conf_get_changed()) {
1583                 e->accept();
1584                 return;
1585         }
1586         QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
1587                         QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1588         mb.setButtonText(QMessageBox::Yes, _("&Save Changes"));
1589         mb.setButtonText(QMessageBox::No, _("&Discard Changes"));
1590         mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
1591         switch (mb.exec()) {
1592         case QMessageBox::Yes:
1593                 conf_write(NULL);
1594         case QMessageBox::No:
1595                 e->accept();
1596                 break;
1597         case QMessageBox::Cancel:
1598                 e->ignore();
1599                 break;
1600         }
1601 }
1602
1603 void ConfigMainWindow::showIntro(void)
1604 {
1605         static const QString str = _("Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
1606                 "For each option, a blank box indicates the feature is disabled, a check\n"
1607                 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1608                 "as a module.  Clicking on the box will cycle through the three states.\n\n"
1609                 "If you do not see an option (e.g., a device driver) that you believe\n"
1610                 "should be present, try turning on Show All Options under the Options menu.\n"
1611                 "Although there is no cross reference yet to help you figure out what other\n"
1612                 "options must be enabled to support the option you are interested in, you can\n"
1613                 "still view the help of a grayed-out option.\n\n"
1614                 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1615                 "which you can then match by examining other options.\n\n");
1616
1617         QMessageBox::information(this, "qconf", str);
1618 }
1619
1620 void ConfigMainWindow::showAbout(void)
1621 {
1622         static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
1623                 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
1624
1625         QMessageBox::information(this, "qconf", str);
1626 }
1627
1628 void ConfigMainWindow::saveSettings(void)
1629 {
1630         configSettings->writeEntry("/window x", pos().x());
1631         configSettings->writeEntry("/window y", pos().y());
1632         configSettings->writeEntry("/window width", size().width());
1633         configSettings->writeEntry("/window height", size().height());
1634
1635         QString entry;
1636         switch(configList->mode) {
1637         case singleMode :
1638                 entry = "single";
1639                 break;
1640
1641         case symbolMode :
1642                 entry = "split";
1643                 break;
1644
1645         case fullMode :
1646                 entry = "full";
1647                 break;
1648
1649         default:
1650                 break;
1651         }
1652         configSettings->writeEntry("/listMode", entry);
1653
1654         configSettings->writeSizes("/split1", split1->sizes());
1655         configSettings->writeSizes("/split2", split2->sizes());
1656 }
1657
1658 void ConfigMainWindow::conf_changed(void)
1659 {
1660         if (saveAction)
1661                 saveAction->setEnabled(conf_get_changed());
1662 }
1663
1664 void fixup_rootmenu(struct menu *menu)
1665 {
1666         struct menu *child;
1667         static int menu_cnt = 0;
1668
1669         menu->flags |= MENU_ROOT;
1670         for (child = menu->list; child; child = child->next) {
1671                 if (child->prompt && child->prompt->type == P_MENU) {
1672                         menu_cnt++;
1673                         fixup_rootmenu(child);
1674                         menu_cnt--;
1675                 } else if (!menu_cnt)
1676                         fixup_rootmenu(child);
1677         }
1678 }
1679
1680 static const char *progname;
1681
1682 static void usage(void)
1683 {
1684         printf(_("%s <config>\n"), progname);
1685         exit(0);
1686 }
1687
1688 int main(int ac, char** av)
1689 {
1690         ConfigMainWindow* v;
1691         const char *name;
1692
1693         bindtextdomain(PACKAGE, LOCALEDIR);
1694         textdomain(PACKAGE);
1695
1696 #ifndef LKC_DIRECT_LINK
1697         kconfig_load();
1698 #endif
1699
1700         progname = av[0];
1701         configApp = new QApplication(ac, av);
1702         if (ac > 1 && av[1][0] == '-') {
1703                 switch (av[1][1]) {
1704                 case 'h':
1705                 case '?':
1706                         usage();
1707                 }
1708                 name = av[2];
1709         } else
1710                 name = av[1];
1711         if (!name)
1712                 usage();
1713
1714         conf_parse(name);
1715         fixup_rootmenu(&rootmenu);
1716         conf_read(NULL);
1717         //zconfdump(stdout);
1718
1719         configSettings = new ConfigSettings();
1720         configSettings->beginGroup("/kconfig/qconf");
1721         v = new ConfigMainWindow();
1722
1723         //zconfdump(stdout);
1724         configApp->setMainWidget(v);
1725         configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1726         configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1727         v->show();
1728         configApp->exec();
1729
1730         configSettings->endGroup();
1731         delete configSettings;
1732
1733         return 0;
1734 }