Wrong rich text height (QTextDocument) in item rendered by custom item delegate



  • Hi,

    I have a problem with the text height of the text in my tree view (which looks like a list view).

    My paint() and sizeHint() methods are almost exactly the same, but calculate different height of the text (the same text).

    The difference of height varies depending on the font. If everything is written in one size, then the height is correct, but if I use different sizes, the heights doesn't match.

    I read a topic about using font metrics, or calcuating the font height form paiter.boundingRect, but I don't know how to use this in a QTextDocument.

    I thought that the problem is with the font, so I changed the font globaly to one with the code below. It didn't help.

    //in main():
        QFont font("MS Shell Dlg 2",8.25,50);
        font.setPointSizeF(8.25);
        QApplication::setFont(font);
    

    My code in my custom itemDelegate is:

    QSize MyItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
            QStyleOptionViewItem options = option;
            initStyleOption(&options, index);
    
            int scrollBarrWidth = -2;
            if(scrollBarVisible){
            scrollBarrWidth = 10; //options.widget->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
            }
            int checkboxWidth = 0;
            if(checkboxesForConferenceActive){
                checkboxWidth = 18;
            }
    
            QRect rectLeft(checkboxWidth,0,26,26);
            QRect rectRight((options.widget->rect().right()-30-scrollBarrWidth),0,26,26); 
            QRect rectCenter((rectLeft.right()+5),-2,(options.widget->rect().width()-(rectLeft.width()+rectRight.width()+scrollBarrWidth+checkboxWidth+8+4)),26);  
            QRect boundingRect;
    
            QString nameText(index.data(Qt::UserRole).toString());
            QString extNoText(index.data(Qt::UserRole+1).toString());
            QString phoneText(index.data(Qt::UserRole+100).toString());
    
            QTextDocument textDoc;
            textDoc.setDefaultFont(options.font);
            textDoc.setTextWidth(rectCenter.width());
            textDoc.setDocumentMargin(0);
    		
            QTextCursor textCursor(&textDoc);
            QString wholeText("");
            QImage statusIcon(*icoChooser->choseCustomStateImageForSubscriber(index.data(Qt::UserRole+12).toInt()));
            bool wczytajfote = !statusIcon.isNull();
    
            wholeText.append("<b>");
            wholeText.append(nameText);
            wholeText.append("</b>");
            textCursor.insertHtml(wholeText);
            if(wczytajfote){
            textCursor.movePosition(QTextCursor::EndOfLine, QTextCursor::MoveAnchor);
            textCursor.insertImage(statusIcon.scaledToWidth(12));
            textCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
            } else {
            textCursor.insertHtml("&nbsp");
            }
            wholeText.clear();
            if(!extNoText.isEmpty()){
    
                wholeText.append("<font color = #005c99>");
                wholeText.append(QString(" ("+extNoText+") "));
                wholeText.append("</font>");
                wholeText.append("<br><font style=\"font-size:10px; color: #6d6d78\">");
                wholeText.append(index.data(Qt::UserRole+4).toString());
                wholeText.append("</font>");
                textCursor.insertHtml(wholeText);
    
                if(textDoc.idealWidth() < rectCenter.width() ){
                    QRect clip(0,0,textDoc.idealWidth(), textDoc.size().height());
    				
                    return QSize(textDoc.idealWidth(), textDoc.size().height()+4);
                } else {
                    QRect clip(0,0,textDoc.idealWidth(), textDoc.size().height());
    				
                    return QSize(textDoc.idealWidth(), textDoc.size().height()+4);
                }
            } else {
                wholeText.append("<br>");
                wholeText.append("<font size = 2 color = #005c99>");
                wholeText.append(QString(" ("+phoneText+") "));
                wholeText.append("</font>");
                textCursor.insertHtml(wholeText);
    
                QRect clip(0,0,textDoc.idealWidth(), textDoc.size().height());
    
                return QSize(textDoc.idealWidth(), textDoc.size().height()+6);
    
            }
    }
    

    and the paint method is almost exactly the same.

    void MyItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {		
    		QStyleOptionViewItem options = option;
            initStyleOption(&options, index);
    
            painter->save();
            painter->setRenderHint(QPainter::Antialiasing, true);
            painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
            painter->setRenderHint(QPainter::TextAntialiasing, true);
    
    
            options.text = "";
    
            int scrollBarrWidth = -2;
            if(scrollBarVisible){
    
            scrollBarrWidth = 10;  //options.widget->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
            }
            int checkboxWidth = 0;
            if(checkboxesForConferenceActive){
                checkboxWidth = 18;
            }
    
            QRect rectLeft(checkboxWidth,0,26,26);
            QRect rectRight((options.widget->rect().right()-30-scrollBarrWidth),0,26,26); //obliczam na podstawie prostokąta, który jest przed nim i który ma dynamicznie ustawiane wymiary
            QRect rectCenter((rectLeft.right()+5),-2,(options.widget->rect().width()-(rectLeft.width()+rectRight.width()+scrollBarrWidth+checkboxWidth+8+4)),26);  //obliczam prostokąt na podstawie wcześniejszego prostokąta i prostokąta wymiarów okna
            QRect boundingRect;
    
            QString nameText(index.data(Qt::UserRole).toString());
            QString extNoText(index.data(Qt::UserRole+1).toString());
            QString phoneText(index.data(Qt::UserRole+100).toString());
    
            painter->translate(options.widget->rect().left(), options.rect.top());
    
                    QTextDocument textDoc;
                    textDoc.setTextWidth(rectCenter.width());
    
                    QTextCursor textCursor(&textDoc);
                    QString wholeText("");
    
                    QImage statusIcon(*icoChooser->choseCustomStateImageForSubscriber(index.data(Qt::UserRole+12).toInt()));
                    bool wczytajfote = !statusIcon.isNull();
    
                    wholeText.append("<b>");
                    wholeText.append(nameText);
                    wholeText.append("</b>");
                    textCursor.insertHtml(wholeText);
                    if(wczytajfote){
                    textCursor.movePosition(QTextCursor::EndOfLine, QTextCursor::MoveAnchor);
                    textCursor.insertImage(statusIcon.scaledToWidth(12));
                    textCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
                    } else {
                    textCursor.insertHtml("&nbsp");
                    }
                    wholeText.clear();
                    if(!extNoText.isEmpty()){
    
                        wholeText.append("<font size = 2 color = #005c99>");
                        wholeText.append(QString(" ("+extNoText+") "));
                        wholeText.append("</font>");
                        wholeText.append("<br><font style=\"font-size:10px; color: #6d6d78\">");
                        wholeText.append(index.data(Qt::UserRole+4).toString());
                        wholeText.append("</font>");
                    } else {
                        wholeText.append("<br>");
                        wholeText.append("<font size = 2 color = #005c99>");
                        wholeText.append(QString(" ("+phoneText+") "));
                        wholeText.append("</font>");
                    }
                    textCursor.insertHtml(wholeText);
    
                    painter->translate(rectCenter.left(), rectCenter.top());
    
                    QRect clip(0,0,textDoc.size().width(), textDoc.size().height());
    
                    textDoc.drawContents(painter, clip);
    
    
            painter->restore();
        }
    }
    

    The text in sizeHint is used to determine the item height, so now it looks like the pic below:
    picture

    I'm using Qt 5.7.1 MSVC 2015 64 bit on windows, but the problem is the same on Ubuntu 16.04 with gcc.



  • Terribly sorry, but it turned out to be my fault all along.

    The line responsible was:

    textDoc.setDocumentMargin(0);
    

    in the sizeHint() method.



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