[SCM] kdeconnect packaging branch, master, updated. debian/0.9g-1-1183-g9d69498
Maximiliano Curia
maxy at moszumanska.debian.org
Fri Oct 14 14:26:51 UTC 2016
Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/kdeconnect.git;a=commitdiff;h=1604309
The following commit has been merged in the master branch:
commit 1604309aceb22f9baaf4e606522df402b51423a6
Author: Albert Vaca <albertvaka at gmail.com>
Date: Fri Aug 30 19:10:43 2013 +0200
Added symmetric pairing
A KNotification asks to accept the pairing when the other ends requests it
---
daemon/daemon.cpp | 68 +++++-
daemon/default_args.h | 8 +
daemon/device.cpp | 232 ++++++++++++++++++---
daemon/device.h | 33 ++-
daemon/networkpackage.h | 3 -
daemon/networkpackagetypes.h | 1 +
.../plugins/notifications/notificationsplugin.cpp | 1 +
kcm/kcm.cpp | 103 +++++++--
kcm/kcm.h | 8 +-
kcm/kcm.ui | 186 +++++++++++------
libkdeconnect/devicesmodel.cpp | 6 +-
11 files changed, 497 insertions(+), 152 deletions(-)
diff --git a/daemon/daemon.cpp b/daemon/daemon.cpp
index 0004d53..98de7f2 100644
--- a/daemon/daemon.cpp
+++ b/daemon/daemon.cpp
@@ -29,6 +29,7 @@
#include <QDBusConnection>
#include <QNetworkSession>
#include <QNetworkConfigurationManager>
+#include <QSslKey>
#include <KIcon>
#include <KConfigGroup>
@@ -50,6 +51,58 @@ Daemon::Daemon(QObject *parent, const QList<QVariant>&)
qDebug() << "My id:" << uuid;
}
+ if (!config->group("myself").hasKey("privateKey")) {
+
+ //TODO: Generate
+
+ QByteArray key = QByteArray(
+ "-----BEGIN RSA PRIVATE KEY-----
"
+ "MIICXAIBAAKBgQCnKxy6aZrABVvbxuWqMPbohH4KRDBGqyO/OwxvUD1qHpqZ9cJT
"
+ "bgttiIaXzdQny5esf6brI6Di/ssIp9awdLBlMT+eR6zR7g446tbxaCFuUiL0QIei
"
+ "izEveTDNRbson/8DPJrn8/81doTeXsuV7YbqmtUGwdZ5kiocAW92ZZukdQIDAQAB
"
+ "AoGBAI18yuLoMQdnQblBne8vZDumsDsmPaoCfc4EP2ETi/d+kaHPxTryABAkJq7j
"
+ "kjZgdi6VGIUacbjOqK/Zxrcw/H460EwOUzh97Z4t9CDtDhz6t3ddT8CfbG2TUgbx
"
+ "Vv3mSYSUDBdNBV6YY4fyLtZl6oI2V+rBaFIT48+vAK9doKlhAkEA2ZKm9dc80IjU
"
+ "c/Wwn8ij+6ALs4Mpa0dPYivgZ2QhXiX5TfMymal2dDufkOH4wIUO+8vV8CSmmTRU
"
+ "8Lv/B3pY7QJBAMSxeJtTSFwBcGRaZKRMIqeuZ/yMMT4EqqIh1DjBpujCRKApVpkO
"
+ "kVx3Yu7xyOfniXBwujiYNSL6LrWdKykEsKkCQEr2UDgbtIRU4H4jhHtI8dbcSavL
"
+ "4RVpOFymqWZ2BVke1EqbJC/1Ry687DlK4h3Sulre3BMlTZEziqB25WN6L/ECQBJv
"
+ "B3yXG4rz35KoHhJ/yCeq4rf6c4r6aPt07Cy9iWT6/+96sFD72oet8KmwI0IIowrU
"
+ "pb80FJbIl6QRrL/VXrECQBDdeCAG6J3Cwm4ozQiDQyiNd1qJqWc4co9savJxLtEU
"
+ "s5L4Qwfrexm16oCJimGmsa5q6Y0n4f5gY+MRh3n+nQo=
"
+ "-----END RSA PRIVATE KEY-----
"
+ );
+
+ //Test for validity
+ //QSslKey privateKey(key.toAscii(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ //qDebug() << "Valid private key:" << !privateKey.isNull();
+
+ config->group("myself").writeEntry("privateKey", key);
+
+ }
+
+ if (!config->group("myself").hasKey("publicKey")) {
+
+ //TODO: Generate
+
+ QByteArray key = QByteArray(
+ "-----BEGIN PUBLIC KEY-----
"
+ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnKxy6aZrABVvbxuWqMPbohH4K
"
+ "RDBGqyO/OwxvUD1qHpqZ9cJTbgttiIaXzdQny5esf6brI6Di/ssIp9awdLBlMT+e
"
+ "R6zR7g446tbxaCFuUiL0QIeiizEveTDNRbson/8DPJrn8/81doTeXsuV7YbqmtUG
"
+ "wdZ5kiocAW92ZZukdQIDAQAB
"
+ "-----END PUBLIC KEY-----
"
+
+ );
+
+ //Test for validity
+ //QSslKey publicKey(key.toAscii(), QSsl::Rsa, QSsl::Pem, QSsl::PublicKey);
+ //qDebug() << "Valid public key:" << !publicKey.isNull();
+
+ config->group("myself").writeEntry("publicKey", key);
+
+ }
+
//Debugging
qDebug() << "Starting KdeConnect daemon";
@@ -58,13 +111,10 @@ Daemon::Daemon(QObject *parent, const QList<QVariant>&)
mLinkProviders.insert(new LoopbackLinkProvider());
//Read remebered paired devices
- const KConfigGroup& known = config->group("devices").group("paired");
+ const KConfigGroup& known = config->group("devices");
const QStringList& list = known.groupList();
- const QString defaultName("unnamed");
Q_FOREACH(const QString& id, list) {
- const KConfigGroup& data = known.group(id);
- const QString& name = data.readEntry<QString>("name", defaultName);
- Device* device = new Device(id, name);
+ Device* device = new Device(id);
connect(device, SIGNAL(reachableStatusChanged()), this, SLOT(onDeviceReachableStatusChanged()));
mDevices[id] = device;
Q_EMIT deviceAdded(id);
@@ -127,16 +177,12 @@ void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink*
if (mDevices.contains(id)) {
qDebug() << "It is a known device";
-
Device* device = mDevices[id];
device->addLink(dl);
-
} else {
qDebug() << "It is a new device";
- const QString& name = identityPackage.get<QString>("deviceName");
-
- Device* device = new Device(id, name, dl);
+ Device* device = new Device(identityPackage, dl);
connect(device, SIGNAL(reachableStatusChanged()), this, SLOT(onDeviceReachableStatusChanged()));
mDevices[id] = device;
@@ -157,7 +203,7 @@ void Daemon::onDeviceReachableStatusChanged()
if (!device->reachable()) {
- if (!device->paired()) {
+ if (!device->isPaired()) {
qDebug() << "Destroying device";
Q_EMIT deviceRemoved(id);
mDevices.remove(id);
diff --git a/daemon/default_args.h b/daemon/default_args.h
index 4cf0fce..ff1b7f7 100644
--- a/daemon/default_args.h
+++ b/daemon/default_args.h
@@ -41,11 +41,19 @@ struct default_arg<int> {
};
//Pointer types -> NULL (partial specialization)
+//NOTE: Comented because it doesn't makeno sense to send a pointer over the network, but I just left it here for reference --albertvaka
/*template<class T*>
struct default_arg<T*> {
static T* get() { NULL; }
};
*/
+
+//QByteArray-> empty qbytearray
+template<>
+struct default_arg<QByteArray> {
+ static QByteArray get() { return QByteArray(); }
+};
+
//QStrings -> empty string
template<>
struct default_arg<QString> {
diff --git a/daemon/device.cpp b/daemon/device.cpp
index 827f757..5f6876a 100644
--- a/daemon/device.cpp
+++ b/daemon/device.cpp
@@ -7,7 +7,10 @@
#include <KPluginSelector>
#include <KServiceTypeTrader>
#include <KPluginInfo>
+#include <KNotification>
+#include <KIcon>
+#include <QSslKey>
#include <QDebug>
#include "plugins/kdeconnectplugin.h"
@@ -16,36 +19,38 @@
#include "linkproviders/linkprovider.h"
#include "networkpackage.h"
-Device::Device(const QString& id, const QString& name)
+Device::Device(const QString& id)
{
m_deviceId = id;
+
+ KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
+ const KConfigGroup& data = config->group("devices").group(id);
+
+ const QString& name = data.readEntry<QString>("name", QString("unnamed"));
m_deviceName = name;
- m_paired = true;
- m_knownIdentiy = true;
- reloadPlugins();
+ const QByteArray& key = data.readEntry<QByteArray>("publicKey",QByteArray());
+ m_publicKey = QSslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PublicKey);
+
+ m_pairingRequested = false;
//Register in bus
QDBusConnection::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors);
}
-Device::Device(const QString& id, const QString& name, DeviceLink* link)
+Device::Device(const NetworkPackage& identityPackage, DeviceLink* dl)
{
+ m_deviceId = identityPackage.get<QString>("deviceId");
+ m_deviceName = identityPackage.get<QString>("deviceName");
- m_deviceId = id;
- m_deviceName = name;
- m_paired = false;
- m_knownIdentiy = true;
+ addLink(dl);
- addLink(link);
-
- reloadPlugins();
+ m_pairingRequested = false;
//Register in bus
QDBusConnection::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors);
-
}
Device::~Device()
@@ -67,7 +72,7 @@ void Device::reloadPlugins()
{
QMap< QString, KdeConnectPlugin* > newPluginMap;
- if (paired() && reachable()) { //Do not load any plugin for unpaired devices, nor useless loading them for unreachable devices
+ if (isPaired() && reachable()) { //Do not load any plugin for unpaired devices, nor useless loading them for unreachable devices
QString path = KStandardDirs().resourceDirs("config").first()+"kdeconnect/";
QMap<QString,QString> pluginStates = KSharedConfig::openConfig(path + id())->group("Plugins").entryMap();
@@ -114,21 +119,75 @@ void Device::reloadPlugins()
}
+//TODO
+QSslKey myPrivateKey() {
+
+ KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
+ const QString& key = config->group("myself").readEntry<QString>("privateKey",QString());
+
+ QSslKey privateKey(key.toAscii(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ qDebug() << "Valid public key:" << !privateKey.isNull();
-void Device::setPair(bool b)
+ return privateKey;
+
+}
+
+void Device::requestPair()
{
- m_paired = b;
+ if (isPaired() || m_pairingRequested) {
+ Q_EMIT pairingFailed(i18n("Already paired"));
+ return;
+ }
+ if (!reachable()) {
+ Q_EMIT pairingFailed(i18n("Device not reachable"));
+ return;
+ }
+
+ //Send our own public key
+ NetworkPackage np(PACKAGE_TYPE_PAIR);
+ np.set("pair", true);
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
- if (b) {
- qDebug() << name() << "paired";
- config->group("devices").group("paired").group(id()).writeEntry("name",name());
- Q_EMIT reachableStatusChanged();
- } else {
- qDebug() << name() << "unpaired";
- config->group("devices").group("paired").deleteGroup(id());
- //Do not Q_EMIT reachableStatusChanged() because we do not want it to suddenly disappear from device list
+ const QByteArray& key = config->group("myself").readEntry<QByteArray>("publicKey",QByteArray());
+ np.set("publicKey",key);
+ bool success = sendPackage(np);
+
+ if (!success) {
+ Q_EMIT pairingFailed(i18n("Error contacting device"));
+ return;
}
- reloadPlugins();
+
+ m_pairingRequested = true;
+ pairingTimer.start(20 * 1000);
+ connect(&pairingTimer, SIGNAL(timeout()),
+ this, SLOT(pairingTimeout()));
+
+}
+
+void Device::unpair()
+{
+ if (!isPaired()) return;
+
+ m_publicKey = QSslKey();
+ m_pairingRequested = false;
+ pairingTimer.stop();
+
+ KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
+ config->group("devices").deleteGroup(id());
+
+ if (reachable()) {
+ NetworkPackage np(PACKAGE_TYPE_PAIR);
+ np.set("pair", false);
+ sendPackage(np);
+ }
+
+ reloadPlugins(); //Will unload the plugins
+
+}
+
+void Device::pairingTimeout()
+{
+ m_pairingRequested = false;
+ Q_EMIT Q_EMIT pairingFailed("Timed out");
}
static bool lessThan(DeviceLink* p1, DeviceLink* p2)
@@ -182,9 +241,10 @@ void Device::removeLink(DeviceLink* link)
bool Device::sendPackage(const NetworkPackage& np) const
{
- if (!m_paired) {
- //qDebug() << "sendpackage disabled on untrusted device" << name();
- return false;
+ //Maybe we could block here any package that is not an identity or a pairing package
+
+ if (isPaired()) {
+
}
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
@@ -198,14 +258,118 @@ bool Device::sendPackage(const NetworkPackage& np) const
void Device::privateReceivedPackage(const NetworkPackage& np)
{
- if (np.type() == "kdeconnect.identity" && !m_knownIdentiy) {
- m_deviceName = np.get<QString>("deviceName");
- } else if (m_paired) {
- //qDebug() << "package received from trusted device" << name();
- Q_EMIT receivedPackage(np);
+
+ if (np.type() == PACKAGE_TYPE_PAIR) {
+
+ qDebug() << "Pair package";
+
+ bool pair = np.get<bool>("pair");
+ if (pair == isPaired()) {
+ qDebug() << "Already" << (pair? "paired":"unpaired");
+ return;
+ }
+
+ KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
+
+ if (pair) {
+
+ if (m_pairingRequested) { //We started pairing
+
+ qDebug() << "Pair answer";
+
+ m_pairingRequested = false;
+ pairingTimer.stop();
+
+ //Store as trusted device
+ const QByteArray& key = np.get<QByteArray>("publicKey");
+ config->group("devices").group(id()).writeEntry("publicKey",key);
+ config->group("devices").group(id()).writeEntry("name",name());
+ m_publicKey = QSslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PublicKey);
+
+ Q_EMIT pairingSuccesful();
+
+ } else {
+
+ qDebug() << "Pair request";
+
+ const QString& key = np.get<QString>("publicKey");
+ m_tempPublicKey = QSslKey(key.toAscii(), QSsl::Rsa, QSsl::Pem, QSsl::PublicKey);
+
+ KNotification* notification = new KNotification("pingReceived"); //KNotification::Persistent
+ notification->setPixmap(KIcon("dialog-information").pixmap(48, 48));
+ notification->setComponentData(KComponentData("kdeconnect", "kdeconnect"));
+ notification->setTitle("KDE Connect");
+ notification->setText(i18n("Pairing request from %1", m_deviceName));
+ notification->setActions(QStringList() << i18n("Accept") << i18n("Reject"));
+ connect(notification, SIGNAL(action1Activated()), this, SLOT(acceptPairing()));
+ connect(notification, SIGNAL(action2Activated()), this, SLOT(rejectPairing()));
+ notification->sendEvent();
+
+ }
+
+ } else {
+
+ qDebug() << "Unpair request";
+ if (m_pairingRequested) {
+ pairingTimer.stop();
+ Q_EMIT pairingFailed(i18n("Canceled by other peer"));
+ }
+ unpair();
+
+ }
+
+ } else if (!isPaired()) {
+
+ //TODO: Alert the other side that we don't trust them
+ qDebug() << "device" << name() << "not paired, ignoring package" << np.type();
+
} else {
- qDebug() << "device" << name() << "not trusted, ignoring package" << np.type();
+
+ //Forward signal
+ Q_EMIT receivedPackage(np);
+
}
+
+}
+
+void Device::acceptPairing()
+{
+ qDebug() << "Accepted pairing";
+
+ KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
+
+ //Send our own public key
+ NetworkPackage np(PACKAGE_TYPE_PAIR);
+ np.set("pair", true);
+ const QByteArray& key = config->group("myself").readEntry<QByteArray>("publicKey",QByteArray());
+ np.set("publicKey",key);
+ bool success = sendPackage(np);
+
+ if (!success) {
+ return;
+ }
+
+ //Store as trusted device
+ m_publicKey = m_tempPublicKey;
+ config->group("devices").group(id()).writeEntry("publicKey", m_tempPublicKey.toPem());
+ config->group("devices").group(id()).writeEntry("name", name());
+
+ reloadPlugins(); //This will load plugins
+}
+
+void Device::rejectPairing()
+{
+ qDebug() << "Rejected pairing";
+
+ NetworkPackage np(PACKAGE_TYPE_PAIR);
+ np.set("pair", false);
+ sendPackage(np);
+
+ KNotification* notification = (KNotification*)sender();
+ notification->setActions(QStringList());
+ notification->setText(i18n("Pairing rejected"));
+ notification->update();
+
}
QStringList Device::availableLinks() const
diff --git a/daemon/device.h b/daemon/device.h
index aaeee3d..edcaadf 100644
--- a/daemon/device.h
+++ b/daemon/device.h
@@ -25,6 +25,8 @@
#include <QDBusConnection>
#include <QString>
#include <QMap>
+#include <QSslKey>
+#include <QTimer>
#include "networkpackage.h"
@@ -40,11 +42,11 @@ class Device
Q_PROPERTY(QString name READ name)
public:
- //Device known from KConfig, we trust it but we need to wait for a incoming devicelink to communicate
- Device(const QString& id, const QString& name);
+ //Read device from KConfig, we already know it but we need to wait for a incoming devicelink to communicate
+ Device(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(const QString& id, const QString& name, DeviceLink* dl);
+ Device(const NetworkPackage& np, DeviceLink* dl);
virtual ~Device();
@@ -57,8 +59,8 @@ public:
void removeLink(DeviceLink*);
Q_SCRIPTABLE QStringList availableLinks() const;
- Q_SCRIPTABLE bool trusted() const { return m_paired; }
- Q_SCRIPTABLE bool paired() const { return m_paired; }
+ Q_SCRIPTABLE bool isPaired() const { return !m_publicKey.isNull(); }
+ Q_SCRIPTABLE bool pairRequested() const { return m_pairingRequested; }
Q_SCRIPTABLE bool reachable() const { return !m_deviceLinks.empty(); }
Q_SCRIPTABLE bool hasPlugin(const QString& name);
Q_SCRIPTABLE QStringList loadedPlugins();
@@ -69,28 +71,37 @@ Q_SIGNALS:
public Q_SLOTS:
virtual bool sendPackage(const NetworkPackage& np) const;
- //Dbus operations called from kcm
+ //Dbus operations
public Q_SLOTS:
- Q_SCRIPTABLE void setPair(bool b);
- Q_SCRIPTABLE void reloadPlugins(); //From settings
+ Q_SCRIPTABLE void requestPair();
+ Q_SCRIPTABLE void unpair();
+ Q_SCRIPTABLE void reloadPlugins(); //From kconf
Q_SCRIPTABLE void sendPing();
+ void acceptPairing();
+ void rejectPairing();
private Q_SLOTS:
+ void privateReceivedPackage(const NetworkPackage& np);
void linkDestroyed(QObject* o = 0);
- virtual void privateReceivedPackage(const NetworkPackage& np);
+ void pairingTimeout();
Q_SIGNALS:
Q_SCRIPTABLE void reachableStatusChanged();
Q_SCRIPTABLE void pluginsChanged();
+ Q_SCRIPTABLE void pairingSuccesful();
+ Q_SCRIPTABLE void pairingFailed(const QString& error);
private:
- bool m_paired;
QString m_deviceId;
QString m_deviceName;
+ QSslKey m_publicKey;
+ QSslKey m_tempPublicKey;
+ bool m_pairingRequested;
+
QList<DeviceLink*> m_deviceLinks;
QMap<QString, KdeConnectPlugin*> m_plugins;
- bool m_knownIdentiy;
+ QTimer pairingTimer;
};
Q_DECLARE_METATYPE(Device*)
diff --git a/daemon/networkpackage.h b/daemon/networkpackage.h
index 92c8d69..a2db3b5 100644
--- a/daemon/networkpackage.h
+++ b/daemon/networkpackage.h
@@ -48,9 +48,6 @@ public:
static void unserialize(const QByteArray&, NetworkPackage*);
QByteArray serialize() const;
- static void rsaUnserialize(const QByteArray&, NetworkPackage*, Qssl );
- QByteArray rsaSerialize() const;
-
static void createIdentityPackage(NetworkPackage*);
long id() const { return mId; }
diff --git a/daemon/networkpackagetypes.h b/daemon/networkpackagetypes.h
index 96ccaab..618a9bf 100644
--- a/daemon/networkpackagetypes.h
+++ b/daemon/networkpackagetypes.h
@@ -22,6 +22,7 @@
#define NETWORKPACKAGETYPES_H
#define PACKAGE_TYPE_IDENTITY QString("kdeconnect.identity")
+#define PACKAGE_TYPE_PAIR QString("kdeconnect.pair")
#define PACKAGE_TYPE_PING QString("kdeconnect.ping")
#define PACKAGE_TYPE_NOTIFICATION QString("kdeconnect.notification")
#define PACKAGE_TYPE_BATTERY QString("kdeconnect.battery")
diff --git a/daemon/plugins/notifications/notificationsplugin.cpp b/daemon/plugins/notifications/notificationsplugin.cpp
index 691677a..4df6dc5 100644
--- a/daemon/plugins/notifications/notificationsplugin.cpp
+++ b/daemon/plugins/notifications/notificationsplugin.cpp
@@ -57,6 +57,7 @@ NotificationsPlugin::~NotificationsPlugin()
bool NotificationsPlugin::receivePackage(const NetworkPackage& np)
{
if (np.type() != PACKAGE_TYPE_NOTIFICATION) return false;
+ if (np.get<bool>("request")) return false;
notificationsDbusInterface->processPackage(np);
diff --git a/kcm/kcm.cpp b/kcm/kcm.cpp
index 8d97e0e..3a65cbe 100644
--- a/kcm/kcm.cpp
+++ b/kcm/kcm.cpp
@@ -59,6 +59,8 @@ KdeConnectKcm::KdeConnectKcm(QWidget *parent, const QVariantList&)
kcmUi->deviceList->setModel(sortProxyModel);
kcmUi->deviceInfo->setVisible(false);
+ kcmUi->progressBar->setVisible(false);
+ kcmUi->messages->setVisible(false);
setButtons(KCModule::NoAdditionalButton);
@@ -66,12 +68,12 @@ KdeConnectKcm::KdeConnectKcm(QWidget *parent, const QVariantList&)
this, SLOT(resetSelection()));
connect(kcmUi->deviceList, SIGNAL(pressed(QModelIndex)),
this, SLOT(deviceSelected(QModelIndex)));
+ connect(kcmUi->pair_button, SIGNAL(pressed()),
+ this, SLOT(requestPair()));
+ connect(kcmUi->unpair_button, SIGNAL(pressed()),
+ this, SLOT(unpair()));
connect(kcmUi->ping_button, SIGNAL(pressed()),
this, SLOT(sendPing()));
- connect(kcmUi->trust_checkbox, SIGNAL(toggled(bool)),
- this, SLOT(trustedStateChanged(bool)));
-
-
}
@@ -85,6 +87,7 @@ void KdeConnectKcm::resetSelection()
kcmUi->deviceList->selectionModel()->setCurrentIndex(sortProxyModel->mapFromSource(currentIndex), QItemSelectionModel::ClearAndSelect);
}
+
void KdeConnectKcm::deviceSelected(const QModelIndex& current)
{
@@ -105,13 +108,33 @@ void KdeConnectKcm::deviceSelected(const QModelIndex& current)
return;
}
+ kcmUi->messages->setVisible(false);
+ if (currentDevice->pairRequested()) {
+ kcmUi->progressBar->setVisible(true);
+ kcmUi->unpair_button->setVisible(false);
+ kcmUi->pair_button->setVisible(false);
+ kcmUi->ping_button->setVisible(false);
+ } else {
+ kcmUi->progressBar->setVisible(false);
+ if (currentDevice->isPaired()) {
+ kcmUi->unpair_button->setVisible(true);
+ kcmUi->pair_button->setVisible(false);
+ kcmUi->ping_button->setVisible(true);
+ } else {
+ kcmUi->unpair_button->setVisible(false);
+ kcmUi->pair_button->setVisible(true);
+ kcmUi->ping_button->setVisible(false);
+ }
+ }
+
+
//FIXME: 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->verticalLayout_2->addWidget(kcmUi->pluginSelector);
- kcmUi->deviceName->setText(currentDevice->name());
- kcmUi->trust_checkbox->setChecked(currentDevice->paired());
+ kcmUi->name_label->setText(currentDevice->name());
+ kcmUi->status_label->setText(currentDevice->isPaired()? "paired" : "unpaired");
KService::List offers = KServiceTypeTrader::self()->query("KdeConnect/Plugin");
QList<KPluginInfo> scriptinfos = KPluginInfo::fromServices(offers);
@@ -124,22 +147,58 @@ void KdeConnectKcm::deviceSelected(const QModelIndex& current)
this, SLOT(pluginsConfigChanged()));
}
-void KdeConnectKcm::trustedStateChanged(bool b)
+void KdeConnectKcm::requestPair()
{
if (!currentDevice) return;
- QDBusPendingReply<void> pendingReply = currentDevice->setPair(b);
- pendingReply.waitForFinished();
- if (pendingReply.isValid()) {
- //If dbus was down, calling this would make kcm crash
- devicesModel->deviceStatusChanged(currentDevice->id());
- } else {
- //Revert checkbox
- disconnect(kcmUi->trust_checkbox, SIGNAL(toggled(bool)),
- this, SLOT(trustedStateChanged(bool)));
- kcmUi->trust_checkbox->setCheckState(b? Qt::Unchecked : Qt::Checked);
- connect(kcmUi->trust_checkbox, SIGNAL(toggled(bool)),
- this, SLOT(trustedStateChanged(bool)));
- }
+
+ kcmUi->messages->hide();
+
+ kcmUi->pair_button->setVisible(false);
+ kcmUi->progressBar->setVisible(true);
+
+ connect(currentDevice,SIGNAL(pairingSuccesful()),
+ this, SLOT(pairingSuccesful()));
+ connect(currentDevice,SIGNAL(pairingFailed(QString)),
+ this, SLOT(pairingFailed(QString)));
+
+ currentDevice->requestPair();
+
+}
+
+void KdeConnectKcm::unpair()
+{
+ if (!currentDevice) return;
+
+ kcmUi->pair_button->setVisible(true);
+ kcmUi->unpair_button->setVisible(false);
+ kcmUi->progressBar->setVisible(false);
+ kcmUi->ping_button->setVisible(false);
+
+ currentDevice->unpair();
+
+ kcmUi->status_label->setText("(unpaired)");
+
+ devicesModel->deviceStatusChanged(currentDevice->id());
+}
+
+void KdeConnectKcm::pairingFailed(const QString& error)
+{
+ kcmUi->messages->setText("Error trying to pair: "+error);
+ kcmUi->messages->animatedShow();
+ kcmUi->progressBar->setVisible(false);
+ kcmUi->pair_button->setVisible(true);
+}
+
+void KdeConnectKcm::pairingSuccesful()
+{
+ kcmUi->progressBar->setVisible(false);
+ kcmUi->unpair_button->setVisible(true);
+ kcmUi->pair_button->setVisible(false);
+ kcmUi->ping_button->setVisible(true);
+
+ kcmUi->status_label->setText("(paired)");
+
+ devicesModel->deviceStatusChanged(currentDevice->id());
}
void KdeConnectKcm::pluginsConfigChanged()
@@ -147,8 +206,8 @@ void KdeConnectKcm::pluginsConfigChanged()
//Store previous selection
if (!currentDevice) return;
- DeviceDbusInterface* auxCurrentDevice = currentDevice; //HACK to avoid infinite recursion (for some reason calling save on pluginselector emits changed)
- currentDevice = 0;
+ DeviceDbusInterface* auxCurrentDevice = currentDevice;
+ currentDevice = 0; //HACK to avoid infinite recursion (for some reason calling save on pluginselector emits changed)
kcmUi->pluginSelector->save();
currentDevice = auxCurrentDevice;
diff --git a/kcm/kcm.h b/kcm/kcm.h
index 2fc8fd1..6dcbc55 100644
--- a/kcm/kcm.h
+++ b/kcm/kcm.h
@@ -56,10 +56,12 @@ private:
private Q_SLOTS:
void deviceSelected(const QModelIndex& current);
- void trustedStateChanged(bool);
+ void requestPair();
void pluginsConfigChanged();
void sendPing();
void resetSelection();
+ void pairingSuccesful();
+ void pairingFailed(const QString& error);
private:
Ui::KdeConnectKcmUi* kcmUi;
@@ -69,8 +71,8 @@ private:
DeviceDbusInterface* currentDevice;
QModelIndex currentIndex;
//KSharedConfigPtr config;
-
-
+public slots:
+ void unpair();
};
#endif
diff --git a/kcm/kcm.ui b/kcm/kcm.ui
index b9879b6..8b86b16 100644
--- a/kcm/kcm.ui
+++ b/kcm/kcm.ui
@@ -54,79 +54,129 @@
</property>
<layout class="QVBoxLayout" name="deviceInfoBorder">
<item>
- <widget class="QGroupBox" name="deviceInfo">
+ <widget class="QWidget" name="deviceInfo" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="title">
- <string/>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <property name="checkable">
- <bool>false</bool>
- </property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QLabel" name="deviceName">
- <property name="font">
- <font>
- <pointsize>10</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Device</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QCheckBox" name="trust_checkbox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Trust this device</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="ping_button">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Send ping</string>
- </property>
- </widget>
- </item>
- </layout>
+ <widget class="QWidget" name="header_2" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <layout class="QHBoxLayout" name="header">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMaximumSize</enum>
+ </property>
+ <item>
+ <widget class="QLabel" name="name_label">
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Device</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="status_label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>(status)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>0</number>
+ </property>
+ <property name="value">
+ <number>-1</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pair_button">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Request pair</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="unpair_button">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Unpair</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="ping_button">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Send ping</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="KMessageWidget" name="messages" native="true"/>
</item>
<item>
<widget class="KPluginSelector" name="pluginSelector" native="true">
@@ -156,6 +206,12 @@
<header>kpluginselector.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>KMessageWidget</class>
+ <extends>QWidget</extends>
+ <header>kmessagewidget.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<resources/>
<connections/>
diff --git a/libkdeconnect/devicesmodel.cpp b/libkdeconnect/devicesmodel.cpp
index 1fc81ec..ccca795 100644
--- a/libkdeconnect/devicesmodel.cpp
+++ b/libkdeconnect/devicesmodel.cpp
@@ -121,7 +121,7 @@ void DevicesModel::refreshDeviceList()
DeviceDbusInterface* deviceDbusInterface = new DeviceDbusInterface(id,this);
bool onlyPaired = (m_displayFilter & StatusPaired);
- if (onlyPaired && !deviceDbusInterface->paired()) continue;
+ if (onlyPaired && !deviceDbusInterface->isPaired()) continue;
bool onlyReachable = (m_displayFilter & StatusReachable);
if (onlyReachable && !deviceDbusInterface->reachable()) continue;
@@ -154,7 +154,7 @@ QVariant DevicesModel::data(const QModelIndex &index, int role) const
//FIXME: This function gets called lots of times, producing lots of dbus calls. Add a cache.
switch (role) {
case IconModelRole: {
- bool paired = device->paired();
+ bool paired = device->isPaired();
bool reachable = device->reachable();
QString icon = reachable? (paired? "user-online" : "user-busy") : "user-offline";
return KIcon(icon).pixmap(32, 32);
@@ -169,7 +169,7 @@ QVariant DevicesModel::data(const QModelIndex &index, int role) const
int status = StatusUnknown;
if (device->reachable()) {
status |= StatusReachable;
- if (device->paired()) status |= StatusPaired;
+ if (device->isPaired()) status |= StatusPaired;
}
return status;
}
--
kdeconnect packaging
More information about the pkg-kde-commits
mailing list