I've written a small library for Qt 4 which provides similar functionality. The library includes:
- QtCallback - A pre-canned QObject method call. QtCallback stores an object, a slot to call and optionally a list of pre-bound arguments to pass to the slot. This is useful if you need to pass additional context to the slot, other than the values provided by the signal.
- QtSignalForwarder::connect() - Connects signals from QObjects to arbitrary functions or methods or QtCallbacks. You can use this together with bind() and function<> to pass additional arguments to the method other than those provided by the signal or re-arrange arguments. You can think of this as a more flexible alternative to the QSignalMapper class that Qt 4 provides. There are also a couple of utility features:
- QtSignalForwarder::delayedCall() - A more flexible alternative to QTimer::singleShot() which can be used to invoke an arbitrary function after a set delay.
- Event connections - Invoke an arbitrary function or QtCallback when an object receives a particular type of event. This is useful when the object does not have a built-in signal that is emitted in response to that event and requires less boilerplate than using QObject::installEventFilter()
- safe_bind() - A downside of connecting a signal to a function object is that the signal does not automatically disconnect if the receiver is destroyed. safe_bind() creates a wrapper around a (QObject*, function) pair which when called, invokes the function if the object still exists or does nothing and returns a default value if the object has been destroyed. You can use this together with QtSignalForwarder to connect a signal to an arbitrary method on a QObject which effectively 'disconnects' when the receiver is destroyed.
- Qt 4.8
- A compiler with the TR1 standard library extensions (most C++ compilers from the past few years - including MSVC >= 2008 and GCC 4.x. I have tested with MSVC 2010 and recent GCC/Clang versions) or one which supports equivalent features from the C++11 standard library.
- Argument type checking happens at runtime when QtSignalForwarder::connect() is called, similar to standard QObject signal-slot connections. QObject::connect() in Qt 5 can do type checking at compile time.
- In order to do the runtime type checking, the types of arguments passed from the signal to the function or method must be registered using Q_DECLARE_METATYPE() or qRegisterMetaType()
- Using QtSignalForwarder does have additional overhead since a hidden proxy object is created to route the signal and arguments to the target function. I investigated using a single proxy object for all forwarded signals or a pool of proxies. Unfortunately it turns out that the QObject::sender() and QObject::senderSignalIndex() functions which are used internally have a cost that is linear in the number of connections.
1 comment:
Very cool!
Post a Comment