qt-signal-tools is a collection of utility classes related to signal and slots in Qt. It includes:
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 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");
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 beQObject::connect()
in Qt 5.2 and later.safe_bind()
function which creates a wrapper around an objectsafe_bind()
bind()
and function
and can be used together with QtSignalForwarder
toQScopedPointer<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 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.
qt-signal-tools is licensed under the BSD license.