on xenial help sign in
Skip parts of the edge tutorial that require a touch device (like spread and bottom edge).
b7d662aMichael Terry
qml/Shell.qml+9
@@ -591,6 +591,15 @@ Item {
591 overlay: overlay
591 overlay: overlay
592 edgeSize: shell.edgeSize
592 edgeSize: shell.edgeSize
593
593
594+ // EdgeDragAreas don't work with mice. So to avoid trapping the user,
595+ // we'll tell the tutorial to avoid using them on the Desktop. The
596+ // Desktop doesn't use the same spread design anyway. The tutorial is
597+ // all a bit of a placeholder on non-phone form factors right now.
598+ // When the design team gives us more guidance, we can do something
599+ // more clever here.
600+ // TODO: use DeviceConfiguration instead of checking source
601+ useEdgeDragArea: applicationsDisplayLoader.source != Qt.resolvedUrl("Stages/DesktopStage.qml")
602+
594 onFinished: {
603 onFinished: {
595 AccountsService.demoEdges = false;
604 AccountsService.demoEdges = false;
596 active = false; // for immediate response / if AS is having problems
605 active = false; // for immediate response / if AS is having problems
qml/Tutorial/Tutorial.qml+7
@@ -23,6 +23,7 @@ Item {
23 property alias active: loader.active
23 property alias active: loader.active
24 property bool paused
24 property bool paused
25 property real edgeSize
25 property real edgeSize
26+ property bool useEdgeDragArea
26
27
27 property Item launcher
28 property Item launcher
28 property Item panel
29 property Item panel
@@ -60,6 +61,12 @@ Item {
60 value: root.edgeSize
61 value: root.edgeSize
61 }
62 }
62
63
64+ Binding {
65+ target: loader.item
66+ property: "useEdgeDragArea"
67+ value: root.useEdgeDragArea
68+ }
69+
63 Binding {
70 Binding {
64 target: loader.item
71 target: loader.item
65 property: "launcher"
72 property: "launcher"
qml/Tutorial/TutorialContent.qml+9−1
@@ -34,6 +34,7 @@ Item {
34
34
35 property bool paused: false
35 property bool paused: false
36 property real edgeSize
36 property real edgeSize
37+ property bool useEdgeDragArea
37
38
38 signal finished()
39 signal finished()
39
40
@@ -81,10 +82,17 @@ Item {
81 anchors.fill: parent
82 anchors.fill: parent
82 textXOffset: root.launcher.panelWidth
83 textXOffset: root.launcher.panelWidth
83 paused: !shown || root.paused
84 paused: !shown || root.paused
85+ text: root.useEdgeDragArea ? i18n.tr("Tap here to continue.") : i18n.tr("Click here to finish.")
84
86
85 onFinished: {
87 onFinished: {
86 root.launcher.hide();
88 root.launcher.hide();
89+ if (root.useEdgeDragArea) {
87− tutorialRight.show();
90+ tutorialRight.show();
91+ } else {
92+ // Last two screens use EdgeDragArea (right edge spread and
93+ // bottom edge). So just end tutorial here.
94+ root.finish();
95+ }
88 }
96 }
89 }
97 }
90
98
tests/mocks/GSettings.1.0/fake_gsettings.cpp+58−22
@@ -20,7 +20,9 @@
20
20
21GSettingsControllerQml* GSettingsControllerQml::s_controllerInstance = 0;
21GSettingsControllerQml* GSettingsControllerQml::s_controllerInstance = 0;
22
22
23−GSettingsControllerQml::GSettingsControllerQml() {
23+GSettingsControllerQml::GSettingsControllerQml()
24+ : m_usageMode("Staged")
25+{
24}
26}
25
27
26GSettingsControllerQml::~GSettingsControllerQml() {
28GSettingsControllerQml::~GSettingsControllerQml() {
@@ -34,17 +36,29 @@ GSettingsControllerQml* GSettingsControllerQml::instance() {
34 return s_controllerInstance;
36 return s_controllerInstance;
35}
37}
36
38
39+QString GSettingsControllerQml::pictureUri() const
40+{
41+ return m_pictureUri;
42+}
43+
37−void GSettingsControllerQml::registerSettingsObject(GSettingsQml *obj) {
44+void GSettingsControllerQml::setPictureUri(const QString &str)
38− m_registeredGSettings.append(obj);
45+{
46+ if (str != m_pictureUri) {
47+ m_pictureUri = str;
48+ Q_EMIT pictureUriChanged(m_pictureUri);
49+ }
39}
50}
40
51
41−void GSettingsControllerQml::unRegisterSettingsObject(GSettingsQml *obj) {
52+QString GSettingsControllerQml::usageMode() const
42− m_registeredGSettings.removeOne(obj);
53+{
54+ return m_usageMode;
43}
55}
44
56
45−void GSettingsControllerQml::setPictureUri(const QString &str) {
57+void GSettingsControllerQml::setUsageMode(const QString &usageMode)
46− Q_FOREACH (GSettingsQml *obj, m_registeredGSettings) {
58+{
47− obj->setPictureUri(str);
59+ if (usageMode != m_usageMode) {
60+ m_usageMode = usageMode;
61+ Q_EMIT usageModeChanged(m_usageMode);
48 }
62 }
49}
63}
50
64
@@ -56,7 +70,7 @@ QByteArray GSettingsSchemaQml::id() const {
56}
70}
57
71
58void GSettingsSchemaQml::setId(const QByteArray &id) {
72void GSettingsSchemaQml::setId(const QByteArray &id) {
59− if (m_id.isEmpty()) {
73+ if (!m_id.isEmpty()) {
60 qWarning("GSettings.schema.id may only be set on construction");
74 qWarning("GSettings.schema.id may only be set on construction");
61 return;
75 return;
62 }
76 }
@@ -69,7 +83,7 @@ QByteArray GSettingsSchemaQml::path() const {
69}
83}
70
84
71void GSettingsSchemaQml::setPath(const QByteArray &path) {
85void GSettingsSchemaQml::setPath(const QByteArray &path) {
72− if (m_path.isEmpty()) {
86+ if (!m_path.isEmpty()) {
73 qWarning("GSettings.schema.path may only be set on construction");
87 qWarning("GSettings.schema.path may only be set on construction");
74 return;
88 return;
75 }
89 }
@@ -77,26 +91,48 @@ void GSettingsSchemaQml::setPath(const QByteArray &path) {
77 m_path = path;
91 m_path = path;
78}
92}
79
93
80−GSettingsQml::GSettingsQml(QObject *parent): QObject(parent) {
94+GSettingsQml::GSettingsQml(QObject *parent)
95+ : QObject(parent)
96+{
81 m_schema = new GSettingsSchemaQml(this);
97 m_schema = new GSettingsSchemaQml(this);
82− GSettingsControllerQml::instance()->registerSettingsObject(this);
98+ connect(GSettingsControllerQml::instance(), SIGNAL(pictureUriChanged(const QString &)),
83−}
99+ this, SIGNAL(pictureUriChanged(const QString &)));
84−
85−GSettingsQml::~GSettingsQml() {
86− GSettingsControllerQml::instance()->unRegisterSettingsObject(this);
100+ connect(GSettingsControllerQml::instance(), SIGNAL(usageModeChanged(const QString &)),
101+ this, SIGNAL(usageModeChanged(const QString &)));
87}
102}
88
103
89GSettingsSchemaQml * GSettingsQml::schema() const {
104GSettingsSchemaQml * GSettingsQml::schema() const {
90 return m_schema;
105 return m_schema;
91}
106}
92
107
93−QString GSettingsQml::pictureUri() const {
108+QString GSettingsQml::pictureUri() const
109+{
110+ if (m_schema->id() == "org.gnome.desktop.background") {
111+ return GSettingsControllerQml::instance()->pictureUri();
112+ } else {
94− return m_pictureUri;
113+ return "";
114+ }
95}
115}
96
116
97−void GSettingsQml::setPictureUri(const QString &str) {
117+void GSettingsQml::setPictureUri(const QString &str)
98− if (str != m_pictureUri) {
118+{
99− m_pictureUri = str;
119+ if (m_schema->id() == "org.gnome.desktop.background") {
100− Q_EMIT pictureUriChanged(m_pictureUri);
120+ GSettingsControllerQml::instance()->setPictureUri(str);
121+ }
122+}
123+
124+QString GSettingsQml::usageMode() const
125+{
126+ if (m_schema->id() == "com.canonical.Unity8") {
127+ return GSettingsControllerQml::instance()->usageMode();
128+ } else {
129+ return "";
130+ }
131+}
132+
133+void GSettingsQml::setUsageMode(const QString &usageMode)
134+{
135+ if (m_schema->id() == "com.canonical.Unity8") {
136+ GSettingsControllerQml::instance()->setUsageMode(usageMode);
101 }
137 }
102}
138}
tests/mocks/GSettings.1.0/fake_gsettings.h+16−6
@@ -46,25 +46,26 @@ class GSettingsQml: public QObject
46
46
47 Q_PROPERTY(GSettingsSchemaQml* schema READ schema NOTIFY schemaChanged)
47 Q_PROPERTY(GSettingsSchemaQml* schema READ schema NOTIFY schemaChanged)
48 Q_PROPERTY(QString pictureUri READ pictureUri WRITE setPictureUri NOTIFY pictureUriChanged)
48 Q_PROPERTY(QString pictureUri READ pictureUri WRITE setPictureUri NOTIFY pictureUriChanged)
49+ Q_PROPERTY(QString usageMode READ usageMode WRITE setUsageMode NOTIFY usageModeChanged)
49
50
50public:
51public:
51 GSettingsQml(QObject *parent = nullptr);
52 GSettingsQml(QObject *parent = nullptr);
52− ~GSettingsQml();
53
53
54 GSettingsSchemaQml * schema() const;
54 GSettingsSchemaQml * schema() const;
55 QString pictureUri() const;
55 QString pictureUri() const;
56+ QString usageMode() const;
56
57
57 void setPictureUri(const QString &str);
58 void setPictureUri(const QString &str);
59+ void setUsageMode(const QString &usageMode);
58
60
59Q_SIGNALS:
61Q_SIGNALS:
60 void schemaChanged();
62 void schemaChanged();
61 void pictureUriChanged(const QString&);
63 void pictureUriChanged(const QString&);
64+ void usageModeChanged(const QString&);
62
65
63private:
66private:
64 GSettingsSchemaQml* m_schema;
67 GSettingsSchemaQml* m_schema;
65
68
66− QString m_pictureUri;
67−
68 friend class GSettingsSchemaQml;
69 friend class GSettingsSchemaQml;
69};
70};
70
71
@@ -76,13 +77,22 @@ public:
76 static GSettingsControllerQml* instance();
77 static GSettingsControllerQml* instance();
77 ~GSettingsControllerQml();
78 ~GSettingsControllerQml();
78
79
79− void registerSettingsObject(GSettingsQml *obj);
80+ QString pictureUri() const;
80− void unRegisterSettingsObject(GSettingsQml *obj);
81− Q_INVOKABLE void setPictureUri(const QString &str);
81+ void setPictureUri(const QString &str);
82+
83+ QString usageMode() const;
84+ void setUsageMode(const QString &usageMode);
85+
86+Q_SIGNALS:
87+ void pictureUriChanged(const QString&);
88+ void usageModeChanged(const QString&);
82
89
83private:
90private:
84 GSettingsControllerQml();
91 GSettingsControllerQml();
85
92
93+ QString m_pictureUri;
94+ QString m_usageMode;
95+
86 static GSettingsControllerQml* s_controllerInstance;
96 static GSettingsControllerQml* s_controllerInstance;
87 QList<GSettingsQml *> m_registeredGSettings;
97 QList<GSettingsQml *> m_registeredGSettings;
88};
98};
tests/mocks/GSettings.1.0/plugin.cpp−6
@@ -19,14 +19,8 @@
19
19
20#include <QtQml/qqml.h>
20#include <QtQml/qqml.h>
21
21
22−static QObject* controllerProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
23−{
24− return GSettingsControllerQml::instance();
25−}
26−
27void FakeGSettingsQmlPlugin::registerTypes(const char *uri)
22void FakeGSettingsQmlPlugin::registerTypes(const char *uri)
28{
23{
29− qmlRegisterSingletonType<GSettingsControllerQml>(uri, 1, 0, "GSettingsController", controllerProvider);
30 qmlRegisterType<GSettingsQml>(uri, 1, 0, "GSettings");
24 qmlRegisterType<GSettingsQml>(uri, 1, 0, "GSettings");
31 qmlRegisterUncreatableType<GSettingsSchemaQml>(uri, 1, 0, "GSettingsSchema",
25 qmlRegisterUncreatableType<GSettingsSchemaQml>(uri, 1, 0, "GSettingsSchema",
32 "GSettingsSchema can only be used inside of a GSettings component");
26 "GSettingsSchema can only be used inside of a GSettings component");
tests/qmltests/Tutorial/tst_Tutorial.qml+22−5
@@ -17,6 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import QtTest 1.0
18import QtTest 1.0
19import AccountsService 0.1
19import AccountsService 0.1
20+import GSettings 1.0
20import LightDM 0.1 as LightDM
21import LightDM 0.1 as LightDM
21import Ubuntu.Components 1.1
22import Ubuntu.Components 1.1
22import Unity.Application 0.1
23import Unity.Application 0.1
@@ -45,6 +46,11 @@ Item {
45 }
46 }
46 }
47 }
47
48
49+ GSettings {
50+ id: unity8Settings
51+ schema.id: "com.canonical.Unity8"
52+ }
53+
48 Component.onCompleted: {
54 Component.onCompleted: {
49 // must set the mock mode before loading the Shell
55 // must set the mock mode before loading the Shell
50 LightDM.Greeter.mockMode = "single-pin";
56 LightDM.Greeter.mockMode = "single-pin";
@@ -112,6 +118,7 @@ Item {
112
118
113 function init() {
119 function init() {
114 tryCompare(shell, "enabled", true); // enabled by greeter when ready
120 tryCompare(shell, "enabled", true); // enabled by greeter when ready
121+ unity8Settings.usageMode = "Staged";
115 AccountsService.demoEdges = false;
122 AccountsService.demoEdges = false;
116 AccountsService.demoEdges = true;
123 AccountsService.demoEdges = true;
117 swipeAwayGreeter();
124 swipeAwayGreeter();
@@ -185,17 +192,19 @@ Item {
185 }
192 }
186
193
187 function checkRightEdge() {
194 function checkRightEdge() {
195+ if (unity8Settings.usageMode === "Staged") {
188− touchFlick(shell, shell.width, halfHeight, halfWidth, halfHeight);
196+ touchFlick(shell, shell.width, halfHeight, halfWidth, halfHeight);
189
197
190− var stage = findChild(shell, "stage");
198+ var stage = findChild(shell, "stage");
191− var spreadView = findChild(stage, "spreadView");
199+ var spreadView = findChild(stage, "spreadView");
192− tryCompare(spreadView, "phase", 0);
200+ tryCompare(spreadView, "phase", 0);
201+ }
193 }
202 }
194
203
195 function checkBottomEdge() {
204 function checkBottomEdge() {
196 // Can't actually check effect of swipe, since dash isn't really loaded
205 // Can't actually check effect of swipe, since dash isn't really loaded
197 var applicationsDisplayLoader = findChild(shell, "applicationsDisplayLoader");
206 var applicationsDisplayLoader = findChild(shell, "applicationsDisplayLoader");
198− tryCompare(applicationsDisplayLoader.item, "interactive", false);
207+ tryCompare(applicationsDisplayLoader, "interactive", false);
199 }
208 }
200
209
201 function checkFinished() {
210 function checkFinished() {
@@ -256,6 +265,14 @@ Item {
256 goToPage(null);
265 goToPage(null);
257 }
266 }
258
267
268+ function test_walkthroughOnDesktop() {
269+ unity8Settings.usageMode = "Windowed";
270+ var page = goToPage("tutorialLeftFinish");
271+ var tick = findChild(page, "tick");
272+ tap(tick);
273+ checkFinished();
274+ }
275+
259 function test_launcherShortDrag() {
276 function test_launcherShortDrag() {
260 // goToPage does a normal launcher pull. But here we want to test
277 // goToPage does a normal launcher pull. But here we want to test
261 // just barely pulling the launcher out and letting go (i.e. not
278 // just barely pulling the launcher out and letting go (i.e. not
tests/qmltests/tst_Shell.qml+3−3
@@ -1084,11 +1084,11 @@ Rectangle {
1084 {
1084 {
1085 var buttonShowDashHome = findChild(launcher, "buttonShowDashHome");
1085 var buttonShowDashHome = findChild(launcher, "buttonShowDashHome");
1086 var startPos = buttonShowDashHome.mapToItem(shell,
1086 var startPos = buttonShowDashHome.mapToItem(shell,
1087− buttonShowDashHome.width * 0.8,
1088− buttonShowDashHome.height * 0.2);
1089− var endPos = buttonShowDashHome.mapToItem(shell,
1090 buttonShowDashHome.width * 0.2,
1087 buttonShowDashHome.width * 0.2,
1091 buttonShowDashHome.height * 0.8);
1088 buttonShowDashHome.height * 0.8);
1089+ var endPos = buttonShowDashHome.mapToItem(shell,
1090+ buttonShowDashHome.width * 0.8,
1091+ buttonShowDashHome.height * 0.2);
1092 touchFlick(shell, startPos.x, startPos.y, endPos.x, endPos.y);
1092 touchFlick(shell, startPos.x, startPos.y, endPos.x, endPos.y);
1093 }
1093 }
1094
1094