QListWidgetItem check/uncheck
Hello,
I have a QListWidget with QAbstractItemView::ContiguousSelection and checkable items.
What I would like to do is to multiple select a couple of items and then check/uncheck them. Unfortunately, the selection of all items changes first and then the checkstate is updated (so I first recieve a selectionChanged and then a itemChanged).
Does anyone have a smart suggestion on how to change the behavior like this:
- If I hit the checkbox I don't want my selection state(s) to be changed
or (if not possible)
- If I do not hit the checkbox, I want my itemChanged event first and then a selectionChanged event
Regards,
Arthur
Re: QListWidgetItem check/uncheck
I think a common way to handle check state changes of multiple items is to provide an "external" widget for that purpose.
You could for example provide a checkbox (outside the list widget) and/or a context menu action for changing the checkstate of selected items.
Otherwise you might have to catch mouse click events (and possible some others too) to prevent the "view" to perform it's normal behaviour..
Re: QListWidgetItem check/uncheck
An external widget to check/uncheck all is of course handy, but what I want is multiple uncheck/check when I have items selected. I couldn't find a way of fixing this (I can't even find a checkbox widget based on mouseclick coordinates).
Is there someone who can help me out?
Re: QListWidgetItem check/uncheck
Quote:
Originally Posted by Arthur
Unfortunately, the selection of all items changes first and then the checkstate is updated (so I first recieve a selectionChanged and then a itemChanged).
Did you notice that item selection is changed due to mouse press events and the check state is not changed until mouse release events..?
Anyhow, as I mentioned in the earlier post, you have to catch certain mouse events in order to prevent the view from acting like it normally does.
Try these steps to solve the problem:
- Override both, mousePressEvent and mouseReleaseEvent. Basically you want to handle these events always when they occur over an item's checkbox, and otherwise pass them over to the base class to handle it's contiguous selection.
- Whenever a mouse press event (or release event, whichever you prefer) occurs over an item's checkbox, change the check state of all selected items.
The hardest part might be calculating whether a mouse press/release event's position is inside an item's checkbox. You can use QStyle for that.
This is just for reference:
Code:
#include <QApplication>
#include <QListWidget>
#include <QListWidgetItem>
#include <QMouseEvent>
#include <QStyle>
#include <QStyleOptionViewItem>
#include <QStyleOptionButton>
{
public:
{
// contiguous selection mode
// add some dummy checkable example items
for (int i = 0; i < 10; ++i)
{
item->setCheckState(Qt::Unchecked);
addItem(item);
}
}
protected:
{
if (item)
{
// mouse pressed over a selected items checkbox,
// change the check states of all selected items
setSelectedCheckStates(item->checkState() == Qt::Checked ? Qt::Unchecked : Qt::Checked);
}
else
{
// otherwise let the base class handle mouse press
}
}
{
// do nothing if mouse released over a selected items checkbox
if (!selectedCheckStateItem(event->pos()))
{
// otherwise let the base class handle mouse release
}
}
private:
// returns the selected item whose checkbox lies under 'pos'
// returns 0 if not selected, no item at pos, or does not fit inside checkbox
{
if (item)
{
// with the help of styles, check if checkbox rect contains 'pos'
opt.rect = visualItemRect(item);
QRect r
= style
()->subElementRect
(QStyle::SE_ViewItemCheckIndicator,
&opt
);
// assure that the item is also selected
if (selectedItems().contains(item) && r.contains(pos))
{
return item;
}
}
return 0;
}
// sets the check state of all selected items to 'checkState'
void setSelectedCheckStates(Qt::CheckState checkState)
{
item->setCheckState(checkState);
}
};
int main(int argc, char *argv[])
{
ListWidget w;
w.show();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
return a.exec();
}
Re: QListWidgetItem check/uncheck
Thanks, I spent hours on finding out how to determine the click was in a checkbox (I hoped that I could get a 'child' widget from a certain position in the QListView...)
I'll check out your code!
Re: QListWidgetItem check/uncheck
Wouldn't it be easier to use an external widget as suggested and when it is activated, check the selection of the list widget and mark all selected items as checked?
It should be as easy as:
Code:
void someClass::someSlot(){
item->setCheckedState(Qt::Checked);
}
Re: QListWidgetItem check/uncheck