diff --git a/README.md b/README.md index 553d846a..bd4510db 100644 --- a/README.md +++ b/README.md @@ -1,65 +1,65 @@ # KDE Connect - desktop app KDE Connect is a multi-platform app that allows your devices to communicate (eg: your phone and your computer). ## (Some) Features - **Shared clipboard**: copy and paste between your phone and your computer (or any other device). -- **Notification sync**: Read your Android notifications from the desktop. +- **Notification sync**: Read and reply to your Android notifications from the desktop. - **Share files and URLs** instantly from one device to another. - **Multimedia remote control**: Use your phone as a remote for Linux media players. -- **Virtual touchpad**: Use your phone screen as your computer's touchpad. +- **Virtual touchpad**: Use your phone screen as your computer's touchpad and keyboard. -All this without wires, over the already existing WiFi network, and using a secure, encrypted protocol. +All this without wires, over the already existing WiFi network, and using TLS encryption. ## Supported platforms -- Computers running Plasma 5, KDE4, Unity (Ubuntu), Gnome 3, Elementary OS... +- Computers running Linux with Plasma 5, Gnome 3, Elementary OS... - Android, by installing the [KDE Connect Android app](https://play.google.com/store/apps/details?id=org.kde.kdeconnect_tp) (also available on [F-Droid](https://f-droid.org/repository/browse/?fdid=org.kde.kdeconnect_tp)). -There is also source code for an unmaintained iOS port, waiting for somebody to give it some love :) - ## How to install This explains how to install KDE Connect on your computer. You will also need to install it in your phone and pair both devices in the app if you want it to be any useful. ### On Linux Look in your distribution repo for a package called `kdeconnect-kde`, `kdeconnect-plasma`, or just `kdeconnect`. If it's not there and you know how to build software from sources, you just found the repo :) -If you are not using Plasma 5 or KDE4, you will also need to install [indicator-kdeconnect](https://github.com/vikoadi/indicator-kdeconnect) (available as an [Ubuntu PPA](https://code.launchpad.net/~vikoadi/+archive/ubuntu/ppa/)) for integration with other desktops using appindicator. +If you are not using Plasma 5, you might want to install a user interface for your platform. The [indicator-kdeconnect](https://github.com/bajoja/indicator-kdeconnect) project provides an appindicator icon plus integration with Nautilus. ### On Mac or Windows -There is no support for Mac or Windows yet. The last time I checked it was compiling on Windows, so it's only lacking a user interface. Same for Mac. Contributions welcome! +Platforms other than Linux are not officially supported, but it should be possible to run KDE Connect there. You can compile KDE Connect for Windows using [Craft](https://community.kde.org/Craft) and it works except for some plugins. I haven't tried on Mac. Contributions welcome! ### On BSD -It should work, but no promises. +It should work, but no promises :) ## How does it work? KDE Connect consists of an UI-agnostic "core" library which exposes a series of DBus interfaces, and several UI components that consume these DBus interfaces. This way, new UI components can be added to integrate better with specific platforms or desktops, without having to reimplement the protocol or any of the internals. The core KDE Connect library is also divided in 4 big blocks: - **LinkProviders**: Are in charge of discovering other KDE Connect-enabled devices in the network and establishing a Link to them. - **Devices**: Represent a remote device, abstracting the specific Link that is being used to reach it. - **NetworkPackets**: JSON-serializable and self-contained pieces of information to be sent by the plugins between devices. - **Plugins**: Independent pieces of code which implement a specific feature. Plugins will use NetworkPackets to exchange information through the network with other Plugins on a remote Device. -The basic structure of a NetworkPacket (before encryption) is the following: +The basic structure of a NetworkPacket is the following: ``` { "id": 123456789, "type": "com.example.myplugin", "body": { }, "version": 5 } ``` The content of the `"body"` section is defined by each Plugin. Hence, only the emisor and receiver plugins of a given packet type need agree on the contents of the body. NetworkPackets can also have binary data attached that can't be serialized to JSON. In this case, two new fields will be added: `"payloadSize"`: The size of the file, or -1 if it is a stream without known size. `"payloadTransferInfo"`: Another JSON object where the specific Link can add information so the Link in the remote end can establish a connection and receive the payload (eg: IP and port in a local network). It's up to the Link implementation to decide how to use this field. +## Contributing + +To contribute patches, use [KDE Connect's Phabricator](https://phabricator.kde.org/project/profile/159/). There you can also find a task list with stuff to do, and links to other relevant resources. It is a good idea to also subscribe to the [KDE Connect mailing list](https://mail.kde.org/mailman/listinfo/kdeconnect). + ## License [GNU GPL v2](https://www.gnu.org/licenses/gpl-2.0.html) and [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.html) -If you are reading this from Github, you should know that this is just a mirror of the [KDE Project repo](https://projects.kde.org/projects/extragear/network/kdeconnect-kde/repository/). - -[![Build Status](https://build.kde.org/buildStatus/icon?job=kdeconnect-kde master kf5-qt5)](https://build.kde.org/job/kdeconnect-kde%20master%20kf5-qt5/) +If you are reading this from Github, you should know that this is just a mirror of the [KDE Project repo](https://cgit.kde.org/kdeconnect-kde.git). diff --git a/app/org.kde.kdeconnect.app.desktop b/app/org.kde.kdeconnect.app.desktop index 9d46a146..da7af246 100644 --- a/app/org.kde.kdeconnect.app.desktop +++ b/app/org.kde.kdeconnect.app.desktop @@ -1,118 +1,106 @@ [Desktop Entry] Name=KDE Connect Application -Name[ar]=تطبيق كدي المتّصل -Name[ast]=Aplicación KDE Connect Name[ca]=Aplicació KDE Connect Name[ca@valencia]=Aplicació KDE Connect Name[cs]=Aplikace KDE Connect Name[da]=Programmet KDE Connect Name[de]=KDE-Connect-Anwendung -Name[el]=Εφαρμογή KDE Connect Name[en_GB]=KDE Connect Application Name[es]=Aplicación KDE Connect Name[et]=KDE Connecti rakendus Name[eu]=KDE Connect aplikazioa Name[fi]=KDE Connect -sovellus Name[fr]=Application KDE Connect Name[gl]=Aplicativo de KDE Connect -Name[he]=היישום KDE Connect Name[hu]=KDE Connect alkalmazás Name[it]=Applicazione KDE Connect Name[ko]=KDE Connect 프로그램 Name[nl]=KDE Connect-toepassing Name[nn]=KDE Connect-program Name[pl]=Program KDE Connect Name[pt]=Aplicação do KDE Connect Name[pt_BR]=Aplicativo KDE Connect Name[ru]=Приложение KDE Connect Name[sk]=KDE Connect aplikácia Name[sr]=КДЕ‑конекцијин програм Name[sr@ijekavian]=КДЕ‑конекцијин програм Name[sr@ijekavianlatin]=KDE‑konekcijin program Name[sr@latin]=KDE‑konekcijin program Name[sv]=Programmet KDE-anslut Name[tr]=KDE Connect Uygulaması Name[uk]=Програма KDE Connect Name[x-test]=xxKDE Connect Applicationxx Name[zh_CN]=KDE Connect 应用程序 Name[zh_TW]=KDE 連線應用程式 GenericName=Device Synchronization -GenericName[ar]=مزامنة الأجهزة -GenericName[ast]=Sincronización de preseos GenericName[ca]=Sincronització de dispositius GenericName[ca@valencia]=Sincronització de dispositius GenericName[cs]=Synchronizace zařízení GenericName[da]=Enhedssynkronisering GenericName[de]=Geräteabgleich -GenericName[el]=Συγχρονισμός συσκευών GenericName[en_GB]=Device Synchronisation GenericName[es]=Sincronización de dispositivos GenericName[et]=Seadmete sünkroonimine GenericName[eu]=Galuak sinkronizatzea GenericName[fi]=Laitteiden synkronointi GenericName[fr]=Synchronisation de périphériques GenericName[gl]=Sincronización de dispositivos -GenericName[he]=סנכרון התקן GenericName[hu]=Eszközszinkronizáció GenericName[it]=Sincronizzazione dispositivo GenericName[ko]=장치 동기화 GenericName[lt]=Įrenginių sinchronizavimas GenericName[nl]=Synchronisatie van apparaat GenericName[nn]=Einingssynkronisering GenericName[pl]=Synchronizacja urządzenia GenericName[pt]=Sincronização de Dispositivos GenericName[pt_BR]=Sincronização de dispositivo GenericName[ru]=Синхронизация с мобильным устройством GenericName[sk]=Synchronizácia zariadení GenericName[sr]=Синхронизација уређаја GenericName[sr@ijekavian]=Синхронизација уређаја GenericName[sr@ijekavianlatin]=Sinhronizacija uređaja GenericName[sr@latin]=Sinhronizacija uređaja GenericName[sv]=Enhetssynkronisering GenericName[tr]=Aygıt Eşzamanlaması GenericName[uk]=Синхронізація із пристроями GenericName[x-test]=xxDevice Synchronizationxx GenericName[zh_CN]=设备同步 GenericName[zh_TW]=設備同步 Comment=Make all your devices one -Comment[ar]=اجعل أجهزتك كلّها واحدًا -Comment[ast]=Fai tolos tos preseos ún Comment[ca]=Fa que tots els vostres dispositius siguin un Comment[ca@valencia]=Fa que tots els vostres dispositius siguen un Comment[cs]=Sjednoťte svá zařízení Comment[da]=Gør alle dine enheder til en Comment[de]=Gleichen Sie alle Ihre Geräte ab -Comment[el]=Όλες οι συσκευές σας σε μία Comment[en_GB]=Make all your devices one Comment[es]=Convertir todos sus dispositivos en uno Comment[et]=Kõigi seadmete ühendamine Comment[eu]=Bat egin zure gailu guztiak Comment[fi]=Yhdistä kaikki laitteesi toisiinsa Comment[fr]=Unifiez vos périphériques Comment[gl]=Unifique os seus dispositivos. -Comment[he]=הפוך את כך ההתקנים שלך לאחד Comment[hu]=Egyesítse eszközeit Comment[it]=Fai di tutti i tuoi dispositivi un solo dispositivo Comment[ko]=모든 장치를 하나로 동기화 Comment[nl]=Al uw apparaten een maken Comment[nn]=Slå alle einingane dine saman Comment[pl]=Uczyń wszystkie swoje urządzenia jednym Comment[pt]=Unifique todos os seus dispositivos Comment[pt_BR]=Torne todos os seus dispositivos em um Comment[ru]=Объедините все ваши устройства Comment[sk]=Urobiť z vašich zariadení jedno Comment[sr]=Обједините своје уређаје Comment[sr@ijekavian]=Обједините своје уређаје Comment[sr@ijekavianlatin]=Objedinite svoje uređaje Comment[sr@latin]=Objedinite svoje uređaje Comment[sv]=Gör alla enheter till en Comment[tr]=Tüm aygıtlarınızı birleştirin Comment[uk]=Поєднайте усі ваші пристрої Comment[x-test]=xxMake all your devices onexx Comment[zh_CN]=连接您所有设备 Comment[zh_TW]=讓您的設備內容全面同步 Exec=kcapp Icon=kdeconnect Type=Application Terminal=false Categories=Qt;KDE;Network diff --git a/core/backends/lan/downloadjob.cpp b/core/backends/lan/downloadjob.cpp index e861af3d..9b341f31 100644 --- a/core/backends/lan/downloadjob.cpp +++ b/core/backends/lan/downloadjob.cpp @@ -1,79 +1,77 @@ /* * 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 "downloadjob.h" #ifndef Q_OS_WIN #include #include #include #include #endif #include "kdeconnectconfig.h" #include "lanlinkprovider.h" #include "core/core_debug.h" DownloadJob::DownloadJob(const QHostAddress& address, const QVariantMap& transferInfo) : KJob() , m_address(address) , m_port(transferInfo[QStringLiteral("port")].toInt()) , m_socket(new QSslSocket) - , m_buffer(new QBuffer) { LanLinkProvider::configureSslSocket(m_socket.data(), transferInfo.value(QStringLiteral("deviceId")).toString(), true); connect(m_socket.data(), SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketFailed(QAbstractSocket::SocketError))); -// connect(mSocket.data(), &QAbstractSocket::stateChanged, [](QAbstractSocket::SocketState state){ qDebug() << "statechange" << state; }); + connect(m_socket.data(), &QAbstractSocket::connected, this, &DownloadJob::socketConnected); + // emit readChannelFinished when the socket gets disconnected. This seems to be a bug in upstream QSslSocket. + // Needs investigation and upstreaming of the fix. QTBUG-62257 + connect(m_socket.data(), &QAbstractSocket::disconnected, m_socket.data(), &QAbstractSocket::readChannelFinished); } DownloadJob::~DownloadJob() { } void DownloadJob::start() { //TODO: Timeout? // Cannot use read only, might be due to ssl handshake, getting QIODevice::ReadOnly error and no connection m_socket->connectToHostEncrypted(m_address.toString(), m_port, QIODevice::ReadWrite); - - bool b = m_buffer->open(QBuffer::ReadWrite); - Q_ASSERT(b); } void DownloadJob::socketFailed(QAbstractSocket::SocketError error) { - if (error != QAbstractSocket::RemoteHostClosedError) { //remote host closes when finishes - qWarning(KDECONNECT_CORE) << "error..." << m_socket->errorString(); - setError(error + 1); - setErrorText(m_socket->errorString()); - } else { - auto ba = m_socket->readAll(); - m_buffer->write(ba); - m_buffer->seek(0); - } + qWarning() << error << m_socket->errorString(); + setError(error + 1); + setErrorText(m_socket->errorString()); emitResult(); } QSharedPointer DownloadJob::getPayload() { - return m_buffer.staticCast(); + return m_socket.staticCast(); +} + +void DownloadJob::socketConnected() +{ + emitResult(); } diff --git a/core/backends/lan/downloadjob.h b/core/backends/lan/downloadjob.h index a84dc626..6bcf2120 100644 --- a/core/backends/lan/downloadjob.h +++ b/core/backends/lan/downloadjob.h @@ -1,57 +1,56 @@ /* * 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 . */ #ifndef DOWNLOADJOB_H #define DOWNLOADJOB_H #include #include #include #include #include #include #include #include "kdeconnectcore_export.h" class KDECONNECTCORE_EXPORT DownloadJob : public KJob { Q_OBJECT public: DownloadJob(const QHostAddress& address, const QVariantMap& transferInfo); ~DownloadJob() override; void start() override; QSharedPointer getPayload(); private: QHostAddress m_address; qint16 m_port; QSharedPointer m_socket; - QSharedPointer m_buffer; private Q_SLOTS: void socketFailed(QAbstractSocket::SocketError error); - + void socketConnected(); }; #endif // UPLOADJOB_H diff --git a/core/backends/lan/lanlinkprovider.cpp b/core/backends/lan/lanlinkprovider.cpp index 87c2abd9..dd88bf5c 100644 --- a/core/backends/lan/lanlinkprovider.cpp +++ b/core/backends/lan/lanlinkprovider.cpp @@ -1,538 +1,537 @@ /** * 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 "lanlinkprovider.h" #include "core_debug.h" #ifndef Q_OS_WIN #include #include #include #include #endif #include #include #include #include #include #include #include #include #include "daemon.h" #include "landevicelink.h" #include "lanpairinghandler.h" #include "kdeconnectconfig.h" #define MIN_VERSION_WITH_SSL_SUPPORT 6 LanLinkProvider::LanLinkProvider(bool testMode) : m_testMode(testMode) { m_tcpPort = 0; m_combineBroadcastsTimer.setInterval(0); // increase this if waiting a single event-loop iteration is not enough m_combineBroadcastsTimer.setSingleShot(true); connect(&m_combineBroadcastsTimer, &QTimer::timeout, this, &LanLinkProvider::broadcastToNetwork); connect(&m_udpSocket, &QIODevice::readyRead, this, &LanLinkProvider::newUdpConnection); m_server = new Server(this); m_server->setProxy(QNetworkProxy::NoProxy); connect(m_server,&QTcpServer::newConnection,this, &LanLinkProvider::newConnection); m_udpSocket.setProxy(QNetworkProxy::NoProxy); //Detect when a network interface changes status, so we announce ourelves in the new network QNetworkConfigurationManager* networkManager = new QNetworkConfigurationManager(this); connect(networkManager, &QNetworkConfigurationManager::configurationChanged, this, &LanLinkProvider::onNetworkConfigurationChanged); } void LanLinkProvider::onNetworkConfigurationChanged(const QNetworkConfiguration& config) { if (m_lastConfig != config && config.state() == QNetworkConfiguration::Active) { m_lastConfig = config; onNetworkChange(); } } LanLinkProvider::~LanLinkProvider() { } void LanLinkProvider::onStart() { const QHostAddress bindAddress = m_testMode? QHostAddress::LocalHost : QHostAddress::Any; bool success = m_udpSocket.bind(bindAddress, UDP_PORT, QUdpSocket::ShareAddress); Q_ASSERT(success); qCDebug(KDECONNECT_CORE) << "onStart"; m_tcpPort = MIN_TCP_PORT; while (!m_server->listen(bindAddress, m_tcpPort)) { m_tcpPort++; if (m_tcpPort > MAX_TCP_PORT) { //No ports available? qCritical(KDECONNECT_CORE) << "Error opening a port in range" << MIN_TCP_PORT << "-" << MAX_TCP_PORT; m_tcpPort = 0; return; } } onNetworkChange(); } void LanLinkProvider::onStop() { qCDebug(KDECONNECT_CORE) << "onStop"; m_udpSocket.close(); m_server->close(); } void LanLinkProvider::onNetworkChange() { if (m_combineBroadcastsTimer.isActive()) { qCDebug(KDECONNECT_CORE()) << "Preventing duplicate broadcasts"; return; } m_combineBroadcastsTimer.start(); } //I'm in a new network, let's be polite and introduce myself void LanLinkProvider::broadcastToNetwork() { if (!m_server->isListening()) { //Not started return; } Q_ASSERT(m_tcpPort != 0); qCDebug(KDECONNECT_CORE()) << "Broadcasting identity packet"; QHostAddress destAddress = m_testMode? QHostAddress::LocalHost : QHostAddress(QStringLiteral("255.255.255.255")); NetworkPackage np(QLatin1String("")); NetworkPackage::createIdentityPackage(&np); np.set(QStringLiteral("tcpPort"), m_tcpPort); #ifdef Q_OS_WIN //On Windows we need to broadcast from every local IP address to reach all networks QUdpSocket sendSocket; sendSocket.setProxy(QNetworkProxy::NoProxy); for (const QNetworkInterface& iface : QNetworkInterface::allInterfaces()) { if ( (iface.flags() & QNetworkInterface::IsUp) && (iface.flags() & QNetworkInterface::IsRunning) && (iface.flags() & QNetworkInterface::CanBroadcast)) { for (const QNetworkAddressEntry& ifaceAddress : iface.addressEntries()) { QHostAddress sourceAddress = ifaceAddress.ip(); if (sourceAddress.protocol() == QAbstractSocket::IPv4Protocol && sourceAddress != QHostAddress::LocalHost) { qCDebug(KDECONNECT_CORE()) << "Broadcasting as" << sourceAddress; sendSocket.bind(sourceAddress, UDP_PORT); sendSocket.writeDatagram(np.serialize(), destAddress, UDP_PORT); sendSocket.close(); } } } } #else m_udpSocket.writeDatagram(np.serialize(), destAddress, UDP_PORT); #endif } //I'm the existing device, a new device is kindly introducing itself. //I will create a TcpSocket and try to connect. This can result in either connected() or connectError(). void LanLinkProvider::newUdpConnection() //udpBroadcastReceived { while (m_udpSocket.hasPendingDatagrams()) { QByteArray datagram; datagram.resize(m_udpSocket.pendingDatagramSize()); QHostAddress sender; m_udpSocket.readDatagram(datagram.data(), datagram.size(), &sender); if (sender.isLoopback() && !m_testMode) continue; NetworkPackage* receivedPackage = new NetworkPackage(QLatin1String("")); bool success = NetworkPackage::unserialize(datagram, receivedPackage); //qCDebug(KDECONNECT_CORE) << "udp connection from " << receivedPackage->; //qCDebug(KDECONNECT_CORE) << "Datagram " << datagram.data() ; if (!success || receivedPackage->type() != PACKAGE_TYPE_IDENTITY) { delete receivedPackage; continue; } if (receivedPackage->get(QStringLiteral("deviceId")) == KdeConnectConfig::instance()->deviceId()) { //qCDebug(KDECONNECT_CORE) << "Ignoring my own broadcast"; delete receivedPackage; continue; } int tcpPort = receivedPackage->get(QStringLiteral("tcpPort")); //qCDebug(KDECONNECT_CORE) << "Received Udp identity package from" << sender << " asking for a tcp connection on port " << tcpPort; QSslSocket* socket = new QSslSocket(this); socket->setProxy(QNetworkProxy::NoProxy); m_receivedIdentityPackages[socket].np = receivedPackage; m_receivedIdentityPackages[socket].sender = sender; connect(socket, &QAbstractSocket::connected, this, &LanLinkProvider::connected); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectError())); socket->connectToHost(sender, tcpPort); } } void LanLinkProvider::connectError() { QSslSocket* socket = qobject_cast(sender()); if (!socket) return; disconnect(socket, &QAbstractSocket::connected, this, &LanLinkProvider::connected); disconnect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectError())); qCDebug(KDECONNECT_CORE) << "Fallback (1), try reverse connection (send udp packet)" << socket->errorString(); NetworkPackage np(QLatin1String("")); NetworkPackage::createIdentityPackage(&np); np.set(QStringLiteral("tcpPort"), m_tcpPort); m_udpSocket.writeDatagram(np.serialize(), m_receivedIdentityPackages[socket].sender, UDP_PORT); //The socket we created didn't work, and we didn't manage //to create a LanDeviceLink from it, deleting everything. delete m_receivedIdentityPackages.take(socket).np; delete socket; } //We received a UDP package and answered by connecting to them by TCP. This gets called on a succesful connection. void LanLinkProvider::connected() { QSslSocket* socket = qobject_cast(sender()); if (!socket) return; disconnect(socket, &QAbstractSocket::connected, this, &LanLinkProvider::connected); disconnect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectError())); configureSocket(socket); // If socket disconnects due to any reason after connection, link on ssl faliure connect(socket, &QAbstractSocket::disconnected, socket, &QObject::deleteLater); NetworkPackage* receivedPackage = m_receivedIdentityPackages[socket].np; const QString& deviceId = receivedPackage->get(QStringLiteral("deviceId")); //qCDebug(KDECONNECT_CORE) << "Connected" << socket->isWritable(); // If network is on ssl, do not believe when they are connected, believe when handshake is completed NetworkPackage np2(QLatin1String("")); NetworkPackage::createIdentityPackage(&np2); socket->write(np2.serialize()); bool success = socket->waitForBytesWritten(); if (success) { qCDebug(KDECONNECT_CORE) << "TCP connection done (i'm the existing device)"; // if ssl supported if (receivedPackage->get(QStringLiteral("protocolVersion")) >= MIN_VERSION_WITH_SSL_SUPPORT) { bool isDeviceTrusted = KdeConnectConfig::instance()->trustedDevices().contains(deviceId); configureSslSocket(socket, deviceId, isDeviceTrusted); qCDebug(KDECONNECT_CORE) << "Starting server ssl (I'm the client TCP socket)"; connect(socket, &QSslSocket::encrypted, this, &LanLinkProvider::encrypted); if (isDeviceTrusted) { connect(socket, SIGNAL(sslErrors(QList)), this, SLOT(sslErrors(QList))); } socket->startServerEncryption(); return; // Return statement prevents from deleting received package, needed in slot "encrypted" } else { qWarning() << receivedPackage->get(QStringLiteral("deviceName")) << "uses an old protocol version, this won't work"; //addLink(deviceId, socket, receivedPackage, LanDeviceLink::Remotely); } } else { //I think this will never happen, but if it happens the deviceLink //(or the socket that is now inside it) might not be valid. Delete them. qCDebug(KDECONNECT_CORE) << "Fallback (2), try reverse connection (send udp packet)"; m_udpSocket.writeDatagram(np2.serialize(), m_receivedIdentityPackages[socket].sender, UDP_PORT); } delete m_receivedIdentityPackages.take(socket).np; //We don't delete the socket because now it's owned by the LanDeviceLink } void LanLinkProvider::encrypted() { qCDebug(KDECONNECT_CORE) << "Socket succesfully stablished an SSL connection"; QSslSocket* socket = qobject_cast(sender()); if (!socket) return; disconnect(socket, &QSslSocket::encrypted, this, &LanLinkProvider::encrypted); disconnect(socket, SIGNAL(sslErrors(QList)), this, SLOT(sslErrors(QList))); Q_ASSERT(socket->mode() != QSslSocket::UnencryptedMode); LanDeviceLink::ConnectionStarted connectionOrigin = (socket->mode() == QSslSocket::SslClientMode)? LanDeviceLink::Locally : LanDeviceLink::Remotely; NetworkPackage* receivedPackage = m_receivedIdentityPackages[socket].np; const QString& deviceId = receivedPackage->get(QStringLiteral("deviceId")); addLink(deviceId, socket, receivedPackage, connectionOrigin); // Copied from connected slot, now delete received package delete m_receivedIdentityPackages.take(socket).np; } void LanLinkProvider::sslErrors(const QList& errors) { QSslSocket* socket = qobject_cast(sender()); if (!socket) return; disconnect(socket, &QSslSocket::encrypted, this, &LanLinkProvider::encrypted); disconnect(socket, SIGNAL(sslErrors(QList)), this, SLOT(sslErrors(QList))); qCDebug(KDECONNECT_CORE) << "Failing due to " << errors; Device* device = Daemon::instance()->getDevice(socket->peerVerifyName()); if (device) { device->unpair(); } delete m_receivedIdentityPackages.take(socket).np; // Socket disconnects itself on ssl error and will be deleted by deleteLater slot, no need to delete manually } //I'm the new device and this is the answer to my UDP identity package (no data received yet). They are connecting to us through TCP, and they should send an identity. void LanLinkProvider::newConnection() { //qCDebug(KDECONNECT_CORE) << "LanLinkProvider newConnection"; while (m_server->hasPendingConnections()) { QSslSocket* socket = m_server->nextPendingConnection(); configureSocket(socket); //This socket is still managed by us (and child of the QTcpServer), if //it disconnects before we manage to pass it to a LanDeviceLink, it's //our responsibility to delete it. We do so with this connection. connect(socket, &QAbstractSocket::disconnected, socket, &QObject::deleteLater); connect(socket, &QIODevice::readyRead, this, &LanLinkProvider::dataReceived); } } //I'm the new device and this is the answer to my UDP identity package (data received) void LanLinkProvider::dataReceived() { QSslSocket* socket = qobject_cast(sender()); const QByteArray data = socket->readLine(); //qCDebug(KDECONNECT_CORE) << "LanLinkProvider received reply:" << data; NetworkPackage* np = new NetworkPackage(QLatin1String("")); bool success = NetworkPackage::unserialize(data, np); if (!success) { delete np; return; } if (np->type() != PACKAGE_TYPE_IDENTITY) { qCWarning(KDECONNECT_CORE) << "LanLinkProvider/newConnection: Expected identity, received " << np->type(); delete np; return; } // Needed in "encrypted" if ssl is used, similar to "connected" m_receivedIdentityPackages[socket].np = np; const QString& deviceId = np->get(QStringLiteral("deviceId")); //qCDebug(KDECONNECT_CORE) << "Handshaking done (i'm the new device)"; //This socket will now be owned by the LanDeviceLink or we don't want more data to be received, forget about it disconnect(socket, &QIODevice::readyRead, this, &LanLinkProvider::dataReceived); if (np->get(QStringLiteral("protocolVersion")) >= MIN_VERSION_WITH_SSL_SUPPORT) { bool isDeviceTrusted = KdeConnectConfig::instance()->trustedDevices().contains(deviceId); configureSslSocket(socket, deviceId, isDeviceTrusted); qCDebug(KDECONNECT_CORE) << "Starting client ssl (but I'm the server TCP socket)"; connect(socket, &QSslSocket::encrypted, this, &LanLinkProvider::encrypted); if (isDeviceTrusted) { connect(socket, SIGNAL(sslErrors(QList)), this, SLOT(sslErrors(QList))); } socket->startClientEncryption(); } else { qWarning() << np->get(QStringLiteral("deviceName")) << "uses an old protocol version, this won't work"; //addLink(deviceId, socket, np, LanDeviceLink::Locally); delete m_receivedIdentityPackages.take(socket).np; } } void LanLinkProvider::deviceLinkDestroyed(QObject* destroyedDeviceLink) { const QString id = destroyedDeviceLink->property("deviceId").toString(); //qCDebug(KDECONNECT_CORE) << "deviceLinkDestroyed" << id; Q_ASSERT(m_links.key(static_cast(destroyedDeviceLink)) == id); QMap< QString, LanDeviceLink* >::iterator linkIterator = m_links.find(id); if (linkIterator != m_links.end()) { Q_ASSERT(linkIterator.value() == destroyedDeviceLink); m_links.erase(linkIterator); m_pairingHandlers.take(id)->deleteLater(); } } void LanLinkProvider::configureSslSocket(QSslSocket* socket, const QString& deviceId, bool isDeviceTrusted) { // Setting supported ciphers manually // Top 3 ciphers are for new Android devices, botton two are for old Android devices // FIXME : These cipher suites should be checked whether they are supported or not on device QList socketCiphers; socketCiphers.append(QSslCipher(QStringLiteral("ECDHE-ECDSA-AES256-GCM-SHA384"))); socketCiphers.append(QSslCipher(QStringLiteral("ECDHE-ECDSA-AES128-GCM-SHA256"))); socketCiphers.append(QSslCipher(QStringLiteral("ECDHE-RSA-AES128-SHA"))); socketCiphers.append(QSslCipher(QStringLiteral("RC4-SHA"))); socketCiphers.append(QSslCipher(QStringLiteral("RC4-MD5"))); // Configure for ssl QSslConfiguration sslConfig; sslConfig.setCiphers(socketCiphers); sslConfig.setProtocol(QSsl::TlsV1_0); socket->setSslConfiguration(sslConfig); socket->setLocalCertificate(KdeConnectConfig::instance()->certificate()); socket->setPrivateKey(KdeConnectConfig::instance()->privateKeyPath()); socket->setPeerVerifyName(deviceId); if (isDeviceTrusted) { QString certString = KdeConnectConfig::instance()->getDeviceProperty(deviceId, QStringLiteral("certificate"), QString()); socket->addCaCertificate(QSslCertificate(certString.toLatin1())); socket->setPeerVerifyMode(QSslSocket::VerifyPeer); } else { socket->setPeerVerifyMode(QSslSocket::QueryPeer); } //Usually SSL errors are only bad for trusted devices. Uncomment this section to log errors in any case, for debugging. //QObject::connect(socket, static_cast&)>(&QSslSocket::sslErrors), [](const QList& errors) //{ // Q_FOREACH (const QSslError& error, errors) { // qCDebug(KDECONNECT_CORE) << "SSL Error:" << error.errorString(); // } //}); } void LanLinkProvider::configureSocket(QSslSocket* socket) { socket->setProxy(QNetworkProxy::NoProxy); socket->setSocketOption(QAbstractSocket::KeepAliveOption, QVariant(1)); #ifdef TCP_KEEPIDLE // time to start sending keepalive packets (seconds) int maxIdle = 10; setsockopt(socket->socketDescriptor(), IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle)); #endif #ifdef TCP_KEEPINTVL // interval between keepalive packets after the initial period (seconds) int interval = 5; setsockopt(socket->socketDescriptor(), IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)); #endif #ifdef TCP_KEEPCNT // number of missed keepalive packets before disconnecting int count = 3; setsockopt(socket->socketDescriptor(), IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count)); #endif } void LanLinkProvider::addLink(const QString& deviceId, QSslSocket* socket, NetworkPackage* receivedPackage, LanDeviceLink::ConnectionStarted connectionOrigin) { // Socket disconnection will now be handled by LanDeviceLink disconnect(socket, &QAbstractSocket::disconnected, socket, &QObject::deleteLater); LanDeviceLink* deviceLink; //Do we have a link for this device already? QMap< QString, LanDeviceLink* >::iterator linkIterator = m_links.find(deviceId); if (linkIterator != m_links.end()) { //qCDebug(KDECONNECT_CORE) << "Reusing link to" << deviceId; deviceLink = linkIterator.value(); deviceLink->reset(socket, connectionOrigin); } else { deviceLink = new LanDeviceLink(deviceId, this, socket, connectionOrigin); connect(deviceLink, &QObject::destroyed, this, &LanLinkProvider::deviceLinkDestroyed); m_links[deviceId] = deviceLink; if (m_pairingHandlers.contains(deviceId)) { //We shouldn't have a pairinghandler if we didn't have a link. //Crash if debug, recover if release (by setting the new devicelink to the old pairinghandler) Q_ASSERT(m_pairingHandlers.contains(deviceId)); m_pairingHandlers[deviceId]->setDeviceLink(deviceLink); } - Q_EMIT onConnectionReceived(*receivedPackage, deviceLink); } - + Q_EMIT onConnectionReceived(*receivedPackage, deviceLink); } LanPairingHandler* LanLinkProvider::createPairingHandler(DeviceLink* link) { LanPairingHandler* ph = m_pairingHandlers.value(link->deviceId()); if (!ph) { ph = new LanPairingHandler(link); qCDebug(KDECONNECT_CORE) << "creating pairing handler for" << link->deviceId(); connect (ph, &LanPairingHandler::pairingError, link, &DeviceLink::pairingError); m_pairingHandlers[link->deviceId()] = ph; } return ph; } void LanLinkProvider::userRequestsPair(const QString& deviceId) { LanPairingHandler* ph = createPairingHandler(m_links.value(deviceId)); ph->requestPairing(); } void LanLinkProvider::userRequestsUnpair(const QString& deviceId) { LanPairingHandler* ph = createPairingHandler(m_links.value(deviceId)); ph->unpair(); } void LanLinkProvider::incomingPairPackage(DeviceLink* deviceLink, const NetworkPackage& np) { LanPairingHandler* ph = createPairingHandler(deviceLink); ph->packageReceived(np); } diff --git a/core/device.cpp b/core/device.cpp index 1afb8f1a..601bcb3c 100644 --- a/core/device.cpp +++ b/core/device.cpp @@ -1,489 +1,489 @@ /** * 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 "device.h" #ifdef interface // MSVC language extension, QDBusConnection uses this as a variable name #undef interface #endif #include #include #include #include #include #include "core_debug.h" #include "kdeconnectplugin.h" #include "pluginloader.h" #include "backends/devicelink.h" #include "backends/lan/landevicelink.h" #include "backends/linkprovider.h" #include "networkpackage.h" #include "kdeconnectconfig.h" #include "daemon.h" static void warn(const QString& info) { qWarning() << "Device pairing error" << info; } Device::Device(QObject* parent, const QString& id) : QObject(parent) , m_deviceId(id) , m_protocolVersion(NetworkPackage::s_protocolVersion) //We don't know it yet { KdeConnectConfig::DeviceInfo info = KdeConnectConfig::instance()->getTrustedDevice(id); m_deviceName = info.deviceName; m_deviceType = str2type(info.deviceType); //Register in bus QDBusConnection::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors); //Assume every plugin is supported until addLink is called and we can get the actual list m_supportedPlugins = PluginLoader::instance()->getPluginList().toSet(); connect(this, &Device::pairingError, this, &warn); } Device::Device(QObject* parent, const NetworkPackage& identityPackage, DeviceLink* dl) : QObject(parent) , m_deviceId(identityPackage.get(QStringLiteral("deviceId"))) , m_deviceName(identityPackage.get(QStringLiteral("deviceName"))) { addLink(identityPackage, dl); //Register in bus QDBusConnection::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors); connect(this, &Device::pairingError, this, &warn); } Device::~Device() { qDeleteAll(m_deviceLinks); m_deviceLinks.clear(); } bool Device::hasPlugin(const QString& name) const { return m_plugins.contains(name); } QStringList Device::loadedPlugins() const { return m_plugins.keys(); } void Device::reloadPlugins() { QHash newPluginMap, oldPluginMap = m_plugins; QMultiMap newPluginsByIncomingCapability; if (isTrusted() && isReachable()) { //Do not load any plugin for unpaired devices, nor useless loading them for unreachable devices PluginLoader* loader = PluginLoader::instance(); for (const QString& pluginName : qAsConst(m_supportedPlugins)) { const KPluginMetaData service = loader->getPluginInfo(pluginName); const bool pluginEnabled = isPluginEnabled(pluginName); const QSet incomingCapabilities = KPluginMetaData::readStringList(service.rawData(), QStringLiteral("X-KdeConnect-SupportedPackageType")).toSet(); if (pluginEnabled) { KdeConnectPlugin* plugin = m_plugins.take(pluginName); if (!plugin) { plugin = loader->instantiatePluginForDevice(pluginName, this); } Q_ASSERT(plugin); for (const QString& interface : incomingCapabilities) { newPluginsByIncomingCapability.insert(interface, plugin); } newPluginMap[pluginName] = plugin; } } } const bool differentPlugins = oldPluginMap != newPluginMap; //Erase all left plugins in the original map (meaning that we don't want //them anymore, otherwise they would have been moved to the newPluginMap) qDeleteAll(m_plugins); m_plugins = newPluginMap; m_pluginsByIncomingCapability = newPluginsByIncomingCapability; QDBusConnection bus = QDBusConnection::sessionBus(); for (KdeConnectPlugin* plugin : qAsConst(m_plugins)) { //TODO: see how it works in Android (only done once, when created) plugin->connected(); const QString dbusPath = plugin->dbusPath(); if (!dbusPath.isEmpty()) { bus.registerObject(dbusPath, plugin, QDBusConnection::ExportAllProperties | QDBusConnection::ExportScriptableInvokables | QDBusConnection::ExportScriptableSignals | QDBusConnection::ExportScriptableSlots); } } if (differentPlugins) { Q_EMIT pluginsChanged(); } } QString Device::pluginsConfigFile() const { return KdeConnectConfig::instance()->deviceConfigDir(id()).absoluteFilePath(QStringLiteral("config")); } void Device::requestPair() { if (isTrusted()) { Q_EMIT pairingError(i18n("Already paired")); return; } if (!isReachable()) { Q_EMIT pairingError(i18n("Device not reachable")); return; } for (DeviceLink* dl : qAsConst(m_deviceLinks)) { dl->userRequestsPair(); } } void Device::unpair() { for (DeviceLink* dl : qAsConst(m_deviceLinks)) { dl->userRequestsUnpair(); } KdeConnectConfig::instance()->removeTrustedDevice(id()); Q_EMIT trustedChanged(false); } void Device::pairStatusChanged(DeviceLink::PairStatus status) { if (status == DeviceLink::NotPaired) { KdeConnectConfig::instance()->removeTrustedDevice(id()); for (DeviceLink* dl : qAsConst(m_deviceLinks)) { if (dl != sender()) { dl->setPairStatus(DeviceLink::NotPaired); } } } else { KdeConnectConfig::instance()->addTrustedDevice(id(), name(), type()); } reloadPlugins(); //Will load/unload plugins bool isTrusted = (status == DeviceLink::Paired); Q_EMIT trustedChanged(isTrusted); Q_ASSERT(isTrusted == this->isTrusted()); } static bool lessThan(DeviceLink* p1, DeviceLink* p2) { return p1->provider()->priority() > p2->provider()->priority(); } void Device::addLink(const NetworkPackage& identityPackage, DeviceLink* link) { //qCDebug(KDECONNECT_CORE) << "Adding link to" << id() << "via" << link->provider(); - Q_ASSERT(!m_deviceLinks.contains(link)); + setName(identityPackage.get(QStringLiteral("deviceName"))); + m_deviceType = str2type(identityPackage.get(QStringLiteral("deviceType"))); + + if (m_deviceLinks.contains(link)) + return; m_protocolVersion = identityPackage.get(QStringLiteral("protocolVersion"), -1); if (m_protocolVersion != NetworkPackage::s_protocolVersion) { qCWarning(KDECONNECT_CORE) << m_deviceName << "- warning, device uses a different protocol version" << m_protocolVersion << "expected" << NetworkPackage::s_protocolVersion; } connect(link, &QObject::destroyed, this, &Device::linkDestroyed); m_deviceLinks.append(link); - //re-read the device name from the identityPackage because it could have changed - setName(identityPackage.get(QStringLiteral("deviceName"))); - m_deviceType = str2type(identityPackage.get(QStringLiteral("deviceType"))); - //Theoretically we will never add two links from the same provider (the provider should destroy //the old one before this is called), so we do not have to worry about destroying old links. //-- Actually, we should not destroy them or the provider will store an invalid ref! connect(link, &DeviceLink::receivedPackage, this, &Device::privateReceivedPackage); qSort(m_deviceLinks.begin(), m_deviceLinks.end(), lessThan); const bool capabilitiesSupported = identityPackage.has(QStringLiteral("incomingCapabilities")) || identityPackage.has(QStringLiteral("outgoingCapabilities")); if (capabilitiesSupported) { const QSet outgoingCapabilities = identityPackage.get(QStringLiteral("outgoingCapabilities")).toSet() , incomingCapabilities = identityPackage.get(QStringLiteral("incomingCapabilities")).toSet(); m_supportedPlugins = PluginLoader::instance()->pluginsForCapabilities(incomingCapabilities, outgoingCapabilities); //qDebug() << "new plugins for" << m_deviceName << m_supportedPlugins << incomingCapabilities << outgoingCapabilities; } else { m_supportedPlugins = PluginLoader::instance()->getPluginList().toSet(); } reloadPlugins(); if (m_deviceLinks.size() == 1) { Q_EMIT reachableChanged(true); } connect(link, &DeviceLink::pairStatusChanged, this, &Device::pairStatusChanged); connect(link, &DeviceLink::pairingRequest, this, &Device::addPairingRequest); connect(link, &DeviceLink::pairingRequestExpired, this, &Device::removePairingRequest); connect(link, &DeviceLink::pairingError, this, &Device::pairingError); } void Device::addPairingRequest(PairingHandler* handler) { const bool wasEmpty = m_pairRequests.isEmpty(); m_pairRequests.insert(handler); if (wasEmpty != m_pairRequests.isEmpty()) Q_EMIT hasPairingRequestsChanged(!m_pairRequests.isEmpty()); } void Device::removePairingRequest(PairingHandler* handler) { const bool wasEmpty = m_pairRequests.isEmpty(); m_pairRequests.remove(handler); if (wasEmpty != m_pairRequests.isEmpty()) Q_EMIT hasPairingRequestsChanged(!m_pairRequests.isEmpty()); } bool Device::hasPairingRequests() const { return !m_pairRequests.isEmpty(); } void Device::acceptPairing() { if (m_pairRequests.isEmpty()) qWarning() << "no pair requests to accept!"; //copying because the pairing handler will be removed upon accept const auto prCopy = m_pairRequests; for (auto ph: prCopy) ph->acceptPairing(); } void Device::rejectPairing() { if (m_pairRequests.isEmpty()) qWarning() << "no pair requests to reject!"; //copying because the pairing handler will be removed upon reject const auto prCopy = m_pairRequests; for (auto ph: prCopy) ph->rejectPairing(); } void Device::linkDestroyed(QObject* o) { removeLink(static_cast(o)); } void Device::removeLink(DeviceLink* link) { m_deviceLinks.removeAll(link); //qCDebug(KDECONNECT_CORE) << "RemoveLink" << m_deviceLinks.size() << "links remaining"; if (m_deviceLinks.isEmpty()) { reloadPlugins(); Q_EMIT reachableChanged(false); } } bool Device::sendPackage(NetworkPackage& np) { Q_ASSERT(np.type() != PACKAGE_TYPE_PAIR); Q_ASSERT(isTrusted()); //Maybe we could block here any package that is not an identity or a pairing package to prevent sending non encrypted data for (DeviceLink* dl : qAsConst(m_deviceLinks)) { if (dl->sendPackage(np)) return true; } return false; } void Device::privateReceivedPackage(const NetworkPackage& np) { Q_ASSERT(np.type() != PACKAGE_TYPE_PAIR); if (isTrusted()) { const QList plugins = m_pluginsByIncomingCapability.values(np.type()); if (plugins.isEmpty()) { qWarning() << "discarding unsupported package" << np.type() << "for" << name(); } for (KdeConnectPlugin* plugin : plugins) { plugin->receivePackage(np); } } else { qCDebug(KDECONNECT_CORE) << "device" << name() << "not paired, ignoring package" << np.type(); unpair(); } } bool Device::isTrusted() const { return KdeConnectConfig::instance()->trustedDevices().contains(id()); } QStringList Device::availableLinks() const { QStringList sl; sl.reserve(m_deviceLinks.size()); for (DeviceLink* dl : qAsConst(m_deviceLinks)) { sl.append(dl->provider()->name()); } return sl; } void Device::cleanUnneededLinks() { if (isTrusted()) { return; } for(int i = 0; i < m_deviceLinks.size(); ) { DeviceLink* dl = m_deviceLinks[i]; if (!dl->linkShouldBeKeptAlive()) { dl->deleteLater(); m_deviceLinks.remove(i); } else { i++; } } } QHostAddress Device::getLocalIpAddress() const { for (DeviceLink* dl : m_deviceLinks) { LanDeviceLink* ldl = dynamic_cast(dl); if (ldl) { return ldl->hostAddress(); } } return QHostAddress::Null; } Device::DeviceType Device::str2type(const QString& deviceType) { if (deviceType == QLatin1String("desktop")) return Desktop; if (deviceType == QLatin1String("laptop")) return Laptop; if (deviceType == QLatin1String("smartphone") || deviceType == QLatin1String("phone")) return Phone; if (deviceType == QLatin1String("tablet")) return Tablet; return Unknown; } QString Device::type2str(Device::DeviceType deviceType) { if (deviceType == Desktop) return QStringLiteral("desktop"); if (deviceType == Laptop) return QStringLiteral("laptop"); if (deviceType == Phone) return QStringLiteral("smartphone"); if (deviceType == Tablet) return QStringLiteral("tablet"); return QStringLiteral("unknown"); } QString Device::statusIconName() const { return iconForStatus(isReachable(), isTrusted()); } QString Device::iconName() const { return iconForStatus(true, false); } QString Device::iconForStatus(bool reachable, bool trusted) const { Device::DeviceType deviceType = m_deviceType; if (deviceType == Device::Unknown) { deviceType = Device::Phone; //Assume phone if we don't know the type } else if (deviceType == Device::Desktop) { deviceType = Device::Device::Laptop; // We don't have desktop icon yet } QString status = (reachable? (trusted? QStringLiteral("connected") : QStringLiteral("disconnected")) : QStringLiteral("trusted")); QString type = type2str(deviceType); return type+status; } void Device::setName(const QString& name) { if (m_deviceName != name) { m_deviceName = name; Q_EMIT nameChanged(name); } } KdeConnectPlugin* Device::plugin(const QString& pluginName) const { return m_plugins[pluginName]; } void Device::setPluginEnabled(const QString& pluginName, bool enabled) { KConfigGroup pluginStates = KSharedConfig::openConfig(pluginsConfigFile())->group("Plugins"); const QString enabledKey = pluginName + QStringLiteral("Enabled"); pluginStates.writeEntry(enabledKey, enabled); reloadPlugins(); } bool Device::isPluginEnabled(const QString& pluginName) const { const QString enabledKey = pluginName + QStringLiteral("Enabled"); KConfigGroup pluginStates = KSharedConfig::openConfig(pluginsConfigFile())->group("Plugins"); return (pluginStates.hasKey(enabledKey) ? pluginStates.readEntry(enabledKey, false) : PluginLoader::instance()->getPluginInfo(pluginName).isEnabledByDefault()); } QString Device::encryptionInfo() const { QString result; QCryptographicHash::Algorithm digestAlgorithm = QCryptographicHash::Algorithm::Sha1; QString localSha1 = QString::fromLatin1(KdeConnectConfig::instance()->certificate().digest(digestAlgorithm).toHex()); for (int i = 2; igetDeviceProperty(id(), QStringLiteral("certificate")).toStdString(); QSslCertificate remoteCertificate = QSslCertificate(QByteArray(remotePem.c_str(), (int)remotePem.size())); QString remoteSha1 = QString::fromLatin1(remoteCertificate.digest(digestAlgorithm).toHex()); for (int i = 2; i < remoteSha1.size(); i += 3) { remoteSha1.insert(i, ':'); // Improve readability } result += i18n("SHA1 fingerprint of remote device certificate is: %1\n", remoteSha1); return result; } diff --git a/core/device.h b/core/device.h index 8cde9440..dd7eac4b 100644 --- a/core/device.h +++ b/core/device.h @@ -1,164 +1,164 @@ /** * 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 . */ #ifndef DEVICE_H #define DEVICE_H #include #include #include #include #include #include "networkpackage.h" #include "backends/devicelink.h" class DeviceLink; class KdeConnectPlugin; class KDECONNECTCORE_EXPORT Device : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device") Q_PROPERTY(QString type READ type CONSTANT) Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(QString iconName READ iconName CONSTANT) Q_PROPERTY(QString statusIconName READ statusIconName) Q_PROPERTY(bool isReachable READ isReachable NOTIFY reachableChanged) Q_PROPERTY(bool isTrusted READ isTrusted NOTIFY trustedChanged) Q_PROPERTY(QStringList supportedPlugins READ supportedPlugins NOTIFY pluginsChanged) Q_PROPERTY(bool hasPairingRequests READ hasPairingRequests NOTIFY hasPairingRequestsChanged) public: enum DeviceType { Unknown, Desktop, Laptop, Phone, Tablet, }; /** * Restores the @p device from the saved configuration * * We already know it but we need to wait for an incoming DeviceLink to communicate */ Device(QObject* parent, const QString& id); /** * Device known via an incoming connection sent to us via a devicelink. * * We know everything but we don't trust it yet */ Device(QObject* parent, const NetworkPackage& np, DeviceLink* dl); ~Device() override; QString id() const { return m_deviceId; } QString name() const { return m_deviceName; } QString dbusPath() const { return "/modules/kdeconnect/devices/"+id(); } QString type() const { return type2str(m_deviceType); } QString iconName() const; QString statusIconName() const; Q_SCRIPTABLE QString encryptionInfo() const; //Add and remove links void addLink(const NetworkPackage& identityPackage, DeviceLink*); void removeLink(DeviceLink*); Q_SCRIPTABLE bool isTrusted() const; Q_SCRIPTABLE QStringList availableLinks() const; bool isReachable() const { return !m_deviceLinks.isEmpty(); } Q_SCRIPTABLE QStringList loadedPlugins() const; Q_SCRIPTABLE bool hasPlugin(const QString& name) const; Q_SCRIPTABLE QString pluginsConfigFile() const; KdeConnectPlugin* plugin(const QString& pluginName) const; - void setPluginEnabled(const QString& pluginName, bool enabled); - bool isPluginEnabled(const QString& pluginName) const; + Q_SCRIPTABLE void setPluginEnabled(const QString& pluginName, bool enabled); + Q_SCRIPTABLE bool isPluginEnabled(const QString& pluginName) const; void cleanUnneededLinks(); int protocolVersion() { return m_protocolVersion; } QStringList supportedPlugins() const { return m_supportedPlugins.toList(); } QHostAddress getLocalIpAddress() const; public Q_SLOTS: ///sends a @p np package to the device ///virtual for testing purposes. virtual bool sendPackage(NetworkPackage& np); //Dbus operations public Q_SLOTS: Q_SCRIPTABLE void requestPair(); //to all links Q_SCRIPTABLE void unpair(); //from all links Q_SCRIPTABLE void reloadPlugins(); //from kconf Q_SCRIPTABLE void acceptPairing(); Q_SCRIPTABLE void rejectPairing(); Q_SCRIPTABLE bool hasPairingRequests() const; private Q_SLOTS: void privateReceivedPackage(const NetworkPackage& np); void linkDestroyed(QObject* o); void pairStatusChanged(DeviceLink::PairStatus current); void addPairingRequest(PairingHandler* handler); void removePairingRequest(PairingHandler* handler); Q_SIGNALS: Q_SCRIPTABLE void pluginsChanged(); Q_SCRIPTABLE void reachableChanged(bool reachable); Q_SCRIPTABLE void trustedChanged(bool trusted); Q_SCRIPTABLE void pairingError(const QString& error); Q_SCRIPTABLE void nameChanged(const QString& name); Q_SCRIPTABLE void hasPairingRequestsChanged(bool hasPairingRequests); private: //Methods static DeviceType str2type(const QString& deviceType); static QString type2str(DeviceType deviceType); void setName(const QString& name); QString iconForStatus(bool reachable, bool paired) const; private: //Fields (TODO: dPointer!) const QString m_deviceId; QString m_deviceName; DeviceType m_deviceType; int m_protocolVersion; QVector m_deviceLinks; QHash m_plugins; //Capabilities stuff QMultiMap m_pluginsByIncomingCapability; QSet m_supportedPlugins; QSet m_pairRequests; }; Q_DECLARE_METATYPE(Device*) #endif // DEVICE_H diff --git a/core/filetransferjob.cpp b/core/filetransferjob.cpp index 0602737b..583cb0af 100644 --- a/core/filetransferjob.cpp +++ b/core/filetransferjob.cpp @@ -1,132 +1,137 @@ /* * Copyright 2013 Albert Vaca * Copyright 2015 Aleix Pol i 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 "filetransferjob.h" #include "daemon.h" #include #include #include #include #include FileTransferJob::FileTransferJob(const QSharedPointer& origin, qint64 size, const QUrl& destination) : KJob() , m_origin(origin) , m_reply(Q_NULLPTR) , m_from(QStringLiteral("KDE Connect")) , m_destination(destination) , m_speedBytes(0) , m_written(0) + , m_size(size) { Q_ASSERT(m_origin); Q_ASSERT(m_origin->isReadable()); if (m_destination.scheme().isEmpty()) { qCWarning(KDECONNECT_CORE) << "Destination QUrl" << m_destination << "lacks a scheme. Setting its scheme to 'file'."; m_destination.setScheme(QStringLiteral("file")); } - if (size >= 0) { - setTotalAmount(Bytes, size); - } - setCapabilities(Killable); - qCDebug(KDECONNECT_CORE) << "FileTransferJob Downloading payload to" << destination; + qCDebug(KDECONNECT_CORE) << "FileTransferJob Downloading payload to" << destination << "size:" << size; } void FileTransferJob::start() { QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection); //qCDebug(KDECONNECT_CORE) << "FileTransferJob start"; } void FileTransferJob::doStart() { description(this, i18n("Receiving file over KDE Connect"), { i18nc("File transfer origin", "From"), m_from } ); if (m_destination.isLocalFile() && QFile::exists(m_destination.toLocalFile())) { setError(2); setErrorText(i18n("Filename already present")); emitResult(); return; } if (m_origin->bytesAvailable()) startTransfer(); connect(m_origin.data(), &QIODevice::readyRead, this, &FileTransferJob::startTransfer); } void FileTransferJob::startTransfer() { + // Don't put each ready read + if (m_reply) + return; + setProcessedAmount(Bytes, 0); - m_timer.start(); description(this, i18n("Receiving file over KDE Connect"), { i18nc("File transfer origin", "From"), m_from }, { i18nc("File transfer destination", "To"), m_destination.toLocalFile() }); QNetworkRequest req(m_destination); - req.setHeader(QNetworkRequest::ContentLengthHeader, totalAmount(Bytes)); + if (m_size >= 0) { + setTotalAmount(Bytes, m_size); + req.setHeader(QNetworkRequest::ContentLengthHeader, m_size); + } m_reply = Daemon::instance()->networkAccessManager()->put(req, m_origin.data()); connect(m_reply, &QNetworkReply::uploadProgress, this, [this](qint64 bytesSent, qint64 /*bytesTotal*/) { + if (!m_timer.isValid()) + m_timer.start(); setProcessedAmount(Bytes, bytesSent); const auto elapsed = m_timer.elapsed(); if (elapsed > 0) { - emitSpeed(bytesSent / elapsed); + emitSpeed((1000 * bytesSent) / elapsed); } }); connect(m_reply, static_cast(&QNetworkReply::error), this, &FileTransferJob::transferFailed); connect(m_reply, &QNetworkReply::finished, this, &FileTransferJob::transferFinished); } void FileTransferJob::transferFailed(QNetworkReply::NetworkError error) { qCDebug(KDECONNECT_CORE) << "Couldn't transfer the file successfully" << error << m_reply->errorString(); setError(error); setErrorText(i18n("Received incomplete file: %1", m_reply->errorString())); emitResult(); m_reply->close(); } void FileTransferJob::transferFinished() { //TODO: MD5-check the file qCDebug(KDECONNECT_CORE) << "Finished transfer" << m_destination; emitResult(); } bool FileTransferJob::doKill() { if (m_reply) { m_reply->close(); } if (m_origin) { m_origin->close(); } return true; } diff --git a/core/filetransferjob.h b/core/filetransferjob.h index 83575a01..9979577a 100644 --- a/core/filetransferjob.h +++ b/core/filetransferjob.h @@ -1,77 +1,78 @@ /* * Copyright 2013 Albert Vaca * Copyright 2015 Aleix Pol i 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 . */ #ifndef FILETRANSFERJOB_H #define FILETRANSFERJOB_H #include #include #include #include #include #include #include "kdeconnectcore_export.h" /** * @short It will stream a device into a url destination * * Given a QIODevice, the file transfer job will use the system's QNetworkAccessManager * for putting the stream into the requested location. */ class KDECONNECTCORE_EXPORT FileTransferJob : public KJob { Q_OBJECT public: /** * @p origin specifies the data to read from. * @p size specifies the expected size of the stream we're reading. * @p destination specifies where these contents should be stored */ FileTransferJob(const QSharedPointer& origin, qint64 size, const QUrl& destination); void start() override; QUrl destination() const { return m_destination; } void setOriginName(const QString& from) { m_from = from; } private Q_SLOTS: void doStart(); protected: bool doKill() override; private: void startTransfer(); void transferFailed(QNetworkReply::NetworkError error); void transferFinished(); QSharedPointer m_origin; QNetworkReply* m_reply; QString m_from; QUrl m_destination; QElapsedTimer m_timer; qulonglong m_speedBytes; qint64 m_written; + qint64 m_size; }; #endif diff --git a/daemon/kdeconnect.desktop b/daemon/kdeconnect.desktop index 05de252a..3c66c423 100644 --- a/daemon/kdeconnect.desktop +++ b/daemon/kdeconnect.desktop @@ -1,91 +1,83 @@ [Desktop Entry] Type=Service Icon=preferences-system-power-management X-KDE-ServiceTypes=KDEDModule X-KDE-Library=kdeconnect X-DBUS-ServiceName=org.kde.kdeconnect X-KDE-DBus-ModuleName=kdeconnect X-KDE-Kded-autoload=true X-KDE-Kded-load-on-demand=false X-KDE-Kded-phase=1 Name=KDE Connect -Name[ar]=كدي المتّصل -Name[ast]=KDE Connect Name[bg]=KDE Connect Name[bs]=Konekcija KDE Name[ca]=KDE Connect Name[ca@valencia]=KDE Connect Name[cs]=KDE Connect Name[da]=KDE Connect Name[de]=KDE-Connect -Name[el]=KDE Connect Name[en_GB]=KDE Connect Name[es]=KDE Connect Name[et]=KDE Connect Name[eu]=KDE Connect Name[fi]=KDE Connect Name[fr]=KDE Connect Name[gl]=KDE Connect -Name[he]=KDE Connect Name[hu]=KDE csatlakozás Name[it]=KDE Connect Name[ko]=KDE Connect Name[nl]=KDE Connect Name[nn]=KDE Connect Name[pl]=KDE Connect Name[pt]=KDE Connect Name[pt_BR]=KDE Connect Name[ro]=KDE Connect Name[ru]=KDE Connect Name[sk]=KDE Connect Name[sr]=КДЕ‑конекција Name[sr@ijekavian]=КДЕ‑конекција Name[sr@ijekavianlatin]=KDE‑konekcija Name[sr@latin]=KDE‑konekcija Name[sv]=KDE-anslut Name[tr]=KDE Connect Name[uk]=З’єднання KDE Name[x-test]=xxKDE Connectxx Name[zh_CN]=KDE Connect Name[zh_TW]=KDE 連線 Comment=Connect KDE with your smartphone -Comment[ar]=أوصل كدي بهاتفك الذّكيّ -Comment[ast]=Coneuta KDE col to teléfonu intelixente Comment[bg]=Свържете КДЕ с вашия смартфон Comment[bs]=Konektujte se na KDE sa Vašim mobitelom Comment[ca]=Connecta el KDE amb el vostre telèfon intel·ligent Comment[ca@valencia]=Connecta el KDE amb el vostre telèfon intel·ligent Comment[cs]=Propojte KDE s vaším telefonem Comment[da]=Forbind KDE med din smartphone Comment[de]=KDE mit Ihren Smartphone verbinden -Comment[el]=Σύνδεση του KDE με το έξυπνο τηλέφωνό σας Comment[en_GB]=Connect KDE with your smartphone Comment[es]=Conecte KDE con su teléfono móvil Comment[et]=KDE ühendamine oma nutitelefoniga Comment[eu]=Konektatu KDE zure mugikorrarekin Comment[fi]=Yhdistä KDE älypuhelimeesi Comment[fr]=Connectez KDE avec votre smartphone Comment[gl]=Conectar KDE co seu teléfono móbil. -Comment[he]=חבר את KDE לפלאפון החכם שלך Comment[hu]=A KDE csatlakoztatása az okostelefonnal Comment[it]=Connetti KDE con il tuo smartphone Comment[ko]=KDE와 스마트폰 연결 Comment[nl]=KDE met uw smartphone verbinden Comment[nn]=Kopla KDE til smarttelefonen din Comment[pl]=Podłącz swój smartfon do KDE Comment[pt]=Ligue o KDE ao seu telemóvel Comment[pt_BR]=Conecte o KDE ao seu celular Comment[ru]=Подключайте смартфон к KDE Comment[sk]=Prepojiť KDE s vašim smartfónom Comment[sr]=Повежите КДЕ са својим паметним телефоном Comment[sr@ijekavian]=Повежите КДЕ са својим паметним телефоном Comment[sr@ijekavianlatin]=Povežite KDE sa svojim pametnim telefonom Comment[sr@latin]=Povežite KDE sa svojim pametnim telefonom Comment[sv]=Anslut KDE till din smartphone Comment[tr]=KDE'yi akıllı telefonunuz ile bağlayın Comment[uk]=З’єднання KDE з вашим смартфоном Comment[x-test]=xxConnect KDE with your smartphonexx Comment[zh_CN]=用您的智能手机连接到 KDE Comment[zh_TW]=將您的智慧型手機與KDE連線 diff --git a/daemon/kdeconnectd.desktop.cmake b/daemon/kdeconnectd.desktop.cmake index a7ec7ccb..3bb88eee 100644 --- a/daemon/kdeconnectd.desktop.cmake +++ b/daemon/kdeconnectd.desktop.cmake @@ -1,47 +1,43 @@ [Desktop Entry] Type=Application Exec=${KDE_INSTALL_FULL_LIBEXECDIR}/kdeconnectd X-KDE-StartupNotify=false X-KDE-autostart-phase=0 X-GNOME-Autostart-enabled=true OnlyShowIn=KDE;GNOME;Unity;XFCE; NoDisplay=true Name=KDEConnect daemon -Name[ar]=عفريت KDEConnect -Name[ast]=Degorriu KDEConnect Name[bg]=Услуга KDE Connect Name[ca]=Dimoni del KDEConnect Name[ca@valencia]=Dimoni del KDEConnect Name[cs]=Démon KDE Connect Name[da]=KDEConnect-dæmon Name[de]=KDE-Connect-Dienst -Name[el]=Δαίμονας του KDEConnect Name[en_GB]=KDEConnect daemon Name[es]=Demonio de KDE Connect Name[et]=KDEConnecti deemon Name[eu]=KDEConnect daimona Name[fi]=KDEConnect-taustapalvelu Name[fr]=Démon KDE Connect Name[gl]=Servizo de KDE Connect -Name[he]=דמון KDEConnect Name[hu]=KDEConnect szolgáltatás Name[it]=Demone KDE Connect Name[ko]=KDE Connect 데몬 Name[nl]=KDEConnect-daemon Name[nn]=KDEConnect-teneste Name[pl]=Usługa KDEConnect Name[pt]=Serviço do KDE Connect Name[pt_BR]=Serviço do KDE Connect Name[ru]=Служба KDE Connect Name[sk]=KDEConnect démon Name[sr]=КДЕ‑конекцијин демон Name[sr@ijekavian]=КДЕ‑конекцијин демон Name[sr@ijekavianlatin]=KDE‑konekcijin demon Name[sr@latin]=KDE‑konekcijin demon Name[sv]=Demon för KDE-anslut Name[tr]=KDEConnect süreci Name[uk]=Фонова служба KDEConnect Name[x-test]=xxKDEConnect daemonxx Name[zh_CN]=KDEConnect 守护进程 Name[zh_TW]=KDE連線作業 diff --git a/fileitemactionplugin/kdeconnectsendfile.desktop b/fileitemactionplugin/kdeconnectsendfile.desktop index 56c5c0ab..41cdc0b2 100644 --- a/fileitemactionplugin/kdeconnectsendfile.desktop +++ b/fileitemactionplugin/kdeconnectsendfile.desktop @@ -1,86 +1,77 @@ [Desktop Entry] Type=Service Name=Send file via KDE Connect service -Name[ar]=أرسل ملفًّا عبر خدمة «كدي المتّصل» -Name[ast]=Unviar ficheru pel serviciu de KDE Connect Name[bg]=Изпращане на файл през услугата KDE Connect Name[bs]=Pošalji datoteku putem KDE Connect servisa Name[ca]=Envia un fitxer a través del servei KDE Connect Name[ca@valencia]=Envia un fitxer a través del servei KDE Connect Name[cs]=Poslat soubor přes službu KDE Connect Name[da]=Send fil via KDE Connect-tjeneste Name[de]=Datei mit KDE-Connect -Dienst versenden -Name[el]=Αποστολή αρχείου μέσω της υπηρεσίας KDE Connect Name[en_GB]=Send file via KDE Connect service Name[es]=Enviar archivo usando el servicio KDE Connect Name[et]=Faili saatmine KDE Connecti teenuse kaudu Name[eu]=Bidali fitxategia KDE Connect zerbitzuaren bidez Name[fi]=Lähetä tiedosto KDE Connect -palvelulla Name[fr]=Envoyer un fichier via le service KDE Connect Name[gl]=Enviar un ficheiro mediante o servizo de KDE Connect -Name[he]=שלח קובץ דרך שירות KDE Connect Name[hu]=Fájl küldése a KDE csatlakozás szolgáltatáson keresztül Name[it]=Invia un file tramite il servizio KDE Connect Name[ko]=KDE Connect 서비스로 파일 보내기 Name[nl]=Bestand via de service KDE Connect versturen Name[nn]=Send fil med KDE Connect-tenesta Name[pl]=Wyślij plik przez usługę KDE Connect Name[pt]=Enviar um ficheiro pelo serviço KDE Connect Name[pt_BR]=Enviar arquivo pelo serviço KDE Connect Name[ru]=Отправить файл через KDE Connect Name[sk]=Poslať súbor cez službu KDE Connect Name[sr]=Шаљи фајл преко КДЕ‑конекцијиног сервиса Name[sr@ijekavian]=Шаљи фајл преко КДЕ‑конекцијиног сервиса Name[sr@ijekavianlatin]=Šalji fajl preko KDE‑konekcijinog servisa Name[sr@latin]=Šalji fajl preko KDE‑konekcijinog servisa Name[sv]=Skicka fil via KDE:s anslutningstjänst Name[tr]=KDE Connect servisi ile dosya gönderin Name[uk]=Надсилання файла за допомогою служби з’єднання KDE Name[x-test]=xxSend file via KDE Connect servicexx Name[zh_CN]=通过 KDE Connect 服务发送文件 Name[zh_TW]=以已經連結到KDE之服務或裝置來傳送檔案 X-KDE-Library=kdeconnectfileitemaction X-KDE-Submenu=Connect -X-KDE-Submenu[ar]=اتّصل,اتصل -X-KDE-Submenu[ast]=Coneutar X-KDE-Submenu[bg]=Свързване X-KDE-Submenu[bs]=Uspostavi vezu X-KDE-Submenu[ca]=Connecta X-KDE-Submenu[ca@valencia]=Connecta X-KDE-Submenu[cs]=Připojit X-KDE-Submenu[da]=Forbind X-KDE-Submenu[de]=Verbinden -X-KDE-Submenu[el]=Σύνδεση X-KDE-Submenu[en_GB]=Connect X-KDE-Submenu[es]=Conectar X-KDE-Submenu[et]=Ühendus X-KDE-Submenu[eu]=Konektatu X-KDE-Submenu[fi]=Yhdistä X-KDE-Submenu[fr]=Connecter X-KDE-Submenu[gl]=Conectar -X-KDE-Submenu[he]=חיבור X-KDE-Submenu[hu]=Csatlakozás -X-KDE-Submenu[ia]=Connecte X-KDE-Submenu[it]=Connetti X-KDE-Submenu[ko]=연결 X-KDE-Submenu[nl]=Verbinden X-KDE-Submenu[nn]=Kopla til X-KDE-Submenu[pl]=Połącz X-KDE-Submenu[pt]=Ligar X-KDE-Submenu[pt_BR]=Conectar X-KDE-Submenu[ru]=KDE Connect X-KDE-Submenu[sk]=Pripojiť X-KDE-Submenu[sr]=Повежи се X-KDE-Submenu[sr@ijekavian]=Повежи се X-KDE-Submenu[sr@ijekavianlatin]=Poveži se X-KDE-Submenu[sr@latin]=Poveži se X-KDE-Submenu[sv]=Anslut X-KDE-Submenu[tr]=Bağlan X-KDE-Submenu[uk]=З’єднання X-KDE-Submenu[x-test]=xxConnectxx X-KDE-Submenu[zh_CN]=连接 X-KDE-Submenu[zh_TW]=連線 Icon=preferences-system-network ServiceTypes=KFileItemAction/Plugin MimeType=application/octet-stream diff --git a/indicator/org.kde.kdeconnect.nonplasma.desktop b/indicator/org.kde.kdeconnect.nonplasma.desktop old mode 100755 new mode 100644 index 2ea61f0a..c118f02c --- a/indicator/org.kde.kdeconnect.nonplasma.desktop +++ b/indicator/org.kde.kdeconnect.nonplasma.desktop @@ -1,68 +1,64 @@ [Desktop Entry] Name=KDE Connect Indicator Name[ca]=Indicador del KDE Connect Name[ca@valencia]=Indicador del KDE Connect Name[cs]=Indikátor KDE Connect Name[da]=KDE Connect-indikator Name[de]=KDE-Connect-Anzeige Name[es]=Indicador de KDE Connect Name[eu]=KDE Connect adierazlea Name[fr]=Indicateur de KDE Connect -Name[gl]=Indicador de KDE Connect Name[it]=Indicatore di KDE Connect -Name[nl]=KDE-Connect indicator +Name[nl]=KDE-Connect-indicator Name[nn]=KDE Connect-indikator Name[pl]=Wskaźnik KDE Connect Name[pt]=Indicador do KDE Connect +Name[sk]=KDE Connect indikátor Name[sr]=КДЕ‑конекцијин показатељ Name[sr@ijekavian]=КДЕ‑конекцијин показатељ Name[sr@ijekavianlatin]=KDE‑konekcijin pokazatelj Name[sr@latin]=KDE‑konekcijin pokazatelj Name[sv]=KDE-anslut indikator Name[tr]=KDE Connect Göstergesi Name[uk]=Індикатор KDE Connect Name[x-test]=xxKDE Connect Indicatorxx Comment=Display information about your devices -Comment[ar]=اعرض معلومات عن أجهزتك -Comment[ast]=Amuesa información tocante a los tos preseos Comment[ca]=Mostra la informació dels vostres dispositius Comment[ca@valencia]=Mostra la informació dels vostres dispositius Comment[cs]=Zobrazit informace o vašich zařízeních Comment[da]=Vis information om dine enheder Comment[de]=Anzeige von Informationen über Ihre Geräte -Comment[el]=Προβολή πληροφοριών σχετικά με τις συσκευές σας Comment[en_GB]=Display information about your devices Comment[es]=Mostrar información sobre sus dispositivos Comment[et]=Teabe kuvamine seadmete kohta Comment[eu]=Bistaratu zure gailuei buruzko informazioa Comment[fi]=Näyttää tietoa laitteistasi Comment[fr]=Afficher les informations de vos périphériques Comment[gl]=Mostrar información sobre os dispositivos -Comment[he]=הצג מידע עך ההתקנים שלך Comment[hu]=Információk megjelenítése az eszközeiről Comment[it]=Visualizza informazioni sui tuoi dispositivi Comment[ko]=장치 정보 표시 Comment[nl]=Toon informatie over uw apparaten Comment[nn]=Vis informasjon om einingane dine Comment[pl]=Wyświetl informacje o twoich urządzeniach Comment[pt]=Mostrar informações sobre os seus dispositivos Comment[pt_BR]=Mostra informações sobre seus dispositivos Comment[ru]=Просмотр информации о мобильных устройствах Comment[sk]=Zobraziť informácie o vašich zariadeniach Comment[sr]=Приказује податке о вашем телефону Comment[sr@ijekavian]=Приказује податке о вашем телефону Comment[sr@ijekavianlatin]=Prikazuje podatke o vašem telefonu Comment[sr@latin]=Prikazuje podatke o vašem telefonu Comment[sv]=Visa information om enheter Comment[tr]=Aygıtlarınız hakkında bilgi görüntüleyin Comment[uk]=Показати дані щодо ваших пристроїв Comment[x-test]=xxDisplay information about your devicesxx Comment[zh_CN]=显示您设备的信息 Comment[zh_TW]=顯示關於您的裝置資訊 Exec=kdeconnect-indicator Icon=kdeconnect Type=Application Terminal=false Categories=Qt;KDE;Network; NotShowIn=KDE; diff --git a/kcm/kcm.cpp b/kcm/kcm.cpp index 2da1c982..421afacd 100644 --- a/kcm/kcm.cpp +++ b/kcm/kcm.cpp @@ -1,373 +1,373 @@ /** * 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 "kcm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_kcm.h" #include "interfaces/dbusinterfaces.h" #include "interfaces/devicesmodel.h" #include "devicessortproxymodel.h" #include "kdeconnect-version.h" K_PLUGIN_FACTORY(KdeConnectKcmFactory, registerPlugin();) static QString createId() { return QStringLiteral("kcm")+QString::number(QCoreApplication::applicationPid()); } KdeConnectKcm::KdeConnectKcm(QWidget* parent, const QVariantList&) : KCModule(KAboutData::pluginData(QStringLiteral("kdeconnect-kcm")), parent) , kcmUi(new Ui::KdeConnectKcmUi()) , daemon(new DaemonDbusInterface(this)) , devicesModel(new DevicesModel(this)) , currentDevice(nullptr) { KAboutData* about = new KAboutData(QStringLiteral("kdeconnect-kcm"), i18n("KDE Connect Settings"), QStringLiteral(KDECONNECT_VERSION_STRING), i18n("KDE Connect Settings module"), KAboutLicense::KAboutLicense::GPL_V2, i18n("(C) 2015 Albert Vaca Cintora"), QString(), QStringLiteral("https://community.kde.org/KDEConnect") ); about->addAuthor(i18n("Albert Vaca Cintora")); setAboutData(about); kcmUi->setupUi(this); sortProxyModel = new DevicesSortProxyModel(devicesModel); kcmUi->deviceList->setModel(sortProxyModel); kcmUi->deviceInfo->setVisible(false); kcmUi->progressBar->setVisible(false); kcmUi->messages->setVisible(false); //Workaround: If we set this directly (or if we set it in the .ui file), the layout breaks kcmUi->noDeviceLinks->setWordWrap(false); QTimer::singleShot(0, [this] { kcmUi->noDeviceLinks->setWordWrap(true); }); setWhenAvailable(daemon->announcedName(), [this](const QString& announcedName) { kcmUi->rename_label->setText(announcedName); kcmUi->rename_edit->setText(announcedName); }, this); connect(daemon, SIGNAL(announcedNameChanged(QString)), kcmUi->rename_edit, SLOT(setText(QString))); connect(daemon, SIGNAL(announcedNameChanged(QString)), kcmUi->rename_label, SLOT(setText(QString))); setRenameMode(false); setButtons(KCModule::Help | KCModule::NoAdditionalButton); connect(devicesModel, &QAbstractItemModel::dataChanged, this, &KdeConnectKcm::resetSelection); connect(kcmUi->deviceList->selectionModel(), &QItemSelectionModel::currentChanged, this, &KdeConnectKcm::deviceSelected); connect(kcmUi->accept_button, &QAbstractButton::clicked, this, &KdeConnectKcm::acceptPairing); connect(kcmUi->reject_button, &QAbstractButton::clicked, this, &KdeConnectKcm::rejectPairing); connect(kcmUi->pair_button, &QAbstractButton::clicked, this, &KdeConnectKcm::requestPair); connect(kcmUi->unpair_button, &QAbstractButton::clicked, this, &KdeConnectKcm::unpair); connect(kcmUi->ping_button, &QAbstractButton::clicked, this, &KdeConnectKcm::sendPing); connect(kcmUi->refresh_button,&QAbstractButton::clicked, this, &KdeConnectKcm::refresh); connect(kcmUi->rename_edit,&QLineEdit::returnPressed, this, &KdeConnectKcm::renameDone); connect(kcmUi->renameDone_button,&QAbstractButton::clicked, this, &KdeConnectKcm::renameDone); connect(kcmUi->renameShow_button,&QAbstractButton::clicked, this, &KdeConnectKcm::renameShow); daemon->acquireDiscoveryMode(createId()); } void KdeConnectKcm::renameShow() { setRenameMode(true); } void KdeConnectKcm::renameDone() { QString newName = kcmUi->rename_edit->text(); if (newName.isEmpty()) { //Rollback changes kcmUi->rename_edit->setText(kcmUi->rename_label->text()); } else { kcmUi->rename_label->setText(newName); daemon->setAnnouncedName(newName); } setRenameMode(false); } void KdeConnectKcm::setRenameMode(bool b) { kcmUi->renameDone_button->setVisible(b); kcmUi->rename_edit->setVisible(b); kcmUi->renameShow_button->setVisible(!b); kcmUi->rename_label->setVisible(!b); } KdeConnectKcm::~KdeConnectKcm() { daemon->releaseDiscoveryMode(createId()); delete kcmUi; } void KdeConnectKcm::refresh() { daemon->acquireDiscoveryMode(createId()); daemon->forceOnNetworkChange(); } void KdeConnectKcm::resetSelection() { if (!currentDevice) { return; } kcmUi->deviceList->selectionModel()->setCurrentIndex(sortProxyModel->mapFromSource(currentIndex), QItemSelectionModel::ClearAndSelect); } void KdeConnectKcm::deviceSelected(const QModelIndex& current) { if (currentDevice) { disconnect(currentDevice, 0, this, 0); } //Store previous device config pluginsConfigChanged(); if (!current.isValid()) { currentDevice = nullptr; kcmUi->deviceInfo->setVisible(false); return; } currentIndex = sortProxyModel->mapToSource(current); currentDevice = devicesModel->getDevice(currentIndex.row()); kcmUi->noDevicePlaceholder->setVisible(false); bool valid = (currentDevice != nullptr && currentDevice->isValid()); kcmUi->deviceInfo->setVisible(valid); if (!valid) { return; } kcmUi->messages->setVisible(false); resetDeviceView(); connect(currentDevice, SIGNAL(pluginsChanged()), this, SLOT(resetCurrentDevice())); connect(currentDevice, SIGNAL(trustedChanged(bool)), this, SLOT(trustedChanged(bool))); connect(currentDevice, SIGNAL(pairingError(QString)), this, SLOT(pairingFailed(QString))); connect(currentDevice, &DeviceDbusInterface::hasPairingRequestsChangedProxy, this, &KdeConnectKcm::currentDevicePairingChanged); } void KdeConnectKcm::currentDevicePairingChanged(bool pairing) { if (pairing) { setCurrentDeviceTrusted(RequestedByPeer); } else { setWhenAvailable(currentDevice->isTrusted(), [this](bool trusted) { setCurrentDeviceTrusted(trusted ? Trusted : NotTrusted); }, this); } } void KdeConnectKcm::resetCurrentDevice() { const QStringList supportedPluginNames = currentDevice->supportedPlugins(); if (m_oldSupportedPluginNames != supportedPluginNames) { resetDeviceView(); } } void KdeConnectKcm::resetDeviceView() { //KPluginSelector has no way to remove a list of plugins and load another, so we need to destroy and recreate it each time delete kcmUi->pluginSelector; kcmUi->pluginSelector = new KPluginSelector(this); kcmUi->deviceInfo_layout->addWidget(kcmUi->pluginSelector); kcmUi->pluginSelector->setConfigurationArguments(QStringList(currentDevice->id())); kcmUi->name_label->setText(currentDevice->name()); setWhenAvailable(currentDevice->isTrusted(), [this](bool trusted) { if (trusted) setCurrentDeviceTrusted(Trusted); else setWhenAvailable(currentDevice->hasPairingRequests(), [this](bool haspr) { setCurrentDeviceTrusted(haspr ? RequestedByPeer : NotTrusted); }, this); }, this); const QList pluginInfo = KPluginInfo::fromMetaData(KPluginLoader::findPlugins(QStringLiteral("kdeconnect/"))); QList availablePluginInfo; m_oldSupportedPluginNames = currentDevice->supportedPlugins(); for (auto it = pluginInfo.cbegin(), itEnd = pluginInfo.cend(); it!=itEnd; ++it) { if (m_oldSupportedPluginNames.contains(it->pluginName())) { availablePluginInfo.append(*it); } } KSharedConfigPtr deviceConfig = KSharedConfig::openConfig(currentDevice->pluginsConfigFile()); kcmUi->pluginSelector->addPlugins(availablePluginInfo, KPluginSelector::ReadConfigFile, i18n("Available plugins"), QString(), deviceConfig); connect(kcmUi->pluginSelector, &KPluginSelector::changed, this, &KdeConnectKcm::pluginsConfigChanged); } void KdeConnectKcm::requestPair() { if (!currentDevice) { return; } kcmUi->messages->hide(); setCurrentDeviceTrusted(Requested); currentDevice->requestPair(); } void KdeConnectKcm::unpair() { if (!currentDevice) { return; } setCurrentDeviceTrusted(NotTrusted); currentDevice->unpair(); } void KdeConnectKcm::acceptPairing() { if (!currentDevice) { return; } currentDevice->acceptPairing(); } void KdeConnectKcm::rejectPairing() { if (!currentDevice) { return; } currentDevice->rejectPairing(); } void KdeConnectKcm::pairingFailed(const QString& error) { if (sender() != currentDevice) return; setCurrentDeviceTrusted(NotTrusted); kcmUi->messages->setText(i18n("Error trying to pair: %1",error)); kcmUi->messages->animatedShow(); } void KdeConnectKcm::trustedChanged(bool trusted) { DeviceDbusInterface* senderDevice = (DeviceDbusInterface*) sender(); if (senderDevice == currentDevice) setCurrentDeviceTrusted(trusted ? Trusted : NotTrusted); } void KdeConnectKcm::setCurrentDeviceTrusted(KdeConnectKcm::TrustStatus trusted) { kcmUi->accept_button->setVisible(trusted == RequestedByPeer); kcmUi->reject_button->setVisible(trusted == RequestedByPeer); kcmUi->pair_button->setVisible(trusted == NotTrusted); kcmUi->unpair_button->setVisible(trusted == Trusted); kcmUi->progressBar->setVisible(trusted == Requested); kcmUi->ping_button->setVisible(trusted == Trusted); switch (trusted) { case Trusted: kcmUi->status_label->setText(i18n("(paired)")); break; case NotTrusted: kcmUi->status_label->setText(i18n("(not paired)")); break; - case Requested: + case RequestedByPeer: kcmUi->status_label->setText(i18n("(incoming pair request)")); break; - case RequestedByPeer: + case Requested: kcmUi->status_label->setText(i18n("(pairing requested)")); break; } } void KdeConnectKcm::pluginsConfigChanged() { //Store previous selection if (!currentDevice) return; DeviceDbusInterface* auxCurrentDevice = currentDevice; currentDevice = nullptr; //HACK to avoid infinite recursion (for some reason calling save on pluginselector emits changed) kcmUi->pluginSelector->save(); currentDevice = auxCurrentDevice; currentDevice->reloadPlugins(); } void KdeConnectKcm::save() { pluginsConfigChanged(); KCModule::save(); } void KdeConnectKcm::sendPing() { if (!currentDevice) return; currentDevice->pluginCall(QStringLiteral("ping"), QStringLiteral("sendPing")); } QSize KdeConnectKcm::sizeHint() const { return QSize(890,550); //Golden ratio :D } QSize KdeConnectKcm::minimumSizeHint() const { return QSize(500,300); } #include "kcm.moc" #include "moc_kcm.cpp" diff --git a/kcm/kcm_kdeconnect.desktop b/kcm/kcm_kdeconnect.desktop index 4c69a543..6593d3f3 100755 --- a/kcm/kcm_kdeconnect.desktop +++ b/kcm/kcm_kdeconnect.desktop @@ -1,134 +1,122 @@ [Desktop Entry] Exec=kcmshell5 kcm_kdeconnect Icon=kdeconnect Type=Service X-KDE-ServiceTypes=KCModule X-KDE-Library=kcm_kdeconnect X-KDE-ParentApp=kcontrol X-KDE-System-Settings-Parent-Category=hardware Name=KDE Connect -Name[ar]=كدي المتّصل -Name[ast]=KDE Connect Name[bg]=KDE Connect Name[bs]=Konekcija KDE Name[ca]=KDE Connect Name[ca@valencia]=KDE Connect Name[cs]=KDE Connect Name[da]=KDE Connect Name[de]=KDE-Connect -Name[el]=KDE Connect Name[en_GB]=KDE Connect Name[es]=KDE Connect Name[et]=KDE Connect Name[eu]=KDE Connect Name[fi]=KDE Connect Name[fr]=KDE Connect Name[gl]=KDE Connect -Name[he]=KDE Connect Name[hu]=KDE csatlakozás Name[it]=KDE Connect Name[ko]=KDE Connect Name[nl]=KDE Connect Name[nn]=KDE Connect Name[pl]=KDE Connect Name[pt]=KDE Connect Name[pt_BR]=KDE Connect Name[ro]=KDE Connect Name[ru]=KDE Connect Name[sk]=KDE Connect Name[sr]=КДЕ‑конекција Name[sr@ijekavian]=КДЕ‑конекција Name[sr@ijekavianlatin]=KDE‑konekcija Name[sr@latin]=KDE‑konekcija Name[sv]=KDE-anslut Name[tr]=KDE Connect Name[uk]=З’єднання KDE Name[x-test]=xxKDE Connectxx Name[zh_CN]=KDE Connect Name[zh_TW]=KDE 連線 Comment=Connect and sync your devices -Comment[ar]=اتّصل وزامن أجهزتك -Comment[ast]=Coneuta y sincroniza los tos preseos Comment[ca]=Connecta i sincronitza els vostres dispositius Comment[ca@valencia]=Connecta i sincronitza els vostres dispositius Comment[cs]=Připojte a synchronizujte svá zařízení Comment[da]=Forbind og synkronisér dine enheder Comment[de]=Verbinden und Abgleichen Ihrer Geräte -Comment[el]=Σύνδεση και συγχρονισμός των συσκευών σας Comment[en_GB]=Connect and sync your devices Comment[es]=Conecte y sincronice sus dispositivos Comment[et]=Oma seadmete ühendamine ja sünkroonimine Comment[eu]=Konektatu eta sinkronizatu zure gailuak Comment[fi]=Yhdistä ja synkronoi laitteitasi Comment[fr]=Connectez et synchronisez vos périphériques Comment[gl]=Conecte e sincronice os seus dispositivos. -Comment[he]=חבר וסנכרן את ההתקנים שלך Comment[hu]=Csatlakoztassa és szinkronizálja eszközeit Comment[it]=Connetti e sincronizza i tuoi dispositivi Comment[ko]=내 장치에 연결하고 동기화 Comment[nl]=Uw apparaten verbinden en synchroniseren Comment[nn]=Kopla til og synkroniser einingar Comment[pl]=Podłącz i zsynchronizuj swoje urządzenia Comment[pt]=Ligue e sincronize os seus dispositivos Comment[pt_BR]=Conecta e sincroniza seus dispositivos Comment[ru]=Подключение и синхронизация с мобильными устройствами Comment[sk]=Pripojiť a synchronizovať vaše zariadenia Comment[sr]=Повежите и синхронизујте своје уређаје Comment[sr@ijekavian]=Повежите и синхронизујте своје уређаје Comment[sr@ijekavianlatin]=Povežite i sinhronizujte svoje uređaje Comment[sr@latin]=Povežite i sinhronizujte svoje uređaje Comment[sv]=Anslut och synkronisera dina apparater Comment[tr]=Aygıtlarınıza bağlanın ve eşitleyin Comment[uk]=З’єднання і синхронізація ваших пристроїв Comment[x-test]=xxConnect and sync your devicesxx Comment[zh_CN]=连接并同步您的设备 Comment[zh_TW]=連線並且同步您的裝置 X-KDE-Keywords=Network,Android,Devices -X-KDE-Keywords[ar]=شبكة,أندرويد,اندرويد,جهاز,أجهزة -X-KDE-Keywords[ast]=Rede,Android,Preseos X-KDE-Keywords[bg]=Мрежа,Андроид,Устройства X-KDE-Keywords[bs]=Mreža,Android,Uređaji X-KDE-Keywords[ca]=Xarxa,Android,Dispositius X-KDE-Keywords[ca@valencia]=Xarxa,Android,Dispositius X-KDE-Keywords[cs]=Síť,Android,Zařízení X-KDE-Keywords[da]=Netværk,Android,Enheder X-KDE-Keywords[de]=Netzwerk,Android,Geräte -X-KDE-Keywords[el]=Δίκτυο,Android,Συσκευές X-KDE-Keywords[en_GB]=Network,Android,Devices X-KDE-Keywords[es]=Red,Android,Dispositivos X-KDE-Keywords[et]=Võrk,Android,Seadmed X-KDE-Keywords[eu]=Sarea,Android,Gailuak X-KDE-Keywords[fi]=Verkko,Android,Laitteet X-KDE-Keywords[fr]=Réseau,Android,Périphériques X-KDE-Keywords[gl]=rede,Android,dispositivos -X-KDE-Keywords[he]=Network,Android,Devices,רשתות,אנדרואיד,התקנים,מכשירים X-KDE-Keywords[hu]=Hálózat,Android,Eszközök X-KDE-Keywords[it]=Rete,Android,Dispositivi X-KDE-Keywords[ko]=Network,Android,Devices,네트워크,안드로이드,장치 X-KDE-Keywords[nl]=Netwerk,Android,Apparaten X-KDE-Keywords[nn]=nettverk,Android,einingar X-KDE-Keywords[pl]=Sieć,Android,Urządzenia X-KDE-Keywords[pt]=Rede,Android,Dispositivos X-KDE-Keywords[pt_BR]=Rede,Android,Dispositivos X-KDE-Keywords[ru]=Network,Android,Devices,сеть,Андроид,устройства,мобильные устройства X-KDE-Keywords[sk]=Sieť,Android,Zariadenia X-KDE-Keywords[sr]=Network,Android,Devices,мрежа,Андроид,уређаји X-KDE-Keywords[sr@ijekavian]=Network,Android,Devices,мрежа,Андроид,уређаји X-KDE-Keywords[sr@ijekavianlatin]=Network,Android,Devices,mreža,Android,uređaji X-KDE-Keywords[sr@latin]=Network,Android,Devices,mreža,Android,uređaji X-KDE-Keywords[sv]=Nätverk, Android, apparater X-KDE-Keywords[tr]=Ağ,Android,Cihazlar,Aygıtlar X-KDE-Keywords[uk]=Network,Android,Devices,мережа,андроїд,пристрої X-KDE-Keywords[x-test]=xxNetworkxx,xxAndroidxx,xxDevicesxx X-KDE-Keywords[zh_CN]=Network,Android,Devices,网络,安卓,设备 X-KDE-Keywords[zh_TW]=網路,Android裝置,設備 X-DocPath=kdeconnect/index.html Categories=Qt;KDE;X-KDE-settings-kdeconnect; diff --git a/kcm/org.kde.kdeconnect.kcm.desktop b/kcm/org.kde.kdeconnect.kcm.desktop index 8e33f44d..a0adc49c 100755 --- a/kcm/org.kde.kdeconnect.kcm.desktop +++ b/kcm/org.kde.kdeconnect.kcm.desktop @@ -1,81 +1,73 @@ [Desktop Entry] Type=Application Icon=kdeconnect Terminal=false Exec=kcmshell5 kcm_kdeconnect Name=KDE Connect Settings -Name[ar]=إعدادات كدي المتّصل -Name[ast]=Axustes de KDE Connect Name[ca]=Arranjament del KDE Connect Name[ca@valencia]=Arranjament del KDE Connect Name[cs]=Nastavení KDE Connect Name[da]=Indstilling af KDE Connect Name[de]=KDE-Connect-Einstellungen -Name[el]=Ρυθμίσεις KDE Connect Name[en_GB]=KDE Connect Settings Name[es]=Ajustes de KDE Connect Name[et]=KDE Connecti seadistused Name[eu]=KDE Connect ezarpenak Name[fi]=KDE Connectin asetukset Name[fr]=Paramètres de KDE Connect Name[gl]=Configuración de KDE Connect -Name[he]=הגדרות KDE Connect Name[hu]=A KDE Connect beállításai Name[it]=Impostazioni di KDE Connect Name[ko]=KDE Connect 설정 Name[nl]=Instellingen van KDE Connect Name[nn]=Innstillingar for KDE Connect Name[pl]=Ustawienia KDE Connect Name[pt]=Configuração do KDE Connect Name[pt_BR]=Configurações do KDE Connect Name[ru]=Настройка KDE Connect Name[sk]=Nastavenia KDE Connect Name[sr]=Поставке за КДЕ‑конекцију Name[sr@ijekavian]=Поставке за КДЕ‑конекцију Name[sr@ijekavianlatin]=Postavke za KDE‑konekciju Name[sr@latin]=Postavke za KDE‑konekciju Name[sv]=Inställning av KDE-anslut Name[tr]=KDE Connect Ayarları Name[uk]=Параметри KDE Connect Name[x-test]=xxKDE Connect Settingsxx Name[zh_CN]=KDE Connect 设置 Name[zh_TW]=KDE 連線設定 GenericName=Connect and sync your devices -GenericName[ar]=اتّصل وزامن أجهزتك -GenericName[ast]=Coneuta y sincroniza los tos preseos GenericName[ca]=Connecta i sincronitza els vostres dispositius GenericName[ca@valencia]=Connecta i sincronitza els vostres dispositius GenericName[cs]=Připojte a synchronizujte svá zařízení GenericName[da]=Forbind og synkronisér dine enheder GenericName[de]=Verbinden und Abgleichen Ihrer Geräte -GenericName[el]=Σύνδεση και συγχρονισμός των συσκευών σας GenericName[en_GB]=Connect and sync your devices GenericName[es]=Conecte y sincronice sus dispositivos GenericName[et]=Oma seadmete ühendamine ja sünkroonimine GenericName[eu]=Konektatu eta sinkronizatu zure gailuak GenericName[fi]=Yhdistä ja synkronoi laitteitasi GenericName[fr]=Connectez et synchronisez vos périphériques GenericName[gl]=Conecte e sincronice os seus dispositivos -GenericName[he]=Connect and sync your devices GenericName[hu]=Csatlakoztassa és szinkronizálja eszközeit GenericName[it]=Connetti e sincronizza i tuoi dispositivi GenericName[ko]=내 장치에 연결하고 동기화 GenericName[nl]=Uw apparaten verbinden en synchroniseren GenericName[nn]=Kopla til og synkroniser einingar GenericName[pl]=Podłącz i zsynchronizuj swoje urządzenia GenericName[pt]=Ligue e sincronize os seus dispositivos GenericName[pt_BR]=Conecta e sincroniza seus dispositivos GenericName[ru]=Подключение и синхронизация с мобильными устройствами GenericName[sk]=Pripojiť a synchronizovať vaše zariadenia GenericName[sr]=Повежите и синхронизујте своје уређаје GenericName[sr@ijekavian]=Повежите и синхронизујте своје уређаје GenericName[sr@ijekavianlatin]=Povežite i sinhronizujte svoje uređaje GenericName[sr@latin]=Povežite i sinhronizujte svoje uređaje GenericName[sv]=Anslut och synkronisera dina apparater GenericName[tr]=Aygıtlarınıza bağlanın ve eşitleyin GenericName[uk]=З’єднання і синхронізація ваших пристроїв GenericName[x-test]=xxConnect and sync your devicesxx GenericName[zh_CN]=连接并同步您的设备 GenericName[zh_TW]=連線並且同步您的裝置 Categories=Qt;KDE;Settings;HardwareSettings; NotShowIn=KDE; diff --git a/org.kde.kdeconnect.kcm.appdata.xml b/org.kde.kdeconnect.kcm.appdata.xml index 1826414a..ca11723a 100644 --- a/org.kde.kdeconnect.kcm.appdata.xml +++ b/org.kde.kdeconnect.kcm.appdata.xml @@ -1,124 +1,111 @@ org.kde.kdeconnect.kcm.desktop CC0-1.0 GPL-2.0+ KDE Connect - كدي المتّصل - KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect KDE-Connect - KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect - KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect KDE Connect КДЕ‑конекција KDE‑konekcija КДЕ‑конекција KDE‑konekcija KDE-anslut - KDE Connect KDE Connect xxKDE Connectxx KDE Connect KDE Connect Seamless connection of your devices - اتّصال سلس بين أجهزتك - Conexón ensin torgues de los tos preseos Connexió transparent amb els vostres dispositius Connexió transparent amb els vostres dispositius Snadné propojení vašich zařízení - Umærkbar forbindelse mellem dine enheder + Supernem forbindelse mellem dine enheder Nahtlose Verbindung zu Ihren Geräten - Απρόσκοπτη σύνδεση των συσκευών σας Seamless connection of your devices Conexión sin interrupciones de sus dispositivos Sujuv ühendus oma seadmetega Zure gailuen etengabeko konexioa Saumaton yhteys laitteisiisi Connecter vos périphériques avec facilité Conexión constante entre dispositivos - חיבור מהיר בין ההתקנים שלך Connessione trasparente dei tuoi dispositivi 장치와 항상 연결하기 Naadloze verbinding met uw apparaten Sømlaus integrering med andre einingar Zintegrowane połączenia do twoich urządzeń Ligação transparente aos seus dispositivos Conexão transparente com seus dispositivos Интеграция с мобильными устройствами Jednoduché prepojenie vašich zariadení Једноставно повезивање ваших уређаја Jednostavno povezivanje vaših uređaja Једноставно повезивање ваших уређаја Jednostavno povezivanje vaših uređaja Sömlös anslutning av dina apparater - Aygıtlarınızı sorunsuz bağlayın Безшовне з’єднання для усіх ваших пристроїв xxSeamless connection of your devicesxx 无缝连接您的设备 與您的裝置無縫連線

