on xenial help sign in
Merge from demo branch
commit23382982d025130e5b95150eec4181c720b15a6c authorMichael Terry <michael.terry@canonical.com> dateFri 16 Aug 2013, 10:36 (13 years ago) parentd2a52164dc4c0c
35 files changed+1253−12
Components/DemoOverlay.qml+239 Greeter/Greeter.qml+6−2 Launcher/Launcher.qml+1 Panel/Indicators.qml+2−2 Shell.qml+135−3 debian/control+2 debian/unity8-private.install+5 plugins/AccountsService/50-com.canonical.unity.AccountsService.pkla+6 plugins/AccountsService/AccountsService.cpp+70 plugins/AccountsService/AccountsService.h+46 plugins/AccountsService/CMakeLists.txt+38 plugins/AccountsService/com.canonical.unity.AccountsService.policy+24 plugins/AccountsService/com.canonical.unity.AccountsService.xml+17 plugins/AccountsService/plugin.cpp+35 plugins/AccountsService/plugin.h+34 plugins/AccountsService/qmldir+3 plugins/CMakeLists.txt+4−3 tests/mocks/AccountsService/AccountsService.cpp+33 tests/mocks/AccountsService/AccountsService.h+39 tests/mocks/AccountsService/CMakeLists.txt+19 tests/mocks/AccountsService/plugin.cpp+36 tests/mocks/AccountsService/plugin.h+35 tests/mocks/AccountsService/qmldir+2 tests/mocks/CMakeLists.txt+1 tests/plugins/AccountsService/AccountsServer.cpp+35 tests/plugins/AccountsService/AccountsServer.h+39 tests/plugins/AccountsService/CMakeLists.txt+40 tests/plugins/AccountsService/PropertiesServer.cpp+45 tests/plugins/AccountsService/PropertiesServer.h+44 tests/plugins/AccountsService/client.cpp+49 tests/plugins/AccountsService/interfaces.xml+20 tests/plugins/AccountsService/server.cpp+46 tests/plugins/CMakeLists.txt+3−2 tests/qmltests/CMakeLists.txt+1 tests/qmltests/Components/tst_DemoOverlay.qml+99
Components/DemoOverlay.qmlnew file+239
@@ -0,0 +1,239 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtGraphicalEffects 1.0
19+import Ubuntu.Application 0.1
20+import Ubuntu.Components 0.1
21+
22+Item {
23+ id: overlay
24+
25+ /*
26+ * Valid values are "left", "right", "top", "bottom", or "none".
27+ */
28+ property string edge: "top"
29+
30+ /*
31+ * This is the header displayed, like "Right edge".
32+ */
33+ property string title
34+
35+ /*
36+ * This is the block of text displayed below the header.
37+ */
38+ property string text
39+
40+ /*
41+ * This is the text for the skip button.
42+ */
43+ property string skipText: i18n.tr("Skip intro")
44+
45+ /*
46+ * Whether this demo is allowed to run.
47+ */
48+ property bool enabled: true
49+
50+ /*
51+ * Whether this demo is running currently.
52+ */
53+ readonly property bool active: enabled && visible
54+
55+ property color __orange: Qt.hsla(16.0/360.0, 0.83, 0.47, 1.0)
56+ property color __orange_transparent: Qt.hsla(16.0/360.0, 0.83, 0.47, 0.4)
57+ property int __edge_margin: units.gu(4)
58+ property int __text_margin: units.gu(3)
59+ property int __anim_running: wholeAnimation.running // for testing
60+
61+ signal skip()
62+
63+ Rectangle {
64+ id: backgroundShade
65+ anchors.fill: parent
66+ color: "black"
67+ opacity: 0.8
68+ visible: overlay.active
69+
70+ MouseArea {
71+ anchors.fill: parent
72+ enabled: overlay.edge == "none" && overlay.opacity == 1.0
73+ onClicked: fadeOutAnimation.running = true
74+ }
75+ }
76+
77+ Item {
78+ id: hintGroup
79+ x: 0
80+ y: 0
81+ width: parent.width
82+ height: parent.height
83+ visible: overlay.active
84+
85+ Column {
86+ id: labelGroup
87+ layer.enabled: true // otherwise the underlining on "Skip intro" jumps
88+ spacing: overlay.__text_margin
89+
90+ anchors {
91+ margins: overlay.__edge_margin
92+ left: parent.left
93+ top: overlay.edge == "bottom" ? undefined : parent.top
94+ bottom: overlay.edge == "bottom" ? parent.bottom : undefined
95+ }
96+
97+ Label {
98+ id: titleLabel
99+ text: overlay.title
100+ fontSize: "x-large"
101+ width: units.gu(25)
102+ wrapMode: Text.WordWrap
103+ }
104+
105+ Label {
106+ id: textLabel
107+ text: overlay.text
108+ width: units.gu(25)
109+ wrapMode: Text.WordWrap
110+ }
111+
112+ Label {
113+ id: skipLabel
114+ objectName: "skipLabel"
115+ text: overlay.skipText
116+ color: overlay.__orange
117+ fontSize: "small"
118+ font.underline: true
119+
120+ MouseArea {
121+ anchors.fill: parent
122+ onClicked: fadeOutAnimation.running = true
123+ }
124+ }
125+ }
126+
127+ LinearGradient {
128+ id: edgeHint
129+ property int size: 1
130+ cached: false
131+ visible: overlay.edge != "none"
132+ gradient: Gradient {
133+ GradientStop {
134+ position: 0.0
135+ color: overlay.__orange_transparent
136+ }
137+ GradientStop {
138+ position: 1.0
139+ color: "#00000000"
140+ }
141+ }
142+ anchors.fill: parent
143+ start: {
144+ if (overlay.edge == "right") {
145+ return Qt.point(width, 0);
146+ } else if (overlay.edge == "left") {
147+ return Qt.point(0, 0);
148+ } else if (overlay.edge == "top") {
149+ return Qt.point(0, 0);
150+ } else {
151+ return Qt.point(0, height);
152+ }
153+ }
154+ end: {
155+ if (overlay.edge == "right") {
156+ return Qt.point(width - size, 0);
157+ } else if (overlay.edge == "left") {
158+ return Qt.point(size, 0);
159+ } else if (overlay.edge == "top") {
160+ return Qt.point(0, size);
161+ } else {
162+ return Qt.point(0, height - size);
163+ }
164+ }
165+ }
166+ }
167+
168+ PropertyAnimation {
169+ id: fadeOutAnimation
170+ target: overlay
171+ property: "opacity"
172+ to: 0
173+ duration: 250
174+
175+ onStopped: {
176+ overlay.enabled = false;
177+ overlay.visible = false;
178+ skip()
179+ }
180+ }
181+
182+ SequentialAnimation {
183+ id: wholeAnimation
184+ running: overlay.active
185+
186+ ParallelAnimation {
187+ id: fadeInAnimation
188+
189+ StandardAnimation {
190+ target: labelGroup
191+ property: {
192+ if (overlay.edge == "right" || overlay.edge == "left") {
193+ return "anchors.leftMargin";
194+ } else if (overlay.edge == "bottom") {
195+ return "anchors.bottomMargin";
196+ } else {
197+ return "anchors.topMargin";
198+ }
199+ }
200+ from: {
201+ if (overlay.edge == "right") {
202+ return overlay.__edge_margin + units.gu(3)
203+ } else {
204+ return overlay.__edge_margin - units.gu(3)
205+ }
206+ }
207+ to: overlay.__edge_margin
208+ duration: overlay.edge == "none" ? 0 : 1000
209+ }
210+ StandardAnimation {
211+ target: overlay
212+ property: "opacity"
213+ from: 0.0
214+ to: 1.0
215+ duration: 1000
216+ }
217+ }
218+
219+ SequentialAnimation {
220+ id: hintAnimation
221+ loops: Animation.Infinite
222+ property string prop: (overlay.edge == "left" || overlay.edge == "right") ? "x" : "y"
223+ property double endVal: units.dp(5) * ((overlay.edge == "left" || overlay.edge == "top") ? 1 : -1)
224+ property double maxGlow: units.dp(20)
225+ property int duration: overlay.edge == "none" ? 0 : 1000
226+
227+ ParallelAnimation {
228+ StandardAnimation { target: hintGroup; property: hintAnimation.prop; from: 0; to: hintAnimation.endVal; duration: hintAnimation.duration }
229+ StandardAnimation { target: edgeHint; property: "size"; from: 1; to: hintAnimation.maxGlow; duration: hintAnimation.duration }
230+ }
231+
232+ // Undo the above
233+ ParallelAnimation {
234+ StandardAnimation { target: hintGroup; property: hintAnimation.prop; from: hintAnimation.endVal; to: 0; duration: hintAnimation.duration }
235+ StandardAnimation { target: edgeHint; property: "size"; from: hintAnimation.maxGlow; to: 1; duration: hintAnimation.duration }
236+ }
237+ }
238+ }
239+}
Greeter/Greeter.qml+6−2
@@ -44,6 +44,8 @@ Showable {
4444 readonly property bool rightTeaserPressed: greeterContentLoader.status == Loader.Ready &&
4545 greeterContentLoader.item.rightTeaserPressed
4646
47+ readonly property int currentIndex: greeterContentLoader.currentIndex
48+
4749 signal selected(int uid)
4850 signal unlocked(int uid)
4951
@@ -63,11 +65,13 @@ Showable {
6365
6466 source: required ? "GreeterContent.qml" : ""
6567
66−
6768 Connections {
6869 target: greeterContentLoader.item
6970
70− onSelected: greeter.selected(uid);
71+ onSelected: {
72+ greeter.selected(uid);
73+ greeterContentLoader.currentIndex = uid;
74+ }
7175 onUnlocked: greeter.unlocked(uid);
7276 }
7377 }
Launcher/Launcher.qml+1
@@ -143,6 +143,7 @@ Item {
143143 LauncherPanel {
144144 id: panel
145145 objectName: "launcherPanel"
146+ enabled: root.available
146147 width: root.panelWidth
147148 anchors {
148149 top: parent.top
Panel/Indicators.qml+2−2
@@ -301,7 +301,7 @@ Showable {
301301 anchors.right: parent.right
302302 height: panelHeight
303303 direction: Direction.Downwards
304− enabled: !indicators.shown
304+ enabled: !indicators.shown && indicators.available
305305 hintDisplacement: pinnedMode ? indicators.hintValue : 0
306306 autoCompleteDragThreshold: maxTotalDragDistance / 2
307307 stretch: true
@@ -318,7 +318,7 @@ Showable {
318318 id: hideDragHandle
319319 anchors.fill: handle
320320 direction: Direction.Upwards
321− enabled: indicators.shown
321+ enabled: indicators.shown && indicators.available
322322 hintDisplacement: indicators.hintValue
323323 autoCompleteDragThreshold: maxTotalDragDistance / 6
324324 stretch: true
Shell.qml+135−3
@@ -19,6 +19,7 @@ import Ubuntu.Application 0.1
1919import Ubuntu.Components 0.1
2020import Ubuntu.Gestures 0.1
2121import LightDM 0.1 as LightDM
22+import AccountsService 0.1
2223import Powerd 0.1
2324import "Dash"
2425import "Greeter"
@@ -58,6 +59,19 @@ FocusScope {
5859 }
5960 }
6061
62+ property bool showEdgeDemo: false
63+ property bool showEdgeDemoInGreeter: showEdgeDemo //AccountsService.getUserProperty("lightdm", "demo-edges")
64+
65+ function hideEdgeDemo() {
66+ var user = LightDM.Users.data(greeter.currentIndex, LightDM.UserRoles.NameRole);
67+ AccountsService.setUserProperty(user, "demo-edges", false);
68+ shell.showEdgeDemo = false;
69+ }
70+ function hideEdgeDemoInGreeter() {
71+ //AccountsService.setUserProperty("lightdm", "demo-edges", false);
72+ shell.showEdgeDemoInGreeter = false;
73+ }
74+
6175 property ListModel searchHistory: SearchHistoryModel {}
6276
6377 property var applicationManager: ApplicationManagerWrapper {}
@@ -160,7 +174,7 @@ FocusScope {
160174 available: !greeter.shown && !lockscreen.shown
161175 hides: [stages, launcher, panel.indicators]
162176 shown: disappearingAnimationProgress !== 1.0
163− enabled: disappearingAnimationProgress === 0.0
177+ enabled: disappearingAnimationProgress === 0.0 && !leftEdgeDemo.active && !topEdgeDemo.active && !finalEdgeDemo.active
164178 // FIXME: unfocus all applications when going back to the dash
165179 onEnabledChanged: {
166180 if (enabled) {
@@ -187,6 +201,50 @@ FocusScope {
187201 // greeterRevealer.animatedProgress are not animated
188202 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
189203 }
204+
205+ DemoOverlay {
206+ id: topEdgeDemo
207+
208+ edge: "top"
209+ title: i18n.tr("Top edge")
210+ text: i18n.tr("Try swiping from the top edge to access the indicators")
211+ anchors.fill: dash
212+ visible: false
213+ enabled: shell.showEdgeDemo
214+ onSkip: shell.hideEdgeDemo()
215+
216+ Connections {
217+ target: greeter
218+ onShownChanged: if (!greeter.shown) topEdgeDemo.visible = true
219+ }
220+
221+ Connections {
222+ target: panel.indicators
223+ onFullyOpenedChanged: if (panel.indicators.fullyOpened) topEdgeDemo.enabled = false
224+ }
225+ }
226+
227+ DemoOverlay {
228+ id: leftEdgeDemo
229+
230+ edge: "left"
231+ title: i18n.tr("Left edge")
232+ text: i18n.tr("Swipe from the left to reveal the launcher for quick access to apps")
233+ anchors.fill: dash
234+ visible: false
235+ enabled: shell.showEdgeDemo
236+ onSkip: shell.hideEdgeDemo()
237+
238+ Connections {
239+ target: bottomEdgeDemo
240+ onActiveChanged: if (!bottomEdgeDemo.active) leftEdgeDemo.visible = true
241+ }
242+
243+ Connections {
244+ target: launcher
245+ onProgressChanged: if (launcher.progress >= 1.0) leftEdgeDemo.enabled = false
246+ }
247+ }
190248 }
191249
192250
@@ -381,6 +439,7 @@ FocusScope {
381439 Component.onCompleted: {
382440 if (LightDM.Users.count == 1) {
383441 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
442+ greeter.selected(0)
384443 }
385444 }
386445 }
@@ -423,6 +482,7 @@ FocusScope {
423482 // If there are more users, the Greeter will handle that
424483 if (LightDM.Users.count == 1) {
425484 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
485+ greeter.selected(0);
426486 }
427487 greeter.forceActiveFocus();
428488 }
@@ -430,8 +490,12 @@ FocusScope {
430490
431491 onUnlocked: greeter.hide()
432492 onSelected: {
493+ // Update background
433494 var bgPath = greeter.model.data(uid, LightDM.UserRoles.BackgroundPathRole)
434495 shell.background = bgPath ? bgPath : default_background
496+ // Update edge demo hint
497+ var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole)
498+ shell.showEdgeDemo = AccountsService.getUserProperty(user, "demo-edges")
435499 }
436500
437501 onLeftTeaserPressedChanged: {
@@ -439,6 +503,34 @@ FocusScope {
439503 launcher.tease();
440504 }
441505 }
506+
507+ DemoOverlay {
508+ id: rightEdgeDemo
509+
510+ edge: "right"
511+ title: i18n.tr("Right edge")
512+ text: i18n.tr("Try swiping from the right edge to unlock the phone")
513+ anchors.fill: parent
514+ visible: shell.showEdgeDemoInGreeter
515+ onSkip: {
516+ shell.hideEdgeDemoInGreeter()
517+ shell.hideEdgeDemo()
518+ }
519+
520+ Connections {
521+ target: greeter
522+
523+ function hide() {
524+ if (rightEdgeDemo.active) {
525+ rightEdgeDemo.enabled = false
526+ shell.hideEdgeDemoInGreeter()
527+ }
528+ }
529+
530+ onUnlocked: hide()
531+ onShownChanged: if (!greeter.shown) hide()
532+ }
533+ }
442534 }
443535
444536 InputFilterArea {
@@ -493,6 +585,7 @@ FocusScope {
493585 indicatorsMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
494586 indicators {
495587 hides: [launcher]
588+ available: !rightEdgeDemo.active && !leftEdgeDemo.active && !finalEdgeDemo.active
496589 }
497590 fullscreenMode: shell.fullscreenMode
498591 searchVisible: !greeter.shown && !lockscreen.shown
@@ -501,6 +594,24 @@ FocusScope {
501594 anchors.fill: parent
502595 blockInput: panel.indicators.shown
503596 }
597+
598+ DemoOverlay {
599+ id: bottomEdgeDemo
600+
601+ edge: "bottom"
602+ title: i18n.tr("Close")
603+ text: i18n.tr("Swipe up again to close the settings screen")
604+ anchors.fill: panel.indicators
605+ visible: false
606+ enabled: shell.showEdgeDemo
607+ onSkip: shell.hideEdgeDemo()
608+
609+ Connections {
610+ target: panel.indicators
611+ onFullyOpenedChanged: if (panel.indicators.fullyOpened) bottomEdgeDemo.visible = true
612+ onPartiallyOpenedChanged: if (!panel.indicators.partiallyOpened && !panel.indicators.fullyOpened) bottomEdgeDemo.enabled = false
613+ }
614+ }
504615 }
505616
506617 Hud {
@@ -509,7 +620,7 @@ FocusScope {
509620 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
510621 height: parent.height
511622
512− available: !greeter.shown && !panel.indicators.shown && !lockscreen.shown
623+ available: !greeter.shown && !panel.indicators.shown && !lockscreen.shown && !topEdgeDemo.active
513624 shown: false
514625 showAnimation: StandardAnimation { property: "y"; duration: hud.showableAnimationDuration; to: 0; easing.type: Easing.Linear }
515626 hideAnimation: StandardAnimation { property: "y"; duration: hud.showableAnimationDuration; to: hudRevealer.closedValue; easing.type: Easing.Linear }
@@ -567,7 +678,7 @@ FocusScope {
567678 anchors.bottom: parent.bottom
568679 width: parent.width
569680 dragAreaWidth: shell.edgeSize
570− available: !greeter.shown || greeter.narrowMode
681+ available: (!greeter.shown || greeter.narrowMode) && !rightEdgeDemo.active && !topEdgeDemo.active && !bottomEdgeDemo.active && !finalEdgeDemo.active
571682 onDashItemSelected: {
572683 greeter.hide()
573684 // Animate if moving between application and dash
@@ -625,6 +736,27 @@ FocusScope {
625736 }
626737 }
627738
739+ DemoOverlay {
740+ id: finalEdgeDemo
741+
742+ edge: "none"
743+ title: i18n.tr("Well done")
744+ text: i18n.tr("You have now mastered the edge gestures and can start using the phone")
745+ skipText: i18n.tr("Finish")
746+ anchors.fill: overlay
747+ visible: false
748+ enabled: shell.showEdgeDemo
749+ onSkip: {
750+ launcher.hide();
751+ shell.hideEdgeDemo();
752+ }
753+
754+ Connections {
755+ target: leftEdgeDemo
756+ onActiveChanged: if (!leftEdgeDemo.active) finalEdgeDemo.visible = true
757+ }
758+ }
759+
628760 focus: true
629761
630762 InputFilterArea {
debian/control+2
@@ -3,6 +3,7 @@ Section: x11
33Priority: optional
44Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
55Build-Depends: cmake,
6+ dbus-test-runner,
67 debhelper (>= 9),
78 libdee-qt5-dev (>= 3.2),
89 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
@@ -31,6 +32,7 @@ Build-Depends: cmake,
3132 python3:any,
3233 qt5-default,
3334 qtbase5-dev,
35+ qtbase5-dev-tools,
3436 qtbase5-private-dev,
3537 qtdeclarative5-dev,
3638 qtdeclarative5-dev-tools,
debian/unity8-private.install+5
@@ -1,3 +1,4 @@
1+usr/lib/*/unity8/qml/AccountsService
12usr/lib/*/unity8/qml/HudClient
23usr/lib/*/unity8/qml/LightDM
34usr/lib/*/unity8/qml/ListViewWithPageHeader
@@ -5,3 +6,7 @@ usr/lib/*/unity8/qml/Powerd
56usr/lib/*/unity8/qml/Ubuntu
67usr/lib/*/unity8/qml/Unity
78usr/lib/*/unity8/qml/Utils
9+usr/share/accountsservice/interfaces
10+usr/share/dbus-1/interfaces
11+usr/share/polkit-1
12+var/lib/polkit-1
plugins/AccountsService/50-com.canonical.unity.AccountsService.pklanew file+6
@@ -0,0 +1,6 @@
1+[Allow LightDM to set Unity AccountsService fields]
2+Identity=unix-user:lightdm
3+Action=com.canonical.unity.AccountsService.ModifyAnyUser
4+ResultActive=yes
5+ResultInactive=yes
6+ResultAny=yes
plugins/AccountsService/AccountsService.cppnew file+70
@@ -0,0 +1,70 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "AccountsService.h"
20+#include <QtDBus/QDBusConnection>
21+#include <QtDBus/QDBusMessage>
22+#include <QtDBus/QDBusVariant>
23+
24+AccountsService::AccountsService(QObject* parent)
25+ : QObject(parent),
26+ accounts_manager(NULL),
27+ users()
28+{
29+ accounts_manager = new QDBusInterface("org.freedesktop.Accounts",
30+ "/org/freedesktop/Accounts",
31+ "org.freedesktop.Accounts",
32+ QDBusConnection::SM_BUSNAME(), this);
33+}
34+
35+QVariant AccountsService::getUserProperty(const QString &user, const QString &property)
36+{
37+ auto iface = getUserInterface(user);
38+ if (iface != nullptr && iface->isValid()) {
39+ auto answer = iface->call("Get", "com.canonical.unity.AccountsService", property);
40+ if (answer.type() == QDBusMessage::ReplyMessage) {
41+ return answer.arguments()[0].value<QDBusVariant>().variant();
42+ }
43+ }
44+ return QVariant();
45+}
46+
47+void AccountsService::setUserProperty(const QString &user, const QString &property, const QVariant &value)
48+{
49+ auto iface = getUserInterface(user);
50+ if (iface != nullptr && iface->isValid()) {
51+ // The value needs to be carefully wrapped
52+ iface->call("Set", "com.canonical.unity.AccountsService", property, QVariant::fromValue(QDBusVariant(value)));
53+ }
54+}
55+
56+QDBusInterface *AccountsService::getUserInterface(const QString &user)
57+{
58+ auto iface = users.value(user);
59+ if (iface == nullptr && accounts_manager->isValid()) {
60+ auto answer = accounts_manager->call("FindUserByName", user);
61+ if (answer.type() == QDBusMessage::ReplyMessage) {
62+ iface = new QDBusInterface("org.freedesktop.Accounts",
63+ answer.arguments()[0].value<QDBusObjectPath>().path(),
64+ "org.freedesktop.DBus.Properties",
65+ accounts_manager->connection(), this);
66+ users.insert(user, iface);
67+ }
68+ }
69+ return iface;
70+}
plugins/AccountsService/AccountsService.hnew file+46
@@ -0,0 +1,46 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#ifndef UNITY_ACCOUNTSSERVICE_H
20+#define UNITY_ACCOUNTSSERVICE_H
21+
22+#include <QtDBus/QDBusInterface>
23+#include <QtCore/QMap>
24+#include <QtCore/QObject>
25+#include <QtCore/QString>
26+
27+class AccountsService: public QObject
28+{
29+ Q_OBJECT
30+
31+public:
32+ explicit AccountsService(QObject *parent = 0);
33+
34+public Q_SLOTS:
35+ QVariant getUserProperty(const QString &user, const QString &property);
36+ void setUserProperty(const QString &user, const QString &property, const QVariant &value);
37+
38+private Q_SLOTS:
39+ QDBusInterface *getUserInterface(const QString &user);
40+
41+private:
42+ QDBusInterface *accounts_manager;
43+ QMap<QString, QDBusInterface *> users;
44+};
45+
46+#endif
plugins/AccountsService/CMakeLists.txtnew file+38
@@ -0,0 +1,38 @@
1+include(Plugins)
2+
3+add_definitions(-DSM_BUSNAME=systemBus)
4+
5+add_library(AccountsService-qml MODULE
6+ AccountsService.cpp
7+ plugin.cpp
8+ )
9+
10+qt5_use_modules(AccountsService-qml DBus Qml)
11+
12+export_qmlfiles(AccountsService AccountsService)
13+export_qmlplugin(AccountsService 0.1 AccountsService TARGETS AccountsService-qml)
14+
15+# Debian defines CMAKE_INSTALL_LOCALSTATEDIR as /usr/var, which is wrong.
16+# So until Debian bug 719148 is fixed, hardcode it.
17+set(POLKIT_LIB_DIR "/var/lib/polkit-1")
18+set(POLKIT_DATA_DIR "${CMAKE_INSTALL_PREFIX}/share/polkit-1")
19+set(DBUS_IFACE_DIR "${CMAKE_INSTALL_PREFIX}/share/dbus-1/interfaces")
20+set(ACCOUNTS_IFACE_DIR "${CMAKE_INSTALL_PREFIX}/share/accountsservice/interfaces")
21+
22+install(FILES com.canonical.unity.AccountsService.xml
23+ DESTINATION "${DBUS_IFACE_DIR}"
24+ )
25+
26+# Create accountsservice symlink for above dbus interface
27+install(CODE "
28+execute_process(COMMAND mkdir -p \"\$ENV{DESTDIR}${ACCOUNTS_IFACE_DIR}\")
29+execute_process(COMMAND ln -sf ../../dbus-1/interfaces/com.canonical.unity.AccountsService.xml \"\$ENV{DESTDIR}${ACCOUNTS_IFACE_DIR}\")
30+ ")
31+
32+install(FILES com.canonical.unity.AccountsService.policy
33+ DESTINATION "${POLKIT_DATA_DIR}/actions"
34+ )
35+
36+install(FILES 50-com.canonical.unity.AccountsService.pkla
37+ DESTINATION "${POLKIT_LIB_DIR}/localauthority/10-vendor.d"
38+ )
plugins/AccountsService/com.canonical.unity.AccountsService.policynew file+24
@@ -0,0 +1,24 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+
3+<policyconfig>
4+ <action id="com.canonical.unity.AccountsService.ModifyOwnUser">
5+ <description>Set properties of own user</description>
6+ <message>Authentication is required to set one's own unity properties.</message>
7+ <defaults>
8+ <allow_any>yes</allow_any>
9+ <allow_inactive>yes</allow_inactive>
10+ <allow_active>yes</allow_active>
11+ </defaults>
12+ </action>
13+
14+ <action id="com.canonical.unity.AccountsService.ModifyAnyUser">
15+ <description>Set properties of any user</description>
16+ <message>Authentication is required to set another user's unity
17+properties.</message>
18+ <defaults>
19+ <allow_any>no</allow_any>
20+ <allow_inactive>no</allow_inactive>
21+ <allow_active>no</allow_active>
22+ </defaults>
23+ </action>
24+</policyconfig>
plugins/AccountsService/com.canonical.unity.AccountsService.xmlnew file+17
@@ -0,0 +1,17 @@
1+<node>
2+ <interface name="com.canonical.unity.AccountsService">
3+
4+ <annotation name="org.freedesktop.Accounts.VendorExtension" value="true"/>
5+
6+ <annotation name="org.freedesktop.Accounts.Authentication.ChangeOwn"
7+ value="com.canonical.unity.AccountsService.ModifyOwnUser"/>
8+
9+ <annotation name="org.freedesktop.Accounts.Authentication.ChangeAny"
10+ value="com.canonical.unity.AccountsService.ModifyAnyUser"/>
11+
12+ <property name="demo-edges" type="b" access="readwrite">
13+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
14+ </property>
15+
16+ </interface>
17+</node>
plugins/AccountsService/plugin.cppnew file+35
@@ -0,0 +1,35 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "plugin.h"
20+#include "AccountsService.h"
21+
22+#include <QtQml/QtQml>
23+
24+static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
25+{
26+ Q_UNUSED(engine)
27+ Q_UNUSED(scriptEngine)
28+ return new AccountsService();
29+}
30+
31+void AccountsServicePlugin::registerTypes(const char *uri)
32+{
33+ Q_ASSERT(uri == QLatin1String("AccountsService"));
34+ qmlRegisterSingletonType<AccountsService>(uri, 0, 1, "AccountsService", service_provider);
35+}
plugins/AccountsService/plugin.hnew file+34
@@ -0,0 +1,34 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#ifndef ACCOUNTSSERVICE_PLUGIN_H
20+#define ACCOUNTSSERVICE_PLUGIN_H
21+
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlExtensionPlugin>
24+
25+class AccountsServicePlugin : public QQmlExtensionPlugin
26+{
27+ Q_OBJECT
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29+
30+public:
31+ void registerTypes(const char *uri);
32+};
33+
34+#endif
plugins/AccountsService/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module AccountsService
2+plugin AccountsService-qml
3+typeinfo plugin.qmltypes
plugins/CMakeLists.txt+4−3
@@ -1,7 +1,8 @@
1−add_subdirectory(Ubuntu)
2−add_subdirectory(Utils)
3−add_subdirectory(Unity)
1+add_subdirectory(AccountsService)
42add_subdirectory(HudClient)
53add_subdirectory(LightDM)
64add_subdirectory(ListViewWithPageHeader)
75add_subdirectory(Powerd)
6+add_subdirectory(Ubuntu)
7+add_subdirectory(Unity)
8+add_subdirectory(Utils)
tests/mocks/AccountsService/AccountsService.cppnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "AccountsService.h"
20+
21+AccountsService::AccountsService(QObject* parent)
22+ : QObject(parent)
23+{
24+}
25+
26+QVariant AccountsService::getUserProperty(const QString &, const QString &)
27+{
28+ return QVariant(false);
29+}
30+
31+void AccountsService::setUserProperty(const QString &, const QString &, const QVariant &)
32+{
33+}
tests/mocks/AccountsService/AccountsService.hnew file+39
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Gerry Boland <gerry.boland@canonical.com>
17+ * Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#ifndef UNITY_MOCK_ACCOUNTSSERVICE_H
21+#define UNITY_MOCK_ACCOUNTSSERVICE_H
22+
23+#include <QtCore/QObject>
24+#include <QtCore/QString>
25+#include <QtCore/QVariant>
26+
27+class AccountsService: public QObject
28+{
29+ Q_OBJECT
30+
31+public:
32+ explicit AccountsService(QObject *parent = 0);
33+
34+public Q_SLOTS:
35+ QVariant getUserProperty(const QString &user, const QString &property);
36+ void setUserProperty(const QString &user, const QString &property, const QVariant &value);
37+};
38+
39+#endif
tests/mocks/AccountsService/CMakeLists.txtnew file+19
@@ -0,0 +1,19 @@
1+add_library(MockAccountsService-qml MODULE
2+ AccountsService.cpp
3+ plugin.cpp
4+ )
5+
6+qt5_use_modules(MockAccountsService-qml DBus Qml)
7+
8+# copy files into build directory for shadow builds
9+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
10+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
11+ )
12+
13+install(TARGETS MockAccountsService-qml
14+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/AccountsService
15+ )
16+
17+install(FILES qmldir
18+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/AccountsService
19+ )
tests/mocks/AccountsService/plugin.cppnew file+36
@@ -0,0 +1,36 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Gerry Boland <gerry.boland@canonical.com>
17+ * Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#include "plugin.h"
21+#include "AccountsService.h"
22+
23+#include <QtQml/QtQml>
24+
25+static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
26+{
27+ Q_UNUSED(engine)
28+ Q_UNUSED(scriptEngine)
29+ return new AccountsService();
30+}
31+
32+void AccountsServicePlugin::registerTypes(const char *uri)
33+{
34+ Q_ASSERT(uri == QLatin1String("AccountsService"));
35+ qmlRegisterSingletonType<AccountsService>(uri, 0, 1, "AccountsService", service_provider);
36+}
tests/mocks/AccountsService/plugin.hnew file+35
@@ -0,0 +1,35 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Gerry Boland <gerry.boland@canonical.com>
17+ * Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#ifndef MOCK_ACCOUNTSSERVICE_PLUGIN_H
21+#define MOCK_ACCOUNTSSERVICE_PLUGIN_H
22+
23+#include <QtQml/QQmlEngine>
24+#include <QtQml/QQmlExtensionPlugin>
25+
26+class AccountsServicePlugin : public QQmlExtensionPlugin
27+{
28+ Q_OBJECT
29+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
30+
31+public:
32+ void registerTypes(const char *uri);
33+};
34+
35+#endif
tests/mocks/AccountsService/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module AccountsService
2+plugin MockAccountsService-qml
tests/mocks/CMakeLists.txt+1
@@ -1,3 +1,4 @@
1+add_subdirectory(AccountsService)
12add_subdirectory(HudClient)
23add_subdirectory(libusermetrics)
34add_subdirectory(LightDM)
tests/plugins/AccountsService/AccountsServer.cppnew file+35
@@ -0,0 +1,35 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ *
17+ * Authored by: Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#include "AccountsServer.h"
21+
22+AccountsServer::AccountsServer(QObject *parent)
23+ : QObject(parent)
24+{
25+}
26+
27+QDBusObjectPath AccountsServer::FindUserByName(const QString &user)
28+{
29+ if (user == "testuser") {
30+ return QDBusObjectPath("/user");
31+ } else {
32+ sendErrorReply(QDBusError::InvalidArgs, "Bad user");
33+ return QDBusObjectPath("/");
34+ }
35+}
tests/plugins/AccountsService/AccountsServer.hnew file+39
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ *
17+ * Authored by: Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#ifndef UNITY_ACCOUNTSSERVER_H
21+#define UNITY_ACCOUNTSSERVER_H
22+
23+#include <QtCore/QObject>
24+#include <QtCore/QString>
25+#include <QtDBus/QDBusContext>
26+#include <QtDBus/QDBusObjectPath>
27+
28+class AccountsServer: public QObject, protected QDBusContext
29+{
30+ Q_OBJECT
31+
32+public:
33+ explicit AccountsServer(QObject *parent = 0);
34+
35+public Q_SLOTS:
36+ QDBusObjectPath FindUserByName(const QString &user);
37+};
38+
39+#endif
tests/plugins/AccountsService/CMakeLists.txtnew file+40
@@ -0,0 +1,40 @@
1+macro(make_dbus_class NAME INTERFACE)
2+ if(${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/${NAME}Adaptor.h)
3+ execute_process(COMMAND qdbusxml2cpp -c ${NAME}Adaptor -a ${CMAKE_CURRENT_BINARY_DIR}/${NAME}Adaptor ${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml ${INTERFACE})
4+ endif()
5+endmacro(make_dbus_class)
6+
7+make_dbus_class(Accounts org.freedesktop.Accounts)
8+make_dbus_class(Properties org.freedesktop.DBus.Properties)
9+
10+include_directories(
11+ ${CMAKE_CURRENT_BINARY_DIR}
12+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
13+ )
14+
15+add_definitions(-DSM_BUSNAME=sessionBus)
16+
17+add_executable(mock-server
18+ ${CMAKE_CURRENT_BINARY_DIR}/AccountsAdaptor.cpp
19+ ${CMAKE_CURRENT_BINARY_DIR}/PropertiesAdaptor.cpp
20+ server.cpp
21+ AccountsServer.cpp
22+ PropertiesServer.cpp
23+ )
24+qt5_use_modules(mock-server Core DBus)
25+
26+add_executable(test-accountsservice
27+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsService.cpp
28+ client.cpp
29+ )
30+qt5_use_modules(test-accountsservice Core DBus Test)
31+
32+add_test(NAME test-accountsservice
33+ COMMAND dbus-test-runner
34+ --task ${CMAKE_CURRENT_BINARY_DIR}/mock-server
35+ --task-name server
36+ --ignore-return
37+ --task ${CMAKE_CURRENT_BINARY_DIR}/test-accountsservice
38+ --task-name client
39+ --wait-for org.freedesktop.Accounts
40+ )
tests/plugins/AccountsService/PropertiesServer.cppnew file+45
@@ -0,0 +1,45 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ *
17+ * Authored by: Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#include "PropertiesServer.h"
21+
22+PropertiesServer::PropertiesServer(QObject *parent)
23+ : QObject(parent),
24+ edge_demo(true)
25+{
26+}
27+
28+QDBusVariant PropertiesServer::Get(const QString &interface, const QString &property)
29+{
30+ if (interface == "com.canonical.unity.AccountsService" && property == "demo-edges") {
31+ return QDBusVariant(QVariant(edge_demo));
32+ } else {
33+ sendErrorReply(QDBusError::InvalidArgs, "Bad interface or property");
34+ return QDBusVariant(QVariant());
35+ }
36+}
37+
38+void PropertiesServer::Set(const QString &interface, const QString &property, const QDBusVariant &variant)
39+{
40+ if (interface == "com.canonical.unity.AccountsService" && property == "demo-edges") {
41+ edge_demo = variant.variant().toBool();
42+ } else {
43+ sendErrorReply(QDBusError::InvalidArgs, "Bad interface or property");
44+ }
45+}
tests/plugins/AccountsService/PropertiesServer.hnew file+44
@@ -0,0 +1,44 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ *
17+ * Authored by: Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#ifndef UNITY_PROPERTIESSERVER_H
21+#define UNITY_PROPERTIESSERVER_H
22+
23+#include "PropertiesServer.h"
24+#include <QtCore/QObject>
25+#include <QtCore/QString>
26+#include <QtDBus/QDBusContext>
27+#include <QtDBus/QDBusVariant>
28+
29+class PropertiesServer: public QObject, protected QDBusContext
30+{
31+ Q_OBJECT
32+
33+public:
34+ explicit PropertiesServer(QObject *parent = 0);
35+
36+public Q_SLOTS:
37+ QDBusVariant Get(const QString &interface, const QString &property);
38+ void Set(const QString &interface, const QString &property, const QDBusVariant &variant);
39+
40+private:
41+ bool edge_demo;
42+};
43+
44+#endif
tests/plugins/AccountsService/client.cppnew file+49
@@ -0,0 +1,49 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ *
17+ * Authored by: Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#include "AccountsService.h"
21+#include <QtTest/QSignalSpy>
22+#include <QtTest/QTest>
23+
24+class AccountsServiceTest : public QObject
25+{
26+ Q_OBJECT
27+
28+private Q_SLOTS:
29+
30+ void testInvalids()
31+ {
32+ // Test various invalid calls
33+ AccountsService session;
34+ QCOMPARE(session.getUserProperty("NOPE", "demo-edges"), QVariant());
35+ QCOMPARE(session.getUserProperty("testuser", "NOPE"), QVariant());
36+ }
37+
38+ void testGetSet()
39+ {
40+ AccountsService session;
41+ QCOMPARE(session.getUserProperty("testuser", "demo-edges"), QVariant(true));
42+ session.setUserProperty("testuser", "demo-edges", QVariant(false));
43+ QCOMPARE(session.getUserProperty("testuser", "demo-edges"), QVariant(false));
44+ }
45+};
46+
47+QTEST_MAIN(AccountsServiceTest)
48+
49+#include "client.moc"
tests/plugins/AccountsService/interfaces.xmlnew file+20
@@ -0,0 +1,20 @@
1+<node>
2+ <interface name="org.freedesktop.DBus.Properties">
3+ <method name="Get">
4+ <arg name="interface" type="s" direction="in" />
5+ <arg name="property" type="s" direction="in" />
6+ <arg name="value" type="v" direction="out" />
7+ </method>
8+ <method name="Set">
9+ <arg name="interface" type="s" direction="in" />
10+ <arg name="property" type="s" direction="in" />
11+ <arg name="value" type="v" direction="in" />
12+ </method>
13+ </interface>
14+ <interface name="org.freedesktop.Accounts">
15+ <method name="FindUserByName">
16+ <arg name="user" type="s" direction="in" />
17+ <arg name="path" type="o" direction="out" />
18+ </method>
19+ </interface>
20+</node>
tests/plugins/AccountsService/server.cppnew file+46
@@ -0,0 +1,46 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ *
17+ * Authored by: Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#include "AccountsAdaptor.h"
21+#include "AccountsServer.h"
22+#include "PropertiesAdaptor.h"
23+#include "PropertiesServer.h"
24+#include <QtCore/QCoreApplication>
25+
26+int main(int argc, char *argv[])
27+{
28+ QCoreApplication a(argc, argv);
29+
30+ auto accounts = new AccountsServer();
31+ new AccountsAdaptor(accounts);
32+
33+ auto props = new PropertiesServer();
34+ new PropertiesAdaptor(props);
35+
36+ // We use the session bus for testing. The real plugin uses the system bus
37+ auto connection = QDBusConnection::sessionBus();
38+ if (!connection.registerObject("/org/freedesktop/Accounts", accounts))
39+ return 1;
40+ if (!connection.registerObject("/user", props))
41+ return 1;
42+ if (!connection.registerService("org.freedesktop.Accounts"))
43+ return 1;
44+
45+ return a.exec();
46+}
tests/plugins/CMakeLists.txt+3−2
@@ -1,4 +1,5 @@
1−add_subdirectory(Utils)
1+add_subdirectory(AccountsService)
2+add_subdirectory(ListViewWithPageHeader)
23add_subdirectory(Ubuntu)
34add_subdirectory(Unity)
4−add_subdirectory(ListViewWithPageHeader)
5+add_subdirectory(Utils)
tests/qmltests/CMakeLists.txt+1
@@ -28,6 +28,7 @@ set(qmltest_DEFAULT_PROPERTIES "")
2828
2929add_qml_test(. Shell IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
3030 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
31+add_qml_test(Components DemoOverlay)
3132add_manual_qml_test(Components DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
3233add_qml_test(Components DraggingArea)
3334add_qml_test(Components FilterGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
tests/qmltests/Components/tst_DemoOverlay.qmlnew file+99
@@ -0,0 +1,99 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtTest 1.0
19+import Unity.Test 0.1 as UT
20+import "../../../Components"
21+
22+Item {
23+ id: root
24+ width: 700
25+ height: 500
26+
27+ DemoOverlay {
28+ id: top
29+ edge: "top"
30+ title: "Top"
31+ text: "Displayed on top left"
32+ x: 0
33+ y: 0
34+ width: parent.width/2
35+ height: parent.height/2
36+ }
37+
38+ DemoOverlay {
39+ id: right
40+ edge: "right"
41+ title: "Right"
42+ text: "Displayed on top right"
43+ x: parent.width/2
44+ y: 0
45+ width: parent.width/2
46+ height: parent.height/2
47+ }
48+
49+ DemoOverlay {
50+ id: left
51+ edge: "left"
52+ title: "Left"
53+ text: "Displayed on bottom right"
54+ x: parent.width/2
55+ y: parent.height/2
56+ width: parent.width/2
57+ height: parent.height/2
58+ enabled: false
59+ }
60+
61+ DemoOverlay {
62+ id: bottom
63+ edge: "bottom"
64+ title: "Bottom"
65+ text: "Displayed on bottom left"
66+ x: 0
67+ y: parent.height/2
68+ width: parent.width/2
69+ height: parent.height/2
70+ }
71+
72+ SignalSpy {
73+ id: signalSpy
74+ target: bottom
75+ }
76+
77+ UT.UnityTestCase {
78+ name: "DemoOverlay"
79+ when: windowShown
80+
81+ function test_animations() {
82+ compare(right.__anim_running, 1)
83+
84+ compare(left.__anim_running, 0)
85+ left.enabled = true
86+ compare(left.__anim_running, 1)
87+ }
88+
89+ function test_skip() {
90+ signalSpy.signalName = "skip"
91+ signalSpy.clear()
92+ var bottomSkip = findChild(bottom, "skipLabel")
93+ mousePress(bottomSkip, 1, 1)
94+ mouseRelease(bottomSkip, 1, 1)
95+ signalSpy.wait()
96+ compare(bottom.enabled, false)
97+ }
98+ }
99+}