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