Utility classes related to Qt signal and slot handling
C++ IDL
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
examples
tests
FunctionTraits.h
FunctionUtils.h
QtCallback.cpp
QtCallback.h
QtMetacallAdapter.h
QtSignalForwarder.cpp
QtSignalForwarder.h
README.md
SafeBinder.h
qt-callbacks.pro

README.md

Qt Signal Tools

qt-signal-tools is a collection of utility classes related to signal and slots in Qt. It includes:

  • QtCallback - Package up a receiver and slot arguments into an object for invoking later.
  • QtSignalForwarder - Connect signals and events from objects to QtCallback or arbitrary functions.
  • QtMetacallAdapter - Low-level interface for calling a function using a list of QGenericArgument() arguments.
  • safe_bind() - Create a wrapper around a method call which does nothing and returns a default value if the object is destroyed before the wrapper is called.

Requirements

  • Qt 4.6 (earliest version tested, may also work with older Qt 4.x releases) or Qt 5.x
  • The TR1 standard library (for C++03 compilers) or the C++11 standard library (for newer compilers when C++11 support is enabled).

Classes

QtCallback

QtCallback is a binder class which provides a way to create callbacks that invoke a signal or slot when invoked, using a mixture of pre-bound arguments and arguments passed to QtCallback::invoke().

Usage:

QtCallback1<int> callback(myWidget, SLOT(someSlot(int,QString)));
callback.bind(42);

// invokes the MyWidget::someSlot() slot with arguments (42, "Hello World")
callback.invoke("Hello World");

void MyWidget::someSlot(int firstArg, const QString& secondArg)
{
}

QtSignalForwarder

QtSignalForwarder provides a way to invoke callbacks when an object emits a signal or receives a particular type of event. The callbacks can be signals and slots (via QtCallback) or arbitrary functions using tr1::function, std::function, boost::function or a similar wrapper.

Qt 5 provides support for connecting signals to arbitrary functions out of the box and to lambdas when using C++11. QtSignalForwarder emulates this for Qt 4.

As well as being able to connect signals to functions that are not slots, this also provides a way to pass additional arguments to the receiver other than those from the signal using QtCallback::bind() or std::tr1::bind().

Usage:

Connecting a signal to a slot with pre-bound arguments:

MyObject receiver;
QPushButton button;
QtSignalForwarder::connect(&button, SIGNAL(clicked(bool)),
  QtCallback(&receiver, SLOT(buttonClicked(int))).bind(42));

// invokes MyObject::buttonClicked() slot with arguments (42)
button.click();

Connecting a signal to an arbitrary function:

using namespace std::tr1;
using namespace std::tr1::placeholders;

SomeObject receiver;
QLineEdit editor;

// function which calls someMethod() with the first-argument fixed (42) and the
// second string argument from the signal
function<void(int,QString)> callback(bind(&SomeObject::someMethod, &receiver, 42, _1));

QtSignalForwarder::connect(&editor, SIGNAL(textChanged(QString)), callback);

// invokes SomeObject::someMethod(42, "Hello World")
editor.setText("Hello World");

Automatic disconnection

For standard signal-slot connections, Qt automatically removes the connection if either the sender or receiver objects are destroyed.

When using QtSignalForwarder::connect(), the connection is automatically removed if the sender is destroyed. However there is no receiver since the callback is a function object - which may call a method on a QObject or it may call a function which is not a QObject method at all.

QtSignalTools provides two solutions to this:

  • QtSignalForwarder::connect() accepts an optional context QObject*. The signal will automatically be disconnected if either the sender or the context object is destroyed. This is the approach that should be used if the callback is a method on a QObject. This behaves the same as the context argument to QObject::connect() in Qt 5.2 and later.
  • A more generic facility is to use the safe_bind() function which creates a wrapper around an object and a method call. The wrapper can then be called with the same arguments as the wrapped method. When a call happens, either the wrapped method is called with the provided arguments, or if the object has been destroyed, nothing happens and a default value is returned. The wrapper created by safe_bind() can be used with bind() and function and can be used together with QtSignalForwarder to automatically 'disconnect' if the receiver is destroyed.
QScopedPointer<QLabel> label(new QLabel);

// create a wrapper around label->setText() which can be run using
// setTextWrapper(text).
function<void(QString)> setTextWrapper = safe_bind(label.data(), &QLabel::setText);

// create a wrapper around label->text() which either calls label->text() and returns
// the same result or returns an empty string if the label has been destroyed
function<QString()> getTextWrapper = safe_bind(label.data(), &QLabel::text);

setTextWrapper("first update"); // sets the label's text to "first update"
qDebug() << "label text" << getTextWrapper(); // prints "first update"
label.reset(); // destroy the label
setTextWrapper("second update"); // does nothing, as the label has been destroyed
qDebug() << "label text" << getTextWrapper(); // prints an empty string

QtMetacallAdapter

QtMetacallAdapter is a low-level wrapper around a function or function object (eg. std::function) which can be used to invoke the function with a list of QGenericArgument (created by the Q_ARG() macro) and introspect the function's argument types at runtime.

License

qt-signal-tools is licensed under the BSD license.

Related Projects & Reading