1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QDBUSPENDINGREPLY_H
5#define QDBUSPENDINGREPLY_H
6
7#include <QtDBus/qtdbusglobal.h>
8#include <QtDBus/qdbusargument.h>
9#include <QtDBus/qdbuspendingcall.h>
10
11#ifndef QT_NO_DBUS
12
13QT_BEGIN_NAMESPACE
14
15
16class Q_DBUS_EXPORT QDBusPendingReplyBase : public QDBusPendingCall
17{
18protected:
19 QDBusPendingReplyBase();
20 ~QDBusPendingReplyBase();
21 void assign(const QDBusPendingCall &call);
22 void assign(const QDBusMessage &message);
23
24 QVariant argumentAt(int index) const;
25 void setMetaTypes(int count, const QMetaType *metaTypes);
26};
27
28namespace QDBusPendingReplyTypes {
29 template<int Index, typename T, typename... Types>
30 struct Select
31 {
32 typedef Select<Index - 1, Types...> Next;
33 typedef typename Next::Type Type;
34 };
35 template<typename T, typename... Types>
36 struct Select<0, T, Types...>
37 {
38 typedef T Type;
39 };
40
41 template<typename T> inline QMetaType metaTypeFor()
42 { return QMetaType::fromType<T>(); }
43 // specialize for QVariant, allowing it to be used in place of QDBusVariant
44 template<> inline QMetaType metaTypeFor<QVariant>()
45 { return QMetaType::fromType<QDBusVariant>(); }
46}
47
48
49template<typename... Types>
50class QDBusPendingReply : public QDBusPendingReplyBase
51{
52 template<int Index> using Select = QDBusPendingReplyTypes::Select<Index, Types...>;
53public:
54 enum { Count = std::is_same_v<typename Select<0>::Type, void> ? 0 : sizeof...(Types) };
55
56 inline constexpr int count() const { return Count; }
57
58
59 inline QDBusPendingReply() = default;
60 inline QDBusPendingReply(const QDBusPendingReply &other)
61 : QDBusPendingReplyBase(other)
62 { }
63 inline Q_IMPLICIT QDBusPendingReply(const QDBusPendingCall &call) // required by qdbusxml2cpp-generated code
64 { *this = call; }
65 inline Q_IMPLICIT QDBusPendingReply(const QDBusMessage &message)
66 { *this = message; }
67
68 inline QDBusPendingReply &operator=(const QDBusPendingReply &other)
69 { assign(other); return *this; }
70 inline QDBusPendingReply &operator=(const QDBusPendingCall &call)
71 { assign(call); return *this; }
72 inline QDBusPendingReply &operator=(const QDBusMessage &message)
73 { assign(message); return *this; }
74
75 using QDBusPendingReplyBase::argumentAt;
76 template<int Index> inline
77 typename Select<Index>::Type argumentAt() const
78 {
79 static_assert(Index >= 0 && Index < Count, "Index out of bounds");
80 typedef typename Select<Index>::Type ResultType;
81 return qdbus_cast<ResultType>(argumentAt(Index));
82 }
83
84#if defined(Q_QDOC)
85 bool isFinished() const;
86 void waitForFinished();
87 QVariant argumentAt(int index) const;
88
89 bool isValid() const;
90 bool isError() const;
91 QDBusError error() const;
92 QDBusMessage reply() const;
93#endif
94
95 inline typename Select<0>::Type value() const
96 {
97 return argumentAt<0>();
98 }
99
100 inline operator typename Select<0>::Type() const
101 {
102 return argumentAt<0>();
103 }
104
105private:
106 inline void calculateMetaTypes()
107 {
108 if (!d) return;
109 if constexpr (Count == 0) {
110 setMetaTypes(count: 0, metaTypes: nullptr);
111 } else {
112 std::array<QMetaType, Count> typeIds = { QDBusPendingReplyTypes::metaTypeFor<Types>()... };
113 setMetaTypes(count: Count, metaTypes: typeIds.data());
114 }
115 }
116
117 inline void assign(const QDBusPendingCall &call)
118 {
119 QDBusPendingReplyBase::assign(call);
120 calculateMetaTypes();
121 }
122
123 inline void assign(const QDBusMessage &message)
124 {
125 QDBusPendingReplyBase::assign(message);
126 calculateMetaTypes();
127 }
128};
129
130template<>
131class QDBusPendingReply<> : public QDBusPendingReplyBase
132{
133public:
134 enum { Count = 0 };
135 inline int count() const { return Count; }
136
137 inline QDBusPendingReply() = default;
138 inline QDBusPendingReply(const QDBusPendingReply &other)
139 : QDBusPendingReplyBase(other)
140 { }
141 inline Q_IMPLICIT QDBusPendingReply(const QDBusPendingCall &call) // required by qdbusxml2cpp-generated code
142 { *this = call; }
143 inline Q_IMPLICIT QDBusPendingReply(const QDBusMessage &message)
144 { *this = message; }
145
146 inline QDBusPendingReply &operator=(const QDBusPendingReply &other)
147 { assign(call: other); return *this; }
148 inline QDBusPendingReply &operator=(const QDBusPendingCall &call)
149 { assign(call); return *this; }
150 inline QDBusPendingReply &operator=(const QDBusMessage &message)
151 { assign(message); return *this; }
152
153private:
154 inline void assign(const QDBusPendingCall &call)
155 {
156 QDBusPendingReplyBase::assign(call);
157 if (d)
158 setMetaTypes(count: 0, metaTypes: nullptr);
159 }
160
161 inline void assign(const QDBusMessage &message)
162 {
163 QDBusPendingReplyBase::assign(message);
164 if (d)
165 setMetaTypes(count: 0, metaTypes: nullptr);
166 }
167
168};
169
170QT_END_NAMESPACE
171
172#endif // QT_NO_DBUS
173#endif
174

source code of qtbase/src/dbus/qdbuspendingreply.h