Linux Audio

Check our new training course

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