[SOLVED] QTableView - custom sizeHint() implementation slow



  • Hi guys,

    I'm using a QTableView to display a bunch of information. Since I need rich text support in the cells I implemented a custom item delegate with QTextDocument and overwrote the sizeHint();
    However, the sizeHint() function causes some problems: It slows everything down really badly. By that I mean, that e.g. moving the cursor over a few cells, the highlighting really lags behind.

    Here's the code that I use for the Delegate and the sizeHint:
    @void RichTextDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const {

    QStyleOptionViewItemV4 options = option;
    initStyleOption(&options, index);

    painter->save();

    QTextDocument doc;
    doc.setTextWidth(options.rect.width());
    doc.setHtml(options.text);

    options.text = "";
    options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);

    painter->translate(options.rect.left(), options.rect.top());
    QRect clip(0, 0, options.rect.width(), options.rect.height());

    QPen greyPen(Qt::lightGray);
    painter->setPen(greyPen);
    painter->drawLine(0,options.rect.height(),options.rect.width(),options.rect.height());
    painter->drawLine(0,0,options.rect.width(),0);

    painter->setClipRect(clip);
    QAbstractTextDocumentLayout::PaintContext ctx;

    ctx.clip = clip;
    doc.documentLayout()->draw(painter, ctx);

    painter->restore();

    }

    QSize RichTextDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const {

    QStyleOptionViewItemV4 optionV4 = option;
    initStyleOption(&optionV4, index);
    QTextDocument doc;
    doc.setHtml(optionV4.text);
    doc.setTextWidth(optionV4.rect.width());
    return QSize(doc.idealWidth(), doc.size().height());

    }@

    I know, the laggish behaviour is caused by sizeHint, because if I remove its implementation everything works just fine... Any idea, what I can do to improve the code, stopping it to be "laggish"?

    Appreciate any help!

    Ps: I tested it both under Qt 4.8.5 and Qt 5.1.1, same result.



  • You are recreating QTextDocument doc everytime sizeHint is called. It may be called a million times on just one refresh of a screen.

    I would recommend to ...

    1. keep doc outside sizeHint.
    2. call doc.setHtml(optionV4.text); only when content has changed.
    3. call #2 outside sizeHint
    4. call doc.setTextWidth(optionV4.rect.width()); also only when content has changed
    5. call #4 outside sizeHint
    6. you can keep the last line maybe with a little modification :)
      return QSize(m_doc.idealWidth(), m_doc.size().height());


  • That makes sense, thanks! No wonder it's slow.

    However, I can't figure out how to check if the content has changed. The problem is, that both functions are const, i.e. assigning anything from there to e.g. a global variable doesn't work:

    (header)
    QString txt;

    (paint/sizehint)
    txt = options.text

    -> doesn't compile:
    passing 'const QString' as 'this' argument of 'QString& QString::operator=(const QString&)' discards qualifiers

    But how else could I keep track of changes of the content?



  • Okay, I think I got it now, the (now deleted?) comment about the mutable keyword helped a lot.
    No I check for changes in content and/or changes in the optionV4.rect, and only if at least one of them changed then I recalculate the sizeHint. Here's the code I came up with:

    (header)
    @private:
    mutable QHash<QPair<int,int>, QString> txt;
    mutable QHash<QPair<int,int>, QSize> docSize;
    mutable QHash<QPair<int,int>, QRect> optionRect;@

    (source)
    @QSize RichTextDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const {

    QStyleOptionViewItemV4 optionV4 = option;
    initStyleOption(&optionV4, index);

    QPair<int,int> p;
    p.first = index.row();
    p.second = index.column();

    if(txt[p] != optionV4.text || optionRect[p] != optionV4.rect) {

    QTextDocument doc;
    doc.setHtml(optionV4.text);
    doc.setTextWidth(optionV4.rect.width());

    txt[p] = optionV4.text;

    docSize[p] = QSize(doc.idealWidth(),doc.size().height());
    optionRect[p] = optionV4.rect;

    }

    return docSize[p];

    }@

    I hope I haven't missed something important, but, as far as I can tell, that works quite well.

    Thanks a million to Agroni and the other person of the deleted comment!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.