Linux Audio

Check our new training course

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