PDA

View Full Version : ListView and CurrentChanged



kroenecker
22nd March 2007, 21:32
I'm using a listview with a custom made model where the items in the listview are delegates.

I can't seem to get clicking on the list view to trigger selection changed. It looks like its because the delegate uses a label to render the information.

Here are some code bits:

This is the paint function in the delegate. The viewPtr is defined elsewhere and is a pointer to the view.



void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
painter->save();

std::cout << "Row: " << index.row() << std::endl;

if(viewPtr->indexWidget(index) == NULL)
{
QLabel *label = new QLabel();
Data *data = qVariantValue<Data*>(index.data(Qt::DisplayRole));
QString displayValue = data->displayValue();
label->setAutoFillBackground(true);
label->setWordWrap(true);
label->setText(displayValue);


if(option.state & QStyle::State_Selected)
{
//painter->fillRect(option.rect, option.palette.highlight());
label->setPalette(option.palette);
label->setBackgroundRole(QPalette::Highlight);
viewPtr->setIndexWidget(index, label);
QItemDelegate::paint(painter, option, index);
}
else
{
if(index.row() & 1)
{
//painter->fillRect(option.rect, QBrush(QColor("#c0c0c0")));
QPalette p;
p.setBrush(QPalette::Background, QBrush(QColor("#c0c0c0")));
label->setPalette(p);
label->setBackgroundRole(QPalette::Background);
viewPtr->setIndexWidget(index, label);
}
else
{
//painter->fillRect(option.rect, QBrush(QColor("#dddddd")));
QPalette p;
p.setBrush(QPalette::Background, QBrush(QColor("#dddddd")));
label->setPalette(p);
label->setBackgroundRole(QPalette::Background);
viewPtr->setIndexWidget(index, label);
}
QItemDelegate::paint(painter, option, index);
}
}
painter->restore();
}


I've tried the following to no avail:



MyDelegate delegate;
delegate.setViewPointer(window->listView);
window->listView->setItemDelegate(&delegate);
QObject::connect(window->listView, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
&delegate, SLOT(selected(const QModelIndex &current, const QModelIndex &)));


The delegate class has a selected slot that I've defined.

Where am I going wrong? The above code works if I'm not using a label...

jacek
22nd March 2007, 22:09
You create your delegate on the stack, so it goes out of scope immediately. As for the label, try installing an event filter to catch the mouse click.

kroenecker
23rd March 2007, 18:26
The creation of my delegate is in the main function. That may not be the best place to declare the object, but that's how I'm doing it right now.

I will take a look event filters. Thanks Jacek.

jacek
23rd March 2007, 18:56
The creation of my delegate is in the main function. That may not be the best place to declare the object, but that's how I'm doing it right now.
If it's in main(), then it doesn't matter how you create it.

kroenecker
23rd March 2007, 21:14
This makes me wonder:

If you use a delegate in a model that displays a custom widget, where is the click event handled? By the delegate? By the widget? By the view?

This is rather ambiguous to me.

If the model handles it then I would think that simple connecting the signals as I did would solve the problem. However, nothing seems to happen.

jacek
23rd March 2007, 21:31
If you use a delegate in a model that displays a custom widget, where is the click event handled? By the delegate? By the widget? By the view?
If you show a widget in a cell, then most likely you want it to behave normally (i.e. just as if it was shown in some other place) and since you can't tell what events such arbitrary widget needs to process, the simpliest solution would be to make it handle all possible events.

kroenecker
23rd March 2007, 21:39
Well I created a custom label that derives from QLabel and that successfully intercepts the mouse click event, but I have no idea how to tell the view that it now needs to select that particular item.

kroenecker
23rd March 2007, 21:53
I thought about changing the labels background color, but then multiple backgrounds would be changed over time. I only want one item to be selected at a time.

Trying to figure this stuff out is extremely time consuming.

jacek
23rd March 2007, 21:57
but I have no idea how to tell the view that it now needs to select that particular item.
Maybe through QItemSelectionModel?

kroenecker
23rd March 2007, 22:22
Well I've been passing pointers around like crazy....

The labels have pointers to the modelindexes that they display. They also have pointers to the view. When clicking on the labels, the mousePressEvent is called. In the event I can use the view's pointer to call the selection model and set the current label's index as the selected item. This, however, changes nothing in the delegates paint event. I can call the selection model in the paint event and it doesn't see the index as being selected.

How weird and utterly annoying is that?

Why am I always butchering this Model/View stuff? Oh yeah, it's because there isn't any good documentation for it :{

kroenecker
23rd March 2007, 22:24
By the way I do appreciate your help. I'm just trying to vent a little. As much as I love open source stuff, I'm always hitting roadblocks like this.... :P Must be me :mad:

jacek
23rd March 2007, 23:26
The labels have pointers to the modelindexes that they display.
Well... I should have asked it in the first place, but what do you need those labels for?

kroenecker
24th March 2007, 02:21
Jacek,

Well I wanted to be able to populate a listview with information that is rendered as rich-text.

I guess I just don't understand how all these different parts intersect.

Like I said above, if I don't use labels, I can simply populate each item in the view with text using painter->setText(*params*) and, in that case, selecting works just fine. I just don't understand why the label event handler shows that an item is selected (it's in the event handler that I use the selection model to select items in the view), but in the


void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const


call none of the items show up as being selected. In both instances I'm using what I would assume is the same pointer to the same selectionModel. I guess that somewhere along the line the selectionModel's values are being changed. Oh well, I just don't get it.

If I can get the text to wrap in the paint call, then I guess I don't need to use a label.

kroenecker
24th March 2007, 02:35
To answer my own question it looks like I can set that sort of thing with the text displayed by paint... Silly me :p