From b40f3cbd14943494ee732e56a28f05c8e1781400 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 30 Mar 2026 21:24:29 +0200 Subject: [PATCH] Fixed toggle switch painting, part I --- bctoggleswitch.cpp | 3 ++ bcvalue.cpp | 7 ++- bcvalue.h | 3 +- bcvaluedelegate.cpp | 106 +++++++++++++++++++++++------------------ bcvaluemodel.cpp | 1 + resources/bikeinfo.xml | 2 +- 6 files changed, 72 insertions(+), 50 deletions(-) diff --git a/bctoggleswitch.cpp b/bctoggleswitch.cpp index f724cc3..e08410e 100644 --- a/bctoggleswitch.cpp +++ b/bctoggleswitch.cpp @@ -82,6 +82,9 @@ void BCToggleSwitch::paintEvent(QPaintEvent *) QPainter p(this); p.setRenderHint(QPainter::Antialiasing); + // Option A: Nutze die Standard-Hintergrundfarbe des aktuellen Qt-Themes + p.fillRect(rect(), palette().window()); + // --- Farben --- // Tipp: In einem echten Projekt diese Farben als const statics // oder aus der QPalette laden. diff --git a/bcvalue.cpp b/bcvalue.cpp index ac0ec25..7451abe 100644 --- a/bcvalue.cpp +++ b/bcvalue.cpp @@ -64,6 +64,11 @@ bool BCValue::isReadOnly() const return _valueFlags.testFlag(BCValue::Flag::ReadOnly); } +bool BCValue::isBoolean() const +{ + return valueType() == BCValue::ValueType::Bool; +} + bool BCValue::testFlag( BCValue::Flag flag ) const { 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; diff --git a/bcvalue.h b/bcvalue.h index 30045b9..9fcb690 100644 --- a/bcvalue.h +++ b/bcvalue.h @@ -119,6 +119,7 @@ public: void dumpValue() const; bool isWord() const; bool isReadOnly() const; + bool isBoolean() const; bool testFlag( Flag flag ) const; void setFlag( Flag flag, bool state=true ) const; @@ -137,7 +138,7 @@ public: QString label() const; QString unitLabel() const; - bool valuesForSlider( ValueRange& valueRange ) const; + bool hasValuesForSlider( ValueRange& valueRange ) const; QString toString() const; diff --git a/bcvaluedelegate.cpp b/bcvaluedelegate.cpp index 0039f4a..801ba2d 100644 --- a/bcvaluedelegate.cpp +++ b/bcvaluedelegate.cpp @@ -45,7 +45,7 @@ #include #include #include - +#include BCValueDelegate::BCValueDelegate(const BCValueList& valueList, BCDeviceView* view) : QStyledItemDelegate{view}, _valueList{valueList}, _view{view} @@ -60,34 +60,41 @@ QWidget* BCValueDelegate::createEditor(QWidget *parent, const QStyleOptionViewIt Q_UNUSED(option) Q_UNUSED(index) - 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; - bool hasData = bcValue.valuesForSlider( params ); + bool hasData = bcValue.hasValuesForSlider( params ); + if( !hasData ) return nullptr; - qDebug() << " --- Create Editor: " << bcValue.label() << " value: " << params.value << " min: " << params.min << " max: " << params.max << " ratio:" << bcValue.calcMinMaxRatio()*100.0 << '%'; - - auto* valueEditor = new BCValueSlider(parent); - valueEditor->setValueAndRange( params ); - + auto* valueSlider = new BCValueSlider{parent}; + valueSlider->setValueAndRange( params ); // Signal für sofortige Updates - connect(valueEditor, &BCValueSlider::valueChanged, this, [this, valueEditor]() + connect(valueSlider, &BCValueSlider::valueChanged, this, [this, valueSlider]() { // Commit data sofort bei Änderung - emit const_cast(this)->commitData(valueEditor); + emit const_cast(this)->commitData(valueSlider); }); // 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; // Commit data sofort bei Änderung - //emit const_cast(this)->commitData(valueEditor); + emit const_cast(this)->commitData(valueSlider); }); - return valueEditor; + return valueSlider; } 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 { Q_UNUSED(index) - QRect sliderRect = clipToSliderRect( option.rect ); - editor->setGeometry(sliderRect); // Slider nur über Progress Bar - qDebug() << " --- Hier: " << sliderRect; - //return QStyledItemDelegate::updateEditorGeometry(editor,option,index); + const BCValue& bcValue = *(_valueList[ index.row()].get()); + QRect editorRect; + if( !bcValue.isBoolean()) + { + 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 { if( index.column() == 1) @@ -128,37 +146,39 @@ void BCValueDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, c void BCValueDelegate::paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - int row = index.row(); - - if( index.column() != 1 ) - return; - if( row<0 || row >= _valueList.size() ) + int row = index.row(); + if( index.column() != 1 || row<0 || row >= _valueList.size() ) return; QStyleOptionViewItem opt = option; initStyleOption(&opt, index); const BCValue& bcValue = *(_valueList[ index.row()].get()); + //qDebug() << " --- RO?: " << bcValue.label() << " Ro: " << bcValue.isReadOnly() << " Bool: " << bcValue.isBoolean() << ": " << index.flags(); - - if( bcValue.valueType() == BCValue::ValueType::Bool ) + if( bcValue.isBoolean() ) { - 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 + QStyledItemDelegate::paint(painter, opt, index); } - - // Standard-Zeichnen (Text, Hintergrund, Selection) durchführen - QStyledItemDelegate::paint(painter, opt, index); if( !bcValue.isReadOnly() ) { // Wir zeichnen boolean Values an toggle switches - if( bcValue.valueType() == BCValue::ValueType::Bool ) + if( bcValue.isBoolean() ) paintPlainToggleSwitch(painter, opt, bcValue); else paintPlainSliderIndicator(painter, opt.rect, bcValue.calcMinMaxRatio() ); } + if(_rowOpacities.contains(row)) paintHighlightRow(painter, opt,index.row()); @@ -166,29 +186,21 @@ void BCValueDelegate::paint(QPainter *painter, const QStyleOptionViewItem& optio 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, -// könntest du das hier tun: -// text = index.data(Qt::DisplayRole).toBool() ? "Aktiv" : "Inaktiv"; + QRect textRect = option.rect.adjusted( 2,0,0,0); -// 2. Das Rechteck für den Text berechnen -// Wir nehmen das gesamte Rechteck der Zelle und schneiden links Platz für die Checkbox ab. -// Angenommen, Checkbox + linkes Padding benötigen ca. 30 Pixel: -QRect textRect = option.rect; -textRect.setLeft(textRect.left() + 30); + // 3. Den tatsächlichen Wert aus dem Model auslesen + QString text = bcValue.rawValue() == 1 ? "Yes" : "No"; // 3. Die korrekte Textfarbe ermitteln (extrem wichtig für die UX!) // Wenn die Zeile markiert ist (Selected), muss der Text meist weiß sein, // ansonsten schwarz (oder je nach System-Theme). -QPalette::ColorRole textRole = (option.state & QStyle::State_Selected) + QPalette::ColorRole textRole = (option.state & QStyle::State_Selected) ? QPalette::HighlightedText : QPalette::Text; // 4. Den Text nativ durch den Style zeichnen lassen -QApplication::style()->drawItemText( + QApplication::style()->drawItemText( painter, textRect, Qt::AlignLeft | Qt::AlignVCenter, // Ausrichtung innerhalb von textRect @@ -196,8 +208,9 @@ QApplication::style()->drawItemText( option.state & QStyle::State_Enabled, // Prüfen, ob die Zelle klickbar/aktiv ist text, // Der zu zeichnende String textRole // Die ermittelte Farb-Rolle -); - */ + ); + return; +/* // 1. Standard-Optionen für die Zelle holen QStyleOptionViewItem opt = option; //initStyleOption(&opt, index); @@ -209,8 +222,6 @@ QApplication::style()->drawItemText( // Wir übergeben nullptr für das Widget, da QStyledItemDelegate ohnehin unabhängig zeichnet 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 QStyleOptionButton cbOpt; @@ -226,6 +237,7 @@ QApplication::style()->drawItemText( // 6. Die native Checkbox zeichnen QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &cbOpt, painter, nullptr); +*/ } QRect BCValueDelegate::clipToSliderRect( const QRect& rect, int buttonOffset ) const @@ -234,7 +246,7 @@ QRect BCValueDelegate::clipToSliderRect( const QRect& rect, int buttonOffset ) c ( rect.width() - cTextBlockOffset, // Von rechts: cTextBlockOffset (==130) px (Breite der Progress Bar) 0, // Oben: kein Offset - -buttonOffset, // Rechts: 8px Padding + -buttonOffset, // Rechts: 8px Padding 0 // Unten: kein Offset ); } diff --git a/bcvaluemodel.cpp b/bcvaluemodel.cpp index 7b184e2..d984700 100644 --- a/bcvaluemodel.cpp +++ b/bcvaluemodel.cpp @@ -168,6 +168,7 @@ Qt::ItemFlags BCValueModel::flags(const QModelIndex& index) const if( row>-1 && row<_valueList.size() ) { 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; } return flag; diff --git a/resources/bikeinfo.xml b/resources/bikeinfo.xml index e2631ef..e9e1618 100644 --- a/resources/bikeinfo.xml +++ b/resources/bikeinfo.xml @@ -34,7 +34,7 @@ - +