]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - scripts/kconfig/qconf.cc
9fe27ca8a1923cdc02bf5a852db7e22d9e27a2c7
[linux-2.6-omap-h63xx.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 <qtoolbar.h>
9 #include <qlayout.h>
10 #include <qvbox.h>
11 #include <qsplitter.h>
12 #include <qlistview.h>
13 #include <qtextbrowser.h>
14 #include <qlineedit.h>
15 #include <qlabel.h>
16 #include <qpushbutton.h>
17 #include <qmenubar.h>
18 #include <qmessagebox.h>
19 #include <qaction.h>
20 #include <qheader.h>
21 #include <qfiledialog.h>
22 #include <qdragobject.h>
23 #include <qregexp.h>
24
25 #include <stdlib.h>
26
27 #include "lkc.h"
28 #include "qconf.h"
29
30 #include "qconf.moc"
31 #include "images.c"
32
33 #ifdef _
34 # undef _
35 # define _ qgettext
36 #endif
37
38 static QApplication *configApp;
39 static ConfigSettings *configSettings;
40
41 QAction *ConfigMainWindow::saveAction;
42
43 static inline QString qgettext(const char* str)
44 {
45         return QString::fromLocal8Bit(gettext(str));
46 }
47
48 static inline QString qgettext(const QString& str)
49 {
50         return QString::fromLocal8Bit(gettext(str.latin1()));
51 }
52
53 /**
54  * Reads a list of integer values from the application settings.
55  */
56 QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
57 {
58         QValueList<int> result;
59         QStringList entryList = readListEntry(key, ok);
60         if (ok) {
61                 QStringList::Iterator it;
62                 for (it = entryList.begin(); it != entryList.end(); ++it)
63                         result.push_back((*it).toInt());
64         }
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 Key_Escape:
301                 break;
302         case Key_Return:
303         case 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() == 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 Key_Return:
656         case 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 Key_Space:
671                 changeValue(item);
672                 break;
673         case Key_N:
674                 setValue(item, no);
675                 break;
676         case Key_M:
677                 setValue(item, mod);
678                 break;
679         case 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), menu(0), sym(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::setSource(const QString& name)
967 {
968         const char *p = name.latin1();
969
970         menu = NULL;
971         sym = NULL;
972
973         switch (p[0]) {
974         case 'm':
975                 struct menu *m;
976
977                 if (sscanf(p, "m%p", &m) == 1 && menu != m) {
978                         menu = m;
979                         menuInfo();
980                         emit menuSelected(menu);
981                 }
982                 break;
983         case 's':
984                 struct symbol *s;
985
986                 if (sscanf(p, "s%p", &s) == 1 && sym != s) {
987                         sym = s;
988                         symbolInfo();
989                 }
990                 break;
991         }
992 }
993
994 void ConfigInfoView::symbolInfo(void)
995 {
996         QString str;
997
998         str += "<big>Symbol: <b>";
999         str += print_filter(sym->name);
1000         str += "</b></big><br><br>value: ";
1001         str += print_filter(sym_get_string_value(sym));
1002         str += "<br>visibility: ";
1003         str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
1004         str += "<br>";
1005         str += debug_info(sym);
1006
1007         setText(str);
1008 }
1009
1010 void ConfigInfoView::menuInfo(void)
1011 {
1012         struct symbol* sym;
1013         QString head, debug, help;
1014
1015         sym = menu->sym;
1016         if (sym) {
1017                 if (menu->prompt) {
1018                         head += "<big><b>";
1019                         head += print_filter(_(menu->prompt->text));
1020                         head += "</b></big>";
1021                         if (sym->name) {
1022                                 head += " (";
1023                                 if (showDebug())
1024                                         head += QString().sprintf("<a href=\"s%p\">", sym);
1025                                 head += print_filter(sym->name);
1026                                 if (showDebug())
1027                                         head += "</a>";
1028                                 head += ")";
1029                         }
1030                 } else if (sym->name) {
1031                         head += "<big><b>";
1032                         if (showDebug())
1033                                 head += QString().sprintf("<a href=\"s%p\">", sym);
1034                         head += print_filter(sym->name);
1035                         if (showDebug())
1036                                 head += "</a>";
1037                         head += "</b></big>";
1038                 }
1039                 head += "<br><br>";
1040
1041                 if (showDebug())
1042                         debug = debug_info(sym);
1043
1044                 help = menu_get_help(menu);
1045                 /* Gettextize if the help text not empty */
1046                 if (help.isEmpty())
1047                         help = print_filter(menu_get_help(menu));
1048                 else
1049                         help = print_filter(_(menu_get_help(menu)));
1050         } else if (menu->prompt) {
1051                 head += "<big><b>";
1052                 head += print_filter(_(menu->prompt->text));
1053                 head += "</b></big><br><br>";
1054                 if (showDebug()) {
1055                         if (menu->prompt->visible.expr) {
1056                                 debug += "&nbsp;&nbsp;dep: ";
1057                                 expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
1058                                 debug += "<br><br>";
1059                         }
1060                 }
1061         }
1062         if (showDebug())
1063                 debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
1064
1065         setText(head + debug + help);
1066 }
1067
1068 QString ConfigInfoView::debug_info(struct symbol *sym)
1069 {
1070         QString debug;
1071
1072         debug += "type: ";
1073         debug += print_filter(sym_type_name(sym->type));
1074         if (sym_is_choice(sym))
1075                 debug += " (choice)";
1076         debug += "<br>";
1077         if (sym->rev_dep.expr) {
1078                 debug += "reverse dep: ";
1079                 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1080                 debug += "<br>";
1081         }
1082         for (struct property *prop = sym->prop; prop; prop = prop->next) {
1083                 switch (prop->type) {
1084                 case P_PROMPT:
1085                 case P_MENU:
1086                         debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
1087                         debug += print_filter(_(prop->text));
1088                         debug += "</a><br>";
1089                         break;
1090                 case P_DEFAULT:
1091                         debug += "default: ";
1092                         expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1093                         debug += "<br>";
1094                         break;
1095                 case P_CHOICE:
1096                         if (sym_is_choice(sym)) {
1097                                 debug += "choice: ";
1098                                 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1099                                 debug += "<br>";
1100                         }
1101                         break;
1102                 case P_SELECT:
1103                         debug += "select: ";
1104                         expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1105                         debug += "<br>";
1106                         break;
1107                 case P_RANGE:
1108                         debug += "range: ";
1109                         expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1110                         debug += "<br>";
1111                         break;
1112                 default:
1113                         debug += "unknown property: ";
1114                         debug += prop_get_type_name(prop->type);
1115                         debug += "<br>";
1116                 }
1117                 if (prop->visible.expr) {
1118                         debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
1119                         expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1120                         debug += "<br>";
1121                 }
1122         }
1123         debug += "<br>";
1124
1125         return debug;
1126 }
1127
1128 QString ConfigInfoView::print_filter(const QString &str)
1129 {
1130         QRegExp re("[<>&\"\\n]");
1131         QString res = str;
1132         for (int i = 0; (i = res.find(re, i)) >= 0;) {
1133                 switch (res[i].latin1()) {
1134                 case '<':
1135                         res.replace(i, 1, "&lt;");
1136                         i += 4;
1137                         break;
1138                 case '>':
1139                         res.replace(i, 1, "&gt;");
1140                         i += 4;
1141                         break;
1142                 case '&':
1143                         res.replace(i, 1, "&amp;");
1144                         i += 5;
1145                         break;
1146                 case '"':
1147                         res.replace(i, 1, "&quot;");
1148                         i += 6;
1149                         break;
1150                 case '\n':
1151                         res.replace(i, 1, "<br>");
1152                         i += 4;
1153                         break;
1154                 }
1155         }
1156         return res;
1157 }
1158
1159 void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
1160 {
1161         QString* text = reinterpret_cast<QString*>(data);
1162         QString str2 = print_filter(str);
1163
1164         if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1165                 *text += QString().sprintf("<a href=\"s%p\">", sym);
1166                 *text += str2;
1167                 *text += "</a>";
1168         } else
1169                 *text += str2;
1170 }
1171
1172 QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
1173 {
1174         QPopupMenu* popup = Parent::createPopupMenu(pos);
1175         QAction* action = new QAction(NULL, _("Show Debug Info"), 0, popup);
1176           action->setToggleAction(TRUE);
1177           connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1178           connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
1179           action->setOn(showDebug());
1180         popup->insertSeparator();
1181         action->addTo(popup);
1182         return popup;
1183 }
1184
1185 void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
1186 {
1187         Parent::contentsContextMenuEvent(e);
1188 }
1189
1190 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
1191         : Parent(parent, name), result(NULL)
1192 {
1193         setCaption("Search Config");
1194
1195         QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);
1196         QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);
1197         layout2->addWidget(new QLabel(_("Find:"), this));
1198         editField = new QLineEdit(this);
1199         connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1200         layout2->addWidget(editField);
1201         searchButton = new QPushButton(_("Search"), this);
1202         searchButton->setAutoDefault(FALSE);
1203         connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1204         layout2->addWidget(searchButton);
1205         layout1->addLayout(layout2);
1206
1207         split = new QSplitter(this);
1208         split->setOrientation(QSplitter::Vertical);
1209         list = new ConfigView(split, name);
1210         list->list->mode = listMode;
1211         info = new ConfigInfoView(split, name);
1212         connect(list->list, SIGNAL(menuChanged(struct menu *)),
1213                 info, SLOT(setInfo(struct menu *)));
1214         connect(list->list, SIGNAL(menuChanged(struct menu *)),
1215                 parent, SLOT(setMenuLink(struct menu *)));
1216
1217         layout1->addWidget(split);
1218
1219         if (name) {
1220                 int x, y, width, height;
1221                 bool ok;
1222
1223                 configSettings->beginGroup(name);
1224                 width = configSettings->readNumEntry("/window width", parent->width() / 2);
1225                 height = configSettings->readNumEntry("/window height", parent->height() / 2);
1226                 resize(width, height);
1227                 x = configSettings->readNumEntry("/window x", 0, &ok);
1228                 if (ok)
1229                         y = configSettings->readNumEntry("/window y", 0, &ok);
1230                 if (ok)
1231                         move(x, y);
1232                 QValueList<int> sizes = configSettings->readSizes("/split", &ok);
1233                 if (ok)
1234                         split->setSizes(sizes);
1235                 configSettings->endGroup();
1236                 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1237         }
1238 }
1239
1240 void ConfigSearchWindow::saveSettings(void)
1241 {
1242         if (name()) {
1243                 configSettings->beginGroup(name());
1244                 configSettings->writeEntry("/window x", pos().x());
1245                 configSettings->writeEntry("/window y", pos().y());
1246                 configSettings->writeEntry("/window width", size().width());
1247                 configSettings->writeEntry("/window height", size().height());
1248                 configSettings->writeSizes("/split", split->sizes());
1249                 configSettings->endGroup();
1250         }
1251 }
1252
1253 void ConfigSearchWindow::search(void)
1254 {
1255         struct symbol **p;
1256         struct property *prop;
1257         ConfigItem *lastItem = NULL;
1258
1259         free(result);
1260         list->list->clear();
1261         info->clear();
1262
1263         result = sym_re_search(editField->text().latin1());
1264         if (!result)
1265                 return;
1266         for (p = result; *p; p++) {
1267                 for_all_prompts((*p), prop)
1268                         lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1269                                                   menu_is_visible(prop->menu));
1270         }
1271 }
1272
1273 /*
1274  * Construct the complete config widget
1275  */
1276 ConfigMainWindow::ConfigMainWindow(void)
1277         : searchWindow(0)
1278 {
1279         QMenuBar* menu;
1280         bool ok;
1281         int x, y, width, height;
1282         char title[256];
1283
1284         QWidget *d = configApp->desktop();
1285         snprintf(title, sizeof(title), _("Linux Kernel v%s Configuration"),
1286                 getenv("KERNELVERSION"));
1287         setCaption(title);
1288
1289         width = configSettings->readNumEntry("/window width", d->width() - 64);
1290         height = configSettings->readNumEntry("/window height", d->height() - 64);
1291         resize(width, height);
1292         x = configSettings->readNumEntry("/window x", 0, &ok);
1293         if (ok)
1294                 y = configSettings->readNumEntry("/window y", 0, &ok);
1295         if (ok)
1296                 move(x, y);
1297
1298         split1 = new QSplitter(this);
1299         split1->setOrientation(QSplitter::Horizontal);
1300         setCentralWidget(split1);
1301
1302         menuView = new ConfigView(split1, "menu");
1303         menuList = menuView->list;
1304
1305         split2 = new QSplitter(split1);
1306         split2->setOrientation(QSplitter::Vertical);
1307
1308         // create config tree
1309         configView = new ConfigView(split2, "config");
1310         configList = configView->list;
1311
1312         helpText = new ConfigInfoView(split2, "help");
1313         helpText->setTextFormat(Qt::RichText);
1314
1315         setTabOrder(configList, helpText);
1316         configList->setFocus();
1317
1318         menu = menuBar();
1319         toolBar = new QToolBar("Tools", this);
1320
1321         backAction = new QAction("Back", QPixmap(xpm_back), _("Back"), 0, this);
1322           connect(backAction, SIGNAL(activated()), SLOT(goBack()));
1323           backAction->setEnabled(FALSE);
1324         QAction *quitAction = new QAction("Quit", _("&Quit"), CTRL+Key_Q, this);
1325           connect(quitAction, SIGNAL(activated()), SLOT(close()));
1326         QAction *loadAction = new QAction("Load", QPixmap(xpm_load), _("&Load"), CTRL+Key_L, this);
1327           connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
1328         saveAction = new QAction("Save", QPixmap(xpm_save), _("&Save"), CTRL+Key_S, this);
1329           connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
1330         conf_set_changed_callback(conf_changed);
1331         // Set saveAction's initial state
1332         conf_changed();
1333         QAction *saveAsAction = new QAction("Save As...", _("Save &As..."), 0, this);
1334           connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
1335         QAction *searchAction = new QAction("Find", _("&Find"), CTRL+Key_F, this);
1336           connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
1337         QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
1338           connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
1339         QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
1340           connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
1341         QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
1342           connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
1343
1344         QAction *showNameAction = new QAction(NULL, _("Show Name"), 0, this);
1345           showNameAction->setToggleAction(TRUE);
1346           connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1347           connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
1348           showNameAction->setOn(configView->showName());
1349         QAction *showRangeAction = new QAction(NULL, _("Show Range"), 0, this);
1350           showRangeAction->setToggleAction(TRUE);
1351           connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1352           connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
1353           showRangeAction->setOn(configList->showRange);
1354         QAction *showDataAction = new QAction(NULL, _("Show Data"), 0, this);
1355           showDataAction->setToggleAction(TRUE);
1356           connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1357           connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
1358           showDataAction->setOn(configList->showData);
1359         QAction *showAllAction = new QAction(NULL, _("Show All Options"), 0, this);
1360           showAllAction->setToggleAction(TRUE);
1361           connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool)));
1362           connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool)));
1363           showAllAction->setOn(configList->showAll);
1364         QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this);
1365           showDebugAction->setToggleAction(TRUE);
1366           connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1367           connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
1368           showDebugAction->setOn(helpText->showDebug());
1369
1370         QAction *showIntroAction = new QAction(NULL, _("Introduction"), 0, this);
1371           connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
1372         QAction *showAboutAction = new QAction(NULL, _("About"), 0, this);
1373           connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
1374
1375         // init tool bar
1376         backAction->addTo(toolBar);
1377         toolBar->addSeparator();
1378         loadAction->addTo(toolBar);
1379         saveAction->addTo(toolBar);
1380         toolBar->addSeparator();
1381         singleViewAction->addTo(toolBar);
1382         splitViewAction->addTo(toolBar);
1383         fullViewAction->addTo(toolBar);
1384
1385         // create config menu
1386         QPopupMenu* config = new QPopupMenu(this);
1387         menu->insertItem(_("&File"), config);
1388         loadAction->addTo(config);
1389         saveAction->addTo(config);
1390         saveAsAction->addTo(config);
1391         config->insertSeparator();
1392         quitAction->addTo(config);
1393
1394         // create edit menu
1395         QPopupMenu* editMenu = new QPopupMenu(this);
1396         menu->insertItem(_("&Edit"), editMenu);
1397         searchAction->addTo(editMenu);
1398
1399         // create options menu
1400         QPopupMenu* optionMenu = new QPopupMenu(this);
1401         menu->insertItem(_("&Option"), optionMenu);
1402         showNameAction->addTo(optionMenu);
1403         showRangeAction->addTo(optionMenu);
1404         showDataAction->addTo(optionMenu);
1405         optionMenu->insertSeparator();
1406         showAllAction->addTo(optionMenu);
1407         showDebugAction->addTo(optionMenu);
1408
1409         // create help menu
1410         QPopupMenu* helpMenu = new QPopupMenu(this);
1411         menu->insertSeparator();
1412         menu->insertItem(_("&Help"), helpMenu);
1413         showIntroAction->addTo(helpMenu);
1414         showAboutAction->addTo(helpMenu);
1415
1416         connect(configList, SIGNAL(menuChanged(struct menu *)),
1417                 helpText, SLOT(setInfo(struct menu *)));
1418         connect(configList, SIGNAL(menuSelected(struct menu *)),
1419                 SLOT(changeMenu(struct menu *)));
1420         connect(configList, SIGNAL(parentSelected()),
1421                 SLOT(goBack()));
1422         connect(menuList, SIGNAL(menuChanged(struct menu *)),
1423                 helpText, SLOT(setInfo(struct menu *)));
1424         connect(menuList, SIGNAL(menuSelected(struct menu *)),
1425                 SLOT(changeMenu(struct menu *)));
1426
1427         connect(configList, SIGNAL(gotFocus(struct menu *)),
1428                 helpText, SLOT(setInfo(struct menu *)));
1429         connect(menuList, SIGNAL(gotFocus(struct menu *)),
1430                 helpText, SLOT(setInfo(struct menu *)));
1431         connect(menuList, SIGNAL(gotFocus(struct menu *)),
1432                 SLOT(listFocusChanged(void)));
1433         connect(helpText, SIGNAL(menuSelected(struct menu *)),
1434                 SLOT(setMenuLink(struct menu *)));
1435
1436         QString listMode = configSettings->readEntry("/listMode", "symbol");
1437         if (listMode == "single")
1438                 showSingleView();
1439         else if (listMode == "full")
1440                 showFullView();
1441         else /*if (listMode == "split")*/
1442                 showSplitView();
1443
1444         // UI setup done, restore splitter positions
1445         QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
1446         if (ok)
1447                 split1->setSizes(sizes);
1448
1449         sizes = configSettings->readSizes("/split2", &ok);
1450         if (ok)
1451                 split2->setSizes(sizes);
1452 }
1453
1454 void ConfigMainWindow::loadConfig(void)
1455 {
1456         QString s = QFileDialog::getOpenFileName(".config", NULL, this);
1457         if (s.isNull())
1458                 return;
1459         if (conf_read(QFile::encodeName(s)))
1460                 QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
1461         ConfigView::updateListAll();
1462 }
1463
1464 void ConfigMainWindow::saveConfig(void)
1465 {
1466         if (conf_write(NULL))
1467                 QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
1468 }
1469
1470 void ConfigMainWindow::saveConfigAs(void)
1471 {
1472         QString s = QFileDialog::getSaveFileName(".config", NULL, this);
1473         if (s.isNull())
1474                 return;
1475         if (conf_write(QFile::encodeName(s)))
1476                 QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
1477 }
1478
1479 void ConfigMainWindow::searchConfig(void)
1480 {
1481         if (!searchWindow)
1482                 searchWindow = new ConfigSearchWindow(this, "search");
1483         searchWindow->show();
1484 }
1485
1486 void ConfigMainWindow::changeMenu(struct menu *menu)
1487 {
1488         configList->setRootMenu(menu);
1489         if (configList->rootEntry->parent == &rootmenu)
1490                 backAction->setEnabled(FALSE);
1491         else
1492                 backAction->setEnabled(TRUE);
1493 }
1494
1495 void ConfigMainWindow::setMenuLink(struct menu *menu)
1496 {
1497         struct menu *parent;
1498         ConfigList* list = NULL;
1499         ConfigItem* item;
1500
1501         if (!menu_is_visible(menu) && !configView->showAll())
1502                 return;
1503
1504         switch (configList->mode) {
1505         case singleMode:
1506                 list = configList;
1507                 parent = menu_get_parent_menu(menu);
1508                 if (!parent)
1509                         return;
1510                 list->setRootMenu(parent);
1511                 break;
1512         case symbolMode:
1513                 if (menu->flags & MENU_ROOT) {
1514                         configList->setRootMenu(menu);
1515                         configList->clearSelection();
1516                         list = menuList;
1517                 } else {
1518                         list = configList;
1519                         parent = menu_get_parent_menu(menu->parent);
1520                         if (!parent)
1521                                 return;
1522                         item = menuList->findConfigItem(parent);
1523                         if (item) {
1524                                 menuList->setSelected(item, TRUE);
1525                                 menuList->ensureItemVisible(item);
1526                         }
1527                         list->setRootMenu(parent);
1528                 }
1529                 break;
1530         case fullMode:
1531                 list = configList;
1532                 break;
1533         }
1534
1535         if (list) {
1536                 item = list->findConfigItem(menu);
1537                 if (item) {
1538                         list->setSelected(item, TRUE);
1539                         list->ensureItemVisible(item);
1540                         list->setFocus();
1541                 }
1542         }
1543 }
1544
1545 void ConfigMainWindow::listFocusChanged(void)
1546 {
1547         if (menuList->mode == menuMode)
1548                 configList->clearSelection();
1549 }
1550
1551 void ConfigMainWindow::goBack(void)
1552 {
1553         ConfigItem* item;
1554
1555         configList->setParentMenu();
1556         if (configList->rootEntry == &rootmenu)
1557                 backAction->setEnabled(FALSE);
1558         item = (ConfigItem*)menuList->selectedItem();
1559         while (item) {
1560                 if (item->menu == configList->rootEntry) {
1561                         menuList->setSelected(item, TRUE);
1562                         break;
1563                 }
1564                 item = (ConfigItem*)item->parent();
1565         }
1566 }
1567
1568 void ConfigMainWindow::showSingleView(void)
1569 {
1570         menuView->hide();
1571         menuList->setRootMenu(0);
1572         configList->mode = singleMode;
1573         if (configList->rootEntry == &rootmenu)
1574                 configList->updateListAll();
1575         else
1576                 configList->setRootMenu(&rootmenu);
1577         configList->setAllOpen(TRUE);
1578         configList->setFocus();
1579 }
1580
1581 void ConfigMainWindow::showSplitView(void)
1582 {
1583         configList->mode = symbolMode;
1584         if (configList->rootEntry == &rootmenu)
1585                 configList->updateListAll();
1586         else
1587                 configList->setRootMenu(&rootmenu);
1588         configList->setAllOpen(TRUE);
1589         configApp->processEvents();
1590         menuList->mode = menuMode;
1591         menuList->setRootMenu(&rootmenu);
1592         menuList->setAllOpen(TRUE);
1593         menuView->show();
1594         menuList->setFocus();
1595 }
1596
1597 void ConfigMainWindow::showFullView(void)
1598 {
1599         menuView->hide();
1600         menuList->setRootMenu(0);
1601         configList->mode = fullMode;
1602         if (configList->rootEntry == &rootmenu)
1603                 configList->updateListAll();
1604         else
1605                 configList->setRootMenu(&rootmenu);
1606         configList->setAllOpen(FALSE);
1607         configList->setFocus();
1608 }
1609
1610 /*
1611  * ask for saving configuration before quitting
1612  * TODO ask only when something changed
1613  */
1614 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1615 {
1616         if (!conf_get_changed()) {
1617                 e->accept();
1618                 return;
1619         }
1620         QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
1621                         QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1622         mb.setButtonText(QMessageBox::Yes, _("&Save Changes"));
1623         mb.setButtonText(QMessageBox::No, _("&Discard Changes"));
1624         mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
1625         switch (mb.exec()) {
1626         case QMessageBox::Yes:
1627                 conf_write(NULL);
1628         case QMessageBox::No:
1629                 e->accept();
1630                 break;
1631         case QMessageBox::Cancel:
1632                 e->ignore();
1633                 break;
1634         }
1635 }
1636
1637 void ConfigMainWindow::showIntro(void)
1638 {
1639         static const QString str = _("Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
1640                 "For each option, a blank box indicates the feature is disabled, a check\n"
1641                 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1642                 "as a module.  Clicking on the box will cycle through the three states.\n\n"
1643                 "If you do not see an option (e.g., a device driver) that you believe\n"
1644                 "should be present, try turning on Show All Options under the Options menu.\n"
1645                 "Although there is no cross reference yet to help you figure out what other\n"
1646                 "options must be enabled to support the option you are interested in, you can\n"
1647                 "still view the help of a grayed-out option.\n\n"
1648                 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1649                 "which you can then match by examining other options.\n\n");
1650
1651         QMessageBox::information(this, "qconf", str);
1652 }
1653
1654 void ConfigMainWindow::showAbout(void)
1655 {
1656         static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
1657                 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
1658
1659         QMessageBox::information(this, "qconf", str);
1660 }
1661
1662 void ConfigMainWindow::saveSettings(void)
1663 {
1664         configSettings->writeEntry("/window x", pos().x());
1665         configSettings->writeEntry("/window y", pos().y());
1666         configSettings->writeEntry("/window width", size().width());
1667         configSettings->writeEntry("/window height", size().height());
1668
1669         QString entry;
1670         switch(configList->mode) {
1671         case singleMode :
1672                 entry = "single";
1673                 break;
1674
1675         case symbolMode :
1676                 entry = "split";
1677                 break;
1678
1679         case fullMode :
1680                 entry = "full";
1681                 break;
1682         }
1683         configSettings->writeEntry("/listMode", entry);
1684
1685         configSettings->writeSizes("/split1", split1->sizes());
1686         configSettings->writeSizes("/split2", split2->sizes());
1687 }
1688
1689 void ConfigMainWindow::conf_changed(void)
1690 {
1691         if (saveAction)
1692                 saveAction->setEnabled(conf_get_changed());
1693 }
1694
1695 void fixup_rootmenu(struct menu *menu)
1696 {
1697         struct menu *child;
1698         static int menu_cnt = 0;
1699
1700         menu->flags |= MENU_ROOT;
1701         for (child = menu->list; child; child = child->next) {
1702                 if (child->prompt && child->prompt->type == P_MENU) {
1703                         menu_cnt++;
1704                         fixup_rootmenu(child);
1705                         menu_cnt--;
1706                 } else if (!menu_cnt)
1707                         fixup_rootmenu(child);
1708         }
1709 }
1710
1711 static const char *progname;
1712
1713 static void usage(void)
1714 {
1715         printf(_("%s <config>\n"), progname);
1716         exit(0);
1717 }
1718
1719 int main(int ac, char** av)
1720 {
1721         ConfigMainWindow* v;
1722         const char *name;
1723
1724         bindtextdomain(PACKAGE, LOCALEDIR);
1725         textdomain(PACKAGE);
1726
1727 #ifndef LKC_DIRECT_LINK
1728         kconfig_load();
1729 #endif
1730
1731         progname = av[0];
1732         configApp = new QApplication(ac, av);
1733         if (ac > 1 && av[1][0] == '-') {
1734                 switch (av[1][1]) {
1735                 case 'h':
1736                 case '?':
1737                         usage();
1738                 }
1739                 name = av[2];
1740         } else
1741                 name = av[1];
1742         if (!name)
1743                 usage();
1744
1745         conf_parse(name);
1746         fixup_rootmenu(&rootmenu);
1747         conf_read(NULL);
1748         //zconfdump(stdout);
1749
1750         configSettings = new ConfigSettings();
1751         configSettings->beginGroup("/kconfig/qconf");
1752         v = new ConfigMainWindow();
1753
1754         //zconfdump(stdout);
1755         configApp->setMainWidget(v);
1756         configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1757         configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1758         v->show();
1759         configApp->exec();
1760
1761         configSettings->endGroup();
1762         delete configSettings;
1763
1764         return 0;
1765 }