File indexing completed on 2024-12-01 04:33:00
0001 /** 0002 * SPDX-FileCopyrightText: 2013 Albert Vaca <albertvaka@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "responsewaiter.h" 0008 0009 #include <QCoreApplication> 0010 #include <QDBusPendingCall> 0011 #include <QDBusPendingReply> 0012 #include <QDebug> 0013 0014 Q_DECLARE_METATYPE(QDBusPendingReply<>) 0015 Q_DECLARE_METATYPE(QDBusPendingReply<QVariant>) 0016 Q_DECLARE_METATYPE(QDBusPendingReply<bool>) 0017 Q_DECLARE_METATYPE(QDBusPendingReply<int>) 0018 Q_DECLARE_METATYPE(QDBusPendingReply<QString>) 0019 0020 DBusResponseWaiter *DBusResponseWaiter::m_instance = nullptr; 0021 0022 DBusResponseWaiter *DBusResponseWaiter::instance() 0023 { 0024 if (!m_instance) { 0025 m_instance = new DBusResponseWaiter(); 0026 } 0027 return m_instance; 0028 } 0029 0030 DBusResponseWaiter::DBusResponseWaiter() 0031 : QObject() 0032 { 0033 m_registered << qRegisterMetaType<QDBusPendingReply<>>("QDBusPendingReply<>") 0034 << qRegisterMetaType<QDBusPendingReply<QVariant>>("QDBusPendingReply<QVariant>") 0035 << qRegisterMetaType<QDBusPendingReply<bool>>("QDBusPendingReply<bool>") << qRegisterMetaType<QDBusPendingReply<int>>("QDBusPendingReply<int>") 0036 << qRegisterMetaType<QDBusPendingReply<QString>>("QDBusPendingReply<QString>"); 0037 } 0038 0039 QVariant DBusResponseWaiter::waitForReply(QVariant variant) const 0040 { 0041 if (QDBusPendingCall *call = const_cast<QDBusPendingCall *>(extractPendingCall(variant))) { 0042 call->waitForFinished(); 0043 0044 if (call->isError()) { 0045 qWarning() << "error:" << call->error(); 0046 return QVariant(QStringLiteral("error")); 0047 } 0048 0049 QDBusMessage reply = call->reply(); 0050 0051 if (reply.arguments().count() > 0) { 0052 return reply.arguments().at(0); 0053 } 0054 } 0055 return QVariant(); 0056 } 0057 0058 DBusAsyncResponse::DBusAsyncResponse(QObject *parent) 0059 : QObject(parent) 0060 , m_autodelete(false) 0061 { 0062 m_timeout.setSingleShot(true); 0063 m_timeout.setInterval(15000); 0064 connect(&m_timeout, &QTimer::timeout, this, &DBusAsyncResponse::onTimeout); 0065 } 0066 0067 void DBusAsyncResponse::setPendingCall(QVariant variant) 0068 { 0069 if (QDBusPendingCall *call = const_cast<QDBusPendingCall *>(DBusResponseWaiter::instance()->extractPendingCall(variant))) { 0070 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(*call); 0071 watcher->setProperty("pengingCallVariant", variant); 0072 connect(watcher, &QDBusPendingCallWatcher::finished, this, &DBusAsyncResponse::onCallFinished); 0073 connect(watcher, &QDBusPendingCallWatcher::finished, watcher, &QObject::deleteLater); 0074 connect(&m_timeout, &QTimer::timeout, watcher, &QObject::deleteLater); 0075 m_timeout.start(); 0076 } 0077 } 0078 0079 void DBusAsyncResponse::onCallFinished(QDBusPendingCallWatcher *watcher) 0080 { 0081 m_timeout.stop(); 0082 QVariant variant = watcher->property("pengingCallVariant"); 0083 0084 if (QDBusPendingCall *call = const_cast<QDBusPendingCall *>(DBusResponseWaiter::instance()->extractPendingCall(variant))) { 0085 if (call->isError()) { 0086 Q_EMIT error(call->error().message()); 0087 } else { 0088 QDBusMessage reply = call->reply(); 0089 0090 if (reply.arguments().count() > 0) { 0091 Q_EMIT success(reply.arguments().at(0)); 0092 } else { 0093 Q_EMIT success(QVariant()); 0094 } 0095 } 0096 } 0097 if (m_autodelete) { 0098 deleteLater(); 0099 } 0100 } 0101 0102 void DBusAsyncResponse::onTimeout() 0103 { 0104 Q_EMIT error(QStringLiteral("timeout when waiting dbus response!")); 0105 } 0106 0107 const QDBusPendingCall *DBusResponseWaiter::extractPendingCall(QVariant &variant) const 0108 { 0109 for (int type : qAsConst(m_registered)) { 0110 if (variant.canConvert(QVariant::Type(type))) { 0111 return reinterpret_cast<const QDBusPendingCall *>(variant.constData()); 0112 } 0113 } 0114 0115 return nullptr; 0116 } 0117 0118 #include "moc_responsewaiter.cpp"