KDE Connect provides several features to integrate your phone and your computer: Please note you will need to install KDE Connect on your computer for this app to work, and keep the desktop version up-to-date with the Android version for the latest features to work.

El KDE Connect proporciona diverses característiques per integrar el telèfon amb l'ordinador: Recordeu que haureu d'instal·lar el KDE Connect a l'ordinador per a que aquesta aplicació funcioni, i mantenir actualitzada la versió de l'escriptori amb la versió d'Android per a que funcionin les últimes característiques.

El KDE Connect proporciona diverses característiques per integrar el telèfon amb l'ordinador: Recordeu que haureu d'instal·lar el KDE Connect a l'ordinador per a que esta aplicació funcione, i mantindre actualitzada la versió de l'escriptori amb la versió d'Android per a que funcionen les últimes característiques.

KDE Connect poskytuje několik vlastností pro vzájemnou integraci vašeho telefonu a počítače: Prosím pamatujte, že pro správnou funkci této aplikace potřebujete nainstalovat KDE Connect na váš počítač a pro správnou funkci nejnovějších vlastností udržovat aplikaci na telefonu i počítači aktuální.

-

KDE Connect tilbyder adskillige funktioner, der integrerer din telefon og din computer: Bemærk at du vil skulle installere KDE Connect på din computer for at denne app virker, samt holde desktop-versionen opdateret sammen med Android-versionen, for at de nyeste funktioner vil virke.

