2019-08-13 16:39:22 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <QObject>
|
|
|
|
#include <type_traits>
|
|
|
|
|
2019-08-13 18:48:22 +02:00
|
|
|
namespace chatterino {
|
|
|
|
/// Holds a pointer to a QObject and resets it to nullptr if the QObject
|
|
|
|
/// gets destroyed.
|
|
|
|
template <typename T>
|
|
|
|
class QObjectRef
|
2019-08-13 16:39:22 +02:00
|
|
|
{
|
2019-08-13 18:48:22 +02:00
|
|
|
public:
|
|
|
|
QObjectRef()
|
2019-08-13 16:39:22 +02:00
|
|
|
{
|
2019-08-13 18:48:22 +02:00
|
|
|
static_assert(std::is_base_of_v<QObject, T>);
|
|
|
|
}
|
2019-08-13 16:39:22 +02:00
|
|
|
|
2019-08-13 18:48:22 +02:00
|
|
|
explicit QObjectRef(T *t)
|
|
|
|
{
|
|
|
|
static_assert(std::is_base_of_v<QObject, T>);
|
2019-08-13 16:39:22 +02:00
|
|
|
|
2019-08-13 18:48:22 +02:00
|
|
|
this->set(t);
|
|
|
|
}
|
2019-08-13 16:39:22 +02:00
|
|
|
|
2020-08-15 18:59:17 +02:00
|
|
|
QObjectRef(const QObjectRef &other)
|
|
|
|
{
|
|
|
|
this->set(other.t_);
|
|
|
|
}
|
|
|
|
|
2019-08-13 18:48:22 +02:00
|
|
|
~QObjectRef()
|
|
|
|
{
|
|
|
|
this->set(nullptr);
|
|
|
|
}
|
2019-08-13 16:39:22 +02:00
|
|
|
|
2019-08-13 18:48:22 +02:00
|
|
|
QObjectRef &operator=(T *t)
|
|
|
|
{
|
|
|
|
this->set(t);
|
2019-08-13 16:39:22 +02:00
|
|
|
|
2019-08-13 18:48:22 +02:00
|
|
|
return *this;
|
|
|
|
}
|
2019-08-13 16:39:22 +02:00
|
|
|
|
2019-08-13 18:48:22 +02:00
|
|
|
operator bool()
|
|
|
|
{
|
|
|
|
return t_;
|
|
|
|
}
|
|
|
|
|
|
|
|
T *operator->()
|
|
|
|
{
|
|
|
|
return t_;
|
|
|
|
}
|
2019-08-13 16:39:22 +02:00
|
|
|
|
2019-08-13 18:48:22 +02:00
|
|
|
T *get()
|
|
|
|
{
|
|
|
|
return t_;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void set(T *other)
|
|
|
|
{
|
|
|
|
// old
|
|
|
|
if (this->conn_)
|
2019-08-13 16:39:22 +02:00
|
|
|
{
|
2019-08-13 18:48:22 +02:00
|
|
|
QObject::disconnect(this->conn_);
|
2019-08-13 16:39:22 +02:00
|
|
|
}
|
|
|
|
|
2019-08-13 18:48:22 +02:00
|
|
|
// new
|
|
|
|
if (other)
|
2019-08-13 16:39:22 +02:00
|
|
|
{
|
2020-08-15 19:46:18 +02:00
|
|
|
// the cast here should absolutely not be necessary, but gcc still requires it
|
|
|
|
this->conn_ =
|
|
|
|
QObject::connect((QObject *)other, &QObject::destroyed, qApp,
|
|
|
|
[this](QObject *) { this->set(nullptr); },
|
|
|
|
Qt::DirectConnection);
|
2019-08-13 16:39:22 +02:00
|
|
|
}
|
|
|
|
|
2019-08-13 18:48:22 +02:00
|
|
|
this->t_ = other;
|
|
|
|
}
|
|
|
|
|
2019-08-20 23:29:11 +02:00
|
|
|
std::atomic<T *> t_{};
|
2019-08-13 18:48:22 +02:00
|
|
|
QMetaObject::Connection conn_;
|
|
|
|
};
|
2019-08-13 16:39:22 +02:00
|
|
|
} // namespace chatterino
|