Plugins are now owned by devices and not by daemon
Plugins can no longer emit networkpackages for *every* device. Plugins are stored in device, wich selectively loads them. A Device is needed in order to instantiate a Plugin (via PluginLoader) PluginLoader is a singleton, because every instance of Device need it. Added KPluginSelector in the KCM to select the plugins to load. Added architecture explanation to README Only PingPlugin is working by now.
This commit is contained in:
parent
9b7eecc69d
commit
88fab1f333
18 changed files with 337 additions and 188 deletions
42
README
42
README
|
@ -1,8 +1,41 @@
|
|||
The kdeconnect protocol:
|
||||
Class diagram
|
||||
==============
|
||||
|
||||
Backend_1 ... Backend_N
|
||||
\ | /
|
||||
Daemon
|
||||
/ | \
|
||||
Device_1 ... Device_N
|
||||
/ \
|
||||
|-Plugin_1 |-DeviceLink_1
|
||||
|-Plugin_2 |-DeviceLink_2
|
||||
|- ... |-...
|
||||
|-Plugin_N |-DeviceLink_N
|
||||
|
||||
|
||||
Daemon instantiates Backends
|
||||
|
||||
Backends manage to create DeviceLinks with the devices they can reach, and Q_EMIT them to Daemon.
|
||||
|
||||
When Daemon receives a DeviceLink from a backend it:
|
||||
- If he already knows the Device, adds the DeviceLink to the Device
|
||||
- If not, it creates a new Device.
|
||||
|
||||
Devices contain a list of DeviceLinks, plus a list of Plugins (instantiated automatically)
|
||||
|
||||
Information for and from Plugins is encapsulated in NetworkPackages.
|
||||
|
||||
When a DeviceLink receives a NetworkPackage from the device in the other end, Device will notify all the plugins.
|
||||
|
||||
When a Plugin wants to send a NetworkPackage, it does so using the pointer to Device
|
||||
|
||||
|
||||
|
||||
The NetworkPackage format
|
||||
=========================
|
||||
|
||||
Communication between heterogenous devices is achieved using NetworkPackages.
|
||||
NetworkPackages are independent and self-contained pieces of information that
|
||||
are sent from one device to another serialized in json.
|
||||
are sent from one device to another (via a DeviceLink) serialized in json.
|
||||
|
||||
The basic structure of a NetworkPackage is the following:
|
||||
|
||||
|
@ -16,5 +49,6 @@ The basic structure of a NetworkPackage is the following:
|
|||
}
|
||||
|
||||
Each type of package defines what it should contain inside its "body", so only
|
||||
the sender and receiver of this type of package need agree about it.
|
||||
the emisor Plugin and receiver Plugin of this type of package need agree about
|
||||
its content.
|
||||
|
||||
|
|
|
@ -57,13 +57,7 @@ Daemon::Daemon(QObject *parent, const QList<QVariant>&)
|
|||
//Debugging
|
||||
qDebug() << "Starting KdeConnect daemon";
|
||||
|
||||
//Load plugins
|
||||
PluginLoader *loader = new PluginLoader(this);
|
||||
connect(loader, SIGNAL(pluginLoaded(PackageInterface*)), this, SLOT(pluginLoaded(PackageInterface*)));
|
||||
loader->loadAllPlugins();
|
||||
|
||||
//Load backends (hardcoded by now)
|
||||
//use: https://techbase.kde.org/Development/Tutorials/Services/Plugins
|
||||
//Load backends (hardcoded by now, should be plugins in a future)
|
||||
mLinkProviders.insert(new BroadcastTcpLinkProvider());
|
||||
//mLinkProviders.insert(new AvahiTcpLinkProvider());
|
||||
//mLinkProviders.insert(new LoopbackLinkProvider());
|
||||
|
@ -77,12 +71,6 @@ Daemon::Daemon(QObject *parent, const QList<QVariant>&)
|
|||
const QString& name = data.readEntry<QString>("name", defaultName);
|
||||
Device* device = new Device(id, name);
|
||||
mDevices[id] = device;
|
||||
Q_FOREACH (PackageInterface* pr, mPackageInterfaces) {
|
||||
connect(device, SIGNAL(receivedPackage(const Device&, const NetworkPackage&)),
|
||||
pr, SLOT(receivePackage(const Device&, const NetworkPackage&)));
|
||||
connect(pr, SIGNAL(sendPackage(const NetworkPackage&)),
|
||||
device, SLOT(sendPackage(const NetworkPackage&)));
|
||||
}
|
||||
}
|
||||
|
||||
QNetworkSession* network = new QNetworkSession(QNetworkConfigurationManager().defaultConfiguration());
|
||||
|
@ -123,19 +111,6 @@ QStringList Daemon::devices()
|
|||
return mDevices.keys();
|
||||
}
|
||||
|
||||
void Daemon::pluginLoaded(PackageInterface* packageInterface)
|
||||
{
|
||||
qDebug() << "PLUUUUUUUUUUUUUUUUGINLOADEEEEEEEEEEEEEEEEEEEEEEED";
|
||||
mPackageInterfaces.append(packageInterface);
|
||||
Q_FOREACH(Device* device, mDevices) {
|
||||
connect(device, SIGNAL(receivedPackage(const Device&, const NetworkPackage&)),
|
||||
packageInterface, SLOT(receivePackage(const Device&, const NetworkPackage&)));
|
||||
connect(packageInterface, SIGNAL(sendPackage(const NetworkPackage&)),
|
||||
device, SLOT(sendPackage(const NetworkPackage&)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink* dl)
|
||||
{
|
||||
const QString& id = identityPackage.get<QString>("deviceId");
|
||||
|
@ -166,10 +141,7 @@ void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink*
|
|||
|
||||
Device* device = new Device(id, name, dl);
|
||||
mDevices[id] = device;
|
||||
Q_FOREACH (PackageInterface* pr, mPackageInterfaces) {
|
||||
connect(device, SIGNAL(receivedPackage(const Device&, const NetworkPackage&)),
|
||||
pr, SLOT(receivePackage(const Device&, const NetworkPackage&)));
|
||||
}
|
||||
|
||||
Q_EMIT newDeviceAdded(id);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,19 +72,14 @@ Q_SIGNALS:
|
|||
|
||||
private Q_SLOTS:
|
||||
void onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink* dl);
|
||||
void pluginLoaded(PackageInterface*);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
//Every known device
|
||||
QMap<QString, Device*> mDevices;
|
||||
|
||||
//Different ways to find devices and connect to them
|
||||
QSet<LinkProvider*> mLinkProviders;
|
||||
|
||||
//The classes that send and receive the packages
|
||||
QVector<PackageInterface*> mPackageInterfaces;
|
||||
//Every known device
|
||||
QMap<QString, Device*> mDevices;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -3,8 +3,14 @@
|
|||
#include <KSharedPtr>
|
||||
#include <KSharedConfig>
|
||||
#include <KConfigGroup>
|
||||
#include <KStandardDirs>
|
||||
#include <KPluginSelector>
|
||||
#include <KServiceTypeTrader>
|
||||
#include <KPluginInfo>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "plugins/pluginloader.h"
|
||||
#include "devicelinks/devicelink.h"
|
||||
#include "linkproviders/linkprovider.h"
|
||||
#include "networkpackage.h"
|
||||
|
@ -19,6 +25,7 @@ Device::Device(const QString& id, const QString& name)
|
|||
//Register in bus
|
||||
QDBusConnection::sessionBus().registerObject("/modules/kdeconnect/devices/"+id, this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors);
|
||||
|
||||
reloadPlugins();
|
||||
}
|
||||
|
||||
Device::Device(const QString& id, const QString& name, DeviceLink* link)
|
||||
|
@ -32,6 +39,8 @@ Device::Device(const QString& id, const QString& name, DeviceLink* link)
|
|||
QDBusConnection::sessionBus().registerObject("/modules/kdeconnect/devices/"+id, this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors);
|
||||
|
||||
addLink(link);
|
||||
|
||||
reloadPlugins();
|
||||
}
|
||||
/*
|
||||
Device::Device(const QString& id, const QString& name, DeviceLink* link)
|
||||
|
@ -50,6 +59,43 @@ Device::Device(const QString& id, const QString& name, DeviceLink* link)
|
|||
QDBusConnection::sessionBus().registerObject("/modules/kdeconnect/Devices/"+id, this);
|
||||
}
|
||||
*/
|
||||
|
||||
void Device::reloadPlugins()
|
||||
{
|
||||
|
||||
qDeleteAll(m_plugins);
|
||||
m_plugins.clear();
|
||||
|
||||
QString path = KStandardDirs().resourceDirs("config").first()+"kdeconnect/";
|
||||
QMap<QString,QString> pluginStates = KSharedConfig::openConfig(path + id())->group("Plugins").entryMap();
|
||||
|
||||
PluginLoader* loader = PluginLoader::instance();
|
||||
|
||||
//Code borrowed from KWin
|
||||
foreach (const QString& pluginName, loader->getPluginList()) {
|
||||
|
||||
const QString value = pluginStates.value(pluginName + QString::fromLatin1("Enabled"), QString());
|
||||
bool enabled = (value.isNull() ? true : QVariant(value).toBool()); //Enable all plugins by default
|
||||
|
||||
qDebug() << pluginName << "enabled:" << enabled;
|
||||
|
||||
if (enabled) {
|
||||
PackageInterface* plugin = loader->instantiatePluginForDevice(pluginName, this);
|
||||
|
||||
connect(this, SIGNAL(receivedPackage(const NetworkPackage&)),
|
||||
plugin, SLOT(receivePackage(const NetworkPackage&)));
|
||||
// connect(packageInterface, SIGNAL(sendPackage(const NetworkPackage&)),
|
||||
// device, SLOT(sendPackage(const NetworkPackage&)));
|
||||
|
||||
|
||||
m_plugins.append(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Device::setPair(bool b)
|
||||
{
|
||||
qDebug() << "setPair" << b;
|
||||
|
@ -122,10 +168,10 @@ 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 paired device";
|
||||
emit receivedPackage(*this, np);
|
||||
qDebug() << "package received from trusted device";
|
||||
Q_EMIT receivedPackage(np);
|
||||
} else {
|
||||
qDebug() << "not paired, ignoring package";
|
||||
qDebug() << "device" << name() << "not trusted, ignoring package" << np.type();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "devicelinks/devicelink.h"
|
||||
|
||||
class DeviceLink;
|
||||
class PackageInterface;
|
||||
|
||||
class Device
|
||||
: public QObject
|
||||
|
@ -38,7 +39,6 @@ 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);
|
||||
|
||||
|
@ -56,19 +56,20 @@ public:
|
|||
void addLink(DeviceLink*);
|
||||
void removeLink(DeviceLink*);
|
||||
|
||||
|
||||
//Send and receive
|
||||
Q_SIGNALS:
|
||||
void receivedPackage(const Device& device, const NetworkPackage& np);
|
||||
public Q_SLOTS:
|
||||
bool sendPackage(const NetworkPackage& np) const;
|
||||
|
||||
//Public dbus operations
|
||||
public Q_SLOTS:
|
||||
Q_SCRIPTABLE QStringList availableLinks() const;
|
||||
Q_SCRIPTABLE bool paired() const { return m_paired; }
|
||||
Q_SCRIPTABLE bool reachable() const { return !m_deviceLinks.empty(); }
|
||||
|
||||
//Send and receive
|
||||
Q_SIGNALS:
|
||||
void receivedPackage(const NetworkPackage& np);
|
||||
public Q_SLOTS:
|
||||
bool sendPackage(const NetworkPackage& np) const;
|
||||
|
||||
//Dbus operations called from kcm
|
||||
public Q_SLOTS:
|
||||
Q_SCRIPTABLE void setPair(bool b);
|
||||
Q_SCRIPTABLE void reloadPlugins();
|
||||
Q_SCRIPTABLE void sendPing();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -83,9 +84,12 @@ private:
|
|||
QString m_deviceId;
|
||||
QString m_deviceName;
|
||||
QList<DeviceLink*> m_deviceLinks;
|
||||
QList<PackageInterface*> m_plugins;
|
||||
bool m_knownIdentiy;
|
||||
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Device*)
|
||||
|
||||
#endif // DEVICE_H
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
|
||||
install(FILES kdeconnect_package_interface.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR})
|
||||
|
||||
add_subdirectory(ping)
|
||||
|
||||
|
|
|
@ -20,8 +20,17 @@
|
|||
|
||||
#include "packageinterface.h"
|
||||
|
||||
PackageInterface::PackageInterface(QObject* parent)
|
||||
#include <QPointer>
|
||||
|
||||
#include "../device.h"
|
||||
|
||||
PackageInterface::PackageInterface(QObject* parent, const QVariantList& args)
|
||||
: QObject(parent)
|
||||
{
|
||||
//gcc complains if we don't add something to compile on a class with virtual functions
|
||||
mDevice = qvariant_cast< Device* >(args.first());
|
||||
}
|
||||
|
||||
Device* PackageInterface::device()
|
||||
{
|
||||
return mDevice;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define PACKAGEINTERFACE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantList>
|
||||
|
||||
#include <kdemacros.h>
|
||||
#include <KPluginFactory>
|
||||
|
@ -40,17 +41,18 @@ class KDE_EXPORT PackageInterface
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PackageInterface(QObject* parent = 0);
|
||||
PackageInterface(QObject* parent, const QVariantList& args);
|
||||
virtual ~PackageInterface() { }
|
||||
Device* device();
|
||||
|
||||
public Q_SLOTS:
|
||||
//Returns true if it has handled the package in some way
|
||||
//device.sendPackage can be used to send an answer back to the device
|
||||
virtual bool receivePackage(const Device& device, const NetworkPackage& np) = 0;
|
||||
virtual bool receivePackage(const NetworkPackage& np) = 0;
|
||||
|
||||
private:
|
||||
Device* mDevice;
|
||||
|
||||
Q_SIGNALS:
|
||||
//Sends a package to *all* connected devices
|
||||
void sendPackage(const NetworkPackage& np);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,11 +8,6 @@ X-KDE-PluginInfo-Email=albertvaka@gmail.com
|
|||
X-KDE-PluginInfo-Name=kdeconnect_ping
|
||||
X-KDE-PluginInfo-Version=0.1
|
||||
X-KDE-PluginInfo-Website=http://albertvaka.wordpress.com
|
||||
X-KDE-PluginInfo-Category=Network
|
||||
X-KDE-PluginInfo-Depends=
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
X-KDE-PluginInfo-EnabledByDefault=true
|
||||
X-KDE-ParentApp=kdeconnect
|
||||
X-KDE-Version=4.0
|
||||
Name=Ping
|
||||
Comment=Send and receive pings
|
||||
|
|
|
@ -20,19 +20,20 @@
|
|||
|
||||
#include "pingpackageinterface.h"
|
||||
|
||||
#include <KDebug>
|
||||
#include <kicon.h>
|
||||
#include <KNotification>
|
||||
#include <KIcon>
|
||||
#include <QDebug>
|
||||
|
||||
K_PLUGIN_FACTORY( KdeConnectPluginFactory, registerPlugin< PingPackageInterface >(); )
|
||||
K_EXPORT_PLUGIN( KdeConnectPluginFactory("kdeconnect_ping", "kdeconnect_ping") )
|
||||
|
||||
PingPackageInterface::PingPackageInterface(QObject* parent, const QVariantList& args)
|
||||
: PackageInterface(parent)
|
||||
: PackageInterface(parent, args)
|
||||
{
|
||||
Q_UNUSED(args);
|
||||
qDebug() << "Plugin constructor for device" << device()->name();
|
||||
}
|
||||
|
||||
bool PingPackageInterface::receivePackage(const Device& device, const NetworkPackage& np)
|
||||
bool PingPackageInterface::receivePackage(const NetworkPackage& np)
|
||||
{
|
||||
|
||||
if (np.type() != PACKAGE_TYPE_PING) return false;
|
||||
|
@ -41,7 +42,7 @@ bool PingPackageInterface::receivePackage(const Device& device, const NetworkPac
|
|||
notification->setPixmap(KIcon("dialog-ok").pixmap(48, 48));
|
||||
notification->setComponentData(KComponentData("kdeconnect", "kdeconnect"));
|
||||
notification->setTitle("Ping!");
|
||||
notification->setText(device.name());
|
||||
notification->setText(device()->name());
|
||||
notification->sendEvent();
|
||||
|
||||
return true;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#ifndef PINGPACKAGEINTERFACE_H
|
||||
#define PINGPACKAGEINTERFACE_H
|
||||
|
||||
#include <knotification.h>
|
||||
#include <QObject>
|
||||
|
||||
#include "../packageinterface.h"
|
||||
|
||||
|
@ -33,7 +33,8 @@ class KDE_EXPORT PingPackageInterface
|
|||
public:
|
||||
explicit PingPackageInterface(QObject *parent, const QVariantList &args);
|
||||
|
||||
virtual bool receivePackage(const Device& device, const NetworkPackage& np);
|
||||
public Q_SLOTS:
|
||||
virtual bool receivePackage(const NetworkPackage& np);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -21,49 +21,58 @@
|
|||
#include "pluginloader.h"
|
||||
|
||||
#include "packageinterface.h"
|
||||
#include "plugins/ping/pingpackageinterface.h"
|
||||
|
||||
#include <KServiceTypeTrader>
|
||||
#include <KDebug>
|
||||
|
||||
PluginLoader::PluginLoader(QObject * parent)
|
||||
: QObject(parent)
|
||||
#include "../device.h"
|
||||
|
||||
PluginLoader* PluginLoader::instance()
|
||||
{
|
||||
static PluginLoader* instance = new PluginLoader();
|
||||
return instance;
|
||||
}
|
||||
|
||||
PluginLoader::~PluginLoader()
|
||||
PluginLoader::PluginLoader()
|
||||
{
|
||||
}
|
||||
|
||||
void PluginLoader::loadAllPlugins()
|
||||
{
|
||||
kDebug() << "Load all plugins";
|
||||
KService::List offers = KServiceTypeTrader::self()->query("KdeConnect/Plugin");
|
||||
|
||||
qDebug() << "LO TRAIGO DE OFERTA CHACHO" << offers;
|
||||
|
||||
KService::List::const_iterator iter;
|
||||
for(iter = offers.begin(); iter < offers.end(); ++iter)
|
||||
{
|
||||
QString error;
|
||||
for(KService::List::const_iterator iter = offers.begin(); iter < offers.end(); ++iter) {
|
||||
KService::Ptr service = *iter;
|
||||
plugins[service->library()] = service;
|
||||
}
|
||||
}
|
||||
|
||||
QStringList PluginLoader::getPluginList()
|
||||
{
|
||||
return plugins.keys();
|
||||
}
|
||||
|
||||
PackageInterface* PluginLoader::instantiatePluginForDevice(QString id, Device* device) {
|
||||
|
||||
KService::Ptr service = plugins[id];
|
||||
if (!service) {
|
||||
qDebug() << "Plugin unknown" << id;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
KPluginFactory *factory = KPluginLoader(service->library()).factory();
|
||||
|
||||
if (!factory)
|
||||
{
|
||||
//KMessageBox::error(0, i18n("<html><p>KPluginFactory could not load the plugin:<br /><i>%1</i></p></html>",
|
||||
// service->library()));
|
||||
kError(5001) << "KPluginFactory could not load the plugin:" << service->library();
|
||||
continue;
|
||||
if (!factory) {
|
||||
qDebug() << "KPluginFactory could not load the plugin:" << service->library();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PackageInterface *plugin = factory->create<PackageInterface>(this);
|
||||
QVariant deviceVariant;
|
||||
deviceVariant.setValue<Device*>(device);
|
||||
|
||||
if (plugin) {
|
||||
kDebug() << "Load plugin:" << service->name();
|
||||
emit pluginLoaded(plugin);
|
||||
} else {
|
||||
kDebug() << error;
|
||||
}
|
||||
//FIXME: create<PackageInterface> return NULL
|
||||
QObject *plugin = factory->create<QObject>(device, QVariantList() << deviceVariant);
|
||||
if (!plugin) {
|
||||
qDebug() << "Error loading plugin";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qDebug() << "Loaded plugin:" << service->name();
|
||||
return (PackageInterface*)plugin;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,21 +22,29 @@
|
|||
#define PACKAGEINTERFACELOADER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
|
||||
#include "packageinterface.h"
|
||||
|
||||
#include <KPluginFactory>
|
||||
#include <KService>
|
||||
|
||||
class PluginLoader : public QObject
|
||||
class Device;
|
||||
|
||||
class PluginLoader
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PluginLoader(QObject * parent);
|
||||
virtual ~PluginLoader();
|
||||
static PluginLoader* instance();
|
||||
PackageInterface* instantiatePluginForDevice(QString name, Device* device);
|
||||
QStringList getPluginList();
|
||||
|
||||
private:
|
||||
PluginLoader();
|
||||
QMap<QString,KService::Ptr> plugins;
|
||||
|
||||
void loadAllPlugins();
|
||||
|
||||
signals:
|
||||
void pluginLoaded(PackageInterface * plugin);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,7 +25,7 @@ target_link_libraries(kcm_kdeconnect
|
|||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
${KDE4_KDEUI_LIBRARY}
|
||||
${KDE4_KIO_LIBRARY}
|
||||
${KDE4_KCMUTILS_LIBS}
|
||||
)
|
||||
|
||||
add_dependencies(kcm_kdeconnect
|
||||
|
|
|
@ -118,7 +118,6 @@ QVariant DevicesModel::data(const QModelIndex &index, int role) const
|
|||
}
|
||||
|
||||
|
||||
qDebug() << index.row() << ">= " << m_deviceList.count() << (index.row() >= m_deviceList.count());
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= m_deviceList.count()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
|
61
kcm/kcm.cpp
61
kcm/kcm.cpp
|
@ -32,6 +32,8 @@
|
|||
#include <QDBusConnection>
|
||||
#include <QDBusInterface>
|
||||
|
||||
#include <KServiceTypeTrader>
|
||||
#include <KPluginInfo>
|
||||
#include <KDebug>
|
||||
#include <kpluginfactory.h>
|
||||
#include <kstandarddirs.h>
|
||||
|
@ -43,7 +45,8 @@ KdeConnectKcm::KdeConnectKcm(QWidget *parent, const QVariantList&)
|
|||
: KCModule(KdeConnectKcmFactory::componentData(), parent)
|
||||
, kcmUi(new Ui::KdeConnectKcmUi())
|
||||
, pairedDevicesList(new DevicesModel(this))
|
||||
, config(KSharedConfig::openConfig("kdeconnectrc"))
|
||||
, currentDevice(0)
|
||||
//, config(KSharedConfig::openConfig("kdeconnectrc"))
|
||||
{
|
||||
kcmUi->setupUi(this);
|
||||
|
||||
|
@ -52,6 +55,8 @@ KdeConnectKcm::KdeConnectKcm(QWidget *parent, const QVariantList&)
|
|||
|
||||
kcmUi->deviceInfo->setVisible(false);
|
||||
|
||||
setButtons(KCModule::NoAdditionalButton);
|
||||
|
||||
connect(kcmUi->deviceList, SIGNAL(pressed(QModelIndex)), this, SLOT(deviceSelected(QModelIndex)));
|
||||
connect(kcmUi->ping_button, SIGNAL(pressed()), this, SLOT(sendPing()));
|
||||
connect(kcmUi->trust_checkbox,SIGNAL(toggled(bool)), this, SLOT(trustedStateChanged(bool)));
|
||||
|
@ -64,27 +69,63 @@ KdeConnectKcm::~KdeConnectKcm()
|
|||
|
||||
void KdeConnectKcm::deviceSelected(const QModelIndex& current)
|
||||
{
|
||||
//Store previous selection
|
||||
pluginsConfigChanged();
|
||||
|
||||
//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);
|
||||
|
||||
bool valid = current.isValid();
|
||||
kcmUi->deviceInfo->setVisible(valid);
|
||||
if (!valid) return;
|
||||
selectedIndex = current;
|
||||
bool paired = pairedDevicesList->getDevice(current)->paired();
|
||||
kcmUi->trust_checkbox->setChecked(paired);
|
||||
|
||||
currentDevice = pairedDevicesList->getDevice(current);
|
||||
kcmUi->deviceName->setText(currentDevice->name());
|
||||
kcmUi->trust_checkbox->setChecked(currentDevice->paired());
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("KdeConnect/Plugin");
|
||||
QList<KPluginInfo> scriptinfos = KPluginInfo::fromServices(offers);
|
||||
|
||||
QString path = KStandardDirs().resourceDirs("config").first()+"kdeconnect/";
|
||||
KSharedConfigPtr deviceConfig = KSharedConfig::openConfig(path + currentDevice->id());
|
||||
kcmUi->pluginSelector->addPlugins(scriptinfos, KPluginSelector::ReadConfigFile, "Plugins", QString(), deviceConfig);
|
||||
|
||||
connect(kcmUi->pluginSelector, SIGNAL(changed(bool)), this, SLOT(pluginsConfigChanged()));
|
||||
}
|
||||
|
||||
void KdeConnectKcm::trustedStateChanged(bool b)
|
||||
{
|
||||
if (!selectedIndex.isValid()) return;
|
||||
DeviceDbusInterface* device = pairedDevicesList->getDevice(selectedIndex);
|
||||
device->setPair(b);
|
||||
pairedDevicesList->deviceStatusChanged(device->id());
|
||||
if (!currentDevice) return;
|
||||
currentDevice->setPair(b);
|
||||
pairedDevicesList->deviceStatusChanged(currentDevice->id());
|
||||
}
|
||||
|
||||
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;
|
||||
kcmUi->pluginSelector->save();
|
||||
currentDevice = auxCurrentDevice;
|
||||
|
||||
currentDevice->reloadPlugins();
|
||||
}
|
||||
|
||||
void KdeConnectKcm::save()
|
||||
{
|
||||
pluginsConfigChanged();
|
||||
KCModule::save();
|
||||
}
|
||||
|
||||
|
||||
void KdeConnectKcm::sendPing()
|
||||
{
|
||||
if (!selectedIndex.isValid()) return;
|
||||
pairedDevicesList->getDevice(selectedIndex)->sendPing();
|
||||
if (!currentDevice) return;
|
||||
currentDevice->sendPing();
|
||||
}
|
||||
|
||||
|
||||
|
|
10
kcm/kcm.h
10
kcm/kcm.h
|
@ -30,13 +30,13 @@
|
|||
#include "wizard.h"
|
||||
#include "devicesmodel.h"
|
||||
|
||||
class Create;
|
||||
class QModelIndex;
|
||||
class AccountsModel;
|
||||
class AccountWidget;
|
||||
class QStackedLayout;
|
||||
class QItemSelectionModel;
|
||||
class QDBusInterface;
|
||||
class DeviceDbusInterface;
|
||||
|
||||
namespace Ui {
|
||||
class KdeConnectKcmUi;
|
||||
|
@ -50,17 +50,21 @@ public:
|
|||
KdeConnectKcm(QWidget *parent, const QVariantList&);
|
||||
virtual ~KdeConnectKcm();
|
||||
|
||||
private:
|
||||
virtual void save();
|
||||
|
||||
private Q_SLOTS:
|
||||
void deviceSelected(const QModelIndex& current);
|
||||
void trustedStateChanged(bool);
|
||||
void pluginsConfigChanged();
|
||||
void sendPing();
|
||||
|
||||
private:
|
||||
Ui::KdeConnectKcmUi* kcmUi;
|
||||
DevicesModel* pairedDevicesList;
|
||||
AddDeviceWizard* addDeviceWizard;
|
||||
KSharedConfigPtr config;
|
||||
QModelIndex selectedIndex;
|
||||
DeviceDbusInterface* currentDevice;
|
||||
//KSharedConfigPtr config;
|
||||
|
||||
};
|
||||
|
||||
|
|
72
kcm/kcm.ui
72
kcm/kcm.ui
|
@ -45,7 +45,16 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="deviceInfoBorder">
|
||||
<widget class="QGroupBox" name="deviceInfoBorder_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="deviceInfoBorder">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="deviceInfo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -56,30 +65,37 @@
|
|||
<string/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="deviceInfo">
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<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::Vertical</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>215</height>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
|
@ -110,18 +126,20 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<widget class="KPluginSelector" name="pluginSelector" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>215</height>
|
||||
</size>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::WheelFocus</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -131,6 +149,14 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KPluginSelector</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>kpluginselector.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
Loading…
Reference in a new issue