1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtDBus module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QDBUSPENDINGREPLY_H
41#define QDBUSPENDINGREPLY_H
42
43#include <QtDBus/qtdbusglobal.h>
44#include <QtDBus/qdbusargument.h>
45#include <QtDBus/qdbuspendingcall.h>
46
47#ifndef QT_NO_DBUS
48
49QT_BEGIN_NAMESPACE
50
51
52class Q_DBUS_EXPORT QDBusPendingReplyData: public QDBusPendingCall
53{
54protected:
55 QDBusPendingReplyData();
56 ~QDBusPendingReplyData();
57 void assign(const QDBusPendingCall &call);
58 void assign(const QDBusMessage &message);
59
60 QVariant argumentAt(int index) const;
61 void setMetaTypes(int count, const int *metaTypes);
62};
63
64namespace QDBusPendingReplyTypes {
65 template<int Index,
66 typename T1, typename T2, typename T3, typename T4,
67 typename T5, typename T6, typename T7, typename T8>
68 struct Select
69 {
70 typedef Select<Index - 1, T2, T3, T4, T5, T6, T7, T8, void> Next;
71 typedef typename Next::Type Type;
72 };
73 template<typename T1, typename T2, typename T3, typename T4,
74 typename T5, typename T6, typename T7, typename T8>
75 struct Select<0, T1, T2, T3, T4, T5, T6, T7, T8>
76 {
77 typedef T1 Type;
78 };
79
80 template<typename T1> inline int metaTypeFor(T1 * = nullptr)
81 { return qMetaTypeId<T1>(); }
82 // specialize for QVariant, allowing it to be used in place of QDBusVariant
83 template<> inline int metaTypeFor<QVariant>(QVariant *)
84 { return qMetaTypeId<QDBusVariant>(); }
85
86 template<typename T1, typename T2, typename T3, typename T4,
87 typename T5, typename T6, typename T7, typename T8>
88 struct ForEach
89 {
90 typedef ForEach<T2, T3, T4, T5, T6, T7, T8, void> Next;
91 enum { Total = Next::Total + 1 };
92 static inline void fillMetaTypes(int *p)
93 {
94 *p = metaTypeFor<T1>(nullptr);
95 Next::fillMetaTypes(++p);
96 }
97 };
98 template<>
99 struct ForEach<void, void, void, void, void, void, void, void>
100 {
101 enum { Total = 0 };
102 static inline void fillMetaTypes(int *)
103 { }
104 };
105
106 struct TypeIsVoid {};
107 template <typename T> struct NotVoid { typedef T Type; };
108 template <> struct NotVoid<void> { typedef TypeIsVoid Type; };
109} // namespace QDBusPendingReplyTypes
110
111template<typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
112 typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
113class QDBusPendingReply:
114#ifdef Q_CLANG_QDOC
115 public QDBusPendingCall
116#else
117 public QDBusPendingReplyData
118#endif
119{
120 typedef QDBusPendingReplyTypes::ForEach<T1, T2, T3, T4, T5, T6, T7, T8> ForEach;
121 template<int Index> struct Select :
122 QDBusPendingReplyTypes::Select<Index, T1, T2, T3, T4, T5, T6, T7, T8>
123 {
124 };
125
126public:
127 enum { Count = ForEach::Total };
128
129 inline QDBusPendingReply()
130 { }
131 inline QDBusPendingReply(const QDBusPendingReply &other)
132 : QDBusPendingReplyData(other)
133 { }
134 inline /*implicit*/ QDBusPendingReply(const QDBusPendingCall &call) // required by qdbusxml2cpp-generated code
135 { *this = call; }
136 inline /*implicit*/ QDBusPendingReply(const QDBusMessage &message)
137 { *this = message; }
138 inline QDBusPendingReply &operator=(const QDBusPendingReply &other)
139 { assign(other); return *this; }
140 inline QDBusPendingReply &operator=(const QDBusPendingCall &call)
141 { assign(call); return *this; }
142 inline QDBusPendingReply &operator=(const QDBusMessage &message)
143 { assign(message); return *this; }
144
145 inline int count() const { return Count; }
146
147#if defined(Q_CLANG_QDOC)
148 QVariant argumentAt(int index) const;
149#else
150 using QDBusPendingReplyData::argumentAt;
151#endif
152
153#ifndef Q_CLANG_QDOC
154 template<int Index> inline
155 const typename Select<Index>::Type argumentAt() const
156 {
157 Q_STATIC_ASSERT_X(Index >= 0 && Index < Count, "Index out of bounds");
158 typedef typename Select<Index>::Type ResultType;
159 return qdbus_cast<ResultType>(argumentAt(Index), nullptr);
160 }
161#endif
162
163#if defined(Q_CLANG_QDOC)
164 bool isFinished() const;
165 void waitForFinished();
166
167 bool isValid() const;
168 bool isError() const;
169 QDBusError error() const;
170 QDBusMessage reply() const;
171
172 inline T1 value() const;
173 inline operator T1() const;
174#else
175 inline typename Select<0>::Type value() const
176 {
177 return argumentAt<0>();
178 }
179
180 inline operator typename QDBusPendingReplyTypes::NotVoid<T1>::Type() const
181 {
182 return argumentAt<0>();
183 }
184#endif
185
186private:
187 inline void calculateMetaTypes()
188 {
189 if (!d) return;
190 int typeIds[Count > 0 ? Count : 1]; // use at least one since zero-sized arrays aren't valid
191 ForEach::fillMetaTypes(typeIds);
192 setMetaTypes(Count, typeIds);
193 }
194
195 inline void assign(const QDBusPendingCall &call)
196 {
197 QDBusPendingReplyData::assign(call);
198 calculateMetaTypes();
199 }
200
201 inline void assign(const QDBusMessage &message)
202 {
203 QDBusPendingReplyData::assign(message);
204 calculateMetaTypes();
205 }
206};
207
208QT_END_NAMESPACE
209
210#endif // QT_NO_DBUS
211#endif
212