Merge lp:~ken-vandine/ubuntu-system-settings/aethercast into lp:ubuntu-system-settings

Proposed by Ken VanDine
Status: Needs review
Proposed branch: lp:~ken-vandine/ubuntu-system-settings/aethercast
Merge into: lp:ubuntu-system-settings
Diff against target: 1744 lines (+1580/-7)
22 files modified
debian/control (+1/-0)
plugins/wifi/CMakeLists.txt (+23/-7)
plugins/wifi/PageComponent.qml (+7/-0)
plugins/wifi/WifiDisplays.qml (+113/-0)
plugins/wifi/aethercast/aethercast_device.cpp (+26/-0)
plugins/wifi/aethercast/aethercast_device.h (+76/-0)
plugins/wifi/aethercast/aethercast_helper.h (+29/-0)
plugins/wifi/aethercast/aethercast_manager.cpp (+26/-0)
plugins/wifi/aethercast/aethercast_manager.h (+79/-0)
plugins/wifi/aethercast/dbus-shared.h (+32/-0)
plugins/wifi/aethercast/device.cpp (+144/-0)
plugins/wifi/aethercast/device.h (+101/-0)
plugins/wifi/aethercast/devicemodel.cpp (+379/-0)
plugins/wifi/aethercast/devicemodel.h (+123/-0)
plugins/wifi/aethercast/displays.cpp (+122/-0)
plugins/wifi/aethercast/displays.h (+73/-0)
plugins/wifi/aethercast/freedesktop_objectmanager.cpp (+26/-0)
plugins/wifi/aethercast/freedesktop_objectmanager.h (+58/-0)
plugins/wifi/aethercast/freedesktop_properties.cpp (+26/-0)
plugins/wifi/aethercast/freedesktop_properties.h (+71/-0)
plugins/wifi/aethercast/org.aethercast.xml (+35/-0)
plugins/wifi/plugin.cpp (+10/-0)
To merge this branch: bzr merge lp:~ken-vandine/ubuntu-system-settings/aethercast
Reviewer Review Type Date Requested Status
system-apps-ci-bot continuous-integration Needs Fixing
PS Jenkins bot continuous-integration Needs Fixing
Ubuntu Touch System Settings Pending
Review via email: mp+282378@code.launchpad.net

Commit message

Aethercast settings UI

Description of the change

=== WIP ===

Aethercast settings UI

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1588. By Ken VanDine

fixed copyrights

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1589. By Ken VanDine

Added connect and disconnect

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1590. By Ken VanDine

refactored sources a bit to put the aethercast code in it's own directory to make it easier to move around if we move it to the displays plugin

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1591. By Ken VanDine

merged trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1592. By Ken VanDine

AddDevice

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1593. By Ken VanDine

merged trunk

1594. By Ken VanDine

Simon Fels 2016-03-09 Pass QString rather than QDBusObjectPath

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

1594. By Ken VanDine

Simon Fels 2016-03-09 Pass QString rather than QDBusObjectPath

1593. By Ken VanDine

