PDA

View Full Version : QItemSelectionModel::currentChanged and revert change



Lykurg
24th March 2009, 17:04
Hi,

I have a QListView and connect the signal from its selection model ItemSelectionModel::currentChanged(const QModelIndex &current, const QModelIndex &previous) to my slot. In that slot I want to revert the change. But I fail. How to revert an selection?

Example:

#include <QtGui>
#include "test.h"

int main(int argc, char **argv)
{
QApplication app(argc, argv);

Test w;
w.show();

return app.exec();
}
#ifndef TEST_H
#define TEST_H

#include <QtGui>

class Test : public QWidget
{
Q_OBJECT
public:
Test(QWidget *parent = 0);
QListView *v;
bool canceled;

public slots:
void changed( const QModelIndex & current, const QModelIndex & previous );
};
#endif
#include "test.h"
#include <QtGui>

Test::Test(QWidget *parent)
: QWidget(parent)
{
QLayout *l = new QHBoxLayout(this);
v = new QListView(this);
v->setSelectionMode(QAbstractItemView::SingleSelectio n);
QStringListModel *model = new QStringListModel();
QStringList list;
list << "a" << "b" << "c" << "d" << "e" << "f";
model->setStringList(list);
v->setModel(model);
l->addWidget(v);
setLayout(l);
v->setCurrentIndex(model->index(0,0));
connect(v->selectionModel(), SIGNAL(currentChanged(const QModelIndex& , const QModelIndex&)), this, SLOT(changed(const QModelIndex& , const QModelIndex&)));
canceled = false;
}

void Test::changed( const QModelIndex & current, const QModelIndex & previous )
{
qWarning() << current << previous;
if (canceled)
{
canceled = false;
return;
}

QMessageBox msgBox;
msgBox.setStandardButtons(QMessageBox::Discard | QMessageBox::Cancel);
int ret = msgBox.exec();
switch (ret)
{
case QMessageBox::Discard:
break;
case QMessageBox::Cancel:
canceled = true;
v->selectionModel()->setCurrentIndex(previous, QItemSelectionModel::ClearAndSelect); // no "back change"
//v->setCurrentIndex(previous); // all lines between current and previous are selected
return;
break;
}
}

Thanks for any help.

spirit
24th March 2009, 17:16
looks and works fine. maybe I don't understand something. :)
when I selected an item a message box appeared. I pressed "cancel" and cursor has been set on previous item.
edited: ah, I see. when mouse is used then reverting is wrong. works fine for keyboard.

spirit
24th March 2009, 17:48
looks like this works
h-file


...
public slots:
void changed( const QModelIndex & current, const QModelIndex & previous );
void restoreSlot(const QModelIndex &index);

signals:
void restore(const QModelIndex &index);
...

cpp-file


...
connect(this, SIGNAL(restore(const QModelIndex &)), this, SLOT(restoreSlot(const QModelIndex &)), Qt::QueuedConnection);
...
void Test::changed( const QModelIndex & current, const QModelIndex & previous )
{
qWarning() << current << previous;
if (canceled)
{
canceled = false;
return;
}

QMessageBox msgBox;
msgBox.setStandardButtons(QMessageBox::Discard | QMessageBox::Cancel);
int ret = msgBox.exec();
switch (ret)
{
case QMessageBox::Discard:
break;
case QMessageBox::Cancel:
canceled = true;
//v->selectionModel()->setCurrentIndex(previous, QItemSelectionModel::ClearAndSelect); // no "back change"
//v->setCurrentIndex(previous); // all lines between current and previous are selected
emit restore(previous);
return;
break;
}
}

void Test::restoreSlot(const QModelIndex &index)
{
v->setCurrentIndex(index);
}

Lykurg
24th March 2009, 22:03
It's amazing how fast this board is! I was just out for spot, came back, got an answer, tried it, works fine, thanks!

The problem is also that qt needs time to revers the selection because without Qt::QueuedConnection it will fail. And it's curios that it doesn't respect the QAbstractItemView::SingleSelection. Is this a thing one could not change or maybe the trolls could? Should we inform them? I don't know, I don't understand all of the issue exact.

Lykurg
25th March 2009, 08:46
Ok, the "real" problem was the signal-slot binding. If i directly use
connect(v->selectionModel(), SIGNAL(currentChanged(const QModelIndex& , const QModelIndex&)), this, SLOT(changed(const QModelIndex& , const QModelIndex&)), Qt::QueuedConnection);
all works as expected without the additional signal.

spirit
25th March 2009, 08:48
nice, I've just posted a solution without investigation. :o