#include #include #include #include #include #include #include #include #include #include #include #include "bcitemdelegate.h" #include "bcdataitem.h" #include "qapplication.h" BCItemDelegate::BCItemDelegate(QListView *view) : QStyledItemDelegate(view), _view{view} { } QString BCItemDelegate::displayText(const QVariant& dataValue, const QLocale& locale) const { // Wir prüfen, ob im Variant unser Struct steckt if (dataValue.canConvert()) { BCDataItem& bc = *dataValue.value(); qDebug() << " --- YES: " << bc.label; // Hier bauen wir den String zusammen, den man sieht, // wenn KEIN Editor offen ist. // Format: "Label: Wert Einheit" return QString("%1: %2 %3").arg(bc.label, bc.value.toString(), "mmX"); } else { //qDebug() << " --- Nö!"; } // Fallback für normale Strings/Zahlen return QStyledItemDelegate::displayText(dataValue, locale); } QWidget *BCItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex& index) const { QVariant rawData = index.data(Qt::EditRole); if (!rawData.canConvert()) return QStyledItemDelegate::createEditor(parent, option, index); const BCDataItem& bc = *rawData.value(); // Nur bei Integern den Slider-Editor bauen if (bc.value.typeId() == QMetaType::Int) { QWidget *container = new QWidget(parent); container->setAutoFillBackground(true); QHBoxLayout *layout = new QHBoxLayout(container); layout->setContentsMargins(4, 0, 4, 0); layout->setSpacing(10); // Linkes Label (Name) QLabel *lblName = new QLabel(bc.label, container); lblName->setFixedWidth(80); // Slider QSlider *slider = new QSlider(Qt::Horizontal, container); slider->setRange(0, 100); slider->setObjectName("slider"); // Rechtes Label (Vorschau Wert + Einheit) QLabel *lblUnit = new QLabel(container); lblUnit->setFixedWidth(60); lblUnit->setAlignment(Qt::AlignRight | Qt::AlignVCenter); lblUnit->setObjectName("lblUnit"); layout->addWidget(lblName); layout->addWidget(slider); layout->addWidget(lblUnit); // Live-Update des Labels im Editor (aber noch kein Speichern im Model) connect(slider, &QSlider::valueChanged, this, [=](int val){ lblUnit->setText(QString("%1 %2").arg(val).arg("mm2")); }); return container; } return QStyledItemDelegate::createEditor(parent, option, index); } void BCItemDelegate::setEditorData(QWidget *editor, const QModelIndex& index) const { // Daten vom Model in den Editor laden const BCDataItem& bc = *index.data(Qt::EditRole).value(); QSlider *slider = editor->findChild("slider"); QLabel *lblUnit = editor->findChild("lblUnit"); if (slider && lblUnit) { bool olDriverState = slider->blockSignals(true); slider->setValue(bc.value.toInt()); slider->blockSignals(olDriverState); lblUnit->setText(QString("%1 %2").arg(bc.value.toInt()).arg( "mm3")); } else { QStyledItemDelegate::setEditorData(editor, index); } } void BCItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const { // Daten vom Editor zurück ins Model speichern (Beim Schließen) QSlider *slider = editor->findChild("slider"); if (slider) { int value = slider->value(); model->setData(index, value, Qt::EditRole); } else { QStyledItemDelegate::setModelData(editor, model, index); } } void BCItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex& index) const { editor->setGeometry(option.rect); } QSize BCItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex& index) const { return QStyledItemDelegate::sizeHint(option,index); /* QStyleOptionViewItem opt = option; initStyleOption(&opt, index); opt.text = formatDisplayString(index); QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); return style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), opt.widget); */ } void BCItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { /* // 1. Standard-Zeichnen (Text, Hintergrund, Selection) durchführen QStyledItemDelegate::paint(painter, option, index); // 2. Unser Custom-Overly: Oranger Rahmen, wenn Zeile passt if (index.row() == _highlightedRow) { painter->save(); qDebug() << " --- is highlight: " << index.row(); // Setup Stift QPen pen(QColor(255, 165, 0)); // Orange pen.setWidth(2); painter->setPen(pen); // Rechteck zeichnen (leicht eingezogen, damit es nicht abgeschnitten wird) QRect rect = option.rect.adjusted(1, 1, -1, -1); painter->drawRect(rect); painter->restore(); } */ QStyledItemDelegate::paint(painter, option, index); /* if (index.row() == _highlightedRow && _opacity > 0.0) { painter->save(); qDebug() << " --- is highlight: " << index.row(); QColor highlightColor( 0xFF9800 ); highlightColor.setAlphaF(_opacity); QPen pen(highlightColor, 3); painter->setPen(pen); painter->setBrush(Qt::NoBrush); painter->drawRoundedRect(option.rect.adjusted(2, 2, -2, -2), 8, 8); painter->restore(); } */ int row = index.row(); if (m_rowOpacities.contains(row)) { /* qreal opacity = m_rowOpacities.value(row); if (opacity > 0.01) { painter->save(); painter->setOpacity(opacity); painter->fillRect(option.rect, QColor(255, 140, 0, 120)); painter->restore(); } */ paintHighlightRow(painter,option,index); } } void BCItemDelegate::paintHighlightRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { painter->save(); painter->setRenderHint(QPainter::Antialiasing); int row = index.row(); qreal opacity = m_rowOpacities.value(row); painter->setOpacity(opacity); // Margin von 4px QRect itemRect = option.rect.adjusted(4, 4, -4, -4); // Border von 2px berücksichtigen (nach innen) QRect contentRect = itemRect.adjusted(2, 2, -2, -2); // Hintergrund (weiß) painter->setBrush(Qt::white); painter->setPen(Qt::NoPen); painter->drawRoundedRect(itemRect, 8, 8); // Border (2px solid #2196F3) QPen borderPen( Qt::red, 2); painter->setPen(borderPen); painter->setBrush(Qt::NoBrush); painter->drawRoundedRect(itemRect, 8, 8); // Padding von 8px für den Content QRect textRect = contentRect.adjusted(8, 8, -8, -8); // Text zeichnen painter->setPen(Qt::black); // oder option.palette.color(QPalette::Text) QString text = index.data(Qt::DisplayRole).toString(); painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text); painter->restore(); } void BCItemDelegate::onHighlightRow(int row) { qDebug() << " --- should highlight: " << row; // Alte Animation für diese Zeile stoppen falls vorhanden if (m_rowAnimations.contains(row)) { m_rowAnimations[row]->stop(); m_rowAnimations[row]->deleteLater(); } // QVariantAnimation ist flexibler als QPropertyAnimation auto* anim = new QVariantAnimation(this); anim->setDuration(800); anim->setStartValue(0.0); anim->setEndValue(1.0); // Custom Easing für Fade-in/out Effekt anim->setEasingCurve(QEasingCurve::OutQuad); connect(anim, &QVariantAnimation::valueChanged, this, [this, row](const QVariant& value) { qreal progress = value.toReal(); qreal opacity; // Schnelles Fade-in (20%), langsames Fade-out (80%) if (progress < 0.2) { opacity = progress * 5.0; // 0->1 in 20% } else { opacity = 1.0 - ((progress - 0.2) / 0.8); // 1->0 in 80% } m_rowOpacities[row] = opacity; updateRow(row); }); connect(anim, &QVariantAnimation::finished, this, [this, row, anim]() { m_rowOpacities.remove(row); m_rowAnimations.remove(row); updateRow(row); anim->deleteLater(); }); m_rowAnimations[row] = anim; anim->start(QAbstractAnimation::DeleteWhenStopped); } // Optional: alle Highlights sofort clearen void BCItemDelegate::clearAllHighlights() { for(auto* anim : std::as_const(m_rowAnimations)) { anim->stop(); anim->deleteLater(); } m_rowAnimations.clear(); m_rowOpacities.clear(); if (_view) { _view->viewport()->update(); } } void BCItemDelegate::updateRow(int row) { if (_view && _view->model() && row >= 0) { QModelIndex idx = _view->model()->index(row, 0); QRect rect = _view->visualRect(idx); if (!rect.isEmpty()) { _view->viewport()->update(rect); } } } QString BCItemDelegate::formatDisplayString(const QModelIndex& index) const { if (!index.isValid()) return QString(); QString displayStr; /* QString label = index.data(BCDataListModel::LabelRole).toString(); QVariant value = index.data(BCDataListModel::ValueRole); QString unit = index.data(BCDataListModel::UnitRole).toString(); QString valueStr = value.toString(); // Formatierung für Zahlen bool ok; double numValue = value.toDouble(&ok); if (ok) { valueStr = QString::number(numValue, 'f', 2); } // Zusammensetzen des Anzeige-Strings QString displayStr = label; if (!displayStr.isEmpty() && !valueStr.isEmpty()) displayStr += ": "; displayStr += valueStr; if (!unit.isEmpty()) displayStr += " " + unit; */ return displayStr; }