merged trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2016-02-29 13:46:09 +0000
3+++ debian/control 2016-03-09 13:21:41 +0000
4@@ -65,6 +65,7 @@
5 ${shlibs:Depends},
6 accountsservice,
7 accountsservice-ubuntu-schemas (>= 0.0.3+14.10.20140829~),
8+ aethercast,
9 bluez (>= 5.23),
10 click | ubuntu-snappy-cli,
11 dbus-property-service [amd64 armhf i386],
12
13=== modified file 'plugins/wifi/CMakeLists.txt'
14--- plugins/wifi/CMakeLists.txt 2015-05-27 00:39:35 +0000
15+++ plugins/wifi/CMakeLists.txt 2016-03-09 13:21:41 +0000
16@@ -18,22 +18,38 @@
17 SectionMenuItem.qml
18 StandardMenuItem.qml
19 SwitchMenuItem.qml
20+WifiDisplays.qml
21 )
22
23 add_library(UbuntuWifiPanel MODULE
24- wifidbushelper.cpp
25+ aethercast/aethercast_device.cpp
26+ aethercast/aethercast_manager.cpp
27+ aethercast/device.cpp
28+ aethercast/devicemodel.cpp
29+ aethercast/displays.cpp
30+ aethercast/freedesktop_properties.cpp
31+ aethercast/freedesktop_objectmanager.cpp
32+ certhandler.cpp
33 plugin.cpp
34+ previousnetworkmodel.cpp
35 unitymenumodelstack.cpp
36- previousnetworkmodel.cpp
37- certhandler.cpp
38- wifidbushelper.h
39- plugin.h
40- unitymenumodelstack.h
41- previousnetworkmodel.h
42+ wifidbushelper.cpp
43+ aethercast/aethercast_helper.h
44+ aethercast/aethercast_device.h
45+ aethercast/aethercast_manager.h
46+ aethercast/device.h
47+ aethercast/devicemodel.h
48+ aethercast/displays.h
49+ aethercast/freedesktop_properties.h
50+ aethercast/freedesktop_objectmanager.h
51 certhandler.h
52 nm_manager_proxy.h
53 nm_settings_proxy.h
54 nm_settings_connection_proxy.h
55+ plugin.h
56+ previousnetworkmodel.h
57+ unitymenumodelstack.h
58+ wifidbushelper.h
59 ${QML_SOURCES}
60 )
61 qt5_use_modules(UbuntuWifiPanel Qml Quick DBus)
62
63=== modified file 'plugins/wifi/PageComponent.qml'
64--- plugins/wifi/PageComponent.qml 2015-08-10 13:31:45 +0000
65+++ plugins/wifi/PageComponent.qml 2016-03-09 13:21:41 +0000
66@@ -71,6 +71,13 @@
67 top: parent.top
68 }
69
70+ ListItem.SingleValue {
71+ objectName: "wifiDisplays"
72+ text: i18n.tr("Wi-Fi Displays")
73+ progression: true
74+ onClicked: pageStack.push(Qt.resolvedUrl("WifiDisplays.qml"))
75+ }
76+
77 Repeater {
78 id: mainMenu
79 model: menuStack.tail ? menuStack.tail : null
80
81=== added file 'plugins/wifi/WifiDisplays.qml'
82--- plugins/wifi/WifiDisplays.qml 1970-01-01 00:00:00 +0000
83+++ plugins/wifi/WifiDisplays.qml 2016-03-09 13:21:41 +0000
84@@ -0,0 +1,113 @@
85+/*
86+ * Copyright 2016 Canonical Ltd.
87+ *
88+ * This program is free software; you can redistribute it and/or modify
89+ * it under the terms of the GNU General Public License as published by
90+ * the Free Software Foundation; version 3.
91+ *
92+ * This program is distributed in the hope that it will be useful,
93+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
94+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
95+ * GNU General Public License for more details.
96+ *
97+ * You should have received a copy of the GNU General Public License
98+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
99+ */
100+
101+import QtQuick 2.4
102+import SystemSettings 1.0
103+import Ubuntu.Components 1.3
104+import Ubuntu.Components.ListItems 1.3 as ListItem
105+import Ubuntu.SystemSettings.Wifi 1.0
106+
107+ItemPage {
108+ id: wifiDisplays
109+ objectName: "wifiDisplays"
110+ title: i18n.tr("Wi-Fi Displays")
111+
112+ Flickable {
113+ id: pageFlickable
114+ anchors.fill: parent
115+ contentWidth: parent.width
116+ contentHeight: contentItem.childrenRect.height
117+
118+ Displays {
119+ id: displays
120+ onDevicesChanged: {
121+ console.warn("onDevicesChanged: " + devices);
122+ }
123+ onScanningChanged: {
124+ console.warn("onScanningChanged: " + scanning);
125+ }
126+ }
127+
128+ Column {
129+ anchors {
130+ left: parent.left
131+ right: parent.right
132+ top: parent.top
133+ }
134+
135+ ListItem.Standard {
136+ objectName: "wifiDisplays"
137+ text: i18n.tr("Wi-Fi Displays")
138+ control: Item {
139+ anchors.verticalCenter: parent.verticalCenter
140+ height: parent.height
141+ width: childrenRect.width
142+ ActivityIndicator {
143+ id: ind
144+ anchors.centerIn: parent
145+ running: displays.scanning
146+ visible: running
147+ }
148+ Icon {
149+ anchors.centerIn: parent
150+ height: units.gu(4)
151+ width: height
152+ visible: !ind.running
153+ name: "reload"
154+ MouseArea {
155+ anchors.fill: parent
156+ onClicked: {
157+ displays.scan();
158+ }
159+ }
160+ }
161+ }
162+ }
163+
164+ Repeater {
165+ id: mainMenu
166+ model: displays.devices ? displays.devices : null
167+ delegate: ListItem.Subtitled {
168+ id: displayDelegate
169+ anchors {
170+ left: parent.left
171+ right: parent.right
172+ }
173+ text: displayName
174+ subText: stateName
175+ Button {
176+ anchors.verticalCenter: parent.verticalCenter
177+ anchors.right: parent.right
178+ height: units.gu(4)
179+ visible: stateName !== "connecting"
180+ text: stateName === "connected" ? i18n.tr("Disconnect") : i18n.tr("Connect")
181+ onClicked: {
182+ if (stateName === "connected")
183+ displays.disconnectDevice(addressName);
184+ else
185+ displays.connectDevice(addressName);
186+ }
187+ }
188+ }
189+ }
190+ }
191+
192+ // Only allow flicking if the content doesn't fit on the page
193+ boundsBehavior: (contentHeight > wifiDisplays.height) ?
194+ Flickable.DragAndOvershootBounds :
195+ Flickable.StopAtBounds
196+ }
197+}
198
199=== added directory 'plugins/wifi/aethercast'
200=== added file 'plugins/wifi/aethercast/aethercast_device.cpp'
201--- plugins/wifi/aethercast/aethercast_device.cpp 1970-01-01 00:00:00 +0000
202+++ plugins/wifi/aethercast/aethercast_device.cpp 2016-03-09 13:21:41 +0000
203@@ -0,0 +1,26 @@
204+/*
205+ * This file was generated by qdbusxml2cpp version 0.8
206+ * Command line was: qdbusxml2cpp -c AethercastDevice -p aethercast_device org.aethercast.xml org.aethercast.Device
207+ *
208+ * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
209+ *
210+ * This is an auto-generated file.
211+ * This file may have been hand-edited. Look for HAND-EDIT comments
212+ * before re-generating it.
213+ */
214+
215+#include "aethercast_device.h"
216+
217+/*
218+ * Implementation of interface class AethercastDevice
219+ */
220+
221+AethercastDevice::AethercastDevice(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
222+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
223+{
224+}
225+
226+AethercastDevice::~AethercastDevice()
227+{
228+}
229+
230
231=== added file 'plugins/wifi/aethercast/aethercast_device.h'
232--- plugins/wifi/aethercast/aethercast_device.h 1970-01-01 00:00:00 +0000
233+++ plugins/wifi/aethercast/aethercast_device.h 2016-03-09 13:21:41 +0000
234@@ -0,0 +1,76 @@
235+/*
236+ * This file was generated by qdbusxml2cpp version 0.8
237+ * Command line was: qdbusxml2cpp -c AethercastDevice -p aethercast_device org.aethercast.xml org.aethercast.Device
238+ *
239+ * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
240+ *
241+ * This is an auto-generated file.
242+ * Do not edit! All changes made to it will be lost.
243+ */
244+
245+#ifndef AETHERCAST_DEVICE_H_1450292154
246+#define AETHERCAST_DEVICE_H_1450292154
247+
248+#include <QtCore/QObject>
249+#include <QtCore/QByteArray>
250+#include <QtCore/QList>
251+#include <QtCore/QMap>
252+#include <QtCore/QString>
253+#include <QtCore/QStringList>
254+#include <QtCore/QVariant>
255+#include <QtDBus/QtDBus>
256+
257+/*
258+ * Proxy class for interface org.aethercast.Device
259+ */
260+class AethercastDevice: public QDBusAbstractInterface
261+{
262+ Q_OBJECT
263+public:
264+ static inline const char *staticInterfaceName()
265+ { return "org.aethercast.Device"; }
266+
267+public:
268+ AethercastDevice(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
269+
270+ ~AethercastDevice();
271+
272+ Q_PROPERTY(QString Address READ address)
273+ inline QString address() const
274+ { return qvariant_cast< QString >(property("Address")); }
275+
276+ Q_PROPERTY(QStringList Capabilities READ capabilities)
277+ inline QStringList capabilities() const
278+ { return qvariant_cast< QStringList >(property("Capabilities")); }
279+
280+ Q_PROPERTY(QString Name READ name)
281+ inline QString name() const
282+ { return qvariant_cast< QString >(property("Name")); }
283+
284+ Q_PROPERTY(QString State READ state)
285+ inline QString state() const
286+ { return qvariant_cast< QString >(property("State")); }
287+
288+public Q_SLOTS: // METHODS
289+ inline QDBusPendingReply<> Connect(const QString &role)
290+ {
291+ QList<QVariant> argumentList;
292+ argumentList << QVariant::fromValue(role);
293+ return asyncCallWithArgumentList(QStringLiteral("Connect"), argumentList);
294+ }
295+
296+ inline QDBusPendingReply<> Disconnect()
297+ {
298+ QList<QVariant> argumentList;
299+ return asyncCallWithArgumentList(QStringLiteral("Disconnect"), argumentList);
300+ }
301+
302+Q_SIGNALS: // SIGNALS
303+};
304+
305+namespace org {
306+ namespace aethercast {
307+ typedef ::AethercastDevice Device;
308+ }
309+}
310+#endif
311
312=== added file 'plugins/wifi/aethercast/aethercast_helper.h'
313--- plugins/wifi/aethercast/aethercast_helper.h 1970-01-01 00:00:00 +0000
314+++ plugins/wifi/aethercast/aethercast_helper.h 2016-03-09 13:21:41 +0000
315@@ -0,0 +1,29 @@
316+/*
317+ * Copyright (C) 2016 Canonical Ltd
318+ *
319+ * This program is free software: you can redistribute it and/or modify
320+ * it under the terms of the GNU General Public License version 3 as
321+ * published by the Free Software Foundation.
322+ *
323+ * This program is distributed in the hope that it will be useful,
324+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
325+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
326+ * GNU General Public License for more details.
327+ *
328+ * You should have received a copy of the GNU General Public License
329+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
330+ *
331+*/
332+
333+#ifndef AETHERCAST_HELPER_H_
334+#define AETHERCAST_HELPER_H_
335+
336+#include <QObject>
337+
338+typedef QMap<QString, QVariantMap> InterfaceList;
339+typedef QMap<QDBusObjectPath, InterfaceList> ManagedObjectList;
340+
341+Q_DECLARE_METATYPE(InterfaceList)
342+Q_DECLARE_METATYPE(ManagedObjectList)
343+
344+#endif
345
346=== added file 'plugins/wifi/aethercast/aethercast_manager.cpp'
347--- plugins/wifi/aethercast/aethercast_manager.cpp 1970-01-01 00:00:00 +0000
348+++ plugins/wifi/aethercast/aethercast_manager.cpp 2016-03-09 13:21:41 +0000
349@@ -0,0 +1,26 @@
350+/*
351+ * This file was generated by qdbusxml2cpp version 0.8
352+ * Command line was: qdbusxml2cpp -c AethercastManager -p aethercast_manager org.aethercast.xml org.aethercast.Manager
353+ *
354+ * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
355+ *
356+ * This is an auto-generated file.
357+ * This file may have been hand-edited. Look for HAND-EDIT comments
358+ * before re-generating it.
359+ */
360+
361+#include "aethercast_manager.h"
362+
363+/*
364+ * Implementation of interface class AethercastManager
365+ */
366+
367+AethercastManager::AethercastManager(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
368+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
369+{
370+}
371+
372+AethercastManager::~AethercastManager()
373+{
374+}
375+
376
377=== added file 'plugins/wifi/aethercast/aethercast_manager.h'
378--- plugins/wifi/aethercast/aethercast_manager.h 1970-01-01 00:00:00 +0000
379+++ plugins/wifi/aethercast/aethercast_manager.h 2016-03-09 13:21:41 +0000
380@@ -0,0 +1,79 @@
381+/*
382+ * This file was generated by qdbusxml2cpp version 0.8
383+ * Command line was: qdbusxml2cpp -c AethercastManager -p aethercast_manager org.aethercast.xml org.aethercast.Manager
384+ *
385+ * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
386+ *
387+ * This is an auto-generated file.
388+ * Do not edit! All changes made to it will be lost.
389+ */
390+
391+#ifndef AETHERCAST_MANAGER_H_1450292154
392+#define AETHERCAST_MANAGER_H_1450292154
393+
394+#include <QtCore/QObject>
395+#include <QtCore/QByteArray>
396+#include <QtCore/QList>
397+#include <QtCore/QMap>
398+#include <QtCore/QString>
399+#include <QtCore/QStringList>
400+#include <QtCore/QVariant>
401+#include <QtDBus/QtDBus>
402+
403+/*
404+ * Proxy class for interface org.aethercast.Manager
405+ */
406+class AethercastManager: public QDBusAbstractInterface
407+{
408+ Q_OBJECT
409+public:
410+ static inline const char *staticInterfaceName()
411+ { return "org.aethercast.Manager"; }
412+
413+public:
414+ AethercastManager(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
415+
416+ ~AethercastManager();
417+
418+ Q_PROPERTY(QStringList Capabilities READ capabilities)
419+ inline QStringList capabilities() const
420+ { return qvariant_cast< QStringList >(property("Capabilities")); }
421+
422+ Q_PROPERTY(bool Scanning READ scanning)
423+ inline bool scanning() const
424+ { return qvariant_cast< bool >(property("Scanning")); }
425+
426+ Q_PROPERTY(QString State READ state)
427+ inline QString state() const
428+ { return qvariant_cast< QString >(property("State")); }
429+
430+public Q_SLOTS: // METHODS
431+ inline QDBusPendingReply<> RegisterMediaManager(const QDBusObjectPath &path)
432+ {
433+ QList<QVariant> argumentList;
434+ argumentList << QVariant::fromValue(path);
435+ return asyncCallWithArgumentList(QStringLiteral("RegisterMediaManager"), argumentList);
436+ }
437+
438+ inline QDBusPendingReply<> Scan()
439+ {
440+ QList<QVariant> argumentList;
441+ return asyncCallWithArgumentList(QStringLiteral("Scan"), argumentList);
442+ }
443+
444+ inline QDBusPendingReply<> UnregisterMediaManager(const QDBusObjectPath &path)
445+ {
446+ QList<QVariant> argumentList;
447+ argumentList << QVariant::fromValue(path);
448+ return asyncCallWithArgumentList(QStringLiteral("UnregisterMediaManager"), argumentList);
449+ }
450+
451+Q_SIGNALS: // SIGNALS
452+};
453+
454+namespace org {
455+ namespace aethercast {
456+ typedef ::AethercastManager Manager;
457+ }
458+}
459+#endif
460
461=== added file 'plugins/wifi/aethercast/dbus-shared.h'
462--- plugins/wifi/aethercast/dbus-shared.h 1970-01-01 00:00:00 +0000
463+++ plugins/wifi/aethercast/dbus-shared.h 2016-03-09 13:21:41 +0000
464@@ -0,0 +1,32 @@
465+/*
466+ * Copyright (C) 2016 Canonical Ltd
467+ *
468+ * This program is free software: you can redistribute it and/or modify
469+ * it under the terms of the GNU General Public License version 3 as
470+ * published by the Free Software Foundation.
471+ *
472+ * This program is distributed in the hope that it will be useful,
473+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
474+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
475+ * GNU General Public License for more details.
476+ *
477+ * You should have received a copy of the GNU General Public License
478+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
479+ *
480+ * Authors:
481+ * Ken VanDine <ken.vandine@canonical.com>
482+ */
483+
484+#ifndef USS_DBUS_SHARED_H
485+#define USS_DBUS_SHARED_H
486+
487+#define AETHERCAST_PATH "/org/aethercast"
488+#define AETHERCAST_SERVICE "org.aethercast"
489+#define AETHERCAST_DEVICE_IFACE "org.aethercast.Device"
490+#define AETHERCAST_MANAGER_IFACE "org.aethercast.Manager"
491+
492+#define watchCall(call, func) \
493+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); \
494+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, func)
495+
496+#endif // USS_DBUS_SHARED_H
497
498=== added file 'plugins/wifi/aethercast/device.cpp'
499--- plugins/wifi/aethercast/device.cpp 1970-01-01 00:00:00 +0000
500+++ plugins/wifi/aethercast/device.cpp 2016-03-09 13:21:41 +0000
501@@ -0,0 +1,144 @@
502+/*
503+ * Copyright (C) 2016 Canonical Ltd
504+ *
505+ * This program is free software: you can redistribute it and/or modify
506+ * it under the terms of the GNU General Public License version 3 as
507+ * published by the Free Software Foundation.
508+ *
509+ * This program is distributed in the hope that it will be useful,
510+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
511+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
512+ * GNU General Public License for more details.
513+ *
514+ * You should have received a copy of the GNU General Public License
515+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
516+ *
517+ * Authors:
518+ * Ken VanDine <ken.vandine@canonical.com>
519+ */
520+
521+#include "aethercast_device.h"
522+#include "device.h"
523+
524+#include <QDBusReply>
525+#include <QDebug> // qWarning()
526+#include <QThread>
527+#include <QTimer>
528+
529+Device::Device(const QString &path, QDBusConnection &bus) :
530+ m_state(QString())
531+{
532+ qWarning() << Q_FUNC_INFO;
533+ initDevice(path, bus);
534+}
535+
536+void Device::initDevice(const QString &path, QDBusConnection &bus)
537+{
538+ qWarning() << Q_FUNC_INFO;
539+ /* whenever any of the properties changes,
540+ trigger the catch-all deviceChanged() signal */
541+ QObject::connect(this, SIGNAL(nameChanged()), this, SIGNAL(deviceChanged()));
542+ QObject::connect(this, SIGNAL(addressChanged()), this, SIGNAL(deviceChanged()));
543+ QObject::connect(this, SIGNAL(stateChanged()), this, SIGNAL(deviceChanged()));
544+
545+ m_aethercastDevice.reset(new AethercastDevice(AETHERCAST_SERVICE, path, bus));
546+ /* Give our calls a bit more time than the default 25 seconds to
547+ * complete whatever they are doing. In some situations (e.g. with
548+ * specific devices) the default doesn't seem to be enough to. */
549+ m_aethercastDevice->setTimeout(60 * 1000 /* 60 seconds */);
550+
551+ m_aethercastDeviceProperties.reset(new FreeDesktopProperties(AETHERCAST_SERVICE, path, bus));
552+
553+ QObject::connect(m_aethercastDeviceProperties.data(), SIGNAL(PropertiesChanged(const QString&, const QVariantMap&, const QStringList&)),
554+ this, SLOT(slotPropertiesChanged(const QString&, const QVariantMap&, const QStringList&)));
555+
556+ Q_EMIT(pathChanged());
557+
558+ watchCall(m_aethercastDeviceProperties->GetAll(AETHERCAST_DEVICE_IFACE), [=](QDBusPendingCallWatcher *watcher) {
559+ QDBusPendingReply<QVariantMap> reply = *watcher;
560+
561+ if (reply.isError()) {
562+ qWarning() << "Failed to retrieve properties for device" << m_aethercastDevice->path();
563+ watcher->deleteLater();
564+ return;
565+ }
566+
567+ auto properties = reply.argumentAt<0>();
568+ setProperties(properties);
569+
570+ watcher->deleteLater();
571+ });
572+}
573+
574+void Device::slotPropertiesChanged(const QString &interface, const QVariantMap &changedProperties,
575+ const QStringList &invalidatedProperties)
576+{
577+ qWarning() << Q_FUNC_INFO;
578+ Q_UNUSED(invalidatedProperties);
579+
580+ if (interface != AETHERCAST_DEVICE_IFACE)
581+ return;
582+
583+ setProperties(changedProperties);
584+}
585+
586+void Device::setProperties(const QMap<QString,QVariant> &properties)
587+{
588+ qWarning() << Q_FUNC_INFO;
589+ QMapIterator<QString,QVariant> it(properties);
590+ while (it.hasNext()) {
591+ it.next();
592+ updateProperty(it.key(), it.value());
593+ }
594+}
595+
596+void Device::disconnect()
597+{
598+ qWarning() << Q_FUNC_INFO;
599+ m_aethercastDevice->Disconnect();
600+}
601+
602+void Device::connect()
603+{
604+ qWarning() << Q_FUNC_INFO;
605+ m_aethercastDevice->Connect(QString());
606+}
607+
608+void Device::setName(const QString &name)
609+{
610+ qWarning() << Q_FUNC_INFO << name;
611+ if (m_name != name) {
612+ m_name = name;
613+ Q_EMIT(nameChanged());
614+ }
615+}
616+
617+void Device::setAddress(const QString &address)
618+{
619+ qWarning() << Q_FUNC_INFO << address;
620+ if (m_address != address) {
621+ m_address = address;
622+ Q_EMIT(addressChanged());
623+ }
624+}
625+
626+void Device::setState(const QString &state)
627+{
628+ qWarning() << Q_FUNC_INFO << state;
629+ if (m_state != state) {
630+ m_state = state;
631+ Q_EMIT(stateChanged());
632+ }
633+}
634+
635+void Device::updateProperty(const QString &key, const QVariant &value)
636+{
637+ qWarning() << Q_FUNC_INFO << key << ":" << value;
638+ if (key == "Name") {
639+ setName(value.toString());
640+ } else if (key == "Address") {
641+ setAddress(value.toString());
642+ } else if (key == "State") {
643+ setState(value.toString());
644+ }
645+}
646
647=== added file 'plugins/wifi/aethercast/device.h'
648--- plugins/wifi/aethercast/device.h 1970-01-01 00:00:00 +0000
649+++ plugins/wifi/aethercast/device.h 2016-03-09 13:21:41 +0000
650@@ -0,0 +1,101 @@
651+/*
652+ * Copyright (C) 2016 Canonical Ltd
653+ *
654+ * This program is free software: you can redistribute it and/or modify
655+ * it under the terms of the GNU General Public License version 3 as
656+ * published by the Free Software Foundation.
657+ *
658+ * This program is distributed in the hope that it will be useful,
659+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
660+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
661+ * GNU General Public License for more details.
662+ *
663+ * You should have received a copy of the GNU General Public License
664+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
665+ *
666+ * Authors:
667+ * Ken VanDine <ken.vandine@canonical.com>
668+ */
669+
670+#ifndef USS_AETHERCAST_DEVICE_H
671+#define USS_AETHERCAST_DEVICE_H
672+
673+#include <QDBusConnection>
674+#include <QDBusInterface>
675+#include <QDBusPendingCallWatcher>
676+#include <QSharedPointer>
677+#include <QString>
678+
679+#include "freedesktop_properties.h"
680+#include "aethercast_device.h"
681+#include "dbus-shared.h"
682+
683+struct Device: QObject
684+{
685+ Q_OBJECT
686+
687+ Q_PROPERTY(QString path
688+ READ getPath
689+ NOTIFY pathChanged)
690+
691+ Q_PROPERTY(QString name
692+ READ getName
693+ NOTIFY nameChanged)
694+
695+ Q_PROPERTY(QString address
696+ READ getAddress
697+ NOTIFY addressChanged)
698+
699+ Q_PROPERTY(QString state
700+ READ getState
701+ NOTIFY stateChanged)
702+
703+public:
704+
705+
706+Q_SIGNALS:
707+ void pathChanged();
708+ void nameChanged();
709+ void addressChanged();
710+ void stateChanged();
711+ void deviceChanged(); // catchall for any change
712+
713+public:
714+ const QString& getName() const { return m_name; }
715+ const QString& getAddress() const { return m_address; }
716+ const QString& getState() const { return m_state; }
717+ QString getPath() const { return m_aethercastDevice ? m_aethercastDevice->path() : QString(); }
718+
719+ private:
720+ QString m_name;
721+ QString m_state;
722+ QString m_address;
723+ QScopedPointer<AethercastDevice> m_aethercastDevice;
724+ QScopedPointer<FreeDesktopProperties> m_aethercastDeviceProperties;
725+
726+ protected:
727+ void setName(const QString &name);
728+ void setAddress(const QString &address);
729+ void setState(const QString &state);
730+
731+ public:
732+ Device() {}
733+ Device(const QString &path, QDBusConnection &bus);
734+ ~Device() {}
735+ void connect();
736+ void disconnect();
737+ void setProperties(const QMap<QString,QVariant> &properties);
738+
739+ private Q_SLOTS:
740+ void slotPropertiesChanged(const QString &interface, const QVariantMap &changedProperties,
741+ const QStringList &invalidatedProperties);
742+
743+ private:
744+ void initDevice(const QString &path, QDBusConnection &bus);
745+ void updateProperties(QSharedPointer<QDBusInterface>);
746+ void updateProperty(const QString &key, const QVariant &value);
747+};
748+
749+Q_DECLARE_METATYPE(Device*)
750+
751+#endif // USS_AETHERCAST_DEVICE_H
752
753=== added file 'plugins/wifi/aethercast/devicemodel.cpp'
754--- plugins/wifi/aethercast/devicemodel.cpp 1970-01-01 00:00:00 +0000
755+++ plugins/wifi/aethercast/devicemodel.cpp 2016-03-09 13:21:41 +0000
756@@ -0,0 +1,379 @@
757+/*
758+ * Copyright (C) 2016 Canonical Ltd
759+ *
760+ * This program is free software: you can redistribute it and/or modify
761+ * it under the terms of the GNU General Public License version 3 as
762+ * published by the Free Software Foundation.
763+ *
764+ * This program is distributed in the hope that it will be useful,
765+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
766+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
767+ * GNU General Public License for more details.
768+ *
769+ * You should have received a copy of the GNU General Public License
770+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
771+ *
772+ * Authors:
773+ * Ken VanDine <ken.vandine@canonical.com>
774+ *
775+*/
776+
777+#include "devicemodel.h"
778+
779+#include <QDBusReply>
780+#include <QDebug>
781+
782+#include "dbus-shared.h"
783+
784+namespace
785+{
786+ const int SCANNING_ACTIVE_DURATION_MSEC = (30 * 1000);
787+ const int SCANNING_IDLE_DURATION_MSEC = (10 * 1000);
788+}
789+
790+DeviceModel::DeviceModel(QDBusConnection &dbus, QObject *parent):
791+ QAbstractListModel(parent),
792+ m_dbus(dbus),
793+ m_aethercastManager(AETHERCAST_SERVICE, "/org/aethercast", m_dbus),
794+ m_isDiscovering(false)
795+{
796+ qWarning() << Q_FUNC_INFO;
797+ if (m_aethercastManager.isValid()) {
798+
799+ connect(&m_aethercastManager, SIGNAL(InterfacesAdded(const QDBusObjectPath&, InterfaceList)),
800+ this, SLOT(slotInterfacesAdded(const QDBusObjectPath&, InterfaceList)));
801+
802+ connect(&m_aethercastManager, SIGNAL(InterfacesRemoved(const QDBusObjectPath&, const QStringList&)),
803+ this, SLOT(slotInterfacesRemoved(const QDBusObjectPath&, const QStringList&)));
804+
805+ watchCall(m_aethercastManager.GetManagedObjects(), [=](QDBusPendingCallWatcher *watcher) {
806+ QDBusPendingReply<ManagedObjectList> reply = *watcher;
807+
808+ if (reply.isError()) {
809+ qWarning() << "Failed to retrieve list of managed objects from Aethercast service: "
810+ << reply.error().message();
811+ watcher->deleteLater();
812+ return;
813+ }
814+
815+ auto objectList = reply.argumentAt<0>();
816+
817+ for (QDBusObjectPath path : objectList.keys()) {
818+ InterfaceList ifaces = objectList.value(path);
819+ addDevice(path.path(), ifaces.value(AETHERCAST_DEVICE_IFACE));
820+ break;
821+ }
822+
823+ watcher->deleteLater();
824+ });
825+ }
826+
827+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
828+}
829+
830+DeviceModel::~DeviceModel()
831+{
832+ qWarning() << "Releasing device model ..";
833+}
834+
835+void DeviceModel::slotInterfacesAdded(const QDBusObjectPath &objectPath, InterfaceList ifacesAndProps)
836+{
837+ Q_UNUSED(ifacesAndProps);
838+
839+ qWarning() << Q_FUNC_INFO << objectPath.path();
840+
841+ auto candidatedPath = objectPath.path();
842+
843+ // At this point we can only get new devices
844+ if (!candidatedPath.startsWith(m_aethercastManager.path()))
845+ return;
846+
847+ if (!ifacesAndProps.contains(AETHERCAST_DEVICE_IFACE))
848+ return;
849+
850+ addDevice(candidatedPath, ifacesAndProps.value(AETHERCAST_DEVICE_IFACE));
851+}
852+
853+void DeviceModel::slotInterfacesRemoved(const QDBusObjectPath &objectPath, const QStringList &interfaces)
854+{
855+ auto candidatedPath = objectPath.path();
856+
857+ if (!m_aethercastManager.isValid())
858+ return;
859+
860+ if (candidatedPath == m_aethercastManager.path() &&
861+ interfaces.contains(AETHERCAST_MANAGER_IFACE)) {
862+ return;
863+ }
864+
865+ if (!candidatedPath.startsWith(m_aethercastManager.path()))
866+ return;
867+
868+ if (!interfaces.contains(AETHERCAST_DEVICE_IFACE))
869+ return;
870+
871+ auto device = getDeviceFromPath(candidatedPath);
872+ if (!device)
873+ return;
874+
875+ const int row = findRowFromAddress(device->getAddress());
876+ if ((row >= 0))
877+ removeRow(row);
878+}
879+
880+int DeviceModel::findRowFromAddress(const QString &address) const
881+{
882+ for (int i=0, n=m_devices.size(); i<n; i++)
883+ if (m_devices[i]->getAddress() == address)
884+ return i;
885+
886+ return -1;
887+}
888+
889+void DeviceModel::setDiscovering(bool value)
890+{
891+ if (value == m_isDiscovering)
892+ return;
893+
894+ m_isDiscovering = value;
895+ Q_EMIT(discoveringChanged(m_isDiscovering));
896+}
897+
898+void DeviceModel::stopDiscovery()
899+{
900+ /*
901+ if (m_aethercastManager.isValid() && m_isDiscovering) {
902+
903+ watchCall(m_aethercastManager.StopDiscovery(), [=](QDBusPendingCallWatcher *watcher) {
904+ QDBusPendingReply<void> reply = *watcher;
905+ if (reply.isError()) {
906+ qWarning() << "Failed to stop device discovery:"
907+ << reply.error().message();
908+ }
909+
910+ watcher->deleteLater();
911+ });
912+ }
913+ */
914+}
915+
916+void DeviceModel::startDiscovery()
917+{
918+ /*
919+ if (m_aethercastManager.isValid() && !m_isDiscovering) {
920+
921+ watchCall(m_aethercastManager->StartDiscovery(), [=](QDBusPendingCallWatcher *watcher) {
922+ QDBusPendingReply<void> reply = *watcher;
923+ if (reply.isError()) {
924+ qWarning() << "Failed to start device discovery:"
925+ << reply.error().message();
926+ }
927+
928+ watcher->deleteLater();
929+ });
930+ }
931+ */
932+}
933+
934+void DeviceModel::toggleDiscovery()
935+{
936+ if (isDiscovering())
937+ stopDiscovery();
938+ else
939+ startDiscovery();
940+}
941+
942+void DeviceModel::slotTimeout()
943+{
944+ toggleDiscovery ();
945+}
946+
947+void DeviceModel::setProperties(const QMap<QString,QVariant> &properties)
948+{
949+ QMapIterator<QString,QVariant> it(properties);
950+ while (it.hasNext()) {
951+ it.next();
952+ updateProperty(it.key(), it.value());
953+ }
954+}
955+
956+void DeviceModel::updateProperty(const QString &key, const QVariant &value)
957+{
958+ qWarning() << Q_FUNC_INFO << key << ":" << value;
959+ /*
960+ if (key == "Name") {
961+ m_adapterName = value.toString();
962+ } else if (key == "Address") {
963+ m_adapterAddress = value.toString();
964+ }
965+ */
966+}
967+
968+void DeviceModel::slotPropertyChanged(const QString &key,
969+ const QDBusVariant &value)
970+{
971+ qWarning() << Q_FUNC_INFO << key << ":" << value.variant();
972+ updateProperty (key, value.variant());
973+}
974+
975+void DeviceModel::slotDevicePairingDone(bool success)
976+{
977+ Device *device = static_cast<Device*>(sender());
978+
979+ Q_EMIT(devicePairingDone(device, success));
980+}
981+
982+void DeviceModel::addDevice(const QString &path, const QVariantMap &properties)
983+{
984+ qWarning() << Q_FUNC_INFO;
985+ QSharedPointer<Device> device(new Device(path, m_dbus));
986+ device->setProperties(properties);
987+ qWarning() << Q_FUNC_INFO;
988+
989+ if (device) {
990+ QObject::connect(device.data(), SIGNAL(deviceChanged()),
991+ this, SLOT(slotDeviceChanged()));
992+ //QObject::connect(device.data(), SIGNAL(pairingDone(bool)),
993+ // this, SLOT(slotDevicePairingDone(bool)));
994+ addDevice(device);
995+ }
996+}
997+
998+void DeviceModel::addDevice(QSharedPointer<Device> &device)
999+{
1000+ qWarning() << Q_FUNC_INFO;
1001+ int row = findRowFromAddress(device->getAddress());
1002+
1003+ if (row >= 0) { // update existing device
1004+ m_devices[row] = device;
1005+ emitRowChanged(row);
1006+ } else { // add new device
1007+ row = m_devices.size();
1008+ beginInsertRows(QModelIndex(), row, row);
1009+ m_devices.append(device);
1010+ endInsertRows();
1011+ }
1012+}
1013+
1014+void DeviceModel::removeRow(int row)
1015+{
1016+ if (0<=row && row<m_devices.size()) {
1017+ beginRemoveRows(QModelIndex(), row, row);
1018+ m_devices.removeAt(row);
1019+ endRemoveRows();
1020+ }
1021+}
1022+
1023+void DeviceModel::emitRowChanged(int row)
1024+{
1025+ if (0<=row && row<m_devices.size()) {
1026+ QModelIndex qmi = index(row, 0);
1027+ Q_EMIT(dataChanged(qmi, qmi));
1028+ }
1029+}
1030+
1031+void DeviceModel::slotDeviceChanged()
1032+{
1033+ const Device * device = qobject_cast<Device*>(sender());
1034+
1035+ // find the row that goes with this device
1036+ int row = -1;
1037+ if (device != nullptr)
1038+ for (int i=0, n=m_devices.size(); row==-1 && i<n; i++)
1039+ if (m_devices[i].data() == device)
1040+ row = i;
1041+
1042+ if (row != -1)
1043+ emitRowChanged(row);
1044+}
1045+
1046+QSharedPointer<Device> DeviceModel::getDeviceFromAddress(const QString &address)
1047+{
1048+ QSharedPointer<Device> device;
1049+
1050+ const int row = findRowFromAddress(address);
1051+ if (row >= 0)
1052+ device = m_devices[row];
1053+
1054+ return device;
1055+}
1056+
1057+QSharedPointer<Device> DeviceModel::getDeviceFromPath(const QString &path)
1058+{
1059+ for (auto device : m_devices)
1060+ if (device->getPath() == path)
1061+ return device;
1062+
1063+ return QSharedPointer<Device>();
1064+}
1065+
1066+void DeviceModel::slotRemoveFinished(QDBusPendingCallWatcher *call)
1067+{
1068+ QDBusPendingReply<void> reply = *call;
1069+
1070+ if (reply.isError()) {
1071+ qWarning() << "Could not remove device:" << reply.error().message();
1072+ }
1073+ call->deleteLater();
1074+}
1075+
1076+int DeviceModel::rowCount(const QModelIndex &parent) const
1077+{
1078+ Q_UNUSED(parent);
1079+
1080+ return m_devices.size();
1081+}
1082+
1083+QHash<int,QByteArray> DeviceModel::roleNames() const
1084+{
1085+ static QHash<int,QByteArray> names;
1086+
1087+ if (Q_UNLIKELY(names.empty())) {
1088+ names[Qt::DisplayRole] = "displayName";
1089+ names[StateRole] = "stateName";
1090+ names[AddressRole] = "addressName";
1091+ }
1092+
1093+ return names;
1094+}
1095+
1096+QVariant DeviceModel::data(const QModelIndex &index, int role) const
1097+{
1098+ QVariant ret;
1099+
1100+ if ((0<=index.row()) && (index.row()<m_devices.size())) {
1101+
1102+ auto device = m_devices[index.row()];
1103+ QString displayName;
1104+
1105+ switch (role) {
1106+ case Qt::DisplayRole:
1107+ displayName = device->getName();
1108+
1109+ if (displayName.isEmpty())
1110+ displayName = device->getAddress();
1111+
1112+ ret = displayName;
1113+ break;
1114+
1115+ case StateRole:
1116+ ret = device->getState();
1117+ break;
1118+
1119+ case AddressRole:
1120+ ret = device->getAddress();
1121+ break;
1122+
1123+ }
1124+ }
1125+
1126+ return ret;
1127+}
1128+
1129+bool DeviceFilter::lessThan(const QModelIndex &left,
1130+ const QModelIndex &right) const
1131+{
1132+ const QString a = sourceModel()->data(left, Qt::DisplayRole).value<QString>();
1133+ const QString b = sourceModel()->data(right, Qt::DisplayRole).value<QString>();
1134+ return a < b;
1135+}
1136
1137=== added file 'plugins/wifi/aethercast/devicemodel.h'
1138--- plugins/wifi/aethercast/devicemodel.h 1970-01-01 00:00:00 +0000
1139+++ plugins/wifi/aethercast/devicemodel.h 2016-03-09 13:21:41 +0000
1140@@ -0,0 +1,123 @@
1141+/*
1142+ * Copyright (C) 2016 Canonical Ltd
1143+ *
1144+ * This program is free software: you can redistribute it and/or modify
1145+ * it under the terms of the GNU General Public License version 3 as
1146+ * published by the Free Software Foundation.
1147+ *
1148+ * This program is distributed in the hope that it will be useful,
1149+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1150+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1151+ * GNU General Public License for more details.
1152+ *
1153+ * You should have received a copy of the GNU General Public License
1154+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1155+ *
1156+ * Authors:
1157+ * Ken VanDine <ken.vandine@canonical.com>
1158+ */
1159+
1160+#ifndef AETHERCAST_DEVICE_MODEL_H
1161+#define AETHERCAST_DEVICE_MODEL_H
1162+
1163+#include <QByteArray>
1164+#include <QHash>
1165+#include <QTimer>
1166+#include <QList>
1167+#include <QVariant>
1168+
1169+#include <QAbstractListModel>
1170+#include <QDBusConnection>
1171+#include <QDBusInterface>
1172+#include <QScopedPointer>
1173+#include <QSharedPointer>
1174+#include <QSortFilterProxyModel>
1175+
1176+#include "device.h"
1177+
1178+#include "freedesktop_objectmanager.h"
1179+#include "freedesktop_properties.h"
1180+#include "aethercast_device.h"
1181+#include "aethercast_manager.h"
1182+
1183+class DeviceModel: public QAbstractListModel
1184+{
1185+ Q_OBJECT
1186+
1187+public:
1188+ explicit DeviceModel(QDBusConnection &dbus, QObject *parent = 0);
1189+ ~DeviceModel();
1190+
1191+ enum Roles
1192+ {
1193+ // Qt::DisplayRole holds device name
1194+ TypeRole = Qt::UserRole,
1195+ AddressRole,
1196+ StateRole,
1197+ LastRole = StateRole
1198+ };
1199+
1200+ // implemented virtual methods from QAbstractTableModel
1201+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
1202+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
1203+ QHash<int,QByteArray> roleNames() const;
1204+
1205+ QSharedPointer<Device> getDeviceFromAddress(const QString &address);
1206+ QSharedPointer<Device> getDeviceFromPath(const QString &path);
1207+
1208+public:
1209+ bool isDiscovering() const { return m_isDiscovering; }
1210+ void stopDiscovery();
1211+ void startDiscovery();
1212+ void toggleDiscovery();
1213+
1214+Q_SIGNALS:
1215+ void discoveringChanged(bool isDiscovering);
1216+ void devicePairingDone(Device *device, bool success);
1217+
1218+private:
1219+ QDBusConnection m_dbus;
1220+ DBusObjectManagerInterface m_aethercastManager;
1221+
1222+ void setProperties(const QMap<QString,QVariant> &properties);
1223+ void updateProperty(const QString &key, const QVariant &value);
1224+
1225+ bool m_isDiscovering = false;
1226+ QTimer m_timer;
1227+
1228+ QList<QSharedPointer<Device> > m_devices;
1229+ void updateDevices();
1230+ void addDevice(QSharedPointer<Device> &device);
1231+ void addDevice(const QString &objectPath, const QVariantMap &properties);
1232+ void removeRow(int i);
1233+ int findRowFromAddress(const QString &address) const;
1234+ void emitRowChanged(int row);
1235+
1236+ void setDiscovering(bool value);
1237+
1238+private Q_SLOTS:
1239+ void slotInterfacesAdded(const QDBusObjectPath &objectPath, InterfaceList ifacesAndProps);
1240+ void slotInterfacesRemoved(const QDBusObjectPath &objectPath, const QStringList &interfaces);
1241+ void slotAdapterPropertiesChanged(const QString &interface, const QVariantMap &changedProperties,
1242+ const QStringList &invalidatedProperties);
1243+ void slotRemoveFinished(QDBusPendingCallWatcher *call);
1244+ void slotPropertyChanged(const QString &key, const QDBusVariant &value);
1245+ void slotTimeout();
1246+ void slotDeviceChanged();
1247+ void slotDevicePairingDone(bool success);
1248+};
1249+
1250+class DeviceFilter: public QSortFilterProxyModel
1251+{
1252+ Q_OBJECT
1253+
1254+public:
1255+ DeviceFilter() {}
1256+ virtual ~DeviceFilter() {}
1257+
1258+protected:
1259+ virtual bool lessThan(const QModelIndex&, const QModelIndex&) const;
1260+
1261+};
1262+
1263+#endif // AETHERCAST_DEVICE_MODEL_H
1264
1265=== added file 'plugins/wifi/aethercast/displays.cpp'
1266--- plugins/wifi/aethercast/displays.cpp 1970-01-01 00:00:00 +0000
1267+++ plugins/wifi/aethercast/displays.cpp 2016-03-09 13:21:41 +0000
1268@@ -0,0 +1,122 @@
1269+/*
1270+ * Copyright (C) 2016 Canonical Ltd
1271+ *
1272+ * This program is free software: you can redistribute it and/or modify
1273+ * it under the terms of the GNU General Public License version 3 as
1274+ * published by the Free Software Foundation.
1275+ *
1276+ * This program is distributed in the hope that it will be useful,
1277+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1278+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1279+ * GNU General Public License for more details.
1280+ *
1281+ * You should have received a copy of the GNU General Public License
1282+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1283+ *
1284+ * Authors:
1285+ * Ken VanDine <ken.vandine@canonical.com>
1286+ *
1287+ */
1288+
1289+#include "displays.h"
1290+#include "aethercast_manager.h"
1291+#include "aethercast_device.h"
1292+
1293+#include <QQmlEngine>
1294+
1295+Displays::Displays(QObject *parent):
1296+ Displays(QDBusConnection::systemBus(), parent)
1297+{
1298+ qWarning() << Q_FUNC_INFO;
1299+}
1300+
1301+Displays::Displays(const QDBusConnection &dbus, QObject *parent):
1302+ QObject(parent),
1303+ m_dbus(dbus),
1304+ m_devices(m_dbus)
1305+{
1306+ qWarning() << Q_FUNC_INFO;
1307+
1308+ m_manager = new AethercastManager(AETHERCAST_SERVICE, AETHERCAST_PATH, m_dbus);
1309+
1310+ m_aethercastProperties.reset(new FreeDesktopProperties(AETHERCAST_SERVICE, AETHERCAST_PATH, m_dbus));
1311+
1312+ QObject::connect(m_aethercastProperties.data(), SIGNAL(PropertiesChanged(const QString&, const QVariantMap&, const QStringList&)),
1313+ this, SLOT(slotPropertiesChanged(const QString&, const QVariantMap&, const QStringList&)));
1314+
1315+
1316+ watchCall(m_aethercastProperties->GetAll(AETHERCAST_MANAGER_IFACE), [=](QDBusPendingCallWatcher *watcher) {
1317+ QDBusPendingReply<QVariantMap> reply = *watcher;
1318+
1319+ if (reply.isError()) {
1320+ qWarning() << "Failed to retrieve properties for manager";
1321+ watcher->deleteLater();
1322+ return;
1323+ }
1324+
1325+ auto properties = reply.argumentAt<0>();
1326+ setProperties(properties);
1327+ watcher->deleteLater();
1328+ });
1329+}
1330+
1331+void Displays::slotPropertiesChanged(const QString &interface, const QVariantMap &changedProperties,
1332+ const QStringList &invalidatedProperties)
1333+{
1334+ Q_UNUSED(invalidatedProperties);
1335+ qWarning() << Q_FUNC_INFO;
1336+
1337+ if (interface != AETHERCAST_MANAGER_IFACE)
1338+ return;
1339+
1340+ setProperties(changedProperties);
1341+}
1342+
1343+void Displays::setProperties(const QMap<QString,QVariant> &properties)
1344+{
1345+ qWarning() << Q_FUNC_INFO;
1346+ QMapIterator<QString,QVariant> it(properties);
1347+ while (it.hasNext()) {
1348+ it.next();
1349+ updateProperty(it.key(), it.value());
1350+ }
1351+}
1352+
1353+void Displays::scan()
1354+{
1355+ qWarning() << Q_FUNC_INFO;
1356+ if (!m_manager)
1357+ return;
1358+ m_manager->Scan();
1359+}
1360+
1361+QAbstractItemModel * Displays::devices()
1362+{
1363+ qWarning() << Q_FUNC_INFO;
1364+ auto ret = &m_devices;
1365+ QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
1366+ return ret;
1367+}
1368+
1369+void Displays::disconnectDevice(const QString &address)
1370+{
1371+ qWarning() << Q_FUNC_INFO << address;
1372+ auto device = m_devices.getDeviceFromAddress(address);
1373+ if (device)
1374+ device->disconnect();
1375+}
1376+
1377+void Displays::connectDevice(const QString &address)
1378+{
1379+ qWarning() << Q_FUNC_INFO << address;
1380+ auto device = m_devices.getDeviceFromAddress(address);
1381+ if (device)
1382+ device->connect();
1383+}
1384+
1385+void Displays::updateProperty(const QString &key, const QVariant &value)
1386+{
1387+ qWarning() << Q_FUNC_INFO << key << ":" << value;
1388+ if (key == "Scanning")
1389+ Q_EMIT(scanningChanged(value.toBool()));
1390+}
1391
1392=== added file 'plugins/wifi/aethercast/displays.h'
1393--- plugins/wifi/aethercast/displays.h 1970-01-01 00:00:00 +0000
1394+++ plugins/wifi/aethercast/displays.h 2016-03-09 13:21:41 +0000
1395@@ -0,0 +1,73 @@
1396+/*
1397+ * Copyright (C) 2016 Canonical Ltd
1398+ *
1399+ * This program is free software: you can redistribute it and/or modify
1400+ * it under the terms of the GNU General Public License version 3 as
1401+ * published by the Free Software Foundation.
1402+ *
1403+ * This program is distributed in the hope that it will be useful,
1404+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1405+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1406+ * GNU General Public License for more details.
1407+ *
1408+ * You should have received a copy of the GNU General Public License
1409+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1410+ *
1411+ * Authors:
1412+ * Ken VanDine <ken.vandine@canonical.com>
1413+ *
1414+ */
1415+
1416+#ifndef DISPLAYS_H
1417+#define DISPLAYS_H
1418+
1419+#include <QObject>
1420+#include <QtDBus>
1421+#include "devicemodel.h"
1422+#include "aethercast_device.h"
1423+#include "aethercast_manager.h"
1424+
1425+class Displays : public QObject
1426+{
1427+ Q_OBJECT
1428+
1429+ Q_PROPERTY (QAbstractItemModel* devices
1430+ READ devices
1431+ NOTIFY devicesChanged)
1432+
1433+ Q_PROPERTY (bool scanning
1434+ READ scanning
1435+ NOTIFY scanningChanged)
1436+
1437+Q_SIGNALS:
1438+ void devicesChanged();
1439+ void scanningChanged(bool isActive);
1440+
1441+public:
1442+ explicit Displays(QObject *parent = nullptr);
1443+ explicit Displays(const QDBusConnection &dbus, QObject *parent = nullptr);
1444+ ~Displays() {}
1445+
1446+ Q_INVOKABLE void connectDevice(const QString &address);
1447+ Q_INVOKABLE void disconnectDevice(const QString &address);
1448+ Q_INVOKABLE void scan();
1449+ void setProperties(const QMap<QString,QVariant> &properties);
1450+
1451+public:
1452+ QAbstractItemModel * devices();
1453+ bool scanning() const { return m_manager->scanning(); }
1454+
1455+private Q_SLOTS:
1456+ void slotPropertiesChanged(const QString &interface, const QVariantMap &changedProperties,
1457+ const QStringList &invalidatedProperties);
1458+
1459+private:
1460+ QDBusConnection m_dbus;
1461+ DeviceModel m_devices;
1462+ AethercastManager* m_manager;
1463+ QScopedPointer<FreeDesktopProperties> m_aethercastProperties;
1464+ void updateProperties(QSharedPointer<QDBusInterface>);
1465+ void updateProperty(const QString &key, const QVariant &value);
1466+};
1467+
1468+#endif // DISPLAYS_H
1469
1470=== added file 'plugins/wifi/aethercast/freedesktop_objectmanager.cpp'
1471--- plugins/wifi/aethercast/freedesktop_objectmanager.cpp 1970-01-01 00:00:00 +0000
1472+++ plugins/wifi/aethercast/freedesktop_objectmanager.cpp 2016-03-09 13:21:41 +0000
1473@@ -0,0 +1,26 @@
1474+/*
1475+ * This file was generated by qdbusxml2cpp version 0.8
1476+ * Command line was: qdbusxml2cpp -p freedesktop_objectmanager -i aethercast_helper.h -v -c DBusObjectManagerInterface org.freedesktop.DBus.ObjectManager.xml
1477+ *
1478+ * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
1479+ *
1480+ * This is an auto-generated file.
1481+ * This file may have been hand-edited. Look for HAND-EDIT comments
1482+ * before re-generating it.
1483+ */
1484+
1485+#include "freedesktop_objectmanager.h"
1486+
1487+/*
1488+ * Implementation of interface class DBusObjectManagerInterface
1489+ */
1490+
1491+DBusObjectManagerInterface::DBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
1492+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
1493+{
1494+}
1495+
1496+DBusObjectManagerInterface::~DBusObjectManagerInterface()
1497+{
1498+}
1499+
1500
1501=== added file 'plugins/wifi/aethercast/freedesktop_objectmanager.h'
1502--- plugins/wifi/aethercast/freedesktop_objectmanager.h 1970-01-01 00:00:00 +0000
1503+++ plugins/wifi/aethercast/freedesktop_objectmanager.h 2016-03-09 13:21:41 +0000
1504@@ -0,0 +1,58 @@
1505+/*
1506+ * This file was generated by qdbusxml2cpp version 0.8
1507+ * Command line was: qdbusxml2cpp -p freedesktop_objectmanager -i aethercast_helper.h -v -c DBusObjectManagerInterface org.freedesktop.DBus.ObjectManager.xml
1508+ *
1509+ * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
1510+ *
1511+ * This is an auto-generated file.
1512+ * Do not edit! All changes made to it will be lost.
1513+ */
1514+
1515+#ifndef FREEDESKTOP_OBJECTMANAGER_H_1452098393
1516+#define FREEDESKTOP_OBJECTMANAGER_H_1452098393
1517+
1518+#include <QtCore/QObject>
1519+#include <QtCore/QByteArray>
1520+#include <QtCore/QList>
1521+#include <QtCore/QMap>
1522+#include <QtCore/QString>
1523+#include <QtCore/QStringList>
1524+#include <QtCore/QVariant>
1525+#include <QtDBus/QtDBus>
1526+#include "aethercast_helper.h"
1527+
1528+/*
1529+ * Proxy class for interface org.freedesktop.DBus.ObjectManager
1530+ */
1531+class DBusObjectManagerInterface: public QDBusAbstractInterface
1532+{
1533+ Q_OBJECT
1534+public:
1535+ static inline const char *staticInterfaceName()
1536+ { return "org.freedesktop.DBus.ObjectManager"; }
1537+
1538+public:
1539+ DBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
1540+
1541+ ~DBusObjectManagerInterface();
1542+
1543+public Q_SLOTS: // METHODS
1544+ inline QDBusPendingReply<ManagedObjectList> GetManagedObjects()
1545+ {
1546+ QList<QVariant> argumentList;
1547+ return asyncCallWithArgumentList(QStringLiteral("GetManagedObjects"), argumentList);
1548+ }
1549+
1550+Q_SIGNALS: // SIGNALS
1551+ void InterfacesAdded(const QDBusObjectPath &object_path, InterfaceList interfaces_and_properties);
1552+ void InterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
1553+};
1554+
1555+namespace org {
1556+ namespace freedesktop {
1557+ namespace DBus {
1558+ typedef ::DBusObjectManagerInterface ObjectManager;
1559+ }
1560+ }
1561+}
1562+#endif
1563
1564=== added file 'plugins/wifi/aethercast/freedesktop_properties.cpp'
1565--- plugins/wifi/aethercast/freedesktop_properties.cpp 1970-01-01 00:00:00 +0000
1566+++ plugins/wifi/aethercast/freedesktop_properties.cpp 2016-03-09 13:21:41 +0000
1567@@ -0,0 +1,26 @@
1568+/*
1569+ * This file was generated by qdbusxml2cpp version 0.8
1570+ * Command line was: qdbusxml2cpp -c FreeDesktopProperties -p freedesktop_properties -v org.freedesktop.DBus.Properties.xml
1571+ *
1572+ * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
1573+ *
1574+ * This is an auto-generated file.
1575+ * This file may have been hand-edited. Look for HAND-EDIT comments
1576+ * before re-generating it.
1577+ */
1578+
1579+#include "freedesktop_properties.h"
1580+
1581+/*
1582+ * Implementation of interface class FreeDesktopProperties
1583+ */
1584+
1585+FreeDesktopProperties::FreeDesktopProperties(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
1586+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
1587+{
1588+}
1589+
1590+FreeDesktopProperties::~FreeDesktopProperties()
1591+{
1592+}
1593+
1594
1595=== added file 'plugins/wifi/aethercast/freedesktop_properties.h'
1596--- plugins/wifi/aethercast/freedesktop_properties.h 1970-01-01 00:00:00 +0000
1597+++ plugins/wifi/aethercast/freedesktop_properties.h 2016-03-09 13:21:41 +0000
1598@@ -0,0 +1,71 @@
1599+/*
1600+ * This file was generated by qdbusxml2cpp version 0.8
1601+ * Command line was: qdbusxml2cpp -c FreeDesktopProperties -p freedesktop_properties -v org.freedesktop.DBus.Properties.xml
1602+ *
1603+ * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
1604+ *
1605+ * This is an auto-generated file.
1606+ * Do not edit! All changes made to it will be lost.
1607+ */
1608+
1609+#ifndef FREEDESKTOP_PROPERTIES_H_1452098393
1610+#define FREEDESKTOP_PROPERTIES_H_1452098393
1611+
1612+#include <QtCore/QObject>
1613+#include <QtCore/QByteArray>
1614+#include <QtCore/QList>
1615+#include <QtCore/QMap>
1616+#include <QtCore/QString>
1617+#include <QtCore/QStringList>
1618+#include <QtCore/QVariant>
1619+#include <QtDBus/QtDBus>
1620+
1621+/*
1622+ * Proxy class for interface org.freedesktop.DBus.Properties
1623+ */
1624+class FreeDesktopProperties: public QDBusAbstractInterface
1625+{
1626+ Q_OBJECT
1627+public:
1628+ static inline const char *staticInterfaceName()
1629+ { return "org.freedesktop.DBus.Properties"; }
1630+
1631+public:
1632+ FreeDesktopProperties(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
1633+
1634+ ~FreeDesktopProperties();
1635+
1636+public Q_SLOTS: // METHODS
1637+ inline QDBusPendingReply<QDBusVariant> Get(const QString &interface, const QString &name)
1638+ {
1639+ QList<QVariant> argumentList;
1640+ argumentList << QVariant::fromValue(interface) << QVariant::fromValue(name);
1641+ return asyncCallWithArgumentList(QStringLiteral("Get"), argumentList);
1642+ }
1643+
1644+ inline QDBusPendingReply<QVariantMap> GetAll(const QString &interface)
1645+ {
1646+ QList<QVariant> argumentList;
1647+ argumentList << QVariant::fromValue(interface);
1648+ return asyncCallWithArgumentList(QStringLiteral("GetAll"), argumentList);
1649+ }
1650+
1651+ inline QDBusPendingReply<> Set(const QString &interface, const QString &name, const QDBusVariant &value)
1652+ {
1653+ QList<QVariant> argumentList;
1654+ argumentList << QVariant::fromValue(interface) << QVariant::fromValue(name) << QVariant::fromValue(value);
1655+ return asyncCallWithArgumentList(QStringLiteral("Set"), argumentList);
1656+ }
1657+
1658+Q_SIGNALS: // SIGNALS
1659+ void PropertiesChanged(const QString &interface, const QVariantMap &changed_properties, const QStringList &invalidated_properties);
1660+};
1661+
1662+namespace org {
1663+ namespace freedesktop {
1664+ namespace DBus {
1665+ typedef ::FreeDesktopProperties Properties;
1666+ }
1667+ }
1668+}
1669+#endif
1670
1671=== added file 'plugins/wifi/aethercast/org.aethercast.xml'
1672--- plugins/wifi/aethercast/org.aethercast.xml 1970-01-01 00:00:00 +0000
1673+++ plugins/wifi/aethercast/org.aethercast.xml 2016-03-09 13:21:41 +0000
1674@@ -0,0 +1,35 @@
1675+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
1676+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
1677+<node>
1678+ <interface name="org.aethercast.Manager">
1679+ <method name="RegisterMediaManager">
1680+ <arg name="path" type="o" direction="in"/>
1681+ </method>
1682+ <method name="UnregisterMediaManager">
1683+ <arg name="path" type="o" direction="in"/>
1684+ </method>
1685+ <method name="Scan"/>
1686+ <property name="State" type="s" access="read"/>
1687+ <property name="Capabilities" type="as" access="read"/>
1688+ <property name="Scanning" type="b" access="read"/>
1689+ </interface>
1690+ <interface name="org.aethercast.Device">
1691+ <method name="Connect">
1692+ <arg name="role" type="s" direction="in"/>
1693+ </method>
1694+ <method name="Disconnect"/>
1695+ <property name="State" type="s" access="read"/>
1696+ <property name="Address" type="s" access="read"/>
1697+ <property name="Name" type="s" access="read"/>
1698+ <property name="Capabilities" type="as" access="read"/>
1699+ </interface>
1700+ <interface name="org.aethercast.MediaManager">
1701+ <method name="Configure">
1702+ <arg name="address" type="s"/>
1703+ <arg name="port" type="i"/>
1704+ </method>
1705+ <method name="Play"/>
1706+ <method name="Pause"/>
1707+ <method name="Teardown"/>
1708+ </interface>
1709+</node>
1710
1711=== modified file 'plugins/wifi/plugin.cpp'
1712--- plugins/wifi/plugin.cpp 2015-06-03 19:35:09 +0000
1713+++ plugins/wifi/plugin.cpp 2016-03-09 13:21:41 +0000
1714@@ -23,6 +23,9 @@
1715 #include "wifidbushelper.h"
1716 #include "previousnetworkmodel.h"
1717 #include "certhandler.h"
1718+#include "aethercast/aethercast_helper.h"
1719+#include "aethercast/displays.h"
1720+#include "aethercast/device.h"
1721
1722 namespace {
1723
1724@@ -43,6 +46,11 @@
1725 void BackendPlugin::registerTypes(const char *uri)
1726 {
1727 Q_ASSERT(uri == QLatin1String("Ubuntu.SystemSettings.Wifi"));
1728+
1729+ // Register additional QtDBus types we need
1730+ qDBusRegisterMetaType<InterfaceList>();
1731+ qDBusRegisterMetaType<ManagedObjectList>();
1732+
1733 qmlRegisterType<UnityMenuModelStack>(uri, 1, 0, "UnityMenuModelStack");
1734 qmlRegisterSingletonType<WifiDbusHelper>(uri, 1, 0, "DbusHelper", dbusProvider);
1735 qmlRegisterType<PreviousNetworkModel>(uri, 1, 0, "PreviousNetworkModel");
1736@@ -50,6 +58,8 @@
1737 qmlRegisterType<PrivatekeyListModel>(uri, 1, 0, "PrivatekeyListModel");
1738 qmlRegisterType<PacFileListModel>(uri, 1, 0, "PacFileListModel");
1739 qmlRegisterType<FileHandler>(uri, 1, 0, "FileHandler");
1740+ qmlRegisterType<Device>(uri, 1, 0, "Device");
1741+ qmlRegisterType<Displays>(uri, 1, 0, "Displays");
1742 }
1743
1744 void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri)

Subscribers

People subscribed via source and target branches