Results 1 to 14 of 14

Thread: How to make QListView consume the space when rows decrease in height on h-resize?

  1. #1
    Join Date
    Dec 2014
    Posts
    10
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default How to make QListView consume the space when rows decrease in height on h-resize?

    I have a QListView working with a custom model and a custom delegate, mainly for displaying two strings of word-wrapped text vertically on top of each other as one item.
    I've reimplemented QStyledItemDelegate::sizeHint() and everything seems to work fine.

    Except:
    1) When I resize the QListView horizontally so its width increases, the height of the individual items should shrink (due to word-wrapping). I know my delegate reports decreasing heights via its sizeHint().
    2) But somehow the view doesn't seem to "get" the items' new heights internally, which leads to gaps between the rows/items i. e. the next item is drawn further down than necessary.


    3) When I decrease the width of the widget my QListView is in the individual items' height increases. No problem with that.
    4) It only happens on horizontal resize. As soon as I vertically resize the window/widget QListView is in, all rows just "snap" into place.
    5) Similarly, as soon as my model emits a dataChanged() signal for a row with a height too large, it just snaps into place.
    6) I do call QListView::setResizeMode(QListView::Adjust);
    7) I'm using Qt 4.8.1.

    Am I missing something? Do I need to hack around this?
    Last edited by JmpNop; 20th December 2014 at 13:55.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    Quote Originally Posted by JmpNop View Post
    1) When I resize the QListView horizontally so its width increases, the height of the individual items should shrink (due to word-wrapping). I know my delegate reports decreasing heights via its sizeHint().
    Do you emit sizeHintChanged() signal to inform about the change? Without it the view will not know it needs to read the sizeHint again.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Dec 2014
    Posts
    10
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    Ah, thank you! No, I don't.
    How is the delegate supposed to know about changed sizes when sizeHint() isn't even called though?
    Where is it supposed to emit this signal?

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    Quote Originally Posted by JmpNop View Post
    How is the delegate supposed to know about changed sizes when sizeHint() isn't even called though?
    Where is it supposed to emit this signal?
    You need to implement it yourself. You can install an event filter on the view's viewport to be notified when it is resized. Then the delegate can emit signals for items that need updating.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Dec 2014
    Posts
    10
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    What I'd have to do after connecting the view's resize event to the delegate is basically to emit sizeHintChanged signals for the whole of my model. That just doesn't appear to be the "right" way to do it, does it?
    After all, the cause for the update is completely "external", not something in the data itself (which is what I think that the delegate's sizeHintChanged signal is probably intended for).

    Isn't there a way to just tell the view to recalculate its items' sizes? It works for 'growing' items already... Maybe I could try to simulate a model-reset with saving/restoring the view's selection-state if there isn't a "best practice way"? All of this seems to be rather hackish though. It thought there has to be a "clean" way to do it...

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    Quote Originally Posted by JmpNop View Post
    What I'd have to do after connecting the view's resize event to the delegate is basically to emit sizeHintChanged signals for the whole of my model.
    No, just for the visible items and only if their height changes. If an item already fits a single line, increasing the width of the item will not influence its height. Same goes the other way -- it seems logical to limit the maximum height of an item.

    After all, the cause for the update is completely "external", not something in the data itself
    The cause for the update is the way you want each item displayed which is the responsibility of the delegate (or the view, depending how you look at it). If data was changing, you'd emit dataChanged().

    Isn't there a way to just tell the view to recalculate its items' sizes?
    Yes. Emit sizeHintChanged() from the delegate. Alternatively reimplement visualRect() in the view and force an update of the whole viewport.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Dec 2014
    Posts
    10
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    No, just for the visible items and only if their height changes.
    I'd have to keep track of all the items' heights in the delegate then...

    I've found a simpler, but hackish solution:
    http://doc.qt.io/qt-4.8/qlistview.html#spacing-prop
    Setting this property when the view is visible will cause the items to be laid out again.
    The event filter object that catches resize events for the view's viewport is connected to a slot that calls setSpacing(0) on the view.
    Now it 'works' ...

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    Quote Originally Posted by JmpNop View Post
    I'd have to keep track of all the items' heights in the delegate then...
    In the resize event you have access to both the old and the new size. Using those values it should be easy to decide whether the span changes or not.

    I've found a simpler, but hackish solution:
    http://doc.qt.io/qt-4.8/qlistview.html#spacing-prop
    Kind of not-so-very-performant solution.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. #9
    Join Date
    Dec 2014
    Posts
    10
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    You are right of course.
    Since I need to display some richtext im my items, I'm now creating a QTextDocument on the stack for every sizeHint and paint of my delegate. That's really ugly.
    How would I go about caching the visible items (rows)?

    My solution would be to get a list from the view via indexAt and visualRect that is updated on every view-scrollbar-change. Than I could cache the data in the delegate and provide sizeHints and sizeHintChanged signals from there. Maybe with a hashtable row -> struct CacheData or something like that... Data for items that cease to be visible would be destroyed after some period.
    Do you have any suggestions or comments?
    Thank you for your help so far.

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    When using linear data in general QContignousCache is your friend. If you want a cache of QTextDocuments (or whatever else you need) for your items in the delegate, go ahead. I never tried this and I'm very interested about the resulting performance of such approach. It might not be a bad idea. When I was implementing a rich text delegate, I was reusing a single document for different items.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #11
    Join Date
    Dec 2014
    Posts
    10
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    A single QTextDocument is probably not an option, since I suspect all the HTML /CSS parsing to be quite slow. I didn't measure anyhing yet, though. Still busy with other stuff. Richtext is not my friend. ^^
    Have a happy new year

  12. #12
    Join Date
    Dec 2014
    Posts
    10
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    Since I had the same problem (rows' heights) with a QTreeView now, I did some digging through Qt's source code.
    Look what I've found:
    Qt Code:
    1. .../qtbase/src/widgets/itemviews$ grep -n sizeHintChanged *
    2. qabstractitemdelegate.cpp:163: \fn void QAbstractItemDelegate::sizeHintChanged(const QModelIndex &index)
    3. qabstractitemdelegate.h:120: void sizeHintChanged(const QModelIndex &);
    4. qabstractitemview.cpp:834: disconnect(d->itemDelegate, SIGNAL(sizeHintChanged(QModelIndex)), this, SLOT(doItemsLayout()));
    5. qabstractitemview.cpp:843: connect(delegate, SIGNAL(sizeHintChanged(QModelIndex)), this, SLOT(doItemsLayout()), Qt::QueuedConnection);
    To copy to clipboard, switch view to plain text mode 
    That's all. See how the QModelIndex that is passed to sizeHintChanged is ignored? Any sizeHintChanged signal just triggers a relayout.
    Even more interesting is the doItemsLayout() slot. It is public and available in all of Qt's item view widgets, but it is not documented. That's exactly what I was looking for
    Someone asked if he could rely on that on another forum a few years ago. So I'm going to repeat the question here.

  13. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    If it is undocumented and not a virtual method then you cannot expect the method to work in future Qt releases. Of course it is unlikely that it goes away until Qt 6.0.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  14. #14
    Join Date
    Dec 2014
    Posts
    10
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to make QListView consume the space when rows decrease in height on h-resize?

    It's virtual. From qabstractitemview.h:
    Qt Code:
    1. public Q_SLOTS:
    2. virtual void reset();
    3. virtual void setRootIndex(const QModelIndex &index);
    4. virtual void doItemsLayout();
    5. virtual void selectAll();
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. How to add space b/w column and rows of gridlayout.
    By Niamita in forum Qt Programming
    Replies: 3
    Last Post: 8th July 2011, 07:55
  2. QCalendarWidget - height rows
    By pease in forum Qt Programming
    Replies: 1
    Last Post: 15th April 2010, 17:31
  3. How to set rows of QtableWidget to the same height?
    By sawerset in forum Qt Programming
    Replies: 3
    Last Post: 7th December 2008, 18:09
  4. Height of the text without balnk space at the top
    By THRESHE in forum Qt Programming
    Replies: 6
    Last Post: 19th March 2008, 13:33
  5. Replies: 2
    Last Post: 22nd January 2008, 16:10

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.