Linux Audio

Check our new training course

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