diff --git a/plugins/battery/batteryplugin.cpp b/plugins/battery/batteryplugin.cpp index fa214e43..5371be56 100644 --- a/plugins/battery/batteryplugin.cpp +++ b/plugins/battery/batteryplugin.cpp @@ -1,81 +1,81 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "batteryplugin.h" #include #include #include #include "batterydbusinterface.h" -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_battery.json", registerPlugin< BatteryPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(BatteryPlugin, "kdeconnect_battery.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_BATTERY, "kdeconnect.plugin.battery") BatteryPlugin::BatteryPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , batteryDbusInterface(new BatteryDbusInterface(device())) { //TODO: Add battery reporting, could be based on: // https://www.linux-apps.com/content/show.php/battery+plasmoid+with+remaining+time?content=120309 } void BatteryPlugin::connected() { NetworkPacket np(PACKET_TYPE_BATTERY_REQUEST, {{QStringLiteral("request"),true}}); sendPacket(np); } BatteryPlugin::~BatteryPlugin() { //FIXME: Qt dbus does not allow to remove an adaptor! (it causes a crash in // the next dbus access to its parent). The implication of not deleting this // is that disabling the plugin does not remove the interface (that will // return outdated values) and that enabling it again instantiates a second // adaptor. This is also a memory leak until the entire device is destroyed. //batteryDbusInterface->deleteLater(); } bool BatteryPlugin::receivePacket(const NetworkPacket& np) { bool isCharging = np.get(QStringLiteral("isCharging"), false); int currentCharge = np.get(QStringLiteral("currentCharge"), -1); int thresholdEvent = np.get(QStringLiteral("thresholdEvent"), (int)ThresholdNone); if (batteryDbusInterface->charge() != currentCharge || batteryDbusInterface->isCharging() != isCharging ) { batteryDbusInterface->updateValues(isCharging, currentCharge); } if ( thresholdEvent == ThresholdBatteryLow && !isCharging ) { Daemon::instance()->sendSimpleNotification(QStringLiteral("batteryLow"), i18nc("device name: low battery", "%1: Low Battery", device()->name()), i18n("Battery at %1%", currentCharge), QStringLiteral("battery-040")); } return true; } #include "batteryplugin.moc" diff --git a/plugins/clipboard/clipboardplugin.cpp b/plugins/clipboard/clipboardplugin.cpp index edb37955..d9926968 100644 --- a/plugins/clipboard/clipboardplugin.cpp +++ b/plugins/clipboard/clipboardplugin.cpp @@ -1,51 +1,51 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "clipboardplugin.h" #include "clipboardlistener.h" #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_clipboard.json", registerPlugin< ClipboardPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(ClipboardPlugin, "kdeconnect_clipboard.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_CLIPBOARD, "kdeconnect.plugin.clipboard") ClipboardPlugin::ClipboardPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { connect(ClipboardListener::instance(), &ClipboardListener::clipboardChanged, this, &ClipboardPlugin::propagateClipboard); } void ClipboardPlugin::propagateClipboard(const QString& content) { NetworkPacket np(PACKET_TYPE_CLIPBOARD, {{QStringLiteral("content"), content}}); sendPacket(np); } bool ClipboardPlugin::receivePacket(const NetworkPacket& np) { QString content = np.get(QStringLiteral("content")); ClipboardListener::instance()->setText(content); return true; } #include "clipboardplugin.moc" diff --git a/plugins/contacts/contactsplugin.cpp b/plugins/contacts/contactsplugin.cpp index dfe2788a..7ea4246a 100644 --- a/plugins/contacts/contactsplugin.cpp +++ b/plugins/contacts/contactsplugin.cpp @@ -1,214 +1,213 @@ /** * Copyright 2018 Simon Redman * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON(KdeConnectPluginFactory, "kdeconnect_contacts.json", - registerPlugin(); ) +K_PLUGIN_CLASS_WITH_JSON(ContactsPlugin, "kdeconnect_contacts.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_CONTACTS, "kdeconnect.plugin.contacts") ContactsPlugin::ContactsPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { vcardsPath = QString(*vcardsLocation).append(QStringLiteral("/kdeconnect-").append(device()->id())); // Register custom types with dbus qRegisterMetaType("uID"); qDBusRegisterMetaType(); qRegisterMetaType("uIDList_t"); qDBusRegisterMetaType(); // Create the storage directory if it doesn't exist if (!QDir().mkpath(vcardsPath)) { qCWarning(KDECONNECT_PLUGIN_CONTACTS) << "Unable to create VCard directory"; } qCDebug(KDECONNECT_PLUGIN_CONTACTS) << "Contacts constructor for device " << device()->name(); } void ContactsPlugin::connected() { synchronizeRemoteWithLocal(); } bool ContactsPlugin::receivePacket(const NetworkPacket& np) { //qCDebug(KDECONNECT_PLUGIN_CONTACTS) << "Packet Received for device " << device()->name(); //qCDebug(KDECONNECT_PLUGIN_CONTACTS) << np.body(); if (np.type() == PACKAGE_TYPE_CONTACTS_RESPONSE_UIDS_TIMESTAMPS) { return handleResponseUIDsTimestamps(np); } else if (np.type() == PACKET_TYPE_CONTACTS_RESPONSE_VCARDS) { return handleResponseVCards(np); } else { // Is this check necessary? qCDebug(KDECONNECT_PLUGIN_CONTACTS) << "Unknown packet type received from device: " << device()->name() << ". Maybe you need to upgrade KDE Connect?"; return false; } } void ContactsPlugin::synchronizeRemoteWithLocal() { sendRequest(PACKET_TYPE_CONTACTS_REQUEST_ALL_UIDS_TIMESTAMP); } bool ContactsPlugin::handleResponseUIDsTimestamps(const NetworkPacket& np) { if (!np.has(QStringLiteral("uids"))) { qCDebug(KDECONNECT_PLUGIN_CONTACTS) << "handleResponseUIDsTimestamps:" << "Malformed packet does not have uids key"; return false; } uIDList_t uIDsToUpdate; QDir vcardsDir(vcardsPath); // Get a list of all file info in this directory // Clean out IDs returned from the remote. Anything leftover should be deleted QFileInfoList localVCards = vcardsDir.entryInfoList({QStringLiteral("*.vcard"), QStringLiteral("*.vcf")}); const QStringList& uIDs = np.get(QStringLiteral("uids")); // Check local storage for the contacts: // If the contact is not found in local storage, request its vcard be sent // If the contact is in local storage but not reported, delete it // If the contact is in local storage, compare its timestamp. If different, request the contact for (const QString& ID : uIDs) { QString filename = vcardsDir.filePath(ID + VCARD_EXTENSION); QFile vcardFile(filename); if (!QFile().exists(filename)) { // We do not have a vcard for this contact. Request it. uIDsToUpdate.push_back(ID); continue; } // Remove this file from the list of known files QFileInfo fileInfo(vcardFile); bool success = localVCards.removeOne(fileInfo); Q_ASSERT(success); // We should have always been able to remove the existing file from our listing // Check if the vcard needs to be updated if (!vcardFile.open(QIODevice::ReadOnly)) { qCWarning(KDECONNECT_PLUGIN_CONTACTS) << "handleResponseUIDsTimestamps:" << "Unable to open" << filename << "to read even though it was reported to exist"; continue; } QTextStream fileReadStream(&vcardFile); QString line; while (!fileReadStream.atEnd()) { fileReadStream >> line; // TODO: Check that the saved ID is the same as the one we were expecting. This requires parsing the VCard if (!line.startsWith(QStringLiteral("X-KDECONNECT-TIMESTAMP:"))) { continue; } QStringList parts = line.split(QLatin1Char(':')); QString timestamp = parts[1]; qint32 remoteTimestamp = np.get(ID); qint32 localTimestamp = timestamp.toInt(); if (!(localTimestamp == remoteTimestamp)) { uIDsToUpdate.push_back(ID); } } } // Delete all locally-known files which were not reported by the remote device for (const QFileInfo& unknownFile : localVCards) { QFile toDelete(unknownFile.filePath()); toDelete.remove(); } sendRequestWithIDs(PACKET_TYPE_CONTACTS_REQUEST_VCARDS_BY_UIDS, uIDsToUpdate); return true; } bool ContactsPlugin::handleResponseVCards(const NetworkPacket& np) { if (!np.has(QStringLiteral("uids"))) { qCDebug(KDECONNECT_PLUGIN_CONTACTS) << "handleResponseVCards:" << "Malformed packet does not have uids key"; return false; } QDir vcardsDir(vcardsPath); const QStringList& uIDs = np.get(QStringLiteral("uids")); // Loop over all IDs, extract the VCard from the packet and write the file for (const auto& ID : uIDs) { //qCDebug(KDECONNECT_PLUGIN_CONTACTS) << "Got VCard:" << np.get(ID); QString filename = vcardsDir.filePath(ID + VCARD_EXTENSION); QFile vcardFile(filename); bool vcardFileOpened = vcardFile.open(QIODevice::WriteOnly); // Want to smash anything that might have already been there if (!vcardFileOpened) { qCWarning(KDECONNECT_PLUGIN_CONTACTS) << "handleResponseVCards:" << "Unable to open" << filename; continue; } QTextStream fileWriteStream(&vcardFile); const QString& vcard = np.get(ID); fileWriteStream << vcard; } qCDebug(KDECONNECT_PLUGIN_CONTACTS) << "handleResponseVCards:" << "Got" << uIDs.size() << "VCards"; Q_EMIT localCacheSynchronized(uIDs); return true; } bool ContactsPlugin::sendRequest(const QString& packetType) { NetworkPacket np(packetType); bool success = sendPacket(np); qCDebug(KDECONNECT_PLUGIN_CONTACTS) << "sendRequest: Sending " << packetType << success; return success; } bool ContactsPlugin::sendRequestWithIDs(const QString& packetType, const uIDList_t& uIDs) { NetworkPacket np(packetType); np.set(QStringLiteral("uids"), uIDs); bool success = sendPacket(np); return success; } QString ContactsPlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/contacts"); } #include "contactsplugin.moc" diff --git a/plugins/findmyphone/findmyphoneplugin.cpp b/plugins/findmyphone/findmyphoneplugin.cpp index 3fb8f252..8d49bf9d 100644 --- a/plugins/findmyphone/findmyphoneplugin.cpp +++ b/plugins/findmyphone/findmyphoneplugin.cpp @@ -1,57 +1,57 @@ /** * Copyright 2014 Apoorv Parle * Copyright 2015 David Edmundson * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "findmyphoneplugin.h" #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_findmyphone.json", registerPlugin< FindMyPhonePlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(FindMyPhonePlugin, "kdeconnect_findmyphone.json") FindMyPhonePlugin::FindMyPhonePlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { } FindMyPhonePlugin::~FindMyPhonePlugin() { } bool FindMyPhonePlugin::receivePacket(const NetworkPacket& np) { Q_UNUSED(np); return false; } void FindMyPhonePlugin::ring() { NetworkPacket np(PACKET_TYPE_FINDMYPHONE_REQUEST); sendPacket(np); } QString FindMyPhonePlugin::dbusPath() const { return QString::fromLatin1("/modules/kdeconnect/devices/") + device()->id() + QString::fromLatin1("/findmyphone"); } #include "findmyphoneplugin.moc" diff --git a/plugins/findthisdevice/findthisdeviceplugin.cpp b/plugins/findthisdevice/findthisdeviceplugin.cpp index 824c1d6d..762d9d2d 100644 --- a/plugins/findthisdevice/findthisdeviceplugin.cpp +++ b/plugins/findthisdevice/findthisdeviceplugin.cpp @@ -1,130 +1,129 @@ /** * Copyright 2018 Friedrich W. H. Kossebau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "findthisdeviceplugin.h" // KF #include #ifndef Q_OS_WIN #include #include #endif // Qt #include #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON(KdeConnectPluginFactory, "kdeconnect_findthisdevice.json", - registerPlugin();) +K_PLUGIN_CLASS_WITH_JSON(FindThisDevicePlugin, "kdeconnect_findthisdevice.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_FINDTHISDEVICE, "kdeconnect.plugin.findthisdevice") FindThisDevicePlugin::FindThisDevicePlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { } FindThisDevicePlugin::~FindThisDevicePlugin() = default; void FindThisDevicePlugin::connected() { } bool FindThisDevicePlugin::receivePacket(const NetworkPacket& np) { Q_UNUSED(np); const QString soundFilename = config()->get(QStringLiteral("ringtone"), defaultSound()); QUrl soundURL; #ifdef Q_OS_WIN QString winDirPath = qEnvironmentVariable("WINDIR") + QStringLiteral("/media"); if (!winDirPath.isEmpty()) { soundURL = QUrl::fromUserInput(soundFilename, winDirPath, QUrl::AssumeLocalFile); } else { qCWarning(KDECONNECT_PLUGIN_FINDTHISDEVICE) << "Not playing sounds, system doesn't know WINDIR : " << soundFilename; } #else const auto dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); for (const QString &dataLocation : dataLocations) { soundURL = QUrl::fromUserInput(soundFilename, dataLocation + QStringLiteral("/sounds"), QUrl::AssumeLocalFile); if (soundURL.isLocalFile()) { if (QFile::exists(soundURL.toLocalFile())) { break; } } else { if (soundURL.isValid()) { break; } } soundURL.clear(); } #endif if (soundURL.isEmpty()) { qCWarning(KDECONNECT_PLUGIN_FINDTHISDEVICE) << "Not playing sounds, could not find ring tone" << soundFilename; return true; } QMediaPlayer* player = new QMediaPlayer; player->setAudioRole(QAudio::Role(QAudio::NotificationRole)); player->setMedia(soundURL); player->setVolume(100); player->play(); #ifndef Q_OS_WIN const auto sinks = PulseAudioQt::Context::instance()->sinks(); QVector mutedSinks; for (auto sink : sinks) { if (sink->isMuted()) { sink->setMuted(false); mutedSinks.append(sink); } } connect(player, &QMediaPlayer::stateChanged, this, [player, mutedSinks]{ player->deleteLater(); for (auto sink : qAsConst(mutedSinks)) { sink->setMuted(true); } }); #endif // TODO: ensure to use built-in loudspeakers return true; } QString FindThisDevicePlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/findthisdevice"); } #include "findthisdeviceplugin.moc" diff --git a/plugins/lockdevice/lockdeviceplugin.cpp b/plugins/lockdevice/lockdeviceplugin.cpp index b5327341..454f52e1 100644 --- a/plugins/lockdevice/lockdeviceplugin.cpp +++ b/plugins/lockdevice/lockdeviceplugin.cpp @@ -1,103 +1,103 @@ /** * Copyright 2015 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "lockdeviceplugin.h" #include #include #include #include #include "screensaverdbusinterface.h" #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectLockPluginFactory, "kdeconnect_lockdevice.json", registerPlugin(); ) +K_PLUGIN_CLASS_WITH_JSON(LockDevicePlugin, "kdeconnect_lockdevice.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_LOCKREMOTE, "kdeconnect.plugin.lock") LockDevicePlugin::LockDevicePlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , m_remoteLocked(false) , m_iface(nullptr) { } LockDevicePlugin::~LockDevicePlugin() { delete m_iface; } bool LockDevicePlugin::isLocked() const { return m_remoteLocked; } void LockDevicePlugin::setLocked(bool locked) { NetworkPacket np(PACKET_TYPE_LOCK_REQUEST, {{QStringLiteral("setLocked"), locked}}); sendPacket(np); } bool LockDevicePlugin::receivePacket(const NetworkPacket & np) { if (np.has(QStringLiteral("isLocked"))) { bool locked = np.get(QStringLiteral("isLocked")); if (m_remoteLocked != locked) { m_remoteLocked = locked; Q_EMIT lockedChanged(locked); } } bool sendState = np.has(QStringLiteral("requestLocked")); if (np.has(QStringLiteral("setLocked"))) { iface()->SetActive(np.get(QStringLiteral("setLocked"))); sendState = true; } if (sendState) { NetworkPacket np(PACKET_TYPE_LOCK, QVariantMap {{QStringLiteral("isLocked"), QVariant::fromValue(iface()->GetActive())}}); sendPacket(np); } return true; } OrgFreedesktopScreenSaverInterface* LockDevicePlugin::iface() { if (!m_iface) { m_iface = new OrgFreedesktopScreenSaverInterface(QStringLiteral("org.freedesktop.ScreenSaver"), QStringLiteral("/org/freedesktop/ScreenSaver"), DbusHelper::sessionBus()); if(!m_iface->isValid()) qCWarning(KDECONNECT_PLUGIN_LOCKREMOTE) << "Couldn't connect to the ScreenSaver interface"; } return m_iface; } void LockDevicePlugin::connected() { NetworkPacket np(PACKET_TYPE_LOCK_REQUEST, {{QStringLiteral("requestLocked"), QVariant()}}); sendPacket(np); } QString LockDevicePlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/lockdevice"); } #include "lockdeviceplugin.moc" diff --git a/plugins/mousepad/mousepadplugin.cpp b/plugins/mousepad/mousepadplugin.cpp index c72ea417..1c9b4ddc 100644 --- a/plugins/mousepad/mousepadplugin.cpp +++ b/plugins/mousepad/mousepadplugin.cpp @@ -1,91 +1,91 @@ /** * Copyright 2018 Albert Vaca Cintora * Copyright 2015 Martin Gräßlin * Copyright 2014 Ahmed I. Khalil * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mousepadplugin.h" #include #include #include #if HAVE_WINDOWS #include "windowsremoteinput.h" #else #if HAVE_X11 #include "x11remoteinput.h" #endif #if HAVE_WAYLAND #include "waylandremoteinput.h" #endif #endif -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_mousepad.json", registerPlugin< MousepadPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(MousepadPlugin, "kdeconnect_mousepad.json") MousepadPlugin::MousepadPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , m_impl(nullptr) { #if HAVE_WINDOWS m_impl = new WindowsRemoteInput(this); #else #if HAVE_X11 if (QGuiApplication::platformName() == QLatin1String("xcb")) { m_impl = new X11RemoteInput(this); } #endif #if HAVE_WAYLAND if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) { m_impl = new WaylandRemoteInput(this); } #endif #endif if (!m_impl) { qDebug() << "KDE Connect was built without" << QGuiApplication::platformName() << "support"; } } MousepadPlugin::~MousepadPlugin() { delete m_impl; } bool MousepadPlugin::receivePacket(const NetworkPacket& np) { if (m_impl) { return m_impl->handlePacket(np); } else { return false; } } void MousepadPlugin::connected() { NetworkPacket np(PACKET_TYPE_MOUSEPAD_KEYBOARDSTATE); if (m_impl) { np.set(QStringLiteral("state"), m_impl->hasKeyboardSupport()); } sendPacket(np); } #include "mousepadplugin.moc" diff --git a/plugins/mpriscontrol/mpriscontrolplugin-win.cpp b/plugins/mpriscontrol/mpriscontrolplugin-win.cpp index dd037fd2..c7f74552 100644 --- a/plugins/mpriscontrol/mpriscontrolplugin-win.cpp +++ b/plugins/mpriscontrol/mpriscontrolplugin-win.cpp @@ -1,99 +1,99 @@ #include "mpriscontrolplugin-win.h" #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_mpriscontrol.json", registerPlugin< MprisControlPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(MprisControlPlugin, "kdeconnect_mpriscontrol.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_MPRIS, "kdeconnect.plugin.mpris") MprisControlPlugin::MprisControlPlugin(QObject *parent, const QVariantList &args) : KdeConnectPlugin(parent, args) { } bool MprisControlPlugin::receivePacket(const NetworkPacket &np) { if (np.has(QStringLiteral("playerList"))) { return false; //Whoever sent this is an mpris client and not an mpris control! } //Send the player list const QString player = np.get(QStringLiteral("player")); bool valid_player = (player == playername); if (!valid_player || np.get(QStringLiteral("requestPlayerList"))) { const QList playerlist = {playername}; NetworkPacket np(PACKET_TYPE_MPRIS); np.set(QStringLiteral("playerList"), playerlist); np.set(QStringLiteral("supportAlbumArtPayload"), false); sendPacket(np); if (!valid_player) { return true; } } if (np.has(QStringLiteral("action"))) { INPUT input={0}; input.type = INPUT_KEYBOARD; input.ki.time = 0; input.ki.dwExtraInfo = 0; input.ki.wScan = 0; input.ki.dwFlags = 0; if (np.has(QStringLiteral("action"))) { const QString& action = np.get(QStringLiteral("action")); if (action == QStringLiteral("PlayPause") || (action == QStringLiteral("Play")) || (action == QStringLiteral("Pause")) ) { input.ki.wVk = VK_MEDIA_PLAY_PAUSE; ::SendInput(1,&input,sizeof(INPUT)); } else if (action == QStringLiteral("Stop")) { input.ki.wVk = VK_MEDIA_STOP; ::SendInput(1,&input,sizeof(INPUT)); } else if (action == QStringLiteral("Next")) { input.ki.wVk = VK_MEDIA_NEXT_TRACK; ::SendInput(1,&input,sizeof(INPUT)); } else if (action == QStringLiteral("Previous")) { input.ki.wVk = VK_MEDIA_PREV_TRACK; ::SendInput(1,&input,sizeof(INPUT)); } else if (action == QStringLiteral("Stop")) { input.ki.wVk = VK_MEDIA_STOP; ::SendInput(1,&input,sizeof(INPUT)); } } } NetworkPacket answer(PACKET_TYPE_MPRIS); bool somethingToSend = false; if (np.get(QStringLiteral("requestNowPlaying"))) { answer.set(QStringLiteral("pos"), 0); answer.set(QStringLiteral("isPlaying"), false); answer.set(QStringLiteral("canPause"), false); answer.set(QStringLiteral("canPlay"), true); answer.set(QStringLiteral("canGoNext"), true); answer.set(QStringLiteral("canGoPrevious"), true); answer.set(QStringLiteral("canSeek"), false); somethingToSend = true; } if (np.get(QStringLiteral("requestVolume"))) { answer.set(QStringLiteral("volume"), 100); somethingToSend = true; } if (somethingToSend) { answer.set(QStringLiteral("player"), player); sendPacket(answer); } return true; } #include "mpriscontrolplugin-win.moc" \ No newline at end of file diff --git a/plugins/mpriscontrol/mpriscontrolplugin.cpp b/plugins/mpriscontrol/mpriscontrolplugin.cpp index 6d59eb6a..6bd58f1b 100644 --- a/plugins/mpriscontrol/mpriscontrolplugin.cpp +++ b/plugins/mpriscontrol/mpriscontrolplugin.cpp @@ -1,382 +1,382 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mpriscontrolplugin.h" #include #include #include #include #include #include #include #include #include #include "mprisdbusinterface.h" #include "propertiesdbusinterface.h" -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_mpriscontrol.json", registerPlugin< MprisControlPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(MprisControlPlugin, "kdeconnect_mpriscontrol.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_MPRIS, "kdeconnect.plugin.mpris") MprisPlayer::MprisPlayer(const QString& serviceName, const QString& dbusObjectPath, const QDBusConnection& busConnection) : m_serviceName(serviceName) , m_propertiesInterface(new OrgFreedesktopDBusPropertiesInterface(serviceName, dbusObjectPath, busConnection)) , m_mediaPlayer2PlayerInterface(new OrgMprisMediaPlayer2PlayerInterface(serviceName, dbusObjectPath, busConnection)) { m_mediaPlayer2PlayerInterface->setTimeout(500); } MprisControlPlugin::MprisControlPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , prevVolume(-1) { m_watcher = new QDBusServiceWatcher(QString(), DbusHelper::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this); // TODO: QDBusConnectionInterface::serviceOwnerChanged is deprecated, maybe query org.freedesktop.DBus directly? connect(DbusHelper::sessionBus().interface(), &QDBusConnectionInterface::serviceOwnerChanged, this, &MprisControlPlugin::serviceOwnerChanged); //Add existing interfaces const QStringList services = DbusHelper::sessionBus().interface()->registeredServiceNames().value(); for (const QString& service : services) { // The string doesn't matter, it just needs to be empty/non-empty serviceOwnerChanged(service, QLatin1String(""), QStringLiteral("1")); } } // Copied from the mpris2 dataengine in the plasma-workspace repository void MprisControlPlugin::serviceOwnerChanged(const QString& serviceName, const QString& oldOwner, const QString& newOwner) { if (!serviceName.startsWith(QLatin1String("org.mpris.MediaPlayer2."))) return; if (!oldOwner.isEmpty()) { qCDebug(KDECONNECT_PLUGIN_MPRIS) << "MPRIS service" << serviceName << "just went offline"; removePlayer(serviceName); } if (!newOwner.isEmpty()) { qCDebug(KDECONNECT_PLUGIN_MPRIS) << "MPRIS service" << serviceName << "just came online"; addPlayer(serviceName); } } void MprisControlPlugin::addPlayer(const QString& service) { const QString mediaPlayerObjectPath = QStringLiteral("/org/mpris/MediaPlayer2"); // estimate identifier string QDBusInterface mprisInterface(service, mediaPlayerObjectPath, QStringLiteral("org.mpris.MediaPlayer2")); //FIXME: This call hangs and returns an empty string if KDED is still starting! QString identity = mprisInterface.property("Identity").toString(); if (identity.isEmpty()) { identity = service.mid(sizeof("org.mpris.MediaPlayer2")); } QString uniqueName = identity; for (int i = 2; playerList.contains(uniqueName); ++i) { uniqueName = identity + QLatin1String(" [") + QString::number(i) + QLatin1Char(']'); } MprisPlayer player(service, mediaPlayerObjectPath, DbusHelper::sessionBus()); playerList.insert(uniqueName, player); connect(player.propertiesInterface(), &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, this, &MprisControlPlugin::propertiesChanged); connect(player.mediaPlayer2PlayerInterface(), &OrgMprisMediaPlayer2PlayerInterface::Seeked, this, &MprisControlPlugin::seeked); qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Mpris addPlayer" << service << "->" << uniqueName; sendPlayerList(); } void MprisControlPlugin::seeked(qlonglong position){ //qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Seeked in player"; OrgMprisMediaPlayer2PlayerInterface* mediaPlayer2PlayerInterface = (OrgMprisMediaPlayer2PlayerInterface*)sender(); const auto end = playerList.constEnd(); const auto it = std::find_if(playerList.constBegin(), end, [mediaPlayer2PlayerInterface](const MprisPlayer& player) { return (player.mediaPlayer2PlayerInterface() == mediaPlayer2PlayerInterface); }); if (it == end) { qCWarning(KDECONNECT_PLUGIN_MPRIS) << "Seeked signal received for no longer tracked service" << mediaPlayer2PlayerInterface->service(); return; } const QString& playerName = it.key(); NetworkPacket np(PACKET_TYPE_MPRIS, { {QStringLiteral("pos"), position/1000}, //Send milis instead of nanos {QStringLiteral("player"), playerName} }); sendPacket(np); } void MprisControlPlugin::propertiesChanged(const QString& propertyInterface, const QVariantMap& properties) { Q_UNUSED(propertyInterface); OrgFreedesktopDBusPropertiesInterface* propertiesInterface = (OrgFreedesktopDBusPropertiesInterface*)sender(); const auto end = playerList.constEnd(); const auto it = std::find_if(playerList.constBegin(), end, [propertiesInterface](const MprisPlayer& player) { return (player.propertiesInterface() == propertiesInterface); }); if (it == end) { qCWarning(KDECONNECT_PLUGIN_MPRIS) << "PropertiesChanged signal received for no longer tracked service" << propertiesInterface->service(); return; } OrgMprisMediaPlayer2PlayerInterface* const mediaPlayer2PlayerInterface = it.value().mediaPlayer2PlayerInterface(); const QString& playerName = it.key(); NetworkPacket np(PACKET_TYPE_MPRIS); bool somethingToSend = false; if (properties.contains(QStringLiteral("Volume"))) { int volume = (int) (properties[QStringLiteral("Volume")].toDouble()*100); if (volume != prevVolume) { np.set(QStringLiteral("volume"),volume); prevVolume = volume; somethingToSend = true; } } if (properties.contains(QStringLiteral("Metadata"))) { QDBusArgument bullshit = qvariant_cast(properties[QStringLiteral("Metadata")]); QVariantMap nowPlayingMap; bullshit >> nowPlayingMap; mprisPlayerMetadataToNetworkPacket(np, nowPlayingMap); somethingToSend = true; } if (properties.contains(QStringLiteral("PlaybackStatus"))) { bool playing = (properties[QStringLiteral("PlaybackStatus")].toString() == QLatin1String("Playing")); np.set(QStringLiteral("isPlaying"), playing); somethingToSend = true; } if (properties.contains(QStringLiteral("CanPause"))) { np.set(QStringLiteral("canPause"), properties[QStringLiteral("CanPause")].toBool()); somethingToSend = true; } if (properties.contains(QStringLiteral("CanPlay"))) { np.set(QStringLiteral("canPlay"), properties[QStringLiteral("CanPlay")].toBool()); somethingToSend = true; } if (properties.contains(QStringLiteral("CanGoNext"))) { np.set(QStringLiteral("canGoNext"), properties[QStringLiteral("CanGoNext")].toBool()); somethingToSend = true; } if (properties.contains(QStringLiteral("CanGoPrevious"))) { np.set(QStringLiteral("canGoPrevious"), properties[QStringLiteral("CanGoPrevious")].toBool()); somethingToSend = true; } if (properties.contains(QStringLiteral("CanSeek"))) { np.set(QStringLiteral("canSeek"), properties[QStringLiteral("CanSeek")].toBool()); somethingToSend = true; } if (somethingToSend) { np.set(QStringLiteral("player"), playerName); // Always also update the position if (mediaPlayer2PlayerInterface->canSeek()) { long long pos = mediaPlayer2PlayerInterface->position(); np.set(QStringLiteral("pos"), pos/1000); //Send milis instead of nanos } sendPacket(np); } } void MprisControlPlugin::removePlayer(const QString& serviceName) { const auto end = playerList.end(); const auto it = std::find_if(playerList.begin(), end, [serviceName](const MprisPlayer& player) { return (player.serviceName() == serviceName); }); if (it == end) { qCWarning(KDECONNECT_PLUGIN_MPRIS) << "Could not find player for serviceName" << serviceName; return; } const QString& playerName = it.key(); qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Mpris removePlayer" << serviceName << "->" << playerName; playerList.erase(it); sendPlayerList(); } bool MprisControlPlugin::sendAlbumArt(const NetworkPacket& np) { const QString player = np.get(QStringLiteral("player")); auto it = playerList.find(player); bool valid_player = (it != playerList.end()); if (!valid_player) { return false; } //Get mpris information auto& mprisInterface = *it.value().mediaPlayer2PlayerInterface(); QVariantMap nowPlayingMap = mprisInterface.metadata(); //Check if the supplied album art url indeed belongs to this mpris player QUrl playerAlbumArtUrl{nowPlayingMap[QStringLiteral("mpris:artUrl")].toString()}; QString requestedAlbumArtUrl = np.get(QStringLiteral("albumArtUrl")); if (!playerAlbumArtUrl.isValid() || playerAlbumArtUrl != QUrl(requestedAlbumArtUrl)) { return false; } //Only support sending local files if (playerAlbumArtUrl.scheme() != QStringLiteral("file")) { return false; } //Open the file to send QSharedPointer art{new QFile(playerAlbumArtUrl.toLocalFile())}; //Send the album art as payload NetworkPacket answer(PACKET_TYPE_MPRIS); answer.set(QStringLiteral("transferringAlbumArt"), true); answer.set(QStringLiteral("player"), player); answer.set(QStringLiteral("albumArtUrl"), requestedAlbumArtUrl); answer.setPayload(art, art->size()); sendPacket(answer); return true; } bool MprisControlPlugin::receivePacket (const NetworkPacket& np) { if (np.has(QStringLiteral("playerList"))) { return false; //Whoever sent this is an mpris client and not an mpris control! } if (np.has(QStringLiteral("albumArtUrl"))) { return sendAlbumArt(np); } //Send the player list const QString player = np.get(QStringLiteral("player")); auto it = playerList.find(player); bool valid_player = (it != playerList.end()); if (!valid_player || np.get(QStringLiteral("requestPlayerList"))) { sendPlayerList(); if (!valid_player) { return true; } } //Do something to the mpris interface const QString& serviceName = it.value().serviceName(); // turn from pointer to reference to keep the patch diff small, // actual patch would change all "mprisInterface." into "mprisInterface->" auto& mprisInterface = *it.value().mediaPlayer2PlayerInterface(); if (np.has(QStringLiteral("action"))) { const QString& action = np.get(QStringLiteral("action")); //qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Calling action" << action << "in" << serviceName; //TODO: Check for valid actions, currently we trust anything the other end sends us mprisInterface.call(action); } if (np.has(QStringLiteral("setVolume"))) { double volume = np.get(QStringLiteral("setVolume"))/100.f; qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Setting volume" << volume << "to" << serviceName; mprisInterface.setVolume(volume); } if (np.has(QStringLiteral("Seek"))) { int offset = np.get(QStringLiteral("Seek")); //qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Seeking" << offset << "to" << serviceName; mprisInterface.Seek(offset); } if (np.has(QStringLiteral("SetPosition"))){ qlonglong position = np.get(QStringLiteral("SetPosition"),0)*1000; qlonglong seek = position - mprisInterface.position(); //qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Setting position by seeking" << seek << "to" << serviceName; mprisInterface.Seek(seek); } //Send something read from the mpris interface NetworkPacket answer(PACKET_TYPE_MPRIS); bool somethingToSend = false; if (np.get(QStringLiteral("requestNowPlaying"))) { QVariantMap nowPlayingMap = mprisInterface.metadata(); mprisPlayerMetadataToNetworkPacket(answer, nowPlayingMap); qlonglong pos = mprisInterface.position(); answer.set(QStringLiteral("pos"), pos/1000); bool playing = (mprisInterface.playbackStatus() == QLatin1String("Playing")); answer.set(QStringLiteral("isPlaying"), playing); answer.set(QStringLiteral("canPause"), mprisInterface.canPause()); answer.set(QStringLiteral("canPlay"), mprisInterface.canPlay()); answer.set(QStringLiteral("canGoNext"), mprisInterface.canGoNext()); answer.set(QStringLiteral("canGoPrevious"), mprisInterface.canGoPrevious()); answer.set(QStringLiteral("canSeek"), mprisInterface.canSeek()); somethingToSend = true; } if (np.get(QStringLiteral("requestVolume"))) { int volume = (int)(mprisInterface.volume() * 100); answer.set(QStringLiteral("volume"),volume); somethingToSend = true; } if (somethingToSend) { answer.set(QStringLiteral("player"), player); sendPacket(answer); } return true; } void MprisControlPlugin::sendPlayerList() { NetworkPacket np(PACKET_TYPE_MPRIS); np.set(QStringLiteral("playerList"),playerList.keys()); np.set(QStringLiteral("supportAlbumArtPayload"), true); sendPacket(np); } void MprisControlPlugin::mprisPlayerMetadataToNetworkPacket(NetworkPacket& np, const QVariantMap& nowPlayingMap) const { QString title = nowPlayingMap[QStringLiteral("xesam:title")].toString(); QString artist = nowPlayingMap[QStringLiteral("xesam:artist")].toString(); QString album = nowPlayingMap[QStringLiteral("xesam:album")].toString(); QString albumArtUrl = nowPlayingMap[QStringLiteral("mpris:artUrl")].toString(); QString nowPlaying = title; if (!artist.isEmpty()) { nowPlaying = artist + QStringLiteral(" - ") + title; } np.set(QStringLiteral("title"), title); np.set(QStringLiteral("artist"), artist); np.set(QStringLiteral("album"), album); np.set(QStringLiteral("albumArtUrl"), albumArtUrl); np.set(QStringLiteral("nowPlaying"), nowPlaying); bool hasLength = false; long long length = nowPlayingMap[QStringLiteral("mpris:length")].toLongLong(&hasLength) / 1000; //nanoseconds to milliseconds if (!hasLength) { length = -1; } np.set(QStringLiteral("length"), length); } #include "mpriscontrolplugin.moc" diff --git a/plugins/mprisremote/mprisremoteplugin.cpp b/plugins/mprisremote/mprisremoteplugin.cpp index be89115e..edb25395 100644 --- a/plugins/mprisremote/mprisremoteplugin.cpp +++ b/plugins/mprisremote/mprisremoteplugin.cpp @@ -1,206 +1,206 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mprisremoteplugin.h" #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_mprisremote.json", registerPlugin< MprisRemotePlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(MprisRemotePlugin, "kdeconnect_mprisremote.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_MPRISREMOTE, "kdeconnect.plugin.mprisremote") MprisRemotePlugin::MprisRemotePlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , m_currentPlayer() , m_players() { } MprisRemotePlugin::~MprisRemotePlugin() { } bool MprisRemotePlugin::receivePacket(const NetworkPacket& np) { if (np.type() != PACKET_TYPE_MPRIS) return false; if (np.has(QStringLiteral("player"))) { const QString player = np.get(QStringLiteral("player")); if(!m_players.contains(player)) { m_players[player] = new MprisRemotePlayer(); } m_players[player]->parseNetworkPacket(np); } if (np.has(QStringLiteral("playerList"))) { QStringList players = np.get(QStringLiteral("playerList")); qDeleteAll(m_players); m_players.clear(); for (const QString& player : players) { m_players[player] = new MprisRemotePlayer(); requestPlayerStatus(player); } if (m_players.empty()) { m_currentPlayer = QString(); } else if (!m_players.contains(m_currentPlayer)) { m_currentPlayer = m_players.firstKey(); } } Q_EMIT propertiesChanged(); return true; } long MprisRemotePlugin::position() const { auto player = m_players.value(m_currentPlayer); return player ? player->position() : 0; } QString MprisRemotePlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/mprisremote"); } void MprisRemotePlugin::requestPlayerStatus(const QString& player) { NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { {QStringLiteral("player"), player}, {QStringLiteral("requestNowPlaying"), true}, {QStringLiteral("requestVolume"), true}} ); sendPacket(np); } void MprisRemotePlugin::requestPlayerList() { NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, {{QStringLiteral("requestPlayerList"), true}}); sendPacket(np); } void MprisRemotePlugin::sendAction(const QString& action) { NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { {QStringLiteral("player"), m_currentPlayer}, {QStringLiteral("action"), action} }); sendPacket(np); } void MprisRemotePlugin::seek(int offset) const { NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { {QStringLiteral("player"), m_currentPlayer}, {QStringLiteral("Seek"), offset}}); sendPacket(np); } void MprisRemotePlugin::setVolume(int volume) { NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { {QStringLiteral("player"), m_currentPlayer}, {QStringLiteral("setVolume"), volume} }); sendPacket(np); } void MprisRemotePlugin::setPosition(int position) { NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { {QStringLiteral("player"), m_currentPlayer}, {QStringLiteral("SetPosition"), position} }); sendPacket(np); m_players[m_currentPlayer]->setPosition(position); } void MprisRemotePlugin::setPlayer(const QString& player) { if (m_currentPlayer != player) { m_currentPlayer = player; requestPlayerStatus(player); Q_EMIT propertiesChanged(); } } bool MprisRemotePlugin::isPlaying() const { auto player = m_players.value(m_currentPlayer); return player ? player->playing() : false; } int MprisRemotePlugin::length() const { auto player = m_players.value(m_currentPlayer); return player ? player->length() : 0; } int MprisRemotePlugin::volume() const { auto player = m_players.value(m_currentPlayer); return player ? player->volume() : 0; } QString MprisRemotePlugin::player() const { if (m_currentPlayer.isEmpty()) return QString(); return m_currentPlayer; } QStringList MprisRemotePlugin::playerList() const { return m_players.keys(); } QString MprisRemotePlugin::nowPlaying() const { auto player = m_players.value(m_currentPlayer); return player ? player->nowPlaying() : QString(); } QString MprisRemotePlugin::title() const { auto player = m_players.value(m_currentPlayer); return player ? player->title() : QString(); } QString MprisRemotePlugin::album() const { auto player = m_players.value(m_currentPlayer); return player ? player->album() : QString(); } QString MprisRemotePlugin::artist() const { auto player = m_players.value(m_currentPlayer); return player ? player->artist() : QString(); } #include "mprisremoteplugin.moc" diff --git a/plugins/notifications/notificationsplugin.cpp b/plugins/notifications/notificationsplugin.cpp index 3fb979b8..115f341f 100644 --- a/plugins/notifications/notificationsplugin.cpp +++ b/plugins/notifications/notificationsplugin.cpp @@ -1,64 +1,64 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "notificationsplugin.h" #include "notificationsdbusinterface.h" #include "notification_debug.h" #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_notifications.json", registerPlugin< NotificationsPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(NotificationsPlugin, "kdeconnect_notifications.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_NOTIFICATION, "kdeconnect.plugin.notification") NotificationsPlugin::NotificationsPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { notificationsDbusInterface = new NotificationsDbusInterface(this); } void NotificationsPlugin::connected() { NetworkPacket np(PACKET_TYPE_NOTIFICATION_REQUEST, {{QStringLiteral("request"), true}}); sendPacket(np); } NotificationsPlugin::~NotificationsPlugin() { qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Destroying NotificationsPlugin"; //FIXME: Qt dbus does not allow to remove an adaptor! (it causes a crash in // the next dbus access to its parent). The implication of not deleting this // is that disabling the plugin leaks the interface. As a mitigation we are // cleaning up the notifications inside the adaptor here. //notificationsDbusInterface->deleteLater(); notificationsDbusInterface->clearNotifications(); } bool NotificationsPlugin::receivePacket(const NetworkPacket& np) { if (np.get(QStringLiteral("request"))) return false; notificationsDbusInterface->processPacket(np); return true; } #include "notificationsplugin.moc" diff --git a/plugins/pausemusic/pausemusicplugin.cpp b/plugins/pausemusic/pausemusicplugin.cpp index 0e8c2717..bd3fcd06 100644 --- a/plugins/pausemusic/pausemusicplugin.cpp +++ b/plugins/pausemusic/pausemusicplugin.cpp @@ -1,128 +1,128 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "pausemusicplugin.h" #include #include #include #include #include #include #include #include //In older Qt released, qAsConst isnt available #include "qtcompat_p.h" -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_pausemusic.json", registerPlugin< PauseMusicPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(PauseMusicPlugin, "kdeconnect_pausemusic.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_PAUSEMUSIC, "kdeconnect.plugin.pausemusic") PauseMusicPlugin::PauseMusicPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , mutedSinks() {} bool PauseMusicPlugin::receivePacket(const NetworkPacket& np) { bool pauseOnlyWhenTalking = config()->get(QStringLiteral("conditionTalking"), false); if (pauseOnlyWhenTalking) { if (np.get(QStringLiteral("event")) != QLatin1String("talking")) { return true; } } else { //Pause as soon as it rings if (np.get(QStringLiteral("event")) != QLatin1String("ringing") && np.get(QStringLiteral("event")) != QLatin1String("talking")) { return true; } } bool pauseConditionFulfilled = !np.get(QStringLiteral("isCancel")); bool pause = config()->get(QStringLiteral("actionPause"), true); bool mute = config()->get(QStringLiteral("actionMute"), false); if (pauseConditionFulfilled) { if (mute) { qCDebug(KDECONNECT_PLUGIN_PAUSEMUSIC) << "Muting system volume"; const auto sinks = PulseAudioQt::Context::instance()->sinks(); for (const auto sink : sinks) { if (!sink->isMuted()) { sink->setMuted(true); mutedSinks.insert(sink->name()); } } } if (pause) { //Search for interfaces currently playing const QStringList interfaces = DbusHelper::sessionBus().interface()->registeredServiceNames().value(); for (const QString& iface : interfaces) { if (iface.startsWith(QLatin1String("org.mpris.MediaPlayer2"))) { QDBusInterface mprisInterface(iface, QStringLiteral("/org/mpris/MediaPlayer2"), QStringLiteral("org.mpris.MediaPlayer2.Player")); QString status = mprisInterface.property("PlaybackStatus").toString(); if (status == QLatin1String("Playing")) { if (!pausedSources.contains(iface)) { pausedSources.insert(iface); if (mprisInterface.property("CanPause").toBool()) { mprisInterface.asyncCall(QStringLiteral("Pause")); } else { mprisInterface.asyncCall(QStringLiteral("Stop")); } } } } } } } else { if (mute) { qCDebug(KDECONNECT_PLUGIN_PAUSEMUSIC) << "Unmuting system volume"; const auto sinks = PulseAudioQt::Context::instance()->sinks(); for (const auto sink : sinks) { if (mutedSinks.contains(sink->name())) { sink->setMuted(false); } } mutedSinks.clear(); } if (pause && !pausedSources.empty()) { for (const QString& iface : qAsConst(pausedSources)) { QDBusInterface mprisInterface(iface, QStringLiteral("/org/mpris/MediaPlayer2"), QStringLiteral("org.mpris.MediaPlayer2.Player")); mprisInterface.asyncCall(QStringLiteral("Play")); } pausedSources.clear(); } } return true; } #include "pausemusicplugin.moc" diff --git a/plugins/photo/photoplugin.cpp b/plugins/photo/photoplugin.cpp index 2260d77b..1db8e6fa 100644 --- a/plugins/photo/photoplugin.cpp +++ b/plugins/photo/photoplugin.cpp @@ -1,72 +1,72 @@ /** * Copyright 2019 Nicolas Fella * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "photoplugin.h" #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_photo.json", registerPlugin< PhotoPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(PhotoPlugin, "kdeconnect_photo.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_PHOTO, "kdeconnect.plugin.photo") PhotoPlugin::PhotoPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { } PhotoPlugin::~PhotoPlugin() { } bool PhotoPlugin::receivePacket(const NetworkPacket& np) { if (requestedFiles.isEmpty() || !np.hasPayload()) { return true; } const QString& fileName = requestedFiles.takeFirst(); FileTransferJob* job = np.createPayloadTransferJob(QUrl::fromLocalFile(fileName)); connect(job, &FileTransferJob::result, this, [this, fileName] { Q_EMIT photoReceived(fileName); }); job->start(); return true; } void PhotoPlugin::requestPhoto(const QString& fileName) { requestedFiles.append(fileName); NetworkPacket np(PACKET_TYPE_PHOTO_REQUEST); sendPacket(np); } QString PhotoPlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/photo"); } #include "photoplugin.moc" diff --git a/plugins/ping/pingplugin.cpp b/plugins/ping/pingplugin.cpp index 91e79c27..a324acc5 100644 --- a/plugins/ping/pingplugin.cpp +++ b/plugins/ping/pingplugin.cpp @@ -1,78 +1,78 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "pingplugin.h" #include #include #include #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_ping.json", registerPlugin< PingPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(PingPlugin, "kdeconnect_ping.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_PING, "kdeconnect.plugin.ping") PingPlugin::PingPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { // qCDebug(KDECONNECT_PLUGIN_PING) << "Ping plugin constructor for device" << device()->name(); } PingPlugin::~PingPlugin() { // qCDebug(KDECONNECT_PLUGIN_PING) << "Ping plugin destructor for device" << device()->name(); } bool PingPlugin::receivePacket(const NetworkPacket& np) { Daemon::instance()->sendSimpleNotification(QStringLiteral("pingReceived"), device()->name(), np.get(QStringLiteral("message"),i18n("Ping!")), QStringLiteral("dialog-ok")); return true; } void PingPlugin::sendPing() { NetworkPacket np(PACKET_TYPE_PING); bool success = sendPacket(np); qCDebug(KDECONNECT_PLUGIN_PING) << "sendPing:" << success; } void PingPlugin::sendPing(const QString& customMessage) { NetworkPacket np(PACKET_TYPE_PING); if (!customMessage.isEmpty()) { np.set(QStringLiteral("message"), customMessage); } bool success = sendPacket(np); qCDebug(KDECONNECT_PLUGIN_PING) << "sendPing:" << success; } QString PingPlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/ping"); } #include "pingplugin.moc" diff --git a/plugins/remotecommands/remotecommandsplugin.cpp b/plugins/remotecommands/remotecommandsplugin.cpp index 4796b2f1..4b103c1c 100644 --- a/plugins/remotecommands/remotecommandsplugin.cpp +++ b/plugins/remotecommands/remotecommandsplugin.cpp @@ -1,87 +1,87 @@ /** * Copyright 2016 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "remotecommandsplugin.h" #include #include #include #include #define PACKET_TYPE_RUNCOMMAND_REQUEST QLatin1String("kdeconnect.runcommand.request") -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_remotecommands.json", registerPlugin< RemoteCommandsPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(RemoteCommandsPlugin, "kdeconnect_remotecommands.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_REMOTECOMMANDS, "kdeconnect.plugin.remotecommands") RemoteCommandsPlugin::RemoteCommandsPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , m_commands("{}") , m_canAddCommand(false) { } RemoteCommandsPlugin::~RemoteCommandsPlugin() = default; bool RemoteCommandsPlugin::receivePacket(const NetworkPacket& np) { if (np.has(QStringLiteral("commandList"))) { m_canAddCommand = np.get(QStringLiteral("canAddCommand")); setCommands(np.get(QStringLiteral("commandList"))); return true; } return false; } void RemoteCommandsPlugin::connected() { NetworkPacket np(PACKET_TYPE_RUNCOMMAND_REQUEST, {{QStringLiteral("requestCommandList"), true}}); sendPacket(np); } QString RemoteCommandsPlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/remotecommands"); } void RemoteCommandsPlugin::setCommands(const QByteArray& cmds) { if (m_commands != cmds) { m_commands = cmds; Q_EMIT commandsChanged(m_commands); } } void RemoteCommandsPlugin::triggerCommand(const QString& key) { NetworkPacket np(PACKET_TYPE_RUNCOMMAND_REQUEST, {{QStringLiteral("key"), key }}); sendPacket(np); } void RemoteCommandsPlugin::editCommands() { NetworkPacket np(PACKET_TYPE_RUNCOMMAND_REQUEST, {{QStringLiteral("setup"), true }}); sendPacket(np); } #include "remotecommandsplugin.moc" diff --git a/plugins/remotecontrol/remotecontrolplugin.cpp b/plugins/remotecontrol/remotecontrolplugin.cpp index 939f7d28..dd6eb668 100644 --- a/plugins/remotecontrol/remotecontrolplugin.cpp +++ b/plugins/remotecontrol/remotecontrolplugin.cpp @@ -1,65 +1,65 @@ /** * Copyright 2015 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "remotecontrolplugin.h" #include #include #include #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_remotecontrol.json", registerPlugin< RemoteControlPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(RemoteControlPlugin, "kdeconnect_remotecontrol.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_REMOTECONTROL, "kdeconnect.plugin.remotecontrol") RemoteControlPlugin::RemoteControlPlugin(QObject* parent, const QVariantList &args) : KdeConnectPlugin(parent, args) { } RemoteControlPlugin::~RemoteControlPlugin() {} void RemoteControlPlugin::moveCursor(const QPoint &p) { NetworkPacket np(PACKET_TYPE_MOUSEPAD_REQUEST, { {QStringLiteral("dx"), p.x()}, {QStringLiteral("dy"), p.y()} }); sendPacket(np); } void RemoteControlPlugin::sendCommand(const QString &name, bool val) { NetworkPacket np(PACKET_TYPE_MOUSEPAD_REQUEST, {{name, val}}); sendPacket(np); } QString RemoteControlPlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/remotecontrol"); } #include "remotecontrolplugin.moc" diff --git a/plugins/remotekeyboard/remotekeyboardplugin.cpp b/plugins/remotekeyboard/remotekeyboardplugin.cpp index 9ac8272a..8c9c087e 100644 --- a/plugins/remotekeyboard/remotekeyboardplugin.cpp +++ b/plugins/remotekeyboard/remotekeyboardplugin.cpp @@ -1,148 +1,148 @@ /** * Copyright 2017 Holger Kaelberer * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "remotekeyboardplugin.h" #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_remotekeyboard.json", registerPlugin< RemoteKeyboardPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(RemoteKeyboardPlugin, "kdeconnect_remotekeyboard.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_REMOTEKEYBOARD, "kdeconnect.plugin.remotekeyboard"); // Mapping of Qt::Key to internal codes, corresponds to the mapping in mousepadplugin QMap specialKeysMap = { //0, // Invalid {Qt::Key_Backspace, 1}, {Qt::Key_Tab, 2}, //XK_Linefeed, // 3 {Qt::Key_Left, 4}, {Qt::Key_Up, 5}, {Qt::Key_Right, 6}, {Qt::Key_Down, 7}, {Qt::Key_PageUp, 8}, {Qt::Key_PageDown, 9}, {Qt::Key_Home, 10}, {Qt::Key_End, 11}, {Qt::Key_Return, 12}, {Qt::Key_Enter, 12}, {Qt::Key_Delete, 13}, {Qt::Key_Escape, 14}, {Qt::Key_SysReq, 15}, {Qt::Key_ScrollLock, 16}, //0, // 17 //0, // 18 //0, // 19 //0, // 20 {Qt::Key_F1, 21}, {Qt::Key_F2, 22}, {Qt::Key_F3, 23}, {Qt::Key_F4, 24}, {Qt::Key_F5, 25}, {Qt::Key_F6, 26}, {Qt::Key_F7, 27}, {Qt::Key_F8, 28}, {Qt::Key_F9, 29}, {Qt::Key_F10, 30}, {Qt::Key_F11, 31}, {Qt::Key_F12, 32}, }; RemoteKeyboardPlugin::RemoteKeyboardPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , m_remoteState(false) { } RemoteKeyboardPlugin::~RemoteKeyboardPlugin() { } bool RemoteKeyboardPlugin::receivePacket(const NetworkPacket& np) { if (np.type() == PACKET_TYPE_MOUSEPAD_ECHO) { if (!np.has(QStringLiteral("isAck")) || !np.has(QStringLiteral("key"))) { qCWarning(KDECONNECT_PLUGIN_REMOTEKEYBOARD) << "Invalid packet of type" << PACKET_TYPE_MOUSEPAD_ECHO; return false; } // qCWarning(KDECONNECT_PLUGIN_REMOTEKEYBOARD) << "Received keypress" << np; Q_EMIT keyPressReceived(np.get(QStringLiteral("key")), np.get(QStringLiteral("specialKey"), 0), np.get(QStringLiteral("shift"), false), np.get(QStringLiteral("ctrl"), false), np.get(QStringLiteral("alt"), 0)); return true; } else if (np.type() == PACKET_TYPE_MOUSEPAD_KEYBOARDSTATE) { // qCWarning(KDECONNECT_PLUGIN_REMOTEKEYBOARD) << "Received keyboardstate" << np; if (m_remoteState != np.get(QStringLiteral("state"))) { m_remoteState = np.get(QStringLiteral("state")); Q_EMIT remoteStateChanged(m_remoteState); } return true; } return false; } void RemoteKeyboardPlugin::sendKeyPress(const QString& key, int specialKey, bool shift, bool ctrl, bool alt, bool sendAck) const { NetworkPacket np(PACKET_TYPE_MOUSEPAD_REQUEST, { {QStringLiteral("key"), key}, {QStringLiteral("specialKey"), specialKey}, {QStringLiteral("shift"), shift}, {QStringLiteral("ctrl"), ctrl}, {QStringLiteral("alt"), alt}, {QStringLiteral("sendAck"), sendAck} }); sendPacket(np); } void RemoteKeyboardPlugin::sendQKeyEvent(const QVariantMap& keyEvent, bool sendAck) const { if (!keyEvent.contains(QStringLiteral("key"))) return; int k = translateQtKey(keyEvent.value(QStringLiteral("key")).toInt()); int modifiers = keyEvent.value(QStringLiteral("modifiers")).toInt(); sendKeyPress(keyEvent.value(QStringLiteral("text")).toString(), k, modifiers & Qt::ShiftModifier, modifiers & Qt::ControlModifier, modifiers & Qt::AltModifier, sendAck); } int RemoteKeyboardPlugin::translateQtKey(int qtKey) const { return specialKeysMap.value(qtKey, 0); } void RemoteKeyboardPlugin::connected() { } QString RemoteKeyboardPlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/remotekeyboard"); } #include "remotekeyboardplugin.moc" diff --git a/plugins/remotesystemvolume/remotesystemvolumeplugin.cpp b/plugins/remotesystemvolume/remotesystemvolumeplugin.cpp index 6eafa8b6..75b6d9aa 100644 --- a/plugins/remotesystemvolume/remotesystemvolumeplugin.cpp +++ b/plugins/remotesystemvolume/remotesystemvolumeplugin.cpp @@ -1,105 +1,105 @@ /** * Copyright 2018 Nicolas Fella * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "remotesystemvolumeplugin.h" #include #include #include #include #include #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_remotesystemvolume.json", registerPlugin< RemoteSystemVolumePlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(RemoteSystemVolumePlugin, "kdeconnect_remotesystemvolume.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_PING, "kdeconnect.plugin.remotesystemvolume") RemoteSystemVolumePlugin::RemoteSystemVolumePlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { } RemoteSystemVolumePlugin::~RemoteSystemVolumePlugin() { } bool RemoteSystemVolumePlugin::receivePacket(const NetworkPacket& np) { if (np.has(QStringLiteral("sinkList"))) { QJsonDocument document(np.get(QStringLiteral("sinkList"))); m_sinks = document.toJson(); Q_EMIT sinksChanged(); } else { QString name = np.get(QStringLiteral("name")); if (np.has(QStringLiteral("volume"))) { Q_EMIT volumeChanged(name, np.get(QStringLiteral("volume"))); } if (np.has(QStringLiteral("muted"))) { Q_EMIT mutedChanged(name, np.get(QStringLiteral("muted"))); } } return true; } void RemoteSystemVolumePlugin::sendVolume(const QString& name, int volume) { NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME_REQUEST); np.set(QStringLiteral("name"), name); np.set(QStringLiteral("volume"), volume); sendPacket(np); } void RemoteSystemVolumePlugin::sendMuted(const QString& name, bool muted) { NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME_REQUEST); np.set(QStringLiteral("name"), name); np.set(QStringLiteral("muted"), muted); sendPacket(np); } void RemoteSystemVolumePlugin::connected() { NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME_REQUEST); np.set(QStringLiteral("requestSinks"), true); sendPacket(np); } QByteArray RemoteSystemVolumePlugin::sinks() { return m_sinks; } QString RemoteSystemVolumePlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/remotesystemvolume"); } #include "remotesystemvolumeplugin.moc" diff --git a/plugins/runcommand/runcommandplugin.cpp b/plugins/runcommand/runcommandplugin.cpp index e962fd56..50b898cf 100644 --- a/plugins/runcommand/runcommandplugin.cpp +++ b/plugins/runcommand/runcommandplugin.cpp @@ -1,111 +1,111 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "runcommandplugin.h" #include #include #include #include #include #include #include #include #include #include #include #define PACKET_TYPE_RUNCOMMAND QStringLiteral("kdeconnect.runcommand") #ifdef Q_OS_WIN #define COMMAND "cmd" #define ARGS "/c" #else #define COMMAND "/bin/sh" #define ARGS "-c" #endif -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_runcommand.json", registerPlugin< RunCommandPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(RunCommandPlugin, "kdeconnect_runcommand.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_RUNCOMMAND, "kdeconnect.plugin.runcommand") RunCommandPlugin::RunCommandPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { connect(config(), &KdeConnectPluginConfig::configChanged, this, &RunCommandPlugin::configChanged); } RunCommandPlugin::~RunCommandPlugin() { } bool RunCommandPlugin::receivePacket(const NetworkPacket& np) { if (np.get(QStringLiteral("requestCommandList"), false)) { sendConfig(); return true; } if (np.has(QStringLiteral("key"))) { QJsonDocument commandsDocument = QJsonDocument::fromJson(config()->get(QStringLiteral("commands"), "{}")); QJsonObject commands = commandsDocument.object(); QString key = np.get(QStringLiteral("key")); QJsonValue value = commands[key]; if (value == QJsonValue::Undefined) { qCWarning(KDECONNECT_PLUGIN_RUNCOMMAND) << key << "is not a configured command"; } const QJsonObject commandJson = value.toObject(); qCInfo(KDECONNECT_PLUGIN_RUNCOMMAND) << "Running:" << COMMAND << ARGS << commandJson[QStringLiteral("command")].toString(); QProcess::startDetached(QStringLiteral(COMMAND), QStringList()<< QStringLiteral(ARGS) << commandJson[QStringLiteral("command")].toString()); return true; } else if (np.has(QStringLiteral("setup"))) { QProcess::startDetached(QStringLiteral("kcmshell5"), {QStringLiteral("kdeconnect"), QStringLiteral("--args"), QString(device()->id() + QStringLiteral(":kdeconnect_runcommand")) }); } return false; } void RunCommandPlugin::connected() { sendConfig(); } void RunCommandPlugin::sendConfig() { QString commands = config()->get(QStringLiteral("commands"),QStringLiteral("{}")); NetworkPacket np(PACKET_TYPE_RUNCOMMAND, {{QStringLiteral("commandList"), commands}}); #if KCMUTILS_VERSION >= QT_VERSION_CHECK(5, 45, 0) np.set(QStringLiteral("canAddCommand"), true); #endif sendPacket(np); } void RunCommandPlugin::configChanged() { sendConfig(); } #include "runcommandplugin.moc" diff --git a/plugins/screensaver-inhibit/screensaverinhibitplugin.cpp b/plugins/screensaver-inhibit/screensaverinhibitplugin.cpp index 0f9b9615..ed154797 100644 --- a/plugins/screensaver-inhibit/screensaverinhibitplugin.cpp +++ b/plugins/screensaver-inhibit/screensaverinhibitplugin.cpp @@ -1,82 +1,82 @@ /** * Copyright 2014 Pramod Dematagoda * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "screensaverinhibitplugin.h" #include #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_screensaver_inhibit.json", registerPlugin< ScreensaverInhibitPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(ScreensaverInhibitPlugin, "kdeconnect_screensaver_inhibit.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_SCREENSAVERINHIBIT, "kdeconnect.plugin.screensaverinhibit") #define INHIBIT_SERVICE QStringLiteral("org.freedesktop.ScreenSaver") #define INHIBIT_INTERFACE INHIBIT_SERVICE #define INHIBIT_PATH QStringLiteral("/ScreenSaver") #define INHIBIT_METHOD QStringLiteral("Inhibit") #define UNINHIBIT_METHOD QStringLiteral("UnInhibit") #define SIMULATE_ACTIVITY_METHOD QStringLiteral("SimulateUserActivity") ScreensaverInhibitPlugin::ScreensaverInhibitPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { QDBusInterface inhibitInterface(INHIBIT_SERVICE, INHIBIT_PATH, INHIBIT_INTERFACE); QDBusMessage reply = inhibitInterface.call(INHIBIT_METHOD, QStringLiteral("org.kde.kdeconnect.daemon"), i18n("Phone is connected")); if (!reply.errorMessage().isEmpty()) { qCDebug(KDECONNECT_PLUGIN_SCREENSAVERINHIBIT) << "Unable to inhibit the screensaver: " << reply.errorMessage(); inhibitCookie = 0; } else { // Store the cookie we receive, this will be sent back when sending the uninhibit call. inhibitCookie = reply.arguments().at(0).toUInt(); } } ScreensaverInhibitPlugin::~ScreensaverInhibitPlugin() { if (inhibitCookie == 0) return; QDBusInterface inhibitInterface(INHIBIT_SERVICE, INHIBIT_PATH, INHIBIT_INTERFACE); inhibitInterface.call(UNINHIBIT_METHOD, this->inhibitCookie); /* * Simulate user activity because what ever manages the screensaver does not seem to start the timer * automatically when all inhibitions are lifted and the user does nothing which results in an * unlocked desktop which would be dangerous. Ideally we should not be doing this and the screen should * be locked anyway. */ inhibitInterface.call(SIMULATE_ACTIVITY_METHOD); } void ScreensaverInhibitPlugin::connected() { } bool ScreensaverInhibitPlugin::receivePacket(const NetworkPacket& np) { Q_UNUSED(np); return false; } #include "screensaverinhibitplugin.moc" diff --git a/plugins/sendnotifications/sendnotificationsplugin.cpp b/plugins/sendnotifications/sendnotificationsplugin.cpp index fd3d8cbc..602f8a05 100644 --- a/plugins/sendnotifications/sendnotificationsplugin.cpp +++ b/plugins/sendnotifications/sendnotificationsplugin.cpp @@ -1,54 +1,54 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "sendnotificationsplugin.h" #include "notificationslistener.h" #include "sendnotification_debug.h" #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_sendnotifications.json", registerPlugin< SendNotificationsPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(SendNotificationsPlugin, "kdeconnect_sendnotifications.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_SENDNOTIFICATION, "kdeconnect.plugin.sendnotification") SendNotificationsPlugin::SendNotificationsPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { notificationsListener = new NotificationsListener(this); } SendNotificationsPlugin::~SendNotificationsPlugin() { delete notificationsListener; } bool SendNotificationsPlugin::receivePacket(const NetworkPacket& np) { Q_UNUSED(np); return true; } void SendNotificationsPlugin::connected() { } #include "sendnotificationsplugin.moc" diff --git a/plugins/sftp/sftpplugin.cpp b/plugins/sftp/sftpplugin.cpp index b0e1d03d..e6f7cf58 100644 --- a/plugins/sftp/sftpplugin.cpp +++ b/plugins/sftp/sftpplugin.cpp @@ -1,201 +1,201 @@ /** * Copyright 2014 Samoilenko Yuri * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "sftpplugin.h" #include #include #include #include #include #include #include #include #include #include "mounter.h" #include "sftp_debug.h" -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_sftp.json", registerPlugin< SftpPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(SftpPlugin, "kdeconnect_sftp.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_SFTP, "kdeconnect.plugin.sftp") static const QSet fields_c = QSet() << QStringLiteral("ip") << QStringLiteral("port") << QStringLiteral("user") << QStringLiteral("port") << QStringLiteral("path"); struct SftpPlugin::Pimpl { Pimpl() : m_mounter(nullptr) {} //Add KIO entry to Dolphin's Places KFilePlacesModel m_placesModel; Mounter* m_mounter; }; SftpPlugin::SftpPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , d(new Pimpl()) { deviceId = device()->id(); addToDolphin(); qCDebug(KDECONNECT_PLUGIN_SFTP) << "Created device:" << device()->name(); } SftpPlugin::~SftpPlugin() { removeFromDolphin(); unmount(); } void SftpPlugin::addToDolphin() { removeFromDolphin(); QUrl kioUrl(QStringLiteral("kdeconnect://") + deviceId + QStringLiteral("/")); d->m_placesModel.addPlace(device()->name(), kioUrl, QStringLiteral("kdeconnect")); qCDebug(KDECONNECT_PLUGIN_SFTP) << "add to dolphin"; } void SftpPlugin::removeFromDolphin() { QUrl kioUrl(QStringLiteral("kdeconnect://") + deviceId + QStringLiteral("/")); QModelIndex index = d->m_placesModel.closestItem(kioUrl); while (index.row() != -1) { d->m_placesModel.removePlace(index); index = d->m_placesModel.closestItem(kioUrl); } } void SftpPlugin::mount() { qCDebug(KDECONNECT_PLUGIN_SFTP) << "Mount device:" << device()->name(); if (d->m_mounter) { return; } d->m_mounter = new Mounter(this); connect(d->m_mounter, &Mounter::mounted, this, &SftpPlugin::onMounted); connect(d->m_mounter, &Mounter::unmounted, this, &SftpPlugin::onUnmounted); connect(d->m_mounter, &Mounter::failed, this, &SftpPlugin::onFailed); } void SftpPlugin::unmount() { if (d->m_mounter) { d->m_mounter->deleteLater(); d->m_mounter = nullptr; } } bool SftpPlugin::mountAndWait() { mount(); return d->m_mounter->wait(); } bool SftpPlugin::isMounted() const { return d->m_mounter && d->m_mounter->isMounted(); } QString SftpPlugin::getMountError() { if (!mountError.isEmpty()) { return mountError; } return QString(); } bool SftpPlugin::startBrowsing() { if (mountAndWait()) { //return new KRun(QUrl::fromLocalFile(mountPoint()), 0); return new KRun(QUrl(QStringLiteral("kdeconnect://") + deviceId), nullptr); } return false; } bool SftpPlugin::receivePacket(const NetworkPacket& np) { if (!(fields_c - np.body().keys().toSet()).isEmpty() && !np.has(QStringLiteral("errorMessage"))) { // packet is invalid return false; } Q_EMIT packetReceived(np); remoteDirectories.clear(); if (np.has(QStringLiteral("multiPaths"))) { QStringList paths = np.get(QStringLiteral("multiPaths"),QStringList()); QStringList names = np.get(QStringLiteral("pathNames"),QStringList()); int size = qMin(names.size(), paths.size()); for (int i = 0; i < size; i++) { remoteDirectories.insert(mountPoint() + paths.at(i), names.at(i)); } } else { remoteDirectories.insert(mountPoint(), i18n("All files")); remoteDirectories.insert(mountPoint() + QStringLiteral("/DCIM/Camera"), i18n("Camera pictures")); } return true; } QString SftpPlugin::mountPoint() { QString runtimePath = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); if (runtimePath.isEmpty()) { runtimePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation); } return QDir(runtimePath).absoluteFilePath(deviceId); } void SftpPlugin::onMounted() { qCDebug(KDECONNECT_PLUGIN_SFTP) << device()->name() << QStringLiteral("Remote filesystem mounted at %1").arg(mountPoint()); Q_EMIT mounted(); } void SftpPlugin::onUnmounted() { qCDebug(KDECONNECT_PLUGIN_SFTP) << device()->name() << "Remote filesystem unmounted"; unmount(); Q_EMIT unmounted(); } void SftpPlugin::onFailed(const QString& message) { mountError = message; KNotification::event(KNotification::Error, device()->name(), message); unmount(); Q_EMIT unmounted(); } QVariantMap SftpPlugin::getDirectories() { return remoteDirectories; } #include "sftpplugin.moc" diff --git a/plugins/share/shareplugin.cpp b/plugins/share/shareplugin.cpp index 321b67a2..31bc7b1e 100644 --- a/plugins/share/shareplugin.cpp +++ b/plugins/share/shareplugin.cpp @@ -1,238 +1,238 @@ /** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "shareplugin.h" #include "share_debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "core/filetransferjob.h" -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_share.json", registerPlugin< SharePlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(SharePlugin, "kdeconnect_share.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_SHARE, "kdeconnect.plugin.share") SharePlugin::SharePlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , m_compositeJob() { } QUrl SharePlugin::destinationDir() const { const QString defaultDownloadPath = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); QUrl dir = QUrl::fromLocalFile(config()->get(QStringLiteral("incoming_path"), defaultDownloadPath)); if (dir.path().contains(QLatin1String("%1"))) { dir.setPath(dir.path().arg(device()->name())); } KJob* job = KIO::mkpath(dir); bool ret = job->exec(); if (!ret) { qWarning() << "couldn't create" << dir; } return dir; } QUrl SharePlugin::getFileDestination(const QString filename) const { const QUrl dir = destinationDir().adjusted(QUrl::StripTrailingSlash); QUrl destination(dir); destination.setPath(dir.path() + QStringLiteral("/") + filename, QUrl::DecodedMode); if (destination.isLocalFile() && QFile::exists(destination.toLocalFile())) { destination.setPath(dir.path() + QStringLiteral("/") + KIO::suggestName(dir, filename), QUrl::DecodedMode); } return destination; } static QString cleanFilename(const QString &filename) { int idx = filename.lastIndexOf(QLatin1Char('/')); return idx>=0 ? filename.mid(idx + 1) : filename; } void SharePlugin::setDateModified(const QUrl& destination, const qint64 timestamp) { QFile receivedFile(destination.toLocalFile()); if (!receivedFile.exists() || !receivedFile.open(QIODevice::ReadWrite | QIODevice::Text)) { return; } receivedFile.setFileTime(QDateTime::fromMSecsSinceEpoch(timestamp), QFileDevice::FileTime(QFileDevice::FileModificationTime)); } bool SharePlugin::receivePacket(const NetworkPacket& np) { /* //TODO: Write a test like this if (np.type() == PACKET_TYPE_PING) { qCDebug(KDECONNECT_PLUGIN_SHARE) << "sending file" << (QDesktopServices::storageLocation(QDesktopServices::HomeLocation) + "/.bashrc"); NetworkPacket out(PACKET_TYPE_SHARE_REQUEST); out.set("filename", mDestinationDir + "itworks.txt"); AutoClosingQFile* file = new AutoClosingQFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation) + "/.bashrc"); //Test file to transfer out.setPayload(file, file->size()); device()->sendPacket(out); return true; } */ qCDebug(KDECONNECT_PLUGIN_SHARE) << "File transfer"; if (np.hasPayload() || np.has(QStringLiteral("filename"))) { // qCDebug(KDECONNECT_PLUGIN_SHARE) << "receiving file" << filename << "in" << dir << "into" << destination; const QString filename = cleanFilename(np.get(QStringLiteral("filename"), QString::number(QDateTime::currentMSecsSinceEpoch()))); QUrl destination = getFileDestination(filename); if (np.hasPayload()) { qint64 dateModified = np.get(QStringLiteral("lastModified"), QDateTime::currentMSecsSinceEpoch()); if (!m_compositeJob) { m_compositeJob = new CompositeFileTransferJob(device()->id()); KIO::getJobTracker()->registerJob(m_compositeJob); } FileTransferJob* job = np.createPayloadTransferJob(destination); job->setOriginName(device()->name() + QStringLiteral(": ") + filename); connect(job, &KJob::result, this, [this, dateModified] (KJob* job) -> void { finished(job, dateModified); }); m_compositeJob->addSubjob(job); if (!m_compositeJob->isRunning()) { m_compositeJob->start(); } } else { QFile file(destination.toLocalFile()); file.open(QIODevice::WriteOnly); file.close(); } } else if (np.has(QStringLiteral("text"))) { QString text = np.get(QStringLiteral("text")); KService::Ptr service = KMimeTypeTrader::self()->preferredService(QStringLiteral("text/plain")); const QString defaultApp = service ? service->desktopEntryName() : QString(); if (defaultApp == QLatin1String("org.kde.kate") || defaultApp == QLatin1String("org.kde.kwrite")) { QProcess* proc = new QProcess(); connect(proc, SIGNAL(finished(int)), proc, SLOT(deleteLater())); proc->start(defaultApp.section(QStringLiteral("."), 2,2), QStringList(QStringLiteral("--stdin"))); proc->write(text.toUtf8()); proc->closeWriteChannel(); } else { QTemporaryFile tmpFile; tmpFile.setFileTemplate(QStringLiteral("kdeconnect-XXXXXX.txt")); tmpFile.setAutoRemove(false); tmpFile.open(); tmpFile.write(text.toUtf8()); tmpFile.close(); const QString fileName = tmpFile.fileName(); Q_EMIT shareReceived(fileName); QDesktopServices::openUrl(QUrl::fromLocalFile(fileName)); } } else if (np.has(QStringLiteral("url"))) { QUrl url = QUrl::fromEncoded(np.get(QStringLiteral("url"))); QDesktopServices::openUrl(url); Q_EMIT shareReceived(url.toString()); } else { qCDebug(KDECONNECT_PLUGIN_SHARE) << "Error: Nothing attached!"; } return true; } void SharePlugin::finished(KJob* job, const qint64 dateModified) { FileTransferJob* ftjob = qobject_cast(job); if (ftjob && !job->error()) { Q_EMIT shareReceived(ftjob->destination().toString()); setDateModified(ftjob->destination(), dateModified); qCDebug(KDECONNECT_PLUGIN_SHARE) << "File transfer finished." << ftjob->destination(); } else { qCDebug(KDECONNECT_PLUGIN_SHARE) << "File transfer failed." << (ftjob ? ftjob->destination() : QUrl()); } } void SharePlugin::openDestinationFolder() { QDesktopServices::openUrl(destinationDir()); } void SharePlugin::shareUrl(const QUrl& url) { NetworkPacket packet(PACKET_TYPE_SHARE_REQUEST); if(url.isLocalFile()) { QSharedPointer ioFile(new QFile(url.toLocalFile())); packet.setPayload(ioFile, ioFile->size()); packet.set(QStringLiteral("filename"), QUrl(url).fileName()); } else { packet.set(QStringLiteral("url"), url.toString()); } sendPacket(packet); } void SharePlugin::shareUrls(const QStringList& urls) { for(const QString& url : urls) { shareUrl(QUrl(url)); } } void SharePlugin::shareText(const QString& text) { NetworkPacket packet(PACKET_TYPE_SHARE_REQUEST); packet.set(QStringLiteral("text"), text); sendPacket(packet); } void SharePlugin::openFile(const QUrl& url) { NetworkPacket packet(PACKET_TYPE_SHARE_REQUEST); if(url.isLocalFile()) { QSharedPointer ioFile(new QFile(url.toLocalFile())); packet.setPayload(ioFile, ioFile->size()); packet.set(QStringLiteral("filename"), QUrl(url).fileName()); packet.set(QStringLiteral("open"), true); } sendPacket(packet); } QString SharePlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/share"); } #include "shareplugin.moc" diff --git a/plugins/sms/smsplugin.cpp b/plugins/sms/smsplugin.cpp index 03d7dec3..64d528d9 100644 --- a/plugins/sms/smsplugin.cpp +++ b/plugins/sms/smsplugin.cpp @@ -1,126 +1,126 @@ /** * Copyright 2013 Albert Vaca * Copyright 2018 Simon Redman * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "smsplugin.h" #include #include #include #include #include #include #include #include "sendreplydialog.h" -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_sms.json", registerPlugin< SmsPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(SmsPlugin, "kdeconnect_sms.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_SMS, "kdeconnect.plugin.sms") SmsPlugin::SmsPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , m_telepathyInterface(QStringLiteral("org.freedesktop.Telepathy.ConnectionManager.kdeconnect"), QStringLiteral("/kdeconnect")) , m_conversationInterface(new ConversationsDbusInterface(this)) { } SmsPlugin::~SmsPlugin() { // m_conversationInterface is self-deleting, see ~ConversationsDbusInterface for more information } bool SmsPlugin::receivePacket(const NetworkPacket& np) { if (np.type() == PACKET_TYPE_SMS_MESSAGES) { return handleBatchMessages(np); } return true; } void SmsPlugin::sendSms(const QString& phoneNumber, const QString& messageBody) { NetworkPacket np(PACKET_TYPE_SMS_REQUEST, { {QStringLiteral("sendSms"), true}, {QStringLiteral("phoneNumber"), phoneNumber}, {QStringLiteral("messageBody"), messageBody} }); qCDebug(KDECONNECT_PLUGIN_SMS) << "Dispatching SMS send request to remote"; sendPacket(np); } void SmsPlugin::requestAllConversations() { NetworkPacket np(PACKET_TYPE_SMS_REQUEST_CONVERSATIONS); sendPacket(np); } void SmsPlugin::requestConversation (const qint64& conversationID) const { NetworkPacket np(PACKET_TYPE_SMS_REQUEST_CONVERSATION); np.set(QStringLiteral("threadID"), conversationID); sendPacket(np); } void SmsPlugin::forwardToTelepathy(const ConversationMessage& message) { // If we don't have a valid Telepathy interface, bail out if (!(m_telepathyInterface.isValid())) return; qCDebug(KDECONNECT_PLUGIN_SMS) << "Passing a text message to the telepathy interface"; connect(&m_telepathyInterface, SIGNAL(messageReceived(QString,QString)), SLOT(sendSms(QString,QString)), Qt::UniqueConnection); const QString messageBody = message.body(); const QString contactName; // TODO: When telepathy support is improved, look up the contact with KPeople const QString phoneNumber = message.address(); m_telepathyInterface.call(QDBus::NoBlock, QStringLiteral("sendMessage"), phoneNumber, contactName, messageBody); } bool SmsPlugin::handleBatchMessages(const NetworkPacket& np) { const auto messages = np.get(QStringLiteral("messages")); QList messagesList; messagesList.reserve(messages.count()); for (const QVariant& body : messages) { ConversationMessage message(body.toMap()); if (message.containsTextBody()) { forwardToTelepathy(message); messagesList.append(message); } } m_conversationInterface->addMessages(messagesList); return true; } QString SmsPlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/sms"); } #include "smsplugin.moc" diff --git a/plugins/systemvolume/systemvolumeplugin-pulse.cpp b/plugins/systemvolume/systemvolumeplugin-pulse.cpp index a4e77abf..da4fb0a6 100644 --- a/plugins/systemvolume/systemvolumeplugin-pulse.cpp +++ b/plugins/systemvolume/systemvolumeplugin-pulse.cpp @@ -1,130 +1,130 @@ /** * Copyright 2017 Nicolas Fella * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "systemvolumeplugin-pulse.h" #include #include #include #include #include #include #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_systemvolume.json", registerPlugin< SystemvolumePlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(SystemvolumePlugin, "kdeconnect_systemvolume.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_SYSTEMVOLUME, "kdeconnect.plugin.systemvolume") SystemvolumePlugin::SystemvolumePlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , sinksMap() {} bool SystemvolumePlugin::receivePacket(const NetworkPacket& np) { if (!PulseAudioQt::Context::instance()->isValid()) return false; if (np.has(QStringLiteral("requestSinks"))) { sendSinkList(); } else { QString name = np.get(QStringLiteral("name")); if (sinksMap.contains(name)) { if (np.has(QStringLiteral("volume"))) { sinksMap[name]->setVolume(np.get(QStringLiteral("volume"))); } if (np.has(QStringLiteral("muted"))) { sinksMap[name]->setMuted(np.get(QStringLiteral("muted"))); } } } return true; } void SystemvolumePlugin::sendSinkList() { QJsonDocument document; QJsonArray array; sinksMap.clear(); const auto sinks = PulseAudioQt::Context::instance()->sinks(); for (PulseAudioQt::Sink* sink : sinks) { sinksMap.insert(sink->name(), sink); connect(sink, &PulseAudioQt::Sink::volumeChanged, this, [this, sink] { NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME); np.set(QStringLiteral("volume"), sink->volume()); np.set(QStringLiteral("name"), sink->name()); sendPacket(np); }); connect(sink, &PulseAudioQt::Sink::mutedChanged, this, [this, sink] { NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME); np.set(QStringLiteral("muted"), sink->isMuted()); np.set(QStringLiteral("name"), sink->name()); sendPacket(np); }); QJsonObject sinkObject { {QStringLiteral("name"), sink->name()}, {QStringLiteral("muted"), sink->isMuted()}, {QStringLiteral("description"), sink->description()}, {QStringLiteral("volume"), sink->volume()}, {QStringLiteral("maxVolume"), PulseAudioQt::normalVolume()} }; array.append(sinkObject); } document.setArray(array); NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME); np.set(QStringLiteral("sinkList"), document); sendPacket(np); } void SystemvolumePlugin::connected() { connect(PulseAudioQt::Context::instance(), &PulseAudioQt::Context::sinkAdded, this, [this] { sendSinkList(); }); connect(PulseAudioQt::Context::instance(), &PulseAudioQt::Context::sinkRemoved, this, [this] { sendSinkList(); }); const auto sinks = PulseAudioQt::Context::instance()->sinks(); for (PulseAudioQt::Sink* sink : sinks) { sinksMap.insert(sink->name(), sink); } } #include "systemvolumeplugin-pulse.moc" diff --git a/plugins/systemvolume/systemvolumeplugin-win.cpp b/plugins/systemvolume/systemvolumeplugin-win.cpp index 8a8916e9..a1c7c89e 100644 --- a/plugins/systemvolume/systemvolumeplugin-win.cpp +++ b/plugins/systemvolume/systemvolumeplugin-win.cpp @@ -1,348 +1,348 @@ /** * Copyright 2018 Jun Bo Bi * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "systemvolumeplugin-win.h" #include #include #include #include #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON(KdeConnectPluginFactory, "kdeconnect_systemvolume.json", registerPlugin();) +K_PLUGIN_CLASS_WITH_JSON(SystemvolumePlugin, "kdeconnect_systemvolume.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_SYSTEMVOLUME, "kdeconnect.plugin.systemvolume") // Private classes of SystemvolumePlugin class SystemvolumePlugin::CMMNotificationClient : public IMMNotificationClient { public: CMMNotificationClient(SystemvolumePlugin &x) : enclosing(x), _cRef(1){}; ~CMMNotificationClient(){}; // IUnknown methods -- AddRef, Release, and QueryInterface ULONG STDMETHODCALLTYPE AddRef() override { return InterlockedIncrement(&_cRef); } ULONG STDMETHODCALLTYPE Release() override { ULONG ulRef = InterlockedDecrement(&_cRef); if (ulRef == 0) { delete this; } return ulRef; } HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface) override { if (IID_IUnknown == riid) { AddRef(); *ppvInterface = (IUnknown *)this; } else if (__uuidof(IMMNotificationClient) == riid) { AddRef(); *ppvInterface = (IMMNotificationClient *)this; } else { *ppvInterface = NULL; return E_NOINTERFACE; } return S_OK; } // Callback methods for device-event notifications. HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) override { if (flow == eRender) { enclosing.sendSinkList(); } return S_OK; } HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) override { enclosing.sendSinkList(); return S_OK; } HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) override { enclosing.sendSinkList(); return S_OK; } HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) override { enclosing.sendSinkList(); return S_OK; } HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) override { enclosing.sendSinkList(); return S_OK; } private: LONG _cRef; SystemvolumePlugin &enclosing; }; class SystemvolumePlugin::CAudioEndpointVolumeCallback : public IAudioEndpointVolumeCallback { LONG _cRef; public: CAudioEndpointVolumeCallback(SystemvolumePlugin &x, QString sinkName) : enclosing(x), name(sinkName), _cRef(1) {} ~CAudioEndpointVolumeCallback(){}; // IUnknown methods -- AddRef, Release, and QueryInterface ULONG STDMETHODCALLTYPE AddRef() override { return InterlockedIncrement(&_cRef); } ULONG STDMETHODCALLTYPE Release() override { ULONG ulRef = InterlockedDecrement(&_cRef); if (ulRef == 0) { delete this; } return ulRef; } HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface) override { if (IID_IUnknown == riid) { AddRef(); *ppvInterface = (IUnknown *)this; } else if (__uuidof(IMMNotificationClient) == riid) { AddRef(); *ppvInterface = (IMMNotificationClient *)this; } else { *ppvInterface = NULL; return E_NOINTERFACE; } return S_OK; } // Callback method for endpoint-volume-change notifications. HRESULT STDMETHODCALLTYPE OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) override { NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME); np.set(QStringLiteral("volume"), (int)(pNotify->fMasterVolume * 100)); np.set(QStringLiteral("muted"), pNotify->bMuted); np.set(QStringLiteral("name"), name); enclosing.sendPacket(np); return S_OK; } private: SystemvolumePlugin &enclosing; QString name; }; SystemvolumePlugin::SystemvolumePlugin(QObject *parent, const QVariantList &args) : KdeConnectPlugin(parent, args), sinkList() { CoInitialize(nullptr); deviceEnumerator = nullptr; HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&(deviceEnumerator)); valid = (hr == S_OK); if (!valid) { qWarning("Initialization failed: Failed to create MMDeviceEnumerator"); qWarning("Error Code: %lx", hr); } } SystemvolumePlugin::~SystemvolumePlugin() { if (valid) { deviceEnumerator->UnregisterEndpointNotificationCallback(deviceCallback); deviceEnumerator->Release(); deviceEnumerator = nullptr; } } bool SystemvolumePlugin::sendSinkList() { if (!valid) return false; QJsonDocument document; QJsonArray array; HRESULT hr; if (!sinkList.empty()) { for (auto const &sink : sinkList) { sink.first->UnregisterControlChangeNotify(sink.second); sink.first->Release(); sink.second->Release(); } sinkList.clear(); } IMMDeviceCollection *devices = nullptr; hr = deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &devices); if (hr != S_OK) { qWarning("Failed to Enumumerate AudioEndpoints"); qWarning("Error Code: %lx", hr); return false; } unsigned int deviceCount; devices->GetCount(&deviceCount); for (unsigned int i = 0; i < deviceCount; i++) { IMMDevice *device = nullptr; IPropertyStore *deviceProperties = nullptr; PROPVARIANT deviceProperty; QString name; QString desc; float volume; BOOL muted; IAudioEndpointVolume *endpoint = nullptr; CAudioEndpointVolumeCallback *callback; // Get Properties devices->Item(i, &device); device->OpenPropertyStore(STGM_READ, &deviceProperties); deviceProperties->GetValue(PKEY_Device_FriendlyName, &deviceProperty); name = QString::fromWCharArray(deviceProperty.pwszVal); //PropVariantClear(&deviceProperty); #ifndef __MINGW32__ deviceProperties->GetValue(PKEY_Device_DeviceDesc, &deviceProperty); desc = QString::fromWCharArray(deviceProperty.pwszVal); //PropVariantClear(&deviceProperty); #endif QJsonObject sinkObject; sinkObject.insert(QStringLiteral("name"), name); sinkObject.insert(QStringLiteral("description"), desc); hr = device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void **)&endpoint); if (hr != S_OK) { qWarning() << "Failed to create IAudioEndpointVolume for device:" << name; qWarning("Error Code: %lx", hr); device->Release(); continue; } endpoint->GetMasterVolumeLevelScalar(&volume); endpoint->GetMute(&muted); sinkObject.insert(QStringLiteral("muted"), (bool)muted); sinkObject.insert(QStringLiteral("volume"), (qint64)(volume * 100)); sinkObject.insert(QStringLiteral("maxVolume"), (qint64)100); // Register Callback callback = new CAudioEndpointVolumeCallback(*this, name); sinkList[name] = qMakePair(endpoint, callback); endpoint->RegisterControlChangeNotify(callback); device->Release(); array.append(sinkObject); } devices->Release(); document.setArray(array); NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME); np.set(QStringLiteral("sinkList"), document); sendPacket(np); return true; } void SystemvolumePlugin::connected() { if (!valid) return; deviceCallback = new CMMNotificationClient(*this); deviceEnumerator->RegisterEndpointNotificationCallback(deviceCallback); sendSinkList(); } bool SystemvolumePlugin::receivePacket(const NetworkPacket &np) { if (!valid) return false; if (np.has(QStringLiteral("requestSinks"))) { return sendSinkList(); } else { QString name = np.get(QStringLiteral("name")); if (sinkList.contains(name)) { if (np.has(QStringLiteral("volume"))) { sinkList[name].first->SetMasterVolumeLevelScalar((float)np.get(QStringLiteral("volume")) / 100, NULL); } if (np.has(QStringLiteral("muted"))) { sinkList[name].first->SetMute(np.get(QStringLiteral("muted")), NULL); } } } return true; } #include "systemvolumeplugin-win.moc" diff --git a/plugins/telephony/telephonyplugin.cpp b/plugins/telephony/telephonyplugin.cpp index 7a450186..5c49c282 100644 --- a/plugins/telephony/telephonyplugin.cpp +++ b/plugins/telephony/telephonyplugin.cpp @@ -1,134 +1,134 @@ /** * Copyright 2013 Albert Vaca * Copyright 2018 Simon Redman * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "telephonyplugin.h" #include #include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_telephony.json", registerPlugin< TelephonyPlugin >(); ) +K_PLUGIN_CLASS_WITH_JSON(TelephonyPlugin, "kdeconnect_telephony.json") Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_TELEPHONY, "kdeconnect.plugin.telephony") TelephonyPlugin::TelephonyPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { } TelephonyPlugin::~TelephonyPlugin() { } KNotification* TelephonyPlugin::createNotification(const NetworkPacket& np) { const QString event = np.get(QStringLiteral("event")); const QString phoneNumber = np.get(QStringLiteral("phoneNumber"), i18n("unknown number")); const QString contactName = np.get(QStringLiteral("contactName"), phoneNumber); const QByteArray phoneThumbnail = QByteArray::fromBase64(np.get(QStringLiteral("phoneThumbnail"), "")); QString content, type, icon; KNotification::NotificationFlags flags = KNotification::CloseOnTimeout; const QString title = device()->name(); if (event == QLatin1String("ringing")) { type = QStringLiteral("callReceived"); icon = QStringLiteral("call-start"); content = i18n("Incoming call from %1", contactName); } else if (event == QLatin1String("missedCall")) { type = QStringLiteral("missedCall"); icon = QStringLiteral("call-start"); content = i18n("Missed call from %1", contactName); flags |= KNotification::Persistent; //Note that in Unity this generates a message box! } else if (event == QLatin1String("talking")) { return nullptr; } else { #ifndef NDEBUG return nullptr; #else type = QStringLiteral("callReceived"); icon = QStringLiteral("phone"); content = i18n("Unknown telephony event: %1", event); #endif } Q_EMIT callReceived(type, phoneNumber, contactName); qCDebug(KDECONNECT_PLUGIN_TELEPHONY) << "Creating notification with type:" << type; KNotification* notification = new KNotification(type, flags, this); if (!phoneThumbnail.isEmpty()) { QPixmap photo; photo.loadFromData(phoneThumbnail, "JPEG"); notification->setPixmap(photo); } else { notification->setIconName(icon); } notification->setComponentName(QStringLiteral("kdeconnect")); notification->setTitle(title); notification->setText(content); if (event == QLatin1String("ringing")) { notification->setActions( QStringList(i18n("Mute Call")) ); connect(notification, &KNotification::action1Activated, this, &TelephonyPlugin::sendMutePacket); } return notification; } bool TelephonyPlugin::receivePacket(const NetworkPacket& np) { if (np.get(QStringLiteral("isCancel"))) { //TODO: Clear the old notification return true; } const QString& event = np.get(QStringLiteral("event"), QStringLiteral("unknown")); // Handle old-style packets if (np.type() == PACKET_TYPE_TELEPHONY) { if (event == QLatin1String("sms")) { return false; } KNotification* n = createNotification(np); if (n != nullptr) n->sendEvent(); return true; } return true; } void TelephonyPlugin::sendMutePacket() { NetworkPacket packet(PACKET_TYPE_TELEPHONY_REQUEST_MUTE, {{QStringLiteral("action"), QStringLiteral("mute")}}); sendPacket(packet); } QString TelephonyPlugin::dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/telephony"); } #include "telephonyplugin.moc"