Results 1 to 20 of 34

Thread: Word wrap in QListView

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Word wrap in QListView

    Hi everybody,
    I was trying to create a listView with word wrap function for text in items (rather than using horizontal scrollbar).

    I know that is necessary using delegates but the QT Manual wasn't of much help to me:
    • SpinBoxDelegate example shows how insert a spinbox in a tableView but the spinBox is visible only when editing and not in view mode. It doesn't use paint().
    • StarDelegate example doesn't use a common widget but a paintDevice. It reimplement paint() (obviously).


    Does somebody know an example/tutorial for delegate a common widget in view mode?

    Delegating a QLabel for my purpose is correct or is recommended a different widget? Have I to reimplement paint() function?

    I don't still have a sample code (a decent code ) to post now, so if some patient man want submit some hints would be very appreciated.

    Best regards
    Giuseppe CalÃ

  2. #2
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Word wrap in QListView

    You will have to do some something similar to the star delegate, only simpler.
    No editor is needed.
    You need the to override the paint for the delegate, and using the painter passed to you, paint the item text.
    Here is where you do the wrapping.
    Based on the item width, you can insert "\n"s in the text, or you can use a QTextLayout.
    With the text layout you would have to draw the text on a pixmap, and display this pixmap in the delegate.

    Regards

  3. #3
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Word wrap in QListView

    Ok marcel, I will follow your suggestion: modify stardelegate example and use qtextlayout.
    Eventually I will post the resulting code.

    Bye
    Giuseppe CalÃ

  4. #4
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Word wrap in QListView

    Well, I have some new and some code to post.

    Following marcel's suggestion I have modified the stardelegate example removing the editor and related parts. I have changed the parameter passed to StarRating (from int, the rating, to QString, the text to wordwrap) and used the code from this post; in this way the tableWidget contains a rich text column and long text is wrapped but it overlaps rows below: the cell height is not updated to enclose the multi-line text (hoping i was clear!).

    Then i have made a new copy of the source code and substituted QTableWidget with QListWidget; after some editing i have obtained a working application but without wordwrap (it used a horizontal scrollbar if text is too long).

    My questions are:
    1) how disable scrollbar in qlistwidget and fix the width forcing word wrap?
    2) how change row height according wordwrapping?

    The application, like Star Delegate example, has 2 classes:
    - TextDelegate.
    - TextPainter.

    Here the code (sorry for the long post):

    textdelegate.h
    Qt Code:
    1. #ifndef TEXTDELEGATE_H
    2. #define TEXTDELEGATE_H
    3.  
    4. #include <QItemDelegate>
    5.  
    6. class TextDelegate : public QItemDelegate
    7. {
    8. Q_OBJECT
    9.  
    10. public:
    11. TextDelegate(QWidget *parent = 0) : QItemDelegate(parent) {}
    12.  
    13. void paint(QPainter *painter, const QStyleOptionViewItem &option,
    14. const QModelIndex &index) const;
    15. QSize sizeHint(const QStyleOptionViewItem &option,
    16. const QModelIndex &index) const;
    17. };
    18.  
    19. #endif
    To copy to clipboard, switch view to plain text mode 

    textdelegate.cpp
    Qt Code:
    1. #include <QtGui>
    2.  
    3. #include "textdelegate.h"
    4. #include "textpainter.h"
    5.  
    6. void TextDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
    7. const QModelIndex &index) const
    8. {
    9. if (qVariantCanConvert<TextPainter>(index.data())) {
    10. TextPainter textPainter = qVariantValue<TextPainter>(index.data());
    11.  
    12. if (option.state & QStyle::State_Selected)
    13. painter->fillRect(option.rect, option.palette.highlight());
    14.  
    15. textPainter.paint(painter, option, TextPainter::ReadOnly);
    16. } else {
    17. QItemDelegate::paint(painter, option, index);
    18. }
    19. }
    20.  
    21. QSize TextDelegate::sizeHint(const QStyleOptionViewItem &option,
    22. const QModelIndex &index) const
    23. {
    24. if (qVariantCanConvert<TextPainter>(index.data())) {
    25. TextPainter textPainter = qVariantValue<TextPainter>(index.data());
    26. return textPainter.sizeHint();
    27. } else {
    28. return QItemDelegate::sizeHint(option, index);
    29. }
    30. }
    To copy to clipboard, switch view to plain text mode 

    textpainter.h
    Qt Code:
    1. #ifndef TEXTPAINTER_H
    2. #define TEXTPAINTER_H
    3.  
    4. #include <QMetaType>
    5. #include <QString>
    6.  
    7. class TextPainter
    8. {
    9. public:
    10. enum EditMode { Editable, ReadOnly };
    11.  
    12. TextPainter(QString text = "");
    13.  
    14. void paint(QPainter *painter, const QStyleOptionViewItem &option, EditMode mode) const;
    15. QSize sizeHint() const;
    16.  
    17. private:
    18.  
    19. QString itemText;
    20. };
    21.  
    22. Q_DECLARE_METATYPE(TextPainter)
    23.  
    24. #endif
    To copy to clipboard, switch view to plain text mode 

    textpainter.cpp
    Qt Code:
    1. #include <QtGui>
    2.  
    3. #include "textpainter.h"
    4.  
    5. const int PaintingScaleFactor = 20;
    6.  
    7. TextPainter::TextPainter(QString text)
    8. {
    9. itemText = text;
    10. }
    11.  
    12. QSize TextPainter::sizeHint() const
    13. {
    14. return PaintingScaleFactor * QSize(itemText.length()/2-2, 1);
    15. }
    16.  
    17. void TextPainter::paint(QPainter *painter, const QStyleOptionViewItem &option, EditMode mode) const
    18. {
    19. if (mode == Editable) {
    20. painter->setBrush(option.palette.highlight());
    21. } else {
    22. painter->setBrush(option.palette.foreground());
    23. }
    24.  
    25.  
    26. painter->save();
    27. doc.setHtml(itemText);
    28. QAbstractTextDocumentLayout::PaintContext context;
    29. doc.setPageSize( option.rect.size());
    30. painter->translate(option.rect.x(), option.rect.y()-20);
    31. doc.documentLayout()->draw(painter, context);
    32. painter->restore();
    33. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by jiveaxe; 3rd August 2007 at 15:46.
    Giuseppe CalÃ

  5. The following user says thank you to jiveaxe for this useful post:

    liuyanghejerry (26th August 2010)

  6. #5
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Word wrap in QListView

    I forgot main.cpp (maybe someone needs it):

    Qt Code:
    1. #include <QApplication>
    2. #include <QListWidget>
    3. #include <QStringList>
    4.  
    5. #include "textdelegate.h"
    6. #include "textpainter.h"
    7.  
    8.  
    9. int main(int argc, char *argv[])
    10. {
    11. QApplication app( argc, argv );
    12.  
    13. QListWidget listWidget;
    14. listWidget.setItemDelegate(new TextDelegate);
    15. listWidget.setAlternatingRowColors(true);
    16. listWidget.setResizeMode(QListWidget::Adjust);
    17.  
    18. list << "The <b>QListWidget</b> class provides an item-based list widget."
    19. << "The <b>QListWidgetItem</b> class provides an item for use with the QListWidget item view class."
    20. << "The <b>QObject</b> class is the base class of all Qt objects."
    21. << "Qt's <b>drag and drop</b> infrastructure is fully supported by the model/view framework. Items in lists, tables, and trees can be dragged within the views, and data can be imported and exported as MIME-encoded data.";
    22.  
    23. for (int row = 0; row < list.size(); ++row) {
    24. item->setData(0, qVariantFromValue(TextPainter(list.at(row))));
    25. listWidget.insertItem(row, item);
    26. }
    27.  
    28. listWidget.setWindowTitle(QObject::tr("Text Delegate"));
    29. listWidget.show();
    30.  
    31.  
    32. return app.exec();
    33. }
    To copy to clipboard, switch view to plain text mode 

    Bye
    Last edited by jacek; 4th August 2007 at 23:14. Reason: changed [html] to [code]
    Giuseppe CalÃ

  7. The following user says thank you to jiveaxe for this useful post:

    liuyanghejerry (26th August 2010)

  8. #6
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Word wrap in QListView

    I did not test the code yet, but I don't think it is a good idea to use the text layout like that.
    Anyway, keeping the code, I think you can compute the wrapped text bounding rect separately from the text layout.
    You should use QFontMetrics, just like in the other post, and compute the size hint height according to how many lines of text you have and the text height(also given by font metrics ).


    Regards

  9. #7
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Word wrap in QListView

    How can I get the number of lines?

    Thanks
    Giuseppe CalÃ

  10. #8
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Word wrap in QListView

    Have found numLines() in Q3MultiLineEdit; maybe switching from QTextDocument to it can help. What do you say?

    Bye

    Edit: Forgot this post, Q3MultiLineEdit is for QT3.
    Last edited by jiveaxe; 4th August 2007 at 17:49.
    Giuseppe CalÃ

  11. #9
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Word wrap in QListView

    Look how it is done in the other post!
    Generally, if the item rect is rW, and the unwrapped text width returned by font metrics tW.
    You have:
    Qt Code:
    1. float f = tW/rW;
    2. int approxLineCount = int(f) + 1;
    To copy to clipboard, switch view to plain text mode 
    approxLineCount tells you how many lines of text you approximately have. In the worst case it can give you one extra line, but never less than what you really have.

    To get the required height for the item, just multiply approxLineCount to the text height returned by the font metrics.

    Regards

  12. #10
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Word wrap in QListView

    Ok marcel; I try.

    Bye
    Giuseppe CalÃ

  13. #11
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Word wrap in QListView

    I have done some progresses, but have a problem retrieving the "item rect" (rW of marcel's last post); I tryed to get it with option.rect.width() but its value is zero and the application fault computing f. Here the new sizeHint:

    Qt Code:
    1. QSize TextPainter::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    2. {
    3. QFontMetrics fontMetrics = option.fontMetrics;
    4. QRect rect = fontMetrics.boundingRect(index.data().toString());
    5. float f = rect.width() / option.rect.width();
    6. int approxLineCount = int(f) + 1;
    7. return QSize(option.rect.width(), approxLineCount * fontMetrics.height());
    8. }
    To copy to clipboard, switch view to plain text mode 

    Regards
    Giuseppe CalÃ

  14. #12
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Word wrap in QListView

    You get a 0 width several times before the widget is actually displayed on the screen and the layout(if any) is set up.

    So you should test this and do nothing if you get 0.
    After the widget is properly initialized by the layout, any subsequent paint events will call your delegate's paint event and pass the correct item rect.

    Regards

Similar Threads

  1. QListView word wrap
    By serega in forum Qt Programming
    Replies: 17
    Last Post: 30th August 2007, 03:13

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.