-

KDE Connect provides several features to integrate your phone and your computer: Please note you will need to install KDE Connect on your computer for this app to work, and keep the desktop version up-to-date with the Android version for the latest features to work.

+

KDE Connect tilbyder adskillige funktioner, der integrerer din telefon og din computer: Bemærk at du vil skulle installere KDE Connect på din computer for at denne app virker, samt holde desktop-versionen opdateret sammen med Android-versionen, for at de nyeste funktioner vil virke.

KDE Connect proporciona varias funcionalidades para integrar su teléfono y su equipo: Por favor, tenga en cuenta que deberá instalar KDE Connect en su equipo para que esta aplicación funcione. Además, deberá mantener la versión de escritorio actualizada con su versión de Android para beneficiarse de las últimas funcionalidades.

KDE Connect-ek eginbide ugari ditu zure telefonoa eta ordenagailua integratzeko: KDE Connect instalatu beharko duzu zure ordenagailuan aplikazioa hau ibili dadin, eta mahaigaineko bertsioa Androiden bertsioarekin eguneratuta izan beharko duzu eginbide berrienak ibili daitezen.

KDE Connect fournit un ensemble de fonctionnalités pour intégrer votre téléphone et votre ordinateur : veuillez noter qu'il est nécessaire d'installer KDE Connect sur votre ordinateur pour faire fonctionner cette application, ainsi que de maintenir le logiciel à jour pour profiter des dernières fonctionnalités.

-

KDE Connect fornece varias funcionalidades para integrar teléfonos con computadores. Teña en conta que terá que instalar KDE Connect no seu computador para que este aplicativo funcione, e manter a versión de escritorio sincronizada coa de Android para que as últimas funcionalidades funcionen.

KDE Connect fornisce diverse funzioni per integrare il tuo telefono e il tuo computer: affinché questa applicazione funzioni, dovrai installare KDE Connect sul tuo computer e mantenere la versione desktop aggiornata alla versione Android, in modo che le funzioni più recenti siano attive.

KDE Connect biedt verschillende functies om uw telefoon en uw computer: merk op dat het nodig is om KDE Connect op uw computer te installeren om deze app te laten werken en de bureabladversie up-to-date te houden met de Android-versie om de laatste functies te laten werken.

KDE Connect har fleire funksjonar for integrering av telefonen og datamaskina di. Merk at du må installera KDE Connect på datamaskina for at denne appen skal fungera. Viss du vil bruka dei nyaste funksjonane, må du òg hugsa på å halda datamaskinversjonen oppdatert når du oppdaterer appen.

KDE Connect zapewnia kilka możliwości integracji twojego telefonu z twoim komputerem: Musisz mieć wgrane KDE Connect na swoim komputerze, aby ta aplikacja zadziałała, a także aktualną wersję zgodną z wersją Androida, aby wszystkie najnowsze funkcje działały.

O KDE Connect oferece diversas funcionalidades para integrar o seu telefone com o seu computador: Lembre-se por favor que terá de instalar o KDE Connect com o seu computador para esta aplicação funcionar e deverá manter a versão no ambiente de trabalho actualizada com a versão para Android, para que as últimas funcionalidades funcionem.

-

KDE Connect предоставляет несколько функций для интеграции телефона и компьютера. Обратите внимание, что для работы этого приложения необходимо установить KDE Connect на свой компьютер и, для работы новейших функций, держать версию обновлённой в соответствии с версией для Android.

+

KDE Connect poskytuje niekoľko funkcií na integráciu vášho mobilu s vašim počítačom: Pamätajte, že budete potrebovať nainštalovať KDE Connect na váš počítač, aby tento program fungoval a udržiavať verziu desktopu aktuálnu s verziou Androidu, aby fungovali najnovšie funkcie.

КДЕ‑конекција поседује вишеструке могућности интеграције вашег телефона и рачунара. Морате да инсталирате КДЕ‑конекцију на ваш рачунар да би ова апликација радила. Такође, нека вам обе апликације буду ажурне како бисте уживали у најновијим могућностима.

KDE‑konekcija poseduje višestruke mogućnosti integracije vašeg telefona i računara. Morate da instalirate KDE‑konekciju na vaš računar da bi ova aplikacija radila. Takođe, neka vam obe aplikacije budu ažurne kako biste uživali u najnovijim mogućnostima.

КДЕ‑конекција поседује вишеструке могућности интеграције вашег телефона и рачунара. Морате да инсталирате КДЕ‑конекцију на ваш рачунар да би ова апликација радила. Такође, нека вам обе апликације буду ажурне како бисте уживали у најновијим могућностима.

KDE‑konekcija poseduje višestruke mogućnosti integracije vašeg telefona i računara. Morate da instalirate KDE‑konekciju na vaš računar da bi ova aplikacija radila. Takođe, neka vam obe aplikacije budu ažurne kako biste uživali u najnovijim mogućnostima.

KDE-anslut tillhandahåller flera funktioner för att integrera telefon och dator. Observera att KDE-anslut måste installeras på datorn för att appen ska fungera, och att skrivbordsdatorns version måste hållas uppdaterad tillsammans med Androidversionen för att de senaste funktionerna ska fungera.

-

KDE Connect, telefonunuzu ve bilgisayarınızı bütünleştirmek için çeşitli özellikler sunar: Bu uygulamanın çalışabilmesi için bilgisayarınıza KDE Connect'i yüklemeniz ve en son özelliklerin çalışabilmesi için masaüstü sürümünün Android sürümü ile güncel tutulması gereklidir.

У KDE Connect передбачено декілька можливостей для інтеграції вашого телефону з вашим комп’ютером. Будь ласка, зауважте, що вам доведеться встановити KDE Connect на ваш комп’ютер, щоб скористатися цією програмою, а також підтримувати актуальність версії на комп’ютері та версії для Android, щоб мати змогу скористатися найсвіжішими можливостями.

xxKDE Connect provides several features to integrate your phone and your computer: Please note you will need to install KDE Connect on your computer for this app to work, and keep the desktop version up-to-date with the Android version for the latest features to work.xx

