Linux Audio

Check our new training course

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