1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QDBUSPENDINGREPLY_H
43#define QDBUSPENDINGREPLY_H
44
45#include <QtCore/qglobal.h>
46#include <QtDBus/qdbusmacros.h>
47#include <QtDBus/qdbusargument.h>
48#include <QtDBus/qdbuspendingcall.h>
49
50#ifndef QT_NO_DBUS
51
52QT_BEGIN_HEADER
53
54QT_BEGIN_NAMESPACE
55
56QT_MODULE(DBus)
57
58class Q_DBUS_EXPORT QDBusPendingReplyData: public QDBusPendingCall
59{
60protected:
61 QDBusPendingReplyData();
62 ~QDBusPendingReplyData();
63 void assign(const QDBusPendingCall &call);
64 void assign(const QDBusMessage &message);
65
66 QVariant argumentAt(int index) const;
67 void setMetaTypes(int count, const int *metaTypes);
68};
69
70namespace QDBusPendingReplyTypes {
71 template<int Index,
72 typename T1, typename T2, typename T3, typename T4,
73 typename T5, typename T6, typename T7, typename T8>
74 struct Select
75 {
76 typedef Select<Index - 1, T2, T3, T4, T5, T6, T7, T8, void> Next;
77 typedef typename Next::Type Type;
78 };
79 template<typename T1, typename T2, typename T3, typename T4,
80 typename T5, typename T6, typename T7, typename T8>
81 struct Select<0, T1, T2, T3, T4, T5, T6, T7, T8>
82 {
83 typedef T1 Type;
84 };
85
86 template<typename T1> inline int metaTypeFor(T1 * = 0)
87 { return qMetaTypeId<T1>(); }
88 // specialize for QVariant, allowing it to be used in place of QDBusVariant
89 template<> inline int metaTypeFor<QVariant>(QVariant *)
90 { return qMetaTypeId<QDBusVariant>(); }
91
92 template<typename T1, typename T2, typename T3, typename T4,
93 typename T5, typename T6, typename T7, typename T8>
94 struct ForEach
95 {
96 typedef ForEach<T2, T3, T4, T5, T6, T7, T8, void> Next;
97 enum { Total = Next::Total + 1 };
98 static inline void fillMetaTypes(int *p)
99 {
100 *p = metaTypeFor<T1>(0);
101 Next::fillMetaTypes(++p);
102 }
103 };
104 template<>
105 struct ForEach<void, void, void, void, void, void, void, void>
106 {
107 enum { Total = 0 };
108 static inline void fillMetaTypes(int *)
109 { }
110 };
111} // namespace QDBusPendingReplyTypes
112
113template<typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
114 typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
115class QDBusPendingReply:
116#ifdef Q_QDOC
117 public QDBusPendingCall
118#else
119 public QDBusPendingReplyData
120#endif
121{
122 typedef QDBusPendingReplyTypes::ForEach<T1, T2, T3, T4, T5, T6, T7, T8> ForEach;
123 template<int Index> struct Select :
124 QDBusPendingReplyTypes::Select<Index, T1, T2, T3, T4, T5, T6, T7, T8>
125 {
126 };
127
128public:
129 enum { Count = ForEach::Total };
130
131 inline QDBusPendingReply()
132 { }
133 inline QDBusPendingReply(const QDBusPendingReply &other)
134 : QDBusPendingReplyData(other)
135 { }
136 inline QDBusPendingReply(const QDBusPendingCall &call)
137 { *this = call; }
138 inline QDBusPendingReply(const QDBusMessage &message)
139 { *this = message; }
140 inline QDBusPendingReply &operator=(const QDBusPendingReply &other)
141 { assign(other); return *this; }
142 inline QDBusPendingReply &operator=(const QDBusPendingCall &call)
143 { assign(call); return *this; }
144 inline QDBusPendingReply &operator=(const QDBusMessage &message)
145 { assign(message); return *this; }
146
147 inline int count() const { return Count; }
148
149#if defined(Q_QDOC) || defined(Q_NO_USING_KEYWORD)
150 inline QVariant argumentAt(int index) const
151 { return QDBusPendingReplyData::argumentAt(index); }
152#else
153 using QDBusPendingReplyData::argumentAt;
154#endif
155
156#if defined(Q_QDOC)
157 bool isFinished() const;
158 void waitForFinished();
159
160 bool isValid() const;
161 bool isError() const;
162 QDBusError error() const;
163 QDBusMessage reply() const;
164
165 template<int Index> inline Type argumentAt() const;
166 inline T1 value() const;
167 inline operator T1() const;
168#else
169 template<int Index> inline
170 const typename Select<Index>::Type argumentAt() const
171 {
172 // static assert?
173 Q_ASSERT_X(Index < count() && Index >= 0, "QDBusPendingReply::argumentAt",
174 "Index out of bounds");
175 typedef typename Select<Index>::Type ResultType;
176 return qdbus_cast<ResultType>(argumentAt(Index), 0);
177 }
178
179 inline typename Select<0>::Type value() const
180 {
181 return argumentAt<0>();
182 }
183
184 inline operator typename Select<0>::Type() const
185 {
186 return argumentAt<0>();
187 }
188#endif
189
190private:
191 inline void calculateMetaTypes()
192 {
193 if (!d) return;
194 int typeIds[Count > 0 ? Count : 1]; // use at least one since zero-sized arrays aren't valid
195 ForEach::fillMetaTypes(typeIds);
196 setMetaTypes(Count, typeIds);
197 }
198
199 inline void assign(const QDBusPendingCall &call)
200 {
201 QDBusPendingReplyData::assign(call);
202 calculateMetaTypes();
203 }
204
205 inline void assign(const QDBusMessage &message)
206 {
207 QDBusPendingReplyData::assign(message);
208 calculateMetaTypes();
209 }
210};
211
212QT_END_NAMESPACE
213
214QT_END_HEADER
215
216#endif // QT_NO_DBUS
217#endif
218