https://community.kde.org/KDEConnect/ https://bugs.kde.org/enter_bug.cgi?format=guided&product=kdeconnect https://docs.kde.org/index.php?application=kdeconnect-kde&language=en https://cdn.kde.org/screenshots/kdeconnect/plasmoid.png https://cdn.kde.org/screenshots/kdeconnect/kcm.png https://cdn.kde.org/screenshots/kdeconnect/gnome3.png KDE kdeconnectd kdeconnect-cli
diff --git a/plasmoid/package/metadata.desktop b/plasmoid/package/metadata.desktop index be02f27a..05b6d08a 100644 --- a/plasmoid/package/metadata.desktop +++ b/plasmoid/package/metadata.desktop @@ -1,99 +1,91 @@ [Desktop Entry] Name=KDE Connect -Name[ar]=كدي المتّصل -Name[ast]=KDE Connect Name[bg]=KDE Connect Name[bs]=Konekcija KDE Name[ca]=KDE Connect Name[ca@valencia]=KDE Connect Name[cs]=KDE Connect Name[da]=KDE Connect Name[de]=KDE-Connect -Name[el]=KDE Connect Name[en_GB]=KDE Connect Name[es]=KDE Connect Name[et]=KDE Connect Name[eu]=KDE Connect Name[fi]=KDE Connect Name[fr]=KDE Connect Name[gl]=KDE Connect -Name[he]=KDE Connect Name[hu]=KDE csatlakozás Name[it]=KDE Connect Name[ko]=KDE Connect Name[nl]=KDE Connect Name[nn]=KDE Connect Name[pl]=KDE Connect Name[pt]=KDE Connect Name[pt_BR]=KDE Connect Name[ro]=KDE Connect Name[ru]=KDE Connect Name[sk]=KDE Connect Name[sr]=КДЕ‑конекција Name[sr@ijekavian]=КДЕ‑конекција Name[sr@ijekavianlatin]=KDE‑konekcija Name[sr@latin]=KDE‑konekcija Name[sv]=KDE-anslut Name[tr]=KDE Connect Name[uk]=З’єднання KDE Name[x-test]=xxKDE Connectxx Name[zh_CN]=KDE Connect Name[zh_TW]=KDE 連線 Comment=Show notifications from your devices using KDE Connect -Comment[ar]=أظهر الإخطارات من أجهزتك باستخدام «كدي المتّصل» -Comment[ast]=Amuesa avisos de los tos preseos qu'usen KDE Connect Comment[bg]=Показване на уведомления от вашите устройства чрез KDE Connect Comment[bs]=Prikaži obavlještenja sa uređaja koji koriste KDE konekciju Comment[ca]=Mostra les notificacions dels vostres dispositius emprant el KDE Connect Comment[ca@valencia]=Mostra les notificacions dels vostres dispositius emprant el KDE Connect Comment[cs]=Zobrazit upozornění z vašich zařízení pomocí KDE Connect Comment[da]=Vis bekendtgørelser fra dine enheder med KDE Connect Comment[de]=Zeigt Benachrichtigungen von Ihren Geräten mit KDE-Connect -Comment[el]=Προβολή ειδοποιήσεων από τις συσκευές σας με το KDE Connect Comment[en_GB]=Show notifications from your devices using KDE Connect Comment[es]=Mostrar notificaciones de sus dispositivos usando KDE Connect Comment[et]=Seadmete märguannete näitamine KDE Connecti vahendusel Comment[eu]=Ikusi zure gailuetako jakinarazpenak KDE Connect erabiliz Comment[fi]=Näytä laitteidesi ilmoitukset KDE Connectilla Comment[fr]=Afficher les notifications provenant de vos périphériques à l'aide de KDE Connect Comment[gl]=Mostrar notificacións de dispositivos usando KDE Connect. -Comment[he]=הראה התראות מההתקן שלך באמצעות KDE Connect Comment[hu]=Az eszközökről származó értesítések megjelenítése a KDE csatlakozás használatával Comment[it]=Mostra le notifiche dei tuoi dispositivi tramite KDE Connect Comment[ko]=KDE Connect로 장치에 표시된 알림 보기 Comment[nl]=Meldingen van uw apparaten met KDE Connect tonen Comment[nn]=Vis varslingar frå einingane dine med KDE Connect Comment[pl]=Pokazuje powiadomienia z urządzeń z KDE Connect Comment[pt]=Mostrar notificações dos seus dispositivos usando o KDE Connect Comment[pt_BR]=Mostrar notificações dos seus dispositivos usando o KDE Connect Comment[ru]=Просмотр уведомлений с мобильных устройств с помощью KDE Connect Comment[sk]=Zobraziť oznámenia z vašich zariadení pomocou KDE Connect Comment[sr]=Приказује обавештења са вашег уређаја помоћу КДЕ‑конекције Comment[sr@ijekavian]=Приказује обавештења са вашег уређаја помоћу КДЕ‑конекције Comment[sr@ijekavianlatin]=Prikazuje obaveštenja sa vašeg uređaja pomoću KDE‑konekcije Comment[sr@latin]=Prikazuje obaveštenja sa vašeg uređaja pomoću KDE‑konekcije Comment[sv]=Visa underrättelser från apparater med KDE anslut Comment[tr]=KDE Connect kullanılarak cihazınızdan bildirimleri görüntüleyin Comment[uk]=Показ сповіщень з ваших пристроїв за допомогою програми «З’єднання KDE» Comment[x-test]=xxShow notifications from your devices using KDE Connectxx Comment[zh_CN]=通过 KDE Connect 显示来自您的设备的通知 Comment[zh_TW]=使用KDE 連線來顯示您的裝置通知 Icon=kdeconnect Type=Service X-KDE-ServiceTypes=Plasma/Applet X-Plasma-API=declarativeappletscript X-Plasma-MainScript=ui/main.qml X-Plasma-NotificationArea=true X-Plasma-ConfigPlugins=kcm_kdeconnect X-KDE-PluginInfo-Author=Albert Vaca Cintora X-KDE-PluginInfo-Email=albertvaka@gmail.com X-KDE-PluginInfo-Name=org.kde.kdeconnect X-KDE-PluginInfo-Version=0.1 X-KDE-PluginInfo-Website=http://albertvaka.wordpress.com X-KDE-PluginInfo-Category=System Information X-KDE-PluginInfo-Depends= X-KDE-PluginInfo-License=GPL X-KDE-PluginInfo-EnabledByDefault=true diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 2a7d63e4..785a71e0 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,32 +1,32 @@ include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}/core) add_definitions(-DTRANSLATION_DOMAIN=\"kdeconnect-plugins\") install(FILES kdeconnect_plugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR}) add_subdirectory(ping) add_subdirectory(clipboard) add_subdirectory(telephony) add_subdirectory(share) add_subdirectory(notifications) add_subdirectory(battery) -add_subdirectory(remotecommands) add_subdirectory(findmyphone) add_subdirectory(remotekeyboard) if(WIN32) add_subdirectory(mousepad_windows) else() add_subdirectory(runcommand) add_subdirectory(sendnotifications) add_subdirectory(pausemusic) add_subdirectory(mpriscontrol) add_subdirectory(mousepad) add_subdirectory(screensaver-inhibit) add_subdirectory(sftp) endif() if(EXPERIMENTALAPP_ENABLED) + add_subdirectory(remotecommands) add_subdirectory(mprisremote) add_subdirectory(remotecontrol) add_subdirectory(lockdevice) endif() #FIXME: If we split notifications in several files, they won't appear in the same group in the Notifications KCM install(FILES kdeconnect.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR}) diff --git a/plugins/battery/kdeconnect_battery.json b/plugins/battery/kdeconnect_battery.json index f8e6317d..2f7e9a25 100644 --- a/plugins/battery/kdeconnect_battery.json +++ b/plugins/battery/kdeconnect_battery.json @@ -1,100 +1,95 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "albertvaka@gmail.com", "Name": "Albert Vaca", "Name[sr@ijekavian]": "Алберт Вака Синтора", "Name[sr@ijekavianlatin]": "Albert Vaka Sintora", "Name[sr@latin]": "Albert Vaka Sintora", "Name[sr]": "Алберт Вака Синтора", "Name[x-test]": "xxAlbert Vacaxx" } ], "Description": "Show your phone battery next to your computer battery", - "Description[ar]": "أظهر بطّاريّة الهاتف بجانب بطّاريّة الحاسوب", "Description[ca@valencia]": "Mostra la bateria del telèfon al costat de la bateria de l'ordinador", "Description[ca]": "Mostra la bateria del telèfon al costat de la bateria de l'ordinador", "Description[cs]": "Zobrazit baterii vedle baterie počítače", - "Description[da]": "Vis din telefons batteri ved siden af dit computerbatteri", + "Description[da]": "Vis dit telefonbatteri ved siden af dit computerbatteri", "Description[de]": "Zeigt den Akku Ihres Telefons neben dem Akku des Rechners", - "Description[el]": "Εμφάνιση μπαταρίας συσκευής δίπλα στη μπαταρία του υπολογιστή", "Description[es]": "Mostrar la batería del teléfono junto a la batería del equipo", "Description[et]": "Telefoniaku näitamine otse arvutiaku kõrval", "Description[eu]": "Erakutsi telefonoaren bateria ordenagailuaren bateriaren ondoan", "Description[fi]": "Näytä puhelimesi akku tietokoneen akun rinnalla", "Description[fr]": "Affichez la batterie de votre téléphone à côté de la batterie de votre ordinateur", "Description[gl]": "Mostra o nivel de batería do teléfono canda o nivel de batería do computador.", "Description[hu]": "A telefon akkumulátorának megjelenítése a számítógépé mellett", "Description[it]": "Mostra la batteria del telefono accanto alla batteria del computer", "Description[ko]": "컴퓨터 배터리와 함께 휴대폰 배터리 표시", "Description[nl]": "Uw telefoonbatterij naast uw computerbatterij tonen", "Description[nn]": "Vis telefonbatteriet ved sida av datamaskinbatteriet", "Description[pl]": "Pokaż baterię swojego telefonu obok baterii komputera", "Description[pt]": "Mostrar a bateria do seu telefone ao lado da do seu computador", "Description[pt_BR]": "Mostra a bateria do seu celular ao lado da bateria do computador", "Description[ru]": "Показ уровня заряда батареи телефона рядом с индикатором батареи компьютера", "Description[sk]": "Zobraziť batériu vášho telefónu pri batérii počítača", "Description[sr@ijekavian]": "Приказ батерије телефона у системској касети", "Description[sr@ijekavianlatin]": "Prikaz baterije telefona u sistemskoj kaseti", "Description[sr@latin]": "Prikaz baterije telefona u sistemskoj kaseti", "Description[sr]": "Приказ батерије телефона у системској касети", "Description[sv]": "Visa telefonens batteri intill datorbatteriet", "Description[tr]": "Bilgisayar pilinizin yanında telefon pil durumunu göster", "Description[uk]": "Показ даних щодо рівня заряду акумулятора на телефоні поряд з даними щодо рівня заряду акумулятора комп’ютера", "Description[x-test]": "xxShow your phone battery next to your computer batteryxx", "Description[zh_CN]": "在计算机电池旁显示手机电池", "Description[zh_TW]": "在您的電腦電池電量旁邊顯示手機電池電量", "EnabledByDefault": true, "Icon": "preferences-system-power-management", "Id": "kdeconnect_battery", "License": "GPL", "Name": "Battery monitor", - "Name[ar]": "مرقاب البطّاريّة", "Name[ca@valencia]": "Monitor de la bateria", "Name[ca]": "Monitor de la bateria", "Name[cs]": "Monitor baterie", "Name[da]": "Batteriovervågning", "Name[de]": "Akkuüberwachung", - "Name[el]": "Παρακολούθηση μπαταρίας", "Name[es]": "Monitor de batería", "Name[et]": "Aku jälgija", "Name[eu]": "Bateriaren monitorea", "Name[fi]": "Akkuvalvonta", "Name[fr]": "Moniteur de batterie", "Name[gl]": "Vixilante da batería", "Name[hu]": "Akkumulátorfigyelő", - "Name[ia]": "Controlator de batteria", "Name[it]": "Monitor della batteria", "Name[ko]": "배터리 모니터", "Name[nl]": "Batterijmonitor", "Name[nn]": "Batteriovervaking", "Name[pl]": "Monitor baterii", "Name[pt]": "Monitor da bateria", "Name[pt_BR]": "Monitor de bateria", "Name[ru]": "Индикатор батареи", "Name[sk]": "Monitor batérie", "Name[sr@ijekavian]": "Надзор батерије", "Name[sr@ijekavianlatin]": "Nadzor baterije", "Name[sr@latin]": "Nadzor baterije", "Name[sr]": "Надзор батерије", "Name[sv]": "Batteriövervakare", "Name[tr]": "Pil izleyici", "Name[uk]": "Монітор акумулятора", "Name[x-test]": "xxBattery monitorxx", "Name[zh_CN]": "电池监视器", "Name[zh_TW]": "電池監視器", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.battery.request" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.battery" ] } diff --git a/plugins/clipboard/kdeconnect_clipboard.json b/plugins/clipboard/kdeconnect_clipboard.json index b68d796c..6e69cab6 100644 --- a/plugins/clipboard/kdeconnect_clipboard.json +++ b/plugins/clipboard/kdeconnect_clipboard.json @@ -1,100 +1,95 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "albertvaka@gmail.com", "Name": "Albert Vaca", "Name[sr@ijekavian]": "Алберт Вака Синтора", "Name[sr@ijekavianlatin]": "Albert Vaka Sintora", "Name[sr@latin]": "Albert Vaka Sintora", "Name[sr]": "Алберт Вака Синтора", "Name[x-test]": "xxAlbert Vacaxx" } ], "Description": "Share the clipboard between devices", - "Description[ar]": "شارك الحافظة بين الجهازين", "Description[ca@valencia]": "Comparteix el porta-retalls entre dispositius", "Description[ca]": "Comparteix el porta-retalls entre dispositius", "Description[cs]": "Sdílet obsah schránky mezi zařízeními", "Description[da]": "Del udklipsholderen mellem enheder", "Description[de]": "Die Zwischenablage mit Geräten teilen", - "Description[el]": "Διαμοιρασμός του προχείρου μεταξύ συσκευών", "Description[es]": "Compartir portapapeles entre dispositivos", "Description[et]": "Lõikepuhvri jagamine seadmete vahel", "Description[eu]": "Partekatu arbela gailuen artean", "Description[fi]": "Jaa leikepöytä laitteiden välillä", "Description[fr]": "Partagez le presse-papiers entre périphériques", "Description[gl]": "Comparta o portapapeis entre os dispositivos.", "Description[hu]": "A vágólap megosztása az eszközök között", "Description[it]": "Condividi gli appunti tra i dispositivi", "Description[ko]": "장치간 클립보드 공유", "Description[nl]": "Het klembord tussen apparaten delen", "Description[nn]": "Del utklippstavla mellom einingar", "Description[pl]": "Współdziel schowek pomiędzy urządzeniami", "Description[pt]": "Partilhar a área de transferência entre dispositivos", "Description[pt_BR]": "Compartilha a área de transferência entre dispositivos", "Description[ru]": "Общий буфер обмена между устройствами", "Description[sk]": "Zdieľať schránku medzi zariadeniami", "Description[sr@ijekavian]": "Дељење клипборда између уређаја", "Description[sr@ijekavianlatin]": "Deljenje klipborda između uređaja", "Description[sr@latin]": "Deljenje klipborda između uređaja", "Description[sr]": "Дељење клипборда између уређаја", "Description[sv]": "Dela klippbordet mellan apparater", "Description[tr]": "Aygıtlar arasında panoyu paylaştır", "Description[uk]": "Спільне використання буфера обміну даними на пристроях", "Description[x-test]": "xxShare the clipboard between devicesxx", "Description[zh_CN]": "在设备间共享剪贴板", "Description[zh_TW]": "在設備之間共享剪貼板", "EnabledByDefault": true, "Icon": "klipper", "Id": "kdeconnect_clipboard", "License": "GPL", "Name": "Clipboard", - "Name[ar]": "الحافظة", "Name[ca@valencia]": "Porta-retalls", "Name[ca]": "Porta-retalls", "Name[cs]": "Schránka", "Name[da]": "Udklipsholder", "Name[de]": "Zwischenablage", - "Name[el]": "Πρόχειρο", "Name[es]": "Portapapeles", "Name[et]": "Lõikepuhver", "Name[eu]": "Arbela", "Name[fi]": "Leikepöytä", "Name[fr]": "Presse-papiers", "Name[gl]": "Portapapeis", "Name[hu]": "Vágólap", - "Name[ia]": "Area de transferentia", "Name[it]": "Appunti", "Name[ko]": "클립보드", "Name[nl]": "Klembord", "Name[nn]": "Utklippstavle", "Name[pl]": "Schowek", "Name[pt]": "Área de Transferência", "Name[pt_BR]": "Área de transferência", "Name[ru]": "Буфер обмена", "Name[sk]": "Schránka", "Name[sr@ijekavian]": "Клипборд", "Name[sr@ijekavianlatin]": "Klipbord", "Name[sr@latin]": "Klipbord", "Name[sr]": "Клипборд", "Name[sv]": "Klippbord", "Name[tr]": "Geçici taşıma panosu", "Name[uk]": "Буфер обміну", "Name[x-test]": "xxClipboardxx", "Name[zh_CN]": "剪贴板", "Name[zh_TW]": "剪貼板", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.clipboard" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.clipboard" ] } diff --git a/plugins/findmyphone/kdeconnect_findmyphone.json b/plugins/findmyphone/kdeconnect_findmyphone.json index a64f117a..9baaacca 100644 --- a/plugins/findmyphone/kdeconnect_findmyphone.json +++ b/plugins/findmyphone/kdeconnect_findmyphone.json @@ -1,103 +1,97 @@ { "KPlugin": { "Authors": [ { "Email": "apparle@gmail.com", "Name": "Apoorv Parle", "Name[sr@ijekavian]": "Апорв Парле", "Name[sr@ijekavianlatin]": "Aporv Parle", "Name[sr@latin]": "Aporv Parle", "Name[sr]": "Апорв Парле", "Name[x-test]": "xxApoorv Parlexx" }, { "Email": "davidedmundson@kde.org", "Name": "David Edmundson", "Name[sr@ijekavian]": "Дејвид Едмундсон", "Name[sr@ijekavianlatin]": "Dejvid Edmundson", "Name[sr@latin]": "Dejvid Edmundson", "Name[sr]": "Дејвид Едмундсон", "Name[x-test]": "xxDavid Edmundsonxx" } ], "Description": "Find your lost phone by making it play an alarm sound", - "Description[ar]": "جِد هاتفك الضّائع بتشغيل صوت المنبّه", "Description[ca@valencia]": "Troba el vostre telèfon perdut fent que reproduïsca un so d'alarma", "Description[ca]": "Troba el vostre telèfon perdut fent que reprodueixi un so d'alarma", "Description[cs]": "Najděte svůj telefon tím, že jej necháte přehrát zvuk upomínky", "Description[da]": "Find din forsvundne telefon ved at få den til at afspille en alarm", "Description[de]": "Finden Sie Ihr verlegtes Telefon, indem Sie mit ihm eine Warnton abspielen", - "Description[el]": "Βρείτε το χαμένο σας τηλέφωνο με ηχητική ειδοποίηση", "Description[es]": "Encuentre su teléfono perdido haciéndole reproducir un sonido de alarma", "Description[et]": "Kaotsi läinud telefoni leidmine sellel häireheli esitamisega", "Description[eu]": "Aurkitu galdutako telefonoa alarma-soinu bat jo araziz", "Description[fi]": "Löydä hukkaamasi puhelin laittamalla se soittamaan hälytysääntä", "Description[fr]": "Trouver votre téléphone perdu en déclenchant une alarme", - "Description[gl]": "Reproducir un son de alarma nun teléfono móbil perdido para atopalo.", "Description[it]": "Trova il tuo telefono smarrito facendogli suonare un allarme sonoro", "Description[ko]": "알람 소리를 울려서 잃어버린 휴대폰 찾기", "Description[nl]": "Zoek uw verloren telefoon door het een wekkersignaal te laten spelen", "Description[nn]": "Finn telefonen din ved å la han spela eit lydsignal", "Description[pl]": "Znajdź twój zgubiony telefon odgrywając na nim dźwięk", "Description[pt]": "Descobrir o seu telefone perdido, fazendo-o tocar um som de alarme", "Description[pt_BR]": "Encontre seu telefone fazendo ele reproduzir um som", "Description[ru]": "Поиск утерянного телефона при помощи звукового сигнала", "Description[sk]": "Nájsť váš stratený telefón zahraním zvuku budíka", "Description[sr@ijekavian]": "Нађите изгубљени телефон активирањем звука аларма", "Description[sr@ijekavianlatin]": "Nađite izgubljeni telefon aktiviranjem zvuka alarma", "Description[sr@latin]": "Nađite izgubljeni telefon aktiviranjem zvuka alarma", "Description[sr]": "Нађите изгубљени телефон активирањем звука аларма", "Description[sv]": "Hitta din förlorade telefon genom att få den att spela ett alarmljud", "Description[tr]": "Bir alarm sesi çalarak kayıp telefonunuzu bulun ", "Description[uk]": "Знайти загублений телефон, наказавши йому відтворити дзвінок", "Description[x-test]": "xxFind your lost phone by making it play an alarm soundxx", "Description[zh_CN]": "通过播放闹铃声来找到您不见的手机", "Description[zh_TW]": "讓您的手機發出警報聲,讓您找到您遺失的手機。", "EnabledByDefault": true, "Encoding": "UTF-8", "Icon": "edit-find", "Id": "kdeconnect_findmyphone", "License": "GPL", "Name": "Ring my phone", - "Name[ar]": "رنّ هاتفي", "Name[ca@valencia]": "Fes sonar el meu telèfon", "Name[ca]": "Fes sonar el meu telèfon", "Name[cs]": "Prozvonit můj telefon", "Name[da]": "Ring min telefon op", "Name[de]": "Mein Telefon anklingeln", - "Name[el]": "Κουδούνισμα του τηλεφώνου μου", "Name[es]": "Hacer sonar mi teléfono", "Name[et]": "Helista minu telefonile", "Name[eu]": "Jo nire telefonoaren dei-doinua", "Name[fi]": "Soita puhelimeeni", "Name[fr]": "Faire sonner mon téléphone", - "Name[gl]": "Facer soar o meu móbil", "Name[it]": "Fai squillare il mio telefono", "Name[ko]": "내 휴대폰 울리기", "Name[nl]": "Bel mijn telefoon", "Name[nn]": "Ring telefonen", "Name[pl]": "Dzwoń z mojego telefonu", "Name[pt]": "Tocar o meu telefone", "Name[pt_BR]": "Tocar meu telefone", "Name[ru]": "Поиск телефона", "Name[sk]": "Prezvoniť môj telefón", "Name[sr@ijekavian]": "Звони мој телефону", "Name[sr@ijekavianlatin]": "Zvoni moj telefonu", "Name[sr@latin]": "Zvoni moj telefonu", "Name[sr]": "Звони мој телефону", "Name[sv]": "Hitta min telefon", "Name[tr]": "Telefonumu çaldır", "Name[uk]": "Дзвінок на вашому телефоні", "Name[x-test]": "xxRing my phonexx", "Name[zh_CN]": "让我的手机响铃", "Name[zh_TW]": "撥打我的電話", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://kde.org" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.findmyphone.request" ] } diff --git a/plugins/kdeconnect.notifyrc b/plugins/kdeconnect.notifyrc index 09e50741..cc233ac7 100644 --- a/plugins/kdeconnect.notifyrc +++ b/plugins/kdeconnect.notifyrc @@ -1,730 +1,655 @@ [Global] IconName=kdeconnect Name=KDE Connect -Name[ar]=كدي المتّصل -Name[ast]=KDE Connect Name[bg]=KDE Connect Name[bs]=Konekcija KDE Name[ca]=KDE Connect Name[ca@valencia]=KDE Connect Name[cs]=KDE Connect Name[da]=KDE Connect Name[de]=KDE-Connect -Name[el]=KDE Connect Name[en_GB]=KDE Connect Name[es]=KDE Connect Name[et]=KDE Connect Name[eu]=KDE Connect Name[fi]=KDE Connect Name[fr]=KDE Connect Name[gl]=KDE Connect -Name[he]=KDE Connect Name[hu]=KDE csatlakozás Name[it]=KDE Connect Name[ko]=KDE Connect Name[nl]=KDE Connect Name[nn]=KDE Connect Name[pl]=KDE Connect Name[pt]=KDE Connect Name[pt_BR]=KDE Connect Name[ro]=KDE Connect Name[ru]=KDE Connect Name[sk]=KDE Connect Name[sr]=КДЕ‑конекција Name[sr@ijekavian]=КДЕ‑конекција Name[sr@ijekavianlatin]=KDE‑konekcija Name[sr@latin]=KDE‑konekcija Name[sv]=KDE-anslut Name[tr]=KDE Connect Name[uk]=З’єднання KDE Name[x-test]=xxKDE Connectxx Name[zh_CN]=KDE Connect Name[zh_TW]=KDE 連線 Comment=Notifications from your devices -Comment[ar]=الإخطارات من أجهزتك -Comment[ast]=Avisos de los tos preseos Comment[bg]=Уведомления от устройствата ви Comment[bs]=Notifikacija sa Vašeg uređaja Comment[ca]=Notificacions dels vostres dispositius Comment[ca@valencia]=Notificacions dels vostres dispositius Comment[cs]=Oznamování z vašich zařízení Comment[da]=Bekendtgørelser fra dine enheder Comment[de]=Benachrichtigungen von Ihren Geräten -Comment[el]=Ειδοποιήσεις από τις συσκευές σας Comment[en_GB]=Notifications from your devices Comment[es]=Notificaciones de sus dispositivos Comment[et]=Seadmete märguanded Comment[eu]=Zure gailuetako jakinarazpenak Comment[fi]=Laitteesi ilmoitukset Comment[fr]=Notifications provenant de vos périphériques Comment[gl]=Notificacións de dispositivos. -Comment[he]=התראות מההתקן שלך Comment[hu]=Az eszközökről származó értesítések Comment[it]=Notifiche dai tuoi dispositivi Comment[ko]=장치에 표시된 알림 Comment[nl]=Meldingen van uw apparaten Comment[nn]=Varslingar frå einingane dine Comment[pl]=Powiadomienia z urządzeń Comment[pt]=Notificações dos seus dispositivos Comment[pt_BR]=Notificações dos seus dispositivos Comment[ro]=Notificări de pe dispozitivele dumneavoastră Comment[ru]=Уведомления от мобильных устройств Comment[sk]=Oznámenia z vašich zariadení Comment[sr]=Обавештење са вашег уређаја Comment[sr@ijekavian]=Обавештење са вашег уређаја Comment[sr@ijekavianlatin]=Obaveštenje sa vašeg uređaja Comment[sr@latin]=Obaveštenje sa vašeg uređaja Comment[sv]=Underrättelser från dina apparater Comment[tr]=Cihazınızdan bildirimler Comment[uk]=Сповіщення з вашого пристрою Comment[x-test]=xxNotifications from your devicesxx Comment[zh_CN]=来自你设备的通知 Comment[zh_TW]=從您的裝置接收到通知 [Event/pairingRequest] Name=Pairing Request -Name[ar]=طلب اقتران -Name[ast]=Solicitú d'empareyamientu Name[bg]=Заявка за сдвояване Name[bs]=Zahtjev za uparivanje Name[ca]=Sol·licitud d'aparellament Name[ca@valencia]=Sol·licitud d'aparellament Name[cs]=Požadavek na párování Name[da]=Parringsanmodning Name[de]=Verbindungsanfrage -Name[el]=Αίτημα σύζευξης Name[en_GB]=Pairing Request Name[es]=Petición de vinculación Name[et]=Paardumissoov Name[eu]=Parekatzeko eskaria Name[fi]=Paripyyntö Name[fr]=Demande d'association Name[gl]=Solicitude de emparellamento -Name[he]=בקשת התאמה Name[hu]=Párosítási kérés Name[it]=Richiesta di associazione Name[ko]=연결 요청 Name[nl]=Verzoek om een paar te maken Name[nn]=Parringsførespurnad Name[pl]=Żądanie parowania Name[pt]=Pedido de Emparelhamento Name[pt_BR]=Solicitação de emparelhamento Name[ru]=Запрос на сопряжение Name[sk]=Požiadavka na spárovanie Name[sr]=Захтев за упаривање Name[sr@ijekavian]=Захтев за упаривање Name[sr@ijekavianlatin]=Zahtev za uparivanje Name[sr@latin]=Zahtev za uparivanje Name[sv]=Begäran om ihopparning Name[tr]=Eşleşme İsteği Name[uk]=Запит щодо пов’язування Name[x-test]=xxPairing Requestxx Name[zh_CN]=配对请求 Name[zh_TW]=配對請求 Comment=Pairing request received from a device -Comment[ar]=استُلم طلب اقتران من جهاز -Comment[ast]=Recibióse una solicitú d'empareyamientu d'un preséu Comment[ca]=Les sol·licituds d'aparellament rebudes des d'un dispositiu Comment[ca@valencia]=Les sol·licituds d'aparellament rebudes des d'un dispositiu Comment[cs]=Požadavek na párování přijat ze zařízení Comment[da]=Parringsanmodning modtaget fra en enhed Comment[de]=Verbindungsanfrage von einem Gerät erhalten -Comment[el]=Λήφθηκε αίτημα σύζευξης από μια συσκευή Comment[en_GB]=Pairing request received from a device Comment[es]=Petición de vinculación recibida desde un dispositivo Comment[et]=Seadmelt saadi paardumissoov Comment[eu]=Parekatzeko eskaria jaso da gailu batetik Comment[fi]=Saatiin paripyyntö laitteelta Comment[fr]=Demande d'association provenant d'un périphérique -Comment[gl]=Recibiuse unha solicitude de emparellamento dun dispositivo. -Comment[he]=התקבלה בקשת התאמה מהתקן Comment[it]=Richiesta di associazione ricevuta da un dispositivo Comment[ko]=장치에서 연결 요청을 받음 -Comment[nl]=Verzoek om een paar te maken ontvangen van apparaten +Comment[nl]=Verzoek om een paar te maken ontvangen van een apparaat Comment[nn]=Fekk parringsførespurnad frå eining Comment[pl]=Otrzymano żądanie parowania z urządzenia Comment[pt]=Pedido de emparelhamento recebido de um dispositivo Comment[pt_BR]=Solicitação de emparelhamento recebida de um dispositivo Comment[ru]=От мобильного устройства получен запрос на сопряжение Comment[sk]=Požiadavka na spárovanie prijatá zo zariadenia Comment[sr]=Захтев за упаривање примљен од уређаја Comment[sr@ijekavian]=Захтев за упаривање примљен од уређаја Comment[sr@ijekavianlatin]=Zahtev za uparivanje primljen od uređaja Comment[sr@latin]=Zahtev za uparivanje primljen od uređaja Comment[sv]=Begäran om ihopparning mottagen från en apparat Comment[tr]=Bir cihazdan alınan eşleştirme isteği Comment[uk]=Від пристрою отримано запит щодо пов’язування Comment[x-test]=xxPairing request received from a devicexx Comment[zh_CN]=收到来自一个设备的配对请求 Comment[zh_TW]=從您的裝置當中收到配對請求 Action=Popup [Event/callReceived] Name=Incoming Call -Name[ar]=مكالمة واردة -Name[ast]=Llamada entrante Name[bg]=Входящо обаждане Name[ca]=Trucada entrant Name[ca@valencia]=Trucada entrant Name[cs]=Příchozí hovor Name[da]=Indkommende opkald Name[de]=Eingehender Anruf -Name[el]=Εισερχόμενη κλήση Name[en_GB]=Incoming Call Name[es]=Llamada entrante Name[et]=Sisenev kõne Name[eu]=Sarrerako deia Name[fi]=Saapuva puhelu Name[fr]=Appel entrant Name[gl]=Chamada entrante -Name[he]=שיחה נכנסת Name[hu]=Bejövő hívás -Name[ia]=Appello in arrivata Name[it]=Chiamata in ingresso Name[ko]=수신 전화 Name[nl]=Inkomende oproep Name[nn]=Innkommande samtale Name[pl]=Rozmowa przychodząca Name[pt]=Chamada Recebida Name[pt_BR]=Chamada recebida Name[ru]=Входящий звонок Name[sk]=Prichádzajúci hovor Name[sr]=Долазни позив Name[sr@ijekavian]=Долазни позив Name[sr@ijekavianlatin]=Dolazni poziv Name[sr@latin]=Dolazni poziv Name[sv]=Inkommande samtal Name[tr]=Gelen Çağrı Name[uk]=Вхідний дзвінок Name[x-test]=xxIncoming Callxx Name[zh_CN]=收到呼叫 Name[zh_TW]=電話來電 Comment=Someone is calling you -Comment[ar]=ثمّة من يتّصل بك -Comment[ast]=Daquién ta llamándote Comment[bg]=Някой ви се обажда Comment[bs]=Neko Vas zove Comment[ca]=Algú us està trucant Comment[ca@valencia]=Algú vos està trucant Comment[cs]=Někdo vám volá Comment[da]=Nogen ringer til dig Comment[de]=Sie werden angerufen -Comment[el]=Κάποιος σας καλεί Comment[en_GB]=Someone is calling you Comment[es]=Alguien le está llamando Comment[et]=Keegi helistab sulle Comment[eu]=Norbait deitzen ari zaizu Comment[fi]=Sinulle soitetaan Comment[fr]=Quelqu'un vous appelle Comment[gl]=Está a recibir unha chamada de alguén. -Comment[he]=מישהו מתקשר אילך Comment[hu]=Valaki hívja önt Comment[it]=Chiamata in arrivo Comment[ko]=누군가가 전화를 걸었음 Comment[nl]=Iemand belt u op Comment[nn]=Nokon ringjer deg Comment[pl]=Ktoś do ciebie dzwoni Comment[pt]=Alguém está a ligar-lhe Comment[pt_BR]=Alguém está chamando você Comment[ro]=Cineva vă apelează Comment[ru]=Вам кто-то звонит Comment[sk]=Niekto vám volá Comment[sr]=Неко вас зове Comment[sr@ijekavian]=Неко вас зове Comment[sr@ijekavianlatin]=Neko vas zove Comment[sr@latin]=Neko vas zove Comment[sv]=Någon ringer till dig Comment[tr]=Biri sizi arıyor Comment[uk]=Хтось телефонує вам Comment[x-test]=xxSomeone is calling youxx Comment[zh_CN]=某人正在呼叫您 Comment[zh_TW]=有人打電話給您 Action=Popup [Event/missedCall] Name=Missed Call -Name[ar]=مكالمة فائتة -Name[ast]=Llamada perdida Name[bg]=Пропуснато обаждане Name[ca]=Trucada perduda Name[ca@valencia]=Trucada perduda Name[cs]=Zmeškaný hovor Name[da]=Ubesvaret opkald Name[de]=Verpasster Anruf -Name[el]=Αναπάντητη κλήση Name[en_GB]=Missed Call Name[es]=Llamada perdida Name[et]=Vastamata kõne Name[eu]=Galdutako deia Name[fi]=Vastaamaton puhelu Name[fr]=Appel manqué Name[gl]=Chamada perdida -Name[he]=שיחה שלא נענתה Name[hu]=Nem fogadott hívás Name[it]=Chiamate perse Name[ko]=부재 중 전화 Name[nl]=Gemiste oproep Name[nn]=Tapt oppringing Name[pl]=Połączenie nieodebrane Name[pt]=Chamada Não Atendida Name[pt_BR]=Chamada não atendida Name[ru]=Пропущенный звонок Name[sk]=Zmeškaný hovor Name[sr]=Пропуштен позив Name[sr@ijekavian]=Пропуштен позив Name[sr@ijekavianlatin]=Propušten poziv Name[sr@latin]=Propušten poziv Name[sv]=Missat samtal Name[tr]=Cevapsız Çağrı Name[uk]=Пропущений дзвінок Name[x-test]=xxMissed Callxx Name[zh_CN]=未接来电 Name[zh_TW]=未接來電 Comment=You have a missed call -Comment[ar]=لقد فاتتك مكالمة -Comment[ast]=Tienes una llamada perdida Comment[bg]=Имате неприето обаждане Comment[bs]=Imate propušten poziv Comment[ca]=Teniu una trucada perduda Comment[ca@valencia]=Teniu una trucada perduda Comment[cs]=Máte zmeškaný hovor Comment[da]=Du har et ubesvaret opkald Comment[de]=Sie haben einen Anruf verpasst -Comment[el]=Έχετε μια αναπάντητη κλήση Comment[en_GB]=You have a missed call Comment[es]=Tiene una llamada perdida Comment[et]=Kõnele jäi vastamata Comment[eu]=Galdutako dei bat duzu Comment[fi]=Sinulla on vastaamaton puhelu Comment[fr]=Vous avez un appel manqué Comment[gl]=Ten unha chamada perdida. -Comment[he]=יש לך שיחה שלא נענטה Comment[hu]=Nem fogadott hívása van Comment[it]=Hai una chiamata persa Comment[ko]=부재 중 전화가 있음 Comment[nl]=U hebt een gemiste oproep Comment[nn]=Du har ei tapt oppringing Comment[pl]=Nie odebrałeś połączenia Comment[pt]=Tem uma chamada não atendida Comment[pt_BR]=Você tem uma chamada não atendida Comment[ro]=Ați pierdut un apel Comment[ru]=У вас есть пропущенный вызов Comment[sk]=Máte zmeškaný hovor Comment[sr]=Имате пропуштен позив Comment[sr@ijekavian]=Имате пропуштен позив Comment[sr@ijekavianlatin]=Imate propušten poziv Comment[sr@latin]=Imate propušten poziv Comment[sv]=Du har missat ett samtal Comment[tr]=Cevapsız çağrınız var Comment[uk]=Вами пропущено телефонний дзвінок Comment[x-test]=xxYou have a missed callxx Comment[zh_CN]=您有未接来电 Comment[zh_TW]=您有一通未接來電 Action=Popup [Event/smsReceived] Name=SMS Received -Name[ar]=استُلمت رسالة -Name[ast]=SMS recibíu Name[bg]=Получен SMS Name[ca]=S'ha rebut un SMS Name[ca@valencia]=S'ha rebut un SMS Name[cs]=SMS přijata Name[da]=SMS-modtaget Name[de]=SMS empfangen -Name[el]=Λήφθηκε SMS Name[en_GB]=SMS Received Name[es]=SMS recibido Name[et]=SMS-i saamine Name[eu]=SMS bat jaso da Name[fi]=Saatiin tekstiviesti Name[fr]=SMS reçu Name[gl]=Recibiuse un SMS -Name[he]=התקבלה הודעת SMS Name[hu]=SMS érkezett Name[it]=SMS ricevuto Name[ko]=SMS 받음 Name[nl]=SMS ontvangen Name[nn]=SMS motteken Name[pl]=Otrzymano SMSa Name[pt]=SMS Recebido Name[pt_BR]=SMS recebido Name[ru]=Входящее SMS Name[sk]=Prijatá SMS Name[sr]=СМС примљен Name[sr@ijekavian]=СМС примљен Name[sr@ijekavianlatin]=SMS primljen Name[sr@latin]=SMS primljen Name[sv]=SMS mottaget Name[tr]=SMS Alındı Name[uk]=Отримано SMS Name[x-test]=xxSMS Receivedxx Name[zh_CN]=收到短信 Name[zh_TW]=您有收到短訊 Comment=Someone sent you an SMS -Comment[ar]=ثمّة من أرسل رسالة إليك -Comment[ast]=Daquién unvióte un SMS Comment[bg]=Някой ви изпрати текстово съобщение Comment[bs]=Neko Vam je poslao SMS poruku Comment[ca]=Algú us ha enviat un SMS Comment[ca@valencia]=Algú vos ha enviat un SMS Comment[cs]=Někdo vám poslal SMS Comment[da]=Nogen sendte dig en SMS Comment[de]=Jemand hat Ihnen eine SMS gesendet -Comment[el]=Κάποιος σας έστειλε SMS Comment[en_GB]=Someone sent you an SMS Comment[es]=Alguien le ha enviado un SMS Comment[et]=Keegi saatis sulle SMS-i Comment[eu]=Norbaitek SMS bat bidali dizu Comment[fi]=Sinulle lähetettiin tekstiviesti Comment[fr]=Quelqu'un vous a envoyé un SMS Comment[gl]=Recibiu unha mensaxe SMS de alguén. -Comment[he]=מישהו שלח לך SMS Comment[hu]=Valaki SMS-t küldött önnek Comment[it]=Hai ricevuto un SMS Comment[ko]=누군가가 문자 메시지를 보냄 Comment[nl]=Iemand heeft u een SMS gestuurd Comment[nn]=Noko sende deg ein SMS Comment[pl]=Ktoś do ciebie wysłał SMSa Comment[pt]=Alguém lhe enviou um SMS Comment[pt_BR]=Alguém lhe enviou um SMS Comment[ro]=Cineva v-a trimis un SMS Comment[ru]=Вы получили SMS-сообщение Comment[sk]=Niekto vám poslal SMS Comment[sr]=Неко вам је послао СМС Comment[sr@ijekavian]=Неко вам је послао СМС Comment[sr@ijekavianlatin]=Neko vam je poslao SMS Comment[sr@latin]=Neko vam je poslao SMS Comment[sv]=Någon skickade ett SMS till dig Comment[tr]=Biri size SMS gönderdi Comment[uk]=Хтось надіслав вам SMS Comment[x-test]=xxSomeone sent you an SMSxx Comment[zh_CN]=某人给您发了短信 Comment[zh_TW]=有人送來一封簡訊 Action=Popup [Event/batteryLow] Name=Battery Low -Name[ar]=البطّاريّة ضعيفة -Name[ast]=Batería baxa Name[bg]=Изтощена батерия Name[ca]=Bateria baixa Name[ca@valencia]=Bateria baixa Name[cs]=Baterie je téměř vybitá Name[da]=Lavt batteri Name[de]=Akku-Ladestand niedrig -Name[el]=Μπαταρία χαμηλή Name[en_GB]=Battery Low Name[es]=Batería baja Name[et]=Aku laetus on madal Name[eu]=Bateria baxu Name[fi]=Akku vähissä Name[fr]=Batterie faible Name[gl]=Batería baixa Name[hu]=Alacsony töltöttség -Name[ia]=Batteria basse Name[it]=Batteria a livello basso Name[ko]=배터리 부족 Name[nl]=Batterij op laag niveau Name[nn]=Lågt batterinivå Name[pl]=Bateria na niskim poziomie Name[pt]=Bateria Fraca Name[pt_BR]=Bateria fraca Name[ru]=Низкий заряд батареи Name[sk]=Batéria je slabá Name[sr]=Батерија при крају Name[sr@ijekavian]=Батерија при крају Name[sr@ijekavianlatin]=Baterija pri kraju Name[sr@latin]=Baterija pri kraju Name[sv]=Låg batteriladdning Name[tr]=Pil Zayıf Name[uk]=Низький рівень заряду Name[x-test]=xxBattery Lowxx Name[zh_CN]=电池电量低 Name[zh_TW]=電池低電量 Comment=Your battery is in low state -Comment[ar]=بطّاريّتك في الحالة الضعيفة -Comment[ast]=La to batería ta escosándose Comment[bg]=Батерията ви е с нисък заряд Comment[bs]=Vaša baterija je gotovo prazna Comment[ca]=La bateria està baixa Comment[ca@valencia]=La bateria està baixa Comment[cs]=Máte slabou baterii Comment[da]=Dit batteri er på lavt niveau Comment[de]=Der Ladestand Ihres Akkus ist niedrig -Comment[el]=Η μπαταρία σας είναι σε χαμηλό επίπεδο Comment[en_GB]=Your battery is in low state Comment[es]=La batería está en nivel bajo Comment[et]=Aku täituvus on madal Comment[eu]=Zure bateria egoera baxuan dago Comment[fi]=Akkusi virta on vähissä Comment[fr]=Votre batterie est faible Comment[gl]=A batería está esgotándose. -Comment[he]=הבטריה שלך הולכת להגמר Comment[hu]=Az akkumulátora feszültsége alacsony Comment[it]=La tua batteria è al livello basso Comment[ko]=배터리가 부족함 Comment[nl]=Uw batterij is bijna leeg Comment[nn]=Det er lite batteri att Comment[pl]=Twoja bateria ma niski poziom naładowania Comment[pt]=A sua bateria está fraca Comment[pt_BR]=Sua bateria está com carga baixa Comment[ro]=Acumulatorul are un nivel scăzut Comment[ru]=Низкий заряд батареи мобильного устройства Comment[sk]=Vaša batéria je na nízkom stave Comment[sr]=Ваша батерија је на издисају Comment[sr@ijekavian]=Ваша батерија је на издисају Comment[sr@ijekavianlatin]=Vaša baterija je na izdisaju Comment[sr@latin]=Vaša baterija je na izdisaju Comment[sv]=Batteriet är nästan slut Comment[tr]=Pilinizin seviyesi düşük Comment[uk]=Рівень заряду акумулятора є низьким Comment[x-test]=xxYour battery is in low statexx Comment[zh_CN]=您的电池电量低 Comment[zh_TW]=您的電池處於低容量狀態 Action=Popup [Event/pingReceived] Name=Ping Received -Name[ar]=استُلمت وكزة -Name[ast]=Ping recibíu Name[bg]=Пингът е приет Name[ca]=S'ha rebut un ping Name[ca@valencia]=S'ha rebut un ping Name[cs]=Ping přijat Name[da]=Ping modtaget Name[de]=Ping empfangen -Name[el]=Λήφθηκε ping Name[en_GB]=Ping Received Name[es]=Ping recibido Name[et]=Pingi saamine Name[eu]=Ping jaso da Name[fi]=Saatiin tiedustelupaketti Name[fr]=Ping reçu Name[gl]=Recibiuse un ping -Name[he]=התקבל פינג Name[hu]=Ping érkezett Name[it]=Ping ricevuto Name[ko]=핑 받음 Name[nl]=Ping ontvangen Name[nn]=Pingsignal motteke Name[pl]=Otrzymano ping Name[pt]=Contacto Recebido Name[pt_BR]=Ping recebido Name[ru]=Пинг получен Name[sk]=Prijatý ping Name[sr]=Примљен пинг Name[sr@ijekavian]=Примљен пинг Name[sr@ijekavianlatin]=Primljen ping Name[sr@latin]=Primljen ping Name[sv]=Ping mottaget Name[tr]=Ping Alındı Name[uk]=Отримано сигнал підтримки зв’язку Name[x-test]=xxPing Receivedxx Name[zh_CN]=收到 Ping Name[zh_TW]=收到Ping回應 Comment=Ping received -Comment[ar]=استُلمت وكزة -Comment[ast]=Recibióse un ping Comment[bg]=Пингът е приет Comment[bs]=Primili ste ping Comment[ca]=S'ha rebut un ping Comment[ca@valencia]=S'ha rebut un ping Comment[cs]=Ping přijat Comment[da]=Ping modtaget Comment[de]=Ping empfangen -Comment[el]=Λήφθηκε ping Comment[en_GB]=Ping received Comment[es]=Ping recibido Comment[et]=Pingi saamine Comment[eu]=Ping jaso da Comment[fi]=Saatiin tiedustelupaketti Comment[fr]=Ping reçu Comment[gl]=Recibiuse un “ping”. -Comment[he]=התקבל פינג Comment[hu]=Ping érkezett Comment[it]=Hai ricevuto un ping Comment[ko]=핑 받음 Comment[nl]=Ping ontvangen Comment[nn]=Pingsignal motteke Comment[pl]=Otrzymano ping Comment[pt]=Pedido de rede recebido Comment[pt_BR]=Ping recebido Comment[ro]=Ping primit Comment[ru]=Получен тестовый сигнал Comment[sk]=Prijatý ping Comment[sr]=Примљен пинг Comment[sr@ijekavian]=Примљен пинг Comment[sr@ijekavianlatin]=Primljen ping Comment[sr@latin]=Primljen ping Comment[sv]=Ping mottaget Comment[tr]=Ping alındı Comment[uk]=Отримано сигнал підтримки зв’язку Comment[x-test]=xxPing receivedxx Comment[zh_CN]=收到 ping Comment[zh_TW]=接收到遠端的Ping回應封包 Action=Popup [Event/notification] Name=Generic Notification -Name[ar]=إخطار عموميّ -Name[ast]=Avisu xenéricu Name[bg]=Общо уведомление Name[ca]=Notificació genèrica Name[ca@valencia]=Notificació genèrica Name[cs]=Obecná hlášení Name[da]=Generisk bekendtgørelse Name[de]=Allgemeine Benachrichtigung -Name[el]=Γενική ειδοποίηση Name[en_GB]=Generic Notification Name[es]=Notificación genérica Name[et]=Üldine märguanne Name[eu]=Jakinarazpen arrunta Name[fi]=Yleinen ilmoitus Name[fr]=Notification Name[gl]=Notificación xenérica -Name[he]=התראה כללית Name[hu]=Általános értesítés Name[it]=Notifica generica Name[ko]=일반 알림 Name[nl]=Algemene melding Name[nn]=Generell varsling Name[pl]=Zwykłe powiadomienie Name[pt]=Notificação Genérica Name[pt_BR]=Notificação genérica Name[ru]=Общее уведомление Name[sk]=Všeobecné upozornenie Name[sr]=Опште обавештење Name[sr@ijekavian]=Опште обавештење Name[sr@ijekavianlatin]=Opšte obaveštenje Name[sr@latin]=Opšte obaveštenje Name[sv]=Generell underrättelse Name[tr]=Genel Bildirim Name[uk]=Загальне сповіщення Name[x-test]=xxGeneric Notificationxx Name[zh_CN]=一般通知 Name[zh_TW]=通用通知 Comment=Notification received -Comment[ar]=استُلم إخطار -Comment[ast]=Recibióse un avisu Comment[bg]=Уведомлението е прието Comment[bs]=Primjeno obavještenje Comment[ca]=Notificació rebuda Comment[ca@valencia]=Notificació rebuda Comment[cs]=Bylo přijato upozornění Comment[da]=Bekendtgørelse modtaget Comment[de]=Benachrichtigung eingegangen -Comment[el]=Λήφθηκε ειδοποίηση Comment[en_GB]=Notification received Comment[es]=Notificación recibida Comment[et]=Saadi märguanne Comment[eu]=Jakinarazpena jaso da Comment[fi]=Saatiin ilmoitus Comment[fr]=Notification reçue Comment[gl]=Recibiuse unha notificación. -Comment[he]=התראה התקבלה Comment[hu]=Értesítés érkezett Comment[it]=Hai ricevuto una notifica Comment[ko]=알림 받음 Comment[nl]=Melding ontvangen Comment[nn]=Varsling motteken Comment[pl]=Otrzymano powiadomienie Comment[pt]=Notificação recebida Comment[pt_BR]=Notificação recebida Comment[ro]=Notificare primită Comment[ru]=На мобильном устройстве получено уведомление Comment[sk]=Prijaté oznámenie Comment[sr]=Примљено је обавештење Comment[sr@ijekavian]=Примљено је обавештење Comment[sr@ijekavianlatin]=Primljeno je obaveštenje Comment[sr@latin]=Primljeno je obaveštenje Comment[sv]=Underrättelse mottagen Comment[tr]=Bildirim alındı Comment[uk]=Отримано сповіщення Comment[x-test]=xxNotification receivedxx Comment[zh_CN]=收到通知 Comment[zh_TW]=收到通知 Action=Popup [Event/transferReceived] Name=File Transfer -Name[ar]=نقل الملفّات -Name[ast]=Tresferencia de ficheros Name[bg]=Прехвърляне на файл Name[ca]=Transferència de fitxers Name[ca@valencia]=Transferència de fitxers Name[cs]=Přenos souboru Name[da]=Filoverførsel Name[de]=Dateiübertragung -Name[el]=Μεταφορά αρχείου Name[en_GB]=File Transfer Name[es]=Transferencia de archivo Name[et]=Failiedastus Name[eu]=Fitxategi-transferentzia Name[fi]=Tiedostonsiirto Name[fr]=Transfert de fichiers Name[gl]=Transferencia dun ficheiro -Name[he]=העברת קובץ Name[hu]=Fájlátvitel -Name[ia]=Transferimento de file Name[it]=Trasferimento file Name[ko]=파일 전송 Name[nl]=Bestandsoverdracht Name[nn]=Filoverføring Name[pl]=Przesył plików Name[pt]=Transferência de Ficheiros Name[pt_BR]=Transferência de arquivo Name[ru]=Передача файла Name[sk]=Prenos súboru Name[sr]=Пренос фајлова Name[sr@ijekavian]=Пренос фајлова Name[sr@ijekavianlatin]=Prenos fajlova Name[sr@latin]=Prenos fajlova Name[sv]=Filöverföring Name[tr]=Dosya Aktarımı Name[uk]=Перенесення файлів Name[x-test]=xxFile Transferxx Name[zh_CN]=文件传送 Name[zh_TW]=檔案傳輸 Comment=Incoming file -Comment[ar]=ملفّ قادم -Comment[ast]=Ficheru entrante Comment[bg]=Входящ файл Comment[ca]=Fitxer entrant Comment[ca@valencia]=Fitxer entrant Comment[cs]=Příchozí soubor Comment[da]=Indkommende fil Comment[de]=Eingehende Datei -Comment[el]=Εισερχόμενο αρχείο Comment[en_GB]=Incoming file Comment[es]=Archivo entrante Comment[et]=Sisenev fail Comment[eu]=Sarrerako fitxategia Comment[fi]=Saapuva tiedosto Comment[fr]=Fichier entrant Comment[gl]=Ficheiro entrante -Comment[he]=קובץ מגיע Comment[hu]=Bejövő fájl Comment[it]=File in ingresso Comment[ko]=파일 수신 Comment[nl]=Inkomend bestand Comment[nn]=Innkommande fil Comment[pl]=Przychodzący plik Comment[pt]=Ficheiro recebido Comment[pt_BR]=Arquivo recebido Comment[ru]=С мобильного устройства отправлен файл Comment[sk]=Prichádzajúci súbor Comment[sr]=Долазни фајл Comment[sr@ijekavian]=Долазни фајл Comment[sr@ijekavianlatin]=Dolazni fajl Comment[sr@latin]=Dolazni fajl Comment[sv]=Inkommande fil Comment[tr]=Gelen dosya Comment[uk]=Вхідний файл Comment[x-test]=xxIncoming filexx Comment[zh_CN]=正在传入的文件 Comment[zh_TW]=接收檔案 Action=Popup diff --git a/plugins/kdeconnect_plugin.desktop b/plugins/kdeconnect_plugin.desktop index 5379fce9..b04ce1c6 100644 --- a/plugins/kdeconnect_plugin.desktop +++ b/plugins/kdeconnect_plugin.desktop @@ -1,51 +1,47 @@ [Desktop Entry] Type=ServiceType X-KDE-ServiceType=KdeConnect/Plugin X-KDE-Derived=KPluginInfo Name=KDEConnect Plugin -Name[ar]=ملحقة KDEConnect -Name[ast]=Complementu de KDEConnect Name[bg]=Приставка на KDEConnect Name[bs]=Priključak za KDE konekciju Name[ca]=Connector del KDE Connect Name[ca@valencia]=Connector del KDE Connect Name[cs]=Modul KDEConnect Name[da]=KDEConnect-plugin Name[de]=KDEConnect-Modul -Name[el]=Πρόσθετο του KDEConnect Name[en_GB]=KDEConnect Plugin Name[es]=Complemento de KDEConnect Name[et]=KDEConnecti plugin Name[eu]=KDEConnect plugina Name[fi]=KDE Connect -liitännäinen Name[fr]=Module externe KDEConnect Name[gl]=Complemento de KDE Connect -Name[he]=תוספי KDEConnect Name[hu]=KDEConnect bővítmény Name[it]=Estensione KDEConnect Name[ko]=KDEConnect 플러그인 Name[nl]=Plug-in van KDEConnect Name[nn]=KDEConnect-tillegg Name[pl]=Wtyczka KDEConnect Name[pt]='Plugin' do KDEConnect Name[pt_BR]=Plugin do KDEConnect Name[ro]=Extensie KDEConnect Name[ru]=Модуль KDE Connect Name[sk]=Plugin KDEConnect Name[sr]=КДЕ‑конекцијин прикључак Name[sr@ijekavian]=КДЕ‑конекцијин прикључак Name[sr@ijekavianlatin]=KDE‑konekcijin priključak Name[sr@latin]=KDE‑konekcijin priključak Name[sv]=KDE anslutningsinsticksprogram Name[tr]=KDEConnect Eklentisi Name[uk]=Додаток KDEConnect Name[x-test]=xxKDEConnect Pluginxx Name[zh_CN]=KDEConnect 插件 Name[zh_TW]=KDE 連線擴展功能插件 # mandatory, list of all the package types supported [PropertyDef::X-KdeConnect-SupportedPackageType] Type=QStringList [PropertyDef::X-KdeConnect-OutgoingPackageType] Type=QStringList diff --git a/plugins/lockdevice/kdeconnect_lockdevice.json b/plugins/lockdevice/kdeconnect_lockdevice.json index 520a94bf..5157af16 100644 --- a/plugins/lockdevice/kdeconnect_lockdevice.json +++ b/plugins/lockdevice/kdeconnect_lockdevice.json @@ -1,96 +1,93 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "aleixpol@kde.org", "Name": "Aleix Pol", "Name[sr@ijekavian]": "Алекс Пол Гонзалез", "Name[sr@ijekavianlatin]": "Aleks Pol Gonzalez", "Name[sr@latin]": "Aleks Pol Gonzalez", "Name[sr]": "Алекс Пол Гонзалез", "Name[x-test]": "xxAleix Polxx" } ], "Description": "Locks your systems", - "Description[ar]": "أوصد الأنظمة", "Description[ca@valencia]": "Bloqueja els vostres sistemes", "Description[ca]": "Bloqueja els vostres sistemes", "Description[cs]": "Zamkne vaše systémy", "Description[da]": "Låser dine systemer", "Description[de]": "Sperrt Ihre Systeme", - "Description[el]": "Κλειδώνει τα συστήματά σας", "Description[es]": "Bloquear sus sistemas", "Description[et]": "Oma süsteemide lukustamine", "Description[eu]": "Zure sistemak blokeatzen ditu", "Description[fi]": "Lukitsee järjestelmäsi", "Description[fr]": "Bloque votre système", "Description[gl]": "Bloquea os seus sistemas.", "Description[it]": "Blocca i tuoi sistemi", "Description[ko]": "내 시스템 잠그기", "Description[nl]": "Vergrendeld uw systemen", "Description[nn]": "Lås systemet", "Description[pl]": "Zablokuj swoje systemy", "Description[pt]": "Bloqueia os seus sistemas", "Description[pt_BR]": "Bloqueia seus sistemas", "Description[ru]": "Блокировка ваших систем", "Description[sk]": "Zamkne vaše systémy", "Description[sr@ijekavian]": "Закључава ваш систем", "Description[sr@ijekavianlatin]": "Zaključava vaš sistem", "Description[sr@latin]": "Zaključava vaš sistem", "Description[sr]": "Закључава ваш систем", "Description[sv]": "Låser dina system", "Description[tr]": "Sistemlerinizi kilitler", "Description[uk]": "Блокує вашу систему", "Description[x-test]": "xxLocks your systemsxx", "Description[zh_CN]": "锁定您的系统", "Description[zh_TW]": "鎖定您的系統", "EnabledByDefault": true, "Icon": "applications-miscelaneaous", "Id": "kdeconnect_lockdevice", "License": "GPL", "Name": "LockDevice", - "Name[ar]": "أوصد الجهاز", "Name[ca@valencia]": "Bloqueja el dispositiu", "Name[ca]": "Bloqueja el dispositiu", "Name[cs]": "Uzamknout zařízení", "Name[da]": "LåsEnhed", "Name[de]": "Gerätesperrung", "Name[es]": "Bloquear dispositivo", "Name[et]": "Seadme lukustamine", "Name[eu]": "BlokeatuGailua", "Name[fi]": "Lukitse laite", "Name[gl]": "Bloqueo do dispositivo", "Name[it]": "Blocco dispositivo", "Name[ko]": "장치 잠금", "Name[nl]": "Apparaat vergrendelen", "Name[nn]": "Lås eining", "Name[pl]": "ZablokujUrządzenie", "Name[pt]": "Bloqueio de Dispositivo", "Name[pt_BR]": "Bloqueio de dispositivo", "Name[ru]": "Блокировка устройства", "Name[sk]": "Zamknúť zariadenie", "Name[sr@ijekavian]": "Катанац", "Name[sr@ijekavianlatin]": "Katanac", "Name[sr@latin]": "Katanac", "Name[sr]": "Катанац", "Name[sv]": "Lås enhet", "Name[tr]": "AygıtıKilitle", "Name[x-test]": "xxLockDevicexx", "Name[zh_CN]": "锁定设备", "Name[zh_TW]": "鎖定裝置", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "https://kde.org" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.lock.request", "kdeconnect.lock" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.lock.request", "kdeconnect.lock" ] } diff --git a/plugins/mousepad/kdeconnect_mousepad.json b/plugins/mousepad/kdeconnect_mousepad.json index b7b052eb..a9947eb8 100644 --- a/plugins/mousepad/kdeconnect_mousepad.json +++ b/plugins/mousepad/kdeconnect_mousepad.json @@ -1,97 +1,92 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "ahmedibrahimkhali@gmail.com", "Name": "Ahmed I. Khalil", - "Name[ar]": "أحمد إبراهيم خليل", "Name[sr@ijekavian]": "Ахмед И. Калил", "Name[sr@ijekavianlatin]": "Ahmed I. Kalil", "Name[sr@latin]": "Ahmed I. Kalil", "Name[sr]": "Ахмед И. Калил", "Name[x-test]": "xxAhmed I. Khalilxx" } ], "Description": "Use your phone as a touchpad and keyboard", - "Description[ar]": "استخدم الهاتف كفأرة ولوحة مفاتيح", "Description[ca@valencia]": "Empra el telèfon com un ratolí tàctil i teclat", "Description[ca]": "Empra el telèfon com un ratolí tàctil i teclat", "Description[cs]": "Používejte svůj telefon jako touchpad a klávesnici", "Description[da]": "Brug din telefon som touchpad og tastatur", "Description[de]": "Verwendet Ihr Handy als Touchpad und Tastatur", - "Description[el]": "Χρήση του τηλεφώνου σας ως οθόνη αφής και πληκτρολογίου", "Description[es]": "Usar teléfono como panel táctil y teclado", "Description[et]": "Telefoni kasutamine puutepadja ja klaviatuurina", "Description[eu]": "Erabili zure telefonoa touchpad eta teklatu gisa", "Description[fi]": "Käytä puhelintasi kosketuslevynä ja näppäimistönä", "Description[fr]": "Utilisez votre téléphone comme un pavé tactile et un clavier", "Description[gl]": "Usar o teléfono móbil como touchpad e teclado.", "Description[hu]": "A telefon használata érintőtáblaként és billentyűzetként", "Description[it]": "Usa il telefono come touchpad e tastiera", "Description[ko]": "휴대폰을 터치패드와 키보드로 사용", "Description[nl]": "Uw telefoon gebruiken als een touchpad en toetsenbord", "Description[nn]": "Bruk telefonen som styreplate og tastatur", "Description[pl]": "Używaj swojego telefonu jako gładzika i klawiatury", "Description[pt]": "Use o seu telefone como um rato e teclado por toque", "Description[pt_BR]": "Use seu telefone como um touchpad e teclado", "Description[ru]": "Использование телефона в качестве сенсорной панели и клавиатуры", "Description[sk]": "Použite váš telefón ako touchpad a klávesnicu", "Description[sr@ijekavian]": "Користите телефон као додирник и тастатуру", "Description[sr@ijekavianlatin]": "Koristite telefon kao dodirnik i tastaturu", "Description[sr@latin]": "Koristite telefon kao dodirnik i tastaturu", "Description[sr]": "Користите телефон као додирник и тастатуру", "Description[sv]": "Använd telefonen som mus och tangentbord", "Description[tr]": "Telefonunuzu dokunmatik yüzey ve klayve olarak kullanın", "Description[uk]": "Скористайтеся телефоном як замінником сенсорної панелі і клавіатури", "Description[x-test]": "xxUse your phone as a touchpad and keyboardxx", "Description[zh_CN]": "用您的手机作为触摸板和键盘", "Description[zh_TW]": "讓您的智慧型手機當作觸碰板與鍵盤", "EnabledByDefault": true, "Icon": "edit-select", "Id": "kdeconnect_mousepad", "License": "GPL", "Name": "Virtual input", - "Name[ar]": "دخل وهميّ", "Name[ca@valencia]": "Entrada virtual", "Name[ca]": "Entrada virtual", "Name[cs]": "Virtuální vstup", "Name[da]": "Virtuelt input", "Name[de]": "Virtuelle Eingabe", - "Name[el]": "Εικονικά στοιχεία εισόδου", "Name[es]": "Entrada virtual", "Name[et]": "Virtuaalsisestus", "Name[eu]": "Sarrera birtuala", "Name[fi]": "Virtuaalinen syöttö", "Name[fr]": "Entrée virtuelle", "Name[gl]": "Entrada virtual", "Name[hu]": "Virtuális bevitel", "Name[it]": "Inserimento virtuale", "Name[ko]": "가상 입력", "Name[nl]": "Virtuele invoer", "Name[nn]": "Virtuelt tastatur", "Name[pl]": "Wirtualna obsługa", "Name[pt]": "Entrada virtual", "Name[pt_BR]": "Entrada virtual", "Name[ru]": "Виртуальный ввод", "Name[sk]": "Virtuálny vstup", "Name[sr@ijekavian]": "Виртуелни унос", "Name[sr@ijekavianlatin]": "Virtuelni unos", "Name[sr@latin]": "Virtuelni unos", "Name[sr]": "Виртуелни унос", "Name[sv]": "Virtuell inmatning", "Name[tr]": "Sanal içe aktarma", "Name[uk]": "Віртуальне введення даних", "Name[x-test]": "xxVirtual inputxx", "Name[zh_CN]": "虚拟输入", "Name[zh_TW]": "虛擬輸入", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1" }, "X-KdeConnect-OutgoingPackageType": [], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.mousepad.request" ] } diff --git a/plugins/mousepad_windows/kdeconnect_mousepad.json b/plugins/mousepad_windows/kdeconnect_mousepad.json index b7b052eb..a9947eb8 100644 --- a/plugins/mousepad_windows/kdeconnect_mousepad.json +++ b/plugins/mousepad_windows/kdeconnect_mousepad.json @@ -1,97 +1,92 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "ahmedibrahimkhali@gmail.com", "Name": "Ahmed I. Khalil", - "Name[ar]": "أحمد إبراهيم خليل", "Name[sr@ijekavian]": "Ахмед И. Калил", "Name[sr@ijekavianlatin]": "Ahmed I. Kalil", "Name[sr@latin]": "Ahmed I. Kalil", "Name[sr]": "Ахмед И. Калил", "Name[x-test]": "xxAhmed I. Khalilxx" } ], "Description": "Use your phone as a touchpad and keyboard", - "Description[ar]": "استخدم الهاتف كفأرة ولوحة مفاتيح", "Description[ca@valencia]": "Empra el telèfon com un ratolí tàctil i teclat", "Description[ca]": "Empra el telèfon com un ratolí tàctil i teclat", "Description[cs]": "Používejte svůj telefon jako touchpad a klávesnici", "Description[da]": "Brug din telefon som touchpad og tastatur", "Description[de]": "Verwendet Ihr Handy als Touchpad und Tastatur", - "Description[el]": "Χρήση του τηλεφώνου σας ως οθόνη αφής και πληκτρολογίου", "Description[es]": "Usar teléfono como panel táctil y teclado", "Description[et]": "Telefoni kasutamine puutepadja ja klaviatuurina", "Description[eu]": "Erabili zure telefonoa touchpad eta teklatu gisa", "Description[fi]": "Käytä puhelintasi kosketuslevynä ja näppäimistönä", "Description[fr]": "Utilisez votre téléphone comme un pavé tactile et un clavier", "Description[gl]": "Usar o teléfono móbil como touchpad e teclado.", "Description[hu]": "A telefon használata érintőtáblaként és billentyűzetként", "Description[it]": "Usa il telefono come touchpad e tastiera", "Description[ko]": "휴대폰을 터치패드와 키보드로 사용", "Description[nl]": "Uw telefoon gebruiken als een touchpad en toetsenbord", "Description[nn]": "Bruk telefonen som styreplate og tastatur", "Description[pl]": "Używaj swojego telefonu jako gładzika i klawiatury", "Description[pt]": "Use o seu telefone como um rato e teclado por toque", "Description[pt_BR]": "Use seu telefone como um touchpad e teclado", "Description[ru]": "Использование телефона в качестве сенсорной панели и клавиатуры", "Description[sk]": "Použite váš telefón ako touchpad a klávesnicu", "Description[sr@ijekavian]": "Користите телефон као додирник и тастатуру", "Description[sr@ijekavianlatin]": "Koristite telefon kao dodirnik i tastaturu", "Description[sr@latin]": "Koristite telefon kao dodirnik i tastaturu", "Description[sr]": "Користите телефон као додирник и тастатуру", "Description[sv]": "Använd telefonen som mus och tangentbord", "Description[tr]": "Telefonunuzu dokunmatik yüzey ve klayve olarak kullanın", "Description[uk]": "Скористайтеся телефоном як замінником сенсорної панелі і клавіатури", "Description[x-test]": "xxUse your phone as a touchpad and keyboardxx", "Description[zh_CN]": "用您的手机作为触摸板和键盘", "Description[zh_TW]": "讓您的智慧型手機當作觸碰板與鍵盤", "EnabledByDefault": true, "Icon": "edit-select", "Id": "kdeconnect_mousepad", "License": "GPL", "Name": "Virtual input", - "Name[ar]": "دخل وهميّ", "Name[ca@valencia]": "Entrada virtual", "Name[ca]": "Entrada virtual", "Name[cs]": "Virtuální vstup", "Name[da]": "Virtuelt input", "Name[de]": "Virtuelle Eingabe", - "Name[el]": "Εικονικά στοιχεία εισόδου", "Name[es]": "Entrada virtual", "Name[et]": "Virtuaalsisestus", "Name[eu]": "Sarrera birtuala", "Name[fi]": "Virtuaalinen syöttö", "Name[fr]": "Entrée virtuelle", "Name[gl]": "Entrada virtual", "Name[hu]": "Virtuális bevitel", "Name[it]": "Inserimento virtuale", "Name[ko]": "가상 입력", "Name[nl]": "Virtuele invoer", "Name[nn]": "Virtuelt tastatur", "Name[pl]": "Wirtualna obsługa", "Name[pt]": "Entrada virtual", "Name[pt_BR]": "Entrada virtual", "Name[ru]": "Виртуальный ввод", "Name[sk]": "Virtuálny vstup", "Name[sr@ijekavian]": "Виртуелни унос", "Name[sr@ijekavianlatin]": "Virtuelni unos", "Name[sr@latin]": "Virtuelni unos", "Name[sr]": "Виртуелни унос", "Name[sv]": "Virtuell inmatning", "Name[tr]": "Sanal içe aktarma", "Name[uk]": "Віртуальне введення даних", "Name[x-test]": "xxVirtual inputxx", "Name[zh_CN]": "虚拟输入", "Name[zh_TW]": "虛擬輸入", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1" }, "X-KdeConnect-OutgoingPackageType": [], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.mousepad.request" ] } diff --git a/plugins/mpriscontrol/kdeconnect_mpriscontrol.json b/plugins/mpriscontrol/kdeconnect_mpriscontrol.json index d846f0a0..03a9d65b 100644 --- a/plugins/mpriscontrol/kdeconnect_mpriscontrol.json +++ b/plugins/mpriscontrol/kdeconnect_mpriscontrol.json @@ -1,99 +1,95 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "albertvaka@gmail.com", "Name": "Albert Vaca", "Name[sr@ijekavian]": "Алберт Вака Синтора", "Name[sr@ijekavianlatin]": "Albert Vaka Sintora", "Name[sr@latin]": "Albert Vaka Sintora", "Name[sr]": "Алберт Вака Синтора", "Name[x-test]": "xxAlbert Vacaxx" } ], "Description": "Remote control your music and videos", - "Description[ar]": "تحكّم بالموسيقى والفيديو عن بعد", "Description[ca@valencia]": "Comandament a distància per a la vostra música i vídeos", "Description[ca]": "Comandament a distància per a la vostra música i vídeos", "Description[cs]": "Ovládejte vzdáleně vaši hudbu a videa", "Description[da]": "Fjernbetjen din musik og videoer", "Description[de]": "Fernbedienung für Musik und Videos", - "Description[el]": "Απομακρυσμένος έλεγχος της μουσικής σας και των βίντεο", "Description[es]": "Controlar remotamente vídeos y música", "Description[et]": "Oma muusika ja videote kaugjuhtimine", "Description[eu]": "Kontrolatu urrunetik zure musika eta bideoak", "Description[fi]": "Kauko-ohjain musiikkiisi ja videoihisi", "Description[fr]": "Contrôlez à distance votre musique et vos vidéos", "Description[gl]": "Use o teléfono móbil como mando a distancia para música e vídeos.", "Description[hu]": "A zene- és videolejátszás irányítása távolról", "Description[it]": "Controlla da remoto la tua musica e i video", "Description[ko]": "음악과 동영상 원격 제어", "Description[nl]": "Op afstand bedienen van uw muziek en video's", "Description[nn]": "Fjernkontroller musikk og video", "Description[pl]": "Steruj zdalnie swoją muzyką i filmami", "Description[pt]": "Comandar à distância a sua música e vídeos", "Description[pt_BR]": "Controle suas músicas e vídeos remotamente", "Description[ru]": "Удалённое управление воспроизведением музыки и видео", "Description[sk]": "Vzdialene ovládať vašu hudbu a videá", "Description[sr@ijekavian]": "Даљински контролишите вашу музику и видео", "Description[sr@ijekavianlatin]": "Daljinski kontrolišite vašu muziku i video", "Description[sr@latin]": "Daljinski kontrolišite vašu muziku i video", "Description[sr]": "Даљински контролишите вашу музику и видео", "Description[sv]": "Fjärrstyr musik och videor", "Description[tr]": "Müzik ve videonuzu uzaktan kontrol edin", "Description[uk]": "Віддалене керування відтворенням музики та відео", "Description[x-test]": "xxRemote control your music and videosxx", "Description[zh_CN]": "远程控制您的音乐和视频", "Description[zh_TW]": "遠端控制您的音樂與影片", "EnabledByDefault": true, "Icon": "media-playback-start", "Id": "kdeconnect_mpriscontrol", "License": "GPL", "Name": "Multimedia control receiver", - "Name[ar]": "مستقبل تحكّمات الوسائط المتعدّدة", "Name[ca@valencia]": "Receptor del comandament multimèdia", "Name[ca]": "Receptor del comandament multimèdia", "Name[cs]": "Dálkový ovladač multimédií", - "Name[da]": "Modtager til multimediekontrol", + "Name[da]": "Multimediekontrol-modtager", "Name[de]": "Steuerung für Multimedia-Empfänger", - "Name[el]": "Δέκτης ελέγχου πολυμέσων", "Name[es]": "Receptor de control multimedia", "Name[et]": "Multimeedia juhtimine", "Name[eu]": "Multimedia-kontroladore hartzailea", "Name[fi]": "Multimediakauko-ohjain", "Name[fr]": "Receveur de contrôle multimédia", "Name[gl]": "Receptor de controis multimedia", "Name[hu]": "Multimédiavezérlő", "Name[it]": "Ricevitore di controllo multimediale", "Name[ko]": "멀티미디어 제어 수신기", "Name[nl]": "Ontvanger van bediening voor multimedia", "Name[nn]": "Mediefjernkontroll", "Name[pl]": "Odbiornik sterowania multimediami", "Name[pt]": "Receptor de controlo multimédia", "Name[pt_BR]": "Receptor de controle multimídia", "Name[ru]": "Управление мультимедиа", "Name[sk]": "Prijímač ovládania multimédií", "Name[sr@ijekavian]": "Мултимедијалне контроле", "Name[sr@ijekavianlatin]": "Multimedijalne kontrole", "Name[sr@latin]": "Multimedijalne kontrole", "Name[sr]": "Мултимедијалне контроле", "Name[sv]": "Mottagare av multimediastyrning", "Name[tr]": "Çokluortam kontrol alıcısı", "Name[uk]": "Отримувач команд щодо керування мультимедійними функціями", "Name[x-test]": "xxMultimedia control receiverxx", "Name[zh_CN]": "多媒体控制接收器", "Name[zh_TW]": "多媒體控制接收器", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.mpris" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.mpris.request" ] } diff --git a/plugins/mpriscontrol/mpriscontrolplugin.cpp b/plugins/mpriscontrol/mpriscontrolplugin.cpp index 3a85a287..02b45101 100644 --- a/plugins/mpriscontrol/mpriscontrolplugin.cpp +++ b/plugins/mpriscontrol/mpriscontrolplugin.cpp @@ -1,285 +1,291 @@ /** * 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 >(); ) Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_MPRIS, "kdeconnect.plugin.mpris") MprisControlPlugin::MprisControlPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , prevVolume(-1) { m_watcher = new QDBusServiceWatcher(QString(), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this); // TODO: QDBusConnectionInterface::serviceOwnerChanged is deprecated, maybe query org.freedesktop.DBus directly? connect(QDBusConnection::sessionBus().interface(), &QDBusConnectionInterface::serviceOwnerChanged, this, &MprisControlPlugin::serviceOwnerChanged); //Add existing interfaces const QStringList services = QDBusConnection::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) { QDBusInterface mprisInterface(service, QStringLiteral("/org/mpris/MediaPlayer2"), 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")); } - playerList[identity] = service; - qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Mpris addPlayer" << service << "->" << identity; + + QString uniqueName = identity; + for (int i = 1 ; !playerList[uniqueName].isEmpty() ; i++) { + uniqueName = identity + " [" + i + "]"; + } + + playerList[uniqueName] = service; + qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Mpris addPlayer" << service << "->" << uniqueName; sendPlayerList(); OrgFreedesktopDBusPropertiesInterface* freedesktopInterface = new OrgFreedesktopDBusPropertiesInterface(service, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus(), this); connect(freedesktopInterface, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, this, &MprisControlPlugin::propertiesChanged); OrgMprisMediaPlayer2PlayerInterface* mprisInterface0 = new OrgMprisMediaPlayer2PlayerInterface(service, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus()); connect(mprisInterface0, &OrgMprisMediaPlayer2PlayerInterface::Seeked, this, &MprisControlPlugin::seeked); } void MprisControlPlugin::seeked(qlonglong position){ //qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Seeked in player"; OrgFreedesktopDBusPropertiesInterface* interface = (OrgFreedesktopDBusPropertiesInterface*)sender(); const QString& service = interface->service(); const QString& player = playerList.key(service); NetworkPackage np(PACKAGE_TYPE_MPRIS, { {"pos", position/1000}, //Send milis instead of nanos {"player", player} }); sendPackage(np); } void MprisControlPlugin::propertiesChanged(const QString& propertyInterface, const QVariantMap& properties) { Q_UNUSED(propertyInterface); NetworkPackage np(PACKAGE_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; if (nowPlayingMap.contains(QStringLiteral("xesam:title"))) { QString nowPlaying = nowPlayingMap[QStringLiteral("xesam:title")].toString(); if (nowPlayingMap.contains(QStringLiteral("xesam:artist"))) { nowPlaying = nowPlayingMap[QStringLiteral("xesam:artist")].toString() + " - " + nowPlaying; } np.set(QStringLiteral("nowPlaying"),nowPlaying); somethingToSend = true; } if (nowPlayingMap.contains(QStringLiteral("mpris:length"))) { if (nowPlayingMap.contains(QStringLiteral("mpris:length"))) { long long length = nowPlayingMap[QStringLiteral("mpris:length")].toLongLong(); np.set(QStringLiteral("length"),length/1000); //milis to nanos } 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) { OrgFreedesktopDBusPropertiesInterface* interface = (OrgFreedesktopDBusPropertiesInterface*)sender(); const QString& service = interface->service(); const QString& player = playerList.key(service); np.set(QStringLiteral("player"), player); // Always also update the position OrgMprisMediaPlayer2PlayerInterface mprisInterface(service, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus()); if (mprisInterface.canSeek()) { long long pos = mprisInterface.position(); np.set(QStringLiteral("pos"), pos/1000); //Send milis instead of nanos } sendPackage(np); } } void MprisControlPlugin::removePlayer(const QString& ifaceName) { const QString identity = playerList.key(ifaceName); qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Mpris removePlayer" << ifaceName << "->" << identity; playerList.remove(identity); sendPlayerList(); } bool MprisControlPlugin::receivePackage (const NetworkPackage& 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 = playerList.contains(player); if (!valid_player || np.get(QStringLiteral("requestPlayerList"))) { sendPlayerList(); if (!valid_player) { return true; } } //Do something to the mpris interface OrgMprisMediaPlayer2PlayerInterface mprisInterface(playerList[player], QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus()); mprisInterface.setTimeout(500); if (np.has(QStringLiteral("action"))) { const QString& action = np.get(QStringLiteral("action")); //qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Calling action" << action << "in" << playerList[player]; //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" << playerList[player]; mprisInterface.setVolume(volume); } if (np.has(QStringLiteral("Seek"))) { int offset = np.get(QStringLiteral("Seek")); //qCDebug(KDECONNECT_PLUGIN_MPRIS) << "Seeking" << offset << "to" << playerList[player]; 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" << playerList[player]; mprisInterface.Seek(seek); } //Send something read from the mpris interface NetworkPackage answer(PACKAGE_TYPE_MPRIS); bool somethingToSend = false; if (np.get(QStringLiteral("requestNowPlaying"))) { QVariantMap nowPlayingMap = mprisInterface.metadata(); QString nowPlaying = nowPlayingMap[QStringLiteral("xesam:title")].toString(); if (nowPlayingMap.contains(QStringLiteral("xesam:artist"))) { nowPlaying = nowPlayingMap[QStringLiteral("xesam:artist")].toString() + " - " + nowPlaying; } answer.set(QStringLiteral("nowPlaying"),nowPlaying); if (nowPlayingMap.contains(QStringLiteral("mpris:length"))) { qlonglong length = nowPlayingMap[QStringLiteral("mpris:length")].toLongLong(); answer.set(QStringLiteral("length"),length/1000); } 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); sendPackage(answer); } return true; } void MprisControlPlugin::sendPlayerList() { NetworkPackage np(PACKAGE_TYPE_MPRIS); np.set(QStringLiteral("playerList"),playerList.keys()); sendPackage(np); } #include "mpriscontrolplugin.moc" diff --git a/plugins/mprisremote/kdeconnect_mprisremote.json b/plugins/mprisremote/kdeconnect_mprisremote.json index b286bcf5..48039200 100644 --- a/plugins/mprisremote/kdeconnect_mprisremote.json +++ b/plugins/mprisremote/kdeconnect_mprisremote.json @@ -1,79 +1,76 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "aleixpol@kde.org", "Name": "Aleix Pol", "Name[sr@ijekavian]": "Алекс Пол Гонзалез", "Name[sr@ijekavianlatin]": "Aleks Pol Gonzalez", "Name[sr@latin]": "Aleks Pol Gonzalez", "Name[sr]": "Алекс Пол Гонзалез", "Name[x-test]": "xxAleix Polxx" } ], "Description": "Control MPRIS services", - "Description[ar]": "تحكّم بخدمات MPRIS", "Description[ca@valencia]": "Serveis de control del MPRIS", "Description[ca]": "Serveis de control del MPRIS", "Description[cs]": "Ovládejte služby MPRIS", "Description[da]": "Kontrollér MPRIS-tjenester", "Description[de]": "Steuerung von MPRIS-Diensten", - "Description[el]": "Έλεγχος υπηρεσιών MPRIS", "Description[es]": "Controlar los servicios MPRIS", "Description[et]": "MPRIS-teenuste juhtimine", "Description[eu]": "Kontrolatu MPRIS zerbitzuak", "Description[fi]": "Ohjaa MPRIS-palveluita", "Description[fr]": "Controllez les services MPRIS", "Description[gl]": "Controle servizos de MPRIS.", "Description[it]": "Servizi di controllo MPRIS", "Description[ko]": "MPRIS 서비스 제어", "Description[nl]": "MPRIS-services besturen", "Description[nn]": "Kontroller MPRIS-tenester", "Description[pl]": "Sterowanie usługami MPRIS", "Description[pt]": "Controlar os serviços MPRIS", "Description[pt_BR]": "Controle dos serviços MPRIS", "Description[ru]": "Управление службами MPRIS", "Description[sk]": "Ovládať MPRIS služby", "Description[sr@ijekavian]": "Контрола МПРИС сервиса", "Description[sr@ijekavianlatin]": "Kontrola MPRIS servisa", "Description[sr@latin]": "Kontrola MPRIS servisa", "Description[sr]": "Контрола МПРИС сервиса", "Description[sv]": "Styr MPRIS-tjänster", "Description[tr]": "MPRIS servislerini kontrol et", "Description[uk]": "Керування службами MPRIS", "Description[x-test]": "xxControl MPRIS servicesxx", "Description[zh_CN]": "控制 MPRIS 服务", "Description[zh_TW]": "控制 MPRIS 服務", "EnabledByDefault": true, "Icon": "applications-multimedia", "Id": "kdeconnect_mprisremote", "License": "GPL", "Name": "MprisRemote", - "Name[ar]": "‏Mpris عن بعد", "Name[et]": "Kaug-Mpris", "Name[fi]": "MPRIS-kauko-ohjain", "Name[nn]": "MPRIS-fjernkontroll", "Name[pl]": "PilotMPRIS", "Name[pt]": "Comando MPRIS", "Name[ru]": "Удалённое управление MPRIS", "Name[sr@ijekavian]": "МПРИС даљински", "Name[sr@ijekavianlatin]": "MPRIS daljinski", "Name[sr@latin]": "MPRIS daljinski", "Name[sr]": "МПРИС даљински", "Name[sv]": "MPRIS-fjärrkontroll", "Name[x-test]": "xxMprisRemotexx", "Name[zh_CN]": "远程 Mpris", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "https://kde.org" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.mpris.request" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.mpris" ] } diff --git a/plugins/notifications/CMakeLists.txt b/plugins/notifications/CMakeLists.txt index a3932a4b..86f962c5 100644 --- a/plugins/notifications/CMakeLists.txt +++ b/plugins/notifications/CMakeLists.txt @@ -1,18 +1,20 @@ find_package(KF5 REQUIRED COMPONENTS Notifications KCMUtils I18n IconThemes Config) set(kdeconnect_notifications_SRCS notification.cpp notificationsplugin.cpp notificationsdbusinterface.cpp sendreplydialog.cpp ) +ki18n_wrap_ui(kdeconnect_notifications_SRCS sendreplydialog.ui) + kdeconnect_add_plugin(kdeconnect_notifications JSON kdeconnect_notifications.json SOURCES ${kdeconnect_notifications_SRCS}) target_link_libraries(kdeconnect_notifications kdeconnectcore Qt5::DBus KF5::Notifications KF5::I18n KF5::IconThemes ) diff --git a/plugins/notifications/kdeconnect_notifications.json b/plugins/notifications/kdeconnect_notifications.json index 56e79427..936c66b9 100644 --- a/plugins/notifications/kdeconnect_notifications.json +++ b/plugins/notifications/kdeconnect_notifications.json @@ -1,98 +1,92 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "albertvaka@gmail.com", "Name": "Albert Vaca", "Name[sr@ijekavian]": "Алберт Вака Синтора", "Name[sr@ijekavianlatin]": "Albert Vaka Sintora", "Name[sr@latin]": "Albert Vaka Sintora", "Name[sr]": "Алберт Вака Синтора", "Name[x-test]": "xxAlbert Vacaxx" } ], "Description": "Show device's notifications on this computer and keep them in sync", - "Description[ar]": "أظهر إخطارات الجهاز على هذا الحاسوب وأبقها متزامنة", "Description[ca@valencia]": "Mostra les notificacions del dispositiu a l'ordinador i les manté sincronitzades", "Description[ca]": "Mostra les notificacions del dispositiu a l'ordinador i les manté sincronitzades", "Description[cs]": "Zobrazit upozornění telefonu v počítači a udržovat je synchronizovaná", "Description[da]": "Vis enhedens bekendtgørelser på denne computer og hold dem synkroniseret", "Description[de]": "Benachrichtigungen des Geräts auf diesem Rechner anzeigen und abgleichen", - "Description[el]": "Εμφάνιση ειδοποιήσεων συσκευής στον υπολογιστή αυτόν και συγχρονισμός τους", "Description[es]": "Mostrar notificaciones del dispositivo en este equipo y mantenerlas en sincronía", "Description[et]": "Seadme märguannete näitamine arvutis ja nende sünkroonis hoidmine", "Description[eu]": "Erakutsi gailuaren jakinarazpenak ordenagailu honetan eta mantendu sinkronizatuta", "Description[fi]": "Näytä laitteen ilmoitukset tällä tietokoneella ja pidä ne ajan tasalla", "Description[fr]": "Affichez les notifications du téléphone sur l'ordinateur et synchronisez-les", - "Description[gl]": "Mostrar as notificacións do dispositivo neste computador e mantelas sincronizadas.", "Description[it]": "Mostra le notifiche del telefono sul tuo computer e tienile sincronizzate", "Description[ko]": "휴대폰 알림을 컴퓨터에 표시하고 동기화하기", "Description[nl]": "Apparaatmeldingen op deze computer tonen en ze gesynchroniseerd houden", "Description[nn]": "Vis telefonvarslingar på datamaskina og hald dei synkronisert", "Description[pl]": "Pokaż powiadomienia urządzenia na swoim komputerze i synchronizuj je", "Description[pt]": "Mostrar as notificações do dispositivo neste computador e mantê-las sincronizadas", "Description[pt_BR]": "Mostra as notificações do aparelho neste computador e as mantém sincronizadas", "Description[ru]": "Показ уведомлений с устройства на компьютере и их синхронизация", "Description[sk]": "Zobraziť oznámenia telefónu na vašom počítači a udržať ich synchronizované", "Description[sr@ijekavian]": "Приказује обавештења са уређаја на рачунару и одржава их ажурним", "Description[sr@ijekavianlatin]": "Prikazuje obaveštenja sa uređaja na računaru i održava ih ažurnim", "Description[sr@latin]": "Prikazuje obaveštenja sa uređaja na računaru i održava ih ažurnim", "Description[sr]": "Приказује обавештења са уређаја на рачунару и одржава их ажурним", "Description[sv]": "Visa enhetens underrättelser på datorn och håll dem synkroniserade", "Description[tr]": "Aygıtın bildirimlerini bilgisayarda göster ve eşzamanlı tut", "Description[uk]": "Показ сповіщень з пристрою на цьому комп’ютері та підтримання синхронізації даних сповіщень", "Description[x-test]": "xxShow device's notifications on this computer and keep them in syncxx", "Description[zh_CN]": "在电脑显示手机通知并保持同步", "Description[zh_TW]": "在電腦上顯示裝置通知並且保持同步", "EnabledByDefault": true, "Icon": "preferences-desktop-notification", "Id": "kdeconnect_notifications", "License": "GPL", "Name": "Receive notifications", - "Name[ar]": "استقبل الإخطارات", "Name[ca@valencia]": "Recepció de les notificacions", "Name[ca]": "Recepció de les notificacions", "Name[cs]": "Přijímat oznámení", "Name[da]": "Modtag bekendtgørelser", "Name[de]": "Benachrichtigungen empfangen", - "Name[el]": "Λήψη ειδοποιήσεων", "Name[es]": "Recibir notificaciones", "Name[et]": "Märguannete vastuvõtmine", "Name[eu]": "Jaso jakinarazpenak", "Name[fi]": "Vastaanota ilmoituksia", "Name[fr]": "Recevoir les notifications", - "Name[gl]": "Recibir notificacións", "Name[it]": "Ricevi notifiche", "Name[ko]": "알림 받기", "Name[nl]": "Meldingen ontvangen", "Name[nn]": "Få varslingar", "Name[pl]": "Otrzymuj powiadomienia", "Name[pt]": "Receber as notificações", "Name[pt_BR]": "Receber notificações", "Name[ru]": "Получение уведомлений", "Name[sk]": "Prijať upozornenia", "Name[sr@ijekavian]": "Пријем обавештења", "Name[sr@ijekavianlatin]": "Prijem obaveštenja", "Name[sr@latin]": "Prijem obaveštenja", "Name[sr]": "Пријем обавештења", "Name[sv]": "Ta emot underrättelser", "Name[tr]": "Bildirimleri al", "Name[uk]": "Отримати сповіщення", "Name[x-test]": "xxReceive notificationsxx", "Name[zh_CN]": "接收通知", "Name[zh_TW]": "收到通知", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.notification.request", "kdeconnect.notification.reply" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.notification" ] } diff --git a/plugins/notifications/notificationsdbusinterface.cpp b/plugins/notifications/notificationsdbusinterface.cpp index ed078da4..0da4ef79 100644 --- a/plugins/notifications/notificationsdbusinterface.cpp +++ b/plugins/notifications/notificationsdbusinterface.cpp @@ -1,176 +1,177 @@ /** * 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 "notificationsdbusinterface.h" #include "notification_debug.h" #include "notification.h" #include #include #include #include "notificationsplugin.h" #include "sendreplydialog.h" NotificationsDbusInterface::NotificationsDbusInterface(KdeConnectPlugin* plugin) : QDBusAbstractAdaptor(const_cast(plugin->device())) , m_device(plugin->device()) , m_plugin(plugin) , m_lastId(0) { } NotificationsDbusInterface::~NotificationsDbusInterface() { qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Destroying NotificationsDbusInterface"; } void NotificationsDbusInterface::clearNotifications() { qDeleteAll(m_notifications); m_notifications.clear(); Q_EMIT allNotificationsRemoved(); } QStringList NotificationsDbusInterface::activeNotifications() { return m_notifications.keys(); } void NotificationsDbusInterface::processPackage(const NetworkPackage& np) { if (np.get(QStringLiteral("isCancel"))) { QString id = np.get(QStringLiteral("id")); // cut off kdeconnect-android's prefix if there: if (id.startsWith(QLatin1String("org.kde.kdeconnect_tp::"))) id = id.mid(id.indexOf(QLatin1String("::")) + 2); removeNotification(id); } else if (np.get(QStringLiteral("isRequest"))) { for (const auto& n : qAsConst(m_notifications)) { NetworkPackage np(PACKAGE_TYPE_NOTIFICATION_REQUEST, { {"id", n->internalId()}, {"appName", n->appName()}, {"ticker", n->ticker()}, {"isClearable", n->dismissable()}, {"requestAnswer", true} }); m_plugin->sendPackage(np); } } else if(np.get(QStringLiteral("requestAnswer"), false)) { } else { QString id = np.get(QStringLiteral("id")); if (!m_internalIdToPublicId.contains(id)) { Notification* noti = new Notification(np, this); addNotification(noti); } else { QString pubId = m_internalIdToPublicId[id]; m_notifications[pubId]->update(np); } } } void NotificationsDbusInterface::addNotification(Notification* noti) { const QString& internalId = noti->internalId(); if (m_internalIdToPublicId.contains(internalId)) { removeNotification(internalId); } //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "addNotification" << internalId; connect(noti, &Notification::dismissRequested, this, &NotificationsDbusInterface::dismissRequested); connect(noti, &Notification::replyRequested, this, [this,noti]{ replyRequested(noti); }); const QString& publicId = newId(); m_notifications[publicId] = noti; m_internalIdToPublicId[internalId] = publicId; QDBusConnection::sessionBus().registerObject(m_device->dbusPath()+"/notifications/"+publicId, noti, QDBusConnection::ExportScriptableContents); Q_EMIT notificationPosted(publicId); } void NotificationsDbusInterface::removeNotification(const QString& internalId) { //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "removeNotification" << internalId; if (!m_internalIdToPublicId.contains(internalId)) { qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by internal Id: " << internalId; return; } QString publicId = m_internalIdToPublicId.take(internalId); Notification* noti = m_notifications.take(publicId); if (!noti) { qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by public Id: " << publicId; return; } //Deleting the notification will unregister it automatically //QDBusConnection::sessionBus().unregisterObject(mDevice->dbusPath()+"/notifications/"+publicId); noti->deleteLater(); Q_EMIT notificationRemoved(publicId); } void NotificationsDbusInterface::dismissRequested(const QString& internalId) { NetworkPackage np(PACKAGE_TYPE_NOTIFICATION_REQUEST); np.set(QStringLiteral("cancel"), internalId); m_plugin->sendPackage(np); //Workaround: we erase notifications without waiting a repsonse from the //phone because we won't receive a response if we are out of sync and this //notification no longer exists. Ideally, each time we reach the phone //after some time disconnected we should re-sync all the notifications. removeNotification(internalId); } void NotificationsDbusInterface::replyRequested(Notification* noti) { QString replyId = noti->replyId(); QString appName = noti->appName(); QString originalMessage = noti->ticker(); SendReplyDialog* dialog = new SendReplyDialog(originalMessage, replyId, appName); connect(dialog, &SendReplyDialog::sendReply, this, &NotificationsDbusInterface::sendReply); dialog->show(); + dialog->raise(); } void NotificationsDbusInterface::sendReply(const QString& replyId, const QString& message) { NetworkPackage np(PACKAGE_TYPE_NOTIFICATION_REPLY); np.set(QStringLiteral("requestReplyId"), replyId); np.set(QStringLiteral("message"), message); m_plugin->sendPackage(np); } QString NotificationsDbusInterface::newId() { return QString::number(++m_lastId); } diff --git a/plugins/notifications/sendreplydialog.cpp b/plugins/notifications/sendreplydialog.cpp index ca883d76..28e82ccd 100644 --- a/plugins/notifications/sendreplydialog.cpp +++ b/plugins/notifications/sendreplydialog.cpp @@ -1,64 +1,60 @@ /** * Copyright 2015 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 "sendreplydialog.h" #include #include #include #include #include +#include "ui_sendreplydialog.h" + SendReplyDialog::SendReplyDialog(const QString& originalMessage, const QString& replyId, const QString& topicName, QWidget* parent) : QDialog(parent) , m_replyId(replyId) + , m_ui(new Ui::SendReplyDialog) { - QVBoxLayout* layout = new QVBoxLayout; - - QTextEdit* textView = new QTextEdit(this); - textView->setReadOnly(true); - textView->setText(topicName + ": \n" + originalMessage); - layout->addWidget(textView); - - m_textEdit = new QTextEdit(this); - layout->addWidget(m_textEdit); + m_ui->setupUi(this); + m_ui->textView->setText(topicName + ": \n" + originalMessage); - QPushButton* sendButton = new QPushButton(i18n("Send"), this); - connect(sendButton, &QAbstractButton::clicked, this, &SendReplyDialog::sendButtonClicked); - layout->addWidget(sendButton); + auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok); + button->setText(i18n("Send")); - setLayout(layout); + connect(this, &QDialog::accepted, this, &SendReplyDialog::sendButtonClicked); setWindowTitle(topicName); setWindowIcon(QIcon::fromTheme(QStringLiteral("kdeconnect"))); setAttribute(Qt::WA_DeleteOnClose); } +SendReplyDialog::~SendReplyDialog() = default; void SendReplyDialog::sendButtonClicked() { - Q_EMIT sendReply(m_replyId, m_textEdit->toPlainText()); + Q_EMIT sendReply(m_replyId, m_ui->replyEdit->toPlainText()); close(); } QSize SendReplyDialog::sizeHint() const { return QSize(512, 64); } diff --git a/plugins/notifications/sendreplydialog.h b/plugins/notifications/sendreplydialog.h index 5880d879..2e0e81d3 100644 --- a/plugins/notifications/sendreplydialog.h +++ b/plugins/notifications/sendreplydialog.h @@ -1,50 +1,50 @@ /** * Copyright 2015 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 . */ #ifndef SENDREPLYDIALOG_H #define SENDREPLYDIALOG_H #include #include -class QTextEdit; -class QLineEdit; -class QPushButton; +namespace Ui { class SendReplyDialog; } class SendReplyDialog : public QDialog { Q_OBJECT public: explicit SendReplyDialog(const QString& originalMessage, const QString& replyId, const QString& topicName, QWidget* parent = nullptr); + ~SendReplyDialog() override; + QSize sizeHint() const override; private Q_SLOTS: void sendButtonClicked(); Q_SIGNALS: void sendReply(const QString& replyId, const QString& messageBody); private: - QString m_replyId; - QTextEdit* m_textEdit; + const QString m_replyId; + const QScopedPointer m_ui; }; #endif diff --git a/plugins/notifications/sendreplydialog.ui b/plugins/notifications/sendreplydialog.ui new file mode 100644 index 00000000..07db50b4 --- /dev/null +++ b/plugins/notifications/sendreplydialog.ui @@ -0,0 +1,74 @@ + + + SendReplyDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + Qt::NoFocus + + + true + + + + + + + + + + QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + SendReplyDialog + accept() + + + 82 + 274 + + + 2 + 279 + + + + + buttonBox + rejected() + SendReplyDialog + reject() + + + 149 + 284 + + + 143 + 298 + + + + + diff --git a/plugins/pausemusic/kdeconnect_pausemusic.json b/plugins/pausemusic/kdeconnect_pausemusic.json index 338135bf..cd00ba72 100644 --- a/plugins/pausemusic/kdeconnect_pausemusic.json +++ b/plugins/pausemusic/kdeconnect_pausemusic.json @@ -1,96 +1,92 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "albertvaka@gmail.com", "Name": "Albert Vaca", "Name[sr@ijekavian]": "Алберт Вака Синтора", "Name[sr@ijekavianlatin]": "Albert Vaka Sintora", "Name[sr@latin]": "Albert Vaka Sintora", "Name[sr]": "Алберт Вака Синтора", "Name[x-test]": "xxAlbert Vacaxx" } ], "Description": "Pause music/videos during a phone call", - "Description[ar]": "ألبث الموسيقى/الفيديو أثناء المكالمات الهاتفيّة", "Description[ca@valencia]": "Pausa la música/vídeos durant una trucada telefònica", "Description[ca]": "Pausa la música/vídeos durant una trucada telefònica", "Description[cs]": "Pozastavit hudbu/video během telefonátu", - "Description[da]": "Sæt musik/videoer på pause under opkald", + "Description[da]": "Sæt musik/video på pause under telefonsamtaler", "Description[de]": "Hält Musik oder Videos während eines Anrufs an", - "Description[el]": "Παύση μουσικής/βίντεο κατά τη διάρκεια κλήσης", "Description[es]": "Pausar música/video durante las llamadas telefónicas", "Description[et]": "Muusika või video peatamine telefonikõne ajal", "Description[eu]": "Pausatu musika / bideoak deietan", "Description[fi]": "Keskeytä musiikki ja videot puhelun aikana", "Description[fr]": "Mettre en pause la musique / les vidéos pendant un appel téléphonique", "Description[gl]": "Deter a reprodución de música ou vídeos durante as chamadas.", "Description[hu]": "A médialejátszás szüneteltetése telefonhívások közben", "Description[it]": "Sospendi musica/video durante una chiamata", "Description[ko]": "휴대폰 통화 중 음악/동영상 일시 정지", "Description[nl]": "Muziek/video's pauzeren tijdens een telefoongesprek", "Description[nn]": "Set avspeling på pause ved oppringingar", "Description[pl]": "Wstrzymaj muzykę/film przy dzwonieniu", "Description[pt]": "Pausar a música/vídeos durante uma chamada telefónica", "Description[pt_BR]": "Pausa a música/vídeo durante uma chamada", "Description[ru]": "Приостановка воспроизведения музыки и видео во время телефонного звонка", "Description[sk]": "Pozastaviť hudbu/videá počas telefónneho hovoru", "Description[sr@ijekavian]": "Паузира музику или видео током телефонског позива", "Description[sr@ijekavianlatin]": "Pauzira muziku ili video tokom telefonskog poziva", "Description[sr@latin]": "Pauzira muziku ili video tokom telefonskog poziva", "Description[sr]": "Паузира музику или видео током телефонског позива", "Description[sv]": "Pausa musik eller videor under ett telefonsamtal", "Description[tr]": "Bir telefon çağrısı sırasında müzik/videoları duraklat", "Description[uk]": "Призупинка відтворення музики і відео на час телефонних дзвінків", "Description[x-test]": "xxPause music/videos during a phone callxx", "Description[zh_CN]": "手机来电时暂停音乐/视频", "Description[zh_TW]": "在通話過程中暫停音樂與影片", "EnabledByDefault": true, "Icon": "media-playback-pause", "Id": "kdeconnect_pausemusic", "License": "GPL", "Name": "Pause media during calls", - "Name[ar]": "ألبث الوسائط أثناء المكالمات", "Name[ca@valencia]": "Pausa els suports durant les trucades", "Name[ca]": "Pausa els suports durant les trucades", "Name[cs]": "Pozastavit média během telefonátu", "Name[da]": "Sæt medier på pause under opkald", "Name[de]": "Medium bei Anrufen anhalten", - "Name[el]": "Παύση πολυμέσων στη διάρκεια κλήσεων", "Name[es]": "Pausar medios durante las llamadas", "Name[et]": "Meedia peatamine kõne ajal", "Name[eu]": "Pausatu media deietan", "Name[fi]": "Keskeytä toisto puhelujen aikana", "Name[fr]": "Mettre en pause le média pendant les appels", "Name[gl]": "Deter a reprodución durante as chamadas.", "Name[hu]": "Médialejátszás felfüggesztése", "Name[it]": "Sospendi i lettori multimediali", "Name[ko]": "통화 중 미디어 일시 정지", "Name[nl]": "Media pauzeren tijdens oproepen", "Name[nn]": "Set avspeling på pause ved oppringingar", "Name[pl]": "Wstrzymaj multimedia przy dzwonieniu", "Name[pt]": "Pausar a reprodução durante as chamadas", "Name[pt_BR]": "Pausar os conteúdos multimídia durante as chamadas", "Name[ru]": "Приостановка воспроизведения во время звонка", "Name[sk]": "Pozastaviť médiá počas hovorov", "Name[sr@ijekavian]": "Паузирање медија током позива", "Name[sr@ijekavianlatin]": "Pauziranje medija tokom poziva", "Name[sr@latin]": "Pauziranje medija tokom poziva", "Name[sr]": "Паузирање медија током позива", "Name[sv]": "Pausa media under samtal", "Name[tr]": "Çağrılar sırasında ortamı duraklat", "Name[uk]": "Призупинка відтворення під час дзвінків", "Name[x-test]": "xxPause media during callsxx", "Name[zh_CN]": "来电时暂停媒体", "Name[zh_TW]": "在通話過程中暫停媒體", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-SupportedPackageType": [ "kdeconnect.telephony" ] } diff --git a/plugins/pausemusic/kdeconnect_pausemusic_config.desktop b/plugins/pausemusic/kdeconnect_pausemusic_config.desktop index 96da36b6..f09c9c0a 100644 --- a/plugins/pausemusic/kdeconnect_pausemusic_config.desktop +++ b/plugins/pausemusic/kdeconnect_pausemusic_config.desktop @@ -1,48 +1,44 @@ [Desktop Entry] Type=Service X-KDE-ServiceTypes=KCModule X-KDE-Library=kdeconnect_pausemusic_config X-KDE-ParentComponents=kdeconnect_pausemusic Name=Pause Music plugin settings -Name[ar]=إعدادات ملحقة إلباث الموسيقى -Name[ast]=Axustes del complementu de posar música Name[bg]=Настройки на приставката за поставяне на пауза Name[bs]=Zaustavi Muziku postavke dodatka Name[ca]=Ajustaments del connector Pausa la música Name[ca@valencia]=Ajustaments del connector Pausa la música Name[cs]=Nastavení modulu Pozastavení hudby Name[da]=Indstilling af plugin til at sætte musik på pause Name[de]=Modul-Einstellungen für das Anhalten der Musikwiedergabe -Name[el]=Ρυθμίσεις προσθέτου παύσης μουσικής Name[en_GB]=Pause Music plugin settings Name[es]=Ajustes del complemento PauseMusic Name[et]=Muusika peatamise plugina seadistused Name[eu]=Pausatu-musika pluginaren ezarpenak Name[fi]=Keskeytä musiikki -liitännäisen asetukset Name[fr]=Paramètres du module de mise en pause Name[gl]=Configuración do complemento para deter a música -Name[he]=הגדרות התוספת השהיית המוזיקה Name[hu]=Zene szüneteltetése bővítmény beállításai Name[it]=Impostazioni estensione Sospendi musica Name[ko]=음악 일시 정지 플러그인 설정 Name[nl]=Plug-in-instellingen voor muziek pauzeren Name[nn]=Innstillingar for tillegg for pausing av musikk Name[pl]=Ustawienia wtyczki wstrzymywania muzyki Name[pt]=Configuração do 'plugin' de Pausa da Música Name[pt_BR]=Pausar as configurações do plugin Músicas Name[ru]=Настройка модуля приостановки музыки Name[sk]=Nastavenia pluginu pozastavenia hudby Name[sr]=Поставке прикључка паузирања музике Name[sr@ijekavian]=Поставке прикључка паузирања музике Name[sr@ijekavianlatin]=Postavke priključka pauziranja muzike Name[sr@latin]=Postavke priključka pauziranja muzike Name[sv]=Inställningar av insticksprogram för paus i musik Name[tr]=Müziği Duraklat eklenti ayarları Name[uk]=Параметри додатка призупинення відтворення музики Name[x-test]=xxPause Music plugin settingsxx Name[zh_CN]=暂停音乐插件设置 Name[zh_TW]=暫停音樂擴展插件設定 Categories=Qt;KDE;X-KDE-settings-kdeconnect; diff --git a/plugins/ping/kdeconnect_ping.json b/plugins/ping/kdeconnect_ping.json index 929d3878..7eb17595 100644 --- a/plugins/ping/kdeconnect_ping.json +++ b/plugins/ping/kdeconnect_ping.json @@ -1,78 +1,75 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "albertvaka@gmail.com", "Name": "Albert Vaca", "Name[sr@ijekavian]": "Алберт Вака Синтора", "Name[sr@ijekavianlatin]": "Albert Vaka Sintora", "Name[sr@latin]": "Albert Vaka Sintora", "Name[sr]": "Алберт Вака Синтора", "Name[x-test]": "xxAlbert Vacaxx" } ], "Description": "Send and receive pings", - "Description[ar]": "أرسل الوخزات واستقبلها", "Description[ca@valencia]": "Envia i rep pings", "Description[ca]": "Envia i rep pings", "Description[cs]": "Posílat a přijímat ping", "Description[da]": "Send og modtag ping", "Description[de]": "Senden und Empfangen von Pings", - "Description[el]": "Αποστολή και λήψη pings", "Description[es]": "Enviar y recibir pings", "Description[et]": "Pingide saatmine ja vastuvõtmine", "Description[eu]": "Bidali eta jaso pingak", "Description[fi]": "Lähetä ja vastaanota tiedustelupaketteja", "Description[fr]": "Envoie et reçoit des commandes « Ping »", "Description[gl]": "Enviar e recibir pings.", "Description[hu]": "Pingek küldése és fogadása", "Description[it]": "Invia e ricevi ping", "Description[ko]": "핑 보내고 받기", "Description[nl]": "Pings verzenden en ontvangen", "Description[nn]": "Send og ta imot pingsignal", "Description[pl]": "Wysyłaj i otrzymuj pingi", "Description[pt]": "Enviar e receber contactos", "Description[pt_BR]": "Envia e recebe pings", "Description[ru]": "Отправка и получение пингов", "Description[sk]": "Poslať a prijať pingy", "Description[sr@ijekavian]": "Шаље и прима пингове", "Description[sr@ijekavianlatin]": "Šalje i prima pingove", "Description[sr@latin]": "Šalje i prima pingove", "Description[sr]": "Шаље и прима пингове", "Description[sv]": "Skicka och ta emot ping", "Description[tr]": "Ping gönder ve al", "Description[uk]": "Надсилання і отримання сигналів підтримання зв’язку", "Description[x-test]": "xxSend and receive pingsxx", "Description[zh_CN]": "发送和接受 ping", "Description[zh_TW]": "傳送與接收Ping回應封包", "EnabledByDefault": true, "Icon": "dialog-ok", "Id": "kdeconnect_ping", "License": "GPL", "Name": "Ping", - "Name[ar]": "وخزة", "Name[fi]": "Tiedustelupaketti", "Name[fr]": "Commande « Ping »", "Name[ko]": "핑", "Name[pt]": "Contacto", "Name[ru]": "Тестовый сигнал", "Name[sr@ijekavian]": "Пинг", "Name[sr]": "Пинг", "Name[sv]": "Pinga", "Name[uk]": "Луна-імпульс", "Name[x-test]": "xxPingxx", "Name[zh_TW]": "Ping回應封包", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.ping" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.ping" ] } diff --git a/plugins/remotecommands/kdeconnect_remotecommands.json b/plugins/remotecommands/kdeconnect_remotecommands.json index 87686695..3fc0ec68 100644 --- a/plugins/remotecommands/kdeconnect_remotecommands.json +++ b/plugins/remotecommands/kdeconnect_remotecommands.json @@ -1,92 +1,86 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "aleixpol@kde.org", "Name": "Aleix Pol", "Name[sr@ijekavian]": "Алекс Пол Гонзалез", "Name[sr@ijekavianlatin]": "Aleks Pol Gonzalez", "Name[sr@latin]": "Aleks Pol Gonzalez", "Name[sr]": "Алекс Пол Гонзалез", "Name[x-test]": "xxAleix Polxx" } ], "Description": "Trigger commands predefined on the remote device", - "Description[ar]": "نفّذ أوامر معرّفة مسبقًا في الجهاز البعيد", "Description[ca@valencia]": "Activa ordes predefinides en el dispositiu remot", "Description[ca]": "Activa ordres predefinides en el dispositiu remot", "Description[cs]": "Spouštět příkazy předpřipravené na vzdáleném zařízení", "Description[da]": "Udløs kommandoer som er prædefinerede på den eksterne enhed", "Description[de]": "Vordefinierte Befehle auf dem entfernten Gerät ausführen", - "Description[el]": "Ενεργοποίηση προκαθορισμένων εντολών στην απομακρυσμένη συσκευή", "Description[es]": "Desencadenar órdenes predefinidas en el dispositivo remoto", "Description[et]": "Kaugseadmes määratud käskude käivitamine", "Description[eu]": "Exekutatu urruneko gailuan aurretiaz zehaztutako komandoak", "Description[fi]": "Suorita ennakkoon määriteltyjä komentoja etälaitteella", "Description[fr]": "Exécuter des commandes prédéfinies sur le périphérique distant", - "Description[gl]": "Provocar ordes predefinidas no dispositivo remoto.", "Description[it]": "Innesca comandi predefiniti sul dispositivo remoto", "Description[ko]": "원격 장치에 미리 정의한 트리거 명령", "Description[nl]": "Start commando's voorgedefinieerd op het apparaat op afstand", "Description[nn]": "Løys ut ferdigdefinerte kommandoar på eininga", "Description[pl]": "Wyzwalaj polecenia określone na zdalnym urządzeniu", "Description[pt]": "Despoletar os comandos predefinidos para o dispositivo remoto", "Description[ru]": "Вызов команд, предопределённых на удалённом устройстве", "Description[sk]": "Vyvolať príkazy preddefinované na vzdialenom zariadení", "Description[sr@ijekavian]": "Окида наредбе предефинисане на удаљеном уређају", "Description[sr@ijekavianlatin]": "Okida naredbe predefinisane na udaljenom uređaju", "Description[sr@latin]": "Okida naredbe predefinisane na udaljenom uređaju", "Description[sr]": "Окида наредбе предефинисане на удаљеном уређају", "Description[sv]": "Utför kommandon fördefinierade på den andra apparaten", "Description[tr]": "Uzak aygıta önceden tanımlanmış komutları tetikleyin", "Description[uk]": "Запуск команд, попередньо визначених на віддаленому пристрої", "Description[x-test]": "xxTrigger commands predefined on the remote devicexx", "Description[zh_CN]": "出发远程设备的预设命令", "Description[zh_TW]": "預先設定在遠端設備上的執行命令", "EnabledByDefault": true, "Icon": "system-run", "Id": "kdeconnect_remotecommands", "License": "GPL", "Name": "Host remote commands", - "Name[ar]": "استضف الأوامر البعيدة", "Name[ca@valencia]": "Allotja ordes remotes", "Name[ca]": "Allotja ordres remotes", "Name[cs]": "Přijímat vzdálené příkazy", "Name[da]": "Vært for eksterne kommandoer", - "Name[el]": "Απομακρυσμένη εκτέλεση εντολών", "Name[es]": "Órdenes en servidor remoto", "Name[et]": "Kaugkäsud", "Name[eu]": "Ostalariaren urruneko komandoak", "Name[fi]": "Etäkomennot", "Name[fr]": "Exécuter des commandes distantes", - "Name[gl]": "Ordes remotas do servidor", "Name[it]": "Comandi remoti host", "Name[ko]": "호스트 원격 명령", - "Name[nl]": "Host voor commando's op afstand", + "Name[nl]": "Commando's op afstand hosten", "Name[nn]": "Fjernkommandoar", "Name[pl]": "Wykonuj polecenia zdalne", "Name[pt]": "Alojar os comandos remotos", "Name[ru]": "Выполнение команд на устройстве", + "Name[sk]": "Vzdialené príkazy hostiteľa", "Name[sr@ijekavian]": "Даљинске наредбе домаћина", "Name[sr@ijekavianlatin]": "Daljinske naredbe domaćina", "Name[sr@latin]": "Daljinske naredbe domaćina", "Name[sr]": "Даљинске наредбе домаћина", "Name[sv]": "Fjärrkommandon för värddator", "Name[tr]": "Sunucu uzaktan komutları", "Name[uk]": "Віддалені команди вузлу", "Name[x-test]": "xxHost remote commandsxx", - "Name[zh_CN]": "主机远程命令", "Name[zh_TW]": "主機與遠端指令", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.runcommand.request" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.runcommand" ] } diff --git a/plugins/remotecontrol/kdeconnect_remotecontrol.json b/plugins/remotecontrol/kdeconnect_remotecontrol.json index ce6ec936..b87d3418 100644 --- a/plugins/remotecontrol/kdeconnect_remotecontrol.json +++ b/plugins/remotecontrol/kdeconnect_remotecontrol.json @@ -1,92 +1,89 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "aleixpol@kde.org", "Name": "Aleix Pol", "Name[sr@ijekavian]": "Алекс Пол Гонзалез", "Name[sr@ijekavianlatin]": "Aleks Pol Gonzalez", "Name[sr@latin]": "Aleks Pol Gonzalez", "Name[sr]": "Алекс Пол Гонзалез", "Name[x-test]": "xxAleix Polxx" } ], "Description": "Control Remote systems", - "Description[ar]": "تحكّم بالأنظمة البعيدة", "Description[ca@valencia]": "Sistemes de control remot", "Description[ca]": "Sistemes de control remot", "Description[cs]": "Ovládejte vzdálené systémy", - "Description[da]": "Kontrollér eksterne systemer", + "Description[da]": "Fjernbetjen systemer", "Description[de]": "Entfernte Systeme steuern", - "Description[el]": "Έλεγχος ανταπόκρισης απομακρυσμένων συστημάτων", "Description[es]": "Controlar sistemas remotos", "Description[et]": "Kaugjuhtimissüsteemid", "Description[eu]": "Kontrolatu urruneko sistemak", "Description[fi]": "Ohjaa järjestelmiä etänä", "Description[fr]": "Controllez les systèmes distants", "Description[gl]": "Controla sistemas remotos.", "Description[it]": "Controlla i sistemi remoti", "Description[ko]": "원격 시스템 제어", "Description[nl]": "Systemen op afstand bedienen", "Description[nn]": "Fjernkontroller system", "Description[pl]": "Sterowanie zdalnymi systemami", "Description[pt]": "Comandar sistemas à distância", "Description[pt_BR]": "Controle remoto de sistemas", "Description[ru]": "Управление удалёнными системами", "Description[sk]": "Ovládať vzdialené systémy", "Description[sr@ijekavian]": "Контролише удаљене системе", "Description[sr@ijekavianlatin]": "Kontroliše udaljene sisteme", "Description[sr@latin]": "Kontroliše udaljene sisteme", "Description[sr]": "Контролише удаљене системе", - "Description[sv]": "Styr externt system", + "Description[sv]": "Styr fjärrsystem", "Description[tr]": "Uzak Sistemleri Kontrol Et", "Description[uk]": "Системи віддаленого керування", "Description[x-test]": "xxControl Remote systemsxx", "Description[zh_CN]": "控制远程系统", "Description[zh_TW]": "控制遠端系統", "EnabledByDefault": true, "Icon": "applications-multimedia", "Id": "kdeconnect_remotecontrol", "License": "GPL", "Name": "RemoteControl", - "Name[ar]": "التّحكّم عن بعد", "Name[ca@valencia]": "Control remot", "Name[ca]": "Control remot", "Name[cs]": "Dálkové ovládání", - "Name[da]": "FjernBetjening", + "Name[da]": "Fjernbetjening", "Name[de]": "Fernsteuerung", "Name[es]": "Control remoto", "Name[et]": "Kaugjuhtimine", "Name[eu]": "UrrunekoKontrola", "Name[fi]": "Kauko-ohjain", "Name[gl]": "Mando a distancia", "Name[it]": "Telecomando", "Name[ko]": "원격 제어", "Name[nl]": "Afstandsbediening", "Name[nn]": "Fjernkontroll", "Name[pl]": "ZdalneSterowanie", "Name[pt]": "Comando à Distância", "Name[pt_BR]": "Controle remoto", "Name[ru]": "Удалённое управление", "Name[sk]": "Diaľkové ovládanie", "Name[sr@ijekavian]": "Удаљене контроле", "Name[sr@ijekavianlatin]": "Udaljene kontrole", "Name[sr@latin]": "Udaljene kontrole", "Name[sr]": "Удаљене контроле", "Name[sv]": "Fjärrkontroll", "Name[tr]": "UzaktanKumanda", "Name[x-test]": "xxRemoteControlxx", "Name[zh_CN]": "远程控制", "Name[zh_TW]": "遠端控制", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "https://kde.org" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.mousepad.request" ], "X-KdeConnect-SupportedPackageType": [] } diff --git a/plugins/remotekeyboard/kdeconnect_remotekeyboard.json b/plugins/remotekeyboard/kdeconnect_remotekeyboard.json index a6dca629..e80aa268 100644 --- a/plugins/remotekeyboard/kdeconnect_remotekeyboard.json +++ b/plugins/remotekeyboard/kdeconnect_remotekeyboard.json @@ -1,79 +1,78 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "holger.k@elberer.de", "Name": "Holger Kaelberer", + "Name[da]": "Holger Freyther", "Name[sr@ijekavian]": "Холгер Келберер", "Name[sr@ijekavianlatin]": "Holger Kelberer", "Name[sr@latin]": "Holger Kelberer", "Name[sr]": "Холгер Келберер", "Name[x-test]": "xxHolger Kaelbererxx" } ], "Description": "Use your keyboard to send key-events to your paired device", "Description[ca@valencia]": "Useu el vostre teclat per enviar esdeveniments de tecla al dispositiu enllaçat", "Description[ca]": "Useu el vostre teclat per enviar esdeveniments de tecla al dispositiu enllaçat", "Description[cs]": "Používejte svoji klávesnici pro odesílání událostí kláves na spárované zařízení", "Description[da]": "Brug dit tastatur til at sende tastehændelser til din parrede enhed", "Description[es]": "Use su teclado para enviar eventos de teclado a su dispositivo vinculado", "Description[eu]": "Erabili zure teklatua tekla-gertaerak zure parekatutako gailura bidaltzeko", "Description[fr]": "Utiliser votre clavier pour envoyer des évènements de touche au périphérique associé", - "Description[gl]": "Usar o teclado para enviar eventos de tecla ao dispositivo emparellado.", "Description[it]": "Utilizza la tua tastiera per inviare eventi di pressione dei tasti al dispositivo associato", "Description[nl]": "Uw toetsenbord gebruiken om toetsgebeurtenissen naar uw gepaarde apparaat te verzenden", "Description[nn]": "Bruk tastaturet til å senda tastetrykk til den para eininga", "Description[pl]": "Użyj swojej klawiatury do wysyłania naciśnięć klawiszy do swojego sparowanego urządzenia", - "Description[pt]": "Usar o seu teclado para enviar eventos de teclas para o seu dispositivo emparelhado", - "Description[ru]": "Используйте клавиатуру для отправки нажатий клавиш на сопряжённое устройство", + "Description[pt]": "Use o seu teclado para enviar eventos de teclado para o seu dispositivo emparelhado", + "Description[sk]": "Použite vašu klávesnicu na posielanie klávesových udalostí vášmu spárovanému zariadeniu", "Description[sr@ijekavian]": "Користите тастатуру за куцање на упареном уређају", "Description[sr@ijekavianlatin]": "Koristite tastaturu za kucanje na uparenom uređaju", "Description[sr@latin]": "Koristite tastaturu za kucanje na uparenom uređaju", "Description[sr]": "Користите тастатуру за куцање на упареном уређају", "Description[sv]": "Använd tangentbordet för att skicka tangenthändelser till den parade enheten", "Description[tr]": "Eşleşmiş cihazınıza önemli etkinlikler göndermek için klavyenizi kullanın", "Description[uk]": "Скористайтеся вашою клавіатурою для надсилання подій натискання клавіш на пов’язаний пристрій", "Description[x-test]": "xxUse your keyboard to send key-events to your paired devicexx", "Description[zh_CN]": "使用您的键盘发送按键事件给配对的设备", "EnabledByDefault": true, "Icon": "edit-select", "Id": "kdeconnect_remotekeyboard", "License": "GPL", "Name": "Remote keyboard from the desktop", "Name[ca@valencia]": "Teclat remot des de l'escriptori", "Name[ca]": "Teclat remot des de l'escriptori", "Name[cs]": "Vzdálená klávesnice pro plochu", "Name[da]": "Eksternt tastatur fra desktoppen", "Name[es]": "Teclado remoto desde el equipo de escritorio", "Name[eu]": "Urruneko teklatua mahaigainetik", "Name[fr]": "Clavier distant depuis le bureau", - "Name[gl]": "Teclado remoto do escritorio", "Name[it]": "Tastiera remota dal desktop", "Name[nl]": "Toetsenbord op afstand vanaf het bureaublad", "Name[nn]": "Fjerntastatur frå skrivebordet", "Name[pl]": "Zdalna klawiatura z pulpitu", - "Name[pt]": "Teclado remoto do ambiente de trabalho", - "Name[ru]": "Удалённая клавиатура с компьютера", + "Name[pt]": "Teclado remoto no ecrã", + "Name[sk]": "Vzdialená klávesnica z plochy", "Name[sr@ijekavian]": "Даљинска тастатура са радне површи", "Name[sr@ijekavianlatin]": "Daljinska tastatura sa radne površi", "Name[sr@latin]": "Daljinska tastatura sa radne površi", "Name[sr]": "Даљинска тастатура са радне површи", "Name[sv]": "Externt tangentbord från skrivbordet", "Name[tr]": "Masaüstünden uzak klavye", "Name[uk]": "Віддалена клавіатура з комп’ютера", "Name[x-test]": "xxRemote keyboard from the desktopxx", "Name[zh_CN]": "来自桌面的远程键盘", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.mousepad.request" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.mousepad.echo", "kdeconnect.mousepad.keyboardstate" ] } diff --git a/plugins/runcommand/kdeconnect_runcommand.json b/plugins/runcommand/kdeconnect_runcommand.json index aab56251..72cbed51 100644 --- a/plugins/runcommand/kdeconnect_runcommand.json +++ b/plugins/runcommand/kdeconnect_runcommand.json @@ -1,107 +1,98 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "albertvaka@gmail.com", "Name": "Albert Vaca", "Name[sr@ijekavian]": "Алберт Вака Синтора", "Name[sr@ijekavianlatin]": "Albert Vaka Sintora", "Name[sr@latin]": "Albert Vaka Sintora", "Name[sr]": "Алберт Вака Синтора", "Name[x-test]": "xxAlbert Vacaxx" }, { "Email": "david@davidedmundson.co.uk", "Name": "David Edmundson", "Name[sr@ijekavian]": "Дејвид Едмундсон", "Name[sr@ijekavianlatin]": "Dejvid Edmundson", "Name[sr@latin]": "Dejvid Edmundson", "Name[sr]": "Дејвид Едмундсон", "Name[x-test]": "xxDavid Edmundsonxx" } ], "Description": "Execute console commands remotely", - "Description[ar]": "نفّذ أوامر طرفيّة عن بعد", "Description[ca@valencia]": "Executa ordes de la consola de forma remota", "Description[ca]": "Executa ordres de la consola de forma remota", "Description[cs]": "Spouštět konzolové příkazy vzdáleně", "Description[da]": "Kør konsolkommandoer udefra", "Description[de]": "Entfernte Konsolenbefehle ausführen", - "Description[el]": "Απομακρυσμένη εκτέλεση εντολών του τερματικού", "Description[es]": "Ejecute órdenes de consola remotamente", "Description[et]": "Konsoolikäskude kaugkäivitamine", "Description[eu]": "Exekutatu kontsolako komandoak urrunetik", "Description[fi]": "Suorita konsolikomentoja etänä", "Description[fr]": "Exécute des commandes console à distance", - "Description[gl]": "Executar ordes de consola remotamente.", "Description[it]": "Esegui da remoto comandi della console", "Description[ko]": "원격으로 콘솔 명령 실행", "Description[nl]": "Commando's in de terminal op afstand laten uitvoeren", "Description[nn]": "Køyr konsollkommandoar på eininga", "Description[pl]": "Wykonaj polecenie konsoli zdalnie", "Description[pt]": "Executar de forma remota comandos da consola", "Description[pt_BR]": "Executa comandos do console remotamente", "Description[ru]": "Выполнение консольных команд удалённо", "Description[sk]": "Spustiť priamo príkazy konzoly", "Description[sr@ijekavian]": "Даљински извршава наредбе у конзоли", "Description[sr@ijekavianlatin]": "Daljinski izvršava naredbe u konzoli", "Description[sr@latin]": "Daljinski izvršava naredbe u konzoli", "Description[sr]": "Даљински извршава наредбе у конзоли", "Description[sv]": "Kör terminalkommandon på distans", "Description[tr]": "Konsol komutlarını uzaktan çalıştır", "Description[uk]": "Віддалене виконання консольних команд", "Description[x-test]": "xxExecute console commands remotelyxx", - "Description[zh_CN]": "远程执行控制台命令", "Description[zh_TW]": "遠程執行控制台命令", "EnabledByDefault": true, "Icon": "system-run", "Id": "kdeconnect_runcommand", "License": "GPL", "Name": "Run commands", - "Name[ar]": "شغّل أوامر", "Name[ca@valencia]": "Executa ordes", "Name[ca]": "Executa ordres", "Name[cs]": "Spustit příkazy", "Name[da]": "Kør kommandoer", "Name[de]": "Befehle ausführen", - "Name[el]": "Εκτέλεση εντολών", "Name[es]": "Ejecutar órdenes", "Name[et]": "Käskude käivitamine", "Name[eu]": "Exekutatu komandoak", "Name[fi]": "Suorita komentoja", "Name[fr]": "Exécute des commandes", - "Name[gl]": "Executar ordes", - "Name[ia]": "Exeque commandos", "Name[it]": "Esegui comandi", "Name[ko]": "명령 실행", "Name[nl]": "Commando's uitvoeren", "Name[nn]": "Køyr kommandoar", "Name[pl]": "Wykonywanie polecenie", "Name[pt]": "Executar comandos", "Name[pt_BR]": "Executar comandos", "Name[ru]": "Выполнение команд", "Name[sk]": "Spustiť príkazy", "Name[sr@ijekavian]": "Изврши наредбе", "Name[sr@ijekavianlatin]": "Izvrši naredbe", "Name[sr@latin]": "Izvrši naredbe", "Name[sr]": "Изврши наредбе", "Name[sv]": "Kör kommandon", "Name[tr]": "Komut çalıştır", "Name[uk]": "Виконання команд", "Name[x-test]": "xxRun commandsxx", - "Name[zh_CN]": "执行命令", "Name[zh_TW]": "執行命令", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.runcommand" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.runcommand.request" ] } diff --git a/plugins/runcommand/kdeconnect_runcommand_config.desktop b/plugins/runcommand/kdeconnect_runcommand_config.desktop index 52d8bc49..de742418 100644 --- a/plugins/runcommand/kdeconnect_runcommand_config.desktop +++ b/plugins/runcommand/kdeconnect_runcommand_config.desktop @@ -1,45 +1,39 @@ [Desktop Entry] Type=Service X-KDE-ServiceTypes=KCModule X-KDE-Library=kdeconnect_runcommand_config X-KDE-ParentComponents=kdeconnect_runcommand Name=Run Command plugin settings -Name[ar]=إعدادات ملحقة تشغيل الأوامر -Name[ast]=Axustes del complementu d'execución de comandos Name[ca]=Ajustaments del connector Executa ordres Name[ca@valencia]=Ajustaments del connector Executa ordes Name[cs]=Nastavení modulu Spustit příkaz Name[da]=Indstilling af kør kommando-plugin Name[de]=Modul-Einstellungen für Befehlsausführung -Name[el]=Ρυθμίσεις προσθέτου εκτέλεσης εντολής Name[en_GB]=Run Command plugin settings Name[es]=Ajustes del complemento de ejecución de órdenes Name[et]=Käsu käivitamise plugina seadistused Name[eu]=Exekutatu komandoa pluginaren ezarpenak Name[fi]=Suorita komento -liitännäisen asetukset Name[fr]=Configuration du module externe d'exécution de commande -Name[gl]=Configuración do complemento de orde de executar -Name[he]=הגדרת התוסף הרץ פקודה Name[it]=Impostazioni estensione Esegui comando Name[ko]=명령 실행 플러그인 설정 Name[nl]=Plug-in-instellingen van commando Uitvoeren Name[nn]=Innstillingar for kommandokøyring Name[pl]=Ustawienia wtyczki wykonywania polecenia Name[pt]=Configuração do 'plugin' de execução de comandos Name[pt_BR]=Configurações do plugin de execução de comandos Name[ru]=Настройка модуля выполнения команд Name[sk]=Nastavenia pluginu spustenia príkazu Name[sr]=Поставке прикључка извршавања наредбе Name[sr@ijekavian]=Поставке прикључка извршавања наредбе Name[sr@ijekavianlatin]=Postavke priključka izvršavanja naredbe Name[sr@latin]=Postavke priključka izvršavanja naredbe Name[sv]=Inställningar av insticksprogram för kör kommando Name[tr]=Komut Çalıştır eklenti ayarları Name[uk]=Параметри додатка запуску команд Name[x-test]=xxRun Command plugin settingsxx -Name[zh_CN]=执行命令插件设置 Name[zh_TW]=命令列擴展插件設定 Categories=Qt;KDE;X-KDE-settings-kdeconnect; diff --git a/plugins/runcommand/runcommandplugin.cpp b/plugins/runcommand/runcommandplugin.cpp index 0bd58243..24ac0ea3 100644 --- a/plugins/runcommand/runcommandplugin.cpp +++ b/plugins/runcommand/runcommandplugin.cpp @@ -1,93 +1,93 @@ /** * 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 #define PACKAGE_TYPE_RUNCOMMAND QStringLiteral("kdeconnect.runcommand") K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_runcommand.json", registerPlugin< RunCommandPlugin >(); ) 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::receivePackage(const NetworkPackage& 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(); - qDebug() << "Running:" << "/bin/sh" << "-c" << commandJson[QStringLiteral("command")].toString(); + qCInfo(KDECONNECT_PLUGIN_RUNCOMMAND) << "Running:" << "/bin/sh" << "-c" << commandJson[QStringLiteral("command")].toString(); QProcess::startDetached(QStringLiteral("/bin/sh"), QStringList()<< QStringLiteral("-c") << commandJson[QStringLiteral("command")].toString()); return true; } return false; } void RunCommandPlugin::connected() { sendConfig(); } void RunCommandPlugin::sendConfig() { QString commands = config()->get(QStringLiteral("commands"),QStringLiteral("{}")); NetworkPackage np(PACKAGE_TYPE_RUNCOMMAND, {{"commandList", commands}}); sendPackage(np); } void RunCommandPlugin::configChanged() { sendConfig(); } #include "runcommandplugin.moc" diff --git a/plugins/screensaver-inhibit/kdeconnect_screensaver_inhibit.json b/plugins/screensaver-inhibit/kdeconnect_screensaver_inhibit.json index d013aa78..3a5b2659 100644 --- a/plugins/screensaver-inhibit/kdeconnect_screensaver_inhibit.json +++ b/plugins/screensaver-inhibit/kdeconnect_screensaver_inhibit.json @@ -1,91 +1,87 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "pmdematagoda@mykolab.ch", "Name": "Pramod Dematagoda", "Name[sr@ijekavian]": "Прамод Дематагода", "Name[sr]": "Прамод Дематагода", "Name[x-test]": "xxPramod Dematagodaxx" } ], "Description": "Inhibit the screensaver when the device is connected", - "Description[ar]": "امنع حافظة الشّاشة إن كان الجهاز متّصلًا", "Description[ca@valencia]": "Inhibeix l'estalvi de pantalla quan es connecta el dispositiu", "Description[ca]": "Inhibeix l'estalvi de pantalla quan es connecta el dispositiu", "Description[cs]": "Potlačit spořič pokud je zařízení připojeno", - "Description[da]": "Tilbagehold pauseskærmen når enheden er tilsluttet", + "Description[da]": "Forhindr pauseskærm når enheden er forbundet", "Description[de]": "Bildschirmschoner unterbinden wenn ein Gerät angeschlossen ist", - "Description[el]": "Απαγόρευση προστασίας οθόνης όταν η συσκευή είναι σε σύνδεση", "Description[es]": "Inhibir el salvapantallas cuando el dispositivo está conectado", "Description[et]": "Ekraanisäästja keelamine, kui seade on ühendatud", "Description[eu]": "Gelditu pantaila-babeslea gailua konektatuta dagoenean", "Description[fi]": "Estä näytönsäästäjän käynnistyminen, kun laite on yhteydessä", "Description[fr]": "Inhiber l'économiseur d'écran quand le périphérique est connecté", "Description[gl]": "Desactivar o salvapantallas mentres o dispositivo estea conectado.", "Description[hu]": "A képernyővédő kikapcsolása, ha az eszköz csatlakoztatva van", "Description[it]": "Impedisci il salvaschermo quando il dispositivo è connesso", "Description[ko]": "장치가 연결되었을 때 화면 보호기 실행 중지", "Description[nl]": "Houdt de schermbeveiliging tegen wanneer het apparaat is verbonden", "Description[nn]": "Hindra pauseskjermen i å starta når eininga er kopla til", "Description[pl]": "Powstrzymaj wygaszacz ekrany po podłączeniu urządzenia", "Description[pt]": "Inibir o protector de ecrã quando o dispositivo estiver ligado", "Description[pt_BR]": "Inibe o protetor de tela quando o dispositivo estiver conectado", "Description[ru]": "Предотвращение запуска блокировщика экрана, когда устройство подключено", "Description[sk]": "Obmedziť šetrič obrazovky keď je pripojené zariadenie", "Description[sr@ijekavian]": "Онемогућава чувара екрана када је уређај повезан", "Description[sr@ijekavianlatin]": "Onemogućava čuvara ekrana kada je uređaj povezan", "Description[sr@latin]": "Onemogućava čuvara ekrana kada je uređaj povezan", "Description[sr]": "Онемогућава чувара екрана када је уређај повезан", "Description[sv]": "Stoppa skärmsläckaren när apparaten ansluts", "Description[tr]": "Aygıt bağlandığında ekran koruyucuyu durdur", "Description[uk]": "Забороняє зберігач екрана, якщо з’єднано пристрій", "Description[x-test]": "xxInhibit the screensaver when the device is connectedxx", "Description[zh_CN]": "连接设备时禁止屏保", "Description[zh_TW]": "當裝置連接中時停止螢幕保護", "EnabledByDefault": false, "Icon": "preferences-desktop-screensaver", "Id": "kdeconnect_screensaver_inhibit", "License": "GPL", "Name": "Inhibit screensaver", - "Name[ar]": "امنع حافظة الشّاشة", "Name[ca@valencia]": "Inhibeix l'estalvi de pantalla", "Name[ca]": "Inhibeix l'estalvi de pantalla", "Name[cs]": "Potlačit spořič obrazovky", - "Name[da]": "Tilbagehold pauseskærm", + "Name[da]": "Forhindr pauseskærm", "Name[de]": "Bildschirmschoner unterbinden", - "Name[el]": "Απαγόρευση προστασίας οθόνης", "Name[es]": "Inhibir salvapantallas", "Name[et]": "Ekraanisäästja keelamine", "Name[eu]": "Gelditu pantaila-babeslea", "Name[fi]": "Estä näytönsäästäjän käynnistyminen", "Name[fr]": "Inhiber l'économiseur d'écran", "Name[gl]": "Desactivar o salvapantallas", "Name[hu]": "Képernyővédő letiltása", "Name[it]": "Impedisci il salvaschermo", "Name[ko]": "화면 보호기 중지", "Name[nl]": "Schermbeveiliging tegenhouden", "Name[nn]": "Hindra pauseskjerm", "Name[pl]": "Powstrzymaj wygaszacz ekranu", "Name[pt]": "Inibir o protector de ecrã", "Name[pt_BR]": "Inibir o protetor de tela", "Name[ru]": "Запрет блокировки экрана", "Name[sk]": "Obmedziť šetrič obrazovky", "Name[sr@ijekavian]": "Онемогући чувара екрана", "Name[sr@ijekavianlatin]": "Onemogući čuvara ekrana", "Name[sr@latin]": "Onemogući čuvara ekrana", "Name[sr]": "Онемогући чувара екрана", "Name[sv]": "Stoppa skärmsläckare", "Name[tr]": "Ekran koruyucuyu durdur", "Name[uk]": "Заборона зберігача екрана", "Name[x-test]": "xxInhibit screensaverxx", "Name[zh_CN]": "禁止屏保", "Name[zh_TW]": "停止螢幕保護", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" } } diff --git a/plugins/sendnotifications/kdeconnect_sendnotifications.json b/plugins/sendnotifications/kdeconnect_sendnotifications.json index 8f66faaa..d99a6f4c 100644 --- a/plugins/sendnotifications/kdeconnect_sendnotifications.json +++ b/plugins/sendnotifications/kdeconnect_sendnotifications.json @@ -1,96 +1,91 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "holger.k@elberer.de", "Name": "Holger Kaelberer", + "Name[da]": "Holger Freyther", "Name[sr@ijekavian]": "Холгер Келберер", "Name[sr@ijekavianlatin]": "Holger Kelberer", "Name[sr@latin]": "Holger Kelberer", "Name[sr]": "Холгер Келберер", "Name[x-test]": "xxHolger Kaelbererxx" } ], "Description": "Broadcast this computer's notifications, so they can be shown on other devices.", - "Description[ar]": "بُثّ إخطارات هذا الحاسوب، لتظهر على الأجهزة الأخرى.", "Description[ca@valencia]": "Transmet les notificacions d'este ordinador, perquè puguen mostrar-se en altres dispositius.", "Description[ca]": "Transmet les notificacions d'aquest ordinador, perquè puguin mostrar-se en altres dispositius.", "Description[cs]": "Posílat upozornění tohoto počítače, takže mohou být zobrazena na jiných zařízeních.", "Description[da]": "Udsend denne computers bekendtgørelser, så de kan vises på andre enheder.", "Description[de]": "Die Benachrichtigungen dieses Rechners aussenden, sodass sie auf anderen Geräten angezeigt werden können.", - "Description[el]": "Μεταδώστε την ειδοποίηση αυτού του υπολογιστή, ώστε να εμφανιστεί σε άλλες συσκευές.", "Description[es]": "Difundir las notificaciones de este equipo, para que puedan mostrarse en otros dispositivos.", "Description[et]": "Arvuti märguannete levitamine, et neid oleks näha ka teistes seadmetes", "Description[eu]": "Hedatu ordenagailu honen jakinarazpenak, beste gailuetan erakutsi ahal izateko", "Description[fi]": "Lähetä tämän tietokoneen ilmoitukset, jotta ne voidaan näyttää muilla laitteilla.", "Description[fr]": "Diffuser les notifications de cet ordinateur pour qu'elles puissent être vues par d'autres périphériques.", - "Description[gl]": "Emitir as notificacións deste computador para que se mostren noutros dispositivos.", "Description[it]": "Trasmetti le notifiche di questo computer, affinché possano essere mostrate su altri dispositivi.", "Description[ko]": "이 컴퓨터의 알림을 다른 장치에도 표시합니다.", "Description[nl]": "De meldingen van deze computer rondsturen, zodat ze op andere apparaten getoond kunnen worden.", "Description[nn]": "Vidaresend varslingar frå datamaskina til andre einingar.", "Description[pl]": "Rozgłaszaj powiadomienia tego komputera, tak aby można je było wyświetlać na innych urządzeniach.", "Description[pt]": "Difunde as notificações deste computador, para que possam ser apresentadas noutros dispositivos.", "Description[ru]": "Трансляция уведомления с этого компьютера, чтобы они могли быть видны на других устройствах", "Description[sk]": "Vysielať upozornenia tohto počítača, aby sa zobrazili na druhom zariadení.", "Description[sr@ijekavian]": "Одашиље обавештења са овог рачунара, да се приказују на осталим уређајима.", "Description[sr@ijekavianlatin]": "Odašilje obaveštenja sa ovog računara, da se prikazuju na ostalim uređajima.", "Description[sr@latin]": "Odašilje obaveštenja sa ovog računara, da se prikazuju na ostalim uređajima.", "Description[sr]": "Одашиље обавештења са овог рачунара, да се приказују на осталим уређајима.", "Description[sv]": "Sänd ut datorns underrättelser så att de kan visas på andra enheter.", "Description[tr]": "Bu bilgisayarın bildirimlerini yayınlayın, böylece diğer cihazlarda gösterilebilirler.", "Description[uk]": "Транслювати сповіщення з цього комп’ютера так, щоб їх було показано на інших пристроях.", "Description[x-test]": "xxBroadcast this computer's notifications, so they can be shown on other devices.xx", "Description[zh_CN]": "广播此计算机的通知,以被其他设备显示。", - "Description[zh_TW]": "廣播此電腦的通知,這樣可以顯示在其他裝置上。", + "Description[zh_TW]": "廣播這臺電腦的通知,這樣它們就可以在其他裝置上顯示。", "EnabledByDefault": false, "Icon": "preferences-desktop-notification", "Id": "kdeconnect_sendnotifications", "License": "GPL", "Name": "Send notifications", - "Name[ar]": "أرسل إخطارات", "Name[ca@valencia]": "Envia les notificacions", "Name[ca]": "Envia les notificacions", "Name[cs]": "Posílat oznamování", "Name[da]": "Send bekendtgørelser", "Name[de]": "Benachrichtigungen senden", - "Name[el]": "Αποστολή ειδοποιήσεων", "Name[es]": "Enviar notificaciones", "Name[et]": "Märguannete saatmine", "Name[eu]": "Bidali jakinarazpenak", "Name[fi]": "Lähetä ilmoituksia", "Name[fr]": "Envoyer les notifications", - "Name[gl]": "Enviar notificacións", "Name[it]": "Invia notifiche", "Name[ko]": "알림 보내기", "Name[nl]": "Stuur meldingen", "Name[nn]": "Send varslingar", "Name[pl]": "Wysyłaj powiadomienia", "Name[pt]": "Enviar as notificações", "Name[pt_BR]": "Enviar notificações", "Name[ru]": "Отправка уведомлений", "Name[sk]": "Posielať upozornenia", "Name[sr@ijekavian]": "Шаљи обавештења", "Name[sr@ijekavianlatin]": "Šalji obaveštenja", "Name[sr@latin]": "Šalji obaveštenja", "Name[sr]": "Шаљи обавештења", "Name[sv]": "Skicka underrättelser", "Name[tr]": "Bildirim gönder", "Name[uk]": "Надіслати сповіщення", "Name[x-test]": "xxSend notificationsxx", "Name[zh_CN]": "发送通知", "Name[zh_TW]": "傳送通知", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.notification" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.notification.request" ] } diff --git a/plugins/sendnotifications/kdeconnect_sendnotifications_config.desktop b/plugins/sendnotifications/kdeconnect_sendnotifications_config.desktop index 8e518c8d..d57b65d4 100644 --- a/plugins/sendnotifications/kdeconnect_sendnotifications_config.desktop +++ b/plugins/sendnotifications/kdeconnect_sendnotifications_config.desktop @@ -1,45 +1,40 @@ [Desktop Entry] Type=Service X-KDE-ServiceTypes=KCModule X-KDE-Library=kdeconnect_sendnotifications_config X-KDE-ParentComponents=kdeconnect_sendnotifications Name=Notification synchronization plugin settings -Name[ar]=إعدادات ملحقة مزامنة الإخطارات -Name[ast]=Axustes del complementu de sincronización d'avisos Name[ca]=Ajustament del connector Sincronitza les notificacions Name[ca@valencia]=Ajustament del connector Sincronitza les notificacions Name[cs]=Nastavení modulu synchronizace upozornění -Name[da]=Indstilling af plugin til bekendtgørelsessynkronisering +Name[da]=Indstilling af plugin til synkronisering af bekendtgørelser Name[de]=Einstellungen für Benachrichtigungsabgleich-Modul -Name[el]=Ρυθμίσεις πρόσθετου συγχρονισμού ειδοποιήσεων Name[en_GB]=Notification synchronisation plugin settings Name[es]=Preferencias del complemento de sincronización de notificaciones Name[et]=Märguande sünkroonimise plugina seaditused Name[eu]=Jakinarazpenak sinkronizatzeko pluginaren ezarpenak Name[fi]=Ilmoitusten synkronointiliitännäisen asetukset Name[fr]=Configuration du module externe de synchronisation des notifications -Name[gl]=Configuración do complemento de sincronización de notificacións -Name[he]=הגדרת התוסף סנכרון התראות Name[it]=Impostazioni dell'estensione di sincronizzazione delle notifiche Name[ko]=알림 동기화 플러그인 설정 -Name[nl]=Instellingen van plug-in voor synchronisatie van meldingen +Name[nl]=Instellingen voor meldingen van synchronisatie plug-in Name[nn]=Innstillingar for tillegg for synkronisering av varslingar Name[pl]=Ustawienia wtyczki synchronizującej powiadomienia Name[pt]=Configuração do 'plugin' de sincronização das notificações Name[pt_BR]=Configuração do plugin de sincronização das notificações Name[ru]=Настройка модуля синхронизации уведомлений Name[sk]=Nastavenia pluginu notifikácií synchronizácie Name[sr]=Поставке прикључка синхронизације обавештења Name[sr@ijekavian]=Поставке прикључка синхронизације обавештења Name[sr@ijekavianlatin]=Postavke priključka sinhronizacije obaveštenja Name[sr@latin]=Postavke priključka sinhronizacije obaveštenja Name[sv]=Inställningar av insticksprogram för underrättelsesynkronisering Name[tr]=Bildirim eşitleme eklentisi ayarları Name[uk]=Параметри додатка синхронізації сповіщень Name[x-test]=xxNotification synchronization plugin settingsxx Name[zh_CN]=通知同步插件设置 Name[zh_TW]=同步通知擴展插件設定 Categories=Qt;KDE;X-KDE-settings-kdeconnect; diff --git a/plugins/sendnotifications/sendnotifications_config.ui b/plugins/sendnotifications/sendnotifications_config.ui index c1ef29a7..cd180a20 100644 --- a/plugins/sendnotifications/sendnotifications_config.ui +++ b/plugins/sendnotifications/sendnotifications_config.ui @@ -1,226 +1,204 @@ SendNotificationsConfigUi Qt::WindowModal 0 0 350 - 326 + 328 0 0 350 0 - - Pause music plugin - 0 0 - - - 11 - 75 - true - - General - - - 50 - false - - Synchronize only notifications with a timeout value of 0? Persistent notifications only 50 false Append the notification body to the summary when synchronizing notifications? Include body 50 false Synchronize icons of notifying applications if possible? Synchronize icons 0 0 40 32 50 false <html><head/><body><p>Minimum urgency level of the notifications</p></body></html> 2 50 false Synchronize only notifications with the given urgency level. Minimum urgency level 0 0 - - - 75 - true - - Applications 0 0 50 false true false Qt::NoPen true true 150 20 true true false diff --git a/plugins/sftp/kdeconnect_sftp.json b/plugins/sftp/kdeconnect_sftp.json index b3e20980..3f82455f 100644 --- a/plugins/sftp/kdeconnect_sftp.json +++ b/plugins/sftp/kdeconnect_sftp.json @@ -1,101 +1,97 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "kinnalru@gmail.com", "Name": "Samoilenko Yuri", "Name[ru]": "Юрий Самойленко", "Name[sr@ijekavian]": "Јуриј Самојленко", "Name[sr@ijekavianlatin]": "Jurij Samojlenko", "Name[sr@latin]": "Jurij Samojlenko", "Name[sr]": "Јуриј Самојленко", "Name[uk]": "Юрій Самойленко", "Name[x-test]": "xxSamoilenko Yurixx" } ], "Description": "Browse the remote device filesystem using SFTP", - "Description[ar]": "تصفّح نظام ملفّات الجهاز البعيد باستخدام SFTP", "Description[ca@valencia]": "Navega pel sistema de fitxers del dispositiu remot emprant SFTP", "Description[ca]": "Navega pel sistema de fitxers del dispositiu remot emprant SFTP", "Description[cs]": "Prohlížejte souborový systém zařízení pomocí SFTP", - "Description[da]": "Gennemse den eksterne enheds filsystem med SFTP", + "Description[da]": "Gennemse filsystemet på eksterne enheder med SFTP", "Description[de]": "Browsen im Dateisystem des entfernten Geräts mit SFTP", - "Description[el]": "Περιήγηση του απομακρυσμένου συστήματος αρχείων με χρήση SFTP", "Description[es]": "Navegar por el sistema de archivos del dispositivo remoto usando SFTP", "Description[et]": "Oma seadme failisüsteemi sirvimine SFTP vahendusel", "Description[eu]": "Arakatu urruneko gailuaren fitxategi-sistema SFTP erabiliz", "Description[fi]": "Selaa etälaitteiden tiedostojärjestelmiä SFTP:llä", "Description[fr]": "Naviguer dans le système de fichiers du périphérique distant en utilisant SFTP", "Description[gl]": "Explore o sistema de ficheiros do dispositivo remoto mediante SFTP.", "Description[hu]": "Távoli fájlrendszerek böngészése SFTP-n keresztül", "Description[it]": "Sfoglia il filesystem del dispositivo remoto utilizzando SFTP", "Description[ko]": "SFTP로 원격 장치 파일 시스템 탐색", "Description[nl]": "Blader door het bestandssysteem met SFTP op het apparaat op afstand", "Description[nn]": "Bla gjennom filsystemet på eininga med SFTP", "Description[pl]": "Przeglądaj zdalny system plików przy użyciu SFTP", "Description[pt]": "Navegar pelo sistema de ficheiros de um dispositivo remoto por SFTP", "Description[pt_BR]": "Navegue pelo sistema de arquivos do dispositivo usando SFTP", "Description[ru]": "Просмотр файловой системы удалённого устройства с помощью SFTP", "Description[sk]": "Prehliadať súborový systém vzdialeného zariadenia pomocou SFTP", "Description[sr@ijekavian]": "Прегледање удаљеног фајл система помоћу СФТП‑а", "Description[sr@ijekavianlatin]": "Pregledanje udaljenog fajl sistema pomoću SFTP‑a", "Description[sr@latin]": "Pregledanje udaljenog fajl sistema pomoću SFTP‑a", "Description[sr]": "Прегледање удаљеног фајл система помоћу СФТП‑а", - "Description[sv]": "Bläddra i den andra apparatens filsystem med SFTP", + "Description[sv]": "Bläddra i fjärrenhetens filsystem med SFTP", "Description[tr]": "Uzak aygıt dosya sistemine SFTP kullanarak göz atın", "Description[uk]": "Перегляд файлових систем на сторонніх пристроях за допомогою SFTP", "Description[x-test]": "xxBrowse the remote device filesystem using SFTPxx", "Description[zh_CN]": "通过 SFTP 浏览远程设备文件系统", "Description[zh_TW]": "使用SFTP來瀏覽遠端的檔案系統", "EnabledByDefault": true, "Icon": "folder-documents", "Id": "kdeconnect_sftp", "License": "GPL", "Name": "Remote filesystem browser", - "Name[ar]": "متصفّح نظام الملفّات البعيد", "Name[ca@valencia]": "Navegador del sistema de fitxers remot", "Name[ca]": "Navegador del sistema de fitxers remot", "Name[cs]": "Vzdálený prohlížeč souborového systému", - "Name[da]": "Browser til eksternt filsystem", + "Name[da]": "Filbrowser til eksternt filsystem", "Name[de]": "Datei-Browser für entferne Systeme", - "Name[el]": "Περιηγητής απομακρυσμένου συστήματος αρχείων", "Name[es]": "Navegador de sistema de archivos remoto", "Name[et]": "Kaug-failisüsteemi sirvija", "Name[eu]": "Urruneko fitxategi-sistemaren arakatzailea", "Name[fi]": "Etätiedostojärjestelmäselain", "Name[fr]": "Explorateur à distance du système de fichiers", "Name[gl]": "Navegador do sistema de ficheiros remoto.", "Name[hu]": "Távoli fájlrendszer-böngésző", "Name[it]": "Navigazione del filesystem remoto", "Name[ko]": "원격 파일 시스템 탐색기", "Name[nl]": "Bestandssysteembrowser op afstand", "Name[nn]": "Bla gjennom eksternt filsystem", "Name[pl]": "Przeglądarka zdalnego systemu plików", "Name[pt]": "Navegador de sistemas de ficheiros remotos", "Name[pt_BR]": "Navegador do sistema de arquivos remoto", "Name[ru]": "Удалённый просмотр файловой системы", "Name[sk]": "Prehliadač vzdialeného súborového systému", "Name[sr@ijekavian]": "Прегледач удаљеног фајл система", "Name[sr@ijekavianlatin]": "Pregledač udaljenog fajl sistema", "Name[sr@latin]": "Pregledač udaljenog fajl sistema", "Name[sr]": "Прегледач удаљеног фајл система", - "Name[sv]": "Extern filsystembläddrare", + "Name[sv]": "Fjärrfilsystembläddrare", "Name[tr]": "Uzak dosya sistemi tarayıcısı", "Name[uk]": "Перегляд віддалених файлових систем", "Name[x-test]": "xxRemote filesystem browserxx", "Name[zh_CN]": "远程文件系统浏览器", "Name[zh_TW]": "遠端檔案瀏覽器", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.sftp.request" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.sftp" ] } diff --git a/plugins/sftp/mounter.cpp b/plugins/sftp/mounter.cpp index 14114092..2c1c9c37 100644 --- a/plugins/sftp/mounter.cpp +++ b/plugins/sftp/mounter.cpp @@ -1,246 +1,247 @@ /** * 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 "mounter.h" #include #include #include #include #include "mountloop.h" #include "config-sftp.h" #include "sftp_debug.h" #include "kdeconnectconfig.h" Mounter::Mounter(SftpPlugin* sftp) : QObject(sftp) , m_sftp(sftp) , m_proc(nullptr) , m_mountPoint(sftp->mountPoint()) , m_started(false) { connect(m_sftp, &SftpPlugin::packageReceived, this, &Mounter::onPakcageReceived); connect(&m_connectTimer, &QTimer::timeout, this, &Mounter::onMountTimeout); connect(this, &Mounter::mounted, &m_connectTimer, &QTimer::stop); connect(this, &Mounter::failed, &m_connectTimer, &QTimer::stop); m_connectTimer.setInterval(10000); m_connectTimer.setSingleShot(true); QTimer::singleShot(0, this, &Mounter::start); qCDebug(KDECONNECT_PLUGIN_SFTP) << "Created mounter"; } Mounter::~Mounter() { qCDebug(KDECONNECT_PLUGIN_SFTP) << "Destroy mounter"; unmount(false); } bool Mounter::wait() { if (m_started) { return true; } qCDebug(KDECONNECT_PLUGIN_SFTP) << "Starting loop to wait for mount"; MountLoop loop; connect(this, &Mounter::mounted, &loop, &MountLoop::successed); connect(this, &Mounter::failed, &loop, &MountLoop::failed); return loop.exec(); } void Mounter::onPakcageReceived(const NetworkPackage& np) { if (np.get(QStringLiteral("stop"), false)) { qCDebug(KDECONNECT_PLUGIN_SFTP) << "SFTP server stopped"; unmount(false); return; } //This is the previous code, to access sftp server using KIO. Now we are //using the external binary sshfs, and accessing it as a local filesystem. /* * QUrl url; * url.setScheme("sftp"); * url.setHost(np.get("ip")); * url.setPort(np.get("port").toInt()); * url.setUserName(np.get("user")); * url.setPassword(np.get("password")); * url.setPath(np.get("path")); * new KRun(url, 0); * Q_EMIT mounted(); */ unmount(false); m_proc = new KProcess(); m_proc->setOutputChannelMode(KProcess::MergedChannels); connect(m_proc, &QProcess::started, this, &Mounter::onStarted); connect(m_proc, SIGNAL(error(QProcess::ProcessError)), SLOT(onError(QProcess::ProcessError))); connect(m_proc, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(onFinished(int,QProcess::ExitStatus))); QDir().mkpath(m_mountPoint); const QString program = QStringLiteral("sshfs"); QString path; if (np.has(QStringLiteral("multiPaths"))) path = '/'; else path = np.get(QStringLiteral("path")); QHostAddress addr = m_sftp->device()->getLocalIpAddress(); if (addr == QHostAddress::Null) { qCDebug(KDECONNECT_PLUGIN_SFTP) << "Device doesn't have a LanDeviceLink, unable to get IP address"; return; } QString ip = addr.toString(); const QStringList arguments = QStringList() << QStringLiteral("%1@%2:%3").arg( np.get(QStringLiteral("user")), ip, path) << m_mountPoint << QStringLiteral("-p") << np.get(QStringLiteral("port")) + << QStringLiteral("-s") // This fixes a bug where file chunks are sent out of order and get corrupted on reception << QStringLiteral("-f") << QStringLiteral("-F") << QStringLiteral("/dev/null") //Do not use ~/.ssh/config << QStringLiteral("-o") << "IdentityFile=" + KdeConnectConfig::instance()->privateKeyPath() << QStringLiteral("-o") << QStringLiteral("StrictHostKeyChecking=no") //Do not ask for confirmation because it is not a known host << QStringLiteral("-o") << QStringLiteral("UserKnownHostsFile=/dev/null") //Prevent storing as a known host << QStringLiteral("-o") << QStringLiteral("HostKeyAlgorithms=ssh-dss") //https://bugs.kde.org/show_bug.cgi?id=351725 << QStringLiteral("-o") << QStringLiteral("uid=") + QString::number(getuid()) << QStringLiteral("-o") << QStringLiteral("gid=") + QString::number(getgid()) << QStringLiteral("-o") << QStringLiteral("ServerAliveInterval=30") << QStringLiteral("-o") << QStringLiteral("password_stdin") ; m_proc->setProgram(program, arguments); qCDebug(KDECONNECT_PLUGIN_SFTP) << "Starting process: " << m_proc->program().join(QStringLiteral(" ")); m_proc->start(); //qCDebug(KDECONNECT_PLUGIN_SFTP) << "Passing password: " << np.get("password").toLatin1(); m_proc->write(np.get(QStringLiteral("password")).toLatin1()); m_proc->write("\n"); } void Mounter::onStarted() { qCDebug(KDECONNECT_PLUGIN_SFTP) << "Process started"; m_started = true; Q_EMIT mounted(); //m_proc->setStandardOutputFile("/tmp/kdeconnect-sftp.out"); //m_proc->setStandardErrorFile("/tmp/kdeconnect-sftp.err"); auto proc = m_proc; connect(m_proc, &KProcess::readyReadStandardError, [proc]() { qCDebug(KDECONNECT_PLUGIN_SFTP) << "stderr: " << proc->readAll(); }); connect(m_proc, &KProcess::readyReadStandardOutput, [proc]() { qCDebug(KDECONNECT_PLUGIN_SFTP) << "stdout:" << proc->readAll(); }); } void Mounter::onError(QProcess::ProcessError error) { if (error == QProcess::FailedToStart) { qCDebug(KDECONNECT_PLUGIN_SFTP) << "Process failed to start"; m_started = false; Q_EMIT failed(i18n("Failed to start sshfs")); } } void Mounter::onFinished(int exitCode, QProcess::ExitStatus exitStatus) { if (exitStatus == QProcess::NormalExit) { qCDebug(KDECONNECT_PLUGIN_SFTP) << "Process finished (exit code: " << exitCode << ")"; Q_EMIT unmounted(); } else { qCDebug(KDECONNECT_PLUGIN_SFTP) << "Process failed (exit code:" << exitCode << ")"; Q_EMIT failed(i18n("Error when accessing to filesystem")); } unmount(true); } void Mounter::onMountTimeout() { qCDebug(KDECONNECT_PLUGIN_SFTP) << "Timeout: device not responding"; Q_EMIT failed(i18n("Failed to mount filesystem: device not responding")); } void Mounter::start() { NetworkPackage np(PACKAGE_TYPE_SFTP_REQUEST, {{"startBrowsing", true}}); m_sftp->sendPackage(np); m_connectTimer.start(); } void Mounter::unmount(bool finished) { qCDebug(KDECONNECT_PLUGIN_SFTP) << "Unmount" << m_proc; if (m_proc) { if (!finished) { //Process is still running, we want to stop it //But when the finished signal come, we might have already gone. //Disconnect everything. m_proc->disconnect(); m_proc->kill(); auto proc = m_proc; m_proc = nullptr; connect(proc, static_cast(&QProcess::finished), [proc]() { qCDebug(KDECONNECT_PLUGIN_SFTP) << "Free" << proc; proc->deleteLater(); }); Q_EMIT unmounted(); } else m_proc->deleteLater(); //Free mount point (won't always succeed if the path is in use) #if defined(HAVE_FUSERMOUNT) KProcess::execute(QStringList() << QStringLiteral("fusermount") << QStringLiteral("-u") << m_mountPoint, 10000); #else KProcess::execute(QStringList() << QStringLiteral("umount") << m_mountPoint, 10000); #endif m_proc = nullptr; } m_started = false; } diff --git a/plugins/share/kdeconnect_share.json b/plugins/share/kdeconnect_share.json index 68d4194f..acf5907d 100644 --- a/plugins/share/kdeconnect_share.json +++ b/plugins/share/kdeconnect_share.json @@ -1,99 +1,95 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "albertvaka@gmail.com", "Name": "Albert Vaca", "Name[sr@ijekavian]": "Алберт Вака Синтора", "Name[sr@ijekavianlatin]": "Albert Vaka Sintora", "Name[sr@latin]": "Albert Vaka Sintora", "Name[sr]": "Алберт Вака Синтора", "Name[x-test]": "xxAlbert Vacaxx" } ], "Description": "Receive and send files, URLs or plain text easily", - "Description[ar]": "استقبل الملفّات أو العناوين أو النّصوص الصّرفة وأرسلها بسهولة", "Description[ca@valencia]": "Rep i envia fitxers, URL o text pla amb facilitat", "Description[ca]": "Rep i envia fitxers, URL o text pla amb facilitat", "Description[cs]": "Snadno přijímejte a posílejte soubory, URL nebo čistý text", "Description[da]": "Modtag og send nemt filer, URL'er eller klartekst", "Description[de]": "Empfang und Senden von Dateien, URLs oder einfachem Text", - "Description[el]": "Εύκολη λήψη και αποστολή αρχείων, URL ή απλού κειμένου", "Description[es]": "Recibir y enviar archivos, URL o texto sin formato fácilmente", "Description[et]": "Failide, URL-ide või lihtteksti hõlpus vastuvõtmine ja saatmine", "Description[eu]": "Jaso eta bidali fitxategiak, URL-ak, edo testu soila erraz", "Description[fi]": "Vastaanota ja lähetä tiedostoja, verkko-osoitteita tai tekstiä helposti", "Description[fr]": "Recevoir et envoyer des fichiers, des URLs ou du texte brut facilement", "Description[gl]": "Comparta e reciba con facilidade ficheiros, enderezos URL ou texto simple.", "Description[hu]": "Fájlok, URL-ek és szöveg fogadása és küldése", "Description[it]": "Ricevi e invia facilmente file, URL o testo semplice", "Description[ko]": "파일, URL, 일반 텍스트 공유하고 받기", "Description[nl]": "Bestanden, URL's of platte tekst gemakkelijk ontvangen en verzenden", "Description[nn]": "Ta imot og send filer, nettadresser og tekst på ein enkel måte", "Description[pl]": "Udostępniaj i otrzymuj pliki, adresy URL lub zwykły tekst z łatwością", "Description[pt]": "Receber e enviar ficheiros, URL's ou texto normal de forma simples", "Description[pt_BR]": "Recebe e envia facilmente arquivos, URLs ou texto simples", "Description[ru]": "Получение и отправка файлов, URL адресов или простого текста", "Description[sk]": "Prijať a poslať súbory, URL alebo čisté texty jednoducho", "Description[sr@ijekavian]": "Примај и шаљи фајлове, УРЛ‑ове или обичан текст, са лакоћом", "Description[sr@ijekavianlatin]": "Primaj i šalji fajlove, URL‑ove ili običan tekst, sa lakoćom", "Description[sr@latin]": "Primaj i šalji fajlove, URL‑ove ili običan tekst, sa lakoćom", "Description[sr]": "Примај и шаљи фајлове, УРЛ‑ове или обичан текст, са лакоћом", "Description[sv]": "Ta emot och skicka filer, webbadresser eller vanlig text enkelt", "Description[tr]": "Dosyaları, adres ve düz metinleri kolayca alın ve gönderin", "Description[uk]": "Спрощене отримання і надсилання файлів, адрес або текстових фрагментів", "Description[x-test]": "xxReceive and send files, URLs or plain text easilyxx", "Description[zh_CN]": "简单地接收和发送文件,URL 或者文本", "Description[zh_TW]": "接收與傳送檔案,URL網址或純文字檔", "EnabledByDefault": true, "Icon": "folder-network", "Id": "kdeconnect_share", "License": "GPL", "Name": "Share and receive", - "Name[ar]": "شارك واستقبل", "Name[ca@valencia]": "Comparteix i rep", "Name[ca]": "Comparteix i rep", "Name[cs]": "Sdílet a přijímat", "Name[da]": "Del og modtag", "Name[de]": "Senden und Empfangen", - "Name[el]": "Διαμοιρασμός και λήψη", "Name[es]": "Compartir y recibir", "Name[et]": "Jagamine ja vastuvõtmine", "Name[eu]": "Partekatu eta jaso", "Name[fi]": "Jaa ja vastaanota", "Name[fr]": "Partager et recevoir", "Name[gl]": "Compartir e recibir.", "Name[hu]": "Megosztás és fogadás", "Name[it]": "Condividi e ricevi", "Name[ko]": "공유하고 받기", "Name[nl]": "Delen en ontvangen", "Name[nn]": "Del og ta imot", "Name[pl]": "Udostępniaj i otrzymuj", "Name[pt]": "Partilhar e receber", "Name[pt_BR]": "Compartilhar e receber", "Name[ru]": "Общий доступ и получение", "Name[sk]": "Zdieľať a prijať", "Name[sr@ijekavian]": "Дели и примај", "Name[sr@ijekavianlatin]": "Deli i primaj", "Name[sr@latin]": "Deli i primaj", "Name[sr]": "Дели и примај", "Name[sv]": "Dela och ta emot", "Name[tr]": "Paylaş ve al", "Name[uk]": "Оприлюднення і отримання", "Name[x-test]": "xxShare and receivexx", "Name[zh_CN]": "分享和接收", "Name[zh_TW]": "共享與接收", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.share.request" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.share.request" ] } diff --git a/plugins/share/kdeconnect_share_config.desktop b/plugins/share/kdeconnect_share_config.desktop index 6f1a4218..f757cd6c 100644 --- a/plugins/share/kdeconnect_share_config.desktop +++ b/plugins/share/kdeconnect_share_config.desktop @@ -1,48 +1,44 @@ [Desktop Entry] Type=Service X-KDE-ServiceTypes=KCModule X-KDE-Library=kdeconnect_share_config X-KDE-ParentComponents=kdeconnect_share Name=Share plugin settings -Name[ar]=إعدادات ملحقة المشاركة -Name[ast]=Axustes del complementu de compartición Name[bg]=Настройки на приставката за споделяне Name[bs]=Podijeli postavke dodatka Name[ca]=Ajustaments del connector Compartició Name[ca@valencia]=Ajustaments del connector Compartició Name[cs]=Nastavení modulu sdílení Name[da]=Indstilling af deling-plugin Name[de]=Modul-Einstellungen für Veröffentlichung -Name[el]=Ρυθμίσεις προσθέτου κοινής χρήσης Name[en_GB]=Share plugin settings Name[es]=Ajustes del complemento para compartir Name[et]=Jagamisplugina seadistused Name[eu]=Partekatu pluginaren ezarpenak Name[fi]=Jakoliitännäisen asetukset Name[fr]=Paramètres du module de partage Name[gl]=Configuración do complemento de compartir -Name[he]=שתף את הגדרות התוספים Name[hu]=Megosztás bővítmény beállításai Name[it]=Impostazioni estensione Condivisione Name[ko]=공유 플러그인 설정 Name[nl]=Plug-in-instellingen van delen Name[nn]=Innstillingar for tillegg for deling Name[pl]=Ustawienia wtyczki udostępniania Name[pt]=Configuração do 'plugin' de partilha Name[pt_BR]=Compartilhar as configurações do plugin Name[ru]=Настройка модуля обмена файлами Name[sk]=Nastavenia pluginu zdieľania Name[sr]=Поставке прикључка дељења Name[sr@ijekavian]=Поставке прикључка дељења Name[sr@ijekavianlatin]=Postavke priključka deljenja Name[sr@latin]=Postavke priključka deljenja Name[sv]=Inställningar av delningsinsticksprogram Name[tr]=Paylaşma eklentisi ayarları Name[uk]=Параметри додатка оприлюднення даних Name[x-test]=xxShare plugin settingsxx Name[zh_CN]=分享插件设置 Name[zh_TW]=共享擴展插件設定 Categories=Qt;KDE;X-KDE-settings-kdeconnect; diff --git a/plugins/share/shareplugin.cpp b/plugins/share/shareplugin.cpp index 0915e2db..129b0d6c 100644 --- a/plugins/share/shareplugin.cpp +++ b/plugins/share/shareplugin.cpp @@ -1,166 +1,168 @@ /** * 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 "core/filetransferjob.h" K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_share.json", registerPlugin< SharePlugin >(); ) Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_SHARE, "kdeconnect.plugin.share") SharePlugin::SharePlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) { } 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; } bool SharePlugin::receivePackage(const NetworkPackage& np) { /* //TODO: Write a test like this if (np.type() == PACKAGE_TYPE_PING) { qCDebug(KDECONNECT_PLUGIN_SHARE) << "sending file" << (QDesktopServices::storageLocation(QDesktopServices::HomeLocation) + "/.bashrc"); NetworkPackage out(PACKAGE_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()->sendPackage(out); return true; } */ qCDebug(KDECONNECT_PLUGIN_SHARE) << "File transfer"; if (np.hasPayload()) { - //qCDebug(KDECONNECT_PLUGIN_SHARE) << "receiving file"; const QString filename = np.get(QStringLiteral("filename"), QString::number(QDateTime::currentMSecsSinceEpoch())); const QUrl dir = destinationDir().adjusted(QUrl::StripTrailingSlash); - QUrl destination(dir.toString() + '/' + filename); + QUrl destination(dir); + destination.setPath(dir.path() + '/' + filename, QUrl::DecodedMode); if (destination.isLocalFile() && QFile::exists(destination.toLocalFile())) { - destination = QUrl(dir.toString() + '/' + KIO::suggestName(dir, filename)); + destination.setPath(dir.path() + '/' + KIO::suggestName(dir, filename), QUrl::DecodedMode); } +// qCDebug(KDECONNECT_PLUGIN_SHARE) << "receiving file" << filename << "in" << dir << "into" << destination; FileTransferJob* job = np.createPayloadTransferJob(destination); job->setOriginName(device()->name() + ": " + filename); connect(job, &KJob::result, this, &SharePlugin::finished); KIO::getJobTracker()->registerJob(job); job->start(); } else if (np.has(QStringLiteral("text"))) { QString text = np.get(QStringLiteral("text")); if (!QStandardPaths::findExecutable(QStringLiteral("kate")).isEmpty()) { QProcess* proc = new QProcess(); connect(proc, SIGNAL(finished(int)), proc, SLOT(deleteLater())); proc->start(QStringLiteral("kate"), QStringList(QStringLiteral("--stdin"))); proc->write(text.toUtf8()); proc->closeWriteChannel(); } else { QTemporaryFile tmpFile; tmpFile.setAutoRemove(false); tmpFile.open(); tmpFile.write(text.toUtf8()); tmpFile.close(); - const QUrl url = QUrl::fromLocalFile(tmpFile.fileName()); - Q_EMIT shareReceived(url); - QDesktopServices::openUrl(url); + 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); + Q_EMIT shareReceived(url.toString()); } else { qCDebug(KDECONNECT_PLUGIN_SHARE) << "Error: Nothing attached!"; } return true; - } void SharePlugin::finished(KJob* job) { FileTransferJob* ftjob = qobject_cast(job); - if (ftjob) - Q_EMIT shareReceived(ftjob->destination()); - - qCDebug(KDECONNECT_PLUGIN_SHARE) << "File transfer finished. Success:" << (!job->error()) << (ftjob ? ftjob->destination() : QUrl()); + if (ftjob && !job->error()) { + Q_EMIT shareReceived(ftjob->destination().toString()); + 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) { NetworkPackage package(PACKAGE_TYPE_SHARE_REQUEST); if(url.isLocalFile()) { QSharedPointer ioFile(new QFile(url.toLocalFile())); package.setPayload(ioFile, ioFile->size()); package.set(QStringLiteral("filename"), QUrl(url).fileName()); } else { package.set(QStringLiteral("url"), url.toString()); } sendPackage(package); } QString SharePlugin::dbusPath() const { return "/modules/kdeconnect/devices/" + device()->id() + "/share"; } #include "shareplugin.moc" diff --git a/plugins/share/shareplugin.h b/plugins/share/shareplugin.h index a8bfba53..e3ca64b0 100644 --- a/plugins/share/shareplugin.h +++ b/plugins/share/shareplugin.h @@ -1,60 +1,60 @@ /** * 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 . */ #ifndef SHAREPLUGIN_H #define SHAREPLUGIN_H #include #include #include #define PACKAGE_TYPE_SHARE_REQUEST QStringLiteral("kdeconnect.share.request") class SharePlugin : public KdeConnectPlugin { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.share") public: explicit SharePlugin(QObject* parent, const QVariantList& args); ///Helper method, QDBus won't recognize QUrl Q_SCRIPTABLE void shareUrl(const QString& url) { shareUrl(QUrl(url)); } bool receivePackage(const NetworkPackage& np) override; void connected() override {} QString dbusPath() const override; private Q_SLOTS: void finished(KJob*); void openDestinationFolder(); Q_SIGNALS: - void shareReceived(const QUrl& url); + void shareReceived(const QString& url); private: void shareUrl(const QUrl& url); QUrl destinationDir() const; }; #endif diff --git a/plugins/telephony/CMakeLists.txt b/plugins/telephony/CMakeLists.txt index 52418e34..f9d4614f 100644 --- a/plugins/telephony/CMakeLists.txt +++ b/plugins/telephony/CMakeLists.txt @@ -1,12 +1,15 @@ find_package(KF5 REQUIRED COMPONENTS Notifications) include_directories(${CMAKE_BINARY_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../notifications/) # needed for the sendreplydialog -kdeconnect_add_plugin(kdeconnect_telephony JSON kdeconnect_telephony.json SOURCES telephonyplugin.cpp sendsmsdialog.cpp) +ki18n_wrap_ui(kdeconnect_telephony_SRCS ../notifications/sendreplydialog.ui) +kdeconnect_add_plugin(kdeconnect_telephony JSON kdeconnect_telephony.json SOURCES telephonyplugin.cpp ../notifications/sendreplydialog.cpp ${kdeconnect_telephony_SRCS}) target_link_libraries(kdeconnect_telephony kdeconnectcore KF5::I18n KF5::Notifications Qt5::DBus + Qt5::Widgets ) diff --git a/plugins/telephony/kdeconnect_telephony.json b/plugins/telephony/kdeconnect_telephony.json index b2f368de..a6aa720c 100644 --- a/plugins/telephony/kdeconnect_telephony.json +++ b/plugins/telephony/kdeconnect_telephony.json @@ -1,97 +1,93 @@ { "Encoding": "UTF-8", "KPlugin": { "Authors": [ { "Email": "albertvaka@gmail.com", "Name": "Albert Vaca", "Name[sr@ijekavian]": "Алберт Вака Синтора", "Name[sr@ijekavianlatin]": "Albert Vaka Sintora", "Name[sr@latin]": "Albert Vaka Sintora", "Name[sr]": "Алберт Вака Синтора", "Name[x-test]": "xxAlbert Vacaxx" } ], "Description": "Show notifications for calls and SMS", - "Description[ar]": "أظهر إخطارات المكالمات والرّسائل", "Description[ca@valencia]": "Mostra les notificacions de les trucades i els SMS", "Description[ca]": "Mostra les notificacions de les trucades i els SMS", "Description[cs]": "Zobrazit upozornění pro telefonáty a SMS", - "Description[da]": "Vis bekendtgørelser for opkald og sms", + "Description[da]": "Vis bekendtgørelser for opkald og SMS'er", "Description[de]": "Benachrichtigungen für Anrufe und SMS anzeigen", - "Description[el]": "Εμφάνιση ειδοποιήσεων για κλήσεις και SMS", "Description[es]": "Mostrar notificaciones de llamadas y SMS", "Description[et]": "Kõnede ja SMS-ide märguannete näitamine", "Description[eu]": "Erakutsi deien eta SMS mezuen jakinarazpenak", "Description[fi]": "Näytä puhelujen ja tekstiviestien ilmoitukset", "Description[fr]": "Affichez les notifications pour les appels et les SMS", - "Description[gl]": "Mostrar notificacións de chamadas e mensaxes SMS.", "Description[it]": "Mostra notifiche per le chiamate e per gli SMS", "Description[ko]": "통화와 SMS 알림 표시", "Description[nl]": "Meldingen tonen van oproepen en SMSjes", "Description[nn]": "Vis varslingar for oppringingar og SMS", "Description[pl]": "Powiadamiaj o dzwonieniu i esemesach", "Description[pt]": "Mostrar notificações para as chamadas e SMS", "Description[ru]": "Показ уведомлений для звонков и SMS", + "Description[sk]": "Zobraziť oznámenia pre hovory a SMS", "Description[sr@ijekavian]": "Приказује обавештења за позиве и СМС", "Description[sr@ijekavianlatin]": "Prikazuje obaveštenja za pozive i SMS", "Description[sr@latin]": "Prikazuje obaveštenja za pozive i SMS", "Description[sr]": "Приказује обавештења за позиве и СМС", "Description[sv]": "Visa underrättelser om samtal och SMS", "Description[tr]": "Çağrı ve SMS'ler için bildirim göster", "Description[uk]": "Показ сповіщень щодо дзвінків і SMS", "Description[x-test]": "xxShow notifications for calls and SMSxx", "Description[zh_CN]": "显示来电和短信通知", "Description[zh_TW]": "顯示來電與短訊通知", "EnabledByDefault": true, "Icon": "call-start", "Id": "kdeconnect_telephony", "License": "GPL", "Name": "Telephony integration", - "Name[ar]": "تكامل الهاتف", "Name[ca@valencia]": "Integració amb la telefonia", "Name[ca]": "Integració amb la telefonia", "Name[cs]": "Integrace telefonu", - "Name[da]": "Integration af telefoni", + "Name[da]": "Telefoniintegration", "Name[de]": "Telefon-Integration", - "Name[el]": "Ενσωμάτωση τηλεφωνίας", "Name[es]": "Integración con el teléfono", "Name[et]": "Telefoniga lõimimine", "Name[eu]": "Telefoniarekin integrazioa", "Name[fi]": "Puhelinintegrointi", "Name[fr]": "Intégration de la téléphonie", "Name[gl]": "Integración telefónica", "Name[hu]": "Telefonintegráció", "Name[it]": "Integrazione telefonica", "Name[ko]": "전화 통합", "Name[nl]": "Telefoonintegratie", "Name[nn]": "Telefonintegrering", "Name[pl]": "Integracja z telefonem", "Name[pt]": "Integração telefónica", "Name[pt_BR]": "Integração telefônica", "Name[ru]": "Интеграция телефонии", "Name[sk]": "Integrácia telefónie", "Name[sr@ijekavian]": "Интегрисана телефонија", "Name[sr@ijekavianlatin]": "Integrisana telefonija", "Name[sr@latin]": "Integrisana telefonija", "Name[sr]": "Интегрисана телефонија", "Name[sv]": "Integrering av telefoni", "Name[tr]": "Telefon tümleştirmesi", "Name[uk]": "Інтеграція з системою телефонії", "Name[x-test]": "xxTelephony integrationxx", "Name[zh_CN]": "Telephony 集成", "Name[zh_TW]": "集成電話", "ServiceTypes": [ "KdeConnect/Plugin" ], "Version": "0.1", "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPackageType": [ "kdeconnect.telephony.request", "kdeconnect.sms.request" ], "X-KdeConnect-SupportedPackageType": [ "kdeconnect.telephony" ] } diff --git a/plugins/telephony/sendsmsdialog.cpp b/plugins/telephony/sendsmsdialog.cpp deleted file mode 100644 index 6d8498be..00000000 --- a/plugins/telephony/sendsmsdialog.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright 2015 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 "sendsmsdialog.h" - -#include -#include -#include -#include - -#include - -SendSmsDialog::SendSmsDialog(const QString& originalMessage, const QString& phoneNumber, const QString& contactName, QWidget* parent) - : QDialog(parent) - , m_phoneNumber(phoneNumber) -{ - QVBoxLayout* layout = new QVBoxLayout; - - QTextEdit* textView = new QTextEdit(this); - textView->setReadOnly(true); - textView->setText(contactName + ": \n" + originalMessage); - layout->addWidget(textView); - - m_textEdit = new QTextEdit(this); - layout->addWidget(m_textEdit); - - QPushButton* sendButton = new QPushButton(i18n("Send"), this); - connect(sendButton, &QAbstractButton::clicked, this, &SendSmsDialog::sendButtonClicked); - layout->addWidget(sendButton); - - setLayout(layout); - setWindowTitle(contactName); - setWindowIcon(QIcon::fromTheme(QStringLiteral("kdeconnect"))); - setAttribute(Qt::WA_DeleteOnClose); -} - - -void SendSmsDialog::sendButtonClicked() -{ - Q_EMIT sendSms(m_phoneNumber, m_textEdit->toPlainText()); - close(); -} - -QSize SendSmsDialog::sizeHint() const -{ - return QSize(512, 64); -} diff --git a/plugins/telephony/sendsmsdialog.h b/plugins/telephony/sendsmsdialog.h deleted file mode 100644 index 1ec8fffc..00000000 --- a/plugins/telephony/sendsmsdialog.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2015 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 . - */ - -#ifndef SENDSMSDIALOG_H -#define SENDSMSDIALOG_H - -#include -#include - -class QTextEdit; -class QLineEdit; -class QPushButton; - -class SendSmsDialog : public QDialog -{ - Q_OBJECT - -public: - explicit SendSmsDialog(const QString& originalMessage, const QString& phoneNumber, const QString& contactName, QWidget* parent = nullptr); - QSize sizeHint() const override; - -private Q_SLOTS: - void sendButtonClicked(); - -Q_SIGNALS: - void sendSms(const QString& phoneNumber, const QString& messageBody); - -private: - QString m_phoneNumber; - QTextEdit* m_textEdit; -}; - -#endif diff --git a/plugins/telephony/telephonyplugin.cpp b/plugins/telephony/telephonyplugin.cpp index e77e9726..02aee86d 100644 --- a/plugins/telephony/telephonyplugin.cpp +++ b/plugins/telephony/telephonyplugin.cpp @@ -1,169 +1,170 @@ /** * 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 "telephonyplugin.h" -#include "sendsmsdialog.h" +#include "sendreplydialog.h" #include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_telephony.json", registerPlugin< TelephonyPlugin >(); ) Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_TELEPHONY, "kdeconnect.plugin.telephony") TelephonyPlugin::TelephonyPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) , m_telepathyInterface(QStringLiteral("org.freedesktop.Telepathy.ConnectionManager.kdeconnect"), QStringLiteral("/kdeconnect")) { } KNotification* TelephonyPlugin::createNotification(const NetworkPackage& 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"), "")); // In case telepathy can handle the message, don't do anything else if (event == QLatin1String("sms") && m_telepathyInterface.isValid()) { qCDebug(KDECONNECT_PLUGIN_TELEPHONY) << "Passing a text message to the telepathy interface"; connect(&m_telepathyInterface, SIGNAL(messageReceived(QString,QString)), SLOT(sendSms(QString,QString)), Qt::UniqueConnection); const QString messageBody = np.get(QStringLiteral("messageBody"),QLatin1String("")); QDBusReply reply = m_telepathyInterface.call(QStringLiteral("sendMessage"), phoneNumber, contactName, messageBody); if (reply) { return nullptr; } else { qCDebug(KDECONNECT_PLUGIN_TELEPHONY) << "Telepathy failed, falling back to the default handling"; } } 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("sms")) { type = QStringLiteral("smsReceived"); icon = QStringLiteral("mail-receive"); QString messageBody = np.get(QStringLiteral("messageBody"), QLatin1String("")); content = i18n("SMS from %1
%2", contactName, messageBody); 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 } 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::sendMutePackage); } else if (event == QLatin1String("sms")) { const QString messageBody = np.get(QStringLiteral("messageBody"),QLatin1String("")); notification->setActions( QStringList(i18n("Reply")) ); notification->setProperty("phoneNumber", phoneNumber); notification->setProperty("contactName", contactName); notification->setProperty("originalMessage", messageBody); connect(notification, &KNotification::action1Activated, this, &TelephonyPlugin::showSendSmsDialog); } return notification; } bool TelephonyPlugin::receivePackage(const NetworkPackage& np) { if (np.get(QStringLiteral("isCancel"))) { //TODO: Clear the old notification return true; } KNotification* n = createNotification(np); if (n != nullptr) n->sendEvent(); return true; } void TelephonyPlugin::sendMutePackage() { NetworkPackage package(PACKAGE_TYPE_TELEPHONY_REQUEST, {{"action", "mute"}}); sendPackage(package); } void TelephonyPlugin::sendSms(const QString& phoneNumber, const QString& messageBody) { NetworkPackage np(PACKAGE_TYPE_SMS_REQUEST, { {"sendSms", true}, {"phoneNumber", phoneNumber}, {"messageBody", messageBody} }); sendPackage(np); } void TelephonyPlugin::showSendSmsDialog() { QString phoneNumber = sender()->property("phoneNumber").toString(); QString contactName = sender()->property("contactName").toString(); QString originalMessage = sender()->property("originalMessage").toString(); - SendSmsDialog* dialog = new SendSmsDialog(originalMessage, phoneNumber, contactName); - connect(dialog, &SendSmsDialog::sendSms, this, &TelephonyPlugin::sendSms); + SendReplyDialog* dialog = new SendReplyDialog(originalMessage, phoneNumber, contactName); + connect(dialog, &SendReplyDialog::sendReply, this, &TelephonyPlugin::sendSms); dialog->show(); + dialog->raise(); } QString TelephonyPlugin::dbusPath() const { return "/modules/kdeconnect/devices/" + device()->id() + "/telephony"; } #include "telephonyplugin.moc" diff --git a/tests/sendfiletest.cpp b/tests/sendfiletest.cpp index 4b2abf8e..b5d2af24 100644 --- a/tests/sendfiletest.cpp +++ b/tests/sendfiletest.cpp @@ -1,149 +1,149 @@ /** * 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 #include #include #include #include #include #include #include #include #include #include #include #include "core/daemon.h" #include "core/device.h" #include "core/kdeconnectplugin.h" #include #include "kdeconnect-version.h" #include "testdaemon.h" class TestSendFile : public QObject { Q_OBJECT public: TestSendFile() { QStandardPaths::setTestModeEnabled(true); m_daemon = new TestDaemon; } private Q_SLOTS: void testSend() { m_daemon->acquireDiscoveryMode(QStringLiteral("test")); Device* d = nullptr; const QList devicesList = m_daemon->devicesList(); for (Device* id : devicesList) { if (id->isReachable()) { if (!id->isTrusted()) id->requestPair(); d = id; } } m_daemon->releaseDiscoveryMode(QStringLiteral("test")); QVERIFY(d); QCOMPARE(d->isReachable(), true); QCOMPARE(d->isTrusted(), true); QByteArray content("12312312312313213123213123"); QTemporaryFile temp; temp.open(); temp.write(content); temp.close(); KdeConnectPlugin* plugin = d->plugin(QStringLiteral("kdeconnect_share")); QVERIFY(plugin); plugin->metaObject()->invokeMethod(plugin, "shareUrl", Q_ARG(QString, QUrl::fromLocalFile(temp.fileName()).toString())); - QSignalSpy spy(plugin, SIGNAL(shareReceived(QUrl))); + QSignalSpy spy(plugin, SIGNAL(shareReceived(QString))); QVERIFY(spy.wait(2000)); QVariantList args = spy.takeFirst(); QUrl sentFile(args.first().toUrl()); QFile file(sentFile.toLocalFile()); QCOMPARE(file.size(), content.size()); QVERIFY(file.open(QIODevice::ReadOnly)); QCOMPARE(file.readAll(), content); } void testSslJobs() { const QString aFile = QFINDTESTDATA("sendfiletest.cpp"); const QString destFile = QDir::tempPath() + "/kdeconnect-test-sentfile"; QFile(destFile).remove(); const QString deviceId = KdeConnectConfig::instance()->deviceId() , deviceName = QStringLiteral("testdevice") , deviceType = KdeConnectConfig::instance()->deviceType(); KdeConnectConfig* kcc = KdeConnectConfig::instance(); kcc->addTrustedDevice(deviceId, deviceName, deviceType); kcc->setDeviceProperty(deviceId, QStringLiteral("certificate"), QString::fromLatin1(kcc->certificate().toPem())); // Using same certificate from kcc, instead of generating QSharedPointer f(new QFile(aFile)); UploadJob* uj = new UploadJob(f, deviceId); QSignalSpy spyUpload(uj, &KJob::result); uj->start(); auto info = uj->transferInfo(); info.insert(QStringLiteral("deviceId"), deviceId); info.insert(QStringLiteral("size"), aFile.size()); DownloadJob* dj = new DownloadJob(QHostAddress::LocalHost, info); QVERIFY(dj->getPayload()->open(QIODevice::ReadOnly)); FileTransferJob* ft = new FileTransferJob(dj->getPayload(), uj->transferInfo()[QStringLiteral("size")].toInt(), QUrl::fromLocalFile(destFile)); QSignalSpy spyDownload(dj, &KJob::result); QSignalSpy spyTransfer(ft, &KJob::result); ft->start(); dj->start(); QVERIFY(spyTransfer.count() || spyTransfer.wait(1000000000)); if (ft->error()) qWarning() << "fterror" << ft->errorString(); QCOMPARE(ft->error(), 0); QCOMPARE(spyDownload.count(), 1); QCOMPARE(spyUpload.count(), 1); QFile resultFile(destFile), originFile(aFile); QVERIFY(resultFile.open(QIODevice::ReadOnly)); QVERIFY(originFile.open(QIODevice::ReadOnly)); const QByteArray resultContents = resultFile.readAll(), originContents = originFile.readAll(); QCOMPARE(resultContents.size(), originContents.size()); QCOMPARE(resultFile.readAll(), originFile.readAll()); } private: TestDaemon* m_daemon; }; QTEST_MAIN(TestSendFile); #include "sendfiletest.moc" diff --git a/urlhandler/org.kde.kdeconnect.telhandler.desktop b/urlhandler/org.kde.kdeconnect.telhandler.desktop index 6b09937f..5468cefa 100644 --- a/urlhandler/org.kde.kdeconnect.telhandler.desktop +++ b/urlhandler/org.kde.kdeconnect.telhandler.desktop @@ -1,29 +1,28 @@ [Desktop Entry] Name=KDE Connect Phone URL Handler Name[ca]=Gestor d'URL de telèfons del KDE Connect Name[ca@valencia]=Gestor d'URL de telèfons del KDE Connect Name[cs]=Nástroj pro práci s URL telefonu v KDE Connect Name[da]=Telefon-URL-håndtering til KDE Connect -Name[es]=Controlador de URL de teléfonos de KDE Connect Name[eu]=KDE Connect-en URL-kudeatzailea Name[fr]=Gestionnaire d'URL téléphoniques de KDE Connect -Name[gl]=Manexador de URL de teléfono de KDE Connect Name[it]=Gestore URL del telefono di KDE Connect -Name[nl]=URL behandelaar van KDE-Connect-telefoon +Name[nl]=KDE-Connect behandelaar van telefoon-URL Name[nn]=Telefon-URL-handsamar for KDE Connect Name[pl]=KDE Connect - obsługa URL telefonu -Name[pt]=Tratamento de URL's Telefónicos do KDE Connect +Name[pt]=Tratamento de URL's no Telefone do KDE Connect +Name[sk]=Spracovač KDE Connect Phone URL Name[sr]=КДЕ‑конекцијин руковалац телефонским УРЛ‑овима Name[sr@ijekavian]=КДЕ‑конекцијин руковалац телефонским УРЛ‑овима Name[sr@ijekavianlatin]=KDE‑konekcijin rukovalac telefonskim URL‑ovima Name[sr@latin]=KDE‑konekcijin rukovalac telefonskim URL‑ovima Name[sv]=KDE-anslut hanterare av telefonwebbadress Name[tr]=KDE Connect Telefon URL İşleyici Name[uk]=Обробник телефонних адрес KDE Connect Name[x-test]=xxKDE Connect Phone URL Handlerxx Exec=kdeconnect-handler %U Icon=kdeconnect Type=Application NoDisplay=true MimeType=x-scheme-handler/tel