1 /*
2     Copyright © 2019 by The qTox Project Contributors
3 
4     This file is part of qTox, a Qt-based graphical interface for Tox.
5 
6     qTox is libre software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10 
11     qTox is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with qTox.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef INTERFACE_H
21 #define INTERFACE_H
22 
23 #include <QMetaObject>
24 
25 #include <functional>
26 
27 /**
28  * @file interface.h
29  *
30  * Qt doesn't support QObject multiple inheritance. But for declaring signals
31  * in class, it should be inherit QObject. To avoid this issue, interface can
32  * provide some pure virtual methods, which allow to connect to some signal.
33  *
34  * This file provides macros to make signals declaring easly. With this macros
35  * signal-like method will be declared and implemented in one line each.
36  *
37  * @example
38  * class IExample {
39  * public:
40  *     // Like signal: void valueChanged(int value) const;
41  *     // Declare `connectTo_valueChanged` method.
42  *     DECLARE_SIGNAL(valueChanged, int value);
43  * };
44  *
45  * class Example : public QObject, public IExample {
46  * public:
47  *     // Declare real signal and implement `connectTo_valueChanged`
48  *     SIGNAL_IMPL(Example, valueChanged, int value);
49  * };
50  */
51 #define DECLARE_SIGNAL(name, ...) \
52     using Slot_##name = std::function<void (__VA_ARGS__)>; \
53     virtual QMetaObject::Connection connectTo_##name(QObject *receiver, Slot_##name slot) const = 0
54 
55 /**
56  * @def DECLARE_SIGNAL
57  * @brief Decalre signal-like method. Should be used in interface
58  */
59 #define DECLARE_SIGNAL(name, ...) \
60     using Slot_##name = std::function<void (__VA_ARGS__)>; \
61     virtual QMetaObject::Connection connectTo_##name(QObject *receiver, Slot_##name slot) const = 0
62 
63 /**
64  * @def SIGNAL_IMPL
65  * @brief Declare signal and implement signal-like method.
66  */
67 #define SIGNAL_IMPL(classname, name, ...) \
68     using Slot_##name = std::function<void (__VA_ARGS__)>; \
69     Q_SIGNAL void name(__VA_ARGS__); \
70     QMetaObject::Connection connectTo_##name(QObject *receiver, Slot_##name slot) const override { \
71         return connect(this, &classname::name, receiver, slot); \
72     }
73 
74 #endif // INTERFACE_H
75