Linux Audio

Check our new training course

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