How to calculate line while wrapping text in QLIstview



  • Hi,

    I am working on messaging application. I have a delegate which arrange text in different rect to draw text. I have to show - Name, date and time, Subject, Message , message status Icon. It doesnt work well (ie it create extra lines) in case if word is long . There is some problem in calculating in sizeHint but i tried different scenarios and couldnt make it working . for long text there are always extra lines coming in QLIstView .
    Please check the link below :
    !http://tinypic.com/r/34dt1de/5(Message shown in QListView)!

    Here's the code for this:
    @
    QSize ConversationViewItemDelegate::sizeHint(const QStyleOptionViewItem& , const QModelIndex& index) const
    {
    QString str = index.data().toString();

    QListView *view = (QListView*)parent();
    QFontMetrics fontMetrics(view->font());
    
    QStringList words = str.split(QChar(' '));
    words.removeAll("\n");
    QStringList lines = str.split(QChar('\n'));
    int noOfLines = lines.size();
    
    QRectF boundingRect = fontMetrics.boundingRect(str);
    int width = view->viewport()->width() -35;
    int height = boundingRect.height();
    int times = 0;
    while (words.size() > 0)
    {
        times++;
        qreal lineWidth = 0;
        bool enoughSpace = true;
        do
        {
            QString word = words.first();
            qreal wordWidth = fontMetrics.width(word);
            wordWidth = wordWidth + lineWidth;
            lineWidth = 0;
            if(wordWidth > width)
            {
                times++;
                while(wordWidth > width )
                {
                    times++;
                    wordWidth -= width;
                }
                lineWidth += wordWidth;
                lineWidth += fontMetrics.width(QChar(' '));
                words.removeFirst();
            }
            else if (wordWidth < width)
            {
                lineWidth += wordWidth;
                lineWidth += fontMetrics.width(QChar(' '));
                words.removeFirst();
            }
            else
                enoughSpace = false;
        }
        while (enoughSpace && words.size() > 0);
    }
    
    height = height * times  + (noOfLines + 3)* boundingRect.height() - times;
    QSize sizeOfSubjectField = QSize();
    if (!index.model()->data(index, ConversationViewMsgSubjectRole).toString().isEmpty())
    {
     QString subject = "Subject: " +  index.model()->data(index, ConversationViewMsgSubjectRole).toString();
     sizeHintforSubject(subject);
    }
    else
    {
        height = height - boundingRect.height();
    }
    
    height += sizeOfSubjectField.height();
    return QSize(width,  height);
    

    }

    QSize ConversationViewItemDelegate::sizeHintforSubject(QString str) const
    {
    QListView p = (QListView)parent();
    QString text = str;
    QFontMetrics fm(p->font());

    float rw = float(p->viewport()->size().width());
    float tw = fm.width(text);
    float ratio = tw/rw;
    int lines = int(ratio) + 1;
    return QSize(rw,lines*fm.height());
    

    }

    @



  • the paint function code is as follows:
    @void ConversationViewItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex & index) const
    {

    QString displayName = index.model()->data(index, ConversationViewDisplayNameRole).toString();
    QString dateTime = index.model()->data(index, ConversationViewDateTimeRole).toString();
    bool messageStatus = index.model()->data(index, ConversationViewMsgReadRole).toBool();
    QString textMessage = index.model()->data(index, ConversationViewMessageRole).toString();
    
    QString subject = QString();
    
    if (!index.model()->data(index, ConversationViewMsgSubjectRole).toString().isEmpty())
    {
     subject = "Subject: " +  index.model()->data(index, ConversationViewMsgSubjectRole).toString();
    }
    
    QIcon messageStatusIcon =  index.model()->data(index, ConversationViewMsgStatusIcon).value<QIcon>();
    QPixmap pMessageStatusPixmap = messageStatusIcon.pixmap(option.decorationSize);
    
    QRect messageRect = option.rect;
    QRect dateTimeRect = option.rect;
    QRect boundaryRect = option.rect;
    QRect displayNameRect = option.rect;
    QRect sendMessageIconRect = option.rect;
    QRect subjectRect = option.rect;
    
    dateTimeRect.setTop(dateTimeRect.top()+5);
    dateTimeRect.setBottom(dateTimeRect.top()+15);
    dateTimeRect.setLeft(dateTimeRect.right()- 110);
    dateTimeRect.setRight(dateTimeRect.right()-5);
    
    displayNameRect.setTop(displayNameRect.top()+5);
    displayNameRect.setBottom(displayNameRect.top()+15);
    displayNameRect.setLeft(displayNameRect.left()+5);
    displayNameRect.setRight(displayNameRect.right()-120);
    
    boundaryRect.setRight(boundaryRect.right() - 2);
    boundaryRect.setLeft(boundaryRect.left() + 2);
    
    if(!index.model()->data(index, ConversationViewMsgSubjectRole).toString().isEmpty())
    {
        QSize a  = sizeHintforSubject(subject);
        subjectRect.setTop(dateTimeRect.bottom() + 2);
        subjectRect.setLeft(subjectRect.left() + 10);
        subjectRect.setRight(subjectRect.right() - 35);
        subjectRect.setBottom(subjectRect.top() + a.height());
    
        messageRect.setTop(subjectRect.bottom()+ 5);
        messageRect.setRight(messageRect.right() - 5);
    }
    else
    {
        messageRect.setTop(dateTimeRect.bottom()+10);
        messageRect.setRight(messageRect.right() - 25);
    }
    messageRect.setLeft(messageRect.left() + 10);
    messageRect.setBottom(messageRect.bottom() - 5);
    
    sendMessageIconRect.setTop(dateTimeRect.bottom()+2 );
    sendMessageIconRect.setRight(sendMessageIconRect.right()-5);
    sendMessageIconRect.setLeft(sendMessageIconRect.right()- 20);
    sendMessageIconRect.setBottom(dateTimeRect.bottom()+20);
    
    QFont boldFont = QApplication::font();
    boldFont.setBold(true);
    QFont normalFont = QApplication::font();
    QFont italicFont = QApplication::font();
    italicFont.setItalic(true);
    
    //Change color in message is UNREAD
    if(!messageStatus)
    {
       painter->fillRect(boundaryRect, "#C0C0C0");
    }
    //Set selected Message item color
    if (option.state & QStyle::State_Selected)
         painter->fillRect(boundaryRect, "#C8E0FD");
    
    painter->save();
    painter->drawRoundedRect(boundaryRect, 3, 3);
    painter->drawText(dateTimeRect, Qt::AlignLeft  , dateTime);
    painter->drawPixmap(sendMessageIconRect, pMessageStatusPixmap);
    
    QTextOption opt ;
    opt.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
    painter->drawText(messageRect,textMessage, opt );
    
    painter->setFont(italicFont);
    painter->drawText(subjectRect,subject, opt );
    painter->setFont(boldFont);
    painter->drawText(displayNameRect, Qt::AlignLeft  , displayName);
    
    
    painter->restore();
    

    }@

    some how the pic didnt come . the link for it is http://tinypic.com/r/34dt1de/5



  • Any suggestions ????


  • Moderators

    what is exactly the problem?!
    the image you've posted seems ok?



  • Hi Raven,

    Thanks for the reply. Actually I am trying to make a chat view using QLIstview to show previous msges. The problem which i am facing is that where the text is very long there are extra space (extra number of lines from size hint) in list view item. i checked the previous post and wrote the size hint , it works only for small texts. If i show long text having long words then extra spaces comes in list view item. I am using WrapAtWordBoundaryOrAnywhere .

    Regards,
    Prankur


  • Moderators

    maybe your text contains "\n" which cause the extra line breaks?


Log in to reply
 

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