Commit 975892dc authored by Albert Vaca Cintora's avatar Albert Vaca Cintora

Yet another refactor, mostly moving code from from daemon class to device class

Device now has a public dbus interface
Removed wizard from kcm: now the main list shows all the devices and you can pair/unpair using a checkbox
Both Kde and Android now use unique device ids
parent 213e8ea9
......@@ -17,6 +17,7 @@ set(kded_kdeconnect_SRCS
device.cpp
${CMAKE_CURRENT_BINARY_DIR}/org.kde.kdeconnect.xml
${CMAKE_CURRENT_BINARY_DIR}/org.kde.kdeconnect.device.xml
)
kde4_add_plugin(kded_kdeconnect ${kded_kdeconnect_SRCS})
......@@ -36,7 +37,14 @@ qt4_generate_dbus_interface(
OPTIONS -a
)
qt4_generate_dbus_interface(
device.h
org.kde.kdeconnect.device.xml
OPTIONS -a
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kdeconnect.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kdeconnect.device.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR})
install(TARGETS kded_kdeconnect DESTINATION ${PLUGIN_INSTALL_DIR})
install(FILES kdeconnect.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kded)
install(FILES kdeconnect.notifyrc DESTINATION ${DATA_INSTALL_DIR}/kdeconnect)
......@@ -27,8 +27,9 @@
#include "devicelinks/devicelink.h"
#include "device.h"
class Announcer
: public QObject
class DeviceLink;
class Announcer : public QObject
{
Q_OBJECT
......@@ -42,13 +43,13 @@ public:
PRIORITY_HIGH = 100 //ie: lan
};
virtual QString getName() = 0;
virtual Priority getPriority() = 0;
virtual QString name() = 0;
virtual Priority priority() = 0;
virtual void setDiscoverable(bool b) = 0;
signals:
void deviceConnection(DeviceLink *);
void onNewDeviceLink(const QString& id, const QString& name, DeviceLink*);
signals:
......
......@@ -22,13 +22,16 @@
#include "devicelinks/udpdevicelink.h"
#include <QHostInfo>
AvahiAnnouncer::AvahiAnnouncer()
{
QString serviceType = "_kdeconnect._udp";
quint16 port = 10601;
//http://api.kde.org/4.x-api/kdelibs-apidocs/dnssd/html/index.html
service = new DNSSD::PublicService("KDE Host", serviceType, port);
service = new DNSSD::PublicService(QHostInfo::localHostName(), serviceType, port);
mUdpSocket = new QUdpSocket();
mUdpSocket->bind(port);
......@@ -60,15 +63,12 @@ void AvahiAnnouncer::readPendingNotifications()
QString id = np.deviceId();
QString name = np.body();
qDebug() << "AvahiAnnouncer creating link to device" << name;
qDebug() << "AvahiAnnouncer creating link to device" << id;
Device* device = new Device(id, name);
DeviceLink* dl = new UdpDeviceLink(device, sender, 10600);
DeviceLink* dl = new UdpDeviceLink(id, this, sender, 10600);
links.append(dl);
qDebug() << "Emitting link" << name;
emit deviceConnection(dl);
emit onNewDeviceLink(id, name, dl);
}
......
......@@ -38,13 +38,11 @@ public:
AvahiAnnouncer();
~AvahiAnnouncer();
QString getName() { return "Avahi"; }
Priority getPriority() { return PRIORITY_HIGH; }
QString name() { return "Avahi"; }
Priority priority() { return PRIORITY_HIGH; }
void setDiscoverable(bool b);
private Q_SLOTS:
void readPendingNotifications();
......
......@@ -23,18 +23,16 @@
FakeAnnouncer::FakeAnnouncer()
{
fakeDevice = new Device("fake","Fake device");
echoDeviceLink = new EchoDeviceLink(fakeDevice);
echoDeviceLink = new EchoDeviceLink("fake", this);
}
FakeAnnouncer::~FakeAnnouncer()
{
//delete echoDeviceLink;
//delete fakeDevice;
}
void FakeAnnouncer::setDiscoverable(bool b)
{
if (b) emit deviceConnection(echoDeviceLink);
if (b) emit onNewDeviceLink(echoDeviceLink->deviceId(),"Echo device", echoDeviceLink);
}
......@@ -23,20 +23,19 @@
#include "announcer.h"
class FakeAnnouncer
: public Announcer
class FakeAnnouncer : public Announcer
{
Q_OBJECT
public:
FakeAnnouncer();
~FakeAnnouncer();
QString getName() { return "FakeAnnouncer"; }
Priority getPriority() { return PRIORITY_LOW; }
QString name() { return "FakeAnnouncer"; }
Priority priority() { return PRIORITY_LOW; }
void setDiscoverable(bool b);
private:
Device* fakeDevice;
DeviceLink* echoDeviceLink;
};
......
......@@ -40,30 +40,15 @@
K_PLUGIN_FACTORY(KdeConnectFactory, registerPlugin<Daemon>();)
K_EXPORT_PLUGIN(KdeConnectFactory("kdeconnect", "kdeconnect"))
void Daemon::linkTo(DeviceLink* dl)
{
linkedDevices.append(dl);
Q_FOREACH (PackageReceiver* pr, packageReceivers) {
QObject::connect(dl,SIGNAL(receivedPackage(const NetworkPackage&)),
pr,SLOT(receivePackage(const NetworkPackage&)));
}
KNotification* notification = new KNotification("pingReceived"); //KNotification::Persistent
notification->setPixmap(KIcon("dialog-ok").pixmap(48, 48));
notification->setComponentData(KComponentData("kdeconnect", "kdeconnect"));
notification->setTitle(dl->device()->name());
notification->setText("Succesfully connected");
}
Daemon::Daemon(QObject *parent, const QList<QVariant>&)
: KDEDModule(parent)
, config(KSharedConfig::openConfig("kdeconnectrc"))
{
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
//Debugging
qDebug() << "GO GO GO!";
config->group("devices").group("paired").group("fake_unreachable").writeEntry("name","Fake device");
//TODO: Do not hardcode the load of the package receivers
//use: https://techbase.kde.org/Development/Tutorials/Services/Plugins
......@@ -81,117 +66,91 @@ Daemon::Daemon(QObject *parent, const QList<QVariant>&)
const KConfigGroup& known = config->group("devices").group("paired");
const QStringList& list = known.groupList();
const QString defaultName("unnamed");
Q_FOREACH(QString id, list) {
Q_FOREACH(const QString& id, list) {
const KConfigGroup& data = known.group(id);
const QString& name = data.readEntry<QString>("name",defaultName);
pairedDevices.push_back(new Device(id,name));
Device* device = new Device(id,name);
m_devices[id] = device;
Q_FOREACH (PackageReceiver* pr, packageReceivers) {
connect(device,SIGNAL(receivedPackage(const NetworkPackage&)),
pr,SLOT(receivePackage(const NetworkPackage&)));
}
}
QDBusConnection::sessionBus().registerService("org.kde.kdeconnect");
//Listen to incomming connections
Q_FOREACH (Announcer* a, announcers) {
QObject::connect(a,SIGNAL(deviceConnection(DeviceLink*)),
this,SLOT(deviceConnection(DeviceLink*)));
}
}
QString Daemon::listVisibleDevices()
{
std::stringstream ret;
ret << std::setw(20) << "ID";
ret << std::setw(20) << "Name";
ret << std::endl;
Q_FOREACH (DeviceLink* d, visibleDevices) {
ret << std::setw(20) << d->device()->id().toStdString();
ret << std::setw(20) << d->device()->name().toStdString();
ret << std::endl;
connect(a,SIGNAL(onNewDeviceLink(QString,QString,DeviceLink*)),
this,SLOT(onNewDeviceLink(QString,QString,DeviceLink*)));
}
QDBusConnection::sessionBus().registerService("org.kde.kdeconnect");
return QString::fromStdString(ret.str());
setDiscoveryEnabled(true);
}
void Daemon::startDiscovery(int timeOut)
void Daemon::setDiscoveryEnabled(bool b)
{
qDebug() << "Start discovery";
qDebug() << "Discovery:" << b;
//Listen to incomming connections
Q_FOREACH (Announcer* a, announcers) {
a->setDiscoverable(true);
a->setDiscoverable(b);
}
}
bool Daemon::pairDevice(QString id)
{
if (!visibleDevices.contains(id)) {
return false;
}
config->group("devices").group("paired").group(id).writeEntry("name",visibleDevices[id]->device()->name());
linkTo(visibleDevices[id]);
return true;
}
bool Daemon::unpairDevice(QString id)
QStringList Daemon::devices()
{
/*qDebug() << "M'han passat" << id;
foreach(QString c, config->group("devices").group("paired").groupList()) {
qDebug() << "Tinc" << c;
}*/
if (!config->group("devices").group("paired").hasGroup(id)) {
return false;
}
config->group("devices").group("paired").deleteGroup(id);
return true;
return m_devices.keys();
}
QString Daemon::listLinkedDevices()
void Daemon::onNewDeviceLink(const QString& id, const QString& name, DeviceLink* dl)
{
QString ret;
Q_FOREACH (DeviceLink* dl, linkedDevices) {
if (!ret.isEmpty()) ret += "\n";
//ret += dl->device()->name() + "(" + dl->device()->id() + ")";
ret += dl->device()->id();
qDebug() << "Device discovered" << dl->deviceId();
if (m_devices.contains(dl->deviceId())) {
Device* device = m_devices[dl->deviceId()];
device->addLink(dl);
KNotification* notification = new KNotification("pingReceived"); //KNotification::Persistent
notification->setPixmap(KIcon("dialog-ok").pixmap(48, 48));
notification->setComponentData(KComponentData("kdeconnect", "kdeconnect"));
notification->setTitle(device->name());
notification->setText("Succesfully connected");
emit deviceStatusChanged(id);
} else {
Device* device = new Device(id,name,dl);
m_devices[dl->deviceId()] = device;
Q_FOREACH (PackageReceiver* pr, packageReceivers) {
connect(device,SIGNAL(receivedPackage(const NetworkPackage&)),
pr,SLOT(receivePackage(const NetworkPackage&)));
}
emit newDeviceAdded(id);
}
return ret;
}
void Daemon::deviceConnection(DeviceLink* dl)
void Daemon::onLostDeviceLink(DeviceLink* dl)
{
qDebug() << "Device lost" << dl->deviceId();
qDebug() << "deviceConnection";
if (m_devices.contains(dl->deviceId())) {
Device* device = m_devices[dl->deviceId()];
device->removeLink(dl);
QString id = dl->device()->id();
bool paired = false;
Q_FOREACH (Device* d, pairedDevices) {
if (id == d->id()) {
paired = true;
break;
}
}
visibleDevices[dl->device()->id()] = dl;
KNotification* notification = new KNotification("pingReceived"); //KNotification::Persistent
notification->setPixmap(KIcon("dialog-ok").pixmap(48, 48));
notification->setComponentData(KComponentData("kdeconnect", "kdeconnect"));
notification->setTitle(device->name());
notification->setText("Disconnected");
if (paired) {
qDebug() << "Known device connected" << dl->device()->name();
linkTo(dl);
}
else {
qDebug() << "Unknown device connected" << dl->device()->name();
emit deviceDiscovered(dl->device()->id(), dl->device()->name());
} else {
qDebug() << "Lost unknown device, this should not happen (?)";
}
}
Daemon::~Daemon()
......
......@@ -49,57 +49,35 @@ class Daemon
: public KDEDModule
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect")
Q_CLASSINFO("D-Bus Interface", "kdeconnect.daemon")
public:
Daemon(QObject *parent, const QList<QVariant>&);
~Daemon();
private Q_SLOTS:
void deviceConnection(DeviceLink* dl);
public Q_SLOTS:
//After calling this, signal deviceDiscovered will be triggered for each device
Q_SCRIPTABLE void startDiscovery(int timeOut);
Q_SCRIPTABLE QString listVisibleDevices();
Q_SCRIPTABLE bool pairDevice(QString id);
Q_SCRIPTABLE bool unpairDevice(QString id);
Q_SCRIPTABLE void setDiscoveryEnabled(bool b);
/*
Q_SCRIPTABLE QString listPairedDevices(QString id);
Q_SCRIPTABLE bool linkAllPairedDevices();
*/
Q_SCRIPTABLE QString listLinkedDevices();
//Returns a list of ids. The respective devices can be manipulated using the dbus path: "/modules/kdeconnect/Devices/"+id
Q_SCRIPTABLE QStringList devices();
Q_SIGNALS:
Q_SCRIPTABLE void newDeviceAdded(const QString& id);
Q_SCRIPTABLE void deviceStatusChanged(const QString& id);
Q_SCRIPTABLE void deviceDiscovered(QString id, QString name);
//Q_SCRIPTABLE void deviceLost(QString id);
private:
private Q_SLOTS:
void linkTo(DeviceLink* dl);
KSharedConfigPtr config;
//(Non paired?) visible devices
QMap<QString, DeviceLink*> visibleDevices;
//All paired devices (should be stored and read from disk)
QVector<Device*> pairedDevices;
//Currently connected devices
QVector<DeviceLink*> linkedDevices;
void onNewDeviceLink(const QString& id, const QString& name, DeviceLink* dl);
void onLostDeviceLink(DeviceLink* dl);
private:
//Every known device
QMap<QString, Device*> m_devices;
//Different ways to find devices and connect to them, ordered by priority
QSet<Announcer*> announcers;
......
#include "device.h"
#include <ksharedptr.h>
#include <ksharedconfig.h>
#include "devicelinks/devicelink.h"
Device::Device(const QString& id, const QString& name) {
mDeviceId = id;
mDeviceName = name;
QDBusConnection::sessionBus().registerObject("module/kdeconnect/Devices/"+id, this);
#include <KConfigGroup>
#include <QDebug>
Device::Device(const QString& id, const QString& name)
{
m_deviceId = id;
m_deviceName = name;
m_paired = true;
m_knownIdentiy = true;
QDBusConnection::sessionBus().registerObject("/modules/kdeconnect/Devices/"+id, this, QDBusConnection::ExportScriptableContents);
}
Device::Device(const QString& id, const QString& name, DeviceLink* link)
{
m_deviceId = id;
m_deviceName = name;
m_paired = false;
m_knownIdentiy = true;
QDBusConnection::sessionBus().registerObject("/modules/kdeconnect/Devices/"+id, this, QDBusConnection::ExportScriptableContents);
addLink(link);
}
/*
Device::Device(const QString& id, const QString& name, DeviceLink* link)
{
m_deviceId = id;
m_deviceName = id; //Temporary name
m_paired = false;
m_knownIdentiy = false;
addLink(link);
NetworkPackage identityRequest;
identityRequest.setType("IDENTITY_REQUEST");
link->sendPackage(identityRequest);
QDBusConnection::sessionBus().registerObject("/modules/kdeconnect/Devices/"+id, this);
}
*/
void Device::setPair(bool b)
{
qDebug() << "setPair" << b;
m_paired = b;
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
if (b) {
qDebug() << name() << "paired";
config->group("devices").group("paired").group(id()).writeEntry("name",name());
} else {
qDebug() << name() << "unpaired";
config->group("devices").group("paired").deleteGroup(id());
}
}
static bool lessThan(DeviceLink* p1, DeviceLink* p2)
{
return p1->announcer()->priority() > p2->announcer()->priority();
}
void Device::addLink(DeviceLink* link)
{
Q_FOREACH(DeviceLink* existing, m_deviceLinks) {
//Do not add duplicate links
if (existing->announcer() == link->announcer()) return;
}
m_deviceLinks.append(link);
connect(link, SIGNAL(receivedPackage(NetworkPackage)), this, SLOT(privateReceivedPackage(NetworkPackage)));
qSort(m_deviceLinks.begin(),m_deviceLinks.end(),lessThan);
}
void Device::removeLink(DeviceLink* link)
{
disconnect(link, SIGNAL(receivedPackage(NetworkPackage)), this, SLOT(privateReceivedPackage(NetworkPackage)));
m_deviceLinks.remove(m_deviceLinks.indexOf(link));
}
void Device::sendPackage(const NetworkPackage& np)
{
m_deviceLinks.first()->sendPackage(np);
}
void Device::privateReceivedPackage(const NetworkPackage& np)
{
if (np.type() == "IDENTITY" && !m_knownIdentiy) {
m_deviceName = np.body();
} else if (m_paired) {
qDebug() << "package received from paired device";
emit receivedPackage(np);
} else {
qDebug() << "not paired, ignoring package";
}
}
void Device::sendPing()
{
qDebug() << "sendPing";
NetworkPackage np;
np.setType("PING");
sendPackage(np);
}
......@@ -24,28 +24,55 @@
#include <QObject>
#include <QDBusConnection>
#include <QString>
#include <qvector.h>
#include "devicelinks/devicelink.h"
class DeviceLink;
class Device : public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "kdeconnect.device")
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);
Q_SCRIPTABLE QString id() const{ return mDeviceId; }
Q_SCRIPTABLE QString name() const { return mDeviceName; }
Q_SCRIPTABLE bool paired() const { return mPaired; }
//Device known via a presentation package 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 known via discovery, we know nothing and have to ask for a presentation package
//(not supported yet, do we need it or we can rely on the device presenging itself?)
//Device(const QString& id, DeviceLink* dl);
void addLink(DeviceLink*);
void removeLink(DeviceLink*);
void pair() {
mPaired = true;
//TODO: Actually do something
void sendPackage(const NetworkPackage& np);
}
Q_SIGNALS:
void receivedPackage(const NetworkPackage& np);
public Q_SLOTS:
Q_SCRIPTABLE QString id() const{ return m_deviceId; }
Q_SCRIPTABLE QString name() const { return m_deviceName; }
Q_SCRIPTABLE bool paired() const { return m_paired; }
Q_SCRIPTABLE bool reachable() const { return !m_deviceLinks.empty(); }
Q_SCRIPTABLE void setPair(bool b);
Q_SCRIPTABLE void sendPing();
private Q_SLOTS:
void privateReceivedPackage(const NetworkPackage& np);
private:
bool mPaired;
QString mDeviceId;
QString mDeviceName;
bool m_paired;
QString m_deviceId;
QString m_deviceName;
QVector<DeviceLink*> m_deviceLinks;
bool m_knownIdentiy;
};
#endif // DEVICE_H
......@@ -20,8 +20,10 @@
#include "devicelink.h"
DeviceLink::DeviceLink(Device* d)
: mDevice(d)
DeviceLink::DeviceLink(const QString& deviceId, Announcer* parent)
: QObject(parent)
, mDeviceId(deviceId)
, mAnnouncer(parent)
{
//gcc complains if we don't add something to compile on a class with virtual functions
}
\ No newline at end of file
......@@ -24,8 +24,10 @@
#include <QObject>
#include "networkpackage.h"
#include <announcers/announcer.h>
class Device;
class Announcer;
class DeviceLink
: public QObject
......@@ -33,10 +35,10 @@ class DeviceLink
Q_OBJECT
public:
//TODO: Add QObject* parent
DeviceLink(Device* d);
DeviceLink(const QString& deviceId, Announcer* parent);
Device* device() { return mDevice; }
const QString& deviceId() { return mDeviceId; }
Announcer* announcer() { return mAnnouncer; }
virtual void sendPackage(const NetworkPackage& np) = 0;
......@@ -44,9 +46,9 @@ signals:
void receivedPackage(const NetworkPackage& np);
private:
Device* mDevice;
QString mDeviceId;
Announcer* mAnnouncer;
};
#endif // DEVICELINK_H
......@@ -19,3 +19,11 @@
*/
#include "echodevicelink.h"
#include "announcers/fakeannouncer.h"
EchoDeviceLink::EchoDeviceLink(const QString& d, FakeAnnouncer* a)
: DeviceLink(d, a)
{
}
......@@ -22,11 +22,13 @@
#define ECHODEVICELINK_H
#include "devicelink.h"
class EchoDeviceLink
: public DeviceLink
class FakeAnnouncer;
class EchoDeviceLink : public DeviceLink
{
Q_OBJECT
public:
EchoDeviceLink(Device* d) : DeviceLink(d) { }
EchoDeviceLink(const QString& d, FakeAnnouncer* a);
void sendPackage(const NetworkPackage& np) {
emit receivedPackage(np);
......
......@@ -19,10 +19,10 @@
*/
#include "udpdevicelink.h"
#include "announcers/avahiannouncer.h"
UdpDeviceLink::UdpDeviceLink(Device* d, QHostAddress ip, quint16 port)
: DeviceLink(d)
UdpDeviceLink::UdpDeviceLink(const QString& d, AvahiAnnouncer* a, QHostAddress ip, quint16 port)
: DeviceLink(d, a)
{
mIp = ip;
......
......@@ -27,13 +27,14 @@
#include "devicelink.h"
#include <qudpsocket.h>
class UdpDeviceLink
: public DeviceLink
class AvahiAnnouncer;
class UdpDeviceLink : public DeviceLink
{
Q_OBJECT
public:
UdpDeviceLink(Device* d, QHostAddress ip, quint16 port);
UdpDeviceLink(const QString& d, AvahiAnnouncer* a, QHostAddress ip, quint16 port);
void sendPackage(const NetworkPackage& np) {
mUdpSocket->writeDatagram(np.toString(), mIp, mPort);
......
......@@ -26,23 +26,33 @@
#include <string>
#include <iostream>
static QString decodeNextString(std::stringstream& ss) {
int length;
ss >> length;
char c[length];