EventFilter() hook sees incorrect object in Windows, works in Linux
-
Hi.
First, the background. I have a QLineEdit subclass. The QLineEdit is the main widget, but the class also contains a QWidget, which in turn contains a QListView and a QLabel. The QLabel displays photos associated to the elements of the QListView.
This QWidget monstrosity acts as a dropdown, so that my QLineEdit derivative is kind of a combobox, but it's not a QComboBox ;)
Also, I wanted the QListView to react to clicks, but in a way that the first click selects, and only after a second one, the dropdown is closed and the changes take effect. This is so that users can select elements, see if the photo, and, if they are happy with what they see, click again to truly select the element and do something else with it.
This is done via a filter event I installed in the QLineEdit derivative, but that's meant to act over the QListView, which is contained within. So, in the QLineEdit eventFilter() I check for
@if(object == listView)@
This works ok in Linux, and I get the desired effect, however, when in Windows, the object points to something else. Not sure why this happens. The code follows, along with qDebug() output in Windows:
@
bool CompleteLineEdit::eventFilter(QObject *object, QEvent *event)
{
if(object == listView)
{
qDebug() << Q_FUNC_INFO << "We are in";
}
else
{
qDebug() << Q_FUNC_INFO << QString("Left QLineEdit::eventFilter handle this. Object is %1")
.arg(object->objectName());
QLineEdit::eventFilter(object, event);
}qDebug() << Q_FUNC_INFO << event->type(); if(event->type() == QEvent::MouseButtonRelease) { qDebug() << Q_FUNC_INFO << "Mouse"; QMouseEvent *me = static_cast<QMouseEvent*>(event); if (!listView->isHidden()) { int button = me->button(); //QModelIndex currentIndex = listView->currentIndex(); if (Qt::LeftButton == button) { qDebug() << Q_FUNC_INFO << "left"; QModelIndex new_index = listView->indexAt(me->pos()); if(new_index.row() == previousIndex) { widget->hide(); qDebug() << Q_FUNC_INFO << QString("index %1 previous index %2").arg(new_index.row()).arg(previousIndex); QString text = listView->currentIndex().data().toString(); this->setText(text); this->close(); } else { qDebug() << Q_FUNC_INFO << "los índices son distintos"; listView->setCurrentIndex(new_index); previousIndex = new_index.row(); } } return true; } else { listView->show(); return QLineEdit::eventFilter(object, event); } } else if(event->type() == QEvent::MouseMove) { qDebug() << Q_FUNC_INFO << "mouse is moving"; return true; } else return QLineEdit::eventFilter(object, event);
}
@
@
virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) "Left QLineEdit::eventFilter handle this. Object is qt_scrollarea_viewport"
virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 25
virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) "Left QLineEdit::eventFilter handle this. Object is qt_scrollarea_viewport"
virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 18
virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) "Left QLineEdit::eventFilter handle this. Object is qt_scrollarea_viewport"
virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 11
@It seems it's pointing to something called "qt_scrollarea_viewport".
I am not sure, but, since the QListView has lots of elements, I guess that could be the scrollarea that appears there. Couldn't it? If so, how would I fix this in a portable way? I need this to work on both OSes so...
Thanks for reading and for any hint you can share.
Postdata: I just remembered about "this":http://qt-project.org/forums/viewthread/33811/#147260 .
You can see I had to attach the filter not to the list widget itself, but to its viewport. So, I was using this to set the filter:
@ pWidget = listView->viewport();
pWidget->installEventFilter(this);@If I do this instead, qDebug() shows that I am getting to the right point, but then the problem in that other thread appears: the mouse events never reach the intended target:
@
#ifdef Q_OS_WIN
pWidget = listView;
pWidget->installEventFilter(this);
#else
pWidget = listView->viewport();
pWidget->installEventFilter(this);
#endif
@Ummm....