/*************************************************************************** source::worx xtree Copyright © 2024-2025 c.holzheuer christoph.holzheuer@gmail.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* #include #include #include class BarDelegate : public QStyledItemDelegate { public: BarDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { // Standard-Zellenhintergrund zeichnen QStyledItemDelegate::paint(painter, option, index); // Wert aus dem Modell holen bool ok; int value = index.data().toInt(&ok); if (!ok || value < 0 || value > 100) return; // Balkenbereich berechnen QRect rect = option.rect.adjusted(4, 4, -4, -4); // etwas Padding int barWidth = static_cast(rect.width() * (value / 100.0)); // Balken zeichnen painter->save(); painter->setRenderHint(QPainter::Antialiasing); QRect barRect(rect.left(), rect.top(), barWidth, rect.height()); QColor barColor = QColor(100, 180, 255); // z. B. hellblau painter->setBrush(barColor); painter->setPen(Qt::NoPen); painter->drawRect(barRect); // Text (Zahl) zentriert zeichnen painter->setPen(Qt::black); painter->drawText(rect, Qt::AlignCenter, QString::number(value)); painter->restore(); } }; */ //! erzeugt eine editorfactory mit den hauseigenen editortypen. class XQItemEditorFactory : public QItemEditorFactory { public: XQItemEditorFactory() { registerEditor(XQItem::LineEditType, new QStandardItemEditorCreator()); registerEditor(XQItem::ComboBoxType, new QStandardItemEditorCreator()); registerEditor(XQItem::PickerType, new QStandardItemEditorCreator()); //registerEditor(XQItem::ColorBarType, new QStandardItemEditorCreator()); registerEditor(XQItem::ColorBarType, new QStandardItemEditorCreator()); registerEditor(XQItem::SpinBoxType, new QStandardItemEditorCreator()); registerEditor(XQItem::CustomEditorType, new QStandardItemEditorCreator()); } }; //! kontruktor mit dem zusändigen viewModel XQItemDelegate::XQItemDelegate( XQViewModel& viewModel) : _modelView{viewModel} { static XQItemEditorFactory s_EditorFactory; setItemEditorFactory(&s_EditorFactory); } //! gibt die interne tree table zurück XQTreeTable* XQItemDelegate::treeTable() const { return _modelView.treeTable(); } //! shortcut: gibt das XQItem für den gegebenen index zurück. XQItem& XQItemDelegate::xqItemFromIndex( const QModelIndex& index ) const { return _modelView.xqItemFromIndex( index ); } //! überladene paint-methode: zeichnet das item je nach render-style. void XQItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { if( !index.isValid() ) qDebug() << " index DEAD!"; XQItem& item = xqItemFromIndex( index ); switch( item.renderStyle() ) { case XQItem::HeaderStyle : return drawHeaderStyle( painter, option, item ); case XQItem::ComboBoxStyle : return drawComboBoxStyle( painter, option, item ); case XQItem::ColorBarStyle : qDebug() << " --- JAJA: " << index.data().toString(); return drawColorBarStyle( painter, option, item ); /* case XQItem::SpinBoxStyle : return drawSpinBoxStyle( painter, option, item ); */ case XQItem::HiddenStyle : return; default: break; } // switch QStyledItemDelegate::paint(painter, option, index); } //! einen section header im header-style zeichnen void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const { QStyleOptionHeader headerOption; // use the header as "parent" for style init QWidget* srcWidget = treeTable();//->header(); headerOption.initFrom(srcWidget); headerOption.text = item.text(); headerOption.rect = option.rect.adjusted(0,0,0,3); headerOption.styleObject = option.styleObject; // __ch: reduce inner offset when painting headerOption.textAlignment |= Qt::AlignVCenter; headerOption.icon = item.icon(); if (srcWidget != nullptr) { // save painter painter->save(); //value = index.data(Qt::ForegroundRole); //if (value.canConvert()) //headerOption.palette.setBrush(QPalette::Text, Qt::red ); //headerOption.palette.setBrush(QPalette::Window, Qt::red ); QCommonStyle itemStyle; //headerOption.backgroundBrush() //srcWidget->style()->drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget); itemStyle.drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget); // restore painter painter->restore(); } } //! firz void XQItemDelegate::drawColorBarStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const { //QStyledItemDelegate::paint(painter, option, item); // Wert aus dem Modell holen bool ok; int value = item.data(Qt::EditRole).toInt(&ok); if (!ok || value < 0 || value > 100) return; // Balkenbereich berechnen QRect rect = option.rect.adjusted(2, 2, -2, -2); // etwas Padding int barWidth = static_cast(rect.width() * (value / 100.0)); // Balken zeichnen painter->save(); painter->setRenderHint(QPainter::Antialiasing); QRect barRect(rect.left(), rect.top(), barWidth, rect.height()); QColor barColor = QColor(100, 180, 255); // z. B. hellblau painter->setBrush(barColor); painter->setPen(Qt::NoPen); painter->drawRect(barRect); // Text (Zahl) zentriert zeichnen painter->setPen(Qt::black); //painter->drawText(rect, Qt::AlignCenter, QString::number(value)+" %"); painter->drawText(rect, Qt::AlignCenter, item.text() ); painter->restore(); } //! Zeichnet das Item als combo box. void XQItemDelegate::drawComboBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const { QWidget* srcWidget = qobject_cast(option.styleObject); QStyleOptionComboBox comboOption; QStyle* comboStyle = srcWidget->style(); comboOption.initFrom(srcWidget); // set options comboOption.rect = option.rect; comboOption.state = option.state | QStyle::State_Selected | QStyle::State_Enabled; // not editable => only visual, but painter needs to know it comboOption.editable = false; comboOption.currentText = item.text(); // decoration (if any) comboOption.currentIcon = qvariant_cast(item.data(Qt::DecorationRole)); comboOption.iconSize = comboOption.currentIcon.actualSize(QSize(option.rect.height() - 3, option.rect.height() - 3)); // save painter painter->save(); // draw combo comboStyle->drawComplexControl(QStyle::CC_ComboBox, &comboOption, painter, srcWidget); // and combobox label comboStyle->drawControl(QStyle::CE_ComboBoxLabel, &comboOption, painter, srcWidget); // restore painter painter->restore(); } //! Zeichnet das Item als spin box. void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const XQItem& item) const { qDebug() << " --- jawas? SPINBOX!"; bool isInt = false; // Den Wert aus dem Modell holen. QString textToShow = item.data(Qt::DisplayRole).toString(); textToShow.toInt(&isInt); if (isInt) { // ----- Schritt 1: Den Rahmen und die Pfeile der SpinBox zeichnen ----- QStyleOptionSpinBox spinBoxOption; spinBoxOption.rect = option.rect; spinBoxOption.state = option.state; spinBoxOption.buttonSymbols = QAbstractSpinBox::UpDownArrows; spinBoxOption.stepEnabled = QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled; spinBoxOption.frame = true; // Zeichnet den "komplexen" Teil des Steuerelements (Rahmen, Hintergrund, Pfeile) QApplication::style()->drawComplexControl(QStyle::CC_SpinBox, &spinBoxOption, painter, nullptr); // ----- Schritt 2: Den Text an der richtigen Position zeichnen ----- // Ermitteln, wo genau das Textfeld innerhalb des Widgets gezeichnet werden soll. QRect textRect = QApplication::style()->subControlRect( QStyle::CC_SpinBox, &spinBoxOption, QStyle::SC_SpinBoxEditField, nullptr ); // Einen kleinen Innenabstand für den Text hinzufügen für besseres Aussehen. textRect.adjust(2, 0, -2, 0); // Den Text aus dem Modell in das ermittelte Rechteck zeichnen. // Die Flags sorgen für die korrekte Ausrichtung (rechtsbündig, vertikal zentriert). painter->drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, textToShow); } } //! Überschreibt QStyledItemDelegate::sizeHint(option, index); QSize XQItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { return QStyledItemDelegate::sizeHint(option, index); } //! Erzeugt ein editor-widget, sofern ein gültiger content-Ptr vorhanden und ein editor-Type gesetzt ist. QWidget* XQItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { XQItem& item = xqItemFromIndex(index); XQItem::EditorType edType = item.editorType(); if( edType == XQItem::NoEditorType ) { qDebug() << "---- NO Content or NO EditorType"; return nullptr; } qDebug() << "---- ed type:" << XQItem::fetchEditorTypeToString( edType ) << ": " << edType; QWidget* editor = itemEditorFactory()->createEditor(edType, parent);; //return QStyledItemDelegate::createEditor( parent, option, index ); return editor; } //! Füttert einen editor mit den model-daten void XQItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { XQItem& item = xqItemFromIndex( index ); XQItem::EditorType edType = item.editorType(); if( edType == XQItem::NoEditorType ) return; switch( edType ) { case XQItemType::ComboBoxType : { QComboBox* comboBox = qobject_cast(editor); // wir erwarten hier ein gültiges model? comboBox->setModel( item.fixedChoices()); comboBox->setCurrentText( item.data().toString() ); comboBox->showPopup(); return; } default: // wir benutzen hier die DisplayRole wenn der Inhalt schon formatiert ist. int role = item.renderStyle() == XQItem::FormattedStyle ? Qt::DisplayRole : Qt::EditRole; QVariant value = index.data(role); QByteArray userProp = editor->metaObject()->userProperty().name(); if (!userProp.isEmpty()) { if (!value.isValid()) value = QVariant(editor->property(userProp).metaType()); editor->setProperty(userProp, value); } } } //! Schreibt die daten aus dem editor ins model zurück void XQItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { XQItem& item = xqItemFromIndex( index ); switch( item.editorType() ) { case XQItem::ComboBoxType : { QComboBox* comboBox = qobject_cast(editor); return; } default: break; } QStyledItemDelegate::setModelData(editor, model, index); } //! firz void XQItemDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const { //qDebug() << " --- update Editor Geometry"; QStyledItemDelegate::updateEditorGeometry(editor, option, index); }