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 49 QT_BEGIN_NAMESPACE 50 51 52 class Q_DBUS_EXPORT QDBusPendingReplyData: public QDBusPendingCall 53 { 54 protected: 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 64 namespace 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 111 template<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> 113 class 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 126 public: 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 186 private: 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 208 QT_END_NAMESPACE 209 210 #endif // QT_NO_DBUS 211 #endif 212