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@kernel.org>
This commit is contained in:
Masahiro Yamada 2020-08-29 17:14:12 +09:00
parent 669a1ee46a
commit 37162a68bf
2 changed files with 91 additions and 17 deletions

View File

@ -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;
}
}
@ -1802,10 +1859,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"
"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 "

View File

@ -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;