on xenial help sign in
870 files changed+52317−84877
since splitsnapshots
unifiedsplit
.bazaar/Makefile−6 .bazaar/plugins/makecheck_unity_phablet.py−51 .bzr-builddeb/default.conf−2 .bzrignore−7 .gitignore+7 CMakeLists.txt+10−3 Jenkinsfile+2 README.md+31 build.sh+16 clickable.yaml+153 cmake/modules/QmlPlugins.cmake−148 cmake/modules/QmlTest.cmake+9−4 data/CMakeLists.txt+1−9 data/com.canonical.Unity.gschema.xml+255 data/com.canonical.Unity8.gschema.xml+17−7 data/test.sensors+12 data/unity8-dash.conf−25 data/unity8-dash.desktop.in−9 data/unity8-dash.png data/unity8-dash.svg−326 data/unity8-dash.url-dispatcher−6 data/unity8-greeter-wrapper+7−4 data/unity8.conf+35−34 debian/changelog+341−20 debian/control+215−196 debian/rules+19−5 debian/source/format−1 debian/tests/control+5−3 debian/unity-scope-tool.install−2 debian/unity8-common.install−2 debian/unity8-greeter.install+1−1 debian/unity8-private.install+1−3 debian/unity8-schemas.install+1 debian/unity8-tests.install−1 debian/unity8.install+6−10 debian/usr.bin.unity8-dash−21 plugins/AccountsService/AccountsService.cpp+1−30 plugins/AccountsService/AccountsService.h−16 plugins/AccountsService/CMakeLists.txt+1−2 plugins/AccountsService/com.canonical.unity.AccountsService.xml+6 plugins/CMakeLists.txt+1−3 plugins/Cursor/CMakeLists.txt+1−2 plugins/Cursor/CursorImageProvider.cpp+2 plugins/Dash/AudioProgressBar.qml−54 plugins/Dash/CMakeLists.txt−47 plugins/Dash/CardAttributes.qml−71 plugins/Dash/CardAudioProgress.qml−59 plugins/Dash/CardCreator.js−999 plugins/Dash/CardCreatorCache.qml−40 plugins/Dash/CardSocialActions.qml−94 plugins/Dash/CroppedImageMinimumSourceSize.qml−38 plugins/Dash/DashAudioPlayer.qml−120 plugins/Dash/ScopeStyle.qml−95 plugins/Dash/abstractdashview.cpp−359 plugins/Dash/abstractdashview.h−128 plugins/Dash/graphics/music_progress_bg.png plugins/Dash/horizontaljournal.cpp−239 plugins/Dash/horizontaljournal.h−63 plugins/Dash/listviewwithpageheader.cpp−1394 plugins/Dash/listviewwithpageheader.h−218 plugins/Dash/organicgrid.cpp−259 plugins/Dash/organicgrid.h−91 plugins/Dash/plugin.cpp−70 plugins/Dash/plugin.h−33 plugins/Dash/qmldir−11 plugins/Dash/verticaljournal.cpp−280 plugins/Dash/verticaljournal.h−103 plugins/GlobalShortcut/CMakeLists.txt+1−1 plugins/GlobalShortcut/globalshortcut.cpp+3 plugins/Greeter/Unity/Launcher/CMakeLists.txt+1−3 plugins/Greeter/Unity/Launcher/launcheritem.cpp+6 plugins/Greeter/Unity/Launcher/launcheritem.h+1 plugins/Greeter/Unity/Launcher/quicklistmodel.cpp+2 plugins/ImageCache/CMakeLists.txt−8 plugins/ImageCache/ImageCache.cpp−135 plugins/ImageCache/ImageCache.h−53 plugins/ImageCache/plugin.cpp−39 plugins/ImageCache/plugin.h−31 plugins/ImageCache/qmldir−2 plugins/LightDM/DBusGreeterList.cpp+3−3 plugins/LightDM/DBusGreeterList.h+1−1 plugins/LightDM/FullLightDM/CMakeLists.txt+1−1 plugins/LightDM/Greeter.cpp+16 plugins/LightDM/Greeter.h+3 plugins/LightDM/GreeterPrivate.h+1 plugins/LightDM/IntegratedLightDM/CMakeLists.txt+1−1 plugins/LightDM/IntegratedLightDM/liblightdm/CMakeLists.txt+3−4 plugins/LightDM/UsersModel.cpp+5 plugins/Lights/CMakeLists.txt+8−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+4−8 plugins/Lights/plugin.cpp+20−1 plugins/Powerd/CMakeLists.txt+4−2 plugins/ScreenshotDirectory/CMakeLists.txt+1−1 plugins/SessionBroadcast/CMakeLists.txt+1−2 plugins/UInput/CMakeLists.txt+1−1 plugins/Ubuntu/CMakeLists.txt−1 plugins/Ubuntu/DownloadDaemonListener/CMakeLists.txt+4−2 plugins/Ubuntu/Gestures/CMakeLists.txt+1−3 plugins/Ubuntu/Gestures/TouchGestureArea.cpp+6−5 plugins/Ubuntu/SystemImage/CMakeLists.txt−15 plugins/Ubuntu/SystemImage/SystemImage.cpp−155 plugins/Ubuntu/SystemImage/SystemImage.h−84 plugins/Ubuntu/SystemImage/plugin.cpp−28 plugins/Ubuntu/SystemImage/plugin.h−31 plugins/Ubuntu/SystemImage/qmldir−3 plugins/Unity/ApplicationMenu/CMakeLists.txt+1−1 plugins/Unity/CMakeLists.txt−1 plugins/Unity/Connectivity/CMakeLists.txt+1−1 plugins/Unity/DashCommunicator/CMakeLists.txt−26 plugins/Unity/DashCommunicator/dashcommunicator.cpp−58 plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp−30 plugins/Unity/DashCommunicator/dashcommunicatorservice.h−38 plugins/Unity/DashCommunicator/dashconnection.cpp−66 plugins/Unity/DashCommunicator/dashconnection.h−37 plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp−35 plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h−39 plugins/Unity/DashCommunicator/plugin.cpp−32 plugins/Unity/DashCommunicator/qmldir−3 plugins/Unity/Indicators/CMakeLists.txt+1−2 plugins/Unity/Indicators/indicatorsmodel.cpp+13 plugins/Unity/Indicators/indicatorsmodel.h+9 plugins/Unity/InputInfo/CMakeLists.txt+1−2 plugins/Unity/Launcher/CMakeLists.txt+4−3 plugins/Unity/Launcher/appdrawermodel.cpp+144−14 plugins/Unity/Launcher/appdrawermodel.h+33−2 plugins/Unity/Launcher/launcheritem.cpp+43−7 plugins/Unity/Launcher/launcheritem.h+6−2 plugins/Unity/Launcher/launchermodel.cpp+51−20 plugins/Unity/Launcher/launchermodel.h+3−1 plugins/Unity/Launcher/quicklistentry.cpp+11 plugins/Unity/Launcher/quicklistentry.h+4 plugins/Unity/Launcher/quicklistmodel.cpp+9 plugins/Unity/Launcher/quicklistmodel.h+1 plugins/Unity/Launcher/ualwrapper.cpp+3−2 plugins/Unity/Launcher/ualwrapper.h+2−1 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+1−1 plugins/Unity/Session/dbusunitysessionservice.cpp+75−4 plugins/Unity/Session/dbusunitysessionservice.h+18−4 plugins/Unity/Session/plugin.cpp+1 plugins/Utils/CMakeLists.txt+6−4 plugins/Utils/URLDispatcher.cpp+5−2 plugins/Utils/WindowInputMonitor.cpp+3 plugins/Utils/appdrawerproxymodel.cpp+4−4 plugins/Utils/deviceconfigparser.cpp+18 plugins/Utils/deviceconfigparser.h+3 plugins/Utils/expressionfiltermodel.cpp+49 plugins/Utils/expressionfiltermodel.h+42 plugins/Utils/plugin.cpp+7−1 plugins/Utils/quicklistproxymodel.cpp+72 plugins/Utils/quicklistproxymodel.h+52 plugins/Utils/tabfocusfence.cpp+72 plugins/Utils/tabfocusfence.h+38 plugins/Utils/windowstatestorage.cpp+294−125 plugins/Utils/windowstatestorage.h+14−15 plugins/WindowManager/AvailableDesktopArea.cpp+50 plugins/Unity/DashCommunicator/dashcommunicator.h → plugins/WindowManager/AvailableDesktopArea.h+14−21 plugins/WindowManager/CMakeLists.txt+11−1 plugins/WindowManager/InputMethodManager.cpp+56 plugins/WindowManager/InputMethodManager.h+55 plugins/WindowManager/TopLevelWindowModel.cpp+197−83 plugins/WindowManager/TopLevelWindowModel.h+58−10 plugins/WindowManager/Window.cpp+41−1 plugins/WindowManager/Window.h+18−3 qml/Dash/DashBackground.qml → plugins/WindowManager/WindowManagerGlobal.h+7−5 plugins/WindowManager/WindowManagerPlugin.cpp+14−1 plugins/WindowManager/WindowMargins.cpp+74 plugins/WindowManager/WindowMargins.h+59 plugins/Wizard/CMakeLists.txt+5−2 plugins/Wizard/Changelog.cpp+58 plugins/Wizard/Changelog.h+52 plugins/Wizard/PageList.cpp+6−5 plugins/Wizard/System.cpp+69−7 plugins/Wizard/System.h+17 plugins/Wizard/Utils/CMakeLists.txt+1−1 plugins/Wizard/plugin.cpp+2 plugins/Wizard/test.sh−18 plugins/Wizard/timezonemodel.h+1−1 po/aa.po+231−324 po/am.po+441−365 po/ar.po+474−484 po/ast.po+542−484 po/az.po+238−327 po/be.po+443−492 po/bg.po+215−322 po/bn.po+418−478 po/br.po+385−362 po/bs.po+288−344 po/ca.po+469−387 po/ca@valencia.po+272−349 po/ce.po+189−305 po/ckb.po+209−319 po/co.po+355−335 po/cs.po+537−493 po/cy.po+288−343 po/da.po+364−418 po/de.po+473−391 po/el.po+445−450 po/en_AU.po+524−419 po/en_GB.po+420−359 po/en_US.po+814 po/eo.po+253−331 po/es.po+481−400 po/et.po+189−305 po/eu.po+293−352 po/fa.po+489−383 po/fi.po+454−372 po/fo.po+263−327 po/fr.po+513−430 po/ga.po+281−342 po/gd.po+436−375 po/gl.po+470−387 po/gu.po+814 po/gv.po+229−319 po/he.po+414−473 po/hi.po+203−315 po/hr.po+434−401 po/hu.po+479−401 po/hy.po+319−414 po/ia.po+427−364 po/id.po+271−347 po/is.po+250−342 po/it.po+479−397 po/ja.po+323−398 po/kk.po+841 po/km.po+285−346 po/kn.po+197−315 po/ko.po+427−467 po/ku.po+236−324 po/ky.po+197−315 po/lo.po+196−312 po/lt.po+476−426 po/lv.po+301−359 po/ml.po+210−321 po/mr.po+212−310 po/ms.po+448−433 po/my.po+247−320 po/nb.po+456−376 po/ne.po+193−306 po/nl.po+542−463 po/nn.po+189−305 po/oc.po+381−346 po/or.po+189−305 po/pa.po+297−355 po/pl.po+484−403 po/pt.po+474−393 po/pt_BR.po+408−452 po/ro.po+303−363 po/ru.po+477−389 po/sc.po+904 po/shn.po+189−305 po/si.po+215−324 po/sk.po+467−384 po/sl.po+413−363 po/sq.po+279−329 po/sr.po+428−367 po/sv.po+451−371 po/sw.po+266−336 po/ta.po+209−320 po/te.po+217−319 po/th.po+209−324 po/tr.po+485−372 po/ug.po+341−360 po/uk.po+430−372 po/unity8.pot+185−302 po/update-unity-pot+17 po/ur.po+210−323 po/uz.po+189−305 po/vi.po+189−305 po/wo.po+297−356 po/xh.po+189−305 po/zh_CN.po+466−384 po/zh_HK.po+226−320 po/zh_TW.po+475−433 qml/ApplicationMenus/ApplicationMenuItemFactory.qml+7−7 qml/Dash/Previews/PreviewSingleton/PreviewSingleton.qml → qml/ApplicationMenus/ApplicationMenusLimits.qml+5−3 qml/ApplicationMenus/MenuBar.qml+343−134 qml/ApplicationMenus/MenuItem.qml+17−21 qml/ApplicationMenus/MenuNavigator.qml+23 qml/ApplicationMenus/MenuPopup.qml+284−135 qml/ApplicationMenus/RegisteredApplicationMenuModel.qml+1−1 qml/ApplicationMenus/qmldir+1 qml/CMakeLists.txt−1 qml/Components/Background.qml+1−1 qml/Components/BaseCarouselDelegate.qml−42 qml/Components/Carousel.qml−335 qml/Components/Dialogs.qml+90−27 qml/Components/EdgeBarrier.qml+1 qml/Components/EdgeBarrierController.qml+1 qml/Panel/Handle.qml → qml/Components/Handle.qml+1 qml/Components/InputMethod.qml+2−1 qml/Components/ItemGrabber.qml+1−1 qml/Components/KeyboardShortcutsOverlay.qml+17−28 qml/Components/KeymapSwitcher.qml+15−7 qml/Components/Lockscreen.qml+5−1 qml/Components/ModeSwitchWarningDialog.qml+8−2 qml/Components/PhysicalKeysMapper.qml+4−4 qml/Components/ResponsiveGridView.qml−98 qml/Components/ResponsiveVerticalJournal.qml−81 qml/Components/ShellDialog.qml+27−12 qml/Components/Showable.qml+15−12 qml/Components/Wallpaper.qml+68−16 qml/Components/WallpaperResolver.qml+17−6 qml/Components/WindowControlButtons.qml+2−21 qml/Dash/CardCarousel.qml−74 qml/Dash/CardGrid.qml−84 qml/Dash/CardHorizontalList.qml−66 qml/Dash/CardTool.qml−298 qml/Dash/CardVerticalJournal.qml−85 qml/Dash/Dash.qml−381 qml/Dash/DashCategoryBase.qml−54 qml/Dash/DashContent.qml−211 qml/Dash/DashContentTabBarStyle.qml−24 qml/Dash/DashNavigation.qml−199 qml/Dash/DashNavigationHeader.qml−73 qml/Dash/DashNavigationList.qml−118 qml/Dash/DashPageHeader.qml−448 qml/Dash/DashRenderer.qml−66 qml/Dash/DashSectionHeader.qml−64 qml/Dash/Filters/FilterExpandableWidget.qml−97 qml/Dash/Filters/FilterOptionSelector.qml−97 qml/Dash/Filters/FilterRangeInput.qml−136 qml/Dash/Filters/FilterValueSlider.qml−87 qml/Dash/Filters/FilterWidget.qml−32 qml/Dash/Filters/FilterWidgetFactory.qml−89 qml/Dash/FiltersPopover.qml−106 qml/Dash/GenericScopeView.qml−797 qml/Dash/PageHeaderExtraPanel.qml−201 qml/Dash/PreviewView.qml−76 qml/Dash/Previews/Preview.qml−145 qml/Dash/Previews/PreviewActionButton.qml−27 qml/Dash/Previews/PreviewActionCombo.qml−79 qml/Dash/Previews/PreviewActions.qml−73 qml/Dash/Previews/PreviewAudioPlayback.qml−152 qml/Dash/Previews/PreviewComment.qml−86 qml/Dash/Previews/PreviewCommentInput.qml−88 qml/Dash/Previews/PreviewExpandable.qml−104 qml/Dash/Previews/PreviewHeader.qml−170 qml/Dash/Previews/PreviewIconActions.qml−88 qml/Dash/Previews/PreviewImageGallery.qml−150 qml/Dash/Previews/PreviewInlineVideo.qml−112 qml/Dash/Previews/PreviewMediaToolbar.qml−57 qml/Dash/Previews/PreviewOverlay.qml−166 qml/Dash/Previews/PreviewProgress.qml−74 qml/Dash/Previews/PreviewRatingDisplay.qml−117 qml/Dash/Previews/PreviewRatingEdit.qml−83 qml/Dash/Previews/PreviewRatingInput.qml−207 qml/Dash/Previews/PreviewRatingSingleDisplay.qml−73 qml/Dash/Previews/PreviewSingleton/qmldir−1 qml/Dash/Previews/PreviewTable.qml−91 qml/Dash/Previews/PreviewTextSummary.qml−78 qml/Dash/Previews/PreviewVideoPlayback.qml−87 qml/Dash/Previews/PreviewWidget.qml−60 qml/Dash/Previews/PreviewWidgetFactory.qml−101 qml/Dash/Previews/PreviewZoomableImage.qml−103 qml/Dash/ScopeListView.qml−28 qml/Dash/ScopeSettings/ScopeSetting.qml−46 qml/Dash/ScopeSettings/ScopeSettingBoolean.qml−63 qml/Dash/ScopeSettings/ScopeSettingList.qml−50 qml/Dash/ScopeSettings/ScopeSettingNumber.qml−21 qml/Dash/ScopeSettings/ScopeSettingString.qml−89 qml/Dash/ScopeSettings/ScopeSettingsWidgetFactory.qml−61 qml/Dash/ScopeSettingsPage.qml−72 qml/Dash/ScopesList.qml−206 qml/Dash/ScopesListCategory.qml−184 qml/Dash/ScopesListCategoryItem.qml−113 qml/Dash/graphics/dark_background.jpg 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/overview_hint@30.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/rectangular_dropshadow@30.png qml/Dash/graphics/rectangular_dropshadow@30.sci−5 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+12 qml/Greeter/ButtonPrompt.qml+51 qml/Greeter/CoverPage.qml+32−11 qml/Greeter/Greeter.qml+51−16 qml/Greeter/GreeterPrompt.qml+66−168 qml/Greeter/GreeterView.qml+534 qml/Greeter/LoginAreaContainer.qml+3−3 qml/Greeter/LoginList.qml+79−86 qml/Greeter/NarrowView.qml−277 qml/Greeter/PinPrompt.qml+184 qml/Greeter/PromptList.qml+21−18 qml/Greeter/SessionsList.qml+36−18 qml/Greeter/ShimGreeter.qml+2 qml/Greeter/TextPrompt.qml+198 qml/Greeter/WideView.qml−205 qml/Launcher/Drawer.qml+286−179 qml/Launcher/DrawerGridView.qml+44−6 qml/Launcher/Launcher.qml+95−52 qml/Launcher/LauncherDelegate.qml+9−12 qml/Launcher/LauncherPanel.qml+61−22 qml/Launcher/MoreAppsHeader.qml−46 qml/Dash/PullToRefreshScopeStyle.qml → qml/Launcher/PullToRefreshScopeStyle.qml qml/Launcher/graphics/home.svg+243 qml/Launcher/graphics/home@18.png qml/Launcher/graphics/launcher-app-focus-ring.svg−12 qml/Notifications/Notification.qml+8−3 qml/Notifications/NotificationButton.qml+2−1 qml/Notifications/SwipeToAct.qml+4 qml/OrientedShell.qml+20−7 qml/Panel/ActiveCallHint.qml+3 qml/Panel/Indicators/IndicatorItem.qml+14−2 qml/Panel/Indicators/IndicatorMenuItemFactory.qml+3−3 qml/Panel/Indicators/IndicatorsLight.qml+185−12 qml/Panel/Indicators/client/IndicatorRepresentation.qml+18−5 qml/Panel/MenuContent.qml+5−2 qml/Panel/Panel.qml+103−30 qml/Panel/PanelBar.qml+28−10 qml/Panel/PanelItemRow.qml+41−33 qml/Panel/PanelMenu.qml+61−29 qml/Panel/PanelMenuPage.qml+4−3 qml/Rotation/RotationStates.qml−3 qml/ScopeTool.qml−165 qml/Shell.qml+215−69 qml/Stage/AbstractStage.qml−93 qml/Stage/ApplicationWindow.qml+16−4 qml/Stage/ChildWindow.qml+203 qml/Stage/ChildWindowRepeater.qml+39 qml/Stage/ChildWindowTree.qml+138 qml/Stage/DecoratedWindow.qml+64−53 qml/Stage/DesktopSpread.qml−576 qml/Stage/DesktopSpreadDelegate.qml−126 qml/Stage/MoveHandler.qml+43−30 qml/Stage/PhoneStage.qml−806 qml/Stage/SideStage.qml+10−6 qml/Stage/Splash.qml+4−4 qml/Stage/Spread/Spread.qml+11 qml/Stage/SpreadDelegate.qml−424 qml/Stage/SpreadMaths.qml−164 qml/Stage/Stage.qml+404−150 qml/Stage/StageMaths.qml+21−2 qml/Stage/StagedFullscreenPolicy.qml+5−11 qml/Stage/TabletStage.qml−1201 qml/Stage/TransformedSpreadDelegate.qml−391 qml/Stage/TransformedTabletSpreadDelegate.qml−437 qml/Stage/WindowControlsOverlay.qml+21−24 qml/Stage/WindowDecoration.qml+19−16 qml/Stage/WindowInfoItem.qml+16 qml/Stage/WindowResizeArea.qml+15−2 qml/Stage/WindowStateSaver.qml+4−3 qml/Stage/WindowedFullscreenPolicy.qml+4−12 qml/Tutorial/Tutorial.qml+1 qml/Tutorial/TutorialContent.qml+61−43 qml/Tutorial/TutorialLeft.qml+1−1 qml/Tutorial/TutorialLeftLong.qml+2−2 qml/Tutorial/TutorialRight.qml+2−3 qml/Tutorial/TutorialTop.qml+2−2 qml/Wizard/Components/InputMethod.qml+9−9 qml/Wizard/Page.qml+15 qml/Wizard/Pages.qml+90−16 qml/Wizard/Pages/10-welcome-update.qml+137 qml/Wizard/Pages/10-welcome.qml+3 qml/Wizard/Pages/11-changelog.qml+95 qml/Wizard/Pages/30-wifi.qml+13−10 qml/Wizard/Pages/40-location.qml−290 qml/Wizard/Pages/50-timezone.qml+11−12 qml/Wizard/Pages/60-account.qml+12−10 qml/Wizard/Pages/70-passwd-type.qml+1 qml/Wizard/Pages/75-report-check.qml−91 qml/Wizard/Pages/78-firmware-update.qml.disabled+246 qml/Wizard/Pages/77-system-update.qml → qml/Wizard/Pages/79-system-update.qml+4−12 qml/Wizard/Pages/80-finished.qml+4−2 qml/Wizard/Pages/here-terms.qml−126 qml/Wizard/Pages/passcode-desktop.qml+14−5 qml/Wizard/Pages/password-set.qml+12−4 qml/Wizard/Wizard.qml+5−2 src/ApplicationArguments.h+5 src/CMakeLists.txt+7−5 src/Dash/CMakeLists.txt−29 src/Dash/main.cpp−146 src/MouseTouchAdaptor.cpp+28−1 src/MouseTouchAdaptor.h+1 src/Panel/CMakeLists.txt−3 src/Panel/Indicators/CMakeLists.txt−1 src/ShellApplication.cpp+19−4 src/ShellApplication.h+1−3 src/ShellView.cpp+22 src/libunity8-private/CMakeLists.txt+1−1 src/main.cpp+9−1 tests/CMakeLists.txt+15−4 tests/autopilot/unity8/dash.py−263 tests/autopilot/unity8/shell/fixture_setup.py+1−27 tests/autopilot/unity8/shell/tests/test_helpers.py−123 tests/autopilot/unity8/shell/tests/test_rotation.py+3−3 tests/copyright/check_copyright.sh+35−4 tests/data/unity/backgrounds/20x30.png tests/data/unity/backgrounds/black.png tests/imports/CMakeLists.txt+1−1 tests/mocks/AccountsService/AccountsService.cpp−36 tests/mocks/AccountsService/AccountsService.h−20 tests/mocks/AccountsService/CMakeLists.txt+1−2 tests/mocks/Biometryd/CMakeLists.txt+1−1 tests/mocks/Biometryd/MockOperation.h−1 tests/mocks/CMakeLists.txt+1−1 tests/mocks/GSettings.1.0/CMakeLists.txt+1−2 tests/mocks/GSettings.1.0/fake_gsettings.cpp+25−27 tests/mocks/GSettings.1.0/fake_gsettings.h+9−9 tests/mocks/LightDMController/CMakeLists.txt+1−2 tests/mocks/Lights/CMakeLists.txt+1−1 tests/mocks/MeeGo/QOfono/CMakeLists.txt+1−1 tests/mocks/Powerd/CMakeLists.txt+1−1 tests/mocks/QMenuModel/CMakeLists.txt+1−2 tests/mocks/QMenuModel/unitymenumodel.cpp+28−4 tests/mocks/QMenuModel/unitymenumodel.h+9 tests/mocks/QtMultimedia/CMakeLists.txt+1−1 tests/mocks/SessionBroadcast/CMakeLists.txt+1−1 tests/mocks/UInput/CMakeLists.txt+1−1 tests/mocks/Ubuntu/CMakeLists.txt−1 tests/mocks/Ubuntu/Connectivity/CMakeLists.txt+1−1 tests/mocks/Ubuntu/Connectivity/networking-status.cpp+7−1 tests/mocks/Ubuntu/Connectivity/networking-status.h+5−3 tests/mocks/Ubuntu/DownloadDaemonListener/CMakeLists.txt+1−1 tests/mocks/Ubuntu/SystemImage/CMakeLists.txt−10 tests/mocks/Ubuntu/SystemImage/MockSystemImage.cpp−50 tests/mocks/Ubuntu/SystemImage/MockSystemImage.h−56 tests/mocks/Ubuntu/SystemImage/plugin.h−31 tests/mocks/Ubuntu/SystemImage/qmldir−3 tests/mocks/Ubuntu/SystemSettings/CMakeLists.txt+1 tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/CMakeLists.txt+1−1 tests/mocks/Ubuntu/SystemSettings/Update/CMakeLists.txt+1 qml/Launcher/DrawerListView.qml → tests/mocks/Ubuntu/SystemSettings/Update/MockSystemImage.qml+11−13 tests/mocks/Ubuntu/SystemSettings/Update/qmldir+2 tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−1 tests/mocks/Unity/Application/ApplicationInfo.cpp+16−5 tests/mocks/Unity/Application/ApplicationInfo.h+5−6 tests/mocks/Unity/Application/ApplicationManager.cpp+29−8 tests/mocks/Unity/Application/ApplicationManager.h+1−6 tests/mocks/Unity/Application/CMakeLists.txt+2−2 tests/mocks/Unity/Application/MirMock.cpp+13 tests/mocks/Unity/Application/MirMock.h+4 tests/mocks/Unity/Application/MirSurface.cpp+52 tests/mocks/Unity/Application/MirSurface.h+16 tests/mocks/Unity/Application/MirSurfaceItem.cpp+19−4 tests/mocks/Unity/Application/MirSurfaceListModel.cpp+7−7 tests/mocks/Unity/Application/MirSurfaceListModel.h+7−10 tests/mocks/Unity/Application/SurfaceManager.cpp+19−13 tests/mocks/Unity/Application/SurfaceManager.h+3−1 tests/mocks/Unity/Application/VirtualKeyboard.cpp+5−4 tests/mocks/Unity/Application/resources/Kate.qml+49 tests/mocks/Unity/Application/resources/KateDialog.qml+48 qml/Dash/DashApplication.qml → tests/mocks/Unity/Application/resources/KateMenu.qml+17−15 tests/mocks/Unity/Application/resources/surfaces.qrc+3 tests/mocks/Unity/ApplicationMenu/CMakeLists.txt+1−1 tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.cpp+2−2 tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.h+1−1 tests/mocks/Unity/CMakeLists.txt−66 tests/mocks/Unity/Connectivity/CMakeLists.txt+1−1 tests/mocks/Unity/DashCommunicator/CMakeLists.txt−18 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+1−2 tests/mocks/Unity/Indicators/IndicatorsModel.qml+30−12 tests/mocks/Unity/Indicators/fakeindicatorsmodeldata.js+22−5 tests/mocks/Unity/InputInfo/CMakeLists.txt+1−1 tests/mocks/Unity/Launcher/CMakeLists.txt+1−3 tests/mocks/Unity/Launcher/MockAppDrawerModel.cpp+27−4 tests/mocks/Unity/Launcher/MockAppDrawerModel.h+11 tests/mocks/Unity/Launcher/MockLauncherItem.cpp+13 tests/mocks/Unity/Launcher/MockLauncherItem.h+3 tests/mocks/Unity/Launcher/MockLauncherModel.cpp+1−1 tests/mocks/Unity/Launcher/MockLauncherModel.h+1−1 tests/mocks/Unity/Launcher/MockQuickListModel.cpp+3−1 tests/mocks/Unity/Launcher/MockQuickListModel.h+2 tests/mocks/Unity/Notifications/CMakeLists.txt+1−1 tests/mocks/Unity/Screens/CMakeLists.txt+1−1 tests/mocks/Unity/fake_categories.cpp−165 tests/mocks/Unity/fake_categories.h−54 tests/mocks/Unity/fake_expandablefilterwidget.cpp−53 tests/mocks/Unity/fake_expandablefilterwidget.h−48 tests/mocks/Unity/fake_filters.cpp−136 tests/mocks/Unity/fake_filters.h−46 tests/mocks/Unity/fake_navigation.cpp−123 tests/mocks/Unity/fake_navigation.h−61 tests/mocks/Unity/fake_optionselectorfilter.cpp−70 tests/mocks/Unity/fake_optionselectorfilter.h−54 tests/mocks/Unity/fake_optionselectoroptions.cpp−90 tests/mocks/Unity/fake_optionselectoroptions.h−49 tests/mocks/Unity/fake_previewmodel.cpp−103 tests/mocks/Unity/fake_previewmodel.h−58 tests/mocks/Unity/fake_previewwidgetmodel.cpp−97 tests/mocks/Unity/fake_previewwidgetmodel.h−47 tests/mocks/Unity/fake_rangeinputfilter.cpp−167 tests/mocks/Unity/fake_rangeinputfilter.h−79 tests/mocks/Unity/fake_resultsmodel.cpp−92 tests/mocks/Unity/fake_resultsmodel.h−52 tests/mocks/Unity/fake_scope.cpp−372 tests/mocks/Unity/fake_scope.h−128 tests/mocks/Unity/fake_scopes.cpp−287 tests/mocks/Unity/fake_scopes.h−83 tests/mocks/Unity/fake_scopesoverview.cpp−340 tests/mocks/Unity/fake_scopesoverview.h−119 tests/mocks/Unity/fake_settingsmodel.cpp−95 tests/mocks/Unity/fake_settingsmodel.h−54 tests/mocks/Unity/fake_unity_plugin.cpp−62 tests/mocks/Unity/fake_unity_plugin.h−34 tests/mocks/Unity/fake_valuesliderfilter.cpp−84 tests/mocks/Unity/fake_valuesliderfilter.h−55 tests/mocks/Unity/fake_valueslidervalues.cpp−51 tests/mocks/Unity/qmldir−3 tests/mocks/Utils/CMakeLists.txt+8−3 tests/mocks/Utils/plugin.cpp+7−1 tests/mocks/Wizard/CMakeLists.txt+2−2 tests/mocks/Wizard/MockSystem.cpp+19−4 tests/mocks/Wizard/MockSystem.h+11−1 tests/mocks/Wizard/mockplugin.cpp+2 tests/mocks/liblightdm/CMakeLists.txt+1−1 tests/mocks/liblightdm/MockController.cpp+2−25 tests/mocks/liblightdm/MockController.h−15 tests/mocks/liblightdm/MockUsersModel.cpp+2−2 tests/mocks/liblightdm/demo/CMakeLists.txt+1−1 tests/mocks/libusermetrics/CMakeLists.txt+1−1 tests/plugins/AccountsService/CMakeLists.txt+2−2 tests/plugins/AccountsService/PropertiesServer.cpp+1−1 tests/plugins/AccountsService/client.cpp+6−34 tests/plugins/CMakeLists.txt+2−3 tests/plugins/Dash/CMakeLists.txt−104 tests/plugins/Dash/cardcreator/1.res−82 tests/plugins/Dash/cardcreator/1.res.cardcreator−69 tests/plugins/Dash/cardcreator/1.tst−4 tests/plugins/Dash/cardcreator/10.res−129 tests/plugins/Dash/cardcreator/10.res.cardcreator−127 tests/plugins/Dash/cardcreator/10.tst−4 tests/plugins/Dash/cardcreator/11.res−176 tests/plugins/Dash/cardcreator/11.res.cardcreator−160 tests/plugins/Dash/cardcreator/11.tst−4 tests/plugins/Dash/cardcreator/12.res−108 tests/plugins/Dash/cardcreator/12.res.cardcreator−95 tests/plugins/Dash/cardcreator/12.tst−4 tests/plugins/Dash/cardcreator/2.res−128 tests/plugins/Dash/cardcreator/2.res.cardcreator−126 tests/plugins/Dash/cardcreator/2.tst−4 tests/plugins/Dash/cardcreator/3.res−90 tests/plugins/Dash/cardcreator/3.res.cardcreator−86 tests/plugins/Dash/cardcreator/3.tst−4 tests/plugins/Dash/cardcreator/4.res−111 tests/plugins/Dash/cardcreator/4.res.cardcreator−99 tests/plugins/Dash/cardcreator/4.tst−4 tests/plugins/Dash/cardcreator/5.res−102 tests/plugins/Dash/cardcreator/5.res.cardcreator−99 tests/plugins/Dash/cardcreator/5.tst−4 tests/plugins/Dash/cardcreator/6.res−127 tests/plugins/Dash/cardcreator/6.res.cardcreator−116 tests/plugins/Dash/cardcreator/6.tst−4 tests/plugins/Dash/cardcreator/7.res−141 tests/plugins/Dash/cardcreator/7.res.cardcreator−139 tests/plugins/Dash/cardcreator/7.tst−4 tests/plugins/Dash/cardcreator/8.res−109 tests/plugins/Dash/cardcreator/8.res.cardcreator−97 tests/plugins/Dash/cardcreator/8.tst−4 tests/plugins/Dash/cardcreator/9.res−120 tests/plugins/Dash/cardcreator/9.res.cardcreator−109 tests/plugins/Dash/cardcreator/9.tst−4 tests/plugins/Dash/cardcreatortest.cpp−126 tests/plugins/Dash/cardcreatortest.qml−29 tests/plugins/Dash/horizontaljournaltest.cpp−490 tests/plugins/Dash/horizontaljournaltest.qml−44 tests/plugins/Dash/horizontaljournaltry.cpp−91 tests/plugins/Dash/horizontaljournaltry.qml−120 tests/plugins/Dash/listviewwithpageheadersectionexternalmodeltest.cpp−246 tests/plugins/Dash/listviewwithpageheadersectiontest.cpp−2212 tests/plugins/Dash/listviewwithpageheadertest.cpp−2038 tests/plugins/Dash/listviewwithpageheadertest.qml−96 tests/plugins/Dash/listviewwithpageheadertestsection.qml−119 tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qml−76 tests/plugins/Dash/organicgridtest.cpp−533 tests/plugins/Dash/organicgridtest.qml−44 tests/plugins/Dash/organicgridtry.cpp−99 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−140 tests/plugins/Dash/tst_ScopeStyle.qml−188 tests/plugins/Dash/verticaljournaltest.cpp−564 tests/plugins/Dash/verticaljournaltest.qml−45 tests/plugins/Dash/verticaljournaltry.cpp−91 tests/plugins/Dash/verticaljournaltry.qml−121 tests/plugins/GlobalShortcut/CMakeLists.txt+1−2 tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt+1−3 tests/plugins/ImageCache/CMakeLists.txt−30 tests/plugins/ImageCache/graphics/wide.jpg tests/plugins/ImageCache/test.cpp−216 tests/plugins/ImageCache/test.qml−23 tests/plugins/LightDM/IntegratedLightDM/CMakeLists.txt+6−6 tests/plugins/LightDM/IntegratedLightDM/dbus.cpp+18−5 tests/plugins/LightDM/IntegratedLightDM/sessionsmodel.cpp+4 tests/plugins/LightDM/IntegratedLightDM/usersmodel.cpp+13 tests/plugins/SessionBroadcast/CMakeLists.txt+2−2 tests/plugins/Ubuntu/Gestures/CMakeLists.txt+4−2 tests/plugins/Ubuntu/Gestures/GestureTest.cpp+10−1 tests/plugins/Ubuntu/Gestures/tst_TouchGate.cpp+11−2 tests/plugins/Ubuntu/Gestures/tst_TouchGestureArea.cpp+30 tests/plugins/Unity/CMakeLists.txt+1 tests/plugins/Unity/Indicators/CMakeLists.txt+1−1 tests/plugins/Unity/Launcher/CMakeLists.txt+39−2 tests/plugins/Unity/Launcher/appdrawermodeltest.cpp+68 tests/plugins/Unity/Launcher/launchermodeltest.cpp+86−7 tests/plugins/Unity/Launcher/ualwrapper.cpp+58 tests/plugins/Unity/Launcher/ualwrapper.h+55 tests/mocks/Ubuntu/SystemImage/plugin.cpp → tests/plugins/Unity/Launcher/xdgwatcher.cpp+22−11 tests/mocks/Unity/fake_valueslidervalues.h → tests/plugins/Unity/Launcher/xdgwatcher.h+16−13 tests/plugins/Unity/Platform/CMakeLists.txt+30 tests/plugins/Unity/Platform/platformtest.cpp+142 tests/plugins/Unity/Session/CMakeLists.txt+15−3 tests/plugins/Unity/Session/LogindServer.cpp+10 tests/plugins/Unity/Session/LogindServer.h+5 tests/plugins/Unity/Session/interfaces.xml+12 tests/plugins/Unity/Session/preload.c+43 tests/plugins/Unity/Session/sessionbackendtest.cpp+130−11 tests/plugins/Utils/CMakeLists.txt+6−5 tests/plugins/Utils/DeviceConfigParserTest.cpp+3 tests/plugins/Utils/ModelTest.cpp+2−1 tests/plugins/Utils/WindowInputMonitorTest.cpp+31−1 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+2−2 tests/qmltests/ApplicationMenuDataLoader.qml+30−6 tests/qmltests/ApplicationMenus/tst_MenuBar.qml+263−9 tests/qmltests/ApplicationMenus/tst_MenuPopup.qml+209−55 tests/qmltests/CMakeLists.txt+5−51 tests/qmltests/Components/CMakeLists.txt+8−4 tests/qmltests/Components/tst_Carousel.qml−292 tests/qmltests/Components/tst_Dialogs.qml−1 tests/qmltests/Components/tst_DragHandle.cpp+19−2 tests/qmltests/Components/tst_DraggingArea.qml+6−6 tests/qmltests/Components/tst_Lockscreen.qml+11−9 tests/qmltests/Components/tst_MediaServices.qml+5−4 tests/qmltests/Components/tst_PhysicalKeysMapper.qml+7−6 tests/qmltests/Components/tst_Rating.qml+1−1 tests/qmltests/Components/tst_ResponsiveGridView.qml−157 tests/qmltests/Components/tst_ResponsiveVerticalJournal.qml−183 tests/qmltests/Components/tst_SharingPicker.qml+3−3 tests/qmltests/Components/tst_Showable.qml+13 tests/qmltests/Components/tst_Wallpaper.qml+118 tests/qmltests/Components/tst_WallpaperResolver.qml+104−18 tests/qmltests/Dash/CardHelpers.js−115 tests/qmltests/Dash/Filters/tst_FilterExpandableWidget.qml−99 tests/qmltests/Dash/Filters/tst_FilterOptionSelector.qml−96 tests/qmltests/Dash/Filters/tst_FilterRangeInput.qml−247 tests/qmltests/Dash/Filters/tst_FilterValueSlider.qml−101 tests/qmltests/Dash/Filters/tst_FilterWidgetFactory.qml−59 tests/qmltests/Dash/Previews/MockPreviewWidget.qml−27 tests/qmltests/Dash/Previews/tst_Preview.qml−214 tests/qmltests/Dash/Previews/tst_PreviewActions.qml−262 tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml−182 tests/qmltests/Dash/Previews/tst_PreviewComment.qml−84 tests/qmltests/Dash/Previews/tst_PreviewCommentInput.qml−113 tests/qmltests/Dash/Previews/tst_PreviewExpandable.qml−353 tests/qmltests/Dash/Previews/tst_PreviewHeader.qml−183 tests/qmltests/Dash/Previews/tst_PreviewIconActions.qml−136 tests/qmltests/Dash/Previews/tst_PreviewImageGallery.qml−147 tests/qmltests/Dash/Previews/tst_PreviewInlineVideo.qml−155 tests/qmltests/Dash/Previews/tst_PreviewMediaToolbar.qml−69 tests/qmltests/Dash/Previews/tst_PreviewProgress.qml−100 tests/qmltests/Dash/Previews/tst_PreviewRatingDisplay.qml−123 tests/qmltests/Dash/Previews/tst_PreviewRatingDisplayCreationRanges.qml−131 tests/qmltests/Dash/Previews/tst_PreviewRatingEdit.qml−87 tests/qmltests/Dash/Previews/tst_PreviewRatingInput.qml−246 tests/qmltests/Dash/Previews/tst_PreviewTable.qml−147 tests/qmltests/Dash/Previews/tst_PreviewTextSummary.qml−87 tests/qmltests/Dash/Previews/tst_PreviewVideoPlayback.qml−61 tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml−104 tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qml−138 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−682 tests/qmltests/Dash/tst_CardBenchmark.qml−95 tests/qmltests/Dash/tst_CardCarousel.qml−111 tests/qmltests/Dash/tst_CardTool.qml−379 tests/qmltests/Dash/tst_Dash.qml−695 tests/qmltests/Dash/tst_DashContent.qml−730 tests/qmltests/Dash/tst_DashPageHeader.qml−357 tests/qmltests/Dash/tst_DashShell.qml−124 tests/qmltests/Dash/tst_GenericScopeView.qml−722 tests/qmltests/Dash/tst_PageHeader/logo-ubuntu-orange.svg−60 tests/qmltests/Dash/tst_PreviewView.qml−122 tests/qmltests/Greeter/TestView.qml+9−6 tests/qmltests/Greeter/tst_Greeter.qml+19−31 tests/qmltests/Greeter/tst_GreeterView.qml+1366 tests/qmltests/Greeter/tst_NarrowView.qml−566 tests/qmltests/Greeter/tst_WideView.qml−781 tests/qmltests/Launcher/tst_Drawer.qml+269−13 tests/qmltests/Launcher/tst_Launcher.qml+255−81 tests/qmltests/Notifications/tst_Notifications.qml+16−10 tests/qmltests/Notifications/tst_OptionToggle.qml+12−6 tests/qmltests/Notifications/tst_SwipeToAct.qml+10−3 tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+3−3 tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml+33−79 tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qml+168−8 tests/qmltests/Panel/PanelUI.qml+286 tests/qmltests/Panel/tst_ActiveCallHint.qml+14−9 tests/qmltests/Panel/tst_MenuContent.qml+2−2 tests/qmltests/Panel/tst_Panel.qml+149−253 tests/qmltests/Panel/tst_PanelItemRow.qml+2−2 tests/qmltests/Panel/tst_PanelMenu.qml+61−22 tests/qmltests/Panel/tst_PanelMenuPage.qml+1−1 tests/qmltests/Panel/tst_PanelSmallScreen.qml+133 tests/qmltests/Stage/ApplicationCheckBox.qml+7−7 tests/qmltests/Stage/tst_ApplicationWindow.qml+3−2 tests/qmltests/Stage/tst_DesktopStage.qml+280−29 tests/qmltests/Stage/tst_PhoneStage.qml+95−64 tests/qmltests/Stage/tst_QMLTopLevelWindowModel.qml+191 tests/qmltests/Stage/tst_SpreadDelegate.qml−423 tests/qmltests/Stage/tst_SurfaceContainer.qml+9−8 tests/qmltests/Stage/tst_TabletStage.qml+137−139 tests/qmltests/Stage/tst_WindowDecoration.qml+3−3 tests/qmltests/Stage/tst_WindowResizeArea.qml+14−3 tests/qmltests/Tutorial/tst_Tutorial.qml+189−190 tests/qmltests/Wizard/tst_Wizard.qml+100−142 tests/qmltests/tst_OrientedShell.qml+398−262 tests/qmltests/tst_Shell.qml+1144−566 tests/qmltests/tst_ShellWithPin.qml+113−118 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+1−1 tests/utils/modules/Unity/Test/CMakeLists.txt+2−4 tests/utils/modules/Unity/Test/MouseTouchEmulationCheckbox.qml+1−1 tests/utils/modules/Unity/Test/StageTestCase.qml+14−18 tests/utils/modules/Unity/Test/TouchEventSequenceWrapper.cpp+10−1 tests/utils/modules/Unity/Test/UnityTestCase.qml+2−11 tools/CMakeLists.txt+2−12 src/Panel/Indicators/client/CMakeLists.txt → tools/indicatorsclient/CMakeLists.txt+1−1 src/Panel/Indicators/client/indicatorsclient.cpp → tools/indicatorsclient/indicatorsclient.cpp src/Panel/Indicators/client/indicatorsclient.h → tools/indicatorsclient/indicatorsclient.h src/Panel/Indicators/client/main.cpp → 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−116 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
.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+10−3
@@ -69,15 +69,24 @@ find_package(Qt5Gui 5.6 REQUIRED)
6969find_package(Qt5DBus 5.6 REQUIRED)
7070find_package(Qt5Concurrent 5.6 REQUIRED)
7171find_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)
7276
73−pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=23)
77+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=27)
7478pkg_check_modules(GEONAMES REQUIRED geonames>=0.2)
7579pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
7680pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
81+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=13)
7782pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
7883pkg_check_modules(GD3 REQUIRED gnome-desktop-3.0)
7984pkg_check_modules(UAL REQUIRED ubuntu-app-launch-2)
8085pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
86+pkg_check_modules(QTDBUSTEST REQUIRED
87+ libqtdbustest-1
88+ libqtdbusmock-1
89+ )
8190
8291### Check UbuntuGestures private headers. No pkg-config (.pc) file is provided for them
8392find_path(UBUNTUGESTUREPRIV
@@ -139,8 +148,6 @@ include(autopilot)
139148declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)
140149
141150set(SHELL_APP unity8)
142−set(DASH_APP unity8-dash)
143−set(SCOPE_TOOL unity-scope-tool)
144151set(INDICATORS_CLIENT_APP indicators-client)
145152set(GREETER_APP unity8-greeter)
146153set(MOCK_INDICATOR_SERVICE_APP unity-mock-indicator-service)
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+16
@@ -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 ))
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+9−4
@@ -201,7 +201,7 @@ function(add_executable_test COMPONENT_NAME TARGET)
201201 add_qmltest_target(xvfbtest${COMPONENT_NAME} ${TARGET}
202202 COMMAND $<TARGET_FILE:xvfb-run> --server-args "-screen 0 1024x768x24" --auto-servernum ${qmltest_command}
203203 ${depends}
204− 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}
205205 TARGETS ${xvfb_targets}
206206 )
207207 endif()
@@ -264,12 +264,16 @@ endfunction()
264264# installed system.
265265
266266function(add_meta_test TARGET_NAME)
267− cmake_parse_arguments(TEST "" "" "DEPENDS" ${ARGN})
267+ cmake_parse_arguments(TEST "SERIAL" "" "DEPENDS" ${ARGN})
268268
269269 add_custom_target(${TARGET_NAME})
270270
271271 set(filename "${CMAKE_BINARY_DIR}/tests/scripts/${TARGET_NAME}.sh")
272− file(WRITE "${filename}" "#!/usr/bin/parallel --shebang --no-notice\n\n")
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()
273277
274278 add_meta_dependencies(${TARGET_NAME} DEPENDS ${TEST_DEPENDS})
275279 # else we will write the rest of the script as we add cmake targets
@@ -307,6 +311,7 @@ function(install_test_script TARGET_NAME)
307311 foreach(ONE_CMD ${TEST_COMMAND})
308312 set(script "${script}'${ONE_CMD}' ")
309313 endforeach()
314+ set(script "${script}\"\$@\"") # Allow passing arguments if desired
310315
311316 set(filename "${CMAKE_BINARY_DIR}/tests/scripts/${TARGET_NAME}.sh")
312317
@@ -370,7 +375,7 @@ function(add_meta_dependencies UPSTREAM_TARGET)
370375 # add depend to the meta test script that we will install on system
371376 set(filename "${CMAKE_BINARY_DIR}/tests/scripts/${UPSTREAM_TARGET}.sh")
372377 if (EXISTS "${filename}")
373− file(APPEND "${filename}" "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}/tests/scripts/${depend}.sh\n")
378+ file(APPEND "${filename}" "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}/tests/scripts/${depend}.sh \"\$@\" 2>&1\n")
374379 endif()
375380 endforeach()
376381endfunction()
data/CMakeLists.txt+1−9
@@ -1,13 +1,11 @@
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)
54configure_file(${GREETER_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${GREETER_APP}.desktop @ONLY)
65
76# install desktop files
87install(FILES
98 ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
10− ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
119 ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop
1210 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
1311 )
@@ -22,14 +20,8 @@ install(FILES
2220 DESTINATION ${CMAKE_INSTALL_DATADIR}/lightdm/lightdm.conf.d
2321 )
2422
25−# install dash icon
26−install(FILES
27− ${CMAKE_CURRENT_SOURCE_DIR}/${DASH_APP}.png
28− DESTINATION ${SHELL_APP_DIR}/Dash/
29− )
30−
3123add_custom_target(pkgversion ALL COMMAND dpkg-parsechangelog -l${CMAKE_SOURCE_DIR}/debian/changelog --show-field version > ${CMAKE_CURRENT_BINARY_DIR}/version)
3224
3325install(FILES com.canonical.Unity8.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
34−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)
3527install(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+17−7
@@ -11,7 +11,7 @@
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">
14+ <key type="u" name="edge-barrier-sensitivity">
1515 <default>50</default>
1616 <range min="1" max="100"/>
1717 <summary>Sensitivity of screen edge barriers for the mouse pointer.</summary>
@@ -33,7 +33,7 @@
3333 <description>How big (in grid units) the edge-drag sensitive area should be.</description>
3434 </key>
3535 <key type="b" name="autohide-launcher">
36− <default>true</default>
36+ <default>false</default>
3737 <summary>Autohide the launcher</summary>
3838 <description>This will only be applied in windowed mode. In staged mode, the launcher will always hide.</description>
3939 </key>
@@ -43,16 +43,26 @@
4343 <summary>Width of the launcher in grid units.</summary>
4444 <description>Changes the width of the launcher in all usage modes.</description>
4545 </key>
46− <key type="b" name="enable-launcher">
47− <default>true</default>
48− <summary>Enable or disable the launcher</summary>
49− <description>Toggle the availability of the launcher</description>
50− </key>
5146 <key type="b" name="enable-indicator-menu">
5247 <default>true</default>
5348 <summary>Enable or disable the indicator pull down menus</summary>
5449 <description>Toggle the availability of the indicator pull down menus</description>
5550 </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>
5666 </schema>
5767
5868 <schema path="/com/canonical/unity8/greeter/" id="com.canonical.Unity8.Greeter" gettext-domain="unity8">
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−25
@@ -1,25 +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−respawn limit unlimited
18−
19−env APP_ID=unity8-dash
20−
21−pre-start script
22− initctl emit scope-ui-starting
23−end script
24−
25−exec ${BINARY:-unity8-dash} $ARGS --desktop_file_hint=unity8-dash.desktop
data/unity8-dash.desktop.indeleted−9
@@ -1,9 +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
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-greeter-wrapper+7−4
@@ -49,9 +49,12 @@ if which ubuntu-touch-session >/dev/null; then
4949 TOUCH_WRAPPER=ubuntu-touch-session
5050fi
5151
52−# Pretend that we're in an ubuntu-touch session, so that indicator-network
53−# will start.
54−export DESKTOP_SESSION=ubuntu-touch
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
5558
5659# We disable ofono using pulse. It causes problems with racing with the user's
5760# pulse. We need to come up with a better long-term fix for this, because we
@@ -100,7 +103,7 @@ if [ "$(id -u phablet 2>/dev/null)" = "32011" ]; then
100103fi
101104
102105# And finally actually start the greeter
103−exec env QT_QPA_PLATFORM=ubuntumirclient MIR_SERVER_FILE=$SUB_SOCKET $TOUCH_WRAPPER $@ &
106+exec env MIR_SERVER_FILE=$SUB_SOCKET $TOUCH_WRAPPER $@ &
104107CMD_PID=$!
105108wait $CMD_PID
106109CMD_PID=
data/unity8.conf+35−34
@@ -2,6 +2,7 @@ description "Unity Shell v8"
22author "Ricardo Mendoza <ricmm@ubuntu.com>"
33
44emits indicator-services-start
5+emits indicator-services-end
56
67start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=unity8-mir) or (xsession SESSION=unity8)) and started dbus
78stop on desktop-end
@@ -20,28 +21,32 @@ env QML_NO_TOUCH_COMPRESSION=1
2021respawn
2122expect stop
2223
24+# FIXME Create an autopilot test that makes sure start+stop and restart
25+# work fine at least 2 times
26+
2327pre-start script
2428 # Tell unity-mir to raise SIGSTOP after we start
2529 initctl set-env UNITY_MIR_EMITS_SIGSTOP=1
2630
27− if [ -n "$MIR_SOCKET" ]; then
28− # FIXME Create an autopilot test that makes sure start+stop and restart
29− # work fine at least 2 times
30− # Save original value of MIR_SOCKET in case we are stopped,
31− # as we modify the variable for future jobs, including ourself.
32− UNITY_MIR_SOCKET=$(initctl get-env --global MIR_SOCKET)
33− initctl set-env --global UNITY_MIR_SOCKET=$UNITY_MIR_SOCKET
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
3434
35− # Point unity8 at unity-system-compositor
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
3642 MIR_SERVER_FILE=$XDG_RUNTIME_DIR/mir_socket
37− initctl set-env MIR_SERVER_FILE=$MIR_SERVER_FILE
38− initctl set-env MIR_SERVER_HOST_SOCKET=$UNITY_MIR_SOCKET
39−
40− # Point all future jobs in this session to our Mir socket instead of
41− # unity-system-compositor's socket.
42− initctl set-env --global MIR_SOCKET=$MIR_SERVER_FILE
43− gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}"
4443 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'}"
4550
4651 # Remove the normal and trusted sockets if still there
4752 if [ -S "$MIR_SERVER_FILE" ]; then
@@ -54,11 +59,14 @@ pre-start script
5459
5560 initctl set-env --global MIR_SERVER_PROMPT_FILE=1
5661
57− #
58− # Mir's input resampling is deprecated and going away soon. Turn it off
59− # so we don't get a surprise change in behaviour when that happens.
60− #
61− initctl set-env --global MIR_CLIENT_INPUT_RATE=0
62+ # Disable Qt's stuttering 'touch compression' to fix scrolling smoothness
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
65+ # reduces lag seen in apps:
66+ initctl set-env --global QML_NO_TOUCH_COMPRESSION=1
67+
68+ # Workaround for text not rendering correctly
69+ initctl set-env --global QT_ENABLE_GLYPH_CACHE_WORKAROUND=1
6270
6371 if [ "$XDG_SESSION_DESKTOP" = "ubuntu-touch" ]; then
6472 # On Ubuntu Touch, we currently use a trick where we auto-login the
@@ -69,30 +77,23 @@ pre-start script
6977 else
7078 initctl set-env MODE=full-shell
7179 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
7286end script
7387
7488exec ${BINARY:-unity8} --mode=$MODE $ARGS
7589
7690post-start script
77− # If no MIR_SOCKET was defined on launch, we try to set one here
78− if [ -z "$(initctl get-env --global UNITY_MIR_SOCKET)" ]; then
79− if [ -S "$XDG_RUNTIME_DIR/mir_socket" ]; then
80− mir_socket=$XDG_RUNTIME_DIR/mir_socket
81− elif [ -S "/tmp/mir_socket" ]; then
82− mir_socket=/tmp/mir_socket
83− fi
84−
85− if [ -n "$mir_socket" ]; then
86− initctl set-env --global MIR_SOCKET="$mir_socket"
87− fi
88− fi
89−
9091 initctl emit --no-wait indicator-services-start
9192end script
9293
9394post-stop script
9495 initctl set-env --global MIR_SOCKET=$UNITY_MIR_SOCKET
95− initctl unset-env --global UNITY_MIR_SOCKET
9696 initctl unset-env --global MIR_SERVER_PROMPT_FILE
9797 initctl emit application-end
98+ initctl emit indicator-services-end
9899end script
debian/changelog+341−20
@@ -1,3 +1,319 @@
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+
1317unity8 (8.15+17.04.20170110.4-0ubuntu1) zesty; urgency=medium
2318
3319 [ Albert Astals Cid ]
@@ -908,7 +1224,7 @@ unity8 (8.12+16.04.20160330-0ubuntu1) xenial; urgency=medium
9081224unity8 (8.12+16.04.20160323.2-0ubuntu1) xenial; urgency=medium
9091225
9101226 [ Michael Terry ]
911− *
1227+ *
9121228 * Fix setting OSK layout in OOBE wizard
9131229 * Stop the left edge tutorial from being shown when the bottom edge
9141230 tutorial wants to be shown after receiving a call.
@@ -3620,7 +3936,7 @@ unity8 (8.00+14.10.20140729-0ubuntu1) utopic; urgency=medium
36203936 * Re-architecture unity8 to use the QtMirCompositor library so that
36213937 the Qt scenegraph renderer is used as the Mir compositor, and
36223938 application surfaces are added to the QML scene as items.
3623−
3939+
36243940 [ Michael Zanetti ]
36253941 * Port phone right-edge spread code to use QtCompositor
36263942 * Add right-edge spread animation for tablet
@@ -3894,8 +4210,8 @@ unity8 (7.90+14.10.20140703.1-0ubuntu1) utopic; urgency=low
38944210
38954211unity8 (7.90+14.10.20140701.2-0ubuntu2) utopic; urgency=medium
38964212
3897− * debian/control:
3898− list qtdeclarative5-ubuntu-ui-toolkit-plugin-gles as an alternative
4213+ * debian/control:
4214+ list qtdeclarative5-ubuntu-ui-toolkit-plugin-gles as an alternative
38994215 choice, since provides are not versionned, should restore installability
39004216 on amd64 and i386
39014217
@@ -6997,7 +7313,7 @@ unity8 (7.81.2) saucy; urgency=low
69977313 [ Michał Sawicz ]
69987314 * Fix icons in ApplicationsFilterGrid.qml.
69997315 * Support flipped image in run_on_device.
7000−
7316+
70017317 [ Michael Zanetti ]
70027318 * Don't clear lockscreen when it's fading out.
70037319 * Reworked Launcher folding.
@@ -7082,7 +7398,7 @@ qml-phone-shell (1.79) raring; urgency=low
70827398
70837399 [ Michael Terry ]
70847400 * Make greeter look like the desktop one
7085−
7401+
70867402 [ Gerry Boland ]
70877403 * Fix a bug where a minimized app gets focus after closing another app
70887404 * Applied a workaround to reduce flickering when launching apps
@@ -7098,7 +7414,7 @@ qml-phone-shell (1.79) raring; urgency=low
70987414qml-phone-shell (1.78) raring; urgency=low
70997415
71007416 [ Sergio Schvezov ]
7101− * 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
71027418 the launcher (LP: #1178262).
71037419
71047420 [ Daniel d'Andrada ]
@@ -7140,7 +7456,7 @@ qml-phone-shell (1.77) raring; urgency=low
71407456 [ Mathieu Trudel-Lapierre ]
71417457 * debian/control:
71427458 - Drop indicators-client-plugin* Depends for qml-phone-shell to Recommends.
7143− - 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.
71447460 * debian/copyright: fix syntax.
71457461
71467462 [ Michał Sawicz ]
@@ -7150,7 +7466,7 @@ qml-phone-shell (1.77) raring; urgency=low
71507466 * Renamed Media player files to match with new application name.
71517467
71527468 [ Daniel d'Andrada ]
7153− * New: DirectionalDragArea component. An area that detects axis-aligned
7469+ * New: DirectionalDragArea component. An area that detects axis-aligned
71547470 single-finger drag gestures.
71557471 * Make it possible to send touch events from within QML test code.
71567472
@@ -7587,7 +7903,7 @@ qml-phone-shell (1.39) quantal; urgency=low
75877903
75887904qml-phone-shell (1.38) quantal; urgency=low
75897905
7590− * fix launching of notepad
7906+ * fix launching of notepad
75917907
75927908 -- Bill Filler <bill.filler@canonical.com> Fri, 01 Feb 2013 03:21:29 -0500
75937909
@@ -7600,14 +7916,14 @@ qml-phone-shell (1.37) quantal; urgency=low
76007916
76017917qml-phone-shell (1.36) quantal; urgency=low
76027918
7603− * launch real notepad app
7919+ * launch real notepad app
76047920 * fix launching of mock apps
76057921
76067922 -- Bill Filler <bill.filler@canonical.com> Thu, 31 Jan 2013 21:36:05 -0500
76077923
76087924qml-phone-shell (1.35) quantal; urgency=low
76097925
7610− * integrate ubuntu-browser instead of snowshoe
7926+ * integrate ubuntu-browser instead of snowshoe
76117927
76127928 -- Bill Filler <bill.filler@canonical.com> Thu, 31 Jan 2013 17:33:37 -0500
76137929
@@ -7691,7 +8007,7 @@ qml-phone-shell (1.22) quantal; urgency=low
76918007
76928008qml-phone-shell (1.21) quantal; urgency=low
76938009
7694− * New release with fullscreen launcher fixes
8010+ * New release with fullscreen launcher fixes
76958011
76968012 -- Bill Filler <bill.filler@canonical.com> Fri, 07 Dec 2012 09:36:37 +0000
76978013
@@ -7703,7 +8019,7 @@ qml-phone-shell (1.20) quantal; urgency=low
77038019
77048020qml-phone-shell (1.19) quantal; urgency=low
77058021
7706− * enable multi-threaded render for apps
8022+ * enable multi-threaded render for apps
77078023
77088024 -- Bill Filler <bill.filler@canonical.com> Wed, 05 Dec 2012 17:34:09 +0000
77098025
@@ -7711,7 +8027,7 @@ qml-phone-shell (1.18) quantal; urgency=low
77118027
77128028 [ Bill Filler ]
77138029 * update launcher to use wk2-render (chromeless webkit) for facebook
7714− and twitter
8030+ and twitter
77158031
77168032 -- Florian Boucault <florian.boucault@canonical.com> Wed, 05 Dec 2012 12:20:50 +0000
77178033
@@ -7723,7 +8039,7 @@ qml-phone-shell (1.17) quantal; urgency=low
77238039
77248040qml-phone-shell (1.16) quantal; urgency=low
77258041
7726− * fix to launch new gallery with correct args
8042+ * fix to launch new gallery with correct args
77278043
77288044 -- Bill Filler <bill.filler@canonical.com> Thu, 29 Nov 2012 17:04:36 -0500
77298045
@@ -7785,7 +8101,7 @@ qml-phone-shell (1.2) quantal; urgency=low
77858101
77868102qml-phone-shell (1.1) quantal; urgency=low
77878103
7788− * comment out console.log() to prevent crash
8104+ * comment out console.log() to prevent crash
77898105
77908106 -- Bill Filler <bill.filler@canonical.com> Sun, 28 Oct 2012 22:18:36 +0100
77918107
@@ -7813,19 +8129,19 @@ qml-phone-shell (0.7) quantal; urgency=low
78138129 * qml-phone-shell.conf: better setup of env vars and launch
78148130 via dbus-luanch to properly setup session bus
78158131 * shellapplication.cpp: don't setup custom env before launching
7816− processes
8132+ processes
78178133
78188134 -- Bill Filler <bill.filler@canonical.com> Sun, 21 Oct 2012 11:32:42 +0200
78198135
78208136qml-phone-shell (0.6) quantal; urgency=low
78218137
7822− * added additional Android env vars to upstart script
8138+ * added additional Android env vars to upstart script
78238139
78248140 -- Bill Filler <bill.filler@canonical.com> Fri, 19 Oct 2012 09:35:25 -0400
78258141
78268142qml-phone-shell (0.5) quantal; urgency=low
78278143
7828− * added support to launch telephony-app
8144+ * added support to launch telephony-app
78298145
78308146 -- Bill Filler <bill.filler@canonical.com> Thu, 18 Oct 2012 13:45:25 -0400
78318147
@@ -7852,3 +8168,8 @@ qml-phone-shell (0.1) quantal; urgency=low
78528168 * Initial release
78538169
78548170 -- 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+215−196
@@ -2,223 +2,224 @@ 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− dh-apparmor,
9− doxyqml,
10−# To allow cross-compiling to work, we also must append :native
11−# to g++ so we don't try to run arm g++
12−# on an x86 CPU for example, when cross-compiling.
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− libgnome-desktop-3-dev,
22− libgl1-mesa-dev[!arm64 !armhf] | libgl-dev[!arm64 !armhf],
23− libgl1-mesa-dri,
24− libgles2-mesa-dev[arm64 armhf],
25− libglib2.0-dev,
26− libgsettings-qt-dev,
27− libhardware-dev,
28− liblightdm-qt5-3-dev,
29− libpam0g-dev,
30− libpulse-dev,
31− libqmenumodel-dev (>= 0.2.11),
32− libqt5svg5-dev,
33− libqt5xmlpatterns5-dev,
34− libsystemsettings-dev,
35− libubuntu-app-launch2-dev,
36− libubuntu-download-manager-common-dev,
37− libubuntugestures5-dev (>= 1.3.2030),
38− libubuntugestures5-private-dev (>= 1.3.2030),
39− libudev-dev,
40− libudm-common-dev,
41− libunity-api-dev (>= 8.0),
42− libusermetricsoutput1-dev,
43−# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
44− libx11-dev[!arm64 !armhf],
45− libxcb1-dev[!arm64 !armhf],
46− libxi-dev[!arm64 !armhf],
47−# End of X11 libs
48− pkg-config,
49− python3-all:any,
50− python3-setuptools,
51− qml-module-qt-labs-folderlistmodel,
52− qml-module-qt-labs-settings,
53− qml-module-qtqml-statemachine,
54− qml-module-qtmultimedia (>= 5.6),
55− qml-module-qtquick-layouts,
56− qml-module-qtquick-xmllistmodel,
57− qml-module-qtquick2,
58− qml-module-qtsysteminfo,
59− qml-module-qttest,
60− qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
61− qml-module-ubuntu-web,
62− qt5-default,
63− qtbase5-dev (>= 5.6),
64− qtbase5-dev-tools,
65− qtbase5-private-dev (>= 5.6),
66− qtdeclarative5-dev (>= 5.6),
67− qtdeclarative5-dev-tools,
68− qtdeclarative5-private-dev (>= 5.6),
69− qtdeclarative5-ubuntu-content1,
70− qtdeclarative5-ubuntu-settings-components (>= 0.11),
71− ttf-ubuntu-font-family,
72− xvfb,
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,
7376Standards-Version: 3.9.4
74−Homepage: http://launchpad.net/unity
75−# If you aren't a member of ~unity-team but need to upload
76−# packaging changes, just go ahead. ~unity-team will notice
77−# and sync up the code again.
78−Vcs-Bzr: https://code.launchpad.net/unity8
79−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
8079XS-Testsuite: autopkgtest
8180X-Ubuntu-Use-Langpack: yes
8281
8382Package: indicators-client
8483Architecture: any
85−Depends: 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},
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},
9090Description: Indicators client test application
9191 This package contains the client application for indicators used by autopilot
9292
9393Package: unity8-greeter
9494Architecture: any
95−Depends: unity8 (= ${binary:Version}),
96− unity-system-compositor,
97− ${misc:Depends},
98− ${shlibs:Depends}
99−Recommends: lightdm
100−Provides: lightdm-greeter
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,
101104Description: The Unity8 Greeter
102105 The Unity 8 greeter is the primary login greeter for Ubuntu devices.
103106
104−Package: unity-scope-tool
105−Architecture: any
106−Depends: unity8-common (= ${source:Version}),
107− unity8-private (= ${binary:Version}),
108− ${misc:Depends},
109− ${shlibs:Depends},
110−# We do call pkg-config libunity-scopes from the code
111− pkg-config,
112− libunity-scopes-dev,
113−Description: Development tool for Unity scopes
114− This package contains the development tool for new generation Unity scopes, based
115− on Unity8.
116−
117107Package: unity8
118108Architecture: any
119−Provides: indicator-renderer,
120−Depends: dmz-cursor-theme,
121− gsettings-desktop-schemas,
122− libcap2-bin,
123− libglib2.0-bin,
124− qmenumodel-qml (>= 0.2.11),
125− qml-module-biometryd,
126− qml-module-qt-labs-folderlistmodel,
127− qml-module-qt-labs-settings,
128− qml-module-qtqml-statemachine,
129− qml-module-qtquick-xmllistmodel,
130− qml-module-qtsysteminfo,
131− qml-module-ubuntu-web,
132− qtdeclarative5-qtmir-plugin (>= 0.4.8),
133− qtdeclarative5-ubuntu-telephony0.1,
134− ubuntu-system-settings (>= 0.4),
135− unity-launcher-impl-10,
136− unity8-common (= ${source:Version}),
137− unity8-private (= ${binary:Version}),
138− unity8-private | unity-launcher-impl,
139− ${misc:Depends},
140− ${shlibs:Depends},
141−Recommends: indicator-keyboard,
142− indicator-session,
143− unity-greeter-session-broadcast,
144− unity-scope-click,
145−Suggests: unity-scope-mediascanner2,
146−Breaks: indicator-network (<< 0.5.1+14.10.20141014),
147− ubuntu-touch-session (<< 0.107),
148− unity8-greeter (<< 7.89),
149− ubuntu-keyboard (<< 0.100),
150−Replaces: ubuntu-touch-session (<< 0.82~),
151− unity8-greeter (<< 7.89),
152−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,
153148Description: Unity 8 shell
154149 The Unity 8 shell is the primary user interface for Ubuntu devices.
155150
156151Package: unity8-common
157152Architecture: all
158−Depends: qml-module-qtquick-layouts,
159− qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
160− qml-module-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
161− qtdeclarative5-ubuntu-settings-components (>= 0.11),
162− qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
163− qttranslations5-l10n,
164− ubuntu-thumbnailer-impl-0,
165− ubuntu-wallpapers,
166− unity-application-impl-23,
167− unity-notifications-impl-3,
168− unity-plugin-scopes | unity-scopes-impl,
169− unity-scopes-impl-12,
170− unity8-tests | unity-application-impl,
171− ${misc:Depends},
172−Breaks: unity8 (<< 7.86),
173−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),
174170Description: Unity 8 shell (common files)
175171 The Unity 8 shell is the primary user interface for Ubuntu devices.
176172 .
177− This package contains the QML, graphics and locale files shared between
178− unity8 and unity-scope-tool.
173+ This package contains the QML, graphics and locale files for unity8.
179174
180175Package: unity8-autopilot
181176Architecture: all
182−Depends: autopilot-qt5 (>= 1.4),
183− gir1.2-glib-2.0,
184− gir1.2-notify-0.7,
185− libqt5test5,
186− libqt5widgets5,
187− ofono-phonesim,
188− python3-autopilot,
189− python3-evdev,
190− python3-fixtures,
191− python3-gi,
192− qttestability-autopilot (>= 1.4),
193− ubuntu-ui-toolkit-autopilot (>= 1.3.2030),
194− unity-scope-click,
195− unity8 (= ${source:Version}),
196− unity8-tests (= ${source:Version}),
197− url-dispatcher-tools,
198− xvfb,
199− ${misc:Depends},
200− ${python3: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},
201196Description: Test package for Unity 8 shell
202197 Autopilot tests for the unity8 package
203198
204199Package: unity8-tests
205200Architecture: any
206201Multi-Arch: same
207−Pre-Depends: ${misc:Pre-Depends},
208−Depends: dbus-test-runner,
209− parallel,
210− qt5-default,
211− qtdeclarative5-dev-tools,
212− unity8 (= ${source:Version}),
213− xvfb,
214− ${misc:Depends},
215− ${shlibs:Depends},
216−Provides: unity-application-impl,
217− unity-application-impl-23,
218− unity8-fake-env,
219−Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1),
220− unity8-fake-env,
221−Conflicts: unity8-fake-env,
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,
222223Description: Scripts and mocks for running Unity 8 shell tests
223224 Provides fake implementations of some QML modules used by Unity 8 shell
224225 (e.g Ubuntu.Application) so that you can run it in a sandboxed environment
@@ -227,27 +228,45 @@ Description: Scripts and mocks for running Unity 8 shell tests
227228Package: unity8-private
228229Architecture: any
229230Multi-Arch: same
230−Pre-Depends: ${misc:Pre-Depends},
231−Depends: accountsservice-ubuntu-schemas (>= 0.0.7),
232− gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
233− libhardware2,
234− unity-schemas (>= 7.3.1+14.10.20140915),
235− qtdeclarative5-gsettings1.0,
236− qml-module-qtmultimedia,
237− ${misc:Depends},
238− ${shlibs:Depends},
239−Provides: unity-launcher-impl,
240− unity-launcher-impl-10,
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,
241245Description: Unity 8 private libs
242246 The Unity 8 shell is the primary user interface for Ubuntu devices.
243247 .
244248 This package contains the private libraries for QML and other components
245249 only used by the shell.
246250
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+
247265Package: unity8-doc
248266Section: doc
249267Architecture: all
250268Multi-Arch: foreign
251−Depends: ${misc:Depends},
269+Depends:
270+ ${misc:Depends},
252271Description: Documentation for Unity8
253272 The Unity 8 shell is the primary user interface for Ubuntu devices. (documentation)
debian/rules+19−5
@@ -7,6 +7,12 @@ 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
@@ -18,7 +24,19 @@ override_dh_auto_configure:
1824
1925override_dh_auto_build:
2026 # doc is not a default target
21− 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
2240
2341override_dh_install:
2442 # install autopilot tests
@@ -29,10 +47,6 @@ override_dh_install:
2947 cd $(CURDIR)
3048 dh_install -X'*.pyc' --fail-missing
3149
32−override_dh_installdeb:
33− dh_apparmor --profile-name=usr.bin.unity8-dash -punity8-dash
34− dh_installdeb
35−
3650# use private lib directories
3751override_dh_makeshlibs:
3852 dh_makeshlibs -Nunity8-private -Nunity8-tests
debian/source/formatdeleted−1
@@ -1 +0,0 @@
1−1.0
debian/tests/control+5−3
@@ -1,9 +1,11 @@
11Tests: qmluitests.sh
22Restrictions: allow-stderr
3−Depends: dpkg-dev,
4− unity8-tests,
3+Depends:
4+ dpkg-dev,
5+ unity8-tests,
56
67Tests: autopilot.sh
78Restrictions: allow-stderr,
89 isolation-machine,
9−Depends: unity8-autopilot,
10+Depends:
11+ unity8-autopilot,
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-greeter.install+1−1
@@ -1,5 +1,5 @@
1−data/unity8-greeter-wrapper usr/bin/
21data/unity8-greeter-init.conf usr/share/upstart/sessions/
2+data/unity8-greeter-wrapper usr/bin/
33data/unity8-greeter.pkla /var/lib/polkit-1/localauthority/10-vendor.d/
44usr/share/lightdm/greeters/unity8-greeter.desktop
55usr/share/lightdm/lightdm.conf.d/51-unity8-greeter.conf
debian/unity8-private.install+1−3
@@ -1,18 +1,16 @@
11usr/lib/*/libunity8-private.*
22usr/lib/*/unity8/qml/AccountsService
33usr/lib/*/unity8/qml/Cursor
4−usr/lib/*/unity8/qml/Dash
54usr/lib/*/unity8/qml/GlobalShortcut
65usr/lib/*/unity8/qml/Greeter
7−usr/lib/*/unity8/qml/ImageCache
86usr/lib/*/unity8/qml/LightDM
97usr/lib/*/unity8/qml/Lights
108usr/lib/*/unity8/qml/Powerd
119usr/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
15−usr/lib/*/unity8/qml/UInput
1614usr/lib/*/unity8/qml/Utils
1715usr/lib/*/unity8/qml/WindowManager
1816usr/lib/*/unity8/qml/Wizard
debian/unity8-schemas.installnew file+1
@@ -0,0 +1 @@
1+usr/share/glib-2.0/schemas
debian/unity8-tests.install−1
@@ -2,7 +2,6 @@ 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
65usr/lib/*/unity8/qml/utils
76usr/lib/*/unity8/tests
87usr/lib/*/unity8/uqmlscene
debian/unity8.install+6−10
@@ -1,23 +1,19 @@
1−debian/usr.bin.unity8-dash etc/apparmor.d
2−var/lib/unity8/version
3−data/unity8-dash.conf usr/share/upstart/sessions/
1+data/devices.conf etc/ubuntu/
2+data/test.sensors etc/ubuntusensors/
43data/unity8-filewatcher.conf usr/share/upstart/sessions/
54data/unity8.conf usr/share/upstart/sessions/
6−data/devices.conf etc/ubuntu/
75usr/bin/unity8
8−usr/bin/unity8-dash
9−usr/share/applications/unity8-dash.desktop
106usr/share/applications/unity8.desktop
117usr/share/unity8/ApplicationMenus
8+usr/share/unity8/DeviceConfiguration.qml
9+usr/share/unity8/DisabledScreenNotice.qml
1210usr/share/unity8/Greeter
1311usr/share/unity8/Launcher
12+usr/share/unity8/OrientedShell.qml
1413usr/share/unity8/Panel
1514usr/share/unity8/Rotation
16−usr/share/unity8/DeviceConfiguration.qml
17−usr/share/unity8/OrientedShell.qml
18−usr/share/unity8/DisabledScreenNotice.qml
1915usr/share/unity8/Shell.qml
2016usr/share/unity8/Stage
2117usr/share/unity8/Tutorial
2218usr/share/unity8/Wizard
23−usr/share/url-dispatcher/urls/unity8-dash.url-dispatcher
19+var/lib/unity8/version
debian/usr.bin.unity8-dashdeleted−21
@@ -1,21 +0,0 @@
1−# vim:syntax=apparmor
2−
3−#include <tunables/global>
4−
5−# v2 compatible wildly permissive profile
6−profile unity8-dash /usr/bin/unity8-dash (attach_disconnected) {
7− capability,
8− network,
9− / rwkl,
10− /** rwlkm,
11− /** pix,
12−
13− mount,
14− remount,
15− umount,
16− pivot_root,
17− dbus,
18− signal,
19− ptrace,
20− unix,
21−}
plugins/AccountsService/AccountsService.cpp+1−30
@@ -25,7 +25,6 @@
2525#include <glib.h>
2626
2727#define IFACE_ACCOUNTS_USER QStringLiteral("org.freedesktop.Accounts.User")
28−#define IFACE_LOCATION_HERE QStringLiteral("com.ubuntu.location.providers.here.AccountsService")
2928#define IFACE_UBUNTU_INPUT QStringLiteral("com.ubuntu.AccountsService.Input")
3029#define IFACE_UBUNTU_SECURITY QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy")
3130#define IFACE_UBUNTU_SECURITY_OLD QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy")
@@ -33,7 +32,7 @@
3332#define IFACE_UNITY_PRIVATE QStringLiteral("com.canonical.unity.AccountsService.Private")
3433
3534#define PROP_BACKGROUND_FILE QStringLiteral("BackgroundFile")
36−#define PROP_DEMO_EDGES QStringLiteral("demo-edges")
35+#define PROP_DEMO_EDGES QStringLiteral("DemoEdges2")
3736#define PROP_DEMO_EDGES_COMPLETED QStringLiteral("DemoEdgesCompleted")
3837#define PROP_EMAIL QStringLiteral("Email")
3938#define PROP_ENABLE_FINGERPRINT_IDENTIFICATION QStringLiteral("EnableFingerprintIdentification")
@@ -93,8 +92,6 @@ AccountsService::AccountsService(QObject* parent, const QString &user)
9392 registerProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, QStringLiteral("emailChanged"));
9493 registerProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, QStringLiteral("realNameChanged"));
9594 registerProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QStringLiteral("keymapsChanged"));
96− registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, QStringLiteral("hereEnabledChanged"));
97− registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH, QStringLiteral("hereLicensePathChanged"));
9895 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION, QStringLiteral("enableFingerprintIdentificationChanged"));
9996 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral("enableLauncherWhileLockedChanged"));
10097 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral("enableIndicatorsWhileLockedChanged"));
@@ -216,32 +213,6 @@ AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() cons
216213 return (PasswordDisplayHint)value.toInt();
217214}
218215
219−bool AccountsService::hereEnabled() const
220−{
221− auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED);
222− return value.toBool();
223−}
224−
225−void AccountsService::setHereEnabled(bool enabled)
226−{
227− setProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, enabled);
228−}
229−
230−QString AccountsService::hereLicensePath() const
231−{
232− auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH);
233− QString hereLicensePath = value.toString();
234− if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
235− hereLicensePath = QStringLiteral("");
236− return hereLicensePath;
237−}
238−
239−bool AccountsService::hereLicensePathValid() const
240−{
241− auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH);
242− return !value.toString().isNull();
243−}
244−
245216QString AccountsService::realName() const
246217{
247218 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME);
plugins/AccountsService/AccountsService.h−16
@@ -66,16 +66,6 @@ class AccountsService: public QObject
6666 READ failedFingerprintLogins
6767 WRITE setFailedFingerprintLogins
6868 NOTIFY failedFingerprintLoginsChanged)
69− Q_PROPERTY(bool hereEnabled
70− READ hereEnabled
71− WRITE setHereEnabled
72− NOTIFY hereEnabledChanged)
73− Q_PROPERTY(QString hereLicensePath
74− READ hereLicensePath
75− NOTIFY hereLicensePathChanged)
76− Q_PROPERTY(bool hereLicensePathValid // qml sees a null string as "", so we use proxy setting for that
77− READ hereLicensePathValid
78− NOTIFY hereLicensePathChanged)
7969 Q_PROPERTY(QString realName READ realName WRITE setRealName NOTIFY realNameChanged)
8070 Q_PROPERTY(QString email READ email WRITE setEmail NOTIFY emailChanged)
8171 Q_PROPERTY(QStringList keymaps READ keymaps WRITE setKeymaps NOTIFY keymapsChanged)
@@ -106,10 +96,6 @@ public:
10696 void setFailedLogins(uint failedLogins);
10797 uint failedFingerprintLogins() const;
10898 void setFailedFingerprintLogins(uint failedFingerprintLogins);
109− bool hereEnabled() const;
110− void setHereEnabled(bool enabled);
111− QString hereLicensePath() const;
112− bool hereLicensePathValid() const;
11399 QString realName() const;
114100 void setRealName(const QString &realName);
115101 QString email() const;
@@ -129,8 +115,6 @@ Q_SIGNALS:
129115 void passwordDisplayHintChanged();
130116 void failedLoginsChanged();
131117 void failedFingerprintLoginsChanged();
132− void hereEnabledChanged();
133− void hereLicensePathChanged();
134118 void realNameChanged();
135119 void emailChanged();
136120 void keymapsChanged();
plugins/AccountsService/CMakeLists.txt+1−2
@@ -7,9 +7,8 @@ add_library(AccountsService-qml MODULE
77 plugin.cpp
88 )
99
10−qt5_use_modules(AccountsService-qml DBus Qml)
11−
1210target_link_libraries(AccountsService-qml
11+ Qt5::DBus Qt5::Qml
1312 ${GLIB_LIBRARIES}
1413 )
1514
plugins/AccountsService/com.canonical.unity.AccountsService.xml+6
@@ -9,11 +9,17 @@
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+
1723 <!-- List of tutorial pages that have been completed by the user -->
1824 <property name="DemoEdgesCompleted" type="as" access="readwrite">
1925 <annotation name="org.freedesktop.Accounts.DefaultValue" value="[]"/>
plugins/CMakeLists.txt+1−3
@@ -1,4 +1,4 @@
1−include(QmlPlugins)
1+find_package(QmlPlugins)
22
33# Set up and install a plugin for unity8.
44#
@@ -15,10 +15,8 @@ add_subdirectory(AccountsService)
1515add_subdirectory(Cursor)
1616add_subdirectory(GlobalShortcut)
1717add_subdirectory(Greeter)
18−add_subdirectory(ImageCache)
1918add_subdirectory(LightDM)
2019add_subdirectory(Lights)
21−add_subdirectory(Dash)
2220add_subdirectory(Powerd)
2321add_subdirectory(ScreenshotDirectory)
2422add_subdirectory(SessionBroadcast)
plugins/Cursor/CMakeLists.txt+1−2
@@ -26,8 +26,7 @@ add_library(Cursor-qml SHARED
2626target_link_libraries(Cursor-qml
2727 xcursorloader-static
2828 ${QT5PLATFORM_SUPPORT_LDFLAGS}
29+ Qt5::Qml Qt5::Quick Qt5::Svg
2930)
3031
31−qt5_use_modules(Cursor-qml Qml Quick Svg)
32−
3332add_unity8_plugin(Cursor 1.1 Cursor TARGETS Cursor-qml)
plugins/Cursor/CursorImageProvider.cpp+2
@@ -174,6 +174,8 @@ CursorImageProvider::CursorImageProvider()
174174 m_fallbackNames[QStringLiteral("forbidden")].append(QStringLiteral("not-allowed"));
175175 m_fallbackNames[QStringLiteral("forbidden")].append(QStringLiteral("circle"));
176176
177+ m_fallbackNames[QStringLiteral("grabbing")].append(QStringLiteral("closedhand")); // Breeze
178+
177179 m_fallbackNames[QStringLiteral("hand")].append(QStringLiteral("pointing_hand"));
178180 m_fallbackNames[QStringLiteral("hand")].append(QStringLiteral("pointer"));
179181
plugins/Dash/AudioProgressBar.qmldeleted−54
@@ -1,54 +0,0 @@
1−/*
2− * Copyright 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−import Ubuntu.Components 1.3
19−import Dash 0.1
20−
21−Item {
22− id: root
23−
24− implicitHeight: progressBarImage.height
25−
26− property url source
27− readonly property double progress: AudioUrlComparer.compare(source, DashAudioPlayer.currentSource) ? DashAudioPlayer.progress : 0
28−
29− Image {
30− id: progressBarImage
31− anchors { left: parent.left; right: parent.right }
32− height: units.dp(6)
33− source: "graphics/music_progress_bg.png"
34− asynchronous: true
35− sourceSize.width: width
36− sourceSize.height: height
37− }
38−
39− UbuntuShape {
40− id: progressBarFill
41− objectName: "progressBarFill"
42−
43− readonly property int maxWidth: progressBarImage.width
44−
45− anchors {
46− left: progressBarImage.left
47− right: progressBarImage.right
48− verticalCenter: progressBarImage.verticalCenter
49− rightMargin: maxWidth - (maxWidth * root.progress)
50− }
51− height: units.dp(2)
52− backgroundColor: theme.palette.normal.activity
53− }
54−}
plugins/Dash/CMakeLists.txtdeleted−47
@@ -1,47 +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−)
14−
15−include_directories(
16− SYSTEM
17− ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
18− ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
19− ${Qt5V8_PRIVATE_INCLUDE_DIR}
20−)
21−
22−remove_definitions(-DQT_NO_KEYWORDS)
23−
24−set(QMLPLUGIN_SRC
25− plugin.cpp
26− listviewwithpageheader.cpp
27− abstractdashview.cpp
28− verticaljournal.cpp
29− horizontaljournal.cpp
30− organicgrid.cpp
31− )
32−
33−add_library(Dash-qml MODULE
34− ${QMLPLUGIN_SRC}
35− )
36−
37−target_link_libraries(Dash-qml
38− ${Qt5Gui_LIBRARIES}
39− ${Qt5Quick_LIBRARIES}
40− )
41−
42−qt5_use_modules(Dash-qml Qml Quick Concurrent)
43−
44−add_unity8_plugin(Dash 0.1 Dash TARGETS Dash-qml)
45−
46−install(FILES graphics/music_progress_bg.png DESTINATION ${SHELL_INSTALL_QML}/Dash/graphics/)
47−file(COPY graphics/music_progress_bg.png DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/graphics/)
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: "x-small"
66− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale)
67− color: grid.color
68− }
69− }
70− }
71−}
plugins/Dash/CardAudioProgress.qmldeleted−59
@@ -1,59 +0,0 @@
1−/*
2− * Copyright 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−import Ubuntu.Components 1.3
19−import Dash 0.1
20−
21−Item {
22− id: root
23−
24− implicitHeight: positionLabel.y + positionLabel.height
25− visible: AudioUrlComparer.compare(source, DashAudioPlayer.currentSource)
26−
27− property int duration: 0
28− property alias source: progress.source
29− property color color: theme.palette.normal.baseText
30− readonly property int position: root.visible ? DashAudioPlayer.position / 1000 : 0
31−
32− AudioProgressBar {
33− id: progress
34− anchors { left: parent.left; right: parent.right }
35− }
36−
37− Label {
38− id: positionLabel
39− anchors {
40− left: parent.left
41− top: progress.bottom
42− }
43− verticalAlignment: Text.AlignBottom
44− fontSize: "x-small"
45− text: DashAudioPlayer.lengthToString(root.position)
46− color: root.color
47− }
48−
49− Label {
50− anchors {
51− right: parent.right
52− top: progress.bottom
53− }
54− verticalAlignment: Text.AlignBottom
55− fontSize: "x-small"
56− text: DashAudioPlayer.lengthToString(duration)
57− color: root.color
58− }
59−}
plugins/Dash/CardCreator.jsdeleted−999
@@ -1,999 +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"]["elements"][0]
20−// %2 is the template["card-background"]["elements"][1]
21−// %3 is whether the loader should be asynchronous or not
22−// %4 is the template["card-background"] string
23−var kBackgroundLoaderCode = 'Loader {\n\
24− id: backgroundLoader; \n\
25− objectName: "backgroundLoader"; \n\
26− anchors.fill: parent; \n\
27− asynchronous: %3; \n\
28− visible: status === Loader.Ready; \n\
29− sourceComponent: UbuntuShape { \n\
30− objectName: "background"; \n\
31− radius: "small"; \n\
32− aspect: { \n\
33− switch (root.backgroundShapeStyle) { \n\
34− case "inset": return UbuntuShape.Inset; \n\
35− case "shadow": return UbuntuShape.DropShadow; \n\
36− default: \n\
37− case "flat": return UbuntuShape.Flat; \n\
38− } \n\
39− } \n\
40− backgroundColor: getColor(0) || "white"; \n\
41− secondaryBackgroundColor: getColor(1) || backgroundColor; \n\
42− backgroundMode: UbuntuShape.VerticalGradient; \n\
43− anchors.fill: parent; \n\
44− source: backgroundImage.source ? backgroundImage : null; \n\
45− property real luminance: Style.luminance(backgroundColor); \n\
46− property Image backgroundImage: Image { \n\
47− objectName: "backgroundImage"; \n\
48− source: { \n\
49− if (cardData && typeof cardData["background"] === "string") return cardData["background"]; \n\
50− else return %4; \n\
51− } \n\
52− } \n\
53− function getColor(index) { \n\
54− if (cardData && typeof cardData["background"] === "object" \n\
55− && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) { \n\
56− return cardData["background"]["elements"][index]; \n\
57− } else return index === 0 ? %1 : %2; \n\
58− } \n\
59− } \n\
60− }\n';
61−
62−// %1 is the aspect of the UbuntuShape
63−var kArtUbuntuShapeCode = 'UbuntuShape { \n\
64− anchors.fill: parent; \n\
65− source: artImage; \n\
66− sourceFillMode: UbuntuShape.PreserveAspectCrop; \n\
67− radius: "small"; \n\
68− aspect: %1; \n\
69− }';
70−
71−var kArtProportionalShapeCode = 'ProportionalShape { \n\
72− anchors.left: parent.left; \n\
73− anchors.right: parent.right; \n\
74− source: artImage; \n\
75− aspect: UbuntuShape.DropShadow; \n\
76− }';
77−
78−// %1 is used as anchors of artShapeLoader
79−// %2 is used as image width
80−// %3 is used as image height
81−// %4 is whether the image should be visible
82−// %5 is whether the loader should be asynchronous or not
83−// %6 is the shape code we want to use
84−// %7 is injected as code to artImage
85−// %8 is used as image fallback
86−var kArtShapeHolderCode = 'Loader { \n\
87− id: artShapeLoader; \n\
88− height: root.fixedArtShapeSize.height; \n\
89− width: root.fixedArtShapeSize.width; \n\
90− anchors { %1 } \n\
91− objectName: "artShapeLoader"; \n\
92− readonly property string cardArt: cardData && cardData["art"] || %8; \n\
93− onCardArtChanged: { if (item) { item.image.source = cardArt; } } \n\
94− active: cardArt != ""; \n\
95− asynchronous: %5; \n\
96− visible: status === Loader.Ready; \n\
97− sourceComponent: Item { \n\
98− id: artShape; \n\
99− objectName: "artShape"; \n\
100− visible: image.status === Image.Ready; \n\
101− readonly property alias image: artImage; \n\
102− %6 \n\
103− width: root.fixedArtShapeSize.width; \n\
104− height: root.fixedArtShapeSize.height; \n\
105− CroppedImageMinimumSourceSize { \n\
106− id: artImage; \n\
107− objectName: "artImage"; \n\
108− source: artShapeLoader.cardArt; \n\
109− asynchronous: %5; \n\
110− visible: %4; \n\
111− width: %2; \n\
112− height: %3; \n\
113− %7 \n\
114− } \n\
115− } \n\
116− }\n';
117−
118−// %1 is used as anchors of artShapeLoader
119−// %2 is used as image width
120−// %3 is used as image height
121−// %4 is whether the image should be visible
122−// %5 is whether the loader should be asynchronous or not
123−// %6 is the shape code we want to use
124−// %7 is injected as code to artImage
125−// %8 is used as image fallback
126−var kArtShapeHolderCodeCardToolCard = 'Loader { \n\
127− id: artShapeLoader; \n\
128− anchors { %1 } \n\
129− objectName: "artShapeLoader"; \n\
130− readonly property string cardArt: cardData && cardData["art"] || %8; \n\
131− onCardArtChanged: { if (item) { item.image.source = cardArt; } } \n\
132− active: cardArt != ""; \n\
133− asynchronous: %5; \n\
134− visible: status === Loader.Ready; \n\
135− sourceComponent: Item { \n\
136− id: artShape; \n\
137− objectName: "artShape"; \n\
138− visible: image.status === Image.Ready; \n\
139− readonly property alias image: artImage; \n\
140− %6 \n\
141− width: image.status !== Image.Ready ? 0 : image.width; \n\
142− height: image.status !== Image.Ready ? 0 : image.height; \n\
143− CroppedImageMinimumSourceSize { \n\
144− id: artImage; \n\
145− objectName: "artImage"; \n\
146− source: artShapeLoader.cardArt; \n\
147− asynchronous: %5; \n\
148− visible: %4; \n\
149− width: %2; \n\
150− height: %3; \n\
151− %7 \n\
152− } \n\
153− } \n\
154− }\n';
155−
156−// %1 is anchors.fill
157−// %2 is width
158−// %3 is height
159−// %4 is whether the icon should be asynchronous or not
160−var kAudioButtonCode = 'AbstractButton { \n\
161− id: audioButton; \n\
162− anchors.fill: %1; \n\
163− width: %2; \n\
164− height: %3; \n\
165− readonly property url source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || ""; \n\
166− UbuntuShape { \n\
167− anchors.fill: parent; \n\
168− visible: parent.pressed; \n\
169− radius: "small"; \n\
170− } \n\
171− Rectangle { \n\
172− color: Qt.rgba(0, 0, 0, 0.5); \n\
173− anchors.centerIn: parent; \n\
174− width: parent.width * 0.5; \n\
175− height: width; \n\
176− radius: width / 2; \n\
177− } \n\
178− Icon { \n\
179− anchors.centerIn: parent; \n\
180− width: parent.width * 0.3; \n\
181− height: width; \n\
182− opacity: 0.9; \n\
183− name: DashAudioPlayer.playing && AudioUrlComparer.compare(parent.source, DashAudioPlayer.currentSource) ? "media-playback-pause" : "media-playback-start"; \n\
184− color: "white"; \n\
185− asynchronous: %4; \n\
186− } \n\
187− onClicked: { \n\
188− if (AudioUrlComparer.compare(source, DashAudioPlayer.currentSource)) { \n\
189− if (DashAudioPlayer.playing) { \n\
190− DashAudioPlayer.pause(); \n\
191− } else { \n\
192− DashAudioPlayer.play(); \n\
193− } \n\
194− } else { \n\
195− var playlist = (cardData["quickPreviewData"] && cardData["quickPreviewData"]["playlist"]) || null; \n\
196− DashAudioPlayer.playSource(source, playlist); \n\
197− } \n\
198− } \n\
199− onPressAndHold: { \n\
200− root.pressAndHold(); \n\
201− } \n\
202− }';
203−
204−// %1 is whether the loader should be asynchronous or not
205−// %2 is the header height code
206−var kOverlayLoaderCode = 'Loader { \n\
207− id: overlayLoader; \n\
208− readonly property real overlayHeight: %2 + units.gu(2); \n\
209− anchors.fill: artShapeLoader; \n\
210− active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false; \n\
211− asynchronous: %1; \n\
212− visible: showHeader && status === Loader.Ready; \n\
213− sourceComponent: UbuntuShapeOverlay { \n\
214− id: overlay; \n\
215− property real luminance: Style.luminance(overlayColor); \n\
216− aspect: UbuntuShape.Flat; \n\
217− radius: "small"; \n\
218− overlayColor: cardData && cardData["overlayColor"] || "#99000000"; \n\
219− overlayRect: Qt.rect(0, 1 - overlayLoader.overlayHeight / height, 1, 1); \n\
220− } \n\
221− }\n';
222−
223−// multiple row version of HeaderRowCode
224−function kHeaderRowCodeGenerator() {
225− var kHeaderRowCodeTemplate = 'Row { \n\
226− id: row; \n\
227− objectName: "outerRow"; \n\
228− property real margins: units.gu(1); \n\
229− spacing: margins; \n\
230− %2\
231− anchors { %1 } \n\
232− anchors.right: parent.right; \n\
233− anchors.margins: margins; \n\
234− anchors.rightMargin: 0; \n\
235− data: [ \n\
236− %3 \n\
237− ] \n\
238− }\n';
239− var args = Array.prototype.slice.call(arguments);
240− var isCardTool = args.shift();
241− var heightCode = isCardTool ? "" : "height: root.fixedHeaderHeight; \n";
242− var code = kHeaderRowCodeTemplate.arg(args.shift()).arg(heightCode).arg(args.join(',\n'));
243− return code;
244−}
245−
246−// multiple item version of kHeaderContainerCode
247−function kHeaderContainerCodeGenerator() {
248− var headerContainerCodeTemplate = 'Item { \n\
249− id: headerTitleContainer; \n\
250− anchors { %1 } \n\
251− width: parent.width - x; \n\
252− implicitHeight: %2; \n\
253− data: [ \n\
254− %3 \n\
255− ]\n\
256− }\n';
257− var args = Array.prototype.slice.call(arguments);
258− var code = headerContainerCodeTemplate.arg(args.shift()).arg(args.shift()).arg(args.join(',\n'));
259− return code;
260−}
261−
262−// %1 is used as anchors of mascotShapeLoader
263−// %2 is whether the loader should be asynchronous or not
264−var kMascotShapeLoaderCode = 'Loader { \n\
265− id: mascotShapeLoader; \n\
266− objectName: "mascotShapeLoader"; \n\
267− asynchronous: %2; \n\
268− active: mascotImage.status === Image.Ready; \n\
269− visible: showHeader && active && status === Loader.Ready; \n\
270− width: units.gu(6); \n\
271− height: units.gu(5.625); \n\
272− sourceComponent: UbuntuShape { aspect: UbuntuShape.Flat; image: mascotImage } \n\
273− anchors { %1 } \n\
274− }\n';
275−
276−// %1 is used as anchors of mascotImage
277−// %2 is used as visible of mascotImage
278−// %3 is injected as code to mascotImage
279−// %4 is used as fallback image
280−var kMascotImageCode = 'CroppedImageMinimumSourceSize { \n\
281− id: mascotImage; \n\
282− objectName: "mascotImage"; \n\
283− anchors { %1 } \n\
284− source: cardData && cardData["mascot"] || %4; \n\
285− width: units.gu(6); \n\
286− height: units.gu(5.625); \n\
287− horizontalAlignment: Image.AlignHCenter; \n\
288− verticalAlignment: Image.AlignVCenter; \n\
289− visible: %2; \n\
290− %3 \n\
291− }\n';
292−
293−// %1 is used as anchors of titleLabel
294−// %2 is used as color of titleLabel
295−// %3 is used as extra condition for visible of titleLabel
296−// %4 is used as title width
297−// %5 is used as horizontal alignment
298−var kTitleLabelCode = 'Label { \n\
299− id: titleLabel; \n\
300− objectName: "titleLabel"; \n\
301− anchors { %1 } \n\
302− elide: Text.ElideRight; \n\
303− fontSize: "small"; \n\
304− wrapMode: Text.Wrap; \n\
305− maximumLineCount: 2; \n\
306− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale); \n\
307− color: %2; \n\
308− visible: showHeader %3; \n\
309− width: %4; \n\
310− text: root.title; \n\
311− font.weight: Font.Normal; \n\
312− horizontalAlignment: %5; \n\
313− }\n';
314−
315−// %1 is used as extra anchors of emblemIcon
316−// %2 is used as color of emblemIcon
317−// FIXME The width code is a
318−// Workaround for bug https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1421293
319−var kEmblemIconCode = 'Icon { \n\
320− id: emblemIcon; \n\
321− objectName: "emblemIcon"; \n\
322− anchors { \n\
323− bottom: titleLabel.baseline; \n\
324− right: parent.right; \n\
325− %1 \n\
326− } \n\
327− source: cardData && cardData["emblem"] || ""; \n\
328− color: %2; \n\
329− height: source != "" ? titleLabel.font.pixelSize : 0; \n\
330− width: implicitWidth > 0 && implicitHeight > 0 ? (implicitWidth / implicitHeight * height) : implicitWidth; \n\
331− }\n';
332−
333−// %1 is used as anchors of touchdown effect
334−var kTouchdownCode = 'Loader { \n\
335− active: root.pressed; \n\
336− anchors { %1 } \n\
337− sourceComponent: UbuntuShape { \n\
338− objectName: "touchdown"; \n\
339− anchors.fill: parent; \n\
340− radius: "small"; \n\
341− borderSource: "radius_pressed.sci" \n\
342− } \n\
343− }\n';
344−
345−// %1 is used as anchors of subtitleLabel
346−// %2 is used as color of subtitleLabel
347−var kSubtitleLabelCode = 'Label { \n\
348− id: subtitleLabel; \n\
349− objectName: "subtitleLabel"; \n\
350− anchors { %1 } \n\
351− anchors.topMargin: units.dp(2); \n\
352− elide: Text.ElideRight; \n\
353− maximumLineCount: 1; \n\
354− fontSize: "x-small"; \n\
355− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale); \n\
356− color: %2; \n\
357− visible: titleLabel.visible && titleLabel.text; \n\
358− text: cardData && cardData["subtitle"] || ""; \n\
359− font.weight: Font.Light; \n\
360− }\n';
361−
362−// %1 is used as anchors of attributesRow
363−// %2 is used as color of attributesRow
364−var kAttributesRowCode = 'CardAttributes { \n\
365− id: attributesRow; \n\
366− objectName: "attributesRow"; \n\
367− anchors { %1 } \n\
368− color: %2; \n\
369− fontScale: root.fontScale; \n\
370− model: cardData && cardData["attributes"]; \n\
371− }\n';
372−
373−// %1 is used as anchors of socialActionsRow
374−// %2 is used as color of socialActionsRow
375−var kSocialActionsRowCode = 'CardSocialActions { \n\
376− id: socialActionsRow; \n\
377− objectName: "socialActionsRow"; \n\
378− anchors { %1 } \n\
379− color: %2; \n\
380− model: cardData && cardData["socialActions"]; \n\
381− onClicked: root.action(actionId); \n\
382− }\n';
383−
384−// %1 is used as top anchor of summary
385−// %2 is used as topMargin anchor of summary
386−// %3 is used as color of summary
387−var kSummaryLabelCode = 'Label { \n\
388− id: summary; \n\
389− objectName: "summaryLabel"; \n\
390− anchors { \n\
391− top: %1; \n\
392− left: parent.left; \n\
393− right: parent.right; \n\
394− margins: units.gu(1); \n\
395− topMargin: %2; \n\
396− } \n\
397− wrapMode: Text.Wrap; \n\
398− maximumLineCount: 5; \n\
399− elide: Text.ElideRight; \n\
400− text: cardData && cardData["summary"] || ""; \n\
401− height: text ? implicitHeight : 0; \n\
402− fontSize: "x-small"; \n\
403− font.weight: Font.Light; \n\
404− color: %3; \n\
405− }\n';
406−
407−// %1 is used as bottom anchor of audio progress bar
408−// %2 is used as left anchor of audio progress bar
409−// %3 is used as text color
410−var kAudioProgressBarCode = 'CardAudioProgress { \n\
411− id: audioProgressBar; \n\
412− duration: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["duration"]) || 0; \n\
413− source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || ""; \n\
414− anchors { \n\
415− bottom: %1; \n\
416− left: %2; \n\
417− right: parent.right; \n\
418− margins: units.gu(1); \n\
419− } \n\
420− color: %3; \n\
421− }';
422−
423−function sanitizeColor(colorString) {
424− if (colorString !== undefined) {
425− if (colorString.match(/^[#a-z0-9]*$/i) === null) {
426− // This is not the perfect regexp for color
427− // but what we're trying to do here is just protect
428− // against injection so it's ok
429− return "";
430− }
431− }
432− return colorString;
433−}
434−
435−function cardString(template, components, isCardTool, artShapeStyle, categoryLayout) {
436− var code;
437−
438− var templateInteractive = (template == null ? true : (template["non-interactive"] !== undefined ? !template["non-interactive"] : true)) ? "true" : "false";
439−
440− code = 'AbstractButton { \n\
441− id: root; \n\
442− property var cardData; \n\
443− property string backgroundShapeStyle: "flat"; \n\
444− property real fontScale: 1.0; \n\
445− property var scopeStyle: null; \n\
446− readonly property string title: cardData && cardData["title"] || ""; \n\
447− property bool showHeader: true; \n\
448− implicitWidth: childrenRect.width; \n\
449− enabled: %1; \n\
450− \n'.arg(templateInteractive);
451−
452− if (!isCardTool) {
453− code += "property int fixedHeaderHeight: -1; \n\
454− property size fixedArtShapeSize: Qt.size(-1, -1); \n";
455− }
456−
457− var hasArt = components["art"] && components["art"]["field"] || false;
458− var hasSummary = components["summary"] || false;
459− var isConciergeMode = components["art"] && components["art"]["conciergeMode"] || false;
460− var artAndSummary = hasArt && hasSummary && !isConciergeMode;
461− var isHorizontal = template["card-layout"] === "horizontal";
462− var hasBackground = (!isHorizontal && (template["card-background"] || components["background"] || artAndSummary)) ||
463− (hasSummary && (template["card-background"] || components["background"]));
464− var hasTitle = components["title"] || false;
465− var hasMascot = components["mascot"] || false;
466− var hasEmblem = components["emblem"] && !(hasMascot && template["card-size"] === "small") || false;
467− var headerAsOverlay = hasArt && template && template["overlay"] === true && (hasTitle || hasMascot);
468− var hasSubtitle = hasTitle && components["subtitle"] || false;
469− var hasHeaderRow = hasMascot && hasTitle;
470− var hasAttributes = hasTitle && components["attributes"] && components["attributes"]["field"] || false;
471− var hasSocialActions = hasTitle && components["social-actions"] || false;
472− var isAudio = template["quick-preview-type"] === "audio";
473− var asynchronous = isCardTool ? "false" : "true";
474−
475− code += 'signal action(var actionId);\n';
476− if (isAudio) {
477− // For now we only support audio cards with [optional] art, title, subtitle
478− // in horizontal mode
479− // Anything else makes it behave not like an audio card
480− if (hasSummary) isAudio = false;
481− if (!isHorizontal) isAudio = false;
482− if (hasMascot) isAudio = false;
483− if (hasEmblem) isAudio = false;
484− if (headerAsOverlay) isAudio = false;
485− if (hasAttributes) isAudio = false;
486− }
487−
488− if (hasBackground) {
489− var templateCardBackground;
490− if (template && typeof template["card-background"] === "string") {
491− templateCardBackground = 'decodeURI("' + encodeURI(template["card-background"]) + '")';
492− } else {
493− templateCardBackground = '""';
494− }
495−
496− var backgroundElements0;
497− var backgroundElements1;
498− if (template && typeof template["card-background"] === "object" && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
499− var element0 = sanitizeColor(template["card-background"]["elements"][0]);
500− var element1 = sanitizeColor(template["card-background"]["elements"][1]);
501− if (element0 !== undefined) {
502− backgroundElements0 = '"%1"'.arg(element0);
503− }
504− if (element1 !== undefined) {
505− backgroundElements1 = '"%1"'.arg(element1);
506− }
507− }
508− code += kBackgroundLoaderCode.arg(backgroundElements0).arg(backgroundElements1).arg(asynchronous).arg(templateCardBackground);
509− }
510−
511− if (hasArt) {
512− var artShapeAspect;
513− if (isCardTool) {
514− code += 'readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);\n';
515−
516− var artShapeAspect = components["art"] && components["art"]["aspect-ratio"] || 1;
517− if (isNaN(artShapeAspect)) {
518− artShapeAspect = 1;
519− }
520− } else {
521− artShapeAspect = "(root.fixedArtShapeSize.width / root.fixedArtShapeSize.height)";
522− }
523−
524− var widthCode, heightCode;
525− var artAnchors;
526− if (isHorizontal) {
527− artAnchors = 'left: parent.left';
528− if (hasMascot || hasTitle) {
529− widthCode = 'height * ' + artShapeAspect;
530− heightCode = 'headerHeight + 2 * units.gu(1)';
531− } else {
532− // This side of the else is a bit silly, who wants an horizontal layout without mascot and title?
533− // So we define a "random" height of the image height + 2 gu for the margins
534− widthCode = 'height * ' + artShapeAspect
535− heightCode = 'units.gu(7.625)';
536− }
537− } else {
538− artAnchors = 'horizontalCenter: parent.horizontalCenter;';
539− widthCode = 'root.width'
540− heightCode = 'width / ' + artShapeAspect;
541− }
542−
543− var fallback = !isCardTool && components["art"] && components["art"]["fallback"] || "";
544− fallback = encodeURI(fallback);
545− var fallbackStatusCode = "";
546− var fallbackURICode = '""';
547− if (fallback !== "") {
548− // fallbackStatusCode has %8 in it because we want to substitute it for fallbackURICode
549− // which in kArtShapeHolderCode is %8
550− fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %8;';
551− fallbackURICode = 'decodeURI("%1")'.arg(fallback);
552− }
553− var artShapeHolderShapeCode;
554− if (!isConciergeMode) {
555− if (artShapeStyle === "icon") {
556− artShapeHolderShapeCode = kArtProportionalShapeCode;
557− } else {
558− var artShapeHolderShapeAspect;
559− switch (artShapeStyle) {
560− case "inset": artShapeHolderShapeAspect = "UbuntuShape.Inset"; break;
561− case "shadow": artShapeHolderShapeAspect = "UbuntuShape.DropShadow"; break;
562− default:
563− case "flat": artShapeHolderShapeAspect = "UbuntuShape.Flat"; break;
564− }
565− artShapeHolderShapeCode = kArtUbuntuShapeCode.arg(artShapeHolderShapeAspect);
566− }
567− } else {
568− artShapeHolderShapeCode = "";
569− }
570− var artShapeHolderCode = isCardTool ? kArtShapeHolderCodeCardToolCard : kArtShapeHolderCode;
571− code += artShapeHolderCode.arg(artAnchors)
572− .arg(widthCode)
573− .arg(heightCode)
574− .arg(isConciergeMode ? "true" : "false")
575− .arg(asynchronous)
576− .arg(artShapeHolderShapeCode)
577− .arg(fallbackStatusCode)
578− .arg(fallbackURICode);
579− } else if (isCardTool) {
580− code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
581− }
582−
583− if (headerAsOverlay) {
584− var headerHeightCode = isCardTool ? "headerHeight" : "root.fixedHeaderHeight";
585− code += kOverlayLoaderCode.arg(asynchronous).arg(headerHeightCode);
586− }
587−
588− var headerVerticalAnchors;
589− if (headerAsOverlay) {
590− headerVerticalAnchors = 'bottom: artShapeLoader.bottom; \n\
591− bottomMargin: units.gu(1);\n';
592− } else {
593− if (hasArt) {
594− if (isHorizontal) {
595− headerVerticalAnchors = 'top: artShapeLoader.top; \n\
596− topMargin: units.gu(1);\n';
597− } else {
598− headerVerticalAnchors = 'top: artShapeLoader.bottom; \n\
599− topMargin: units.gu(1);\n';
600− }
601− } else {
602− headerVerticalAnchors = 'top: parent.top; \n\
603− topMargin: units.gu(1);\n';
604− }
605− }
606−
607− var headerLeftAnchor;
608− var headerLeftAnchorHasMargin = false;
609− if (isHorizontal && hasArt) {
610− headerLeftAnchor = 'left: artShapeLoader.right; \n\
611− leftMargin: units.gu(1);\n';
612− headerLeftAnchorHasMargin = true;
613− } else if (isHorizontal && isAudio) {
614− headerLeftAnchor = 'left: audioButton.right; \n\
615− leftMargin: units.gu(1);\n';
616− headerLeftAnchorHasMargin = true;
617− } else {
618− headerLeftAnchor = 'left: parent.left;\n';
619− }
620−
621− var touchdownOnArtShape = !hasBackground && hasArt && !hasMascot && !hasSummary && !isAudio;
622−
623− if (hasHeaderRow) {
624− code += 'readonly property int headerHeight: row.height;\n'
625− } else if (hasMascot) {
626− code += 'readonly property int headerHeight: mascotImage.height;\n'
627− } else if (hasAttributes) {
628− if (hasTitle && hasSubtitle) {
629− code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + attributesRow.height + attributesRow.anchors.topMargin;\n'
630− } else if (hasTitle) {
631− code += 'readonly property int headerHeight: titleLabel.height + attributesRow.height + attributesRow.anchors.topMargin;\n'
632− } else {
633− code += 'readonly property int headerHeight: attributesRow.height;\n'
634− }
635− } else if (isAudio) {
636− if (hasSubtitle) {
637− code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + audioProgressBar.height + audioProgressBar.anchors.topMargin;\n'
638− } else if (hasTitle) {
639− code += 'readonly property int headerHeight: titleLabel.height + audioProgressBar.height + audioProgressBar.anchors.topMargin;\n'
640− } else {
641− code += 'readonly property int headerHeight: audioProgressBar.height;\n'
642− }
643− } else if (hasSubtitle) {
644− code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;\n'
645− } else if (hasTitle) {
646− code += 'readonly property int headerHeight: titleLabel.height;\n'
647− } else {
648− code += 'readonly property int headerHeight: 0;\n'
649− }
650−
651− var mascotShapeCode = '';
652− var mascotCode = '';
653− if (hasMascot) {
654− var useMascotShape = !hasBackground && !headerAsOverlay;
655− var mascotAnchors = '';
656− if (!hasHeaderRow) {
657− mascotAnchors += headerLeftAnchor;
658− mascotAnchors += headerVerticalAnchors;
659− if (!headerLeftAnchorHasMargin) {
660− mascotAnchors += 'leftMargin: units.gu(1);\n'
661− }
662− } else {
663− mascotAnchors = 'verticalCenter: parent.verticalCenter;'
664− }
665−
666− if (useMascotShape) {
667− mascotShapeCode = kMascotShapeLoaderCode.arg(mascotAnchors).arg(asynchronous);
668− }
669−
670− var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
671− var fallback = !isCardTool && components["mascot"] && components["mascot"]["fallback"] || "";
672− fallback = encodeURI(fallback);
673− var fallbackStatusCode = "";
674− var fallbackURICode = '""';
675− if (fallback !== "") {
676− // fallbackStatusCode has %4 in it because we want to substitute it for fallbackURICode
677− // which in kMascotImageCode is %4
678− fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %4;';
679− fallbackURICode = 'decodeURI("%1")'.arg(fallback);
680− }
681− mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible).arg(fallbackStatusCode).arg(fallbackURICode);
682− }
683−
684− 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")';
685−
686− var hasTitleContainer = hasTitle && (hasEmblem || (hasMascot && (hasSubtitle || hasAttributes)));
687− var titleSubtitleCode = '';
688− if (hasTitle) {
689− var titleColor;
690− if (headerAsOverlay) {
691− titleColor = 'root.scopeStyle && overlayLoader.item ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item && overlayLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white")';
692− } else if (hasSummary) {
693− titleColor = 'summary.color';
694− } else if (hasBackground) {
695− titleColor = summaryColorWithBackground;
696− } else {
697− titleColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
698− }
699−
700− var titleAnchors;
701− var subtitleAnchors;
702− var attributesAnchors;
703− var titleContainerAnchors;
704− var titleRightAnchor;
705− var titleWidth = "undefined";
706−
707− var extraRightAnchor = '';
708− var extraLeftAnchor = '';
709− if (!touchdownOnArtShape) {
710− extraRightAnchor = 'rightMargin: units.gu(1); \n';
711− extraLeftAnchor = 'leftMargin: units.gu(1); \n';
712− } else if (headerAsOverlay && !hasEmblem) {
713− extraRightAnchor = 'rightMargin: units.gu(1); \n';
714− }
715−
716− if (hasMascot) {
717− titleContainerAnchors = 'verticalCenter: parent.verticalCenter; ';
718− } else {
719− titleContainerAnchors = 'right: parent.right; ';
720− titleContainerAnchors += headerLeftAnchor;
721− titleContainerAnchors += headerVerticalAnchors;
722− if (!headerLeftAnchorHasMargin) {
723− titleContainerAnchors += extraLeftAnchor;
724− }
725− }
726− if (hasEmblem) {
727− titleRightAnchor = 'right: emblemIcon.left; \n\
728− rightMargin: emblemIcon.width > 0 ? units.gu(0.5) : 0; \n';
729− } else {
730− titleRightAnchor = 'right: parent.right; \n'
731− titleRightAnchor += extraRightAnchor;
732− }
733−
734− if (hasTitleContainer) {
735− // Using headerTitleContainer
736− titleAnchors = titleRightAnchor;
737− titleAnchors += 'left: parent.left; \n\
738− top: parent.top;';
739− subtitleAnchors = 'right: parent.right; \n\
740− left: parent.left; \n';
741− subtitleAnchors += extraRightAnchor;
742− if (hasSubtitle) {
743− attributesAnchors = subtitleAnchors + 'top: subtitleLabel.bottom;\n';
744− subtitleAnchors += 'top: titleLabel.bottom;\n';
745− } else {
746− attributesAnchors = subtitleAnchors + 'top: titleLabel.bottom;\n';
747− }
748− } else if (hasMascot) {
749− // Using row without titleContainer
750− titleAnchors = 'verticalCenter: parent.verticalCenter;\n';
751− titleWidth = "parent.width - x";
752− } else {
753− if (headerAsOverlay) {
754− // Using anchors to the overlay
755− titleAnchors = titleRightAnchor;
756− titleAnchors += 'left: parent.left; \n\
757− leftMargin: units.gu(1); \n\
758− top: overlayLoader.top; \n\
759− topMargin: units.gu(1) + overlayLoader.height - overlayLoader.overlayHeight; \n';
760− } else {
761− // Using anchors to the mascot/parent
762− titleAnchors = titleRightAnchor;
763− titleAnchors += headerLeftAnchor;
764− titleAnchors += headerVerticalAnchors;
765− if (!headerLeftAnchorHasMargin) {
766− titleAnchors += extraLeftAnchor;
767− }
768− }
769− subtitleAnchors = 'left: titleLabel.left; \n\
770− leftMargin: titleLabel.leftMargin; \n';
771− subtitleAnchors += extraRightAnchor;
772− if (hasEmblem) {
773− // using container
774− subtitleAnchors += 'right: parent.right; \n';
775− } else {
776− subtitleAnchors += 'right: titleLabel.right; \n';
777− }
778−
779− if (hasSubtitle) {
780− attributesAnchors = subtitleAnchors + 'top: subtitleLabel.bottom;\n';
781− subtitleAnchors += 'top: titleLabel.bottom;\n';
782− } else {
783− attributesAnchors = subtitleAnchors + 'top: titleLabel.bottom;\n';
784− }
785− }
786−
787− var titleAlignment = "Text.AlignHCenter";
788− if (template["card-layout"] === "horizontal"
789− || typeof components["title"] !== "object"
790− || components["title"]["align"] === "left") titleAlignment = "Text.AlignLeft";
791− var keys = ["mascot", "emblem", "subtitle", "attributes", "summary"];
792− for (var key in keys) {
793− key = keys[key];
794− try {
795− if (typeof components[key] === "string"
796− || typeof components[key]["field"] === "string") titleAlignment = "Text.AlignLeft";
797− } catch (e) {
798− continue;
799− }
800− }
801−
802− // code for different elements
803− var titleLabelVisibleExtra = (headerAsOverlay ? '&& overlayLoader.active': '');
804− var titleCode = kTitleLabelCode.arg(titleAnchors).arg(titleColor).arg(titleLabelVisibleExtra).arg(titleWidth).arg(titleAlignment);
805− var subtitleCode;
806− var attributesCode;
807−
808− // code for the title container
809− var containerCode = [];
810− var containerHeight = 'titleLabel.height';
811− containerCode.push(titleCode);
812− if (hasSubtitle) {
813− subtitleCode = kSubtitleLabelCode.arg(subtitleAnchors).arg(titleColor);
814− containerCode.push(subtitleCode);
815− containerHeight += ' + subtitleLabel.height';
816− }
817− if (hasEmblem) {
818− containerCode.push(kEmblemIconCode.arg(extraRightAnchor).arg(titleColor));
819− }
820− if (hasAttributes) {
821− attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(titleColor);
822− containerCode.push(attributesCode);
823− containerHeight += ' + attributesRow.height';
824− }
825−
826− if (hasTitleContainer) {
827− // use container
828− titleSubtitleCode = kHeaderContainerCodeGenerator(titleContainerAnchors, containerHeight, containerCode);
829− } else {
830− // no container
831− titleSubtitleCode = titleCode;
832− if (hasSubtitle) {
833− titleSubtitleCode += subtitleCode;
834− }
835− if (hasAttributes) {
836− titleSubtitleCode += attributesCode;
837− }
838− }
839− }
840−
841− if (hasHeaderRow) {
842− var rowCode = [mascotCode, titleSubtitleCode];
843− if (mascotShapeCode != '') {
844− rowCode.unshift(mascotShapeCode);
845− }
846− code += kHeaderRowCodeGenerator(isCardTool, headerVerticalAnchors + headerLeftAnchor, rowCode)
847− } else {
848− code += mascotShapeCode + mascotCode + titleSubtitleCode;
849− }
850−
851− if (isAudio) {
852− var audioProgressBarLeftAnchor = 'audioButton.right';
853− var audioProgressBarBottomAnchor = 'audioButton.bottom';
854− var audioProgressBarTextColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
855−
856− code += kAudioProgressBarCode.arg(audioProgressBarBottomAnchor)
857− .arg(audioProgressBarLeftAnchor)
858− .arg(audioProgressBarTextColor);
859−
860− var audioButtonAnchorsFill;
861− var audioButtonWidth;
862− var audioButtonHeight;
863− if (hasArt) {
864− audioButtonAnchorsFill = 'artShapeLoader';
865− audioButtonWidth = 'undefined';
866− audioButtonHeight = 'undefined';
867− } else {
868− audioButtonAnchorsFill = 'undefined';
869− audioButtonWidth = 'height';
870− audioButtonHeight = isCardTool ? 'headerHeight + 2 * units.gu(1)'
871− : 'root.fixedHeaderHeight + 2 * units.gu(1)';
872− }
873− code += kAudioButtonCode.arg(audioButtonAnchorsFill).arg(audioButtonWidth).arg(audioButtonHeight).arg(asynchronous);
874− }
875−
876− if (hasSummary) {
877− var summaryTopAnchor;
878− if (isHorizontal && hasArt) summaryTopAnchor = 'artShapeLoader.bottom';
879− else if (headerAsOverlay && hasArt) summaryTopAnchor = 'artShapeLoader.bottom';
880− else if (hasHeaderRow) summaryTopAnchor = 'row.bottom';
881− else if (hasTitleContainer) summaryTopAnchor = 'headerTitleContainer.bottom';
882− else if (hasMascot) summaryTopAnchor = 'mascotImage.bottom';
883− else if (hasAttributes) summaryTopAnchor = 'attributesRow.bottom';
884− else if (hasSubtitle) summaryTopAnchor = 'subtitleLabel.bottom';
885− else if (hasTitle) summaryTopAnchor = 'titleLabel.bottom';
886− else if (hasArt) summaryTopAnchor = 'artShapeLoader.bottom';
887− else summaryTopAnchor = 'parent.top';
888−
889− var summaryColor;
890− if (hasBackground) {
891− summaryColor = summaryColorWithBackground;
892− } else {
893− summaryColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
894− }
895−
896− var summaryTopMargin = (hasMascot || hasSubtitle || hasAttributes ? 'anchors.margins' : '0');
897−
898− code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(summaryColor);
899− }
900−
901− if (hasSocialActions) {
902− var socialAnchors;
903− var socialTopAnchor;
904−
905− if (hasSummary) socialTopAnchor = 'summary.bottom;';
906− else if (isHorizontal && hasArt) socialTopAnchor = 'artShapeLoader.bottom;';
907− else if (headerAsOverlay && hasArt) socialTopAnchor = 'artShapeLoader.bottom;';
908− else if (hasHeaderRow) socialTopAnchor = 'row.bottom;';
909− else if (hasTitleContainer) socialTopAnchor = 'headerTitleContainer.bottom;';
910− else if (hasMascot) socialTopAnchor = 'mascotImage.bottom;';
911− else if (hasAttributes) socialTopAnchor = 'attributesRow.bottom;';
912− else if (hasSubtitle) socialTopAnchor = 'subtitleLabel.bottom;';
913− else if (hasTitle) socialTopAnchor = 'titleLabel.bottom;';
914− else if (hasArt) socialTopAnchor = 'artShapeLoader.bottom;';
915− else socialTopAnchor = 'parent.top';
916−
917− socialAnchors = 'top: ' + socialTopAnchor + ' left: parent.left; right: parent.right; topMargin: units.gu(1);'
918−
919− var socialColor;
920− if (hasBackground) {
921− socialColor = summaryColorWithBackground;
922− } else {
923− socialColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
924− }
925−
926− code += kSocialActionsRowCode.arg(socialAnchors).arg(socialColor);
927− }
928−
929− if (artShapeStyle != "shadow" && artShapeStyle != "icon" && !isCardTool) {
930− var touchdownAnchors;
931− if (hasBackground) {
932− touchdownAnchors = 'fill: backgroundLoader';
933− } else if (touchdownOnArtShape) {
934− touchdownAnchors = 'fill: artShapeLoader';
935− } else {
936− touchdownAnchors = 'fill: root'
937− }
938− code += kTouchdownCode.arg(touchdownAnchors);
939− }
940−
941− if (isCardTool || categoryLayout !== "grid") {
942− var implicitHeight = 'implicitHeight: ';
943− if (hasSocialActions) {
944− implicitHeight += 'socialActionsRow.y + socialActionsRow.height + units.gu(1);\n';
945− } else if (hasSummary) {
946− implicitHeight += 'summary.y + summary.height + units.gu(1);\n';
947− } else if (isAudio) {
948− implicitHeight += 'audioButton.height;\n';
949− } else if (headerAsOverlay) {
950− implicitHeight += 'artShapeLoader.height;\n';
951− } else if (hasHeaderRow) {
952− implicitHeight += 'row.y + row.height + units.gu(1);\n';
953− } else if (hasMascot) {
954− implicitHeight += 'mascotImage.y + mascotImage.height;\n';
955− } else if (hasTitleContainer) {
956− implicitHeight += 'headerTitleContainer.y + headerTitleContainer.height + units.gu(1);\n';
957− } else if (hasAttributes) {
958− implicitHeight += 'attributesRow.y + attributesRow.height + units.gu(1);\n';
959− } else if (hasSubtitle) {
960− implicitHeight += 'subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
961− } else if (hasTitle) {
962− implicitHeight += 'titleLabel.y + titleLabel.height + units.gu(1);\n';
963− } else if (hasArt) {
964− implicitHeight += 'artShapeLoader.height;\n';
965− } else {
966− implicitHeight = '';
967− }
968− } else {
969− implicitHeight = '';
970− }
971−
972− // Close the AbstractButton
973− code += implicitHeight + '}\n';
974−
975− return code;
976−}
977−
978−function createCardComponent(parent, template, components, isCardTool, artShapeStyle, categoryLayout, identifier) {
979− var imports = 'import QtQuick 2.4; \n\
980− import Ubuntu.Components 1.3; \n\
981− import Ubuntu.Settings.Components 0.1; \n\
982− import Dash 0.1;\n\
983− import Utils 0.1;\n';
984− var card = cardString(template, components, isCardTool, artShapeStyle, categoryLayout);
985− var code = imports + 'Component {\n' + card + '}\n';
986−
987− try {
988− return Qt.createQmlObject(code, parent, identifier);
989− } catch (e) {
990− console.error("ERROR: Invalid component created.");
991− console.error("Template:");
992− console.error(JSON.stringify(template));
993− console.error("Components:");
994− console.error(JSON.stringify(components));
995− console.error("Code:");
996− console.error(code);
997− throw e;
998− }
999−}
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, isCardTool, artShapeStyle, categoryLayout) {
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 + isCardTool + artShapeStyle + categoryLayout;
33− var component = cache[allString];
34− if (component === undefined) {
35− component = CardCreator.createCardComponent(root, template, components, isCardTool, artShapeStyle, categoryLayout, allString);
36− cache[allString] = component;
37− }
38− return component;
39− }
40−}
plugins/Dash/CardSocialActions.qmldeleted−94
@@ -1,94 +0,0 @@
1−/*
2− * Copyright 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−import QtQuick 2.4
18−import QtQuick.Layouts 1.1
19−import Ubuntu.Components 1.3
20−
21−Column {
22− id: socialActions
23− spacing: units.gu(0.5)
24−
25− property alias model: repeater.model
26− property color color: theme.palette.normal.baseText
27−
28− signal clicked(var actionId)
29−
30− Rectangle {
31− id: divider
32− visible: repeater.count > 0
33− anchors {
34− left: parent.left;
35− right: parent.right;
36− leftMargin:units.dp(1);
37− rightMargin: units.dp(1);
38− }
39− color: Qt.darker(theme.palette.normal.background, 1.12)
40− height: visible ? units.dp(1) : 0
41− }
42−
43− Row {
44− id: row
45− anchors {
46− left: parent.left
47− right: parent.right
48− leftMargin: units.gu(1)
49− rightMargin: units.gu(1)
50− }
51− spacing: units.gu(2)
52− readonly property int visibleItems: {
53− if (width <= units.gu(12)) // small card
54− return 2;
55− else if (width <= units.gu(21)) // medium card
56− return 3;
57− else // large or horizontal card
58− return 4;
59− }
60−
61− Repeater {
62− id: repeater
63− delegate: Loader {
64− height: units.gu(2)
65− active: index < row.visibleItems
66− sourceComponent: AbstractButton {
67− objectName: "delegate" + index
68− height: units.gu(2)
69− width: icon.width
70− Icon {
71− id: icon
72− objectName: "icon"
73−
74− readonly property url urlIcon: modelData && modelData["icon"] || ""
75− readonly property url urlTemporaryIcon: "temporaryIcon" in modelData && modelData["temporaryIcon"] || ""
76−
77− height: units.gu(2)
78− // FIXME Workaround for bug https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1421293
79− width: implicitWidth > 0 && implicitHeight > 0 ? (implicitWidth / implicitHeight * height) : implicitWidth
80− source: urlIcon
81− color: socialActions.color
82−
83− onUrlIconChanged: {
84− if (urlIcon) source = urlIcon
85− }
86− }
87−
88− onClicked: socialActions.clicked(modelData["id"]);
89− onPressedChanged: if (pressed && icon.urlTemporaryIcon != "") icon.source = icon.urlTemporaryIcon
90− }
91− }
92− }
93− }
94−}
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/DashAudioPlayer.qmldeleted−120
@@ -1,120 +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−pragma Singleton
18−import QtQuick 2.4
19−import QtMultimedia 5.6
20−import Dash 0.1
21−
22−QtObject {
23− id: root
24− readonly property real progress: priv.audio ? priv.audio.position / priv.audio.duration : 0.0
25− readonly property bool playing: priv.audio ? priv.audio.playbackState === Audio.PlayingState : false
26− readonly property bool paused: priv.audio ? priv.audio.playbackState === Audio.PausedState : false
27− readonly property bool stopped: priv.audio ? priv.audio.playbackState === Audio.StoppedState : true
28− readonly property int position: priv.audio ? priv.audio.position : 0
29− readonly property url currentSource: priv.audio ? priv.audio.playlist.currentItemSource : ""
30− readonly property Playlist playlist: priv.audio ? priv.audio.playlist : null
31−
32− function playSource(newSource, newPlaylist) {
33− if (!priv.audio) {
34− console.info("DashAudioPlayer: creating player");
35− priv.audio = priv.audioComponent.createObject(root);
36− }
37− stop();
38− priv.audio.playlist.clear();
39− if (newPlaylist) {
40− // Look for newSource in newPlaylist
41− var sourceIndex = -1;
42− for (var i in newPlaylist) {
43− if (AudioUrlComparer.compare(newSource, newPlaylist[i])) {
44− sourceIndex = i;
45− break;
46− }
47− }
48− var urls = [];
49− if (sourceIndex === -1 && newSource != "") {
50− // If the playing song is not in the playlist, add it
51− urls.push(newSource);
52− sourceIndex = 0;
53− }
54− for (var i in newPlaylist) {
55− urls.push(newPlaylist[i]);
56− }
57− priv.audio.playlist.addItems(urls);
58− priv.audio.playlist.currentIndex = sourceIndex;
59− } else {
60− priv.audio.playlist.addItem(newSource);
61− priv.audio.playlist.currentIndex = 0;
62− }
63− play();
64− }
65−
66− function stop() {
67− if (priv.audio) {
68− priv.audio.stop();
69− }
70− }
71−
72− function play() {
73− if (priv.audio) {
74− priv.audio.play();
75− }
76− }
77−
78− function pause() {
79− if (priv.audio) {
80− priv.audio.pause();
81− }
82− }
83−
84− property QtObject priv: QtObject {
85− id: priv
86− property Audio audio: null
87− property Component audioComponent: Component {
88− Audio {
89− playlist: Playlist {
90− objectName: "playlist"
91− }
92− /* Remove player in case of error so it gets recreated next time
93− * we need it. Happens if backend media player restarted, for
94− * instance. qtmultimedia should probably handle this
95− * transparently (LP: #1616425).
96− */
97− onError: {
98− console.warn("DashAudioPlayer: error event (" +
99− priv.audio.errorString + "), destroying");
100− priv.audio.destroy();
101− }
102− }
103− }
104− }
105−
106− function lengthToString(s) {
107− if (typeof(s) !== "number" || s < 0) return "";
108−
109− var sec = "" + s % 60;
110− if (sec.length == 1) sec = "0" + sec;
111− var hour = Math.floor(s / 3600);
112− if (hour < 1) {
113− return Math.floor(s / 60) + ":" + sec;
114− } else {
115− var min = "" + Math.floor(s / 60) % 60;
116− if (min.length == 1) min = "0" + min;
117− return hour + ":" + min + ":" + sec;
118− }
119− }
120−}
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:///#ffffff"
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"] : theme.palette.normal.positive
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−359
@@ -1,359 +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−#include <private/qquickitem_p.h>
20−
21−AbstractDashView::AbstractDashView()
22− : m_delegateModel(nullptr)
23− , m_asyncRequestedIndex(-1)
24− , m_columnSpacing(0)
25− , m_rowSpacing(0)
26− , m_buffer(320) // Same value as QML_VIEW_DEFAULTCACHEBUFFER in qquickitemview.cpp (Qt 5.6)
27− , m_displayMarginBeginning(0)
28− , m_displayMarginEnd(0)
29− , m_needsRelayout(false)
30− , m_delegateValidated(false)
31− , m_implicitHeightDirty(false)
32−{
33− connect(this, &AbstractDashView::widthChanged, this, &AbstractDashView::relayout);
34− connect(this, &AbstractDashView::heightChanged, this, &AbstractDashView::onHeightChanged);
35−}
36−
37−QAbstractItemModel *AbstractDashView::model() const
38−{
39− return m_delegateModel ? m_delegateModel->model().value<QAbstractItemModel *>() : nullptr;
40−}
41−
42−void AbstractDashView::setModel(QAbstractItemModel *model)
43−{
44− if (model != this->model()) {
45− if (!m_delegateModel) {
46− createDelegateModel();
47− } else {
48− disconnect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &AbstractDashView::onModelUpdated);
49− }
50− m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
51− connect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &AbstractDashView::onModelUpdated);
52−
53− cleanupExistingItems();
54−
55− Q_EMIT modelChanged();
56− polish();
57− }
58−}
59−
60−QQmlComponent *AbstractDashView::delegate() const
61−{
62− return m_delegateModel ? m_delegateModel->delegate() : nullptr;
63−}
64−
65−void AbstractDashView::setDelegate(QQmlComponent *delegate)
66−{
67− if (delegate != this->delegate()) {
68− if (!m_delegateModel) {
69− createDelegateModel();
70− }
71−
72− cleanupExistingItems();
73−
74− m_delegateModel->setDelegate(delegate);
75−
76− Q_EMIT delegateChanged();
77− m_delegateValidated = false;
78− polish();
79− }
80−}
81−
82−qreal AbstractDashView::columnSpacing() const
83−{
84− return m_columnSpacing;
85−}
86−
87−void AbstractDashView::setColumnSpacing(qreal columnSpacing)
88−{
89− if (columnSpacing != m_columnSpacing) {
90− m_columnSpacing = columnSpacing;
91− Q_EMIT columnSpacingChanged();
92−
93− if (isComponentComplete()) {
94− relayout();
95− }
96− }
97−}
98−
99−qreal AbstractDashView::rowSpacing() const
100−{
101− return m_rowSpacing;
102−}
103−
104−void AbstractDashView::setRowSpacing(qreal rowSpacing)
105−{
106− if (rowSpacing != m_rowSpacing) {
107− m_rowSpacing = rowSpacing;
108− Q_EMIT rowSpacingChanged();
109−
110− if (isComponentComplete()) {
111− relayout();
112− }
113− }
114−}
115−
116−int AbstractDashView::cacheBuffer() const
117−{
118− return m_buffer;
119−}
120−
121−void AbstractDashView::setCacheBuffer(int buffer)
122−{
123− if (buffer < 0) {
124− qmlInfo(this) << "Cannot set a negative cache buffer";
125− return;
126− }
127−
128− if (m_buffer != buffer) {
129− m_buffer = buffer;
130− if (isComponentComplete()) {
131− polish();
132− }
133− emit cacheBufferChanged();
134− }
135−}
136−
137−qreal AbstractDashView::displayMarginBeginning() const
138−{
139− return m_displayMarginBeginning;
140−}
141−
142−void AbstractDashView::setDisplayMarginBeginning(qreal begin)
143−{
144− if (m_displayMarginBeginning == begin)
145− return;
146− m_displayMarginBeginning = begin;
147− if (isComponentComplete()) {
148− polish();
149− }
150− emit displayMarginBeginningChanged();
151−}
152−
153−qreal AbstractDashView::displayMarginEnd() const
154−{
155− return m_displayMarginEnd;
156−}
157−
158−void AbstractDashView::setDisplayMarginEnd(qreal end)
159−{
160− if (m_displayMarginEnd == end)
161− return;
162− m_displayMarginEnd = end;
163− if (isComponentComplete()) {
164− polish();
165− }
166− emit displayMarginEndChanged();
167−}
168−
169−void AbstractDashView::createDelegateModel()
170−{
171− m_delegateModel = new QQmlDelegateModel(qmlContext(this), this);
172− connect(m_delegateModel, &QQmlDelegateModel::createdItem, this, &AbstractDashView::itemCreated);
173− if (isComponentComplete())
174− m_delegateModel->componentComplete();
175−}
176−
177−void AbstractDashView::refill()
178−{
179− if (!isComponentComplete() || height() < 0) {
180− return;
181− }
182−
183− const qreal from = -m_displayMarginBeginning;
184− const qreal to = height() + m_displayMarginEnd;
185− const qreal bufferFrom = from - m_buffer;
186− const qreal bufferTo = to + m_buffer;
187−
188− bool added = addVisibleItems(from, to, false);
189− bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
190− added |= addVisibleItems(bufferFrom, bufferTo, true);
191−
192− if (added || removed) {
193− m_implicitHeightDirty = true;
194− polish();
195− }
196−}
197−
198−bool AbstractDashView::addVisibleItems(qreal fillFromY, qreal fillToY, bool asynchronous)
199−{
200− if (fillToY <= fillFromY)
201− return false;
202−
203− if (!delegate())
204− return false;
205−
206− if (m_delegateModel->count() == 0)
207− return false;
208−
209− int modelIndex;
210− qreal yPos;
211− findBottomModelIndexToAdd(&modelIndex, &yPos);
212− bool changed = false;
213− while (modelIndex < m_delegateModel->count() && yPos <= fillToY) {
214− if (!createItem(modelIndex, asynchronous))
215− break;
216−
217− changed = true;
218− findBottomModelIndexToAdd(&modelIndex, &yPos);
219− }
220−
221− findTopModelIndexToAdd(&modelIndex, &yPos);
222− while (modelIndex >= 0 && yPos > fillFromY) {
223− if (!createItem(modelIndex, asynchronous))
224− break;
225−
226− changed = true;
227− findTopModelIndexToAdd(&modelIndex, &yPos);
228− }
229−
230− return changed;
231−}
232−
233−QQuickItem *AbstractDashView::createItem(int modelIndex, bool asynchronous)
234−{
235− if (asynchronous && m_asyncRequestedIndex != -1)
236− return nullptr;
237−
238− m_asyncRequestedIndex = -1;
239− QObject* object = m_delegateModel->object(modelIndex, asynchronous);
240− QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
241− if (!item) {
242− if (object) {
243− m_delegateModel->release(object);
244− if (!m_delegateValidated) {
245− m_delegateValidated = true;
246− QObject* delegateObj = delegate();
247− qmlInfo(delegateObj ? delegateObj : this) << "Delegate must be of Item type";
248− }
249− } else {
250− m_asyncRequestedIndex = modelIndex;
251− }
252− return nullptr;
253− } else {
254− QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
255− addItemToView(modelIndex, item);
256− return item;
257− }
258−}
259−
260−void AbstractDashView::releaseItem(QQuickItem *item)
261−{
262− QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
263− QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item);
264− if (flags & QQmlDelegateModel::Destroyed) {
265− item->setParentItem(nullptr);
266− }
267−}
268−
269−void AbstractDashView::setImplicitHeightDirty()
270−{
271− m_implicitHeightDirty = true;
272−}
273−
274−void AbstractDashView::itemCreated(int modelIndex, QObject *object)
275−{
276− QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
277− if (!item) {
278− qWarning() << "AbstractDashView::itemCreated got a non item for index" << modelIndex;
279− return;
280− }
281− item->setParentItem(this);
282−
283− // We only need to call createItem if we are here because of an asynchronous generation
284− // otherwise we are in this slot because createItem is creating the item sync
285− // and thus we don't need to call createItem again, nor need to set m_implicitHeightDirty
286− // and call polish because the sync createItem was called from addVisibleItems that
287− // is called from refill that will already do those if an item was added
288− if (modelIndex == m_asyncRequestedIndex) {
289− createItem(modelIndex, false);
290− m_implicitHeightDirty = true;
291− polish();
292− }
293−}
294−
295−void AbstractDashView::onModelUpdated(const QQmlChangeSet &changeSet, bool reset)
296−{
297− if (reset) {
298− cleanupExistingItems();
299− } else {
300− processModelRemoves(changeSet.removes());
301−
302− // The current AbstractDashViews do not support insertions that are not at the end
303− // so reset if that happens
304− Q_FOREACH(const QQmlChangeSet::Change insert, changeSet.inserts()) {
305− if (insert.index < m_delegateModel->count() - 1) {
306− cleanupExistingItems();
307− break;
308− }
309− }
310− }
311− polish();
312−}
313−
314−
315−void AbstractDashView::relayout()
316−{
317− m_needsRelayout = true;
318− polish();
319−}
320−
321−void AbstractDashView::onHeightChanged()
322−{
323− polish();
324−}
325−
326−void AbstractDashView::updatePolish()
327−{
328− if (!model())
329− return;
330−
331− if (m_needsRelayout) {
332− doRelayout();
333− m_needsRelayout = false;
334− m_implicitHeightDirty = true;
335− }
336−
337− refill();
338−
339− const qreal from = -m_displayMarginBeginning;
340− const qreal to = height() + m_displayMarginEnd;
341− updateItemCulling(from, to);
342−
343− if (m_implicitHeightDirty) {
344− calculateImplicitHeight();
345− m_implicitHeightDirty = false;
346− }
347−}
348−
349−void AbstractDashView::componentComplete()
350−{
351− if (m_delegateModel)
352− m_delegateModel->componentComplete();
353−
354− QQuickItem::componentComplete();
355−
356− m_needsRelayout = true;
357−
358− polish();
359−}
plugins/Dash/abstractdashview.hdeleted−128
@@ -1,128 +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−
25−#include <private/qqmldelegatemodel_p.h>
26−#include <private/qquickitemchangelistener_p.h>
27−#include <qqmlinfo.h>
28−
29−class AbstractDashView : public QQuickItem, public QQuickItemChangeListener
30−{
31− Q_OBJECT
32−
33− Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
34− Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
35− Q_PROPERTY(qreal columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
36− Q_PROPERTY(qreal rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged)
37− Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
38− Q_PROPERTY(qreal displayMarginBeginning READ displayMarginBeginning
39− WRITE setDisplayMarginBeginning
40− NOTIFY displayMarginBeginningChanged)
41− Q_PROPERTY(qreal displayMarginEnd READ displayMarginEnd
42− WRITE setDisplayMarginEnd
43− NOTIFY displayMarginEndChanged)
44−
45−friend class VerticalJournalTest;
46−friend class HorizontalJournalTest;
47−friend class OrganicGridTest;
48−
49−public:
50− AbstractDashView();
51−
52− QAbstractItemModel *model() const;
53− void setModel(QAbstractItemModel *model);
54−
55− QQmlComponent *delegate() const;
56− void setDelegate(QQmlComponent *delegate);
57−
58− qreal columnSpacing() const;
59− void setColumnSpacing(qreal columnSpacing);
60−
61− qreal rowSpacing() const;
62− void setRowSpacing(qreal rowSpacing);
63−
64− int cacheBuffer() const;
65− void setCacheBuffer(int);
66−
67− qreal displayMarginBeginning() const;
68− void setDisplayMarginBeginning(qreal);
69−
70− qreal displayMarginEnd() const;
71− void setDisplayMarginEnd(qreal);
72−
73−Q_SIGNALS:
74− void modelChanged();
75− void delegateChanged();
76− void columnSpacingChanged();
77− void rowSpacingChanged();
78− void cacheBufferChanged();
79− void displayMarginBeginningChanged();
80− void displayMarginEndChanged();
81−
82−protected Q_SLOTS:
83− void relayout();
84−
85−protected:
86− void updatePolish() override;
87− void componentComplete() override;
88−
89− void releaseItem(QQuickItem *item);
90− void setImplicitHeightDirty();
91−
92−private Q_SLOTS:
93− void itemCreated(int modelIndex, QObject *object);
94− void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
95− void onHeightChanged();
96−
97−private:
98− void createDelegateModel();
99− void refill();
100− bool addVisibleItems(qreal fillFromY, qreal fillToY, bool asynchronous);
101− QQuickItem *createItem(int modelIndex, bool asynchronous);
102−
103− virtual void findBottomModelIndexToAdd(int *modelIndex, qreal *yPos) = 0;
104− virtual void findTopModelIndexToAdd(int *modelIndex, qreal *yPos) = 0;
105− virtual void addItemToView(int modelIndex, QQuickItem *item) = 0;
106− virtual bool removeNonVisibleItems(qreal bufferFromY, qreal bufferToY) = 0;
107− virtual void cleanupExistingItems() = 0;
108− virtual void doRelayout() = 0;
109− virtual void updateItemCulling(qreal visibleFromY, qreal visibleToY) = 0;
110− virtual void calculateImplicitHeight() = 0;
111− virtual void processModelRemoves(const QVector<QQmlChangeSet::Change> &removes) = 0;
112−
113− QQmlDelegateModel *m_delegateModel;
114−
115− // Index we are waiting because we requested it asynchronously
116− int m_asyncRequestedIndex;
117−
118− int m_columnSpacing;
119− int m_rowSpacing;
120− int m_buffer;
121− qreal m_displayMarginBeginning;
122− qreal m_displayMarginEnd;
123− bool m_needsRelayout;
124− bool m_delegateValidated;
125− bool m_implicitHeightDirty;
126−};
127−
128−#endif
plugins/Dash/graphics/music_progress_bg.pngdeleted

Binary file not shown.

plugins/Dash/horizontaljournal.cppdeleted−239
@@ -1,239 +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−#include <qqmlinfo.h>
30−#include <private/qqmldelegatemodel_p.h>
31−#include <private/qquickitem_p.h>
32−
33−HorizontalJournal::HorizontalJournal()
34− : m_firstVisibleIndex(-1)
35− , m_rowHeight(0)
36−{
37−}
38−
39−qreal HorizontalJournal::rowHeight() const
40−{
41− return m_rowHeight;
42−}
43−
44−void HorizontalJournal::setRowHeight(qreal rowHeight)
45−{
46− if (rowHeight != m_rowHeight) {
47− m_rowHeight = rowHeight;
48− Q_EMIT rowHeightChanged();
49−
50− if (isComponentComplete()) {
51− Q_FOREACH(QQuickItem *item, m_visibleItems) {
52− item->setHeight(rowHeight);
53− }
54− relayout();
55− }
56− }
57−}
58−
59−void HorizontalJournal::findBottomModelIndexToAdd(int *modelIndex, qreal *yPos)
60−{
61− if (m_visibleItems.isEmpty()) {
62− *modelIndex = 0;
63− *yPos = 0;
64− } else {
65− *modelIndex = m_firstVisibleIndex + m_visibleItems.count();
66− if (m_lastInRowIndexPosition.contains(*modelIndex - 1)) {
67− *yPos = m_visibleItems.last()->y() + m_rowHeight + rowSpacing();
68− } else {
69− *yPos = m_visibleItems.last()->y();
70− }
71− }
72−}
73−
74−void HorizontalJournal::findTopModelIndexToAdd(int *modelIndex, qreal *yPos)
75−{
76− if (m_visibleItems.isEmpty()) {
77− *modelIndex = -1;
78− *yPos = INT_MIN;
79− } else {
80− *modelIndex = m_firstVisibleIndex - 1;
81− if (m_lastInRowIndexPosition.contains(*modelIndex)) {
82− *yPos = m_visibleItems.first()->y() - rowSpacing() - m_rowHeight;
83− } else {
84− *yPos = m_visibleItems.first()->y();
85− }
86− }
87−}
88−
89−bool HorizontalJournal::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
90−{
91− bool changed = false;
92−
93− while (!m_visibleItems.isEmpty() && m_visibleItems.first()->y() + m_rowHeight < bufferFromY) {
94− releaseItem(m_visibleItems.takeFirst());
95− changed = true;
96− m_firstVisibleIndex++;
97− }
98−
99− while (!m_visibleItems.isEmpty() && m_visibleItems.last()->y() > bufferToY) {
100− releaseItem(m_visibleItems.takeLast());
101− changed = true;
102− m_lastInRowIndexPosition.remove(m_firstVisibleIndex + m_visibleItems.count());
103− }
104−
105− if (m_visibleItems.isEmpty()) {
106− m_firstVisibleIndex = -1;
107− }
108−
109− return changed;
110−}
111−
112−void HorizontalJournal::addItemToView(int modelIndex, QQuickItem *item)
113−{
114− if (item->height() != m_rowHeight) {
115− qWarning() << "Item" << modelIndex << "height is not the one that the rowHeight mandates, resetting it";
116− item->setHeight(m_rowHeight);
117− }
118−
119− if (m_visibleItems.isEmpty()) {
120− Q_ASSERT(modelIndex == 0);
121− item->setY(0);
122− item->setX(0);
123− m_visibleItems << item;
124− m_firstVisibleIndex = 0;
125− } else {
126− // modelIndex has to be either m_firstVisibleIndex - 1 or m_firstVisibleIndex + m_visibleItems.count()
127− if (modelIndex == m_firstVisibleIndex + m_visibleItems.count()) {
128− QQuickItem *lastItem = m_visibleItems.last();
129− if (lastItem->x() + lastItem->width() + columnSpacing() + item->width() <= width()) {
130− // Fits in the row
131− item->setY(lastItem->y());
132− item->setX(lastItem->x() + lastItem->width() + columnSpacing());
133− } else {
134− // Starts a new row
135− item->setY(lastItem->y() + m_rowHeight + rowSpacing());
136− item->setX(0);
137− m_lastInRowIndexPosition[modelIndex - 1] = lastItem->x();
138− }
139− m_visibleItems << item;
140− } else if (modelIndex == m_firstVisibleIndex - 1) {
141− QQuickItem *firstItem = m_visibleItems.first();
142− if (m_lastInRowIndexPosition.contains(modelIndex)) {
143− // It is the last item of its row, so start a new one since we're going back
144− item->setY(firstItem->y() - rowSpacing() - m_rowHeight);
145− item->setX(m_lastInRowIndexPosition[modelIndex]);
146− } else {
147− item->setY(firstItem->y());
148− item->setX(firstItem->x() - columnSpacing() - item->width());
149− }
150− m_firstVisibleIndex = modelIndex;
151− m_visibleItems.prepend(item);
152− } else {
153− qWarning() << "HorizontalJournal::addItemToView - Got unexpected modelIndex"
154− << modelIndex << m_firstVisibleIndex << m_visibleItems.count();
155− }
156− }
157−}
158−
159−void HorizontalJournal::cleanupExistingItems()
160−{
161− // Cleanup the existing items
162− Q_FOREACH(QQuickItem *item, m_visibleItems)
163− releaseItem(item);
164− m_visibleItems.clear();
165− m_lastInRowIndexPosition.clear();
166− m_firstVisibleIndex = -1;
167− setImplicitHeightDirty();
168−}
169−
170−void HorizontalJournal::calculateImplicitHeight()
171−{
172− if (m_firstVisibleIndex >= 0) {
173− const int nIndexes = m_firstVisibleIndex + m_visibleItems.count();
174− const double bottomMostY = m_visibleItems.last()->y() + m_rowHeight;
175− const double averageHeight = bottomMostY / nIndexes;
176− setImplicitHeight(bottomMostY + averageHeight * (model()->rowCount() - nIndexes));
177− } else {
178− setImplicitHeight(0);
179− }
180−}
181−
182−void HorizontalJournal::processModelRemoves(const QVector<QQmlChangeSet::Change> &removes)
183−{
184− Q_FOREACH(const QQmlChangeSet::Change remove, removes) {
185− for (int i = remove.count - 1; i >= 0; --i) {
186− const int indexToRemove = remove.index + i;
187− // We only support removing from the end so
188− // any of the last items of a column has to be indexToRemove
189− const int lastIndex = m_firstVisibleIndex + m_visibleItems.count() - 1;
190− if (indexToRemove == lastIndex) {
191− releaseItem(m_visibleItems.takeLast());
192− m_lastInRowIndexPosition.remove(indexToRemove);
193− } else {
194− if (indexToRemove < lastIndex) {
195− qDebug() << "HorizontalJournal only supports removal from the end of the model, resetting instead";
196− cleanupExistingItems();
197− break;
198− } else {
199− setImplicitHeightDirty();
200− }
201− }
202− }
203− }
204− if (m_visibleItems.isEmpty()) {
205− m_firstVisibleIndex = -1;
206− }
207−}
208−
209−
210−void HorizontalJournal::doRelayout()
211−{
212− // If m_firstVisibleIndex is not 0 we need to drop all the delegates
213− // since we can't consistently relayout without the first item being there
214−
215− if (m_firstVisibleIndex == 0) {
216− int i = 0;
217− const QList<QQuickItem*> allItems = m_visibleItems;
218− m_visibleItems.clear();
219− m_lastInRowIndexPosition.clear();
220− Q_FOREACH(QQuickItem *item, allItems) {
221− addItemToView(i, item);
222− ++i;
223− }
224− } else {
225− Q_FOREACH(QQuickItem *item, m_visibleItems) {
226− releaseItem(item);
227− }
228− m_visibleItems.clear();
229− m_lastInRowIndexPosition.clear();
230− m_firstVisibleIndex = -1;
231− }
232−}
233−
234−void HorizontalJournal::updateItemCulling(qreal visibleFromY, qreal visibleToY)
235−{
236− Q_FOREACH(QQuickItem *item, m_visibleItems) {
237− QQuickItemPrivate::get(item)->setCulled(item->y() + m_rowHeight <= visibleFromY || item->y() >= visibleToY);
238− }
239−}
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−1394
@@ -1,1394 +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−#include <private/qqmlcontext_p.h>
99−#include <private/qqmldelegatemodel_p.h>
100−#include <private/qqmlglobal_p.h>
101−#include <private/qquickitem_p.h>
102−#include <private/qquickanimation_p.h>
103−// #include <private/qquickrectangle_p.h>
104−
105−qreal ListViewWithPageHeader::ListItem::height() const
106−{
107− return m_item->height() + (m_sectionItem ? m_sectionItem->height() : 0);
108−}
109−
110−qreal ListViewWithPageHeader::ListItem::y() const
111−{
112− return m_item->y() - (m_sectionItem ? m_sectionItem->height() : 0);
113−}
114−
115−void ListViewWithPageHeader::ListItem::setY(qreal newY)
116−{
117− if (m_sectionItem) {
118− m_sectionItem->setY(newY);
119− m_item->setY(newY + m_sectionItem->height());
120− } else {
121− m_item->setY(newY);
122− }
123−}
124−
125−bool ListViewWithPageHeader::ListItem::culled() const
126−{
127− return QQuickItemPrivate::get(m_item)->culled;
128−}
129−
130−void ListViewWithPageHeader::ListItem::setCulled(bool culled)
131−{
132− QQuickItemPrivate::get(m_item)->setCulled(culled);
133− if (m_sectionItem)
134− QQuickItemPrivate::get(m_sectionItem)->setCulled(culled);
135−}
136−
137−void ListViewWithPageHeader::ListItem::setSectionItem(QQuickItem *sectionItem)
138−{
139− m_sectionItem = sectionItem;
140−}
141−
142−ListViewWithPageHeader::ListViewWithPageHeader()
143− : m_delegateModel(nullptr)
144− , m_asyncRequestedIndex(-1)
145− , m_delegateValidated(false)
146− , m_firstVisibleIndex(-1)
147− , m_minYExtent(0)
148− , m_contentHeightDirty(false)
149− , m_headerItem(nullptr)
150− , m_previousContentY(0)
151− , m_headerItemShownHeight(0)
152− , m_sectionDelegate(nullptr)
153− , m_topSectionItem(nullptr)
154− , m_forceNoClip(false)
155− , m_inLayout(false)
156− , m_inContentHeightKeepHeaderShown(false)
157− , m_cacheBuffer(0)
158−{
159− m_clipItem = new QQuickItem(contentItem());
160−// m_clipItem = new QQuickRectangle(contentItem());
161−// ((QQuickRectangle*)m_clipItem)->setColor(Qt::gray);
162−
163− m_contentYAnimation = new QQuickNumberAnimation(this);
164− m_contentYAnimation->setEasing(QEasingCurve::OutQuad);
165− m_contentYAnimation->setProperty(QStringLiteral("contentY"));
166− m_contentYAnimation->setDuration(200);
167− m_contentYAnimation->setTargetObject(this);
168−
169− connect(contentItem(), &QQuickItem::widthChanged, this, &ListViewWithPageHeader::onContentWidthChanged);
170− connect(this, &ListViewWithPageHeader::contentHeightChanged, this, &ListViewWithPageHeader::onContentHeightChanged);
171− connect(this, &ListViewWithPageHeader::heightChanged, this, &ListViewWithPageHeader::onHeightChanged);
172− connect(m_contentYAnimation, &QQuickNumberAnimation::runningChanged, this, &ListViewWithPageHeader::contentYAnimationRunningChanged);
173−
174− setFlickableDirection(VerticalFlick);
175−}
176−
177−ListViewWithPageHeader::~ListViewWithPageHeader()
178−{
179−}
180−
181−QAbstractItemModel *ListViewWithPageHeader::model() const
182−{
183− return m_delegateModel ? m_delegateModel->model().value<QAbstractItemModel *>() : nullptr;
184−}
185−
186−void ListViewWithPageHeader::setModel(QAbstractItemModel *model)
187−{
188− if (model != this->model()) {
189− if (!m_delegateModel) {
190− createDelegateModel();
191− } else {
192− disconnect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &ListViewWithPageHeader::onModelUpdated);
193− }
194− m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
195− connect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &ListViewWithPageHeader::onModelUpdated);
196− Q_EMIT modelChanged();
197− polish();
198− // TODO?
199−// Q_EMIT contentHeightChanged();
200−// Q_EMIT contentYChanged();
201− }
202−}
203−
204−QQmlComponent *ListViewWithPageHeader::delegate() const
205−{
206− return m_delegateModel ? m_delegateModel->delegate() : nullptr;
207−}
208−
209−void ListViewWithPageHeader::setDelegate(QQmlComponent *delegate)
210−{
211− if (delegate != this->delegate()) {
212− if (!m_delegateModel) {
213− createDelegateModel();
214− }
215−
216− // Cleanup the existing items
217− Q_FOREACH(ListItem *item, m_visibleItems)
218− releaseItem(item);
219− m_visibleItems.clear();
220− initializeValuesForEmptyList();
221−
222− m_delegateModel->setDelegate(delegate);
223−
224− Q_EMIT delegateChanged();
225− m_delegateValidated = false;
226− m_contentHeightDirty = true;
227− polish();
228− }
229−}
230−
231−void ListViewWithPageHeader::initializeValuesForEmptyList()
232−{
233− m_firstVisibleIndex = -1;
234− adjustMinYExtent();
235− setContentY(0);
236− m_clipItem->setY(0);
237− if (m_topSectionItem) {
238− QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
239− }
240−}
241−
242−QQuickItem *ListViewWithPageHeader::header() const
243−{
244− return m_headerItem;
245−}
246−
247−void ListViewWithPageHeader::setHeader(QQuickItem *headerItem)
248−{
249− if (m_headerItem != headerItem) {
250− qreal oldHeaderHeight = 0;
251− qreal oldHeaderY = 0;
252− if (m_headerItem) {
253− oldHeaderHeight = m_headerItem->height();
254− oldHeaderY = m_headerItem->y();
255− m_headerItem->setParentItem(nullptr);
256− QQuickItemPrivate::get(m_headerItem)->removeItemChangeListener(this, QQuickItemPrivate::ImplicitHeight);
257− }
258− m_headerItem = headerItem;
259− if (m_headerItem) {
260− m_headerItem->setParentItem(contentItem());
261− m_headerItem->setZ(1);
262− m_previousHeaderImplicitHeight = m_headerItem->implicitHeight();
263− QQuickItemPrivate::get(m_headerItem)->addItemChangeListener(this, QQuickItemPrivate::ImplicitHeight);
264− }
265− qreal newHeaderHeight = m_headerItem ? m_headerItem->height() : 0;
266− if (!m_visibleItems.isEmpty() && newHeaderHeight != oldHeaderHeight) {
267− headerHeightChanged(newHeaderHeight, oldHeaderHeight, oldHeaderY);
268− polish();
269− m_contentHeightDirty = true;
270− }
271− Q_EMIT headerChanged();
272− }
273−}
274−
275−QQmlComponent *ListViewWithPageHeader::sectionDelegate() const
276−{
277− return m_sectionDelegate;
278−}
279−
280−void ListViewWithPageHeader::setSectionDelegate(QQmlComponent *delegate)
281−{
282− if (delegate != m_sectionDelegate) {
283− // TODO clean existing sections
284−
285− m_sectionDelegate = delegate;
286−
287− m_topSectionItem = getSectionItem(QString(), false /*watchGeometry*/);
288− if (m_topSectionItem) {
289− m_topSectionItem->setZ(3);
290− QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
291− connect(m_topSectionItem, &QQuickItem::heightChanged, this, &ListViewWithPageHeader::stickyHeaderHeightChanged);
292− }
293−
294− // TODO create sections for existing items
295−
296− Q_EMIT sectionDelegateChanged();
297− Q_EMIT stickyHeaderHeightChanged();
298− }
299−}
300−
301−QString ListViewWithPageHeader::sectionProperty() const
302−{
303− return m_sectionProperty;
304−}
305−
306−void ListViewWithPageHeader::setSectionProperty(const QString &property)
307−{
308− if (property != m_sectionProperty) {
309− m_sectionProperty = property;
310−
311− updateWatchedRoles();
312−
313− // TODO recreate sections
314−
315− Q_EMIT sectionPropertyChanged();
316− }
317−}
318−
319−bool ListViewWithPageHeader::forceNoClip() const
320−{
321− return m_forceNoClip;
322−}
323−
324−void ListViewWithPageHeader::setForceNoClip(bool noClip)
325−{
326− if (noClip != m_forceNoClip) {
327− m_forceNoClip = noClip;
328− updateClipItem();
329− Q_EMIT forceNoClipChanged();
330− }
331−}
332−
333−int ListViewWithPageHeader::stickyHeaderHeight() const
334−{
335− return m_topSectionItem ? m_topSectionItem->height() : 0;
336−}
337−
338−qreal ListViewWithPageHeader::headerItemShownHeight() const
339−{
340− return m_headerItemShownHeight;
341−}
342−
343−int ListViewWithPageHeader::cacheBuffer() const
344−{
345− return m_cacheBuffer;
346−}
347−
348−void ListViewWithPageHeader::setCacheBuffer(int cacheBuffer)
349−{
350− if (cacheBuffer < 0) {
351− qmlInfo(this) << "Cannot set a negative cache buffer";
352− return;
353− }
354−
355− if (cacheBuffer != m_cacheBuffer) {
356− m_cacheBuffer = cacheBuffer;
357− Q_EMIT cacheBufferChanged();
358− polish();
359− }
360−}
361−
362−void ListViewWithPageHeader::positionAtBeginning()
363−{
364− if (m_delegateModel->count() <= 0)
365− return;
366−
367− qreal headerHeight = (m_headerItem ? m_headerItem->height() : 0);
368− if (m_firstVisibleIndex != 0) {
369− // TODO This could be optimized by trying to reuse the interesection
370− // of items that may end up intersecting between the existing
371− // m_visibleItems and the items we are creating in the next loop
372− Q_FOREACH(ListItem *item, m_visibleItems)
373− releaseItem(item);
374− m_visibleItems.clear();
375− m_firstVisibleIndex = -1;
376−
377− // Create the item 0, it will be already correctly positioned at createItem()
378− m_clipItem->setY(0);
379− ListItem *item = createItem(0, false);
380− // Create the subsequent items
381− int modelIndex = 1;
382− qreal pos = item->y() + item->height();
383− const qreal bufferTo = height() + m_cacheBuffer;
384− while (modelIndex < m_delegateModel->count() && pos <= bufferTo) {
385− if (!(item = createItem(modelIndex, false)))
386− break;
387− pos += item->height();
388− ++modelIndex;
389− }
390−
391− m_previousContentY = m_visibleItems.first()->y() - headerHeight;
392− }
393− setContentY(m_visibleItems.first()->y() + m_clipItem->y() - headerHeight);
394− if (m_headerItem) {
395− // TODO This should not be needed and the code that adjust the m_headerItem position
396− // in viewportMoved() should be enough but in some cases we have not found a way to reproduce
397− // yet the code of viewportMoved() fails so here we make sure that at least if we are calling
398− // positionAtBeginning the header item will be correctly positioned
399− m_headerItem->setY(-m_minYExtent);
400− }
401−}
402−
403−static inline bool uFuzzyCompare(qreal r1, qreal r2)
404−{
405− return qFuzzyCompare(r1, r2) || (qFuzzyIsNull(r1) && qFuzzyIsNull(r2));
406−}
407−
408−void ListViewWithPageHeader::showHeader()
409−{
410− if (!m_headerItem)
411− return;
412−
413− const auto to = qMax(-minYExtent(), contentY() - m_headerItem->height() + m_headerItemShownHeight);
414− if (!uFuzzyCompare(to, contentY())) {
415− const bool headerShownByItsOwn = contentY() < m_headerItem->y() + m_headerItem->height();
416− if (headerShownByItsOwn && m_headerItemShownHeight == 0) {
417− // We are not clipping since we are just at the top of the viewport
418− // but because of the showHeader animation we will need to, so
419− // enable the clipping without logically moving the items
420− m_headerItemShownHeight = m_headerItem->y() + m_headerItem->height() - contentY();
421− if (!m_visibleItems.isEmpty()) {
422− updateClipItem();
423− ListItem *firstItem = m_visibleItems.first();
424− firstItem->setY(firstItem->y() - m_headerItemShownHeight);
425− layout();
426− }
427− Q_EMIT headerItemShownHeightChanged();
428− }
429− m_contentYAnimation->setTo(to);
430− contentYAnimationType = ContentYAnimationShowHeader;
431− m_contentYAnimation->start();
432− }
433−}
434−
435−int ListViewWithPageHeader::firstCreatedIndex() const
436−{
437− return m_firstVisibleIndex;
438−}
439−
440−int ListViewWithPageHeader::createdItemCount() const
441−{
442− return m_visibleItems.count();
443−}
444−
445−QQuickItem *ListViewWithPageHeader::item(int modelIndex) const
446−{
447− ListItem *item = itemAtIndex(modelIndex);
448− if (item)
449− return item->m_item;
450− else
451− return nullptr;
452−}
453−
454−bool ListViewWithPageHeader::maximizeVisibleArea(int modelIndex)
455−{
456− ListItem *listItem = itemAtIndex(modelIndex);
457− if (listItem) {
458− return maximizeVisibleArea(listItem, listItem->height());
459− }
460−
461− return false;
462−}
463−
464−bool ListViewWithPageHeader::maximizeVisibleArea(int modelIndex, int itemHeight)
465−{
466− if (itemHeight < 0)
467− return false;
468−
469− ListItem *listItem = itemAtIndex(modelIndex);
470− if (listItem) {
471− return maximizeVisibleArea(listItem, itemHeight + (listItem->sectionItem() ? listItem->sectionItem()->height() : 0));
472− }
473−
474− return false;
475−}
476−
477−bool ListViewWithPageHeader::maximizeVisibleArea(ListItem *listItem, int listItemHeight)
478−{
479− if (listItem) {
480− layout();
481− const auto listItemY = m_clipItem->y() + listItem->y();
482− if (listItemY > contentY() && listItemY + listItemHeight > contentY() + height()) {
483− // we can scroll the list up to show more stuff
484− const auto to = qMin(listItemY, listItemY + listItemHeight - height());
485− m_contentYAnimation->setTo(to);
486− contentYAnimationType = ContentYAnimationMaximizeVisibleArea;
487− m_contentYAnimation->start();
488− } else if ((listItemY < contentY() && listItemY + listItemHeight < contentY() + height()) ||
489− (m_topSectionItem && !listItem->sectionItem() && listItemY - m_topSectionItem->height() < contentY() && listItemY + listItemHeight < contentY() + height()))
490− {
491− // we can scroll the list down to show more stuff
492− auto realVisibleListItemY = listItemY;
493− if (m_topSectionItem) {
494− // If we are showing the top section sticky item and this item doesn't have a section
495− // item we have to make sure to scroll it a bit more so that it is not underlapping
496− // the top section sticky item
497− bool topSectionShown = !QQuickItemPrivate::get(m_topSectionItem)->culled;
498− if (topSectionShown && !listItem->sectionItem()) {
499− realVisibleListItemY -= m_topSectionItem->height();
500− }
501− }
502− const auto to = qMax(realVisibleListItemY, listItemY + listItemHeight - height());
503− m_contentYAnimation->setTo(to);
504− contentYAnimationType = ContentYAnimationMaximizeVisibleArea;
505− m_contentYAnimation->start();
506− }
507− return true;
508− }
509− return false;
510−}
511−
512−qreal ListViewWithPageHeader::minYExtent() const
513−{
514−// qDebug() << "ListViewWithPageHeader::minYExtent" << m_minYExtent;
515− return m_minYExtent;
516−}
517−
518−qreal ListViewWithPageHeader::maxYExtent() const
519−{
520− return height() - contentHeight();
521−}
522−
523−void ListViewWithPageHeader::componentComplete()
524−{
525− if (m_delegateModel)
526− m_delegateModel->componentComplete();
527−
528− QQuickFlickable::componentComplete();
529−
530− polish();
531−}
532−
533−void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
534−{
535− // Check we are not being taken down and don't paint anything
536− // TODO Check if we still need this in 5.2
537− // For reproduction just inifnite loop testDash or testDashContent
538− if (!QQmlEngine::contextForObject(this)->parentContext())
539− return;
540−
541− QQuickFlickable::viewportMoved(orient);
542−// qDebug() << "ListViewWithPageHeader::viewportMoved" << contentY();
543− const qreal diff = m_previousContentY - contentY();
544− adjustHeader(diff);
545− m_previousContentY = contentY();
546− layout();
547− polish();
548−}
549−
550−void ListViewWithPageHeader::adjustHeader(qreal diff)
551−{
552− const bool showHeaderAnimationRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationShowHeader;
553− if (m_headerItem) {
554− const auto oldHeaderItemShownHeight = m_headerItemShownHeight;
555− if (uFuzzyCompare(contentY(), -m_minYExtent) || contentY() > -m_minYExtent) {
556− m_headerItem->setHeight(m_headerItem->implicitHeight());
557− // We are going down (but it's not because of the rebound at the end)
558− // (but the header was not shown by it's own position)
559− // or the header is partially shown and we are not doing a maximizeVisibleArea either
560− const bool scrolledUp = m_previousContentY > contentY();
561− const bool notRebounding = qRound(contentY() + height()) < qRound(contentHeight());
562− const bool notShownByItsOwn = contentY() + diff >= m_headerItem->y() + m_headerItem->height();
563− const bool maximizeVisibleAreaRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationMaximizeVisibleArea;
564−
565− if (!scrolledUp && (contentY() == -m_minYExtent || (m_headerItemShownHeight == 0 && m_previousContentY == m_headerItem->y()))) {
566− m_headerItemShownHeight = 0;
567− m_headerItem->setY(-m_minYExtent);
568− } else if ((scrolledUp && notRebounding && notShownByItsOwn && !maximizeVisibleAreaRunning) || (m_headerItemShownHeight > 0) || m_inContentHeightKeepHeaderShown) {
569− if (maximizeVisibleAreaRunning && diff > 0) {
570− // If we are maximizing and the header was shown, make sure we hide it
571− m_headerItemShownHeight -= diff;
572− } else {
573− m_headerItemShownHeight += diff;
574− }
575− if (uFuzzyCompare(contentY(), -m_minYExtent)) {
576− m_headerItemShownHeight = 0;
577− } else {
578− m_headerItemShownHeight = qBound(static_cast<qreal>(0.), m_headerItemShownHeight, m_headerItem->height());
579− }
580− if (m_headerItemShownHeight > 0) {
581− if (uFuzzyCompare(m_headerItem->height(), m_headerItemShownHeight)) {
582− m_headerItem->setY(contentY());
583− m_headerItemShownHeight = m_headerItem->height();
584− } else {
585− m_headerItem->setY(contentY() - m_headerItem->height() + m_headerItemShownHeight);
586− }
587− } else {
588− m_headerItem->setY(-m_minYExtent);
589− }
590− } else if (m_headerItemShownHeight == 0 && m_previousContentY > m_headerItem->y() && contentY() < m_headerItem->y()) {
591− // The header was hidden but now that we've moved up (e.g. because of item removed) it's visible
592− // make sure it isn't
593− m_headerItem->setY(-m_minYExtent);
594− }
595− Q_EMIT headerItemShownHeightChanged();
596− } else {
597− // Stick the header item to the top when dragging down
598− m_headerItem->setY(contentY());
599− m_headerItem->setHeight(m_headerItem->implicitHeight() + (-m_minYExtent - contentY()));
600− }
601− // We will be changing the clip item, need to accomadate for it
602− // otherwise we move the firstItem down/up twice (unless the
603− // show header animation is running, where we want to keep the viewport stable)
604− if (!showHeaderAnimationRunning) {
605− diff += oldHeaderItemShownHeight - m_headerItemShownHeight;
606− } else {
607− diff = -diff;
608− }
609− }
610− if (!m_visibleItems.isEmpty()) {
611− updateClipItem();
612− ListItem *firstItem = m_visibleItems.first();
613− firstItem->setY(firstItem->y() + diff);
614− if (showHeaderAnimationRunning) {
615− adjustMinYExtent();
616− }
617− }
618−}
619−
620−void ListViewWithPageHeader::createDelegateModel()
621−{
622− m_delegateModel = new QQmlDelegateModel(qmlContext(this), this);
623− connect(m_delegateModel, &QQmlDelegateModel::createdItem, this, &ListViewWithPageHeader::itemCreated);
624− if (isComponentComplete())
625− m_delegateModel->componentComplete();
626− updateWatchedRoles();
627−}
628−
629−void ListViewWithPageHeader::refill()
630−{
631− if (m_inLayout) {
632− return;
633− }
634− if (!isComponentComplete()) {
635− return;
636− }
637−
638− const qreal from = contentY();
639− const qreal to = from + height();
640− const qreal bufferFrom = from - m_cacheBuffer;
641− const qreal bufferTo = to + m_cacheBuffer;
642−
643− bool added = addVisibleItems(from, to, false);
644− bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
645− added |= addVisibleItems(bufferFrom, bufferTo, true);
646−
647− if (added || removed) {
648− m_contentHeightDirty = true;
649− }
650−}
651−
652−bool ListViewWithPageHeader::addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous)
653−{
654− if (!delegate())
655− return false;
656−
657− if (m_delegateModel->count() == 0)
658− return false;
659−
660− ListItem *item;
661−// qDebug() << "ListViewWithPageHeader::addVisibleItems" << fillFrom << fillTo << asynchronous;
662−
663− int modelIndex = 0;
664− qreal pos = 0;
665− if (!m_visibleItems.isEmpty()) {
666− modelIndex = m_firstVisibleIndex + m_visibleItems.count();
667− item = m_visibleItems.last();
668− pos = item->y() + item->height() + m_clipItem->y();
669− }
670− bool changed = false;
671−// qDebug() << (modelIndex < m_delegateModel->count()) << pos << fillTo;
672− while (modelIndex < m_delegateModel->count() && pos <= fillTo) {
673−// qDebug() << "refill: append item" << modelIndex << "pos" << pos << "asynchronous" << asynchronous;
674− if (!(item = createItem(modelIndex, asynchronous)))
675− break;
676− pos += item->height();
677− ++modelIndex;
678− changed = true;
679− }
680−
681− modelIndex = 0;
682− pos = 0;
683− if (!m_visibleItems.isEmpty()) {
684− modelIndex = m_firstVisibleIndex - 1;
685− item = m_visibleItems.first();
686− pos = item->y() + m_clipItem->y();
687− }
688− while (modelIndex >= 0 && pos > fillFrom) {
689−// qDebug() << "refill: prepend item" << modelIndex << "pos" << pos << "fillFrom" << fillFrom << "asynchronous" << asynchronous;
690− if (!(item = createItem(modelIndex, asynchronous)))
691− break;
692− pos -= item->height();
693− --modelIndex;
694− changed = true;
695− }
696−
697− return changed;
698−}
699−
700−void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
701−{
702− QQuickItem *item = listItem->m_item;
703− QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item);
704− if (flags & QQmlDelegateModel::Destroyed) {
705− item->setParentItem(nullptr);
706− }
707− if (listItem->sectionItem()) {
708− listItem->sectionItem()->deleteLater();
709− }
710− delete listItem;
711−}
712−
713−void ListViewWithPageHeader::releaseItem(ListItem *listItem)
714−{
715− QQuickItemPrivate::get(listItem->m_item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
716− if (listItem->sectionItem()) {
717− QQuickItemPrivate::get(listItem->sectionItem())->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
718− }
719− m_itemsToRelease << listItem;
720−}
721−
722−void ListViewWithPageHeader::updateWatchedRoles()
723−{
724− if (m_delegateModel) {
725− QList<QByteArray> roles;
726− if (!m_sectionProperty.isEmpty())
727− roles << m_sectionProperty.toUtf8();
728− m_delegateModel->setWatchedRoles(roles);
729− }
730−}
731−
732−QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyInserted)
733−{
734− if (!m_sectionDelegate)
735− return nullptr;
736−
737− const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
738−
739− if (modelIndex > 0) {
740− const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
741− if (section == prevSection)
742− return nullptr;
743− }
744− if (modelIndex + 1 < model()->rowCount() && !alreadyInserted) {
745− // Already inserted items can't steal next section header
746− const QString nextSection = m_delegateModel->stringValue(modelIndex + 1, m_sectionProperty);
747− if (section == nextSection) {
748− // Steal the section header
749− ListItem *nextItem = itemAtIndex(modelIndex); // Not +1 since not yet inserted into m_visibleItems
750− if (nextItem) {
751− QQuickItem *sectionItem = nextItem->sectionItem();
752− nextItem->setSectionItem(nullptr);
753− return sectionItem;
754− }
755− }
756− }
757−
758− return getSectionItem(section);
759−}
760−
761−QQuickItem *ListViewWithPageHeader::getSectionItem(const QString &sectionText, bool watchGeometry)
762−{
763− QQuickItem *sectionItem = nullptr;
764−
765− QQmlContext *creationContext = m_sectionDelegate->creationContext();
766− QQmlContext *context = new QQmlContext(creationContext ? creationContext : qmlContext(this));
767− QObject *nobj = m_sectionDelegate->beginCreate(context);
768− if (nobj) {
769− QQml_setParent_noEvent(context, nobj);
770− sectionItem = qobject_cast<QQuickItem *>(nobj);
771− if (!sectionItem) {
772− delete nobj;
773− } else {
774− sectionItem->setProperty("text", sectionText);
775− sectionItem->setProperty("delegate", QVariant());
776− sectionItem->setZ(2);
777− QQml_setParent_noEvent(sectionItem, m_clipItem);
778− sectionItem->setParentItem(m_clipItem);
779− }
780− } else {
781− delete context;
782− }
783− m_sectionDelegate->completeCreate();
784−
785− if (watchGeometry && sectionItem) {
786− QQuickItemPrivate::get(sectionItem)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
787− }
788−
789− return sectionItem;
790−}
791−
792−void ListViewWithPageHeader::updateSectionItem(int modelIndex)
793−{
794− ListItem *item = itemAtIndex(modelIndex);
795− if (item) {
796− const QString sectionText = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
797−
798− bool needSectionHeader = true;
799− // if it is the same section as the previous item need to drop the section
800− if (modelIndex > 0) {
801− const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
802− if (sectionText == prevSection) {
803− needSectionHeader = false;
804− }
805− }
806−
807− if (needSectionHeader) {
808− if (!item->sectionItem()) {
809− item->setSectionItem(getSectionItem(sectionText));
810− } else {
811− item->sectionItem()->setProperty("text", sectionText);
812− }
813− } else {
814− if (item->sectionItem()) {
815− item->sectionItem()->deleteLater();
816− item->setSectionItem(nullptr);
817− }
818− }
819− }
820−}
821−
822−bool ListViewWithPageHeader::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
823−{
824−// qDebug() << "ListViewWithPageHeader::removeNonVisibleItems" << bufferFrom << bufferTo;
825− // Do not remove items if we are overshooting up or down, since we'll come back
826− // to the "stable" position and delete/create items without any reason
827− if (contentY() < -m_minYExtent) {
828− return false;
829− } else if (contentY() + height() > contentHeight()) {
830− return false;
831− }
832− bool changed = false;
833−
834− bool foundVisible = false;
835− int i = 0;
836− int removedItems = 0;
837− const auto oldFirstVisibleIndex = m_firstVisibleIndex;
838− while (i < m_visibleItems.count()) {
839− ListItem *item = m_visibleItems[i];
840− const qreal pos = item->y() + m_clipItem->y();
841−// qDebug() << i << pos << (pos + item->height()) << bufferFrom << bufferTo;
842− if (pos + item->height() < bufferFrom || pos > bufferTo) {
843−// qDebug() << "Releasing" << i << (pos + item->height() < bufferFrom) << pos + item->height() << bufferFrom << (pos > bufferTo) << pos << bufferTo;
844− releaseItem(item);
845− m_visibleItems.removeAt(i);
846− changed = true;
847− ++removedItems;
848− } else {
849− if (!foundVisible) {
850− foundVisible = true;
851− const int itemIndex = m_firstVisibleIndex + removedItems + i;
852− m_firstVisibleIndex = itemIndex;
853− }
854− ++i;
855− }
856− }
857− if (!foundVisible) {
858− initializeValuesForEmptyList();
859− }
860− if (m_firstVisibleIndex != oldFirstVisibleIndex) {
861− adjustMinYExtent();
862− }
863−
864− return changed;
865−}
866−
867−ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIndex, bool asynchronous)
868−{
869−// qDebug() << "CREATE ITEM" << modelIndex;
870− if (asynchronous && m_asyncRequestedIndex != -1)
871− return nullptr;
872−
873− m_asyncRequestedIndex = -1;
874− QObject* object = m_delegateModel->object(modelIndex, asynchronous);
875− QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
876− if (!item) {
877− if (object) {
878− m_delegateModel->release(object);
879− if (!m_delegateValidated) {
880− m_delegateValidated = true;
881− QObject* delegateObj = delegate();
882− qmlInfo(delegateObj ? delegateObj : this) << "Delegate must be of Item type";
883− }
884− } else {
885− m_asyncRequestedIndex = modelIndex;
886− }
887− return 0;
888− } else {
889−// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
890− ListItem *listItem = new ListItem;
891− listItem->m_item = item;
892− listItem->setSectionItem(getSectionItem(modelIndex, false /*Not yet inserted into m_visibleItems*/));
893− QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
894− ListItem *prevItem = itemAtIndex(modelIndex - 1);
895− bool lostItem = false; // Is an item that we requested async but because of model changes
896− // it is no longer attached to any of the existing items (has no prev nor next item)
897− // nor is the first item
898− if (prevItem) {
899− listItem->setY(prevItem->y() + prevItem->height());
900− } else {
901− ListItem *currItem = itemAtIndex(modelIndex);
902− if (currItem) {
903− // There's something already in m_visibleItems at out index, meaning this is an insert, so attach to its top
904− listItem->setY(currItem->y() - listItem->height());
905− } else {
906− ListItem *nextItem = itemAtIndex(modelIndex + 1);
907− if (nextItem) {
908− listItem->setY(nextItem->y() - listItem->height());
909− } else if (modelIndex == 0) {
910− listItem->setY(-m_clipItem->y() + (m_headerItem ? m_headerItem->height() : 0));
911− } else if (!m_visibleItems.isEmpty()) {
912− lostItem = true;
913− }
914− }
915− }
916− if (lostItem) {
917− listItem->setCulled(true);
918− releaseItem(listItem);
919− listItem = nullptr;
920− } else {
921− listItem->setCulled(listItem->y() + listItem->height() + m_clipItem->y() <= contentY() || listItem->y() + m_clipItem->y() >= contentY() + height());
922− if (m_visibleItems.isEmpty()) {
923− m_visibleItems << listItem;
924− } else {
925− m_visibleItems.insert(modelIndex - m_firstVisibleIndex, listItem);
926− }
927− if (m_firstVisibleIndex < 0 || modelIndex < m_firstVisibleIndex) {
928− m_firstVisibleIndex = modelIndex;
929− polish();
930− }
931− if (listItem->sectionItem()) {
932− listItem->sectionItem()->setProperty("delegate", QVariant::fromValue(listItem->m_item));
933− }
934− adjustMinYExtent();
935− m_contentHeightDirty = true;
936− }
937− return listItem;
938− }
939−}
940−
941−void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
942−{
943− QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
944− if (!item) {
945− qWarning() << "ListViewWithPageHeader::itemCreated got a non item for index" << modelIndex;
946− return;
947− }
948−// qDebug() << "ListViewWithPageHeader::itemCreated" << modelIndex << item;
949− // Check we are not being taken down and don't paint anything
950− // TODO Check if we still need this in 5.2
951− // For reproduction just inifnite loop testDash or testDashContent
952− if (!QQmlEngine::contextForObject(this)->parentContext())
953− return;
954−
955− item->setParentItem(m_clipItem);
956− // FIXME Why do we need the refreshExpressions call?
957− QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
958− QQmlContextPrivate::get(context)->data->refreshExpressions();
959− item->setProperty("heightToClip", QVariant::fromValue<int>(0));
960− if (modelIndex == m_asyncRequestedIndex) {
961− createItem(modelIndex, false);
962− refill();
963− }
964−}
965−
966−void ListViewWithPageHeader::updateClipItem()
967−{
968− m_clipItem->setHeight(height() - m_headerItemShownHeight);
969− m_clipItem->setY(contentY() + m_headerItemShownHeight);
970− m_clipItem->setClip(!m_forceNoClip && m_headerItemShownHeight > 0);
971−}
972−
973−void ListViewWithPageHeader::onContentHeightChanged()
974−{
975− updateClipItem();
976−}
977−
978−void ListViewWithPageHeader::onContentWidthChanged()
979−{
980− m_clipItem->setWidth(contentItem()->width());
981−}
982−
983−void ListViewWithPageHeader::onHeightChanged()
984−{
985− m_clipItem->setHeight(height() - m_headerItemShownHeight);
986− polish();
987−}
988−
989−
990−void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool /*reset*/)
991−{
992− // TODO Do something with reset
993−// qDebug() << "ListViewWithPageHeader::onModelUpdated" << changeSet << reset;
994− const auto oldFirstVisibleIndex = m_firstVisibleIndex;
995−
996− Q_FOREACH(const QQmlChangeSet::Change remove, changeSet.removes()) {
997−// qDebug() << "ListViewWithPageHeader::onModelUpdated Remove" << remove.index << remove.count;
998− if (remove.index + remove.count > m_firstVisibleIndex && remove.index < m_firstVisibleIndex + m_visibleItems.count()) {
999− const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
1000− // If all the items we are removing are either not created or culled
1001− // we have to grow down to avoid viewport changing
1002− bool growDown = true;
1003− for (int i = 0; growDown && i < remove.count; ++i) {
1004− const int modelIndex = remove.index + i;
1005− ListItem *item = itemAtIndex(modelIndex);
1006− if (item && !item->culled()) {
1007− growDown = false;
1008− }
1009− }
1010− for (int i = remove.count - 1; i >= 0; --i) {
1011− const int visibleIndex = remove.index + i - m_firstVisibleIndex;
1012− if (visibleIndex >= 0 && visibleIndex < m_visibleItems.count()) {
1013− ListItem *item = m_visibleItems[visibleIndex];
1014− // Pass the section item down if needed
1015− if (item->sectionItem() && visibleIndex + 1 < m_visibleItems.count()) {
1016− ListItem *nextItem = m_visibleItems[visibleIndex + 1];
1017− if (!nextItem->sectionItem()) {
1018− nextItem->setSectionItem(item->sectionItem());
1019− item->setSectionItem(nullptr);
1020− }
1021− }
1022− releaseItem(item);
1023− m_visibleItems.removeAt(visibleIndex);
1024− }
1025− }
1026− if (growDown) {
1027− adjustMinYExtent();
1028− } else if (remove.index <= m_firstVisibleIndex && !m_visibleItems.isEmpty()) {
1029− m_visibleItems.first()->setY(oldFirstValidIndexPos);
1030− }
1031− if (m_visibleItems.isEmpty()) {
1032− m_firstVisibleIndex = -1;
1033− } else {
1034− m_firstVisibleIndex -= qMax(0, m_firstVisibleIndex - remove.index);
1035− }
1036− } else if (remove.index + remove.count <= m_firstVisibleIndex) {
1037− m_firstVisibleIndex -= remove.count;
1038− }
1039− for (int i = remove.count - 1; i >= 0; --i) {
1040− const int modelIndex = remove.index + i;
1041− if (modelIndex == m_asyncRequestedIndex) {
1042− m_asyncRequestedIndex = -1;
1043− } else if (modelIndex < m_asyncRequestedIndex) {
1044− m_asyncRequestedIndex--;
1045− }
1046− }
1047− }
1048−
1049− Q_FOREACH(const QQmlChangeSet::Change insert, changeSet.inserts()) {
1050−// qDebug() << "ListViewWithPageHeader::onModelUpdated Insert" << insert.index << insert.count;
1051− const bool insertingInValidIndexes = insert.index > m_firstVisibleIndex && insert.index < m_firstVisibleIndex + m_visibleItems.count();
1052− const bool firstItemWithViewOnTop = insert.index == 0 && m_firstVisibleIndex == 0 && m_visibleItems.first()->y() + m_clipItem->y() > contentY();
1053− if (insertingInValidIndexes || firstItemWithViewOnTop)
1054− {
1055− // If the items we are adding won't be really visible
1056− // we grow up instead of down to not change the viewport
1057− bool growUp = false;
1058− if (!firstItemWithViewOnTop) {
1059− for (int i = 0; i < m_visibleItems.count(); ++i) {
1060− if (!m_visibleItems[i]->culled()) {
1061− if (insert.index <= m_firstVisibleIndex + i) {
1062− growUp = true;
1063− }
1064− break;
1065− }
1066− }
1067− }
1068−
1069− const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
1070− for (int i = insert.count - 1; i >= 0; --i) {
1071− const int modelIndex = insert.index + i;
1072− ListItem *item = createItem(modelIndex, false);
1073− if (growUp) {
1074− ListItem *firstItem = m_visibleItems.first();
1075− firstItem->setY(firstItem->y() - item->height());
1076− }
1077− // Adding an item may break a "same section" chain, so check
1078− // if we need adding a new section item
1079− if (m_sectionDelegate) {
1080− ListItem *nextItem = itemAtIndex(modelIndex + 1);
1081− if (nextItem && !nextItem->sectionItem()) {
1082− nextItem->setSectionItem(getSectionItem(modelIndex + 1, true /* alredy inserted into m_visibleItems*/));
1083− if (growUp && nextItem->sectionItem()) {
1084− ListItem *firstItem = m_visibleItems.first();
1085− firstItem->setY(firstItem->y() - nextItem->sectionItem()->height());
1086− }
1087− }
1088− }
1089− }
1090− if (firstItemWithViewOnTop) {
1091− ListItem *firstItem = m_visibleItems.first();
1092− firstItem->setY(oldFirstValidIndexPos);
1093− }
1094− adjustMinYExtent();
1095− } else if (insert.index <= m_firstVisibleIndex) {
1096− m_firstVisibleIndex += insert.count;
1097− }
1098−
1099− for (int i = insert.count - 1; i >= 0; --i) {
1100− const int modelIndex = insert.index + i;
1101− if (modelIndex <= m_asyncRequestedIndex) {
1102− m_asyncRequestedIndex++;
1103− }
1104− }
1105− }
1106−
1107− Q_FOREACH(const QQmlChangeSet::Change change, changeSet.changes()) {
1108− for (int i = change.start(); i < change.end(); ++i) {
1109− updateSectionItem(i);
1110− }
1111− // Also update the section header for the next item after the change since it may be influenced
1112− updateSectionItem(change.end());
1113− }
1114−
1115− if (m_firstVisibleIndex != oldFirstVisibleIndex) {
1116− if (m_visibleItems.isEmpty()) {
1117− initializeValuesForEmptyList();
1118− } else {
1119− adjustMinYExtent();
1120− }
1121− }
1122−
1123− for (int i = 0; i < m_visibleItems.count(); ++i) {
1124− ListItem *item = m_visibleItems[i];
1125− if (item->sectionItem()) {
1126− item->sectionItem()->setProperty("delegate", QVariant::fromValue(item->m_item));
1127− }
1128− }
1129−
1130− layout();
1131− polish();
1132− m_contentHeightDirty = true;
1133−}
1134−
1135−void ListViewWithPageHeader::contentYAnimationRunningChanged(bool running)
1136−{
1137− setInteractive(!running);
1138− if (!running) {
1139− m_contentHeightDirty = true;
1140− polish();
1141− }
1142−}
1143−
1144−void ListViewWithPageHeader::itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
1145−{
1146− const qreal heightDiff = newGeometry.height() - oldGeometry.height();
1147− if (heightDiff != 0) {
1148− if (!m_visibleItems.isEmpty()) {
1149− ListItem *firstItem = m_visibleItems.first();
1150− const auto prevFirstItemY = firstItem->y();
1151− if (!m_inContentHeightKeepHeaderShown && oldGeometry.y() + oldGeometry.height() + m_clipItem->y() <= contentY()) {
1152− firstItem->setY(firstItem->y() - heightDiff);
1153− } else if (item == firstItem->sectionItem()) {
1154− firstItem->setY(firstItem->y() + heightDiff);
1155− }
1156−
1157− if (firstItem->y() != prevFirstItemY) {
1158− adjustMinYExtent();
1159− layout();
1160− }
1161− }
1162− refill();
1163− adjustMinYExtent();
1164− polish();
1165− m_contentHeightDirty = true;
1166− }
1167−}
1168−
1169−void ListViewWithPageHeader::itemImplicitHeightChanged(QQuickItem *item)
1170−{
1171− if (item == m_headerItem) {
1172− const qreal diff = m_headerItem->implicitHeight() - m_previousHeaderImplicitHeight;
1173− if (diff != 0) {
1174− adjustHeader(diff);
1175− m_previousHeaderImplicitHeight = m_headerItem->implicitHeight();
1176− layout();
1177− polish();
1178− m_contentHeightDirty = true;
1179− }
1180− }
1181−}
1182−
1183−void ListViewWithPageHeader::headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY)
1184−{
1185− const qreal heightDiff = newHeaderHeight - oldHeaderHeight;
1186− if (m_headerItemShownHeight > 0) {
1187− // If the header is shown because of the clip
1188− // Change its size
1189− m_headerItemShownHeight += heightDiff;
1190− m_headerItemShownHeight = qBound(static_cast<qreal>(0.), m_headerItemShownHeight, newHeaderHeight);
1191− updateClipItem();
1192− adjustMinYExtent();
1193− Q_EMIT headerItemShownHeightChanged();
1194− } else {
1195− if (oldHeaderY + oldHeaderHeight > contentY()) {
1196− // If the header is shown because its position
1197− // Change its size
1198− ListItem *firstItem = m_visibleItems.first();
1199− firstItem->setY(firstItem->y() + heightDiff);
1200− layout();
1201− } else {
1202− // If the header is not on screen, just change the start of the list
1203− // so the viewport is not changed
1204− adjustMinYExtent();
1205− }
1206− }
1207−}
1208−
1209−
1210−void ListViewWithPageHeader::adjustMinYExtent()
1211−{
1212− if (m_visibleItems.isEmpty() || (contentHeight() + m_minYExtent < height())) {
1213− m_minYExtent = 0;
1214− } else {
1215− qreal nonCreatedHeight = 0;
1216− if (m_firstVisibleIndex != 0) {
1217− // Calculate the average height of items to estimate the position of the list start
1218− const int visibleItems = m_visibleItems.count();
1219− qreal visibleItemsHeight = 0;
1220− Q_FOREACH(ListItem *item, m_visibleItems) {
1221− visibleItemsHeight += item->height();
1222− }
1223− nonCreatedHeight = m_firstVisibleIndex * visibleItemsHeight / visibleItems;
1224−// qDebug() << m_firstVisibleIndex << visibleItemsHeight << visibleItems << nonCreatedHeight;
1225− }
1226− const qreal headerHeight = (m_headerItem ? m_headerItem->implicitHeight() : 0);
1227− m_minYExtent = nonCreatedHeight - m_visibleItems.first()->y() - m_clipItem->y() + headerHeight;
1228− if (m_minYExtent != 0 && qFuzzyIsNull(m_minYExtent)) {
1229− m_minYExtent = 0;
1230− m_visibleItems.first()->setY(nonCreatedHeight - m_clipItem->y() + headerHeight);
1231− }
1232− }
1233−}
1234−
1235−ListViewWithPageHeader::ListItem *ListViewWithPageHeader::itemAtIndex(int modelIndex) const
1236−{
1237− const int visibleIndexedModelIndex = modelIndex - m_firstVisibleIndex;
1238− if (visibleIndexedModelIndex >= 0 && visibleIndexedModelIndex < m_visibleItems.count())
1239− return m_visibleItems[visibleIndexedModelIndex];
1240−
1241− return nullptr;
1242−}
1243−
1244−void ListViewWithPageHeader::layout()
1245−{
1246− if (m_inLayout)
1247− return;
1248−
1249− m_inLayout = true;
1250− if (!m_visibleItems.isEmpty()) {
1251− const qreal visibleFrom = contentY() - m_clipItem->y() + m_headerItemShownHeight;
1252− const qreal visibleTo = contentY() + height() - m_clipItem->y();
1253−
1254− qreal pos = m_visibleItems.first()->y();
1255−
1256−// qDebug() << "ListViewWithPageHeader::layout Updating positions and heights. contentY" << contentY() << "minYExtent" << minYExtent();
1257− int firstReallyVisibleItem = -1;
1258− int modelIndex = m_firstVisibleIndex;
1259− Q_FOREACH(ListItem *item, m_visibleItems) {
1260− const bool cull = pos + item->height() <= visibleFrom || pos >= visibleTo;
1261− item->setCulled(cull);
1262− item->setY(pos);
1263− if (!cull && firstReallyVisibleItem == -1) {
1264− firstReallyVisibleItem = modelIndex;
1265− if (m_topSectionItem) {
1266− // Positing the top section sticky item is a two step process
1267− // First we set it either we cull it (because it doesn't need to be sticked to the top)
1268− // or stick it to the top
1269− // Then after the loop we'll make sure that if there's another section just below it
1270− // pushed the sticky section up to make it disappear
1271− const qreal topSectionStickPos = m_headerItemShownHeight + contentY() - m_clipItem->y();
1272− bool showStickySectionItem;
1273− // We need to show the "top section sticky item" when the position at the "top" of the
1274− // viewport is bigger than the start of the position of the first visible item
1275− // i.e. the first visible item starts before the viewport, or when the first
1276− // visible item starts just at the viewport start and it does not have its own section item
1277− if (topSectionStickPos > pos) {
1278− showStickySectionItem = true;
1279− } else if (topSectionStickPos == pos) {
1280− showStickySectionItem = !item->sectionItem();
1281− } else {
1282− showStickySectionItem = false;
1283− }
1284− if (!showStickySectionItem) {
1285− QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
1286− if (item->sectionItem()) {
1287− // This seems it should happen since why would we cull the top section
1288− // if the first visible item has no section header? This only happens briefly
1289− // when increasing the height of a list that is at the bottom, the m_topSectionItem
1290− // gets shown shortly in the next polish call
1291− QQuickItemPrivate::get(item->sectionItem())->setCulled(false);
1292− }
1293− } else {
1294− // Update the top sticky section header
1295− const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
1296− m_topSectionItem->setProperty("text", section);
1297−
1298− QQuickItemPrivate::get(m_topSectionItem)->setCulled(false);
1299− m_topSectionItem->setY(topSectionStickPos);
1300− m_topSectionItem->setProperty("delegate", QVariant::fromValue(item->m_item));
1301− if (item->sectionItem()) {
1302− QQuickItemPrivate::get(item->sectionItem())->setCulled(true);
1303− }
1304− }
1305− }
1306− }
1307− const qreal clipFrom = visibleFrom + (!item->sectionItem() && m_topSectionItem && !QQuickItemPrivate::get(m_topSectionItem)->culled ? m_topSectionItem->height() : 0);
1308− if (!cull && pos < clipFrom) {
1309− item->m_item->setProperty("heightToClip", clipFrom - pos);
1310− } else {
1311− item->m_item->setProperty("heightToClip", QVariant::fromValue<int>(0));
1312− }
1313−// qDebug() << "ListViewWithPageHeader::layout" << item->m_item;
1314− pos += item->height();
1315− ++modelIndex;
1316− }
1317−
1318− // Second step of section sticky item positioning
1319− // Look at the next section header, check if it's pushing up the sticky one
1320− if (m_topSectionItem) {
1321− if (firstReallyVisibleItem >= 0) {
1322− for (int i = firstReallyVisibleItem - m_firstVisibleIndex + 1; i < m_visibleItems.count(); ++i) {
1323− ListItem *item = m_visibleItems[i];
1324− if (item->sectionItem()) {
1325− if (m_topSectionItem->y() + m_topSectionItem->height() > item->y()) {
1326− m_topSectionItem->setY(item->y() - m_topSectionItem->height());
1327− }
1328− break;
1329− }
1330− }
1331− }
1332− }
1333− }
1334− if (m_headerItem) {
1335− const bool cullHeader = m_headerItem->y() + m_headerItem->height() < contentY();
1336− QQuickItemPrivate::get(m_headerItem)->setCulled(cullHeader);
1337− }
1338− m_inLayout = false;
1339−}
1340−
1341−void ListViewWithPageHeader::updatePolish()
1342−{
1343− // Check we are not being taken down and don't paint anything
1344− // TODO Check if we still need this in 5.2
1345− // For reproduction just inifnite loop testDash or testDashContent
1346− if (!QQmlEngine::contextForObject(this)->parentContext())
1347− return;
1348−
1349− Q_FOREACH(ListItem *item, m_itemsToRelease)
1350− reallyReleaseItem(item);
1351− m_itemsToRelease.clear();
1352−
1353− if (!model())
1354− return;
1355−
1356− layout();
1357−
1358− refill();
1359−
1360− if (m_contentHeightDirty) {
1361− qreal contentHeight;
1362− if (m_visibleItems.isEmpty()) {
1363− contentHeight = m_headerItem ? m_headerItem->height() : 0;
1364− } else {
1365− const int modelCount = model()->rowCount();
1366− const int visibleItems = m_visibleItems.count();
1367− const int lastValidIndex = m_firstVisibleIndex + visibleItems - 1;
1368− qreal nonCreatedHeight = 0;
1369− if (lastValidIndex != modelCount - 1) {
1370− const int visibleItems = m_visibleItems.count();
1371− qreal visibleItemsHeight = 0;
1372− Q_FOREACH(ListItem *item, m_visibleItems) {
1373− visibleItemsHeight += item->height();
1374− }
1375− const int unknownSizes = modelCount - (m_firstVisibleIndex + visibleItems);
1376− nonCreatedHeight = unknownSizes * visibleItemsHeight / visibleItems;
1377− }
1378− ListItem *item = m_visibleItems.last();
1379− contentHeight = nonCreatedHeight + item->y() + item->height() + m_clipItem->y();
1380− if (m_firstVisibleIndex != 0) {
1381− // Make sure that if we are shrinking we tell the view we still fit
1382− m_minYExtent = qMax(m_minYExtent, -(contentHeight - height()));
1383− }
1384− }
1385−
1386− m_contentHeightDirty = false;
1387− adjustMinYExtent();
1388− m_inContentHeightKeepHeaderShown = m_headerItem && m_headerItem->y() == contentY();
1389− setContentHeight(contentHeight);
1390− m_inContentHeightKeepHeaderShown = false;
1391− }
1392−}
1393−
1394−#include "moc_listviewwithpageheader.cpp"
plugins/Dash/listviewwithpageheader.hdeleted−218
@@ -1,218 +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− qreal maxYExtent() const override;
119− void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) override;
120− void itemImplicitHeightChanged(QQuickItem *item) override;
121− void updatePolish() override;
122−
123−private Q_SLOTS:
124− void itemCreated(int modelIndex, QObject *object);
125− void onContentHeightChanged();
126− void onContentWidthChanged();
127− void onHeightChanged();
128− void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
129− void contentYAnimationRunningChanged(bool running);
130−
131−private:
132− class ListItem
133− {
134− public:
135− qreal height() const;
136−
137− qreal y() const;
138− void setY(qreal newY);
139−
140− bool culled() const;
141− void setCulled(bool culled);
142−
143− QQuickItem *sectionItem() const { return m_sectionItem; }
144− void setSectionItem(QQuickItem *sectionItem);
145−
146− QQuickItem *m_item;
147− private:
148− QQuickItem *m_sectionItem;
149− };
150−
151− bool maximizeVisibleArea(ListItem *listItem, int listItemHeight);
152−
153− void createDelegateModel();
154−
155− void layout();
156− void refill();
157− bool addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous);
158− bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
159− ListItem *createItem(int modelIndex, bool asynchronous);
160−
161− void adjustHeader(qreal diff);
162− void adjustMinYExtent();
163− void updateClipItem();
164− void headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY);
165− ListItem *itemAtIndex(int modelIndex) const; // Returns the item at modelIndex if has been created
166− void releaseItem(ListItem *item);
167− void reallyReleaseItem(ListItem *item);
168− void updateWatchedRoles();
169− QQuickItem *getSectionItem(int modelIndex, bool alreadyInserted);
170− QQuickItem *getSectionItem(const QString &sectionText, bool watchGeometry = true);
171− void updateSectionItem(int modelIndex);
172− void initializeValuesForEmptyList();
173−
174− QQmlDelegateModel *m_delegateModel;
175−
176− // Index we are waiting because we requested it asynchronously
177− int m_asyncRequestedIndex;
178−
179− // Used to only give a warning once if the delegate does not return objects
180− bool m_delegateValidated;
181−
182− // Visible indexes, [0] is m_firstValidIndex, [0+1] is m_firstValidIndex +1, ...
183− QList<ListItem *> m_visibleItems;
184− int m_firstVisibleIndex;
185−
186− qreal m_minYExtent;
187−
188− QQuickItem *m_clipItem;
189−
190− // If any of the heights has changed
191− // or new items have been added/removed
192− bool m_contentHeightDirty;
193−
194− QQuickItem *m_headerItem;
195− qreal m_previousContentY;
196− qreal m_previousHeaderImplicitHeight;
197− qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position
198− // i.e. it's being shown after dragging down in the middle of the list
199− enum ContentYAnimationType { ContentYAnimationShowHeader, ContentYAnimationMaximizeVisibleArea };
200− ContentYAnimationType contentYAnimationType;
201− QQuickNumberAnimation *m_contentYAnimation;
202−
203− QQmlComponent *m_sectionDelegate;
204− QString m_sectionProperty;
205− QQuickItem *m_topSectionItem;
206−
207− bool m_forceNoClip;
208− bool m_inLayout;
209− bool m_inContentHeightKeepHeaderShown;
210− int m_cacheBuffer;
211−
212− // Qt 5.0 doesn't like releasing the items just after itemCreated
213− // so we delay the releasing until the next updatePolish
214− QList<ListItem *> m_itemsToRelease;
215−};
216−
217−
218−#endif
plugins/Dash/organicgrid.cppdeleted−259
@@ -1,259 +0,0 @@
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 "organicgrid.h"
18−
19−#include <math.h>
20−
21−#include <private/qquickitem_p.h>
22−
23−OrganicGrid::OrganicGrid()
24− : m_firstVisibleIndex(-1)
25− , m_numberOfModulesPerRow(-1)
26−{
27−}
28−
29−QSizeF OrganicGrid::smallDelegateSize() const
30−{
31− return m_smallDelegateSize;
32−}
33−
34−void OrganicGrid::setSmallDelegateSize(const QSizeF size)
35−{
36− if (m_smallDelegateSize != size) {
37− m_smallDelegateSize = size;
38− Q_EMIT smallDelegateSizeChanged();
39−
40− if (isComponentComplete()) {
41− relayout();
42− }
43− }
44−}
45−
46−QSizeF OrganicGrid::bigDelegateSize() const
47−{
48− return m_bigDelegateSize;
49−}
50−
51−void OrganicGrid::setBigDelegateSize(const QSizeF size)
52−{
53− if (m_bigDelegateSize != size) {
54− m_bigDelegateSize = size;
55− Q_EMIT bigDelegateSizeChanged();
56−
57− if (isComponentComplete()) {
58− relayout();
59− }
60− }
61−}
62−
63−QPointF OrganicGrid::positionForIndex(int modelIndex) const
64−{
65− const qreal moduleHeight = m_smallDelegateSize.height() + rowSpacing() + m_bigDelegateSize.height();
66− const qreal moduleWidth = m_smallDelegateSize.width() * 2 + columnSpacing() * 2 + m_bigDelegateSize.width();
67− const int itemsPerRow = m_numberOfModulesPerRow * 6;
68− const int rowIndex = floor(modelIndex / itemsPerRow);
69− const int columnIndex = floor((modelIndex - rowIndex * itemsPerRow) / 6);
70−
71− qreal yPos = (moduleHeight + rowSpacing()) * rowIndex;
72− const int moduleIndex = modelIndex % 6;
73− if (moduleIndex == 2) {
74− yPos += m_smallDelegateSize.height() + rowSpacing();
75− } else if (moduleIndex == 3 || moduleIndex == 5) {
76− yPos += m_bigDelegateSize.height() + rowSpacing();
77− }
78−
79− qreal xPos = (moduleWidth + columnSpacing()) * columnIndex;
80− if (moduleIndex == 1) {
81− xPos += m_smallDelegateSize.width() + columnSpacing();
82− } else if (moduleIndex == 3) {
83− xPos += m_bigDelegateSize.width() + columnSpacing();
84− } else if (moduleIndex == 4) {
85− xPos += (m_smallDelegateSize.width() + columnSpacing()) * 2;
86− } else if (moduleIndex == 5) {
87− xPos += m_bigDelegateSize.width() + m_smallDelegateSize.width() + columnSpacing() * 2;
88− }
89−
90− return QPointF(xPos, yPos);
91−}
92−
93−QSizeF OrganicGrid::sizeForIndex(int modelIndex) const
94−{
95− const int moduleIndex = modelIndex % 6;
96− if (moduleIndex == 0 || moduleIndex == 1 || moduleIndex == 3 || moduleIndex == 5) {
97− return m_smallDelegateSize;
98− } else {
99− return m_bigDelegateSize;
100− }
101−}
102−
103−void OrganicGrid::findBottomModelIndexToAdd(int *modelIndex, qreal *yPos)
104−{
105− if (m_visibleItems.isEmpty()) {
106− *modelIndex = 0;
107− *yPos = 0;
108− } else {
109− *modelIndex = m_firstVisibleIndex + m_visibleItems.count();
110− // We create stuff in a 6-module basis, so always return back
111− // the y position of the first item
112− const int firstModuleIndex = ((*modelIndex) / 6) * 6;
113− *yPos = positionForIndex(firstModuleIndex).y();
114− }
115−}
116−
117−void OrganicGrid::findTopModelIndexToAdd(int *modelIndex, qreal *yPos)
118−{
119− if (m_visibleItems.isEmpty()) {
120− *modelIndex = 0;
121− *yPos = 0;
122− } else {
123− *modelIndex = m_firstVisibleIndex - 1;
124− // We create stuff in a 6-module basis, so always return back
125− // the y position of the last item bottom
126− const int lastModuleIndex = ((*modelIndex) / 6) * 6 + 5;
127− *yPos = positionForIndex(lastModuleIndex).y();
128− *yPos += sizeForIndex(lastModuleIndex).height();
129− }
130−}
131−
132−void OrganicGrid::addItemToView(int modelIndex, QQuickItem *item)
133−{
134− // modelIndex has to be either m_firstVisibleIndex - 1 or m_firstVisibleIndex + m_visibleItems.count() or the first
135− if (modelIndex == m_firstVisibleIndex + m_visibleItems.count()) {
136− m_visibleItems << item;
137− } else if (modelIndex == m_firstVisibleIndex - 1) {
138− m_firstVisibleIndex = modelIndex;
139− m_visibleItems.prepend(item);
140− } else if (modelIndex == 0) {
141− m_firstVisibleIndex = 0;
142− m_visibleItems << item;
143− } else {
144− qWarning() << "OrganicGrid::addItemToView - Got unexpected modelIndex"
145− << modelIndex << m_firstVisibleIndex << m_visibleItems.count();
146− return;
147− }
148−
149− const QPointF pos = positionForIndex(modelIndex);
150− item->setPosition(pos);
151−
152− item->setSize(sizeForIndex(modelIndex));
153−}
154−
155−bool OrganicGrid::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
156−{
157− bool changed = false;
158−
159− // As adding, we also remove in a 6-module basis
160− int lastModuleIndex = (m_firstVisibleIndex / 6) * 6 + 5;
161− bool removeIndex = positionForIndex(lastModuleIndex).y() + sizeForIndex(lastModuleIndex).height() < bufferFromY;
162− while (removeIndex && !m_visibleItems.isEmpty()) {
163− releaseItem(m_visibleItems.takeFirst());
164− changed = true;
165− m_firstVisibleIndex++;
166−
167− lastModuleIndex = (m_firstVisibleIndex / 6) * 6 + 5;
168− removeIndex = positionForIndex(lastModuleIndex).y() + sizeForIndex(lastModuleIndex).height() < bufferFromY;
169− }
170−
171− int firstModuleIndex = ((m_firstVisibleIndex + m_visibleItems.count() - 1) / 6) * 6;
172− removeIndex = positionForIndex(firstModuleIndex).y() > bufferToY;
173− while (removeIndex && !m_visibleItems.isEmpty()) {
174− releaseItem(m_visibleItems.takeLast());
175− changed = true;
176−
177− firstModuleIndex = ((m_firstVisibleIndex + m_visibleItems.count() - 1) / 6) * 6;
178− removeIndex = positionForIndex(firstModuleIndex).y() > bufferToY;
179− }
180−
181− if (m_visibleItems.isEmpty()) {
182− m_firstVisibleIndex = -1;
183− }
184−
185− return changed;
186−}
187−
188−void OrganicGrid::cleanupExistingItems()
189−{
190− Q_FOREACH(QQuickItem *item, m_visibleItems)
191− releaseItem(item);
192− m_visibleItems.clear();
193− m_firstVisibleIndex = -1;
194− setImplicitHeightDirty();
195−}
196−
197−void OrganicGrid::doRelayout()
198−{
199− const qreal moduleWidth = m_smallDelegateSize.width() * 2 + columnSpacing() * 2 + m_bigDelegateSize.width();
200− m_numberOfModulesPerRow = floor((width() + columnSpacing()) / (moduleWidth + columnSpacing()));
201− m_numberOfModulesPerRow = qMax(1, m_numberOfModulesPerRow);
202−
203− int i = m_firstVisibleIndex;
204− const QList<QQuickItem*> allItems = m_visibleItems;
205− m_visibleItems.clear();
206− Q_FOREACH(QQuickItem *item, allItems) {
207− addItemToView(i, item);
208− ++i;
209− }
210−}
211−
212−void OrganicGrid::updateItemCulling(qreal visibleFromY, qreal visibleToY)
213−{
214− Q_FOREACH(QQuickItem *item, m_visibleItems) {
215− QQuickItemPrivate::get(item)->setCulled(item->y() + item->height() <= visibleFromY || item->y() >= visibleToY);
216− }
217−}
218−
219−void OrganicGrid::calculateImplicitHeight()
220−{
221− const qreal moduleHeight = m_smallDelegateSize.height() + rowSpacing() + m_bigDelegateSize.height();
222− const int itemCount = !model() ? 0 : model()->rowCount();
223− const int itemsPerRow = m_numberOfModulesPerRow * 6;
224− const int fullRows = floor(itemCount / itemsPerRow);
225− const qreal fullRowsHeight = fullRows == 0 ? 0 : fullRows * moduleHeight + rowSpacing() * (fullRows - 1);
226−
227− const int remainingItems = itemCount - fullRows * itemsPerRow;
228− if (remainingItems == 0) {
229− setImplicitHeight(fullRowsHeight);
230− } else if (remainingItems <= 2) {
231− setImplicitHeight(fullRowsHeight + m_smallDelegateSize.height() + rowSpacing());
232− } else {
233− setImplicitHeight(fullRowsHeight + rowSpacing() + moduleHeight);
234− }
235−}
236−
237−void OrganicGrid::processModelRemoves(const QVector<QQmlChangeSet::Change> &removes)
238−{
239− Q_FOREACH(const QQmlChangeSet::Change remove, removes) {
240− for (int i = remove.count - 1; i >= 0; --i) {
241− const int indexToRemove = remove.index + i;
242− // We only support removing from the end
243− const int lastIndex = m_firstVisibleIndex + m_visibleItems.count() - 1;
244− if (indexToRemove == lastIndex) {
245− releaseItem(m_visibleItems.takeLast());
246− } else {
247− if (indexToRemove < lastIndex) {
248− qDebug() << "OrganicGrid only supports removal from the end of the model, resetting instead";
249− cleanupExistingItems();
250− break;
251− }
252− }
253− }
254− }
255− if (m_visibleItems.isEmpty()) {
256− m_firstVisibleIndex = -1;
257− }
258− setImplicitHeightDirty();
259−}
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−70
@@ -1,70 +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−#include <QUrlQuery>
27−
28−static QUrl oauthCleanedUrl(QUrl u)
29−{
30− QUrlQuery q(u);
31− q.removeQueryItem(QStringLiteral("oauth_nonce"));
32− q.removeQueryItem(QStringLiteral("oauth_timestamp"));
33− q.removeQueryItem(QStringLiteral("oauth_consumer_key"));
34− q.removeQueryItem(QStringLiteral("oauth_signature_method"));
35− q.removeQueryItem(QStringLiteral("oauth_version"));
36− q.removeQueryItem(QStringLiteral("oauth_signature"));
37− u.setQuery(q);
38− return u;
39−}
40−
41−class AudioComparer : public QObject
42−{
43− Q_OBJECT
44−public:
45− Q_INVOKABLE bool compare(const QUrl &url1, const QUrl &url2)
46− {
47− return oauthCleanedUrl(url1) == oauthCleanedUrl(url2);
48− }
49−};
50−
51−static QObject *audio_comparer_singleton_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
52−{
53− Q_UNUSED(engine)
54− Q_UNUSED(scriptEngine)
55−
56− return new AudioComparer();
57−}
58−
59−void DashPlugin::registerTypes(const char *uri)
60−{
61− Q_ASSERT(uri == QLatin1String("Dash"));
62− qmlRegisterType<QAbstractItemModel>();
63− qmlRegisterType<HorizontalJournal>(uri, 0, 1, "HorizontalJournal");
64− qmlRegisterType<ListViewWithPageHeader>(uri, 0, 1, "ListViewWithPageHeader");
65− qmlRegisterType<OrganicGrid>(uri, 0, 1, "OrganicGrid");
66− qmlRegisterType<VerticalJournal>(uri, 0, 1, "VerticalJournal");
67− qmlRegisterSingletonType<AudioComparer>(uri, 0, 1, "AudioUrlComparer", audio_comparer_singleton_provider);
68−}
69−
70−#include "plugin.moc"
plugins/Dash/plugin.hdeleted−33
@@ -1,33 +0,0 @@
1−/*
2− * Copyright (C) 2012 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 DASH_PLUGIN_H
19−#define DASH_PLUGIN_H
20−
21−#include <QtQml/QQmlEngine>
22−#include <QtQml/QQmlExtensionPlugin>
23−
24−class DashPlugin : public QQmlExtensionPlugin
25−{
26− Q_OBJECT
27− Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
28−
29−public:
30− void registerTypes(const char *uri) override;
31−};
32−
33−#endif
plugins/Dash/qmldirdeleted−11
@@ -1,11 +0,0 @@
1−module Dash
2−plugin Dash-qml
3−typeinfo Dash.qmltypes
4−singleton CardCreatorCache 0.1 CardCreatorCache.qml
5−singleton DashAudioPlayer 0.1 DashAudioPlayer.qml
6−ScopeStyle 0.1 ScopeStyle.qml
7−CardAttributes 0.1 CardAttributes.qml
8−CardSocialActions 0.1 CardSocialActions.qml
9−CroppedImageMinimumSourceSize 0.1 CroppedImageMinimumSourceSize.qml
10−AudioProgressBar 0.1 AudioProgressBar.qml
11−CardAudioProgress 0.1 CardAudioProgress.qml
plugins/Dash/verticaljournal.cppdeleted−280
@@ -1,280 +0,0 @@
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−
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−#include <math.h>
31−
32−#include <private/qquickitem_p.h>
33−
34−VerticalJournal::VerticalJournal()
35− : m_columnWidth(0)
36−{
37−}
38−
39−qreal VerticalJournal::columnWidth() const
40−{
41− return m_columnWidth;
42−}
43−
44−void VerticalJournal::setColumnWidth(qreal columnWidth)
45−{
46− if (columnWidth != m_columnWidth) {
47− m_columnWidth = columnWidth;
48− Q_EMIT columnWidthChanged();
49−
50− if (isComponentComplete()) {
51− Q_FOREACH(const auto &column, m_columnVisibleItems) {
52− Q_FOREACH(const ViewItem item, column) {
53− item.m_item->setWidth(columnWidth);
54− }
55− }
56− relayout();
57− }
58− }
59−}
60−
61−void VerticalJournal::findBottomModelIndexToAdd(int *modelIndex, qreal *yPos)
62−{
63− *modelIndex = 0;
64− *yPos = std::numeric_limits<qreal>::max();
65−
66− Q_FOREACH(const auto &column, m_columnVisibleItems) {
67− if (!column.isEmpty()) {
68− const ViewItem &item = column.last();
69− *yPos = qMin(*yPos, item.y() + item.height() + rowSpacing());
70− *modelIndex = qMax(*modelIndex, item.m_modelIndex + 1);
71− } else {
72− *yPos = 0;
73− }
74− }
75−}
76−
77−void VerticalJournal::findTopModelIndexToAdd(int *modelIndex, qreal *yPos)
78−{
79− *modelIndex = 0;
80− *yPos = std::numeric_limits<qreal>::lowest();
81− int columnToAddTo = -1;
82−
83− // Find the topmost free column
84− for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
85− const auto &column = m_columnVisibleItems[i];
86− if (!column.isEmpty()) {
87− const ViewItem &item = column.first();
88− const auto itemTopPos = item.y() - rowSpacing();
89− if (itemTopPos > *yPos) {
90− *yPos = itemTopPos;
91− *modelIndex = item.m_modelIndex - 1;
92− columnToAddTo = i;
93− }
94− }
95− }
96−
97− if (*modelIndex > 0) {
98− Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
99− while (*modelIndex > 0 && m_indexColumnMap[*modelIndex] != columnToAddTo) {
100− // We found out that we have to add to columnToAddTo
101− // and thought that we had to add *modelIndex, but history tells
102− // it is not correct, so find up from *modelIndex until we found the index
103− // that has to end up in columnToAddTo
104− *modelIndex = *modelIndex - 1;
105− Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
106− }
107− }
108−}
109−
110−bool VerticalJournal::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
111−{
112− bool changed = false;
113−
114− for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
115− QList<ViewItem> &column = m_columnVisibleItems[i];
116− while (!column.isEmpty() && column.first().y() + column.first().height() < bufferFromY) {
117− releaseItem(column.takeFirst().m_item);
118− changed = true;
119− }
120−
121− while (!column.isEmpty() && column.last().y() > bufferToY) {
122− releaseItem(column.takeLast().m_item);
123− changed = true;
124− }
125− }
126−
127− return changed;
128−}
129−
130−void VerticalJournal::addItemToView(int modelIndex, QQuickItem *item)
131−{
132− if (item->width() != m_columnWidth) {
133− qWarning() << "Item" << modelIndex << "width is not the one that the columnWidth mandates, resetting it";
134− item->setWidth(m_columnWidth);
135− }
136−
137− // Check if we add it to the bottom of existing column items
138− const QList<ViewItem> &firstColumn = m_columnVisibleItems[0];
139− qreal columnToAddY = !firstColumn.isEmpty() ? firstColumn.last().y() + firstColumn.last().height() : -rowSpacing();
140− int columnToAddTo = 0;
141− for (int i = 1; i < m_columnVisibleItems.count(); ++i) {
142− const QList<ViewItem> &column = m_columnVisibleItems[i];
143− const qreal iY = !column.isEmpty() ? column.last().y() + column.last().height() : -rowSpacing();
144− if (iY < columnToAddY) {
145− columnToAddTo = i;
146− columnToAddY = iY;
147− }
148− }
149−
150− const QList<ViewItem> &columnToAdd = m_columnVisibleItems[columnToAddTo];
151− if (columnToAdd.isEmpty() || columnToAdd.last().m_modelIndex < modelIndex) {
152− item->setX(columnToAddTo * (m_columnWidth + columnSpacing()));
153− item->setY(columnToAddY + rowSpacing());
154−
155− m_columnVisibleItems[columnToAddTo] << ViewItem(item, modelIndex);
156− m_indexColumnMap[modelIndex] = columnToAddTo;
157− } else {
158− Q_ASSERT(m_indexColumnMap.contains(modelIndex));
159− columnToAddTo = m_indexColumnMap[modelIndex];
160− columnToAddY = m_columnVisibleItems[columnToAddTo].first().y();
161−
162− item->setX(columnToAddTo * (m_columnWidth + columnSpacing()));
163− item->setY(columnToAddY - rowSpacing() - item->height());
164−
165− m_columnVisibleItems[columnToAddTo].prepend(ViewItem(item, modelIndex));
166− }
167−}
168−
169−void VerticalJournal::cleanupExistingItems()
170−{
171− // Cleanup the existing items
172− for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
173− QList<ViewItem> &column = m_columnVisibleItems[i];
174− Q_FOREACH(const ViewItem item, column)
175− releaseItem(item.m_item);
176− column.clear();
177− }
178− m_indexColumnMap.clear();
179− setImplicitHeightDirty();
180−}
181−
182−void VerticalJournal::calculateImplicitHeight()
183−{
184− int lastModelIndex = -1;
185− qreal bottomMostY = 0;
186− Q_FOREACH(const auto &column, m_columnVisibleItems) {
187− if (!column.isEmpty()) {
188− const ViewItem &item = column.last();
189− lastModelIndex = qMax(lastModelIndex, item.m_modelIndex);
190− bottomMostY = qMax(bottomMostY, item.y() + item.height());
191− }
192− }
193− if (lastModelIndex >= 0) {
194− const double averageHeight = bottomMostY / (lastModelIndex + 1);
195− setImplicitHeight(bottomMostY + averageHeight * (model()->rowCount() - lastModelIndex - 1));
196− } else {
197− setImplicitHeight(0);
198− }
199−}
200−
201−void VerticalJournal::doRelayout()
202−{
203− QList<ViewItem> allItems;
204− Q_FOREACH(const auto &column, m_columnVisibleItems)
205− allItems << column;
206−
207− qSort(allItems);
208−
209− const int nColumns = qMax(1., floor((double)(width() + columnSpacing()) / (m_columnWidth + columnSpacing())));
210− m_columnVisibleItems.resize(nColumns);
211− m_indexColumnMap.clear();
212− for (int i = 0; i < nColumns; ++i)
213− m_columnVisibleItems[i].clear();
214−
215− // If the first of allItems doesn't contain index 0 we need to drop them
216− // all since we can't consistently relayout without the first item being there
217−
218− if (!allItems.isEmpty()) {
219− if (allItems.first().m_modelIndex == 0) {
220− Q_FOREACH(const ViewItem item, allItems)
221− addItemToView(item.m_modelIndex, item.m_item);
222− } else {
223− Q_FOREACH(const ViewItem item, allItems)
224− releaseItem(item.m_item);
225− }
226− }
227−}
228−
229−void VerticalJournal::updateItemCulling(qreal visibleFromY, qreal visibleToY)
230−{
231− Q_FOREACH(const auto &column, m_columnVisibleItems) {
232− Q_FOREACH(const ViewItem item, column) {
233− const bool cull = item.y() + item.height() <= visibleFromY || item.y() >= visibleToY;
234− QQuickItemPrivate::get(item.m_item)->setCulled(cull);
235− }
236− }
237−}
238−
239−void VerticalJournal::processModelRemoves(const QVector<QQmlChangeSet::Change> &removes)
240−{
241− Q_FOREACH(const QQmlChangeSet::Change remove, removes) {
242− for (int i = remove.count - 1; i >= 0; --i) {
243− const int indexToRemove = remove.index + i;
244− // Since we only support removing from the end, indexToRemove
245− // must refer to the last item of one of the columns or
246− // be bigger than them (because it's not in the viewport and
247− // thus we have not created a delegate for it)
248− bool found = false;
249− int lastCreatedIndex = INT_MIN;
250− for (int i = 0; !found && i < m_columnVisibleItems.count(); ++i) {
251− QList<ViewItem> &column = m_columnVisibleItems[i];
252− if (!column.isEmpty()) {
253− const int lastColumnIndex = column.last().m_modelIndex;
254− if (lastColumnIndex == indexToRemove) {
255− releaseItem(column.takeLast().m_item);
256− found = true;
257− }
258− lastCreatedIndex = qMax(lastCreatedIndex, lastColumnIndex);
259− }
260− }
261− if (!found) {
262− if (indexToRemove < lastCreatedIndex) {
263− qDebug() << "VerticalJournal only supports removal from the end of the model, resetting instead";
264− cleanupExistingItems();
265− break;
266− } else {
267− setImplicitHeightDirty();
268− }
269− }
270− }
271− }
272−}
273−
274−void VerticalJournal::itemGeometryChanged(QQuickItem * /*item*/, const QRectF &newGeometry, const QRectF &oldGeometry)
275−{
276− const qreal heightDiff = newGeometry.height() - oldGeometry.height();
277− if (heightDiff != 0) {
278− relayout();
279− }
280−}
plugins/Dash/verticaljournal.hdeleted−103
@@ -1,103 +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−protected:
69− void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) override;
70−
71−Q_SIGNALS:
72− void columnWidthChanged();
73−
74−private:
75− class ViewItem
76− {
77− public:
78− ViewItem(QQuickItem *item, int modelIndex) : m_item(item), m_modelIndex(modelIndex) {}
79− qreal x() const { return m_item->x(); }
80− qreal y() const { return m_item->y(); }
81− qreal height() const { return m_item->height(); }
82− bool operator<(const ViewItem v) const { return m_modelIndex < v.m_modelIndex; }
83−
84− QQuickItem *m_item;
85− int m_modelIndex;
86− };
87−
88− void findBottomModelIndexToAdd(int *modelIndex, qreal *yPos) override;
89− void findTopModelIndexToAdd(int *modelIndex, qreal *yPos) override;
90− bool removeNonVisibleItems(qreal bufferFromY, qreal bufferToY) override;
91− void addItemToView(int modelIndex, QQuickItem *item) override;
92− void cleanupExistingItems() override;
93− void calculateImplicitHeight() override;
94− void doRelayout() override;
95− void updateItemCulling(qreal visibleFromY, qreal visibleToY) override;
96− void processModelRemoves(const QVector<QQmlChangeSet::Change> &removes) override;
97−
98− QVector<QList<ViewItem>> m_columnVisibleItems;
99− QHash<int, int> m_indexColumnMap;
100− int m_columnWidth;
101−};
102−
103−#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+3
@@ -58,6 +58,9 @@ 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
plugins/Greeter/Unity/Launcher/CMakeLists.txt+1−3
@@ -1,4 +1,3 @@
1−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=11)
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/launcheritem.cpp+6
@@ -89,6 +89,12 @@ void LauncherItem::setKeywords(const QStringList &keywords)
8989 }
9090}
9191
92+uint LauncherItem::popularity() const
93+{
94+ // Not exposing usage order in greeter session at this point.
95+ return 0;
96+}
97+
9298bool LauncherItem::pinned() const
9399{
94100 return m_pinned;
plugins/Greeter/Unity/Launcher/launcheritem.h+1
@@ -35,6 +35,7 @@ public:
3535 QString name() const override;
3636 QString icon() const override;
3737 QStringList keywords() const override;
38+ uint popularity() const override;
3839 bool pinned() const override;
3940 bool running() const override;
4041 bool recent() const 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/ImageCache/CMakeLists.txtdeleted−8
@@ -1,8 +0,0 @@
1−add_library(ImageCache-qml MODULE
2− ImageCache.cpp
3− plugin.cpp
4− )
5−
6−qt5_use_modules(ImageCache-qml Gui Qml Quick)
7−
8−add_unity8_plugin(ImageCache 0.1 ImageCache TARGETS ImageCache-qml)
plugins/ImageCache/ImageCache.cppdeleted−135
@@ -1,135 +0,0 @@
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 <QDateTime>
18−#include <QDebug>
19−#include <QDir>
20−#include <QUrl>
21−#include <QUrlQuery>
22−
23−#include "ImageCache.h"
24−
25−ImageCache::ImageCache()
26− : QQuickImageProvider(QQmlImageProviderBase::Image,
27− QQmlImageProviderBase::ForceAsynchronousImageLoading)
28−{
29−}
30−
31−QString ImageCache::imageCacheRoot()
32−{
33− QString xdgCache(qgetenv("XDG_CACHE_HOME"));
34− if (xdgCache.isEmpty()) {
35− xdgCache = QDir::homePath() + QStringLiteral("/.cache");
36− }
37−
38− return QDir::cleanPath(xdgCache) + QStringLiteral("/unity8/imagecache");
39−}
40−
41−QFileInfo ImageCache::imagePath(const QUrl &image)
42−{
43− QUrlQuery query(image);
44−
45− auto name = query.queryItemValue(QStringLiteral("name"));
46− if (name.isEmpty()) {
47− name = QStringLiteral("/paths") + image.toLocalFile();
48− } else {
49− name = QStringLiteral("/names/") + name;
50− }
51−
52− return QFileInfo(imageCacheRoot() + name);
53−}
54−
55−bool ImageCache::needsUpdate(const QUrl &image, const QFileInfo &cachePath, const QSize &imageSize, const QSize &requestedSize, QSize &finalSize)
56−{
57− if (!cachePath.exists())
58− return true;
59−
60− QFileInfo imageInfo(image.toLocalFile());
61− if (imageInfo.lastModified() > cachePath.lastModified())
62− return true;
63−
64− QSize cacheSize(QImageReader(cachePath.filePath()).size());
65− finalSize = calculateSize(imageSize, requestedSize);
66− if (finalSize.isValid() && cacheSize != finalSize)
67− return true;
68−
69− return false;
70−}
71−
72−QSize ImageCache::calculateSize(const QSize &imageSize, const QSize &requestedSize)
73−{
74− QSize finalSize(requestedSize);
75−
76− if (finalSize.width() == 0) {
77− finalSize.setWidth(imageSize.width() * (((double)finalSize.height()) / imageSize.height()));
78− } else if (finalSize.height() == 0) {
79− finalSize.setHeight(imageSize.height() * (((double)finalSize.width()) / imageSize.width()));
80− }
81−
82− return finalSize;
83−}
84−
85−QImage ImageCache::loadAndCacheImage(QImageReader &reader, const QFileInfo &cachePath, const QSize &finalSize)
86−{
87− reader.setQuality(100);
88− reader.setScaledSize(finalSize);
89− auto format = reader.format(); // can't get this after reading
90−
91− QImage loadedImage(reader.read());
92− if (loadedImage.isNull()) {
93− qWarning() << "ImageCache could not read image" << reader.fileName() << ":" << reader.errorString();
94− return QImage();
95− }
96−
97− cachePath.dir().mkpath(QStringLiteral("."));
98− loadedImage.save(cachePath.filePath(), format, 100);
99−
100− return loadedImage;
101−}
102−
103−QImage ImageCache::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
104−{
105− QUrl image(id);
106− QImageReader imageReader(image.toLocalFile());
107− QSize imageSize(imageReader.size());
108− QImage result;
109−
110− // Early exit here, with no sourceSize, scaled-up sourceSize, or bad source image
111− if ((requestedSize.width() <= 0 && requestedSize.height() <= 0) ||
112− imageSize.isEmpty() ||
113− requestedSize.height() >= imageSize.height() ||
114− requestedSize.width() >= imageSize.width()) {
115− // We're only interested in scaling down, not up.
116− result = imageReader.read();
117− *size = result.size();
118− return result;
119− }
120−
121− auto cachePath = imagePath(image);
122− QSize finalSize;
123−
124− if (needsUpdate(image, cachePath, imageSize, requestedSize, finalSize)) {
125− if (finalSize.isEmpty()) {
126− finalSize = calculateSize(imageSize, requestedSize);
127− }
128− result = loadAndCacheImage(imageReader, cachePath, finalSize);
129− } else {
130− result = QImage(cachePath.filePath());
131− }
132−
133− *size = result.size();
134− return result;
135−}
plugins/ImageCache/ImageCache.hdeleted−53
@@ -1,53 +0,0 @@
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−#pragma once
18−
19−#include <QFileInfo>
20−#include <QImageReader>
21−#include <QQuickImageProvider>
22−#include <QSize>
23−
24−/**
25− * This class accepts an id formulated like a URL. So you'd use something like:
26− *
27− * Image {
28− * source: "image://unity8imagecache/file:///usr/share/..."
29− * }
30− *
31− * Right now, we only support file:/// URLs. We do accept some flags though:
32− *
33− * ?name=NAME
34− * - This will use NAME as the cache lookup key instead of the provided URL.
35− *
36− * We don't do any cleaning of old cached files yet. So you may want to always
37− * provide a name to avoid leaving lots of files around.
38− */
39−
40−class ImageCache: public QQuickImageProvider
41−{
42−public:
43− ImageCache();
44−
45− QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
46−
47−private:
48− static QString imageCacheRoot();
49− static QFileInfo imagePath(const QUrl &image);
50− static bool needsUpdate(const QUrl &image, const QFileInfo &cachePath, const QSize &imageSize, const QSize &requestedSize, QSize &finalSize);
51− static QSize calculateSize(const QSize &imageSize, const QSize &requestedSize);
52− static QImage loadAndCacheImage(QImageReader &reader, const QFileInfo &cachePath, const QSize &finalSize);
53−};
plugins/ImageCache/plugin.cppdeleted−39
@@ -1,39 +0,0 @@
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 <QQmlEngine>
18−
19−#include "ImageCache.h"
20−#include "plugin.h"
21−
22−#include <QtQml>
23−
24−void ImageCachePlugin::registerTypes(const char *uri)
25−{
26− Q_ASSERT(uri == QLatin1String("ImageCache"));
27−
28− qmlRegisterTypeNotAvailable(uri, 0, 1, "__ImageCacheIgnoreMe",
29− QStringLiteral("Ignore this: QML plugins must contain at least one type"));
30−}
31−
32−void ImageCachePlugin::initializeEngine(QQmlEngine* engine, const char* uri)
33−{
34− Q_ASSERT(uri == QLatin1String("ImageCache"));
35−
36− QQmlExtensionPlugin::initializeEngine(engine, uri);
37−
38− engine->addImageProvider("unity8imagecache", new ImageCache);
39−}
plugins/ImageCache/plugin.hdeleted−31
@@ -1,31 +0,0 @@
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−#pragma once
18−
19−#include <QQmlExtensionPlugin>
20−
21−class QQmlEngine;
22−
23−class ImageCachePlugin : public QQmlExtensionPlugin
24−{
25− Q_OBJECT
26− Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
27−
28−public:
29− void registerTypes(const char* uri) override;
30− void initializeEngine(QQmlEngine* engine, const char* uri) override;
31−};
plugins/ImageCache/qmldirdeleted−2
@@ -1,2 +0,0 @@
1−module ImageCache
2−plugin ImageCache-qml
plugins/LightDM/DBusGreeterList.cpp+3−3
@@ -25,7 +25,7 @@ DBusGreeterList::DBusGreeterList(Greeter *greeter, const QString &path)
2525 m_greeter(greeter)
2626{
2727 connect(m_greeter, &Greeter::authenticationUserChanged, this, &DBusGreeterList::authenticationUserChangedHandler);
28− connect(m_greeter, &Greeter::isAuthenticatedChanged, this, &DBusGreeterList::authenticatedChangedHandler);
28+ connect(m_greeter, &Greeter::promptlessChanged, this, &DBusGreeterList::promptlessChangedHandler);
2929}
3030
3131QString DBusGreeterList::GetActiveEntry() const
@@ -40,7 +40,7 @@ void DBusGreeterList::SetActiveEntry(const QString &entry)
4040
4141bool DBusGreeterList::entryIsLocked() const
4242{
43− return !m_greeter->isAuthenticated();
43+ return !m_greeter->promptless();
4444}
4545
4646void DBusGreeterList::authenticationUserChangedHandler()
@@ -49,7 +49,7 @@ void DBusGreeterList::authenticationUserChangedHandler()
4949 Q_EMIT EntrySelected(m_greeter->authenticationUser());
5050}
5151
52−void DBusGreeterList::authenticatedChangedHandler()
52+void DBusGreeterList::promptlessChangedHandler()
5353{
5454 notifyPropertyChanged(QStringLiteral("EntryIsLocked"), entryIsLocked());
5555 Q_EMIT entryIsLockedChanged();
plugins/LightDM/DBusGreeterList.h+1−1
@@ -48,7 +48,7 @@ Q_SIGNALS:
4848
4949private Q_SLOTS:
5050 void authenticationUserChangedHandler();
51− void authenticatedChangedHandler();
51+ void promptlessChangedHandler();
5252
5353private:
5454 Greeter *m_greeter;
plugins/LightDM/FullLightDM/CMakeLists.txt+1−1
@@ -26,7 +26,7 @@ target_link_libraries(FullLightDM-qml
2626 unity8-private
2727 ${LIBLIGHTDM_LDFLAGS}
2828 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
29+ Qt5::DBus Qt5::Gui Qt5::Qml
2930 )
3031
31−qt5_use_modules(FullLightDM-qml DBus Gui Qml)
3232add_unity8_plugin(FullLightDM 0.1 LightDM/FullLightDM TARGETS FullLightDM-qml)
plugins/LightDM/Greeter.cpp+16
@@ -27,6 +27,7 @@ GreeterPrivate::GreeterPrivate(Greeter* parent)
2727 m_active(false),
2828 responded(false),
2929 everResponded(false),
30+ promptless(false),
3031 q_ptr(parent)
3132{
3233}
@@ -112,6 +113,12 @@ QString Greeter::defaultSessionHint() const
112113 return d->m_greeter->defaultSessionHint();
113114}
114115
116+bool Greeter::promptless() const
117+{
118+ Q_D(const Greeter);
119+ return d->promptless;
120+}
121+
115122QString Greeter::selectUser() const
116123{
117124 Q_D(const Greeter);
@@ -146,6 +153,10 @@ void Greeter::authenticate(const QString &username)
146153 d->prompts.clear();
147154 d->responded = false;
148155 d->everResponded = false;
156+ if (d->promptless) {
157+ d->promptless = false;
158+ Q_EMIT promptlessChanged();
159+ }
149160
150161 if (authenticationUser() == username) {
151162 d->prompts = d->leftovers;
@@ -235,6 +246,11 @@ void Greeter::authenticationCompleteFilter()
235246 bool automatic = !d->everResponded;
236247 bool pamHasLeftoverMessages = !d->prompts.hasPrompt() && d->prompts.rowCount() > 0;
237248
249+ if (isAuthenticated() && automatic) {
250+ d->promptless = true;
251+ Q_EMIT promptlessChanged();
252+ }
253+
238254 if (!isAuthenticated()) {
239255 if (pamHasLeftoverMessages) {
240256 d->leftovers = d->prompts; // Prefer PAM's messages
plugins/LightDM/Greeter.h+3
@@ -37,6 +37,7 @@ class Greeter : public QObject
3737 Q_PROPERTY(bool authenticated READ isAuthenticated NOTIFY isAuthenticatedChanged)
3838 Q_PROPERTY(QString authenticationUser READ authenticationUser NOTIFY authenticationUserChanged)
3939 Q_PROPERTY(QString defaultSession READ defaultSessionHint CONSTANT)
40+ Q_PROPERTY(bool promptless READ promptless NOTIFY promptlessChanged)
4041 Q_PROPERTY(QString selectUser READ selectUser CONSTANT)
4142
4243public:
@@ -47,6 +48,7 @@ public:
4748 bool isAuthenticated() const;
4849 QString authenticationUser() const;
4950 QString defaultSessionHint() const;
51+ bool promptless() const;
5052 QString selectUser() const;
5153 bool hasGuestAccount() const;
5254 bool showManualLoginHint() const;
@@ -64,6 +66,7 @@ Q_SIGNALS:
6466 void authenticationUserChanged();
6567 void isActiveChanged();
6668 void isAuthenticatedChanged();
69+ void promptlessChanged();
6770 void showGreeter();
6871 void hideGreeter();
6972 void loginError(bool automatic);
plugins/LightDM/GreeterPrivate.h+1
@@ -34,6 +34,7 @@ public:
3434 PromptsModel leftovers; // prompts to show during next auth for same user
3535 bool responded;
3636 bool everResponded;
37+ bool promptless;
3738 QString cachedAuthUser;
3839
3940protected:
plugins/LightDM/IntegratedLightDM/CMakeLists.txt+1−1
@@ -25,9 +25,9 @@ target_link_libraries(IntegratedLightDM-qml
2525 integratedLightDM
2626 unity8-private
2727 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
28+ Qt5::DBus Qt5::Gui Qt5::Qml
2829 )
2930
30−qt5_use_modules(IntegratedLightDM-qml DBus Gui Qml)
3131add_unity8_plugin(IntegratedLightDM 0.1 LightDM/IntegratedLightDM TARGETS IntegratedLightDM-qml)
3232
3333add_subdirectory(liblightdm)
plugins/LightDM/IntegratedLightDM/liblightdm/CMakeLists.txt+3−4
@@ -26,22 +26,21 @@ target_link_libraries(integratedLightDM
2626 ${GLIB_LIBRARIES}
2727 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
2828 -lpam
29+ Qt5::Concurrent Qt5::DBus Qt5::Gui
2930)
3031target_link_libraries(integratedLightDMSession
3132 ${GLIB_LIBRARIES}
3233 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
3334 -lpam
35+ Qt5::Concurrent Qt5::DBus Qt5::Gui
3436)
3537target_link_libraries(MockLightDM-demo-shared
3638 ${GLIB_LIBRARIES}
3739 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
3840 -lpam
41+ Qt5::Concurrent Qt5::DBus Qt5::Gui
3942)
4043
41−qt5_use_modules(integratedLightDM Concurrent DBus Gui)
42−qt5_use_modules(integratedLightDMSession Concurrent DBus Gui)
43−qt5_use_modules(MockLightDM-demo-shared Concurrent DBus Gui)
44−
4544set_target_properties(integratedLightDM PROPERTIES
4645 COMPILE_FLAGS "-DSM_BUSNAME=systemBus -fPIC")
4746set_target_properties(integratedLightDMSession PROPERTIES
plugins/LightDM/UsersModel.cpp+5
@@ -109,6 +109,11 @@ QVariant MangleModel::data(const QModelIndex &index, int role) const
109109 variantData = stringData;
110110 }
111111
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+
112117 return variantData;
113118}
114119
plugins/Lights/CMakeLists.txt+8−2
@@ -1,5 +1,6 @@
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(
56 SYSTEM
@@ -9,9 +10,14 @@ include_directories(
910add_library(Lights-qml MODULE
1011 plugin.cpp
1112 Lights.cpp
13+ LegacyLights.cpp
14+ HfdLights.cpp
1215 )
1316
14−qt5_use_modules(Lights-qml Qml Gui)
15−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+ )
1622
1723add_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+4−8
@@ -22,8 +22,6 @@
2222#include <QtCore/QObject>
2323#include <QtGui/QColor>
2424
25−struct light_device_t;
26−
2725class Lights: public QObject
2826{
2927 Q_OBJECT
@@ -40,7 +38,6 @@ public:
4038 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/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−2
@@ -9,7 +9,9 @@ add_library(Powerd-qml MODULE
99 Powerd.cpp
1010 )
1111
12−qt5_use_modules(Powerd-qml DBus Qml)
13−target_link_libraries(Powerd-qml ${GIO_LDFLAGS})
12+target_link_libraries(Powerd-qml
13+ Qt5::DBus Qt5::Qml
14+ ${GIO_LDFLAGS}
15+ )
1416
1517add_unity8_plugin(Powerd 0.1 Powerd TARGETS Powerd-qml)
plugins/ScreenshotDirectory/CMakeLists.txt+1−1
@@ -4,6 +4,6 @@ set(PLUGIN_SOURCES
44)
55
66add_library(ScreenshotDirectory-qml MODULE ${PLUGIN_SOURCES})
7−qt5_use_modules(ScreenshotDirectory-qml Qml Gui Quick)
7+target_link_libraries(ScreenshotDirectory-qml Qt5::Qml Qt5::Gui Qt5::Quick)
88
99add_unity8_plugin(ScreenshotDirectory 0.1 ScreenshotDirectory TARGETS ScreenshotDirectory-qml)
plugins/SessionBroadcast/CMakeLists.txt+1−2
@@ -6,9 +6,8 @@ add_library(SessionBroadcast-qml MODULE
66 plugin.cpp
77 )
88
9−qt5_use_modules(SessionBroadcast-qml DBus Qml)
10−
119target_link_libraries(SessionBroadcast-qml
10+ Qt5::DBus Qt5::Qml
1211 ${GLIB_LIBRARIES}
1312 )
1413
plugins/UInput/CMakeLists.txt+1−1
@@ -3,5 +3,5 @@ add_library(UInput-qml MODULE
33 uinput.cpp
44)
55
6−qt5_use_modules(UInput-qml Qml)
6+target_link_libraries(UInput-qml Qt5::Qml)
77add_unity8_plugin(UInput 0.1 UInput TARGETS UInput-qml)
plugins/Ubuntu/CMakeLists.txt−1
@@ -1,3 +1,2 @@
11add_subdirectory(Gestures)
22add_subdirectory(DownloadDaemonListener)
3−add_subdirectory(SystemImage)
plugins/Ubuntu/DownloadDaemonListener/CMakeLists.txt+4−2
@@ -11,8 +11,10 @@ set(DOWNLOADDAEMONLISTENER_SOURCES
1111
1212add_library(DownloadDaemonListener MODULE ${DOWNLOADDAEMONLISTENER_SOURCES})
1313
14−qt5_use_modules(DownloadDaemonListener Qml Quick DBus Core)
1514pkg_check_modules(DDLADAPTER REQUIRED udm-common)
1615add_definitions(${DDLADAPTER_CFLAGS} ${DDLADAPTER_CFLAGS_OTHER})
17−target_link_libraries(DownloadDaemonListener ${DDLADAPTER_LIBRARIES})
16+target_link_libraries(DownloadDaemonListener
17+ Qt5::Qml Qt5::Quick Qt5::DBus Qt5::Core
18+ ${DDLADAPTER_LIBRARIES}
19+ )
1820add_unity8_plugin(Ubuntu.DownloadDaemonListener 0.1 Ubuntu/DownloadDaemonListener TARGETS DownloadDaemonListener)
plugins/Ubuntu/Gestures/CMakeLists.txt+1−3
@@ -17,9 +17,7 @@ pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
1717add_definitions(-DUBUNTUGESTURESQML_LIBRARY)
1818
1919add_library(UbuntuGesturesQml SHARED ${UbuntuGesturesQml_SOURCES})
20−target_link_libraries(UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES})
21−
22−qt5_use_modules(UbuntuGesturesQml Core Quick)
20+target_link_libraries(UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES} Qt5::Core Qt5::Quick)
2321
2422# So that Foo.cpp can #include "Foo.moc"
2523include_directories(${CMAKE_CURRENT_BINARY_DIR})
plugins/Ubuntu/Gestures/TouchGestureArea.cpp+6−5
@@ -328,6 +328,12 @@ void TouchGestureArea::touchEvent_rejected(QTouchEvent *event)
328328 }
329329 }
330330 }
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();
331337}
332338
333339void TouchGestureArea::unownedTouchEvent(QTouchEvent *unownedTouchEvent)
@@ -735,7 +741,6 @@ void TouchGestureArea::resyncCachedTouchPoints()
735741 bool added = false;
736742 bool ended = false;
737743 bool moved = false;
738− bool wantsDrag = false;
739744
740745 // list of deletes
741746 QMutableHashIterator<int, GestureTouchPoint*> removeIter(m_cachedTouchPoints);
@@ -765,10 +770,6 @@ void TouchGestureArea::resyncCachedTouchPoints()
765770 }
766771 }
767772
768− if (wantsDrag && !dragging()) {
769− setDragging(true);
770− }
771−
772773 if (ended) {
773774 if (m_cachedTouchPoints.isEmpty()) {
774775 if (!dragging()) Q_EMIT clicked();
plugins/Ubuntu/SystemImage/CMakeLists.txtdeleted−15
@@ -1,15 +0,0 @@
1−include_directories(
2− ${GLIB_INCLUDE_DIRS}
3−)
4−
5−set(SYSTEMIMAGE_SOURCES
6− plugin.cpp
7− SystemImage.cpp
8−)
9−
10−add_library(SystemImage MODULE ${SYSTEMIMAGE_SOURCES})
11−
12−qt5_use_modules(SystemImage Qml DBus Core)
13−target_link_libraries(SystemImage ${GLIB_LIBRARIES})
14−
15−add_unity8_plugin(Ubuntu.SystemImage 0.1 Ubuntu/SystemImage TARGETS SystemImage)
plugins/Ubuntu/SystemImage/SystemImage.cppdeleted−155
@@ -1,155 +0,0 @@
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 <QDBusConnection>
18−#include <QDBusPendingCall>
19−#include <QDBusReply>
20−#include <QDebug>
21−
22−#include <glib.h>
23−
24−#include "SystemImage.h"
25−
26−#define SYSTEMIMAGE_SERVICE QStringLiteral("com.canonical.SystemImage")
27−#define SYSTEMIMAGE_PATH QStringLiteral("/Service")
28−#define SYSTEMIMAGE_IFACE QStringLiteral("com.canonical.SystemImage")
29−
30−Q_LOGGING_CATEGORY(SYSTEMIMAGEPLUGIN, "unity8.systemimage", QtWarningMsg)
31−
32−#define DEBUG_MSG qCDebug(SYSTEMIMAGEPLUGIN).nospace().noquote() << Q_FUNC_INFO
33−#define WARNING_MSG qCWarning(SYSTEMIMAGEPLUGIN).nospace().noquote() << Q_FUNC_INFO
34−
35−SystemImage::SystemImage(QObject *parent)
36− : QObject(parent)
37−{
38− QDBusConnection::systemBus().connect(SYSTEMIMAGE_SERVICE, SYSTEMIMAGE_PATH, SYSTEMIMAGE_IFACE, QStringLiteral("UpdateAvailableStatus"),
39− this, SLOT(onUpdateAvailableStatus(bool,bool,QString,int,QString,QString)));
40− QDBusConnection::systemBus().connect(SYSTEMIMAGE_SERVICE, SYSTEMIMAGE_PATH, SYSTEMIMAGE_IFACE, QStringLiteral("UpdateDownloaded"),
41− this, SLOT(onUpdateDownloaded()));
42− QDBusConnection::systemBus().connect(SYSTEMIMAGE_SERVICE, SYSTEMIMAGE_PATH, SYSTEMIMAGE_IFACE, QStringLiteral("UpdateFailed"),
43− this, SLOT(onUpdateFailed(int,QString)));
44− QDBusConnection::systemBus().connect(SYSTEMIMAGE_SERVICE, SYSTEMIMAGE_PATH, SYSTEMIMAGE_IFACE, QStringLiteral("Applied"),
45− this, SLOT(onUpdateApplied(bool)));
46− QDBusConnection::systemBus().connect(SYSTEMIMAGE_SERVICE, SYSTEMIMAGE_PATH, SYSTEMIMAGE_IFACE, QStringLiteral("Rebooting"),
47− this, SLOT(onRebooting(bool)));
48−}
49−
50−void SystemImage::checkForUpdate()
51−{
52− DEBUG_MSG << "Checking for update";
53− const QDBusMessage msg = QDBusMessage::createMethodCall(SYSTEMIMAGE_SERVICE, SYSTEMIMAGE_PATH, SYSTEMIMAGE_IFACE,
54− QStringLiteral("CheckForUpdate"));
55− QDBusConnection::systemBus().asyncCall(msg);
56−}
57−
58−void SystemImage::applyUpdate()
59−{
60− DEBUG_MSG << "Applying update";
61− setUpdateApplying(true);
62−
63− const QDBusMessage msg = QDBusMessage::createMethodCall(SYSTEMIMAGE_SERVICE, SYSTEMIMAGE_PATH, SYSTEMIMAGE_IFACE,
64− QStringLiteral("ApplyUpdate"));
65− QDBusConnection::systemBus().asyncCall(msg);
66−}
67−
68−void SystemImage::factoryReset()
69−{
70− const QDBusMessage msg = QDBusMessage::createMethodCall(SYSTEMIMAGE_SERVICE, SYSTEMIMAGE_PATH, SYSTEMIMAGE_IFACE,
71− QStringLiteral("FactoryReset"));
72− QDBusConnection::systemBus().asyncCall(msg);
73−}
74−
75−void SystemImage::onUpdateAvailableStatus(bool is_available, bool downloading, const QString &available_version, int update_size,
76− const QString &last_update_date, const QString &error_reason)
77−{
78− DEBUG_MSG << "A new update is " << (is_available ? "" : "NOT") << "available";
79−
80− if (is_available == m_updateAvailable) {
81− return;
82− }
83−
84− m_updateAvailable = is_available;
85− m_downloading = downloading;
86− m_availableVersion = available_version;
87− m_updateSize = formatSize(update_size);
88− m_lastUpdateDate = last_update_date;
89− m_errorReason = error_reason;
90− Q_EMIT updateAvailableStatus();
91−
92− DEBUG_MSG << "Downloading: " << downloading << ", version: " << available_version << ", last update: " << last_update_date <<
93− ", size: " << m_updateSize;
94−}
95−
96−void SystemImage::onUpdateDownloaded()
97−{
98− DEBUG_MSG << "Update downloaded";
99−
100− m_downloaded = true;
101− Q_EMIT updateDownloadedChanged();
102−}
103−
104−void SystemImage::onUpdateFailed(int /*consecutive_failure_count*/, const QString &last_reason)
105−{
106− WARNING_MSG << "System Update failed: " << last_reason;
107− setUpdateApplying(false);
108−}
109−
110−void SystemImage::onUpdateApplied(bool applied)
111−{
112− DEBUG_MSG << "System Update applied with status: " << applied;
113− setUpdateApplying(false);
114− if (applied) {
115− resetUpdateStatus();
116− Q_EMIT updateAvailableStatus();
117− }
118−}
119−
120−void SystemImage::onRebooting(bool status)
121−{
122− setUpdateApplying(false);
123− DEBUG_MSG << "Rebooting: " << status;
124−}
125−
126−void SystemImage::setUpdateApplying(bool status)
127−{
128− if (status != m_updateApplying) {
129− m_updateApplying = status;
130− Q_EMIT updateApplyingChanged();
131− }
132−}
133−
134−void SystemImage::resetUpdateStatus()
135−{
136− m_updateAvailable = false;
137− m_updateApplying = false;
138− m_downloading = false;
139− m_downloaded = false;
140− m_availableVersion.clear();
141− m_updateSize.clear();
142− m_lastUpdateDate.clear();
143− m_errorReason.clear();
144−}
145−
146−QString SystemImage::formatSize(quint64 size) const
147−{
148− guint64 g_size = size;
149−
150− gchar * formatted_size = g_format_size(g_size);
151− QString q_formatted_size = QString::fromLocal8Bit(formatted_size);
152− g_free(formatted_size);
153−
154− return q_formatted_size;
155−}
plugins/Ubuntu/SystemImage/SystemImage.hdeleted−84
@@ -1,84 +0,0 @@
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 SYSTEMIMAGE_H
18−#define SYSTEMIMAGE_H
19−
20−#include <QObject>
21−#include <QLoggingCategory>
22−
23−Q_DECLARE_LOGGING_CATEGORY(SYSTEMIMAGEPLUGIN)
24−
25−class SystemImage : public QObject
26−{
27− Q_OBJECT
28− Q_DISABLE_COPY(SystemImage)
29−
30− Q_PROPERTY(bool updateAvailable READ updateAvailable NOTIFY updateAvailableStatus)
31− Q_PROPERTY(bool updateDownloading READ updateDownloading NOTIFY updateAvailableStatus)
32− Q_PROPERTY(QString availableVersion READ availableVersion NOTIFY updateAvailableStatus)
33− Q_PROPERTY(QString updateSize READ updateSize NOTIFY updateAvailableStatus)
34− Q_PROPERTY(bool updateApplying READ updateApplying NOTIFY updateApplyingChanged)
35− Q_PROPERTY(bool updateDownloaded READ updateDownloaded NOTIFY updateDownloadedChanged)
36−
37−public:
38− explicit SystemImage(QObject *parent = nullptr);
39− ~SystemImage() = default;
40−
41− bool updateAvailable() const { return m_updateAvailable; }
42− bool updateDownloading() const { return m_downloading; }
43− QString availableVersion() const { return m_availableVersion; }
44− QString updateSize() const { return m_updateSize; }
45− bool updateApplying() const { return m_updateApplying; }
46− bool updateDownloaded() const { return m_downloaded; }
47−
48−public Q_SLOTS:
49− Q_INVOKABLE void checkForUpdate();
50− Q_INVOKABLE void applyUpdate();
51− Q_INVOKABLE void factoryReset();
52−
53−private Q_SLOTS:
54− void onUpdateAvailableStatus(bool is_available, bool updateDownloading, const QString &available_version,
55− int update_size, const QString &last_update_date, const QString &error_reason);
56− void onUpdateDownloaded();
57− void onUpdateFailed(int consecutive_failure_count, const QString & last_reason);
58− void onUpdateApplied(bool applied);
59− void onRebooting(bool status);
60−
61−Q_SIGNALS:
62− void updateAvailableStatus();
63− void updateDownloadedChanged();
64− void updateApplyingChanged();
65−
66−private Q_SLOTS:
67− void setUpdateApplying(bool status);
68−
69−private:
70− void resetUpdateStatus();
71− QString formatSize(quint64 size) const;
72−
73−private:
74− bool m_updateAvailable = false;
75− bool m_updateApplying = false;
76− bool m_downloading = false;
77− bool m_downloaded = false;
78− QString m_availableVersion;
79− QString m_updateSize;
80− QString m_lastUpdateDate;
81− QString m_errorReason;
82−};
83−
84−#endif // SYSTEMIMAGE_H
plugins/Ubuntu/SystemImage/plugin.cppdeleted−28
@@ -1,28 +0,0 @@
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 "plugin.h"
18−#include "SystemImage.h"
19−
20−#include <QtQml>
21−
22−void BackendPlugin::registerTypes(const char *uri)
23−{
24− Q_ASSERT(uri == QLatin1String("Ubuntu.SystemImage"));
25−
26− qmlRegisterSingletonType<SystemImage>(uri, 0, 1, "SystemImage",
27− [](QQmlEngine*, QJSEngine*) -> QObject* { return new SystemImage; });
28−}
plugins/Ubuntu/SystemImage/plugin.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 SYSTEMIMAGE_PLUGIN_H
18−#define SYSTEMIMAGE_PLUGIN_H
19−
20−#include <QQmlExtensionPlugin>
21−
22−class BackendPlugin : public QQmlExtensionPlugin
23−{
24− Q_OBJECT
25− Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
26−
27−public:
28− void registerTypes(const char *uri) override;
29−};
30−
31−#endif // SYSTEMIMAGE_PLUGIN_H
plugins/Ubuntu/SystemImage/qmldirdeleted−3
@@ -1,3 +0,0 @@
1−module Ubuntu.SystemImage
2−plugin SystemImage
3−typeinfo SystemImage.qmltypes
plugins/Unity/ApplicationMenu/CMakeLists.txt+1−1
@@ -14,6 +14,6 @@ qt5_add_dbus_adaptor(applicationMenu_SRCS com.ubuntu.MenuRegistrar.xml dbusappli
1414
1515add_library(ApplicationMenu-qml MODULE ${applicationMenu_SRCS})
1616
17−qt5_use_modules(ApplicationMenu-qml DBus Qml)
17+target_link_libraries(ApplicationMenu-qml Qt5::DBus Qt5::Qml)
1818
1919add_unity8_plugin(Unity.ApplicationMenu 0.1 Unity/ApplicationMenu TARGETS ApplicationMenu-qml)
plugins/Unity/CMakeLists.txt−1
@@ -3,6 +3,5 @@ add_subdirectory(Connectivity)
33add_subdirectory(Indicators)
44add_subdirectory(Launcher)
55add_subdirectory(Session)
6−add_subdirectory(DashCommunicator)
76add_subdirectory(InputInfo)
87add_subdirectory(Platform)
plugins/Unity/Connectivity/CMakeLists.txt+1−1
@@ -5,6 +5,6 @@ set(CONNECTIVITY_SOURCES
55
66add_library(Connectivity MODULE ${CONNECTIVITY_SOURCES})
77
8−qt5_use_modules(Connectivity Qml DBus Core)
8+target_link_libraries(Connectivity Qt5::Qml Qt5::DBus Qt5::Core)
99
1010add_unity8_plugin(Unity.Connectivity 0.1 Unity/Connectivity TARGETS Connectivity)
plugins/Unity/DashCommunicator/CMakeLists.txtdeleted−26
@@ -1,26 +0,0 @@
1−include_directories(
2− ${CMAKE_CURRENT_SOURCE_DIR}
3− ${CMAKE_CURRENT_BINARY_DIR}
4− ${libunity8-private_SOURCE_DIR}
5−)
6−
7−set(QMLDASHCOMMUNICATORPLUGIN_SRC
8− plugin.cpp
9− dbusdashcommunicatorservice.cpp
10− dashcommunicatorservice.cpp
11− dashcommunicator.cpp
12− dashconnection.cpp
13−)
14−
15−add_library(DashCommunicator-qml MODULE
16− ${QMLDASHCOMMUNICATORPLUGIN_SRC}
17−)
18−
19−qt5_use_modules(DashCommunicator-qml DBus Qml)
20−
21−target_link_libraries(DashCommunicator-qml
22− unity8-private
23−)
24−
25−# export the qmldir and qmltypes files
26−add_unity8_plugin(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS DashCommunicator-qml)
plugins/Unity/DashCommunicator/dashcommunicator.cppdeleted−58
@@ -1,58 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it under
5− * the terms of the GNU Lesser General Public License version 3, as published by
6− * the Free Software Foundation.
7− *
8− * This program is distributed in the hope that it will be useful, but WITHOUT
9− * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10− * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11− * 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−
17−#include "dashcommunicator.h"
18−#include "dashconnection.h"
19−
20−#include <QObject>
21−
22−DashCommunicator::DashCommunicator(QObject *parent):
23− QThread(parent),
24− m_dashConnection(nullptr),
25− m_created(false)
26−{
27− start();
28−}
29−
30−DashCommunicator::~DashCommunicator()
31−{
32− quit();
33− wait();
34−}
35−
36−void DashCommunicator::setCurrentScope(int index, bool animate, bool isSwipe)
37−{
38− m_mutex.lock();
39− if (m_created) {
40− QMetaObject::invokeMethod(m_dashConnection, "setCurrentScope",
41− Q_ARG(int, index),
42− Q_ARG(bool, animate),
43− Q_ARG(bool, isSwipe));
44− }
45− m_mutex.unlock();
46−}
47−
48−void DashCommunicator::run()
49−{
50− m_dashConnection = new DashConnection(QStringLiteral("com.canonical.UnityDash"),
51− QStringLiteral("/com/canonical/UnityDash"),
52− QLatin1String(""), this);
53− m_mutex.lock();
54− m_created = true;
55− m_mutex.unlock();
56−
57− exec();
58−}
plugins/Unity/DashCommunicator/dashcommunicatorservice.cppdeleted−30
@@ -1,30 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it under
5− * the terms of the GNU Lesser General Public License version 3, as published by
6− * the Free Software Foundation.
7− *
8− * This program is distributed in the hope that it will be useful, but WITHOUT
9− * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10− * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11− * 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−
17−#include "dashcommunicatorservice.h"
18−
19−DashCommunicatorService::DashCommunicatorService(QObject *parent):
20− QObject(parent),
21− m_dbusService(new DBusDashCommunicatorService(this))
22−{
23− connect(m_dbusService, &DBusDashCommunicatorService::setCurrentScopeRequested, this, &DashCommunicatorService::setCurrentScopeRequested);
24−}
25−
26−
27−DashCommunicatorService::~DashCommunicatorService()
28−{
29−
30−}
plugins/Unity/DashCommunicator/dashcommunicatorservice.hdeleted−38
@@ -1,38 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it under
5− * the terms of the GNU Lesser General Public License version 3, as published by
6− * the Free Software Foundation.
7− *
8− * This program is distributed in the hope that it will be useful, but WITHOUT
9− * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10− * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11− * 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−
17−#ifndef DASHCOMMUNICATORSERVICE_H
18−#define DASHCOMMUNICATORSERVICE_H
19−
20−#include "dbusdashcommunicatorservice.h"
21−
22−#include <QObject>
23−
24−class DashCommunicatorService: public QObject
25−{
26− Q_OBJECT
27−public:
28− DashCommunicatorService(QObject *parent = 0);
29− ~DashCommunicatorService();
30−
31−Q_SIGNALS:
32− void setCurrentScopeRequested(int index, bool animate, bool isSwipe);
33−
34−private:
35− DBusDashCommunicatorService *m_dbusService;
36−};
37−
38−#endif // DBUSUNITYSESSIONSERVICE_H
plugins/Unity/DashCommunicator/dashconnection.cppdeleted−66
@@ -1,66 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it under
5− * the terms of the GNU Lesser General Public License version 3, as published by
6− * the Free Software Foundation.
7− *
8− * This program is distributed in the hope that it will be useful, but WITHOUT
9− * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10− * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11− * 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−
17−#include "dashconnection.h"
18−
19−#include <QDBusInterface>
20−#include <QDBusPendingCall>
21−
22−/* The default implementation of AbstractDBusServiceMonitor creates a QDBusInterface when the service
23− * appears on the bus.
24− *
25− * On construction QDBusInterface synchronously introspects the service, which will block the GUI
26− * thread of this process if the service is busy. QDBusAbstractInterface does not perform this
27− * introspection, so let's subclass that and avoid the blocking scenario.
28− *
29− * However we lose Qt's wrapping of the DBus service with a MetaObject, with the result that we
30− * cannot easily connect to DBus signals with the usual connect() calls. So this approach only
31− * suited to push communication with the DBus service.
32− */
33−class AsyncDBusInterface : public QDBusAbstractInterface
34−{
35− Q_OBJECT
36−public:
37− AsyncDBusInterface(const QString &service, const QString &path,
38− const QString &interface, const QDBusConnection &connection,
39− QObject *parent = 0)
40− : QDBusAbstractInterface(service, path, interface.toLatin1().data(), connection, parent)
41− {}
42− ~AsyncDBusInterface() = default;
43−};
44−
45−
46−DashConnection::DashConnection(const QString &service, const QString &path, const QString &interface, QObject *parent):
47− AbstractDBusServiceMonitor(service, path, interface, SessionBus, parent)
48−{
49−
50−}
51−
52−/* Override the default implementation to create a non-blocking DBus interface (see note above). */
53−QDBusAbstractInterface* DashConnection::createInterface(const QString &service, const QString &path,
54− const QString &interface, const QDBusConnection &connection)
55−{
56− return new AsyncDBusInterface(service, path, interface, connection);
57−}
58−
59−void DashConnection::setCurrentScope(int index, bool animate, bool isSwipe)
60−{
61− if (dbusInterface()) {
62− dbusInterface()->asyncCall(QStringLiteral("SetCurrentScope"), index, animate, isSwipe);
63− }
64−}
65−
66−#include "dashconnection.moc"
plugins/Unity/DashCommunicator/dashconnection.hdeleted−37
@@ -1,37 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it under
5− * the terms of the GNU Lesser General Public License version 3, as published by
6− * the Free Software Foundation.
7− *
8− * This program is distributed in the hope that it will be useful, but WITHOUT
9− * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10− * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11− * 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−
17−#ifndef THREADEDDASHCONNECTION_H
18−#define THREADEDDASHCONNECTION_H
19−
20−// local
21−#include "abstractdbusservicemonitor.h"
22−
23−class DashConnection: public AbstractDBusServiceMonitor
24−{
25− Q_OBJECT
26−public:
27− DashConnection(const QString &service, const QString &path, const QString &interface, QObject *parent = 0);
28−
29−public Q_SLOTS:
30− void setCurrentScope(int index, bool animate, bool isSwipe);
31−
32−private:
33− QDBusAbstractInterface* createInterface(const QString &service, const QString &path,
34− const QString &interface, const QDBusConnection &connection) override;
35−};
36−
37−#endif
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cppdeleted−35
@@ -1,35 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it under
5− * the terms of the GNU Lesser General Public License version 3, as published by
6− * the Free Software Foundation.
7− *
8− * This program is distributed in the hope that it will be useful, but WITHOUT
9− * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10− * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11− * 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−
17−#include "dbusdashcommunicatorservice.h"
18−
19−#include <QDBusConnection>
20−#include <QDBusInterface>
21−#include <QDebug>
22−
23−DBusDashCommunicatorService::DBusDashCommunicatorService(QObject *parent):
24− UnityDBusObject(QStringLiteral("/com/canonical/UnityDash"), QStringLiteral("com.canonical.UnityDash"), false, parent)
25−{
26−}
27−
28−DBusDashCommunicatorService::~DBusDashCommunicatorService()
29−{
30−}
31−
32−void DBusDashCommunicatorService::SetCurrentScope(int index, bool animate, bool isSwipe)
33−{
34− Q_EMIT setCurrentScopeRequested(index, animate, isSwipe);
35−}
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.hdeleted−39
@@ -1,39 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it under
5− * the terms of the GNU Lesser General Public License version 3, as published by
6− * the Free Software Foundation.
7− *
8− * This program is distributed in the hope that it will be useful, but WITHOUT
9− * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10− * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11− * 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−
17−#ifndef DBUSDASHCOMMUNICATORSERVICE_H
18−#define DBUSDASHCOMMUNICATORSERVICE_H
19−
20−#include "unitydbusobject.h"
21−
22−class DBusDashCommunicatorService: public UnityDBusObject
23−{
24− Q_OBJECT
25− Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26−
27−public:
28− DBusDashCommunicatorService(QObject *parent = 0);
29− ~DBusDashCommunicatorService();
30−
31−Q_SIGNALS:
32− void setCurrentScopeRequested(int index, bool animate, bool isSwipe);
33−
34−public Q_SLOTS:
35− Q_SCRIPTABLE void SetCurrentScope(int index, bool animate, bool isSwipe);
36−
37−};
38−
39−#endif // DBUSDASHCOMMUNICATORSERVICE_H
plugins/Unity/DashCommunicator/plugin.cppdeleted−32
@@ -1,32 +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− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17− */
18−
19−#include "plugin.h"
20−#include "dashcommunicator.h"
21−#include "dashcommunicatorservice.h"
22−
23−#include <QDBusConnection>
24−#include <QtQml/qqml.h>
25−
26−void DashCommunicatorPlugin::registerTypes(const char *uri)
27−{
28− // @uri Unity.DashCommunicator
29− Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator"));
30− qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService");
31− qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator");
32−}
plugins/Unity/DashCommunicator/qmldirdeleted−3
@@ -1,3 +0,0 @@
1−module Unity.DashCommunicator
2−plugin DashCommunicator-qml
3−typeinfo DashCommunicator.qmltypes
plugins/Unity/Indicators/CMakeLists.txt+1−2
@@ -44,8 +44,7 @@ target_link_libraries(IndicatorsQml
4444 ${GLIB_LIBRARIES}
4545 ${GIO_LIBRARIES}
4646 ${QMENUMODEL_LDFLAGS}
47+ Qt5::Core Qt5::Qml Qt5::Quick Qt5::DBus
4748)
4849
49−qt5_use_modules(IndicatorsQml Core Qml Quick DBus)
50−
5150add_unity8_plugin(Unity.Indicators 0.1 Unity/Indicators TARGETS IndicatorsQml)
plugins/Unity/Indicators/indicatorsmodel.cpp+13
@@ -103,6 +103,19 @@ void IndicatorsModel::setProfile(const QString &profile)
103103 m_manager->setProfile(profile);
104104}
105105
106+bool IndicatorsModel::light() const
107+{
108+ return m_light;
109+}
110+
111+void IndicatorsModel::setLight(const bool &light)
112+{
113+ if (m_light != light) {
114+ m_light = light;
115+ Q_EMIT lightChanged();
116+ }
117+}
118+
106119/*!
107120 \qmlmethod IndicatorsModel::unload()
108121
plugins/Unity/Indicators/indicatorsmodel.h+9
@@ -35,6 +35,9 @@ class UNITYINDICATORS_EXPORT IndicatorsModel : public QAbstractListModel
3535 Q_PROPERTY(int count READ count NOTIFY countChanged)
3636 Q_PROPERTY(QString profile READ profile WRITE setProfile NOTIFY profileChanged)
3737
38+ // Used for tests
39+ Q_PROPERTY(bool light READ light WRITE setLight NOTIFY lightChanged)
40+
3841public:
3942
4043 IndicatorsModel(QObject *parent=nullptr);
@@ -48,6 +51,9 @@ public:
4851 QString profile() const;
4952 void setProfile(const QString& profile);
5053
54+ bool light() const;
55+ void setLight(const bool &light);
56+
5157 /* QAbstractItemModel */
5258 QHash<int, QByteArray> roleNames() const override;
5359 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -60,6 +66,7 @@ Q_SIGNALS:
6066 void countChanged();
6167 void profileChanged();
6268 void indicatorDataChanged(const QVariant& data);
69+ void lightChanged();
6370
6471private Q_SLOTS:
6572 void onIdentifierChanged();
@@ -74,6 +81,8 @@ private:
7481
7582 void notifyDataChanged(QObject *sender, int role);
7683 int count() const;
84+
85+ bool m_light;
7786};
7887
7988#endif // INDICATORSMODEL_H
plugins/Unity/InputInfo/CMakeLists.txt+1−2
@@ -32,8 +32,7 @@ add_library(InputInfo SHARED
3232target_link_libraries(InputInfo
3333 ${LIBUDEV_LDFLAGS}
3434 ${LIBEVDEV_LDFLAGS}
35+ Qt5::Core Qt5::Qml Qt5::Quick
3536)
3637
37−qt5_use_modules(InputInfo Core Qml Quick)
38−
3938add_unity8_plugin(Unity.InputInfo 0.1 Unity/InputInfo TARGETS InputInfo)
plugins/Unity/Launcher/CMakeLists.txt+4−3
@@ -1,4 +1,3 @@
1−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=11)
21pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
32
43add_definitions(-DSM_BUSNAME=systemBus)
@@ -27,10 +26,13 @@ set(QMLLAUNCHERPLUGIN_SRC
2726 asadapter.cpp
2827 appdrawermodel.cpp
2928 ualwrapper.cpp
29+ xdgwatcher.cpp
3030 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
3131 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
3232 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
3333 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h
34+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
35+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
3436 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
3537 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
3638 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
@@ -46,8 +48,7 @@ target_link_libraries(UnityLauncher-qml
4648 ${GSETTINGS_QT_LDFLAGS}
4749 ${GLIB_LIBRARIES}
4850 ${UAL_LIBRARIES}
51+ Qt5::DBus Qt5::Qml Qt5::Gui Qt5::Concurrent
4952 )
5053
51−qt5_use_modules(UnityLauncher-qml DBus Qml Gui)
52−
5354add_unity8_plugin(Unity.Launcher 0.1 Unity/Launcher TARGETS UnityLauncher-qml)
plugins/Unity/Launcher/appdrawermodel.cpp+144−14
@@ -1,5 +1,6 @@
11/*
22 * Copyright (C) 2016 Canonical, Ltd.
3+ * Copyright (C) 2020 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
@@ -16,23 +17,35 @@
1617
1718#include "appdrawermodel.h"
1819#include "ualwrapper.h"
20+#include "xdgwatcher.h"
1921
2022#include <QDebug>
2123#include <QDateTime>
24+#include <QtConcurrentRun>
25+
26+static std::shared_ptr<LauncherItem> makeSharedLauncherItem(
27+ const QString &appId, const QString &name, const QString &icon, QObject * parent)
28+{
29+ return std::shared_ptr<LauncherItem>(
30+ new LauncherItem(appId, name, icon, parent),
31+ [] (LauncherItem *item) { item->deleteLater(); });
32+}
2233
2334AppDrawerModel::AppDrawerModel(QObject *parent):
24− AppDrawerModelInterface(parent)
35+ AppDrawerModelInterface(parent),
36+ m_ual(new UalWrapper(this)),
37+ m_xdgWatcher(new XdgWatcher(this)),
38+ m_refreshing(false)
2539{
26− Q_FOREACH (const QString &appId, UalWrapper::installedApps()) {
27− UalWrapper::AppInfo info = UalWrapper::getApplicationInfo(appId);
28− if (!info.valid) {
29− qWarning() << "Failed to get app info for app" << appId;
30− continue;
31− }
32− m_list.append(new LauncherItem(appId, info.name, info.icon, this));
33− m_list.last()->setKeywords(info.keywords);
34− }
35− qsrand(QDateTime::currentMSecsSinceEpoch() / 100);
40+ connect(&m_refreshFutureWatcher, &QFutureWatcher<ItemList>::finished,
41+ this, &AppDrawerModel::onRefreshFinished);
42+
43+ // keep this a queued connection as it's coming from another thread.
44+ connect(m_xdgWatcher, &XdgWatcher::appAdded, this, &AppDrawerModel::appAdded, Qt::QueuedConnection);
45+ connect(m_xdgWatcher, &XdgWatcher::appRemoved, this, &AppDrawerModel::appRemoved, Qt::QueuedConnection);
46+ connect(m_xdgWatcher, &XdgWatcher::appInfoChanged, this, &AppDrawerModel::appInfoChanged, Qt::QueuedConnection);
47+
48+ refresh();
3649}
3750
3851int AppDrawerModel::rowCount(const QModelIndex &parent) const
@@ -53,10 +66,127 @@ QVariant AppDrawerModel::data(const QModelIndex &index, int role) const
5366 case RoleKeywords:
5467 return m_list.at(index.row())->keywords();
5568 case RoleUsage:
56− // FIXME: u-a-l needs to provide API for usage stats.
57− // don't forget to drop the qsrand() call in the ctor when dropping this.
58− return qrand();
69+ return m_list.at(index.row())->popularity();
5970 }
6071
6172 return QVariant();
6273}
74+
75+void AppDrawerModel::appAdded(const QString &appId)
76+{
77+ if (m_refreshing)
78+ // Will be replaced by the refresh result anyway.
79+ return;
80+
81+ UalWrapper::AppInfo info = UalWrapper::getApplicationInfo(appId);
82+ if (!info.valid) {
83+ qWarning() << "App added signal received but failed to get app info for app" << appId;
84+ return;
85+ }
86+
87+ beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
88+ auto item = makeSharedLauncherItem(appId, info.name, info.icon, /* parent */ nullptr);
89+ item->setKeywords(info.keywords);
90+ item->setPopularity(info.popularity);
91+ m_list.append(std::move(item));
92+ endInsertRows();
93+}
94+
95+void AppDrawerModel::appRemoved(const QString &appId)
96+{
97+ if (m_refreshing)
98+ // Will be replaced by the refresh result anyway.
99+ return;
100+
101+ int idx = -1;
102+ for (int i = 0; i < m_list.count(); i++) {
103+ if (m_list.at(i)->appId() == appId) {
104+ idx = i;
105+ break;
106+ }
107+ }
108+ if (idx < 0) {
109+ qWarning() << "App removed signal received but app doesn't seem to be in the drawer model";
110+ return;
111+ }
112+ beginRemoveRows(QModelIndex(), idx, idx);
113+ m_list.removeAt(idx);
114+ endRemoveRows();
115+}
116+
117+void AppDrawerModel::appInfoChanged(const QString &appId)
118+{
119+ if (m_refreshing)
120+ // Will be replaced by the refresh result anyway.
121+ return;
122+
123+ std::shared_ptr<LauncherItem> item;
124+ int idx = -1;
125+
126+ for(int i = 0; i < m_list.count(); i++) {
127+ if (m_list.at(i)->appId() == appId) {
128+ item = m_list.at(i);
129+ idx = i;
130+ break;
131+ }
132+ }
133+
134+ if (!item) {
135+ return;
136+ }
137+
138+ UalWrapper::AppInfo info = m_ual->getApplicationInfo(appId);
139+ item->setPopularity(info.popularity);
140+ Q_EMIT dataChanged(index(idx), index(idx), {AppDrawerModelInterface::RoleUsage});
141+}
142+
143+bool AppDrawerModel::refreshing() {
144+ return m_refreshing;
145+}
146+
147+void AppDrawerModel::refresh() {
148+ if (m_refreshing)
149+ return;
150+
151+ m_refreshFutureWatcher.setFuture(QtConcurrent::run([](QThread *thread) {
152+ ItemList list;
153+
154+ Q_FOREACH (const QString &appId, UalWrapper::installedApps()) {
155+ UalWrapper::AppInfo info = UalWrapper::getApplicationInfo(appId);
156+ if (!info.valid) {
157+ qWarning() << "Failed to get app info for app" << appId;
158+ continue;
159+ }
160+ // We don't pass parent in because this may run after the model is destroyed.
161+ // (And, in fact, we can't, because the model is in a diferent thread.)
162+ auto item = makeSharedLauncherItem(appId, info.name, info.icon, /* parent */ nullptr);
163+ item->setKeywords(info.keywords);
164+ item->setPopularity(info.popularity);
165+ item->moveToThread(thread);
166+ list.append(std::move(item));
167+ }
168+
169+ return list;
170+ }, this->thread()));
171+
172+ m_refreshing = true;
173+ Q_EMIT refreshingChanged();
174+}
175+
176+void AppDrawerModel::onRefreshFinished() {
177+ if (m_refreshFutureWatcher.isCanceled())
178+ // This is the result of setting canceled future below.
179+ return;
180+
181+ beginResetModel();
182+
183+ m_list = m_refreshFutureWatcher.result();
184+ // Remove the future & its result, so that future modifications won't
185+ // create a copy.
186+ m_refreshFutureWatcher.setFuture(QFuture<ItemList>());
187+
188+ endResetModel();
189+
190+ m_refreshing = false;
191+ Q_EMIT refreshingChanged();
192+}
plugins/Unity/Launcher/appdrawermodel.h+33−2
@@ -1,5 +1,6 @@
11/*
22 * Copyright (C) 2016 Canonical, Ltd.
3+ * Copyright (C) 2020 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
@@ -14,20 +15,50 @@
1415 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1516 */
1617
17−
18+#include <memory>
19+#include <QFutureWatcher>
1820#include <unity/shell/launcher/AppDrawerModelInterface.h>
1921
2022#include "launcheritem.h"
2123
24+class UalWrapper;
25+class XdgWatcher;
26+
2227class AppDrawerModel: public AppDrawerModelInterface
2328{
2429 Q_OBJECT
30+ // TODO: Add this to AppDrawerModelInterface in unity-api.
31+ // Or, better yet, remove AppDrawerModelInterface from unity-api.
32+ Q_PROPERTY(bool refreshing READ refreshing NOTIFY refreshingChanged)
2533public:
2634 AppDrawerModel(QObject* parent = nullptr);
2735
2836 int rowCount(const QModelIndex &parent) const override;
2937 QVariant data(const QModelIndex &index, int role) const override;
3038
39+ // TODO: add these to AppDrawerModelInterface too.
40+ bool refreshing();
41+ Q_INVOKABLE void refresh();
42+
43+Q_SIGNALS:
44+ void refreshingChanged();
45+
46+private Q_SLOTS:
47+ void appAdded(const QString &appId);
48+ void appRemoved(const QString &appId);
49+ void appInfoChanged(const QString &appId);
50+
51+ void onRefreshFinished();
52+
3153private:
32− QList<LauncherItem*> m_list;
54+ // Using shared_ptr is unavoidable in order to share the refresh result
55+ // from the worker thread safely without a memory leak, in case the model
56+ // is destructed before the worker finishes.
57+ typedef QList<std::shared_ptr<LauncherItem>> ItemList;
58+
59+ ItemList m_list;
60+ UalWrapper *m_ual;
61+ XdgWatcher *m_xdgWatcher;
62+ QFutureWatcher<ItemList> m_refreshFutureWatcher;
63+ bool m_refreshing;
3364};
plugins/Unity/Launcher/launcheritem.cpp+43−7
@@ -35,10 +35,8 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
3535 m_countVisible(false),
3636 m_focused(false),
3737 m_alerting(false),
38− m_surfaceCount(0),
3938 m_quickList(new QuickListModel(this))
4039{
41− Q_ASSERT(parent != nullptr);
4240 QuickListEntry nameAction;
4341 nameAction.setActionId(QStringLiteral("launch_item"));
4442 nameAction.setText(m_name);
@@ -48,11 +46,13 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
4846 QuickListEntry pinningAction;
4947 pinningAction.setActionId(QStringLiteral("pin_item"));
5048 pinningAction.setText(gettext("Pin shortcut"));
49+ pinningAction.setIsPrivate(true);
5150 m_quickList->appendAction(pinningAction);
5251
5352 m_quitAction.setActionId(QStringLiteral("stop_item"));
5453 m_quitAction.setIcon(QStringLiteral("application-exit"));
5554 m_quitAction.setText(gettext("Quit"));
55+ m_quitAction.setIsPrivate(true);
5656}
5757
5858QString LauncherItem::appId() const
@@ -120,6 +120,7 @@ void LauncherItem::setPinned(bool pinned)
120120 QuickListEntry entry;
121121 entry.setActionId(QStringLiteral("pin_item"));
122122 entry.setText(pinned ? gettext("Unpin shortcut") : gettext("Pin shortcut"));
123+ entry.setIsPrivate(true);
123124 m_quickList->updateAction(entry);
124125}
125126
@@ -221,14 +222,49 @@ void LauncherItem::setAlerting(bool alerting)
221222
222223int LauncherItem::surfaceCount() const
223224{
224− return m_surfaceCount;
225+ return m_surfaces.count();
225226}
226227
227−void LauncherItem::setSurfaceCount(int surfaceCount)
228+void LauncherItem::setSurfaces(const QList<QPair<QString, QString> > &surfaces)
228229{
229− if (m_surfaceCount != surfaceCount) {
230− m_surfaceCount = surfaceCount;
231− Q_EMIT surfaceCountChanged(surfaceCount);
230+ if (m_surfaces != surfaces) {
231+ m_surfaces = surfaces;
232+
233+ QList<QuickListEntry> removedEntries;
234+ for (int i = 0; i < m_quickList->rowCount(); ++i) {
235+ QuickListEntry entry = m_quickList->get(i);
236+ if (entry.actionId().startsWith(QStringLiteral("surface_"))) {
237+ removedEntries.append(entry);
238+ }
239+ }
240+ Q_FOREACH (const QuickListEntry &entry, removedEntries) {
241+ m_quickList->removeAction(entry);
242+ }
243+ for (int i = 0; i < surfaces.count(); ++i) {
244+ QuickListEntry entry;
245+ entry.setActionId(QStringLiteral("surface_") + surfaces.at(i).first);
246+ entry.setText(surfaces.at(i).second);
247+ entry.setIsPrivate(true);
248+ if (i == surfaces.count() - 1) {
249+ entry.setHasSeparator(true);
250+ }
251+ m_quickList->insertAction(entry, i + 1);
252+ }
253+
254+ Q_EMIT surfaceCountChanged(m_surfaces.count());
255+ }
256+}
257+
258+uint LauncherItem::popularity() const
259+{
260+ return m_popularity;
261+}
262+
263+void LauncherItem::setPopularity(uint popularity)
264+{
265+ if (m_popularity != popularity) {
266+ m_popularity = popularity;
267+ Q_EMIT popularityChanged(popularity);
232268 }
233269}
234270
plugins/Unity/Launcher/launcheritem.h+6−2
@@ -23,6 +23,7 @@
2323#include "quicklistmodel.h"
2424
2525#include <unity/shell/launcher/LauncherItemInterface.h>
26+#include <unity/shell/application/MirSurfaceInterface.h>
2627
2728class QuickListModel;
2829
@@ -38,6 +39,7 @@ public:
3839 QString name() const override;
3940 QString icon() const override;
4041 QStringList keywords() const override;
42+ uint popularity() const override;
4143 bool pinned() const override;
4244 bool running() const override;
4345 bool recent() const override;
@@ -54,6 +56,7 @@ private:
5456 void setName(const QString &name);
5557 void setIcon(const QString &icon);
5658 void setKeywords(const QStringList &keywords);
59+ void setPopularity(uint popularity);
5760 void setPinned(bool pinned);
5861 void setRunning(bool running);
5962 void setRecent(bool recent);
@@ -62,13 +65,14 @@ private:
6265 void setCountVisible(bool countVisible);
6366 void setFocused(bool focused);
6467 void setAlerting(bool alerting);
65− void setSurfaceCount(int surfaceCount);
68+ void setSurfaces(const QList<QPair<QString, QString >> &surfaces);
6669
6770private:
6871 QString m_appId;
6972 QString m_name;
7073 QString m_icon;
7174 QStringList m_keywords;
75+ uint m_popularity;
7276 bool m_pinned;
7377 bool m_running;
7478 bool m_recent;
@@ -77,7 +81,7 @@ private:
7781 bool m_countVisible;
7882 bool m_focused;
7983 bool m_alerting;
80− int m_surfaceCount;
84+ QList<QPair<QString, QString> > m_surfaces;
8185 QuickListModel *m_quickList;
8286 QuickListEntry m_quitAction;
8387
plugins/Unity/Launcher/launchermodel.cpp+51−20
@@ -23,6 +23,7 @@
2323
2424#include <unity/shell/application/ApplicationInfoInterface.h>
2525#include <unity/shell/application/MirSurfaceListInterface.h>
26+#include <unity/shell/application/MirSurfaceInterface.h>
2627
2728#include <QDesktopServices>
2829#include <QDebug>
@@ -166,6 +167,7 @@ void LauncherModel::pin(const QString &appId, int index)
166167 appInfo.icon,
167168 this);
168169 item->setPinned(true);
170+ item->setPopularity(appInfo.popularity);
169171 m_list.insert(index, item);
170172 endInsertRows();
171173 }
@@ -198,12 +200,26 @@ void LauncherModel::quickListActionInvoked(const QString &appId, int actionIndex
198200 } else {
199201 pin(appId);
200202 }
201− } else if (actionId == QLatin1String("launch_item")) {
203+ } else if (actionId == QStringLiteral("launch_item")) {
202204 QDesktopServices::openUrl(getUrlForAppId(appId));
203− } else if (actionId == QLatin1String("stop_item")) { // Quit
205+ } else if (actionId == QStringLiteral("stop_item")) { // Quit
204206 if (m_appManager) {
205207 m_appManager->stopApplication(appId);
206208 }
209+ } else if (actionId.startsWith(QStringLiteral("surface_"))){
210+ ApplicationInfoInterface *appInfo = m_appManager->findApplication(appId);
211+ if (appInfo) {
212+ for (int i = 0; i < appInfo->surfaceList()->count(); ++i) {
213+ MirSurfaceInterface *iface = appInfo->surfaceList()->get(i);
214+ QString id = actionId;
215+ id.remove(QRegExp("^surface_"));
216+ if (id == iface->persistentId()) {
217+ iface->activate();
218+ }
219+ }
220+ } else {
221+ qWarning() << "App for" << appId << "not found in launcher. Cannot invoke quicklist action";
222+ }
207223 // Nope, we don't know this action, let the backend forward it to the application
208224 } else {
209225 // TODO: forward quicklist action to app, possibly via m_dbusIface
@@ -214,7 +230,6 @@ void LauncherModel::quickListActionInvoked(const QString &appId, int actionIndex
214230void LauncherModel::setUser(const QString &username)
215231{
216232 Q_UNUSED(username)
217− qWarning() << "This backend doesn't support multiple users";
218233}
219234
220235QString LauncherModel::getUrlForAppId(const QString &appId) const
@@ -506,11 +521,6 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
506521 return;
507522 }
508523
509− if (app->appId() == QLatin1String("unity8-dash")) {
510− // Not adding the dash app
511− return;
512− }
513−
514524 const int itemIndex = findApplication(app->appId());
515525 if (itemIndex != -1) {
516526 LauncherItem *item = m_list.at(itemIndex);
@@ -518,40 +528,61 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
518528 item->setRecent(true);
519529 Q_EMIT dataChanged(index(itemIndex), index(itemIndex), {RoleRecent});
520530 }
521− if (item->surfaceCount() != app->surfaceCount()) {
522− item->setSurfaceCount(app->surfaceCount());
523− Q_EMIT dataChanged(index(itemIndex), index(itemIndex), {RoleSurfaceCount});
524− }
525−
526531 item->setRunning(true);
527532 } else {
528533 LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString(), this);
529534 item->setRecent(true);
530535 item->setRunning(true);
531536 item->setFocused(app->focused());
532− item->setSurfaceCount(app->surfaceCount());
533537 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
534538 m_list.append(item);
535539 endInsertRows();
536540 }
537− connect(app, &ApplicationInfoInterface::surfaceCountChanged, this, &LauncherModel::applicationSurfaceCountChanged);
541+ connect(app, &ApplicationInfoInterface::surfaceCountChanged, this, &LauncherModel::updateSurfaceList);
538542 m_asAdapter->syncItems(m_list);
539543 Q_EMIT dataChanged(index(itemIndex), index(itemIndex), {RoleRunning});
540544}
541545
542−void LauncherModel::applicationSurfaceCountChanged(int count)
546+void LauncherModel::updateSurfaceList()
543547{
544548 ApplicationInfoInterface *app = static_cast<ApplicationInfoInterface*>(sender());
549+ updateSurfaceListForApp(app);
550+}
551+
552+void LauncherModel::updateSurfaceListForSurface()
553+{
554+ MirSurfaceInterface *iface = static_cast<MirSurfaceInterface*>(sender());
555+ ApplicationInfoInterface* app = m_appManager->findApplication(iface->appId());
556+ if (!app) {
557+ return;
558+ }
559+ updateSurfaceListForApp(app);
560+}
561+
562+void LauncherModel::updateSurfaceListForApp(ApplicationInfoInterface* app)
563+{
545564 int idx = findApplication(app->appId());
546565 if (idx < 0) {
547566 qWarning() << "Received a surface count changed event from an app that's not in the Launcher model";
548567 return;
549568 }
550569 LauncherItem *item = m_list.at(idx);
551− if (item->surfaceCount() != count) {
552− item->setSurfaceCount(count);
553− Q_EMIT dataChanged(index(idx), index(idx), {RoleSurfaceCount});
570+ QList<QPair<QString, QString> > surfaces;
571+ for (int i = 0; i < app->surfaceList()->count(); ++i) {
572+ MirSurfaceInterface* iface = app->surfaceList()->get(i);
573+ if (iface->type() == Mir::NormalType || iface->type() == Mir::DialogType) {
574+ // Avoid duplicate connections, so let's just disconnect first to be sure
575+ disconnect(iface, &MirSurfaceInterface::nameChanged, this, &LauncherModel::updateSurfaceListForSurface);
576+ connect(iface, &MirSurfaceInterface::nameChanged, this, &LauncherModel::updateSurfaceListForSurface);
577+ QString name = iface->name();
578+ if (name.isEmpty()) {
579+ name = app->name();
580+ }
581+ surfaces.append({iface->persistentId(), name});
582+ }
554583 }
584+ item->setSurfaces(surfaces);
585+ Q_EMIT dataChanged(index(idx), index(idx), {RoleSurfaceCount});
555586}
556587
557588void LauncherModel::applicationRemoved(const QModelIndex &parent, int row)
@@ -572,7 +603,7 @@ void LauncherModel::applicationRemoved(const QModelIndex &parent, int row)
572603 return;
573604 }
574605
575− disconnect(app, &ApplicationInfoInterface::surfaceCountChanged, this, &LauncherModel::applicationSurfaceCountChanged);
606+ disconnect(app, &ApplicationInfoInterface::surfaceCountChanged, this, &LauncherModel::updateSurfaceList);
576607
577608 LauncherItem * item = m_list.at(appIndex);
578609
plugins/Unity/Launcher/launchermodel.h+3−1
@@ -75,7 +75,9 @@ private Q_SLOTS:
7575 void applicationAdded(const QModelIndex &parent, int row);
7676 void applicationRemoved(const QModelIndex &parent, int row);
7777 void focusedAppIdChanged();
78− void applicationSurfaceCountChanged(int);
78+ void updateSurfaceList();
79+ void updateSurfaceListForApp(ApplicationInfoInterface *app);
80+ void updateSurfaceListForSurface();
7981
8082private:
8183 QList<LauncherItem*> m_list;
plugins/Unity/Launcher/quicklistentry.cpp+11
@@ -20,6 +20,7 @@
2020
2121QuickListEntry::QuickListEntry()
2222 : m_hasSeparator(false)
23+ , m_isPrivate(false)
2324{
2425}
2526
@@ -72,3 +73,13 @@ bool QuickListEntry::operator==(const QuickListEntry &other)
7273{
7374 return !other.actionId().isEmpty() && other.actionId() == m_actionId;
7475}
76+
77+bool QuickListEntry::isPrivate() const
78+{
79+ return m_isPrivate;
80+}
81+
82+void QuickListEntry::setIsPrivate(bool isPrivate)
83+{
84+ m_isPrivate = isPrivate;
85+}
plugins/Unity/Launcher/quicklistentry.h+4
@@ -42,11 +42,15 @@ public:
4242
4343 bool operator==(const QuickListEntry & other);
4444
45+ bool isPrivate() const;
46+ void setIsPrivate(bool isPrivate);
47+
4548private:
4649 QString m_actionId;
4750 QString m_text;
4851 QString m_icon;
4952 bool m_hasSeparator;
53+ bool m_isPrivate;
5054};
5155
5256#endif // QUICKLISTENTRY
plugins/Unity/Launcher/quicklistmodel.cpp+9
@@ -37,6 +37,13 @@ void QuickListModel::appendAction(const QuickListEntry &entry)
3737 endInsertRows();
3838}
3939
40+void QuickListModel::insertAction(const QuickListEntry &entry, int index)
41+{
42+ beginInsertRows(QModelIndex(), index, index);
43+ m_list.insert(index, entry);
44+ endInsertRows();
45+}
46+
4047void QuickListModel::updateAction(const QuickListEntry &entry)
4148{
4249 for (int i = 0; i < m_list.count(); ++i) {
@@ -81,6 +88,8 @@ QVariant QuickListModel::data(const QModelIndex &index, int role) const
8188 return m_list.at(index.row()).clickable();
8289 case RoleHasSeparator:
8390 return m_list.at(index.row()).hasSeparator();
91+ case RoleIsPrivate:
92+ return m_list.at(index.row()).isPrivate();
8493 }
8594 return QVariant();
8695}
plugins/Unity/Launcher/quicklistmodel.h+1
@@ -36,6 +36,7 @@ public:
3636 ~QuickListModel();
3737
3838 void appendAction(const QuickListEntry &entry);
39+ void insertAction(const QuickListEntry &entry, int index);
3940
4041 /**
4142 * @brief Update an existing action
plugins/Unity/Launcher/ualwrapper.cpp+3−2
@@ -24,7 +24,6 @@ using namespace ubuntu::app_launch;
2424UalWrapper::UalWrapper(QObject *parent):
2525 QObject(parent)
2626{
27−
2827}
2928
3029QStringList UalWrapper::installedApps()
@@ -39,7 +38,7 @@ QStringList UalWrapper::installedApps()
3938 }
4039 }
4140 } catch (const std::runtime_error &e) {
42− qWarning() << "ubuntu-all-launch threw an exception listing apps:" << e.what();
41+ qWarning() << "ubuntu-app-launch threw an exception listing apps:" << e.what();
4342 }
4443
4544 return appIds;
@@ -59,11 +58,13 @@ UalWrapper::AppInfo UalWrapper::getApplicationInfo(const QString &appId)
5958 std::shared_ptr<Application> ualApp;
6059 ualApp = Application::create(ualAppId, Registry::getDefault());
6160
61+ info.appId = appId;
6262 info.name = QString::fromStdString(ualApp->info()->name());
6363 info.icon = QString::fromStdString(ualApp->info()->iconPath());
6464 for (const std::string &keyword : ualApp->info()->keywords().value()) {
6565 info.keywords << QString::fromStdString(keyword);
6666 }
67+ //info.popularity = ualApp->info()->popularity();
6768 info.valid = true;
6869 } catch (const std::runtime_error &e) {
6970 qWarning() << "ubuntu-app-launch threw an exception getting app info for appId:" << appId << ":" << e.what();
plugins/Unity/Launcher/ualwrapper.h+2−1
@@ -21,15 +21,16 @@ class UalWrapper: public QObject
2121 Q_OBJECT
2222public:
2323 struct AppInfo {
24+ QString appId;
2425 bool valid = false;
2526 QString name;
2627 QString icon;
2728 QStringList keywords;
29+ uint popularity = 0;
2830 };
2931
3032 UalWrapper(QObject* parent = nullptr);
3133
3234 static QStringList installedApps();
3335 static AppInfo getApplicationInfo(const QString &appId);
34−
3536};
plugins/Unity/Launcher/xdgwatcher.cppnew file+129
@@ -0,0 +1,129 @@
1+/*
2+ * Copyright (C) 2019 UBports Foundation
3+ * Author(s): Marius Gripsgard <marius@ubports.com>
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+
18+#include "xdgwatcher.h"
19+
20+#include <QDebug>
21+#include <QDir>
22+#include <QFile>
23+#include <QStandardPaths>
24+#include <QTextStream>
25+
26+XdgWatcher::XdgWatcher(QObject* parent)
27+ : QObject(parent),
28+ m_watcher(new QFileSystemWatcher(this))
29+{
30+ connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &XdgWatcher::onDirectoryChanged);
31+ connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &XdgWatcher::onFileChanged);
32+
33+ const auto paths = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
34+ for (const auto &path: paths) {
35+ const auto qdir = QDir(path);
36+ if (!qdir.exists()) {
37+ continue;
38+ }
39+
40+ // Add the path itself to watch for newly added apps
41+ m_watcher->addPath(path);
42+
43+ // Add watcher for eatch app to watch for changes
44+ const auto files = qdir.entryInfoList(QDir::Files);
45+ for (const auto &file: files) {
46+ if (file.suffix() == "desktop") {
47+ const auto path = file.absoluteFilePath();
48+ m_watcher->addPath(path);
49+ m_registry.insert(path, getAppId(file));
50+ }
51+ }
52+ }
53+}
54+
55+// "Ubuntu style" appID is filename without versionNumber after last "_"
56+const QString XdgWatcher::stripAppIdVersion(const QString rawAppID) const {
57+ auto appIdComponents = rawAppID.split("_");
58+ appIdComponents.removeLast();
59+ return appIdComponents.join("_");
60+}
61+
62+// Standard appID see:
63+// https://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id
64+const QString XdgWatcher::toStandardAppId(const QFileInfo fileInfo) const {
65+ const auto paths = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
66+ for (const auto &path: paths) {
67+ if (fileInfo.absolutePath() == path) {
68+ break;
69+ }
70+ if (fileInfo.absolutePath().contains(path)) {
71+ auto fileStr = fileInfo.absoluteFilePath();
72+ fileStr.replace(path, "");
73+ fileStr.replace("/", "-");
74+ fileStr.replace(".desktop", "");
75+ return fileStr;
76+ }
77+ }
78+ return fileInfo.completeBaseName();
79+}
80+
81+const QString XdgWatcher::getAppId(const QFileInfo fileInfo) const {
82+ // We need to open the file to check if its and Ual application
83+ // as we cant just rely on the app name as "normal" apps can also
84+ // contain 3 _ causing us to belive its an ubuntu app
85+ // Example kde_org_kate would become kde_org
86+ QFile qFile(fileInfo.absoluteFilePath());
87+ qFile.open(QIODevice::ReadOnly);
88+ QTextStream fileStream(&qFile);
89+ QString line;
90+ while (fileStream.readLineInto(&line)) {
91+ if (line.startsWith("X-Ubuntu-Application-ID=")) {
92+ auto rawAppID = line.replace("X-Ubuntu-Application-ID=", "");
93+ qFile.close();
94+ return stripAppIdVersion(rawAppID);
95+ }
96+ }
97+ qFile.close();
98+
99+ // If it's not an "Ubuntu" appID, we follow freedesktop standard
100+ return toStandardAppId(fileInfo);
101+}
102+
103+// Watch for newly added apps
104+void XdgWatcher::onDirectoryChanged(const QString &path) {
105+ const auto files = QDir(path).entryInfoList(QDir::Files);
106+ const auto watchedFiles = m_watcher->files();
107+ for (const auto &file: files) {
108+ const auto appPath = file.absoluteFilePath();
109+ if (file.suffix() == "desktop" && !watchedFiles.contains(appPath)) {
110+ m_watcher->addPath(appPath);
111+
112+ const auto appId = getAppId(file);
113+ m_registry.insert(appPath, appId);
114+ Q_EMIT appAdded(appId);
115+ }
116+ }
117+}
118+
119+void XdgWatcher::onFileChanged(const QString &path) {
120+ QFileInfo file(path);
121+ if (file.exists()) {
122+ // The file exists, this must be an modify event
123+ Q_EMIT appInfoChanged(m_registry.value(path));
124+ } else {
125+ // File does not exist, assume this is an remove event.
126+ // onDirectoryChanged will handle rename event
127+ Q_EMIT appRemoved(m_registry.take(path));
128+ }
129+}
plugins/Unity/Launcher/xdgwatcher.hnew file+46
@@ -0,0 +1,46 @@
1+/*
2+ * Copyright (C) 2019 UBports Foundation
3+ * Author(s): Marius Gripsgard <marius@ubports.com>
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+
18+#include <QFileSystemWatcher>
19+#include <QHash>
20+#include <QFileInfo>
21+
22+class QFileInfo;
23+
24+class XdgWatcher: public QObject
25+{
26+ Q_OBJECT
27+public:
28+ XdgWatcher(QObject* parent = nullptr);
29+
30+Q_SIGNALS:
31+ void appAdded(const QString &appId);
32+ void appRemoved(const QString &appId);
33+ void appInfoChanged(const QString &appId);
34+
35+private Q_SLOTS:
36+ void onDirectoryChanged(const QString &path);
37+ void onFileChanged(const QString &path);
38+
39+private:
40+ const QString toStandardAppId(const QFileInfo fileInfo) const;
41+ const QString getAppId(const QFileInfo file) const;
42+ const QString stripAppIdVersion(const QString rawAppID) const;
43+
44+ QFileSystemWatcher* m_watcher;
45+ QHash<const QString, QString> m_registry;
46+};
plugins/Unity/Platform/CMakeLists.txt+1−1
@@ -6,6 +6,6 @@ set(platformplugin_SRCS
66
77add_library(Platform-qml SHARED ${platformplugin_SRCS})
88
9−qt5_use_modules(Platform-qml DBus Qml)
9+target_link_libraries(Platform-qml Qt5::DBus Qt5::Qml)
1010
1111add_unity8_plugin(Unity.Platform 1.0 Unity/Platform TARGETS Platform-qml)
plugins/Unity/Platform/platform.cpp+16−2
@@ -17,9 +17,11 @@
1717#include "platform.h"
1818
1919#include <QDBusConnection>
20+#include <QSet>
21+#include <QString>
2022
2123Platform::Platform(QObject *parent)
22− : QObject(parent)
24+ : QObject(parent), m_isPC(true), m_isMultiSession(true)
2325{
2426 QMetaObject::invokeMethod(this, "init");
2527}
@@ -31,8 +33,20 @@ void Platform::init()
3133 QDBusInterface seatIface("org.freedesktop.login1", "/org/freedesktop/login1/seat/self", "org.freedesktop.login1.Seat",
3234 QDBusConnection::systemBus(), this);
3335
36+ // From the source at https://cgit.freedesktop.org/systemd/systemd/tree/src/hostname/hostnamed.c#n130
37+ // "vm\0"
38+ // "container\0"
39+ // "desktop\0"
40+ // "laptop\0"
41+ // "server\0"
42+ // "tablet\0"
43+ // "handset\0"
44+ // "watch\0"
45+ // "embedded\0",
3446 m_chassis = iface.property("Chassis").toString();
35− m_isPC = (m_chassis == "desktop" || m_chassis == "laptop" || m_chassis == "server");
47+
48+ // A PC is not a handset, tablet or watch.
49+ m_isPC = !QSet<QString>{"handset", "tablet", "watch"}.contains(m_chassis);
3650 m_isMultiSession = seatIface.property("CanMultiSession").toBool() && seatIface.property("CanGraphical").toBool();
3751}
3852
plugins/Unity/Session/CMakeLists.txt+1−1
@@ -18,8 +18,8 @@ add_library(UnitySession-qml MODULE
1818 ${QMLSESSIONPLUGIN_SRC}
1919 )
2020
21−qt5_use_modules(UnitySession-qml DBus Qml)
2221target_link_libraries(UnitySession-qml
22+ Qt5::DBus Qt5::Qml
2323 unity8-private
2424 ${GIO_LDFLAGS}
2525 ${GLIB_LIBRARIES}
plugins/Unity/Session/dbusunitysessionservice.cpp+75−4
@@ -18,6 +18,7 @@
1818#include "dbusunitysessionservice.h"
1919
2020// system
21+#include <grp.h>
2122#include <sys/types.h>
2223#include <unistd.h>
2324#include <pwd.h>
@@ -211,6 +212,23 @@ public:
211212 QDBusConnection::SM_BUSNAME().asyncCall(msg);
212213 }
213214
215+ bool isUserInGroup(const QString &user, const QString &groupName) const
216+ {
217+ auto group = getgrnam(groupName.toUtf8().data());
218+
219+ if (group && group->gr_mem)
220+ {
221+ for (int i = 0; group->gr_mem[i]; ++i)
222+ {
223+ if (g_strcmp0(group->gr_mem[i], user.toUtf8().data()) == 0) {
224+ return true;
225+ }
226+ }
227+ }
228+
229+ return false;
230+ }
231+
214232private Q_SLOTS:
215233 void onPropertiesChanged(const QString &iface, const QVariantMap &changedProps, const QStringList &invalidatedProps)
216234 {
@@ -297,7 +315,13 @@ bool DBusUnitySessionService::CanShutdown() const
297315
298316bool DBusUnitySessionService::CanLock() const
299317{
300− return true; // FIXME
318+ auto user = UserName();
319+ if (user.startsWith(QStringLiteral("guest-")) ||
320+ d->isUserInGroup(user, QStringLiteral("nopasswdlogin"))) {
321+ return false;
322+ } else {
323+ return true;
324+ }
301325}
302326
303327QString DBusUnitySessionService::UserName() const
@@ -335,8 +359,10 @@ void DBusUnitySessionService::PromptLock()
335359 // Prompt as in quick. No locking animation needed. Usually used by
336360 // indicator-session in combination with a switch to greeter or other
337361 // user session.
338− Q_EMIT LockRequested();
339− Q_EMIT lockRequested();
362+ if (CanLock()) {
363+ Q_EMIT LockRequested();
364+ Q_EMIT lockRequested();
365+ }
340366}
341367
342368void DBusUnitySessionService::Lock()
@@ -468,11 +494,56 @@ void performAsyncUnityCall(const QString &method)
468494
469495
470496DBusGnomeSessionManagerWrapper::DBusGnomeSessionManagerWrapper()
497+ : UnityDBusObject(QStringLiteral("/org/gnome/SessionManager"), QStringLiteral("org.gnome.SessionManager"))
498+{
499+}
500+
501+void DBusGnomeSessionManagerWrapper::Logout(quint32 mode)
502+{
503+ auto call = QStringLiteral("RequestLogout");
504+
505+ // These modes are documented as bitwise flags, not an enum, even though
506+ // they only ever seem to be used as enums.
507+
508+ if (mode & 1) // without dialog
509+ call = QStringLiteral("Logout");
510+ if (mode & 2) // without dialog, ignoring inhibitors (which we don't have)
511+ call = QStringLiteral("Logout");
512+
513+ performAsyncUnityCall(call);
514+}
515+
516+void DBusGnomeSessionManagerWrapper::Reboot()
517+{
518+ // GNOME's Reboot means with dialog (they use Request differently than us).
519+ performAsyncUnityCall(QStringLiteral("RequestReboot"));
520+}
521+
522+void DBusGnomeSessionManagerWrapper::RequestReboot()
523+{
524+ // GNOME's RequestReboot means no dialog (they use Request differently than us).
525+ performAsyncUnityCall(QStringLiteral("Reboot"));
526+}
527+
528+void DBusGnomeSessionManagerWrapper::RequestShutdown()
529+{
530+ // GNOME's RequestShutdown means no dialog (they use Request differently than us).
531+ performAsyncUnityCall(QStringLiteral("Shutdown"));
532+}
533+
534+void DBusGnomeSessionManagerWrapper::Shutdown()
535+{
536+ // GNOME's Shutdown means with dialog (they use Request differently than us).
537+ performAsyncUnityCall(QStringLiteral("RequestShutdown"));
538+}
539+
540+
541+DBusGnomeSessionManagerDialogWrapper::DBusGnomeSessionManagerDialogWrapper()
471542 : UnityDBusObject(QStringLiteral("/org/gnome/SessionManager/EndSessionDialog"), QStringLiteral("com.canonical.Unity"))
472543{
473544}
474545
475−void DBusGnomeSessionManagerWrapper::Open(const unsigned type, const unsigned arg_1, const unsigned max_wait, const QList<QDBusObjectPath> &inhibitors)
546+void DBusGnomeSessionManagerDialogWrapper::Open(const unsigned type, const unsigned arg_1, const unsigned max_wait, const QList<QDBusObjectPath> &inhibitors)
476547{
477548 Q_UNUSED(arg_1);
478549 Q_UNUSED(max_wait);
plugins/Unity/Session/dbusunitysessionservice.h+18−4
@@ -270,17 +270,31 @@ private:
270270class DBusGnomeSessionManagerWrapper : public UnityDBusObject
271271{
272272 Q_OBJECT
273− Q_CLASSINFO("D-Bus Interface", "org.gnome.SessionManager.EndSessionDialog")
273+ Q_CLASSINFO("D-Bus Interface", "org.gnome.SessionManager")
274274
275275public:
276276 DBusGnomeSessionManagerWrapper();
277277 ~DBusGnomeSessionManagerWrapper() = default;
278278
279279public Q_SLOTS:
280− Q_SCRIPTABLE void Open(const unsigned int type, const unsigned int arg_1, const unsigned int max_wait, const QList<QDBusObjectPath> &inhibitors);
280+ Q_SCRIPTABLE void Logout(quint32 mode);
281+ Q_SCRIPTABLE void Reboot();
282+ Q_SCRIPTABLE void RequestReboot();
283+ Q_SCRIPTABLE void RequestShutdown();
284+ Q_SCRIPTABLE void Shutdown();
285+};
281286
282−private:
283− void performAsyncCall(const QString &method);
287+class DBusGnomeSessionManagerDialogWrapper : public UnityDBusObject
288+{
289+ Q_OBJECT
290+ Q_CLASSINFO("D-Bus Interface", "org.gnome.SessionManager.EndSessionDialog")
291+
292+public:
293+ DBusGnomeSessionManagerDialogWrapper();
294+ ~DBusGnomeSessionManagerDialogWrapper() = default;
295+
296+public Q_SLOTS:
297+ Q_SCRIPTABLE void Open(const unsigned int type, const unsigned int arg_1, const unsigned int max_wait, const QList<QDBusObjectPath> &inhibitors);
284298};
285299
286300class DBusGnomeScreensaverWrapper: public UnityDBusObject
plugins/Unity/Session/plugin.cpp+1
@@ -26,6 +26,7 @@
2626
2727static QObject *dbusunitysessionservice_provider(QQmlEngine */*engine*/, QJSEngine */*jsEngine*/)
2828{
29+ new DBusGnomeSessionManagerDialogWrapper();
2930 new DBusGnomeSessionManagerWrapper();
3031 new DBusGnomeScreensaverWrapper();
3132 new DBusScreensaverWrapper();
plugins/Utils/CMakeLists.txt+6−4
@@ -7,7 +7,6 @@ include_directories(
77 SYSTEM
88 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
99 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
10− ${GIO_INCLUDE_DIRS}
1110)
1211
1312set(QMLPLUGIN_SRC
@@ -34,6 +33,9 @@ set(QMLPLUGIN_SRC
3433 deviceconfigparser.cpp
3534 globalfunctions.cpp
3635 URLDispatcher.cpp
36+ tabfocusfence.cpp
37+ expressionfiltermodel.cpp
38+ quicklistproxymodel.cpp
3739 plugin.cpp
3840 )
3941
@@ -41,7 +43,9 @@ add_library(Utils-qml SHARED
4143 ${QMLPLUGIN_SRC}
4244 )
4345
44−target_link_libraries(Utils-qml ${GIO_LDFLAGS})
46+target_link_libraries(Utils-qml
47+ Qt5::Qml Qt5::Quick Qt5::DBus Qt5::Network Qt5::Gui Qt5::Sql Qt5::Concurrent
48+ )
4549
4650# Because this is an internal support library, we want
4751# to expose all symbols in it. Consider changing this
@@ -49,6 +53,4 @@ target_link_libraries(Utils-qml ${GIO_LDFLAGS})
4953# files directly in targets.
5054set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
5155
52−qt5_use_modules(Utils-qml Qml Quick DBus Network Gui Sql Concurrent)
53−
5456add_unity8_plugin(Utils 0.1 Utils TARGETS Utils-qml)
plugins/Utils/URLDispatcher.cpp+5−2
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2016-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
@@ -17,6 +17,7 @@
1717#include "URLDispatcher.h"
1818
1919#include <QDBusConnection>
20+#include <QDebug>
2021
2122class URLDispatcherInterface : public QObject
2223{
@@ -63,7 +64,9 @@ void URLDispatcher::setActive(bool value)
6364 connection.registerObject(QStringLiteral("/com/canonical/URLDispatcher"),
6465 dispatcher,
6566 QDBusConnection::ExportScriptableContents);
66− connection.registerService(QStringLiteral("com.canonical.URLDispatcher"));
67+ if (!connection.registerService(QStringLiteral("com.canonical.URLDispatcher"))) {
68+ qWarning() << "Unable to register DBus service com.canonical.URLDispatcher";
69+ }
6770 m_dispatcher = dispatcher;
6871 } else {
6972 connection.unregisterService(QStringLiteral("com.canonical.URLDispatcher"));
plugins/Utils/WindowInputMonitor.cpp+3
@@ -73,6 +73,9 @@ void WindowInputMonitor::update(QEvent *event)
7373 && m_windowLastTouchedTimer->elapsed() >= msecsWithoutTouches) {
7474 m_pressedHomeKey = keyEvent->key();
7575 m_activationTimer->start();
76+ } else if (m_pressedHomeKey != 0 && !m_homeKeys.contains(keyEvent->key())) {
77+ // something else came in... cancel activation
78+ m_activationTimer->stop();
7679 }
7780
7881 } else if (event->type() == QEvent::KeyRelease) {
plugins/Utils/appdrawerproxymodel.cpp+4−4
@@ -43,8 +43,8 @@ void AppDrawerProxyModel::setSource(QAbstractItemModel *source)
4343 m_source = source;
4444 setSourceModel(m_source);
4545 setSortRole(m_sortBy == SortByAToZ ? AppDrawerModelInterface::RoleName : AppDrawerModelInterface::RoleUsage);
46− connect(m_source, &QAbstractItemModel::rowsRemoved, this, &AppDrawerProxyModel::invalidateFilter);
47− connect(m_source, &QAbstractItemModel::rowsInserted, this, &AppDrawerProxyModel::invalidateFilter);
46+ connect(m_source, &QAbstractItemModel::rowsRemoved, this, &AppDrawerProxyModel::invalidate);
47+ connect(m_source, &QAbstractItemModel::rowsInserted, this, &AppDrawerProxyModel::invalidate);
4848 Q_EMIT sourceChanged();
4949 }
5050}
@@ -158,7 +158,7 @@ bool AppDrawerProxyModel::filterAcceptsRow(int source_row, const QModelIndex &so
158158 allWords.prepend(m_source->data(m_source->index(source_row, 0), AppDrawerModelInterface::RoleName).toString());
159159 bool found = false;
160160 Q_FOREACH (const QString &currentWord, allWords) {
161− if (currentWord.startsWith(m_filterString, Qt::CaseInsensitive)) {
161+ if (currentWord.contains(m_filterString, Qt::CaseInsensitive)) {
162162 found = true;
163163 break;
164164 }
@@ -185,5 +185,5 @@ QString AppDrawerProxyModel::appId(int index) const
185185 return adpm->appId(sourceIndex.row());
186186 }
187187 }
188− return nullptr;
188+ return QString();
189189}
plugins/Utils/deviceconfigparser.cpp+18
@@ -116,6 +116,24 @@ QString DeviceConfigParser::category() const
116116 return value;
117117}
118118
119+bool DeviceConfigParser::supportsMultiColorLed() const
120+{
121+ return readBoolFromConfig("SupportsMultiColorLed", true);
122+}
123+
124+bool DeviceConfigParser::readBoolFromConfig(const QString &key, bool defaultValue) const
125+{
126+ m_config->beginGroup(m_name);
127+
128+ bool ret = defaultValue;
129+ if (m_config->contains(key)) {
130+ ret = m_config->value(key).toBool();
131+ }
132+
133+ m_config->endGroup();
134+ return ret;
135+}
136+
119137QStringList DeviceConfigParser::readOrientationsFromConfig(const QString &key) const
120138{
121139 m_config->beginGroup(m_name);
plugins/Utils/deviceconfigparser.h+3
@@ -33,6 +33,7 @@ class DeviceConfigParser: public QObject
3333 Q_PROPERTY(Qt::ScreenOrientation portraitOrientation READ portraitOrientation NOTIFY changed)
3434 Q_PROPERTY(Qt::ScreenOrientation invertedPortraitOrientation READ invertedPortraitOrientation NOTIFY changed)
3535 Q_PROPERTY(QString category READ category NOTIFY changed)
36+ Q_PROPERTY(bool supportsMultiColorLed READ supportsMultiColorLed NOTIFY changed)
3637
3738public:
3839 DeviceConfigParser(QObject *parent = nullptr);
@@ -47,6 +48,7 @@ public:
4748 Qt::ScreenOrientation portraitOrientation() const;
4849 Qt::ScreenOrientation invertedPortraitOrientation() const;
4950 QString category() const;
51+ bool supportsMultiColorLed() const;
5052
5153Q_SIGNALS:
5254 void changed();
@@ -58,6 +60,7 @@ private:
5860 QStringList readOrientationsFromConfig(const QString &key) const;
5961 QString readOrientationFromConfig(const QString &key) const;
6062 Qt::ScreenOrientation stringToOrientation(const QString &orientationString, Qt::ScreenOrientation defaultValue) const;
63+ bool readBoolFromConfig(const QString &key, bool defaultValue) const;
6164};
6265
6366#endif
plugins/Utils/expressionfiltermodel.cppnew file+49
@@ -0,0 +1,49 @@
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+#include "expressionfiltermodel.h"
18+
19+ExpressionFilterModel::ExpressionFilterModel(QObject *parent)
20+ : UnitySortFilterProxyModelQML(parent)
21+{
22+}
23+
24+QJSValue ExpressionFilterModel::matchExpression() const
25+{
26+ return m_matchExpression;
27+}
28+
29+void ExpressionFilterModel::setMatchExpression(const QJSValue &value)
30+{
31+ m_matchExpression = value;
32+ invalidateFilter();
33+}
34+
35+bool
36+ExpressionFilterModel::filterAcceptsRow(int sourceRow,
37+ const QModelIndex &sourceParent) const
38+{
39+ if (m_matchExpression.isCallable()) {
40+ QJSValueList args;
41+ args << sourceRow;
42+ QJSValue ret = m_matchExpression.call(args);
43+ if (ret.isBool()) {
44+ return ret.toBool();
45+ }
46+ }
47+
48+ return UnitySortFilterProxyModelQML::filterAcceptsRow(sourceRow, sourceParent);
49+}
plugins/Utils/expressionfiltermodel.hnew file+42
@@ -0,0 +1,42 @@
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+#ifndef EXPRESSIONFILTERMODEL_H
18+#define EXPRESSIONFILTERMODEL_H
19+
20+#include "unitysortfilterproxymodelqml.h"
21+#include <QJSValue>
22+
23+class ExpressionFilterModel : public UnitySortFilterProxyModelQML
24+{
25+ Q_OBJECT
26+ Q_PROPERTY(QJSValue matchExpression READ matchExpression WRITE setMatchExpression NOTIFY matchExpressionChanged)
27+public:
28+ explicit ExpressionFilterModel(QObject *parent = 0);
29+
30+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
31+
32+ QJSValue matchExpression() const;
33+ void setMatchExpression(const QJSValue& value);
34+
35+Q_SIGNALS:
36+ void matchExpressionChanged();
37+
38+private:
39+ mutable QJSValue m_matchExpression;
40+};
41+
42+#endif // EXPRESSIONFILTERMODEL_H
plugins/Utils/plugin.cpp+7−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012-2015 Canonical, Ltd.
2+ * Copyright (C) 2012-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
@@ -40,6 +40,9 @@
4040#include "globalfunctions.h"
4141#include "URLDispatcher.h"
4242#include "appdrawerproxymodel.h"
43+#include "tabfocusfence.h"
44+#include "expressionfiltermodel.h"
45+#include "quicklistproxymodel.h"
4346
4447static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
4548{
@@ -84,4 +87,7 @@ void UtilsPlugin::registerTypes(const char *uri)
8487 qmlRegisterSingletonType<GlobalFunctions>(uri, 0, 1, "Functions", createGlobalFunctions);
8588 qmlRegisterType<URLDispatcher>(uri, 0, 1, "URLDispatcher");
8689 qmlRegisterType<AppDrawerProxyModel>(uri, 0, 1, "AppDrawerProxyModel");
90+ qmlRegisterType<TabFocusFenceItem>(uri, 0, 1, "TabFocusFence");
91+ qmlRegisterType<ExpressionFilterModel>(uri, 0, 1, "ExpressionFilterModel");
92+ qmlRegisterType<QuickListProxyModel>(uri, 0, 1, "QuickListProxyModel");
8793}
plugins/Utils/quicklistproxymodel.cppnew file+72
@@ -0,0 +1,72 @@
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+#include "quicklistproxymodel.h"
18+
19+#include <QDebug>
20+
21+QuickListProxyModel::QuickListProxyModel(QObject *parent):
22+ QSortFilterProxyModel(parent)
23+{
24+ connect(this, &QAbstractListModel::rowsInserted, this, &QuickListProxyModel::countChanged);
25+ connect(this, &QAbstractListModel::rowsRemoved, this, &QuickListProxyModel::countChanged);
26+ connect(this, &QAbstractListModel::layoutChanged, this, &QuickListProxyModel::countChanged);
27+}
28+
29+QAbstractItemModel *QuickListProxyModel::source() const
30+{
31+ return m_source;
32+}
33+
34+bool QuickListProxyModel::privateMode() const
35+{
36+ return m_privateMode;
37+}
38+
39+void QuickListProxyModel::setPrivateMode(bool privateMode)
40+{
41+ if (m_privateMode != privateMode) {
42+ m_privateMode = privateMode;
43+ invalidateFilter();
44+ Q_EMIT privateModeChanged();
45+ }
46+}
47+
48+void QuickListProxyModel::setSource(QAbstractItemModel *source)
49+{
50+ if (m_source != source) {
51+ m_source = source;
52+ setSourceModel(m_source);
53+ connect(m_source, &QAbstractItemModel::rowsRemoved, this, &QuickListProxyModel::invalidate);
54+ connect(m_source, &QAbstractItemModel::rowsInserted, this, &QuickListProxyModel::invalidate);
55+ Q_EMIT sourceChanged();
56+ }
57+}
58+
59+int QuickListProxyModel::count() const
60+{
61+ return rowCount();
62+}
63+
64+bool QuickListProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
65+{
66+ Q_UNUSED(source_parent)
67+
68+ if (m_privateMode) {
69+ return !m_source->data(m_source->index(source_row, 0), QuickListModelInterface::RoleIsPrivate).toBool();
70+ }
71+ return true;
72+}
plugins/Utils/quicklistproxymodel.hnew file+52
@@ -0,0 +1,52 @@
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+#include <QSortFilterProxyModel>
18+
19+#include <unity/shell/launcher/QuickListModelInterface.h>
20+
21+using namespace unity::shell::launcher;
22+
23+class QuickListProxyModel: public QSortFilterProxyModel
24+{
25+ Q_OBJECT
26+ Q_PROPERTY(QAbstractItemModel* source READ source WRITE setSource NOTIFY sourceChanged)
27+ Q_PROPERTY(bool privateMode READ privateMode WRITE setPrivateMode NOTIFY privateModeChanged)
28+ Q_PROPERTY(int count READ count NOTIFY countChanged)
29+
30+public:
31+ QuickListProxyModel(QObject* parent = nullptr);
32+
33+ QAbstractItemModel* source() const;
34+ void setSource(QAbstractItemModel* source);
35+
36+ bool privateMode() const;
37+ void setPrivateMode(bool privateMode);
38+
39+ int count() const;
40+
41+protected:
42+ bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
43+
44+Q_SIGNALS:
45+ void sourceChanged();
46+ void privateModeChanged();
47+ void countChanged();
48+
49+private:
50+ QAbstractItemModel* m_source = nullptr;
51+ bool m_privateMode = false;
52+};
plugins/Utils/tabfocusfence.cppnew file+72
@@ -0,0 +1,72 @@
1+/*
2+ * Copyright 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 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+
17+#include "tabfocusfence.h"
18+
19+#include <private/qquickitem_p.h>
20+
21+TabFocusFenceItem::TabFocusFenceItem(QQuickItem *parent) : QQuickItem(parent)
22+{
23+ QQuickItemPrivate *d = QQuickItemPrivate::get(this);
24+ d->isTabFence = true;
25+ setFlag(ItemIsFocusScope);
26+}
27+
28+bool TabFocusFenceItem::focusNext()
29+{
30+ QQuickItem * current = scopedFocusItem();
31+ if (current) {
32+ QQuickItem * next = current->nextItemInFocusChain(true);
33+ if (next) {
34+ next->setFocus(true, Qt::TabFocusReason);
35+ return true;
36+ }
37+ }
38+ return false;
39+}
40+
41+bool TabFocusFenceItem::focusPrev()
42+{
43+ QQuickItem * current = scopedFocusItem();
44+ if (current) {
45+ QQuickItem * prev = current->nextItemInFocusChain(false);
46+ if (prev) {
47+ prev->setFocus(true, Qt::BacktabFocusReason);
48+ return true;
49+ }
50+ }
51+ return false;
52+}
53+
54+void TabFocusFenceItem::keyPressEvent(QKeyEvent *event)
55+{
56+ // Needed so we eat Tab keys when there's only one item inside the fence
57+ if (event->key() == Qt::Key_Tab) {
58+ event->accept();
59+ } else {
60+ QQuickItem::keyPressEvent(event);
61+ }
62+}
63+
64+void TabFocusFenceItem::keyReleaseEvent(QKeyEvent *event)
65+{
66+ // Needed so we eat Tab keys when there's only one item inside the fence
67+ if (event->key() == Qt::Key_Tab) {
68+ event->accept();
69+ } else {
70+ QQuickItem::keyReleaseEvent(event);
71+ }
72+}
plugins/Utils/tabfocusfence.hnew file+38
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright 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 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+
17+#ifndef TABFOCUSFENCE_H
18+#define TABFOCUSFENCE_H
19+
20+#include <QQuickItem>
21+
22+// An item that restricts focus Tab travelling
23+// to its children
24+class TabFocusFenceItem : public QQuickItem
25+{
26+Q_OBJECT
27+
28+public:
29+ TabFocusFenceItem(QQuickItem *parent = nullptr);
30+
31+ Q_INVOKABLE bool focusNext();
32+ Q_INVOKABLE bool focusPrev();
33+
34+ void keyPressEvent(QKeyEvent *event) override;
35+ void keyReleaseEvent(QKeyEvent *event) override;
36+};
37+
38+#endif
plugins/Utils/windowstatestorage.cpp+294−125
@@ -1,5 +1,6 @@
11/*
22 * Copyright 2015-2016 Canonical Ltd.
3+ * Copyright 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 Lesser General Public License as published by
@@ -16,178 +17,344 @@
1617
1718#include "windowstatestorage.h"
1819
19−#include <QtConcurrent>
2020#include <QDebug>
21−#include <QFutureSynchronizer>
21+#include <QDir>
22+#include <QMetaObject>
23+#include <QObject>
2224#include <QSqlQuery>
2325#include <QSqlError>
2426#include <QSqlResult>
27+#include <QStandardPaths>
2528#include <QRect>
2629#include <unity/shell/application/ApplicationInfoInterface.h>
2730
28−QMutex WindowStateStorage::s_mutex;
2931
30−inline QString sanitiseString(QString string) {
31− return string.remove(QLatin1Char('\"'))
32− .remove(QLatin1Char('\''))
33− .remove(QLatin1Char('\\'));
34−}
35−
36−WindowStateStorage::WindowStateStorage(QObject *parent):
37− QObject(parent)
32+class AsyncQuery: public QObject
3833{
39− const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/unity8/");
40− m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"));
41− QDir dir;
42− dir.mkpath(dbPath);
43− m_db.setDatabaseName(dbPath + "windowstatestorage.sqlite");
44− initdb();
45−}
34+ Q_OBJECT
4635
47−WindowStateStorage::~WindowStateStorage()
48−{
49− QFutureSynchronizer<void> futureSync;
50− for (int i = 0; i < m_asyncQueries.count(); ++i) {
51− futureSync.addFuture(m_asyncQueries[i]);
36+public:
37+ AsyncQuery(const QString &dbName):
38+ m_dbName(dbName)
39+ {
5240 }
53− futureSync.waitForFinished();
54− m_db.close();
55−}
5641
57−void WindowStateStorage::saveState(const QString &windowId, WindowStateStorage::WindowState state)
58−{
59− const QString queryString = QStringLiteral("INSERT OR REPLACE INTO state (windowId, state) values ('%1', '%2');")
60− .arg(sanitiseString(windowId))
61− .arg((int)state);
42+ ~AsyncQuery()
43+ {
44+ QSqlDatabase::removeDatabase(m_connectionName);
45+ }
6246
63− saveValue(queryString);
64−}
47+ Q_INVOKABLE const QString getDbName()
48+ {
49+ if (!m_ok) {
50+ return "ERROR";
51+ }
52+ QSqlDatabase connection = QSqlDatabase::database(m_connectionName);
53+ return connection.databaseName();
54+ }
6555
66−WindowStateStorage::WindowState WindowStateStorage::getState(const QString &windowId, WindowStateStorage::WindowState defaultValue) const
67−{
68− const QString queryString = QStringLiteral("SELECT state FROM state WHERE windowId = '%1';")
69− .arg(sanitiseString(windowId));
56+ Q_INVOKABLE bool initdb()
57+ {
58+ if (m_ok) {
59+ return true;
60+ }
61+ QSqlDatabase connection = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), m_connectionName);
62+ connection.setDatabaseName(m_dbName);
63+ connection.setConnectOptions(QStringLiteral("QSQLITE_BUSY_TIMEOUT=1000"));
64+ if (!connection.open()) {
65+ qWarning() << "AsyncQuery::initdb: Error opening state database. Window positions will not be saved or restored." << m_dbName << connection.lastError().driverText() << connection.lastError().databaseText();
66+ return false;
67+ }
68+ QSqlQuery query(connection);
69+
70+ if (!connection.tables().contains(QStringLiteral("geometry"))) {
71+ QString geometryQuery = QStringLiteral("CREATE TABLE geometry(windowId TEXT UNIQUE, x INTEGER, y INTEGER, width INTEGER, height INTEGER);");
72+ if (!query.exec(geometryQuery)) {
73+ logSqlError(query);
74+ return false;
75+ }
76+ }
77+
78+ if (!connection.tables().contains(QStringLiteral("state"))) {
79+ QString stateQuery = QStringLiteral("CREATE TABLE state(windowId TEXT UNIQUE, state INTEGER);");
80+ if (!query.exec(stateQuery)) {
81+ logSqlError(query);
82+ return false;
83+ }
84+ }
85+
86+ if (!connection.tables().contains(QStringLiteral("stage"))) {
87+ QString stageQuery = QStringLiteral("CREATE TABLE stage(appId TEXT UNIQUE, stage INTEGER);");
88+ if (!query.exec(stageQuery)) {
89+ logSqlError(query);
90+ return false;
91+ }
92+ }
93+ m_ok = true;
94+ return true;
95+ }
7096
71− QSqlQuery query = getValue(queryString);
97+ Q_INVOKABLE int getState(const QString &windowId) const
98+ {
99+ if (!m_ok) {
100+ return -1;
101+ }
102+ QSqlDatabase connection = QSqlDatabase::database(m_connectionName);
103+ QSqlQuery query(connection);
104+ query.prepare(m_getStateQuery);
105+ query.bindValue(":windowId", windowId);
106+ query.exec();
107+ if (!query.isActive() || !query.isSelect()) {
108+ logSqlError(query);
109+ return -1;
110+ }
111+ if (!query.first()) {
112+ return -1;
113+ }
114+ bool converted = false;
115+ QVariant resultStr = query.value(0);
116+ int result = resultStr.toInt(&converted);
117+ if (converted) {
118+ return result;
119+ } else {
120+ qWarning() << "getState result expected integer, got " << resultStr;
121+ return -1;
122+ }
123+ }
124+
125+ Q_INVOKABLE QRect getGeometry(const QString &windowId) const
126+ {
127+ if (!m_ok) {
128+ return QRect();
129+ }
130+ QSqlDatabase connection = QSqlDatabase::database(m_connectionName);
131+ QSqlQuery query(connection);
132+ query.prepare(m_getGeometryQuery);
133+ query.bindValue(":windowId", windowId);
134+ query.exec();
135+ if (!query.isActive() || !query.isSelect()) {
136+ logSqlError(query);
137+ return QRect();
138+ }
139+
140+ if (!query.first()) {
141+ return QRect();
142+ }
143+
144+ bool xConverted, yConverted, widthConverted, heightConverted = false;
145+ int x, y, width, height;
146+ QVariant xResultStr = query.value(QStringLiteral("x"));
147+ QVariant yResultStr = query.value(QStringLiteral("y"));
148+ QVariant widthResultStr = query.value(QStringLiteral("width"));
149+ QVariant heightResultStr = query.value(QStringLiteral("height"));
150+ x = xResultStr.toInt(&xConverted);
151+ y = yResultStr.toInt(&yConverted);
152+ width = widthResultStr.toInt(&widthConverted);
153+ height = heightResultStr.toInt(&heightConverted);
154+
155+ if (xConverted && yConverted && widthConverted && heightConverted) {
156+ return QRect(x, y, width, height);
157+ } else {
158+ qWarning() << "getGeometry result expected integers, got x:"
159+ << xResultStr << "y:" << yResultStr << "width" << widthResultStr
160+ << "height:" << heightResultStr;
161+ return QRect();
162+ }
72163
73− if (!query.first()) {
74− return defaultValue;
75164 }
76− return (WindowState)query.value(QStringLiteral("state")).toInt();
77−}
78165
79−void WindowStateStorage::saveGeometry(const QString &windowId, const QRect &rect)
80−{
81− const QString queryString = QStringLiteral("INSERT OR REPLACE INTO geometry (windowId, x, y, width, height) values ('%1', '%2', '%3', '%4', '%5');")
82− .arg(sanitiseString(windowId))
83− .arg(rect.x())
84− .arg(rect.y())
85− .arg(rect.width())
86− .arg(rect.height());
87−
88− saveValue(queryString);
89−}
166+ Q_INVOKABLE int getStage(const QString &appId) const
167+ {
168+ if (!m_ok) {
169+ return -1;
170+ }
171+ QSqlDatabase connection = QSqlDatabase::database(m_connectionName);
172+ QSqlQuery query(connection);
173+ query.prepare(m_getStageQuery);
174+ query.bindValue(":appId", appId);
175+ query.exec();
176+ if (!query.isActive() || !query.isSelect()) {
177+ logSqlError(query);
178+ return -1;
179+ }
180+ if (!query.first()) {
181+ return -1;
182+ }
183+ bool converted = false;
184+ QVariant resultStr = query.value(0);
185+ int result = resultStr.toInt(&converted);
186+ if (converted) {
187+ return result;
188+ } else {
189+ qWarning() << "getStage result expected integer, got " << resultStr;
190+ return -1;
191+ }
192+ }
90193
91−void WindowStateStorage::saveStage(const QString &appId, int stage)
92−{
93− const QString queryString = QStringLiteral("INSERT OR REPLACE INTO stage (appId, stage) values ('%1', '%2');")
94− .arg(sanitiseString(appId))
95− .arg(stage);
194+public Q_SLOTS:
195+
196+ void saveState(const QString &windowId, WindowStateStorage::WindowState state)
197+ {
198+ if (!m_ok) {
199+ return;
200+ }
201+ QSqlDatabase connection = QSqlDatabase::database(m_connectionName);
202+ QSqlQuery query(connection);
203+ query.prepare(m_saveStateQuery);
204+ query.bindValue(":windowId", windowId);
205+ query.bindValue(":state", (int)state);
206+ if (!query.exec()) {
207+ logSqlError(query);
208+ }
209+ }
96210
97− saveValue(queryString);
98−}
211+ void saveGeometry(const QString &windowId, const QRect &rect)
212+ {
213+ if (!m_ok) {
214+ return;
215+ }
216+ QSqlDatabase connection = QSqlDatabase::database(m_connectionName);
217+ QSqlQuery query(connection);
218+ query.prepare(m_saveGeometryQuery);
219+ query.bindValue(":windowId", windowId);
220+ query.bindValue(":x", rect.x());
221+ query.bindValue(":y", rect.y());
222+ query.bindValue(":width", rect.width());
223+ query.bindValue(":height", rect.height());
224+ if (!query.exec()) {
225+ logSqlError(query);
226+ }
227+ }
99228
100−int WindowStateStorage::getStage(const QString &appId, int defaultValue) const
101−{
102− const QString queryString = QStringLiteral("SELECT stage FROM stage WHERE appId = '%1';")
103− .arg(sanitiseString(appId));
229+ void saveStage(const QString &appId, int stage)
230+ {
231+ if (!m_ok) {
232+ return;
233+ }
234+ QSqlDatabase connection = QSqlDatabase::database(m_connectionName);
235+ QSqlQuery query(connection);
236+ query.prepare(m_saveStageQuery);
237+ query.bindValue(":appId", appId);
238+ query.bindValue(":stage", stage);
239+ if (!query.exec()) {
240+ logSqlError(query);
241+ }
242+ }
104243
105− QSqlQuery query = getValue(queryString);
244+private:
245+ static const QString m_connectionName;
246+ static const QString m_getStateQuery;
247+ static const QString m_saveStateQuery;
248+ static const QString m_getGeometryQuery;
249+ static const QString m_saveGeometryQuery;
250+ static const QString m_getStageQuery;
251+ static const QString m_saveStageQuery;
252+
253+ static void logSqlError(const QSqlQuery query)
254+ {
255+ qWarning() << "Error executing query" << query.lastQuery()
256+ << "Driver error:" << query.lastError().driverText()
257+ << "Database error:" << query.lastError().databaseText();
258+ }
106259
107− if (!query.first()) {
108− return defaultValue;
260+ QString m_dbName;
261+ bool m_ok = false;
262+};
263+
264+const QString AsyncQuery::m_connectionName = QStringLiteral("WindowStateStorage");
265+const QString AsyncQuery::m_getStateQuery = QStringLiteral("SELECT state FROM state WHERE windowId = :windowId");
266+const QString AsyncQuery::m_saveStateQuery = QStringLiteral("INSERT OR REPLACE INTO state (windowId, state) values (:windowId, :state)");
267+const QString AsyncQuery::m_getGeometryQuery = QStringLiteral("SELECT * FROM geometry WHERE windowId = :windowId");
268+const QString AsyncQuery::m_saveGeometryQuery = QStringLiteral("INSERT OR REPLACE INTO geometry (windowId, x, y, width, height) values (:windowId, :x, :y, :width, :height)");
269+const QString AsyncQuery::m_getStageQuery = QStringLiteral("SELECT stage FROM stage WHERE appId = :appId");
270+const QString AsyncQuery::m_saveStageQuery = QStringLiteral("INSERT OR REPLACE INTO stage (appId, stage) values (:appId, :stage)");
271+
272+WindowStateStorage::WindowStateStorage(const QString &dbName, QObject *parent):
273+ QObject(parent),
274+ m_thread()
275+{
276+ qRegisterMetaType<WindowStateStorage::WindowState>("WindowStateStorage::WindowState");
277+ QString dbFile;
278+ if (dbName.isEmpty()) {
279+ const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/unity8/");
280+ QDir dir;
281+ dir.mkpath(dbPath);
282+ dbFile = QString(dbPath) + QStringLiteral("windowstatestorage.sqlite");
283+ } else {
284+ dbFile = dbName;
109285 }
110− return query.value("stage").toInt();
286+ m_asyncQuery = new AsyncQuery(dbFile);
287+ m_asyncQuery->moveToThread(&m_thread);
288+ connect(&m_thread, &QThread::finished, m_asyncQuery, &QObject::deleteLater);
289+ m_thread.start();
290+ // Note that we're relying on initdb being called before any other methods
291+ // on AsyncQuery. Given the current behavior of QueuedConnection (slots
292+ // invoked in the order they are received), this is fine.
293+ QMetaObject::invokeMethod(m_asyncQuery, "initdb",
294+ Qt::QueuedConnection);
295+ connect(this, &WindowStateStorage::saveState, m_asyncQuery, &AsyncQuery::saveState);
296+ connect(this, &WindowStateStorage::saveGeometry, m_asyncQuery, &AsyncQuery::saveGeometry);
297+ connect(this, &WindowStateStorage::saveStage, m_asyncQuery, &AsyncQuery::saveStage);
111298}
112299
113−void WindowStateStorage::executeAsyncQuery(const QString &queryString)
300+WindowStateStorage::~WindowStateStorage()
114301{
115− QMutexLocker l(&s_mutex);
116− QSqlQuery query;
117−
118− bool ok = query.exec(queryString);
119− if (!ok) {
120− qWarning() << "Error executing query" << queryString
121− << "Driver error:" << query.lastError().driverText()
122− << "Database error:" << query.lastError().databaseText();
123− }
302+ m_thread.quit();
303+ m_thread.wait();
124304}
125305
126−QRect WindowStateStorage::getGeometry(const QString &windowId, const QRect &defaultValue) const
306+WindowStateStorage::WindowState WindowStateStorage::getState(const QString &windowId, WindowStateStorage::WindowState defaultValue) const
127307{
128− QString queryString = QStringLiteral("SELECT * FROM geometry WHERE windowId = '%1';")
129− .arg(sanitiseString(windowId));
308+ int state;
130309
131− QSqlQuery query = getValue(queryString);
310+ QMetaObject::invokeMethod(m_asyncQuery, "getState", Qt::BlockingQueuedConnection,
311+ Q_RETURN_ARG(int, state),
312+ Q_ARG(const QString&, windowId)
313+ );
132314
133− if (!query.first()) {
315+ if (state == -1) {
134316 return defaultValue;
135317 }
136− return QRect(query.value(QStringLiteral("x")).toInt(), query.value(QStringLiteral("y")).toInt(),
137− query.value(QStringLiteral("width")).toInt(), query.value(QStringLiteral("height")).toInt());
318+
319+ return (WindowState)state;
138320}
139321
140−void WindowStateStorage::initdb()
322+int WindowStateStorage::getStage(const QString &appId, int defaultValue) const
141323{
142− m_db.open();
143− if (!m_db.open()) {
144− qWarning() << "Error opening state database:" << m_db.lastError().driverText() << m_db.lastError().databaseText();
145− return;
146− }
324+ int stage;
147325
148− if (!m_db.tables().contains(QStringLiteral("geometry"))) {
149− QSqlQuery query;
150− query.exec(QStringLiteral("CREATE TABLE geometry(windowId TEXT UNIQUE, x INTEGER, y INTEGER, width INTEGER, height INTEGER);"));
151− }
326+ QMetaObject::invokeMethod(m_asyncQuery, "getStage", Qt::BlockingQueuedConnection,
327+ Q_RETURN_ARG(int, stage),
328+ Q_ARG(const QString&, appId)
329+ );
152330
153− if (!m_db.tables().contains(QStringLiteral("state"))) {
154− QSqlQuery query;
155− query.exec(QStringLiteral("CREATE TABLE state(windowId TEXT UNIQUE, state INTEGER);"));
331+ if (stage == -1) {
332+ return defaultValue;
156333 }
157334
158− if (!m_db.tables().contains(QStringLiteral("stage"))) {
159− QSqlQuery query;
160− query.exec(QStringLiteral("CREATE TABLE stage(appId TEXT UNIQUE, stage INTEGER);"));
161− }
335+ return stage;
162336}
163337
164−void WindowStateStorage::saveValue(const QString &queryString)
338+QRect WindowStateStorage::getGeometry(const QString &windowId, const QRect &defaultValue) const
165339{
166− QMutexLocker mutexLocker(&s_mutex);
167−
168− QFuture<void> future = QtConcurrent::run(executeAsyncQuery, queryString);
169− m_asyncQueries.append(future);
170−
171− QFutureWatcher<void> *futureWatcher = new QFutureWatcher<void>();
172− futureWatcher->setFuture(future);
173− connect(futureWatcher, &QFutureWatcher<void>::finished,
174− this,
175− [=](){ m_asyncQueries.removeAll(futureWatcher->future());
176− futureWatcher->deleteLater(); });
340+ QRect geometry;
341+ QMetaObject::invokeMethod(m_asyncQuery, "getGeometry", Qt::BlockingQueuedConnection,
342+ Q_RETURN_ARG(QRect, geometry),
343+ Q_ARG(const QString&, windowId)
344+ );
345+ if (geometry.isNull() || !geometry.isValid()) {
346+ return defaultValue;
347+ }
348+ return geometry;
177349}
178350
179−QSqlQuery WindowStateStorage::getValue(const QString &queryString) const
351+const QString WindowStateStorage::getDbName()
180352{
181− QMutexLocker l(&s_mutex);
182− QSqlQuery query;
183−
184− bool ok = query.exec(queryString);
185− if (!ok) {
186− qWarning() << "Error retrieving database query:" << queryString
187− << "Driver error:" << query.lastError().driverText()
188− << "Database error:" << query.lastError().databaseText();
189− }
190− return query;
353+ QString dbName;
354+ QMetaObject::invokeMethod(m_asyncQuery, "getDbName", Qt::BlockingQueuedConnection,
355+ Q_RETURN_ARG(QString, dbName)
356+ );
357+ return QString(dbName);
191358}
192359
193360Mir::State WindowStateStorage::toMirState(WindowState state) const
@@ -212,3 +379,5 @@ Mir::State WindowStateStorage::toMirState(WindowState state) const
212379 return Mir::RestoredState;
213380 }
214381}
382+
383+#include "windowstatestorage.moc"
plugins/Utils/windowstatestorage.h+14−15
@@ -1,5 +1,6 @@
11/*
22 * Copyright 2015-2016 Canonical Ltd.
3+ * Copyright 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 Lesser General Public License as published by
@@ -16,12 +17,16 @@
1617
1718#include <QObject>
1819#include <QSqlDatabase>
20+#include <QSqlQuery>
1921#include <QMutex>
2022#include <QFuture>
23+#include <QThread>
2124
2225// unity-api
2326#include <unity/shell/application/Mir.h>
2427
28+class AsyncQuery;
29+
2530class WindowStateStorage: public QObject
2631{
2732 Q_OBJECT
@@ -45,31 +50,25 @@ public:
4550 Q_DECLARE_FLAGS(WindowStates, WindowState)
4651 Q_FLAG(WindowStates)
4752
48− WindowStateStorage(QObject *parent = nullptr);
53+ WindowStateStorage(const QString &dbName = QString(), QObject *parent = nullptr);
4954 virtual ~WindowStateStorage();
5055
51− Q_INVOKABLE void saveState(const QString &windowId, WindowState state);
5256 Q_INVOKABLE WindowState getState(const QString &windowId, WindowState defaultValue) const;
5357
54− Q_INVOKABLE void saveGeometry(const QString &windowId, const QRect &rect);
5558 Q_INVOKABLE QRect getGeometry(const QString &windowId, const QRect &defaultValue) const;
5659
57− Q_INVOKABLE void saveStage(const QString &appId, int stage);
5860 Q_INVOKABLE int getStage(const QString &appId, int defaultValue) const;
5961
6062 Q_INVOKABLE Mir::State toMirState(WindowState state) const;
6163
62−private:
63− void initdb();
64−
65− void saveValue(const QString &queryString);
66− QSqlQuery getValue(const QString &queryString) const;
64+ const QString getDbName();
6765
68− static void executeAsyncQuery(const QString &queryString);
69− static QMutex s_mutex;
66+Q_SIGNALS:
67+ void saveStage(const QString &appId, int stage);
68+ void saveGeometry(const QString &windowId, const QRect &rect);
69+ void saveState(const QString &windowId, WindowStateStorage::WindowState state);
7070
71− // NB: This is accessed from threads. Make sure to mutex it.
72− QSqlDatabase m_db;
73−
74− QList<QFuture<void>> m_asyncQueries;
71+private:
72+ QThread m_thread;
73+ AsyncQuery *m_asyncQuery;
7574};
plugins/WindowManager/AvailableDesktopArea.cppnew file+50
@@ -0,0 +1,50 @@
1+/*
2+ * Copyright (C) 2017 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * 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+
17+#include "AvailableDesktopArea.h"
18+
19+#include <QGuiApplication>
20+#include <QQuickWindow>
21+#include <qpa/qplatformnativeinterface.h>
22+
23+AvailableDesktopArea::AvailableDesktopArea(QQuickItem *parent)
24+ : QQuickItem(parent)
25+{
26+ connect(this, &QQuickItem::xChanged, this, &AvailableDesktopArea::updatePlatformWindowProperty);
27+ connect(this, &QQuickItem::yChanged, this, &AvailableDesktopArea::updatePlatformWindowProperty);
28+ connect(this, &QQuickItem::widthChanged, this, &AvailableDesktopArea::updatePlatformWindowProperty);
29+ connect(this, &QQuickItem::heightChanged, this, &AvailableDesktopArea::updatePlatformWindowProperty);
30+}
31+
32+void AvailableDesktopArea::updatePlatformWindowProperty()
33+{
34+ if (!window()) {
35+ return;
36+ }
37+
38+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
39+
40+ QRect rect(x(), y(), width(), height());
41+
42+ nativeInterface->setWindowProperty(window()->handle(), "availableDesktopArea", QVariant(rect));
43+}
44+
45+void AvailableDesktopArea::itemChange(ItemChange change, const ItemChangeData &)
46+{
47+ if (change == ItemSceneChange) {
48+ updatePlatformWindowProperty();
49+ }
50+}
plugins/Unity/DashCommunicator/dashcommunicator.h → plugins/WindowManager/AvailableDesktopArea.hrenamed+14−21
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2017 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
@@ -14,32 +14,25 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#ifndef DASHCOMMUNICATOR_H
18−#define DASHCOMMUNICATOR_H
17+#ifndef AVAILABLEDESKTOPAREA_H
18+#define AVAILABLEDESKTOPAREA_H
1919
20−// Qt
21−#include <QThread>
22−#include <QMutex>
20+#include <QQuickItem>
2321
24−class DashConnection;
22+/**
23+ @brief Used to inform qtmir/miral about the available desktop area of shell
2524
26−class DashCommunicator: public QThread
25+ So that qtmir/miral can take correct window management decisions.
26+ */
27+class AvailableDesktopArea : public QQuickItem
2728{
2829 Q_OBJECT
2930public:
30− explicit DashCommunicator(QObject *parent = 0);
31− ~DashCommunicator();
32−
33−public Q_SLOTS:
34− void setCurrentScope(int index, bool animate, bool isSwipe);
35−
31+ AvailableDesktopArea(QQuickItem *parent = nullptr);
3632protected:
37− void run() override;
38−
39−private:
40− DashConnection *m_dashConnection;
41− bool m_created;
42− QMutex m_mutex;
33+ void itemChange(ItemChange change, const ItemChangeData &value) override;
34+private Q_SLOTS:
35+ void updatePlatformWindowProperty();
4336};
4437
45−#endif
38+#endif // AVAILABLEDESKTOPAREA_H
plugins/WindowManager/CMakeLists.txt+11−1
@@ -1,7 +1,10 @@
11set(WINDOWMANAGER_SRC
2+ AvailableDesktopArea.cpp
23 TopLevelWindowModel.cpp
34 Window.cpp
45 WindowManagerPlugin.cpp
6+ WindowMargins.cpp
7+ InputMethodManager.cpp
58 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
69 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
710 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
@@ -9,8 +12,15 @@ set(WINDOWMANAGER_SRC
912 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/SurfaceManagerInterface.h
1013 )
1114
15+add_definitions(-DWINDOWMANAGERQML_LIBRARY)
16+
17+include_directories(
18+ SYSTEM
19+ ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
20+)
21+
1222add_library(windowmanager-qml SHARED ${WINDOWMANAGER_SRC})
1323
14−qt5_use_modules(windowmanager-qml Qml Quick Gui)
24+target_link_libraries(windowmanager-qml Qt5::Qml Qt5::Quick Qt5::Gui)
1525
1626add_unity8_plugin(WindowManager 0.1 WindowManager TARGETS windowmanager-qml)
plugins/WindowManager/InputMethodManager.cppnew file+56
@@ -0,0 +1,56 @@
1+/*
2+ * Copyright (C) 2019 UBports Foundation.
3+ * Author(s) Marius Gripsgard <marius@ubports.com>
4+ *
5+ * This program is free software: you can redistribute it and/or modify it under
6+ * the terms of the GNU Lesser General Public License version 3, as published by
7+ * the Free Software Foundation.
8+ *
9+ * This program is distributed in the hope that it will be useful, but WITHOUT
10+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
11+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+ * Lesser General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU Lesser General Public License
15+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16+ */
17+
18+#include "InputMethodManager.h"
19+#include <QDebug>
20+
21+#include <unity/shell/application/MirSurfaceInterface.h>
22+
23+// local
24+#include "Window.h"
25+
26+Q_LOGGING_CATEGORY(INPUTMETHODMANAGER, "InputMethodManager", QtInfoMsg)
27+#define DEBUG_MSG qCDebug(INPUTMETHODMANAGER).nospace().noquote() << __func__
28+
29+namespace unityapi = unity::shell::application;
30+
31+InputMethodManager *InputMethodManager::instance()
32+{
33+ static InputMethodManager* inputMethod(new InputMethodManager());
34+ return inputMethod;
35+}
36+
37+InputMethodManager::InputMethodManager()
38+{
39+}
40+
41+void InputMethodManager::setWindow(Window* window)
42+{
43+ if (window == m_inputMethodWindow) {
44+ return;
45+ }
46+
47+ DEBUG_MSG << "(" << window << ")";
48+
49+ m_inputMethodWindow = window;
50+ Q_EMIT surfaceChanged(surface());
51+}
52+
53+unityapi::MirSurfaceInterface* InputMethodManager::surface() const
54+{
55+ return m_inputMethodWindow ? m_inputMethodWindow->surface() : nullptr;
56+}
plugins/WindowManager/InputMethodManager.hnew file+55
@@ -0,0 +1,55 @@
1+/*
2+ * Copyright (C) 2019 UBports Foundation.
3+ * Author(s) Marius Gripsgard <marius@ubports.com>
4+ *
5+ * This program is free software: you can redistribute it and/or modify it under
6+ * the terms of the GNU Lesser General Public License version 3, as published by
7+ * the Free Software Foundation.
8+ *
9+ * This program is distributed in the hope that it will be useful, but WITHOUT
10+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
11+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+ * Lesser General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU Lesser General Public License
15+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16+ */
17+
18+#pragma once
19+
20+#include <QLoggingCategory>
21+#include <QObject>
22+
23+#include "WindowManagerGlobal.h"
24+
25+Q_DECLARE_LOGGING_CATEGORY(INPUTMETHODMANAGER)
26+
27+class Window;
28+
29+namespace unity {
30+ namespace shell {
31+ namespace application {
32+ class MirSurfaceInterface;
33+ }
34+ }
35+}
36+
37+class WINDOWMANAGERQML_EXPORT InputMethodManager : public QObject
38+{
39+ Q_OBJECT
40+ Q_PROPERTY(unity::shell::application::MirSurfaceInterface* surface READ surface NOTIFY surfaceChanged)
41+
42+public:
43+ InputMethodManager();
44+ static InputMethodManager* instance();
45+
46+ void setWindow(Window* window);
47+
48+Q_SIGNALS:
49+ void surfaceChanged(unity::shell::application::MirSurfaceInterface* inputMethodSurface);
50+
51+private:
52+ unity::shell::application::MirSurfaceInterface* surface() const;
53+
54+ Window* m_inputMethodWindow{nullptr};
55+};
plugins/WindowManager/TopLevelWindowModel.cpp+197−83
@@ -1,5 +1,6 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2016-2017 Canonical, Ltd.
3+ * Copyright 2019 UBports Foundation
34 *
45 * This program is free software: you can redistribute it and/or modify it under
56 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -29,6 +30,7 @@
2930
3031// local
3132#include "Window.h"
33+#include "InputMethodManager.h"
3234
3335Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtInfoMsg)
3436
@@ -38,7 +40,12 @@ Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtInfoMsg)
3840namespace unityapi = unity::shell::application;
3941
4042TopLevelWindowModel::TopLevelWindowModel()
43+ : m_nullWindow(createNullWindow()),
44+ m_surfaceManagerBusy(false)
4145{
46+ connect(m_nullWindow, &Window::focusedChanged, this, [this] {
47+ Q_EMIT rootFocusChanged();
48+ });
4249}
4350
4451void TopLevelWindowModel::setApplicationManager(unityapi::ApplicationManagerInterface* value)
@@ -130,7 +137,7 @@ void TopLevelWindowModel::removeApplication(unityapi::ApplicationInfoInterface *
130137 int i = 0;
131138 while (i < m_windowModel.count()) {
132139 if (m_windowModel.at(i).application == application) {
133− removeAt(i);
140+ deleteAt(i);
134141 } else {
135142 ++i;
136143 }
@@ -148,12 +155,13 @@ void TopLevelWindowModel::prependSurface(unityapi::MirSurfaceInterface *surface,
148155{
149156 Q_ASSERT(surface != nullptr);
150157
158+ connectSurface(surface);
159+
151160 bool filledPlaceholder = false;
152161 for (int i = 0; i < m_windowModel.count() && !filledPlaceholder; ++i) {
153162 ModelEntry &entry = m_windowModel[i];
154163 if (entry.application == application && entry.window->surface() == nullptr) {
155164 entry.window->setSurface(surface);
156− connectSurface(surface);
157165 INFO_MSG << " appId=" << application->appId() << " surface=" << surface
158166 << ", filling out placeholder. after: " << toString();
159167 filledPlaceholder = true;
@@ -167,6 +175,33 @@ void TopLevelWindowModel::prependSurface(unityapi::MirSurfaceInterface *surface,
167175}
168176
169177void TopLevelWindowModel::prependSurfaceHelper(unityapi::MirSurfaceInterface *surface, unityapi::ApplicationInfoInterface *application)
178+{
179+
180+ Window *window = createWindow(surface);
181+
182+ connect(window, &Window::stateChanged, this, [=](Mir::State newState) {
183+ if (newState == Mir::HiddenState) {
184+ // Comply, removing it from our model. Just as if it didn't exist anymore.
185+ removeAt(indexForId(window->id()));
186+ } else {
187+ if (indexForId(window->id()) == -1) {
188+ // was probably hidden before. put it back on the list
189+ auto *application = m_applicationManager->findApplicationWithSurface(window->surface());
190+ Q_ASSERT(application);
191+ prependWindow(window, application);
192+ }
193+ }
194+ });
195+
196+ prependWindow(window, application);
197+
198+ // Activate the newly-prepended window.
199+ window->activate();
200+
201+ INFO_MSG << " after " << toString();
202+}
203+
204+void TopLevelWindowModel::prependWindow(Window *window, unityapi::ApplicationInfoInterface *application)
170205{
171206 if (m_modelState == IdleState) {
172207 m_modelState = InsertingState;
@@ -176,17 +211,7 @@ void TopLevelWindowModel::prependSurfaceHelper(unityapi::MirSurfaceInterface *su
176211 // No point in signaling anything if we're resetting the whole model
177212 }
178213
179− int id = generateId();
180− Window *window = new Window(id, this);
181− if (surface) {
182− window->setSurface(surface);
183− }
184214 m_windowModel.prepend(ModelEntry(window, application));
185− if (surface) {
186− connectSurface(surface);
187− }
188−
189− connectWindow(window);
190215
191216 if (m_modelState == InsertingState) {
192217 endInsertRows();
@@ -194,12 +219,6 @@ void TopLevelWindowModel::prependSurfaceHelper(unityapi::MirSurfaceInterface *su
194219 Q_EMIT listChanged();
195220 m_modelState = IdleState;
196221 }
197−
198− if (!surface) {
199− activateEmptyWindow(window);
200− }
201−
202− INFO_MSG << " after " << toString();
203222}
204223
205224void TopLevelWindowModel::connectWindow(Window *window)
@@ -248,6 +267,13 @@ void TopLevelWindowModel::connectWindow(Window *window)
248267 connect(window, &Window::emptyWindowActivated, this, [this, window]() {
249268 activateEmptyWindow(window);
250269 });
270+
271+ connect(window, &Window::liveChanged, this, [this, window](bool isAlive) {
272+ if (!isAlive && window->state() == Mir::HiddenState) {
273+ // Hidden windows are not in the model. So just delete it right away.
274+ delete window;
275+ }
276+ });
251277}
252278
253279void TopLevelWindowModel::activateEmptyWindow(Window *window)
@@ -291,10 +317,11 @@ void TopLevelWindowModel::onSurfaceDied(unityapi::MirSurfaceInterface *surface)
291317
292318 auto application = m_windowModel[i].application;
293319
294− // can't be starting if it already has a surface
295− Q_ASSERT(application->state() != unityapi::ApplicationInfoInterface::Starting);
320+ DEBUG_MSG << " application->name()=" << application->name()
321+ << " application->state()=" << application->state();
296322
297− if (application->state() == unityapi::ApplicationInfoInterface::Running) {
323+ if (application->state() == unityapi::ApplicationInfoInterface::Running
324+ || application->state() == unityapi::ApplicationInfoInterface::Starting) {
298325 m_windowModel[i].removeOnceSurfaceDestroyed = true;
299326 } else {
300327 // assume it got killed by the out-of-memory daemon.
@@ -313,7 +340,7 @@ void TopLevelWindowModel::onSurfaceDestroyed(unityapi::MirSurfaceInterface *surf
313340 }
314341
315342 if (m_windowModel[i].removeOnceSurfaceDestroyed) {
316− removeAt(i);
343+ deleteAt(i);
317344 } else {
318345 auto window = m_windowModel[i].window;
319346 window->setSurface(nullptr);
@@ -322,34 +349,78 @@ void TopLevelWindowModel::onSurfaceDestroyed(unityapi::MirSurfaceInterface *surf
322349 }
323350}
324351
352+Window *TopLevelWindowModel::createWindow(unityapi::MirSurfaceInterface *surface)
353+{
354+ int id = m_nextId.fetchAndAddAcquire(1);
355+ return createWindowWithId(surface, id);
356+}
357+
358+Window *TopLevelWindowModel::createNullWindow()
359+{
360+ return createWindowWithId(nullptr, 0);
361+}
362+
363+Window *TopLevelWindowModel::createWindowWithId(unityapi::MirSurfaceInterface *surface, int id)
364+{
365+ Window *qmlWindow = new Window(id, this);
366+ connectWindow(qmlWindow);
367+ if (surface) {
368+ qmlWindow->setSurface(surface);
369+ }
370+ return qmlWindow;
371+}
372+
325373void TopLevelWindowModel::onSurfaceCreated(unityapi::MirSurfaceInterface *surface)
326374{
327375 DEBUG_MSG << "(" << surface << ")";
328− if (surface->type() == Mir::InputMethodType) {
329− int id = generateId();
330− Window *qmlWindow = new Window(id, this);
331− connectWindow(qmlWindow);
332− qmlWindow->setSurface(surface);
333− setInputMethodWindow(qmlWindow);
376+
377+ if (surface->parentSurface()) {
378+ // Wrap it in a Window so that we keep focusedWindow() up to date.
379+ Window *window = createWindow(surface);
380+ connect(surface, &QObject::destroyed, window, [=](){
381+ window->setSurface(nullptr);
382+ window->deleteLater();
383+ });
334384 } else {
335− auto application = m_applicationManager->findApplicationWithSurface(surface);
336− if (application) {
337− prependSurface(surface, application);
385+ if (surface->type() == Mir::InputMethodType) {
386+ connectSurface(surface);
387+ setInputMethodWindow(createWindow(surface));
338388 } else {
339− // Must be a prompt session. No need to do add it as a prompt surface is not top-level.
340− // It will show up in the ApplicationInfoInterface::promptSurfaceList of some application.
341− // Still wrap it in a Window though, so that we keep focusedWindow() up to date.
342− int id = generateId();
343− Window *promptWindow = new Window(id, this);
344− connectWindow(promptWindow);
345− promptWindow->setSurface(surface);
346− connect(surface, &QObject::destroyed, promptWindow, [=](){
347− promptWindow->setSurface(nullptr);
348− promptWindow->deleteLater();
349− });
389+ auto *application = m_applicationManager->findApplicationWithSurface(surface);
390+ if (application) {
391+ if (surface->state() == Mir::HiddenState) {
392+ // Ignore it until it's finally shown
393+ connect(surface, &unityapi::MirSurfaceInterface::stateChanged, this, [=](Mir::State newState) {
394+ Q_ASSERT(newState != Mir::HiddenState);
395+ disconnect(surface, &unityapi::MirSurfaceInterface::stateChanged, this, 0);
396+ prependSurface(surface, application);
397+ });
398+ } else {
399+ prependSurface(surface, application);
400+ }
401+ } else {
402+ // Must be a prompt session. No need to do add it as a prompt surface is not top-level.
403+ // It will show up in the ApplicationInfoInterface::promptSurfaceList of some application.
404+ // Still wrap it in a Window though, so that we keep focusedWindow() up to date.
405+ Window *promptWindow = createWindow(surface);
406+ connect(surface, &QObject::destroyed, promptWindow, [=](){
407+ promptWindow->setSurface(nullptr);
408+ promptWindow->deleteLater();
409+ });
410+ }
350411 }
351412 }
352− // TODO: handle surfaces that are neither top-level windows nor input method. eg: child dialogs, popups, menus
413+}
414+
415+void TopLevelWindowModel::deleteAt(int index)
416+{
417+ auto window = m_windowModel[index].window;
418+
419+ removeAt(index);
420+
421+ window->setSurface(nullptr);
422+
423+ delete window;
353424}
354425
355426void TopLevelWindowModel::removeAt(int index)
@@ -364,8 +435,9 @@ void TopLevelWindowModel::removeAt(int index)
364435
365436 auto window = m_windowModel[index].window;
366437
367− window->setSurface(nullptr);
368− window->setFocused(false);
438+ if (!window->surface()) {
439+ window->setFocused(false);
440+ }
369441
370442 m_windowModel.removeAt(index);
371443
@@ -376,13 +448,21 @@ void TopLevelWindowModel::removeAt(int index)
376448 m_modelState = IdleState;
377449 }
378450
379− disconnect(window, 0, this, 0);
380451 if (m_focusedWindow == window) {
381452 setFocusedWindow(nullptr);
382453 }
383− delete window;
384454
385− INFO_MSG << " after " << toString();
455+ if (m_previousWindow == window) {
456+ m_previousWindow = nullptr;
457+ }
458+
459+ if (m_closingAllApps) {
460+ if (m_windowModel.isEmpty()) {
461+ Q_EMIT closedAllWindows();
462+ }
463+ }
464+
465+ INFO_MSG << " after " << toString() << " apps left " << m_windowModel.count();
386466}
387467
388468void TopLevelWindowModel::setInputMethodWindow(Window *window)
@@ -393,6 +473,7 @@ void TopLevelWindowModel::setInputMethodWindow(Window *window)
393473 }
394474 m_inputMethodWindow = window;
395475 Q_EMIT inputMethodSurfaceChanged(m_inputMethodWindow->surface());
476+ InputMethodManager::instance()->setWindow(window);
396477}
397478
398479void TopLevelWindowModel::removeInputMethodWindow()
@@ -401,6 +482,7 @@ void TopLevelWindowModel::removeInputMethodWindow()
401482 delete m_inputMethodWindow;
402483 m_inputMethodWindow = nullptr;
403484 Q_EMIT inputMethodSurfaceChanged(nullptr);
485+ InputMethodManager::instance()->setWindow(nullptr);
404486 }
405487}
406488
@@ -446,37 +528,6 @@ int TopLevelWindowModel::findIndexOf(const unityapi::MirSurfaceInterface *surfac
446528 return -1;
447529}
448530
449−int TopLevelWindowModel::generateId()
450−{
451− int id = m_nextId;
452− m_nextId = nextFreeId(nextId(id), id);
453− return id;
454−}
455−
456−int TopLevelWindowModel::nextId(int id) const
457−{
458− if (id == m_maxId) {
459− return id = 1;
460− } else {
461− return id + 1;
462− }
463−}
464−
465−int TopLevelWindowModel::nextFreeId(int candidateId, const int latestId)
466−{
467− int firstCandidateId = candidateId;
468−
469− while (indexForId(candidateId) != -1 || candidateId == latestId) {
470− candidateId = nextId(candidateId);
471−
472− if (candidateId == firstCandidateId) {
473− qFatal("TopLevelWindowModel: run out of window ids.");
474− }
475− }
476−
477− return candidateId;
478−}
479−
480531QString TopLevelWindowModel::toString()
481532{
482533 QString str;
@@ -590,16 +641,19 @@ void TopLevelWindowModel::setFocusedWindow(Window *window)
590641 if (window != m_focusedWindow) {
591642 INFO_MSG << "(" << window << ")";
592643
593− Window* previousWindow = m_focusedWindow;
644+ m_previousWindow = m_focusedWindow;
594645
595646 m_focusedWindow = window;
596647 Q_EMIT focusedWindowChanged(m_focusedWindow);
597648
598− if (previousWindow && previousWindow->focused() && !previousWindow->surface()) {
649+ if (m_previousWindow && m_previousWindow->focused() && !m_previousWindow->surface()) {
599650 // do it ourselves. miral doesn't know about this window
600− previousWindow->setFocused(false);
651+ m_previousWindow->setFocused(false);
601652 }
602653 }
654+
655+ // Reset
656+ m_pendingActivation = false;
603657}
604658
605659unityapi::MirSurfaceInterface* TopLevelWindowModel::inputMethodSurface() const
@@ -643,6 +697,7 @@ void TopLevelWindowModel::move(int from, int to)
643697}
644698void TopLevelWindowModel::onModificationsStarted()
645699{
700+ m_surfaceManagerBusy = true;
646701}
647702
648703void TopLevelWindowModel::onModificationsEnded()
@@ -653,6 +708,7 @@ void TopLevelWindowModel::onModificationsEnded()
653708 // reset
654709 m_focusedWindowChanged = false;
655710 m_newlyFocusedWindow = nullptr;
711+ m_surfaceManagerBusy = false;
656712}
657713
658714void TopLevelWindowModel::activateTopMostWindowWithoutId(int forbiddenId)
@@ -663,6 +719,64 @@ void TopLevelWindowModel::activateTopMostWindowWithoutId(int forbiddenId)
663719 Window *window = m_windowModel[i].window;
664720 if (window->id() != forbiddenId) {
665721 window->activate();
722+ break;
666723 }
667724 }
668725}
726+
727+void TopLevelWindowModel::closeAllWindows()
728+{
729+ m_closingAllApps = true;
730+ for (auto win : m_windowModel) {
731+ win.window->close();
732+ }
733+
734+ // This is done after the for loop in the unlikely event that
735+ // an app starts in between this
736+ if (m_windowModel.isEmpty()) {
737+ Q_EMIT closedAllWindows();
738+ }
739+}
740+
741+bool TopLevelWindowModel::rootFocus()
742+{
743+ return !m_nullWindow->focused();
744+}
745+
746+void TopLevelWindowModel::setRootFocus(bool focus)
747+{
748+ INFO_MSG << "(" << focus << "), surfaceManagerBusy is " << m_surfaceManagerBusy;
749+
750+ if (m_surfaceManagerBusy) {
751+ // Something else is probably being focused already, let's not add to
752+ // the noise.
753+ return;
754+ }
755+
756+ if (focus) {
757+ // Give focus back to previous focused window, only if null window is focused.
758+ // If null window is not focused, a different app had taken the focus and we
759+ // should repect that, or if a pendingActivation is going on.
760+ if (m_previousWindow && !m_previousWindow->focused() && !m_pendingActivation &&
761+ m_nullWindow == m_focusedWindow && m_previousWindow != m_nullWindow) {
762+ m_previousWindow->activate();
763+ } else if (!m_pendingActivation) {
764+ // The previous window does not exist any more, focus top window.
765+ activateTopMostWindowWithoutId(-1);
766+ }
767+ } else {
768+ if (!m_nullWindow->focused()) {
769+ m_nullWindow->activate();
770+ }
771+ }
772+}
773+
774+// Pending Activation will block refocus of previous focused window
775+// this is needed since surface activation with miral is async,
776+// and activation of placeholder is sync. This causes a race condition
777+// between placeholder and prev window. This results in prev window
778+// gets focused, as it will always be later than the placeholder.
779+void TopLevelWindowModel::pendingActivation()
780+{
781+ m_pendingActivation = true;
782+}
plugins/WindowManager/TopLevelWindowModel.h+58−10
@@ -1,5 +1,6 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2016-2017 Canonical, Ltd.
3+ * Copyright 2019 UBports Foundation
34 *
45 * This program is free software: you can redistribute it and/or modify it under
56 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -18,8 +19,11 @@
1819#define TOPLEVELWINDOWMODEL_H
1920
2021#include <QAbstractListModel>
22+#include <QAtomicInteger>
2123#include <QLoggingCategory>
2224
25+#include "WindowManagerGlobal.h"
26+
2327Q_DECLARE_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL)
2428
2529class Window;
@@ -47,7 +51,7 @@ namespace unity {
4751 * As applications can have multiple surfaces and you can also have entries without surfaces at all,
4852 * the only way to unambiguously refer to an entry in this model is through its id.
4953 */
50−class TopLevelWindowModel : public QAbstractListModel
54+class WINDOWMANAGERQML_EXPORT TopLevelWindowModel : public QAbstractListModel
5155{
5256 Q_OBJECT
5357
@@ -84,7 +88,28 @@ class TopLevelWindowModel : public QAbstractListModel
8488 The id to be used on the next entry created
8589 Useful for tests
8690 */
87− Q_PROPERTY(int nextId READ nextId NOTIFY nextIdChanged)
91+ Q_PROPERTY(int nextId READ nextId)
92+
93+
94+ /**
95+ * @brief Sets whether a user Window or "nothing" should be focused
96+ *
97+ * This implementation of TLWM must have something focused. However, the
98+ * user may wish to have nothing in some cases - for example, when they
99+ * minimize all their windows on the desktop or unfocus the app they're
100+ * using by clicking the background or indicators.
101+ *
102+ * Unsetting rootFocus effectively focuses "nothing" by setting up a Window
103+ * that has no displayable Surfaces and bringing it into focus.
104+ *
105+ * Setting rootFocus attempts to focus the Window which was focused last -
106+ * unless another app is attempting to gain focus (as determined by
107+ * pendingActivation) and that's why we got rootFocus.
108+ *
109+ * If the previously-focused Window was closed before rootFocus was set,
110+ * the next available window will be focused.
111+ */
112+ Q_PROPERTY(bool rootFocus READ rootFocus WRITE setRootFocus NOTIFY rootFocusChanged)
88113
89114public:
90115 /**
@@ -120,7 +145,7 @@ public:
120145 unity::shell::application::SurfaceManagerInterface *surfaceManager() const { return m_surfaceManager; }
121146 void setSurfaceManager(unity::shell::application::SurfaceManagerInterface*);
122147
123− int nextId() const { return m_nextId; }
148+ int nextId() const { return m_nextId.load(); }
124149
125150public:
126151 /**
@@ -162,6 +187,19 @@ public:
162187 */
163188 Q_INVOKABLE void raiseId(int id);
164189
190+ /**
191+ * @brief Closes all windows, emits closedAllWindows when done
192+ */
193+ Q_INVOKABLE void closeAllWindows();
194+
195+ /**
196+ * @brief Sets pending activation flag
197+ */
198+ Q_INVOKABLE void pendingActivation();
199+
200+ void setRootFocus(bool focus);
201+ bool rootFocus();
202+
165203Q_SIGNALS:
166204 void countChanged();
167205 void inputMethodSurfaceChanged(unity::shell::application::MirSurfaceInterface* inputMethodSurface);
@@ -176,7 +214,9 @@ Q_SIGNALS:
176214 */
177215 void listChanged();
178216
179− void nextIdChanged();
217+ void closedAllWindows();
218+
219+ void rootFocusChanged();
180220
181221private Q_SLOTS:
182222 void onSurfaceCreated(unity::shell::application::MirSurfaceInterface *surface);
@@ -197,6 +237,7 @@ private:
197237 void setFocusedWindow(Window *window);
198238 void removeInputMethodWindow();
199239 int findIndexOf(const unity::shell::application::MirSurfaceInterface *surface) const;
240+ void deleteAt(int index);
200241 void removeAt(int index);
201242
202243 void addApplication(unity::shell::application::ApplicationInfoInterface *application);
@@ -207,6 +248,7 @@ private:
207248 unity::shell::application::ApplicationInfoInterface *application);
208249 void prependSurfaceHelper(unity::shell::application::MirSurfaceInterface *surface,
209250 unity::shell::application::ApplicationInfoInterface *application);
251+ void prependWindow(Window *window, unity::shell::application::ApplicationInfoInterface *application);
210252
211253 void connectWindow(Window *window);
212254 void connectSurface(unity::shell::application::MirSurfaceInterface *surface);
@@ -220,6 +262,10 @@ private:
220262
221263 void activateTopMostWindowWithoutId(int forbiddenId);
222264
265+ Window *createWindow(unity::shell::application::MirSurfaceInterface *surface);
266+ Window *createWindowWithId(unity::shell::application::MirSurfaceInterface *surface, int id);
267+ Window *createNullWindow();
268+
223269 struct ModelEntry {
224270 ModelEntry() {}
225271 ModelEntry(Window *window,
@@ -233,15 +279,15 @@ private:
233279 QVector<ModelEntry> m_windowModel;
234280 Window* m_inputMethodWindow{nullptr};
235281 Window* m_focusedWindow{nullptr};
282+ Window* m_nullWindow;
283+ Window* m_previousWindow{nullptr};
284+ bool m_pendingActivation;
236285
237− int m_nextId{1};
238− // Just something big enough that we don't risk running out of unused id numbers.
239− // Not sure if QML int type supports something close to std::numeric_limits<int>::max() and
240− // there's no reason to try out its limits.
241− static const int m_maxId{1000000};
286+ QAtomicInteger<int> m_nextId{1};
242287
243288 unity::shell::application::ApplicationManagerInterface* m_applicationManager{nullptr};
244289 unity::shell::application::SurfaceManagerInterface *m_surfaceManager{nullptr};
290+ bool m_surfaceManagerBusy;
245291
246292 enum ModelState {
247293 IdleState,
@@ -255,6 +301,8 @@ private:
255301 // Valid between modificationsStarted and modificationsEnded
256302 bool m_focusedWindowChanged{false};
257303 Window *m_newlyFocusedWindow{nullptr};
304+
305+ bool m_closingAllApps{false};
258306};
259307
260308#endif // TOPLEVELWINDOWMODEL_H
plugins/WindowManager/Window.cpp+41−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2016-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
@@ -27,6 +27,7 @@ namespace unityapi = unity::shell::application;
2727Q_LOGGING_CATEGORY(UNITY_WINDOW, "unity.window", QtWarningMsg)
2828
2929#define DEBUG_MSG qCDebug(UNITY_WINDOW).nospace() << qPrintable(toString()) << "::" << __func__
30+#define WARNING_MSG qCWarning(UNITY_WINDOW).nospace() << qPrintable(toString()) << "::" << __func__
3031
3132Window::Window(int id, QObject *parent)
3233 : QObject(parent)
@@ -67,6 +68,23 @@ void Window::setRequestedPosition(const QPoint &value)
6768 }
6869}
6970
71+bool Window::allowClientResize() const
72+{
73+ return m_allowClientResize;
74+}
75+
76+void Window::setAllowClientResize(bool value)
77+{
78+ if (value != m_allowClientResize) {
79+ DEBUG_MSG << "("<<value<<")";
80+ m_allowClientResize = value;
81+ if (m_surface) {
82+ m_surface->setAllowClientResize(value);
83+ }
84+ Q_EMIT allowClientResizeChanged(m_allowClientResize);
85+ }
86+}
87+
7088Mir::State Window::state() const
7189{
7290 return m_state;
@@ -154,13 +172,35 @@ void Window::setSurface(unityapi::MirSurfaceInterface *surface)
154172 updateFocused();
155173 });
156174
175+ connect(surface, &unityapi::MirSurfaceInterface::allowClientResizeChanged, this, [this]() {
176+ if (m_surface->allowClientResize() != m_allowClientResize) {
177+ m_allowClientResize = m_surface->allowClientResize();
178+ Q_EMIT allowClientResizeChanged(m_allowClientResize);
179+ }
180+ });
181+
182+ connect(surface, &unityapi::MirSurfaceInterface::liveChanged, this, &Window::liveChanged);
183+
184+ connect(surface, &QObject::destroyed, this, [this]() {
185+ setSurface(nullptr);
186+ });
187+
188+ // Surface should never be focused at this point!
189+ if (m_surface->focused()) {
190+ WARNING_MSG << "Inital surface is focused!";
191+ }
192+
157193 // bring it up to speed
194+ if (m_focused) {
195+ m_surface->activate();
196+ }
158197 if (m_positionRequested) {
159198 m_surface->setRequestedPosition(m_requestedPosition);
160199 }
161200 if (m_stateRequested && m_surface->state() == Mir::RestoredState) {
162201 m_surface->requestState(m_state);
163202 }
203+ m_surface->setAllowClientResize(m_allowClientResize);
164204
165205 // and sync with surface
166206 updatePosition();
plugins/WindowManager/Window.h+18−3
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2016-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
@@ -24,6 +24,8 @@
2424// Unity API
2525#include <unity/shell/application/Mir.h>
2626
27+#include "WindowManagerGlobal.h"
28+
2729namespace unity {
2830 namespace shell {
2931 namespace application {
@@ -32,7 +34,6 @@ namespace unity {
3234 }
3335}
3436
35−
3637Q_DECLARE_LOGGING_CATEGORY(UNITY_WINDOW)
3738
3839/**
@@ -43,7 +44,7 @@ Q_DECLARE_LOGGING_CATEGORY(UNITY_WINDOW)
4344 was killed to free up memory, as it should still remain in the window list since the user
4445 did not explicitly close it).
4546 */
46−class Window : public QObject
47+class WINDOWMANAGERQML_EXPORT Window : public QObject
4748{
4849 Q_OBJECT
4950
@@ -90,6 +91,13 @@ class Window : public QObject
9091 */
9192 Q_PROPERTY(unity::shell::application::MirSurfaceInterface* surface READ surface NOTIFY surfaceChanged)
9293
94+ /**
95+ * @brief Whether to comply to resize requests coming from the client side
96+ *
97+ * It's true by default
98+ */
99+ Q_PROPERTY(bool allowClientResize READ allowClientResize WRITE setAllowClientResize NOTIFY allowClientResizeChanged)
100+
93101public:
94102 Window(int id, QObject *parent = nullptr);
95103 virtual ~Window();
@@ -105,6 +113,9 @@ public:
105113 void setSurface(unity::shell::application::MirSurfaceInterface *surface);
106114 void setFocused(bool value);
107115
116+ bool allowClientResize() const;
117+ void setAllowClientResize(bool);
118+
108119 QString toString() const;
109120
110121public Q_SLOTS:
@@ -134,6 +145,8 @@ Q_SIGNALS:
134145 void focusedChanged(bool value);
135146 void confinesMousePointerChanged(bool value);
136147 void surfaceChanged(unity::shell::application::MirSurfaceInterface *surface);
148+ void allowClientResizeChanged(bool value);
149+ void liveChanged(bool value);
137150
138151 /**
139152 * @brief Emitted when focus for this window is requested by an external party
@@ -153,6 +166,8 @@ private:
153166 Mir::State m_state{Mir::RestoredState};
154167 bool m_stateRequested{false};
155168 unity::shell::application::MirSurfaceInterface *m_surface{nullptr};
169+
170+ bool m_allowClientResize{true};
156171};
157172
158173QDebug operator<<(QDebug dbg, const Window *window);
qml/Dash/DashBackground.qml → plugins/WindowManager/WindowManagerGlobal.hrenamed+7−5
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013, 2014 Canonical, Ltd.
2+ * Copyright (C) 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,8 +14,10 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−import QtQuick 2.4
17+#include <QtCore/QtGlobal>
1818
19−Rectangle {
20− color: "white"
21−}
19+#if defined(WINDOWMANAGERQML_LIBRARY)
20+# define WINDOWMANAGERQML_EXPORT Q_DECL_EXPORT
21+#else
22+# define WINDOWMANAGERQML_EXPORT Q_DECL_IMPORT
23+#endif
plugins/WindowManager/WindowManagerPlugin.cpp+14−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2016-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
@@ -16,14 +16,27 @@
1616
1717#include "WindowManagerPlugin.h"
1818
19+#include "AvailableDesktopArea.h"
1920#include "TopLevelWindowModel.h"
2021#include "Window.h"
22+#include "WindowMargins.h"
23+#include "InputMethodManager.h"
2124
2225#include <QtQml>
2326
27+QObject *inputMethodManager(QQmlEngine *engine, QJSEngine *scriptEngine)
28+{
29+ Q_UNUSED(engine)
30+ Q_UNUSED(scriptEngine)
31+ return InputMethodManager::instance();
32+}
33+
2434void WindowManagerPlugin::registerTypes(const char *uri)
2535{
36+ qmlRegisterType<AvailableDesktopArea>(uri, 1, 0, "AvailableDesktopArea");
2637 qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel");
38+ qmlRegisterType<WindowMargins>(uri, 1, 0, "WindowMargins");
39+ qmlRegisterSingletonType<InputMethodManager>(uri, 1, 0, "InputMethodManager", inputMethodManager);
2740
2841 qRegisterMetaType<Window*>("Window*");
2942
plugins/WindowManager/WindowMargins.cppnew file+74
@@ -0,0 +1,74 @@
1+/*
2+ * Copyright (C) 2017 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * 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+
17+#include "WindowMargins.h"
18+
19+#include <QGuiApplication>
20+#include <QQuickWindow>
21+#include <qpa/qplatformnativeinterface.h>
22+
23+void WindowMargins::setNormal(QRectF value)
24+{
25+ if (m_normal == value) {
26+ return;
27+ }
28+
29+ m_normal = value;
30+
31+ if (window()) {
32+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
33+ nativeInterface->setWindowProperty(window()->handle(), "normalWindowMargins", QVariant(m_normal.toRect()));
34+ }
35+
36+ Q_EMIT normalChanged();
37+}
38+
39+QRectF WindowMargins::normal() const
40+{
41+ return m_normal;
42+}
43+
44+void WindowMargins::setDialog(QRectF value)
45+{
46+ if (m_dialog == value) {
47+ return;
48+ }
49+
50+ m_dialog = value;
51+
52+ if (window()) {
53+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
54+ nativeInterface->setWindowProperty(window()->handle(), "dialogWindowMargins", QVariant(m_dialog.toRect()));
55+ }
56+
57+ Q_EMIT dialogChanged();
58+}
59+
60+QRectF WindowMargins::dialog() const
61+{
62+ return m_dialog;
63+}
64+
65+void WindowMargins::itemChange(ItemChange change, const ItemChangeData &data)
66+{
67+ if (change == ItemSceneChange && data.window != nullptr) {
68+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
69+ if (!m_normal.isNull()) {
70+ nativeInterface->setWindowProperty(data.window->handle(), "normalWindowMargins", QVariant(m_normal.toRect()));
71+ nativeInterface->setWindowProperty(data.window->handle(), "dialogWindowMargins", QVariant(m_dialog.toRect()));
72+ }
73+ }
74+}
plugins/WindowManager/WindowMargins.hnew file+59
@@ -0,0 +1,59 @@
1+/*
2+ * Copyright (C) 2017 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * 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+
17+#ifndef WINDOWMARGINS_H
18+#define WINDOWMARGINS_H
19+
20+#include <QQuickItem>
21+#include <QRectF>
22+
23+/*
24+ * Specifies window margins for different Mir window types
25+ *
26+ * Used to inform MirAL so that it can take window management decisions that match
27+ * the visuals drawn by Unity.
28+ */
29+class WindowMargins : public QQuickItem
30+{
31+ Q_OBJECT
32+
33+ // Margins for windows of normal type
34+ Q_PROPERTY(QRectF normal READ normal WRITE setNormal NOTIFY normalChanged)
35+
36+ // Margins for windows of dialog type
37+ Q_PROPERTY(QRectF dialog READ dialog WRITE setDialog NOTIFY dialogChanged)
38+
39+ // TODO: Add margins for other window types as needed
40+
41+public:
42+ QRectF normal() const;
43+ void setNormal(QRectF value);
44+
45+ QRectF dialog() const;
46+ void setDialog(QRectF value);
47+
48+protected:
49+ void itemChange(ItemChange change, const ItemChangeData &value) override;
50+
51+Q_SIGNALS:
52+ void normalChanged();
53+ void dialogChanged();
54+private:
55+ QRectF m_normal;
56+ QRectF m_dialog;
57+};
58+
59+#endif // WINDOWMARGINS_H
plugins/Wizard/CMakeLists.txt+5−2
@@ -10,10 +10,13 @@ add_library(Wizard-qml MODULE
1010 timezonemodel.cpp
1111 Status.cpp
1212 keyboardLayoutsModel.cpp
13+ Changelog.cpp
1314)
1415
15−qt5_use_modules(Wizard-qml DBus Qml)
16−target_link_libraries(Wizard-qml ${GD3_LDFLAGS} ${GLIB_LDFLAGS} ${GEONAMES_LDFLAGS})
16+target_link_libraries(Wizard-qml
17+ Qt5::DBus Qt5::Qml
18+ ${GD3_LDFLAGS} ${GLIB_LDFLAGS} ${GEONAMES_LDFLAGS}
19+)
1720add_unity8_plugin(Wizard 0.1 Wizard TARGETS Wizard-qml)
1821
1922set(POLKIT_LIB_DIR "${CMAKE_INSTALL_LOCALSTATEDIR}/lib/polkit-1")
plugins/Wizard/Changelog.cppnew file+58
@@ -0,0 +1,58 @@
1+/*
2+ * Copyright (C) 2018 The UBports project
3+ * Written by: Marius Gripsgard <marius@ubports.com>
4+ *
5+ * This program is free software: you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 3, as published
7+ * by the Free Software Foundation.
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 GNU General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU General Public License along
15+ * with this program. If not, see <http://www.gnu.org/licenses/>.
16+ */
17+
18+#include "Changelog.h"
19+
20+#include <QDir>
21+#include <QFile>
22+#include <QTextStream>
23+
24+Changelog::Changelog()
25+ : QObject()
26+{
27+ readChangelog();
28+ if(QFile::exists(changelogPath()))
29+ m_fsWatcher.addPath(changelogPath());
30+ connect(&m_fsWatcher, &QFileSystemWatcher::fileChanged, this, &Changelog::watcherFileChanged);
31+}
32+
33+QString Changelog::changelogPath()
34+{
35+ return "/usr/share/ubports/changelogs/current";
36+}
37+
38+QString Changelog::text() const
39+{
40+ return m_text;
41+}
42+
43+void Changelog::readChangelog()
44+{
45+ if(!QFile::exists(changelogPath()))
46+ return;
47+ QFile f(changelogPath());
48+ if (!f.open(QFile::ReadOnly | QFile::Text)) return;
49+ QTextStream in(&f);
50+ m_text = in.readAll();
51+ Q_EMIT textChanged();
52+}
53+
54+void Changelog::watcherFileChanged()
55+{
56+ readChangelog();
57+ m_fsWatcher.removePath(changelogPath());
58+}
plugins/Wizard/Changelog.hnew file+52
@@ -0,0 +1,52 @@
1+/*
2+ * Copyright (C) 2018 The UBports project
3+ * Written by: Marius Gripsgard <marius@ubports.com>
4+ *
5+ * This program is free software: you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 3, as published
7+ * by the Free Software Foundation.
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 GNU General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU General Public License along
15+ * with this program. If not, see <http://www.gnu.org/licenses/>.
16+ */
17+
18+#ifndef WIZARD_CHANGELOG_H
19+#define WIZARD_CHANGELOG_H
20+
21+#include <QFileSystemWatcher>
22+#include <QObject>
23+#include <QString>
24+
25+class Changelog : public QObject
26+{
27+ Q_OBJECT
28+ Q_PROPERTY(QString text READ text NOTIFY textChanged)
29+
30+public:
31+ Changelog();
32+ ~Changelog() = default;
33+
34+ QString text() const;
35+
36+Q_SIGNALS:
37+ void textChanged();
38+
39+private Q_SLOTS:
40+ void watcherFileChanged();
41+
42+private:
43+ Q_DISABLE_COPY(Changelog)
44+
45+ static QString changelogPath();
46+ void readChangelog();
47+
48+ QFileSystemWatcher m_fsWatcher;
49+ QString m_text;
50+};
51+
52+#endif
plugins/Wizard/PageList.cpp+6−5
@@ -46,9 +46,7 @@ PageList::PageList(QObject *parent)
4646 QSet<QString> disabledPages;
4747 QStringList dataDirs;
4848
49− if (getenv("WIZARD_TESTING") != nullptr) {
50− dataDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
51− } else if (!isRunningInstalled()) {
49+ if (!isRunningInstalled() && getenv("WIZARD_TESTING") == nullptr) {
5250 dataDirs << qmlDirectory();
5351 } else {
5452 dataDirs = shellDataDirs();
@@ -73,8 +71,11 @@ PageList::PageList(QObject *parent)
7371 // If there was a system update installed, skip until the last page to just greet the user
7472 QSettings settings;
7573 if (settings.value(QStringLiteral("Wizard/SkipUntilFinishedPage")).toBool()) {
76− while (m_pages.count() > 1) {
77− m_pages.erase(m_pages.begin());
74+ const QString lastPage = m_pages.lastKey();
75+ Q_FOREACH(const QString &page, m_pages.keys()) {
76+ if (Q_UNLIKELY(page != lastPage)) {
77+ m_pages.remove(page);
78+ }
7879 }
7980
8081 // ... and reset it again for the next run
plugins/Wizard/System.cpp+69−7
@@ -1,4 +1,5 @@
11/*
2+ * Copyright (C) 2018 The UBports project
23 * Copyright (C) 2014-2016 Canonical Ltd.
34 *
45 * This program is free software: you can redistribute it and/or modify it
@@ -46,29 +47,93 @@ QString System::wizardEnabledPath()
4647 return QDir::home().filePath(QStringLiteral(".config/ubuntu-system-settings/wizard-has-run"));
4748}
4849
50+QString System::currentFrameworkPath()
51+{
52+ QFileInfo f("/usr/share/click/frameworks/current");
53+ return f.canonicalFilePath();
54+}
55+
56+/*
57+wizardEnabled and isUpdate logic
58+
59+if wizard-has-run does NOT exist == is new install
60+if wizard-has-run exists but does NOT match current framework == is update
61+if wizard-has-run exists but does match current framework == show no wizard
62+*/
63+
64+bool System::wizardPathExists() {
65+ return QFile::exists(wizardEnabledPath());
66+}
67+
4968bool System::wizardEnabled() const
5069{
51− return !QFile::exists(wizardEnabledPath());
70+ if (!wizardPathExists()) {
71+ return true;
72+ }
73+ return isUpdate();
74+}
75+
76+QString System::readCurrentFramework()
77+{
78+ QFile f(currentFrameworkPath());
79+ if (!f.open(QFile::ReadOnly | QFile::Text)) return "";
80+ QTextStream in(&f);
81+ return in.readAll();
82+}
83+
84+QString System::readWizardEnabled()
85+{
86+ QFile f(wizardEnabledPath());
87+ if (!f.open(QFile::ReadOnly | QFile::Text)) return "";
88+ QTextStream in(&f);
89+ return in.readAll();
90+}
91+
92+QString System::version() const
93+{
94+ return readCurrentFramework();
95+}
96+
97+bool System::isUpdate() const
98+{
99+ if (!wizardPathExists()) {
100+ return false;
101+ }
102+
103+ return readCurrentFramework() != readWizardEnabled();
52104}
53105
54106void System::setWizardEnabled(bool enabled)
55107{
56− if (wizardEnabled() == enabled)
108+ if (wizardEnabled() == enabled && !isUpdate())
57109 return;
58110
59111 if (enabled) {
60112 QFile::remove(wizardEnabledPath());
61113 } else {
62114 QDir(wizardEnabledPath()).mkpath(QStringLiteral(".."));
63− QFile(wizardEnabledPath()).open(QIODevice::WriteOnly);
115+ if (QFile::exists(wizardEnabledPath())) {
116+ QFile::remove(wizardEnabledPath());
117+ }
118+ // For special cases check if wizardEnabledPath is a folder
119+ if (QDir(wizardEnabledPath()).exists()) {
120+ QDir(wizardEnabledPath()).removeRecursively();
121+ }
122+ if (!QFile::copy(currentFrameworkPath(), wizardEnabledPath())) {
123+ // Make en empty file if framework does not exist
124+ QFile f(wizardEnabledPath());
125+ f.open(QFile::WriteOnly);
126+ }
64127 m_fsWatcher.addPath(wizardEnabledPath());
65128 Q_EMIT wizardEnabledChanged();
129+ Q_EMIT isUpdateChanged();
66130 }
67131}
68132
69133void System::watcherFileChanged()
70134{
71135 Q_EMIT wizardEnabledChanged();
136+ Q_EMIT isUpdateChanged();
72137 m_fsWatcher.removePath(wizardEnabledPath());
73138}
74139
@@ -103,13 +168,10 @@ void System::updateSessionLocale(const QString &locale)
103168
104169 // Restart bits of the session to pick up new language.
105170 QProcess::startDetached(QStringLiteral("sh -c \"initctl emit indicator-services-end; \
106− initctl stop scope-registry; \
107− initctl stop smart-scopes-proxy; \
108171 initctl emit --no-wait indicator-services-start; \
109172 initctl restart --no-wait ubuntu-location-service-trust-stored; \
110173 initctl restart --no-wait maliit-server; \
111− initctl restart --no-wait indicator-messages; \
112− initctl restart --no-wait unity8-dash\""));
174+ initctl restart --no-wait indicator-messages"));
113175}
114176
115177void System::skipUntilFinishedPage()
plugins/Wizard/System.h+17
@@ -1,4 +1,5 @@
11/*
2+ * Copyright (C) 2018 The UBports project
23 * Copyright (C) 2014-2016 Canonical Ltd.
34 *
45 * This program is free software: you can redistribute it and/or modify it
@@ -18,6 +19,7 @@
1819#define WIZARD_SYSTEM_H
1920
2021#include <QFileSystemWatcher>
22+#include <QVersionNumber>
2123#include <QObject>
2224#include <QString>
2325
@@ -25,12 +27,21 @@ class System : public QObject
2527{
2628 Q_OBJECT
2729 Q_PROPERTY(bool wizardEnabled READ wizardEnabled WRITE setWizardEnabled NOTIFY wizardEnabledChanged)
30+ Q_PROPERTY(QString version READ version NOTIFY versionChanged)
31+ Q_PROPERTY(bool isUpdate READ isUpdate NOTIFY isUpdateChanged)
2832
2933public:
3034 System();
3135 ~System() = default;
3236
37+ /**
38+ * Checks whether the wizard is enabled for first-run or otherwise.
39+ */
3340 bool wizardEnabled() const;
41+
42+ QString version() const;
43+ bool isUpdate() const;
44+
3445 void setWizardEnabled(bool enabled);
3546
3647public Q_SLOTS:
@@ -42,6 +53,8 @@ public Q_SLOTS:
4253
4354Q_SIGNALS:
4455 void wizardEnabledChanged();
56+ void versionChanged();
57+ void isUpdateChanged();
4558
4659private Q_SLOTS:
4760 void watcherFileChanged();
@@ -50,7 +63,11 @@ private:
5063 Q_DISABLE_COPY(System)
5164
5265 static QString wizardEnabledPath();
66+ static QString currentFrameworkPath();
5367 static void setSessionVariable(const QString &variable, const QString &value);
68+ static QString readCurrentFramework();
69+ static QString readWizardEnabled();
70+ static bool wizardPathExists();
5471
5572 QFileSystemWatcher m_fsWatcher;
5673};
plugins/Wizard/Utils/CMakeLists.txt+1−1
@@ -20,7 +20,7 @@ add_library(WizardUtils-qml SHARED
2020# files directly in targets.
2121set_target_properties(WizardUtils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
2222
23−qt5_use_modules(WizardUtils-qml DBus Qml Quick)
23+target_link_libraries(WizardUtils-qml Qt5::DBus Qt5::Qml Qt5::Quick)
2424
2525set(PLUG_DIR ${PLUGIN_PRIVATE_MODULE_DIR}/Ubuntu/SystemSettings/Wizard/Utils)
2626install(FILES qmldir DESTINATION ${PLUG_DIR})
plugins/Wizard/plugin.cpp+2
@@ -20,6 +20,7 @@
2020#include "timezonemodel.h"
2121#include "LocalePlugin.h"
2222#include "Status.h"
23+#include "Changelog.h"
2324#include "keyboardLayoutsModel.h"
2425
2526#include <QtQml/qqml.h>
@@ -30,6 +31,7 @@ void WizardPlugin::registerTypes(const char *uri)
3031 qmlRegisterType<PageList>(uri, 0, 1, "PageList");
3132 qmlRegisterSingletonType<System>(uri, 0, 1, "System", [](QQmlEngine*, QJSEngine*) -> QObject* { return new System; });
3233 qmlRegisterSingletonType<Status>(uri, 0, 1, "Status", [](QQmlEngine*, QJSEngine*) -> QObject* { return new Status; });
34+ qmlRegisterSingletonType<Changelog>(uri, 0, 1, "Changelog", [](QQmlEngine*, QJSEngine*) -> QObject* { return new Changelog; });
3335 qmlRegisterType<TimeZoneLocationModel>(uri, 0, 1, "TimeZoneModel");
3436 qmlRegisterType<KeyboardLayoutsModel>(uri, 0, 1, "KeyboardLayoutsModel");
3537 qmlRegisterType<LocalePlugin>(uri, 0, 1, "LocalePlugin");
plugins/Wizard/test.shdeleted−18
@@ -1,18 +0,0 @@
1−#!/bin/sh
2−
3−TOPDIR=$(readlink -e "$(dirname ${0})/..")
4−
5−LOCAL_PRIVATE_DIR=$(ls -d ${TOPDIR}/debian/tmp/usr/lib/*/ubuntu-system-settings/private)
6−if [ -n ${LOCAL_PRIVATE_DIR} ]; then
7− echo "Testing against locally built version"
8− export UBUNTU_SYSTEM_SETTINGS_WIZARD_ROOT="${TOPDIR}/debian/tmp/usr/share"
9− export UBUNTU_SYSTEM_SETTINGS_WIZARD_MODULES="${LOCAL_PRIVATE_DIR}"
10− export QML2_IMPORT_PATH=${LOCAL_PRIVATE_DIR}:${QML2_IMPORT_PATH}
11− export PATH=${TOPDIR}/debian/tmp/usr/bin:${PATH}
12−else
13− echo "Testing against system version"
14−fi
15−
16−export QML2_IMPORT_PATH=${TOPDIR}/tests/mocks:${QML2_IMPORT_PATH}
17−
18−exec system-settings-wizard
plugins/Wizard/timezonemodel.h+1−1
@@ -27,6 +27,7 @@ class TimeZoneLocationModel: public QAbstractListModel
2727 Q_PROPERTY(bool listUpdating READ listUpdating NOTIFY listUpdatingChanged)
2828 Q_PROPERTY(QString filter READ filter WRITE setFilter NOTIFY filterChanged)
2929 Q_PROPERTY(QString country READ country WRITE setCountry NOTIFY countryChanged)
30+ Q_ENUMS(Roles)
3031
3132public:
3233 explicit TimeZoneLocationModel(QObject *parent = nullptr);
@@ -41,7 +42,6 @@ public:
4142 LatitudeRole,
4243 LongitudeRole
4344 };
44− Q_ENUM(Roles)
4545
4646 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
4747 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
po/aa.po+231−324
@@ -6,28 +6,58 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
9−"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2017-01-10 14:48+0000\n"
11−"PO-Revision-Date: 2016-02-12 10:18+0000\n"
12−"Last-Translator: Charif AYFARAH <ayfarah@ymail.com>\n"
13−"Language-Team: Afar <aa@li.org>\n"
9+"Report-Msgid-Bugs-To: \n"
10+"POT-Creation-Date: 2021-01-29 11:42-0600\n"
11+"PO-Revision-Date: 2021-03-08 10:42+0000\n"
12+"Last-Translator: TigranKhachatryan0 <tigrank2008@gmail.com>\n"
13+"Language-Team: Afar <https://translate.ubports.com/projects/ubports/lomiri/"
14+"aa/>\n"
15+"Language: aa\n"
1416"MIME-Version: 1.0\n"
1517"Content-Type: text/plain; charset=UTF-8\n"
1618"Content-Transfer-Encoding: 8bit\n"
1719"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2017-01-16 05:47+0000\n"
19−"X-Generator: Launchpad (build 18302)\n"
20+"X-Generator: Weblate 3.11.3\n"
21+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
2022
21−#: plugins/LightDM/Greeter.cpp:123
23+#: plugins/LightDM/Greeter.cpp:199
2224msgid "Password: "
23−msgstr "Cuumita "
25+msgstr ""
26+
27+#: plugins/LightDM/Greeter.cpp:214
28+msgid "Username"
29+msgstr ""
30+
31+#: plugins/LightDM/Greeter.cpp:258
32+msgid "Failed to authenticate"
33+msgstr ""
34+
35+#: plugins/LightDM/Greeter.cpp:260
36+msgid "Invalid password, please try again"
37+msgstr ""
38+
39+#: plugins/LightDM/Greeter.cpp:270
40+msgid "Log In"
41+msgstr ""
42+
43+#: plugins/LightDM/Greeter.cpp:270
44+msgid "Retry"
45+msgstr "Qagis"
2446
25−#: plugins/Unity/Launcher/launcheritem.cpp:50
47+#: plugins/LightDM/UsersModel.cpp:157
48+msgid "Login"
49+msgstr ""
50+
51+#: plugins/LightDM/UsersModel.cpp:165
52+msgid "Guest Session"
53+msgstr ""
54+
55+#: plugins/Unity/Launcher/launcheritem.cpp:48
2656#: plugins/Unity/Launcher/launcheritem.cpp:122
2757msgid "Pin shortcut"
2858msgstr ""
2959
30−#: plugins/Unity/Launcher/launcheritem.cpp:55
60+#: plugins/Unity/Launcher/launcheritem.cpp:54
3161msgid "Quit"
3262msgstr "Kat"
3363
@@ -35,76 +65,79 @@ msgstr "Kat"
3565msgid "Unpin shortcut"
3666msgstr ""
3767
38−#: qml/Components/Dialogs.qml:149
68+#: qml/Components/Dialogs.qml:176
3969msgctxt "Title: Lock/Log out dialog"
4070msgid "Log out"
4171msgstr "Eweq"
4272
43−#: qml/Components/Dialogs.qml:150
73+#: qml/Components/Dialogs.qml:177
4474msgid "Are you sure you want to log out?"
4575msgstr ""
4676
47−#: qml/Components/Dialogs.qml:152
77+#: qml/Components/Dialogs.qml:180
4878msgctxt "Button: Lock the system"
4979msgid "Lock"
5080msgstr "Koflis"
5181
52−#: qml/Components/Dialogs.qml:160
82+#: qml/Components/Dialogs.qml:191
5383msgctxt "Button: Log out from the system"
5484msgid "Log Out"
5585msgstr "Eweq"
5686
57−#: qml/Components/Dialogs.qml:167 qml/Components/Dialogs.qml:225
58−#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:232
59−#: qml/Wizard/Pages/passcode-confirm.qml:32
87+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
88+#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
6089#: qml/Wizard/Pages/passcode-set.qml:32
6190msgid "Cancel"
6291msgstr "Bayis"
6392
64−#: qml/Components/Dialogs.qml:179
93+#: qml/Components/Dialogs.qml:211
6594msgctxt "Title: Reboot dialog"
6695msgid "Reboot"
6796msgstr "Wadir-ugus"
6897
69−#: qml/Components/Dialogs.qml:180
98+#: qml/Components/Dialogs.qml:212
7099msgid "Are you sure you want to reboot?"
71100msgstr "Wadir-ugussuh digga maay litoo?"
72101
73−#: qml/Components/Dialogs.qml:182
102+#: qml/Components/Dialogs.qml:215
74103msgid "No"
75104msgstr "Maleey"
76105
77−#: qml/Components/Dialogs.qml:189
106+#: qml/Components/Dialogs.qml:223
78107msgid "Yes"
79108msgstr "Yeey"
80109
81−#: qml/Components/Dialogs.qml:204
110+#: qml/Components/Dialogs.qml:243
82111msgctxt "Title: Power off/Restart dialog"
83112msgid "Power"
84113msgstr "Cayla"
85114
86−#: qml/Components/Dialogs.qml:205
115+#: qml/Components/Dialogs.qml:244
87116msgid ""
88117"Are you sure you would like\n"
89118"to power off?"
90119msgstr "Timmi haytuh digga maay litoo?"
91120
92−#: qml/Components/Dialogs.qml:208
121+#: qml/Components/Dialogs.qml:248
93122msgctxt "Button: Power off the system"
94123msgid "Power off"
95124msgstr "Timmi hayis"
96125
97−#: qml/Components/Dialogs.qml:217
126+#: qml/Components/Dialogs.qml:263
98127msgctxt "Button: Restart the system"
99128msgid "Restart"
100129msgstr "Wadir-qimbis"
101130
131+#: qml/Components/Dialogs.qml:276
132+msgid "Screenshot"
133+msgstr ""
134+
102135#: qml/Components/KeyboardShortcutsOverlay.qml:41
103136msgid "Keyboard Shortcuts"
104137msgstr ""
105138
106139#: qml/Components/KeyboardShortcutsOverlay.qml:55
107−msgid "Unity 8"
140+msgid "Lomiri"
108141msgstr ""
109142
110143#: qml/Components/KeyboardShortcutsOverlay.qml:62
@@ -120,7 +153,7 @@ msgid "Alt + PrtScr"
120153msgstr ""
121154
122155#: qml/Components/KeyboardShortcutsOverlay.qml:80
123−msgid "Takes a screenshot of a window."
156+msgid "Takes a screenshot of the current window."
124157msgstr ""
125158
126159#: qml/Components/KeyboardShortcutsOverlay.qml:88
@@ -139,135 +172,131 @@ msgstr ""
139172msgid "Switches to previous keyboard layout."
140173msgstr ""
141174
142−#: qml/Components/KeyboardShortcutsOverlay.qml:118
143−msgid "Launcher"
175+#: qml/Components/KeyboardShortcutsOverlay.qml:114
176+msgid "Ctrl + Alt + T"
144177msgstr ""
145178
146−#: qml/Components/KeyboardShortcutsOverlay.qml:125
147−msgid "Super (Hold)"
179+#: qml/Components/KeyboardShortcutsOverlay.qml:119
180+msgid "Starts the Terminal application."
148181msgstr ""
149182
150−#: qml/Components/KeyboardShortcutsOverlay.qml:130
151−msgid "Opens the launcher, displays shortcuts."
183+#: qml/Components/KeyboardShortcutsOverlay.qml:131
184+msgid "Launcher"
152185msgstr ""
153186
154187#: qml/Components/KeyboardShortcutsOverlay.qml:138
155−msgid "Alt + F1"
188+msgid "Super (Hold)"
156189msgstr ""
157190
158191#: qml/Components/KeyboardShortcutsOverlay.qml:143
159−msgid "Opens launcher keyboard navigation mode."
192+msgid "Opens the launcher, displays shortcuts."
160193msgstr ""
161194
162195#: qml/Components/KeyboardShortcutsOverlay.qml:151
163−msgid "Super + Tab"
196+msgid "Alt + F1"
164197msgstr ""
165198
166199#: qml/Components/KeyboardShortcutsOverlay.qml:156
167−msgid "Switches applications via the launcher."
200+msgid "Opens launcher keyboard navigation mode."
168201msgstr ""
169202
170203#: qml/Components/KeyboardShortcutsOverlay.qml:164
171−msgid "Super + 0 to 9"
204+msgid "Super + Tab"
172205msgstr ""
173206
174207#: qml/Components/KeyboardShortcutsOverlay.qml:169
175−msgid "Same as clicking on a launcher icon."
208+msgid "Switches applications via the launcher."
176209msgstr ""
177210
178211#: qml/Components/KeyboardShortcutsOverlay.qml:177
179−msgid "Super + A"
212+msgid "Super + 1 to 0"
180213msgstr ""
181214
182215#: qml/Components/KeyboardShortcutsOverlay.qml:182
183−msgid "Opens the Application Drawer."
184−msgstr ""
185−
186−#: qml/Components/KeyboardShortcutsOverlay.qml:194
187−msgid "Scopes"
216+msgid "Same as clicking on a launcher icon."
188217msgstr ""
189218
190−#: qml/Components/KeyboardShortcutsOverlay.qml:201
191−msgid "Super (Tap)"
219+#: qml/Components/KeyboardShortcutsOverlay.qml:190
220+msgid "Super + A"
192221msgstr ""
193222
194−#: qml/Components/KeyboardShortcutsOverlay.qml:206
195−msgid "Opens the Scopes home."
223+#: qml/Components/KeyboardShortcutsOverlay.qml:195
224+msgid "Opens the Application Drawer."
196225msgstr ""
197226
198−#: qml/Components/KeyboardShortcutsOverlay.qml:222
227+#: qml/Components/KeyboardShortcutsOverlay.qml:235
199228msgid "Switching"
200229msgstr ""
201230
202−#: qml/Components/KeyboardShortcutsOverlay.qml:229
231+#: qml/Components/KeyboardShortcutsOverlay.qml:242
203232msgid "Alt + Tab"
204233msgstr ""
205234
206−#: qml/Components/KeyboardShortcutsOverlay.qml:234
235+#: qml/Components/KeyboardShortcutsOverlay.qml:247
207236msgid "Switches between applications."
208237msgstr ""
209238
210−#: qml/Components/KeyboardShortcutsOverlay.qml:242
239+#: qml/Components/KeyboardShortcutsOverlay.qml:255
211240msgid "Super + W"
212241msgstr ""
213242
214−#: qml/Components/KeyboardShortcutsOverlay.qml:247
243+#: qml/Components/KeyboardShortcutsOverlay.qml:260
215244msgid "Opens the desktop spread."
216245msgstr ""
217246
218−#: qml/Components/KeyboardShortcutsOverlay.qml:255
247+#: qml/Components/KeyboardShortcutsOverlay.qml:268
219248msgid "Cursor Left or Right"
220249msgstr ""
221250
222−#: qml/Components/KeyboardShortcutsOverlay.qml:260
251+#: qml/Components/KeyboardShortcutsOverlay.qml:273
223252msgid "Moves the focus."
224253msgstr ""
225254
226−#: qml/Components/KeyboardShortcutsOverlay.qml:272
255+#: qml/Components/KeyboardShortcutsOverlay.qml:285
227256msgid "Windows"
228257msgstr ""
229258
230−#: qml/Components/KeyboardShortcutsOverlay.qml:279
259+#: qml/Components/KeyboardShortcutsOverlay.qml:292
231260msgid "Ctrl + Super + D"
232261msgstr ""
233262
234−#: qml/Components/KeyboardShortcutsOverlay.qml:284
263+#: qml/Components/KeyboardShortcutsOverlay.qml:297
235264msgid "Minimizes all windows."
236265msgstr ""
237266
238−#: qml/Components/KeyboardShortcutsOverlay.qml:292
267+#: qml/Components/KeyboardShortcutsOverlay.qml:305
239268msgid "Ctrl + Super + Up"
240269msgstr ""
241270
242−#: qml/Components/KeyboardShortcutsOverlay.qml:297
271+#: qml/Components/KeyboardShortcutsOverlay.qml:310
243272msgid "Maximizes the current window."
244273msgstr ""
245274
246−#: qml/Components/KeyboardShortcutsOverlay.qml:305
275+#: qml/Components/KeyboardShortcutsOverlay.qml:318
247276msgid "Ctrl + Super + Down"
248277msgstr ""
249278
250−#: qml/Components/KeyboardShortcutsOverlay.qml:310
279+#: qml/Components/KeyboardShortcutsOverlay.qml:323
251280msgid "Minimizes or restores the current window."
252281msgstr ""
253282
254−#: qml/Components/KeyboardShortcutsOverlay.qml:318
283+#: qml/Components/KeyboardShortcutsOverlay.qml:331
255284msgid "Ctrl + Super + Left or Right"
256285msgstr ""
257286
258−#: qml/Components/KeyboardShortcutsOverlay.qml:323
287+#: qml/Components/KeyboardShortcutsOverlay.qml:336
259288msgid "Semi-maximizes the current window."
260289msgstr ""
261290
262−#: qml/Components/KeyboardShortcutsOverlay.qml:331
291+#: qml/Components/KeyboardShortcutsOverlay.qml:344
263292msgid "Alt + F4"
264293msgstr ""
265294
266−#: qml/Components/KeyboardShortcutsOverlay.qml:336
295+#: qml/Components/KeyboardShortcutsOverlay.qml:349
267296msgid "Closes the current window."
268297msgstr ""
269298
270−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:252
299+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
271300msgid "Return to Call"
272301msgstr "Seecol gacis"
273302
@@ -275,7 +304,7 @@ msgstr "Seecol gacis"
275304msgid "Emergency Call"
276305msgstr ""
277306
278−#: qml/Components/Lockscreen.qml:244
307+#: qml/Components/Lockscreen.qml:245
279308msgid "OK"
280309msgstr "Hayya"
281310
@@ -289,29 +318,29 @@ msgstr ""
289318msgid "%1:%2"
290319msgstr ""
291320
292−#: qml/Components/ModeSwitchWarningDialog.qml:32
321+#: qml/Components/ModeSwitchWarningDialog.qml:33
293322msgid "Apps may have unsaved data:"
294323msgstr ""
295324
296−#: qml/Components/ModeSwitchWarningDialog.qml:57
325+#: qml/Components/ModeSwitchWarningDialog.qml:60
297326msgctxt ""
298327"Re-dock means connect the device again to an external screen/mouse/keyboard"
299328msgid "Re-dock, save your work and close these apps to continue."
300329msgstr ""
301330
302−#: qml/Components/ModeSwitchWarningDialog.qml:63
331+#: qml/Components/ModeSwitchWarningDialog.qml:67
303332msgid "Or force close now (unsaved data will be lost)."
304333msgstr ""
305334
306−#: qml/Components/ModeSwitchWarningDialog.qml:75
335+#: qml/Components/ModeSwitchWarningDialog.qml:80
307336msgid "OK, I will reconnect"
308337msgstr ""
309338
310−#: qml/Components/ModeSwitchWarningDialog.qml:76
339+#: qml/Components/ModeSwitchWarningDialog.qml:81
311340msgid "Reconnect now!"
312341msgstr ""
313342
314−#: qml/Components/ModeSwitchWarningDialog.qml:88
343+#: qml/Components/ModeSwitchWarningDialog.qml:94
315344msgid "Close all"
316345msgstr "Inkih alif"
317346
@@ -341,103 +370,6 @@ msgstr ""
341370msgid "Find more settings in the system settings."
342371msgstr ""
343372
344−#: qml/Dash/DashPageHeader.qml:361
345−msgctxt "Button: Open the Ubuntu Store"
346−msgid "Store"
347−msgstr ""
348−
349−#: qml/Dash/DashPageHeader.qml:368
350−msgctxt "Button: Start a search in the current dash scope"
351−msgid "Search"
352−msgstr "Goranto"
353−
354−#: qml/Dash/DashPageHeader.qml:378
355−msgctxt "Button: Show the current dash scope settings"
356−msgid "Settings"
357−msgstr "Massosu"
358−
359−#: qml/Dash/DashPageHeader.qml:385
360−msgid "Remove from Favorites"
361−msgstr ""
362−
363−#: qml/Dash/DashPageHeader.qml:385
364−msgid "Add to Favorites"
365−msgstr ""
366−
367−#: qml/Dash/FiltersPopover.qml:61
368−msgid "Refine your results"
369−msgstr ""
370−
371−#: qml/Dash/FiltersPopover.qml:70
372−msgid "Reset"
373−msgstr ""
374−
375−#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
376−msgid "Show less"
377−msgstr ""
378−
379−#: qml/Dash/GenericScopeView.qml:547
380−msgid "Show all"
381−msgstr ""
382−
383−#: qml/Dash/GenericScopeView.qml:578
384−msgctxt "Label: Hint for dash search line edit"
385−msgid "Search"
386−msgstr "Goranto"
387−
388−#: qml/Dash/PageHeaderExtraPanel.qml:67
389−msgid "Recent Searches"
390−msgstr ""
391−
392−#: qml/Dash/PageHeaderExtraPanel.qml:78
393−msgid "Clear All"
394−msgstr ""
395−
396−#: qml/Dash/Previews/PreviewActionCombo.qml:36
397−msgid "More..."
398−msgstr ""
399−
400−#: qml/Dash/Previews/PreviewActionCombo.qml:36
401−msgid "Less..."
402−msgstr ""
403−
404−#: qml/Dash/Previews/PreviewCommentInput.qml:83
405−#: qml/Dash/Previews/PreviewRatingInput.qml:202
406−msgid "Send"
407−msgstr "Rub"
408−
409−#: qml/Dash/Previews/PreviewRatingInput.qml:109
410−msgid "Rate this"
411−msgstr ""
412−
413−#: qml/Dash/Previews/PreviewRatingInput.qml:184
414−msgid "Add a review"
415−msgstr ""
416−
417−#: qml/Dash/PullToRefreshScopeStyle.qml:56
418−msgid "Pull to refresh…"
419−msgstr ""
420−
421−#: qml/Dash/PullToRefreshScopeStyle.qml:61
422−msgid "Release to refresh…"
423−msgstr ""
424−
425−#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
426−msgid "Enable location data"
427−msgstr ""
428−
429−#: qml/Dash/ScopesList.qml:146
430−msgid "Manage"
431−msgstr ""
432−
433−#: qml/Dash/ScopesList.qml:187
434−msgid "Home"
435−msgstr "Dabqi"
436−
437−#: qml/Dash/ScopesList.qml:188
438−msgid "Also installed"
439−msgstr ""
440−
441373#: qml/Greeter/CoverPage.qml:127
442374msgid "Unlock"
443375msgstr ""
@@ -461,45 +393,51 @@ msgid_plural "Please wait %1 minutes and then try again…"
461393msgstr[0] "Maganak %1 minit qambaalaay, kaadu gabbat"
462394msgstr[1] "Maganak %1 minit qambaalaay, kaadu gabbat"
463395
464−#: qml/Greeter/Greeter.qml:592
396+#: qml/Greeter/Greeter.qml:550
465397msgid "Try again"
466398msgstr ""
467399
468−#: qml/Greeter/LoginList.qml:70
469−msgid "Passphrase"
470−msgstr ""
400+#: qml/Greeter/Greeter.qml:551
401+#, fuzzy
402+#| msgid "Enter passphrase"
403+msgid "Enter passphrase to unlock"
404+msgstr "Tatur-maxco culus"
471405
472−#: qml/Greeter/LoginList.qml:71
473−msgid "Passcode"
474−msgstr ""
406+#: qml/Greeter/Greeter.qml:552
407+#, fuzzy
408+#| msgid "Enter passcode"
409+msgid "Enter passcode to unlock"
410+msgstr "Tatur-mudenta culus"
475411
476−#: qml/Greeter/LoginList.qml:98
477−msgid "Retry"
478−msgstr "Qagis"
412+#: qml/Greeter/NarrowView.qml:235
413+msgid "Emergency"
414+msgstr ""
479415
480−#: qml/Greeter/LoginList.qml:99
481−msgid "Log In"
416+#: qml/Greeter/PromptList.qml:126
417+msgid "Passphrase"
482418msgstr ""
483419
484−#: qml/Greeter/NarrowView.qml:252
485−msgid "Emergency"
420+#: qml/Greeter/PromptList.qml:126
421+msgid "Passcode"
486422msgstr ""
487423
488−#: qml/Greeter/SessionsList.qml:122
424+#: qml/Greeter/SessionsList.qml:124
489425msgid "Select desktop environment"
490426msgstr ""
491427
492−#: qml/Launcher/Drawer.qml:80
428+#: qml/Launcher/Drawer.qml:250
429+#, fuzzy
430+#| msgctxt "Button: Start a search in the current dash scope"
431+#| msgid "Search"
493432msgid "Search…"
494−msgstr ""
433+msgstr "Goranto"
495434
496−#: qml/Launcher/Drawer.qml:101
497−msgctxt "Apps sorted alphabetically"
498−msgid "A-Z"
435+#: qml/Launcher/PullToRefreshScopeStyle.qml:56
436+msgid "Pull to refresh…"
499437msgstr ""
500438
501−#: qml/Launcher/MoreAppsHeader.qml:32
502−msgid "More apps in the store"
439+#: qml/Launcher/PullToRefreshScopeStyle.qml:61
440+msgid "Release to refresh…"
503441msgstr ""
504442
505443#: qml/Notifications/NotificationMenuItemFactory.qml:124
@@ -589,23 +527,34 @@ msgctxt "Button: Call back on phone"
589527msgid "Call back"
590528msgstr ""
591529
530+#: qml/Panel/PanelMenuPage.qml:92
531+#, fuzzy
532+#| msgctxt "Button: Go back one page in the Wizard"
533+#| msgid "Back"
534+msgid "Back"
535+msgstr "Derre"
536+
592537#: qml/Stage/SideStage.qml:76
593538msgid "Drag using 3 fingers any application from one window to the other"
594539msgstr ""
595540
541+#: qml/Stage/Stage.qml:671
542+msgid "No running apps"
543+msgstr ""
544+
596545#: qml/Tutorial/TutorialLeftLong.qml:49
597−msgid "Long swipe from the left edge to open the Today scope"
546+msgid "Long swipe from the left edge to open the Application Drawer"
598547msgstr ""
599548
600549#: qml/Tutorial/TutorialLeft.qml:47
601550msgid "Short swipe from the left edge to open the launcher"
602551msgstr ""
603552
604−#: qml/Tutorial/TutorialRight.qml:55
553+#: qml/Tutorial/TutorialRight.qml:54
605554msgid "Push your mouse against the right edge to view your open apps"
606555msgstr ""
607556
608−#: qml/Tutorial/TutorialRight.qml:56
557+#: qml/Tutorial/TutorialRight.qml:55
609558msgid "Swipe from the right edge to view your open apps"
610559msgstr ""
611560
@@ -613,25 +562,41 @@ msgstr ""
613562msgid "Swipe from the top edge to access notifications and quick settings"
614563msgstr ""
615564
616−#: qml/Wizard/Page.qml:54
565+#: qml/Wizard/Page.qml:59
617566msgctxt "Button: Go back one page in the Wizard"
618567msgid "Back"
619568msgstr "Derre"
620569
621−#: qml/Wizard/Pages/10-welcome.qml:28
570+#: qml/Wizard/Pages/10-welcome.qml:29
622571msgid "Language"
623572msgstr ""
624573
625−#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
626−#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
627−#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
628−#: qml/Wizard/Pages/70-passwd-type.qml:145
629−#: qml/Wizard/Pages/75-report-check.qml:84
630−#: qml/Wizard/Pages/passcode-desktop.qml:142
631−#: qml/Wizard/Pages/password-set.qml:142
574+#: qml/Wizard/Pages/10-welcome.qml:176
575+#: qml/Wizard/Pages/10-welcome-update.qml:126
576+#: qml/Wizard/Pages/11-changelog.qml:74 qml/Wizard/Pages/20-keyboard.qml:152
577+#: qml/Wizard/Pages/30-wifi.qml:214 qml/Wizard/Pages/50-timezone.qml:272
578+#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/70-passwd-type.qml:146
579+#: qml/Wizard/Pages/passcode-desktop.qml:154
580+#: qml/Wizard/Pages/password-set.qml:153
632581msgid "Next"
633582msgstr ""
634583
584+#: qml/Wizard/Pages/10-welcome-update.qml:91
585+msgid "Welcome to "
586+msgstr ""
587+
588+#: qml/Wizard/Pages/10-welcome-update.qml:106
589+msgid "We will make sure your device is ready to use "
590+msgstr ""
591+
592+#: qml/Wizard/Pages/11-changelog.qml:28
593+msgid "What's new"
594+msgstr ""
595+
596+#: qml/Wizard/Pages/11-changelog.qml:74
597+msgid "Loading..."
598+msgstr ""
599+
635600#: qml/Wizard/Pages/20-keyboard.qml:31
636601msgid "Select Keyboard"
637602msgstr ""
@@ -644,8 +609,8 @@ msgstr ""
644609msgid "Keyboard layout"
645610msgstr ""
646611
647−#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
648−#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
612+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:214
613+#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/79-system-update.qml:144
649614#: qml/Wizard/Pages/sim.qml:101
650615msgid "Skip"
651616msgstr "Kaqit"
@@ -654,55 +619,23 @@ msgstr "Kaqit"
654619msgid "Connect to Wi‑Fi"
655620msgstr ""
656621
657−#: qml/Wizard/Pages/30-wifi.qml:132
622+#: qml/Wizard/Pages/30-wifi.qml:139
658623msgid "Connected"
659624msgstr ""
660625
661−#: qml/Wizard/Pages/30-wifi.qml:165
626+#: qml/Wizard/Pages/30-wifi.qml:172
662627msgid "Available Wi-Fi networks"
663628msgstr ""
664629
665−#: qml/Wizard/Pages/30-wifi.qml:166
630+#: qml/Wizard/Pages/30-wifi.qml:173
666631msgid "No available Wi-Fi networks"
667632msgstr ""
668633
669−#: qml/Wizard/Pages/40-location.qml:27
670−msgid "Location Services"
671−msgstr ""
672−
673−#: qml/Wizard/Pages/40-location.qml:83
674−msgid ""
675−"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
676−"(recommended)"
677−msgstr ""
678−
679−#: qml/Wizard/Pages/40-location.qml:105
680−#, qt-format
681−msgid "By selecting this option you agree to the Nokia HERE %1."
682−msgstr ""
683−
684−#: qml/Wizard/Pages/40-location.qml:106
685−msgctxt "part of: Nokia HERE terms and conditions"
686−msgid "terms and conditions"
687−msgstr ""
688−
689−#: qml/Wizard/Pages/40-location.qml:160
690−msgid "GPS only"
691−msgstr ""
692−
693−#: qml/Wizard/Pages/40-location.qml:214
694−msgid "Don't use my location"
695−msgstr ""
696−
697−#: qml/Wizard/Pages/40-location.qml:260
698−msgid "You can change it later in System Settings."
699−msgstr ""
700−
701634#: qml/Wizard/Pages/50-timezone.qml:30
702635msgid "Time Zone"
703636msgstr ""
704637
705−#: qml/Wizard/Pages/50-timezone.qml:182
638+#: qml/Wizard/Pages/50-timezone.qml:183
706639msgid "Enter your city"
707640msgstr ""
708641
@@ -710,7 +643,7 @@ msgstr ""
710643msgid "Personalize Your Device"
711644msgstr ""
712645
713−#: qml/Wizard/Pages/60-account.qml:48
646+#: qml/Wizard/Pages/60-account.qml:54
714647msgid "Preferred Name"
715648msgstr ""
716649
@@ -718,110 +651,72 @@ msgstr ""
718651msgid "Lock Screen"
719652msgstr ""
720653
721−#: qml/Wizard/Pages/70-passwd-type.qml:102
654+#: qml/Wizard/Pages/70-passwd-type.qml:103
722655msgctxt "Label: Type of security method"
723656msgid "Create new password"
724657msgstr ""
725658
726−#: qml/Wizard/Pages/70-passwd-type.qml:104
659+#: qml/Wizard/Pages/70-passwd-type.qml:105
727660msgctxt "Label: Type of security method"
728661msgid "Create passcode (numbers only)"
729662msgstr ""
730663
731−#: qml/Wizard/Pages/70-passwd-type.qml:106
664+#: qml/Wizard/Pages/70-passwd-type.qml:107
732665msgctxt "Label: Type of security method"
733666msgid "No lock code"
734667msgstr ""
735668
736−#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
737−msgid "Privacy Policy"
738−msgstr ""
739−
740−#: qml/Wizard/Pages/75-report-check.qml:26
741−msgid "Help Us Improve"
742−msgstr ""
743−
744−#: qml/Wizard/Pages/75-report-check.qml:59
745−msgid "Improve system performance by sending us crashes and error reports."
746−msgstr ""
747−
748−#: qml/Wizard/Pages/75-report-check.qml:60
749−msgid "Privacy policy"
750−msgstr ""
751−
752−#: qml/Wizard/Pages/77-system-update.qml:28
669+#: qml/Wizard/Pages/79-system-update.qml:28
753670msgid "Update Device"
754671msgstr ""
755672
756−#: qml/Wizard/Pages/77-system-update.qml:55
673+#: qml/Wizard/Pages/79-system-update.qml:55
757674msgid ""
758675"There is a system update available and ready to install. Afterwards, the "
759676"device will automatically restart."
760677msgstr ""
761678
762−#: qml/Wizard/Pages/77-system-update.qml:76
679+#: qml/Wizard/Pages/79-system-update.qml:76
763680msgctxt "string identifying name of the update"
764−msgid "Ubuntu system"
681+msgid "Ubuntu Touch system"
765682msgstr ""
766683
767−#: qml/Wizard/Pages/77-system-update.qml:83
684+#: qml/Wizard/Pages/79-system-update.qml:83
768685#, qt-format
769686msgctxt "version of the system update"
770687msgid "Version %1"
771688msgstr ""
772689
773−#: qml/Wizard/Pages/77-system-update.qml:102
690+#: qml/Wizard/Pages/79-system-update.qml:95
774691msgid "This could take a few minutes..."
775692msgstr ""
776693
777−#: qml/Wizard/Pages/77-system-update.qml:116
694+#: qml/Wizard/Pages/79-system-update.qml:109
778695msgid "Install and restart now"
779696msgstr ""
780697
781−#: qml/Wizard/Pages/80-finished.qml:89
782−msgid "Welcome to Ubuntu"
783−msgstr ""
784−
785−#: qml/Wizard/Pages/80-finished.qml:104
786−msgid "You are ready to use your device now"
698+#: qml/Wizard/Pages/80-finished.qml:91
699+msgid "Welcome Back"
787700msgstr ""
788701
789−#: qml/Wizard/Pages/80-finished.qml:124
790−msgid "Get Started"
791−msgstr ""
792−
793−#: qml/Wizard/Pages/here-terms.qml:25
794−msgid "Terms & Conditions"
795−msgstr ""
796−
797−#: qml/Wizard/Pages/here-terms.qml:69
798−msgid "Your device uses positioning technologies provided by HERE."
799−msgstr ""
800−
801−#: qml/Wizard/Pages/here-terms.qml:81
802−msgid ""
803−"To provide you with positioning services and to improve their quality, HERE "
804−"collects information about nearby cell towers and Wi-Fi hotspots around your "
805−"current location whenever your position is being found."
702+#: qml/Wizard/Pages/80-finished.qml:91
703+msgid "Welcome to Ubuntu"
806704msgstr ""
807705
808−#: qml/Wizard/Pages/here-terms.qml:93
809−msgid ""
810−"The information collected is used to analyze the service and to improve the "
811−"use of service, but not to identify you personally."
706+#: qml/Wizard/Pages/80-finished.qml:106
707+msgid "You are ready to use your device now"
812708msgstr ""
813709
814−#: qml/Wizard/Pages/here-terms.qml:106
815−#, qt-format
816−msgid "By continuing, you agree to the HERE platform %1 and %2."
817−msgstr ""
710+#: qml/Wizard/Pages/80-finished.qml:126
711+msgid "Continue"
712+msgstr "Tatur"
818713
819−#: qml/Wizard/Pages/here-terms.qml:107
820−msgid "Service Terms"
714+#: qml/Wizard/Pages/80-finished.qml:126
715+msgid "Get Started"
821716msgstr ""
822717
823718#: qml/Wizard/Pages/passcode-confirm.qml:43
824−#: qml/Wizard/Pages/passcode-desktop.qml:97
719+#: qml/Wizard/Pages/passcode-desktop.qml:104
825720msgid "Confirm passcode"
826721msgstr ""
827722
@@ -838,24 +733,24 @@ msgstr ""
838733msgid "Lock Screen Passcode"
839734msgstr ""
840735
841−#: qml/Wizard/Pages/passcode-desktop.qml:61
736+#: qml/Wizard/Pages/passcode-desktop.qml:68
842737msgid "Enter 4 numbers to setup your passcode"
843738msgstr ""
844739
845−#: qml/Wizard/Pages/passcode-desktop.qml:77
740+#: qml/Wizard/Pages/passcode-desktop.qml:84
846741#: qml/Wizard/Pages/passcode-set.qml:54
847742msgid "Choose passcode"
848743msgstr ""
849744
850−#: qml/Wizard/Pages/passcode-desktop.qml:127
745+#: qml/Wizard/Pages/passcode-desktop.qml:139
851746msgid "Passcode too short"
852747msgstr ""
853748
854−#: qml/Wizard/Pages/passcode-desktop.qml:129
749+#: qml/Wizard/Pages/passcode-desktop.qml:141
855750msgid "Passcodes match"
856751msgstr ""
857752
858−#: qml/Wizard/Pages/passcode-desktop.qml:131
753+#: qml/Wizard/Pages/passcode-desktop.qml:143
859754msgid "Passcodes do not match"
860755msgstr ""
861756
@@ -867,15 +762,15 @@ msgstr ""
867762msgid "Lock Screen Password"
868763msgstr ""
869764
870−#: qml/Wizard/Pages/password-set.qml:62
765+#: qml/Wizard/Pages/password-set.qml:68
871766msgid "Enter at least 8 characters"
872767msgstr ""
873768
874−#: qml/Wizard/Pages/password-set.qml:74
769+#: qml/Wizard/Pages/password-set.qml:80
875770msgid "Choose password"
876771msgstr ""
877772
878−#: qml/Wizard/Pages/password-set.qml:104
773+#: qml/Wizard/Pages/password-set.qml:110
879774msgid "Confirm password"
880775msgstr ""
881776
@@ -931,6 +826,28 @@ msgstr ""
931826msgid "Very weak password"
932827msgstr ""
933828
829+#~ msgctxt "Button: Show the current dash scope settings"
830+#~ msgid "Settings"
831+#~ msgstr "Massosu"
832+
833+#~ msgctxt "Label: Hint for dash search line edit"
834+#~ msgid "Search"
835+#~ msgstr "Goranto"
836+
837+#~ msgid "Send"
838+#~ msgstr "Rub"
839+
840+#~ msgid "Home"
841+#~ msgstr "Dabqi"
842+
843+#, fuzzy
844+#~ msgid "Download"
845+#~ msgstr "Qulluumah"
846+
847+#, fuzzy
848+#~ msgid "Downloaded"
849+#~ msgstr "Qulluumah"
850+
934851#~ msgctxt "Title: Reboot/Shut down dialog"
935852#~ msgid "Shut down"
936853#~ msgstr "Bargus"
@@ -946,16 +863,9 @@ msgstr ""
946863#~ msgid "Reboot"
947864#~ msgstr "Wadir-ugus"
948865
949−#, qt-format
950866#~ msgid "Enter %1"
951867#~ msgstr "%1 culus"
952868
953−#~ msgid "Enter passphrase"
954−#~ msgstr "Tatur-maxco culus"
955−
956−#~ msgid "Enter passcode"
957−#~ msgstr "Tatur-mudenta culus"
958−
959869#~ msgctxt "Label: Type of security method"
960870#~ msgid "Swipe"
961871#~ msgstr "Uysuttuc"
@@ -968,6 +878,3 @@ msgstr ""
968878
969879#~ msgid "Let’s get started."
970880#~ msgstr "Hayya qimbisnay."
971−
972−#~ msgid "Continue"
973−#~ msgstr "Tatur"
po/am.po+441−365
@@ -6,28 +6,58 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
9−"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2017-01-10 14:48+0000\n"
11−"PO-Revision-Date: 2016-08-13 14:45+0000\n"
12−"Last-Translator: samson <Unknown>\n"
13−"Language-Team: Amharic <am@li.org>\n"
9+"Report-Msgid-Bugs-To: \n"
10+"POT-Creation-Date: 2021-01-29 11:42-0600\n"
11+"PO-Revision-Date: 2021-08-29 20:18+0000\n"
12+"Last-Translator: Samson <sambelet@yahoo.com>\n"
13+"Language-Team: Amharic <https://translate.ubports.com/projects/ubports/"
14+"lomiri/am/>\n"
15+"Language: am\n"
1416"MIME-Version: 1.0\n"
1517"Content-Type: text/plain; charset=UTF-8\n"
1618"Content-Transfer-Encoding: 8bit\n"
1719"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2017-01-16 05:47+0000\n"
19−"X-Generator: Launchpad (build 18302)\n"
20+"X-Generator: Weblate 3.11.3\n"
21+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
2022
21−#: plugins/LightDM/Greeter.cpp:123
23+#: plugins/LightDM/Greeter.cpp:199
2224msgid "Password: "
2325msgstr "የ መግቢያ ቃል: "
2426
25−#: plugins/Unity/Launcher/launcheritem.cpp:50
27+#: plugins/LightDM/Greeter.cpp:214
28+msgid "Username"
29+msgstr "የ ተጠቃሚ ስም"
30+
31+#: plugins/LightDM/Greeter.cpp:258
32+msgid "Failed to authenticate"
33+msgstr "ማረጋገጥ አልተቻለም"
34+
35+#: plugins/LightDM/Greeter.cpp:260
36+msgid "Invalid password, please try again"
37+msgstr "ዋጋ የሌለው የ መግቢያ ቃል: እባክዎን እንደገና ይሞክሩ"
38+
39+#: plugins/LightDM/Greeter.cpp:270
40+msgid "Log In"
41+msgstr "መግቢያ"
42+
43+#: plugins/LightDM/Greeter.cpp:270
44+msgid "Retry"
45+msgstr "እንደገና ይሞክሩ"
46+
47+#: plugins/LightDM/UsersModel.cpp:157
48+msgid "Login"
49+msgstr "መግቢያ"
50+
51+#: plugins/LightDM/UsersModel.cpp:165
52+msgid "Guest Session"
53+msgstr "የ እንግዳ ክፍለ ጊዜ"
54+
55+#: plugins/Unity/Launcher/launcheritem.cpp:48
2656#: plugins/Unity/Launcher/launcheritem.cpp:122
2757msgid "Pin shortcut"
2858msgstr "አቋራጭ ማጣበቂያ"
2959
30−#: plugins/Unity/Launcher/launcheritem.cpp:55
60+#: plugins/Unity/Launcher/launcheritem.cpp:54
3161msgid "Quit"
3262msgstr "ማጥፊያ"
3363
@@ -35,55 +65,54 @@ msgstr "ማጥፊያ"
3565msgid "Unpin shortcut"
3666msgstr "አቋራጭ መለያያ"
3767
38−#: qml/Components/Dialogs.qml:149
68+#: qml/Components/Dialogs.qml:176
3969msgctxt "Title: Lock/Log out dialog"
4070msgid "Log out"
4171msgstr "መውጫ"
4272
43−#: qml/Components/Dialogs.qml:150
73+#: qml/Components/Dialogs.qml:177
4474msgid "Are you sure you want to log out?"
4575msgstr "በእርግጥ መውጣት ይፈልጋሉ?"
4676
47−#: qml/Components/Dialogs.qml:152
77+#: qml/Components/Dialogs.qml:180
4878msgctxt "Button: Lock the system"
4979msgid "Lock"
5080msgstr "መቆለፊያ"
5181
52−#: qml/Components/Dialogs.qml:160
82+#: qml/Components/Dialogs.qml:191
5383msgctxt "Button: Log out from the system"
5484msgid "Log Out"
5585msgstr "መውጫ"
5686
57−#: qml/Components/Dialogs.qml:167 qml/Components/Dialogs.qml:225
58−#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:232
59−#: qml/Wizard/Pages/passcode-confirm.qml:32
87+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
88+#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
6089#: qml/Wizard/Pages/passcode-set.qml:32
6190msgid "Cancel"
6291msgstr "መሰረዣ"
6392
64−#: qml/Components/Dialogs.qml:179
93+#: qml/Components/Dialogs.qml:211
6594msgctxt "Title: Reboot dialog"
6695msgid "Reboot"
6796msgstr "እንደገና ማስነሻ"
6897
69−#: qml/Components/Dialogs.qml:180
98+#: qml/Components/Dialogs.qml:212
7099msgid "Are you sure you want to reboot?"
71100msgstr "በእርግጥ እንደገና ማስነሳት ይፈልጋሉ?"
72101
73−#: qml/Components/Dialogs.qml:182
102+#: qml/Components/Dialogs.qml:215
74103msgid "No"
75104msgstr "አይ"
76105
77−#: qml/Components/Dialogs.qml:189
106+#: qml/Components/Dialogs.qml:223
78107msgid "Yes"
79108msgstr "አዎ"
80109
81−#: qml/Components/Dialogs.qml:204
110+#: qml/Components/Dialogs.qml:243
82111msgctxt "Title: Power off/Restart dialog"
83112msgid "Power"
84113msgstr "ሐይል"
85114
86−#: qml/Components/Dialogs.qml:205
115+#: qml/Components/Dialogs.qml:244
87116msgid ""
88117"Are you sure you would like\n"
89118"to power off?"
@@ -91,23 +120,27 @@ msgstr ""
91120"በእርግጥ ሐይሉን ማጥፋት\n"
92121"ይፈልጋሉ?"
93122
94−#: qml/Components/Dialogs.qml:208
123+#: qml/Components/Dialogs.qml:248
95124msgctxt "Button: Power off the system"
96125msgid "Power off"
97126msgstr "ሐይል ማጥፊያ"
98127
99−#: qml/Components/Dialogs.qml:217
128+#: qml/Components/Dialogs.qml:263
100129msgctxt "Button: Restart the system"
101130msgid "Restart"
102131msgstr "እንደገና ማስጀመሪያ"
103132
133+#: qml/Components/Dialogs.qml:276
134+msgid "Screenshot"
135+msgstr "መመልከቻ ፎቶ ማንሻ"
136+
104137#: qml/Components/KeyboardShortcutsOverlay.qml:41
105138msgid "Keyboard Shortcuts"
106139msgstr "የ ፊደል ገበታ አቋራጮች"
107140
108141#: qml/Components/KeyboardShortcutsOverlay.qml:55
109−msgid "Unity 8"
110−msgstr "Unity 8"
142+msgid "Lomiri"
143+msgstr "Lomiri"
111144
112145#: qml/Components/KeyboardShortcutsOverlay.qml:62
113146msgid "PrtScr"
@@ -122,8 +155,8 @@ msgid "Alt + PrtScr"
122155msgstr "Alt + PrtScr"
123156
124157#: qml/Components/KeyboardShortcutsOverlay.qml:80
125−msgid "Takes a screenshot of a window."
126−msgstr "የ መስኮት መመልከቻ ፎቶ ማንሻ"
158+msgid "Takes a screenshot of the current window."
159+msgstr "የ አሁኑን መስኮት መመልከቻ ፎቶ ማንሻ"
127160
128161#: qml/Components/KeyboardShortcutsOverlay.qml:88
129162msgid "Super + Space"
@@ -141,135 +174,131 @@ msgstr "Super + Shift + Space"
141174msgid "Switches to previous keyboard layout."
142175msgstr "ወዳለፈው የ ፊደል ገበታ እቅድ መቀየሪያ"
143176
144−#: qml/Components/KeyboardShortcutsOverlay.qml:118
177+#: qml/Components/KeyboardShortcutsOverlay.qml:114
178+msgid "Ctrl + Alt + T"
179+msgstr "Ctrl + Alt + T"
180+
181+#: qml/Components/KeyboardShortcutsOverlay.qml:119
182+msgid "Starts the Terminal application."
183+msgstr "የ ተርሚናል መተግበሪያ ማስጀመሪያ"
184+
185+#: qml/Components/KeyboardShortcutsOverlay.qml:131
145186msgid "Launcher"
146187msgstr "ማስነሻ"
147188
148−#: qml/Components/KeyboardShortcutsOverlay.qml:125
189+#: qml/Components/KeyboardShortcutsOverlay.qml:138
149190msgid "Super (Hold)"
150191msgstr "Super (ይጫኑ)"
151192
152−#: qml/Components/KeyboardShortcutsOverlay.qml:130
193+#: qml/Components/KeyboardShortcutsOverlay.qml:143
153194msgid "Opens the launcher, displays shortcuts."
154195msgstr "ማስነሻውን መክፈቻ እና አቋራጮች ማሳያ"
155196
156−#: qml/Components/KeyboardShortcutsOverlay.qml:138
197+#: qml/Components/KeyboardShortcutsOverlay.qml:151
157198msgid "Alt + F1"
158199msgstr "Alt + F1"
159200
160−#: qml/Components/KeyboardShortcutsOverlay.qml:143
201+#: qml/Components/KeyboardShortcutsOverlay.qml:156
161202msgid "Opens launcher keyboard navigation mode."
162203msgstr "መክፈቻ በ ፊደል ገበታ መቃኛ ዘዴ ማስነሻ"
163204
164−#: qml/Components/KeyboardShortcutsOverlay.qml:151
205+#: qml/Components/KeyboardShortcutsOverlay.qml:164
165206msgid "Super + Tab"
166207msgstr "Super + Tab"
167208
168−#: qml/Components/KeyboardShortcutsOverlay.qml:156
209+#: qml/Components/KeyboardShortcutsOverlay.qml:169
169210msgid "Switches applications via the launcher."
170211msgstr "መተግበሪያዎችን በ ማስጀመሪያ መቀየሪያ"
171212
172−#: qml/Components/KeyboardShortcutsOverlay.qml:164
173−msgid "Super + 0 to 9"
213+#: qml/Components/KeyboardShortcutsOverlay.qml:177
214+msgid "Super + 1 to 0"
174215msgstr "Super + 0 እስከ 9"
175216
176−#: qml/Components/KeyboardShortcutsOverlay.qml:169
217+#: qml/Components/KeyboardShortcutsOverlay.qml:182
177218msgid "Same as clicking on a launcher icon."
178219msgstr "ተመሳሳይ በ ማስጀመሪያ ምልክት ላይ እንደ መጫን"
179220
180−#: qml/Components/KeyboardShortcutsOverlay.qml:177
221+#: qml/Components/KeyboardShortcutsOverlay.qml:190
181222msgid "Super + A"
182−msgstr ""
223+msgstr "Super + A"
183224
184−#: qml/Components/KeyboardShortcutsOverlay.qml:182
225+#: qml/Components/KeyboardShortcutsOverlay.qml:195
185226msgid "Opens the Application Drawer."
186−msgstr ""
187−
188−#: qml/Components/KeyboardShortcutsOverlay.qml:194
189−msgid "Scopes"
190−msgstr "ክልል"
191−
192−#: qml/Components/KeyboardShortcutsOverlay.qml:201
193−msgid "Super (Tap)"
194−msgstr "Super (Tap)"
195−
196−#: qml/Components/KeyboardShortcutsOverlay.qml:206
197−msgid "Opens the Scopes home."
198−msgstr "የ ክልል ቤት መክፈቻ"
227+msgstr "የ መሳያ መተግበሪያ ማስጀመሪያ"
199228
200−#: qml/Components/KeyboardShortcutsOverlay.qml:222
229+#: qml/Components/KeyboardShortcutsOverlay.qml:235
201230msgid "Switching"
202231msgstr "በ መቀየር ላይ"
203232
204−#: qml/Components/KeyboardShortcutsOverlay.qml:229
233+#: qml/Components/KeyboardShortcutsOverlay.qml:242
205234msgid "Alt + Tab"
206235msgstr "Alt + Tab"
207236
208−#: qml/Components/KeyboardShortcutsOverlay.qml:234
237+#: qml/Components/KeyboardShortcutsOverlay.qml:247
209238msgid "Switches between applications."
210239msgstr "በ መተግበሪያዎች መካከል መቀያየሪያ"
211240
212−#: qml/Components/KeyboardShortcutsOverlay.qml:242
241+#: qml/Components/KeyboardShortcutsOverlay.qml:255
213242msgid "Super + W"
214243msgstr "Super + W"
215244
216−#: qml/Components/KeyboardShortcutsOverlay.qml:247
245+#: qml/Components/KeyboardShortcutsOverlay.qml:260
217246msgid "Opens the desktop spread."
218247msgstr "የ ዴስክቶፕ ማስፊያ መክፈቻ"
219248
220−#: qml/Components/KeyboardShortcutsOverlay.qml:255
249+#: qml/Components/KeyboardShortcutsOverlay.qml:268
221250msgid "Cursor Left or Right"
222251msgstr "መጠቆሚያ የ ግራ ወይንም የ ቀኝ"
223252
224−#: qml/Components/KeyboardShortcutsOverlay.qml:260
253+#: qml/Components/KeyboardShortcutsOverlay.qml:273
225254msgid "Moves the focus."
226255msgstr "ትኩረት ማንቀሳቀሻ"
227256
228−#: qml/Components/KeyboardShortcutsOverlay.qml:272
257+#: qml/Components/KeyboardShortcutsOverlay.qml:285
229258msgid "Windows"
230259msgstr "መስኮቶች"
231260
232−#: qml/Components/KeyboardShortcutsOverlay.qml:279
261+#: qml/Components/KeyboardShortcutsOverlay.qml:292
233262msgid "Ctrl + Super + D"
234263msgstr "Ctrl + Super + D"
235264
236−#: qml/Components/KeyboardShortcutsOverlay.qml:284
265+#: qml/Components/KeyboardShortcutsOverlay.qml:297
237266msgid "Minimizes all windows."
238267msgstr "ሁሉንም መስኮቶች ማሳነሻ"
239268
240−#: qml/Components/KeyboardShortcutsOverlay.qml:292
269+#: qml/Components/KeyboardShortcutsOverlay.qml:305
241270msgid "Ctrl + Super + Up"
242271msgstr "Ctrl + Super + Up"
243272
244−#: qml/Components/KeyboardShortcutsOverlay.qml:297
273+#: qml/Components/KeyboardShortcutsOverlay.qml:310
245274msgid "Maximizes the current window."
246275msgstr "የ አሁኑን መስኮት ማሳደጊያ"
247276
248−#: qml/Components/KeyboardShortcutsOverlay.qml:305
277+#: qml/Components/KeyboardShortcutsOverlay.qml:318
249278msgid "Ctrl + Super + Down"
250279msgstr "Ctrl + Super + Down"
251280
252−#: qml/Components/KeyboardShortcutsOverlay.qml:310
281+#: qml/Components/KeyboardShortcutsOverlay.qml:323
253282msgid "Minimizes or restores the current window."
254283msgstr "የ አሁኑን መስኮትማሳነሻ ወይንም እንደ ነበር መመለሻ"
255284
256−#: qml/Components/KeyboardShortcutsOverlay.qml:318
285+#: qml/Components/KeyboardShortcutsOverlay.qml:331
257286msgid "Ctrl + Super + Left or Right"
258287msgstr "Ctrl + Super + Left or Right"
259288
260−#: qml/Components/KeyboardShortcutsOverlay.qml:323
289+#: qml/Components/KeyboardShortcutsOverlay.qml:336
261290msgid "Semi-maximizes the current window."
262291msgstr "የ አሁኑን መስኮት በ ንዑስ-ማሳደጊያ"
263292
264−#: qml/Components/KeyboardShortcutsOverlay.qml:331
293+#: qml/Components/KeyboardShortcutsOverlay.qml:344
265294msgid "Alt + F4"
266295msgstr "Alt + F4"
267296
268−#: qml/Components/KeyboardShortcutsOverlay.qml:336
297+#: qml/Components/KeyboardShortcutsOverlay.qml:349
269298msgid "Closes the current window."
270299msgstr "የ አሁኑን መስኮት መዝጊያ"
271300
272−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:252
301+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
273302msgid "Return to Call"
274303msgstr "ወደ ጥሪ መመለሻ"
275304
@@ -277,7 +306,7 @@ msgstr "ወደ ጥሪ መመለሻ"
277306msgid "Emergency Call"
278307msgstr "የ ድንገተኛ ጥሪ"
279308
280−#: qml/Components/Lockscreen.qml:244
309+#: qml/Components/Lockscreen.qml:245
281310msgid "OK"
282311msgstr "እሺ"
283312
@@ -291,29 +320,29 @@ msgstr "%1:%2:%3"
291320msgid "%1:%2"
292321msgstr "%1:%2"
293322
294−#: qml/Components/ModeSwitchWarningDialog.qml:32
323+#: qml/Components/ModeSwitchWarningDialog.qml:33
295324msgid "Apps may have unsaved data:"
296325msgstr "መተግበሪያው ያልተቀመጠ ዳታ ይዟል:"
297326
298−#: qml/Components/ModeSwitchWarningDialog.qml:57
327+#: qml/Components/ModeSwitchWarningDialog.qml:60
299328msgctxt ""
300329"Re-dock means connect the device again to an external screen/mouse/keyboard"
301330msgid "Re-dock, save your work and close these apps to continue."
302331msgstr "እንደገና-ማሳረፊያ: ስራዎትን ያስቀምጡ እና ይዝጉ መተግበሪያው እንዲቀጥል"
303332
304−#: qml/Components/ModeSwitchWarningDialog.qml:63
333+#: qml/Components/ModeSwitchWarningDialog.qml:67
305334msgid "Or force close now (unsaved data will be lost)."
306335msgstr "ወይንም አሁን አስገድዶ ማጥፊያ (ያልተቀመጠ ዳታ ይጠፋል)"
307336
308−#: qml/Components/ModeSwitchWarningDialog.qml:75
337+#: qml/Components/ModeSwitchWarningDialog.qml:80
309338msgid "OK, I will reconnect"
310339msgstr "እሺ: እኔ አሁን እንደገና እገናኛለሁ"
311340
312−#: qml/Components/ModeSwitchWarningDialog.qml:76
341+#: qml/Components/ModeSwitchWarningDialog.qml:81
313342msgid "Reconnect now!"
314343msgstr "አሁን እንደገና መገናኛ!"
315344
316−#: qml/Components/ModeSwitchWarningDialog.qml:88
345+#: qml/Components/ModeSwitchWarningDialog.qml:94
317346msgid "Close all"
318347msgstr "ሁሉንም መዝጊያ"
319348
@@ -329,116 +358,19 @@ msgstr "የ እርስዎ አካል አሁን ከ ውጪ ማሳያ ጋር ተገ
329358
330359#: qml/Components/VirtualTouchPad.qml:327
331360msgid "Tap left button to click."
332−msgstr ""
361+msgstr "የ ግራ ቁልፍ መታ ያድርጉ ለ መጫን"
333362
334363#: qml/Components/VirtualTouchPad.qml:339
335364msgid "Tap right button to right click."
336−msgstr ""
365+msgstr "የ ቀኝ ቁልፍ መታ ያድርጉ በ ቀኝ ለ መጫን"
337366
338367#: qml/Components/VirtualTouchPad.qml:351
339368msgid "Swipe with two fingers to scroll."
340−msgstr ""
369+msgstr "ለ መሸብለል በ ሁለት ጣቶች ይጥረጉ"
341370
342371#: qml/Components/VirtualTouchPad.qml:396
343372msgid "Find more settings in the system settings."
344−msgstr ""
345−
346−#: qml/Dash/DashPageHeader.qml:361
347−msgctxt "Button: Open the Ubuntu Store"
348−msgid "Store"
349−msgstr "ማስቀመጫ"
350−
351−#: qml/Dash/DashPageHeader.qml:368
352−msgctxt "Button: Start a search in the current dash scope"
353−msgid "Search"
354−msgstr "መፈለጊያ"
355−
356−#: qml/Dash/DashPageHeader.qml:378
357−msgctxt "Button: Show the current dash scope settings"
358−msgid "Settings"
359−msgstr "ማሰናጃዎች"
360−
361−#: qml/Dash/DashPageHeader.qml:385
362−msgid "Remove from Favorites"
363−msgstr "ከምወዳቸው ማስወገጃ"
364−
365−#: qml/Dash/DashPageHeader.qml:385
366−msgid "Add to Favorites"
367−msgstr "ወደምወዳቸው መጨመሪያ"
368−
369−#: qml/Dash/FiltersPopover.qml:61
370−msgid "Refine your results"
371−msgstr "የ እርስዎን ውጤቶች እንደገና ማጣሪያ"
372−
373−#: qml/Dash/FiltersPopover.qml:70
374−msgid "Reset"
375−msgstr "እንደ ነበረ መመለሻ"
376−
377−#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
378−msgid "Show less"
379−msgstr "ትንሽ ማሳያ"
380−
381−#: qml/Dash/GenericScopeView.qml:547
382−msgid "Show all"
383−msgstr "ሁሉንም ማሳያ"
384−
385−#: qml/Dash/GenericScopeView.qml:578
386−msgctxt "Label: Hint for dash search line edit"
387−msgid "Search"
388−msgstr "መፈለጊያ"
389−
390−#: qml/Dash/PageHeaderExtraPanel.qml:67
391−msgid "Recent Searches"
392−msgstr "የ ቅርብ ጊዜ ፍለጋዎች"
393−
394−#: qml/Dash/PageHeaderExtraPanel.qml:78
395−msgid "Clear All"
396−msgstr "ሁሉንም ማጽጃ"
397−
398−#: qml/Dash/Previews/PreviewActionCombo.qml:36
399−msgid "More..."
400−msgstr "ተጨማሪ..."
401−
402−#: qml/Dash/Previews/PreviewActionCombo.qml:36
403−msgid "Less..."
404−msgstr "አነስተኛ..."
405−
406−#: qml/Dash/Previews/PreviewCommentInput.qml:83
407−#: qml/Dash/Previews/PreviewRatingInput.qml:202
408−msgid "Send"
409−msgstr "መላኪያ"
410−
411−#: qml/Dash/Previews/PreviewRatingInput.qml:109
412−msgid "Rate this"
413−msgstr "ለዚህ ደረጃ ይስጡ"
414−
415−#: qml/Dash/Previews/PreviewRatingInput.qml:184
416−msgid "Add a review"
417−msgstr "ግምገማ መጨመሪያ"
418−
419−#: qml/Dash/PullToRefreshScopeStyle.qml:56
420−msgid "Pull to refresh…"
421−msgstr "ይሳቡ ለማነቃቃት…"
422−
423−#: qml/Dash/PullToRefreshScopeStyle.qml:61
424−msgid "Release to refresh…"
425−msgstr "ይልቀቁ ለማነቃቃት…"
426−
427−#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
428−msgid "Enable location data"
429−msgstr "የአካባቢ ዳታ ማስቻያ"
430−
431−#: qml/Dash/ScopesList.qml:146
432−msgid "Manage"
433−msgstr "አስተዳዳሪ"
434−
435−#: qml/Dash/ScopesList.qml:187
436−msgid "Home"
437−msgstr "ቤት"
438−
439−#: qml/Dash/ScopesList.qml:188
440−msgid "Also installed"
441−msgstr "እንዲሁም የተገጠሙ"
373+msgstr "ተጨማሪ ማሰናጃ በ ስርአት ማሰናጃ ውስጥ መፈለጊያ"
442374
443375#: qml/Greeter/CoverPage.qml:127
444376msgid "Unlock"
@@ -463,46 +395,45 @@ msgid_plural "Please wait %1 minutes and then try again…"
463395msgstr[0] "እባክዎን ይቆዩ %1 ደቂቃ እና ከዛ እንደ ገና ይምክሩ…"
464396msgstr[1] "እባክዎን ይቆዩ %1 ደቂቃዎች እና ከዛ እንደ ገና ይምክሩ…"
465397
466−#: qml/Greeter/Greeter.qml:592
398+#: qml/Greeter/Greeter.qml:550
467399msgid "Try again"
468400msgstr "እንደገና ይሞክሩ"
469401
470−#: qml/Greeter/LoginList.qml:70
402+#: qml/Greeter/Greeter.qml:551
403+msgid "Enter passphrase to unlock"
404+msgstr "የ ማለፊያ ሀረግ ያስገቡ"
405+
406+#: qml/Greeter/Greeter.qml:552
407+msgid "Enter passcode to unlock"
408+msgstr "የ ማለፊያ ኮድ ያስገቡ ለ መክፈት"
409+
410+#: qml/Greeter/NarrowView.qml:235
411+msgid "Emergency"
412+msgstr "ድንገተኛ"
413+
414+#: qml/Greeter/PromptList.qml:126
471415msgid "Passphrase"
472416msgstr "የማለፊያ ሐረግ"
473417
474−#: qml/Greeter/LoginList.qml:71
418+#: qml/Greeter/PromptList.qml:126
475419msgid "Passcode"
476420msgstr "ማለፊያ ኮድ"
477421
478−#: qml/Greeter/LoginList.qml:98
479−msgid "Retry"
480−msgstr "እንደገና ይሞክሩ"
481−
482−#: qml/Greeter/LoginList.qml:99
483−msgid "Log In"
484−msgstr "መግቢያ"
485−
486−#: qml/Greeter/NarrowView.qml:252
487−msgid "Emergency"
488−msgstr "ድንገተኛ"
489−
490−#: qml/Greeter/SessionsList.qml:122
422+#: qml/Greeter/SessionsList.qml:124
491423msgid "Select desktop environment"
492424msgstr "የ ዴስክቶፕ አይነት ይምረጡ"
493425
494−#: qml/Launcher/Drawer.qml:80
426+#: qml/Launcher/Drawer.qml:250
495427msgid "Search…"
496−msgstr ""
428+msgstr "መፈለጊያ…"
497429
498−#: qml/Launcher/Drawer.qml:101
499−msgctxt "Apps sorted alphabetically"
500−msgid "A-Z"
501−msgstr ""
430+#: qml/Launcher/PullToRefreshScopeStyle.qml:56
431+msgid "Pull to refresh…"
432+msgstr "ይሳቡ ለማነቃቃት…"
502433
503−#: qml/Launcher/MoreAppsHeader.qml:32
504−msgid "More apps in the store"
505−msgstr ""
434+#: qml/Launcher/PullToRefreshScopeStyle.qml:61
435+msgid "Release to refresh…"
436+msgstr "ይልቀቁ ለማነቃቃት…"
506437
507438#: qml/Notifications/NotificationMenuItemFactory.qml:124
508439msgid "Show password"
@@ -591,23 +522,33 @@ msgctxt "Button: Call back on phone"
591522msgid "Call back"
592523msgstr "መልሶ መደወያ"
593524
525+#: qml/Panel/PanelMenuPage.qml:92
526+msgid "Back"
527+msgstr "ወደ ኋላ"
528+
594529#: qml/Stage/SideStage.qml:76
595530msgid "Drag using 3 fingers any application from one window to the other"
596531msgstr "መጎተቻ 3 ጣቶች በ መጠቀም ማንኛውንም መተግበሪያ ከ አንድ መስኮት ወደ ሌላ"
597532
533+#: qml/Stage/Stage.qml:671
534+msgid "No running apps"
535+msgstr ""
536+
598537#: qml/Tutorial/TutorialLeftLong.qml:49
599−msgid "Long swipe from the left edge to open the Today scope"
538+#, fuzzy
539+#| msgid "Long swipe from the left edge to open the Today scope"
540+msgid "Long swipe from the left edge to open the Application Drawer"
600541msgstr "በ ረጅሙ ከ ግራ ጠርዝ በኩል ይጥረጉ የ ዛሬን ክልል ለ መክፈት"
601542
602543#: qml/Tutorial/TutorialLeft.qml:47
603544msgid "Short swipe from the left edge to open the launcher"
604545msgstr "በ አጭሩ ይጥረጉ ከ ግራ ጠርዝ በኩል ማስጀመሪያውን ለ መክፈት"
605546
606−#: qml/Tutorial/TutorialRight.qml:55
547+#: qml/Tutorial/TutorialRight.qml:54
607548msgid "Push your mouse against the right edge to view your open apps"
608549msgstr "የ እርስዎን አይጥ መጠቆሚያ ወደ ቀኝ ጠርዝ በኩል ያስጠጉ የ ተከፈቱ መተግበሪያዎችን ለ መመልከት"
609550
610−#: qml/Tutorial/TutorialRight.qml:56
551+#: qml/Tutorial/TutorialRight.qml:55
611552msgid "Swipe from the right edge to view your open apps"
612553msgstr "ከ ቀኝ በኩል ይጥረጉ የ ተከፈቱ መተግበሪያዎችን ለ መመልከት"
613554
@@ -615,28 +556,44 @@ msgstr "ከ ቀኝ በኩል ይጥረጉ የ ተከፈቱ መተግበሪያዎ
615556msgid "Swipe from the top edge to access notifications and quick settings"
616557msgstr "ከ ላይ ጠረዝ በኩል ይጥረጉ ማስታወቂያዎች እና በፍጥነት ማሰናጃዎች ጋር ለ መድረስ"
617558
618−#: qml/Wizard/Page.qml:54
559+#: qml/Wizard/Page.qml:59
619560msgctxt "Button: Go back one page in the Wizard"
620561msgid "Back"
621562msgstr "ወደ ኋላ"
622563
623−#: qml/Wizard/Pages/10-welcome.qml:28
564+#: qml/Wizard/Pages/10-welcome.qml:29
624565msgid "Language"
625566msgstr "ቋንቋ"
626567
627−#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
628−#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
629−#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
630−#: qml/Wizard/Pages/70-passwd-type.qml:145
631−#: qml/Wizard/Pages/75-report-check.qml:84
632−#: qml/Wizard/Pages/passcode-desktop.qml:142
633−#: qml/Wizard/Pages/password-set.qml:142
568+#: qml/Wizard/Pages/10-welcome.qml:176
569+#: qml/Wizard/Pages/10-welcome-update.qml:126
570+#: qml/Wizard/Pages/11-changelog.qml:74 qml/Wizard/Pages/20-keyboard.qml:152
571+#: qml/Wizard/Pages/30-wifi.qml:214 qml/Wizard/Pages/50-timezone.qml:272
572+#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/70-passwd-type.qml:146
573+#: qml/Wizard/Pages/passcode-desktop.qml:154
574+#: qml/Wizard/Pages/password-set.qml:153
634575msgid "Next"
635576msgstr "ይቀጥሉ"
636577
578+#: qml/Wizard/Pages/10-welcome-update.qml:91
579+msgid "Welcome to "
580+msgstr "እንኳን ደህና መጡ ወደ: "
581+
582+#: qml/Wizard/Pages/10-welcome-update.qml:106
583+msgid "We will make sure your device is ready to use "
584+msgstr "የ እርስዎ አካል ለ መጠቀም ዝግጁ ነው: "
585+
586+#: qml/Wizard/Pages/11-changelog.qml:28
587+msgid "What's new"
588+msgstr "ምን አዲስ ነገር አለ"
589+
590+#: qml/Wizard/Pages/11-changelog.qml:74
591+msgid "Loading..."
592+msgstr "በ መጫን ላይ..."
593+
637594#: qml/Wizard/Pages/20-keyboard.qml:31
638595msgid "Select Keyboard"
639−msgstr "ቋንቋ ይምረጡ"
596+msgstr "የ ፊደል ገበታ ይምረጡ"
640597
641598#: qml/Wizard/Pages/20-keyboard.qml:71
642599msgid "Keyboard language"
@@ -646,8 +603,8 @@ msgstr "የ ፊደል ገበታ ቋንቋ"
646603msgid "Keyboard layout"
647604msgstr "የ ፊደል ገበታ አቀራረብ"
648605
649−#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
650−#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
606+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:214
607+#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/79-system-update.qml:144
651608#: qml/Wizard/Pages/sim.qml:101
652609msgid "Skip"
653610msgstr "መዝለያ"
@@ -656,55 +613,23 @@ msgstr "መዝለያ"
656613msgid "Connect to Wi‑Fi"
657614msgstr "ወደ ዋይ‑ፋይ መገናኛ"
658615
659−#: qml/Wizard/Pages/30-wifi.qml:132
616+#: qml/Wizard/Pages/30-wifi.qml:139
660617msgid "Connected"
661618msgstr "ተገናኝቷል"
662619
663−#: qml/Wizard/Pages/30-wifi.qml:165
620+#: qml/Wizard/Pages/30-wifi.qml:172
664621msgid "Available Wi-Fi networks"
665622msgstr "ዝግጁ የ ዋይ-ፋይ ኔትዎርኮች"
666623
667−#: qml/Wizard/Pages/30-wifi.qml:166
624+#: qml/Wizard/Pages/30-wifi.qml:173
668625msgid "No available Wi-Fi networks"
669626msgstr "ምንም ዝግጁ ዋይ-ፋይ ኔትዎርኮች አልተገኙም"
670627
671−#: qml/Wizard/Pages/40-location.qml:27
672−msgid "Location Services"
673−msgstr "የ አካባቢ ግልጋሎት"
674−
675−#: qml/Wizard/Pages/40-location.qml:83
676−msgid ""
677−"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
678−"(recommended)"
679−msgstr "ይጠቀሙ ጂፒኤስ: ዋይ-ፋይ: hotspots እና ተንቀሳቃሽ ኔትዎርክ ሳይታወቁ አካባቢ ለማግኘት (ይመከራሉ)"
680−
681−#: qml/Wizard/Pages/40-location.qml:105
682−#, qt-format
683−msgid "By selecting this option you agree to the Nokia HERE %1."
684−msgstr "ይህን ምርጫ በ መምረጥ እርስዎ ተስማምተዋል ከ Nokia HERE %1."
685−
686−#: qml/Wizard/Pages/40-location.qml:106
687−msgctxt "part of: Nokia HERE terms and conditions"
688−msgid "terms and conditions"
689−msgstr "ስምምነት እና ሁኔታዎች"
690−
691−#: qml/Wizard/Pages/40-location.qml:160
692−msgid "GPS only"
693−msgstr "ጂፒኤስ ብቻ"
694−
695−#: qml/Wizard/Pages/40-location.qml:214
696−msgid "Don't use my location"
697−msgstr "የ እኔን አካባቢ አትጠቀም"
698−
699−#: qml/Wizard/Pages/40-location.qml:260
700−msgid "You can change it later in System Settings."
701−msgstr "እርስዎ በኋላ በ ስርአት ማሰናጃ ውስጥ መቀየር ይችላሉ"
702−
703628#: qml/Wizard/Pages/50-timezone.qml:30
704629msgid "Time Zone"
705630msgstr "የ ሰአት ክልል"
706631
707−#: qml/Wizard/Pages/50-timezone.qml:182
632+#: qml/Wizard/Pages/50-timezone.qml:183
708633msgid "Enter your city"
709634msgstr "የ እርስዎን ከተማ ያስገቡ"
710635
@@ -712,7 +637,7 @@ msgstr "የ እርስዎን ከተማ ያስገቡ"
712637msgid "Personalize Your Device"
713638msgstr "የ እርስዎን አካል የ ግልዎ ያድርጉ"
714639
715−#: qml/Wizard/Pages/60-account.qml:48
640+#: qml/Wizard/Pages/60-account.qml:54
716641msgid "Preferred Name"
717642msgstr "የመረጡት ስም"
718643
@@ -720,112 +645,75 @@ msgstr "የመረጡት ስም"
720645msgid "Lock Screen"
721646msgstr "መመልከቻውን መቆለፊያ"
722647
723−#: qml/Wizard/Pages/70-passwd-type.qml:102
648+#: qml/Wizard/Pages/70-passwd-type.qml:103
724649msgctxt "Label: Type of security method"
725650msgid "Create new password"
726651msgstr "አዲስ የ መግቢያ ቃል መፍጠሪያ"
727652
728−#: qml/Wizard/Pages/70-passwd-type.qml:104
653+#: qml/Wizard/Pages/70-passwd-type.qml:105
729654msgctxt "Label: Type of security method"
730655msgid "Create passcode (numbers only)"
731656msgstr "አዲስ የ ማለፊያ ኮድ መፍጠሪያ (ቁጥር ብቻ)"
732657
733−#: qml/Wizard/Pages/70-passwd-type.qml:106
658+#: qml/Wizard/Pages/70-passwd-type.qml:107
734659msgctxt "Label: Type of security method"
735660msgid "No lock code"
736661msgstr "ምንም መቆለፊያ ኮድ አልተገኘም"
737662
738−#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
739−msgid "Privacy Policy"
740−msgstr "የ ግላዊነት መመሪያ"
741−
742−#: qml/Wizard/Pages/75-report-check.qml:26
743−msgid "Help Us Improve"
744−msgstr "እንድንሻሻል ይርዱን"
745−
746−#: qml/Wizard/Pages/75-report-check.qml:59
747−msgid "Improve system performance by sending us crashes and error reports."
748−msgstr "የ ስርአቱን አፈጻጸም ለማሻሻል የ ግጭት እና የ ስህተት መልእክቶች ይላኩልን"
749−
750−#: qml/Wizard/Pages/75-report-check.qml:60
751−msgid "Privacy policy"
752−msgstr "የ ግላዊነት መመሪያ"
753−
754−#: qml/Wizard/Pages/77-system-update.qml:28
663+#: qml/Wizard/Pages/79-system-update.qml:28
755664msgid "Update Device"
756665msgstr "አካሉን ማሻሻያ"
757666
758−#: qml/Wizard/Pages/77-system-update.qml:55
667+#: qml/Wizard/Pages/79-system-update.qml:55
759668msgid ""
760669"There is a system update available and ready to install. Afterwards, the "
761670"device will automatically restart."
762671msgstr "የ ስርአት ማሻሻያ ዝግጁ ነው ለ መግጠም: ከዚያ በኋላ አካሉ ራሱ በራሱ እንደገና ይጀምራል"
763672
764−#: qml/Wizard/Pages/77-system-update.qml:76
673+#: qml/Wizard/Pages/79-system-update.qml:76
674+#, fuzzy
675+#| msgctxt "string identifying name of the update"
676+#| msgid "Ubuntu system"
765677msgctxt "string identifying name of the update"
766−msgid "Ubuntu system"
678+msgid "Ubuntu Touch system"
767679msgstr "የ ኡቡቱ ስርአት"
768680
769−#: qml/Wizard/Pages/77-system-update.qml:83
681+#: qml/Wizard/Pages/79-system-update.qml:83
770682#, qt-format
771683msgctxt "version of the system update"
772684msgid "Version %1"
773685msgstr "እትም %1"
774686
775−#: qml/Wizard/Pages/77-system-update.qml:102
687+#: qml/Wizard/Pages/79-system-update.qml:95
776688msgid "This could take a few minutes..."
777−msgstr "ይህ ትንሽ ደቂቆች ይወስዳል"
689+msgstr "ይህ ትንሽ ደቂቃዎች ይወስዳል..."
778690
779−#: qml/Wizard/Pages/77-system-update.qml:116
691+#: qml/Wizard/Pages/79-system-update.qml:109
780692msgid "Install and restart now"
781693msgstr "መግጠሚያ እና እንደገና ማስጀመሪያ"
782694
783−#: qml/Wizard/Pages/80-finished.qml:89
695+#: qml/Wizard/Pages/80-finished.qml:91
696+msgid "Welcome Back"
697+msgstr "እንኳን ደህና መጡ:"
698+
699+#: qml/Wizard/Pages/80-finished.qml:91
784700msgid "Welcome to Ubuntu"
785701msgstr "እንኳን ደህና መጡ ወደ ኡቡንቱ"
786702
787−#: qml/Wizard/Pages/80-finished.qml:104
703+#: qml/Wizard/Pages/80-finished.qml:106
788704msgid "You are ready to use your device now"
789705msgstr "የ እርስዎን አካል ለ መጠቀም አሁን ዝግጁ ነው"
790706
791−#: qml/Wizard/Pages/80-finished.qml:124
707+#: qml/Wizard/Pages/80-finished.qml:126
708+msgid "Continue"
709+msgstr "ይቀጥሉ"
710+
711+#: qml/Wizard/Pages/80-finished.qml:126
792712msgid "Get Started"
793713msgstr "እንጀምር"
794714
795−#: qml/Wizard/Pages/here-terms.qml:25
796−msgid "Terms & Conditions"
797−msgstr "ውሎች & ሁኔታዎች"
798−
799−#: qml/Wizard/Pages/here-terms.qml:69
800−msgid "Your device uses positioning technologies provided by HERE."
801−msgstr "የ እርስዎ አካል ይጠቀማል ያሉበትን አካባቢ ቴክኖሎጂ የቀረበውን በ HERE."
802−
803−#: qml/Wizard/Pages/here-terms.qml:81
804−msgid ""
805−"To provide you with positioning services and to improve their quality, HERE "
806−"collects information about nearby cell towers and Wi-Fi hotspots around your "
807−"current location whenever your position is being found."
808−msgstr ""
809−"እርስዎ ያሉበትን አካባቢ ግልጋሎት ለ መስጠት እና ለማሻሻል: HERE መረጃ ይሰበስባል በቅርብ ያሉ የ ሴል ምሶሶዎች እና "
810−"ዋይ-ፋይ hotspots እርስዎ አሁን ያሉበትን አካባቢ ሲታወቅ"
811−
812−#: qml/Wizard/Pages/here-terms.qml:93
813−msgid ""
814−"The information collected is used to analyze the service and to improve the "
815−"use of service, but not to identify you personally."
816−msgstr "የ ተሰበሰበው መረጃ የሚጠቅመው ግልጋሎት ለማሻሻል ነው: ነገር ግን እርስዎን በ ግል ለ መለየት አይደለም"
817−
818−#: qml/Wizard/Pages/here-terms.qml:106
819−#, qt-format
820−msgid "By continuing, you agree to the HERE platform %1 and %2."
821−msgstr "በ መቀጠል እርስዎ ተስማምተዋል ከ HERE platform %1 እና %2."
822−
823−#: qml/Wizard/Pages/here-terms.qml:107
824−msgid "Service Terms"
825−msgstr "የ ግልጋሎት ስምምነቶች"
826−
827715#: qml/Wizard/Pages/passcode-confirm.qml:43
828−#: qml/Wizard/Pages/passcode-desktop.qml:97
716+#: qml/Wizard/Pages/passcode-desktop.qml:104
829717msgid "Confirm passcode"
830718msgstr "የማለፊያ ኮድ ማረጋገጫ"
831719
@@ -842,24 +730,24 @@ msgstr "እባክዎን እንደገና-ያስገቡ"
842730msgid "Lock Screen Passcode"
843731msgstr "የ መመልከቻው መቆለፊያ የ ማለፊያ ኮድ"
844732
845−#: qml/Wizard/Pages/passcode-desktop.qml:61
733+#: qml/Wizard/Pages/passcode-desktop.qml:68
846734msgid "Enter 4 numbers to setup your passcode"
847735msgstr "ያስገቡ 4 ቁጥሮች የ እርስዎን የ ማለፊያ ኮድ ለማሰናዳት"
848736
849−#: qml/Wizard/Pages/passcode-desktop.qml:77
737+#: qml/Wizard/Pages/passcode-desktop.qml:84
850738#: qml/Wizard/Pages/passcode-set.qml:54
851739msgid "Choose passcode"
852740msgstr "የ ማለፊያ ኮድ ይምረጡ"
853741
854−#: qml/Wizard/Pages/passcode-desktop.qml:127
742+#: qml/Wizard/Pages/passcode-desktop.qml:139
855743msgid "Passcode too short"
856744msgstr "የ ማለፊያ ኮዱ በጣም አጭር ነው"
857745
858−#: qml/Wizard/Pages/passcode-desktop.qml:129
746+#: qml/Wizard/Pages/passcode-desktop.qml:141
859747msgid "Passcodes match"
860748msgstr "የ ማለፊያ ኮዶቹ ተመሳሳይ ናቸው"
861749
862−#: qml/Wizard/Pages/passcode-desktop.qml:131
750+#: qml/Wizard/Pages/passcode-desktop.qml:143
863751msgid "Passcodes do not match"
864752msgstr "የ ማለፊያ ኮዶቹ አይመሳሰሉም"
865753
@@ -871,15 +759,15 @@ msgstr "የ ማለፊያ ኮድ 4 ባህሪዎች መሆን አለበት"
871759msgid "Lock Screen Password"
872760msgstr "የ መመልከቻ መቆለፊያ የ መግቢያ ቃል"
873761
874−#: qml/Wizard/Pages/password-set.qml:62
762+#: qml/Wizard/Pages/password-set.qml:68
875763msgid "Enter at least 8 characters"
876764msgstr "ያስገቡ ቢያንስ 8 ባህሪዎች"
877765
878−#: qml/Wizard/Pages/password-set.qml:74
766+#: qml/Wizard/Pages/password-set.qml:80
879767msgid "Choose password"
880768msgstr "የ መግቢያ ቃል ይምረጡ"
881769
882−#: qml/Wizard/Pages/password-set.qml:104
770+#: qml/Wizard/Pages/password-set.qml:110
883771msgid "Confirm password"
884772msgstr "የ መግቢያ ቃሉን ያረጋግጡ"
885773
@@ -935,6 +823,217 @@ msgstr "ደካማ የ መግቢያ ቃል"
935823msgid "Very weak password"
936824msgstr "በጣም ደካማ የ መግቢያ ቃል"
937825
826+#~ msgid "Unity 8"
827+#~ msgstr "Unity 8"
828+
829+#~ msgid "Scopes"
830+#~ msgstr "ክልል"
831+
832+#~ msgid "Super (Tap)"
833+#~ msgstr "Super (Tap)"
834+
835+#~ msgid "Opens the Scopes home."
836+#~ msgstr "የ ክልል ቤት መክፈቻ"
837+
838+#~ msgctxt "Button: Open the Ubuntu Store"
839+#~ msgid "Store"
840+#~ msgstr "ማስቀመጫ"
841+
842+#~ msgctxt "Button: Start a search in the current dash scope"
843+#~ msgid "Search"
844+#~ msgstr "መፈለጊያ"
845+
846+#~ msgctxt "Button: Show the current dash scope settings"
847+#~ msgid "Settings"
848+#~ msgstr "ማሰናጃዎች"
849+
850+#~ msgid "Remove from Favorites"
851+#~ msgstr "ከምወዳቸው ማስወገጃ"
852+
853+#~ msgid "Add to Favorites"
854+#~ msgstr "ወደምወዳቸው መጨመሪያ"
855+
856+#~ msgid "Refine your results"
857+#~ msgstr "የ እርስዎን ውጤቶች እንደገና ማጣሪያ"
858+
859+#~ msgid "Reset"
860+#~ msgstr "እንደ ነበረ መመለሻ"
861+
862+#~ msgid "Show less"
863+#~ msgstr "ትንሽ ማሳያ"
864+
865+#~ msgid "Show all"
866+#~ msgstr "ሁሉንም ማሳያ"
867+
868+#~ msgctxt "Label: Hint for dash search line edit"
869+#~ msgid "Search"
870+#~ msgstr "መፈለጊያ"
871+
872+#~ msgid "Recent Searches"
873+#~ msgstr "የ ቅርብ ጊዜ ፍለጋዎች"
874+
875+#~ msgid "Clear All"
876+#~ msgstr "ሁሉንም ማጽጃ"
877+
878+#~ msgid "More..."
879+#~ msgstr "ተጨማሪ..."
880+
881+#~ msgid "Less..."
882+#~ msgstr "አነስተኛ..."
883+
884+#~ msgid "Send"
885+#~ msgstr "መላኪያ"
886+
887+#~ msgid "Rate this"
888+#~ msgstr "ለዚህ ደረጃ ይስጡ"
889+
890+#~ msgid "Add a review"
891+#~ msgstr "ግምገማ መጨመሪያ"
892+
893+#~ msgid "Enable location data"
894+#~ msgstr "የአካባቢ ዳታ ማስቻያ"
895+
896+#~ msgid "Manage"
897+#~ msgstr "አስተዳዳሪ"
898+
899+#~ msgid "Home"
900+#~ msgstr "ቤት"
901+
902+#~ msgid "Also installed"
903+#~ msgstr "እንዲሁም የተገጠሙ"
904+
905+#~ msgid "Privacy Policy"
906+#~ msgstr "የ ግላዊነት መመሪያ"
907+
908+#~ msgid "Help Us Improve"
909+#~ msgstr "እንድንሻሻል ይርዱን"
910+
911+#~ msgid "Improve system performance by sending us crashes and error reports."
912+#~ msgstr "የ ስርአቱን አፈጻጸም ለማሻሻል የ ግጭት እና የ ስህተት መልእክቶች ይላኩልን"
913+
914+#~ msgid "Privacy policy"
915+#~ msgstr "የ ግላዊነት መመሪያ"
916+
917+#~ msgid "Update Apps"
918+#~ msgstr "መተግበሪያ ማሻሻያ"
919+
920+#~ msgid "This device is not connected to the internet."
921+#~ msgstr "ይህ አካል ከ ኢንተርኔት ጋር አልተገናኘም:"
922+
923+#~ msgid "Software is up to date"
924+#~ msgstr "ሶፍትዌሩ ዘመናዊ ነው:"
925+
926+#~ msgid "The update server is not responding."
927+#~ msgstr "የ ማሻሻያ ሰርቨር አይመልስም:"
928+
929+#~ msgid "Please wait..."
930+#~ msgstr "እባክዎን ይቆዩ..."
931+
932+#~ msgid "Installation failed"
933+#~ msgstr "መግጠሙ አልተሳካም:"
934+
935+#~ msgid "Checking for updates…"
936+#~ msgstr "ማሻሻያ በ መፈለግ ላይ…"
937+
938+#~ msgid "%1 update available"
939+#~ msgid_plural "%1 updates available"
940+#~ msgstr[0] "%1 ማሻሻያ ዝግጁ ነው:"
941+#~ msgstr[1] "%1 ማሻሻያዎች ዝግጁ ናቸው:"
942+
943+#~ msgid "Update all…"
944+#~ msgstr "ሁሉንም ማሻሻያ…"
945+
946+#~ msgid "Update all"
947+#~ msgstr "ሁሉንም ማሻሻያ"
948+
949+#~ msgid "Update"
950+#~ msgstr "ማሻሻያ"
951+
952+#~ msgid "Download"
953+#~ msgstr "የ ወረደ"
954+
955+#~ msgid "Resume"
956+#~ msgstr "ይቀጥሉ"
957+
958+#~ msgid "Install…"
959+#~ msgstr "መግጠሚያ…"
960+
961+#~ msgid "Install"
962+#~ msgstr "መግጠሚያ"
963+
964+#~ msgid "Open"
965+#~ msgstr "መክፈቻ"
966+
967+#~ msgid "Installing"
968+#~ msgstr "በ መግጠም ላይ"
969+
970+#~ msgid "Waiting to download"
971+#~ msgstr "ለ ማውረድ በ መጠበቅ ላይ"
972+
973+#~ msgid "%1 of %2"
974+#~ msgstr "%1 ከ %2"
975+
976+#~ msgid "Downloaded"
977+#~ msgstr "የ ወረደ"
978+
979+#~ msgid "Installed"
980+#~ msgstr "ተገጥሟል:"
981+
982+#~ msgid "Updated %1"
983+#~ msgstr "ተሻሽሏል %1"
984+
985+#~ msgid "Update failed"
986+#~ msgstr "ማሻሻል አልተቻለም:"
987+
988+#~ msgid "Location Services"
989+#~ msgstr "የ አካባቢ ግልጋሎት"
990+
991+#~ msgid ""
992+#~ "Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
993+#~ "(recommended)"
994+#~ msgstr "ይጠቀሙ ጂፒኤስ: ዋይ-ፋይ: hotspots እና ተንቀሳቃሽ ኔትዎርክ ሳይታወቁ አካባቢ ለማግኘት (ይመከራሉ)"
995+
996+#~ msgid "By selecting this option you agree to the Nokia HERE %1."
997+#~ msgstr "ይህን ምርጫ በ መምረጥ እርስዎ ተስማምተዋል ከ Nokia HERE %1."
998+
999+#~ msgctxt "part of: Nokia HERE terms and conditions"
1000+#~ msgid "terms and conditions"
1001+#~ msgstr "ስምምነት እና ሁኔታዎች"
1002+
1003+#~ msgid "GPS only"
1004+#~ msgstr "ጂፒኤስ ብቻ"
1005+
1006+#~ msgid "Don't use my location"
1007+#~ msgstr "የ እኔን አካባቢ አትጠቀም"
1008+
1009+#~ msgid "You can change it later in System Settings."
1010+#~ msgstr "እርስዎ በኋላ በ ስርአት ማሰናጃ ውስጥ መቀየር ይችላሉ"
1011+
1012+#~ msgid "Terms & Conditions"
1013+#~ msgstr "ውሎች & ሁኔታዎች"
1014+
1015+#~ msgid "Your device uses positioning technologies provided by HERE."
1016+#~ msgstr "የ እርስዎ አካል ይጠቀማል ያሉበትን አካባቢ ቴክኖሎጂ የቀረበውን በ HERE."
1017+
1018+#~ msgid ""
1019+#~ "To provide you with positioning services and to improve their quality, "
1020+#~ "HERE collects information about nearby cell towers and Wi-Fi hotspots "
1021+#~ "around your current location whenever your position is being found."
1022+#~ msgstr ""
1023+#~ "እርስዎ ያሉበትን አካባቢ ግልጋሎት ለ መስጠት እና ለማሻሻል: HERE መረጃ ይሰበስባል በቅርብ ያሉ የ ሴል ምሶሶዎች "
1024+#~ "እና ዋይ-ፋይ hotspots እርስዎ አሁን ያሉበትን አካባቢ ሲታወቅ"
1025+
1026+#~ msgid ""
1027+#~ "The information collected is used to analyze the service and to improve "
1028+#~ "the use of service, but not to identify you personally."
1029+#~ msgstr "የ ተሰበሰበው መረጃ የሚጠቅመው ግልጋሎት ለማሻሻል ነው: ነገር ግን እርስዎን በ ግል ለ መለየት አይደለም"
1030+
1031+#~ msgid "By continuing, you agree to the HERE platform %1 and %2."
1032+#~ msgstr "በ መቀጠል እርስዎ ተስማምተዋል ከ HERE platform %1 እና %2."
1033+
1034+#~ msgid "Service Terms"
1035+#~ msgstr "የ ግልጋሎት ስምምነቶች"
1036+
9381037#~ msgid "Top edge"
9391038#~ msgstr "የላይ ጠርዝ"
9401039
@@ -950,21 +1049,12 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
9501049#~ msgid "Type or say a command"
9511050#~ msgstr "ትእዛዝ ይናገሩ ወይንም ይጻፉ"
9521051
953−#~ msgid "Loading. Please Wait..."
954−#~ msgstr "እባክዎን ይቆዩ በመጫን ላይ..."
955−
956−#~ msgid "Speaking..."
957−#~ msgstr "በመናገር ላይ..."
958−
9591052#~ msgid "Speak Now..."
9601053#~ msgstr "አሁን ይናገሩ..."
9611054
9621055#~ msgid "Confirm"
9631056#~ msgstr "ማረጋገጫ"
9641057
965−#~ msgid "Search"
966−#~ msgstr "መፈለጊያ"
967−
9681058#~ msgid "See less"
9691059#~ msgstr "አነስተኛ መመልከቻ"
9701060
@@ -1007,7 +1097,6 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
10071097#~ msgid "This will be your last attempt."
10081098#~ msgstr "ይህ የመጨረሻ ሙከራዎ ነው"
10091099
1010−#, qt-format
10111100#~ msgid "Sorry, incorrect %1"
10121101#~ msgstr "አዝናለሁ: የተሳሳተ%1"
10131102
@@ -1048,11 +1137,12 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
10481137#~ "You have now mastered the edge gestures and can start using the "
10491138#~ "phone<br><br>Tap on the screen to start"
10501139#~ msgstr ""
1051−#~ "አሁን የ ጠርዝ እንቅስቃሴን አውቀዋል እና መጀመር ይችላሉ ስልኩን መጠቀም <br><br>መመልከቻውን መታ ያድርጉ ለመጀመር"
1140+#~ "አሁን የ ጠርዝ እንቅስቃሴን አውቀዋል እና መጀመር ይችላሉ ስልኩን መጠቀም <br><br>መመልከቻውን መታ ያድርጉ "
1141+#~ "ለመጀመር"
10521142
10531143#~ msgid ""
1054−#~ "If passcode is entered incorrectly, your phone will conduct a factory reset "
1055−#~ "and all personal data will be deleted."
1144+#~ "If passcode is entered incorrectly, your phone will conduct a factory "
1145+#~ "reset and all personal data will be deleted."
10561146#~ msgstr ""
10571147#~ "የተሳሳተ የማለፊያ ኮድ ካስገቡ የ እርስዎ ስልክ ወደ ነበረበት ወደ ፋክቶሪው ዘዴ ይመለሳል: እና የ ግል ዳታ በሙሉ "
10581148#~ "ይጠፋል"
@@ -1061,8 +1151,8 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
10611151#~ "If passphrase is entered incorrectly, your phone will conduct a factory "
10621152#~ "reset and all personal data will be deleted."
10631153#~ msgstr ""
1064−#~ "የተሳሳተ የማለፊያ ሐረግ ካስገቡ የ እርስዎ ስልክ ወደ ነበረበት ወደ ፋክቶሪው ዘዴ ይመለሳል: እና የ ግል ዳታ በሙሉ "
1065−#~ "ይጠፋል"
1154+#~ "የተሳሳተ የማለፊያ ሐረግ ካስገቡ የ እርስዎ ስልክ ወደ ነበረበት ወደ ፋክቶሪው ዘዴ ይመለሳል: እና የ ግል ዳታ "
1155+#~ "በሙሉ ይጠፋል"
10661156
10671157#~ msgid "Roaming"
10681158#~ msgstr "ማዘዋወሪያ"
@@ -1070,19 +1160,12 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
10701160#~ msgid "Manage Scopes"
10711161#~ msgstr "የ ክልል አስተዳዳሪ"
10721162
1073−#, qt-format
10741163#~ msgid "Enter %1"
10751164#~ msgstr "ማስገቢያ %1"
10761165
10771166#~ msgid "Please re-enter"
10781167#~ msgstr "እባክዎን እንደገና-ያስገቡ"
10791168
1080−#~ msgid "Enter passphrase"
1081−#~ msgstr "የ ማለፊያ ሀረግ ያስገቡ"
1082−
1083−#~ msgid "Enter passcode"
1084−#~ msgstr "የ ማለፊያ ኮድ ያስገቡ"
1085−
10861169#~ msgid "Lock security"
10871170#~ msgstr "ደህንነት መቆለፊያ"
10881171
@@ -1105,7 +1188,8 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
11051188#~ "This can be disabled in <b>System Settings</b> under <b>Security &amp; "
11061189#~ "Privacy</b>"
11071190#~ msgstr ""
1108−#~ "ይህን ግልጋሎት ማሰናከል ይችላሉ ከ <b>ስርአት ማሰናጃዎች</b> under <b>Security &amp; Privacy</b>"
1191+#~ "ይህን ግልጋሎት ማሰናከል ይችላሉ ከ <b>ስርአት ማሰናጃዎች</b> under <b>Security &amp; "
1192+#~ "Privacy</b>"
11091193
11101194#~ msgid "Nice work!"
11111195#~ msgstr "ጥሩ ሰርተዋል!"
@@ -1140,9 +1224,6 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
11401224#~ msgid "Let’s get started."
11411225#~ msgstr "ስራ እንጀምር"
11421226
1143−#~ msgid "Continue"
1144−#~ msgstr "ይቀጥሉ"
1145−
11461227#~ msgid "Passphrase must be 4 characters long"
11471228#~ msgstr "የ ማለፊያ ሀረግ ቢያንስ 4 ባህሪዎች መሆን አለበት"
11481229
@@ -1152,11 +1233,9 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
11521233#~ msgid "Let the phone detect your location:"
11531234#~ msgstr "እባክዎን እርስዎ ያሉበትን አካባቢ ስልኩ እራሱ ይፈልግ:"
11541235
1155−#, qt-format
11561236#~ msgid "〈 %1"
11571237#~ msgstr "〈 %1"
11581238
1159−#, qt-format
11601239#~ msgid "%1 〉"
11611240#~ msgstr "%1 〉"
11621241
@@ -1173,12 +1252,12 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
11731252#~ "Your phone is set up to automatically report errors to Canonical and its "
11741253#~ "partners, the makers of the operating system."
11751254#~ msgstr ""
1176−#~ "የ እርስዎ ስልክ ራሱ በራሱ የ ስህተት መግለጫዎች ወደ Canonical and its partners, የ መስሪያ ስርአት "
1177−#~ "አምራቾች"
1255+#~ "የ እርስዎ ስልክ ራሱ በራሱ የ ስህተት መግለጫዎች ወደ Canonical and its partners, የ መስሪያ "
1256+#~ "ስርአት አምራቾች"
11781257
11791258#~ msgid ""
1180−#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
1181−#~ "conditions</a>."
1259+#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms "
1260+#~ "and conditions</a>."
11821261#~ msgstr "ይህን ምርጫ በመምረጥ ተስማምቻለሁ ከ Nokia HERE <a href='#'>ውሎች እና ሁኔታዎች ጋር</a>."
11831262
11841263#~ msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
@@ -1193,9 +1272,6 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
11931272#~ msgid "Short swipe from the left edge."
11941273#~ msgstr "ከ ግራ ጠርዝ በኩል በትንሹ ይጥረጉ"
11951274
1196−#~ msgid "Open the launcher"
1197−#~ msgstr "ማስጀመሪያውን መክፈቻ"
1198−
11991275#~ msgid "Tap here to continue."
12001276#~ msgstr "እዚህ መታ ይድርጉ ለመቀጠል"
12011277
po/ar.po+474−484
@@ -6,85 +6,114 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
9−"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2017-01-10 14:48+0000\n"
11−"PO-Revision-Date: 2017-01-14 05:20+0000\n"
12−"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
13−"Language-Team: Arabic <ar@li.org>\n"
9+"Report-Msgid-Bugs-To: \n"
10+"POT-Creation-Date: 2021-01-29 11:42-0600\n"
11+"PO-Revision-Date: 2021-10-12 07:49+0000\n"
12+"Last-Translator: HEROBRINE7GAMER <tapermeerkat77@gmail.com>\n"
13+"Language-Team: Arabic <https://translate.ubports.com/projects/ubports/lomiri/"
14+"ar/>\n"
15+"Language: ar\n"
1416"MIME-Version: 1.0\n"
1517"Content-Type: text/plain; charset=UTF-8\n"
1618"Content-Transfer-Encoding: 8bit\n"
17−"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
18−"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
19−"X-Launchpad-Export-Date: 2017-01-16 05:47+0000\n"
20−"X-Generator: Launchpad (build 18302)\n"
19+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
20+"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
21+"X-Generator: Weblate 3.11.3\n"
22+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
2123
22−#: plugins/LightDM/Greeter.cpp:123
24+#: plugins/LightDM/Greeter.cpp:199
2325msgid "Password: "
2426msgstr "كلمة السر: "
2527
26−#: plugins/Unity/Launcher/launcheritem.cpp:50
28+#: plugins/LightDM/Greeter.cpp:214
29+msgid "Username"
30+msgstr "اسم المستخدم"
31+
32+#: plugins/LightDM/Greeter.cpp:258
33+msgid "Failed to authenticate"
34+msgstr "فشل التحقق"
35+
36+#: plugins/LightDM/Greeter.cpp:260
37+msgid "Invalid password, please try again"
38+msgstr "كلمة المرور غير صحيحة، الرجاء المحاولة مرة أخرى"
39+
40+#: plugins/LightDM/Greeter.cpp:270
41+msgid "Log In"
42+msgstr "سجل الدخول"
43+
44+#: plugins/LightDM/Greeter.cpp:270
45+msgid "Retry"
46+msgstr "حاول مجدداً"
47+
48+#: plugins/LightDM/UsersModel.cpp:157
49+msgid "Login"
50+msgstr "سجل الدخول"
51+
52+#: plugins/LightDM/UsersModel.cpp:165
53+msgid "Guest Session"
54+msgstr "جلسة ضيف"
55+
56+#: plugins/Unity/Launcher/launcheritem.cpp:48
2757#: plugins/Unity/Launcher/launcheritem.cpp:122
2858msgid "Pin shortcut"
29−msgstr "تثبيت الاختصار"
59+msgstr "ثبت اختصارًا"
3060
31−#: plugins/Unity/Launcher/launcheritem.cpp:55
61+#: plugins/Unity/Launcher/launcheritem.cpp:54
3262msgid "Quit"
3363msgstr "خروج"
3464
3565#: plugins/Unity/Launcher/launcheritem.cpp:122
3666msgid "Unpin shortcut"
37−msgstr "إزالة تثبيت الاختصار"
67+msgstr "ألغ تثبيت الاختصار"
3868
39−#: qml/Components/Dialogs.qml:149
69+#: qml/Components/Dialogs.qml:176
4070msgctxt "Title: Lock/Log out dialog"
4171msgid "Log out"
42−msgstr "خروج"
72+msgstr "اخرج"
4373
44−#: qml/Components/Dialogs.qml:150
74+#: qml/Components/Dialogs.qml:177
4575msgid "Are you sure you want to log out?"
46−msgstr "هل أنت متأكد من رغبتك في تسجيل الخروج؟"
76+msgstr "أمتأكد أنك تريد تسجيل الخروج ؟"
4777
48−#: qml/Components/Dialogs.qml:152
78+#: qml/Components/Dialogs.qml:180
4979msgctxt "Button: Lock the system"
5080msgid "Lock"
5181msgstr "أوصِد"
5282
53−#: qml/Components/Dialogs.qml:160
83+#: qml/Components/Dialogs.qml:191
5484msgctxt "Button: Log out from the system"
5585msgid "Log Out"
56−msgstr "خروج"
86+msgstr "اخرج"
5787
58−#: qml/Components/Dialogs.qml:167 qml/Components/Dialogs.qml:225
59−#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:232
60−#: qml/Wizard/Pages/passcode-confirm.qml:32
88+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
89+#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
6190#: qml/Wizard/Pages/passcode-set.qml:32
6291msgid "Cancel"
63−msgstr "إلغاء"
92+msgstr "ألغ"
6493
65−#: qml/Components/Dialogs.qml:179
94+#: qml/Components/Dialogs.qml:211
6695msgctxt "Title: Reboot dialog"
6796msgid "Reboot"
68−msgstr "إعادة التشغيل"
97+msgstr "أعد التشغيل"
6998
70−#: qml/Components/Dialogs.qml:180
99+#: qml/Components/Dialogs.qml:212
71100msgid "Are you sure you want to reboot?"
72−msgstr "هل أنت متأكد من رغبتك في إعادة تشغيل الجهاز؟"
101+msgstr "أمتأكد أنك تريد إعادة التشغيل؟"
73102
74−#: qml/Components/Dialogs.qml:182
103+#: qml/Components/Dialogs.qml:215
75104msgid "No"
76105msgstr "لا"
77106
78−#: qml/Components/Dialogs.qml:189
107+#: qml/Components/Dialogs.qml:223
79108msgid "Yes"
80109msgstr "نعم"
81110
82−#: qml/Components/Dialogs.qml:204
111+#: qml/Components/Dialogs.qml:243
83112msgctxt "Title: Power off/Restart dialog"
84113msgid "Power"
85114msgstr "الطاقة"
86115
87−#: qml/Components/Dialogs.qml:205
116+#: qml/Components/Dialogs.qml:244
88117msgid ""
89118"Are you sure you would like\n"
90119"to power off?"
@@ -92,23 +121,27 @@ msgstr ""
92121"هل أنت متأكد من رغبتك\n"
93122"في إيقاف التشغيل؟"
94123
95−#: qml/Components/Dialogs.qml:208
124+#: qml/Components/Dialogs.qml:248
96125msgctxt "Button: Power off the system"
97126msgid "Power off"
98−msgstr "إيقاف التشغيل"
127+msgstr "أوقف التشغيل"
99128
100−#: qml/Components/Dialogs.qml:217
129+#: qml/Components/Dialogs.qml:263
101130msgctxt "Button: Restart the system"
102131msgid "Restart"
103−msgstr "إعادة التشغيل"
132+msgstr "أعد التشغيل"
133+
134+#: qml/Components/Dialogs.qml:276
135+msgid "Screenshot"
136+msgstr "لقطة شاشة"
104137
105138#: qml/Components/KeyboardShortcutsOverlay.qml:41
106139msgid "Keyboard Shortcuts"
107140msgstr "اختصارات لوحة المفاتيح"
108141
109142#: qml/Components/KeyboardShortcutsOverlay.qml:55
110−msgid "Unity 8"
111−msgstr "يونتي 8"
143+msgid "Lomiri"
144+msgstr "لوميري"
112145
113146#: qml/Components/KeyboardShortcutsOverlay.qml:62
114147msgid "PrtScr"
@@ -116,15 +149,15 @@ msgstr "PrtScr"
116149
117150#: qml/Components/KeyboardShortcutsOverlay.qml:67
118151msgid "Takes a screenshot."
119−msgstr "أخذ لقطة للشاشة"
152+msgstr "خُذ لقطة للشاشة."
120153
121154#: qml/Components/KeyboardShortcutsOverlay.qml:75
122155msgid "Alt + PrtScr"
123156msgstr "Alt + PrtScr"
124157
125158#: qml/Components/KeyboardShortcutsOverlay.qml:80
126−msgid "Takes a screenshot of a window."
127−msgstr "أخذ لقطة شاشة للنافذة"
159+msgid "Takes a screenshot of the current window."
160+msgstr "خُذ لقطة شاشة للنافذة الحالية."
128161
129162#: qml/Components/KeyboardShortcutsOverlay.qml:88
130163msgid "Super + Space"
@@ -132,7 +165,7 @@ msgstr "Super + Space"
132165
133166#: qml/Components/KeyboardShortcutsOverlay.qml:93
134167msgid "Switches to next keyboard layout."
135−msgstr "للتحويل إلى مخطط لوحة المفاتيح التالي."
168+msgstr "بدل إلى تخطيط لوحة المفاتيح التالي."
136169
137170#: qml/Components/KeyboardShortcutsOverlay.qml:101
138171msgid "Super + Shift + Space"
@@ -140,193 +173,189 @@ msgstr "Super + Shift + Space"
140173
141174#: qml/Components/KeyboardShortcutsOverlay.qml:106
142175msgid "Switches to previous keyboard layout."
143−msgstr "للتحويل إلى مخطط لوحة المفاتيح السابق."
176+msgstr "بدل إلى تخطيط لوحة المفاتيح السابق."
177+
178+#: qml/Components/KeyboardShortcutsOverlay.qml:114
179+msgid "Ctrl + Alt + T"
180+msgstr "Ctrl + Alt + T"
144181
145−#: qml/Components/KeyboardShortcutsOverlay.qml:118
182+#: qml/Components/KeyboardShortcutsOverlay.qml:119
183+msgid "Starts the Terminal application."
184+msgstr "شغِل الطرفية."
185+
186+#: qml/Components/KeyboardShortcutsOverlay.qml:131
146187msgid "Launcher"
147−msgstr "شريط بدء التطبيقات"
188+msgstr "مطلق"
148189
149−#: qml/Components/KeyboardShortcutsOverlay.qml:125
190+#: qml/Components/KeyboardShortcutsOverlay.qml:138
150191msgid "Super (Hold)"
151−msgstr "Super (Hold)"
192+msgstr "Super (ضغط مع التعليق)"
152193
153−#: qml/Components/KeyboardShortcutsOverlay.qml:130
194+#: qml/Components/KeyboardShortcutsOverlay.qml:143
154195msgid "Opens the launcher, displays shortcuts."
155−msgstr "لفتح شريط بدء التطبيقات، وإظهار الاختصارات."
196+msgstr "يشغل المطلق، ويعرض الاختصارات."
156197
157−#: qml/Components/KeyboardShortcutsOverlay.qml:138
198+#: qml/Components/KeyboardShortcutsOverlay.qml:151
158199msgid "Alt + F1"
159200msgstr "Alt + F1"
160201
161−#: qml/Components/KeyboardShortcutsOverlay.qml:143
202+#: qml/Components/KeyboardShortcutsOverlay.qml:156
162203msgid "Opens launcher keyboard navigation mode."
163−msgstr ""
204+msgstr "فتح وضع التنقل بلوحة المفاتيح المشغلة."
164205
165−#: qml/Components/KeyboardShortcutsOverlay.qml:151
206+#: qml/Components/KeyboardShortcutsOverlay.qml:164
166207msgid "Super + Tab"
167208msgstr "Super + Tab"
168209
169−#: qml/Components/KeyboardShortcutsOverlay.qml:156
210+#: qml/Components/KeyboardShortcutsOverlay.qml:169
170211msgid "Switches applications via the launcher."
171−msgstr "للتحويل بين التطبيقات عبر شريط بدء التطبيقات."
212+msgstr "انتقل بين التطبيقات عبر المُطلق."
172213
173−#: qml/Components/KeyboardShortcutsOverlay.qml:164
174−msgid "Super + 0 to 9"
175−msgstr "Super + 0 to 9"
214+#: qml/Components/KeyboardShortcutsOverlay.qml:177
215+msgid "Super + 1 to 0"
216+msgstr "Super + 1 to 0"
176217
177−#: qml/Components/KeyboardShortcutsOverlay.qml:169
218+#: qml/Components/KeyboardShortcutsOverlay.qml:182
178219msgid "Same as clicking on a launcher icon."
179−msgstr "نفس إجراء الضغط على أيقونة في الشريط."
220+msgstr "نفس تأثير النقر على أيقونة المطلق."
180221
181−#: qml/Components/KeyboardShortcutsOverlay.qml:177
222+#: qml/Components/KeyboardShortcutsOverlay.qml:190
182223msgid "Super + A"
183224msgstr "Super + A"
184225
185−#: qml/Components/KeyboardShortcutsOverlay.qml:182
226+#: qml/Components/KeyboardShortcutsOverlay.qml:195
186227msgid "Opens the Application Drawer."
187−msgstr ""
188−
189−#: qml/Components/KeyboardShortcutsOverlay.qml:194
190−msgid "Scopes"
191−msgstr ""
192−
193−#: qml/Components/KeyboardShortcutsOverlay.qml:201
194−msgid "Super (Tap)"
195−msgstr ""
196−
197−#: qml/Components/KeyboardShortcutsOverlay.qml:206
198−msgid "Opens the Scopes home."
199−msgstr ""
228+msgstr "يفتح درج التطبيقات."
200229
201−#: qml/Components/KeyboardShortcutsOverlay.qml:222
230+#: qml/Components/KeyboardShortcutsOverlay.qml:235
202231msgid "Switching"
203−msgstr "التبديل"
232+msgstr "يبدل"
204233
205−#: qml/Components/KeyboardShortcutsOverlay.qml:229
234+#: qml/Components/KeyboardShortcutsOverlay.qml:242
206235msgid "Alt + Tab"
207236msgstr "Alt + Tab"
208237
209−#: qml/Components/KeyboardShortcutsOverlay.qml:234
238+#: qml/Components/KeyboardShortcutsOverlay.qml:247
210239msgid "Switches between applications."
211−msgstr "للتبديل بين التطبيقات المفتوحة."
240+msgstr "يبدل بين التطبيقات."
212241
213−#: qml/Components/KeyboardShortcutsOverlay.qml:242
242+#: qml/Components/KeyboardShortcutsOverlay.qml:255
214243msgid "Super + W"
215−msgstr ""
244+msgstr "Super + W"
216245
217−#: qml/Components/KeyboardShortcutsOverlay.qml:247
246+#: qml/Components/KeyboardShortcutsOverlay.qml:260
218247msgid "Opens the desktop spread."
219−msgstr ""
248+msgstr "يفتح وضع سطح المكتب."
220249
221−#: qml/Components/KeyboardShortcutsOverlay.qml:255
250+#: qml/Components/KeyboardShortcutsOverlay.qml:268
222251msgid "Cursor Left or Right"
223−msgstr ""
252+msgstr "اتجاه المؤشر لليمين أو اليسار"
224253
225−#: qml/Components/KeyboardShortcutsOverlay.qml:260
254+#: qml/Components/KeyboardShortcutsOverlay.qml:273
226255msgid "Moves the focus."
227−msgstr "لنقل التركيز."
256+msgstr "بدّل التركيز."
228257
229−#: qml/Components/KeyboardShortcutsOverlay.qml:272
258+#: qml/Components/KeyboardShortcutsOverlay.qml:285
230259msgid "Windows"
231−msgstr "النوافذ"
260+msgstr "نوافذ"
232261
233−#: qml/Components/KeyboardShortcutsOverlay.qml:279
262+#: qml/Components/KeyboardShortcutsOverlay.qml:292
234263msgid "Ctrl + Super + D"
235264msgstr "Ctrl + Super + D"
236265
237−#: qml/Components/KeyboardShortcutsOverlay.qml:284
266+#: qml/Components/KeyboardShortcutsOverlay.qml:297
238267msgid "Minimizes all windows."
239−msgstr "لتصغير جميع النوافذ."
268+msgstr "يصغر كل النوافذ."
240269
241−#: qml/Components/KeyboardShortcutsOverlay.qml:292
270+#: qml/Components/KeyboardShortcutsOverlay.qml:305
242271msgid "Ctrl + Super + Up"
243272msgstr "Ctrl + Super + Up"
244273
245−#: qml/Components/KeyboardShortcutsOverlay.qml:297
274+#: qml/Components/KeyboardShortcutsOverlay.qml:310
246275msgid "Maximizes the current window."
247−msgstr "لتكبير النافذة الحالية."
276+msgstr "يكبر النافذة الحالية."
248277
249−#: qml/Components/KeyboardShortcutsOverlay.qml:305
278+#: qml/Components/KeyboardShortcutsOverlay.qml:318
250279msgid "Ctrl + Super + Down"
251280msgstr "Ctrl + Super + Down"
252281
253−#: qml/Components/KeyboardShortcutsOverlay.qml:310
282+#: qml/Components/KeyboardShortcutsOverlay.qml:323
254283msgid "Minimizes or restores the current window."
255−msgstr "لتصغير او استعادة النافذة الحالية."
284+msgstr "يصغر أو يستعيد النافذة الحالية."
256285
257−#: qml/Components/KeyboardShortcutsOverlay.qml:318
286+#: qml/Components/KeyboardShortcutsOverlay.qml:331
258287msgid "Ctrl + Super + Left or Right"
259−msgstr ""
288+msgstr "Ctrl + Super + Left or Right"
260289
261−#: qml/Components/KeyboardShortcutsOverlay.qml:323
290+#: qml/Components/KeyboardShortcutsOverlay.qml:336
262291msgid "Semi-maximizes the current window."
263−msgstr ""
292+msgstr "كبر النافذة الحالة جزئيا."
264293
265−#: qml/Components/KeyboardShortcutsOverlay.qml:331
294+#: qml/Components/KeyboardShortcutsOverlay.qml:344
266295msgid "Alt + F4"
267−msgstr ""
296+msgstr "Alt + F4"
268297
269−#: qml/Components/KeyboardShortcutsOverlay.qml:336
298+#: qml/Components/KeyboardShortcutsOverlay.qml:349
270299msgid "Closes the current window."
271−msgstr ""
300+msgstr "يغلق النافذة الحالية."
272301
273−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:252
302+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
274303msgid "Return to Call"
275−msgstr "العودة إلى المكالمة"
304+msgstr "عُد للمكالمة"
276305
277306#: qml/Components/Lockscreen.qml:212
278307msgid "Emergency Call"
279308msgstr "مكالمة طوارئ"
280309
281−#: qml/Components/Lockscreen.qml:244
310+#: qml/Components/Lockscreen.qml:245
282311msgid "OK"
283312msgstr "موافق"
284313
285314#: qml/Components/MediaServices/VideoPlayerControls.qml:44
286315#, qt-format
287316msgid "%1:%2:%3"
288−msgstr ""
317+msgstr "%1:%2:%3"
289318
290319#: qml/Components/MediaServices/VideoPlayerControls.qml:49
291320#, qt-format
292321msgid "%1:%2"
293−msgstr ""
322+msgstr "%1:%2"
294323
295−#: qml/Components/ModeSwitchWarningDialog.qml:32
324+#: qml/Components/ModeSwitchWarningDialog.qml:33
296325msgid "Apps may have unsaved data:"
297−msgstr ""
326+msgstr "ربما لم تَحفظ بيانات هذه التطبيقات:"
298327
299−#: qml/Components/ModeSwitchWarningDialog.qml:57
328+#: qml/Components/ModeSwitchWarningDialog.qml:60
300329msgctxt ""
301330"Re-dock means connect the device again to an external screen/mouse/keyboard"
302331msgid "Re-dock, save your work and close these apps to continue."
303−msgstr ""
332+msgstr "أعد الوصل، احفظ عملك على هذه التطبيقات ثم أغلقها للمتابعة."
304333
305−#: qml/Components/ModeSwitchWarningDialog.qml:63
334+#: qml/Components/ModeSwitchWarningDialog.qml:67
306335msgid "Or force close now (unsaved data will be lost)."
307−msgstr "أو أغلق إجباريا الآن (ستفقد أي بيانات غير محفوظة)."
336+msgstr "أو أغلقها قسريا (ستفقد البيانات غير المحفوظة)."
308337
309−#: qml/Components/ModeSwitchWarningDialog.qml:75
338+#: qml/Components/ModeSwitchWarningDialog.qml:80
310339msgid "OK, I will reconnect"
311−msgstr ""
340+msgstr "موافق، سؤعيد الاتصال"
312341
313−#: qml/Components/ModeSwitchWarningDialog.qml:76
342+#: qml/Components/ModeSwitchWarningDialog.qml:81
314343msgid "Reconnect now!"
315−msgstr ""
344+msgstr "أعد الاتصال الآن!"
316345
317−#: qml/Components/ModeSwitchWarningDialog.qml:88
346+#: qml/Components/ModeSwitchWarningDialog.qml:94
318347msgid "Close all"
319−msgstr ""
348+msgstr "أغلق الكل"
320349
321350#: qml/Components/SharingPicker.qml:54
322351msgid "Preview Share Item"
323−msgstr ""
352+msgstr "معاينة الملف المشارك"
324353
325354#: qml/Components/VirtualTouchPad.qml:317
326355msgid ""
327356"Your device is now connected to an external display. Use this screen as a "
328357"touch pad to interact with the pointer."
329−msgstr ""
358+msgstr "جهازك متصل بجهاز عرض خارجي. استخدم جهازك كلوحة لمس لتحكم بالمؤشر."
330359
331360#: qml/Components/VirtualTouchPad.qml:327
332361msgid "Tap left button to click."
@@ -334,116 +363,19 @@ msgstr "اضغط الزر الأيسر للنقر."
334363
335364#: qml/Components/VirtualTouchPad.qml:339
336365msgid "Tap right button to right click."
337−msgstr "اضغط الزر الأيمن للنقر الأيمن."
366+msgstr "اضغط على الزر الأيمن للنقر."
338367
339368#: qml/Components/VirtualTouchPad.qml:351
340369msgid "Swipe with two fingers to scroll."
341−msgstr ""
370+msgstr "اسحب بإصبعين للتمرير."
342371
343372#: qml/Components/VirtualTouchPad.qml:396
344373msgid "Find more settings in the system settings."
345−msgstr "اعثر على مزيد من الإعدادات في إعدادات النظام."
346−
347−#: qml/Dash/DashPageHeader.qml:361
348−msgctxt "Button: Open the Ubuntu Store"
349−msgid "Store"
350−msgstr "المتجر"
351−
352−#: qml/Dash/DashPageHeader.qml:368
353−msgctxt "Button: Start a search in the current dash scope"
354−msgid "Search"
355−msgstr "بحث"
356−
357−#: qml/Dash/DashPageHeader.qml:378
358−msgctxt "Button: Show the current dash scope settings"
359−msgid "Settings"
360−msgstr "الإعدادات"
361−
362−#: qml/Dash/DashPageHeader.qml:385
363−msgid "Remove from Favorites"
364−msgstr "حذف من المفضلات"
365−
366−#: qml/Dash/DashPageHeader.qml:385
367−msgid "Add to Favorites"
368−msgstr "إضافة إلى المفضلات"
369−
370−#: qml/Dash/FiltersPopover.qml:61
371−msgid "Refine your results"
372−msgstr ""
373−
374−#: qml/Dash/FiltersPopover.qml:70
375−msgid "Reset"
376−msgstr ""
377−
378−#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
379−msgid "Show less"
380−msgstr "عرض أقل"
381−
382−#: qml/Dash/GenericScopeView.qml:547
383−msgid "Show all"
384−msgstr "عرض الكل"
385−
386−#: qml/Dash/GenericScopeView.qml:578
387−msgctxt "Label: Hint for dash search line edit"
388−msgid "Search"
389−msgstr "بحث"
390−
391−#: qml/Dash/PageHeaderExtraPanel.qml:67
392−msgid "Recent Searches"
393−msgstr ""
394−
395−#: qml/Dash/PageHeaderExtraPanel.qml:78
396−msgid "Clear All"
397−msgstr ""
398−
399−#: qml/Dash/Previews/PreviewActionCombo.qml:36
400−msgid "More..."
401−msgstr "المزيد..."
402−
403−#: qml/Dash/Previews/PreviewActionCombo.qml:36
404−msgid "Less..."
405−msgstr "أقل..."
406−
407−#: qml/Dash/Previews/PreviewCommentInput.qml:83
408−#: qml/Dash/Previews/PreviewRatingInput.qml:202
409−msgid "Send"
410−msgstr "أرسل"
411−
412−#: qml/Dash/Previews/PreviewRatingInput.qml:109
413−msgid "Rate this"
414−msgstr "قيّم ذلك"
415−
416−#: qml/Dash/Previews/PreviewRatingInput.qml:184
417−msgid "Add a review"
418−msgstr "أضف تعليق"
419−
420−#: qml/Dash/PullToRefreshScopeStyle.qml:56
421−msgid "Pull to refresh…"
422−msgstr "اسحب للتحديث..."
423−
424−#: qml/Dash/PullToRefreshScopeStyle.qml:61
425−msgid "Release to refresh…"
426−msgstr "حرّر للتحديث..."
427−
428−#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
429−msgid "Enable location data"
430−msgstr "تفعيل بيانات الموقع"
431−
432−#: qml/Dash/ScopesList.qml:146
433−msgid "Manage"
434−msgstr "إدارة"
435−
436−#: qml/Dash/ScopesList.qml:187
437−msgid "Home"
438−msgstr "الرئيسية"
439−
440−#: qml/Dash/ScopesList.qml:188
441−msgid "Also installed"
442−msgstr "أيضا تم تثبيت"
374+msgstr "جد إعدادات إضافية في إعدادات النظام."
443375
444376#: qml/Greeter/CoverPage.qml:127
445377msgid "Unlock"
446−msgstr "فك القفل"
378+msgstr "فك الإيصاد"
447379
448380#: qml/Greeter/DelayedLockscreen.qml:43
449381msgid "Device Locked"
@@ -463,57 +395,56 @@ msgstr ""
463395#, qt-format
464396msgid "Please wait %1 minute and then try again…"
465397msgid_plural "Please wait %1 minutes and then try again…"
466−msgstr[0] "برجاء الانتظار %1 دقيقة ثم المحاولة مجددًا..."
467−msgstr[1] "برجاء الانتظار دقيقة واحدة (%1) ثم المحاولة مجددًا..."
468−msgstr[2] "برجاء الانتظار دقيقتين (%1) ثم المحاولة مجددًا..."
469−msgstr[3] "برجاء الانتظار %1 دقائق ثم المحاولة مجددًا..."
470−msgstr[4] "برجاء الانتظار %1 دقيقة ثم المحاولة مجددًا..."
471−msgstr[5] "برجاء الانتظار %1 دقيقة ثم المحاولة مجددًا..."
472−
473−#: qml/Greeter/Greeter.qml:592
398+msgstr[0] "برجاء الانتظار %1 دقيقة ثم المحاولة مجددًا…"
399+msgstr[1] "برجاء الانتظار دقيقة واحدة (%1) ثم المحاولة مجددًا…"
400+msgstr[2] "برجاء الانتظار دقيقتين (%1) ثم المحاولة مجددًا…"
401+msgstr[3] "برجاء الانتظار %1 دقائق ثم المحاولة مجددًا…"
402+msgstr[4] "برجاء الانتظار %1 دقيقة ثم المحاولة مجددًا…"
403+msgstr[5] "برجاء الانتظار %1 دقيقة ثم المحاولة مجددًا…"
404+
405+#: qml/Greeter/Greeter.qml:550
474406msgid "Try again"
475−msgstr ""
407+msgstr "حاول مجددا"
476408
477−#: qml/Greeter/LoginList.qml:70
478−msgid "Passphrase"
479−msgstr ""
409+#: qml/Greeter/Greeter.qml:551
410+msgid "Enter passphrase to unlock"
411+msgstr "أدخِل العبارة السرية لفك الإيصاد"
480412
481−#: qml/Greeter/LoginList.qml:71
482−msgid "Passcode"
483−msgstr ""
413+#: qml/Greeter/Greeter.qml:552
414+msgid "Enter passcode to unlock"
415+msgstr "أدخِل الرمز السرّي لفك الإيصاد"
484416
485−#: qml/Greeter/LoginList.qml:98
486−msgid "Retry"
487−msgstr "إعادة المحاولة"
417+#: qml/Greeter/NarrowView.qml:235
418+msgid "Emergency"
419+msgstr "طوارئ"
488420
489−#: qml/Greeter/LoginList.qml:99
490−msgid "Log In"
491−msgstr ""
421+#: qml/Greeter/PromptList.qml:126
422+msgid "Passphrase"
423+msgstr "كلمة السر"
492424
493−#: qml/Greeter/NarrowView.qml:252
494−msgid "Emergency"
495−msgstr ""
425+#: qml/Greeter/PromptList.qml:126
426+msgid "Passcode"
427+msgstr "الرمز السري"
496428
497−#: qml/Greeter/SessionsList.qml:122
429+#: qml/Greeter/SessionsList.qml:124
498430msgid "Select desktop environment"
499−msgstr ""
431+msgstr "اختر بيئة سطح المكتب"
500432
501−#: qml/Launcher/Drawer.qml:80
433+#: qml/Launcher/Drawer.qml:250
502434msgid "Search…"
503−msgstr ""
435+msgstr "ابحث…"
504436
505−#: qml/Launcher/Drawer.qml:101
506−msgctxt "Apps sorted alphabetically"
507−msgid "A-Z"
508−msgstr ""
437+#: qml/Launcher/PullToRefreshScopeStyle.qml:56
438+msgid "Pull to refresh…"
439+msgstr "اسحب للتحديث…"
509440
510−#: qml/Launcher/MoreAppsHeader.qml:32
511−msgid "More apps in the store"
512−msgstr ""
441+#: qml/Launcher/PullToRefreshScopeStyle.qml:61
442+msgid "Release to refresh…"
443+msgstr "حرّر للتحديث…"
513444
514445#: qml/Notifications/NotificationMenuItemFactory.qml:124
515446msgid "Show password"
516−msgstr "عرض كلمة السر"
447+msgstr "اعرض كلمة السر"
517448
518449#: qml/Panel/ActiveCallHint.qml:79
519450msgid "Tap to return to call..."
@@ -542,9 +473,9 @@ msgstr[5] "%1 ساعة"
542473#, qt-format
543474msgid "%1 minute"
544475msgid_plural "%1 minutes"
545−msgstr[0] "أقل من دقيقة (%1)"
546−msgstr[1] "دقيقة واحدة (%1)"
547−msgstr[2] "دقيقتان (%1)"
476+msgstr[0] "%1 دقيقة"
477+msgstr[1] "دقيقة واحدة"
478+msgstr[2] "دقيقتان"
548479msgstr[3] "%1 دقائق"
549480msgstr[4] "%1 دقيقة"
550481msgstr[5] "%1 دقيقة"
@@ -572,11 +503,11 @@ msgstr "باق %1"
572503
573504#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1017
574505msgid "In queue…"
575−msgstr "في الانتظار..."
506+msgstr "في الانتظار…"
576507
577508#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1021
578509msgid "Downloading"
579−msgstr "التنزيل"
510+msgstr "ينزل"
580511
581512#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1023
582513msgid "Paused, tap to resume"
@@ -584,7 +515,7 @@ msgstr "مُلبث، انقر للاستئناف"
584515
585516#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1025
586517msgid "Canceled"
587−msgstr "تم إلغائه"
518+msgstr "أُلغي"
588519
589520#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1027
590521msgid "Finished"
@@ -592,13 +523,13 @@ msgstr "انتهى"
592523
593524#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1029
594525msgid "Failed, tap to retry"
595−msgstr "فشل، انقل لإعادة المحاولة"
526+msgstr "فشل، انقر لإعادة المحاولة"
596527
597528#: qml/Panel/Indicators/MessageMenuItemFactory.qml:151
598529#: qml/Panel/Indicators/MessageMenuItemFactory.qml:210
599530msgctxt "Button: Send a reply message"
600531msgid "Send"
601−msgstr ""
532+msgstr "أرسل"
602533
603534#: qml/Panel/Indicators/MessageMenuItemFactory.qml:152
604535msgctxt "Label: Hint in message indicator line edit"
@@ -608,349 +539,431 @@ msgstr "رد"
608539#: qml/Panel/Indicators/MessageMenuItemFactory.qml:209
609540msgctxt "Button: Call back on phone"
610541msgid "Call back"
611−msgstr ""
542+msgstr "عاود الاتصال"
543+
544+#: qml/Panel/PanelMenuPage.qml:92
545+msgid "Back"
546+msgstr "للخلف"
612547
613548#: qml/Stage/SideStage.qml:76
614549msgid "Drag using 3 fingers any application from one window to the other"
615−msgstr ""
550+msgstr "اسحب أي تطبيق بثلاث أصابع من نافذة لأخرى"
551+
552+#: qml/Stage/Stage.qml:671
553+msgid "No running apps"
554+msgstr "لا توجد تطبيقات مشغلة"
616555
617556#: qml/Tutorial/TutorialLeftLong.qml:49
618−msgid "Long swipe from the left edge to open the Today scope"
619−msgstr ""
557+msgid "Long swipe from the left edge to open the Application Drawer"
558+msgstr "اسحب اصبعك مطولا بدءً من الحافة اليسرى لفتح درج التطبيقات"
620559
621560#: qml/Tutorial/TutorialLeft.qml:47
622561msgid "Short swipe from the left edge to open the launcher"
623−msgstr ""
562+msgstr "اسحب اصبعك سحبا قصيرا بدءً من الحافة اليسرى لفتح المُطلِق"
624563
625−#: qml/Tutorial/TutorialRight.qml:55
564+#: qml/Tutorial/TutorialRight.qml:54
626565msgid "Push your mouse against the right edge to view your open apps"
627−msgstr ""
566+msgstr "حرك المؤشر للحافة اليمنى لعرض التطبيقات المفتوحة"
628567
629−#: qml/Tutorial/TutorialRight.qml:56
568+#: qml/Tutorial/TutorialRight.qml:55
630569msgid "Swipe from the right edge to view your open apps"
631−msgstr ""
570+msgstr "اسحب اصبعك بدءً من الحافة اليمنى لعرض التطبيقات المفتوحة"
632571
633572#: qml/Tutorial/TutorialTop.qml:53
634573msgid "Swipe from the top edge to access notifications and quick settings"
635574msgstr ""
575+"اسحب اصبعك بدءً من الحافة العلوية للوصول الى التنبيهات والإعدادات السريعة"
636576
637−#: qml/Wizard/Page.qml:54
577+#: qml/Wizard/Page.qml:59
638578msgctxt "Button: Go back one page in the Wizard"
639579msgid "Back"
640−msgstr "عودة"
580+msgstr "للخلف"
641581
642−#: qml/Wizard/Pages/10-welcome.qml:28
582+#: qml/Wizard/Pages/10-welcome.qml:29
643583msgid "Language"
644−msgstr ""
645−
646−#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
647−#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
648−#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
649−#: qml/Wizard/Pages/70-passwd-type.qml:145
650−#: qml/Wizard/Pages/75-report-check.qml:84
651−#: qml/Wizard/Pages/passcode-desktop.qml:142
652−#: qml/Wizard/Pages/password-set.qml:142
584+msgstr "اللغة"
585+
586+#: qml/Wizard/Pages/10-welcome.qml:176
587+#: qml/Wizard/Pages/10-welcome-update.qml:126
588+#: qml/Wizard/Pages/11-changelog.qml:74 qml/Wizard/Pages/20-keyboard.qml:152
589+#: qml/Wizard/Pages/30-wifi.qml:214 qml/Wizard/Pages/50-timezone.qml:272
590+#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/70-passwd-type.qml:146
591+#: qml/Wizard/Pages/passcode-desktop.qml:154
592+#: qml/Wizard/Pages/password-set.qml:153
653593msgid "Next"
654−msgstr ""
594+msgstr "التالي"
595+
596+#: qml/Wizard/Pages/10-welcome-update.qml:91
597+msgid "Welcome to "
598+msgstr "مرحبا بك في "
599+
600+#: qml/Wizard/Pages/10-welcome-update.qml:106
601+msgid "We will make sure your device is ready to use "
602+msgstr "سوف نتأكد أن جهازك معد للاستخدام "
603+
604+#: qml/Wizard/Pages/11-changelog.qml:28
605+msgid "What's new"
606+msgstr "ما الجديد"
607+
608+#: qml/Wizard/Pages/11-changelog.qml:74
609+msgid "Loading..."
610+msgstr "يحمل..."
655611
656612#: qml/Wizard/Pages/20-keyboard.qml:31
657613msgid "Select Keyboard"
658−msgstr ""
614+msgstr "اختر لوحة المفاتيح"
659615
660616#: qml/Wizard/Pages/20-keyboard.qml:71
661617msgid "Keyboard language"
662−msgstr ""
618+msgstr "لغة لوحة المفاتيح"
663619
664620#: qml/Wizard/Pages/20-keyboard.qml:93
665621msgid "Keyboard layout"
666−msgstr ""
622+msgstr "تخطيط لوحة المفاتيح"
667623
668−#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
669−#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
624+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:214
625+#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/79-system-update.qml:144
670626#: qml/Wizard/Pages/sim.qml:101
671627msgid "Skip"
672−msgstr "تخطي"
628+msgstr "تخط"
673629
674630#: qml/Wizard/Pages/30-wifi.qml:31
675631msgid "Connect to Wi‑Fi"
676−msgstr "اتصل بالواي فاي"
632+msgstr "اتصل بالإنترنت"
677633
678−#: qml/Wizard/Pages/30-wifi.qml:132
634+#: qml/Wizard/Pages/30-wifi.qml:139
679635msgid "Connected"
680−msgstr ""
636+msgstr "متصل"
681637
682−#: qml/Wizard/Pages/30-wifi.qml:165
638+#: qml/Wizard/Pages/30-wifi.qml:172
683639msgid "Available Wi-Fi networks"
684−msgstr ""
640+msgstr "شبكات الواي فاي المتاحة"
685641
686−#: qml/Wizard/Pages/30-wifi.qml:166
642+#: qml/Wizard/Pages/30-wifi.qml:173
687643msgid "No available Wi-Fi networks"
688−msgstr ""
689−
690−#: qml/Wizard/Pages/40-location.qml:27
691−msgid "Location Services"
692−msgstr ""
693−
694−#: qml/Wizard/Pages/40-location.qml:83
695−msgid ""
696−"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
697−"(recommended)"
698−msgstr ""
699−
700−#: qml/Wizard/Pages/40-location.qml:105
701−#, qt-format
702−msgid "By selecting this option you agree to the Nokia HERE %1."
703−msgstr ""
704−
705−#: qml/Wizard/Pages/40-location.qml:106
706−msgctxt "part of: Nokia HERE terms and conditions"
707−msgid "terms and conditions"
708−msgstr ""
709−
710−#: qml/Wizard/Pages/40-location.qml:160
711−msgid "GPS only"
712−msgstr ""
713−
714−#: qml/Wizard/Pages/40-location.qml:214
715−msgid "Don't use my location"
716−msgstr ""
717−
718−#: qml/Wizard/Pages/40-location.qml:260
719−msgid "You can change it later in System Settings."
720−msgstr ""
644+msgstr "لا توجد شبكات واي فاي"
721645
722646#: qml/Wizard/Pages/50-timezone.qml:30
723647msgid "Time Zone"
724−msgstr ""
648+msgstr "المنطقة الزمنية"
725649
726−#: qml/Wizard/Pages/50-timezone.qml:182
650+#: qml/Wizard/Pages/50-timezone.qml:183
727651msgid "Enter your city"
728−msgstr ""
652+msgstr "أدخل مدينتك"
729653
730654#: qml/Wizard/Pages/60-account.qml:24
731655msgid "Personalize Your Device"
732−msgstr ""
656+msgstr "خصص جهازك"
733657
734−#: qml/Wizard/Pages/60-account.qml:48
658+#: qml/Wizard/Pages/60-account.qml:54
735659msgid "Preferred Name"
736−msgstr ""
660+msgstr "اسم مستحسن"
737661
738662#: qml/Wizard/Pages/70-passwd-type.qml:40
739663msgid "Lock Screen"
740−msgstr ""
664+msgstr "قفل الشاشة"
741665
742−#: qml/Wizard/Pages/70-passwd-type.qml:102
666+#: qml/Wizard/Pages/70-passwd-type.qml:103
743667msgctxt "Label: Type of security method"
744668msgid "Create new password"
745−msgstr ""
669+msgstr "أنشئ كلمة سر جديدة"
746670
747−#: qml/Wizard/Pages/70-passwd-type.qml:104
671+#: qml/Wizard/Pages/70-passwd-type.qml:105
748672msgctxt "Label: Type of security method"
749673msgid "Create passcode (numbers only)"
750−msgstr ""
674+msgstr "أنشئ رمز مرور (أرقام فقط)"
751675
752−#: qml/Wizard/Pages/70-passwd-type.qml:106
676+#: qml/Wizard/Pages/70-passwd-type.qml:107
753677msgctxt "Label: Type of security method"
754678msgid "No lock code"
755−msgstr ""
756−
757−#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
758−msgid "Privacy Policy"
759−msgstr ""
760−
761−#: qml/Wizard/Pages/75-report-check.qml:26
762−msgid "Help Us Improve"
763−msgstr ""
679+msgstr "لا يوجد رمز إيصاد"
764680
765−#: qml/Wizard/Pages/75-report-check.qml:59
766−msgid "Improve system performance by sending us crashes and error reports."
767−msgstr ""
768−
769−#: qml/Wizard/Pages/75-report-check.qml:60
770−msgid "Privacy policy"
771−msgstr ""
772−
773−#: qml/Wizard/Pages/77-system-update.qml:28
681+#: qml/Wizard/Pages/79-system-update.qml:28
774682msgid "Update Device"
775−msgstr ""
683+msgstr "حدث الجهاز"
776684
777−#: qml/Wizard/Pages/77-system-update.qml:55
685+#: qml/Wizard/Pages/79-system-update.qml:55
778686msgid ""
779687"There is a system update available and ready to install. Afterwards, the "
780688"device will automatically restart."
781−msgstr ""
689+msgstr "يتوفر تحديث للنظام وهو جاهز للتثبيت، سيُعاد تشغيل الجهاز تلقائيا."
782690
783−#: qml/Wizard/Pages/77-system-update.qml:76
691+#: qml/Wizard/Pages/79-system-update.qml:76
784692msgctxt "string identifying name of the update"
785−msgid "Ubuntu system"
786−msgstr ""
693+msgid "Ubuntu Touch system"
694+msgstr "نظام أبونتو تاتش"
787695
788−#: qml/Wizard/Pages/77-system-update.qml:83
696+#: qml/Wizard/Pages/79-system-update.qml:83
789697#, qt-format
790698msgctxt "version of the system update"
791699msgid "Version %1"
792−msgstr ""
700+msgstr "الإصدار %1"
793701
794−#: qml/Wizard/Pages/77-system-update.qml:102
702+#: qml/Wizard/Pages/79-system-update.qml:95
795703msgid "This could take a few minutes..."
796−msgstr ""
704+msgstr "قد يحتاج بضع دقائق..."
797705
798−#: qml/Wizard/Pages/77-system-update.qml:116
706+#: qml/Wizard/Pages/79-system-update.qml:109
799707msgid "Install and restart now"
800−msgstr ""
708+msgstr "ثبت وأعد التشغيل الآن"
801709
802−#: qml/Wizard/Pages/80-finished.qml:89
710+#: qml/Wizard/Pages/80-finished.qml:91
711+msgid "Welcome Back"
712+msgstr "مرحبا بعودتك"
713+
714+#: qml/Wizard/Pages/80-finished.qml:91
803715msgid "Welcome to Ubuntu"
804−msgstr ""
716+msgstr "مرحبا بك في أبونتو"
805717
806−#: qml/Wizard/Pages/80-finished.qml:104
718+#: qml/Wizard/Pages/80-finished.qml:106
807719msgid "You are ready to use your device now"
808−msgstr ""
720+msgstr "أنت مستعد لاستخدام جهازك"
809721
810−#: qml/Wizard/Pages/80-finished.qml:124
811−msgid "Get Started"
812−msgstr ""
722+#: qml/Wizard/Pages/80-finished.qml:126
723+msgid "Continue"
724+msgstr "تابع"
813725
814−#: qml/Wizard/Pages/here-terms.qml:25
815−msgid "Terms & Conditions"
816−msgstr "الشروط والأحكام"
817−
818−#: qml/Wizard/Pages/here-terms.qml:69
819−msgid "Your device uses positioning technologies provided by HERE."
820−msgstr ""
821−
822−#: qml/Wizard/Pages/here-terms.qml:81
823−msgid ""
824−"To provide you with positioning services and to improve their quality, HERE "
825−"collects information about nearby cell towers and Wi-Fi hotspots around your "
826−"current location whenever your position is being found."
827−msgstr ""
828−
829−#: qml/Wizard/Pages/here-terms.qml:93
830−msgid ""
831−"The information collected is used to analyze the service and to improve the "
832−"use of service, but not to identify you personally."
833−msgstr ""
834−
835−#: qml/Wizard/Pages/here-terms.qml:106
836−#, qt-format
837−msgid "By continuing, you agree to the HERE platform %1 and %2."
838−msgstr ""
839−
840−#: qml/Wizard/Pages/here-terms.qml:107
841−msgid "Service Terms"
842−msgstr ""
726+#: qml/Wizard/Pages/80-finished.qml:126
727+msgid "Get Started"
728+msgstr "ابدأ"
843729
844730#: qml/Wizard/Pages/passcode-confirm.qml:43
845−#: qml/Wizard/Pages/passcode-desktop.qml:97
731+#: qml/Wizard/Pages/passcode-desktop.qml:104
846732msgid "Confirm passcode"
847−msgstr "تأكيد الرمز السري"
733+msgstr "تأكيد كلمة السر"
848734
849735#: qml/Wizard/Pages/passcode-confirm.qml:45
850736msgid "Incorrect passcode."
851−msgstr ""
737+msgstr "الرمز السري غير صحيح."
852738
853739#: qml/Wizard/Pages/passcode-confirm.qml:45
854740msgctxt "Enter the passcode again"
855741msgid "Please re-enter."
856−msgstr ""
742+msgstr "رجاء أعد الإدخال."
857743
858744#: qml/Wizard/Pages/passcode-desktop.qml:31
859745msgid "Lock Screen Passcode"
860−msgstr ""
746+msgstr "الرمز السري لقفل الشاشة"
861747
862−#: qml/Wizard/Pages/passcode-desktop.qml:61
748+#: qml/Wizard/Pages/passcode-desktop.qml:68
863749msgid "Enter 4 numbers to setup your passcode"
864−msgstr ""
750+msgstr "أدخل 4 أرقام لإعداد الرمز السري"
865751
866−#: qml/Wizard/Pages/passcode-desktop.qml:77
752+#: qml/Wizard/Pages/passcode-desktop.qml:84
867753#: qml/Wizard/Pages/passcode-set.qml:54
868754msgid "Choose passcode"
869−msgstr ""
755+msgstr "اختر كلمة السر"
870756
871−#: qml/Wizard/Pages/passcode-desktop.qml:127
757+#: qml/Wizard/Pages/passcode-desktop.qml:139
872758msgid "Passcode too short"
873−msgstr ""
759+msgstr "الرمز السري قصير جدا"
874760
875−#: qml/Wizard/Pages/passcode-desktop.qml:129
761+#: qml/Wizard/Pages/passcode-desktop.qml:141
876762msgid "Passcodes match"
877−msgstr ""
763+msgstr "الرمزان السريان متطابقة"
878764
879−#: qml/Wizard/Pages/passcode-desktop.qml:131
765+#: qml/Wizard/Pages/passcode-desktop.qml:143
880766msgid "Passcodes do not match"
881−msgstr ""
767+msgstr "الرمزان السريان لا يتطبقان"
882768
883769#: qml/Wizard/Pages/passcode-set.qml:62
884770msgid "Passcode must be 4 characters long"
885−msgstr ""
771+msgstr "يجب أن يكون الرمز السري 4 محارف"
886772
887773#: qml/Wizard/Pages/password-set.qml:31
888774msgid "Lock Screen Password"
889−msgstr ""
775+msgstr "كلمة سر قفل الشاشة"
890776
891−#: qml/Wizard/Pages/password-set.qml:62
777+#: qml/Wizard/Pages/password-set.qml:68
892778msgid "Enter at least 8 characters"
893−msgstr ""
779+msgstr "أدخل 8 محارف على الأقل"
894780
895−#: qml/Wizard/Pages/password-set.qml:74
781+#: qml/Wizard/Pages/password-set.qml:80
896782msgid "Choose password"
897−msgstr ""
783+msgstr "اختر كلمة السر"
898784
899−#: qml/Wizard/Pages/password-set.qml:104
785+#: qml/Wizard/Pages/password-set.qml:110
900786msgid "Confirm password"
901−msgstr ""
787+msgstr "أكد كلمة السر"
902788
903789#: qml/Wizard/Pages/sim.qml:27
904790msgid "No SIM card installed"
905−msgstr ""
791+msgstr "لم تدخل بطاقة SIM"
906792
907793#: qml/Wizard/Pages/sim.qml:54
908794msgid "SIM card added"
909−msgstr ""
795+msgstr "أُدخلت بطاقة SIM"
910796
911797#: qml/Wizard/Pages/sim.qml:55
912798msgid "You must restart the device to access the mobile network."
913−msgstr ""
799+msgstr "يجب عليك إعادة تشغيل الجهاز لتتمكن من دخول شبكة الجوال."
914800
915801#: qml/Wizard/Pages/sim.qml:59
916802msgid "Restart"
917−msgstr ""
803+msgstr "أعد التشغيل"
918804
919805#: qml/Wizard/Pages/sim.qml:78
920806msgid "You won’t be able to make calls or use text messaging without a SIM."
921−msgstr ""
807+msgstr "لن تتمكن من إجراء المكالمات أو إرسال الرسائل القصيرة بدون بطاقة SIM."
922808
923809#: qml/Wizard/Pages/sim.qml:90
924810msgid "To proceed with no SIM tap Skip."
925−msgstr ""
811+msgstr "للاستمرار بدون بطاقة SIM اضغط تخطى."
926812
927813#: qml/Wizard/PasswordMeter.qml:87
928814msgid "Password too short"
929−msgstr ""
815+msgstr "كلمة السر قصيرة جداً"
930816
931817#: qml/Wizard/PasswordMeter.qml:89
932818msgid "Passwords match"
933−msgstr ""
819+msgstr "كلمتا المرور متطابقتان"
934820
935821#: qml/Wizard/PasswordMeter.qml:91
936822msgid "Passwords do not match"
937−msgstr ""
823+msgstr "كلمتا المرور غير متطابقتين"
938824
939825#: qml/Wizard/PasswordMeter.qml:95
940826msgid "Strong password"
941−msgstr ""
827+msgstr "كلمة سر قوية"
942828
943829#: qml/Wizard/PasswordMeter.qml:97
944830msgid "Fair password"
945−msgstr ""
831+msgstr "كلمة سر متوسطة"
946832
947833#: qml/Wizard/PasswordMeter.qml:99
948834msgid "Weak password"
949−msgstr ""
835+msgstr "كلمة سر ضعيفة"
950836
951837#: qml/Wizard/PasswordMeter.qml:101
952838msgid "Very weak password"
953−msgstr ""
839+msgstr "كلمة السر ضعيفة جداً"
840+
841+#~ msgid "Unity 8"
842+#~ msgstr "يونتي 8"
843+
844+#~ msgid "Super (Tap)"
845+#~ msgstr "Super (نقر)"
846+
847+#~ msgctxt "Button: Open the Ubuntu Store"
848+#~ msgid "Store"
849+#~ msgstr "المتجر"
850+
851+#~ msgctxt "Button: Start a search in the current dash scope"
852+#~ msgid "Search"
853+#~ msgstr "بحث"
854+
855+#~ msgctxt "Button: Show the current dash scope settings"
856+#~ msgid "Settings"
857+#~ msgstr "الإعدادات"
858+
859+#~ msgid "Remove from Favorites"
860+#~ msgstr "حذف من المفضلات"
861+
862+#~ msgid "Add to Favorites"
863+#~ msgstr "إضافة إلى المفضلات"
864+
865+#~ msgctxt "Label: Hint for dash search line edit"
866+#~ msgid "Search"
867+#~ msgstr "بحث"
868+
869+#~ msgid "More..."
870+#~ msgstr "المزيد..."
871+
872+#~ msgid "Less..."
873+#~ msgstr "أقل..."
874+
875+#~ msgid "Send"
876+#~ msgstr "أرسل"
877+
878+#~ msgid "Rate this"
879+#~ msgstr "قيّم ذلك"
880+
881+#~ msgid "Add a review"
882+#~ msgstr "أضف تعليق"
883+
884+#~ msgid "Enable location data"
885+#~ msgstr "تفعيل بيانات الموقع"
886+
887+#~ msgid "Manage"
888+#~ msgstr "إدارة"
889+
890+#~ msgid "Home"
891+#~ msgstr "الرئيسية"
892+
893+#~ msgid "Also installed"
894+#~ msgstr "أيضا تم تثبيت"
895+
896+#~ msgid "Privacy Policy"
897+#~ msgstr "سياسة الخصوصية"
898+
899+#~ msgid "Help Us Improve"
900+#~ msgstr "ساعدنا على التحسن"
901+
902+#~ msgid "Improve system performance by sending us crashes and error reports."
903+#~ msgstr "تحسين أداء النظام عير إرسال تقارير التوقف والأخطاء"
904+
905+#~ msgid "Privacy policy"
906+#~ msgstr "سياسة الخصوصية"
907+
908+#~ msgid "Update Apps"
909+#~ msgstr "تحديث التطبيقات"
910+
911+#~ msgid "This device is not connected to the internet."
912+#~ msgstr "الجهاز غير متصل باﻹنترنت"
913+
914+#, fuzzy
915+#~ msgid "Please wait..."
916+#~ msgstr "يجري التحميل. برجاء الانتظار..."
917+
918+#~ msgid "Update"
919+#~ msgstr "تحديث"
920+
921+#~ msgid "Download"
922+#~ msgstr "تنزيل"
923+
924+#~ msgid "Resume"
925+#~ msgstr "استئناف"
926+
927+#~ msgid "Pause"
928+#~ msgstr "إيقاف"
929+
930+#~ msgid "Install…"
931+#~ msgstr "تثبيت …"
932+
933+#~ msgid "Install"
934+#~ msgstr "تثبيت"
935+
936+#~ msgid "Open"
937+#~ msgstr "فتح"
938+
939+#~ msgid "Installing"
940+#~ msgstr "جاري التثبيت"
941+
942+#~ msgid "Paused"
943+#~ msgstr "تم اﻹيقاف"
944+
945+#~ msgid "Waiting to download"
946+#~ msgstr "انتظار التنزيل"
947+
948+#~ msgid "%1 of %2"
949+#~ msgstr "%1 من 2%"
950+
951+#, fuzzy
952+#~ msgid "Downloaded"
953+#~ msgstr "التنزيل"
954+
955+#, fuzzy
956+#~ msgid "Installed"
957+#~ msgstr "أيضا تم تثبيت"
958+
959+#~ msgid "Updated %1"
960+#~ msgstr "تحديث 1%"
961+
962+#~ msgid "Update failed"
963+#~ msgstr "فشل التحديث"
964+
965+#~ msgid "Terms & Conditions"
966+#~ msgstr "الشروط والأحكام"
954967
955968#~ msgid "Confirm"
956969#~ msgstr "التأكيد"
@@ -958,21 +971,9 @@ msgstr ""
958971#~ msgid "Type or say a command"
959972#~ msgstr "اكتب أو قُل أمرا"
960973
961−#~ msgid "Loading. Please Wait..."
962−#~ msgstr "يجري التحميل. برجاء الانتظار..."
963−
964974#~ msgid "Speak Now..."
965975#~ msgstr "تكلم الآن..."
966976
967−#~ msgid "Speaking..."
968−#~ msgstr "تتكلم الآن..."
969−
970−#~ msgid "Search"
971−#~ msgstr "ابحث"
972−
973−#~ msgid "Try swiping from the top edge to access the indicators"
974−#~ msgstr "اسحب اصبعك من الحافة العلوية للوصول إلى المؤشرات"
975−
976977#~ msgid "Top edge"
977978#~ msgstr "الحافة العلوية"
978979
@@ -1008,8 +1009,8 @@ msgstr ""
10081009#~ "You have now mastered the edge gestures and can start using the "
10091010#~ "phone<br><br>Tap on the screen to start"
10101011#~ msgstr ""
1011−#~ "أنت الآن بارع في إيماءات الحواف ويمكنك البدء باستخدام هاتفك<br><br>انقر على "
1012−#~ "الشاشة للبدء"
1012+#~ "أنت الآن بارع في إيماءات الحواف ويمكنك البدء باستخدام هاتفك<br><br>انقر "
1013+#~ "على الشاشة للبدء"
10131014
10141015#~ msgid "%a %l:%M %p"
10151016#~ msgstr "%a %l:%M %p"
@@ -1062,26 +1063,18 @@ msgstr ""
10621063#~ msgid "Tap to unlock"
10631064#~ msgstr "انقر لفك القفل"
10641065
1065−#, qt-format
10661066#~ msgid "Enter %1"
10671067#~ msgstr "أدخِل %1"
10681068
10691069#~ msgid "Sorry, incorrect passcode."
10701070#~ msgstr "عذرًا، رمز سرّي خاطيء."
10711071
1072−#~ msgid "Enter passphrase"
1073−#~ msgstr "أدخِل العبارة السرية"
1074−
1075−#~ msgid "Enter passcode"
1076−#~ msgstr "أدخِل الرمز السرّي"
1077−
10781072#~ msgid "Sorry, incorrect passphrase."
10791073#~ msgstr "عذرًا، عبارة سرّية خاطئة."
10801074
10811075#~ msgid "This will be your last attempt."
10821076#~ msgstr "هذه ستكون المحاولة الأخيرة لك."
10831077
1084−#, qt-format
10851078#~ msgid "Sorry, incorrect %1"
10861079#~ msgstr "نأسف، %1 غير صحيحية"
10871080
@@ -1152,9 +1145,6 @@ msgstr ""
11521145#~ msgid "Let’s get started."
11531146#~ msgstr "هيا بنا نبدأ."
11541147
1155−#~ msgid "Continue"
1156−#~ msgstr "متابعة"
1157−
11581148#~ msgid "Choose your passcode"
11591149#~ msgstr "اختر الرمز السري خاصتك"
11601150
@@ -1251,15 +1241,15 @@ msgstr ""
12511241#~ msgstr "فتح قفل بطاقة SIM"
12521242
12531243#~ msgid ""
1254−#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
1255−#~ "conditions</a>."
1244+#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms "
1245+#~ "and conditions</a>."
12561246#~ msgstr ""
1257−#~ "باختيارك لهذا الخيار فإنك توافق على <a href='#'>الشروط والأحكام</a> الخاصة "
1258−#~ "بـ Nokia HERE."
1247+#~ "باختيارك لهذا الخيار فإنك توافق على <a href='#'>الشروط والأحكام</a> "
1248+#~ "الخاصة بـ Nokia HERE."
12591249
12601250#~ msgid ""
1261−#~ "If passcode is entered incorrectly, your phone will conduct a factory reset "
1262−#~ "and all personal data will be deleted."
1251+#~ "If passcode is entered incorrectly, your phone will conduct a factory "
1252+#~ "reset and all personal data will be deleted."
12631253#~ msgstr ""
12641254#~ "إذا تم إدخال العبارة السرية بشكل خاطئ، فسوف يتم إعادة الهاتف لحالة ضبط "
12651255#~ "المصنع وسيتم حذف كافة البيانات الشخصية."
po/ast.po+542−484
@@ -6,108 +6,143 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
9−"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2017-01-10 14:48+0000\n"
11−"PO-Revision-Date: 2016-12-16 02:13+0000\n"
9+"Report-Msgid-Bugs-To: \n"
10+"POT-Creation-Date: 2021-01-29 11:42-0600\n"
11+"PO-Revision-Date: 2019-10-30 03:35+0000\n"
1212"Last-Translator: enolp <enolp@softastur.org>\n"
13−"Language-Team: Asturian <ast@li.org>\n"
13+"Language-Team: Asturian <https://translate.ubports.com/projects/unity8/"
14+"unity8/ast/>\n"
15+"Language: ast\n"
1416"MIME-Version: 1.0\n"
1517"Content-Type: text/plain; charset=UTF-8\n"
1618"Content-Transfer-Encoding: 8bit\n"
1719"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2017-01-16 05:47+0000\n"
19−"X-Generator: Launchpad (build 18302)\n"
20+"X-Generator: Weblate 3.8\n"
21+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
2022
21−#: plugins/LightDM/Greeter.cpp:123
23+#: plugins/LightDM/Greeter.cpp:199
2224msgid "Password: "
2325msgstr "Contraseña: "
2426
25−#: plugins/Unity/Launcher/launcheritem.cpp:50
27+#: plugins/LightDM/Greeter.cpp:214
28+msgid "Username"
29+msgstr ""
30+
31+#: plugins/LightDM/Greeter.cpp:258
32+msgid "Failed to authenticate"
33+msgstr ""
34+
35+#: plugins/LightDM/Greeter.cpp:260
36+msgid "Invalid password, please try again"
37+msgstr ""
38+
39+#: plugins/LightDM/Greeter.cpp:270
40+msgid "Log In"
41+msgstr ""
42+
43+#: plugins/LightDM/Greeter.cpp:270
44+msgid "Retry"
45+msgstr ""
46+
47+#: plugins/LightDM/UsersModel.cpp:157
48+msgid "Login"
49+msgstr ""
50+
51+#: plugins/LightDM/UsersModel.cpp:165
52+msgid "Guest Session"
53+msgstr ""
54+
55+#: plugins/Unity/Launcher/launcheritem.cpp:48
2656#: plugins/Unity/Launcher/launcheritem.cpp:122
2757msgid "Pin shortcut"
28−msgstr "Anclar atayu"
58+msgstr "Fixar l'atayu"
2959
30−#: plugins/Unity/Launcher/launcheritem.cpp:55
60+#: plugins/Unity/Launcher/launcheritem.cpp:54
3161msgid "Quit"
3262msgstr "Colar"
3363
3464#: plugins/Unity/Launcher/launcheritem.cpp:122
3565msgid "Unpin shortcut"
36−msgstr "Desanclar atayu"
66+msgstr "Quitar l'atayu"
3767
38−#: qml/Components/Dialogs.qml:149
68+#: qml/Components/Dialogs.qml:176
3969msgctxt "Title: Lock/Log out dialog"
4070msgid "Log out"
41−msgstr "Zarrar sesión"
71+msgstr "Zarru de la sesión"
4272
43−#: qml/Components/Dialogs.qml:150
73+#: qml/Components/Dialogs.qml:177
4474msgid "Are you sure you want to log out?"
4575msgstr "¿De xuru que quies zarrar la sesión?"
4676
47−#: qml/Components/Dialogs.qml:152
77+#: qml/Components/Dialogs.qml:180
4878msgctxt "Button: Lock the system"
4979msgid "Lock"
5080msgstr "Bloquiar"
5181
52−#: qml/Components/Dialogs.qml:160
82+#: qml/Components/Dialogs.qml:191
5383msgctxt "Button: Log out from the system"
5484msgid "Log Out"
5585msgstr "Zarrar sesión"
5686
57−#: qml/Components/Dialogs.qml:167 qml/Components/Dialogs.qml:225
58−#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:232
59−#: qml/Wizard/Pages/passcode-confirm.qml:32
87+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
88+#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
6089#: qml/Wizard/Pages/passcode-set.qml:32
6190msgid "Cancel"
6291msgstr "Encaboxar"
6392
64−#: qml/Components/Dialogs.qml:179
93+#: qml/Components/Dialogs.qml:211
6594msgctxt "Title: Reboot dialog"
6695msgid "Reboot"
6796msgstr "Reaniciu"
6897
69−#: qml/Components/Dialogs.qml:180
98+#: qml/Components/Dialogs.qml:212
7099msgid "Are you sure you want to reboot?"
71100msgstr "¿De xuru que quies reaniciar?"
72101
73−#: qml/Components/Dialogs.qml:182
102+#: qml/Components/Dialogs.qml:215
74103msgid "No"
75104msgstr "Non"
76105
77−#: qml/Components/Dialogs.qml:189
106+#: qml/Components/Dialogs.qml:223
78107msgid "Yes"
79108msgstr "Sí"
80109
81−#: qml/Components/Dialogs.qml:204
110+#: qml/Components/Dialogs.qml:243
82111msgctxt "Title: Power off/Restart dialog"
83112msgid "Power"
84−msgstr "Apagáu"
113+msgstr "Enerxía"
85114
86−#: qml/Components/Dialogs.qml:205
115+#: qml/Components/Dialogs.qml:244
87116msgid ""
88117"Are you sure you would like\n"
89118"to power off?"
90119msgstr ""
91−"¿De xuru que te prestaría\n"
120+"¿De xuru que quies\n"
92121"apagar?"
93122
94−#: qml/Components/Dialogs.qml:208
123+#: qml/Components/Dialogs.qml:248
95124msgctxt "Button: Power off the system"
96125msgid "Power off"
97126msgstr "Apagar"
98127
99−#: qml/Components/Dialogs.qml:217
128+#: qml/Components/Dialogs.qml:263
100129msgctxt "Button: Restart the system"
101130msgid "Restart"
102131msgstr "Reaniciar"
103132
133+#: qml/Components/Dialogs.qml:276
134+#, fuzzy
135+#| msgid "Takes a screenshot."
136+msgid "Screenshot"
137+msgstr "Fai una captura de pantalla."
138+
104139#: qml/Components/KeyboardShortcutsOverlay.qml:41
105140msgid "Keyboard Shortcuts"
106−msgstr "Atayos de tecláu"
141+msgstr "Atayos del tecláu"
107142
108143#: qml/Components/KeyboardShortcutsOverlay.qml:55
109−msgid "Unity 8"
110−msgstr "Unity 8"
144+msgid "Lomiri"
145+msgstr ""
111146
112147#: qml/Components/KeyboardShortcutsOverlay.qml:62
113148msgid "PrtScr"
@@ -115,171 +150,177 @@ msgstr "ImprPant"
115150
116151#: qml/Components/KeyboardShortcutsOverlay.qml:67
117152msgid "Takes a screenshot."
118−msgstr "Saca una imaxe de la pantalla."
153+msgstr "Fai una captura de pantalla."
119154
120155#: qml/Components/KeyboardShortcutsOverlay.qml:75
121156msgid "Alt + PrtScr"
122157msgstr "Alt + ImprPant"
123158
124159#: qml/Components/KeyboardShortcutsOverlay.qml:80
125−msgid "Takes a screenshot of a window."
126−msgstr "Saca una imaxe d'una ventana."
160+#, fuzzy
161+#| msgid "Takes a screenshot of a window."
162+msgid "Takes a screenshot of the current window."
163+msgstr "Fai una captura d'una ventana."
127164
128165#: qml/Components/KeyboardShortcutsOverlay.qml:88
129166msgid "Super + Space"
130−msgstr "Super + Espaciu"
167+msgstr "Súper + Espaciu"
131168
132169#: qml/Components/KeyboardShortcutsOverlay.qml:93
133170msgid "Switches to next keyboard layout."
134−msgstr "Salta al siguiente diseñu de tecláu."
171+msgstr "Cambia a la distribución siguiente del tecláu."
135172
136173#: qml/Components/KeyboardShortcutsOverlay.qml:101
137174msgid "Super + Shift + Space"
138−msgstr "Super +Mayús + Espaciu"
175+msgstr "Súper + Mayús + Espaciu"
139176
140177#: qml/Components/KeyboardShortcutsOverlay.qml:106
141178msgid "Switches to previous keyboard layout."
142−msgstr "Salta al diseñu de tecláu anterior."
179+msgstr "Cambia a la distribución anterior del tecláu."
143180
144−#: qml/Components/KeyboardShortcutsOverlay.qml:118
181+#: qml/Components/KeyboardShortcutsOverlay.qml:114
182+#, fuzzy
183+#| msgid "Ctrl + Super + D"
184+msgid "Ctrl + Alt + T"
185+msgstr "Ctrl + Súper + D"
186+
187+#: qml/Components/KeyboardShortcutsOverlay.qml:119
188+msgid "Starts the Terminal application."
189+msgstr ""
190+
191+#: qml/Components/KeyboardShortcutsOverlay.qml:131
145192msgid "Launcher"
146193msgstr "Llanzador"
147194
148−#: qml/Components/KeyboardShortcutsOverlay.qml:125
195+#: qml/Components/KeyboardShortcutsOverlay.qml:138
149196msgid "Super (Hold)"
150−msgstr "Super (Caltener)"
197+msgstr ""
151198
152−#: qml/Components/KeyboardShortcutsOverlay.qml:130
199+#: qml/Components/KeyboardShortcutsOverlay.qml:143
153200msgid "Opens the launcher, displays shortcuts."
154−msgstr "Abre'l llanzador, amuesa atayos."
201+msgstr "Abre'l llanzador, amuesa los atayos."
155202
156−#: qml/Components/KeyboardShortcutsOverlay.qml:138
203+#: qml/Components/KeyboardShortcutsOverlay.qml:151
157204msgid "Alt + F1"
158205msgstr "Alt + F1"
159206
160−#: qml/Components/KeyboardShortcutsOverlay.qml:143
207+#: qml/Components/KeyboardShortcutsOverlay.qml:156
161208msgid "Opens launcher keyboard navigation mode."
162−msgstr "Abre'l mou de navegación con tecláu del llanzador."
209+msgstr ""
163210
164−#: qml/Components/KeyboardShortcutsOverlay.qml:151
211+#: qml/Components/KeyboardShortcutsOverlay.qml:164
165212msgid "Super + Tab"
166−msgstr "Super + Tab"
213+msgstr "Súper + Tabulador"
167214
168−#: qml/Components/KeyboardShortcutsOverlay.qml:156
215+#: qml/Components/KeyboardShortcutsOverlay.qml:169
169216msgid "Switches applications via the launcher."
170−msgstr "Cambia d'aplicaciones col llanzador."
217+msgstr ""
171218
172−#: qml/Components/KeyboardShortcutsOverlay.qml:164
173−msgid "Super + 0 to 9"
174−msgstr "Super + 0 a 9"
219+#: qml/Components/KeyboardShortcutsOverlay.qml:177
220+#, fuzzy
221+#| msgid "Super + 0 to 9"
222+msgid "Super + 1 to 0"
223+msgstr "Súper + 0 a 9"
175224
176−#: qml/Components/KeyboardShortcutsOverlay.qml:169
225+#: qml/Components/KeyboardShortcutsOverlay.qml:182
177226msgid "Same as clicking on a launcher icon."
178−msgstr "Igual que facer click nel iconu del llanzador."
227+msgstr "Igual que calcar nun iconu del llanzador."
179228
180−#: qml/Components/KeyboardShortcutsOverlay.qml:177
229+#: qml/Components/KeyboardShortcutsOverlay.qml:190
230+#, fuzzy
231+#| msgid "Super + W"
181232msgid "Super + A"
182−msgstr ""
233+msgstr "Súper + W"
183234
184−#: qml/Components/KeyboardShortcutsOverlay.qml:182
235+#: qml/Components/KeyboardShortcutsOverlay.qml:195
236+#, fuzzy
237+#| msgid "Open the launcher"
185238msgid "Opens the Application Drawer."
186−msgstr "Abre'l caxón d'aplicaciones."
187−
188−#: qml/Components/KeyboardShortcutsOverlay.qml:194
189−msgid "Scopes"
190−msgstr "Ámbitos"
191−
192−#: qml/Components/KeyboardShortcutsOverlay.qml:201
193−msgid "Super (Tap)"
194−msgstr "Super (Tocar)"
239+msgstr "Abrir el llanzador"
195240
196−#: qml/Components/KeyboardShortcutsOverlay.qml:206
197−msgid "Opens the Scopes home."
198−msgstr "Abre'l principiu d'Ámbitos"
199−
200−#: qml/Components/KeyboardShortcutsOverlay.qml:222
241+#: qml/Components/KeyboardShortcutsOverlay.qml:235
201242msgid "Switching"
202−msgstr "Conmutación"
243+msgstr "Cambéu"
203244
204−#: qml/Components/KeyboardShortcutsOverlay.qml:229
245+#: qml/Components/KeyboardShortcutsOverlay.qml:242
205246msgid "Alt + Tab"
206−msgstr "Alt + Tab"
247+msgstr "Alt + Tabulador"
207248
208−#: qml/Components/KeyboardShortcutsOverlay.qml:234
249+#: qml/Components/KeyboardShortcutsOverlay.qml:247
209250msgid "Switches between applications."
210−msgstr "Conmuta ente aplicaciones."
251+msgstr ""
211252
212−#: qml/Components/KeyboardShortcutsOverlay.qml:242
253+#: qml/Components/KeyboardShortcutsOverlay.qml:255
213254msgid "Super + W"
214−msgstr "Super + W"
255+msgstr "Súper + W"
215256
216−#: qml/Components/KeyboardShortcutsOverlay.qml:247
257+#: qml/Components/KeyboardShortcutsOverlay.qml:260
217258msgid "Opens the desktop spread."
218−msgstr "Abre esparder l'escritoriu."
259+msgstr ""
219260
220−#: qml/Components/KeyboardShortcutsOverlay.qml:255
261+#: qml/Components/KeyboardShortcutsOverlay.qml:268
221262msgid "Cursor Left or Right"
222−msgstr "Flecha izq. o dre."
263+msgstr ""
223264
224−#: qml/Components/KeyboardShortcutsOverlay.qml:260
265+#: qml/Components/KeyboardShortcutsOverlay.qml:273
225266msgid "Moves the focus."
226−msgstr "Mueve'l focu"
267+msgstr "Mueve'l focu."
227268
228−#: qml/Components/KeyboardShortcutsOverlay.qml:272
269+#: qml/Components/KeyboardShortcutsOverlay.qml:285
229270msgid "Windows"
230−msgstr "Ventanes"
271+msgstr ""
231272
232−#: qml/Components/KeyboardShortcutsOverlay.qml:279
273+#: qml/Components/KeyboardShortcutsOverlay.qml:292
233274msgid "Ctrl + Super + D"
234−msgstr "Ctrl + Super + D"
275+msgstr "Ctrl + Súper + D"
235276
236−#: qml/Components/KeyboardShortcutsOverlay.qml:284
277+#: qml/Components/KeyboardShortcutsOverlay.qml:297
237278msgid "Minimizes all windows."
238−msgstr "Amenorga toles ventanes."
279+msgstr "Minimiza toles ventanes."
239280
240−#: qml/Components/KeyboardShortcutsOverlay.qml:292
281+#: qml/Components/KeyboardShortcutsOverlay.qml:305
241282msgid "Ctrl + Super + Up"
242−msgstr "Ctrl + Super + Arriba"
283+msgstr "Ctrl + Súper + Arriba"
243284
244−#: qml/Components/KeyboardShortcutsOverlay.qml:297
285+#: qml/Components/KeyboardShortcutsOverlay.qml:310
245286msgid "Maximizes the current window."
246287msgstr "Maximiza la ventana actual."
247288
248−#: qml/Components/KeyboardShortcutsOverlay.qml:305
289+#: qml/Components/KeyboardShortcutsOverlay.qml:318
249290msgid "Ctrl + Super + Down"
250−msgstr "Ctrl + Super + Abaxo"
291+msgstr "Ctrl + Súper + Abaxo"
251292
252−#: qml/Components/KeyboardShortcutsOverlay.qml:310
293+#: qml/Components/KeyboardShortcutsOverlay.qml:323
253294msgid "Minimizes or restores the current window."
254−msgstr "Amenorga o restaura la ventana actual."
295+msgstr "Minimiza o restaura la ventana actual."
255296
256−#: qml/Components/KeyboardShortcutsOverlay.qml:318
297+#: qml/Components/KeyboardShortcutsOverlay.qml:331
257298msgid "Ctrl + Super + Left or Right"
258−msgstr "Ctrl + Super + Izquierda o Drecha"
299+msgstr "Ctrl + Súper + Esquierda o Drecha"
259300
260−#: qml/Components/KeyboardShortcutsOverlay.qml:323
301+#: qml/Components/KeyboardShortcutsOverlay.qml:336
261302msgid "Semi-maximizes the current window."
262−msgstr "Semi-maximiza la ventana actual."
303+msgstr ""
263304
264−#: qml/Components/KeyboardShortcutsOverlay.qml:331
305+#: qml/Components/KeyboardShortcutsOverlay.qml:344
265306msgid "Alt + F4"
266307msgstr "Alt + F4"
267308
268−#: qml/Components/KeyboardShortcutsOverlay.qml:336
309+#: qml/Components/KeyboardShortcutsOverlay.qml:349
269310msgid "Closes the current window."
270−msgstr "Zarra la ventana actual."
311+msgstr "Zarra toles ventanes actuales."
271312
272−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:252
313+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
273314msgid "Return to Call"
274−msgstr "Tornar a la llamada"
315+msgstr ""
275316
276317#: qml/Components/Lockscreen.qml:212
277318msgid "Emergency Call"
278319msgstr "Llamada d'emerxencia"
279320
280−#: qml/Components/Lockscreen.qml:244
321+#: qml/Components/Lockscreen.qml:245
281322msgid "OK"
282−msgstr "Aceutar"
323+msgstr ""
283324
284325#: qml/Components/MediaServices/VideoPlayerControls.qml:44
285326#, qt-format
@@ -291,156 +332,61 @@ msgstr "%1:%2:%3"
291332msgid "%1:%2"
292333msgstr "%1:%2"
293334
294−#: qml/Components/ModeSwitchWarningDialog.qml:32
335+#: qml/Components/ModeSwitchWarningDialog.qml:33
295336msgid "Apps may have unsaved data:"
296−msgstr "Apps que pueden tener datos sin guardar:"
337+msgstr "Aplicaciones con datos ensin guardar:"
297338
298−#: qml/Components/ModeSwitchWarningDialog.qml:57
339+#: qml/Components/ModeSwitchWarningDialog.qml:60
299340msgctxt ""
300341"Re-dock means connect the device again to an external screen/mouse/keyboard"
301342msgid "Re-dock, save your work and close these apps to continue."
302−msgstr "Reconeuta, guarda'l trabayu y zarra eses apps pa siguir."
343+msgstr ""
303344
304−#: qml/Components/ModeSwitchWarningDialog.qml:63
345+#: qml/Components/ModeSwitchWarningDialog.qml:67
305346msgid "Or force close now (unsaved data will be lost)."
306−msgstr "O fuerza salir agora (perderás tolos datos sin guardar)."
347+msgstr ""
307348
308−#: qml/Components/ModeSwitchWarningDialog.qml:75
349+#: qml/Components/ModeSwitchWarningDialog.qml:80
309350msgid "OK, I will reconnect"
310−msgstr "D'alcuerdu, reconeutaré"
351+msgstr ""
311352
312−#: qml/Components/ModeSwitchWarningDialog.qml:76
353+#: qml/Components/ModeSwitchWarningDialog.qml:81
313354msgid "Reconnect now!"
314−msgstr "Reconeutar agora."
355+msgstr ""
315356
316−#: qml/Components/ModeSwitchWarningDialog.qml:88
357+#: qml/Components/ModeSwitchWarningDialog.qml:94
317358msgid "Close all"
318359msgstr "Zarrar too"
319360
320361#: qml/Components/SharingPicker.qml:54
321362msgid "Preview Share Item"
322−msgstr "Entever l'elementu compartíu"
363+msgstr ""
323364
324365#: qml/Components/VirtualTouchPad.qml:317
325366msgid ""
326367"Your device is now connected to an external display. Use this screen as a "
327368"touch pad to interact with the pointer."
328369msgstr ""
329−"El preséu agora ta coneutáu con una pantalla esterna. Usa esta pantalla como "
330−"touch pad pa interactuar col punteru."
370+"Agora'l preséu ta coneutáu a una pantalla esterna. Usa esta pantalla como "
371+"panel táutil pa interactuar col punteru."
331372
332373#: qml/Components/VirtualTouchPad.qml:327
374+#, fuzzy
375+#| msgid "Tap to return to call..."
333376msgid "Tap left button to click."
334−msgstr "Calca nel botón esquierdu pa facer clic."
377+msgstr "Toca pa volver a la llamada…"
335378
336379#: qml/Components/VirtualTouchPad.qml:339
337380msgid "Tap right button to right click."
338−msgstr "Calca nel botón drechu pa facer clic."
381+msgstr ""
339382
340383#: qml/Components/VirtualTouchPad.qml:351
341384msgid "Swipe with two fingers to scroll."
342−msgstr "Esliza con dos deos pa desplazate."
385+msgstr ""
343386
344387#: qml/Components/VirtualTouchPad.qml:396
345388msgid "Find more settings in the system settings."
346−msgstr "Alcuentra más axustes nos Axustes del Sistema."
347−
348−#: qml/Dash/DashPageHeader.qml:361
349−msgctxt "Button: Open the Ubuntu Store"
350−msgid "Store"
351−msgstr "Tienda"
352−
353−#: qml/Dash/DashPageHeader.qml:368
354−msgctxt "Button: Start a search in the current dash scope"
355−msgid "Search"
356−msgstr "Guetar"
357−
358−#: qml/Dash/DashPageHeader.qml:378
359−msgctxt "Button: Show the current dash scope settings"
360−msgid "Settings"
361−msgstr "Axustes"
362−
363−#: qml/Dash/DashPageHeader.qml:385
364−msgid "Remove from Favorites"
365−msgstr "Desaniciar de favoritos"
366−
367−#: qml/Dash/DashPageHeader.qml:385
368−msgid "Add to Favorites"
369−msgstr "Amestar a favoritos"
370−
371−#: qml/Dash/FiltersPopover.qml:61
372−msgid "Refine your results"
373−msgstr "Refina los resultaos"
374−
375−#: qml/Dash/FiltersPopover.qml:70
376−msgid "Reset"
377−msgstr "Reafitar"
378−
379−#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
380−msgid "Show less"
381−msgstr "Ver menos"
382−
383−#: qml/Dash/GenericScopeView.qml:547
384−msgid "Show all"
385−msgstr "Ver too"
386−
387−#: qml/Dash/GenericScopeView.qml:578
388−msgctxt "Label: Hint for dash search line edit"
389−msgid "Search"
390−msgstr "Guetar"
391−
392−#: qml/Dash/PageHeaderExtraPanel.qml:67
393−msgid "Recent Searches"
394−msgstr "Guetes recién"
395−
396−#: qml/Dash/PageHeaderExtraPanel.qml:78
397−msgid "Clear All"
398−msgstr "Llimpiar too"
399−
400−#: qml/Dash/Previews/PreviewActionCombo.qml:36
401−msgid "More..."
402−msgstr "Más…"
403−
404−#: qml/Dash/Previews/PreviewActionCombo.qml:36
405−msgid "Less..."
406−msgstr "Menos…"
407−
408−#: qml/Dash/Previews/PreviewCommentInput.qml:83
409−#: qml/Dash/Previews/PreviewRatingInput.qml:202
410−msgid "Send"
411−msgstr "Unviar"
412−
413−#: qml/Dash/Previews/PreviewRatingInput.qml:109
414−msgid "Rate this"
415−msgstr "Valorar esto"
416−
417−#: qml/Dash/Previews/PreviewRatingInput.qml:184
418−msgid "Add a review"
419−msgstr "Amestar una reseña"
420−
421−#: qml/Dash/PullToRefreshScopeStyle.qml:56
422−msgid "Pull to refresh…"
423−msgstr "Tira p'anovar..."
424−
425−#: qml/Dash/PullToRefreshScopeStyle.qml:61
426−msgid "Release to refresh…"
427−msgstr "Sueltar p'anovar..."
428−
429−#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
430−msgid "Enable location data"
431−msgstr "Habilitar datos d'allugamientu"
432−
433−#: qml/Dash/ScopesList.qml:146
434−msgid "Manage"
435−msgstr "Xestionar"
436−
437−#: qml/Dash/ScopesList.qml:187
438−msgid "Home"
439−msgstr "Aniciu"
440−
441−#: qml/Dash/ScopesList.qml:188
442−msgid "Also installed"
443−msgstr "Tamién instalaos"
389+msgstr ""
444390
445391#: qml/Greeter/CoverPage.qml:127
446392msgid "Unlock"
@@ -452,68 +398,75 @@ msgstr "Preséu bloquiáu"
452398
453399#: qml/Greeter/DelayedLockscreen.qml:58
454400msgid "You have been locked out due to too many failed passphrase attempts."
455−msgstr "Quedasti bloquiáu polos escesivos intentos fallíos de fras de pasu."
401+msgstr ""
402+"Bloquióse'l preséu dempués d'introducir mal el códigu numbéricu milenta "
403+"vegaes."
456404
457405#: qml/Greeter/DelayedLockscreen.qml:59
458406msgid "You have been locked out due to too many failed passcode attempts."
459407msgstr ""
460−"Quedasti bloquiáu polos escesivos intentos fallíos de códigu de pasu."
408+"Bloquióse'l preséu dempués d'introducir mal la contraseña milenta vegaes."
461409
462410#: qml/Greeter/DelayedLockscreen.qml:68
463411#, qt-format
464412msgid "Please wait %1 minute and then try again…"
465413msgid_plural "Please wait %1 minutes and then try again…"
466−msgstr[0] "Por favor, espera %1 minutu y vuelvi a intentalo…"
467−msgstr[1] "Por favor, espera %1 minutos y vuelvi a intentalo…"
414+msgstr[0] "Espera %1 minutu y volvi tentalo darréu…"
415+msgstr[1] "Espera %1 minutos y volvi tentalo darréu…"
468416
469−#: qml/Greeter/Greeter.qml:592
417+#: qml/Greeter/Greeter.qml:550
470418msgid "Try again"
471−msgstr "Tentar otra vuelta"
472−
473−#: qml/Greeter/LoginList.qml:70
474−msgid "Passphrase"
475−msgstr "Fras de pasu"
476−
477−#: qml/Greeter/LoginList.qml:71
478−msgid "Passcode"
479−msgstr "Códigu de pasu"
419+msgstr ""
480420
481−#: qml/Greeter/LoginList.qml:98
482−msgid "Retry"
483−msgstr "Reintentar"
421+#: qml/Greeter/Greeter.qml:551
422+#, fuzzy
423+#| msgid "Enter passphrase"
424+msgid "Enter passphrase to unlock"
425+msgstr "Introduz la fras de pasu"
484426
485−#: qml/Greeter/LoginList.qml:99
486−msgid "Log In"
487−msgstr "Aniciar sesión"
427+#: qml/Greeter/Greeter.qml:552
428+#, fuzzy
429+#| msgid "Enter passcode"
430+msgid "Enter passcode to unlock"
431+msgstr "Introduz el códigu de pasu"
488432
489−#: qml/Greeter/NarrowView.qml:252
433+#: qml/Greeter/NarrowView.qml:235
490434msgid "Emergency"
491435msgstr "Emerxencia"
492436
493−#: qml/Greeter/SessionsList.qml:122
437+#: qml/Greeter/PromptList.qml:126
438+msgid "Passphrase"
439+msgstr "Fras de pasu"
440+
441+#: qml/Greeter/PromptList.qml:126
442+msgid "Passcode"
443+msgstr "Códigu numbéricu"
444+
445+#: qml/Greeter/SessionsList.qml:124
494446msgid "Select desktop environment"
495−msgstr "Esbillar entornu d'escritoriu"
447+msgstr ""
496448
497−#: qml/Launcher/Drawer.qml:80
449+#: qml/Launcher/Drawer.qml:250
450+#, fuzzy
451+#| msgid "Search"
498452msgid "Search…"
499−msgstr "Guetar..."
453+msgstr "Guetar"
500454
501−#: qml/Launcher/Drawer.qml:101
502−msgctxt "Apps sorted alphabetically"
503−msgid "A-Z"
504−msgstr "A-Z"
455+#: qml/Launcher/PullToRefreshScopeStyle.qml:56
456+msgid "Pull to refresh…"
457+msgstr "Tira pa refrescar…"
505458
506−#: qml/Launcher/MoreAppsHeader.qml:32
507−msgid "More apps in the store"
508−msgstr "Más aplicaciones na tienda"
459+#: qml/Launcher/PullToRefreshScopeStyle.qml:61
460+msgid "Release to refresh…"
461+msgstr "Suelta pa refrescar…"
509462
510463#: qml/Notifications/NotificationMenuItemFactory.qml:124
511464msgid "Show password"
512−msgstr "Amosar contraseña"
465+msgstr "Amosar la contraseña"
513466
514467#: qml/Panel/ActiveCallHint.qml:79
515468msgid "Tap to return to call..."
516−msgstr "Toca pa tornar a la llamada..."
469+msgstr "Toca pa volver a la llamada…"
517470
518471#: qml/Panel/ActiveCallHint.qml:92
519472msgid "Conference"
@@ -521,7 +474,7 @@ msgstr "Conferencia"
521474
522475#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:869
523476msgid "Nothing is playing"
524−msgstr "Nun ta reproduciéndose nada"
477+msgstr "Nada en reproducción"
525478
526479#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:997
527480#, qt-format
@@ -552,11 +505,11 @@ msgstr "0 segundos"
552505#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1011
553506#, qt-format
554507msgid "%1 remaining"
555−msgstr "Queden %1"
508+msgstr "%1 restante(s)"
556509
557510#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1017
558511msgid "In queue…"
559−msgstr "Na cola..."
512+msgstr "Na cola…"
560513
561514#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1021
562515msgid "Downloading"
@@ -564,11 +517,11 @@ msgstr "Baxando"
564517
565518#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1023
566519msgid "Paused, tap to resume"
567−msgstr "Posáu, toca pa reanudar"
520+msgstr "Posóse, toca pa siguir"
568521
569522#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1025
570523msgid "Canceled"
571−msgstr "Encaboxáu"
524+msgstr "Encaboxóse"
572525
573526#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1027
574527msgid "Finished"
@@ -576,7 +529,7 @@ msgstr "Finó"
576529
577530#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1029
578531msgid "Failed, tap to retry"
579−msgstr "Falló, toca pa reintentar"
532+msgstr "Falló, toca pa retentar"
580533
581534#: qml/Panel/Indicators/MessageMenuItemFactory.qml:151
582535#: qml/Panel/Indicators/MessageMenuItemFactory.qml:210
@@ -587,61 +540,88 @@ msgstr "Unviar"
587540#: qml/Panel/Indicators/MessageMenuItemFactory.qml:152
588541msgctxt "Label: Hint in message indicator line edit"
589542msgid "Reply"
590−msgstr "Responder"
543+msgstr ""
591544
592545#: qml/Panel/Indicators/MessageMenuItemFactory.qml:209
593546msgctxt "Button: Call back on phone"
594547msgid "Call back"
595−msgstr "Devolver llamada"
548+msgstr "Rellamar"
549+
550+#: qml/Panel/PanelMenuPage.qml:92
551+#, fuzzy
552+#| msgctxt "Button: Go back one page in the Wizard"
553+#| msgid "Back"
554+msgid "Back"
555+msgstr "Atrás"
596556
597557#: qml/Stage/SideStage.qml:76
598558msgid "Drag using 3 fingers any application from one window to the other"
599−msgstr "Abasnar cualquier aplicación d'una ventana a otra usando 3 deos"
559+msgstr "Arrastra con tres deos cualquier aplicación dende una ventana a otra"
560+
561+#: qml/Stage/Stage.qml:671
562+msgid "No running apps"
563+msgstr ""
600564
601565#: qml/Tutorial/TutorialLeftLong.qml:49
602−msgid "Long swipe from the left edge to open the Today scope"
603−msgstr "Eslizamientu llargu dende'l berbesu izquierdu pa ver el scope Güei"
566+#, fuzzy
567+#| msgid "Long swipe from the left edge to open the Today scope"
568+msgid "Long swipe from the left edge to open the Application Drawer"
569+msgstr "Eslizamientu llargu dende'l berbesu esquierdu p'abrir l'ámbitu Güei"
604570
605571#: qml/Tutorial/TutorialLeft.qml:47
606572msgid "Short swipe from the left edge to open the launcher"
607−msgstr "Barríu curtiu dende'l berbesu izquierdu p'abrir el llanzador"
573+msgstr "Esliza dende'l berbesu esquierdu p'abrir el llanzador"
608574
609−#: qml/Tutorial/TutorialRight.qml:55
575+#: qml/Tutorial/TutorialRight.qml:54
610576msgid "Push your mouse against the right edge to view your open apps"
611−msgstr "Emburria'l mur escontra'l berbesu drechu pa ver les apps abiertes"
577+msgstr "Lleva'l mur al berbesu drechu pa ver les aplicaciones abiertes"
612578
613−#: qml/Tutorial/TutorialRight.qml:56
579+#: qml/Tutorial/TutorialRight.qml:55
614580msgid "Swipe from the right edge to view your open apps"
615−msgstr "Barríu dende'l berbesu drechu pa ver les apps abiertes"
581+msgstr "Esliza dende'l berbesu drechu pa ver les aplicaciones abiertes"
616582
617583#: qml/Tutorial/TutorialTop.qml:53
618584msgid "Swipe from the top edge to access notifications and quick settings"
619−msgstr ""
620−"Barríu dende'l berbesu superior pa tener accesu a los avisos y configuración "
621−"nel intre"
585+msgstr "Esliza dende'l berbesu cimeru p'acceder a los avisos y axustes rápidos"
622586
623−#: qml/Wizard/Page.qml:54
587+#: qml/Wizard/Page.qml:59
624588msgctxt "Button: Go back one page in the Wizard"
625589msgid "Back"
626−msgstr "Atrás"
590+msgstr "Atrás"
627591
628−#: qml/Wizard/Pages/10-welcome.qml:28
592+#: qml/Wizard/Pages/10-welcome.qml:29
629593msgid "Language"
630594msgstr "Llingua"
631595
632−#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
633−#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
634−#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
635−#: qml/Wizard/Pages/70-passwd-type.qml:145
636−#: qml/Wizard/Pages/75-report-check.qml:84
637−#: qml/Wizard/Pages/passcode-desktop.qml:142
638−#: qml/Wizard/Pages/password-set.qml:142
596+#: qml/Wizard/Pages/10-welcome.qml:176
597+#: qml/Wizard/Pages/10-welcome-update.qml:126
598+#: qml/Wizard/Pages/11-changelog.qml:74 qml/Wizard/Pages/20-keyboard.qml:152
599+#: qml/Wizard/Pages/30-wifi.qml:214 qml/Wizard/Pages/50-timezone.qml:272
600+#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/70-passwd-type.qml:146
601+#: qml/Wizard/Pages/passcode-desktop.qml:154
602+#: qml/Wizard/Pages/password-set.qml:153
639603msgid "Next"
640604msgstr "Siguiente"
641605
606+#: qml/Wizard/Pages/10-welcome-update.qml:91
607+msgid "Welcome to "
608+msgstr ""
609+
610+#: qml/Wizard/Pages/10-welcome-update.qml:106
611+msgid "We will make sure your device is ready to use "
612+msgstr "Vamos aseguranos de que'l preséu ta preparáu pa usase "
613+
614+#: qml/Wizard/Pages/11-changelog.qml:28
615+msgid "What's new"
616+msgstr "Qué hai nuevo"
617+
618+#: qml/Wizard/Pages/11-changelog.qml:74
619+msgid "Loading..."
620+msgstr "Cargando…"
621+
642622#: qml/Wizard/Pages/20-keyboard.qml:31
643623msgid "Select Keyboard"
644−msgstr "Escoyer tecláu"
624+msgstr ""
645625
646626#: qml/Wizard/Pages/20-keyboard.qml:71
647627msgid "Keyboard language"
@@ -651,279 +631,203 @@ msgstr "Llingua del tecláu"
651631msgid "Keyboard layout"
652632msgstr "Distribución del tecláu"
653633
654−#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
655−#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
634+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:214
635+#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/79-system-update.qml:144
656636#: qml/Wizard/Pages/sim.qml:101
657637msgid "Skip"
658638msgstr "Saltar"
659639
660640#: qml/Wizard/Pages/30-wifi.qml:31
661641msgid "Connect to Wi‑Fi"
662−msgstr "Coneutase al WiFi"
642+msgstr "Conexón a una Wi-Fi"
663643
664−#: qml/Wizard/Pages/30-wifi.qml:132
644+#: qml/Wizard/Pages/30-wifi.qml:139
665645msgid "Connected"
666−msgstr "Coneutáu"
646+msgstr "Coneutóse"
667647
668−#: qml/Wizard/Pages/30-wifi.qml:165
648+#: qml/Wizard/Pages/30-wifi.qml:172
669649msgid "Available Wi-Fi networks"
670650msgstr "Redes Wi-Fi disponibles"
671651
672−#: qml/Wizard/Pages/30-wifi.qml:166
652+#: qml/Wizard/Pages/30-wifi.qml:173
673653msgid "No available Wi-Fi networks"
674654msgstr "Nun hai redes Wi-Fi disponibles"
675655
676−#: qml/Wizard/Pages/40-location.qml:27
677−msgid "Location Services"
678−msgstr "Servicios d'allugamientu"
679−
680−#: qml/Wizard/Pages/40-location.qml:83
681−msgid ""
682−"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
683−"(recommended)"
684−msgstr ""
685−"Usar GPS, puntos Wi-Fi y redes móviles de mou anónimu pa detectar "
686−"l'allugamientu (recomendao)"
687−
688−#: qml/Wizard/Pages/40-location.qml:105
689−#, qt-format
690−msgid "By selecting this option you agree to the Nokia HERE %1."
691−msgstr "Seleicionando esta opción aceutes los %1 de Nokia HERE."
692−
693−#: qml/Wizard/Pages/40-location.qml:106
694−msgctxt "part of: Nokia HERE terms and conditions"
695−msgid "terms and conditions"
696−msgstr "términos y condiciones"
697−
698−#: qml/Wizard/Pages/40-location.qml:160
699−msgid "GPS only"
700−msgstr "Sólo GPS"
701−
702−#: qml/Wizard/Pages/40-location.qml:214
703−msgid "Don't use my location"
704−msgstr "Nun usar l'allugamientu"
705−
706−#: qml/Wizard/Pages/40-location.qml:260
707−msgid "You can change it later in System Settings."
708−msgstr "Pues camudalo sero na Configuración del Sistema."
709−
710656#: qml/Wizard/Pages/50-timezone.qml:30
711657msgid "Time Zone"
712−msgstr "Estaya horaria"
658+msgstr "Fusu horariu"
713659
714−#: qml/Wizard/Pages/50-timezone.qml:182
660+#: qml/Wizard/Pages/50-timezone.qml:183
715661msgid "Enter your city"
716−msgstr "Escribe la ciudá"
662+msgstr "Introduz la to ciudá"
717663
718664#: qml/Wizard/Pages/60-account.qml:24
719665msgid "Personalize Your Device"
720−msgstr "Personaliza'l preséu"
666+msgstr "Personalización del preséu"
721667
722−#: qml/Wizard/Pages/60-account.qml:48
668+#: qml/Wizard/Pages/60-account.qml:54
723669msgid "Preferred Name"
724670msgstr "Nome preferíu"
725671
726672#: qml/Wizard/Pages/70-passwd-type.qml:40
727673msgid "Lock Screen"
728−msgstr "Bloquiar pantalla"
674+msgstr "Pantalla de bloquéu"
729675
730−#: qml/Wizard/Pages/70-passwd-type.qml:102
676+#: qml/Wizard/Pages/70-passwd-type.qml:103
731677msgctxt "Label: Type of security method"
732678msgid "Create new password"
733−msgstr "Crear contraseña nueva"
679+msgstr "Crear una contraseña"
734680
735−#: qml/Wizard/Pages/70-passwd-type.qml:104
681+#: qml/Wizard/Pages/70-passwd-type.qml:105
736682msgctxt "Label: Type of security method"
737683msgid "Create passcode (numbers only)"
738−msgstr "Crear códigu d'accesu (sólo númberos)"
684+msgstr "Crear un códigu numbéricu"
739685
740−#: qml/Wizard/Pages/70-passwd-type.qml:106
686+#: qml/Wizard/Pages/70-passwd-type.qml:107
741687msgctxt "Label: Type of security method"
742688msgid "No lock code"
743−msgstr "Ensin códigu de bloquéu"
744−
745−#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
746−msgid "Privacy Policy"
747−msgstr "Política d'intimidá"
748−
749−#: qml/Wizard/Pages/75-report-check.qml:26
750−msgid "Help Us Improve"
751−msgstr "Ayúdanos a meyorar"
752−
753−#: qml/Wizard/Pages/75-report-check.qml:59
754−msgid "Improve system performance by sending us crashes and error reports."
755−msgstr ""
756−"Ameyora'l rindimientu del sistema unviándonos los informes d'errores y "
757−"cuelgues."
758−
759−#: qml/Wizard/Pages/75-report-check.qml:60
760−msgid "Privacy policy"
761−msgstr "Política d'intimidá"
689+msgstr "Nada"
762690
763−#: qml/Wizard/Pages/77-system-update.qml:28
691+#: qml/Wizard/Pages/79-system-update.qml:28
764692msgid "Update Device"
765−msgstr "Anovar preséu"
693+msgstr ""
766694
767−#: qml/Wizard/Pages/77-system-update.qml:55
695+#: qml/Wizard/Pages/79-system-update.qml:55
768696msgid ""
769697"There is a system update available and ready to install. Afterwards, the "
770698"device will automatically restart."
771699msgstr ""
772−"Hai un anovamientu del sistema disponible y preparáu pa instalar. Darréu, el "
773−"preséu reaniciará de mou automáticu."
700+"Hai un anovamientu del sistema disponible y preparáu pa instalase. Dempués, "
701+"el preséu va reaniciase automáticamente."
774702
775−#: qml/Wizard/Pages/77-system-update.qml:76
703+#: qml/Wizard/Pages/79-system-update.qml:76
704+#, fuzzy
705+#| msgctxt "string identifying name of the update"
706+#| msgid "Ubuntu system"
776707msgctxt "string identifying name of the update"
777−msgid "Ubuntu system"
708+msgid "Ubuntu Touch system"
778709msgstr "Sistema Ubuntu"
779710
780−#: qml/Wizard/Pages/77-system-update.qml:83
711+#: qml/Wizard/Pages/79-system-update.qml:83
781712#, qt-format
782713msgctxt "version of the system update"
783714msgid "Version %1"
784715msgstr "Versión %1"
785716
786−#: qml/Wizard/Pages/77-system-update.qml:102
717+#: qml/Wizard/Pages/79-system-update.qml:95
787718msgid "This could take a few minutes..."
788−msgstr "Esto podría tardar dellos minutos..."
719+msgstr "Esto podría tardar unos minutos…"
789720
790−#: qml/Wizard/Pages/77-system-update.qml:116
721+#: qml/Wizard/Pages/79-system-update.qml:109
791722msgid "Install and restart now"
792−msgstr "Instalar y reaniciar agora"
723+msgstr ""
793724
794−#: qml/Wizard/Pages/80-finished.qml:89
725+#: qml/Wizard/Pages/80-finished.qml:91
726+msgid "Welcome Back"
727+msgstr "Volvi afayate"
728+
729+#: qml/Wizard/Pages/80-finished.qml:91
795730msgid "Welcome to Ubuntu"
796−msgstr "Bienveníu/a a Ubuntu"
731+msgstr "Afáyate n'Ubuntu"
797732
798−#: qml/Wizard/Pages/80-finished.qml:104
733+#: qml/Wizard/Pages/80-finished.qml:106
799734msgid "You are ready to use your device now"
800−msgstr "Ya tas preparáu pa usar el preséu"
801−
802−#: qml/Wizard/Pages/80-finished.qml:124
803−msgid "Get Started"
804−msgstr "Primeros pasos"
805−
806−#: qml/Wizard/Pages/here-terms.qml:25
807−msgid "Terms & Conditions"
808−msgstr "Términos y condiciones"
809−
810−#: qml/Wizard/Pages/here-terms.qml:69
811−msgid "Your device uses positioning technologies provided by HERE."
812−msgstr "El preséu usa teunoloxíes de posición qu'ufre HERE."
813−
814−#: qml/Wizard/Pages/here-terms.qml:81
815−msgid ""
816−"To provide you with positioning services and to improve their quality, HERE "
817−"collects information about nearby cell towers and Wi-Fi hotspots around your "
818−"current location whenever your position is being found."
819−msgstr ""
820−"Pa ufrir los servicios de posición y ameyorar la so calidá, HERE collecha "
821−"información de les antenes celulares y puntos d'accesu Wi-Fi cercanos al to "
822−"allugamientu actual siempre que se conoza la to posición."
735+msgstr "Agora tas preparáu pa usar el preséu"
823736
824−#: qml/Wizard/Pages/here-terms.qml:93
825−msgid ""
826−"The information collected is used to analyze the service and to improve the "
827−"use of service, but not to identify you personally."
828−msgstr ""
829−"La información collechada úsase p'analizar el serviciu y ameyorar l'usu del "
830−"serviciu, non pa identificate personalmente."
831−
832−#: qml/Wizard/Pages/here-terms.qml:106
833−#, qt-format
834−msgid "By continuing, you agree to the HERE platform %1 and %2."
835−msgstr "Al siguir, aceutes %1 y %2 de la plataforma HERE."
737+#: qml/Wizard/Pages/80-finished.qml:126
738+msgid "Continue"
739+msgstr "Siguir"
836740
837−#: qml/Wizard/Pages/here-terms.qml:107
838−msgid "Service Terms"
839−msgstr "Términos del serviciu"
741+#: qml/Wizard/Pages/80-finished.qml:126
742+msgid "Get Started"
743+msgstr "Entamar"
840744
841745#: qml/Wizard/Pages/passcode-confirm.qml:43
842−#: qml/Wizard/Pages/passcode-desktop.qml:97
746+#: qml/Wizard/Pages/passcode-desktop.qml:104
843747msgid "Confirm passcode"
844−msgstr "Confirmar códigu de pasu"
748+msgstr "Confirmación"
845749
846750#: qml/Wizard/Pages/passcode-confirm.qml:45
847751msgid "Incorrect passcode."
848−msgstr "Códigu de pasu incorreutu."
752+msgstr "El códigu numbéricu ye incorreutu."
849753
850754#: qml/Wizard/Pages/passcode-confirm.qml:45
851755msgctxt "Enter the passcode again"
852756msgid "Please re-enter."
853−msgstr "Vuelve a escribilu."
757+msgstr "Volvi introducilu."
854758
855759#: qml/Wizard/Pages/passcode-desktop.qml:31
856760msgid "Lock Screen Passcode"
857−msgstr "Códigu de pasu de bloquéu de pantalla"
761+msgstr "Códigu numbéricu de la pantalla de bloquéu"
858762
859−#: qml/Wizard/Pages/passcode-desktop.qml:61
763+#: qml/Wizard/Pages/passcode-desktop.qml:68
860764msgid "Enter 4 numbers to setup your passcode"
861−msgstr "Escribi 4 númberos pa configurar el códigu de pasu"
765+msgstr "Introduz 4 númberos pa configurar el códigu numbéricu"
862766
863−#: qml/Wizard/Pages/passcode-desktop.qml:77
767+#: qml/Wizard/Pages/passcode-desktop.qml:84
864768#: qml/Wizard/Pages/passcode-set.qml:54
865769msgid "Choose passcode"
866−msgstr "Escueyi'l códigu de pasu"
770+msgstr "Códigu numbéricu"
867771
868−#: qml/Wizard/Pages/passcode-desktop.qml:127
772+#: qml/Wizard/Pages/passcode-desktop.qml:139
869773msgid "Passcode too short"
870−msgstr "Códigu de pasu curtiu enforma"
774+msgstr "El códigu numbéricu ye percurtiu"
871775
872−#: qml/Wizard/Pages/passcode-desktop.qml:129
776+#: qml/Wizard/Pages/passcode-desktop.qml:141
873777msgid "Passcodes match"
874−msgstr "Los códigos de pasu casen"
778+msgstr "Los códigos numbéricos concasen"
875779
876−#: qml/Wizard/Pages/passcode-desktop.qml:131
780+#: qml/Wizard/Pages/passcode-desktop.qml:143
877781msgid "Passcodes do not match"
878−msgstr "Los códigos de pasu nun casen"
782+msgstr "Los códigos numbéricos nun concasen"
879783
880784#: qml/Wizard/Pages/passcode-set.qml:62
881785msgid "Passcode must be 4 characters long"
882−msgstr "El códigu de pasu tien de tener 4 caráuteres de llargo"
786+msgstr "El códigu numbéricu a ser de 4 caráuteres"
883787
884788#: qml/Wizard/Pages/password-set.qml:31
885789msgid "Lock Screen Password"
886−msgstr "Contraseña del Bloquéu de pantalla"
790+msgstr "Contraseña de la pantalla de bloquéu"
887791
888−#: qml/Wizard/Pages/password-set.qml:62
792+#: qml/Wizard/Pages/password-set.qml:68
889793msgid "Enter at least 8 characters"
890−msgstr "Escribe polo menos 8 caráuteres"
794+msgstr "Introduz 8 caráuteres polo menos"
891795
892−#: qml/Wizard/Pages/password-set.qml:74
796+#: qml/Wizard/Pages/password-set.qml:80
893797msgid "Choose password"
894−msgstr "Escueye la contraseña"
798+msgstr "Contraseña"
895799
896−#: qml/Wizard/Pages/password-set.qml:104
800+#: qml/Wizard/Pages/password-set.qml:110
897801msgid "Confirm password"
898−msgstr "Confirmar contraseña"
802+msgstr "Confirmación"
899803
900804#: qml/Wizard/Pages/sim.qml:27
901805msgid "No SIM card installed"
902−msgstr "Nun ta instalada nenguna tarxeta SIM"
806+msgstr "Nun s'instaló denguna tarxeta SIM"
903807
904808#: qml/Wizard/Pages/sim.qml:54
905809msgid "SIM card added"
906−msgstr "Amestóse tarxeta SIM"
810+msgstr ""
907811
908812#: qml/Wizard/Pages/sim.qml:55
909813msgid "You must restart the device to access the mobile network."
910−msgstr "Tienes de reaniciar el preséu pa tener accesu a la rede móvil."
814+msgstr "Has reaniciar el preséu p'acceder a la rede móvil."
911815
912816#: qml/Wizard/Pages/sim.qml:59
913817msgid "Restart"
914−msgstr "Reaniciar"
818+msgstr ""
915819
916820#: qml/Wizard/Pages/sim.qml:78
917821msgid "You won’t be able to make calls or use text messaging without a SIM."
918−msgstr "Nun podrás facer llamaes nin usar mensaxería de testu sin una SIM."
822+msgstr "Nun vas ser a facer llamaes o unviar SMS ensin una SIM."
919823
920824#: qml/Wizard/Pages/sim.qml:90
921825msgid "To proceed with no SIM tap Skip."
922−msgstr "Pa siguir ensin SIM toca Saltar."
826+msgstr "Pa siguir ensin una tarxeta SIM toca Saltar."
923827
924828#: qml/Wizard/PasswordMeter.qml:87
925829msgid "Password too short"
926−msgstr "Contraseña curtia enforma"
830+msgstr "La contraseña ye percurtia"
927831
928832#: qml/Wizard/PasswordMeter.qml:89
929833msgid "Passwords match"
@@ -935,11 +839,11 @@ msgstr "Les contraseñes nun concasen"
935839
936840#: qml/Wizard/PasswordMeter.qml:95
937841msgid "Strong password"
938−msgstr "Contraseña fuerte"
842+msgstr "Contraseña perbona"
939843
940844#: qml/Wizard/PasswordMeter.qml:97
941845msgid "Fair password"
942−msgstr "Contraseña aceutable"
846+msgstr "Contraseña bona"
943847
944848#: qml/Wizard/PasswordMeter.qml:99
945849msgid "Weak password"
@@ -947,7 +851,185 @@ msgstr "Contraseña feble"
947851
948852#: qml/Wizard/PasswordMeter.qml:101
949853msgid "Very weak password"
950−msgstr "Contraseña feble enforma"
854+msgstr "Contraseña perfeble"
855+
856+#~ msgid "Unity 8"
857+#~ msgstr "Unity 8"
858+
859+#~ msgid "Scopes"
860+#~ msgstr "Ámbitos"
861+
862+#~ msgid "Super (Tap)"
863+#~ msgstr "Súper (Toque)"
864+
865+#~ msgid "Opens the Scopes home."
866+#~ msgstr "Abre l'aniciu d'Ámbitos."
867+
868+#~ msgctxt "Button: Open the Ubuntu Store"
869+#~ msgid "Store"
870+#~ msgstr "Tienda"
871+
872+#~ msgctxt "Button: Start a search in the current dash scope"
873+#~ msgid "Search"
874+#~ msgstr "Guetar"
875+
876+#~ msgctxt "Button: Show the current dash scope settings"
877+#~ msgid "Settings"
878+#~ msgstr "Axustes"
879+
880+#~ msgid "Show less"
881+#~ msgstr "Amosar menos"
882+
883+#~ msgid "Show all"
884+#~ msgstr "Amosar too"
885+
886+#~ msgid "Recent Searches"
887+#~ msgstr "Guetes d'apocayá"
888+
889+#~ msgid "Clear All"
890+#~ msgstr "Llimpiar too"
891+
892+#~ msgid "More..."
893+#~ msgstr "Más…"
894+
895+#~ msgid "Less..."
896+#~ msgstr "Menos…"
897+
898+#~ msgid "Manage"
899+#~ msgstr "Xestión"
900+
901+#~ msgid "Home"
902+#~ msgstr "Aniciu"
903+
904+#~ msgid "Also installed"
905+#~ msgstr "Tamién s'instaló"
906+
907+#~ msgid "Privacy Policy"
908+#~ msgstr "Política de privacidá"
909+
910+#~ msgid "Help Us Improve"
911+#~ msgstr "Ayúdanos a ameyorar"
912+
913+#~ msgid "Improve system performance by sending us crashes and error reports."
914+#~ msgstr ""
915+#~ "Ameyora'l rindimientu del sistema unviándonos informes de casques y "
916+#~ "fallos."
917+
918+#~ msgid "Privacy policy"
919+#~ msgstr "Política de privacidá"
920+
921+#~ msgid "This device is not connected to the internet."
922+#~ msgstr "El preséu nun ta coneutáu a internet."
923+
924+#~ msgid "Software is up to date"
925+#~ msgstr "El software ta anováu"
926+
927+#~ msgid "The update server is not responding."
928+#~ msgstr "El sirvidor d'anovamientos nun ta respondiendo."
929+
930+#~ msgid "Please wait..."
931+#~ msgstr "Espera…"
932+
933+#~ msgid "Installation failed"
934+#~ msgstr "Falló la instalación"
935+
936+#~ msgid "Checking for updates…"
937+#~ msgstr "Comprobando anovamientos…"
938+
939+#~ msgid "%1 update available"
940+#~ msgid_plural "%1 updates available"
941+#~ msgstr[0] "%1 anovamientu disponible"
942+#~ msgstr[1] "%1 anovamientos disponibles"
943+
944+#~ msgid "Update all…"
945+#~ msgstr "Anovar too…"
946+
947+#~ msgid "Update all"
948+#~ msgstr "Anovar too"
949+
950+#~ msgid "Resume"
951+#~ msgstr "Siguir"
952+
953+#~ msgid "Install…"
954+#~ msgstr "Instalar…"
955+
956+#~ msgid "Open"
957+#~ msgstr "Abrir"
958+
959+#~ msgid "Installing"
960+#~ msgstr "Instalando"
961+
962+#~ msgid "Paused"
963+#~ msgstr "Posóse"
964+
965+#~ msgid "Waiting to download"
966+#~ msgstr "Esperando pola descarga"
967+
968+#~ msgid "%1 of %2"
969+#~ msgstr "%1 de %2"
970+
971+#~ msgid "Downloaded"
972+#~ msgstr "Baxó"
973+
974+#~ msgid "Installed"
975+#~ msgstr "Instalóse"
976+
977+#~ msgid "Updated %1"
978+#~ msgstr "Anovóse %1"
979+
980+#~ msgid "Location Services"
981+#~ msgstr "Servicios d'allugamientu"
982+
983+#~ msgid ""
984+#~ "Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
985+#~ "(recommended)"
986+#~ msgstr ""
987+#~ "Usar GPS, puntos Wi-Fi y redes móviles de mou anónimu pa detectar "
988+#~ "l'allugamientu (recomendao)"
989+
990+#~ msgid "By selecting this option you agree to the Nokia HERE %1."
991+#~ msgstr "Seleicionando esta opción aceutes los %1 de Nokia HERE."
992+
993+#~ msgctxt "part of: Nokia HERE terms and conditions"
994+#~ msgid "terms and conditions"
995+#~ msgstr "términos y condiciones"
996+
997+#~ msgid "GPS only"
998+#~ msgstr "Sólo GPS"
999+
1000+#~ msgid "Don't use my location"
1001+#~ msgstr "Nun usar l'allugamientu"
1002+
1003+#~ msgid "You can change it later in System Settings."
1004+#~ msgstr "Pues camudalo sero na Configuración del Sistema."
1005+
1006+#~ msgid "Terms & Conditions"
1007+#~ msgstr "Términos y condiciones"
1008+
1009+#~ msgid "Your device uses positioning technologies provided by HERE."
1010+#~ msgstr "El preséu usa teunoloxíes de posición qu'ufre HERE."
1011+
1012+#~ msgid ""
1013+#~ "To provide you with positioning services and to improve their quality, "
1014+#~ "HERE collects information about nearby cell towers and Wi-Fi hotspots "
1015+#~ "around your current location whenever your position is being found."
1016+#~ msgstr ""
1017+#~ "Pa ufrir los servicios de posición y ameyorar la so calidá, HERE collecha "
1018+#~ "información de les antenes celulares y puntos d'accesu Wi-Fi cercanos al "
1019+#~ "to allugamientu actual siempre que se conoza la to posición."
1020+
1021+#~ msgid ""
1022+#~ "The information collected is used to analyze the service and to improve "
1023+#~ "the use of service, but not to identify you personally."
1024+#~ msgstr ""
1025+#~ "La información collechada úsase p'analizar el serviciu y ameyorar l'usu "
1026+#~ "del serviciu, non pa identificate personalmente."
1027+
1028+#~ msgid "By continuing, you agree to the HERE platform %1 and %2."
1029+#~ msgstr "Al siguir, aceutes %1 y %2 de la plataforma HERE."
1030+
1031+#~ msgid "Service Terms"
1032+#~ msgstr "Términos del serviciu"
9511033
9521034#~ msgid "Skip intro"
9531035#~ msgstr "Omitir la intro"
@@ -975,8 +1057,8 @@ msgstr "Contraseña feble enforma"
9751057
9761058#~ msgid "Swipe from the left to reveal the launcher for quick access to apps"
9771059#~ msgstr ""
978−#~ "Esliza'l deu dende la esquierda p'amosar el llanzador y acceder rápidamente "
979−#~ "a les aplicaciones"
1060+#~ "Esliza'l deu dende la esquierda p'amosar el llanzador y acceder "
1061+#~ "rápidamente a les aplicaciones"
9801062
9811063#~ msgid "Well done"
9821064#~ msgstr "Bien fecho"
@@ -984,21 +1066,12 @@ msgstr "Contraseña feble enforma"
9841066#~ msgid "Confirm"
9851067#~ msgstr "Confirmar"
9861068
987−#~ msgid "Speaking..."
988−#~ msgstr "Falando…"
989−
990−#~ msgid "Loading. Please Wait..."
991−#~ msgstr "Cargando, espera…"
992−
9931069#~ msgid "Type or say a command"
9941070#~ msgstr "Escribi o di una orde"
9951071
9961072#~ msgid "Speak Now..."
9971073#~ msgstr "Fala agora…"
9981074
999−#~ msgid "Search"
1000−#~ msgstr "Guetar"
1001−
10021075#~ msgid "See less"
10031076#~ msgstr "Ver menos"
10041077
@@ -1045,7 +1118,6 @@ msgstr "Contraseña feble enforma"
10451118#~ msgid "Store"
10461119#~ msgstr "Tienda"
10471120
1048−#, qt-format
10491121#~ msgid "Sorry, incorrect %1"
10501122#~ msgstr "Sentímoslo, %1 incorreutu"
10511123
@@ -1061,9 +1133,6 @@ msgstr "Contraseña feble enforma"
10611133#~ msgid "Manage Scopes"
10621134#~ msgstr "Xestionar ámbitos"
10631135
1064−#~ msgid "Continue"
1065−#~ msgstr "Siguir"
1066−
10671136#~ msgid "Without it, you won’t be able to make calls or use text messaging."
10681137#~ msgstr "Ensin ella, nun vas poder facer llamaes nin unviar mensaxes."
10691138
@@ -1095,17 +1164,12 @@ msgstr "Contraseña feble enforma"
10951164#~ msgid "Not at all"
10961165#~ msgstr "De nengún mou"
10971166
1098−#, qt-format
10991167#~ msgid "〈 %1"
11001168#~ msgstr "〈 %1"
11011169
1102−#, qt-format
11031170#~ msgid "%1 〉"
11041171#~ msgstr "%1 〉"
11051172
1106−#~ msgid "Open the launcher"
1107−#~ msgstr "Abrir el llanzador"
1108−
11091173#~ msgid "Tap here to continue."
11101174#~ msgstr "Toca equí pa siguir."
11111175
@@ -1146,35 +1210,28 @@ msgstr "Contraseña feble enforma"
11461210#~ msgid "Sorry, incorrect passphrase."
11471211#~ msgstr "Perdón, fras de pasu incorreuta"
11481212
1149−#, qt-format
11501213#~ msgid "Enter %1"
11511214#~ msgstr "Introduz %1"
11521215
11531216#~ msgid "Sorry, incorrect passcode."
11541217#~ msgstr "Perdón, códigu de pasu incorreutu."
11551218
1156−#~ msgid "Enter passcode"
1157−#~ msgstr "Introduz el códigu de pasu"
1158−
1159−#~ msgid "Enter passphrase"
1160−#~ msgstr "Introduz la fras de pasu"
1161−
11621219#~ msgid "Please re-enter"
11631220#~ msgstr "Por favor, reintroduzla"
11641221
11651222#~ msgid ""
1166−#~ "If passcode is entered incorrectly, your phone will conduct a factory reset "
1167−#~ "and all personal data will be deleted."
1223+#~ "If passcode is entered incorrectly, your phone will conduct a factory "
1224+#~ "reset and all personal data will be deleted."
11681225#~ msgstr ""
1169−#~ "Si s'inxerta'l códigu de pasu incorreutamente, el to teléfonu va reafitase y "
1170−#~ "van desaniciase tolos datos personales."
1226+#~ "Si s'inxerta'l códigu de pasu incorreutamente, el to teléfonu va "
1227+#~ "reafitase y van desaniciase tolos datos personales."
11711228
11721229#~ msgid ""
11731230#~ "If passphrase is entered incorrectly, your phone will conduct a factory "
11741231#~ "reset and all personal data will be deleted."
11751232#~ msgstr ""
1176−#~ "Si s'inxerta la fras de pasu incorreutamente, el to teléfonu va reafitase y "
1177−#~ "van desaniciase tolos datos personales."
1233+#~ "Si s'inxerta la fras de pasu incorreutamente, el to teléfonu va reafitase "
1234+#~ "y van desaniciase tolos datos personales."
11781235
11791236#~ msgid "This will be your last attempt."
11801237#~ msgstr "Esti sedra'l to caberu intentu"
@@ -1258,11 +1315,11 @@ msgstr "Contraseña feble enforma"
12581315#~ msgstr "¡Bon trabayu!"
12591316
12601317#~ msgid ""
1261−#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
1262−#~ "conditions</a>."
1318+#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms "
1319+#~ "and conditions</a>."
12631320#~ msgstr ""
1264−#~ "Esbillando esta opción aceutes los <a href='#'>términos y condiciones</a> de "
1265−#~ "Nokia HERE."
1321+#~ "Esbillando esta opción aceutes los <a href='#'>términos y condiciones</a> "
1322+#~ "de Nokia HERE."
12661323
12671324#~ msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
12681325#~ msgstr ""
@@ -1341,7 +1398,8 @@ msgstr "Contraseña feble enforma"
13411398
13421399#~ msgid "Short or long swipe from the right edge to view your open apps"
13431400#~ msgstr ""
1344−#~ "Eslizamientu curtiu o llargu dende'l berbesu drechu pa ver les apps abiertes"
1401+#~ "Eslizamientu curtiu o llargu dende'l berbesu drechu pa ver les apps "
1402+#~ "abiertes"
13451403
13461404#~ msgid "Swipe up to manage the app"
13471405#~ msgstr "Eslizar p'alministrar la app"
po/az.po+238−327
@@ -6,28 +6,57 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
9−"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2017-01-10 14:48+0000\n"
9+"Report-Msgid-Bugs-To: \n"
10+"POT-Creation-Date: 2021-01-29 11:42-0600\n"
1111"PO-Revision-Date: 2014-09-03 16:39+0000\n"
1212"Last-Translator: Nicat Məmmədov <n1c4t97@gmail.com>\n"
1313"Language-Team: Azerbaijani <az@li.org>\n"
14+"Language: az\n"
1415"MIME-Version: 1.0\n"
1516"Content-Type: text/plain; charset=UTF-8\n"
1617"Content-Transfer-Encoding: 8bit\n"
1718"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2017-01-16 05:47+0000\n"
19−"X-Generator: Launchpad (build 18302)\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
20+"X-Generator: Launchpad (build 18269)\n"
2021
21−#: plugins/LightDM/Greeter.cpp:123
22+#: plugins/LightDM/Greeter.cpp:199
2223msgid "Password: "
2324msgstr "Şifrә: "
2425
25−#: plugins/Unity/Launcher/launcheritem.cpp:50
26+#: plugins/LightDM/Greeter.cpp:214
27+msgid "Username"
28+msgstr ""
29+
30+#: plugins/LightDM/Greeter.cpp:258
31+msgid "Failed to authenticate"
32+msgstr ""
33+
34+#: plugins/LightDM/Greeter.cpp:260
35+msgid "Invalid password, please try again"
36+msgstr ""
37+
38+#: plugins/LightDM/Greeter.cpp:270
39+msgid "Log In"
40+msgstr ""
41+
42+#: plugins/LightDM/Greeter.cpp:270
43+msgid "Retry"
44+msgstr ""
45+
46+#: plugins/LightDM/UsersModel.cpp:157
47+msgid "Login"
48+msgstr ""
49+
50+#: plugins/LightDM/UsersModel.cpp:165
51+msgid "Guest Session"
52+msgstr ""
53+
54+#: plugins/Unity/Launcher/launcheritem.cpp:48
2655#: plugins/Unity/Launcher/launcheritem.cpp:122
2756msgid "Pin shortcut"
2857msgstr "Pin qısayolu"
2958
30−#: plugins/Unity/Launcher/launcheritem.cpp:55
59+#: plugins/Unity/Launcher/launcheritem.cpp:54
3160msgid "Quit"
3261msgstr ""
3362
@@ -35,76 +64,79 @@ msgstr ""
3564msgid "Unpin shortcut"
3665msgstr "Açma qısayolu"
3766
38−#: qml/Components/Dialogs.qml:149
67+#: qml/Components/Dialogs.qml:176
3968msgctxt "Title: Lock/Log out dialog"
4069msgid "Log out"
4170msgstr ""
4271
43−#: qml/Components/Dialogs.qml:150
72+#: qml/Components/Dialogs.qml:177
4473msgid "Are you sure you want to log out?"
4574msgstr "Çıxmaq istәdiyinizdәn әminsiniz?"
4675
47−#: qml/Components/Dialogs.qml:152
76+#: qml/Components/Dialogs.qml:180
4877msgctxt "Button: Lock the system"
4978msgid "Lock"
5079msgstr ""
5180
52−#: qml/Components/Dialogs.qml:160
81+#: qml/Components/Dialogs.qml:191
5382msgctxt "Button: Log out from the system"
5483msgid "Log Out"
5584msgstr ""
5685
57−#: qml/Components/Dialogs.qml:167 qml/Components/Dialogs.qml:225
58−#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:232
59−#: qml/Wizard/Pages/passcode-confirm.qml:32
86+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
87+#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
6088#: qml/Wizard/Pages/passcode-set.qml:32
6189msgid "Cancel"
6290msgstr "İmtina"
6391
64−#: qml/Components/Dialogs.qml:179
92+#: qml/Components/Dialogs.qml:211
6593msgctxt "Title: Reboot dialog"
6694msgid "Reboot"
6795msgstr ""
6896
69−#: qml/Components/Dialogs.qml:180
97+#: qml/Components/Dialogs.qml:212
7098msgid "Are you sure you want to reboot?"
7199msgstr "Yenidәn başlatmaq istәdiyinizә әminsiniz?"
72100
73−#: qml/Components/Dialogs.qml:182
101+#: qml/Components/Dialogs.qml:215
74102msgid "No"
75103msgstr "Yox"
76104
77−#: qml/Components/Dialogs.qml:189
105+#: qml/Components/Dialogs.qml:223
78106msgid "Yes"
79107msgstr "Hə"
80108
81−#: qml/Components/Dialogs.qml:204
109+#: qml/Components/Dialogs.qml:243
82110msgctxt "Title: Power off/Restart dialog"
83111msgid "Power"
84112msgstr ""
85113
86−#: qml/Components/Dialogs.qml:205
114+#: qml/Components/Dialogs.qml:244
87115msgid ""
88116"Are you sure you would like\n"
89117"to power off?"
90118msgstr ""
91119
92−#: qml/Components/Dialogs.qml:208
120+#: qml/Components/Dialogs.qml:248
93121msgctxt "Button: Power off the system"
94122msgid "Power off"
95123msgstr ""
96124
97−#: qml/Components/Dialogs.qml:217
125+#: qml/Components/Dialogs.qml:263
98126msgctxt "Button: Restart the system"
99127msgid "Restart"
100128msgstr ""
101129
130+#: qml/Components/Dialogs.qml:276
131+msgid "Screenshot"
132+msgstr ""
133+
102134#: qml/Components/KeyboardShortcutsOverlay.qml:41
103135msgid "Keyboard Shortcuts"
104136msgstr ""
105137
106138#: qml/Components/KeyboardShortcutsOverlay.qml:55
107−msgid "Unity 8"
139+msgid "Lomiri"
108140msgstr ""
109141
110142#: qml/Components/KeyboardShortcutsOverlay.qml:62
@@ -120,7 +152,7 @@ msgid "Alt + PrtScr"
120152msgstr ""
121153
122154#: qml/Components/KeyboardShortcutsOverlay.qml:80
123−msgid "Takes a screenshot of a window."
155+msgid "Takes a screenshot of the current window."
124156msgstr ""
125157
126158#: qml/Components/KeyboardShortcutsOverlay.qml:88
@@ -139,135 +171,131 @@ msgstr ""
139171msgid "Switches to previous keyboard layout."
140172msgstr ""
141173
142−#: qml/Components/KeyboardShortcutsOverlay.qml:118
143−msgid "Launcher"
174+#: qml/Components/KeyboardShortcutsOverlay.qml:114
175+msgid "Ctrl + Alt + T"
144176msgstr ""
145177
146−#: qml/Components/KeyboardShortcutsOverlay.qml:125
147−msgid "Super (Hold)"
178+#: qml/Components/KeyboardShortcutsOverlay.qml:119
179+msgid "Starts the Terminal application."
148180msgstr ""
149181
150−#: qml/Components/KeyboardShortcutsOverlay.qml:130
151−msgid "Opens the launcher, displays shortcuts."
182+#: qml/Components/KeyboardShortcutsOverlay.qml:131
183+msgid "Launcher"
152184msgstr ""
153185
154186#: qml/Components/KeyboardShortcutsOverlay.qml:138
155−msgid "Alt + F1"
187+msgid "Super (Hold)"
156188msgstr ""
157189
158190#: qml/Components/KeyboardShortcutsOverlay.qml:143
159−msgid "Opens launcher keyboard navigation mode."
191+msgid "Opens the launcher, displays shortcuts."
160192msgstr ""
161193
162194#: qml/Components/KeyboardShortcutsOverlay.qml:151
163−msgid "Super + Tab"
195+msgid "Alt + F1"
164196msgstr ""
165197
166198#: qml/Components/KeyboardShortcutsOverlay.qml:156
167−msgid "Switches applications via the launcher."
199+msgid "Opens launcher keyboard navigation mode."
168200msgstr ""
169201
170202#: qml/Components/KeyboardShortcutsOverlay.qml:164
171−msgid "Super + 0 to 9"
203+msgid "Super + Tab"
172204msgstr ""
173205
174206#: qml/Components/KeyboardShortcutsOverlay.qml:169
175−msgid "Same as clicking on a launcher icon."
207+msgid "Switches applications via the launcher."
176208msgstr ""
177209
178210#: qml/Components/KeyboardShortcutsOverlay.qml:177
179−msgid "Super + A"
211+msgid "Super + 1 to 0"
180212msgstr ""
181213
182214#: qml/Components/KeyboardShortcutsOverlay.qml:182
183−msgid "Opens the Application Drawer."
184−msgstr ""
185−
186−#: qml/Components/KeyboardShortcutsOverlay.qml:194
187−msgid "Scopes"
215+msgid "Same as clicking on a launcher icon."
188216msgstr ""
189217
190−#: qml/Components/KeyboardShortcutsOverlay.qml:201
191−msgid "Super (Tap)"
218+#: qml/Components/KeyboardShortcutsOverlay.qml:190
219+msgid "Super + A"
192220msgstr ""
193221
194−#: qml/Components/KeyboardShortcutsOverlay.qml:206
195−msgid "Opens the Scopes home."
222+#: qml/Components/KeyboardShortcutsOverlay.qml:195
223+msgid "Opens the Application Drawer."
196224msgstr ""
197225
198−#: qml/Components/KeyboardShortcutsOverlay.qml:222
226+#: qml/Components/KeyboardShortcutsOverlay.qml:235
199227msgid "Switching"
200228msgstr ""
201229
202−#: qml/Components/KeyboardShortcutsOverlay.qml:229
230+#: qml/Components/KeyboardShortcutsOverlay.qml:242
203231msgid "Alt + Tab"
204232msgstr ""
205233
206−#: qml/Components/KeyboardShortcutsOverlay.qml:234
234+#: qml/Components/KeyboardShortcutsOverlay.qml:247
207235msgid "Switches between applications."
208236msgstr ""
209237
210−#: qml/Components/KeyboardShortcutsOverlay.qml:242
238+#: qml/Components/KeyboardShortcutsOverlay.qml:255
211239msgid "Super + W"
212240msgstr ""
213241
214−#: qml/Components/KeyboardShortcutsOverlay.qml:247
242+#: qml/Components/KeyboardShortcutsOverlay.qml:260
215243msgid "Opens the desktop spread."
216244msgstr ""
217245
218−#: qml/Components/KeyboardShortcutsOverlay.qml:255
246+#: qml/Components/KeyboardShortcutsOverlay.qml:268
219247msgid "Cursor Left or Right"
220248msgstr ""
221249
222−#: qml/Components/KeyboardShortcutsOverlay.qml:260
250+#: qml/Components/KeyboardShortcutsOverlay.qml:273
223251msgid "Moves the focus."
224252msgstr ""
225253
226−#: qml/Components/KeyboardShortcutsOverlay.qml:272
254+#: qml/Components/KeyboardShortcutsOverlay.qml:285
227255msgid "Windows"
228256msgstr ""
229257
230−#: qml/Components/KeyboardShortcutsOverlay.qml:279
258+#: qml/Components/KeyboardShortcutsOverlay.qml:292
231259msgid "Ctrl + Super + D"
232260msgstr ""
233261
234−#: qml/Components/KeyboardShortcutsOverlay.qml:284
262+#: qml/Components/KeyboardShortcutsOverlay.qml:297
235263msgid "Minimizes all windows."
236264msgstr ""
237265
238−#: qml/Components/KeyboardShortcutsOverlay.qml:292
266+#: qml/Components/KeyboardShortcutsOverlay.qml:305
239267msgid "Ctrl + Super + Up"
240268msgstr ""
241269
242−#: qml/Components/KeyboardShortcutsOverlay.qml:297
270+#: qml/Components/KeyboardShortcutsOverlay.qml:310
243271msgid "Maximizes the current window."
244272msgstr ""
245273
246−#: qml/Components/KeyboardShortcutsOverlay.qml:305
274+#: qml/Components/KeyboardShortcutsOverlay.qml:318
247275msgid "Ctrl + Super + Down"
248276msgstr ""
249277
250−#: qml/Components/KeyboardShortcutsOverlay.qml:310
278+#: qml/Components/KeyboardShortcutsOverlay.qml:323
251279msgid "Minimizes or restores the current window."
252280msgstr ""
253281
254−#: qml/Components/KeyboardShortcutsOverlay.qml:318
282+#: qml/Components/KeyboardShortcutsOverlay.qml:331
255283msgid "Ctrl + Super + Left or Right"
256284msgstr ""
257285
258−#: qml/Components/KeyboardShortcutsOverlay.qml:323
286+#: qml/Components/KeyboardShortcutsOverlay.qml:336
259287msgid "Semi-maximizes the current window."
260288msgstr ""
261289
262−#: qml/Components/KeyboardShortcutsOverlay.qml:331
290+#: qml/Components/KeyboardShortcutsOverlay.qml:344
263291msgid "Alt + F4"
264292msgstr ""
265293
266−#: qml/Components/KeyboardShortcutsOverlay.qml:336
294+#: qml/Components/KeyboardShortcutsOverlay.qml:349
267295msgid "Closes the current window."
268296msgstr ""
269297
270−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:252
298+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
271299msgid "Return to Call"
272300msgstr ""
273301
@@ -275,7 +303,7 @@ msgstr ""
275303msgid "Emergency Call"
276304msgstr "Zərurət zəngi"
277305
278−#: qml/Components/Lockscreen.qml:244
306+#: qml/Components/Lockscreen.qml:245
279307msgid "OK"
280308msgstr "Oldu"
281309
@@ -289,29 +317,29 @@ msgstr ""
289317msgid "%1:%2"
290318msgstr ""
291319
292−#: qml/Components/ModeSwitchWarningDialog.qml:32
320+#: qml/Components/ModeSwitchWarningDialog.qml:33
293321msgid "Apps may have unsaved data:"
294322msgstr ""
295323
296−#: qml/Components/ModeSwitchWarningDialog.qml:57
324+#: qml/Components/ModeSwitchWarningDialog.qml:60
297325msgctxt ""
298326"Re-dock means connect the device again to an external screen/mouse/keyboard"
299327msgid "Re-dock, save your work and close these apps to continue."
300328msgstr ""
301329
302−#: qml/Components/ModeSwitchWarningDialog.qml:63
330+#: qml/Components/ModeSwitchWarningDialog.qml:67
303331msgid "Or force close now (unsaved data will be lost)."
304332msgstr ""
305333
306−#: qml/Components/ModeSwitchWarningDialog.qml:75
334+#: qml/Components/ModeSwitchWarningDialog.qml:80
307335msgid "OK, I will reconnect"
308336msgstr ""
309337
310−#: qml/Components/ModeSwitchWarningDialog.qml:76
338+#: qml/Components/ModeSwitchWarningDialog.qml:81
311339msgid "Reconnect now!"
312340msgstr ""
313341
314−#: qml/Components/ModeSwitchWarningDialog.qml:88
342+#: qml/Components/ModeSwitchWarningDialog.qml:94
315343msgid "Close all"
316344msgstr ""
317345
@@ -326,8 +354,10 @@ msgid ""
326354msgstr ""
327355
328356#: qml/Components/VirtualTouchPad.qml:327
357+#, fuzzy
358+#| msgid "Tap to return to call..."
329359msgid "Tap left button to click."
330−msgstr ""
360+msgstr "Zəngə qayıtmaq üçün toxunun..."
331361
332362#: qml/Components/VirtualTouchPad.qml:339
333363msgid "Tap right button to right click."
@@ -341,103 +371,6 @@ msgstr ""
341371msgid "Find more settings in the system settings."
342372msgstr ""
343373
344−#: qml/Dash/DashPageHeader.qml:361
345−msgctxt "Button: Open the Ubuntu Store"
346−msgid "Store"
347−msgstr ""
348−
349−#: qml/Dash/DashPageHeader.qml:368
350−msgctxt "Button: Start a search in the current dash scope"
351−msgid "Search"
352−msgstr ""
353−
354−#: qml/Dash/DashPageHeader.qml:378
355−msgctxt "Button: Show the current dash scope settings"
356−msgid "Settings"
357−msgstr ""
358−
359−#: qml/Dash/DashPageHeader.qml:385
360−msgid "Remove from Favorites"
361−msgstr "Seçilmişlәrdәn çıxart"
362−
363−#: qml/Dash/DashPageHeader.qml:385
364−msgid "Add to Favorites"
365−msgstr "Seçilmişlәrә әlavә et"
366−
367−#: qml/Dash/FiltersPopover.qml:61
368−msgid "Refine your results"
369−msgstr ""
370−
371−#: qml/Dash/FiltersPopover.qml:70
372−msgid "Reset"
373−msgstr ""
374−
375−#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
376−msgid "Show less"
377−msgstr ""
378−
379−#: qml/Dash/GenericScopeView.qml:547
380−msgid "Show all"
381−msgstr ""
382−
383−#: qml/Dash/GenericScopeView.qml:578
384−msgctxt "Label: Hint for dash search line edit"
385−msgid "Search"
386−msgstr ""
387−
388−#: qml/Dash/PageHeaderExtraPanel.qml:67
389−msgid "Recent Searches"
390−msgstr ""
391−
392−#: qml/Dash/PageHeaderExtraPanel.qml:78
393−msgid "Clear All"
394−msgstr ""
395−
396−#: qml/Dash/Previews/PreviewActionCombo.qml:36
397−msgid "More..."
398−msgstr "Daha çox..."
399−
400−#: qml/Dash/Previews/PreviewActionCombo.qml:36
401−msgid "Less..."
402−msgstr "Az..."
403−
404−#: qml/Dash/Previews/PreviewCommentInput.qml:83
405−#: qml/Dash/Previews/PreviewRatingInput.qml:202
406−msgid "Send"
407−msgstr "Göndər"
408−
409−#: qml/Dash/Previews/PreviewRatingInput.qml:109
410−msgid "Rate this"
411−msgstr "Qiymәtlәndir"
412−
413−#: qml/Dash/Previews/PreviewRatingInput.qml:184
414−msgid "Add a review"
415−msgstr "Rəy yaz"
416−
417−#: qml/Dash/PullToRefreshScopeStyle.qml:56
418−msgid "Pull to refresh…"
419−msgstr ""
420−
421−#: qml/Dash/PullToRefreshScopeStyle.qml:61
422−msgid "Release to refresh…"
423−msgstr ""
424−
425−#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
426−msgid "Enable location data"
427−msgstr ""
428−
429−#: qml/Dash/ScopesList.qml:146
430−msgid "Manage"
431−msgstr ""
432−
433−#: qml/Dash/ScopesList.qml:187
434−msgid "Home"
435−msgstr ""
436−
437−#: qml/Dash/ScopesList.qml:188
438−msgid "Also installed"
439−msgstr ""
440−
441374#: qml/Greeter/CoverPage.qml:127
442375msgid "Unlock"
443376msgstr ""
@@ -461,45 +394,46 @@ msgid_plural "Please wait %1 minutes and then try again…"
461394msgstr[0] ""
462395msgstr[1] ""
463396
464−#: qml/Greeter/Greeter.qml:592
397+#: qml/Greeter/Greeter.qml:550
465398msgid "Try again"
466399msgstr ""
467400
468−#: qml/Greeter/LoginList.qml:70
469−msgid "Passphrase"
401+#: qml/Greeter/Greeter.qml:551
402+msgid "Enter passphrase to unlock"
470403msgstr ""
471404
472−#: qml/Greeter/LoginList.qml:71
473−msgid "Passcode"
405+#: qml/Greeter/Greeter.qml:552
406+msgid "Enter passcode to unlock"
474407msgstr ""
475408
476−#: qml/Greeter/LoginList.qml:98
477−msgid "Retry"
409+#: qml/Greeter/NarrowView.qml:235
410+msgid "Emergency"
478411msgstr ""
479412
480−#: qml/Greeter/LoginList.qml:99
481−msgid "Log In"
413+#: qml/Greeter/PromptList.qml:126
414+msgid "Passphrase"
482415msgstr ""
483416
484−#: qml/Greeter/NarrowView.qml:252
485−msgid "Emergency"
417+#: qml/Greeter/PromptList.qml:126
418+msgid "Passcode"
486419msgstr ""
487420
488−#: qml/Greeter/SessionsList.qml:122
421+#: qml/Greeter/SessionsList.qml:124
489422msgid "Select desktop environment"
490423msgstr ""
491424
492−#: qml/Launcher/Drawer.qml:80
425+#: qml/Launcher/Drawer.qml:250
426+#, fuzzy
427+#| msgid "Search"
493428msgid "Search…"
494−msgstr ""
429+msgstr "Axtar"
495430
496−#: qml/Launcher/Drawer.qml:101
497−msgctxt "Apps sorted alphabetically"
498−msgid "A-Z"
431+#: qml/Launcher/PullToRefreshScopeStyle.qml:56
432+msgid "Pull to refresh…"
499433msgstr ""
500434
501−#: qml/Launcher/MoreAppsHeader.qml:32
502−msgid "More apps in the store"
435+#: qml/Launcher/PullToRefreshScopeStyle.qml:61
436+msgid "Release to refresh…"
503437msgstr ""
504438
505439#: qml/Notifications/NotificationMenuItemFactory.qml:124
@@ -589,23 +523,33 @@ msgctxt "Button: Call back on phone"
589523msgid "Call back"
590524msgstr ""
591525
526+#: qml/Panel/PanelMenuPage.qml:92
527+msgid "Back"
528+msgstr ""
529+
592530#: qml/Stage/SideStage.qml:76
593531msgid "Drag using 3 fingers any application from one window to the other"
594532msgstr ""
595533
596−#: qml/Tutorial/TutorialLeftLong.qml:49
597−msgid "Long swipe from the left edge to open the Today scope"
534+#: qml/Stage/Stage.qml:671
535+msgid "No running apps"
598536msgstr ""
599537
538+#: qml/Tutorial/TutorialLeftLong.qml:49
539+#, fuzzy
540+#| msgid "Try swiping from the top edge to access the indicators"
541+msgid "Long swipe from the left edge to open the Application Drawer"
542+msgstr "Göstəriciləri görmәk üçün yuxarı küncdən sürüşdürün"
543+
600544#: qml/Tutorial/TutorialLeft.qml:47
601545msgid "Short swipe from the left edge to open the launcher"
602546msgstr ""
603547
604−#: qml/Tutorial/TutorialRight.qml:55
548+#: qml/Tutorial/TutorialRight.qml:54
605549msgid "Push your mouse against the right edge to view your open apps"
606550msgstr ""
607551
608−#: qml/Tutorial/TutorialRight.qml:56
552+#: qml/Tutorial/TutorialRight.qml:55
609553msgid "Swipe from the right edge to view your open apps"
610554msgstr ""
611555
@@ -613,25 +557,42 @@ msgstr ""
613557msgid "Swipe from the top edge to access notifications and quick settings"
614558msgstr ""
615559
616−#: qml/Wizard/Page.qml:54
560+#: qml/Wizard/Page.qml:59
617561msgctxt "Button: Go back one page in the Wizard"
618562msgid "Back"
619563msgstr ""
620564
621−#: qml/Wizard/Pages/10-welcome.qml:28
565+#: qml/Wizard/Pages/10-welcome.qml:29
622566msgid "Language"
623567msgstr ""
624568
625−#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
626−#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
627−#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
628−#: qml/Wizard/Pages/70-passwd-type.qml:145
629−#: qml/Wizard/Pages/75-report-check.qml:84
630−#: qml/Wizard/Pages/passcode-desktop.qml:142
631−#: qml/Wizard/Pages/password-set.qml:142
569+#: qml/Wizard/Pages/10-welcome.qml:176
570+#: qml/Wizard/Pages/10-welcome-update.qml:126
571+#: qml/Wizard/Pages/11-changelog.qml:74 qml/Wizard/Pages/20-keyboard.qml:152
572+#: qml/Wizard/Pages/30-wifi.qml:214 qml/Wizard/Pages/50-timezone.qml:272
573+#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/70-passwd-type.qml:146
574+#: qml/Wizard/Pages/passcode-desktop.qml:154
575+#: qml/Wizard/Pages/password-set.qml:153
632576msgid "Next"
633577msgstr ""
634578
579+#: qml/Wizard/Pages/10-welcome-update.qml:91
580+msgid "Welcome to "
581+msgstr ""
582+
583+#: qml/Wizard/Pages/10-welcome-update.qml:106
584+msgid "We will make sure your device is ready to use "
585+msgstr ""
586+
587+#: qml/Wizard/Pages/11-changelog.qml:28
588+msgid "What's new"
589+msgstr ""
590+
591+#: qml/Wizard/Pages/11-changelog.qml:74
592+#, fuzzy
593+msgid "Loading..."
594+msgstr "Danışır..."
595+
635596#: qml/Wizard/Pages/20-keyboard.qml:31
636597msgid "Select Keyboard"
637598msgstr ""
@@ -644,8 +605,8 @@ msgstr ""
644605msgid "Keyboard layout"
645606msgstr ""
646607
647−#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
648−#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
608+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:214
609+#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/79-system-update.qml:144
649610#: qml/Wizard/Pages/sim.qml:101
650611msgid "Skip"
651612msgstr ""
@@ -654,55 +615,23 @@ msgstr ""
654615msgid "Connect to Wi‑Fi"
655616msgstr ""
656617
657−#: qml/Wizard/Pages/30-wifi.qml:132
618+#: qml/Wizard/Pages/30-wifi.qml:139
658619msgid "Connected"
659620msgstr ""
660621
661−#: qml/Wizard/Pages/30-wifi.qml:165
622+#: qml/Wizard/Pages/30-wifi.qml:172
662623msgid "Available Wi-Fi networks"
663624msgstr ""
664625
665−#: qml/Wizard/Pages/30-wifi.qml:166
626+#: qml/Wizard/Pages/30-wifi.qml:173
666627msgid "No available Wi-Fi networks"
667628msgstr ""
668629
669−#: qml/Wizard/Pages/40-location.qml:27
670−msgid "Location Services"
671−msgstr ""
672−
673−#: qml/Wizard/Pages/40-location.qml:83
674−msgid ""
675−"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
676−"(recommended)"
677−msgstr ""
678−
679−#: qml/Wizard/Pages/40-location.qml:105
680−#, qt-format
681−msgid "By selecting this option you agree to the Nokia HERE %1."
682−msgstr ""
683−
684−#: qml/Wizard/Pages/40-location.qml:106
685−msgctxt "part of: Nokia HERE terms and conditions"
686−msgid "terms and conditions"
687−msgstr ""
688−
689−#: qml/Wizard/Pages/40-location.qml:160
690−msgid "GPS only"
691−msgstr ""
692−
693−#: qml/Wizard/Pages/40-location.qml:214
694−msgid "Don't use my location"
695−msgstr ""
696−
697−#: qml/Wizard/Pages/40-location.qml:260
698−msgid "You can change it later in System Settings."
699−msgstr ""
700−
701630#: qml/Wizard/Pages/50-timezone.qml:30
702631msgid "Time Zone"
703632msgstr ""
704633
705−#: qml/Wizard/Pages/50-timezone.qml:182
634+#: qml/Wizard/Pages/50-timezone.qml:183
706635msgid "Enter your city"
707636msgstr ""
708637
@@ -710,7 +639,7 @@ msgstr ""
710639msgid "Personalize Your Device"
711640msgstr ""
712641
713−#: qml/Wizard/Pages/60-account.qml:48
642+#: qml/Wizard/Pages/60-account.qml:54
714643msgid "Preferred Name"
715644msgstr ""
716645
@@ -718,110 +647,72 @@ msgstr ""
718647msgid "Lock Screen"
719648msgstr ""
720649
721−#: qml/Wizard/Pages/70-passwd-type.qml:102
650+#: qml/Wizard/Pages/70-passwd-type.qml:103
722651msgctxt "Label: Type of security method"
723652msgid "Create new password"
724653msgstr ""
725654
726−#: qml/Wizard/Pages/70-passwd-type.qml:104
655+#: qml/Wizard/Pages/70-passwd-type.qml:105
727656msgctxt "Label: Type of security method"
728657msgid "Create passcode (numbers only)"
729658msgstr ""
730659
731−#: qml/Wizard/Pages/70-passwd-type.qml:106
660+#: qml/Wizard/Pages/70-passwd-type.qml:107
732661msgctxt "Label: Type of security method"
733662msgid "No lock code"
734663msgstr ""
735664
736−#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
737−msgid "Privacy Policy"
738−msgstr ""
739−
740−#: qml/Wizard/Pages/75-report-check.qml:26
741−msgid "Help Us Improve"
742−msgstr ""
743−
744−#: qml/Wizard/Pages/75-report-check.qml:59
745−msgid "Improve system performance by sending us crashes and error reports."
746−msgstr ""
747−
748−#: qml/Wizard/Pages/75-report-check.qml:60
749−msgid "Privacy policy"
750−msgstr ""
751−
752−#: qml/Wizard/Pages/77-system-update.qml:28
665+#: qml/Wizard/Pages/79-system-update.qml:28
753666msgid "Update Device"
754667msgstr ""
755668
756−#: qml/Wizard/Pages/77-system-update.qml:55
669+#: qml/Wizard/Pages/79-system-update.qml:55
757670msgid ""
758671"There is a system update available and ready to install. Afterwards, the "
759672"device will automatically restart."
760673msgstr ""
761674
762−#: qml/Wizard/Pages/77-system-update.qml:76
675+#: qml/Wizard/Pages/79-system-update.qml:76
763676msgctxt "string identifying name of the update"
764−msgid "Ubuntu system"
677+msgid "Ubuntu Touch system"
765678msgstr ""
766679
767−#: qml/Wizard/Pages/77-system-update.qml:83
680+#: qml/Wizard/Pages/79-system-update.qml:83
768681#, qt-format
769682msgctxt "version of the system update"
770683msgid "Version %1"
771684msgstr ""
772685
773−#: qml/Wizard/Pages/77-system-update.qml:102
686+#: qml/Wizard/Pages/79-system-update.qml:95
774687msgid "This could take a few minutes..."
775688msgstr ""
776689
777−#: qml/Wizard/Pages/77-system-update.qml:116
690+#: qml/Wizard/Pages/79-system-update.qml:109
778691msgid "Install and restart now"
779692msgstr ""
780693
781−#: qml/Wizard/Pages/80-finished.qml:89
782−msgid "Welcome to Ubuntu"
783−msgstr ""
784−
785−#: qml/Wizard/Pages/80-finished.qml:104
786−msgid "You are ready to use your device now"
787−msgstr ""
788−
789−#: qml/Wizard/Pages/80-finished.qml:124
790−msgid "Get Started"
791−msgstr ""
792−
793−#: qml/Wizard/Pages/here-terms.qml:25
794−msgid "Terms & Conditions"
795−msgstr ""
796−
797−#: qml/Wizard/Pages/here-terms.qml:69
798−msgid "Your device uses positioning technologies provided by HERE."
694+#: qml/Wizard/Pages/80-finished.qml:91
695+msgid "Welcome Back"
799696msgstr ""
800697
801−#: qml/Wizard/Pages/here-terms.qml:81
802−msgid ""
803−"To provide you with positioning services and to improve their quality, HERE "
804−"collects information about nearby cell towers and Wi-Fi hotspots around your "
805−"current location whenever your position is being found."
698+#: qml/Wizard/Pages/80-finished.qml:91
699+msgid "Welcome to Ubuntu"
806700msgstr ""
807701
808−#: qml/Wizard/Pages/here-terms.qml:93
809−msgid ""
810−"The information collected is used to analyze the service and to improve the "
811−"use of service, but not to identify you personally."
702+#: qml/Wizard/Pages/80-finished.qml:106
703+msgid "You are ready to use your device now"
812704msgstr ""
813705
814−#: qml/Wizard/Pages/here-terms.qml:106
815−#, qt-format
816−msgid "By continuing, you agree to the HERE platform %1 and %2."
706+#: qml/Wizard/Pages/80-finished.qml:126
707+msgid "Continue"
817708msgstr ""
818709
819−#: qml/Wizard/Pages/here-terms.qml:107
820−msgid "Service Terms"
710+#: qml/Wizard/Pages/80-finished.qml:126
711+msgid "Get Started"
821712msgstr ""
822713
823714#: qml/Wizard/Pages/passcode-confirm.qml:43
824−#: qml/Wizard/Pages/passcode-desktop.qml:97
715+#: qml/Wizard/Pages/passcode-desktop.qml:104
825716msgid "Confirm passcode"
826717msgstr ""
827718
@@ -838,24 +729,24 @@ msgstr ""
838729msgid "Lock Screen Passcode"
839730msgstr ""
840731
841−#: qml/Wizard/Pages/passcode-desktop.qml:61
732+#: qml/Wizard/Pages/passcode-desktop.qml:68
842733msgid "Enter 4 numbers to setup your passcode"
843734msgstr ""
844735
845−#: qml/Wizard/Pages/passcode-desktop.qml:77
736+#: qml/Wizard/Pages/passcode-desktop.qml:84
846737#: qml/Wizard/Pages/passcode-set.qml:54
847738msgid "Choose passcode"
848739msgstr ""
849740
850−#: qml/Wizard/Pages/passcode-desktop.qml:127
741+#: qml/Wizard/Pages/passcode-desktop.qml:139
851742msgid "Passcode too short"
852743msgstr ""
853744
854−#: qml/Wizard/Pages/passcode-desktop.qml:129
745+#: qml/Wizard/Pages/passcode-desktop.qml:141
855746msgid "Passcodes match"
856747msgstr ""
857748
858−#: qml/Wizard/Pages/passcode-desktop.qml:131
749+#: qml/Wizard/Pages/passcode-desktop.qml:143
859750msgid "Passcodes do not match"
860751msgstr ""
861752
@@ -867,15 +758,15 @@ msgstr ""
867758msgid "Lock Screen Password"
868759msgstr ""
869760
870−#: qml/Wizard/Pages/password-set.qml:62
761+#: qml/Wizard/Pages/password-set.qml:68
871762msgid "Enter at least 8 characters"
872763msgstr ""
873764
874−#: qml/Wizard/Pages/password-set.qml:74
765+#: qml/Wizard/Pages/password-set.qml:80
875766msgid "Choose password"
876767msgstr ""
877768
878−#: qml/Wizard/Pages/password-set.qml:104
769+#: qml/Wizard/Pages/password-set.qml:110
879770msgid "Confirm password"
880771msgstr ""
881772
@@ -931,12 +822,42 @@ msgstr ""
931822msgid "Very weak password"
932823msgstr ""
933824
825+#~ msgid "Remove from Favorites"
826+#~ msgstr "Seçilmişlәrdәn çıxart"
827+
828+#~ msgid "Add to Favorites"
829+#~ msgstr "Seçilmişlәrә әlavә et"
830+
831+#~ msgid "More..."
832+#~ msgstr "Daha çox..."
833+
834+#~ msgid "Less..."
835+#~ msgstr "Az..."
836+
837+#~ msgid "Send"
838+#~ msgstr "Göndər"
839+
840+#~ msgid "Rate this"
841+#~ msgstr "Qiymәtlәndir"
842+
843+#~ msgid "Add a review"
844+#~ msgstr "Rəy yaz"
845+
846+#, fuzzy
847+#~ msgid "Please wait..."
848+#~ msgstr "Yüklənir. Zəhmət olmasa, gözləyin..."
849+
850+#, fuzzy
851+#~ msgid "Download"
852+#~ msgstr "Endirilir"
853+
854+#, fuzzy
855+#~ msgid "Downloaded"
856+#~ msgstr "Endirilir"
857+
934858#~ msgid "Confirm"
935859#~ msgstr "Təsdiqlə"
936860
937−#~ msgid "Search"
938−#~ msgstr "Axtar"
939−
940861#~ msgid "Top edge"
941862#~ msgstr "Yuxarı künc"
942863
@@ -952,12 +873,6 @@ msgstr ""
952873#~ msgid "Right edge"
953874#~ msgstr "Sağ Künc"
954875
955−#~ msgid "Speaking..."
956−#~ msgstr "Danışır..."
957−
958−#~ msgid "Loading. Please Wait..."
959−#~ msgstr "Yüklənir. Zəhmət olmasa, gözləyin..."
960−
961876#~ msgid "Speak Now..."
962877#~ msgstr "Danışın..."
963878
@@ -993,18 +908,18 @@ msgstr ""
993908#~ msgstr "Bu sizin son cəhdiniz olacaq."
994909
995910#~ msgid ""
996−#~ "If passcode is entered incorrectly, your phone will conduct a factory reset "
997−#~ "and all personal data will be deleted."
911+#~ "If passcode is entered incorrectly, your phone will conduct a factory "
912+#~ "reset and all personal data will be deleted."
998913#~ msgstr ""
999−#~ "Əgər açar kod yanlış daxil edilibsə, onda telefonunuz fabrika parametrlərinə "
1000−#~ "geri qayıdacaq və bütün şəxsi məlumatlarınız silinəcək."
914+#~ "Əgər açar kod yanlış daxil edilibsə, onda telefonunuz fabrika "
915+#~ "parametrlərinə geri qayıdacaq və bütün şəxsi məlumatlarınız silinəcək."
1001916
1002917#~ msgid ""
1003918#~ "If passphrase is entered incorrectly, your phone will conduct a factory "
1004919#~ "reset and all personal data will be deleted."
1005920#~ msgstr ""
1006−#~ "Əgər açar söz yanlış daxil edilibsə, onda telefonunuz fabrika parametrlərinə "
1007−#~ "geri qayıdacaq və bütün şəxsi məlumatlarınız silinəcək."
921+#~ "Əgər açar söz yanlış daxil edilibsə, onda telefonunuz fabrika "
922+#~ "parametrlərinə geri qayıdacaq və bütün şəxsi məlumatlarınız silinəcək."
1008923
1009924#~ msgid "Log out"
1010925#~ msgstr "Çıxış"
@@ -1018,9 +933,6 @@ msgstr ""
1018933#~ msgid "Reboot"
1019934#~ msgstr "Yenidən yüklə"
1020935
1021−#~ msgid "Try swiping from the top edge to access the indicators"
1022−#~ msgstr "Göstəriciləri görmәk üçün yuxarı küncdən sürüşdürün"
1023−
1024936#~ msgid "Skip intro"
1025937#~ msgstr "Tәqdimatı keç"
1026938
@@ -1049,7 +961,6 @@ msgstr ""
1049961#~ msgid "Sorry, incorrect passphrase"
1050962#~ msgstr "Bağışlayın, açar söz yanlışdır"
1051963
1052−#, qt-format
1053964#~ msgid "Sorry, incorrect %1"
1054965#~ msgstr "Bağışlayın, %1 yanlışdır"
1055966
po/be.po+443−492

This diff is too big to show here.

po/bg.po+215−322

This diff is too big to show here.

po/bn.po+418−478

This diff is too big to show here.

po/br.po+385−362

This diff is too big to show here.

po/bs.po+288−344

This diff is too big to show here.

po/ca.po+469−387

This diff is too big to show here.

po/ca@valencia.po+272−349

This diff is too big to show here.

po/ce.po+189−305

This diff is too big to show here.

po/ckb.po+209−319

This diff is too big to show here.

po/co.po+355−335

This diff is too big to show here.

po/cs.po+537−493

This diff is too big to show here.

po/cy.po+288−343

This diff is too big to show here.

po/da.po+364−418

This diff is too big to show here.

po/de.po+473−391

This diff is too big to show here.

po/el.po+445−450

This diff is too big to show here.

po/en_AU.po+524−419

This diff is too big to show here.

po/en_GB.po+420−359

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+253−331

This diff is too big to show here.

po/es.po+481−400

This diff is too big to show here.

po/et.po+189−305

This diff is too big to show here.

po/eu.po+293−352

This diff is too big to show here.

po/fa.po+489−383

This diff is too big to show here.

po/fi.po+454−372

This diff is too big to show here.

po/fo.po+263−327

This diff is too big to show here.

po/fr.po+513−430

This diff is too big to show here.

po/ga.po+281−342

This diff is too big to show here.

po/gd.po+436−375

This diff is too big to show here.

po/gl.po+470−387

This diff is too big to show here.

po/gu.ponew file+814

This diff is too big to show here.

po/gv.po+229−319

This diff is too big to show here.

po/he.po+414−473

This diff is too big to show here.

po/hi.po+203−315

This diff is too big to show here.

po/hr.po+434−401

This diff is too big to show here.

po/hu.po+479−401

This diff is too big to show here.

po/hy.po+319−414

This diff is too big to show here.

po/ia.po+427−364

This diff is too big to show here.

po/id.po+271−347

This diff is too big to show here.

po/is.po+250−342

This diff is too big to show here.

po/it.po+479−397

This diff is too big to show here.

po/ja.po+323−398

This diff is too big to show here.

po/kk.ponew file+841

This diff is too big to show here.

po/km.po+285−346

This diff is too big to show here.

po/kn.po+197−315

This diff is too big to show here.

po/ko.po+427−467

This diff is too big to show here.

po/ku.po+236−324

This diff is too big to show here.

po/ky.po+197−315

This diff is too big to show here.

po/lo.po+196−312

This diff is too big to show here.

po/lt.po+476−426

This diff is too big to show here.

po/lv.po+301−359

This diff is too big to show here.

po/ml.po+210−321

This diff is too big to show here.

po/mr.po+212−310

This diff is too big to show here.

po/ms.po+448−433

This diff is too big to show here.

po/my.po+247−320

This diff is too big to show here.

po/nb.po+456−376

This diff is too big to show here.

po/ne.po+193−306

This diff is too big to show here.

po/nl.po+542−463

This diff is too big to show here.

po/nn.po+189−305

This diff is too big to show here.

po/oc.po+381−346

This diff is too big to show here.

po/or.po+189−305

This diff is too big to show here.

po/pa.po+297−355

This diff is too big to show here.

po/pl.po+484−403

This diff is too big to show here.

po/pt.po+474−393

This diff is too big to show here.

po/pt_BR.po+408−452

This diff is too big to show here.

po/ro.po+303−363

This diff is too big to show here.

po/ru.po+477−389

This diff is too big to show here.

po/sc.ponew file+904

This diff is too big to show here.

po/shn.po+189−305

This diff is too big to show here.

po/si.po+215−324

This diff is too big to show here.

po/sk.po+467−384

This diff is too big to show here.

po/sl.po+413−363

This diff is too big to show here.

po/sq.po+279−329

This diff is too big to show here.

po/sr.po+428−367

This diff is too big to show here.

po/sv.po+451−371

This diff is too big to show here.

po/sw.po+266−336

This diff is too big to show here.

po/ta.po+209−320

This diff is too big to show here.

po/te.po+217−319

This diff is too big to show here.

po/th.po+209−324

This diff is too big to show here.

po/tr.po+485−372

This diff is too big to show here.

po/ug.po+341−360

This diff is too big to show here.

po/uk.po+430−372

This diff is too big to show here.

po/unity8.pot+185−302

This diff is too big to show here.

po/update-unity-pot+17

This diff is too big to show here.

po/ur.po+210−323

This diff is too big to show here.

po/uz.po+189−305

This diff is too big to show here.

po/vi.po+189−305

This diff is too big to show here.

po/wo.po+297−356

This diff is too big to show here.

po/xh.po+189−305

This diff is too big to show here.

po/zh_CN.po+466−384

This diff is too big to show here.

po/zh_HK.po+226−320

This diff is too big to show here.

po/zh_TW.po+475−433

This diff is too big to show here.

qml/ApplicationMenus/ApplicationMenuItemFactory.qml+7−7

This diff is too big to show here.

qml/Dash/Previews/PreviewSingleton/PreviewSingleton.qml → qml/ApplicationMenus/ApplicationMenusLimits.qmlrenamed+5−3

This diff is too big to show here.

qml/ApplicationMenus/MenuBar.qml+343−134

This diff is too big to show here.

qml/ApplicationMenus/MenuItem.qml+17−21

This diff is too big to show here.

qml/ApplicationMenus/MenuNavigator.qml+23

This diff is too big to show here.

qml/ApplicationMenus/MenuPopup.qml+284−135

This diff is too big to show here.

qml/ApplicationMenus/RegisteredApplicationMenuModel.qml+1−1

This diff is too big to show here.

qml/ApplicationMenus/qmldirnew file+1

This diff is too big to show here.

qml/CMakeLists.txt−1

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/Carousel.qmldeleted−335

This diff is too big to show here.

qml/Components/Dialogs.qml+90−27

This diff is too big to show here.

qml/Components/EdgeBarrier.qml+1

This diff is too big to show here.

qml/Components/EdgeBarrierController.qml+1

This diff is too big to show here.

qml/Panel/Handle.qml → qml/Components/Handle.qmlrenamed+1

This diff is too big to show here.

qml/Components/InputMethod.qml+2−1

This diff is too big to show here.

qml/Components/ItemGrabber.qml+1−1

This diff is too big to show here.

qml/Components/KeyboardShortcutsOverlay.qml+17−28

This diff is too big to show here.

qml/Components/KeymapSwitcher.qml+15−7

This diff is too big to show here.

qml/Components/Lockscreen.qml+5−1

This diff is too big to show here.

qml/Components/ModeSwitchWarningDialog.qml+8−2

This diff is too big to show here.

qml/Components/PhysicalKeysMapper.qml+4−4

This diff is too big to show here.

qml/Components/ResponsiveGridView.qmldeleted−98

This diff is too big to show here.

qml/Components/ResponsiveVerticalJournal.qmldeleted−81

This diff is too big to show here.

qml/Components/ShellDialog.qml+27−12

This diff is too big to show here.

qml/Components/Showable.qml+15−12

This diff is too big to show here.

qml/Components/Wallpaper.qml+68−16

This diff is too big to show here.

qml/Components/WallpaperResolver.qml+17−6

This diff is too big to show here.

qml/Components/WindowControlButtons.qml+2−21

This diff is too big to show here.

qml/Dash/CardCarousel.qmldeleted−74

This diff is too big to show here.

qml/Dash/CardGrid.qmldeleted−84

This diff is too big to show here.

qml/Dash/CardHorizontalList.qmldeleted−66

This diff is too big to show here.

qml/Dash/CardTool.qmldeleted−298

This diff is too big to show here.

qml/Dash/CardVerticalJournal.qmldeleted−85

This diff is too big to show here.

qml/Dash/Dash.qmldeleted−381

This diff is too big to show here.

qml/Dash/DashCategoryBase.qmldeleted−54

This diff is too big to show here.

qml/Dash/DashContent.qmldeleted−211

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−199

This diff is too big to show here.

qml/Dash/DashNavigationHeader.qmldeleted−73

This diff is too big to show here.

qml/Dash/DashNavigationList.qmldeleted−118

This diff is too big to show here.

qml/Dash/DashPageHeader.qmldeleted−448

This diff is too big to show here.

qml/Dash/DashRenderer.qmldeleted−66

This diff is too big to show here.

qml/Dash/DashSectionHeader.qmldeleted−64

This diff is too big to show here.

qml/Dash/Filters/FilterExpandableWidget.qmldeleted−97

This diff is too big to show here.

qml/Dash/Filters/FilterOptionSelector.qmldeleted−97

This diff is too big to show here.

qml/Dash/Filters/FilterRangeInput.qmldeleted−136

This diff is too big to show here.

qml/Dash/Filters/FilterValueSlider.qmldeleted−87

This diff is too big to show here.

qml/Dash/Filters/FilterWidget.qmldeleted−32

This diff is too big to show here.

qml/Dash/Filters/FilterWidgetFactory.qmldeleted−89

This diff is too big to show here.

qml/Dash/FiltersPopover.qmldeleted−106

This diff is too big to show here.

qml/Dash/GenericScopeView.qmldeleted−797

This diff is too big to show here.

qml/Dash/PageHeaderExtraPanel.qmldeleted−201

This diff is too big to show here.

qml/Dash/PreviewView.qmldeleted−76

This diff is too big to show here.

qml/Dash/Previews/Preview.qmldeleted−145

This diff is too big to show here.

qml/Dash/Previews/PreviewActionButton.qmldeleted−27

This diff is too big to show here.

qml/Dash/Previews/PreviewActionCombo.qmldeleted−79

This diff is too big to show here.

qml/Dash/Previews/PreviewActions.qmldeleted−73

This diff is too big to show here.

qml/Dash/Previews/PreviewAudioPlayback.qmldeleted−152

This diff is too big to show here.

qml/Dash/Previews/PreviewComment.qmldeleted−86

This diff is too big to show here.

qml/Dash/Previews/PreviewCommentInput.qmldeleted−88

This diff is too big to show here.

qml/Dash/Previews/PreviewExpandable.qmldeleted−104

This diff is too big to show here.

qml/Dash/Previews/PreviewHeader.qmldeleted−170

This diff is too big to show here.

qml/Dash/Previews/PreviewIconActions.qmldeleted−88

This diff is too big to show here.

qml/Dash/Previews/PreviewImageGallery.qmldeleted−150

This diff is too big to show here.

qml/Dash/Previews/PreviewInlineVideo.qmldeleted−112

This diff is too big to show here.

qml/Dash/Previews/PreviewMediaToolbar.qmldeleted−57

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/PreviewProgress.qmldeleted−74

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingDisplay.qmldeleted−117

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingEdit.qmldeleted−83

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingInput.qmldeleted−207

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingSingleDisplay.qmldeleted−73

This diff is too big to show here.

qml/Dash/Previews/PreviewSingleton/qmldirdeleted−1

This diff is too big to show here.

qml/Dash/Previews/PreviewTable.qmldeleted−91

This diff is too big to show here.

qml/Dash/Previews/PreviewTextSummary.qmldeleted−78

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−60

This diff is too big to show here.

qml/Dash/Previews/PreviewWidgetFactory.qmldeleted−101

This diff is too big to show here.

qml/Dash/Previews/PreviewZoomableImage.qmldeleted−103

This diff is too big to show here.

qml/Dash/ScopeListView.qmldeleted−28

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/ScopeSettingNumber.qmldeleted−21

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−206

This diff is too big to show here.

qml/Dash/ScopesListCategory.qmldeleted−184

This diff is too big to show here.

qml/Dash/ScopesListCategoryItem.qmldeleted−113

This diff is too big to show here.

qml/Dash/graphics/dark_background.jpgdeleted

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/overview_hint@30.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/rectangular_dropshadow@30.pngdeleted

Binary file not shown.

qml/Dash/graphics/rectangular_dropshadow@30.scideleted−5

This diff is too big to show here.

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+12

This diff is too big to show here.

qml/Greeter/ButtonPrompt.qmlnew file+51

This diff is too big to show here.

qml/Greeter/CoverPage.qml+32−11

This diff is too big to show here.

qml/Greeter/Greeter.qml+51−16

This diff is too big to show here.

qml/Greeter/GreeterPrompt.qml+66−168

This diff is too big to show here.

qml/Greeter/GreeterView.qmlnew file+534

This diff is too big to show here.

qml/Greeter/LoginAreaContainer.qml+3−3

This diff is too big to show here.

qml/Greeter/LoginList.qml+79−86

This diff is too big to show here.

qml/Greeter/NarrowView.qmldeleted−277

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.qml+21−18

This diff is too big to show here.

qml/Greeter/SessionsList.qml+36−18

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−205

This diff is too big to show here.

qml/Launcher/Drawer.qml+286−179

This diff is too big to show here.

qml/Launcher/DrawerGridView.qml+44−6

This diff is too big to show here.

qml/Launcher/Launcher.qml+95−52

This diff is too big to show here.

qml/Launcher/LauncherDelegate.qml+9−12

This diff is too big to show here.

qml/Launcher/LauncherPanel.qml+61−22

This diff is too big to show here.

qml/Launcher/MoreAppsHeader.qmldeleted−46

This diff is too big to show here.

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

The content is the same.

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/launcher-app-focus-ring.svgdeleted−12

This diff is too big to show here.

qml/Notifications/Notification.qml+8−3

This diff is too big to show here.

qml/Notifications/NotificationButton.qml+2−1

This diff is too big to show here.

qml/Notifications/SwipeToAct.qml+4

This diff is too big to show here.

qml/OrientedShell.qml+20−7

This diff is too big to show here.

qml/Panel/ActiveCallHint.qml+3

This diff is too big to show here.

qml/Panel/Indicators/IndicatorItem.qml+14−2

This diff is too big to show here.

qml/Panel/Indicators/IndicatorMenuItemFactory.qml+3−3

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/client/IndicatorRepresentation.qml+18−5

This diff is too big to show here.

qml/Panel/MenuContent.qml+5−2

This diff is too big to show here.

qml/Panel/Panel.qml+103−30

This diff is too big to show here.

qml/Panel/PanelBar.qml+28−10

This diff is too big to show here.

qml/Panel/PanelItemRow.qml+41−33

This diff is too big to show here.

qml/Panel/PanelMenu.qml+61−29

This diff is too big to show here.

qml/Panel/PanelMenuPage.qml+4−3

This diff is too big to show here.

qml/Rotation/RotationStates.qml−3

This diff is too big to show here.

qml/ScopeTool.qmldeleted−165

This diff is too big to show here.

qml/Shell.qml+215−69

This diff is too big to show here.

qml/Stage/AbstractStage.qmldeleted−93

This diff is too big to show here.

qml/Stage/ApplicationWindow.qml+16−4

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.qml+64−53

This diff is too big to show here.

qml/Stage/DesktopSpread.qmldeleted−576

This diff is too big to show here.

qml/Stage/DesktopSpreadDelegate.qmldeleted−126

This diff is too big to show here.

qml/Stage/MoveHandler.qml+43−30

This diff is too big to show here.

qml/Stage/PhoneStage.qmldeleted−806

This diff is too big to show here.

qml/Stage/SideStage.qml+10−6

This diff is too big to show here.

qml/Stage/Splash.qml+4−4

This diff is too big to show here.

qml/Stage/Spread/Spread.qml+11

This diff is too big to show here.

qml/Stage/SpreadDelegate.qmldeleted−424

This diff is too big to show here.

qml/Stage/SpreadMaths.qmldeleted−164

This diff is too big to show here.

qml/Stage/Stage.qml+404−150

This diff is too big to show here.

qml/Stage/StageMaths.qml+21−2

This diff is too big to show here.

qml/Stage/StagedFullscreenPolicy.qml+5−11

This diff is too big to show here.

qml/Stage/TabletStage.qmldeleted−1201

This diff is too big to show here.

qml/Stage/TransformedSpreadDelegate.qmldeleted−391

This diff is too big to show here.

qml/Stage/TransformedTabletSpreadDelegate.qmldeleted−437

This diff is too big to show here.

qml/Stage/WindowControlsOverlay.qml+21−24

This diff is too big to show here.

qml/Stage/WindowDecoration.qml+19−16

This diff is too big to show here.

qml/Stage/WindowInfoItem.qml+16

This diff is too big to show here.

qml/Stage/WindowResizeArea.qml+15−2

This diff is too big to show here.

qml/Stage/WindowStateSaver.qml+4−3

This diff is too big to show here.

qml/Stage/WindowedFullscreenPolicy.qml+4−12

This diff is too big to show here.

qml/Tutorial/Tutorial.qml+1

This diff is too big to show here.

qml/Tutorial/TutorialContent.qml+61−43

This diff is too big to show here.

qml/Tutorial/TutorialLeft.qml+1−1

This diff is too big to show here.

qml/Tutorial/TutorialLeftLong.qml+2−2

This diff is too big to show here.

qml/Tutorial/TutorialRight.qml+2−3

This diff is too big to show here.

qml/Tutorial/TutorialTop.qml+2−2

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+15

This diff is too big to show here.

qml/Wizard/Pages.qml+90−16

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+3

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/30-wifi.qml+13−10

This diff is too big to show here.

qml/Wizard/Pages/40-location.qmldeleted−290

This diff is too big to show here.

qml/Wizard/Pages/50-timezone.qml+11−12

This diff is too big to show here.

qml/Wizard/Pages/60-account.qml+12−10

This diff is too big to show here.

qml/Wizard/Pages/70-passwd-type.qml+1

This diff is too big to show here.

qml/Wizard/Pages/75-report-check.qmldeleted−91

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/77-system-update.qml → qml/Wizard/Pages/79-system-update.qmlrenamed+4−12

This diff is too big to show here.

qml/Wizard/Pages/80-finished.qml+4−2

This diff is too big to show here.

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

This diff is too big to show here.

qml/Wizard/Pages/passcode-desktop.qml+14−5

This diff is too big to show here.

qml/Wizard/Pages/password-set.qml+12−4

This diff is too big to show here.

qml/Wizard/Wizard.qml+5−2

This diff is too big to show here.

src/ApplicationArguments.h+5

This diff is too big to show here.

src/CMakeLists.txt+7−5

This diff is too big to show here.

src/Dash/CMakeLists.txtdeleted−29

This diff is too big to show here.

src/Dash/main.cppdeleted−146

This diff is too big to show here.

src/MouseTouchAdaptor.cpp+28−1

This diff is too big to show here.

src/MouseTouchAdaptor.h+1

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/ShellApplication.cpp+19−4

This diff is too big to show here.

src/ShellApplication.h+1−3

This diff is too big to show here.

src/ShellView.cpp+22

This diff is too big to show here.

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

This diff is too big to show here.

src/main.cpp+9−1

This diff is too big to show here.

tests/CMakeLists.txt+15−4

This diff is too big to show here.

tests/autopilot/unity8/dash.pydeleted−263

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/test_helpers.py−123

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/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/imports/CMakeLists.txt+1−1

This diff is too big to show here.

tests/mocks/AccountsService/AccountsService.cpp−36

This diff is too big to show here.

tests/mocks/AccountsService/AccountsService.h−20

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/Biometryd/MockOperation.h−1

This diff is too big to show here.

tests/mocks/CMakeLists.txt+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/fake_gsettings.cpp+25−27

This diff is too big to show here.

tests/mocks/GSettings.1.0/fake_gsettings.h+9−9

This diff is too big to show here.

tests/mocks/LightDMController/CMakeLists.txt+1−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/MeeGo/QOfono/CMakeLists.txt+1−1

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/QMenuModel/CMakeLists.txt+1−2

This diff is too big to show here.

tests/mocks/QMenuModel/unitymenumodel.cpp+28−4

This diff is too big to show here.

tests/mocks/QMenuModel/unitymenumodel.h+9

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/Ubuntu/CMakeLists.txt−1

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+5−3

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/SystemImage/CMakeLists.txtdeleted−10

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/MockSystemImage.cppdeleted−50

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/MockSystemImage.hdeleted−56

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/plugin.hdeleted−31

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+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/Update/CMakeLists.txtnew file+1

This diff is too big to show here.

qml/Launcher/DrawerListView.qml → tests/mocks/Ubuntu/SystemSettings/Update/MockSystemImage.qmlrenamed+11−13

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/Unity/Application/ApplicationInfo.cpp+16−5

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationInfo.h+5−6

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationManager.cpp+29−8

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationManager.h+1−6

This diff is too big to show here.

tests/mocks/Unity/Application/CMakeLists.txt+2−2

This diff is too big to show here.

tests/mocks/Unity/Application/MirMock.cpp+13

This diff is too big to show here.

tests/mocks/Unity/Application/MirMock.h+4

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurface.cpp+52

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurface.h+16

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurfaceItem.cpp+19−4

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurfaceListModel.cpp+7−7

This diff is too big to show here.

tests/mocks/Unity/Application/MirSurfaceListModel.h+7−10

This diff is too big to show here.

tests/mocks/Unity/Application/SurfaceManager.cpp+19−13

This diff is too big to show here.

tests/mocks/Unity/Application/SurfaceManager.h+3−1

This diff is too big to show here.

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

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.

tests/mocks/Unity/Application/resources/KateDialog.qmlnew file+48

This diff is too big to show here.

qml/Dash/DashApplication.qml → tests/mocks/Unity/Application/resources/KateMenu.qmlrenamed+17−15

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.cpp+2−2

This diff is too big to show here.

tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.h+1−1

This diff is too big to show here.

tests/mocks/Unity/CMakeLists.txt−66

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/DashCommunicator/CMakeLists.txtdeleted−18

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+1−2

This diff is too big to show here.

tests/mocks/Unity/Indicators/IndicatorsModel.qml+30−12

This diff is too big to show here.

tests/mocks/Unity/Indicators/fakeindicatorsmodeldata.js+22−5

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/Launcher/CMakeLists.txt+1−3

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockAppDrawerModel.cpp+27−4

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockAppDrawerModel.h+11

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockLauncherItem.cpp+13

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/Unity/Launcher/MockQuickListModel.cpp+3−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/Notifications/CMakeLists.txt+1−1

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/Unity/fake_categories.cppdeleted−165

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_expandablefilterwidget.cppdeleted−53

This diff is too big to show here.

tests/mocks/Unity/fake_expandablefilterwidget.hdeleted−48

This diff is too big to show here.

tests/mocks/Unity/fake_filters.cppdeleted−136

This diff is too big to show here.

tests/mocks/Unity/fake_filters.hdeleted−46

This diff is too big to show here.

tests/mocks/Unity/fake_navigation.cppdeleted−123

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_optionselectorfilter.cppdeleted−70

This diff is too big to show here.

tests/mocks/Unity/fake_optionselectorfilter.hdeleted−54

This diff is too big to show here.

tests/mocks/Unity/fake_optionselectoroptions.cppdeleted−90

This diff is too big to show here.

tests/mocks/Unity/fake_optionselectoroptions.hdeleted−49

This diff is too big to show here.

tests/mocks/Unity/fake_previewmodel.cppdeleted−103

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_previewwidgetmodel.cppdeleted−97

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_rangeinputfilter.cppdeleted−167

This diff is too big to show here.

tests/mocks/Unity/fake_rangeinputfilter.hdeleted−79

This diff is too big to show here.

tests/mocks/Unity/fake_resultsmodel.cppdeleted−92

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−372

This diff is too big to show here.

tests/mocks/Unity/fake_scope.hdeleted−128

This diff is too big to show here.

tests/mocks/Unity/fake_scopes.cppdeleted−287

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−119

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−62

This diff is too big to show here.

tests/mocks/Unity/fake_unity_plugin.hdeleted−34

This diff is too big to show here.

tests/mocks/Unity/fake_valuesliderfilter.cppdeleted−84

This diff is too big to show here.

tests/mocks/Unity/fake_valuesliderfilter.hdeleted−55

This diff is too big to show here.

tests/mocks/Unity/fake_valueslidervalues.cppdeleted−51

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+8−3

This diff is too big to show here.

tests/mocks/Utils/plugin.cpp+7−1

This diff is too big to show here.

tests/mocks/Wizard/CMakeLists.txt+2−2

This diff is too big to show here.

tests/mocks/Wizard/MockSystem.cpp+19−4

This diff is too big to show here.

tests/mocks/Wizard/MockSystem.h+11−1

This diff is too big to show here.

tests/mocks/Wizard/mockplugin.cpp+2

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/liblightdm/MockController.cpp+2−25

This diff is too big to show here.

tests/mocks/liblightdm/MockController.h−15

This diff is too big to show here.

tests/mocks/liblightdm/MockUsersModel.cpp+2−2

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+1−1

This diff is too big to show here.

tests/plugins/AccountsService/CMakeLists.txt+2−2

This diff is too big to show here.

tests/plugins/AccountsService/PropertiesServer.cpp+1−1

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/CMakeLists.txt+2−3

This diff is too big to show here.

tests/plugins/Dash/CMakeLists.txtdeleted−104

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/1.res.cardcreatordeleted−69

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/10.resdeleted−129

This diff is too big to show here.

tests/plugins/Dash/cardcreator/10.res.cardcreatordeleted−127

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/11.resdeleted−176

This diff is too big to show here.

tests/plugins/Dash/cardcreator/11.res.cardcreatordeleted−160

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/12.resdeleted−108

This diff is too big to show here.

tests/plugins/Dash/cardcreator/12.res.cardcreatordeleted−95

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/2.res.cardcreatordeleted−126

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/3.res.cardcreatordeleted−86

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/4.res.cardcreatordeleted−99

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/5.res.cardcreatordeleted−99

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/6.res.cardcreatordeleted−116

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/7.res.cardcreatordeleted−139

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/8.res.cardcreatordeleted−97

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreator/9.resdeleted−120

This diff is too big to show here.

tests/plugins/Dash/cardcreator/9.res.cardcreatordeleted−109

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Dash/cardcreatortest.cppdeleted−126

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−91

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−2212

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertest.cppdeleted−2038

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertest.qmldeleted−96

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertestsection.qmldeleted−119

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qmldeleted−76

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−99

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−140

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−564

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−91

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+1−2

This diff is too big to show here.

tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt+1−3

This diff is too big to show here.

tests/plugins/ImageCache/CMakeLists.txtdeleted−30

This diff is too big to show here.

tests/plugins/ImageCache/graphics/wide.jpgdeleted

Binary file not shown.

tests/plugins/ImageCache/test.cppdeleted−216

This diff is too big to show here.

tests/plugins/ImageCache/test.qmldeleted−23

This diff is too big to show here.

tests/plugins/LightDM/IntegratedLightDM/CMakeLists.txt+6−6

This diff is too big to show here.

tests/plugins/LightDM/IntegratedLightDM/dbus.cpp+18−5

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/SessionBroadcast/CMakeLists.txt+2−2

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/CMakeLists.txt+4−2

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/GestureTest.cpp+10−1

This diff is too big to show here.

tests/plugins/Ubuntu/Gestures/tst_TouchGate.cpp+11−2

This diff is too big to show here.

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

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+1−1

This diff is too big to show here.

tests/plugins/Unity/Launcher/CMakeLists.txt+39−2

This diff is too big to show here.

tests/plugins/Unity/Launcher/appdrawermodeltest.cppnew file+68

This diff is too big to show here.

tests/plugins/Unity/Launcher/launchermodeltest.cpp+86−7

This diff is too big to show here.

tests/plugins/Unity/Launcher/ualwrapper.cppnew file+58

This diff is too big to show here.

tests/plugins/Unity/Launcher/ualwrapper.hnew file+55

This diff is too big to show here.

tests/mocks/Ubuntu/SystemImage/plugin.cpp → tests/plugins/Unity/Launcher/xdgwatcher.cpprenamed+22−11

This diff is too big to show here.

tests/mocks/Unity/fake_valueslidervalues.h → tests/plugins/Unity/Launcher/xdgwatcher.hrenamed+16−13

This diff is too big to show here.

tests/plugins/Unity/Platform/CMakeLists.txtnew file+30

This diff is too big to show here.

tests/plugins/Unity/Platform/platformtest.cppnew file+142

This diff is too big to show here.

tests/plugins/Unity/Session/CMakeLists.txt+15−3

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/Unity/Session/preload.cnew file+43

This diff is too big to show here.

tests/plugins/Unity/Session/sessionbackendtest.cpp+130−11

This diff is too big to show here.

tests/plugins/Utils/CMakeLists.txt+6−5

This diff is too big to show here.

tests/plugins/Utils/DeviceConfigParserTest.cpp+3

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/WindowInputMonitorTest.cpp+31−1

This diff is too big to show here.

tests/plugins/Utils/WindowStateStorageTest.cppnew file+121

This diff is too big to show here.

tests/plugins/WindowManager/CMakeLists.txtnew file+36

This diff is too big to show here.

tests/plugins/WindowManager/UnityApplicationMocks.hnew file+211

This diff is too big to show here.

tests/plugins/WindowManager/tst_TopLevelWindowModel.cppnew file+193

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/ApplicationMenuDataLoader.qml+30−6

This diff is too big to show here.

tests/qmltests/ApplicationMenus/tst_MenuBar.qml+263−9

This diff is too big to show here.

tests/qmltests/ApplicationMenus/tst_MenuPopup.qml+209−55

This diff is too big to show here.

tests/qmltests/CMakeLists.txt+5−51

This diff is too big to show here.

tests/qmltests/Components/CMakeLists.txt+8−4

This diff is too big to show here.

tests/qmltests/Components/tst_Carousel.qmldeleted−292

This diff is too big to show here.

tests/qmltests/Components/tst_Dialogs.qml−1

This diff is too big to show here.

tests/qmltests/Components/tst_DragHandle.cpp+19−2

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_Lockscreen.qml+11−9

This diff is too big to show here.

tests/qmltests/Components/tst_MediaServices.qml+5−4

This diff is too big to show here.

tests/qmltests/Components/tst_PhysicalKeysMapper.qml+7−6

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.qmldeleted−157

This diff is too big to show here.

tests/qmltests/Components/tst_ResponsiveVerticalJournal.qmldeleted−183

This diff is too big to show here.

tests/qmltests/Components/tst_SharingPicker.qml+3−3

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_Wallpaper.qmlnew file+118

This diff is too big to show here.

tests/qmltests/Components/tst_WallpaperResolver.qml+104−18

This diff is too big to show here.

tests/qmltests/Dash/CardHelpers.jsdeleted−115

This diff is too big to show here.

tests/qmltests/Dash/Filters/tst_FilterExpandableWidget.qmldeleted−99

This diff is too big to show here.

tests/qmltests/Dash/Filters/tst_FilterOptionSelector.qmldeleted−96

This diff is too big to show here.

tests/qmltests/Dash/Filters/tst_FilterRangeInput.qmldeleted−247

This diff is too big to show here.

tests/qmltests/Dash/Filters/tst_FilterValueSlider.qmldeleted−101

This diff is too big to show here.

tests/qmltests/Dash/Filters/tst_FilterWidgetFactory.qmldeleted−59

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_Preview.qmldeleted−214

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewActions.qmldeleted−262

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qmldeleted−182

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewCommentInput.qmldeleted−113

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewExpandable.qmldeleted−353

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewHeader.qmldeleted−183

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewIconActions.qmldeleted−136

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewImageGallery.qmldeleted−147

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewInlineVideo.qmldeleted−155

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewMediaToolbar.qmldeleted−69

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewProgress.qmldeleted−100

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingDisplay.qmldeleted−123

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingDisplayCreationRanges.qmldeleted−131

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingEdit.qmldeleted−87

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingInput.qmldeleted−246

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewTable.qmldeleted−147

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qmldeleted−104

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qmldeleted−138

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

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

Binary file not shown.

tests/qmltests/Dash/artwork/background.pngdeleted

Binary file not shown.

tests/qmltests/Dash/artwork/checkers.pngdeleted

Binary file not shown.

tests/qmltests/Dash/artwork/emblem.pngdeleted

Binary file not shown.

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

Binary file not shown.

tests/qmltests/Dash/tst_Card.qmldeleted−682

This diff is too big to show here.

tests/qmltests/Dash/tst_CardBenchmark.qmldeleted−95

This diff is too big to show here.

tests/qmltests/Dash/tst_CardCarousel.qmldeleted−111

This diff is too big to show here.

tests/qmltests/Dash/tst_CardTool.qmldeleted−379

This diff is too big to show here.

tests/qmltests/Dash/tst_Dash.qmldeleted−695

This diff is too big to show here.

tests/qmltests/Dash/tst_DashContent.qmldeleted−730

This diff is too big to show here.

tests/qmltests/Dash/tst_DashPageHeader.qmldeleted−357

This diff is too big to show here.

tests/qmltests/Dash/tst_DashShell.qmldeleted−124

This diff is too big to show here.

tests/qmltests/Dash/tst_GenericScopeView.qmldeleted−722

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Dash/tst_PreviewView.qmldeleted−122

This diff is too big to show here.

tests/qmltests/Greeter/TestView.qml+9−6

This diff is too big to show here.

tests/qmltests/Greeter/tst_Greeter.qml+19−31

This diff is too big to show here.

tests/qmltests/Greeter/tst_GreeterView.qmlnew file+1366

This diff is too big to show here.

tests/qmltests/Greeter/tst_NarrowView.qmldeleted−566

This diff is too big to show here.

tests/qmltests/Greeter/tst_WideView.qmldeleted−781

This diff is too big to show here.

tests/qmltests/Launcher/tst_Drawer.qml+269−13

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Notifications/tst_Notifications.qml+16−10

This diff is too big to show here.

tests/qmltests/Notifications/tst_OptionToggle.qml+12−6

This diff is too big to show here.

tests/qmltests/Notifications/tst_SwipeToAct.qml+10−3

This diff is too big to show here.

tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+3−3

This diff is too big to show here.

tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml+33−79

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/PanelUI.qmlnew file+286

This diff is too big to show here.

tests/qmltests/Panel/tst_ActiveCallHint.qml+14−9

This diff is too big to show here.

tests/qmltests/Panel/tst_MenuContent.qml+2−2

This diff is too big to show here.

tests/qmltests/Panel/tst_Panel.qml+149−253

This diff is too big to show here.

tests/qmltests/Panel/tst_PanelItemRow.qml+2−2

This diff is too big to show here.

tests/qmltests/Panel/tst_PanelMenu.qml+61−22

This diff is too big to show here.

tests/qmltests/Panel/tst_PanelMenuPage.qml+1−1

This diff is too big to show here.

tests/qmltests/Panel/tst_PanelSmallScreen.qmlnew file+133

This diff is too big to show here.

tests/qmltests/Stage/ApplicationCheckBox.qml+7−7

This diff is too big to show here.

tests/qmltests/Stage/tst_ApplicationWindow.qml+3−2

This diff is too big to show here.

tests/qmltests/Stage/tst_DesktopStage.qml+280−29

This diff is too big to show here.

tests/qmltests/Stage/tst_PhoneStage.qml+95−64

This diff is too big to show here.

tests/qmltests/Stage/tst_QMLTopLevelWindowModel.qmlnew file+191

This diff is too big to show here.

tests/qmltests/Stage/tst_SpreadDelegate.qmldeleted−423

This diff is too big to show here.

tests/qmltests/Stage/tst_SurfaceContainer.qml+9−8

This diff is too big to show here.

tests/qmltests/Stage/tst_TabletStage.qml+137−139

This diff is too big to show here.

tests/qmltests/Stage/tst_WindowDecoration.qml+3−3

This diff is too big to show here.

tests/qmltests/Stage/tst_WindowResizeArea.qml+14−3

This diff is too big to show here.

tests/qmltests/Tutorial/tst_Tutorial.qml+189−190

This diff is too big to show here.

tests/qmltests/Wizard/tst_Wizard.qml+100−142

This diff is too big to show here.

tests/qmltests/tst_OrientedShell.qml+398−262

This diff is too big to show here.

tests/qmltests/tst_Shell.qml+1144−566

This diff is too big to show here.

tests/qmltests/tst_ShellWithPin.qml+113−118

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+1−1

This diff is too big to show here.

tests/utils/modules/Unity/Test/CMakeLists.txt+2−4

This diff is too big to show here.

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

This diff is too big to show here.

tests/utils/modules/Unity/Test/StageTestCase.qml+14−18

This diff is too big to show here.

tests/utils/modules/Unity/Test/TouchEventSequenceWrapper.cpp+10−1

This diff is too big to show here.

tests/utils/modules/Unity/Test/UnityTestCase.qml+2−11

This diff is too big to show here.

tools/CMakeLists.txt+2−12

This diff is too big to show here.

src/Panel/Indicators/client/CMakeLists.txt → tools/indicatorsclient/CMakeLists.txtrenamed+1−1

This diff is too big to show here.

src/Panel/Indicators/client/indicatorsclient.cpp → tools/indicatorsclient/indicatorsclient.cpprenamed

The content is the same.

src/Panel/Indicators/client/indicatorsclient.h → tools/indicatorsclient/indicatorsclient.hrenamed

The content is the same.

src/Panel/Indicators/client/main.cpp → tools/indicatorsclient/main.cpprenamed

The content is the same.

tools/menutool/CMakeLists.txtnew file+5

This diff is too big to show here.

tools/menutool/READMEnew file+11

This diff is too big to show here.

tools/menutool/menutool.cppnew file+62

This diff is too big to show here.

tools/menutool/menutool.qmlnew file+118

This diff is too big to show here.

tools/registry-tracker.cppdeleted−146

This diff is too big to show here.

tools/registry-tracker.hdeleted−49

This diff is too big to show here.

tools/scopetool.cppdeleted−116

This diff is too big to show here.

tools/unlock-device+16

This diff is too big to show here.