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