Linux Audio

Check our new training course

Buildroot integration, development and maintenance

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