Expose pairing state for devices
Will allow to have information about whether we're pairing, mostly for better GUI. Pair-programmed with Albert Vaca
This commit is contained in:
parent
339ce7beea
commit
ea41d3786e
9 changed files with 99 additions and 25 deletions
|
@ -60,9 +60,11 @@ public:
|
|||
virtual bool linkShouldBeKeptAlive() { return false; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void receivedPackage(const NetworkPackage& np);
|
||||
void pairingRequest(PairingHandler* handler);
|
||||
void pairingRequestExpired(PairingHandler* handler);
|
||||
void pairStatusChanged(DeviceLink::PairStatus status);
|
||||
void pairingError(const QString &error);
|
||||
void receivedPackage(const NetworkPackage& np);
|
||||
|
||||
protected:
|
||||
QCA::PrivateKey mPrivateKey;
|
||||
|
|
|
@ -38,8 +38,6 @@ LanPairingHandler::LanPairingHandler(DeviceLink* deviceLink)
|
|||
|
||||
void LanPairingHandler::packageReceived(const NetworkPackage& np)
|
||||
{
|
||||
m_pairingTimeout.stop();
|
||||
|
||||
bool wantsPair = np.get<bool>(QStringLiteral("pair"));
|
||||
|
||||
if (wantsPair) {
|
||||
|
@ -57,7 +55,6 @@ void LanPairingHandler::packageReceived(const NetworkPackage& np)
|
|||
return;
|
||||
}
|
||||
|
||||
Daemon::instance()->askPairingConfirmation(this);
|
||||
setInternalPairStatus(RequestedByPeer);
|
||||
}
|
||||
|
||||
|
@ -93,14 +90,12 @@ bool LanPairingHandler::requestPairing()
|
|||
const bool success = deviceLink()->sendPackage(np);
|
||||
if (success) {
|
||||
setInternalPairStatus(Requested);
|
||||
m_pairingTimeout.start();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool LanPairingHandler::acceptPairing()
|
||||
{
|
||||
m_pairingTimeout.stop(); // Just in case it is started
|
||||
NetworkPackage np(PACKAGE_TYPE_PAIR, {{"pair", true}});
|
||||
bool success = deviceLink()->sendPackage(np);
|
||||
if (success) {
|
||||
|
@ -132,6 +127,18 @@ void LanPairingHandler::pairingTimeout()
|
|||
|
||||
void LanPairingHandler::setInternalPairStatus(LanPairingHandler::InternalPairStatus status)
|
||||
{
|
||||
if (status == Requested || status == RequestedByPeer) {
|
||||
m_pairingTimeout.start();
|
||||
} else {
|
||||
m_pairingTimeout.stop();
|
||||
}
|
||||
|
||||
if (m_status == RequestedByPeer && (status == NotPaired || status == Paired)) {
|
||||
Q_EMIT deviceLink()->pairingRequestExpired(this);
|
||||
} else if (status == RequestedByPeer) {
|
||||
Q_EMIT deviceLink()->pairingRequest(this);
|
||||
}
|
||||
|
||||
m_status = status;
|
||||
if (status == Paired) {
|
||||
deviceLink()->setPairStatus(DeviceLink::Paired);
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
|
||||
virtual void packageReceived(const NetworkPackage& np) = 0;
|
||||
virtual void unpair() = 0;
|
||||
virtual int pairingTimeoutMsec() const { return 30 * 1000; } // 30 seconds of timeout (default), subclasses that use different values should override
|
||||
static int pairingTimeoutMsec() { return 30 * 1000; } // 30 seconds of timeout (default), subclasses that use different values should override
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual bool requestPairing() = 0;
|
||||
|
|
|
@ -70,11 +70,7 @@ Daemon::Daemon(QObject *parent, bool testMode)
|
|||
//Read remebered paired devices
|
||||
const QStringList& list = KdeConnectConfig::instance()->trustedDevices();
|
||||
Q_FOREACH (const QString& id, list) {
|
||||
Device* device = new Device(this, id);
|
||||
connect(device, &Device::reachableChanged, this, &Daemon::onDeviceStatusChanged);
|
||||
connect(device, &Device::trustedChanged, this, &Daemon::onDeviceStatusChanged);
|
||||
d->mDevices[id] = device;
|
||||
Q_EMIT deviceAdded(id);
|
||||
addDevice(new Device(this, id));
|
||||
}
|
||||
|
||||
//Listen to new devices
|
||||
|
@ -185,11 +181,7 @@ void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink*
|
|||
if (!isDiscoveringDevices() && !device->isTrusted() && !dl->linkShouldBeKeptAlive()) {
|
||||
device->deleteLater();
|
||||
} else {
|
||||
connect(device, &Device::reachableChanged, this, &Daemon::onDeviceStatusChanged);
|
||||
connect(device, &Device::trustedChanged, this, &Daemon::onDeviceStatusChanged);
|
||||
d->mDevices[id] = device;
|
||||
|
||||
Q_EMIT deviceAdded(id);
|
||||
addDevice(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -250,6 +242,28 @@ QString Daemon::deviceIdByName(const QString &name) const
|
|||
return {};
|
||||
}
|
||||
|
||||
void Daemon::addDevice(Device* device)
|
||||
{
|
||||
const QString id = device->id();
|
||||
connect(device, &Device::reachableChanged, this, &Daemon::onDeviceStatusChanged);
|
||||
connect(device, &Device::trustedChanged, this, &Daemon::onDeviceStatusChanged);
|
||||
connect(device, &Device::pairingRequestsChanged, this, &Daemon::pairingRequestsChanged);
|
||||
connect(device, &Device::pairingRequestsChanged, this, [this, device]() { askPairingConfirmation(device); } );
|
||||
d->mDevices[id] = device;
|
||||
|
||||
Q_EMIT deviceAdded(id);
|
||||
}
|
||||
|
||||
QStringList Daemon::pairingRequests() const
|
||||
{
|
||||
QStringList ret;
|
||||
for(Device* dev: d->mDevices) {
|
||||
if (dev->hasPairingRequests())
|
||||
ret += dev->id();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Daemon::~Daemon()
|
||||
{
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ class KDECONNECTCORE_EXPORT Daemon
|
|||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.daemon")
|
||||
Q_PROPERTY(bool isDiscoveringDevices READ isDiscoveringDevices)
|
||||
Q_PROPERTY(QStringList pairingRequests READ pairingRequests NOTIFY pairingRequestsChanged)
|
||||
|
||||
public:
|
||||
explicit Daemon(QObject *parent, bool testMode = false);
|
||||
|
@ -48,12 +49,14 @@ public:
|
|||
|
||||
QList<Device*> devicesList() const;
|
||||
|
||||
virtual void askPairingConfirmation(PairingHandler *d) = 0;
|
||||
virtual void askPairingConfirmation(Device *device) = 0;
|
||||
virtual void reportError(const QString &title, const QString &description) = 0;
|
||||
virtual QNetworkAccessManager* networkAccessManager();
|
||||
|
||||
Device* getDevice(const QString& deviceId);
|
||||
|
||||
QStringList pairingRequests() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
Q_SCRIPTABLE void acquireDiscoveryMode(const QString &id);
|
||||
Q_SCRIPTABLE void releaseDiscoveryMode(const QString &id);
|
||||
|
@ -74,12 +77,14 @@ Q_SIGNALS:
|
|||
Q_SCRIPTABLE void deviceRemoved(const QString& id); //Note that paired devices will never be removed
|
||||
Q_SCRIPTABLE void deviceVisibilityChanged(const QString& id, bool isVisible);
|
||||
Q_SCRIPTABLE void announcedNameChanged(const QString &announcedName);
|
||||
Q_SCRIPTABLE void pairingRequestsChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink* dl);
|
||||
void onDeviceStatusChanged();
|
||||
|
||||
private:
|
||||
void addDevice(Device* device);
|
||||
bool isDiscoveringDevices() const;
|
||||
void removeDevice(Device* d);
|
||||
void cleanDevices();
|
||||
|
|
|
@ -251,9 +251,45 @@ void Device::addLink(const NetworkPackage& identityPackage, DeviceLink* link)
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
m_pairRequests.insert(handler);
|
||||
Q_EMIT pairingRequestsChanged();
|
||||
}
|
||||
|
||||
void Device::removePairingRequest(PairingHandler* handler)
|
||||
{
|
||||
m_pairRequests.remove(handler);
|
||||
Q_EMIT pairingRequestsChanged();
|
||||
}
|
||||
|
||||
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<DeviceLink*>(o));
|
||||
|
|
|
@ -44,6 +44,7 @@ class KDECONNECTCORE_EXPORT Device
|
|||
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 pairingRequestsChanged)
|
||||
|
||||
public:
|
||||
|
||||
|
@ -102,6 +103,8 @@ public:
|
|||
int protocolVersion() { return m_protocolVersion; }
|
||||
QStringList supportedPlugins() const { return m_supportedPlugins.toList(); }
|
||||
|
||||
bool hasPairingRequests() const { return !m_pairRequests.isEmpty(); }
|
||||
|
||||
public Q_SLOTS:
|
||||
///sends a @p np package to the device
|
||||
///virtual for testing purposes.
|
||||
|
@ -113,10 +116,15 @@ public Q_SLOTS:
|
|||
Q_SCRIPTABLE void unpair(); //from all links
|
||||
Q_SCRIPTABLE void reloadPlugins(); //from kconf
|
||||
|
||||
Q_SCRIPTABLE void acceptPairing();
|
||||
Q_SCRIPTABLE void rejectPairing();
|
||||
|
||||
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();
|
||||
|
@ -125,6 +133,8 @@ Q_SIGNALS:
|
|||
Q_SCRIPTABLE void pairingError(const QString& error);
|
||||
Q_SCRIPTABLE void nameChanged(const QString& name);
|
||||
|
||||
void pairingRequestsChanged();
|
||||
|
||||
private: //Methods
|
||||
static DeviceType str2type(const QString &deviceType);
|
||||
static QString type2str(DeviceType deviceType);
|
||||
|
@ -144,6 +154,7 @@ private: //Fields (TODO: dPointer!)
|
|||
//Capabilities stuff
|
||||
QMultiMap<QString, KdeConnectPlugin*> m_pluginsByIncomingCapability;
|
||||
QSet<QString> m_supportedPlugins;
|
||||
QSet<PairingHandler*> m_pairRequests;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Device*)
|
||||
|
|
|
@ -42,18 +42,17 @@ public:
|
|||
, m_nam(Q_NULLPTR)
|
||||
{}
|
||||
|
||||
void askPairingConfirmation(PairingHandler* d) override
|
||||
void askPairingConfirmation(Device* device) override
|
||||
{
|
||||
KNotification* notification = new KNotification(QStringLiteral("pairingRequest"),
|
||||
KNotification::Persistent);
|
||||
notification->setIconName(QStringLiteral("dialog-information"));
|
||||
notification->setComponentName(QStringLiteral("kdeconnect"));
|
||||
notification->setText(i18n("Pairing request from %1", getDevice(d->deviceLink()->deviceId())->name()));
|
||||
notification->setText(i18n("Pairing request from %1", device->name()));
|
||||
notification->setActions(QStringList() << i18n("Accept") << i18n("Reject"));
|
||||
connect(notification, &KNotification::ignored, d, &PairingHandler::rejectPairing);
|
||||
connect(notification, &KNotification::action1Activated, d, &PairingHandler::acceptPairing);
|
||||
connect(notification, &KNotification::action2Activated, d, &PairingHandler::rejectPairing);
|
||||
QTimer::singleShot(d->pairingTimeoutMsec(), notification, &KNotification::close); // close after pairing timeout, assuming that the peer uses the same timeout value
|
||||
// notification->setTimeout(PairingHandler::pairingTimeoutMsec());
|
||||
connect(notification, &KNotification::action1Activated, device, &Device::acceptPairing);
|
||||
connect(notification, &KNotification::action2Activated, device, &Device::rejectPairing);
|
||||
notification->sendEvent();
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
qWarning() << "error:" << title << description;
|
||||
}
|
||||
|
||||
void askPairingConfirmation(PairingHandler * d) override {
|
||||
void askPairingConfirmation(Device * d) override {
|
||||
d->acceptPairing();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue