Linux Audio

Check our new training course

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