lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sat, 29 Aug 2020 17:14:12 +0900
From:   Masahiro Yamada <masahiroy@...nel.org>
To:     linux-kbuild@...r.kernel.org
Cc:     Randy Dunlap <rdunlap@...radead.org>,
        Mauro Carvalho Chehab <mchehab@...nel.org>,
        Masahiro Yamada <masahiroy@...nel.org>,
        linux-kernel@...r.kernel.org
Subject: [PATCH 06/11] kconfig: qconf: allow to edit "int", "hex", "string" menus in-place

Previously, when you double-clicked the "int", "hex", or "string" menus,
a line-edit gadget showed up to allow you to input the value, which
looked clumsy.

Also, it was buggy; the editor opened even if the config option was not
editable. For example, just try to double-click CC_VERSION_TEXT, which
has no prompt.

This commit sub-classes QStyleItemDelegate to allow users to edit
"int", "hex", "string" menus in-place. Just double-click (or press
the F2 key) in the data column. Then, an editor widget is placed on
top of the item view.

The two methods are overridden:

 createEditor - process only when the data column is being accessed
 and the menu is visible. Otherwise, return nullptr to disallow editing.

 setModelData - take the new data from the editor, and set it to the
 addressed symbol. If it was successful, update all the list windows.
 Otherwise, (the reason for the failure is possibly the input data was
 out of range), set the old value back to the editor.

Signed-off-by: Masahiro Yamada <masahiroy@...nel.org>
---

 scripts/kconfig/qconf.cc | 93 ++++++++++++++++++++++++++++++++--------
 scripts/kconfig/qconf.h  | 15 +++++++
 2 files changed, 91 insertions(+), 17 deletions(-)

diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index c48e48a3735f..d592f05363c9 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -180,15 +180,7 @@ void ConfigItem::updateMenu(void)
 	case S_INT:
 	case S_HEX:
 	case S_STRING:
-		const char* data;
-
-		data = sym_get_string_value(sym);
-
-		setText(dataColIdx, data);
-		if (type == S_STRING)
-			prompt = QString("%1: %2").arg(prompt).arg(data);
-		else
-			prompt = QString("(%2) %1").arg(prompt).arg(data);
+		setText(dataColIdx, sym_get_string_value(sym));
 		break;
 	}
 	if (!sym_has_value(sym) && visible)
@@ -229,6 +221,17 @@ void ConfigItem::init(void)
 		if (list->mode != fullMode)
 			setExpanded(true);
 		sym_calc_value(menu->sym);
+
+		if (menu->sym) {
+			enum symbol_type type = menu->sym->type;
+
+			// Allow to edit "int", "hex", and "string" in-place in
+			// the data column. Unfortunately, you cannot specify
+			// the flags per column. Set ItemIsEditable for all
+			// columns here, and check the column in createEditor().
+			if (type == S_INT || type == S_HEX || type == S_STRING)
+				setFlags(flags() | Qt::ItemIsEditable);
+		}
 	}
 	updateMenu();
 }
@@ -249,6 +252,61 @@ ConfigItem::~ConfigItem(void)
 	}
 }
 
+QWidget *ConfigItemDelegate::createEditor(QWidget *parent,
+					  const QStyleOptionViewItem &option,
+					  const QModelIndex &index) const
+{
+	ConfigItem *item;
+
+	// Only the data column is editable
+	if (index.column() != dataColIdx)
+		return nullptr;
+
+	// You cannot edit invisible menus
+	item = static_cast<ConfigItem *>(index.internalPointer());
+	if (!item || !item->menu || !menu_is_visible(item->menu))
+		return nullptr;
+
+	return QStyledItemDelegate::createEditor(parent, option, index);
+}
+
+void ConfigItemDelegate::setModelData(QWidget *editor,
+				      QAbstractItemModel *model,
+				      const QModelIndex &index) const
+{
+	QLineEdit *lineEdit;
+	ConfigItem *item;
+	struct symbol *sym;
+	bool success;
+
+	lineEdit = qobject_cast<QLineEdit *>(editor);
+	// If this is not a QLineEdit, use the parent's default.
+	// (does this happen?)
+	if (!lineEdit)
+		goto parent;
+
+	item = static_cast<ConfigItem *>(index.internalPointer());
+	if (!item || !item->menu)
+		goto parent;
+
+	sym = item->menu->sym;
+	if (!sym)
+		goto parent;
+
+	success = sym_set_string_value(sym, lineEdit->text().toUtf8().data());
+	if (success) {
+		ConfigList::updateListForAll();
+	} else {
+		QMessageBox::information(editor, "qconf",
+			"Cannot set the data (maybe due to out of range).\n"
+			"Setting the old value.");
+		lineEdit->setText(sym_get_string_value(sym));
+	}
+
+parent:
+	QStyledItemDelegate::setModelData(editor, model, index);
+}
+
 ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
 	: Parent(parent)
 {
@@ -314,6 +372,8 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
 
 	showColumn(promptColIdx);
 
+	setItemDelegate(new ConfigItemDelegate(this));
+
 	allLists.append(this);
 
 	reinit();
@@ -534,10 +594,7 @@ void ConfigList::changeValue(ConfigItem* item)
 		if (oldexpr != newexpr)
 			ConfigList::updateListForAll();
 		break;
-	case S_INT:
-	case S_HEX:
-	case S_STRING:
-		parent()->lineEdit->show(item);
+	default:
 		break;
 	}
 }
@@ -1797,10 +1854,12 @@ void ConfigMainWindow::showIntro(void)
 	static const QString str =
 		"Welcome to the qconf graphical configuration tool.\n\n"
 
-		"For each option, a blank box indicates the feature is "
-		"disabled, a check indicates it is enabled, and a dot "
-		"indicates that it is to be compiled as a module. Clicking on "
-		"the box will cycle through the three states.\n\n"
+		"For bool and tristate options, a blank box indicates the "
+		"feature is disabled, a check indicates it is enabled, and a "
+		"dot indicates that it is to be compiled as a module. Clicking "
+		"on the box will cycle through the three states. For int, hex, "
+		"and string options, double-clicking or pressing F2 on the "
+		"Value cell will allow you to edit the value.\n\n"
 
 		"If you do not see an option (e.g., a device driver) that you "
 		"believe should be present, try turning on Show All Options "
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index d01a6c620dbb..b02acf2464ec 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -11,6 +11,7 @@
 #include <QPushButton>
 #include <QSettings>
 #include <QSplitter>
+#include <QStyledItemDelegate>
 #include <QTextBrowser>
 #include <QTreeWidget>
 
@@ -172,6 +173,20 @@ class ConfigItem : public QTreeWidgetItem {
 	static QIcon menuIcon, menubackIcon;
 };
 
+class ConfigItemDelegate : public QStyledItemDelegate
+{
+private:
+	struct menu *menu;
+public:
+	ConfigItemDelegate(QObject *parent = nullptr)
+		: QStyledItemDelegate(parent) {}
+	QWidget *createEditor(QWidget *parent,
+			      const QStyleOptionViewItem &option,
+			      const QModelIndex &index) const override;
+	void setModelData(QWidget *editor, QAbstractItemModel *model,
+			  const QModelIndex &index) const override;
+};
+
 class ConfigLineEdit : public QLineEdit {
 	Q_OBJECT
 	typedef class QLineEdit Parent;
-- 
2.25.1

Powered by blists - more mailing lists