File indexing completed on 2025-01-26 05:06:09

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