PDA

View Full Version : [solved]QListView dynamic item height



kernel_panic
18th February 2009, 18:02
Hi all,
im trying to implement a listview with model and delegate which items should resize dynamicaly.
for example if i press an item and its selected the height should be 2*normal height.
i tried to reimplement sizeHint of QItemDelegate, but the sizeHint isnt catched dynamically. it seems its only used on initialising the view.
I found no methods in QAbstractItemModel or QItemDelegate or QListView that could handle this.
Any suggestions?

Lykurg
19th February 2009, 10:46
Hi kernel_panic,

how do you solved it? I only know the trick with a QTreeWidget...

Please can you provide some/the relevant code?


Thanks

kernel_panic
26th February 2009, 22:29
Hey folks!
Heres a small example.
The trick is simply this:

const void wantsUpdate(){emit layoutChanged();}
and


mutable int currentIndex;
void DirObjectDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (option.state & QStyle::State_Selected)
{
int moi = index.row();
if(moi != currentIndex)
{
PodModel *mymodel = const_cast<PodModel*>(dynamic_cast<const PodModel*>(index.model()));
currentIndex = moi;
mymodel->wantsUpdate();
}
}
.....
}
QSize DirObjectDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
QSize s;
s = QSize(option.decorationSize.width(), option.decorationSize.height());
if(currentIndex == index.row())
{
s.setHeight(option.decorationSize.height()*2);
}
return s;
}
If you have questions to the code PM me!
Good luck!

Lykurg
26th February 2009, 23:00
Great! Thanks, had a short look and it worked fine.
I'll try tomorrow to get it transformed into my needs... (A simple standard QListWidget with custom non editable items, which have different heights when selected of course...)

Once again thank you very much.

Lykurg

aamer4yu
2nd March 2009, 10:58
Hi Lykurg...
Did you find any solution ? I was also trying similar thing with QListWidget... but there are many issues,,, Qt doesnt split text if space is not there.
Even if you manage to explicitly insert a space, the are is clipped to option.rect . Again if you dont clip it, all text will be displayed, but the extra area wont be updated.

if your problems are same, may be we can find a solution. I have so far limited my display lines to 2 rows... atleast I get to see extra text than in one line.

Lykurg
3rd March 2009, 19:52
Hi,

unfortunately I currently don't have not much time (because I am abroad and I am about to learn a new language without any knowledge of it...(and in a country where the people neither speak my language nor English, it isn't fun!)), so my "scientific" interest are cut down.

For the issue with the item height, I currently go the same way as kernel_panic with a model and delegate. But I am still not done. Problems are:
- definitely calculate the new item height when selected, which varies for each item. (Here's the problem with the text. I guess QFontMetrics must help.)
- reduce repainting (Because this time every selection change causes an repaint of all items, not only the visible)

So long, if I see clearer I will post. Maybe it would be good if we open a wiki page for that.


Lykurg

aamer4yu
4th March 2009, 06:00
With model and delegate it can me done as kernel panic suggested...
but with listwidget you cant have your own model :(
Also i was searching way which wud merge with Qt's flow...like all decoration position and icon sizes are taken into consideration.
Even with kernel panics code, text is not displayed in icon mode, thought the wantsUpdate trick can still be used.
But I dont want to do ALL the drawing myself,,, just specify rects properly and let Qt do the rest ;)

neways njoy ur trip,,, when u come back u can reply back :)

Lykurg
17th March 2009, 14:51
Hi,

I have played with the code and added to my view an "QSortFilterProxyModel". so I have changed the paint method as follow:
QSortFilterProxyModel *proxymodel = const_cast<QSortFilterProxyModel*> (dynamic_cast<const QSortFilterProxyModel*> (index.model()));
PodModel *mymodel = const_cast<PodModel*> (dynamic_cast<const PodModel*> (proxymodel ? proxymodel->sourceModel() : index.model()));
but when calling mymodel->wantsUpdate(); the application crashes:

