Fixed toggle switch painting, part I

This commit is contained in:
2026-03-30 21:24:29 +02:00
parent 842129931f
commit b40f3cbd14
6 changed files with 72 additions and 50 deletions

View File

@@ -82,6 +82,9 @@ void BCToggleSwitch::paintEvent(QPaintEvent *)
QPainter p(this); QPainter p(this);
p.setRenderHint(QPainter::Antialiasing); p.setRenderHint(QPainter::Antialiasing);
// Option A: Nutze die Standard-Hintergrundfarbe des aktuellen Qt-Themes
p.fillRect(rect(), palette().window());
// --- Farben --- // --- Farben ---
// Tipp: In einem echten Projekt diese Farben als const statics // Tipp: In einem echten Projekt diese Farben als const statics
// oder aus der QPalette laden. // oder aus der QPalette laden.

View File

@@ -64,6 +64,11 @@ bool BCValue::isReadOnly() const
return _valueFlags.testFlag(BCValue::Flag::ReadOnly); return _valueFlags.testFlag(BCValue::Flag::ReadOnly);
} }
bool BCValue::isBoolean() const
{
return valueType() == BCValue::ValueType::Bool;
}
bool BCValue::testFlag( BCValue::Flag flag ) const bool BCValue::testFlag( BCValue::Flag flag ) const
{ {
return _valueFlags.testFlag( flag ); return _valueFlags.testFlag( flag );
@@ -207,7 +212,7 @@ double BCValue::calcMinMaxRatio() const
} }
bool BCValue::valuesForSlider(ValueRange& valueRange) const bool BCValue::hasValuesForSlider(ValueRange& valueRange) const
{ {
valueRange.value = valueRange.min = valueRange.max = 0; valueRange.value = valueRange.min = valueRange.max = 0;

View File

@@ -119,6 +119,7 @@ public:
void dumpValue() const; void dumpValue() const;
bool isWord() const; bool isWord() const;
bool isReadOnly() const; bool isReadOnly() const;
bool isBoolean() const;
bool testFlag( Flag flag ) const; bool testFlag( Flag flag ) const;
void setFlag( Flag flag, bool state=true ) const; void setFlag( Flag flag, bool state=true ) const;
@@ -137,7 +138,7 @@ public:
QString label() const; QString label() const;
QString unitLabel() const; QString unitLabel() const;
bool valuesForSlider( ValueRange& valueRange ) const; bool hasValuesForSlider( ValueRange& valueRange ) const;
QString toString() const; QString toString() const;

View File

@@ -45,7 +45,7 @@
#include <bcdeviceview.h> #include <bcdeviceview.h>
#include <bcvaluedelegate.h> #include <bcvaluedelegate.h>
#include <bcvalueslider.h> #include <bcvalueslider.h>
#include <bctoggleswitch.h>
BCValueDelegate::BCValueDelegate(const BCValueList& valueList, BCDeviceView* view) BCValueDelegate::BCValueDelegate(const BCValueList& valueList, BCDeviceView* view)
: QStyledItemDelegate{view}, _valueList{valueList}, _view{view} : QStyledItemDelegate{view}, _valueList{valueList}, _view{view}
@@ -62,32 +62,39 @@ QWidget* BCValueDelegate::createEditor(QWidget *parent, const QStyleOptionViewIt
const BCValue& bcValue = *(_valueList[ index.row() ].get()); const BCValue& bcValue = *(_valueList[ index.row() ].get());
//qDebug() << " --- Create Editor: " << bcValue.label() << " value: " << params.value << " min: " << params.min << " max: " << params.max << " ratio:" << bcValue.calcMinMaxRatio()*100.0 << '%';
if( bcValue.isBoolean() )
{
auto* toogleSwitch = new BCToggleSwitch{parent};
return toogleSwitch;
}
BCValue::ValueRange params; BCValue::ValueRange params;
bool hasData = bcValue.valuesForSlider( params ); bool hasData = bcValue.hasValuesForSlider( params );
if( !hasData ) if( !hasData )
return nullptr; return nullptr;
qDebug() << " --- Create Editor: " << bcValue.label() << " value: " << params.value << " min: " << params.min << " max: " << params.max << " ratio:" << bcValue.calcMinMaxRatio()*100.0 << '%'; auto* valueSlider = new BCValueSlider{parent};
valueSlider->setValueAndRange( params );
auto* valueEditor = new BCValueSlider(parent);
valueEditor->setValueAndRange( params );
// Signal für sofortige Updates // Signal für sofortige Updates
connect(valueEditor, &BCValueSlider::valueChanged, this, [this, valueEditor]() connect(valueSlider, &BCValueSlider::valueChanged, this, [this, valueSlider]()
{ {
// Commit data sofort bei Änderung // Commit data sofort bei Änderung
emit const_cast<BCValueDelegate*>(this)->commitData(valueEditor); emit const_cast<BCValueDelegate*>(this)->commitData(valueSlider);
}); });
// Signal für sofortige Updates // Signal für sofortige Updates
connect(valueEditor, &BCValueSlider::valueCommited, this, [this, valueEditor](int newValue) connect(valueSlider, &BCValueSlider::valueCommited, this, [this, valueSlider](int newValue)
{ {
qDebug() << " --- value set:" << newValue; qDebug() << " --- value set:" << newValue;
// Commit data sofort bei Änderung // Commit data sofort bei Änderung
//emit const_cast<BCValueDelegate*>(this)->commitData(valueEditor); emit const_cast<BCValueDelegate*>(this)->commitData(valueSlider);
}); });
return valueEditor; return valueSlider;
} }
void BCValueDelegate::setEditorData(QWidget *editor, const QModelIndex& index) const void BCValueDelegate::setEditorData(QWidget *editor, const QModelIndex& index) const
@@ -99,15 +106,26 @@ void BCValueDelegate::setEditorData(QWidget *editor, const QModelIndex& index) c
} }
void BCValueDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const void BCValueDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{ {
Q_UNUSED(index) Q_UNUSED(index)
QRect sliderRect = clipToSliderRect( option.rect ); const BCValue& bcValue = *(_valueList[ index.row()].get());
editor->setGeometry(sliderRect); // Slider nur über Progress Bar QRect editorRect;
qDebug() << " --- Hier: " << sliderRect; if( !bcValue.isBoolean())
//return QStyledItemDelegate::updateEditorGeometry(editor,option,index); {
editorRect = clipToSliderRect( option.rect );
} }
else
{
editorRect = option.rect.adjusted(2,4,0,0);
}
editor->setGeometry(editorRect);
}
void BCValueDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const void BCValueDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const
{ {
if( index.column() == 1) if( index.column() == 1)
@@ -129,36 +147,38 @@ void BCValueDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, c
void BCValueDelegate::paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const void BCValueDelegate::paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{ {
int row = index.row(); int row = index.row();
if( index.column() != 1 || row<0 || row >= _valueList.size() )
if( index.column() != 1 )
return;
if( row<0 || row >= _valueList.size() )
return; return;
QStyleOptionViewItem opt = option; QStyleOptionViewItem opt = option;
initStyleOption(&opt, index); initStyleOption(&opt, index);
const BCValue& bcValue = *(_valueList[ index.row()].get()); const BCValue& bcValue = *(_valueList[ index.row()].get());
//qDebug() << " --- RO?: " << bcValue.label() << " Ro: " << bcValue.isReadOnly() << " Bool: " << bcValue.isBoolean() << ": " << index.flags();
if( bcValue.isBoolean() )
if( bcValue.valueType() == BCValue::ValueType::Bool )
{ {
opt.text = bcValue.rawValue() == 1 ? "Yes" : "No"; paintBooleanValue( painter, opt, bcValue );
//opt.text = bcValue.rawValue() == 1 ? "Yes" : "No";
//painter->drawText( opt.rect, bcValue.rawValue() == 1 ? "Yes" : "No" );
} }
else
{
// Standard-Zeichnen (Text, Hintergrund, Selection) durchführen // Standard-Zeichnen (Text, Hintergrund, Selection) durchführen
QStyledItemDelegate::paint(painter, opt, index); QStyledItemDelegate::paint(painter, opt, index);
}
if( !bcValue.isReadOnly() ) if( !bcValue.isReadOnly() )
{ {
// Wir zeichnen boolean Values an toggle switches // Wir zeichnen boolean Values an toggle switches
if( bcValue.valueType() == BCValue::ValueType::Bool ) if( bcValue.isBoolean() )
paintPlainToggleSwitch(painter, opt, bcValue); paintPlainToggleSwitch(painter, opt, bcValue);
else else
paintPlainSliderIndicator(painter, opt.rect, bcValue.calcMinMaxRatio() ); paintPlainSliderIndicator(painter, opt.rect, bcValue.calcMinMaxRatio() );
} }
if(_rowOpacities.contains(row)) if(_rowOpacities.contains(row))
paintHighlightRow(painter, opt,index.row()); paintHighlightRow(painter, opt,index.row());
@@ -166,19 +186,11 @@ void BCValueDelegate::paint(QPainter *painter, const QStyleOptionViewItem& optio
void BCValueDelegate::paintBooleanValue( QPainter *painter, const QStyleOptionViewItem& option, const BCValue& bcValue ) const void BCValueDelegate::paintBooleanValue( QPainter *painter, const QStyleOptionViewItem& option, const BCValue& bcValue ) const
{ {
/*
* // 1. Den anzuzeigenden Text aus dem Model holen
QString text = index.data(Qt::DisplayRole).toString();
// Wenn du vorher z. B. '0' oder '1' durch "Aktiv" oder "Inaktiv" ersetzen willst, QRect textRect = option.rect.adjusted( 2,0,0,0);
// könntest du das hier tun:
// text = index.data(Qt::DisplayRole).toBool() ? "Aktiv" : "Inaktiv";
// 2. Das Rechteck für den Text berechnen // 3. Den tatsächlichen Wert aus dem Model auslesen
// Wir nehmen das gesamte Rechteck der Zelle und schneiden links Platz für die Checkbox ab. QString text = bcValue.rawValue() == 1 ? "Yes" : "No";
// Angenommen, Checkbox + linkes Padding benötigen ca. 30 Pixel:
QRect textRect = option.rect;
textRect.setLeft(textRect.left() + 30);
// 3. Die korrekte Textfarbe ermitteln (extrem wichtig für die UX!) // 3. Die korrekte Textfarbe ermitteln (extrem wichtig für die UX!)
// Wenn die Zeile markiert ist (Selected), muss der Text meist weiß sein, // Wenn die Zeile markiert ist (Selected), muss der Text meist weiß sein,
@@ -197,7 +209,8 @@ QApplication::style()->drawItemText(
text, // Der zu zeichnende String text, // Der zu zeichnende String
textRole // Die ermittelte Farb-Rolle textRole // Die ermittelte Farb-Rolle
); );
*/ return;
/*
// 1. Standard-Optionen für die Zelle holen // 1. Standard-Optionen für die Zelle holen
QStyleOptionViewItem opt = option; QStyleOptionViewItem opt = option;
//initStyleOption(&opt, index); //initStyleOption(&opt, index);
@@ -209,8 +222,6 @@ QApplication::style()->drawItemText(
// Wir übergeben nullptr für das Widget, da QStyledItemDelegate ohnehin unabhängig zeichnet // Wir übergeben nullptr für das Widget, da QStyledItemDelegate ohnehin unabhängig zeichnet
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, nullptr); QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, nullptr);
// 3. Den tatsächlichen Wert aus dem Model auslesen
bool isChecked = bcValue.rawValue() == 1;
// 4. Optionen für die Checkbox konfigurieren // 4. Optionen für die Checkbox konfigurieren
QStyleOptionButton cbOpt; QStyleOptionButton cbOpt;
@@ -226,6 +237,7 @@ QApplication::style()->drawItemText(
// 6. Die native Checkbox zeichnen // 6. Die native Checkbox zeichnen
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &cbOpt, painter, nullptr); QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &cbOpt, painter, nullptr);
*/
} }
QRect BCValueDelegate::clipToSliderRect( const QRect& rect, int buttonOffset ) const QRect BCValueDelegate::clipToSliderRect( const QRect& rect, int buttonOffset ) const

View File

@@ -168,6 +168,7 @@ Qt::ItemFlags BCValueModel::flags(const QModelIndex& index) const
if( row>-1 && row<_valueList.size() ) if( row>-1 && row<_valueList.size() )
{ {
const BCValue& bcValue = *_valueList[row].get(); const BCValue& bcValue = *_valueList[row].get();
//qDebug() << " --- flags: " << bcValue.label() << " Ro: " << bcValue.isReadOnly() << " Bool: " << bcValue.isBoolean();
flag = bcValue.isReadOnly() ? flag : flag|Qt::ItemIsEditable|Qt::ItemIsEnabled; flag = bcValue.isReadOnly() ? flag : flag|Qt::ItemIsEditable|Qt::ItemIsEnabled;
} }
return flag; return flag;