Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+153
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* General Qt-connection
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Fröbel, SLSE, 2017-07-24
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QMetaObject>
|
||||
#include <QPointer>
|
||||
#include <QtGlobal>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
/**
|
||||
* IConnection represents a general Qt-connection.
|
||||
* It is useful in cases where you need to store different Qt-connections
|
||||
* for later use.
|
||||
* @author Christian Fröbel
|
||||
*/
|
||||
class IConnection
|
||||
{
|
||||
public:
|
||||
virtual ~IConnection() = default;
|
||||
virtual void connect(Qt::ConnectionType = Qt::AutoConnection) = 0;
|
||||
virtual void disconnect() = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A DummyConnection can be used when there is no connection.
|
||||
* connect() and disconnect() are no-ops.
|
||||
*/
|
||||
class DummyConnection : public IConnection
|
||||
{
|
||||
public:
|
||||
void connect(Qt::ConnectionType = Qt::AutoConnection) override {}
|
||||
void disconnect() override {}
|
||||
};
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/**
|
||||
* Helper class to extract the class type from a given pointer to member,
|
||||
* where member can be an object or a function (aka method).
|
||||
* We need it only for methods though.
|
||||
* This is just the main template declaration without implementation.
|
||||
*/
|
||||
template<class T>
|
||||
struct ExtractClass;
|
||||
|
||||
/**
|
||||
* Specialization vor pointer to member.
|
||||
*/
|
||||
template<class T, class Member>
|
||||
struct ExtractClass<Member T::*>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
/**
|
||||
* Implements a Qt-connection based on the pointer to the methods being connected.
|
||||
* The connection can be signal to signal or signal to slot.
|
||||
*
|
||||
* Connection is guarded against the case where either the signal-emitter
|
||||
* or -target is deleted before conntect() is actually called.
|
||||
*
|
||||
* @param Signal Pointer to method of the Emitter
|
||||
* @param Slot Pointer to method of the Target; might also be a signal.
|
||||
* @author Christian Fröbel
|
||||
*/
|
||||
template<class Signal, class Slot>
|
||||
class Connection : public IConnection
|
||||
{
|
||||
static_assert(std::is_member_function_pointer<Signal>::value, "Must be a pointer to method");
|
||||
static_assert(std::is_member_function_pointer<Slot>::value, "Must be a pointer to method");
|
||||
|
||||
using Emitter = typename detail::ExtractClass<Signal>::type;
|
||||
using Target = typename detail::ExtractClass<Slot>::type;
|
||||
|
||||
static_assert(std::is_base_of<QObject, Emitter>::value, "Must be derived from QObject");
|
||||
static_assert(std::is_base_of<QObject, Target>::value, "Must be derived from QObject");
|
||||
|
||||
public:
|
||||
Connection(Emitter *emitter, Signal signal, Target *target, Slot slot):
|
||||
m_emitter(emitter),
|
||||
m_signal(signal),
|
||||
m_target(target),
|
||||
m_slot(slot)
|
||||
{
|
||||
Q_ASSERT(emitter);
|
||||
Q_ASSERT(signal);
|
||||
Q_ASSERT(target);
|
||||
Q_ASSERT(slot);
|
||||
}
|
||||
|
||||
void connect(Qt::ConnectionType connectionType = Qt::AutoConnection) override
|
||||
{
|
||||
Q_ASSERT(!m_connected);
|
||||
|
||||
m_connected = true;
|
||||
|
||||
// Guard against the possibility when either m_emitter or m_target got deleted before
|
||||
// the Connection is actually connected.
|
||||
if (!m_emitter || !m_target)
|
||||
return;
|
||||
|
||||
m_conn = QObject::connect(m_emitter.data(), m_signal, m_target.data(), m_slot, connectionType);
|
||||
Q_ASSERT(m_conn);
|
||||
}
|
||||
|
||||
void disconnect() override
|
||||
{
|
||||
Q_ASSERT(m_connected);
|
||||
|
||||
if (m_conn)
|
||||
QObject::disconnect(m_conn);
|
||||
|
||||
m_connected = false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_connected{false};
|
||||
QPointer<Emitter> m_emitter;
|
||||
Signal m_signal;
|
||||
QPointer<Target> m_target;
|
||||
Slot m_slot;
|
||||
QMetaObject::Connection m_conn;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function in order to deduce the template parameters.
|
||||
*/
|
||||
template<class Signal, class Slot>
|
||||
Connection<Signal, Slot>* createConnection(typename detail::ExtractClass<Signal>::type *emitter, Signal signal,
|
||||
typename detail::ExtractClass<Slot>::type *target, Slot slot)
|
||||
{
|
||||
return new Connection<Signal, Slot>(emitter, signal, target, slot);
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
Reference in new issue
Block a user