Files
qt6-migration-pipeline/Lts/Common/LtsUtils/LtsUtilsCore/connection.h
T

100 lines
2.5 KiB
C++

#pragma once
#include <QMetaObject>
#include <QObject>
#include <QPointer>
#include <QtGlobal>
#include <type_traits>
namespace LtsUtils {
class IConnection {
public:
virtual ~IConnection() = default;
virtual void connect(Qt::ConnectionType = Qt::AutoConnection) = 0;
virtual void disconnect() = 0;
};
class DummyConnection : public IConnection {
public:
void connect(Qt::ConnectionType = Qt::AutoConnection) override {}
void disconnect() override {}
};
namespace detail {
template <class T> struct ExtractClass;
template <class T, class Member> struct ExtractClass<Member T::*> {
using type = T;
};
} // namespace detail
template <class Signal, class Slot> class Connection : public IConnection {
static_assert(std::is_member_function_pointer_v<Signal>,
"Must be a pointer to method");
static_assert(std::is_member_function_pointer_v<Slot>,
"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_v<QObject, Emitter>,
"Must be derived from QObject");
static_assert(std::is_base_of_v<QObject, Target>,
"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;
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;
};
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