Linux Audio

Check our new training course

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