/*************************************************************************** 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 //! 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::ProgressBarType, 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, index ); case XQItem::ComboBoxStyle : return drawComboBoxStyle( painter, option, index ); case XQItem::HiddenStyle : return; //case XQItem::ProgressBarStyle : // return drawProgressBarStyle( painter, option, index ); default: break; } // switch QStyledItemDelegate::paint(painter, option, index); } //! einen section header im header-style zeichnen void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QStyleOptionHeader headerOption; XQItem& item = xqItemFromIndex( index ); // use the header as "parent" for style init QWidget* srcWidget = treeTable();//->header(); headerOption.initFrom(srcWidget); headerOption.text = index.data(Qt::DisplayRole).toString(); 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::drawProgressBarStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { int progress = index.data(XQItem::ContentRole ).toInt(); QStyleOptionProgressBar progressBarOption; progressBarOption.rect = option.rect; progressBarOption.minimum = 0; progressBarOption.maximum = 100; progressBarOption.progress = progress; progressBarOption.text = QString::number(progress) + "%"; progressBarOption.textAlignment = Qt::AlignCenter; progressBarOption.textVisible = true; QApplication::style()->drawControl(QStyle::CE_ProgressBar,&progressBarOption, painter); } //! firz void XQItemDelegate::drawComboBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) 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 = index.data(Qt::DisplayRole).toString(); // decoration (if any) comboOption.currentIcon = qvariant_cast(index.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(); } //! firz void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { // xx_fix! //int value = index.data(XQItem::ContentRole ).toInt(); QStyleOptionSpinBox spinBoxOption; spinBoxOption.rect = option.rect; /* spinBoxOption.text = QString::number(value); spinBoxOption.textAlignment = Qt::AlignCenter; spinBoxOption.textVisible = true; */ QApplication::style()->drawComplexControl(QStyle::CC_SpinBox,&spinBoxOption, painter); } //! firz 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); 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); }