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