#ifndef SLIDERDELEGATE_H #define SLIDERDELEGATE_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Custom Delegate für QSlider in Spalte 3 // Fluent Design Slider Style class FluentSliderStyle : public QProxyStyle { public: FluentSliderStyle() : QProxyStyle() {} // Wichtig: Genug Platz für Handle reservieren int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override { switch (metric) { case PM_SliderThickness: return 32; // Höhe für horizontalen Slider case PM_SliderLength: return 20; // Handle-Größe case PM_SliderControlThickness: return 20; case PM_SliderSpaceAvailable: if (option) { if (const QStyleOptionSlider* sliderOpt = qstyleoption_cast(option)) { if (sliderOpt->orientation == Qt::Horizontal) { return sliderOpt->rect.width() - 20; } else { return sliderOpt->rect.height() - 20; } } } return QProxyStyle::pixelMetric(metric, option, widget); default: return QProxyStyle::pixelMetric(metric, option, widget); } } QRect subControlRect(ComplexControl cc, const QStyleOptionComplex* opt,SubControl sc, const QWidget* widget) const override { if (cc == CC_Slider) { if (const QStyleOptionSlider* slider = qstyleoption_cast(opt)) { QRect rect = slider->rect; int handleSize = 20; if (sc == SC_SliderHandle) { // Handle Position korrekt berechnen if (slider->orientation == Qt::Horizontal) { int range = slider->maximum - slider->minimum; int pos = slider->sliderPosition - slider->minimum; int pixelRange = rect.width() - handleSize; int pixelPos = (range != 0) ? (pos * pixelRange) / range : 0; return QRect(rect.x() + pixelPos, rect.center().y() - handleSize / 2, handleSize, handleSize); } else { int range = slider->maximum - slider->minimum; int pos = slider->sliderPosition - slider->minimum; int pixelRange = rect.height() - handleSize; int pixelPos = (range != 0) ? (pos * pixelRange) / range : 0; return QRect(rect.center().x() - handleSize / 2, rect.bottom() - pixelPos - handleSize, handleSize, handleSize); } } } } return QProxyStyle::subControlRect(cc, opt, sc, widget); } void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const override { if (control == CC_Slider) { if (const QStyleOptionSlider* slider = qstyleoption_cast(option)) { painter->setRenderHint(QPainter::Antialiasing); // Fluent Colors QColor accentColor(0, 120, 212); // #0078D4 QColor inactiveColor(138, 136, 134); // #8A8886 QColor bgColor(255, 255, 255); // White background if (slider->orientation == Qt::Horizontal) { drawHorizontalFluentSlider(painter, slider, accentColor, inactiveColor, bgColor); } else { drawVerticalFluentSlider(painter, slider, accentColor, inactiveColor, bgColor); } return; } } QProxyStyle::drawComplexControl(control, option, painter, widget); } private: void drawHorizontalFluentSlider(QPainter* painter, const QStyleOptionSlider* slider, const QColor& activeColor, const QColor& inactiveColor, const QColor& bgColor) const { QRect groove = slider->rect; QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, nullptr); int grooveHeight = 4; // Track sollte im Widget-Zentrum sein, nicht im groove-Zentrum int grooveY = slider->rect.center().y() - grooveHeight / 2; // Full background track QRect fullTrack(groove.left(), grooveY, groove.width(), grooveHeight); painter->setPen(Qt::NoPen); painter->setBrush(inactiveColor.lighter(150)); painter->drawRoundedRect(fullTrack, grooveHeight / 2, grooveHeight / 2); // Active track (filled portion) int activeWidth = handle.center().x() - groove.left(); QRect activeTrack(groove.left(), grooveY, activeWidth, grooveHeight); painter->setBrush(activeColor); painter->drawRoundedRect(activeTrack, grooveHeight / 2, grooveHeight / 2); // Handle (Thumb) - Fluent style is more subtle int handleSize = 20; QRect thumbRect(handle.center().x() - handleSize / 2, handle.center().y() - handleSize / 2, handleSize, handleSize); // Hover effect - subtle glow if (slider->state & State_MouseOver) { painter->setBrush(QColor(activeColor.red(), activeColor.green(), activeColor.blue(), 30)); int glowSize = 32; QRect glow(handle.center().x() - glowSize / 2, handle.center().y() - glowSize / 2, glowSize, glowSize); painter->drawEllipse(glow); } // Thumb painter->setBrush(bgColor); painter->setPen(QPen(activeColor, 2)); painter->drawEllipse(thumbRect); // Inner circle for pressed state if (slider->state & State_Sunken) { int innerSize = 8; QRect inner(handle.center().x() - innerSize / 2, handle.center().y() - innerSize / 2, innerSize, innerSize); painter->setPen(Qt::NoPen); painter->setBrush(activeColor); painter->drawEllipse(inner); } } void drawVerticalFluentSlider(QPainter* painter, const QStyleOptionSlider* slider, const QColor& activeColor, const QColor& inactiveColor, const QColor& bgColor) const { QRect groove = slider->rect; QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, nullptr); int grooveWidth = 4; // Track sollte im Widget-Zentrum sein int grooveX = slider->rect.center().x() - grooveWidth / 2; // Full background track QRect fullTrack(grooveX, groove.top(), grooveWidth, groove.height()); painter->setPen(Qt::NoPen); painter->setBrush(inactiveColor.lighter(150)); painter->drawRoundedRect(fullTrack, grooveWidth / 2, grooveWidth / 2); // Active track int activeHeight = groove.bottom() - handle.center().y(); QRect activeTrack(grooveX, handle.center().y(), grooveWidth, activeHeight); painter->setBrush(activeColor); painter->drawRoundedRect(activeTrack, grooveWidth / 2, grooveWidth / 2); // Handle int handleSize = 20; QRect thumbRect(handle.center().x() - handleSize / 2, handle.center().y() - handleSize / 2, handleSize, handleSize); if (slider->state & State_MouseOver) { painter->setBrush(QColor(activeColor.red(), activeColor.green(), activeColor.blue(), 30)); int glowSize = 32; QRect glow(handle.center().x() - glowSize / 2, handle.center().y() - glowSize / 2, glowSize, glowSize); painter->drawEllipse(glow); } painter->setBrush(bgColor); painter->setPen(QPen(activeColor, 2)); painter->drawEllipse(thumbRect); if (slider->state & State_Sunken) { int innerSize = 8; QRect inner(handle.center().x() - innerSize / 2, handle.center().y() - innerSize / 2, innerSize, innerSize); painter->setPen(Qt::NoPen); painter->setBrush(activeColor); painter->drawEllipse(inner); } } }; class SliderDelegate : public QStyledItemDelegate { Q_OBJECT public: SliderDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {} // Editor erstellen (QSlider) QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option,const QModelIndex& index) const override { Q_UNUSED(option) Q_UNUSED(index) auto* slider = new QSlider(Qt::Horizontal, parent); slider->setRange(0, 100); slider->setSingleStep(1); slider->setPageStep(10); slider->setStyle(new FluentSliderStyle()); // Signal für sofortige Updates connect(slider, &QSlider::valueChanged, this, [this, slider]() { // Commit data sofort bei Änderung emit const_cast(this)->commitData(slider); }); return slider; } // Editor mit aktuellem Wert füllen void setEditorData(QWidget* editor, const QModelIndex& index) const override { int value = index.model()->data(index, Qt::EditRole).toInt(); auto* slider = static_cast(editor); slider->setValue(value); } // Wert vom Editor ins Model schreiben void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override { auto* slider = static_cast(editor); int value = slider->value(); model->setData(index, value, Qt::EditRole); } // Editor-Geometrie (wichtig für korrekte Positionierung) void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override { Q_UNUSED(index) /* QRect barRect = option.rect.adjusted(option.rect.width() - 55, option.rect.height() / 2 - 2, -8, -option.rect.height() / 2 + 2); */ QRect sliderRect = option.rect.adjusted( option.rect.width() - 115, // Von rechts: 115px (Breite der Progress Bar) 0, // Oben: kein Offset -8, // Rechts: 8px Padding 0 // Unten: kein Offset ); editor->setGeometry(sliderRect); // Slider nur über Progress Bar //editor->setGeometry(option.rect); } // Anzeige wenn NICHT editiert wird void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override { if (index.column() == 1) { // Nur für Wert-Spalte // Wert holen int value = index.model()->data(index, Qt::DisplayRole).toInt(); // Hintergrund if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, option.palette.highlight()); } else if (index.row() % 2 == 1) { painter->fillRect(option.rect, QColor(0xFAFAFA)); } else { painter->fillRect(option.rect, Qt::white); } // Text und kleiner Slider-Indikator zeichnen painter->save(); painter->setRenderHint(QPainter::Antialiasing); QRect textRect = option.rect.adjusted(8, 0, -120, 0); QRect barRect = option.rect.adjusted(option.rect.width() - 115, option.rect.height() / 2 - 2, -8, -option.rect.height() / 2 + 2); // Text painter->setPen(option.state & QStyle::State_Selected ? option.palette.highlightedText().color() : Qt::black); painter->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, QString::number(value)); // Mini Progress Bar painter->setPen(Qt::NoPen); painter->setBrush(QColor(0xE0E0E0)); painter->drawRoundedRect(barRect, 2, 2); QRect fillRect = barRect; fillRect.setWidth(barRect.width() * value / 100); painter->setBrush(QColor(0x0078D4)); painter->drawRoundedRect(fillRect, 2, 2); painter->restore(); } else { // Standard-Zeichnung für andere Spalten QStyledItemDelegate::paint(painter, option, index); } } }; #endif // SLIDERDELEGATE_H