File indexing completed on 2024-04-28 16:45:13
0001 /* 0002 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 #include "powermanagement.h" 0007 0008 #include <QDBusConnection> 0009 #include <QDBusConnectionInterface> 0010 #include <QDBusServiceWatcher> 0011 0012 static const QString s_fdoPowerService = QStringLiteral("org.freedesktop.PowerManagement"); 0013 static const QString s_fdoPowerPath = QStringLiteral("/org/freedesktop/PowerManagement"); 0014 0015 class PowerManagementInstance : public PowerManagement 0016 { 0017 Q_OBJECT 0018 public: 0019 explicit PowerManagementInstance() 0020 : PowerManagement() 0021 { 0022 } 0023 }; 0024 Q_GLOBAL_STATIC(PowerManagementInstance, s_instance) 0025 0026 class PowerManagement::Private 0027 { 0028 public: 0029 Private(PowerManagement *q); 0030 void update(); 0031 void setCanSuspend(bool set); 0032 void setCanHibernate(bool set); 0033 0034 bool serviceRegistered; 0035 bool canSuspend; 0036 bool canHibernate; 0037 QScopedPointer<QDBusServiceWatcher> fdoPowerServiceWatcher; 0038 0039 private: 0040 void updateProperty(const QString &dbusName, void (Private::*setter)(bool)); 0041 PowerManagement *q; 0042 }; 0043 0044 PowerManagement::Private::Private(PowerManagement *q) 0045 : serviceRegistered(false) 0046 , canSuspend(false) 0047 , canHibernate(false) 0048 , fdoPowerServiceWatcher(new QDBusServiceWatcher(s_fdoPowerService, 0049 QDBusConnection::sessionBus(), 0050 QDBusServiceWatcher::WatchForUnregistration | QDBusServiceWatcher::WatchForRegistration)) 0051 , q(q) 0052 { 0053 } 0054 0055 void PowerManagement::Private::update() 0056 { 0057 serviceRegistered = true; 0058 updateProperty(QStringLiteral("CanSuspend"), &Private::setCanSuspend); 0059 updateProperty(QStringLiteral("CanHibernate"), &Private::setCanHibernate); 0060 } 0061 0062 void PowerManagement::Private::updateProperty(const QString &dbusName, void (Private::*setter)(bool)) 0063 { 0064 QDBusMessage message = QDBusMessage::createMethodCall(s_fdoPowerService, s_fdoPowerPath, s_fdoPowerService, dbusName); 0065 QDBusPendingReply<bool> reply = QDBusConnection::sessionBus().asyncCall(message); 0066 QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(reply, q); 0067 QObject::connect(callWatcher, &QDBusPendingCallWatcher::finished, q, [this, setter](QDBusPendingCallWatcher *self) { 0068 QDBusPendingReply<bool> reply = *self; 0069 self->deleteLater(); 0070 if (!reply.isValid()) { 0071 return; 0072 } 0073 ((this)->*setter)(reply.value()); 0074 }); 0075 } 0076 0077 void PowerManagement::Private::setCanHibernate(bool set) 0078 { 0079 if (canHibernate == set) { 0080 return; 0081 } 0082 canHibernate = set; 0083 Q_EMIT q->canHibernateChanged(); 0084 } 0085 0086 void PowerManagement::Private::setCanSuspend(bool set) 0087 { 0088 if (canSuspend == set) { 0089 return; 0090 } 0091 canSuspend = set; 0092 Q_EMIT q->canSuspendChanged(); 0093 } 0094 0095 PowerManagement *PowerManagement::instance() 0096 { 0097 return s_instance; 0098 } 0099 0100 PowerManagement::PowerManagement() 0101 : QObject() 0102 , d(new Private(this)) 0103 { 0104 connect(d->fdoPowerServiceWatcher.data(), &QDBusServiceWatcher::serviceRegistered, this, [this] { 0105 d->update(); 0106 }); 0107 connect(d->fdoPowerServiceWatcher.data(), &QDBusServiceWatcher::serviceUnregistered, this, [this] { 0108 d->serviceRegistered = false; 0109 d->setCanSuspend(false); 0110 d->setCanHibernate(false); 0111 }); 0112 0113 // check whether the service is registered 0114 QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DBus"), 0115 QStringLiteral("/"), 0116 QStringLiteral("org.freedesktop.DBus"), 0117 QStringLiteral("ListNames")); 0118 QDBusPendingReply<QStringList> async = QDBusConnection::sessionBus().asyncCall(message); 0119 QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(async, this); 0120 connect(callWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *self) { 0121 QDBusPendingReply<QStringList> reply = *self; 0122 self->deleteLater(); 0123 if (!reply.isValid()) { 0124 return; 0125 } 0126 if (reply.value().contains(s_fdoPowerService)) { 0127 d->update(); 0128 } 0129 }); 0130 } 0131 0132 PowerManagement::~PowerManagement() 0133 { 0134 } 0135 0136 void PowerManagement::suspend() 0137 { 0138 if (!d->serviceRegistered) { 0139 return; 0140 } 0141 if (!d->canSuspend) { 0142 return; 0143 } 0144 QDBusMessage message = QDBusMessage::createMethodCall(s_fdoPowerService, s_fdoPowerPath, s_fdoPowerService, QStringLiteral("Suspend")); 0145 QDBusConnection::sessionBus().asyncCall(message); 0146 } 0147 0148 void PowerManagement::hibernate() 0149 { 0150 if (!d->serviceRegistered) { 0151 return; 0152 } 0153 if (!d->canHibernate) { 0154 return; 0155 } 0156 QDBusMessage message = QDBusMessage::createMethodCall(s_fdoPowerService, s_fdoPowerPath, s_fdoPowerService, QStringLiteral("Hibernate")); 0157 QDBusConnection::sessionBus().asyncCall(message); 0158 } 0159 0160 bool PowerManagement::canSuspend() const 0161 { 0162 return d->canSuspend; 0163 } 0164 0165 bool PowerManagement::canHibernate() const 0166 { 0167 return d->canHibernate; 0168 } 0169 0170 #include "powermanagement.moc"