Merge lp:~mterry/unity8/tutorial-redesign into lp:unity8

Proposed by Michael Terry on 2015-09-16
Status: Superseded
Proposed branch: lp:~mterry/unity8/tutorial-redesign
Merge into: lp:unity8
Diff against target: 4565 lines (+1545/-1541)
62 files modified
plugins/AccountsService/AccountsService.cpp (+49/-0)
plugins/AccountsService/AccountsService.h (+9/-0)
plugins/AccountsService/AccountsService.qmltypes (+5/-0)
plugins/AccountsService/com.canonical.unity.AccountsService.xml (+5/-0)
plugins/ScreenGrabber/screengrabber.cpp (+0/-2)
plugins/Ubuntu/Gestures/DirectionalDragArea.cpp (+40/-5)
plugins/Ubuntu/Gestures/DirectionalDragArea.h (+8/-0)
plugins/Ubuntu/Gestures/DirectionalDragArea_p.h (+2/-0)
plugins/Utils/CMakeLists.txt (+1/-1)
plugins/Utils/Utils.qmltypes (+2/-2)
plugins/Utils/plugin.cpp (+2/-2)
plugins/Utils/windowinputfilter.cpp (+14/-16)
plugins/Utils/windowinputfilter.h (+11/-11)
qml/Components/InputMethod.qml (+1/-9)
qml/Greeter/Greeter.qml (+10/-6)
qml/Launcher/Launcher.qml (+2/-3)
qml/Panel/IndicatorsMenu.qml (+0/-2)
qml/Shell.qml (+27/-45)
qml/Stages/AbstractStage.qml (+1/-0)
qml/Stages/ApplicationWindow.qml (+0/-2)
qml/Stages/PhoneStage.qml (+3/-6)
qml/Stages/TabletStage.qml (+15/-11)
qml/Tutorial/Arrow.qml (+0/-56)
qml/Tutorial/InactivityTimer.qml (+62/-0)
qml/Tutorial/Slider.qml (+0/-123)
qml/Tutorial/Tick.qml (+0/-29)
qml/Tutorial/Tutorial.qml (+43/-18)
qml/Tutorial/TutorialBottom.qml (+0/-104)
qml/Tutorial/TutorialBottomFinish.qml (+0/-41)
qml/Tutorial/TutorialContent.qml (+250/-80)
qml/Tutorial/TutorialLeft.qml (+28/-75)
qml/Tutorial/TutorialLeftFinish.qml (+0/-41)
qml/Tutorial/TutorialLeftLong.qml (+54/-0)
qml/Tutorial/TutorialPage.qml (+66/-190)
qml/Tutorial/TutorialRight.qml (+0/-223)
qml/Tutorial/TutorialTop.qml (+61/-0)
qml/Tutorial/graphics/arrow.svg (+19/-0)
tests/autopilot/unity8/shell/emulators.py (+0/-2)
tests/autopilot/unity8/shell/tests/test_tutorial.py (+0/-57)
tests/autopilot/unity8/tutorial.py (+0/-73)
tests/mocks/AccountsService/AccountsService.cpp (+20/-0)
tests/mocks/AccountsService/AccountsService.h (+10/-0)
tests/mocks/AccountsService/AccountsService.qmltypes (+5/-0)
tests/mocks/Unity/Application/ApplicationInfo.h (+1/-1)
tests/mocks/Unity/Application/MirSurface.cpp (+3/-2)
tests/mocks/Unity/Application/MirSurface.h (+2/-1)
tests/mocks/Unity/Application/SurfaceManager.cpp (+8/-9)
tests/mocks/Unity/Application/SurfaceManager.h (+3/-3)
tests/mocks/Unity/Application/VirtualKeyboard.cpp (+3/-2)
tests/mocks/Unity/Application/VirtualKeyboard.h (+1/-1)
tests/mocks/Unity/Application/plugin.cpp (+2/-1)
tests/mocks/Utils/CMakeLists.txt (+1/-1)
tests/mocks/Utils/Utils.qmltypes (+2/-2)
tests/mocks/Utils/plugin.cpp (+2/-2)
tests/plugins/AccountsService/PropertiesServer.cpp (+1/-0)
tests/plugins/AccountsService/client.cpp (+37/-0)
tests/qmltests/Components/tst_PhysicalKeysMapper.qml (+3/-3)
tests/qmltests/Greeter/tst_Greeter.qml (+7/-1)
tests/qmltests/Tutorial/tst_Tutorial.qml (+639/-245)
tests/qmltests/tst_OrientedShell.qml (+1/-1)
tests/qmltests/tst_Shell.qml (+4/-9)
tests/qmltests/tst_ShellWithPin.qml (+0/-22)
To merge this branch: bzr merge lp:~mterry/unity8/tutorial-redesign
Reviewer Review Type Date Requested Status
Unity8 CI Bot continuous-integration Needs Fixing on 2016-03-10
PS Jenkins bot continuous-integration Needs Fixing on 2016-02-19
Michael Zanetti (community) 2015-09-16 Needs Fixing on 2015-12-01
Albert Astals Cid (community) merges fine Abstain on 2015-11-20
Review via email: mp+271342@code.launchpad.net

This proposal has been superseded by a proposal from 2016-03-10.

Commit Message

Redesign the first-boot edge tutorial

Description of the Change

Based on new design specs [1], this is whole new tutorial code.

Some of the interesting things going on here:

- New DDA feature "monitorOnly" which lets input events "fall through" (i.e. it doesn't own them) but continues to monitor them. This is how we implement the bottom edge tutorial fading out without having to communicate with the app.

- New AccountsService key to keep track of which particular edges are done, now that they are presented separately. We still use the old key for overall "done" status.

- Renamed WindowKeysFilter to WindowInputFilter. I needed a way to keep track of input inactivity. And since WindowKeysFilter was already injecting itself into the event stream and already kept track of timestamps for us (which usually isn't exposed to Qml), I just modified it a bit. I felt like the new scope should be indicated in the name, so I renamed it.

- I took out some old hacks only needed for the old tutorial.

[1] https://docs.google.com/document/d/1pZ-Ro--2eaRzjZKNRoYAeDvQHMkCuyvVuPFWFQfPW4s/edit

== Checklist ==

 * Are there any related MPs required for this MP to build/function as expected? Please list.

 Yes. A new phablet-tools branch for your desktop [2] and a new upload of dbus-property-service (not in a VCS). Both are in silo 33.

 [2] https://code.launchpad.net/~mterry/phablet-tools/tutorial-redesign/+merge/277764

 * Did you perform an exploratory manual test run of your code change and any related functionality?
 Yes

 * Did you make sure that your branch does not contain spurious tags?
 Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
 NA

 * If you changed the UI, has there been a design review?
 Yes. Patricia is on board with this MP. She has another screen coming (long swipe on left), but I'll do that as a separate MP.

To post a comment you must log in.
Michael Terry (mterry) wrote :

<dandrader> mterry, DDA changes in lp:~mterry/unity8/tutorial-redesign look fine
<mterry> dandrader, awesome, thanks
 will quote you in the MP :)
<dandrader> mterry, only unsure about the property name. Because it will work all the same, only difference is that it won't claim ownership over the touch point once it recognizes it's performing a gesture
<mterry> dandrader, yeah. I'm happy to rename it. Got something you like better?
<dandrader> mterry, no :)

Michael Terry (mterry) wrote :

OK, I'm opening this up to review, although the final design review isn't done yet and I need to add a couple more qmltests. But I'd like to get the review train started on its way.

lp:~mterry/unity8/tutorial-redesign updated on 2015-11-18
1978. By Michael Terry on 2015-11-18

Make tryTutorial more useful; add bottom edge tests

Michael Terry (mterry) wrote :

OK, added more tests and cleaned up existing ones. Hopefully this is "done-ish" from a technical POV and only design-related changes will happen now (like changes to strings or alignment).

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1977
http://jenkins.qa.ubuntu.com/job/unity8-ci/6737/
Executed test runs:
    ABORTED: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5244/console
    ABORTED: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/152/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1450
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/152
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1344
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1345
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/151
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/151
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4164/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5264
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5264/artifact/work/output/*zip*/output.zip
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/33/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/152
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/152/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6737/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1978
http://jenkins.qa.ubuntu.com/job/unity8-ci/6739/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5250
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/154/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1452
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/154/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1346
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1347
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/153
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/153
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4168
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5270
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5270/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25246
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/34/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/154
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/154/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25244

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6739/rebuild

review: Needs Fixing (continuous-integration)
Michael Zanetti (mzanetti) wrote :

Hmm... I've just flashed a device and enabled the edges-intro with phablet-config. I could see the intro for left, top and bottom edges, however, still waiting for the right edge one to appear.

====

As you renamed WindowKeyFilter, please update this comment too

qml/Shell.qml: // dummy shortcut to force creation of GlobalShortcutRegistry before WindowKeyFilter

===

- readonly property real dragProgress: spreadRepeater.count > 0 ? -spreadRepeater.itemAt(0).xTranslate : 0
+ dragProgress: spreadRepeater.count > 0 ? spreadRepeater.itemAt(0).animatedProgress : 0

Given that it's not obvious what the dragProgress is used for, please add a comment in the stages code to indicate it. otherwise it's likely to be removed at some point because noone knows what it does.

===

+ ////

Is there a purpose to this? :)

===
+ sourceSize.height: 1080
+ sourceSize.width: 1916

erm... can you explain the values? Looks wrong to me

review: Needs Fixing
Michael Zanetti (mzanetti) wrote :

Notes for myself:

* test if CPU usage drops if screen locks during animation
* test what happens if plugging external screen while in tutorial

lp:~mterry/unity8/tutorial-redesign updated on 2015-11-19
1979. By Michael Terry on 2015-11-19

Add a little more spacing between tutorial lines (design request)

1980. By Michael Terry on 2015-11-19

Add support for custom bottom-edge messages for the five apps we support; put each tutorial object under a loader, since they'll be around much longer now

1981. By Michael Terry on 2015-11-19

Fix design notes

Michael Terry (mterry) wrote :
Download full text (3.2 KiB)

OK, I've made some changes. One, I added some more space between tutorial text lines, per design request.

Second, also per design request, I've added unique helper text on the bottom edge tutorial for each supported app. This also means that we show the tutorial for each app rather than once for any of them. Since this meant that the tutorial might not formally "finish" for quite some time, I've optimized the rest of the tutorial to use Loaders. So that we're not loading three unused background images a week after the user unboxes their phone.

As for your comments:

> Hmm... I've just flashed a device and enabled the edges-intro
> with phablet-config. I could see the intro for left, top and
> bottom edges, however, still waiting for the right edge one to appear.

As discussed on IRC, we're guessing this was user error. Unless you've seen it again?

====

> As you renamed WindowKeyFilter, please update this comment too
>
> qml/Shell.qml: // dummy shortcut to force creation of GlobalShortcutRegistry before WindowKeyFilter

Done.

===

> - readonly property real dragProgress: spreadRepeater.count > 0 ? -spreadRepeater.itemAt(0).xTranslate : 0
> + dragProgress: spreadRepeater.count > 0 ? spreadRepeater.itemAt(0).animatedProgress : 0

> Given that it's not obvious what the dragProgress is used for,
> please add a comment in the stages code to indicate it. otherwise
> it's likely to be removed at some point because noone knows what it does.

Done.

===

> + ////
>
> Is there a purpose to this? :)

Ah, that's just a little visual separator I use between the public interface part of the object and the implementation parts. Qml doesn't use headers, and while we seem to use the placement of the QtObject component to separate the portions of code, sometimes an object doesn't warrant a QtObject, so it isn't a universal distinguisher. Plus, I like the extra visual space.

I can take it out if it will be as confusing to you as others. I know Cimi doesn't like that I do that.

===

> + sourceSize.height: 1080
> + sourceSize.width: 1916
>
> erm... can you explain the values? Looks wrong to me

Duh, I swapped height and width. Fixed.

===

> * test if CPU usage drops if screen locks during animation

Please do, but note that there isn't any animation anymore. So I expect no CPU difference.

===

> * test what happens if plugging external screen while in tutorial

Ah yes. Here's what I expect the code to do:

- Any visible tutorials that aren't marked for desktop use will fade out.
- The right edge tutorial will appear (or update itself) with desktop-specific text when you have enough apps open.
- If you finish the right edge tutorial while in desktop mode, the tutorial will be marked complete and you won't see any more coach marks. However, if you don't finish the right edge tutorial before undocking, you will continue to see all the tutorials you haven't seen yet, as normal.

How do you feel about that last behavior? It might be tricky to do something much smarter unless either (A) we know the "native" usageScenario of the device or (B) we stop marking the "whole-tutorial-is-complete" flag and accept that if we add new pages or redesign th...

Read more...

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1979
http://jenkins.qa.ubuntu.com/job/unity8-ci/6745/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5277
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/160/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1458
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/160/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1352
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1353
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/159
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/159
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4186
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5297
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5297/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25290
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/37/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/160
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/160/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25292

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6745/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1981
http://jenkins.qa.ubuntu.com/job/unity8-ci/6749/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5285
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/164/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1462
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/164/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1356
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1357
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/163
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/163
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4194
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5305
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5305/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25309
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/40/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/164
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/164/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25308

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6749/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

Text conflict in tests/plugins/AccountsService/PropertiesServer.cpp
1 conflicts encountered.

review: Needs Fixing
lp:~mterry/unity8/tutorial-redesign updated on 2015-11-20
1982. By Michael Terry on 2015-11-20

Merge from trunk

Michael Terry (mterry) wrote :

Fixed conflicts.

Albert Astals Cid (aacid) :
review: Abstain (merges fine)
lp:~mterry/unity8/tutorial-redesign updated on 2015-11-23
1983. By Michael Terry on 2015-11-23

Fix compile error

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1983
http://jenkins.qa.ubuntu.com/job/unity8-ci/6787/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5345
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/202/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1500
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/202/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1394
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1395
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/201
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/201
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4239
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5365
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5365/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25431
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/63/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/202
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/202/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25433

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6787/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-redesign updated on 2015-11-24
1984. By Michael Terry on 2015-11-24

Fix qmltests

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1984
http://jenkins.qa.ubuntu.com/job/unity8-ci/6794/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5367
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/209/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1507
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/209/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1401
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1402
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/208
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/208
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4256
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5387
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5387/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25462
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/67/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/209
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/209/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25460

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6794/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-redesign updated on 2015-11-27
1985. By Michael Terry on 2015-11-27

Make bottom edge arrow & text closer to bottom edge, per design

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1985
http://jenkins.qa.ubuntu.com/job/unity8-ci/6823/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5458
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/238/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1534
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/236
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1429
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1429
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/236
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/235
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4306
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5472
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5472/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25583
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/82/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/237
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/237/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25582

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6823/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-redesign updated on 2015-11-30
1986. By Michael Terry on 2015-11-30

Merge from trunk

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1986
http://jenkins.qa.ubuntu.com/job/unity8-ci/6834/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5490
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/249/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1545
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/248
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1440
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1440
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/247
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/246
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4318
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5504
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5504/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25632
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/88/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/248
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/248/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25631

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6834/rebuild

review: Needs Fixing (continuous-integration)
Michael Zanetti (mzanetti) wrote :

+ i18n.tr("Hover your mouse on the right edge to view your open apps") :
+ i18n.tr("Short or long swipe from the right edge to view your open apps")

I know those have been given by design, but gotta point out some errors:
- In windowed mode, you need to push the mouse against the right edge and even overcome some resistance. Hovering is not enough.
- While at it, we might want to ask back on short swipe one too, but I guess that would be ok to oversimplify it in this case.

========

+ text: d.landscape ? i18n.tr("Swipe from the top right edge to open the notification bar")
+ : i18n.tr("Swipe from the top edge to open the notification bar")

this might needs a windowed mode special case too. We don't want to encourage clicking with a mouse so the indicators can also be revealed by clicking the icons. Although this is not wrong. If you have a touch screen too, you can also swipe then on a desktop.

========

+ text: i18n.tr("Swipe from the left edge to open the launcher")

same as for the right edge. With a mouse, it requires pushing towards the edge. Why not special cased here?

review: Needs Information
Michael Zanetti (mzanetti) wrote :

Another question:

I figure it will take ages until completed goes to true. Some people might never open the calculator app which would leave us with the tutorial being enabled forever. What are the implications of that?

review: Needs Information
Michael Terry (mterry) wrote :

You mention the wording on the left edge drag needing to be changed for desktop mode -- but we don't show that tutorial on desktop. So I'm guessing we can leave it as is.

And you asked about the tutorial never "completing". This is a small issue. And it's why I revised TutorialContent to use loaders for each tutorial page. I don't think it's a problem, per se. But it does mean that we'll likely have the TutorialBottom page loaded most of the time. Until they load all the bottom-supported apps anyway...

Michael Zanetti (mzanetti) wrote :

On the right edge in windowed mode, it's not only the text, but the hoverMouseArea disappered and it's not possible to get past that step any more.

review: Needs Fixing
lp:~mterry/unity8/tutorial-redesign updated on 2015-12-14
1987. By Michael Terry on 2015-12-14

Merge from trunkA

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1987
http://jenkins.qa.ubuntu.com/job/unity8-ci/6940/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5756
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/355/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1651
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/354
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1546
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1546
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/353
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/352
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4467
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5769
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5769/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26035
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/130/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/354
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/354/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26036

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6940/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

Text conflict in qml/Launcher/Launcher.qml
1 conflicts encountered.

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:1987
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/35/
Executed test runs:

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/35/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-redesign updated on 2016-01-18
1988. By Michael Terry on 2016-01-18

Merge trunk

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:1988
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/124/
Executed test runs:

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/124/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1988
http://jenkins.qa.ubuntu.com/job/unity8-ci/7092/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6059
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/507/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1797
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/500
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1692
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1692
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/499
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/498
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4680
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6070
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6070/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26746
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/247/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/505
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/505/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26745

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/7092/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-redesign updated on 2016-01-21
1989. By Michael Terry on 2016-01-21

Flip tutorial arrows

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:1989
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/168/
Executed test runs:

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/168/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1989
http://jenkins.qa.ubuntu.com/job/unity8-ci/7129/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6133
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/544/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1834
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/537
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1729
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1729
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/536
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/535
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4732
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6144
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6144/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26923
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/280/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/542
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/542/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26924

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/7129/rebuild

review: Needs Fixing (continuous-integration)
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:1989
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/168/
Executed test runs:

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/168/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

Text conflict in qml/Stages/PhoneStage.qml
Text conflict in qml/Stages/TabletStage.qml
2 conflicts encountered.

lp:~mterry/unity8/tutorial-redesign updated on 2016-02-10
1990. By Michael Terry on 2016-02-10

Merge from trunk

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:1990
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/322/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/443/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/466
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/484
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/484
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/480
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/480/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/480/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/480
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/480/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/480/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/480
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/480/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/480/console

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/322/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1990
http://jenkins.qa.ubuntu.com/job/unity8-ci/7260/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6417
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/675/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1965
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/668
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1860
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1860
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/667
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/666
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4914
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6428
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6428/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27481
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/347/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/673
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/673/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27480

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/7260/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-redesign updated on 2016-02-16
1991. By Michael Terry on 2016-02-16

Don't show bottom tutorial for clock app, it shows permission screen on first launch

1992. By Michael Terry on 2016-02-16

Merge from trunk

1993. By Michael Terry on 2016-02-16

remove bit of cleanup that is in another branch; we conflict if I include it

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:1992
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/385/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/523
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay/165
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial/165
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/546
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/564
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/564
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/560
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/560/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/560
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/560/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/560
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/560/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/560
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/560/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/560
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/560/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/560
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/560/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/385/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1992
http://jenkins.qa.ubuntu.com/job/unity8-ci/7323/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6516
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/738/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/2028
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/731
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1923
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1923
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/730
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/729
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4975
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6527
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6527/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27663
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/383/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/736
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/736/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27664

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/7323/rebuild

review: Needs Fixing (continuous-integration)
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:1993
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/390/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/528
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay/170
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial/170
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/551
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/569
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/569
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/565/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/565/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/565/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/565/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/565/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/565/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/390/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1993
http://jenkins.qa.ubuntu.com/job/unity8-ci/7328/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6521
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/743/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/2033
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/736
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1928
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1928
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/735
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/734
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4980
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6532
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6532/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27677
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/388/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/741
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/741/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27678

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/7328/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-redesign updated on 2016-02-19
1994. By Michael Terry on 2016-02-19

Merge from trunk

1995. By Michael Terry on 2016-02-19

Add long-swipe-from-left-edge screen

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:1995
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/452/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/607
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay/191
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial/191
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/630
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/648
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/648
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/644
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/644/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/644
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/644/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/644
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/644/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/644
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/644/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/644
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/644/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/644
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/644/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/452/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1995
http://jenkins.qa.ubuntu.com/job/unity8-ci/7383/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6583
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/798/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/2088
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/791
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1983
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1983
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/790
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/789
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/5009
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6594
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6594/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27779
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/410/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/796
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/796/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27778

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/7383/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-redesign updated on 2016-03-08
1996. By Michael Terry on 2016-03-08

Merge from trunk

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:1996
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/628/
Executed test runs:
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/356
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial,testname=qmluitests.sh/356
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=phone-armhf,release=vivid+overlay,testname=autopilot.sh/356
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/832
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/848
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/848
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/846
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/846/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/846
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/846/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/846
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/846/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/846
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/846/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/846
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/846/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/846
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/846/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/628/rebuild

review: Needs Fixing (continuous-integration)
Michał Sawicz (saviq) wrote :

Tests need fixin ↑?

lp:~mterry/unity8/tutorial-redesign updated on 2016-03-09
1997. By Michael Terry on 2016-03-09

Merge from trunk

1998. By Michael Terry on 2016-03-09

Fix failing test

1999. By Michael Terry on 2016-03-09

Remove tutorial autopilot test; it's much harder to test via autopilot now that each page fires separately, and we cover it well in qmluitests; there's nothing autopilot-integraty about it

Michael Terry (mterry) wrote :

Fixed the qmluitest, and removed the autopilot test. The tutorial is harder to test via one autopilot test now that the pages have been split up and separately triggered. Plus, we cover them well in qmluitests. And there's nothing autopilot-centric to test there.

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:1999
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/642/
Executed test runs:
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/364
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial,testname=qmluitests.sh/364
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=phone-armhf,release=vivid+overlay,testname=autopilot.sh/364
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/847
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/863
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/863
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/861
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/861/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/861
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/861/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/861
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/861/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/861
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/861/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/861
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/861/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/861
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/861/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/642/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-redesign updated on 2016-03-10
2000. By Michael Terry on 2016-03-10

Fix Tutorial qmluitest too, whoops!

2001. By Michael Terry on 2016-03-10

Merge from trunk

2002. By Michael Terry on 2016-03-10

Merge in catch-osk

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2000
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/656/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/373
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial,testname=qmluitests.sh/373
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=phone-armhf,release=vivid+overlay,testname=autopilot.sh/373
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/862
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/878
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/878
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/876
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/876/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/876
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/876/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/876
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/876/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/876
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/876/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/876
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/876/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/876
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/876/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/656/rebuild

review: Needs Fixing (continuous-integration)
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2002
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/662/
Executed test runs:
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/377
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial,testname=qmluitests.sh/377
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=phone-armhf,release=vivid+overlay,testname=autopilot.sh/377
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/869
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/885
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/885
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/883
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/883/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/883
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/883/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/883
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/883/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/883
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/883/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/883
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/883/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/883
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/883/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/662/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-redesign updated on 2016-03-11
2003. By Michael Terry on 2016-03-11

Merge silo 64

2004. By Michael Terry on 2016-03-11

Merge oobe

Unmerged revisions

2004. By Michael Terry on 2016-03-11

Merge oobe

2003. By Michael Terry on 2016-03-11

Merge silo 64

2002. By Michael Terry on 2016-03-10

