PDA

View Full Version : QListWidget back to previous item in currentItemChanged



laszlo.gosztola
12th May 2012, 03:21
Hi all,

I found an interesting problem. I use a QListWidget for selection between items. I would like to ask the user if he is sure to change the current item. My plan is to use the currentItemChanged signal of the QListWidget, because it has the previous item pointer.

Sample code:

#include "mainwidget.h"

#include <QListWidget>
#include <QGridLayout>

#include <QMessageBox>
#include <QTimer>

MainWidget::MainWidget(QWidget *parent) : QWidget(parent)
{
list = new QListWidget(this);

QGridLayout* mainLayout = new QGridLayout();
mainLayout->addWidget(list);
setLayout(mainLayout);

list->addItem("Item1");
list->addItem("Item2");
list->addItem("Item3");
list->addItem("Item4");

connect(list, SIGNAL(currentItemChanged(QListWidgetItem*,QListWi dgetItem*)), this, SLOT(currentItemChanged(QListWidgetItem*,QListWidg etItem*)));
}

MainWidget::~MainWidget()
{
delete list;
}

void MainWidget::currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
qDebug("CurrentItemChanged - Index: %d", list->row(current));
if ( list->row(current) == currentRow )
{
return;
}
if ( QMessageBox::No == QMessageBox::question(this, "Question", "Really want to change?", QMessageBox::Yes | QMessageBox::No) )
{
//TODO: change back to the previous item
list->setCurrentItem(previous);
}
}

That was my first idea, but of course it asks again the question, so I tried to temporally disable signals


if ( QMessageBox::No == QMessageBox::question(this, "Question", "Really want to change?", QMessageBox::Yes | QMessageBox::No) )
{
//TODO: change back to the previous item
list->blockSignals(true);
list->setCurrentItem(previous);
list->blockSignals(false);
}

The problem with this is that the current item changes back to the previous item, but the selection not and I don't really understand this behaviour.
For a workaround, I have this solution, but I think it's not very elegant.


void MainWidget::currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
qDebug("CurrentItemChanged - Index: %d", list->row(current));
if ( list->row(current) == currentRow )
{
return;
}
if ( QMessageBox::No == QMessageBox::question(this, "Question", "Really want to change?", QMessageBox::Yes | QMessageBox::No) )
{
//TODO: change back to the previous item
QTimer::singleShot(0, this, SLOT(goBack()));
}else
{
currentRow = list->row(current);
}
}

void MainWidget::goBack()
{
qDebug("GoBack: %d", currentRow);
list->setCurrentRow(currentRow);
}


Do You have any explanation why this workaround works, and why the selection doesn't go back if I call it from the slot directly? Is it normal? Do You have any idea for a more elegant solution?

Thanks!

Spitfire
14th May 2012, 16:34
You need to update selection model as well and because you block the signals model doesn't get updated.

Anyway, another solution could be to install event filter on the List widget, and capture mouse release or key up/down (whatever lets you change current item).
There you can show your dialog and if the user cancels it, you can return true to filter out the event and prevent anything from happening.

laszlo.gosztola
15th May 2012, 14:56
Thanks, I will try to update the selection model also.