Model View - Delegate - setIndexWidget
Hi,
I tried to use the setIndexWidget() function in my MV GUI Qt Code.
I just want to have a simple composed widget in my subclass instance of QTableView, an widget inside an table cell.
Do you have any ideas or better code examples, how to use this function in the right way ? Trolltechs API docu does not explain, how to use this function in Qt's Model-View architecture. As is read before, the best way would be to use this in the delagate (with some dirty tricks), here you find some threads too, which describe my problem best:
http://lists.trolltech.com/qt-intere...ad00097-0.html
http://lists.trolltech.com/qt-intere...ad00550-0.html
Kind regards,
Alex
Re: Model View - Delegate - setIndexWidget
Index widgets are not actually part of the MVC concept but they are additional widgets laid on top of items in the view. They are expensive to maintain and one should avoid them. What kind of widgets would you like to put there?
Re: Model View - Delegate - setIndexWidget
I want to provide widgets in table cells, which consist of some text labels, some icons and an text edit field(date field), perhaps similar to the graphical interface of outlook calender...
Can you help me how to proceed ?
Re: Model View - Delegate - setIndexWidget
As for icons and text the default delegate should handle it fine. As for text edit fields - you'll be only editing one field at a time, so a slightly modified delegate returning a QTextEdit instance as the editor should be enough.
Re: Model View - Delegate - setIndexWidget
Do you mean, I have to use the different roles in my custom model to let the default delegate render the cells content ?
I tried to do so, but what made me first think of to try an different way, was, that with the decoration role I only could render one icon.
I am also not sure, would it be possible to have drag and drop support, if I implement the cells content in this way ?
Re: Model View - Delegate - setIndexWidget
Quote:
Originally Posted by
starcontrol
Do you mean, I have to use the different roles in my custom model to let the default delegate render the cells content ?
Yes, that's correct.
Quote:
I tried to do so, but what made me first think of to try an different way, was, that with the decoration role I only could render one icon.
If you want something non-standard, use a custom delegate. You'll be able to render whatever you want depending on the data contained in an item.
Quote:
I am also not sure, would it be possible to have drag and drop support, if I implement the cells content in this way ?
Yes, itemviews support d&d.
Re: Model View - Delegate - setIndexWidget
So I have to implement the delegates paint() function to render my widget ?
Do I have to paint my icons, text labels, editor fields ? There must be an way, instead "manually painting" the widgets, or ?
A second wish:
I have to create spans inside my table view, these spans will have to contain what I described before. The QTableView has an method setSpan(), but how can I check in my custom view from my custom model, where it has to paint the spans?
Re: Model View - Delegate - setIndexWidget
Quote:
Originally Posted by
starcontrol
So I have to implement the delegates paint() function to render my widget ?
Not widget, but item - yes.
Quote:
Do I have to paint my icons, text labels, editor fields ?
You only paint the inactive state. In the editing state the delegate returns a real widget.
Quote:
There must be an way, instead "manually painting" the widgets, or ?
I think you have to define what you mean by "widget". Icon is not a widget. Text is not a widget. So, what is a widget according to your definition?
Quote:
I have to create spans inside my table view, these spans will have to contain what I described before. The QTableView has an method setSpan(), but how can I check in my custom view from my custom model, where it has to paint the spans?
Why should the model care about the span? It's just a set of data.
Re: Model View - Delegate - setIndexWidget
I think "manually painting" the items may not be the succeeding way. If I'll use the delegates paint method, I have a simple bitmap, which is rendered inside the table view cell (in my case, inside the span). If the span will be very long, because of an longer event (calender event) the bitmap will be strechted and the text will be rendered not clean, you understand what I mean ?
The second problem is, the item will also have to contain an "active text edit field (date edit field for editing the event)" in the inactive state, how will this be possible with an rendered bitmap ?
Kind regards,
Alex
Re: Model View - Delegate - setIndexWidget
Quote:
Originally Posted by
starcontrol
If the span will be very long, because of an longer event (calender event) the bitmap will be strechted and the text will be rendered not clean, you understand what I mean ?
The model doesn't care. It doesn't have a concept of width or height. The delegate handles all that and it is given the rectangle that needs to be painted.
Quote:
The second problem is, the item will also have to contain an "active text edit field (date edit field for editing the event)" in the inactive state, how will this be possible with an rendered bitmap ?
Render the date as text and react on clicking the cell - activate the editor and let the user edit the date. You don't need the spinbox to be active all the time. You can even render the looks of the box if you really need to.
Re: Model View - Delegate - setIndexWidget
Ok, I tried your suggestion..., but nothing is displayed in my table cells, do you know, what I am doing wrong ? How do I have to implement the sizeHint() function ?
Code:
void SchulungsplanDelegate
::paint(QPainter* painter,
const QStyleOptionViewItem
& option,
const QModelIndex &index
) {
painter->save();
if (option.
state & QStyle::State_Active) painter->fillRect(option.rect, option.palette.highlight());
// gets the cells size and draws the text inside
QRect myRect
= QRect(option.
rect.
topLeft(), option.
rect.
bottomRight()) ;
painter->drawText(myRect, Qt::AlignCenter, "test");
painter->restore();
}
/*
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index ) const
{
// ????????????
}
Re: Model View - Delegate - setIndexWidget
The signature doesn't match. QAbstractItemDelegate::paint() is a const method. So in fact you're not reimplementing but shadowing the function.
Re: Model View - Delegate - setIndexWidget
ok, thanks a lot ! ;-)
Now it paints right... My second approach is, to paint an widget inside the table cell by grabbing the widget to an pixmap. This experiment seems to function, but the widget is VERY small inside the cell and you can only see the picture, if you resize the cell to a very, very large cell. I don't know why. The delegates painter got the right size of the cell.
painter->drawPixmap(option.rect, courseItem);
Do you know what I have to do ?
Code:
void SchulungsplanDelegate
::paint(QPainter* painter,
const QStyleOptionViewItem
& option,
const QModelIndex &index
) const {
if (index.column() == 3 && index.row() == 2)
{
painter->save();
if (option.
state & QStyle::State_Active) painter
->fillRect
(option.
rect,
QBrush(QColor(Qt
::darkGreen), Qt
::SolidPattern));
painter
->setPen
(QColor(Qt
::white));
painter->drawText(option.rect, Qt::AlignCenter, " 060505K1 8 von 01.01.2008 bis 10.01.2008 ");
// painter->drawPixmap(option.rect, QPixmap("arrowOpen.png"));
painter->restore();
}
if (index.column() == 1 && index.row() == 1)
{
painter->save();
painter->drawPixmap(option.rect, courseItem);
painter->restore();
}
}
Re: Model View - Delegate - setIndexWidget
You might not want to allocate a QLabel like that during every call to paint(). First of all, currently it's leaking memory quite a bit because those labels allocated during every paint event are never deleted. Secondly, the geometry of a widget is calculated upon first time shown so you should call something like QWidget::adjustSize() or QWidget::ensurePolished() first. But anyway, what's the point of doing so expensive operations such as constructing a label with text and taking a screenshot of it when you could just paint the text with QPainter?
Re: Model View - Delegate - setIndexWidget
ups, that's right, obviously it is much more performant to render the items manually, but I thought, it'll be easier for me to implement, because so I only need to create a simple widget and let this paint. I need to fill the table cells with some text and some icons, so I don't know how to get the icons on the right side of the cell, beside the text information.
The item (cell) has to be like this "abstract graphic":
Course 4711 From: 01.01.2008 To: 10.01.2008 ICON1 ICON2
Sometimes there has to be one icon, sometimes two. So I think I have to calculate some space to render between the text and the icon. Do you have any idea how to solve this ?
I think, it will go in this direction, or ?:
/*
QPoint iconStart = ... end of text
QPoint iconEnd = ... end of cell ???
QRect iconsRect = ...
painter->drawPixmap(iconsRect, QPixmap("test.png"));
*/
Re: Model View - Delegate - setIndexWidget
I think, i will have to devide the cell into two or more rectangles and paint into the devided new rectangles, perhaps like this:
Code:
void SchulungsplanDelegate
::paint(QPainter* painter,
const QStyleOptionViewItem
& option,
const QModelIndex &index
) const {
if (index.column() == 3 && index.row() == 2)
{
painter->save();
if (option.
state & QStyle::State_Active) painter
->fillRect
(option.
rect,
QBrush(QColor(Qt
::darkGreen), Qt
::SolidPattern));
if (option.
state & QStyle::State_Selected) painter
->fillRect
(option.
rect,
QBrush(QColor(Qt
::red), Qt
::SolidPattern));
QPoint(option.
rect->center
()->x
(), option.
rect->bottomLeft
()->y
()));
QRect rect2
= QRect(QPoint(option.
rect->center
()->x
(), option.
rect->topRight
->y
()),
option.rect->bottomRight());
painter
->setPen
(QColor(Qt
::white));
painter->drawText(rect1, Qt::AlignCenter, " RECT1 ");
painter
->setPen
(QColor(Qt
::yellow));
painter->drawText(rect2, Qt::AlignCenter, " RECT2 ");
/*
QPoint iconStart = ... end of text
QPoint iconEnd = ... end of cell ???
QRect iconsRect = ...
painter->drawPixmap(iconsRect, QPixmap("test.png"));
*/
painter->restore();
}
Re: Model View - Delegate - setIndexWidget
Yes, that's basically how QItemDelegate does it too. It divides to whole area to sub-areas for possible icon, checkbox, text etc. QRect should have enough helpful methods for the calculation and QStyle::alignedRect() might also become handy especially if you have to take both layout directions into consideration.