diff mbox

[19/39] Port xconfig to Qt5 - Put back some of the old implementation(part 2).

Message ID 1442946999-37018-20-git-send-email-thiago.macieira@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Thiago Macieira Sept. 22, 2015, 6:36 p.m. UTC
From: Boris Barbulovski <bbarbulovski@gmail.com>

Signed-off-by: Boris Barbulovski <bbarbulovski@gmail.com>
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
---
 scripts/kconfig/qconf.h  |  45 +--
 scripts/kconfig/qconf.cc | 788 ++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 807 insertions(+), 26 deletions(-)
diff mbox

Patch

diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index 7c55b1d..819e029 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -53,10 +53,10 @@  public:
 
 protected:
 	void keyPressEvent(QKeyEvent *e);
-	void contentsMousePressEvent(QMouseEvent *e);
-	void contentsMouseReleaseEvent(QMouseEvent *e);
-	void contentsMouseMoveEvent(QMouseEvent *e);
-	void contentsMouseDoubleClickEvent(QMouseEvent *e);
+	void mousePressEvent(QMouseEvent *e);
+	void mouseReleaseEvent(QMouseEvent *e);
+	void mouseMoveEvent(QMouseEvent *e);
+	void mouseDoubleClickEvent(QMouseEvent *e);
 	void focusInEvent(QFocusEvent *e);
 	void contextMenuEvent(QContextMenuEvent *e);
 
@@ -87,16 +87,15 @@  public:
 	}
 	ConfigItem* firstChild() const
 	{
-		// TODO: Implement me.
-		return NULL;
+		return (ConfigItem *)children().first();
 	}
-	void addColumn(colIdx idx, const QString& label)
+	void addColumn(colIdx idx)
 	{
-		// TODO: Implement me.
+		showColumn(idx);
 	}
 	void removeColumn(colIdx idx)
 	{
-		// TODO: Implement me.
+		hideColumn(idx);
 	}
 	void setAllOpen(bool open);
 	void setParentMenu(void);
