5

I have a custom QItemDelegate drawing text within a QTreeView. In paint(), I get the size of the cell from the style. I then draw the text, with wordwrap, using the current cell's width.

In sizeHint(), I really only want to calculate the height. The width should just be whatever the current cell width is. As the user changes the cell width, sizeHint would just calculate the new height of the word-wrapped text and return that.

The problem is that I can't get the cell width inside sizeHint() like I do in paint(). I was using :

style = QApplication.style()
style.subElementRect(QStyle.SE_ItemViewItemText, option).width()

This works in paint(), but returns -1 in sizeHint(). How do I get the current cell width in sizeHint()?

1 Answers1

6

Original: I use the base class' sizeHint() method to get the cell size as it would have been, then modify the QSize as needed, like this:

QSize MyDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
    QSize sz=QItemDelegate::sizeHint(option, index);
    int h=sz.height();

    < MODIFY h HERE > 

    sz.setHeight(h);
    return sz;
}

Seems to work fine.

Edit: poster indicates that this doesn't work for him... So here's another option, maybe not the most elegant: add a view member to the delegate (which I can't think of a way to get from the delegate), and use the model index to get to the header's section size. For example:

class MyDelegate : public QItemDelegate
{
public:
    <the usual, then add>

    void setView(QAbstractItemView* v) { theView=v; }

protected:
    QAbstractItemView* theView;
};

and in the implementation

QSize MyDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
    int theWidth=-1;

    // handle other types of view here if needed
    QTreeView* tree=qobject_cast<QTreeView*>(theView);
    if(tree)
    {
        qDebug("WIDTH @ %d : %d",index.column(),tree->header()->sectionSize(index.column()));
        theWidth=tree->header()->sectionSize(index.column());
    }

    QSize sz=QItemDelegate::sizeHint(option, index);
    if(theWidth>=0)
        sz.setWidth(theWidth);

    // compute height here and call sz.setHeight()

    return sz;
}

Only thing left to do is in your code, after creating the delegate, call setView():

MyDelegate* theDelegate=new MyDelegate(...);
theDelegate->setView(theView);
Serge VK
  • 89
  • 1
  • 3
  • The base sizeHint is not the cell width. It's the size of the data within the cell. But since I'm drawing ALL the data myself, the base sizeHint thinks the cells have no data and returns a super small width. –  Jan 20 '12 at 00:05