on xenial help sign in
1564 files changed+141942−100913
since splitsnapshots
unifiedsplit
.bazaar/Makefile−6 .bazaar/plugins/makecheck_unity_phablet.py−51 .bzr-builddeb/default.conf−2 .bzrignore−7 .crossbuilder/post_deploy+1 .gitignore+7 CMakeLists.txt+59−14 CODING+46−59 Jenkinsfile+2 README.md+31 build.sh+22−37 clickable.yaml+153 cmake/modules/QmlPlugins.cmake−148 cmake/modules/QmlTest.cmake+189−13 data/51-unity8-greeter.conf+2 data/CMakeLists.txt+9−6 data/com.canonical.Unity.gschema.xml+255 data/com.canonical.Unity8.gschema.xml+39−3 data/devices.conf+30 data/test.sensors+12 data/unity8-dash.conf−24 data/unity8-dash.desktop.in−10 data/unity8-dash.png data/unity8-dash.svg−326 data/unity8-dash.url-dispatcher−6 data/unity8-filewatcher.conf+5 data/unity8-greeter-init.conf+12 data/unity8-greeter-wrapper+109 data/unity8-greeter.desktop.in+7 data/unity8-greeter.pkla+44 data/unity8.conf+57−26 debian/bileto_pre_release_hook+5 debian/changelog+1731−19 debian/control+224−160 debian/rules+23−8 debian/shlibs.local+1 debian/source/format−1 debian/tests/autopilot.sh+13 debian/tests/control+9−3 debian/tests/qmluitests.sh+6−14 debian/unity-scope-tool.install−2 debian/unity8-common.install−2 debian/unity8-common.udev+2 debian/unity8-doc.install+1 debian/unity8-greeter.install+5 debian/unity8-private.install+4−4 debian/unity8-schemas.install+1 debian/unity8-fake-env.install → debian/unity8-tests.install+4−1 debian/unity8-tests.lintian-overrides+1 debian/unity8.install+8−9 doc/devices.conf+45 include/paths.h.in+59−25 libs/CMakeLists.txt−1 libs/UbuntuGestures/CMakeLists.txt−41 libs/UbuntuGestures/CandidateInactivityTimer.cpp−46 libs/UbuntuGestures/CandidateInactivityTimer.h−51 libs/UbuntuGestures/DebugHelpers.cpp−95 libs/UbuntuGestures/DebugHelpers.h−31 libs/UbuntuGestures/Pool.h−124 libs/UbuntuGestures/TimeSource.cpp−49 libs/UbuntuGestures/TimeSource.h−64 libs/UbuntuGestures/Timer.cpp−152 libs/UbuntuGestures/Timer.h−117 libs/UbuntuGestures/TouchOwnershipEvent.h−50 libs/UbuntuGestures/TouchRegistry.cpp−548 libs/UbuntuGestures/TouchRegistry.h−201 libs/UbuntuGestures/UnownedTouchEvent.h−45 plugins/AccountsService/AccountsService.cpp+268−283 plugins/AccountsService/AccountsService.h+60−38 plugins/AccountsService/AccountsService.qmltypes−36 plugins/AccountsService/AccountsServiceDBusAdaptor.cpp+23−6 plugins/AccountsService/AccountsServiceDBusAdaptor.h+5−6 plugins/AccountsService/CMakeLists.txt+5−1 plugins/AccountsService/com.canonical.unity.AccountsService.xml+15 plugins/CMakeLists.txt+5−4 plugins/Cursor/CMakeLists.txt+8−4 plugins/Cursor/Cursor.qml+40−6 plugins/Cursor/CursorImageInfo.cpp+115 plugins/Cursor/CursorImageInfo.h+82 plugins/Cursor/CursorImageProvider.cpp+86−41 plugins/Cursor/CursorImageProvider.h+20−9 plugins/Cursor/MousePointer.cpp+130−39 plugins/Cursor/MousePointer.h+33−7 plugins/Cursor/plugin.cpp+4−2 plugins/Cursor/qmldir+1−1 plugins/Dash/CMakeLists.txt−40 plugins/Dash/CardAttributes.qml−71 plugins/Dash/CardCreator.js−711 plugins/Dash/CardCreatorCache.qml−40 plugins/Dash/CroppedImageMinimumSourceSize.qml−38 plugins/Dash/Dash.qmltypes−100 plugins/Dash/ScopeStyle.qml−95 plugins/Dash/abstractdashview.cpp−346 plugins/Dash/abstractdashview.h−129 plugins/Dash/horizontaljournal.cpp−242 plugins/Dash/horizontaljournal.h−63 plugins/Dash/listviewwithpageheader.cpp−1341 plugins/Dash/listviewwithpageheader.h−215 plugins/Dash/organicgrid.cpp−260 plugins/Dash/organicgrid.h−91 plugins/Dash/plugin.cpp−35 plugins/Dash/qmldir−7 plugins/Dash/verticaljournal.cpp−273 plugins/Dash/verticaljournal.h−100 plugins/GlobalShortcut/CMakeLists.txt+1−1 plugins/GlobalShortcut/globalshortcut.cpp+15−4 plugins/GlobalShortcut/globalshortcut.h+5 plugins/GlobalShortcut/globalshortcutregistry.cpp+18−8 plugins/Greeter/Unity/Launcher/CMakeLists.txt+1−3 plugins/Greeter/Unity/Launcher/Launcher.qmltypes−182 plugins/Greeter/Unity/Launcher/launcheritem.cpp+33 plugins/Greeter/Unity/Launcher/launcheritem.h+7−1 plugins/Greeter/Unity/Launcher/launchermodelas.cpp+2−7 plugins/Greeter/Unity/Launcher/launchermodelas.h−1 plugins/Greeter/Unity/Launcher/quicklistmodel.cpp+2 plugins/IntegratedLightDM/CMakeLists.txt−40 plugins/IntegratedLightDM/Greeter.cpp−138 plugins/IntegratedLightDM/IntegratedLightDM.qmltypes−251 plugins/IntegratedLightDM/UsersModel.cpp−71 plugins/IntegratedLightDM/liblightdm/CMakeLists.txt−37 plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp−42 plugins/LightDM/CMakeLists.txt+26 plugins/IntegratedLightDM/DBusGreeter.cpp → plugins/LightDM/DBusGreeter.cpp+5−4 plugins/IntegratedLightDM/DBusGreeter.h → plugins/LightDM/DBusGreeter.h plugins/IntegratedLightDM/DBusGreeterList.cpp → plugins/LightDM/DBusGreeterList.cpp+3−3 plugins/IntegratedLightDM/DBusGreeterList.h → plugins/LightDM/DBusGreeterList.h+1−1 plugins/LightDM/FullLightDM/CMakeLists.txt+32 plugins/LightDM/FullLightDM/qmldir+3 plugins/LightDM/Greeter.cpp+279 plugins/IntegratedLightDM/Greeter.h → plugins/LightDM/Greeter.h+21−11 plugins/IntegratedLightDM/GreeterPrivate.h → plugins/LightDM/GreeterPrivate.h+13−7 plugins/LightDM/IntegratedLightDM/CMakeLists.txt+33 tests/mocks/IntegratedLightDM/QLightDM/Greeter → plugins/LightDM/IntegratedLightDM/QLightDM/Greeter+1−1 qml/Components/Circle.qml → plugins/LightDM/IntegratedLightDM/QLightDM/SessionsModel+2−7 tests/mocks/IntegratedLightDM/QLightDM/UsersModel → plugins/LightDM/IntegratedLightDM/QLightDM/UsersModel+1−1 plugins/LightDM/IntegratedLightDM/liblightdm/CMakeLists.txt+54 plugins/IntegratedLightDM/liblightdm/Greeter.cpp → plugins/LightDM/IntegratedLightDM/liblightdm/Greeter.cpp+6−8 plugins/IntegratedLightDM/liblightdm/Greeter.h → plugins/LightDM/IntegratedLightDM/liblightdm/Greeter.h+2−4 plugins/IntegratedLightDM/liblightdm/GreeterPrivate.cpp → plugins/LightDM/IntegratedLightDM/liblightdm/GreeterPrivate.cpp+28−24 plugins/IntegratedLightDM/liblightdm/GreeterPrivate.h → plugins/LightDM/IntegratedLightDM/liblightdm/GreeterPrivate.h+1 plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModel.cpp+87 plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModel.h+72 plugins/Utils/windowscreenshotprovider.h → plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModelPrivate.cpp+15−10 plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModelPrivate.h+54 plugins/IntegratedLightDM/liblightdm/UsersModel.cpp → plugins/LightDM/IntegratedLightDM/liblightdm/UsersModel.cpp+8−21 plugins/IntegratedLightDM/liblightdm/UsersModel.h → plugins/LightDM/IntegratedLightDM/liblightdm/UsersModel.h+4−4 plugins/LightDM/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp+94 plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h → plugins/LightDM/IntegratedLightDM/liblightdm/UsersModelPrivate.h+17−4 plugins/LightDM/IntegratedLightDM/qmldir+3 plugins/LightDM/PromptsModel.cpp+97 plugins/LightDM/PromptsModel.h+70 plugins/LightDM/SessionsModel.cpp+135 plugins/LightDM/SessionsModel.h+66 plugins/LightDM/UsersModel.cpp+238 plugins/IntegratedLightDM/UsersModel.h → plugins/LightDM/UsersModel.h+6−8 plugins/IntegratedLightDM/plugin.cpp → plugins/LightDM/plugin.cpp+37−7 plugins/IntegratedLightDM/plugin.h → plugins/LightDM/plugin.h+5−5 plugins/IntegratedLightDM/qmldir → plugins/LightDM/qmldir plugins/Lights/CMakeLists.txt+9−2 plugins/Lights/HfdLights.cpp+62 tests/mocks/Unity/DashCommunicator/plugin.h → plugins/Lights/HfdLights.h+17−9 plugins/Lights/LegacyLights.cpp+91 plugins/Unity/DashCommunicator/plugin.h → plugins/Lights/LegacyLights.h+19−8 plugins/Lights/Lights.cpp−65 plugins/Lights/Lights.h+5−9 plugins/Lights/Lights.qmltypes−45 plugins/Lights/android-hardware.h−4 plugins/Lights/plugin.cpp+20−1 plugins/Powerd/CMakeLists.txt+4−4 plugins/Powerd/Powerd.h+2−2 plugins/Powerd/Powerd.qmltypes−39 plugins/ScreenGrabber/CMakeLists.txt−13 plugins/ScreenGrabber/qmldir−3 plugins/ScreenGrabber/screengrabber.cpp−117 plugins/ScreenshotDirectory/CMakeLists.txt+9 plugins/ScreenGrabber/ScreenGrabber.qmltypes → plugins/ScreenshotDirectory/ScreenGrabber.qmltypes plugins/ScreenshotDirectory/ScreenshotDirectory.cpp+64 plugins/ScreenshotDirectory/ScreenshotDirectory.h+39 plugins/ScreenGrabber/plugin.cpp → plugins/ScreenshotDirectory/plugin.cpp+5−7 plugins/ScreenGrabber/plugin.h → plugins/ScreenshotDirectory/plugin.h+5−7 plugins/ScreenshotDirectory/qmldir+2 plugins/SessionBroadcast/CMakeLists.txt+5−1 plugins/SessionBroadcast/SessionBroadcast.cpp+40−10 plugins/SessionBroadcast/SessionBroadcast.h+13−3 plugins/SessionBroadcast/SessionBroadcast.qmltypes−19 plugins/UInput/CMakeLists.txt+7 plugins/UInput/plugin.cpp+26 plugins/Dash/plugin.h → plugins/UInput/plugin.h+4−5 plugins/UInput/qmldir+3 plugins/UInput/uinput.cpp+182 plugins/UInput/uinput.h+61 plugins/Ubuntu/CMakeLists.txt−2 plugins/Ubuntu/DownloadDaemonListener/CMakeLists.txt+6−3 plugins/Ubuntu/DownloadDaemonListener/DownloadDaemonListener.qmltypes−60 plugins/Ubuntu/DownloadDaemonListener/DownloadTracker.cpp+2−1 plugins/Ubuntu/DownloadDaemonListener/DownloadTracker.h+2−1 plugins/Ubuntu/DownloadDaemonListener/interface/downloadtrackeradaptor.cpp+2−2 plugins/Ubuntu/DownloadDaemonListener/interface/downloadtrackeradaptor.h+71−4 plugins/Ubuntu/DownloadDaemonListener/interface/metatypes.h+3−6 plugins/Ubuntu/Gestures/AxisVelocityCalculator.cpp+1−1 plugins/Ubuntu/Gestures/AxisVelocityCalculator.h+4−4 plugins/Ubuntu/Gestures/CMakeLists.txt+12−8 plugins/Ubuntu/Gestures/Damper.h−89 plugins/Ubuntu/Gestures/Direction.h+2−1 plugins/Ubuntu/Gestures/DirectionalDragArea.cpp−888 plugins/Ubuntu/Gestures/DirectionalDragArea.h−135 plugins/Ubuntu/Gestures/DirectionalDragArea_p.h−167 plugins/Ubuntu/Gestures/FloatingFlickable.cpp−150 plugins/Ubuntu/Gestures/FloatingFlickable.h−86 plugins/Ubuntu/Gestures/Gestures.qmltypes−168 plugins/Ubuntu/Gestures/MouseEventGenerator.cpp+64 plugins/Ubuntu/Gestures/MouseEventGenerator.h+48 plugins/Ubuntu/Gestures/PressedOutsideNotifier.h+1−1 plugins/Ubuntu/Gestures/TouchDispatcher.cpp+1−5 plugins/Ubuntu/Gestures/TouchGate.cpp+10−5 plugins/Ubuntu/Gestures/TouchGate.h+3−2 plugins/Ubuntu/Gestures/TouchGestureArea.cpp+879 plugins/Ubuntu/Gestures/TouchGestureArea.h+229 plugins/Ubuntu/Gestures/plugin.cpp+6−5 plugins/Ubuntu/Payments/CMakeLists.txt−20 plugins/Ubuntu/Payments/Payments.cpp−136 plugins/Ubuntu/Payments/Payments.h−69 plugins/Ubuntu/Payments/Payments.qmltypes−43 plugins/Ubuntu/Payments/qmldir−3 plugins/Ubuntu/SystemImage/CMakeLists.txt−10 plugins/Ubuntu/SystemImage/SystemImage.cpp−33 plugins/Ubuntu/SystemImage/SystemImage.qmltypes−19 plugins/Ubuntu/SystemImage/qmldir−3 plugins/Unity/ApplicationMenu/CMakeLists.txt+19 plugins/Unity/ApplicationMenu/applicationmenuregistry.cpp+141 plugins/Unity/ApplicationMenu/applicationmenuregistry.h+83 plugins/Unity/ApplicationMenu/com.ubuntu.MenuRegistrar.xml+83 plugins/Unity/ApplicationMenu/dbusapplicationmenuregistry.cpp+44 plugins/Unity/ApplicationMenu/dbusapplicationmenuregistry.h+34 plugins/Unity/ApplicationMenu/plugin.cpp+42 plugins/Ubuntu/SystemImage/plugin.h → plugins/Unity/ApplicationMenu/plugin.h+6−5 plugins/Unity/ApplicationMenu/qmldir+3 plugins/Unity/CMakeLists.txt+1−1 plugins/Unity/Connectivity/CMakeLists.txt+1−1 plugins/Unity/Connectivity/Connectivity.qmltypes−19 plugins/Unity/DashCommunicator/CMakeLists.txt−25 plugins/Unity/DashCommunicator/DashCommunicator.qmltypes−47 plugins/Unity/DashCommunicator/dashcommunicator.cpp−52 plugins/Unity/DashCommunicator/dashconnection.cpp−63 plugins/Unity/DashCommunicator/dashconnection.h−37 plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp−35 plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h−39 plugins/Unity/DashCommunicator/qmldir−3 plugins/Unity/Indicators/CMakeLists.txt+8−6 plugins/Unity/Indicators/Indicators.qmltypes−264 plugins/Unity/Indicators/actionrootstate.cpp+1−1 plugins/Unity/Indicators/indicators.h+5−5 plugins/Unity/Indicators/indicatorsmanager.cpp+6−13 plugins/Unity/Indicators/indicatorsmanager.h−2 plugins/Unity/Indicators/indicatorsmodel.cpp+13 plugins/Unity/Indicators/indicatorsmodel.h+9−1 plugins/Unity/Indicators/modelactionrootstate.cpp+76−1 plugins/Unity/Indicators/modelactionrootstate.h+15−4 plugins/Unity/Indicators/modelprinter.cpp+19−4 plugins/Unity/Indicators/modelprinter.h+2−1 plugins/Unity/Indicators/rootstateparser.h+1 plugins/Unity/Indicators/sharedunitymenumodel.cpp+4 plugins/Unity/InputInfo/CMakeLists.txt+1−2 plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux.cpp+10−2 plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux_p.h−2 plugins/Unity/InputInfo/plugin.h+1−1 plugins/Unity/InputInfo/qdeclarativeinputdevicemodel_p.h+3−3 plugins/Unity/InputInfo/qinputinfo.h+2−3 plugins/Unity/Launcher/CMakeLists.txt+18−5 plugins/Unity/Launcher/Launcher.qmltypes−182 plugins/Unity/Launcher/appdrawermodel.cpp+192 plugins/Unity/Launcher/appdrawermodel.h+64 plugins/Unity/Launcher/asadapter.cpp+6−2 plugins/Unity/Launcher/desktopfilehandler.cpp−155 plugins/Unity/Launcher/desktopfilehandler.h−56 plugins/Unity/Launcher/launcheritem.cpp+65−9 plugins/Unity/Launcher/launcheritem.h+12−1 plugins/Unity/Launcher/launchermodel.cpp+128−59 plugins/Unity/Launcher/launchermodel.h+7−10 plugins/Unity/Launcher/plugin.cpp+2−1 plugins/Unity/Launcher/quicklistentry.cpp+22 plugins/Unity/Launcher/quicklistentry.h+8 plugins/Unity/Launcher/quicklistmodel.cpp+11 plugins/Unity/Launcher/quicklistmodel.h+1 plugins/Unity/Launcher/ualwrapper.cpp+74 plugins/Unity/Launcher/ualwrapper.h+36 plugins/Unity/Launcher/xdgwatcher.cpp+129 plugins/Unity/Launcher/xdgwatcher.h+46 plugins/Unity/Platform/CMakeLists.txt+1−1 plugins/Unity/Platform/platform.cpp+16−2 plugins/Unity/Session/CMakeLists.txt+5−3 plugins/Unity/Session/Session.qmltypes−85 plugins/Unity/Session/dbusunitysessionservice.cpp+139−28 plugins/Unity/Session/dbusunitysessionservice.h+25−4 plugins/Unity/Session/plugin.cpp+1 plugins/Utils/CMakeLists.txt+21−9 plugins/Utils/EdgeBarrierSettings.qml+1−1 plugins/Utils/ElapsedTimer.h+1−1 plugins/Utils/HomeKeyWatcher.h−74 plugins/Utils/Timer.cpp+5−2 plugins/Utils/Timer.h+5−6 plugins/Utils/URLDispatcher.cpp+80 plugins/Utils/URLDispatcher.h+47 plugins/Utils/Utils.qmltypes−175 plugins/Utils/HomeKeyWatcher.cpp → plugins/Utils/WindowInputMonitor.cpp+30−20 plugins/Utils/WindowInputMonitor.h+97 plugins/Utils/appdrawerproxymodel.cpp+189 plugins/Utils/appdrawerproxymodel.h+87 plugins/Utils/constants.cpp+6−1 plugins/Utils/constants.h+5−5 plugins/Utils/deviceconfigparser.cpp+176 plugins/Utils/deviceconfigparser.h+66 plugins/Utils/easingcurve.h−1 plugins/Utils/expressionfiltermodel.cpp+49 plugins/Utils/expressionfiltermodel.h+42 plugins/Utils/globalfunctions.cpp+58 plugins/Utils/globalfunctions.h+44 plugins/Utils/inputeventgenerator.cpp+34 plugins/Utils/inputeventgenerator.h+40 plugins/Utils/plugin.cpp+28−13 plugins/Utils/plugin.h−1 plugins/Utils/quicklistproxymodel.cpp+72 plugins/Utils/quicklistproxymodel.h+52 plugins/Utils/tabfocusfence.cpp+72 plugins/Utils/tabfocusfence.h+38 plugins/Utils/timezoneFormatter.cpp+10 plugins/Utils/timezoneFormatter.h+1 plugins/Utils/unitysortfilterproxymodelqml.h+5 plugins/Utils/windowkeysfilter.cpp → plugins/Utils/windowinputfilter.cpp+14−16 plugins/Utils/windowkeysfilter.h → plugins/Utils/windowinputfilter.h+11−11 plugins/Utils/windowscreenshotprovider.cpp−59 plugins/Utils/windowstatestorage.cpp+322−95 plugins/Utils/windowstatestorage.h+37−17 plugins/WindowManager/AvailableDesktopArea.cpp+50 plugins/Unity/DashCommunicator/dashcommunicator.h → plugins/WindowManager/AvailableDesktopArea.h+14−21 plugins/WindowManager/CMakeLists.txt+26 plugins/WindowManager/InputMethodManager.cpp+56 plugins/WindowManager/InputMethodManager.h+55 plugins/WindowManager/TopLevelWindowModel.cpp+782 plugins/WindowManager/TopLevelWindowModel.h+308 plugins/WindowManager/Window.cpp+277 plugins/WindowManager/Window.h+176 libs/UbuntuGestures/UbuntuGesturesGlobal.h → plugins/WindowManager/WindowManagerGlobal.h+4−4 plugins/WindowManager/WindowManagerPlugin.cpp+44 plugins/WindowManager/WindowManagerPlugin.h+32 plugins/WindowManager/WindowMargins.cpp+74 plugins/WindowManager/WindowMargins.h+59 plugins/WindowManager/qmldir+2 plugins/Wizard/CMakeLists.txt+13−1 plugins/Wizard/Changelog.cpp+58 plugins/Wizard/Changelog.h+52 plugins/Wizard/LocalePlugin.cpp+291 plugins/Wizard/LocalePlugin.h+58 plugins/Wizard/PageList.cpp+20−5 plugins/Wizard/Status.cpp+143 plugins/Wizard/Status.h+60 plugins/Wizard/System.cpp+82−10 plugins/Wizard/System.h+24−2 plugins/Wizard/Utils/CMakeLists.txt+1−1 plugins/Wizard/Wizard.qmltypes−33 plugins/Wizard/keyboardLayoutsModel.cpp+163 plugins/Wizard/keyboardLayoutsModel.h+66 plugins/Wizard/plugin.cpp+11−8 plugins/Wizard/plugin.h+1−2 plugins/Wizard/qmldir−1 plugins/Wizard/test.sh−18 plugins/Wizard/timezonemodel.cpp+244 plugins/Wizard/timezonemodel.h+80 po/aa.po+880 po/am.po+1041−432 po/ar.po+946−469 po/ast.po+1044−441 po/az.po+565−343 po/be.po+916−464 po/bg.po+491−328 po/bn.po+848−448 po/br.po+971−435 po/bs.po+875−422 po/ca.po+1093−450 po/ca@valencia.po+745−403 po/ce.po+461−307 po/ckb.po+483−323 po/co.po+1061 po/cs.po+1027−458 po/cy.po+859−410 po/da.po+887−441 po/de.po+1083−442 po/el.po+975−452 po/en_AU.po+1081−436 po/en_GB.po+1035−432 po/en_US.po+814 po/eo.po+594−332 po/es.po+1080−447 po/et.po+816 po/eu.po+868−426 po/fa.po+1090−437 po/fi.po+1071−438 po/fo.po+581−357 po/fr.po+1109−457 po/ga.po+789−342 po/gd.po+1080−447 po/gl.po+1072−439 po/gu.po+814 po/gv.po+530−344 po/he.po+798−440 po/hi.po+477−319 po/hr.po+1089−438 po/hu.po+1072−441 po/hy.po+601−388 po/ia.po+1047−433 po/id.po+608−363 po/is.po+589−360 po/it.po+1080−445 po/ja.po+640−382 po/kk.po+841 po/km.po+705−394 po/kn.po+468−316 po/ko.po+888−427 po/ku.po+569−343 po/ky.po+468−316 po/lo.po+468−314 po/lt.po+714−394 po/lv.po+867−424 po/ml.po+484−325 po/mr.po+488−316 po/ms.po+1008−435 po/my.po+540−333 po/nb.po+1066−441 po/ne.po+834 po/nl.po+1086−457 po/nn.po+461−307 po/oc.po+1046−432 po/or.po+461−307 po/pa.po+850−411 po/pl.po+1081−445 po/pt.po+1080−452 po/pt_BR.po+899−442 po/ro.po+865−428 po/ru.po+1073−451 po/sc.po+904 po/shn.po+462−308 po/si.po+492−331 po/sk.po+1136−446 po/sl.po+1053−428 po/sq.po+732−365 po/sr.po+1054−447 po/sv.po+1063−436 po/sw.po+767−390 po/ta.po+483−324 po/te.po+492−324 po/th.po+478−323 po/tr.po+1071−438 po/ug.po+889−421 po/uk.po+1063−445 po/unity8.pot+458−305 po/update-unity-pot+17 po/ur.po+483−326 po/uz.po+461−307 po/vi.po+461−307 po/wo.po+866−424 po/xh.po+461−307 po/zh_CN.po+1043−427 po/zh_HK.po+511−329 po/zh_TW.po+977−434 qml/ApplicationMenus/ApplicationMenuItemFactory.qml+135 qml/ApplicationMenus/ApplicationMenusLimits.qml+24 qml/ApplicationMenus/MenuBar.qml+513 qml/ApplicationMenus/MenuItem.qml+146 qml/ApplicationMenus/MenuNavigator.qml+101 qml/ApplicationMenus/MenuPopup.qml+510 qml/ApplicationMenus/RegisteredApplicationMenuModel.qml+56 qml/ApplicationMenus/qmldir+1 qml/CMakeLists.txt+2−2 qml/Components/Background.qml+1−1 qml/Components/BaseCarouselDelegate.qml−42 qml/Components/BlurLayer.qml+10−40 qml/Components/BrightnessControl.qml+54 qml/Components/Carousel.qml−336 qml/Components/Dialogs.qml+111−84 qml/Components/DragHandle.qml+44−25 qml/Components/EdgeBarrier.qml+4−1 qml/Components/EdgeBarrierController.qml+3 qml/Components/FadingLabel.qml+42 qml/Components/Flickable.qml+24 qml/Components/FloatingFlickable.qml+63 qml/Dash/Previews/PreviewActionButton.qml → qml/Components/GridView.qml+7−10 qml/Panel/Handle.qml → qml/Components/Handle.qml+3−2 qml/Components/InputMethod.qml+14−53 qml/Components/ScreenGrabber.qml → qml/Components/ItemGrabber.qml+28−18 qml/Components/WindowScreenshot.qml → qml/Components/ItemSnapshot.qml+13−3 qml/Components/KeyboardShortcutsOverlay.qml+336 qml/Components/KeymapSwitcher.qml+102 qml/Components/LazyImage.qml+5−1 qml/Components/ListItems/Header.qml−64 qml/Components/ListItems/ThinDivider.qml−27 qml/Components/ListItems/graphics/ListItemDividerHorizontal@18.png qml/Tutorial/Tick.qml → qml/Components/ListView.qml+7−12 qml/Components/Lockscreen.qml+76−105 qml/Components/MediaServices/MediaServices.qml+386 qml/Components/MediaServices/MediaServicesControls.qml+192 qml/Components/MediaServices/MediaServicesHeader.qml+71 qml/Components/MediaServices/VideoPlayer.qml+155 qml/Components/MediaServices/VideoPlayerControls.qml+158 qml/Components/ModeSwitchWarningDialog.qml+10−4 qml/Components/NotificationAudio.qml+27−9 qml/Components/PanelState/PanelState.qml+11−7 qml/Components/PassphraseLockscreen.qml+5−4 qml/Components/PhysicalKeysMapper.qml+39−5 qml/Components/PinLockscreen.qml+24−2 qml/Components/PinPadButton.qml+17−2 qml/Components/Rating.qml+1 qml/Components/RatingStyle.qml+3 qml/Components/ResponsiveGridView.qml−99 qml/Components/ResponsiveVerticalJournal.qml−81 qml/Components/ScrollCalculator.qml+21−2 qml/Dash/Previews/PreviewSharing.qml → qml/Components/SharingPicker.qml+20−23 qml/Components/ShellDialog.qml+29−4 qml/Components/Showable.qml+23−10 qml/Components/UbuntuShapeForItem.qml−46 qml/Components/Unity8Settings.qml−50 qml/Components/VirtualTouchPad.qml+406 qml/Components/VolumeControl.qml+4−9 qml/Components/Wallpaper.qml+96 qml/Components/WallpaperResolver.qml+34−37 qml/Components/WindowControlButtons.qml+52−39 qml/Components/ZoomableImage.qml+2−2 qml/Components/flickableUtils.js+28 qml/Components/graphics/close@20.png qml/Components/graphics/icon_star_empty@20.png qml/Components/graphics/icon_star_full@20.png qml/Components/graphics/icon_star_half@20.png qml/Components/graphics/icon_star_off@20.png qml/Components/graphics/icon_star_on@20.png qml/Components/graphics/non-selected@18.png qml/Components/graphics/window-close.svg+164−14 qml/Components/graphics/window-maximize.svg+164−12 qml/Components/graphics/window-minimize.svg+164−13 qml/Components/graphics/window-window.svg+41 qml/Dash/CardCarousel.qml−76 qml/Dash/CardGrid.qml−83 qml/Dash/CardHorizontalList.qml−67 qml/Dash/CardTool.qml−246 qml/Dash/CardVerticalJournal.qml−86 qml/Dash/Dash.qml−381 qml/Dash/DashBackground.qml−26 qml/Dash/DashCategoryBase.qml−62 qml/Dash/DashContent.qml−213 qml/Dash/DashContentTabBarStyle.qml−24 qml/Dash/DashNavigation.qml−117 qml/Dash/DashNavigationButton.qml−233 qml/Dash/DashNavigationList.qml−167 qml/Dash/DashPageHeader.qml−443 qml/Dash/DashRenderer.qml−60 qml/Dash/GenericScopeView.qml−814 qml/Dash/PreviewListView.qml−140 qml/Dash/Previews/Preview.qml−115 qml/Dash/Previews/PreviewActionCombo.qml−68 qml/Dash/Previews/PreviewActions.qml−71 qml/Dash/Previews/PreviewAudioPlayback.qml−205 qml/Dash/Previews/PreviewComment.qml−83 qml/Dash/Previews/PreviewCommentInput.qml−73 qml/Dash/Previews/PreviewExpandable.qml−105 qml/Dash/Previews/PreviewHeader.qml−140 qml/Dash/Previews/PreviewIconActions.qml−72 qml/Dash/Previews/PreviewImageGallery.qml−147 qml/Dash/Previews/PreviewOverlay.qml−166 qml/Dash/Previews/PreviewPayments.qml−83 qml/Dash/Previews/PreviewProgress.qml−71 qml/Dash/Previews/PreviewRatingDisplay.qml−67 qml/Dash/Previews/PreviewRatingEdit.qml−80 qml/Dash/Previews/PreviewRatingInput.qml−181 qml/Dash/Previews/PreviewRatingSingleDisplay.qml−70 qml/Dash/Previews/PreviewTable.qml−85 qml/Dash/Previews/PreviewTextSummary.qml−73 qml/Dash/Previews/PreviewVideoPlayback.qml−87 qml/Dash/Previews/PreviewWidget.qml−57 qml/Dash/Previews/PreviewWidgetFactory.qml−92 qml/Dash/Previews/PreviewZoomableImage.qml−97 qml/Dash/Previews/graphics/music_progress_bg.png qml/Dash/ScopeListView.qml−26 qml/Dash/ScopeSettings/ScopeSetting.qml−46 qml/Dash/ScopeSettings/ScopeSettingBoolean.qml−63 qml/Dash/ScopeSettings/ScopeSettingList.qml−50 qml/Dash/ScopeSettings/ScopeSettingString.qml−89 qml/Dash/ScopeSettings/ScopeSettingsWidgetFactory.qml−61 qml/Dash/ScopeSettingsPage.qml−72 qml/Dash/ScopesList.qml−134 qml/Dash/ScopesListCategory.qml−180 qml/Dash/ScopesListCategoryItem.qml−108 qml/Dash/graphics/dark_background.jpg qml/Dash/graphics/dash_divider_top_darkgrad@27.png qml/Dash/graphics/dash_divider_top_lightgrad@27.png qml/Dash/graphics/header_handlearrow2@27.png qml/Dash/graphics/header_handlearrow@27.png qml/Dash/graphics/icon_clear@20.png qml/Dash/graphics/icon_search_active@20.png qml/Dash/graphics/icon_search_inactive@20.png qml/Dash/graphics/navigation_shadow@18.png qml/Dash/graphics/navigation_shadow_light@18.png qml/Dash/graphics/overview_hint@27.png qml/Dash/graphics/pagination_dot_off@30.png qml/Dash/graphics/pagination_dot_on@30.png qml/Dash/graphics/paper_landscape@27.png qml/Dash/graphics/paper_portrait@27.png qml/Dash/graphics/pixel.png qml/Dash/graphics/play_button@18.png qml/Dash/graphics/play_button_active@18.png qml/Dash/graphics/play_button_active_big@20.png qml/Dash/graphics/play_button_big@20.png qml/Dash/graphics/tabbarchevron@27.png qml/Dash/graphics/tablet/icon_close_preview@20.png qml/Dash/graphics/tooltip_arrow@27.png qml/DeviceConfiguration.qml+65−20 qml/DisabledScreenNotice.qml+54−22 qml/Greeter/ButtonPrompt.qml+51 qml/Greeter/Circle.qml+57 qml/Greeter/Clock.qml−2 qml/Greeter/CoverPage.qml+74−20 qml/Components/DelayedLockscreen.qml → qml/Greeter/DelayedLockscreen.qml+6−14 qml/Greeter/FullLightDMImpl.qml+31 qml/Greeter/Greeter.qml+290−117 qml/Greeter/GreeterPrompt.qml+127 qml/Greeter/GreeterView.qml+534 qml/Greeter/Infographics.qml+46−24 qml/Greeter/IntegratedLightDMImpl.qml+4−2 qml/Greeter/LightDM.qml → qml/Greeter/LightDMService.qml+16−3 qml/Dash/Previews/PreviewMediaToolbar.qml → qml/Greeter/LoginAreaContainer.qml+15−13 qml/Greeter/LoginList.qml+147−154 qml/Greeter/NarrowView.qml−171 qml/Greeter/PinPrompt.qml+184 qml/Greeter/PromptList.qml+151 qml/Greeter/SessionIcon.qml+47 qml/Greeter/SessionsList.qml+205 qml/Greeter/ShimGreeter.qml+2 qml/Greeter/TextPrompt.qml+198 qml/Greeter/WideView.qml−135 qml/Greeter/graphics/dot_empty.png qml/Greeter/graphics/dot_filled.png qml/Greeter/graphics/dot_pointer.png qml/Greeter/graphics/icon_arrow.png qml/Greeter/graphics/infographic_circle_back.png qml/Greeter/graphics/session_icons/gnome_badge.png qml/Greeter/graphics/session_icons/kde_badge.png qml/Greeter/graphics/session_icons/recovery_console_badge.png qml/Greeter/graphics/session_icons/ubuntu_badge.png qml/Greeter/graphics/session_icons/unknown_badge.png qml/Greeter/qmldir+1 qml/Launcher/BackgroundBlur.qml+81 qml/Launcher/Drawer.qml+413 qml/Launcher/DrawerGridView.qml+85 qml/Launcher/Launcher.qml+391−81 qml/Launcher/LauncherDelegate.qml+60−33 qml/Launcher/LauncherPanel.qml+390−126 qml/Dash/PullToRefreshScopeStyle.qml → qml/Launcher/PullToRefreshScopeStyle.qml+1 qml/Launcher/Tooltip.qml+72 qml/Launcher/graphics/divider-line.png qml/Launcher/graphics/focused_app_arrow@30.png qml/Launcher/graphics/home.svg+243 qml/Launcher/graphics/home@18.png qml/Launcher/graphics/quicklist_tooltip@30.png qml/Notifications/Notification.qml+168−140 qml/Notifications/NotificationButton.qml+73 qml/Notifications/NotificationMenuItemFactory.qml+5−10 qml/Notifications/Notifications.qml+18−18 qml/Notifications/OptionToggle.qml+12−10 qml/Notifications/ShapedIcon.qml+2 qml/Notifications/SwipeToAct.qml+20−20 qml/Notifications/grip-large.svg−150 qml/OrientedShell.qml+119−29 qml/Panel/ActiveCallHint.qml+3 qml/Panel/FakePanelMenu.qml+26 qml/Panel/IndicatorPage.qml−187 qml/Panel/IndicatorItem.qml → qml/Panel/Indicators/IndicatorItem.qml+73−17 qml/Panel/Indicators/MenuItemFactory.qml → qml/Panel/Indicators/IndicatorMenuItemFactory.qml+220−89 qml/Panel/Indicators/IndicatorsLight.qml+185−12 qml/Panel/Indicators/MessageMenuItemFactory.qml+1−5 qml/Panel/Indicators/ModemInfoItem.qml−111 qml/Panel/Indicators/RoamingIndication.qml−40 qml/Panel/Indicators/client/IndicatorRepresentation.qml+45−28 qml/Panel/Indicators/client/IndicatorsClient.qml+9−3 qml/Panel/Indicators/client/IndicatorsList.qml+19−17 qml/Panel/Indicators/client/IndicatorsTree.qml+6−8 qml/Panel/MenuContent.qml+13−13 qml/Panel/Panel.qml+389−107 qml/Panel/IndicatorsBar.qml → qml/Panel/PanelBar.qml+87−36 qml/Panel/IndicatorItemRow.qml → qml/Panel/PanelItemRow.qml+65−92 qml/Panel/IndicatorsMenu.qml → qml/Panel/PanelMenu.qml+118−60 qml/Panel/PanelMenuPage.qml+226 qml/Panel/graphics/Battery@18.png qml/Panel/graphics/Bluetooth@18.png qml/Panel/graphics/Clock@18.png qml/Panel/graphics/Location@18.png qml/Panel/graphics/Messages@18.png qml/Panel/graphics/Network@18.png qml/Panel/graphics/Sound@18.png qml/Panel/graphics/Sync@18.png qml/Panel/graphics/System@18.png qml/Panel/graphics/Time@18.png qml/Panel/graphics/VerticalDivider@18.png qml/Panel/graphics/handle@12.png qml/Panel/graphics/handle@12.sci−5 qml/Panel/graphics/rectangular_dropshadow@30.png qml/Panel/graphics/search@12.png qml/Panel/graphics/time_and_date@18.png qml/Rotation/HalfLoopRotationAnimation.qml+2−1 qml/Rotation/ImmediateRotationAction.qml+11−22 qml/Rotation/NinetyRotationAnimation.qml+14−16 qml/Rotation/RotationStates.qml+27−16 qml/Rotation/UpdateShellTransformations.qml+42 qml/ScopeTool.qml−173 qml/Shell.qml+554−303 qml/Stages/ApplicationWindow.qml → qml/Stage/ApplicationWindow.qml+179−85 qml/Stage/ChildWindow.qml+203 qml/Stage/ChildWindowRepeater.qml+39 qml/Stage/ChildWindowTree.qml+138 qml/Stage/DecoratedWindow.qml+319 qml/Stage/FakeMaximizeDelegate.qml+233 qml/Stages/MainViewStyle.qml → qml/Stage/MainViewStyle.qml qml/Stage/MoveHandler.qml+201 qml/Stages/OrientationChangeAnimation.qml → qml/Stage/OrientationChangeAnimation.qml+30−6 qml/Stage/PromptSurfaceAnimations.qml+80 qml/Tutorial/Arrow.qml → qml/Stage/ResizeGrip.qml+18−28 qml/Stage/SideStage.qml+121 qml/Stages/Splash.qml → qml/Stage/Splash.qml+22−29 qml/Stage/Spread/BezierCurve.qml+45 qml/Stage/Spread/KeySpline.js+66 qml/Stage/Spread/MathUtils.js+95 qml/Stage/Spread/OpacityMask.qml+82 qml/Stage/Spread/Spread.qml+173 qml/Stage/Spread/SpreadDelegateInputArea.qml+189 qml/Stage/Spread/SpreadMaths.qml+78 qml/Stage/Spread/StagedRightEdgeMaths.qml+174 qml/Stage/Spread/WindowedRightEdgeMaths.qml+96 qml/Stage/Spread/cubic-bezier.js+39 qml/Stage/Stage.qml+2241 qml/Stage/StageMaths.qml+93 qml/Stage/StagedFullscreenPolicy.qml+50 qml/Stage/SurfaceContainer.qml+108 qml/Stage/TabletSideStageTouchGesture.qml+157 qml/Stage/WindowControlsOverlay.qml+254 qml/Stage/WindowDecoration.qml+163 qml/Stage/WindowInfoItem.qml+69 qml/Stages/WindowResizeArea.qml → qml/Stage/WindowResizeArea.qml+112−75 qml/Stage/WindowStateSaver.qml+64 qml/Stage/WindowedFullscreenPolicy.qml+31 qml/Stage/graphics/PageHeaderBaseDividerBottom@18.png qml/Stage/graphics/PageHeaderBaseDividerLight@18.png qml/Stages/graphics/PageHeaderBaseDividerLight@18.sci → qml/Stage/graphics/PageHeaderBaseDividerLight@18.sci qml/Stage/graphics/arrows-centre.png qml/Stage/graphics/arrows.png qml/Stage/graphics/sidestage_drag.svg+207 qml/Stage/graphics/sidestage_handle@20.png qml/Stages/graphics/sidestage_handle@20.sci → qml/Stage/graphics/sidestage_handle@20.sci qml/Stage/graphics/sidestage_open.svg+181 qml/Stages/graphics/window-close.svg → qml/Stage/graphics/window-close.svg qml/Stages/AbstractStage.qml−63 qml/Stages/Animations/BaseSessionAnimation.qml−96 qml/Stages/Animations/SwipeFromBottomAnimation.qml−53 qml/Stages/DecoratedWindow.qml−98 qml/Stages/DesktopSpread.qml−523 qml/Stages/DesktopSpreadDelegate.qml−111 qml/Stages/DesktopStage.qml−517 qml/Stages/PhoneStage.qml−648 qml/Stages/SessionContainer.qml−178 qml/Stages/SpreadDelegate.qml−407 qml/Stages/SpreadMaths.qml−164 qml/Stages/SurfaceContainer.qml−152 qml/Stages/TabletStage.qml−802 qml/Stages/TransformedSpreadDelegate.qml−391 qml/Stages/TransformedTabletSpreadDelegate.qml−403 qml/Stages/WindowDecoration.qml−104 qml/Stages/graphics/PageHeaderBaseDividerBottom@18.png qml/Stages/graphics/PageHeaderBaseDividerLight@18.png qml/Stages/graphics/dropshadow2gu@30.png qml/Stages/graphics/sidestage_handle@20.png qml/Tutorial/InactivityTimer.qml+78 qml/Tutorial/Slider.qml−123 qml/Tutorial/Tutorial.qml+43−16 qml/Tutorial/TutorialBottom.qml−104 qml/Tutorial/TutorialContent.qml+168−61 qml/Tutorial/TutorialLeft.qml+21−68 qml/Tutorial/TutorialLeftLong.qml+56 qml/Tutorial/TutorialPage.qml+63−187 qml/Tutorial/TutorialRight.qml+30−192 qml/Tutorial/TutorialTop.qml+60 qml/Tutorial/graphics/arrow.svg+19 qml/Tutorial/graphics/background1.png qml/Tutorial/graphics/background2.png qml/Tutorial/graphics/camera.png qml/Tutorial/graphics/chevron.png qml/Tutorial/graphics/dialer.png qml/Tutorial/graphics/facebook.png qml/Tutorial/graphics/gallery.png qml/Tutorial/graphics/tick.png qml/Wizard/CheckableSetting.qml+11−3 qml/Wizard/Components/InputMethod.qml+9−9 qml/Wizard/Page.qml+277−45 qml/Wizard/Pages.qml+157−39 qml/Wizard/Pages/10-welcome-update.qml+137 qml/Wizard/Pages/10-welcome.qml+146−48 qml/Wizard/Pages/11-changelog.qml+95 qml/Wizard/Pages/20-keyboard.qml+161 qml/Wizard/Pages/20-sim.qml−77 qml/Wizard/Pages/30-passwd-type.qml−135 qml/Wizard/Pages/30-wifi.qml+219 qml/Wizard/Pages/40-wifi.qml−219 qml/Wizard/Pages/50-location.qml−150 qml/Wizard/Pages/50-timezone.qml+278 qml/Wizard/Pages/60-reporting.qml → qml/Wizard/Pages/60-account.qml+31−19 qml/Wizard/Pages/70-passwd-type.qml+168 qml/Wizard/Pages/78-firmware-update.qml.disabled+246 qml/Wizard/Pages/79-system-update.qml+148 qml/Wizard/Pages/80-finished.qml+96−16 qml/Wizard/Pages/data/Desktop_header_bkg.png qml/Wizard/Pages/data/Desktop_splash_screen_bkg.png qml/Wizard/Pages/data/Phone_header_bkg.png qml/Wizard/Pages/data/Phone_splash_screen_bkg.png qml/Wizard/Pages/data/Tick@30.png qml/Wizard/Pages/data/meet_ubuntu_simcard@30.png qml/Wizard/Pages/data/timezonemap/map.png qml/Wizard/Pages/data/timezonemap/pin.png qml/Wizard/Pages/data/timezonemap/timezone_-1.png qml/Wizard/Pages/data/timezonemap/timezone_-10.png qml/Wizard/Pages/data/timezonemap/timezone_-11.png qml/Wizard/Pages/data/timezonemap/timezone_-2.png qml/Wizard/Pages/data/timezonemap/timezone_-3.5.png qml/Wizard/Pages/data/timezonemap/timezone_-3.png qml/Wizard/Pages/data/timezonemap/timezone_-4.5.png qml/Wizard/Pages/data/timezonemap/timezone_-4.png qml/Wizard/Pages/data/timezonemap/timezone_-5.png qml/Wizard/Pages/data/timezonemap/timezone_-6.png qml/Wizard/Pages/data/timezonemap/timezone_-7.png qml/Wizard/Pages/data/timezonemap/timezone_-8.png qml/Wizard/Pages/data/timezonemap/timezone_-9.5.png qml/Wizard/Pages/data/timezonemap/timezone_-9.png qml/Wizard/Pages/data/timezonemap/timezone_0.png qml/Wizard/Pages/data/timezonemap/timezone_1.png qml/Wizard/Pages/data/timezonemap/timezone_10.5.png qml/Wizard/Pages/data/timezonemap/timezone_10.png qml/Wizard/Pages/data/timezonemap/timezone_11.png qml/Wizard/Pages/data/timezonemap/timezone_12.75.png qml/Wizard/Pages/data/timezonemap/timezone_12.png qml/Wizard/Pages/data/timezonemap/timezone_13.png qml/Wizard/Pages/data/timezonemap/timezone_2.png qml/Wizard/Pages/data/timezonemap/timezone_3.5.png qml/Wizard/Pages/data/timezonemap/timezone_3.png qml/Wizard/Pages/data/timezonemap/timezone_4.5.png qml/Wizard/Pages/data/timezonemap/timezone_4.png qml/Wizard/Pages/data/timezonemap/timezone_5.5.png qml/Wizard/Pages/data/timezonemap/timezone_5.75.png qml/Wizard/Pages/data/timezonemap/timezone_5.png qml/Wizard/Pages/data/timezonemap/timezone_6.5.png qml/Wizard/Pages/data/timezonemap/timezone_6.png qml/Wizard/Pages/data/timezonemap/timezone_7.png qml/Wizard/Pages/data/timezonemap/timezone_8.5.png qml/Wizard/Pages/data/timezonemap/timezone_8.png qml/Wizard/Pages/data/timezonemap/timezone_9.5.png qml/Wizard/Pages/data/timezonemap/timezone_9.png qml/Wizard/Pages/here-terms.qml−121 qml/Wizard/Pages/passwd-confirm.qml → qml/Wizard/Pages/passcode-confirm.qml+15−32 qml/Wizard/Pages/passcode-desktop.qml+159 qml/Wizard/Pages/passwd-set.qml → qml/Wizard/Pages/passcode-set.qml+15−31 qml/Wizard/Pages/password-set.qml+158 qml/Wizard/Pages/sim.qml+108 qml/Wizard/PasswordMeter.qml+108 qml/Wizard/StackButton.qml+7−12 qml/Wizard/Wizard.qml+11−13 qml/Wizard/WizardItemSelector.qml+129 qml/Components/Header.qml → qml/Wizard/WizardTextField.qml+6−8 qml/graphics/12_10_background_wide@12.png qml/graphics/applicationIcons/browser@18.png qml/graphics/applicationIcons/calendar@18.png qml/graphics/applicationIcons/camera@18.png qml/graphics/applicationIcons/contacts-app@18.png qml/graphics/applicationIcons/dash.png qml/graphics/applicationIcons/dialer-app@18.png qml/graphics/applicationIcons/evernote@18.png qml/graphics/applicationIcons/facebook@18.png qml/graphics/applicationIcons/gallery@18.png qml/graphics/applicationIcons/gmail@18.png qml/graphics/applicationIcons/libreoffice@18.png qml/graphics/applicationIcons/map@18.png qml/graphics/applicationIcons/messages-app@18.png qml/graphics/applicationIcons/notepad@18.png qml/graphics/applicationIcons/pinterest@18.png qml/graphics/applicationIcons/soundcloud@18.png qml/graphics/applicationIcons/system-settings@18.png qml/graphics/applicationIcons/twitter@18.png qml/graphics/applicationIcons/weather@18.png qml/graphics/applicationIcons/wikipedia@18.png qml/graphics/applicationIcons/youtube@18.png qml/graphics/avatars/amanda@12.png qml/graphics/avatars/anna_olsson@12.png qml/graphics/avatars/funky@12.png qml/graphics/clock@18.png qml/graphics/dropshadow2gu@30.png qml/Stages/graphics/dropshadow2gu@30.sci → qml/graphics/dropshadow2gu@30.sci qml/graphics/dropshadow_left@20.png qml/graphics/dropshadow_right@20.png qml/graphics/phone_background.jpg qml/graphics/tablet_background.jpg run.sh−70 run_on_device.sh−164 src/ApplicationArguments.h+5 src/CMakeLists.txt+29−16 src/CachingNetworkManagerFactory.cpp+2−2 src/CachingNetworkManagerFactory.h+3−2 src/Dash/CMakeLists.txt−28 src/Dash/main.cpp−121 src/DebuggingController.cpp+92 src/DebuggingController.h+57 src/MouseTouchAdaptor.cpp+254−24 src/MouseTouchAdaptor.h+13−3 src/Panel/CMakeLists.txt−3 src/Panel/Indicators/CMakeLists.txt−1 src/SecondaryWindow.cpp+9 src/ShellApplication.cpp+44−11 src/ShellApplication.h+13−7 src/ShellView.cpp+28−2 src/UnityCommandLineParser.cpp+6 src/UnityCommandLineParser.h+8 tools/unix-signal-handler.cpp → src/UnixSignalHandler.cpp+4−6 tools/unix-signal-handler.h → src/UnixSignalHandler.h src/libunity8-private/CMakeLists.txt+1−1 src/libunity8-private/abstractdbusservicemonitor.h+1−1 src/main.cpp+33−3 src/qmldebuggerutils.h+33 tests/CMakeLists.txt+43−24 tests/autopilot/unity8/dash.py−265 tests/autopilot/unity8/fixture_setup.py+1−1 tests/autopilot/unity8/greeter/__init__.py+1−1 tests/autopilot/unity8/greeter/tests/test_args.py−5 tests/autopilot/unity8/settings_wizard/__init__.py−555 tests/autopilot/unity8/settings_wizard/fixture_setup.py−58 tests/autopilot/unity8/settings_wizard/ofono_helper.py−116 tests/autopilot/unity8/settings_wizard/tests/__init__.py tests/autopilot/unity8/settings_wizard/tests/test_settings_wizard.py−99 tests/autopilot/unity8/shell/__init__.py+2 tests/autopilot/unity8/shell/emulators.py−2 tests/autopilot/unity8/shell/fixture_setup.py+1−27 tests/autopilot/unity8/shell/tests/__init__.py+5−2 tests/autopilot/unity8/shell/tests/test_helpers.py−124 tests/autopilot/unity8/shell/tests/test_notifications.py+10−10 tests/autopilot/unity8/shell/tests/test_rotation.py+3−3 tests/autopilot/unity8/shell/tests/test_tutorial.py−57 tests/autopilot/unity8/tutorial.py−73 tests/copyright/check_copyright.sh+35−4 tests/data/unity/backgrounds/20x30.png tests/data/unity/backgrounds/black.png tests/data/unity/backgrounds/blue.png tests/data/unity/backgrounds/red.png tests/graphics/applicationIcons/browser@18.png tests/graphics/applicationIcons/calendar@18.png tests/graphics/applicationIcons/camera@18.png tests/graphics/applicationIcons/contacts-app@18.png tests/graphics/applicationIcons/dash@18.png tests/graphics/applicationIcons/dialer-app@18.png tests/graphics/applicationIcons/evernote@18.png tests/graphics/applicationIcons/facebook@18.png tests/graphics/applicationIcons/gallery@18.png tests/graphics/applicationIcons/gmail@18.png tests/graphics/applicationIcons/libreoffice@18.png tests/graphics/applicationIcons/map@18.png tests/graphics/applicationIcons/messages-app@18.png tests/graphics/applicationIcons/notepad@18.png tests/graphics/applicationIcons/pinterest@18.png tests/graphics/applicationIcons/soundcloud@18.png tests/graphics/applicationIcons/system-settings@18.png tests/graphics/applicationIcons/twitter@18.png tests/graphics/applicationIcons/weather@18.png tests/graphics/applicationIcons/wikipedia@18.png tests/graphics/applicationIcons/youtube@18.png tests/graphics/avatars/amanda@12.png tests/graphics/avatars/anna_olsson@12.png tests/graphics/avatars/funky@12.png tests/graphics/clock@18.png tests/graphics/screenshots/gallery@12.png tests/imports/CMakeLists.txt+1−1 tests/imports/check_imports.py+58 tests/libs/CMakeLists.txt−1 tests/libs/UbuntuGestures/CMakeLists.txt−16 tests/libs/UbuntuGestures/tst_TouchRegistry.cpp−915 tests/mocks/AccountsService/AccountsService.cpp+85−25 tests/mocks/AccountsService/AccountsService.h+51−30 tests/mocks/AccountsService/AccountsService.qmltypes−36 tests/mocks/AccountsService/CMakeLists.txt+15−2 tests/mocks/Biometryd/CMakeLists.txt+14 libs/UbuntuGestures/TouchOwnershipEvent.cpp → tests/mocks/Biometryd/MockBiometryd.cpp+20−12 tests/mocks/Biometryd/MockBiometryd.h+50 plugins/Ubuntu/Payments/plugin.cpp → tests/mocks/Biometryd/MockDevice.cpp+10−9 tests/mocks/IntegratedLightDM/MockUsersModel.h → tests/mocks/Biometryd/MockDevice.h+16−13 tests/mocks/Biometryd/MockIdentifier.cpp+28 plugins/Ubuntu/SystemImage/SystemImage.h → tests/mocks/Biometryd/MockIdentifier.h+11−9 tests/mocks/Ubuntu/SystemImage/MockSystemImage.cpp → tests/mocks/Biometryd/MockObserver.cpp+3−8 tests/mocks/Ubuntu/SystemImage/MockSystemImage.h → tests/mocks/Biometryd/MockObserver.h+11−10 tests/mocks/Biometryd/MockOperation.cpp+56 plugins/ScreenGrabber/screengrabber.h → tests/mocks/Biometryd/MockOperation.h+18−20 plugins/Ubuntu/SystemImage/plugin.cpp → tests/mocks/Biometryd/plugin.cpp+14−7 plugins/Ubuntu/Payments/plugin.h → tests/mocks/Biometryd/plugin.h+4−4 tests/mocks/Biometryd/qmldir+3 tests/mocks/CMakeLists.txt+19−16 tests/mocks/Cursor/CMakeLists.txt+1−1 tests/mocks/Cursor/Cursor.qml+13−1 tests/mocks/Cursor/qmldir+1−1 tests/mocks/GSettings.1.0/CMakeLists.txt+1−2 tests/mocks/GSettings.1.0/GSettings.qmltypes−42 tests/mocks/GSettings.1.0/fake_gsettings.cpp+243−26 tests/mocks/GSettings.1.0/fake_gsettings.h+79−18 tests/mocks/IntegratedLightDM/CMakeLists.txt−49 tests/mocks/IntegratedLightDM/IntegratedLightDM.qmltypes−269 tests/mocks/IntegratedLightDM/MockGreeter.h−37 tests/mocks/IntegratedLightDM/MockUsersModel.cpp−39 tests/mocks/IntegratedLightDM/liblightdm/CMakeLists.txt−18 tests/mocks/IntegratedLightDM/liblightdm/Greeter.cpp−199 tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp−134 tests/mocks/IntegratedLightDM/plugin.cpp−68 tests/mocks/IntegratedLightDM/qmldir−3 tests/mocks/LightDMController/CMakeLists.txt+14 plugins/Unity/DashCommunicator/plugin.cpp → tests/mocks/LightDMController/plugin.cpp+14−11 tests/mocks/Ubuntu/Payments/plugin.h → tests/mocks/LightDMController/plugin.h+4−6 tests/mocks/LightDMController/qmldir+2 tests/mocks/Lights/CMakeLists.txt+1−1 tests/mocks/Lights/Lights.h+1−1 tests/mocks/Lights/Lights.qmltypes−45 tests/mocks/MeeGo/QOfono/CMakeLists.txt+1−1 tests/mocks/MeeGo/QOfono/MockOfonoSimManager.qml+1 tests/mocks/MeeGo/QOfono/QOfono.qmltypes−30 tests/mocks/Powerd/CMakeLists.txt+1−1 tests/mocks/Powerd/Powerd.h+2−2 tests/mocks/Powerd/Powerd.qmltypes−39 tests/mocks/QMenuModel/CMakeLists.txt+1−2 tests/mocks/QMenuModel/QDBusActionGroup.qml+5−5 tests/mocks/QMenuModel/QMenuModel.qmltypes−111 tests/mocks/QMenuModel/dbus-enums.h+2−3 tests/mocks/QMenuModel/unitymenumodel.cpp+78−13 tests/mocks/QMenuModel/unitymenumodel.h+12−1 tests/mocks/QtMultimedia/CMakeLists.txt+9−2 tests/mocks/QtMultimedia/QtMultimedia.qmltypes−62 tests/mocks/QtMultimedia/VideoSurface.qml+111 tests/mocks/QtMultimedia/audio.cpp−117 tests/mocks/QtMultimedia/audio.h−90 tests/mocks/QtMultimedia/declarativeplaylist.cpp+73 tests/mocks/QtMultimedia/declarativeplaylist.h+54 tests/mocks/QtMultimedia/mediaplayer.cpp+319 tests/mocks/QtMultimedia/mediaplayer.h+224 tests/mocks/QtMultimedia/plugin.cpp+9−3 tests/mocks/QtMultimedia/videooutput.cpp+127 tests/mocks/QtMultimedia/videooutput.h+52 tests/mocks/SessionBroadcast/CMakeLists.txt+8 tests/mocks/Ubuntu/SystemImage/plugin.cpp → tests/mocks/SessionBroadcast/SessionBroadcast.cpp+12−12 tests/mocks/SessionBroadcast/SessionBroadcast.h+39 tests/mocks/IntegratedLightDM/MockGreeter.cpp → tests/mocks/SessionBroadcast/plugin.cpp+10−14 tests/mocks/Unity/fake_unity_plugin.h → tests/mocks/SessionBroadcast/plugin.h+5−7 tests/mocks/SessionBroadcast/qmldir+2 tests/mocks/UInput/CMakeLists.txt+7 tests/mocks/UInput/mockuinput.cpp+73 tests/mocks/UInput/mockuinput.h+63 tests/mocks/UInput/plugin.cpp+26 tests/mocks/IntegratedLightDM/plugin.h → tests/mocks/UInput/plugin.h+4−4 tests/mocks/UInput/qmldir+2 tests/mocks/Ubuntu/CMakeLists.txt−2 tests/mocks/Ubuntu/Connectivity/CMakeLists.txt+1−1 tests/mocks/Ubuntu/Connectivity/networking-status.cpp+7−1 tests/mocks/Ubuntu/Connectivity/networking-status.h+7−6 tests/mocks/Ubuntu/Connectivity/plugin.cpp+1 tests/mocks/Ubuntu/DownloadDaemonListener/CMakeLists.txt+1−1 tests/mocks/Ubuntu/DownloadDaemonListener/DownloadDaemonListener.qmltypes−60 tests/mocks/Ubuntu/DownloadDaemonListener/MockDownloadTracker.cpp+3−1 tests/mocks/Ubuntu/DownloadDaemonListener/MockDownloadTracker.h+2−1 tests/mocks/Ubuntu/Payments/CMakeLists.txt−10 tests/mocks/Ubuntu/Payments/MockPayments.cpp−94 tests/mocks/Ubuntu/Payments/MockPayments.h−62 tests/mocks/Ubuntu/Payments/Payments.qmltypes−44 tests/mocks/Ubuntu/Payments/qmldir−3 tests/mocks/Ubuntu/SystemImage/CMakeLists.txt−10 tests/mocks/Ubuntu/SystemImage/SystemImage.qmltypes−20 tests/mocks/Ubuntu/SystemImage/qmldir−3 tests/mocks/Ubuntu/SystemSettings/CMakeLists.txt+3 tests/mocks/Ubuntu/SystemSettings/Diagnostics/CMakeLists.txt+1 plugins/Ubuntu/Gestures/Damper.cpp → tests/mocks/Ubuntu/SystemSettings/Diagnostics/MockDiagnostics.qml+6−6 tests/mocks/Ubuntu/SystemSettings/Diagnostics/qmldir+2 tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/LanguagePlugin.qmltypes−10 qml/Dash/ScopeSettings/ScopeSettingNumber.qml → tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/MockKeyboardPlugin.qml+3−3 tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/MockLanguagePlugin.qml+3−2 tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/qmldir+1 tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/CMakeLists.txt+1−1 tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.cpp+9−2 tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.h+9−1 tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/SecurityPrivacy.qmltypes−39 tests/mocks/Ubuntu/SystemSettings/TimeDate/CMakeLists.txt+1 tests/mocks/Ubuntu/SystemSettings/TimeDate/MockTimeDate.qml+37 tests/mocks/Ubuntu/SystemSettings/TimeDate/qmldir+2 tests/mocks/Ubuntu/SystemSettings/Update/CMakeLists.txt+1 tests/mocks/Ubuntu/Payments/plugin.cpp → tests/mocks/Ubuntu/SystemSettings/Update/MockSystemImage.qml+11−9 tests/mocks/Ubuntu/SystemSettings/Update/qmldir+2 tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−1 tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.cpp+27 tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.h+22 tests/mocks/Ubuntu/Telephony/Telephony.qmltypes−58 tests/mocks/Ubuntu/Thumbnailer/Thumbnailer.qmltypes−17 tests/mocks/Unity/Application/Application.qmltypes−517 tests/mocks/Unity/Application/ApplicationInfo.cpp+256−101 tests/mocks/Unity/Application/ApplicationInfo.h+55−31 tests/mocks/Unity/Application/ApplicationManager.cpp+209−126 tests/mocks/Unity/Application/ApplicationManager.h+42−30 tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp−79 tests/mocks/Unity/Application/ApplicationScreenshotProvider.h−34 tests/mocks/Unity/Application/ApplicationTestInterface.cpp−117 tests/mocks/Unity/Application/ApplicationTestInterface.h−45 tests/mocks/Unity/Application/CMakeLists.txt+7−9 tests/mocks/Unity/Application/MirMock.cpp+62 tests/mocks/Unity/Application/MirMock.h+43 tests/mocks/Unity/Application/MirSurface.cpp+313−22 tests/mocks/Unity/Application/MirSurface.h+110−12 tests/mocks/Unity/Application/MirSurfaceItem.cpp+143−35 tests/mocks/Unity/Application/MirSurfaceItem.h+25−3 tests/mocks/Unity/Application/MirSurfaceListModel.cpp+136 tests/mocks/Unity/Application/MirSurfaceListModel.h+54 tests/mocks/Unity/Application/ObjectListModel.h+2 tests/mocks/Unity/Application/Session.cpp−174 tests/mocks/Unity/Application/Session.h−94 tests/mocks/Unity/Application/SessionManager.cpp−55 tests/mocks/Unity/Application/SurfaceManager.cpp+242−25 tests/mocks/Unity/Application/SurfaceManager.h+76−11 tests/mocks/Unity/Application/UbuntuKeyboardInfo.cpp−60 tests/mocks/Unity/Application/UbuntuKeyboardInfo.h−66 tests/mocks/Unity/Application/VirtualKeyboard.cpp+27−5 tests/mocks/Unity/Application/VirtualKeyboard.h+4−1 tests/mocks/Unity/Application/plugin.cpp+16−49 tests/mocks/Unity/Application/resources/Kate.qml+49 qml/Tutorial/TutorialLeftFinish.qml → tests/mocks/Unity/Application/resources/KateDialog.qml+25−18 qml/Stages/ShimStage.qml → tests/mocks/Unity/Application/resources/KateMenu.qml+17−20 tests/mocks/Unity/Application/resources/MirSurfaceItem.qml+61−5 tests/mocks/Unity/Application/resources/VirtualKeyboard.qml+1−6 tests/mocks/Unity/Application/resources/screenshots/browser@12.png tests/mocks/Unity/Application/resources/screenshots/camera@12.png tests/mocks/Unity/Application/resources/screenshots/dialer@12.png tests/mocks/Unity/Application/resources/screenshots/facebook@12.png tests/mocks/Unity/Application/resources/screenshots/gallery@12.png tests/mocks/Unity/Application/resources/screenshots/libreoffice@12.png tests/mocks/Unity/Application/resources/screenshots/map@12.png tests/mocks/Unity/Application/resources/screenshots/music@12.png tests/mocks/Unity/Application/resources/screenshots/twitter@12.png tests/mocks/Unity/Application/resources/screenshots/unity8-dash@12.png tests/mocks/Unity/Application/resources/screenshots/vkb_portrait.png tests/mocks/Unity/Application/resources/surfaces.qrc+3 tests/mocks/Unity/Application/resources/vkb_portrait.png tests/mocks/Unity/ApplicationMenu/CMakeLists.txt+18 tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.cpp+47 tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.h+41 tests/mocks/Unity/ApplicationMenu/plugin.cpp+42 tests/mocks/Ubuntu/SystemImage/plugin.h → tests/mocks/Unity/ApplicationMenu/plugin.h+6−5 tests/mocks/Unity/ApplicationMenu/qmldir+3 tests/mocks/Unity/CMakeLists.txt+3−50 tests/mocks/Unity/Connectivity/CMakeLists.txt+1−1 tests/mocks/Unity/Connectivity/Connectivity.qmltypes−20 tests/mocks/Unity/DashCommunicator/CMakeLists.txt−18 tests/mocks/Unity/DashCommunicator/DashCommunicator.qmltypes−46 tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp−42 tests/mocks/Unity/DashCommunicator/dashcommunicator.h−39 tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp−46 tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h−41 tests/mocks/Unity/DashCommunicator/plugin.cpp−31 tests/mocks/Unity/DashCommunicator/qmldir−3 tests/mocks/Unity/Indicators/CMakeLists.txt+5−1 tests/mocks/Unity/Indicators/Indicators.qmltypes−232 tests/mocks/Unity/Indicators/IndicatorsModel.qml+97−14 tests/mocks/Unity/Indicators/ModelActionRootState.qml+33−1 tests/mocks/Unity/Indicators/fakeindicatorsmodel.h−1 tests/mocks/Unity/Indicators/fakeindicatorsmodeldata.js+1328 tests/mocks/Unity/Indicators/fakeplugin.cpp+2 tests/mocks/Unity/InputInfo/CMakeLists.txt+1−1 tests/mocks/Unity/InputInfo/plugin.h+1−1 tests/mocks/Unity/InputInfo/qinputdeviceinfo_mock.cpp+7−3 tests/mocks/Unity/Launcher/CMakeLists.txt+5−3 tests/mocks/Unity/Launcher/Launcher.qmltypes−187 tests/mocks/Unity/Launcher/MockAppDrawerModel.cpp+98 tests/mocks/Unity/Launcher/MockAppDrawerModel.h+43 tests/mocks/Unity/Launcher/MockLauncherItem.cpp+41−1 tests/mocks/Unity/Launcher/MockLauncherItem.h+12 tests/mocks/Unity/Launcher/MockLauncherModel.cpp+14−1 tests/mocks/Unity/Launcher/MockLauncherModel.h+2−2 tests/mocks/Unity/Launcher/MockQuickListModel.cpp+5−1 tests/mocks/Unity/Launcher/MockQuickListModel.h+2 tests/mocks/Unity/Launcher/plugin.cpp+4 tests/mocks/Unity/Notifications/CMakeLists.txt+1−1 tests/mocks/Unity/Notifications/MockActionModel.h+1−1 tests/mocks/Unity/Notifications/MockNotification.cpp+15 tests/mocks/Unity/Notifications/MockNotification.h+7−1 tests/mocks/Unity/Notifications/MockNotificationModel.cpp+10−17 tests/mocks/Unity/Notifications/MockNotificationModel.h+2−4 tests/mocks/Unity/Notifications/Notifications.qmltypes−149 tests/mocks/Unity/Platform/CMakeLists.txt+1 tests/mocks/Unity/Platform/MockPlatform.qml+25 tests/mocks/Unity/Platform/qmldir+2 tests/mocks/Unity/Screens/CMakeLists.txt+14 plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp → tests/mocks/Unity/Screens/plugin.cpp+9−10 tests/mocks/Unity/Application/SessionModel.h → tests/mocks/Unity/Screens/plugin.h+6−16 tests/mocks/Unity/Screens/qmldir+2 tests/mocks/Unity/Screens/screens.cpp+71 tests/mocks/Unity/Screens/screens.h+82 tests/mocks/Unity/Unity.qmltypes−486 tests/mocks/Unity/fake_categories.cpp−158 tests/mocks/Unity/fake_categories.h−54 tests/mocks/Unity/fake_navigation.cpp−124 tests/mocks/Unity/fake_navigation.h−61 tests/mocks/Unity/fake_previewmodel.cpp−95 tests/mocks/Unity/fake_previewmodel.h−58 tests/mocks/Unity/fake_previewstack.cpp−68 tests/mocks/Unity/fake_previewstack.h−52 tests/mocks/Unity/fake_previewwidgetmodel.cpp−89 tests/mocks/Unity/fake_previewwidgetmodel.h−47 tests/mocks/Unity/fake_resultsmodel.cpp−90 tests/mocks/Unity/fake_resultsmodel.h−52 tests/mocks/Unity/fake_scope.cpp−328 tests/mocks/Unity/fake_scope.h−113 tests/mocks/Unity/fake_scopes.cpp−265 tests/mocks/Unity/fake_scopes.h−83 tests/mocks/Unity/fake_scopesoverview.cpp−340 tests/mocks/Unity/fake_scopesoverview.h−117 tests/mocks/Unity/fake_settingsmodel.cpp−95 tests/mocks/Unity/fake_settingsmodel.h−54 tests/mocks/Unity/fake_unity_plugin.cpp−56 tests/mocks/Unity/qmldir−3 tests/mocks/Utils/CMakeLists.txt+27−9 tests/mocks/Utils/URLDispatcher.cpp+38 tests/mocks/Utils/URLDispatcher.h+47 tests/mocks/Utils/Utils.qmltypes−178 tests/mocks/Utils/HomeKeyWatcher.qml → tests/mocks/Utils/WindowInputMonitor.qml+3−1 tests/mocks/Utils/constants.cpp+2−1 tests/mocks/Utils/constants.h+5−5 tests/mocks/Utils/plugin.cpp+29−11 tests/mocks/Utils/plugin.h+1−2 tests/mocks/Utils/qmldir+1−1 tests/mocks/Utils/windowstatestorage.cpp+39−2 tests/mocks/Utils/windowstatestorage.h+32−6 tests/mocks/Wizard/CMakeLists.txt+9−1 tests/mocks/Wizard/MockSystem.cpp+28−3 tests/mocks/Wizard/MockSystem.h+17−3 tests/mocks/Wizard/Wizard.qmltypes−37 tests/mocks/Wizard/mockplugin.cpp+11−8 tests/mocks/indicator-service/CMakeLists.txt−1 tests/mocks/liblightdm/CMakeLists.txt+18 tests/mocks/IntegratedLightDM/liblightdm/GreeterPrivate.cpp → tests/mocks/liblightdm/GreeterPrivate.cpp tests/mocks/IntegratedLightDM/liblightdm/GreeterPrivate.h → tests/mocks/liblightdm/GreeterPrivate.h+1−1 tests/mocks/liblightdm/MockController.cpp+192 tests/mocks/liblightdm/MockController.h+106 tests/mocks/liblightdm/MockGreeter.cpp+316 tests/mocks/IntegratedLightDM/liblightdm/Greeter.h → tests/mocks/liblightdm/MockGreeter.h+10−24 tests/mocks/liblightdm/MockSessionsModel.cpp+118 tests/mocks/liblightdm/MockSessionsModel.h+64 tests/mocks/liblightdm/MockUsersModel.cpp+220 tests/mocks/IntegratedLightDM/liblightdm/UsersModel.h → tests/mocks/liblightdm/MockUsersModel.h+11−19 tests/mocks/liblightdm/SessionsModelPrivate.cpp+83 tests/mocks/liblightdm/SessionsModelPrivate.h+63 tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp → tests/mocks/liblightdm/UsersModelPrivate.cpp+43−23 tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.h → tests/mocks/liblightdm/UsersModelPrivate.h+2−1 tests/mocks/liblightdm/demo/CMakeLists.txt+1−1 tests/mocks/libusermetrics/CMakeLists.txt+2−1 tests/mocks/libusermetrics/ColorTheme.cpp+4 tests/mocks/libusermetrics/UserMetrics.cpp+39−14 tests/mocks/libusermetrics/UserMetrics.h+2 tests/mocks/libusermetrics/libusermetricsoutput/ColorTheme.h−1 tests/mocks/libusermetrics/libusermetricsoutput/UserMetrics.h−1 tests/plugins/AccountsService/CMakeLists.txt+20−8 tests/plugins/AccountsService/PropertiesServer.cpp+56−5 tests/plugins/AccountsService/PropertiesServer.h+9−2 tests/plugins/AccountsService/UscServer.cpp+28 tests/plugins/AccountsService/UscServer.h+39 tests/plugins/AccountsService/client.cpp+161−34 tests/plugins/AccountsService/interfaces.xml+29 tests/plugins/AccountsService/server.cpp+12 tests/plugins/AccountsService/types.h+25 tests/plugins/CMakeLists.txt+5−4 tests/plugins/Cursor/CMakeLists.txt+8 plugins/Unity/DashCommunicator/dashcommunicatorservice.h → tests/plugins/Cursor/TextEntry.qml+18−22 tests/plugins/Cursor/tst_Cursor.qml+151 tests/plugins/Dash/CMakeLists.txt−75 tests/plugins/Dash/cardcreator/1.res−122 tests/plugins/Dash/cardcreator/1.tst−3 tests/plugins/Dash/cardcreator/2.res−132 tests/plugins/Dash/cardcreator/2.tst−3 tests/plugins/Dash/cardcreator/3.res−140 tests/plugins/Dash/cardcreator/3.tst−3 tests/plugins/Dash/cardcreator/4.res−113 tests/plugins/Dash/cardcreator/4.tst−3 tests/plugins/Dash/cardcreator/5.res−159 tests/plugins/Dash/cardcreator/5.tst−3 tests/plugins/Dash/cardcreator/6.res−121 tests/plugins/Dash/cardcreator/6.tst−3 tests/plugins/Dash/cardcreator/7.res−145 tests/plugins/Dash/cardcreator/7.tst−3 tests/plugins/Dash/cardcreator/8.res−103 tests/plugins/Dash/cardcreator/8.tst−3 tests/plugins/Dash/cardcreatortest.cpp−107 tests/plugins/Dash/cardcreatortest.qml−29 tests/plugins/Dash/horizontaljournaltest.cpp−490 tests/plugins/Dash/horizontaljournaltest.qml−44 tests/plugins/Dash/horizontaljournaltry.cpp−89 tests/plugins/Dash/horizontaljournaltry.qml−120 tests/plugins/Dash/listviewwithpageheadersectionexternalmodeltest.cpp−246 tests/plugins/Dash/listviewwithpageheadersectiontest.cpp−2161 tests/plugins/Dash/listviewwithpageheadertest.cpp−1966 tests/plugins/Dash/listviewwithpageheadertest.qml−97 tests/plugins/Dash/listviewwithpageheadertestsection.qml−107 tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qml−75 tests/plugins/Dash/organicgridtest.cpp−533 tests/plugins/Dash/organicgridtest.qml−44 tests/plugins/Dash/organicgridtry.cpp−97 tests/plugins/Dash/organicgridtry.qml−114 tests/plugins/Dash/tst_CardAttributes.qml−57 tests/plugins/Dash/tst_CroppedImageMinimumSourceSize.qml−56 tests/plugins/Dash/tst_ListViewWithPageHeaderQML.qml−138 tests/plugins/Dash/tst_ScopeStyle.qml−188 tests/plugins/Dash/verticaljournaltest.cpp−502 tests/plugins/Dash/verticaljournaltest.qml−45 tests/plugins/Dash/verticaljournaltry.cpp−89 tests/plugins/Dash/verticaljournaltry.qml−121 tests/plugins/GlobalShortcut/CMakeLists.txt+12−7 tests/plugins/GlobalShortcut/GlobalShortcutTest.cpp+3−2 tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt+5−23 tests/plugins/Greeter/Unity/Launcher/launchermodelastest.cpp+4−1 tests/plugins/IntegratedLightDM/CMakeLists.txt−67 tests/plugins/IntegratedLightDM/usersmodel.cpp−84 tests/plugins/LightDM/CMakeLists.txt+1 tests/plugins/LightDM/IntegratedLightDM/CMakeLists.txt+157 tests/plugins/LightDM/IntegratedLightDM/dbus.cpp+23−15 tests/plugins/LightDM/IntegratedLightDM/greeter.qml+2−7 tests/plugins/LightDM/IntegratedLightDM/integrated.cpp+88 tests/plugins/LightDM/IntegratedLightDM/pam.cpp+3−1 tests/plugins/LightDM/IntegratedLightDM/promptsmodel.cpp+175 tests/plugins/LightDM/IntegratedLightDM/sessionsmodel.cpp+134 tests/plugins/LightDM/IntegratedLightDM/usersmodel.cpp+168 tests/plugins/ScreenGrabber/CMakeLists.txt−14 tests/plugins/ScreenGrabber/ScreenGrabberTest.cpp−77 tests/plugins/SessionBroadcast/BroadcastServer.cpp+33 tests/plugins/SessionBroadcast/BroadcastServer.h+40 tests/plugins/SessionBroadcast/CMakeLists.txt+51 tests/plugins/SessionBroadcast/interfaces.xml+18 tests/plugins/SessionBroadcast/server.cpp+37 tests/plugins/SessionBroadcast/sessionbroadcasttest.cpp+111 tests/plugins/Ubuntu/Gestures/CMakeLists.txt+25−11 tests/plugins/Ubuntu/Gestures/DownwardsLauncher.qml−72 tests/plugins/Ubuntu/Gestures/GestureTest.cpp+58−4 tests/plugins/Ubuntu/Gestures/GestureTest.h+17−6 tests/plugins/Ubuntu/Gestures/LeftwardsLauncher.qml−76 tests/plugins/Ubuntu/Gestures/RightwardsLauncher.qml−76 tests/plugins/Ubuntu/Gestures/UpwardsLauncher.qml−76 tests/plugins/Ubuntu/Gestures/tst_AxisVelocityCalculator.cpp+1−1 tests/plugins/Ubuntu/Gestures/tst_Damper.cpp−40 tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp−1306 tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.qml−76 tests/plugins/Ubuntu/Gestures/tst_FloatingFlickable.cpp+28−19 tests/plugins/Ubuntu/Gestures/tst_FloatingFlickable.qml+1 tests/plugins/Ubuntu/Gestures/tst_TouchGate.cpp+17−4 tests/plugins/Ubuntu/Gestures/tst_TouchGestureArea.cpp+300 tests/plugins/Ubuntu/Gestures/tst_TouchGestureArea.qml+90 tests/plugins/Unity/CMakeLists.txt+1 tests/plugins/Unity/Indicators/CMakeLists.txt+12−6 tests/plugins/Unity/Indicators/IndicatorsManagerTest.cpp+1−1 tests/plugins/Unity/Indicators/IndicatorsModelTest.cpp+1−1 tests/plugins/Unity/Indicators/MenuContentActivatorTest.cpp+1 tests/plugins/Unity/Launcher/CMakeLists.txt+59−21 tests/plugins/Unity/Launcher/appdrawermodeltest.cpp+68 tests/plugins/Unity/Launcher/applications/abs-icon.desktop+1 tests/plugins/Unity/Launcher/applications/click-icon.desktop+1 tests/plugins/Unity/Launcher/applications/click-icon.svg tests/plugins/Unity/Launcher/applications/no-name.desktop+1 tests/plugins/Unity/Launcher/applications/rel-icon.desktop+1 tests/plugins/Unity/Launcher/applications/rel-icon.svg tests/plugins/Unity/Launcher/launchermodeltest.cpp+175−30 tests/plugins/Unity/Launcher/no-icon.desktop−2 tests/plugins/Unity/Launcher/ualwrapper.cpp+58 tests/plugins/Unity/Launcher/ualwrapper.h+55 tests/plugins/Unity/Launcher/xdgwatcher.cpp+19−13 tests/plugins/Unity/Launcher/xdgwatcher.h+14−19 tests/plugins/Unity/Platform/CMakeLists.txt+30 tests/plugins/Unity/Platform/platformtest.cpp+142 tests/plugins/Unity/Session/CMakeLists.txt+50−2 tests/plugins/Unity/Session/LightDMServer.cpp+29 tests/plugins/Unity/Session/LightDMServer.h+38 tests/plugins/Unity/Session/LogindServer.cpp+43 tests/plugins/Unity/Session/LogindServer.h+48 tests/plugins/Unity/Session/interfaces.xml+29 tests/plugins/Unity/Session/preload.c+43 tests/plugins/Unity/Session/server.cpp+50 tests/plugins/Unity/Session/sessionbackendtest.cpp+138−19 tests/plugins/Utils/CMakeLists.txt+27−4 tests/plugins/Utils/DeviceConfigParserTest.cpp+76 tests/plugins/Utils/ModelTest.cpp+2−1 tests/plugins/Utils/URLDispatcherTest.cpp+78 tests/plugins/Utils/WindowInputMonitorTest.cpp+170−32 tests/plugins/Utils/WindowStateStorageTest.cpp+121 tests/plugins/WindowManager/CMakeLists.txt+36 tests/plugins/WindowManager/UnityApplicationMocks.h+211 tests/plugins/WindowManager/tst_TopLevelWindowModel.cpp+193 tests/plugins/Wizard/CMakeLists.txt+8−2 tests/plugins/Wizard/tst_pagelist.cpp+30−1 tests/qmltests/ApplicationMenuDataLoader.qml+99 tests/qmltests/ApplicationMenus/tst_MenuBar.qml+437 tests/qmltests/ApplicationMenus/tst_MenuPopup.qml+361 tests/qmltests/CMakeLists.txt+49−64 tests/qmltests/Components/CMakeLists.txt+35−9 tests/qmltests/Components/tst_Carousel.qml−293 tests/qmltests/Components/tst_Dialogs.qml+4−3 tests/qmltests/Components/tst_DragHandle.cpp+52−29 tests/qmltests/Components/tst_DragHandle.qml+28−10 tests/qmltests/Components/tst_DragHandle/BottomEdgeShowable.qml+108 tests/qmltests/Components/tst_DragHandle/LeftEdgeShowable.qml tests/qmltests/Components/tst_DragHandle/RightEdgeShowable.qml+108 tests/qmltests/Components/tst_DragHandle/SimpleButton.qml+14−9 tests/qmltests/Components/tst_DragHandle/TopEdgeShowable.qml+7−7 tests/qmltests/Components/tst_DraggingArea.qml+6−6 tests/qmltests/Components/tst_EdgeDragEvaluator.cpp+6−4 tests/qmltests/Components/tst_LazyImage.qml+27−8 tests/qmltests/Components/tst_LazyImage/portrait.png tests/qmltests/Components/tst_LazyImage/square.png tests/qmltests/Components/tst_LazyImage/wide.png tests/qmltests/Components/tst_Lockscreen.qml+28−39 tests/qmltests/Components/tst_MediaServices.qml+231 tests/qmltests/Components/tst_ModeSwitchWarningDialog.qml+2−2 tests/qmltests/Components/tst_PhysicalKeysMapper.qml+128−62 tests/qmltests/Components/tst_Rating.qml+1−1 tests/qmltests/Components/tst_ResponsiveGridView.qml−193 tests/qmltests/Components/tst_ResponsiveVerticalJournal.qml−183 tests/qmltests/Components/tst_SharingPicker.qml+22−20 tests/qmltests/Components/tst_Showable.qml+13 tests/qmltests/Components/tst_VirtualTouchPad.qml+197 tests/qmltests/Components/tst_Wallpaper.qml+118 tests/qmltests/Components/tst_WallpaperResolver.qml+115−43 tests/qmltests/Components/tst_ZoomableImage.qml+10−7 tests/qmltests/Dash/CardHelpers.js−113 tests/qmltests/Dash/Previews/MockPreviewWidget.qml−27 tests/qmltests/Dash/Previews/tst_Preview.qml−135 tests/qmltests/Dash/Previews/tst_PreviewActions.qml−148 tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml−179 tests/qmltests/Dash/Previews/tst_PreviewComment.qml−84 tests/qmltests/Dash/Previews/tst_PreviewCommentInput.qml−85 tests/qmltests/Dash/Previews/tst_PreviewExpandable.qml−339 tests/qmltests/Dash/Previews/tst_PreviewHeader.qml−155 tests/qmltests/Dash/Previews/tst_PreviewIconActions.qml−126 tests/qmltests/Dash/Previews/tst_PreviewImageGallery.qml−127 tests/qmltests/Dash/Previews/tst_PreviewPayments.qml−203 tests/qmltests/Dash/Previews/tst_PreviewProgress.qml−87 tests/qmltests/Dash/Previews/tst_PreviewRatingDisplay.qml−125 tests/qmltests/Dash/Previews/tst_PreviewRatingEdit.qml−80 tests/qmltests/Dash/Previews/tst_PreviewRatingInput.qml−202 tests/qmltests/Dash/Previews/tst_PreviewTable.qml−126 tests/qmltests/Dash/Previews/tst_PreviewTextSummary.qml−87 tests/qmltests/Dash/Previews/tst_PreviewVideoPlayback.qml−61 tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml−103 tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qml−104 tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qml−62 tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingList.qml−84 tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qml−98 tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qml−88 tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingsWidgetFactory.qml−65 tests/qmltests/Dash/artwork/avatar@12.png tests/qmltests/Dash/artwork/background.png tests/qmltests/Dash/artwork/checkers.png tests/qmltests/Dash/artwork/emblem.png tests/qmltests/Dash/artwork/music-player-design.png tests/qmltests/Dash/tst_Card.qml−622 tests/qmltests/Dash/tst_CardBenchmark.qml−97 tests/qmltests/Dash/tst_CardCarousel.qml−87 tests/qmltests/Dash/tst_CardTool.qml−379 tests/qmltests/Dash/tst_Dash.qml−569 tests/qmltests/Dash/tst_DashContent.qml−603 tests/qmltests/Dash/tst_DashPageHeader.qml−331 tests/qmltests/Dash/tst_DashShell.qml−135 tests/qmltests/Dash/tst_GenericScopeView.qml−666 tests/qmltests/Dash/tst_PageHeader/logo-ubuntu-orange.svg−60 tests/qmltests/Dash/tst_PreviewListView.qml−115 tests/qmltests/Greeter/TestView.qml+24−22 tests/qmltests/Greeter/tst_Greeter.qml+325−156 tests/qmltests/Greeter/tst_GreeterView.qml+1366 tests/qmltests/Greeter/tst_Infographics.qml+78−24 tests/qmltests/Greeter/tst_NarrowView.qml−522 tests/qmltests/Greeter/tst_WideView.qml−526 tests/qmltests/Launcher/tst_Drawer.qml+520 tests/qmltests/Launcher/tst_Launcher.qml+842−81 tests/qmltests/Notifications/Notification.qml+1 tests/qmltests/Notifications/tst_Notifications.qml+222−76 tests/qmltests/Notifications/tst_OptionToggle.qml+26−26 tests/qmltests/Notifications/tst_SwipeToAct.qml+30−27 tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+27−33 tests/qmltests/Panel/Indicators/tst_IndicatorItem.qml+18−18 tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml+98−93 tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qml+168−8 tests/qmltests/Panel/Indicators/tst_MessageMenuItemFactory.qml+1 tests/qmltests/Panel/PanelTest.qml+2−6 tests/qmltests/Panel/PanelUI.qml+286 tests/qmltests/Panel/tst_ActiveCallHint.qml+31−11 tests/qmltests/Panel/tst_MenuContent.qml+16−4 tests/qmltests/Panel/tst_Panel.qml+434−231 tests/qmltests/Panel/tst_PanelBar.qml+25−34 tests/qmltests/Panel/tst_PanelItemRow.qml+42−14 tests/qmltests/Panel/tst_PanelMenu.qml+140−38 tests/qmltests/Panel/tst_PanelMenuPage.qml+53−49 tests/qmltests/Panel/tst_PanelSmallScreen.qml+133 tests/qmltests/Stage/ApplicationCheckBox.qml+189 tests/qmltests/Stage/SizeHintField.qml+13−11 tests/qmltests/Stage/SurfaceManagerControls.qml+32 tests/qmltests/Stage/SurfaceManagerField.qml+17−18 tests/qmltests/Stage/tst_ApplicationWindow.qml+184−93 tests/qmltests/Stage/tst_DecoratedWindow.qml+267 tests/qmltests/Stage/tst_DesktopStage.qml+1085 tests/qmltests/Stage/tst_PhoneStage.qml+624 tests/qmltests/Stage/tst_QMLTopLevelWindowModel.qml+191 tests/qmltests/Stage/tst_Splash.qml+16−2 tests/qmltests/Stage/tst_SurfaceContainer.qml+258 tests/qmltests/Stage/tst_TabletStage.qml+764 tests/qmltests/Stage/tst_WindowDecoration.qml+244 tests/qmltests/Stage/tst_WindowResizeArea.qml+465 tests/qmltests/Stages/ApplicationCheckBox.qml−114 tests/qmltests/Stages/RecursingChildSessionControl.qml−145 tests/qmltests/Stages/tst_DesktopStage.qml−462 tests/qmltests/Stages/tst_PhoneStage.qml−467 tests/qmltests/Stages/tst_SessionContainer.qml−309 tests/qmltests/Stages/tst_SpreadDelegate.qml−312 tests/qmltests/Stages/tst_SurfaceContainer.qml−184 tests/qmltests/Stages/tst_TabletStage.qml−370 tests/qmltests/Stages/tst_WindowResizeArea.qml−294 tests/qmltests/Tutorial/tst_Tutorial.qml+664−247 tests/qmltests/UnityLogo.png tests/qmltests/Wizard/tst_Wizard.qml+240−317 tests/qmltests/tst_DeviceConfiguration.qml+49 tests/qmltests/tst_DisabledScreenNotice.qml+98−2 tests/qmltests/tst_OrientedShell.qml+719−465 tests/qmltests/tst_Shell.qml+2284−853 tests/qmltests/tst_ShellWithPin.qml+189−265 tests/qmltests/utils/Unity/Test/tst_UnityTest.qml+31 tests/scripts/alert-launcher-icon.sh+16 tests/scripts/get-progress.sh+16 tests/scripts/list-launcher-icons.sh+16 tests/scripts/set-count-visible.sh+16 tests/scripts/set-count.sh+16 tests/scripts/set-progress.sh+16 tests/uqmlscene/CMakeLists.txt+14−2 tests/uqmlscene/main.cpp+7−4 tests/utils/modules/Unity/Test/CMakeLists.txt+22−8 tests/utils/modules/Unity/Test/MouseTouchEmulationCheckbox.qml+5−1 tests/utils/modules/Unity/Test/StageTestCase.qml+64 tests/utils/modules/Unity/Test/Test.qmltypes−60 tests/utils/modules/Unity/Test/TouchEventSequenceWrapper.cpp+18−4 tests/utils/modules/Unity/Test/TouchEventSequenceWrapper.h+4−2 tests/utils/modules/Unity/Test/UnityTestCase.qml+205−44 tests/utils/modules/Unity/Test/plugin.cpp+13−3 tests/utils/modules/Unity/Test/qmldir+2−1 tests/utils/modules/Unity/Test/testutil.cpp+33−5 tests/utils/modules/Unity/Test/testutil.h+1 tools/CMakeLists.txt+2−12 tools/indicatorsclient/CMakeLists.txt+1−1 tools/indicatorsclient/indicatorsclient.cpp+10−8 tools/indicatorsclient/indicatorsclient.h−2 tools/indicatorsclient/main.cpp tools/menutool/CMakeLists.txt+5 tools/menutool/README+11 tools/menutool/menutool.cpp+62 tools/menutool/menutool.qml+118 tools/registry-tracker.cpp−146 tools/registry-tracker.h−49 tools/scopetool.cpp−112 tools/unlock-device+16
.bazaar/Makefiledeleted−6
@@ -1,6 +0,0 @@
1−install:
2− mkdir -p ~/.bazaar/plugins
3− cp plugins/* ~/.bazaar/plugins
4−
5−uninstall:
6− rm ~/.bazaar/plugins/makecheck_unity_phablet.py*
.bazaar/plugins/makecheck_unity_phablet.pydeleted−51
@@ -1,51 +0,0 @@
1−#!/usr/bin/python
2−# Copyright 2013, 2014 Canonical Ltd.
3−#
4−# This program is free software; you can redistribute it and/or modify
5−# it under the terms of the GNU Lesser General Public License as published by
6−# the Free Software Foundation; version 3.
7−#
8−# This program is distributed in the hope that it will be useful,
9−# but WITHOUT ANY WARRANTY; without even the implied warranty of
10−# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11−# GNU Lesser General Public License for more details.
12−#
13−# You should have received a copy of the GNU Lesser General Public License
14−# along with this program. If not, see <http://www.gnu.org/licenses/>.
15−
16−import os
17−import subprocess
18−from bzrlib import branch
19−from bzrlib.urlutils import local_path_from_url
20−
21−
22−def execute_makecheck(
23− local_branch, master_branch, old_revision_number, old_revision_id,
24− future_revision_number, future_revision_id, tree_delta, future_tree):
25− if not master_branch.basis_tree().has_filename("qml/Shell.qml"):
26− return
27−
28− os.chdir(local_path_from_url(master_branch.base))
29−
30− print "Executing 'make -C builddir test'.."
31− os.environ['CTEST_OUTPUT_ON_FAILURE'] = "1"
32− if (subprocess.call("make -C builddir test", shell=True) != 0):
33−
34− print("\n\n*** Warning ***\n\n"
35− "Basic tests failed. This commit will not pass continuous "
36− "integration.")
37−
38− branch = local_branch or master_branch
39− revision = branch.repository.get_revision(future_revision_id)
40− msg_file = open('message.txt', 'w')
41− msg_file.write(revision.message)
42− msg_file.close()
43−
44− print("\n\nSaved commit message to $SRC_DIR/message.txt.")
45− print("You can uncommit this revision, fix the tests and reuse your "
46− "message running:\n\nbzr commit -F message.txt\n\n")
47− elif os.path.isfile("message.txt"):
48− os.remove("message.txt")
49−
50−branch.Branch.hooks.install_named_hook(
51− 'pre_commit', execute_makecheck, 'make check pre-commit')
.bzr-builddeb/default.confdeleted−2
@@ -1,2 +0,0 @@
1−[BUILDDEB]
2−split = True
.bzrignoredeleted−7
@@ -1,7 +0,0 @@
1−# default build dir
2−/builddir
3−# QtCreator project files
4−/*.user
5−# Eclipse project files
6−.settings
7−message.txt
.crossbuilder/post_deploynew file+1
@@ -0,0 +1 @@
1+restart unity8
.gitignore+7
@@ -2,8 +2,15 @@
22/builddir
33# QtCreator project files
44/*.user
5+*.qmlc
6+*.jsc
57# Eclipse project files
68/.project
79/.cproject
810/.settings
911/.pydevproject
12+# KDevelop project Files
13+/.kdev4/
14+/build/
15+/*.kdev4
16+.clickable/
CMakeLists.txt+59−14
@@ -40,6 +40,19 @@ if(cmake_build_type_lower MATCHES coverage)
4040 ENABLE_COVERAGE_REPORT(TARGETS ${SHELL_APP} FILTER /usr/include ${CMAKE_SOURCE_DIR}/tests/* ${CMAKE_BINARY_DIR}/*)
4141endif()
4242
43+find_package (ECM 1.7.0 QUIET NO_MODULE)
44+if (ECM_FOUND)
45+ # Provides us with -DECM_ENABLE_SANITIZERS='X'
46+ # Where X can be address, thread, memory, leak, undefined
47+ include("${ECM_MODULE_DIR}/ECMEnableSanitizers.cmake")
48+endif()
49+
50+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
51+ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0")
52+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override" )
53+ endif()
54+endif()
55+
4356# Make sure we have all the needed symbols
4457set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,defs")
4558set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,defs")
@@ -49,15 +62,41 @@ add_custom_target(cppcheck COMMAND cppcheck --enable=all -q --error-exitcode=2
4962 ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/tests)
5063
5164include(FindPkgConfig)
52−find_package(Qt5Core 5.4 REQUIRED)
53−find_package(Qt5Qml 5.4 REQUIRED)
54−find_package(Qt5Quick 5.4 REQUIRED)
55−find_package(Qt5Gui 5.4 REQUIRED)
56−find_package(Qt5DBus 5.4 REQUIRED)
57−find_package(Qt5Concurrent 5.4 REQUIRED)
58−find_package(Qt5Sql 5.4 REQUIRED)
59−
60−pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=11)
65+find_package(Qt5Core 5.6 REQUIRED)
66+find_package(Qt5Qml 5.6 REQUIRED)
67+find_package(Qt5Quick 5.6 REQUIRED)
68+find_package(Qt5Gui 5.6 REQUIRED)
69+find_package(Qt5DBus 5.6 REQUIRED)
70+find_package(Qt5Concurrent 5.6 REQUIRED)
71+find_package(Qt5Sql 5.6 REQUIRED)
72+find_package(Qt5Test 5.6 REQUIRED)
73+find_package(Qt5Svg 5.6 REQUIRED)
74+find_package(Qt5Network 5.6 REQUIRED)
75+find_package(Qt5Xml 5.6 REQUIRED)
76+
77+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=27)
78+pkg_check_modules(GEONAMES REQUIRED geonames>=0.2)
79+pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
80+pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
81+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=13)
82+pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
83+pkg_check_modules(GD3 REQUIRED gnome-desktop-3.0)
84+pkg_check_modules(UAL REQUIRED ubuntu-app-launch-2)
85+pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
86+pkg_check_modules(QTDBUSTEST REQUIRED
87+ libqtdbustest-1
88+ libqtdbusmock-1
89+ )
90+
91+### Check UbuntuGestures private headers. No pkg-config (.pc) file is provided for them
92+find_path(UBUNTUGESTUREPRIV
93+ NAMES UbuntuGestures/private/damper_p.h UbuntuGestures/private/ucswipearea_p.h UbuntuGestures/private/ucswipearea_p_p.h
94+ PATHS ${UBUNTUGESTURES_INCLUDEDIR}/UbuntuGestures/${UBUNTUGESTURES_VERSION}
95+ NO_DEFAULT_PATH)
96+if (${UBUNTUGESTUREPRIV} STREQUAL UBUNTUGESTUREPRIV-NOTFOUND)
97+ message(FATAL_ERROR "UbuntuGestures private headers not found.")
98+endif()
99+# end of UbuntuGesture private headers check
61100
62101# Standard install paths
63102include(GNUInstallDirs)
@@ -109,9 +148,8 @@ include(autopilot)
109148declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)
110149
111150set(SHELL_APP unity8)
112−set(DASH_APP unity8-dash)
113−set(SCOPE_TOOL unity-scope-tool)
114151set(INDICATORS_CLIENT_APP indicators-client)
152+set(GREETER_APP unity8-greeter)
115153set(MOCK_INDICATOR_SERVICE_APP unity-mock-indicator-service)
116154
117155include_directories(
@@ -120,17 +158,24 @@ include_directories(
120158 ${APPLICATION_API_INCLUDE_DIRS}
121159)
122160
123−set(ARTIFACTS_DIR "" CACHE PATH "Store test artifacts in this directory.")
124−
125161# Quiet logger
126162set(QUIET_LOGGER OFF CACHE BOOL "Disable test output on stdout.")
127163if(NOT QUIET_LOGGER)
128164 set(STDOUT_LOGGER "-o" "-,txt")
129165endif()
130166
167+execute_process(COMMAND dpkg-architecture -qDEB_HOST_ARCH OUTPUT_VARIABLE ARCH)
168+if (NOT ARCH MATCHES "arm*")
169+ set(ENABLE_TOUCH_EMULATION true)
170+ add_definitions(-DUNITY8_ENABLE_TOUCH_EMULATION)
171+ pkg_check_modules(MOUSETOUCHADAPTOR_LIBS REQUIRED x11 xcb xi)
172+else()
173+ set(ENABLE_TOUCH_EMULATION false)
174+ message(STATUS "Touch emulation support disabled.")
175+endif()
176+
131177# add subdirectories to build
132178add_subdirectory(include)
133−add_subdirectory(libs)
134179add_subdirectory(src)
135180add_subdirectory(tools)
136181add_subdirectory(qml)
CODING+46−59
@@ -15,23 +15,17 @@ download source
1515 $ bzr branch lp:unity8 ~/unity8/trunk
1616 $ cd ~/unity8/trunk
1717
18−install dependencies
18+install dependencies and build Unity 8
1919--------------------
20−If its your first time, install build dependencies
2120
2221$ cd ~/unity8/trunk
23−$ ./build.sh --setup
24−
25− this will:
26− - install the required dependencies to build, as well as run on the desktop
27− - it should also install unity-scope-home and unity-lens-application which
28− are technically "recommends", not strict dependencies
22+$ ./build.sh
2923
30−build Unity 8
31−-------------
24+ If its your first time, this will install the required dependencies to build and
25+ build it.
3226
33−$ cd ~/unity8/trunk
34−$ ./build.sh
27+ You might want to also install unity-scope-home and unity-scope-click which
28+ are technically "recommends", not strict dependencies
3529
3630You may also rebuild with the -c for clean, which just deletes the build
3731directory.
@@ -43,17 +37,21 @@ Running Unity 8 on your desktop
4337run the Unity 8 shell
4438---------------------
4539$ cd ~/unity8/trunk
46−$ ./run.sh
40+$ cd builddir
4741
48−Options can be passed to test the lock screen
49−$ ./run.sh -p OR -k
42+Each component of unity8 can be ran independently for development and testing
43+For example:
44+$ make tryShell
45+$ make tryLauncher
46+$ make tryLockscreen
5047
51−-p is for pin lock, for which the default prompt answer is "1234"
52−-k is for keylock passphrase, for which the default prompt answer is "password"
48+Check out the tests/qmltests/ directory for a list of things that can be ran.
5349
5450Notes
5551-----
5652- to navigate, utilize the mouse left button as you would your finger
53+- a three point drag (for side stage operations) can be performed by using
54+ the Shift+Control+Alt (all together) keyboard modifiers while using the mouse.
5755- to get the translations work, currently you have to do make install to
5856 put the *.mo files into correct structure. We'll look for a better solution
5957 later.
@@ -68,50 +66,15 @@ Notes
6866
6967Running Unity 8 on devices
7068==========================
71−- Ubuntu Touch builds are currently only available in 14.04 flavour
72−- supported hardware should match one of those listed here
73− https://wiki.ubuntu.com/Touch/Devices#Running_fine
74−- follow the Ubuntu Touch install instructions for your chosen device
75− https://wiki.ubuntu.com/Touch/Install
76−- make sure your device is connected to a network
77−- also make sure you have your SSH key in ~/.ssh/id_rsa.pub (or install one
78− on the device yourself)
79−
80−$ cd ~/unity/trunk
81−$ ./run_on_device.sh --setup
82− this will:
83− - install your public SSH key on the device
84− - install the needed dependencies
8569
86−$ ./run_on_device.sh
87− this will:
88− - rsync the code to the device
89− - build on the device
90− - replace the running shell
91−
92−Options can be passed to test the lock screen
93−$ ./run_on_device.sh -p OR -k
94−
95−-p is for pin lock, for which the default prompt answer is "1234"
96−-k is for keylock passphrase, for which the default prompt answer is "password"
97−
98−Notes
99−-----
100−- using adb over TCP has some advantages, Google will be of help here
101− - NOTE: this is not yet available for flipped images
102− - TL;DR: `adb tcpip 5555; adb connect $your_device_ip`
103− - you can persist the above via `adb shell setprop persist.adb.tcp.port 5555`
104− - it's unsafe - anyone can connect to your device
105− - with TCP the Nexus 10 doesn't drop the adb connection when locking
106− the screen
107−- exporting ANDROID_SERIAL=$your_device_serial or
108− ANDROID_SERIAL=$your_device_ip:5555 will make adb not complain about
109− multiple devices
110−- you can export TARGET_IP=$your_device_ip TARGET_SSH_PORT=22 for run_on_device.sh
111− to not use adb forwarding - useful if you use multiple devices
112−- using Ninja (package ninja-build - run_on_device.sh -s installs this now)
113− will improve build times (especially in the nothing-to-build case)
70+Running unity8 on a device should be done using crossbuilder.
71+Go to
72+* https://launchpad.net/crossbuilder and
73+* https://wiki.ubuntu.com/Touch/Crossbuilder
74+for more details on crossbuilder.
11475
76+unity8 will automatically restart on the phone once deployment
77+has finished due to post-build-steps set up in this repository.
11578
11679Coding guidelines
11780=================
@@ -199,3 +162,27 @@ $ PYTHONPATH=../tests/autopilot autopilot3 run unity8.some.very.long.test.name
199162or run them all with
200163
201164$ PYTHONPATH=../tests/autopilot autopilot3 run unity8
165+
166+Debugging techniques
167+====================
168+
169+Unity8 heavily uses Qt and with that Qt debugging techniques mostly apply in the
170+same fashion. There are, however, some additional unity8-specific notes:
171+
172+* Enable/disable Qt scenegraph visualizer on the fly:
173+
174+ $ qdbus com.canonical.Unity8.Debugging /com/canonical/Unity8/Debugging SetSceneGraphVisualizer <mode>
175+
176+ This is equivalent to exporting QSG_VISUALIZE=<mode> before running unity8, except it does it on the
177+ fly.
178+
179+* Toggle slow animations on the fly:
180+
181+ $ qdbus com.canonical.Unity8.Debugging /com/canonical/Unity8/Debugging SetSlowAnimations <true|false>
182+
183+* Change logging filter rules on the fly:
184+
185+ $ qdbus com.canonical.Unity8.Debugging /com/canonical/Unity8/Debugging SetLoggingFilterRules <filter>
186+
187+ This is equivalent to exporting QT_LOGGING_RULES or defining them in QT_LOGGING_CONF, except it does
188+ it on the fly.
Jenkinsfilenew file+2
@@ -0,0 +1,2 @@
1+@Library('ubports-build-tools') _
2+buildAndProvideDebianPackage()
README.mdnew file+31
@@ -0,0 +1,31 @@
1+# Lomiri
2+
3+Lomiri is the operating environment for everywhere. It is able to span the gaps between touch, mouse, and keyboard; between phones, tablets, and workstations; and look good doing it.
4+
5+If you want to contribute to Lomiri on Ubuntu Touch, you've come to the right place. If you want to package Lomiri for other operating systems, you'll be better served by the main branch on the repository that we're migrating to: https://gitlab.com/ubports/core/lomiri
6+
7+Lomiri has been renamed from Unity8. Most of the software on-device in Ubuntu Touch based on Ubuntu 16.04 is still called `unity8`.
8+
9+## Where to report issues
10+
11+Issues related to the version of Lomiri that currently runs on Ubuntu Touch devices may still be reported on this repository. We will move these reports to the GitLab repository as part of our final migration.
12+
13+## Developing Lomiri on Ubuntu Touch
14+
15+This repository contains the code for Lomiri currently running on Ubuntu Touch. If you would like to modify this version of Lomiri, follow the steps below. If you would like to modify Lomiri in another operating system, check out our new repository: https://gitlab.com/ubports/core/lomiri
16+
17+Lomiri can be built and its test suite run using [`clickable`](https://clickable-ut.dev). This is a convenient method to try out most graphical changes to Lomiri without an annoying redeployment process. If you wish to test your changes on your device or make changes that are more difficult to test without real hardware, check out [Making changes and testing locally on the UBports documentation](https://docs.ubports.com/en/latest/systemdev/testing-locally.html). If not, read on.
18+
19+Before you start, [install Clickable](https://clickable-ut.dev/en/latest/install.html).
20+
21+Now, clone this repository to your computer: `git clone https://github.com/ubports/unity8.git`
22+
23+Move into this directory: `cd unity8`
24+
25+Now you can use the full suite of tools provided by this repository's [clickable.yaml](clickable.yaml). For example:
26+
27+* `clickable ide qtcreator` will open QtCreator with this repository open as a project. You can edit and build the project this way, but running the tests will be a bit difficult.
28+* `clickable build --libs --verbose` will build Lomiri in the same environment as it would receive in Ubuntu Touch.
29+* `clickable test --libs` will run the entire Lomiri test suite. This test suite includes graphical tests (which are run on a virtual, invisible desktop) and non-graphical unit tests. These tests make sure Lomiri functions as prescribed and prevents new bugs from being added. You should run them before you create a PR on this repository. This command takes about 7 minutes on an Intel i7-8550U, so plan your time accordingly and use the next two options to reduce the number of times you need to run the whole test suite...
30+* `clickable ide 'cd build/x86_64-linux-gnu/unity8/ && make tryShell'` and similar commands that replace the `Shell` with another test target defined in [tests/qmltests/CMakeLists.txt](tests/qmltests/CMakeLists.txt) allow trying out some Lomiri components in a mock environment. You can use this to try out your changes to Lomiri as you develop.
31+* `clickable ide 'cd build/x86_64-linux-gnu/unity8/ && make xvfbtestShell'` and similar commands that replace the `Shell` with another test target defined in [tests/qmltests/CMakeLists.txt](tests/qmltests/CMakeLists.txt) allow running a single TestCase. You can remove the `xvfb` part of the make target to run the test case graphically, which might help you see what is causing the test to fail.
build.sh+22−37
@@ -1,5 +1,21 @@
11#!/bin/sh
22
3+#
4+# Copyright (C) 2017 Canonical Ltd
5+#
6+# This program is free software: you can redistribute it and/or modify
7+# it under the terms of the GNU General Public License version 3 as
8+# published by the Free Software Foundation.
9+#
10+# This program is distributed in the hope that it will be useful,
11+# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+# GNU General Public License for more details.
14+#
15+# You should have received a copy of the GNU General Public License
16+# along with this program. If not, see <http://www.gnu.org/licenses/>.
17+#
18+
319SETUP=false
420CLEAN=false
521NUM_JOBS=$(( `grep -c ^processor /proc/cpuinfo` + 1 ))
@@ -9,7 +25,6 @@ usage() {
925 echo "usage: build [OPTIONS] [BUILD_TYPE]\n" >&2
1026 echo "Script to build the shell. If BUILD_TYPE is not specified, it defaults to \"debug\".\n" >&2
1127 echo "OPTIONS:" >&2
12− echo " -s, --setup Setup the build environment and branch Unity" >&2
1328 echo " -c, --clean Clean the build tree before building" >&2
1429 echo >&2
1530 exit 1
@@ -22,7 +37,6 @@ eval set -- "$ARGS"
2237while [ $# -gt 0 ]
2338do
2439 case "$1" in
25− -s|--setup) SETUP=true;;
2640 -c|--clean) CLEAN=true;;
2741 -h|--help) usage;;
2842 --) shift;break;;
@@ -35,31 +49,6 @@ done
3549BUILD_TYPE="debug"
3650[ $# -eq 1 ] && BUILD_TYPE="$1"
3751
38−install_dependencies() {
39− sudo apt-get update || exit 4
40− echo "Installing Unity 8 dependencies.."
41− sudo apt-get install devscripts \
42− equivs \
43− gsettings-desktop-schemas \
44− gsettings-ubuntu-schemas \
45− pay-service \
46− qmenumodel-qml \
47− qml-module-qtquick-layouts \
48− qml-module-qtquick-xmllistmodel \
49− qtdeclarative5-gsettings1.0 \
50− qtdeclarative5-ubuntu-ui-toolkit-plugin \
51− qtdeclarative5-ubuntu-settings-components \
52− qtdeclarative5-ubuntu-telephony0.1 \
53− qtdeclarative5-ubuntu-thumbnailer0.1 \
54− qtdeclarative5-unity-notifications-plugin \
55− qml-module-ubuntu-connectivity \
56− ubuntu-mobile-icons \
57− ubuntu-system-settings \
58− unity-plugin-scopes \
59− xvfb \
60− || exit 5
61−}
62−
6352mk_build_deps() {
6453 if [ ! -f control -o $CODE_DIR/debian/control -nt control ]; then
6554 sed 's/\:native//g' $CODE_DIR/debian/control > control
@@ -85,13 +74,9 @@ else
8574 BUILD_COMMAND="make -j$NUM_JOBS"
8675fi
8776
88−if $SETUP; then
89− install_dependencies
90−else
91− if $CLEAN; then rm -rf builddir; fi
92− mkdir -p builddir
93− cd builddir
94− mk_build_deps
95− cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE $CODE_DIR ${GENERATOR} || exit 6
96− ${BUILD_COMMAND} || exit 7
97−fi
77+if $CLEAN; then rm -rf builddir; fi
78+mkdir -p builddir
79+cd builddir
80+mk_build_deps
81+cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE $CODE_DIR ${GENERATOR} || exit 6
82+${BUILD_COMMAND} || exit 7
clickable.yamlnew file+153
@@ -0,0 +1,153 @@
1+clickable_minimum_required: '7'
2+builder: custom
3+build: echo Run \'clickable build --libs --verbose\' to build && false
4+restrict_arch: amd64
5+libraries:
6+ unity8:
7+ builder: cmake
8+ src_dir: "${ROOT}"
9+ test: make xvfballtests -j${NUM_PROCS}
10+ dependencies_host:
11+ - android-headers
12+ - cmake
13+ - cmake-extras
14+ - dbus-test-runner
15+ - debhelper
16+ - dh-apparmor
17+ - doxyqml
18+ - g++:native
19+ - gdb
20+ - graphviz
21+ - gsettings-ubuntu-schemas
22+ - libandroid-properties-dev
23+ - libconnectivity-qt1-dev
24+ - libevdev-dev
25+ - libgeonames-dev
26+ - libgl1-mesa-dev
27+ - libgl1-mesa-dri
28+ - libgles2-mesa-dev
29+ - libglib2.0-dev
30+ - libgnome-desktop-3-12
31+ - libgnome-desktop-3-dev
32+ - libgsettings-qt-dev
33+ - libhardware-dev
34+ - liblightdm-qt5-3-dev
35+ - libpam0g-dev
36+ - libpulse-dev
37+ - libqmenumodel-dev
38+ - libqt5sql5-sqlite
39+ - libqt5svg5-dev
40+ - libqt5xmlpatterns5-dev
41+ - libqtdbusmock1-dev
42+ - libqtdbustest1-dev
43+ - libsystemsettings-dev
44+ - libubuntu-app-launch2-dev
45+ - libubuntu-download-manager-common-dev
46+ - libubuntugestures5-dev
47+ - libubuntugestures5-private-dev
48+ - libudev-dev
49+ - libudm-common-dev
50+ - libunity-api-dev
51+ - libusermetricsoutput1-dev
52+ - libx11-dev
53+ - libxcb1-dev
54+ - libxi-dev
55+ - pkg-config
56+ - python3-all:any
57+ - python3-setuptools:native
58+ - qml-module-qt-labs-folderlistmodel
59+ - qml-module-qt-labs-settings
60+ - qml-module-qtmultimedia
61+ - qml-module-qtqml-statemachine
62+ - qml-module-qtquick-layouts
63+ - qml-module-qtquick-xmllistmodel
64+ - qml-module-qtquick2
65+ - qml-module-qtsysteminfo
66+ - qml-module-qttest
67+ - qml-module-ubuntu-components
68+ - qml-module-ubuntu-layouts
69+ - qml-module-ubuntu-settings-components
70+ - qml-module-ubuntu-test
71+ - qtbase5-dev
72+ - qtbase5-dev-tools
73+ - qtbase5-private-dev
74+ - qtdbustest-runner
75+ - qtdeclarative5-dev
76+ - qtdeclarative5-dev-tools
77+ - qtdeclarative5-private-dev
78+ - qtdeclarative5-ubuntu-content1
79+ - ttf-ubuntu-font-family
80+ - ubports-wallpapers
81+ - xvfb
82+dependencies_target:
83+ - android-headers
84+ - cmake
85+ - cmake-extras
86+ - dbus-test-runner
87+ - debhelper
88+ - dh-apparmor
89+ - doxyqml
90+ - g++:native
91+ - gdb
92+ - graphviz
93+ - gsettings-ubuntu-schemas
94+ - libandroid-properties-dev
95+ - libconnectivity-qt1-dev
96+ - libevdev-dev
97+ - libgeonames-dev
98+ - libgl1-mesa-dev
99+ - libgl1-mesa-dri
100+ - libgles2-mesa-dev
101+ - libglib2.0-dev
102+ - libgnome-desktop-3-12
103+ - libgnome-desktop-3-dev
104+ - libgsettings-qt-dev
105+ - libhardware-dev
106+ - liblightdm-qt5-3-dev
107+ - libpam0g-dev
108+ - libpulse-dev
109+ - libqmenumodel-dev
110+ - libqt5sql5-sqlite
111+ - libqt5svg5-dev
112+ - libqt5xmlpatterns5-dev
113+ - libqtdbusmock1-dev
114+ - libqtdbustest1-dev
115+ - libsystemsettings-dev
116+ - libubuntu-app-launch2-dev
117+ - libubuntu-download-manager-common-dev
118+ - libubuntugestures5-dev
119+ - libubuntugestures5-private-dev
120+ - libudev-dev
121+ - libudm-common-dev
122+ - libunity-api-dev
123+ - libusermetricsoutput1-dev
124+ - libx11-dev
125+ - libxcb1-dev
126+ - libxi-dev
127+ - pkg-config
128+ - python3-all:any
129+ - python3-setuptools:native
130+ - qml-module-qt-labs-folderlistmodel
131+ - qml-module-qt-labs-settings
132+ - qml-module-qtmultimedia
133+ - qml-module-qtqml-statemachine
134+ - qml-module-qtquick-layouts
135+ - qml-module-qtquick-xmllistmodel
136+ - qml-module-qtquick2
137+ - qml-module-qtsysteminfo
138+ - qml-module-qttest
139+ - qml-module-ubuntu-components
140+ - qml-module-ubuntu-layouts
141+ - qml-module-ubuntu-settings-components
142+ - qml-module-ubuntu-test
143+ - qtbase5-dev
144+ - qtbase5-dev-tools
145+ - qtbase5-private-dev
146+ - qtdbustest-runner
147+ - qtdeclarative5-dev
148+ - qtdeclarative5-dev-tools
149+ - qtdeclarative5-private-dev
150+ - qtdeclarative5-ubuntu-content1
151+ - ttf-ubuntu-font-family
152+ - ubports-wallpapers
153+ - xvfb
cmake/modules/QmlPlugins.cmakedeleted−148
@@ -1,148 +0,0 @@
1−# If you need to override the qmlplugindump binary, create the qmlplugin executable
2−# target before loading this plugin.
3−
4−if(NOT TARGET qmlplugindump)
5− find_program(qmlplugindump_exe qmlplugindump)
6−
7− if(NOT qmlplugindump_exe)
8− msg(FATAL_ERROR "Could not locate qmlplugindump.")
9− endif()
10−
11− add_executable(qmlplugindump IMPORTED)
12− set_target_properties(qmlplugindump PROPERTIES IMPORTED_LOCATION ${qmlplugindump_exe})
13−endif()
14−
15−#
16−# A custom target for building the qmltypes files manually.
17−#
18−if (NOT TARGET qmltypes)
19− add_custom_target(qmltypes)
20−endif()
21−
22−# Creates a target for copying resource files into build dir and optionally installing them.
23−#
24−# Files will be copied into ${BINARY_DIR}/${path} or ${CMAKE_CURRENT_BINARY_DIR} and installed
25−# into ${DESTINATION}/${path}.
26−#
27−# Resource file names are matched against {*.{qml,js,jpg,png,sci,svg},qmldir}.
28−#
29−# export_qmlfiles(plugin path
30−# [SEARCH_PATH path] # Path to search for resources in (defaults to ${CMAKE_CURRENT_SOURCE_DIR})
31−# [BINARY_DIR path]
32−# [DESTINATION path]
33−# [TARGET_PREFIX string] # Will be prefixed to the target name
34−# )
35−#
36−# Created target:
37−# - ${TARGET_PREFIX}${plugin}-qmlfiles - Copies resources into the binary dir.
38−
39−macro(export_qmlfiles PLUGIN PATH)
40− set(single SEARCH_PATH BINARY_DIR DESTINATION TARGET_PREFIX)
41− cmake_parse_arguments(QMLFILES "" "${single}" "" ${ARGN})
42−
43− if(NOT QMLFILES_SEARCH_PATH)
44− set(QMLFILES_SEARCH_PATH ${CMAKE_CURRENT_SOURCE_DIR})
45− endif()
46−
47− if(QMLFILES_BINARY_DIR)
48− set(qmlfiles_dir ${QMLFILES_BINARY_DIR}/${PATH})
49− else()
50− set(qmlfiles_dir ${CMAKE_CURRENT_BINARY_DIR})
51− endif()
52−
53− file(GLOB QMLFILES
54− ${QMLFILES_SEARCH_PATH}/*.qml
55− ${QMLFILES_SEARCH_PATH}/*.js
56− ${QMLFILES_SEARCH_PATH}/*.jpg
57− ${QMLFILES_SEARCH_PATH}/*.png
58− ${QMLFILES_SEARCH_PATH}/*.sci
59− ${QMLFILES_SEARCH_PATH}/*.svg
60− ${QMLFILES_SEARCH_PATH}/*.qmltypes
61− ${QMLFILES_SEARCH_PATH}/qmldir
62− )
63−
64− execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${qmlfiles_dir})
65−
66− # copy the files
67− add_custom_target(${QMLFILES_TARGET_PREFIX}${PLUGIN}-qmlfiles ALL
68− COMMAND cp ${QMLFILES} ${qmlfiles_dir}
69− DEPENDS ${QMLFILES}
70− SOURCES ${QMLFILES}
71− )
72−
73− if(QMLFILES_DESTINATION)
74− # install the qmlfiles file.
75− install(FILES ${QMLFILES}
76− DESTINATION ${QMLFILES_DESTINATION}/${PATH}
77− )
78− endif()
79−endmacro()
80−
81−
82−# Creates a target for generating the typeinfo file for a QML plugin and/or installs the plugin
83−# targets.
84−#
85−# Files will be copied into ${BINARY_DIR}/${path} or ${CMAKE_CURRENT_BINARY_DIR} and installed
86−# into ${DESTINATION}/${path}. If you don't pass BINARY_DIR, it's assumed that current source
87−# path ends with ${path}.
88−#
89−# The generated file will be named after the last segment of the plugin name, e.g. Foo.qmltypes.
90−#
91−# export_qmlplugin(plugin version path
92−# [BINARY_DIR path]
93−# [DESTINATION path]
94−# [TARGET_PREFIX string] # Will be prefixed to the target name
95−# [ENVIRONMENT string] # Will be added to qmlplugindump's env
96−# [TARGETS target1 [target2 ...]] # Targets to depend on and install (e.g. the plugin shared object)
97−# [NO_TYPES] # Do not create the qmltypes target
98−# )
99−#
100−# Created target:
101−# - ${TARGET_PREFIX}${plugin}-qmltypes - Generates the qmltypes file in the source dir.
102−# It will be made a dependency of the "qmltypes" target.
103−
104−macro(export_qmlplugin PLUGIN VERSION PATH)
105− set(options NO_TYPES)
106− set(single BINARY_DIR DESTINATION TARGET_PREFIX ENVIRONMENT)
107− set(multi TARGETS)
108− cmake_parse_arguments(QMLPLUGIN "${options}" "${single}" "${multi}" ${ARGN})
109−
110− if(QMLPLUGIN_BINARY_DIR)
111− set(qmlplugin_dir ${QMLPLUGIN_BINARY_DIR}/${PATH})
112− else()
113− # Find import path to point qmlplugindump at
114− string(REGEX REPLACE "/${PATH}$" "" QMLPLUGIN_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
115− set(qmlplugin_dir ${CMAKE_CURRENT_BINARY_DIR})
116− endif()
117−
118− if(NOT QMLPLUGIN_NO_TYPES)
119− # Relative path for the module
120− string(REPLACE "${CMAKE_BINARY_DIR}/" "" QMLPLUGIN_MODULE_DIR "${QMLPLUGIN_BINARY_DIR}")
121−
122− # Find the last segment of the plugin name to use as qmltypes basename
123− string(REGEX MATCH "[^.]+$" plugin_suffix ${PLUGIN})
124− set(target_prefix ${QMLPLUGIN_TARGET_PREFIX}${PLUGIN})
125− set(qmltypes_path ${CMAKE_CURRENT_SOURCE_DIR}/${plugin_suffix}.qmltypes)
126−
127− add_custom_target(${target_prefix}-qmltypes
128− COMMAND env ${QMLPLUGIN_ENVIRONMENT} $<TARGET_FILE:qmlplugindump> -notrelocatable
129− ${PLUGIN} ${VERSION} ${QMLPLUGIN_MODULE_DIR} > ${qmltypes_path}
130− WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
131− )
132− add_dependencies(${target_prefix}-qmltypes ${target_prefix}-qmlfiles ${QMLPLUGIN_TARGETS})
133− add_dependencies(qmltypes ${target_prefix}-qmltypes)
134− endif()
135−
136− set_target_properties(${QMLPLUGIN_TARGETS} PROPERTIES
137− ARCHIVE_OUTPUT_DIRECTORY ${qmlplugin_dir}
138− LIBRARY_OUTPUT_DIRECTORY ${qmlplugin_dir}
139− RUNTIME_OUTPUT_DIRECTORY ${qmlplugin_dir}
140− )
141−
142− if (QMLPLUGIN_DESTINATION)
143− # Install additional targets
144− install(TARGETS ${QMLPLUGIN_TARGETS}
145− DESTINATION ${QMLPLUGIN_DESTINATION}/${PATH}
146− )
147− endif()
148−endmacro()
cmake/modules/QmlTest.cmake+189−13
@@ -55,6 +55,55 @@ function(add_qml_test PATH COMPONENT_NAME)
5555endfunction()
5656
5757
58+# add_qml_test_data(path component_name
59+# [...]
60+# )
61+#
62+# Install file called ${component_name} (or ${component_name}.qml) under
63+# ${path}.
64+
65+function(add_qml_test_data PATH COMPONENT_NAME)
66+ cmake_parse_arguments(TEST "" "DESTINATION" "" ${ARGN})
67+
68+ set(filename "${CMAKE_CURRENT_SOURCE_DIR}/${PATH}/${COMPONENT_NAME}")
69+
70+ if (IS_DIRECTORY "${filename}")
71+ # As a convenience, allow specifying a directory and we will install
72+ # all files in the dir. We do it this way rather than passing
73+ # DIRECTORY to install() because we want to process any qml files.
74+ file(GLOB subfiles RELATIVE "${filename}" "${filename}/*")
75+ foreach(subfile ${subfiles})
76+ add_qml_test_data("${PATH}/${COMPONENT_NAME}" "${subfile}")
77+ endforeach()
78+ return()
79+ endif()
80+
81+ if (NOT EXISTS "${filename}")
82+ set(filename "${filename}.qml")
83+ set(COMPONENT_NAME "${COMPONENT_NAME}.qml")
84+ endif()
85+
86+ if ("${filename}" MATCHES "\\.qml$")
87+ file(READ "${filename}" contents)
88+ string(REGEX REPLACE "(\"[./]*)/qml(/|\")" "\\1\\2" contents "${contents}")
89+ # this is for (at least) cardcreatortest which pulls in an architecture-specific
90+ # import into the plugins directory (which is a 'qml' once installed).
91+ string(REGEX REPLACE "(import \"[./]*)/plugins(/|\")" "\\1/qml\\2" contents "${contents}")
92+ set(filename "${CMAKE_CURRENT_BINARY_DIR}/${PATH}/${COMPONENT_NAME}")
93+ file(WRITE "${filename}" "${contents}")
94+ endif()
95+
96+ if (TEST_DESTINATION)
97+ set(DESTINATION "${TEST_DESTINATION}")
98+ else()
99+ file(RELATIVE_PATH relcurpath "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
100+ set(DESTINATION "${SHELL_APP_DIR}/${relcurpath}/${PATH}")
101+ endif()
102+
103+ install(FILES "${filename}" DESTINATION "${DESTINATION}")
104+endfunction()
105+
106+
58107# add_qml_unittest(path component_name
59108# [...]
60109# )
@@ -71,6 +120,10 @@ function(add_qml_unittest PATH COMPONENT_NAME)
71120 ${ARGN}
72121 ARGS -input ${CMAKE_CURRENT_SOURCE_DIR}/${PATH}/tst_${COMPONENT_NAME}.qml ${QMLTEST_ARGS}
73122 )
123+
124+ if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PATH}/tst_${COMPONENT_NAME}.qml")
125+ add_qml_test_data("${PATH}" "tst_${COMPONENT_NAME}.qml")
126+ endif()
74127endfunction()
75128
76129
@@ -91,6 +144,10 @@ function(add_manual_qml_test PATH COMPONENT_NAME)
91144 ${ARGN}
92145 ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${PATH}/tst_${COMPONENT_NAME}.qml ${QMLTEST_ARGS}
93146 )
147+
148+ if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PATH}/tst_${COMPONENT_NAME}.qml")
149+ add_qml_test_data("${PATH}" "tst_${COMPONENT_NAME}.qml")
150+ endif()
94151endfunction()
95152
96153
@@ -108,8 +165,7 @@ endfunction()
108165#
109166# Logging options in the standard form of "-o filename,format"
110167# will be appended to the arguments list, prefixed with ARG_PREFIX.
111−# XUnitXML files will be stored in current binary dir or under
112−# ARTIFACTS_DIR, if set.
168+# XUnitXML files will be stored in current binary dir.
113169#
114170# Three targets will be created:
115171# - test${component_name} - Runs the test
@@ -122,14 +178,8 @@ function(add_executable_test COMPONENT_NAME TARGET)
122178 cmake_parse_arguments(QMLTEST "${QMLTEST_OPTIONS}" "${QMLTEST_SINGLE}" "${QMLTEST_MULTI}" ${ARGN})
123179 mangle_arguments()
124180
125− if(ARTIFACTS_DIR)
126− file(RELATIVE_PATH path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
127− file(MAKE_DIRECTORY ${ARTIFACTS_DIR}/${path})
128− set(file_logger -o ${ARTIFACTS_DIR}/${path}/test${COMPONENT_NAME}.xml,xunitxml)
129− else()
130− file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
131− set(file_logger -o ${CMAKE_CURRENT_BINARY_DIR}/test${COMPONENT_NAME}.xml,xunitxml)
132− endif()
181+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
182+ set(file_logger -o ${CMAKE_CURRENT_BINARY_DIR}/test${COMPONENT_NAME}.xml,xunitxml)
133183
134184 bake_arguments("${QMLTEST_ARG_PREFIX}" args ${iterations} ${file_logger} ${STDOUT_LOGGER})
135185
@@ -151,7 +201,7 @@ function(add_executable_test COMPONENT_NAME TARGET)
151201 add_qmltest_target(xvfbtest${COMPONENT_NAME} ${TARGET}
152202 COMMAND $<TARGET_FILE:xvfb-run> --server-args "-screen 0 1024x768x24" --auto-servernum ${qmltest_command}
153203 ${depends}
154− ENVIRONMENT QML2_IMPORT_PATH=${imports} ${QMLTEST_ENVIRONMENT} LD_PRELOAD=/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/mesa/libGL.so.1
204+ ENVIRONMENT QT_QPA_PLATFORM=xcb QML2_IMPORT_PATH=${imports} LD_PRELOAD=/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/mesa/libGL.so.1 ${QMLTEST_ENVIRONMENT}
155205 TARGETS ${xvfb_targets}
156206 )
157207 endif()
@@ -183,7 +233,7 @@ function(add_manual_test COMPONENT_NAME TARGET)
183233 cmake_parse_arguments(QMLTEST "${QMLTEST_OPTIONS}" "${QMLTEST_SINGLE}" "${QMLTEST_MULTI}" ${ARGN})
184234 mangle_arguments()
185235
186− bake_arguments("${QMLTEST_ARG_PREFIX}" args -qmljsdebugger=port:3768)
236+ bake_arguments("${QMLTEST_ARG_PREFIX}" args -qmljsdebugger=port:3768,3800)
187237
188238 set(qmltry_command
189239 $<TARGET_FILE:${TARGET}>
@@ -207,8 +257,129 @@ function(add_manual_test COMPONENT_NAME TARGET)
207257endfunction()
208258
209259
260+# add_meta_test(target)
261+#
262+# Adds a test target that will run one of our "meta" test targets, like
263+# xvfbuitests. This script will run the specified suite of tests on an
264+# installed system.
265+
266+function(add_meta_test TARGET_NAME)
267+ cmake_parse_arguments(TEST "SERIAL" "" "DEPENDS" ${ARGN})
268+
269+ add_custom_target(${TARGET_NAME})
270+
271+ set(filename "${CMAKE_BINARY_DIR}/tests/scripts/${TARGET_NAME}.sh")
272+ if(TEST_SERIAL)
273+ file(WRITE "${filename}" "#!/bin/sh\n\n")
274+ else()
275+ file(WRITE "${filename}" "#!/usr/bin/parallel --shebang --no-notice\n\n")
276+ endif()
277+
278+ add_meta_dependencies(${TARGET_NAME} DEPENDS ${TEST_DEPENDS})
279+ # else we will write the rest of the script as we add cmake targets
280+
281+ install(FILES "${filename}"
282+ PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE
283+ GROUP_EXECUTE GROUP_READ
284+ WORLD_EXECUTE WORLD_READ
285+ DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/scripts"
286+ )
287+endfunction()
288+
289+
210290################### INTERNAL ####################
211291
292+function(install_test_script TARGET_NAME)
293+ cmake_parse_arguments(TEST "" "" "COMMAND;ENVIRONMENT" ${ARGN})
294+
295+ # Now write the above test into a shell script that we can run on an
296+ # installed system.
297+ set(script "#!/bin/sh\n\nset -x\n\n")
298+ foreach(ONE_ENV ${TEST_ENVIRONMENT})
299+ set(script "${script}export ${ONE_ENV}\n")
300+ endforeach()
301+ set(script "${script}export UNITY_TESTING_DATADIR=\"${CMAKE_INSTALL_PREFIX}/${SHELL_APP_DIR}\"\n")
302+ set(script "${script}export UNITY_TESTING_LIBDIR=\"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}\"\n")
303+ set(script "${script}\n")
304+ set(script "${script}XML_ARGS=\n")
305+ set(script "${script}if [ -n \"\$ARTIFACTS_DIR\" ]; then\n")
306+ set(script "${script} XML_ARGS=\"@XML_ARGS@\"\n")
307+ set(script "${script} mkdir -p \"@XML_DIR@\"\n")
308+ set(script "${script} touch \"@XML_FILE@\"\n")
309+ set(script "${script}fi\n")
310+ set(script "${script}\n")
311+ foreach(ONE_CMD ${TEST_COMMAND})
312+ set(script "${script}'${ONE_CMD}' ")
313+ endforeach()
314+ set(script "${script}\"\$@\"") # Allow passing arguments if desired
315+
316+ set(filename "${CMAKE_BINARY_DIR}/tests/scripts/${TARGET_NAME}.sh")
317+
318+ # Generate script to file then read it back to resolve any generator
319+ # expressions before we try to replace paths.
320+ file(GENERATE
321+ OUTPUT "${filename}"
322+ CONTENT "${script}"
323+ )
324+
325+ # Do replacement at install time to save needless work and to make sure
326+ # we are modifying file after generate step above (which doesn't happen
327+ # immediately). We can't use a custom-defined function or macro here...
328+ # So instead we use a giant ugly code block.
329+
330+ # START OF CODE BLOCK --------------------------------------------------
331+ install(CODE "
332+ file(READ \"${filename}\" replacestr)
333+
334+ # Now some replacements...
335+ # tests like to write xml output to our builddir; we don't need that, but we do want them in ARTIFACTS_DIR
336+ string(REGEX MATCH \"( '--parameter')? '-o'( '--parameter')? '[^']*,xunitxml' \" xmlargs \"\${replacestr}\")
337+ string(REGEX REPLACE \"( '--parameter')? '-o'( '--parameter')? '[^']*,xunitxml' \" \" \\\$XML_ARGS \" replacestr \"\${replacestr}\")
338+ string(REGEX REPLACE \"'[^']*/tests/\" \"'\\\$ARTIFACTS_DIR/tests/\" xmlargs \"\${xmlargs}\")
339+ string(REGEX REPLACE \".*'([^']*),xunitxml'.*\" \"\\\\1\" xmlfile \"\${xmlargs}\")
340+ string(REGEX REPLACE \"(.*)/[^/]*\" \"\\\\1\" xmldir \"\${xmlfile}\")
341+ string(REGEX REPLACE \"'\" \"\" xmlargs \"\${xmlargs}\") # strip single quotes
342+ string(REGEX REPLACE \"@XML_ARGS@\" \"\${xmlargs}\" replacestr \"\${replacestr}\")
343+ string(REGEX REPLACE \"@XML_DIR@\" \"\${xmldir}\" replacestr \"\${replacestr}\")
344+ string(REGEX REPLACE \"@XML_FILE@\" \"\${xmlfile}\" replacestr \"\${replacestr}\")
345+ # replace build/source roots with their install paths
346+ string(REPLACE \"${CMAKE_BINARY_DIR}/libs\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}\" replacestr \"\${replacestr}\")
347+ string(REPLACE \"${CMAKE_BINARY_DIR}/plugins\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_INSTALL_QML}\" replacestr \"\${replacestr}\")
348+ string(REPLACE \"${CMAKE_BINARY_DIR}/tests/libs\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}/tests/libs\" replacestr \"\${replacestr}\")
349+ string(REPLACE \"${CMAKE_BINARY_DIR}/tests/mocks\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_INSTALL_QML}/mocks\" replacestr \"\${replacestr}\")
350+ string(REPLACE \"${CMAKE_BINARY_DIR}/tests/plugins\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}/tests/plugins\" replacestr \"\${replacestr}\")
351+ string(REPLACE \"${CMAKE_BINARY_DIR}/tests/qmltests\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}/tests/qmltests\" replacestr \"\${replacestr}\")
352+ string(REPLACE \"${CMAKE_BINARY_DIR}/tests/uqmlscene\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}\" replacestr \"\${replacestr}\")
353+ string(REPLACE \"${CMAKE_BINARY_DIR}/tests/utils/modules\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_INSTALL_QML}/utils\" replacestr \"\${replacestr}\")
354+ string(REPLACE \"${CMAKE_SOURCE_DIR}/tests/plugins\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_APP_DIR}/tests/plugins\" replacestr \"\${replacestr}\")
355+ string(REPLACE \"${CMAKE_SOURCE_DIR}/tests/qmltests\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_APP_DIR}/tests/qmltests\" replacestr \"\${replacestr}\")
356+
357+ file(WRITE \"${filename}\" \"\${replacestr}\")
358+ ")
359+ # END OF CODE BLOCK --------------------------------------------------
360+
361+ install(FILES "${filename}"
362+ PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE
363+ GROUP_EXECUTE GROUP_READ
364+ WORLD_EXECUTE WORLD_READ
365+ DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/scripts"
366+ )
367+endfunction()
368+
369+function(add_meta_dependencies UPSTREAM_TARGET)
370+ cmake_parse_arguments(TEST "" "" "DEPENDS" ${ARGN})
371+
372+ foreach(depend ${TEST_DEPENDS})
373+ add_dependencies(${UPSTREAM_TARGET} ${depend})
374+
375+ # add depend to the meta test script that we will install on system
376+ set(filename "${CMAKE_BINARY_DIR}/tests/scripts/${UPSTREAM_TARGET}.sh")
377+ if (EXISTS "${filename}")
378+ file(APPEND "${filename}" "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}/tests/scripts/${depend}.sh \"\$@\" 2>&1\n")
379+ endif()
380+ endforeach()
381+endfunction()
382+
212383# add_qmltest_target(target_name target
213384# COMMAND test_exe [arg1 [...]] # execute this test with arguments
214385# [...] # see above for available arguments:
@@ -231,6 +402,11 @@ function(add_qmltest_target TARGET_NAME TARGET)
231402 DEPENDS ${TARGET} ${QMLTEST_DEPENDS}
232403 )
233404
405+ install_test_script(${TARGET_NAME}
406+ ENVIRONMENT ${QMLTEST_ENVIRONMENT}
407+ COMMAND ${QMLTEST_COMMAND}
408+ )
409+
234410 if(QMLTEST_ADD_TEST)
235411 add_test(
236412 NAME ${TARGET_NAME}
@@ -248,7 +424,7 @@ function(add_qmltest_target TARGET_NAME TARGET)
248424 endif()
249425
250426 foreach(UPSTREAM_TARGET ${QMLTEST_TARGETS})
251− add_dependencies(${UPSTREAM_TARGET} ${TARGET_NAME})
427+ add_meta_dependencies(${UPSTREAM_TARGET} DEPENDS ${TARGET_NAME})
252428 endforeach()
253429endfunction()
254430
data/51-unity8-greeter.confnew file+2
@@ -0,0 +1,2 @@
1+[Seat:*]
2+greeter-session=unity8-greeter
data/CMakeLists.txt+9−6
@@ -1,24 +1,27 @@
11# generate desktop files
22configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY)
3−configure_file(${DASH_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop @ONLY)
43configure_file(${INDICATORS_CLIENT_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop @ONLY)
4+configure_file(${GREETER_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${GREETER_APP}.desktop @ONLY)
55
66# install desktop files
77install(FILES
88 ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
9− ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
109 ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop
1110 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
1211 )
1312
14−# install dash icon
1513install(FILES
16− ${CMAKE_CURRENT_SOURCE_DIR}/${DASH_APP}.png
17− DESTINATION ${SHELL_APP_DIR}/Dash/
14+ ${CMAKE_CURRENT_BINARY_DIR}/${GREETER_APP}.desktop
15+ DESTINATION ${CMAKE_INSTALL_DATADIR}/lightdm/greeters
16+ )
17+
18+install(FILES
19+ 51-unity8-greeter.conf
20+ DESTINATION ${CMAKE_INSTALL_DATADIR}/lightdm/lightdm.conf.d
1821 )
1922
2023add_custom_target(pkgversion ALL COMMAND dpkg-parsechangelog -l${CMAKE_SOURCE_DIR}/debian/changelog --show-field version > ${CMAKE_CURRENT_BINARY_DIR}/version)
2124
2225install(FILES com.canonical.Unity8.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
23−install(FILES unity8-dash.url-dispatcher DESTINATION ${CMAKE_INSTALL_DATADIR}/url-dispatcher/urls)
26+install(FILES com.canonical.Unity.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
2427install(FILES ${CMAKE_CURRENT_BINARY_DIR}/version DESTINATION ${CMAKE_INSTALL_LOCALSTATEDIR}/lib/unity8)
data/com.canonical.Unity.gschema.xmlnew file+255
@@ -0,0 +1,255 @@
1+<schemalist>
2+ <enum id="form-factor-enum">
3+ <value nick="Automatic" value="0" />
4+ <value nick="Desktop" value="1" />
5+ <value nick="Netbook" value="2" />
6+ <value nick="TV" value="3" />
7+ </enum>
8+ <enum id="home-expanded-enum">
9+ <value nick="Not Expanded" value="0" />
10+ <value nick="Expanded" value="1" />
11+ </enum>
12+ <enum id="launcher-position-enum">
13+ <value nick="Left" value="0" />
14+ <value nick="Bottom" value="1" />
15+ </enum>
16+ <enum id="desktop-type-enum">
17+ <value nick="Ubuntu" value="0" />
18+ <value nick="UbuntuKylin" value="1" />
19+ </enum>
20+
21+ <schema path="/com/canonical/unity/" id="com.canonical.Unity" gettext-domain="unity">
22+ <key enum="form-factor-enum" name="form-factor">
23+ <default>"Automatic"</default>
24+ <summary>The form factor Unity should target.</summary>
25+ <description>The form factor chosen will affect the size and appearance of the Dash, Launcher and also the Window Management behaviour.</description>
26+ </key>
27+ <key enum="home-expanded-enum" name="home-expanded">
28+ <default>"Expanded"</default>
29+ <summary>Whether the home screen should be expanded.</summary>
30+ <description>Whether the home screen should be expanded.</description>
31+ </key>
32+ <key enum="desktop-type-enum" name="desktop-type">
33+ <default>"Ubuntu"</default>
34+ <summary>The current desktop name.</summary>
35+ <description>The current desktop name.</description>
36+ </key>
37+ <key type="i" name="minimize-count">
38+ <default>0</default>
39+ <summary>Number of times a normal window has been minimized.</summary>
40+ <description>This is used to adjust the animation speed by making it progressively faster the more it is used.</description>
41+ </key>
42+ <key type="i" name="minimize-fast-duration">
43+ <default>300</default>
44+ <summary>The duration for the minimize animation when it is at its fastest setting.</summary>
45+ <description>This is the duration that the minimize animation will have when it has been used more than an number of times equal minimize-speed-threshold.</description>
46+ </key>
47+ <key type="i" name="minimize-slow-duration">
48+ <default>800</default>
49+ <summary>The duration for the minimize animation when it is at its slowest setting.</summary>
50+ <description>This is the duration that the minimize animation will have when it has never been used.</description>
51+ </key>
52+ <key type="i" name="minimize-speed-threshold">
53+ <default>100</default>
54+ <summary>The number of minimizations required to reach maximum speed.</summary>
55+ <description>The speed of the minimize animation will progressively get faster as minimize-count approaches this value.</description>
56+ </key>
57+ <key type="b" name="double-click-activate">
58+ <default>true</default>
59+ <summary>Enable/Disable dash result double-click activation.</summary>
60+ <description>This is used to enable/disable double-click result activation in the dash. Double-click to activate, single click preview</description>
61+ </key>
62+ <key type="b" name="integrated-menus">
63+ <default>false</default>
64+ <summary>Enable/Disable the integrated menus in Unity.</summary>
65+ <description>When this is enabled, the application menus will be shown
66+ on the window decoration, otherwise they will be always shown on the
67+ unity top panel</description>
68+ </key>
69+ <key type="u" name="show-menus-now-delay">
70+ <default>180</default>
71+ <range min="0" max="5000"/>
72+ <summary>Delay (in ms) before showing the menus when pressing Alt</summary>
73+ <description>This allows tune the delay before presenting unity menus
74+ (in non always-show-menus mode).</description>
75+ </key>
76+ <key type="b" name="always-show-menus">
77+ <default>false</default>
78+ <summary>Toggle the menu visibility based on mouse hovering.</summary>
79+ <description>When this is enabled, the application menus will be always
80+ shown (on the window decoration or in the unity panel, depending whether
81+ integrated menus are enabled), otherwise they will be shown only when
82+ the mouse cursor is over the relative mouse area.</description>
83+ </key>
84+ <key type="as" name="whitelist-repeated-keys">
85+ <default>[
86+ 'XF86KbdBrightnessUp',
87+ 'XF86KbdBrightnessDown',
88+ 'XF86MonBrightnessUp',
89+ 'XF86MonBrightnessDown',
90+ 'XF86AudioRaiseVolume',
91+ 'XF86AudioLowerVolume'
92+ ]</default>
93+ <summary>List of keycodes that should be processed even if auto-repated.</summary>
94+ <description>These keycodes are processed even if they are auto-repeated.</description>
95+ </key>
96+ <key type="b" name="pam-check-account-type">
97+ <default>false</default>
98+ <summary>Enable/Disable PAM account checking</summary>
99+ <description>Whether PAM should check the result of account modules
100+ when authenticating. Only do this if you have account
101+ configured properly on your system.</description>
102+ </key>
103+ <key type="b" name="lowgfx">
104+ <default>false</default>
105+ <summary>Enable/Disable Low Graphics Mode</summary>
106+ <description>Whether Unity runs in Low Graphics Mode.</description>
107+ </key>
108+ </schema>
109+ <schema path="/com/canonical/unity/interface/" id="com.canonical.Unity.Interface" gettext-domain="unity">
110+ <key type="d" name="text-scale-factor">
111+ <default>1.0</default>
112+ <range min="0.5" max="3.0"/>
113+ <summary>Font scaling for unity and applications.</summary>
114+ <description>This value defines the global font scaling used by both
115+ unity and applications. It will match the current system font scaling.</description>
116+ </key>
117+ <key type="d" name="cursor-scale-factor">
118+ <default>1.0</default>
119+ <range min="0.5" max="3.0"/>
120+ <summary>Mouse cursor scaling.</summary>
121+ <description>This value defines the global mouse cursor scaling used by both
122+ unity and applications. Changing this value allows to use a custom scaling
123+ for the mouse cursor.</description>
124+ </key>
125+ <key type="s" name="app-scale-factor-monitor">
126+ <default>''</default>
127+ <summary>The name of the monitor that controls the global app scaling factor.</summary>
128+ <description>This value defines the monitor that unity will use (if found) as reference
129+ for scaling all the applications.</description>
130+ </key>
131+ <key type="b" name="app-fallback-to-maximum-scale-factor">
132+ <default>true</default>
133+ <summary>Use the maximum per-monitor scale-factor as application scale factor if no target monitor is found.</summary>
134+ <description>When this is enabled, the applications scale factor will match
135+ the scale factor of the monitor with the greater value, in case the monitor
136+ defined in 'app-scale-factor-monitor' is not provided or available.</description>
137+ </key>
138+ </schema>
139+ <schema path="/com/canonical/unity/launcher/" id="com.canonical.Unity.Launcher" gettext-domain="unity">
140+ <key type="as" name="favorites">
141+ <default>[
142+ 'application://ubiquity.desktop',
143+ 'application://org.gnome.Nautilus.desktop',
144+ 'application://firefox.desktop',
145+ 'application://libreoffice-writer.desktop',
146+ 'application://libreoffice-calc.desktop',
147+ 'application://libreoffice-impress.desktop',
148+ 'application://org.gnome.Software.desktop',
149+ 'application://ubuntu-amazon-default.desktop',
150+ 'application://unity-control-center.desktop',
151+ 'unity://running-apps',
152+ 'unity://expo-icon',
153+ 'unity://devices'
154+ ]</default>
155+ <summary>List of items that should be shown by default in the launcher</summary>
156+ <description>These items can be: application://desktop-id.desktop, device://uiid and unity://special-id (including: unity://running-apps (icons of running applications) unity://devices (icons of attached devices), unity://expo-icon (icon of the workspace switcher) and unity://desktop-icon (the show-desktop icon)); the order of this list determines the launcher item's position.</description>
157+ </key>
158+ <key type="as" name="items">
159+ <default>[
160+ 'application:///dialer-app.desktop',
161+ 'application:///messaging-app.desktop',
162+ 'application:///address-book-app.desktop',
163+ 'application:///ubuntu-system-settings.desktop',
164+ 'appid://openstore.openstore-team/openstore/current-user-version',
165+ 'appid://com.ubuntu.camera/camera/current-user-version',
166+ 'appid://com.ubuntu.gallery/gallery/current-user-version',
167+ 'application:///morph-browser.desktop'
168+ ]</default>
169+ <summary>List of items that should be shown by default in the launcher</summary>
170+ <description>These items can be: application:///desktop-id.desktop or appid://package/app/current-user-version.</description>
171+ </key>
172+ <key type="s" name="favorite-migration">
173+ <default>''</default>
174+ <summary>Version of last migration done</summary>
175+ <description>This is a detection key for the favorite migration script to know whether the needed migration is done or not.</description>
176+ </key>
177+ <key enum="launcher-position-enum" name="launcher-position">
178+ <default>"Left"</default>
179+ <summary>The position of launcher.</summary>
180+ <description>The position of launcher.</description>
181+ </key>
182+ </schema>
183+ <schema path="/com/canonical/unity/devices/" id="com.canonical.Unity.Devices" gettext-domain="unity">
184+ <key type="as" name="blacklist">
185+ <default>[]</default>
186+ <summary>List of device uuid blacklist from the launcher.</summary>
187+ <description>These devices are not shown in the launcher by default.</description>
188+ </key>
189+ </schema>
190+ <schema path="/com/canonical/unity/dash/" id="com.canonical.Unity.Dash" gettext-domain="unity">
191+ <key type="as" name="scopes">
192+ <default>[ 'home.scope', 'applications.scope', 'files.scope', 'video.scope', 'music.scope', 'photos.scope', 'social.scope' ]</default>
193+ <summary>List of scope ids specifying which scopes should be created and the order to display them in.</summary>
194+ <description>The scopes listed in the scope bar will be ordered according to this list.</description>
195+ </key>
196+ <key type="as" name="favorite-scopes">
197+ <default>[ 'scope://clickscope', 'scope://musicaggregator', 'scope://videoaggregator' ]</default>
198+ <summary>List of scope queries specifying what should be displayed in the dash.</summary>
199+ <description>List of favorite scopes displayed in the dash.</description>
200+ </key>
201+ </schema>
202+ <schema path="/com/canonical/unity/decorations/" id="com.canonical.Unity.Decorations" gettext-domain="unity">
203+ <key type="u" name="grab-wait">
204+ <default>175</default>
205+ <range min="0" max="1000"/>
206+ <summary>Milliseconds to wait before considering a mouse pressure a grab</summary>
207+ <description>The number of ms to wait before starting the window movement (and then
208+ showing the proper mouse cursor, and grabbing the window)</description>
209+ </key>
210+ </schema>
211+ <schema path="/com/canonical/unity/integrated-menus/" id="com.canonical.Unity.IntegratedMenus" gettext-domain="unity">
212+ <key type="u" name="click-movement-threshold">
213+ <default>15</default>
214+ <range min="0" max="30"/>
215+ <summary>Number of pixels to ignore on mouse pressure</summary>
216+ <description>This value define how many pixels the user can move the mouse
217+ when holding the mouse button, before we consider his action a movement
218+ (to grab the window).</description>
219+ </key>
220+ <key type="u" name="double-click-wait">
221+ <default>0</default>
222+ <range min="0" max="300"/>
223+ <summary>Milliseconds to wait before activating a menu after mouse release</summary>
224+ <description>The number of ms to wait after a mouse button release event before considering
225+ it a click. When this value is greater than 0, then it's possible to maximize
226+ a window by double-clicking on its menus if the second click happens before the
227+ specified value of ms is elapsed</description>
228+ </key>
229+ <key type="b" name="unfocused-windows-popup">
230+ <default>true</default>
231+ <summary>Whether to pop-up a menu when clicking over unfocused windows entries</summary>
232+ <description>By disabling this setting you can make unity to only focus a window
233+ when clicking over unfocused menu entries</description>
234+ </key>
235+ </schema>
236+ <schema path="/com/canonical/unity/gestures/" id="com.canonical.Unity.Gestures" gettext-domain="unity">
237+ <key type="b" name="launcher-drag">
238+ <default>true</default>
239+ <summary>Multi-touch gesture to reveal the launcher.</summary>
240+ <description>When this is enabled, a 4 finger swipe from left to right will reveal launcher,
241+ provided that the launcher is set to auto-hide.</description>
242+ </key>
243+ <key type="b" name="dash-tap">
244+ <default>true</default>
245+ <summary>Multi-touch gesture to open the dash.</summary>
246+ <description>When this is enabled, a 4 finger tap will open the dash.</description>
247+ </key>
248+ <key type="b" name="windows-drag-pinch">
249+ <default>true</default>
250+ <summary>Multi-touch gestures to manage the windows.</summary>
251+ <description>When this is enabled, 3 finger gestures such as drag, and pinch, will
252+ help manage the windows.</description>
253+ </key>
254+ </schema>
255+</schemalist>
data/com.canonical.Unity8.gschema.xml+39−3
@@ -11,8 +11,8 @@
1111 <summary>The usage mode.</summary>
1212 <description>The usage mode chosen will affect the Window Management behaviour.</description>
1313 </key>
14− <key type="y" name="edge-barrier-sensitivity">
15− <default>35</default>
14+ <key type="u" name="edge-barrier-sensitivity">
15+ <default>50</default>
1616 <range min="1" max="100"/>
1717 <summary>Sensitivity of screen edge barriers for the mouse pointer.</summary>
1818 <description>Some UI actions like revealing the launcher or the applications spread are triggered by pushing the mouse pointer against a screen edge. This key defines how much you have to push in order to trigger the associated action.</description>
@@ -23,10 +23,46 @@
2323 <description>How much you have to push (in grid units)the mouse against an edge barrier when sensibility is 100.</description>
2424 </key>
2525 <key type="u" name="edge-barrier-max-push">
26− <default>60</default>
26+ <default>120</default>
2727 <summary>Maximum push needed to overcome edge barrier</summary>
2828 <description>How much you have to push (in grid units) the mouse against an edge barrier when sensibility is 1.</description>
2929 </key>
30+ <key type="u" name="edge-drag-width">
31+ <default>2</default>
32+ <summary>The width of the edge drag areas</summary>
33+ <description>How big (in grid units) the edge-drag sensitive area should be.</description>
34+ </key>
35+ <key type="b" name="autohide-launcher">
36+ <default>false</default>
37+ <summary>Autohide the launcher</summary>
38+ <description>This will only be applied in windowed mode. In staged mode, the launcher will always hide.</description>
39+ </key>
40+ <key type="u" name="launcher-width">
41+ <default>8</default>
42+ <range min="6" max="12"/>
43+ <summary>Width of the launcher in grid units.</summary>
44+ <description>Changes the width of the launcher in all usage modes.</description>
45+ </key>
46+ <key type="b" name="enable-indicator-menu">
47+ <default>true</default>
48+ <summary>Enable or disable the indicator pull down menus</summary>
49+ <description>Toggle the availability of the indicator pull down menus</description>
50+ </key>
51+ <key type="s" name="appstore-uri">
52+ <default>'appid://openstore.openstore-team/openstore/current-user-version'</default>
53+ <summary>The uri to the app store</summary>
54+ <description>This will be used whenever the user triggers an action to open the app store.</description>
55+ </key>
56+ <key type="b" name="always-show-osk">
57+ <default>false</default>
58+ <summary>Force showing/hiding the OSK</summary>
59+ <description>Toggle the visibility of the On Screen Keyboard unconditionally</description>
60+ </key>
61+ <key type="b" name="osk-switch-visible">
62+ <default>false</default>
63+ <summary>Whether the OSK switch should be visible</summary>
64+ <description>Toggle the visibility of the OSK switch</description>
65+ </key>
3066 </schema>
3167
3268 <schema path="/com/canonical/unity8/greeter/" id="com.canonical.Unity8.Greeter" gettext-domain="unity8">
data/devices.confnew file+30
@@ -0,0 +1,30 @@
1+# This file can hold multiple device configs. Devices are separated by sections.
2+#
3+# SupportedOrientations holds a list of all enabled orientations. A standard
4+# phone will usually have Portrait,Landcape,InvertedLandscape in order to
5+# disable upside down usage.
6+#
7+# PrimaryOrientation gives the orientation the device will start up with
8+# when there is no orientations sensor input available (yet) or lock to
9+# when an application specifies to be locked to PrimaryOrientation.
10+#
11+# The other Orientation settings can be used to re-map the orientations.
12+# A device might be used with different orientations than how the screen
13+# is physically mounted on the hardware.
14+#
15+# Category can be phone, tablet, or desktop. This option determines
16+# whether the side stage is shown (tablet) or not (phone). Using
17+# desktop will load the shell in windowed mode. Note that the user
18+# can override/change this by connecting input hardware or change
19+# user settings.
20+#
21+# Any options not listed will default to the values of the example below.
22+
23+# [devicename]
24+# SupportedOrientations=Portrait,InvertedPortrait,Landscape,InvertedLandscape
25+# PrimaryOrientation=PrimaryOrienation
26+# PortraitOrientation=Portrait
27+# InvertedPortraitOrientation=InvertedPortrait
28+# LandscapeOrientation=Landscape
29+# InvertedLandscapeOrientation=InvertedLandscape
30+# Category=phone
data/test.sensorsnew file+12
@@ -0,0 +1,12 @@
1+create light 0 10 1
2+create accel 0 1000 0.1
3+create proximity
4+
5+200 proximity near
6+500 light 5
7+# simulate crash on the ground
8+500 accel 0.2 0.1 10
9+100 accel 0.2 0.2 1000
10+20 accel 0 0 0
11+10 proximity far
12+10 light 10
data/unity8-dash.confdeleted−24
@@ -1,24 +0,0 @@
1−description "Unity Shell v8 Dash"
2−author "Michael Zanetti <michael.zanetti@canonical.com>"
3−
4−emits scope-ui-starting
5−
6−start on started unity8
7−stop on stopping unity8
8−
9−kill timeout 120
10−
11−# Focused app is 100 so we want to be less likely to get
12−# killed than the focused app but more than Unity8
13−
14−oom score 50
15−
16−respawn
17−
18−env APP_ID=unity8-dash
19−
20−pre-start script
21− initctl emit scope-ui-starting
22−end script
23−
24−exec ${BINARY:-unity8-dash} $ARGS --desktop_file_hint=/usr/share/applications/unity8-dash.desktop
data/unity8-dash.desktop.indeleted−10
@@ -1,10 +0,0 @@
1−[Desktop Entry]
2−Type=Application
3−Name=Scopes
4−Comment=An interface for using the Scopes system
5−Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8-dash
6−Terminal=false
7−Icon=@CMAKE_INSTALL_PREFIX@/@SHELL_APP_DIR@/Dash/unity8-dash.png
8−NoDisplay=true
9−X-Ubuntu-Touch=true
10−X-Ubuntu-Supported-Orientations=primary
data/unity8-dash.pngdeleted

Binary file not shown.

data/unity8-dash.svgdeleted−326
@@ -1,326 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2−<!-- Created with Inkscape (http://www.inkscape.org/) -->
3−
4−<svg
5− xmlns:dc="http://purl.org/dc/elements/1.1/"
6− xmlns:cc="http://creativecommons.org/ns#"
7− xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8− xmlns:svg="http://www.w3.org/2000/svg"
9− xmlns="http://www.w3.org/2000/svg"
10− xmlns:xlink="http://www.w3.org/1999/xlink"
11− xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
12− xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13− viewBox="0 0 512 512"
14− style="enable-background:new"
15− inkscape:export-ydpi="180"
16− inkscape:export-xdpi="180"
17− inkscape:export-filename="app_shape02.png"
18− sodipodi:docname="apps-scope.svg"
19− inkscape:version="0.91+devel r"
20− version="1.1"
21− id="svg3336"
22− height="512"
23− width="512">
24− <sodipodi:namedview
25− inkscape:snap-global="false"
26− fit-margin-bottom="18"
27− fit-margin-right="0"
28− fit-margin-left="0"
29− fit-margin-top="18"
30− inkscape:snap-grids="true"
31− inkscape:guide-bbox="true"
32− showguides="false"
33− inkscape:snap-center="true"
34− inkscape:snap-object-midpoints="true"
35− inkscape:snap-midpoints="true"
36− inkscape:snap-smooth-nodes="true"
37− inkscape:snap-intersection-paths="true"
38− inkscape:object-nodes="true"
39− inkscape:object-paths="true"
40− inkscape:snap-bbox-midpoints="true"
41− inkscape:snap-bbox-edge-midpoints="true"
42− inkscape:bbox-nodes="true"
43− inkscape:bbox-paths="true"
44− inkscape:snap-bbox="true"
45− showborder="true"
46− inkscape:showpageshadow="false"
47− inkscape:snap-page="true"
48− inkscape:window-maximized="1"
49− inkscape:window-y="24"
50− inkscape:window-x="0"
51− inkscape:window-height="1029"
52− inkscape:window-width="1920"
53− showgrid="false"
54− inkscape:current-layer="layer3"
55− inkscape:document-units="px"
56− inkscape:cy="204.04409"
57− inkscape:cx="-384.5809"
58− inkscape:zoom="0.64"
59− inkscape:pageshadow="2"
60− inkscape:pageopacity="0"
61− borderopacity="1.0"
62− bordercolor="#666666"
63− pagecolor="#4f4f4f"
64− id="base">
65− <inkscape:grid
66− type="xygrid"
67− id="grid811"
68− originx="0"
69− originy="15.999999"
70− visible="true"
71− enabled="true" />
72− <sodipodi:guide
73− orientation="1,0"
74− position="104,176"
75− id="guide819" />
76− <sodipodi:guide
77− orientation="1,0"
78− position="120,160"
79− id="guide821" />
80− <sodipodi:guide
81− orientation="1,0"
82− position="392,144"
83− id="guide823" />
84− <sodipodi:guide
85− orientation="1,0"
86− position="408,144"
87− id="guide825" />
88− <sodipodi:guide
89− orientation="0,1"
90− position="328,408"
91− id="guide827" />
92− <sodipodi:guide
93− orientation="0,1"
94− position="336,392"
95− id="guide829" />
96− <sodipodi:guide
97− orientation="0,1"
98− position="176,120"
99− id="guide831" />
100− <sodipodi:guide
101− orientation="0,1"
102− position="216,104"
103− id="guide833" />
104− <inkscape:grid
105− type="axonomgrid"
106− id="grid835"
107− units="px"
108− empspacing="60"
109− gridanglex="42.9"
110− gridanglez="42.9"
111− spacingy="3.522px"
112− enabled="false"
113− originx="0"
114− originy="16.999996" />
115− <sodipodi:guide
116− orientation="0,1"
117− position="344,376"
118− id="guide4126" />
119− <sodipodi:guide
120− orientation="0,1"
121− position="160,136"
122− id="guide4128" />
123− <sodipodi:guide
124− orientation="1,0"
125− position="136,96"
126− id="guide4130" />
127− <sodipodi:guide
128− orientation="1,0"
129− position="376,136"
130− id="guide4134" />
131− <sodipodi:guide
132− orientation="-0.70710678,0.70710678"
133− position="544,544"
134− id="guide4136" />
135− <sodipodi:guide
136− orientation="1,0"
137− position="256,-32.000001"
138− id="guide4138" />
139− <sodipodi:guide
140− orientation="0,1"
141− position="544,256"
142− id="guide4140" />
143− <sodipodi:guide
144− orientation="0.70710678,0.70710678"
145− position="544,-32.000001"
146− id="guide4142" />
147− <sodipodi:guide
148− orientation="0,1"
149− position="248,15.999999"
150− id="guide4152" />
151− <sodipodi:guide
152− orientation="0,1"
153− position="336,496"
154− id="guide4154" />
155− <sodipodi:guide
156− position="344,96"
157− orientation="1,0"
158− id="guide4361" />
159− <sodipodi:guide
160− position="576,168"
161− orientation="0,1"
162− id="guide4363" />
163− <sodipodi:guide
164− position="168,192"
165− orientation="1,0"
166− id="guide4229" />
167− <sodipodi:guide
168− position="312,344"
169− orientation="0,1"
170− id="guide4233" />
171− <sodipodi:guide
172− position="180.48,-96"
173− orientation="0,1"
174− id="guide4235" />
175− </sodipodi:namedview>
176− <defs
177− id="defs3338">
178− <linearGradient
179− inkscape:collect="always"
180− id="linearGradient4203">
181− <stop
182− style="stop-color:#ea5420;stop-opacity:1"
183− offset="0"
184− id="stop4205" />
185− <stop
186− style="stop-color:#f37e40;stop-opacity:1"
187− offset="1"
188− id="stop4207" />
189− </linearGradient>
190− <clipPath
191− clipPathUnits="userSpaceOnUse"
192− id="clipPath4755">
193− <path
194− style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.24899998;fill:#5e2c73;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
195− d="M 360,50 594,284 V 215.89844 C 594,70.73665 573.2426,50 427.94531,50 Z"
196− id="path4757"
197− inkscape:connector-curvature="0" />
198− </clipPath>
199− <clipPath
200− clipPathUnits="userSpaceOnUse"
201− id="clipPath4767">
202− <path
203− style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#f6f6f6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
204− d="M 543.8125,454.1875 312.18945,685.81055 367.94531,681 C 512.70468,668.50896 526.55393,654.72881 539,510.10156 Z"
205− id="path4769"
206− inkscape:connector-curvature="0" />
207− </clipPath>
208− <linearGradient
209− inkscape:collect="always"
210− xlink:href="#linearGradient4203"
211− id="linearGradient4209"
212− x1="167.5"
213− y1="17.25"
214− x2="343.25"
215− y2="491"
216− gradientUnits="userSpaceOnUse" />
217− <filter
218− inkscape:collect="always"
219− style="color-interpolation-filters:sRGB"
220− id="filter4220"
221− x="-0.012"
222− width="1.024"
223− y="-0.012"
224− height="1.024">
225− <feGaussianBlur
226− inkscape:collect="always"
227− stdDeviation="1.4390401"
228− id="feGaussianBlur4222" />
229− </filter>
230− <linearGradient
231− inkscape:collect="always"
232− xlink:href="#linearGradient4226"
233− id="linearGradient4232"
234− x1="255.99998"
235− y1="-255.99998"
236− x2="405.35773"
237− y2="-255.99998"
238− gradientUnits="userSpaceOnUse"
239− spreadMethod="reflect" />
240− <linearGradient
241− inkscape:collect="always"
242− id="linearGradient4226">
243− <stop
244− style="stop-color:#a73812;stop-opacity:1"
245− offset="0"
246− id="stop4228" />
247− <stop
248− style="stop-color:#973310;stop-opacity:0"
249− offset="1"
250− id="stop4230" />
251− </linearGradient>
252− <filter
253− inkscape:collect="always"
254− style="color-interpolation-filters:sRGB"
255− id="filter4234"
256− x="-0.096000001"
257− width="1.192"
258− y="-0.096000001"
259− height="1.192">
260− <feGaussianBlur
261− inkscape:collect="always"
262− stdDeviation="11.512321"
263− id="feGaussianBlur4236" />
264− </filter>
265− </defs>
266− <metadata
267− id="metadata3341">
268− <rdf:RDF>
269− <cc:Work
270− rdf:about="">
271− <dc:format>image/svg+xml</dc:format>
272− <dc:type
273− rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
274− <dc:title></dc:title>
275− </cc:Work>
276− </rdf:RDF>
277− </metadata>
278− <g
279− inkscape:groupmode="layer"
280− id="layer3"
281− inkscape:label="Background">
282− <path
283− style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient4209);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate"
284− d="M 0 0 L 0 183.89844 L 0 328.10156 L 0 512 L 512 512 L 512 328.10156 L 512 183.89844 L 512 0 L 0 0 z "
285− id="rect4158" />
286− <path
287− style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
288− d="M 0 256 L 0 328.10156 L 0 462.53516 C 0 479.69677 0.052846476 496.03174 0.13085938 512 L 511.86914 512 C 511.94715 496.03174 512 479.69677 512 462.53516 L 512 256 L 0 256 z "
289− id="rect4286" />
290− </g>
291− <g
292− inkscape:groupmode="layer"
293− id="layer1"
294− inkscape:label="Pictogram"
295− style="display:inline"
296− transform="translate(-32,-32)">
297− <circle
298− style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.4;fill:#d04616;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.99999952;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;filter:url(#filter4220);enable-background:accumulate"
299− id="circle4218"
300− cx="258"
301− cy="-256"
302− r="143.90401"
303− transform="rotate(90,-7.1132638e-7,31.999996)" />
304− <circle
305− transform="rotate(90,-7.1132638e-7,31.999996)"
306− r="143.90401"
307− cy="-256"
308− cx="258"
309− id="circle4224"
310− style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient4232);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.99999952;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;filter:url(#filter4234);enable-background:accumulate" />
311− <circle
312− transform="rotate(90)"
313− r="143.90401"
314− cy="-288"
315− cx="288"
316− id="circle4206"
317− style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.99999952;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
318− <path
319− style="display:inline;fill:#ea5420;fill-opacity:1;stroke-width:2.9398191;enable-background:new"
320− id="path4258"
321− d="m 193.9963,269.54024 c -10.19878,0 -18.46137,8.2634 -18.46137,18.46139 0,10.19309 8.26259,18.45568 18.46137,18.45568 10.19311,0 18.45569,-8.26259 18.45569,-18.45568 0,-10.19799 -8.26258,-18.46139 -18.45569,-18.46139 z m 131.78525,83.88906 c -8.82832,5.09898 -11.85536,16.38129 -6.75557,25.20475 5.0933,8.82834 16.37561,11.85455 25.20393,6.75556 8.82752,-5.0933 11.85457,-16.37561 6.75559,-25.20475 -5.0933,-8.82263 -16.38212,-11.84887 -25.20395,-6.75556 z m -91.69319,-65.42767 c 0,-18.24028 9.05999,-34.35498 22.92309,-44.11321 l -13.49406,-22.6012 c -16.14883,10.79461 -28.16435,27.28971 -33.15766,46.60863 5.82648,4.75434 9.55584,11.99194 9.55584,20.10497 0,8.10813 -3.72936,15.34572 -9.55584,20.10006 4.98681,19.32463 17.00232,35.82055 33.15766,46.61514 l 13.49406,-22.60689 c -13.8631,-9.75253 -22.92309,-25.86641 -22.92309,-44.1075 z m 53.91207,-53.91776 c 28.16514,0 51.27274,21.59491 53.69828,49.13495 l 26.30048,-0.38772 c -1.29405,-20.33173 -10.17604,-38.58421 -23.82372,-52.00594 -7.01814,2.65149 -15.12464,2.2459 -22.13139,-1.79314 -7.01894,-4.0504 -11.41969,-10.88319 -12.62271,-18.30044 -6.8214,-1.88254 -14.00046,-2.91323 -21.42257,-2.91323 -12.75925,0 -24.82271,2.99695 -35.53359,8.29836 l 12.82509,22.98243 c 6.89944,-3.21075 14.5963,-5.01526 22.71013,-5.01526 z m 0,107.82982 c -8.11383,0 -15.81069,-1.80533 -22.70931,-5.01528 l -12.82511,22.98163 c 10.71088,5.3079 22.77434,8.30568 35.53442,8.30568 7.42211,0 14.60118,-1.0315 21.42177,-2.91975 1.20301,-7.41724 5.60537,-14.24352 12.6227,-18.30125 7.01161,-4.04555 15.11326,-4.44382 22.13137,-1.79232 13.64769,-13.42174 22.52968,-31.67421 23.82372,-52.00595 l -26.30696,-0.38772 c -2.41986,27.54738 -25.52665,49.13496 -53.6926,49.13496 z m 37.77461,-119.35113 c 8.82834,5.09818 20.11145,2.07845 25.20475,-6.74987 5.099,-8.82833 2.07928,-20.11145 -6.74988,-25.21126 -8.82832,-5.0933 -20.11063,-2.06705 -25.21125,6.76127 -5.09247,8.82345 -2.06625,20.10657 6.75638,25.19986 z"
322− inkscape:connector-curvature="0"
323− inkscape:transform-center-x="16.232534"
324− inkscape:transform-center-y="-0.0024900663" />
325− </g>
326−</svg>
data/unity8-dash.url-dispatcherdeleted−6
@@ -1,6 +0,0 @@
1−[
2− {
3− "protocol": "scope"
4− }
5−]
6−
data/unity8-filewatcher.conf+5
@@ -1,6 +1,11 @@
11description "File system watcher for unity8"
22author "Michael Zanetti <michael.zanetti@canonical.com>"
33
4+# This method of updating the launcher will not work in our new snappy world,
5+# neither for snaps installed in the system nor if we are running inside a snap.
6+# Plus it hardcodes the phablet user... To be replaced once bug 1630997 is
7+# fixed in ubuntu-app-launch.
8+
49# Workaround for bug 1360208. ~ and * in one expression doesn't work currently
510start on (file FILE=/home/phablet/.local/share/applications/*.desktop) or (file FILE=/usr/share/applications/*.desktop)
611
data/unity8-greeter-init.confnew file+12
@@ -0,0 +1,12 @@
1+description "Unity 8 Greeter initialization"
2+author "Michael Terry <mterry@ubuntu.com>"
3+
4+start on unity8-greeter-started
5+task
6+emits indicator-services-start
7+
8+script
9+ start --no-wait ofono-setup || true
10+ initctl emit --no-wait indicator-services-start || true
11+ start --no-wait maliit-server || true
12+end script
data/unity8-greeter-wrappernew file+109
@@ -0,0 +1,109 @@
1+#!/bin/sh
2+# -*- Mode: sh; indent-tabs-mode: nil; tab-width: 4 -*-
3+#
4+# Copyright (C) 2011,2013,2016 Canonical Ltd
5+#
6+# This program is free software: you can redistribute it and/or modify it under
7+# the terms of the GNU General Public License as published by the Free Software
8+# Foundation, version 3 of the License.
9+#
10+# See http://www.gnu.org/copyleft/gpl.html the full text of the license.
11+
12+# This wrapper merely ensures that init and friends live only as long as this
13+# script does. Otherwise, it's very easy for some processes to not notice that
14+# the session died. We could try to do this in-process, but we want to do this
15+# cleanup even if the greeter aborts.
16+
17+trap cleanup TERM EXIT
18+
19+cleanup()
20+{
21+ trap - TERM EXIT
22+ # Kill upstart and indicators
23+ if [ -n "$INIT_PID" ]; then
24+ kill "$INIT_PID"
25+ fi
26+ if [ -n "$CMD_PID" ]; then
27+ kill "$CMD_PID"
28+ fi
29+ exit 0
30+}
31+
32+set_greeter_var()
33+{
34+ export "$1=$2"
35+ gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "{'$1': '$2'}"
36+ if [ -n "$INIT_PID" ]; then
37+ initctl set-env --global "$1=$2"
38+ fi
39+}
40+
41+SUB_SOCKET=$XDG_RUNTIME_DIR/mir_socket
42+rm -f $SUB_SOCKET # clear socket in case we were hard shut down
43+
44+echo "DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS}" >"$XDG_RUNTIME_DIR/dbus-session"
45+
46+# If touch session script (which sets up grid units and mir variables) is available, use it
47+TOUCH_WRAPPER=
48+if which ubuntu-touch-session >/dev/null; then
49+ TOUCH_WRAPPER=ubuntu-touch-session
50+fi
51+
52+# Advertise as a unity8 session, so that indicator-network will start.
53+export XDG_SESSION_DESKTOP=unity8
54+export DESKTOP_SESSION=$XDG_SESSION_DESKTOP
55+
56+set_greeter_var QT_IM_MODULE maliitphablet
57+set_greeter_var QT_QPA_PLATFORM ubuntumirclient
58+
59+# We disable ofono using pulse. It causes problems with racing with the user's
60+# pulse. We need to come up with a better long-term fix for this, because we
61+# eventually need the greeter to play ringtones for users that aren't logged in.
62+set_greeter_var PA_DISABLED 1
63+
64+# Normal unity8 sessions are entirely driven by Upstart. But greeters
65+# are special. They need access to the file descriptors that lightdm
66+# creates for them and don't want to start all the services that a normal
67+# session would. So it's inconvenient to live within an upstart session.
68+# But... we still want to use Upstart for some services. So launch here.
69+MIR_SOCKET=$SUB_SOCKET $TOUCH_WRAPPER upstart --user --no-startup-event &
70+INIT_PID=$!
71+while [ ! -e "$XDG_RUNTIME_DIR/upstart/sessions/$INIT_PID.session" ]; do sleep 0.1; done
72+. "$XDG_RUNTIME_DIR/upstart/sessions/$INIT_PID.session"
73+export UPSTART_SESSION
74+
75+# Connect upstart to system, but do first command in a loop to avoid any
76+# race condition between the session file above being written and upstart being
77+# ready to handle requests.
78+while ! initctl notify-dbus-address "$DBUS_SESSION_BUS_ADDRESS"; do sleep 0.1; done
79+initctl start notify-cgmanager
80+
81+# Start any pre-greeter tasks if needed (like wizard)
82+initctl emit unity8-greeter-starting
83+
84+# Define language here for phone if available. When phone user switches their
85+# language, they expect that to affect the greeter too. But the user doesn't
86+# have permission to switch system language, only their own. So we notice if
87+# the phablet user exists and use their language if so. TODO: talk to design
88+# about whether we should switch language on fly as users are selected (this
89+# is very hard to do technically).
90+#
91+# Do this after unity8-greeter-starting, in case a customization upstart job
92+# changes language.
93+if [ "$(id -u phablet 2>/dev/null)" = "32011" ]; then
94+ USER_LANG=$(gdbus call --system --dest org.freedesktop.Accounts --object-path /org/freedesktop/Accounts/User32011 --method org.freedesktop.DBus.Properties.Get org.freedesktop.Accounts.User Language | cut -d\' -f2)
95+ if [ -n "$USER_LANG" ]; then
96+ set_greeter_var LANGUAGE "$USER_LANG"
97+ fi
98+ USER_LOCALE=$(gdbus call --system --dest org.freedesktop.Accounts --object-path /org/freedesktop/Accounts/User32011 --method org.freedesktop.DBus.Properties.Get org.freedesktop.Accounts.User FormatsLocale | cut -d\' -f2)
99+ if [ -n "$USER_LOCALE" ]; then
100+ set_greeter_var LANG "$USER_LOCALE"
101+ set_greeter_var LC_ALL "$USER_LOCALE"
102+ fi
103+fi
104+
105+# And finally actually start the greeter
106+exec env MIR_SERVER_FILE=$SUB_SOCKET $TOUCH_WRAPPER $@ &
107+CMD_PID=$!
108+wait $CMD_PID
109+CMD_PID=
data/unity8-greeter.desktop.innew file+7
@@ -0,0 +1,7 @@
1+[Desktop Entry]
2+Type=Application
3+Name=Unity 8 Greeter
4+Comment=The converged Unity shell's Greeter
5+Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8-greeter-wrapper @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8 --mode=greeter
6+X-LightDM-Session-Type=mir
7+X-Ubuntu-Touch=true
data/unity8-greeter.pklanew file+44
@@ -0,0 +1,44 @@
1+# DO NOT EDIT THIS FILE, it will be overwritten on update
2+# Place your local configurations under /etc/polkit-1/localauthority/
3+
4+[Disable Controlling of Network Devices]
5+Identity=unix-user:lightdm
6+Action=org.freedesktop.NetworkManager.enable-disable-network;org.freedesktop.NetworkManager.enable-disable-wifi;org.freedesktop.NetworkManager.enable-disable-wwan;org.freedesktop.NetworkManager.enable-disable-wimax;
7+ResultActive=no
8+ResultInactive=no
9+ResultsAny=no
10+
11+[Disable Sleep and Wake]
12+Identity=unix-user:lightdm
13+Action=org.freedesktop.NetworkManager.sleep-wake
14+ResultActive=no
15+ResultInactive=no
16+ResultsAny=no
17+
18+[Disable WiFi Sharing]
19+Identity=unix-user:lightdm
20+Action=org.freedesktop.NetworkManager.wifi.share.protected;org.freedesktop.NetworkManager.wifi.share.open
21+ResultActive=no
22+ResultInactive=no
23+ResultsAny=no
24+
25+[Disable Settings Modifications]
26+Identity=unix-user:lightdm
27+Action=org.freedesktop.NetworkManager.settings.modify.own;org.freedesktop.NetworkManager.settings.modify.system;org.freedesktop.NetworkManager.settings.modify.hostname
28+ResultActive=no
29+ResultInactive=no
30+ResultsAny=no
31+
32+[Disable User Connections]
33+Identity=unix-user:lightdm
34+Action=org.freedesktop.NetworkManager.use-user-connections
35+ResultActive=no
36+ResultInactive=no
37+ResultsAny=no
38+
39+[Enable Controlling of Network Connections]
40+Identity=unix-user:lightdm
41+Action=org.freedesktop.NetworkManager.network-control
42+ResultActive=yes
43+ResultInactive=no
44+ResultsAny=no
data/unity8.conf+57−26
@@ -2,37 +2,51 @@ description "Unity Shell v8"
22author "Ricardo Mendoza <ricmm@ubuntu.com>"
33
44emits indicator-services-start
5+emits indicator-services-end
56
6−start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=unity8-mir)) and started dbus
7+start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=unity8-mir) or (xsession SESSION=unity8)) and started dbus
78stop on desktop-end
89
910kill timeout 120
1011
12+#
13+# Ensure the shell always gets unthrottled touch events, so that applications
14+# who want full speed low-latency input can get it (LP: #1497105) and so that
15+# apps can use QML touch compression safely (the QML touch compression
16+# algorithm does not support nesting well - LP: #1486341, LP: #1556763 - so
17+# must be fed by the raw input event stream from Unity8).
18+#
19+env QML_NO_TOUCH_COMPRESSION=1
20+
1121respawn
1222expect stop
1323
24+# FIXME Create an autopilot test that makes sure start+stop and restart
25+# work fine at least 2 times
26+
1427pre-start script
1528 # Tell unity-mir to raise SIGSTOP after we start
1629 initctl set-env UNITY_MIR_EMITS_SIGSTOP=1
1730
18− if [ -n "$MIR_SOCKET" ]; then
19− # FIXME Create an autopilot test that makes sure start+stop and restart
20− # work fine at least 2 times
21− # Save original value of MIR_SOCKET in case we are stopped,
22− # as we modify the variable for future jobs, including ourself.
23− UNITY_MIR_SOCKET=$(initctl get-env --global MIR_SOCKET)
24− initctl set-env --global UNITY_MIR_SOCKET=$UNITY_MIR_SOCKET
25−
26− # Point unity8 at unity-system-compositor
31+ # Save original value of MIR_SOCKET so that we can restore it when stopped,
32+ # as we modify the variable for future jobs, including ourself.
33+ initctl set-env UNITY_MIR_SOCKET=$MIR_SOCKET
34+
35+ # Decide where we are going to put our own socket file
36+ if [ -n "$SNAP" ]; then
37+ # In snappy, we want to hard code our path because our apparmor profile
38+ # only lets us put the socket in one place. And consumers expect it
39+ # there.
40+ MIR_SERVER_FILE=/run/user/$(id -u)/mir_socket
41+ else
2742 MIR_SERVER_FILE=$XDG_RUNTIME_DIR/mir_socket
28− initctl set-env MIR_SERVER_FILE=$MIR_SERVER_FILE
29− initctl set-env MIR_SERVER_HOST_SOCKET=$UNITY_MIR_SOCKET
30−
31− # Point all future jobs in this session to our Mir socket instead of
32− # unity-system-compositor's socket.
33− initctl set-env --global MIR_SOCKET=$MIR_SERVER_FILE
34− gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}"
3543 fi
44+ initctl set-env MIR_SERVER_FILE=$MIR_SERVER_FILE
45+
46+ # Point all future jobs in this session to our Mir socket instead of
47+ # unity-system-compositor's socket.
48+ initctl set-env --global MIR_SOCKET=$MIR_SERVER_FILE
49+ gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}"
3650
3751 # Remove the normal and trusted sockets if still there
3852 if [ -S "$MIR_SERVER_FILE" ]; then
@@ -45,24 +59,41 @@ pre-start script
4559
4660 initctl set-env --global MIR_SERVER_PROMPT_FILE=1
4761
48− initctl emit --no-wait indicator-services-start
49−
5062 # Disable Qt's stuttering 'touch compression' to fix scrolling smoothness
51− # issues (LP: #1486341). As a bonus, this eliminates most of the
52− # lag seen in the indicator panel pull-down (LP: #1488327) and also
63+ # issues (LP: #1486341, LP: #1556763). As a bonus, this eliminates most of
64+ # the lag seen in the indicator panel pull-down (LP: #1488327) and also
5365 # reduces lag seen in apps:
5466 initctl set-env --global QML_NO_TOUCH_COMPRESSION=1
5567
56− # For twice the fun and half the latency, try this (Warning: not all
57− # devices are fast enough to keep up smoothly yet)...
58− # initctl set-env MIR_SERVER_NBUFFERS=2
68+ # Workaround for text not rendering correctly
69+ initctl set-env --global QT_ENABLE_GLYPH_CACHE_WORKAROUND=1
70+
71+ if [ "$XDG_SESSION_DESKTOP" = "ubuntu-touch" ]; then
72+ # On Ubuntu Touch, we currently use a trick where we auto-login the
73+ # user without a LightDM greeter at all. In this case, we want to
74+ # start with the lockscreen visible. Once we switch to using a
75+ # proper greeter for the first login, we can remove this code path.
76+ initctl set-env MODE=full-greeter
77+ else
78+ initctl set-env MODE=full-shell
79+ fi
80+
81+ # HACK! WORKAROUND FOR HALIUM MISSING UBUNTU_PLATFORM_API
82+ if [ ! -f /system/lib/libubuntu_application_api.so ]; then
83+ initctl set-env --global UBUNTU_PLATFORM_API_BACKEND=test.so.3
84+ initctl set-env --global UBUNTU_PLATFORM_API_SENSOR_TEST=/etc/ubuntusensors/test.sensors
85+ fi
5986end script
6087
61−exec ${BINARY:-unity8} $ARGS
88+exec ${BINARY:-unity8} --mode=$MODE $ARGS
89+
90+post-start script
91+ initctl emit --no-wait indicator-services-start
92+end script
6293
6394post-stop script
6495 initctl set-env --global MIR_SOCKET=$UNITY_MIR_SOCKET
65− initctl unset-env --global UNITY_MIR_SOCKET
6696 initctl unset-env --global MIR_SERVER_PROMPT_FILE
6797 initctl emit application-end
98+ initctl emit indicator-services-end
6899end script
debian/bileto_pre_release_hooknew file+5
@@ -0,0 +1,5 @@
1+#!/bin/sh
2+
3+set -eux
4+
5+sh ./po/update-unity-pot
debian/changelog+1731−19
@@ -1,3 +1,1710 @@
1+unity8 (8.20+ubports) xenial; urgency=medium
2+
3+ * Replace dependency on ubuntu-wallpapers with ubports-wallpapers
4+
5+ -- Dalton Durst <dalton@ubports.com> Fri, 5 Oct 2018 13:28:20 -0500
6+
7+unity8 (8.17+ubports3) xenial; urgency=medium
8+
9+ * Imported to UBports
10+
11+ -- UBports auto importer <infra@ubports.com> Mon, 31 Jul 2017 03:12:43 +0200
12+
13+unity8 (8.15+17.04.20170404.7-0ubuntu2) zesty; urgency=medium
14+
15+ [ Michael Zanetti ]
16+ * Make the default store uri point to gnome software center
17+
18+ -- Timo Jyrinki <timo-jyrinki@ubuntu.com> Thu, 06 Apr 2017 10:49:29 +0300
19+
20+unity8 (8.15+17.04.20170404.7-0ubuntu1) zesty; urgency=medium
21+
22+ [ Albert Astals Cid ]
23+ * Tweak app drawer a bit (LP: #1667570)
24+
25+ [ Josh Arenson ]
26+ * Make some small changes to the greeter's session list
27+ * Handle a user in the greeter having never selected a session better
28+ (LP: #1673199)
29+
30+ [ Lukáš Tinkl ]
31+ * Do not occlude windows with an ongoing unmaximize transition (LP:
32+ #1666363)
33+ * Show and implement close buttons for child windows (LP: #1668053)
34+ * Sanitize the logic for pointer vs. touch menus, fixes hiding the
35+ window title in staged mode, when hovering the panel with mouse and
36+ no menus available.
37+
38+ [ Michael Zanetti ]
39+ * Don't hide the launcher on super press if it's locked visible (LP:
40+ #1675373)
41+ * fix searchfield selection in drawer (LP: #1677259)
42+ * make sure the stage has focus when going to spread (LP: #1672053,
43+ #1672673, #1676995)
44+ * don't autostart the dash app, but show its .desktop file instead
45+
46+ -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 04 Apr 2017 22:56:06 +0000
47+
48+unity8 (8.15+17.04.20170328.3-0ubuntu1) zesty; urgency=medium
49+
50+ [ Albert Astals Cid ]
51+ * mock: Remove empty property and move invokable
52+ * Tune quicklist item selection
53+ * Fix unminimizing going to the wrong position the second time (LP:
54+ #1671458)
55+ * Remove unclickable gaps on the menubar (LP: #1672722)
56+ * indicators client is a tool
57+ * Make sure we destroy the popups when the item goes away (LP:
58+ #1670338)
59+ * UnityApplicationMocks: Initialize m_state and m_requestedState
60+ * Don't use appInfo after checking it if is null
61+ * Initialize m_privateMode
62+ * Hook up aboutToShow for overflow menus (LP: #1676016)
63+
64+ [ Daniel d'Andrada ]
65+ * Give active focus to child surface qml items (LP: #1671072)
66+ * Satellite child windows (LP: #1673415)
67+ * Tell qtmir/miral about the available desktop area
68+
69+ [ Florian Boucault ]
70+ * WindowStateStorage: use a private QThreadPool to ensure that
71+ WindowStateStorage::saveValue always has a thread available to
72+ execute the query in. (LP: #1675424)
73+
74+ [ Lukáš Tinkl ]
75+ * Protect against loading invalid window geometry (LP: #1674262)
76+ * Remove usage of the deprecated (and non-functional) system-image-
77+ dbus service.
78+ * Implement Ctrl+Alt+T to launch the terminal app (LP: #1673500)
79+ * Only take normal and dialog surface types into account for launcher
80+ items (LP: #1669047)
81+ * Fix the shutdown dialog after recent refactoring in
82+ DBusUnitySessionService (LP: #1676426)
83+
84+ [ Michael Zanetti ]
85+ * drop the grey background behind icons in the drawer (LP: #1675688)
86+
87+ [ Pete Woods ]
88+ * Fix Unity/Platform::isPC, and add tests (LP: #1670657)
89+
90+ -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 28 Mar 2017 21:50:20 +0000
91+
92+unity8 (8.15+17.04.20170321-0ubuntu1) zesty; urgency=medium
93+
94+ [ Albert Astals Cid ]
95+ * Signal aboutToShow (LP: #1664578)
96+ * Support Panel top level items to be disabled (LP: #1670694)
97+ * Improve Launcher ←→ touch menu interaction (LP: #1667620, #1671069)
98+ * Fix real world submenus (e.g. kate) not getting their first item
99+ selected on open (LP: #1666859)
100+
101+ [ Daniel d'Andrada ]
102+ * Really disable the window decoration when in staged mode (LP:
103+ #1670361)
104+ * Don't let clients resize their surfaces while in staged
105+ (phone/tablet) mode (LP: #1670390)
106+ * TopLevelWindowModel: don't put hidden windows in the model (LP:
107+ #1665286)
108+
109+ [ Lukáš Tinkl ]
110+ * Reset always-show-osk gsetting on startup to default value (false
111+ atm)
112+ * Fix the restored-to position with Miral due to the state changes
113+ being async (LP: #1669819)
114+ * Add a cursor name fallback mapping "grabbing" -> "closedhand" for
115+ Breeze
116+ * Fix unsnapping a maximized window from the panel (LP: #1671721)
117+ * Disable altDrag feature outside windowed mode
118+
119+ [ Michael Terry ]
120+ * Don't lock the screen for guest users or users in the nopasswdlogin
121+ group. (LP: #1644237)
122+ * Support GNOME-style logout DBus API (making the Logout, Reboot, and
123+ Shutdown launcher commands work) (LP: #1673229)
124+
125+ [ Michael Zanetti ]
126+ * Add support for closing apps from the spread with "Q" (LP: #1670327)
127+ * hide "private" launcher quicklist entries when the greeter is locked
128+ (LP: #1667649)
129+ * add surface titles to launcher's quicklist (LP: #1661668)
130+ * properly reset the drawer state when cancelling a horizontal drag
131+ (LP: #1669536)
132+ * fix the focus moving correctly between launcher and drawer (LP:
133+ #1669880)
134+ * unfocus the drawer's textfield when it is moved (LP: #1669839)
135+
136+ [ Pete Woods ]
137+ * Fix up indicators-client after refactoring (LP: #1672797)
138+
139+ -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 21 Mar 2017 10:58:13 +0000
140+
141+unity8 (8.15+17.04.20170308-0ubuntu1) zesty; urgency=medium
142+
143+ [ Albert Astals Cid ]
144+ * Let's follow the keyboard order
145+ * Enable the license check (LP: #1590044)
146+ * Show a barebones error message if loading the QML doesn't work
147+ * Make sure cursor is back to normal when closing the window (LP:
148+ #1666158)
149+ * Fix small warning when sensitive is undefined
150+ * Remove unused member variable
151+ * Initialize m_msecsSinceReference
152+ * Add warning if registerService fails
153+ * Move menus Component {} out of the repeater
154+ * Add tool to browse menus of a running app
155+
156+ [ Daniel d'Andrada ]
157+ * Drag child windows with Alt+LeftMouseButton (LP: #1664947)
158+
159+ [ Gerry Boland ]
160+ * TopLevelWindowModel: connect to the OSK surface to know when it goes
161+ away so we can clean up after it. (LP: #1670681)
162+
163+ [ Josh Arenson ]
164+ * Initialize sessionMode to single when mock is reset (LP: #1667463)
165+
166+ [ Lukáš Tinkl ]
167+ * Make the menu string "Back" translatable
168+ * Let the OSK be driven by a switch in indicator-keyboard (LP:
169+ #1521518)
170+ * Disable the tutorial when there's no touchscreen (LP: #1661557)
171+ * Shell chrome fixes (LP: #1658117, #1665723, #1665724, #1669010)
172+ * Cancel the drag as soon as we're entering the spread (LP: #1668642)
173+ * Fix being unable to use window control buttons or menus with touch
174+ (LP: #1667604, #1668387)
175+
176+ [ Michael Terry ]
177+ * Set QT_IM_MODULE in the greeter so that the OSK can come up. (LP:
178+ #1670383)
179+ * Simplify our startup handling of Mir environment variables and set
180+ the right socket path in snappy.
181+
182+ [ Michael Zanetti ]
183+ * Cancel the home key activation if something else is pressed along
184+ with Meta (LP: #1670678)
185+ * close the drawer when something is launched from the launcher (LP:
186+ #1660367)
187+ * use a svg instead of a png for the Launcher's BFB (LP: #1668057)
188+ * change the default setting for the launcher autohiding (LP:
189+ #1670655)
190+
191+ [ Nick Dedekind ]
192+ * Split up Shell::test_spreadDisabled to ensure initial state for each
193+ test.
194+
195+ -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 08 Mar 2017 09:56:46 +0000
196+
197+unity8 (8.15+17.04.20170221-0ubuntu1) zesty; urgency=medium
198+
199+ * Handle ubuntu-app-launch API/ABI break
200+
201+ -- Ken VanDine <ken.vandine@canonical.com> Tue, 21 Feb 2017 13:23:23 +0000
202+
203+unity8 (8.15+17.04.20170216.1-0ubuntu1) zesty; urgency=medium
204+
205+ [ Albert Astals Cid ]
206+ * Make menus items close the menu when clicking on them (LP: #1657082,
207+ #1657399)
208+ * Clicking on an open menu closes it + test
209+ * Make the menus and submenus do not go outside the screen when
210+ popping out
211+ * Auto open submenus on hover (LP: #1657085)
212+ * Make the double click on a menu not be maximize the window below
213+ (LP: #1657079)
214+ * Make the MenuBar InverseMouseArea eat hover events when there's a
215+ popup open (LP: #1657763)
216+ * Make double click on the window decoration maximize (LP: #1657758)
217+ * Eat hover events when the launcher quicklist is open (LP: #1640776)
218+ * Remove TODO now that we require Qt > 5.5
219+ * Serialize two make targets that want to cp to the same target file
220+ (LP: #1660576)
221+ * Remove variable that is always false (LP: #1585910)
222+
223+ [ Daniel d'Andrada ]
224+ * Consolidate launcher API checks
225+
226+ [ Lukáš Tinkl ]
227+ * Fixes for activating minimized windows and restoring fullscreen ones
228+ (LP: #1656808, #1658937, #1658938)
229+
230+ [ Michael Zanetti ]
231+ * move right edge push area up some levels so it can be used on top of
232+ the indicators
233+ * fix minimizing/restoring transitions (LP: #1658936)
234+ * fix some glitches with spread positioning
235+ * fix jumpy animation when closing an item from the spread
236+ * Show the wallpaper while the focused app is moving in staged mode
237+ (LP: #1648251)
238+ * Update the tutorial to mention the app drawer instead of the dash on
239+ long left edge swipe (LP: #1658932)
240+ * prevent hiding the launcher when the mouse hover event is eaten by
241+ the EdgePushArea (LP: #1657045)
242+ * properly invalidate the whole model (LP: #1658190)
243+ * stabilize OrientedShell test (LP: #1658994)
244+
245+ [ Nick Dedekind ]
246+ * Added overflow support to application menus.
247+ * Updated menu colors
248+
249+ -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 16 Feb 2017 13:49:18 +0000
250+
251+unity8 (8.15+17.04.20170206-0ubuntu1) zesty; urgency=medium
252+
253+ [ Daniel d'Andrada ]
254+ * Initial support for child windows (menus, dialogs, tooltips) (LP:
255+ #1543467, #1591384, #1656727)
256+
257+ -- Albert Astals Cid <albert.astals@canonical.com> Mon, 06 Feb 2017 09:12:23 +0000
258+
259+unity8 (8.15+17.04.20170131.1-0ubuntu1) zesty; urgency=medium
260+
261+ [ Rodney Dawes ]
262+ * Remove dependencies on clickscope.
263+
264+ -- Albert Astals Cid <albert.astals@canonical.com> Tue, 31 Jan 2017 14:40:33 +0000
265+
266+unity8 (8.15+17.04.20170124-0ubuntu1) zesty; urgency=medium
267+
268+ [ Albert Astals Cid ]
269+ * Limit tab-focus travelling on dialogs with a fence
270+ * Restore focus to where it was when our ShellDialogs get unloaded
271+ * Update current session after changing the user
272+ * Add keyboard navigation for Indicators
273+ * a window -> the current window
274+ * There's no spreadDelegate_ anymore
275+
276+ [ Daniel d'Andrada ]
277+ * Simplify DecoratedWindow
278+ * Remove unnecessary warning message
279+
280+ [ Josh Arenson ]
281+ * Add a test for the session chooser icon in the greeter's sessions
282+ list
283+
284+ [ Lukáš Tinkl ]
285+ * Fix keymap not being applied on the shell itself (LP: #1626435)
286+ * Shell dialog improvements (kbd focus, mouse eater)
287+ * Start searching directly as you type, w/o having to first
288+ focus/click the search field.
289+ * Add a test for the real implementation of WindowStateStorage
290+ * Use a four finger gesture to open the drawer, much like in u7
291+
292+ [ Michael Terry ]
293+ * Simplify the lightdm mock to make future greeter improvements easier
294+ to test.
295+ * Add support for guest sessions in unity8-greeter.
296+ * Use a model for PAM prompts, supporting more possible interactions.
297+ * Fix grouping of autopkg output and allow optionally passing
298+ arguments to installed test scripts.
299+ * Add support for LightDM hints for manual logins and hiding normal
300+ users.
301+
302+ [ Michael Zanetti ]
303+ * hint the launcher to indicate a successful size change to the user
304+ (LP: #1646457)
305+ * Improvements for the appdrawer (LP: #1648173)
306+ * Adjust home key to still focus the dash instead of messing with the
307+ drawer
308+ * allow 4 finger simulation with mousetouchadaptor
309+
310+ [ Nick Dedekind ]
311+ * Added Alt+F10 shortcut to open app menus. (LP: #1656896)
312+ * Fixed menu layout width calculations. (LP: #1657050)
313+ * Skip Panel::test_drag_indicator_item_down_shows_menu
314+
315+ -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 24 Jan 2017 07:46:58 +0000
316+
317+unity8 (8.15+17.04.20170110.4-0ubuntu1) zesty; urgency=medium
318+
319+ [ Albert Astals Cid ]
320+ * Give focus to one of the buttons of the dialog
321+ * tst_WindowResizeArea: Use default values for mouseFlick speed and
322+ iterations (LP: #1651580)
323+ * Require Qt 5.6 & misc fixes
324+
325+ [ Daniel van Vugt ]
326+ * Deprecate usage of Mir's input resampling, instead opting for: (LP:
327+ #1497105, #1591328)
328+
329+ [ Josh Arenson ]
330+ * Allow the scopes list to automatically scroll when a scope is being
331+ dragged past the bounds of the screen. (LP: #1575319)
332+
333+ [ Lukáš Tinkl ]
334+ * Fix touch window controls being unreachable when the overlay is
335+ being displayed (LP: #1648167)
336+ * Fixup paths for window state storage in snappy environment
337+ * Add Unity.Platform mock for our tests (LP: #1655336)
338+
339+ [ Michael Zanetti ]
340+ * PreviewRatingInput: Use displayText instead of text to
341+ enable/disable the Send button (LP: #1595910)
342+ * Add a D-Bus interface to control some debug facilities on the fly
343+ * some launcher workarounds for the snapping
344+
345+ [ Michał Sawicz ]
346+ * Nuke leftover Platform in IndicatorsManager
347+
348+ [ Nick Dedekind ]
349+ * Added registry for application menus
350+
351+ [ Michael Terry, Nick Dedekind ]
352+ * Run the qmluitests.sh autopkg test against the installed package.
353+
354+ [ Michał Sawicz, Nick Dedekind ]
355+ * Application menus
356+
357+ [ Rodney Dawes ]
358+ * Remove the payments widget and dependency on libpay as no longer
359+ needed.
360+
361+ -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 10 Jan 2017 14:48:42 +0000
362+
363+unity8 (8.15+17.04.20161215-0ubuntu2~1) zesty; urgency=medium
364+
365+ * No change rebuild
366+
367+ -- Timo Jyrinki <timo-jyrinki@ubuntu.com> Wed, 04 Jan 2017 10:54:32 +0200
368+
369+unity8 (8.15+17.04.20161215-0ubuntu1) zesty; urgency=medium
370+
371+ * Let the model deal with some window management decisions (LP:
372+ #1346633)
373+
374+ -- Daniel d'Andrada <daniel.dandrada@canonical.com> Thu, 15 Dec 2016 16:17:29 +0000
375+
376+unity8 (8.15+17.04.20161207.1-0ubuntu1) zesty; urgency=medium
377+
378+ [ Albert Astals Cid ]
379+ * Add the Wsuggest-override flag to gcc
380+ * Add support for compiler sanitizers via ECM
381+ * Use timeStep as delay time (LP: #1642919)
382+ * Bring back fix for 1517830 (LP: #1517830)
383+ * Fix compile warnings in mocks
384+ * Do not hide panel when launching an application if the mouse is on
385+ the panel (LP: #1591311)
386+
387+ [ Daniel d'Andrada ]
388+ * Fix "make tryApplicationWindow"
389+ * Take save/restore functions out of WindowResizeArea
390+
391+ [ Josh Arenson ]
392+ * Enable the greeter to remember which session the user last logged
393+ into (LP: #1631365)
394+
395+ [ Lukáš Tinkl ]
396+ * Fix the Super key not invoking the dash scope home (LP: #1607427)
397+
398+ [ Michael Zanetti ]
399+ * Add the ApplicationDrawer
400+ * tune right edge push (LP: #1646094)
401+ * improve close button visiblity when hovering with the mouse
402+ * Update virtual touchpad visuals and add a tutorial. (LP: #1585220)
403+
404+ [ Pete Woods ]
405+ * MenuItemFactory: Add subtitle support to SwitchItem widget
406+
407+ -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 07 Dec 2016 13:49:24 +0000
408+
409+unity8 (8.15+17.04.20161129-0ubuntu1) zesty; urgency=medium
410+
411+ [ Albert Astals Cid ]
412+ * Fix PreviewProgress implicitHeight (LP: #1641943)
413+ * Adapt to dummy notification being gone
414+ * Fix autopilot test_lock_screen tests
415+ * Autopilot: Add more applications to the list for wider screens
416+ * Fix autopilot DashHelperTestCase.test_search
417+ * Also install the Screens mock
418+ * Give default value to gu-px size
419+
420+ [ Andrea Azzarone ]
421+ * Set Mir.cursorName to "grabbing" on first mouse press on a window
422+ decoration. Don't wait for press+motion. (LP: #1618078)
423+ * Do not show a divider between each quicklist entry but just between
424+ each section, similar to how unity7 does. (LP: #1637478)
425+
426+ [ Andrea Cimitan ]
427+ * Fix white text (LP: #1644468)
428+ * Make MascotLoader in CardCreator flat
429+ * Make the remaining UbuntuShape flat
430+ * added dropshadow from panel indicators to dash page header extra
431+ panel, so there is right shadow when the extra panel is narrow
432+ * Look up for expandable template dash category flag
433+
434+ [ Brian Douglass ]
435+ * Added a setting to enable/disable the indicator dropdown menu.
436+
437+ [ Daniel d'Andrada ]
438+ * There's no need for WindowDecoration to access the appDelegate
439+
440+ [ Lukáš Tinkl ]
441+ * Enable brightness (laptop backlight) handling on desktop/laptop PCs
442+ (LP: #1595947)
443+
444+ [ Michael Zanetti ]
445+ * disable spread interaction while locked (LP: #1641578)
446+
447+ [ Andrea Azzarone, Michał Sawicz ]
448+ * Implement launcher tooltips.
449+
450+ [ Olivier Tilloy ]
451+ * Remove dependency on transitional package. (LP: #1583079)
452+
453+ -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 29 Nov 2016 09:43:33 +0000
454+
455+unity8 (8.15+17.04.20161116.1-0ubuntu1) zesty; urgency=medium
456+
457+ [ Marco Trevisan (Treviño) ]
458+ * MenuItemFactory: bind calendar backend properties to calendarMenu item
459+
460+ Adds support for showing the calendar at the requested date, marking days
461+ with events properly and toggling the visibility of the week number.
462+
463+ * MenuItemFactory: use Menus.RadioMenu and Menus.ButtonMenu
464+
465+ * Bump version as USC breaks with unity8 << 8.14
466+
467+ [ Albert Astals Cid ]
468+ * [Hopefully] Fix infinite loop in some of the GSV tests (LP:
469+ #1599301)
470+
471+ [ Marco Trevisan (Treviño) ]
472+ * testLauncher: use tryCompare to check launcher contentY
473+
474+ [ Michael Zanetti ]
475+ * Stabilize OrientedShell tests
476+
477+ -- Marco Trevisan (Treviño) <mail@3v1n0.net> Wed, 16 Nov 2016 10:44:59 +0000
478+
479+unity8 (8.14+17.04.20161109-0ubuntu1) zesty; urgency=medium
480+
481+ [ Albert Astals Cid ]
482+ * Make more CardTool properties readonly
483+ * Make the > in Dash Section Header be after text (LP: #1508905)
484+ * Rework Dash Preview column margins
485+ * Improve LVWPH <-> GenericScopeView interaction (LP: #1508905,
486+ #1622423)
487+ * Make the PreviewButtons be of the width of the button and not half
488+ the total width
489+ * Fix first column of the preview table to be 25%
490+
491+ [ Andrea Cimitan ]
492+ * Remove background under header pagination dots, update dots assets,
493+ remove dash paper background, update bottom edge asset
494+ * Few styling changes for cards
495+ * various tweaks to fonts inside previews
496+ * More visual tweaks
497+
498+ [ Brian Douglass ]
499+ * Add a new setting to enable/disable the launcher
500+
501+ [ Lukáš Tinkl ]
502+ * Stabilize test_doubleTapToMaximizeWindow()
503+ * Enable loading the main Qt catalog which in turn allows for using
504+ RTL languages
505+ * Fix the pixelated notification icon by setting sourceSize (LP:
506+ #1637712)
507+
508+ [ Michael Terry ]
509+ * More path lookup fixes for running inside of a snap. (LP: #1629009)
510+
511+ [ Michael Zanetti ]
512+ * Added blur and darkening to wallpaper while in spread
513+ * Fixes in the spread after design review (LP: #1637502, #1638848)
514+ * More fixes to the unified stages code (LP: #1637205, #1637249,
515+ #1637258)
516+ * Delay alt tab for tiny bit in order to avoid flickering on quick alt-
517+ tabs
518+
519+ [ Tomás Tormo ]
520+ * Reload Infographics userdata when the day changes (LP: #1378814)
521+
522+ -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 09 Nov 2016 15:10:32 +0000
523+
524+unity8 (8.14+17.04.20161027-0ubuntu1) zesty; urgency=medium
525+
526+ * MenuItemFactory: activate item on calendar selection change (LP:
527+ #1541125)
528+
529+ -- Marco Trevisan (Treviño) <mail@3v1n0.net> Thu, 27 Oct 2016 12:32:25 +0000
530+
531+unity8 (8.14+17.04.20161024-0ubuntu1) zesty; urgency=medium
532+
533+ [ Albert Astals Cid ]
534+ * Make PreviewProgress be thicker again (LP: #1629382)
535+ * tst_PreviewZoomableImage: Wait for LazyImage transitions on init()
536+ (LP: #1630136)
537+
538+ [ Andrea Azzarone ]
539+ * Remove UbuntuShapeForItem and replace its use with the more standard
540+ Ubuntu.Components.UbuntuShape.
541+
542+ [ Lukáš Tinkl ]
543+ * Restore the double tap decoration to maximize feature (LP: #1627281)
544+ * Hide the cursor for fullscreen apps after 3 seconds of inactivity
545+ * Implement moving windows by Alt + left mouse button
546+
547+ [ Marco Trevisan (Treviño) ]
548+ * MenuItemFactory: use more features from SlotsLayout based settings
549+ components
550+
551+ [ Michael Terry ]
552+ * Grab launcher icon information from ubuntu-app-launch, not directly
553+ from desktop files.
554+ * Adjust root paths if we're running inside a snap. (LP: #1629009)
555+
556+ [ Michael Zanetti ]
557+ * Merge all Stages into one single codebase. Apply new spread visuals.
558+ (LP: #1489517, #1603914, #1635800)
559+
560+ -- Michael Zanetti <michael.zanetti@canonical.com> Mon, 24 Oct 2016 11:37:28 +0000
561+
562+unity8 (8.14+16.10.20160922-0ubuntu2) yakkety; urgency=medium
563+
564+ * debian/control:
565+ - Drop unity-scope-mediascanner2 to a Suggests rather than a Recommends,
566+ to ease our transition to main. It's already seeded directly in
567+ Touch, so this will only affect the Desktop variant of unity8.
568+
569+ -- Michael Terry <mterry@ubuntu.com> Mon, 03 Oct 2016 10:43:25 -0400
570+
571+unity8 (8.14+16.10.20160922-0ubuntu1) yakkety; urgency=medium
572+
573+ [ Albert Astals Cid ]
574+ * LVWPH: update clipItem height when list height changes (LP:
575+ #1606935)
576+ * Put the touchdown shape inside a loader
577+ * No need for the touchdown in the card for the cardtool
578+ * Add bottom gradient to the Show Less floating button
579+ * Remove artShapeSize from non cardtool cards
580+ * LVWPH: Fix case in which header was shown incorrectly
581+ * LVWPH: Fix items cut on top in the dash (or at least some instances
582+ of it)
583+ * Reduce calls to CardCreatorCache.getCardComponent while the
584+ component is being created (LP: #1615675)
585+ * Dash::test_cardIconStyle change compare into tryCompareFunction
586+ * Make PreviewActionsTest::test_comboButton more stable
587+ * Adapt onShiftedContentXChanged to work when the content changes very
588+ abruptly
589+ * Make tryGenericScopeView show the scope correctly
590+ * Make sure the spinner does not get too close to the title text (LP:
591+ #1597392)
592+ * Show "Pull to refresh" in white when overlaid in low luminance
593+ colors (LP: #1596849)
594+ * Make test_Shell non ultra slow again (LP: #1597366)
595+ * Improve findChild calls inside tryCompareFunction.
596+
597+ [ Andrea Cimitan ]
598+ * override some Qt Components definitions so we can have sane default
599+ values for flick speeds
600+ * Elide the label text inside recent searches panel (LP: #1611796)
601+ * Add a PreviewSingleton module to store some data for previews (LP:
602+ #1595235)
603+ * Use PreviewSingleton for PreviewRatingInput and PreviewCommentInput
604+ (LP: #1595235)
605+ * rework GenericScopeView PullToRefresh test
606+ * use mouseFlick instead touchFlick for manage_dash_move_current
607+ * add a couple of waiting tricks for a flaky dash test
608+
609+ [ Daniel d'Andrada ]
610+ * Set progress bar indeterminate when processing signal received. (LP:
611+ #1249349)
612+ * Implement cursor confinement (LP: #1590099)
613+
614+ [ Josh Arenson ]
615+ * Add a frontend to the sessions model and enable a session chooser in
616+ the greeter.
617+
618+ [ Lukáš Tinkl ]
619+ * Implement edge maximizing (aka window snapping) (LP: #1602628)
620+ * On the PC platform (as opposed to running on $devices), use the
621+ "mute" action instead of silent mode
622+ * Respect Fitt's law wrt the window control buttons in panel (LP:
623+ #1611959)
624+ * Fix 2 failing color-related tests
625+
626+ [ Marco Trevisan (Treviño) ]
627+ * Indicators, mocks: add fake indicators menuitem to populate mocks
628+ with different menu types
629+ * IndicatorsClient: use PageHeader and ListItemLayout's
630+
631+ [ Michael Terry ]
632+ * Support launching apps inside a unity8 session from the greeter and
633+ support emergency dialing inside the greeter.
634+ * Fix tryShell to actually show appropriate backgrounds for each mock
635+ user.
636+ * Add an indicator to the greeter when a user is logged in (only shown
637+ if we have more than one user)
638+ * Hide the greeter OSK if indicators are open and don't show the edge
639+ tutorial during an emergency call.
640+ * Switch from lockscreen PIN pad to a passcode entry box that uses the
641+ OSK.
642+ * Use the default system wallpaper instead of our custom one.
643+ * Update look of infographic a bit
644+ * Make infographic bubbles white even on the default wallpaper.
645+
646+ -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 22 Sep 2016 07:46:57 +0000
647+
648+unity8 (8.14+16.10.20160831.3-0ubuntu1) yakkety; urgency=medium
649+
650+ [ Daniel d'Andrada ]
651+ * Added implementation for MirSurfaceInterface::persistentId
652+
653+ -- Ken VanDine <ken.vandine@canonical.com> Wed, 31 Aug 2016 11:56:09 +0000
654+
655+unity8 (8.14+16.10.20160826-0ubuntu1) yakkety; urgency=medium
656+
657+ * Make sure we emit sounds when taking a screenshot even after media-
658+ hub (LP: #1544477)
659+
660+ -- Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com> Fri, 26 Aug 2016 08:14:14 +0000
661+
662+unity8 (8.14+16.10.20160819-0ubuntu1) yakkety; urgency=medium
663+
664+ [ Lukáš Tinkl ]
665+ * Reset topmostIsFullscreen to correctly rotate the shell when
666+ dismissing SIM PIN screen (LP: #1614070)
667+
668+ -- Michał Sawicz <michal.sawicz@canonical.com> Fri, 19 Aug 2016 14:16:54 +0000
669+
670+unity8 (8.14+16.10.20160811.1-0ubuntu1) yakkety; urgency=medium
671+
672+ [ Albert Astals Cid ]
673+ * Take into account carousel selectedItemScaleFactor when setting card
674+ fixedArtShapeSize (LP: #1599238)
675+ * Remove unused LimitProxyModel
676+ * Do not calculate implicitHeight for Cards in a CardGrid
677+ * Small clazy fixes
678+
679+ [ Daniel d'Andrada ]
680+ * Remove stage property from Application
681+
682+ [ Larry Price ]
683+ * Allow libertine-scope to show empty search result hint unmodified.
684+ (LP: #1606693)
685+
686+ [ Lukáš Tinkl ]
687+ * Open the quicklist (context) menu also using the Menu key (LP:
688+ #1608265)
689+ * Fix incorrect SIM PIN dialog position when entering a wrong PIN (LP:
690+ #1596076)
691+ * Apply the correct keymap also on prompt surfaces (LP: #1610124)
692+ * Implement an optional system update feature during OOBE wizard (LP:
693+ #1580785)
694+ * Implement a page for choosing HW keyboard layout in OOBE wizard
695+
696+ [ Michael Zanetti ]
697+ * Clean up some build script legacy
698+ * Add a crossbuilder_post file to make crossbuilder restart unity8
699+ after deploying
700+ * fixes for the automatic switching between usage modes (LP: #1590944)
701+
702+ [ Omer Akram ]
703+ * Add object names for setup wizard
704+
705+ -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 11 Aug 2016 06:28:20 +0000
706+
707+unity8 (8.14+16.10.20160803-0ubuntu1) yakkety; urgency=medium
708+
709+ [ Albert Astals Cid ]
710+ * Fix DisabledScreenNotice::test_rotation
711+ * Make the delegate of DashNavigationList an async Loader
712+ * unity-scope-tool: Use parse instead of process
713+ * VerticalJournal improvements regarding model insertions and item
714+ height changes (LP: #1599754)
715+ * Add math.h includes for compilation in yakkety (LP: #1605502)
716+
717+ [ Andrea Cimitan ]
718+ * Unfocus the search text field in the dash page header when requested
719+ (LP: #1590820)
720+ * Use binding for filter popover contentWidth (LP: #1595116)
721+ * Add few sourceSize for Image we forgot (LP: #1595113)
722+ * Replace Flickable with an Item inside DashPageHeader for
723+ headerContainer (LP: #1599235)
724+
725+ [ Albert Astals Cid, Andrea Cimitan ]
726+ * Unbox the artshapeLoader
727+
728+ [ Daniel d'Andrada ]
729+ * Fix splashscreen orientation when app rotates own contents (LP:
730+ #1586050)
731+ * tst_PreviewIconActions: Make test name match filename
732+ * Cursor: make its size grid unit based (LP: #1604014)
733+ * TouchEventSequenceWrapper: item might get deleted when touch
734+ sequence is committed (LP: #1607686)
735+
736+ [ Lukáš Tinkl ]
737+ * Implement frontend support for running keyboard indicator
738+ * Provide window/surface close shortcuts across all the stages (LP:
739+ #1578392, #1606528)
740+ * Restart the location trust prompt service when exiting the wizard
741+ (LP: #1594430)
742+ * Implement clearing the search and closing the panel on pressing
743+ Escape key in the dash header
744+ * Fix log timestamps (LP: #1602196)
745+ * Don't display the mode switch warning dialog on tablets (LP:
746+ #1600290)
747+
748+ [ Michael Terry ]
749+ * Fix indicator profile bug that caused sound indicator to say Mute
750+ instead of Silent Mode. (LP: #1604205)
751+ * Fix lockscreen appearing right after unlocking a locked session on
752+ the desktop. (LP: #1604374)
753+
754+ [ Michał Sawicz ]
755+ * Add arm64 support, drop unnecessary B-D on web plugin
756+
757+ -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 03 Aug 2016 15:56:27 +0000
758+
759+unity8 (8.14+16.10.20160728-0ubuntu1) yakkety; urgency=medium
760+
761+ [ Zoltán Balogh ]
762+ * Bump the version to secure UITK compatibility
763+
764+ [ Albert Astals Cid ]
765+ * Pass the correct number of arguments to mapToItem (LP: #1606835)
766+
767+ -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 28 Jul 2016 08:17:13 +0000
768+
769+unity8 (8.13+16.10.20160714+fix1-0ubuntu2~1) yakkety; urgency=medium
770+
771+ * Rebuild against Qt 5.6.
772+ * Add https://code.launchpad.net/~aacid/unity8/floor_includes/+merge/300850
773+
774+ -- Timo Jyrinki <timo-jyrinki@ubuntu.com> Fri, 22 Jul 2016 09:03:54 +0300
775+
776+unity8 (8.13+16.10.20160714-0ubuntu1) yakkety; urgency=medium
777+
778+ [ Daniel d'Andrada ]
779+ * Make use of MirSurface::inputBounds and drop UbuntuKeyboardInfo hack
780+
781+ -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 14 Jul 2016 07:09:29 +0000
782+
783+unity8 (8.12+16.10.20160711-0ubuntu1) yakkety; urgency=medium
784+
785+ [ Josh Arenson ]
786+ * Add a SessionsModel to lightdm to support the greeter's session
787+ chooser
788+ * Add unity8-greeter package which contains a basic, but usable
789+ LightDM greeter. (LP: #1324602)
790+
791+ [ Michael Terry ]
792+ * Make sure indicators and launcher hide when power button is pressed
793+ on greeter. (LP: #1595569)
794+ * Fix tablet greeter focus to be always-on, no longer hiding the OSK
795+ or forcing a mouse click to type a password. (LP: #1435923)
796+
797+ -- Michael Terry <michael.terry@canonical.com> Mon, 11 Jul 2016 17:24:20 +0000
798+
799+unity8 (8.12+16.10.20160707-0ubuntu1) yakkety; urgency=medium
800+
801+ [ Michael Zanetti ]
802+ * emit the correct role changed signal on count visible changed (LP:
803+ #1599925)
804+
805+ -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 07 Jul 2016 16:49:32 +0000
806+
807+unity8 (8.12+16.10.20160705-0ubuntu1) yakkety; urgency=medium
808+
809+ [ Michael Zanetti ]
810+ * don't displace windows if the OSK is on another screen (LP:
811+ #1598917)
812+
813+ -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 05 Jul 2016 10:00:57 +0000
814+
815+unity8 (8.12+16.10.20160627.5-0ubuntu1) yakkety; urgency=medium
816+
817+ [ Albert Astals Cid ]
818+ * Stop watching the old header item height once it's not our header
819+ anymore
820+ * LVWPH: cull the header item when not on view to save some painting
821+ * Adapt test to new mock behaviour
822+ * Don't let the mouse go outside the parentItem (LP: #1525350)
823+ * Use non deprecated package names
824+ * Mark system includes as such
825+ * Fix initialization order warning
826+ * Do not rely on deleteLater not crashing on null pointers
827+ * Add more headers of classes we use for automoc to be run
828+ * CardTool: Fix the fallback value to be a size and not an integer
829+ * CardTool: Include Ubuntu Components since we're using units.gu
830+ * Rework tst_PreviewRatingDisplayCreationRanges
831+
832+ [ Daniel d'Andrada ]
833+ * Cursor: Let AnimatedSprite run only on animated cursors and while
834+ the display is on (LP: #1588873, #1594358)
835+ * Fix missing screenshot when orientation changes while shell rotation
836+ ongoing (LP: #1587796)
837+
838+ [ Josh Arenson ]
839+ * Make PreviewRatingSingleDisplay visible again after editing a
840+ review. (LP: #1587097)
841+ * Correct errors in all png images to prevent libpng warnings.
842+
843+ [ Lukáš Tinkl ]
844+ * Fix some smaller issues with OOBE wizard password pages (LP:
845+ #1590467)
846+ * Prevent mouse wheel events from going through shell elements (LP:
847+ #1536268)
848+ * Do not let mouse and wheel events pass thru the titlebar (LP:
849+ #1588424)
850+ * Hide the maximize window button based on size restrictions (LP:
851+ #1541982)
852+
853+ [ Marco Trevisan (Treviño) ]
854+ * Unity8.conf: ensure MIR_SOCKET is set for future customers (such as
855+ the dash)
856+ * ClientIndicator: be more informative about loading failures for
857+ dynamically created objects
858+
859+ [ Michael Terry ]
860+ * Stop unity8 from getting in a "switch-to-greeter" loop when locking
861+ on a desktop. (LP: #1593718)
862+
863+ [ Michael Zanetti ]
864+ * set minimum window sizes on dash
865+ * displace application windows when the OSK would cover them
866+
867+ [ Nick Dedekind ]
868+ * Force dash to always stay in the main stage. (lp:#1592404) (LP:
869+ #1592404)
870+ * Save the last surface stage on stage drop. (LP: #1579003)
871+ * Default portrait only apps to the side stage. (LP: #1573153)
872+
873+ [ Albert Astals Cid, Andrea Cimitan, Michał Sawicz, Nick Dedekind ]
874+ * Added live video playback in dash previews
875+
876+ -- Michael Zanetti <michael.zanetti@canonical.com> Mon, 27 Jun 2016 18:48:59 +0000
877+
878+unity8 (8.12+16.10.20160620.3-0ubuntu1) yakkety; urgency=medium
879+
880+ [ Michael Terry, Michał Sawicz ]
881+ * Support unlocking via fingerprint, if one is registered.
882+
883+ -- Michael Terry <michael.terry@canonical.com> Mon, 20 Jun 2016 20:25:25 +0000
884+
885+unity8 (8.12+16.10.20160617-0ubuntu1) yakkety; urgency=medium
886+
887+ [ Michael Terry ]
888+ * Do not create Label/Icon if we don't need it
889+ * Fix Z-ordering of prompt surfaces (LP: #1586219)
890+ * Drop bottom edge tutorials completely and small fixes for other
891+ edges. (LP: #1565103)
892+ * Redo visuals for greeter prompt box. (LP: #1435923)
893+ * Make tutorial qmltests more robust. (LP: #1590810)
894+ * Stop showing an extra lockscreen in desktop unity8 sessions. (LP:
895+ #1582987)
896+
897+ [ Albert Astals Cid ]
898+ * Improve dash plugin mock
899+ * Stabilize PreviewExpandableTest::test_all_widgets_height
900+ * Workaround QTBUG-53460
901+ * Split artShape code for cardTool card and regular card
902+ * Simplify the code since fixedArtSize code is mandatory for regular
903+ cards
904+ * Desktop stage: Support rotatesWindowContents (LP: #1547481)
905+ * Turn if if else into if elseif else
906+ * Fix leaks in QInputDeviceManagerPrivate::addDevice
907+ * Do not call |= on uninitialized sigterm.sa_flags
908+ * initialize udevMonitor
909+ * Make notifier and notifierFd function local variables
910+ * Fix crash if a component that is not an Item is given to
911+ sectionDelegate
912+ * Tests: Do not use dynamic_cast if we're not going to test it anyway
913+ * Minor coverity fixes
914+ * Fix warning about anchors.fill in ProportionalShape (LP: #1590963)
915+ * Make wait in cleanup() wait for snapTo animation to have finished
916+
917+ [ Alexandros Frantzis ]
918+ * Improve the way notifications interact with power management (LP:
919+ #1570922)
920+
921+ [ Andrea Cimitan ]
922+ * Correctly refresh cardcreator cache on artshapestyle changes (LP:
923+ #1588335)
924+ * Same tweaks we have for click scope now for libertine
925+ * add a timer to pull to refresh to work on small windows (LP:
926+ #1589060)
927+
928+ [ Daniel d'Andrada ]
929+ * Clean up debug leftovers
930+ * Ensure mouse and window movement are pixel-aligned (LP: #1510382)
931+ * Fix SpreadDelegate rotation animations
932+ * No point in version-controlling files that are automatically
933+ generated
934+ * Center cursor on screen when it's first shown
935+ * Custom cursor name just have to start with "custom"
936+ * Work around AnimatedSprite infinite loop bug (LP: #1588929)
937+
938+ [ Josh Arenson ]
939+ * Disable showDash when it is already shown. (LP: #1506708)
940+ * Add a timestamp to the dash log (LP: #1580074)
941+ * Add timestamp to unity8 log (LP: #1498169)
942+
943+ [ Lukáš Tinkl ]
944+ * Implement keyboard shortcuts info panel
945+ * Implement window controls overlay activatable with 3 fingers tap
946+ (LP: #1489020)
947+ * Select correct Chinese input method for OSK in the wizard (LP:
948+ #1588633)
949+
950+ [ Michael Zanetti ]
951+ * Add support for the launcher surface pips displaying the correct
952+ number of surfaces
953+ * Add support for the persistent alert state. (LP: #1575147, #1584348,
954+ #1586621)
955+ * send a Alt-release event on alt+tab instead of delaying it
956+ completely and invoking it later (LP: #1565236)
957+
958+ [ Stephen M. Webb ]
959+ * added a new upstart $SESSION for unity8-desktop-session (LP:
960+ #1376715)
961+
962+ -- Michael Terry <michael.terry@canonical.com> Fri, 17 Jun 2016 01:22:57 +0000
963+
964+unity8 (8.12+16.10.20160601.1-0ubuntu1) yakkety; urgency=medium
965+
966+ [ Pawel Stolowski ]
967+ * Added apparmor profile for unity8-dash.
968+
969+ -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 01 Jun 2016 20:59:03 +0000
970+
971+unity8 (8.12+16.10.20160527-0ubuntu1) yakkety; urgency=medium
972+
973+ [ Albert Astals Cid ]
974+ * Activate on click for SimpleMessages (LP: #1421696)
975+ * Add override
976+ * Change the art back to the cardData value if it changes from broken
977+ to valid image (LP: #1533577)
978+ * Concierge mode generated code optimization
979+ * Don't use context properties but properties of the delegates
980+ * Listen to contentItem::widthChanged instead of
981+ Flickable::contentWidthChanged (LP: #1565763)
982+ * Make some AP code faster
983+ * Make tests a bit more stable
984+ * Make unity8 and unity8-dash handle termination signals
985+ * Remove workaround not needed anymore (LP: #1475643)
986+ * Resolve cardArtStyle on compile time
987+ * Set the theme earlier (LP: #1574048)
988+
989+ [ Albert Astals Cid, Daniel d'Andrada ]
990+ * Remove DirectionalDragArea and libs/UbuntuGestures and port to SDK
991+ equivalents
992+
993+ [ Andrea Cimitan ]
994+ * Hide the preview review input field when a rating is required (LP:
995+ #1541971)
996+
997+ [ CI Train Bot ]
998+ * Resync trunk.
999+
1000+ [ Daniel d'Andrada ]
1001+ * Fix DragHandle so it works in all directions
1002+ * Support animated cursors
1003+ * WindowInputMonitor - also map Qt::Key_HomePage to our home key
1004+ * plugins/Cursor: properly register to the screen's QPlatformCursor
1005+ when screen changes (LP: #1579742)
1006+
1007+ [ Josh Arenson ]
1008+ * Close the PageHeaderExtraPanel when a filter option is selected (LP:
1009+ #1569498)
1010+ * Wrap primaryFilter in a flickable to make it behave nicely. (LP:
1011+ #1569492)
1012+
1013+ [ Lukáš Tinkl ]
1014+ * First snap decision should always be expanded, unless user decides
1015+ otherwise (LP: #1580090, #1575045)
1016+ * Fullscreen notification bug fixes (LP: #1583944, #1581498, #1422711)
1017+ * Implement maximizing windows horizontally/vertically
1018+ * Lock the session when putting the laptop into sleep (LP: #1581063)
1019+
1020+ [ Lukáš Tinkl, Michael Terry ]
1021+ * With a maximized window, "dragging" the panel down should restore it
1022+
1023+ [ Michael Terry ]
1024+ * Change some dash button colors from orange to green. (LP: #1581047)
1025+ * Use PageHeader instead Ambiance's PageHeadStyle
1026+ * Use new setTimeZone method to set user-friendly timezone name in the
1027+ wizard. (LP: #1566295)
1028+
1029+ [ Michael Zanetti ]
1030+ * Remove the background dimming when the launcher is revealed by a
1031+ drag (LP: #1575137)
1032+ * reenable or drop disabled tests
1033+
1034+ -- Michael Terry <michael.terry@canonical.com> Fri, 27 May 2016 13:54:44 +0000
1035+
1036+unity8 (8.12+16.10.20160520.1-0ubuntu1) yakkety; urgency=medium
1037+
1038+ [ Lukáš Tinkl ]
1039+ * Don't dim screen when the indicators are open (LP: #1564342)
1040+ * Fix upcoming alarms ETA labels (LP: #1576741)
1041+ * Stabilize flaky wizard tests (LP: #1582994)
1042+
1043+ [ Michael Zanetti ]
1044+ * fix the SIM PIN darkening after it got removed accidentally (LP:
1045+ #1577147)
1046+
1047+ [ Michał Sawicz, Nick Dedekind ]
1048+ * Fixed saving current stage and loss of surface focus when switching
1049+ stages
1050+
1051+ [ Nick Dedekind ]
1052+ * Fixed incorrect osk surface item resizing the surface.
1053+
1054+ -- Michał Sawicz <michal.sawicz@canonical.com> Fri, 20 May 2016 08:44:19 +0000
1055+
1056+unity8 (8.12+16.04.20160518.1-0ubuntu1) xenial; urgency=medium
1057+
1058+ [ CI Train Bot ]
1059+ * Resync trunk.
1060+
1061+ [ Daniel d'Andrada, Michał Sawicz ]
1062+ * Move prompt surfaces from MirSurface to Application
1063+
1064+ -- Nick Dedekind <ci-train-bot@canonical.com> Wed, 18 May 2016 11:20:04 +0000
1065+
1066+unity8 (8.12+16.04.20160504.2-0ubuntu1) xenial; urgency=medium
1067+
1068+ [ Albert Astals Cid ]
1069+ * Expandable Filter Widget
1070+ * Pass the category correctly
1071+
1072+ [ Albert Astals Cid, CI Train Bot ]
1073+ * Make the previewActions react to the actions model changing (LP:
1074+ #1485887)
1075+ * Reload Preview Zoomable Image source if it gets updated
1076+ * Update the icon also to the original one if that's what the scope
1077+ wants
1078+
1079+ [ Andrea Cimitan ]
1080+ * Add social actions to cards
1081+
1082+ [ CI Train Bot ]
1083+ * Resync trunk.
1084+
1085+ -- Pawel Stolowski <ci-train-bot@canonical.com> Wed, 04 May 2016 18:09:33 +0000
1086+
1087+unity8 (8.12+16.04.20160429.2-0ubuntu1) xenial; urgency=medium
1088+
1089+ [ CI Train Bot ]
1090+ * Resync trunk.
1091+
1092+ [ Daniel d'Andrada ]
1093+ * Ensure shell transformations use bindings as OrientedShell can get
1094+ resized
1095+ * Make shell rotation animation work on multimonitor scenarios.
1096+ * Refactor screenshotting code and make it work in multimonitor
1097+ scenarios
1098+
1099+ [ Gerry Boland, Nick Dedekind ]
1100+ * Indicators: set menu height binding while fully open/closed, fixes
1101+ dynamic grid unit bug.
1102+
1103+ [ Michael Zanetti ]
1104+ * Call the dash sizing hack when units.gu changes
1105+ * Temporary means to override GUs on the internal screen
1106+ * reduce some paint layers.
1107+
1108+ -- Michał Sawicz <michal.sawicz@canonical.com> Fri, 29 Apr 2016 20:07:37 +0000
1109+
1110+unity8 (8.12+16.04.20160427.3-0ubuntu1) xenial; urgency=medium
1111+
1112+ [ Albert Astals Cid ]
1113+ * Add env var to enable js debugging/profiling even if not built on
1114+ debug mode
1115+ * Better error message if the item does not exist
1116+ * CardCreator: Remove ShaderEffectSource (LP: #1544875)
1117+ * Compile with Qt 5.6 (LP: #1565632)
1118+ * LVWPH: Account for contentHeight not really being "all" of the
1119+ content height (LP: #1569976)
1120+ * NotificationAudio: We don't need weird "ifdef" for multimedia 5.6 vs
1121+ 5.0 roles anymore
1122+ * See all/less -> Show all/less (LP: #1349471)
1123+ * Stabilize test_superTabToCycleLauncher
1124+ * Take into account that sectionItem height can change
1125+ * Turn verify intro tryCompareFunction
1126+ * forceLayout before calling positionViewAtIndex (LP: #1553475)
1127+ * rootObject can be null for a small moment after setSource is called
1128+ (LP: #1560501)
1129+
1130+ [ CI Train Bot ]
1131+ * Resync trunk.
1132+
1133+ [ Daniel van Vugt ]
1134+ * Reinstate the touch performance/smoothness fix (LP: #1486341, LP:
1135+ #1556763). (LP: #1556763, #1486341)
1136+
1137+ [ Josh Arenson ]
1138+ * Change the color of the activity pulse to blue (LP: #1568082)
1139+ * Make scope filter settings button the same color as other foreground
1140+ elements (LP: #1563357)
1141+
1142+ [ Lukáš Tinkl ]
1143+ * Drop OOBE wizard autopilot tests
1144+ * Fix labels in desktop spread
1145+ * Fix upcoming event ETAs falling out of sync (LP: #1557571)
1146+ * Hide the close button for dash (LP: #1550056, #1564347)
1147+ * Notifications visual update, close button on mouse hover (LP:
1148+ #1564343)
1149+ * Shell visual update
1150+ * Stabilize wizard tests
1151+ * Unity8 windows now cascade instead of opening all in the top left
1152+ corner (LP: #1513813)
1153+
1154+ [ Michael Terry ]
1155+ * Fix some unreliable test code.
1156+ * Ignore Home Key presses when the greeter is up. (LP: #1565818)
1157+
1158+ [ Michael Zanetti ]
1159+ * Drop the rotation lock for the dash (LP: #1465331, #1574165)
1160+ * improve the pin lockscreen
1161+ * install devices.conf by default
1162+
1163+ [ Ted Gould ]
1164+ * Switch to using uid/pwdent for getting username
1165+
1166+ -- Michael Terry <michael.terry@canonical.com> Wed, 27 Apr 2016 15:01:28 +0000
1167+
1168+unity8 (8.12+16.04.20160421.1-0ubuntu1) xenial; urgency=medium
1169+
1170+ [ Daniel d'Andrada ]
1171+ * Refactor keymap switching code
1172+ * Surface-based window management
1173+ * Use Item.grabToImage() instead of qtmir's ApplicationScreenshot
1174+ provider
1175+
1176+ [ Michael Zanetti ]
1177+ * Fixes for programmatically closing Applications
1178+
1179+ [ Robert Bruce Park ]
1180+ * Use new bileto_pre_release_hook
1181+
1182+ -- Gerry Boland <ci-train-bot@canonical.com> Thu, 21 Apr 2016 13:48:02 +0000
1183+
1184+unity8 (8.12+16.04.20160414.1-0ubuntu1) xenial; urgency=medium
1185+
1186+ [ Michael Terry ]
1187+ * Make sure that usageMode is set on startup, fixing a problem with
1188+ the tutorial not noticing that it is running on a desktop. (LP:
1189+ #1564351)
1190+
1191+ [ Michael Zanetti ]
1192+ * make the edge drag area width configurable (LP: #1559512)
1193+
1194+ -- Michael Zanetti <michael.zanetti@canonical.com> Thu, 14 Apr 2016 21:20:28 +0000
1195+
1196+unity8 (8.12+16.04.20160401-0ubuntu1) xenial; urgency=medium
1197+
1198+ * Add missing Testsuite header
1199+ * Skip the failing test until we have a working solution for bug
1200+ #1564571 (LP: #1564571)
1201+
1202+ -- Michał Sawicz <michal.sawicz@canonical.com> Fri, 01 Apr 2016 08:32:16 +0000
1203+
1204+unity8 (8.12+16.04.20160330-0ubuntu1) xenial; urgency=medium
1205+
1206+ [ Albert Astals Cid ]
1207+ * Use tutorialLeftLoader instead of tutorialLeft
1208+
1209+ [ CI Train Bot ]
1210+ * Update translation template
1211+
1212+ [ Lukáš Tinkl ]
1213+ * Fix the last chance popup colors/theme
1214+
1215+ [ Michael Terry ]
1216+ * Adjust text for desktop right edge tutorial to be accurate. (LP:
1217+ #1563103)
1218+ * Fix OOBE wizard not setting your name. (LP: #1562872)
1219+ * Fix showing "Retry" in password prompt when turning on screen in
1220+ tablet mode.
1221+
1222+ -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 30 Mar 2016 07:46:51 +0000
1223+
1224+unity8 (8.12+16.04.20160323.2-0ubuntu1) xenial; urgency=medium
1225+
1226+ [ Michael Terry ]
1227+ *
1228+ * Fix setting OSK layout in OOBE wizard
1229+ * Stop the left edge tutorial from being shown when the bottom edge
1230+ tutorial wants to be shown after receiving a call.
1231+
1232+ [ Albert Astals Cid ]
1233+ * Filter implementation with Option Selector filter as the only filter
1234+ * Get the engine from the parent context
1235+ * Implement the API changes due to filters
1236+ * Match design visuals for the new dash navigation/page header popup
1237+ * New Dash Navigation UX
1238+ * Range Input filter
1239+ * Value slider filter
1240+ * Workaround SDK ListItem bug
1241+
1242+ [ Albert Astals Cid, Lukáš Tinkl ]
1243+ * Fix various tests
1244+
1245+ [ CI Train Bot ]
1246+ * Resync trunk.
1247+ * Update translation template
1248+
1249+ [ Lukáš Tinkl, Michael Terry ]
1250+ * New first-run wizard for the phone (part of the OOBE effort) (LP:
1251+ #1536688, #1536617, #1543790, #1555222)
1252+
1253+ [ Lukáš Tinkl, Michał Sawicz ]
1254+ * Keymap switching support (LP: #1524400, #1412492, #1491340)
1255+
1256+ [ Michael Terry, Michael Zanetti ]
1257+ * Redesign the first-boot edge tutorial
1258+
1259+ [ Michael Zanetti ]
1260+ * disabling some tests that are flaky in adt but can't be made fail on
1261+ our machines
1262+
1263+ [ Michael Zanetti, Michał Sawicz ]
1264+ * Change the behavior alond with the switch in indicator-display (LP:
1265+ #1538591)
1266+
1267+ [ Michael Zanetti, Michał Sawicz, Nick Dedekind ]
1268+ * Add support for low shell chrome. (LP: #1535397)
1269+ * Sidestage load/unload redesign (LP: #1544479)
1270+
1271+ -- Michael Zanetti <michael.zanetti@canonical.com> Wed, 23 Mar 2016 09:53:17 +0000
1272+
1273+unity8 (8.11+16.04.20160318.1-0ubuntu1) xenial; urgency=medium
1274+
1275+ [ CI Train Bot ]
1276+ * Update translation template
1277+
1278+ [ Lukáš Tinkl ]
1279+ * Fix notifications with the new UITK color schemes (LP: #1554616,
1280+ #1556523)
1281+
1282+ [ Lukáš Tinkl, Michael Zanetti, Nick Dedekind ]
1283+ * more fixes for the new theme palette (LP: #1554616, #1557534)
1284+
1285+ -- Michael Zanetti <michael.zanetti@canonical.com> Fri, 18 Mar 2016 17:12:53 +0000
1286+
1287+unity8 (8.11+16.04.20160310.4-0ubuntu1) xenial; urgency=medium
1288+
1289+ [ Albert Astals Cid ]
1290+ * Add context for Re-dock as asked by translators (LP: #1534608)
1291+ * Add emblem to the preview header widget (LP: #1424720)
1292+ * Add haptics to ScopesListCategoryItem buttons
1293+ * Audio Cards: Make some of the image loading async (LP: #1533432)
1294+ * Do not create fallback code for the card tool fake card (LP:
1295+ #1545865)
1296+ * Fix resizing the dash bringing temp scopes size out of sync (LP:
1297+ #1543130)
1298+ * Minor fixes for unity-scope-tool
1299+ * Resolve title alignment on card creator time instead of on runtime
1300+ * Use fixedHeaderHeight only in the non cardtool cards
1301+ * Use the new undeprecated connectivityqt::Connectivity
1302+ * asynchronous is only false on the fake card in cardtool
1303+ * clazy fixes
1304+
1305+ [ Albert Astals Cid, CI Train Bot ]
1306+ * click scope: Add the else branch so we reset the card size in all
1307+ situations
1308+
1309+ [ Andrea Cimitan ]
1310+ * PreviewSharing widget now accepts both string and array of
1311+ widgetData["share-data"]["uri"] (LP: #1549056)
1312+ * Update AP tests for new single preview
1313+ * Use Text.Wrap for body notification text (LP: #1544909)
1314+
1315+ [ Andrea Cimitan, Lukáš Tinkl, Michael Zanetti, Nick Dedekind ]
1316+ * some fixes for the new palette (LP: #1554616)
1317+
1318+ [ CI Train Bot ]
1319+ * Resync trunk.
1320+ * Update translation template
1321+
1322+ [ CI Train Bot, Daniel d'Andrada ]
1323+ * Ensure the QML engine doesn't delete our mock MirSurfaces on its
1324+ own.
1325+
1326+ [ Daniel d'Andrada ]
1327+ * tst_Shell: Remove unused qml items
1328+
1329+ [ Josh Arenson ]
1330+ * Allow the shell to blacklist input devices and force the OSK shown.
1331+ (LP: #1542224)
1332+
1333+ [ Lukáš Tinkl ]
1334+ * Disallow resizing windows up, past the Panel (LP: #1544766)
1335+ * Elide the window title not to let it overflow into the indicators
1336+ area (LP: #1535767)
1337+ * Enable the PIN lockscreen to be used with a HW keyboard (LP:
1338+ #1550359)
1339+ * Fix tiny windows when switching stages
1340+ * Provide a range of ports to QML JS Debugger
1341+ * Watch for launcher item icon changes (LP: #1543290)
1342+
1343+ [ Michael Terry ]
1344+ * Proxy more mouse and touchpad properties to USC (LP: #1540398) (LP:
1345+ #1543344, #1540398)
1346+ * Refactor the AccountsService plugin and make it slightly faster.
1347+ * To let the user log in if a mouse is connected, hide the greeter
1348+ cover page on a mouse click (but NOT a touch click). (LP: #1540497)
1349+ * Watch AccountsService for changes to the user's real name. This was
1350+ preventing us from noticing when the user set their name in the
1351+ welcome wizard.
1352+
1353+ [ Michael Zanetti ]
1354+ * Allow alt+tabbing in staged mode too (LP: #1540502)
1355+ * Allow invoking the staged mode spreads by mouse right edge pushes
1356+ too (LP: #1540392)
1357+ * Allow loading the device configuration from an external file
1358+ * Implement Launcher's keyboard navigation and updated pip design
1359+ * Make launcher scalable, allow it locking (LP: #1511015)
1360+ * Properly parent launcher items in all cases (LP: #1495732)
1361+ * Read inputMethod surface from the new property int QtMir (LP:
1362+ #1545286)
1363+ * Some visual updates and rotation lock for the virtual touchpad (LP:
1364+ #1549087)
1365+ * Visual updates for the windowed spread (LP: #1488148)
1366+ * stabilize swipeAwayGreeter()
1367+
1368+ [ Michał Sawicz ]
1369+ * Add udev rules to make sure we have access to uinput
1370+ * Make dash respawn indefinitely (LP: #1550056)
1371+ * Use dpkg-architecture, not arch, to disable touch emulation
1372+
1373+ [ Vesa Rautiainen ]
1374+ * Fixing the vertical position of desktop spread item icon.
1375+
1376+ -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 10 Mar 2016 22:44:16 +0000
1377+
1378+unity8 (8.11+16.04.20160308-0ubuntu1) xenial; urgency=medium
1379+
1380+ [ Albert Astals Cid ]
1381+ * Make these tests pass with the new SDK
1382+
1383+ [ Andrea Cimitan, Nick Dedekind ]
1384+ * replace selected.backgroundText with normal.backgroundText in
1385+ Splash, Notifications, Wizard
1386+
1387+ [ CI Train Bot ]
1388+ * Update translation template
1389+
1390+ [ Michał Sawicz, Nick Dedekind ]
1391+ * Fixed colours palette value set. Moved ModemItem to USC.
1392+
1393+ [ Michał Sawicz, Tim Peeters ]
1394+ * Update headers for Dash and Splash to work properly with the new UI
1395+ toolkit release.
1396+
1397+ [ Zoltán Balogh, Zsombor Egri ]
1398+ * Use SuruDark theme instead of the deprecated SuruGradient.
1399+
1400+ -- Zoltan Balogh <zoltan.balogh@canonical.com> Tue, 08 Mar 2016 20:59:34 +0000
1401+
1402+unity8 (8.11+16.04.20160307-0ubuntu1) xenial; urgency=medium
1403+
1404+ [ CI Train Bot ]
1405+ * Resync trunk.
1406+ * Update translation template
1407+
1408+ [ Rodney Dawes ]
1409+ * Re-enable the purchaseCancelled signal.
1410+
1411+ -- Rodney Dawes <ci-train-bot@canonical.com> Mon, 07 Mar 2016 14:12:08 +0000
1412+
1413+unity8 (8.11+16.04.20160301-0ubuntu1) xenial; urgency=medium
1414+
1415+ [ Albert Astals Cid ]
1416+ * Hook the new scope.activationInProgress property (LP: #1537132)
1417+
1418+ [ Andrea Cimitan ]
1419+ * Updated the Preview view to use a single PreviewModel instead old
1420+ PreviewStack, using a Loader instead ListView (LP: #1541967)
1421+
1422+ [ CI Train Bot ]
1423+ * Resync trunk.
1424+ * Update translation template
1425+
1426+ [ Michał Sawicz ]
1427+ * Add autopilot as DEP-8 tests added: debian/tests/autopilot.sh
1428+
1429+ -- Pawel Stolowski <ci-train-bot@canonical.com> Tue, 01 Mar 2016 10:28:52 +0000
1430+
1431+unity8 (8.11+16.04.20160216.1-0ubuntu1) xenial; urgency=medium
1432+
1433+ [ Albert Astals Cid ]
1434+ * Make the audio previews create a playlist (LP: #1540477)
1435+
1436+ [ CI Train Bot ]
1437+ * Resync trunk. added: po/aa.po
1438+ * Update translation template
1439+
1440+ -- Pawel Stolowski <ci-train-bot@canonical.com> Tue, 16 Feb 2016 03:24:46 +0000
1441+
1442+unity8 (8.11+16.04.20160212-0ubuntu1) xenial; urgency=medium
1443+
1444+ [ Albert Astals Cid ]
1445+ * Do not use components in card creator generated code
1446+ * Forward the makesurevisible signal from the inner preview widget
1447+ * Make fallback also be fallback when the image is empty and not only
1448+ on error (LP: #1531913)
1449+ * Make the artShapeSize assignment be updated when using dynamic grid
1450+ units
1451+ * Visual improvements to the dash audio play cards
1452+ * We don't use the unity-scope-scopes anymore (LP: #1439172)
1453+
1454+ [ Andrea Cimitan ]
1455+ * only request a bigger image if zoomable widget data property is
1456+ true, otherwise just leave the screen size (LP: #1536814)
1457+
1458+ [ CI Train Bot ]
1459+ * Update translation template
1460+
1461+ [ Daniel d'Andrada ]
1462+ * Set initial surface size (LP: #1532974)
1463+
1464+ [ Daniel d'Andrada, Michał Sawicz ]
1465+ * Window Size Hints
1466+
1467+ [ Florian Boucault ]
1468+ * Splash screen: delay showing the ActivityIndicator by 2 seconds.
1469+
1470+ [ Lukáš Tinkl ]
1471+ * Replace the word "phone" with a more generic term "device" in the
1472+ welcome wizard (LP: #1294732, #1543527)
1473+
1474+ [ Michael Terry ]
1475+ * Have the tablet greeter set appropriate OSK hints if the user has a
1476+ passcode instead of a passphrase. (LP: #1544173)
1477+
1478+ [ Michael Zanetti ]
1479+ * Don't eat mouse events in the edgebarrer
1480+
1481+ [ Michał Sawicz ]
1482+ * Bump unity-api dependencies
1483+
1484+ [ Nick Dedekind ]
1485+ * Added support for secondary indicator actions (LP: #1398888)
1486+ * Remove zombie if they're not animated. (LP: #1534541)
1487+ * Removed unused panel resources
1488+
1489+ [ Ted Gould ]
1490+ * Start the indicators after Unity8 starts instead of before
1491+
1492+ -- Michał Sawicz <michal.sawicz@canonical.com> Fri, 12 Feb 2016 00:12:41 +0000
1493+
1494+unity8 (8.11+16.04.20160208-0ubuntu1) xenial; urgency=medium
1495+
1496+ [ Albert Astals Cid ]
1497+ * LVWPH: Reset to initial values when list is empty (LP: #1540490)
1498+ * Make LazyImage qmltest less flaky on CI
1499+
1500+ [ Andrea Cimitan ]
1501+ * Make LazyImage qmltest less flaky on CI
1502+
1503+ [ CI Train Bot ]
1504+ * Resync trunk.
1505+ * Update translation template
1506+
1507+ [ Michael Terry ]
1508+ * Display the current user's real name on the tablet lockscreen. (LP:
1509+ #1536714)
1510+
1511+ -- Michał Sawicz <michal.sawicz@canonical.com> Mon, 08 Feb 2016 09:38:00 +0000
1512+
1513+unity8 (8.11+16.04.20160129-0ubuntu1) xenial; urgency=medium
1514+
1515+ [ Albert Astals Cid ]
1516+ * Audio Preview Button: Don't gain focus on press (LP: #1517830)
1517+ * Better attempt at sanitization
1518+ * Better looking application scopes for wide screens
1519+ * Call printSettings correctly
1520+ * Card test: Limit the precision we ask for doubles to be equal
1521+ * Convert while into tryCompareFunction
1522+ * Do not use the same filepath parameter for all the card creator
1523+ createQmlObject calls (LP: #1536379)
1524+ * Fix some test shells being unstable in the armhf builders
1525+ * Make revealByEdgePush more stable
1526+ * More reliable compares
1527+ * Move the mouse over the bfb before waiting for rendering
1528+ * Remove the DDAs constrains for every test
1529+ * Set the background source size to the max we'll need + new
1530+ background (LP: #1539011)
1531+
1532+ [ Andrea Cimitan ]
1533+ * Dynamically change click scope card size according to size (LP:
1534+ #1536745)
1535+ * Should fix lazyimage test failures on fast machines
1536+
1537+ [ CI Train Bot ]
1538+ * Fix card tests on the phone
1539+ * Update translation template
1540+
1541+ [ Daniel d'Andrada ]
1542+ * Desktop stage rotates only to follow screen orientation (LP:
1543+ #1515977)
1544+
1545+ [ Lukáš Tinkl ]
1546+ * Hide/reveal the mouse pointer on touch/mouse events renamed:
1547+ plugins/Utils/HomeKeyWatcher.cpp =>
1548+ plugins/Utils/WindowInputMonitor.cpp plugins/Utils/HomeKeyWatcher.h
1549+ => plugins/Utils/WindowInputMonitor.h
1550+ tests/mocks/Utils/HomeKeyWatcher.qml =>
1551+ tests/mocks/Utils/WindowInputMonitor.qml
1552+ tests/plugins/Utils/HomeKeyWatcherTest.cpp =>
1553+ tests/plugins/Utils/WindowInputMonitorTest.cpp
1554+
1555+ [ Michael Terry ]
1556+ * Synchronize the mouse-cursor-speed and touchpad-cursor-speed
1557+ properties with USC. (LP: #1536383)
1558+
1559+ [ Michael Zanetti ]
1560+ * Add InputMethod to secondary screen
1561+ * Add a virtual Touchpad while external screen is connected
1562+ * Make big tablets switch to windowed mode by plugging a kbd only (LP:
1563+ #1535399)
1564+ * Prevent alt key presses from being dispatched to the app on alt+tab
1565+ (LP: #1532862)
1566+
1567+ [ Michał Sawicz ]
1568+ * Make qmluitests.sh more robust and allow parallel test execution
1569+ * Skip SessionBackendTest::testLogin1Capabilities until we talk to a
1570+ mock instead (LP: #1532112, #1532113)
1571+
1572+ -- Michał Sawicz <michal.sawicz@canonical.com> Fri, 29 Jan 2016 11:53:27 +0000
1573+
1574+unity8 (8.11+16.04.20160122-0ubuntu1) xenial; urgency=medium
1575+
1576+ [ Albert Astals Cid ]
1577+ * Fix bug #1536296 added: tests/plugins/Dash/cardcreator/10.tst (LP:
1578+ #1536296)
1579+ * Fix card tests on the phone
1580+
1581+ [ CI Train Bot ]
1582+ * Update translation template
1583+
1584+ -- Michał Sawicz <michal.sawicz@canonical.com> Fri, 22 Jan 2016 16:56:04 +0000
1585+
1586+unity8 (8.11+16.04.20160111.1-0ubuntu1) xenial; urgency=medium
1587+
1588+ [ Albert Astals Cid ]
1589+ * Clear fake item icon name as soon as it goes invisible (LP:
1590+ #1531172)
1591+ * Fix LVWPH test failing on Xenial (Qt 5.5)
1592+ * Fix dragging so that test passes on Xenial
1593+ * Fix focus on the dash page header text field with new SDK (LP:
1594+ #1528178)
1595+ * Make the card creator test pass again
1596+ * Quit the dash communicator thread before destroying it (LP:
1597+ #1508485)
1598+ * Remove duplicated override_dh_auto_clean
1599+ * SDK changed the name they give to the buttons, follow
1600+
1601+ [ Andrea Cimitan ]
1602+ * Fix a broken binding
1603+
1604+ [ CI Train Bot ]
1605+ * Resync trunk.
1606+ * Update translation template
1607+
1608+ [ Daniel d'Andrada ]
1609+ * Have "make tryFoo" work with Qt 5.5
1610+ * Make DragHandle tests run again.
1611+
1612+ [ Lukáš Tinkl ]
1613+ * Fix dismissing the launcher when clicking/tapping outside (LP:
1614+ #1531339, #1530940)
1615+ * Fix panel drop shadow and click-to-focus of maximized apps (LP:
1616+ #1531854)
1617+ * Fix wifi access point indicator items signal strength icon on
1618+ desktop
1619+
1620+ [ Michael Terry ]
1621+ * Guard against a couple odd timing scenarios for the too-many-failed-
1622+ login-attempts lockout screen.
1623+ * Skip the wizard's password screens if there is already a password
1624+ set by other means. (LP: #1531268)
1625+ * Stop the emergency dialer from accidentally exposing the mtp
1626+ service. (LP: #1525981)
1627+
1628+ [ Michael Zanetti ]
1629+ * Make sure the triangle of the quicklist is in bounds (LP: #1531340)
1630+
1631+ [ Pawel Stolowski ]
1632+ * Changes 'shareData' and 'contentType' attributes to 'share-data' and
1633+ 'content-type', to match existing naming schema.
1634+
1635+ -- Michał Sawicz <michal.sawicz@canonical.com> Mon, 11 Jan 2016 17:38:49 +0000
1636+
1637+unity8 (8.11+16.04.20160107-0ubuntu1) xenial; urgency=medium
1638+
1639+ [ Albert Astals Cid ]
1640+ * Introduce audio cards
1641+
1642+ [ CI Train Bot ]
1643+ * Update translation template
1644+
1645+ [ Michael Zanetti ]
1646+ * Introduce audio cards
1647+
1648+ -- CI Train Bot <ci-train-bot@canonical.com> Thu, 07 Jan 2016 08:04:47 +0000
1649+
1650+unity8 (8.11+16.04.20160105.1-0ubuntu1) xenial; urgency=medium
1651+
1652+ [ CI Train Bot ]
1653+ * Resync trunk.
1654+ * Update translation template
1655+
1656+ [ Nick Dedekind ]
1657+ * Use volume-sync action to resync the volume control. (LP: #1520548)
1658+
1659+ -- Xavi Garcia <xavi.garcia.mena@canonical.com> Tue, 05 Jan 2016 13:55:38 +0000
1660+
1661+unity8 (8.11+16.04.20151208.1-0ubuntu1) xenial; urgency=medium
1662+
1663+ [ Albert Astals Cid ]
1664+ * Allow dragging launcher items with the quicklist open (LP: #1250861)
1665+ * Create ratings on demand instead of all at the same time (LP:
1666+ #1519898, #1492214)
1667+ * LVWPH: Process correctly section changes (LP: #1519893)
1668+ * Make sure that unfavoriting a scope gives us the next one
1669+ * Move images only used in tests to tests folder
1670+
1671+ [ Andrea Cimitan ]
1672+ * Add shadows to ubuntu store icon
1673+
1674+ [ Daniel d'Andrada ]
1675+ * MirSurfaceItem got a new property: fillMode (LP: #1497083)
1676+ * Session can have multiple surfaces now
1677+ * plugins/Cursor: Do not force loading a specific cursor size (LP:
1678+ #1517878)
1679+
1680+ [ Lukáš Tinkl ]
1681+ * Indicators convergence: use the "phone" profile everywhere (LP:
1682+ #1520492)
1683+
1684+ [ Michael Terry ]
1685+ * Let qtmir know which apps are exempt from the lifecycle management.
1686+ This way, it can manage its own wakelocks better (and stop
1687+ preventing the system from deep sleeping).
1688+
1689+ [ Michael Zanetti ]
1690+ * Use proper z ordering instead of app index for occlusion detection
1691+ * add some debug prints to the uinput backend
1692+ * drop the ignoredMice hack again (LP: #1521580)
1693+
1694+ [ Michał Sawicz ]
1695+ * Let qtmir know which apps are exempt from the lifecycle management.
1696+ This way, it can manage its own wakelocks better (and stop
1697+ preventing the system from deep sleeping).
1698+ * Update .pot file in debian/clean when in train
1699+
1700+ -- Gerry Boland <ci-train-bot@canonical.com> Tue, 08 Dec 2015 15:37:58 +0000
1701+
1702+unity8 (8.11+16.04.20151126-0ubuntu2) xenial; urgency=medium
1703+
1704+ * Rebuild against Qt 5.5.1.
1705+
1706+ -- Timo Jyrinki <timo-jyrinki@ubuntu.com> Mon, 30 Nov 2015 16:19:18 +0200
1707+
11708unity8 (8.11+16.04.20151126-0ubuntu1) xenial; urgency=medium
21709
31710 [ Albert Astals Cid ]
@@ -2229,7 +3936,7 @@ unity8 (8.00+14.10.20140729-0ubuntu1) utopic; urgency=medium
22293936 * Re-architecture unity8 to use the QtMirCompositor library so that
22303937 the Qt scenegraph renderer is used as the Mir compositor, and
22313938 application surfaces are added to the QML scene as items.
2232−
3939+
22333940 [ Michael Zanetti ]
22343941 * Port phone right-edge spread code to use QtCompositor
22353942 * Add right-edge spread animation for tablet
@@ -2503,8 +4210,8 @@ unity8 (7.90+14.10.20140703.1-0ubuntu1) utopic; urgency=low
25034210
25044211unity8 (7.90+14.10.20140701.2-0ubuntu2) utopic; urgency=medium
25054212
2506− * debian/control:
2507− list qtdeclarative5-ubuntu-ui-toolkit-plugin-gles as an alternative
4213+ * debian/control:
4214+ list qtdeclarative5-ubuntu-ui-toolkit-plugin-gles as an alternative
25084215 choice, since provides are not versionned, should restore installability
25094216 on amd64 and i386
25104217
@@ -5606,7 +7313,7 @@ unity8 (7.81.2) saucy; urgency=low
56067313 [ Michał Sawicz ]
56077314 * Fix icons in ApplicationsFilterGrid.qml.
56087315 * Support flipped image in run_on_device.
5609−
7316+
56107317 [ Michael Zanetti ]
56117318 * Don't clear lockscreen when it's fading out.
56127319 * Reworked Launcher folding.
@@ -5691,7 +7398,7 @@ qml-phone-shell (1.79) raring; urgency=low
56917398
56927399 [ Michael Terry ]
56937400 * Make greeter look like the desktop one
5694−
7401+
56957402 [ Gerry Boland ]
56967403 * Fix a bug where a minimized app gets focus after closing another app
56977404 * Applied a workaround to reduce flickering when launching apps
@@ -5707,7 +7414,7 @@ qml-phone-shell (1.79) raring; urgency=low
57077414qml-phone-shell (1.78) raring; urgency=low
57087415
57097416 [ Sergio Schvezov ]
5710− * Replacing the music and ski safari mock apps with calendar and weather in
7417+ * Replacing the music and ski safari mock apps with calendar and weather in
57117418 the launcher (LP: #1178262).
57127419
57137420 [ Daniel d'Andrada ]
@@ -5749,7 +7456,7 @@ qml-phone-shell (1.77) raring; urgency=low
57497456 [ Mathieu Trudel-Lapierre ]
57507457 * debian/control:
57517458 - Drop indicators-client-plugin* Depends for qml-phone-shell to Recommends.
5752− - Add/update Vcs-Browser, Vcs-Bzr and add a notice to uploaders.
7459+ - Add/update Vcs-Browser, Vcs-Bzr and add a notice to uploaders.
57537460 * debian/copyright: fix syntax.
57547461
57557462 [ Michał Sawicz ]
@@ -5759,7 +7466,7 @@ qml-phone-shell (1.77) raring; urgency=low
57597466 * Renamed Media player files to match with new application name.
57607467
57617468 [ Daniel d'Andrada ]
5762− * New: DirectionalDragArea component. An area that detects axis-aligned
7469+ * New: DirectionalDragArea component. An area that detects axis-aligned
57637470 single-finger drag gestures.
57647471 * Make it possible to send touch events from within QML test code.
57657472
@@ -6196,7 +7903,7 @@ qml-phone-shell (1.39) quantal; urgency=low
61967903
61977904qml-phone-shell (1.38) quantal; urgency=low
61987905
6199− * fix launching of notepad
7906+ * fix launching of notepad
62007907
62017908 -- Bill Filler <bill.filler@canonical.com> Fri, 01 Feb 2013 03:21:29 -0500
62027909
@@ -6209,14 +7916,14 @@ qml-phone-shell (1.37) quantal; urgency=low
62097916
62107917qml-phone-shell (1.36) quantal; urgency=low
62117918
6212− * launch real notepad app
7919+ * launch real notepad app
62137920 * fix launching of mock apps
62147921
62157922 -- Bill Filler <bill.filler@canonical.com> Thu, 31 Jan 2013 21:36:05 -0500
62167923
62177924qml-phone-shell (1.35) quantal; urgency=low
62187925
6219− * integrate ubuntu-browser instead of snowshoe
7926+ * integrate ubuntu-browser instead of snowshoe
62207927
62217928 -- Bill Filler <bill.filler@canonical.com> Thu, 31 Jan 2013 17:33:37 -0500
62227929
@@ -6300,7 +8007,7 @@ qml-phone-shell (1.22) quantal; urgency=low
63008007
63018008qml-phone-shell (1.21) quantal; urgency=low
63028009
6303− * New release with fullscreen launcher fixes
8010+ * New release with fullscreen launcher fixes
63048011
63058012 -- Bill Filler <bill.filler@canonical.com> Fri, 07 Dec 2012 09:36:37 +0000
63068013
@@ -6312,7 +8019,7 @@ qml-phone-shell (1.20) quantal; urgency=low
63128019
63138020qml-phone-shell (1.19) quantal; urgency=low
63148021
6315− * enable multi-threaded render for apps
8022+ * enable multi-threaded render for apps
63168023
63178024 -- Bill Filler <bill.filler@canonical.com> Wed, 05 Dec 2012 17:34:09 +0000
63188025
@@ -6320,7 +8027,7 @@ qml-phone-shell (1.18) quantal; urgency=low
63208027
63218028 [ Bill Filler ]
63228029 * update launcher to use wk2-render (chromeless webkit) for facebook
6323− and twitter
8030+ and twitter
63248031
63258032 -- Florian Boucault <florian.boucault@canonical.com> Wed, 05 Dec 2012 12:20:50 +0000
63268033
@@ -6332,7 +8039,7 @@ qml-phone-shell (1.17) quantal; urgency=low
63328039
63338040qml-phone-shell (1.16) quantal; urgency=low
63348041
6335− * fix to launch new gallery with correct args
8042+ * fix to launch new gallery with correct args
63368043
63378044 -- Bill Filler <bill.filler@canonical.com> Thu, 29 Nov 2012 17:04:36 -0500
63388045
@@ -6394,7 +8101,7 @@ qml-phone-shell (1.2) quantal; urgency=low
63948101
63958102qml-phone-shell (1.1) quantal; urgency=low
63968103
6397− * comment out console.log() to prevent crash
8104+ * comment out console.log() to prevent crash
63988105
63998106 -- Bill Filler <bill.filler@canonical.com> Sun, 28 Oct 2012 22:18:36 +0100
64008107
@@ -6422,19 +8129,19 @@ qml-phone-shell (0.7) quantal; urgency=low
64228129 * qml-phone-shell.conf: better setup of env vars and launch
64238130 via dbus-luanch to properly setup session bus
64248131 * shellapplication.cpp: don't setup custom env before launching
6425− processes
8132+ processes
64268133
64278134 -- Bill Filler <bill.filler@canonical.com> Sun, 21 Oct 2012 11:32:42 +0200
64288135
64298136qml-phone-shell (0.6) quantal; urgency=low
64308137
6431− * added additional Android env vars to upstart script
8138+ * added additional Android env vars to upstart script
64328139
64338140 -- Bill Filler <bill.filler@canonical.com> Fri, 19 Oct 2012 09:35:25 -0400
64348141
64358142qml-phone-shell (0.5) quantal; urgency=low
64368143
6437− * added support to launch telephony-app
8144+ * added support to launch telephony-app
64388145
64398146 -- Bill Filler <bill.filler@canonical.com> Thu, 18 Oct 2012 13:45:25 -0400
64408147
@@ -6461,3 +8168,8 @@ qml-phone-shell (0.1) quantal; urgency=low
64618168 * Initial release
64628169
64638170 -- Bill Filler <bill.filler@canonical.com> Wed, 10 Oct 2012 10:19:53 -0400
8171+unity8 (8.15+17.04.20170404.7-0ubuntu2) zesty; urgency=medium
8172+
8173+ [ Michael Zanetti ]
8174+ * Make the default store uri point to gnome software center
8175+
debian/control+224−160
@@ -2,207 +2,271 @@ Source: unity8
22Section: x11
33Priority: optional
44Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
5−Build-Depends: cmake,
6− dbus-test-runner,
7− debhelper (>= 9),
8− doxyqml,
9−# To allow cross-compiling to work, we also must append :native
10−# to g++ so we don't try to run armhf g++
11−# on an x86 CPU for eaxmple, when cross-compiling.
12− g++:native,
13− libandroid-properties-dev,
14− graphviz,
15− gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
16− libconnectivity-qt1-dev,
17− libevdev-dev,
18− libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
19− libgl1-mesa-dri,
20− libgles2-mesa-dev[armhf],
21− libglib2.0-dev,
22− libgsettings-qt-dev,
23− libhardware-dev,
24− libpam0g-dev,
25− libpay2-dev,
26− libpulse-dev,
27− libqmenumodel-dev (>= 0.2.9),
28− libqt5svg5-dev,
29− libqt5xmlpatterns5-dev,
30− libsystemsettings-dev,
31− libudev-dev,
32− libunity-api-dev (>= 7.103),
33− libusermetricsoutput1-dev,
34− libxcb1-dev,
35− pkg-config,
36− python3-all:any,
37− python3-setuptools,
38− qml-module-qt-labs-folderlistmodel,
39− qml-module-qtquick-layouts,
40− qml-module-qtquick-xmllistmodel,
41− qml-module-qtquick2,
42− qml-module-qtsysteminfo,
43− qml-module-qttest,
44− qt5-default,
45− qtbase5-dev (>= 5.4),
46− qtbase5-dev-tools,
47− qtbase5-private-dev (>= 5.4),
48− qtdeclarative5-dev (>= 5.4),
49− qtdeclarative5-dev-tools,
50− qtdeclarative5-private-dev (>= 5.4),
51− qtdeclarative5-qtmultimedia-plugin,
52− qtdeclarative5-ubuntu-content1,
53− qtdeclarative5-ubuntu-settings-components (>= 0.6),
54− qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1676) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1676),
55− qtdeclarative5-ubuntu-web-plugin,
56− ttf-ubuntu-font-family,
5+Build-Depends:
6+ android-headers,
7+ cmake,
8+ cmake-extras,
9+ dbus-test-runner,
10+ debhelper (>= 9),
11+ dh-apparmor,
12+ doxyqml,
13+ g++:native,
14+ gdb,
15+ graphviz,
16+ gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
17+ libandroid-properties-dev,
18+ libconnectivity-qt1-dev (>= 0.7.1),
19+ libevdev-dev,
20+ libgeonames-dev (>= 0.2),
21+ libgl1-mesa-dev[!arm64 !armhf] | libgl-dev[!arm64 !armhf],
22+ libgl1-mesa-dri,
23+ libgles2-mesa-dev[arm64 armhf],
24+ libglib2.0-dev,
25+ libgnome-desktop-3-dev,
26+ libgsettings-qt-dev,
27+ libhardware-dev,
28+ liblightdm-qt5-3-dev,
29+ libpam0g-dev,
30+ libpulse-dev,
31+ libqmenumodel-dev (>= 0.2.12),
32+ libqt5sql5-sqlite,
33+ libqt5svg5-dev,
34+ libqt5xmlpatterns5-dev,
35+ libqtdbusmock1-dev (>= 0.7),
36+ libqtdbustest1-dev,
37+ libsystemsettings-dev,
38+ libubuntu-app-launch2-dev,
39+ libubuntu-download-manager-common-dev,
40+ libubuntugestures5-dev (>= 1.3.2030),
41+ libubuntugestures5-private-dev (>= 1.3.2030),
42+ libudev-dev,
43+ libudm-common-dev,
44+ libunity-api-dev (>= 8.7),
45+ libusermetricsoutput1-dev,
46+ libx11-dev[!arm64 !armhf],
47+ libxcb1-dev[!arm64 !armhf],
48+ libxi-dev[!arm64 !armhf],
49+ pkg-config,
50+ python3-all:any,
51+ python3-setuptools,
52+ qml-module-qt-labs-folderlistmodel,
53+ qml-module-qt-labs-settings,
54+ qml-module-qtmultimedia (>= 5.6),
55+ qml-module-qtqml-statemachine,
56+ qml-module-qtquick-layouts,
57+ qml-module-qtquick-xmllistmodel,
58+ qml-module-qtquick2,
59+ qml-module-qtsysteminfo,
60+ qml-module-qttest,
61+ qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
62+ qml-module-ubuntu-layouts,
63+ qml-module-ubuntu-settings-components,
64+ qml-module-ubuntu-test,
65+ qtbase5-dev (>= 5.6),
66+ qtbase5-dev-tools,
67+ qtbase5-private-dev (>= 5.6),
68+ qtdbustest-runner,
69+ qtdeclarative5-dev (>= 5.6),
70+ qtdeclarative5-dev-tools,
71+ qtdeclarative5-private-dev (>= 5.6),
72+ qtdeclarative5-ubuntu-content1,
73+ ttf-ubuntu-font-family,
74+ ubports-wallpapers,
75+ xvfb,
5776Standards-Version: 3.9.4
58−Homepage: http://launchpad.net/unity
59−# If you aren't a member of ~unity-team but need to upload
60−# packaging changes, just go ahead. ~unity-team will notice
61−# and sync up the code again.
62−Vcs-Bzr: https://code.launchpad.net/unity8
63−Vcs-Browser: https://bazaar.launchpad.net/~unity-team/unity8/trunk
77+Homepage: https://github.com/ubports/unity8
78+Vcs-Git: https://github.com/ubports/unity8
79+XS-Testsuite: autopkgtest
6480X-Ubuntu-Use-Langpack: yes
6581
6682Package: indicators-client
67−Architecture: amd64 armhf i386
68−Depends: qmenumodel-qml (>= 0.2.9),
69− qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1627) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1627),
70− unity8 (= ${binary:Version}),
71− ${misc:Depends},
72− ${shlibs:Depends},
83+Architecture: any
84+Depends:
85+ qmenumodel-qml (>= 0.2.11),
86+ qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
87+ unity8 (= ${binary:Version}),
88+ ${misc:Depends},
89+ ${shlibs:Depends},
7390Description: Indicators client test application
7491 This package contains the client application for indicators used by autopilot
7592
76−Package: unity-scope-tool
93+Package: unity8-greeter
7794Architecture: any
78−Depends: unity8-common (= ${source:Version}),
79− unity8-private (= ${binary:Version}),
80− ${misc:Depends},
81− ${shlibs:Depends},
82−# We do call pkg-config libunity-scopes from the code
83− pkg-config,
84− libunity-scopes-dev,
85−Description: Development tool for Unity scopes
86− This package contains the development tool for new generation Unity scopes, based
87− on Unity8.
95+Depends:
96+ unity-system-compositor,
97+ unity8 (= ${binary:Version}),
98+ ${misc:Depends},
99+ ${shlibs:Depends},
100+Recommends:
101+ lightdm,
102+Provides:
103+ lightdm-greeter,
104+Description: The Unity8 Greeter
105+ The Unity 8 greeter is the primary login greeter for Ubuntu devices.
88106
89107Package: unity8
90108Architecture: any
91−Provides: indicator-renderer,
92−Depends: dmz-cursor-theme,
93− gsettings-desktop-schemas,
94− libcap2-bin,
95− libglib2.0-bin,
96− qmenumodel-qml (>= 0.2.9),
97− qml-module-qt-labs-folderlistmodel,
98− qml-module-qtquick-xmllistmodel,
99− qml-module-qtsysteminfo,
100− qtdeclarative5-gsettings1.0,
101− qtdeclarative5-qtmir-plugin (>= 0.4.5),
102− qtdeclarative5-ubuntu-telephony0.1,
103− qtdeclarative5-ubuntu-web-plugin,
104− ubuntu-system-settings,
105− unity-launcher-impl-7,
106− unity8-common (= ${source:Version}),
107− unity8-private (= ${binary:Version}),
108− unity8-private | unity-launcher-impl,
109− ${misc:Depends},
110− ${shlibs:Depends},
111−Recommends: unity-scope-click,
112− unity-scope-mediascanner2,
113− unity-scope-scopes,
114−Breaks: indicator-network (<< 0.5.1+14.10.20141014),
115− ubuntu-touch-session (<< 0.107),
116− unity8-greeter (<< 7.89),
117−Replaces: ubuntu-touch-session (<< 0.82~),
118− unity8-greeter (<< 7.89),
119−Conflicts: ubuntu-system-settings-wizard,
109+Provides:
110+ indicator-renderer,
111+Depends:
112+ dmz-cursor-theme,
113+ gsettings-desktop-schemas,
114+ libcap2-bin,
115+ libglib2.0-bin,
116+ qmenumodel-qml (>= 0.2.11),
117+ qml-module-biometryd,
118+ qml-module-qt-labs-folderlistmodel,
119+ qml-module-qt-labs-settings,
120+ qml-module-qtqml-statemachine,
121+ qml-module-qtquick-xmllistmodel,
122+ qml-module-qtsysteminfo,
123+ qtdeclarative5-qtmir-plugin (>= 0.4.8),
124+ qtdeclarative5-ubuntu-telephony0.1,
125+ ubuntu-system-settings (>= 0.4),
126+ unity-launcher-impl-13,
127+ unity8-common (= ${source:Version}),
128+ unity8-private (= ${binary:Version}),
129+ unity8-private | unity-launcher-impl,
130+ ${misc:Depends},
131+ ${shlibs:Depends},
132+Recommends:
133+ indicator-keyboard,
134+ indicator-session,
135+ unity-greeter-session-broadcast,
136+Breaks:
137+ indicator-network (<< 0.5.1+14.10.20141014),
138+ ubuntu-keyboard (<< 0.100),
139+ ubuntu-touch-session (<< 0.107),
140+ unity-scope-tool,
141+ unity8-greeter (<< 7.89),
142+Replaces:
143+ ubuntu-touch-session (<< 0.82~),
144+ unity-scope-tool,
145+ unity8-greeter (<< 7.89),
146+Conflicts:
147+ ubuntu-system-settings-wizard,
120148Description: Unity 8 shell
121149 The Unity 8 shell is the primary user interface for Ubuntu devices.
122150
123151Package: unity8-common
124152Architecture: all
125−Depends: qml-module-qtquick-layouts,
126− qtdeclarative5-ubuntu-settings-components (>= 0.6),
127− qtdeclarative5-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
128− qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1627) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1627),
129− qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
130− ubuntu-thumbnailer-impl-0,
131− unity-application-impl-11,
132− unity-notifications-impl-3,
133− unity-plugin-scopes | unity-scopes-impl,
134− unity-scopes-impl-7,
135− unity8-fake-env | unity-application-impl,
136− ${misc:Depends},
137−Breaks: unity8 (<< 7.86),
138−Replaces: unity8 (<< 7.86),
153+Depends:
154+ qml-module-qtquick-layouts,
155+ qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
156+ qml-module-ubuntu-settings-components,
157+ qml-module-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
158+ qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
159+ qttranslations5-l10n,
160+ ubuntu-thumbnailer-impl-0,
161+ unity-application-impl-27,
162+ unity-notifications-impl-3,
163+ unity8-schemas,
164+ unity8-tests | unity-application-impl,
165+ ${misc:Depends},
166+Breaks:
167+ unity8 (<< 7.86),
168+Replaces:
169+ unity8 (<< 7.86),
139170Description: Unity 8 shell (common files)
140171 The Unity 8 shell is the primary user interface for Ubuntu devices.
141172 .
142− This package contains the QML, graphics and locale files shared between
143− unity8 and unity-scope-tool.
173+ This package contains the QML, graphics and locale files for unity8.
144174
145175Package: unity8-autopilot
146176Architecture: all
147−Depends: autopilot-qt5 (>= 1.4),
148− gir1.2-glib-2.0,
149− gir1.2-notify-0.7,
150− libqt5test5,
151− libqt5widgets5,
152− ofono-phonesim,
153− python3-autopilot,
154− python3-evdev,
155− python3-fixtures,
156− python3-gi,
157− qttestability-autopilot (>= 1.4),
158− ubuntu-ui-toolkit-autopilot (>= 1.2.1485+15.04.20150417.1-0ubuntu1),
159− unity-scope-click,
160− unity8 (= ${source:Version}),
161− unity8-fake-env (= ${source:Version}),
162− url-dispatcher-tools,
163− xvfb,
164− ${misc:Depends},
165− ${python3:Depends},
166− ${shlibs:Depends},
177+Depends:
178+ autopilot-qt5 (>= 1.4),
179+ gir1.2-glib-2.0,
180+ gir1.2-notify-0.7,
181+ libqt5test5,
182+ libqt5widgets5,
183+ ofono-phonesim,
184+ python3-autopilot,
185+ python3-evdev,
186+ python3-fixtures,
187+ python3-gi,
188+ qttestability-autopilot (>= 1.4),
189+ ubuntu-ui-toolkit-autopilot (>= 1.3.2030),
190+ unity8 (= ${source:Version}),
191+ unity8-tests (= ${source:Version}),
192+ url-dispatcher-tools,
193+ xvfb,
194+ ${misc:Depends},
195+ ${python3:Depends},
167196Description: Test package for Unity 8 shell
168197 Autopilot tests for the unity8 package
169198
170−Package: unity8-fake-env
199+Package: unity8-tests
171200Architecture: any
172201Multi-Arch: same
173−Pre-Depends: ${misc:Pre-Depends},
174−Depends: ${misc:Depends},
175− ${shlibs:Depends},
176−Provides: unity-application-impl,
177− unity-application-impl-11,
178−Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1)
179−Description: Fake environment for running Unity 8 shell
202+Pre-Depends:
203+ ${misc:Pre-Depends},
204+Depends:
205+ dbus-test-runner,
206+ parallel,
207+ qt5-default,
208+ qtdbustest-runner,
209+ qtdeclarative5-dev-tools,
210+ unity8 (= ${source:Version}),
211+ xvfb,
212+ ${misc:Depends},
213+ ${shlibs:Depends},
214+Provides:
215+ unity-application-impl,
216+ unity-application-impl-27,
217+ unity8-fake-env,
218+Replaces:
219+ unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1),
220+ unity8-fake-env,
221+Conflicts:
222+ unity8-fake-env,
223+Description: Scripts and mocks for running Unity 8 shell tests
180224 Provides fake implementations of some QML modules used by Unity 8 shell
181− (e.g Ubuntu.Application) so that you can run it in a sandboxed environment.
225+ (e.g Ubuntu.Application) so that you can run it in a sandboxed environment
226+ and scripts to run its test suite.
182227
183228Package: unity8-private
184229Architecture: any
185230Multi-Arch: same
186−Pre-Depends: ${misc:Pre-Depends},
187−Depends: accountsservice-ubuntu-schemas (>= 0.0.3),
188− gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
189− libhardware2,
190− pay-service,
191− unity-schemas (>= 7.3.1+14.10.20140915),
192− ${misc:Depends},
193− ${shlibs:Depends},
194−Provides: unity-launcher-impl,
195− unity-launcher-impl-7,
231+Pre-Depends:
232+ ${misc:Pre-Depends},
233+Depends:
234+ accountsservice-ubuntu-schemas (>= 0.0.7),
235+ gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
236+ libhardware2,
237+ qml-module-qtmultimedia,
238+ qtdeclarative5-gsettings1.0,
239+ unity8-schemas,
240+ ${misc:Depends},
241+ ${shlibs:Depends},
242+Provides:
243+ unity-launcher-impl,
244+ unity-launcher-impl-13,
196245Description: Unity 8 private libs
197246 The Unity 8 shell is the primary user interface for Ubuntu devices.
198247 .
199248 This package contains the private libraries for QML and other components
200249 only used by the shell.
201250
251+Package: unity8-schemas
252+Architecture: all
253+Multi-Arch: foreign
254+Depends:
255+ ${misc:Depends},
256+Replaces:
257+ unity-schemas (>= 7.3.1+14.10.20140915),
258+Breaks:
259+ unity-schemas (>= 7.3.1+14.10.20140915),
260+Description: Unity 8 schemas
261+ The Unity 8 shell is the primary user interface for Ubuntu devices.
262+ .
263+ This package contains the configuration schemas used by unity.
264+
202265Package: unity8-doc
203266Section: doc
204267Architecture: all
205268Multi-Arch: foreign
206−Depends: ${misc:Depends},
269+Depends:
270+ ${misc:Depends},
207271Description: Documentation for Unity8
208272 The Unity 8 shell is the primary user interface for Ubuntu devices. (documentation)
debian/rules+23−8
@@ -7,14 +7,16 @@ include /usr/share/dpkg/default.mk
77#export DH_VERBOSE=1
88export DPKG_GENSYMBOLS_CHECK_LEVEL=4
99export NO_PNG_PKG_MANGLE=1
10+export QT_SELECT=qt5
11+
12+DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
13+
14+# Skip tests on the archs they are known to be flaky with current configuration
15+testskip_architectures := arm64 powerpc ppc64el s390x
1016
1117%:
1218 dh $@ --parallel --fail-missing --with python3
1319
14−override_dh_auto_clean:
15− dh_auto_clean
16− rm -rf builddir
17−
1820override_dh_auto_configure:
1921 # Debian defines CMAKE_INSTALL_LOCALSTATEDIR as /usr/var, which is wrong.
2022 # So until Debian bug 719148 is fixed, do it ourselves.
@@ -22,7 +24,19 @@ override_dh_auto_configure:
2224
2325override_dh_auto_build:
2426 # doc is not a default target
25− dh_auto_build -- all doc
27+ dh_auto_build -- -O all doc
28+
29+override_dh_auto_test:
30+ # Run the entire test battery
31+ # Parallel tests have a risk of starting xvfb on the same DISPLAY multiple times,
32+ # causing the whole battery to fail.
33+ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
34+ifneq (,$(filter $(DEB_HOST_ARCH),$(testskip_architectures)))
35+ -dh_auto_test --no-parallel -- -O -k xvfballtests
36+else
37+ dh_auto_test --no-parallel -- -O -k xvfballtests
38+endif
39+endif
2640
2741override_dh_install:
2842 # install autopilot tests
@@ -35,8 +49,9 @@ override_dh_install:
3549
3650# use private lib directories
3751override_dh_makeshlibs:
38− dh_makeshlibs -Nunity8-private -Nunity8-fake-env
52+ dh_makeshlibs -Nunity8-private -Nunity8-tests
3953
40−# libMockLightDM-qml.so links against liblightdm-qt5-2.so which doesn't exist
4154override_dh_shlibdeps:
42− dh_shlibdeps -XlibMockLightDM-qml.so
55+ # Some mock libraries link against liblightdm-qt5-3.so which we want to
56+ # avoid, since we only really link against our mock one, not the system one.
57+ dh_shlibdeps -XlibMockAccountsService-qml.so -Lunity8-private
debian/shlibs.localnew file+1
@@ -0,0 +1 @@
1+libunity8-private 0 unity8-private
debian/source/formatdeleted−1
@@ -1 +0,0 @@
1−1.0
debian/tests/autopilot.shnew file+13
@@ -0,0 +1,13 @@
1+#!/bin/sh
2+
3+# log all commands and abort on error
4+set -xe
5+
6+if [ ! -f /system/build.prop ]; then
7+ echo "WARNING: Skipping autopilot test, will only run on devices at the moment."
8+ exit 0
9+fi
10+
11+initctl --session stop unity8
12+autopilot3 run --verbose --format xml --output "${ADT_ARTIFACTS}/unity8.xml" unity8
13+initctl --session start unity8
debian/tests/control+9−3
@@ -1,5 +1,11 @@
11Tests: qmluitests.sh
22Restrictions: allow-stderr
3−Depends: @,
4− @builddeps@,
5− xvfb,
3+Depends:
4+ dpkg-dev,
5+ unity8-tests,
6+
7+Tests: autopilot.sh
8+Restrictions: allow-stderr,
9+ isolation-machine,
10+Depends:
11+ unity8-autopilot,
debian/tests/qmluitests.sh+6−14
@@ -1,19 +1,11 @@
11#!/bin/sh
2+# -*- Mode: sh; indent-tabs-mode: nil; tab-width: 4 -*-
23
3−SHELL_QML_PATH=$(pkg-config --variable=plugindir unity-shell-api)
4−UNITY_SOURCE_DIR=$(readlink -f $(dirname $(readlink -f $0))/../..)
4+# log all commands and abort on error
5+set -xe
56
6−dh_auto_configure -- -DCMAKE_INSTALL_LOCALSTATEDIR="/var" \
7− -DARTIFACTS_DIR=${ADT_ARTIFACTS} \
8− -DUNITY_PLUGINPATH=${SHELL_QML_PATH} \
9− -DUNITY_MOCKPATH=${SHELL_QML_PATH}/mocks
10−dh_auto_build --parallel -- -C tests/mocks
11−dh_auto_build --parallel -- -C tests/plugins
12−dh_auto_build --parallel -- -C tests/qmltests
13−dh_auto_build --parallel -- -C tests/uqmlscene
14−dh_auto_build --parallel -- -C tests/utils
7+DEB_HOST_MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH)
158
16−export UNITY_SOURCE_DIR
9+export ARTIFACTS_DIR="${ADT_ARTIFACTS}"
1710
18−# FIXME: --parallel here causes some failures
19−dh_auto_build -- -k xvfballtests
11+/usr/lib/$DEB_HOST_MULTIARCH/unity8/tests/scripts/xvfballtests.sh
debian/unity-scope-tool.installdeleted−2
@@ -1,2 +0,0 @@
1−usr/bin/unity-scope-tool
2−usr/share/unity8/ScopeTool.qml
debian/unity8-common.install−2
@@ -1,7 +1,5 @@
1−usr/share/glib-2.0/schemas
21usr/share/locale
32usr/share/unity8/Components
4−usr/share/unity8/Dash
53usr/share/unity8/Notifications
64usr/share/unity8/graphics
75var/lib/polkit-1/localauthority/10-vendor.d
debian/unity8-common.udevnew file+2
@@ -0,0 +1,2 @@
1+# Make local foreground session able to inject input
2+KERNEL=="uinput", SUBSYSTEM=="misc", TAG+="uaccess"
debian/unity8-doc.install+1
@@ -1 +1,2 @@
1+doc/devices.conf usr/share/doc/unity8/
12usr/share/doc/unity8/*
debian/unity8-greeter.installnew file+5
@@ -0,0 +1,5 @@
1+data/unity8-greeter-init.conf usr/share/upstart/sessions/
2+data/unity8-greeter-wrapper usr/bin/
3+data/unity8-greeter.pkla /var/lib/polkit-1/localauthority/10-vendor.d/
4+usr/share/lightdm/greeters/unity8-greeter.desktop
5+usr/share/lightdm/lightdm.conf.d/51-unity8-greeter.conf
debian/unity8-private.install+4−4
@@ -1,18 +1,18 @@
11usr/lib/*/libunity8-private.*
2−usr/lib/*/unity8/libUbuntuGestures*
32usr/lib/*/unity8/qml/AccountsService
43usr/lib/*/unity8/qml/Cursor
5−usr/lib/*/unity8/qml/Dash
64usr/lib/*/unity8/qml/GlobalShortcut
75usr/lib/*/unity8/qml/Greeter
8−usr/lib/*/unity8/qml/IntegratedLightDM
6+usr/lib/*/unity8/qml/LightDM
97usr/lib/*/unity8/qml/Lights
108usr/lib/*/unity8/qml/Powerd
11−usr/lib/*/unity8/qml/ScreenGrabber
9+usr/lib/*/unity8/qml/ScreenshotDirectory
1210usr/lib/*/unity8/qml/SessionBroadcast
11+usr/lib/*/unity8/qml/UInput
1312usr/lib/*/unity8/qml/Ubuntu
1413usr/lib/*/unity8/qml/Unity
1514usr/lib/*/unity8/qml/Utils
15+usr/lib/*/unity8/qml/WindowManager
1616usr/lib/*/unity8/qml/Wizard
1717usr/share/accountsservice/interfaces
1818usr/share/dbus-1/interfaces
debian/unity8-schemas.installnew file+1
@@ -0,0 +1 @@
1+usr/share/glib-2.0/schemas
debian/unity8-fake-env.install → debian/unity8-tests.installrenamed+4−1
@@ -2,5 +2,8 @@ data/unity-mock-indicator-service.conf usr/share/upstart/sessions/
22usr/bin/unity-mock-indicator-service
33usr/lib/*/unity8/qml/mocks
44usr/lib/*/unity8/qml/nonmirplugins
5−usr/lib/*/unity8/qml/scopefakes
5+usr/lib/*/unity8/qml/utils
6+usr/lib/*/unity8/tests
7+usr/lib/*/unity8/uqmlscene
68usr/share/unity8/mocks
9+usr/share/unity8/tests
debian/unity8-tests.lintian-overridesnew file+1
@@ -0,0 +1 @@
1+unity8-tests: unusual-interpreter usr/lib/*/unity8/tests/scripts/*.sh #!/usr/bin/parallel
debian/unity8.install+8−9
@@ -1,20 +1,19 @@
1−var/lib/unity8/version
2−data/unity8-dash.conf usr/share/upstart/sessions/
1+data/devices.conf etc/ubuntu/
2+data/test.sensors etc/ubuntusensors/
33data/unity8-filewatcher.conf usr/share/upstart/sessions/
44data/unity8.conf usr/share/upstart/sessions/
55usr/bin/unity8
6−usr/bin/unity8-dash
7−usr/share/applications/unity8-dash.desktop
86usr/share/applications/unity8.desktop
7+usr/share/unity8/ApplicationMenus
8+usr/share/unity8/DeviceConfiguration.qml
9+usr/share/unity8/DisabledScreenNotice.qml
910usr/share/unity8/Greeter
1011usr/share/unity8/Launcher
12+usr/share/unity8/OrientedShell.qml
1113usr/share/unity8/Panel
1214usr/share/unity8/Rotation
13−usr/share/unity8/DeviceConfiguration.qml
14−usr/share/unity8/OrientedShell.qml
15−usr/share/unity8/DisabledScreenNotice.qml
1615usr/share/unity8/Shell.qml
17−usr/share/unity8/Stages
16+usr/share/unity8/Stage
1817usr/share/unity8/Tutorial
1918usr/share/unity8/Wizard
20−usr/share/url-dispatcher/urls/unity8-dash.url-dispatcher
19+var/lib/unity8/version
doc/devices.confnew file+45
@@ -0,0 +1,45 @@
1+# This file can hold multiple device configs. Devices are separated by sections.
2+#
3+# SupportedOrientations holds a list of all enabled orientations. A standard
4+# phone will usually have Portrait,Landcape,InvertedLandscape in order to
5+# disable upside down usage.
6+#
7+# PrimaryOrientation gives the orientation the device will start up with
8+# when there is no orientations sensor input available (yet) or lock to
9+# when an application specifies to be locked to PrimaryOrientation.
10+#
11+# The other Orientation settings can be used to re-map the orientations.
12+# A device might be used with different orientations than how the screen
13+# is physically mounted on the hardware.
14+#
15+# Category can be phone, tablet, or desktop. This option determines
16+# whether the side stage is shown (tablet) or not (phone). Using
17+# desktop will load the shell in windowed mode. Note that the user
18+# can override/change this by connecting input hardware or change
19+# user settings.
20+#
21+# Any options not listed will default to the values of the example below.
22+
23+[devicename]
24+SupportedOrientations=Portrait,InvertedPortrait,Landscape,InvertedLandscape
25+PrimaryOrientation=PrimaryOrienation
26+PortraitOrientation=Portrait
27+InvertedPortraitOrientation=InvertedPortrait
28+LandscapeOrientation=Landscape
29+InvertedLandscapeOrientation=InvertedLandscape
30+Category=phone
31+
32+# Example for the Nexus 7
33+# This device has the screen mounted in portrait, but we run it as a landscape
34+# device and we want the side stage on it.
35+[flo]
36+PrimaryOrientation=LandscapeOrienation
37+Category=tablet
38+
39+# Example for the Nexus 4
40+# The screen is already mounted the way we want it, so no special config
41+# required. However, we don't want the phone to rotate upside down, so lets
42+# restrict that.
43+[mako]
44+SupportedOrientations=Portrait,Landscape,InvertedLandscape
45+Category=phone
include/paths.h.in+59−25
@@ -1,8 +1,5 @@
11/*
2− * Copyright (C) 2012 Canonical, Ltd.
3− *
4− * Authors:
5− * Ugo Riboni <ugo.riboni@canonical.com>
2+ * Copyright (C) 2012-2016 Canonical, Ltd.
63 *
74 * This program is free software; you can redistribute it and/or modify
85 * it under the terms of the GNU General Public License as published by
@@ -17,8 +14,7 @@
1714 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1815 */
1916
20−#ifndef PATHS_H
21−#define PATHS_H
17+#pragma once
2218
2319// Qt
2420#include <QtCore/QCoreApplication>
@@ -27,10 +23,28 @@
2723#include <QtQml/QQmlEngine>
2824#include <QStandardPaths>
2925
26+inline QString installRoot() {
27+ static QString installRoot;
28+ static bool installRootSet = false;
29+ if (!installRootSet) {
30+ QString snapRoot = QFile::decodeName(qgetenv("SNAP"));
31+ if (!snapRoot.isEmpty() && QCoreApplication::applicationDirPath() ==
32+ QDir(snapRoot + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@")).canonicalPath()) {
33+ installRoot = snapRoot;
34+ } else if (QCoreApplication::applicationDirPath() ==
35+ QDir(QStringLiteral("@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@")).canonicalPath()) {
36+ installRoot = QStringLiteral("");
37+ }
38+ installRootSet = true;
39+ }
40+ return installRoot;
41+}
42+
3043inline bool isRunningInstalled() {
31− static bool installed = (QCoreApplication::applicationDirPath() ==
32− QDir(QStringLiteral("@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@")).canonicalPath());
33− return installed;
44+ // Tests don't use the normal binary, so we want to check binary *and*
45+ // the environment. Installed tests have UNITY_TESTING_DATADIR set.
46+ static bool installed_test_env = !qgetenv("UNITY_TESTING_DATADIR").isEmpty();
47+ return !installRoot().isNull() || installed_test_env;
3448}
3549
3650inline QString buildDirectory() {
@@ -45,24 +59,46 @@ inline QString sourceDirectory() {
4559
4660inline QString translationDirectory() {
4761 if (isRunningInstalled()) {
48− return QStringLiteral("@CMAKE_INSTALL_PREFIX@/share/locale");
62+ return installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/share/locale");
63+ } else {
64+ return buildDirectory() + QStringLiteral("/po/locale");
65+ }
66+}
67+
68+inline QString testDataDir() {
69+ // Can't use isRunningInstalled, since tests don't use the normal unity8
70+ // executable. $UNITY_TESTING_DATADIR is set by installed tests.
71+ QString datadir(qgetenv("UNITY_TESTING_DATADIR"));
72+ if (datadir.isEmpty()) {
73+ return sourceDirectory() + "/tests";
74+ } else {
75+ return datadir + "/tests";
76+ }
77+}
78+
79+inline QString testLibDir() {
80+ // Can't use isRunningInstalled, since tests don't use the normal unity8
81+ // executable. $UNITY_TESTING_DATADIR is set by installed tests.
82+ QString libdir(qgetenv("UNITY_TESTING_LIBDIR"));
83+ if (libdir.isEmpty()) {
84+ return buildDirectory() + "/tests";
4985 } else {
50− return QString(buildDirectory() + "/po/locale");
86+ return libdir + "/tests";
5187 }
5288}
5389
5490inline QString qmlDirectory() {
5591 if (isRunningInstalled()) {
56− return QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_APP_DIR@/");
92+ return installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_APP_DIR@/");
5793 } else {
58− return QString(sourceDirectory() + "/qml");
94+ return sourceDirectory() + QStringLiteral("/qml");
5995 }
6096}
6197
6298inline QStringList overrideImportPaths() {
6399 QStringList paths;
64100 if (!isRunningInstalled()) {
65− paths << QString(buildDirectory() + "/plugins");
101+ paths << buildDirectory() + QStringLiteral("/plugins");
66102 }
67103 return paths;
68104}
@@ -70,9 +106,9 @@ inline QStringList overrideImportPaths() {
70106inline QStringList nonMirImportPaths() {
71107 QStringList paths;
72108 if (isRunningInstalled()) {
73− paths << QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/nonmirplugins");
109+ paths << installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/nonmirplugins");
74110 } else {
75− paths << QString(buildDirectory() + "/nonmirplugins");
111+ paths << buildDirectory() + QStringLiteral("/nonmirplugins");
76112 }
77113 return paths;
78114}
@@ -80,23 +116,23 @@ inline QStringList nonMirImportPaths() {
80116inline QStringList fallbackImportPaths() {
81117 QStringList paths;
82118 if (isRunningInstalled()) {
83− paths << QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@");
84− paths << QStringLiteral("@USS_PRIVATE_PLUGINDIR@");
85− paths << QStringLiteral("@SHELL_PLUGINDIR@");
86− paths << QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/mocks");
119+ paths << installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@");
120+ paths << installRoot() + QStringLiteral("@USS_PRIVATE_PLUGINDIR@");
121+ paths << installRoot() + QStringLiteral("@SHELL_PLUGINDIR@");
122+ paths << installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/mocks");
87123 } else {
88124 paths << QStringLiteral("@USS_PRIVATE_PLUGINDIR@");
89125 paths << QStringLiteral("@SHELL_PLUGINDIR@");
90− paths << QString(buildDirectory() + "/tests/mocks");
126+ paths << buildDirectory() + QStringLiteral("/tests/mocks");
91127 }
92128 return paths;
93129}
94130
95131inline QString mockPluginsDir() {
96132 if (isRunningInstalled()) {
97− return QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/mocks");
133+ return installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/mocks");
98134 } else {
99− return QString(buildDirectory() + "/tests/mocks");
135+ return buildDirectory() + QStringLiteral("/tests/mocks");
100136 }
101137}
102138
@@ -137,5 +173,3 @@ inline void appendImportPaths(QQmlEngine *engine, const QStringList &paths)
137173 }
138174 engine->setImportPathList(importPathList);
139175}
140−
141−#endif
libs/CMakeLists.txtdeleted−1
@@ -1 +0,0 @@
1−add_subdirectory(UbuntuGestures)
libs/UbuntuGestures/CMakeLists.txtdeleted−41
@@ -1,41 +0,0 @@
1−# in order to include Qt's private headers
2−remove_definitions(-DQT_NO_KEYWORDS)
3−
4−set(UbuntuGestures_SOURCES
5− CandidateInactivityTimer.cpp
6− DebugHelpers.cpp
7− Timer.cpp
8− TimeSource.cpp
9− TouchOwnershipEvent.cpp
10− TouchRegistry.cpp
11− UnownedTouchEvent.cpp
12−)
13−
14−add_definitions(-DUBUNTUGESTURES_LIBRARY)
15−
16−add_library(UbuntuGestures SHARED ${UbuntuGestures_SOURCES})
17−
18−qt5_use_modules(UbuntuGestures Core Quick)
19−
20−# So that Foo.cpp can #include "Foo.moc"
21−include_directories(${CMAKE_CURRENT_BINARY_DIR})
22−
23−install(TARGETS UbuntuGestures
24− DESTINATION ${SHELL_PRIVATE_LIBDIR})
25−
26−
27−# There's no cmake var for v8 include path :-/ so create one
28−LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
29−if(${Qt5Core_VERSION_STRING} VERSION_LESS "5.1.0")
30− SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
31−else()
32− SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/QtV8/${Qt5Core_VERSION_STRING}/QtV8)
33−endif()
34−
35−# DANGER! DANGER! Using Qt's private API!
36−include_directories(
37− ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
38− ${Qt5Quick_INCLUDE_DIRS}
39− ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
40− ${Qt5V8_PRIVATE_INCLUDE_DIR}
41−)
libs/UbuntuGestures/CandidateInactivityTimer.cppdeleted−46
@@ -1,46 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "CandidateInactivityTimer.h"
18−
19−namespace UbuntuGestures {
20−
21−CandidateInactivityTimer::CandidateInactivityTimer(int touchId, QQuickItem *candidate,
22− AbstractTimer *timer, QObject *parent)
23− : QObject(parent)
24− , m_timer(timer)
25− , m_touchId(touchId)
26− , m_candidate(candidate)
27−{
28− connect(m_timer, &AbstractTimer::timeout,
29− this, &CandidateInactivityTimer::onTimeout);
30− m_timer->setInterval(durationMs);
31− m_timer->setSingleShot(true);
32− m_timer->start();
33−}
34−
35−CandidateInactivityTimer::~CandidateInactivityTimer()
36−{
37− delete m_timer;
38−}
39−
40−void CandidateInactivityTimer::onTimeout()
41−{
42− qWarning("[TouchRegistry] Candidate for touch %d defaulted!", m_touchId);
43− Q_EMIT candidateDefaulted(m_touchId, m_candidate);
44−}
45−
46−} // namespace UbuntuGestures
libs/UbuntuGestures/CandidateInactivityTimer.hdeleted−51
@@ -1,51 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTUGESTURES_CANDIDATE_INACTIVITY_TIMER_H
18−#define UBUNTUGESTURES_CANDIDATE_INACTIVITY_TIMER_H
19−
20−#include <QObject>
21−
22−class QQuickItem;
23−
24−#include "Timer.h"
25−
26−namespace UbuntuGestures {
27−
28−class UBUNTUGESTURES_EXPORT CandidateInactivityTimer : public QObject {
29− Q_OBJECT
30−public:
31− CandidateInactivityTimer(int touchId, QQuickItem *candidate,
32− AbstractTimer *timer,
33− QObject *parent = nullptr);
34−
35− virtual ~CandidateInactivityTimer();
36−
37− const int durationMs = 1000;
38−
39−Q_SIGNALS:
40− void candidateDefaulted(int touchId, QQuickItem *candidate);
41−private Q_SLOTS:
42− void onTimeout();
43−private:
44− AbstractTimer *m_timer;
45− int m_touchId;
46− QQuickItem *m_candidate;
47−};
48−
49−} // namespace UbuntuGestures
50−
51−#endif // UBUNTUGESTURES_CANDIDATE_INACTIVITY_TIMER_H
libs/UbuntuGestures/DebugHelpers.cppdeleted−95
@@ -1,95 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "DebugHelpers.h"
18−#include <QTouchEvent>
19−#include <QMouseEvent>
20−
21−QString touchPointStateToString(Qt::TouchPointState state)
22−{
23− switch (state) {
24− case Qt::TouchPointPressed:
25− return QStringLiteral("pressed");
26− case Qt::TouchPointMoved:
27− return QStringLiteral("moved");
28− case Qt::TouchPointStationary:
29− return QStringLiteral("stationary");
30− case Qt::TouchPointReleased:
31− return QStringLiteral("released");
32− default:
33− return QStringLiteral("INVALID_STATE");
34− }
35−}
36−
37−QString touchEventToString(const QTouchEvent *ev)
38−{
39− QString message;
40−
41− switch (ev->type()) {
42− case QEvent::TouchBegin:
43− message.append("TouchBegin ");
44− break;
45− case QEvent::TouchUpdate:
46− message.append("TouchUpdate ");
47− break;
48− case QEvent::TouchEnd:
49− message.append("TouchEnd ");
50− break;
51− case QEvent::TouchCancel:
52− message.append("TouchCancel ");
53− break;
54− default:
55− message.append("INVALID_TOUCH_EVENT_TYPE ");
56− }
57−
58− foreach(const QTouchEvent::TouchPoint& touchPoint, ev->touchPoints()) {
59− message.append(
60− QStringLiteral("(id:%1, state:%2, scenePos:(%3,%4)) ")
61− .arg(touchPoint.id())
62− .arg(touchPointStateToString(touchPoint.state()))
63− .arg(touchPoint.scenePos().x())
64− .arg(touchPoint.scenePos().y())
65− );
66− }
67−
68− return message;
69−}
70−
71−QString mouseEventToString(const QMouseEvent *ev)
72−{
73− QString message;
74−
75− switch (ev->type()) {
76− case QEvent::MouseButtonPress:
77− message.append("MouseButtonPress ");
78− break;
79− case QEvent::MouseButtonRelease:
80− message.append("MouseButtonRelease ");
81− break;
82− case QEvent::MouseButtonDblClick:
83− message.append("MouseButtonDblClick ");
84− break;
85− case QEvent::MouseMove:
86− message.append("MouseMove ");
87− break;
88− default:
89− message.append("INVALID_MOUSE_EVENT_TYPE ");
90− }
91−
92− message.append(QStringLiteral("pos(%1, %2)").arg(ev->x()).arg(ev->y()));
93−
94− return message;
95−}
libs/UbuntuGestures/DebugHelpers.hdeleted−31
@@ -1,31 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTUGESTURES_DEBUG_HELPER_H
18−#define UBUNTUGESTURES_DEBUG_HELPER_H
19−
20−#include <QString>
21−
22−#include "UbuntuGesturesGlobal.h"
23−
24−class QMouseEvent;
25−class QTouchEvent;
26−
27−UBUNTUGESTURES_EXPORT QString touchPointStateToString(Qt::TouchPointState state);
28−UBUNTUGESTURES_EXPORT QString touchEventToString(const QTouchEvent *ev);
29−UBUNTUGESTURES_EXPORT QString mouseEventToString(const QMouseEvent *ev);
30−
31−#endif // UBUNTUGESTURES_DEBUG_HELPER_H
libs/UbuntuGestures/Pool.hdeleted−124
@@ -1,124 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTUGESTURES_POOL_H
18−#define UBUNTUGESTURES_POOL_H
19−
20−#include <QVector>
21−
22−#include "UbuntuGesturesGlobal.h"
23−
24−/*
25− An object pool.
26− Avoids unnecessary creations/initializations and deletions/destructions of items. Useful
27− in a scenario where items are created and destroyed very frequently but the total number
28− of items at any given time remains small. They're stored in a unordered fashion.
29−
30− To be used in Pool, ItemType needs to have the following methods:
31−
32− - ItemType();
33−
34− A constructor that takes no parameters. An object contructed with it must return false if
35− isValid() is called.
36−
37− - bool isValid() const;
38−
39− Returns wheter the object holds a valid , "filled" state or is empty.
40− Used by Pool to check if the slot occupied by this object is actually available.
41−
42− - void reset();
43−
44− Resets the object to its initial, empty, state. After calling this method, isValid() must
45− return false.
46− */
47−template <class ItemType> class Pool
48−{
49−public:
50− Pool() : m_lastUsedIndex(-1) {
51− }
52−
53− class Iterator {
54− public:
55− Iterator() : index(-1), item(nullptr) {}
56− Iterator(int index, ItemType *item)
57− : index(index), item(item) {}
58−
59− ItemType *operator->() const { return item; }
60− ItemType &operator*() const { return *item; }
61− ItemType &value() const { return *item; }
62−
63− operator bool() const { return item != nullptr; }
64−
65− int index;
66− ItemType *item;
67− };
68−
69− ItemType &getEmptySlot() {
70− Q_ASSERT(m_lastUsedIndex < m_slots.size());
71−
72− // Look for an in-between vacancy first
73− for (int i = 0; i < m_lastUsedIndex; ++i) {
74− ItemType &item = m_slots[i];
75− if (!item.isValid()) {
76− return item;
77− }
78− }
79−
80− ++m_lastUsedIndex;
81− if (m_lastUsedIndex >= m_slots.size()) {
82− m_slots.resize(m_lastUsedIndex + 1);
83− }
84−
85− return m_slots[m_lastUsedIndex];
86− }
87−
88− void freeSlot(Iterator &iterator) {
89− m_slots[iterator.index].reset();
90− if (iterator.index == m_lastUsedIndex) {
91− do {
92− --m_lastUsedIndex;
93− } while (m_lastUsedIndex >= 0 && !m_slots.at(m_lastUsedIndex).isValid());
94− }
95− }
96−
97− // Iterates through all valid items (i.e. the occupied slots)
98− // calling the given function, with the option of ending the loop early.
99− //
100− // bool Func(Iterator& item)
101− //
102− // Returning true means it wants to continue the "for" loop, false
103− // terminates the loop.
104− template<typename Func> void forEach(Func func) {
105− Iterator it;
106− for (it.index = 0; it.index <= m_lastUsedIndex; ++it.index) {
107− it.item = &m_slots[it.index];
108− if (!it.item->isValid())
109− continue;
110−
111− if (!func(it))
112− break;
113− }
114− }
115−
116− bool isEmpty() const { return m_lastUsedIndex == -1; }
117−
118−
119−private:
120− QVector<ItemType> m_slots;
121− int m_lastUsedIndex;
122−};
123−
124−#endif // UBUNTUGESTURES_POOL_H
libs/UbuntuGestures/TimeSource.cppdeleted−49
@@ -1,49 +0,0 @@
1−/*
2− * Copyright (C) 2013 - Canonical Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it
5− * under the terms of the GNU Lesser General Public License, as
6− * published by the Free Software Foundation; either version 2.1 or 3.0
7− * of the License.
8− *
9− * This program is distributed in the hope that it will be useful, but
10− * WITHOUT ANY WARRANTY; without even the implied warranties of
11− * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12− * PURPOSE. See the applicable version of the GNU Lesser General Public
13− * License for more details.
14− *
15− * You should have received a copy of both the GNU Lesser General Public
16− * License along with this program. If not, see <http://www.gnu.org/licenses/>
17− *
18− * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19− */
20−
21−#include "TimeSource.h"
22−
23−#include <QElapsedTimer>
24−
25−namespace UbuntuGestures {
26−class RealTimeSourcePrivate {
27−public:
28− QElapsedTimer timer;
29−};
30−}
31−
32−using namespace UbuntuGestures;
33−
34−RealTimeSource::RealTimeSource()
35− : UbuntuGestures::TimeSource()
36− , d(new RealTimeSourcePrivate)
37−{
38− d->timer.start();
39−}
40−
41−RealTimeSource::~RealTimeSource()
42−{
43− delete d;
44−}
45−
46−qint64 RealTimeSource::msecsSinceReference()
47−{
48− return d->timer.elapsed();
49−}
libs/UbuntuGestures/TimeSource.hdeleted−64
@@ -1,64 +0,0 @@
1−/*
2− * Copyright (C) 2013,2015 Canonical Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it
5− * under the terms of the GNU Lesser General Public License, as
6− * published by the Free Software Foundation; either version 2.1 or 3.0
7− * of the License.
8− *
9− * This program is distributed in the hope that it will be useful, but
10− * WITHOUT ANY WARRANTY; without even the implied warranties of
11− * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12− * PURPOSE. See the applicable version of the GNU Lesser General Public
13− * License for more details.
14− *
15− * You should have received a copy of both the GNU Lesser General Public
16− * License along with this program. If not, see <http://www.gnu.org/licenses/>
17− *
18− * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19− */
20−
21−#ifndef UBUNTUGESTURES_TIMESOURCE_H
22−#define UBUNTUGESTURES_TIMESOURCE_H
23−
24−#include "UbuntuGesturesGlobal.h"
25−#include <QSharedPointer>
26−
27−namespace UbuntuGestures {
28−/*
29− Interface for a time source.
30− */
31−class UBUNTUGESTURES_EXPORT TimeSource {
32−public:
33− virtual ~TimeSource() {}
34− /* Returns the current time in milliseconds since some reference time in the past. */
35− virtual qint64 msecsSinceReference() = 0;
36−};
37−typedef QSharedPointer<TimeSource> SharedTimeSource;
38−
39−/*
40− Implementation of a time source
41− */
42−class RealTimeSourcePrivate;
43−class UBUNTUGESTURES_EXPORT RealTimeSource : public TimeSource {
44−public:
45− RealTimeSource();
46− virtual ~RealTimeSource();
47− qint64 msecsSinceReference() override;
48−private:
49− RealTimeSourcePrivate *d;
50−};
51−
52−/*
53− A fake time source, useful for tests
54− */
55−class FakeTimeSource : public TimeSource {
56−public:
57− FakeTimeSource() { m_msecsSinceReference = 0; }
58− qint64 msecsSinceReference() override { return m_msecsSinceReference; }
59− qint64 m_msecsSinceReference;
60−};
61−
62−} // namespace UbuntuGestures
63−
64−#endif // UBUNTUGESTURES_TIMESOURCE_H
libs/UbuntuGestures/Timer.cppdeleted−152
@@ -1,152 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "Timer.h"
18−
19−namespace UbuntuGestures {
20−
21−Timer::Timer(QObject *parent) : AbstractTimer(parent)
22−{
23− m_timer.setSingleShot(false);
24− connect(&m_timer, &QTimer::timeout, this, &AbstractTimer::timeout);
25−}
26−
27−int Timer::interval() const
28−{
29− return m_timer.interval();
30−}
31−
32−void Timer::setInterval(int msecs)
33−{
34− m_timer.setInterval(msecs);
35−}
36−
37−void Timer::start()
38−{
39− m_timer.start();
40− AbstractTimer::start();
41−}
42−
43−void Timer::stop()
44−{
45− m_timer.stop();
46− AbstractTimer::stop();
47−}
48−
49−bool Timer::isSingleShot() const
50−{
51− return m_timer.isSingleShot();
52−}
53−
54−void Timer::setSingleShot(bool value)
55−{
56− m_timer.setSingleShot(value);
57−}
58−
59−/////////////////////////////////// FakeTimer //////////////////////////////////
60−
61−FakeTimer::FakeTimer(const SharedTimeSource &timeSource, QObject *parent)
62− : UbuntuGestures::AbstractTimer(parent)
63− , m_interval(0)
64− , m_singleShot(false)
65− , m_timeSource(timeSource)
66−{
67−}
68−
69−void FakeTimer::update()
70−{
71− if (!isRunning()) {
72− return;
73− }
74−
75− if (m_nextTimeoutTime <= m_timeSource->msecsSinceReference()) {
76− if (isSingleShot()) {
77− stop();
78− } else {
79− m_nextTimeoutTime += interval();
80− }
81− Q_EMIT timeout();
82− }
83−}
84−
85−void FakeTimer::start()
86−{
87− AbstractTimer::start();
88− m_nextTimeoutTime = m_timeSource->msecsSinceReference() + (qint64)interval();
89−}
90−
91−int FakeTimer::interval() const
92−{
93− return m_interval;
94−}
95−
96−void FakeTimer::setInterval(int msecs)
97−{
98− m_interval = msecs;
99−}
100−
101−bool FakeTimer::isSingleShot() const
102−{
103− return m_singleShot;
104−}
105−
106−void FakeTimer::setSingleShot(bool value)
107−{
108− m_singleShot = value;
109−}
110−
111−/////////////////////////////////// FakeTimerFactory //////////////////////////////////
112−
113−FakeTimerFactory::FakeTimerFactory()
114−{
115− m_timeSource.reset(new FakeTimeSource);
116−}
117−
118−void FakeTimerFactory::updateTime(qint64 targetTime)
119−{
120− qint64 minTimeoutTime = targetTime;
121−
122− for (int i = 0; i < timers.count(); ++i) {
123− FakeTimer *timer = timers[i].data();
124− if (timer && timer->isRunning() && timer->nextTimeoutTime() < minTimeoutTime) {
125− minTimeoutTime = timer->nextTimeoutTime();
126− }
127− }
128−
129− m_timeSource->m_msecsSinceReference = minTimeoutTime;
130−
131− for (int i = 0; i < timers.count(); ++i) {
132− FakeTimer *timer = timers[i].data();
133− if (timer) {
134− timer->update();
135− }
136− }
137−
138− if (m_timeSource->msecsSinceReference() < targetTime) {
139− updateTime(targetTime);
140− }
141−}
142−
143−AbstractTimer *FakeTimerFactory::createTimer(QObject *parent)
144−{
145− FakeTimer *fakeTimer = new FakeTimer(m_timeSource, parent);
146−
147− timers.append(fakeTimer);
148−
149− return fakeTimer;
150−}
151−
152−} // namespace UbuntuGestures
libs/UbuntuGestures/Timer.hdeleted−117
@@ -1,117 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTUGESTURES_TIMER_H
18−#define UBUNTUGESTURES_TIMER_H
19−
20−#include "UbuntuGesturesGlobal.h"
21−#include "TimeSource.h"
22−
23−#include <QObject>
24−#include <QPointer>
25−#include <QTimer>
26−
27−namespace UbuntuGestures {
28−
29−/* Defines an interface for a Timer. Useful for tests. */
30−class UBUNTUGESTURES_EXPORT AbstractTimer : public QObject
31−{
32− Q_OBJECT
33−public:
34− AbstractTimer(QObject *parent) : QObject(parent), m_isRunning(false) {}
35− virtual int interval() const = 0;
36− virtual void setInterval(int msecs) = 0;
37− virtual void start() { m_isRunning = true; }
38− virtual void stop() { m_isRunning = false; }
39− bool isRunning() const { return m_isRunning; }
40− virtual bool isSingleShot() const = 0;
41− virtual void setSingleShot(bool value) = 0;
42−Q_SIGNALS:
43− void timeout();
44−private:
45− bool m_isRunning;
46−};
47−
48−/* Essentially a QTimer wrapper */
49−class UBUNTUGESTURES_EXPORT Timer : public AbstractTimer
50−{
51− Q_OBJECT
52−public:
53− Timer(QObject *parent = nullptr);
54−
55− int interval() const override;
56− void setInterval(int msecs) override;
57− void start() override;
58− void stop() override;
59− bool isSingleShot() const override;
60− void setSingleShot(bool value) override;
61−private:
62− QTimer m_timer;
63−};
64−
65−/* For tests */
66−class UBUNTUGESTURES_EXPORT FakeTimer : public AbstractTimer
67−{
68− Q_OBJECT
69−public:
70− FakeTimer(const SharedTimeSource &timeSource, QObject *parent = nullptr);
71−
72− void update();
73− qint64 nextTimeoutTime() const { return m_nextTimeoutTime; }
74−
75− int interval() const override;
76− void setInterval(int msecs) override;
77− void start() override;
78− bool isSingleShot() const override;
79− void setSingleShot(bool value) override;
80−private:
81− int m_interval;
82− bool m_singleShot;
83− SharedTimeSource m_timeSource;
84− qint64 m_nextTimeoutTime;
85−};
86−
87−class UBUNTUGESTURES_EXPORT AbstractTimerFactory
88−{
89−public:
90− virtual ~AbstractTimerFactory() {}
91− virtual AbstractTimer *createTimer(QObject *parent = nullptr) = 0;
92−};
93−
94−class UBUNTUGESTURES_EXPORT TimerFactory : public AbstractTimerFactory
95−{
96−public:
97− AbstractTimer *createTimer(QObject *parent = nullptr) override { return new Timer(parent); }
98−};
99−
100−class UBUNTUGESTURES_EXPORT FakeTimerFactory : public AbstractTimerFactory
101−{
102−public:
103− FakeTimerFactory();
104− virtual ~FakeTimerFactory() {}
105−
106− void updateTime(qint64 msecsSinceReference);
107− QSharedPointer<TimeSource> timeSource() { return m_timeSource; }
108−
109− AbstractTimer *createTimer(QObject *parent = nullptr) override;
110− QList<QPointer<FakeTimer>> timers;
111−private:
112− QSharedPointer<FakeTimeSource> m_timeSource;
113−};
114−
115−} // namespace UbuntuGestures
116−
117−#endif // UBUNTUGESTURES_TIMER_H
libs/UbuntuGestures/TouchOwnershipEvent.hdeleted−50
@@ -1,50 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTU_TOUCHOWNERSHIPEVENT_H
18−#define UBUNTU_TOUCHOWNERSHIPEVENT_H
19−
20−#include <QEvent>
21−#include "UbuntuGesturesGlobal.h"
22−
23−/*
24− When an item get an ownership event for a touch it can grab/steal that touch
25− with a clean conscience.
26− */
27−class UBUNTUGESTURES_EXPORT TouchOwnershipEvent : public QEvent
28−{
29−public:
30− TouchOwnershipEvent(int touchId, bool gained);
31−
32− static Type touchOwnershipEventType();
33−
34− /*
35− Whether ownership was gained (true) or lost (false)
36− */
37− bool gained() const { return m_gained; }
38−
39− /*
40− Id of the touch whose ownership was granted.
41− */
42− int touchId() const { return m_touchId; }
43−
44−private:
45− static Type m_touchOwnershipType;
46− int m_touchId;
47− bool m_gained;
48−};
49−
50−#endif // UBUNTU_TOUCHOWNERSHIPEVENT_H
libs/UbuntuGestures/TouchRegistry.cppdeleted−548
@@ -1,548 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "TouchRegistry.h"
18−
19−#include <QCoreApplication>
20−#include <QDebug>
21−
22−#pragma GCC diagnostic push
23−#pragma GCC diagnostic ignored "-pedantic"
24−#include <private/qquickitem_p.h>
25−#pragma GCC diagnostic pop
26−
27−#include "CandidateInactivityTimer.h"
28−#include "Timer.h"
29−#include "TouchOwnershipEvent.h"
30−#include "UnownedTouchEvent.h"
31−
32−#define TOUCHREGISTRY_DEBUG 0
33−
34−#if TOUCHREGISTRY_DEBUG
35− #include "DebugHelpers.h"
36− #define UG_DEBUG qDebug() << "[TouchRegistry]"
37−#endif // TOUCHREGISTRY_DEBUG
38−
39−using namespace UbuntuGestures;
40−
41−TouchRegistry *TouchRegistry::m_instance = nullptr;
42−
43−TouchRegistry::TouchRegistry(QObject *parent)
44− : QObject(parent)
45− , m_inDispatchLoop(false)
46− , m_timerFactory(new TimerFactory)
47−{
48−}
49−
50−TouchRegistry::~TouchRegistry()
51−{
52− Q_ASSERT(m_instance != nullptr);
53− m_instance = nullptr;
54− delete m_timerFactory;
55−}
56−
57−TouchRegistry *TouchRegistry::instance()
58−{
59− if (m_instance == nullptr) {
60− m_instance = new TouchRegistry;
61− }
62− return m_instance;
63−}
64−
65−void TouchRegistry::setTimerFactory(AbstractTimerFactory *timerFactory)
66−{
67− delete m_timerFactory;
68− m_timerFactory = timerFactory;
69−}
70−
71−void TouchRegistry::update(const QTouchEvent *event)
72−{
73− #if TOUCHREGISTRY_DEBUG
74− UG_DEBUG << "got" << qPrintable(touchEventToString(event));
75− #endif
76−
77− const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
78− for (int i = 0; i < touchPoints.count(); ++i) {
79− const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
80− if (touchPoint.state() == Qt::TouchPointPressed) {
81− TouchInfo &touchInfo = m_touchInfoPool.getEmptySlot();
82− touchInfo.init(touchPoint.id());
83− } else if (touchPoint.state() == Qt::TouchPointReleased) {
84− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(touchPoint.id());
85−
86− touchInfo->physicallyEnded = true;
87− }
88− }
89−
90− deliverTouchUpdatesToUndecidedCandidatesAndWatchers(event);
91−
92− freeEndedTouchInfos();
93−}
94−
95−void TouchRegistry::deliverTouchUpdatesToUndecidedCandidatesAndWatchers(const QTouchEvent *event)
96−{
97− // TODO: Look into how we could optimize this whole thing.
98− // Although it's not really a problem as we should have at most two candidates
99− // for each point and there should not be many active points at any given moment.
100− // But having three nested for-loops does scare.
101−
102− const QList<QTouchEvent::TouchPoint> &updatedTouchPoints = event->touchPoints();
103−
104− // Maps an item to the touches in this event he should be informed about.
105− // E.g.: a QTouchEvent might have three touches but a given item might be interested in only
106− // one of them. So he will get a UnownedTouchEvent from this QTouchEvent containing only that
107− // touch point.
108− QHash<QQuickItem*, QList<int>> touchIdsForItems;
109−
110− // Build touchIdsForItems
111− m_touchInfoPool.forEach([&](Pool<TouchInfo>::Iterator &touchInfo) {
112− if (touchInfo->isOwned() && touchInfo->watchers.isEmpty())
113− return true;
114−
115− for (int j = 0; j < updatedTouchPoints.count(); ++j) {
116− if (updatedTouchPoints[j].id() == touchInfo->id) {
117− if (!touchInfo->isOwned()) {
118− for (int i = 0; i < touchInfo->candidates.count(); ++i) {
119− CandidateInfo &candidate = touchInfo->candidates[i];
120− Q_ASSERT(!candidate.item.isNull());
121− if (candidate.state != CandidateInfo::InterimOwner) {
122− touchIdsForItems[candidate.item.data()].append(touchInfo->id);
123− }
124− }
125− }
126−
127− const QList<QPointer<QQuickItem>> &watchers = touchInfo->watchers;
128− for (int i = 0; i < watchers.count(); ++i) {
129− if (!watchers[i].isNull()) {
130− touchIdsForItems[watchers[i].data()].append(touchInfo->id);
131− }
132− }
133−
134− return true;
135− }
136− }
137−
138− return true;
139− });
140−
141− // TODO: Consider what happens if an item calls any of TouchRegistry's public methods
142− // from the event handler callback.
143− m_inDispatchLoop = true;
144− auto it = touchIdsForItems.constBegin();
145− while (it != touchIdsForItems.constEnd()) {
146− QQuickItem *item = it.key();
147− const QList<int> &touchIds = it.value();
148− dispatchPointsToItem(event, touchIds, item);
149− ++it;
150− };
151− m_inDispatchLoop = false;
152−}
153−
154−void TouchRegistry::freeEndedTouchInfos()
155−{
156− m_touchInfoPool.forEach([&](Pool<TouchInfo>::Iterator &touchInfo) {
157− if (touchInfo->ended()) {
158− m_touchInfoPool.freeSlot(touchInfo);
159− }
160− return true;
161− });
162−}
163−
164−/*
165− Extracts the touches with the given touchIds from event and send them in a
166− UnownedTouchEvent to the given item
167− */
168−void TouchRegistry::dispatchPointsToItem(const QTouchEvent *event, const QList<int> &touchIds,
169− QQuickItem *item)
170−{
171− Qt::TouchPointStates touchPointStates = 0;
172− QList<QTouchEvent::TouchPoint> touchPoints;
173−
174− const QList<QTouchEvent::TouchPoint> &allTouchPoints = event->touchPoints();
175−
176− QTransform windowToCandidateTransform = QQuickItemPrivate::get(item)->windowToItemTransform();
177− QMatrix4x4 windowToCandidateMatrix(windowToCandidateTransform);
178−
179− for (int i = 0; i < allTouchPoints.count(); ++i) {
180− const QTouchEvent::TouchPoint &originalTouchPoint = allTouchPoints[i];
181− if (touchIds.contains(originalTouchPoint.id())) {
182− QTouchEvent::TouchPoint touchPoint = originalTouchPoint;
183−
184− translateTouchPointFromScreenToWindowCoords(touchPoint);
185−
186− // Set the point's local coordinates to that of the item
187− touchPoint.setRect(windowToCandidateTransform.mapRect(touchPoint.sceneRect()));
188− touchPoint.setStartPos(windowToCandidateTransform.map(touchPoint.startScenePos()));
189− touchPoint.setLastPos(windowToCandidateTransform.map(touchPoint.lastScenePos()));
190− touchPoint.setVelocity(windowToCandidateMatrix.mapVector(touchPoint.velocity()).toVector2D());
191−
192− touchPoints.append(touchPoint);
193− touchPointStates |= touchPoint.state();
194− }
195− }
196−
197− QTouchEvent *eventForItem = new QTouchEvent(event->type(),
198− event->device(),
199− event->modifiers(),
200− touchPointStates,
201− touchPoints);
202− eventForItem->setWindow(event->window());
203− eventForItem->setTimestamp(event->timestamp());
204− eventForItem->setTarget(event->target());
205−
206− UnownedTouchEvent unownedTouchEvent(eventForItem);
207−
208− #if TOUCHREGISTRY_DEBUG
209− UG_DEBUG << "Sending unowned" << qPrintable(touchEventToString(eventForItem))
210− << "to" << item;
211− #endif
212−
213− QCoreApplication::sendEvent(item, &unownedTouchEvent);
214−}
215−
216−void TouchRegistry::translateTouchPointFromScreenToWindowCoords(QTouchEvent::TouchPoint &touchPoint)
217−{
218− touchPoint.setScreenRect(touchPoint.sceneRect());
219− touchPoint.setStartScreenPos(touchPoint.startScenePos());
220− touchPoint.setLastScreenPos(touchPoint.lastScenePos());
221−
222− touchPoint.setSceneRect(touchPoint.rect());
223− touchPoint.setStartScenePos(touchPoint.startPos());
224− touchPoint.setLastScenePos(touchPoint.lastPos());
225−}
226−
227−bool TouchRegistry::eventFilter(QObject *watched, QEvent *event)
228−{
229− Q_UNUSED(watched);
230−
231− switch (event->type()) {
232− case QEvent::TouchBegin:
233− case QEvent::TouchUpdate:
234− case QEvent::TouchEnd:
235− case QEvent::TouchCancel:
236− update(static_cast<QTouchEvent*>(event));
237− break;
238− default:
239− // do nothing
240− break;
241− }
242−
243− // Do not filter out the event. i.e., let it be handled further as
244− // we're just monitoring events
245− return false;
246−}
247−
248−void TouchRegistry::addCandidateOwnerForTouch(int id, QQuickItem *candidate)
249−{
250− #if TOUCHREGISTRY_DEBUG
251− UG_DEBUG << "addCandidateOwnerForTouch id" << id << "candidate" << candidate;
252− #endif
253−
254− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(id);
255− if (!touchInfo) { qFatal("TouchRegistry: Failed to find TouchInfo"); }
256−
257− if (touchInfo->isOwned()) {
258− qWarning("TouchRegistry: trying to add candidate owner for a touch that's already owned");
259− return;
260− }
261−
262− // TODO: Check if candidate already exists
263−
264− CandidateInfo candidateInfo;
265− candidateInfo.state = CandidateInfo::Undecided;
266− candidateInfo.item = candidate;
267− candidateInfo.inactivityTimer = new CandidateInactivityTimer(id, candidate,
268− m_timerFactory->createTimer(),
269− this);
270− connect(candidateInfo.inactivityTimer, &CandidateInactivityTimer::candidateDefaulted,
271− this, &TouchRegistry::rejectCandidateOwnerForTouch);
272−
273− touchInfo->candidates.append(candidateInfo);
274−
275− connect(candidate, &QObject::destroyed, this, [=](){ pruneNullCandidatesForTouch(id); });
276−}
277−
278−void TouchRegistry::addTouchWatcher(int touchId, QQuickItem *watcher)
279−{
280− #if TOUCHREGISTRY_DEBUG
281− UG_DEBUG << "addTouchWatcher id" << touchId << "watcher" << watcher;
282− #endif
283−
284− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(touchId);
285− if (!touchInfo) { qFatal("TouchRegistry: Failed to find TouchInfo"); }
286−
287− // TODO: Check if watcher already exists
288−
289− touchInfo->watchers.append(watcher);
290−}
291−
292−void TouchRegistry::removeCandidateOwnerForTouch(int id, QQuickItem *candidate)
293−{
294− #if TOUCHREGISTRY_DEBUG
295− UG_DEBUG << "removeCandidateOwnerForTouch id" << id << "candidate" << candidate;
296− #endif
297−
298− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(id);
299− if (!touchInfo) { qFatal("TouchRegistry: Failed to find TouchInfo"); }
300−
301−
302− // TODO: check if the candidate is in fact the owner of the touch
303−
304− bool removed = false;
305− for (int i = 0; i < touchInfo->candidates.count() && !removed; ++i) {
306− if (touchInfo->candidates[i].item == candidate) {
307− removeCandidateOwnerForTouchByIndex(touchInfo, i);
308− removed = true;
309− }
310− }
311−}
312−
313−void TouchRegistry::pruneNullCandidatesForTouch(int touchId)
314−{
315− #if TOUCHREGISTRY_DEBUG
316− UG_DEBUG << "pruneNullCandidatesForTouch touchId" << touchId;
317− #endif
318−
319− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(touchId);
320− if (!touchInfo) {
321− // doesn't matter as touch is already gone.
322− return;
323− }
324−
325− int i = 0;
326− while (i < touchInfo->candidates.count()) {
327− if (touchInfo->candidates[i].item.isNull()) {
328− removeCandidateOwnerForTouchByIndex(touchInfo, i);
329− } else {
330− ++i;
331− }
332− }
333−}
334−
335−void TouchRegistry::removeCandidateOwnerForTouchByIndex(Pool<TouchRegistry::TouchInfo>::Iterator &touchInfo,
336− int candidateIndex)
337−{
338− // TODO: check if the candidate is in fact the owner of the touch
339−
340− Q_ASSERT(candidateIndex < touchInfo->candidates.count());
341−
342− if (candidateIndex == 0 && touchInfo->candidates[candidateIndex].state != CandidateInfo::Undecided) {
343− qCritical("TouchRegistry: touch owner is being removed.");
344− }
345− removeCandidateHelper(touchInfo, candidateIndex);
346−
347− if (candidateIndex == 0) {
348− // the top candidate has been removed. if the new top candidate
349− // wants the touch let him know he's now the owner.
350− if (touchInfo->isOwned()) {
351− touchInfo->notifyCandidatesOfOwnershipResolution();
352− }
353− }
354−
355− if (!m_inDispatchLoop && touchInfo->ended()) {
356− m_touchInfoPool.freeSlot(touchInfo);
357− }
358−}
359−
360−void TouchRegistry::requestTouchOwnership(int id, QQuickItem *candidate)
361−{
362− #if TOUCHREGISTRY_DEBUG
363− UG_DEBUG << "requestTouchOwnership id " << id << "candidate" << candidate;
364− #endif
365−
366− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(id);
367− if (!touchInfo) { qFatal("TouchRegistry: Failed to find TouchInfo"); }
368−
369− Q_ASSERT(!touchInfo->isOwned());
370−
371− int candidateIndex = -1;
372− for (int i = 0; i < touchInfo->candidates.count(); ++i) {
373− CandidateInfo &candidateInfo = touchInfo->candidates[i];
374− if (candidateInfo.item == candidate) {
375− candidateInfo.state = CandidateInfo::Requested;
376− delete candidateInfo.inactivityTimer;
377− candidateInfo.inactivityTimer = nullptr;
378− candidateIndex = i;
379− break;
380− }
381− }
382−
383− // add it as a candidate if not present yet
384− if (candidateIndex < 0) {
385− CandidateInfo candidateInfo;
386− candidateInfo.state = CandidateInfo::InterimOwner;
387− candidateInfo.item = candidate;
388− candidateInfo.inactivityTimer = nullptr;
389− touchInfo->candidates.append(candidateInfo);
390− // it's the last one
391− candidateIndex = touchInfo->candidates.count() - 1;
392− connect(candidate, &QObject::destroyed, this, [=](){ pruneNullCandidatesForTouch(id); });
393− }
394−
395− // If it's the top candidate it means it's now the owner. Let
396− // it know about it.
397− if (candidateIndex == 0) {
398− touchInfo->notifyCandidatesOfOwnershipResolution();
399− }
400−}
401−
402−Pool<TouchRegistry::TouchInfo>::Iterator TouchRegistry::findTouchInfo(int id)
403−{
404− Pool<TouchInfo>::Iterator touchInfo;
405−
406− m_touchInfoPool.forEach([&](Pool<TouchInfo>::Iterator &someTouchInfo) -> bool {
407− if (someTouchInfo->id == id) {
408− touchInfo = someTouchInfo;
409− return false;
410− } else {
411− return true;
412− }
413− });
414−
415− return touchInfo;
416−}
417−
418−
419−void TouchRegistry::rejectCandidateOwnerForTouch(int id, QQuickItem *candidate)
420−{
421− // NB: It's technically possible that candidate is a dangling pointer at this point.
422− // Although that would most likely be due to a bug in our code.
423− // In any case, only dereference it after it's confirmed that it indeed exists.
424−
425− #if TOUCHREGISTRY_DEBUG
426− UG_DEBUG << "rejectCandidateOwnerForTouch id" << id << "candidate" << (void*)candidate;
427− #endif
428−
429− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(id);
430− if (!touchInfo) {
431− #if TOUCHREGISTRY_DEBUG
432− UG_DEBUG << "Failed to find TouchInfo for id" << id;
433− #endif
434− return;
435− }
436−
437− int rejectedCandidateIndex = -1;
438−
439− // Check if the given candidate is valid and still undecided
440− for (int i = 0; i < touchInfo->candidates.count() && rejectedCandidateIndex == -1; ++i) {
441− CandidateInfo &candidateInfo = touchInfo->candidates[i];
442− if (candidateInfo.item == candidate) {
443− Q_ASSERT(i > 0 || candidateInfo.state == CandidateInfo::Undecided);
444− if (i == 0 && candidateInfo.state != CandidateInfo::Undecided) {
445− qCritical() << "TouchRegistry: Can't reject item (" << (void*)candidate
446− << ") as it already owns touch" << id;
447− return;
448− } else {
449− // we found the guy and it's all fine.
450− rejectedCandidateIndex = i;
451− }
452− }
453− }
454−
455− // If we reached this point it's because the given candidate exists and is indeed undecided.
456−
457− Q_ASSERT(rejectedCandidateIndex >= 0 && rejectedCandidateIndex < touchInfo->candidates.size());
458−
459− {
460− TouchOwnershipEvent lostOwnershipEvent(id, false /*gained*/);
461− QCoreApplication::sendEvent(candidate, &lostOwnershipEvent);
462− }
463−
464− removeCandidateHelper(touchInfo, rejectedCandidateIndex);
465−
466− if (rejectedCandidateIndex == 0) {
467− // the top candidate has been removed. if the new top candidate
468− // wants the touch let him know he's now the owner.
469− if (touchInfo->isOwned()) {
470− touchInfo->notifyCandidatesOfOwnershipResolution();
471− }
472− }
473−}
474−
475−void TouchRegistry::removeCandidateHelper(Pool<TouchInfo>::Iterator &touchInfo, int candidateIndex)
476−{
477− {
478− CandidateInfo &candidateInfo = touchInfo->candidates[candidateIndex];
479−
480− delete candidateInfo.inactivityTimer;
481− candidateInfo.inactivityTimer = nullptr;
482−
483− if (candidateInfo.item) {
484− disconnect(candidateInfo.item.data(), nullptr, this, nullptr);
485− }
486− }
487− touchInfo->candidates.removeAt(candidateIndex);
488−}
489−
490−////////////////////////////////////// TouchRegistry::TouchInfo ////////////////////////////////////
491−
492−TouchRegistry::TouchInfo::TouchInfo(int id)
493−{
494− init(id);
495−}
496−
497−void TouchRegistry::TouchInfo::reset()
498−{
499− id = -1;
500−
501− for (int i = 0; i < candidates.count(); ++i) {
502− CandidateInfo &candidate = candidates[i];
503− delete candidate.inactivityTimer;
504− candidate.inactivityTimer.clear(); // shoundn't be needed but anyway...
505− }
506−}
507−
508−void TouchRegistry::TouchInfo::init(int id)
509−{
510− this->id = id;
511− physicallyEnded = false;
512− candidates.clear();
513− watchers.clear();
514−}
515−
516−bool TouchRegistry::TouchInfo::isOwned() const
517−{
518− return !candidates.isEmpty() && candidates.first().state != CandidateInfo::Undecided;
519−}
520−
521−bool TouchRegistry::TouchInfo::ended() const
522−{
523− Q_ASSERT(isValid());
524− return physicallyEnded && (isOwned() || candidates.isEmpty());
525−}
526−
527−void TouchRegistry::TouchInfo::notifyCandidatesOfOwnershipResolution()
528−{
529− Q_ASSERT(isOwned());
530−
531− #if TOUCHREGISTRY_DEBUG
532− UG_DEBUG << "sending TouchOwnershipEvent(id =" << id
533− << " gained) to candidate" << candidates[0].item;
534− #endif
535−
536− TouchOwnershipEvent gainedOwnershipEvent(id, true /*gained*/);
537− QCoreApplication::sendEvent(candidates[0].item, &gainedOwnershipEvent);
538−
539−
540− TouchOwnershipEvent lostOwnershipEvent(id, false /*gained*/);
541− for (int i = 1; i < candidates.count(); ++i) {
542− #if TOUCHREGISTRY_DEBUG
543− UG_DEBUG << "sending TouchWonershipEvent(id =" << id << " lost) to candidate"
544− << candidates[i].item;
545− #endif
546− QCoreApplication::sendEvent(candidates[i].item, &lostOwnershipEvent);
547− }
548−}
libs/UbuntuGestures/TouchRegistry.hdeleted−201
@@ -1,201 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UNITY_TOUCHREGISTRY_H
18−#define UNITY_TOUCHREGISTRY_H
19−
20−#include <QQuickItem>
21−#include <QObject>
22−#include <QPointer>
23−#include <QTouchEvent>
24−#include <QVector>
25−
26−#include "UbuntuGesturesGlobal.h"
27−#include "CandidateInactivityTimer.h"
28−#include "Timer.h"
29−#include "Pool.h"
30−
31−namespace UbuntuGestures {
32− class AbstractTimerFactory;
33−}
34−
35−/*
36− Where the ownership of touches is registered.
37−
38− Singleton used for adding a touch point ownership model analogous to the one
39− described in the XInput 2.2 protocol[1] on top of the existing input dispatch logic in QQuickWindow.
40−
41− It provides a much more flexible and powerful way of dealing with pointer ownership than the existing
42− mechanisms in Qt. Namely QQuickItem::grabTouchPoints, QuickItem::keepTouchGrab,
43− QQuickItem::setFiltersChildMouseEvents, QQuickItem::ungrabTouchPoints and QQuickItem::touchUngrabEvent.
44−
45− Usage:
46−
47− 1- An item receives a a new touch point. If he's not sure whether he wants it yet, he calls:
48− TouchRegistry::instance()->addCandidateOwnerForTouch(touchId, this);
49− touchEvent->ignore();
50− Ignoring the event is crucial so that it can be seen by other interested parties, which will
51− behave similarly.
52−
53− 2- That item will then start receiving UnownedTouchEvents for that touch from step 1. Once he's
54− made a decision he calls either:
55− TouchRegistry::instance()->requestTouchOwnership(touchId, this);
56− If he wants the touch point or:
57− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, this);
58−  if he does not want it.
59−
60− Candidates are put in a priority queue. The first one to call addCandidateOwnerForTouch() will
61− take precedence over the others for receiving ownership over the touch point (from now on called
62− simply top-candidate).
63−
64− If the top-candidate calls requestTouchOwnership() he will immediately receive a
65− TouchOwnershipEvent(gained=true) for that touch point. He can then safely call
66− QQuickItem::grabTouchPoints to actually get the owned touch points. The other candidates
67− will receive TouchOwnershipEvent(gained=false) and will no longer receive UnownedTouchEvents
68− for that touch point. They will have to undo whatever action they were performing with that
69− touch point.
70−
71− But if the top-candidate calls removeCandidateOwnerForTouch() instead, he's popped from the
72− candidacy queue and ownership is given to the new top-most candidate if he has already
73− made his decision, that is.
74−
75− The TouchRegistry cannot enforce the results of this pointer ownership negotiation (i.e.,
76− who gets to grab the touch points) as that would clash with QQuickWindow's input event
77− dispatching logic. The candidates have to respect the decision and grab the touch points
78− themselves.
79−
80− If an item wants ownership over touches as soon as he receives the TouchBegin for them, his step 1
81− would be instead:
82− TouchRegistry::instance()->requestTouchOwnership(touchId, this);
83− touchEvent->accept();
84− He won't get any UnownedTouchEvent for that touch as he is already the interim owner (ie, QQuickWindow
85− will keep sending touch updates to him already). Eventually he will be notified once ownership has
86− been granted to him (from TouchRegistry perspective), from which point onwards he could safely assume
87− other TouchRegistry users wouldn't snatch this touch away from him.
88−
89− Items oblivious to TouchRegistry will lose their touch points without warning, just like in plain Qt.
90−
91− [1] - http://www.x.org/releases/X11R7.7/doc/inputproto/XI2proto.txt (see multitouch-ownership)
92− */
93−class UBUNTUGESTURES_EXPORT TouchRegistry : public QObject
94−{
95− Q_OBJECT
96−public:
97− virtual ~TouchRegistry();
98−
99− // Returns a pointer to the application's TouchRegistry instance.
100− static TouchRegistry *instance();
101−
102− void update(const QTouchEvent *event);
103−
104− // Calls update() if the given event is a QTouchEvent
105− bool eventFilter(QObject *watched, QEvent *event) override;
106−
107− // An item that might later request ownership over the given touch point.
108− // He will be kept informed about that touch point through UnownedTouchEvents
109− // All candidates must eventually decide whether they want to own the touch point
110− // or not. That decision is informed through requestTouchOwnership() or
111− // removeCandidateOwnerForTouch()
112− void addCandidateOwnerForTouch(int id, QQuickItem *candidate);
113−
114− // The same as rejecting ownership of a touch
115− void removeCandidateOwnerForTouch(int id, QQuickItem *candidate);
116−
117− // The candidate object wants to be the owner of the touch with the given id.
118− // If he's currently the oldest/top-most candidate, he will get an ownership
119− // event immediately. If not, he will get ownership if (or once) he becomes the
120− // top-most candidate.
121− void requestTouchOwnership(int id, QQuickItem *candidate);
122−
123− // An item that has no interest (effective or potential) in owning a touch point
124− // but would nonetheless like to be kept up-to-date on its state.
125− void addTouchWatcher(int touchId, QQuickItem *watcherItem);
126−
127− // Useful for tests, where you should use fake timers
128− void setTimerFactory(UbuntuGestures::AbstractTimerFactory *timerFactory);
129−
130−private Q_SLOTS:
131− void rejectCandidateOwnerForTouch(int id, QQuickItem *candidate);
132−
133−private:
134− // Only instance() can cronstruct one
135− TouchRegistry(QObject *parent = nullptr);
136−
137− class CandidateInfo {
138− public:
139− enum {
140− // A candidate owner that doesn't yet know for sure whether he wants the touch point
141− // (gesture recognition is stilll going on)
142− Undecided = 0,
143− // A candidate owner that wants the touch but hasn't been granted it yet,
144− // most likely because there's an undecided candidate with higher priority
145− Requested = 1,
146− // An item that is the interim owner of the touch, receiving QTouchEvents of it
147− // from QQuickWindow. Ie, it's the actual touch owner from Qt's point of view.
148− // It wants to keep its touch ownership but hasn't been granted it by TouchRegistry
149− // yet because of undecided candidates higher up.
150− InterimOwner = 2
151− } state;
152− QPointer<QQuickItem> item;
153− QPointer<UbuntuGestures::CandidateInactivityTimer> inactivityTimer;
154− };
155−
156− class TouchInfo {
157− public:
158− TouchInfo() : id(-1) {}
159− TouchInfo(int id);
160− bool isValid() const { return id >= 0; }
161− void reset();
162− void init(int id);
163− int id;
164− bool physicallyEnded;
165− bool isOwned() const;
166− bool ended() const;
167− void notifyCandidatesOfOwnershipResolution();
168−
169− // TODO optimize storage (s/QList/Pool)
170− QList<CandidateInfo> candidates;
171− QList<QPointer<QQuickItem>> watchers;
172− };
173−
174− void pruneNullCandidatesForTouch(int touchId);
175− void removeCandidateOwnerForTouchByIndex(Pool<TouchInfo>::Iterator &touchInfo, int candidateIndex);
176− void removeCandidateHelper(Pool<TouchInfo>::Iterator &touchInfo, int candidateIndex);
177−
178− Pool<TouchInfo>::Iterator findTouchInfo(int id);
179−
180− void deliverTouchUpdatesToUndecidedCandidatesAndWatchers(const QTouchEvent *event);
181−
182− static void translateTouchPointFromScreenToWindowCoords(QTouchEvent::TouchPoint &touchPoint);
183−
184− static void dispatchPointsToItem(const QTouchEvent *event, const QList<int> &touchIds,
185− QQuickItem *item);
186− void freeEndedTouchInfos();
187−
188− Pool<TouchInfo> m_touchInfoPool;
189−
190− // the singleton instance
191− static TouchRegistry *m_instance;
192−
193− bool m_inDispatchLoop;
194−
195− UbuntuGestures::AbstractTimerFactory *m_timerFactory;
196−
197− friend class tst_TouchRegistry;
198− friend class tst_DirectionalDragArea;
199−};
200−
201−#endif // UNITY_TOUCHREGISTRY_H
libs/UbuntuGestures/UnownedTouchEvent.hdeleted−45
@@ -1,45 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTU_UNOWNEDTOUCHEVENT_H
18−#define UBUNTU_UNOWNEDTOUCHEVENT_H
19−
20−#include <QTouchEvent>
21−#include <QScopedPointer>
22−#include "UbuntuGesturesGlobal.h"
23−
24−/*
25− A touch event with touch points that do not belong the item receiving it.
26−
27− See TouchRegistry::addCandidateOwnerForTouch and TouchRegistry::addTouchWatcher
28− */
29−class UBUNTUGESTURES_EXPORT UnownedTouchEvent : public QEvent
30−{
31−public:
32− UnownedTouchEvent(QTouchEvent *touchEvent);
33− static Type unownedTouchEventType();
34−
35− // TODO: It might be cleaner to store the information directly in UnownedTouchEvent
36− // instead of carrying around a synthesized QTouchEvent. But the latter option
37− // is very convenient.
38− QTouchEvent *touchEvent();
39−
40−private:
41− static Type m_unownedTouchEventType;
42− QScopedPointer<QTouchEvent> m_touchEvent;
43−};
44−
45−#endif // UBUNTU_UNOWNEDTOUCHEVENT_H
plugins/AccountsService/AccountsService.cpp+268−283
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,33 +12,124 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Author: Michael Terry <michael.terry@canonical.com>
1715 */
1816
1917#include "AccountsService.h"
2018#include "AccountsServiceDBusAdaptor.h"
2119
20+#include <QDBusInterface>
2221#include <QFile>
2322#include <QStringList>
2423#include <QDebug>
2524
25+#include <glib.h>
26+
27+#define IFACE_ACCOUNTS_USER QStringLiteral("org.freedesktop.Accounts.User")
28+#define IFACE_UBUNTU_INPUT QStringLiteral("com.ubuntu.AccountsService.Input")
29+#define IFACE_UBUNTU_SECURITY QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy")
30+#define IFACE_UBUNTU_SECURITY_OLD QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy")
31+#define IFACE_UNITY QStringLiteral("com.canonical.unity.AccountsService")
32+#define IFACE_UNITY_PRIVATE QStringLiteral("com.canonical.unity.AccountsService.Private")
33+
34+#define PROP_BACKGROUND_FILE QStringLiteral("BackgroundFile")
35+#define PROP_DEMO_EDGES QStringLiteral("DemoEdges2")
36+#define PROP_DEMO_EDGES_COMPLETED QStringLiteral("DemoEdgesCompleted")
37+#define PROP_EMAIL QStringLiteral("Email")
38+#define PROP_ENABLE_FINGERPRINT_IDENTIFICATION QStringLiteral("EnableFingerprintIdentification")
39+#define PROP_ENABLE_INDICATORS_WHILE_LOCKED QStringLiteral("EnableIndicatorsWhileLocked")
40+#define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked")
41+#define PROP_FAILED_FINGERPRINT_LOGINS QStringLiteral("FailedFingerprintLogins")
42+#define PROP_FAILED_LOGINS QStringLiteral("FailedLogins")
43+#define PROP_INPUT_SOURCES QStringLiteral("InputSources")
44+#define PROP_LICENSE_ACCEPTED QStringLiteral("LicenseAccepted")
45+#define PROP_LICENSE_BASE_PATH QStringLiteral("LicenseBasePath")
46+#define PROP_MOUSE_CURSOR_SPEED QStringLiteral("MouseCursorSpeed")
47+#define PROP_MOUSE_DOUBLE_CLICK_SPEED QStringLiteral("MouseDoubleClickSpeed")
48+#define PROP_MOUSE_PRIMARY_BUTTON QStringLiteral("MousePrimaryButton")
49+#define PROP_MOUSE_SCROLL_SPEED QStringLiteral("MouseScrollSpeed")
50+#define PROP_PASSWORD_DISPLAY_HINT QStringLiteral("PasswordDisplayHint")
51+#define PROP_REAL_NAME QStringLiteral("RealName")
52+#define PROP_STATS_WELCOME_SCREEN QStringLiteral("StatsWelcomeScreen")
53+#define PROP_TOUCHPAD_CURSOR_SPEED QStringLiteral("TouchpadCursorSpeed")
54+#define PROP_TOUCHPAD_DISABLE_WHILE_TYPING QStringLiteral("TouchpadDisableWhileTyping")
55+#define PROP_TOUCHPAD_DISABLE_WITH_MOUSE QStringLiteral("TouchpadDisableWithMouse")
56+#define PROP_TOUCHPAD_DOUBLE_CLICK_SPEED QStringLiteral("TouchpadDoubleClickSpeed")
57+#define PROP_TOUCHPAD_PRIMARY_BUTTON QStringLiteral("TouchpadPrimaryButton")
58+#define PROP_TOUCHPAD_SCROLL_SPEED QStringLiteral("TouchpadScrollSpeed")
59+#define PROP_TOUCHPAD_TAP_TO_CLICK QStringLiteral("TouchpadTapToClick")
60+#define PROP_TOUCHPAD_TWO_FINGER_SCROLL QStringLiteral("TouchpadTwoFingerScroll")
61+
62+using StringMap = QMap<QString,QString>;
63+using StringMapList = QList<StringMap>;
64+Q_DECLARE_METATYPE(StringMapList)
65+
66+
67+QVariant primaryButtonConverter(const QVariant &value)
68+{
69+ QString stringValue = value.toString();
70+ if (stringValue == QLatin1String("left")) {
71+ return QVariant::fromValue(0);
72+ } else if (stringValue == QLatin1String("right")) {
73+ return QVariant::fromValue(1); // Mir is less clear on this -- any non-zero value is the same
74+ } else {
75+ return QVariant::fromValue(0); // default to left
76+ }
77+}
78+
2679AccountsService::AccountsService(QObject* parent, const QString &user)
27− : QObject(parent),
28− m_service(new AccountsServiceDBusAdaptor(this)),
29− m_demoEdges(false),
30− m_enableLauncherWhileLocked(false),
31− m_enableIndicatorsWhileLocked(false),
32− m_statsWelcomeScreen(false),
33− m_passwordDisplayHint(Keyboard),
34− m_failedLogins(0),
35− m_hereEnabled(false),
36− m_hereLicensePath() // null means not set yet
80+ : QObject(parent)
81+ , m_service(new AccountsServiceDBusAdaptor(this))
3782{
83+ m_unityInput = new QDBusInterface(QStringLiteral("com.canonical.Unity.Input"),
84+ QStringLiteral("/com/canonical/Unity/Input"),
85+ QStringLiteral("com.canonical.Unity.Input"),
86+ QDBusConnection::SM_BUSNAME(), this);
87+
3888 connect(m_service, &AccountsServiceDBusAdaptor::propertiesChanged, this, &AccountsService::onPropertiesChanged);
3989 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged, this, &AccountsService::onMaybeChanged);
4090
41− setUser(!user.isEmpty() ? user : QString::fromUtf8(qgetenv("USER")));
91+ registerProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE, QStringLiteral("backgroundFileChanged"));
92+ registerProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, QStringLiteral("emailChanged"));
93+ registerProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, QStringLiteral("realNameChanged"));
94+ registerProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QStringLiteral("keymapsChanged"));
95+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION, QStringLiteral("enableFingerprintIdentificationChanged"));
96+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral("enableLauncherWhileLockedChanged"));
97+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral("enableIndicatorsWhileLockedChanged"));
98+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral("passwordDisplayHintChanged"));
99+ registerProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN, QStringLiteral("statsWelcomeScreenChanged"));
100+ registerProperty(IFACE_UNITY, PROP_DEMO_EDGES, QStringLiteral("demoEdgesChanged"));
101+ registerProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED, QStringLiteral("demoEdgesCompletedChanged"));
102+ registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, QStringLiteral("failedFingerprintLoginsChanged"));
103+ registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, QStringLiteral("failedLoginsChanged"));
104+
105+ registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_CURSOR_SPEED,
106+ m_unityInput, QStringLiteral("setMouseCursorSpeed"));
107+ registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_DOUBLE_CLICK_SPEED,
108+ m_unityInput, QStringLiteral("setMouseDoubleClickSpeed"));
109+ registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_PRIMARY_BUTTON,
110+ m_unityInput, QStringLiteral("setMousePrimaryButton"),
111+ primaryButtonConverter);
112+ registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_SCROLL_SPEED,
113+ m_unityInput, QStringLiteral("setMouseScrollSpeed"));
114+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_CURSOR_SPEED,
115+ m_unityInput, QStringLiteral("setTouchpadCursorSpeed"));
116+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_SCROLL_SPEED,
117+ m_unityInput, QStringLiteral("setTouchpadScrollSpeed"));
118+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WHILE_TYPING,
119+ m_unityInput, QStringLiteral("setTouchpadDisableWhileTyping"));
120+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WITH_MOUSE,
121+ m_unityInput, QStringLiteral("setTouchpadDisableWithMouse"));
122+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DOUBLE_CLICK_SPEED,
123+ m_unityInput, QStringLiteral("setTouchpadDoubleClickSpeed"));
124+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_PRIMARY_BUTTON,
125+ m_unityInput, QStringLiteral("setTouchpadPrimaryButton"),
126+ primaryButtonConverter);
127+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TAP_TO_CLICK,
128+ m_unityInput, QStringLiteral("setTouchpadTapToClick"));
129+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TWO_FINGER_SCROLL,
130+ m_unityInput, QStringLiteral("setTouchpadTwoFingerScroll"));
131+
132+ setUser(!user.isEmpty() ? user : QString::fromUtf8(g_get_user_name()));
42133}
43134
44135QString AccountsService::user() const
@@ -51,362 +142,264 @@ void AccountsService::setUser(const QString &user)
51142 if (user.isEmpty() || m_user == user)
52143 return;
53144
145+ bool wasEmpty = m_user.isEmpty();
146+
54147 m_user = user;
55148 Q_EMIT userChanged();
56149
57− updateDemoEdges(false);
58− updateEnableLauncherWhileLocked(false);
59− updateEnableIndicatorsWhileLocked(false);
60− updateBackgroundFile(false);
61− updateStatsWelcomeScreen(false);
62− updatePasswordDisplayHint(false);
63− updateFailedLogins(false);
64− updateHereEnabled(false);
65− updateHereLicensePath(false);
150+ // Do the first update synchronously, as a cheap way to block rendering
151+ // until we have the right values on bootup.
152+ refresh(!wasEmpty);
66153}
67154
68155bool AccountsService::demoEdges() const
69156{
70− return m_demoEdges;
157+ auto value = getProperty(IFACE_UNITY, PROP_DEMO_EDGES);
158+ return value.toBool();
71159}
72160
73161void AccountsService::setDemoEdges(bool demoEdges)
74162{
75− if (m_demoEdges != demoEdges) {
76− m_demoEdges = demoEdges;
77− m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("demo-edges"), demoEdges);
163+ setProperty(IFACE_UNITY, PROP_DEMO_EDGES, demoEdges);
164+}
165+
166+QStringList AccountsService::demoEdgesCompleted() const
167+{
168+ auto value = getProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED);
169+ return value.toStringList();
170+}
78171
79− Q_EMIT demoEdgesChanged();
172+void AccountsService::markDemoEdgeCompleted(const QString &edge)
173+{
174+ auto currentList = demoEdgesCompleted();
175+ if (!currentList.contains(edge)) {
176+ setProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED, currentList << edge);
80177 }
81178}
82179
180+bool AccountsService::enableFingerprintIdentification() const
181+{
182+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION);
183+ return value.toBool();
184+}
185+
83186bool AccountsService::enableLauncherWhileLocked() const
84187{
85− return m_enableLauncherWhileLocked;
188+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
189+ return value.toBool();
86190}
87191
88192bool AccountsService::enableIndicatorsWhileLocked() const
89193{
90− return m_enableIndicatorsWhileLocked;
194+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED);
195+ return value.toBool();
91196}
92197
93198QString AccountsService::backgroundFile() const
94199{
95− return m_backgroundFile;
200+ auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE);
201+ return value.toString();
96202}
97203
98204bool AccountsService::statsWelcomeScreen() const
99205{
100− return m_statsWelcomeScreen;
206+ auto value = getProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN);
207+ return value.toBool();
101208}
102209
103210AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const
104211{
105− return m_passwordDisplayHint;
212+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT);
213+ return (PasswordDisplayHint)value.toInt();
106214}
107215
108−bool AccountsService::hereEnabled() const
216+QString AccountsService::realName() const
109217{
110− return m_hereEnabled;
218+ auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME);
219+ return value.toString();
111220}
112221
113−void AccountsService::setHereEnabled(bool enabled)
222+void AccountsService::setRealName(const QString &realName)
114223{
115− if (m_hereEnabled != enabled) {
116− m_hereEnabled = enabled;
117− m_service->setUserPropertyAsync(m_user, QStringLiteral("com.ubuntu.location.providers.here.AccountsService"), QStringLiteral("LicenseAccepted"), enabled);
118−
119− Q_EMIT hereEnabledChanged();
120− }
224+ setProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, realName);
121225}
122226
123−QString AccountsService::hereLicensePath() const
227+QString AccountsService::email() const
124228{
125− return m_hereLicensePath;
229+ auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL);
230+ return value.toString();
126231}
127232
128−bool AccountsService::hereLicensePathValid() const
233+void AccountsService::setEmail(const QString &email)
129234{
130− return !m_hereLicensePath.isNull();
235+ setProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, email);
131236}
132237
133−void AccountsService::updateDemoEdges(bool async)
238+QStringList AccountsService::keymaps() const
134239{
135− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
136− QStringLiteral("com.canonical.unity.AccountsService"),
137− QStringLiteral("demo-edges"));
138− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
139−
140− connect(watcher, &QDBusPendingCallWatcher::finished,
141− this, [this](QDBusPendingCallWatcher* watcher) {
142−
143− QDBusPendingReply<QDBusVariant> reply = *watcher;
144− watcher->deleteLater();
145− if (reply.isError()) {
146− qWarning() << "Failed to get 'demo-edges' property - " << reply.error().message();
147− return;
240+ auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES);
241+ QDBusArgument arg = value.value<QDBusArgument>();
242+ StringMapList maps = qdbus_cast<StringMapList>(arg);
243+ QStringList simplifiedMaps;
244+
245+ Q_FOREACH(const StringMap &map, maps) {
246+ Q_FOREACH(const QString &entry, map) {
247+ simplifiedMaps.append(entry);
148248 }
249+ }
149250
150− auto demoEdges = reply.value().variant().toBool();
151− if (m_demoEdges != demoEdges) {
152− m_demoEdges = demoEdges;
153− Q_EMIT demoEdgesChanged();
154− }
155− });
156− if (!async) {
157− watcher->waitForFinished();
158− delete watcher;
251+ if (!simplifiedMaps.isEmpty()) {
252+ return simplifiedMaps;
159253 }
254+
255+ return {QStringLiteral("us")};
160256}
161257
162−void AccountsService::updateEnableLauncherWhileLocked(bool async)
258+void AccountsService::setKeymaps(const QStringList &keymaps)
163259{
164− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
165− QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
166− QStringLiteral("EnableLauncherWhileLocked"));
167− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
168−
169− connect(watcher, &QDBusPendingCallWatcher::finished,
170− this, [this](QDBusPendingCallWatcher* watcher) {
171−
172− QDBusPendingReply<QVariant> reply = *watcher;
173− watcher->deleteLater();
174− if (reply.isError()) {
175− qWarning() << "Failed to get 'EnableLauncherWhileLocked' property - " << reply.error().message();
176− return;
177− }
260+ if (keymaps.isEmpty()) {
261+ qWarning() << "Setting empty keymaps is not supported";
262+ return;
263+ }
178264
179− const bool enableLauncherWhileLocked = reply.value().toBool();
180− if (m_enableLauncherWhileLocked != enableLauncherWhileLocked) {
181− m_enableLauncherWhileLocked = enableLauncherWhileLocked;
182− Q_EMIT enableLauncherWhileLockedChanged();
183− }
184− });
185− if (!async) {
186− watcher->waitForFinished();
187− delete watcher;
265+ StringMapList result;
266+ Q_FOREACH(const QString &keymap, keymaps) {
267+ StringMap map;
268+ map.insert(QStringLiteral("xkb"), keymap);
269+ result.append(map);
188270 }
271+
272+ setProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QVariant::fromValue(result));
273+ Q_EMIT keymapsChanged();
189274}
190275
191−void AccountsService::updateEnableIndicatorsWhileLocked(bool async)
276+uint AccountsService::failedFingerprintLogins() const
192277{
193− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
194− QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
195− QStringLiteral("EnableIndicatorsWhileLocked"));
196− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
197−
198− connect(watcher, &QDBusPendingCallWatcher::finished,
199− this, [this](QDBusPendingCallWatcher* watcher) {
200−
201− QDBusPendingReply<QVariant> reply = *watcher;
202− watcher->deleteLater();
203− if (reply.isError()) {
204− qWarning() << "Failed to get 'EnableIndicatorsWhileLocked' property - " << reply.error().message();
205− return;
206− }
207−
208− const bool enableIndicatorsWhileLocked = reply.value().toBool();
209− if (m_enableIndicatorsWhileLocked != enableIndicatorsWhileLocked) {
210− m_enableIndicatorsWhileLocked = enableIndicatorsWhileLocked;
211− Q_EMIT enableIndicatorsWhileLockedChanged();
212− }
213− });
214− if (!async) {
215− watcher->waitForFinished();
216− delete watcher;
217− }
278+ return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS).toUInt();
218279}
219280
220−void AccountsService::updateBackgroundFile(bool async)
281+void AccountsService::setFailedFingerprintLogins(uint failedFingerprintLogins)
221282{
222− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
223− QStringLiteral("org.freedesktop.Accounts.User"),
224− QStringLiteral("BackgroundFile"));
225− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
226−
227− connect(watcher, &QDBusPendingCallWatcher::finished,
228− this, [this](QDBusPendingCallWatcher* watcher) {
229−
230− QDBusPendingReply<QVariant> reply = *watcher;
231− watcher->deleteLater();
232− if (reply.isError()) {
233− qWarning() << "Failed to get 'BackgroundFile' property - " << reply.error().message();
234− return;
235− }
236−
237− const QString backgroundFile = reply.value().toString();
238− if (m_backgroundFile != backgroundFile) {
239− m_backgroundFile = backgroundFile;
240− Q_EMIT backgroundFileChanged();
241− }
242− });
243− if (!async) {
244− watcher->waitForFinished();
245− delete watcher;
246− }
283+ setProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, failedFingerprintLogins);
247284}
248285
249−void AccountsService::updateStatsWelcomeScreen(bool async)
286+uint AccountsService::failedLogins() const
250287{
251− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
252− QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy"),
253− QStringLiteral("StatsWelcomeScreen"));
254− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
288+ return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS).toUInt();
289+}
255290
256− connect(watcher, &QDBusPendingCallWatcher::finished,
257− this, [this](QDBusPendingCallWatcher* watcher) {
291+void AccountsService::setFailedLogins(uint failedLogins)
292+{
293+ setProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, failedLogins);
294+}
258295
259− QDBusPendingReply<QVariant> reply = *watcher;
260− watcher->deleteLater();
261− if (reply.isError()) {
262− qWarning() << "Failed to get 'StatsWelcomeScreen' property - " << reply.error().message();
263− return;
264− }
296+// ====================================================
297+// Everything below this line is generic helper methods
298+// ====================================================
265299
266− const bool statsWelcomeScreen = reply.value().toBool();
267− if (m_statsWelcomeScreen != statsWelcomeScreen) {
268− m_statsWelcomeScreen = statsWelcomeScreen;
269− Q_EMIT statsWelcomeScreenChanged();
270− }
271− });
272− if (!async) {
273− watcher->waitForFinished();
274− delete watcher;
275− }
300+void AccountsService::emitChangedForProperty(const QString &interface, const QString &property)
301+{
302+ QString signalName = m_properties[interface][property].signal;
303+ QMetaObject::invokeMethod(this, signalName.toUtf8().data());
276304}
277305
278−void AccountsService::updatePasswordDisplayHint(bool async)
306+QVariant AccountsService::getProperty(const QString &interface, const QString &property) const
279307{
280− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
281− QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
282− QStringLiteral("PasswordDisplayHint"));
283− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
284−
285− connect(watcher, &QDBusPendingCallWatcher::finished,
286− this, [this](QDBusPendingCallWatcher* watcher) {
287−
288− QDBusPendingReply<QVariant> reply = *watcher;
289− watcher->deleteLater();
290− if (reply.isError()) {
291− qWarning() << "Failed to get 'PasswordDisplayHint' property - " << reply.error().message();
292− return;
293− }
308+ return m_properties[interface][property].value;
309+}
294310
295− const PasswordDisplayHint passwordDisplayHint = (PasswordDisplayHint)reply.value().toInt();
296− if (m_passwordDisplayHint != passwordDisplayHint) {
297− m_passwordDisplayHint = passwordDisplayHint;
298− Q_EMIT passwordDisplayHintChanged();
299− }
300− });
301− if (!async) {
302− watcher->waitForFinished();
303− delete watcher;
311+void AccountsService::setProperty(const QString &interface, const QString &property, const QVariant &value)
312+{
313+ if (m_properties[interface][property].value != value) {
314+ m_properties[interface][property].value = value;
315+ m_service->setUserPropertyAsync(m_user, interface, property, value);
316+ emitChangedForProperty(interface, property);
304317 }
305318}
306319
307−void AccountsService::updateFailedLogins(bool async)
320+void AccountsService::updateCache(const QString &interface, const QString &property, const QVariant &value)
308321{
309− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
310− QStringLiteral("com.canonical.unity.AccountsService.Private"),
311− QStringLiteral("FailedLogins"));
312− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
313−
314− connect(watcher, &QDBusPendingCallWatcher::finished,
315− this, [this](QDBusPendingCallWatcher* watcher) {
316−
317− QDBusPendingReply<QVariant> reply = *watcher;
318− watcher->deleteLater();
319− if (reply.isError()) {
320− qWarning() << "Failed to get 'FailedLogins' property - " << reply.error().message();
321− return;
322+ PropertyInfo &info = m_properties[interface][property];
323+
324+ if (info.proxyInterface) {
325+ QVariant finalValue;
326+ if (info.proxyConverter) {
327+ finalValue = info.proxyConverter(value);
328+ } else {
329+ finalValue = value;
322330 }
331+ info.proxyInterface->asyncCall(info.proxyMethod, finalValue);
332+ return; // don't bother saving a copy
333+ }
323334
324− const uint failedLogins = reply.value().toUInt();
325− if (m_failedLogins != failedLogins) {
326− m_failedLogins = failedLogins;
327− Q_EMIT failedLoginsChanged();
328− }
329− });
330− if (!async) {
331− watcher->waitForFinished();
332− delete watcher;
335+ if (info.value != value) {
336+ info.value = value;
337+ emitChangedForProperty(interface, property);
333338 }
334339}
335340
336−void AccountsService::updateHereEnabled(bool async)
341+void AccountsService::updateProperty(const QString &interface, const QString &property)
337342{
338343 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
339− QStringLiteral("com.ubuntu.location.providers.here.AccountsService"),
340− QStringLiteral("LicenseAccepted"));
344+ interface,
345+ property);
341346 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
342347
343348 connect(watcher, &QDBusPendingCallWatcher::finished,
344− this, [this](QDBusPendingCallWatcher* watcher) {
349+ this, [this, interface, property](QDBusPendingCallWatcher* watcher) {
345350
346351 QDBusPendingReply<QVariant> reply = *watcher;
347352 watcher->deleteLater();
348353 if (reply.isError()) {
349− qWarning() << "Failed to get 'LicenseAccepted' property - " << reply.error().message();
354+ qWarning() << "Failed to get '" << property << "' property:" << reply.error().message();
350355 return;
351356 }
352357
353− const bool hereEnabled = reply.value().toBool();
354− if (m_hereEnabled != hereEnabled) {
355− m_hereEnabled = hereEnabled;
356− Q_EMIT hereEnabledChanged();
357− }
358+ updateCache(interface, property, reply.value());
358359 });
359− if (!async) {
360− watcher->waitForFinished();
361− delete watcher;
362− }
363360}
364361
365−void AccountsService::updateHereLicensePath(bool async)
362+void AccountsService::updateAllProperties(const QString &interface, bool async)
366363{
367− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
368− QStringLiteral("com.ubuntu.location.providers.here.AccountsService"),
369− QStringLiteral("LicenseBasePath"));
364+ QDBusPendingCall pendingReply = m_service->getAllPropertiesAsync(m_user,
365+ interface);
370366 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
371367
372368 connect(watcher, &QDBusPendingCallWatcher::finished,
373− this, [this](QDBusPendingCallWatcher* watcher) {
369+ this, [this, interface](QDBusPendingCallWatcher* watcher) {
374370
375− QDBusPendingReply<QVariant> reply = *watcher;
371+ QDBusPendingReply< QHash<QString, QVariant> > reply = *watcher;
376372 watcher->deleteLater();
377373 if (reply.isError()) {
378− qWarning() << "Failed to get 'LicenseBasePath' property - " << reply.error().message();
374+ qWarning() << "Failed to get all properties for" << interface << ":" << reply.error().message();
379375 return;
380376 }
381377
382− QString hereLicensePath = reply.value().toString();
383− if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
384− hereLicensePath = QLatin1String("");
385−
386− if (m_hereLicensePath.isNull() || m_hereLicensePath != hereLicensePath) {
387− m_hereLicensePath = hereLicensePath;
388− Q_EMIT hereLicensePathChanged();
378+ auto valueHash = reply.value();
379+ auto i = valueHash.constBegin();
380+ while (i != valueHash.constEnd()) {
381+ updateCache(interface, i.key(), i.value());
382+ ++i;
389383 }
390384 });
391385 if (!async) {
392386 watcher->waitForFinished();
393− delete watcher;
394387 }
395388}
396389
397−uint AccountsService::failedLogins() const
390+void AccountsService::registerProxy(const QString &interface, const QString &property, QDBusInterface *iface, const QString &method, ProxyConverter converter)
398391{
399− return m_failedLogins;
392+ registerProperty(interface, property, nullptr);
393+
394+ m_properties[interface][property].proxyInterface = iface;
395+ m_properties[interface][property].proxyMethod = method;
396+ m_properties[interface][property].proxyConverter = converter;
400397}
401398
402−void AccountsService::setFailedLogins(uint failedLogins)
399+void AccountsService::registerProperty(const QString &interface, const QString &property, const QString &signal)
403400{
404− if (m_failedLogins != failedLogins) {
405− m_failedLogins = failedLogins;
406− m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService.Private"), QStringLiteral("FailedLogins"), failedLogins);
407−
408− Q_EMIT failedLoginsChanged();
409− }
401+ m_properties[interface][property] = PropertyInfo();
402+ m_properties[interface][property].signal = signal;
410403}
411404
412405void AccountsService::onPropertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
@@ -415,35 +408,13 @@ void AccountsService::onPropertiesChanged(const QString &user, const QString &in
415408 return;
416409 }
417410
418− if (interface == QLatin1String("com.canonical.unity.AccountsService")) {
419− if (changed.contains(QStringLiteral("demo-edges"))) {
420− updateDemoEdges();
421− }
422− } else if (interface == QLatin1String("com.canonical.unity.AccountsService.Private")) {
423− if (changed.contains(QStringLiteral("FailedLogins"))) {
424− updateFailedLogins();
425− }
426− } else if (interface == QLatin1String("com.ubuntu.touch.AccountsService.SecurityPrivacy")) {
427− if (changed.contains(QStringLiteral("StatsWelcomeScreen"))) {
428− updateStatsWelcomeScreen();
429− }
430− } else if (interface == QLatin1String("com.ubuntu.AccountsService.SecurityPrivacy")) {
431− if (changed.contains(QStringLiteral("PasswordDisplayHint"))) {
432− updatePasswordDisplayHint();
433− }
434− if (changed.contains(QStringLiteral("EnableLauncherWhileLocked"))) {
435− updateEnableLauncherWhileLocked();
436− }
437− if (changed.contains(QStringLiteral("EnableIndicatorsWhileLocked"))) {
438− updateEnableIndicatorsWhileLocked();
439− }
440− } else if (interface == QLatin1String("com.ubuntu.location.providers.here.AccountsService")) {
441− if (changed.contains(QStringLiteral("LicenseAccepted"))) {
442− updateHereEnabled();
443− }
444− if (changed.contains(QStringLiteral("LicenseBasePath"))) {
445− updateHereLicensePath();
411+ auto propHash = m_properties.value(interface);
412+ auto i = propHash.constBegin();
413+ while (i != propHash.constEnd()) {
414+ if (changed.contains(i.key())) {
415+ updateProperty(interface, i.key());
446416 }
417+ ++i;
447418 }
448419}
449420
@@ -453,6 +424,20 @@ void AccountsService::onMaybeChanged(const QString &user)
453424 return;
454425 }
455426
456− // Standard properties might have changed
457− updateBackgroundFile();
427+ // Any of the standard properties might have changed!
428+ auto propHash = m_properties.value(IFACE_ACCOUNTS_USER);
429+ auto i = propHash.constBegin();
430+ while (i != propHash.constEnd()) {
431+ updateProperty(IFACE_ACCOUNTS_USER, i.key());
432+ ++i;
433+ }
434+}
435+
436+void AccountsService::refresh(bool async)
437+{
438+ auto i = m_properties.constBegin();
439+ while (i != m_properties.constEnd()) {
440+ updateAllProperties(i.key(), async);
441+ ++i;
442+ }
458443}
plugins/AccountsService/AccountsService.h+60−38
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,22 +12,23 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Terry <michael.terry@canonical.com>
1715 */
1816
1917#ifndef UNITY_ACCOUNTSSERVICE_H
2018#define UNITY_ACCOUNTSSERVICE_H
2119
20+#include <QHash>
2221#include <QObject>
2322#include <QString>
23+#include <QStringList>
24+#include <QVariant>
2425
2526class AccountsServiceDBusAdaptor;
27+class QDBusInterface;
2628
2729class AccountsService: public QObject
2830{
2931 Q_OBJECT
30− Q_ENUMS(PasswordDisplayHint)
3132 Q_PROPERTY (QString user
3233 READ user
3334 WRITE setUser
@@ -36,6 +37,12 @@ class AccountsService: public QObject
3637 READ demoEdges
3738 WRITE setDemoEdges
3839 NOTIFY demoEdgesChanged)
40+ Q_PROPERTY (QStringList demoEdgesCompleted
41+ READ demoEdgesCompleted
42+ NOTIFY demoEdgesCompletedChanged)
43+ Q_PROPERTY (bool enableFingerprintIdentification
44+ READ enableFingerprintIdentification
45+ NOTIFY enableFingerprintIdentificationChanged)
3946 Q_PROPERTY (bool enableLauncherWhileLocked
4047 READ enableLauncherWhileLocked
4148 NOTIFY enableLauncherWhileLockedChanged)
@@ -55,22 +62,20 @@ class AccountsService: public QObject
5562 READ failedLogins
5663 WRITE setFailedLogins
5764 NOTIFY failedLoginsChanged)
58− Q_PROPERTY(bool hereEnabled
59− READ hereEnabled
60− WRITE setHereEnabled
61− NOTIFY hereEnabledChanged)
62− Q_PROPERTY(QString hereLicensePath
63− READ hereLicensePath
64− NOTIFY hereLicensePathChanged)
65− Q_PROPERTY(bool hereLicensePathValid // qml sees a null string as "", so we use proxy setting for that
66− READ hereLicensePathValid
67− NOTIFY hereLicensePathChanged)
65+ Q_PROPERTY (uint failedFingerprintLogins
66+ READ failedFingerprintLogins
67+ WRITE setFailedFingerprintLogins
68+ NOTIFY failedFingerprintLoginsChanged)
69+ Q_PROPERTY(QString realName READ realName WRITE setRealName NOTIFY realNameChanged)
70+ Q_PROPERTY(QString email READ email WRITE setEmail NOTIFY emailChanged)
71+ Q_PROPERTY(QStringList keymaps READ keymaps WRITE setKeymaps NOTIFY keymapsChanged)
6872
6973public:
7074 enum PasswordDisplayHint {
7175 Keyboard,
7276 Numeric,
7377 };
78+ Q_ENUM(PasswordDisplayHint)
7479
7580 explicit AccountsService(QObject *parent = 0, const QString & user = QString());
7681 ~AccountsService() = default;
@@ -79,6 +84,9 @@ public:
7984 void setUser(const QString &user);
8085 bool demoEdges() const;
8186 void setDemoEdges(bool demoEdges);
87+ QStringList demoEdgesCompleted() const;
88+ Q_INVOKABLE void markDemoEdgeCompleted(const QString &edge);
89+ bool enableFingerprintIdentification() const;
8290 bool enableLauncherWhileLocked() const;
8391 bool enableIndicatorsWhileLocked() const;
8492 QString backgroundFile() const;
@@ -86,49 +94,63 @@ public:
8694 PasswordDisplayHint passwordDisplayHint() const;
8795 uint failedLogins() const;
8896 void setFailedLogins(uint failedLogins);
89− bool hereEnabled() const;
90− void setHereEnabled(bool enabled);
91− QString hereLicensePath() const;
92− bool hereLicensePathValid() const;
97+ uint failedFingerprintLogins() const;
98+ void setFailedFingerprintLogins(uint failedFingerprintLogins);
99+ QString realName() const;
100+ void setRealName(const QString &realName);
101+ QString email() const;
102+ void setEmail(const QString &email);
103+ QStringList keymaps() const;
104+ void setKeymaps(const QStringList &keymaps);
93105
94106Q_SIGNALS:
95107 void userChanged();
96108 void demoEdgesChanged();
109+ void demoEdgesCompletedChanged();
110+ void enableFingerprintIdentificationChanged();
97111 void enableLauncherWhileLockedChanged();
98112 void enableIndicatorsWhileLockedChanged();
99113 void backgroundFileChanged();
100114 void statsWelcomeScreenChanged();
101115 void passwordDisplayHintChanged();
102116 void failedLoginsChanged();
103− void hereEnabledChanged();
104− void hereLicensePathChanged();
117+ void failedFingerprintLoginsChanged();
118+ void realNameChanged();
119+ void emailChanged();
120+ void keymapsChanged();
105121
106122private Q_SLOTS:
107123 void onPropertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
108124 void onMaybeChanged(const QString &user);
109125
110126private:
111− void updateDemoEdges(bool async = true);
112− void updateEnableLauncherWhileLocked(bool async = true);
113− void updateEnableIndicatorsWhileLocked(bool async = true);
114− void updateBackgroundFile(bool async = true);
115− void updateStatsWelcomeScreen(bool async = true);
116− void updatePasswordDisplayHint(bool async = true);
117− void updateFailedLogins(bool async = true);
118− void updateHereEnabled(bool async = true);
119− void updateHereLicensePath(bool async = true);
127+ typedef QVariant (*ProxyConverter)(const QVariant &);
128+
129+ void refresh(bool async);
130+ void registerProperty(const QString &interface, const QString &property, const QString &signal);
131+ void registerProxy(const QString &interface, const QString &property, QDBusInterface *iface, const QString &method, ProxyConverter converter = nullptr);
132+
133+ void updateAllProperties(const QString &interface, bool async);
134+ void updateProperty(const QString &interface, const QString &property);
135+ void updateCache(const QString &interface, const QString &property, const QVariant &value);
120136
137+ void setProperty(const QString &interface, const QString &property, const QVariant &value);
138+ QVariant getProperty(const QString &interface, const QString &property) const;
139+
140+ void emitChangedForProperty(const QString &interface, const QString &property);
141+
142+ struct PropertyInfo {
143+ QVariant value{};
144+ QString signal{};
145+ QDBusInterface *proxyInterface{};
146+ QString proxyMethod{};
147+ ProxyConverter proxyConverter{};
148+ };
149+ typedef QHash< QString, QHash<QString, PropertyInfo> > PropertyHash;
150+ PropertyHash m_properties;
121151 AccountsServiceDBusAdaptor *m_service;
152+ QDBusInterface *m_unityInput;
122153 QString m_user;
123− bool m_demoEdges;
124− bool m_enableLauncherWhileLocked;
125− bool m_enableIndicatorsWhileLocked;
126− QString m_backgroundFile;
127− bool m_statsWelcomeScreen;
128− PasswordDisplayHint m_passwordDisplayHint;
129− uint m_failedLogins;
130− bool m_hereEnabled;
131− QString m_hereLicensePath;
132154};
133155
134156#endif
plugins/AccountsService/AccountsService.qmltypesdeleted−36
@@ -1,36 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable AccountsService 0.1 plugins'
8−
9−Module {
10− Component {
11− name: "AccountsService"
12− prototype: "QObject"
13− exports: ["AccountsService/AccountsService 0.1"]
14− isCreatable: false
15− isSingleton: true
16− exportMetaObjectRevisions: [0]
17− Enum {
18− name: "PasswordDisplayHint"
19− values: {
20− "Keyboard": 0,
21− "Numeric": 1
22− }
23− }
24− Property { name: "user"; type: "string" }
25− Property { name: "demoEdges"; type: "bool" }
26− Property { name: "enableLauncherWhileLocked"; type: "bool"; isReadonly: true }
27− Property { name: "enableIndicatorsWhileLocked"; type: "bool"; isReadonly: true }
28− Property { name: "backgroundFile"; type: "string"; isReadonly: true }
29− Property { name: "statsWelcomeScreen"; type: "bool"; isReadonly: true }
30− Property { name: "passwordDisplayHint"; type: "PasswordDisplayHint"; isReadonly: true }
31− Property { name: "failedLogins"; type: "uint" }
32− Property { name: "hereEnabled"; type: "bool" }
33− Property { name: "hereLicensePath"; type: "string"; isReadonly: true }
34− Property { name: "hereLicensePathValid"; type: "bool"; isReadonly: true }
35− }
36−}
plugins/AccountsService/AccountsServiceDBusAdaptor.cpp+23−6
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,8 +12,6 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Author: Michael Terry <michael.terry@canonical.com>
1715 */
1816
1917#include "AccountsServiceDBusAdaptor.h"
@@ -37,6 +35,15 @@ AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
3735 connection, this);
3836}
3937
38+QDBusPendingReply<QVariantMap> AccountsServiceDBusAdaptor::getAllPropertiesAsync(const QString &user, const QString &interface)
39+{
40+ QDBusInterface *iface = getUserInterface(user);
41+ if (iface != nullptr && iface->isValid()) {
42+ return iface->asyncCall(QStringLiteral("GetAll"), interface);
43+ }
44+ return QDBusPendingReply<QVariantMap>(QDBusMessage::createError(QDBusError::Other, QStringLiteral("Invalid Interface")));
45+}
46+
4047QDBusPendingReply<QVariant> AccountsServiceDBusAdaptor::getUserPropertyAsync(const QString &user, const QString &interface, const QString &property)
4148{
4249 QDBusInterface *iface = getUserInterface(user);
@@ -50,8 +57,18 @@ QDBusPendingCall AccountsServiceDBusAdaptor::setUserPropertyAsync(const QString
5057{
5158 QDBusInterface *iface = getUserInterface(user);
5259 if (iface != nullptr && iface->isValid()) {
53− // The value needs to be carefully wrapped
54− return iface->asyncCall(QStringLiteral("Set"), interface, property, QVariant::fromValue(QDBusVariant(value)));
60+ if (interface == QStringLiteral("org.freedesktop.Accounts.User")) {
61+ // Standard AccountsService properties use special set methods.
62+ // It will not let you use the usual DBus property setters.
63+ QDBusInterface accountsIface(iface->service(),
64+ iface->path(),
65+ interface,
66+ iface->connection());
67+ return accountsIface.asyncCall(QStringLiteral("Set") + property, value);
68+ } else {
69+ // The value needs to be carefully wrapped
70+ return iface->asyncCall(QStringLiteral("Set"), interface, property, QVariant::fromValue(QDBusVariant(value)));
71+ }
5572 }
5673 return QDBusPendingCall::fromCompletedCall(QDBusMessage::createError(QDBusError::Other, QStringLiteral("Invalid Interface")));
5774}
@@ -80,7 +97,7 @@ void AccountsServiceDBusAdaptor::maybeChangedSlot()
8097 m_ignoreNextChanged = false;
8198}
8299
83−QString AccountsServiceDBusAdaptor::getUserForPath(const QString &path)
100+QString AccountsServiceDBusAdaptor::getUserForPath(const QString &path) const
84101{
85102 QMap<QString, QDBusInterface *>::const_iterator i;
86103 for (i = m_users.constBegin(); i != m_users.constEnd(); ++i) {
plugins/AccountsService/AccountsServiceDBusAdaptor.h+5−6
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,8 +12,6 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Terry <michael.terry@canonical.com>
1715 */
1816
1917#ifndef UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
@@ -35,8 +33,9 @@ public:
3533 explicit AccountsServiceDBusAdaptor(QObject *parent = 0);
3634 ~AccountsServiceDBusAdaptor() = default;
3735
38− Q_INVOKABLE QDBusPendingReply<QVariant> getUserPropertyAsync(const QString &user, const QString &interface, const QString &property);
39− Q_INVOKABLE QDBusPendingCall setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value);
36+ QDBusPendingReply<QVariantMap> getAllPropertiesAsync(const QString &user, const QString &interface);
37+ QDBusPendingReply<QVariant> getUserPropertyAsync(const QString &user, const QString &interface, const QString &property);
38+ QDBusPendingCall setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value);
4039
4140Q_SIGNALS:
4241 void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
@@ -48,7 +47,7 @@ private Q_SLOTS:
4847
4948private:
5049 QDBusInterface *getUserInterface(const QString &user);
51− QString getUserForPath(const QString &path);
50+ QString getUserForPath(const QString &path) const;
5251
5352 QDBusInterface *m_accountsManager;
5453 QMap<QString, QDBusInterface *> m_users;
plugins/AccountsService/CMakeLists.txt+5−1
@@ -1,4 +1,5 @@
11add_definitions(-DSM_BUSNAME=systemBus)
2+include_directories(${GLIB_INCLUDE_DIRS})
23
34add_library(AccountsService-qml MODULE
45 AccountsService.cpp
@@ -6,7 +7,10 @@ add_library(AccountsService-qml MODULE
67 plugin.cpp
78 )
89
9−qt5_use_modules(AccountsService-qml DBus Qml)
10+target_link_libraries(AccountsService-qml
11+ Qt5::DBus Qt5::Qml
12+ ${GLIB_LIBRARIES}
13+ )
1014
1115add_unity8_plugin(AccountsService 0.1 AccountsService TARGETS AccountsService-qml)
1216
plugins/AccountsService/com.canonical.unity.AccountsService.xml+15
@@ -9,11 +9,22 @@
99 <annotation name="org.freedesktop.Accounts.Authentication.ChangeAny"
1010 value="com.ubuntu.AccountsService.GreeterChangeAny"/>
1111
12+ <!-- Marks that V1 (pre-8.21) edge demos have been run. Legacy value. -->
1213 <!-- Should have been named DemoEdges, sorry folks. -mterry -->
1314 <property name="demo-edges" type="b" access="readwrite">
1415 <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
1516 </property>
1617
18+ <!-- Marks that V2 (post-8.21) edge demos have been run -->
19+ <property name="DemoEdges2" type="b" access="readwrite">
20+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
21+ </property>
22+
23+ <!-- List of tutorial pages that have been completed by the user -->
24+ <property name="DemoEdgesCompleted" type="as" access="readwrite">
25+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="[]"/>
26+ </property>
27+
1728 <property name="LauncherItems" type="aa{sv}" access="readwrite">
1829 <annotation name="org.freedesktop.Accounts.DefaultValue" value="[{'defaults': <true>}]"/>
1930 </property>
@@ -42,5 +53,9 @@
4253 <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
4354 </property>
4455
56+ <property name="FailedFingerprintLogins" type="u" access="readwrite">
57+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
58+ </property>
59+
4560 </interface>
4661</node>
plugins/CMakeLists.txt+5−4
@@ -1,4 +1,4 @@
1−include(QmlPlugins)
1+find_package(QmlPlugins)
22
33# Set up and install a plugin for unity8.
44#
@@ -15,13 +15,14 @@ add_subdirectory(AccountsService)
1515add_subdirectory(Cursor)
1616add_subdirectory(GlobalShortcut)
1717add_subdirectory(Greeter)
18−add_subdirectory(IntegratedLightDM)
18+add_subdirectory(LightDM)
1919add_subdirectory(Lights)
20−add_subdirectory(Dash)
2120add_subdirectory(Powerd)
21+add_subdirectory(ScreenshotDirectory)
2222add_subdirectory(SessionBroadcast)
23−add_subdirectory(ScreenGrabber)
2423add_subdirectory(Ubuntu)
24+add_subdirectory(UInput)
2525add_subdirectory(Unity)
2626add_subdirectory(Utils)
27+add_subdirectory(WindowManager)
2728add_subdirectory(Wizard)
plugins/Cursor/CMakeLists.txt+8−4
@@ -3,13 +3,18 @@ add_subdirectory(3rd_party)
33include_directories(
44 ${CMAKE_CURRENT_SOURCE_DIR}
55 ${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/xcursor
6+)
7+
8+include_directories(
9+ SYSTEM
610 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
711)
812
913set(QMLPLUGIN_SRC
1014 plugin.cpp
11− MousePointer.cpp
15+ CursorImageInfo.cpp
1216 CursorImageProvider.cpp
17+ MousePointer.cpp
1318 # We need to run moc on this header
1419 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirMousePointerInterface.h
1520 )
@@ -21,8 +26,7 @@ add_library(Cursor-qml SHARED
2126target_link_libraries(Cursor-qml
2227 xcursorloader-static
2328 ${QT5PLATFORM_SUPPORT_LDFLAGS}
29+ Qt5::Qml Qt5::Quick Qt5::Svg
2430)
2531
26−qt5_use_modules(Cursor-qml Qml Quick DBus Network Gui Sql Concurrent Svg)
27−
28−add_unity8_plugin(Cursor 1.0 Cursor TARGETS Cursor-qml)
32+add_unity8_plugin(Cursor 1.1 Cursor TARGETS Cursor-qml)
plugins/Cursor/Cursor.qml+40−6
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -15,14 +15,48 @@
1515 */
1616
1717import QtQuick 2.4
18−import Cursor 1.0 // For MousePointer
18+import Cursor 1.1
19+import Powerd 0.1
1920
2021MousePointer {
2122 id: mousePointer
2223
23− Image {
24− x: -mousePointer.hotspotX
25− y: -mousePointer.hotspotY
26− source: "image://cursor/" + mousePointer.themeName + "/" + mousePointer.cursorName
24+ CursorImageInfo {
25+ id: imageInfo
26+ themeName: mousePointer.themeName
27+ cursorName: mousePointer.cursorName
28+ cursorHeight: mousePointer.height
29+ }
30+
31+ Loader {
32+ active: mousePointer.visible && imageInfo.frameCount > 1
33+ sourceComponent: AnimatedSprite {
34+ x: -imageInfo.hotspot.x
35+ y: -imageInfo.hotspot.y
36+ source: imageInfo.imageSource
37+
38+ interpolate: false
39+
40+ width: imageInfo.frameWidth
41+ height: imageInfo.frameHeight
42+
43+ frameCount: imageInfo.frameCount
44+ frameDuration: imageInfo.frameDuration
45+ frameWidth: imageInfo.frameWidth
46+ frameHeight: imageInfo.frameHeight
47+
48+ running: Powerd.status === Powerd.On
49+ }
50+ }
51+
52+ Loader {
53+ active: mousePointer.visible && imageInfo.frameCount === 1
54+ sourceComponent: Image {
55+ x: -imageInfo.hotspot.x
56+ y: -imageInfo.hotspot.y
57+ source: imageInfo.imageSource
58+ width: sourceSize.width
59+ height: sourceSize.height
60+ }
2761 }
2862}
plugins/Cursor/CursorImageInfo.cppnew file+115
@@ -0,0 +1,115 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "CursorImageInfo.h"
18+
19+CursorImageInfo::CursorImageInfo(QObject *parent)
20+ : QObject(parent)
21+{
22+}
23+
24+void CursorImageInfo::setCursorName(const QString &cursorName)
25+{
26+ if (cursorName != m_cursorName) {
27+ m_cursorName = cursorName;
28+ update();
29+ Q_EMIT cursorNameChanged();
30+ }
31+
32+}
33+void CursorImageInfo::setCursorHeight(qreal cursorHeight)
34+{
35+ if (cursorHeight != m_cursorHeight) {
36+ m_cursorHeight = cursorHeight;
37+ update();
38+ Q_EMIT cursorHeightChanged();
39+ }
40+}
41+
42+void CursorImageInfo::setThemeName(const QString &themeName)
43+{
44+ if (m_themeName != themeName) {
45+ m_themeName = themeName;
46+ update();
47+ Q_EMIT themeNameChanged();
48+ }
49+}
50+
51+void CursorImageInfo::update()
52+{
53+ m_cursorImage = CursorImageProvider::instance()->fetchCursor(m_themeName, m_cursorName, (int) m_cursorHeight);
54+
55+ Q_EMIT hotspotChanged();
56+ Q_EMIT frameWidthChanged();
57+ Q_EMIT frameHeightChanged();
58+ Q_EMIT frameCountChanged();
59+ Q_EMIT frameDurationChanged();
60+ Q_EMIT imageSourceChanged();
61+}
62+
63+QPoint CursorImageInfo::hotspot() const
64+{
65+ if (m_cursorImage) {
66+ return m_cursorImage->hotspot;
67+ } else {
68+ return QPoint();
69+ }
70+}
71+
72+qreal CursorImageInfo::frameWidth() const
73+{
74+ if (m_cursorImage) {
75+ return m_cursorImage->frameWidth;
76+ } else {
77+ return 0;
78+ }
79+}
80+
81+qreal CursorImageInfo::frameHeight() const
82+{
83+ if (m_cursorImage) {
84+ return m_cursorImage->frameHeight;
85+ } else {
86+ return 0;
87+ }
88+}
89+
90+int CursorImageInfo::frameCount() const
91+{
92+ if (m_cursorImage) {
93+ return m_cursorImage->frameCount;
94+ } else {
95+ return 0;
96+ }
97+}
98+
99+int CursorImageInfo::frameDuration() const
100+{
101+ if (m_cursorImage) {
102+ return m_cursorImage->frameDuration;
103+ } else {
104+ return 0;
105+ }
106+}
107+
108+QUrl CursorImageInfo::imageSource() const
109+{
110+ auto urlString = QString("image://cursor/%1/%2/%3")
111+ .arg(m_themeName, m_cursorName)
112+ .arg(m_cursorHeight);
113+
114+ return QUrl(urlString);
115+}
plugins/Cursor/CursorImageInfo.hnew file+82
@@ -0,0 +1,82 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef CURSOR_IMAGE_INFO_H
18+#define CURSOR_IMAGE_INFO_H
19+
20+#include "CursorImageProvider.h"
21+
22+#include <QObject>
23+#include <QString>
24+#include <QUrl>
25+
26+class CursorImageInfo : public QObject
27+{
28+ Q_OBJECT
29+
30+ Q_PROPERTY(QString themeName READ themeName WRITE setThemeName NOTIFY themeNameChanged)
31+ Q_PROPERTY(QString cursorName READ cursorName WRITE setCursorName NOTIFY cursorNameChanged)
32+ Q_PROPERTY(qreal cursorHeight READ cursorHeight WRITE setCursorHeight NOTIFY cursorHeightChanged)
33+
34+ Q_PROPERTY(QPoint hotspot READ hotspot NOTIFY hotspotChanged)
35+ Q_PROPERTY(qreal frameWidth READ frameWidth NOTIFY frameWidthChanged)
36+ Q_PROPERTY(qreal frameHeight READ frameHeight NOTIFY frameHeightChanged)
37+ Q_PROPERTY(int frameCount READ frameCount NOTIFY frameCountChanged)
38+ Q_PROPERTY(int frameDuration READ frameDuration NOTIFY frameDurationChanged)
39+ Q_PROPERTY(QUrl imageSource READ imageSource NOTIFY imageSourceChanged)
40+
41+public:
42+ CursorImageInfo(QObject *parent = nullptr);
43+
44+ QString themeName() const { return m_themeName; }
45+ void setThemeName(const QString &);
46+
47+ QString cursorName() const { return m_cursorName; }
48+ void setCursorName(const QString &);
49+
50+ qreal cursorHeight() const { return m_cursorHeight; }
51+ void setCursorHeight(qreal);
52+
53+ QPoint hotspot() const;
54+ qreal frameWidth() const;
55+ qreal frameHeight() const;
56+ int frameCount() const;
57+ int frameDuration() const;
58+ QUrl imageSource() const;
59+
60+Q_SIGNALS:
61+ void themeNameChanged();
62+ void cursorNameChanged();
63+ void cursorHeightChanged();
64+ void hotspotChanged();
65+ void frameWidthChanged();
66+ void frameHeightChanged();
67+ void frameCountChanged();
68+ void frameDurationChanged();
69+ void imageSourceChanged();
70+
71+private Q_SLOTS:
72+ void update();
73+
74+private:
75+ QString m_themeName;
76+ QString m_cursorName;
77+ qreal m_cursorHeight{0};
78+
79+ CursorImage *m_cursorImage{nullptr};
80+};
81+
82+#endif // CURSOR_IMAGE_INFO_H
plugins/Cursor/CursorImageProvider.cpp+86−41
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it under
55 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -27,7 +27,7 @@ CursorImageProvider *CursorImageProvider::m_instance = nullptr;
2727/////
2828// BuiltInCursorImage
2929
30−BuiltInCursorImage::BuiltInCursorImage()
30+BuiltInCursorImage::BuiltInCursorImage(int cursorHeight)
3131{
3232 const char *svgString =
3333 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
@@ -42,10 +42,15 @@ BuiltInCursorImage::BuiltInCursorImage()
4242 " d=\"M 20.504,50.94931 460.42533,518.14486 266.47603,515.61948 366.48114,719.16522 274.05218,770.68296 172.53185,559.56112 20.504,716.13476 Z\" />"
4343 "</svg>";
4444
45− qimage = QImage(20, 32, QImage::Format_ARGB32);
45+ // NB: Original image dimension is 20x32. Ensure aspect ratio is kept
46+ qimage = QImage((20./32.)*cursorHeight, cursorHeight, QImage::Format_ARGB32);
4647 qimage.fill(Qt::transparent);
4748 QPainter imagePainter(&qimage);
4849
50+ frameWidth = qimage.width();
51+ frameHeight = qimage.height();
52+ requestedHeight = cursorHeight;
53+
4954 QSvgRenderer *svgRenderer = new QSvgRenderer(QByteArray(svgString));
5055 svgRenderer->render(&imagePainter);
5156 delete svgRenderer;
@@ -59,6 +64,8 @@ BlankCursorImage::BlankCursorImage()
5964{
6065 qimage = QImage(1, 1, QImage::Format_ARGB32);
6166 qimage.fill(Qt::transparent);
67+ frameWidth = qimage.width();
68+ frameHeight = qimage.height();
6269}
6370
6471/////
@@ -69,38 +76,72 @@ CustomCursorImage::CustomCursorImage(const QCursor &cursor)
6976{
7077 qimage = cursor.pixmap().toImage();
7178 hotspot = cursor.hotSpot();
79+ frameWidth = qimage.width();
80+ frameHeight = qimage.height();
7281}
7382
7483/////
7584// XCursorImage
7685
77−XCursorImage::XCursorImage(const QString &theme, const QString &file)
78− : xcursorImages(nullptr)
86+XCursorImage::XCursorImage(const QString &theme, const QString &file, int preferredCursorHeightPx)
7987{
80− xcursorImages = XcursorLibraryLoadImages(QFile::encodeName(file), QFile::encodeName(theme), 32);
81− if (!xcursorImages) {
88+ requestedHeight = preferredCursorHeightPx;
89+
90+ XcursorImages *xcursorImages = XcursorLibraryLoadImages(QFile::encodeName(file), QFile::encodeName(theme),
91+ preferredCursorHeightPx);
92+ if (!xcursorImages || xcursorImages->nimage == 0) {
8293 return;
8394 }
8495
85− bool loaded = false;
86− for (int i = 0; i < xcursorImages->nimage && !loaded; ++i) {
96+ frameCount = xcursorImages->nimage;
97+
98+ for (int i = 0; i < xcursorImages->nimage; ++i) {
8799 XcursorImage *xcursorImage = xcursorImages->images[i];
88− if (xcursorImage->size == 32) {
100+ if (frameWidth < (int)xcursorImage->width) {
101+ frameWidth = xcursorImage->width;
102+ }
103+ if (frameHeight < (int)xcursorImage->height) {
104+ frameHeight = xcursorImage->height;
105+ }
106+ if (i == 0) {
107+ frameDuration = (int)xcursorImage->delay;
108+ } else {
109+ if (frameDuration != (int)xcursorImage->delay) {
110+ qWarning().nospace() << "CursorImageProvider: XCursorImage("<<theme<<","<<file<<") has"
111+ " varying delays in its animation. Animation won't look right.";
112+ }
113+ }
114+ }
89115
90− qimage = QImage((uchar*)xcursorImage->pixels,
91− xcursorImage->width, xcursorImage->height, QImage::Format_ARGB32);
116+ {
117+ // Assume that the hotspot position does not animate
118+ XcursorImage *xcursorImage = xcursorImages->images[0];
119+ hotspot.setX(xcursorImage->xhot);
120+ hotspot.setY(xcursorImage->yhot);
121+ }
122+
123+ // Build the sprite as a single row of frames
124+ qimage = QImage(frameWidth*frameCount, frameHeight, QImage::Format_ARGB32);
125+ qimage.fill(Qt::transparent);
126+
127+ {
128+ QPainter painter(&qimage);
129+
130+ for (int i = 0; i < xcursorImages->nimage; ++i) {
131+ XcursorImage *xcursorImage = xcursorImages->images[i];
92132
93− hotspot.setX(xcursorImage->xhot);
94− hotspot.setY(xcursorImage->yhot);
133+ auto frameImage = QImage((uchar*)xcursorImage->pixels,
134+ xcursorImage->width, xcursorImage->height, QImage::Format_ARGB32);
95135
96− loaded = true;
136+ painter.drawImage(QPoint(i*frameWidth, 0), frameImage);
97137 }
98138 }
139+
140+ XcursorImagesDestroy(xcursorImages);
99141}
100142
101143XCursorImage::~XCursorImage()
102144{
103− XcursorImagesDestroy(xcursorImages);
104145}
105146
106147/////
@@ -133,6 +174,8 @@ CursorImageProvider::CursorImageProvider()
133174 m_fallbackNames[QStringLiteral("forbidden")].append(QStringLiteral("not-allowed"));
134175 m_fallbackNames[QStringLiteral("forbidden")].append(QStringLiteral("circle"));
135176
177+ m_fallbackNames[QStringLiteral("grabbing")].append(QStringLiteral("closedhand")); // Breeze
178+
136179 m_fallbackNames[QStringLiteral("hand")].append(QStringLiteral("pointing_hand"));
137180 m_fallbackNames[QStringLiteral("hand")].append(QStringLiteral("pointer"));
138181
@@ -194,44 +237,43 @@ CursorImageProvider::~CursorImageProvider()
194237 m_instance = nullptr;
195238}
196239
197−QImage CursorImageProvider::requestImage(const QString &cursorThemeAndName, QSize *size, const QSize & /*requestedSize*/)
240+QImage CursorImageProvider::requestImage(const QString &cursorThemeAndNameAndHeight, QSize *size, const QSize & /*requestedSize*/)
198241{
199− CursorImage *cursorImage = fetchCursor(cursorThemeAndName);
242+ CursorImage *cursorImage = fetchCursor(cursorThemeAndNameAndHeight);
200243 size->setWidth(cursorImage->qimage.width());
201244 size->setHeight(cursorImage->qimage.height());
202245
203246 return cursorImage->qimage;
204247}
205248
206−QPoint CursorImageProvider::hotspot(const QString &themeName, const QString &cursorName)
207−{
208− CursorImage *cursorImage = fetchCursor(themeName, cursorName);
209− if (cursorImage) {
210− return cursorImage->hotspot;
211− } else {
212− return QPoint(0,0);
213− }
214−}
215−
216−CursorImage *CursorImageProvider::fetchCursor(const QString &cursorThemeAndName)
249+CursorImage *CursorImageProvider::fetchCursor(const QString &cursorThemeAndNameAndHeight)
217250{
218251 QString themeName;
219252 QString cursorName;
253+ int cursorHeight;
220254 {
221− QStringList themeAndNameList = cursorThemeAndName.split('/');
222− if (themeAndNameList.size() != 2) {
255+ QStringList themeAndNameList = cursorThemeAndNameAndHeight.split('/');
256+ if (themeAndNameList.size() != 3) {
223257 return nullptr;
224258 }
225259 themeName = themeAndNameList[0];
226260 cursorName = themeAndNameList[1];
261+
262+ bool ok;
263+ cursorHeight = themeAndNameList[2].toInt(&ok);
264+ if (!ok) {
265+ cursorHeight = 32;
266+ qWarning().nospace() << "CursorImageProvider: invalid cursor height ("<<themeAndNameList[2]<<")."
267+ " Falling back to "<<cursorHeight<<" pixels";
268+ }
227269 }
228270
229− return fetchCursor(themeName, cursorName);
271+ return fetchCursor(themeName, cursorName, cursorHeight);
230272}
231273
232−CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QString &cursorName)
274+CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QString &cursorName, int cursorHeight)
233275{
234− CursorImage *cursorImage = fetchCursorHelper(themeName, cursorName);
276+ CursorImage *cursorImage = fetchCursorHelper(themeName, cursorName, cursorHeight);
235277
236278 // Try some fallbacks
237279 if (cursorImage->qimage.isNull()) {
@@ -240,7 +282,7 @@ CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QS
240282 int i = 0;
241283 while (cursorImage->qimage.isNull() && i < fallbackNames.count()) {
242284 qDebug().nospace() << "CursorImageProvider: "<< cursorName <<" not found, trying " << fallbackNames.at(i);
243− cursorImage = fetchCursorHelper(themeName, fallbackNames.at(i));
285+ cursorImage = fetchCursorHelper(themeName, fallbackNames.at(i), cursorHeight);
244286 ++i;
245287 }
246288 }
@@ -250,14 +292,14 @@ CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QS
250292 if (cursorImage->qimage.isNull() && cursorName != QLatin1String("left_ptr")) {
251293 qDebug() << "CursorImageProvider:" << cursorName
252294 << "not found (nor its fallbacks, if any). Going for \"left_ptr\" as a last resort.";
253− cursorImage = fetchCursorHelper(themeName, QStringLiteral("left_ptr"));
295+ cursorImage = fetchCursorHelper(themeName, QStringLiteral("left_ptr"), cursorHeight);
254296 }
255297
256298 if (cursorImage->qimage.isNull()) {
257299 // finally, go for the built-in cursor
258300 qWarning() << "CursorImageProvider: couldn't find any cursors. Using the built-in one";
259− if (!m_builtInCursorImage) {
260− m_builtInCursorImage.reset(new BuiltInCursorImage);
301+ if (!m_builtInCursorImage || m_builtInCursorImage->requestedHeight != cursorHeight) {
302+ m_builtInCursorImage.reset(new BuiltInCursorImage(cursorHeight));
261303 }
262304 cursorImage = m_builtInCursorImage.data();
263305 }
@@ -265,17 +307,20 @@ CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QS
265307 return cursorImage;
266308}
267309
268−CursorImage *CursorImageProvider::fetchCursorHelper(const QString &themeName, const QString &cursorName)
310+CursorImage *CursorImageProvider::fetchCursorHelper(const QString &themeName, const QString &cursorName, int cursorHeight)
269311{
270312 if (cursorName == QLatin1String("blank")) {
271313 return &m_blankCursorImage;
272− } else if (cursorName == QLatin1String("custom")) {
314+ } else if (cursorName.startsWith(QLatin1String("custom"))) {
273315 return m_customCursorImage.data();
274316 } else {
275317 QMap<QString, CursorImage*> &themeCursors = m_cursors[themeName];
276318
277319 if (!themeCursors.contains(cursorName)) {
278− themeCursors[cursorName] = new XCursorImage(themeName, cursorName);
320+ themeCursors[cursorName] = new XCursorImage(themeName, cursorName, cursorHeight);
321+ } else if (themeCursors[cursorName]->requestedHeight != cursorHeight) {
322+ delete themeCursors.take(cursorName);
323+ themeCursors[cursorName] = new XCursorImage(themeName, cursorName, cursorHeight);
279324 }
280325
281326 return themeCursors[cursorName];
plugins/Cursor/CursorImageProvider.h+20−9
@@ -31,20 +31,31 @@ public:
3131 virtual ~CursorImage() {}
3232
3333 QImage qimage;
34+
35+ // TODO: consider if there's a need to animate the hotspot
36+ // ie, if there's a need to make it an array of points, one for each frame.
37+ // Maybe no single xcursor (or at least the ones we know of or use)
38+ // vary its hotspot position through its animation.
3439 QPoint hotspot;
40+
41+ int frameWidth{0};
42+ int frameHeight{0};
43+ int frameCount{1};
44+ int frameDuration{40};
45+
46+ // Requested height when creating this cursor.
47+ int requestedHeight{0};
3548};
3649
3750class XCursorImage : public CursorImage {
3851public:
39− XCursorImage(const QString &theme, const QString &file);
52+ XCursorImage(const QString &theme, const QString &file, int preferredCursorHeightPx);
4053 virtual ~XCursorImage();
41−
42− XcursorImages *xcursorImages;
4354};
4455
4556class BuiltInCursorImage : public CursorImage {
4657public:
47− BuiltInCursorImage();
58+ BuiltInCursorImage(int cursorHeight);
4859};
4960
5061class BlankCursorImage : public CursorImage {
@@ -66,18 +77,18 @@ public:
6677 static CursorImageProvider *instance() { return m_instance; }
6778
6879
69− QImage requestImage(const QString &cursorName, QSize *size, const QSize &requestedSize) override;
80+ QImage requestImage(const QString &cursorThemeAndNameAndHeight, QSize *size, const QSize &requestedSize) override;
7081
71− QPoint hotspot(const QString &themeName, const QString &cursorName);
82+ CursorImage *fetchCursor(const QString &themeName, const QString &cursorName, int cursorHeight);
7283
7384 void setCustomCursor(const QCursor &customCursor);
7485
7586private:
76− CursorImage *fetchCursor(const QString &cursorThemeAndName);
77− CursorImage *fetchCursor(const QString &themeName, const QString &cursorName);
78− CursorImage *fetchCursorHelper(const QString &themeName, const QString &cursorName);
87+ CursorImage *fetchCursor(const QString &cursorThemeAndNameAndHeight);
88+ CursorImage *fetchCursorHelper(const QString &themeName, const QString &cursorName, int cursorHeight);
7989
8090 // themeName -> (cursorName -> cursorImage)
91+ // TODO: discard old, unused, cursors
8192 QMap<QString, QMap<QString, CursorImage*> > m_cursors;
8293
8394 QScopedPointer<CursorImage> m_builtInCursorImage;
plugins/Cursor/MousePointer.cpp+130−39
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it under
55 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -22,6 +22,7 @@
2222
2323#include <QQuickWindow>
2424#include <QGuiApplication>
25+#include <QtMath>
2526
2627#include <qpa/qwindowsysteminterface.h>
2728
@@ -29,10 +30,7 @@ MousePointer::MousePointer(QQuickItem *parent)
2930 : MirMousePointerInterface(parent)
3031 , m_cursorName(QStringLiteral("left_ptr"))
3132 , m_themeName(QStringLiteral("default"))
32− , m_hotspotX(0)
33− , m_hotspotY(0)
3433{
35− updateHotspot();
3634}
3735
3836void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
@@ -42,29 +40,87 @@ void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::Mouse
4240 return;
4341 }
4442
45− qreal newX = x() + movement.x();
46− if (newX < 0) {
47− Q_EMIT pushedLeftBoundary(qAbs(newX), buttons);
48− newX = 0;
49− } else if (newX > parentItem()->width()) {
50− Q_EMIT pushedRightBoundary(newX - parentItem()->width(), buttons);
51− newX = parentItem()->width();
43+ if (!movement.isNull()) {
44+ Q_EMIT mouseMoved();
5245 }
53− setX(newX);
5446
55− qreal newY = y() + movement.y();
56− if (newY < 0) {
57− newY = 0;
58− } else if (newY > parentItem()->height()) {
59− newY = parentItem()->height();
47+ m_accumulatedMovement += movement;
48+ // don't apply the fractional part
49+ QPointF appliedMovement(int(m_accumulatedMovement.x()), int(m_accumulatedMovement.y()));
50+ m_accumulatedMovement -= appliedMovement;
51+
52+ qreal newX = x() + appliedMovement.x();
53+ qreal newY = y() + appliedMovement.y();
54+ const qreal sceneWidth = parentItem()->width();
55+ const qreal sceneHeight = parentItem()->height();
56+
57+ if (newX <= 0 && newY < m_topBoundaryOffset) { // top left corner
58+ const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-m_topBoundaryOffset, 2));
59+ Q_EMIT pushedTopLeftCorner(qAbs(distance), buttons);
60+ m_pushing = true;
61+ } else if (newX >= sceneWidth-1 && newY < m_topBoundaryOffset) { // top right corner
62+ const auto distance = qSqrt(qPow(newX-sceneWidth, 2) + qPow(newY-m_topBoundaryOffset, 2));
63+ Q_EMIT pushedTopRightCorner(qAbs(distance), buttons);
64+ m_pushing = true;
65+ } else if (newX < 0 && newY >= sceneHeight-1) { // bottom left corner
66+ const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-sceneHeight, 2));
67+ Q_EMIT pushedBottomLeftCorner(qAbs(distance), buttons);
68+ m_pushing = true;
69+ } else if (newX >= sceneWidth-1 && newY >= sceneHeight-1) { // bottom right corner
70+ const auto distance = qSqrt(qPow(newX-sceneWidth, 2) + qPow(newY-sceneHeight, 2));
71+ Q_EMIT pushedBottomRightCorner(qAbs(distance), buttons);
72+ m_pushing = true;
73+ } else if (newX < 0) { // left edge
74+ Q_EMIT pushedLeftBoundary(qAbs(newX), buttons);
75+ m_pushing = true;
76+ } else if (newX >= sceneWidth) { // right edge
77+ Q_EMIT pushedRightBoundary(newX - (sceneWidth - 1), buttons);
78+ m_pushing = true;
79+ } else if (newY < m_topBoundaryOffset) { // top edge
80+ Q_EMIT pushedTopBoundary(qAbs(newY - m_topBoundaryOffset), buttons);
81+ m_pushing = true;
82+ } else if (Q_LIKELY(newX > 0 && newX < sceneWidth-1 && newY > 0 && newY < sceneHeight-1)) { // normal pos, not pushing
83+ if (m_pushing) {
84+ Q_EMIT pushStopped();
85+ m_pushing = false;
86+ }
6087 }
61− setY(newY);
88+
89+ applyItemConfinement(newX, newY);
90+
91+ setX(qBound(0.0, newX, sceneWidth - 1));
92+ setY(qBound(0.0, newY, sceneHeight - 1));
6293
6394 QPointF scenePosition = mapToItem(nullptr, QPointF(0, 0));
6495 QWindowSystemInterface::handleMouseEvent(window(), timestamp, scenePosition /*local*/, scenePosition /*global*/,
6596 buttons, modifiers);
6697}
6798
99+void MousePointer::applyItemConfinement(qreal &newX, qreal &newY)
100+{
101+ Q_ASSERT(parentItem() != nullptr);
102+
103+ if (m_confiningItem.isNull()) {
104+ return;
105+ }
106+
107+ QRectF confiningItemGeometry(0, 0, m_confiningItem->width(), m_confiningItem->height());
108+
109+ QRectF confiningRect = m_confiningItem->mapRectToItem(parentItem(), confiningItemGeometry);
110+
111+ if (newX < confiningRect.x()) {
112+ newX = confiningRect.x();
113+ } else if (newX > confiningRect.right()) {
114+ newX = confiningRect.right();
115+ }
116+
117+ if (newY < confiningRect.y()) {
118+ newY = confiningRect.y();
119+ } else if (newY > confiningRect.bottom()) {
120+ newY = confiningRect.bottom();
121+ }
122+}
123+
68124void MousePointer::handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::KeyboardModifiers modifiers)
69125{
70126 if (!parentItem()) {
@@ -76,6 +132,20 @@ void MousePointer::handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::Keyb
76132 QPoint() /* pixelDelta */, angleDelta, modifiers, Qt::ScrollUpdate);
77133}
78134
135+int MousePointer::topBoundaryOffset() const
136+{
137+ return m_topBoundaryOffset;
138+}
139+
140+void MousePointer::setTopBoundaryOffset(int topBoundaryOffset)
141+{
142+ if (m_topBoundaryOffset == topBoundaryOffset)
143+ return;
144+
145+ m_topBoundaryOffset = topBoundaryOffset;
146+ Q_EMIT topBoundaryOffsetChanged(topBoundaryOffset);
147+}
148+
79149void MousePointer::itemChange(ItemChange change, const ItemChangeData &value)
80150{
81151 if (change == ItemSceneChange) {
@@ -85,8 +155,32 @@ void MousePointer::itemChange(ItemChange change, const ItemChangeData &value)
85155
86156void MousePointer::registerWindow(QWindow *window)
87157{
88− if (m_registeredWindow && window != m_registeredWindow) {
89− auto previousCursor = dynamic_cast<MirPlatformCursor*>(m_registeredWindow->screen()->handle()->cursor());
158+ if (window == m_registeredWindow) {
159+ return;
160+ }
161+
162+ if (m_registeredWindow) {
163+ m_registeredWindow->disconnect(this);
164+ }
165+
166+ m_registeredWindow = window;
167+
168+ if (m_registeredWindow) {
169+ connect(window, &QWindow::screenChanged, this, &MousePointer::registerScreen);
170+ registerScreen(window->screen());
171+ } else {
172+ registerScreen(nullptr);
173+ }
174+}
175+
176+void MousePointer::registerScreen(QScreen *screen)
177+{
178+ if (m_registeredScreen == screen) {
179+ return;
180+ }
181+
182+ if (m_registeredScreen) {
183+ auto previousCursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
90184 if (previousCursor) {
91185 previousCursor->setMousePointer(nullptr);
92186 } else {
@@ -94,10 +188,10 @@ void MousePointer::registerWindow(QWindow *window)
94188 }
95189 }
96190
97− m_registeredWindow = window;
191+ m_registeredScreen = screen;
98192
99− if (m_registeredWindow) {
100− auto cursor = dynamic_cast<MirPlatformCursor*>(window->screen()->handle()->cursor());
193+ if (m_registeredScreen) {
194+ auto cursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
101195 if (cursor) {
102196 cursor->setMousePointer(this);
103197 } else {
@@ -111,22 +205,6 @@ void MousePointer::setCursorName(const QString &cursorName)
111205 if (cursorName != m_cursorName) {
112206 m_cursorName = cursorName;
113207 Q_EMIT cursorNameChanged(m_cursorName);
114− updateHotspot();
115− }
116−}
117−
118−void MousePointer::updateHotspot()
119−{
120− QPoint newHotspot = CursorImageProvider::instance()->hotspot(m_themeName, m_cursorName);
121−
122− if (m_hotspotX != newHotspot.x()) {
123− m_hotspotX = newHotspot.x();
124− Q_EMIT hotspotXChanged(m_hotspotX);
125− }
126−
127− if (m_hotspotY != newHotspot.y()) {
128− m_hotspotY = newHotspot.y();
129− Q_EMIT hotspotYChanged(m_hotspotY);
130208 }
131209}
132210
@@ -142,3 +220,16 @@ void MousePointer::setCustomCursor(const QCursor &customCursor)
142220{
143221 CursorImageProvider::instance()->setCustomCursor(customCursor);
144222}
223+
224+QQuickItem* MousePointer::confiningItem() const
225+{
226+ return m_confiningItem.data();
227+}
228+
229+void MousePointer::setConfiningItem(QQuickItem *item)
230+{
231+ if (item != m_confiningItem) {
232+ m_confiningItem = item;
233+ Q_EMIT confiningItemChanged();
234+ }
235+}
plugins/Cursor/MousePointer.h+33−7
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it under
55 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -20,12 +20,15 @@
2020// Qt
2121#include <QPointer>
2222#include <QWindow>
23+#include <QScreen>
2324
2425// Unity API
2526#include <unity/shell/application/MirMousePointerInterface.h>
2627
2728class MousePointer : public MirMousePointerInterface {
2829 Q_OBJECT
30+ Q_PROPERTY(QQuickItem* confiningItem READ confiningItem WRITE setConfiningItem NOTIFY confiningItemChanged)
31+ Q_PROPERTY(int topBoundaryOffset READ topBoundaryOffset WRITE setTopBoundaryOffset NOTIFY topBoundaryOffsetChanged)
2932public:
3033 MousePointer(QQuickItem *parent = nullptr);
3134
@@ -35,11 +38,14 @@ public:
3538 void setThemeName(const QString &themeName) override;
3639 QString themeName() const override { return m_themeName; }
3740
38− qreal hotspotX() const override { return m_hotspotX; }
39− qreal hotspotY() const override { return m_hotspotY; }
40−
4141 void setCustomCursor(const QCursor &) override;
4242
43+ QQuickItem* confiningItem() const;
44+ void setConfiningItem(QQuickItem*);
45+
46+ int topBoundaryOffset() const;
47+ void setTopBoundaryOffset(int topBoundaryOffset);
48+
4349public Q_SLOTS:
4450 void handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
4551 Qt::KeyboardModifiers modifiers) override;
@@ -48,19 +54,39 @@ public Q_SLOTS:
4854Q_SIGNALS:
4955 void pushedLeftBoundary(qreal amount, Qt::MouseButtons buttons);
5056 void pushedRightBoundary(qreal amount, Qt::MouseButtons buttons);
57+ void pushedTopBoundary(qreal amount, Qt::MouseButtons buttons);
58+ void pushedTopLeftCorner(qreal amount, Qt::MouseButtons buttons);
59+ void pushedTopRightCorner(qreal amount, Qt::MouseButtons buttons);
60+ void pushedBottomLeftCorner(qreal amount, Qt::MouseButtons buttons);
61+ void pushedBottomRightCorner(qreal amount, Qt::MouseButtons buttons);
62+ void pushStopped();
63+ void mouseMoved();
64+ void confiningItemChanged();
65+
66+ void topBoundaryOffsetChanged(int topBoundaryOffset);
5167
5268protected:
5369 void itemChange(ItemChange change, const ItemChangeData &value) override;
5470
71+private Q_SLOTS:
72+ void registerScreen(QScreen *screen);
73+
5574private:
5675 void registerWindow(QWindow *window);
57− void updateHotspot();
76+ void applyItemConfinement(qreal &newX, qreal &newY);
5877
5978 QPointer<QWindow> m_registeredWindow;
79+ QPointer<QScreen> m_registeredScreen;
6080 QString m_cursorName;
6181 QString m_themeName;
62− int m_hotspotX;
63− int m_hotspotY;
82+
83+ // Accumulated, unapplied, mouse movement.
84+ QPointF m_accumulatedMovement;
85+
86+ QPointer<QQuickItem> m_confiningItem;
87+
88+ int m_topBoundaryOffset{0};
89+ bool m_pushing{false};
6490};
6591
6692#endif // MOUSEPOINTER_H
plugins/Cursor/plugin.cpp+4−2
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -22,13 +22,15 @@
2222#include "plugin.h"
2323
2424// local
25+#include "CursorImageInfo.h"
2526#include "CursorImageProvider.h"
2627#include "MousePointer.h"
2728
2829void CursorPlugin::registerTypes(const char *uri)
2930{
3031 Q_ASSERT(uri == QLatin1String("Cursor"));
31− qmlRegisterType<MousePointer>(uri, 1, 0, "MousePointer");
32+ qmlRegisterType<CursorImageInfo>(uri, 1, 1, "CursorImageInfo");
33+ qmlRegisterType<MousePointer>(uri, 1, 1, "MousePointer");
3234}
3335
3436void CursorPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
plugins/Cursor/qmldir+1−1
@@ -1,3 +1,3 @@
11module Cursor
22plugin Cursor-qml
3−Cursor 1.0 Cursor.qml
3+Cursor 1.1 Cursor.qml
plugins/Dash/CMakeLists.txtdeleted−40
@@ -1,40 +0,0 @@
1−# There's no cmake var for v8 include path :-/
2−# so create one
3−LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
4−if(${Qt5Core_VERSION_STRING} VERSION_LESS "5.1.0")
5− SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
6−else()
7− SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/QtV8/${Qt5Core_VERSION_STRING}/QtV8)
8−endif()
9−
10−include_directories(
11− ${CMAKE_CURRENT_SOURCE_DIR}
12− ${CMAKE_CURRENT_BINARY_DIR}
13− ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
14− ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
15− ${Qt5V8_PRIVATE_INCLUDE_DIR}
16−)
17−
18−remove_definitions(-DQT_NO_KEYWORDS)
19−
20−set(QMLPLUGIN_SRC
21− plugin.cpp
22− listviewwithpageheader.cpp
23− abstractdashview.cpp
24− verticaljournal.cpp
25− horizontaljournal.cpp
26− organicgrid.cpp
27− )
28−
29−add_library(Dash-qml MODULE
30− ${QMLPLUGIN_SRC}
31− )
32−
33−target_link_libraries(Dash-qml
34− ${Qt5Gui_LIBRARIES}
35− ${Qt5Quick_LIBRARIES}
36− )
37−
38−qt5_use_modules(Dash-qml Qml Quick Concurrent)
39−
40−add_unity8_plugin(Dash 0.1 Dash TARGETS Dash-qml)
plugins/Dash/CardAttributes.qmldeleted−71
@@ -1,71 +0,0 @@
1−/*
2− * Copyright 2014 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import QtQuick.Layouts 1.1
19−import Ubuntu.Components 1.3
20−
21−GridLayout {
22− id: grid
23− anchors {
24− left: parent.left;
25− right: parent.right;
26− }
27− columns: 2 + repeater.count % 2
28− rowSpacing: units.gu(.5)
29− property alias model: repeater.model
30− property color color: theme.palette.normal.baseText
31− property real fontScale: 1.0
32−
33− Repeater {
34− id: repeater
35− delegate: Row {
36− spacing: units.gu(0.5)
37− readonly property int column: index % grid.columns;
38− Layout.alignment: {
39− if (column == 0) return Qt.AlignLeft;
40− if (column == grid.columns - 1 || index == repeater.count - 1) return Qt.AlignRight;
41− if (column == 1) return Qt.AlignHCenter;
42− }
43− Layout.column: index % grid.columns
44− Layout.row: index / grid.columns
45− Layout.columnSpan: index == repeater.count - 1 && grid.columns == 3 && column == 1 ? 2 : 1
46− Layout.maximumWidth: Math.max(icon.width, label.x + label.implicitWidth)
47− Layout.fillWidth: true
48− height: units.gu(2)
49− Icon {
50− id: icon
51− height: units.gu(2)
52− // FIXME Workaround for bug https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1421293
53− width: implicitWidth > 0 && implicitHeight > 0 ? (implicitWidth / implicitHeight * height) : implicitWidth
54− source: "icon" in modelData && modelData["icon"] || ""
55− color: grid.color
56− }
57− Label {
58− id: label
59− width: parent.width - x
60− anchors.verticalCenter: parent.verticalCenter
61− text: "value" in modelData && modelData["value"] || "";
62− elide: Text.ElideRight
63− maximumLineCount: 1
64− font.weight: "style" in modelData && modelData["style"] === "highlighted" ? Font.Bold : Font.Light
65− fontSize: "small"
66− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale)
67− color: grid.color
68− }
69− }
70− }
71−}
plugins/Dash/CardCreator.jsdeleted−711
@@ -1,711 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−.pragma library
18−
19−// %1 is the template["card-background"] string
20−// %2 is the template["card-background"]["elements"][0]
21−// %3 is the template["card-background"]["elements"][1]
22−var kBackgroundLoaderCode = 'Loader {\n\
23− id: backgroundLoader; \n\
24− objectName: "backgroundLoader"; \n\
25− anchors.fill: parent; \n\
26− asynchronous: root.asynchronous; \n\
27− visible: status == Loader.Ready; \n\
28− sourceComponent: UbuntuShape { \n\
29− objectName: "background"; \n\
30− radius: "medium"; \n\
31− backgroundColor: getColor(0) || "white"; \n\
32− secondaryBackgroundColor: getColor(1) || backgroundColor; \n\
33− backgroundMode: UbuntuShape.VerticalGradient; \n\
34− anchors.fill: parent; \n\
35− source: backgroundImage.source ? backgroundImage : null; \n\
36− property real luminance: Style.luminance(backgroundColor); \n\
37− property Image backgroundImage: Image { \n\
38− objectName: "backgroundImage"; \n\
39− source: { \n\
40− if (cardData && typeof cardData["background"] === "string") return cardData["background"]; \n\
41− else return "%1"; \n\
42− } \n\
43− } \n\
44− function getColor(index) { \n\
45− if (cardData && typeof cardData["background"] === "object" \n\
46− && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) { \n\
47− return cardData["background"]["elements"][index]; \n\
48− } else return index === 0 ? %2 : %3; \n\
49− } \n\
50− } \n\
51− }\n';
52−
53−// %1 is used as anchors of artShapeHolder
54−// %2 is used as image width
55−// %3 is used as image height
56−var kArtShapeHolderCode = 'Item { \n\
57− id: artShapeHolder; \n\
58− height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height; \n\
59− width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width; \n\
60− anchors { %1 } \n\
61− Loader { \n\
62− id: artShapeLoader; \n\
63− objectName: "artShapeLoader"; \n\
64− active: cardData && cardData["art"] || false; \n\
65− asynchronous: root.asynchronous; \n\
66− visible: status == Loader.Ready; \n\
67− sourceComponent: Item { \n\
68− id: artShape; \n\
69− objectName: "artShape"; \n\
70− readonly property bool doShapeItem: components["art"]["conciergeMode"] !== true; \n\
71− visible: image.status == Image.Ready; \n\
72− readonly property alias image: artImage; \n\
73− ShaderEffectSource { \n\
74− id: artShapeSource; \n\
75− sourceItem: artImage; \n\
76− anchors.centerIn: parent; \n\
77− width: 1; \n\
78− height: 1; \n\
79− hideSource: doShapeItem; \n\
80− } \n\
81− Loader { \n\
82− anchors.fill: parent; \n\
83− visible: artShape.doShapeItem; \n\
84− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent; \n\
85− Component { \n\
86− id: artShapeShapeComponent; \n\
87− UbuntuShape { \n\
88− source: artShapeSource; \n\
89− sourceFillMode: UbuntuShape.PreserveAspectCrop; \n\
90− radius: "medium"; \n\
91− aspect: { \n\
92− switch (root.artShapeStyle) { \n\
93− case "inset": return UbuntuShape.Inset; \n\
94− case "shadow": return UbuntuShape.DropShadow; \n\
95− default: \n\
96− case "flat": return UbuntuShape.Flat; \n\
97− } \n\
98− } \n\
99− } \n\
100− } \n\
101− Component { \n\
102− id: artShapeIconComponent; \n\
103− ProportionalShape { source: artShapeSource; aspect: UbuntuShape.DropShadow; } \n\
104− } \n\
105− } \n\
106− readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1; \n\
107− readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1; \n\
108− Component.onCompleted: { updateWidthHeightBindings(); } \n\
109− Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); } \n\
110− function updateWidthHeightBindings() { \n\
111− if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) { \n\
112− width = root.fixedArtShapeSize.width; \n\
113− height = root.fixedArtShapeSize.height; \n\
114− } else { \n\
115− width = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.width }); \n\
116− height = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.height }); \n\
117− } \n\
118− } \n\
119− CroppedImageMinimumSourceSize { \n\
120− id: artImage; \n\
121− objectName: "artImage"; \n\
122− source: cardData && cardData["art"] || ""; \n\
123− asynchronous: root.asynchronous; \n\
124− width: %2; \n\
125− height: %3; \n\
126− } \n\
127− } \n\
128− } \n\
129− }\n';
130−
131−var kOverlayLoaderCode = 'Loader { \n\
132− id: overlayLoader; \n\
133− readonly property real overlayHeight: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
134− anchors.fill: artShapeHolder; \n\
135− active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false; \n\
136− asynchronous: root.asynchronous; \n\
137− visible: showHeader && status == Loader.Ready; \n\
138− sourceComponent: UbuntuShapeOverlay { \n\
139− id: overlay; \n\
140− property real luminance: Style.luminance(overlayColor); \n\
141− aspect: UbuntuShape.Flat; \n\
142− radius: "medium"; \n\
143− overlayColor: cardData && cardData["overlayColor"] || "#99000000"; \n\
144− overlayRect: Qt.rect(0, 1 - overlayLoader.overlayHeight / height, 1, 1); \n\
145− } \n\
146− }\n';
147−
148−// multiple row version of HeaderRowCode
149−function kHeaderRowCodeGenerator() {
150− var kHeaderRowCodeTemplate = 'Row { \n\
151− id: row; \n\
152− objectName: "outerRow"; \n\
153− property real margins: units.gu(1); \n\
154− spacing: margins; \n\
155− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight; \n\
156− anchors { %1 } \n\
157− anchors.right: parent.right; \n\
158− anchors.margins: margins; \n\
159− anchors.rightMargin: 0; \n\
160− data: [ \n\
161− %2 \n\
162− ] \n\
163− }\n';
164− var args = Array.prototype.slice.call(arguments);
165− var code = kHeaderRowCodeTemplate.arg(args.shift()).arg(args.join(',\n'));
166− return code;
167−}
168−
169−// multiple item version of kHeaderContainerCode
170−function kHeaderContainerCodeGenerator() {
171− var headerContainerCodeTemplate = 'Item { \n\
172− id: headerTitleContainer; \n\
173− anchors { %1 } \n\
174− width: parent.width - x; \n\
175− implicitHeight: %2; \n\
176− data: [ \n\
177− %3 \n\
178− ]\n\
179− }\n';
180− var args = Array.prototype.slice.call(arguments);
181− var code = headerContainerCodeTemplate.arg(args.shift()).arg(args.shift()).arg(args.join(',\n'));
182− return code;
183−}
184−
185−// %1 is used as anchors of mascotShapeLoader
186−var kMascotShapeLoaderCode = 'Loader { \n\
187− id: mascotShapeLoader; \n\
188− objectName: "mascotShapeLoader"; \n\
189− asynchronous: root.asynchronous; \n\
190− active: mascotImage.status === Image.Ready; \n\
191− visible: showHeader && active && status == Loader.Ready; \n\
192− width: units.gu(6); \n\
193− height: units.gu(5.625); \n\
194− sourceComponent: UbuntuShape { image: mascotImage } \n\
195− anchors { %1 } \n\
196− }\n';
197−
198−// %1 is used as anchors of mascotImage
199−// %2 is used as visible of mascotImage
200−var kMascotImageCode = 'CroppedImageMinimumSourceSize { \n\
201− id: mascotImage; \n\
202− objectName: "mascotImage"; \n\
203− anchors { %1 } \n\
204− source: cardData && cardData["mascot"] || ""; \n\
205− width: units.gu(6); \n\
206− height: units.gu(5.625); \n\
207− horizontalAlignment: Image.AlignHCenter; \n\
208− verticalAlignment: Image.AlignVCenter; \n\
209− visible: %2; \n\
210− }\n';
211−
212−// %1 is used as anchors of titleLabel
213−// %2 is used as color of titleLabel
214−// %3 is used as extra condition for visible of titleLabel
215−// %4 is used as title width
216−var kTitleLabelCode = 'Label { \n\
217− id: titleLabel; \n\
218− objectName: "titleLabel"; \n\
219− anchors { %1 } \n\
220− elide: Text.ElideRight; \n\
221− fontSize: "small"; \n\
222− wrapMode: Text.Wrap; \n\
223− maximumLineCount: 2; \n\
224− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale); \n\
225− color: %2; \n\
226− visible: showHeader %3; \n\
227− width: %4; \n\
228− text: root.title; \n\
229− font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal; \n\
230− horizontalAlignment: root.titleAlignment; \n\
231− }\n';
232−
233−// %1 is used as extra anchors of emblemIcon
234−// %2 is used as color of emblemIcon
235−// FIXME The width code is a
236−// Workaround for bug https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1421293
237−var kEmblemIconCode = 'Icon { \n\
238− id: emblemIcon; \n\
239− objectName: "emblemIcon"; \n\
240− anchors { \n\
241− bottom: titleLabel.baseline; \n\
242− right: parent.right; \n\
243− %1 \n\
244− } \n\
245− source: cardData && cardData["emblem"] || ""; \n\
246− color: %2; \n\
247− height: source != "" ? titleLabel.font.pixelSize : 0; \n\
248− width: implicitWidth > 0 && implicitHeight > 0 ? (implicitWidth / implicitHeight * height) : implicitWidth; \n\
249− }\n';
250−
251−// %1 is used as anchors of touchdown effect
252−var kTouchdownCode = 'UbuntuShape { \n\
253− id: touchdown; \n\
254− objectName: "touchdown"; \n\
255− anchors { %1 } \n\
256− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed; \n\
257− radius: "medium"; \n\
258− borderSource: "radius_pressed.sci" \n\
259− }\n';
260−
261−// %1 is used as anchors of subtitleLabel
262−// %2 is used as color of subtitleLabel
263−var kSubtitleLabelCode = 'Label { \n\
264− id: subtitleLabel; \n\
265− objectName: "subtitleLabel"; \n\
266− anchors { %1 } \n\
267− anchors.topMargin: units.dp(2); \n\
268− elide: Text.ElideRight; \n\
269− maximumLineCount: 1; \n\
270− fontSize: "x-small"; \n\
271− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale); \n\
272− color: %2; \n\
273− visible: titleLabel.visible && titleLabel.text; \n\
274− text: cardData && cardData["subtitle"] || ""; \n\
275− font.weight: Font.Light; \n\
276− }\n';
277−
278−// %1 is used as anchors of attributesRow
279−// %2 is used as color of attributesRow
280−var kAttributesRowCode = 'CardAttributes { \n\
281− id: attributesRow; \n\
282− objectName: "attributesRow"; \n\
283− anchors { %1 } \n\
284− color: %2; \n\
285− fontScale: root.fontScale; \n\
286− model: cardData && cardData["attributes"]; \n\
287− }\n';
288−
289−// %1 is used as top anchor of summary
290−// %2 is used as topMargin anchor of summary
291−// %3 is used as color of summary
292−var kSummaryLabelCode = 'Label { \n\
293− id: summary; \n\
294− objectName: "summaryLabel"; \n\
295− anchors { \n\
296− top: %1; \n\
297− left: parent.left; \n\
298− right: parent.right; \n\
299− margins: units.gu(1); \n\
300− topMargin: %2; \n\
301− } \n\
302− wrapMode: Text.Wrap; \n\
303− maximumLineCount: 5; \n\
304− elide: Text.ElideRight; \n\
305− text: cardData && cardData["summary"] || ""; \n\
306− height: text ? implicitHeight : 0; \n\
307− fontSize: "small"; \n\
308− color: %3; \n\
309− }\n';
310−
311−function cardString(template, components) {
312− var code;
313−
314− var templateInteractive = (template == null ? true : (template["non-interactive"] !== undefined ? !template["non-interactive"] : true)) ? "true" : "false";
315−
316− code = 'AbstractButton { \n\
317− id: root; \n\
318− property var components; \n\
319− property var cardData; \n\
320− property string artShapeStyle: "inset"; \n\
321− property real fontScale: 1.0; \n\
322− property var scopeStyle: null; \n\
323− property int titleAlignment: Text.AlignLeft; \n\
324− property int fixedHeaderHeight: -1; \n\
325− property size fixedArtShapeSize: Qt.size(-1, -1); \n\
326− readonly property string title: cardData && cardData["title"] || ""; \n\
327− property bool asynchronous: true; \n\
328− property bool showHeader: true; \n\
329− implicitWidth: childrenRect.width; \n\
330− enabled: %1; \n\
331− \n'.arg(templateInteractive);
332−
333− var hasArt = components["art"] && components["art"]["field"] || false;
334− var hasSummary = components["summary"] || false;
335− var artAndSummary = hasArt && hasSummary && components["art"]["conciergeMode"] !== true;
336− var isHorizontal = template["card-layout"] === "horizontal";
337− var hasBackground = (!isHorizontal && (template["card-background"] || components["background"] || artAndSummary)) ||
338− (hasSummary && (template["card-background"] || components["background"]));
339− var hasTitle = components["title"] || false;
340− var hasMascot = components["mascot"] || false;
341− var hasEmblem = components["emblem"] && !(hasMascot && template["card-size"] === "small") || false;
342− var headerAsOverlay = hasArt && template && template["overlay"] === true && (hasTitle || hasMascot);
343− var hasSubtitle = hasTitle && components["subtitle"] || false;
344− var hasHeaderRow = hasMascot && hasTitle;
345− var hasAttributes = hasTitle && components["attributes"]["field"] || false;
346−
347− if (hasBackground) {
348− var templateCardBackground = (template && typeof template["card-background"] === "string") ? template["card-background"] : "";
349− var backgroundElements0;
350− var backgroundElements1;
351− if (template && typeof template["card-background"] === "object" && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
352− if (template["card-background"]["elements"][0] !== undefined) {
353− backgroundElements0 = '"%1"'.arg(template["card-background"]["elements"][0]);
354− }
355− if (template["card-background"]["elements"][1] !== undefined) {
356− backgroundElements1 = '"%1"'.arg(template["card-background"]["elements"][1]);
357− }
358− }
359− code += kBackgroundLoaderCode.arg(templateCardBackground).arg(backgroundElements0).arg(backgroundElements1);
360− }
361−
362− if (hasArt) {
363− code += 'readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);\n';
364−
365− var widthCode, heightCode;
366− var artAnchors;
367− if (isHorizontal) {
368− artAnchors = 'left: parent.left';
369− if (hasMascot || hasTitle) {
370− widthCode = 'height * artShape.aspect'
371− heightCode = 'headerHeight + 2 * units.gu(1)';
372− } else {
373− // This side of the else is a bit silly, who wants an horizontal layout without mascot and title?
374− // So we define a "random" height of the image height + 2 gu for the margins
375− widthCode = 'height * artShape.aspect'
376− heightCode = 'units.gu(7.625)';
377− }
378− } else {
379− artAnchors = 'horizontalCenter: parent.horizontalCenter;';
380− widthCode = 'root.width'
381− heightCode = 'width / artShape.aspect';
382− }
383−
384− code += kArtShapeHolderCode.arg(artAnchors).arg(widthCode).arg(heightCode);
385− var fallback = components["art"] && components["art"]["fallback"] || "";
386− if (fallback !== "") {
387− code += 'Connections { target: artShapeLoader.item ? artShapeLoader.item.image : null; onStatusChanged: if (artShapeLoader.item.image.status === Image.Error) artShapeLoader.item.image.source = "%1"; } \n'.arg(fallback);
388− }
389− } else {
390− code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
391− }
392−
393− if (headerAsOverlay) {
394− code += kOverlayLoaderCode;
395− }
396−
397− var headerVerticalAnchors;
398− if (headerAsOverlay) {
399− headerVerticalAnchors = 'bottom: artShapeHolder.bottom; \n\
400− bottomMargin: units.gu(1);\n';
401− } else {
402− if (hasArt) {
403− if (isHorizontal) {
404− headerVerticalAnchors = 'top: artShapeHolder.top; \n\
405− topMargin: units.gu(1);\n';
406− } else {
407− headerVerticalAnchors = 'top: artShapeHolder.bottom; \n\
408− topMargin: units.gu(1);\n';
409− }
410− } else {
411− headerVerticalAnchors = 'top: parent.top; \n\
412− topMargin: units.gu(1);\n';
413− }
414− }
415− var headerLeftAnchor;
416− var headerLeftAnchorHasMargin = false;
417− if (isHorizontal && hasArt) {
418− headerLeftAnchor = 'left: artShapeHolder.right; \n\
419− leftMargin: units.gu(1);\n';
420− headerLeftAnchorHasMargin = true;
421− } else {
422− headerLeftAnchor = 'left: parent.left;\n';
423− }
424−
425− var touchdownOnArtShape = !hasBackground && hasArt && !hasMascot && !hasSummary;
426−
427− if (hasHeaderRow) {
428− code += 'readonly property int headerHeight: row.height;\n'
429− } else if (hasMascot) {
430− code += 'readonly property int headerHeight: mascotImage.height;\n'
431− } else if (hasAttributes) {
432− if (hasTitle && hasSubtitle) {
433− code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + attributesRow.height + attributesRow.anchors.topMargin;\n'
434− } else if (hasTitle) {
435− code += 'readonly property int headerHeight: titleLabel.height + attributesRow.height + attributesRow.anchors.topMargin;\n'
436− } else {
437− code += 'readonly property int headerHeight: attributesRow.height;\n'
438− }
439− } else if (hasSubtitle) {
440− code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;\n'
441− } else if (hasTitle) {
442− code += 'readonly property int headerHeight: titleLabel.height;\n'
443− } else {
444− code += 'readonly property int headerHeight: 0;\n'
445− }
446−
447− var mascotShapeCode = '';
448− var mascotCode = '';
449− if (hasMascot) {
450− var useMascotShape = !hasBackground && !headerAsOverlay;
451− var mascotAnchors = '';
452− if (!hasHeaderRow) {
453− mascotAnchors += headerLeftAnchor;
454− mascotAnchors += headerVerticalAnchors;
455− if (!headerLeftAnchorHasMargin) {
456− mascotAnchors += 'leftMargin: units.gu(1);\n'
457− }
458− } else {
459− mascotAnchors = 'verticalCenter: parent.verticalCenter;'
460− }
461−
462− if (useMascotShape) {
463− mascotShapeCode = kMascotShapeLoaderCode.arg(mascotAnchors);
464− }
465−
466− var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
467− mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible);
468− var fallback = components["mascot"] && components["mascot"]["fallback"] || "";
469− if (fallback !== "") {
470− code += 'Connections { target: mascotImage; onStatusChanged: if (mascotImage.status === Image.Error) mascotImage.source = "%1"; } \n'.arg(fallback);
471− }
472− }
473−
474− var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white")';
475−
476− var hasTitleContainer = hasTitle && (hasEmblem || (hasMascot && (hasSubtitle || hasAttributes)));
477− var titleSubtitleCode = '';
478− if (hasTitle) {
479− var titleColor;
480− if (headerAsOverlay) {
481− titleColor = 'root.scopeStyle && overlayLoader.item ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item && overlayLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white")';
482− } else if (hasSummary) {
483− titleColor = 'summary.color';
484− } else if (hasBackground) {
485− titleColor = summaryColorWithBackground;
486− } else {
487− titleColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
488− }
489−
490− var titleAnchors;
491− var subtitleAnchors;
492− var attributesAnchors;
493− var titleContainerAnchors;
494− var titleRightAnchor;
495− var titleWidth = "undefined";
496−
497− var extraRightAnchor = '';
498− var extraLeftAnchor = '';
499− if (!touchdownOnArtShape) {
500− extraRightAnchor = 'rightMargin: units.gu(1); \n';
501− extraLeftAnchor = 'leftMargin: units.gu(1); \n';
502− } else if (headerAsOverlay && !hasEmblem) {
503− extraRightAnchor = 'rightMargin: units.gu(1); \n';
504− }
505−
506− if (hasMascot) {
507− titleContainerAnchors = 'verticalCenter: parent.verticalCenter; ';
508− } else {
509− titleContainerAnchors = 'right: parent.right; ';
510− titleContainerAnchors += headerLeftAnchor;
511− titleContainerAnchors += headerVerticalAnchors;
512− if (!headerLeftAnchorHasMargin) {
513− titleContainerAnchors += extraLeftAnchor;
514− }
515− }
516− if (hasEmblem) {
517− titleRightAnchor = 'right: emblemIcon.left; \n\
518− rightMargin: emblemIcon.width > 0 ? units.gu(0.5) : 0; \n';
519− } else {
520− titleRightAnchor = 'right: parent.right; \n'
521− titleRightAnchor += extraRightAnchor;
522− }
523−
524− if (hasTitleContainer) {
525− // Using headerTitleContainer
526− titleAnchors = titleRightAnchor;
527− titleAnchors += 'left: parent.left; \n\
528− top: parent.top;';
529− subtitleAnchors = 'right: parent.right; \n\
530− left: parent.left; \n';
531− subtitleAnchors += extraRightAnchor;
532− if (hasSubtitle) {
533− attributesAnchors = subtitleAnchors + 'top: subtitleLabel.bottom;\n';
534− subtitleAnchors += 'top: titleLabel.bottom;\n';
535− } else {
536− attributesAnchors = subtitleAnchors + 'top: titleLabel.bottom;\n';
537− }
538− } else if (hasMascot) {
539− // Using row without titleContainer
540− titleAnchors = 'verticalCenter: parent.verticalCenter;\n';
541− titleWidth = "parent.width - x";
542− } else {
543− if (headerAsOverlay) {
544− // Using anchors to the overlay
545− titleAnchors = titleRightAnchor;
546− titleAnchors += 'left: parent.left; \n\
547− leftMargin: units.gu(1); \n\
548− top: overlayLoader.top; \n\
549− topMargin: units.gu(1) + overlayLoader.height - overlayLoader.overlayHeight; \n';
550− } else {
551− // Using anchors to the mascot/parent
552− titleAnchors = titleRightAnchor;
553− titleAnchors += headerLeftAnchor;
554− titleAnchors += headerVerticalAnchors;
555− if (!headerLeftAnchorHasMargin) {
556− titleAnchors += extraLeftAnchor;
557− }
558− }
559− subtitleAnchors = 'left: titleLabel.left; \n\
560− leftMargin: titleLabel.leftMargin; \n';
561− subtitleAnchors += extraRightAnchor;
562− if (hasEmblem) {
563− // using container
564− subtitleAnchors += 'right: parent.right; \n';
565− } else {
566− subtitleAnchors += 'right: titleLabel.right; \n';
567− }
568−
569− if (hasSubtitle) {
570− attributesAnchors = subtitleAnchors + 'top: subtitleLabel.bottom;\n';
571− subtitleAnchors += 'top: titleLabel.bottom;\n';
572− } else {
573− attributesAnchors = subtitleAnchors + 'top: titleLabel.bottom;\n';
574− }
575− }
576−
577− // code for different elements
578− var titleLabelVisibleExtra = (headerAsOverlay ? '&& overlayLoader.active': '');
579− var titleCode = kTitleLabelCode.arg(titleAnchors).arg(titleColor).arg(titleLabelVisibleExtra).arg(titleWidth);
580− var subtitleCode;
581− var attributesCode;
582−
583− // code for the title container
584− var containerCode = [];
585− var containerHeight = 'titleLabel.height';
586− containerCode.push(titleCode);
587− if (hasSubtitle) {
588− subtitleCode = kSubtitleLabelCode.arg(subtitleAnchors).arg(titleColor);
589− containerCode.push(subtitleCode);
590− containerHeight += ' + subtitleLabel.height';
591− }
592− if (hasEmblem) {
593− containerCode.push(kEmblemIconCode.arg(extraRightAnchor).arg(titleColor));
594− }
595− if (hasAttributes) {
596− attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(titleColor);
597− containerCode.push(attributesCode);
598− containerHeight += ' + attributesRow.height';
599− }
600−
601− if (hasTitleContainer) {
602− // use container
603− titleSubtitleCode = kHeaderContainerCodeGenerator(titleContainerAnchors, containerHeight, containerCode);
604− } else {
605− // no container
606− titleSubtitleCode = titleCode;
607− if (hasSubtitle) {
608− titleSubtitleCode += subtitleCode;
609− }
610− if (hasAttributes) {
611− titleSubtitleCode += attributesCode;
612− }
613− }
614− }
615−
616− if (hasHeaderRow) {
617− var rowCode = [mascotCode, titleSubtitleCode];
618− if (mascotShapeCode != '') {
619− rowCode.unshift(mascotShapeCode);
620− }
621− code += kHeaderRowCodeGenerator(headerVerticalAnchors + headerLeftAnchor, rowCode)
622− } else {
623− code += mascotShapeCode + mascotCode + titleSubtitleCode;
624− }
625−
626− if (hasSummary) {
627− var summaryTopAnchor;
628− if (isHorizontal && hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
629− else if (headerAsOverlay && hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
630− else if (hasHeaderRow) summaryTopAnchor = 'row.bottom';
631− else if (hasTitleContainer) summaryTopAnchor = 'headerTitleContainer.bottom';
632− else if (hasMascot) summaryTopAnchor = 'mascotImage.bottom';
633− else if (hasAttributes) summaryTopAnchor = 'attributesRow.bottom';
634− else if (hasSubtitle) summaryTopAnchor = 'subtitleLabel.bottom';
635− else if (hasTitle) summaryTopAnchor = 'titleLabel.bottom';
636− else if (hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
637− else summaryTopAnchor = 'parent.top';
638−
639− var summaryColor;
640− if (hasBackground) {
641− summaryColor = summaryColorWithBackground;
642− } else {
643− summaryColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
644− }
645−
646− var summaryTopMargin = (hasMascot || hasSubtitle || hasAttributes ? 'anchors.margins' : '0');
647−
648− code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(summaryColor);
649− }
650−
651− var touchdownAnchors;
652− if (hasBackground) {
653− touchdownAnchors = 'fill: backgroundLoader';
654− } else if (touchdownOnArtShape) {
655− touchdownAnchors = 'fill: artShapeHolder';
656− } else {
657− touchdownAnchors = 'fill: root'
658− }
659− code += kTouchdownCode.arg(touchdownAnchors);
660−
661− var implicitHeight = 'implicitHeight: ';
662− if (hasSummary) {
663− implicitHeight += 'summary.y + summary.height + units.gu(1);\n';
664− } else if (headerAsOverlay) {
665− implicitHeight += 'artShapeHolder.height;\n';
666− } else if (hasHeaderRow) {
667− implicitHeight += 'row.y + row.height + units.gu(1);\n';
668− } else if (hasMascot) {
669− implicitHeight += 'mascotImage.y + mascotImage.height;\n';
670− } else if (hasTitleContainer) {
671− implicitHeight += 'headerTitleContainer.y + headerTitleContainer.height + units.gu(1);\n';
672− } else if (hasAttributes) {
673− implicitHeight += 'attributesRow.y + attributesRow.height + units.gu(1);\n';
674− } else if (hasSubtitle) {
675− implicitHeight += 'subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
676− } else if (hasTitle) {
677− implicitHeight += 'titleLabel.y + titleLabel.height + units.gu(1);\n';
678− } else if (hasArt) {
679− implicitHeight += 'artShapeHolder.height;\n';
680− } else {
681− implicitHeight = '';
682− }
683−
684− // Close the AbstractButton
685− code += implicitHeight + '}\n';
686−
687− return code;
688−}
689−
690−function createCardComponent(parent, template, components) {
691− var imports = 'import QtQuick 2.4; \n\
692− import Ubuntu.Components 1.3; \n\
693− import Ubuntu.Settings.Components 0.1; \n\
694− import Dash 0.1;\n\
695− import Utils 0.1;\n';
696− var card = cardString(template, components);
697− var code = imports + 'Component {\n' + card + '}\n';
698−
699− try {
700− return Qt.createQmlObject(code, parent, "createCardComponent");
701− } catch (e) {
702− console.error("ERROR: Invalid component created.");
703− console.error("Template:");
704− console.error(JSON.stringify(template));
705− console.error("Components:");
706− console.error(JSON.stringify(components));
707− console.error("Code:");
708− console.error(code);
709− throw e;
710− }
711−}
plugins/Dash/CardCreatorCache.qmldeleted−40
@@ -1,40 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−pragma Singleton
18−import QtQuick 2.4
19−import "CardCreator.js" as CardCreator
20−
21−QtObject {
22− id: root
23−
24− property var cache: new Object();
25−
26− function getCardComponent(template, components) {
27− if (template === undefined || components === undefined)
28− return undefined;
29−
30− var tString = JSON.stringify(template);
31− var cString = JSON.stringify(components);
32− var allString = tString + cString;
33− var component = cache[allString];
34− if (component === undefined) {
35− component = CardCreator.createCardComponent(root, template, components);
36− cache[allString] = component;
37− }
38− return component;
39− }
40−}
plugins/Dash/CroppedImageMinimumSourceSize.qmldeleted−38
@@ -1,38 +0,0 @@
1−/*
2− * Copyright (C) 2014, 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−
19−Image {
20− id: root
21−
22− fillMode: Image.PreserveAspectCrop
23−
24− property bool useHeight: false
25− function updateUseHeight()
26− {
27− // Do not turn into a binding since otherwise the qml
28− // engine complains about binding loops
29− useHeight = (implicitWidth / implicitHeight) > (width / height);
30− }
31−
32− onHeightChanged: updateUseHeight();
33− onWidthChanged: updateUseHeight();
34− onImplicitHeightChanged: updateUseHeight();
35− onImplicitWidthChanged: updateUseHeight();
36−
37− sourceSize: useHeight ? Qt.size(0, height) : Qt.size(width, 0)
38−}
plugins/Dash/Dash.qmltypesdeleted−100
@@ -1,100 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable Dash 0.1 plugins'
8−
9−Module {
10− Component {
11− name: "AbstractDashView"
12− defaultProperty: "data"
13− prototype: "QQuickItem"
14− Property { name: "model"; type: "QAbstractItemModel"; isPointer: true }
15− Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
16− Property { name: "columnSpacing"; type: "double" }
17− Property { name: "rowSpacing"; type: "double" }
18− Property { name: "cacheBuffer"; type: "int" }
19− Property { name: "displayMarginBeginning"; type: "double" }
20− Property { name: "displayMarginEnd"; type: "double" }
21− }
22− Component {
23− name: "HorizontalJournal"
24− defaultProperty: "data"
25− prototype: "AbstractDashView"
26− exports: ["Dash/HorizontalJournal 0.1"]
27− exportMetaObjectRevisions: [0]
28− Property { name: "rowHeight"; type: "double" }
29− }
30− Component {
31− name: "ListViewWithPageHeader"
32− defaultProperty: "flickableData"
33− prototype: "QQuickFlickable"
34− exports: ["Dash/ListViewWithPageHeader 0.1"]
35− exportMetaObjectRevisions: [0]
36− Property { name: "model"; type: "QAbstractItemModel"; isPointer: true }
37− Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
38− Property { name: "pageHeader"; type: "QQuickItem"; isPointer: true }
39− Property { name: "sectionDelegate"; type: "QQmlComponent"; isPointer: true }
40− Property { name: "sectionProperty"; type: "string" }
41− Property { name: "forceNoClip"; type: "bool" }
42− Property { name: "stickyHeaderHeight"; type: "int"; isReadonly: true }
43− Property { name: "headerItemShownHeight"; type: "double"; isReadonly: true }
44− Property { name: "cacheBuffer"; type: "int" }
45− Signal { name: "headerChanged" }
46− Method { name: "positionAtBeginning" }
47− Method { name: "showHeader" }
48− Method { name: "firstCreatedIndex"; type: "int" }
49− Method { name: "createdItemCount"; type: "int" }
50− Method {
51− name: "item"
52− type: "QQuickItem*"
53− Parameter { name: "modelIndex"; type: "int" }
54− }
55− Method {
56− name: "maximizeVisibleArea"
57− type: "bool"
58− Parameter { name: "modelIndex"; type: "int" }
59− }
60− Method {
61− name: "maximizeVisibleArea"
62− type: "bool"
63− Parameter { name: "modelIndex"; type: "int" }
64− Parameter { name: "itemHeight"; type: "int" }
65− }
66− }
67− Component {
68− name: "OrganicGrid"
69− defaultProperty: "data"
70− prototype: "AbstractDashView"
71− exports: ["Dash/OrganicGrid 0.1"]
72− exportMetaObjectRevisions: [0]
73− Property { name: "smallDelegateSize"; type: "QSizeF" }
74− Property { name: "bigDelegateSize"; type: "QSizeF" }
75− }
76− Component {
77− name: "VerticalJournal"
78− defaultProperty: "data"
79− prototype: "AbstractDashView"
80− exports: ["Dash/VerticalJournal 0.1"]
81− exportMetaObjectRevisions: [0]
82− Property { name: "columnWidth"; type: "double" }
83− }
84− Component {
85− prototype: "QObject"
86− name: "CardCreatorCache"
87− exports: ["CardCreatorCache -1.-1"]
88− exportMetaObjectRevisions: [-1]
89− isComposite: true
90− isCreatable: false
91− isSingleton: true
92− Property { name: "cache"; type: "QVariant" }
93− Method {
94− name: "getCardComponent"
95− type: "QVariant"
96− Parameter { name: "template"; type: "QVariant" }
97− Parameter { name: "components"; type: "QVariant" }
98− }
99− }
100−}
plugins/Dash/ScopeStyle.qmldeleted−95
@@ -1,95 +0,0 @@
1−/*
2− * Copyright 2014 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Utils 0.1
19−import Ubuntu.Components 1.3
20−
21−/*! \brief Helper for processing scope customization options.
22−
23− It will take the customizations object passed by the scope and
24− process it to provide the scope UI with data such as colors or
25− image paths.
26− */
27−
28−QtObject {
29− /// Style object passed from the scope
30− property var style: Object()
31−
32− /// Color used for text and symbolic icons
33− readonly property color foreground: "foreground-color" in style ? style["foreground-color"] : d.defaultDark
34−
35− /// Luminance of the foreground color
36− readonly property real foregroundLuminance: foreground ? Style.luminance(foreground) : Style.luminance(d.defaultDark)
37−
38− /// Color used for the overall background
39− readonly property color background: "background-color" in style ? style["background-color"] : "#00f5f5f5"
40−
41− /// Luminance of the background color
42− readonly property real backgroundLuminance: background ? Style.luminance(background) : Style.luminance(d.defaultLight)
43−
44− /*! \brief Get the most contrasting available color based on luminance
45− *
46− * If background color is transparent, theme provided colors are taken into account
47− */
48− function getTextColor(luminance) {
49− if (Math.abs(foregroundLuminance - luminance) >
50− Math.abs(d.opaqueBackgroundLuminance - luminance)) {
51− return foreground;
52− } else {
53− return d.opaqueBackground;
54− }
55− }
56−
57− /// Source of the logo image for the header
58− readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
59−
60− /// Background style for the header
61− readonly property url headerBackground: "background" in d.headerStyle ? d.headerStyle["background"] : "color:///#f5f5f5"
62−
63− /// Foreground color for the header
64− readonly property color headerForeground: "foreground-color" in d.headerStyle ? d.headerStyle["foreground-color"] : foreground
65−
66− /// Color of the header divider
67− readonly property color headerDividerColor: "divider-color" in d.headerStyle ? d.headerStyle["divider-color"] : "#e0e0e0"
68−
69− /// Background style for the navigation
70− readonly property url navigationBackground: "navigation-background" in d.headerStyle ? d.headerStyle["navigation-background"] : "color:///#f5f5f5"
71−
72− /// Color of the primary preview button
73− readonly property color previewButtonColor: "preview-button-color" in style ? style["preview-button-color"] : UbuntuColors.orange
74−
75− //! @cond
76− property var d: QtObject {
77− // FIXME: should be taken from the theme
78− readonly property color defaultLight: "white"
79− readonly property color defaultDark: UbuntuColors.darkGrey
80− readonly property real defaultLightLuminance: Style.luminance(defaultLight)
81− readonly property real defaultDarkLuminance: Style.luminance(defaultDark)
82−
83− readonly property color opaqueBackground: {
84− background.a > 0 ?
85− background :
86− (Math.abs(foregroundLuminance - defaultLightLuminance) >
87− Math.abs(foregroundLuminance - defaultDarkLuminance)) ?
88− defaultLight : defaultDark
89− }
90− readonly property real opaqueBackgroundLuminance: Style.luminance(opaqueBackground)
91−
92− readonly property var headerStyle: "page-header" in style ? style["page-header"] : { }
93− }
94− //! @endcond
95−}
plugins/Dash/abstractdashview.cppdeleted−346
@@ -1,346 +0,0 @@
1−/*
2− * Copyright (C) 2013, 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "abstractdashview.h"
18−
19−AbstractDashView::AbstractDashView()
20− : m_delegateModel(nullptr)
21− , m_asyncRequestedIndex(-1)
22− , m_columnSpacing(0)
23− , m_rowSpacing(0)
24− , m_buffer(320) // Same value used in qquickitemview.cpp in Qt 5.4
25− , m_displayMarginBeginning(0)
26− , m_displayMarginEnd(0)
27− , m_needsRelayout(false)
28− , m_delegateValidated(false)
29− , m_implicitHeightDirty(false)
30−{
31− connect(this, &AbstractDashView::widthChanged, this, &AbstractDashView::relayout);
32− connect(this, &AbstractDashView::heightChanged, this, &AbstractDashView::onHeightChanged);
33−}
34−
35−QAbstractItemModel *AbstractDashView::model() const
36−{
37− return m_delegateModel ? m_delegateModel->model().value<QAbstractItemModel *>() : nullptr;
38−}
39−
40−void AbstractDashView::setModel(QAbstractItemModel *model)
41−{
42− if (model != this->model()) {
43− if (!m_delegateModel) {
44− createDelegateModel();
45− } else {
46− disconnect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &AbstractDashView::onModelUpdated);
47− }
48− m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
49− connect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &AbstractDashView::onModelUpdated);
50−
51− cleanupExistingItems();
52−
53− Q_EMIT modelChanged();
54− polish();
55− }
56−}
57−
58−QQmlComponent *AbstractDashView::delegate() const
59−{
60− return m_delegateModel ? m_delegateModel->delegate() : nullptr;
61−}
62−
63−void AbstractDashView::setDelegate(QQmlComponent *delegate)
64−{
65− if (delegate != this->delegate()) {
66− if (!m_delegateModel) {
67− createDelegateModel();
68− }
69−
70− cleanupExistingItems();
71−
72− m_delegateModel->setDelegate(delegate);
73−
74− Q_EMIT delegateChanged();
75− m_delegateValidated = false;
76− polish();
77− }
78−}
79−
80−qreal AbstractDashView::columnSpacing() const
81−{
82− return m_columnSpacing;
83−}
84−
85−void AbstractDashView::setColumnSpacing(qreal columnSpacing)
86−{
87− if (columnSpacing != m_columnSpacing) {
88− m_columnSpacing = columnSpacing;
89− Q_EMIT columnSpacingChanged();
90−
91− if (isComponentComplete()) {
92− relayout();
93− }
94− }
95−}
96−
97−qreal AbstractDashView::rowSpacing() const
98−{
99− return m_rowSpacing;
100−}
101−
102−void AbstractDashView::setRowSpacing(qreal rowSpacing)
103−{
104− if (rowSpacing != m_rowSpacing) {
105− m_rowSpacing = rowSpacing;
106− Q_EMIT rowSpacingChanged();
107−
108− if (isComponentComplete()) {
109− relayout();
110− }
111− }
112−}
113−
114−int AbstractDashView::cacheBuffer() const
115−{
116− return m_buffer;
117−}
118−
119−void AbstractDashView::setCacheBuffer(int buffer)
120−{
121− if (buffer < 0) {
122− qmlInfo(this) << "Cannot set a negative cache buffer";
123− return;
124− }
125−
126− if (m_buffer != buffer) {
127− m_buffer = buffer;
128− if (isComponentComplete()) {
129− polish();
130− }
131− emit cacheBufferChanged();
132− }
133−}
134−
135−qreal AbstractDashView::displayMarginBeginning() const
136−{
137− return m_displayMarginBeginning;
138−}
139−
140−void AbstractDashView::setDisplayMarginBeginning(qreal begin)
141−{
142− if (m_displayMarginBeginning == begin)
143− return;
144− m_displayMarginBeginning = begin;
145− if (isComponentComplete()) {
146− polish();
147− }
148− emit displayMarginBeginningChanged();
149−}
150−
151−qreal AbstractDashView::displayMarginEnd() const
152−{
153− return m_displayMarginEnd;
154−}
155−
156−void AbstractDashView::setDisplayMarginEnd(qreal end)
157−{
158− if (m_displayMarginEnd == end)
159− return;
160− m_displayMarginEnd = end;
161− if (isComponentComplete()) {
162− polish();
163− }
164− emit displayMarginEndChanged();
165−}
166−
167−void AbstractDashView::createDelegateModel()
168−{
169− m_delegateModel = new QQmlDelegateModel(qmlContext(this), this);
170− connect(m_delegateModel, &QQmlDelegateModel::createdItem, this, &AbstractDashView::itemCreated);
171− if (isComponentComplete())
172− m_delegateModel->componentComplete();
173−}
174−
175−void AbstractDashView::refill()
176−{
177− if (!isComponentComplete() || height() < 0) {
178− return;
179− }
180−
181− const qreal from = -m_displayMarginBeginning;
182− const qreal to = height() + m_displayMarginEnd;
183− const qreal bufferFrom = from - m_buffer;
184− const qreal bufferTo = to + m_buffer;
185−
186− bool added = addVisibleItems(from, to, false);
187− bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
188− added |= addVisibleItems(bufferFrom, bufferTo, true);
189−
190− if (added || removed) {
191− m_implicitHeightDirty = true;
192− polish();
193− }
194−}
195−
196−bool AbstractDashView::addVisibleItems(qreal fillFromY, qreal fillToY, bool asynchronous)
197−{
198− if (fillToY <= fillFromY)
199− return false;
200−
201− if (!delegate())
202− return false;
203−
204− if (m_delegateModel->count() == 0)
205− return false;
206−
207− int modelIndex;
208− qreal yPos;
209− findBottomModelIndexToAdd(&modelIndex, &yPos);
210− bool changed = false;
211− while (modelIndex < m_delegateModel->count() && yPos <= fillToY) {
212− if (!createItem(modelIndex, asynchronous))
213− break;
214−
215− changed = true;
216− findBottomModelIndexToAdd(&modelIndex, &yPos);
217− }
218−
219− findTopModelIndexToAdd(&modelIndex, &yPos);
220− while (modelIndex >= 0 && yPos > fillFromY) {
221− if (!createItem(modelIndex, asynchronous))
222− break;
223−
224− changed = true;
225− findTopModelIndexToAdd(&modelIndex, &yPos);
226− }
227−
228− return changed;
229−}
230−
231−QQuickItem *AbstractDashView::createItem(int modelIndex, bool asynchronous)
232−{
233− if (asynchronous && m_asyncRequestedIndex != -1)
234− return nullptr;
235−
236− m_asyncRequestedIndex = -1;
237− QObject* object = m_delegateModel->object(modelIndex, asynchronous);
238− QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
239− if (!item) {
240− if (object) {
241− m_delegateModel->release(object);
242− if (!m_delegateValidated) {
243− m_delegateValidated = true;
244− QObject* delegateObj = delegate();
245− qmlInfo(delegateObj ? delegateObj : this) << "Delegate must be of Item type";
246− }
247− } else {
248− m_asyncRequestedIndex = modelIndex;
249− }
250− return nullptr;
251− } else {
252− addItemToView(modelIndex, item);
253− return item;
254− }
255−}
256−
257−void AbstractDashView::releaseItem(QQuickItem *item)
258−{
259− QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item);
260− if (flags & QQmlDelegateModel::Destroyed) {
261− item->setParentItem(nullptr);
262− }
263−}
264−
265−void AbstractDashView::setImplicitHeightDirty()
266−{
267− m_implicitHeightDirty = true;
268−}
269−
270−void AbstractDashView::itemCreated(int modelIndex, QObject *object)
271−{
272− QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
273− if (!item) {
274− qWarning() << "AbstractDashView::itemCreated got a non item for index" << modelIndex;
275− return;
276− }
277− item->setParentItem(this);
278−
279− // We only need to call createItem if we are here because of an asynchronous generation
280− // otherwise we are in this slot because createItem is creating the item sync
281− // and thus we don't need to call createItem again, nor need to set m_implicitHeightDirty
282− // and call polish because the sync createItem was called from addVisibleItems that
283− // is called from refill that will already do those if an item was added
284− if (modelIndex == m_asyncRequestedIndex) {
285− createItem(modelIndex, false);
286− m_implicitHeightDirty = true;
287− polish();
288− }
289−}
290−
291−void AbstractDashView::onModelUpdated(const QQmlChangeSet &changeSet, bool reset)
292−{
293− if (reset) {
294− cleanupExistingItems();
295− } else {
296− processModelRemoves(changeSet.removes());
297− }
298− polish();
299−}
300−
301−
302−void AbstractDashView::relayout()
303−{
304− m_needsRelayout = true;
305− polish();
306−}
307−
308−void AbstractDashView::onHeightChanged()
309−{
310− polish();
311−}
312−
313−void AbstractDashView::updatePolish()
314−{
315− if (!model())
316− return;
317−
318− if (m_needsRelayout) {
319− doRelayout();
320− m_needsRelayout = false;
321− m_implicitHeightDirty = true;
322− }
323−
324− refill();
325−
326− const qreal from = -m_displayMarginBeginning;
327− const qreal to = height() + m_displayMarginEnd;
328− updateItemCulling(from, to);
329−
330− if (m_implicitHeightDirty) {
331− calculateImplicitHeight();
332− m_implicitHeightDirty = false;
333− }
334−}
335−
336−void AbstractDashView::componentComplete()
337−{
338− if (m_delegateModel)
339− m_delegateModel->componentComplete();
340−
341− QQuickItem::componentComplete();
342−
343− m_needsRelayout = true;
344−
345− polish();
346−}
plugins/Dash/abstractdashview.hdeleted−129
@@ -1,129 +0,0 @@
1−/*
2− * Copyright (C) 2013, 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef ABSTRACTDASHVIEW_H
18−#define ABSTRACTDASHVIEW_H
19−
20−#include <QQuickItem>
21−
22−class QAbstractItemModel;
23−class QQmlComponent;
24−#pragma GCC diagnostic push
25−#pragma GCC diagnostic ignored "-pedantic"
26−#include <private/qqmldelegatemodel_p.h>
27−#include <qqmlinfo.h>
28−#pragma GCC diagnostic pop
29−
30−class AbstractDashView : public QQuickItem
31−{
32− Q_OBJECT
33−
34− Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
35− Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
36− Q_PROPERTY(qreal columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
37− Q_PROPERTY(qreal rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged)
38− Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
39− Q_PROPERTY(qreal displayMarginBeginning READ displayMarginBeginning
40− WRITE setDisplayMarginBeginning
41− NOTIFY displayMarginBeginningChanged)
42− Q_PROPERTY(qreal displayMarginEnd READ displayMarginEnd
43− WRITE setDisplayMarginEnd
44− NOTIFY displayMarginEndChanged)
45−
46−friend class VerticalJournalTest;
47−friend class HorizontalJournalTest;
48−friend class OrganicGridTest;
49−
50−public:
51− AbstractDashView();
52−
53− QAbstractItemModel *model() const;
54− void setModel(QAbstractItemModel *model);
55−
56− QQmlComponent *delegate() const;
57− void setDelegate(QQmlComponent *delegate);
58−
59− qreal columnSpacing() const;
60− void setColumnSpacing(qreal columnSpacing);
61−
62− qreal rowSpacing() const;
63− void setRowSpacing(qreal rowSpacing);
64−
65− int cacheBuffer() const;
66− void setCacheBuffer(int);
67−
68− qreal displayMarginBeginning() const;
69− void setDisplayMarginBeginning(qreal);
70−
71− qreal displayMarginEnd() const;
72− void setDisplayMarginEnd(qreal);
73−
74−Q_SIGNALS:
75− void modelChanged();
76− void delegateChanged();
77− void columnSpacingChanged();
78− void rowSpacingChanged();
79− void cacheBufferChanged();
80− void displayMarginBeginningChanged();
81− void displayMarginEndChanged();
82−
83−protected Q_SLOTS:
84− void relayout();
85−
86−protected:
87− void updatePolish() override;
88− void componentComplete() override;
89−
90− void releaseItem(QQuickItem *item);
91− void setImplicitHeightDirty();
92−
93−private Q_SLOTS:
94− void itemCreated(int modelIndex, QObject *object);
95− void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
96− void onHeightChanged();
97−
98−private:
99− void createDelegateModel();
100− void refill();
101− bool addVisibleItems(qreal fillFromY, qreal fillToY, bool asynchronous);
102− QQuickItem *createItem(int modelIndex, bool asynchronous);
103−
104− virtual void findBottomModelIndexToAdd(int *modelIndex, qreal *yPos) = 0;
105− virtual void findTopModelIndexToAdd(int *modelIndex, qreal *yPos) = 0;
106− virtual void addItemToView(int modelIndex, QQuickItem *item) = 0;
107− virtual bool removeNonVisibleItems(qreal bufferFromY, qreal bufferToY) = 0;
108− virtual void cleanupExistingItems() = 0;
109− virtual void doRelayout() = 0;
110− virtual void updateItemCulling(qreal visibleFromY, qreal visibleToY) = 0;
111− virtual void calculateImplicitHeight() = 0;
112− virtual void processModelRemoves(const QVector<QQmlChangeSet::Change> &removes) = 0;
113−
114− QQmlDelegateModel *m_delegateModel;
115−
116− // Index we are waiting because we requested it asynchronously
117− int m_asyncRequestedIndex;
118−
119− int m_columnSpacing;
120− int m_rowSpacing;
121− int m_buffer;
122− qreal m_displayMarginBeginning;
123− qreal m_displayMarginEnd;
124− bool m_needsRelayout;
125− bool m_delegateValidated;
126− bool m_implicitHeightDirty;
127−};
128−
129−#endif
plugins/Dash/horizontaljournal.cppdeleted−242
@@ -1,242 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−/*
18− * The implementation is centered around m_visibleItems
19− * that a list for each of the items in the view.
20− * m_firstVisibleIndex is the index of the first item in m_visibleItems
21− * m_lastInRowIndexPosition is a map that contains the x position
22− * of items that are the last ones of a row so we can reconstruct the rows
23− * when building back
24− */
25−
26−#include "horizontaljournal.h"
27−
28−#include <qqmlengine.h>
29−#pragma GCC diagnostic push
30−#pragma GCC diagnostic ignored "-pedantic"
31−#include <private/qqmldelegatemodel_p.h>
32−#include <qqmlinfo.h>
33−#include <private/qquickitem_p.h>
34−#pragma GCC diagnostic pop
35−
36−HorizontalJournal::HorizontalJournal()
37− : m_firstVisibleIndex(-1)
38− , m_rowHeight(0)
39−{
40−}
41−
42−qreal HorizontalJournal::rowHeight() const
43−{
44− return m_rowHeight;
45−}
46−
47−void HorizontalJournal::setRowHeight(qreal rowHeight)
48−{
49− if (rowHeight != m_rowHeight) {
50− m_rowHeight = rowHeight;
51− Q_EMIT rowHeightChanged();
52−
53− if (isComponentComplete()) {
54− Q_FOREACH(QQuickItem *item, m_visibleItems) {
55− item->setHeight(rowHeight);
56− }
57− relayout();
58− }
59− }
60−}
61−
62−void HorizontalJournal::findBottomModelIndexToAdd(int *modelIndex, qreal *yPos)
63−{
64− if (m_visibleItems.isEmpty()) {
65− *modelIndex = 0;
66− *yPos = 0;
67− } else {
68− *modelIndex = m_firstVisibleIndex + m_visibleItems.count();
69− if (m_lastInRowIndexPosition.contains(*modelIndex - 1)) {
70− *yPos = m_visibleItems.last()->y() + m_rowHeight + rowSpacing();
71− } else {
72− *yPos = m_visibleItems.last()->y();
73− }
74− }
75−}
76−
77−void HorizontalJournal::findTopModelIndexToAdd(int *modelIndex, qreal *yPos)
78−{
79− if (m_visibleItems.isEmpty()) {
80− *modelIndex = -1;
81− *yPos = INT_MIN;
82− } else {
83− *modelIndex = m_firstVisibleIndex - 1;
84− if (m_lastInRowIndexPosition.contains(*modelIndex)) {
85− *yPos = m_visibleItems.first()->y() - rowSpacing() - m_rowHeight;
86− } else {
87− *yPos = m_visibleItems.first()->y();
88− }
89− }
90−}
91−
92−bool HorizontalJournal::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
93−{
94− bool changed = false;
95−
96− while (!m_visibleItems.isEmpty() && m_visibleItems.first()->y() + m_rowHeight < bufferFromY) {
97− releaseItem(m_visibleItems.takeFirst());
98− changed = true;
99− m_firstVisibleIndex++;
100− }
101−
102− while (!m_visibleItems.isEmpty() && m_visibleItems.last()->y() > bufferToY) {
103− releaseItem(m_visibleItems.takeLast());
104− changed = true;
105− m_lastInRowIndexPosition.remove(m_firstVisibleIndex + m_visibleItems.count());
106− }
107−
108− if (m_visibleItems.isEmpty()) {
109− m_firstVisibleIndex = -1;
110− }
111−
112− return changed;
113−}
114−
115−void HorizontalJournal::addItemToView(int modelIndex, QQuickItem *item)
116−{
117− if (item->height() != m_rowHeight) {
118− qWarning() << "Item" << modelIndex << "height is not the one that the rowHeight mandates, resetting it";
119− item->setHeight(m_rowHeight);
120− }
121−
122− if (m_visibleItems.isEmpty()) {
123− Q_ASSERT(modelIndex == 0);
124− item->setY(0);
125− item->setX(0);
126− m_visibleItems << item;
127− m_firstVisibleIndex = 0;
128− } else {
129− // modelIndex has to be either m_firstVisibleIndex - 1 or m_firstVisibleIndex + m_visibleItems.count()
130− if (modelIndex == m_firstVisibleIndex + m_visibleItems.count()) {
131− QQuickItem *lastItem = m_visibleItems.last();
132− if (lastItem->x() + lastItem->width() + columnSpacing() + item->width() <= width()) {
133− // Fits in the row
134− item->setY(lastItem->y());
135− item->setX(lastItem->x() + lastItem->width() + columnSpacing());
136− } else {
137− // Starts a new row
138− item->setY(lastItem->y() + m_rowHeight + rowSpacing());
139− item->setX(0);
140− m_lastInRowIndexPosition[modelIndex - 1] = lastItem->x();
141− }
142− m_visibleItems << item;
143− } else if (modelIndex == m_firstVisibleIndex - 1) {
144− QQuickItem *firstItem = m_visibleItems.first();
145− if (m_lastInRowIndexPosition.contains(modelIndex)) {
146− // It is the last item of its row, so start a new one since we're going back
147− item->setY(firstItem->y() - rowSpacing() - m_rowHeight);
148− item->setX(m_lastInRowIndexPosition[modelIndex]);
149− } else {
150− item->setY(firstItem->y());
151− item->setX(firstItem->x() - columnSpacing() - item->width());
152− }
153− m_firstVisibleIndex = modelIndex;
154− m_visibleItems.prepend(item);
155− } else {
156− qWarning() << "HorizontalJournal::addItemToView - Got unexpected modelIndex"
157− << modelIndex << m_firstVisibleIndex << m_visibleItems.count();
158− }
159− }
160−}
161−
162−void HorizontalJournal::cleanupExistingItems()
163−{
164− // Cleanup the existing items
165− Q_FOREACH(QQuickItem *item, m_visibleItems)
166− releaseItem(item);
167− m_visibleItems.clear();
168− m_lastInRowIndexPosition.clear();
169− m_firstVisibleIndex = -1;
170− setImplicitHeightDirty();
171−}
172−
173−void HorizontalJournal::calculateImplicitHeight()
174−{
175− if (m_firstVisibleIndex >= 0) {
176− const int nIndexes = m_firstVisibleIndex + m_visibleItems.count();
177− const double bottomMostY = m_visibleItems.last()->y() + m_rowHeight;
178− const double averageHeight = bottomMostY / nIndexes;
179− setImplicitHeight(bottomMostY + averageHeight * (model()->rowCount() - nIndexes));
180− } else {
181− setImplicitHeight(0);
182− }
183−}
184−
185−void HorizontalJournal::processModelRemoves(const QVector<QQmlChangeSet::Change> &removes)
186−{
187− Q_FOREACH(const QQmlChangeSet::Change remove, removes) {
188− for (int i = remove.count - 1; i >= 0; --i) {
189− const int indexToRemove = remove.index + i;
190− // We only support removing from the end so
191− // any of the last items of a column has to be indexToRemove
192− const int lastIndex = m_firstVisibleIndex + m_visibleItems.count() - 1;
193− if (indexToRemove == lastIndex) {
194− releaseItem(m_visibleItems.takeLast());
195− m_lastInRowIndexPosition.remove(indexToRemove);
196− } else {
197− if (indexToRemove < lastIndex) {
198− qDebug() << "HorizontalJournal only supports removal from the end of the model, resetting instead";
199− cleanupExistingItems();
200− break;
201− } else {
202− setImplicitHeightDirty();
203− }
204− }
205− }
206− }
207− if (m_visibleItems.isEmpty()) {
208− m_firstVisibleIndex = -1;
209− }
210−}
211−
212−
213−void HorizontalJournal::doRelayout()
214−{
215− // If m_firstVisibleIndex is not 0 we need to drop all the delegates
216− // since we can't consistently relayout without the first item being there
217−
218− if (m_firstVisibleIndex == 0) {
219− int i = 0;
220− const QList<QQuickItem*> allItems = m_visibleItems;
221− m_visibleItems.clear();
222− m_lastInRowIndexPosition.clear();
223− Q_FOREACH(QQuickItem *item, allItems) {
224− addItemToView(i, item);
225− ++i;
226− }
227− } else {
228− Q_FOREACH(QQuickItem *item, m_visibleItems) {
229− releaseItem(item);
230− }
231− m_visibleItems.clear();
232− m_lastInRowIndexPosition.clear();
233− m_firstVisibleIndex = -1;
234− }
235−}
236−
237−void HorizontalJournal::updateItemCulling(qreal visibleFromY, qreal visibleToY)
238−{
239− Q_FOREACH(QQuickItem *item, m_visibleItems) {
240− QQuickItemPrivate::get(item)->setCulled(item->y() + m_rowHeight <= visibleFromY || item->y() >= visibleToY);
241− }
242−}
plugins/Dash/horizontaljournal.hdeleted−63
@@ -1,63 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef HORIZONTALJOURNAL_H
18−#define HORIZONTALJOURNAL_H
19−
20−#include "abstractdashview.h"
21−
22− /** A horizontal journal is a view that creates delegates
23− * based on a model and layouts them one after the other
24− * in the same row until there is no more free space for the next item
25− * and so that item is layouted in the next row
26− *
27− * All delegates are forced to rowHeight if they don't have it.
28− */
29− class HorizontalJournal : public AbstractDashView
30−{
31− Q_OBJECT
32−
33− Q_PROPERTY(qreal rowHeight READ rowHeight WRITE setRowHeight NOTIFY rowHeightChanged)
34−
35−friend class HorizontalJournalTest;
36−
37−public:
38− HorizontalJournal();
39−
40− qreal rowHeight() const;
41− void setRowHeight(qreal rowHeight);
42−
43−Q_SIGNALS:
44− void rowHeightChanged();
45−
46−private:
47− void findBottomModelIndexToAdd(int *modelIndex, qreal *yPos) override;
48− void findTopModelIndexToAdd(int *modelIndex, qreal *yPos) override;
49− bool removeNonVisibleItems(qreal bufferFromY, qreal bufferToY) override;
50− void addItemToView(int modelIndex, QQuickItem *item) override;
51− void cleanupExistingItems() override;
52− void calculateImplicitHeight() override;
53− void doRelayout() override;
54− void updateItemCulling(qreal visibleFromY, qreal visibleToY) override;
55− void processModelRemoves(const QVector<QQmlChangeSet::Change> &removes) override;
56−
57− int m_firstVisibleIndex;
58− QList<QQuickItem*> m_visibleItems;
59− QMap<int, double> m_lastInRowIndexPosition;
60− int m_rowHeight;
61−};
62−
63−#endif
plugins/Dash/listviewwithpageheader.cppdeleted−1341
@@ -1,1341 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−/*
18− * Some documentation on how this thing works:
19− *
20− * A flickable has two very important concepts that define the top and
21− * height of the flickable area.
22− * The top is returned in minYExtent()
23− * The height is set using setContentHeight()
24− * By changing those two values we can make the list grow up or down
25− * as needed. e.g. if we are in the middle of the list
26− * and something that is above the viewport grows, since we do not
27− * want to change the viewport because of that we just adjust the
28− * minYExtent so that the list grows up.
29− *
30− * The implementation on the list relies on the delegateModel doing
31− * most of the instantiation work. You call createItem() when you
32− * need to create an item asking for it async or not. If returns null
33− * it means the item will be created async and the model will call the
34− * itemCreated slot with the item.
35− *
36− * updatePolish is the central point of dispatch for the work of the
37− * class. It is called by the scene graph just before drawing the class.
38− * In it we:
39− * * Make sure all items are positioned correctly
40− * * Add/Remove items if needed
41− * * Update the content height if it was dirty
42− *
43− * m_visibleItems contains all the items we have created at the moment.
44− * Actually not all of them are visible since it includes the ones
45− * in the cache area we create asynchronously to help performance.
46− * The first item in m_visibleItems has the m_firstVisibleIndex in
47− * the model. If you actually want to know what is the first
48− * item in the viewport you have to find the first non culled element
49− * in m_visibleItems
50− *
51− * All the items (except the header) are childs of m_clipItem which
52− * is a child of the contentItem() of the flickable (The contentItem()
53− * is what actually 'moves' in a a flickable). This way
54− * we can implement the clipping needed so we can have the header
55− * shown in the middle of the list over the items without the items
56− * leaking under the header in case it is transparent.
57− *
58− * The first item of m_visibleItems is the one that defines the
59− * positions of all the rest of items (see updatePolish()) and
60− * this is why sometimes we move it even if it's not the item
61− * that has triggered the function (i.e. in itemGeometryChanged())
62− *
63− * m_visibleItems is a list of ListItem. Each ListItem
64− * will contain a item and potentially a sectionItem. The sectionItem
65− * is only there when the list is using sectionDelegate+sectionProperty
66− * and this is the first item of the section. Each ListItem is vertically
67− * layouted with the sectionItem first and then the item.
68− *
69− * For sectioning we also have a section item alone (m_topSectionItem)
70− * that is used for the cases we need to show the sticky section item at
71− * the top of the view.
72− *
73− * Each delegate item has a context property called heightToClip that is
74− * used to communicate to the delegate implementation in case it has to
75− * clip itself because of overlapping with the top sticky section item.
76− * This is an implementation decision since it has been agreed it
77− * is easier to implement the clipping in QML with this info than to
78− * do it at the C++ level.
79− *
80− * Note that minYExtent and height are not always totally accurate, since
81− * we don't have the items created we can't guess their heights
82− * so we can only guarantee the values are correct when the first/last
83− * items of the list are visible, otherwise we just live with good enough
84− * values that make the list scrollable
85− *
86− * There are a few things that are not really implemented or tested properly
87− * which we don't use at the moment like changing the model, changing
88− * the section delegate, having a section delegate that changes its size, etc.
89− * The known missing features are marked with TODOs along the code.
90− */
91−
92−#include "listviewwithpageheader.h"
93−
94−#include <QCoreApplication>
95−#include <QDebug>
96−#include <qqmlinfo.h>
97−#include <qqmlengine.h>
98−#pragma GCC diagnostic push
99−#pragma GCC diagnostic ignored "-pedantic"
100−#include <private/qqmldelegatemodel_p.h>
101−#include <private/qqmlglobal_p.h>
102−#include <private/qquickitem_p.h>
103−#include <private/qquickanimation_p.h>
104−#pragma GCC diagnostic pop
105−// #include <private/qquickrectangle_p.h>
106−
107−qreal ListViewWithPageHeader::ListItem::height() const
108−{
109− return m_item->height() + (m_sectionItem ? m_sectionItem->height() : 0);
110−}
111−
112−qreal ListViewWithPageHeader::ListItem::y() const
113−{
114− return m_item->y() - (m_sectionItem ? m_sectionItem->height() : 0);
115−}
116−
117−void ListViewWithPageHeader::ListItem::setY(qreal newY)
118−{
119− if (m_sectionItem) {
120− m_sectionItem->setY(newY);
121− m_item->setY(newY + m_sectionItem->height());
122− } else {
123− m_item->setY(newY);
124− }
125−}
126−
127−bool ListViewWithPageHeader::ListItem::culled() const
128−{
129− return QQuickItemPrivate::get(m_item)->culled;
130−}
131−
132−void ListViewWithPageHeader::ListItem::setCulled(bool culled)
133−{
134− QQuickItemPrivate::get(m_item)->setCulled(culled);
135− if (m_sectionItem)
136− QQuickItemPrivate::get(m_sectionItem)->setCulled(culled);
137−}
138−
139−void ListViewWithPageHeader::ListItem::setSectionItem(QQuickItem *sectionItem)
140−{
141− m_sectionItem = sectionItem;
142−}
143−
144−ListViewWithPageHeader::ListViewWithPageHeader()
145− : m_delegateModel(nullptr)
146− , m_asyncRequestedIndex(-1)
147− , m_delegateValidated(false)
148− , m_firstVisibleIndex(-1)
149− , m_minYExtent(0)
150− , m_contentHeightDirty(false)
151− , m_headerItem(nullptr)
152− , m_previousContentY(0)
153− , m_headerItemShownHeight(0)
154− , m_sectionDelegate(nullptr)
155− , m_topSectionItem(nullptr)
156− , m_forceNoClip(false)
157− , m_inLayout(false)
158− , m_inContentHeightKeepHeaderShown(false)
159− , m_cacheBuffer(0)
160−{
161− m_clipItem = new QQuickItem(contentItem());
162−// m_clipItem = new QQuickRectangle(contentItem());
163−// ((QQuickRectangle*)m_clipItem)->setColor(Qt::gray);
164−
165− m_contentYAnimation = new QQuickNumberAnimation(this);
166− m_contentYAnimation->setEasing(QEasingCurve::OutQuad);
167− m_contentYAnimation->setProperty(QStringLiteral("contentY"));
168− m_contentYAnimation->setDuration(200);
169− m_contentYAnimation->setTargetObject(this);
170−
171− connect(this, &ListViewWithPageHeader::contentWidthChanged, this, &ListViewWithPageHeader::onContentWidthChanged);
172− connect(this, &ListViewWithPageHeader::contentHeightChanged, this, &ListViewWithPageHeader::onContentHeightChanged);
173− connect(this, &ListViewWithPageHeader::heightChanged, this, &ListViewWithPageHeader::onHeightChanged);
174− connect(m_contentYAnimation, &QQuickNumberAnimation::runningChanged, this, &ListViewWithPageHeader::contentYAnimationRunningChanged);
175−
176− setFlickableDirection(VerticalFlick);
177−}
178−
179−ListViewWithPageHeader::~ListViewWithPageHeader()
180−{
181−}
182−
183−QAbstractItemModel *ListViewWithPageHeader::model() const
184−{
185− return m_delegateModel ? m_delegateModel->model().value<QAbstractItemModel *>() : nullptr;
186−}
187−
188−void ListViewWithPageHeader::setModel(QAbstractItemModel *model)
189−{
190− if (model != this->model()) {
191− if (!m_delegateModel) {
192− createDelegateModel();
193− } else {
194− disconnect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &ListViewWithPageHeader::onModelUpdated);
195− }
196− m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
197− connect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &ListViewWithPageHeader::onModelUpdated);
198− Q_EMIT modelChanged();
199− polish();
200− // TODO?
201−// Q_EMIT contentHeightChanged();
202−// Q_EMIT contentYChanged();
203− }
204−}
205−
206−QQmlComponent *ListViewWithPageHeader::delegate() const
207−{
208− return m_delegateModel ? m_delegateModel->delegate() : nullptr;
209−}
210−
211−void ListViewWithPageHeader::setDelegate(QQmlComponent *delegate)
212−{
213− if (delegate != this->delegate()) {
214− if (!m_delegateModel) {
215− createDelegateModel();
216− }
217−
218− // Cleanup the existing items
219− Q_FOREACH(ListItem *item, m_visibleItems)
220− releaseItem(item);
221− m_visibleItems.clear();
222− m_firstVisibleIndex = -1;
223− adjustMinYExtent();
224− setContentY(0);
225− m_clipItem->setY(0);
226− if (m_topSectionItem) {
227− QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
228− }
229−
230− m_delegateModel->setDelegate(delegate);
231−
232− Q_EMIT delegateChanged();
233− m_delegateValidated = false;
234− m_contentHeightDirty = true;
235− polish();
236− }
237−}
238−
239−QQuickItem *ListViewWithPageHeader::header() const
240−{
241− return m_headerItem;
242−}
243−
244−void ListViewWithPageHeader::setHeader(QQuickItem *headerItem)
245−{
246− if (m_headerItem != headerItem) {
247− qreal oldHeaderHeight = 0;
248− qreal oldHeaderY = 0;
249− if (m_headerItem) {
250− oldHeaderHeight = m_headerItem->height();
251− oldHeaderY = m_headerItem->y();
252− m_headerItem->setParentItem(nullptr);
253− }
254− m_headerItem = headerItem;
255− if (m_headerItem) {
256− m_headerItem->setParentItem(contentItem());
257− m_headerItem->setZ(1);
258− m_previousHeaderImplicitHeight = m_headerItem->implicitHeight();
259− QQuickItemPrivate::get(m_headerItem)->addItemChangeListener(this, QQuickItemPrivate::ImplicitHeight);
260− }
261− qreal newHeaderHeight = m_headerItem ? m_headerItem->height() : 0;
262− if (!m_visibleItems.isEmpty() && newHeaderHeight != oldHeaderHeight) {
263− headerHeightChanged(newHeaderHeight, oldHeaderHeight, oldHeaderY);
264− polish();
265− m_contentHeightDirty = true;
266− }
267− Q_EMIT headerChanged();
268− }
269−}
270−
271−QQmlComponent *ListViewWithPageHeader::sectionDelegate() const
272−{
273− return m_sectionDelegate;
274−}
275−
276−void ListViewWithPageHeader::setSectionDelegate(QQmlComponent *delegate)
277−{
278− if (delegate != m_sectionDelegate) {
279− // TODO clean existing sections
280−
281− m_sectionDelegate = delegate;
282−
283− m_topSectionItem = getSectionItem(QString());
284− m_topSectionItem->setZ(3);
285− QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
286− connect(m_topSectionItem, &QQuickItem::heightChanged, this, &ListViewWithPageHeader::stickyHeaderHeightChanged);
287−
288− // TODO create sections for existing items
289−
290− Q_EMIT sectionDelegateChanged();
291− Q_EMIT stickyHeaderHeightChanged();
292− }
293−}
294−
295−QString ListViewWithPageHeader::sectionProperty() const
296−{
297− return m_sectionProperty;
298−}
299−
300−void ListViewWithPageHeader::setSectionProperty(const QString &property)
301−{
302− if (property != m_sectionProperty) {
303− m_sectionProperty = property;
304−
305− updateWatchedRoles();
306−
307− // TODO recreate sections
308−
309− Q_EMIT sectionPropertyChanged();
310− }
311−}
312−
313−bool ListViewWithPageHeader::forceNoClip() const
314−{
315− return m_forceNoClip;
316−}
317−
318−void ListViewWithPageHeader::setForceNoClip(bool noClip)
319−{
320− if (noClip != m_forceNoClip) {
321− m_forceNoClip = noClip;
322− updateClipItem();
323− Q_EMIT forceNoClipChanged();
324− }
325−}
326−
327−int ListViewWithPageHeader::stickyHeaderHeight() const
328−{
329− return m_topSectionItem ? m_topSectionItem->height() : 0;
330−}
331−
332−qreal ListViewWithPageHeader::headerItemShownHeight() const
333−{
334− return m_headerItemShownHeight;
335−}
336−
337−int ListViewWithPageHeader::cacheBuffer() const
338−{
339− return m_cacheBuffer;
340−}
341−
342−void ListViewWithPageHeader::setCacheBuffer(int cacheBuffer)
343−{
344− if (cacheBuffer < 0) {
345− qmlInfo(this) << "Cannot set a negative cache buffer";
346− return;
347− }
348−
349− if (cacheBuffer != m_cacheBuffer) {
350− m_cacheBuffer = cacheBuffer;
351− Q_EMIT cacheBufferChanged();
352− polish();
353− }
354−}
355−
356−void ListViewWithPageHeader::positionAtBeginning()
357−{
358− if (m_delegateModel->count() <= 0)
359− return;
360−
361− qreal headerHeight = (m_headerItem ? m_headerItem->height() : 0);
362− if (m_firstVisibleIndex != 0) {
363− // TODO This could be optimized by trying to reuse the interesection
364− // of items that may end up intersecting between the existing
365− // m_visibleItems and the items we are creating in the next loop
366− Q_FOREACH(ListItem *item, m_visibleItems)
367− releaseItem(item);
368− m_visibleItems.clear();
369− m_firstVisibleIndex = -1;
370−
371− // Create the item 0, it will be already correctly positioned at createItem()
372− m_clipItem->setY(0);
373− ListItem *item = createItem(0, false);
374− // Create the subsequent items
375− int modelIndex = 1;
376− qreal pos = item->y() + item->height();
377− const qreal bufferTo = height() + m_cacheBuffer;
378− while (modelIndex < m_delegateModel->count() && pos <= bufferTo) {
379− if (!(item = createItem(modelIndex, false)))
380− break;
381− pos += item->height();
382− ++modelIndex;
383− }
384−
385− m_previousContentY = m_visibleItems.first()->y() - headerHeight;
386− }
387− setContentY(m_visibleItems.first()->y() + m_clipItem->y() - headerHeight);
388− if (m_headerItem) {
389− // TODO This should not be needed and the code that adjust the m_headerItem position
390− // in viewportMoved() should be enough but in some cases we have not found a way to reproduce
391− // yet the code of viewportMoved() fails so here we make sure that at least if we are calling
392− // positionAtBeginning the header item will be correctly positioned
393− m_headerItem->setY(-m_minYExtent);
394− }
395−}
396−
397−static inline bool uFuzzyCompare(qreal r1, qreal r2)
398−{
399− return qFuzzyCompare(r1, r2) || (qFuzzyIsNull(r1) && qFuzzyIsNull(r2));
400−}
401−
402−void ListViewWithPageHeader::showHeader()
403−{
404− if (!m_headerItem)
405− return;
406−
407− const auto to = qMax(-minYExtent(), contentY() - m_headerItem->height() + m_headerItemShownHeight);
408− if (!uFuzzyCompare(to, contentY())) {
409− const bool headerShownByItsOwn = contentY() < m_headerItem->y() + m_headerItem->height();
410− if (headerShownByItsOwn && m_headerItemShownHeight == 0) {
411− // We are not clipping since we are just at the top of the viewport
412− // but because of the showHeader animation we will need to, so
413− // enable the clipping without logically moving the items
414− m_headerItemShownHeight = m_headerItem->y() + m_headerItem->height() - contentY();
415− if (!m_visibleItems.isEmpty()) {
416− updateClipItem();
417− ListItem *firstItem = m_visibleItems.first();
418− firstItem->setY(firstItem->y() - m_headerItemShownHeight);
419− layout();
420− }
421− Q_EMIT headerItemShownHeightChanged();
422− }
423− m_contentYAnimation->setTo(to);
424− contentYAnimationType = ContentYAnimationShowHeader;
425− m_contentYAnimation->start();
426− }
427−}
428−
429−int ListViewWithPageHeader::firstCreatedIndex() const
430−{
431− return m_firstVisibleIndex;
432−}
433−
434−int ListViewWithPageHeader::createdItemCount() const
435−{
436− return m_visibleItems.count();
437−}
438−
439−QQuickItem *ListViewWithPageHeader::item(int modelIndex) const
440−{
441− ListItem *item = itemAtIndex(modelIndex);
442− if (item)
443− return item->m_item;
444− else
445− return nullptr;
446−}
447−
448−bool ListViewWithPageHeader::maximizeVisibleArea(int modelIndex)
449−{
450− ListItem *listItem = itemAtIndex(modelIndex);
451− if (listItem) {
452− return maximizeVisibleArea(listItem, listItem->height());
453− }
454−
455− return false;
456−}
457−
458−bool ListViewWithPageHeader::maximizeVisibleArea(int modelIndex, int itemHeight)
459−{
460− if (itemHeight < 0)
461− return false;
462−
463− ListItem *listItem = itemAtIndex(modelIndex);
464− if (listItem) {
465− return maximizeVisibleArea(listItem, itemHeight + (listItem->sectionItem() ? listItem->sectionItem()->height() : 0));
466− }
467−
468− return false;
469−}
470−
471−bool ListViewWithPageHeader::maximizeVisibleArea(ListItem *listItem, int listItemHeight)
472−{
473− if (listItem) {
474− layout();
475− const auto listItemY = m_clipItem->y() + listItem->y();
476− if (listItemY > contentY() && listItemY + listItemHeight > contentY() + height()) {
477− // we can scroll the list up to show more stuff
478− const auto to = qMin(listItemY, listItemY + listItemHeight - height());
479− m_contentYAnimation->setTo(to);
480− contentYAnimationType = ContentYAnimationMaximizeVisibleArea;
481− m_contentYAnimation->start();
482− } else if ((listItemY < contentY() && listItemY + listItemHeight < contentY() + height()) ||
483− (m_topSectionItem && !listItem->sectionItem() && listItemY - m_topSectionItem->height() < contentY() && listItemY + listItemHeight < contentY() + height()))
484− {
485− // we can scroll the list down to show more stuff
486− auto realVisibleListItemY = listItemY;
487− if (m_topSectionItem) {
488− // If we are showing the top section sticky item and this item doesn't have a section
489− // item we have to make sure to scroll it a bit more so that it is not underlapping
490− // the top section sticky item
491− bool topSectionShown = !QQuickItemPrivate::get(m_topSectionItem)->culled;
492− if (topSectionShown && !listItem->sectionItem()) {
493− realVisibleListItemY -= m_topSectionItem->height();
494− }
495− }
496− const auto to = qMax(realVisibleListItemY, listItemY + listItemHeight - height());
497− m_contentYAnimation->setTo(to);
498− contentYAnimationType = ContentYAnimationMaximizeVisibleArea;
499− m_contentYAnimation->start();
500− }
501− return true;
502− }
503− return false;
504−}
505−
506−qreal ListViewWithPageHeader::minYExtent() const
507−{
508−// qDebug() << "ListViewWithPageHeader::minYExtent" << m_minYExtent;
509− return m_minYExtent;
510−}
511−
512−void ListViewWithPageHeader::componentComplete()
513−{
514− if (m_delegateModel)
515− m_delegateModel->componentComplete();
516−
517− QQuickFlickable::componentComplete();
518−
519− polish();
520−}
521−
522−void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
523−{
524− // Check we are not being taken down and don't paint anything
525− // TODO Check if we still need this in 5.2
526− // For reproduction just inifnite loop testDash or testDashContent
527− if (!QQmlEngine::contextForObject(this)->parentContext())
528− return;
529−
530− QQuickFlickable::viewportMoved(orient);
531−// qDebug() << "ListViewWithPageHeader::viewportMoved" << contentY();
532− const qreal diff = m_previousContentY - contentY();
533− adjustHeader(diff);
534− m_previousContentY = contentY();
535− layout();
536− polish();
537−}
538−
539−void ListViewWithPageHeader::adjustHeader(qreal diff)
540−{
541− const bool showHeaderAnimationRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationShowHeader;
542− if (m_headerItem) {
543− const auto oldHeaderItemShownHeight = m_headerItemShownHeight;
544− if (uFuzzyCompare(contentY(), -m_minYExtent) || contentY() > -m_minYExtent) {
545− m_headerItem->setHeight(m_headerItem->implicitHeight());
546− // We are going down (but it's not because of the rebound at the end)
547− // (but the header was not shown by it's own position)
548− // or the header is partially shown and we are not doing a maximizeVisibleArea either
549− const bool scrolledUp = m_previousContentY > contentY();
550− const bool notRebounding = qRound(contentY() + height()) < qRound(contentHeight());
551− const bool notShownByItsOwn = contentY() + diff >= m_headerItem->y() + m_headerItem->height();
552− const bool maximizeVisibleAreaRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationMaximizeVisibleArea;
553−
554− if (!scrolledUp && (contentY() == -m_minYExtent || (m_headerItemShownHeight == 0 && m_previousContentY == m_headerItem->y()))) {
555− m_headerItemShownHeight = 0;
556− m_headerItem->setY(-m_minYExtent);
557− } else if ((scrolledUp && notRebounding && notShownByItsOwn && !maximizeVisibleAreaRunning) || (m_headerItemShownHeight > 0) || m_inContentHeightKeepHeaderShown) {
558− if (maximizeVisibleAreaRunning && diff > 0) {
559− // If we are maximizing and the header was shown, make sure we hide it
560− m_headerItemShownHeight -= diff;
561− } else {
562− m_headerItemShownHeight += diff;
563− }
564− if (uFuzzyCompare(contentY(), -m_minYExtent)) {
565− m_headerItemShownHeight = 0;
566− } else {
567− m_headerItemShownHeight = qBound(static_cast<qreal>(0.), m_headerItemShownHeight, m_headerItem->height());
568− }
569− if (m_headerItemShownHeight > 0) {
570− if (uFuzzyCompare(m_headerItem->height(), m_headerItemShownHeight)) {
571− m_headerItem->setY(contentY());
572− m_headerItemShownHeight = m_headerItem->height();
573− } else {
574− m_headerItem->setY(contentY() - m_headerItem->height() + m_headerItemShownHeight);
575− }
576− } else {
577− m_headerItem->setY(-m_minYExtent);
578− }
579− }
580− Q_EMIT headerItemShownHeightChanged();
581− } else {
582− // Stick the header item to the top when dragging down
583− m_headerItem->setY(contentY());
584− m_headerItem->setHeight(m_headerItem->implicitHeight() + (-m_minYExtent - contentY()));
585− }
586− // We will be changing the clip item, need to accomadate for it
587− // otherwise we move the firstItem down/up twice (unless the
588− // show header animation is running, where we want to keep the viewport stable)
589− if (!showHeaderAnimationRunning) {
590− diff += oldHeaderItemShownHeight - m_headerItemShownHeight;
591− } else {
592− diff = -diff;
593− }
594− }
595− if (!m_visibleItems.isEmpty()) {
596− updateClipItem();
597− ListItem *firstItem = m_visibleItems.first();
598− firstItem->setY(firstItem->y() + diff);
599− if (showHeaderAnimationRunning) {
600− adjustMinYExtent();
601− }
602− }
603−}
604−
605−void ListViewWithPageHeader::createDelegateModel()
606−{
607− m_delegateModel = new QQmlDelegateModel(qmlContext(this), this);
608− connect(m_delegateModel, &QQmlDelegateModel::createdItem, this, &ListViewWithPageHeader::itemCreated);
609− if (isComponentComplete())
610− m_delegateModel->componentComplete();
611− updateWatchedRoles();
612−}
613−
614−void ListViewWithPageHeader::refill()
615−{
616− if (m_inLayout) {
617− return;
618− }
619− if (!isComponentComplete()) {
620− return;
621− }
622−
623− const qreal from = contentY();
624− const qreal to = from + height();
625− const qreal bufferFrom = from - m_cacheBuffer;
626− const qreal bufferTo = to + m_cacheBuffer;
627−
628− bool added = addVisibleItems(from, to, false);
629− bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
630− added |= addVisibleItems(bufferFrom, bufferTo, true);
631−
632− if (added || removed) {
633− m_contentHeightDirty = true;
634− }
635−}
636−
637−bool ListViewWithPageHeader::addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous)
638−{
639− if (!delegate())
640− return false;
641−
642− if (m_delegateModel->count() == 0)
643− return false;
644−
645− ListItem *item;
646−// qDebug() << "ListViewWithPageHeader::addVisibleItems" << fillFrom << fillTo << asynchronous;
647−
648− int modelIndex = 0;
649− qreal pos = 0;
650− if (!m_visibleItems.isEmpty()) {
651− modelIndex = m_firstVisibleIndex + m_visibleItems.count();
652− item = m_visibleItems.last();
653− pos = item->y() + item->height() + m_clipItem->y();
654− }
655− bool changed = false;
656−// qDebug() << (modelIndex < m_delegateModel->count()) << pos << fillTo;
657− while (modelIndex < m_delegateModel->count() && pos <= fillTo) {
658−// qDebug() << "refill: append item" << modelIndex << "pos" << pos << "asynchronous" << asynchronous;
659− if (!(item = createItem(modelIndex, asynchronous)))
660− break;
661− pos += item->height();
662− ++modelIndex;
663− changed = true;
664− }
665−
666− modelIndex = 0;
667− pos = 0;
668− if (!m_visibleItems.isEmpty()) {
669− modelIndex = m_firstVisibleIndex - 1;
670− item = m_visibleItems.first();
671− pos = item->y() + m_clipItem->y();
672− }
673− while (modelIndex >= 0 && pos > fillFrom) {
674−// qDebug() << "refill: prepend item" << modelIndex << "pos" << pos << "fillFrom" << fillFrom << "asynchronous" << asynchronous;
675− if (!(item = createItem(modelIndex, asynchronous)))
676− break;
677− pos -= item->height();
678− --modelIndex;
679− changed = true;
680− }
681−
682− return changed;
683−}
684−
685−void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
686−{
687− QQuickItem *item = listItem->m_item;
688− QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item);
689− if (flags & QQmlDelegateModel::Destroyed) {
690− item->setParentItem(nullptr);
691− }
692− listItem->sectionItem()->deleteLater();
693− delete listItem;
694−}
695−
696−void ListViewWithPageHeader::releaseItem(ListItem *listItem)
697−{
698− QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(listItem->m_item);
699− itemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
700− m_itemsToRelease << listItem;
701−}
702−
703−void ListViewWithPageHeader::updateWatchedRoles()
704−{
705− if (m_delegateModel) {
706− QList<QByteArray> roles;
707− if (!m_sectionProperty.isEmpty())
708− roles << m_sectionProperty.toUtf8();
709− m_delegateModel->setWatchedRoles(roles);
710− }
711−}
712−
713−QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyInserted)
714−{
715− if (!m_sectionDelegate)
716− return nullptr;
717−
718− const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
719−
720− if (modelIndex > 0) {
721− const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
722− if (section == prevSection)
723− return nullptr;
724− }
725− if (modelIndex + 1 < model()->rowCount() && !alreadyInserted) {
726− // Already inserted items can't steal next section header
727− const QString nextSection = m_delegateModel->stringValue(modelIndex + 1, m_sectionProperty);
728− if (section == nextSection) {
729− // Steal the section header
730− ListItem *nextItem = itemAtIndex(modelIndex); // Not +1 since not yet inserted into m_visibleItems
731− if (nextItem) {
732− QQuickItem *sectionItem = nextItem->sectionItem();
733− nextItem->setSectionItem(nullptr);
734− return sectionItem;
735− }
736− }
737− }
738−
739− return getSectionItem(section);
740−}
741−
742−QQuickItem *ListViewWithPageHeader::getSectionItem(const QString &sectionText)
743−{
744− QQuickItem *sectionItem = nullptr;
745−
746− QQmlContext *creationContext = m_sectionDelegate->creationContext();
747− QQmlContext *context = new QQmlContext(creationContext ? creationContext : qmlContext(this));
748− context->setContextProperty(QStringLiteral("section"), sectionText);
749− context->setContextProperty(QStringLiteral("delegateIndex"), -1);
750− QObject *nobj = m_sectionDelegate->beginCreate(context);
751− if (nobj) {
752− QQml_setParent_noEvent(context, nobj);
753− sectionItem = qobject_cast<QQuickItem *>(nobj);
754− if (!sectionItem) {
755− delete nobj;
756− } else {
757− sectionItem->setZ(2);
758− QQml_setParent_noEvent(sectionItem, m_clipItem);
759− sectionItem->setParentItem(m_clipItem);
760− }
761− } else {
762− delete context;
763− }
764− m_sectionDelegate->completeCreate();
765−
766− // TODO attach to sectionItem so we can accomodate to it changing its height
767−
768− return sectionItem;
769−}
770−
771−bool ListViewWithPageHeader::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
772−{
773−// qDebug() << "ListViewWithPageHeader::removeNonVisibleItems" << bufferFrom << bufferTo;
774− // Do not remove items if we are overshooting up or down, since we'll come back
775− // to the "stable" position and delete/create items without any reason
776− if (contentY() < -m_minYExtent) {
777− return false;
778− } else if (contentY() + height() > contentHeight()) {
779− return false;
780− }
781− bool changed = false;
782−
783− bool foundVisible = false;
784− int i = 0;
785− int removedItems = 0;
786− const auto oldFirstVisibleIndex = m_firstVisibleIndex;
787− while (i < m_visibleItems.count()) {
788− ListItem *item = m_visibleItems[i];
789− const qreal pos = item->y() + m_clipItem->y();
790−// qDebug() << i << pos << (pos + item->height()) << bufferFrom << bufferTo;
791− if (pos + item->height() < bufferFrom || pos > bufferTo) {
792−// qDebug() << "Releasing" << i << (pos + item->height() < bufferFrom) << pos + item->height() << bufferFrom << (pos > bufferTo) << pos << bufferTo;
793− releaseItem(item);
794− m_visibleItems.removeAt(i);
795− changed = true;
796− ++removedItems;
797− } else {
798− if (!foundVisible) {
799− foundVisible = true;
800− const int itemIndex = m_firstVisibleIndex + removedItems + i;
801− m_firstVisibleIndex = itemIndex;
802− }
803− ++i;
804− }
805− }
806− if (!foundVisible) {
807− m_firstVisibleIndex = -1;
808− }
809− if (m_firstVisibleIndex != oldFirstVisibleIndex) {
810− adjustMinYExtent();
811− }
812−
813− return changed;
814−}
815−
816−ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIndex, bool asynchronous)
817−{
818−// qDebug() << "CREATE ITEM" << modelIndex;
819− if (asynchronous && m_asyncRequestedIndex != -1)
820− return nullptr;
821−
822− m_asyncRequestedIndex = -1;
823− QObject* object = m_delegateModel->object(modelIndex, asynchronous);
824− QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
825− if (!item) {
826− if (object) {
827− m_delegateModel->release(object);
828− if (!m_delegateValidated) {
829− m_delegateValidated = true;
830− QObject* delegateObj = delegate();
831− qmlInfo(delegateObj ? delegateObj : this) << "Delegate must be of Item type";
832− }
833− } else {
834− m_asyncRequestedIndex = modelIndex;
835− }
836− return 0;
837− } else {
838−// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
839− ListItem *listItem = new ListItem;
840− listItem->m_item = item;
841− listItem->setSectionItem(getSectionItem(modelIndex, false /*Not yet inserted into m_visibleItems*/));
842− QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
843− ListItem *prevItem = itemAtIndex(modelIndex - 1);
844− bool lostItem = false; // Is an item that we requested async but because of model changes
845− // it is no longer attached to any of the existing items (has no prev nor next item)
846− // nor is the first item
847− if (prevItem) {
848− listItem->setY(prevItem->y() + prevItem->height());
849− } else {
850− ListItem *currItem = itemAtIndex(modelIndex);
851− if (currItem) {
852− // There's something already in m_visibleItems at out index, meaning this is an insert, so attach to its top
853− listItem->setY(currItem->y() - listItem->height());
854− } else {
855− ListItem *nextItem = itemAtIndex(modelIndex + 1);
856− if (nextItem) {
857− listItem->setY(nextItem->y() - listItem->height());
858− } else if (modelIndex == 0) {
859− listItem->setY(-m_clipItem->y() + (m_headerItem ? m_headerItem->height() : 0));
860− } else if (!m_visibleItems.isEmpty()) {
861− lostItem = true;
862− }
863− }
864− }
865− if (lostItem) {
866− listItem->setCulled(true);
867− releaseItem(listItem);
868− listItem = nullptr;
869− } else {
870− listItem->setCulled(listItem->y() + listItem->height() + m_clipItem->y() <= contentY() || listItem->y() + m_clipItem->y() >= contentY() + height());
871− if (m_visibleItems.isEmpty()) {
872− m_visibleItems << listItem;
873− } else {
874− m_visibleItems.insert(modelIndex - m_firstVisibleIndex, listItem);
875− }
876− if (m_firstVisibleIndex < 0 || modelIndex < m_firstVisibleIndex) {
877− m_firstVisibleIndex = modelIndex;
878− polish();
879− }
880− if (listItem->sectionItem()) {
881− QQmlContext *context = QQmlEngine::contextForObject(listItem->sectionItem())->parentContext();
882− context->setContextProperty(QStringLiteral("delegateIndex"), modelIndex);
883− }
884− adjustMinYExtent();
885− m_contentHeightDirty = true;
886− }
887− return listItem;
888− }
889−}
890−
891−void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
892−{
893− QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
894− if (!item) {
895− qWarning() << "ListViewWithPageHeader::itemCreated got a non item for index" << modelIndex;
896− return;
897− }
898−// qDebug() << "ListViewWithPageHeader::itemCreated" << modelIndex << item;
899− // Check we are not being taken down and don't paint anything
900− // TODO Check if we still need this in 5.2
901− // For reproduction just inifnite loop testDash or testDashContent
902− if (!QQmlEngine::contextForObject(this)->parentContext())
903− return;
904−
905− item->setParentItem(m_clipItem);
906− QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
907− context->setContextProperty(QStringLiteral("ListViewWithPageHeader"), this);
908− context->setContextProperty(QStringLiteral("heightToClip"), QVariant::fromValue<int>(0));
909− if (modelIndex == m_asyncRequestedIndex) {
910− createItem(modelIndex, false);
911− refill();
912− }
913−}
914−
915−void ListViewWithPageHeader::updateClipItem()
916−{
917− m_clipItem->setHeight(height() - m_headerItemShownHeight);
918− m_clipItem->setY(contentY() + m_headerItemShownHeight);
919− m_clipItem->setClip(!m_forceNoClip && m_headerItemShownHeight > 0);
920−}
921−
922−void ListViewWithPageHeader::onContentHeightChanged()
923−{
924− updateClipItem();
925−}
926−
927−void ListViewWithPageHeader::onContentWidthChanged()
928−{
929− m_clipItem->setWidth(contentItem()->width());
930−}
931−
932−void ListViewWithPageHeader::onHeightChanged()
933−{
934− polish();
935−}
936−
937−
938−void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool /*reset*/)
939−{
940− // TODO Do something with reset
941−// qDebug() << "ListViewWithPageHeader::onModelUpdated" << changeSet << reset;
942− const auto oldFirstVisibleIndex = m_firstVisibleIndex;
943−
944− Q_FOREACH(const QQmlChangeSet::Change remove, changeSet.removes()) {
945−// qDebug() << "ListViewWithPageHeader::onModelUpdated Remove" << remove.index << remove.count;
946− if (remove.index + remove.count > m_firstVisibleIndex && remove.index < m_firstVisibleIndex + m_visibleItems.count()) {
947− const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
948− // If all the items we are removing are either not created or culled
949− // we have to grow down to avoid viewport changing
950− bool growDown = true;
951− for (int i = 0; growDown && i < remove.count; ++i) {
952− const int modelIndex = remove.index + i;
953− ListItem *item = itemAtIndex(modelIndex);
954− if (item && !item->culled()) {
955− growDown = false;
956− }
957− }
958− for (int i = remove.count - 1; i >= 0; --i) {
959− const int visibleIndex = remove.index + i - m_firstVisibleIndex;
960− if (visibleIndex >= 0 && visibleIndex < m_visibleItems.count()) {
961− ListItem *item = m_visibleItems[visibleIndex];
962− // Pass the section item down if needed
963− if (item->sectionItem() && visibleIndex + 1 < m_visibleItems.count()) {
964− ListItem *nextItem = m_visibleItems[visibleIndex + 1];
965− if (!nextItem->sectionItem()) {
966− nextItem->setSectionItem(item->sectionItem());
967− item->setSectionItem(nullptr);
968− }
969− }
970− releaseItem(item);
971− m_visibleItems.removeAt(visibleIndex);
972− }
973− }
974− if (growDown) {
975− adjustMinYExtent();
976− } else if (remove.index <= m_firstVisibleIndex && !m_visibleItems.isEmpty()) {
977− m_visibleItems.first()->setY(oldFirstValidIndexPos);
978− }
979− if (m_visibleItems.isEmpty()) {
980− m_firstVisibleIndex = -1;
981− } else {
982− m_firstVisibleIndex -= qMax(0, m_firstVisibleIndex - remove.index);
983− }
984− } else if (remove.index + remove.count <= m_firstVisibleIndex) {
985− m_firstVisibleIndex -= remove.count;
986− }
987− for (int i = remove.count - 1; i >= 0; --i) {
988− const int modelIndex = remove.index + i;
989− if (modelIndex == m_asyncRequestedIndex) {
990− m_asyncRequestedIndex = -1;
991− } else if (modelIndex < m_asyncRequestedIndex) {
992− m_asyncRequestedIndex--;
993− }
994− }
995− }
996−
997− Q_FOREACH(const QQmlChangeSet::Change insert, changeSet.inserts()) {
998−// qDebug() << "ListViewWithPageHeader::onModelUpdated Insert" << insert.index << insert.count;
999− const bool insertingInValidIndexes = insert.index > m_firstVisibleIndex && insert.index < m_firstVisibleIndex + m_visibleItems.count();
1000− const bool firstItemWithViewOnTop = insert.index == 0 && m_firstVisibleIndex == 0 && m_visibleItems.first()->y() + m_clipItem->y() > contentY();
1001− if (insertingInValidIndexes || firstItemWithViewOnTop)
1002− {
1003− // If the items we are adding won't be really visible
1004− // we grow up instead of down to not change the viewport
1005− bool growUp = false;
1006− if (!firstItemWithViewOnTop) {
1007− for (int i = 0; i < m_visibleItems.count(); ++i) {
1008− if (!m_visibleItems[i]->culled()) {
1009− if (insert.index <= m_firstVisibleIndex + i) {
1010− growUp = true;
1011− }
1012− break;
1013− }
1014− }
1015− }
1016−
1017− const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
1018− for (int i = insert.count - 1; i >= 0; --i) {
1019− const int modelIndex = insert.index + i;
1020− ListItem *item = createItem(modelIndex, false);
1021− if (growUp) {
1022− ListItem *firstItem = m_visibleItems.first();
1023− firstItem->setY(firstItem->y() - item->height());
1024− }
1025− // Adding an item may break a "same section" chain, so check
1026− // if we need adding a new section item
1027− if (m_sectionDelegate) {
1028− ListItem *nextItem = itemAtIndex(modelIndex + 1);
1029− if (nextItem && !nextItem->sectionItem()) {
1030− nextItem->setSectionItem(getSectionItem(modelIndex + 1, true /* alredy inserted into m_visibleItems*/));
1031− if (growUp && nextItem->sectionItem()) {
1032− ListItem *firstItem = m_visibleItems.first();
1033− firstItem->setY(firstItem->y() - nextItem->sectionItem()->height());
1034− }
1035− }
1036− }
1037− }
1038− if (firstItemWithViewOnTop) {
1039− ListItem *firstItem = m_visibleItems.first();
1040− firstItem->setY(oldFirstValidIndexPos);
1041− }
1042− adjustMinYExtent();
1043− } else if (insert.index <= m_firstVisibleIndex) {
1044− m_firstVisibleIndex += insert.count;
1045− }
1046−
1047− for (int i = insert.count - 1; i >= 0; --i) {
1048− const int modelIndex = insert.index + i;
1049− if (modelIndex <= m_asyncRequestedIndex) {
1050− m_asyncRequestedIndex++;
1051− }
1052− }
1053− }
1054−
1055− Q_FOREACH(const QQmlChangeSet::Change change, changeSet.changes()) {
1056−// qDebug() << "ListViewWithPageHeader::onModelUpdated Change" << change.index << change.count;
1057− for (int i = change.index; i < change.count; ++i) {
1058− ListItem *item = itemAtIndex(i);
1059− if (item && item->sectionItem()) {
1060− QQmlContext *context = QQmlEngine::contextForObject(item->sectionItem())->parentContext();
1061− const QString sectionText = m_delegateModel->stringValue(i, m_sectionProperty);
1062− context->setContextProperty(QStringLiteral("section"), sectionText);
1063− }
1064− }
1065− }
1066−
1067− if (m_firstVisibleIndex != oldFirstVisibleIndex) {
1068− adjustMinYExtent();
1069− }
1070−
1071− for (int i = 0; i < m_visibleItems.count(); ++i) {
1072− ListItem *item = m_visibleItems[i];
1073− if (item->sectionItem()) {
1074− QQmlContext *context = QQmlEngine::contextForObject(item->sectionItem())->parentContext();
1075− context->setContextProperty(QStringLiteral("delegateIndex"), m_firstVisibleIndex + i);
1076− }
1077− }
1078−
1079− layout();
1080− polish();
1081− m_contentHeightDirty = true;
1082−}
1083−
1084−void ListViewWithPageHeader::contentYAnimationRunningChanged(bool running)
1085−{
1086− setInteractive(!running);
1087− if (!running) {
1088− m_contentHeightDirty = true;
1089− polish();
1090− }
1091−}
1092−
1093−void ListViewWithPageHeader::itemGeometryChanged(QQuickItem * /*item*/, const QRectF &newGeometry, const QRectF &oldGeometry)
1094−{
1095− const qreal heightDiff = newGeometry.height() - oldGeometry.height();
1096− if (heightDiff != 0) {
1097− if (!m_inContentHeightKeepHeaderShown && oldGeometry.y() + oldGeometry.height() + m_clipItem->y() <= contentY() && !m_visibleItems.isEmpty()) {
1098− ListItem *firstItem = m_visibleItems.first();
1099− firstItem->setY(firstItem->y() - heightDiff);
1100− adjustMinYExtent();
1101− layout();
1102− }
1103− refill();
1104− adjustMinYExtent();
1105− polish();
1106− m_contentHeightDirty = true;
1107− }
1108−}
1109−
1110−void ListViewWithPageHeader::itemImplicitHeightChanged(QQuickItem *item)
1111−{
1112− if (item == m_headerItem) {
1113− const qreal diff = m_headerItem->implicitHeight() - m_previousHeaderImplicitHeight;
1114− if (diff != 0) {
1115− adjustHeader(diff);
1116− m_previousHeaderImplicitHeight = m_headerItem->implicitHeight();
1117− layout();
1118− polish();
1119− m_contentHeightDirty = true;
1120− }
1121− }
1122−}
1123−
1124−void ListViewWithPageHeader::headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY)
1125−{
1126− const qreal heightDiff = newHeaderHeight - oldHeaderHeight;
1127− if (m_headerItemShownHeight > 0) {
1128− // If the header is shown because of the clip
1129− // Change its size
1130− m_headerItemShownHeight += heightDiff;
1131− m_headerItemShownHeight = qBound(static_cast<qreal>(0.), m_headerItemShownHeight, newHeaderHeight);
1132− updateClipItem();
1133− adjustMinYExtent();
1134− Q_EMIT headerItemShownHeightChanged();
1135− } else {
1136− if (oldHeaderY + oldHeaderHeight > contentY()) {
1137− // If the header is shown because its position
1138− // Change its size
1139− ListItem *firstItem = m_visibleItems.first();
1140− firstItem->setY(firstItem->y() + heightDiff);
1141− layout();
1142− } else {
1143− // If the header is not on screen, just change the start of the list
1144− // so the viewport is not changed
1145− adjustMinYExtent();
1146− }
1147− }
1148−}
1149−
1150−
1151−void ListViewWithPageHeader::adjustMinYExtent()
1152−{
1153− if (m_visibleItems.isEmpty()) {
1154− m_minYExtent = 0;
1155− } else {
1156− qreal nonCreatedHeight = 0;
1157− if (m_firstVisibleIndex != 0) {
1158− // Calculate the average height of items to estimate the position of the list start
1159− const int visibleItems = m_visibleItems.count();
1160− qreal visibleItemsHeight = 0;
1161− Q_FOREACH(ListItem *item, m_visibleItems) {
1162− visibleItemsHeight += item->height();
1163− }
1164− nonCreatedHeight = m_firstVisibleIndex * visibleItemsHeight / visibleItems;
1165−// qDebug() << m_firstVisibleIndex << visibleItemsHeight << visibleItems << nonCreatedHeight;
1166− }
1167− const qreal headerHeight = (m_headerItem ? m_headerItem->implicitHeight() : 0);
1168− m_minYExtent = nonCreatedHeight - m_visibleItems.first()->y() - m_clipItem->y() + headerHeight;
1169− if (m_minYExtent != 0 && qFuzzyIsNull(m_minYExtent)) {
1170− m_minYExtent = 0;
1171− m_visibleItems.first()->setY(nonCreatedHeight - m_clipItem->y() + headerHeight);
1172− }
1173− }
1174−}
1175−
1176−ListViewWithPageHeader::ListItem *ListViewWithPageHeader::itemAtIndex(int modelIndex) const
1177−{
1178− const int visibleIndexedModelIndex = modelIndex - m_firstVisibleIndex;
1179− if (visibleIndexedModelIndex >= 0 && visibleIndexedModelIndex < m_visibleItems.count())
1180− return m_visibleItems[visibleIndexedModelIndex];
1181−
1182− return nullptr;
1183−}
1184−
1185−void ListViewWithPageHeader::layout()
1186−{
1187− if (m_inLayout)
1188− return;
1189−
1190− m_inLayout = true;
1191− if (!m_visibleItems.isEmpty()) {
1192− const qreal visibleFrom = contentY() - m_clipItem->y() + m_headerItemShownHeight;
1193− const qreal visibleTo = contentY() + height() - m_clipItem->y();
1194−
1195− qreal pos = m_visibleItems.first()->y();
1196−
1197−// qDebug() << "ListViewWithPageHeader::layout Updating positions and heights. contentY" << contentY() << "minYExtent" << minYExtent();
1198− int firstReallyVisibleItem = -1;
1199− int modelIndex = m_firstVisibleIndex;
1200− Q_FOREACH(ListItem *item, m_visibleItems) {
1201− const bool cull = pos + item->height() <= visibleFrom || pos >= visibleTo;
1202− item->setCulled(cull);
1203− item->setY(pos);
1204− if (!cull && firstReallyVisibleItem == -1) {
1205− firstReallyVisibleItem = modelIndex;
1206− if (m_topSectionItem) {
1207− // Positing the top section sticky item is a two step process
1208− // First we set it either we cull it (because it doesn't need to be sticked to the top)
1209− // or stick it to the top
1210− // Then after the loop we'll make sure that if there's another section just below it
1211− // pushed the sticky section up to make it disappear
1212− const qreal topSectionStickPos = m_headerItemShownHeight + contentY() - m_clipItem->y();
1213− bool showStickySectionItem;
1214− // We need to show the "top section sticky item" when the position at the "top" of the
1215− // viewport is bigger than the start of the position of the first visible item
1216− // i.e. the first visible item starts before the viewport, or when the first
1217− // visible item starts just at the viewport start and it does not have its own section item
1218− if (topSectionStickPos > pos) {
1219− showStickySectionItem = true;
1220− } else if (topSectionStickPos == pos) {
1221− showStickySectionItem = !item->sectionItem();
1222− } else {
1223− showStickySectionItem = false;
1224− }
1225− if (!showStickySectionItem) {
1226− QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
1227− if (item->sectionItem()) {
1228− // This seems it should happen since why would we cull the top section
1229− // if the first visible item has no section header? This only happens briefly
1230− // when increasing the height of a list that is at the bottom, the m_topSectionItem
1231− // gets shown shortly in the next polish call
1232− QQuickItemPrivate::get(item->sectionItem())->setCulled(false);
1233− }
1234− } else {
1235− // Update the top sticky section header
1236− const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
1237− QQmlContext *context = QQmlEngine::contextForObject(m_topSectionItem)->parentContext();
1238− context->setContextProperty(QStringLiteral("section"), section);
1239−
1240− QQuickItemPrivate::get(m_topSectionItem)->setCulled(false);
1241− m_topSectionItem->setY(topSectionStickPos);
1242− int delegateIndex = modelIndex;
1243− // Look for the first index with this section text
1244− while (delegateIndex > 0) {
1245− const QString prevSection = m_delegateModel->stringValue(delegateIndex - 1, m_sectionProperty);
1246− if (prevSection != section)
1247− break;
1248− delegateIndex--;
1249− }
1250− context->setContextProperty(QStringLiteral("delegateIndex"), delegateIndex);
1251− if (item->sectionItem()) {
1252− QQuickItemPrivate::get(item->sectionItem())->setCulled(true);
1253− }
1254− }
1255− }
1256− }
1257− QQmlContext *context = QQmlEngine::contextForObject(item->m_item)->parentContext();
1258− const qreal clipFrom = visibleFrom + (!item->sectionItem() && m_topSectionItem && !QQuickItemPrivate::get(m_topSectionItem)->culled ? m_topSectionItem->height() : 0);
1259− if (!cull && pos < clipFrom) {
1260− context->setContextProperty(QStringLiteral("heightToClip"), clipFrom - pos);
1261− } else {
1262− context->setContextProperty(QStringLiteral("heightToClip"), QVariant::fromValue<int>(0));
1263− }
1264−// qDebug() << "ListViewWithPageHeader::layout" << item->m_item;
1265− pos += item->height();
1266− ++modelIndex;
1267− }
1268−
1269− // Second step of section sticky item positioning
1270− // Look at the next section header, check if it's pushing up the sticky one
1271− if (m_topSectionItem) {
1272− if (firstReallyVisibleItem >= 0) {
1273− for (int i = firstReallyVisibleItem - m_firstVisibleIndex + 1; i < m_visibleItems.count(); ++i) {
1274− ListItem *item = m_visibleItems[i];
1275− if (item->sectionItem()) {
1276− if (m_topSectionItem->y() + m_topSectionItem->height() > item->y()) {
1277− m_topSectionItem->setY(item->y() - m_topSectionItem->height());
1278− }
1279− break;
1280− }
1281− }
1282− }
1283− }
1284− }
1285− m_inLayout = false;
1286−}
1287−
1288−void ListViewWithPageHeader::updatePolish()
1289−{
1290− // Check we are not being taken down and don't paint anything
1291− // TODO Check if we still need this in 5.2
1292− // For reproduction just inifnite loop testDash or testDashContent
1293− if (!QQmlEngine::contextForObject(this)->parentContext())
1294− return;
1295−
1296− Q_FOREACH(ListItem *item, m_itemsToRelease)
1297− reallyReleaseItem(item);
1298− m_itemsToRelease.clear();
1299−
1300− if (!model())
1301− return;
1302−
1303− layout();
1304−
1305− refill();
1306−
1307− if (m_contentHeightDirty) {
1308− qreal contentHeight;
1309− if (m_visibleItems.isEmpty()) {
1310− contentHeight = m_headerItem ? m_headerItem->height() : 0;
1311− } else {
1312− const int modelCount = model()->rowCount();
1313− const int visibleItems = m_visibleItems.count();
1314− const int lastValidIndex = m_firstVisibleIndex + visibleItems - 1;
1315− qreal nonCreatedHeight = 0;
1316− if (lastValidIndex != modelCount - 1) {
1317− const int visibleItems = m_visibleItems.count();
1318− qreal visibleItemsHeight = 0;
1319− Q_FOREACH(ListItem *item, m_visibleItems) {
1320− visibleItemsHeight += item->height();
1321− }
1322− const int unknownSizes = modelCount - (m_firstVisibleIndex + visibleItems);
1323− nonCreatedHeight = unknownSizes * visibleItemsHeight / visibleItems;
1324− }
1325− ListItem *item = m_visibleItems.last();
1326− contentHeight = nonCreatedHeight + item->y() + item->height() + m_clipItem->y();
1327− if (m_firstVisibleIndex != 0) {
1328− // Make sure that if we are shrinking we tell the view we still fit
1329− m_minYExtent = qMax(m_minYExtent, -(contentHeight - height()));
1330− }
1331− }
1332−
1333− m_contentHeightDirty = false;
1334− adjustMinYExtent();
1335− m_inContentHeightKeepHeaderShown = m_headerItem && m_headerItem->y() == contentY();
1336− setContentHeight(contentHeight);
1337− m_inContentHeightKeepHeaderShown = false;
1338− }
1339−}
1340−
1341−#include "moc_listviewwithpageheader.cpp"
plugins/Dash/listviewwithpageheader.hdeleted−215
@@ -1,215 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef LISTVIEWWITHPAGEHEADER_H
18−#define LISTVIEWWITHPAGEHEADER_H
19−
20−#include <private/qquickitemchangelistener_p.h>
21−#include <private/qquickflickable_p.h>
22−
23−class QAbstractItemModel;
24−class QQuickNumberAnimation;
25−class QQmlChangeSet;
26−class QQmlDelegateModel;
27−
28−
29−/**
30− Note for users of this class
31−
32− ListViewWithPageHeader already loads delegates async when appropiate so if
33− your delegate uses a Loader you should not enable the asynchronous feature since
34− that will need to introduce sizing problems
35−
36− With the double async it may happen what while we are scrolling down
37− we reach to a point where given the size of the just created delegate with loader not yet loaded (which will be very close to 0)
38− we are already "at the end" of the list, but then a few milliseconds later the loader finishes loading and we could
39− have kept scrolling. This is specially visible at the end of the list where you realize
40− that scrolling ended a bit before the end of the list but the speed of the flicking was good
41− to reach the end
42−
43− By not having the second async we get a better sizing when the delegate is created and things work better
44−*/
45−
46−class ListViewWithPageHeader : public QQuickFlickable, public QQuickItemChangeListener
47−{
48− Q_OBJECT
49− Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
50− Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
51− Q_PROPERTY(QQuickItem *pageHeader READ header WRITE setHeader NOTIFY headerChanged)
52− Q_PROPERTY(QQmlComponent *sectionDelegate READ sectionDelegate WRITE setSectionDelegate NOTIFY sectionDelegateChanged)
53− Q_PROPERTY(QString sectionProperty READ sectionProperty WRITE setSectionProperty NOTIFY sectionPropertyChanged)
54− Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
55− Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
56− Q_PROPERTY(qreal headerItemShownHeight READ headerItemShownHeight NOTIFY headerItemShownHeightChanged)
57− Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
58−
59− friend class ListViewWithPageHeaderTest;
60− friend class ListViewWithPageHeaderTestSection;
61− friend class ListViewWithPageHeaderTestExternalModel;
62−
63−public:
64− ListViewWithPageHeader();
65− ~ListViewWithPageHeader();
66−
67− QAbstractItemModel *model() const;
68− void setModel(QAbstractItemModel *model);
69−
70− QQmlComponent *delegate() const;
71− void setDelegate(QQmlComponent *delegate);
72−
73− QQuickItem *header() const;
74− void setHeader(QQuickItem *header);
75−
76− QQmlComponent *sectionDelegate() const;
77− void setSectionDelegate(QQmlComponent *delegate);
78−
79− QString sectionProperty() const;
80− void setSectionProperty(const QString &property);
81−
82− bool forceNoClip() const;
83− void setForceNoClip(bool noClip);
84−
85− int stickyHeaderHeight() const;
86− qreal headerItemShownHeight() const;
87−
88− int cacheBuffer() const;
89− void setCacheBuffer(int cacheBuffer);
90−
91− Q_INVOKABLE void positionAtBeginning();
92− Q_INVOKABLE void showHeader();
93− Q_INVOKABLE int firstCreatedIndex() const;
94− Q_INVOKABLE int createdItemCount() const;
95− Q_INVOKABLE QQuickItem *item(int modelIndex) const;
96−
97− // The index has to be created for this to try to do something
98− // Created items are those visible and the precached ones
99− // Returns if the item existed or not
100− Q_INVOKABLE bool maximizeVisibleArea(int modelIndex);
101− Q_INVOKABLE bool maximizeVisibleArea(int modelIndex, int itemHeight);
102−
103−Q_SIGNALS:
104− void modelChanged();
105− void delegateChanged();
106− void headerChanged();
107− void sectionDelegateChanged();
108− void sectionPropertyChanged();
109− void forceNoClipChanged();
110− void stickyHeaderHeightChanged();
111− void headerItemShownHeightChanged();
112− void cacheBufferChanged();
113−
114−protected:
115− void componentComplete() override;
116− void viewportMoved(Qt::Orientations orient) override;
117− qreal minYExtent() const override;
118− void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) override;
119− void itemImplicitHeightChanged(QQuickItem *item) override;
120− void updatePolish() override;
121−
122−private Q_SLOTS:
123− void itemCreated(int modelIndex, QObject *object);
124− void onContentHeightChanged();
125− void onContentWidthChanged();
126− void onHeightChanged();
127− void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
128− void contentYAnimationRunningChanged(bool running);
129−
130−private:
131− class ListItem
132− {
133− public:
134− qreal height() const;
135−
136− qreal y() const;
137− void setY(qreal newY);
138−
139− bool culled() const;
140− void setCulled(bool culled);
141−
142− QQuickItem *sectionItem() const { return m_sectionItem; }
143− void setSectionItem(QQuickItem *sectionItem);
144−
145− QQuickItem *m_item;
146− private:
147− QQuickItem *m_sectionItem;
148− };
149−
150− bool maximizeVisibleArea(ListItem *listItem, int listItemHeight);
151−
152− void createDelegateModel();
153−
154− void layout();
155− void refill();
156− bool addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous);
157− bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
158− ListItem *createItem(int modelIndex, bool asynchronous);
159−
160− void adjustHeader(qreal diff);
161− void adjustMinYExtent();
162− void updateClipItem();
163− void headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY);
164− ListItem *itemAtIndex(int modelIndex) const; // Returns the item at modelIndex if has been created
165− void releaseItem(ListItem *item);
166− void reallyReleaseItem(ListItem *item);
167− void updateWatchedRoles();
168− QQuickItem *getSectionItem(int modelIndex, bool alreadyInserted);
169− QQuickItem *getSectionItem(const QString &sectionText);
170−
171− QQmlDelegateModel *m_delegateModel;
172−
173− // Index we are waiting because we requested it asynchronously
174− int m_asyncRequestedIndex;
175−
176− // Used to only give a warning once if the delegate does not return objects
177− bool m_delegateValidated;
178−
179− // Visible indexes, [0] is m_firstValidIndex, [0+1] is m_firstValidIndex +1, ...
180− QList<ListItem *> m_visibleItems;
181− int m_firstVisibleIndex;
182−
183− qreal m_minYExtent;
184−
185− QQuickItem *m_clipItem;
186−
187− // If any of the heights has changed
188− // or new items have been added/removed
189− bool m_contentHeightDirty;
190−
191− QQuickItem *m_headerItem;
192− qreal m_previousContentY;
193− qreal m_previousHeaderImplicitHeight;
194− qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position
195− // i.e. it's being shown after dragging down in the middle of the list
196− enum ContentYAnimationType { ContentYAnimationShowHeader, ContentYAnimationMaximizeVisibleArea };
197− ContentYAnimationType contentYAnimationType;
198− QQuickNumberAnimation *m_contentYAnimation;
199−
200− QQmlComponent *m_sectionDelegate;
201− QString m_sectionProperty;
202− QQuickItem *m_topSectionItem;
203−
204− bool m_forceNoClip;
205− bool m_inLayout;
206− bool m_inContentHeightKeepHeaderShown;
207− int m_cacheBuffer;
208−
209− // Qt 5.0 doesn't like releasing the items just after itemCreated
210− // so we delay the releasing until the next updatePolish
211− QList<ListItem *> m_itemsToRelease;
212−};
213−
214−
215−#endif
plugins/Dash/organicgrid.cppdeleted−260
@@ -1,260 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "organicgrid.h"
18−
19−#pragma GCC diagnostic push
20−#pragma GCC diagnostic ignored "-pedantic"
21−#include <private/qquickitem_p.h>
22−#pragma GCC diagnostic pop
23−
24−OrganicGrid::OrganicGrid()
25− : m_firstVisibleIndex(-1)
26− , m_numberOfModulesPerRow(-1)
27−{
28−}
29−
30−QSizeF OrganicGrid::smallDelegateSize() const
31−{
32− return m_smallDelegateSize;
33−}
34−
35−void OrganicGrid::setSmallDelegateSize(const QSizeF size)
36−{
37− if (m_smallDelegateSize != size) {
38− m_smallDelegateSize = size;
39− Q_EMIT smallDelegateSizeChanged();
40−
41− if (isComponentComplete()) {
42− relayout();
43− }
44− }
45−}
46−
47−QSizeF OrganicGrid::bigDelegateSize() const
48−{
49− return m_bigDelegateSize;
50−}
51−
52−void OrganicGrid::setBigDelegateSize(const QSizeF size)
53−{
54− if (m_bigDelegateSize != size) {
55− m_bigDelegateSize = size;
56− Q_EMIT bigDelegateSizeChanged();
57−
58− if (isComponentComplete()) {
59− relayout();
60− }
61− }
62−}
63−
64−QPointF OrganicGrid::positionForIndex(int modelIndex) const
65−{
66− const qreal moduleHeight = m_smallDelegateSize.height() + rowSpacing() + m_bigDelegateSize.height();
67− const qreal moduleWidth = m_smallDelegateSize.width() * 2 + columnSpacing() * 2 + m_bigDelegateSize.width();
68− const int itemsPerRow = m_numberOfModulesPerRow * 6;
69− const int rowIndex = floor(modelIndex / itemsPerRow);
70− const int columnIndex = floor((modelIndex - rowIndex * itemsPerRow) / 6);
71−
72− qreal yPos = (moduleHeight + rowSpacing()) * rowIndex;
73− const int moduleIndex = modelIndex % 6;
74− if (moduleIndex == 2) {
75− yPos += m_smallDelegateSize.height() + rowSpacing();
76− } else if (moduleIndex == 3 || moduleIndex == 5) {
77− yPos += m_bigDelegateSize.height() + rowSpacing();
78− }
79−
80− qreal xPos = (moduleWidth + columnSpacing()) * columnIndex;
81− if (moduleIndex == 1) {
82− xPos += m_smallDelegateSize.width() + columnSpacing();
83− } else if (moduleIndex == 3) {
84− xPos += m_bigDelegateSize.width() + columnSpacing();
85− } else if (moduleIndex == 4) {
86− xPos += (m_smallDelegateSize.width() + columnSpacing()) * 2;
87− } else if (moduleIndex == 5) {
88− xPos += m_bigDelegateSize.width() + m_smallDelegateSize.width() + columnSpacing() * 2;
89− }
90−
91− return QPointF(xPos, yPos);
92−}
93−
94−QSizeF OrganicGrid::sizeForIndex(int modelIndex) const
95−{
96− const int moduleIndex = modelIndex % 6;
97− if (moduleIndex == 0 || moduleIndex == 1 || moduleIndex == 3 || moduleIndex == 5) {
98− return m_smallDelegateSize;
99− } else {
100− return m_bigDelegateSize;
101− }
102−}
103−
104−void OrganicGrid::findBottomModelIndexToAdd(int *modelIndex, qreal *yPos)
105−{
106− if (m_visibleItems.isEmpty()) {
107− *modelIndex = 0;
108− *yPos = 0;
109− } else {
110− *modelIndex = m_firstVisibleIndex + m_visibleItems.count();
111− // We create stuff in a 6-module basis, so always return back
112− // the y position of the first item
113− const int firstModuleIndex = ((*modelIndex) / 6) * 6;
114− *yPos = positionForIndex(firstModuleIndex).y();
115− }
116−}
117−
118−void OrganicGrid::findTopModelIndexToAdd(int *modelIndex, qreal *yPos)
119−{
120− if (m_visibleItems.isEmpty()) {
121− *modelIndex = 0;
122− *yPos = 0;
123− } else {
124− *modelIndex = m_firstVisibleIndex - 1;
125− // We create stuff in a 6-module basis, so always return back
126− // the y position of the last item bottom
127− const int lastModuleIndex = ((*modelIndex) / 6) * 6 + 5;
128− *yPos = positionForIndex(lastModuleIndex).y();
129− *yPos += sizeForIndex(lastModuleIndex).height();
130− }
131−}
132−
133−void OrganicGrid::addItemToView(int modelIndex, QQuickItem *item)
134−{
135− // modelIndex has to be either m_firstVisibleIndex - 1 or m_firstVisibleIndex + m_visibleItems.count() or the first
136− if (modelIndex == m_firstVisibleIndex + m_visibleItems.count()) {
137− m_visibleItems << item;
138− } else if (modelIndex == m_firstVisibleIndex - 1) {
139− m_firstVisibleIndex = modelIndex;
140− m_visibleItems.prepend(item);
141− } else if (modelIndex == 0) {
142− m_firstVisibleIndex = 0;
143− m_visibleItems << item;
144− } else {
145− qWarning() << "OrganicGrid::addItemToView - Got unexpected modelIndex"
146− << modelIndex << m_firstVisibleIndex << m_visibleItems.count();
147− return;
148− }
149−
150− const QPointF pos = positionForIndex(modelIndex);
151− item->setPosition(pos);
152−
153− item->setSize(sizeForIndex(modelIndex));
154−}
155−
156−bool OrganicGrid::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
157−{
158− bool changed = false;
159−
160− // As adding, we also remove in a 6-module basis
161− int lastModuleIndex = (m_firstVisibleIndex / 6) * 6 + 5;
162− bool removeIndex = positionForIndex(lastModuleIndex).y() + sizeForIndex(lastModuleIndex).height() < bufferFromY;
163− while (removeIndex && !m_visibleItems.isEmpty()) {
164− releaseItem(m_visibleItems.takeFirst());
165− changed = true;
166− m_firstVisibleIndex++;
167−
168− lastModuleIndex = (m_firstVisibleIndex / 6) * 6 + 5;
169− removeIndex = positionForIndex(lastModuleIndex).y() + sizeForIndex(lastModuleIndex).height() < bufferFromY;
170− }
171−
172− int firstModuleIndex = ((m_firstVisibleIndex + m_visibleItems.count() - 1) / 6) * 6;
173− removeIndex = positionForIndex(firstModuleIndex).y() > bufferToY;
174− while (removeIndex && !m_visibleItems.isEmpty()) {
175− releaseItem(m_visibleItems.takeLast());
176− changed = true;
177−
178− firstModuleIndex = ((m_firstVisibleIndex + m_visibleItems.count() - 1) / 6) * 6;
179− removeIndex = positionForIndex(firstModuleIndex).y() > bufferToY;
180− }
181−
182− if (m_visibleItems.isEmpty()) {
183− m_firstVisibleIndex = -1;
184− }
185−
186− return changed;
187−}
188−
189−void OrganicGrid::cleanupExistingItems()
190−{
191− Q_FOREACH(QQuickItem *item, m_visibleItems)
192− releaseItem(item);
193− m_visibleItems.clear();
194− m_firstVisibleIndex = -1;
195− setImplicitHeightDirty();
196−}
197−
198−void OrganicGrid::doRelayout()
199−{
200− const qreal moduleWidth = m_smallDelegateSize.width() * 2 + columnSpacing() * 2 + m_bigDelegateSize.width();
201− m_numberOfModulesPerRow = floor((width() + columnSpacing()) / (moduleWidth + columnSpacing()));
202− m_numberOfModulesPerRow = qMax(1, m_numberOfModulesPerRow);
203−
204− int i = m_firstVisibleIndex;
205− const QList<QQuickItem*> allItems = m_visibleItems;
206− m_visibleItems.clear();
207− Q_FOREACH(QQuickItem *item, allItems) {
208− addItemToView(i, item);
209− ++i;
210− }
211−}
212−
213−void OrganicGrid::updateItemCulling(qreal visibleFromY, qreal visibleToY)
214−{
215− Q_FOREACH(QQuickItem *item, m_visibleItems) {
216− QQuickItemPrivate::get(item)->setCulled(item->y() + item->height() <= visibleFromY || item->y() >= visibleToY);
217− }
218−}
219−
220−void OrganicGrid::calculateImplicitHeight()
221−{
222− const qreal moduleHeight = m_smallDelegateSize.height() + rowSpacing() + m_bigDelegateSize.height();
223− const int itemCount = !model() ? 0 : model()->rowCount();
224− const int itemsPerRow = m_numberOfModulesPerRow * 6;
225− const int fullRows = floor(itemCount / itemsPerRow);
226− const qreal fullRowsHeight = fullRows == 0 ? 0 : fullRows * moduleHeight + rowSpacing() * (fullRows - 1);
227−
228− const int remainingItems = itemCount - fullRows * itemsPerRow;
229− if (remainingItems == 0) {
230− setImplicitHeight(fullRowsHeight);
231− } else if (remainingItems <= 2) {
232− setImplicitHeight(fullRowsHeight + m_smallDelegateSize.height() + rowSpacing());
233− } else {
234− setImplicitHeight(fullRowsHeight + rowSpacing() + moduleHeight);
235− }
236−}
237−
238−void OrganicGrid::processModelRemoves(const QVector<QQmlChangeSet::Change> &removes)
239−{
240− Q_FOREACH(const QQmlChangeSet::Change remove, removes) {
241− for (int i = remove.count - 1; i >= 0; --i) {
242− const int indexToRemove = remove.index + i;
243− // We only support removing from the end
244− const int lastIndex = m_firstVisibleIndex + m_visibleItems.count() - 1;
245− if (indexToRemove == lastIndex) {
246− releaseItem(m_visibleItems.takeLast());
247− } else {
248− if (indexToRemove < lastIndex) {
249− qDebug() << "OrganicGrid only supports removal from the end of the model, resetting instead";
250− cleanupExistingItems();
251− break;
252− }
253− }
254− }
255− }
256− if (m_visibleItems.isEmpty()) {
257− m_firstVisibleIndex = -1;
258− }
259− setImplicitHeightDirty();
260−}
plugins/Dash/organicgrid.hdeleted−91
@@ -1,91 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef ORGANICGRID_H
18−#define ORGANICGRID_H
19−
20−#include "abstractdashview.h"
21−
22− /** An Organic Grid is is a view that creates delegates
23− * based on a model and layouts them in groups of six items (called module).
24− *
25− * In each module there are 4 items that are forced to the small delegate size
26− * and two that are forced to the big delegate size.
27− *
28− * Example:
29− *
30− * +---+ +---+ +-----+
31− * | 1 | | 2 | | |
32− * +---+ +---+ | 5 |
33− * +-----+ | |
34− * | | +-----+
35− * | 3 | +---+ +---+
36− * | | | 4 | | 6 |
37− * +-----+ +---+ +---+
38− *
39− * Modules are positioned one after the other in a grid like fashion, i.e.
40− *
41− * +---+ +---+
42− * | 1 | | 2 |
43− * +---+ +---+
44− * +---+ +---+
45− * | 3 | | 4 |
46− * +---+ +---+
47− */
48−
49−class OrganicGrid : public AbstractDashView
50−{
51− Q_OBJECT
52−
53− Q_PROPERTY(QSizeF smallDelegateSize READ smallDelegateSize WRITE setSmallDelegateSize NOTIFY smallDelegateSizeChanged)
54− Q_PROPERTY(QSizeF bigDelegateSize READ bigDelegateSize WRITE setBigDelegateSize NOTIFY bigDelegateSizeChanged)
55−
56−friend class OrganicGridTest;
57−
58−public:
59− OrganicGrid();
60−
61− QSizeF smallDelegateSize() const;
62− void setSmallDelegateSize(const QSizeF size);
63−
64− QSizeF bigDelegateSize() const;
65− void setBigDelegateSize(const QSizeF size);
66−
67−Q_SIGNALS:
68− void smallDelegateSizeChanged();
69− void bigDelegateSizeChanged();
70−private:
71− QPointF positionForIndex(int modelIndex) const;
72− QSizeF sizeForIndex(int modelIndex) const;
73−
74− void findBottomModelIndexToAdd(int *modelIndex, qreal *yPos) override;
75− void findTopModelIndexToAdd(int *modelIndex, qreal *yPos) override;
76− void addItemToView(int modelIndex, QQuickItem *item) override;
77− bool removeNonVisibleItems(qreal bufferFromY, qreal bufferToY) override;
78− void cleanupExistingItems() override;
79− void doRelayout() override;
80− void updateItemCulling(qreal visibleFromY, qreal visibleToY) override;
81− void calculateImplicitHeight() override;
82− void processModelRemoves(const QVector<QQmlChangeSet::Change> &removes) override;
83−
84− QSizeF m_smallDelegateSize;
85− QSizeF m_bigDelegateSize;
86− int m_firstVisibleIndex;
87− int m_numberOfModulesPerRow;
88− QList<QQuickItem*> m_visibleItems;
89−};
90−
91−#endif
plugins/Dash/plugin.cppdeleted−35
@@ -1,35 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− */
17−
18−#include "plugin.h"
19−
20−#include "horizontaljournal.h"
21−#include "listviewwithpageheader.h"
22−#include "organicgrid.h"
23−#include "verticaljournal.h"
24−
25−#include <QAbstractItemModel>
26−
27−void DashPlugin::registerTypes(const char *uri)
28−{
29− Q_ASSERT(uri == QLatin1String("Dash"));
30− qmlRegisterType<QAbstractItemModel>();
31− qmlRegisterType<HorizontalJournal>(uri, 0, 1, "HorizontalJournal");
32− qmlRegisterType<ListViewWithPageHeader>(uri, 0, 1, "ListViewWithPageHeader");
33− qmlRegisterType<OrganicGrid>(uri, 0, 1, "OrganicGrid");
34− qmlRegisterType<VerticalJournal>(uri, 0, 1, "VerticalJournal");
35−}
plugins/Dash/qmldirdeleted−7
@@ -1,7 +0,0 @@
1−module Dash
2−plugin Dash-qml
3−typeinfo Dash.qmltypes
4−singleton CardCreatorCache 0.1 CardCreatorCache.qml
5−ScopeStyle 0.1 ScopeStyle.qml
6−CardAttributes 0.1 CardAttributes.qml
7−CroppedImageMinimumSourceSize 0.1 CroppedImageMinimumSourceSize.qml
plugins/Dash/verticaljournal.cppdeleted−273
@@ -1,273 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−/*
18− * The implementation is centered around m_columnVisibleItems
19− * that holds a vector of lists. There's a list for each of the
20− * columns the view has. In the list the items of the column are
21− * ordered as they appear topdown in the view. m_indexColumnMap is
22− * used when re-building the list up since given a position
23− * in the middle of the list and the need to create the previous does
24− * not give us enough information to know in which column we have
25− * to position the item so that when we reach the item the view is
26− * correctly layouted at 0 for all the columns
27− */
28−#include "verticaljournal.h"
29−
30−#pragma GCC diagnostic push
31−#pragma GCC diagnostic ignored "-pedantic"
32−#include <private/qquickitem_p.h>
33−#pragma GCC diagnostic pop
34−
35−VerticalJournal::VerticalJournal()
36− : m_columnWidth(0)
37−{
38−}
39−
40−qreal VerticalJournal::columnWidth() const
41−{
42− return m_columnWidth;
43−}
44−
45−void VerticalJournal::setColumnWidth(qreal columnWidth)
46−{
47− if (columnWidth != m_columnWidth) {
48− m_columnWidth = columnWidth;
49− Q_EMIT columnWidthChanged();
50−
51− if (isComponentComplete()) {
52− Q_FOREACH(const auto &column, m_columnVisibleItems) {
53− Q_FOREACH(const ViewItem item, column) {
54− item.m_item->setWidth(columnWidth);
55− }
56− }
57− relayout();
58− }
59− }
60−}
61−
62−void VerticalJournal::findBottomModelIndexToAdd(int *modelIndex, qreal *yPos)
63−{
64− *modelIndex = 0;
65− *yPos = std::numeric_limits<qreal>::max();
66−
67− Q_FOREACH(const auto &column, m_columnVisibleItems) {
68− if (!column.isEmpty()) {
69− const ViewItem &item = column.last();
70− *yPos = qMin(*yPos, item.y() + item.height() + rowSpacing());
71− *modelIndex = qMax(*modelIndex, item.m_modelIndex + 1);
72− } else {
73− *yPos = 0;
74− }
75− }
76−}
77−
78−void VerticalJournal::findTopModelIndexToAdd(int *modelIndex, qreal *yPos)
79−{
80− *modelIndex = 0;
81− *yPos = std::numeric_limits<qreal>::lowest();
82− int columnToAddTo = -1;
83−
84− // Find the topmost free column
85− for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
86− const auto &column = m_columnVisibleItems[i];
87− if (!column.isEmpty()) {
88− const ViewItem &item = column.first();
89− const auto itemTopPos = item.y() - rowSpacing();
90− if (itemTopPos > *yPos) {
91− *yPos = itemTopPos;
92− *modelIndex = item.m_modelIndex - 1;
93− columnToAddTo = i;
94− }
95− }
96− }
97−
98− if (*modelIndex > 0) {
99− Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
100− while (m_indexColumnMap[*modelIndex] != columnToAddTo) {
101− // We found out that we have to add to columnToAddTo
102− // and thought that we had to add *modelIndex, but history tells
103− // it is not correct, so find up from *modelIndex until we found the index
104− // that has to end up in columnToAddTo
105− *modelIndex = *modelIndex - 1;
106− Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
107− }
108− }
109−}
110−
111−bool VerticalJournal::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
112−{
113− bool changed = false;
114−
115− for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
116− QList<ViewItem> &column = m_columnVisibleItems[i];
117− while (!column.isEmpty() && column.first().y() + column.first().height() < bufferFromY) {
118− releaseItem(column.takeFirst().m_item);
119− changed = true;
120− }
121−
122− while (!column.isEmpty() && column.last().y() > bufferToY) {
123− releaseItem(column.takeLast().m_item);
124− changed = true;
125− }
126− }
127−
128− return changed;
129−}
130−
131−void VerticalJournal::addItemToView(int modelIndex, QQuickItem *item)
132−{
133− if (item->width() != m_columnWidth) {
134− qWarning() << "Item" << modelIndex << "width is not the one that the columnWidth mandates, resetting it";
135− item->setWidth(m_columnWidth);
136− }
137−
138− // Check if we add it to the bottom of existing column items
139− const QList<ViewItem> &firstColumn = m_columnVisibleItems[0];
140− qreal columnToAddY = !firstColumn.isEmpty() ? firstColumn.last().y() + firstColumn.last().height() : -rowSpacing();
141− int columnToAddTo = 0;
142− for (int i = 1; i < m_columnVisibleItems.count(); ++i) {
143− const QList<ViewItem> &column = m_columnVisibleItems[i];
144− const qreal iY = !column.isEmpty() ? column.last().y() + column.last().height() : -rowSpacing();
145− if (iY < columnToAddY) {
146− columnToAddTo = i;
147− columnToAddY = iY;
148− }
149− }
150−
151− const QList<ViewItem> &columnToAdd = m_columnVisibleItems[columnToAddTo];
152− if (columnToAdd.isEmpty() || columnToAdd.last().m_modelIndex < modelIndex) {
153− item->setX(columnToAddTo * (m_columnWidth + columnSpacing()));
154− item->setY(columnToAddY + rowSpacing());
155−
156− m_columnVisibleItems[columnToAddTo] << ViewItem(item, modelIndex);
157− m_indexColumnMap[modelIndex] = columnToAddTo;
158− } else {
159− Q_ASSERT(m_indexColumnMap.contains(modelIndex));
160− columnToAddTo = m_indexColumnMap[modelIndex];
161− columnToAddY = m_columnVisibleItems[columnToAddTo].first().y();
162−
163− item->setX(columnToAddTo * (m_columnWidth + columnSpacing()));
164− item->setY(columnToAddY - rowSpacing() - item->height());
165−
166− m_columnVisibleItems[columnToAddTo].prepend(ViewItem(item, modelIndex));
167− }
168−}
169−
170−void VerticalJournal::cleanupExistingItems()
171−{
172− // Cleanup the existing items
173− for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
174− QList<ViewItem> &column = m_columnVisibleItems[i];
175− Q_FOREACH(const ViewItem item, column)
176− releaseItem(item.m_item);
177− column.clear();
178− }
179− m_indexColumnMap.clear();
180− setImplicitHeightDirty();
181−}
182−
183−void VerticalJournal::calculateImplicitHeight()
184−{
185− int lastModelIndex = -1;
186− qreal bottomMostY = 0;
187− Q_FOREACH(const auto &column, m_columnVisibleItems) {
188− if (!column.isEmpty()) {
189− const ViewItem &item = column.last();
190− lastModelIndex = qMax(lastModelIndex, item.m_modelIndex);
191− bottomMostY = qMax(bottomMostY, item.y() + item.height());
192− }
193− }
194− if (lastModelIndex >= 0) {
195− const double averageHeight = bottomMostY / (lastModelIndex + 1);
196− setImplicitHeight(bottomMostY + averageHeight * (model()->rowCount() - lastModelIndex - 1));
197− } else {
198− setImplicitHeight(0);
199− }
200−}
201−
202−void VerticalJournal::doRelayout()
203−{
204− QList<ViewItem> allItems;
205− Q_FOREACH(const auto &column, m_columnVisibleItems)
206− allItems << column;
207−
208− qSort(allItems);
209−
210− const int nColumns = qMax(1., floor((double)(width() + columnSpacing()) / (m_columnWidth + columnSpacing())));
211− m_columnVisibleItems.resize(nColumns);
212− m_indexColumnMap.clear();
213− for (int i = 0; i < nColumns; ++i)
214− m_columnVisibleItems[i].clear();
215−
216− // If the first of allItems doesn't contain index 0 we need to drop them
217− // all since we can't consistently relayout without the first item being there
218−
219− if (!allItems.isEmpty()) {
220− if (allItems.first().m_modelIndex == 0) {
221− Q_FOREACH(const ViewItem item, allItems)
222− addItemToView(item.m_modelIndex, item.m_item);
223− } else {
224− Q_FOREACH(const ViewItem item, allItems)
225− releaseItem(item.m_item);
226− }
227− }
228−}
229−
230−void VerticalJournal::updateItemCulling(qreal visibleFromY, qreal visibleToY)
231−{
232− Q_FOREACH(const auto &column, m_columnVisibleItems) {
233− Q_FOREACH(const ViewItem item, column) {
234− const bool cull = item.y() + item.height() <= visibleFromY || item.y() >= visibleToY;
235− QQuickItemPrivate::get(item.m_item)->setCulled(cull);
236− }
237− }
238−}
239−
240−void VerticalJournal::processModelRemoves(const QVector<QQmlChangeSet::Change> &removes)
241−{
242− Q_FOREACH(const QQmlChangeSet::Change remove, removes) {
243− for (int i = remove.count - 1; i >= 0; --i) {
244− const int indexToRemove = remove.index + i;
245− // Since we only support removing from the end, indexToRemove
246− // must refer to the last item of one of the columns or
247− // be bigger than them (because it's not in the viewport and
248− // thus we have not created a delegate for it)
249− bool found = false;
250− int lastCreatedIndex = INT_MIN;
251− for (int i = 0; !found && i < m_columnVisibleItems.count(); ++i) {
252− QList<ViewItem> &column = m_columnVisibleItems[i];
253− if (!column.isEmpty()) {
254− const int lastColumnIndex = column.last().m_modelIndex;
255− if (lastColumnIndex == indexToRemove) {
256− releaseItem(column.takeLast().m_item);
257− found = true;
258− }
259− lastCreatedIndex = qMax(lastCreatedIndex, lastColumnIndex);
260− }
261− }
262− if (!found) {
263− if (indexToRemove < lastCreatedIndex) {
264− qDebug() << "VerticalJournal only supports removal from the end of the model, resetting instead";
265− cleanupExistingItems();
266− break;
267− } else {
268− setImplicitHeightDirty();
269− }
270− }
271− }
272− }
273−}
plugins/Dash/verticaljournal.hdeleted−100
@@ -1,100 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef VERTICALJOURNAL_H
18−#define VERTICALJOURNAL_H
19−
20−#include "abstractdashview.h"
21−
22− /** A vertical journal is a view that creates delegates
23− * based on a model and layouts them in columns following
24− * a top-left most position rule.
25− *
26− * The number of columns is calculated using the width of
27− * the view itself, the columnWidth (i.e. the width of each individual delegate)
28− * and the columnSpacing between columns.
29− *
30− * All delegates are forced to columnWidth if they don't have it.
31− *
32− * The first nColumns items are layouted at row 0 from column 0
33− * to column nColumns-1 in order. After that every new item
34− * is positioned in the column which provides the free topmost
35− * position as possible. If more than one column tie in providing
36− * the topmost free position the leftmost column will be used.
37− *
38− * Example:
39− *
40− * +-----+ +-----+ +-----+
41− * | | | 2 | | |
42− * | | | | | |
43− * | 1 | +-----+ | 3 |
44− * | | +-----+ | |
45− * | | | | +-----+
46− * +-----+ | 4 | +-----+
47− * +-----+ | | | 5 |
48− * | 6 | +-----+ | |
49− * | | +-----+
50− * +-----+
51− *
52− */
53−
54−class VerticalJournal : public AbstractDashView
55−{
56− Q_OBJECT
57−
58− Q_PROPERTY(qreal columnWidth READ columnWidth WRITE setColumnWidth NOTIFY columnWidthChanged)
59−
60−friend class VerticalJournalTest;
61−
62−public:
63− VerticalJournal();
64−
65− qreal columnWidth() const;
66− void setColumnWidth(qreal columnWidth);
67−
68−Q_SIGNALS:
69− void columnWidthChanged();
70−
71−private:
72− class ViewItem
73− {
74− public:
75− ViewItem(QQuickItem *item, int modelIndex) : m_item(item), m_modelIndex(modelIndex) {}
76− qreal x() const { return m_item->x(); }
77− qreal y() const { return m_item->y(); }
78− qreal height() const { return m_item->height(); }
79− bool operator<(const ViewItem v) const { return m_modelIndex < v.m_modelIndex; }
80−
81− QQuickItem *m_item;
82− int m_modelIndex;
83− };
84−
85− void findBottomModelIndexToAdd(int *modelIndex, qreal *yPos) override;
86− void findTopModelIndexToAdd(int *modelIndex, qreal *yPos) override;
87− bool removeNonVisibleItems(qreal bufferFromY, qreal bufferToY) override;
88− void addItemToView(int modelIndex, QQuickItem *item) override;
89− void cleanupExistingItems() override;
90− void calculateImplicitHeight() override;
91− void doRelayout() override;
92− void updateItemCulling(qreal visibleFromY, qreal visibleToY) override;
93− void processModelRemoves(const QVector<QQmlChangeSet::Change> &removes) override;
94−
95− QVector<QList<ViewItem>> m_columnVisibleItems;
96− QHash<int, int> m_indexColumnMap;
97− int m_columnWidth;
98−};
99−
100−#endif
plugins/GlobalShortcut/CMakeLists.txt+1−1
@@ -5,6 +5,6 @@ set(globalshortcutplugin_SRCS
55
66add_library(GlobalShortcut-qml SHARED ${globalshortcutplugin_SRCS})
77
8−qt5_use_modules(GlobalShortcut-qml Quick Gui)
8+target_link_libraries(GlobalShortcut-qml Qt5::Quick Qt5::Gui)
99
1010add_unity8_plugin(GlobalShortcut 1.0 GlobalShortcut TARGETS GlobalShortcut-qml)
plugins/GlobalShortcut/globalshortcut.cpp+15−4
@@ -58,15 +58,26 @@ void GlobalShortcut::setActive(bool active)
5858
5959void GlobalShortcut::componentComplete()
6060{
61+ if (this->window()) {
62+ QMetaObject::invokeMethod(this, "setupFilterOnWindow", Q_ARG(QQuickWindow*, this->window()));
63+ }
6164 connect(this, &QQuickItem::windowChanged, this, &GlobalShortcut::setupFilterOnWindow);
6265}
6366
6467void GlobalShortcut::keyPressEvent(QKeyEvent * event)
6568{
66− Q_UNUSED(event)
67− if (m_active) {
68− Q_EMIT triggered(m_shortcut.toString());
69− }
69+ if (!m_active) return;
70+
71+ event->accept();
72+ Q_EMIT triggered(m_shortcut.toString());
73+}
74+
75+void GlobalShortcut::keyReleaseEvent(QKeyEvent * event)
76+{
77+ if (!m_active) return;
78+
79+ event->accept();
80+ Q_EMIT released(m_shortcut.toString());
7081}
7182
7283void GlobalShortcut::setupFilterOnWindow(QQuickWindow *window)
plugins/GlobalShortcut/globalshortcut.h+5
@@ -55,6 +55,7 @@ public:
5555protected:
5656 void componentComplete() override;
5757 void keyPressEvent(QKeyEvent * event) override;
58+ void keyReleaseEvent(QKeyEvent * event) override;
5859
5960Q_SIGNALS:
6061 void shortcutChanged(const QVariant &shortcut);
@@ -62,6 +63,10 @@ Q_SIGNALS:
6263 * Emitted when a global keypress of @p shortcut is detected
6364 */
6465 void triggered(const QString &shortcut);
66+ /**
67+ * Emitted when a global keypress of @p shortcut is released
68+ */
69+ void released(const QString &shortcut);
6570 void activeChanged(bool active);
6671
6772private Q_SLOTS:
plugins/GlobalShortcut/globalshortcutregistry.cpp+18−8
@@ -35,13 +35,13 @@ GlobalShortcutList GlobalShortcutRegistry::shortcuts() const
3535
3636bool GlobalShortcutRegistry::hasShortcut(const QVariant &seq) const
3737{
38− return m_shortcuts.keys().contains(seq);
38+ return m_shortcuts.contains(seq);
3939}
4040
4141void GlobalShortcutRegistry::addShortcut(const QVariant &seq, GlobalShortcut *sc)
4242{
4343 if (sc) {
44− if (!m_shortcuts.keys().contains(seq)) { // create a new entry
44+ if (!m_shortcuts.contains(seq)) { // create a new entry
4545 m_shortcuts.insert(seq, {sc});
4646 } else { // append to an existing one
4747 auto shortcuts = m_shortcuts[seq];
@@ -73,20 +73,30 @@ bool GlobalShortcutRegistry::eventFilter(QObject *obj, QEvent *event)
7373 Q_ASSERT(m_filteredWindow);
7474 Q_ASSERT(obj == static_cast<QObject*>(m_filteredWindow.data()));
7575
76− if (event->type() == QEvent::KeyPress) {
76+ if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
77+
7778 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
78− QKeySequence seq = QKeySequence(keyEvent->key() + keyEvent->modifiers());
79− if (m_shortcuts.keys().contains(seq)) {
79+
80+ // Make a copy of the event so we don't alter it for passing on.
81+ QKeyEvent eCopy(keyEvent->type(),
82+ keyEvent->key(),
83+ keyEvent->modifiers(),
84+ keyEvent->text(),
85+ keyEvent->isAutoRepeat(),
86+ keyEvent->count());
87+ eCopy.ignore();
88+
89+ int seq = keyEvent->key() + keyEvent->modifiers();
90+ if (m_shortcuts.contains(seq)) {
8091 const auto shortcuts = m_shortcuts.value(seq);
8192 Q_FOREACH(const auto &shortcut, shortcuts) {
8293 if (shortcut) {
83− qApp->sendEvent(shortcut, keyEvent);
84− event->accept();
94+ qApp->sendEvent(shortcut, &eCopy);
8595 }
8696 }
8797 }
8898
89− return event->isAccepted();
99+ return eCopy.isAccepted();
90100 }
91101
92102 return QObject::eventFilter(obj, event);
plugins/Greeter/Unity/Launcher/CMakeLists.txt+1−3
@@ -1,4 +1,3 @@
1−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
21pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
32
43add_definitions(-DSM_BUSNAME=systemBus)
@@ -30,8 +29,7 @@ add_library(UnityLauncherAS-qml MODULE
3029target_link_libraries(UnityLauncherAS-qml
3130 unity8-private
3231 ${GSETTINGS_QT_LDFLAGS}
32+ Qt5::DBus Qt5::Qml Qt5::Gui
3333 )
3434
35−qt5_use_modules(UnityLauncherAS-qml DBus Qml Gui)
36−
3735add_unity8_greeter_plugin(Unity.Launcher 0.1 Unity/Launcher TARGETS UnityLauncherAS-qml)
plugins/Greeter/Unity/Launcher/Launcher.qmltypesdeleted−182
@@ -1,182 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable Unity.Launcher 0.1 plugins/Greeter'
8−
9−Module {
10− Component {
11− name: "LauncherItem"
12− prototype: "unity::shell::launcher::LauncherItemInterface"
13− exports: ["Unity.Launcher/LauncherItem 0.1"]
14− isCreatable: false
15− exportMetaObjectRevisions: [0]
16− }
17− Component {
18− name: "LauncherModel"
19− prototype: "unity::shell::launcher::LauncherModelInterface"
20− exports: ["Unity.Launcher/LauncherModel 0.1"]
21− isCreatable: false
22− isSingleton: true
23− exportMetaObjectRevisions: [0]
24− Method {
25− name: "requestRemove"
26− Parameter { name: "appId"; type: "string" }
27− }
28− Method { name: "refresh" }
29− Method {
30− name: "get"
31− type: "unity::shell::launcher::LauncherItemInterface*"
32− Parameter { name: "index"; type: "int" }
33− }
34− Method {
35− name: "move"
36− Parameter { name: "oldIndex"; type: "int" }
37− Parameter { name: "newIndex"; type: "int" }
38− }
39− Method {
40− name: "pin"
41− Parameter { name: "appId"; type: "string" }
42− Parameter { name: "index"; type: "int" }
43− }
44− Method {
45− name: "pin"
46− Parameter { name: "appId"; type: "string" }
47− }
48− Method {
49− name: "quickListActionInvoked"
50− Parameter { name: "appId"; type: "string" }
51− Parameter { name: "actionIndex"; type: "int" }
52− }
53− Method {
54− name: "setUser"
55− Parameter { name: "username"; type: "string" }
56− }
57− Method {
58− name: "getUrlForAppId"
59− type: "string"
60− Parameter { name: "appId"; type: "string" }
61− }
62− }
63− Component {
64− name: "QuickListModel"
65− prototype: "unity::shell::launcher::QuickListModelInterface"
66− exports: ["Unity.Launcher/QuickListModel 0.1"]
67− isCreatable: false
68− exportMetaObjectRevisions: [0]
69− }
70− Component {
71− name: "unity::shell::launcher::LauncherItemInterface"
72− prototype: "QObject"
73− exports: ["Unity.Launcher/LauncherItemInterface 0.1"]
74− isCreatable: false
75− exportMetaObjectRevisions: [0]
76− Property { name: "appId"; type: "string"; isReadonly: true }
77− Property { name: "name"; type: "string"; isReadonly: true }
78− Property { name: "icon"; type: "string"; isReadonly: true }
79− Property { name: "pinned"; type: "bool"; isReadonly: true }
80− Property { name: "running"; type: "bool"; isReadonly: true }
81− Property { name: "recent"; type: "bool"; isReadonly: true }
82− Property { name: "progress"; type: "int"; isReadonly: true }
83− Property { name: "count"; type: "int"; isReadonly: true }
84− Property { name: "countVisible"; type: "bool"; isReadonly: true }
85− Property { name: "focused"; type: "bool"; isReadonly: true }
86− Property {
87− name: "quickList"
88− type: "unity::shell::launcher::QuickListModelInterface"
89− isReadonly: true
90− isPointer: true
91− }
92− Signal {
93− name: "nameChanged"
94− Parameter { name: "name"; type: "string" }
95− }
96− Signal {
97− name: "iconChanged"
98− Parameter { name: "icon"; type: "string" }
99− }
100− Signal {
101− name: "pinnedChanged"
102− Parameter { name: "pinned"; type: "bool" }
103− }
104− Signal {
105− name: "runningChanged"
106− Parameter { name: "running"; type: "bool" }
107− }
108− Signal {
109− name: "recentChanged"
110− Parameter { name: "running"; type: "bool" }
111− }
112− Signal {
113− name: "progressChanged"
114− Parameter { name: "progress"; type: "int" }
115− }
116− Signal {
117− name: "countChanged"
118− Parameter { name: "count"; type: "int" }
119− }
120− Signal {
121− name: "countVisibleChanged"
122− Parameter { name: "countVisible"; type: "bool" }
123− }
124− Signal {
125− name: "focusedChanged"
126− Parameter { name: "focused"; type: "bool" }
127− }
128− }
129− Component {
130− name: "unity::shell::launcher::LauncherModelInterface"
131− prototype: "QAbstractListModel"
132− exports: ["Unity.Launcher/LauncherModelInterface 0.1"]
133− isCreatable: false
134− exportMetaObjectRevisions: [0]
135− Property {
136− name: "applicationManager"
137− type: "unity::shell::application::ApplicationManagerInterface"
138− isPointer: true
139− }
140− Property { name: "onlyPinned"; type: "bool" }
141− Signal { name: "hint" }
142− Method {
143− name: "move"
144− Parameter { name: "oldIndex"; type: "int" }
145− Parameter { name: "newIndex"; type: "int" }
146− }
147− Method {
148− name: "get"
149− type: "unity::shell::launcher::LauncherItemInterface*"
150− Parameter { name: "index"; type: "int" }
151− }
152− Method {
153− name: "pin"
154− Parameter { name: "appId"; type: "string" }
155− Parameter { name: "index"; type: "int" }
156− }
157− Method {
158− name: "pin"
159− Parameter { name: "appId"; type: "string" }
160− }
161− Method {
162− name: "requestRemove"
163− Parameter { name: "appId"; type: "string" }
164− }
165− Method {
166− name: "quickListActionInvoked"
167− Parameter { name: "appId"; type: "string" }
168− Parameter { name: "actionIndex"; type: "int" }
169− }
170− Method {
171− name: "setUser"
172− Parameter { name: "username"; type: "string" }
173− }
174− }
175− Component {
176− name: "unity::shell::launcher::QuickListModelInterface"
177− prototype: "QAbstractListModel"
178− exports: ["Unity.Launcher/QuickListInterface 0.1"]
179− isCreatable: false
180− exportMetaObjectRevisions: [0]
181− }
182−}
plugins/Greeter/Unity/Launcher/launcheritem.cpp+33
@@ -32,6 +32,7 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
3232 m_countVisible(false),
3333 m_focused(false),
3434 m_alerting(false),
35+ m_surfaceCount(0),
3536 m_quickList(new QuickListModel(this))
3637{
3738 QuickListEntry nameAction;
@@ -75,6 +76,25 @@ void LauncherItem::setIcon(const QString &icon)
7576 }
7677}
7778
79+QStringList LauncherItem::keywords() const
80+{
81+ return m_keywords;
82+}
83+
84+void LauncherItem::setKeywords(const QStringList &keywords)
85+{
86+ if (m_keywords != keywords) {
87+ m_keywords = keywords;
88+ Q_EMIT keywordsChanged(keywords);
89+ }
90+}
91+
92+uint LauncherItem::popularity() const
93+{
94+ // Not exposing usage order in greeter session at this point.
95+ return 0;
96+}
97+
7898bool LauncherItem::pinned() const
7999{
80100 return m_pinned;
@@ -179,6 +199,19 @@ void LauncherItem::setAlerting(bool alerting)
179199 }
180200}
181201
202+int LauncherItem::surfaceCount() const
203+{
204+ return m_surfaceCount;
205+}
206+
207+void LauncherItem::setSurfaceCount(int surfaceCount)
208+{
209+ if (m_surfaceCount != surfaceCount) {
210+ m_surfaceCount = surfaceCount;
211+ Q_EMIT surfaceCountChanged(surfaceCount);
212+ }
213+}
214+
182215unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
183216{
184217 return m_quickList;
plugins/Greeter/Unity/Launcher/launcheritem.h+7−1
@@ -34,6 +34,8 @@ public:
3434 QString appId() const override;
3535 QString name() const override;
3636 QString icon() const override;
37+ QStringList keywords() const override;
38+ uint popularity() const override;
3739 bool pinned() const override;
3840 bool running() const override;
3941 bool recent() const override;
@@ -42,12 +44,14 @@ public:
4244 bool countVisible() const override;
4345 bool focused() const override;
4446 bool alerting() const override;
47+ int surfaceCount() const override;
4548
4649 unity::shell::launcher::QuickListModelInterface *quickList() const override;
4750
4851private:
4952 void setName(const QString &name);
5053 void setIcon(const QString &icon);
54+ void setKeywords(const QStringList &keywords);
5155 void setPinned(bool pinned);
5256 void setRunning(bool running);
5357 void setRecent(bool recent);
@@ -56,12 +60,13 @@ private:
5660 void setCountVisible(bool countVisible);
5761 void setFocused(bool focused);
5862 void setAlerting(bool alerting);
59−
63+ void setSurfaceCount(int surfaceCount);
6064
6165private:
6266 QString m_appId;
6367 QString m_name;
6468 QString m_icon;
69+ QStringList m_keywords;
6570 bool m_pinned;
6671 bool m_running;
6772 bool m_recent;
@@ -70,6 +75,7 @@ private:
7075 bool m_countVisible;
7176 bool m_focused;
7277 bool m_alerting;
78+ int m_surfaceCount;
7379 QuickListModel *m_quickList;
7480
7581 friend class LauncherModel;
plugins/Greeter/Unity/Launcher/launchermodelas.cpp+2−7
@@ -69,18 +69,13 @@ QVariant LauncherModel::data(const QModelIndex &index, int role) const
6969 return item->focused();
7070 case RoleRunning:
7171 return item->running();
72+ case RoleSurfaceCount:
73+ return item->surfaceCount();
7274 }
7375
7476 return QVariant();
7577}
7678
77−void LauncherModel::setAlerting(const QString &appId, bool alerting)
78−{
79− Q_UNUSED(appId)
80− Q_UNUSED(alerting)
81− qWarning() << "This is a read only implementation. Cannot set alert-state of items.";
82−}
83−
8479unity::shell::launcher::LauncherItemInterface *LauncherModel::get(int index) const
8580{
8681 if (index < 0 || index >= m_list.count()) {
plugins/Greeter/Unity/Launcher/launchermodelas.h−1
@@ -41,7 +41,6 @@ public:
4141
4242 QVariant data(const QModelIndex &index, int role) const override;
4343
44− Q_INVOKABLE void setAlerting(const QString &appId, bool alerting) override;
4544 Q_INVOKABLE unity::shell::launcher::LauncherItemInterface* get(int index) const override;
4645 Q_INVOKABLE void move(int oldIndex, int newIndex) override;
4746 Q_INVOKABLE void pin(const QString &appId, int index = -1) override;
plugins/Greeter/Unity/Launcher/quicklistmodel.cpp+2
@@ -65,6 +65,8 @@ QVariant QuickListModel::data(const QModelIndex &index, int role) const
6565 return m_list.at(index.row()).icon();
6666 case RoleClickable:
6767 return m_list.at(index.row()).clickable();
68+ case RoleIsPrivate:
69+ return false; // The greeter plugin would just not add any private entries
6870 }
6971 return QVariant();
7072}
plugins/IntegratedLightDM/CMakeLists.txtdeleted−40
@@ -1,40 +0,0 @@
1−pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
2−# TODO: Once we split out a separate greeter process, uncomment these lines
3−#pkg_check_modules(LIBLIGHTDM REQUIRED liblightdm-qt5-2)
4−
5−add_subdirectory(liblightdm)
6−
7−include_directories(
8− ${CMAKE_CURRENT_SOURCE_DIR}
9− ${CMAKE_CURRENT_BINARY_DIR}
10− ${CMAKE_SOURCE_DIR}/plugins/Utils
11− ${CMAKE_SOURCE_DIR}/tests/mocks/IntegratedLightDM
12− #${LIBLIGHTDM_INCLUDE_DIRS}
13− ${libunity8-private_SOURCE_DIR}
14− ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
15−)
16−
17−set(QMLPLUGIN_SRC
18− ../Utils/unitysortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
19− DBusGreeter.cpp
20− DBusGreeterList.cpp
21− Greeter.cpp
22− plugin.cpp
23− UsersModel.cpp
24− )
25−
26−add_library(IntegratedLightDM-qml MODULE
27− ${QMLPLUGIN_SRC}
28− )
29−
30−target_link_libraries(IntegratedLightDM-qml
31− integratedLightDM
32− unity8-private
33−# TODO: Once we split out a separate greeter process, uncomment these lines
34−# ${LIBLIGHTDM_LDFLAGS}
35− ${LIBUSERMETRICSOUTPUT_LDFLAGS}
36− )
37−
38−qt5_use_modules(IntegratedLightDM-qml DBus Gui Qml)
39−
40−add_unity8_plugin(IntegratedLightDM 0.1 IntegratedLightDM TARGETS IntegratedLightDM-qml)
plugins/IntegratedLightDM/Greeter.cppdeleted−138
@@ -1,138 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Author: Michael Terry <michael.terry@canonical.com>
17− */
18−
19−#include "Greeter.h"
20−#include "GreeterPrivate.h"
21−#include <libintl.h>
22−
23−GreeterPrivate::GreeterPrivate(Greeter* parent)
24− : m_greeter(new QLightDM::Greeter(parent)),
25− m_active(false),
26− wasPrompted(false),
27− promptless(false),
28− q_ptr(parent)
29−{
30−}
31−
32−Greeter::Greeter(QObject* parent)
33− : QObject(parent),
34− d_ptr(new GreeterPrivate(this))
35−{
36− Q_D(Greeter);
37−
38− connect(d->m_greeter, &QLightDM::Greeter::showMessage,
39− this, &Greeter::showMessageFilter);
40− connect(d->m_greeter, &QLightDM::Greeter::showPrompt,
41− this, &Greeter::showPromptFilter);
42− connect(d->m_greeter, &QLightDM::Greeter::authenticationComplete,
43− this, &Greeter::authenticationCompleteFilter);
44−
45− d->m_greeter->connectSync();
46−}
47−
48−bool Greeter::isActive() const
49−{
50− Q_D(const Greeter);
51− return d->m_active;
52−}
53−
54−void Greeter::setIsActive(bool active)
55−{
56− Q_D(Greeter);
57− if (d->m_active != active) {
58− d->m_active = active;
59− Q_EMIT isActiveChanged();
60− }
61−}
62−
63−bool Greeter::isAuthenticated() const
64−{
65− Q_D(const Greeter);
66− return d->m_greeter->isAuthenticated();
67−}
68−
69−QString Greeter::authenticationUser() const
70−{
71− Q_D(const Greeter);
72− return d->m_greeter->authenticationUser();
73−}
74−
75−bool Greeter::promptless() const
76−{
77− Q_D(const Greeter);
78− return d->promptless;
79−}
80−
81−void Greeter::authenticate(const QString &username)
82−{
83− Q_D(Greeter);
84− d->wasPrompted = false;
85− if (d->promptless) {
86− d->promptless = false;
87− Q_EMIT promptlessChanged();
88− }
89−
90− d->m_greeter->authenticate(username);
91− Q_EMIT isAuthenticatedChanged();
92− Q_EMIT authenticationUserChanged(username);
93−}
94−
95−void Greeter::respond(const QString &response)
96−{
97− Q_D(Greeter);
98− d->m_greeter->respond(response);
99−}
100−
101−bool Greeter::startSessionSync(const QString &session)
102−{
103− Q_D(Greeter);
104− return d->m_greeter->startSessionSync(session);
105−}
106−
107−void Greeter::showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type)
108−{
109− Q_D(Greeter);
110− d->wasPrompted = true;
111−
112− bool isDefaultPrompt = (text == dgettext("Linux-PAM", "Password: "));
113−
114− // Strip prompt of any colons at the end
115− QString trimmedText = text.trimmed();
116− if (trimmedText.endsWith(':') || trimmedText.endsWith(QStringLiteral(":"))) {
117− trimmedText.chop(1);
118− }
119−
120− Q_EMIT showPrompt(trimmedText, type == QLightDM::Greeter::PromptTypeSecret, isDefaultPrompt);
121−}
122−
123−void Greeter::showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type)
124−{
125− Q_EMIT showMessage(text, type == QLightDM::Greeter::MessageTypeError);
126−}
127−
128−void Greeter::authenticationCompleteFilter()
129−{
130− Q_D(Greeter);
131− if (!d->wasPrompted) {
132− d->promptless = true;
133− Q_EMIT promptlessChanged();
134− }
135−
136− Q_EMIT isAuthenticatedChanged();
137− Q_EMIT authenticationComplete();
138−}
plugins/IntegratedLightDM/IntegratedLightDM.qmltypesdeleted−251
@@ -1,251 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable LightDM 0.1 plugins'
8−
9−Module {
10− Component {
11− name: "Greeter"
12− prototype: "QObject"
13− exports: ["LightDM/Greeter 0.1"]
14− isCreatable: false
15− isSingleton: true
16− exportMetaObjectRevisions: [0]
17− Property { name: "active"; type: "bool" }
18− Property { name: "authenticated"; type: "bool"; isReadonly: true }
19− Property { name: "authenticationUser"; type: "string"; isReadonly: true }
20− Property { name: "promptless"; type: "bool"; isReadonly: true }
21− Signal {
22− name: "showMessage"
23− Parameter { name: "text"; type: "string" }
24− Parameter { name: "isError"; type: "bool" }
25− }
26− Signal {
27− name: "showPrompt"
28− Parameter { name: "text"; type: "string" }
29− Parameter { name: "isSecret"; type: "bool" }
30− Parameter { name: "isDefaultPrompt"; type: "bool" }
31− }
32− Signal { name: "authenticationComplete" }
33− Signal {
34− name: "authenticationUserChanged"
35− Parameter { name: "user"; type: "string" }
36− }
37− Signal { name: "isActiveChanged" }
38− Signal { name: "isAuthenticatedChanged" }
39− Signal { name: "showGreeter" }
40− Signal { name: "hideGreeter" }
41− Signal {
42− name: "requestAuthenticationUser"
43− Parameter { name: "user"; type: "string" }
44− }
45− Method {
46− name: "authenticate"
47− Parameter { name: "username"; type: "string" }
48− }
49− Method { name: "authenticate" }
50− Method {
51− name: "respond"
52− Parameter { name: "response"; type: "string" }
53− }
54− Method {
55− name: "startSessionSync"
56− type: "bool"
57− Parameter { name: "session"; type: "string" }
58− }
59− Method { name: "startSessionSync"; type: "bool" }
60− Method {
61− name: "setIsActive"
62− Parameter { name: "isActive"; type: "bool" }
63− }
64− }
65− Component {
66− name: "QAbstractProxyModel"
67− prototype: "QAbstractItemModel"
68− Property { name: "sourceModel"; type: "QAbstractItemModel"; isPointer: true }
69− }
70− Component {
71− name: "QLightDM::UsersModel"
72− prototype: "QAbstractListModel"
73− exports: ["LightDM/UserRoles 0.1"]
74− isCreatable: false
75− exportMetaObjectRevisions: [0]
76− Enum {
77− name: "UserModelRoles"
78− values: {
79− "NameRole": 256,
80− "RealNameRole": 257,
81− "LoggedInRole": 258,
82− "BackgroundRole": 259,
83− "SessionRole": 260,
84− "HasMessagesRole": 261,
85− "ImagePathRole": 262,
86− "BackgroundPathRole": 263
87− }
88− }
89− }
90− Component {
91− name: "QSortFilterProxyModel"
92− prototype: "QAbstractProxyModel"
93− Property { name: "filterRegExp"; type: "QRegExp" }
94− Property { name: "filterKeyColumn"; type: "int" }
95− Property { name: "dynamicSortFilter"; type: "bool" }
96− Property { name: "filterCaseSensitivity"; type: "Qt::CaseSensitivity" }
97− Property { name: "sortCaseSensitivity"; type: "Qt::CaseSensitivity" }
98− Property { name: "isSortLocaleAware"; type: "bool" }
99− Property { name: "sortRole"; type: "int" }
100− Property { name: "filterRole"; type: "int" }
101− Method {
102− name: "setFilterRegExp"
103− Parameter { name: "pattern"; type: "string" }
104− }
105− Method {
106− name: "setFilterWildcard"
107− Parameter { name: "pattern"; type: "string" }
108− }
109− Method {
110− name: "setFilterFixedString"
111− Parameter { name: "pattern"; type: "string" }
112− }
113− Method { name: "clear" }
114− Method { name: "invalidate" }
115− }
116− Component {
117− name: "UnitySortFilterProxyModelQML"
118− prototype: "QSortFilterProxyModel"
119− Property { name: "model"; type: "QAbstractItemModel"; isPointer: true }
120− Property { name: "totalCount"; type: "int"; isReadonly: true }
121− Property { name: "count"; type: "int"; isReadonly: true }
122− Property { name: "invertMatch"; type: "bool" }
123− Signal {
124− name: "invertMatchChanged"
125− Parameter { type: "bool" }
126− }
127− Method {
128− name: "get"
129− type: "QVariantMap"
130− Parameter { name: "row"; type: "int" }
131− }
132− Method {
133− name: "data"
134− type: "QVariant"
135− Parameter { name: "row"; type: "int" }
136− Parameter { name: "role"; type: "int" }
137− }
138− Method { name: "count"; type: "int" }
139− Method {
140− name: "findFirst"
141− type: "int"
142− Parameter { name: "role"; type: "int" }
143− Parameter { name: "value"; type: "QVariant" }
144− }
145− Method {
146− name: "mapRowToSource"
147− type: "int"
148− Parameter { name: "row"; type: "int" }
149− }
150− Method {
151− name: "mapFromSource"
152− type: "int"
153− Parameter { name: "row"; type: "int" }
154− }
155− Method {
156− name: "mapToSource"
157− type: "int"
158− Parameter { name: "row"; type: "int" }
159− }
160− }
161− Component {
162− name: "UserMetricsOutput::ColorTheme"
163− prototype: "QObject"
164− Property { name: "start"; type: "QColor"; isReadonly: true }
165− Property { name: "main"; type: "QColor"; isReadonly: true }
166− Property { name: "end"; type: "QColor"; isReadonly: true }
167− Signal {
168− name: "startChanged"
169− Parameter { name: "color"; type: "QColor" }
170− }
171− Signal {
172− name: "mainChanged"
173− Parameter { name: "color"; type: "QColor" }
174− }
175− Signal {
176− name: "endChanged"
177− Parameter { name: "color"; type: "QColor" }
178− }
179− }
180− Component {
181− name: "UserMetricsOutput::UserMetrics"
182− prototype: "QObject"
183− exports: ["LightDM/Infographic 0.1"]
184− isCreatable: false
185− isSingleton: true
186− exportMetaObjectRevisions: [0]
187− Property { name: "label"; type: "string"; isReadonly: true }
188− Property { name: "username"; type: "string" }
189− Property {
190− name: "firstColor"
191− type: "UserMetricsOutput::ColorTheme"
192− isReadonly: true
193− isPointer: true
194− }
195− Property {
196− name: "secondColor"
197− type: "UserMetricsOutput::ColorTheme"
198− isReadonly: true
199− isPointer: true
200− }
201− Property { name: "firstMonth"; type: "QAbstractItemModel"; isReadonly: true; isPointer: true }
202− Property { name: "secondMonth"; type: "QAbstractItemModel"; isReadonly: true; isPointer: true }
203− Property { name: "currentDay"; type: "int"; isReadonly: true }
204− Signal {
205− name: "labelChanged"
206− Parameter { name: "label"; type: "string" }
207− }
208− Signal {
209− name: "usernameChanged"
210− Parameter { name: "username"; type: "string" }
211− }
212− Signal {
213− name: "firstColorChanged"
214− Parameter { name: "color"; type: "ColorTheme"; isPointer: true }
215− }
216− Signal {
217− name: "firstMonthChanged"
218− Parameter { name: "firstMonth"; type: "QAbstractItemModel"; isPointer: true }
219− }
220− Signal {
221− name: "currentDayChanged"
222− Parameter { name: "currentDay"; type: "int" }
223− }
224− Signal {
225− name: "secondColorChanged"
226− Parameter { name: "color"; type: "ColorTheme"; isPointer: true }
227− }
228− Signal {
229− name: "secondMonthChanged"
230− Parameter { name: "secondMonth"; type: "QAbstractItemModel"; isPointer: true }
231− }
232− Signal { name: "nextDataSource" }
233− Signal { name: "readyForDataChange" }
234− Signal { name: "dataAboutToAppear" }
235− Signal { name: "dataAppeared" }
236− Signal { name: "dataAboutToChange" }
237− Signal { name: "dataChanged" }
238− Signal { name: "dataAboutToDisappear" }
239− Signal { name: "dataDisappeared" }
240− Method { name: "nextDataSourceSlot" }
241− Method { name: "readyForDataChangeSlot" }
242− }
243− Component {
244− name: "UsersModel"
245− prototype: "UnitySortFilterProxyModelQML"
246− exports: ["LightDM/Users 0.1"]
247− isCreatable: false
248− isSingleton: true
249− exportMetaObjectRevisions: [0]
250− }
251−}
plugins/IntegratedLightDM/UsersModel.cppdeleted−71
@@ -1,71 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Author: Michael Terry <michael.terry@canonical.com>
17− */
18−
19−#include "UsersModel.h"
20−#include <QLightDM/UsersModel>
21−#include <QtCore/QSortFilterProxyModel>
22−
23−// First, we define an internal class that wraps LightDM's UsersModel. This
24−// class will modify some of the data coming from LightDM. For example, we
25−// modify any empty Real Names into just normal Names.
26−// (We can't modify the data directly in UsersModel below because it won't sort
27−// using the modified data.)
28−class MangleModel : public QSortFilterProxyModel
29−{
30− Q_OBJECT
31−
32−public:
33− explicit MangleModel(QObject* parent=0);
34−
35− QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
36−};
37−
38−MangleModel::MangleModel(QObject* parent)
39− : QSortFilterProxyModel(parent)
40−{
41− setSourceModel(new QLightDM::UsersModel(this));
42−}
43−
44−QVariant MangleModel::data(const QModelIndex &index, int role) const
45−{
46− QVariant variantData = QSortFilterProxyModel::data(index, role);
47−
48− // If user's real name is empty, switch to unix name
49− if (role == QLightDM::UsersModel::RealNameRole && variantData.toString().isEmpty()) {
50− variantData = QSortFilterProxyModel::data(index, QLightDM::UsersModel::NameRole);
51− } else if (role == QLightDM::UsersModel::BackgroundPathRole && variantData.toString().startsWith('#')) {
52− const QString stringData = "data:image/svg+xml,<svg><rect width='100%' height='100%' fill='" + variantData.toString() + "'/></svg>";
53− variantData = stringData;
54− }
55−
56− return variantData;
57−}
58−
59−// **** Now we continue with actual UsersModel class ****
60−
61−UsersModel::UsersModel(QObject* parent)
62− : UnitySortFilterProxyModelQML(parent)
63−{
64− setModel(new MangleModel(this));
65− setSortCaseSensitivity(Qt::CaseInsensitive);
66− setSortLocaleAware(true);
67− setSortRole(QLightDM::UsersModel::RealNameRole);
68− sort(0);
69−}
70−
71−#include "UsersModel.moc"
plugins/IntegratedLightDM/liblightdm/CMakeLists.txtdeleted−37
@@ -1,37 +0,0 @@
1−pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
2−
3−set(LibLightDM_SOURCES
4− Greeter.cpp
5− UsersModel.cpp
6− GreeterPrivate.cpp
7− UsersModelPrivate.cpp
8− ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
9− )
10−
11−add_library(integratedLightDM STATIC ${LibLightDM_SOURCES})
12−add_library(MockLightDM-demo-shared SHARED ${LibLightDM_SOURCES})
13−
14−include_directories(
15− ${CMAKE_CURRENT_BINARY_DIR}
16− ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
17−)
18−
19−target_link_libraries(integratedLightDM
20− ${LIBUSERMETRICSOUTPUT_LDFLAGS}
21− -lpam
22−)
23−target_link_libraries(MockLightDM-demo-shared
24− ${LIBUSERMETRICSOUTPUT_LDFLAGS}
25− -lpam
26−)
27−
28−qt5_use_modules(integratedLightDM Concurrent Gui)
29−qt5_use_modules(MockLightDM-demo-shared Concurrent Gui)
30−
31−set_target_properties(integratedLightDM PROPERTIES COMPILE_FLAGS -fPIC)
32−set_target_properties(MockLightDM-demo-shared PROPERTIES
33− OUTPUT_NAME lightdm-qt5-2)
34−
35−install(TARGETS MockLightDM-demo-shared
36− DESTINATION ${SHELL_INSTALL_QML}/mocks/IntegratedLightDM/demo
37− )
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cppdeleted−42
@@ -1,42 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Author: Michael Terry <michael.terry@canonical.com>
17− */
18−
19−#include "UsersModelPrivate.h"
20−
21−#include <QDir>
22−#include <QSettings>
23−#include <QStringList>
24−
25−namespace QLightDM
26−{
27−
28−UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
29− : q_ptr(parent)
30−{
31− QSettings settings(QDir::homePath() + "/.unity8-greeter-demo", QSettings::NativeFormat);
32− QStringList users = settings.value(QStringLiteral("users"), QStringList() << qgetenv("USER")).toStringList();
33−
34− entries.reserve(users.count());
35− Q_FOREACH(const QString &user, users)
36− {
37− QString name = settings.value(user + "/name", user).toString();
38− entries.append({user, name, 0, 0, false, false, 0, 0});
39− }
40−}
41−
42−}
plugins/LightDM/CMakeLists.txtnew file+26
@@ -0,0 +1,26 @@
1+pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
2+
3+find_package(Qt5Core REQUIRED)
4+find_package(Qt5Quick REQUIRED)
5+
6+include_directories(
7+ ${CMAKE_CURRENT_SOURCE_DIR}
8+ ${CMAKE_CURRENT_BINARY_DIR}
9+ ${CMAKE_SOURCE_DIR}/plugins/Utils
10+ ${libunity8-private_SOURCE_DIR}
11+ ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
12+)
13+
14+set(QMLPLUGIN_SRC
15+ ../Utils/unitysortfilterproxymodelqml.cpp
16+ DBusGreeter.cpp
17+ DBusGreeterList.cpp
18+ Greeter.cpp
19+ plugin.cpp
20+ PromptsModel.cpp
21+ SessionsModel.cpp
22+ UsersModel.cpp
23+ )
24+
25+add_subdirectory(FullLightDM)
26+add_subdirectory(IntegratedLightDM)
plugins/IntegratedLightDM/DBusGreeter.cpp → plugins/LightDM/DBusGreeter.cpprenamed+5−4
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014, 2015 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -24,7 +24,8 @@ DBusGreeter::DBusGreeter(Greeter *greeter, const QString &path)
2424 : UnityDBusObject(path, QStringLiteral("com.canonical.UnityGreeter"), true, greeter),
2525 m_greeter(greeter)
2626{
27− connect(m_greeter, &Greeter::isActiveChanged, this, &DBusGreeter::isActiveChangedHandler);
27+ connect(m_greeter, &Greeter::isActiveChanged,
28+ this, &DBusGreeter::isActiveChangedHandler);
2829}
2930
3031bool DBusGreeter::isActive() const
@@ -34,12 +35,12 @@ bool DBusGreeter::isActive() const
3435
3536void DBusGreeter::ShowGreeter()
3637{
37− return Q_EMIT m_greeter->showGreeter();
38+ Q_EMIT m_greeter->showGreeter();
3839}
3940
4041void DBusGreeter::HideGreeter()
4142{
42− return Q_EMIT m_greeter->hideGreeter();
43+ Q_EMIT m_greeter->hideGreeter();
4344}
4445
4546void DBusGreeter::isActiveChangedHandler()
plugins/IntegratedLightDM/DBusGreeter.h → plugins/LightDM/DBusGreeter.hrenamed

The content is the same.

plugins/IntegratedLightDM/DBusGreeterList.cpp → plugins/LightDM/DBusGreeterList.cpprenamed+3−3
@@ -43,10 +43,10 @@ bool DBusGreeterList::entryIsLocked() const
4343 return !m_greeter->promptless();
4444}
4545
46−void DBusGreeterList::authenticationUserChangedHandler(const QString &user)
46+void DBusGreeterList::authenticationUserChangedHandler()
4747{
48− notifyPropertyChanged(QStringLiteral("ActiveEntry"), user);
49− Q_EMIT EntrySelected(user);
48+ notifyPropertyChanged(QStringLiteral("ActiveEntry"), m_greeter->authenticationUser());
49+ Q_EMIT EntrySelected(m_greeter->authenticationUser());
5050}
5151
5252void DBusGreeterList::promptlessChangedHandler()
plugins/IntegratedLightDM/DBusGreeterList.h → plugins/LightDM/DBusGreeterList.hrenamed+1−1
@@ -47,7 +47,7 @@ Q_SIGNALS:
4747 void entryIsLockedChanged();
4848
4949private Q_SLOTS:
50− void authenticationUserChangedHandler(const QString &user);
50+ void authenticationUserChangedHandler();
5151 void promptlessChangedHandler();
5252
5353private:
plugins/LightDM/FullLightDM/CMakeLists.txtnew file+32
@@ -0,0 +1,32 @@
1+pkg_check_modules(LIBLIGHTDM REQUIRED liblightdm-qt5-3)
2+
3+set(PLUGIN_CLASSNAME "FullLightDM")
4+
5+add_definitions(-DFULL_LIGHTDM)
6+
7+include_directories(
8+ ../
9+ ${CMAKE_CURRENT_BINARY_DIR}
10+ )
11+
12+include_directories(
13+ SYSTEM
14+ ${LIBLIGHTDM_INCLUDE_DIRS}
15+ )
16+
17+foreach(source_file ${QMLPLUGIN_SRC})
18+ list(APPEND RELATIVE_QMLPLUGIN_SRC ../${source_file})
19+endforeach()
20+
21+add_library(FullLightDM-qml MODULE
22+ ${RELATIVE_QMLPLUGIN_SRC}
23+ )
24+
25+target_link_libraries(FullLightDM-qml
26+ unity8-private
27+ ${LIBLIGHTDM_LDFLAGS}
28+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
29+ Qt5::DBus Qt5::Gui Qt5::Qml
30+ )
31+
32+add_unity8_plugin(FullLightDM 0.1 LightDM/FullLightDM TARGETS FullLightDM-qml)
plugins/LightDM/FullLightDM/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module LightDM.FullLightDM
2+plugin FullLightDM-qml
3+typeinfo FullLightDM.qmltypes
plugins/LightDM/Greeter.cppnew file+279
@@ -0,0 +1,279 @@
1+/*
2+ * Copyright (C) 2013-2017 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#include "Greeter.h"
19+#include "GreeterPrivate.h"
20+#include <QCoreApplication>
21+#include <libintl.h>
22+
23+static Greeter *singleton = nullptr;
24+
25+GreeterPrivate::GreeterPrivate(Greeter* parent)
26+ : m_greeter(new QLightDM::Greeter(parent)),
27+ m_active(false),
28+ responded(false),
29+ everResponded(false),
30+ promptless(false),
31+ q_ptr(parent)
32+{
33+}
34+
35+Greeter::Greeter(QObject* parent)
36+ : QObject(parent),
37+ d_ptr(new GreeterPrivate(this))
38+{
39+ Q_D(Greeter);
40+
41+ connect(d->m_greeter, &QLightDM::Greeter::showMessage,
42+ this, &Greeter::showMessageFilter);
43+ connect(d->m_greeter, &QLightDM::Greeter::showPrompt,
44+ this, &Greeter::showPromptFilter);
45+ connect(d->m_greeter, &QLightDM::Greeter::authenticationComplete,
46+ this, &Greeter::authenticationCompleteFilter);
47+
48+ // Don't get stuck waiting for PAM as we shut down.
49+ connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
50+ d->m_greeter, &QLightDM::Greeter::cancelAuthentication);
51+
52+ d->m_greeter->connectSync();
53+}
54+
55+Greeter::~Greeter()
56+{
57+ singleton = nullptr;
58+}
59+
60+Greeter *Greeter::instance()
61+{
62+ if (!singleton) {
63+ singleton = new Greeter;
64+ }
65+ return singleton;
66+}
67+
68+PromptsModel *Greeter::promptsModel()
69+{
70+ Q_D(Greeter);
71+ return &d->prompts;
72+}
73+
74+bool Greeter::isActive() const
75+{
76+ Q_D(const Greeter);
77+ return d->m_active;
78+}
79+
80+void Greeter::setIsActive(bool active)
81+{
82+ Q_D(Greeter);
83+ if (d->m_active != active) {
84+ d->m_active = active;
85+ Q_EMIT isActiveChanged();
86+ }
87+}
88+
89+bool Greeter::isAuthenticated() const
90+{
91+ Q_D(const Greeter);
92+ return d->m_greeter->isAuthenticated();
93+}
94+
95+QString Greeter::authenticationUser() const
96+{
97+ Q_D(const Greeter);
98+ return d->cachedAuthUser;
99+}
100+
101+void Greeter::checkAuthenticationUser()
102+{
103+ Q_D(Greeter);
104+ if (d->cachedAuthUser != d->m_greeter->authenticationUser()) {
105+ d->cachedAuthUser = d->m_greeter->authenticationUser();
106+ Q_EMIT authenticationUserChanged();
107+ }
108+}
109+
110+QString Greeter::defaultSessionHint() const
111+{
112+ Q_D(const Greeter);
113+ return d->m_greeter->defaultSessionHint();
114+}
115+
116+bool Greeter::promptless() const
117+{
118+ Q_D(const Greeter);
119+ return d->promptless;
120+}
121+
122+QString Greeter::selectUser() const
123+{
124+ Q_D(const Greeter);
125+ if (hasGuestAccount() && d->m_greeter->selectGuestHint()) {
126+ return QStringLiteral("*guest");
127+ } else {
128+ return d->m_greeter->selectUserHint();
129+ }
130+}
131+
132+bool Greeter::hasGuestAccount() const
133+{
134+ Q_D(const Greeter);
135+ return d->m_greeter->hasGuestAccountHint();
136+}
137+
138+bool Greeter::showManualLoginHint() const
139+{
140+ Q_D(const Greeter);
141+ return d->m_greeter->showManualLoginHint();
142+}
143+
144+bool Greeter::hideUsersHint() const
145+{
146+ Q_D(const Greeter);
147+ return d->m_greeter->hideUsersHint();
148+}
149+
150+void Greeter::authenticate(const QString &username)
151+{
152+ Q_D(Greeter);
153+ d->prompts.clear();
154+ d->responded = false;
155+ d->everResponded = false;
156+ if (d->promptless) {
157+ d->promptless = false;
158+ Q_EMIT promptlessChanged();
159+ }
160+
161+ if (authenticationUser() == username) {
162+ d->prompts = d->leftovers;
163+ }
164+ d->leftovers.clear();
165+
166+ if (username == QStringLiteral("*guest")) {
167+ d->m_greeter->authenticateAsGuest();
168+ } else if (username == QStringLiteral("*other")) {
169+ d->m_greeter->authenticate(nullptr);
170+ } else {
171+ d->m_greeter->authenticate(username);
172+ }
173+
174+ Q_EMIT authenticationStarted();
175+ Q_EMIT isAuthenticatedChanged();
176+ checkAuthenticationUser();
177+}
178+
179+void Greeter::respond(const QString &response)
180+{
181+ Q_D(Greeter);
182+ d->responded = true;
183+ d->everResponded = true;
184+ d->m_greeter->respond(response);
185+}
186+
187+bool Greeter::startSessionSync(const QString &session)
188+{
189+ Q_D(Greeter);
190+ return d->m_greeter->startSessionSync(session);
191+}
192+
193+void Greeter::showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type)
194+{
195+ Q_D(Greeter);
196+
197+ checkAuthenticationUser(); // may have changed in liblightdm
198+
199+ bool isDefaultPrompt = (text == dgettext("Linux-PAM", "Password: "));
200+ bool isSecret = type == QLightDM::Greeter::PromptTypeSecret;
201+
202+ QString trimmedText;
203+ if (!isDefaultPrompt)
204+ trimmedText = text.trimmed();
205+
206+ // Strip prompt of any colons at the end
207+ if (trimmedText.endsWith(':') || trimmedText.endsWith(QStringLiteral(":"))) {
208+ trimmedText.chop(1);
209+ }
210+
211+ if (trimmedText == "login") {
212+ // 'login' is provided untranslated by LightDM when asking for a manual
213+ // login username.
214+ trimmedText = gettext("Username");
215+ }
216+
217+ if (d->responded) {
218+ d->prompts.clear();
219+ d->responded = false;
220+ }
221+
222+ d->prompts.append(trimmedText, isSecret ? PromptsModel::Secret : PromptsModel::Question);
223+}
224+
225+void Greeter::showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type)
226+{
227+ Q_D(Greeter);
228+
229+ checkAuthenticationUser(); // may have changed in liblightdm
230+
231+ bool isError = type == QLightDM::Greeter::MessageTypeError;
232+
233+ if (d->responded) {
234+ d->prompts.clear();
235+ d->responded = false;
236+ }
237+ d->prompts.append(text, isError? PromptsModel::Error : PromptsModel::Message);
238+}
239+
240+void Greeter::authenticationCompleteFilter()
241+{
242+ Q_D(Greeter);
243+
244+ Q_EMIT isAuthenticatedChanged();
245+
246+ bool automatic = !d->everResponded;
247+ bool pamHasLeftoverMessages = !d->prompts.hasPrompt() && d->prompts.rowCount() > 0;
248+
249+ if (isAuthenticated() && automatic) {
250+ d->promptless = true;
251+ Q_EMIT promptlessChanged();
252+ }
253+
254+ if (!isAuthenticated()) {
255+ if (pamHasLeftoverMessages) {
256+ d->leftovers = d->prompts; // Prefer PAM's messages
257+ } else if (automatic) {
258+ d->leftovers.append(gettext("Failed to authenticate"), PromptsModel::Error);
259+ } else {
260+ d->leftovers.append(gettext("Invalid password, please try again"), PromptsModel::Error);
261+ }
262+ } else if (pamHasLeftoverMessages) {
263+ automatic = true; // treat this successful login as automatic, so user sees message
264+ d->leftovers = d->prompts;
265+ }
266+
267+ if (automatic) {
268+ d->prompts = d->leftovers; // OK, we'll just use these now
269+ d->leftovers.clear();
270+ d->prompts.append(isAuthenticated() ? gettext("Log In") : gettext("Retry"),
271+ PromptsModel::Button);
272+ }
273+
274+ if (isAuthenticated()) {
275+ Q_EMIT loginSuccess(automatic);
276+ } else {
277+ Q_EMIT loginError(automatic);
278+ }
279+}
plugins/IntegratedLightDM/Greeter.h → plugins/LightDM/Greeter.hrenamed+21−11
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012,2013 Canonical, Ltd.
2+ * Copyright (C) 2012-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -13,7 +13,6 @@
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 *
16− * Authors: Michael Terry <michael.terry@canonical.com>
1716 */
1817
1918/* This class is a really tiny filter around QLightDM::Greeter. There are some
@@ -22,13 +21,13 @@
2221 such edits in the future, and by inserting ourselves here, we have more
2322 control. */
2423
25−#ifndef UNITY_GREETER_H
26−#define UNITY_GREETER_H
24+#pragma once
2725
2826#include <QLightDM/Greeter>
2927#include <QtCore/QObject>
3028
3129class GreeterPrivate;
30+class PromptsModel;
3231
3332class Greeter : public QObject
3433{
@@ -37,15 +36,25 @@ class Greeter : public QObject
3736 Q_PROPERTY(bool active READ isActive WRITE setIsActive NOTIFY isActiveChanged)
3837 Q_PROPERTY(bool authenticated READ isAuthenticated NOTIFY isAuthenticatedChanged)
3938 Q_PROPERTY(QString authenticationUser READ authenticationUser NOTIFY authenticationUserChanged)
39+ Q_PROPERTY(QString defaultSession READ defaultSessionHint CONSTANT)
4040 Q_PROPERTY(bool promptless READ promptless NOTIFY promptlessChanged)
41+ Q_PROPERTY(QString selectUser READ selectUser CONSTANT)
4142
4243public:
43− explicit Greeter(QObject* parent=0);
44+ static Greeter *instance();
45+ virtual ~Greeter();
4446
4547 bool isActive() const;
4648 bool isAuthenticated() const;
4749 QString authenticationUser() const;
50+ QString defaultSessionHint() const;
4851 bool promptless() const;
52+ QString selectUser() const;
53+ bool hasGuestAccount() const;
54+ bool showManualLoginHint() const;
55+ bool hideUsersHint() const;
56+
57+ PromptsModel *promptsModel();
4958
5059public Q_SLOTS:
5160 void authenticate(const QString &username=QString());
@@ -54,21 +63,23 @@ public Q_SLOTS:
5463 void setIsActive(bool isActive);
5564
5665Q_SIGNALS:
57− void showMessage(const QString &text, bool isError);
58− void showPrompt(const QString &text, bool isSecret, bool isDefaultPrompt);
59− void authenticationComplete();
60− void authenticationUserChanged(const QString &user);
66+ void authenticationUserChanged();
6167 void isActiveChanged();
6268 void isAuthenticatedChanged();
6369 void promptlessChanged();
6470 void showGreeter();
6571 void hideGreeter();
72+ void loginError(bool automatic);
73+ void loginSuccess(bool automatic);
74+ void authenticationStarted(); // useful for testing
6675
6776 // This signal is emitted by external agents like indicators, and the UI
6877 // should switch to this user if possible.
6978 void requestAuthenticationUser(const QString &user);
7079
7180protected:
81+ explicit Greeter(QObject* parent=0);
82+
7283 GreeterPrivate * const d_ptr;
7384
7485 Q_DECLARE_PRIVATE(Greeter)
@@ -77,6 +88,5 @@ private Q_SLOTS:
7788 void showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type);
7889 void showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type);
7990 void authenticationCompleteFilter();
91+ void checkAuthenticationUser();
8092};
81−
82−#endif
plugins/IntegratedLightDM/GreeterPrivate.h → plugins/LightDM/GreeterPrivate.hrenamed+13−7
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2015-2017 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -14,10 +14,14 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#ifndef UNITY_GREETER_PRIVATE_H
18−#define UNITY_GREETER_PRIVATE_H
17+#pragma once
1918
20−#include <QLightDM/Greeter>
19+#include "PromptsModel.h"
20+#include <QObject>
21+
22+namespace QLightDM {
23+ class Greeter;
24+}
2125
2226class GreeterPrivate
2327{
@@ -26,8 +30,12 @@ public:
2630
2731 QLightDM::Greeter *m_greeter;
2832 bool m_active;
29− bool wasPrompted;
33+ PromptsModel prompts;
34+ PromptsModel leftovers; // prompts to show during next auth for same user
35+ bool responded;
36+ bool everResponded;
3037 bool promptless;
38+ QString cachedAuthUser;
3139
3240protected:
3341 Greeter * const q_ptr;
@@ -35,5 +43,3 @@ protected:
3543private:
3644 Q_DECLARE_PUBLIC(Greeter)
3745};
38−
39−#endif // UNITY_GREETER_PRIVATE_H
plugins/LightDM/IntegratedLightDM/CMakeLists.txtnew file+33
@@ -0,0 +1,33 @@
1+set(PLUGIN_CLASSNAME "IntegratedLightDM")
2+
3+add_definitions(-DINTEGRATED_LIGHTDM)
4+
5+foreach(include_directory ${QMLPLUGIN_INCLUDES})
6+ list(APPEND RELATIVE_QMLPLUGIN_INCLUDES ../${include_directory})
7+endforeach()
8+
9+include_directories(
10+ . #QLightDM
11+ ${QMLPLUGIN_INCLUDES}
12+ ${libunity8-private_SOURCE_DIR}
13+ ${CMAKE_CURRENT_BINARY_DIR}
14+)
15+
16+foreach(source_file ${QMLPLUGIN_SRC})
17+ list(APPEND RELATIVE_QMLPLUGIN_SRC ../${source_file})
18+endforeach()
19+
20+add_library(IntegratedLightDM-qml MODULE
21+ ${RELATIVE_QMLPLUGIN_SRC}
22+ )
23+
24+target_link_libraries(IntegratedLightDM-qml
25+ integratedLightDM
26+ unity8-private
27+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
28+ Qt5::DBus Qt5::Gui Qt5::Qml
29+ )
30+
31+add_unity8_plugin(IntegratedLightDM 0.1 LightDM/IntegratedLightDM TARGETS IntegratedLightDM-qml)
32+
33+add_subdirectory(liblightdm)
tests/mocks/IntegratedLightDM/QLightDM/Greeter → plugins/LightDM/IntegratedLightDM/QLightDM/Greeterrenamed+1−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
qml/Components/Circle.qml → plugins/LightDM/IntegratedLightDM/QLightDM/SessionsModelrenamed+2−7
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -14,9 +14,4 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−import QtQuick 2.4
18−
19−Rectangle {
20− antialiasing: true
21− radius: width / 2
22− }
17+#include "../liblightdm/SessionsModel.h"
tests/mocks/IntegratedLightDM/QLightDM/UsersModel → plugins/LightDM/IntegratedLightDM/QLightDM/UsersModelrenamed+1−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
plugins/LightDM/IntegratedLightDM/liblightdm/CMakeLists.txtnew file+54
@@ -0,0 +1,54 @@
1+pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
2+
3+set(LibLightDM_SOURCES
4+ Greeter.cpp
5+ SessionsModel.cpp
6+ UsersModel.cpp
7+ GreeterPrivate.cpp
8+ SessionsModelPrivate.cpp
9+ UsersModelPrivate.cpp
10+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
11+ ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
12+ )
13+
14+add_library(integratedLightDM STATIC ${LibLightDM_SOURCES})
15+add_library(integratedLightDMSession STATIC ${LibLightDM_SOURCES})
16+add_library(MockLightDM-demo-shared SHARED ${LibLightDM_SOURCES})
17+
18+include_directories(
19+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
20+ ${CMAKE_CURRENT_BINARY_DIR}
21+ ${GLIB_INCLUDE_DIRS}
22+ ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
23+)
24+
25+target_link_libraries(integratedLightDM
26+ ${GLIB_LIBRARIES}
27+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
28+ -lpam
29+ Qt5::Concurrent Qt5::DBus Qt5::Gui
30+)
31+target_link_libraries(integratedLightDMSession
32+ ${GLIB_LIBRARIES}
33+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
34+ -lpam
35+ Qt5::Concurrent Qt5::DBus Qt5::Gui
36+)
37+target_link_libraries(MockLightDM-demo-shared
38+ ${GLIB_LIBRARIES}
39+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
40+ -lpam
41+ Qt5::Concurrent Qt5::DBus Qt5::Gui
42+)
43+
44+set_target_properties(integratedLightDM PROPERTIES
45+ COMPILE_FLAGS "-DSM_BUSNAME=systemBus -fPIC")
46+set_target_properties(integratedLightDMSession PROPERTIES
47+ COMPILE_FLAGS "-DSM_BUSNAME=sessionBus -fPIC")
48+set_target_properties(MockLightDM-demo-shared PROPERTIES
49+ COMPILE_FLAGS "-DSM_BUSNAME=systemBus"
50+ OUTPUT_NAME lightdm-qt5-3)
51+
52+install(TARGETS MockLightDM-demo-shared
53+ DESTINATION ${SHELL_INSTALL_QML}/mocks/LightDM/IntegratedLightDM/demo
54+ )
plugins/IntegratedLightDM/liblightdm/Greeter.cpp → plugins/LightDM/IntegratedLightDM/liblightdm/Greeter.cpprenamed+6−8
@@ -49,7 +49,7 @@ QString Greeter::authenticationUser() const
4949
5050bool Greeter::hasGuestAccountHint() const
5151{
52− return true;
52+ return false;
5353}
5454
5555QString Greeter::getHint(const QString &name) const
@@ -70,15 +70,10 @@ bool Greeter::hideUsersHint() const
7070
7171bool Greeter::showManualLoginHint() const
7272{
73− return true;
73+ return false;
7474}
7575
7676bool Greeter::showRemoteLoginHint() const
77−{
78− return true;
79−}
80−
81−bool Greeter::lockHint () const
8277{
8378 return false;
8479}
@@ -151,7 +146,10 @@ void Greeter::authenticateRemote(const QString &session, const QString &username
151146}
152147
153148void Greeter::cancelAuthentication()
154−{}
149+{
150+ Q_D(Greeter);
151+ d->cancelAuthentication();
152+}
155153
156154void Greeter::setLanguage (const QString &language)
157155{
plugins/IntegratedLightDM/liblightdm/Greeter.h → plugins/LightDM/IntegratedLightDM/liblightdm/Greeter.hrenamed+2−4
@@ -45,20 +45,19 @@ class Q_DECL_EXPORT Greeter : public QObject
4545
4646 Q_PROPERTY(QString hostname READ hostname CONSTANT)
4747 Q_PROPERTY(bool hasGuestAccount READ hasGuestAccountHint CONSTANT)
48− Q_PROPERTY(bool locked READ lockHint CONSTANT)
49−
50− Q_ENUMS(PromptType MessageType)
5148
5249public:
5350 enum PromptType {
5451 PromptTypeQuestion,
5552 PromptTypeSecret
5653 };
54+ Q_ENUM(PromptType)
5755
5856 enum MessageType {
5957 MessageTypeInfo,
6058 MessageTypeError
6159 };
60+ Q_ENUM(MessageType)
6261
6362 explicit Greeter(QObject* parent=0);
6463 virtual ~Greeter();
@@ -68,7 +67,6 @@ public:
6867 bool hideUsersHint() const;
6968 bool showManualLoginHint() const;
7069 bool showRemoteLoginHint() const;
71− bool lockHint () const;
7270 bool hasGuestAccountHint() const;
7371 QString selectUserHint() const;
7472 bool selectGuestHint() const;
plugins/IntegratedLightDM/liblightdm/GreeterPrivate.cpp → plugins/LightDM/IntegratedLightDM/liblightdm/GreeterPrivate.cpprenamed+28−24
@@ -50,8 +50,7 @@ public:
5050 {
5151 qRegisterMetaType<QLightDM::GreeterImpl::ResponseFuture>("QLightDM::GreeterImpl::ResponseFuture");
5252
53− connect(&futureWatcher, &QFutureWatcher<int>::finished,
54− this, &GreeterImpl::finishPam);
53+ connect(&futureWatcher, &QFutureWatcher<int>::finished, this, &GreeterImpl::finishPam);
5554 connect(this, SIGNAL(showMessage(pam_handle *, QString, QLightDM::Greeter::MessageType)),
5655 this, SLOT(handleMessage(pam_handle *, QString, QLightDM::Greeter::MessageType)));
5756 // This next connect is how we pass ResponseFutures between threads
@@ -207,6 +206,28 @@ public Q_SLOTS:
207206 }
208207 }
209208
209+ void cancelPam()
210+ {
211+ if (pamHandle != nullptr) {
212+ QFuture<int> pamFuture = futureWatcher.future();
213+ pam_handle *handle = pamHandle;
214+ pamHandle = nullptr; // to disable normal finishPam() handling
215+ pamFuture.cancel();
216+
217+ // Note the empty loop, we just want to clear the futures queue.
218+ // Any further prompts from the pam thread will be immediately
219+ // responded to/dismissed in handlePrompt().
220+ while (respond(QString()));
221+
222+ // Now let signal/slot handling happen so the thread can finish
223+ while (!pamFuture.isFinished()) {
224+ QCoreApplication::processEvents();
225+ }
226+
227+ pam_end(handle, PAM_CONV_ERR);
228+ }
229+ }
230+
210231Q_SIGNALS:
211232 void showMessage(pam_handle *handle, QString text, QLightDM::Greeter::MessageType type);
212233 void showPrompt(pam_handle *handle, QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture response);
@@ -248,28 +269,6 @@ private Q_SLOTS:
248269 }
249270
250271private:
251− void cancelPam()
252− {
253− if (pamHandle != nullptr) {
254− QFuture<int> pamFuture = futureWatcher.future();
255− pam_handle *handle = pamHandle;
256− pamHandle = nullptr; // to disable normal finishPam() handling
257− pamFuture.cancel();
258−
259− // Note the empty loop, we just want to clear the futures queue.
260− // Any further prompts from the pam thread will be immediately
261− // responded to/dismissed in handlePrompt().
262− while (respond(QString()));
263−
264− // Now let signal/slot handling happen so the thread can finish
265− while (!pamFuture.isFinished()) {
266− QCoreApplication::processEvents();
267− }
268−
269− pam_end(handle, PAM_CONV_ERR);
270− }
271− }
272−
273272 Greeter *greeter;
274273 GreeterPrivate *greeterPrivate;
275274 pam_handle* pamHandle;
@@ -300,6 +299,11 @@ void GreeterPrivate::handleRespond(const QString &response)
300299 m_impl->respond(response);
301300}
302301
302+void GreeterPrivate::cancelAuthentication()
303+{
304+ m_impl->cancelPam();
305+}
306+
303307}
304308
305309#include "GreeterPrivate.moc"
plugins/IntegratedLightDM/liblightdm/GreeterPrivate.h → plugins/LightDM/IntegratedLightDM/liblightdm/GreeterPrivate.hrenamed+1
@@ -38,6 +38,7 @@ public:
3838
3939 void handleAuthenticate();
4040 void handleRespond(const QString &response);
41+ void cancelAuthentication();
4142
4243protected:
4344 GreeterImpl *m_impl; // if the backend needs more private data
plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModel.cppnew file+87
@@ -0,0 +1,87 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+
19+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20+ * CHANGES MADE HERE MUST BE REFLECTED ON THE MOCK LIB
21+ * COUNTERPART IN tests/mocks/LightDM/IntegratedLightDM/liblightdm
22+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
23+
24+// LightDM currently is Qt4 compatible, and so doesn't define setRoleNames.
25+// To use the same method of setting role name that it does, we
26+// set our compatibility to Qt4 here too.
27+#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(4, 0, 0)
28+
29+#include "SessionsModel.h"
30+#include "SessionsModelPrivate.h"
31+#include <QtCore/QDir>
32+#include <QtCore/QString>
33+
34+namespace QLightDM
35+{
36+
37+SessionsModel::SessionsModel(QObject* parent) :
38+ QAbstractListModel(parent),
39+ d_ptr(new SessionsModelPrivate(this))
40+{
41+ m_roleNames = QAbstractListModel::roleNames();
42+ m_roleNames[KeyRole] = "key";
43+ m_roleNames[TypeRole] = "type";
44+}
45+
46+SessionsModel::~SessionsModel()
47+{
48+ delete d_ptr;
49+}
50+
51+QVariant SessionsModel::data(const QModelIndex& index, int role) const
52+{
53+ Q_D(const SessionsModel);
54+
55+ if(!index.isValid()) {
56+ return QVariant();
57+ }
58+
59+ int row = index.row();
60+
61+ switch (role) {
62+ case QLightDM::SessionsModel::KeyRole:
63+ return d->sessionItems[row].key;
64+ case Qt::DisplayRole:
65+ return d->sessionItems[row].name;
66+ default:
67+ return QVariant();
68+ }
69+}
70+
71+QHash<int, QByteArray> SessionsModel::roleNames() const
72+{
73+ return m_roleNames;
74+}
75+
76+int SessionsModel::rowCount(const QModelIndex& parent) const
77+{
78+ Q_D(const SessionsModel);
79+
80+ if (parent.isValid()) {
81+ return 0;
82+ } else { // parent is root
83+ return d->sessionItems.size();
84+ }
85+}
86+
87+} // namespace QLightDM
plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModel.hnew file+72
@@ -0,0 +1,72 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#ifndef UNITY_INTEGRATED_SESSIONSMODEL_H
19+#define UNITY_INTEGRATED_SESSIONSMODEL_H
20+
21+#include <QtCore/QAbstractListModel>
22+#include <QtCore/QString>
23+
24+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
25+ * CHANGES MADE HERE MUST BE REFLECTED ON THE MOCK LIB
26+ * COUNTERPART IN tests/mocks/LightDM/IntegratedLightDM/liblightdm
27+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
28+
29+// This is taken from liblightdm and modified to confirm to our syle conventions
30+namespace QLightDM
31+{
32+class SessionsModelPrivate;
33+
34+class Q_DECL_EXPORT SessionsModel : public QAbstractListModel
35+ {
36+ Q_OBJECT
37+
38+ public:
39+
40+ enum SessionModelRoles {
41+ //name is exposed as Qt::DisplayRole
42+ //comment is exposed as Qt::TooltipRole
43+ KeyRole = Qt::UserRole,
44+ IdRole = KeyRole, /** Deprecated */
45+ TypeRole
46+ };
47+ Q_ENUM(SessionModelRoles)
48+
49+ enum SessionType {
50+ LocalSessions,
51+ RemoteSessions
52+ };
53+ Q_ENUM(SessionType)
54+
55+ explicit SessionsModel(QObject* parent=0); /** Deprecated. Loads local sessions*/
56+ explicit SessionsModel(SessionsModel::SessionType, QObject* parent=0);
57+ virtual ~SessionsModel();
58+
59+ QHash<int, QByteArray> roleNames() const override;
60+ int rowCount(const QModelIndex& parent) const override;
61+ QVariant data(const QModelIndex& index, int role) const override;
62+
63+ protected:
64+ SessionsModelPrivate* const d_ptr;
65+
66+ private:
67+ QHash<int, QByteArray> m_roleNames;
68+ Q_DECLARE_PRIVATE(SessionsModel)
69+ };
70+}
71+
72+#endif // UNITY_INTEGRATED_SESSIONSMODEL_H
plugins/Utils/windowscreenshotprovider.h → plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModelPrivate.cpprenamed+15−10
@@ -12,20 +12,25 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
1516 */
1617
17−#ifndef WINDOW_SCREENSHOT_PROVIDER_H_
18−#define WINDOW_SCREENSHOT_PROVIDER_H_
18+#include "SessionsModelPrivate.h"
1919
20−#include <QQuickImageProvider>
20+#include <QDir>
21+#include <QSettings>
22+#include <QStringList>
2123
22−class WindowScreenshotProvider : public QQuickImageProvider
24+namespace QLightDM
2325{
24−public:
25− WindowScreenshotProvider();
2626
27− // id is ignored for now
28− QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
29−};
27+SessionsModelPrivate::SessionsModelPrivate(SessionsModel* parent)
28+ : q_ptr(parent)
29+{
30+ // Since this model is never visible, as there is only 1 session,
31+ // just use the session name as the key
32+ QString sessionName = qgetenv("XDG_SESSION_DESKTOP");
33+ sessionItems.append({sessionName, "", sessionName, ""});
34+}
3035
31−#endif // WINDOW_SCREENSHOT_PROVIDER_H_
36+} // namespace QLightDM
plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModelPrivate.hnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#ifndef UNITY_INTEGRATED_SESSIONSMODEL_PRIVATE_H
19+#define UNITY_INTEGRATED_SESSIONSMODEL_PRIVATE_H
20+
21+#include <QtCore/QList>
22+#include <QtCore/QString>
23+
24+namespace QLightDM
25+{
26+class SessionsModel;
27+
28+class SessionItem
29+{
30+public:
31+ QString key;
32+ QString type; // unused
33+ QString name;
34+ QString comment; // unused
35+};
36+
37+class SessionsModelPrivate
38+{
39+public:
40+ explicit SessionsModelPrivate(SessionsModel* parent=0);
41+ virtual ~SessionsModelPrivate() = default;
42+
43+ QList<SessionItem> sessionItems;
44+
45+protected:
46+ SessionsModel* const q_ptr;
47+
48+private:
49+ Q_DECLARE_PUBLIC(SessionsModel)
50+};
51+
52+} // namespace QLightDM
53+
54+#endif // UNITY_INTEGRATED_SESSIONSMODEL_PRIVATE_H
plugins/IntegratedLightDM/liblightdm/UsersModel.cpp → plugins/LightDM/IntegratedLightDM/liblightdm/UsersModel.cpprenamed+8−21
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -40,8 +40,6 @@ UsersModel::UsersModel(QObject *parent) :
4040 QAbstractListModel(parent),
4141 d_ptr(new UsersModelPrivate(this))
4242{
43− Q_D(UsersModel);
44−
4543 // Extend roleNames (we want to keep the "display" role)
4644 QHash<int, QByteArray> roles = roleNames();
4745 roles[NameRole] = "name";
@@ -52,26 +50,13 @@ UsersModel::UsersModel(QObject *parent) :
5250 roles[SessionRole] = "session";
5351 roles[HasMessagesRole] = "hasMessages";
5452 roles[ImagePathRole] = "imagePath";
53+ roles[UidRole] = "uid";
5554 setRoleNames(roles);
5655
57− // Now modify our mock user backgrounds
58− QDir bgdir = QDir(QStringLiteral("/usr/share/demo-assets/shell/backgrounds/"));
59− QStringList backgrounds = bgdir.entryList(QDir::Files | QDir::NoDotAndDotDot);
60−
61− for (int i = 0, j = 0; i < d->entries.size(); i++) {
62− Entry &entry = d->entries[i];
63− if (entry.background.isNull() && !backgrounds.isEmpty()) {
64− entry.background = bgdir.filePath(backgrounds[j++]);
65− if (j >= backgrounds.length()) {
66− j = 0;
67− }
68− }
69− }
70−}
71−
72−UsersModel::~UsersModel()
73−{
74− delete d_ptr;
56+ connect(d_ptr, &UsersModelPrivate::dataChanged, this, [this](int i) {
57+ QModelIndex index = createIndex(i, 0);
58+ Q_EMIT dataChanged(index, index);
59+ });
7560}
7661
7762int UsersModel::rowCount(const QModelIndex &parent) const
@@ -115,6 +100,8 @@ QVariant UsersModel::data(const QModelIndex &index, int role) const
115100 return d->entries[row].has_messages;
116101 case UsersModel::ImagePathRole:
117102 return "";
103+ case UsersModel::UidRole:
104+ return d->entries[row].uid;
118105 default:
119106 return QVariant();
120107 }
plugins/IntegratedLightDM/liblightdm/UsersModel.h → plugins/LightDM/IntegratedLightDM/liblightdm/UsersModel.hrenamed+4−4
@@ -37,11 +37,9 @@ class Q_DECL_EXPORT UsersModel : public QAbstractListModel
3737{
3838 Q_OBJECT
3939
40− Q_ENUMS(UserModelRoles)
41−
4240public:
4341 explicit UsersModel(QObject *parent = 0);
44− virtual ~UsersModel();
42+ virtual ~UsersModel() = default;
4543
4644 enum UserModelRoles {NameRole = Qt::UserRole,
4745 RealNameRole,
@@ -50,8 +48,10 @@ public:
5048 SessionRole,
5149 HasMessagesRole,
5250 ImagePathRole,
53− BackgroundPathRole
51+ BackgroundPathRole,
52+ UidRole
5453 };
54+ Q_ENUM(UserModelRoles)
5555
5656 int rowCount(const QModelIndex &parent) const override;
5757 QVariant data(const QModelIndex &index, int role) const override;
plugins/LightDM/IntegratedLightDM/liblightdm/UsersModelPrivate.cppnew file+94
@@ -0,0 +1,94 @@
1+/*
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "UsersModelPrivate.h"
20+
21+#include "AccountsServiceDBusAdaptor.h"
22+#include "UsersModel.h"
23+
24+#include <glib.h>
25+#include <QDebug>
26+#include <QDir>
27+#include <QSettings>
28+#include <QStringList>
29+#include <unistd.h>
30+
31+namespace QLightDM
32+{
33+
34+UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
35+ : QObject(parent),
36+ q_ptr(parent),
37+ m_service(new AccountsServiceDBusAdaptor(this))
38+{
39+ QFileInfo demoFile(QDir::homePath() + "/.unity8-greeter-demo");
40+ QString currentUser = g_get_user_name();
41+ uid_t currentUid = getuid();
42+
43+ if (demoFile.exists()) {
44+ QSettings settings(demoFile.filePath(), QSettings::NativeFormat);
45+ QStringList users = settings.value(QStringLiteral("users"), QStringList() << currentUser).toStringList();
46+
47+ entries.reserve(users.count());
48+ Q_FOREACH(const QString &user, users)
49+ {
50+ QString name = settings.value(user + "/name", user).toString();
51+ entries.append({user, name, 0, 0, false, false, 0, 0, currentUid++});
52+ }
53+ } else {
54+ entries.append({currentUser, 0, 0, 0, false, false, 0, 0, currentUid});
55+
56+ connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
57+ this, [this](const QString &user) {
58+ if (user == entries[0].username) {
59+ updateName(true);
60+ }
61+ });
62+ updateName(false);
63+ }
64+}
65+
66+void UsersModelPrivate::updateName(bool async)
67+{
68+ auto pendingReply = m_service->getUserPropertyAsync(entries[0].username,
69+ QStringLiteral("org.freedesktop.Accounts.User"),
70+ QStringLiteral("RealName"));
71+ auto *watcher = new QDBusPendingCallWatcher(pendingReply, this);
72+
73+ connect(watcher, &QDBusPendingCallWatcher::finished,
74+ this, [this](QDBusPendingCallWatcher* watcher) {
75+
76+ QDBusPendingReply<QVariant> reply = *watcher;
77+ watcher->deleteLater();
78+ if (reply.isError()) {
79+ qWarning() << "Failed to get 'RealName' property - " << reply.error().message();
80+ return;
81+ }
82+
83+ const QString realName = reply.value().toString();
84+ if (entries[0].real_name != realName) {
85+ entries[0].real_name = realName;
86+ Q_EMIT dataChanged(0);
87+ }
88+ });
89+ if (!async) {
90+ watcher->waitForFinished();
91+ }
92+}
93+
94+}
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h → plugins/LightDM/IntegratedLightDM/liblightdm/UsersModelPrivate.hrenamed+17−4
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -19,8 +19,11 @@
1919#ifndef UNITY_MOCK_USERSMODEL_PRIVATE_H
2020#define UNITY_MOCK_USERSMODEL_PRIVATE_H
2121
22−#include <QtCore/QList>
23−#include <QtCore/QString>
22+#include <QList>
23+#include <QObject>
24+#include <QString>
25+
26+class AccountsServiceDBusAdaptor;
2427
2528namespace QLightDM
2629{
@@ -37,21 +40,31 @@ public:
3740 bool has_messages;
3841 QString session;
3942 QString infographic;
43+ uid_t uid;
4044};
4145
42−class UsersModelPrivate
46+class UsersModelPrivate : public QObject
4347{
48+ Q_OBJECT
49+
4450public:
4551 explicit UsersModelPrivate(UsersModel *parent = 0);
4652 virtual ~UsersModelPrivate() = default;
4753
4854 QList<Entry> entries;
4955
56+Q_SIGNALS:
57+ void dataChanged(int);
58+
5059protected:
5160 UsersModel * const q_ptr;
5261
5362private:
5463 Q_DECLARE_PUBLIC(UsersModel)
64+
65+ void updateName(bool async);
66+
67+ AccountsServiceDBusAdaptor *m_service;
5568};
5669
5770}
plugins/LightDM/IntegratedLightDM/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module LightDM.IntegratedLightDM
2+plugin IntegratedLightDM-qml
3+typeinfo IntegratedLightDM.qmltypes
plugins/LightDM/PromptsModel.cppnew file+97
@@ -0,0 +1,97 @@
1+/*
2+ * Copyright (C) 2017 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#include "PromptsModel.h"
19+
20+PromptsModel::PromptsModel(QObject* parent)
21+ : QAbstractListModel(parent)
22+{
23+ m_roleNames[TypeRole] = "type";
24+ m_roleNames[TextRole] = "text";
25+}
26+
27+PromptsModel& PromptsModel::operator=(const PromptsModel &other)
28+{
29+ beginResetModel();
30+ m_prompts = other.m_prompts;
31+ endResetModel();
32+ Q_EMIT countChanged();
33+ return *this;
34+}
35+
36+int PromptsModel::rowCount(const QModelIndex &parent) const
37+{
38+ if (parent.isValid())
39+ return 0;
40+
41+ return m_prompts.size();
42+}
43+
44+QVariant PromptsModel::data(const QModelIndex &index, int role) const
45+{
46+ if (!index.isValid() || index.column() > 0 || index.row() >= m_prompts.size())
47+ return QVariant();
48+
49+ switch (role) {
50+ case Qt::DisplayRole: // fallthrough
51+ case TextRole: return m_prompts[index.row()].prompt;
52+ case TypeRole: return m_prompts[index.row()].type;
53+ default: return QVariant();
54+ }
55+}
56+
57+QHash<int, QByteArray> PromptsModel::roleNames() const
58+{
59+ return m_roleNames;
60+}
61+
62+void PromptsModel::prepend(const QString &text, PromptType type)
63+{
64+ beginInsertRows(QModelIndex(), 0, 0);
65+ m_prompts.prepend(PromptInfo{text, type});
66+ endInsertRows();
67+
68+ Q_EMIT countChanged();
69+}
70+
71+void PromptsModel::append(const QString &text, PromptType type)
72+{
73+ beginInsertRows(QModelIndex(), m_prompts.size(), m_prompts.size());
74+ m_prompts.append(PromptInfo{text, type});
75+ endInsertRows();
76+
77+ Q_EMIT countChanged();
78+}
79+
80+void PromptsModel::clear()
81+{
82+ beginResetModel();
83+ m_prompts.clear();
84+ endResetModel();
85+
86+ Q_EMIT countChanged();
87+}
88+
89+bool PromptsModel::hasPrompt() const
90+{
91+ Q_FOREACH(const PromptInfo &info, m_prompts) {
92+ if (info.type == PromptType::Secret || info.type == PromptType::Question) {
93+ return true;
94+ }
95+ }
96+ return false;
97+}
plugins/LightDM/PromptsModel.hnew file+70
@@ -0,0 +1,70 @@
1+/*
2+ * Copyright (C) 2017 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#pragma once
19+
20+#include <QAbstractListModel>
21+
22+class PromptsModel : public QAbstractListModel
23+{
24+ Q_OBJECT
25+
26+ Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
27+
28+public:
29+ enum PromptsModelRoles {
30+ TypeRole = Qt::UserRole,
31+ TextRole,
32+ };
33+ Q_ENUM(PromptsModelRoles)
34+
35+ enum PromptType {
36+ Message,
37+ Error,
38+ Secret,
39+ Question,
40+ Button,
41+ };
42+ Q_ENUM(PromptType)
43+
44+ explicit PromptsModel(QObject* parent=0);
45+
46+ PromptsModel& operator=(const PromptsModel &other);
47+
48+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
49+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
50+ QHash<int, QByteArray> roleNames() const override;
51+
52+ Q_INVOKABLE void prepend(const QString &text, PromptType type);
53+ Q_INVOKABLE void append(const QString &text, PromptType type);
54+
55+ void clear();
56+
57+ bool hasPrompt() const;
58+
59+Q_SIGNALS:
60+ void countChanged();
61+
62+private:
63+ struct PromptInfo {
64+ QString prompt;
65+ PromptType type;
66+ };
67+
68+ QList<PromptInfo> m_prompts;
69+ QHash<int, QByteArray> m_roleNames;
70+};
plugins/LightDM/SessionsModel.cppnew file+135
@@ -0,0 +1,135 @@
1+/*
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#include "SessionsModel.h"
19+#include <QtCore/QFile>
20+#include <QtCore/QSortFilterProxyModel>
21+
22+QHash<int, QByteArray> SessionsModel::roleNames() const
23+{
24+ return m_roleNames;
25+}
26+
27+int SessionsModel::rowCount(const QModelIndex& parent) const
28+{
29+ return m_model->rowCount(parent);
30+}
31+
32+QList<QUrl> SessionsModel::iconSearchDirectories() const
33+{
34+ return m_iconSearchDirectories;
35+}
36+
37+void SessionsModel::setIconSearchDirectories(const QList<QUrl> searchDirectories)
38+{
39+ // QML gives us a url with file:// prepended which breaks QFile::exists()
40+ // so convert the url to a local file
41+ QList<QUrl> localList = {};
42+ Q_FOREACH(const QUrl& searchDirectory, searchDirectories)
43+ {
44+ localList.append(searchDirectory.toLocalFile());
45+ }
46+ m_iconSearchDirectories = localList;
47+ Q_EMIT iconSearchDirectoriesChanged();
48+}
49+
50+QUrl SessionsModel::iconUrl(const QString sessionKey) const
51+{
52+ Q_FOREACH(const QUrl& searchDirectory, m_iconSearchDirectories)
53+ {
54+ // This is an established icon naming convention
55+ QString customIconUrl = searchDirectory.toString(QUrl::StripTrailingSlash) +
56+ "/custom_" + sessionKey + "_badge.png";
57+ QString iconUrl = searchDirectory.toString(QUrl::StripTrailingSlash) +
58+ "/" + sessionKey + "_badge.png";
59+
60+ QFile customIconFile(customIconUrl);
61+ QFile iconFile(iconUrl);
62+ if (customIconFile.exists()) {
63+ return QUrl(customIconUrl);
64+ } else if (iconFile.exists()) {
65+ return QUrl(iconUrl);
66+ } else {
67+ // Search the legacy way
68+ QString path = searchDirectory.toString(QUrl::StripTrailingSlash) + "/";
69+ bool iconFound = false;
70+ if (sessionKey == "ubuntu" || sessionKey == "ubuntu-2d") {
71+ path += "ubuntu_badge.png";
72+ iconFound = true;
73+ } else if(
74+ sessionKey == "gnome-classic" ||
75+ sessionKey == "gnome-flashback-compiz" ||
76+ sessionKey == "gnome-flashback-metacity" ||
77+ sessionKey == "gnome-shell" ||
78+ sessionKey == "gnome-wayland" ||
79+ sessionKey == "gnome"
80+ ){
81+ path += "gnome_badge.png";
82+ iconFound = true;
83+ } else if (sessionKey == "plasma") {
84+ path += "kde_badge.png";
85+ iconFound = true;
86+ } else if (sessionKey == "xterm") {
87+ path += "recovery_console_badge.png";
88+ iconFound = true;
89+ } else if (sessionKey == "remote-login") {
90+ path += "remote_login_help.png";
91+ iconFound = true;
92+ }
93+
94+ if (QFile(path).exists() && iconFound) {
95+ return path;
96+ }
97+ }
98+ }
99+
100+ // FIXME make this smarter
101+ return QUrl("./graphics/session_icons/unknown_badge.png");
102+}
103+
104+QVariant SessionsModel::data(const QModelIndex& index, int role) const
105+{
106+ switch (role) {
107+ case SessionsModel::IconRole:
108+ return iconUrl(m_model->data(index, QLightDM::SessionsModel::KeyRole).toString());
109+ default:
110+ return m_model->data(index, role);
111+ }
112+}
113+
114+SessionsModel::SessionsModel(QObject* parent)
115+ : UnitySortFilterProxyModelQML(parent)
116+{
117+ // Add a custom IconRole that isn't in either of the lightdm implementations
118+ m_model = new QLightDM::SessionsModel(this);
119+ m_roleNames = m_model->roleNames();
120+ m_roleNames[IconRole] = "icon_url";
121+
122+ // Update search locations to use $SNAP prefix if specified
123+ auto snapRoot = QFile::decodeName(qgetenv("SNAP"));
124+ if (!snapRoot.isEmpty()) {
125+ for (int i = 0; i < m_iconSearchDirectories.size(); i++) {
126+ m_iconSearchDirectories[i] = snapRoot + m_iconSearchDirectories[i].path();
127+ }
128+ }
129+
130+ setModel(m_model);
131+ setSortCaseSensitivity(Qt::CaseInsensitive);
132+ setSortLocaleAware(true);
133+ setSortRole(Qt::DisplayRole);
134+ sort(0);
135+}
plugins/LightDM/SessionsModel.hnew file+66
@@ -0,0 +1,66 @@
1+/*
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#pragma once
19+
20+#include <unitysortfilterproxymodelqml.h>
21+#include <QLightDM/SessionsModel>
22+#include <QtCore/QHash>
23+#include <QtCore/QObject>
24+#include <QtCore/QUrl>
25+
26+class SessionsModel : public UnitySortFilterProxyModelQML
27+{
28+ Q_OBJECT
29+
30+ Q_PROPERTY(QList<QUrl> iconSearchDirectories READ iconSearchDirectories
31+ WRITE setIconSearchDirectories NOTIFY iconSearchDirectoriesChanged)
32+
33+Q_SIGNALS:
34+ void iconSearchDirectoriesChanged();
35+
36+public:
37+ enum SessionModelRoles {
38+ /* This is tricky / ugly. Since we are ultimately chaining 3 enums together,
39+ * the _first_ value of this enum MUST be the _last_ value of
40+ * QLightDM::SessionsModel::SessionModelRoles and consquently, this must
41+ * also match the last value in the corresponding enum of the integrated lib
42+ */
43+ TypeRole = QLightDM::SessionsModel::SessionModelRoles::TypeRole,
44+ IconRole
45+ };
46+ Q_ENUM(SessionModelRoles)
47+
48+ explicit SessionsModel(QObject* parent=nullptr);
49+
50+ QHash<int, QByteArray> roleNames() const override;
51+ int rowCount(const QModelIndex& parent) const override;
52+ QVariant data(const QModelIndex& index, int role) const override;
53+ QList<QUrl> iconSearchDirectories() const;
54+ Q_INVOKABLE QUrl iconUrl(const QString sessionName) const;
55+
56+ void setIconSearchDirectories(const QList<QUrl> searchDirectories);
57+
58+private:
59+ QLightDM::SessionsModel* m_model;
60+ QHash<int, QByteArray> m_roleNames;
61+ QList<QUrl> m_iconSearchDirectories{
62+ QUrl("/usr/share/unity8/Greeter/graphics/session_icons"),
63+ QUrl("/usr/local/share/unity-greeter"),
64+ QUrl("/usr/share/unity-greeter/")};
65+
66+};
plugins/LightDM/UsersModel.cppnew file+238
@@ -0,0 +1,238 @@
1+/*
2+ * Copyright (C) 2013,2015-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "Greeter.h"
18+#include "UsersModel.h"
19+#include <QIdentityProxyModel>
20+#include <QLightDM/UsersModel>
21+
22+#include <libintl.h>
23+
24+// First, we define an internal class that wraps LightDM's UsersModel. This
25+// class will modify some of the data coming from LightDM. For example, we
26+// modify any empty Real Names into just normal Names. We also add optional
27+// rows, depending on configuration.
28+// (We can't modify the data directly in UsersModel below because it won't sort
29+// using the modified data.)
30+class MangleModel : public QIdentityProxyModel
31+{
32+ Q_OBJECT
33+
34+public:
35+ explicit MangleModel(QObject* parent=0);
36+
37+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
38+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
39+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
40+
41+private:
42+ struct CustomRow {
43+ QString name;
44+ QString realName;
45+ };
46+
47+ int sourceRowCount() const;
48+
49+ void updateGuestRow();
50+ void updateManualRow();
51+ void updateCustomRows();
52+
53+ void addCustomRow(const CustomRow &newRow);
54+ void removeCustomRow(const QString &rowName);
55+
56+ QList<CustomRow> m_customRows;
57+ bool m_updatingCustomRows;
58+};
59+
60+MangleModel::MangleModel(QObject* parent)
61+ : QIdentityProxyModel(parent)
62+ , m_updatingCustomRows(false)
63+{
64+ setSourceModel(new QLightDM::UsersModel(this));
65+
66+ updateCustomRows();
67+
68+ // Would be nice if there were a rowCountChanged signal in the base class.
69+ // We redo all custom rows on any row count change, because (A) some of
70+ // custom rows (manual login) use row count information and (B) when
71+ // testing, we use a modelReset signal as a way to indicate that a custom
72+ // row has been toggled off or on.
73+ connect(this, &QIdentityProxyModel::modelReset,
74+ this, &MangleModel::updateCustomRows);
75+ connect(this, &QIdentityProxyModel::rowsInserted,
76+ this, &MangleModel::updateCustomRows);
77+ connect(this, &QIdentityProxyModel::rowsRemoved,
78+ this, &MangleModel::updateCustomRows);
79+}
80+
81+QVariant MangleModel::data(const QModelIndex &index, int role) const
82+{
83+ QVariant variantData;
84+
85+ if (index.row() >= rowCount())
86+ return QVariant();
87+
88+ bool isCustomRow = index.row() >= sourceRowCount();
89+ if (isCustomRow && index.column() == 0) {
90+ int customIndex = index.row() - sourceRowCount();
91+ if (role == QLightDM::UsersModel::NameRole) {
92+ variantData = m_customRows[customIndex].name;
93+ } else if (role == QLightDM::UsersModel::RealNameRole) {
94+ variantData = m_customRows[customIndex].realName;
95+ } else if (role == QLightDM::UsersModel::LoggedInRole) {
96+ variantData = false;
97+ } else if (role == QLightDM::UsersModel::SessionRole) {
98+ variantData = Greeter::instance()->defaultSessionHint();
99+ }
100+ } else {
101+ variantData = QIdentityProxyModel::data(index, role);
102+ }
103+
104+ // If user's real name is empty, switch to unix name
105+ if (role == QLightDM::UsersModel::RealNameRole && variantData.toString().isEmpty()) {
106+ variantData = data(index, QLightDM::UsersModel::NameRole);
107+ } else if (role == QLightDM::UsersModel::BackgroundPathRole && variantData.toString().startsWith('#')) {
108+ const QString stringData = "data:image/svg+xml,<svg><rect width='100%' height='100%' fill='" + variantData.toString() + "'/></svg>";
109+ variantData = stringData;
110+ }
111+
112+ // Workaround for liblightdm returning "" when a user has no default session
113+ if (Q_UNLIKELY(role == QLightDM::UsersModel::SessionRole && variantData.toString().isEmpty())) {
114+ variantData = Greeter::instance()->defaultSessionHint();
115+ }
116+
117+ return variantData;
118+}
119+
120+void MangleModel::addCustomRow(const CustomRow &newRow)
121+{
122+ for (int i = 0; i < m_customRows.size(); i++) {
123+ if (m_customRows[i].name == newRow.name) {
124+ return; // we don't have custom rows that change content yet
125+ }
126+ }
127+
128+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
129+ m_customRows << newRow;
130+ endInsertRows();
131+}
132+
133+void MangleModel::removeCustomRow(const QString &rowName)
134+{
135+ for (int i = 0; i < m_customRows.size(); i++) {
136+ if (m_customRows[i].name == rowName) {
137+ int rowNum = sourceRowCount() + i;
138+ beginRemoveRows(QModelIndex(), rowNum, rowNum);
139+ m_customRows.removeAt(i);
140+ endRemoveRows();
141+ break;
142+ }
143+ }
144+}
145+
146+void MangleModel::updateManualRow()
147+{
148+ bool hasAnotherEntry = sourceRowCount() > 0;
149+ for (int i = 0; !hasAnotherEntry && i < m_customRows.size(); i++) {
150+ if (m_customRows[i].name != QStringLiteral("*other")) {
151+ hasAnotherEntry = true;
152+ }
153+ }
154+
155+ // Show manual login if we are asked to OR if no other entry exists
156+ if (Greeter::instance()->showManualLoginHint() || !hasAnotherEntry)
157+ addCustomRow({QStringLiteral("*other"), gettext("Login")});
158+ else
159+ removeCustomRow(QStringLiteral("*other"));
160+}
161+
162+void MangleModel::updateGuestRow()
163+{
164+ if (Greeter::instance()->hasGuestAccount())
165+ addCustomRow({QStringLiteral("*guest"), gettext("Guest Session")});
166+ else
167+ removeCustomRow(QStringLiteral("*guest"));
168+}
169+
170+void MangleModel::updateCustomRows()
171+{
172+ // We update when rowCount changes, but we also insert/remove rows here.
173+ // So guard this function to avoid recursion.
174+ if (m_updatingCustomRows)
175+ return;
176+
177+ m_updatingCustomRows = true;
178+ updateGuestRow();
179+ updateManualRow();
180+ m_updatingCustomRows = false;
181+}
182+
183+int MangleModel::rowCount(const QModelIndex &parent) const
184+{
185+ if (parent.isValid())
186+ return 0;
187+ else
188+ return sourceRowCount() + m_customRows.size();
189+}
190+
191+int MangleModel::sourceRowCount() const
192+{
193+ return Greeter::instance()->hideUsersHint() ? 0 : sourceModel()->rowCount();
194+}
195+
196+QModelIndex MangleModel::index(int row, int column, const QModelIndex &parent) const
197+{
198+ if (row >= rowCount())
199+ return QModelIndex();
200+
201+ bool isCustomRow = row >= sourceRowCount();
202+ if (isCustomRow && !parent.isValid()) {
203+ return createIndex(row, column);
204+ } else {
205+ return QIdentityProxyModel::index(row, column, parent);
206+ }
207+}
208+
209+// **** Now we continue with actual UsersModel class ****
210+
211+UsersModel::UsersModel(QObject* parent)
212+ : UnitySortFilterProxyModelQML(parent)
213+{
214+ setModel(new MangleModel(this));
215+ setSortCaseSensitivity(Qt::CaseInsensitive);
216+ setSortLocaleAware(true);
217+ setSortRole(QLightDM::UsersModel::RealNameRole);
218+ sort(0);
219+}
220+
221+bool UsersModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
222+{
223+ auto leftName = source_left.data(QLightDM::UsersModel::NameRole);
224+ auto rightName = source_right.data(QLightDM::UsersModel::NameRole);
225+
226+ if (leftName == QStringLiteral("*guest"))
227+ return false;
228+ if (rightName == QStringLiteral("*guest"))
229+ return true;
230+ if (leftName == QStringLiteral("*other"))
231+ return false;
232+ if (rightName == QStringLiteral("*other"))
233+ return true;
234+
235+ return UnitySortFilterProxyModelQML::lessThan(source_left, source_right);
236+}
237+
238+#include "UsersModel.moc"
plugins/IntegratedLightDM/UsersModel.h → plugins/LightDM/UsersModel.hrenamed+6−8
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012,2013 Canonical, Ltd.
2+ * Copyright (C) 2012-2013,2015-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,19 +12,16 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Terry <michael.terry@canonical.com>
1715 */
1816
1917/* This class is a really tiny filter around QLightDM::UsersModel. There are
2018 some operations that we want to edit a bit for the benefit of Qml.
2119 Specifically, we want to sort users according to realName. */
2220
23−#ifndef UNITY_USERSMODEL_H
24−#define UNITY_USERSMODEL_H
21+#pragma once
2522
2623#include <unitysortfilterproxymodelqml.h>
27−#include <QtCore/QObject>
24+#include <QObject>
2825
2926class UsersModel : public UnitySortFilterProxyModelQML
3027{
@@ -32,6 +29,7 @@ class UsersModel : public UnitySortFilterProxyModelQML
3229
3330public:
3431 explicit UsersModel(QObject* parent=0);
35−};
3632
37−#endif
33+protected:
34+ bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
35+};
plugins/IntegratedLightDM/plugin.cpp → plugins/LightDM/plugin.cpprenamed+37−7
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012,2013, 2015 Canonical, Ltd.
2+ * Copyright (C) 2012,2013,2015 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -19,9 +19,12 @@
1919#include "DBusGreeter.h"
2020#include "DBusGreeterList.h"
2121#include "Greeter.h"
22+#include "PromptsModel.h"
23+#include "SessionsModel.h"
2224#include "UsersModel.h"
2325#include <libusermetricsoutput/ColorTheme.h>
2426#include <libusermetricsoutput/UserMetrics.h>
27+#include <QLightDM/SessionsModel>
2528#include <QLightDM/UsersModel>
2629
2730#include <QAbstractItemModel>
@@ -30,16 +33,31 @@
3033
3134static QObject *greeter_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
3235{
33− Q_UNUSED(engine)
3436 Q_UNUSED(scriptEngine)
3537
36− Greeter *greeter = new Greeter();
38+ Greeter *greeter = Greeter::instance();
3739 new DBusGreeter(greeter, QStringLiteral("/"));
3840 new DBusGreeterList(greeter, QStringLiteral("/list"));
3941
42+ engine->setObjectOwnership(greeter, QQmlEngine::CppOwnership);
43+
4044 return greeter;
4145}
4246
47+static QObject *prompts_provider(QQmlEngine *engine, QJSEngine *)
48+{
49+ auto model = Greeter::instance()->promptsModel();
50+ engine->setObjectOwnership(model, QQmlEngine::CppOwnership);
51+ return model;
52+}
53+
54+static QObject *sessions_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
55+{
56+ Q_UNUSED(engine)
57+ Q_UNUSED(scriptEngine)
58+ return new SessionsModel();
59+}
60+
4361static QObject *users_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
4462{
4563 Q_UNUSED(engine)
@@ -54,16 +72,28 @@ static QObject *infographic_provider(QQmlEngine *engine, QJSEngine *scriptEngine
5472 return UserMetricsOutput::UserMetrics::getInstance();
5573}
5674
57−void IntegratedLightDMPlugin::registerTypes(const char *uri)
75+void PLUGIN_CLASSNAME::registerTypes(const char *uri)
5876{
5977 qmlRegisterType<QAbstractItemModel>();
6078 qmlRegisterType<UserMetricsOutput::ColorTheme>();
6179
62− Q_ASSERT(uri == QLatin1String("IntegratedLightDM"));
63− qRegisterMetaType<QLightDM::Greeter::MessageType>("QLightDM::Greeter::MessageType");
64− qRegisterMetaType<QLightDM::Greeter::PromptType>("QLightDM::Greeter::PromptType");
80+#if defined INTEGRATED_LIGHTDM
81+ Q_ASSERT(uri == QLatin1String("LightDM.IntegratedLightDM"));
6582 qmlRegisterSingletonType<Greeter>(uri, 0, 1, "Greeter", greeter_provider);
83+#elif defined FULL_LIGHTDM
84+ Q_ASSERT(uri == QLatin1String("LightDM.FullLightDM"));
85+ qmlRegisterSingletonType<QLightDM::Greeter>(uri, 0, 1, "Greeter", greeter_provider);
86+#else
87+ #error No library defined in LightDM plugin
88+#endif
89+
90+ qmlRegisterSingletonType<PromptsModel>(uri, 0, 1, "Prompts", prompts_provider);
91+
92+ qmlRegisterSingletonType<SessionsModel>(uri, 0, 1, "Sessions", sessions_provider);
93+ qmlRegisterUncreatableType<QLightDM::SessionsModel>(uri, 0, 1, "SessionRoles", QStringLiteral("Type is not instantiable"));
94+
6695 qmlRegisterSingletonType<UsersModel>(uri, 0, 1, "Users", users_provider);
6796 qmlRegisterUncreatableType<QLightDM::UsersModel>(uri, 0, 1, "UserRoles", QStringLiteral("Type is not instantiable"));
97+
6898 qmlRegisterSingletonType<UserMetricsOutput::UserMetrics>(uri, 0, 1, "Infographic", infographic_provider);
6999}
plugins/IntegratedLightDM/plugin.h → plugins/LightDM/plugin.hrenamed+5−5
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012,2013, 2015 Canonical, Ltd.
2+ * Copyright (C) 2012,2013,2015 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -15,13 +15,13 @@
1515 *
1616 */
1717
18−#ifndef INTEGRATED_LIGHTDM_PLUGIN_H
19−#define INTEGRATED_LIGHTDM_PLUGIN_H
18+#ifndef LIGHTDM_PLUGIN_H
19+#define LIGHTDM_PLUGIN_H
2020
2121#include <QtQml/QQmlEngine>
2222#include <QtQml/QQmlExtensionPlugin>
2323
24−class IntegratedLightDMPlugin : public QQmlExtensionPlugin
24+class PLUGIN_CLASSNAME : public QQmlExtensionPlugin
2525{
2626 Q_OBJECT
2727 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
@@ -30,4 +30,4 @@ public:
3030 void registerTypes(const char *uri) override;
3131};
3232
33−#endif /* INTEGRATED_LIGHTDM_PLUGIN_H */
33+#endif /* LIGHTDM_PLUGIN_H */
plugins/IntegratedLightDM/qmldir → plugins/LightDM/qmldirrenamed

The content is the same.

plugins/Lights/CMakeLists.txt+9−2
@@ -1,16 +1,23 @@
11pkg_check_modules(ANDROID_HEADERS REQUIRED android-headers)
22pkg_check_modules(ANDROID_HARDWARE REQUIRED libhardware)
3+pkg_check_modules(ANDROID_PROPERTIES REQUIRED libandroid-properties)
34
45include_directories(
6+ SYSTEM
57 ${ANDROID_HEADERS_INCLUDE_DIRS}
68)
79
810add_library(Lights-qml MODULE
911 plugin.cpp
1012 Lights.cpp
13+ LegacyLights.cpp
14+ HfdLights.cpp
1115 )
1216
13−qt5_use_modules(Lights-qml Qml Gui)
14−target_link_libraries(Lights-qml ${ANDROID_HARDWARE_LIBRARIES})
17+target_link_libraries(Lights-qml
18+ Qt5::Qml Qt5::Gui Qt5::DBus
19+ ${ANDROID_HARDWARE_LIBRARIES}
20+ ${ANDROID_PROPERTIES_LIBRARIES}
21+ )
1522
1623add_unity8_plugin(Lights 0.1 Lights TARGETS Lights-qml)
plugins/Lights/HfdLights.cppnew file+62
@@ -0,0 +1,62 @@
1+/*
2+ * Copyright (C) 2021 UBports Foundation.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Florian Leeber <florian@ubports.com>
17+ */
18+
19+#include "HfdLights.h"
20+#include <QtCore/QDebug>
21+#include <QDBusArgument>
22+#include <QDBusConnection>
23+#include <iostream>
24+
25+#define HFD_SERVICE_NAME "com.lomiri.hfd"
26+#define HFD_SERVICE_PATH "/com/lomiri/hfd"
27+#define HFD_SERVICE_INTERFACE "com.lomiri.hfd.Leds"
28+
29+HfdLights::HfdLights(QObject* parent)
30+ : Lights(parent)
31+{
32+ m_hfdInterface = new QDBusInterface(
33+ QStringLiteral(HFD_SERVICE_NAME),
34+ QStringLiteral(HFD_SERVICE_PATH),
35+ QStringLiteral(HFD_SERVICE_INTERFACE),
36+ QDBusConnection::systemBus(),
37+ this
38+ );
39+}
40+
41+bool HfdLights::init()
42+{
43+ // hfd does not need any initalization to be used
44+ return true;
45+}
46+
47+void HfdLights::turnOn()
48+{
49+ m_hfdInterface->call(QStringLiteral("setState"), 0);
50+ m_hfdInterface->call(QStringLiteral("setColor"), (quint32)m_color.rgba());
51+ m_hfdInterface->call(QStringLiteral("setOnMs"), m_onMs);
52+ m_hfdInterface->call(QStringLiteral("setOffMs"), m_offMs);
53+ m_hfdInterface->call(QStringLiteral("setState"), 1);
54+}
55+
56+void HfdLights::turnOff()
57+{
58+ m_hfdInterface->call(QStringLiteral("setState"), 0);
59+ m_hfdInterface->call(QStringLiteral("setColor"), (quint32)0);
60+ m_hfdInterface->call(QStringLiteral("setOnMs"), 0);
61+ m_hfdInterface->call(QStringLiteral("setOffMs"), 0);
62+}
tests/mocks/Unity/DashCommunicator/plugin.h → plugins/Lights/HfdLights.hrenamed+17−9
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2021 UBports Foundation.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -13,22 +13,30 @@
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 *
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
16+ * Author: Florian Leeber <florian@ubports.com>
1717 */
1818
19−#ifndef DASHCOMMUNICATOR_PLUGIN_H
20−#define DASHCOMMUNICATOR_PLUGIN_H
19+#ifndef UNITY_HFDLIGHTS_H
20+#define UNITY_HFDLIGHTS_H
2121
22−#include <QtQml/QQmlEngine>
23−#include <QtQml/QQmlExtensionPlugin>
22+#include <QtCore/QObject>
23+#include <QDBusInterface>
24+#include "Lights.h"
2425
25−class DashCommunicatorPlugin : public QQmlExtensionPlugin
26+class HfdLights: public Lights
2627{
2728 Q_OBJECT
28− Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
2929
3030public:
31− void registerTypes(const char *uri) override;
31+ explicit HfdLights(QObject *parent = 0);
32+
33+protected:
34+ bool init() override;
35+ void turnOff() override;
36+ void turnOn() override;
37+
38+private:
39+ QDBusInterface* m_hfdInterface;
3240};
3341
3442#endif
plugins/Lights/LegacyLights.cppnew file+91
@@ -0,0 +1,91 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ * Copyright (C) 2021 UBports Foundation.
4+ *
5+ * This program is free software; you can redistribute it and/or modify
6+ * it under the terms of the GNU General Public License as published by
7+ * the Free Software Foundation; version 3.
8+ *
9+ * This program is distributed in the hope that it will be useful,
10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+ * GNU General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU General Public License
15+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16+ *
17+ * Author: Renato Araujo Oliveira Filho <renato.filho@canonical.com>
18+ */
19+
20+#include "LegacyLights.h"
21+#include <QtCore/QDebug>
22+
23+extern "C" {
24+#include "android-hardware.h"
25+#include <string.h>
26+}
27+
28+LegacyLights::~LegacyLights()
29+{
30+ if (m_lightDevice) {
31+ hw_device_t* device = (hw_device_t*) m_lightDevice;
32+ device->close(device);
33+ }
34+}
35+
36+bool LegacyLights::init()
37+{
38+ if (m_lightDevice) {
39+ return true;
40+ }
41+
42+ int err;
43+ hw_module_t* module;
44+
45+ err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
46+ if (err == 0) {
47+ hw_device_t* device;
48+ err = module->methods->open(module, LIGHT_ID_NOTIFICATIONS, &device);
49+ if (err == 0) {
50+ m_lightDevice = (light_device_t*)device;
51+ turnOff();
52+ return true;
53+ } else {
54+ qWarning() << "Failed to access notification lights";
55+ }
56+ } else {
57+ qWarning() << "Failed to initialize lights hardware.";
58+ }
59+ return false;
60+}
61+
62+void LegacyLights::turnOn()
63+{
64+ // pulse
65+ light_state_t state;
66+ memset(&state, 0, sizeof(light_state_t));
67+ state.color = m_color.rgba();
68+ state.flashMode = LIGHT_FLASH_TIMED;
69+ state.flashOnMS = m_onMs;
70+ state.flashOffMS = m_offMs;
71+ state.brightnessMode = BRIGHTNESS_MODE_USER;
72+
73+ if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
74+ qWarning() << "Failed to turn the light off";
75+ }
76+}
77+
78+void LegacyLights::turnOff()
79+{
80+ light_state_t state;
81+ memset(&state, 0, sizeof(light_state_t));
82+ state.color = 0x00000000;
83+ state.flashMode = LIGHT_FLASH_NONE;
84+ state.flashOnMS = 0;
85+ state.flashOffMS = 0;
86+ state.brightnessMode = 0;
87+
88+ if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
89+ qWarning() << "Failed to turn the light off";
90+ }
91+}
plugins/Unity/DashCommunicator/plugin.h → plugins/Lights/LegacyLights.hrenamed+19−8
@@ -1,5 +1,6 @@
11/*
22 * Copyright (C) 2014 Canonical, Ltd.
3+ * Copyright (C) 2021 UBports Foundation.
34 *
45 * This program is free software; you can redistribute it and/or modify
56 * it under the terms of the GNU General Public License as published by
@@ -13,22 +14,32 @@
1314 * You should have received a copy of the GNU General Public License
1415 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1516 *
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+ * Author: Renato Araujo Oliveira Filho <renato.filho@canonical.com>
1718 */
1819
19−#ifndef DASHCOMMUNICATOR_PLUGIN_H
20−#define DASHCOMMUNICATOR_PLUGIN_H
20+#ifndef UNITY_LEGACYLIGHTS_H
21+#define UNITY_LEGACYLIGHTS_H
2122
22−#include <QtQml/QQmlEngine>
23−#include <QtQml/QQmlExtensionPlugin>
23+#include <QtCore/QObject>
24+#include "Lights.h"
2425
25−class DashCommunicatorPlugin : public QQmlExtensionPlugin
26+struct light_device_t;
27+
28+class LegacyLights: public Lights
2629{
2730 Q_OBJECT
28− Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
2931
3032public:
31− void registerTypes(const char *uri) override;
33+ ~LegacyLights();
34+
35+protected:
36+ bool init() override;
37+ void turnOff() override;
38+ void turnOn() override;
39+
40+private:
41+ light_device_t* m_lightDevice;
42+
3243};
3344
3445#endif
plugins/Lights/Lights.cpp−65
@@ -26,20 +26,12 @@ extern "C" {
2626
2727Lights::Lights(QObject* parent)
2828 : QObject(parent),
29− m_lightDevice(0),
3029 m_color("blue"),
3130 m_state(Lights::Off),
3231 m_onMs(1000),
3332 m_offMs(3000)
3433{
35−}
3634
37−Lights::~Lights()
38−{
39− if (m_lightDevice) {
40− hw_device_t* device = (hw_device_t*) m_lightDevice;
41− device->close(device);
42− }
4335}
4436
4537void Lights::setState(Lights::State newState)
@@ -107,60 +99,3 @@ void Lights::setOffMillisec(int offMs)
10799 // FIXME: update the property if the light is already on
108100 }
109101}
110−
111−bool Lights::init()
112−{
113− if (m_lightDevice) {
114− return true;
115− }
116−
117− int err;
118− hw_module_t* module;
119−
120− err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
121− if (err == 0) {
122− hw_device_t* device;
123− err = module->methods->open(module, LIGHT_ID_NOTIFICATIONS, &device);
124− if (err == 0) {
125− m_lightDevice = (light_device_t*)device;
126− turnOff();
127− return true;
128− } else {
129− qWarning() << "Failed to access notification lights";
130− }
131− } else {
132− qWarning() << "Failed to initialize lights hardware.";
133− }
134− return false;
135−}
136−
137−void Lights::turnOn()
138−{
139− // pulse
140− light_state_t state;
141− memset(&state, 0, sizeof(light_state_t));
142− state.color = m_color.rgba();
143− state.flashMode = LIGHT_FLASH_TIMED;
144− state.flashOnMS = m_onMs;
145− state.flashOffMS = m_offMs;
146− state.brightnessMode = BRIGHTNESS_MODE_USER;
147−
148− if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
149− qWarning() << "Failed to turn the light off";
150− }
151−}
152−
153−void Lights::turnOff()
154−{
155− light_state_t state;
156− memset(&state, 0, sizeof(light_state_t));
157− state.color = 0x00000000;
158− state.flashMode = LIGHT_FLASH_NONE;
159− state.flashOnMS = 0;
160− state.flashOffMS = 0;
161− state.brightnessMode = 0;
162−
163− if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
164− qWarning() << "Failed to turn the light off";
165− }
166−}
plugins/Lights/Lights.h+5−9
@@ -22,12 +22,9 @@
2222#include <QtCore/QObject>
2323#include <QtGui/QColor>
2424
25−struct light_device_t;
26−
2725class Lights: public QObject
2826{
2927 Q_OBJECT
30− Q_ENUMS(State)
3128 Q_PROPERTY(State state READ state WRITE setState NOTIFY stateChanged)
3229 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
3330 Q_PROPERTY(int onMillisec READ onMillisec WRITE setOnMillisec NOTIFY onMillisecChanged)
@@ -38,9 +35,9 @@ public:
3835 Off,
3936 On,
4037 };
38+ Q_ENUM(State)
4139
4240 explicit Lights(QObject *parent = 0);
43− ~Lights();
4441
4542 void setState(State newState);
4643 State state() const;
@@ -60,16 +57,15 @@ Q_SIGNALS:
6057 void onMillisecChanged(int onMs);
6158 void offMillisecChanged(int offMs);
6259
63−private:
64− light_device_t* m_lightDevice;
60+protected:
6561 QColor m_color;
6662 State m_state;
6763 int m_onMs;
6864 int m_offMs;
6965
70− bool init();
71− void turnOff();
72− void turnOn();
66+ virtual bool init() = 0;
67+ virtual void turnOff() = 0;
68+ virtual void turnOn() = 0;
7369};
7470
7571#endif
plugins/Lights/Lights.qmltypesdeleted−45
@@ -1,45 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable Lights 0.1 plugins'
8−
9−Module {
10− Component {
11− name: "Lights"
12− prototype: "QObject"
13− exports: ["Lights/Lights 0.1"]
14− isCreatable: false
15− isSingleton: true
16− exportMetaObjectRevisions: [0]
17− Enum {
18− name: "State"
19− values: {
20− "Off": 0,
21− "On": 1
22− }
23− }
24− Property { name: "state"; type: "State" }
25− Property { name: "color"; type: "QColor" }
26− Property { name: "onMillisec"; type: "int" }
27− Property { name: "offMillisec"; type: "int" }
28− Signal {
29− name: "stateChanged"
30− Parameter { name: "newState"; type: "State" }
31− }
32− Signal {
33− name: "colorChanged"
34− Parameter { name: "color"; type: "QColor" }
35− }
36− Signal {
37− name: "onMillisecChanged"
38− Parameter { name: "onMs"; type: "int" }
39− }
40− Signal {
41− name: "offMillisecChanged"
42− Parameter { name: "offMs"; type: "int" }
43− }
44− }
45−}
plugins/Lights/android-hardware.h−4
@@ -15,9 +15,5 @@
1515 *
1616 */
1717
18−// The purpose of this header wrapper is just to avoid having warnings being reported on
19−// code from external header files, as we can't do anything about them.
20−#pragma GCC system_header
21−
2218#include <hardware/hardware.h>
2319#include <hardware/lights.h>
plugins/Lights/plugin.cpp+20−1
@@ -18,6 +18,11 @@
1818
1919#include "plugin.h"
2020#include "Lights.h"
21+#include "HfdLights.h"
22+#include "LegacyLights.h"
23+
24+// libandroid-properties
25+#include <hybris/properties/properties.h>
2126
2227#include <QtQml/qqml.h>
2328
@@ -25,7 +30,21 @@ static QObject *lights_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
2530{
2631 Q_UNUSED(engine)
2732 Q_UNUSED(scriptEngine)
28− return new Lights();
33+
34+ bool use_hfd = false;
35+ char buffer[PROP_VALUE_MAX];
36+ auto result = property_get("ro.build.version.sdk", buffer, "0");
37+ if (result) {
38+ auto sdkVersion = QString(buffer).toInt();
39+ if (sdkVersion >= 27 || sdkVersion == 0) {
40+ use_hfd = true;
41+ }
42+ }
43+ if (use_hfd) {
44+ return new HfdLights();
45+ } else {
46+ return new LegacyLights();
47+ }
2948}
3049
3150void LightsPlugin::registerTypes(const char *uri)
plugins/Powerd/CMakeLists.txt+4−4
@@ -1,5 +1,3 @@
1−pkg_search_module(GIO REQUIRED gio-2.0)
2−
31include_directories(
42 ${GIO_INCLUDE_DIRS}
53)
@@ -11,7 +9,9 @@ add_library(Powerd-qml MODULE
119 Powerd.cpp
1210 )
1311
14−qt5_use_modules(Powerd-qml DBus Qml)
15−target_link_libraries(Powerd-qml ${GIO_LDFLAGS})
12+target_link_libraries(Powerd-qml
13+ Qt5::DBus Qt5::Qml
14+ ${GIO_LDFLAGS}
15+ )
1616
1717add_unity8_plugin(Powerd 0.1 Powerd TARGETS Powerd-qml)
plugins/Powerd/Powerd.h+2−2
@@ -27,8 +27,6 @@
2727class Powerd: public QObject
2828{
2929 Q_OBJECT
30− Q_ENUMS(Status)
31− Q_ENUMS(DisplayStateChangeReason)
3230 Q_PROPERTY(Status status READ status NOTIFY statusChanged)
3331
3432public:
@@ -41,11 +39,13 @@ public:
4139 SnapDecision = 5, // Display changed state due to snap decision prompt
4240 CallDone = 6, // Display changed state due to voice call end
4341 };
42+ Q_ENUM(DisplayStateChangeReason)
4443
4544 enum Status {
4645 Off,
4746 On,
4847 };
48+ Q_ENUM(Status)
4949
5050 explicit Powerd(QObject *parent = 0);
5151 ~Powerd();
plugins/Powerd/Powerd.qmltypesdeleted−39
@@ -1,39 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable Powerd 0.1 plugins'
8−
9−Module {
10− Component {
11− name: "Powerd"
12− prototype: "QObject"
13− exports: ["Powerd/Powerd 0.1"]
14− isCreatable: false
15− isSingleton: true
16− exportMetaObjectRevisions: [0]
17− Enum {
18− name: "DisplayStateChangeReason"
19− values: {
20− "Unknown": 0,
21− "Inactivity": 1,
22− "PowerKey": 2,
23− "Proximity": 3
24− }
25− }
26− Enum {
27− name: "Status"
28− values: {
29− "Off": 0,
30− "On": 1
31− }
32− }
33− Property { name: "status"; type: "Status"; isReadonly: true }
34− Signal {
35− name: "statusChanged"
36− Parameter { name: "reason"; type: "DisplayStateChangeReason" }
37− }
38− }
39−}
plugins/ScreenGrabber/CMakeLists.txtdeleted−13
@@ -1,13 +0,0 @@
1−include_directories(
2− ${CMAKE_CURRENT_BINARY_DIR}
3−)
4−
5−set(SCREENGRABBERSOURCES
6− screengrabber.cpp
7− plugin.cpp
8−)
9−
10−add_library(ScreenGrabber-qml MODULE ${SCREENGRABBERSOURCES})
11−qt5_use_modules(ScreenGrabber-qml Qml Gui Quick Concurrent)
12−
13−add_unity8_plugin(ScreenGrabber 0.1 ScreenGrabber TARGETS ScreenGrabber-qml)
plugins/ScreenGrabber/qmldirdeleted−3
@@ -1,3 +0,0 @@
1−module ScreenGrabber
2−plugin ScreenGrabber-qml
3−typeinfo ScreenGrabber.qmltypes
plugins/ScreenGrabber/screengrabber.cppdeleted−117
@@ -1,117 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "screengrabber.h"
18−
19−#include <QDir>
20−#include <QDateTime>
21−#include <QStandardPaths>
22−#include <QTemporaryDir>
23−#include <QtGui/QImage>
24−#include <QtGui/QGuiApplication>
25−#include <QtQuick/QQuickWindow>
26−
27−#include <QDebug>
28−
29−QString saveScreenshot(const QImage &screenshot, const QString &filename, const QString &format, int quality)
30−{
31− if (screenshot.save(filename, format.toLatin1().data(), quality)) {
32− return filename;
33− } else {
34− qWarning() << "ScreenGrabber: failed to save snapshot!";
35− }
36− return QString();
37−}
38−
39−ScreenGrabber::ScreenGrabber(QObject *parent)
40− : QObject(parent)
41−{
42− QObject::connect(&m_watcher,
43− &QFutureWatcher<QString>::finished,
44− this,
45− &ScreenGrabber::onScreenshotSaved);
46−
47− QDir screenshotsDir;
48− if (qEnvironmentVariableIsSet("UNITY_TESTING")) {
49− qDebug() << "Using test environment";
50− QTemporaryDir tDir;
51− tDir.setAutoRemove(false);
52− screenshotsDir = tDir.path();
53− } else {
54− qDebug() << "Using real environment";
55− screenshotsDir = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
56− }
57− screenshotsDir.mkpath(QStringLiteral("Screenshots"));
58− screenshotsDir.cd(QStringLiteral("Screenshots"));
59− if (screenshotsDir.exists()) {
60− fileNamePrefix = screenshotsDir.absolutePath();
61− fileNamePrefix.append("/screenshot");
62− } else {
63− qWarning() << "ScreenGrabber: failed to create directory at: " << screenshotsDir.absolutePath();
64− }
65−}
66−
67−void ScreenGrabber::captureAndSave(int angle)
68−{
69− if (fileNamePrefix.isEmpty())
70− {
71− qWarning() << "ScreenShotter: no directory to save screenshot";
72− return;
73− }
74−
75− const QWindowList windows = QGuiApplication::topLevelWindows();
76− if (windows.empty())
77− {
78− qWarning() << "ScreenShotter: no top level windows found!";
79− return;
80− }
81−
82− QQuickWindow *main_window = qobject_cast<QQuickWindow *>(windows[0]);
83− if (!main_window)
84− {
85− qWarning() << "ScreenShotter: can only take screenshots of QQuickWindows";
86− return;
87− }
88−
89− const QImage screenshot = main_window->grabWindow().transformed(QTransform().rotate(angle));
90− const QString filename = makeFileName();
91− qDebug() << "Saving screenshot to" << filename;
92− QFuture<QString> saveFuture(QtConcurrent::run(saveScreenshot, screenshot, filename, getFormat(), screenshotQuality));
93− m_watcher.setFuture(saveFuture);
94−}
95−
96−void ScreenGrabber::onScreenshotSaved()
97−{
98− const QString filename = m_watcher.future().result();
99− if (!filename.isEmpty()) {
100− Q_EMIT screenshotSaved(filename);
101− }
102−}
103−
104−QString ScreenGrabber::makeFileName() const
105−{
106− QString fileName(fileNamePrefix);
107− fileName.append(QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMdd_hhmmsszzz")));
108− fileName.append(".");
109− fileName.append(getFormat());
110− return fileName;
111−}
112−
113−QString ScreenGrabber::getFormat() const
114−{
115− //TODO: This should be configurable (perhaps through gsettings?)
116− return QStringLiteral("png");
117−}
plugins/ScreenshotDirectory/CMakeLists.txtnew file+9
@@ -0,0 +1,9 @@
1+set(PLUGIN_SOURCES
2+ ScreenshotDirectory.cpp
3+ plugin.cpp
4+)
5+
6+add_library(ScreenshotDirectory-qml MODULE ${PLUGIN_SOURCES})
7+target_link_libraries(ScreenshotDirectory-qml Qt5::Qml Qt5::Gui Qt5::Quick)
8+
9+add_unity8_plugin(ScreenshotDirectory 0.1 ScreenshotDirectory TARGETS ScreenshotDirectory-qml)
plugins/ScreenGrabber/ScreenGrabber.qmltypes → plugins/ScreenshotDirectory/ScreenGrabber.qmltypesrenamed

The content is the same.

plugins/ScreenshotDirectory/ScreenshotDirectory.cppnew file+64
@@ -0,0 +1,64 @@
1+/*
2+ * Copyright (C) 2014-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "ScreenshotDirectory.h"
18+
19+#include <QDir>
20+#include <QDateTime>
21+#include <QStandardPaths>
22+#include <QTemporaryDir>
23+
24+#include <QDebug>
25+
26+ScreenshotDirectory::ScreenshotDirectory(QObject *parent)
27+ : QObject(parent)
28+{
29+ QDir screenshotsDir;
30+ if (qEnvironmentVariableIsSet("UNITY_TESTING")) {
31+ QTemporaryDir tDir;
32+ tDir.setAutoRemove(false);
33+ screenshotsDir = tDir.path();
34+ } else {
35+ screenshotsDir = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
36+ }
37+ screenshotsDir.mkpath(QStringLiteral("Screenshots"));
38+ screenshotsDir.cd(QStringLiteral("Screenshots"));
39+ if (screenshotsDir.exists()) {
40+ m_fileNamePrefix = screenshotsDir.absolutePath();
41+ m_fileNamePrefix.append("/screenshot");
42+ } else {
43+ qWarning() << "ScreenshotDirectory: failed to create directory at:" << screenshotsDir.absolutePath();
44+ }
45+}
46+
47+QString ScreenshotDirectory::makeFileName() const
48+{
49+ if (m_fileNamePrefix.isEmpty()) {
50+ return QString();
51+ }
52+
53+ QString fileName(m_fileNamePrefix);
54+ fileName.append(QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMdd_hhmmsszzz")));
55+ fileName.append(".");
56+ fileName.append(format());
57+ return fileName;
58+}
59+
60+QString ScreenshotDirectory::format() const
61+{
62+ //TODO: This should be configurable (perhaps through gsettings?)
63+ return QStringLiteral("png");
64+}
plugins/ScreenshotDirectory/ScreenshotDirectory.hnew file+39
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright (C) 2014-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef SCREENSHOTDIRECTORY_H
18+#define SCREENSHOTDIRECTORY_H
19+
20+#include <QObject>
21+#include <QString>
22+
23+class ScreenshotDirectory: public QObject
24+{
25+ Q_OBJECT
26+
27+public:
28+ explicit ScreenshotDirectory(QObject *parent = 0);
29+ ~ScreenshotDirectory() = default;
30+
31+public Q_SLOTS:
32+ QString makeFileName() const;
33+
34+private:
35+ QString format() const;
36+ QString m_fileNamePrefix;
37+};
38+
39+#endif // SCREENSHOTDIRECTORY_H
plugins/ScreenGrabber/plugin.cpp → plugins/ScreenshotDirectory/plugin.cpprenamed+5−7
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014,2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,17 +12,15 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Alberto Aguirre <alberto.aguirre@canonical.com>
1715 */
1816
1917#include "plugin.h"
20−#include "screengrabber.h"
18+#include "ScreenshotDirectory.h"
2119
2220#include <QtQml/qqml.h>
2321
24−void ScreenGrabberPlugin::registerTypes(const char *uri)
22+void ScreenshotDirectoryPlugin::registerTypes(const char *uri)
2523{
26− Q_ASSERT(uri == QLatin1String("ScreenGrabber"));
27− qmlRegisterType<ScreenGrabber>(uri, 0, 1, "ScreenGrabber");
24+ Q_ASSERT(uri == QLatin1String("ScreenshotDirectory"));
25+ qmlRegisterType<ScreenshotDirectory>(uri, 0, 1, "ScreenshotDirectory");
2826}
plugins/ScreenGrabber/plugin.h → plugins/ScreenshotDirectory/plugin.hrenamed+5−7
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014,2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,16 +12,14 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Alberto Aguirre <alberto.aguirre@canonical.com>
1715 */
1816
19−#ifndef SCREENGRABBER_PLUGIN_H
20−#define SCREENGRABBER_PLUGIN_H
17+#ifndef SCREENSHOTDIRECTORY_PLUGIN_H
18+#define SCREENSHOTDIRECTORY_PLUGIN_H
2119
2220#include <QtQml/QQmlExtensionPlugin>
2321
24−class ScreenGrabberPlugin : public QQmlExtensionPlugin
22+class ScreenshotDirectoryPlugin : public QQmlExtensionPlugin
2523{
2624 Q_OBJECT
2725 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
@@ -30,4 +28,4 @@ public:
3028 void registerTypes(const char *uri) override;
3129};
3230
33−#endif // SCREENGRABBER_PLUGIN_H
31+#endif // SCREENSHOTDIRECTORY_PLUGIN_H
plugins/ScreenshotDirectory/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module ScreenshotDirectory
2+plugin ScreenshotDirectory-qml
plugins/SessionBroadcast/CMakeLists.txt+5−1
@@ -1,3 +1,4 @@
1+include_directories(${GLIB_INCLUDE_DIRS})
12add_definitions(-DSM_BUSNAME=systemBus)
23
34add_library(SessionBroadcast-qml MODULE
@@ -5,6 +6,9 @@ add_library(SessionBroadcast-qml MODULE
56 plugin.cpp
67 )
78
8−qt5_use_modules(SessionBroadcast-qml DBus Qml)
9+target_link_libraries(SessionBroadcast-qml
10+ Qt5::DBus Qt5::Qml
11+ ${GLIB_LIBRARIES}
12+ )
913
1014add_unity8_plugin(SessionBroadcast 0.1 SessionBroadcast TARGETS SessionBroadcast-qml)
plugins/SessionBroadcast/SessionBroadcast.cpp+40−10
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013,2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,30 +12,60 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Author: Michael Terry <michael.terry@canonical.com>
1715 */
1816
1917#include "SessionBroadcast.h"
2018#include <QDBusConnection>
19+#include <QDBusConnectionInterface>
20+#include <QDBusInterface>
21+
22+#include <glib.h>
2123
2224SessionBroadcast::SessionBroadcast(QObject* parent)
2325 : QObject(parent)
2426{
27+ m_username = QString::fromUtf8(g_get_user_name());
28+
2529 auto connection = QDBusConnection::SM_BUSNAME();
30+ auto interface = connection.interface();
31+ interface->startService(QStringLiteral("com.canonical.Unity.Greeter.Broadcast"));
32+
33+ m_broadcaster = new QDBusInterface(QStringLiteral("com.canonical.Unity.Greeter.Broadcast"),
34+ QStringLiteral("/com/canonical/Unity/Greeter/Broadcast"),
35+ QStringLiteral("com.canonical.Unity.Greeter.Broadcast"),
36+ connection, this);
2637
27− connection.connect(QStringLiteral("com.canonical.Unity.Greeter.Broadcast"),
28− QStringLiteral("/com/canonical/Unity/Greeter/Broadcast"),
29− QStringLiteral("com.canonical.Unity.Greeter.Broadcast"),
30− QStringLiteral("ShowHome"),
31− this,
32− SLOT(onShowHome(const QString &)));
38+ connect(m_broadcaster, SIGNAL(StartUrl(const QString &, const QString &)),
39+ this, SLOT(onStartUrl(const QString &, const QString &)));
40+
41+ connect(m_broadcaster, SIGNAL(ShowHome(const QString &)),
42+ this, SLOT(onShowHome(const QString &)));
43+}
44+
45+void SessionBroadcast::requestUrlStart(const QString &username, const QString &url)
46+{
47+ m_broadcaster->asyncCall(QStringLiteral("RequestUrlStart"), username, url);
48+}
49+
50+void SessionBroadcast::requestHomeShown(const QString &username)
51+{
52+ m_broadcaster->asyncCall(QStringLiteral("RequestHomeShown"), username);
53+}
54+
55+void SessionBroadcast::onStartUrl(const QString &username, const QString &url)
56+{
57+ // Since this signal is just used for testing, we don't *really* care if
58+ // username matches, but just in case we do eventually use the signal, we
59+ // should only listen to our own requests.
60+ if (username == m_username) {
61+ Q_EMIT startUrl(url);
62+ }
3363}
3464
3565void SessionBroadcast::onShowHome(const QString &username)
3666{
3767 // Only listen to requests meant for us
38− if (username == qgetenv("USER")) {
68+ if (username == m_username) {
3969 Q_EMIT showHome();
4070 }
4171}
plugins/SessionBroadcast/SessionBroadcast.h+13−3
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013,2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,8 +12,6 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Terry <michael.terry@canonical.com>
1715 */
1816
1917#ifndef UNITY_SESSIONBROADCAST_H
@@ -31,11 +29,23 @@ class SessionBroadcast: public QObject
3129public:
3230 explicit SessionBroadcast(QObject *parent = 0);
3331
32+ Q_INVOKABLE void requestUrlStart(const QString &username, const QString &url);
33+ Q_INVOKABLE void requestHomeShown(const QString &username);
34+
3435Q_SIGNALS:
36+ // This signal isn't actually used by the shell
37+ // (unity-greeter-session-broadcast handles launching an app for us), but
38+ // it's useful for testing the plugin.
39+ void startUrl(const QString &url);
3540 void showHome();
3641
3742private Q_SLOTS:
43+ void onStartUrl(const QString &username, const QString &url);
3844 void onShowHome(const QString &username);
45+
46+private:
47+ QString m_username;
48+ QDBusInterface *m_broadcaster;
3949};
4050
4151#endif
plugins/SessionBroadcast/SessionBroadcast.qmltypesdeleted−19
@@ -1,19 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable SessionBroadcast 0.1 plugins'
8−
9−Module {
10− Component {
11− name: "SessionBroadcast"
12− prototype: "QObject"
13− exports: ["SessionBroadcast/SessionBroadcast 0.1"]
14− isCreatable: false
15− isSingleton: true
16− exportMetaObjectRevisions: [0]
17− Signal { name: "showHome" }
18− }
19−}
plugins/UInput/CMakeLists.txtnew file+7
@@ -0,0 +1,7 @@
1+add_library(UInput-qml MODULE
2+ plugin.cpp
3+ uinput.cpp
4+)
5+
6+target_link_libraries(UInput-qml Qt5::Qml)
7+add_unity8_plugin(UInput 0.1 UInput TARGETS UInput-qml)
plugins/UInput/plugin.cppnew file+26
@@ -0,0 +1,26 @@
1+/*
2+ * Copyright (C) 2015 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "plugin.h"
18+#include "uinput.h"
19+
20+#include <QtQml/qqml.h>
21+
22+void UInputPlugin::registerTypes(const char *uri)
23+{
24+ Q_ASSERT(uri == QLatin1String("UInput"));
25+ qmlRegisterType<UInput>(uri, 0, 1, "UInput");
26+}
plugins/Dash/plugin.h → plugins/UInput/plugin.hrenamed+4−5
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012 Canonical, Ltd.
2+ * Copyright (C) 2015 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,16 +12,15 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
1615 */
1716
18−#ifndef DASH_PLUGIN_H
19−#define DASH_PLUGIN_H
17+#ifndef UINPUT_PLUGIN_H
18+#define UINPUT_PLUGIN_H
2019
2120#include <QtQml/QQmlEngine>
2221#include <QtQml/QQmlExtensionPlugin>
2322
24−class DashPlugin : public QQmlExtensionPlugin
23+class UInputPlugin : public QQmlExtensionPlugin
2524{
2625 Q_OBJECT
2726 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
plugins/UInput/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module UInput
2+plugin UInput-qml
3+typeinfo UInput.qmltypes
plugins/UInput/uinput.cppnew file+182
@@ -0,0 +1,182 @@
1+/*
2+ * Copyright (C) 2015 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "uinput.h"
18+
19+#include <QFile>
20+#include <QDebug>
21+#include <QDateTime>
22+
23+#include <unistd.h>
24+#include <time.h>
25+
26+UInput::UInput(QObject *parent) :
27+ QObject(parent)
28+{
29+ m_devName = QByteArrayLiteral("unity8-simulated-mouse");
30+ m_uinput.setFileName(QStringLiteral("/dev/uinput"));
31+
32+ memset(&m_uinput_mouse_dev, 0, sizeof(m_uinput_mouse_dev));
33+ m_uinput_mouse_dev.id.bustype = BUS_USB;
34+ m_uinput_mouse_dev.id.version = 1;
35+ strncpy(m_uinput_mouse_dev.name, m_devName.constData(), m_devName.length());
36+}
37+
38+UInput::~UInput()
39+{
40+ if (m_mouseCreated) {
41+ removeMouse();
42+ }
43+}
44+
45+void UInput::createMouse()
46+{
47+ if (m_mouseCreated) {
48+ qDebug() << "Already have a virtual device. Not creating another one.";
49+ return;
50+ }
51+
52+ if (!m_uinput.isOpen() && !m_uinput.open(QFile::WriteOnly)) {
53+ return;
54+ }
55+
56+ ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_REL);
57+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_X);
58+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_Y);
59+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_HWHEEL);
60+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_WHEEL);
61+
62+ ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_KEY);
63+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_MOUSE);
64+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_LEFT);
65+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_MIDDLE);
66+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_RIGHT);
67+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_FORWARD);
68+ ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_BACK);
69+
70+ ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_SYN);
71+
72+ int len = write(m_uinput.handle(), &m_uinput_mouse_dev, sizeof(m_uinput_mouse_dev));
73+ if (len <= 0) {
74+ qWarning() << "Failed to write to uinput. Cannot create virtual uinput mouse.";
75+ return;
76+ }
77+
78+ int err = ioctl(m_uinput.handle(), UI_DEV_CREATE);
79+ if (err != 0) {
80+ qWarning() << "Cannot create virtual uinput device. Create ioctl failed:" << err;
81+ return;
82+ }
83+ m_mouseCreated = true;
84+ qDebug() << "Virtual uinput mouse device created.";
85+}
86+
87+void UInput::removeMouse()
88+{
89+ if (!m_mouseCreated) {
90+ return;
91+ }
92+
93+ if (!m_uinput.isOpen() && !m_uinput.open(QFile::WriteOnly)) {
94+ qWarning() << "cannot open uinput... ";
95+ return;
96+ }
97+
98+ int err = ioctl(m_uinput.handle(), UI_DEV_DESTROY);
99+ if (err != 0) {
100+ qWarning() << "Failed to destroy virtual uinput device. Destroy ioctl failed:" << err;
101+ } else {
102+ qDebug() << "Virtual uinput mouse device removed.";
103+ }
104+ m_uinput.close();
105+ m_mouseCreated = false;
106+}
107+
108+void UInput::moveMouse(int dx, int dy)
109+{
110+ struct input_event event;
111+ memset(&event, 0, sizeof(event));
112+ clock_gettime(CLOCK_MONOTONIC, (timespec*)&event.time);
113+ event.type = EV_REL;
114+ event.code = REL_X;
115+ event.value = dx;
116+ write(m_uinput.handle(), &event, sizeof(event));
117+
118+ event.code = REL_Y;
119+ event.value = dy;
120+ write(m_uinput.handle(), &event, sizeof(event));
121+
122+ event.type = EV_SYN;
123+ event.code = SYN_REPORT;
124+ event.value = 0;
125+ write(m_uinput.handle(), &event, sizeof(event));
126+}
127+
128+void UInput::pressMouse(Button button)
129+{
130+ injectMouse(button, 1);
131+}
132+
133+void UInput::releaseMouse(Button button)
134+{
135+ injectMouse(button, 0);
136+}
137+
138+void UInput::scrollMouse(int dh, int dv)
139+{
140+ struct input_event event;
141+ memset(&event, 0, sizeof(event));
142+ clock_gettime(CLOCK_MONOTONIC, (timespec*)&event.time);
143+ event.type = EV_REL;
144+ event.code = REL_HWHEEL;
145+ event.value = dh;
146+ write(m_uinput.handle(), &event, sizeof(event));
147+
148+ event.code = REL_WHEEL;
149+ event.value = dv;
150+ write(m_uinput.handle(), &event, sizeof(event));
151+
152+ event.type = EV_SYN;
153+ event.code = SYN_REPORT;
154+ event.value = 0;
155+ write(m_uinput.handle(), &event, sizeof(event));
156+}
157+
158+void UInput::injectMouse(Button button, int down)
159+{
160+ struct input_event event;
161+ memset(&event, 0, sizeof(event));
162+ clock_gettime(CLOCK_MONOTONIC, (timespec*)&event.time);
163+ event.type = EV_KEY;
164+ switch (button) {
165+ case ButtonLeft:
166+ event.code = BTN_LEFT;
167+ break;
168+ case ButtonRight:
169+ event.code = BTN_RIGHT;
170+ break;
171+ case ButtonMiddle:
172+ event.code = BTN_MIDDLE;
173+ break;
174+ }
175+ event.value = down;
176+ write(m_uinput.handle(), &event, sizeof(event));
177+
178+ event.type = EV_SYN;
179+ event.code = SYN_REPORT;
180+ event.value = 0;
181+ write(m_uinput.handle(), &event, sizeof(event));
182+}
plugins/UInput/uinput.hnew file+61
@@ -0,0 +1,61 @@
1+/*
2+ * Copyright (C) 2015 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+
18+#ifndef UINPUT_H
19+#define UINPUT_H
20+
21+#include <QObject>
22+#include <QFile>
23+
24+#include <linux/uinput.h>
25+
26+
27+class UInput : public QObject
28+{
29+ Q_OBJECT
30+
31+public:
32+ enum Button {
33+ ButtonLeft,
34+ ButtonRight,
35+ ButtonMiddle
36+ };
37+ Q_ENUM(Button)
38+
39+ explicit UInput(QObject *parent = nullptr);
40+ ~UInput();
41+
42+ Q_INVOKABLE void createMouse();
43+ Q_INVOKABLE void removeMouse();
44+
45+ Q_INVOKABLE void moveMouse(int dx, int dy);
46+ Q_INVOKABLE void pressMouse(Button button);
47+ Q_INVOKABLE void releaseMouse(Button button);
48+ Q_INVOKABLE void scrollMouse(int dh, int dv);
49+
50+private:
51+ void injectMouse(Button button, int down);
52+
53+private:
54+ QFile m_uinput;
55+ uinput_user_dev m_uinput_mouse_dev;
56+ QByteArray m_devName;
57+
58+ bool m_mouseCreated = false;
59+};
60+
61+#endif // UINPUT_H
plugins/Ubuntu/CMakeLists.txt−2
@@ -1,4 +1,2 @@
11add_subdirectory(Gestures)
22add_subdirectory(DownloadDaemonListener)
3−add_subdirectory(Payments)
4−add_subdirectory(SystemImage)
plugins/Ubuntu/DownloadDaemonListener/CMakeLists.txt+6−3
@@ -1,7 +1,6 @@
11include_directories(
22 ${CMAKE_CURRENT_SOURCE_DIR}
33 ${CMAKE_CURRENT_BINARY_DIR}
4− ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
54)
65
76set(DOWNLOADDAEMONLISTENER_SOURCES
@@ -12,6 +11,10 @@ set(DOWNLOADDAEMONLISTENER_SOURCES
1211
1312add_library(DownloadDaemonListener MODULE ${DOWNLOADDAEMONLISTENER_SOURCES})
1413
15−qt5_use_modules(DownloadDaemonListener Qml Quick DBus Core)
16−
14+pkg_check_modules(DDLADAPTER REQUIRED udm-common)
15+add_definitions(${DDLADAPTER_CFLAGS} ${DDLADAPTER_CFLAGS_OTHER})
16+target_link_libraries(DownloadDaemonListener
17+ Qt5::Qml Qt5::Quick Qt5::DBus Qt5::Core
18+ ${DDLADAPTER_LIBRARIES}
19+ )
1720add_unity8_plugin(Ubuntu.DownloadDaemonListener 0.1 Ubuntu/DownloadDaemonListener TARGETS DownloadDaemonListener)
plugins/Ubuntu/DownloadDaemonListener/DownloadDaemonListener.qmltypesdeleted−60
@@ -1,60 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable Ubuntu.DownloadDaemonListener 0.1 plugins'
8−
9−Module {
10− Component {
11− name: "DownloadTracker"
12− prototype: "QObject"
13− exports: ["Ubuntu.DownloadDaemonListener/DownloadTracker 0.1"]
14− exportMetaObjectRevisions: [0]
15− Property { name: "service"; type: "string" }
16− Property { name: "dbusPath"; type: "string" }
17− Property { name: "serviceReady"; type: "bool"; isReadonly: true }
18− Signal {
19− name: "serviceChanged"
20− Parameter { name: "service"; type: "string" }
21− }
22− Signal {
23− name: "dbusPathChanged"
24− Parameter { name: "dbusPath"; type: "string" }
25− }
26− Signal {
27− name: "serviceReadyChanged"
28− Parameter { name: "serviceReady"; type: "bool" }
29− }
30− Signal {
31− name: "canceled"
32− Parameter { name: "success"; type: "bool" }
33− }
34− Signal {
35− name: "error"
36− Parameter { name: "error"; type: "string" }
37− }
38− Signal {
39− name: "finished"
40− Parameter { name: "path"; type: "string" }
41− }
42− Signal {
43− name: "paused"
44− Parameter { name: "success"; type: "bool" }
45− }
46− Signal {
47− name: "progress"
48− Parameter { name: "received"; type: "qulonglong" }
49− Parameter { name: "total"; type: "qulonglong" }
50− }
51− Signal {
52− name: "resumed"
53− Parameter { name: "success"; type: "bool" }
54− }
55− Signal {
56− name: "started"
57− Parameter { name: "success"; type: "bool" }
58− }
59− }
60−}
plugins/Ubuntu/DownloadDaemonListener/DownloadTracker.cpp+2−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 - Canonical Ltd.
2+ * Copyright (C) 2013-2016 Canonical Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it
55 * under the terms of the GNU Lesser General Public License, as
@@ -78,6 +78,7 @@ void DownloadTracker::startService()
7878 connect(m_adaptor, static_cast<void (DownloadTrackerAdaptor::*)(qulonglong, qulonglong)>(&DownloadTrackerAdaptor::progress), this, &DownloadTracker::progress);
7979 connect(m_adaptor, &DownloadTrackerAdaptor::resumed, this, &DownloadTracker::resumed);
8080 connect(m_adaptor, &DownloadTrackerAdaptor::started, this, &DownloadTracker::started);
81+ connect(m_adaptor, &DownloadTrackerAdaptor::processing, this, &DownloadTracker::processing);
8182 }
8283 // FIXME find a better way of determining if the service is ready
8384 Q_EMIT serviceReadyChanged(m_adaptor && m_adaptor->isValid());
plugins/Ubuntu/DownloadDaemonListener/DownloadTracker.h+2−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 - Canonical Ltd.
2+ * Copyright (C) 2013-2016 Canonical Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it
55 * under the terms of the GNU Lesser General Public License, as
@@ -54,6 +54,7 @@ Q_SIGNALS:
5454 void error(const QString &error);
5555 void finished(const QString &path);
5656 void paused(bool success);
57+ void processing(const QString &path);
5758 void progress(qulonglong received, qulonglong total);
5859 void resumed(bool success);
5960 void started(bool success);
plugins/Ubuntu/DownloadDaemonListener/interface/downloadtrackeradaptor.cpp+2−2
@@ -1,8 +1,8 @@
11/*
22 * This file was generated by qdbusxml2cpp version 0.8
3− * Command line was: qdbusxml2cpp -v -c DownloadTrackerAdaptor -p downloadtrackeradaptor.h:downloadtrackeradaptor.cpp -i metatypes.h com.canonical.applications.download.xml
3+ * Command line was: qdbusxml2cpp -v -c DownloadTrackerAdaptor -p downloadtrackeradaptor.h:downloadtrackeradaptor.cpp -i metatypes.h ../../../../../../ubuntu-download-manager/trunk/docs/dbus/com.canonical.applications.download.xml
44 *
5− * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
5+ * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
66 *
77 * This is an auto-generated file.
88 * This file may have been hand-edited. Look for HAND-EDIT comments
plugins/Ubuntu/DownloadDaemonListener/interface/downloadtrackeradaptor.h+71−4
@@ -1,15 +1,15 @@
11/*
22 * This file was generated by qdbusxml2cpp version 0.8
3− * Command line was: qdbusxml2cpp -v -c DownloadTrackerAdaptor -p downloadtrackeradaptor.h:downloadtrackeradaptor.cpp -i metatypes.h com.canonical.applications.download.xml
3+ * Command line was: qdbusxml2cpp -v -c DownloadTrackerAdaptor -p downloadtrackeradaptor.h:downloadtrackeradaptor.cpp -i metatypes.h ../../../../../../ubuntu-download-manager/trunk/docs/dbus/com.canonical.applications.download.xml
44 *
5− * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
5+ * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
66 *
77 * This is an auto-generated file.
88 * Do not edit! All changes made to it will be lost.
99 */
1010
11−#ifndef DOWNLOADTRACKERADAPTOR_H_1374434371
12−#define DOWNLOADTRACKERADAPTOR_H_1374434371
11+#ifndef DOWNLOADTRACKERADAPTOR_H
12+#define DOWNLOADTRACKERADAPTOR_H
1313
1414#include <QtCore/QObject>
1515#include <QtCore/QByteArray>
@@ -36,6 +36,22 @@ public:
3636
3737 ~DownloadTrackerAdaptor();
3838
39+ Q_PROPERTY(QString ClickPackage READ clickPackage)
40+ inline QString clickPackage() const
41+ { return qvariant_cast< QString >(property("ClickPackage")); }
42+
43+ Q_PROPERTY(QString DestinationApp READ destinationApp)
44+ inline QString destinationApp() const
45+ { return qvariant_cast< QString >(property("DestinationApp")); }
46+
47+ Q_PROPERTY(bool ShowInIndicator READ showInIndicator)
48+ inline bool showInIndicator() const
49+ { return qvariant_cast< bool >(property("ShowInIndicator")); }
50+
51+ Q_PROPERTY(QString Title READ title)
52+ inline QString title() const
53+ { return qvariant_cast< QString >(property("Title")); }
54+
3955public Q_SLOTS: // METHODS
4056 inline QDBusPendingReply<> allowGSMDownload(bool allowed)
4157 {
@@ -50,6 +66,24 @@ public Q_SLOTS: // METHODS
5066 return asyncCallWithArgumentList(QStringLiteral("cancel"), argumentList);
5167 }
5268
69+ inline QDBusPendingReply<> collected()
70+ {
71+ QList<QVariant> argumentList;
72+ return asyncCallWithArgumentList(QStringLiteral("collected"), argumentList);
73+ }
74+
75+ inline QDBusPendingReply<QString> filePath()
76+ {
77+ QList<QVariant> argumentList;
78+ return asyncCallWithArgumentList(QStringLiteral("filePath"), argumentList);
79+ }
80+
81+ inline QDBusPendingReply<StringMap> headers()
82+ {
83+ QList<QVariant> argumentList;
84+ return asyncCallWithArgumentList(QStringLiteral("headers"), argumentList);
85+ }
86+
5387 inline QDBusPendingReply<bool> isGSMDownloadAllowed()
5488 {
5589 QList<QVariant> argumentList;
@@ -80,6 +114,27 @@ public Q_SLOTS: // METHODS
80114 return asyncCallWithArgumentList(QStringLiteral("resume"), argumentList);
81115 }
82116
117+ inline QDBusPendingReply<> setDestinationDir(const QString &path)
118+ {
119+ QList<QVariant> argumentList;
120+ argumentList << QVariant::fromValue(path);
121+ return asyncCallWithArgumentList(QStringLiteral("setDestinationDir"), argumentList);
122+ }
123+
124+ inline QDBusPendingReply<> setHeaders(StringMap headers)
125+ {
126+ QList<QVariant> argumentList;
127+ argumentList << QVariant::fromValue(headers);
128+ return asyncCallWithArgumentList(QStringLiteral("setHeaders"), argumentList);
129+ }
130+
131+ inline QDBusPendingReply<> setMetadata(const QVariantMap &data)
132+ {
133+ QList<QVariant> argumentList;
134+ argumentList << QVariant::fromValue(data);
135+ return asyncCallWithArgumentList(QStringLiteral("setMetadata"), argumentList);
136+ }
137+
83138 inline QDBusPendingReply<> setThrottle(qulonglong speed)
84139 {
85140 QList<QVariant> argumentList;
@@ -93,6 +148,12 @@ public Q_SLOTS: // METHODS
93148 return asyncCallWithArgumentList(QStringLiteral("start"), argumentList);
94149 }
95150
151+ inline QDBusPendingReply<int> state()
152+ {
153+ QList<QVariant> argumentList;
154+ return asyncCallWithArgumentList(QStringLiteral("state"), argumentList);
155+ }
156+
96157 inline QDBusPendingReply<qulonglong> throttle()
97158 {
98159 QList<QVariant> argumentList;
@@ -106,10 +167,16 @@ public Q_SLOTS: // METHODS
106167 }
107168
108169Q_SIGNALS: // SIGNALS
170+ void authError(AuthErrorStruct error);
109171 void canceled(bool success);
110172 void error(const QString &error);
111173 void finished(const QString &path);
174+ void hashError(HashErrorStruct error);
175+ void httpError(HttpErrorStruct error);
176+ void networkError(NetworkErrorStruct error);
112177 void paused(bool success);
178+ void processError(ProcessErrorStruct error);
179+ void processing(const QString &path);
113180 void progress(qulonglong received, qulonglong total);
114181 void resumed(bool success);
115182 void started(bool success);
plugins/Ubuntu/DownloadDaemonListener/interface/metatypes.h+3−6
@@ -1,5 +1,5 @@
11/*
2− * Copyright 2013 2013 Canonical Ltd.
2+ * Copyright 2013-2016 Canonical Ltd.
33 *
44 * This library is free software; you can redistribute it and/or
55 * modify it under the terms of version 3 of the GNU Lesser General Public
@@ -19,10 +19,7 @@
1919#ifndef DOWNLOADER_LIB_APP_METATYPES_H
2020#define DOWNLOADER_LIB_APP_METATYPES_H
2121
22−#include <QMap>
23−
24−typedef QMap<QString, QString> StringMap;
25−
26−Q_DECLARE_METATYPE(StringMap)
22+// Just include the system file so we're always up to date.
23+#include <ubuntu/download_manager/metatypes.h>
2724
2825#endif // METATYPES_H
plugins/Ubuntu/Gestures/AxisVelocityCalculator.cpp+1−1
@@ -21,7 +21,7 @@
2121#include "AxisVelocityCalculator.h"
2222#include <QtCore/QElapsedTimer>
2323
24−using namespace UbuntuGestures;
24+UG_USE_NAMESPACE
2525
2626AxisVelocityCalculator::AxisVelocityCalculator(QObject *parent)
2727 : AxisVelocityCalculator(SharedTimeSource(new RealTimeSource), parent)
plugins/Ubuntu/Gestures/AxisVelocityCalculator.h+4−4
@@ -24,7 +24,7 @@
2424#include "UbuntuGesturesQmlGlobal.h"
2525#include <stdint.h>
2626#include <QtCore/QObject>
27−#include "TimeSource.h"
27+#include <UbuntuGestures/private/timesource_p.h>
2828
2929/*
3030 Estimates the current velocity of a finger based on recent movement along an axis
@@ -68,7 +68,7 @@ public:
6868 /*
6969 Constructor that takes a TimeSource
7070 */
71− AxisVelocityCalculator(const UbuntuGestures::SharedTimeSource &timeSource, QObject *parent = 0);
71+ AxisVelocityCalculator(const UG_PREPEND_NAMESPACE(SharedTimeSource) &timeSource, QObject *parent = 0);
7272
7373 virtual ~AxisVelocityCalculator();
7474
@@ -90,7 +90,7 @@ public:
9090 /*
9191 Replaces the TimeSource with the given one. Useful for testing purposes.
9292 */
93− void setTimeSource(const UbuntuGestures::SharedTimeSource &timeSource);
93+ void setTimeSource(const UG_PREPEND_NAMESPACE(SharedTimeSource) &timeSource);
9494
9595 /*
9696 The minimum amount of samples needed for a velocity calculation.
@@ -138,7 +138,7 @@ private:
138138 int m_samplesRead; /* index of the oldest sample available. -1 if buffer is empty */
139139 int m_samplesWrite; /* index where the next sample will be written */
140140
141− UbuntuGestures::SharedTimeSource m_timeSource;
141+ UG_PREPEND_NAMESPACE(SharedTimeSource) m_timeSource;
142142
143143 qreal m_trackedPosition;
144144};
plugins/Ubuntu/Gestures/CMakeLists.txt+12−8
@@ -4,26 +4,29 @@ remove_definitions(-DQT_NO_KEYWORDS)
44set(UbuntuGesturesQml_SOURCES
55 plugin.cpp
66 AxisVelocityCalculator.cpp
7− Damper.cpp
87 Direction.cpp
9− DirectionalDragArea.cpp
10− FloatingFlickable.cpp
8+ MouseEventGenerator.cpp
119 PressedOutsideNotifier.cpp
1210 TouchDispatcher.cpp
1311 TouchGate.cpp
12+ TouchGestureArea.cpp
1413)
1514
16−add_definitions(-DUBUNTUGESTURESQML_LIBRARY)
15+pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
1716
18−add_library(UbuntuGesturesQml MODULE ${UbuntuGesturesQml_SOURCES})
19−target_link_libraries(UbuntuGesturesQml UbuntuGestures)
17+add_definitions(-DUBUNTUGESTURESQML_LIBRARY)
2018
21−qt5_use_modules(UbuntuGesturesQml Core Quick)
19+add_library(UbuntuGesturesQml SHARED ${UbuntuGesturesQml_SOURCES})
20+target_link_libraries(UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES} Qt5::Core Qt5::Quick)
2221
2322# So that Foo.cpp can #include "Foo.moc"
2423include_directories(${CMAKE_CURRENT_BINARY_DIR})
2524
26−include_directories(${CMAKE_SOURCE_DIR}/libs/UbuntuGestures)
25+include_directories(
26+ SYSTEM
27+ ${UBUNTUGESTURES_INCLUDE_DIRS}
28+ ${UBUNTUGESTURES_INCLUDEDIR}/UbuntuGestures/${UBUNTUGESTURES_VERSION}
29+)
2730
2831# There's no cmake var for v8 include path :-/ so create one
2932LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
@@ -31,6 +34,7 @@ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/QtV8/${Qt5Core_VERSION_STRING}/QtV8)
3134
3235# DANGER! DANGER! Using Qt's private API!
3336include_directories(
37+ SYSTEM
3438 ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
3539 ${Qt5Quick_INCLUDE_DIRS}
3640 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
plugins/Ubuntu/Gestures/Damper.hdeleted−89
@@ -1,89 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTU_GESTURES_DAMPER_H
18−#define UBUNTU_GESTURES_DAMPER_H
19−
20−#include <QtCore/QPointF>
21−
22−/*
23− Decreases the oscillations of a value along an axis.
24− */
25−template <class Type> class Damper {
26−public:
27− Damper() : m_value(0), m_maxDelta(0) { }
28−
29− // Maximum delta between the raw value and its dampened counterpart.
30− void setMaxDelta(Type maxDelta) {
31− if (maxDelta < 0) qFatal("Damper::maxDelta must be a positive number.");
32− m_maxDelta = maxDelta;
33− }
34− Type maxDelta() const { return m_maxDelta; }
35−
36− void reset(Type value) {
37− m_value = value;
38− }
39−
40− Type update(Type value) {
41− Type delta = value - m_value;
42− if (delta > 0 && delta > m_maxDelta) {
43− m_value += delta - m_maxDelta;
44− } else if (delta < 0 && delta < -m_maxDelta) {
45− m_value += delta + m_maxDelta;
46− }
47−
48− return m_value;
49− }
50−
51− Type value() const { return m_value; }
52−
53−private:
54− Type m_value;
55− Type m_maxDelta;
56−};
57−
58−/*
59− A point that has its movement dampened.
60− */
61−class DampedPointF {
62−public:
63− void setMaxDelta(qreal maxDelta) {
64− m_x.setMaxDelta(maxDelta);
65− m_y.setMaxDelta(maxDelta);
66− }
67−
68− qreal maxDelta() const { return m_x.maxDelta(); }
69−
70− void reset(const QPointF point) {
71− m_x.reset(point.x());
72− m_y.reset(point.y());
73− }
74−
75− void update(const QPointF point) {
76− m_x.update(point.x());
77− m_y.update(point.y());
78− }
79−
80− qreal x() const { return m_x.value(); }
81− qreal y() const { return m_y.value(); }
82−private:
83− Damper<qreal> m_x;
84− Damper<qreal> m_y;
85−};
86−
87−QDebug operator<<(QDebug dbg, const DampedPointF &p);
88−
89−#endif // UBUNTU_GESTURES_DAMPER_H
plugins/Ubuntu/Gestures/Direction.h+2−1
@@ -26,9 +26,9 @@
2626 */
2727class UBUNTUGESTURESQML_EXPORT Direction : public QObject {
2828 Q_OBJECT
29− Q_ENUMS(Type)
3029
3130public:
31+ // Make sure it is kept synchronized with SDK UCSwipeArea::Direction
3232 enum Type {
3333 Rightwards, // Along the positive direction of the X axis
3434 Leftwards, // Along the negative direction of the X axis
@@ -37,6 +37,7 @@ public:
3737 Horizontal, // Along the X axis, in any direction
3838 Vertical // Along the Y axis, in any direction
3939 };
40+ Q_ENUM(Type)
4041
4142 Q_INVOKABLE static bool isHorizontal(Direction::Type type);
4243 Q_INVOKABLE static bool isVertical(Direction::Type type);
plugins/Ubuntu/Gestures/DirectionalDragArea.cppdeleted−888
@@ -1,888 +0,0 @@
1−/*
2− * Copyright (C) 2013-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#define ACTIVETOUCHESINFO_DEBUG 0
18−#define DIRECTIONALDRAGAREA_DEBUG 0
19−
20−#include "DirectionalDragArea.h"
21−
22−#include <QQuickWindow>
23−#include <QtCore/qmath.h>
24−#include <QScreen>
25−#include <QDebug>
26−
27−#pragma GCC diagnostic push
28−#pragma GCC diagnostic ignored "-pedantic"
29−#include <private/qquickwindow_p.h>
30−#pragma GCC diagnostic pop
31−
32−// local
33−#include "TouchOwnershipEvent.h"
34−#include "TouchRegistry.h"
35−#include "UnownedTouchEvent.h"
36−
37−#include "DirectionalDragArea_p.h"
38−
39−using namespace UbuntuGestures;
40−
41−#if DIRECTIONALDRAGAREA_DEBUG
42−#define ddaDebug(params) qDebug().nospace() << "[DDA(" << qPrintable(objectName()) << ")] " << params
43−#include "DebugHelpers.h"
44−
45−namespace {
46−const char *statusToString(DirectionalDragAreaPrivate::Status status)
47−{
48− if (status == DirectionalDragAreaPrivate::WaitingForTouch) {
49− return "WaitingForTouch";
50− } else if (status == DirectionalDragAreaPrivate::Undecided) {
51− return "Undecided";
52− } else {
53− return "Recognized";
54− }
55−}
56−
57−} // namespace {
58−#else // DIRECTIONALDRAGAREA_DEBUG
59−#define ddaDebug(params) ((void)0)
60−#endif // DIRECTIONALDRAGAREA_DEBUG
61−
62−DirectionalDragArea::DirectionalDragArea(QQuickItem *parent)
63− : QQuickItem(parent)
64− , d(new DirectionalDragAreaPrivate(this))
65−{
66− d->setRecognitionTimer(new Timer(this));
67− d->recognitionTimer->setInterval(d->maxTime);
68− d->recognitionTimer->setSingleShot(true);
69−
70− connect(this, &QQuickItem::enabledChanged, d, &DirectionalDragAreaPrivate::giveUpIfDisabledOrInvisible);
71− connect(this, &QQuickItem::visibleChanged, d, &DirectionalDragAreaPrivate::giveUpIfDisabledOrInvisible);
72−}
73−
74−Direction::Type DirectionalDragArea::direction() const
75−{
76− return d->direction;
77−}
78−
79−void DirectionalDragArea::setDirection(Direction::Type direction)
80−{
81− if (direction != d->direction) {
82− d->direction = direction;
83− Q_EMIT directionChanged(d->direction);
84− }
85−}
86−
87−void DirectionalDragAreaPrivate::setDistanceThreshold(qreal value)
88−{
89− if (distanceThreshold != value) {
90− distanceThreshold = value;
91− distanceThresholdSquared = distanceThreshold * distanceThreshold;
92− }
93−}
94−
95−void DirectionalDragAreaPrivate::setMaxTime(int value)
96−{
97− if (maxTime != value) {
98− maxTime = value;
99− recognitionTimer->setInterval(maxTime);
100− }
101−}
102−
103−void DirectionalDragAreaPrivate::setRecognitionTimer(UbuntuGestures::AbstractTimer *timer)
104−{
105− int interval = 0;
106− bool timerWasRunning = false;
107− bool wasSingleShot = false;
108−
109− // can be null when called from the constructor
110− if (recognitionTimer) {
111− interval = recognitionTimer->interval();
112− timerWasRunning = recognitionTimer->isRunning();
113− if (recognitionTimer->parent() == this) {
114− delete recognitionTimer;
115− }
116− }
117−
118− recognitionTimer = timer;
119− timer->setInterval(interval);
120− timer->setSingleShot(wasSingleShot);
121− connect(timer, &UbuntuGestures::AbstractTimer::timeout,
122− this, &DirectionalDragAreaPrivate::rejectGesture);
123− if (timerWasRunning) {
124− recognitionTimer->start();
125− }
126−}
127−
128−void DirectionalDragAreaPrivate::setTimeSource(const SharedTimeSource &timeSource)
129−{
130− this->timeSource = timeSource;
131− activeTouches.m_timeSource = timeSource;
132−}
133−
134−qreal DirectionalDragArea::distance() const
135−{
136− if (Direction::isHorizontal(d->direction)) {
137− return d->publicPos.x() - d->startPos.x();
138− } else {
139− return d->publicPos.y() - d->startPos.y();
140− }
141−}
142−
143−void DirectionalDragAreaPrivate::updateSceneDistance()
144−{
145− QPointF totalMovement = publicScenePos - startScenePos;
146− sceneDistance = projectOntoDirectionVector(totalMovement);
147−}
148−
149−qreal DirectionalDragArea::sceneDistance() const
150−{
151− return d->sceneDistance;
152−}
153−
154−qreal DirectionalDragArea::touchX() const
155−{
156− return d->publicPos.x();
157−}
158−
159−qreal DirectionalDragArea::touchY() const
160−{
161− return d->publicPos.y();
162−}
163−
164−qreal DirectionalDragArea::touchSceneX() const
165−{
166− return d->publicScenePos.x();
167−}
168−
169−qreal DirectionalDragArea::touchSceneY() const
170−{
171− return d->publicScenePos.y();
172−}
173−
174−bool DirectionalDragArea::dragging() const
175−{
176− return d->status == DirectionalDragAreaPrivate::Recognized;
177−}
178−
179−bool DirectionalDragArea::pressed() const
180−{
181− return d->status != DirectionalDragAreaPrivate::WaitingForTouch;
182−}
183−
184−bool DirectionalDragArea::immediateRecognition() const
185−{
186− return d->immediateRecognition;
187−}
188−
189−void DirectionalDragArea::setImmediateRecognition(bool enabled)
190−{
191− if (d->immediateRecognition != enabled) {
192− d->immediateRecognition = enabled;
193− Q_EMIT immediateRecognitionChanged(enabled);
194− }
195−}
196−
197−void DirectionalDragArea::removeTimeConstraints()
198−{
199− d->setMaxTime(60 * 60 * 1000);
200− d->compositionTime = 0;
201− ddaDebug("removed time constraints");
202−}
203−
204−bool DirectionalDragArea::event(QEvent *event)
205−{
206− if (event->type() == TouchOwnershipEvent::touchOwnershipEventType()) {
207− d->touchOwnershipEvent(static_cast<TouchOwnershipEvent *>(event));
208− return true;
209− } else if (event->type() == UnownedTouchEvent::unownedTouchEventType()) {
210− d->unownedTouchEvent(static_cast<UnownedTouchEvent *>(event));
211− return true;
212− } else {
213− return QQuickItem::event(event);
214− }
215−}
216−
217−void DirectionalDragAreaPrivate::touchOwnershipEvent(TouchOwnershipEvent *event)
218−{
219− if (event->gained()) {
220− QVector<int> ids;
221− ids.append(event->touchId());
222− ddaDebug("grabbing touch");
223− q->grabTouchPoints(ids);
224−
225− // Work around for Qt bug. If we grab a touch that is being used for mouse pointer
226− // emulation it will cause the emulation logic to go nuts.
227− // Thus we have to also grab the mouse in this case.
228− //
229− // The fix for this bug has landed in Qt 5.4 (https://codereview.qt-project.org/96887)
230− // TODO: Remove this workaround once we start using Qt 5.4
231− if (q->window()) {
232− QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(q->window());
233− if (windowPrivate->touchMouseId == event->touchId() && q->window()->mouseGrabberItem()) {
234− ddaDebug("removing mouse grabber");
235− q->window()->mouseGrabberItem()->ungrabMouse();
236− }
237− }
238− } else {
239− // We still wanna know when it ends for keeping the composition time window up-to-date
240− TouchRegistry::instance()->addTouchWatcher(touchId, q);
241−
242− setStatus(WaitingForTouch);
243− }
244−}
245−
246−void DirectionalDragAreaPrivate::unownedTouchEvent(UnownedTouchEvent *unownedTouchEvent)
247−{
248− QTouchEvent *event = unownedTouchEvent->touchEvent();
249−
250− Q_ASSERT(!event->touchPointStates().testFlag(Qt::TouchPointPressed));
251−
252− ddaDebug("Unowned " << timeSource->msecsSinceReference() << " " << qPrintable(touchEventToString(event)));
253−
254− switch (status) {
255− case WaitingForTouch:
256− // do nothing
257− break;
258− case Undecided:
259− Q_ASSERT(q->isEnabled() && q->isVisible());
260− unownedTouchEvent_undecided(unownedTouchEvent);
261− break;
262− default: // Recognized:
263− // do nothing
264− break;
265− }
266−
267− activeTouches.update(event);
268−}
269−
270−void DirectionalDragAreaPrivate::unownedTouchEvent_undecided(UnownedTouchEvent *unownedTouchEvent)
271−{
272− const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(unownedTouchEvent->touchEvent());
273− if (!touchPoint) {
274− qCritical() << "DirectionalDragArea[status=Undecided]: touch " << touchId
275− << "missing from UnownedTouchEvent without first reaching state Qt::TouchPointReleased. "
276− "Considering it as released.";
277−
278− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
279− setStatus(WaitingForTouch);
280− return;
281− }
282−
283− const QPointF &touchScenePos = touchPoint->scenePos();
284−
285− if (touchPoint->state() == Qt::TouchPointReleased) {
286− // touch has ended before recognition concluded
287− ddaDebug("Touch has ended before recognition concluded");
288− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
289− setStatus(WaitingForTouch);
290− return;
291− }
292−
293− previousDampedScenePos.setX(dampedScenePos.x());
294− previousDampedScenePos.setY(dampedScenePos.y());
295− dampedScenePos.update(touchScenePos);
296−
297− if (!movingInRightDirection()) {
298− ddaDebug("Rejecting gesture because touch point is moving in the wrong direction.");
299− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
300− // We still wanna know when it ends for keeping the composition time window up-to-date
301− TouchRegistry::instance()->addTouchWatcher(touchId, q);
302− setStatus(WaitingForTouch);
303− return;
304− }
305−
306− if (isWithinTouchCompositionWindow()) {
307− // There's still time for some new touch to appear and ruin our party as it would be combined
308− // with our touchId one and therefore deny the possibility of a single-finger gesture.
309− ddaDebug("Sill within composition window. Let's wait more.");
310− return;
311− }
312−
313− if (movedFarEnoughAlongGestureAxis()) {
314− TouchRegistry::instance()->requestTouchOwnership(touchId, q);
315− setStatus(Recognized);
316− setPublicPos(touchPoint->pos());
317− setPublicScenePos(touchScenePos);
318− } else if (isPastMaxDistance()) {
319− ddaDebug("Rejecting gesture because it went farther than maxDistance without getting recognized.");
320− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
321− // We still wanna know when it ends for keeping the composition time window up-to-date
322− TouchRegistry::instance()->addTouchWatcher(touchId, q);
323− setStatus(WaitingForTouch);
324− } else {
325− ddaDebug("Didn't move far enough yet. Let's wait more.");
326− }
327−}
328−
329−void DirectionalDragArea::touchEvent(QTouchEvent *event)
330−{
331− // TODO: Consider when more than one touch starts in the same event (although it's not possible
332− // with Mir's android-input). Have to track them all. Consider it a plus/bonus.
333−
334− ddaDebug(d->timeSource->msecsSinceReference() << " " << qPrintable(touchEventToString(event)));
335−
336− if (!isEnabled() || !isVisible()) {
337− QQuickItem::touchEvent(event);
338− return;
339− }
340−
341− switch (d->status) {
342− case DirectionalDragAreaPrivate::WaitingForTouch:
343− d->touchEvent_absent(event);
344− break;
345− case DirectionalDragAreaPrivate::Undecided:
346− d->touchEvent_undecided(event);
347− break;
348− default: // Recognized:
349− d->touchEvent_recognized(event);
350− break;
351− }
352−
353− d->activeTouches.update(event);
354−}
355−
356−void DirectionalDragAreaPrivate::touchEvent_absent(QTouchEvent *event)
357−{
358− // TODO: accept/reject is for the whole event, not per touch id. See how that affects us.
359−
360− if (!event->touchPointStates().testFlag(Qt::TouchPointPressed)) {
361− // Nothing to see here. No touch starting in this event.
362− return;
363− }
364−
365− // to be proven wrong, if that's the case
366− bool allGood = true;
367−
368− if (isWithinTouchCompositionWindow()) {
369− // too close to the last touch start. So we consider them as starting roughly at the same time.
370− // Can't be a single-touch gesture.
371− ddaDebug("A new touch point came in but we're still within time composition window. Ignoring it.");
372− allGood = false;
373− }
374−
375− const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
376−
377− const QTouchEvent::TouchPoint *newTouchPoint = nullptr;
378− for (int i = 0; i < touchPoints.count() && allGood; ++i) {
379− const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
380− if (touchPoint.state() == Qt::TouchPointPressed) {
381− if (newTouchPoint) {
382− // more than one touch starting in this QTouchEvent. Can't be a single-touch gesture
383− allGood = false;
384− } else {
385− // that's our candidate
386− newTouchPoint = &touchPoint;
387− }
388− }
389− }
390−
391− if (allGood) {
392− allGood = sanityCheckRecognitionProperties();
393− if (!allGood) {
394− qWarning("DirectionalDragArea: recognition properties are wrongly set. Gesture recognition"
395− " is impossible");
396− }
397− }
398−
399− if (allGood) {
400− Q_ASSERT(newTouchPoint);
401−
402− startPos = newTouchPoint->pos();
403− startScenePos = newTouchPoint->scenePos();
404− touchId = newTouchPoint->id();
405− dampedScenePos.reset(startScenePos);
406− setPublicPos(startPos);
407−
408− setPublicScenePos(startScenePos);
409− updateSceneDirectionVector();
410−
411− if (recognitionIsDisabled()) {
412− // Behave like a dumb TouchArea
413− ddaDebug("Gesture recognition is disabled. Requesting touch ownership immediately.");
414− TouchRegistry::instance()->requestTouchOwnership(touchId, q);
415− setStatus(Recognized);
416− event->accept();
417− } else {
418− // just monitor the touch points for now.
419− TouchRegistry::instance()->addCandidateOwnerForTouch(touchId, q);
420−
421− setStatus(Undecided);
422− // Let the item below have it. We will monitor it and grab it later if a gesture
423− // gets recognized.
424− event->ignore();
425− }
426− } else {
427− watchPressedTouchPoints(touchPoints);
428− event->ignore();
429− }
430−}
431−
432−void DirectionalDragAreaPrivate::touchEvent_undecided(QTouchEvent *event)
433−{
434− Q_ASSERT(fetchTargetTouchPoint(event) == nullptr);
435−
436− // We're not interested in new touch points. We already have our candidate (touchId).
437− // But we do want to know when those new touches end for keeping the composition time
438− // window up-to-date
439− event->ignore();
440− watchPressedTouchPoints(event->touchPoints());
441−
442− if (event->touchPointStates().testFlag(Qt::TouchPointPressed) && isWithinTouchCompositionWindow()) {
443− // multi-finger drags are not accepted
444− ddaDebug("Multi-finger drags are not accepted");
445−
446− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
447− // We still wanna know when it ends for keeping the composition time window up-to-date
448− TouchRegistry::instance()->addTouchWatcher(touchId, q);
449−
450− setStatus(WaitingForTouch);
451− }
452−}
453−
454−void DirectionalDragAreaPrivate::touchEvent_recognized(QTouchEvent *event)
455−{
456− const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
457−
458− if (!touchPoint) {
459− qCritical() << "DirectionalDragArea[status=Recognized]: touch " << touchId
460− << "missing from QTouchEvent without first reaching state Qt::TouchPointReleased. "
461− "Considering it as released.";
462− setStatus(WaitingForTouch);
463− } else {
464− setPublicPos(touchPoint->pos());
465− setPublicScenePos(touchPoint->scenePos());
466−
467− if (touchPoint->state() == Qt::TouchPointReleased) {
468− setStatus(WaitingForTouch);
469− }
470− }
471−}
472−
473−void DirectionalDragAreaPrivate::watchPressedTouchPoints(const QList<QTouchEvent::TouchPoint> &touchPoints)
474−{
475− for (int i = 0; i < touchPoints.count(); ++i) {
476− const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
477− if (touchPoint.state() == Qt::TouchPointPressed) {
478− TouchRegistry::instance()->addTouchWatcher(touchPoint.id(), q);
479− }
480− }
481−}
482−
483−bool DirectionalDragAreaPrivate::recognitionIsDisabled() const
484−{
485− return immediateRecognition || (distanceThreshold <= 0 && compositionTime <= 0);
486−}
487−
488−bool DirectionalDragAreaPrivate::sanityCheckRecognitionProperties()
489−{
490− return recognitionIsDisabled()
491− || (distanceThreshold < maxDistance && compositionTime < maxTime);
492−}
493−
494−const QTouchEvent::TouchPoint *DirectionalDragAreaPrivate::fetchTargetTouchPoint(QTouchEvent *event)
495−{
496− const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
497− const QTouchEvent::TouchPoint *touchPoint = 0;
498− for (int i = 0; i < touchPoints.size(); ++i) {
499− if (touchPoints.at(i).id() == touchId) {
500− touchPoint = &touchPoints.at(i);
501− break;
502− }
503− }
504− return touchPoint;
505−}
506−
507−bool DirectionalDragAreaPrivate::movingInRightDirection() const
508−{
509− if (direction == Direction::Horizontal || direction == Direction::Vertical) {
510− return true;
511− } else {
512− QPointF movementVector(dampedScenePos.x() - previousDampedScenePos.x(),
513− dampedScenePos.y() - previousDampedScenePos.y());
514−
515− qreal scalarProjection = projectOntoDirectionVector(movementVector);
516−
517− return scalarProjection >= 0.;
518− }
519−}
520−
521−bool DirectionalDragAreaPrivate::movedFarEnoughAlongGestureAxis() const
522−{
523− if (distanceThreshold <= 0.) {
524− // distance threshold check is disabled
525− return true;
526− } else {
527− QPointF totalMovement(dampedScenePos.x() - startScenePos.x(),
528− dampedScenePos.y() - startScenePos.y());
529−
530− qreal scalarProjection = projectOntoDirectionVector(totalMovement);
531−
532− ddaDebug(" movedFarEnoughAlongGestureAxis: scalarProjection=" << scalarProjection
533− << ", distanceThreshold=" << distanceThreshold);
534−
535− if (direction == Direction::Horizontal || direction == Direction::Vertical) {
536− return qAbs(scalarProjection) > distanceThreshold;
537− } else {
538− return scalarProjection > distanceThreshold;
539− }
540− }
541−}
542−
543−bool DirectionalDragAreaPrivate::isPastMaxDistance() const
544−{
545− QPointF totalMovement(dampedScenePos.x() - startScenePos.x(),
546− dampedScenePos.y() - startScenePos.y());
547−
548− qreal squaredDistance = totalMovement.x()*totalMovement.x() + totalMovement.y()*totalMovement.y();
549− return squaredDistance > maxDistance*maxDistance;
550−}
551−
552−void DirectionalDragAreaPrivate::giveUpIfDisabledOrInvisible()
553−{
554− if (!q->isEnabled() || !q->isVisible()) {
555− if (status == Undecided) {
556− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
557− // We still wanna know when it ends for keeping the composition time window up-to-date
558− TouchRegistry::instance()->addTouchWatcher(touchId, q);
559− }
560−
561− if (status != WaitingForTouch) {
562− ddaDebug("Resetting status because got disabled or made invisible");
563− setStatus(WaitingForTouch);
564− }
565− }
566−}
567−
568−void DirectionalDragAreaPrivate::rejectGesture()
569−{
570− if (status == Undecided) {
571− ddaDebug("Rejecting gesture because it's taking too long to drag beyond the threshold.");
572−
573− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
574− // We still wanna know when it ends for keeping the composition time window up-to-date
575− TouchRegistry::instance()->addTouchWatcher(touchId, q);
576−
577− setStatus(WaitingForTouch);
578− }
579−}
580−
581−void DirectionalDragAreaPrivate::setStatus(Status newStatus)
582−{
583− if (newStatus == status)
584− return;
585−
586− Status oldStatus = status;
587−
588− if (oldStatus == Undecided) {
589− recognitionTimer->stop();
590− }
591−
592− status = newStatus;
593− Q_EMIT statusChanged(status);
594−
595− ddaDebug(statusToString(oldStatus) << " -> " << statusToString(newStatus));
596−
597− switch (newStatus) {
598− case WaitingForTouch:
599− if (oldStatus == Recognized) {
600− Q_EMIT q->draggingChanged(false);
601− }
602− Q_EMIT q->pressedChanged(false);
603− break;
604− case Undecided:
605− recognitionTimer->start();
606− Q_EMIT q->pressedChanged(true);
607− break;
608− case Recognized:
609− Q_EMIT q->draggingChanged(true);
610− break;
611− default:
612− // no-op
613− break;
614− }
615−}
616−
617−void DirectionalDragAreaPrivate::setPublicPos(const QPointF point)
618−{
619− bool xChanged = publicPos.x() != point.x();
620− bool yChanged = publicPos.y() != point.y();
621−
622− // Public position should not get updated while the gesture is still being recognized
623− // (ie, Undecided status).
624− Q_ASSERT(status == WaitingForTouch || status == Recognized);
625−
626− if (status == Recognized && !recognitionIsDisabled()) {
627− // When the gesture finally gets recognized, the finger will likely be
628− // reasonably far from the edge. If we made the contentX immediately
629− // follow the finger position it would be visually unpleasant as it
630− // would appear right next to the user's finger out of nowhere (ie,
631− // it would jump). Instead, we make contentX go towards the user's
632− // finger in several steps. ie., in an animated way.
633− QPointF delta = point - publicPos;
634− // the trick is not to go all the way (1.0) as it would cause a sudden jump
635− publicPos.rx() += 0.4 * delta.x();
636− publicPos.ry() += 0.4 * delta.y();
637− } else {
638− // no smoothing when initializing or if gesture recognition was immediate as there will
639− // be no jump.
640− publicPos = point;
641− }
642−
643− if (xChanged) {
644− Q_EMIT q->touchXChanged(publicPos.x());
645− if (Direction::isHorizontal(direction))
646− Q_EMIT q->distanceChanged(q->distance());
647− }
648−
649− if (yChanged) {
650− Q_EMIT q->touchYChanged(publicPos.y());
651− if (Direction::isVertical(direction))
652− Q_EMIT q->distanceChanged(q->distance());
653− }
654−}
655−
656−void DirectionalDragAreaPrivate::setPublicScenePos(const QPointF point)
657−{
658− bool xChanged = publicScenePos.x() != point.x();
659− bool yChanged = publicScenePos.y() != point.y();
660−
661− if (!xChanged && !yChanged)
662− return;
663−
664− // Public position should not get updated while the gesture is still being recognized
665− // (ie, Undecided status).
666− Q_ASSERT(status == WaitingForTouch || status == Recognized);
667−
668− qreal oldSceneDistance = sceneDistance;
669−
670− if (status == Recognized && !recognitionIsDisabled()) {
671− // When the gesture finally gets recognized, the finger will likely be
672− // reasonably far from the edge. If we made the contentX immediately
673− // follow the finger position it would be visually unpleasant as it
674− // would appear right next to the user's finger out of nowhere (ie,
675− // it would jump). Instead, we make contentX go towards the user's
676− // finger in several steps. ie., in an animated way.
677− QPointF delta = point - publicScenePos;
678− // the trick is not to go all the way (1.0) as it would cause a sudden jump
679− publicScenePos.rx() += 0.4 * delta.x();
680− publicScenePos.ry() += 0.4 * delta.y();
681− } else {
682− // no smoothing when initializing or if gesture recognition was immediate as there will
683− // be no jump.
684− publicScenePos = point;
685− }
686−
687− updateSceneDistance();
688−
689− if (oldSceneDistance != sceneDistance) {
690− Q_EMIT q->sceneDistanceChanged(sceneDistance);
691− }
692−
693− if (xChanged) {
694− Q_EMIT q->touchSceneXChanged(publicScenePos.x());
695− }
696−
697− if (yChanged) {
698− Q_EMIT q->touchSceneYChanged(publicScenePos.y());
699− }
700−}
701−
702−bool DirectionalDragAreaPrivate::isWithinTouchCompositionWindow()
703−{
704− return
705− compositionTime > 0 &&
706− !activeTouches.isEmpty() &&
707− timeSource->msecsSinceReference() <=
708− activeTouches.mostRecentStartTime() + (qint64)compositionTime;
709−}
710−
711−void DirectionalDragArea::itemChange(ItemChange change, const ItemChangeData &value)
712−{
713− if (change == QQuickItem::ItemSceneChange) {
714− if (value.window != nullptr) {
715− value.window->installEventFilter(TouchRegistry::instance());
716−
717− // TODO: Handle window->screen() changes (ie window changing screens)
718− qreal pixelsPerMm = value.window->screen()->physicalDotsPerInch() / 25.4;
719− d->setPixelsPerMm(pixelsPerMm);
720− }
721− }
722−}
723−
724−void DirectionalDragAreaPrivate::setPixelsPerMm(qreal pixelsPerMm)
725−{
726− dampedScenePos.setMaxDelta(1. * pixelsPerMm);
727− setDistanceThreshold(4. * pixelsPerMm);
728− maxDistance = 10. * pixelsPerMm;
729−}
730−
731−//************************** ActiveTouchesInfo **************************
732−
733−ActiveTouchesInfo::ActiveTouchesInfo(const SharedTimeSource &timeSource)
734− : m_timeSource(timeSource)
735−{
736−}
737−
738−void ActiveTouchesInfo::update(QTouchEvent *event)
739−{
740− if (!(event->touchPointStates() & (Qt::TouchPointPressed | Qt::TouchPointReleased))) {
741− // nothing to update
742− #if ACTIVETOUCHESINFO_DEBUG
743− qDebug("[DDA::ActiveTouchesInfo] Nothing to Update");
744− #endif
745− return;
746− }
747−
748− const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
749− for (int i = 0; i < touchPoints.count(); ++i) {
750− const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
751− if (touchPoint.state() == Qt::TouchPointPressed) {
752− addTouchPoint(touchPoint.id());
753− } else if (touchPoint.state() == Qt::TouchPointReleased) {
754− removeTouchPoint(touchPoint.id());
755− }
756− }
757−}
758−
759−#if ACTIVETOUCHESINFO_DEBUG
760−QString ActiveTouchesInfo::toString()
761−{
762− QString string = "(";
763−
764− {
765− QTextStream stream(&string);
766− m_touchInfoPool.forEach([&](Pool<ActiveTouchInfo>::Iterator &touchInfo) {
767− stream << "(id=" << touchInfo->id << ",startTime=" << touchInfo->startTime << ")";
768− return true;
769− });
770− }
771−
772− string.append(")");
773−
774− return string;
775−}
776−#endif // ACTIVETOUCHESINFO_DEBUG
777−
778−void ActiveTouchesInfo::addTouchPoint(int touchId)
779−{
780− ActiveTouchInfo &activeTouchInfo = m_touchInfoPool.getEmptySlot();
781− activeTouchInfo.id = touchId;
782− activeTouchInfo.startTime = m_timeSource->msecsSinceReference();
783−
784− #if ACTIVETOUCHESINFO_DEBUG
785− qDebug() << "[DDA::ActiveTouchesInfo]" << qPrintable(toString());
786− #endif
787−}
788−
789−qint64 ActiveTouchesInfo::touchStartTime(int touchId)
790−{
791− qint64 result = -1;
792−
793− m_touchInfoPool.forEach([&](Pool<ActiveTouchInfo>::Iterator &touchInfo) {
794− if (touchId == touchInfo->id) {
795− result = touchInfo->startTime;
796− return false;
797− } else {
798− return true;
799− }
800− });
801−
802− Q_ASSERT(result != -1);
803− return result;
804−}
805−
806−void ActiveTouchesInfo::removeTouchPoint(int touchId)
807−{
808− m_touchInfoPool.forEach([&](Pool<ActiveTouchInfo>::Iterator &touchInfo) {
809− if (touchId == touchInfo->id) {
810− m_touchInfoPool.freeSlot(touchInfo);
811− return false;
812− } else {
813− return true;
814− }
815− });
816−
817− #if ACTIVETOUCHESINFO_DEBUG
818− qDebug() << "[DDA::ActiveTouchesInfo]" << qPrintable(toString());
819− #endif
820−}
821−
822−qint64 ActiveTouchesInfo::mostRecentStartTime()
823−{
824− Q_ASSERT(!m_touchInfoPool.isEmpty());
825−
826− qint64 highestStartTime = -1;
827−
828− m_touchInfoPool.forEach([&](Pool<ActiveTouchInfo>::Iterator &activeTouchInfo) {
829− if (activeTouchInfo->startTime > highestStartTime) {
830− highestStartTime = activeTouchInfo->startTime;
831− }
832− return true;
833− });
834−
835− return highestStartTime;
836−}
837−
838−void DirectionalDragAreaPrivate::updateSceneDirectionVector()
839−{
840− QPointF localOrigin(0., 0.);
841− QPointF localDirection;
842− switch (direction) {
843− case Direction::Upwards:
844− localDirection.rx() = 0.;
845− localDirection.ry() = -1.;
846− break;
847− case Direction::Downwards:
848− case Direction::Vertical:
849− localDirection.rx() = 0.;
850− localDirection.ry() = 1;
851− break;
852− case Direction::Leftwards:
853− localDirection.rx() = -1.;
854− localDirection.ry() = 0.;
855− break;
856− default: // Direction::Rightwards || Direction.Horizontal
857− localDirection.rx() = 1.;
858− localDirection.ry() = 0.;
859− break;
860− }
861− QPointF sceneOrigin = q->mapToScene(localOrigin);
862− QPointF sceneDirection = q->mapToScene(localDirection);
863− sceneDirectionVector = sceneDirection - sceneOrigin;
864−}
865−
866−qreal DirectionalDragAreaPrivate::projectOntoDirectionVector(const QPointF sceneVector) const
867−{
868− // same as dot product as sceneDirectionVector is a unit vector
869− return sceneVector.x() * sceneDirectionVector.x() +
870− sceneVector.y() * sceneDirectionVector.y();
871−}
872−
873−DirectionalDragAreaPrivate::DirectionalDragAreaPrivate(DirectionalDragArea *q)
874− : q(q)
875− , status(WaitingForTouch)
876− , sceneDistance(0)
877− , touchId(-1)
878− , direction(Direction::Rightwards)
879− , distanceThreshold(0)
880− , distanceThresholdSquared(0.)
881− , maxTime(400)
882− , compositionTime(60)
883− , immediateRecognition(false)
884− , recognitionTimer(nullptr)
885− , timeSource(new RealTimeSource)
886− , activeTouches(timeSource)
887−{
888−}
plugins/Ubuntu/Gestures/DirectionalDragArea.hdeleted−135
@@ -1,135 +0,0 @@
1−/*
2− * Copyright (C) 2013,2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef DIRECTIONAL_DRAG_AREA_H
18−#define DIRECTIONAL_DRAG_AREA_H
19−
20−#include <QtQuick/QQuickItem>
21−#include "UbuntuGesturesQmlGlobal.h"
22−#include "Damper.h"
23−#include "Direction.h"
24−
25−// lib UbuntuGestures
26−#include <Pool.h>
27−#include <Timer.h>
28−
29−class TouchOwnershipEvent;
30−class UnownedTouchEvent;
31−class DirectionalDragAreaPrivate;
32−
33−/*
34− An area that detects axis-aligned single-finger drag gestures
35−
36− If a drag deviates too much from the components' direction recognition will
37− fail. It will also fail if the drag or flick is too short. E.g. a noisy or
38− fidgety click
39−
40− See doc/DirectionalDragArea.svg
41− */
42−class UBUNTUGESTURESQML_EXPORT DirectionalDragArea : public QQuickItem {
43− Q_OBJECT
44−
45− // The direction in which the gesture should move in order to be recognized.
46− Q_PROPERTY(Direction::Type direction READ direction WRITE setDirection NOTIFY directionChanged)
47−
48− // The distance travelled by the finger along the axis specified by
49− // DirectionalDragArea's direction.
50− Q_PROPERTY(qreal distance READ distance NOTIFY distanceChanged)
51−
52− // The distance travelled by the finger along the axis specified by
53− // DirectionalDragArea's direction in scene coordinates
54− Q_PROPERTY(qreal sceneDistance READ sceneDistance NOTIFY sceneDistanceChanged)
55−
56− // Position of the touch point performing the drag relative to this item.
57− Q_PROPERTY(qreal touchX READ touchX NOTIFY touchXChanged)
58− Q_PROPERTY(qreal touchY READ touchY NOTIFY touchYChanged)
59−
60− // Position of the touch point performing the drag, in scene's coordinate system
61− Q_PROPERTY(qreal touchSceneX READ touchSceneX NOTIFY touchSceneXChanged)
62− Q_PROPERTY(qreal touchSceneY READ touchSceneY NOTIFY touchSceneYChanged)
63−
64− // Whether a drag gesture is taking place
65− Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
66−
67− // Whether the drag area is pressed.
68− Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
69−
70− // Whether a gesture should be Recognized as soon a touch lands on the area.
71− // With this property enabled it will work pretty much like a MultiPointTouchArea,
72− // just with a different API.
73− //
74− // It's false by default. In most cases you will not want that enabled.
75− Q_PROPERTY(bool immediateRecognition
76− READ immediateRecognition
77− WRITE setImmediateRecognition
78− NOTIFY immediateRecognitionChanged)
79−
80− Q_ENUMS(Direction)
81−public:
82− DirectionalDragArea(QQuickItem *parent = 0);
83−
84− Direction::Type direction() const;
85− void setDirection(Direction::Type);
86−
87− qreal distance() const;
88− qreal sceneDistance() const;
89−
90− qreal touchX() const;
91− qreal touchY() const;
92−
93− qreal touchSceneX() const;
94− qreal touchSceneY() const;
95−
96− bool dragging() const;
97−
98− bool pressed() const;
99−
100− bool immediateRecognition() const;
101− void setImmediateRecognition(bool enabled);
102−
103− bool event(QEvent *e) override;
104−
105− /*
106− In qmltests, sequences of touch events are sent all at once, unlike in "real life".
107− Also qmltests might run really slowly, e.g. when run from inside virtual machines.
108− Thus to remove a variable that qmltests cannot really control, namely time, this
109− function removes all constraints that are sensible to elapsed time.
110−
111− This effectively makes the DirectionalDragArea easier to fool.
112− */
113− Q_INVOKABLE void removeTimeConstraints();
114−
115−Q_SIGNALS:
116− void directionChanged(Direction::Type direction);
117− void draggingChanged(bool value);
118− void pressedChanged(bool value);
119− void distanceChanged(qreal value);
120− void sceneDistanceChanged(qreal value);
121− void touchXChanged(qreal value);
122− void touchYChanged(qreal value);
123− void touchSceneXChanged(qreal value);
124− void touchSceneYChanged(qreal value);
125− void immediateRecognitionChanged(bool value);
126−
127−protected:
128− void touchEvent(QTouchEvent *event) override;
129− void itemChange(ItemChange change, const ItemChangeData &value) override;
130−
131−public: // so tests can access it
132− DirectionalDragAreaPrivate *d;
133−};
134−
135−#endif // DIRECTIONAL_DRAG_AREA_H
plugins/Ubuntu/Gestures/DirectionalDragArea_p.hdeleted−167
@@ -1,167 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef DIRECTIONAL_DRAG_AREA_PRIV_H
18−#define DIRECTIONAL_DRAG_AREA_PRIV_H
19−
20−// Information about an active touch point
21−struct UBUNTUGESTURESQML_EXPORT ActiveTouchInfo {
22− ActiveTouchInfo() : id(-1), startTime(-1) {}
23− bool isValid() const { return id != -1; }
24− void reset() { id = -1; }
25− int id;
26− qint64 startTime;
27−};
28−class UBUNTUGESTURESQML_EXPORT ActiveTouchesInfo {
29−public:
30− ActiveTouchesInfo(const UbuntuGestures::SharedTimeSource &timeSource);
31− void update(QTouchEvent *event);
32− qint64 touchStartTime(int id);
33− bool isEmpty() const { return m_touchInfoPool.isEmpty(); }
34− qint64 mostRecentStartTime();
35− UbuntuGestures::SharedTimeSource m_timeSource;
36−private:
37− void addTouchPoint(int touchId);
38− void removeTouchPoint(int touchId);
39− #if ACTIVETOUCHESINFO_DEBUG
40− QString toString();
41− #endif
42−
43− Pool<ActiveTouchInfo> m_touchInfoPool;
44−};
45−
46−class UBUNTUGESTURESQML_EXPORT DirectionalDragAreaPrivate : public QObject {
47− Q_OBJECT
48−
49− Q_ENUMS(Status)
50−public:
51− DirectionalDragAreaPrivate(DirectionalDragArea *q);
52−
53−public Q_SLOTS:
54− void giveUpIfDisabledOrInvisible();
55− void rejectGesture();
56−
57−public:
58− // Describes the state of the directional drag gesture.
59− enum Status {
60− // Waiting for a new touch point to land on this area. No gesture is being processed
61− // or tracked.
62− WaitingForTouch,
63−
64− // A touch point has landed on this area but it's not know yet whether it is
65− // performing a drag in the correct direction.
66− // If it's decided that the touch point is not performing a directional drag gesture,
67− // it will be rejected/ignored and status will return to WaitingForTouch.
68− Undecided, //Recognizing,
69−
70− // There's a touch point in this area and it performed a drag in the correct
71− // direction.
72− //
73− // Once recognized, the gesture state will move back to WaitingForTouch only once
74− // that touch point ends. The gesture will remain in the Recognized state even if
75− // the touch point starts moving in other directions or halts.
76− Recognized,
77− };
78−
79− void touchEvent_absent(QTouchEvent *event);
80− void touchEvent_undecided(QTouchEvent *event);
81− void touchEvent_recognized(QTouchEvent *event);
82− bool movingInRightDirection() const;
83− bool movedFarEnoughAlongGestureAxis() const;
84− bool isPastMaxDistance() const;
85− const QTouchEvent::TouchPoint *fetchTargetTouchPoint(QTouchEvent *event);
86− void setStatus(Status newStatus);
87− void setPublicPos(const QPointF point);
88− void setPublicScenePos(const QPointF point);
89− bool isWithinTouchCompositionWindow();
90− void updateSceneDirectionVector();
91− // returns the scalar projection between the given vector (in scene coordinates)
92− // and m_sceneDirectionVector
93− qreal projectOntoDirectionVector(const QPointF sceneVector) const;
94− void touchOwnershipEvent(TouchOwnershipEvent *event);
95− void unownedTouchEvent(UnownedTouchEvent *event);
96− void unownedTouchEvent_undecided(UnownedTouchEvent *unownedTouchEvent);
97− void watchPressedTouchPoints(const QList<QTouchEvent::TouchPoint> &touchPoints);
98− bool recognitionIsDisabled() const;
99− bool sanityCheckRecognitionProperties();
100− void updateSceneDistance();
101− void setMaxTime(int value);
102− void setDistanceThreshold(qreal value);
103− void setPixelsPerMm(qreal pixelsPerMm);
104− QString objectName() const { return q->objectName(); }
105−
106− // Replaces the existing Timer with the given one.
107− //
108− // Useful for providing a fake timer when testing.
109− void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
110−
111− // Useful for testing, where a fake time source can be supplied
112− void setTimeSource(const UbuntuGestures::SharedTimeSource &timeSource);
113−
114− DirectionalDragArea *q;
115−
116− // The current status of the directional drag gesture area.
117− Status status;
118−
119− QPointF startPos;
120− QPointF startScenePos;
121− qreal sceneDistance;
122− int touchId;
123−
124− // The touch position exposed in the public API.
125− // It only starts to move once the gesture gets recognized.
126− QPointF publicPos;
127− QPointF publicScenePos;
128−
129− // A movement damper is used in some of the gesture recognition calculations
130− // to get rid of noise or small oscillations in the touch position.
131− DampedPointF dampedScenePos;
132− QPointF previousDampedScenePos;
133−
134− // Unit vector in scene coordinates describing the direction of the gesture recognition
135− QPointF sceneDirectionVector;
136−
137− Direction::Type direction;
138−
139− // How far a touch point has to move from its initial position along the gesture axis in order
140− // for it to be recognized as a directional drag.
141− qreal distanceThreshold;
142− qreal distanceThresholdSquared; // it's pow(distanceThreshold, 2)
143−
144− // Maximum time (in milliseconds) the gesture can take to go beyond the distance threshold
145− int maxTime;
146−
147− // Maximum distance the gesture can go without crossing the axis-aligned distance threshold
148− qreal maxDistance;
149−
150− // Maximum time (in milliseconds) after the start of a given touch point where
151− // subsequent touch starts are grouped with the first one into an N-touches gesture
152− // (e.g. a two-fingers tap or drag).
153− int compositionTime;
154−
155− bool immediateRecognition;
156−
157− UbuntuGestures::AbstractTimer *recognitionTimer;
158−
159− UbuntuGestures::SharedTimeSource timeSource;
160−
161− ActiveTouchesInfo activeTouches;
162−
163−Q_SIGNALS:
164− void statusChanged(Status value);
165−};
166−
167−#endif // DIRECTIONAL_DRAG_AREA_PRIV_H
plugins/Ubuntu/Gestures/FloatingFlickable.cppdeleted−150
@@ -1,150 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "FloatingFlickable.h"
18−
19−#include <private/qquickflickable_p.h>
20−#include "DirectionalDragArea.h"
21−
22−#include <QDebug>
23−
24−FloatingFlickable::FloatingFlickable(QQuickItem *parent)
25− : QQuickItem(parent)
26− , m_mousePressed(false)
27−{
28− m_dragArea = new DirectionalDragArea(this);
29− m_dragArea->setWidth(width());
30− m_dragArea->setHeight(height());
31− m_dragArea->setDirection(Direction::Horizontal);
32− connect(m_dragArea, &DirectionalDragArea::touchXChanged,
33− this, &FloatingFlickable::onDragAreaTouchPosChanged);
34− connect(m_dragArea, &DirectionalDragArea::touchYChanged,
35− this, &FloatingFlickable::onDragAreaTouchPosChanged);
36− connect(m_dragArea, &DirectionalDragArea::draggingChanged,
37− this, &FloatingFlickable::onDragAreaDraggingChanged);
38− connect(m_dragArea, &DirectionalDragArea::directionChanged, this, &FloatingFlickable::directionChanged);
39−
40− m_flickable = new QQuickFlickable(this);
41− m_flickable->setEnabled(false);
42− m_flickable->setWidth(width());
43− m_flickable->setHeight(height());
44− connect(m_flickable, &QQuickFlickable::contentWidthChanged, this, &FloatingFlickable::contentWidthChanged);
45− connect(m_flickable, &QQuickFlickable::contentHeightChanged, this, &FloatingFlickable::contentHeightChanged);
46− connect(m_flickable, &QQuickFlickable::contentXChanged, this, &FloatingFlickable::contentXChanged);
47− connect(m_flickable, &QQuickFlickable::contentYChanged, this, &FloatingFlickable::contentYChanged);
48−
49− connect(this, &QQuickItem::widthChanged, this, &FloatingFlickable::updateChildrenWidth);
50− connect(this, &QQuickItem::heightChanged, this, &FloatingFlickable::updateChildrenHeight);
51−}
52−
53−qreal FloatingFlickable::contentWidth() const
54−{
55− return m_flickable->contentWidth();
56−}
57−
58−void FloatingFlickable::setContentWidth(qreal contentWidth)
59−{
60− m_flickable->setContentWidth(contentWidth);
61−}
62−
63−qreal FloatingFlickable::contentHeight() const
64−{
65− return m_flickable->contentHeight();
66−}
67−
68−void FloatingFlickable::setContentHeight(qreal contentHeight)
69−{
70− m_flickable->setContentHeight(contentHeight);
71−}
72−
73−qreal FloatingFlickable::contentX() const
74−{
75− return m_flickable->contentX();
76−}
77−
78−void FloatingFlickable::setContentX(qreal contentX)
79−{
80− m_flickable->setContentX(contentX);
81−}
82−
83−qreal FloatingFlickable::contentY() const
84−{
85− return m_flickable->contentY();
86−}
87−
88−void FloatingFlickable::setContentY(qreal contentY)
89−{
90− m_flickable->setContentY(contentY);
91−}
92−
93−Direction::Type FloatingFlickable::direction() const
94−{
95− return m_dragArea->direction();
96−}
97−
98−void FloatingFlickable::setDirection(Direction::Type direction)
99−{
100− m_dragArea->setDirection(direction);
101− if (Direction::isHorizontal(direction)) {
102− m_flickable->setFlickableDirection(QQuickFlickable::HorizontalFlick);
103− } else {
104− m_flickable->setFlickableDirection(QQuickFlickable::VerticalFlick);
105− }
106−}
107−
108−void FloatingFlickable::updateChildrenWidth()
109−{
110− m_dragArea->setWidth(width());
111− m_flickable->setWidth(width());
112−}
113−
114−void FloatingFlickable::updateChildrenHeight()
115−{
116− m_dragArea->setHeight(height());
117− m_flickable->setHeight(height());
118−}
119−
120−void FloatingFlickable::onDragAreaTouchPosChanged(qreal)
121−{
122− if (m_mousePressed) {
123− QMouseEvent mouseEvent(QEvent::MouseMove,
124− QPointF(m_dragArea->touchX(),m_dragArea->touchY()),
125− Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
126−
127− QCoreApplication::sendEvent(m_flickable, &mouseEvent);
128−
129− }
130−}
131−
132−void FloatingFlickable::onDragAreaDraggingChanged(bool dragging)
133−{
134− if (dragging && !m_mousePressed) {
135− QMouseEvent mouseEvent(QEvent::MouseButtonPress,
136− QPointF(m_dragArea->touchX(),m_dragArea->touchY()),
137− Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
138−
139− QCoreApplication::sendEvent(m_flickable, &mouseEvent);
140− m_mousePressed = true;
141−
142− } else if (!dragging && m_mousePressed) {
143− QMouseEvent mouseEvent(QEvent::MouseButtonRelease,
144− QPointF(m_dragArea->touchX(),m_dragArea->touchY()),
145− Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
146−
147− QCoreApplication::sendEvent(m_flickable, &mouseEvent);
148− m_mousePressed = false;
149− }
150−}
plugins/Ubuntu/Gestures/FloatingFlickable.hdeleted−86
@@ -1,86 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef FLOATING_FLICKABLE_H
18−#define FLOATING_FLICKABLE_H
19−
20−#include <QQuickItem>
21−#include "UbuntuGesturesQmlGlobal.h"
22−#include "Direction.h"
23−
24−class DirectionalDragArea;
25−class QQuickFlickable;
26−
27−/*
28− A Flickable that can be put in front of the item to be flicked and
29− still have the item-to-be-flicked receive input events that are not flicks.
30−
31− Ie, it's a Flickable that, input-wise, is transparent to non-flick gestures.
32−
33− With a regular Flickable you would have to make the item-to-be-flicked a child
34− of Flicakble to achieve the same result. FloatingFlickable has no such requirement
35− or limitation.
36− */
37−class UBUNTUGESTURESQML_EXPORT FloatingFlickable : public QQuickItem {
38− Q_OBJECT
39−
40− Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged)
41− Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged)
42− Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged)
43− Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged)
44−
45− Q_PROPERTY(Direction::Type direction READ direction WRITE setDirection NOTIFY directionChanged)
46−
47−Q_SIGNALS:
48− void contentWidthChanged();
49− void contentHeightChanged();
50− void contentXChanged();
51− void contentYChanged();
52− void directionChanged();
53−
54−public:
55− FloatingFlickable(QQuickItem *parent = nullptr);
56−
57− qreal contentWidth() const;
58− void setContentWidth(qreal contentWidth);
59−
60− qreal contentHeight() const;
61− void setContentHeight(qreal contentHeight);
62−
63− qreal contentX() const;
64− void setContentX(qreal contentX);
65−
66− qreal contentY() const;
67− void setContentY(qreal contentY);
68−
69− Direction::Type direction() const;
70− void setDirection(Direction::Type);
71−
72−private Q_SLOTS:
73− void updateChildrenWidth();
74− void updateChildrenHeight();
75− void onDragAreaTouchPosChanged(qreal);
76− void onDragAreaDraggingChanged(bool value);
77−
78−private:
79− DirectionalDragArea *m_dragArea;
80− QQuickFlickable *m_flickable;
81− bool m_mousePressed;
82−
83− friend class tst_FloatingFlickable;
84−};
85−
86−#endif // FLOATING_FLICKABLE_H
plugins/Ubuntu/Gestures/Gestures.qmltypesdeleted−168
@@ -1,168 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable Ubuntu.Gestures 0.1 plugins'
8−
9−Module {
10− Component {
11− name: "AxisVelocityCalculator"
12− prototype: "QObject"
13− exports: ["Ubuntu.Gestures/AxisVelocityCalculator 0.1"]
14− exportMetaObjectRevisions: [0]
15− Property { name: "trackedPosition"; type: "double" }
16− Signal {
17− name: "trackedPositionChanged"
18− Parameter { name: "value"; type: "double" }
19− }
20− Method { name: "calculate"; type: "double" }
21− Method { name: "reset" }
22− }
23− Component {
24− name: "Direction"
25− prototype: "QObject"
26− exports: ["Ubuntu.Gestures/Direction 0.1"]
27− isCreatable: false
28− isSingleton: true
29− exportMetaObjectRevisions: [0]
30− Enum {
31− name: "Type"
32− values: {
33− "Rightwards": 0,
34− "Leftwards": 1,
35− "Downwards": 2,
36− "Upwards": 3,
37− "Horizontal": 4
38− }
39− }
40− Method {
41− name: "isHorizontal"
42− type: "bool"
43− Parameter { name: "type"; type: "Direction::Type" }
44− }
45− Method {
46− name: "isVertical"
47− type: "bool"
48− Parameter { name: "type"; type: "Direction::Type" }
49− }
50− Method {
51− name: "isPositive"
52− type: "bool"
53− Parameter { name: "type"; type: "Direction::Type" }
54− }
55− }
56− Component {
57− name: "DirectionalDragArea"
58− defaultProperty: "data"
59− prototype: "QQuickItem"
60− exports: ["Ubuntu.Gestures/DirectionalDragArea 0.1"]
61− exportMetaObjectRevisions: [0]
62− Enum {
63− name: "Status"
64− values: {
65− "WaitingForTouch": 0,
66− "Undecided": 1,
67− "Recognized": 2
68− }
69− }
70− Property { name: "direction"; type: "Direction::Type" }
71− Property { name: "distance"; type: "double"; isReadonly: true }
72− Property { name: "sceneDistance"; type: "double"; isReadonly: true }
73− Property { name: "touchX"; type: "double"; isReadonly: true }
74− Property { name: "touchY"; type: "double"; isReadonly: true }
75− Property { name: "touchSceneX"; type: "double"; isReadonly: true }
76− Property { name: "touchSceneY"; type: "double"; isReadonly: true }
77− Property { name: "status"; type: "Status"; isReadonly: true }
78− Property { name: "dragging"; type: "bool"; isReadonly: true }
79− Property { name: "maxDeviation"; type: "double" }
80− Property { name: "wideningAngle"; type: "double" }
81− Property { name: "distanceThreshold"; type: "double" }
82− Property { name: "minSpeed"; type: "double" }
83− Property { name: "maxSilenceTime"; type: "int" }
84− Property { name: "compositionTime"; type: "int" }
85− Signal {
86− name: "directionChanged"
87− Parameter { name: "direction"; type: "Direction::Type" }
88− }
89− Signal {
90− name: "statusChanged"
91− Parameter { name: "value"; type: "Status" }
92− }
93− Signal {
94− name: "draggingChanged"
95− Parameter { name: "value"; type: "bool" }
96− }
97− Signal {
98− name: "distanceChanged"
99− Parameter { name: "value"; type: "double" }
100− }
101− Signal {
102− name: "sceneDistanceChanged"
103− Parameter { name: "value"; type: "double" }
104− }
105− Signal {
106− name: "maxDeviationChanged"
107− Parameter { name: "value"; type: "double" }
108− }
109− Signal {
110− name: "wideningAngleChanged"
111− Parameter { name: "value"; type: "double" }
112− }
113− Signal {
114− name: "distanceThresholdChanged"
115− Parameter { name: "value"; type: "double" }
116− }
117− Signal {
118− name: "minSpeedChanged"
119− Parameter { name: "value"; type: "double" }
120− }
121− Signal {
122− name: "maxSilenceTimeChanged"
123− Parameter { name: "value"; type: "int" }
124− }
125− Signal {
126− name: "compositionTimeChanged"
127− Parameter { name: "value"; type: "int" }
128− }
129− Signal {
130− name: "touchXChanged"
131− Parameter { name: "value"; type: "double" }
132− }
133− Signal {
134− name: "touchYChanged"
135− Parameter { name: "value"; type: "double" }
136− }
137− Signal {
138− name: "touchSceneXChanged"
139− Parameter { name: "value"; type: "double" }
140− }
141− Signal {
142− name: "touchSceneYChanged"
143− Parameter { name: "value"; type: "double" }
144− }
145− Signal { name: "tapped" }
146− }
147− Component {
148− name: "PressedOutsideNotifier"
149− defaultProperty: "data"
150− prototype: "QQuickItem"
151− exports: ["Ubuntu.Gestures/PressedOutsideNotifier 0.1"]
152− exportMetaObjectRevisions: [0]
153− Signal { name: "pressedOutside" }
154− }
155− Component {
156− name: "TouchGate"
157− defaultProperty: "data"
158− prototype: "QQuickItem"
159− exports: ["Ubuntu.Gestures/TouchGate 0.1"]
160− exportMetaObjectRevisions: [0]
161− Property { name: "targetItem"; type: "QQuickItem"; isPointer: true }
162− Signal {
163− name: "targetItemChanged"
164− Parameter { name: "item"; type: "QQuickItem"; isPointer: true }
165− }
166− Signal { name: "pressed" }
167− }
168−}
plugins/Ubuntu/Gestures/MouseEventGenerator.cppnew file+64
@@ -0,0 +1,64 @@
1+/*
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "MouseEventGenerator.h"
18+
19+#include <QCoreApplication>
20+#include <QMouseEvent>
21+#include <QQuickItem>
22+
23+MouseEventGenerator::MouseEventGenerator(QObject *parent)
24+ : QObject(parent)
25+{
26+}
27+
28+void MouseEventGenerator::move(const QPointF position)
29+{
30+ if (!m_mousePressed || !m_targetItem) {
31+ return;
32+ }
33+
34+ QMouseEvent mouseEvent(QEvent::MouseMove,
35+ QPointF(position.x(), position.y()), Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
36+
37+ QCoreApplication::sendEvent(m_targetItem, &mouseEvent);
38+}
39+
40+void MouseEventGenerator::press(const QPointF position)
41+{
42+ if (m_mousePressed || !m_targetItem) {
43+ return;
44+ }
45+
46+ QMouseEvent mouseEvent(QEvent::MouseButtonPress,
47+ QPointF(position.x(), position.y()), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
48+
49+ QCoreApplication::sendEvent(m_targetItem, &mouseEvent);
50+ m_mousePressed = true;
51+}
52+
53+void MouseEventGenerator::release(const QPointF position)
54+{
55+ if (!m_mousePressed || !m_targetItem) {
56+ return;
57+ }
58+
59+ QMouseEvent mouseEvent(QEvent::MouseButtonRelease,
60+ QPointF(position.x(), position.y()), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
61+
62+ QCoreApplication::sendEvent(m_targetItem, &mouseEvent);
63+ m_mousePressed = false;
64+}
plugins/Ubuntu/Gestures/MouseEventGenerator.hnew file+48
@@ -0,0 +1,48 @@
1+/*
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef MOUSEEVENTGENERATOR_H
18+#define MOUSEEVENTGENERATOR_H
19+
20+#include <QObject>
21+#include <QPointF>
22+
23+#include "UbuntuGesturesQmlGlobal.h"
24+
25+class QQuickItem;
26+
27+class UBUNTUGESTURESQML_EXPORT MouseEventGenerator : public QObject {
28+ Q_OBJECT
29+ Q_PROPERTY(QQuickItem* targetItem MEMBER m_targetItem NOTIFY targetItemChanged)
30+
31+public:
32+ MouseEventGenerator(QObject *parent = nullptr);
33+
34+ Q_INVOKABLE void move(const QPointF position);
35+ Q_INVOKABLE void press(const QPointF position);
36+ Q_INVOKABLE void release(const QPointF position);
37+
38+Q_SIGNALS:
39+ void targetItemChanged(QQuickItem *);
40+
41+private:
42+ bool m_mousePressed {false};
43+ QQuickItem *m_targetItem {nullptr};
44+
45+ friend class tst_FloatingFlickable;
46+};
47+
48+#endif // MOUSEEVENTGENERATOR_H
plugins/Ubuntu/Gestures/PressedOutsideNotifier.h+1−1
@@ -23,7 +23,7 @@
2323#include <QPointer>
2424#include <QTimer>
2525
26−#include "UbuntuGesturesGlobal.h"
26+#include <ubuntugesturesglobal.h>
2727
2828/*
2929 Notifies when a point, mouse or touch, is pressed outside its area.
plugins/Ubuntu/Gestures/TouchDispatcher.cpp+1−5
@@ -19,11 +19,7 @@
1919#include <QGuiApplication>
2020#include <QScopedPointer>
2121#include <QStyleHints>
22−
23−#pragma GCC diagnostic push
24−#pragma GCC diagnostic ignored "-pedantic"
2522#include <private/qquickitem_p.h>
26−#pragma GCC diagnostic pop
2723
2824#define TOUCHDISPATCHER_DEBUG 0
2925
@@ -225,7 +221,7 @@ void TouchDispatcher::dispatchAsMouse(
225221 QEvent::Type eventType;
226222 if (touchMouse->state() == Qt::TouchPointPressed) {
227223 eventType = QEvent::MouseButtonPress;
228− } if (touchMouse->state() == Qt::TouchPointReleased) {
224+ } else if (touchMouse->state() == Qt::TouchPointReleased) {
229225 eventType = QEvent::MouseButtonRelease;
230226 m_touchMouseId = -1;
231227 } else {
plugins/Ubuntu/Gestures/TouchGate.cpp+10−5
@@ -20,16 +20,18 @@
2020#include <QDebug>
2121#include <QQuickWindow>
2222
23−#include <TouchOwnershipEvent.h>
24−#include <TouchRegistry.h>
23+#include <UbuntuGestures/private/touchownershipevent_p.h>
24+#include <UbuntuGestures/private/touchregistry_p.h>
2525
2626#if TOUCHGATE_DEBUG
2727#define ugDebug(params) qDebug().nospace() << "[TouchGate(" << (void*)this << ")] " << params
28−#include <DebugHelpers.h>
28+#include <UbuntuGestures/private/debughelpers_p.h>
2929#else // TOUCHGATE_DEBUG
3030#define ugDebug(params) ((void)0)
3131#endif // TOUCHGATE_DEBUG
3232
33+UG_USE_NAMESPACE
34+
3335TouchGate::TouchGate(QQuickItem *parent)
3436 : QQuickItem(parent)
3537{
@@ -40,7 +42,7 @@ TouchGate::TouchGate(QQuickItem *parent)
4042bool TouchGate::event(QEvent *e)
4143{
4244 if (e->type() == TouchOwnershipEvent::touchOwnershipEventType()) {
43− touchOwnershipEvent(static_cast<TouchOwnershipEvent *>(e));
45+ touchOwnershipEvent(static_cast<TouchOwnershipEvent*>(e));
4446 return true;
4547 } else {
4648 return QQuickItem::event(e);
@@ -59,7 +61,10 @@ void TouchGate::touchEvent(QTouchEvent *event)
5961 const QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
6062
6163 if (touchPoint.state() == Qt::TouchPointPressed) {
62− Q_ASSERT(!m_touchInfoMap.contains(touchPoint.id()));
64+// FIXME: This assert triggers frequently in make trySomething. We have verified
65+// that it's a bug in the mouse to touch conversion of the test environment
66+// and not in the actual product. Still, it probably should be cleaned up eventually.
67+// Q_ASSERT(!m_touchInfoMap.contains(touchPoint.id()));
6368 m_touchInfoMap[touchPoint.id()].ownership = OwnershipRequested;
6469 m_touchInfoMap[touchPoint.id()].ended = false;
6570 TouchRegistry::instance()->requestTouchOwnership(touchPoint.id(), this);
plugins/Ubuntu/Gestures/TouchGate.h+3−2
@@ -19,6 +19,7 @@
1919
2020#include "UbuntuGesturesQmlGlobal.h"
2121#include "TouchDispatcher.h"
22+#include <UbuntuGestures/ubuntugesturesglobal.h>
2223
2324#include <QQuickItem>
2425#include <QList>
@@ -26,7 +27,7 @@
2627
2728#define TOUCHGATE_DEBUG 0
2829
29−class TouchOwnershipEvent;
30+UG_FORWARD_DECLARE_CLASS(TouchOwnershipEvent)
3031
3132/*
3233 Blocks the passage of events until ownership over the related touch points is granted.
@@ -82,7 +83,7 @@ private:
8283 ulong timestamp;
8384 };
8485
85− void touchOwnershipEvent(TouchOwnershipEvent *event);
86+ void touchOwnershipEvent(UG_PREPEND_NAMESPACE(TouchOwnershipEvent) *event);
8687 bool isTouchPointOwned(int touchId) const;
8788 void storeTouchEvent(QTouchDevice *device,
8889 Qt::KeyboardModifiers modifiers,
plugins/Ubuntu/Gestures/TouchGestureArea.cppnew file+879
@@ -0,0 +1,879 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "TouchGestureArea.h"
18+
19+#include <UbuntuGestures/private/touchownershipevent_p.h>
20+#include <UbuntuGestures/private/touchregistry_p.h>
21+#include <UbuntuGestures/private/unownedtouchevent_p.h>
22+// #include "TouchRegistry.h"
23+// #include "UnownedTouchEvent.h"
24+
25+#include <QGuiApplication>
26+#include <QStyleHints>
27+#include <private/qquickwindow_p.h>
28+
29+UG_USE_NAMESPACE
30+
31+#define TOUCHGESTUREAREA_DEBUG 0
32+
33+// TODO - understand more about why we lose touch event releases.
34+// Workaround for now is to monitor all the touch points from first touch till
35+// all have been released; no matter if we've rejected the gesture.
36+
37+namespace {
38+
39+struct InternalStatus {
40+ enum Status {
41+ WaitingForTouch,
42+ WaitingForMoreTouches,
43+ WaitingForOwnership, //Recognizing,
44+ Recognized,
45+ WaitingForRejection,
46+ Rejected
47+ };
48+};
49+
50+TouchGestureArea::Status internalStatusToGestureStatus(int internalStatus) {
51+ switch (internalStatus) {
52+ case InternalStatus::WaitingForTouch: return TouchGestureArea::WaitingForTouch;
53+ case InternalStatus::WaitingForMoreTouches: return TouchGestureArea::Undecided;
54+ case InternalStatus::WaitingForOwnership: return TouchGestureArea::Undecided;
55+ case InternalStatus::Recognized: return TouchGestureArea::Recognized;
56+ case InternalStatus::WaitingForRejection: return TouchGestureArea::Recognized;
57+ case InternalStatus::Rejected: return TouchGestureArea::Rejected;
58+ }
59+ return TouchGestureArea::WaitingForTouch;
60+}
61+
62+}
63+
64+#if TOUCHGESTUREAREA_DEBUG
65+#define tgaDebug(params) qDebug().nospace() << "[TGA(" << qPrintable(objectName()) << ")] " << params
66+#include "DebugHelpers.h"
67+
68+namespace {
69+
70+const char *statusToString(int status)
71+{
72+ if (status == InternalStatus::WaitingForTouch) {
73+ return "WaitingForTouch";
74+ } else if (status == InternalStatus::WaitingForMoreTouches) {
75+ return "WaitingForMoreTouches";
76+ } else if (status == InternalStatus::WaitingForOwnership) {
77+ return "WaitingForOwnership";
78+ } else if (status == InternalStatus::Rejected) {
79+ return "Rejected";
80+ } else if (status == InternalStatus::WaitingForRejection) {
81+ return "WaitingForRejection";
82+ } else {
83+ return "Recognized";
84+ }
85+ return "Unknown";
86+}
87+
88+QString touchState(Qt::TouchPointState state) {
89+ switch (state) {
90+ case Qt::TouchPointPressed: return "pressed";
91+ case Qt::TouchPointMoved: return "moved";
92+ case Qt::TouchPointStationary: return "stationary";
93+ case Qt::TouchPointReleased: return "released";
94+ break;
95+ }
96+ return "unknown";
97+}
98+
99+QString touchesString(const QList<QObject*> touches) {
100+ QString str;
101+ Q_FOREACH(QObject* object, touches) {
102+ GestureTouchPoint* touchPoint = qobject_cast<GestureTouchPoint*>(object);
103+ if (touchPoint) {
104+ str += QStringLiteral("[%1 @ (%2, %3)], ").arg(touchPoint->id())
105+ .arg(touchPoint->x())
106+ .arg(touchPoint->y());
107+ }
108+ }
109+ return str;
110+}
111+
112+QString touchEventString(QTouchEvent* event) {
113+ if (!event) return QString();
114+ QString str;
115+ Q_FOREACH(const auto& touchPoint, event->touchPoints()) {
116+ str += QStringLiteral("[%1:%2 @ (%3, %4)], ").arg(touchPoint.id())
117+ .arg(touchState(touchPoint.state()))
118+ .arg(touchPoint.pos().x())
119+ .arg(touchPoint.pos().y());
120+ }
121+ return str;
122+}
123+
124+
125+} // namespace {
126+#else // TOUCHGESTUREAREA_DEBUG
127+#define tgaDebug(params) ((void)0)
128+#endif // TOUCHGESTUREAREA_DEBUG
129+
130+TouchGestureArea::TouchGestureArea(QQuickItem* parent)
131+ : QQuickItem(parent)
132+ , m_status(WaitingForTouch)
133+ , m_recognitionTimer(nullptr)
134+ , m_dragging(false)
135+ , m_minimumTouchPoints(1)
136+ , m_maximumTouchPoints(INT_MAX)
137+ , m_recognitionPeriod(50)
138+ , m_releaseRejectPeriod(100)
139+{
140+ setRecognitionTimer(new Timer(this));
141+ m_recognitionTimer->setInterval(m_recognitionPeriod);
142+ m_recognitionTimer->setSingleShot(true);
143+}
144+
145+TouchGestureArea::~TouchGestureArea()
146+{
147+ clearTouchLists();
148+ qDeleteAll(m_liveTouchPoints);
149+ m_liveTouchPoints.clear();
150+ qDeleteAll(m_cachedTouchPoints);
151+ m_cachedTouchPoints.clear();
152+}
153+
154+bool TouchGestureArea::event(QEvent *event)
155+{
156+ // Process unowned touch events (handles update/release for incomplete gestures)
157+ if (event->type() == TouchOwnershipEvent::touchOwnershipEventType()) {
158+ touchOwnershipEvent(static_cast<TouchOwnershipEvent*>(event));
159+ return true;
160+ } else if (event->type() == UnownedTouchEvent::unownedTouchEventType()) {
161+ unownedTouchEvent(static_cast<UnownedTouchEvent*>(event)->touchEvent());
162+ return true;
163+ }
164+
165+ return QQuickItem::event(event);
166+}
167+
168+void TouchGestureArea::touchOwnershipEvent(TouchOwnershipEvent *event)
169+{
170+ int touchId = event->touchId();
171+ tgaDebug("touchOwnershipEvent - id:" << touchId << ", gained:" << event->gained());
172+
173+ if (event->gained()) {
174+ grabTouchPoints(QVector<int>() << touchId);
175+ m_candidateTouches.remove(touchId);
176+ TouchRegistry::instance()->addTouchWatcher(touchId, this);
177+ m_watchedTouches.insert(touchId);
178+
179+ if (m_watchedTouches.count() >= m_minimumTouchPoints) {
180+ setInternalStatus(InternalStatus::Recognized);
181+ }
182+ } else {
183+ rejectGesture();
184+ }
185+}
186+
187+void TouchGestureArea::touchEvent(QTouchEvent *event)
188+{
189+ if (!isEnabled() || !isVisible()) {
190+ tgaDebug(QString("NOT ENABLED touchEvent(%1) %2").arg(statusToString(m_status)).arg(touchEventString(event)));
191+ QQuickItem::touchEvent(event);
192+ return;
193+ }
194+
195+ tgaDebug(QString("touchEvent(%1) %2").arg(statusToString(m_status)).arg(touchEventString(event)));
196+
197+ switch (m_status) {
198+ case InternalStatus::WaitingForTouch:
199+ touchEvent_waitingForTouch(event);
200+ break;
201+ case InternalStatus::WaitingForMoreTouches:
202+ touchEvent_waitingForMoreTouches(event);
203+ break;
204+ case InternalStatus::WaitingForOwnership:
205+ touchEvent_waitingForOwnership(event);
206+ break;
207+ case InternalStatus::Recognized:
208+ case InternalStatus::WaitingForRejection:
209+ touchEvent_recognized(event);
210+ break;
211+ case InternalStatus::Rejected:
212+ touchEvent_rejected(event);
213+ break;
214+ default: // Recognized:
215+ break;
216+ }
217+
218+ updateTouchPoints(event);
219+}
220+
221+void TouchGestureArea::touchEvent_waitingForTouch(QTouchEvent *event)
222+{
223+ Q_FOREACH(const QTouchEvent::TouchPoint& touchPoint, event->touchPoints()) {
224+ Qt::TouchPointState touchPointState = touchPoint.state();
225+ int touchId = touchPoint.id();
226+
227+ if (touchPointState == Qt::TouchPointPressed) {
228+ if (!m_candidateTouches.contains(touchId)) {
229+ TouchRegistry::instance()->addCandidateOwnerForTouch(touchId, this);
230+ m_candidateTouches.insert(touchId);
231+ }
232+ }
233+ }
234+ event->ignore();
235+
236+ if (m_candidateTouches.count() > m_maximumTouchPoints) {
237+ rejectGesture();
238+ } else if (m_candidateTouches.count() >= m_minimumTouchPoints) {
239+ setInternalStatus(InternalStatus::WaitingForOwnership);
240+
241+ QSet<int> tmpCandidates(m_candidateTouches);
242+ Q_FOREACH(int candidateTouchId, tmpCandidates) {
243+ TouchRegistry::instance()->requestTouchOwnership(candidateTouchId, this);
244+ }
245+ // We accept the gesture; so don't pass to lower items
246+ event->accept();
247+ } else if (m_candidateTouches.count() > 0) {
248+ setInternalStatus(InternalStatus::WaitingForMoreTouches);
249+ }
250+}
251+
252+void TouchGestureArea::touchEvent_waitingForMoreTouches(QTouchEvent *event)
253+{
254+ Q_FOREACH(const QTouchEvent::TouchPoint& touchPoint, event->touchPoints()) {
255+ Qt::TouchPointState touchPointState = touchPoint.state();
256+ int touchId = touchPoint.id();
257+
258+ if (touchPointState == Qt::TouchPointPressed) {
259+ if (!m_candidateTouches.contains(touchId)) {
260+ TouchRegistry::instance()->addCandidateOwnerForTouch(touchId, this);
261+ m_candidateTouches.insert(touchId);
262+ }
263+ }
264+ }
265+ event->ignore();
266+
267+ if (m_candidateTouches.count() > m_maximumTouchPoints) {
268+ rejectGesture();
269+ } else if (m_candidateTouches.count() >= m_minimumTouchPoints) {
270+ setInternalStatus(InternalStatus::WaitingForOwnership);
271+
272+ QSet<int> tmpCandidates(m_candidateTouches);
273+ Q_FOREACH(int candidateTouchId, tmpCandidates) {
274+ TouchRegistry::instance()->requestTouchOwnership(candidateTouchId, this);
275+ }
276+ // We accept the gesture; so don't pass to lower items
277+ event->accept();
278+ }
279+}
280+
281+void TouchGestureArea::touchEvent_waitingForOwnership(QTouchEvent *event)
282+{
283+ Q_FOREACH(const QTouchEvent::TouchPoint& touchPoint, event->touchPoints()) {
284+ Qt::TouchPointState touchPointState = touchPoint.state();
285+ int touchId = touchPoint.id();
286+
287+ if (touchPointState == Qt::TouchPointPressed) {
288+ if (!m_watchedTouches.contains(touchId)) {
289+ TouchRegistry::instance()->addTouchWatcher(touchId, this);
290+ m_watchedTouches.insert(touchId);
291+ }
292+ }
293+ }
294+}
295+
296+void TouchGestureArea::touchEvent_recognized(QTouchEvent *event)
297+{
298+ Q_FOREACH(const QTouchEvent::TouchPoint& touchPoint, event->touchPoints()) {
299+ Qt::TouchPointState touchPointState = touchPoint.state();
300+ int touchId = touchPoint.id();
301+
302+ if (touchPointState == Qt::TouchPointPressed) {
303+ if (!m_watchedTouches.contains(touchId)) {
304+ TouchRegistry::instance()->addTouchWatcher(touchId, this);
305+ m_watchedTouches.insert(touchId);
306+ }
307+ }
308+ }
309+
310+ if (m_watchedTouches.count() > m_maximumTouchPoints) {
311+ rejectGesture();
312+ } else if (m_watchedTouches.count() >= m_minimumTouchPoints &&
313+ m_status==InternalStatus::WaitingForRejection) {
314+ setInternalStatus(InternalStatus::Recognized);
315+ }
316+}
317+
318+void TouchGestureArea::touchEvent_rejected(QTouchEvent *event)
319+{
320+ Q_FOREACH(const QTouchEvent::TouchPoint& touchPoint, event->touchPoints()) {
321+ Qt::TouchPointState touchPointState = touchPoint.state();
322+ int touchId = touchPoint.id();
323+
324+ if (touchPointState == Qt::TouchPointPressed) {
325+ if (!m_watchedTouches.contains(touchId)) {
326+ TouchRegistry::instance()->addTouchWatcher(touchId, this);
327+ m_watchedTouches.insert(touchId);
328+ }
329+ }
330+ }
331+
332+ // If this event is a new touch, ignore it and let the item below have it.
333+ // We won't recognize any new touch until the whole current gesture is done
334+ // i.e. we're in WaitingForTouch state.
335+ // And even if it isn't, just ignore it anyway; we don't care about it.
336+ event->ignore();
337+}
338+
339+void TouchGestureArea::unownedTouchEvent(QTouchEvent *unownedTouchEvent)
340+{
341+ tgaDebug(QString("unownedTouchEvent(%1) %2").arg(statusToString(m_status)).arg(touchEventString(unownedTouchEvent)));
342+
343+ // Only monitor unowned touch events for presses/releases
344+ if ((unownedTouchEvent->touchPointStates() & (Qt::TouchPointPressed|Qt::TouchPointReleased)) == 0) {
345+ return;
346+ }
347+
348+ switch (m_status) {
349+ case InternalStatus::WaitingForTouch:
350+ break;
351+ case InternalStatus::WaitingForMoreTouches:
352+ unownedTouchEvent_waitingForMoreTouches(unownedTouchEvent);
353+ // do nothing
354+ break;
355+ case InternalStatus::WaitingForOwnership:
356+ unownedTouchEvent_waitingForOwnership(unownedTouchEvent);
357+ break;
358+ case InternalStatus::Recognized:
359+ case InternalStatus::WaitingForRejection:
360+ unownedTouchEvent_recognised(unownedTouchEvent);
361+ break;
362+ case InternalStatus::Rejected:
363+ unownedTouchEvent_rejected(unownedTouchEvent);
364+ break;
365+ default:
366+ break;
367+ }
368+
369+ updateTouchPoints(unownedTouchEvent);
370+}
371+
372+void TouchGestureArea::unownedTouchEvent_waitingForMoreTouches(QTouchEvent *event)
373+{
374+ Q_FOREACH(const QTouchEvent::TouchPoint& touchPoint, event->touchPoints()) {
375+ Qt::TouchPointState touchPointState = touchPoint.state();
376+ int touchId = touchPoint.id();
377+
378+ if (touchPointState == Qt::TouchPointReleased) {
379+ if (m_candidateTouches.contains(touchId)) {
380+ TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, this);
381+ m_candidateTouches.remove(touchId);
382+ }
383+ }
384+ }
385+
386+ if (m_candidateTouches.isEmpty()) {
387+ setInternalStatus(InternalStatus::WaitingForTouch);
388+ }
389+}
390+
391+void TouchGestureArea::unownedTouchEvent_waitingForOwnership(QTouchEvent *event)
392+{
393+ Q_FOREACH(const QTouchEvent::TouchPoint& touchPoint, event->touchPoints()) {
394+ Qt::TouchPointState touchPointState = touchPoint.state();
395+ int touchId = touchPoint.id();
396+
397+ if (touchPointState == Qt::TouchPointReleased) {
398+ if (m_candidateTouches.contains(touchId)) {
399+ TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, this);
400+ m_candidateTouches.remove(touchId);
401+ }
402+ if (m_watchedTouches.contains(touchId)) {
403+ m_watchedTouches.remove(touchId);
404+ }
405+ }
406+ }
407+
408+ if (m_candidateTouches.count() + m_watchedTouches.count() == 0) {
409+ setInternalStatus(InternalStatus::WaitingForTouch);
410+ }
411+}
412+
413+void TouchGestureArea::unownedTouchEvent_recognised(QTouchEvent *event)
414+{
415+ Q_FOREACH(const QTouchEvent::TouchPoint& touchPoint, event->touchPoints()) {
416+ Qt::TouchPointState touchPointState = touchPoint.state();
417+ int touchId = touchPoint.id();
418+
419+ if (touchPointState == Qt::TouchPointReleased) {
420+ if (m_watchedTouches.contains(touchId)) {
421+ m_watchedTouches.remove(touchId);
422+ }
423+ }
424+ }
425+
426+ if (m_watchedTouches.count() < m_minimumTouchPoints && m_status==InternalStatus::Recognized) {
427+ setInternalStatus(InternalStatus::WaitingForRejection);
428+ }
429+}
430+
431+void TouchGestureArea::unownedTouchEvent_rejected(QTouchEvent *event)
432+{
433+ Q_FOREACH(const QTouchEvent::TouchPoint& touchPoint, event->touchPoints()) {
434+ Qt::TouchPointState touchPointState = touchPoint.state();
435+ int touchId = touchPoint.id();
436+
437+ if (touchPointState == Qt::TouchPointPressed) {
438+ if (!m_watchedTouches.contains(touchId)) {
439+ TouchRegistry::instance()->addTouchWatcher(touchId, this);
440+ m_watchedTouches.insert(touchId);
441+ }
442+ }
443+ if (touchPointState == Qt::TouchPointReleased) {
444+ if (m_watchedTouches.contains(touchId)) {
445+ m_watchedTouches.remove(touchId);
446+ }
447+ }
448+ }
449+
450+ if (m_watchedTouches.isEmpty()) {
451+ setInternalStatus(InternalStatus::WaitingForTouch);
452+ }
453+}
454+
455+void TouchGestureArea::updateTouchPoints(QTouchEvent *touchEvent)
456+{
457+ bool added = false;
458+ bool ended = false;
459+ bool moved = false;
460+
461+ const int dragThreshold = qApp->styleHints()->startDragDistance();
462+ const int dragVelocity = qApp->styleHints()->startDragVelocity();
463+
464+ clearTouchLists();
465+ bool updateable = m_status != InternalStatus::WaitingForRejection;
466+
467+ Q_FOREACH(const QTouchEvent::TouchPoint& touchPoint, touchEvent->touchPoints()) {
468+ Qt::TouchPointState touchPointState = touchPoint.state();
469+ int touchId = touchPoint.id();
470+
471+ if (touchPointState & Qt::TouchPointReleased) {
472+ GestureTouchPoint* gtp = m_liveTouchPoints.value(touchId);
473+ if (!gtp) continue;
474+
475+ gtp->setPos(touchPoint.pos());
476+ gtp->setPressed(false);
477+ m_releasedTouchPoints.append(gtp);
478+ m_liveTouchPoints.remove(touchId);
479+
480+ if (updateable) {
481+ if (m_cachedTouchPoints.contains(touchId)) {
482+ GestureTouchPoint* cachedPoint = m_cachedTouchPoints.take(touchId);
483+ cachedPoint->deleteLater();
484+ }
485+ }
486+ ended = true;
487+ } else {
488+ GestureTouchPoint* gtp = m_liveTouchPoints.value(touchPoint.id(), nullptr);
489+ if (!gtp) {
490+ gtp = addTouchPoint(&touchPoint);
491+ m_pressedTouchPoints.append(gtp);
492+
493+ if (updateable) {
494+ if (m_cachedTouchPoints.contains(touchId)) {
495+ m_cachedTouchPoints[touchId]->setPos(touchPoint.pos());
496+ } else {
497+ m_cachedTouchPoints[touchId] = new GestureTouchPoint(*gtp);
498+ }
499+ }
500+ added = true;
501+ } else if (touchPointState & Qt::TouchPointMoved) {
502+ gtp->setPos(touchPoint.pos());
503+ m_movedTouchPoints.append(gtp);
504+ moved = true;
505+
506+ const QPointF &currentPos = touchPoint.scenePos();
507+ const QPointF &startPos = touchPoint.startScenePos();
508+
509+ bool overDragThreshold = false;
510+ bool supportsVelocity = (touchEvent->device()->capabilities() & QTouchDevice::Velocity) && dragVelocity;
511+ overDragThreshold |= qAbs(currentPos.x() - startPos.x()) > dragThreshold ||
512+ qAbs(currentPos.y() - startPos.y()) > dragThreshold;
513+ if (supportsVelocity) {
514+ QVector2D velocityVec = touchPoint.velocity();
515+ overDragThreshold |= qAbs(velocityVec.x()) > dragVelocity;
516+ overDragThreshold |= qAbs(velocityVec.y()) > dragVelocity;
517+ }
518+
519+ if (overDragThreshold) {
520+ gtp->setDragging(true);
521+ }
522+
523+ if (updateable) {
524+ if (m_cachedTouchPoints.contains(touchId)) {
525+ m_cachedTouchPoints[touchId]->setPos(touchPoint.pos());
526+ if (overDragThreshold) {
527+ m_cachedTouchPoints[touchId]->setDragging(true);
528+ }
529+ }
530+ }
531+ }
532+ }
533+ }
534+
535+ if (updateable) {
536+ if (!dragging() && m_status == InternalStatus::Recognized) {
537+ bool allWantDrag = !m_liveTouchPoints.isEmpty();
538+ Q_FOREACH(const auto &point, m_liveTouchPoints) {
539+ allWantDrag &= point->dragging();
540+ }
541+ // only dragging if all points are dragging.
542+ if (allWantDrag) {
543+ setDragging(true);
544+ }
545+ }
546+
547+ if (ended) {
548+ if (m_liveTouchPoints.isEmpty()) {
549+ if (!dragging()) Q_EMIT clicked();
550+ setDragging(false);
551+ }
552+ tgaDebug("Released " << touchesString(m_releasedTouchPoints));
553+ Q_EMIT released(m_releasedTouchPoints);
554+ }
555+ if (added) {
556+ tgaDebug("Pressed " << touchesString(m_pressedTouchPoints));
557+ Q_EMIT pressed(m_pressedTouchPoints);
558+ }
559+ if (moved) {
560+ tgaDebug("Updated " << touchesString(m_movedTouchPoints));
561+ Q_EMIT updated(m_movedTouchPoints);
562+ }
563+ if (added || ended || moved) {
564+ Q_EMIT touchPointsUpdated();
565+ }
566+ }
567+}
568+
569+void TouchGestureArea::clearTouchLists()
570+{
571+ Q_FOREACH (QObject *gtp, m_releasedTouchPoints) {
572+ delete gtp;
573+ }
574+ m_releasedTouchPoints.clear();
575+ m_pressedTouchPoints.clear();
576+ m_movedTouchPoints.clear();
577+}
578+
579+void TouchGestureArea::setInternalStatus(uint newStatus)
580+{
581+ if (newStatus == m_status)
582+ return;
583+
584+ uint oldStatus = m_status;
585+
586+ m_status = newStatus;
587+ Q_EMIT statusChanged(status());
588+
589+ if (oldStatus == InternalStatus::WaitingForMoreTouches || oldStatus == InternalStatus::WaitingForRejection) {
590+ m_recognitionTimer->stop();
591+ }
592+
593+ tgaDebug(statusToString(oldStatus) << " -> " << statusToString(newStatus));
594+
595+ switch (newStatus) {
596+ case InternalStatus::WaitingForTouch:
597+ resyncCachedTouchPoints();
598+ break;
599+ case InternalStatus::WaitingForMoreTouches:
600+ m_recognitionTimer->setInterval(m_recognitionPeriod);
601+ m_recognitionTimer->start();
602+ break;
603+ case InternalStatus::Recognized:
604+ resyncCachedTouchPoints();
605+ break;
606+ case InternalStatus::WaitingForRejection:
607+ m_recognitionTimer->setInterval(m_releaseRejectPeriod);
608+ m_recognitionTimer->start();
609+ break;
610+ case InternalStatus::Rejected:
611+ resyncCachedTouchPoints();
612+ break;
613+ default:
614+ // no-op
615+ break;
616+ }
617+}
618+
619+void TouchGestureArea::setRecognitionTimer(AbstractTimer *timer)
620+{
621+ int interval = 0;
622+ bool timerWasRunning = false;
623+ bool wasSingleShot = false;
624+
625+ // can be null when called from the constructor
626+ if (m_recognitionTimer) {
627+ interval = m_recognitionTimer->interval();
628+ timerWasRunning = m_recognitionTimer->isRunning();
629+ if (m_recognitionTimer->parent() == this) {
630+ delete m_recognitionTimer;
631+ }
632+ }
633+
634+ m_recognitionTimer = timer;
635+ timer->setInterval(interval);
636+ timer->setSingleShot(wasSingleShot);
637+ connect(timer, SIGNAL(timeout()),
638+ this, SLOT(rejectGesture()));
639+ if (timerWasRunning) {
640+ m_recognitionTimer->start();
641+ }
642+}
643+
644+int TouchGestureArea::status() const
645+{
646+ return internalStatusToGestureStatus(m_status);
647+}
648+
649+bool TouchGestureArea::dragging() const
650+{
651+ return m_dragging;
652+}
653+
654+QQmlListProperty<GestureTouchPoint> TouchGestureArea::touchPoints()
655+{
656+ return QQmlListProperty<GestureTouchPoint>(this,
657+ nullptr,
658+ TouchGestureArea::touchPoint_count,
659+ TouchGestureArea::touchPoint_at);
660+}
661+
662+int TouchGestureArea::minimumTouchPoints() const
663+{
664+ return m_minimumTouchPoints;
665+}
666+
667+void TouchGestureArea::setMinimumTouchPoints(int value)
668+{
669+ if (m_minimumTouchPoints != value) {
670+ m_minimumTouchPoints = value;
671+ Q_EMIT minimumTouchPointsChanged(value);
672+ }
673+}
674+
675+int TouchGestureArea::maximumTouchPoints() const
676+{
677+ return m_maximumTouchPoints;
678+}
679+
680+void TouchGestureArea::setMaximumTouchPoints(int value)
681+{
682+ if (m_maximumTouchPoints != value) {
683+ m_maximumTouchPoints = value;
684+ Q_EMIT maximumTouchPointsChanged(value);
685+ }
686+}
687+
688+int TouchGestureArea::recognitionPeriod() const
689+{
690+ return m_recognitionPeriod;
691+}
692+
693+void TouchGestureArea::setRecognitionPeriod(int value)
694+{
695+ if (value != m_recognitionPeriod) {
696+ m_recognitionPeriod = value;
697+ Q_EMIT recognitionPeriodChanged(value);
698+ }
699+}
700+
701+int TouchGestureArea::releaseRejectPeriod() const
702+{
703+ return m_releaseRejectPeriod;
704+}
705+
706+void TouchGestureArea::setReleaseRejectPeriod(int value)
707+{
708+ if (value != m_releaseRejectPeriod) {
709+ m_releaseRejectPeriod = value;
710+ Q_EMIT releaseRejectPeriodChanged(value);
711+ }
712+}
713+
714+void TouchGestureArea::rejectGesture()
715+{
716+ tgaDebug("rejectGesture");
717+ ungrabTouchPoints();
718+
719+ Q_FOREACH(int touchId, m_candidateTouches) {
720+ TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, this);
721+ }
722+
723+ // Monitor the candidates
724+ Q_FOREACH(int touchId, m_candidateTouches) {
725+ TouchRegistry::instance()->addTouchWatcher(touchId, this);
726+ m_watchedTouches.insert(touchId);
727+ }
728+ m_candidateTouches.clear();
729+
730+ if (m_watchedTouches.isEmpty()) {
731+ setInternalStatus(InternalStatus::WaitingForTouch);
732+ } else {
733+ setInternalStatus(InternalStatus::Rejected);
734+ }
735+}
736+
737+void TouchGestureArea::resyncCachedTouchPoints()
738+{
739+ clearTouchLists();
740+
741+ bool added = false;
742+ bool ended = false;
743+ bool moved = false;
744+
745+ // list of deletes
746+ QMutableHashIterator<int, GestureTouchPoint*> removeIter(m_cachedTouchPoints);
747+ while(removeIter.hasNext()) {
748+ removeIter.next();
749+ if (!m_liveTouchPoints.contains(removeIter.key())) {
750+ m_releasedTouchPoints.append(removeIter.value());
751+ removeIter.remove();
752+ ended = true;
753+ }
754+ }
755+
756+ // list of adds/moves
757+ Q_FOREACH(GestureTouchPoint* touchPoint, m_liveTouchPoints) {
758+ if (m_cachedTouchPoints.contains(touchPoint->id())) {
759+ GestureTouchPoint* cachedPoint = m_cachedTouchPoints[touchPoint->id()];
760+
761+ if (*cachedPoint != *touchPoint) {
762+ *cachedPoint = *touchPoint;
763+ m_movedTouchPoints.append(touchPoint);
764+ moved = true;
765+ }
766+ } else {
767+ m_cachedTouchPoints.insert(touchPoint->id(), new GestureTouchPoint(*touchPoint));
768+ m_pressedTouchPoints.append(touchPoint);
769+ added = true;
770+ }
771+ }
772+
773+ if (ended) {
774+ if (m_cachedTouchPoints.isEmpty()) {
775+ if (!dragging()) Q_EMIT clicked();
776+ setDragging(false);
777+ }
778+ tgaDebug("Cached Release " << touchesString(m_releasedTouchPoints));
779+ Q_EMIT released(m_releasedTouchPoints);
780+ }
781+ if (added) {
782+ tgaDebug("Cached Press " << touchesString(m_pressedTouchPoints));
783+ Q_EMIT pressed(m_pressedTouchPoints);
784+ }
785+ if (moved) {
786+ tgaDebug("Cached Update " << touchesString(m_movedTouchPoints));
787+ Q_EMIT updated(m_movedTouchPoints);
788+ }
789+ if (added || ended || moved) Q_EMIT touchPointsUpdated();
790+}
791+
792+int TouchGestureArea::touchPoint_count(QQmlListProperty<GestureTouchPoint> *list)
793+{
794+ TouchGestureArea *q = static_cast<TouchGestureArea*>(list->object);
795+ return q->m_cachedTouchPoints.count();
796+}
797+
798+GestureTouchPoint *TouchGestureArea::touchPoint_at(QQmlListProperty<GestureTouchPoint> *list, int index)
799+{
800+ TouchGestureArea *q = static_cast<TouchGestureArea*>(list->object);
801+ return (q->m_cachedTouchPoints.begin()+index).value();
802+}
803+
804+GestureTouchPoint* TouchGestureArea::addTouchPoint(QTouchEvent::TouchPoint const* tp)
805+{
806+ GestureTouchPoint* gtp = new GestureTouchPoint();
807+ gtp->setId(tp->id());
808+ gtp->setPressed(true);
809+ gtp->setPos(tp->pos());
810+ m_liveTouchPoints.insert(tp->id(), gtp);
811+ return gtp;
812+}
813+
814+void TouchGestureArea::itemChange(ItemChange change, const ItemChangeData &value)
815+{
816+ if (change == QQuickItem::ItemSceneChange) {
817+ if (value.window != nullptr) {
818+ value.window->installEventFilter(TouchRegistry::instance());
819+ }
820+ }
821+}
822+
823+void TouchGestureArea::setDragging(bool dragging)
824+{
825+ if (m_dragging == dragging)
826+ return;
827+
828+ tgaDebug("setDragging " << dragging);
829+
830+ m_dragging = dragging;
831+ Q_EMIT draggingChanged(m_dragging);
832+}
833+
834+void GestureTouchPoint::setId(int id)
835+{
836+ if (m_id == id)
837+ return;
838+ m_id = id;
839+ Q_EMIT idChanged();
840+}
841+
842+void GestureTouchPoint::setPressed(bool pressed)
843+{
844+ if (m_pressed == pressed)
845+ return;
846+ m_pressed = pressed;
847+ Q_EMIT pressedChanged();
848+}
849+
850+void GestureTouchPoint::setX(qreal x)
851+{
852+ if (m_x == x)
853+ return;
854+ m_x = x;
855+ Q_EMIT xChanged();
856+}
857+
858+void GestureTouchPoint::setY(qreal y)
859+{
860+ if (m_y == y)
861+ return;
862+ m_y = y;
863+ Q_EMIT yChanged();
864+}
865+
866+void GestureTouchPoint::setDragging(bool dragging)
867+{
868+ if (m_dragging == dragging)
869+ return;
870+
871+ m_dragging = dragging;
872+ Q_EMIT draggingChanged();
873+}
874+
875+void GestureTouchPoint::setPos(const QPointF &pos)
876+{
877+ setX(pos.x());
878+ setY(pos.y());
879+}
plugins/Ubuntu/Gestures/TouchGestureArea.hnew file+229

This diff is too big to show here.

plugins/Ubuntu/Gestures/plugin.cpp+6−5

This diff is too big to show here.

plugins/Ubuntu/Payments/CMakeLists.txtdeleted−20

This diff is too big to show here.

plugins/Ubuntu/Payments/Payments.cppdeleted−136

This diff is too big to show here.

plugins/Ubuntu/Payments/Payments.hdeleted−69

This diff is too big to show here.

plugins/Ubuntu/Payments/Payments.qmltypesdeleted−43

This diff is too big to show here.

plugins/Ubuntu/Payments/qmldirdeleted−3

This diff is too big to show here.

plugins/Ubuntu/SystemImage/CMakeLists.txtdeleted−10

This diff is too big to show here.

plugins/Ubuntu/SystemImage/SystemImage.cppdeleted−33

This diff is too big to show here.

plugins/Ubuntu/SystemImage/SystemImage.qmltypesdeleted−19

This diff is too big to show here.

plugins/Ubuntu/SystemImage/qmldirdeleted−3

This diff is too big to show here.

plugins/Unity/ApplicationMenu/CMakeLists.txtnew file+19

This diff is too big to show here.

plugins/Unity/ApplicationMenu/applicationmenuregistry.cppnew file+141

This diff is too big to show here.

plugins/Unity/ApplicationMenu/applicationmenuregistry.hnew file+83

This diff is too big to show here.

plugins/Unity/ApplicationMenu/com.ubuntu.MenuRegistrar.xmlnew file+83

This diff is too big to show here.

plugins/Unity/ApplicationMenu/dbusapplicationmenuregistry.cppnew file+44

This diff is too big to show here.

plugins/Unity/ApplicationMenu/dbusapplicationmenuregistry.hnew file+34

This diff is too big to show here.

plugins/Unity/ApplicationMenu/plugin.cppnew file+42

This diff is too big to show here.

plugins/Ubuntu/SystemImage/plugin.h → plugins/Unity/ApplicationMenu/plugin.hrenamed+6−5

This diff is too big to show here.

plugins/Unity/ApplicationMenu/qmldirnew file+3

This diff is too big to show here.

plugins/Unity/CMakeLists.txt+1−1

This diff is too big to show here.

plugins/Unity/Connectivity/CMakeLists.txt+1−1

This diff is too big to show here.

plugins/Unity/Connectivity/Connectivity.qmltypesdeleted−19

This diff is too big to show here.

plugins/Unity/DashCommunicator/CMakeLists.txtdeleted−25

This diff is too big to show here.

plugins/Unity/DashCommunicator/DashCommunicator.qmltypesdeleted−47

This diff is too big to show here.

plugins/Unity/DashCommunicator/dashcommunicator.cppdeleted−52

This diff is too big to show here.

plugins/Unity/DashCommunicator/dashconnection.cppdeleted−63

This diff is too big to show here.

plugins/Unity/DashCommunicator/dashconnection.hdeleted−37

This diff is too big to show here.

plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cppdeleted−35

This diff is too big to show here.

plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.hdeleted−39

This diff is too big to show here.

plugins/Unity/DashCommunicator/qmldirdeleted−3

This diff is too big to show here.

plugins/Unity/Indicators/CMakeLists.txt+8−6

This diff is too big to show here.

plugins/Unity/Indicators/Indicators.qmltypesdeleted−264

This diff is too big to show here.

plugins/Unity/Indicators/actionrootstate.cpp+1−1

This diff is too big to show here.

plugins/Unity/Indicators/indicators.h+5−5

This diff is too big to show here.

plugins/Unity/Indicators/indicatorsmanager.cpp+6−13

This diff is too big to show here.

plugins/Unity/Indicators/indicatorsmanager.h−2

This diff is too big to show here.

plugins/Unity/Indicators/indicatorsmodel.cpp+13

This diff is too big to show here.

plugins/Unity/Indicators/indicatorsmodel.h+9−1

This diff is too big to show here.

plugins/Unity/Indicators/modelactionrootstate.cpp+76−1

This diff is too big to show here.

plugins/Unity/Indicators/modelactionrootstate.h+15−4

This diff is too big to show here.

plugins/Unity/Indicators/modelprinter.cpp+19−4

This diff is too big to show here.

plugins/Unity/Indicators/modelprinter.h+2−1

This diff is too big to show here.

plugins/Unity/Indicators/rootstateparser.h+1

This diff is too big to show here.

plugins/Unity/Indicators/sharedunitymenumodel.cpp+4

This diff is too big to show here.

plugins/Unity/InputInfo/CMakeLists.txt+1−2

This diff is too big to show here.

plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux.cpp+10−2

This diff is too big to show here.

plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux_p.h−2

This diff is too big to show here.

plugins/Unity/InputInfo/plugin.h+1−1

This diff is too big to show here.

plugins/Unity/InputInfo/qdeclarativeinputdevicemodel_p.h+3−3

This diff is too big to show here.

plugins/Unity/InputInfo/qinputinfo.h+2−3

This diff is too big to show here.

plugins/Unity/Launcher/CMakeLists.txt+18−5

This diff is too big to show here.

plugins/Unity/Launcher/Launcher.qmltypesdeleted−182

This diff is too big to show here.

plugins/Unity/Launcher/appdrawermodel.cppnew file+192

This diff is too big to show here.

plugins/Unity/Launcher/appdrawermodel.hnew file+64

This diff is too big to show here.

plugins/Unity/Launcher/asadapter.cpp+6−2

This diff is too big to show here.

plugins/Unity/Launcher/desktopfilehandler.cppdeleted−155

This diff is too big to show here.

plugins/Unity/Launcher/desktopfilehandler.hdeleted−56

This diff is too big to show here.

plugins/Unity/Launcher/launcheritem.cpp+65−9

This diff is too big to show here.

plugins/Unity/Launcher/launcheritem.h+12−1

This diff is too big to show here.

plugins/Unity/Launcher/launchermodel.cpp+128−59

This diff is too big to show here.

plugins/Unity/Launcher/launchermodel.h+7−10

This diff is too big to show here.

plugins/Unity/Launcher/plugin.cpp+2−1

This diff is too big to show here.

plugins/Unity/Launcher/quicklistentry.cpp+22

This diff is too big to show here.

plugins/Unity/Launcher/quicklistentry.h+8

This diff is too big to show here.

plugins/Unity/Launcher/quicklistmodel.cpp+11

This diff is too big to show here.

plugins/Unity/Launcher/quicklistmodel.h+1

This diff is too big to show here.

plugins/Unity/Launcher/ualwrapper.cppnew file+74

This diff is too big to show here.

plugins/Unity/Launcher/ualwrapper.hnew file+36

This diff is too big to show here.

plugins/Unity/Launcher/xdgwatcher.cppnew file+129

This diff is too big to show here.

plugins/Unity/Launcher/xdgwatcher.hnew file+46

This diff is too big to show here.

plugins/Unity/Platform/CMakeLists.txt+1−1

This diff is too big to show here.

plugins/Unity/Platform/platform.cpp+16−2

This diff is too big to show here.

plugins/Unity/Session/CMakeLists.txt+5−3

This diff is too big to show here.

plugins/Unity/Session/Session.qmltypesdeleted−85

This diff is too big to show here.

plugins/Unity/Session/dbusunitysessionservice.cpp+139−28

This diff is too big to show here.

plugins/Unity/Session/dbusunitysessionservice.h+25−4

This diff is too big to show here.

plugins/Unity/Session/plugin.cpp+1

This diff is too big to show here.

plugins/Utils/CMakeLists.txt+21−9

This diff is too big to show here.

plugins/Utils/EdgeBarrierSettings.qml+1−1

This diff is too big to show here.

plugins/Utils/ElapsedTimer.h+1−1

This diff is too big to show here.

plugins/Utils/HomeKeyWatcher.hdeleted−74

This diff is too big to show here.

plugins/Utils/Timer.cpp+5−2

This diff is too big to show here.

plugins/Utils/Timer.h+5−6

This diff is too big to show here.

plugins/Utils/URLDispatcher.cppnew file+80

This diff is too big to show here.

plugins/Utils/URLDispatcher.hnew file+47

This diff is too big to show here.

plugins/Utils/Utils.qmltypesdeleted−175

This diff is too big to show here.

plugins/Utils/HomeKeyWatcher.cpp → plugins/Utils/WindowInputMonitor.cpprenamed+30−20

This diff is too big to show here.

plugins/Utils/WindowInputMonitor.hnew file+97

This diff is too big to show here.

plugins/Utils/appdrawerproxymodel.cppnew file+189

This diff is too big to show here.

plugins/Utils/appdrawerproxymodel.hnew file+87

This diff is too big to show here.

plugins/Utils/constants.cpp+6−1

This diff is too big to show here.

plugins/Utils/constants.h+5−5

This diff is too big to show here.

plugins/Utils/deviceconfigparser.cppnew file+176

This diff is too big to show here.

plugins/Utils/deviceconfigparser.hnew file+66

This diff is too big to show here.

plugins/Utils/easingcurve.h−1

This diff is too big to show here.

plugins/Utils/expressionfiltermodel.cppnew file+49

This diff is too big to show here.

plugins/Utils/expressionfiltermodel.hnew file+42

This diff is too big to show here.

plugins/Utils/globalfunctions.cppnew file+58

This diff is too big to show here.

plugins/Utils/globalfunctions.hnew file+44

This diff is too big to show here.

plugins/Utils/inputeventgenerator.cppnew file+34

This diff is too big to show here.

plugins/Utils/inputeventgenerator.hnew file+40

This diff is too big to show here.

plugins/Utils/plugin.cpp+28−13

This diff is too big to show here.

plugins/Utils/plugin.h−1

This diff is too big to show here.

plugins/Utils/quicklistproxymodel.cppnew file+72

This diff is too big to show here.

plugins/Utils/quicklistproxymodel.hnew file+52

This diff is too big to show here.

plugins/Utils/tabfocusfence.cppnew file+72

This diff is too big to show here.

plugins/Utils/tabfocusfence.hnew file+38

This diff is too big to show here.

plugins/Utils/timezoneFormatter.cpp+10

This diff is too big to show here.

plugins/Utils/timezoneFormatter.h+1

This diff is too big to show here.

plugins/Utils/unitysortfilterproxymodelqml.h+5

This diff is too big to show here.

plugins/Utils/windowkeysfilter.cpp → plugins/Utils/windowinputfilter.cpprenamed+14−16

This diff is too big to show here.

plugins/Utils/windowkeysfilter.h → plugins/Utils/windowinputfilter.hrenamed+11−11

This diff is too big to show here.

plugins/Utils/windowscreenshotprovider.cppdeleted−59

This diff is too big to show here.

plugins/Utils/windowstatestorage.cpp+322−95

This diff is too big to show here.

plugins/Utils/windowstatestorage.h+37−17

This diff is too big to show here.

plugins/WindowManager/AvailableDesktopArea.cppnew file+50

This diff is too big to show here.

plugins/Unity/DashCommunicator/dashcommunicator.h → plugins/WindowManager/AvailableDesktopArea.hrenamed+14−21

This diff is too big to show here.

plugins/WindowManager/CMakeLists.txtnew file+26

This diff is too big to show here.

plugins/WindowManager/InputMethodManager.cppnew file+56

This diff is too big to show here.

plugins/WindowManager/InputMethodManager.hnew file+55

This diff is too big to show here.

plugins/WindowManager/TopLevelWindowModel.cppnew file+782

This diff is too big to show here.

plugins/WindowManager/TopLevelWindowModel.hnew file+308

This diff is too big to show here.

plugins/WindowManager/Window.cppnew file+277

This diff is too big to show here.

plugins/WindowManager/Window.hnew file+176

This diff is too big to show here.

libs/UbuntuGestures/UbuntuGesturesGlobal.h → plugins/WindowManager/WindowManagerGlobal.hrenamed+4−4

This diff is too big to show here.

plugins/WindowManager/WindowManagerPlugin.cppnew file+44

This diff is too big to show here.

plugins/WindowManager/WindowManagerPlugin.hnew file+32

This diff is too big to show here.

plugins/WindowManager/WindowMargins.cppnew file+74

This diff is too big to show here.

plugins/WindowManager/WindowMargins.hnew file+59

This diff is too big to show here.

plugins/WindowManager/qmldirnew file+2

This diff is too big to show here.

plugins/Wizard/CMakeLists.txt+13−1

This diff is too big to show here.

plugins/Wizard/Changelog.cppnew file+58

This diff is too big to show here.

plugins/Wizard/Changelog.hnew file+52

This diff is too big to show here.

plugins/Wizard/LocalePlugin.cppnew file+291

This diff is too big to show here.

plugins/Wizard/LocalePlugin.hnew file+58

This diff is too big to show here.

plugins/Wizard/PageList.cpp+20−5

This diff is too big to show here.

plugins/Wizard/Status.cppnew file+143

This diff is too big to show here.

plugins/Wizard/Status.hnew file+60

This diff is too big to show here.

plugins/Wizard/System.cpp+82−10

This diff is too big to show here.

plugins/Wizard/System.h+24−2

This diff is too big to show here.

plugins/Wizard/Utils/CMakeLists.txt+1−1

This diff is too big to show here.

plugins/Wizard/Wizard.qmltypesdeleted−33

This diff is too big to show here.

plugins/Wizard/keyboardLayoutsModel.cppnew file+163

This diff is too big to show here.

plugins/Wizard/keyboardLayoutsModel.hnew file+66

This diff is too big to show here.

plugins/Wizard/plugin.cpp+11−8

This diff is too big to show here.

plugins/Wizard/plugin.h+1−2

This diff is too big to show here.

plugins/Wizard/qmldir−1

This diff is too big to show here.

plugins/Wizard/test.shdeleted−18

This diff is too big to show here.

plugins/Wizard/timezonemodel.cppnew file+244

This diff is too big to show here.

plugins/Wizard/timezonemodel.hnew file+80

This diff is too big to show here.

po/aa.ponew file+880

This diff is too big to show here.

po/am.po+1041−432

This diff is too big to show here.

po/ar.po+946−469

This diff is too big to show here.

po/ast.po+1044−441

This diff is too big to show here.

po/az.po+565−343

This diff is too big to show here.

po/be.po+916−464

This diff is too big to show here.

po/bg.po+491−328

This diff is too big to show here.

po/bn.po+848−448

This diff is too big to show here.

po/br.po+971−435

This diff is too big to show here.

po/bs.po+875−422

This diff is too big to show here.

po/ca.po+1093−450

This diff is too big to show here.

po/ca@valencia.po+745−403

This diff is too big to show here.

po/ce.po+461−307

This diff is too big to show here.

po/ckb.po+483−323

This diff is too big to show here.

po/co.ponew file+1061

This diff is too big to show here.

po/cs.po+1027−458

This diff is too big to show here.

po/cy.po+859−410

This diff is too big to show here.

po/da.po+887−441

This diff is too big to show here.

po/de.po+1083−442

This diff is too big to show here.

po/el.po+975−452

This diff is too big to show here.

po/en_AU.po+1081−436

This diff is too big to show here.

po/en_GB.po+1035−432

This diff is too big to show here.

po/en_US.ponew file+814

This diff is too big to show here.

po/eo.po+594−332

This diff is too big to show here.

po/es.po+1080−447

This diff is too big to show here.

po/et.ponew file+816

This diff is too big to show here.

po/eu.po+868−426

This diff is too big to show here.

po/fa.po+1090−437

This diff is too big to show here.

po/fi.po+1071−438

This diff is too big to show here.

po/fo.po+581−357

This diff is too big to show here.

po/fr.po+1109−457

This diff is too big to show here.

po/ga.po+789−342

This diff is too big to show here.

po/gd.po+1080−447

This diff is too big to show here.

po/gl.po+1072−439

This diff is too big to show here.

po/gu.ponew file+814

This diff is too big to show here.

po/gv.po+530−344

This diff is too big to show here.

po/he.po+798−440

This diff is too big to show here.

po/hi.po+477−319

This diff is too big to show here.

po/hr.po+1089−438

This diff is too big to show here.

po/hu.po+1072−441

This diff is too big to show here.

po/hy.po+601−388

This diff is too big to show here.

po/ia.po+1047−433

This diff is too big to show here.

po/id.po+608−363

This diff is too big to show here.

po/is.po+589−360

This diff is too big to show here.

po/it.po+1080−445

This diff is too big to show here.

po/ja.po+640−382

This diff is too big to show here.

po/kk.ponew file+841

This diff is too big to show here.

po/km.po+705−394

This diff is too big to show here.

po/kn.po+468−316

This diff is too big to show here.

po/ko.po+888−427

This diff is too big to show here.

po/ku.po+569−343

This diff is too big to show here.

po/ky.po+468−316

This diff is too big to show here.

po/lo.po+468−314

This diff is too big to show here.

po/lt.po+714−394

This diff is too big to show here.

po/lv.po+867−424

This diff is too big to show here.

po/ml.po+484−325

This diff is too big to show here.

po/mr.po+488−316

This diff is too big to show here.

po/ms.po+1008−435

This diff is too big to show here.

po/my.po+540−333

This diff is too big to show here.

po/nb.po+1066−441

This diff is too big to show here.

po/ne.ponew file+834

This diff is too big to show here.

po/nl.po+1086−457

This diff is too big to show here.

po/nn.po+461−307

This diff is too big to show here.

po/oc.po+1046−432

This diff is too big to show here.

po/or.po+461−307

This diff is too big to show here.

po/pa.po+850−411

This diff is too big to show here.

po/pl.po+1081−445

This diff is too big to show here.

po/pt.po+1080−452

This diff is too big to show here.

po/pt_BR.po+899−442

This diff is too big to show here.

po/ro.po+865−428

This diff is too big to show here.

po/ru.po+1073−451

This diff is too big to show here.

po/sc.ponew file+904

This diff is too big to show here.

po/shn.po+462−308

This diff is too big to show here.

po/si.po+492−331

This diff is too big to show here.

po/sk.po+1136−446

This diff is too big to show here.

po/sl.po+1053−428

This diff is too big to show here.

po/sq.po+732−365

This diff is too big to show here.

po/sr.po+1054−447

This diff is too big to show here.

po/sv.po+1063−436

This diff is too big to show here.

po/sw.po+767−390

This diff is too big to show here.

po/ta.po+483−324

This diff is too big to show here.

po/te.po+492−324

This diff is too big to show here.

po/th.po+478−323

This diff is too big to show here.

po/tr.po+1071−438

This diff is too big to show here.

po/ug.po+889−421

This diff is too big to show here.

po/uk.po+1063−445

This diff is too big to show here.

po/unity8.pot+458−305

This diff is too big to show here.

po/update-unity-pot+17

This diff is too big to show here.

po/ur.po+483−326

This diff is too big to show here.

po/uz.po+461−307

This diff is too big to show here.

po/vi.po+461−307

This diff is too big to show here.

po/wo.po+866−424

This diff is too big to show here.

po/xh.po+461−307

This diff is too big to show here.

po/zh_CN.po+1043−427

This diff is too big to show here.

po/zh_HK.po+511−329

This diff is too big to show here.

po/zh_TW.po+977−434

This diff is too big to show here.

qml/ApplicationMenus/ApplicationMenuItemFactory.qmlnew file+135

This diff is too big to show here.

qml/ApplicationMenus/ApplicationMenusLimits.qmlnew file+24

This diff is too big to show here.

qml/ApplicationMenus/MenuBar.qmlnew file+513

This diff is too big to show here.

qml/ApplicationMenus/MenuItem.qmlnew file+146

This diff is too big to show here.

qml/ApplicationMenus/MenuNavigator.qmlnew file+101

This diff is too big to show here.

qml/ApplicationMenus/MenuPopup.qmlnew file+510

This diff is too big to show here.

qml/ApplicationMenus/RegisteredApplicationMenuModel.qmlnew file+56

This diff is too big to show here.

qml/ApplicationMenus/qmldirnew file+1

This diff is too big to show here.

qml/CMakeLists.txt+2−2

This diff is too big to show here.

qml/Components/Background.qml+1−1

This diff is too big to show here.

qml/Components/BaseCarouselDelegate.qmldeleted−42

This diff is too big to show here.

qml/Components/BlurLayer.qml+10−40

This diff is too big to show here.

qml/Components/BrightnessControl.qmlnew file+54

This diff is too big to show here.

qml/Components/Carousel.qmldeleted−336

This diff is too big to show here.

qml/Components/Dialogs.qml+111−84

This diff is too big to show here.

qml/Components/DragHandle.qml+44−25

This diff is too big to show here.

qml/Components/EdgeBarrier.qml+4−1

This diff is too big to show here.

qml/Components/EdgeBarrierController.qml+3

This diff is too big to show here.

qml/Components/FadingLabel.qmlnew file+42

This diff is too big to show here.

qml/Components/Flickable.qmlnew file+24

This diff is too big to show here.

qml/Components/FloatingFlickable.qmlnew file+63

This diff is too big to show here.

qml/Dash/Previews/PreviewActionButton.qml → qml/Components/GridView.qmlrenamed+7−10

This diff is too big to show here.

qml/Panel/Handle.qml → qml/Components/Handle.qmlrenamed+3−2

This diff is too big to show here.

qml/Components/InputMethod.qml+14−53

This diff is too big to show here.

qml/Components/ScreenGrabber.qml → qml/Components/ItemGrabber.qmlrenamed+28−18

This diff is too big to show here.

qml/Components/WindowScreenshot.qml → qml/Components/ItemSnapshot.qmlrenamed+13−3

This diff is too big to show here.

qml/Components/KeyboardShortcutsOverlay.qmlnew file+336

This diff is too big to show here.

qml/Components/KeymapSwitcher.qmlnew file+102

This diff is too big to show here.

qml/Components/LazyImage.qml+5−1

This diff is too big to show here.

qml/Components/ListItems/Header.qmldeleted−64

This diff is too big to show here.

qml/Components/ListItems/ThinDivider.qmldeleted−27

This diff is too big to show here.

qml/Components/ListItems/graphics/ListItemDividerHorizontal@18.pngdeleted

Binary file not shown.

qml/Tutorial/Tick.qml → qml/Components/ListView.qmlrenamed+7−12

This diff is too big to show here.

qml/Components/Lockscreen.qml+76−105

This diff is too big to show here.

qml/Components/MediaServices/MediaServices.qmlnew file+386

This diff is too big to show here.

qml/Components/MediaServices/MediaServicesControls.qmlnew file+192

This diff is too big to show here.

qml/Components/MediaServices/MediaServicesHeader.qmlnew file+71

This diff is too big to show here.

qml/Components/MediaServices/VideoPlayer.qmlnew file+155

This diff is too big to show here.

qml/Components/MediaServices/VideoPlayerControls.qmlnew file+158

This diff is too big to show here.

qml/Components/ModeSwitchWarningDialog.qml+10−4

This diff is too big to show here.

qml/Components/NotificationAudio.qml+27−9

This diff is too big to show here.

qml/Components/PanelState/PanelState.qml+11−7

This diff is too big to show here.

qml/Components/PassphraseLockscreen.qml+5−4

This diff is too big to show here.

qml/Components/PhysicalKeysMapper.qml+39−5

This diff is too big to show here.

qml/Components/PinLockscreen.qml+24−2

This diff is too big to show here.

qml/Components/PinPadButton.qml+17−2

This diff is too big to show here.

qml/Components/Rating.qml+1

This diff is too big to show here.

qml/Components/RatingStyle.qml+3

This diff is too big to show here.

qml/Components/ResponsiveGridView.qmldeleted−99

This diff is too big to show here.

qml/Components/ResponsiveVerticalJournal.qmldeleted−81

This diff is too big to show here.

qml/Components/ScrollCalculator.qml+21−2

This diff is too big to show here.

qml/Dash/Previews/PreviewSharing.qml → qml/Components/SharingPicker.qmlrenamed+20−23

This diff is too big to show here.

qml/Components/ShellDialog.qml+29−4

This diff is too big to show here.

qml/Components/Showable.qml+23−10

This diff is too big to show here.

qml/Components/UbuntuShapeForItem.qmldeleted−46

This diff is too big to show here.

qml/Components/Unity8Settings.qmldeleted−50

This diff is too big to show here.

qml/Components/VirtualTouchPad.qmlnew file+406

This diff is too big to show here.

qml/Components/VolumeControl.qml+4−9

This diff is too big to show here.

qml/Components/Wallpaper.qmlnew file+96

This diff is too big to show here.

qml/Components/WallpaperResolver.qml+34−37

This diff is too big to show here.

qml/Components/WindowControlButtons.qml+52−39

This diff is too big to show here.

qml/Components/ZoomableImage.qml+2−2

This diff is too big to show here.

qml/Components/flickableUtils.jsnew file+28

This diff is too big to show here.

qml/Components/graphics/close@20.png

Binary file not shown.

qml/Components/graphics/icon_star_empty@20.png

Binary file not shown.

qml/Components/graphics/icon_star_full@20.png

Binary file not shown.

qml/Components/graphics/icon_star_half@20.png

Binary file not shown.

qml/Components/graphics/icon_star_off@20.png

Binary file not shown.

qml/Components/graphics/icon_star_on@20.png

Binary file not shown.

qml/Components/graphics/non-selected@18.png

Binary file not shown.

qml/Components/graphics/window-close.svg+164−14

This diff is too big to show here.

qml/Components/graphics/window-maximize.svg+164−12

This diff is too big to show here.

qml/Components/graphics/window-minimize.svg+164−13

This diff is too big to show here.

qml/Components/graphics/window-window.svgnew file+41

This diff is too big to show here.

qml/Dash/CardCarousel.qmldeleted−76

This diff is too big to show here.

qml/Dash/CardGrid.qmldeleted−83

This diff is too big to show here.

qml/Dash/CardHorizontalList.qmldeleted−67

This diff is too big to show here.

qml/Dash/CardTool.qmldeleted−246

This diff is too big to show here.

qml/Dash/CardVerticalJournal.qmldeleted−86

This diff is too big to show here.

qml/Dash/Dash.qmldeleted−381

This diff is too big to show here.

qml/Dash/DashBackground.qmldeleted−26

This diff is too big to show here.

qml/Dash/DashCategoryBase.qmldeleted−62

This diff is too big to show here.

qml/Dash/DashContent.qmldeleted−213

This diff is too big to show here.

qml/Dash/DashContentTabBarStyle.qmldeleted−24

This diff is too big to show here.

qml/Dash/DashNavigation.qmldeleted−117

This diff is too big to show here.

qml/Dash/DashNavigationButton.qmldeleted−233

This diff is too big to show here.

qml/Dash/DashNavigationList.qmldeleted−167

This diff is too big to show here.

qml/Dash/DashPageHeader.qmldeleted−443

This diff is too big to show here.

qml/Dash/DashRenderer.qmldeleted−60

This diff is too big to show here.

qml/Dash/GenericScopeView.qmldeleted−814

This diff is too big to show here.

qml/Dash/PreviewListView.qmldeleted−140

This diff is too big to show here.

qml/Dash/Previews/Preview.qmldeleted−115

This diff is too big to show here.

qml/Dash/Previews/PreviewActionCombo.qmldeleted−68

This diff is too big to show here.

qml/Dash/Previews/PreviewActions.qmldeleted−71

This diff is too big to show here.

qml/Dash/Previews/PreviewAudioPlayback.qmldeleted−205

This diff is too big to show here.

qml/Dash/Previews/PreviewComment.qmldeleted−83

This diff is too big to show here.

qml/Dash/Previews/PreviewCommentInput.qmldeleted−73

This diff is too big to show here.

qml/Dash/Previews/PreviewExpandable.qmldeleted−105

This diff is too big to show here.

qml/Dash/Previews/PreviewHeader.qmldeleted−140

This diff is too big to show here.

qml/Dash/Previews/PreviewIconActions.qmldeleted−72

This diff is too big to show here.

qml/Dash/Previews/PreviewImageGallery.qmldeleted−147

This diff is too big to show here.

qml/Dash/Previews/PreviewOverlay.qmldeleted−166

This diff is too big to show here.

qml/Dash/Previews/PreviewPayments.qmldeleted−83

This diff is too big to show here.

qml/Dash/Previews/PreviewProgress.qmldeleted−71

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingDisplay.qmldeleted−67

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingEdit.qmldeleted−80

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingInput.qmldeleted−181

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingSingleDisplay.qmldeleted−70

This diff is too big to show here.

qml/Dash/Previews/PreviewTable.qmldeleted−85

This diff is too big to show here.

qml/Dash/Previews/PreviewTextSummary.qmldeleted−73

This diff is too big to show here.

qml/Dash/Previews/PreviewVideoPlayback.qmldeleted−87

This diff is too big to show here.

qml/Dash/Previews/PreviewWidget.qmldeleted−57

This diff is too big to show here.

qml/Dash/Previews/PreviewWidgetFactory.qmldeleted−92

This diff is too big to show here.

qml/Dash/Previews/PreviewZoomableImage.qmldeleted−97

This diff is too big to show here.

qml/Dash/Previews/graphics/music_progress_bg.pngdeleted

Binary file not shown.

qml/Dash/ScopeListView.qmldeleted−26

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSetting.qmldeleted−46

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSettingBoolean.qmldeleted−63

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSettingList.qmldeleted−50

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSettingString.qmldeleted−89

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSettingsWidgetFactory.qmldeleted−61

This diff is too big to show here.

qml/Dash/ScopeSettingsPage.qmldeleted−72

This diff is too big to show here.

qml/Dash/ScopesList.qmldeleted−134

This diff is too big to show here.

qml/Dash/ScopesListCategory.qmldeleted−180

This diff is too big to show here.

qml/Dash/ScopesListCategoryItem.qmldeleted−108

This diff is too big to show here.

qml/Dash/graphics/dark_background.jpgdeleted

Binary file not shown.

qml/Dash/graphics/dash_divider_top_darkgrad@27.pngdeleted

Binary file not shown.

qml/Dash/graphics/dash_divider_top_lightgrad@27.pngdeleted

Binary file not shown.

qml/Dash/graphics/header_handlearrow2@27.pngdeleted

Binary file not shown.

qml/Dash/graphics/header_handlearrow@27.pngdeleted

Binary file not shown.

qml/Dash/graphics/icon_clear@20.pngdeleted

Binary file not shown.

qml/Dash/graphics/icon_search_active@20.pngdeleted

Binary file not shown.

qml/Dash/graphics/icon_search_inactive@20.pngdeleted

Binary file not shown.

qml/Dash/graphics/navigation_shadow@18.pngdeleted

Binary file not shown.

qml/Dash/graphics/navigation_shadow_light@18.pngdeleted

Binary file not shown.

qml/Dash/graphics/overview_hint@27.pngdeleted

Binary file not shown.

qml/Dash/graphics/pagination_dot_off@30.pngdeleted

Binary file not shown.

qml/Dash/graphics/pagination_dot_on@30.pngdeleted

Binary file not shown.

qml/Dash/graphics/paper_landscape@27.pngdeleted

Binary file not shown.

qml/Dash/graphics/paper_portrait@27.pngdeleted

Binary file not shown.

qml/Dash/graphics/pixel.pngdeleted

Binary file not shown.

qml/Dash/graphics/play_button@18.pngdeleted

Binary file not shown.

qml/Dash/graphics/play_button_active@18.pngdeleted

Binary file not shown.

qml/Dash/graphics/play_button_active_big@20.pngdeleted

Binary file not shown.

qml/Dash/graphics/play_button_big@20.pngdeleted

Binary file not shown.

qml/Dash/graphics/tabbarchevron@27.pngdeleted

Binary file not shown.

qml/Dash/graphics/tablet/icon_close_preview@20.pngdeleted

Binary file not shown.

qml/Dash/graphics/tooltip_arrow@27.pngdeleted

Binary file not shown.

qml/DeviceConfiguration.qml+65−20

This diff is too big to show here.

qml/DisabledScreenNotice.qml+54−22

This diff is too big to show here.

qml/Greeter/ButtonPrompt.qmlnew file+51

This diff is too big to show here.

qml/Greeter/Circle.qmlnew file+57

This diff is too big to show here.

qml/Greeter/Clock.qml−2

This diff is too big to show here.

qml/Greeter/CoverPage.qml+74−20

This diff is too big to show here.

qml/Components/DelayedLockscreen.qml → qml/Greeter/DelayedLockscreen.qmlrenamed+6−14

This diff is too big to show here.

qml/Greeter/FullLightDMImpl.qmlnew file+31

This diff is too big to show here.

qml/Greeter/Greeter.qml+290−117

This diff is too big to show here.

qml/Greeter/GreeterPrompt.qmlnew file+127

This diff is too big to show here.

qml/Greeter/GreeterView.qmlnew file+534

This diff is too big to show here.

qml/Greeter/Infographics.qml+46−24

This diff is too big to show here.

qml/Greeter/IntegratedLightDMImpl.qml+4−2

This diff is too big to show here.

qml/Greeter/LightDM.qml → qml/Greeter/LightDMService.qmlrenamed+16−3

This diff is too big to show here.

qml/Dash/Previews/PreviewMediaToolbar.qml → qml/Greeter/LoginAreaContainer.qmlrenamed+15−13

This diff is too big to show here.

qml/Greeter/LoginList.qml+147−154

This diff is too big to show here.

qml/Greeter/NarrowView.qmldeleted−171

This diff is too big to show here.

qml/Greeter/PinPrompt.qmlnew file+184

This diff is too big to show here.

qml/Greeter/PromptList.qmlnew file+151

This diff is too big to show here.

qml/Greeter/SessionIcon.qmlnew file+47

This diff is too big to show here.

qml/Greeter/SessionsList.qmlnew file+205

This diff is too big to show here.

qml/Greeter/ShimGreeter.qml+2

This diff is too big to show here.

qml/Greeter/TextPrompt.qmlnew file+198

This diff is too big to show here.

qml/Greeter/WideView.qmldeleted−135

This diff is too big to show here.

qml/Greeter/graphics/dot_empty.png

Binary file not shown.

qml/Greeter/graphics/dot_filled.png

Binary file not shown.

qml/Greeter/graphics/dot_pointer.png

Binary file not shown.

qml/Greeter/graphics/icon_arrow.png

Binary file not shown.

qml/Greeter/graphics/infographic_circle_back.pngdeleted

Binary file not shown.

qml/Greeter/graphics/session_icons/gnome_badge.pngnew file

Binary file not shown.

qml/Greeter/graphics/session_icons/kde_badge.pngnew file

Binary file not shown.

qml/Greeter/graphics/session_icons/recovery_console_badge.pngnew file

Binary file not shown.

qml/Greeter/graphics/session_icons/ubuntu_badge.pngnew file

Binary file not shown.

qml/Greeter/graphics/session_icons/unknown_badge.pngnew file

Binary file not shown.

qml/Greeter/qmldirnew file+1

This diff is too big to show here.

qml/Launcher/BackgroundBlur.qmlnew file+81

This diff is too big to show here.

qml/Launcher/Drawer.qmlnew file+413

This diff is too big to show here.

qml/Launcher/DrawerGridView.qmlnew file+85

This diff is too big to show here.

qml/Launcher/Launcher.qml+391−81

This diff is too big to show here.

qml/Launcher/LauncherDelegate.qml+60−33

This diff is too big to show here.

qml/Launcher/LauncherPanel.qml+390−126

This diff is too big to show here.

qml/Dash/PullToRefreshScopeStyle.qml → qml/Launcher/PullToRefreshScopeStyle.qmlrenamed+1

This diff is too big to show here.

qml/Launcher/Tooltip.qmlnew file+72

This diff is too big to show here.

qml/Launcher/graphics/divider-line.png

Binary file not shown.

qml/Launcher/graphics/focused_app_arrow@30.png

Binary file not shown.

qml/Launcher/graphics/home.svgnew file+243

This diff is too big to show here.

qml/Launcher/graphics/home@18.pngdeleted

Binary file not shown.

qml/Launcher/graphics/quicklist_tooltip@30.png

Binary file not shown.

qml/Notifications/Notification.qml+168−140

This diff is too big to show here.

qml/Notifications/NotificationButton.qmlnew file+73

This diff is too big to show here.

qml/Notifications/NotificationMenuItemFactory.qml+5−10

This diff is too big to show here.

qml/Notifications/Notifications.qml+18−18

This diff is too big to show here.

qml/Notifications/OptionToggle.qml+12−10

This diff is too big to show here.

qml/Notifications/ShapedIcon.qml+2

This diff is too big to show here.

qml/Notifications/SwipeToAct.qml+20−20

This diff is too big to show here.

qml/Notifications/grip-large.svgdeleted−150

This diff is too big to show here.

qml/OrientedShell.qml+119−29

This diff is too big to show here.

qml/Panel/ActiveCallHint.qml+3

This diff is too big to show here.

qml/Panel/FakePanelMenu.qmlnew file+26

This diff is too big to show here.

qml/Panel/IndicatorPage.qmldeleted−187

This diff is too big to show here.

qml/Panel/IndicatorItem.qml → qml/Panel/Indicators/IndicatorItem.qmlrenamed+73−17

This diff is too big to show here.

qml/Panel/Indicators/MenuItemFactory.qml → qml/Panel/Indicators/IndicatorMenuItemFactory.qmlrenamed+220−89

This diff is too big to show here.

qml/Panel/Indicators/IndicatorsLight.qml+185−12

This diff is too big to show here.

qml/Panel/Indicators/MessageMenuItemFactory.qml+1−5

This diff is too big to show here.

qml/Panel/Indicators/ModemInfoItem.qmldeleted−111

This diff is too big to show here.

qml/Panel/Indicators/RoamingIndication.qmldeleted−40

This diff is too big to show here.

qml/Panel/Indicators/client/IndicatorRepresentation.qml+45−28

This diff is too big to show here.

qml/Panel/Indicators/client/IndicatorsClient.qml+9−3

This diff is too big to show here.

qml/Panel/Indicators/client/IndicatorsList.qml+19−17

This diff is too big to show here.

qml/Panel/Indicators/client/IndicatorsTree.qml+6−8

This diff is too big to show here.

qml/Panel/MenuContent.qml+13−13

This diff is too big to show here.

qml/Panel/Panel.qml+389−107

This diff is too big to show here.

qml/Panel/IndicatorsBar.qml → qml/Panel/PanelBar.qmlrenamed+87−36

This diff is too big to show here.

qml/Panel/IndicatorItemRow.qml → qml/Panel/PanelItemRow.qmlrenamed+65−92

This diff is too big to show here.

qml/Panel/IndicatorsMenu.qml → qml/Panel/PanelMenu.qmlrenamed+118−60

This diff is too big to show here.

qml/Panel/PanelMenuPage.qmlnew file+226

This diff is too big to show here.

qml/Panel/graphics/Battery@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/Bluetooth@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/Clock@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/Location@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/Messages@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/Network@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/Sound@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/Sync@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/System@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/Time@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/VerticalDivider@18.pngdeleted

Binary file not shown.

qml/Panel/graphics/handle@12.pngdeleted

Binary file not shown.

qml/Panel/graphics/handle@12.scideleted−5

This diff is too big to show here.

qml/Panel/graphics/rectangular_dropshadow@30.png

Binary file not shown.

qml/Panel/graphics/search@12.pngdeleted

Binary file not shown.

qml/Panel/graphics/time_and_date@18.pngdeleted

Binary file not shown.

qml/Rotation/HalfLoopRotationAnimation.qml+2−1

This diff is too big to show here.

qml/Rotation/ImmediateRotationAction.qml+11−22

This diff is too big to show here.

qml/Rotation/NinetyRotationAnimation.qml+14−16

This diff is too big to show here.

qml/Rotation/RotationStates.qml+27−16

This diff is too big to show here.

qml/Rotation/UpdateShellTransformations.qmlnew file+42

This diff is too big to show here.

qml/ScopeTool.qmldeleted−173

This diff is too big to show here.

qml/Shell.qml+554−303

This diff is too big to show here.

qml/Stages/ApplicationWindow.qml → qml/Stage/ApplicationWindow.qmlrenamed+179−85

This diff is too big to show here.

qml/Stage/ChildWindow.qmlnew file+203

This diff is too big to show here.

qml/Stage/ChildWindowRepeater.qmlnew file+39

This diff is too big to show here.

qml/Stage/ChildWindowTree.qmlnew file+138

This diff is too big to show here.

qml/Stage/DecoratedWindow.qmlnew file+319

This diff is too big to show here.

qml/Stage/FakeMaximizeDelegate.qmlnew file+233

This diff is too big to show here.

qml/Stages/MainViewStyle.qml → qml/Stage/MainViewStyle.qmlrenamed

The content is the same.

qml/Stage/MoveHandler.qmlnew file+201

This diff is too big to show here.

qml/Stages/OrientationChangeAnimation.qml → qml/Stage/OrientationChangeAnimation.qmlrenamed+30−6

This diff is too big to show here.

qml/Stage/PromptSurfaceAnimations.qmlnew file+80

This diff is too big to show here.

qml/Tutorial/Arrow.qml → qml/Stage/ResizeGrip.qmlrenamed+18−28

This diff is too big to show here.

qml/Stage/SideStage.qmlnew file+121

This diff is too big to show here.

qml/Stages/Splash.qml → qml/Stage/Splash.qmlrenamed+22−29

This diff is too big to show here.

qml/Stage/Spread/BezierCurve.qmlnew file+45

This diff is too big to show here.

qml/Stage/Spread/KeySpline.jsnew file+66

This diff is too big to show here.

qml/Stage/Spread/MathUtils.jsnew file+95

This diff is too big to show here.

qml/Stage/Spread/OpacityMask.qmlnew file+82

This diff is too big to show here.

qml/Stage/Spread/Spread.qmlnew file+173

This diff is too big to show here.

qml/Stage/Spread/SpreadDelegateInputArea.qmlnew file+189

This diff is too big to show here.

qml/Stage/Spread/SpreadMaths.qmlnew file+78

This diff is too big to show here.

qml/Stage/Spread/StagedRightEdgeMaths.qmlnew file+174

This diff is too big to show here.

qml/Stage/Spread/WindowedRightEdgeMaths.qmlnew file+96

This diff is too big to show here.

qml/Stage/Spread/cubic-bezier.jsnew file+39

This diff is too big to show here.

qml/Stage/Stage.qmlnew file+2241

This diff is too big to show here.

qml/Stage/StageMaths.qmlnew file+93

This diff is too big to show here.

qml/Stage/StagedFullscreenPolicy.qmlnew file+50

This diff is too big to show here.

qml/Stage/SurfaceContainer.qmlnew file+108

This diff is too big to show here.

qml/Stage/TabletSideStageTouchGesture.qmlnew file+157

This diff is too big to show here.

qml/Stage/WindowControlsOverlay.qmlnew file+254

This diff is too big to show here.

qml/Stage/WindowDecoration.qmlnew file+163

This diff is too big to show here.

qml/Stage/WindowInfoItem.qmlnew file+69

This diff is too big to show here.

qml/Stages/WindowResizeArea.qml → qml/Stage/WindowResizeArea.qmlrenamed+112−75

This diff is too big to show here.

qml/Stage/WindowStateSaver.qmlnew file+64

This diff is too big to show here.

qml/Stage/WindowedFullscreenPolicy.qmlnew file+31

This diff is too big to show here.

qml/Stage/graphics/PageHeaderBaseDividerBottom@18.pngnew file

Binary file not shown.

qml/Stage/graphics/PageHeaderBaseDividerLight@18.pngnew file

Binary file not shown.

qml/Stages/graphics/PageHeaderBaseDividerLight@18.sci → qml/Stage/graphics/PageHeaderBaseDividerLight@18.scirenamed

The content is the same.

qml/Stage/graphics/arrows-centre.pngnew file

Binary file not shown.

qml/Stage/graphics/arrows.pngnew file

Binary file not shown.

qml/Stage/graphics/sidestage_drag.svgnew file+207

This diff is too big to show here.

qml/Stage/graphics/sidestage_handle@20.pngnew file

Binary file not shown.

qml/Stages/graphics/sidestage_handle@20.sci → qml/Stage/graphics/sidestage_handle@20.scirenamed

The content is the same.

qml/Stage/graphics/sidestage_open.svgnew file+181

This diff is too big to show here.

qml/Stages/graphics/window-close.svg → qml/Stage/graphics/window-close.svgrenamed

The content is the same.

qml/Stages/AbstractStage.qmldeleted−63

This diff is too big to show here.

qml/Stages/Animations/BaseSessionAnimation.qmldeleted−96

This diff is too big to show here.

qml/Stages/Animations/SwipeFromBottomAnimation.qmldeleted−53

This diff is too big to show here.

qml/Stages/DecoratedWindow.qmldeleted−98

This diff is too big to show here.

qml/Stages/DesktopSpread.qmldeleted−523

This diff is too big to show here.

qml/Stages/DesktopSpreadDelegate.qmldeleted−111

This diff is too big to show here.

qml/Stages/DesktopStage.qmldeleted−517

This diff is too big to show here.

qml/Stages/PhoneStage.qmldeleted−648

This diff is too big to show here.

qml/Stages/SessionContainer.qmldeleted−178

This diff is too big to show here.

qml/Stages/SpreadDelegate.qmldeleted−407

This diff is too big to show here.

qml/Stages/SpreadMaths.qmldeleted−164

This diff is too big to show here.

qml/Stages/SurfaceContainer.qmldeleted−152

This diff is too big to show here.

qml/Stages/TabletStage.qmldeleted−802

This diff is too big to show here.

qml/Stages/TransformedSpreadDelegate.qmldeleted−391

This diff is too big to show here.

qml/Stages/TransformedTabletSpreadDelegate.qmldeleted−403

This diff is too big to show here.

qml/Stages/WindowDecoration.qmldeleted−104

This diff is too big to show here.

qml/Stages/graphics/PageHeaderBaseDividerBottom@18.pngdeleted

Binary file not shown.

qml/Stages/graphics/PageHeaderBaseDividerLight@18.pngdeleted

Binary file not shown.

qml/Stages/graphics/dropshadow2gu@30.pngdeleted

Binary file not shown.

qml/Stages/graphics/sidestage_handle@20.pngdeleted

Binary file not shown.

qml/Tutorial/InactivityTimer.qmlnew file+78

This diff is too big to show here.

qml/Tutorial/Slider.qmldeleted−123

This diff is too big to show here.

qml/Tutorial/Tutorial.qml+43−16

This diff is too big to show here.

qml/Tutorial/TutorialBottom.qmldeleted−104

This diff is too big to show here.

qml/Tutorial/TutorialContent.qml+168−61

This diff is too big to show here.

qml/Tutorial/TutorialLeft.qml+21−68

This diff is too big to show here.

qml/Tutorial/TutorialLeftLong.qmlnew file+56

This diff is too big to show here.

qml/Tutorial/TutorialPage.qml+63−187

This diff is too big to show here.

qml/Tutorial/TutorialRight.qml+30−192

This diff is too big to show here.

qml/Tutorial/TutorialTop.qmlnew file+60

This diff is too big to show here.

qml/Tutorial/graphics/arrow.svgnew file+19

This diff is too big to show here.

qml/Tutorial/graphics/background1.pngnew file

Binary file not shown.

qml/Tutorial/graphics/background2.pngnew file

Binary file not shown.

qml/Tutorial/graphics/camera.pngdeleted

Binary file not shown.

qml/Tutorial/graphics/chevron.pngdeleted

Binary file not shown.

qml/Tutorial/graphics/dialer.pngdeleted

Binary file not shown.

qml/Tutorial/graphics/facebook.pngdeleted

Binary file not shown.

qml/Tutorial/graphics/gallery.pngdeleted

Binary file not shown.

qml/Tutorial/graphics/tick.pngdeleted

Binary file not shown.

qml/Wizard/CheckableSetting.qml+11−3

This diff is too big to show here.

qml/Wizard/Components/InputMethod.qml+9−9

This diff is too big to show here.

qml/Wizard/Page.qml+277−45

This diff is too big to show here.

qml/Wizard/Pages.qml+157−39

This diff is too big to show here.

qml/Wizard/Pages/10-welcome-update.qmlnew file+137

This diff is too big to show here.

qml/Wizard/Pages/10-welcome.qml+146−48

This diff is too big to show here.

qml/Wizard/Pages/11-changelog.qmlnew file+95

This diff is too big to show here.

qml/Wizard/Pages/20-keyboard.qmlnew file+161

This diff is too big to show here.

qml/Wizard/Pages/20-sim.qmldeleted−77

This diff is too big to show here.

qml/Wizard/Pages/30-passwd-type.qmldeleted−135

This diff is too big to show here.

qml/Wizard/Pages/30-wifi.qmlnew file+219

This diff is too big to show here.

qml/Wizard/Pages/40-wifi.qmldeleted−219

This diff is too big to show here.

qml/Wizard/Pages/50-location.qmldeleted−150

This diff is too big to show here.

qml/Wizard/Pages/50-timezone.qmlnew file+278

This diff is too big to show here.

qml/Wizard/Pages/60-reporting.qml → qml/Wizard/Pages/60-account.qmlrenamed+31−19

This diff is too big to show here.

qml/Wizard/Pages/70-passwd-type.qmlnew file+168

This diff is too big to show here.

qml/Wizard/Pages/78-firmware-update.qml.disablednew file+246

This diff is too big to show here.

qml/Wizard/Pages/79-system-update.qmlnew file+148

This diff is too big to show here.

qml/Wizard/Pages/80-finished.qml+96−16

This diff is too big to show here.

qml/Wizard/Pages/data/Desktop_header_bkg.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/Desktop_splash_screen_bkg.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/Phone_header_bkg.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/Phone_splash_screen_bkg.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/Tick@30.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/meet_ubuntu_simcard@30.pngdeleted

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/map.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/pin.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-1.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-10.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-11.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-2.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-3.5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-3.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-4.5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-4.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-6.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-7.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-8.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-9.5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_-9.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_0.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_1.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_10.5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_10.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_11.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_12.75.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_12.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_13.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_2.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_3.5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_3.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_4.5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_4.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_5.5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_5.75.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_6.5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_6.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_7.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_8.5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_8.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_9.5.pngnew file

Binary file not shown.

qml/Wizard/Pages/data/timezonemap/timezone_9.pngnew file

Binary file not shown.

qml/Wizard/Pages/here-terms.qmldeleted−121

This diff is too big to show here.

qml/Wizard/Pages/passwd-confirm.qml → qml/Wizard/Pages/passcode-confirm.qmlrenamed+15−32

This diff is too big to show here.

qml/Wizard/Pages/passcode-desktop.qmlnew file+159

This diff is too big to show here.

qml/Wizard/Pages/passwd-set.qml → qml/Wizard/Pages/passcode-set.qmlrenamed+15−31

This diff is too big to show here.

qml/Wizard/Pages/password-set.qmlnew file+158

This diff is too big to show here.

qml/Wizard/Pages/sim.qmlnew file+108

This diff is too big to show here.

qml/Wizard/PasswordMeter.qmlnew file+108

This diff is too big to show here.

qml/Wizard/StackButton.qml+7−12

This diff is too big to show here.

qml/Wizard/Wizard.qml+11−13

This diff is too big to show here.

qml/Wizard/WizardItemSelector.qmlnew file+129

This diff is too big to show here.

qml/Components/Header.qml → qml/Wizard/WizardTextField.qmlrenamed+6−8

This diff is too big to show here.

qml/graphics/12_10_background_wide@12.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/browser@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/calendar@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/camera@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/contacts-app@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/dash.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/dialer-app@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/evernote@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/facebook@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/gallery@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/gmail@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/libreoffice@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/map@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/messages-app@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/notepad@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/pinterest@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/soundcloud@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/system-settings@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/twitter@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/weather@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/wikipedia@18.pngdeleted

Binary file not shown.

qml/graphics/applicationIcons/youtube@18.pngdeleted

Binary file not shown.

qml/graphics/avatars/amanda@12.pngdeleted

Binary file not shown.

qml/graphics/avatars/anna_olsson@12.pngdeleted

Binary file not shown.

qml/graphics/avatars/funky@12.pngdeleted

Binary file not shown.

qml/graphics/clock@18.pngdeleted

Binary file not shown.

qml/graphics/dropshadow2gu@30.pngnew file

Binary file not shown.

qml/Stages/graphics/dropshadow2gu@30.sci → qml/graphics/dropshadow2gu@30.scirenamed

The content is the same.

qml/graphics/dropshadow_left@20.png

Binary file not shown.

qml/graphics/dropshadow_right@20.png

Binary file not shown.

qml/graphics/phone_background.jpgdeleted

Binary file not shown.

qml/graphics/tablet_background.jpgdeleted

Binary file not shown.

run.shdeleted−70

This diff is too big to show here.

run_on_device.shdeleted−164

This diff is too big to show here.

src/ApplicationArguments.h+5

This diff is too big to show here.

src/CMakeLists.txt+29−16

This diff is too big to show here.

src/CachingNetworkManagerFactory.cpp+2−2

This diff is too big to show here.

src/CachingNetworkManagerFactory.h+3−2

This diff is too big to show here.

src/Dash/CMakeLists.txtdeleted−28

This diff is too big to show here.

src/Dash/main.cppdeleted−121

This diff is too big to show here.

src/DebuggingController.cppnew file+92

This diff is too big to show here.

src/DebuggingController.hnew file+57

This diff is too big to show here.

src/MouseTouchAdaptor.cpp+254−24

This diff is too big to show here.

src/MouseTouchAdaptor.h+13−3

This diff is too big to show here.

src/Panel/CMakeLists.txtdeleted−3

This diff is too big to show here.

src/Panel/Indicators/CMakeLists.txtdeleted−1

This diff is too big to show here.

src/SecondaryWindow.cpp+9

This diff is too big to show here.

src/ShellApplication.cpp+44−11

This diff is too big to show here.

src/ShellApplication.h+13−7

This diff is too big to show here.

src/ShellView.cpp+28−2

This diff is too big to show here.

src/UnityCommandLineParser.cpp+6

This diff is too big to show here.

src/UnityCommandLineParser.h+8

This diff is too big to show here.

tools/unix-signal-handler.cpp → src/UnixSignalHandler.cpprenamed+4−6

This diff is too big to show here.

tools/unix-signal-handler.h → src/UnixSignalHandler.hrenamed

The content is the same.

src/libunity8-private/CMakeLists.txt+1−1

This diff is too big to show here.

src/libunity8-private/abstractdbusservicemonitor.h+1−1

This diff is too big to show here.

src/main.cpp+33−3

This diff is too big to show here.

src/qmldebuggerutils.hnew file+33

This diff is too big to show here.

tests/CMakeLists.txt+43−24

This diff is too big to show here.

tests/autopilot/unity8/dash.pydeleted−265

This diff is too big to show here.

tests/autopilot/unity8/fixture_setup.py+1−1

This diff is too big to show here.

tests/autopilot/unity8/greeter/__init__.py+1−1

This diff is too big to show here.

tests/autopilot/unity8/greeter/tests/test_args.py−5

This diff is too big to show here.

tests/autopilot/unity8/settings_wizard/__init__.pydeleted−555

This diff is too big to show here.

tests/autopilot/unity8/settings_wizard/fixture_setup.pydeleted−58

This diff is too big to show here.

tests/autopilot/unity8/settings_wizard/ofono_helper.pydeleted−116

This diff is too big to show here.

tests/autopilot/unity8/settings_wizard/tests/__init__.pydeleted

No changes to the content.

tests/autopilot/unity8/settings_wizard/tests/test_settings_wizard.pydeleted−99

This diff is too big to show here.

tests/autopilot/unity8/shell/__init__.py+2

This diff is too big to show here.

tests/autopilot/unity8/shell/emulators.py−2

This diff is too big to show here.

tests/autopilot/unity8/shell/fixture_setup.py+1−27

This diff is too big to show here.

tests/autopilot/unity8/shell/tests/__init__.py+5−2

This diff is too big to show here.

tests/autopilot/unity8/shell/tests/test_helpers.py−124

This diff is too big to show here.

tests/autopilot/unity8/shell/tests/test_notifications.py+10−10

This diff is too big to show here.

tests/autopilot/unity8/shell/tests/test_rotation.py+3−3

This diff is too big to show here.

tests/autopilot/unity8/shell/tests/test_tutorial.pydeleted−57

This diff is too big to show here.

tests/autopilot/unity8/tutorial.pydeleted−73

This diff is too big to show here.

tests/copyright/check_copyright.sh+35−4

This diff is too big to show here.

tests/data/unity/backgrounds/20x30.pngnew file

Binary file not shown.

tests/data/unity/backgrounds/black.pngnew file

Binary file not shown.

tests/data/unity/backgrounds/blue.png

Binary file not shown.

tests/data/unity/backgrounds/red.png

Binary file not shown.

tests/graphics/applicationIcons/browser@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/calendar@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/camera@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/contacts-app@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/dash@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/dialer-app@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/evernote@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/facebook@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/gallery@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/gmail@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/libreoffice@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/map@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/messages-app@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/notepad@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/pinterest@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/soundcloud@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/system-settings@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/twitter@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/weather@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/wikipedia@18.pngnew file

Binary file not shown.

tests/graphics/applicationIcons/youtube@18.pngnew file

Binary file not shown.

tests/graphics/avatars/amanda@12.pngnew file

Binary file not shown.

tests/graphics/avatars/anna_olsson@12.pngnew file

Binary file not shown.

tests/graphics/avatars/funky@12.pngnew file

Binary file not shown.

tests/graphics/clock@18.pngnew file

Binary file not shown.

tests/graphics/screenshots/gallery@12.pngnew file

Binary file not shown.

tests/imports/CMakeLists.txt+1−1

This diff is too big to show here.

tests/imports/check_imports.py+58

This diff is too big to show here.

tests/libs/CMakeLists.txtdeleted−1

This diff is too big to show here.

tests/libs/UbuntuGestures/CMakeLists.txtdeleted−16

This diff is too big to show here.

tests/libs/UbuntuGestures/tst_TouchRegistry.cppdeleted−915

This diff is too big to show here.

tests/mocks/AccountsService/AccountsService.cpp+85−25

This diff is too big to show here.

tests/mocks/AccountsService/AccountsService.h+51−30

This diff is too big to show here.

tests/mocks/AccountsService/AccountsService.qmltypesdeleted−36

This diff is too big to show here.

tests/mocks/AccountsService/CMakeLists.txt+15−2

This diff is too big to show here.

tests/mocks/Biometryd/CMakeLists.txtnew file+14

This diff is too big to show here.

libs/UbuntuGestures/TouchOwnershipEvent.cpp → tests/mocks/Biometryd/MockBiometryd.cpprenamed+20−12

This diff is too big to show here.

tests/mocks/Biometryd/MockBiometryd.hnew file+50

This diff is too big to show here.

plugins/Ubuntu/Payments/plugin.cpp → tests/mocks/Biometryd/MockDevice.cpprenamed+10−9

This diff is too big to show here.

tests/mocks/IntegratedLightDM/MockUsersModel.h → tests/mocks/Biometryd/MockDevice.hrenamed+16−13

This diff is too big to show here.

tests/mocks/Biometryd/MockIdentifier.cppnew file+28

This diff is too big to show here.

plugins/Ubuntu/SystemImage/SystemImage.h → tests/mocks/Biometryd/MockIdentifier.hrenamed+11−9

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/MockSystemImage.cpp → tests/mocks/Biometryd/MockObserver.cpprenamed+3−8

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/MockSystemImage.h → tests/mocks/Biometryd/MockObserver.hrenamed+11−10

This diff is too big to show here.

tests/mocks/Biometryd/MockOperation.cppnew file+56

This diff is too big to show here.

plugins/ScreenGrabber/screengrabber.h → tests/mocks/Biometryd/MockOperation.hrenamed+18−20

This diff is too big to show here.

plugins/Ubuntu/SystemImage/plugin.cpp → tests/mocks/Biometryd/plugin.cpprenamed+14−7

This diff is too big to show here.

plugins/Ubuntu/Payments/plugin.h → tests/mocks/Biometryd/plugin.hrenamed+4−4

This diff is too big to show here.

tests/mocks/Biometryd/qmldirnew file+3

This diff is too big to show here.

tests/mocks/CMakeLists.txt+19−16

This diff is too big to show here.

tests/mocks/Cursor/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/Cursor/Cursor.qml+13−1

This diff is too big to show here.

tests/mocks/Cursor/qmldir+1−1

This diff is too big to show here.

tests/mocks/GSettings.1.0/CMakeLists.txt+1−2

This diff is too big to show here.

tests/mocks/GSettings.1.0/GSettings.qmltypesdeleted−42

This diff is too big to show here.

tests/mocks/GSettings.1.0/fake_gsettings.cpp+243−26

This diff is too big to show here.

tests/mocks/GSettings.1.0/fake_gsettings.h+79−18

This diff is too big to show here.

tests/mocks/IntegratedLightDM/CMakeLists.txtdeleted−49

This diff is too big to show here.

tests/mocks/IntegratedLightDM/IntegratedLightDM.qmltypesdeleted−269

This diff is too big to show here.

tests/mocks/IntegratedLightDM/MockGreeter.hdeleted−37

This diff is too big to show here.

tests/mocks/IntegratedLightDM/MockUsersModel.cppdeleted−39

This diff is too big to show here.

tests/mocks/IntegratedLightDM/liblightdm/CMakeLists.txtdeleted−18

This diff is too big to show here.

tests/mocks/IntegratedLightDM/liblightdm/Greeter.cppdeleted−199

This diff is too big to show here.

tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cppdeleted−134

This diff is too big to show here.

tests/mocks/IntegratedLightDM/plugin.cppdeleted−68

This diff is too big to show here.

tests/mocks/IntegratedLightDM/qmldirdeleted−3

This diff is too big to show here.

tests/mocks/LightDMController/CMakeLists.txtnew file+14

This diff is too big to show here.

plugins/Unity/DashCommunicator/plugin.cpp → tests/mocks/LightDMController/plugin.cpprenamed+14−11

This diff is too big to show here.

tests/mocks/Ubuntu/Payments/plugin.h → tests/mocks/LightDMController/plugin.hrenamed+4−6

This diff is too big to show here.

tests/mocks/LightDMController/qmldirnew file+2

This diff is too big to show here.

tests/mocks/Lights/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/Lights/Lights.h+1−1

This diff is too big to show here.

tests/mocks/Lights/Lights.qmltypesdeleted−45

This diff is too big to show here.

tests/mocks/MeeGo/QOfono/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/MeeGo/QOfono/MockOfonoSimManager.qml+1

This diff is too big to show here.

tests/mocks/MeeGo/QOfono/QOfono.qmltypesdeleted−30

This diff is too big to show here.

tests/mocks/Powerd/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/Powerd/Powerd.h+2−2

This diff is too big to show here.

tests/mocks/Powerd/Powerd.qmltypesdeleted−39

This diff is too big to show here.

tests/mocks/QMenuModel/CMakeLists.txt+1−2

This diff is too big to show here.

tests/mocks/QMenuModel/QDBusActionGroup.qml+5−5

This diff is too big to show here.

tests/mocks/QMenuModel/QMenuModel.qmltypesdeleted−111

This diff is too big to show here.

tests/mocks/QMenuModel/dbus-enums.h+2−3

This diff is too big to show here.

tests/mocks/QMenuModel/unitymenumodel.cpp+78−13

This diff is too big to show here.

tests/mocks/QMenuModel/unitymenumodel.h+12−1

This diff is too big to show here.

tests/mocks/QtMultimedia/CMakeLists.txt+9−2

This diff is too big to show here.

tests/mocks/QtMultimedia/QtMultimedia.qmltypesdeleted−62

This diff is too big to show here.

tests/mocks/QtMultimedia/VideoSurface.qmlnew file+111

This diff is too big to show here.

tests/mocks/QtMultimedia/audio.cppdeleted−117

This diff is too big to show here.

tests/mocks/QtMultimedia/audio.hdeleted−90

This diff is too big to show here.

tests/mocks/QtMultimedia/declarativeplaylist.cppnew file+73

This diff is too big to show here.

tests/mocks/QtMultimedia/declarativeplaylist.hnew file+54

This diff is too big to show here.

tests/mocks/QtMultimedia/mediaplayer.cppnew file+319

This diff is too big to show here.

tests/mocks/QtMultimedia/mediaplayer.hnew file+224

This diff is too big to show here.

tests/mocks/QtMultimedia/plugin.cpp+9−3

This diff is too big to show here.

tests/mocks/QtMultimedia/videooutput.cppnew file+127

This diff is too big to show here.

tests/mocks/QtMultimedia/videooutput.hnew file+52

This diff is too big to show here.

tests/mocks/SessionBroadcast/CMakeLists.txtnew file+8

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/plugin.cpp → tests/mocks/SessionBroadcast/SessionBroadcast.cpprenamed+12−12

This diff is too big to show here.

tests/mocks/SessionBroadcast/SessionBroadcast.hnew file+39

This diff is too big to show here.

tests/mocks/IntegratedLightDM/MockGreeter.cpp → tests/mocks/SessionBroadcast/plugin.cpprenamed+10−14

This diff is too big to show here.

tests/mocks/Unity/fake_unity_plugin.h → tests/mocks/SessionBroadcast/plugin.hrenamed+5−7

This diff is too big to show here.

tests/mocks/SessionBroadcast/qmldirnew file+2

This diff is too big to show here.

tests/mocks/UInput/CMakeLists.txtnew file+7

This diff is too big to show here.

tests/mocks/UInput/mockuinput.cppnew file+73

This diff is too big to show here.

tests/mocks/UInput/mockuinput.hnew file+63

This diff is too big to show here.

tests/mocks/UInput/plugin.cppnew file+26

This diff is too big to show here.

tests/mocks/IntegratedLightDM/plugin.h → tests/mocks/UInput/plugin.hrenamed+4−4

This diff is too big to show here.

tests/mocks/UInput/qmldirnew file+2

This diff is too big to show here.

tests/mocks/Ubuntu/CMakeLists.txt−2

This diff is too big to show here.

tests/mocks/Ubuntu/Connectivity/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/Ubuntu/Connectivity/networking-status.cpp+7−1

This diff is too big to show here.

tests/mocks/Ubuntu/Connectivity/networking-status.h+7−6

This diff is too big to show here.

tests/mocks/Ubuntu/Connectivity/plugin.cpp+1

This diff is too big to show here.

tests/mocks/Ubuntu/DownloadDaemonListener/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/Ubuntu/DownloadDaemonListener/DownloadDaemonListener.qmltypesdeleted−60

This diff is too big to show here.

tests/mocks/Ubuntu/DownloadDaemonListener/MockDownloadTracker.cpp+3−1

This diff is too big to show here.

tests/mocks/Ubuntu/DownloadDaemonListener/MockDownloadTracker.h+2−1

This diff is too big to show here.

tests/mocks/Ubuntu/Payments/CMakeLists.txtdeleted−10

This diff is too big to show here.

tests/mocks/Ubuntu/Payments/MockPayments.cppdeleted−94

This diff is too big to show here.

tests/mocks/Ubuntu/Payments/MockPayments.hdeleted−62

This diff is too big to show here.

tests/mocks/Ubuntu/Payments/Payments.qmltypesdeleted−44

This diff is too big to show here.

tests/mocks/Ubuntu/Payments/qmldirdeleted−3

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/CMakeLists.txtdeleted−10

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/SystemImage.qmltypesdeleted−20

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/qmldirdeleted−3

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/CMakeLists.txt+3

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/Diagnostics/CMakeLists.txtnew file+1

This diff is too big to show here.

plugins/Ubuntu/Gestures/Damper.cpp → tests/mocks/Ubuntu/SystemSettings/Diagnostics/MockDiagnostics.qmlrenamed+6−6

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/Diagnostics/qmldirnew file+2

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/LanguagePlugin.qmltypesdeleted−10

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSettingNumber.qml → tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/MockKeyboardPlugin.qmlrenamed+3−3

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/MockLanguagePlugin.qml+3−2

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/qmldir+1

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.cpp+9−2

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.h+9−1

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/SecurityPrivacy.qmltypesdeleted−39

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/TimeDate/CMakeLists.txtnew file+1

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/TimeDate/MockTimeDate.qmlnew file+37

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/TimeDate/qmldirnew file+2

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/Update/CMakeLists.txtnew file+1

This diff is too big to show here.

tests/mocks/Ubuntu/Payments/plugin.cpp → tests/mocks/Ubuntu/SystemSettings/Update/MockSystemImage.qmlrenamed+11−9

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/Update/qmldirnew file+2

This diff is too big to show here.

tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.cpp+27

This diff is too big to show here.

tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.h+22

This diff is too big to show here.

tests/mocks/Ubuntu/Telephony/Telephony.qmltypesdeleted−58

This diff is too big to show here.

tests/mocks/Ubuntu/Thumbnailer/Thumbnailer.qmltypesdeleted−17

This diff is too big to show here.

tests/mocks/Unity/Application/Application.qmltypesdeleted−517

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationInfo.cpp+256−101

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationInfo.h+55−31

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationManager.cpp+209−126

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationManager.h+42−30

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationScreenshotProvider.cppdeleted−79

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationScreenshotProvider.hdeleted−34

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationTestInterface.cppdeleted−117

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationTestInterface.hdeleted−45

This diff is too big to show here.

tests/mocks/Unity/Application/CMakeLists.txt+7−9

This diff is too big to show here.

tests/mocks/Unity/Application/MirMock.cppnew file+62

This diff is too big to show here.

tests/mocks/Unity/Application/MirMock.hnew file+43

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurface.cpp+313−22

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurface.h+110−12

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurfaceItem.cpp+143−35

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurfaceItem.h+25−3

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurfaceListModel.cppnew file+136

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurfaceListModel.hnew file+54

This diff is too big to show here.

tests/mocks/Unity/Application/ObjectListModel.h+2

This diff is too big to show here.

tests/mocks/Unity/Application/Session.cppdeleted−174

This diff is too big to show here.

tests/mocks/Unity/Application/Session.hdeleted−94

This diff is too big to show here.

tests/mocks/Unity/Application/SessionManager.cppdeleted−55

This diff is too big to show here.

tests/mocks/Unity/Application/SurfaceManager.cpp+242−25

This diff is too big to show here.

tests/mocks/Unity/Application/SurfaceManager.h+76−11

This diff is too big to show here.

tests/mocks/Unity/Application/UbuntuKeyboardInfo.cppdeleted−60

This diff is too big to show here.

tests/mocks/Unity/Application/UbuntuKeyboardInfo.hdeleted−66

This diff is too big to show here.

tests/mocks/Unity/Application/VirtualKeyboard.cpp+27−5

This diff is too big to show here.

tests/mocks/Unity/Application/VirtualKeyboard.h+4−1

This diff is too big to show here.

tests/mocks/Unity/Application/plugin.cpp+16−49

This diff is too big to show here.

tests/mocks/Unity/Application/resources/Kate.qmlnew file+49

This diff is too big to show here.

qml/Tutorial/TutorialLeftFinish.qml → tests/mocks/Unity/Application/resources/KateDialog.qmlrenamed+25−18

This diff is too big to show here.

qml/Stages/ShimStage.qml → tests/mocks/Unity/Application/resources/KateMenu.qmlrenamed+17−20

This diff is too big to show here.

tests/mocks/Unity/Application/resources/MirSurfaceItem.qml+61−5

This diff is too big to show here.

tests/mocks/Unity/Application/resources/VirtualKeyboard.qml+1−6

This diff is too big to show here.

tests/mocks/Unity/Application/resources/screenshots/browser@12.png

Binary file not shown.

tests/mocks/Unity/Application/resources/screenshots/camera@12.png

Binary file not shown.

tests/mocks/Unity/Application/resources/screenshots/dialer@12.png

Binary file not shown.

tests/mocks/Unity/Application/resources/screenshots/facebook@12.png

Binary file not shown.

tests/mocks/Unity/Application/resources/screenshots/gallery@12.png

Binary file not shown.

tests/mocks/Unity/Application/resources/screenshots/libreoffice@12.png

Binary file not shown.

tests/mocks/Unity/Application/resources/screenshots/map@12.png

Binary file not shown.

tests/mocks/Unity/Application/resources/screenshots/music@12.png

Binary file not shown.

tests/mocks/Unity/Application/resources/screenshots/twitter@12.png

Binary file not shown.

tests/mocks/Unity/Application/resources/screenshots/unity8-dash@12.png

Binary file not shown.

tests/mocks/Unity/Application/resources/screenshots/vkb_portrait.png

Binary file not shown.

tests/mocks/Unity/Application/resources/surfaces.qrc+3

This diff is too big to show here.

tests/mocks/Unity/Application/resources/vkb_portrait.png

Binary file not shown.

tests/mocks/Unity/ApplicationMenu/CMakeLists.txtnew file+18

This diff is too big to show here.

tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.cppnew file+47

This diff is too big to show here.

tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.hnew file+41

This diff is too big to show here.

tests/mocks/Unity/ApplicationMenu/plugin.cppnew file+42

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/plugin.h → tests/mocks/Unity/ApplicationMenu/plugin.hrenamed+6−5

This diff is too big to show here.

tests/mocks/Unity/ApplicationMenu/qmldirnew file+3

This diff is too big to show here.

tests/mocks/Unity/CMakeLists.txt+3−50

This diff is too big to show here.

tests/mocks/Unity/Connectivity/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/Unity/Connectivity/Connectivity.qmltypesdeleted−20

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/CMakeLists.txtdeleted−18

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/DashCommunicator.qmltypesdeleted−46

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/dashcommunicator.cppdeleted−42

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/dashcommunicator.hdeleted−39

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cppdeleted−46

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.hdeleted−41

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/plugin.cppdeleted−31

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/qmldirdeleted−3

This diff is too big to show here.

tests/mocks/Unity/Indicators/CMakeLists.txt+5−1

This diff is too big to show here.

tests/mocks/Unity/Indicators/Indicators.qmltypesdeleted−232

This diff is too big to show here.

tests/mocks/Unity/Indicators/IndicatorsModel.qml+97−14

This diff is too big to show here.

tests/mocks/Unity/Indicators/ModelActionRootState.qml+33−1

This diff is too big to show here.

tests/mocks/Unity/Indicators/fakeindicatorsmodel.h−1

This diff is too big to show here.

tests/mocks/Unity/Indicators/fakeindicatorsmodeldata.jsnew file+1328

This diff is too big to show here.

tests/mocks/Unity/Indicators/fakeplugin.cpp+2

This diff is too big to show here.

tests/mocks/Unity/InputInfo/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/Unity/InputInfo/plugin.h+1−1

This diff is too big to show here.

tests/mocks/Unity/InputInfo/qinputdeviceinfo_mock.cpp+7−3

This diff is too big to show here.

tests/mocks/Unity/Launcher/CMakeLists.txt+5−3

This diff is too big to show here.

tests/mocks/Unity/Launcher/Launcher.qmltypesdeleted−187

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockAppDrawerModel.cppnew file+98

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockAppDrawerModel.hnew file+43

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockLauncherItem.cpp+41−1

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockLauncherItem.h+12

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockLauncherModel.cpp+14−1

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockLauncherModel.h+2−2

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockQuickListModel.cpp+5−1

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockQuickListModel.h+2

This diff is too big to show here.

tests/mocks/Unity/Launcher/plugin.cpp+4

This diff is too big to show here.

tests/mocks/Unity/Notifications/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/Unity/Notifications/MockActionModel.h+1−1

This diff is too big to show here.

tests/mocks/Unity/Notifications/MockNotification.cpp+15

This diff is too big to show here.

tests/mocks/Unity/Notifications/MockNotification.h+7−1

This diff is too big to show here.

tests/mocks/Unity/Notifications/MockNotificationModel.cpp+10−17

This diff is too big to show here.

tests/mocks/Unity/Notifications/MockNotificationModel.h+2−4

This diff is too big to show here.

tests/mocks/Unity/Notifications/Notifications.qmltypesdeleted−149

This diff is too big to show here.

tests/mocks/Unity/Platform/CMakeLists.txtnew file+1

This diff is too big to show here.

tests/mocks/Unity/Platform/MockPlatform.qmlnew file+25

This diff is too big to show here.

tests/mocks/Unity/Platform/qmldirnew file+2

This diff is too big to show here.

tests/mocks/Unity/Screens/CMakeLists.txtnew file+14

This diff is too big to show here.

plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp → tests/mocks/Unity/Screens/plugin.cpprenamed+9−10

This diff is too big to show here.

tests/mocks/Unity/Application/SessionModel.h → tests/mocks/Unity/Screens/plugin.hrenamed+6−16

This diff is too big to show here.

tests/mocks/Unity/Screens/qmldirnew file+2

This diff is too big to show here.

tests/mocks/Unity/Screens/screens.cppnew file+71

This diff is too big to show here.

tests/mocks/Unity/Screens/screens.hnew file+82

This diff is too big to show here.

tests/mocks/Unity/Unity.qmltypesdeleted−486

This diff is too big to show here.

tests/mocks/Unity/fake_categories.cppdeleted−158

This diff is too big to show here.

tests/mocks/Unity/fake_categories.hdeleted−54

This diff is too big to show here.

tests/mocks/Unity/fake_navigation.cppdeleted−124

This diff is too big to show here.

tests/mocks/Unity/fake_navigation.hdeleted−61

This diff is too big to show here.

tests/mocks/Unity/fake_previewmodel.cppdeleted−95

This diff is too big to show here.

tests/mocks/Unity/fake_previewmodel.hdeleted−58

This diff is too big to show here.

tests/mocks/Unity/fake_previewstack.cppdeleted−68

This diff is too big to show here.

tests/mocks/Unity/fake_previewstack.hdeleted−52

This diff is too big to show here.

tests/mocks/Unity/fake_previewwidgetmodel.cppdeleted−89

This diff is too big to show here.

tests/mocks/Unity/fake_previewwidgetmodel.hdeleted−47

This diff is too big to show here.

tests/mocks/Unity/fake_resultsmodel.cppdeleted−90

This diff is too big to show here.

tests/mocks/Unity/fake_resultsmodel.hdeleted−52

This diff is too big to show here.

tests/mocks/Unity/fake_scope.cppdeleted−328

This diff is too big to show here.

tests/mocks/Unity/fake_scope.hdeleted−113

This diff is too big to show here.

tests/mocks/Unity/fake_scopes.cppdeleted−265

This diff is too big to show here.

tests/mocks/Unity/fake_scopes.hdeleted−83

This diff is too big to show here.

tests/mocks/Unity/fake_scopesoverview.cppdeleted−340

This diff is too big to show here.

tests/mocks/Unity/fake_scopesoverview.hdeleted−117

This diff is too big to show here.

tests/mocks/Unity/fake_settingsmodel.cppdeleted−95

This diff is too big to show here.

tests/mocks/Unity/fake_settingsmodel.hdeleted−54

This diff is too big to show here.

tests/mocks/Unity/fake_unity_plugin.cppdeleted−56

This diff is too big to show here.

tests/mocks/Unity/qmldirdeleted−3

This diff is too big to show here.

tests/mocks/Utils/CMakeLists.txt+27−9

This diff is too big to show here.

tests/mocks/Utils/URLDispatcher.cppnew file+38

This diff is too big to show here.

tests/mocks/Utils/URLDispatcher.hnew file+47

This diff is too big to show here.

tests/mocks/Utils/Utils.qmltypesdeleted−178

This diff is too big to show here.

tests/mocks/Utils/HomeKeyWatcher.qml → tests/mocks/Utils/WindowInputMonitor.qmlrenamed+3−1

This diff is too big to show here.

tests/mocks/Utils/constants.cpp+2−1

This diff is too big to show here.

tests/mocks/Utils/constants.h+5−5

This diff is too big to show here.

tests/mocks/Utils/plugin.cpp+29−11

This diff is too big to show here.

tests/mocks/Utils/plugin.h+1−2

This diff is too big to show here.

tests/mocks/Utils/qmldir+1−1

This diff is too big to show here.

tests/mocks/Utils/windowstatestorage.cpp+39−2

This diff is too big to show here.

tests/mocks/Utils/windowstatestorage.h+32−6

This diff is too big to show here.

tests/mocks/Wizard/CMakeLists.txt+9−1

This diff is too big to show here.

tests/mocks/Wizard/MockSystem.cpp+28−3

This diff is too big to show here.

tests/mocks/Wizard/MockSystem.h+17−3

This diff is too big to show here.

tests/mocks/Wizard/Wizard.qmltypesdeleted−37

This diff is too big to show here.

tests/mocks/Wizard/mockplugin.cpp+11−8

This diff is too big to show here.

tests/mocks/indicator-service/CMakeLists.txt−1

This diff is too big to show here.

tests/mocks/liblightdm/CMakeLists.txtnew file+18

This diff is too big to show here.

tests/mocks/IntegratedLightDM/liblightdm/GreeterPrivate.cpp → tests/mocks/liblightdm/GreeterPrivate.cpprenamed

The content is the same.

tests/mocks/IntegratedLightDM/liblightdm/GreeterPrivate.h → tests/mocks/liblightdm/GreeterPrivate.hrenamed+1−1

This diff is too big to show here.

tests/mocks/liblightdm/MockController.cppnew file+192

This diff is too big to show here.

tests/mocks/liblightdm/MockController.hnew file+106

This diff is too big to show here.

tests/mocks/liblightdm/MockGreeter.cppnew file+316

This diff is too big to show here.

tests/mocks/IntegratedLightDM/liblightdm/Greeter.h → tests/mocks/liblightdm/MockGreeter.hrenamed+10−24

This diff is too big to show here.

tests/mocks/liblightdm/MockSessionsModel.cppnew file+118

This diff is too big to show here.

tests/mocks/liblightdm/MockSessionsModel.hnew file+64

This diff is too big to show here.

tests/mocks/liblightdm/MockUsersModel.cppnew file+220

This diff is too big to show here.

tests/mocks/IntegratedLightDM/liblightdm/UsersModel.h → tests/mocks/liblightdm/MockUsersModel.hrenamed+11−19

This diff is too big to show here.

tests/mocks/liblightdm/SessionsModelPrivate.cppnew file+83

This diff is too big to show here.

tests/mocks/liblightdm/SessionsModelPrivate.hnew file+63

This diff is too big to show here.

tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp → tests/mocks/liblightdm/UsersModelPrivate.cpprenamed+43−23

This diff is too big to show here.

tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.h → tests/mocks/liblightdm/UsersModelPrivate.hrenamed+2−1

This diff is too big to show here.

tests/mocks/liblightdm/demo/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/libusermetrics/CMakeLists.txt+2−1

This diff is too big to show here.

tests/mocks/libusermetrics/ColorTheme.cpp+4

This diff is too big to show here.

tests/mocks/libusermetrics/UserMetrics.cpp+39−14

This diff is too big to show here.

tests/mocks/libusermetrics/UserMetrics.h+2

This diff is too big to show here.

tests/mocks/libusermetrics/libusermetricsoutput/ColorTheme.hdeleted−1

This diff is too big to show here.

tests/mocks/libusermetrics/libusermetricsoutput/UserMetrics.hdeleted−1

This diff is too big to show here.

tests/plugins/AccountsService/CMakeLists.txt+20−8

This diff is too big to show here.

tests/plugins/AccountsService/PropertiesServer.cpp+56−5

This diff is too big to show here.

tests/plugins/AccountsService/PropertiesServer.h+9−2

This diff is too big to show here.

tests/plugins/AccountsService/UscServer.cppnew file+28

This diff is too big to show here.

tests/plugins/AccountsService/UscServer.hnew file+39

This diff is too big to show here.

tests/plugins/AccountsService/client.cpp+161−34

This diff is too big to show here.

tests/plugins/AccountsService/interfaces.xml+29

This diff is too big to show here.

tests/plugins/AccountsService/server.cpp+12

This diff is too big to show here.

tests/plugins/AccountsService/types.hnew file+25

This diff is too big to show here.

tests/plugins/CMakeLists.txt+5−4

This diff is too big to show here.

tests/plugins/Cursor/CMakeLists.txtnew file+8

This diff is too big to show here.

plugins/Unity/DashCommunicator/dashcommunicatorservice.h → tests/plugins/Cursor/TextEntry.qmlrenamed+18−22

This diff is too big to show here.

tests/plugins/Cursor/tst_Cursor.qmlnew file+151

This diff is too big to show here.

tests/plugins/Dash/CMakeLists.txtdeleted−75

This diff is too big to show here.

tests/plugins/Dash/cardcreator/1.resdeleted−122

This diff is too big to show here.

tests/plugins/Dash/cardcreator/1.tstdeleted−3

This diff is too big to show here.

tests/plugins/Dash/cardcreator/2.resdeleted−132

This diff is too big to show here.

tests/plugins/Dash/cardcreator/2.tstdeleted−3

This diff is too big to show here.

tests/plugins/Dash/cardcreator/3.resdeleted−140

This diff is too big to show here.

tests/plugins/Dash/cardcreator/3.tstdeleted−3

This diff is too big to show here.

tests/plugins/Dash/cardcreator/4.resdeleted−113

This diff is too big to show here.

tests/plugins/Dash/cardcreator/4.tstdeleted−3

This diff is too big to show here.

tests/plugins/Dash/cardcreator/5.resdeleted−159

This diff is too big to show here.

tests/plugins/Dash/cardcreator/5.tstdeleted−3

This diff is too big to show here.

tests/plugins/Dash/cardcreator/6.resdeleted−121

This diff is too big to show here.

tests/plugins/Dash/cardcreator/6.tstdeleted−3

This diff is too big to show here.

tests/plugins/Dash/cardcreator/7.resdeleted−145

This diff is too big to show here.

tests/plugins/Dash/cardcreator/7.tstdeleted−3

This diff is too big to show here.

tests/plugins/Dash/cardcreator/8.resdeleted−103

This diff is too big to show here.

tests/plugins/Dash/cardcreator/8.tstdeleted−3

This diff is too big to show here.

tests/plugins/Dash/cardcreatortest.cppdeleted−107

This diff is too big to show here.

tests/plugins/Dash/cardcreatortest.qmldeleted−29

This diff is too big to show here.

tests/plugins/Dash/horizontaljournaltest.cppdeleted−490

This diff is too big to show here.

tests/plugins/Dash/horizontaljournaltest.qmldeleted−44

This diff is too big to show here.

tests/plugins/Dash/horizontaljournaltry.cppdeleted−89

This diff is too big to show here.

tests/plugins/Dash/horizontaljournaltry.qmldeleted−120

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadersectionexternalmodeltest.cppdeleted−246

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadersectiontest.cppdeleted−2161

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertest.cppdeleted−1966

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertest.qmldeleted−97

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertestsection.qmldeleted−107

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qmldeleted−75

This diff is too big to show here.

tests/plugins/Dash/organicgridtest.cppdeleted−533

This diff is too big to show here.

tests/plugins/Dash/organicgridtest.qmldeleted−44

This diff is too big to show here.

tests/plugins/Dash/organicgridtry.cppdeleted−97

This diff is too big to show here.

tests/plugins/Dash/organicgridtry.qmldeleted−114

This diff is too big to show here.

tests/plugins/Dash/tst_CardAttributes.qmldeleted−57

This diff is too big to show here.

tests/plugins/Dash/tst_CroppedImageMinimumSourceSize.qmldeleted−56

This diff is too big to show here.

tests/plugins/Dash/tst_ListViewWithPageHeaderQML.qmldeleted−138

This diff is too big to show here.

tests/plugins/Dash/tst_ScopeStyle.qmldeleted−188

This diff is too big to show here.

tests/plugins/Dash/verticaljournaltest.cppdeleted−502

This diff is too big to show here.

tests/plugins/Dash/verticaljournaltest.qmldeleted−45

This diff is too big to show here.

tests/plugins/Dash/verticaljournaltry.cppdeleted−89

This diff is too big to show here.

tests/plugins/Dash/verticaljournaltry.qmldeleted−121

This diff is too big to show here.

tests/plugins/GlobalShortcut/CMakeLists.txt+12−7

This diff is too big to show here.

tests/plugins/GlobalShortcut/GlobalShortcutTest.cpp+3−2

This diff is too big to show here.

tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt+5−23

This diff is too big to show here.

tests/plugins/Greeter/Unity/Launcher/launchermodelastest.cpp+4−1

This diff is too big to show here.

tests/plugins/IntegratedLightDM/CMakeLists.txtdeleted−67

This diff is too big to show here.

tests/plugins/IntegratedLightDM/usersmodel.cpp−84

This diff is too big to show here.

tests/plugins/LightDM/CMakeLists.txt+1

This diff is too big to show here.

tests/plugins/LightDM/IntegratedLightDM/CMakeLists.txt+157

This diff is too big to show here.

tests/plugins/LightDM/IntegratedLightDM/dbus.cpp+23−15

This diff is too big to show here.

tests/plugins/LightDM/IntegratedLightDM/greeter.qml+2−7

This diff is too big to show here.

tests/plugins/LightDM/IntegratedLightDM/integrated.cpp+88

This diff is too big to show here.

tests/plugins/LightDM/IntegratedLightDM/pam.cpp+3−1

This diff is too big to show here.

tests/plugins/LightDM/IntegratedLightDM/promptsmodel.cpp+175

This diff is too big to show here.

tests/plugins/LightDM/IntegratedLightDM/sessionsmodel.cpp+134

This diff is too big to show here.

tests/plugins/LightDM/IntegratedLightDM/usersmodel.cpp+168

This diff is too big to show here.

tests/plugins/ScreenGrabber/CMakeLists.txt−14

This diff is too big to show here.

tests/plugins/ScreenGrabber/ScreenGrabberTest.cpp−77

This diff is too big to show here.

tests/plugins/SessionBroadcast/BroadcastServer.cpp+33

This diff is too big to show here.

tests/plugins/SessionBroadcast/BroadcastServer.h+40

This diff is too big to show here.

tests/plugins/SessionBroadcast/CMakeLists.txt+51

This diff is too big to show here.

tests/plugins/SessionBroadcast/interfaces.xml+18

This diff is too big to show here.

tests/plugins/SessionBroadcast/server.cpp+37

This diff is too big to show here.

tests/plugins/SessionBroadcast/sessionbroadcasttest.cpp+111

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/CMakeLists.txt+25−11

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/DownwardsLauncher.qml−72

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/GestureTest.cpp+58−4

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/GestureTest.h+17−6

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/LeftwardsLauncher.qml−76

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/RightwardsLauncher.qml−76

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/UpwardsLauncher.qml−76

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/tst_AxisVelocityCalculator.cpp+1−1

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/tst_Damper.cpp−40

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp−1306

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.qml−76

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/tst_FloatingFlickable.cpp+28−19

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/tst_FloatingFlickable.qml+1

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/tst_TouchGate.cpp+17−4

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/tst_TouchGestureArea.cpp+300

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/tst_TouchGestureArea.qml+90

This diff is too big to show here.

tests/plugins/Unity/CMakeLists.txt+1

This diff is too big to show here.

tests/plugins/Unity/Indicators/CMakeLists.txt+12−6

This diff is too big to show here.

tests/plugins/Unity/Indicators/IndicatorsManagerTest.cpp+1−1

This diff is too big to show here.

tests/plugins/Unity/Indicators/IndicatorsModelTest.cpp+1−1

This diff is too big to show here.

tests/plugins/Unity/Indicators/MenuContentActivatorTest.cpp+1

This diff is too big to show here.

tests/plugins/Unity/Launcher/CMakeLists.txt+59−21

This diff is too big to show here.

tests/plugins/Unity/Launcher/appdrawermodeltest.cpp+68

This diff is too big to show here.

tests/plugins/Unity/Launcher/applications/abs-icon.desktop+1

This diff is too big to show here.

tests/plugins/Unity/Launcher/applications/click-icon.desktop+1

This diff is too big to show here.

tests/plugins/Unity/Launcher/applications/click-icon.svg

This diff is too big to show here.

tests/plugins/Unity/Launcher/applications/no-name.desktop+1

This diff is too big to show here.

tests/plugins/Unity/Launcher/applications/rel-icon.desktop+1

This diff is too big to show here.

tests/plugins/Unity/Launcher/applications/rel-icon.svg

This diff is too big to show here.

tests/plugins/Unity/Launcher/launchermodeltest.cpp+175−30

This diff is too big to show here.

tests/plugins/Unity/Launcher/no-icon.desktop−2

This diff is too big to show here.

tests/plugins/Unity/Launcher/ualwrapper.cpp+58

This diff is too big to show here.

tests/plugins/Unity/Launcher/ualwrapper.h+55

This diff is too big to show here.

tests/plugins/Unity/Launcher/xdgwatcher.cpp+19−13

This diff is too big to show here.

tests/plugins/Unity/Launcher/xdgwatcher.h+14−19

This diff is too big to show here.

tests/plugins/Unity/Platform/CMakeLists.txt+30

This diff is too big to show here.

tests/plugins/Unity/Platform/platformtest.cpp+142

This diff is too big to show here.

tests/plugins/Unity/Session/CMakeLists.txt+50−2

This diff is too big to show here.

tests/plugins/Unity/Session/LightDMServer.cpp+29

This diff is too big to show here.

tests/plugins/Unity/Session/LightDMServer.h+38

This diff is too big to show here.

tests/plugins/Unity/Session/LogindServer.cpp+43

This diff is too big to show here.

tests/plugins/Unity/Session/LogindServer.h+48

This diff is too big to show here.

tests/plugins/Unity/Session/interfaces.xml+29

This diff is too big to show here.

tests/plugins/Unity/Session/preload.c+43

This diff is too big to show here.

tests/plugins/Unity/Session/server.cpp+50

This diff is too big to show here.

tests/plugins/Unity/Session/sessionbackendtest.cpp+138−19

This diff is too big to show here.

tests/plugins/Utils/CMakeLists.txt+27−4

This diff is too big to show here.

tests/plugins/Utils/DeviceConfigParserTest.cpp+76

This diff is too big to show here.

tests/plugins/Utils/ModelTest.cpp+2−1

This diff is too big to show here.

tests/plugins/Utils/URLDispatcherTest.cpp+78

This diff is too big to show here.

tests/plugins/Utils/WindowInputMonitorTest.cpp+170−32

This diff is too big to show here.

tests/plugins/Utils/WindowStateStorageTest.cpp+121

This diff is too big to show here.

tests/plugins/WindowManager/CMakeLists.txt+36

This diff is too big to show here.

tests/plugins/WindowManager/UnityApplicationMocks.h+211

This diff is too big to show here.

tests/plugins/WindowManager/tst_TopLevelWindowModel.cpp+193

This diff is too big to show here.

tests/plugins/Wizard/CMakeLists.txt+8−2

This diff is too big to show here.

tests/plugins/Wizard/tst_pagelist.cpp+30−1

This diff is too big to show here.

tests/qmltests/ApplicationMenuDataLoader.qml+99

This diff is too big to show here.

tests/qmltests/ApplicationMenus/tst_MenuBar.qml+437

This diff is too big to show here.

tests/qmltests/ApplicationMenus/tst_MenuPopup.qml+361

This diff is too big to show here.

tests/qmltests/CMakeLists.txt+49−64

This diff is too big to show here.

tests/qmltests/Components/CMakeLists.txt+35−9

This diff is too big to show here.

tests/qmltests/Components/tst_Carousel.qml−293

This diff is too big to show here.

tests/qmltests/Components/tst_Dialogs.qml+4−3

This diff is too big to show here.

tests/qmltests/Components/tst_DragHandle.cpp+52−29

This diff is too big to show here.

tests/qmltests/Components/tst_DragHandle.qml+28−10

This diff is too big to show here.

tests/qmltests/Components/tst_DragHandle/BottomEdgeShowable.qml+108

This diff is too big to show here.

tests/qmltests/Components/tst_DragHandle/LeftEdgeShowable.qml

This diff is too big to show here.

tests/qmltests/Components/tst_DragHandle/RightEdgeShowable.qml+108

This diff is too big to show here.

tests/qmltests/Components/tst_DragHandle/SimpleButton.qml+14−9

This diff is too big to show here.

tests/qmltests/Components/tst_DragHandle/TopEdgeShowable.qml+7−7

This diff is too big to show here.

tests/qmltests/Components/tst_DraggingArea.qml+6−6

This diff is too big to show here.

tests/qmltests/Components/tst_EdgeDragEvaluator.cpp+6−4

This diff is too big to show here.

tests/qmltests/Components/tst_LazyImage.qml+27−8

This diff is too big to show here.

tests/qmltests/Components/tst_LazyImage/portrait.png

This diff is too big to show here.

tests/qmltests/Components/tst_LazyImage/square.png

This diff is too big to show here.

tests/qmltests/Components/tst_LazyImage/wide.png

This diff is too big to show here.

tests/qmltests/Components/tst_Lockscreen.qml+28−39

This diff is too big to show here.

tests/qmltests/Components/tst_MediaServices.qml+231

This diff is too big to show here.

tests/qmltests/Components/tst_ModeSwitchWarningDialog.qml+2−2

This diff is too big to show here.

tests/qmltests/Components/tst_PhysicalKeysMapper.qml+128−62

This diff is too big to show here.

tests/qmltests/Components/tst_Rating.qml+1−1

This diff is too big to show here.

tests/qmltests/Components/tst_ResponsiveGridView.qml−193

This diff is too big to show here.

tests/qmltests/Components/tst_ResponsiveVerticalJournal.qml−183

This diff is too big to show here.

tests/qmltests/Components/tst_SharingPicker.qml+22−20

This diff is too big to show here.

tests/qmltests/Components/tst_Showable.qml+13

This diff is too big to show here.

tests/qmltests/Components/tst_VirtualTouchPad.qml+197

This diff is too big to show here.

tests/qmltests/Components/tst_Wallpaper.qml+118

This diff is too big to show here.

tests/qmltests/Components/tst_WallpaperResolver.qml+115−43

This diff is too big to show here.

tests/qmltests/Components/tst_ZoomableImage.qml+10−7

This diff is too big to show here.

tests/qmltests/Dash/CardHelpers.js−113

This diff is too big to show here.

tests/qmltests/Dash/Previews/MockPreviewWidget.qml−27

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_Preview.qml−135

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewActions.qml−148

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml−179

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewComment.qml−84

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewCommentInput.qml−85

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewExpandable.qml−339

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewHeader.qml−155

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewIconActions.qml−126

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewImageGallery.qml−127

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewPayments.qml−203

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewProgress.qml−87

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingDisplay.qml−125

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingEdit.qml−80

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingInput.qml−202

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewTable.qml−126

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewTextSummary.qml−87

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewVideoPlayback.qml−61

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml−103

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qml−104

This diff is too big to show here.

tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qml−62

This diff is too big to show here.

tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingList.qml−84

This diff is too big to show here.

tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qml−98

This diff is too big to show here.

tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qml−88

This diff is too big to show here.

tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingsWidgetFactory.qml−65

This diff is too big to show here.

tests/qmltests/Dash/artwork/avatar@12.png

This diff is too big to show here.

tests/qmltests/Dash/artwork/background.png

This diff is too big to show here.

tests/qmltests/Dash/artwork/checkers.png

This diff is too big to show here.

tests/qmltests/Dash/artwork/emblem.png

This diff is too big to show here.

tests/qmltests/Dash/artwork/music-player-design.png

This diff is too big to show here.

tests/qmltests/Dash/tst_Card.qml−622

This diff is too big to show here.

tests/qmltests/Dash/tst_CardBenchmark.qml−97

This diff is too big to show here.

tests/qmltests/Dash/tst_CardCarousel.qml−87

This diff is too big to show here.

tests/qmltests/Dash/tst_CardTool.qml−379

This diff is too big to show here.

tests/qmltests/Dash/tst_Dash.qml−569

This diff is too big to show here.

tests/qmltests/Dash/tst_DashContent.qml−603

This diff is too big to show here.

tests/qmltests/Dash/tst_DashPageHeader.qml−331

This diff is too big to show here.

tests/qmltests/Dash/tst_DashShell.qml−135

This diff is too big to show here.

tests/qmltests/Dash/tst_GenericScopeView.qml−666

This diff is too big to show here.

tests/qmltests/Dash/tst_PageHeader/logo-ubuntu-orange.svg−60

This diff is too big to show here.

tests/qmltests/Dash/tst_PreviewListView.qml−115

This diff is too big to show here.

tests/qmltests/Greeter/TestView.qml+24−22

This diff is too big to show here.

tests/qmltests/Greeter/tst_Greeter.qml+325−156

This diff is too big to show here.

tests/qmltests/Greeter/tst_GreeterView.qml+1366

This diff is too big to show here.

tests/qmltests/Greeter/tst_Infographics.qml+78−24

This diff is too big to show here.

tests/qmltests/Greeter/tst_NarrowView.qml−522

This diff is too big to show here.

tests/qmltests/Greeter/tst_WideView.qml−526

This diff is too big to show here.

tests/qmltests/Launcher/tst_Drawer.qml+520

This diff is too big to show here.

tests/qmltests/Launcher/tst_Launcher.qml+842−81

This diff is too big to show here.

tests/qmltests/Notifications/Notification.qml+1

This diff is too big to show here.

tests/qmltests/Notifications/tst_Notifications.qml+222−76

This diff is too big to show here.

tests/qmltests/Notifications/tst_OptionToggle.qml+26−26

This diff is too big to show here.

tests/qmltests/Notifications/tst_SwipeToAct.qml+30−27

This diff is too big to show here.

tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+27−33

This diff is too big to show here.

tests/qmltests/Panel/Indicators/tst_IndicatorItem.qml+18−18

This diff is too big to show here.

tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml+98−93

This diff is too big to show here.

tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qml+168−8

This diff is too big to show here.

tests/qmltests/Panel/Indicators/tst_MessageMenuItemFactory.qml+1

This diff is too big to show here.

tests/qmltests/Panel/PanelTest.qml+2−6

This diff is too big to show here.

tests/qmltests/Panel/PanelUI.qml+286

This diff is too big to show here.

tests/qmltests/Panel/tst_ActiveCallHint.qml+31−11

This diff is too big to show here.

tests/qmltests/Panel/tst_MenuContent.qml+16−4

This diff is too big to show here.

tests/qmltests/Panel/tst_Panel.qml+434−231

This diff is too big to show here.

tests/qmltests/Panel/tst_PanelBar.qml+25−34

This diff is too big to show here.

tests/qmltests/Panel/tst_PanelItemRow.qml+42−14

This diff is too big to show here.

tests/qmltests/Panel/tst_PanelMenu.qml+140−38

This diff is too big to show here.

tests/qmltests/Panel/tst_PanelMenuPage.qml+53−49

This diff is too big to show here.

tests/qmltests/Panel/tst_PanelSmallScreen.qml+133

This diff is too big to show here.

tests/qmltests/Stage/ApplicationCheckBox.qml+189

This diff is too big to show here.

tests/qmltests/Stage/SizeHintField.qml+13−11

This diff is too big to show here.

tests/qmltests/Stage/SurfaceManagerControls.qml+32

This diff is too big to show here.

tests/qmltests/Stage/SurfaceManagerField.qml+17−18

This diff is too big to show here.

tests/qmltests/Stage/tst_ApplicationWindow.qml+184−93

This diff is too big to show here.

tests/qmltests/Stage/tst_DecoratedWindow.qml+267

This diff is too big to show here.

tests/qmltests/Stage/tst_DesktopStage.qml+1085

This diff is too big to show here.

tests/qmltests/Stage/tst_PhoneStage.qml+624

This diff is too big to show here.

tests/qmltests/Stage/tst_QMLTopLevelWindowModel.qml+191

This diff is too big to show here.

tests/qmltests/Stage/tst_Splash.qml+16−2

This diff is too big to show here.

tests/qmltests/Stage/tst_SurfaceContainer.qml+258

This diff is too big to show here.

tests/qmltests/Stage/tst_TabletStage.qml+764

This diff is too big to show here.

tests/qmltests/Stage/tst_WindowDecoration.qml+244

This diff is too big to show here.

tests/qmltests/Stage/tst_WindowResizeArea.qml+465

This diff is too big to show here.

tests/qmltests/Stages/ApplicationCheckBox.qml−114

This diff is too big to show here.

tests/qmltests/Stages/RecursingChildSessionControl.qml−145

This diff is too big to show here.

tests/qmltests/Stages/tst_DesktopStage.qml−462

This diff is too big to show here.

tests/qmltests/Stages/tst_PhoneStage.qml−467

This diff is too big to show here.

tests/qmltests/Stages/tst_SessionContainer.qml−309

This diff is too big to show here.

tests/qmltests/Stages/tst_SpreadDelegate.qml−312

This diff is too big to show here.

tests/qmltests/Stages/tst_SurfaceContainer.qml−184

This diff is too big to show here.

tests/qmltests/Stages/tst_TabletStage.qml−370

This diff is too big to show here.

tests/qmltests/Stages/tst_WindowResizeArea.qml−294

This diff is too big to show here.

tests/qmltests/Tutorial/tst_Tutorial.qml+664−247

This diff is too big to show here.

tests/qmltests/UnityLogo.png

This diff is too big to show here.

tests/qmltests/Wizard/tst_Wizard.qml+240−317

This diff is too big to show here.

tests/qmltests/tst_DeviceConfiguration.qml+49

This diff is too big to show here.

tests/qmltests/tst_DisabledScreenNotice.qml+98−2

This diff is too big to show here.

tests/qmltests/tst_OrientedShell.qml+719−465

This diff is too big to show here.

tests/qmltests/tst_Shell.qml+2284−853

This diff is too big to show here.

tests/qmltests/tst_ShellWithPin.qml+189−265

This diff is too big to show here.

tests/qmltests/utils/Unity/Test/tst_UnityTest.qml+31

This diff is too big to show here.

tests/scripts/alert-launcher-icon.sh+16

This diff is too big to show here.

tests/scripts/get-progress.sh+16

This diff is too big to show here.

tests/scripts/list-launcher-icons.sh+16

This diff is too big to show here.

tests/scripts/set-count-visible.sh+16

This diff is too big to show here.

tests/scripts/set-count.sh+16

This diff is too big to show here.

tests/scripts/set-progress.sh+16

This diff is too big to show here.

tests/uqmlscene/CMakeLists.txt+14−2

This diff is too big to show here.

tests/uqmlscene/main.cpp+7−4

This diff is too big to show here.

tests/utils/modules/Unity/Test/CMakeLists.txt+22−8

This diff is too big to show here.

tests/utils/modules/Unity/Test/MouseTouchEmulationCheckbox.qml+5−1

This diff is too big to show here.

tests/utils/modules/Unity/Test/StageTestCase.qml+64

This diff is too big to show here.

tests/utils/modules/Unity/Test/Test.qmltypes−60

This diff is too big to show here.

tests/utils/modules/Unity/Test/TouchEventSequenceWrapper.cpp+18−4

This diff is too big to show here.

tests/utils/modules/Unity/Test/TouchEventSequenceWrapper.h+4−2

This diff is too big to show here.

tests/utils/modules/Unity/Test/UnityTestCase.qml+205−44

This diff is too big to show here.

tests/utils/modules/Unity/Test/plugin.cpp+13−3

This diff is too big to show here.

tests/utils/modules/Unity/Test/qmldir+2−1

This diff is too big to show here.

tests/utils/modules/Unity/Test/testutil.cpp+33−5

This diff is too big to show here.

tests/utils/modules/Unity/Test/testutil.h+1

This diff is too big to show here.

tools/CMakeLists.txt+2−12

This diff is too big to show here.

tools/indicatorsclient/CMakeLists.txt+1−1

This diff is too big to show here.

tools/indicatorsclient/indicatorsclient.cpp+10−8

This diff is too big to show here.

tools/indicatorsclient/indicatorsclient.h−2

This diff is too big to show here.

tools/indicatorsclient/main.cpp

This diff is too big to show here.

tools/menutool/CMakeLists.txt+5

This diff is too big to show here.

tools/menutool/README+11

This diff is too big to show here.

tools/menutool/menutool.cpp+62

This diff is too big to show here.

tools/menutool/menutool.qml+118

This diff is too big to show here.

tools/registry-tracker.cpp−146

This diff is too big to show here.

tools/registry-tracker.h−49

This diff is too big to show here.

tools/scopetool.cpp−112

This diff is too big to show here.

tools/unlock-device+16

This diff is too big to show here.