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