Merge in catch-osk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/AccountsService/AccountsService.cpp'
2--- plugins/AccountsService/AccountsService.cpp 2016-01-21 21:04:00 +0000
3+++ plugins/AccountsService/AccountsService.cpp 2016-03-10 17:24:40 +0000
4@@ -28,6 +28,7 @@
5 : QObject(parent),
6 m_service(new AccountsServiceDBusAdaptor(this)),
7 m_demoEdges(false),
8+ m_demoEdgesCompleted(),
9 m_enableLauncherWhileLocked(false),
10 m_enableIndicatorsWhileLocked(false),
11 m_statsWelcomeScreen(false),
12@@ -60,6 +61,7 @@
13 m_user = user;
14 Q_EMIT userChanged();
15
16+ updateDemoEdgesCompleted(false);
17 updateDemoEdges(false);
18 updateEnableLauncherWhileLocked(false);
19 updateEnableIndicatorsWhileLocked(false);
20@@ -88,6 +90,21 @@
21 }
22 }
23
24+QStringList AccountsService::demoEdgesCompleted() const
25+{
26+ return m_demoEdgesCompleted;
27+}
28+
29+void AccountsService::markDemoEdgeCompleted(const QString &edge)
30+{
31+ if (!m_demoEdgesCompleted.contains(edge)) {
32+ m_demoEdgesCompleted << edge;
33+ m_service->setUserPropertyAsync(m_user, "com.canonical.unity.AccountsService", "DemoEdgesCompleted", m_demoEdgesCompleted);
34+
35+ Q_EMIT demoEdgesCompletedChanged();
36+ }
37+}
38+
39 bool AccountsService::enableLauncherWhileLocked() const
40 {
41 return m_enableLauncherWhileLocked;
42@@ -167,6 +184,35 @@
43 }
44 }
45
46+void AccountsService::updateDemoEdgesCompleted(bool async)
47+{
48+ QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
49+ "com.canonical.unity.AccountsService",
50+ "DemoEdgesCompleted");
51+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
52+
53+ connect(watcher, &QDBusPendingCallWatcher::finished,
54+ this, [this](QDBusPendingCallWatcher* watcher) {
55+
56+ QDBusPendingReply<QDBusVariant> reply = *watcher;
57+ watcher->deleteLater();
58+ if (reply.isError()) {
59+ qWarning() << "Failed to get 'DemoEdgesCompleted' property - " << reply.error().message();
60+ return;
61+ }
62+
63+ auto demoEdgesCompleted = reply.value().variant().toStringList();
64+ if (m_demoEdgesCompleted != demoEdgesCompleted) {
65+ m_demoEdgesCompleted = demoEdgesCompleted;
66+ Q_EMIT demoEdgesCompletedChanged();
67+ }
68+ });
69+ if (!async) {
70+ watcher->waitForFinished();
71+ delete watcher;
72+ }
73+}
74+
75 void AccountsService::updateEnableLauncherWhileLocked(bool async)
76 {
77 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
78@@ -473,6 +519,9 @@
79 if (changed.contains(QStringLiteral("demo-edges"))) {
80 updateDemoEdges();
81 }
82+ if (changed.contains(QStringLiteral("DemoEdgesCompleted"))) {
83+ updateDemoEdgesCompleted();
84+ }
85 } else if (interface == QLatin1String("com.canonical.unity.AccountsService.Private")) {
86 if (changed.contains(QStringLiteral("FailedLogins"))) {
87 updateFailedLogins();
88
89=== modified file 'plugins/AccountsService/AccountsService.h'
90--- plugins/AccountsService/AccountsService.h 2016-01-21 21:04:00 +0000
91+++ plugins/AccountsService/AccountsService.h 2016-03-10 17:24:40 +0000
92@@ -21,6 +21,7 @@
93
94 #include <QObject>
95 #include <QString>
96+#include <QStringList>
97
98 class AccountsServiceDBusAdaptor;
99 class QDBusInterface;
100@@ -37,6 +38,9 @@
101 READ demoEdges
102 WRITE setDemoEdges
103 NOTIFY demoEdgesChanged)
104+ Q_PROPERTY (QStringList demoEdgesCompleted
105+ READ demoEdgesCompleted
106+ NOTIFY demoEdgesCompletedChanged)
107 Q_PROPERTY (bool enableLauncherWhileLocked
108 READ enableLauncherWhileLocked
109 NOTIFY enableLauncherWhileLockedChanged)
110@@ -80,6 +84,8 @@
111 void setUser(const QString &user);
112 bool demoEdges() const;
113 void setDemoEdges(bool demoEdges);
114+ QStringList demoEdgesCompleted() const;
115+ Q_INVOKABLE void markDemoEdgeCompleted(const QString &edge);
116 bool enableLauncherWhileLocked() const;
117 bool enableIndicatorsWhileLocked() const;
118 QString backgroundFile() const;
119@@ -95,6 +101,7 @@
120 Q_SIGNALS:
121 void userChanged();
122 void demoEdgesChanged();
123+ void demoEdgesCompletedChanged();
124 void enableLauncherWhileLockedChanged();
125 void enableIndicatorsWhileLockedChanged();
126 void backgroundFileChanged();
127@@ -110,6 +117,7 @@
128
129 private:
130 void updateDemoEdges(bool async = true);
131+ void updateDemoEdgesCompleted(bool async = true);
132 void updateEnableLauncherWhileLocked(bool async = true);
133 void updateEnableIndicatorsWhileLocked(bool async = true);
134 void updateBackgroundFile(bool async = true);
135@@ -125,6 +133,7 @@
136 QDBusInterface *m_unityInput;
137 QString m_user;
138 bool m_demoEdges;
139+ QStringList m_demoEdgesCompleted;
140 bool m_enableLauncherWhileLocked;
141 bool m_enableIndicatorsWhileLocked;
142 QString m_backgroundFile;
143
144=== modified file 'plugins/AccountsService/AccountsService.qmltypes'
145--- plugins/AccountsService/AccountsService.qmltypes 2015-02-13 09:01:16 +0000
146+++ plugins/AccountsService/AccountsService.qmltypes 2016-03-10 17:24:40 +0000
147@@ -23,6 +23,7 @@
148 }
149 Property { name: "user"; type: "string" }
150 Property { name: "demoEdges"; type: "bool" }
151+ Property { name: "demoEdgesCompleted"; type: "QStringList"; isReadonly: true }
152 Property { name: "enableLauncherWhileLocked"; type: "bool"; isReadonly: true }
153 Property { name: "enableIndicatorsWhileLocked"; type: "bool"; isReadonly: true }
154 Property { name: "backgroundFile"; type: "string"; isReadonly: true }
155@@ -32,5 +33,9 @@
156 Property { name: "hereEnabled"; type: "bool" }
157 Property { name: "hereLicensePath"; type: "string"; isReadonly: true }
158 Property { name: "hereLicensePathValid"; type: "bool"; isReadonly: true }
159+ Method {
160+ name: "markDemoEdgeCompleted"
161+ Parameter { name: "edge"; type: "string" }
162+ }
163 }
164 }
165
166=== modified file 'plugins/AccountsService/com.canonical.unity.AccountsService.xml'
167--- plugins/AccountsService/com.canonical.unity.AccountsService.xml 2015-02-04 15:12:36 +0000
168+++ plugins/AccountsService/com.canonical.unity.AccountsService.xml 2016-03-10 17:24:40 +0000
169@@ -14,6 +14,11 @@
170 <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
171 </property>
172
173+ <!-- List of tutorial pages that have been completed by the user -->
174+ <property name="DemoEdgesCompleted" type="as" access="readwrite">
175+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="[]"/>
176+ </property>
177+
178 <property name="LauncherItems" type="aa{sv}" access="readwrite">
179 <annotation name="org.freedesktop.Accounts.DefaultValue" value="[{'defaults': <true>}]"/>
180 </property>
181
182=== modified file 'plugins/ScreenGrabber/screengrabber.cpp'
183--- plugins/ScreenGrabber/screengrabber.cpp 2015-11-18 18:38:36 +0000
184+++ plugins/ScreenGrabber/screengrabber.cpp 2016-03-10 17:24:40 +0000
185@@ -46,12 +46,10 @@
186
187 QDir screenshotsDir;
188 if (qEnvironmentVariableIsSet("UNITY_TESTING")) {
189- qDebug() << "Using test environment";
190 QTemporaryDir tDir;
191 tDir.setAutoRemove(false);
192 screenshotsDir = tDir.path();
193 } else {
194- qDebug() << "Using real environment";
195 screenshotsDir = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
196 }
197 screenshotsDir.mkpath(QStringLiteral("Screenshots"));
198
199=== modified file 'plugins/Ubuntu/Gestures/DirectionalDragArea.cpp'
200--- plugins/Ubuntu/Gestures/DirectionalDragArea.cpp 2015-12-16 18:28:21 +0000
201+++ plugins/Ubuntu/Gestures/DirectionalDragArea.cpp 2016-03-10 17:24:40 +0000
202@@ -194,6 +194,26 @@
203 }
204 }
205
206+bool DirectionalDragArea::monitorOnly() const
207+{
208+ return d->monitorOnly;
209+}
210+
211+void DirectionalDragArea::setMonitorOnly(bool monitorOnly)
212+{
213+ if (d->monitorOnly != monitorOnly) {
214+ d->monitorOnly = monitorOnly;
215+
216+ if (monitorOnly && d->status == DirectionalDragAreaPrivate::Undecided) {
217+ TouchRegistry::instance()->removeCandidateOwnerForTouch(d->touchId, this);
218+ // We still wanna know when it ends for keeping the composition time window up-to-date
219+ TouchRegistry::instance()->addTouchWatcher(d->touchId, this);
220+ }
221+
222+ Q_EMIT monitorOnlyChanged(monitorOnly);
223+ }
224+}
225+
226 void DirectionalDragArea::removeTimeConstraints()
227 {
228 d->setMaxTime(60 * 60 * 1000);
229@@ -260,7 +280,10 @@
230 unownedTouchEvent_undecided(unownedTouchEvent);
231 break;
232 default: // Recognized:
233- // do nothing
234+ if (monitorOnly) {
235+ // Treat unowned event as if we owned it, but we are really just watching it
236+ touchEvent_recognized(event);
237+ }
238 break;
239 }
240
241@@ -311,7 +334,9 @@
242 }
243
244 if (movedFarEnoughAlongGestureAxis()) {
245- TouchRegistry::instance()->requestTouchOwnership(touchId, q);
246+ if (!monitorOnly) {
247+ TouchRegistry::instance()->requestTouchOwnership(touchId, q);
248+ }
249 setStatus(Recognized);
250 setPublicPos(touchPoint->pos());
251 setPublicScenePos(touchScenePos);
252@@ -411,12 +436,21 @@
253 if (recognitionIsDisabled()) {
254 // Behave like a dumb TouchArea
255 ddaDebug("Gesture recognition is disabled. Requesting touch ownership immediately.");
256- TouchRegistry::instance()->requestTouchOwnership(touchId, q);
257 setStatus(Recognized);
258- event->accept();
259+ if (monitorOnly) {
260+ watchPressedTouchPoints(touchPoints);
261+ event->ignore();
262+ } else {
263+ TouchRegistry::instance()->requestTouchOwnership(touchId, q);
264+ event->accept();
265+ }
266 } else {
267 // just monitor the touch points for now.
268- TouchRegistry::instance()->addCandidateOwnerForTouch(touchId, q);
269+ if (monitorOnly) {
270+ watchPressedTouchPoints(touchPoints);
271+ } else {
272+ TouchRegistry::instance()->addCandidateOwnerForTouch(touchId, q);
273+ }
274
275 setStatus(Undecided);
276 // Let the item below have it. We will monitor it and grab it later if a gesture
277@@ -890,5 +924,6 @@
278 , recognitionTimer(nullptr)
279 , timeSource(new RealTimeSource)
280 , activeTouches(timeSource)
281+ , monitorOnly(false)
282 {
283 }
284
285=== modified file 'plugins/Ubuntu/Gestures/DirectionalDragArea.h'
286--- plugins/Ubuntu/Gestures/DirectionalDragArea.h 2015-05-11 07:49:36 +0000
287+++ plugins/Ubuntu/Gestures/DirectionalDragArea.h 2016-03-10 17:24:40 +0000
288@@ -77,6 +77,10 @@
289 WRITE setImmediateRecognition
290 NOTIFY immediateRecognitionChanged)
291
292+ // Whether we are merely monitoring touch events (in which case, we don't
293+ // claim ownership of the touch).
294+ Q_PROPERTY(bool monitorOnly READ monitorOnly WRITE setMonitorOnly NOTIFY monitorOnlyChanged)
295+
296 Q_ENUMS(Direction)
297 public:
298 DirectionalDragArea(QQuickItem *parent = 0);
299@@ -100,6 +104,9 @@
300 bool immediateRecognition() const;
301 void setImmediateRecognition(bool enabled);
302
303+ bool monitorOnly() const;
304+ void setMonitorOnly(bool monitorOnly);
305+
306 bool event(QEvent *e) override;
307
308 /*
309@@ -123,6 +130,7 @@
310 void touchSceneXChanged(qreal value);
311 void touchSceneYChanged(qreal value);
312 void immediateRecognitionChanged(bool value);
313+ void monitorOnlyChanged(bool value);
314
315 protected:
316 void touchEvent(QTouchEvent *event) override;
317
318=== modified file 'plugins/Ubuntu/Gestures/DirectionalDragArea_p.h'
319--- plugins/Ubuntu/Gestures/DirectionalDragArea_p.h 2015-11-20 15:01:39 +0000
320+++ plugins/Ubuntu/Gestures/DirectionalDragArea_p.h 2016-03-10 17:24:40 +0000
321@@ -160,6 +160,8 @@
322
323 ActiveTouchesInfo activeTouches;
324
325+ bool monitorOnly;
326+
327 Q_SIGNALS:
328 void statusChanged(Status value);
329 };
330
331=== modified file 'plugins/Utils/CMakeLists.txt'
332--- plugins/Utils/CMakeLists.txt 2016-02-08 09:37:48 +0000
333+++ plugins/Utils/CMakeLists.txt 2016-03-10 17:24:40 +0000
334@@ -17,7 +17,7 @@
335 unitysortfilterproxymodelqml.cpp
336 Timer.cpp
337 unitymenumodelpaths.cpp
338- windowkeysfilter.cpp
339+ windowinputfilter.cpp
340 windowscreenshotprovider.cpp
341 easingcurve.cpp
342 windowstatestorage.cpp
343
344=== modified file 'plugins/Utils/Utils.qmltypes'
345--- plugins/Utils/Utils.qmltypes 2015-09-03 11:08:46 +0000
346+++ plugins/Utils/Utils.qmltypes 2016-03-10 17:24:40 +0000
347@@ -147,10 +147,10 @@
348 }
349 }
350 Component {
351- name: "WindowKeysFilter"
352+ name: "WindowInputFilter"
353 defaultProperty: "data"
354 prototype: "QQuickItem"
355- exports: ["Utils/WindowKeysFilter 0.1"]
356+ exports: ["Utils/WindowInputFilter 0.1"]
357 exportMetaObjectRevisions: [0]
358 }
359 Component {
360
361=== modified file 'plugins/Utils/plugin.cpp'
362--- plugins/Utils/plugin.cpp 2016-01-29 11:52:14 +0000
363+++ plugins/Utils/plugin.cpp 2016-03-10 17:24:40 +0000
364@@ -30,7 +30,7 @@
365 #include "qlimitproxymodelqml.h"
366 #include "unitysortfilterproxymodelqml.h"
367 #include "unitymenumodelpaths.h"
368-#include "windowkeysfilter.h"
369+#include "windowinputfilter.h"
370 #include "windowscreenshotprovider.h"
371 #include "windowstatestorage.h"
372 #include "constants.h"
373@@ -60,7 +60,7 @@
374 qmlRegisterType<QLimitProxyModelQML>(uri, 0, 1, "LimitProxyModel");
375 qmlRegisterType<UnitySortFilterProxyModelQML>(uri, 0, 1, "UnitySortFilterProxyModel");
376 qmlRegisterType<UnityMenuModelPaths>(uri, 0, 1, "UnityMenuModelPaths");
377- qmlRegisterType<WindowKeysFilter>(uri, 0, 1, "WindowKeysFilter");
378+ qmlRegisterType<WindowInputFilter>(uri, 0, 1, "WindowInputFilter");
379 qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
380 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
381 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
382
383=== renamed file 'plugins/Utils/windowkeysfilter.cpp' => 'plugins/Utils/windowinputfilter.cpp'
384--- plugins/Utils/windowkeysfilter.cpp 2015-10-22 17:37:26 +0000
385+++ plugins/Utils/windowinputfilter.cpp 2016-03-10 17:24:40 +0000
386@@ -16,36 +16,34 @@
387 * Author: Daniel d'Andrada <daniel.dandrada@canonical.com>
388 */
389
390-#include "windowkeysfilter.h"
391+#include "windowinputfilter.h"
392
393 #include <QQuickWindow>
394
395-WindowKeysFilter::WindowKeysFilter(QQuickItem *parent)
396+WindowInputFilter::WindowInputFilter(QQuickItem *parent)
397 : QQuickItem(parent),
398- m_currentEventTimestamp(0)
399+ m_lastInputTimestamp(0)
400 {
401 connect(this, &QQuickItem::windowChanged,
402- this, &WindowKeysFilter::setupFilterOnWindow);
403+ this, &WindowInputFilter::setupFilterOnWindow);
404 }
405
406-bool WindowKeysFilter::eventFilter(QObject *watched, QEvent *event)
407+bool WindowInputFilter::eventFilter(QObject *watched, QEvent *event)
408 {
409 Q_ASSERT(!m_filteredWindow.isNull());
410 Q_ASSERT(watched == static_cast<QObject*>(m_filteredWindow.data()));
411 Q_UNUSED(watched);
412
413+ QInputEvent *inputEvent = dynamic_cast<QInputEvent*>(event);
414+ if (inputEvent) {
415+ m_lastInputTimestamp = inputEvent->timestamp();
416+ Q_EMIT lastInputTimestampChanged();
417+ }
418+
419 if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
420 // Let QML see this event and decide if it does not want it
421 event->accept();
422-
423- m_currentEventTimestamp = static_cast<QInputEvent*>(event)->timestamp();
424- Q_EMIT currentEventTimestampChanged();
425-
426 QCoreApplication::sendEvent(this, event);
427-
428- m_currentEventTimestamp = 0;
429- Q_EMIT currentEventTimestampChanged();
430-
431 return event->isAccepted();
432 } else {
433 // Not interested
434@@ -53,7 +51,7 @@
435 }
436 }
437
438-void WindowKeysFilter::setupFilterOnWindow(QQuickWindow *window)
439+void WindowInputFilter::setupFilterOnWindow(QQuickWindow *window)
440 {
441 if (!m_filteredWindow.isNull()) {
442 m_filteredWindow->removeEventFilter(this);
443@@ -66,7 +64,7 @@
444 }
445 }
446
447-ulong WindowKeysFilter::currentEventTimestamp() const
448+ulong WindowInputFilter::lastInputTimestamp() const
449 {
450- return m_currentEventTimestamp;
451+ return m_lastInputTimestamp;
452 }
453
454=== renamed file 'plugins/Utils/windowkeysfilter.h' => 'plugins/Utils/windowinputfilter.h'
455--- plugins/Utils/windowkeysfilter.h 2015-10-22 17:37:26 +0000
456+++ plugins/Utils/windowinputfilter.h 2016-03-10 17:24:40 +0000
457@@ -16,8 +16,8 @@
458 * Author: Daniel d'Andrada <daniel.dandrada@canonical.com>
459 */
460
461-#ifndef UNITY_WINDOWKEYSFILTER_H
462-#define UNITY_WINDOWKEYSFILTER_H
463+#ifndef UNITY_WINDOWINPUTFILTER_H
464+#define UNITY_WINDOWINPUTFILTER_H
465
466 #include <QQuickItem>
467 #include <QPointer>
468@@ -29,30 +29,30 @@
469 accepted ones will be filtered out. Events are accepted by default, so make sure you reject
470 the keys you're not interested in.
471
472- If more than one WindowKeysFilter exist in the same QML scene (and thus in the same QQuickWindow)
473+ If more than one WindowInputFilter exist in the same QML scene (and thus in the same QQuickWindow)
474 they will be called in the order of creation, which can be tricky to assess. So the best practice
475- is to have at most one WindowKeysFilter per QML scene.
476+ is to have at most one WindowInputFilter per QML scene.
477 */
478-class WindowKeysFilter : public QQuickItem
479+class WindowInputFilter : public QQuickItem
480 {
481 Q_OBJECT
482- Q_PROPERTY(ulong currentEventTimestamp READ currentEventTimestamp NOTIFY currentEventTimestampChanged)
483+ Q_PROPERTY(ulong lastInputTimestamp READ lastInputTimestamp NOTIFY lastInputTimestampChanged)
484 public:
485- WindowKeysFilter(QQuickItem *parent = 0);
486+ WindowInputFilter(QQuickItem *parent = 0);
487
488 bool eventFilter(QObject *watched, QEvent *event) override;
489
490- ulong currentEventTimestamp() const;
491+ ulong lastInputTimestamp() const;
492
493 Q_SIGNALS:
494- void currentEventTimestampChanged();
495+ void lastInputTimestampChanged();
496
497 private Q_SLOTS:
498 void setupFilterOnWindow(QQuickWindow *window);
499
500 private:
501 QPointer<QQuickWindow> m_filteredWindow;
502- ulong m_currentEventTimestamp;
503+ ulong m_lastInputTimestamp;
504 };
505
506-#endif // UNITY_WINDOWKEYSFILTER_H
507+#endif // UNITY_WINDOWINPUTFILTER_H
508
509=== modified file 'qml/Components/InputMethod.qml'
510--- qml/Components/InputMethod.qml 2015-12-02 10:34:31 +0000
511+++ qml/Components/InputMethod.qml 2016-03-10 17:24:40 +0000
512@@ -22,15 +22,6 @@
513 Item {
514 id: root
515
516- Connections {
517- target: SurfaceManager
518- onSurfaceCreated: {
519- if (surface.type == Mir.InputMethodType) {
520- surfaceItem.surface = surface;
521- }
522- }
523- }
524-
525 property int transitionDuration: UbuntuAnimation.FastDuration
526
527 MirSurfaceItem {
528@@ -41,6 +32,7 @@
529
530 surfaceWidth: width
531 surfaceHeight: height
532+ surface: SurfaceManager.inputMethodSurface
533
534 onLiveChanged: {
535 if (surface !== null && !live) {
536
537=== modified file 'qml/Greeter/Greeter.qml'
538--- qml/Greeter/Greeter.qml 2016-01-11 17:37:02 +0000
539+++ qml/Greeter/Greeter.qml 2016-03-10 17:24:40 +0000
540@@ -160,6 +160,14 @@
541 return false;
542 }
543 }
544+
545+ function checkForcedUnlock() {
546+ if (forcedUnlock && shown && loader.item) {
547+ // pretend we were just authenticated
548+ loader.item.notifyAuthenticationSucceeded();
549+ loader.item.hide();
550+ }
551+ }
552 }
553
554 onLauncherOffsetChanged: {
555@@ -168,12 +176,8 @@
556 }
557 }
558
559- onForcedUnlockChanged: {
560- if (forcedUnlock && shown) {
561- // pretend we were just authenticated
562- loader.item.notifyAuthenticationSucceeded();
563- }
564- }
565+ onForcedUnlockChanged: d.checkForcedUnlock()
566+ Component.onCompleted: d.checkForcedUnlock()
567
568 onRequiredChanged: {
569 if (required) {
570
571=== modified file 'qml/Launcher/Launcher.qml'
572--- qml/Launcher/Launcher.qml 2016-01-19 15:26:15 +0000
573+++ qml/Launcher/Launcher.qml 2016-03-10 17:24:40 +0000
574@@ -26,7 +26,6 @@
575 property bool autohideEnabled: false
576 property bool available: true // can be used to disable all interactions
577 property alias inverted: panel.inverted
578- property bool shadeBackground: true // can be used to disable background shade when launcher is visible
579
580 property int panelWidth: units.gu(8)
581 property int dragAreaWidth: units.gu(1)
582@@ -172,7 +171,7 @@
583 InverseMouseArea {
584 id: closeMouseArea
585 anchors.fill: panel
586- enabled: root.shadeBackground && root.state == "visible"
587+ enabled: root.state == "visible"
588 visible: enabled
589 onPressed: {
590 root.hide();
591@@ -183,7 +182,7 @@
592 id: backgroundShade
593 anchors.fill: parent
594 color: "black"
595- opacity: root.shadeBackground && root.state == "visible" ? 0.6 : 0
596+ opacity: root.state == "visible" ? 0.6 : 0
597
598 Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.BriskDuration } }
599 }
600
601=== modified file 'qml/Panel/IndicatorsMenu.qml'
602--- qml/Panel/IndicatorsMenu.qml 2016-03-08 20:59:14 +0000
603+++ qml/Panel/IndicatorsMenu.qml 2016-03-10 17:24:40 +0000
604@@ -36,7 +36,6 @@
605 readonly property bool partiallyOpened: unitProgress > 0 && unitProgress < 1.0
606 readonly property bool fullyClosed: unitProgress == 0
607 property bool enableHint: true
608- property bool contentEnabled: true
609 property bool showOnClick: true
610 property color panelColor: theme.palette.normal.background
611
612@@ -86,7 +85,6 @@
613 height: openedHeight - bar.height - handle.height
614 indicatorsModel: root.indicatorsModel
615 visible: root.unitProgress > 0
616- enabled: contentEnabled
617 currentMenuIndex: bar.currentItemIndex
618 }
619
620
621=== modified file 'qml/Shell.qml'
622--- qml/Shell.qml 2016-03-08 20:59:08 +0000
623+++ qml/Shell.qml 2016-03-10 17:24:40 +0000
624@@ -24,7 +24,7 @@
625 import Ubuntu.Telephony 0.1 as Telephony
626 import Unity.Connectivity 0.1
627 import Unity.Launcher 0.1
628-import GlobalShortcut 1.0 // has to be before Utils, because of WindowKeysFilter
629+import GlobalShortcut 1.0 // has to be before Utils, because of WindowInputFilter
630 import Utils 0.1
631 import Powerd 0.1
632 import SessionBroadcast 0.1
633@@ -168,12 +168,13 @@
634 }
635
636 GlobalShortcut {
637- // dummy shortcut to force creation of GlobalShortcutRegistry before WindowKeyFilter
638+ // dummy shortcut to force creation of GlobalShortcutRegistry before WindowInputFilter
639 }
640
641- WindowKeysFilter {
642- Keys.onPressed: physicalKeysMapper.onKeyPressed(event, currentEventTimestamp);
643- Keys.onReleased: physicalKeysMapper.onKeyReleased(event, currentEventTimestamp);
644+ WindowInputFilter {
645+ id: inputFilter
646+ Keys.onPressed: physicalKeysMapper.onKeyPressed(event, lastInputTimestamp);
647+ Keys.onReleased: physicalKeysMapper.onKeyReleased(event, lastInputTimestamp);
648 }
649
650 WindowInputMonitor {
651@@ -201,7 +202,7 @@
652 onFocusedApplicationIdChanged: {
653 var appId = ApplicationManager.focusedApplicationId;
654
655- if (tutorial.running && appId != "" && appId != "unity8-dash") {
656+ if (wizard.active && appId != "" && appId != "unity8-dash") {
657 // If this happens on first boot, we may be in edge
658 // tutorial or wizard while receiving a call. But a call
659 // is more important than wizard so just bail out of those.
660@@ -254,8 +255,7 @@
661 }
662 }
663
664- property bool interactive: tutorial.spreadEnabled
665- && (!greeter || !greeter.shown)
666+ property bool interactive: (!greeter || !greeter.shown)
667 && panel.indicators.fullyClosed
668 && launcher.progress == 0
669 && !notifications.useModal
670@@ -344,37 +344,13 @@
671 value: physicalKeysMapper.altTabPressed
672 }
673 }
674-
675- Tutorial {
676- id: tutorial
677- objectName: "tutorial"
678- anchors.fill: parent
679-
680- // EdgeDragAreas don't work with mice. So to avoid trapping the user,
681- // we skip the tutorial on the Desktop to avoid using them. The
682- // Desktop doesn't use the same spread design anyway. The tutorial is
683- // all a bit of a placeholder on non-phone form factors right now.
684- // When the design team gives us more guidance, we can do something
685- // more clever here.
686- active: usageScenario != "desktop" && AccountsService.demoEdges
687-
688- paused: lightDM.greeter.active
689- launcher: launcher
690- panel: panel
691- edgeSize: shell.edgeSize
692-
693- onFinished: {
694- AccountsService.demoEdges = false;
695- active = false; // for immediate response / if AS is having problems
696- }
697- }
698 }
699
700 InputMethod {
701 id: inputMethod
702 objectName: "inputMethod"
703 anchors { fill: parent; topMargin: panel.panelHeight }
704- z: notifications.useModal || panel.indicators.shown || wizard.active ? overlay.z + 1 : overlay.z - 1
705+ z: notifications.useModal || panel.indicators.shown || wizard.active || tutorial.running ? overlay.z + 1 : overlay.z - 1
706 }
707
708 Connections {
709@@ -405,7 +381,7 @@
710 hides: [launcher, panel.indicators]
711 tabletMode: shell.usageScenario != "phone"
712 launcherOffset: launcher.progress
713- forcedUnlock: tutorial.running
714+ forcedUnlock: wizard.active
715 background: wallpaperResolver.background
716
717 // avoid overlapping with Launcher's edge drag area
718@@ -462,7 +438,7 @@
719
720 onStatusChanged: {
721 if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity &&
722- !callManager.hasCalls && !tutorial.running) {
723+ !callManager.hasCalls && !wizard.active) {
724 // We don't want to simply call greeter.showNow() here, because
725 // that will take too long. Qt will delay button event
726 // handling until the greeter is done loading and may think the
727@@ -478,10 +454,6 @@
728 }
729
730 function showHome() {
731- if (tutorial.running) {
732- return
733- }
734-
735 greeter.notifyAboutToFocusApp("unity8-dash");
736
737 var animate = !lightDM.greeter.active && !stages.shown
738@@ -515,7 +487,6 @@
739 available: tutorial.panelEnabled
740 && ((!greeter || !greeter.locked) || AccountsService.enableIndicatorsWhileLocked)
741 && (!greeter || !greeter.hasLockedApp)
742- contentEnabled: tutorial.panelContentEnabled
743 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
744
745 minimizedPanelHeight: units.gu(3)
746@@ -556,7 +527,6 @@
747 && (!greeter.locked || AccountsService.enableLauncherWhileLocked)
748 && !greeter.hasLockedApp
749 inverted: shell.usageScenario !== "desktop"
750- shadeBackground: !tutorial.running
751
752 onShowDashHome: showHome()
753 onDash: showDash()
754@@ -566,10 +536,8 @@
755 }
756 }
757 onLauncherApplicationSelected: {
758- if (!tutorial.running) {
759- greeter.notifyAboutToFocusApp(appId);
760- shell.activateApplication(appId)
761- }
762+ greeter.notifyAboutToFocusApp(appId);
763+ shell.activateApplication(appId);
764 }
765 onShownChanged: {
766 if (shown) {
767@@ -578,6 +546,20 @@
768 }
769 }
770
771+ Tutorial {
772+ id: tutorial
773+ objectName: "tutorial"
774+ anchors.fill: parent
775+
776+ paused: callManager.hasCalls || greeter.shown
777+ keyboardVisible: inputMethod.state === "shown"
778+ usageScenario: shell.usageScenario
779+ lastInputTimestamp: inputFilter.lastInputTimestamp
780+ launcher: launcher
781+ panel: panel
782+ stage: applicationsDisplayLoader.item
783+ }
784+
785 Wizard {
786 id: wizard
787 objectName: "wizard"
788
789=== modified file 'qml/Stages/AbstractStage.qml'
790--- qml/Stages/AbstractStage.qml 2016-01-14 13:03:20 +0000
791+++ qml/Stages/AbstractStage.qml 2016-03-10 17:24:40 +0000
792@@ -28,6 +28,7 @@
793 property url background
794 property bool beingResized
795 property int dragAreaWidth
796+ property real dragProgress // How far left the stage has been dragged, used externally by tutorial code
797 property bool interactive
798 property real inverseProgress // This is the progress for left edge drags, in pixels.
799 property bool keepDashRunning: true
800
801=== modified file 'qml/Stages/ApplicationWindow.qml'
802--- qml/Stages/ApplicationWindow.qml 2016-02-12 00:10:54 +0000
803+++ qml/Stages/ApplicationWindow.qml 2016-03-10 17:24:40 +0000
804@@ -58,7 +58,6 @@
805 readonly property color splashColor: root.application ? root.application.splashColor : "#00000000"
806 readonly property color splashColorHeader: root.application ? root.application.splashColorHeader : "#00000000"
807 readonly property color splashColorFooter: root.application ? root.application.splashColorFooter : "#00000000"
808- readonly property url defaultScreenshot: (root.application && root.application.defaultScreenshot !== undefined) ? root.application.defaultScreenshot : ""
809
810 // Whether the Application had a surface before but lost it.
811 property bool hadSurface: sessionContainer.surfaceContainer.hadSurface
812@@ -110,7 +109,6 @@
813 Image {
814 id: screenshotImage
815 objectName: "screenshotImage"
816- source: d.defaultScreenshot
817 anchors.fill: parent
818 antialiasing: !root.interactive
819
820
821=== modified file 'qml/Stages/PhoneStage.qml'
822--- qml/Stages/PhoneStage.qml 2016-01-14 13:03:20 +0000
823+++ qml/Stages/PhoneStage.qml 2016-03-10 17:24:40 +0000
824@@ -87,14 +87,11 @@
825 : (Qt.PortraitOrientation | Qt.LandscapeOrientation
826 | Qt.InvertedPortraitOrientation | Qt.InvertedLandscapeOrientation)
827
828- // How far left the stage has been dragged
829- readonly property real dragProgress: spreadRepeater.count > 0 ? -spreadRepeater.itemAt(0).xTranslate : 0
830+ // How far left the stage has been dragged, used externally by tutorial code
831+ dragProgress: spreadRepeater.count > 0 ? spreadRepeater.itemAt(0).animatedProgress : 0
832
833 readonly property alias dragging: spreadDragArea.dragging
834
835- // Only used by the tutorial right now, when it is teasing the right edge
836- property real dragAreaOverlap
837-
838 signal opened()
839
840 function select(appId) {
841@@ -598,7 +595,7 @@
842 direction: Direction.Leftwards
843 enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging
844
845- anchors { top: parent.top; right: parent.right; bottom: parent.bottom; rightMargin: -root.dragAreaOverlap }
846+ anchors { top: parent.top; right: parent.right; bottom: parent.bottom; }
847 width: root.dragAreaWidth
848
849 property var gesturePoints: new Array()
850
851=== modified file 'qml/Stages/TabletStage.qml'
852--- qml/Stages/TabletStage.qml 2016-01-14 13:03:20 +0000
853+++ qml/Stages/TabletStage.qml 2016-03-10 17:24:40 +0000
854@@ -27,6 +27,9 @@
855 objectName: "stages"
856 anchors.fill: parent
857
858+ property bool sideStageVisible: priv.sideStageAppId
859+ property real sideStageWidth: units.gu(40)
860+
861 // Functions to be called from outside
862 function updateFocusedAppOrientation() {
863 var mainStageAppIndex = priv.indexOf(priv.mainStageAppId);
864@@ -76,6 +79,9 @@
865 : (Qt.PortraitOrientation | Qt.LandscapeOrientation
866 | Qt.InvertedPortraitOrientation | Qt.InvertedLandscapeOrientation)
867
868+ // How far left the stage has been dragged, used externally by tutorial code
869+ dragProgress: spreadRepeater.count > 0 ? spreadRepeater.itemAt(0).animatedProgress : 0
870+
871 onWidthChanged: {
872 spreadView.selectedIndex = -1;
873 spreadView.phase = 0;
874@@ -237,8 +243,6 @@
875 contentX: -shift
876
877 property int tileDistance: units.gu(20)
878- property int sideStageWidth: units.gu(40)
879- property bool sideStageVisible: priv.sideStageAppId
880
881 // This indicates when the spreadView is active. That means, all the animations
882 // are activated and tiles need to line up for the spread.
883@@ -258,14 +262,14 @@
884 // 2: The list is dragged further and snaps into the spread view when entering phase 2
885 property int phase
886
887- readonly property int phase0Width: sideStageWidth
888- readonly property int phase1Width: sideStageWidth
889+ readonly property int phase0Width: root.sideStageWidth
890+ readonly property int phase1Width: root.sideStageWidth
891
892 // Those markers mark the various positions in the spread (ratio to screen width from right to left):
893 // 0 - 1: following finger, snap back to the beginning on release
894 readonly property real positionMarker1: 0.2
895 // 1 - 2: curved snapping movement, snap to nextInStack on release
896- readonly property real positionMarker2: sideStageWidth / spreadView.width
897+ readonly property real positionMarker2: root.sideStageWidth / spreadView.width
898 // 2 - 3: movement follows finger, snaps to phase 2 (full spread) on release
899 readonly property real positionMarker3: 0.6
900 // passing 3, we detach movement from the finger and snap to phase 2 (full spread)
901@@ -494,7 +498,7 @@
902 Rectangle {
903 id: sideStageBackground
904 color: "black"
905- width: spreadView.sideStageWidth * (1 - sideStageDragHandle.progress)
906+ width: root.sideStageWidth * (1 - sideStageDragHandle.progress)
907 height: priv.landscapeHeight
908 x: spreadView.width - width
909 z: spreadView.indexToZIndex(priv.indexOf(priv.sideStageAppId))
910@@ -509,16 +513,16 @@
911 width: units.gu(2)
912 height: priv.landscapeHeight
913 z: sideStageBackground.z
914- opacity: spreadView.phase <= 0 && spreadView.sideStageVisible ? 1 : 0
915+ opacity: spreadView.phase <= 0 && root.sideStageVisible ? 1 : 0
916 property real progress: 0
917 property bool dragging: false
918
919 Behavior on opacity { UbuntuNumberAnimation {} }
920
921 Connections {
922- target: spreadView
923+ target: root
924 onSideStageVisibleChanged: {
925- if (spreadView.sideStageVisible) {
926+ if (root.sideStageVisible) {
927 sideStageDragHandle.progress = 0;
928 }
929 }
930@@ -550,7 +554,7 @@
931 onMouseXChanged: {
932 totalDiff += mouseX - startX;
933 if (priv.mainStageAppId) {
934- sideStageDragHandle.progress = Math.max(0, totalDiff / spreadView.sideStageWidth);
935+ sideStageDragHandle.progress = Math.max(0, totalDiff / root.sideStageWidth);
936 }
937 gesturePoints.push(mouseX);
938 }
939@@ -590,7 +594,7 @@
940 if (wantsMainStage) {
941 return spreadView.width;
942 } else {
943- return spreadView.sideStageWidth;
944+ return root.sideStageWidth;
945 }
946 }
947 height: {
948
949=== removed file 'qml/Tutorial/Arrow.qml'
950--- qml/Tutorial/Arrow.qml 2015-07-15 15:07:19 +0000
951+++ qml/Tutorial/Arrow.qml 1970-01-01 00:00:00 +0000
952@@ -1,56 +0,0 @@
953-/*
954- * Copyright (C) 2014 Canonical, Ltd.
955- *
956- * This program is free software; you can redistribute it and/or modify
957- * it under the terms of the GNU General Public License as published by
958- * the Free Software Foundation; version 3.
959- *
960- * This program is distributed in the hope that it will be useful,
961- * but WITHOUT ANY WARRANTY; without even the implied warranty of
962- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
963- * GNU General Public License for more details.
964- *
965- * You should have received a copy of the GNU General Public License
966- * along with this program. If not, see <http://www.gnu.org/licenses/>.
967- */
968-
969-import QtQuick 2.4
970-import Ubuntu.Components 1.3
971-
972-Item {
973- id: root
974-
975- property alias color: circle.color
976-
977- // Will make whole arrow darker
978- property real darkenBy: 0
979-
980- property alias chevronOpacity: chevron.opacity
981-
982- ////
983-
984- Rectangle {
985- id: circle
986- anchors.fill: parent
987- radius: width / 2
988- }
989-
990- Image {
991- id: chevron
992- anchors.centerIn: parent
993- source: Qt.resolvedUrl("graphics/chevron.png")
994- fillMode: Image.PreserveAspectFit
995- sourceSize.width: 152
996- sourceSize.height: 152
997- width: parent.width / 2
998- height: parent.height / 2
999- }
1000-
1001- Rectangle {
1002- id: darkCircle
1003- anchors.fill: parent
1004- radius: width / 2
1005- color: "black"
1006- opacity: root.darkenBy
1007- }
1008-}
1009
1010=== added file 'qml/Tutorial/InactivityTimer.qml'
1011--- qml/Tutorial/InactivityTimer.qml 1970-01-01 00:00:00 +0000
1012+++ qml/Tutorial/InactivityTimer.qml 2016-03-10 17:24:40 +0000
1013@@ -0,0 +1,62 @@
1014+/*
1015+ * Copyright (C) 2015 Canonical, Ltd.
1016+ *
1017+ * This program is free software; you can redistribute it and/or modify
1018+ * it under the terms of the GNU General Public License as published by
1019+ * the Free Software Foundation; version 3.
1020+ *
1021+ * This program is distributed in the hope that it will be useful,
1022+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1023+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1024+ * GNU General Public License for more details.
1025+ *
1026+ * You should have received a copy of the GNU General Public License
1027+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1028+ */
1029+
1030+import QtQuick 2.4
1031+import Ubuntu.Components 1.3
1032+
1033+Item {
1034+ readonly property alias running: internalTimer.running
1035+ property alias interval: internalTimer.interval
1036+ property var page
1037+ property int lastInputTimestamp
1038+
1039+ function start() {
1040+ internalTimer.start();
1041+ }
1042+
1043+ ////
1044+
1045+ onLastInputTimestampChanged: {
1046+ if (internalTimer.running) {
1047+ internalTimer.restart();
1048+ }
1049+ }
1050+
1051+ Connections {
1052+ target: page
1053+ onIsReadyChanged: {
1054+ if (page.isReady && internalTimer.running) {
1055+ internalTimer.restart();
1056+ }
1057+ }
1058+ }
1059+
1060+ Timer {
1061+ id: internalTimer
1062+
1063+ interval: 3000
1064+
1065+ onTriggered: {
1066+ if (page.isReady) {
1067+ if (!page.shown) {
1068+ page.show();
1069+ }
1070+ } else if (!page.skipped) {
1071+ restart();
1072+ }
1073+ }
1074+ }
1075+}
1076
1077=== removed file 'qml/Tutorial/Slider.qml'
1078--- qml/Tutorial/Slider.qml 2015-07-15 15:07:19 +0000
1079+++ qml/Tutorial/Slider.qml 1970-01-01 00:00:00 +0000
1080@@ -1,123 +0,0 @@
1081-/*
1082- * Copyright (C) 2014 Canonical, Ltd.
1083- *
1084- * This program is free software; you can redistribute it and/or modify
1085- * it under the terms of the GNU General Public License as published by
1086- * the Free Software Foundation; version 3.
1087- *
1088- * This program is distributed in the hope that it will be useful,
1089- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1090- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1091- * GNU General Public License for more details.
1092- *
1093- * You should have received a copy of the GNU General Public License
1094- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1095- */
1096-
1097-import QtQuick 2.4
1098-import Ubuntu.Components 1.3
1099-
1100-Item {
1101- id: root
1102-
1103- // Whether this slider is short or long
1104- property bool shortSwipe
1105-
1106- // How far the user has slid
1107- property real offset
1108-
1109- // Set to true when slider is being used
1110- property bool active
1111-
1112- // How far in percentage terms
1113- readonly property real percent: d.slideOffset / target.x
1114-
1115- QtObject {
1116- id: d
1117- readonly property color trayColor: "#424141"
1118- readonly property real margin: units.gu(0.5)
1119- readonly property real arrowSize: root.height - margin * 2
1120- readonly property real dotSize: units.dp(1)
1121- readonly property real slideOffset: MathUtils.clamp(root.offset - offscreenOffset, -offscreenOffset, target.x)
1122- readonly property real offscreenOffset: units.gu(2)
1123- }
1124-
1125- implicitWidth: shortSwipe ? units.gu(15) : units.gu(27.5)
1126- implicitHeight: units.gu(6.5)
1127-
1128- Rectangle {
1129- color: d.trayColor
1130- anchors.fill: parent
1131- anchors.rightMargin: clipBox.width - 1
1132- }
1133-
1134- // We want to have a circular border around the target. But we can't just
1135- // do a radius on two of a rectangle's corners. So we clip a full circle.
1136- Item {
1137- id: clipBox
1138-
1139- clip: true
1140- anchors.top: parent.top
1141- anchors.bottom: parent.bottom
1142- anchors.right: parent.right
1143- width: parent.height / 2
1144-
1145- Rectangle {
1146- color: d.trayColor
1147- anchors.top: parent.top
1148- anchors.bottom: parent.bottom
1149- anchors.right: parent.right
1150- width: parent.width * 2
1151- radius: parent.width
1152- }
1153- }
1154-
1155- Arrow {
1156- id: target
1157- width: d.arrowSize
1158- height: d.arrowSize
1159- color: "#73000000"
1160- chevronOpacity: 0.52
1161- anchors.right: parent.right
1162- anchors.rightMargin: d.margin
1163- anchors.verticalCenter: parent.verticalCenter
1164- }
1165-
1166- Row {
1167- anchors.left: handle.horizontalCenter
1168- anchors.right: target.horizontalCenter
1169- anchors.verticalCenter: parent.verticalCenter
1170-
1171- layoutDirection: Qt.RightToLeft
1172- spacing: d.dotSize * 2
1173-
1174- Repeater {
1175- model: parent.width / (parent.spacing + d.dotSize)
1176- Rectangle {
1177- anchors.verticalCenter: parent ? parent.verticalCenter : undefined
1178- height: d.dotSize
1179- width: height
1180- radius: width
1181- color: "white"
1182- opacity: 0.2
1183- }
1184- }
1185- }
1186-
1187- Arrow {
1188- id: handle
1189- width: d.arrowSize
1190- height: d.arrowSize
1191- color: UbuntuColors.orange
1192- darkenBy: root.active ? 0.5 : 0
1193- anchors.left: parent.left
1194- // We use a Translate transform rather than anchors.leftMargin because
1195- // the latter has weird performance problems on the TutorialRight page.
1196- transform: [
1197- Translate {
1198- x: d.slideOffset
1199- }
1200- ]
1201- anchors.verticalCenter: parent.verticalCenter
1202- }
1203-}
1204
1205=== removed file 'qml/Tutorial/Tick.qml'
1206--- qml/Tutorial/Tick.qml 2015-07-15 15:07:19 +0000
1207+++ qml/Tutorial/Tick.qml 1970-01-01 00:00:00 +0000
1208@@ -1,29 +0,0 @@
1209-/*
1210- * Copyright (C) 2015 Canonical, Ltd.
1211- *
1212- * This program is free software; you can redistribute it and/or modify
1213- * it under the terms of the GNU General Public License as published by
1214- * the Free Software Foundation; version 3.
1215- *
1216- * This program is distributed in the hope that it will be useful,
1217- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1218- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1219- * GNU General Public License for more details.
1220- *
1221- * You should have received a copy of the GNU General Public License
1222- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1223- */
1224-
1225-import QtQuick 2.4
1226-import Ubuntu.Components 1.3
1227-
1228-MouseArea {
1229- implicitHeight: tick.height
1230- implicitWidth: tick.width
1231- Image {
1232- id: tick
1233- source: Qt.resolvedUrl("graphics/tick.png")
1234- height: units.gu(6.5)
1235- width: units.gu(6.5)
1236- }
1237-}
1238
1239=== modified file 'qml/Tutorial/Tutorial.qml'
1240--- qml/Tutorial/Tutorial.qml 2015-08-25 07:25:26 +0000
1241+++ qml/Tutorial/Tutorial.qml 2016-03-10 17:24:40 +0000
1242@@ -16,21 +16,29 @@
1243
1244 import QtQuick 2.4
1245 import Ubuntu.Components 1.3
1246+import AccountsService 0.1
1247+
1248+/**
1249+ * This object is always present, so it should be lean and mean. It will
1250+ * use a Loader to create the heavier tutorial pages if needed.
1251+ */
1252
1253 Item {
1254 id: root
1255
1256 property alias active: loader.active
1257- property bool paused
1258- property real edgeSize
1259
1260 property Item launcher
1261 property Item panel
1262+ property Item stage
1263+ property string usageScenario
1264+ property bool paused
1265+ property bool keyboardVisible
1266+ property int lastInputTimestamp
1267
1268 readonly property bool launcherEnabled: loader.item ? loader.item.launcherEnabled : true
1269 readonly property bool spreadEnabled: loader.item ? loader.item.spreadEnabled : true
1270 readonly property bool panelEnabled: loader.item ? loader.item.panelEnabled : true
1271- readonly property bool panelContentEnabled: loader.item ? loader.item.panelContentEnabled : true
1272 readonly property bool running: loader.item ? loader.item.running : false
1273
1274 function finish() {
1275@@ -39,24 +47,11 @@
1276 }
1277 }
1278
1279- signal finished()
1280-
1281 Loader {
1282 id: loader
1283 anchors.fill: parent
1284 source: "TutorialContent.qml"
1285-
1286- Binding {
1287- target: loader.item
1288- property: "paused"
1289- value: root.paused
1290- }
1291-
1292- Binding {
1293- target: loader.item
1294- property: "edgeSize"
1295- value: root.edgeSize
1296- }
1297+ active: AccountsService.demoEdges
1298
1299 Binding {
1300 target: loader.item
1301@@ -70,9 +65,39 @@
1302 value: root.panel
1303 }
1304
1305+ Binding {
1306+ target: loader.item
1307+ property: "stage"
1308+ value: root.stage
1309+ }
1310+
1311+ Binding {
1312+ target: loader.item
1313+ property: "usageScenario"
1314+ value: root.usageScenario
1315+ }
1316+
1317+ Binding {
1318+ target: loader.item
1319+ property: "paused"
1320+ value: root.paused
1321+ }
1322+
1323+ Binding {
1324+ target: loader.item
1325+ property: "keyboardVisible"
1326+ value: root.keyboardVisible
1327+ }
1328+
1329+ Binding {
1330+ target: loader.item
1331+ property: "lastInputTimestamp"
1332+ value: root.lastInputTimestamp
1333+ }
1334+
1335 Connections {
1336 target: loader.item
1337- onFinished: root.finished()
1338+ onFinished: AccountsService.demoEdges = false
1339 }
1340 }
1341 }
1342
1343=== added file 'qml/Tutorial/TutorialBottom.qml'
1344--- qml/Tutorial/TutorialBottom.qml 1970-01-01 00:00:00 +0000
1345+++ qml/Tutorial/TutorialBottom.qml 2016-03-10 17:24:40 +0000
1346@@ -0,0 +1,126 @@
1347+/*
1348+ * Copyright (C) 2015 Canonical, Ltd.
1349+ *
1350+ * This program is free software; you can redistribute it and/or modify
1351+ * it under the terms of the GNU General Public License as published by
1352+ * the Free Software Foundation; version 3.
1353+ *
1354+ * This program is distributed in the hope that it will be useful,
1355+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1356+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1357+ * GNU General Public License for more details.
1358+ *
1359+ * You should have received a copy of the GNU General Public License
1360+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1361+ */
1362+
1363+import QtQuick 2.4
1364+import Ubuntu.Components 1.3
1365+import Ubuntu.Gestures 0.1
1366+import Unity.Application 0.1
1367+
1368+TutorialPage {
1369+ id: root
1370+
1371+ property string usageScenario
1372+ property var stage
1373+ property var application: null
1374+
1375+ // This page is a bit fragile. It relies on knowing how the app beneath
1376+ // the shell will react to a drag. What we do is put a monitor-only DDA
1377+ // at the bottom of the page (so that we know when the drag is finished)
1378+ // and pass the events on through to the app. Thus, it sees the drag and
1379+ // brings its bottom edge up.
1380+ //
1381+ // Unfortunately, each app is on its own when implementing the bottom edge
1382+ // drag. Most share copied-and-pasted code right now, but they will
1383+ // eventually consolidate on a version of DirectionalDragArea that will
1384+ // land in the SDK (making our guessing job easier). Though, also in the
1385+ // future, this whole bottom tutorial component will also land in the SDK,
1386+ // rendering our version here obsolete.
1387+ //
1388+ // Anyway, for the moment, we base our guesses on the copied-and-pasted
1389+ // code used in several of the core apps and only bring this component
1390+ // up if we are in those core apps.
1391+
1392+ readonly property real mainStageWidth: stage.width - sideStageWidth
1393+ readonly property real sideStageWidth: root.usageScenario === "tablet" && stage.sideStageVisible ?
1394+ stage.sideStageWidth : 0
1395+ readonly property bool isMainStageApp: usageScenario !== "tablet" ||
1396+ application.stage === ApplicationInfoInterface.MainStage
1397+ readonly property real dragAreaHeight: units.gu(3) // based on PageWithBottomEdge.qml
1398+ readonly property real targetDistance: height * 0.2 + dragAreaHeight // based on PageWithBottomEdge.qml
1399+
1400+ opacityOverride: dragArea.dragging ? 1 - (-dragArea.distance / targetDistance) : 1
1401+
1402+ mouseArea {
1403+ anchors.bottomMargin: root.dragAreaHeight
1404+ }
1405+
1406+ background {
1407+ sourceSize.height: 1916
1408+ sourceSize.width: 1080
1409+ source: Qt.resolvedUrl("graphics/background2.png")
1410+ rotation: 180
1411+ }
1412+
1413+ arrow {
1414+ anchors.bottom: root.bottom
1415+ anchors.bottomMargin: units.gu(3)
1416+ anchors.horizontalCenter: label.horizontalCenter
1417+ anchors.horizontalCenterOffset: -(label.width - label.contentWidth) / 2
1418+ rotation: 90
1419+ }
1420+
1421+ label {
1422+ text: !application ? "" :
1423+ application.appId === "address-book-app" ?
1424+ i18n.tr("Swipe up to add a contact") :
1425+ application.appId === "com.ubuntu.calculator_calculator" ?
1426+ i18n.tr("Swipe up for favorite calculations") :
1427+ application.appId === "com.ubuntu.clock_clock" ?
1428+ i18n.tr("Swipe up to manage alarms") :
1429+ application.appId === "dialer-app" ?
1430+ i18n.tr("Swipe up for recent calls") :
1431+ application.appId === "messaging-app" ?
1432+ i18n.tr("Swipe up to create a message") :
1433+ i18n.tr("Swipe up to manage the app") // shouldn't be used
1434+ anchors.bottom: arrow.top
1435+ anchors.bottomMargin: units.gu(3)
1436+ anchors.left: root.left
1437+ anchors.leftMargin: (label.width - label.contentWidth) / 2 + sideMargin +
1438+ (isMainStageApp ? 0 : mainStageWidth)
1439+ width: (isMainStageApp ? mainStageWidth : sideStageWidth) - sideMargin * 2
1440+
1441+ readonly property real sideMargin: units.gu(4)
1442+ }
1443+
1444+ // Watches drag events but does not intercept them, so that the app beneath
1445+ // will still drag the bottom edge up.
1446+ DirectionalDragArea {
1447+ id: dragArea
1448+ monitorOnly: true
1449+ direction: Direction.Upwards
1450+ anchors.left: parent.left
1451+ anchors.right: parent.right
1452+ anchors.bottom: parent.bottom
1453+ height: root.dragAreaHeight
1454+
1455+ // Apps currently don't use DDA. DDA will stop a gesture if
1456+ // horizontal motion is detected. But our apps won't. So turn off
1457+ // that gesture cleverness on our part, it will only get us out of sync.
1458+ immediateRecognition: true
1459+ }
1460+
1461+ MouseArea {
1462+ // A second mouse area because in tablet mode, we only want to let the
1463+ // user drag up on one of the stages, not both. So we want to cover
1464+ // the second bottom edge with an event eater.
1465+ enabled: root.usageScenario === "tablet"
1466+ height: root.dragAreaHeight
1467+ width: isMainStageApp ? sideStageWidth : mainStageWidth
1468+ anchors.bottom: parent.bottom
1469+ anchors.left: isMainStageApp ? undefined : parent.left
1470+ anchors.right: isMainStageApp ? parent.right : undefined
1471+ }
1472+}
1473
1474=== removed file 'qml/Tutorial/TutorialBottom.qml'
1475--- qml/Tutorial/TutorialBottom.qml 2015-07-15 15:07:19 +0000
1476+++ qml/Tutorial/TutorialBottom.qml 1970-01-01 00:00:00 +0000
1477@@ -1,104 +0,0 @@
1478-/*
1479- * Copyright (C) 2014 Canonical, Ltd.
1480- *
1481- * This program is free software; you can redistribute it and/or modify
1482- * it under the terms of the GNU General Public License as published by
1483- * the Free Software Foundation; version 3.
1484- *
1485- * This program is distributed in the hope that it will be useful,
1486- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1487- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1488- * GNU General Public License for more details.
1489- *
1490- * You should have received a copy of the GNU General Public License
1491- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1492- */
1493-
1494-import QtQuick 2.4
1495-import Ubuntu.Components 1.3
1496-import Ubuntu.Gestures 0.1
1497-import "../Components"
1498-import "." as LocalComponents
1499-
1500-TutorialPage {
1501- id: root
1502-
1503- property alias edgeSize: dragArea.height
1504-
1505- title: i18n.tr("Open special menus")
1506- text: i18n.tr("Swipe up from the bottom edge.")
1507- fullTextWidth: true
1508-
1509- SequentialAnimation {
1510- id: teaseAnimation
1511- paused: running && root.paused
1512- running: !dragArea.useTouchY && slider.dragOffset === 0
1513- loops: Animation.Infinite
1514-
1515- UbuntuNumberAnimation {
1516- target: slider
1517- property: "teaseOffset"
1518- to: units.gu(1)
1519- duration: UbuntuAnimation.SleepyDuration
1520- }
1521- UbuntuNumberAnimation {
1522- target: slider
1523- property: "teaseOffset"
1524- to: 0
1525- duration: UbuntuAnimation.SleepyDuration
1526- }
1527- }
1528-
1529- foreground {
1530- children: [
1531- LocalComponents.Slider {
1532- id: slider
1533- anchors {
1534- bottom: parent.bottom
1535- bottomMargin: width / 2 - height / 2
1536- horizontalCenter: parent.horizontalCenter
1537- }
1538- rotation: -90
1539- offset: teaseOffset + dragOffset
1540- active: dragArea.dragging
1541-
1542- property real teaseOffset
1543- property real dragOffset: dragArea.useTouchY ? -dragArea.touchY : 0
1544-
1545- Behavior on dragOffset {
1546- id: offsetAnimation
1547- UbuntuNumberAnimation {}
1548- }
1549- }
1550- ]
1551- }
1552-
1553- DirectionalDragArea {
1554- id: dragArea
1555- direction: Direction.Upwards
1556- anchors {
1557- bottom: parent.bottom
1558- left: parent.left
1559- right: parent.right
1560- }
1561-
1562- property bool useTouchY
1563-
1564- onDraggingChanged: {
1565- if (!dragging) {
1566- if (slider.percent >= 0.85) {
1567- root.hide();
1568- } else if (slider.percent >= 0.15) {
1569- root.showError();
1570- }
1571- }
1572-
1573- // We use a separate vars here rather than just directly looking at
1574- // 'dragging' because we want to preserve our 'slider.offset'
1575- // value during the above percent check. Now that we made it,
1576- // we can have 'slider.offset' go back to zero.
1577- offsetAnimation.enabled = !dragging;
1578- useTouchY = dragging;
1579- }
1580- }
1581-}
1582
1583=== removed file 'qml/Tutorial/TutorialBottomFinish.qml'
1584--- qml/Tutorial/TutorialBottomFinish.qml 2015-07-15 15:07:19 +0000
1585+++ qml/Tutorial/TutorialBottomFinish.qml 1970-01-01 00:00:00 +0000
1586@@ -1,41 +0,0 @@
1587-/*
1588- * Copyright (C) 2014 Canonical, Ltd.
1589- *
1590- * This program is free software; you can redistribute it and/or modify
1591- * it under the terms of the GNU General Public License as published by
1592- * the Free Software Foundation; version 3.
1593- *
1594- * This program is distributed in the hope that it will be useful,
1595- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1596- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1597- * GNU General Public License for more details.
1598- *
1599- * You should have received a copy of the GNU General Public License
1600- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1601- */
1602-
1603-import QtQuick 2.4
1604-import Ubuntu.Components 1.3
1605-import "." as LocalComponents
1606-
1607-TutorialPage {
1608- id: root
1609-
1610- title: i18n.tr("This action does different things for different apps")
1611- text: i18n.tr("Tap here to finish.")
1612- fullTextWidth: true
1613-
1614- foreground {
1615- children: [
1616- LocalComponents.Tick {
1617- objectName: "tick"
1618- anchors {
1619- horizontalCenter: parent.horizontalCenter
1620- top: parent.top
1621- topMargin: root.textBottom + units.gu(3)
1622- }
1623- onClicked: root.hide()
1624- }
1625- ]
1626- }
1627-}
1628
1629=== modified file 'qml/Tutorial/TutorialContent.qml'
1630--- qml/Tutorial/TutorialContent.qml 2015-08-25 07:25:26 +0000
1631+++ qml/Tutorial/TutorialContent.qml 2016-03-10 17:24:40 +0000
1632@@ -16,103 +16,273 @@
1633
1634 import QtQuick 2.4
1635 import Ubuntu.Components 1.3
1636+import AccountsService 0.1
1637+import Unity.Application 0.1
1638
1639 Item {
1640 id: root
1641
1642 property Item launcher
1643 property Item panel
1644-
1645- readonly property bool launcherEnabled: !running ||
1646- (!paused && tutorialLeft.shown)
1647- readonly property bool spreadEnabled: !running
1648- readonly property bool panelEnabled: !running
1649- readonly property bool panelContentEnabled: !running
1650- readonly property alias running: d.running
1651-
1652- property bool paused: false
1653- property real edgeSize
1654+ property Item stage
1655+ property string usageScenario
1656+ property bool paused
1657+ property bool keyboardVisible
1658+ property var lastInputTimestamp
1659+
1660+ readonly property bool launcherEnabled: !running
1661+ || tutorialLeftLoader.shown
1662+ || tutorialLeftLongLoader.shown
1663+ readonly property bool spreadEnabled: !running || tutorialRightLoader.shown
1664+ readonly property bool panelEnabled: !running || tutorialTopLoader.shown
1665+ readonly property bool running: tutorialLeftLoader.shown
1666+ || tutorialTopLoader.shown
1667+ || tutorialRightLoader.shown
1668+ || tutorialBottomLoader.shown
1669
1670 signal finished()
1671
1672 function finish() {
1673- d.stop();
1674 finished();
1675 }
1676
1677 ////
1678
1679- Component.onCompleted: {
1680- d.start();
1681- }
1682-
1683 QtObject {
1684 id: d
1685
1686- property bool running
1687-
1688- function stop() {
1689- running = false;
1690- }
1691-
1692- function start() {
1693- running = true;
1694- tutorialLeft.show();
1695- }
1696- }
1697-
1698- TutorialLeft {
1699- id: tutorialLeft
1700- objectName: "tutorialLeft"
1701- anchors.fill: parent
1702- launcher: root.launcher
1703- paused: !shown || root.paused
1704-
1705- onFinished: tutorialLeftFinish.show()
1706- }
1707-
1708- TutorialLeftFinish {
1709- id: tutorialLeftFinish
1710- objectName: "tutorialLeftFinish"
1711- anchors.fill: parent
1712- textXOffset: root.launcher.panelWidth
1713- paused: !shown || root.paused
1714- text: i18n.tr("Tap here to continue.")
1715-
1716- onFinished: {
1717- root.launcher.hide();
1718- tutorialRight.show();
1719- }
1720- }
1721-
1722- TutorialRight {
1723- id: tutorialRight
1724- objectName: "tutorialRight"
1725- anchors.fill: parent
1726- edgeSize: root.edgeSize
1727- panel: root.panel
1728- paused: !shown || root.paused
1729-
1730- onFinished: tutorialBottom.show()
1731- }
1732-
1733- TutorialBottom {
1734- id: tutorialBottom
1735- objectName: "tutorialBottom"
1736- anchors.fill: parent
1737- edgeSize: root.edgeSize
1738- paused: !shown || root.paused
1739-
1740- onFinished: tutorialBottomFinish.show()
1741- }
1742-
1743- TutorialBottomFinish {
1744- id: tutorialBottomFinish
1745- objectName: "tutorialBottomFinish"
1746- anchors.fill: parent
1747- backgroundFadesOut: true
1748- paused: !shown || root.paused
1749-
1750- onFinished: root.finish()
1751+ // We allow "" because it is briefly empty on startup, and we don't
1752+ // want to improperly skip any mobile tutorials.
1753+ property bool mobileScenario: root.usageScenario === "" ||
1754+ root.usageScenario === "phone" ||
1755+ root.usageScenario === "tablet"
1756+
1757+ property var focusedApp: ApplicationManager.focusedApplicationId
1758+ ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId)
1759+ : null
1760+
1761+ function haveShown(tutorialId) {
1762+ return AccountsService.demoEdgesCompleted.indexOf(tutorialId) != -1;
1763+ }
1764+
1765+ property bool endPointsFinished: tutorialRightLoader.skipped &&
1766+ tutorialBottomLoader.skipped
1767+ onEndPointsFinishedChanged: if (endPointsFinished) root.finish()
1768+ }
1769+
1770+ Loader {
1771+ id: tutorialLeftLoader
1772+ objectName: "tutorialLeftLoader"
1773+ anchors.fill: parent
1774+
1775+ readonly property bool skipped: !d.mobileScenario || d.haveShown("left")
1776+ readonly property bool shown: item && item.shown
1777+ active: !skipped || (item && item.visible)
1778+ onSkippedChanged: if (skipped && shown) item.hide()
1779+
1780+ sourceComponent: TutorialLeft {
1781+ id: tutorialLeft
1782+ objectName: "tutorialLeft"
1783+ anchors.fill: parent
1784+ launcher: root.launcher
1785+ hides: [launcher, panel.indicators]
1786+ paused: root.paused
1787+
1788+ isReady: !tutorialLeftLoader.skipped && !paused && !keyboardVisible
1789+
1790+ // Use an idle timer here, because when constructed, all our isReady variables will be false.
1791+ // Qml needs a moment to copy their values from Tutorial.qml. So we idle it and recheck.
1792+ Timer {
1793+ id: tutorialLeftTimer
1794+ interval: 0
1795+ onTriggered: if (tutorialLeft.isReady && !tutorialLeft.shown) tutorialLeft.show()
1796+ }
1797+
1798+ onIsReadyChanged: if (isReady && !shown) tutorialLeftTimer.start()
1799+ onFinished: AccountsService.markDemoEdgeCompleted("left")
1800+ }
1801+ }
1802+
1803+ Loader {
1804+ id: tutorialLeftLongLoader
1805+ objectName: "tutorialLeftLongLoader"
1806+ anchors.fill: parent
1807+
1808+ readonly property bool skipped: !d.mobileScenario || d.haveShown("left-long")
1809+ readonly property bool shown: item && item.shown
1810+ active: !skipped || (item && item.visible)
1811+ onSkippedChanged: if (skipped && shown) item.hide()
1812+
1813+ sourceComponent: TutorialLeftLong {
1814+ id: tutorialLeftLong
1815+ objectName: "tutorialLeftLong"
1816+ anchors.fill: parent
1817+ launcher: root.launcher
1818+ hides: [launcher, panel.indicators]
1819+ paused: root.paused
1820+
1821+ skipped: tutorialLeftLongLoader.skipped
1822+ isReady: tutorialLeftLoader.skipped && !skipped && !paused && !keyboardVisible &&
1823+ !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow
1824+
1825+ Timer {
1826+ id: tutorialLeftLongTimer
1827+ objectName: "tutorialLeftLongTimer"
1828+ interval: 5000
1829+ onTriggered: {
1830+ if (parent.isReady) {
1831+ if (!parent.shown) {
1832+ parent.show();
1833+ }
1834+ } else if (!parent.skipped) {
1835+ restart();
1836+ }
1837+ }
1838+ }
1839+
1840+ onIsReadyChanged: if (isReady && !shown) tutorialLeftLongTimer.start()
1841+ onFinished: AccountsService.markDemoEdgeCompleted("left-long")
1842+ }
1843+ }
1844+
1845+ Loader {
1846+ id: tutorialTopLoader
1847+ objectName: "tutorialTopLoader"
1848+ anchors.fill: parent
1849+
1850+ readonly property bool skipped: !d.mobileScenario || d.haveShown("top")
1851+ readonly property bool shown: item && item.shown
1852+ active: !skipped || (item && item.visible)
1853+ onSkippedChanged: if (skipped && shown) item.hide()
1854+
1855+ sourceComponent: TutorialTop {
1856+ id: tutorialTop
1857+ objectName: "tutorialTop"
1858+ anchors.fill: parent
1859+ panel: root.panel
1860+ hides: [launcher, panel.indicators]
1861+ paused: root.paused
1862+
1863+ skipped: tutorialTopLoader.skipped
1864+ isReady: tutorialLeftLongLoader.skipped && !skipped && !paused && !keyboardVisible &&
1865+ !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow
1866+
1867+ // We fire 30s after left edge tutorial, with at least 3s of inactivity
1868+
1869+ InactivityTimer {
1870+ id: tutorialTopInactivityTimer
1871+ lastInputTimestamp: root.lastInputTimestamp
1872+ page: parent
1873+ }
1874+
1875+ Timer {
1876+ id: tutorialTopTimer
1877+ objectName: "tutorialTopTimer"
1878+ interval: 27000
1879+ onTriggered: tutorialTopInactivityTimer.start()
1880+ }
1881+
1882+ onIsReadyChanged: if (isReady && !shown) tutorialTopTimer.start()
1883+ onFinished: AccountsService.markDemoEdgeCompleted("top")
1884+ }
1885+ }
1886+
1887+ Loader {
1888+ id: tutorialRightLoader
1889+ objectName: "tutorialRightLoader"
1890+ anchors.fill: parent
1891+
1892+ readonly property bool skipped: d.haveShown("right")
1893+ readonly property bool shown: item && item.shown
1894+ active: !skipped || (item && item.visible)
1895+ onSkippedChanged: if (skipped && shown) item.hide()
1896+
1897+ sourceComponent: TutorialRight {
1898+ id: tutorialRight
1899+ objectName: "tutorialRight"
1900+ anchors.fill: parent
1901+ stage: root.stage
1902+ usageScenario: root.usageScenario
1903+ hides: [launcher, panel.indicators]
1904+ paused: root.paused
1905+
1906+ skipped: tutorialRightLoader.skipped
1907+ isReady: tutorialTopLoader.skipped && !skipped && !paused && !keyboardVisible &&
1908+ !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow &&
1909+ ApplicationManager.count >= 3
1910+
1911+ InactivityTimer {
1912+ id: tutorialRightInactivityTimer
1913+ objectName: "tutorialRightInactivityTimer"
1914+ lastInputTimestamp: root.lastInputTimestamp
1915+ page: parent
1916+ }
1917+
1918+ Connections {
1919+ target: d
1920+ onFocusedAppChanged: {
1921+ if (tutorialRight.isReady && !tutorialRight.shown && d.focusedApp
1922+ && d.focusedApp.state === ApplicationInfoInterface.Starting) {
1923+ tutorialRight.show();
1924+ }
1925+ }
1926+ }
1927+
1928+ onIsReadyChanged: if (isReady && !shown) tutorialRightInactivityTimer.start()
1929+ onFinished: AccountsService.markDemoEdgeCompleted("right")
1930+ }
1931+ }
1932+
1933+ Loader {
1934+ id: tutorialBottomLoader
1935+ objectName: "tutorialBottomLoader"
1936+ anchors.fill: parent
1937+
1938+ // See TutorialBottom.qml for an explanation of why we only support
1939+ // certain apps.
1940+ readonly property var supportedApps: ["address-book-app",
1941+ "com.ubuntu.calculator_calculator",
1942+ "dialer-app",
1943+ "messaging-app"]
1944+ readonly property bool skipped: {
1945+ if (!d.mobileScenario) {
1946+ return true;
1947+ }
1948+ for (var i = 0; i < supportedApps.length; i++) {
1949+ if (!d.haveShown("bottom-" + supportedApps[i])) {
1950+ return false;
1951+ }
1952+ }
1953+ return true;
1954+ }
1955+ readonly property bool shown: item && item.shown
1956+ readonly property bool haveShownFocusedApp: d.focusedApp &&
1957+ d.haveShown("bottom-" + d.focusedApp.appId)
1958+ readonly property bool mightShow: !skipped && d.focusedApp &&
1959+ supportedApps.indexOf(d.focusedApp.appId) !== -1 &&
1960+ !haveShownFocusedApp
1961+ active: !skipped || (item && item.visible)
1962+ onHaveShownFocusedAppChanged: if (haveShownFocusedApp && shown) hide()
1963+ onSkippedChanged: if (skipped && shown) item.hide()
1964+
1965+ sourceComponent: TutorialBottom {
1966+ id: tutorialBottom
1967+ objectName: "tutorialBottom"
1968+ anchors.fill: parent
1969+ hides: [launcher, panel.indicators]
1970+ paused: root.paused
1971+ usageScenario: root.usageScenario
1972+ stage: root.stage
1973+ application: d.focusedApp
1974+
1975+ skipped: tutorialBottomLoader.skipped
1976+ isReady: !tutorialBottomLoader.skipped && !paused && !keyboardVisible &&
1977+ !tutorialTopLoader.shown && !tutorialRightLoader.shown &&
1978+ tutorialBottomLoader.mightShow &&
1979+ d.focusedApp.state === ApplicationInfoInterface.Running
1980+
1981+ onIsReadyChanged: if (isReady && !shown) show()
1982+ onFinished: AccountsService.markDemoEdgeCompleted("bottom-" + d.focusedApp.appId)
1983+ }
1984 }
1985 }
1986
1987=== modified file 'qml/Tutorial/TutorialLeft.qml'
1988--- qml/Tutorial/TutorialLeft.qml 2015-07-21 14:38:35 +0000
1989+++ qml/Tutorial/TutorialLeft.qml 2016-03-10 17:24:40 +0000
1990@@ -1,5 +1,5 @@
1991 /*
1992- * Copyright (C) 2014,2015 Canonical, Ltd.
1993+ * Copyright (C) 2015 Canonical, Ltd.
1994 *
1995 * This program is free software; you can redistribute it and/or modify
1996 * it under the terms of the GNU General Public License as published by
1997@@ -23,79 +23,32 @@
1998
1999 property var launcher
2000
2001- title: i18n.tr("Open the launcher")
2002- text: i18n.tr("Short swipe from the left edge.")
2003-
2004- textXOffset: root.launcher.x + root.launcher.visibleWidth
2005-
2006- Connections {
2007- target: root.launcher
2008-
2009- onStateChanged: {
2010- if (root.launcher.state === "visible") {
2011- finishTimer.start();
2012- }
2013- }
2014-
2015- onDash: {
2016- finishTimer.stop();
2017- root.showError();
2018- root.launcher.hide();
2019- }
2020- }
2021-
2022- SequentialAnimation {
2023- id: teaseAnimation
2024- objectName: "teaseAnimation"
2025- paused: running && root.paused
2026- running: !slider.active && root.launcher.visibleWidth === 0 && root.shown
2027- loops: Animation.Infinite
2028- property real bounce: 0
2029- readonly property real maxBounce: units.gu(2)
2030-
2031- UbuntuNumberAnimation {
2032- target: teaseAnimation
2033- property: "bounce"
2034- to: teaseAnimation.maxBounce
2035- duration: UbuntuAnimation.SleepyDuration
2036- }
2037- UbuntuNumberAnimation {
2038- target: teaseAnimation
2039- property: "bounce"
2040- to: 0
2041- duration: UbuntuAnimation.SleepyDuration
2042- }
2043- }
2044-
2045- Binding {
2046- target: root.launcher
2047- when: root.shown
2048- property: "x"
2049- value: Math.min(root.launcher.panelWidth - root.launcher.visibleWidth, teaseAnimation.bounce)
2050- }
2051-
2052- Timer {
2053- id: finishTimer
2054- interval: 1
2055- onTriggered: {
2056- root.hide();
2057- root.launcher.x = 0; // make sure to reset launcher before we go
2058- }
2059- }
2060-
2061- foreground {
2062- children: [
2063- LocalComponents.Slider {
2064- id: slider
2065- anchors {
2066- left: parent.left
2067- top: parent.top
2068- topMargin: root.textBottom + units.gu(3)
2069- }
2070- offset: root.launcher.x + root.launcher.visibleWidth + root.launcher.progress
2071- active: root.launcher.dragging
2072- shortSwipe: true
2073- }
2074- ]
2075+ opacityOverride: 1 - launcher.visibleWidth / launcher.panelWidth
2076+
2077+ mouseArea {
2078+ anchors.leftMargin: launcher.dragAreaWidth
2079+ }
2080+
2081+ background {
2082+ sourceSize.height: 1916
2083+ sourceSize.width: 1080
2084+ source: Qt.resolvedUrl("graphics/background1.png")
2085+ mirror: true
2086+ }
2087+
2088+ arrow {
2089+ anchors.left: root.left
2090+ anchors.leftMargin: units.gu(2)
2091+ anchors.verticalCenter: root.verticalCenter
2092+ rotation: 180
2093+ }
2094+
2095+ label {
2096+ text: i18n.tr("Swipe from the left edge to open the launcher")
2097+ anchors.left: arrow.right
2098+ anchors.leftMargin: units.gu(3)
2099+ anchors.right: root.right
2100+ anchors.rightMargin: units.gu(4)
2101+ anchors.verticalCenter: arrow.verticalCenter
2102 }
2103 }
2104
2105=== removed file 'qml/Tutorial/TutorialLeftFinish.qml'
2106--- qml/Tutorial/TutorialLeftFinish.qml 2015-07-15 15:07:19 +0000
2107+++ qml/Tutorial/TutorialLeftFinish.qml 1970-01-01 00:00:00 +0000
2108@@ -1,41 +0,0 @@
2109-/*
2110- * Copyright (C) 2014 Canonical, Ltd.
2111- *
2112- * This program is free software; you can redistribute it and/or modify
2113- * it under the terms of the GNU General Public License as published by
2114- * the Free Software Foundation; version 3.
2115- *
2116- * This program is distributed in the hope that it will be useful,
2117- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2118- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2119- * GNU General Public License for more details.
2120- *
2121- * You should have received a copy of the GNU General Public License
2122- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2123- */
2124-
2125-import QtQuick 2.4
2126-import Ubuntu.Components 1.3
2127-import "." as LocalComponents
2128-
2129-TutorialPage {
2130- id: root
2131-
2132- title: i18n.tr("These are the shortcuts to favorite apps")
2133- text: i18n.tr("Tap here to continue.")
2134- fullTextWidth: true
2135-
2136- foreground {
2137- children: [
2138- LocalComponents.Tick {
2139- objectName: "tick"
2140- anchors {
2141- horizontalCenter: parent.horizontalCenter
2142- top: parent.top
2143- topMargin: root.textBottom + units.gu(3)
2144- }
2145- onClicked: root.hide()
2146- }
2147- ]
2148- }
2149-}
2150
2151=== added file 'qml/Tutorial/TutorialLeftLong.qml'
2152--- qml/Tutorial/TutorialLeftLong.qml 1970-01-01 00:00:00 +0000
2153+++ qml/Tutorial/TutorialLeftLong.qml 2016-03-10 17:24:40 +0000
2154@@ -0,0 +1,54 @@
2155+/*
2156+ * Copyright (C) 2016 Canonical, Ltd.
2157+ *
2158+ * This program is free software; you can redistribute it and/or modify
2159+ * it under the terms of the GNU General Public License as published by
2160+ * the Free Software Foundation; version 3.
2161+ *
2162+ * This program is distributed in the hope that it will be useful,
2163+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2164+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2165+ * GNU General Public License for more details.
2166+ *
2167+ * You should have received a copy of the GNU General Public License
2168+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2169+ */
2170+
2171+import QtQuick 2.4
2172+import Ubuntu.Components 1.3
2173+import "." as LocalComponents
2174+
2175+TutorialPage {
2176+ id: root
2177+
2178+ property var launcher
2179+
2180+ opacityOverride: 1 - launcher.dragDistance / launcher.minimizeDistance
2181+
2182+ mouseArea {
2183+ anchors.leftMargin: launcher.dragAreaWidth
2184+ }
2185+
2186+ background {
2187+ sourceSize.height: 1916
2188+ sourceSize.width: 1080
2189+ source: Qt.resolvedUrl("graphics/background1.png")
2190+ mirror: true
2191+ }
2192+
2193+ arrow {
2194+ anchors.left: root.left
2195+ anchors.leftMargin: units.gu(2)
2196+ anchors.verticalCenter: root.verticalCenter
2197+ rotation: 180
2198+ }
2199+
2200+ label {
2201+ text: i18n.tr("Long swipe from the left edge to open the Today scope")
2202+ anchors.left: arrow.right
2203+ anchors.leftMargin: units.gu(3)
2204+ anchors.right: root.right
2205+ anchors.rightMargin: units.gu(4)
2206+ anchors.verticalCenter: arrow.verticalCenter
2207+ }
2208+}
2209
2210=== modified file 'qml/Tutorial/TutorialPage.qml'
2211--- qml/Tutorial/TutorialPage.qml 2015-07-15 15:07:19 +0000
2212+++ qml/Tutorial/TutorialPage.qml 2016-03-10 17:24:40 +0000
2213@@ -21,225 +21,101 @@
2214 Showable {
2215 id: root
2216
2217- // This is the header displayed, like "Right edge"
2218- property alias title: titleLabel.text
2219-
2220- // This is the block of text displayed below the header
2221- property alias text: textLabel.text
2222-
2223- // Whether animations are paused
2224+ property alias arrow: arrow
2225+ property alias label: label
2226+ property alias background: background
2227+ property alias mouseArea: mouseArea
2228+ property real opacityOverride: 1
2229 property bool paused
2230-
2231- // Whether to give the text the full width that the title has
2232- property bool fullTextWidth
2233-
2234- // Whether whole page (background + foreground) or just the foreground fades in
2235- property bool backgroundFadesIn: false
2236-
2237- // Whether whole page (background + foreground) or just the foreground fades out
2238- property bool backgroundFadesOut: false
2239-
2240- // The foreground Item, add children to it that you want to fade in
2241- property alias foreground: foregroundExtra
2242-
2243- // The text label bottom, so you can position elements relative to it
2244- readonly property real textBottom: Math.max(textLabel.y + textLabel.height, errorTextLabel.y + errorTextLabel.height)
2245-
2246- // The MouseArea that eats events (so you can adjust size as you will)
2247- property alias mouseArea: mouseArea
2248-
2249- // X/Y offsets for text
2250- property real textXOffset: 0
2251- property real textYOffset: 0
2252-
2253- // Foreground text opacity
2254- property real textOpacity: 1
2255+ property bool skipped
2256+ property bool isReady
2257
2258 signal finished()
2259
2260- function showError() {
2261- errorTimer.start();
2262- }
2263-
2264 ////
2265
2266+ QtObject {
2267+ id: d
2268+ property bool showOnUnpause
2269+ }
2270+
2271 visible: false
2272 shown: false
2273
2274- property real _foregroundHideOpacity
2275+ opacity: Math.max(Math.min(_showOpacity, opacityOverride), 0)
2276+ onOpacityOverrideChanged: {
2277+ if (opacityOverride <= 0) {
2278+ d.showOnUnpause = false;
2279+ hide();
2280+ }
2281+ }
2282+ property real _showOpacity: 0
2283+
2284+ onPausedChanged: {
2285+ if (paused && shown) {
2286+ d.showOnUnpause = true;
2287+ hide();
2288+ } else if (!paused && d.showOnUnpause) {
2289+ if (isReady) {
2290+ show();
2291+ } else if (hideAnimation.running) {
2292+ hideAnimation.stop();
2293+ }
2294+ d.showOnUnpause = false;
2295+ }
2296+ }
2297
2298 showAnimation: StandardAnimation {
2299- property: root.backgroundFadesIn ? "opacity" : "_foregroundHideOpacity"
2300+ property: "_showOpacity"
2301 from: 0
2302 to: 1
2303- duration: root.backgroundFadesIn ? UbuntuAnimation.SleepyDuration : UbuntuAnimation.BriskDuration
2304+ duration: UbuntuAnimation.SleepyDuration
2305 onStarted: root.visible = true
2306 }
2307
2308 hideAnimation: StandardAnimation {
2309- property: root.backgroundFadesOut ? "opacity" : "_foregroundHideOpacity"
2310+ property: "_showOpacity"
2311 to: 0
2312 duration: UbuntuAnimation.BriskDuration
2313 onStopped: {
2314 root.visible = false;
2315- root.finished();
2316- }
2317- }
2318-
2319- QtObject {
2320- id: d
2321-
2322- readonly property real sideMargin: units.gu(5.5)
2323- readonly property real verticalOffset: -units.gu(9)
2324- readonly property real textXOffset: Math.max(0, root.textXOffset - sideMargin + units.gu(2))
2325-
2326- property real fadeInOffset: {
2327- if (showAnimation.running) {
2328- var opacity = root[root.showAnimation.property]
2329- return (1 - opacity) * units.gu(3);
2330- } else {
2331- return 0;
2332+ if (!d.showOnUnpause) {
2333+ root.finished();
2334 }
2335 }
2336 }
2337
2338- Timer {
2339- id: errorTimer
2340- interval: 3500
2341- }
2342-
2343 MouseArea { // eat any errant presses
2344 id: mouseArea
2345 anchors.fill: parent
2346 }
2347
2348- Rectangle {
2349- anchors.fill: parent
2350- color: "black"
2351- opacity: 0.82
2352- }
2353-
2354- Item {
2355- id: foreground
2356- anchors.fill: parent
2357- opacity: root._foregroundHideOpacity
2358-
2359- Item {
2360- anchors.fill: parent
2361- opacity: root.textOpacity
2362-
2363- Label {
2364- id: titleLabel
2365- anchors {
2366- top: parent.verticalCenter
2367- topMargin: d.verticalOffset + root.textYOffset
2368- left: parent.left
2369- leftMargin: d.sideMargin + d.textXOffset
2370- }
2371- width: parent.width - d.sideMargin * 2
2372- horizontalAlignment: Text.AlignLeft
2373- wrapMode: Text.Wrap
2374- font.weight: Font.Light
2375- font.pixelSize: units.gu(3.5)
2376- }
2377-
2378- Label {
2379- id: textLabel
2380- anchors {
2381- top: titleLabel.bottom
2382- topMargin: units.gu(2)
2383- left: parent.left
2384- leftMargin: d.sideMargin + d.textXOffset
2385- }
2386- width: (parent.width - d.sideMargin * 2) * (fullTextWidth ? 1 : 0.66)
2387- horizontalAlignment: Text.AlignLeft
2388- wrapMode: Text.Wrap
2389- font.weight: Font.Light
2390- font.pixelSize: units.gu(2.5)
2391- }
2392-
2393- // We use two separate labels like this rather than just changing
2394- // the text of the above labels because we want to know where to place
2395- // sliders (via root.textBottom) without having that place change
2396- // as the text changes length.
2397- Label {
2398- id: errorTitleLabel
2399- objectName: "errorTitleLabel"
2400- anchors {
2401- top: titleLabel.top
2402- left: titleLabel.left
2403- }
2404- width: titleLabel.width
2405- horizontalAlignment: titleLabel.horizontalAlignment
2406- wrapMode: titleLabel.wrapMode
2407- font.weight: titleLabel.font.weight
2408- font.pixelSize: titleLabel.font.pixelSize
2409- opacity: 0
2410- text: i18n.tr("You almost got it!")
2411- }
2412-
2413- Label {
2414- id: errorTextLabel
2415- objectName: "errorTextLabel"
2416- anchors {
2417- top: errorTitleLabel.bottom
2418- topMargin: textLabel.anchors.topMargin
2419- left: textLabel.left
2420- }
2421- width: textLabel.width
2422- horizontalAlignment: textLabel.horizontalAlignment
2423- wrapMode: textLabel.wrapMode
2424- font.weight: textLabel.font.weight
2425- font.pixelSize: textLabel.font.pixelSize
2426- opacity: 0
2427- text: i18n.tr("Try again.")
2428- }
2429- }
2430-
2431- // A place for subclasses to add extra widgets
2432- Item {
2433- id: foregroundExtra
2434- anchors.fill: parent
2435- }
2436- }
2437-
2438- states: State {
2439- name: "errorState"
2440- when: errorTimer.running
2441- PropertyChanges { target: titleLabel; opacity: 0 }
2442- PropertyChanges { target: textLabel; opacity: 0 }
2443- PropertyChanges { target: errorTitleLabel; opacity: 1 }
2444- PropertyChanges { target: errorTextLabel; opacity: 1 }
2445- }
2446-
2447- transitions: Transition {
2448- to: "errorState"
2449- reversible: true
2450- SequentialAnimation {
2451- ParallelAnimation {
2452- StandardAnimation {
2453- target: titleLabel
2454- property: "opacity"
2455- duration: UbuntuAnimation.BriskDuration
2456- }
2457- StandardAnimation {
2458- target: textLabel
2459- property: "opacity"
2460- duration: UbuntuAnimation.BriskDuration
2461- }
2462- }
2463- ParallelAnimation {
2464- StandardAnimation {
2465- target: errorTitleLabel
2466- property: "opacity"
2467- duration: UbuntuAnimation.BriskDuration
2468- }
2469- StandardAnimation {
2470- target: errorTextLabel
2471- property: "opacity"
2472- duration: UbuntuAnimation.BriskDuration
2473- }
2474- }
2475- }
2476+ Image {
2477+ id: background
2478+ // Use x/y/height/width instead of anchors so that we don't adjust
2479+ // the image if the OSK appears.
2480+ x: 0
2481+ y: 0
2482+ height: root.height
2483+ width: root.width
2484+ fillMode: Image.PreserveAspectCrop
2485+ }
2486+
2487+ Image {
2488+ id: arrow
2489+ width: units.gu(1.5)
2490+ source: Qt.resolvedUrl("graphics/arrow.svg")
2491+ fillMode: Image.PreserveAspectFit
2492+ mipmap: true
2493+ }
2494+
2495+ Label {
2496+ id: label
2497+ objectName: "tutorialLabel"
2498+ fontSize: "large"
2499+ font.weight: Font.Light
2500+ color: "#333333"
2501+ wrapMode: Text.Wrap
2502+ lineHeight: 1.2
2503 }
2504 }
2505
2506=== added file 'qml/Tutorial/TutorialRight.qml'
2507--- qml/Tutorial/TutorialRight.qml 1970-01-01 00:00:00 +0000
2508+++ qml/Tutorial/TutorialRight.qml 2016-03-10 17:24:40 +0000
2509@@ -0,0 +1,61 @@
2510+/*
2511+ * Copyright (C) 2015 Canonical, Ltd.
2512+ *
2513+ * This program is free software; you can redistribute it and/or modify
2514+ * it under the terms of the GNU General Public License as published by
2515+ * the Free Software Foundation; version 3.
2516+ *
2517+ * This program is distributed in the hope that it will be useful,
2518+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2519+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2520+ * GNU General Public License for more details.
2521+ *
2522+ * You should have received a copy of the GNU General Public License
2523+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2524+ */
2525+
2526+import QtQuick 2.4
2527+import Ubuntu.Components 1.3
2528+
2529+TutorialPage {
2530+ id: root
2531+
2532+ property var stage
2533+ property string usageScenario
2534+
2535+ // When on phone or tablet, fade out as the drag progresses
2536+ opacityOverride: usageScenario === "desktop" ? 1 : 1 - stage.dragProgress * 2
2537+
2538+ // Else on desktop, fade out when the spread is shown
2539+ Connections {
2540+ target: usageScenario === "desktop" ? stage : null
2541+ ignoreUnknownSignals: true
2542+ onSpreadShownChanged: if (stage.spreadShown && root.shown) root.hide()
2543+ }
2544+
2545+ mouseArea {
2546+ anchors.rightMargin: stage.dragAreaWidth
2547+ }
2548+
2549+ background {
2550+ sourceSize.height: 1916
2551+ sourceSize.width: 1080
2552+ source: Qt.resolvedUrl("graphics/background1.png")
2553+ }
2554+
2555+ arrow {
2556+ anchors.right: root.right
2557+ anchors.rightMargin: units.gu(2)
2558+ anchors.verticalCenter: root.verticalCenter
2559+ }
2560+
2561+ label {
2562+ text: root.usageScenario === "desktop" ?
2563+ i18n.tr("Hover your mouse on the right edge to view your open apps") :
2564+ i18n.tr("Short or long swipe from the right edge to view your open apps")
2565+ anchors.right: arrow.left
2566+ anchors.rightMargin: units.gu(2) - (label.width - label.contentWidth)
2567+ anchors.verticalCenter: arrow.verticalCenter
2568+ width: Math.min(units.gu(40), arrow.x - units.gu(4))
2569+ }
2570+}
2571
2572=== removed file 'qml/Tutorial/TutorialRight.qml'
2573--- qml/Tutorial/TutorialRight.qml 2015-07-15 15:07:19 +0000
2574+++ qml/Tutorial/TutorialRight.qml 1970-01-01 00:00:00 +0000
2575@@ -1,223 +0,0 @@
2576-/*
2577- * Copyright (C) 2014 Canonical, Ltd.
2578- *
2579- * This program is free software; you can redistribute it and/or modify
2580- * it under the terms of the GNU General Public License as published by
2581- * the Free Software Foundation; version 3.
2582- *
2583- * This program is distributed in the hope that it will be useful,
2584- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2585- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2586- * GNU General Public License for more details.
2587- *
2588- * You should have received a copy of the GNU General Public License
2589- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2590- */
2591-
2592-import QtQuick 2.4
2593-import Ubuntu.Components 1.3
2594-import Ubuntu.Gestures 0.1
2595-import Unity.Application 0.1
2596-import "../Components"
2597-import "../Stages"
2598-import "." as LocalComponents
2599-
2600-TutorialPage {
2601- id: root
2602-
2603- property var panel
2604- property alias edgeSize: stage.dragAreaWidth
2605-
2606- title: i18n.tr("To view open apps")
2607- text: i18n.tr("Long swipe from the right edge.")
2608-
2609- textOpacity: 1 - slider.percent
2610-
2611- SequentialAnimation {
2612- id: teaseAnimation
2613- paused: running && root.paused
2614- running: !stage.dragging && stage.dragProgress === 0
2615- loops: Animation.Infinite
2616-
2617- UbuntuNumberAnimation {
2618- target: stage
2619- property: "x"
2620- to: -units.gu(2)
2621- duration: UbuntuAnimation.SleepyDuration
2622- }
2623- UbuntuNumberAnimation {
2624- target: stage
2625- property: "x"
2626- to: 0
2627- duration: UbuntuAnimation.SleepyDuration
2628- }
2629- }
2630-
2631- foreground {
2632- children: [
2633- LocalComponents.Slider {
2634- id: slider
2635- anchors {
2636- right: parent.right
2637- top: parent.top
2638- topMargin: root.textBottom + units.gu(3)
2639- }
2640- rotation: 180
2641- offset: stage.dragProgress - stage.x
2642- active: stage.dragging
2643- },
2644-
2645- // Just assume PhoneStage for now. The tablet version of the right-edge
2646- // tutorial is still being spec'd by the design team.
2647- PhoneStage {
2648- id: stage
2649- objectName: "stage"
2650- anchors.top: parent.top
2651- width: parent.width
2652- height: parent.height
2653- applicationManager: fakeAppManager
2654- color: "transparent"
2655- interactive: false
2656- altTabEnabled: false
2657- focusFirstApp: false
2658- startScale: 0.8
2659- endScale: 0.6
2660- dragAreaOverlap: -x
2661-
2662- onOpened: {
2663- overlay.show();
2664- root.textOpacity = 0;
2665- slider.visible = false;
2666- }
2667-
2668- onDraggingChanged: {
2669- if (!dragging) {
2670- if (!overlay.shown) {
2671- root.showError();
2672- }
2673- teaseAnimation.complete();
2674- }
2675- }
2676- },
2677-
2678- Showable {
2679- id: overlay
2680- objectName: "overlay"
2681- anchors.fill: parent
2682-
2683- opacity: 0
2684- shown: false
2685- showAnimation: UbuntuNumberAnimation { property: "opacity"; to: 1 }
2686-
2687- Label {
2688- anchors.top: parent.top
2689- anchors.topMargin: root.panel.panelHeight + units.gu(2)
2690- anchors.left: parent.left
2691- anchors.leftMargin: units.gu(2)
2692- anchors.right: parent.right
2693- anchors.rightMargin: units.gu(2)
2694- wrapMode: Text.Wrap
2695- horizontalAlignment: Text.AlignHCenter
2696- fontSize: "large"
2697- text: i18n.tr("View all your running tasks.")
2698- }
2699-
2700- LocalComponents.Tick {
2701- objectName: "tick"
2702- anchors.bottom: bottomOverlayText.top
2703- anchors.bottomMargin: units.gu(1)
2704- anchors.horizontalCenter: bottomOverlayText.horizontalCenter
2705- onClicked: root.hide()
2706- }
2707-
2708- Label {
2709- id: bottomOverlayText
2710- anchors.bottom: parent.bottom
2711- anchors.bottomMargin: units.gu(2)
2712- anchors.left: parent.left
2713- anchors.leftMargin: units.gu(2)
2714- anchors.right: parent.right
2715- anchors.rightMargin: units.gu(2)
2716- wrapMode: Text.Wrap
2717- horizontalAlignment: Text.AlignHCenter
2718- fontSize: "small"
2719- text: i18n.tr("Tap here to continue.")
2720- }
2721- }
2722- ]
2723- }
2724-
2725- ListModel {
2726- id: fakeAppManager
2727-
2728- readonly property string focusedApplicationId: "facebook"
2729-
2730- function focusApplication(appId) {}
2731- function requestFocusApplication(appId) {}
2732- function findApplication(appId) {return null;}
2733-
2734- signal applicationAdded(string appId)
2735- signal applicationRemoved(string appId)
2736- signal focusRequested(string appId)
2737-
2738- ListElement {
2739- appId: "facebook"
2740- fullscreen: false
2741- name: ""
2742- icon: ""
2743- state: ApplicationInfoInterface.Stopped
2744- splashTitle: ""
2745- splashImage: ""
2746- splashShowHeader: false
2747- splashColor: "transparent"
2748- splashColorHeader: "transparent"
2749- splashColorFooter: "transparent"
2750- defaultScreenshot: "../Tutorial/graphics/facebook.png"
2751- }
2752-
2753- ListElement {
2754- appId: "camera"
2755- fullscreen: false
2756- name: ""
2757- icon: ""
2758- state: ApplicationInfoInterface.Stopped
2759- splashTitle: ""
2760- splashImage: ""
2761- splashShowHeader: false
2762- splashColor: "transparent"
2763- splashColorHeader: "transparent"
2764- splashColorFooter: "transparent"
2765- defaultScreenshot: "../Tutorial/graphics/camera.png"
2766- }
2767-
2768- ListElement {
2769- appId: "gallery"
2770- fullscreen: false
2771- name: ""
2772- icon: ""
2773- state: ApplicationInfoInterface.Stopped
2774- splashTitle: ""
2775- splashImage: ""
2776- splashShowHeader: false
2777- splashColor: "transparent"
2778- splashColorHeader: "transparent"
2779- splashColorFooter: "transparent"
2780- defaultScreenshot: "../Tutorial/graphics/gallery.png"
2781- }
2782-
2783- ListElement {
2784- appId: "dialer"
2785- fullscreen: false
2786- name: ""
2787- icon: ""
2788- state: ApplicationInfoInterface.Stopped
2789- splashTitle: ""
2790- splashImage: ""
2791- splashShowHeader: false
2792- splashColor: "transparent"
2793- splashColorHeader: "transparent"
2794- splashColorFooter: "transparent"
2795- defaultScreenshot: "../Tutorial/graphics/dialer.png"
2796- }
2797- }
2798-}
2799
2800=== added file 'qml/Tutorial/TutorialTop.qml'
2801--- qml/Tutorial/TutorialTop.qml 1970-01-01 00:00:00 +0000
2802+++ qml/Tutorial/TutorialTop.qml 2016-03-10 17:24:40 +0000
2803@@ -0,0 +1,61 @@
2804+/*
2805+ * Copyright (C) 2015 Canonical, Ltd.
2806+ *
2807+ * This program is free software; you can redistribute it and/or modify
2808+ * it under the terms of the GNU General Public License as published by
2809+ * the Free Software Foundation; version 3.
2810+ *
2811+ * This program is distributed in the hope that it will be useful,
2812+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2813+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2814+ * GNU General Public License for more details.
2815+ *
2816+ * You should have received a copy of the GNU General Public License
2817+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2818+ */
2819+
2820+import QtQuick 2.4
2821+import Ubuntu.Components 1.3
2822+import "." as LocalComponents
2823+
2824+TutorialPage {
2825+ id: root
2826+
2827+ property var panel
2828+
2829+ opacityOverride: 1 - panel.indicators.unitProgress
2830+
2831+ QtObject {
2832+ id: d
2833+ readonly property bool landscape: root.width > units.gu(50)
2834+ readonly property real columnWidth: landscape ? panel.indicators.width : root.width
2835+ }
2836+
2837+ mouseArea {
2838+ anchors.topMargin: panel.indicators.minimizedPanelHeight
2839+ }
2840+
2841+ background {
2842+ sourceSize.height: 1916
2843+ sourceSize.width: 1080
2844+ source: Qt.resolvedUrl("graphics/background2.png")
2845+ }
2846+
2847+ arrow {
2848+ anchors.top: root.top
2849+ anchors.topMargin: units.gu(4)
2850+ anchors.horizontalCenter: root.right
2851+ anchors.horizontalCenterOffset: - d.columnWidth / 2
2852+ rotation: -90
2853+ }
2854+
2855+ label {
2856+ text: d.landscape ? i18n.tr("Swipe from the top right edge to open the notification bar")
2857+ : i18n.tr("Swipe from the top edge to open the notification bar")
2858+ anchors.top: arrow.bottom
2859+ anchors.topMargin: units.gu(3)
2860+ anchors.horizontalCenter: arrow.horizontalCenter
2861+ anchors.horizontalCenterOffset: (label.width - label.contentWidth) / 2
2862+ width: d.columnWidth - units.gu(8)
2863+ }
2864+}
2865
2866=== added file 'qml/Tutorial/graphics/arrow.svg'
2867--- qml/Tutorial/graphics/arrow.svg 1970-01-01 00:00:00 +0000
2868+++ qml/Tutorial/graphics/arrow.svg 2016-03-10 17:24:40 +0000
2869@@ -0,0 +1,19 @@
2870+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2871+<svg width="35px" height="106px" viewBox="0 0 35 106" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
2872+ <!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
2873+ <title>left swipe arrow</title>
2874+ <desc>Created with Sketch.</desc>
2875+ <defs></defs>
2876+ <g id="Final-design" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
2877+ <g id="1.Left-swipe" sketch:type="MSArtboardGroup" transform="translate(-54.000000, -906.000000)">
2878+ <g id="left-swipe-arrow" sketch:type="MSLayerGroup" transform="translate(15.000000, 903.000000)">
2879+ <g id="layer1" transform="translate(0.857146, 0.494959)" sketch:type="MSShapeGroup">
2880+ <g id="g4216" transform="translate(0.952384, 0.831650)">
2881+ <path d="M38.0127338,5.94292186 C40.8696258,9.70328846 43.6961579,13.5492607 46.4521869,17.5776877 C50.0756129,22.8738077 53.4767719,28.2917937 56.6611719,33.8315937 C60.6031619,40.9214757 64.3797399,47.5658927 67.7217189,54.6714377 C64.3797399,61.7769828 60.6031619,68.4213998 56.6611719,75.5112818 C53.4767719,81.0510808 50.0756129,86.4690678 46.4521869,91.7651878 C43.6961579,95.7936138 40.8696258,99.6395938 38.0127338,103.399951 L38.0127338,107.669481 C42.0030779,102.508161 45.9748129,97.3405748 49.5537499,92.0679218 C54.5609019,84.6937758 59.0395839,77.5443828 62.9990629,70.6226098 C66.5019159,64.4983168 69.0866949,59.3452977 71.2158589,54.6733907 L69.4678129,54.6713907 L71.2158589,54.6693907 C69.0866949,49.9975777 66.5019159,44.8445587 62.9990629,38.7202657 C59.0395839,31.7984927 54.5609019,24.6490997 49.5537499,17.2749527 C45.9748129,12.0022997 42.0030779,6.83471186 38.0127338,1.67339065 L38.0127338,5.94292186 Z" id="left-swipe-arrow" fill="#6C0D52" transform="translate(54.614296, 54.671436) scale(-1, 1) translate(-54.614296, -54.671436) "></path>
2882+ <rect id="rect4782-01" transform="translate(54.190469, 54.673389) rotate(90.000000) translate(-54.190469, -54.673389) " x="0.190470662" y="0.67339065" width="107.999997" height="107.999997"></rect>
2883+ </g>
2884+ </g>
2885+ </g>
2886+ </g>
2887+ </g>
2888+</svg>
2889\ No newline at end of file
2890
2891=== added file 'qml/Tutorial/graphics/background1.png'
2892Binary files qml/Tutorial/graphics/background1.png 1970-01-01 00:00:00 +0000 and qml/Tutorial/graphics/background1.png 2016-03-10 17:24:40 +0000 differ
2893=== added file 'qml/Tutorial/graphics/background2.png'
2894Binary files qml/Tutorial/graphics/background2.png 1970-01-01 00:00:00 +0000 and qml/Tutorial/graphics/background2.png 2016-03-10 17:24:40 +0000 differ
2895=== removed file 'qml/Tutorial/graphics/camera.png'
2896Binary files qml/Tutorial/graphics/camera.png 2015-01-09 21:56:17 +0000 and qml/Tutorial/graphics/camera.png 1970-01-01 00:00:00 +0000 differ
2897=== removed file 'qml/Tutorial/graphics/chevron.png'
2898Binary files qml/Tutorial/graphics/chevron.png 2014-12-18 23:32:42 +0000 and qml/Tutorial/graphics/chevron.png 1970-01-01 00:00:00 +0000 differ
2899=== removed file 'qml/Tutorial/graphics/dialer.png'
2900Binary files qml/Tutorial/graphics/dialer.png 2015-01-09 21:56:17 +0000 and qml/Tutorial/graphics/dialer.png 1970-01-01 00:00:00 +0000 differ
2901=== removed file 'qml/Tutorial/graphics/facebook.png'
2902Binary files qml/Tutorial/graphics/facebook.png 2015-01-12 14:02:33 +0000 and qml/Tutorial/graphics/facebook.png 1970-01-01 00:00:00 +0000 differ
2903=== removed file 'qml/Tutorial/graphics/gallery.png'
2904Binary files qml/Tutorial/graphics/gallery.png 2015-01-09 21:56:17 +0000 and qml/Tutorial/graphics/gallery.png 1970-01-01 00:00:00 +0000 differ
2905=== removed file 'qml/Tutorial/graphics/tick.png'
2906Binary files qml/Tutorial/graphics/tick.png 2014-12-18 23:32:42 +0000 and qml/Tutorial/graphics/tick.png 1970-01-01 00:00:00 +0000 differ
2907=== modified file 'tests/autopilot/unity8/shell/emulators.py'
2908--- tests/autopilot/unity8/shell/emulators.py 2015-04-29 19:21:18 +0000
2909+++ tests/autopilot/unity8/shell/emulators.py 2016-03-10 17:24:40 +0000
2910@@ -36,7 +36,6 @@
2911 'greeter',
2912 'launcher',
2913 'main_window',
2914- 'tutorial',
2915 'UnityEmulatorException',
2916 ]
2917
2918@@ -46,7 +45,6 @@
2919 dash,
2920 launcher,
2921 shell as main_window,
2922- tutorial,
2923 UnityException as UnityEmulatorException
2924 )
2925 from unity8.shell import create_interactive_notification
2926
2927=== removed file 'tests/autopilot/unity8/shell/tests/test_tutorial.py'
2928--- tests/autopilot/unity8/shell/tests/test_tutorial.py 2015-04-29 19:21:18 +0000
2929+++ tests/autopilot/unity8/shell/tests/test_tutorial.py 1970-01-01 00:00:00 +0000
2930@@ -1,57 +0,0 @@
2931-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2932-#
2933-# Unity Autopilot Test Suite
2934-# Copyright (C) 2014, 2015 Canonical
2935-#
2936-# This program is free software: you can redistribute it and/or modify
2937-# it under the terms of the GNU General Public License as published by
2938-# the Free Software Foundation, either version 3 of the License, or
2939-# (at your option) any later version.
2940-#
2941-# This program is distributed in the hope that it will be useful,
2942-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2943-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2944-# GNU General Public License for more details.
2945-#
2946-# You should have received a copy of the GNU General Public License
2947-# along with this program. If not, see <http://www.gnu.org/licenses/>.
2948-#
2949-
2950-from autopilot.matchers import Eventually
2951-from testtools.matchers import Equals
2952-
2953-from unity8.shell import (
2954- fixture_setup,
2955- tests
2956-)
2957-# unused import to load the tutorial helpers custom proxy objects.
2958-from unity8 import tutorial as tutorial_helpers # NOQA
2959-
2960-
2961-class TutorialTestCase(tests.UnityTestCase):
2962-
2963- def setUp(self):
2964- super().setUp()
2965- self._qml_mock_enabled = False
2966- self._data_dirs_mock_enabled = False
2967-
2968- self.useFixture(fixture_setup.Tutorial(True))
2969- self.unity = self.launch_unity()
2970-
2971- def test_complete_tutorial(self):
2972- greeter = self.main_window.get_greeter()
2973- tutorial = self.unity.select_single('Tutorial')
2974- self.assertThat(tutorial.running, Eventually(Equals(True)))
2975- greeter.swipe()
2976- page = self.unity.wait_select_single(objectName='tutorialLeft')
2977- page.short_swipe_right()
2978- page = self.unity.wait_select_single(objectName='tutorialLeftFinish')
2979- page.tap()
2980- page = self.unity.wait_select_single(objectName='tutorialRight')
2981- page.swipe_left()
2982- page.tap()
2983- page = self.unity.wait_select_single(objectName='tutorialBottom')
2984- page.swipe_up()
2985- page = self.unity.wait_select_single(objectName='tutorialBottomFinish')
2986- page.tap()
2987- self.assertThat(tutorial.running, Eventually(Equals(False)))
2988
2989=== removed file 'tests/autopilot/unity8/tutorial.py'
2990--- tests/autopilot/unity8/tutorial.py 2015-04-29 19:21:18 +0000
2991+++ tests/autopilot/unity8/tutorial.py 1970-01-01 00:00:00 +0000
2992@@ -1,73 +0,0 @@
2993-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2994-#
2995-# Unity Autopilot Test Suite
2996-# Copyright (C) 2014 Canonical
2997-#
2998-# This program is free software: you can redistribute it and/or modify
2999-# it under the terms of the GNU General Public License as published by
3000-# the Free Software Foundation, either version 3 of the License, or
3001-# (at your option) any later version.
3002-#
3003-# This program is distributed in the hope that it will be useful,
3004-# but WITHOUT ANY WARRANTY; without even the implied warranty of
3005-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3006-# GNU General Public License for more details.
3007-#
3008-# You should have received a copy of the GNU General Public License
3009-# along with this program. If not, see <http://www.gnu.org/licenses/>.
3010-#
3011-
3012-import logging
3013-
3014-import ubuntuuitoolkit
3015-
3016-import autopilot
3017-from autopilot import introspection
3018-
3019-
3020-logger = logging.getLogger(__name__)
3021-
3022-
3023-class TutorialPage(
3024- ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
3025-
3026- @classmethod
3027- def validate_dbus_object(cls, path, state):
3028- name = introspection.get_classname_from_path(path)
3029- return name in (b'TutorialPage', b'TutorialLeft',
3030- b'TutorialLeftFinish', b'TutorialRight',
3031- b'TutorialBottom', b'TutorialBottomFinish')
3032-
3033- @autopilot.logging.log_action(logger.info)
3034- def short_swipe_right(self):
3035- self.shown.wait_for(True)
3036- x, y, width, height = self.globalRect
3037- start_x = x
3038- stop_x = x + width // 3
3039- start_y = stop_y = y + height // 2
3040- self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
3041-
3042- @autopilot.logging.log_action(logger.info)
3043- def swipe_left(self):
3044- self.shown.wait_for(True)
3045- x, y, width, height = self.globalRect
3046- start_x = width
3047- stop_x = x
3048- start_y = stop_y = y + height // 2
3049- self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
3050-
3051- @autopilot.logging.log_action(logger.info)
3052- def swipe_up(self):
3053- self.shown.wait_for(True)
3054- x, y, width, height = self.globalRect
3055- start_y = height
3056- stop_y = y
3057- start_x = stop_x = x + width // 2
3058- self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
3059-
3060- @autopilot.logging.log_action(logger.info)
3061- def tap(self):
3062- """Tap the tick button to complete this step."""
3063- self.shown.wait_for(True)
3064- button = self.wait_select_single(objectName="tick")
3065- self.pointing_device.click_object(button)
3066
3067=== modified file 'tests/mocks/AccountsService/AccountsService.cpp'
3068--- tests/mocks/AccountsService/AccountsService.cpp 2015-09-22 10:44:21 +0000
3069+++ tests/mocks/AccountsService/AccountsService.cpp 2016-03-10 17:24:40 +0000
3070@@ -28,6 +28,7 @@
3071 m_statsWelcomeScreen(true),
3072 m_failedLogins(0),
3073 m_demoEdges(false),
3074+ m_demoEdgesCompleted(),
3075 m_hereEnabled(false),
3076 m_hereLicensePath("")
3077 {
3078@@ -56,6 +57,25 @@
3079 Q_EMIT demoEdgesChanged();
3080 }
3081
3082+QStringList AccountsService::demoEdgesCompleted() const
3083+{
3084+ return m_demoEdgesCompleted;
3085+}
3086+
3087+void AccountsService::markDemoEdgeCompleted(const QString &edge)
3088+{
3089+ if (!m_demoEdgesCompleted.contains(edge)) {
3090+ m_demoEdgesCompleted << edge;
3091+ Q_EMIT demoEdgesCompletedChanged();
3092+ }
3093+}
3094+
3095+void AccountsService::setDemoEdgesCompleted(const QStringList &demoEdgesCompleted)
3096+{
3097+ m_demoEdgesCompleted = demoEdgesCompleted;
3098+ Q_EMIT demoEdgesCompletedChanged();
3099+}
3100+
3101 bool AccountsService::enableLauncherWhileLocked() const
3102 {
3103 return m_enableLauncherWhileLocked;
3104
3105=== modified file 'tests/mocks/AccountsService/AccountsService.h'
3106--- tests/mocks/AccountsService/AccountsService.h 2014-11-24 17:42:36 +0000
3107+++ tests/mocks/AccountsService/AccountsService.h 2016-03-10 17:24:40 +0000
3108@@ -22,6 +22,7 @@
3109
3110 #include <QObject>
3111 #include <QString>
3112+#include <QStringList>
3113 #include <QVariant>
3114
3115 class AccountsService: public QObject
3116@@ -36,6 +37,10 @@
3117 READ demoEdges
3118 WRITE setDemoEdges
3119 NOTIFY demoEdgesChanged)
3120+ Q_PROPERTY (QStringList demoEdgesCompleted
3121+ READ demoEdgesCompleted
3122+ WRITE setDemoEdgesCompleted // only available in mock
3123+ NOTIFY demoEdgesCompletedChanged)
3124 Q_PROPERTY (bool enableLauncherWhileLocked
3125 READ enableLauncherWhileLocked
3126 WRITE setEnableLauncherWhileLocked // only available in mock
3127@@ -83,6 +88,9 @@
3128 void setUser(const QString &user);
3129 bool demoEdges() const;
3130 void setDemoEdges(bool demoEdges);
3131+ QStringList demoEdgesCompleted() const;
3132+ void setDemoEdgesCompleted(const QStringList &demoEdges);
3133+ Q_INVOKABLE void markDemoEdgeCompleted(const QString &edge);
3134 bool enableLauncherWhileLocked() const;
3135 void setEnableLauncherWhileLocked(bool enableLauncherWhileLocked);
3136 bool enableIndicatorsWhileLocked() const;
3137@@ -103,6 +111,7 @@
3138 Q_SIGNALS:
3139 void userChanged();
3140 void demoEdgesChanged();
3141+ void demoEdgesCompletedChanged();
3142 void enableLauncherWhileLockedChanged();
3143 void enableIndicatorsWhileLockedChanged();
3144 void backgroundFileChanged();
3145@@ -120,6 +129,7 @@
3146 bool m_statsWelcomeScreen;
3147 uint m_failedLogins;
3148 bool m_demoEdges;
3149+ QStringList m_demoEdgesCompleted;
3150 bool m_hereEnabled;
3151 QString m_hereLicensePath;
3152 };
3153
3154=== modified file 'tests/mocks/AccountsService/AccountsService.qmltypes'
3155--- tests/mocks/AccountsService/AccountsService.qmltypes 2015-02-13 09:01:16 +0000
3156+++ tests/mocks/AccountsService/AccountsService.qmltypes 2016-03-10 17:24:40 +0000
3157@@ -23,6 +23,7 @@
3158 }
3159 Property { name: "user"; type: "string" }
3160 Property { name: "demoEdges"; type: "bool" }
3161+ Property { name: "demoEdgesCompleted"; type: "QStringList" }
3162 Property { name: "enableLauncherWhileLocked"; type: "bool" }
3163 Property { name: "enableIndicatorsWhileLocked"; type: "bool" }
3164 Property { name: "backgroundFile"; type: "string" }
3165@@ -32,5 +33,9 @@
3166 Property { name: "hereEnabled"; type: "bool" }
3167 Property { name: "hereLicensePath"; type: "string" }
3168 Property { name: "hereLicensePathValid"; type: "bool"; isReadonly: true }
3169+ Method {
3170+ name: "markDemoEdgeCompleted"
3171+ Parameter { name: "edge"; type: "string" }
3172+ }
3173 }
3174 }
3175
3176=== modified file 'tests/mocks/Unity/Application/ApplicationInfo.h'
3177--- tests/mocks/Unity/Application/ApplicationInfo.h 2016-01-19 21:41:34 +0000
3178+++ tests/mocks/Unity/Application/ApplicationInfo.h 2016-03-10 17:24:40 +0000
3179@@ -59,7 +59,7 @@
3180
3181 QUrl icon() const override { return m_icon; }
3182
3183- void setStage(Stage value);
3184+ Q_INVOKABLE void setStage(Stage value); // invokable only for mock
3185 Stage stage() const override { return m_stage; }
3186
3187 Q_INVOKABLE void setState(State value);
3188
3189=== modified file 'tests/mocks/Unity/Application/MirSurface.cpp'
3190--- tests/mocks/Unity/Application/MirSurface.cpp 2015-11-30 18:25:47 +0000
3191+++ tests/mocks/Unity/Application/MirSurface.cpp 2016-03-10 17:24:40 +0000
3192@@ -22,8 +22,9 @@
3193 Mir::Type type,
3194 Mir::State state,
3195 const QUrl& screenshot,
3196- const QUrl &qmlFilePath)
3197- : unity::shell::application::MirSurfaceInterface(nullptr)
3198+ const QUrl &qmlFilePath,
3199+ QObject *parent)
3200+ : unity::shell::application::MirSurfaceInterface(parent)
3201 , m_name(name)
3202 , m_type(type)
3203 , m_state(state)
3204
3205=== modified file 'tests/mocks/Unity/Application/MirSurface.h'
3206--- tests/mocks/Unity/Application/MirSurface.h 2015-11-30 18:25:47 +0000
3207+++ tests/mocks/Unity/Application/MirSurface.h 2016-03-10 17:24:40 +0000
3208@@ -41,7 +41,8 @@
3209 Mir::Type type,
3210 Mir::State state,
3211 const QUrl& screenshot,
3212- const QUrl &qmlFilePath = QUrl());
3213+ const QUrl &qmlFilePath = QUrl(),
3214+ QObject *parent = nullptr);
3215 virtual ~MirSurface();
3216
3217 ////
3218
3219=== modified file 'tests/mocks/Unity/Application/SurfaceManager.cpp'
3220--- tests/mocks/Unity/Application/SurfaceManager.cpp 2015-11-30 18:25:47 +0000
3221+++ tests/mocks/Unity/Application/SurfaceManager.cpp 2016-03-10 17:24:40 +0000
3222@@ -34,6 +34,13 @@
3223 QObject(parent)
3224 , m_virtualKeyboard(nullptr)
3225 {
3226+ m_virtualKeyboard = new VirtualKeyboard(this);
3227+ connect(m_virtualKeyboard, &QObject::destroyed, this, [this](QObject *obj) {
3228+ MirSurface* surface = qobject_cast<MirSurface*>(obj);
3229+ m_virtualKeyboard = nullptr;
3230+ Q_EMIT inputMethodSurfaceChanged();
3231+ Q_EMIT surfaceDestroyed(surface);
3232+ });
3233 }
3234
3235 MirSurface *SurfaceManager::createSurface(const QString& name,
3236@@ -58,16 +65,8 @@
3237 return surface;
3238 }
3239
3240-MirSurface *SurfaceManager::inputMethodSurface()
3241+MirSurface *SurfaceManager::inputMethodSurface() const
3242 {
3243- if (!m_virtualKeyboard) {
3244- m_virtualKeyboard = new VirtualKeyboard;
3245- connect(m_virtualKeyboard, &QObject::destroyed, this, [this](QObject *obj) {
3246- MirSurface* surface = qobject_cast<MirSurface*>(obj);
3247- Q_EMIT surfaceDestroyed(surface);
3248- });
3249- Q_EMIT surfaceCreated(m_virtualKeyboard);
3250- }
3251 return m_virtualKeyboard;
3252 }
3253
3254
3255=== modified file 'tests/mocks/Unity/Application/SurfaceManager.h'
3256--- tests/mocks/Unity/Application/SurfaceManager.h 2015-11-30 18:25:47 +0000
3257+++ tests/mocks/Unity/Application/SurfaceManager.h 2016-03-10 17:24:40 +0000
3258@@ -25,7 +25,7 @@
3259 class SurfaceManager : public QObject
3260 {
3261 Q_OBJECT
3262-
3263+ Q_PROPERTY(MirSurface* inputMethodSurface READ inputMethodSurface NOTIFY inputMethodSurfaceChanged)
3264 Q_PROPERTY(int newSurfaceMinimumWidth READ newSurfaceMinimumWidth WRITE setNewSurfaceMinimumWidth NOTIFY newSurfaceMinimumWidthChanged)
3265 Q_PROPERTY(int newSurfaceMaximumWidth READ newSurfaceMaximumWidth WRITE setNewSurfaceMaximumWidth NOTIFY newSurfaceMaximumWidthChanged)
3266 Q_PROPERTY(int newSurfaceMinimumHeight READ newSurfaceMinimumHeight WRITE setNewSurfaceMinimumHeight NOTIFY newSurfaceMinimumHeightChanged)
3267@@ -43,8 +43,7 @@
3268 Mir::State state,
3269 const QUrl& screenshot);
3270
3271- // To be used in the tests
3272- Q_INVOKABLE MirSurface* inputMethodSurface();
3273+ MirSurface* inputMethodSurface() const;
3274
3275 int newSurfaceMinimumWidth() const { return m_newSurfaceMinimumWidth; }
3276 void setNewSurfaceMinimumWidth(int value);
3277@@ -65,6 +64,7 @@
3278 void setNewSurfaceHeightIncrement(int);
3279
3280 Q_SIGNALS:
3281+ void inputMethodSurfaceChanged();
3282 void countChanged();
3283 void surfaceCreated(MirSurface *surface);
3284 void surfaceDestroyed(MirSurface*surface);
3285
3286=== modified file 'tests/mocks/Unity/Application/VirtualKeyboard.cpp'
3287--- tests/mocks/Unity/Application/VirtualKeyboard.cpp 2015-09-02 10:35:16 +0000
3288+++ tests/mocks/Unity/Application/VirtualKeyboard.cpp 2016-03-10 17:24:40 +0000
3289@@ -22,12 +22,13 @@
3290
3291 #include <QDebug>
3292
3293-VirtualKeyboard::VirtualKeyboard()
3294+VirtualKeyboard::VirtualKeyboard(QObject *parent)
3295 : MirSurface("input-method",
3296 Mir::InputMethodType,
3297 Mir::MinimizedState,
3298 QUrl("qrc:///Unity/Application/vkb_portrait.png"),
3299- QUrl("qrc:///Unity/Application/VirtualKeyboard.qml"))
3300+ QUrl("qrc:///Unity/Application/VirtualKeyboard.qml"),
3301+ parent)
3302 {
3303 }
3304
3305
3306=== modified file 'tests/mocks/Unity/Application/VirtualKeyboard.h'
3307--- tests/mocks/Unity/Application/VirtualKeyboard.h 2015-08-19 20:30:09 +0000
3308+++ tests/mocks/Unity/Application/VirtualKeyboard.h 2016-03-10 17:24:40 +0000
3309@@ -25,7 +25,7 @@
3310 {
3311 Q_OBJECT
3312 public:
3313- explicit VirtualKeyboard();
3314+ explicit VirtualKeyboard(QObject *parent = nullptr);
3315 ~VirtualKeyboard();
3316 };
3317
3318
3319=== modified file 'tests/mocks/Unity/Application/plugin.cpp'
3320--- tests/mocks/Unity/Application/plugin.cpp 2015-08-03 15:00:47 +0000
3321+++ tests/mocks/Unity/Application/plugin.cpp 2016-03-10 17:24:40 +0000
3322@@ -78,8 +78,9 @@
3323 qmlRegisterUncreatableType<unity::shell::application::ApplicationInfoInterface>(uri, 0, 1, "ApplicationInfoInterface", "Abstract interface. Cannot be created in QML");
3324 qmlRegisterUncreatableType<Session>(uri, 0, 1, "Session", "Session can't be instantiated from QML");
3325 qmlRegisterUncreatableType<MirSurface>(uri, 0, 1, "MirSurface", "MirSurface can't be instantiated from QML");
3326+ qmlRegisterUncreatableType<unity::shell::application::MirSurfaceInterface>(
3327+ uri, 0, 1, "MirSurface", "MirSurface can't be instantiated from QML");
3328 qmlRegisterType<MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem");
3329-
3330 qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");
3331
3332 qmlRegisterSingletonType<ApplicationManager>(uri, 0, 1, "ApplicationManager", applicationManagerSingleton);
3333
3334=== modified file 'tests/mocks/Utils/CMakeLists.txt'
3335--- tests/mocks/Utils/CMakeLists.txt 2016-02-08 09:37:48 +0000
3336+++ tests/mocks/Utils/CMakeLists.txt 2016-03-10 17:24:40 +0000
3337@@ -12,7 +12,7 @@
3338 ${CMAKE_SOURCE_DIR}/plugins/Utils/qlimitproxymodelqml.cpp
3339 ${CMAKE_SOURCE_DIR}/plugins/Utils/unitysortfilterproxymodelqml.cpp
3340 ${CMAKE_SOURCE_DIR}/plugins/Utils/unitymenumodelpaths.cpp
3341- ${CMAKE_SOURCE_DIR}/plugins/Utils/windowkeysfilter.cpp
3342+ ${CMAKE_SOURCE_DIR}/plugins/Utils/windowinputfilter.cpp
3343 ${CMAKE_SOURCE_DIR}/plugins/Utils/windowscreenshotprovider.cpp
3344 ${CMAKE_SOURCE_DIR}/plugins/Utils/easingcurve.cpp
3345 ${CMAKE_SOURCE_DIR}/plugins/Utils/inputwatcher.cpp
3346
3347=== modified file 'tests/mocks/Utils/Utils.qmltypes'
3348--- tests/mocks/Utils/Utils.qmltypes 2015-07-15 11:37:23 +0000
3349+++ tests/mocks/Utils/Utils.qmltypes 2016-03-10 17:24:40 +0000
3350@@ -145,10 +145,10 @@
3351 }
3352 }
3353 Component {
3354- name: "WindowKeysFilter"
3355+ name: "WindowInputFilter"
3356 defaultProperty: "data"
3357 prototype: "QQuickItem"
3358- exports: ["Utils/WindowKeysFilter 0.1"]
3359+ exports: ["Utils/WindowInputFilter 0.1"]
3360 exportMetaObjectRevisions: [0]
3361 }
3362 Component {
3363
3364=== modified file 'tests/mocks/Utils/plugin.cpp'
3365--- tests/mocks/Utils/plugin.cpp 2016-01-13 17:52:51 +0000
3366+++ tests/mocks/Utils/plugin.cpp 2016-03-10 17:24:40 +0000
3367@@ -32,7 +32,7 @@
3368 #include <qlimitproxymodelqml.h>
3369 #include <unitysortfilterproxymodelqml.h>
3370 #include <unitymenumodelpaths.h>
3371-#include <windowkeysfilter.h>
3372+#include <windowinputfilter.h>
3373 #include <windowscreenshotprovider.h>
3374 #include <easingcurve.h>
3375 #include <applicationsfiltermodel.h>
3376@@ -59,7 +59,7 @@
3377 qmlRegisterType<QLimitProxyModelQML>(uri, 0, 1, "LimitProxyModel");
3378 qmlRegisterType<UnitySortFilterProxyModelQML>(uri, 0, 1, "UnitySortFilterProxyModel");
3379 qmlRegisterType<UnityMenuModelPaths>(uri, 0, 1, "UnityMenuModelPaths");
3380- qmlRegisterType<WindowKeysFilter>(uri, 0, 1, "WindowKeysFilter");
3381+ qmlRegisterType<WindowInputFilter>(uri, 0, 1, "WindowInputFilter");
3382 qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
3383 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
3384 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
3385
3386=== modified file 'tests/plugins/AccountsService/PropertiesServer.cpp'
3387--- tests/plugins/AccountsService/PropertiesServer.cpp 2015-10-26 14:05:14 +0000
3388+++ tests/plugins/AccountsService/PropertiesServer.cpp 2016-03-10 17:24:40 +0000
3389@@ -79,6 +79,7 @@
3390 void PropertiesServer::Reset()
3391 {
3392 m_properties["com.canonical.unity.AccountsService"]["demo-edges"] = false;
3393+ m_properties["com.canonical.unity.AccountsService"]["DemoEdgesCompleted"] = QStringList();
3394 m_properties["com.canonical.unity.AccountsService"]["LauncherItems"] = QVariant::fromValue(QList<QVariantMap>());
3395 m_properties["com.canonical.unity.AccountsService.Private"]["FailedLogins"] = 0;
3396 m_properties["com.ubuntu.touch.AccountsService.SecurityPrivacy"]["StatsWelcomeScreen"] = true;
3397
3398=== modified file 'tests/plugins/AccountsService/client.cpp'
3399--- tests/plugins/AccountsService/client.cpp 2015-10-26 14:05:14 +0000
3400+++ tests/plugins/AccountsService/client.cpp 2016-03-10 17:24:40 +0000
3401@@ -107,6 +107,43 @@
3402 QCOMPARE(session.hereEnabled(), true);
3403 }
3404
3405+ void testMarkDemoEdgeCompleted()
3406+ {
3407+ AccountsService session(this, QTest::currentTestFunction());
3408+ QSignalSpy changedSpy(&session, &AccountsService::demoEdgesCompletedChanged);
3409+
3410+ QCOMPARE(changedSpy.count(), 0);
3411+ QCOMPARE(session.demoEdgesCompleted(), QStringList());
3412+
3413+ session.markDemoEdgeCompleted("testedge");
3414+ QCOMPARE(changedSpy.count(), 1);
3415+ QCOMPARE(session.demoEdgesCompleted(), QStringList() << "testedge");
3416+
3417+ session.markDemoEdgeCompleted("testedge");
3418+ QCOMPARE(changedSpy.count(), 1);
3419+ QCOMPARE(session.demoEdgesCompleted(), QStringList() << "testedge");
3420+
3421+ session.markDemoEdgeCompleted("testedge2");
3422+ QCOMPARE(changedSpy.count(), 2);
3423+ QCOMPARE(session.demoEdgesCompleted(), QStringList() << "testedge" << "testedge2");
3424+ }
3425+
3426+ void testAsynchronousChangeForDemoEdgesCompleted()
3427+ {
3428+ AccountsService session(this, QTest::currentTestFunction());
3429+ QSignalSpy changedSpy(&session, &AccountsService::demoEdgesCompletedChanged);
3430+
3431+ QCOMPARE(changedSpy.count(), 0);
3432+ QCOMPARE(session.demoEdgesCompleted(), QStringList());
3433+
3434+ ASSERT_DBUS_CALL(m_userInterface->call("Set",
3435+ "com.canonical.unity.AccountsService",
3436+ "DemoEdgesCompleted",
3437+ dbusVariant(QStringList() << "testedge")));
3438+ QTRY_COMPARE(changedSpy.count(), 1);
3439+ QCOMPARE(session.demoEdgesCompleted(), QStringList() << "testedge");
3440+ }
3441+
3442 void testAsynchornousChangeForDemoEdges()
3443 {
3444 AccountsService session(this, QTest::currentTestFunction());
3445
3446=== modified file 'tests/qmltests/Components/tst_PhysicalKeysMapper.qml'
3447--- tests/qmltests/Components/tst_PhysicalKeysMapper.qml 2016-01-15 10:21:18 +0000
3448+++ tests/qmltests/Components/tst_PhysicalKeysMapper.qml 2016-03-10 17:24:40 +0000
3449@@ -26,9 +26,9 @@
3450
3451 property var physicalKeysMapper: loader.item
3452
3453- WindowKeysFilter {
3454- Keys.onPressed: physicalKeysMapper.onKeyPressed(event, currentEventTimestamp);
3455- Keys.onReleased: physicalKeysMapper.onKeyReleased(event, currentEventTimestamp);
3456+ WindowInputFilter {
3457+ Keys.onPressed: physicalKeysMapper.onKeyPressed(event, lastInputTimestamp);
3458+ Keys.onReleased: physicalKeysMapper.onKeyReleased(event, lastInputTimestamp);
3459 }
3460
3461 Loader {
3462
3463=== modified file 'tests/qmltests/Greeter/tst_Greeter.qml'
3464--- tests/qmltests/Greeter/tst_Greeter.qml 2016-01-11 17:37:02 +0000
3465+++ tests/qmltests/Greeter/tst_Greeter.qml 2016-03-10 17:24:40 +0000
3466@@ -328,9 +328,15 @@
3467 LightDM.Greeter.active = true;
3468
3469 greeter.forcedUnlock = true;
3470- compare(view.locked, false);
3471+ compare(greeter.required, false);
3472 greeter.forcedUnlock = false;
3473
3474+ // Now recover from tearing down the view above
3475+ LightDM.Greeter.showGreeter();
3476+ tryCompare(greeter, "required", true);
3477+ tryCompare(greeter, "waiting", false);
3478+ view = findChild(greeter, "testView");
3479+
3480 selectUser("no-password");
3481 tryCompare(view, "locked", false);
3482 selectUser("has-password");
3483
3484=== modified file 'tests/qmltests/Tutorial/tst_Tutorial.qml'
3485--- tests/qmltests/Tutorial/tst_Tutorial.qml 2015-09-02 07:42:27 +0000
3486+++ tests/qmltests/Tutorial/tst_Tutorial.qml 2016-03-10 17:24:40 +0000
3487@@ -19,15 +19,19 @@
3488 import AccountsService 0.1
3489 import IntegratedLightDM 0.1 as LightDM
3490 import Ubuntu.Components 1.3
3491+import Ubuntu.Components.ListItems 1.3
3492+import Ubuntu.Telephony 0.1 as Telephony
3493 import Unity.Application 0.1
3494 import Unity.Test 0.1 as UT
3495
3496 import "../../../qml"
3497+import "../../../qml/Components"
3498
3499-Item {
3500+Rectangle {
3501 id: root
3502- width: shellLoader.width + buttons.width
3503- height: shellLoader.height
3504+ color: UbuntuColors.lightGrey
3505+ width: units.gu(100) + buttons.width
3506+ height: units.gu(71)
3507
3508 QtObject {
3509 id: applicationArguments
3510@@ -45,6 +49,11 @@
3511 }
3512 }
3513
3514+ Telephony.CallEntry {
3515+ id: phoneCall
3516+ phoneNumber: "+447812221111"
3517+ }
3518+
3519 Component.onCompleted: {
3520 // must set the mock mode before loading the Shell
3521 LightDM.Greeter.mockMode = "single-pin";
3522@@ -52,21 +61,63 @@
3523 shellLoader.active = true;
3524 }
3525
3526- Row {
3527- spacing: 0
3528- anchors.fill: parent
3529+ Item {
3530+ id: shellContainer
3531+ anchors.left: root.left
3532+ anchors.right: buttons.left
3533+ anchors.top: root.top
3534+ anchors.bottom: root.bottom
3535
3536 Loader {
3537 id: shellLoader
3538
3539 active: false
3540- width: units.gu(40)
3541- height: units.gu(71)
3542+ anchors.horizontalCenter: parent.horizontalCenter
3543+ anchors.top: parent.top
3544+ anchors.bottom: parent.bottom
3545+
3546+ property int shellOrientation: Qt.PortraitOrientation
3547+ property int nativeOrientation: Qt.PortraitOrientation
3548+ property int primaryOrientation: Qt.PortraitOrientation
3549+
3550+ state: modeSelector.model[modeSelector.selectedIndex]
3551+ states: [
3552+ State {
3553+ name: "phone"
3554+ PropertyChanges {
3555+ target: shellLoader
3556+ width: units.gu(40)
3557+ }
3558+ },
3559+ State {
3560+ name: "tablet"
3561+ PropertyChanges {
3562+ target: shellLoader
3563+ width: units.gu(100)
3564+ shellOrientation: Qt.LandscapeOrientation
3565+ nativeOrientation: Qt.LandscapeOrientation
3566+ primaryOrientation: Qt.LandscapeOrientation
3567+ }
3568+ },
3569+ State {
3570+ name: "desktop"
3571+ PropertyChanges {
3572+ target: shellLoader
3573+ width: units.gu(100)
3574+ }
3575+ }
3576+ ]
3577
3578 property bool itemDestroyed: false
3579 sourceComponent: Component {
3580 Shell {
3581+ usageScenario: shellLoader.state
3582 property string indicatorProfile: "phone"
3583+ orientation: shellLoader.shellOrientation
3584+ orientations: Orientations {
3585+ native_: shellLoader.nativeOrientation
3586+ primary: shellLoader.primaryOrientation
3587+ }
3588
3589 Component.onDestruction: {
3590 shellLoader.itemDestroyed = true;
3591@@ -74,29 +125,92 @@
3592 }
3593 }
3594 }
3595-
3596- Rectangle {
3597- id: buttons
3598- color: "white"
3599- width: units.gu(30)
3600- height: shellLoader.height
3601-
3602- Column {
3603- anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
3604- spacing: units.gu(1)
3605- Row {
3606- anchors { left: parent.left; right: parent.right }
3607- Button {
3608- text: "Restart Tutorial"
3609- onClicked: {
3610- if (shellLoader.status !== Loader.Ready)
3611- return;
3612-
3613- AccountsService.demoEdges = false;
3614- AccountsService.demoEdges = true;
3615- }
3616- }
3617- }
3618+ }
3619+
3620+ Rectangle {
3621+ id: buttons
3622+ color: UbuntuColors.darkGrey
3623+ width: units.gu(30)
3624+ anchors.top: root.top
3625+ anchors.bottom: root.bottom
3626+ anchors.right: root.right
3627+
3628+ Column {
3629+ anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
3630+ spacing: units.gu(1)
3631+ Row {
3632+ anchors { left: parent.left; right: parent.right }
3633+ Button {
3634+ text: "Hide Greeter"
3635+ onClicked: {
3636+ if (shellLoader.status !== Loader.Ready)
3637+ return;
3638+
3639+ var greeter = testCase.findChild(shellLoader.item, "greeter");
3640+ if (greeter.shown) {
3641+ greeter.hide();
3642+ }
3643+ }
3644+ }
3645+ }
3646+
3647+ Row {
3648+ anchors { left: parent.left; right: parent.right }
3649+ Button {
3650+ text: "Restart Tutorial"
3651+ onClicked: {
3652+ if (shellLoader.status !== Loader.Ready)
3653+ return;
3654+
3655+ AccountsService.demoEdges = false;
3656+ AccountsService.demoEdgesCompleted = [];
3657+ AccountsService.demoEdges = true;
3658+ }
3659+ }
3660+ }
3661+
3662+ Row {
3663+ anchors { left: parent.left; right: parent.right }
3664+ CheckBox {
3665+ onCheckedChanged: {
3666+ if (checked) {
3667+ callManager.foregroundCall = phoneCall;
3668+ } else {
3669+ callManager.foregroundCall = null;
3670+ }
3671+ }
3672+ }
3673+ Label {
3674+ text: "Active Call"
3675+ anchors.verticalCenter: parent.verticalCenter
3676+ }
3677+ }
3678+
3679+ Row {
3680+ anchors { left: parent.left; right: parent.right }
3681+ CheckBox {
3682+ activeFocusOnPress: false
3683+ onCheckedChanged: {
3684+ var surface = SurfaceManager.inputMethodSurface;
3685+ if (checked) {
3686+ surface.setState(Mir.RestoredState);
3687+ } else {
3688+ surface.setState(Mir.MinimizedState);
3689+ }
3690+ }
3691+ }
3692+ Label {
3693+ text: "Input Method"
3694+ anchors.verticalCenter: parent.verticalCenter
3695+ }
3696+ }
3697+
3698+ ItemSelector {
3699+ id: modeSelector
3700+ anchors { left: parent.left; right: parent.right }
3701+ activeFocusOnPress: false
3702+ text: "Mode"
3703+ model: ["phone", "tablet", "desktop"]
3704 }
3705 }
3706 }
3707@@ -111,17 +225,21 @@
3708 property real halfHeight: shell ? shell.height / 2 : 0
3709
3710 function init() {
3711- tryCompare(shell, "enabled", true); // enabled by greeter when ready
3712+ prepareShell();
3713
3714- AccountsService.demoEdges = false;
3715- AccountsService.demoEdges = true;
3716- swipeAwayGreeter();
3717+ var tutorialLeft = findChild(shell, "tutorialLeft");
3718+ tryCompare(tutorialLeft, "opacity", 1);
3719 }
3720
3721 function cleanup() {
3722+ resetLoader("phone");
3723+ }
3724+
3725+ function resetLoader(state) {
3726 shellLoader.itemDestroyed = false;
3727
3728 shellLoader.active = false;
3729+ shellLoader.state = state;
3730
3731 tryCompare(shellLoader, "status", Loader.Null);
3732 tryCompare(shellLoader, "item", null);
3733@@ -133,6 +251,11 @@
3734 // Shell instance gets destroyed.
3735 tryCompare(shellLoader, "itemDestroyed", true);
3736
3737+ // Reset any futzing our tests may have done with persistent objects
3738+ var app = ApplicationManager.findApplication("dialer-app");
3739+ if (app) {
3740+ app.setStage(ApplicationInfoInterface.SideStage);
3741+ }
3742 // kill all (fake) running apps
3743 killApps();
3744
3745@@ -143,6 +266,25 @@
3746 removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item);
3747 }
3748
3749+ function prepareShell() {
3750+ tryCompare(shell, "enabled", true); // enabled by greeter when ready
3751+
3752+ callManager.foregroundCall = null;
3753+ AccountsService.demoEdges = false;
3754+ AccountsService.demoEdgesCompleted = [];
3755+ AccountsService.demoEdges = true;
3756+
3757+ var surface = SurfaceManager.inputMethodSurface;
3758+ surface.setState(Mir.MinimizedState);
3759+
3760+ LightDM.Greeter.hideGreeter();
3761+ }
3762+
3763+ function loadShell(state) {
3764+ resetLoader(state);
3765+ prepareShell();
3766+ }
3767+
3768 function killApps() {
3769 while (ApplicationManager.count > 1) {
3770 var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
3771@@ -163,234 +305,486 @@
3772 waitForRendering(greeter);
3773 }
3774
3775- function waitForPage(name) {
3776- waitForRendering(findChild(shell, name));
3777- var page = findChild(shell, name);
3778- tryCompare(page, "shown", true);
3779- tryCompare(page.showAnimation, "running", false);
3780- return page;
3781- }
3782-
3783- function checkTopEdge() {
3784- touchFlick(shell, halfWidth, 0, halfWidth, halfHeight);
3785-
3786+ function openTutorialTop() {
3787+ var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
3788+ var tutorialTop = findChild(shell, "tutorialTop");
3789+ var tutorialTopTimer = findInvisibleChild(tutorialTop, "tutorialTopTimer");
3790+
3791+ tutorialTopTimer.interval = 1;
3792+ AccountsService.demoEdgesCompleted = ["left", "left-long"];
3793+
3794+ tryCompare(tutorialLeftLoader, "active", false);
3795+ tryCompare(tutorialTop, "shown", true);
3796+ tryCompare(tutorialTop, "opacity", 1);
3797+ }
3798+
3799+ function openTutorialRight() {
3800+ var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
3801+ var tutorialRight = findChild(shell, "tutorialRight");
3802+
3803+ AccountsService.demoEdgesCompleted = ["left", "left-long", "top"];
3804+ ApplicationManager.startApplication("gallery-app");
3805+ ApplicationManager.startApplication("facebook-webapp");
3806+
3807+ tryCompare(tutorialLeftLoader, "active", false);
3808+ tryCompare(tutorialRight, "shown", true);
3809+ tryCompare(tutorialRight, "opacity", 1);
3810+ }
3811+
3812+ function openTutorialBottom() {
3813+ var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
3814+ var tutorialBottom = findChild(shell, "tutorialBottom");
3815+
3816+ AccountsService.demoEdgesCompleted = ["left", "left-long", "top", "right"];
3817+ ApplicationManager.startApplication("dialer-app");
3818+
3819+ tryCompare(tutorialLeftLoader, "active", false);
3820+ tryCompare(tutorialBottom, "shown", true);
3821+ tryCompare(tutorialBottom, "opacity", 1);
3822+ }
3823+
3824+ function test_tutorialLeftEdges() {
3825+ var tutorial = findChild(shell, "tutorial");
3826+ var tutorialLeft = findChild(tutorial, "tutorialLeft");
3827+ var launcher = findChild(shell, "launcher");
3828+ var stage = findChild(shell, "stage");
3829 var panel = findChild(shell, "panel");
3830- tryCompare(panel.indicators, "fullyClosed", true);
3831- }
3832-
3833- function checkLeftEdge() {
3834- touchFlick(shell, 0, halfHeight, halfWidth, halfHeight);
3835-
3836- var launcher = findChild(shell, "launcher");
3837- tryCompare(launcher, "state", "");
3838- }
3839-
3840- function checkRightEdge() {
3841- if (shell.usageScenario === "phone") {
3842- touchFlick(shell, shell.width, halfHeight, halfWidth, halfHeight);
3843-
3844- var stage = findChild(shell, "stage");
3845- var spreadView = findChild(stage, "spreadView");
3846- tryCompare(spreadView, "phase", 0);
3847- }
3848- }
3849-
3850- function checkBottomEdge() {
3851- // Can't actually check effect of swipe, since dash isn't really loaded
3852- var applicationsDisplayLoader = findChild(shell, "applicationsDisplayLoader");
3853- tryCompare(applicationsDisplayLoader, "interactive", false);
3854- }
3855-
3856- function checkFinished() {
3857- tryCompare(AccountsService, "demoEdges", false);
3858-
3859- var tutorial = findChild(shell, "tutorial");
3860- tryCompare(tutorial, "running", false);
3861-
3862- var launcher = findChild(shell, "launcher");
3863- tryCompare(launcher, "shown", false);
3864- }
3865-
3866- function goToPage(name) {
3867- var page = waitForPage("tutorialLeft");
3868- checkTopEdge();
3869- checkRightEdge();
3870- checkBottomEdge();
3871- if (name === "tutorialLeft") return page;
3872- touchFlick(shell, 0, halfHeight, halfWidth, halfHeight);
3873-
3874- page = waitForPage("tutorialLeftFinish");
3875- if (name === "tutorialLeftFinish") return page;
3876- var tick = findChild(page, "tick");
3877- tap(tick);
3878-
3879- page = waitForPage("tutorialRight");
3880- checkTopEdge();
3881- checkLeftEdge();
3882- checkBottomEdge();
3883- if (name === "tutorialRight") return page;
3884- touchFlick(shell,
3885- shell.width, halfHeight,
3886- halfWidth, halfHeight,
3887- true /* beginTouch */, true /* endTouch */,
3888- 20 /* speed */, 50 /* iterations */);
3889- var overlay = findChild(page, "overlay");
3890- tryCompare(overlay, "shown", true);
3891- var tick = findChild(page, "tick");
3892- tap(tick);
3893-
3894- var page = waitForPage("tutorialBottom");
3895- checkTopEdge();
3896- checkLeftEdge();
3897- checkRightEdge();
3898- if (name === "tutorialBottom") return page;
3899- touchFlick(shell, halfWidth, shell.height, halfWidth, halfHeight);
3900-
3901- var page = waitForPage("tutorialBottomFinish");
3902- checkTopEdge();
3903- checkLeftEdge();
3904- checkRightEdge();
3905- checkBottomEdge();
3906- if (name === "tutorialBottomFinish") return page;
3907- var tick = findChild(page, "tick");
3908- tap(tick);
3909-
3910- checkFinished();
3911- return null;
3912- }
3913-
3914- function test_walkthrough() {
3915- goToPage(null);
3916- }
3917-
3918- function test_skipOnDesktop() {
3919- var tutorial = findChild(shell, "tutorial");
3920- tryCompare(tutorial, "active", true);
3921- tryCompare(tutorial, "running", true);
3922-
3923- shell.usageScenario = "desktop";
3924- tryCompare(tutorial, "active", false);
3925- tryCompare(tutorial, "running", false);
3926- }
3927-
3928- function test_launcherShortDrag() {
3929- // goToPage does a normal launcher pull. But here we want to test
3930- // just barely pulling the launcher out and letting go (i.e. not
3931- // triggering the "progress" property of Launcher).
3932-
3933- var left = goToPage("tutorialLeft");
3934+
3935+ verify(tutorial.running);
3936+ verify(tutorial.launcherEnabled);
3937+ verify(!tutorial.spreadEnabled);
3938+ verify(!tutorial.panelEnabled);
3939+ verify(tutorialLeft.shown);
3940+ verify(launcher.available);
3941+ verify(!stage.spreadEnabled);
3942+ verify(!panel.indicators.available);
3943+ }
3944+
3945+ function test_tutorialLeftFinish() {
3946+ var tutorial = findChild(shell, "tutorial");
3947+ var tutorialLeft = findChild(tutorial, "tutorialLeft");
3948+ var launcher = findChild(shell, "launcher");
3949+
3950+ touchFlick(shell, 0, halfHeight, halfWidth, halfHeight);
3951+
3952+ tryCompare(tutorialLeft, "shown", false);
3953+ tryCompare(AccountsService, "demoEdgesCompleted", ["left"]);
3954+ tryCompare(launcher, "state", "visible");
3955+ }
3956+
3957+ function test_tutorialLeftShortDrag() {
3958+ // Here we want to test just barely pulling the launcher out and
3959+ // letting go (i.e. not triggering the "progress" property of
3960+ // Launcher).
3961+ var tutorialLeft = findChild(shell, "tutorialLeft");
3962+ var launcher = findChild(shell, "launcher");
3963+
3964+ // Confirm fade during drag
3965+ touchFlick(shell, 0, halfHeight, launcher.panelWidth * 0.4, halfHeight, true, false);
3966+ // compare opacity with a bound rather than hard 0.6 because progress doesn't
3967+ // always match the drag perfectly (takes a moment for drag to kick in)
3968+ tryCompareFunction(function() {
3969+ return tutorialLeft.opacity >= 0.6 && tutorialLeft.opacity < 0.7;
3970+ }, true);
3971+ touchFlick(shell, 0, halfHeight, launcher.panelWidth * 0.4, halfHeight, false, true);
3972+
3973
3974 // Make sure we don't do anything if we don't pull the launcher
3975 // out much.
3976- var launcher = findChild(shell, "launcher");
3977 touchFlick(shell, 0, halfHeight, launcher.panelWidth * 0.4, halfHeight);
3978 tryCompare(launcher, "state", ""); // should remain hidden
3979- tryCompare(left, "shown", true); // and we should still be on left
3980+ tryCompare(tutorialLeft, "shown", true); // and we should still be on left
3981+
3982
3983 // Now drag out but not past launcher itself
3984 touchFlick(shell, 0, halfHeight, launcher.panelWidth * 0.9, halfHeight);
3985
3986- waitForPage("tutorialLeftFinish");
3987+ tryCompare(tutorialLeft, "shown", false);
3988+ tryCompare(AccountsService, "demoEdgesCompleted", ["left"]);
3989+ tryCompare(launcher, "state", "visible");
3990 }
3991
3992- function test_launcherLongDrag() {
3993- // goToPage does a normal launcher pull. But here we want to test
3994- // a full pull across the page.
3995+ function test_tutorialLeftLongDrag() {
3996+ // Just confirm that a long drag ("dash" drag) doesn't confuse us
3997
3998- var left = goToPage("tutorialLeft");
3999+ // So that we actually switch to dash and launcher hides
4000+ ApplicationManager.startApplication("gallery-app");
4001
4002 var launcher = findChild(shell, "launcher");
4003+ var tutorialLeft = findChild(shell, "tutorialLeft");
4004 touchFlick(shell, 0, halfHeight, shell.width, halfHeight);
4005
4006- var errorTextLabel = findChild(left, "errorTextLabel");
4007- var errorTitleLabel = findChild(left, "errorTitleLabel");
4008- tryCompare(launcher, "state", ""); // launcher goes away
4009- tryCompare(left, "shown", true); // still on left page
4010- tryCompare(errorTextLabel, "opacity", 1); // show error
4011- tryCompare(errorTitleLabel, "opacity", 1); // show error
4012- }
4013-
4014- function test_launcherDragBack() {
4015- // goToPage does a full launcher pull. But here we test pulling
4016- // all the way out, then dragging back into place.
4017-
4018- var left = goToPage("tutorialLeft");
4019- touchFlick(shell, 0, halfHeight, halfWidth, halfHeight, true, false);
4020- touchFlick(shell, halfWidth, halfHeight, 0, halfHeight, false, true);
4021-
4022- tryCompare(left, "shown", true); // and we should still be on left
4023- }
4024-
4025- function test_launcherNoDragGap() {
4026- // See bug 1454882, where if you dragged the launcher while it was
4027- // visible, you could pull it further than the edge of the screen.
4028-
4029- var left = goToPage("tutorialLeft");
4030- var launcher = findChild(shell, "launcher");
4031- var teaseAnimation = findInvisibleChild(left, "teaseAnimation");
4032-
4033- // Wait for launcher to be really out there
4034- tryCompareFunction(function() {return launcher.x > teaseAnimation.maxBounce/2}, true);
4035- verify(teaseAnimation.running);
4036-
4037- // Start a drag, make sure animation stops
4038- touchFlick(shell, 0, halfHeight, units.gu(4), halfHeight, true, false);
4039- verify(!teaseAnimation.running);
4040- verify(launcher.visibleWidth > 0);
4041- verify(launcher.x > 0);
4042- compare(launcher.x, teaseAnimation.bounce);
4043-
4044- // Continue drag, make sure we don't create a gap on the left hand side
4045- touchFlick(shell, units.gu(4), halfHeight, shell.width, halfHeight, false, false);
4046- verify(!teaseAnimation.running);
4047- compare(launcher.visibleWidth, launcher.panelWidth);
4048- compare(launcher.x, 0);
4049-
4050- // Finish and make sure we continue animation
4051- touchFlick(shell, shell.width, halfHeight, shell.width, halfHeight, false, true);
4052- tryCompare(teaseAnimation, "running", true);
4053- }
4054-
4055- function test_spread() {
4056- // Unfortunately, most of what we want to test of the spread is
4057- // "did it render correctly?" but that's hard to test. So instead,
4058- // just poke and prod it a little bit to see if some of the values
4059- // we'd expect to be correct, are so.
4060-
4061- var right = goToPage("tutorialRight");
4062- var stage = findChild(right, "stage");
4063- var delegate0 = findChild(right, "appDelegate0");
4064-
4065- tryCompare(stage, "dragProgress", 0);
4066+ tryCompare(tutorialLeft, "shown", false);
4067+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long"]);
4068+ }
4069+
4070+ function test_tutorialLeftAutoSkipped() {
4071+ // Test that we skip the tutorial if user uses left edge themselves
4072+
4073+ var tutorialLeft = findChild(shell, "tutorialLeft");
4074+ LightDM.Greeter.showGreeter();
4075+ tryCompare(tutorialLeft, "visible", false);
4076+ compare(AccountsService.demoEdgesCompleted, []);
4077+
4078+ touchFlick(shell, 0, halfHeight, halfWidth, halfHeight);
4079+ tryCompare(AccountsService, "demoEdgesCompleted", ["left"]);
4080+ }
4081+
4082+ function test_tutorialTopEdges() {
4083+ var tutorial = findChild(shell, "tutorial");
4084+ var tutorialTop = findChild(tutorial, "tutorialTop");
4085+ var launcher = findChild(shell, "launcher");
4086+ var stage = findChild(shell, "stage");
4087+ var panel = findChild(shell, "panel");
4088+
4089+ openTutorialTop();
4090+
4091+ tryCompare(tutorial, "running", true);
4092+ verify(!tutorial.launcherEnabled);
4093+ verify(!tutorial.spreadEnabled);
4094+ verify(tutorial.panelEnabled);
4095+ verify(tutorialTop.shown);
4096+ verify(!launcher.available);
4097+ verify(!stage.spreadEnabled);
4098+ verify(panel.indicators.available);
4099+ }
4100+
4101+ function test_tutorialTopFinish() {
4102+ var tutorial = findChild(shell, "tutorial");
4103+ var tutorialTop = findChild(tutorial, "tutorialTop");
4104+ var panel = findChild(shell, "panel");
4105+
4106+ openTutorialTop();
4107+ touchFlick(shell, halfWidth, 0, halfWidth, shell.height);
4108+
4109+ tryCompare(tutorialTop, "shown", false);
4110+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top"]);
4111+ tryCompare(panel.indicators, "fullyOpened", true);
4112+ }
4113+
4114+ function test_tutorialTopShortDrag() {
4115+ var tutorial = findChild(shell, "tutorial");
4116+ var tutorialTop = findChild(tutorial, "tutorialTop");
4117+ var panel = findChild(shell, "panel");
4118+
4119+ openTutorialTop();
4120+ touchFlick(shell, halfWidth, 0, halfWidth, shell.height * 0.4, true, false);
4121+ // compare opacity with a bound rather than hard 0.6 because progress doesn't
4122+ // always match the drag perfectly (takes a moment for drag to kick in)
4123+ tryCompareFunction(function() {
4124+ return tutorialTop.opacity >= 0.6 && tutorialTop.opacity < 0.7;
4125+ }, true);
4126+ touchFlick(shell, halfWidth, 0, halfWidth, shell.height * 0.4, false, true);
4127+
4128+ compare(tutorialTop.shown, true);
4129+ }
4130+
4131+ function test_tutorialTopAutoSkipped() {
4132+ // Test that we skip the tutorial if user uses top edge themselves
4133+
4134+ var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
4135+ var tutorialTop = findChild(shell, "tutorialTop");
4136+ AccountsService.demoEdgesCompleted = ["left", "left-long"];
4137+ tryCompare(tutorialLeftLoader, "active", false);
4138+ verify(!tutorialTop.shown);
4139+
4140+ touchFlick(shell, halfWidth, 0, halfWidth, shell.height);
4141+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top"]);
4142+ }
4143+
4144+ function test_tutorialRightEdges() {
4145+ var tutorial = findChild(shell, "tutorial");
4146+ var tutorialRight = findChild(tutorial, "tutorialRight");
4147+ var launcher = findChild(shell, "launcher");
4148+ var stage = findChild(shell, "stage");
4149+ var panel = findChild(shell, "panel");
4150+
4151+ openTutorialRight();
4152+
4153+ tryCompare(tutorial, "running", true);
4154+ verify(!tutorial.launcherEnabled);
4155+ verify(tutorial.spreadEnabled);
4156+ verify(!tutorial.panelEnabled);
4157+ verify(tutorialRight.shown);
4158+ verify(!launcher.available);
4159+ verify(stage.spreadEnabled);
4160+ verify(!panel.indicators.available);
4161+ }
4162+
4163+ function test_tutorialRightFinish() {
4164+ var tutorial = findChild(shell, "tutorial");
4165+ var tutorialRight = findChild(tutorial, "tutorialRight");
4166+ var stage = findChild(shell, "stage");
4167+
4168+ openTutorialRight();
4169+ touchFlick(shell, shell.width, halfHeight, 0, halfHeight);
4170+
4171+ tryCompare(tutorialRight, "shown", false);
4172+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top", "right"]);
4173+ }
4174+
4175+ function test_tutorialRightShortDrag() {
4176+ var tutorial = findChild(shell, "tutorial");
4177+ var tutorialRight = findChild(tutorial, "tutorialRight");
4178+ var stage = findChild(shell, "stage");
4179+
4180+ openTutorialRight();
4181 touchFlick(shell, shell.width, halfHeight, shell.width * 0.8, halfHeight, true, false);
4182- verify(stage.dragProgress > 0);
4183- compare(stage.dragProgress, -delegate0.xTranslate);
4184- touchFlick(shell, shell.width * 0.8, halfHeight, shell.width, halfHeight, false, true);
4185- tryCompare(stage, "dragProgress", 0);
4186-
4187- tryCompare(delegate0, "x", shell.width);
4188-
4189- var screenshotImage = findChild(right, "screenshotImage");
4190- tryCompare(screenshotImage, "source", Qt.resolvedUrl("../../../qml/Tutorial/graphics/facebook.png"));
4191- tryCompare(screenshotImage, "visible", true);
4192- }
4193-
4194- function test_bottomShortDrag() {
4195- var bottom = goToPage("tutorialBottom");
4196-
4197- touchFlick(shell, halfWidth, shell.height, halfWidth, shell.height * 0.8);
4198-
4199- var errorTextLabel = findChild(bottom, "errorTextLabel");
4200- var errorTitleLabel = findChild(bottom, "errorTitleLabel");
4201- tryCompare(bottom, "shown", true); // still on bottom page
4202- tryCompare(errorTextLabel, "opacity", 1); // show error
4203- tryCompare(errorTitleLabel, "opacity", 1); // show error
4204- }
4205-
4206- function test_interrupted() {
4207- goToPage("tutorialLeft");
4208- ApplicationManager.startApplication("dialer-app");
4209- checkFinished();
4210+ // compare opacity with a bound rather than hard 0.6 because progress doesn't
4211+ // always match the drag perfectly (takes a moment for drag to kick in)
4212+ tryCompareFunction(function() {
4213+ return tutorialRight.opacity >= 0.6 && tutorialRight.opacity < 0.8;
4214+ }, true);
4215+ touchFlick(shell, shell.width, halfHeight, shell.width * 0.8, halfHeight, false, true);
4216+
4217+ compare(tutorialRight.shown, true);
4218+ }
4219+
4220+ function test_tutorialRightDelay() {
4221+ // Test that if we exit the top tutorial, we don't immediately
4222+ // jump into right tutorial.
4223+ var tutorialRight = findChild(shell, "tutorialRight");
4224+ var tutorialRightTimer = findInvisibleChild(tutorialRight, "tutorialRightInactivityTimer");
4225+
4226+ tutorialRightTimer.interval = 1;
4227+ openTutorialTop();
4228+ ApplicationManager.startApplication("gallery-app");
4229+ ApplicationManager.startApplication("facebook-webapp");
4230+ tryCompare(ApplicationManager, "count", 3);
4231+
4232+ AccountsService.demoEdgesCompleted = ["left", "left-long", "top"];
4233+ verify(tutorialRightTimer.running, true);
4234+ verify(!tutorialRight.shown);
4235+ tryCompare(tutorialRight, "shown", true);
4236+ }
4237+
4238+ function test_tutorialRightAutoSkipped() {
4239+ // Test that we skip the tutorial if user uses right edge themselves
4240+
4241+ var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
4242+ AccountsService.demoEdgesCompleted = ["left", "left-long"];
4243+ tryCompare(tutorialLeftLoader, "active", false);
4244+
4245+ touchFlick(shell, shell.width, halfHeight, 0, halfHeight);
4246+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "right"]);
4247+ }
4248+
4249+ function test_tutorialBottomEdges() {
4250+ var tutorial = findChild(shell, "tutorial");
4251+ var tutorialBottom = findChild(tutorial, "tutorialBottom");
4252+ var tutorialLabel = findChild(tutorialBottom, "tutorialLabel");
4253+ var launcher = findChild(shell, "launcher");
4254+ var stage = findChild(shell, "stage");
4255+ var panel = findChild(shell, "panel");
4256+
4257+ openTutorialBottom();
4258+
4259+ tryCompare(tutorial, "running", true);
4260+ verify(!tutorial.launcherEnabled);
4261+ verify(!tutorial.spreadEnabled);
4262+ verify(!tutorial.panelEnabled);
4263+ verify(tutorialBottom.shown);
4264+ verify(!launcher.available);
4265+ verify(!stage.spreadEnabled);
4266+ verify(!panel.indicators.available);
4267+ compare(tutorialLabel.text, "Swipe up for recent calls");
4268+ }
4269+
4270+ function test_tutorialBottomFinish() {
4271+ var tutorial = findChild(shell, "tutorial");
4272+ var tutorialBottom = findChild(tutorial, "tutorialBottom");
4273+
4274+ openTutorialBottom();
4275+ touchFlick(shell, halfWidth, shell.height, halfWidth, halfHeight);
4276+
4277+ tryCompare(tutorialBottom, "shown", false);
4278+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top", "right", "bottom-dialer-app"]);
4279+
4280+ // OK, we did one, just confirm that when all are done, we mark whole tutorial as done.
4281+ verify(AccountsService.demoEdges);
4282+ AccountsService.demoEdgesCompleted = ["left", "left-long", "top", "right",
4283+ "bottom-address-book-app",
4284+ "bottom-com.ubuntu.calculator_calculator",
4285+ "bottom-dialer-app",
4286+ "bottom-messaging-app"];
4287+ verify(!AccountsService.demoEdges);
4288+ }
4289+
4290+ function test_tutorialBottomAppearsBeforeRight() {
4291+ // Confirm that if bottom edge and right edge would appear on the
4292+ // the same app open, bottom edge appears first. (this is a lightly
4293+ // edited version of openTutorialRight)
4294+ var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
4295+ var tutorialRight = findChild(shell, "tutorialRight");
4296+ var tutorialBottom = findChild(shell, "tutorialBottom");
4297+
4298+ AccountsService.demoEdgesCompleted = ["left", "left-long", "top"];
4299+ ApplicationManager.startApplication("gallery-app");
4300+ ApplicationManager.startApplication("dialer-app");
4301+
4302+ tryCompare(tutorialLeftLoader, "active", false);
4303+ tryCompare(tutorialBottom, "shown", true);
4304+ tryCompare(tutorialBottom, "opacity", 1);
4305+ tryCompare(tutorialRight, "visible", false);
4306+ }
4307+
4308+ function test_tutorialBottomOnlyCoversSideStageOnTablet() {
4309+ loadShell("tablet");
4310+
4311+ var tutorialBottom = findChild(shell, "tutorialBottom");
4312+ var targetHeight = shell.height - units.gu(4);
4313+ var mainStageX = units.gu(20);
4314+ var sideStageX = shell.width - units.gu(20);
4315+
4316+ openTutorialBottom();
4317+
4318+ touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, true, false);
4319+ compare(tutorialBottom.opacity, 1);
4320+ touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, false, true);
4321+
4322+ touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, true, false);
4323+ verify(tutorialBottom.opacity < 1);
4324+ touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, false, true);
4325+ }
4326+
4327+ function test_tutorialBottomOnlyCoversMainStageOnTablet() {
4328+ loadShell("tablet");
4329+
4330+ var tutorialBottom = findChild(shell, "tutorialBottom");
4331+ var targetHeight = shell.height - units.gu(4);
4332+ var mainStageX = units.gu(20);
4333+ var sideStageX = shell.width - units.gu(20);
4334+
4335+ openTutorialBottom();
4336+ var app = ApplicationManager.findApplication("dialer-app");
4337+ app.setStage(ApplicationInfoInterface.MainStage);
4338+
4339+ touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, true, false);
4340+ compare(tutorialBottom.opacity, 1);
4341+ touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, false, true);
4342+
4343+ touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, true, false);
4344+ verify(tutorialBottom.opacity < 1);
4345+ touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, false, true);
4346+ }
4347+
4348+ function test_activeCallInterruptsTutorial() {
4349+ var tutorialLeft = findChild(shell, "tutorialLeft");
4350+ verify(tutorialLeft.shown);
4351+ verify(!tutorialLeft.paused);
4352+
4353+ callManager.foregroundCall = phoneCall;
4354+ verify(!tutorialLeft.shown);
4355+ verify(tutorialLeft.paused);
4356+ tryCompare(tutorialLeft, "visible", false);
4357+
4358+ callManager.foregroundCall = null;
4359+ tryCompare(tutorialLeft, "shown", true);
4360+ verify(!tutorialLeft.paused);
4361+ }
4362+
4363+ function test_greeterInterruptsTutorial() {
4364+ var tutorialLeft = findChild(shell, "tutorialLeft");
4365+ verify(tutorialLeft.shown);
4366+ verify(!tutorialLeft.paused);
4367+
4368+ LightDM.Greeter.showGreeter();
4369+ verify(!tutorialLeft.shown);
4370+ verify(tutorialLeft.paused);
4371+ tryCompare(tutorialLeft, "visible", false);
4372+
4373+ LightDM.Greeter.hideGreeter();
4374+ tryCompare(tutorialLeft, "shown", true);
4375+ verify(!tutorialLeft.paused);
4376+ }
4377+
4378+ function test_interruptionChecksReadyStateWhenDone() {
4379+ // If we're done with an interruption (like active call), make sure
4380+ // that we don't blindly resume the tutorial -- our trigger
4381+ // conditions still need to be met. For example, there need to be
4382+ // enough apps open for the right edge tutorial.
4383+
4384+ openTutorialRight();
4385+
4386+ var tutorialRight = findChild(shell, "tutorialRight");
4387+ verify(tutorialRight.isReady);
4388+ verify(tutorialRight.shown);
4389+ verify(!tutorialRight.paused);
4390+
4391+ callManager.foregroundCall = phoneCall;
4392+ killApps();
4393+ callManager.foregroundCall = null;
4394+
4395+ verify(!tutorialRight.isReady);
4396+ verify(!tutorialRight.shown);
4397+ verify(!tutorialRight.paused);
4398+ compare(AccountsService.demoEdgesCompleted, ["left", "left-long", "top"]);
4399+ }
4400+
4401+ function test_desktopOnlyShowsTutorialRight() {
4402+ loadShell("desktop");
4403+
4404+ var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
4405+ var tutorialTopLoader = findChild(shell, "tutorialTopLoader");
4406+ var tutorialRightLoader = findChild(shell, "tutorialRightLoader");
4407+ var tutorialBottomLoader = findChild(shell, "tutorialBottomLoader");
4408+ verify(!tutorialLeftLoader.active);
4409+ verify(!tutorialTopLoader.active);
4410+ verify(tutorialRightLoader.active);
4411+ verify(!tutorialBottomLoader.active);
4412+ compare(AccountsService.demoEdgesCompleted, []);
4413+
4414+ ApplicationManager.startApplication("dialer-app");
4415+ ApplicationManager.startApplication("camera-app");
4416+ tryCompare(tutorialRightLoader.item, "isReady", true);
4417+ tryCompare(tutorialRightLoader, "shown", true);
4418+ }
4419+
4420+ function test_oskDoesNotHideTutorial() {
4421+ var tutorialLeft = findChild(shell, "tutorialLeft");
4422+ verify(tutorialLeft.shown);
4423+
4424+ var surface = SurfaceManager.inputMethodSurface;
4425+ surface.setState(Mir.RestoredState);
4426+
4427+ var inputMethod = findInvisibleChild(shell, "inputMethod");
4428+ tryCompare(inputMethod, "state", "shown");
4429+
4430+ verify(tutorialLeft.shown);
4431+ }
4432+
4433+ function test_oskPreventsTutorial() {
4434+ var surface = SurfaceManager.inputMethodSurface;
4435+ var inputMethod = findInvisibleChild(shell, "inputMethod");
4436+
4437+ AccountsService.demoEdges = false;
4438+ surface.setState(Mir.RestoredState);
4439+ tryCompare(inputMethod, "state", "shown");
4440+
4441+ var tutorial = findChild(shell, "tutorial");
4442+ tryCompare(tutorial, "keyboardVisible", true);
4443+
4444+ AccountsService.demoEdges = true;
4445+ var tutorialLeft = findChild(shell, "tutorialLeft");
4446+ verify(!tutorialLeft.shown);
4447+
4448+ surface.setState(Mir.MinimizedState);
4449+ tryCompare(inputMethod, "state", "hidden");
4450+ tryCompare(tutorialLeft, "shown", false);
4451+ }
4452+
4453+ function test_accountsServiceSettings() {
4454+ var tutorialLeft = findChild(shell, "tutorialLeft");
4455+ verify(tutorialLeft != null);
4456+ verify(tutorialLeft.shown);
4457+
4458+ AccountsService.demoEdges = false;
4459+ verify(findChild(shell, "tutorialLeft") == null);
4460+
4461+ AccountsService.demoEdges = true;
4462+ tutorialLeft = findChild(shell, "tutorialLeft");
4463+ verify(tutorialLeft != null);
4464+ tryCompare(tutorialLeft, "shown", true);
4465 }
4466 }
4467 }
4468
4469=== modified file 'tests/qmltests/tst_OrientedShell.qml'
4470--- tests/qmltests/tst_OrientedShell.qml 2016-01-28 11:31:48 +0000
4471+++ tests/qmltests/tst_OrientedShell.qml 2016-03-10 17:24:40 +0000
4472@@ -314,7 +314,7 @@
4473 checked: false
4474 activeFocusOnPress: false
4475 onCheckedChanged: {
4476- var surface = SurfaceManager.inputMethodSurface();
4477+ var surface = SurfaceManager.inputMethodSurface;
4478 if (checked) {
4479 surface.setState(Mir.RestoredState);
4480 } else {
4481
4482=== modified file 'tests/qmltests/tst_Shell.qml'
4483--- tests/qmltests/tst_Shell.qml 2016-02-12 00:11:28 +0000
4484+++ tests/qmltests/tst_Shell.qml 2016-03-10 17:24:40 +0000
4485@@ -414,6 +414,7 @@
4486 setLightDMMockMode("single"); // back to the default value
4487
4488 AccountsService.demoEdges = false;
4489+ AccountsService.demoEdgesCompleted = [];
4490 Wizard.System.wizardEnabled = false;
4491
4492 // kill all (fake) running apps
4493@@ -565,9 +566,8 @@
4494
4495 function test_tabletLeftEdgeDrag_data() {
4496 return [
4497- {tag: "without password", user: "no-password", loggedIn: true, demo: false},
4498- {tag: "with password", user: "has-password", loggedIn: false, demo: false},
4499- {tag: "with demo", user: "has-password", loggedIn: true, demo: true},
4500+ {tag: "without password", user: "no-password", loggedIn: true},
4501+ {tag: "with password", user: "has-password", loggedIn: false},
4502 ]
4503 }
4504
4505@@ -577,10 +577,6 @@
4506
4507 selectUser(data.user)
4508
4509- AccountsService.demoEdges = data.demo
4510- var tutorial = findChild(shell, "tutorial");
4511- tryCompare(tutorial, "running", data.demo);
4512-
4513 swipeFromLeftEdge(shell.width * 0.75)
4514 wait(500) // to give time to handle dash() signal from Launcher
4515 confirmLoggedIn(data.loggedIn)
4516@@ -773,7 +769,7 @@
4517 loadShell("phone");
4518 swipeAwayGreeter();
4519 var item = findChild(shell, "inputMethod");
4520- var surface = SurfaceManager.inputMethodSurface();
4521+ var surface = SurfaceManager.inputMethodSurface;
4522
4523 surface.setState(Mir.MinimizedState);
4524 tryCompare(item, "visible", false);
4525@@ -1176,7 +1172,6 @@
4526 var tutorial = findChild(shell, "tutorial");
4527
4528 AccountsService.demoEdges = true;
4529- tryCompare(tutorial, "running", true);
4530 tryCompare(tutorial, "paused", true);
4531
4532 swipeAwayGreeter();
4533
4534=== modified file 'tests/qmltests/tst_ShellWithPin.qml'
4535--- tests/qmltests/tst_ShellWithPin.qml 2016-01-19 19:46:01 +0000
4536+++ tests/qmltests/tst_ShellWithPin.qml 2016-03-10 17:24:40 +0000
4537@@ -270,28 +270,6 @@
4538 tryCompare(sessionSpy, "count", 1)
4539 }
4540
4541- function test_edgeDemoHidesLockscreen() {
4542- LightDM.Greeter.showGreeter()
4543- sessionSpy.clear()
4544- var lockscreen = findChild(shell, "lockscreen")
4545-
4546- tryCompare(lockscreen, "shown", true)
4547- AccountsService.demoEdges = true
4548- tryCompare(lockscreen, "shown", false)
4549-
4550- var greeter = findChild(shell, "greeter");
4551- swipeAwayGreeter(false);
4552- tryCompare(greeter, "shown", false);
4553- tryCompare(sessionSpy, "count", 1)
4554-
4555- // Lockscreen is only hidden by the edge demo, so if we turn that
4556- // off and show greeter again, lockscreen should appear
4557- AccountsService.demoEdges = false
4558- LightDM.Greeter.showGreeter()
4559- lockscreen = findChild(shell, "lockscreen");
4560- tryCompare(lockscreen, "shown", true)
4561- }
4562-
4563 function test_disabledEdges() {
4564 var launcher = findChild(shell, "launcher")
4565 tryCompare(launcher, "available", true)

Subscribers

People subscribed via source and target branches