Thread [1] (Suspended: Signal 'SIGSEGV' received. Description: Segmentation fault.)
36 QSortFilterProxyModel :: parent() /qt/qtsdk-2009.01/qt/src/corelib/kernel/qabstractitemmodel.h:65 0xb6ba3372
35 QListView :: rectForIndex() /qt/qtsdk-2009.01/qt/src/corelib/kernel/qabstractitemmodel.h:369 0xb6b40db0
34 QListView :: visualRect() /qt/qtsdk-2009.01/qt/src/gui/itemviews/qlistview.cpp:576 0xb6b43a4a
33 QListView :: paintEvent() /qt/qtsdk-2009.01/qt/src/gui/itemviews/qlistview.cpp:1128 0xb6b3dff5
32 QWidget :: event() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:7654 0xb65e061a
31 QFrame :: event() /qt/qtsdk-2009.01/qt/src/gui/widgets/qframe.cpp:559 0xb69da4f3
30 QAbstractScrollArea :: viewportEvent() /qt/qtsdk-2009.01/qt/src/gui/widgets/qabstractscrollarea.cpp:962 0xb6a75f3c
29 QAbstractItemView :: viewportEvent() /qt/qtsdk-2009.01/qt/src/gui/itemviews/qabstractitemview.cpp:1466 0xb6b226d3
28 QAbstractScrollAreaFilter :: eventFilter() /qt/qtsdk-2009.01/qt/src/gui/widgets/qabstractscrollarea_p.h:100 0xb6a77ec5
27 QCoreApplicationPrivate :: sendThroughObjectEventFilters() /qt/qtsdk-2009.01/qt/src/corelib/kernel/qcoreapplication.cpp:718 0xb6008d09
26 QApplicationPrivate :: notify_helper() /qt/qtsdk-2009.01/qt/src/gui/kernel/qapplication.cpp:4080 0xb6584a59
25 QApplication :: notify() /qt/qtsdk-2009.01/qt/src/gui/kernel/qapplication.cpp:4049 0xb65887be
24 QCoreApplication :: notifyInternal() /qt/qtsdk-2009.01/qt/src/corelib/kernel/qcoreapplication.cpp:602 0xb600881b
23 QWidgetPrivate :: drawWidget() /qt/qtsdk-2009.01/qt/src/corelib/kernel/qcoreapplication.h:216 0xb65d7d82
22 QWidgetPrivate :: paintSiblingsRecursive() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5156 0xb65d8549
21 QWidgetPrivate :: paintSiblingsRecursive() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5147 0xb65d8444
20 QWidgetPrivate :: drawWidget() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5095 0xb65d790a
19 QWidgetPrivate :: paintSiblingsRecursive() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5156 0xb65d8549
18 QWidgetPrivate :: paintSiblingsRecursive() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5147 0xb65d8444
17 QWidgetPrivate :: drawWidget() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5095 0xb65d790a
16 QWidgetPrivate :: paintSiblingsRecursive() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5156 0xb65d8549
15 QWidgetPrivate :: drawWidget() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5095 0xb65d790a
14 QWidgetPrivate :: paintSiblingsRecursive() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5156 0xb65d8549
13 QWidgetPrivate :: drawWidget() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5095 0xb65d790a
12 QWidgetPrivate :: paintSiblingsRecursive() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5156 0xb65d8549
11 QWidgetPrivate :: paintSiblingsRecursive() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5147 0xb65d8444
10 QWidgetPrivate :: paintSiblingsRecursive() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5147 0xb65d8444
9 QWidgetPrivate :: paintSiblingsRecursive() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5147 0xb65d8444
8 QWidgetPrivate :: drawWidget() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:5095 0xb65d790a
7 QWidgetBackingStore :: sync() /qt/qtsdk-2009.01/qt/src/gui/painting/qbackingstore.cpp:1266 0xb67ac0b7
6 QWidgetPrivate :: syncBackingStore() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget.cpp:1603 0xb65d02b5
5 QETWidget :: translateConfigEvent() /qt/qtsdk-2009.01/qt/src/gui/kernel/qapplication_x11.cpp:5291 0xb65e8c14
4 QApplication :: x11ProcessEvent() /qt/qtsdk-2009.01/qt/src/gui/kernel/qapplication_x11.cpp:3448 0xb65f5db8
3 qt_x11_wait_for_window_manager() /qt/qtsdk-2009.01/qt/src/gui/kernel/qwidget_x11.cpp:356 0xb660f162
2 QSplashScreen :: finish() /qt/qtsdk-2009.01/qt/src/gui/widgets/qsplashscreen.cpp:226 0xb6a41d71
1 main() /home/lykurg/workspace/RMEingabe/src/main.cpp:43 0x0806a890

Why, I dont understand it?

Thanks Lykurg

EDIT: it's in "inline QModelIndex::QModelIndex(const QModelIndex &other) : r(other.r), c(other.c), p(other.p), m(other.m) {}"

Lykurg
17th March 2009, 15:05
Damn, the solution comes always after posting :mad:



currentIndex = moi;
SortFilterBibtexModel *proxymodel = const_cast<SortFilterBibtexModel*> (dynamic_cast<const SortFilterBibtexModel*> (index.model()));
if (proxymodel)
proxymodel->wantsUpdate();
else
{
BibtexModel *mymodel = const_cast<BibtexModel*> (dynamic_cast<const BibtexModel*> (proxymodel ? proxymodel->sourceModel() : index.model()));
mymodel->wantsUpdate();
}

where BibtexModel is a subclass of QAbstractListModel and SortFilterBibtexModel of QSortFilterProxyModel. SortFilterBibtexModel has a
void wantsUpdate()
{
emit layoutChanged();
}

So long...