2

For some columns from a QTreeView widget, I use an icon. The icon is set on

QVariant headerData (int section, Qt::Orientation orientation, int role) const{
    if(role ==  Qt::DecorationRole)
    {
        QIcon icon;
        if (section == 0) {
            icon.addFile(":/icon1");
        } else if (section == 1){
            icon.addFile(":/icon2");
        }
    }

    if(role ==  Qt::TextAlignmentRole)
    {
        return (Qt::AlignLeft + Qt::AlignVCenter);
    }

The header looks like this:

enter image description here

I want to align the icons with the text. TextAlignmentRole only works for text, but not for the icons. How can I do that?

I also tried by setting the default alignment:

m_treeview->header()->setDefaultAlignment(Qt::AlignCenter); but no luck.

laurapons
  • 971
  • 13
  • 32

1 Answers1

3

In order to center icon with text you will have to implement your own proxy style to create this specific style behavior.

#include <QProxyStyle>
#include <QPainter>

class HeaderProxyStyle : public QProxyStyle
{
public:
    void drawControl(ControlElement oCtrElement, const QStyleOption * poStylrOptionption, QPainter * poPainter, const QWidget * poWidget = 0) const;

};

Center icon with text implementation

    void HeaderProxyStyle::drawControl(ControlElement oCtrElement, const QStyleOption *poStylrOptionption, QPainter *poPainter, const QWidget *poWidget) const
    {
        // Header label?
        if (oCtrElement == CE_HeaderLabel) {
            // YES - Allocate style option header
            QStyleOptionHeader *poStyleOptionHeader =
                    (QStyleOptionHeader *) poStylrOptionption;

            // Get header icon
            QIcon oIcon = qvariant_cast<QIcon>(poStyleOptionHeader->icon);

            // Icon is valid?
            if(oIcon.isNull()){
                // No - Draw text header
                QProxyStyle::drawControl(oCtrElement, poStylrOptionption, poPainter, poWidget);
                return;
            }

            // Set icon size 16x16
            QSize oIconSize = QSize(16,16);

            // Get header section rect
            QRect oRect = poStyleOptionHeader->rect;

            // Create header icon pixmap
            QPixmap oIconPixmap = oIcon.pixmap(oIconSize.width(),oIconSize.height());

            // Calculate header text width
            int iTextWidth = poStyleOptionHeader->fontMetrics.width(poStyleOptionHeader->text);

            QRect oCenterRec = QRect(oRect.left(),
                                    oRect.top() + (oRect.height - iTextSize)/2,
                                    oIconPixmap.width(),oIconPixmap.height());


            QRect oTextRect = QRect(oCenterRec.left()+ oIconSize.width(),
                              oCenterRec.top(), oCenterRec.width() + iTextWidth, oCenterRec.height());
            // Draw icon
            poPainter->drawPixmap(oCenterRec, oIconPixmap);
            // Draw text
            poPainter->drawText(oTextRect, poStyleOptionHeader->text);
            return;
        }
        QProxyStyle::drawControl(oCtrElement, poStylrOptionption, poPainter, poWidget);

    }

Then apply this header style in your tree view

// Set header style
m_treeview->header()->setStyle(&m_oHeaderStyle);
Simon
  • 1,522
  • 2
  • 12
  • 24
  • @laurapons: do you need any more help with this question? – Simon Nov 08 '17 at 15:58
  • I am not sure how to integrate this into the code (the widget inherited from qtreewidget uses models/delegates and proxys already), I will get bakc asap, thanks for your quick response! – laurapons Nov 08 '17 at 18:14
  • I also used model view structure in my project and I tried it and it works, so to integrate just create separate class `HeaderProxyStyle` then add private member 'HeaderProxyStyle m_oHeaderStyle` in the scope where you are using the `m_treeview` and set the style to the header `m_treeview->header()->setStyle(&m_oHeaderStyle);` it should work. you also can post more code I can help you. – Simon Nov 09 '17 at 06:31
  • Ok so I have integrated (thanks for your help!). Now, even if I set TextAlignmentRole on headerData() to (Qt::AlignLeft + Qt::AlignVCenter), all the headers with an icon are aligned on the top-center (the ones without icons are properly aligned). – laurapons Nov 09 '17 at 17:02
  • Ok, so I changed "oCenterRec" y point from "oRect.top()" to "oRect.top() + (oRect.height() - iTextSize)/2", where "iTextSize = poStyleOptionHeader->fontMetrics.height();" and now it's vertically centered, but I still need to align left instead of horitzontalcentered. – laurapons Nov 09 '17 at 18:56
  • Last change that made the trick: change "oCenterRec" x point from "oRect.left() + (oRect.width() / 2) - ( (iTextWidth + 16) / 2)" to "oRect.left()". Thanks, it works great! – laurapons Nov 09 '17 at 19:19
  • @laurapons, I'm glad I was able to help, I edited my answer with your comments. thanks. – Simon Nov 12 '17 at 08:52