File indexing completed on 2024-04-21 16:30:33
0001 // SPDX-License-Identifier: GPL-3.0-or-later 0002 /* 0003 Copyright 2017 - 2023 Martin Koller, kollix@aon.at 0004 0005 This file is part of liquidshell. 0006 0007 liquidshell is free software: you can redistribute it and/or modify 0008 it under the terms of the GNU General Public License as published by 0009 the Free Software Foundation, either version 3 of the License, or 0010 (at your option) any later version. 0011 0012 liquidshell is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 GNU General Public License for more details. 0016 0017 You should have received a copy of the GNU General Public License 0018 along with liquidshell. If not, see <http://www.gnu.org/licenses/>. 0019 */ 0020 0021 #include <KdeConnect.hxx> 0022 #include <Battery.hxx> 0023 0024 #include <QDBusConnection> 0025 #include <QDBusConnectionInterface> 0026 #include <QDBusServiceWatcher> 0027 #include <QDBusMessage> 0028 #include <QDebug> 0029 0030 #include <KLocalizedString> 0031 0032 //-------------------------------------------------------------------------------- 0033 0034 KdeConnect::KdeConnect() 0035 { 0036 getDevices(); 0037 0038 QDBusConnection::sessionBus().connect("org.kde.kdeconnect", "/modules/kdeconnect", 0039 "org.kde.kdeconnect.daemon", "deviceAdded", 0040 this, SLOT(deviceAddedSlot(QString))); 0041 0042 QDBusConnection::sessionBus().connect("org.kde.kdeconnect", "/modules/kdeconnect", 0043 "org.kde.kdeconnect.daemon", "deviceRemoved", 0044 this, SLOT(deviceRemovedSlot(QString))); 0045 0046 QDBusConnection::sessionBus().connect("org.kde.kdeconnect", "/modules/kdeconnect", 0047 "org.kde.kdeconnect.daemon", "deviceVisibilityChanged", 0048 this, SLOT(deviceVisibilityChanged(QString, bool))); 0049 } 0050 0051 //-------------------------------------------------------------------------------- 0052 0053 void KdeConnect::getDevices() 0054 { 0055 QDBusMessage msg = 0056 QDBusMessage::createMethodCall("org.kde.kdeconnect", "/modules/kdeconnect", 0057 "org.kde.kdeconnect.daemon", "devices"); 0058 msg << true << true; // onlyReachable, onlyPaired 0059 QDBusConnection::sessionBus().callWithCallback(msg, this, SLOT(gotDevices(QDBusMessage))); 0060 } 0061 0062 //-------------------------------------------------------------------------------- 0063 0064 void KdeConnect::gotDevices(const QDBusMessage &msg) 0065 { 0066 QStringList deviceList = msg.arguments()[0].toStringList(); 0067 0068 //qDebug() << __FUNCTION__ << deviceList; 0069 for (const QString &device : deviceList) 0070 deviceAddedSlot(device); 0071 } 0072 0073 //-------------------------------------------------------------------------------- 0074 0075 void KdeConnect::deviceVisibilityChanged(const QString &dev, bool visible) 0076 { 0077 //qDebug() << __FUNCTION__ << dev << visible; 0078 if ( visible ) 0079 deviceAddedSlot(dev); 0080 else 0081 deviceRemovedSlot(dev); 0082 } 0083 0084 //-------------------------------------------------------------------------------- 0085 0086 void KdeConnect::deviceAddedSlot(const QString &dev) 0087 { 0088 //qDebug() << __FUNCTION__ << dev; 0089 if ( devices.contains(dev) ) 0090 return; 0091 0092 const QString devicePath = "/modules/kdeconnect/devices/" + dev; 0093 0094 QDBusInterface interface("org.kde.kdeconnect", devicePath, "org.kde.kdeconnect.device"); 0095 0096 if ( !interface.property("isTrusted").toBool() || 0097 !interface.property("isReachable").toBool() ) 0098 return; // only show paired, reachable devices 0099 0100 Device device; 0101 device->id = dev; 0102 0103 device->name = interface.property("name").toString(); 0104 0105 QDBusConnection::sessionBus().connect("org.kde.kdeconnect", devicePath, 0106 "org.kde.kdeconnect.device", "nameChanged", 0107 device.data(), SLOT(nameChangedSlot(const QString &))); 0108 0109 QDBusConnection::sessionBus().connect("org.kde.kdeconnect", devicePath, 0110 "org.kde.kdeconnect.device", "pluginsChanged", 0111 device.data(), SLOT(updatePlugins())); 0112 0113 QString type = interface.property("type").toString(); 0114 0115 if ( type == "smartphone" ) 0116 device->icon = QIcon::fromTheme("smartphone"); 0117 else if ( type == "tablet" ) 0118 device->icon = QIcon::fromTheme("tablet"); 0119 else 0120 device->icon = QIcon::fromTheme(interface.property("statusIconName").toString()); 0121 0122 device->updatePlugins(); 0123 0124 devices.insert(dev, device); 0125 0126 emit deviceAdded(device); 0127 } 0128 0129 //-------------------------------------------------------------------------------- 0130 0131 void KdeConnect::deviceRemovedSlot(const QString &dev) 0132 { 0133 if ( !devices.contains(dev) ) 0134 return; 0135 0136 devices.remove(dev); 0137 emit deviceRemoved(dev); 0138 } 0139 0140 //-------------------------------------------------------------------------------- 0141 //-------------------------------------------------------------------------------- 0142 //-------------------------------------------------------------------------------- 0143 0144 void KdeConnectDevice::ringPhone() 0145 { 0146 QDBusMessage msg = 0147 QDBusMessage::createMethodCall("org.kde.kdeconnect", "/modules/kdeconnect/devices/" + id + "/findmyphone", 0148 "org.kde.kdeconnect.device.findmyphone", "ring"); 0149 QDBusConnection::sessionBus().call(msg); 0150 } 0151 0152 //-------------------------------------------------------------------------------- 0153 0154 void KdeConnectDevice::chargeChangedSlot() 0155 { 0156 charge = batteryInterface->property("charge").toInt(); 0157 isCharging = batteryInterface->property("isCharging").toBool(); 0158 0159 //qDebug() << __FUNCTION__ << name << charge << isCharging; 0160 0161 if ( charge < 0 ) 0162 return; 0163 0164 chargeIcon = Battery::getStatusIcon(charge, isCharging); 0165 emit changed(); 0166 0167 if ( isCharging ) 0168 { 0169 if ( notif ) notif->close(); 0170 return; 0171 } 0172 0173 const int LIMIT = 40; 0174 0175 if ( charge < LIMIT ) // I want to keep charge above 40% 0176 { 0177 if ( !warned ) 0178 { 0179 warned = true; 0180 notif = new KNotification("device needs charging", KNotification::Persistent); 0181 notif->setTitle(i18n("Device needs charging")); 0182 notif->setText(i18n("Device charge of '%1' is at %2%.\nYou should charge it.", name, charge)); 0183 notif->setIconName("battery-040"); 0184 notif->sendEvent(); 0185 } 0186 } 0187 else 0188 { 0189 warned = false; 0190 if ( notif ) notif->close(); 0191 } 0192 } 0193 0194 //-------------------------------------------------------------------------------- 0195 0196 void KdeConnectDevice::nameChangedSlot(const QString &newName) 0197 { 0198 //qDebug() << __FUNCTION__ << newName; 0199 name = newName; 0200 emit changed(); 0201 } 0202 0203 //-------------------------------------------------------------------------------- 0204 0205 void KdeConnectDevice::updatePlugins() 0206 { 0207 const QString devicePath = "/modules/kdeconnect/devices/" + id; 0208 QDBusInterface interface("org.kde.kdeconnect", devicePath, "org.kde.kdeconnect.device"); 0209 0210 QDBusReply<QStringList> strings = interface.call("loadedPlugins"); 0211 plugins = strings.value(); 0212 0213 if ( plugins.contains("kdeconnect_battery") ) 0214 { 0215 if ( !batteryInterface ) 0216 { 0217 batteryInterface = new QDBusInterface("org.kde.kdeconnect", devicePath + "/battery", 0218 "org.kde.kdeconnect.device.battery", QDBusConnection::sessionBus(), 0219 this); 0220 0221 chargeChangedSlot(); 0222 0223 connect(batteryInterface, SIGNAL(refreshed(bool, int)), this, SLOT(chargeChangedSlot())); 0224 } 0225 } 0226 else 0227 { 0228 delete batteryInterface; 0229 batteryInterface = nullptr; 0230 charge = -1; 0231 } 0232 0233 emit changed(); 0234 } 0235 0236 //--------------------------------------------------------------------------------