@@ -124,7 +123,7 @@  public:
 class ConfigItem : public QTreeWidgetItem {
 	typedef class QTreeWidgetItem Parent;
 public:
-	ConfigItem(QTreeWidgetItem *parent, ConfigItem *after, struct menu *m, bool v)
+	ConfigItem(QTreeWidget *parent, ConfigItem *after, struct menu *m, bool v)
 	: Parent(parent, after), menu(m), visible(v), goParent(false)
 	{
 		init();
@@ -134,7 +133,7 @@  public:
 	{
 		init();
 	}
-	ConfigItem(QTreeWidgetItem *parent, ConfigItem *after, bool v)
+	ConfigItem(QTreeWidget *parent, ConfigItem *after, bool v)
 	: Parent(parent, after), menu(0), visible(v), goParent(true)
 	{
 		init();
@@ -152,9 +151,19 @@  public:
 	{
 		return (ConfigItem *)Parent::child(0);
 	}
-	ConfigItem* nextSibling() const
+	ConfigItem* nextSibling()
 	{
-		return NULL; // TODO: Implement me
+		ConfigItem *ret = NULL;
+		ConfigItem *_parent = (ConfigItem *)parent();
+
+		if(_parent) {
+		  ret = (ConfigItem *)_parent->child(_parent->indexOfChild(this)+1);
+		} else {
+		  QTreeWidget *_treeWidget = treeWidget();
+		  ret = (ConfigItem *)_treeWidget->topLevelItem(_treeWidget->indexOfTopLevelItem(this)+1);
+		}
+
+		return ret;
 	}
 	void setText(colIdx idx, const QString& text)
 	{
@@ -164,15 +173,15 @@  public:
 	{
 		return Parent::text(idx);
 	}
-	void setPixmap(colIdx idx, const QPixmap& pm)
+	void setPixmap(colIdx idx, const QIcon &icon)
 	{
-		// TODO: Implement me
+		Parent::setIcon(idx, icon);
 	}
-	const QPixmap* pixmap(colIdx idx) const
+	const QIcon pixmap(colIdx idx) const
 	{
-		return NULL; // TODO: Implement me
+		return icon(idx);
 	}
-	// Implement paintCell
+	// TODO: Implement paintCell
 
 	ConfigItem* nextItem;
 	struct menu *menu;
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index 0987a75..e0518ca 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -102,10 +102,135 @@  void ConfigItem::okRename(int col)
  */
 void ConfigItem::updateMenu(void)
 {
+	ConfigList* list;
+	struct symbol* sym;
+	struct property *prop;
+	QString prompt;
+	int type;
+	tristate expr;
+
+	list = listView();
+	if (goParent) {
+		setPixmap(promptColIdx, list->menuBackPix);
+		prompt = "..";
+		goto set_prompt;
+	}
+
+	sym = menu->sym;
+	prop = menu->prompt;
+	prompt = _(menu_get_prompt(menu));
+
+	if (prop) switch (prop->type) {
+	case P_MENU:
+		if (list->mode == singleMode || list->mode == symbolMode) {
+			/* a menuconfig entry is displayed differently
+			 * depending whether it's at the view root or a child.
+			 */
+			if (sym && list->rootEntry == menu)
+				break;
+			setPixmap(promptColIdx, list->menuPix);
+		} else {
+			if (sym)
+				break;
+			setPixmap(promptColIdx, QIcon());
+		}
+		goto set_prompt;
+	case P_COMMENT:
+		setPixmap(promptColIdx, QIcon());
+		goto set_prompt;
+	default:
+		;
+	}
+	if (!sym)
+		goto set_prompt;
+
+	setText(nameColIdx, QString::fromLocal8Bit(sym->name));
+
+	type = sym_get_type(sym);
+	switch (type) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		char ch;
+
+		if (!sym_is_changable(sym) && list->optMode == normalOpt) {
+			setPixmap(promptColIdx, QIcon());
+			setText(noColIdx, QString::null);
+			setText(modColIdx, QString::null);
+			setText(yesColIdx, QString::null);
+			break;
+		}
+		expr = sym_get_tristate_value(sym);
+		switch (expr) {
+		case yes:
+			if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+				setPixmap(promptColIdx, list->choiceYesPix);
+			else
+				setPixmap(promptColIdx, list->symbolYesPix);
+			setText(yesColIdx, "Y");
+			ch = 'Y';
+			break;
+		case mod:
+			setPixmap(promptColIdx, list->symbolModPix);
+			setText(modColIdx, "M");
+			ch = 'M';
+			break;
+		default:
+			if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+				setPixmap(promptColIdx, list->choiceNoPix);
+			else
+				setPixmap(promptColIdx, list->symbolNoPix);
+			setText(noColIdx, "N");
+			ch = 'N';
+			break;
+		}
+		if (expr != no)
+			setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
+		if (expr != mod)
+			setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
+		if (expr != yes)
+			setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
+
+		setText(dataColIdx, QChar(ch));
+		break;
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+		const char* data;
+
+		data = sym_get_string_value(sym);
+
+		//int i = list->mapIdx(dataColIdx);
+		//if (i >= 0)
+		//	setRenameEnabled(i, true);
+		setText(dataColIdx, data);
+		if (type == S_STRING)
+			prompt = QString("%1: %2").arg(prompt).arg(data);
+		else
+			prompt = QString("(%2) %1").arg(prompt).arg(data);
+		break;
+	}
+	if (!sym_has_value(sym) && visible)
+		prompt += _(" (NEW)");
+set_prompt:
+	setText(promptColIdx, prompt);
 }
 
 void ConfigItem::testUpdateMenu(bool v)
 {
+	ConfigItem* i;
+
+	visible = v;
+	if (!menu)
+		return;
+
+	sym_calc_value(menu->sym);
+	if (menu->flags & MENU_CHANGED) {
+		/* the menu entry changed, so update all list items */
+		menu->flags &= ~MENU_CHANGED;
+		for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
+			i->updateMenu();
+	} else if (listView()->updateAll)
+		updateMenu();
 }
 
 
@@ -114,6 +239,16 @@  void ConfigItem::testUpdateMenu(bool v)
  */
 void ConfigItem::init(void)
 {
+	if (menu) {
+		ConfigList* list = listView();
+		nextItem = (ConfigItem*)menu->data;
+		menu->data = this;
+
+		if (list->mode != fullMode)
+			setExpanded(true);
+		sym_calc_value(menu->sym);
+	}
+	updateMenu();
 }
 
 /*
@@ -121,17 +256,30 @@  void ConfigItem::init(void)
  */
 ConfigItem::~ConfigItem(void)
 {
+	if (menu) {
+		ConfigItem** ip = (ConfigItem**)&menu->data;
+		for (; *ip; ip = &(*ip)->nextItem) {
+			if (*ip == this) {
+				*ip = nextItem;
+				break;
+			}
+		}
+	}
 }
 
 ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
 	: Parent(parent)
 {
-	connect(this, SIGNAL(editingFinished()), SLOT(hide()));
+	connect(this, SIGNAL(lostFocus()), SLOT(hide()));
 }
 
 void ConfigLineEdit::show(ConfigItem* i)
 {
 	item = i;
+	if (sym_get_string_value(item->menu->sym))
+		setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
+	else
+		setText(QString::null);
 	Parent::show();
 	setFocus();
 }
@@ -143,6 +291,7 @@  void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
 		break;
 	case Qt::Key_Return:
 	case Qt::Key_Enter:
+		sym_set_string_value(item->menu->sym, text().toLatin1());
 		parent()->updateList(item);
 		break;
 	default:
@@ -163,42 +312,251 @@  ConfigList::ConfigList(ConfigView* p, const char *name)
 	  showName(false), showRange(false), showData(false), optMode(normalOpt),
 	  rootEntry(0), headerPopup(0)
 {
+	int i;
+
+	setObjectName(name);
+	setSortingEnabled(-1);
+	setRootIsDecorated(true);
+
+	connect(this, SIGNAL(selectionChanged(void)),
+		SLOT(updateSelection(void)));
+
+	if (name) {
+		configSettings->beginGroup(name);
+		showName = configSettings->value("/showName", false).toBool();
+		showRange = configSettings->value("/showRange", false).toBool();
+		showData = configSettings->value("/showData", false).toBool();
+		optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt();
+		configSettings->endGroup();
+		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+	}
+
+	addColumn(promptColIdx);
+
+	reinit();
+}
+
+bool ConfigList::menuSkip(struct menu *menu)
+{
+	if (optMode == normalOpt && menu_is_visible(menu))
+		return false;
+	if (optMode == promptOpt && menu_has_prompt(menu))
+		return false;
+	if (optMode == allOpt)
+		return false;
+	return true;
 }
 
 void ConfigList::reinit(void)
 {
+	removeColumn(dataColIdx);
+	removeColumn(yesColIdx);
+	removeColumn(modColIdx);
+	removeColumn(noColIdx);
+	removeColumn(nameColIdx);
+
+	if (showName)
+		addColumn(nameColIdx);
+	if (showRange) {
+		addColumn(noColIdx);
+		addColumn(modColIdx);
+		addColumn(yesColIdx);
+	}
+	if (showData)
+		addColumn(dataColIdx);
+
+	updateListAll();
 }
 
 void ConfigList::saveSettings(void)
 {
+	if (!objectName().isEmpty()) {
+		configSettings->beginGroup(objectName());
+		configSettings->setValue("/showName", showName);
+		configSettings->setValue("/showRange", showRange);
+		configSettings->setValue("/showData", showData);
+		configSettings->setValue("/optionMode", (int)optMode);
+		configSettings->endGroup();
+	}
 }
 
 ConfigItem* ConfigList::findConfigItem(struct menu *menu)
 {
+	ConfigItem* item = (ConfigItem*)menu->data;
+
+	for (; item; item = item->nextItem) {
+		if (this == item->listView())
+			break;
+	}
+
+	return item;
 }
 
 void ConfigList::updateSelection(void)
 {
+	struct menu *menu;
+	enum prop_type type;
+
+	ConfigItem* item = (ConfigItem*)selectedItems().first();
+	if (!item)
+		return;
+
+	menu = item->menu;
+	emit menuChanged(menu);
+	if (!menu)
+		return;
+	type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+	if (mode == menuMode && type == P_MENU)
+		emit menuSelected(menu);
 }
 
 void ConfigList::updateList(ConfigItem* item)
 {
+	ConfigItem* last = 0;
+
+	if (!rootEntry) {
+		if (mode != listMode)
+			goto update;
+		QTreeWidgetItemIterator it(this);
+		ConfigItem* item;
+
+		while (*it) {
+			item = (ConfigItem*)(*it);
+			if (!item->menu)
+				continue;
+			item->testUpdateMenu(menu_is_visible(item->menu));
+
+			++it;
+		}
+		return;
+	}
+
+	if (rootEntry != &rootmenu && (mode == singleMode ||
+	    (mode == symbolMode && rootEntry->parent != &rootmenu))) {
+		item = firstChild();
+		if (!item)
+			item = new ConfigItem(this, 0, true);
+		last = item;
+	}
+	if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
+	    rootEntry->sym && rootEntry->prompt) {
+		item = last ? last->nextSibling() : firstChild();
+		if (!item)
+			item = new ConfigItem(this, last, rootEntry, true);
+		else
+			item->testUpdateMenu(true);
+
+		updateMenuList(item, rootEntry);
+		update();
+		return;
+	}
+update:
+	updateMenuList(this, rootEntry);
+	update();
 }
 
 void ConfigList::setValue(ConfigItem* item, tristate val)
 {
+	struct symbol* sym;
+	int type;
+	tristate oldval;
+
+	sym = item->menu ? item->menu->sym : 0;
+	if (!sym)
+		return;
+
+	type = sym_get_type(sym);
+	switch (type) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		oldval = sym_get_tristate_value(sym);
+
+		if (!sym_set_tristate_value(sym, val))
+			return;
+		if (oldval == no && item->menu->list)
+			item->setExpanded(true);
+		parent()->updateList(item);
+		break;
+	}
 }
 
 void ConfigList::changeValue(ConfigItem* item)
 {
+	struct symbol* sym;
+	struct menu* menu;
+	int type, oldexpr, newexpr;
+
+	menu = item->menu;
+	if (!menu)
+		return;
+	sym = menu->sym;
+	if (!sym) {
+		if (item->menu->list)
+			item->setExpanded(!item->isExpanded());
+		return;
+	}
+
+	type = sym_get_type(sym);
+	switch (type) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		oldexpr = sym_get_tristate_value(sym);
+		newexpr = sym_toggle_tristate_value(sym);
+		if (item->menu->list) {
+			if (oldexpr == newexpr)
+				item->setExpanded(!item->isExpanded());
+			else if (oldexpr == no)
+				item->setExpanded(true);
+		}
+		if (oldexpr != newexpr)
+			parent()->updateList(item);
+		break;
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+		break;
+	}
 }
 
 void ConfigList::setRootMenu(struct menu *menu)
 {
+	enum prop_type type;
+
+	if (rootEntry == menu)
+		return;
+	type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
+	if (type != P_MENU)
+		return;
+	updateMenuList(this, 0);
+	rootEntry = menu;
+	updateListAll();
+	if (currentItem()) {
+		currentItem()->setSelected(hasFocus());
+		scrollToItem(currentItem());
+	}
 }
 
 void ConfigList::setParentMenu(void)
 {
+	ConfigItem* item;
+	struct menu *oldroot;
+
+	oldroot = rootEntry;
+	if (rootEntry == &rootmenu)
+		return;
+	setRootMenu(menu_get_parent_menu(rootEntry->parent));
+
+	QTreeWidgetItemIterator it(this);
+	while (*it) {
+		item = (ConfigItem *)(*it);
+		if (item->menu == oldroot) {
+			setCurrentItem(item);
+			scrollToItem(item);
+			break;
+		}
+
+		++it;
+	}
 }
 
 /*
@@ -211,34 +569,250 @@  void ConfigList::setParentMenu(void)
 template <class P>
 void ConfigList::updateMenuList(P* parent, struct menu* menu)
 {
+	struct menu* child;
+	ConfigItem* item;
+	ConfigItem* last;
+	bool visible;
+	enum prop_type type;
+
+	if (!menu) {
+		while ((item = parent->firstChild()))
+			item->parent()->removeChild(item);
+			delete item;
+		return;
+	}
+
+	last = parent->firstChild();
+	if (last && !last->goParent)
+		last = 0;
+	for (child = menu->list; child; child = child->next) {
+		item = last ? last->nextSibling() : parent->firstChild();
+		type = child->prompt ? child->prompt->type : P_UNKNOWN;
+
+		switch (mode) {
+		case menuMode:
+			if (!(child->flags & MENU_ROOT))
+				goto hide;
+			break;
+		case symbolMode:
+			if (child->flags & MENU_ROOT)
+				goto hide;
+			break;
+		default:
+			break;
+		}
+
+		visible = menu_is_visible(child);
+		if (!menuSkip(child)) {
+			if (!child->sym && !child->list && !child->prompt)
+				continue;
+			if (!item || item->menu != child)
+				item = new ConfigItem(parent, last, child, visible);
+			else
+				item->testUpdateMenu(visible);
+
+			if (mode == fullMode || mode == menuMode || type != P_MENU)
+				updateMenuList(item, child);
+			else
+				updateMenuList(item, 0);
+			last = item;
+			continue;
+		}
+	hide:
+		if (item && item->menu == child) {
+			last = parent->firstChild();
+			if (last == item)
+				last = 0;
+			else while (last->nextSibling() != item)
+				last = last->nextSibling();
+			delete item;
+		}
+	}
 }
 
 void ConfigList::keyPressEvent(QKeyEvent* ev)
 {
+	QTreeWidgetItem* i = currentItem();
+	ConfigItem* item;
+	struct menu *menu;
+	enum prop_type type;
+
+	if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
+		emit parentSelected();
+		ev->accept();
+		return;
+	}
+
+	if (!i) {
+		Parent::keyPressEvent(ev);
+		return;
+	}
+	item = (ConfigItem*)i;
+
+	switch (ev->key()) {
+	case Qt::Key_Return:
+	case Qt::Key_Enter:
+		if (item->goParent) {
+			emit parentSelected();
+			break;
+		}
+		menu = item->menu;
+		if (!menu)
+			break;
+		type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+		if (type == P_MENU && rootEntry != menu &&
+		    mode != fullMode && mode != menuMode) {
+			emit menuSelected(menu);
+			break;
+		}
+	case Qt::Key_Space:
+		changeValue(item);
+		break;
+	case Qt::Key_N:
+		setValue(item, no);
+		break;
+	case Qt::Key_M:
+		setValue(item, mod);
+		break;
+	case Qt::Key_Y:
+		setValue(item, yes);
+		break;
+	default:
+		Parent::keyPressEvent(ev);
+		return;
+	}
+	ev->accept();
 }
 
-void ConfigList::contentsMousePressEvent(QMouseEvent* e)
+void ConfigList::mousePressEvent(QMouseEvent* e)
 {
+	//QPoint p(contentsToViewport(e->pos()));
+	//printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
+	Parent::mousePressEvent(e);
 }
 
-void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
+void ConfigList::mouseReleaseEvent(QMouseEvent* e)
 {
+	QPoint p = e->pos();
+	ConfigItem* item = (ConfigItem*)itemAt(p);
+	struct menu *menu;
+	enum prop_type ptype;
+	QIcon icon;
+	int idx, x;
+
+	if (!item)
+		goto skip;
+
+	menu = item->menu;
+	x = header()->offset() + p.x();
+	idx = header()->sectionPosition(x);
+	switch (idx) {
+	case promptColIdx:
+		icon = item->pixmap(promptColIdx);
+		break;
+	case noColIdx:
+		setValue(item, no);
+		break;
+	case modColIdx:
+		setValue(item, mod);
+		break;
+	case yesColIdx:
+		setValue(item, yes);
+		break;
+	case dataColIdx:
+		changeValue(item);
+		break;
+	}
+
+skip:
+	//printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
+	Parent::mouseReleaseEvent(e);
 }
 
-void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
+void ConfigList::mouseMoveEvent(QMouseEvent* e)
 {
+	//QPoint p(contentsToViewport(e->pos()));
+	//printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
+	Parent::mouseMoveEvent(e);
 }
 
-void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
+void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
 {
+	QPoint p = e->pos(); // TODO: Check if this works(was contentsToViewport).
+	ConfigItem* item = (ConfigItem*)itemAt(p);
+	struct menu *menu;
+	enum prop_type ptype;
+
+	if (!item)
+		goto skip;
+	if (item->goParent) {
+		emit parentSelected();
+		goto skip;
+	}
+	menu = item->menu;
+	if (!menu)
+		goto skip;
+	ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+	if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
+		emit menuSelected(menu);
+	else if (menu->sym)
+		changeValue(item);
+
+skip:
+	//printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
+	Parent::mouseDoubleClickEvent(e);
 }
 
 void ConfigList::focusInEvent(QFocusEvent *e)
 {
+	struct menu *menu = NULL;
+
+	Parent::focusInEvent(e);
+
+	ConfigItem* item = (ConfigItem *)currentItem();
+	if (item) {
+		item->setSelected(true);
+		menu = item->menu;
+	}
+	emit gotFocus(menu);
 }
 
 void ConfigList::contextMenuEvent(QContextMenuEvent *e)
 {
+	if (e->y() <= header()->geometry().bottom()) {
+		if (!headerPopup) {
+			QAction *action;
+
+			headerPopup = new QMenu(this);
+			action = new QAction(_("Show Name"), this);
+			  action->setCheckable(true);
+			  connect(action, SIGNAL(toggled(bool)),
+				  parent(), SLOT(setShowName(bool)));
+			  connect(parent(), SIGNAL(showNameChanged(bool)),
+				  action, SLOT(setOn(bool)));
+			  action->setChecked(showName);
+			  headerPopup->addAction(action);
+			action = new QAction(_("Show Range"), this);
+			  action->setCheckable(true);
+			  connect(action, SIGNAL(toggled(bool)),
+				  parent(), SLOT(setShowRange(bool)));
+			  connect(parent(), SIGNAL(showRangeChanged(bool)),
+				  action, SLOT(setOn(bool)));
+			  action->setChecked(showRange);
+			  headerPopup->addAction(action);
+			action = new QAction(_("Show Data"), this);
+			  action->setCheckable(true);
+			  connect(action, SIGNAL(toggled(bool)),
+				  parent(), SLOT(setShowData(bool)));
+			  connect(parent(), SIGNAL(showDataChanged(bool)),
+				  action, SLOT(setOn(bool)));
+			  action->setChecked(showData);
+			  headerPopup->addAction(action);
+		}
+		headerPopup->exec(e->globalPos());
+		e->accept();
+	} else
+		e->ignore();
 }
 
 ConfigView*ConfigView::viewList;
@@ -276,33 +850,78 @@  ConfigView::~ConfigView(void)
 
 void ConfigView::setOptionMode(QAction *act)
 {
+	if (act == showNormalAction)
+		list->optMode = normalOpt;
+	else if (act == showAllAction)
+		list->optMode = allOpt;
+	else
+		list->optMode = promptOpt;
+
+	list->updateListAll();
 }
 
 void ConfigView::setShowName(bool b)
 {
+	if (list->showName != b) {
+		list->showName = b;
+		list->reinit();
+		emit showNameChanged(b);
+	}
 }
 
 void ConfigView::setShowRange(bool b)
 {
+	if (list->showRange != b) {
+		list->showRange = b;
+		list->reinit();
+		emit showRangeChanged(b);
+	}
 }
 
 void ConfigView::setShowData(bool b)
 {
+	if (list->showData != b) {
+		list->showData = b;
+		list->reinit();
+		emit showDataChanged(b);
+	}
+}
+
+void ConfigList::setAllOpen(bool open)
+{
+	QTreeWidgetItemIterator it(this);
+
+	while (*it) {
+		(*it)->setExpanded(open);
+
+		++it;
+	}
 }
 
 void ConfigView::updateList(ConfigItem* item)
 {
+	ConfigView* v;
+
+	for (v = viewList; v; v = v->nextView)
+		v->list->updateList(item);
 }
 
 void ConfigView::updateListAll(void)
 {
+	ConfigView* v;
+
+	for (v = viewList; v; v = v->nextView)
+		v->list->updateListAll();
 }
 
 ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
 	: Parent(parent), sym(0), _menu(0)
 {
-	if (name) {
-		configSettings->beginGroup(name);
+	setObjectName(name);
+
+
+	if (!objectName().isEmpty()) {
+		configSettings->beginGroup(objectName());
 		_showDebug = configSettings->value("/showDebug", false).toBool();
 		configSettings->endGroup();
 		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
@@ -311,6 +930,11 @@  ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
 
 void ConfigInfoView::saveSettings(void)
 {
+	if (!objectName().isEmpty()) {
+		configSettings->beginGroup(objectName());
+		configSettings->setValue("/showDebug", showDebug());
+		configSettings->endGroup();
+	}
 }
 
 void ConfigInfoView::setShowDebug(bool b)
@@ -528,6 +1152,7 @@  void ConfigInfoView::contextMenuEvent(QContextMenuEvent *e)
 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
 	: Parent(parent), result(NULL)
 {
+	setObjectName(name);
 	setWindowTitle("Search Config");
 
 	QVBoxLayout* layout1 = new QVBoxLayout(this);
@@ -549,6 +1174,7 @@  ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
 	split = new QSplitter(this);
 	split->setOrientation(Qt::Vertical);
 	list = new ConfigView(split, name);
+	list->list->mode = listMode;
 	info = new ConfigInfoView(split, name);
 	connect(list->list, SIGNAL(menuChanged(struct menu *)),
 		info, SLOT(setInfo(struct menu *)));
@@ -580,10 +1206,35 @@  ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
 
 void ConfigSearchWindow::saveSettings(void)
 {
+	if (!objectName().isEmpty()) {
+		configSettings->beginGroup(objectName());
+		configSettings->setValue("/window x", pos().x());
+		configSettings->setValue("/window y", pos().y());
+		configSettings->setValue("/window width", size().width());
+		configSettings->setValue("/window height", size().height());
+		configSettings->writeSizes("/split", split->sizes());
+		configSettings->endGroup();
+	}
 }
 
 void ConfigSearchWindow::search(void)
 {
+	struct symbol **p;
+	struct property *prop;
+	ConfigItem *lastItem = NULL;
+
+	free(result);
+	list->list->clear();
+	info->clear();
+
+	result = sym_re_search(editField->text().toLatin1());
+	if (!result)
+		return;
+	for (p = result; *p; p++) {
+		for_all_prompts((*p), prop)
+			lastItem = new ConfigItem(list->list, lastItem, prop->menu,
+						  menu_is_visible(prop->menu));
+	}
 }
 
 /*
@@ -739,6 +1390,23 @@  ConfigMainWindow::ConfigMainWindow(void)
 	helpMenu->addAction(showIntroAction);
 	helpMenu->addAction(showAboutAction);
 
+	connect(configList, SIGNAL(menuChanged(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(configList, SIGNAL(menuSelected(struct menu *)),
+		SLOT(changeMenu(struct menu *)));
+	connect(configList, SIGNAL(parentSelected()),
+		SLOT(goBack()));
+	connect(menuList, SIGNAL(menuChanged(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(menuList, SIGNAL(menuSelected(struct menu *)),
+		SLOT(changeMenu(struct menu *)));
+
+	connect(configList, SIGNAL(gotFocus(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(menuList, SIGNAL(gotFocus(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(menuList, SIGNAL(gotFocus(struct menu *)),
+		SLOT(listFocusChanged(void)));
 	connect(helpText, SIGNAL(menuSelected(struct menu *)),
 		SLOT(setMenuLink(struct menu *)));
 
@@ -796,19 +1464,86 @@  void ConfigMainWindow::searchConfig(void)
 
 void ConfigMainWindow::changeMenu(struct menu *menu)
 {
-
+	configList->setRootMenu(menu);
+	if (configList->rootEntry->parent == &rootmenu)
+		backAction->setEnabled(false);
+	else
+		backAction->setEnabled(true);
 }
 
 void ConfigMainWindow::setMenuLink(struct menu *menu)
 {
+	struct menu *parent;
+	ConfigList* list = NULL;
+	ConfigItem* item;
+
+	if (configList->menuSkip(menu))
+		return;
+
+	switch (configList->mode) {
+	case singleMode:
+		list = configList;
+		parent = menu_get_parent_menu(menu);
+		if (!parent)
+			return;
+		list->setRootMenu(parent);
+		break;
+	case symbolMode:
+		if (menu->flags & MENU_ROOT) {
+			configList->setRootMenu(menu);
+			configList->clearSelection();
+			list = menuList;
+		} else {
+			list = configList;
+			parent = menu_get_parent_menu(menu->parent);
+			if (!parent)
+				return;
+			item = menuList->findConfigItem(parent);
+			if (item) {
+				item->setSelected(true);
+				menuList->scrollToItem(item);
+			}
+			list->setRootMenu(parent);
+		}
+		break;
+	case fullMode:
+		list = configList;
+		break;
+	default:
+		break;
+	}
+
+	if (list) {
+		item = list->findConfigItem(menu);
+		if (item) {
+			item->setSelected(true);
+			list->scrollToItem(item);
+			list->setFocus();
+		}
+	}
 }
 
 void ConfigMainWindow::listFocusChanged(void)
 {
+	if (menuList->mode == menuMode)
+		configList->clearSelection();
 }
 
 void ConfigMainWindow::goBack(void)
 {
+	ConfigItem* item;
+
+	configList->setParentMenu();
+	if (configList->rootEntry == &rootmenu)
+		backAction->setEnabled(false);
+	item = (ConfigItem*)menuList->selectedItems().first();
+	while (item) {
+		if (item->menu == configList->rootEntry) {
+			item->setSelected(true);
+			break;
+		}
+		item = (ConfigItem*)item->parent();
+	}
 }
 
 void ConfigMainWindow::showSingleView(void)
@@ -821,6 +1556,12 @@  void ConfigMainWindow::showSingleView(void)
 	fullViewAction->setChecked(false);
 
 	menuView->hide();
+	menuList->setRootMenu(0);
+	configList->mode = singleMode;
+	if (configList->rootEntry == &rootmenu)
+		configList->updateListAll();
+	else
+		configList->setRootMenu(&rootmenu);
 	configList->setFocus();
 }
 
@@ -833,6 +1574,16 @@  void ConfigMainWindow::showSplitView(void)
 	fullViewAction->setEnabled(true);
 	fullViewAction->setChecked(false);
 
+	configList->mode = symbolMode;
+	if (configList->rootEntry == &rootmenu)
+		configList->updateListAll();
+	else
+		configList->setRootMenu(&rootmenu);
+	configList->setAllOpen(true);
+	configApp->processEvents();
+	menuList->mode = menuMode;
+	menuList->setRootMenu(&rootmenu);
+	menuList->setAllOpen(true);
 	menuView->show();
 	menuList->setFocus();
 }
@@ -847,6 +1598,12 @@  void ConfigMainWindow::showFullView(void)
 	fullViewAction->setChecked(true);
 
 	menuView->hide();
+	menuList->setRootMenu(0);
+	configList->mode = fullMode;
+	if (configList->rootEntry == &rootmenu)
+		configList->updateListAll();
+	else
+		configList->setRootMenu(&rootmenu);
 	configList->setFocus();
 }
 
@@ -914,7 +1671,22 @@  void ConfigMainWindow::saveSettings(void)
 	configSettings->setValue("/window height", size().height());
 
 	QString entry;
+	switch(configList->mode) {
+	case singleMode :
+		entry = "single";
+		break;
+
+	case symbolMode :
+		entry = "split";
+		break;
+
+	case fullMode :
+		entry = "full";
+		break;
 
+	default:
+		break;
+	}
 	configSettings->setValue("/listMode", entry);
 
 	configSettings->writeSizes("/split1", split1->sizes());