Merge lp:~aacid/unity8/desktopRotatedCamera into lp:unity8

Proposed by Michał Sawicz
Status: Superseded
Proposed branch: lp:~aacid/unity8/desktopRotatedCamera
Merge into: lp:unity8
Prerequisite: lp:~unity-team/unity8/fixTinyWindows
Diff against target: 8499 lines (+3975/-1071)
147 files modified
CMakeLists.txt (+1/-1)
cmake/modules/QmlTest.cmake (+1/-1)
data/unity8-dash.conf (+1/-0)
debian/changelog (+91/-0)
debian/control (+7/-6)
debian/unity8-common.udev (+2/-0)
debian/unity8-doc.install (+1/-0)
doc/devices.conf (+30/-0)
plugins/AccountsService/AccountsService.cpp (+244/-397)
plugins/AccountsService/AccountsService.h (+26/-21)
plugins/AccountsService/AccountsServiceDBusAdaptor.cpp (+11/-4)
plugins/AccountsService/AccountsServiceDBusAdaptor.h (+5/-6)
plugins/Dash/AudioProgressBar.qml (+1/-0)
plugins/Dash/CardCreator.js (+69/-34)
plugins/Dash/CardCreatorCache.qml (+3/-3)
plugins/Dash/plugin.cpp (+6/-6)
plugins/GlobalShortcut/globalshortcutregistry.cpp (+4/-4)
plugins/IntegratedLightDM/liblightdm/CMakeLists.txt (+16/-3)
plugins/IntegratedLightDM/liblightdm/UsersModel.cpp (+4/-18)
plugins/IntegratedLightDM/liblightdm/UsersModel.h (+1/-1)
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp (+44/-10)
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h (+15/-3)
plugins/Unity/Indicators/indicatorsmanager.cpp (+2/-2)
plugins/Unity/Indicators/rootstateparser.h (+1/-0)
plugins/Unity/Launcher/desktopfilehandler.cpp (+2/-2)
plugins/Unity/Launcher/launcheritem.cpp (+1/-0)
plugins/Unity/Launcher/launcheritem.h (+1/-1)
plugins/Unity/Launcher/launchermodel.cpp (+15/-5)
plugins/Unity/Launcher/launchermodel.h (+1/-1)
plugins/Utils/CMakeLists.txt (+1/-0)
plugins/Utils/deviceconfigparser.cpp (+150/-0)
plugins/Utils/deviceconfigparser.h (+62/-0)
plugins/Utils/plugin.cpp (+2/-0)
po/unity8.pot (+29/-27)
qml/Components/EdgeBarrier.qml (+1/-1)
qml/Components/InputMethod.qml (+1/-9)
qml/Components/Lockscreen.qml (+86/-100)
qml/Components/ModeSwitchWarningDialog.qml (+1/-1)
qml/Components/PassphraseLockscreen.qml (+5/-4)
qml/Components/PinLockscreen.qml (+22/-1)
qml/Components/ShellDialog.qml (+8/-0)
qml/Dash/CardCarousel.qml (+0/-1)
qml/Dash/CardGrid.qml (+0/-1)
qml/Dash/CardHorizontalList.qml (+0/-1)
qml/Dash/CardTool.qml (+2/-26)
qml/Dash/CardVerticalJournal.qml (+0/-1)
qml/Dash/Dash.qml (+11/-11)
qml/Dash/GenericScopeView.qml (+2/-0)
qml/Dash/Previews/PreviewHeader.qml (+37/-9)
qml/Dash/Previews/PreviewOverlay.qml (+1/-1)
qml/Dash/Previews/PreviewSharing.qml (+17/-7)
qml/Dash/ScopesListCategoryItem.qml (+8/-4)
qml/DeviceConfiguration.qml (+56/-18)
qml/DisabledScreenNotice.qml (+44/-20)
qml/Greeter/CoverPage.qml (+13/-2)
qml/Greeter/Infographics.qml (+2/-1)
qml/Greeter/NarrowView.qml (+14/-1)
qml/Launcher/Launcher.qml (+4/-3)
qml/Launcher/LauncherDelegate.qml (+1/-0)
qml/Notifications/Notification.qml (+6/-2)
qml/OrientedShell.qml (+26/-1)
qml/Panel/Handle.qml (+2/-2)
qml/Panel/Indicators/MenuItemFactory.qml (+0/-1)
qml/Panel/IndicatorsMenu.qml (+1/-1)
qml/Panel/Panel.qml (+5/-1)
qml/ScopeTool.qml (+0/-8)
qml/Stages/AbstractStage.qml (+1/-1)
qml/Stages/DecoratedWindow.qml (+34/-10)
qml/Stages/DesktopSpread.qml (+64/-17)
qml/Stages/DesktopSpreadDelegate.qml (+15/-1)
qml/Stages/DesktopStage.qml (+53/-30)
qml/Stages/PhoneStage.qml (+77/-3)
qml/Stages/SpreadDelegate.qml (+20/-0)
qml/Stages/TabletStage.qml (+83/-3)
qml/Stages/WindowResizeArea.qml (+1/-1)
src/CMakeLists.txt (+1/-1)
src/CachingNetworkManagerFactory.cpp (+2/-2)
src/CachingNetworkManagerFactory.h (+3/-2)
src/Dash/CMakeLists.txt (+1/-1)
tests/autopilot/unity8/dash.py (+1/-2)
tests/autopilot/unity8/shell/tests/test_helpers.py (+0/-2)
tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp (+0/-14)
tests/mocks/Unity/Application/ApplicationManager.cpp (+12/-0)
tests/mocks/Unity/Application/MirSurface.cpp (+6/-2)
tests/mocks/Unity/Application/MirSurface.h (+2/-1)
tests/mocks/Unity/Application/MirSurfaceItem.cpp (+2/-5)
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/Unity/Launcher/MockLauncherModel.cpp (+3/-0)
tests/mocks/Utils/CMakeLists.txt (+1/-0)
tests/mocks/Utils/plugin.cpp (+2/-0)
tests/plugins/AccountsService/CMakeLists.txt (+5/-0)
tests/plugins/AccountsService/PropertiesServer.cpp (+16/-4)
tests/plugins/AccountsService/PropertiesServer.h (+2/-1)
tests/plugins/AccountsService/UscServer.cpp (+28/-0)
tests/plugins/AccountsService/UscServer.h (+39/-0)
tests/plugins/AccountsService/client.cpp (+63/-9)
tests/plugins/AccountsService/interfaces.xml (+16/-0)
tests/plugins/AccountsService/server.cpp (+12/-0)
tests/plugins/Dash/cardcreator/1.res (+4/-6)
tests/plugins/Dash/cardcreator/1.res.cardcreator (+119/-0)
tests/plugins/Dash/cardcreator/10.res (+3/-5)
tests/plugins/Dash/cardcreator/10.res.cardcreator (+137/-0)
tests/plugins/Dash/cardcreator/11.res (+5/-7)
tests/plugins/Dash/cardcreator/11.res.cardcreator (+210/-0)
tests/plugins/Dash/cardcreator/2.res (+3/-5)
tests/plugins/Dash/cardcreator/2.res.cardcreator (+136/-0)
tests/plugins/Dash/cardcreator/3.res (+3/-5)
tests/plugins/Dash/cardcreator/3.res.cardcreator (+137/-0)
tests/plugins/Dash/cardcreator/4.res (+3/-5)
tests/plugins/Dash/cardcreator/4.res.cardcreator (+109/-0)
tests/plugins/Dash/cardcreator/5.res (+5/-7)
tests/plugins/Dash/cardcreator/5.res.cardcreator (+156/-0)
tests/plugins/Dash/cardcreator/6.res (+2/-4)
tests/plugins/Dash/cardcreator/6.res.cardcreator (+126/-0)
tests/plugins/Dash/cardcreator/7.res (+3/-5)
tests/plugins/Dash/cardcreator/7.res.cardcreator (+149/-0)
tests/plugins/Dash/cardcreator/8.res (+3/-5)
tests/plugins/Dash/cardcreator/8.res.cardcreator (+107/-0)
tests/plugins/Dash/cardcreator/9.res (+4/-5)
tests/plugins/Dash/cardcreator/9.res.cardcreator (+119/-0)
tests/plugins/Dash/cardcreatortest.cpp (+35/-25)
tests/plugins/Dash/cardcreatortest.qml (+4/-4)
tests/plugins/IntegratedLightDM/CMakeLists.txt (+25/-0)
tests/plugins/IntegratedLightDM/integrated.cpp (+91/-0)
tests/plugins/Utils/CMakeLists.txt (+7/-1)
tests/plugins/Utils/DeviceConfigParserTest.cpp (+70/-0)
tests/qmltests/CMakeLists.txt (+1/-0)
tests/qmltests/Components/tst_Lockscreen.qml (+14/-7)
tests/qmltests/Dash/Previews/tst_PreviewHeader.qml (+18/-1)
tests/qmltests/Dash/Previews/tst_PreviewSharing.qml (+17/-3)
tests/qmltests/Dash/tst_CardTool.qml (+4/-4)
tests/qmltests/Dash/tst_Dash.qml (+89/-0)
tests/qmltests/Greeter/tst_NarrowView.qml (+9/-0)
tests/qmltests/Launcher/tst_Launcher.qml (+13/-3)
tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml (+2/-4)
tests/qmltests/Stages/tst_DesktopStage.qml (+2/-1)
tests/qmltests/Stages/tst_PhoneStage.qml (+19/-6)
tests/qmltests/Stages/tst_SpreadDelegate.qml (+7/-0)
tests/qmltests/Stages/tst_TabletStage.qml (+19/-1)
tests/qmltests/tst_DeviceConfiguration.qml (+49/-0)
tests/qmltests/tst_DisabledScreenNotice.qml (+76/-2)
tests/qmltests/tst_OrientedShell.qml (+14/-2)
tests/qmltests/tst_Shell.qml (+39/-25)
To merge this branch: bzr merge lp:~aacid/unity8/desktopRotatedCamera
Reviewer Review Type Date Requested Status
Michał Sawicz Needs Fixing
Unity8 CI Bot continuous-integration Needs Fixing
PS Jenkins bot continuous-integration Pending
Lukáš Tinkl Pending
Review via email: mp+288621@code.launchpad.net

This proposal supersedes a proposal from 2016-02-25.

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

Commit message

Desktop stage: Support rotatesWindowContents

Description of the change

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

 * 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?
N/A

 * If you changed the UI, has there been a design review?
N/A

To post a comment you must log in.
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:2205
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/481/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/643
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay/209
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial/209
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/666
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/684
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/684
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/680
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/680/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/680
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/680/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/680
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/680/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/680
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/680/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/680
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/680/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/680
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/680/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:2205
http://jenkins.qa.ubuntu.com/job/unity8-ci/7411/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6628
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/826/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/2116
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/819
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/2011
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/2011
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/818
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/817
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/5031
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6639
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6639/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27879
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/424/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/824
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/824/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27878

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:2206
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/499/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/663
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay/227
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial/227
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay/229
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial/229
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/686
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/704
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/704
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/700
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/700/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/700
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/700/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/700
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/700/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/700
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/700/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/700
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/700/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/700
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/700/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Lukáš Tinkl (lukas-kde) wrote : Posted in a previous version of this proposal

Left some inline comments, also seems you want to rotate just the ApplicationWindow inside the delegate, why not do it directly there instead of doing the calculations to take the decoration into account?

Revision history for this message
Lukáš Tinkl (lukas-kde) wrote : Posted in a previous version of this proposal

Also, shouldn't there be some transition/animation when the window rotates?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:2206
http://jenkins.qa.ubuntu.com/job/unity8-ci/7429/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6659
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/844/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/2134
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/837
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/2029
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/2029
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/836
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/835
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/5053
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6670
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6670/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27923
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/441/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/842
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/842/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27922

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> Left some inline comments, also seems you want to rotate just the
> ApplicationWindow inside the delegate, why not do it directly there instead of
> doing the calculations to take the decoration into account?

Yes, only the ApplicationWindow needs rotating and that's what i'm rotating only, no? I'm not sure what you mean with "there" means as instead of what i'm doing now.

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> Also, shouldn't there be some transition/animation when the window rotates?

The window doesn't really rotate, you move the phone and the window stays "the same" visually

Revision history for this message
Lukáš Tinkl (lukas-kde) wrote : Posted in a previous version of this proposal

> > Left some inline comments, also seems you want to rotate just the
> > ApplicationWindow inside the delegate, why not do it directly there instead
> of
> > doing the calculations to take the decoration into account?
>
> Yes, only the ApplicationWindow needs rotating and that's what i'm rotating
> only, no? I'm not sure what you mean with "there" means as instead of what i'm
> doing now.

Yup sorry, that's what I meant, blaming launchpad diff for not being to show/expand the context...

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> Why not just use "rotation: rotationAngle" instead of constructing the Rotation Transform? The "transformOrigin" is by default Item.Center

Because it doesn't work, see current code http://i.imgur.com/SeDA0n4.png vs using rotation as you say http://i.imgur.com/ptyxvQL.png

You need the correct origin otherwise the rotation sends the item away from the rest of the item

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> What about other states like "maximized", shouldn't we care about them as well?

They do work already, see tryOrientedShell, mako, windowed, start the second camera app and maximize it, then go to invertedlandscape and see how it works fine

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:2208
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/501/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/665
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay/231
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial/231
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/688
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/706
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/706
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/702
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/702/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/702
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/702/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/702
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/702/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/702
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/702/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/702
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/702/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/702
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/702/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

Maybe we would make camera-app not be fullscreen when in desktop mode (have code somewhere calling cameraApplication->setFullcreen(false)) instead of creating another app.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

Good work, by the way. Completely forgot about implementing RotatesWindowContents in DesktopStage.

Another thing:
"""
{tag: "mako_windowed", deviceName: "mako", orientationAngleAfterRotation: 90, windowed: true},
"""

Wouldn't a "manta_windowed" make more sense? (larger display area)

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

> Maybe we would make camera-app not be fullscreen when in desktop mode (have
> code somewhere calling cameraApplication->setFullcreen(false)) instead of
> creating another app.

