File indexing completed on 2024-05-12 05:29:23

0001 /*
0002  *   SPDX-FileCopyrightText: 2013-2016 Ivan Cukic <ivan.cukic@kde.org>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #pragma once
0008 
0009 #include <QDBusAbstractInterface>
0010 #include <QDBusPendingCallWatcher>
0011 #include <QDBusPendingReply>
0012 #include <QDBusServiceWatcher>
0013 #include <QFuture>
0014 #include <QFutureInterface>
0015 #include <QFutureWatcherBase>
0016 
0017 namespace DBusFuture
0018 {
0019 namespace detail
0020 { //_
0021 
0022 template<typename _Result>
0023 class DBusCallFutureInterface : public QObject, public QFutureInterface<_Result>
0024 {
0025 public:
0026     DBusCallFutureInterface(QDBusPendingReply<_Result> reply)
0027         : reply(reply)
0028         , replyWatcher(nullptr)
0029     {
0030     }
0031 
0032     ~DBusCallFutureInterface()
0033     {
0034         delete replyWatcher;
0035     }
0036 
0037     void callFinished();
0038 
0039     QFuture<_Result> start()
0040     {
0041         replyWatcher = new QDBusPendingCallWatcher(reply);
0042 
0043         QObject::connect(replyWatcher, &QDBusPendingCallWatcher::finished, [this]() {
0044             callFinished();
0045         });
0046 
0047         this->reportStarted();
0048 
0049         if (reply.isFinished()) {
0050             this->callFinished();
0051         }
0052 
0053         return this->future();
0054     }
0055 
0056 private:
0057     QDBusPendingReply<_Result> reply;
0058     QDBusPendingCallWatcher *replyWatcher;
0059 };
0060 
0061 template<typename _Result>
0062 void DBusCallFutureInterface<_Result>::callFinished()
0063 {
0064     deleteLater();
0065 
0066     if (!reply.isError()) {
0067         this->reportResult(reply.value());
0068     }
0069 
0070     this->reportFinished();
0071 }
0072 
0073 template<>
0074 void DBusCallFutureInterface<void>::callFinished();
0075 
0076 template<typename _Result>
0077 class ValueFutureInterface : public QObject, QFutureInterface<_Result>
0078 {
0079 public:
0080     ValueFutureInterface(const _Result &value)
0081         : value(value)
0082     {
0083     }
0084 
0085     QFuture<_Result> start()
0086     {
0087         auto future = this->future();
0088 
0089         this->reportResult(value);
0090         this->reportFinished();
0091 
0092         deleteLater();
0093 
0094         return future;
0095     }
0096 
0097 private:
0098     _Result value;
0099 };
0100 
0101 template<>
0102 class ValueFutureInterface<void> : public QObject, QFutureInterface<void>
0103 {
0104 public:
0105     ValueFutureInterface();
0106 
0107     QFuture<void> start();
0108     // {
0109     //     auto future = this->future();
0110     //     this->reportFinished();
0111     //     deleteLater();
0112     //     return future;
0113     // }
0114 };
0115 
0116 } //^ namespace detail
0117 
0118 template<typename _Result>
0119 QFuture<_Result> asyncCall(QDBusAbstractInterface *interface,
0120                            const QString &method,
0121                            const QVariant &arg1 = QVariant(),
0122                            const QVariant &arg2 = QVariant(),
0123                            const QVariant &arg3 = QVariant(),
0124                            const QVariant &arg4 = QVariant(),
0125                            const QVariant &arg5 = QVariant(),
0126                            const QVariant &arg6 = QVariant(),
0127                            const QVariant &arg7 = QVariant(),
0128                            const QVariant &arg8 = QVariant())
0129 {
0130     using namespace detail;
0131 
0132     auto callFutureInterface = new DBusCallFutureInterface<_Result>(interface->asyncCall(method, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
0133 
0134     return callFutureInterface->start();
0135 }
0136 
0137 template<typename _Result>
0138 QFuture<_Result> fromValue(const _Result &value)
0139 {
0140     using namespace detail;
0141 
0142     auto valueFutureInterface = new ValueFutureInterface<_Result>(value);
0143 
0144     return valueFutureInterface->start();
0145 }
0146 
0147 template<typename _Result>
0148 QFuture<_Result> fromReply(const QDBusPendingReply<_Result> &reply)
0149 {
0150     using namespace detail;
0151 
0152     auto callFutureInterface = new DBusCallFutureInterface<_Result>(reply);
0153 
0154     return callFutureInterface->start();
0155 }
0156 
0157 QFuture<void> fromVoid();
0158 
0159 } // namespace DBusFuture