File indexing completed on 2024-12-22 05:11:50
0001 /* 0002 SPDX-FileCopyrightText: 2019 Ivan Čukić <ivan.cukic(at)kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #ifndef VOY_WRAPPERS_QT_CONNECT_H 0008 #define VOY_WRAPPERS_QT_CONNECT_H 0009 0010 // STL 0011 #include <functional> 0012 0013 // Qt 0014 #include <QObject> 0015 #include <QMetaObject> 0016 #include <QDebug> 0017 0018 // Self 0019 #include "../../utils.h" 0020 #include "../../traits.h" 0021 #include "../../dsl/node_tags.h" 0022 0023 namespace voy::qt { 0024 0025 using voy::utils::non_copyable; 0026 0027 using voy::dsl::continuator_base, 0028 voy::dsl::source_node_tag; 0029 0030 namespace detail { 0031 0032 template <typename T, typename Object, typename Signal> 0033 class signal_impl: non_copyable { 0034 voy_assert_value_type(T); 0035 0036 public: 0037 using node_category = source_node_tag; 0038 0039 explicit signal_impl(Object* sender, Signal signal) 0040 : m_sender{sender} 0041 , m_signal{std::move(signal)} 0042 { 0043 } 0044 0045 template <typename Cont> 0046 class node: public continuator_base<Cont>, non_copyable { 0047 using base = continuator_base<Cont>; 0048 0049 public: 0050 node(Object* sender, Signal signal, Cont cont) 0051 : base{std::move(cont)} 0052 , m_sender{sender} 0053 , m_signal{std::move(signal)} 0054 { 0055 } 0056 0057 void init() 0058 { 0059 qDebug() << "Calling init"; 0060 base::init(); 0061 0062 if constexpr (std::is_same_v<void, T>) { 0063 m_connection = QObject::connect( 0064 m_sender, m_signal, 0065 [this] (auto value) { 0066 // TODO: This needs to be async 0067 base::emit(std::move(value)); 0068 }); 0069 } else { 0070 m_connection = QObject::connect( 0071 m_sender, m_signal, 0072 [this] (T value) { 0073 // TODO: This needs to be async 0074 base::emit(std::move(value)); 0075 }); 0076 } 0077 0078 QObject::connect( 0079 m_sender, &QObject::destroyed, 0080 [this] { 0081 base::notify_ended(); 0082 }); 0083 } 0084 0085 private: 0086 QMetaObject::Connection m_connection; 0087 Object* m_sender; 0088 Signal m_signal; 0089 }; 0090 0091 0092 template <typename Cont> 0093 auto with_continuation(Cont&& cont) && 0094 { 0095 return node<Cont>(m_sender, std::move(m_signal), voy_fwd(cont)); 0096 } 0097 0098 private: 0099 Object* m_sender; 0100 Signal m_signal; 0101 0102 }; 0103 0104 0105 0106 template <typename Object, typename Slot> 0107 class slot_impl: non_copyable { 0108 public: 0109 using node_category = sink_node_tag; 0110 0111 explicit slot_impl(Object* object, Slot slot) 0112 : m_receiver(object) 0113 , m_slot(slot) 0114 { 0115 } 0116 0117 template <typename T> 0118 void operator() (T&& value) const 0119 { 0120 std::invoke(m_slot, m_receiver, voy_fwd(value)); 0121 } 0122 0123 void init() 0124 { 0125 } 0126 0127 void notify_ended() const 0128 { 0129 } 0130 0131 private: 0132 Object* m_receiver; 0133 Slot m_slot; 0134 }; 0135 0136 0137 } // namespace detail 0138 0139 0140 template <typename T = void, typename Object = QObject, typename Signal = void> 0141 auto signal(Object* sender, Signal&& signal) 0142 { 0143 return detail::signal_impl<T, Object, Signal>(sender, voy_fwd(signal)); 0144 } 0145 0146 0147 template <typename Object, typename Slot> 0148 auto slot(Object* receiver, Slot&& slot) 0149 { 0150 return detail::slot_impl<Object, Slot>(receiver, voy_fwd(slot)); 0151 } 0152 0153 } // namespace voy 0154 0155 #endif // include guard 0156