File indexing completed on 2024-05-12 15:57:03

0001 /*
0002  *  SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "KisSynchronizedConnection.h"
0008 
0009 #include <QThread>
0010 #include <QCoreApplication>
0011 #include <kis_assert.h>
0012 
0013 /**
0014  * @brief The KisSynchronizedConnectionEventTypeRegistrar is a simple
0015  * class to register QEvent type in the Qt's system
0016  */
0017 struct KisSynchronizedConnectionEventTypeRegistrar
0018 {
0019     KisSynchronizedConnectionEventTypeRegistrar() {
0020         eventType = QEvent::registerEventType(QEvent::User + 1000);
0021     }
0022 
0023     int eventType = -1;
0024 };
0025 
0026 struct KisBarrierCallbackContainer
0027 {
0028     std::function<void()> callback;
0029 };
0030 
0031 Q_GLOBAL_STATIC(KisSynchronizedConnectionEventTypeRegistrar, s_instance)
0032 Q_GLOBAL_STATIC(KisBarrierCallbackContainer, s_barrier)
0033 
0034 
0035 /************************************************************************/
0036 /*            KisSynchronizedConnectionEvent                            */
0037 /************************************************************************/
0038 
0039 KisSynchronizedConnectionEvent::KisSynchronizedConnectionEvent(QObject *_destination)
0040     : QEvent(QEvent::Type(s_instance->eventType)),
0041       destination(_destination)
0042 {
0043 }
0044 
0045 KisSynchronizedConnectionEvent::KisSynchronizedConnectionEvent(const KisSynchronizedConnectionEvent &rhs)
0046     : QEvent(QEvent::Type(s_instance->eventType)),
0047       destination(rhs.destination)
0048 {
0049 }
0050 
0051 KisSynchronizedConnectionEvent::~KisSynchronizedConnectionEvent()
0052 {
0053 }
0054 
0055 /************************************************************************/
0056 /*            KisSynchronizedConnectionBase                             */
0057 /************************************************************************/
0058 
0059 int KisSynchronizedConnectionBase::eventType()
0060 {
0061     return s_instance->eventType;
0062 }
0063 
0064 void KisSynchronizedConnectionBase::registerSynchronizedEventBarrier(std::function<void ()> callback)
0065 {
0066     KIS_SAFE_ASSERT_RECOVER_NOOP(!s_barrier->callback);
0067     s_barrier->callback = callback;
0068 }
0069 
0070 bool KisSynchronizedConnectionBase::event(QEvent *event)
0071 {
0072     if (event->type() == s_instance->eventType) {
0073         KisSynchronizedConnectionEvent *typedEvent =
0074                 static_cast<KisSynchronizedConnectionEvent*>(event);
0075 
0076         KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(typedEvent->destination == this, false);
0077         deliverEventToReceiver();
0078         return true;
0079     }
0080 
0081     return QObject::event(event);
0082 }
0083 
0084 void KisSynchronizedConnectionBase::postEvent()
0085 {
0086     if (QThread::currentThread() == this->thread()) {
0087         /// TODO: This assert triggers in unittests that don't have a fully-featured
0088         /// KisApplication object. Perhaps we should add a fake callback to KISTEST_MAIN
0089         /// KIS_SAFE_ASSERT_RECOVER_NOOP(s_barrier->callback);
0090 
0091         if (s_barrier->callback) {
0092             s_barrier->callback();
0093         }
0094 
0095         deliverEventToReceiver();
0096     } else {
0097         qApp->postEvent(this, new KisSynchronizedConnectionEvent(this));
0098     }
0099 }
0100