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