An open API service indexing awesome lists of open source software.

https://github.com/robertknight/qt-signal-tools

Utility classes related to Qt signal and slot handling
https://github.com/robertknight/qt-signal-tools

Last synced: 14 days ago
JSON representation

Utility classes related to Qt signal and slot handling

Awesome Lists containing this project

README

        

# 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:
```cpp
QtCallback1 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:
```cpp
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:
```cpp
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 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.

```cpp
QScopedPointer label(new QLabel);

// create a wrapper around label->setText() which can be run using
// setTextWrapper(text).
function 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 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

* Qt Signal Adapters - Library for connecting signals to Boost function objects: http://sourceforge.net/projects/qtsignaladapter/
* sigfwd - Library for connecting signals to function objects. Uses Boost. https://bitbucket.org/edd/sigfwd/wiki/Home
* Qt 5 meta-object system changes - http://blog.qt.digia.com/blog/2012/06/22/changes-to-the-meta-object-system-in-qt-5/