By the way, that would mimic the magic that will (or already does, don't recall trying) happen on the device.

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> Wouldn't a "manta_windowed" make more sense? (larger display area)

Does it matter? I guess the point is that it works on one it "should" work on all, maybe i can just add all three?

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> Maybe we would make camera-app not be fullscreen when in desktop mode (have code somewhere
> calling cameraApplication->setFullcreen(false)) instead of creating another app.

This has advantage that we kind of test the "same" camera app that we [will] have on the real world, the disadvantage is that we lose the hability to try/test pure fullscreen apps on the destkop stage (which i guess at some point makes sense too).

That's why i decided to go for the duplication case, but can make it the other way if you prefer.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 26/02/2016 10:36, Albert Astals Cid wrote:
>> Wouldn't a "manta_windowed" make more sense? (larger display area)
> Does it matter? I guess the point is that it works on one it "should" work on all, maybe i can just add all three?

just sugar on top. makes more sense when you look at it or try it out
manually.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 26/02/2016 10:43, Albert Astals Cid wrote:
> This has advantage that we kind of test the "same" camera app that we [will] have on the real world, the disadvantage is that we lose the hability to try/test pure fullscreen apps on the destkop stage (which i guess at some point makes sense too).

We already have other fullscreen apps there: gallery-app, webbrowser-app

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> We already have other fullscreen apps there: gallery-app, webbrowser-app

Sure, but they do not have rotatesWindowContents set

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:2208
http://jenkins.qa.ubuntu.com/job/unity8-ci/7430/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6660
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/845/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/2135
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/838
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/2030
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/2030
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/837
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/836
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/5054
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6671
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6671/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27925
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/442/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/843
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/843/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27924

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:2210
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/504/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/668
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay/237
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial/237
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=phone-armhf,release=vivid+overlay/238
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/691
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/709
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/709
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/705
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/705/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/705
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/705/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/705
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/705/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/705
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/705/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/705
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/705/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/705
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/705/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:2210
http://jenkins.qa.ubuntu.com/job/unity8-ci/7432/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6663
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/847/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/2137
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/840
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/2032
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/2032
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/839
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/838
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/5058
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6674
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6674/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27930
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/444/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/845
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/845/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27929

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Lukáš Tinkl (lukas-kde) wrote : Posted in a previous version of this proposal

Worked fine from my testing

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

Yes

* Did CI run pass? If not, please explain why.

Yes, unrelated failures

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

Yes

review: Approve
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

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

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

Approving per superseded MP

review: Approve
Revision history for this message
Michał Sawicz (saviq) wrote :
review: Needs Fixing
2099. By Albert Astals Cid

Merge makeMakeTryOrientedShellWork

2100. By Albert Astals Cid

account for 180

2101. By Albert Astals Cid

Merge

2102. By Albert Astals Cid

Merge

2103. By Albert Astals Cid

Merge

2104. By Albert Astals Cid

Change to windowed/not windowed before starting the app

2105. By Albert Astals Cid

Merge

2106. By Albert Astals Cid

Merge

2107. By Albert Astals Cid

"compile"

2108. By Albert Astals Cid

fix startup of non rotatesWindowContents apps

2109. By Albert Astals Cid

Revert change infected from other branch

2110. By Albert Astals Cid

Merge

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-02-12 00:12:30 +0000
3+++ CMakeLists.txt 2016-03-11 13:51:30 +0000
4@@ -131,7 +131,7 @@
5 set(STDOUT_LOGGER "-o" "-,txt")
6 endif()
7
8-execute_process(COMMAND arch OUTPUT_VARIABLE ARCH)
9+execute_process(COMMAND dpkg-architecture -qDEB_HOST_ARCH OUTPUT_VARIABLE ARCH)
10 if (NOT ARCH MATCHES "arm*")
11 set(ENABLE_TOUCH_EMULATION true)
12 add_definitions(-DUNITY8_ENABLE_TOUCH_EMULATION)
13
14=== modified file 'cmake/modules/QmlTest.cmake'
15--- cmake/modules/QmlTest.cmake 2015-05-21 20:24:47 +0000
16+++ cmake/modules/QmlTest.cmake 2016-03-11 13:51:30 +0000
17@@ -183,7 +183,7 @@
18 cmake_parse_arguments(QMLTEST "${QMLTEST_OPTIONS}" "${QMLTEST_SINGLE}" "${QMLTEST_MULTI}" ${ARGN})
19 mangle_arguments()
20
21- bake_arguments("${QMLTEST_ARG_PREFIX}" args -qmljsdebugger=port:3768)
22+ bake_arguments("${QMLTEST_ARG_PREFIX}" args -qmljsdebugger=port:3768,3800)
23
24 set(qmltry_command
25 $<TARGET_FILE:${TARGET}>
26
27=== modified file 'data/unity8-dash.conf'
28--- data/unity8-dash.conf 2015-04-21 15:41:09 +0000
29+++ data/unity8-dash.conf 2016-03-11 13:51:30 +0000
30@@ -14,6 +14,7 @@
31 oom score 50
32
33 respawn
34+respawn limit unlimited
35
36 env APP_ID=unity8-dash
37
38
39=== modified file 'debian/changelog'
40--- debian/changelog 2016-03-08 20:59:35 +0000
41+++ debian/changelog 2016-03-11 13:51:30 +0000
42@@ -1,3 +1,94 @@
43+unity8 (8.11+16.04.20160310.4-0ubuntu1) xenial; urgency=medium
44+
45+ [ Albert Astals Cid ]
46+ * Add context for Re-dock as asked by translators (LP: #1534608)
47+ * Add emblem to the preview header widget (LP: #1424720)
48+ * Add haptics to ScopesListCategoryItem buttons
49+ * Audio Cards: Make some of the image loading async (LP: #1533432)
50+ * Do not create fallback code for the card tool fake card (LP:
51+ #1545865)
52+ * Fix resizing the dash bringing temp scopes size out of sync (LP:
53+ #1543130)
54+ * Minor fixes for unity-scope-tool
55+ * Resolve title alignment on card creator time instead of on runtime
56+ * Use fixedHeaderHeight only in the non cardtool cards
57+ * Use the new undeprecated connectivityqt::Connectivity
58+ * asynchronous is only false on the fake card in cardtool
59+ * clazy fixes
60+
61+ [ Albert Astals Cid, CI Train Bot ]
62+ * click scope: Add the else branch so we reset the card size in all
63+ situations
64+
65+ [ Andrea Cimitan ]
66+ * PreviewSharing widget now accepts both string and array of
67+ widgetData["share-data"]["uri"] (LP: #1549056)
68+ * Update AP tests for new single preview
69+ * Use Text.Wrap for body notification text (LP: #1544909)
70+
71+ [ Andrea Cimitan, Lukáš Tinkl, Michael Zanetti, Nick Dedekind ]
72+ * some fixes for the new palette (LP: #1554616)
73+
74+ [ CI Train Bot ]
75+ * Resync trunk.
76+ * Update translation template
77+
78+ [ CI Train Bot, Daniel d'Andrada ]
79+ * Ensure the QML engine doesn't delete our mock MirSurfaces on its
80+ own.
81+
82+ [ Daniel d'Andrada ]
83+ * tst_Shell: Remove unused qml items
84+
85+ [ Josh Arenson ]
86+ * Allow the shell to blacklist input devices and force the OSK shown.
87+ (LP: #1542224)
88+
89+ [ Lukáš Tinkl ]
90+ * Disallow resizing windows up, past the Panel (LP: #1544766)
91+ * Elide the window title not to let it overflow into the indicators
92+ area (LP: #1535767)
93+ * Enable the PIN lockscreen to be used with a HW keyboard (LP:
94+ #1550359)
95+ * Fix tiny windows when switching stages
96+ * Provide a range of ports to QML JS Debugger
97+ * Watch for launcher item icon changes (LP: #1543290)
98+
99+ [ Michael Terry ]
100+ * Proxy more mouse and touchpad properties to USC (LP: #1540398) (LP:
101+ #1543344, #1540398)
102+ * Refactor the AccountsService plugin and make it slightly faster.
103+ * To let the user log in if a mouse is connected, hide the greeter
104+ cover page on a mouse click (but NOT a touch click). (LP: #1540497)
105+ * Watch AccountsService for changes to the user's real name. This was
106+ preventing us from noticing when the user set their name in the
107+ welcome wizard.
108+
109+ [ Michael Zanetti ]
110+ * Allow alt+tabbing in staged mode too (LP: #1540502)
111+ * Allow invoking the staged mode spreads by mouse right edge pushes
112+ too (LP: #1540392)
113+ * Allow loading the device configuration from an external file
114+ * Implement Launcher's keyboard navigation and updated pip design
115+ * Make launcher scalable, allow it locking (LP: #1511015)
116+ * Properly parent launcher items in all cases (LP: #1495732)
117+ * Read inputMethod surface from the new property int QtMir (LP:
118+ #1545286)
119+ * Some visual updates and rotation lock for the virtual touchpad (LP:
120+ #1549087)
121+ * Visual updates for the windowed spread (LP: #1488148)
122+ * stabilize swipeAwayGreeter()
123+
124+ [ Michał Sawicz ]
125+ * Add udev rules to make sure we have access to uinput
126+ * Make dash respawn indefinitely (LP: #1550056)
127+ * Use dpkg-architecture, not arch, to disable touch emulation
128+
129+ [ Vesa Rautiainen ]
130+ * Fixing the vertical position of desktop spread item icon.
131+
132+ -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 10 Mar 2016 22:44:16 +0000
133+
134 unity8 (8.11+16.04.20160308-0ubuntu1) xenial; urgency=medium
135
136 [ Albert Astals Cid ]
137
138=== modified file 'debian/control'
139--- debian/control 2016-03-04 21:03:43 +0000
140+++ debian/control 2016-03-11 13:51:30 +0000
141@@ -13,7 +13,7 @@
142 libandroid-properties-dev,
143 graphviz,
144 gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
145- libconnectivity-qt1-dev,
146+ libconnectivity-qt1-dev (>= 0.7.1),
147 libevdev-dev,
148 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
149 libgl1-mesa-dri,
150@@ -55,7 +55,7 @@
151 qtdeclarative5-qtmultimedia-plugin (>= 5.4.1-1ubuntu19~overlay2),
152 qtdeclarative5-ubuntu-content1,
153 qtdeclarative5-ubuntu-settings-components (>= 0.7),
154- qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1796) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1796),
155+ qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1845) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1845),
156 qtdeclarative5-ubuntu-web-plugin,
157 ttf-ubuntu-font-family,
158 Standards-Version: 3.9.4
159@@ -70,7 +70,7 @@
160 Package: indicators-client
161 Architecture: amd64 armhf i386
162 Depends: qmenumodel-qml (>= 0.2.9),
163- qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1796) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1796),
164+ qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1845) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1845),
165 unity8 (= ${binary:Version}),
166 ${misc:Depends},
167 ${shlibs:Depends},
168@@ -101,7 +101,6 @@
169 qml-module-qt-labs-folderlistmodel,
170 qml-module-qtquick-xmllistmodel,
171 qml-module-qtsysteminfo,
172- qtdeclarative5-gsettings1.0,
173 qtdeclarative5-qtmir-plugin (>= 0.4.5),
174 qtdeclarative5-ubuntu-telephony0.1,
175 qtdeclarative5-ubuntu-web-plugin,
176@@ -128,7 +127,7 @@
177 Depends: qml-module-qtquick-layouts,
178 qtdeclarative5-ubuntu-settings-components (>= 0.7),
179 qtdeclarative5-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
180- qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1796) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1796),
181+ qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1845) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1845),
182 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
183 ubuntu-thumbnailer-impl-0,
184 unity-application-impl-13,
185@@ -158,7 +157,7 @@
186 python3-fixtures,
187 python3-gi,
188 qttestability-autopilot (>= 1.4),
189- ubuntu-ui-toolkit-autopilot (>= 1.3.1796),
190+ ubuntu-ui-toolkit-autopilot (>= 1.3.1845),
191 unity-scope-click,
192 unity8 (= ${source:Version}),
193 unity8-fake-env (= ${source:Version}),
194@@ -192,6 +191,8 @@
195 libhardware2,
196 pay-service,
197 unity-schemas (>= 7.3.1+14.10.20140915),
198+ qtdeclarative5-gsettings1.0,
199+ qml-module-qtmultimedia,
200 ${misc:Depends},
201 ${shlibs:Depends},
202 Provides: unity-launcher-impl,
203
204=== added file 'debian/unity8-common.udev'
205--- debian/unity8-common.udev 1970-01-01 00:00:00 +0000
206+++ debian/unity8-common.udev 2016-03-11 13:51:30 +0000
207@@ -0,0 +1,2 @@
208+# Make local foreground session able to inject input
209+KERNEL=="uinput", SUBSYSTEM=="misc", TAG+="uaccess"
210
211=== modified file 'debian/unity8-doc.install'
212--- debian/unity8-doc.install 2014-01-30 22:32:37 +0000
213+++ debian/unity8-doc.install 2016-03-11 13:51:30 +0000
214@@ -1,1 +1,2 @@
215+doc/devices.conf usr/share/doc/unity8/
216 usr/share/doc/unity8/*
217
218=== added file 'doc/devices.conf'
219--- doc/devices.conf 1970-01-01 00:00:00 +0000
220+++ doc/devices.conf 2016-03-11 13:51:30 +0000
221@@ -0,0 +1,30 @@
222+# This file can hold multiple device configs. Devices are separated by sections.
223+#
224+# SupportedOrientations holds a list of all enabled orientations. A standard
225+# phone will usually have Portrait,Landcape,InvertedLandscape in order to
226+# disable upside down usage.
227+#
228+# PrimaryOrientation gives the orientation the device will start up with
229+# when there is no orientations sensor input available (yet) or lock to
230+# when an application specifies to be locked to PrimaryOrientation.
231+#
232+# The other Orientation settings can be used to re-map the orientations.
233+# A device might be used with different orientations than how the screen
234+# is physically mounted on the hardware.
235+#
236+# Category can be phone, tablet, or desktop. This option determines
237+# whether the side stage is shown (tablet) or not (phone). Using
238+# desktop will load the shell in windowed mode. Note that the user
239+# can override/change this by connecting input hardware or change
240+# user settings.
241+#
242+# Any options not listed will default to the values of the example below.
243+
244+[devicename]
245+SupportedOrientations=Portrait,InvertedPortrait,Landscape,InvertedLandscape
246+PrimaryOrientation=PrimaryOrienation
247+PortraitOrientation=Portrait
248+InvertedPortraitOrientation=InvertedPortrait
249+LandscapeOrientation=Landscape
250+InvertedLandscapeOrientation=InvertedLandscape
251+Category=phone
252
253=== modified file 'plugins/AccountsService/AccountsService.cpp'
254--- plugins/AccountsService/AccountsService.cpp 2016-01-21 21:04:00 +0000
255+++ plugins/AccountsService/AccountsService.cpp 2016-03-11 13:51:30 +0000
256@@ -24,17 +24,52 @@
257 #include <QStringList>
258 #include <QDebug>
259
260+#define IFACE_ACCOUNTS_USER QStringLiteral("org.freedesktop.Accounts.User")
261+#define IFACE_LOCATION_HERE QStringLiteral("com.ubuntu.location.providers.here.AccountsService")
262+#define IFACE_UBUNTU_INPUT QStringLiteral("com.ubuntu.AccountsService.Input")
263+#define IFACE_UBUNTU_SECURITY QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy")
264+#define IFACE_UBUNTU_SECURITY_OLD QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy")
265+#define IFACE_UNITY QStringLiteral("com.canonical.unity.AccountsService")
266+#define IFACE_UNITY_PRIVATE QStringLiteral("com.canonical.unity.AccountsService.Private")
267+
268+#define PROP_BACKGROUND_FILE QStringLiteral("BackgroundFile")
269+#define PROP_DEMO_EDGES QStringLiteral("demo-edges")
270+#define PROP_ENABLE_INDICATORS_WHILE_LOCKED QStringLiteral("EnableIndicatorsWhileLocked")
271+#define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked")
272+#define PROP_FAILED_LOGINS QStringLiteral("FailedLogins")
273+#define PROP_LICENSE_ACCEPTED QStringLiteral("LicenseAccepted")
274+#define PROP_LICENSE_BASE_PATH QStringLiteral("LicenseBasePath")
275+#define PROP_MOUSE_CURSOR_SPEED QStringLiteral("MouseCursorSpeed")
276+#define PROP_MOUSE_DOUBLE_CLICK_SPEED QStringLiteral("MouseDoubleClickSpeed")
277+#define PROP_MOUSE_PRIMARY_BUTTON QStringLiteral("MousePrimaryButton")
278+#define PROP_MOUSE_SCROLL_SPEED QStringLiteral("MouseScrollSpeed")
279+#define PROP_PASSWORD_DISPLAY_HINT QStringLiteral("PasswordDisplayHint")
280+#define PROP_STATS_WELCOME_SCREEN QStringLiteral("StatsWelcomeScreen")
281+#define PROP_TOUCHPAD_CURSOR_SPEED QStringLiteral("TouchpadCursorSpeed")
282+#define PROP_TOUCHPAD_DISABLE_WHILE_TYPING QStringLiteral("TouchpadDisableWhileTyping")
283+#define PROP_TOUCHPAD_DISABLE_WITH_MOUSE QStringLiteral("TouchpadDisableWithMouse")
284+#define PROP_TOUCHPAD_DOUBLE_CLICK_SPEED QStringLiteral("TouchpadDoubleClickSpeed")
285+#define PROP_TOUCHPAD_PRIMARY_BUTTON QStringLiteral("TouchpadPrimaryButton")
286+#define PROP_TOUCHPAD_SCROLL_SPEED QStringLiteral("TouchpadScrollSpeed")
287+#define PROP_TOUCHPAD_TAP_TO_CLICK QStringLiteral("TouchpadTapToClick")
288+#define PROP_TOUCHPAD_TWO_FINGER_SCROLL QStringLiteral("TouchpadTwoFingerScroll")
289+
290+
291+QVariant primaryButtonConverter(const QVariant &value)
292+{
293+ QString stringValue = value.toString();
294+ if (stringValue == "left") {
295+ return QVariant::fromValue(0);
296+ } else if (stringValue == "right") {
297+ return QVariant::fromValue(1); // Mir is less clear on this -- any non-zero value is the same
298+ } else {
299+ return QVariant::fromValue(0); // default to left
300+ }
301+}
302+
303 AccountsService::AccountsService(QObject* parent, const QString &user)
304- : QObject(parent),
305- m_service(new AccountsServiceDBusAdaptor(this)),
306- m_demoEdges(false),
307- m_enableLauncherWhileLocked(false),
308- m_enableIndicatorsWhileLocked(false),
309- m_statsWelcomeScreen(false),
310- m_passwordDisplayHint(Keyboard),
311- m_failedLogins(0),
312- m_hereEnabled(false),
313- m_hereLicensePath() // null means not set yet
314+ : QObject(parent)
315+ , m_service(new AccountsServiceDBusAdaptor(this))
316 {
317 m_unityInput = new QDBusInterface(QStringLiteral("com.canonical.Unity.Input"),
318 QStringLiteral("/com/canonical/Unity/Input"),
319@@ -44,6 +79,43 @@
320 connect(m_service, &AccountsServiceDBusAdaptor::propertiesChanged, this, &AccountsService::onPropertiesChanged);
321 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged, this, &AccountsService::onMaybeChanged);
322
323+ registerProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE, QStringLiteral("backgroundFileChanged"));
324+ registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, QStringLiteral("hereEnabledChanged"));
325+ registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH, QStringLiteral("hereLicensePathChanged"));
326+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral("enableLauncherWhileLockedChanged"));
327+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral("enableIndicatorsWhileLockedChanged"));
328+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral("passwordDisplayHintChanged"));
329+ registerProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN, QStringLiteral("statsWelcomeScreenChanged"));
330+ registerProperty(IFACE_UNITY, PROP_DEMO_EDGES, QStringLiteral("demoEdgesChanged"));
331+ registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, QStringLiteral("failedLoginsChanged"));
332+
333+ registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_CURSOR_SPEED,
334+ m_unityInput, QStringLiteral("setMouseCursorSpeed"));
335+ registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_DOUBLE_CLICK_SPEED,
336+ m_unityInput, QStringLiteral("setMouseDoubleClickSpeed"));
337+ registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_PRIMARY_BUTTON,
338+ m_unityInput, QStringLiteral("setMousePrimaryButton"),
339+ primaryButtonConverter);
340+ registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_SCROLL_SPEED,
341+ m_unityInput, QStringLiteral("setMouseScrollSpeed"));
342+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_CURSOR_SPEED,
343+ m_unityInput, QStringLiteral("setTouchpadCursorSpeed"));
344+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_SCROLL_SPEED,
345+ m_unityInput, QStringLiteral("setTouchpadScrollSpeed"));
346+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WHILE_TYPING,
347+ m_unityInput, QStringLiteral("setTouchpadDisableWhileTyping"));
348+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WITH_MOUSE,
349+ m_unityInput, QStringLiteral("setTouchpadDisableWithMouse"));
350+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DOUBLE_CLICK_SPEED,
351+ m_unityInput, QStringLiteral("setTouchpadDoubleClickSpeed"));
352+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_PRIMARY_BUTTON,
353+ m_unityInput, QStringLiteral("setTouchpadPrimaryButton"),
354+ primaryButtonConverter);
355+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TAP_TO_CLICK,
356+ m_unityInput, QStringLiteral("setTouchpadTapToClick"));
357+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TWO_FINGER_SCROLL,
358+ m_unityInput, QStringLiteral("setTouchpadTwoFingerScroll"));
359+
360 setUser(!user.isEmpty() ? user : QString::fromUtf8(qgetenv("USER")));
361 }
362
363@@ -57,410 +129,200 @@
364 if (user.isEmpty() || m_user == user)
365 return;
366
367+ bool wasEmpty = m_user.isEmpty();
368+
369 m_user = user;
370 Q_EMIT userChanged();
371
372- updateDemoEdges(false);
373- updateEnableLauncherWhileLocked(false);
374- updateEnableIndicatorsWhileLocked(false);
375- updateBackgroundFile(false);
376- updateMouseCursorSpeed();
377- updateTouchpadCursorSpeed();
378- updateStatsWelcomeScreen(false);
379- updatePasswordDisplayHint(false);
380- updateFailedLogins(false);
381- updateHereEnabled(false);
382- updateHereLicensePath(false);
383+ // Do the first update synchronously, as a cheap way to block rendering
384+ // until we have the right values on bootup.
385+ refresh(!wasEmpty);
386 }
387
388 bool AccountsService::demoEdges() const
389 {
390- return m_demoEdges;
391+ auto value = getProperty(IFACE_UNITY, PROP_DEMO_EDGES);
392+ return value.toBool();
393 }
394
395 void AccountsService::setDemoEdges(bool demoEdges)
396 {
397- if (m_demoEdges != demoEdges) {
398- m_demoEdges = demoEdges;
399- m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("demo-edges"), demoEdges);
400-
401- Q_EMIT demoEdgesChanged();
402- }
403+ setProperty(IFACE_UNITY, PROP_DEMO_EDGES, demoEdges);
404 }
405
406 bool AccountsService::enableLauncherWhileLocked() const
407 {
408- return m_enableLauncherWhileLocked;
409+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
410+ return value.toBool();
411 }
412
413 bool AccountsService::enableIndicatorsWhileLocked() const
414 {
415- return m_enableIndicatorsWhileLocked;
416+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED);
417+ return value.toBool();
418 }
419
420 QString AccountsService::backgroundFile() const
421 {
422- return m_backgroundFile;
423+ auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE);
424+ return value.toString();
425 }
426
427 bool AccountsService::statsWelcomeScreen() const
428 {
429- return m_statsWelcomeScreen;
430+ auto value = getProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN);
431+ return value.toBool();
432 }
433
434 AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const
435 {
436- return m_passwordDisplayHint;
437+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT);
438+ return (PasswordDisplayHint)value.toInt();
439 }
440
441 bool AccountsService::hereEnabled() const
442 {
443- return m_hereEnabled;
444+ auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED);
445+ return value.toBool();
446 }
447
448 void AccountsService::setHereEnabled(bool enabled)
449 {
450- if (m_hereEnabled != enabled) {
451- m_hereEnabled = enabled;
452- m_service->setUserPropertyAsync(m_user, QStringLiteral("com.ubuntu.location.providers.here.AccountsService"), QStringLiteral("LicenseAccepted"), enabled);
453-
454- Q_EMIT hereEnabledChanged();
455- }
456+ setProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, enabled);
457 }
458
459 QString AccountsService::hereLicensePath() const
460 {
461- return m_hereLicensePath;
462+ auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH);
463+ QString hereLicensePath = value.toString();
464+ if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
465+ hereLicensePath = QStringLiteral("");
466+ return hereLicensePath;
467 }
468
469 bool AccountsService::hereLicensePathValid() const
470 {
471- return !m_hereLicensePath.isNull();
472-}
473-
474-void AccountsService::updateDemoEdges(bool async)
475-{
476- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
477- QStringLiteral("com.canonical.unity.AccountsService"),
478- QStringLiteral("demo-edges"));
479- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
480-
481- connect(watcher, &QDBusPendingCallWatcher::finished,
482- this, [this](QDBusPendingCallWatcher* watcher) {
483-
484- QDBusPendingReply<QDBusVariant> reply = *watcher;
485- watcher->deleteLater();
486- if (reply.isError()) {
487- qWarning() << "Failed to get 'demo-edges' property - " << reply.error().message();
488- return;
489- }
490-
491- auto demoEdges = reply.value().variant().toBool();
492- if (m_demoEdges != demoEdges) {
493- m_demoEdges = demoEdges;
494- Q_EMIT demoEdgesChanged();
495- }
496- });
497- if (!async) {
498- watcher->waitForFinished();
499- delete watcher;
500- }
501-}
502-
503-void AccountsService::updateEnableLauncherWhileLocked(bool async)
504-{
505- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
506- QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
507- QStringLiteral("EnableLauncherWhileLocked"));
508- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
509-
510- connect(watcher, &QDBusPendingCallWatcher::finished,
511- this, [this](QDBusPendingCallWatcher* watcher) {
512-
513- QDBusPendingReply<QVariant> reply = *watcher;
514- watcher->deleteLater();
515- if (reply.isError()) {
516- qWarning() << "Failed to get 'EnableLauncherWhileLocked' property - " << reply.error().message();
517- return;
518- }
519-
520- const bool enableLauncherWhileLocked = reply.value().toBool();
521- if (m_enableLauncherWhileLocked != enableLauncherWhileLocked) {
522- m_enableLauncherWhileLocked = enableLauncherWhileLocked;
523- Q_EMIT enableLauncherWhileLockedChanged();
524- }
525- });
526- if (!async) {
527- watcher->waitForFinished();
528- delete watcher;
529- }
530-}
531-
532-void AccountsService::updateEnableIndicatorsWhileLocked(bool async)
533-{
534- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
535- QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
536- QStringLiteral("EnableIndicatorsWhileLocked"));
537- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
538-
539- connect(watcher, &QDBusPendingCallWatcher::finished,
540- this, [this](QDBusPendingCallWatcher* watcher) {
541-
542- QDBusPendingReply<QVariant> reply = *watcher;
543- watcher->deleteLater();
544- if (reply.isError()) {
545- qWarning() << "Failed to get 'EnableIndicatorsWhileLocked' property - " << reply.error().message();
546- return;
547- }
548-
549- const bool enableIndicatorsWhileLocked = reply.value().toBool();
550- if (m_enableIndicatorsWhileLocked != enableIndicatorsWhileLocked) {
551- m_enableIndicatorsWhileLocked = enableIndicatorsWhileLocked;
552- Q_EMIT enableIndicatorsWhileLockedChanged();
553- }
554- });
555- if (!async) {
556- watcher->waitForFinished();
557- delete watcher;
558- }
559-}
560-
561-void AccountsService::updateBackgroundFile(bool async)
562-{
563- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
564- QStringLiteral("org.freedesktop.Accounts.User"),
565- QStringLiteral("BackgroundFile"));
566- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
567-
568- connect(watcher, &QDBusPendingCallWatcher::finished,
569- this, [this](QDBusPendingCallWatcher* watcher) {
570-
571- QDBusPendingReply<QVariant> reply = *watcher;
572- watcher->deleteLater();
573- if (reply.isError()) {
574- qWarning() << "Failed to get 'BackgroundFile' property - " << reply.error().message();
575- return;
576- }
577-
578- const QString backgroundFile = reply.value().toString();
579- if (m_backgroundFile != backgroundFile) {
580- m_backgroundFile = backgroundFile;
581- Q_EMIT backgroundFileChanged();
582- }
583- });
584- if (!async) {
585- watcher->waitForFinished();
586- delete watcher;
587- }
588-}
589-
590-void AccountsService::updateMouseCursorSpeed()
591-{
592- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
593- QStringLiteral("com.ubuntu.AccountsService.Input"),
594- QStringLiteral("MouseCursorSpeed"));
595- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
596-
597- connect(watcher, &QDBusPendingCallWatcher::finished,
598- this, [this](QDBusPendingCallWatcher* watcher) {
599-
600- QDBusPendingReply<QVariant> reply = *watcher;
601- watcher->deleteLater();
602- if (reply.isError()) {
603- qWarning() << "Failed to get 'MouseCursorSpeed' property - " << reply.error().message();
604- return;
605- }
606-
607- // Merely proxy this along to USC. We don't care about keeping a copy
608- // or exporting it internally.
609- m_unityInput->asyncCall(QStringLiteral("setMouseCursorSpeed"), reply.value());
610- });
611-}
612-
613-void AccountsService::updateTouchpadCursorSpeed()
614-{
615- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
616- QStringLiteral("com.ubuntu.AccountsService.Input"),
617- QStringLiteral("TouchpadCursorSpeed"));
618- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
619-
620- connect(watcher, &QDBusPendingCallWatcher::finished,
621- this, [this](QDBusPendingCallWatcher* watcher) {
622-
623- QDBusPendingReply<QVariant> reply = *watcher;
624- watcher->deleteLater();
625- if (reply.isError()) {
626- qWarning() << "Failed to get 'TouchpadCursorSpeed' property - " << reply.error().message();
627- return;
628- }
629-
630- // Merely proxy this along to USC. We don't care about keeping a copy
631- // or exporting it internally.
632- m_unityInput->asyncCall(QStringLiteral("setTouchpadCursorSpeed"), reply.value());
633- });
634-}
635-
636-void AccountsService::updateStatsWelcomeScreen(bool async)
637-{
638- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
639- QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy"),
640- QStringLiteral("StatsWelcomeScreen"));
641- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
642-
643- connect(watcher, &QDBusPendingCallWatcher::finished,
644- this, [this](QDBusPendingCallWatcher* watcher) {
645-
646- QDBusPendingReply<QVariant> reply = *watcher;
647- watcher->deleteLater();
648- if (reply.isError()) {
649- qWarning() << "Failed to get 'StatsWelcomeScreen' property - " << reply.error().message();
650- return;
651- }
652-
653- const bool statsWelcomeScreen = reply.value().toBool();
654- if (m_statsWelcomeScreen != statsWelcomeScreen) {
655- m_statsWelcomeScreen = statsWelcomeScreen;
656- Q_EMIT statsWelcomeScreenChanged();
657- }
658- });
659- if (!async) {
660- watcher->waitForFinished();
661- delete watcher;
662- }
663-}
664-
665-void AccountsService::updatePasswordDisplayHint(bool async)
666-{
667- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
668- QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
669- QStringLiteral("PasswordDisplayHint"));
670- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
671-
672- connect(watcher, &QDBusPendingCallWatcher::finished,
673- this, [this](QDBusPendingCallWatcher* watcher) {
674-
675- QDBusPendingReply<QVariant> reply = *watcher;
676- watcher->deleteLater();
677- if (reply.isError()) {
678- qWarning() << "Failed to get 'PasswordDisplayHint' property - " << reply.error().message();
679- return;
680- }
681-
682- const PasswordDisplayHint passwordDisplayHint = (PasswordDisplayHint)reply.value().toInt();
683- if (m_passwordDisplayHint != passwordDisplayHint) {
684- m_passwordDisplayHint = passwordDisplayHint;
685- Q_EMIT passwordDisplayHintChanged();
686- }
687- });
688- if (!async) {
689- watcher->waitForFinished();
690- delete watcher;
691- }
692-}
693-
694-void AccountsService::updateFailedLogins(bool async)
695-{
696- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
697- QStringLiteral("com.canonical.unity.AccountsService.Private"),
698- QStringLiteral("FailedLogins"));
699- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
700-
701- connect(watcher, &QDBusPendingCallWatcher::finished,
702- this, [this](QDBusPendingCallWatcher* watcher) {
703-
704- QDBusPendingReply<QVariant> reply = *watcher;
705- watcher->deleteLater();
706- if (reply.isError()) {
707- qWarning() << "Failed to get 'FailedLogins' property - " << reply.error().message();
708- return;
709- }
710-
711- const uint failedLogins = reply.value().toUInt();
712- if (m_failedLogins != failedLogins) {
713- m_failedLogins = failedLogins;
714- Q_EMIT failedLoginsChanged();
715- }
716- });
717- if (!async) {
718- watcher->waitForFinished();
719- delete watcher;
720- }
721-}
722-
723-void AccountsService::updateHereEnabled(bool async)
724-{
725- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
726- QStringLiteral("com.ubuntu.location.providers.here.AccountsService"),
727- QStringLiteral("LicenseAccepted"));
728- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
729-
730- connect(watcher, &QDBusPendingCallWatcher::finished,
731- this, [this](QDBusPendingCallWatcher* watcher) {
732-
733- QDBusPendingReply<QVariant> reply = *watcher;
734- watcher->deleteLater();
735- if (reply.isError()) {
736- qWarning() << "Failed to get 'LicenseAccepted' property - " << reply.error().message();
737- return;
738- }
739-
740- const bool hereEnabled = reply.value().toBool();
741- if (m_hereEnabled != hereEnabled) {
742- m_hereEnabled = hereEnabled;
743- Q_EMIT hereEnabledChanged();
744- }
745- });
746- if (!async) {
747- watcher->waitForFinished();
748- delete watcher;
749- }
750-}
751-
752-void AccountsService::updateHereLicensePath(bool async)
753-{
754- QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
755- QStringLiteral("com.ubuntu.location.providers.here.AccountsService"),
756- QStringLiteral("LicenseBasePath"));
757- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
758-
759- connect(watcher, &QDBusPendingCallWatcher::finished,
760- this, [this](QDBusPendingCallWatcher* watcher) {
761-
762- QDBusPendingReply<QVariant> reply = *watcher;
763- watcher->deleteLater();
764- if (reply.isError()) {
765- qWarning() << "Failed to get 'LicenseBasePath' property - " << reply.error().message();
766- return;
767- }
768-
769- QString hereLicensePath = reply.value().toString();
770- if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
771- hereLicensePath = QLatin1String("");
772-
773- if (m_hereLicensePath.isNull() || m_hereLicensePath != hereLicensePath) {
774- m_hereLicensePath = hereLicensePath;
775- Q_EMIT hereLicensePathChanged();
776- }
777- });
778- if (!async) {
779- watcher->waitForFinished();
780- delete watcher;
781- }
782+ auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH);
783+ return !value.toString().isNull();
784 }
785
786 uint AccountsService::failedLogins() const
787 {
788- return m_failedLogins;
789+ return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS).toUInt();
790 }
791
792 void AccountsService::setFailedLogins(uint failedLogins)
793 {
794- if (m_failedLogins != failedLogins) {
795- m_failedLogins = failedLogins;
796- m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService.Private"), QStringLiteral("FailedLogins"), failedLogins);
797-
798- Q_EMIT failedLoginsChanged();
799- }
800+ setProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, failedLogins);
801+}
802+
803+// ====================================================
804+// Everything below this line is generic helper methods
805+// ====================================================
806+
807+void AccountsService::emitChangedForProperty(const QString &interface, const QString &property)
808+{
809+ QString signalName = m_properties[interface][property].signal;
810+ QMetaObject::invokeMethod(this, signalName.toUtf8().data());
811+}
812+
813+QVariant AccountsService::getProperty(const QString &interface, const QString &property) const
814+{
815+ return m_properties[interface][property].value;
816+}
817+
818+void AccountsService::setProperty(const QString &interface, const QString &property, const QVariant &value)
819+{
820+ if (m_properties[interface][property].value != value) {
821+ m_properties[interface][property].value = value;
822+ m_service->setUserPropertyAsync(m_user, interface, property, value);
823+ emitChangedForProperty(interface, property);
824+ }
825+}
826+
827+void AccountsService::updateCache(const QString &interface, const QString &property, const QVariant &value)
828+{
829+ PropertyInfo &info = m_properties[interface][property];
830+
831+ if (info.proxyInterface) {
832+ QVariant finalValue;
833+ if (info.proxyConverter) {
834+ finalValue = info.proxyConverter(value);
835+ } else {
836+ finalValue = value;
837+ }
838+ info.proxyInterface->asyncCall(info.proxyMethod, finalValue);
839+ return; // don't bother saving a copy
840+ }
841+
842+ if (info.value != value) {
843+ info.value = value;
844+ emitChangedForProperty(interface, property);
845+ }
846+}
847+
848+void AccountsService::updateProperty(const QString &interface, const QString &property)
849+{
850+ QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
851+ interface,
852+ property);
853+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
854+
855+ connect(watcher, &QDBusPendingCallWatcher::finished,
856+ this, [this, interface, property](QDBusPendingCallWatcher* watcher) {
857+
858+ QDBusPendingReply<QVariant> reply = *watcher;
859+ watcher->deleteLater();
860+ if (reply.isError()) {
861+ qWarning() << "Failed to get '" << property << "' property:" << reply.error().message();
862+ return;
863+ }
864+
865+ updateCache(interface, property, reply.value());
866+ });
867+}
868+
869+void AccountsService::updateAllProperties(const QString &interface, bool async)
870+{
871+ QDBusPendingCall pendingReply = m_service->getAllPropertiesAsync(m_user,
872+ interface);
873+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
874+
875+ connect(watcher, &QDBusPendingCallWatcher::finished,
876+ this, [this, interface](QDBusPendingCallWatcher* watcher) {
877+
878+ QDBusPendingReply< QHash<QString, QVariant> > reply = *watcher;
879+ watcher->deleteLater();
880+ if (reply.isError()) {
881+ qWarning() << "Failed to get all properties for" << interface << ":" << reply.error().message();
882+ return;
883+ }
884+
885+ auto valueHash = reply.value();
886+ auto i = valueHash.constBegin();
887+ while (i != valueHash.constEnd()) {
888+ updateCache(interface, i.key(), i.value());
889+ ++i;
890+ }
891+ });
892+ if (!async) {
893+ watcher->waitForFinished();
894+ }
895+}
896+
897+void AccountsService::registerProxy(const QString &interface, const QString &property, QDBusInterface *iface, const QString &method, ProxyConverter converter)
898+{
899+ registerProperty(interface, property, nullptr);
900+
901+ m_properties[interface][property].proxyInterface = iface;
902+ m_properties[interface][property].proxyMethod = method;
903+ m_properties[interface][property].proxyConverter = converter;
904+}
905+
906+void AccountsService::registerProperty(const QString &interface, const QString &property, const QString &signal)
907+{
908+ m_properties[interface][property] = PropertyInfo();
909+ m_properties[interface][property].signal = signal;
910 }
911
912 void AccountsService::onPropertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
913@@ -469,42 +331,13 @@
914 return;
915 }
916
917- if (interface == QLatin1String("com.canonical.unity.AccountsService")) {
918- if (changed.contains(QStringLiteral("demo-edges"))) {
919- updateDemoEdges();
920- }
921- } else if (interface == QLatin1String("com.canonical.unity.AccountsService.Private")) {
922- if (changed.contains(QStringLiteral("FailedLogins"))) {
923- updateFailedLogins();
924- }
925- } else if (interface == QLatin1String("com.ubuntu.AccountsService.Input")) {
926- if (changed.contains(QStringLiteral("MouseCursorSpeed"))) {
927- updateMouseCursorSpeed();
928- }
929- if (changed.contains(QStringLiteral("TouchpadCursorSpeed"))) {
930- updateTouchpadCursorSpeed();
931- }
932- } else if (interface == QLatin1String("com.ubuntu.touch.AccountsService.SecurityPrivacy")) {
933- if (changed.contains(QStringLiteral("StatsWelcomeScreen"))) {
934- updateStatsWelcomeScreen();
935- }
936- } else if (interface == QLatin1String("com.ubuntu.AccountsService.SecurityPrivacy")) {
937- if (changed.contains(QStringLiteral("PasswordDisplayHint"))) {
938- updatePasswordDisplayHint();
939- }
940- if (changed.contains(QStringLiteral("EnableLauncherWhileLocked"))) {
941- updateEnableLauncherWhileLocked();
942- }
943- if (changed.contains(QStringLiteral("EnableIndicatorsWhileLocked"))) {
944- updateEnableIndicatorsWhileLocked();
945- }
946- } else if (interface == QLatin1String("com.ubuntu.location.providers.here.AccountsService")) {
947- if (changed.contains(QStringLiteral("LicenseAccepted"))) {
948- updateHereEnabled();
949- }
950- if (changed.contains(QStringLiteral("LicenseBasePath"))) {
951- updateHereLicensePath();
952- }
953+ auto propHash = m_properties.value(interface);
954+ auto i = propHash.constBegin();
955+ while (i != propHash.constEnd()) {
956+ if (changed.contains(i.key())) {
957+ updateProperty(interface, i.key());
958+ }
959+ ++i;
960 }
961 }
962
963@@ -514,6 +347,20 @@
964 return;
965 }
966
967- // Standard properties might have changed
968- updateBackgroundFile();
969+ // Any of the standard properties might have changed!
970+ auto propHash = m_properties.value(IFACE_ACCOUNTS_USER);
971+ auto i = propHash.constBegin();
972+ while (i != propHash.constEnd()) {
973+ updateProperty(IFACE_ACCOUNTS_USER, i.key());
974+ ++i;
975+ }
976+}
977+
978+void AccountsService::refresh(bool async)
979+{
980+ auto i = m_properties.constBegin();
981+ while (i != m_properties.constEnd()) {
982+ updateAllProperties(i.key(), async);
983+ ++i;
984+ }
985 }
986
987=== modified file 'plugins/AccountsService/AccountsService.h'
988--- plugins/AccountsService/AccountsService.h 2016-01-21 21:04:00 +0000
989+++ plugins/AccountsService/AccountsService.h 2016-03-11 13:51:30 +0000
990@@ -19,8 +19,10 @@
991 #ifndef UNITY_ACCOUNTSSERVICE_H
992 #define UNITY_ACCOUNTSSERVICE_H
993
994+#include <QHash>
995 #include <QObject>
996 #include <QString>
997+#include <QVariant>
998
999 class AccountsServiceDBusAdaptor;
1000 class QDBusInterface;
1001@@ -109,30 +111,33 @@
1002 void onMaybeChanged(const QString &user);
1003
1004 private:
1005- void updateDemoEdges(bool async = true);
1006- void updateEnableLauncherWhileLocked(bool async = true);
1007- void updateEnableIndicatorsWhileLocked(bool async = true);
1008- void updateBackgroundFile(bool async = true);
1009- void updateMouseCursorSpeed();
1010- void updateTouchpadCursorSpeed();
1011- void updateStatsWelcomeScreen(bool async = true);
1012- void updatePasswordDisplayHint(bool async = true);
1013- void updateFailedLogins(bool async = true);
1014- void updateHereEnabled(bool async = true);
1015- void updateHereLicensePath(bool async = true);
1016-
1017+ typedef QVariant (*ProxyConverter)(const QVariant &);
1018+
1019+ void refresh(bool async);
1020+ void registerProperty(const QString &interface, const QString &property, const QString &signal);
1021+ void registerProxy(const QString &interface, const QString &property, QDBusInterface *iface, const QString &method, ProxyConverter converter = nullptr);
1022+
1023+ void updateAllProperties(const QString &interface, bool async);
1024+ void updateProperty(const QString &interface, const QString &property);
1025+ void updateCache(const QString &interface, const QString &property, const QVariant &value);
1026+
1027+ void setProperty(const QString &interface, const QString &property, const QVariant &value);
1028+ QVariant getProperty(const QString &interface, const QString &property) const;
1029+
1030+ void emitChangedForProperty(const QString &interface, const QString &property);
1031+
1032+ struct PropertyInfo {
1033+ QVariant value{};
1034+ QString signal{};
1035+ QDBusInterface *proxyInterface{};
1036+ QString proxyMethod{};
1037+ ProxyConverter proxyConverter{};
1038+ };
1039+ typedef QHash< QString, QHash<QString, PropertyInfo> > PropertyHash;
1040+ PropertyHash m_properties;
1041 AccountsServiceDBusAdaptor *m_service;
1042 QDBusInterface *m_unityInput;
1043 QString m_user;
1044- bool m_demoEdges;
1045- bool m_enableLauncherWhileLocked;
1046- bool m_enableIndicatorsWhileLocked;
1047- QString m_backgroundFile;
1048- bool m_statsWelcomeScreen;
1049- PasswordDisplayHint m_passwordDisplayHint;
1050- uint m_failedLogins;
1051- bool m_hereEnabled;
1052- QString m_hereLicensePath;
1053 };
1054
1055 #endif
1056
1057=== modified file 'plugins/AccountsService/AccountsServiceDBusAdaptor.cpp'
1058--- plugins/AccountsService/AccountsServiceDBusAdaptor.cpp 2015-10-26 14:05:14 +0000
1059+++ plugins/AccountsService/AccountsServiceDBusAdaptor.cpp 2016-03-11 13:51:30 +0000
1060@@ -1,5 +1,5 @@
1061 /*
1062- * Copyright (C) 2013 Canonical, Ltd.
1063+ * Copyright (C) 2013-2016 Canonical, Ltd.
1064 *
1065 * This program is free software; you can redistribute it and/or modify
1066 * it under the terms of the GNU General Public License as published by
1067@@ -12,8 +12,6 @@
1068 *
1069 * You should have received a copy of the GNU General Public License
1070 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1071- *
1072- * Author: Michael Terry <michael.terry@canonical.com>
1073 */
1074
1075 #include "AccountsServiceDBusAdaptor.h"
1076@@ -37,6 +35,15 @@
1077 connection, this);
1078 }
1079
1080+QDBusPendingReply<QVariantMap> AccountsServiceDBusAdaptor::getAllPropertiesAsync(const QString &user, const QString &interface)
1081+{
1082+ QDBusInterface *iface = getUserInterface(user);
1083+ if (iface != nullptr && iface->isValid()) {
1084+ return iface->asyncCall(QStringLiteral("GetAll"), interface);
1085+ }
1086+ return QDBusPendingReply<QVariantMap>(QDBusMessage::createError(QDBusError::Other, QStringLiteral("Invalid Interface")));
1087+}
1088+
1089 QDBusPendingReply<QVariant> AccountsServiceDBusAdaptor::getUserPropertyAsync(const QString &user, const QString &interface, const QString &property)
1090 {
1091 QDBusInterface *iface = getUserInterface(user);
1092@@ -80,7 +87,7 @@
1093 m_ignoreNextChanged = false;
1094 }
1095
1096-QString AccountsServiceDBusAdaptor::getUserForPath(const QString &path)
1097+QString AccountsServiceDBusAdaptor::getUserForPath(const QString &path) const
1098 {
1099 QMap<QString, QDBusInterface *>::const_iterator i;
1100 for (i = m_users.constBegin(); i != m_users.constEnd(); ++i) {
1101
1102=== modified file 'plugins/AccountsService/AccountsServiceDBusAdaptor.h'
1103--- plugins/AccountsService/AccountsServiceDBusAdaptor.h 2015-10-26 14:05:14 +0000
1104+++ plugins/AccountsService/AccountsServiceDBusAdaptor.h 2016-03-11 13:51:30 +0000
1105@@ -1,5 +1,5 @@
1106 /*
1107- * Copyright (C) 2013 Canonical, Ltd.
1108+ * Copyright (C) 2013-2016 Canonical, Ltd.
1109 *
1110 * This program is free software; you can redistribute it and/or modify
1111 * it under the terms of the GNU General Public License as published by
1112@@ -12,8 +12,6 @@
1113 *
1114 * You should have received a copy of the GNU General Public License
1115 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1116- *
1117- * Authors: Michael Terry <michael.terry@canonical.com>
1118 */
1119
1120 #ifndef UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
1121@@ -35,8 +33,9 @@
1122 explicit AccountsServiceDBusAdaptor(QObject *parent = 0);
1123 ~AccountsServiceDBusAdaptor() = default;
1124
1125- Q_INVOKABLE QDBusPendingReply<QVariant> getUserPropertyAsync(const QString &user, const QString &interface, const QString &property);
1126- Q_INVOKABLE QDBusPendingCall setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value);
1127+ QDBusPendingReply<QVariantMap> getAllPropertiesAsync(const QString &user, const QString &interface);
1128+ QDBusPendingReply<QVariant> getUserPropertyAsync(const QString &user, const QString &interface, const QString &property);
1129+ QDBusPendingCall setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value);
1130
1131 Q_SIGNALS:
1132 void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
1133@@ -48,7 +47,7 @@
1134
1135 private:
1136 QDBusInterface *getUserInterface(const QString &user);
1137- QString getUserForPath(const QString &path);
1138+ QString getUserForPath(const QString &path) const;
1139
1140 QDBusInterface *m_accountsManager;
1141 QMap<QString, QDBusInterface *> m_users;
1142
1143=== modified file 'plugins/Dash/AudioProgressBar.qml'
1144--- plugins/Dash/AudioProgressBar.qml 2015-12-03 14:44:08 +0000
1145+++ plugins/Dash/AudioProgressBar.qml 2016-03-11 13:51:30 +0000
1146@@ -31,6 +31,7 @@
1147 anchors { left: parent.left; right: parent.right }
1148 height: units.dp(6)
1149 source: "graphics/music_progress_bg.png"
1150+ asynchronous: true
1151 sourceSize.width: width
1152 sourceSize.height: height
1153 }
1154
1155=== modified file 'plugins/Dash/CardCreator.js'
1156--- plugins/Dash/CardCreator.js 2016-02-12 00:11:52 +0000
1157+++ plugins/Dash/CardCreator.js 2016-03-11 13:51:30 +0000
1158@@ -18,12 +18,13 @@
1159
1160 // %1 is the template["card-background"]["elements"][0]
1161 // %2 is the template["card-background"]["elements"][1]
1162-// %3 is the template["card-background"] string
1163+// %3 is whether the loader should be asynchronous or not
1164+// %4 is the template["card-background"] string
1165 var kBackgroundLoaderCode = 'Loader {\n\
1166 id: backgroundLoader; \n\
1167 objectName: "backgroundLoader"; \n\
1168 anchors.fill: parent; \n\
1169- asynchronous: root.asynchronous; \n\
1170+ asynchronous: %3; \n\
1171 visible: status == Loader.Ready; \n\
1172 sourceComponent: UbuntuShape { \n\
1173 objectName: "background"; \n\
1174@@ -46,7 +47,7 @@
1175 objectName: "backgroundImage"; \n\
1176 source: { \n\
1177 if (cardData && typeof cardData["background"] === "string") return cardData["background"]; \n\
1178- else return %3; \n\
1179+ else return %4; \n\
1180 } \n\
1181 } \n\
1182 function getColor(index) { \n\
1183@@ -63,8 +64,9 @@
1184 // %3 is used as image height
1185 // %4 is used for artShapeSource.hideSource and inner Loader visible
1186 // %5 is used as aspect ratio fallback
1187-// %6 is injected as code to artImage
1188-// %7 is used as image fallback
1189+// %6 is whether the loader should be asynchronous or not
1190+// %7 is injected as code to artImage
1191+// %8 is used as image fallback
1192 var kArtShapeHolderCode = 'Item { \n\
1193 id: artShapeHolder; \n\
1194 height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height; \n\
1195@@ -73,9 +75,9 @@
1196 Loader { \n\
1197 id: artShapeLoader; \n\
1198 objectName: "artShapeLoader"; \n\
1199- readonly property string cardArt: cardData && cardData["art"] || %7; \n\
1200+ readonly property string cardArt: cardData && cardData["art"] || %8; \n\
1201 active: cardArt != ""; \n\
1202- asynchronous: root.asynchronous; \n\
1203+ asynchronous: %6; \n\
1204 visible: status == Loader.Ready; \n\
1205 sourceComponent: Item { \n\
1206 id: artShape; \n\
1207@@ -132,10 +134,10 @@
1208 id: artImage; \n\
1209 objectName: "artImage"; \n\
1210 source: artShapeLoader.cardArt; \n\
1211- asynchronous: root.asynchronous; \n\
1212+ asynchronous: %6; \n\
1213 width: %2; \n\
1214 height: %3; \n\
1215- %6 \n\
1216+ %7 \n\
1217 } \n\
1218 } \n\
1219 } \n\
1220@@ -144,6 +146,7 @@
1221 // %1 is anchors.fill
1222 // %2 is width
1223 // %3 is height
1224+// %4 is whether the icon should be asynchronous or not
1225 var kAudioButtonCode = 'AbstractButton { \n\
1226 id: audioButton; \n\
1227 anchors.fill: %1; \n\
1228@@ -169,6 +172,7 @@
1229 opacity: 0.9; \n\
1230 name: DashAudioPlayer.playing && AudioUrlComparer.compare(parent.source, DashAudioPlayer.currentSource) ? "media-playback-pause" : "media-playback-start"; \n\
1231 color: "white"; \n\
1232+ asynchronous: %4; \n\
1233 } \n\
1234 onClicked: { \n\
1235 if (AudioUrlComparer.compare(source, DashAudioPlayer.currentSource)) { \n\
1236@@ -187,12 +191,14 @@
1237 } \n\
1238 }';
1239
1240+// %1 is whether the loader should be asynchronous or not
1241+// %2 is the header height code
1242 var kOverlayLoaderCode = 'Loader { \n\
1243 id: overlayLoader; \n\
1244- readonly property real overlayHeight: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
1245+ readonly property real overlayHeight: %2 + units.gu(2); \n\
1246 anchors.fill: artShapeHolder; \n\
1247 active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false; \n\
1248- asynchronous: root.asynchronous; \n\
1249+ asynchronous: %1; \n\
1250 visible: showHeader && status == Loader.Ready; \n\
1251 sourceComponent: UbuntuShapeOverlay { \n\
1252 id: overlay; \n\
1253@@ -211,17 +217,19 @@
1254 objectName: "outerRow"; \n\
1255 property real margins: units.gu(1); \n\
1256 spacing: margins; \n\
1257- height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight; \n\
1258+ %2\
1259 anchors { %1 } \n\
1260 anchors.right: parent.right; \n\
1261 anchors.margins: margins; \n\
1262 anchors.rightMargin: 0; \n\
1263 data: [ \n\
1264- %2 \n\
1265+ %3 \n\
1266 ] \n\
1267 }\n';
1268 var args = Array.prototype.slice.call(arguments);
1269- var code = kHeaderRowCodeTemplate.arg(args.shift()).arg(args.join(',\n'));
1270+ var isCardTool = args.shift();
1271+ var heightCode = isCardTool ? "" : "height: root.fixedHeaderHeight; \n";
1272+ var code = kHeaderRowCodeTemplate.arg(args.shift()).arg(heightCode).arg(args.join(',\n'));
1273 return code;
1274 }
1275
1276@@ -242,10 +250,11 @@
1277 }
1278
1279 // %1 is used as anchors of mascotShapeLoader
1280+// %2 is whether the loader should be asynchronous or not
1281 var kMascotShapeLoaderCode = 'Loader { \n\
1282 id: mascotShapeLoader; \n\
1283 objectName: "mascotShapeLoader"; \n\
1284- asynchronous: root.asynchronous; \n\
1285+ asynchronous: %2; \n\
1286 active: mascotImage.status === Image.Ready; \n\
1287 visible: showHeader && active && status == Loader.Ready; \n\
1288 width: units.gu(6); \n\
1289@@ -275,6 +284,7 @@
1290 // %2 is used as color of titleLabel
1291 // %3 is used as extra condition for visible of titleLabel
1292 // %4 is used as title width
1293+// %5 is used as horizontal alignment
1294 var kTitleLabelCode = 'Label { \n\
1295 id: titleLabel; \n\
1296 objectName: "titleLabel"; \n\
1297@@ -289,7 +299,7 @@
1298 width: %4; \n\
1299 text: root.title; \n\
1300 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal; \n\
1301- horizontalAlignment: root.titleAlignment; \n\
1302+ horizontalAlignment: %5; \n\
1303 }\n';
1304
1305 // %1 is used as extra anchors of emblemIcon
1306@@ -398,7 +408,7 @@
1307 return colorString;
1308 }
1309
1310-function cardString(template, components) {
1311+function cardString(template, components, isCardTool) {
1312 var code;
1313
1314 var templateInteractive = (template == null ? true : (template["non-interactive"] !== undefined ? !template["non-interactive"] : true)) ? "true" : "false";
1315@@ -410,16 +420,16 @@
1316 property string backgroundShapeStyle: "inset"; \n\
1317 property real fontScale: 1.0; \n\
1318 property var scopeStyle: null; \n\
1319- property int titleAlignment: Text.AlignLeft; \n\
1320- property int fixedHeaderHeight: -1; \n\
1321+ %2\
1322 property size fixedArtShapeSize: Qt.size(-1, -1); \n\
1323 readonly property string title: cardData && cardData["title"] || ""; \n\
1324- property bool asynchronous: true; \n\
1325 property bool showHeader: true; \n\
1326 implicitWidth: childrenRect.width; \n\
1327 enabled: %1; \n\
1328 \n'.arg(templateInteractive);
1329
1330+ code = code.arg(isCardTool ? "" : "property int fixedHeaderHeight: -1; \n");
1331+
1332 var hasArt = components["art"] && components["art"]["field"] || false;
1333 var hasSummary = components["summary"] || false;
1334 var isConciergeMode = components["art"] && components["art"]["conciergeMode"] || false;
1335@@ -435,6 +445,7 @@
1336 var hasHeaderRow = hasMascot && hasTitle;
1337 var hasAttributes = hasTitle && components["attributes"] && components["attributes"]["field"] || false;
1338 var isAudio = template["quick-preview-type"] === "audio";
1339+ var asynchronous = isCardTool ? "false" : "true";
1340
1341 if (isAudio) {
1342 // For now we only support audio cards with [optional] art, title, subtitle
1343@@ -468,7 +479,7 @@
1344 backgroundElements1 = '"%1"'.arg(element1);
1345 }
1346 }
1347- code += kBackgroundLoaderCode.arg(backgroundElements0).arg(backgroundElements1).arg(templateCardBackground);
1348+ code += kBackgroundLoaderCode.arg(backgroundElements0).arg(backgroundElements1).arg(asynchronous).arg(templateCardBackground);
1349 }
1350
1351 if (hasArt) {
1352@@ -497,23 +508,31 @@
1353 if (isNaN(aspectRatio)) {
1354 aspectRatio = 1;
1355 }
1356- var fallback = components["art"] && components["art"]["fallback"] || "";
1357+ var fallback = !isCardTool && components["art"] && components["art"]["fallback"] || "";
1358 fallback = encodeURI(fallback);
1359 var fallbackStatusCode = "";
1360 var fallbackURICode = '""';
1361 if (fallback !== "") {
1362 // fallbackStatusCode has %6 in it because we want to substitute it for fallbackURICode
1363- // which in kArtShapeHolderCode is %7
1364- fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %7;';
1365+ // which in kArtShapeHolderCode is %8
1366+ fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %8;';
1367 fallbackURICode = 'decodeURI("%1")'.arg(fallback);
1368 }
1369- code += kArtShapeHolderCode.arg(artAnchors).arg(widthCode).arg(heightCode).arg(isConciergeMode ? "false" : "true").arg(aspectRatio).arg(fallbackStatusCode).arg(fallbackURICode);
1370+ code += kArtShapeHolderCode.arg(artAnchors)
1371+ .arg(widthCode)
1372+ .arg(heightCode)
1373+ .arg(isConciergeMode ? "false" : "true")
1374+ .arg(aspectRatio)
1375+ .arg(asynchronous)
1376+ .arg(fallbackStatusCode)
1377+ .arg(fallbackURICode);
1378 } else {
1379 code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
1380 }
1381
1382 if (headerAsOverlay) {
1383- code += kOverlayLoaderCode;
1384+ var headerHeightCode = isCardTool ? "headerHeight" : "root.fixedHeaderHeight";
1385+ code += kOverlayLoaderCode.arg(asynchronous).arg(headerHeightCode);
1386 }
1387
1388 var headerVerticalAnchors;
1389@@ -595,11 +614,11 @@
1390 }
1391
1392 if (useMascotShape) {
1393- mascotShapeCode = kMascotShapeLoaderCode.arg(mascotAnchors);
1394+ mascotShapeCode = kMascotShapeLoaderCode.arg(mascotAnchors).arg(asynchronous);
1395 }
1396
1397 var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
1398- var fallback = components["mascot"] && components["mascot"]["fallback"] || "";
1399+ var fallback = !isCardTool && components["mascot"] && components["mascot"]["fallback"] || "";
1400 fallback = encodeURI(fallback);
1401 var fallbackStatusCode = "";
1402 var fallbackURICode = '""';
1403@@ -715,9 +734,24 @@
1404 }
1405 }
1406
1407+ var titleAlignment = "Text.AlignHCenter";
1408+ if (template["card-layout"] === "horizontal"
1409+ || typeof components["title"] !== "object"
1410+ || components["title"]["align"] === "left") titleAlignment = "Text.AlignLeft";
1411+ var keys = ["mascot", "emblem", "subtitle", "attributes", "summary"];
1412+ for (var key in keys) {
1413+ key = keys[key];
1414+ try {
1415+ if (typeof components[key] === "string"
1416+ || typeof components[key]["field"] === "string") titleAlignment = "Text.AlignLeft";
1417+ } catch (e) {
1418+ continue;
1419+ }
1420+ }
1421+
1422 // code for different elements
1423 var titleLabelVisibleExtra = (headerAsOverlay ? '&& overlayLoader.active': '');
1424- var titleCode = kTitleLabelCode.arg(titleAnchors).arg(titleColor).arg(titleLabelVisibleExtra).arg(titleWidth);
1425+ var titleCode = kTitleLabelCode.arg(titleAnchors).arg(titleColor).arg(titleLabelVisibleExtra).arg(titleWidth).arg(titleAlignment);
1426 var subtitleCode;
1427 var attributesCode;
1428
1429@@ -759,7 +793,7 @@
1430 if (mascotShapeCode != '') {
1431 rowCode.unshift(mascotShapeCode);
1432 }
1433- code += kHeaderRowCodeGenerator(headerVerticalAnchors + headerLeftAnchor, rowCode)
1434+ code += kHeaderRowCodeGenerator(isCardTool, headerVerticalAnchors + headerLeftAnchor, rowCode)
1435 } else {
1436 code += mascotShapeCode + mascotCode + titleSubtitleCode;
1437 }
1438@@ -783,9 +817,10 @@
1439 } else {
1440 audioButtonAnchorsFill = 'undefined';
1441 audioButtonWidth = 'height';
1442- audioButtonHeight = '(root.fixedHeaderHeight > 0 ? root.fixedHeaderHeight : headerHeight) + 2 * units.gu(1)';
1443+ audioButtonHeight = isCardTool ? 'headerHeight + 2 * units.gu(1)'
1444+ : 'root.fixedHeaderHeight + 2 * units.gu(1)';
1445 }
1446- code += kAudioButtonCode.arg(audioButtonAnchorsFill).arg(audioButtonWidth).arg(audioButtonHeight);
1447+ code += kAudioButtonCode.arg(audioButtonAnchorsFill).arg(audioButtonWidth).arg(audioButtonHeight).arg(asynchronous);
1448 }
1449
1450 if (hasSummary) {
1451@@ -854,13 +889,13 @@
1452 return code;
1453 }
1454
1455-function createCardComponent(parent, template, components, identifier) {
1456+function createCardComponent(parent, template, components, isCardTool, identifier) {
1457 var imports = 'import QtQuick 2.4; \n\
1458 import Ubuntu.Components 1.3; \n\
1459 import Ubuntu.Settings.Components 0.1; \n\
1460 import Dash 0.1;\n\
1461 import Utils 0.1;\n';
1462- var card = cardString(template, components);
1463+ var card = cardString(template, components, isCardTool);
1464 var code = imports + 'Component {\n' + card + '}\n';
1465
1466 try {
1467
1468=== modified file 'plugins/Dash/CardCreatorCache.qml'
1469--- plugins/Dash/CardCreatorCache.qml 2016-01-21 17:56:08 +0000
1470+++ plugins/Dash/CardCreatorCache.qml 2016-03-11 13:51:30 +0000
1471@@ -23,16 +23,16 @@
1472
1473 property var cache: new Object();
1474
1475- function getCardComponent(template, components) {
1476+ function getCardComponent(template, components, isCardTool) {
1477 if (template === undefined || components === undefined)
1478 return undefined;
1479
1480 var tString = JSON.stringify(template);
1481 var cString = JSON.stringify(components);
1482- var allString = tString + cString;
1483+ var allString = tString + cString + isCardTool;
1484 var component = cache[allString];
1485 if (component === undefined) {
1486- component = CardCreator.createCardComponent(root, template, components, allString);
1487+ component = CardCreator.createCardComponent(root, template, components, isCardTool, allString);
1488 cache[allString] = component;
1489 }
1490 return component;
1491
1492=== modified file 'plugins/Dash/plugin.cpp'
1493--- plugins/Dash/plugin.cpp 2015-09-18 07:44:50 +0000
1494+++ plugins/Dash/plugin.cpp 2016-03-11 13:51:30 +0000
1495@@ -28,12 +28,12 @@
1496 static QUrl oauthCleanedUrl(QUrl u)
1497 {
1498 QUrlQuery q(u);
1499- q.removeQueryItem("oauth_nonce");
1500- q.removeQueryItem("oauth_timestamp");
1501- q.removeQueryItem("oauth_consumer_key");
1502- q.removeQueryItem("oauth_signature_method");
1503- q.removeQueryItem("oauth_version");
1504- q.removeQueryItem("oauth_signature");
1505+ q.removeQueryItem(QStringLiteral("oauth_nonce"));
1506+ q.removeQueryItem(QStringLiteral("oauth_timestamp"));
1507+ q.removeQueryItem(QStringLiteral("oauth_consumer_key"));
1508+ q.removeQueryItem(QStringLiteral("oauth_signature_method"));
1509+ q.removeQueryItem(QStringLiteral("oauth_version"));
1510+ q.removeQueryItem(QStringLiteral("oauth_signature"));
1511 u.setQuery(q);
1512 return u;
1513 }
1514
1515=== modified file 'plugins/GlobalShortcut/globalshortcutregistry.cpp'
1516--- plugins/GlobalShortcut/globalshortcutregistry.cpp 2015-11-20 15:01:39 +0000
1517+++ plugins/GlobalShortcut/globalshortcutregistry.cpp 2016-03-11 13:51:30 +0000
1518@@ -35,13 +35,13 @@
1519
1520 bool GlobalShortcutRegistry::hasShortcut(const QVariant &seq) const
1521 {
1522- return m_shortcuts.keys().contains(seq);
1523+ return m_shortcuts.contains(seq);
1524 }
1525
1526 void GlobalShortcutRegistry::addShortcut(const QVariant &seq, GlobalShortcut *sc)
1527 {
1528 if (sc) {
1529- if (!m_shortcuts.keys().contains(seq)) { // create a new entry
1530+ if (!m_shortcuts.contains(seq)) { // create a new entry
1531 m_shortcuts.insert(seq, {sc});
1532 } else { // append to an existing one
1533 auto shortcuts = m_shortcuts[seq];
1534@@ -75,8 +75,8 @@
1535
1536 if (event->type() == QEvent::KeyPress) {
1537 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
1538- QKeySequence seq = QKeySequence(keyEvent->key() + keyEvent->modifiers());
1539- if (m_shortcuts.keys().contains(seq)) {
1540+ int seq = keyEvent->key() + keyEvent->modifiers();
1541+ if (m_shortcuts.contains(seq)) {
1542 const auto shortcuts = m_shortcuts.value(seq);
1543 Q_FOREACH(const auto &shortcut, shortcuts) {
1544 if (shortcut) {
1545
1546=== modified file 'plugins/IntegratedLightDM/liblightdm/CMakeLists.txt'
1547--- plugins/IntegratedLightDM/liblightdm/CMakeLists.txt 2016-02-01 15:15:09 +0000
1548+++ plugins/IntegratedLightDM/liblightdm/CMakeLists.txt 2016-03-11 13:51:30 +0000
1549@@ -5,13 +5,16 @@
1550 UsersModel.cpp
1551 GreeterPrivate.cpp
1552 UsersModelPrivate.cpp
1553+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
1554 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
1555 )
1556
1557 add_library(integratedLightDM STATIC ${LibLightDM_SOURCES})
1558+add_library(integratedLightDMSession STATIC ${LibLightDM_SOURCES})
1559 add_library(MockLightDM-demo-shared SHARED ${LibLightDM_SOURCES})
1560
1561 include_directories(
1562+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
1563 ${CMAKE_CURRENT_BINARY_DIR}
1564 ${GLIB_INCLUDE_DIRS}
1565 ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
1566@@ -22,17 +25,27 @@
1567 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
1568 -lpam
1569 )
1570+target_link_libraries(integratedLightDMSession
1571+ ${GLIB_LIBRARIES}
1572+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
1573+ -lpam
1574+)
1575 target_link_libraries(MockLightDM-demo-shared
1576 ${GLIB_LIBRARIES}
1577 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
1578 -lpam
1579 )
1580
1581-qt5_use_modules(integratedLightDM Concurrent Gui)
1582-qt5_use_modules(MockLightDM-demo-shared Concurrent Gui)
1583+qt5_use_modules(integratedLightDM Concurrent DBus Gui)
1584+qt5_use_modules(integratedLightDMSession Concurrent DBus Gui)
1585+qt5_use_modules(MockLightDM-demo-shared Concurrent DBus Gui)
1586
1587-set_target_properties(integratedLightDM PROPERTIES COMPILE_FLAGS -fPIC)
1588+set_target_properties(integratedLightDM PROPERTIES
1589+ COMPILE_FLAGS "-DSM_BUSNAME=systemBus -fPIC")
1590+set_target_properties(integratedLightDMSession PROPERTIES
1591+ COMPILE_FLAGS "-DSM_BUSNAME=sessionBus -fPIC")
1592 set_target_properties(MockLightDM-demo-shared PROPERTIES
1593+ COMPILE_FLAGS "-DSM_BUSNAME=systemBus"
1594 OUTPUT_NAME lightdm-qt5-2)
1595
1596 install(TARGETS MockLightDM-demo-shared
1597
1598=== modified file 'plugins/IntegratedLightDM/liblightdm/UsersModel.cpp'
1599--- plugins/IntegratedLightDM/liblightdm/UsersModel.cpp 2015-09-14 09:11:08 +0000
1600+++ plugins/IntegratedLightDM/liblightdm/UsersModel.cpp 2016-03-11 13:51:30 +0000
1601@@ -54,24 +54,10 @@
1602 roles[ImagePathRole] = "imagePath";
1603 setRoleNames(roles);
1604
1605- // Now modify our mock user backgrounds
1606- QDir bgdir = QDir(QStringLiteral("/usr/share/demo-assets/shell/backgrounds/"));
1607- QStringList backgrounds = bgdir.entryList(QDir::Files | QDir::NoDotAndDotDot);
1608-
1609- for (int i = 0, j = 0; i < d->entries.size(); i++) {
1610- Entry &entry = d->entries[i];
1611- if (entry.background.isNull() && !backgrounds.isEmpty()) {
1612- entry.background = bgdir.filePath(backgrounds[j++]);
1613- if (j >= backgrounds.length()) {
1614- j = 0;
1615- }
1616- }
1617- }
1618-}
1619-
1620-UsersModel::~UsersModel()
1621-{
1622- delete d_ptr;
1623+ connect(d_ptr, &UsersModelPrivate::dataChanged, this, [this](int i) {
1624+ QModelIndex index = createIndex(i, 0);
1625+ Q_EMIT dataChanged(index, index);
1626+ });
1627 }
1628
1629 int UsersModel::rowCount(const QModelIndex &parent) const
1630
1631=== modified file 'plugins/IntegratedLightDM/liblightdm/UsersModel.h'
1632--- plugins/IntegratedLightDM/liblightdm/UsersModel.h 2015-04-30 09:31:51 +0000
1633+++ plugins/IntegratedLightDM/liblightdm/UsersModel.h 2016-03-11 13:51:30 +0000
1634@@ -41,7 +41,7 @@
1635
1636 public:
1637 explicit UsersModel(QObject *parent = 0);
1638- virtual ~UsersModel();
1639+ virtual ~UsersModel() = default;
1640
1641 enum UserModelRoles {NameRole = Qt::UserRole,
1642 RealNameRole,
1643
1644=== modified file 'plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp'
1645--- plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp 2016-02-04 14:10:42 +0000
1646+++ plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp 2016-03-11 13:51:30 +0000
1647@@ -18,7 +18,11 @@
1648
1649 #include "UsersModelPrivate.h"
1650
1651+#include "AccountsServiceDBusAdaptor.h"
1652+#include "UsersModel.h"
1653+
1654 #include <glib.h>
1655+#include <QDebug>
1656 #include <QDir>
1657 #include <QSettings>
1658 #include <QStringList>
1659@@ -27,7 +31,9 @@
1660 {
1661
1662 UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
1663- : q_ptr(parent)
1664+ : QObject(parent),
1665+ q_ptr(parent),
1666+ m_service(new AccountsServiceDBusAdaptor(this))
1667 {
1668 QFileInfo demoFile(QDir::homePath() + "/.unity8-greeter-demo");
1669 QString currentUser = g_get_user_name();
1670@@ -43,15 +49,43 @@
1671 entries.append({user, name, 0, 0, false, false, 0, 0});
1672 }
1673 } else {
1674- // If we were using the actual liblightdm, we could just ask it
1675- // for the user's real name. But we aren't. We *should* ask
1676- // AccountsService for the real name, like liblightdm does internally,
1677- // but this is close enough since AS and passwd are always in sync.
1678- QString realName = QString::fromUtf8(g_get_real_name()); // gets name from passwd entry
1679- if (realName == QStringLiteral("Unknown")) { // glib doesn't translate this string
1680- realName.clear();
1681- }
1682- entries.append({currentUser, realName, 0, 0, false, false, 0, 0});
1683+ entries.append({currentUser, 0, 0, 0, false, false, 0, 0});
1684+
1685+ connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
1686+ this, [this](const QString &user) {
1687+ if (user == entries[0].username) {
1688+ updateName(true);
1689+ }
1690+ });
1691+ updateName(false);
1692+ }
1693+}
1694+
1695+void UsersModelPrivate::updateName(bool async)
1696+{
1697+ auto pendingReply = m_service->getUserPropertyAsync(entries[0].username,
1698+ QStringLiteral("org.freedesktop.Accounts.User"),
1699+ QStringLiteral("RealName"));
1700+ auto *watcher = new QDBusPendingCallWatcher(pendingReply, this);
1701+
1702+ connect(watcher, &QDBusPendingCallWatcher::finished,
1703+ this, [this](QDBusPendingCallWatcher* watcher) {
1704+
1705+ QDBusPendingReply<QVariant> reply = *watcher;
1706+ watcher->deleteLater();
1707+ if (reply.isError()) {
1708+ qWarning() << "Failed to get 'RealName' property - " << reply.error().message();
1709+ return;
1710+ }
1711+
1712+ const QString realName = reply.value().toString();
1713+ if (entries[0].real_name != realName) {
1714+ entries[0].real_name = realName;
1715+ Q_EMIT dataChanged(0);
1716+ }
1717+ });
1718+ if (!async) {
1719+ watcher->waitForFinished();
1720 }
1721 }
1722
1723
1724=== modified file 'plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h'
1725--- plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h 2015-01-20 11:50:19 +0000
1726+++ plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h 2016-03-11 13:51:30 +0000
1727@@ -19,8 +19,11 @@
1728 #ifndef UNITY_MOCK_USERSMODEL_PRIVATE_H
1729 #define UNITY_MOCK_USERSMODEL_PRIVATE_H
1730
1731-#include <QtCore/QList>
1732-#include <QtCore/QString>
1733+#include <QList>
1734+#include <QObject>
1735+#include <QString>
1736+
1737+class AccountsServiceDBusAdaptor;
1738
1739 namespace QLightDM
1740 {
1741@@ -39,19 +42,28 @@
1742 QString infographic;
1743 };
1744
1745-class UsersModelPrivate
1746+class UsersModelPrivate : public QObject
1747 {
1748+ Q_OBJECT
1749+
1750 public:
1751 explicit UsersModelPrivate(UsersModel *parent = 0);
1752 virtual ~UsersModelPrivate() = default;
1753
1754 QList<Entry> entries;
1755
1756+Q_SIGNALS:
1757+ void dataChanged(int);
1758+
1759 protected:
1760 UsersModel * const q_ptr;
1761
1762 private:
1763 Q_DECLARE_PUBLIC(UsersModel)
1764+
1765+ void updateName(bool async);
1766+
1767+ AccountsServiceDBusAdaptor *m_service;
1768 };
1769
1770 }
1771
1772=== modified file 'plugins/Unity/Indicators/indicatorsmanager.cpp'
1773--- plugins/Unity/Indicators/indicatorsmanager.cpp 2015-12-02 12:02:50 +0000
1774+++ plugins/Unity/Indicators/indicatorsmanager.cpp 2016-03-11 13:51:30 +0000
1775@@ -116,7 +116,7 @@
1776 QSettings indicator_settings(file_info.absoluteFilePath(), QSettings::IniFormat, this);
1777 const QString name = indicator_settings.value(QStringLiteral("Indicator Service/Name")).toString();
1778
1779- if (m_platform.isPC() && name == "indicator-keyboard") {
1780+ if (m_platform.isPC() && name == QLatin1String("indicator-keyboard")) {
1781 return; // convergence: skip this indicator until it works in Mir
1782 }
1783
1784@@ -293,7 +293,7 @@
1785 // The rest of the indicators respect their default profile (which is "phone", even on desktop PCs)
1786 if ((new_indicator->identifier() == QStringLiteral("indicator-session") && m_platform.isMultiSession())
1787 || (new_indicator->identifier() == QStringLiteral("indicator-power") && m_platform.isPC())) {
1788- new_indicator->setProfile("desktop");
1789+ new_indicator->setProfile(QStringLiteral("desktop"));
1790 } else {
1791 new_indicator->setProfile(m_profile);
1792 }
1793
1794=== modified file 'plugins/Unity/Indicators/rootstateparser.h'
1795--- plugins/Unity/Indicators/rootstateparser.h 2014-11-11 15:28:13 +0000
1796+++ plugins/Unity/Indicators/rootstateparser.h 2016-03-11 13:51:30 +0000
1797@@ -23,6 +23,7 @@
1798
1799 class UNITYINDICATORS_EXPORT RootStateParser : public ActionStateParser
1800 {
1801+Q_OBJECT
1802 public:
1803 RootStateParser(QObject* parent = nullptr);
1804 virtual QVariant toQVariant(GVariant* state) const override;
1805
1806=== modified file 'plugins/Unity/Launcher/desktopfilehandler.cpp'
1807--- plugins/Unity/Launcher/desktopfilehandler.cpp 2015-09-30 12:43:53 +0000
1808+++ plugins/Unity/Launcher/desktopfilehandler.cpp 2016-03-11 13:51:30 +0000
1809@@ -146,9 +146,9 @@
1810 QString iconString = settings.value(QStringLiteral("Icon")).toString();
1811 QString pathString = settings.value(QStringLiteral("Path")).toString();
1812
1813- if (QFileInfo(iconString).exists()) {
1814+ if (QFileInfo::exists(iconString)) {
1815 return QFileInfo(iconString).absoluteFilePath();
1816- } else if (QFileInfo(pathString + '/' + iconString).exists()) {
1817+ } else if (QFileInfo::exists(pathString + '/' + iconString)) {
1818 return pathString + '/' + iconString;
1819 }
1820 return "image://theme/" + iconString;
1821
1822=== modified file 'plugins/Unity/Launcher/launcheritem.cpp'
1823--- plugins/Unity/Launcher/launcheritem.cpp 2015-09-14 09:11:08 +0000
1824+++ plugins/Unity/Launcher/launcheritem.cpp 2016-03-11 13:51:30 +0000
1825@@ -37,6 +37,7 @@
1826 m_alerting(false),
1827 m_quickList(new QuickListModel(this))
1828 {
1829+ Q_ASSERT(parent != nullptr);
1830 QuickListEntry nameAction;
1831 nameAction.setActionId(QStringLiteral("launch_item"));
1832 nameAction.setText(m_name);
1833
1834=== modified file 'plugins/Unity/Launcher/launcheritem.h'
1835--- plugins/Unity/Launcher/launcheritem.h 2015-07-23 14:13:57 +0000
1836+++ plugins/Unity/Launcher/launcheritem.h 2016-03-11 13:51:30 +0000
1837@@ -32,7 +32,7 @@
1838 {
1839 Q_OBJECT
1840 public:
1841- LauncherItem(const QString &appId, const QString &name, const QString &icon, QObject *parent = 0);
1842+ LauncherItem(const QString &appId, const QString &name, const QString &icon, QObject *parent);
1843
1844 QString appId() const override;
1845 QString name() const override;
1846
1847=== modified file 'plugins/Unity/Launcher/launchermodel.cpp'
1848--- plugins/Unity/Launcher/launchermodel.cpp 2015-09-14 09:11:08 +0000
1849+++ plugins/Unity/Launcher/launchermodel.cpp 2016-03-11 13:51:30 +0000
1850@@ -103,7 +103,7 @@
1851 LauncherItem *item = m_list.at(index);
1852 if (!item->focused()) {
1853 item->setAlerting(alerting);
1854- Q_EMIT dataChanged(modelIndex, modelIndex, QVector<int>() << RoleAlerting);
1855+ Q_EMIT dataChanged(modelIndex, modelIndex, {RoleAlerting});
1856 }
1857 }
1858 }
1859@@ -389,7 +389,8 @@
1860 if (countVisible && desktopFile.isValid()) {
1861 LauncherItem *item = new LauncherItem(appId,
1862 desktopFile.displayName(),
1863- desktopFile.icon());
1864+ desktopFile.icon(),
1865+ this);
1866 item->setCountVisible(true);
1867 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
1868 m_list.append(item);
1869@@ -414,10 +415,19 @@
1870 } else {
1871 int idx = m_list.indexOf(item);
1872 item->setName(desktopFile.displayName());
1873- item->setIcon(desktopFile.icon());
1874 item->setPinned(item->pinned()); // update pinned text if needed
1875 item->setRunning(item->running());
1876- Q_EMIT dataChanged(index(idx), index(idx), {RoleName, RoleIcon, RoleRunning});
1877+ Q_EMIT dataChanged(index(idx), index(idx), {RoleName, RoleRunning});
1878+
1879+ const QString oldIcon = item->icon();
1880+ if (oldIcon == desktopFile.icon()) { // same icon file, perhaps different contents, simulate changing the icon name to force reload
1881+ item->setIcon(QString());
1882+ Q_EMIT dataChanged(index(idx), index(idx), {RoleIcon});
1883+ }
1884+
1885+ // now set the icon for real
1886+ item->setIcon(desktopFile.icon());
1887+ Q_EMIT dataChanged(index(idx), index(idx), {RoleIcon});
1888 }
1889 }
1890
1891@@ -489,7 +499,7 @@
1892 if (idx >= 0) {
1893 LauncherItem *item = m_list.at(idx);
1894 setAlerting(item->appId(), true);
1895- Q_EMIT dataChanged(index(idx), index(idx), QVector<int>() << RoleAlerting);
1896+ Q_EMIT dataChanged(index(idx), index(idx), {RoleAlerting});
1897 }
1898 }
1899
1900
1901=== modified file 'plugins/Unity/Launcher/launchermodel.h'
1902--- plugins/Unity/Launcher/launchermodel.h 2015-07-29 12:32:57 +0000
1903+++ plugins/Unity/Launcher/launchermodel.h 2016-03-11 13:51:30 +0000
1904@@ -38,7 +38,7 @@
1905 Q_OBJECT
1906
1907 public:
1908- LauncherModel(QObject *parent = 0);
1909+ LauncherModel(QObject *parent = nullptr);
1910 ~LauncherModel();
1911
1912 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
1913
1914=== modified file 'plugins/Utils/CMakeLists.txt'
1915--- plugins/Utils/CMakeLists.txt 2016-02-08 09:37:48 +0000
1916+++ plugins/Utils/CMakeLists.txt 2016-03-11 13:51:30 +0000
1917@@ -23,6 +23,7 @@
1918 windowstatestorage.cpp
1919 timezoneFormatter.cpp
1920 inputeventgenerator.cpp
1921+ deviceconfigparser.cpp
1922 plugin.cpp
1923 )
1924
1925
1926=== added file 'plugins/Utils/deviceconfigparser.cpp'
1927--- plugins/Utils/deviceconfigparser.cpp 1970-01-01 00:00:00 +0000
1928+++ plugins/Utils/deviceconfigparser.cpp 2016-03-11 13:51:30 +0000
1929@@ -0,0 +1,150 @@
1930+/*
1931+ * Copyright 2016 Canonical Ltd.
1932+ *
1933+ * This program is free software; you can redistribute it and/or modify
1934+ * it under the terms of the GNU Lesser General Public License as published by
1935+ * the Free Software Foundation; version 3.
1936+ *
1937+ * This program is distributed in the hope that it will be useful,
1938+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1939+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1940+ * GNU Lesser General Public License for more details.
1941+ *
1942+ * You should have received a copy of the GNU Lesser General Public License
1943+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1944+ */
1945+
1946+#include "deviceconfigparser.h"
1947+
1948+#include <QSettings>
1949+#include <QFileInfo>
1950+#include <QDebug>
1951+#include <QStandardPaths>
1952+
1953+DeviceConfigParser::DeviceConfigParser(QObject *parent): QObject(parent)
1954+{
1955+ QString path;
1956+ Q_FOREACH (const QString &standardPath, QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation)) {
1957+ if (QFileInfo(standardPath + "/devices.conf").exists()) {
1958+ path = standardPath + "/devices.conf";
1959+ break;
1960+ }
1961+ }
1962+
1963+ if (path.isEmpty()) {
1964+ path = "/etc/ubuntu/devices.conf";
1965+ }
1966+ qDebug() << "Using" << path << "as device configuration file";
1967+ m_config = new QSettings(path, QSettings::IniFormat, this);
1968+}
1969+
1970+QString DeviceConfigParser::name() const
1971+{
1972+ return m_name;
1973+}
1974+
1975+void DeviceConfigParser::setName(const QString &name)
1976+{
1977+ if (m_name == name) {
1978+ return;
1979+ }
1980+ m_name = name;
1981+ Q_EMIT changed();
1982+}
1983+
1984+Qt::ScreenOrientation DeviceConfigParser::primaryOrientation() const
1985+{
1986+ return stringToOrientation(readOrientationFromConfig("PrimaryOrientation"), Qt::PrimaryOrientation);
1987+}
1988+
1989+Qt::ScreenOrientations DeviceConfigParser::supportedOrientations() const
1990+{
1991+ QStringList values = readOrientationsFromConfig("SupportedOrientations");
1992+ if (values.isEmpty()) {
1993+ return Qt::PortraitOrientation
1994+ | Qt::InvertedPortraitOrientation
1995+ | Qt::LandscapeOrientation
1996+ | Qt::InvertedLandscapeOrientation;
1997+ }
1998+
1999+ Qt::ScreenOrientations ret = Qt::PrimaryOrientation;
2000+ Q_FOREACH(const QString &orientationString, values) {
2001+ ret |= stringToOrientation(orientationString, Qt::PrimaryOrientation);
2002+ }
2003+ return ret;
2004+}
2005+
2006+Qt::ScreenOrientation DeviceConfigParser::landscapeOrientation() const
2007+{
2008+ return stringToOrientation(readOrientationFromConfig("LandscapeOrientation"), Qt::LandscapeOrientation);
2009+}
2010+
2011+Qt::ScreenOrientation DeviceConfigParser::invertedLandscapeOrientation() const
2012+{
2013+ return stringToOrientation(readOrientationFromConfig("InvertedLandscapeOrientation"), Qt::InvertedLandscapeOrientation);
2014+}
2015+
2016+Qt::ScreenOrientation DeviceConfigParser::portraitOrientation() const
2017+{
2018+ return stringToOrientation(readOrientationFromConfig("PortraitOrientation"), Qt::PortraitOrientation);
2019+}
2020+
2021+Qt::ScreenOrientation DeviceConfigParser::invertedPortraitOrientation() const
2022+{
2023+ return stringToOrientation(readOrientationFromConfig("InvertedPortraitOrientation"), Qt::InvertedPortraitOrientation);
2024+}
2025+
2026+QString DeviceConfigParser::category() const
2027+{
2028+ QStringList supportedValues = {"phone", "tablet", "desktop"};
2029+ m_config->beginGroup(m_name);
2030+ QString value = m_config->value("Category", "phone").toString();
2031+ if (!supportedValues.contains(value)) {
2032+ qWarning().nospace().noquote() << "Unknown option \"" << value << "\" in " << m_config->fileName()
2033+ << ". Supported options are: " << supportedValues.join(", ") << ".";
2034+ return "phone";
2035+ }
2036+ m_config->endGroup();
2037+ return value;
2038+}
2039+
2040+QStringList DeviceConfigParser::readOrientationsFromConfig(const QString &key) const
2041+{
2042+ m_config->beginGroup(m_name);
2043+
2044+ QStringList ret;
2045+ if (m_config->contains(key)) {
2046+ ret = m_config->value(key).toStringList();
2047+ }
2048+
2049+ m_config->endGroup();
2050+ return ret;
2051+}
2052+
2053+QString DeviceConfigParser::readOrientationFromConfig(const QString &key) const
2054+{
2055+ QStringList ret = readOrientationsFromConfig(key);
2056+ return ret.count() > 0 ? ret.first() : QString();
2057+}
2058+
2059+Qt::ScreenOrientation DeviceConfigParser::stringToOrientation(const QString &orientationString, Qt::ScreenOrientation defaultValue) const
2060+{
2061+ if (orientationString == "Landscape") {
2062+ return Qt::LandscapeOrientation;
2063+ }
2064+ if (orientationString == "InvertedLandscape") {
2065+ return Qt::InvertedLandscapeOrientation;
2066+ }
2067+ if (orientationString == "Portrait") {
2068+ return Qt::PortraitOrientation;
2069+ }
2070+ if (orientationString == "InvertedPortrait") {
2071+ return Qt::InvertedPortraitOrientation;
2072+ }
2073+ if (!orientationString.isEmpty()) {
2074+ // Some option we don't know. Give some hint on what went wrong.
2075+ qWarning().nospace().noquote() << "Unknown option \"" << orientationString << "\" in " << m_config->fileName()
2076+ << ". Supported options are: Landscape, InvertedLandscape, Portrait and InvertedPortrait.";
2077+ }
2078+ return defaultValue;
2079+}
2080
2081=== added file 'plugins/Utils/deviceconfigparser.h'
2082--- plugins/Utils/deviceconfigparser.h 1970-01-01 00:00:00 +0000
2083+++ plugins/Utils/deviceconfigparser.h 2016-03-11 13:51:30 +0000
2084@@ -0,0 +1,62 @@
2085+/*
2086+ * Copyright 2016 Canonical Ltd.
2087+ *
2088+ * This program is free software; you can redistribute it and/or modify
2089+ * it under the terms of the GNU Lesser General Public License as published by
2090+ * the Free Software Foundation; version 3.
2091+ *
2092+ * This program is distributed in the hope that it will be useful,
2093+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2094+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2095+ * GNU Lesser General Public License for more details.
2096+ *
2097+ * You should have received a copy of the GNU Lesser General Public License
2098+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2099+ */
2100+
2101+#ifndef DEVICECONFIGPARSER_H
2102+#define DEVICECONFIGPARSER_H
2103+
2104+#include <QObject>
2105+#include <QSettings>
2106+
2107+class DeviceConfigParser: public QObject
2108+{
2109+ Q_OBJECT
2110+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY changed)
2111+
2112+ Q_PROPERTY(Qt::ScreenOrientation primaryOrientation READ primaryOrientation NOTIFY changed)
2113+ Q_PROPERTY(Qt::ScreenOrientations supportedOrientations READ supportedOrientations NOTIFY changed)
2114+ Q_PROPERTY(Qt::ScreenOrientation landscapeOrientation READ landscapeOrientation NOTIFY changed)
2115+ Q_PROPERTY(Qt::ScreenOrientation invertedLandscapeOrientation READ invertedLandscapeOrientation NOTIFY changed)
2116+ Q_PROPERTY(Qt::ScreenOrientation portraitOrientation READ portraitOrientation NOTIFY changed)
2117+ Q_PROPERTY(Qt::ScreenOrientation invertedPortraitOrientation READ invertedPortraitOrientation NOTIFY changed)
2118+ Q_PROPERTY(QString category READ category NOTIFY changed)
2119+
2120+public:
2121+ DeviceConfigParser(QObject *parent = nullptr);
2122+
2123+ QString name() const;
2124+ void setName(const QString &name);
2125+
2126+ Qt::ScreenOrientation primaryOrientation() const;
2127+ Qt::ScreenOrientations supportedOrientations() const;
2128+ Qt::ScreenOrientation landscapeOrientation() const;
2129+ Qt::ScreenOrientation invertedLandscapeOrientation() const;
2130+ Qt::ScreenOrientation portraitOrientation() const;
2131+ Qt::ScreenOrientation invertedPortraitOrientation() const;
2132+ QString category() const;
2133+
2134+Q_SIGNALS:
2135+ void changed();
2136+
2137+private:
2138+ QString m_name;
2139+ QSettings *m_config;
2140+
2141+ QStringList readOrientationsFromConfig(const QString &key) const;
2142+ QString readOrientationFromConfig(const QString &key) const;
2143+ Qt::ScreenOrientation stringToOrientation(const QString &orientationString, Qt::ScreenOrientation defaultValue) const;
2144+};
2145+
2146+#endif
2147
2148=== modified file 'plugins/Utils/plugin.cpp'
2149--- plugins/Utils/plugin.cpp 2016-01-29 11:52:14 +0000
2150+++ plugins/Utils/plugin.cpp 2016-03-11 13:51:30 +0000
2151@@ -37,6 +37,7 @@
2152 #include "timezoneFormatter.h"
2153 #include "applicationsfiltermodel.h"
2154 #include "inputeventgenerator.h"
2155+#include "deviceconfigparser.h"
2156
2157 static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
2158 {
2159@@ -70,6 +71,7 @@
2160 qmlRegisterType<ActiveFocusLogger>(uri, 0, 1, "ActiveFocusLogger");
2161 qmlRegisterType<ApplicationsFilterModel>(uri, 0, 1, "ApplicationsFilterModel");
2162 qmlRegisterType<InputEventGenerator>(uri, 0, 1, "InputEventGenerator");
2163+ qmlRegisterType<DeviceConfigParser>(uri, 0, 1, "DeviceConfigParser");
2164 }
2165
2166 void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
2167
2168=== modified file 'po/unity8.pot'
2169--- po/unity8.pot 2016-03-08 21:04:17 +0000
2170+++ po/unity8.pot 2016-03-11 13:51:30 +0000
2171@@ -8,7 +8,7 @@
2172 msgstr ""
2173 "Project-Id-Version: unity8\n"
2174 "Report-Msgid-Bugs-To: \n"
2175-"POT-Creation-Date: 2016-03-08 21:04+0000\n"
2176+"POT-Creation-Date: 2016-03-10 22:48+0000\n"
2177 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
2178 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
2179 "Language-Team: LANGUAGE <LL@li.org>\n"
2180@@ -22,16 +22,16 @@
2181 msgid "Password: "
2182 msgstr ""
2183
2184-#: plugins/Unity/Launcher/launcheritem.cpp:47
2185-#: plugins/Unity/Launcher/launcheritem.cpp:106
2186+#: plugins/Unity/Launcher/launcheritem.cpp:48
2187+#: plugins/Unity/Launcher/launcheritem.cpp:107
2188 msgid "Pin shortcut"
2189 msgstr ""
2190
2191-#: plugins/Unity/Launcher/launcheritem.cpp:52
2192+#: plugins/Unity/Launcher/launcheritem.cpp:53
2193 msgid "Quit"
2194 msgstr ""
2195
2196-#: plugins/Unity/Launcher/launcheritem.cpp:106
2197+#: plugins/Unity/Launcher/launcheritem.cpp:107
2198 msgid "Unpin shortcut"
2199 msgstr ""
2200
2201@@ -135,15 +135,15 @@
2202 msgid "Restart"
2203 msgstr ""
2204
2205-#: qml/Components/Lockscreen.qml:245
2206+#: qml/Components/Lockscreen.qml:231
2207 msgid "Return to Call"
2208 msgstr ""
2209
2210-#: qml/Components/Lockscreen.qml:245
2211+#: qml/Components/Lockscreen.qml:231
2212 msgid "Emergency Call"
2213 msgstr ""
2214
2215-#: qml/Components/Lockscreen.qml:277
2216+#: qml/Components/Lockscreen.qml:263
2217 msgid "OK"
2218 msgstr ""
2219
2220@@ -152,6 +152,8 @@
2221 msgstr ""
2222
2223 #: qml/Components/ModeSwitchWarningDialog.qml:57
2224+msgctxt ""
2225+"Re-dock means connect the device again to an external screen/mouse/keyboard"
2226 msgid "Re-dock, save your work and close these apps to continue."
2227 msgstr ""
2228
2229@@ -194,15 +196,15 @@
2230 msgid "Add to Favorites"
2231 msgstr ""
2232
2233-#: qml/Dash/GenericScopeView.qml:565 qml/Dash/GenericScopeView.qml:723
2234+#: qml/Dash/GenericScopeView.qml:567 qml/Dash/GenericScopeView.qml:725
2235 msgid "See less"
2236 msgstr ""
2237
2238-#: qml/Dash/GenericScopeView.qml:565
2239+#: qml/Dash/GenericScopeView.qml:567
2240 msgid "See all"
2241 msgstr ""
2242
2243-#: qml/Dash/GenericScopeView.qml:627
2244+#: qml/Dash/GenericScopeView.qml:629
2245 msgctxt "Label: Hint for dash search line edit"
2246 msgid "Search"
2247 msgstr ""
2248@@ -228,7 +230,7 @@
2249 msgid "Add a review"
2250 msgstr ""
2251
2252-#: qml/Dash/Previews/PreviewSharing.qml:50
2253+#: qml/Dash/Previews/PreviewSharing.qml:66
2254 msgid "Preview Share Item"
2255 msgstr ""
2256
2257@@ -256,13 +258,13 @@
2258 msgid "Also installed"
2259 msgstr ""
2260
2261-#: qml/DisabledScreenNotice.qml:87
2262+#: qml/DisabledScreenNotice.qml:104
2263 msgid ""
2264 "Your device is now connected to an external display. Use this screen as a "
2265-"touch pad to interact with the mouse."
2266+"touch pad to interact with the pointer."
2267 msgstr ""
2268
2269-#: qml/Greeter/CoverPage.qml:107
2270+#: qml/Greeter/CoverPage.qml:118
2271 msgid "Unlock"
2272 msgstr ""
2273
2274@@ -341,62 +343,62 @@
2275 msgid "Conference"
2276 msgstr ""
2277
2278-#: qml/Panel/Indicators/MenuItemFactory.qml:753
2279+#: qml/Panel/Indicators/MenuItemFactory.qml:752
2280 msgid "Nothing is playing"
2281 msgstr ""
2282
2283-#: qml/Panel/Indicators/MenuItemFactory.qml:882
2284+#: qml/Panel/Indicators/MenuItemFactory.qml:881
2285 #, qt-format
2286 msgid "%1 hour"
2287 msgid_plural "%1 hours"
2288 msgstr[0] ""
2289 msgstr[1] ""
2290
2291-#: qml/Panel/Indicators/MenuItemFactory.qml:886
2292+#: qml/Panel/Indicators/MenuItemFactory.qml:885
2293 #, qt-format
2294 msgid "%1 minute"
2295 msgid_plural "%1 minutes"
2296 msgstr[0] ""
2297 msgstr[1] ""
2298
2299-#: qml/Panel/Indicators/MenuItemFactory.qml:891
2300+#: qml/Panel/Indicators/MenuItemFactory.qml:890
2301 #, qt-format
2302 msgid "%1 second"
2303 msgid_plural "%1 seconds"
2304 msgstr[0] ""
2305 msgstr[1] ""
2306
2307-#: qml/Panel/Indicators/MenuItemFactory.qml:894
2308+#: qml/Panel/Indicators/MenuItemFactory.qml:893
2309 msgid "0 seconds"
2310 msgstr ""
2311
2312 #. Translators: String like "1 hour, 2 minutes, 3 seconds remaining"
2313-#: qml/Panel/Indicators/MenuItemFactory.qml:896
2314+#: qml/Panel/Indicators/MenuItemFactory.qml:895
2315 #, qt-format
2316 msgid "%1 remaining"
2317 msgstr ""
2318
2319-#: qml/Panel/Indicators/MenuItemFactory.qml:902
2320+#: qml/Panel/Indicators/MenuItemFactory.qml:901
2321 msgid "In queue…"
2322 msgstr ""
2323
2324-#: qml/Panel/Indicators/MenuItemFactory.qml:906
2325+#: qml/Panel/Indicators/MenuItemFactory.qml:905
2326 msgid "Downloading"
2327 msgstr ""
2328
2329-#: qml/Panel/Indicators/MenuItemFactory.qml:908
2330+#: qml/Panel/Indicators/MenuItemFactory.qml:907
2331 msgid "Paused, tap to resume"
2332 msgstr ""
2333
2334-#: qml/Panel/Indicators/MenuItemFactory.qml:910
2335+#: qml/Panel/Indicators/MenuItemFactory.qml:909
2336 msgid "Canceled"
2337 msgstr ""
2338
2339-#: qml/Panel/Indicators/MenuItemFactory.qml:912
2340+#: qml/Panel/Indicators/MenuItemFactory.qml:911
2341 msgid "Finished"
2342 msgstr ""
2343
2344-#: qml/Panel/Indicators/MenuItemFactory.qml:914
2345+#: qml/Panel/Indicators/MenuItemFactory.qml:913
2346 msgid "Failed, tap to retry"
2347 msgstr ""
2348
2349
2350=== modified file 'qml/Components/EdgeBarrier.qml'
2351--- qml/Components/EdgeBarrier.qml 2015-11-24 17:44:18 +0000
2352+++ qml/Components/EdgeBarrier.qml 2016-03-11 13:51:30 +0000
2353@@ -105,7 +105,7 @@
2354 },
2355 Transition {
2356 from: "resisting"; to: "passed"
2357- UbuntuNumberAnimation { target: materialContainer; property: "opacity" }
2358+ UbuntuNumberAnimation { duration: UbuntuAnimation.BriskDuration; target: materialContainer; property: "opacity" }
2359 }
2360 ]
2361 }
2362
2363=== modified file 'qml/Components/InputMethod.qml'
2364--- qml/Components/InputMethod.qml 2015-12-02 10:34:31 +0000
2365+++ qml/Components/InputMethod.qml 2016-03-11 13:51:30 +0000
2366@@ -22,15 +22,6 @@
2367 Item {
2368 id: root
2369
2370- Connections {
2371- target: SurfaceManager
2372- onSurfaceCreated: {
2373- if (surface.type == Mir.InputMethodType) {
2374- surfaceItem.surface = surface;
2375- }
2376- }
2377- }
2378-
2379 property int transitionDuration: UbuntuAnimation.FastDuration
2380
2381 MirSurfaceItem {
2382@@ -41,6 +32,7 @@
2383
2384 surfaceWidth: width
2385 surfaceHeight: height
2386+ surface: SurfaceManager.inputMethodSurface
2387
2388 onLiveChanged: {
2389 if (surface !== null && !live) {
2390
2391=== modified file 'qml/Components/Lockscreen.qml'
2392--- qml/Components/Lockscreen.qml 2015-07-15 15:07:19 +0000
2393+++ qml/Components/Lockscreen.qml 2016-03-11 13:51:30 +0000
2394@@ -121,107 +121,93 @@
2395 opacity: root.darkenBackground
2396 }
2397
2398- MouseArea {
2399- anchors.fill: root
2400- onClicked: {
2401- if (pinPadLoader.item)
2402- pinPadLoader.item.forceActiveFocus()
2403- }
2404- }
2405-
2406- FocusScope {
2407- id: loaderScope
2408+ Loader {
2409+ id: pinPadLoader
2410+ objectName: "pinPadLoader"
2411 anchors.fill: parent
2412-
2413- Loader {
2414- id: pinPadLoader
2415- objectName: "pinPadLoader"
2416- anchors.fill: parent
2417- property bool resetting: false
2418- property bool waiting: false
2419- property bool showWrongText: false
2420-
2421- source: {
2422- if (resetting || !root.required) {
2423- return ""
2424- } else if (root.delayMinutes > 0) {
2425- return "DelayedLockscreen.qml"
2426- } else if (root.alphaNumeric) {
2427- return "PassphraseLockscreen.qml"
2428- } else {
2429- return "PinLockscreen.qml"
2430- }
2431- }
2432- onSourceChanged: {
2433- waiting = false
2434- showWrongText = false
2435- if (loaderScope.activeFocus && pinPadLoader.item)
2436- pinPadLoader.item.forceActiveFocus()
2437- }
2438-
2439- Connections {
2440- target: pinPadLoader.item
2441-
2442- onEntered: {
2443- pinPadLoader.waiting = true
2444- root.entered(passphrase);
2445- }
2446-
2447- onCancel: {
2448- root.cancel()
2449- }
2450- }
2451-
2452- Binding {
2453- target: pinPadLoader.item
2454- property: "minPinLength"
2455- value: root.minPinLength
2456- }
2457- Binding {
2458- target: pinPadLoader.item
2459- property: "maxPinLength"
2460- value: root.maxPinLength
2461- }
2462- Binding {
2463- target: pinPadLoader.item
2464- property: "infoText"
2465- value: root.infoText
2466- }
2467- Binding {
2468- target: pinPadLoader.item
2469- property: "retryText"
2470- value: root.retryText
2471- }
2472- Binding {
2473- target: pinPadLoader.item
2474- property: "errorText"
2475- value: pinPadLoader.showWrongText ? root.errorText : ""
2476- }
2477- Binding {
2478- target: pinPadLoader.item
2479- property: "entryEnabled"
2480- value: !pinPadLoader.waiting
2481- }
2482- Binding {
2483- target: pinPadLoader.item
2484- property: "alphaNumeric"
2485- value: root.alphaNumeric
2486- }
2487- Binding {
2488- target: pinPadLoader.item
2489- property: "delayMinutes"
2490- value: root.delayMinutes
2491- }
2492- Binding {
2493- target: pinPadLoader.item
2494- property: "showCancelButton"
2495- value: root.showCancelButton
2496- }
2497- Binding {
2498- target: pinPadLoader.item
2499- property: "foregroundColor"
2500- value: root.foregroundColor
2501- }
2502+ property bool resetting: false
2503+ property bool waiting: false
2504+ property bool showWrongText: false
2505+ focus: true
2506+
2507+ source: {
2508+ if (resetting || !root.required) {
2509+ return ""
2510+ } else if (root.delayMinutes > 0) {
2511+ return "DelayedLockscreen.qml"
2512+ } else if (root.alphaNumeric) {
2513+ return "PassphraseLockscreen.qml"
2514+ } else {
2515+ return "PinLockscreen.qml"
2516+ }
2517+ }
2518+ onSourceChanged: {
2519+ waiting = false
2520+ showWrongText = false
2521+ }
2522+
2523+ Connections {
2524+ target: pinPadLoader.item
2525+
2526+ onEntered: {
2527+ pinPadLoader.waiting = true
2528+ root.entered(passphrase);
2529+ }
2530+
2531+ onCancel: {
2532+ root.cancel()
2533+ }
2534+ }
2535+
2536+ Binding {
2537+ target: pinPadLoader.item
2538+ property: "minPinLength"
2539+ value: root.minPinLength
2540+ }
2541+ Binding {
2542+ target: pinPadLoader.item
2543+ property: "maxPinLength"
2544+ value: root.maxPinLength
2545+ }
2546+ Binding {
2547+ target: pinPadLoader.item
2548+ property: "infoText"
2549+ value: root.infoText
2550+ }
2551+ Binding {
2552+ target: pinPadLoader.item
2553+ property: "retryText"
2554+ value: root.retryText
2555+ }
2556+ Binding {
2557+ target: pinPadLoader.item
2558+ property: "errorText"
2559+ value: pinPadLoader.showWrongText ? root.errorText : ""
2560+ }
2561+ Binding {
2562+ target: pinPadLoader.item
2563+ property: "entryEnabled"
2564+ value: !pinPadLoader.waiting
2565+ }
2566+ Binding {
2567+ target: pinPadLoader.item
2568+ property: "alphaNumeric"
2569+ value: root.alphaNumeric
2570+ }
2571+ Binding {
2572+ target: pinPadLoader.item
2573+ property: "delayMinutes"
2574+ value: root.delayMinutes
2575+ }
2576+ Binding {
2577+ target: pinPadLoader.item
2578+ property: "showCancelButton"
2579+ value: root.showCancelButton
2580+ }
2581+ Binding {
2582+ target: pinPadLoader.item
2583+ property: "foregroundColor"
2584+ value: root.foregroundColor
2585 }
2586 }
2587
2588
2589=== modified file 'qml/Components/ModeSwitchWarningDialog.qml'
2590--- qml/Components/ModeSwitchWarningDialog.qml 2015-11-25 13:57:34 +0000
2591+++ qml/Components/ModeSwitchWarningDialog.qml 2016-03-11 13:51:30 +0000
2592@@ -54,7 +54,7 @@
2593 }
2594
2595 Label {
2596- text: i18n.tr("Re-dock, save your work and close these apps to continue.")
2597+ text: i18n.ctr("Re-dock means connect the device again to an external screen/mouse/keyboard", "Re-dock, save your work and close these apps to continue.")
2598 wrapMode: Text.WordWrap
2599 color: "#888888"
2600 }
2601
2602=== modified file 'qml/Components/PassphraseLockscreen.qml'
2603--- qml/Components/PassphraseLockscreen.qml 2015-07-15 15:07:19 +0000
2604+++ qml/Components/PassphraseLockscreen.qml 2016-03-11 13:51:30 +0000
2605@@ -18,10 +18,11 @@
2606 import Ubuntu.Components 1.3
2607 import "../Components"
2608
2609-Item {
2610+FocusScope {
2611 id: root
2612 y: units.gu(4)
2613 height: shakeContainer.height
2614+ focus: true
2615
2616 property string infoText
2617 property string errorText
2618@@ -42,8 +43,6 @@
2619 }
2620 }
2621
2622- onActiveFocusChanged: if (activeFocus) pinentryField.forceActiveFocus()
2623-
2624 Column {
2625 id: shakeContainer
2626 anchors.horizontalCenter: parent.horizontalCenter
2627@@ -59,14 +58,16 @@
2628 text: root.infoText
2629 }
2630
2631- Item {
2632+ FocusScope {
2633 id: entryContainer
2634 anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
2635 height: units.gu(4)
2636+ focus: true
2637
2638 TextInput {
2639 id: pinentryField
2640 objectName: "pinentryField"
2641+ focus: true
2642
2643 property bool incorrectOverride: false
2644
2645
2646=== modified file 'qml/Components/PinLockscreen.qml'
2647--- qml/Components/PinLockscreen.qml 2015-07-15 15:07:19 +0000
2648+++ qml/Components/PinLockscreen.qml 2016-03-11 13:51:30 +0000
2649@@ -19,8 +19,9 @@
2650 import Ubuntu.Components.ListItems 1.3
2651 import "../Components"
2652
2653-Item {
2654+FocusScope {
2655 id: root
2656+ focus: true
2657
2658 property string infoText
2659 property string retryText
2660@@ -45,6 +46,24 @@
2661 }
2662 }
2663
2664+ Keys.onPressed: {
2665+ if (pinentryField.text.length == root.maxPinLength)
2666+ return;
2667+
2668+ if (event.key === Qt.Key_Backspace) {
2669+ pinentryField.backspace();
2670+ } else if (event.key === Qt.Key_Delete || event.key === Qt.Key_Escape) {
2671+ closeButton.clicked()
2672+ } else if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
2673+ confirmButton.clicked()
2674+ } else {
2675+ var digit = parseInt(event.text);
2676+ if (!isNaN(digit) && typeof digit == "number") {
2677+ pinentryField.appendNumber(digit);
2678+ }
2679+ }
2680+ }
2681+
2682 Column {
2683 anchors {
2684 left: parent.left;
2685@@ -204,6 +223,7 @@
2686 width: numbersGrid.buttonWidth
2687 }
2688 PinPadButton {
2689+ id: closeButton
2690 iconName: "close"
2691 height: units.gu(5) // visual spec has this row a little closer in
2692 width: numbersGrid.buttonWidth
2693@@ -216,6 +236,7 @@
2694 width: numbersGrid.buttonWidth
2695 }
2696 PinPadButton {
2697+ id: confirmButton
2698 iconName: "tick"
2699 objectName: "confirmButton"
2700 height: units.gu(5)
2701
2702=== modified file 'qml/Components/ShellDialog.qml'
2703--- qml/Components/ShellDialog.qml 2015-11-06 10:06:58 +0000
2704+++ qml/Components/ShellDialog.qml 2016-03-11 13:51:30 +0000
2705@@ -37,7 +37,15 @@
2706
2707 focus: true
2708
2709+ // FIXME: this is a hack because Dialog subtheming seems broken atm
2710+ // https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1555548
2711+ ThemeSettings {
2712+ id: themeHack
2713+ name: "Ubuntu.Components.Themes.Ambiance"
2714+ }
2715+
2716 Component.onCompleted: {
2717+ __foreground.theme = themeHack
2718 show();
2719 }
2720 }
2721
2722=== modified file 'qml/Dash/CardCarousel.qml'
2723--- qml/Dash/CardCarousel.qml 2016-01-28 14:11:14 +0000
2724+++ qml/Dash/CardCarousel.qml 2016-03-11 13:51:30 +0000
2725@@ -66,7 +66,6 @@
2726 item.cardData = Qt.binding(function() { return model; });
2727 item.fontScale = Qt.binding(function() { return carousel.fontScale; });
2728 item.showHeader = Qt.binding(function() { return loader.explicitlyScaled; });
2729- item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
2730 item.artShapeStyle = "shadow";
2731 item.scopeStyle = cardCarousel.scopeStyle;
2732 }
2733
2734=== modified file 'qml/Dash/CardGrid.qml'
2735--- qml/Dash/CardGrid.qml 2016-02-02 08:47:07 +0000
2736+++ qml/Dash/CardGrid.qml 2016-03-11 13:51:30 +0000
2737@@ -70,7 +70,6 @@
2738 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
2739 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
2740 item.cardData = Qt.binding(function() { return model; });
2741- item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
2742 item.scopeStyle = root.scopeStyle;
2743 item.artShapeStyle = root.artShapeStyle;
2744 item.backgroundShapeStyle = root.backgroundShapeStyle;
2745
2746=== modified file 'qml/Dash/CardHorizontalList.qml'
2747--- qml/Dash/CardHorizontalList.qml 2016-01-28 14:11:14 +0000
2748+++ qml/Dash/CardHorizontalList.qml 2016-03-11 13:51:30 +0000
2749@@ -53,7 +53,6 @@
2750 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
2751 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
2752 item.cardData = Qt.binding(function() { return model; });
2753- item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
2754 item.scopeStyle = root.scopeStyle;
2755 }
2756 Connections {
2757
2758=== modified file 'qml/Dash/CardTool.qml'
2759--- qml/Dash/CardTool.qml 2016-01-28 14:11:14 +0000
2760+++ qml/Dash/CardTool.qml 2016-03-11 13:51:30 +0000
2761@@ -66,7 +66,7 @@
2762 return layout;
2763 }
2764
2765- property var cardComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components);
2766+ property var cardComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, false);
2767
2768 // FIXME: Saviq
2769 // Only way for the card below to actually be laid out completely.
2770@@ -139,29 +139,6 @@
2771 readonly property int headerHeight: cardLoader.item ? cardLoader.item.headerHeight : 0
2772 property size artShapeSize: cardLoader.item ? cardLoader.item.artShapeSize : 0
2773
2774- /*!
2775- \brief Desired alignment of title
2776- */
2777- readonly property int titleAlignment: {
2778- if (template["card-layout"] === "horizontal"
2779- || typeof components["title"] !== "object"
2780- || components["title"]["align"] === "left") return Text.AlignLeft;
2781-
2782- var keys = ["mascot", "emblem", "subtitle", "attributes", "summary"];
2783-
2784- for (var key in keys) {
2785- key = keys[key];
2786- try {
2787- if (typeof components[key] === "string"
2788- || typeof components[key]["field"] === "string") return Text.AlignLeft;
2789- } catch (e) {
2790- continue;
2791- }
2792- }
2793-
2794- return Text.AlignHCenter;
2795- }
2796-
2797 QtObject {
2798 id: carouselTool
2799
2800@@ -216,10 +193,9 @@
2801 "summary": "—\n—\n—\n—\n—",
2802 "attributes": attributesModel.model
2803 }
2804- sourceComponent: cardTool.cardComponent
2805+ sourceComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, true);
2806 onLoaded: {
2807 item.objectName = "cardToolCard";
2808- item.asynchronous = false;
2809 item.width = Qt.binding(function() { return cardTool.cardWidth !== -1 ? cardTool.cardWidth : item.implicitWidth; });
2810 item.height = Qt.binding(function() { return cardTool.cardHeight !== -1 ? cardTool.cardHeight : item.implicitHeight; });
2811 }
2812
2813=== modified file 'qml/Dash/CardVerticalJournal.qml'
2814--- qml/Dash/CardVerticalJournal.qml 2016-01-28 14:11:14 +0000
2815+++ qml/Dash/CardVerticalJournal.qml 2016-03-11 13:51:30 +0000
2816@@ -72,7 +72,6 @@
2817 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
2818 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
2819 item.cardData = Qt.binding(function() { return model; });
2820- item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
2821 item.scopeStyle = root.scopeStyle;
2822 }
2823 Connections {
2824
2825=== modified file 'qml/Dash/Dash.qml'
2826--- qml/Dash/Dash.qml 2015-11-19 16:55:31 +0000
2827+++ qml/Dash/Dash.qml 2016-03-11 13:51:30 +0000
2828@@ -37,6 +37,7 @@
2829 }
2830
2831 property bool windowActive: window.active
2832+ property bool showOverlayScope: false
2833
2834 DashCommunicatorService {
2835 objectName: "dashCommunicatorService"
2836@@ -80,7 +81,7 @@
2837 return
2838 }
2839
2840- closeOverlayScope();
2841+ dash.showOverlayScope = false;
2842
2843 dashContent.closePreview();
2844
2845@@ -93,12 +94,6 @@
2846 dashContent.setCurrentScopeAtIndex(scopeIndex, animate, reset)
2847 }
2848
2849- function closeOverlayScope() {
2850- if (dashContent.x != 0) {
2851- dashContent.x = 0;
2852- }
2853- }
2854-
2855 Scopes {
2856 id: scopes
2857 }
2858@@ -133,12 +128,13 @@
2859 height: dash.height
2860 scopes: scopes
2861 visible: x != -width
2862+ x: dash.showOverlayScope ? -width : 0
2863 onGotoScope: {
2864 dash.setCurrentScope(scopeId, true, false);
2865 }
2866 onOpenScope: {
2867 scopeItem.scope = scope;
2868- x = -width;
2869+ dash.showOverlayScope = true;
2870 }
2871 Behavior on x {
2872 UbuntuNumberAnimation {
2873@@ -207,7 +203,7 @@
2874 bottomEdgeController.enableAnimation = true;
2875 bottomEdgeController.progress = 0;
2876 scopeItem.scope = scope;
2877- dashContent.x = -dashContent.width;
2878+ dash.showOverlayScope = true;
2879 }
2880 onGotoScope: {
2881 bottomEdgeController.enableAnimation = true;
2882@@ -226,7 +222,7 @@
2883 id: scopeItem
2884 objectName: "dashTempScopeItem"
2885
2886- x: dashContent.x + width
2887+ x: dash.showOverlayScope ? 0 : width
2888 y: dashContent.y
2889 width: parent.width
2890 height: parent.height
2891@@ -234,7 +230,7 @@
2892 hasBackAction: true
2893 isCurrent: visible
2894 onBackClicked: {
2895- closeOverlayScope();
2896+ dash.showOverlayScope = false;
2897 closePreview();
2898 }
2899
2900@@ -250,6 +246,10 @@
2901 scopes.closeScope(oldScope);
2902 }
2903 }
2904+
2905+ Behavior on x {
2906+ UbuntuNumberAnimation { }
2907+ }
2908 }
2909
2910 Rectangle {
2911
2912=== modified file 'qml/Dash/GenericScopeView.qml'
2913--- qml/Dash/GenericScopeView.qml 2016-02-19 11:50:12 +0000
2914+++ qml/Dash/GenericScopeView.qml 2016-03-11 13:51:30 +0000
2915@@ -370,6 +370,8 @@
2916 } else {
2917 cardTool.cardWidth = units.gu(10);
2918 }
2919+ } else {
2920+ cardTool.cardWidth = units.gu(12);
2921 }
2922 item.minimumHorizontalSpacing = item.defaultMinimumHorizontalSpacing;
2923 }
2924
2925=== modified file 'qml/Dash/Previews/PreviewHeader.qml'
2926--- qml/Dash/Previews/PreviewHeader.qml 2016-01-08 14:19:08 +0000
2927+++ qml/Dash/Previews/PreviewHeader.qml 2016-03-11 13:51:30 +0000
2928@@ -25,6 +25,7 @@
2929 * The mascot fall back image comes in widgetData["fallback"]
2930 * The subtitle comes in widgetData["subtitle"]
2931 * The attributes comes in widgetData["attributes"]
2932+ * The emblem comes in widgetData["emblem"]
2933 */
2934
2935 PreviewWidget {
2936@@ -40,6 +41,7 @@
2937 readonly property string title: root.widgetData["title"] || ""
2938 readonly property string subtitle: root.widgetData["subtitle"] || ""
2939 readonly property var attributes: root.widgetData["attributes"] || null
2940+ readonly property url emblem: root.widgetData["emblem"] || ""
2941 readonly property color fontColor: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText
2942
2943 // Rewire the source since we may have unwired it on onStatusChanged
2944@@ -98,16 +100,42 @@
2945 spacing: units.dp(2)
2946 anchors.verticalCenter: parent.verticalCenter
2947
2948- Label {
2949- id: titleLabel
2950- objectName: "titleLabel"
2951+ Item {
2952 anchors { left: parent.left; right: parent.right }
2953- elide: Text.ElideRight
2954- font.weight: Font.Normal
2955- fontSize: "large"
2956- wrapMode: Text.Wrap
2957- color: headerRoot.fontColor
2958- text: headerRoot.title
2959+ height: titleLabel.height
2960+
2961+ Label {
2962+ id: titleLabel
2963+ objectName: "titleLabel"
2964+ anchors {
2965+ left: parent.left;
2966+ right: iconLoader.right
2967+ rightMargin: iconLoader.width > 0 ? units.gu(0.5) : 0
2968+ }
2969+ elide: Text.ElideRight
2970+ font.weight: Font.Normal
2971+ fontSize: "large"
2972+ wrapMode: Text.Wrap
2973+ color: headerRoot.fontColor
2974+ text: headerRoot.title
2975+ }
2976+
2977+ Loader {
2978+ id: iconLoader
2979+ active: headerRoot.emblem != ""
2980+ anchors {
2981+ bottom: titleLabel.baseline
2982+ right: parent.right
2983+ }
2984+ sourceComponent: Icon {
2985+ objectName: "emblemIcon"
2986+ source: headerRoot.emblem
2987+ color: headerRoot.fontColor
2988+ height: source != "" ? titleLabel.font.pixelSize : 0
2989+ // FIXME Workaround for bug https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1421293
2990+ width: implicitWidth > 0 && implicitHeight > 0 ? (implicitWidth / implicitHeight * height) : implicitWidth
2991+ }
2992+ }
2993 }
2994
2995 Loader {
2996
2997=== modified file 'qml/Dash/Previews/PreviewOverlay.qml'
2998--- qml/Dash/Previews/PreviewOverlay.qml 2015-07-15 15:07:19 +0000
2999+++ qml/Dash/Previews/PreviewOverlay.qml 2016-03-11 13:51:30 +0000
3000@@ -158,7 +158,7 @@
3001 anchors.centerIn: parent
3002 width: units.gu(2.5)
3003 height: width
3004- color: theme.palette.normal.foregroundText
3005+ color: "white"
3006 name: "close"
3007 }
3008 }
3009
3010=== modified file 'qml/Dash/Previews/PreviewSharing.qml'
3011--- qml/Dash/Previews/PreviewSharing.qml 2015-12-17 15:42:39 +0000
3012+++ qml/Dash/Previews/PreviewSharing.qml 2016-03-11 13:51:30 +0000
3013@@ -44,6 +44,22 @@
3014 }
3015 }
3016
3017+ function createExportedItems(url) {
3018+ var items = new Array();
3019+ if (typeof url === "string") {
3020+ var exportItem = exportItemComponent.createObject();
3021+ exportItem.url = url;
3022+ items.push(exportItem);
3023+ } else {
3024+ for (var i = 0; i < url.length; i++) {
3025+ var exportItem = exportItemComponent.createObject();
3026+ exportItem.url = url[i];
3027+ items.push(exportItem);
3028+ }
3029+ }
3030+ return items;
3031+ }
3032+
3033 Component {
3034 id: exportItemComponent
3035 ContentItem {
3036@@ -76,13 +92,7 @@
3037 onPeerSelected: {
3038 var transfer = peer.request();
3039 if (transfer.state === ContentTransfer.InProgress) {
3040- var items = new Array();
3041- for (var i = 0; i < url.length; i++) {
3042- var exportItem = exportItemComponent.createObject();
3043- exportItem.url = url[i];
3044- items.push(exportItem);
3045- }
3046- transfer.items = items;
3047+ transfer.items = createExportedItems(url);
3048 transfer.state = ContentTransfer.Charged;
3049 }
3050 peerPicker.visible = false;
3051
3052=== modified file 'qml/Dash/ScopesListCategoryItem.qml'
3053--- qml/Dash/ScopesListCategoryItem.qml 2015-11-04 14:57:13 +0000
3054+++ qml/Dash/ScopesListCategoryItem.qml 2016-03-11 13:51:30 +0000
3055@@ -18,7 +18,7 @@
3056 import QtQuick.Layouts 1.1
3057 import Ubuntu.Components 1.3
3058
3059-MouseArea {
3060+AbstractButton {
3061 id: root
3062
3063 signal requestFavorite(string scopeId, bool favorite)
3064@@ -84,15 +84,19 @@
3065 visible: text != ""
3066 }
3067 }
3068- MouseArea {
3069+ AbstractButton {
3070 id: starArea
3071 objectName: "starArea"
3072 height: parent.height
3073 width: height
3074 anchors.right: parent.right
3075 onClicked: if (!editMode) root.requestFavorite(model.scopeId, !isFavorite);
3076- onPressed: if (editMode) root.handlePressed(starArea);
3077- onReleased: if (editMode) root.handleReleased(starArea);
3078+ onPressedChanged: {
3079+ if (editMode) {
3080+ if (pressed) root.handlePressed(starArea.__mouseArea);
3081+ else root.handleReleased(starArea.__mouseArea);
3082+ }
3083+ }
3084 visible: editMode || showStar
3085 Icon {
3086 id: star
3087
3088=== modified file 'qml/DeviceConfiguration.qml'
3089--- qml/DeviceConfiguration.qml 2015-12-01 13:56:54 +0000
3090+++ qml/DeviceConfiguration.qml 2016-03-11 13:51:30 +0000
3091@@ -1,5 +1,5 @@
3092 /*
3093- * Copyright (C) 2015 Canonical, Ltd.
3094+ * Copyright (C) 2015-2016 Canonical, Ltd.
3095 *
3096 * This program is free software; you can redistribute it and/or modify
3097 * it under the terms of the GNU General Public License as published by
3098@@ -15,6 +15,7 @@
3099 */
3100
3101 import QtQuick 2.4
3102+import Utils 0.1
3103
3104 QtObject {
3105 id: root
3106@@ -34,57 +35,83 @@
3107
3108 readonly property alias category: priv.category
3109
3110+ readonly property var deviceConfigParser: DeviceConfigParser {
3111+ name: root.name
3112+ }
3113+
3114 readonly property var priv: StateGroup {
3115 id: priv
3116
3117- property int primaryOrientation: root.useNativeOrientation
3118-
3119- property int supportedOrientations: Qt.PortraitOrientation
3120- | Qt.InvertedPortraitOrientation
3121- | Qt.LandscapeOrientation
3122- | Qt.InvertedLandscapeOrientation
3123-
3124- property int landscapeOrientation: Qt.LandscapeOrientation
3125- property int invertedLandscapeOrientation: Qt.InvertedLandscapeOrientation
3126- property int portraitOrientation: Qt.PortraitOrientation
3127- property int invertedPortraitOrientation: Qt.InvertedPortraitOrientation
3128-
3129- // Supported values so far:
3130- // "phone", "tablet" or "desktop"
3131- property string category: "phone"
3132+ property int primaryOrientation: deviceConfigParser.primaryOrientation == Qt.PrimaryOrientation ?
3133+ root.useNativeOrientation : deviceConfigParser.primaryOrientation
3134+
3135+ property int supportedOrientations: deviceConfigParser.supportedOrientations
3136+
3137+ property int landscapeOrientation: deviceConfigParser.landscapeOrientation
3138+ property int invertedLandscapeOrientation: deviceConfigParser.invertedLandscapeOrientation
3139+ property int portraitOrientation: deviceConfigParser.portraitOrientation
3140+ property int invertedPortraitOrientation: deviceConfigParser.invertedPortraitOrientation
3141+ property string category: deviceConfigParser.category
3142
3143 states: [
3144 State {
3145 name: "mako"
3146 PropertyChanges {
3147 target: priv
3148+ primaryOrientation: root.useNativeOrientation
3149 supportedOrientations: Qt.PortraitOrientation
3150 | Qt.LandscapeOrientation
3151 | Qt.InvertedLandscapeOrientation
3152+ landscapeOrientation: Qt.LandscapeOrientation
3153+ invertedLandscapeOrientation: Qt.InvertedLandscapeOrientation
3154+ portraitOrientation: Qt.PortraitOrientation
3155+ invertedPortraitOrientation: Qt.InvertedPortraitOrientation
3156+ category: "phone"
3157 }
3158 },
3159 State {
3160 name: "krillin"
3161 PropertyChanges {
3162 target: priv
3163+ primaryOrientation: root.useNativeOrientation
3164 supportedOrientations: Qt.PortraitOrientation
3165 | Qt.LandscapeOrientation
3166 | Qt.InvertedLandscapeOrientation
3167+ landscapeOrientation: Qt.LandscapeOrientation
3168+ invertedLandscapeOrientation: Qt.InvertedLandscapeOrientation
3169+ portraitOrientation: Qt.PortraitOrientation
3170+ invertedPortraitOrientation: Qt.InvertedPortraitOrientation
3171+ category: "phone"
3172 }
3173 },
3174 State {
3175 name: "arale"
3176 PropertyChanges {
3177 target: priv
3178+ primaryOrientation: root.useNativeOrientation
3179 supportedOrientations: Qt.PortraitOrientation
3180 | Qt.LandscapeOrientation
3181 | Qt.InvertedLandscapeOrientation
3182+ landscapeOrientation: Qt.LandscapeOrientation
3183+ invertedLandscapeOrientation: Qt.InvertedLandscapeOrientation
3184+ portraitOrientation: Qt.PortraitOrientation
3185+ invertedPortraitOrientation: Qt.InvertedPortraitOrientation
3186+ category: "phone"
3187 }
3188 },
3189 State {
3190 name: "manta"
3191 PropertyChanges {
3192 target: priv
3193+ primaryOrientation: root.useNativeOrientation
3194+ supportedOrientations: Qt.PortraitOrientation
3195+ | Qt.InvertedPortraitOrientation
3196+ | Qt.LandscapeOrientation
3197+ | Qt.InvertedLandscapeOrientation
3198+ landscapeOrientation: Qt.LandscapeOrientation
3199+ invertedLandscapeOrientation: Qt.InvertedLandscapeOrientation
3200+ portraitOrientation: Qt.PortraitOrientation
3201+ invertedPortraitOrientation: Qt.InvertedPortraitOrientation
3202 category: "tablet"
3203 }
3204 },
3205@@ -92,9 +119,15 @@
3206 name: "flo"
3207 PropertyChanges {
3208 target: priv
3209+ primaryOrientation: Qt.InvertedLandscapeOrientation
3210+ supportedOrientations: Qt.PortraitOrientation
3211+ | Qt.InvertedPortraitOrientation
3212+ | Qt.LandscapeOrientation
3213+ | Qt.InvertedLandscapeOrientation
3214 landscapeOrientation: Qt.InvertedLandscapeOrientation
3215 invertedLandscapeOrientation: Qt.LandscapeOrientation
3216- primaryOrientation: Qt.InvertedLandscapeOrientation
3217+ portraitOrientation: Qt.PortraitOrientation
3218+ invertedPortraitOrientation: Qt.InvertedPortraitOrientation
3219 category: "tablet"
3220 }
3221 },
3222@@ -102,8 +135,13 @@
3223 name: "desktop"
3224 PropertyChanges {
3225 target: priv
3226+ primaryOrientation: root.useNativeOrientation
3227+ supportedOrientations: root.useNativeOrientation
3228+ landscapeOrientation: Qt.LandscapeOrientation
3229+ invertedLandscapeOrientation: Qt.InvertedLandscapeOrientation
3230+ portraitOrientation: Qt.PortraitOrientation
3231+ invertedPortraitOrientation: Qt.InvertedPortraitOrientation
3232 category: "desktop"
3233- supportedOrientations: root.useNativeOrientation
3234 }
3235 }
3236 ]
3237
3238=== modified file 'qml/DisabledScreenNotice.qml'
3239--- qml/DisabledScreenNotice.qml 2016-01-26 15:29:54 +0000
3240+++ qml/DisabledScreenNotice.qml 2016-03-11 13:51:30 +0000
3241@@ -17,6 +17,7 @@
3242 import QtQuick 2.4
3243 import QtQuick.Layouts 1.1
3244 import Ubuntu.Components 1.3
3245+import Unity.Session 0.1
3246 import QtQuick.Window 2.2
3247 import "Components"
3248
3249@@ -25,19 +26,36 @@
3250
3251 property bool infoNoteDisplayed: true
3252
3253- WallpaperResolver {
3254- width: root.width
3255- id: wallpaperResolver
3256+ // For testing
3257+ property var screen: Screen
3258+ property var orientationLock: OrientationLock
3259+
3260+ DeviceConfiguration {
3261+ id: deviceConfiguration
3262+ name: applicationArguments.deviceName
3263 }
3264
3265 Item {
3266 id: contentContainer
3267+ objectName: "contentContainer"
3268 anchors.centerIn: parent
3269 height: rotation == 90 || rotation == 270 ? parent.width : parent.height
3270 width: rotation == 90 || rotation == 270 ? parent.height : parent.width
3271
3272+ property int savedOrientation: deviceConfiguration.primaryOrientation == deviceConfiguration.useNativeOrientation
3273+ ? (root.width > root.height ? Qt.LandscapeOrientation : Qt.PortraitOrientation)
3274+ : deviceConfiguration.primaryOrientation
3275+
3276 rotation: {
3277- switch (Screen.orientation) {
3278+ var usedOrientation = root.screen.orientation;
3279+
3280+ if (root.orientationLock.enabled) {
3281+ usedOrientation = savedOrientation;
3282+ }
3283+
3284+ savedOrientation = usedOrientation;
3285+
3286+ switch (usedOrientation) {
3287 case Qt.PortraitOrientation:
3288 return 0;
3289 case Qt.LandscapeOrientation:
3290@@ -47,6 +65,8 @@
3291 case Qt.InvertedLandscapeOrientation:
3292 return 90;
3293 }
3294+
3295+ return 0;
3296 }
3297 transformOrigin: Item.Center
3298
3299@@ -60,9 +80,9 @@
3300 }
3301 }
3302
3303- Image {
3304+ Rectangle {
3305 anchors.fill: parent
3306- source: wallpaperResolver.background
3307+ color: "#3b3b3b"
3308 }
3309
3310 Item {
3311@@ -74,22 +94,26 @@
3312 UbuntuNumberAnimation { }
3313 }
3314
3315- Rectangle {
3316- anchors.fill: parent
3317- color: "black"
3318- opacity: 0.4
3319- }
3320-
3321- Label {
3322- id: text
3323+ Column {
3324 anchors.centerIn: parent
3325 width: parent.width - units.gu(8)
3326- text: i18n.tr("Your device is now connected to an external display. Use this screen as a touch pad to interact with the mouse.")
3327- color: "white"
3328- horizontalAlignment: Text.AlignHCenter
3329- verticalAlignment: Text.AlignVCenter
3330- fontSize: "x-large"
3331- wrapMode: Text.Wrap
3332+ spacing: units.gu(4)
3333+
3334+ Label {
3335+ id: text
3336+ text: i18n.tr("Your device is now connected to an external display. Use this screen as a touch pad to interact with the pointer.")
3337+ color: "white"
3338+ width: parent.width
3339+ fontSize: "large"
3340+ wrapMode: Text.Wrap
3341+ }
3342+ Icon {
3343+ height: units.gu(8)
3344+ width: height
3345+ name: "input-touchpad-symbolic"
3346+ color: "white"
3347+ anchors.horizontalCenter: parent.horizontalCenter
3348+ }
3349 }
3350 }
3351
3352
3353=== modified file 'qml/Greeter/CoverPage.qml'
3354--- qml/Greeter/CoverPage.qml 2015-07-15 15:07:19 +0000
3355+++ qml/Greeter/CoverPage.qml 2016-03-11 13:51:30 +0000
3356@@ -1,5 +1,5 @@
3357 /*
3358- * Copyright (C) 2013,2014,2015 Canonical, Ltd.
3359+ * Copyright (C) 2013-2016 Canonical, Ltd.
3360 *
3361 * This program is free software; you can redistribute it and/or modify
3362 * it under the terms of the GNU General Public License as published by
3363@@ -34,6 +34,7 @@
3364 readonly property real showProgress: MathUtils.clamp((width - Math.abs(x)) / width, 0, 1)
3365
3366 signal tease()
3367+ signal clicked()
3368
3369 function hideRight() {
3370 d.forceRightOnNextHideAnimation = true;
3371@@ -55,7 +56,17 @@
3372 // instead, we can get a little extra horizontal push by using transforms.
3373 transform: Translate { id: translation; x: root.draggable ? launcherOffset : 0 }
3374
3375- MouseArea { anchors.fill: parent; }
3376+ // Eat events elsewhere on the coverpage, except mouse clicks which we pass
3377+ // up (they are used in the NarrowView to hide the cover page)
3378+ MouseArea {
3379+ anchors.fill: parent
3380+ onClicked: root.clicked()
3381+
3382+ MultiPointTouchArea {
3383+ anchors.fill: parent
3384+ mouseEnabled: false
3385+ }
3386+ }
3387
3388 Rectangle {
3389 // In case background fails to load
3390
3391=== modified file 'qml/Greeter/Infographics.qml'
3392--- qml/Greeter/Infographics.qml 2015-09-29 12:28:10 +0000
3393+++ qml/Greeter/Infographics.qml 2016-03-11 13:51:30 +0000
3394@@ -1,5 +1,5 @@
3395 /*
3396- * Copyright (C) 2013 Canonical, Ltd.
3397+ * Copyright (C) 2013-2016 Canonical, Ltd.
3398 *
3399 * This program is free software; you can redistribute it and/or modify
3400 * it under the terms of the GNU General Public License as published by
3401@@ -402,6 +402,7 @@
3402
3403 MouseArea {
3404 anchors.fill: dataCircle
3405+ enabled: notification.text != ""
3406
3407 onDoubleClicked: {
3408 if (!d.animating) {
3409
3410=== modified file 'qml/Greeter/NarrowView.qml'
3411--- qml/Greeter/NarrowView.qml 2015-11-19 16:55:31 +0000
3412+++ qml/Greeter/NarrowView.qml 2016-03-11 13:51:30 +0000
3413@@ -1,5 +1,5 @@
3414 /*
3415- * Copyright (C) 2015 Canonical, Ltd.
3416+ * Copyright (C) 2015-2016 Canonical, Ltd.
3417 *
3418 * This program is free software; you can redistribute it and/or modify
3419 * it under the terms of the GNU General Public License as published by
3420@@ -125,6 +125,18 @@
3421 onCancel: coverPage.show()
3422 onEmergencyCall: root.emergencyCall()
3423
3424+ onEnabledChanged: {
3425+ if (enabled) {
3426+ lockscreen.forceActiveFocus();
3427+ }
3428+ }
3429+
3430+ onVisibleChanged: {
3431+ if (visible) {
3432+ lockscreen.forceActiveFocus();
3433+ }
3434+ }
3435+
3436 function maybeShow() {
3437 if (root.locked && !shown) {
3438 showNow();
3439@@ -145,6 +157,7 @@
3440 width: parent.width
3441 background: root.background
3442 onTease: root.tease()
3443+ onClicked: hide()
3444
3445 onShowProgressChanged: {
3446 if (showProgress === 1) {
3447
3448=== modified file 'qml/Launcher/Launcher.qml'
3449--- qml/Launcher/Launcher.qml 2016-03-11 13:51:29 +0000
3450+++ qml/Launcher/Launcher.qml 2016-03-11 13:51:30 +0000
3451@@ -175,7 +175,7 @@
3452 event.accepted = true;
3453 break;
3454 case Qt.Key_Escape:
3455- panel.highlightIndex = -2
3456+ panel.highlightIndex = -2;
3457 // Falling through intentionally
3458 case Qt.Key_Enter:
3459 case Qt.Key_Return:
3460@@ -186,6 +186,7 @@
3461 launcherApplicationSelected(LauncherModel.get(panel.highlightIndex).appId);
3462 }
3463 root.hide();
3464+ panel.highlightIndex = -2
3465 event.accepted = true;
3466 root.focus = false;
3467 }
3468@@ -328,8 +329,8 @@
3469 rotation: -90
3470 anchors.centerIn: parent
3471 gradient: Gradient {
3472- GradientStop { position: 0.0; color: panel.color}
3473- GradientStop { position: 1.0; color: Qt.rgba(panel.r,panel.g,panel.b,0)}
3474+ GradientStop { position: 0.0; color: Qt.rgba(panel.color.r, panel.color.g, panel.color.b, .5)}
3475+ GradientStop { position: 1.0; color: Qt.rgba(panel.color.r,panel.color.g,panel.color.b,0)}
3476 }
3477 }
3478 }
3479
3480=== modified file 'qml/Launcher/LauncherDelegate.qml'
3481--- qml/Launcher/LauncherDelegate.qml 2016-03-11 13:51:29 +0000
3482+++ qml/Launcher/LauncherDelegate.qml 2016-03-11 13:51:30 +0000
3483@@ -149,6 +149,7 @@
3484 sourceSize.width: iconShape.width
3485 sourceSize.height: iconShape.height
3486 source: root.iconName
3487+ cache: false // see lpbug#1543290 why no cache
3488 }
3489 }
3490
3491
3492=== modified file 'qml/Notifications/Notification.qml'
3493--- qml/Notifications/Notification.qml 2016-02-29 11:31:46 +0000
3494+++ qml/Notifications/Notification.qml 2016-03-11 13:51:30 +0000
3495@@ -23,7 +23,7 @@
3496 import Utils 0.1
3497 import "../Components"
3498
3499-Item {
3500+StyledItem {
3501 id: notification
3502
3503 property alias iconSource: icon.fileSource
3504@@ -58,6 +58,10 @@
3505 color: (type === Notification.Confirmation && notificationList.useModal && !greeter.shown) || darkOnBright ? sdLightGrey : Qt.rgba(0.132, 0.117, 0.109, 0.97)
3506 opacity: 1 - (x / notification.width) // FIXME: non-zero initially because of LP: #1354406 workaround, we want this to start at 0 upon creation eventually
3507
3508+ theme: ThemeSettings {
3509+ name: "Ubuntu.Components.Themes.Ambiance"
3510+ }
3511+
3512 state: {
3513 var result = "";
3514
3515@@ -297,7 +301,7 @@
3516 visible: body != "" && type !== Notification.Confirmation
3517 fontSize: "small"
3518 color: darkOnBright ? sdFontColor : theme.palette.normal.backgroundText
3519- wrapMode: Text.WordWrap
3520+ wrapMode: Text.Wrap
3521 maximumLineCount: type == Notification.SnapDecision ? 12 : 2
3522 elide: Text.ElideRight
3523 textFormat: Text.PlainText
3524
3525=== modified file 'qml/OrientedShell.qml'
3526--- qml/OrientedShell.qml 2016-01-28 11:31:48 +0000
3527+++ qml/OrientedShell.qml 2016-03-11 13:51:30 +0000
3528@@ -19,6 +19,7 @@
3529 import Unity.InputInfo 0.1
3530 import Unity.Session 0.1
3531 import Unity.Screens 0.1
3532+import Utils 0.1
3533 import GSettings 1.0
3534 import "Components"
3535 import "Rotation"
3536@@ -77,6 +78,8 @@
3537 InputDeviceModel {
3538 id: keyboardsModel
3539 deviceFilter: InputInfo.Keyboard
3540+ onDeviceAdded: forceOSKEnabled = autopilotDevicePresent();
3541+ onDeviceRemoved: forceOSKEnabled = autopilotDevicePresent();
3542 }
3543
3544 InputDeviceModel {
3545@@ -84,6 +87,27 @@
3546 deviceFilter: InputInfo.TouchScreen
3547 }
3548
3549+ /* FIXME: This exposes the NameRole as a work arround for lp:1542224.
3550+ * When QInputInfo exposes NameRole to QML, this should be removed.
3551+ */
3552+ property bool forceOSKEnabled: false
3553+ property var autopilotEmulatedDeviceNames: ["py-evdev-uinput"]
3554+ UnitySortFilterProxyModel {
3555+ id: autopilotDevices
3556+ model: keyboardsModel
3557+ }
3558+
3559+ function autopilotDevicePresent() {
3560+ for(var i = 0; i < autopilotDevices.count; i++) {
3561+ var device = autopilotDevices.get(i);
3562+ if (autopilotEmulatedDeviceNames.indexOf(device.name) != -1) {
3563+ console.warn("Forcing the OSK to be enabled as there is an autopilot eumlated device present.")
3564+ return true;
3565+ }
3566+ }
3567+ return false;
3568+ }
3569+
3570 Screens {
3571 id: screens
3572 }
3573@@ -195,7 +219,8 @@
3574 // have multiple keyboards around. For now we only enable one keyboard at a time
3575 // thus hiding it here if there is a physical one around or if we have a second
3576 // screen (the virtual touchpad & osk on the phone) attached.
3577- oskEnabled: keyboardsModel.count === 0 && screens.count === 1
3578+ oskEnabled: (keyboardsModel.count === 0 && screens.count === 1) ||
3579+ forceOSKEnabled
3580
3581 // TODO: Factor in the connected input devices (eg: physical keyboard, mouse, touchscreen),
3582 // what's the output device (eg: big TV, desktop monitor, phone display), etc.
3583
3584=== modified file 'qml/Panel/Handle.qml'
3585--- qml/Panel/Handle.qml 2016-03-08 20:59:14 +0000
3586+++ qml/Panel/Handle.qml 2016-03-11 13:51:30 +0000
3587@@ -19,7 +19,7 @@
3588
3589 Rectangle {
3590 id: handle
3591- color: UbuntuColors.slate
3592+ color: theme.palette.normal.foreground
3593 height: units.gu(2)
3594 property bool active: false
3595
3596@@ -35,7 +35,7 @@
3597 id: dot
3598 width: units.dp(3)
3599 height: width
3600- color: handle.active ? UbuntuColors.orange : UbuntuColors.ash
3601+ color: handle.active ? theme.palette.highlighted.foreground : theme.palette.normal.raised
3602 radius: units.dp(1)
3603 }
3604 }
3605
3606=== modified file 'qml/Panel/Indicators/MenuItemFactory.qml'
3607--- qml/Panel/Indicators/MenuItemFactory.qml 2016-03-08 20:59:14 +0000
3608+++ qml/Panel/Indicators/MenuItemFactory.qml 2016-03-11 13:51:30 +0000
3609@@ -228,7 +228,6 @@
3610 text: menuData && menuData.label || ""
3611 iconSource: menuData && menuData.icon || ""
3612 value : menuData && menuData.actionState || 0.0
3613- enabled: menuData && menuData.sensitive || false
3614 highlightWhenPressed: false
3615 }
3616 }
3617
3618=== modified file 'qml/Panel/IndicatorsMenu.qml'
3619--- qml/Panel/IndicatorsMenu.qml 2016-03-08 20:59:14 +0000
3620+++ qml/Panel/IndicatorsMenu.qml 2016-03-11 13:51:30 +0000
3621@@ -38,7 +38,7 @@
3622 property bool enableHint: true
3623 property bool contentEnabled: true
3624 property bool showOnClick: true
3625- property color panelColor: theme.palette.normal.background
3626+ property color panelColor: UbuntuColors.jet
3627
3628 signal showTapped(point position)
3629
3630
3631=== modified file 'qml/Panel/Panel.qml'
3632--- qml/Panel/Panel.qml 2016-03-08 20:59:14 +0000
3633+++ qml/Panel/Panel.qml 2016-03-11 13:51:30 +0000
3634@@ -89,7 +89,7 @@
3635
3636 Rectangle {
3637 id: indicatorAreaBackground
3638- color: callHint.visible ? UbuntuColors.green : theme.palette.normal.background
3639+ color: callHint.visible ? UbuntuColors.green : indicators.panelColor
3640 anchors {
3641 top: parent.top
3642 left: parent.left
3643@@ -169,8 +169,10 @@
3644 objectName: "windowDecorationTitle"
3645 anchors {
3646 left: parent.left
3647+ right: __indicators.left
3648 top: parent.top
3649 leftMargin: units.gu(1)
3650+ rightMargin: units.gu(1)
3651 topMargin: units.gu(0.5)
3652 bottomMargin: units.gu(0.5)
3653 }
3654@@ -181,6 +183,8 @@
3655 fontSize: "medium"
3656 font.weight: Font.Normal
3657 text: PanelState.title
3658+ elide: Text.ElideRight
3659+ maximumLineCount: 1
3660 }
3661
3662 // TODO here would the Locally integrated menus come
3663
3664=== modified file 'qml/ScopeTool.qml'
3665--- qml/ScopeTool.qml 2015-07-15 15:07:19 +0000
3666+++ qml/ScopeTool.qml 2016-03-11 13:51:30 +0000
3667@@ -52,14 +52,6 @@
3668 color: "#FCFCFC"
3669 }
3670
3671- Image {
3672- anchors.fill: dashContent
3673- source: root.width > root.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png"
3674- fillMode: Image.PreserveAspectCrop
3675- horizontalAlignment: Image.AlignRight
3676- verticalAlignment: Image.AlignTop
3677- }
3678-
3679 DashContent {
3680 id: dashContent
3681
3682
3683=== modified file 'qml/Stages/AbstractStage.qml'
3684--- qml/Stages/AbstractStage.qml 2016-03-11 13:51:29 +0000
3685+++ qml/Stages/AbstractStage.qml 2016-03-11 13:51:30 +0000
3686@@ -21,7 +21,7 @@
3687 Rectangle {
3688 id: root
3689
3690- color: "#111111"
3691+ color: "#060606"
3692
3693 // Controls to be set from outside
3694 property bool altTabPressed
3695
3696=== modified file 'qml/Stages/DecoratedWindow.qml'
3697--- qml/Stages/DecoratedWindow.qml 2015-11-30 18:25:47 +0000
3698+++ qml/Stages/DecoratedWindow.qml 2016-03-11 13:51:30 +0000
3699@@ -23,8 +23,8 @@
3700 FocusScope {
3701 id: root
3702
3703- width: applicationWindow.width
3704- height: (decorationShown ? decoration.height : 0) + applicationWindow.height
3705+ width: !counterRotate ? applicationWindow.width : applicationWindow.height
3706+ height: visibleDecorationHeight + (!counterRotate ? applicationWindow.height : applicationWindow.width)
3707
3708 property alias window: applicationWindow
3709 property alias application: applicationWindow.application
3710@@ -36,15 +36,18 @@
3711 property bool highlightShown: false
3712 property real shadowOpacity: 1
3713
3714- property alias requestedWidth: applicationWindow.requestedWidth
3715+ property real requestedWidth
3716 property real requestedHeight
3717+ property alias surfaceOrientationAngle: applicationWindow.surfaceOrientationAngle
3718+ readonly property real visibleDecorationHeight: root.decorationShown ? decoration.height : 0
3719+ readonly property bool counterRotate: surfaceOrientationAngle != 0 && surfaceOrientationAngle != 180
3720
3721- property alias minimumWidth: applicationWindow.minimumWidth
3722- readonly property int minimumHeight: (root.decorationShown ? decoration.height : 0) + applicationWindow.minimumHeight
3723- property alias maximumWidth: applicationWindow.maximumWidth
3724- readonly property int maximumHeight: (root.decorationShown ? decoration.height : 0) + applicationWindow.maximumHeight
3725- property alias widthIncrement: applicationWindow.widthIncrement
3726- property alias heightIncrement: applicationWindow.heightIncrement
3727+ readonly property int minimumWidth: !counterRotate ? applicationWindow.minimumWidth : applicationWindow.minimumHeight
3728+ readonly property int minimumHeight: visibleDecorationHeight + (!counterRotate ? applicationWindow.minimumHeight : applicationWindow.minimumWidth)
3729+ readonly property int maximumWidth: !counterRotate ? applicationWindow.maximumWidth : applicationWindow.maximumHeight
3730+ readonly property int maximumHeight: visibleDecorationHeight + (!counterRotate ? applicationWindow.maximumHeight : applicationWindow.maximumWidth)
3731+ readonly property int widthIncrement: !counterRotate ? applicationWindow.widthIncrement : applicationWindow.heightIncrement
3732+ readonly property int heightIncrement: !counterRotate ? applicationWindow.heightIncrement : applicationWindow.widthIncrement
3733
3734 signal close()
3735 signal maximize()
3736@@ -98,8 +101,29 @@
3737 anchors.top: parent.top
3738 anchors.topMargin: decoration.height
3739 anchors.left: parent.left
3740- requestedHeight: root.requestedHeight - (root.decorationShown ? decoration.height : 0)
3741+ readonly property real requestedHeightMinusDecoration: root.requestedHeight - root.visibleDecorationHeight
3742+ requestedHeight: !counterRotate ? requestedHeightMinusDecoration : root.requestedWidth
3743+ requestedWidth: !counterRotate ? root.requestedWidth : requestedHeightMinusDecoration
3744 interactive: true
3745 focus: true
3746+
3747+ transform: Rotation {
3748+ readonly property int rotationAngle: applicationWindow.application &&
3749+ applicationWindow.application.rotatesWindowContents
3750+ ? ((360 - applicationWindow.surfaceOrientationAngle) % 360) : 0
3751+ origin.x: {
3752+ if (rotationAngle == 90) return applicationWindow.height / 2;
3753+ else if (rotationAngle == 270) return applicationWindow.width / 2;
3754+ else if (rotationAngle == 180) return applicationWindow.width / 2;
3755+ else return 0;
3756+ }
3757+ origin.y: {
3758+ if (rotationAngle == 90) return applicationWindow.height / 2;
3759+ else if (rotationAngle == 270) return applicationWindow.width / 2;
3760+ else if (rotationAngle == 180) return applicationWindow.height / 2;
3761+ else return 0;
3762+ }
3763+ angle: rotationAngle
3764+ }
3765 }
3766 }
3767
3768=== modified file 'qml/Stages/DesktopSpread.qml'
3769--- qml/Stages/DesktopSpread.qml 2015-11-24 17:44:18 +0000
3770+++ qml/Stages/DesktopSpread.qml 2016-03-11 13:51:30 +0000
3771@@ -19,6 +19,7 @@
3772 import Ubuntu.Components 1.3
3773 import Ubuntu.Gestures 0.1
3774 import Unity.Application 0.1
3775+import "../Components"
3776
3777 FocusScope {
3778 id: root
3779@@ -26,8 +27,11 @@
3780 property bool altTabPressed: false
3781 property Item workspace: null
3782
3783+ readonly property alias ready: blurLayer.ready
3784 readonly property alias highlightedIndex: spreadRepeater.highlightedIndex
3785
3786+ signal playFocusAnimation(int index)
3787+
3788 function show() {
3789 spreadContainer.animateIn = true;
3790 root.state = "altTab";
3791@@ -91,6 +95,9 @@
3792
3793 function focusSelected() {
3794 if (spreadRepeater.highlightedIndex != -1) {
3795+ if (spreadContainer.visible) {
3796+ root.playFocusAnimation(spreadRepeater.highlightedIndex)
3797+ }
3798 var application = ApplicationManager.get(spreadRepeater.highlightedIndex);
3799 ApplicationManager.requestFocusApplication(application.appId);
3800 }
3801@@ -101,6 +108,31 @@
3802 state = ""
3803 }
3804
3805+ BlurLayer {
3806+ id: blurLayer
3807+ anchors.fill: parent
3808+ source: root.workspace
3809+ visible: false
3810+ }
3811+
3812+ Rectangle {
3813+ id: spreadBackground
3814+ anchors.fill: parent
3815+ color: "#B2000000"
3816+ visible: false
3817+ opacity: visible ? 1 : 0
3818+ Behavior on opacity {
3819+ UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
3820+ }
3821+ }
3822+
3823+ MouseArea {
3824+ id: eventEater
3825+ anchors.fill: parent
3826+ visible: spreadBackground.visible
3827+ enabled: visible
3828+ }
3829+
3830 Item {
3831 id: spreadContainer
3832 objectName: "spreadContainer"
3833@@ -226,13 +258,20 @@
3834 Transition {
3835 from: ""
3836 to: "altTab"
3837- PropertyAction { target: spreadDelegate; properties: "y,height,width,angle,z,itemScale,itemScaleOriginY,visible" }
3838- PropertyAction { target: clippedSpreadDelegate; properties: "anchors.topMargin" }
3839- PropertyAnimation {
3840- target: spreadDelegate; properties: "x"
3841- from: root.width
3842- duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration :0
3843- easing: UbuntuAnimation.StandardEasing
3844+ SequentialAnimation {
3845+ ParallelAnimation {
3846+ PropertyAction { target: spreadDelegate; properties: "y,height,width,angle,z,itemScale,itemScaleOriginY,visible" }
3847+ PropertyAction { target: clippedSpreadDelegate; properties: "anchors.topMargin" }
3848+ PropertyAnimation {
3849+ target: spreadDelegate; properties: "x"
3850+ from: root.width
3851+ duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration :0
3852+ easing: UbuntuAnimation.StandardEasing
3853+ }
3854+ UbuntuNumberAnimation { target: clippedSpreadDelegate; property: "shadowOpacity"; from: 0; to: spreadMaths.shadowOpacity; duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0 }
3855+ UbuntuNumberAnimation { target: tileInfo; property: "opacity"; from: 0; to: spreadMaths.tileInfoOpacity; duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0 }
3856+ }
3857+ PropertyAction { target: spreadSelectArea; property: "enabled" }
3858 }
3859 }
3860 ]
3861@@ -240,7 +279,11 @@
3862 MouseArea {
3863 id: tileInfo
3864 objectName: "tileInfo"
3865- anchors { left: parent.left; top: clippedSpreadDelegate.bottom; topMargin: units.gu(5) }
3866+ anchors {
3867+ left: parent.left
3868+ top: clippedSpreadDelegate.bottom
3869+ topMargin: ((spreadMaths.sceneHeight - spreadDelegate.y) - clippedSpreadDelegate.height) * 0.2
3870+ }
3871 property int nextItemX: spreadRepeater.count > index + 1 ? spreadRepeater.itemAt(index + 1).x : spreadDelegate.x + units.gu(30)
3872 width: Math.min(units.gu(30), nextItemX - spreadDelegate.x)
3873 height: titleInfoColumn.height
3874@@ -262,12 +305,20 @@
3875 anchors { left: parent.left; top: parent.top; right: parent.right }
3876 spacing: units.gu(1)
3877
3878- UbuntuShape {
3879+ UbuntuShapeForItem {
3880 Layout.preferredHeight: Math.min(units.gu(6), root.height * .05)
3881 Layout.preferredWidth: height * 8 / 7.6
3882 image: Image {
3883 anchors.fill: parent
3884 source: model.icon
3885+ Rectangle {
3886+ anchors.fill: parent
3887+ color: "black"
3888+ opacity: clippedSpreadDelegate.highlightShown ? 0 : .1
3889+ Behavior on opacity {
3890+ UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
3891+ }
3892+ }
3893 }
3894 }
3895 Label {
3896@@ -420,7 +471,7 @@
3897
3898 property var source: ShaderEffectSource {
3899 id: shaderEffectSource
3900- sourceItem: appContainer
3901+ sourceItem: root.workspace
3902 }
3903
3904 fragmentShader: "
3905@@ -494,20 +545,17 @@
3906 from: "*"
3907 to: "altTab"
3908 SequentialAnimation {
3909- PropertyAction { target: hoverMouseArea; property: "progressiveScrollingEnabled"; value: false }
3910 PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: Math.min(ApplicationManager.count - 1, 1) }
3911- PauseAnimation { duration: 140 }
3912+ PauseAnimation { duration: spreadContainer.animateIn ? 0 : 140 }
3913 PropertyAction { target: workspaceSelector; property: "visible" }
3914 PropertyAction { target: spreadContainer; property: "visible" }
3915 ParallelAnimation {
3916- UbuntuNumberAnimation {
3917- target: blurLayer; properties: "saturation,blurRadius";
3918- duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0
3919- }
3920+ UbuntuNumberAnimation { target: blurLayer; properties: "saturation,blurRadius"; duration: UbuntuAnimation.SnapDuration }
3921 PropertyAction { target: spreadFlickable; property: "visible" }
3922 PropertyAction { targets: [currentSelectedLabel,spreadBackground]; property: "visible" }
3923 PropertyAction { target: spreadFlickable; property: "contentX"; value: 0 }
3924 }
3925+ PropertyAction { target: hoverMouseArea; properties: "enabled,progressiveScrollingEnabled"; value: false }
3926 }
3927 },
3928 Transition {
3929@@ -518,6 +566,5 @@
3930 PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: -1 }
3931 PropertyAction { target: spreadContainer; property: "animateIn"; value: false }
3932 }
3933-
3934 ]
3935 }
3936
3937=== modified file 'qml/Stages/DesktopSpreadDelegate.qml'
3938--- qml/Stages/DesktopSpreadDelegate.qml 2015-12-01 12:17:24 +0000
3939+++ qml/Stages/DesktopSpreadDelegate.qml 2016-03-11 13:51:30 +0000
3940@@ -56,6 +56,11 @@
3941 }
3942 ]
3943
3944+ scale: highlightShown ? 1.025 : 1
3945+ Behavior on scale {
3946+ UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
3947+ }
3948+
3949 BorderImage {
3950 anchors {
3951 fill: root
3952@@ -70,7 +75,7 @@
3953 anchors.fill: parent
3954 anchors.margins: -units.gu(1)
3955 color: "white"
3956- opacity: highlightShown ? 0.15 : 0
3957+ opacity: highlightShown ? 0.55 : 0
3958 antialiasing: true
3959 }
3960
3961@@ -108,4 +113,13 @@
3962 ]
3963 }
3964 }
3965+
3966+ Rectangle {
3967+ anchors.fill: parent
3968+ color: "black"
3969+ opacity: root.highlightShown ? 0 : .1
3970+ Behavior on opacity {
3971+ UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
3972+ }
3973+ }
3974 }
3975
3976=== modified file 'qml/Stages/DesktopStage.qml'
3977--- qml/Stages/DesktopStage.qml 2016-03-11 13:51:29 +0000
3978+++ qml/Stages/DesktopStage.qml 2016-03-11 13:51:30 +0000
3979@@ -255,14 +255,40 @@
3980 focus: appId === priv.focusedAppId
3981 width: decoratedWindow.width
3982 height: decoratedWindow.height
3983+
3984+ Connections {
3985+ target: root
3986+ onShellOrientationAngleChanged: {
3987+ // at this point decoratedWindow.surfaceOrientationAngle is the old shellOrientationAngle
3988+ if (application && application.rotatesWindowContents) {
3989+ if (state == "normal") {
3990+ var angleDiff = decoratedWindow.surfaceOrientationAngle - shellOrientationAngle;
3991+ angleDiff = (360 + angleDiff) % 360;
3992+ if (angleDiff === 90 || angleDiff === 270) {
3993+ var aux = decoratedWindow.requestedHeight;
3994+ decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.visibleDecorationHeight;
3995+ decoratedWindow.requestedWidth = aux - decoratedWindow.visibleDecorationHeight;
3996+ }
3997+ }
3998+ decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;
3999+ } else {
4000+ decoratedWindow.surfaceOrientationAngle = 0;
4001+ }
4002+ }
4003+ }
4004+ Component.onCompleted: {
4005+ decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;
4006+ }
4007+
4008+ readonly property alias application: decoratedWindow.application
4009+ readonly property alias minimumWidth: decoratedWindow.minimumWidth
4010+ readonly property alias minimumHeight: decoratedWindow.minimumHeight
4011+ readonly property alias maximumWidth: decoratedWindow.maximumWidth
4012+ readonly property alias maximumHeight: decoratedWindow.maximumHeight
4013+ readonly property alias widthIncrement: decoratedWindow.widthIncrement
4014+ readonly property alias heightIncrement: decoratedWindow.heightIncrement
4015 property alias requestedWidth: decoratedWindow.requestedWidth
4016 property alias requestedHeight: decoratedWindow.requestedHeight
4017- property alias minimumWidth: decoratedWindow.minimumWidth
4018- property alias minimumHeight: decoratedWindow.minimumHeight
4019- property alias maximumWidth: decoratedWindow.maximumWidth
4020- property alias maximumHeight: decoratedWindow.maximumHeight
4021- property alias widthIncrement: decoratedWindow.widthIncrement
4022- property alias heightIncrement: decoratedWindow.heightIncrement
4023
4024 QtObject {
4025 id: appDelegatePrivate
4026@@ -351,12 +377,26 @@
4027 ApplicationManager.focusApplication(appId);
4028 }
4029
4030+ function playFocusAnimation() {
4031+ focusAnimation.start()
4032+ }
4033+
4034+ UbuntuNumberAnimation {
4035+ id: focusAnimation
4036+ target: appDelegate
4037+ property: "scale"
4038+ from: 0.98
4039+ to: 1
4040+ duration: UbuntuAnimation.SnapDuration
4041+ }
4042+
4043 states: [
4044 State {
4045 name: "fullscreen"; when: decoratedWindow.fullscreen
4046 PropertyChanges {
4047 target: appDelegate;
4048- x: 0; y: -PanelState.panelHeight
4049+ x: rotation == 0 ? 0 : (parent.width - width) / 2 + (shellOrientationAngle == 90 ? -PanelState.panelHeight : PanelState.panelHeight)
4050+ y: rotation == 0 ? -PanelState.panelHeight : (parent.height - height) / 2
4051 requestedWidth: appContainer.width; requestedHeight: appContainer.height;
4052 }
4053 },
4054@@ -441,7 +481,7 @@
4055 target: appDelegate
4056 property: "z"
4057 value: ApplicationManager.count + 1
4058- when: index == spread.highlightedIndex && blurLayer.ready
4059+ when: index == spread.highlightedIndex && spread.ready
4060 }
4061
4062 WindowResizeArea {
4063@@ -477,27 +517,6 @@
4064 }
4065 }
4066
4067- BlurLayer {
4068- id: blurLayer
4069- anchors.fill: appContainer
4070- source: appContainer
4071- visible: false
4072- }
4073-
4074- Rectangle {
4075- id: spreadBackground
4076- anchors.fill: parent
4077- color: "#55000000"
4078- visible: false
4079- }
4080-
4081- MouseArea {
4082- id: eventEater
4083- anchors.fill: parent
4084- visible: spreadBackground.visible
4085- enabled: visible
4086- }
4087-
4088 EdgeBarrier {
4089 id: edgeBarrier
4090
4091@@ -513,7 +532,7 @@
4092 rotation: 90
4093 anchors.centerIn: parent
4094 gradient: Gradient {
4095- GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
4096+ GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.5)}
4097 GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}
4098 }
4099 }
4100@@ -535,5 +554,9 @@
4101 workspace: appContainer
4102 focus: state == "altTab"
4103 altTabPressed: root.altTabPressed
4104+
4105+ onPlayFocusAnimation: {
4106+ appRepeater.itemAt(index).playFocusAnimation();
4107+ }
4108 }
4109 }
4110
4111=== modified file 'qml/Stages/PhoneStage.qml'
4112--- qml/Stages/PhoneStage.qml 2016-01-14 13:03:20 +0000
4113+++ qml/Stages/PhoneStage.qml 2016-03-11 13:51:30 +0000
4114@@ -44,6 +44,33 @@
4115 }
4116 }
4117
4118+ onAltTabPressedChanged: {
4119+ if (!spreadEnabled || !altTabEnabled) {
4120+ return;
4121+ }
4122+ if (altTabPressed) {
4123+ spreadView.snapToSpread();
4124+ priv.highlightIndex = Math.min(spreadRepeater.count - 1, 1);
4125+ } else {
4126+ spreadView.snapTo(priv.highlightIndex)
4127+ }
4128+ }
4129+
4130+ FocusScope {
4131+ focus: root.altTabPressed
4132+
4133+ Keys.onPressed: {
4134+ switch (event.key) {
4135+ case Qt.Key_Tab:
4136+ priv.highlightIndex = (priv.highlightIndex + 1) % spreadRepeater.count
4137+ break;
4138+ case Qt.Key_Backtab:
4139+ priv.highlightIndex = (priv.highlightIndex + spreadRepeater.count - 1) % spreadRepeater.count
4140+ break;
4141+ }
4142+ }
4143+ }
4144+
4145 // Functions to be called from outside
4146 function updateFocusedAppOrientation() {
4147 if (spreadRepeater.count > 0) {
4148@@ -74,6 +101,12 @@
4149 }
4150 }
4151
4152+ function pushRightEdge(amount) {
4153+ if (spreadView.contentX == -spreadView.shift) {
4154+ edgeBarrier.push(amount);
4155+ }
4156+ }
4157+
4158 mainApp: applicationManager.focusedApplicationId
4159 ? applicationManager.findApplication(applicationManager.focusedApplicationId)
4160 : null
4161@@ -180,6 +213,7 @@
4162
4163 property real oldInverseProgress: 0
4164 property bool animateX: false
4165+ property int highlightIndex: 0
4166
4167 onFocusedAppDelegateChanged: {
4168 if (focusedAppDelegate) {
4169@@ -214,6 +248,10 @@
4170 spreadView.phase = 0;
4171 spreadView.contentX = -spreadView.shift;
4172 }
4173+
4174+ onHighlightIndexChanged: {
4175+ spreadView.contentX = highlightIndex * spreadView.contentWidth / (spreadRepeater.count + 2)
4176+ }
4177 }
4178 Timer {
4179 id: fullyShowingFocusedAppUpdateTimer
4180@@ -281,6 +319,11 @@
4181 }
4182 }
4183
4184+ Behavior on contentX {
4185+ enabled: root.altTabPressed
4186+ UbuntuNumberAnimation {}
4187+ }
4188+
4189 onShiftedContentXChanged: {
4190 if (root.beingResized) {
4191 // Flickabe.contentX wiggles during resizes. Don't react to it.
4192@@ -319,12 +362,17 @@
4193 } else if (shiftedContentX < positionMarker3 * width) {
4194 snapTo(1);
4195 } else if (phase < 2){
4196- // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
4197- snapAnimation.targetContentX = width * positionMarker4 + 1 - shift;
4198- snapAnimation.start();
4199+ snapToSpread();
4200 root.opened();
4201 }
4202 }
4203+
4204+ function snapToSpread() {
4205+ // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
4206+ snapAnimation.targetContentX = (root.width * spreadView.positionMarker4) + 1 - spreadView.shift;
4207+ snapAnimation.start();
4208+ }
4209+
4210 function snapTo(index) {
4211 if (!root.altTabEnabled) {
4212 // Reset to start instead
4213@@ -427,6 +475,7 @@
4214 maximizedAppTopMargin: root.maximizedAppTopMargin
4215 dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated
4216 focusFirstApp: root.focusFirstApp
4217+ highlightShown: root.altTabPressed && index === priv.highlightIndex
4218
4219 readonly property bool isDash: model.appId == "unity8-dash"
4220
4221@@ -651,4 +700,29 @@
4222 }
4223 }
4224 }
4225+
4226+ EdgeBarrier {
4227+ id: edgeBarrier
4228+
4229+ // NB: it does its own positioning according to the specified edge
4230+ edge: Qt.RightEdge
4231+
4232+ onPassed: {
4233+ spreadView.snapToSpread();
4234+ }
4235+ material: Component {
4236+ Item {
4237+ Rectangle {
4238+ width: parent.height
4239+ height: parent.width
4240+ rotation: 90
4241+ anchors.centerIn: parent
4242+ gradient: Gradient {
4243+ GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
4244+ GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}
4245+ }
4246+ }
4247+ }
4248+ }
4249+ }
4250 }
4251
4252=== modified file 'qml/Stages/SpreadDelegate.qml'
4253--- qml/Stages/SpreadDelegate.qml 2015-11-04 14:57:45 +0000
4254+++ qml/Stages/SpreadDelegate.qml 2016-03-11 13:51:30 +0000
4255@@ -43,6 +43,7 @@
4256 property int shellOrientationAngle
4257 property int shellOrientation
4258 property QtObject orientations
4259+ property bool highlightShown: false
4260
4261 function matchShellOrientation() {
4262 if (!root.application)
4263@@ -261,6 +262,25 @@
4264 Behavior on opacity { UbuntuNumberAnimation {} }
4265 }
4266
4267+ Rectangle {
4268+ id: selectionHighlight
4269+ objectName: "selectionHighlight"
4270+ anchors.fill: appWindow
4271+ anchors.margins: -units.gu(1)
4272+ color: "white"
4273+ opacity: root.highlightShown ? 0.15 : 0
4274+ antialiasing: true
4275+ visible: opacity > 0
4276+ }
4277+
4278+ Rectangle {
4279+ anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
4280+ height: units.dp(2)
4281+ color: UbuntuColors.orange
4282+ visible: root.highlightShown
4283+ antialiasing: true
4284+ }
4285+
4286 ApplicationWindow {
4287 id: appWindow
4288 objectName: application ? "appWindow_" + application.appId : "appWindow_null"
4289
4290=== modified file 'qml/Stages/TabletStage.qml'
4291--- qml/Stages/TabletStage.qml 2016-01-14 13:03:20 +0000
4292+++ qml/Stages/TabletStage.qml 2016-03-11 13:51:30 +0000
4293@@ -70,6 +70,12 @@
4294 }
4295 }
4296
4297+ function pushRightEdge(amount) {
4298+ if (spreadView.contentX == -spreadView.shift) {
4299+ edgeBarrier.push(amount);
4300+ }
4301+ }
4302+
4303 orientationChangesEnabled: priv.mainAppOrientationChangesEnabled
4304
4305 supportedOrientations: mainApp ? mainApp.supportedOrientations
4306@@ -102,6 +108,38 @@
4307 priv.oldInverseProgress = inverseProgress;
4308 }
4309
4310+ onAltTabPressedChanged: {
4311+ if (!spreadEnabled) {
4312+ return;
4313+ }
4314+ if (altTabPressed) {
4315+ priv.highlightIndex = Math.min(spreadRepeater.count - 1, 1);
4316+ spreadView.snapToSpread();
4317+ } else {
4318+ for (var i = 0; i < spreadRepeater.count; i++) {
4319+ if (spreadRepeater.itemAt(i).zIndex === priv.highlightIndex) {
4320+ spreadView.snapTo(i);
4321+ return;
4322+ }
4323+ }
4324+ }
4325+ }
4326+
4327+ FocusScope {
4328+ focus: root.altTabPressed
4329+
4330+ Keys.onPressed: {
4331+ switch (event.key) {
4332+ case Qt.Key_Tab:
4333+ priv.highlightIndex = (priv.highlightIndex + 1) % spreadRepeater.count
4334+ break;
4335+ case Qt.Key_Backtab:
4336+ priv.highlightIndex = (priv.highlightIndex + spreadRepeater.count - 1) % spreadRepeater.count
4337+ break;
4338+ }
4339+ }
4340+ }
4341+
4342 QtObject {
4343 id: priv
4344 objectName: "stagesPriv"
4345@@ -130,6 +168,8 @@
4346
4347 property int oldInverseProgress: 0
4348
4349+ property int highlightIndex: 0
4350+
4351 onFocusedAppIdChanged: {
4352 if (priv.focusedAppId.length > 0) {
4353 var focusedApp = ApplicationManager.findApplication(focusedAppId);
4354@@ -185,6 +225,10 @@
4355 }
4356 return oneWayFlick;
4357 }
4358+
4359+ onHighlightIndexChanged: {
4360+ spreadView.contentX = highlightIndex * spreadView.contentWidth / (spreadRepeater.count + 2)
4361+ }
4362 }
4363
4364 Connections {
4365@@ -391,11 +435,16 @@
4366 } else if (shiftedContentX < phase1Width) {
4367 snapTo(1);
4368 } else {
4369- // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
4370- snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1 - shift;
4371- snapAnimation.start();
4372+ snapToSpread();
4373 }
4374 }
4375+
4376+ function snapToSpread() {
4377+ // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
4378+ snapAnimation.targetContentX = (spreadView.width * spreadView.positionMarker4) + 1 - shift;
4379+ snapAnimation.start();
4380+ }
4381+
4382 function snapTo(index) {
4383 spreadView.selectedIndex = index;
4384 snapAnimation.targetContentX = -shift;
4385@@ -481,6 +530,11 @@
4386 }
4387 }
4388
4389+ Behavior on contentX {
4390+ enabled: root.altTabPressed
4391+ UbuntuNumberAnimation {}
4392+ }
4393+
4394 MouseArea {
4395 id: spreadRow
4396 x: spreadView.contentX
4397@@ -611,6 +665,7 @@
4398 dragOffset: !isDash && model.appId == priv.mainStageAppId && root.inverseProgress > 0 && spreadView.phase === 0 ? root.inverseProgress : 0
4399 application: ApplicationManager.get(index)
4400 closeable: !isDash
4401+ highlightShown: root.altTabPressed && priv.highlightIndex == zIndex
4402
4403 readonly property bool wantsMainStage: model.stage == ApplicationInfoInterface.MainStage
4404
4405@@ -805,4 +860,29 @@
4406 }
4407 }
4408 }
4409+
4410+ EdgeBarrier {
4411+ id: edgeBarrier
4412+
4413+ // NB: it does its own positioning according to the specified edge
4414+ edge: Qt.RightEdge
4415+
4416+ onPassed: {
4417+ spreadView.snapToSpread();
4418+ }
4419+ material: Component {
4420+ Item {
4421+ Rectangle {
4422+ width: parent.height
4423+ height: parent.width
4424+ rotation: 90
4425+ anchors.centerIn: parent
4426+ gradient: Gradient {
4427+ GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
4428+ GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}
4429+ }
4430+ }
4431+ }
4432+ }
4433+ }
4434 }
4435
4436=== modified file 'qml/Stages/WindowResizeArea.qml'
4437--- qml/Stages/WindowResizeArea.qml 2016-03-11 13:51:29 +0000
4438+++ qml/Stages/WindowResizeArea.qml 2016-03-11 13:51:30 +0000
4439@@ -301,7 +301,7 @@
4440 }
4441
4442 if (d.topBorder) {
4443- var newTargetY = d.startY + deltaY;
4444+ var newTargetY = Math.max(d.startY + deltaY, PanelState.panelHeight); // disallow resizing up past Panel
4445 var bottomBorderY = target.y + target.height;
4446 if (bottomBorderY > newTargetY + d.minimumHeight) {
4447 if (bottomBorderY < newTargetY + d.maximumHeight) {
4448
4449=== modified file 'src/CMakeLists.txt'
4450--- src/CMakeLists.txt 2015-12-16 13:58:39 +0000
4451+++ src/CMakeLists.txt 2016-03-11 13:51:30 +0000
4452@@ -33,7 +33,7 @@
4453
4454 pkg_check_modules(ANDROID_PROPERTIES REQUIRED libandroid-properties)
4455 add_executable(${SHELL_APP} ${SOURCE_FILES})
4456-qt5_use_modules(${SHELL_APP} Gui Qml Quick Test)
4457+qt5_use_modules(${SHELL_APP} DBus Gui Qml Quick Test)
4458
4459 if (NOT "${ANDROID_PROPERTIES_INCLUDE_DIRS}" STREQUAL "")
4460 set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${ANDROID_PROPERTIES_INCLUDE_DIRS})
4461
4462=== modified file 'src/CachingNetworkManagerFactory.cpp'
4463--- src/CachingNetworkManagerFactory.cpp 2015-10-27 14:17:37 +0000
4464+++ src/CachingNetworkManagerFactory.cpp 2016-03-11 13:51:30 +0000
4465@@ -24,12 +24,12 @@
4466 CachingNetworkAccessManager::CachingNetworkAccessManager(QObject *parent)
4467 : QNetworkAccessManager(parent)
4468 {
4469- m_networkingStatus = new ubuntu::connectivity::NetworkingStatus(this);
4470+ m_networkingStatus = new connectivityqt::Connectivity(QDBusConnection::sessionBus(), this);
4471 }
4472
4473 QNetworkReply* CachingNetworkAccessManager::createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
4474 {
4475- if (m_networkingStatus->status() != ubuntu::connectivity::NetworkingStatus::Status::Online) {
4476+ if (m_networkingStatus->status() != connectivityqt::Connectivity::Status::Online) {
4477 qDebug() << "Not connected to the internet. Request for" << request.url().toString() << "will be served only from the cache.";
4478 QNetworkRequest req(request);
4479 req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
4480
4481=== modified file 'src/CachingNetworkManagerFactory.h'
4482--- src/CachingNetworkManagerFactory.h 2014-11-20 12:57:02 +0000
4483+++ src/CachingNetworkManagerFactory.h 2016-03-11 13:51:30 +0000
4484@@ -21,10 +21,11 @@
4485 #include <QQmlNetworkAccessManagerFactory>
4486 #include <QNetworkAccessManager>
4487
4488-#include <ubuntu/connectivity/networking-status.h>
4489+#include <connectivityqt/connectivity.h>
4490
4491 class CachingNetworkAccessManager : public QNetworkAccessManager
4492 {
4493+Q_OBJECT
4494 public:
4495 CachingNetworkAccessManager(QObject *parent = 0);
4496
4497@@ -32,7 +33,7 @@
4498 QNetworkReply* createRequest(Operation op, const QNetworkRequest &req, QIODevice *outgoingData = 0) override;
4499
4500 private:
4501- ubuntu::connectivity::NetworkingStatus* m_networkingStatus;
4502+ connectivityqt::Connectivity* m_networkingStatus;
4503 };
4504
4505 class CachingNetworkManagerFactory : public QQmlNetworkAccessManagerFactory
4506
4507=== modified file 'src/Dash/CMakeLists.txt'
4508--- src/Dash/CMakeLists.txt 2015-12-16 13:58:39 +0000
4509+++ src/Dash/CMakeLists.txt 2016-03-11 13:51:30 +0000
4510@@ -9,7 +9,7 @@
4511
4512 add_executable(unity8-dash ${DASH_SRCS})
4513
4514-qt5_use_modules(unity8-dash Gui Qml Quick Test)
4515+qt5_use_modules(unity8-dash DBus Gui Qml Quick Test)
4516
4517 # For it to find libUbuntuGestures.so, needed by Ubuntu.Gestures QML module.
4518 set_target_properties(unity8-dash PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}")
4519
4520=== modified file 'tests/autopilot/unity8/dash.py'
4521--- tests/autopilot/unity8/dash.py 2015-12-11 09:10:01 +0000
4522+++ tests/autopilot/unity8/dash.py 2016-03-11 13:51:30 +0000
4523@@ -211,8 +211,7 @@
4524 self.get_root_instance().select_single(
4525 objectName='processingIndicator').visible.wait_for(False)
4526 return preview_list.select_single(
4527- Preview, objectName='preview{}'.format(
4528- preview_list.initialIndex))
4529+ Preview, objectName='preview')
4530
4531 @autopilot_logging.log_action(logger.debug)
4532 def click_scope_item(self, category, title, press_duration=0.10):
4533
4534=== modified file 'tests/autopilot/unity8/shell/tests/test_helpers.py'
4535--- tests/autopilot/unity8/shell/tests/test_helpers.py 2015-09-03 07:44:51 +0000
4536+++ tests/autopilot/unity8/shell/tests/test_helpers.py 2016-03-11 13:51:30 +0000
4537@@ -117,13 +117,11 @@
4538 def test_open_preview(self):
4539 preview = self.generic_scope.open_preview('0', 'Title.0.0')
4540 self.assertIsInstance(preview, dash_helpers.Preview)
4541- self.assertTrue(preview.isCurrent)
4542
4543 def test_open_preview_of_non_visible_item(self):
4544 """Open an item that requires swiping to make it visible."""
4545 preview = self.generic_scope.open_preview('2', 'Title.2.0')
4546 self.assertIsInstance(preview, dash_helpers.Preview)
4547- self.assertTrue(preview.isCurrent)
4548
4549
4550 class DashAppsHelperTestCase(tests.DashBaseTestCase):
4551
4552=== modified file 'tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp'
4553--- tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp 2015-01-20 11:50:19 +0000
4554+++ tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp 2016-03-11 13:51:30 +0000
4555@@ -47,20 +47,6 @@
4556 roles[HasMessagesRole] = "hasMessages";
4557 roles[ImagePathRole] = "imagePath";
4558 setRoleNames(roles);
4559-
4560- // Now modify our mock user backgrounds
4561- QDir bgdir = QDir("/usr/share/demo-assets/shell/backgrounds/");
4562- QStringList backgrounds = bgdir.entryList(QDir::Files | QDir::NoDotAndDotDot);
4563-
4564- for (int i = 0, j = 0; i < d->entries.size(); i++) {
4565- Entry &entry = d->entries[i];
4566- if (entry.background.isNull() && !backgrounds.isEmpty()) {
4567- entry.background = bgdir.filePath(backgrounds[j++]);
4568- if (j >= backgrounds.length()) {
4569- j = 0;
4570- }
4571- }
4572- }
4573 }
4574
4575 UsersModel::~UsersModel()
4576
4577=== modified file 'tests/mocks/Unity/Application/ApplicationManager.cpp'
4578--- tests/mocks/Unity/Application/ApplicationManager.cpp 2015-12-03 18:10:39 +0000
4579+++ tests/mocks/Unity/Application/ApplicationManager.cpp 2016-03-11 13:51:30 +0000
4580@@ -345,6 +345,18 @@
4581 m_availableApplications.append(application);
4582
4583 application = new ApplicationInfo(this);
4584+ application->setAppId("camera-app2");
4585+ application->setName("Camera2");
4586+ application->setScreenshotId("camera");
4587+ application->setIconId("camera");
4588+ application->setSupportedOrientations(Qt::PortraitOrientation
4589+ | Qt::LandscapeOrientation
4590+ | Qt::InvertedPortraitOrientation
4591+ | Qt::InvertedLandscapeOrientation);
4592+ application->setRotatesWindowContents(true);
4593+ m_availableApplications.append(application);
4594+
4595+ application = new ApplicationInfo(this);
4596 application->setAppId("gallery-app");
4597 application->setName("Gallery");
4598 application->setScreenshotId("gallery");
4599
4600=== modified file 'tests/mocks/Unity/Application/MirSurface.cpp'
4601--- tests/mocks/Unity/Application/MirSurface.cpp 2015-11-30 18:25:47 +0000
4602+++ tests/mocks/Unity/Application/MirSurface.cpp 2016-03-11 13:51:30 +0000
4603@@ -17,13 +17,15 @@
4604 #include "MirSurface.h"
4605
4606 #include <QDebug>
4607+#include <QQmlEngine>
4608
4609 MirSurface::MirSurface(const QString& name,
4610 Mir::Type type,
4611 Mir::State state,
4612 const QUrl& screenshot,
4613- const QUrl &qmlFilePath)
4614- : unity::shell::application::MirSurfaceInterface(nullptr)
4615+ const QUrl &qmlFilePath,
4616+ QObject *parent)
4617+ : unity::shell::application::MirSurfaceInterface(parent)
4618 , m_name(name)
4619 , m_type(type)
4620 , m_state(state)
4621@@ -38,6 +40,8 @@
4622 , m_slowToResize(false)
4623 {
4624 // qDebug() << "MirSurface::MirSurface() " << name;
4625+ QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
4626+
4627 m_delayedResizeTimer.setInterval(600);
4628 m_delayedResizeTimer.setSingleShot(true);
4629 connect(&m_delayedResizeTimer, &QTimer::timeout, this, &MirSurface::applyDelayedResize);
4630
4631=== modified file 'tests/mocks/Unity/Application/MirSurface.h'
4632--- tests/mocks/Unity/Application/MirSurface.h 2015-11-30 18:25:47 +0000
4633+++ tests/mocks/Unity/Application/MirSurface.h 2016-03-11 13:51:30 +0000
4634@@ -41,7 +41,8 @@
4635 Mir::Type type,
4636 Mir::State state,
4637 const QUrl& screenshot,
4638- const QUrl &qmlFilePath = QUrl());
4639+ const QUrl &qmlFilePath = QUrl(),
4640+ QObject *parent = nullptr);
4641 virtual ~MirSurface();
4642
4643 ////
4644
4645=== modified file 'tests/mocks/Unity/Application/MirSurfaceItem.cpp'
4646--- tests/mocks/Unity/Application/MirSurfaceItem.cpp 2016-01-25 15:00:31 +0000
4647+++ tests/mocks/Unity/Application/MirSurfaceItem.cpp 2016-03-11 13:51:30 +0000
4648@@ -20,6 +20,7 @@
4649
4650 #include <QGuiApplication>
4651 #include <QQuickView>
4652+#include <QQmlContext>
4653 #include <QQmlProperty>
4654 #include <QQmlEngine>
4655 #include <QString>
4656@@ -220,10 +221,6 @@
4657 connect(m_qmlSurface, &MirSurface::liveChanged, this, &MirSurfaceItem::liveChanged);
4658 connect(m_qmlSurface, &MirSurface::stateChanged, this, &MirSurfaceItem::surfaceStateChanged);
4659
4660- // The assumptions I make here really should hold.
4661- QQuickView *quickView =
4662- qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
4663-
4664 QUrl qmlComponentFilePath;
4665 if (!m_qmlSurface->qmlFilePath().isEmpty()) {
4666 qmlComponentFilePath = m_qmlSurface->qmlFilePath();
4667@@ -231,7 +228,7 @@
4668 qmlComponentFilePath = QUrl("qrc:///Unity/Application/MirSurfaceItem.qml");
4669 }
4670
4671- m_qmlContentComponent = new QQmlComponent(quickView->engine(), qmlComponentFilePath);
4672+ m_qmlContentComponent = new QQmlComponent(QQmlEngine::contextForObject(parent())->engine(), qmlComponentFilePath);
4673
4674 switch (m_qmlContentComponent->status()) {
4675 case QQmlComponent::Ready:
4676
4677=== modified file 'tests/mocks/Unity/Application/SurfaceManager.cpp'
4678--- tests/mocks/Unity/Application/SurfaceManager.cpp 2015-11-30 18:25:47 +0000
4679+++ tests/mocks/Unity/Application/SurfaceManager.cpp 2016-03-11 13:51:30 +0000
4680@@ -34,6 +34,13 @@
4681 QObject(parent)
4682 , m_virtualKeyboard(nullptr)
4683 {
4684+ m_virtualKeyboard = new VirtualKeyboard(this);
4685+ connect(m_virtualKeyboard, &QObject::destroyed, this, [this](QObject *obj) {
4686+ MirSurface* surface = qobject_cast<MirSurface*>(obj);
4687+ m_virtualKeyboard = nullptr;
4688+ Q_EMIT inputMethodSurfaceChanged();
4689+ Q_EMIT surfaceDestroyed(surface);
4690+ });
4691 }
4692
4693 MirSurface *SurfaceManager::createSurface(const QString& name,
4694@@ -58,16 +65,8 @@
4695 return surface;
4696 }
4697
4698-MirSurface *SurfaceManager::inputMethodSurface()
4699+MirSurface *SurfaceManager::inputMethodSurface() const
4700 {
4701- if (!m_virtualKeyboard) {
4702- m_virtualKeyboard = new VirtualKeyboard;
4703- connect(m_virtualKeyboard, &QObject::destroyed, this, [this](QObject *obj) {
4704- MirSurface* surface = qobject_cast<MirSurface*>(obj);
4705- Q_EMIT surfaceDestroyed(surface);
4706- });
4707- Q_EMIT surfaceCreated(m_virtualKeyboard);
4708- }
4709 return m_virtualKeyboard;
4710 }
4711
4712
4713=== modified file 'tests/mocks/Unity/Application/SurfaceManager.h'
4714--- tests/mocks/Unity/Application/SurfaceManager.h 2015-11-30 18:25:47 +0000
4715+++ tests/mocks/Unity/Application/SurfaceManager.h 2016-03-11 13:51:30 +0000
4716@@ -25,7 +25,7 @@
4717 class SurfaceManager : public QObject
4718 {
4719 Q_OBJECT
4720-
4721+ Q_PROPERTY(MirSurface* inputMethodSurface READ inputMethodSurface NOTIFY inputMethodSurfaceChanged)
4722 Q_PROPERTY(int newSurfaceMinimumWidth READ newSurfaceMinimumWidth WRITE setNewSurfaceMinimumWidth NOTIFY newSurfaceMinimumWidthChanged)
4723 Q_PROPERTY(int newSurfaceMaximumWidth READ newSurfaceMaximumWidth WRITE setNewSurfaceMaximumWidth NOTIFY newSurfaceMaximumWidthChanged)
4724 Q_PROPERTY(int newSurfaceMinimumHeight READ newSurfaceMinimumHeight WRITE setNewSurfaceMinimumHeight NOTIFY newSurfaceMinimumHeightChanged)
4725@@ -43,8 +43,7 @@
4726 Mir::State state,
4727 const QUrl& screenshot);
4728
4729- // To be used in the tests
4730- Q_INVOKABLE MirSurface* inputMethodSurface();
4731+ MirSurface* inputMethodSurface() const;
4732
4733 int newSurfaceMinimumWidth() const { return m_newSurfaceMinimumWidth; }
4734 void setNewSurfaceMinimumWidth(int value);
4735@@ -65,6 +64,7 @@
4736 void setNewSurfaceHeightIncrement(int);
4737
4738 Q_SIGNALS:
4739+ void inputMethodSurfaceChanged();
4740 void countChanged();
4741 void surfaceCreated(MirSurface *surface);
4742 void surfaceDestroyed(MirSurface*surface);
4743
4744=== modified file 'tests/mocks/Unity/Application/VirtualKeyboard.cpp'
4745--- tests/mocks/Unity/Application/VirtualKeyboard.cpp 2015-09-02 10:35:16 +0000
4746+++ tests/mocks/Unity/Application/VirtualKeyboard.cpp 2016-03-11 13:51:30 +0000
4747@@ -22,12 +22,13 @@
4748
4749 #include <QDebug>
4750
4751-VirtualKeyboard::VirtualKeyboard()
4752+VirtualKeyboard::VirtualKeyboard(QObject *parent)
4753 : MirSurface("input-method",
4754 Mir::InputMethodType,
4755 Mir::MinimizedState,
4756 QUrl("qrc:///Unity/Application/vkb_portrait.png"),
4757- QUrl("qrc:///Unity/Application/VirtualKeyboard.qml"))
4758+ QUrl("qrc:///Unity/Application/VirtualKeyboard.qml"),
4759+ parent)
4760 {
4761 }
4762
4763
4764=== modified file 'tests/mocks/Unity/Application/VirtualKeyboard.h'
4765--- tests/mocks/Unity/Application/VirtualKeyboard.h 2015-08-19 20:30:09 +0000
4766+++ tests/mocks/Unity/Application/VirtualKeyboard.h 2016-03-11 13:51:30 +0000
4767@@ -25,7 +25,7 @@
4768 {
4769 Q_OBJECT
4770 public:
4771- explicit VirtualKeyboard();
4772+ explicit VirtualKeyboard(QObject *parent = nullptr);
4773 ~VirtualKeyboard();
4774 };
4775
4776
4777=== modified file 'tests/mocks/Unity/Application/plugin.cpp'
4778--- tests/mocks/Unity/Application/plugin.cpp 2015-08-03 15:00:47 +0000
4779+++ tests/mocks/Unity/Application/plugin.cpp 2016-03-11 13:51:30 +0000
4780@@ -78,8 +78,9 @@
4781 qmlRegisterUncreatableType<unity::shell::application::ApplicationInfoInterface>(uri, 0, 1, "ApplicationInfoInterface", "Abstract interface. Cannot be created in QML");
4782 qmlRegisterUncreatableType<Session>(uri, 0, 1, "Session", "Session can't be instantiated from QML");
4783 qmlRegisterUncreatableType<MirSurface>(uri, 0, 1, "MirSurface", "MirSurface can't be instantiated from QML");
4784+ qmlRegisterUncreatableType<unity::shell::application::MirSurfaceInterface>(
4785+ uri, 0, 1, "MirSurface", "MirSurface can't be instantiated from QML");
4786 qmlRegisterType<MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem");
4787-
4788 qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");
4789
4790 qmlRegisterSingletonType<ApplicationManager>(uri, 0, 1, "ApplicationManager", applicationManagerSingleton);
4791
4792=== modified file 'tests/mocks/Unity/Launcher/MockLauncherModel.cpp'
4793--- tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2016-03-11 13:51:29 +0000
4794+++ tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2016-03-11 13:51:30 +0000
4795@@ -32,6 +32,9 @@
4796 item->setProgress(10);
4797 item->setPinned(true);
4798 m_list.append(item);
4799+ item = new MockLauncherItem("camera-app2", "/usr/share/applications/camera-app2.desktop", "Camera2", "camera", this);
4800+ item->setPinned(true);
4801+ m_list.append(item);
4802 item = new MockLauncherItem("gallery-app", "/usr/share/applications/gallery-app.desktop", "Gallery", "gallery", this);
4803 item->setProgress(50);
4804 item->setCountVisible(true);
4805
4806=== modified file 'tests/mocks/Utils/CMakeLists.txt'
4807--- tests/mocks/Utils/CMakeLists.txt 2016-02-08 09:37:48 +0000
4808+++ tests/mocks/Utils/CMakeLists.txt 2016-03-11 13:51:30 +0000
4809@@ -18,6 +18,7 @@
4810 ${CMAKE_SOURCE_DIR}/plugins/Utils/inputwatcher.cpp
4811 ${CMAKE_SOURCE_DIR}/plugins/Utils/applicationsfiltermodel.cpp
4812 ${CMAKE_SOURCE_DIR}/plugins/Utils/inputeventgenerator.cpp
4813+ ${CMAKE_SOURCE_DIR}/plugins/Utils/deviceconfigparser.cpp
4814 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
4815 constants.cpp
4816 plugin.cpp
4817
4818=== modified file 'tests/mocks/Utils/plugin.cpp'
4819--- tests/mocks/Utils/plugin.cpp 2016-01-13 17:52:51 +0000
4820+++ tests/mocks/Utils/plugin.cpp 2016-03-11 13:51:30 +0000
4821@@ -37,6 +37,7 @@
4822 #include <easingcurve.h>
4823 #include <applicationsfiltermodel.h>
4824 #include <inputeventgenerator.h>
4825+#include <deviceconfigparser.h>
4826
4827 static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
4828 {
4829@@ -67,6 +68,7 @@
4830 qmlRegisterType<ActiveFocusLogger>(uri, 0, 1, "ActiveFocusLogger");
4831 qmlRegisterType<ApplicationsFilterModel>(uri, 0, 1, "ApplicationsFilterModel");
4832 qmlRegisterType<InputEventGenerator>(uri, 0, 1, "InputEventGenerator");
4833+ qmlRegisterType<DeviceConfigParser>(uri, 0, 1, "DeviceConfigParser");
4834 }
4835
4836 void FakeUtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
4837
4838=== modified file 'tests/plugins/AccountsService/CMakeLists.txt'
4839--- tests/plugins/AccountsService/CMakeLists.txt 2015-04-29 22:05:49 +0000
4840+++ tests/plugins/AccountsService/CMakeLists.txt 2016-03-11 13:51:30 +0000
4841@@ -10,11 +10,13 @@
4842 endmacro(make_dbus_class)
4843
4844 make_dbus_class(Accounts org.freedesktop.Accounts)
4845+make_dbus_class(Input com.ubuntu.AccountsService.Input)
4846 make_dbus_class(Properties org.freedesktop.DBus.Properties)
4847 make_dbus_class(SecurityPrivacy com.ubuntu.touch.AccountsService.SecurityPrivacy)
4848 make_dbus_class(Location com.ubuntu.location.providers.here.AccountsService)
4849 make_dbus_class(AccountsUser org.freedesktop.Accounts.User)
4850 make_dbus_class(AccountsPrivate com.canonical.unity.AccountsService.Private)
4851+make_dbus_class(UscInput com.canonical.Unity.Input)
4852
4853 include_directories(
4854 ${CMAKE_CURRENT_BINARY_DIR}
4855@@ -27,12 +29,15 @@
4856 ${CMAKE_CURRENT_BINARY_DIR}/AccountsAdaptor.cpp
4857 ${CMAKE_CURRENT_BINARY_DIR}/AccountsPrivateAdaptor.cpp
4858 ${CMAKE_CURRENT_BINARY_DIR}/AccountsUserAdaptor.cpp
4859+ ${CMAKE_CURRENT_BINARY_DIR}/InputAdaptor.cpp
4860 ${CMAKE_CURRENT_BINARY_DIR}/PropertiesAdaptor.cpp
4861 ${CMAKE_CURRENT_BINARY_DIR}/LocationAdaptor.cpp
4862 ${CMAKE_CURRENT_BINARY_DIR}/SecurityPrivacyAdaptor.cpp
4863+ ${CMAKE_CURRENT_BINARY_DIR}/UscInputAdaptor.cpp
4864 server.cpp
4865 AccountsServer.cpp
4866 PropertiesServer.cpp
4867+ UscServer.cpp
4868 )
4869 qt5_use_modules(mock-server Core DBus)
4870
4871
4872=== modified file 'tests/plugins/AccountsService/PropertiesServer.cpp'
4873--- tests/plugins/AccountsService/PropertiesServer.cpp 2015-10-26 14:05:14 +0000
4874+++ tests/plugins/AccountsService/PropertiesServer.cpp 2016-03-11 13:51:30 +0000
4875@@ -32,9 +32,9 @@
4876 Reset();
4877 }
4878
4879-QDBusVariant PropertiesServer::Get(const QString &interface, const QString &property)
4880+QDBusVariant PropertiesServer::Get(const QString &interface, const QString &property) const
4881 {
4882- if (m_properties[interface].contains(property)) {
4883+ if (m_properties.contains(interface) && m_properties[interface].contains(property)) {
4884 return QDBusVariant(m_properties[interface][property]);
4885 } else {
4886 sendErrorReply(QDBusError::InvalidArgs, "Bad interface or property");
4887@@ -42,6 +42,16 @@
4888 }
4889 }
4890
4891+QVariantMap PropertiesServer::GetAll(const QString &interface) const
4892+{
4893+ if (m_properties.contains(interface)) {
4894+ return m_properties[interface];
4895+ } else {
4896+ sendErrorReply(QDBusError::InvalidArgs, "Bad interface");
4897+ return QVariantMap();
4898+ }
4899+}
4900+
4901 void PropertiesServer::Set(const QString &interface, const QString &property, const QDBusVariant &variant)
4902 {
4903 QVariant newValue = variant.variant();
4904@@ -57,8 +67,8 @@
4905
4906 oldValue = newValue;
4907
4908- // Special case for Background file.
4909- if (interface == "org.freedesktop.Accounts.User" && property == "BackgroundFile") {
4910+ // Special case for user properties.
4911+ if (interface == "org.freedesktop.Accounts.User") {
4912 Q_EMIT Changed();
4913 } else {
4914 QVariantMap propertyChanges;
4915@@ -82,10 +92,12 @@
4916 m_properties["com.canonical.unity.AccountsService"]["LauncherItems"] = QVariant::fromValue(QList<QVariantMap>());
4917 m_properties["com.canonical.unity.AccountsService.Private"]["FailedLogins"] = 0;
4918 m_properties["com.ubuntu.touch.AccountsService.SecurityPrivacy"]["StatsWelcomeScreen"] = true;
4919+ m_properties["com.ubuntu.AccountsService.Input"]["MousePrimaryButton"] = "right";
4920 m_properties["com.ubuntu.AccountsService.SecurityPrivacy"]["EnableLauncherWhileLocked"] = true;
4921 m_properties["com.ubuntu.AccountsService.SecurityPrivacy"]["EnableIndicatorsWhileLocked"] = true;
4922 m_properties["com.ubuntu.AccountsService.SecurityPrivacy"]["PasswordDisplayHint"] = AccountsService::Keyboard;
4923 m_properties["com.ubuntu.location.providers.here.AccountsService"]["LicenseAccepted"] = false;
4924 m_properties["com.ubuntu.location.providers.here.AccountsService"]["LicenseBasePath"] = "";
4925 m_properties["org.freedesktop.Accounts.User"]["BackgroundFile"] = "";
4926+ m_properties["org.freedesktop.Accounts.User"]["RealName"] = "";
4927 }
4928
4929=== modified file 'tests/plugins/AccountsService/PropertiesServer.h'
4930--- tests/plugins/AccountsService/PropertiesServer.h 2015-04-17 16:39:43 +0000
4931+++ tests/plugins/AccountsService/PropertiesServer.h 2016-03-11 13:51:30 +0000
4932@@ -34,7 +34,8 @@
4933 explicit PropertiesServer(QObject *parent = 0);
4934
4935 public Q_SLOTS:
4936- QDBusVariant Get(const QString &interface, const QString &property);
4937+ QDBusVariant Get(const QString &interface, const QString &property) const;
4938+ QVariantMap GetAll(const QString &interface) const;
4939 void Set(const QString &interface, const QString &property, const QDBusVariant &variant);
4940
4941 // mock only.
4942
4943=== added file 'tests/plugins/AccountsService/UscServer.cpp'
4944--- tests/plugins/AccountsService/UscServer.cpp 1970-01-01 00:00:00 +0000
4945+++ tests/plugins/AccountsService/UscServer.cpp 2016-03-11 13:51:30 +0000
4946@@ -0,0 +1,28 @@
4947+/*
4948+ * Copyright 2016 Canonical Ltd.
4949+ *
4950+ * This program is free software: you can redistribute it and/or modify it
4951+ * under the terms of the GNU General Public License version 3, as published
4952+ * by the Free Software Foundation.
4953+ *
4954+ * This program is distributed in the hope that it will be useful, but
4955+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4956+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
4957+ * PURPOSE. See the GNU General Public License for more details.
4958+ *
4959+ * You should have received a copy of the GNU General Public License
4960+ * version 3 along with this program. If not, see
4961+ * <http://www.gnu.org/licenses/>
4962+ */
4963+
4964+#include "UscServer.h"
4965+
4966+UscServer::UscServer(QObject *parent)
4967+ : QObject(parent)
4968+{
4969+}
4970+
4971+void UscServer::setMousePrimaryButton(int button)
4972+{
4973+ Q_EMIT setMousePrimaryButtonCalled(button);
4974+}
4975
4976=== added file 'tests/plugins/AccountsService/UscServer.h'
4977--- tests/plugins/AccountsService/UscServer.h 1970-01-01 00:00:00 +0000
4978+++ tests/plugins/AccountsService/UscServer.h 2016-03-11 13:51:30 +0000
4979@@ -0,0 +1,39 @@
4980+/*
4981+ * Copyright 2016 Canonical Ltd.
4982+ *
4983+ * This program is free software: you can redistribute it and/or modify it
4984+ * under the terms of the GNU General Public License version 3, as published
4985+ * by the Free Software Foundation.
4986+ *
4987+ * This program is distributed in the hope that it will be useful, but
4988+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4989+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
4990+ * PURPOSE. See the GNU General Public License for more details.
4991+ *
4992+ * You should have received a copy of the GNU General Public License
4993+ * version 3 along with this program. If not, see
4994+ * <http://www.gnu.org/licenses/>
4995+ */
4996+
4997+#ifndef UNITY_USCSERVER_H
4998+#define UNITY_USCSERVER_H
4999+
5000+#include <QDBusContext>
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches