147 lines
4.4 KiB
C++
147 lines
4.4 KiB
C++
|
|
#include "qeventbus.h"
|
||
|
|
#include <QDebug>
|
||
|
|
#include <QMetaObject>
|
||
|
|
#include <QCoreApplication>
|
||
|
|
QEventBus* QEventBus::instance()
|
||
|
|
{
|
||
|
|
static QEventBus* instance = nullptr;
|
||
|
|
static QMutex mutex;
|
||
|
|
if (!instance) {
|
||
|
|
QMutexLocker locker(&mutex);
|
||
|
|
if (!instance) {
|
||
|
|
instance = new QEventBus();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return instance;
|
||
|
|
}
|
||
|
|
QEventBus::QEventBus(QObject *parent) : QObject(parent)
|
||
|
|
{
|
||
|
|
qDebug() << "QEventBus initialized";
|
||
|
|
}
|
||
|
|
QEventBus::~QEventBus()
|
||
|
|
{
|
||
|
|
m_subscriptions.clear();
|
||
|
|
m_eventHistory.clear();
|
||
|
|
}
|
||
|
|
void QEventBus::publish(const QString& eventType, const QVariant& data, const QString& source)
|
||
|
|
{
|
||
|
|
QMutexLocker locker(&m_mutex);
|
||
|
|
Event event(eventType, data, source);
|
||
|
|
m_eventHistory.prepend(event);
|
||
|
|
if (m_eventHistory.size() > m_maxHistorySize) {
|
||
|
|
m_eventHistory.removeLast();
|
||
|
|
}
|
||
|
|
emit eventPublished(event);
|
||
|
|
if (m_subscriptions.contains(eventType)) {
|
||
|
|
const QList<Subscription>& subscribers = m_subscriptions[eventType];
|
||
|
|
for (const Subscription& sub : subscribers) {
|
||
|
|
if (sub.receiver) {
|
||
|
|
QMetaObject::invokeMethod(sub.receiver, sub.method.constData(),
|
||
|
|
Q_ARG(QVariant, data));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (m_subscriptions.contains("*")) {
|
||
|
|
const QList<Subscription>& subscribers = m_subscriptions["*"];
|
||
|
|
for (const Subscription& sub : subscribers) {
|
||
|
|
if (sub.receiver) {
|
||
|
|
QMetaObject::invokeMethod(sub.receiver, sub.method.constData(),
|
||
|
|
Q_ARG(QString, eventType),
|
||
|
|
Q_ARG(QVariant, data));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void QEventBus::subscribe(const QString& eventType, QObject* receiver, const char* method)
|
||
|
|
{
|
||
|
|
if (!receiver || !method) {
|
||
|
|
qWarning() << "QEventBus: Invalid subscription - receiver or method is null";
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
QMutexLocker locker(&m_mutex);
|
||
|
|
Subscription sub;
|
||
|
|
sub.receiver = receiver;
|
||
|
|
sub.method = QMetaObject::normalizedSignature(method + 1);
|
||
|
|
const QMetaObject* meta = receiver->metaObject();
|
||
|
|
bool methodFound = false;
|
||
|
|
for (int i = 0; i < meta->methodCount(); ++i) {
|
||
|
|
QMetaMethod metaMethod = meta->method(i);
|
||
|
|
if (metaMethod.methodSignature() == sub.method) {
|
||
|
|
methodFound = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (!methodFound) {
|
||
|
|
qWarning() << "QEventBus: Method not found:" << sub.method << "in" << receiver;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
m_subscriptions[eventType].append(sub);
|
||
|
|
connect(receiver, &QObject::destroyed, this, [this, receiver, eventType]() {
|
||
|
|
unsubscribe(eventType, receiver);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
void QEventBus::unsubscribe(const QString& eventType, QObject* receiver)
|
||
|
|
{
|
||
|
|
QMutexLocker locker(&m_mutex);
|
||
|
|
if (m_subscriptions.contains(eventType)) {
|
||
|
|
QList<Subscription>& subscribers = m_subscriptions[eventType];
|
||
|
|
for (int i = subscribers.size() - 1; i >= 0; --i) {
|
||
|
|
if (subscribers[i].receiver == receiver) {
|
||
|
|
subscribers.removeAt(i);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (subscribers.isEmpty()) {
|
||
|
|
m_subscriptions.remove(eventType);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void QEventBus::unsubscribeAll(QObject* receiver)
|
||
|
|
{
|
||
|
|
QMutexLocker locker(&m_mutex);
|
||
|
|
QList<QString> eventTypes = m_subscriptions.keys();
|
||
|
|
for (const QString& eventType : eventTypes) {
|
||
|
|
unsubscribe(eventType, receiver);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
QList<Event> QEventBus::getEventHistory(const QString& type, int limit) const
|
||
|
|
{
|
||
|
|
QMutexLocker locker(&m_mutex);
|
||
|
|
QList<Event> result;
|
||
|
|
int count = 0;
|
||
|
|
for (const Event& event : m_eventHistory) {
|
||
|
|
if (type.isEmpty() || event.type == type) {
|
||
|
|
result.append(event);
|
||
|
|
count++;
|
||
|
|
if (count >= limit) break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
void QEventBus::clearEventHistory()
|
||
|
|
{
|
||
|
|
QMutexLocker locker(&m_mutex);
|
||
|
|
m_eventHistory.clear();
|
||
|
|
}
|
||
|
|
int QEventBus::getEventCount(const QString& type) const
|
||
|
|
{
|
||
|
|
QMutexLocker locker(&m_mutex);
|
||
|
|
if (type.isEmpty()) {
|
||
|
|
return m_eventHistory.size();
|
||
|
|
}
|
||
|
|
int count = 0;
|
||
|
|
for (const Event& event : m_eventHistory) {
|
||
|
|
if (event.type == type) {
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
QMap<QString, int> QEventBus::getEventStatistics() const
|
||
|
|
{
|
||
|
|
QMutexLocker locker(&m_mutex);
|
||
|
|
QMap<QString, int> stats;
|
||
|
|
for (const Event& event : m_eventHistory) {
|
||
|
|
stats[event.type]++;
|
||
|
|
}
|
||
|
|
return stats;
|
||
|
|
}
|