Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [Solved] Are nested event filters allowed/recommended
Forum Updated to NodeBB v4.3 + New Features

[Solved] Are nested event filters allowed/recommended

Scheduled Pinned Locked Moved General and Desktop
20 Posts 5 Posters 11.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    andre
    wrote on last edited by
    #6

    Volker, you are right of course that I could have referenced the source code. Thanks for doing this, and confirming my suspision that Qt won't do funny stuff such as adding the same object twice in the filter chain. Not sure if you can rely on this behaviour 100% in the future, as it is not documented and thus may change. Sure, not very likely, but still.

    Perhaps we should wait for an answer from Dieter however to hear if I understood him correctly on what he was worried about and what he meant with "nested event filters".

    1 Reply Last reply
    0
    • G Offline
      G Offline
      goetz
      wrote on last edited by
      #7

      I'm pretty sure they will not change that :-) In fact it's good programming style to be liberal in what you accept and pedantic in what you put out.

      http://www.catb.org/~esr/faqs/smart-questions.html

      1 Reply Last reply
      0
      • D Offline
        D Offline
        d.oberkofler
        wrote on last edited by
        #8

        [quote author="Andre" date="1294652387"]Let me try to see if I got your question right. "nested" is a tricky concept, I think. It seems you are talking about what happens in this case:
        @
        class ObjectParent: public QObject {
        objectParent(QObject* someWatchedObject, QObject* parent):
        QObject(parent)
        {
        someWatchedObject->installEventFilter(this);
        }
        }

        class ObjectChild: public ObjectParent {
        objectChild(QObject* someWatchedObject, QObject* parent):
        ObjectParent(someWatchedObject, parent)
        {
        someWatchedObject->installEventFilter(this);
        }
        }
        @
        [/quote]

        This is exactly what I was referring to and the answer I've received are (as always) excellent!
        The reason why I've asked this in the first place is actually less "abstract" then what it might seem.
        I my use case the base class is part of a mostly static framework and the derived class will be instantiated by a user of the library. As described the intuitive way to install an event filter in the base class would not work as expected if the derived class is not aware of this implementation detail and this is what I wanted to prevent in the framework.

        If I got it right, I would need to install an event filter to a stand-alone event filter object to get this solved in a transparent way like in the following example:

        @
        class objectParent;

        class EventFilterParent: public QObject
        {
        public:
        eventFilterParent(objectParent* parent): QObject(parent), itsParent(parent) {}
        bool eventFilter(QObject* obj, QEvent* event)
        {
        return itsParent->event(obj, event);
        }

        private:
        objectParent* itsParent;
        }

        class objectParent: public QObject
        {
        objectParent()
        {
        this->installEventFilter(new eventFilterParent(this));
        }
        bool eventFilter(QObject* obj, QEvent* event)
        {
        // do stuff
        return ???;
        }
        }

        class ObjectChild: public ObjectParent {
        objectChild(QObject* someWatchedObject, QObject* parent):
        ObjectParent(someWatchedObject, parent)
        {
        someWatchedObject->installEventFilter(this);
        }
        }
        @

        1 Reply Last reply
        0
        • G Offline
          G Offline
          giesbert
          wrote on last edited by
          #9

          Hi Dieter,

          Why do you implement eventFilter in the objectParent class?
          You install an event filter on your own with a helper that calls your eventFilter method?
          Then you can just overwrite event(), that has the same effect.

          The EventFilterParent class is totally not needed here.

          From your example, you can remove the eventFilter stuff from the objectParent class and the complete EventFilterParent class.

          Nokia Certified Qt Specialist.
          Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

          1 Reply Last reply
          0
          • A Offline
            A Offline
            andre
            wrote on last edited by
            #10

            In principle, I think you are right (though your implementation lacks a bit). You could protect your eventFilter implementation by putting the actual event filter in a separate, private object in your class and either handle it there, or defer the handling again to a private method in the widget. Still, you have to ask yourself how useful that is. You run the risk that the user is unaware of the internals of your class not only with the eventFilter method, but with every virtual method in your widget, including those inherited from QObject and QWidget. And those are certainly not the -most- least important ones! When reimplementing a virtual method, you have to know what you're doing, and it often is a great idea to call the base implementation for the cases you don't handle yourself anyway. You have to ask yourself if you really want to try to protect the user of your library from all these possible pitfals?

            1 Reply Last reply
            0
            • G Offline
              G Offline
              goetz
              wrote on last edited by
              #11

              The API docs on "QObject::eventFilter() ":http://doc.qt.nokia.com/stable/qobject.html#eventFilter even mentions this:

              bq. Notice in the example above that unhandled events are passed to the base class's eventFilter() function, since the base class might have reimplemented eventFilter() for its own internal purposes.

              You can add a prominent message in your API docs to warn your users.

              Andre is totally right. It is good practice to call the base class' virtual method unless you really know what you're doing.

              If you really want to, you can of course put the event filter in a private object of the parent class. If you do that, then there is no need to define and implement an eventFilter() method in the parent class.

              http://www.catb.org/~esr/faqs/smart-questions.html

              1 Reply Last reply
              0
              • G Offline
                G Offline
                giesbert
                wrote on last edited by
                #12

                But the implemented filter was set on the parent class, where you don't need an event filter, as it always gets it's own events.
                In the example code, the event filter object redirects the events from the object to itself.

                Nokia Certified Qt Specialist.
                Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  goetz
                  wrote on last edited by
                  #13

                  Calling event() from eventFilter() seems quite dangerous to me (infinite recursion?).

                  I would go with Andre's first suggestion. It's clean and well understandable and supported. And it's what virtual functions are meant for :-)

                  http://www.catb.org/~esr/faqs/smart-questions.html

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    giesbert
                    wrote on last edited by
                    #14

                    Volker, if you read the example code of Dieter, you see:

                    @
                    class CInternalFilterObject : public QObject
                    {
                    public:
                    CInternalFilterObject(CObjectToFilter* parent): QObject(parent), itsParent(parent) {}
                    bool eventFilter(QObject* obj, QEvent* event)
                    {
                    return itsParent->event(obj, event);
                    }

                    private:
                    CObjectToFilter* itsParent;
                    }

                    class CObjectToFilter: public QObject
                    {
                    CObjectToFilter()
                    {
                    installEventFilter(new CInternalFilterObject(this));
                    }
                    bool eventFilter(QObject* obj, QEvent* event)
                    {
                    // do stuff
                    return ???;
                    }
                    }
                    @

                    That means, in the class CObjectToFilter, he creates an object to filter the events of CObjectToFilter (CInternalFilterObject), which then calls CObjectToFilter. This is a loop from CObjectToFilter over CInternalFilterObject to CObjectToFilter. That means, it can also be removed and will have the same effect.

                    Nokia Certified Qt Specialist.
                    Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                    1 Reply Last reply
                    0
                    • G Offline
                      G Offline
                      goetz
                      wrote on last edited by
                      #15

                      That solution is way to complicated! I don't even want to understand it!

                      One should go with Andre's first suggestion.
                      It works. It is simple. It is beautiful. It is like C++ was meant. Point.

                      http://www.catb.org/~esr/faqs/smart-questions.html

                      1 Reply Last reply
                      0
                      • G Offline
                        G Offline
                        giesbert
                        wrote on last edited by
                        #16

                        That's not my solution, that was the initial code by Dieter.

                        And as he redirected the events to himself, I said, he can juts leave the event filters out and overwrite event :-)

                        Nokia Certified Qt Specialist.
                        Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                        1 Reply Last reply
                        0
                        • D Offline
                          D Offline
                          d.oberkofler
                          wrote on last edited by
                          #17

                          Thank you for all your valuable input.

                          • I must admit that I did not even know of the option to just overload the method QObject::event()
                            This is an interesting alternative to the use of an event filter and would clearly make my second code snippet simpler.

                          • For my specific problem I will stick with the good old "call the base class’ virtual method" approach as suggested.

                          @
                          bool derivedClass::eventFilter(QObjectobj, QEvent event)
                          {
                          if (event->type() == ...)
                          {
                          // do stuff ...
                          return ???;
                          }
                          else
                          {
                          // if it's not "ours", just pass the event on to our parent class
                          return parentClass::eventFilter(obj, event);
                          }
                          }
                          @

                          1 Reply Last reply
                          0
                          • G Offline
                            G Offline
                            giesbert
                            wrote on last edited by
                            #18

                            [quote author="Dieter" date="1294754903"]

                            • I must admit that I did not even know of the option to just overload the method QObject::event()
                              This is an interesting alternative to the use of an event filter and would clearly make my second code snippet simpler.
                              [/quote]

                            If you are only interested in some special events, you can also just overwrite the specific event handlers (see "QObject":http://doc.qt.nokia.com/latest/qobject.html#protected-functions and "QWidget":http://doc.qt.nokia.com/latest/qwidget.html#protected-functions documentation).

                            Nokia Certified Qt Specialist.
                            Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                            1 Reply Last reply
                            0
                            • G Offline
                              G Offline
                              goetz
                              wrote on last edited by
                              #19

                              QObject::event() only works for the events that are actually delivered to the QObject where this method is (re)implemented.

                              QObject::eventFilter() is for one QObject that filters the events of another QObject. Although it can be abused on this object too (thus filtering events on itself), it would definitely be better to reimplement event() (or any of the specialized xyzEvent() methods) in this case! Please do everyone a favor and consider this!

                              Also, watch out to check the obj pointer in eventFilter()! You should react on the event type and the proper object!

                              http://www.catb.org/~esr/faqs/smart-questions.html

                              1 Reply Last reply
                              0
                              • D Offline
                                D Offline
                                d.oberkofler
                                wrote on last edited by
                                #20

                                Thank you for the additional clarifications!

                                1 Reply Last reply
                                0

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved