Linux Audio

Check our new training course

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