Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

disable the Icon (decoration role) of the QStandardItems on for certain QTreeView?



  • Hello,
    I'm having a main View that display my Model with icons on my items and I'd like to display a part of it on another view but without the icons.
    Would this be possible?
    Could I tell the view to not go for the decoration?



  • It's not the view, it's the delegate but sure you can

    WARNING: wrong code, see below

    class NoIconDelegate : public QStyledItemDelegate{
    Q_OBJECT
    Q_DISABLE_COPY(NoIconDelegate)
    public:
    exclicit NoIconDelegate(QObject* parent=Q_NULLPTR) : QStyledItemDelegate(parent){}
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE{
     Q_ASSERT(index.isValid());
        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);
    opt.icon = QIcon();
    opt.decorationSize=QSize(-1, -1);
    opt.features &= ~QStyleOptionViewItem::HasDecoration;
        QStyle *style = option.widget ? option.widget->style() : QApplication::style();
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, option.widget);
    }
    }


  • Cheers,
    It makes sense that it is the delegate and not the view directly that does the job!
    Thanks



  • @mbruel On second thought, this is much better, it is more effivcient and also impacts sizeHint:

    class NoIconDelegate : public QStyledItemDelegate{
        Q_OBJECT
        Q_DISABLE_COPY(NoIconDelegate)
    public:
        explicit NoIconDelegate(QObject* parent=Q_NULLPTR) : QStyledItemDelegate(parent){}
    protected:
        void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const Q_DECL_OVERRIDE
        {
            QVariant value = index.data(Qt::FontRole);
            if (value.isValid() && !value.isNull()) {
                option->font = qvariant_cast<QFont>(value).resolve(option->font);
                option->fontMetrics = QFontMetrics(option->font);
            }
            value = index.data(Qt::TextAlignmentRole);
            if (value.isValid() && !value.isNull())
                option->displayAlignment = Qt::Alignment(value.toInt());
            value = index.data(Qt::ForegroundRole);
            if (value.canConvert<QBrush>())
                option->palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
            option->index = index;
            value = index.data(Qt::CheckStateRole);
            if (value.isValid() && !value.isNull()) {
                option->features |= QStyleOptionViewItem::HasCheckIndicator;
                option->checkState = static_cast<Qt::CheckState>(value.toInt());
            }
            value = index.data(Qt::DisplayRole);
            if (value.isValid() && !value.isNull()) {
                option->features |= QStyleOptionViewItem::HasDisplay;
                option->text = displayText(value, option->locale);
            }
            option->backgroundBrush = qvariant_cast<QBrush>(index.data(Qt::BackgroundRole));
            option->styleObject = 0;
        }
    };
    


  • @VRonin

    cool to use directly the initStyleOption method :)
    I'm not sure why you explore so many Roles, this seems to do the job perfectly:

    void NoIconTreeItemDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
    {
        QStyledItemDelegate::initStyleOption(option, index);
        option->icon           = QIcon();
        option->decorationSize = QSize(-1, -1);
        option->features      &= ~QStyleOptionViewItem::HasDecoration;
    }
    

    Personnaly I wish to only let the icons for my Root elements so here is my implementation:

    void NoIconTreeItemDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
    {
        QStyledItemDelegate::initStyleOption(option, index);
        TreeItem *item = static_cast<const TreeProxyModel*>(index.model())->itemFromIndex(index);
        if (item && !static_cast<TreeItem*>(item)->isRootItem())
        {
            option->icon           = QIcon();
            option->decorationSize = QSize(-1, -1);
            option->features      &= ~QStyleOptionViewItem::HasDecoration;
        }
    }
    


  • @mbruel said in disable the Icon (decoration role) of the QStandardItems on for certain QTreeView?:

    I'm not sure why you explore so many Roles

    I just copy-pasted the body of QStyledItemDelegate::initStyleOption and removed the part that had to do with the decoration role.

    TreeItem *item = static_cast<const TreeProxyModel*>(index.model())->itemFromIndex(index);
        if (item && !static_cast<TreeItem*>(item)->isRootItem())
    

    Using model-specific stuff inside the delegate is bad design. that whole snippet can be replaced with if(!index.parent().isValid()) and be compatible with all models



  • @VRonin said in disable the Icon (decoration role) of the QStandardItems on for certain QTreeView?:

    Using model-specific stuff inside the delegate is bad design. that whole snippet can be replaced with if(!index.parent().isValid()) and be compatible with all models

    Yeah I know but my delegate is completely specialized to the need of my App.

    static_cast<TreeItem*>(item)->isRootItem()
    

    is not telling me if the item the root of TreeModel but rather if I should display the item bigger.
    I could have several types of Items that I wish to display bigger in my main TreeView. In the other ones where I'll use this delegate with no icon, I will just display the Icon only for those types without making it bigger and not display the icons for the "standard" other items

    @VRonin said in disable the Icon (decoration role) of the QStandardItems on for certain QTreeView?:

    I just copy-pasted the body of QStyledItemDelegate::initStyleOption and removed the part that had to do with the decoration role.

    Ah ok I see. I find it more clear to use the main method and then just override the decoration part.


Log in to reply