[SOLVED] QLineEdit --> QListView and event filter not catching mouse events



  • Hello.

    I have a line edit widget, and a QListView which acts as a completer for the former. I want to control from the first how the later behaves, in a way that, let's say, single click will select, and, then, if you click the same element again, it will be set as the text for the QLineEdit.

    If I understand that correctly, for that, I have to install an event filter in the QLineEdit, so that it will handle the events received by the QListView, and then define the eventFilter() method also in the QLineEdit().

    So far so good. I did so, and the eventFilter() is being triggered, but it doesn't get any mouse related events when I click the items in QListView.

    @bool CompleteLineEdit::eventFilter(QObject *object, QEvent *event)
    {
    qDebug() << Q_FUNC_INFO;
    if(event->type() == QEvent::MouseButtonPress)
    {
    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)
                {
                    listView->hide();
                    QString text = listView->currentIndex().data().toString();
                    setText(text);
                }
                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);
    

    }@

    In qdebug I get a lot of

    @virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*)
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*)
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*)
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*)
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*)
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*)
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*)
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*)
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) @

    But no other qDebug line ever runs. Is there a chance that something else is filtering these events out or something? Or am I doing something wrong in that code?

    Thanks you for any help :)



  • Hi,

    how have you installed the filter and what type of events do you get? I suppose mostly are paint events ... print out event->type()



  • [quote author="NicuPopescu" date="1382104701"]Hi,

    how have you installed the filter and what type of events do you get? I suppose mostly are paint events ... print out event->type() [/quote]

    I have a class that inherits from QLineEdit, that's the one I was talking about above. I install the event filter in the constructor for that class.

    @CompleteLineEdit::CompleteLineEdit(/QStringList words/QSqlQueryModel *m, QWidget *parent)
    : QLineEdit(parent), m(m) {

    widget = new QWidget;
    QHBoxLayout *hbox = new QHBoxLayout;
    widget->setLayout(hbox);
    
    listView = new QListView;
    photo = new QLabel;
    model = new QStringListModel;
    listView->setModel(model);
    
    hbox->setMargin(0);
    hbox->addWidget(listView);
    hbox->addWidget(photo);
    hbox->setSpacing(0);
    
    photo->setVisible(false);
    photo->setMinimumWidth(0);
    photo->setStyleSheet("border: 2px solid black;");
    
    widget->setWindowFlags(Qt::ToolTip|Qt::WindowStaysOnTopHint);
    
    listView->installEventFilter(this);
    
    previousIndex = -1;
    
    connect(listView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(onSelectionChanged(QItemSelection)));
    connect(this, SIGNAL(textChanged(const QString &)), this, SLOT(setCompleter(const QString &)));
    

    // connect(listView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(completeText(const QModelIndex &)));
    }@

    One thing to note is that the completer is a QWidget that contains the two things: a QListView and a QLabel. This QListView is the one whose events I am trying to fetch from my QLineEdit derivative.

    I hope it's a bit clearer now.

    About the type of events I am getting, I have tried to print them, but that gives me little info because they are just integers. I guess I'll have to check some qt header to get the meaning for those so that's what I'll do next.

    @virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 75
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 70
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 70
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 70
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 69
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 69
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 69
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 26
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 13
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 14
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 17
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 67
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 74
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 43
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 76
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 1
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 12
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 10
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 11
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 10
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 11
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 10
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 11
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 10
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) We are in
    virtual bool CompleteLineEdit::eventFilter(QObject*, QEvent*) 18 @



  • Oh, for what it's worth, if I click a QListView line, a '1' is printed.

    I tried hard-coding that value (just for testing purposes, of course), but then lots and lots of '1' are printed, and the eventFilter() doesn't work either.

    I don't know what that can mean.

    Also, as you can see, I disabled a connection that I have to the clicked() signal in the list view, so that it doesn't interfere...

    ps.

    This is stranger and stranger. According to /usr/include/qt4/QtCore/qcoreevent.h, '1' is a Timer event. That would make sense if it wasn't because it's not always ticking... mmm... maybe some other eventFilter is catching this (and MouseButtonPress) before they arrive there?



  • I think your CompleteLineEdit widget and listView lay in different window-children hierarchy

    @widget = new QWidget;@

    it seems this with parent=0 becomes a window as doc says and has its own children ... anyway among the event type codes there are and related to the mouse, Enter, Leave etc.

    try to put list view and completer in the same main window



  • First thing first, thanks you so much for all your help.

    However I have no idea how to do that hehe. This QLineEdit is an edit delegate for a column of a QTableView, so, the QLineEdit lies in there.

    The QWidget enclosing a QListView and a QLabel opens as a popup with the Qt::Tooltip hint which as I understand it is what allows the whole thing to "fly" over the main window.

    As you say, I get events when I traverse the borders in and out. I am also getting the click event in the QLineEdit, but not in the QListView inside my QWidget.

    Maybe I should redo the whole thing in a way that QWidget does not wrap the widget that instantiates QWidget, in first place. I don't know if that can be a problem... I did it that way just because this originally was a QListView. There wasn't a photo to the right side, and hence QWidget wasn't needed to wrap it all together.

    Well, I have some things to try now hehe, again, thank you :)



  • I really can't tell you why, but doing "this":http://www.qtcentre.org/threads/20151-QTextEdit-not-receiving-MouseButtonDblClick-or-MouseButtonPress?p=98976#post98976 made the whole thing work as it was intended, without a single modification in the rest of the code.



  • good to know!

    at the moment I only have this clue:

    bq. bool QAbstractItemView::viewportEvent ( QEvent * event ) [virtual protected]
    Reimplemented from QAbstractScrollArea::viewportEvent().
    This function is used to handle tool tips, and What's This? mode, if the given event is a QEvent::ToolTip,or a QEvent::WhatsThis. It passes all other events on to its base class viewportEvent() handler.

    it looks a little weird :)



  • So it's my tooltip hint which cause the havoc. As I understand it, in that case, the event is not passed from the intended place, but from the parent object (which is below and out of the mouse focus, of course). Well, thanks for the hint, now at least I know that what was happening has its logic and is not some kind of random behavior on qt's side.

    Thank you :)



  • I don't know if anyone is still listening here, but it turned out that this doesn't work in Windows. Ideas are welcome. I'll post back if I find something.



  • Right, I managed to solve this by just using listView->viewport()->grabMouse() after show()'ing the widget. Note that, unless you enjoy paralysis, you must be careful enough to also use listView->viewport()->releaseMouse() when hiding it, otherwise you'll need to kill the program by using the keyboard, which in some OSes is more difficult that in some others :)



  • This is going to be bitting me for longer that I was expecting :P

    I just discovered that this whole mess has rendered my scrollbar useless. It doesn't seem to get any event at all. I can still scroll using the wheel over the listview, or with the keyboard, though. Still, it's a pain. :(



  • I just ran into the same problem: I install an event filter on a QListView, but it never receives mouse-related events. This is using Qt 5.2 on Windows.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.