Gui: Property editor use a checkbox instead of a combobox for booleans (#21555)

* Gui: property-editor add property copy context menu

* Gui: Property editor checkbox brighter border

* Gui: Property editor refactor optimize

* Gui: Property editor checkbox react to first click and add label

* Gui: Property editor remove auto-inserted include

* Gui: property-checkbox fix not painting the grid
This commit is contained in:
Alfredo Monclus
2025-06-03 13:05:30 -06:00
committed by GitHub
parent 324f610782
commit 9fabeae75c
2 changed files with 66 additions and 14 deletions

View File

@@ -29,6 +29,7 @@
#include <limits>
#include <QApplication>
#include <QComboBox>
#include <QCheckBox>
#include <QFontDatabase>
#include <QLocale>
#include <QMessageBox>
@@ -1376,26 +1377,25 @@ void PropertyBoolItem::setValue(const QVariant& value)
QWidget* PropertyBoolItem::createEditor(QWidget* parent,
const std::function<void()>& method,
FrameOption frameOption) const
FrameOption /*frameOption*/) const
{
auto cb = new QComboBox(parent);
cb->setFrame(static_cast<bool>(frameOption));
cb->addItem(QLatin1String("false"));
cb->addItem(QLatin1String("true"));
QObject::connect(cb, qOverload<int>(&QComboBox::activated), method);
return cb;
auto checkbox = new QCheckBox(parent);
return checkbox;
}
void PropertyBoolItem::setEditorData(QWidget* editor, const QVariant& data) const
{
auto cb = qobject_cast<QComboBox*>(editor);
cb->setCurrentIndex(cb->findText(data.toString()));
if (auto checkbox = qobject_cast<QCheckBox*>(editor)) {
checkbox->setChecked(data.toBool());
}
}
QVariant PropertyBoolItem::editorData(QWidget* editor) const
{
auto cb = qobject_cast<QComboBox*>(editor);
return {cb->currentText()};
if (auto checkbox = qobject_cast<QCheckBox*>(editor)) {
return checkbox->isChecked();
}
return false;
}
// ---------------------------------------------------------------

View File

@@ -25,9 +25,11 @@
#ifndef _PreComp_
# include <QApplication>
# include <QCheckBox>
# include <QComboBox>
# include <QModelIndex>
# include <QPainter>
# include <QTimer>
#endif
#include <Base/Tools.h>
@@ -103,7 +105,44 @@ void PropertyItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
QPen savedPen = painter->pen();
QItemDelegate::paint(painter, option, index);
if (index.column() == 1 && property && dynamic_cast<PropertyBoolItem*>(property)) {
bool checked = index.data(Qt::EditRole).toBool();
QStyleOptionButton checkboxOption;
if (property->isReadOnly()) {
checkboxOption.state |= QStyle::State_ReadOnly;
} else {
checkboxOption.state |= QStyle::State_Enabled;
}
checkboxOption.state |= checked ? QStyle::State_On : QStyle::State_Off;
// Draw the checkbox
checkboxOption.rect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkboxOption);
int leftSpacing = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr);
QRect checkboxRect = QStyle::alignedRect(
option.direction, Qt::AlignVCenter,
checkboxOption.rect.size(),
option.rect.adjusted(leftSpacing, 0, -leftSpacing, 0)
);
checkboxOption.rect = checkboxRect;
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkboxOption, painter);
// Draw a bright border on the checkbox to stand out
QColor borderColor = QApplication::palette().color(QPalette::BrightText);
painter->setPen(borderColor);
painter->drawRect(checkboxOption.rect.adjusted(0, 0, -1, -1));
// Draw the label of the checkbox
QString labelText = checked ? tr("Yes") : tr("No");
int spacing = QApplication::style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, nullptr);
QRect textRect(
checkboxOption.rect.right() + spacing,
checkboxOption.rect.top(),
option.rect.right() - (checkboxOption.rect.right() + spacing),
checkboxOption.rect.height()
);
painter->setPen(option.palette.color(QPalette::Text));
painter->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, labelText);
}
else {
QItemDelegate::paint(painter, option, index);
}
QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt, qobject_cast<QWidget*>(parent())));
painter->setPen(QPen(color));
@@ -136,6 +175,17 @@ bool PropertyItemDelegate::eventFilter(QObject *o, QEvent *ev)
comboBox->showPopup();
}
}
auto *checkBox = qobject_cast<QCheckBox*>(o);
if (checkBox) {
auto parentEditor = qobject_cast<PropertyEditor*>(this->parent());
if (parentEditor && parentEditor->activeEditor == checkBox) {
checkBox->toggle();
// Delay valueChanged to ensure proper recomputation
QTimer::singleShot(0, this, [this]() {
valueChanged();
});
}
}
}
else if (ev->type() == QEvent::FocusOut) {
auto parentEditor = qobject_cast<PropertyEditor*>(this->parent());
@@ -233,9 +283,11 @@ void PropertyItemDelegate::valueChanged()
if (propertyEditor) {
Base::FlagToggler<> flag(changed);
Q_EMIT commitData(propertyEditor);
auto *comboBox = qobject_cast<QComboBox*>(propertyEditor);
if (comboBox) {
if (qobject_cast<QComboBox*>(propertyEditor)
|| qobject_cast<QCheckBox*>(propertyEditor))
{
Q_EMIT closeEditor(propertyEditor);
return;
}
}
}