on da10fdf help sign in
760 files changed+82348−41476
since splitsnapshots
unifiedsplit
.bazaar/Makefile+6 .bazaar/plugins/makecheck_unity_phablet.py+51 .bzr-builddeb/default.conf+2 .bzrignore+7 .gitignore−7 CMakeLists.txt+4−5 Jenkinsfile−2 README.md−31 clickable.yaml−153 cmake/modules/QmlPlugins.cmake+148 cmake/modules/QmlTest.cmake+1−1 data/CMakeLists.txt+9−1 data/com.canonical.Unity.gschema.xml−255 data/com.canonical.Unity8.gschema.xml+7−2 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.conf−17 debian/changelog+20−72 debian/control+198−215 debian/rules+5−19 debian/source/format+1 debian/tests/control+3−5 debian/unity-scope-tool.install+2 debian/unity8-common.install+2 debian/unity8-greeter.install+1−1 debian/unity8-private.install+3−1 debian/unity8-schemas.install−1 debian/unity8-tests.install+1 debian/unity8.install+10−6 debian/usr.bin.unity8-dash+21 plugins/AccountsService/AccountsService.cpp+30−1 plugins/AccountsService/AccountsService.h+16 plugins/AccountsService/CMakeLists.txt+2−1 plugins/AccountsService/com.canonical.unity.AccountsService.xml−6 plugins/CMakeLists.txt+3−1 plugins/Cursor/CMakeLists.txt+2−1 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/Lights/HfdLights.h → plugins/Dash/plugin.h+8−17 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+2−1 plugins/Greeter/Unity/Launcher/launcheritem.cpp−6 plugins/Greeter/Unity/Launcher/launcheritem.h−1 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+4−3 plugins/LightDM/UsersModel.cpp−5 plugins/Lights/CMakeLists.txt+2−8 plugins/Lights/HfdLights.cpp−62 plugins/Lights/LegacyLights.cpp−91 plugins/Lights/Lights.cpp+65 plugins/Lights/Lights.h+8−4 plugins/Lights/plugin.cpp+1−20 plugins/Powerd/CMakeLists.txt+2−4 plugins/ScreenshotDirectory/CMakeLists.txt+1−1 plugins/SessionBroadcast/CMakeLists.txt+2−1 plugins/UInput/CMakeLists.txt+1−1 plugins/Ubuntu/DownloadDaemonListener/CMakeLists.txt+2−4 plugins/Ubuntu/Gestures/CMakeLists.txt+3−1 plugins/Ubuntu/Gestures/TouchGestureArea.cpp−6 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/dashcommunicator.h+45 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/Lights/LegacyLights.h → plugins/Unity/DashCommunicator/plugin.h+8−19 plugins/Unity/DashCommunicator/qmldir+3 plugins/Unity/Indicators/CMakeLists.txt+2−1 plugins/Unity/Indicators/indicatorsmodel.cpp−13 plugins/Unity/Indicators/indicatorsmodel.h−9 plugins/Unity/InputInfo/CMakeLists.txt+2−1 plugins/Unity/Launcher/CMakeLists.txt+2−2 plugins/Unity/Launcher/appdrawermodel.cpp+14−144 plugins/Unity/Launcher/appdrawermodel.h+2−33 plugins/Unity/Launcher/launcheritem.cpp+1−13 plugins/Unity/Launcher/launcheritem.h−3 plugins/Unity/Launcher/launchermodel.cpp+5−1 plugins/Unity/Launcher/ualwrapper.cpp+2−3 plugins/Unity/Launcher/ualwrapper.h+1−2 plugins/Unity/Launcher/xdgwatcher.cpp−129 plugins/Unity/Launcher/xdgwatcher.h−46 plugins/Unity/Platform/CMakeLists.txt+1−1 plugins/Unity/Session/CMakeLists.txt+1−1 plugins/Utils/CMakeLists.txt+4−3 plugins/Utils/appdrawerproxymodel.cpp+1−1 plugins/Utils/deviceconfigparser.cpp−18 plugins/Utils/deviceconfigparser.h−3 plugins/Utils/windowstatestorage.cpp+131−293 plugins/Utils/windowstatestorage.h+17−14 plugins/WindowManager/CMakeLists.txt+1−2 plugins/WindowManager/InputMethodManager.cpp−56 plugins/WindowManager/InputMethodManager.h−55 plugins/WindowManager/TopLevelWindowModel.cpp+42−103 plugins/WindowManager/TopLevelWindowModel.h+8−50 plugins/WindowManager/Window.cpp−9 plugins/WindowManager/WindowManagerPlugin.cpp−9 plugins/Wizard/CMakeLists.txt+2−5 plugins/Wizard/Changelog.cpp−58 plugins/Wizard/Changelog.h−52 plugins/Wizard/PageList.cpp+5−6 plugins/Wizard/System.cpp+7−69 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+309−184 po/am.po+357−392 po/ar.po+482−434 po/ast.po+478−495 po/az.po+312−191 po/be.po+483−402 po/bg.po+307−168 po/bn.po+470−378 po/br.po+370−349 po/bs.po+329−241 po/ca.po+378−418 po/ca@valencia.po+334−225 po/ce.po+290−142 po/ckb.po+304−162 po/co.po+324−309 po/cs.po+485−497 po/cy.po+328−241 po/da.po+409−323 po/de.po+387−428 po/el.po+442−402 po/en_AU.po+409−479 po/en_GB.po+361−381 po/en_US.po−814 po/eo.po+316−206 po/es.po+385−423 po/et.po+290−142 po/eu.po+337−246 po/fa.po+377−442 po/fi.po+364−405 po/fo.po+312−216 po/fr.po+426−466 po/ga.po+327−234 po/gd.po+371−391 po/gl.po+382−423 po/gu.po−814 po/gv.po+304−182 po/he.po+464−373 po/hi.po+300−156 po/hr.po+392−384 po/hu.po+399−436 po/hy.po+406−279 po/ia.po+359−381 po/id.po+340−232 po/is.po+327−203 po/it.po+391−430 po/ja.po+389−282 po/kk.po−841 po/km.po+332−239 po/kn.po+300−150 po/ko.po+458−386 po/ku.po+337−217 po/ky.po+300−150 po/lo.po+297−149 po/lt.po+414−432 po/lv.po+344−254 po/ml.po+306−163 po/mr.po+295−165 po/ms.po+427−401 po/my.po+305−200 po/nb.po+369−408 po/ne.po+290−145 po/nl.po+461−499 po/nn.po+290−142 po/oc.po+342−336 po/or.po+290−142 po/pa.po+340−250 po/pl.po+402−442 po/pt.po+390−430 po/pt_BR.po+443−367 po/ro.po+348−256 po/ru.po+381−431 po/sc.po−904 po/shn.po+290−142 po/si.po+310−169 po/sk.po+382−424 po/sl.po+354−366 po/sq.po+314−232 po/sr.po+362−382 po/sv.po+368−407 po/sw.po+321−219 po/ta.po+322−177 po/te.po+304−170 po/th.po+317−170 po/tr.po+367−439 po/ug.po+347−293 po/uk.po+374−391 po/unity8.pot+238−111 po/ur.po+316−171 po/uz.po+290−142 po/vi.po+290−142 po/wo.po+341−250 po/xh.po+290−142 po/zh_CN.po+383−424 po/zh_HK.po+305−179 po/zh_TW.po+420−427 qml/ApplicationMenus/ApplicationMenuItemFactory.qml+7−7 qml/ApplicationMenus/MenuItem.qml+3−3 qml/ApplicationMenus/RegisteredApplicationMenuModel.qml+1−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+20−44 qml/Components/InputMethod.qml+1−2 qml/Components/ItemGrabber.qml+1−1 qml/Components/KeyboardShortcutsOverlay.qml+26−2 qml/Components/Lockscreen.qml−2 qml/Components/PhysicalKeysMapper.qml+4−4 qml/Components/ResponsiveGridView.qml+98 qml/Components/ResponsiveVerticalJournal.qml+81 qml/Components/ShellDialog.qml+10−7 qml/Components/Showable.qml+12−15 qml/Components/Wallpaper.qml+16−68 qml/Components/WallpaperResolver.qml+6−17 qml/Dash/CardCarousel.qml+74 qml/Dash/CardGrid.qml+83 qml/Dash/CardHorizontalList.qml+66 qml/Dash/CardTool.qml+274 qml/Dash/CardVerticalJournal.qml+85 qml/Dash/Dash.qml+381 qml/Dash/DashApplication.qml+39 qml/Dash/DashBackground.qml+21 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 tests/plugins/Unity/Launcher/xdgwatcher.cpp → qml/Dash/Filters/FilterWidget.qml+11−24 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 tests/mocks/Ubuntu/SystemSettings/Update/MockSystemImage.qml → qml/Dash/Previews/PreviewSingleton/PreviewSingleton.qml+5−13 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/Launcher/PullToRefreshScopeStyle.qml → qml/Dash/PullToRefreshScopeStyle.qml 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+11−32 qml/Greeter/Greeter.qml+5−51 qml/Greeter/GreeterPrompt.qml+185−64 qml/Greeter/GreeterView.qml−534 qml/Greeter/LoginAreaContainer.qml+3−3 qml/Greeter/LoginList.qml+84−73 qml/Greeter/NarrowView.qml+263 qml/Greeter/PinPrompt.qml−184 qml/Greeter/PromptList.qml+18−21 qml/Greeter/SessionsList.qml+18−36 qml/Greeter/ShimGreeter.qml−2 qml/Greeter/TextPrompt.qml−198 qml/Greeter/WideView.qml+205 qml/Launcher/Drawer.qml+247−263 qml/Launcher/DrawerGridView.qml+5−41 qml/Launcher/DrawerListView.qml+38 qml/Launcher/Launcher.qml+44−72 qml/Launcher/LauncherDelegate.qml+3−1 qml/Launcher/LauncherPanel.qml+11−15 qml/Launcher/MoreAppsHeader.qml+69 qml/Notifications/Notification.qml+3−8 qml/Notifications/NotificationButton.qml+1−2 qml/Notifications/SwipeToAct.qml−4 qml/OrientedShell.qml+1−11 qml/Panel/ActiveCallHint.qml−3 qml/Components/Handle.qml → qml/Panel/Handle.qml−1 qml/Panel/Indicators/IndicatorItem.qml+2−14 qml/Panel/Indicators/IndicatorMenuItemFactory.qml+3−3 qml/Panel/Indicators/IndicatorsLight.qml+12−185 qml/Panel/MenuContent.qml+1−4 qml/Panel/Panel.qml+22−60 qml/Panel/PanelBar.qml+8−10 qml/Panel/PanelItemRow.qml+4−6 qml/Panel/PanelMenu.qml+9−15 qml/Panel/PanelMenuPage.qml+1−1 qml/Rotation/RotationStates.qml+3 qml/ScopeTool.qml+165 qml/Shell.qml+66−119 qml/Stage/AbstractStage.qml+93 qml/Stage/ApplicationWindow.qml+4−15 qml/Stage/ChildWindow.qml+4 qml/Stage/DecoratedWindow.qml+1−1 qml/Stage/DesktopSpread.qml+576 qml/Stage/DesktopSpreadDelegate.qml+126 qml/Stage/MoveHandler.qml+7−7 qml/Stage/PhoneStage.qml+806 qml/Stage/SideStage.qml+6−10 qml/Stage/Splash.qml+4−4 qml/Stage/SpreadDelegate.qml+424 qml/Stage/SpreadMaths.qml+164 qml/Stage/Stage.qml+44−166 qml/Stage/StageMaths.qml+2−5 qml/Stage/TabletStage.qml+1201 qml/Stage/TransformedSpreadDelegate.qml+391 qml/Stage/TransformedTabletSpreadDelegate.qml+437 qml/Stage/WindowDecoration.qml+6−5 qml/Stage/WindowedFullscreenPolicy.qml+1−1 qml/Tutorial/Tutorial.qml−1 qml/Tutorial/TutorialContent.qml+43−61 qml/Tutorial/TutorialLeft.qml+1−1 qml/Tutorial/TutorialLeftLong.qml+1−1 qml/Tutorial/TutorialRight.qml+3−2 qml/Tutorial/TutorialTop.qml+2−2 qml/Wizard/Components/InputMethod.qml+9−9 qml/Wizard/Page.qml−15 qml/Wizard/Pages.qml+16−90 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+6−13 qml/Wizard/Pages/40-location.qml+290 qml/Wizard/Pages/50-timezone.qml+12−11 qml/Wizard/Pages/60-account.qml+10−12 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/79-system-update.qml−148 qml/Wizard/Pages/80-finished.qml+2−4 qml/Wizard/Pages/here-terms.qml+126 qml/Wizard/Pages/passcode-desktop.qml+5−14 qml/Wizard/Pages/password-set.qml+4−12 qml/Wizard/Wizard.qml+2−5 src/ApplicationArguments.h−5 src/CMakeLists.txt+4−5 src/Dash/CMakeLists.txt+29 src/Dash/main.cpp+146 src/ShellApplication.cpp+4−14 src/ShellApplication.h+3−1 src/libunity8-private/CMakeLists.txt+1−1 src/main.cpp+1−9 tests/CMakeLists.txt+2−9 tests/autopilot/unity8/dash.py+247 tests/autopilot/unity8/shell/fixture_setup.py+27−1 tests/autopilot/unity8/shell/tests/test_helpers.py+74 tests/autopilot/unity8/shell/tests/test_rotation.py+3−3 tests/copyright/check_copyright.sh−2 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+2−1 tests/mocks/Biometryd/CMakeLists.txt+1−1 tests/mocks/CMakeLists.txt+1−1 tests/mocks/GSettings.1.0/CMakeLists.txt+2−1 tests/mocks/GSettings.1.0/fake_gsettings.cpp+35−19 tests/mocks/GSettings.1.0/fake_gsettings.h+15−8 tests/mocks/LightDMController/CMakeLists.txt+2−1 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+2−1 tests/mocks/QtMultimedia/CMakeLists.txt+1−1 tests/mocks/SessionBroadcast/CMakeLists.txt+1−1 tests/mocks/UInput/CMakeLists.txt+1−1 tests/mocks/Ubuntu/Connectivity/CMakeLists.txt+1−1 tests/mocks/Ubuntu/Connectivity/networking-status.cpp+1−7 tests/mocks/Ubuntu/Connectivity/networking-status.h+3−5 tests/mocks/Ubuntu/DownloadDaemonListener/CMakeLists.txt+1−1 tests/mocks/Ubuntu/SystemSettings/CMakeLists.txt−1 tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/CMakeLists.txt+1−1 tests/mocks/Ubuntu/SystemSettings/Update/CMakeLists.txt−1 tests/mocks/Ubuntu/SystemSettings/Update/qmldir−2 tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−1 tests/mocks/Unity/Application/ApplicationInfo.cpp+4−7 tests/mocks/Unity/Application/ApplicationInfo.h+6−2 tests/mocks/Unity/Application/ApplicationManager.cpp+1−14 tests/mocks/Unity/Application/CMakeLists.txt+2−2 tests/mocks/Unity/Application/MirSurface.h−1 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+72 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/plugin.h+34 tests/mocks/Unity/DashCommunicator/qmldir+3 tests/mocks/Unity/Indicators/CMakeLists.txt+2−1 tests/mocks/Unity/Indicators/IndicatorsModel.qml+12−30 tests/mocks/Unity/Indicators/fakeindicatorsmodeldata.js+5−6 tests/mocks/Unity/InputInfo/CMakeLists.txt+1−1 tests/mocks/Unity/Launcher/CMakeLists.txt+1−1 tests/mocks/Unity/Launcher/MockAppDrawerModel.cpp+3−27 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/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+286 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/plugins/Unity/Launcher/xdgwatcher.h → tests/mocks/Unity/fake_valueslidervalues.h+13−16 tests/mocks/Unity/qmldir+3 tests/mocks/Utils/CMakeLists.txt+3−4 tests/mocks/Wizard/CMakeLists.txt+2−2 tests/mocks/Wizard/MockSystem.cpp+4−19 tests/mocks/Wizard/MockSystem.h+1−11 tests/mocks/Wizard/mockplugin.cpp−2 tests/mocks/liblightdm/CMakeLists.txt+1−1 tests/mocks/liblightdm/MockUsersModel.cpp−1 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+34−6 tests/plugins/CMakeLists.txt+3−1 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+2−1 tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt+1−1 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+5−18 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+2−4 tests/plugins/Ubuntu/Gestures/GestureTest.cpp+1−10 tests/plugins/Ubuntu/Gestures/tst_TouchGate.cpp+2−11 tests/plugins/Ubuntu/Gestures/tst_TouchGestureArea.cpp−30 tests/plugins/Unity/Indicators/CMakeLists.txt+1−1 tests/plugins/Unity/Launcher/CMakeLists.txt+1−36 tests/plugins/Unity/Launcher/appdrawermodeltest.cpp−68 tests/plugins/Unity/Launcher/launchermodeltest.cpp−1 tests/plugins/Unity/Launcher/ualwrapper.cpp−58 tests/plugins/Unity/Launcher/ualwrapper.h−55 tests/plugins/Unity/Session/CMakeLists.txt+2−2 tests/plugins/Utils/CMakeLists.txt+4−2 tests/plugins/Utils/DeviceConfigParserTest.cpp−3 tests/plugins/Utils/ModelTest.cpp+1−2 tests/plugins/Utils/WindowStateStorageTest.cpp+1−49 tests/plugins/WindowManager/CMakeLists.txt+2−4 tests/plugins/WindowManager/UnityApplicationMocks.h−1 tests/plugins/WindowManager/tst_TopLevelWindowModel.cpp−63 tests/plugins/Wizard/CMakeLists.txt+2−2 tests/qmltests/ApplicationMenuDataLoader.qml+1−1 tests/qmltests/ApplicationMenus/tst_MenuBar.qml+18−46 tests/qmltests/ApplicationMenus/tst_MenuPopup.qml+9−10 tests/qmltests/CMakeLists.txt+51−5 tests/qmltests/Components/CMakeLists.txt+4−8 tests/qmltests/Components/tst_Carousel.qml+292 tests/qmltests/Components/tst_Dialogs.qml+1 tests/qmltests/Components/tst_DragHandle.cpp+2−19 tests/qmltests/Components/tst_DraggingArea.qml+6−6 tests/qmltests/Components/tst_Lockscreen.qml+9−11 tests/qmltests/Components/tst_MediaServices.qml+4−5 tests/qmltests/Components/tst_PhysicalKeysMapper.qml+6−7 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+18−104 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+648 tests/qmltests/Dash/tst_DashContent.qml+730 tests/qmltests/Dash/tst_DashPageHeader.qml+357 tests/qmltests/Dash/tst_DashShell.qml+84 tests/qmltests/Dash/tst_GenericScopeView.qml+706 tests/qmltests/Dash/tst_PageHeader/logo-ubuntu-orange.svg+60 tests/qmltests/Dash/tst_PreviewView.qml+122 tests/qmltests/Greeter/TestView.qml+1−9 tests/qmltests/Greeter/tst_Greeter.qml+24−19 tests/qmltests/Greeter/tst_GreeterView.qml−1366 tests/qmltests/Greeter/tst_NarrowView.qml+566 tests/qmltests/Greeter/tst_WideView.qml+765 tests/qmltests/Launcher/tst_Drawer.qml+51−200 tests/qmltests/Launcher/tst_Launcher.qml+83−167 tests/qmltests/Notifications/tst_Notifications.qml+10−16 tests/qmltests/Notifications/tst_OptionToggle.qml+6−12 tests/qmltests/Notifications/tst_SwipeToAct.qml+3−10 tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+3−3 tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml+79−33 tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qml+8−168 tests/qmltests/Panel/PanelUI.qml−286 tests/qmltests/Panel/tst_ActiveCallHint.qml+9−14 tests/qmltests/Panel/tst_MenuContent.qml+2−2 tests/qmltests/Panel/tst_Panel.qml+240−58 tests/qmltests/Panel/tst_PanelItemRow.qml+2−2 tests/qmltests/Panel/tst_PanelMenu.qml+22−61 tests/qmltests/Panel/tst_PanelMenuPage.qml+1−1 tests/qmltests/Panel/tst_PanelSmallScreen.qml−133 tests/qmltests/Stage/ApplicationCheckBox.qml+6−6 tests/qmltests/Stage/tst_ApplicationWindow.qml+2−3 tests/qmltests/Stage/tst_DesktopStage.qml+11−22 tests/qmltests/Stage/tst_PhoneStage.qml+60−87 tests/qmltests/Stage/tst_QMLTopLevelWindowModel.qml−191 tests/qmltests/Stage/tst_SpreadDelegate.qml+423 tests/qmltests/Stage/tst_SurfaceContainer.qml+8−9 tests/qmltests/Stage/tst_TabletStage.qml+151−112 tests/qmltests/Stage/tst_WindowDecoration.qml+3−3 tests/qmltests/Stage/tst_WindowResizeArea.qml+3−4 tests/qmltests/Tutorial/tst_Tutorial.qml+189−187 tests/qmltests/Wizard/tst_Wizard.qml+136−100 tests/qmltests/tst_OrientedShell.qml+266−312 tests/qmltests/tst_Shell.qml+543−635 tests/qmltests/tst_ShellWithPin.qml+79−96 tests/uqmlscene/CMakeLists.txt+1−1 tests/utils/modules/Unity/Test/CMakeLists.txt+4−2 tests/utils/modules/Unity/Test/MouseTouchEmulationCheckbox.qml+1−1 tests/utils/modules/Unity/Test/StageTestCase.qml+18−14 tests/utils/modules/Unity/Test/TouchEventSequenceWrapper.cpp+1−10 tests/utils/modules/Unity/Test/UnityTestCase.qml+2−2 tools/CMakeLists.txt+1 tools/indicatorsclient/CMakeLists.txt+1−1 tools/menutool/CMakeLists.txt+1−1 tools/scopetool/CMakeLists.txt+12 tools/scopetool/registry-tracker.cpp+146 tools/scopetool/registry-tracker.h+49 tools/scopetool/scopetool.cpp+116
.bazaar/Makefilenew file+6
@@ -0,0 +1,6 @@
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.pynew file+51
@@ -0,0 +1,51 @@
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.confnew file+2
@@ -0,0 +1,2 @@
1+[BUILDDEB]
2+split = True
.bzrignorenew file+7
@@ -0,0 +1,7 @@
1+# default build dir
2+/builddir
3+# QtCreator project files
4+/*.user
5+# Eclipse project files
6+.settings
7+message.txt
.gitignore−7
@@ -2,15 +2,8 @@
22/builddir
33# QtCreator project files
44/*.user
5−*.qmlc
6−*.jsc
75# Eclipse project files
86/.project
97/.cproject
108/.settings
119/.pydevproject
12−# KDevelop project Files
13−/.kdev4/
14−/build/
15−/*.kdev4
16−.clickable/
CMakeLists.txt+4−5
@@ -70,18 +70,15 @@ find_package(Qt5DBus 5.6 REQUIRED)
7070find_package(Qt5Concurrent 5.6 REQUIRED)
7171find_package(Qt5Sql 5.6 REQUIRED)
7272find_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)
7673
7774pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=27)
7875pkg_check_modules(GEONAMES REQUIRED geonames>=0.2)
7976pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
8077pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
81−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=13)
78+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=12)
8279pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
8380pkg_check_modules(GD3 REQUIRED gnome-desktop-3.0)
84−pkg_check_modules(UAL REQUIRED ubuntu-app-launch-2)
81+pkg_check_modules(UAL REQUIRED ubuntu-app-launch-3)
8582pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
8683pkg_check_modules(QTDBUSTEST REQUIRED
8784 libqtdbustest-1
@@ -148,6 +145,8 @@ include(autopilot)
148145declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)
149146
150147set(SHELL_APP unity8)
148+set(DASH_APP unity8-dash)
149+set(SCOPE_TOOL unity-scope-tool)
151150set(INDICATORS_CLIENT_APP indicators-client)
152151set(GREETER_APP unity8-greeter)
153152set(MOCK_INDICATOR_SERVICE_APP unity-mock-indicator-service)
Jenkinsfiledeleted−2
@@ -1,2 +0,0 @@
1−@Library('ubports-build-tools') _
2−buildAndProvideDebianPackage()
README.mddeleted−31
@@ -1,31 +0,0 @@
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.
clickable.yamldeleted−153
@@ -1,153 +0,0 @@
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.cmakenew file+148
@@ -0,0 +1,148 @@
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+1−1
@@ -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 QT_QPA_PLATFORM=xcb QML2_IMPORT_PATH=${imports} LD_PRELOAD=/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/mesa/libGL.so.1 ${QMLTEST_ENVIRONMENT}
204+ ENVIRONMENT QML2_IMPORT_PATH=${imports} LD_PRELOAD=/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/mesa/libGL.so.1 ${QMLTEST_ENVIRONMENT}
205205 TARGETS ${xvfb_targets}
206206 )
207207 endif()
data/CMakeLists.txt+9−1
@@ -1,11 +1,13 @@
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)
34configure_file(${INDICATORS_CLIENT_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop @ONLY)
45configure_file(${GREETER_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${GREETER_APP}.desktop @ONLY)
56
67# install desktop files
78install(FILES
89 ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
10+ ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
911 ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop
1012 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
1113 )
@@ -20,8 +22,14 @@ install(FILES
2022 DESTINATION ${CMAKE_INSTALL_DATADIR}/lightdm/lightdm.conf.d
2123 )
2224
25+# install dash icon
26+install(FILES
27+ ${CMAKE_CURRENT_SOURCE_DIR}/${DASH_APP}.png
28+ DESTINATION ${SHELL_APP_DIR}/Dash/
29+ )
30+
2331add_custom_target(pkgversion ALL COMMAND dpkg-parsechangelog -l${CMAKE_SOURCE_DIR}/debian/changelog --show-field version > ${CMAKE_CURRENT_BINARY_DIR}/version)
2432
2533install(FILES com.canonical.Unity8.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
26−install(FILES com.canonical.Unity.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
34+install(FILES unity8-dash.url-dispatcher DESTINATION ${CMAKE_INSTALL_DATADIR}/url-dispatcher/urls)
2735install(FILES ${CMAKE_CURRENT_BINARY_DIR}/version DESTINATION ${CMAKE_INSTALL_LOCALSTATEDIR}/lib/unity8)
data/com.canonical.Unity.gschema.xmldeleted−255
@@ -1,255 +0,0 @@
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+7−2
@@ -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="u" name="edge-barrier-sensitivity">
14+ <key type="y" 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>
@@ -43,13 +43,18 @@
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>
4651 <key type="b" name="enable-indicator-menu">
4752 <default>true</default>
4853 <summary>Enable or disable the indicator pull down menus</summary>
4954 <description>Toggle the availability of the indicator pull down menus</description>
5055 </key>
5156 <key type="s" name="appstore-uri">
52− <default>'appid://openstore.openstore-team/openstore/current-user-version'</default>
57+ <default>'scope://com.canonical.scopes.clickstore'</default>
5358 <summary>The uri to the app store</summary>
5459 <description>This will be used whenever the user triggers an action to open the app store.</description>
5560 </key>
data/test.sensorsdeleted−12
@@ -1,12 +0,0 @@
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.confnew file+25
@@ -0,0 +1,25 @@
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.innew file+9
@@ -0,0 +1,9 @@
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.pngnew file

Binary file not shown.

data/unity8-dash.svgnew file+326
@@ -0,0 +1,326 @@
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-dispatchernew file+6
@@ -0,0 +1,6 @@
1+[
2+ {
3+ "protocol": "scope"
4+ }
5+]
6+
data/unity8.conf−17
@@ -2,7 +2,6 @@ description "Unity Shell v8"
22author "Ricardo Mendoza <ricmm@ubuntu.com>"
33
44emits indicator-services-start
5−emits indicator-services-end
65
76start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=unity8-mir) or (xsession SESSION=unity8)) and started dbus
87stop on desktop-end
@@ -59,15 +58,6 @@ pre-start script
5958
6059 initctl set-env --global MIR_SERVER_PROMPT_FILE=1
6160
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
70−
7161 if [ "$XDG_SESSION_DESKTOP" = "ubuntu-touch" ]; then
7262 # On Ubuntu Touch, we currently use a trick where we auto-login the
7363 # user without a LightDM greeter at all. In this case, we want to
@@ -77,12 +67,6 @@ pre-start script
7767 else
7868 initctl set-env MODE=full-shell
7969 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
8670end script
8771
8872exec ${BINARY:-unity8} --mode=$MODE $ARGS
@@ -95,5 +79,4 @@ post-stop script
9579 initctl set-env --global MIR_SOCKET=$UNITY_MIR_SOCKET
9680 initctl unset-env --global MIR_SERVER_PROMPT_FILE
9781 initctl emit application-end
98− initctl emit indicator-services-end
9982end script
debian/changelog+20−72
@@ -1,50 +1,3 @@
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−
481unity8 (8.15+17.04.20170328.3-0ubuntu1) zesty; urgency=medium
492
503 [ Albert Astals Cid ]
@@ -1224,7 +1177,7 @@ unity8 (8.12+16.04.20160330-0ubuntu1) xenial; urgency=medium
12241177unity8 (8.12+16.04.20160323.2-0ubuntu1) xenial; urgency=medium
12251178
12261179 [ Michael Terry ]
1227− *
1180+ *
12281181 * Fix setting OSK layout in OOBE wizard
12291182 * Stop the left edge tutorial from being shown when the bottom edge
12301183 tutorial wants to be shown after receiving a call.
@@ -3936,7 +3889,7 @@ unity8 (8.00+14.10.20140729-0ubuntu1) utopic; urgency=medium
39363889 * Re-architecture unity8 to use the QtMirCompositor library so that
39373890 the Qt scenegraph renderer is used as the Mir compositor, and
39383891 application surfaces are added to the QML scene as items.
3939−
3892+
39403893 [ Michael Zanetti ]
39413894 * Port phone right-edge spread code to use QtCompositor
39423895 * Add right-edge spread animation for tablet
@@ -4210,8 +4163,8 @@ unity8 (7.90+14.10.20140703.1-0ubuntu1) utopic; urgency=low
42104163
42114164unity8 (7.90+14.10.20140701.2-0ubuntu2) utopic; urgency=medium
42124165
4213− * debian/control:
4214− list qtdeclarative5-ubuntu-ui-toolkit-plugin-gles as an alternative
4166+ * debian/control:
4167+ list qtdeclarative5-ubuntu-ui-toolkit-plugin-gles as an alternative
42154168 choice, since provides are not versionned, should restore installability
42164169 on amd64 and i386
42174170
@@ -7313,7 +7266,7 @@ unity8 (7.81.2) saucy; urgency=low
73137266 [ Michał Sawicz ]
73147267 * Fix icons in ApplicationsFilterGrid.qml.
73157268 * Support flipped image in run_on_device.
7316−
7269+
73177270 [ Michael Zanetti ]
73187271 * Don't clear lockscreen when it's fading out.
73197272 * Reworked Launcher folding.
@@ -7398,7 +7351,7 @@ qml-phone-shell (1.79) raring; urgency=low
73987351
73997352 [ Michael Terry ]
74007353 * Make greeter look like the desktop one
7401−
7354+
74027355 [ Gerry Boland ]
74037356 * Fix a bug where a minimized app gets focus after closing another app
74047357 * Applied a workaround to reduce flickering when launching apps
@@ -7414,7 +7367,7 @@ qml-phone-shell (1.79) raring; urgency=low
74147367qml-phone-shell (1.78) raring; urgency=low
74157368
74167369 [ Sergio Schvezov ]
7417− * Replacing the music and ski safari mock apps with calendar and weather in
7370+ * Replacing the music and ski safari mock apps with calendar and weather in
74187371 the launcher (LP: #1178262).
74197372
74207373 [ Daniel d'Andrada ]
@@ -7456,7 +7409,7 @@ qml-phone-shell (1.77) raring; urgency=low
74567409 [ Mathieu Trudel-Lapierre ]
74577410 * debian/control:
74587411 - Drop indicators-client-plugin* Depends for qml-phone-shell to Recommends.
7459− - Add/update Vcs-Browser, Vcs-Bzr and add a notice to uploaders.
7412+ - Add/update Vcs-Browser, Vcs-Bzr and add a notice to uploaders.
74607413 * debian/copyright: fix syntax.
74617414
74627415 [ Michał Sawicz ]
@@ -7466,7 +7419,7 @@ qml-phone-shell (1.77) raring; urgency=low
74667419 * Renamed Media player files to match with new application name.
74677420
74687421 [ Daniel d'Andrada ]
7469− * New: DirectionalDragArea component. An area that detects axis-aligned
7422+ * New: DirectionalDragArea component. An area that detects axis-aligned
74707423 single-finger drag gestures.
74717424 * Make it possible to send touch events from within QML test code.
74727425
@@ -7903,7 +7856,7 @@ qml-phone-shell (1.39) quantal; urgency=low
79037856
79047857qml-phone-shell (1.38) quantal; urgency=low
79057858
7906− * fix launching of notepad
7859+ * fix launching of notepad
79077860
79087861 -- Bill Filler <bill.filler@canonical.com> Fri, 01 Feb 2013 03:21:29 -0500
79097862
@@ -7916,14 +7869,14 @@ qml-phone-shell (1.37) quantal; urgency=low
79167869
79177870qml-phone-shell (1.36) quantal; urgency=low
79187871
7919− * launch real notepad app
7872+ * launch real notepad app
79207873 * fix launching of mock apps
79217874
79227875 -- Bill Filler <bill.filler@canonical.com> Thu, 31 Jan 2013 21:36:05 -0500
79237876
79247877qml-phone-shell (1.35) quantal; urgency=low
79257878
7926− * integrate ubuntu-browser instead of snowshoe
7879+ * integrate ubuntu-browser instead of snowshoe
79277880
79287881 -- Bill Filler <bill.filler@canonical.com> Thu, 31 Jan 2013 17:33:37 -0500
79297882
@@ -8007,7 +7960,7 @@ qml-phone-shell (1.22) quantal; urgency=low
80077960
80087961qml-phone-shell (1.21) quantal; urgency=low
80097962
8010− * New release with fullscreen launcher fixes
7963+ * New release with fullscreen launcher fixes
80117964
80127965 -- Bill Filler <bill.filler@canonical.com> Fri, 07 Dec 2012 09:36:37 +0000
80137966
@@ -8019,7 +7972,7 @@ qml-phone-shell (1.20) quantal; urgency=low
80197972
80207973qml-phone-shell (1.19) quantal; urgency=low
80217974
8022− * enable multi-threaded render for apps
7975+ * enable multi-threaded render for apps
80237976
80247977 -- Bill Filler <bill.filler@canonical.com> Wed, 05 Dec 2012 17:34:09 +0000
80257978
@@ -8027,7 +7980,7 @@ qml-phone-shell (1.18) quantal; urgency=low
80277980
80287981 [ Bill Filler ]
80297982 * update launcher to use wk2-render (chromeless webkit) for facebook
8030− and twitter
7983+ and twitter
80317984
80327985 -- Florian Boucault <florian.boucault@canonical.com> Wed, 05 Dec 2012 12:20:50 +0000
80337986
@@ -8039,7 +7992,7 @@ qml-phone-shell (1.17) quantal; urgency=low
80397992
80407993qml-phone-shell (1.16) quantal; urgency=low
80417994
8042− * fix to launch new gallery with correct args
7995+ * fix to launch new gallery with correct args
80437996
80447997 -- Bill Filler <bill.filler@canonical.com> Thu, 29 Nov 2012 17:04:36 -0500
80457998
@@ -8101,7 +8054,7 @@ qml-phone-shell (1.2) quantal; urgency=low
81018054
81028055qml-phone-shell (1.1) quantal; urgency=low
81038056
8104− * comment out console.log() to prevent crash
8057+ * comment out console.log() to prevent crash
81058058
81068059 -- Bill Filler <bill.filler@canonical.com> Sun, 28 Oct 2012 22:18:36 +0100
81078060
@@ -8129,19 +8082,19 @@ qml-phone-shell (0.7) quantal; urgency=low
81298082 * qml-phone-shell.conf: better setup of env vars and launch
81308083 via dbus-luanch to properly setup session bus
81318084 * shellapplication.cpp: don't setup custom env before launching
8132− processes
8085+ processes
81338086
81348087 -- Bill Filler <bill.filler@canonical.com> Sun, 21 Oct 2012 11:32:42 +0200
81358088
81368089qml-phone-shell (0.6) quantal; urgency=low
81378090
8138− * added additional Android env vars to upstart script
8091+ * added additional Android env vars to upstart script
81398092
81408093 -- Bill Filler <bill.filler@canonical.com> Fri, 19 Oct 2012 09:35:25 -0400
81418094
81428095qml-phone-shell (0.5) quantal; urgency=low
81438096
8144− * added support to launch telephony-app
8097+ * added support to launch telephony-app
81458098
81468099 -- Bill Filler <bill.filler@canonical.com> Thu, 18 Oct 2012 13:45:25 -0400
81478100
@@ -8168,8 +8121,3 @@ qml-phone-shell (0.1) quantal; urgency=low
81688121 * Initial release
81698122
81708123 -- 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+198−215
@@ -2,224 +2,225 @@ Source: unity8
22Section: x11
33Priority: optional
44Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
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,
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.12),
32+ libqtdbusmock1-dev (>= 0.7),
33+ libqtdbustest1-dev,
34+ libqt5svg5-dev,
35+ libqt5xmlpatterns5-dev,
36+ libsystemsettings-dev,
37+ libubuntu-app-launch3-dev,
38+ libubuntu-download-manager-common-dev,
39+ libubuntugestures5-dev (>= 1.3.2030),
40+ libubuntugestures5-private-dev (>= 1.3.2030),
41+ libudev-dev,
42+ libudm-common-dev,
43+ libunity-api-dev (>= 8.6),
44+ libusermetricsoutput1-dev,
45+# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
46+ libx11-dev[!arm64 !armhf],
47+ libxcb1-dev[!arm64 !armhf],
48+ libxi-dev[!arm64 !armhf],
49+# End of X11 libs
50+ pkg-config,
51+ python3-all:any,
52+ python3-setuptools,
53+ qtdbustest-runner,
54+ qml-module-qt-labs-folderlistmodel,
55+ qml-module-qt-labs-settings,
56+ qml-module-qtqml-statemachine,
57+ qml-module-qtmultimedia (>= 5.6),
58+ qml-module-qtquick-layouts,
59+ qml-module-qtquick-xmllistmodel,
60+ qml-module-qtquick2,
61+ qml-module-qtsysteminfo,
62+ qml-module-qttest,
63+ qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
64+ qml-module-ubuntu-web,
65+ qt5-default,
66+ qtbase5-dev (>= 5.6),
67+ qtbase5-dev-tools,
68+ qtbase5-private-dev (>= 5.6),
69+ qtdeclarative5-dev (>= 5.6),
70+ qtdeclarative5-dev-tools,
71+ qtdeclarative5-private-dev (>= 5.6),
72+ qtdeclarative5-ubuntu-content1,
73+ qtdeclarative5-ubuntu-settings-components (>= 0.11),
74+ ttf-ubuntu-font-family,
75+ xvfb,
7676Standards-Version: 3.9.4
77−Homepage: https://github.com/ubports/unity8
78−Vcs-Git: https://github.com/ubports/unity8
77+Homepage: http://launchpad.net/unity
78+# If you aren't a member of ~unity-team but need to upload
79+# packaging changes, just go ahead. ~unity-team will notice
80+# and sync up the code again.
81+Vcs-Bzr: https://code.launchpad.net/unity8
82+Vcs-Browser: https://bazaar.launchpad.net/~unity-team/unity8/trunk
7983XS-Testsuite: autopkgtest
8084X-Ubuntu-Use-Langpack: yes
8185
8286Package: indicators-client
8387Architecture: any
84−Depends:
85− qmenumodel-qml (>= 0.2.11),
86− qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
87− unity8 (= ${binary:Version}),
88− ${misc:Depends},
89− ${shlibs:Depends},
88+Depends: qmenumodel-qml (>= 0.2.11),
89+ qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
90+ unity8 (= ${binary:Version}),
91+ ${misc:Depends},
92+ ${shlibs:Depends},
9093Description: Indicators client test application
9194 This package contains the client application for indicators used by autopilot
9295
9396Package: unity8-greeter
9497Architecture: any
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,
98+Depends: unity8 (= ${binary:Version}),
99+ unity-system-compositor,
100+ ${misc:Depends},
101+ ${shlibs:Depends}
102+Recommends: lightdm
103+Provides: lightdm-greeter
104104Description: The Unity8 Greeter
105105 The Unity 8 greeter is the primary login greeter for Ubuntu devices.
106106
107+Package: unity-scope-tool
108+Architecture: any
109+Depends: unity8-common (= ${source:Version}),
110+ unity8-private (= ${binary:Version}),
111+ ${misc:Depends},
112+ ${shlibs:Depends},
113+# We do call pkg-config libunity-scopes from the code
114+ pkg-config,
115+ libunity-scopes-dev,
116+Description: Development tool for Unity scopes
117+ This package contains the development tool for new generation Unity scopes, based
118+ on Unity8.
119+
107120Package: unity8
108121Architecture: any
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,
122+Provides: indicator-renderer,
123+Depends: dmz-cursor-theme,
124+ gsettings-desktop-schemas,
125+ libcap2-bin,
126+ libglib2.0-bin,
127+ qmenumodel-qml (>= 0.2.11),
128+ qml-module-biometryd,
129+ qml-module-qt-labs-folderlistmodel,
130+ qml-module-qt-labs-settings,
131+ qml-module-qtqml-statemachine,
132+ qml-module-qtquick-xmllistmodel,
133+ qml-module-qtsysteminfo,
134+ qml-module-ubuntu-web,
135+ qtdeclarative5-qtmir-plugin (>= 0.4.8),
136+ qtdeclarative5-ubuntu-telephony0.1,
137+ ubuntu-system-settings (>= 0.4),
138+ unity-launcher-impl-12,
139+ unity8-common (= ${source:Version}),
140+ unity8-private (= ${binary:Version}),
141+ unity8-private | unity-launcher-impl,
142+ ${misc:Depends},
143+ ${shlibs:Depends},
144+Recommends: indicator-keyboard,
145+ indicator-session,
146+ unity-greeter-session-broadcast,
147+Suggests: unity-scope-mediascanner2,
148+Breaks: indicator-network (<< 0.5.1+14.10.20141014),
149+ ubuntu-touch-session (<< 0.107),
150+ unity8-greeter (<< 7.89),
151+ ubuntu-keyboard (<< 0.100),
152+Replaces: ubuntu-touch-session (<< 0.82~),
153+ unity8-greeter (<< 7.89),
154+Conflicts: ubuntu-system-settings-wizard,
148155Description: Unity 8 shell
149156 The Unity 8 shell is the primary user interface for Ubuntu devices.
150157
151158Package: unity8-common
152159Architecture: all
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),
160+Depends: qml-module-qtquick-layouts,
161+ qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
162+ qml-module-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
163+ qtdeclarative5-ubuntu-settings-components (>= 0.11),
164+ qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
165+ qttranslations5-l10n,
166+ ubuntu-thumbnailer-impl-0,
167+ ubuntu-wallpapers,
168+ unity-application-impl-27,
169+ unity-notifications-impl-3,
170+ unity-plugin-scopes | unity-scopes-impl,
171+ unity-scopes-impl-12,
172+ unity8-tests | unity-application-impl,
173+ ${misc:Depends},
174+Breaks: unity8 (<< 7.86),
175+Replaces: unity8 (<< 7.86),
170176Description: Unity 8 shell (common files)
171177 The Unity 8 shell is the primary user interface for Ubuntu devices.
172178 .
173− This package contains the QML, graphics and locale files for unity8.
179+ This package contains the QML, graphics and locale files shared between
180+ unity8 and unity-scope-tool.
174181
175182Package: unity8-autopilot
176183Architecture: all
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},
184+Depends: autopilot-qt5 (>= 1.4),
185+ gir1.2-glib-2.0,
186+ gir1.2-notify-0.7,
187+ libqt5test5,
188+ libqt5widgets5,
189+ ofono-phonesim,
190+ python3-autopilot,
191+ python3-evdev,
192+ python3-fixtures,
193+ python3-gi,
194+ qttestability-autopilot (>= 1.4),
195+ ubuntu-ui-toolkit-autopilot (>= 1.3.2030),
196+ unity8 (= ${source:Version}),
197+ unity8-tests (= ${source:Version}),
198+ url-dispatcher-tools,
199+ xvfb,
200+ ${misc:Depends},
201+ ${python3:Depends},
196202Description: Test package for Unity 8 shell
197203 Autopilot tests for the unity8 package
198204
199205Package: unity8-tests
200206Architecture: any
201207Multi-Arch: same
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,
208+Pre-Depends: ${misc:Pre-Depends},
209+Depends: dbus-test-runner,
210+ parallel,
211+ qtdbustest-runner,
212+ qt5-default,
213+ qtdeclarative5-dev-tools,
214+ unity8 (= ${source:Version}),
215+ xvfb,
216+ ${misc:Depends},
217+ ${shlibs:Depends},
218+Provides: unity-application-impl,
219+ unity-application-impl-27,
220+ unity8-fake-env,
221+Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1),
222+ unity8-fake-env,
223+Conflicts: unity8-fake-env,
223224Description: Scripts and mocks for running Unity 8 shell tests
224225 Provides fake implementations of some QML modules used by Unity 8 shell
225226 (e.g Ubuntu.Application) so that you can run it in a sandboxed environment
@@ -228,45 +229,27 @@ Description: Scripts and mocks for running Unity 8 shell tests
228229Package: unity8-private
229230Architecture: any
230231Multi-Arch: same
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,
232+Pre-Depends: ${misc:Pre-Depends},
233+Depends: accountsservice-ubuntu-schemas (>= 0.0.7),
234+ gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
235+ libhardware2,
236+ unity-schemas (>= 7.3.1+14.10.20140915),
237+ qtdeclarative5-gsettings1.0,
238+ qml-module-qtmultimedia,
239+ ${misc:Depends},
240+ ${shlibs:Depends},
241+Provides: unity-launcher-impl,
242+ unity-launcher-impl-12,
245243Description: Unity 8 private libs
246244 The Unity 8 shell is the primary user interface for Ubuntu devices.
247245 .
248246 This package contains the private libraries for QML and other components
249247 only used by the shell.
250248
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−
265249Package: unity8-doc
266250Section: doc
267251Architecture: all
268252Multi-Arch: foreign
269−Depends:
270− ${misc:Depends},
253+Depends: ${misc:Depends},
271254Description: Documentation for Unity8
272255 The Unity 8 shell is the primary user interface for Ubuntu devices. (documentation)
debian/rules+5−19
@@ -7,12 +7,6 @@ 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
1610
1711%:
1812 dh $@ --parallel --fail-missing --with python3
@@ -24,19 +18,7 @@ override_dh_auto_configure:
2418
2519override_dh_auto_build:
2620 # doc is not a default target
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
21+ dh_auto_build -- all doc
4022
4123override_dh_install:
4224 # install autopilot tests
@@ -47,6 +29,10 @@ override_dh_install:
4729 cd $(CURDIR)
4830 dh_install -X'*.pyc' --fail-missing
4931
32+override_dh_installdeb:
33+ dh_apparmor --profile-name=usr.bin.unity8-dash -punity8-dash
34+ dh_installdeb
35+
5036# use private lib directories
5137override_dh_makeshlibs:
5238 dh_makeshlibs -Nunity8-private -Nunity8-tests
debian/source/formatnew file+1
@@ -0,0 +1 @@
1+1.0
debian/tests/control+3−5
@@ -1,11 +1,9 @@
11Tests: qmluitests.sh
22Restrictions: allow-stderr
3−Depends:
4− dpkg-dev,
5− unity8-tests,
3+Depends: dpkg-dev,
4+ unity8-tests,
65
76Tests: autopilot.sh
87Restrictions: allow-stderr,
98 isolation-machine,
10−Depends:
11− unity8-autopilot,
9+Depends: unity8-autopilot,
debian/unity-scope-tool.installnew file+2
@@ -0,0 +1,2 @@
1+usr/bin/unity-scope-tool
2+usr/share/unity8/ScopeTool.qml
debian/unity8-common.install+2
@@ -1,5 +1,7 @@
1+usr/share/glib-2.0/schemas
12usr/share/locale
23usr/share/unity8/Components
4+usr/share/unity8/Dash
35usr/share/unity8/Notifications
46usr/share/unity8/graphics
57var/lib/polkit-1/localauthority/10-vendor.d
debian/unity8-greeter.install+1−1
@@ -1,5 +1,5 @@
1−data/unity8-greeter-init.conf usr/share/upstart/sessions/
21data/unity8-greeter-wrapper usr/bin/
2+data/unity8-greeter-init.conf usr/share/upstart/sessions/
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+3−1
@@ -1,16 +1,18 @@
11usr/lib/*/libunity8-private.*
22usr/lib/*/unity8/qml/AccountsService
33usr/lib/*/unity8/qml/Cursor
4+usr/lib/*/unity8/qml/Dash
45usr/lib/*/unity8/qml/GlobalShortcut
56usr/lib/*/unity8/qml/Greeter
7+usr/lib/*/unity8/qml/ImageCache
68usr/lib/*/unity8/qml/LightDM
79usr/lib/*/unity8/qml/Lights
810usr/lib/*/unity8/qml/Powerd
911usr/lib/*/unity8/qml/ScreenshotDirectory
1012usr/lib/*/unity8/qml/SessionBroadcast
11−usr/lib/*/unity8/qml/UInput
1213usr/lib/*/unity8/qml/Ubuntu
1314usr/lib/*/unity8/qml/Unity
15+usr/lib/*/unity8/qml/UInput
1416usr/lib/*/unity8/qml/Utils
1517usr/lib/*/unity8/qml/WindowManager
1618usr/lib/*/unity8/qml/Wizard
debian/unity8-schemas.installdeleted−1
@@ -1 +0,0 @@
1−usr/share/glib-2.0/schemas
debian/unity8-tests.install+1
@@ -2,6 +2,7 @@ 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
56usr/lib/*/unity8/qml/utils
67usr/lib/*/unity8/tests
78usr/lib/*/unity8/uqmlscene
debian/unity8.install+10−6
@@ -1,19 +1,23 @@
1−data/devices.conf etc/ubuntu/
2−data/test.sensors etc/ubuntusensors/
1+debian/usr.bin.unity8-dash etc/apparmor.d
2+var/lib/unity8/version
3+data/unity8-dash.conf usr/share/upstart/sessions/
34data/unity8-filewatcher.conf usr/share/upstart/sessions/
45data/unity8.conf usr/share/upstart/sessions/
6+data/devices.conf etc/ubuntu/
57usr/bin/unity8
8+usr/bin/unity8-dash
9+usr/share/applications/unity8-dash.desktop
610usr/share/applications/unity8.desktop
711usr/share/unity8/ApplicationMenus
8−usr/share/unity8/DeviceConfiguration.qml
9−usr/share/unity8/DisabledScreenNotice.qml
1012usr/share/unity8/Greeter
1113usr/share/unity8/Launcher
12−usr/share/unity8/OrientedShell.qml
1314usr/share/unity8/Panel
1415usr/share/unity8/Rotation
16+usr/share/unity8/DeviceConfiguration.qml
17+usr/share/unity8/OrientedShell.qml
18+usr/share/unity8/DisabledScreenNotice.qml
1519usr/share/unity8/Shell.qml
1620usr/share/unity8/Stage
1721usr/share/unity8/Tutorial
1822usr/share/unity8/Wizard
19−var/lib/unity8/version
23+usr/share/url-dispatcher/urls/unity8-dash.url-dispatcher
debian/usr.bin.unity8-dashnew file+21
@@ -0,0 +1,21 @@
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+30−1
@@ -25,6 +25,7 @@
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")
2829#define IFACE_UBUNTU_INPUT QStringLiteral("com.ubuntu.AccountsService.Input")
2930#define IFACE_UBUNTU_SECURITY QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy")
3031#define IFACE_UBUNTU_SECURITY_OLD QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy")
@@ -32,7 +33,7 @@
3233#define IFACE_UNITY_PRIVATE QStringLiteral("com.canonical.unity.AccountsService.Private")
3334
3435#define PROP_BACKGROUND_FILE QStringLiteral("BackgroundFile")
35−#define PROP_DEMO_EDGES QStringLiteral("DemoEdges2")
36+#define PROP_DEMO_EDGES QStringLiteral("demo-edges")
3637#define PROP_DEMO_EDGES_COMPLETED QStringLiteral("DemoEdgesCompleted")
3738#define PROP_EMAIL QStringLiteral("Email")
3839#define PROP_ENABLE_FINGERPRINT_IDENTIFICATION QStringLiteral("EnableFingerprintIdentification")
@@ -92,6 +93,8 @@ AccountsService::AccountsService(QObject* parent, const QString &user)
9293 registerProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, QStringLiteral("emailChanged"));
9394 registerProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, QStringLiteral("realNameChanged"));
9495 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"));
9598 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION, QStringLiteral("enableFingerprintIdentificationChanged"));
9699 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral("enableLauncherWhileLockedChanged"));
97100 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral("enableIndicatorsWhileLockedChanged"));
@@ -213,6 +216,32 @@ AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() cons
213216 return (PasswordDisplayHint)value.toInt();
214217}
215218
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+
216245QString AccountsService::realName() const
217246{
218247 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME);
plugins/AccountsService/AccountsService.h+16
@@ -66,6 +66,16 @@ 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)
6979 Q_PROPERTY(QString realName READ realName WRITE setRealName NOTIFY realNameChanged)
7080 Q_PROPERTY(QString email READ email WRITE setEmail NOTIFY emailChanged)
7181 Q_PROPERTY(QStringList keymaps READ keymaps WRITE setKeymaps NOTIFY keymapsChanged)
@@ -96,6 +106,10 @@ public:
96106 void setFailedLogins(uint failedLogins);
97107 uint failedFingerprintLogins() const;
98108 void setFailedFingerprintLogins(uint failedFingerprintLogins);
109+ bool hereEnabled() const;
110+ void setHereEnabled(bool enabled);
111+ QString hereLicensePath() const;
112+ bool hereLicensePathValid() const;
99113 QString realName() const;
100114 void setRealName(const QString &realName);
101115 QString email() const;
@@ -115,6 +129,8 @@ Q_SIGNALS:
115129 void passwordDisplayHintChanged();
116130 void failedLoginsChanged();
117131 void failedFingerprintLoginsChanged();
132+ void hereEnabledChanged();
133+ void hereLicensePathChanged();
118134 void realNameChanged();
119135 void emailChanged();
120136 void keymapsChanged();
plugins/AccountsService/CMakeLists.txt+2−1
@@ -7,8 +7,9 @@ add_library(AccountsService-qml MODULE
77 plugin.cpp
88 )
99
10+qt5_use_modules(AccountsService-qml DBus Qml)
11+
1012target_link_libraries(AccountsService-qml
11− Qt5::DBus Qt5::Qml
1213 ${GLIB_LIBRARIES}
1314 )
1415
plugins/AccountsService/com.canonical.unity.AccountsService.xml−6
@@ -9,17 +9,11 @@
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. -->
1312 <!-- Should have been named DemoEdges, sorry folks. -mterry -->
1413 <property name="demo-edges" type="b" access="readwrite">
1514 <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
1615 </property>
1716
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−
2317 <!-- List of tutorial pages that have been completed by the user -->
2418 <property name="DemoEdgesCompleted" type="as" access="readwrite">
2519 <annotation name="org.freedesktop.Accounts.DefaultValue" value="[]"/>
plugins/CMakeLists.txt+3−1
@@ -1,4 +1,4 @@
1−find_package(QmlPlugins)
1+include(QmlPlugins)
22
33# Set up and install a plugin for unity8.
44#
@@ -15,8 +15,10 @@ add_subdirectory(AccountsService)
1515add_subdirectory(Cursor)
1616add_subdirectory(GlobalShortcut)
1717add_subdirectory(Greeter)
18+add_subdirectory(ImageCache)
1819add_subdirectory(LightDM)
1920add_subdirectory(Lights)
21+add_subdirectory(Dash)
2022add_subdirectory(Powerd)
2123add_subdirectory(ScreenshotDirectory)
2224add_subdirectory(SessionBroadcast)
plugins/Cursor/CMakeLists.txt+2−1
@@ -26,7 +26,8 @@ add_library(Cursor-qml SHARED
2626target_link_libraries(Cursor-qml
2727 xcursorloader-static
2828 ${QT5PLATFORM_SUPPORT_LDFLAGS}
29− Qt5::Qml Qt5::Quick Qt5::Svg
3029)
3130
31+qt5_use_modules(Cursor-qml Qml Quick Svg)
32+
3233add_unity8_plugin(Cursor 1.1 Cursor TARGETS Cursor-qml)
plugins/Dash/AudioProgressBar.qmlnew file+54
@@ -0,0 +1,54 @@
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.txtnew file+47
@@ -0,0 +1,47 @@
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.qmlnew file+71
@@ -0,0 +1,71 @@
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.qmlnew file+59
@@ -0,0 +1,59 @@
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.jsnew file+999
@@ -0,0 +1,999 @@
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.qmlnew file+40
@@ -0,0 +1,40 @@
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.qmlnew file+94
@@ -0,0 +1,94 @@
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.qmlnew file+38
@@ -0,0 +1,38 @@
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.qmlnew file+120
@@ -0,0 +1,120 @@
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.qmlnew file+95
@@ -0,0 +1,95 @@
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.cppnew file+359
@@ -0,0 +1,359 @@
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.hnew file+128
@@ -0,0 +1,128 @@
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.pngnew file

Binary file not shown.

plugins/Dash/horizontaljournal.cppnew file+239
@@ -0,0 +1,239 @@
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.hnew file+63
@@ -0,0 +1,63 @@
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.cppnew file+1394
@@ -0,0 +1,1394 @@
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.hnew file+218
@@ -0,0 +1,218 @@
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.cppnew file+259
@@ -0,0 +1,259 @@
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.hnew file+91
@@ -0,0 +1,91 @@
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.cppnew file+70
@@ -0,0 +1,70 @@
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/Lights/HfdLights.h → plugins/Dash/plugin.hrenamed+8−17
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2021 UBports Foundation.
2+ * Copyright (C) 2012 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -13,30 +13,21 @@
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− * Author: Florian Leeber <florian@ubports.com>
1716 */
1817
19−#ifndef UNITY_HFDLIGHTS_H
20−#define UNITY_HFDLIGHTS_H
18+#ifndef DASH_PLUGIN_H
19+#define DASH_PLUGIN_H
2120
22−#include <QtCore/QObject>
23−#include <QDBusInterface>
24−#include "Lights.h"
21+#include <QtQml/QQmlEngine>
22+#include <QtQml/QQmlExtensionPlugin>
2523
26−class HfdLights: public Lights
24+class DashPlugin : public QQmlExtensionPlugin
2725{
2826 Q_OBJECT
27+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
2928
3029public:
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;
30+ void registerTypes(const char *uri) override;
4031};
4132
4233#endif
plugins/Dash/qmldirnew file+11
@@ -0,0 +1,11 @@
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.cppnew file+280
@@ -0,0 +1,280 @@
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.hnew file+103
@@ -0,0 +1,103 @@
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−target_link_libraries(GlobalShortcut-qml Qt5::Quick Qt5::Gui)
8+qt5_use_modules(GlobalShortcut-qml Quick Gui)
99
1010add_unity8_plugin(GlobalShortcut 1.0 GlobalShortcut TARGETS GlobalShortcut-qml)
plugins/GlobalShortcut/globalshortcut.cpp−3
@@ -58,9 +58,6 @@ 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− }
6461 connect(this, &QQuickItem::windowChanged, this, &GlobalShortcut::setupFilterOnWindow);
6562}
6663
plugins/Greeter/Unity/Launcher/CMakeLists.txt+2−1
@@ -29,7 +29,8 @@ add_library(UnityLauncherAS-qml MODULE
2929target_link_libraries(UnityLauncherAS-qml
3030 unity8-private
3131 ${GSETTINGS_QT_LDFLAGS}
32− Qt5::DBus Qt5::Qml Qt5::Gui
3332 )
3433
34+qt5_use_modules(UnityLauncherAS-qml DBus Qml Gui)
35+
3536add_unity8_greeter_plugin(Unity.Launcher 0.1 Unity/Launcher TARGETS UnityLauncherAS-qml)
plugins/Greeter/Unity/Launcher/launcheritem.cpp−6
@@ -89,12 +89,6 @@ 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−
9892bool LauncherItem::pinned() const
9993{
10094 return m_pinned;
plugins/Greeter/Unity/Launcher/launcheritem.h−1
@@ -35,7 +35,6 @@ public:
3535 QString name() const override;
3636 QString icon() const override;
3737 QStringList keywords() const override;
38− uint popularity() const override;
3938 bool pinned() const override;
4039 bool running() const override;
4140 bool recent() const override;
plugins/ImageCache/CMakeLists.txtnew file+8
@@ -0,0 +1,8 @@
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.cppnew file+135
@@ -0,0 +1,135 @@
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.hnew file+53
@@ -0,0 +1,53 @@
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.cppnew file+39
@@ -0,0 +1,39 @@
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.hnew file+31
@@ -0,0 +1,31 @@
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/qmldirnew file+2
@@ -0,0 +1,2 @@
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::promptlessChanged, this, &DBusGreeterList::promptlessChangedHandler);
28+ connect(m_greeter, &Greeter::isAuthenticatedChanged, this, &DBusGreeterList::authenticatedChangedHandler);
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->promptless();
43+ return !m_greeter->isAuthenticated();
4444}
4545
4646void DBusGreeterList::authenticationUserChangedHandler()
@@ -49,7 +49,7 @@ void DBusGreeterList::authenticationUserChangedHandler()
4949 Q_EMIT EntrySelected(m_greeter->authenticationUser());
5050}
5151
52−void DBusGreeterList::promptlessChangedHandler()
52+void DBusGreeterList::authenticatedChangedHandler()
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 promptlessChangedHandler();
51+ void authenticatedChangedHandler();
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
3029 )
3130
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,7 +27,6 @@ GreeterPrivate::GreeterPrivate(Greeter* parent)
2727 m_active(false),
2828 responded(false),
2929 everResponded(false),
30− promptless(false),
3130 q_ptr(parent)
3231{
3332}
@@ -113,12 +112,6 @@ QString Greeter::defaultSessionHint() const
113112 return d->m_greeter->defaultSessionHint();
114113}
115114
116−bool Greeter::promptless() const
117−{
118− Q_D(const Greeter);
119− return d->promptless;
120−}
121−
122115QString Greeter::selectUser() const
123116{
124117 Q_D(const Greeter);
@@ -153,10 +146,6 @@ void Greeter::authenticate(const QString &username)
153146 d->prompts.clear();
154147 d->responded = false;
155148 d->everResponded = false;
156− if (d->promptless) {
157− d->promptless = false;
158− Q_EMIT promptlessChanged();
159− }
160149
161150 if (authenticationUser() == username) {
162151 d->prompts = d->leftovers;
@@ -246,11 +235,6 @@ void Greeter::authenticationCompleteFilter()
246235 bool automatic = !d->everResponded;
247236 bool pamHasLeftoverMessages = !d->prompts.hasPrompt() && d->prompts.rowCount() > 0;
248237
249− if (isAuthenticated() && automatic) {
250− d->promptless = true;
251− Q_EMIT promptlessChanged();
252− }
253−
254238 if (!isAuthenticated()) {
255239 if (pamHasLeftoverMessages) {
256240 d->leftovers = d->prompts; // Prefer PAM's messages
plugins/LightDM/Greeter.h−3
@@ -37,7 +37,6 @@ 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)
4140 Q_PROPERTY(QString selectUser READ selectUser CONSTANT)
4241
4342public:
@@ -48,7 +47,6 @@ public:
4847 bool isAuthenticated() const;
4948 QString authenticationUser() const;
5049 QString defaultSessionHint() const;
51− bool promptless() const;
5250 QString selectUser() const;
5351 bool hasGuestAccount() const;
5452 bool showManualLoginHint() const;
@@ -66,7 +64,6 @@ Q_SIGNALS:
6664 void authenticationUserChanged();
6765 void isActiveChanged();
6866 void isAuthenticatedChanged();
69− void promptlessChanged();
7067 void showGreeter();
7168 void hideGreeter();
7269 void loginError(bool automatic);
plugins/LightDM/GreeterPrivate.h−1
@@ -34,7 +34,6 @@ public:
3434 PromptsModel leftovers; // prompts to show during next auth for same user
3535 bool responded;
3636 bool everResponded;
37− bool promptless;
3837 QString cachedAuthUser;
3938
4039protected:
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
2928 )
3029
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+4−3
@@ -26,21 +26,22 @@ target_link_libraries(integratedLightDM
2626 ${GLIB_LIBRARIES}
2727 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
2828 -lpam
29− Qt5::Concurrent Qt5::DBus Qt5::Gui
3029)
3130target_link_libraries(integratedLightDMSession
3231 ${GLIB_LIBRARIES}
3332 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
3433 -lpam
35− Qt5::Concurrent Qt5::DBus Qt5::Gui
3634)
3735target_link_libraries(MockLightDM-demo-shared
3836 ${GLIB_LIBRARIES}
3937 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
4038 -lpam
41− Qt5::Concurrent Qt5::DBus Qt5::Gui
4239)
4340
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+
4445set_target_properties(integratedLightDM PROPERTIES
4546 COMPILE_FLAGS "-DSM_BUSNAME=systemBus -fPIC")
4647set_target_properties(integratedLightDMSession PROPERTIES
plugins/LightDM/UsersModel.cpp−5
@@ -109,11 +109,6 @@ 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−
117112 return variantData;
118113}
119114
plugins/Lights/CMakeLists.txt+2−8
@@ -1,6 +1,5 @@
11pkg_check_modules(ANDROID_HEADERS REQUIRED android-headers)
22pkg_check_modules(ANDROID_HARDWARE REQUIRED libhardware)
3−pkg_check_modules(ANDROID_PROPERTIES REQUIRED libandroid-properties)
43
54include_directories(
65 SYSTEM
@@ -10,14 +9,9 @@ include_directories(
109add_library(Lights-qml MODULE
1110 plugin.cpp
1211 Lights.cpp
13− LegacyLights.cpp
14− HfdLights.cpp
1512 )
1613
17−target_link_libraries(Lights-qml
18− Qt5::Qml Qt5::Gui Qt5::DBus
19− ${ANDROID_HARDWARE_LIBRARIES}
20− ${ANDROID_PROPERTIES_LIBRARIES}
21− )
14+qt5_use_modules(Lights-qml Qml Gui)
15+target_link_libraries(Lights-qml ${ANDROID_HARDWARE_LIBRARIES})
2216
2317add_unity8_plugin(Lights 0.1 Lights TARGETS Lights-qml)
plugins/Lights/HfdLights.cppdeleted−62
@@ -1,62 +0,0 @@
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−}
plugins/Lights/LegacyLights.cppdeleted−91
@@ -1,91 +0,0 @@
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/Lights/Lights.cpp+65
@@ -26,12 +26,20 @@ extern "C" {
2626
2727Lights::Lights(QObject* parent)
2828 : QObject(parent),
29+ m_lightDevice(0),
2930 m_color("blue"),
3031 m_state(Lights::Off),
3132 m_onMs(1000),
3233 m_offMs(3000)
3334{
35+}
3436
37+Lights::~Lights()
38+{
39+ if (m_lightDevice) {
40+ hw_device_t* device = (hw_device_t*) m_lightDevice;
41+ device->close(device);
42+ }
3543}
3644
3745void Lights::setState(Lights::State newState)
@@ -99,3 +107,60 @@ void Lights::setOffMillisec(int offMs)
99107 // FIXME: update the property if the light is already on
100108 }
101109}
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+8−4
@@ -22,6 +22,8 @@
2222#include <QtCore/QObject>
2323#include <QtGui/QColor>
2424
25+struct light_device_t;
26+
2527class Lights: public QObject
2628{
2729 Q_OBJECT
@@ -38,6 +40,7 @@ public:
3840 Q_ENUM(State)
3941
4042 explicit Lights(QObject *parent = 0);
43+ ~Lights();
4144
4245 void setState(State newState);
4346 State state() const;
@@ -57,15 +60,16 @@ Q_SIGNALS:
5760 void onMillisecChanged(int onMs);
5861 void offMillisecChanged(int offMs);
5962
60−protected:
63+private:
64+ light_device_t* m_lightDevice;
6165 QColor m_color;
6266 State m_state;
6367 int m_onMs;
6468 int m_offMs;
6569
66− virtual bool init() = 0;
67− virtual void turnOff() = 0;
68− virtual void turnOn() = 0;
70+ bool init();
71+ void turnOff();
72+ void turnOn();
6973};
7074
7175#endif
plugins/Lights/plugin.cpp+1−20
@@ -18,11 +18,6 @@
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>
2621
2722#include <QtQml/qqml.h>
2823
@@ -30,21 +25,7 @@ static QObject *lights_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
3025{
3126 Q_UNUSED(engine)
3227 Q_UNUSED(scriptEngine)
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− }
28+ return new Lights();
4829}
4930
5031void LightsPlugin::registerTypes(const char *uri)
plugins/Powerd/CMakeLists.txt+2−4
@@ -9,9 +9,7 @@ add_library(Powerd-qml MODULE
99 Powerd.cpp
1010 )
1111
12−target_link_libraries(Powerd-qml
13− Qt5::DBus Qt5::Qml
14− ${GIO_LDFLAGS}
15− )
12+qt5_use_modules(Powerd-qml DBus Qml)
13+target_link_libraries(Powerd-qml ${GIO_LDFLAGS})
1614
1715add_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−target_link_libraries(ScreenshotDirectory-qml Qt5::Qml Qt5::Gui Qt5::Quick)
7+qt5_use_modules(ScreenshotDirectory-qml Qml Gui Quick)
88
99add_unity8_plugin(ScreenshotDirectory 0.1 ScreenshotDirectory TARGETS ScreenshotDirectory-qml)
plugins/SessionBroadcast/CMakeLists.txt+2−1
@@ -6,8 +6,9 @@ add_library(SessionBroadcast-qml MODULE
66 plugin.cpp
77 )
88
9+qt5_use_modules(SessionBroadcast-qml DBus Qml)
10+
911target_link_libraries(SessionBroadcast-qml
10− Qt5::DBus Qt5::Qml
1112 ${GLIB_LIBRARIES}
1213 )
1314
plugins/UInput/CMakeLists.txt+1−1
@@ -3,5 +3,5 @@ add_library(UInput-qml MODULE
33 uinput.cpp
44)
55
6−target_link_libraries(UInput-qml Qt5::Qml)
6+qt5_use_modules(UInput-qml Qml)
77add_unity8_plugin(UInput 0.1 UInput TARGETS UInput-qml)
plugins/Ubuntu/DownloadDaemonListener/CMakeLists.txt+2−4
@@ -11,10 +11,8 @@ set(DOWNLOADDAEMONLISTENER_SOURCES
1111
1212add_library(DownloadDaemonListener MODULE ${DOWNLOADDAEMONLISTENER_SOURCES})
1313
14+qt5_use_modules(DownloadDaemonListener Qml Quick DBus Core)
1415pkg_check_modules(DDLADAPTER REQUIRED udm-common)
1516add_definitions(${DDLADAPTER_CFLAGS} ${DDLADAPTER_CFLAGS_OTHER})
16−target_link_libraries(DownloadDaemonListener
17− Qt5::Qml Qt5::Quick Qt5::DBus Qt5::Core
18− ${DDLADAPTER_LIBRARIES}
19− )
17+target_link_libraries(DownloadDaemonListener ${DDLADAPTER_LIBRARIES})
2018add_unity8_plugin(Ubuntu.DownloadDaemonListener 0.1 Ubuntu/DownloadDaemonListener TARGETS DownloadDaemonListener)
plugins/Ubuntu/Gestures/CMakeLists.txt+3−1
@@ -17,7 +17,9 @@ pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
1717add_definitions(-DUBUNTUGESTURESQML_LIBRARY)
1818
1919add_library(UbuntuGesturesQml SHARED ${UbuntuGesturesQml_SOURCES})
20−target_link_libraries(UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES} Qt5::Core Qt5::Quick)
20+target_link_libraries(UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES})
21+
22+qt5_use_modules(UbuntuGesturesQml Core Quick)
2123
2224# So that Foo.cpp can #include "Foo.moc"
2325include_directories(${CMAKE_CURRENT_BINARY_DIR})
plugins/Ubuntu/Gestures/TouchGestureArea.cpp−6
@@ -328,12 +328,6 @@ 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();
337331}
338332
339333void TouchGestureArea::unownedTouchEvent(QTouchEvent *unownedTouchEvent)
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−target_link_libraries(ApplicationMenu-qml Qt5::DBus Qt5::Qml)
17+qt5_use_modules(ApplicationMenu-qml DBus Qml)
1818
1919add_unity8_plugin(Unity.ApplicationMenu 0.1 Unity/ApplicationMenu TARGETS ApplicationMenu-qml)
plugins/Unity/CMakeLists.txt+1
@@ -3,5 +3,6 @@ add_subdirectory(Connectivity)
33add_subdirectory(Indicators)
44add_subdirectory(Launcher)
55add_subdirectory(Session)
6+add_subdirectory(DashCommunicator)
67add_subdirectory(InputInfo)
78add_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−target_link_libraries(Connectivity Qt5::Qml Qt5::DBus Qt5::Core)
8+qt5_use_modules(Connectivity Qml DBus Core)
99
1010add_unity8_plugin(Unity.Connectivity 0.1 Unity/Connectivity TARGETS Connectivity)
plugins/Unity/DashCommunicator/CMakeLists.txtnew file+26
@@ -0,0 +1,26 @@
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.cppnew file+58
@@ -0,0 +1,58 @@
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/dashcommunicator.hnew file+45
@@ -0,0 +1,45 @@
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 DASHCOMMUNICATOR_H
18+#define DASHCOMMUNICATOR_H
19+
20+// Qt
21+#include <QThread>
22+#include <QMutex>
23+
24+class DashConnection;
25+
26+class DashCommunicator: public QThread
27+{
28+ Q_OBJECT
29+public:
30+ explicit DashCommunicator(QObject *parent = 0);
31+ ~DashCommunicator();
32+
33+public Q_SLOTS:
34+ void setCurrentScope(int index, bool animate, bool isSwipe);
35+
36+protected:
37+ void run() override;
38+
39+private:
40+ DashConnection *m_dashConnection;
41+ bool m_created;
42+ QMutex m_mutex;
43+};
44+
45+#endif
plugins/Unity/DashCommunicator/dashcommunicatorservice.cppnew file+30
@@ -0,0 +1,30 @@
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.hnew file+38
@@ -0,0 +1,38 @@
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.cppnew file+66
@@ -0,0 +1,66 @@
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.hnew file+37
@@ -0,0 +1,37 @@
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.cppnew file+35
@@ -0,0 +1,35 @@
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.hnew file+39
@@ -0,0 +1,39 @@
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.cppnew file+32
@@ -0,0 +1,32 @@
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/Lights/LegacyLights.h → plugins/Unity/DashCommunicator/plugin.hrenamed+8−19
@@ -1,6 +1,5 @@
11/*
22 * Copyright (C) 2014 Canonical, Ltd.
3− * Copyright (C) 2021 UBports Foundation.
43 *
54 * This program is free software; you can redistribute it and/or modify
65 * it under the terms of the GNU General Public License as published by
@@ -14,32 +13,22 @@
1413 * You should have received a copy of the GNU General Public License
1514 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1615 *
17− * Author: Renato Araujo Oliveira Filho <renato.filho@canonical.com>
16+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1817 */
1918
20−#ifndef UNITY_LEGACYLIGHTS_H
21−#define UNITY_LEGACYLIGHTS_H
19+#ifndef DASHCOMMUNICATOR_PLUGIN_H
20+#define DASHCOMMUNICATOR_PLUGIN_H
2221
23−#include <QtCore/QObject>
24−#include "Lights.h"
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlExtensionPlugin>
2524
26−struct light_device_t;
27−
28−class LegacyLights: public Lights
25+class DashCommunicatorPlugin : public QQmlExtensionPlugin
2926{
3027 Q_OBJECT
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
3129
3230public:
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−
31+ void registerTypes(const char *uri) override;
4332};
4433
4534#endif
plugins/Unity/DashCommunicator/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Unity.DashCommunicator
2+plugin DashCommunicator-qml
3+typeinfo DashCommunicator.qmltypes
plugins/Unity/Indicators/CMakeLists.txt+2−1
@@ -44,7 +44,8 @@ target_link_libraries(IndicatorsQml
4444 ${GLIB_LIBRARIES}
4545 ${GIO_LIBRARIES}
4646 ${QMENUMODEL_LDFLAGS}
47− Qt5::Core Qt5::Qml Qt5::Quick Qt5::DBus
4847)
4948
49+qt5_use_modules(IndicatorsQml Core Qml Quick DBus)
50+
5051add_unity8_plugin(Unity.Indicators 0.1 Unity/Indicators TARGETS IndicatorsQml)
plugins/Unity/Indicators/indicatorsmodel.cpp−13
@@ -103,19 +103,6 @@ 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−
119106/*!
120107 \qmlmethod IndicatorsModel::unload()
121108
plugins/Unity/Indicators/indicatorsmodel.h−9
@@ -35,9 +35,6 @@ 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−
4138public:
4239
4340 IndicatorsModel(QObject *parent=nullptr);
@@ -51,9 +48,6 @@ public:
5148 QString profile() const;
5249 void setProfile(const QString& profile);
5350
54− bool light() const;
55− void setLight(const bool &light);
56−
5751 /* QAbstractItemModel */
5852 QHash<int, QByteArray> roleNames() const override;
5953 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -66,7 +60,6 @@ Q_SIGNALS:
6660 void countChanged();
6761 void profileChanged();
6862 void indicatorDataChanged(const QVariant& data);
69− void lightChanged();
7063
7164private Q_SLOTS:
7265 void onIdentifierChanged();
@@ -81,8 +74,6 @@ private:
8174
8275 void notifyDataChanged(QObject *sender, int role);
8376 int count() const;
84−
85− bool m_light;
8677};
8778
8879#endif // INDICATORSMODEL_H
plugins/Unity/InputInfo/CMakeLists.txt+2−1
@@ -32,7 +32,8 @@ add_library(InputInfo SHARED
3232target_link_libraries(InputInfo
3333 ${LIBUDEV_LDFLAGS}
3434 ${LIBEVDEV_LDFLAGS}
35− Qt5::Core Qt5::Qml Qt5::Quick
3635)
3736
37+qt5_use_modules(InputInfo Core Qml Quick)
38+
3839add_unity8_plugin(Unity.InputInfo 0.1 Unity/InputInfo TARGETS InputInfo)
plugins/Unity/Launcher/CMakeLists.txt+2−2
@@ -26,7 +26,6 @@ set(QMLLAUNCHERPLUGIN_SRC
2626 asadapter.cpp
2727 appdrawermodel.cpp
2828 ualwrapper.cpp
29− xdgwatcher.cpp
3029 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
3130 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
3231 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
@@ -48,7 +47,8 @@ target_link_libraries(UnityLauncher-qml
4847 ${GSETTINGS_QT_LDFLAGS}
4948 ${GLIB_LIBRARIES}
5049 ${UAL_LIBRARIES}
51− Qt5::DBus Qt5::Qml Qt5::Gui Qt5::Concurrent
5250 )
5351
52+qt5_use_modules(UnityLauncher-qml DBus Qml Gui)
53+
5454add_unity8_plugin(Unity.Launcher 0.1 Unity/Launcher TARGETS UnityLauncher-qml)
plugins/Unity/Launcher/appdrawermodel.cpp+14−144
@@ -1,6 +1,5 @@
11/*
22 * Copyright (C) 2016 Canonical, Ltd.
3− * Copyright (C) 2020 UBports Foundation.
43 *
54 * This program is free software; you can redistribute it and/or modify
65 * it under the terms of the GNU General Public License as published by
@@ -17,35 +16,23 @@
1716
1817#include "appdrawermodel.h"
1918#include "ualwrapper.h"
20−#include "xdgwatcher.h"
2119
2220#include <QDebug>
2321#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−}
3322
3423AppDrawerModel::AppDrawerModel(QObject *parent):
35− AppDrawerModelInterface(parent),
36− m_ual(new UalWrapper(this)),
37− m_xdgWatcher(new XdgWatcher(this)),
38− m_refreshing(false)
24+ AppDrawerModelInterface(parent)
3925{
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();
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);
4936}
5037
5138int AppDrawerModel::rowCount(const QModelIndex &parent) const
@@ -66,127 +53,10 @@ QVariant AppDrawerModel::data(const QModelIndex &index, int role) const
6653 case RoleKeywords:
6754 return m_list.at(index.row())->keywords();
6855 case RoleUsage:
69− return m_list.at(index.row())->popularity();
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();
7059 }
7160
7261 return QVariant();
7362}
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+2−33
@@ -1,6 +1,5 @@
11/*
22 * Copyright (C) 2016 Canonical, Ltd.
3− * Copyright (C) 2020 UBports Foundation.
43 *
54 * This program is free software; you can redistribute it and/or modify
65 * it under the terms of the GNU General Public License as published by
@@ -15,50 +14,20 @@
1514 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1615 */
1716
18−#include <memory>
19−#include <QFutureWatcher>
17+
2018#include <unity/shell/launcher/AppDrawerModelInterface.h>
2119
2220#include "launcheritem.h"
2321
24−class UalWrapper;
25−class XdgWatcher;
26−
2722class AppDrawerModel: public AppDrawerModelInterface
2823{
2924 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)
3325public:
3426 AppDrawerModel(QObject* parent = nullptr);
3527
3628 int rowCount(const QModelIndex &parent) const override;
3729 QVariant data(const QModelIndex &index, int role) const override;
3830
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−
5331private:
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;
32+ QList<LauncherItem*> m_list;
6433};
plugins/Unity/Launcher/launcheritem.cpp+1−13
@@ -37,6 +37,7 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
3737 m_alerting(false),
3838 m_quickList(new QuickListModel(this))
3939{
40+ Q_ASSERT(parent != nullptr);
4041 QuickListEntry nameAction;
4142 nameAction.setActionId(QStringLiteral("launch_item"));
4243 nameAction.setText(m_name);
@@ -255,19 +256,6 @@ void LauncherItem::setSurfaces(const QList<QPair<QString, QString> > &surfaces)
255256 }
256257}
257258
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);
268− }
269−}
270−
271259unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
272260{
273261 return m_quickList;
plugins/Unity/Launcher/launcheritem.h−3
@@ -39,7 +39,6 @@ public:
3939 QString name() const override;
4040 QString icon() const override;
4141 QStringList keywords() const override;
42− uint popularity() const override;
4342 bool pinned() const override;
4443 bool running() const override;
4544 bool recent() const override;
@@ -56,7 +55,6 @@ private:
5655 void setName(const QString &name);
5756 void setIcon(const QString &icon);
5857 void setKeywords(const QStringList &keywords);
59− void setPopularity(uint popularity);
6058 void setPinned(bool pinned);
6159 void setRunning(bool running);
6260 void setRecent(bool recent);
@@ -72,7 +70,6 @@ private:
7270 QString m_name;
7371 QString m_icon;
7472 QStringList m_keywords;
75− uint m_popularity;
7673 bool m_pinned;
7774 bool m_running;
7875 bool m_recent;
plugins/Unity/Launcher/launchermodel.cpp+5−1
@@ -167,7 +167,6 @@ void LauncherModel::pin(const QString &appId, int index)
167167 appInfo.icon,
168168 this);
169169 item->setPinned(true);
170− item->setPopularity(appInfo.popularity);
171170 m_list.insert(index, item);
172171 endInsertRows();
173172 }
@@ -521,6 +520,11 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
521520 return;
522521 }
523522
523+ if (app->appId() == QLatin1String("unity8-dash")) {
524+ // Not adding the dash app
525+ return;
526+ }
527+
524528 const int itemIndex = findApplication(app->appId());
525529 if (itemIndex != -1) {
526530 LauncherItem *item = m_list.at(itemIndex);
plugins/Unity/Launcher/ualwrapper.cpp+2−3
@@ -24,6 +24,7 @@ using namespace ubuntu::app_launch;
2424UalWrapper::UalWrapper(QObject *parent):
2525 QObject(parent)
2626{
27+
2728}
2829
2930QStringList UalWrapper::installedApps()
@@ -38,7 +39,7 @@ QStringList UalWrapper::installedApps()
3839 }
3940 }
4041 } catch (const std::runtime_error &e) {
41− qWarning() << "ubuntu-app-launch threw an exception listing apps:" << e.what();
42+ qWarning() << "ubuntu-all-launch threw an exception listing apps:" << e.what();
4243 }
4344
4445 return appIds;
@@ -58,13 +59,11 @@ UalWrapper::AppInfo UalWrapper::getApplicationInfo(const QString &appId)
5859 std::shared_ptr<Application> ualApp;
5960 ualApp = Application::create(ualAppId, Registry::getDefault());
6061
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();
6867 info.valid = true;
6968 } catch (const std::runtime_error &e) {
7069 qWarning() << "ubuntu-app-launch threw an exception getting app info for appId:" << appId << ":" << e.what();
plugins/Unity/Launcher/ualwrapper.h+1−2
@@ -21,16 +21,15 @@ class UalWrapper: public QObject
2121 Q_OBJECT
2222public:
2323 struct AppInfo {
24− QString appId;
2524 bool valid = false;
2625 QString name;
2726 QString icon;
2827 QStringList keywords;
29− uint popularity = 0;
3028 };
3129
3230 UalWrapper(QObject* parent = nullptr);
3331
3432 static QStringList installedApps();
3533 static AppInfo getApplicationInfo(const QString &appId);
34+
3635};
plugins/Unity/Launcher/xdgwatcher.cppdeleted−129
@@ -1,129 +0,0 @@
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.hdeleted−46
@@ -1,46 +0,0 @@
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−target_link_libraries(Platform-qml Qt5::DBus Qt5::Qml)
9+qt5_use_modules(Platform-qml DBus Qml)
1010
1111add_unity8_plugin(Unity.Platform 1.0 Unity/Platform TARGETS Platform-qml)
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)
2122target_link_libraries(UnitySession-qml
22− Qt5::DBus Qt5::Qml
2323 unity8-private
2424 ${GIO_LDFLAGS}
2525 ${GLIB_LIBRARIES}
plugins/Utils/CMakeLists.txt+4−3
@@ -7,6 +7,7 @@ include_directories(
77 SYSTEM
88 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
99 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
10+ ${GIO_INCLUDE_DIRS}
1011)
1112
1213set(QMLPLUGIN_SRC
@@ -43,9 +44,7 @@ add_library(Utils-qml SHARED
4344 ${QMLPLUGIN_SRC}
4445 )
4546
46−target_link_libraries(Utils-qml
47− Qt5::Qml Qt5::Quick Qt5::DBus Qt5::Network Qt5::Gui Qt5::Sql Qt5::Concurrent
48− )
47+target_link_libraries(Utils-qml ${GIO_LDFLAGS})
4948
5049# Because this is an internal support library, we want
5150# to expose all symbols in it. Consider changing this
@@ -53,4 +52,6 @@ target_link_libraries(Utils-qml
5352# files directly in targets.
5453set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
5554
55+qt5_use_modules(Utils-qml Qml Quick DBus Network Gui Sql Concurrent)
56+
5657add_unity8_plugin(Utils 0.1 Utils TARGETS Utils-qml)
plugins/Utils/appdrawerproxymodel.cpp+1−1
@@ -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.contains(m_filterString, Qt::CaseInsensitive)) {
161+ if (currentWord.startsWith(m_filterString, Qt::CaseInsensitive)) {
162162 found = true;
163163 break;
164164 }
plugins/Utils/deviceconfigparser.cpp−18
@@ -116,24 +116,6 @@ 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−
137119QStringList DeviceConfigParser::readOrientationsFromConfig(const QString &key) const
138120{
139121 m_config->beginGroup(m_name);
plugins/Utils/deviceconfigparser.h−3
@@ -33,7 +33,6 @@ 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)
3736
3837public:
3938 DeviceConfigParser(QObject *parent = nullptr);
@@ -48,7 +47,6 @@ public:
4847 Qt::ScreenOrientation portraitOrientation() const;
4948 Qt::ScreenOrientation invertedPortraitOrientation() const;
5049 QString category() const;
51− bool supportsMultiColorLed() const;
5250
5351Q_SIGNALS:
5452 void changed();
@@ -60,7 +58,6 @@ private:
6058 QStringList readOrientationsFromConfig(const QString &key) const;
6159 QString readOrientationFromConfig(const QString &key) const;
6260 Qt::ScreenOrientation stringToOrientation(const QString &orientationString, Qt::ScreenOrientation defaultValue) const;
63− bool readBoolFromConfig(const QString &key, bool defaultValue) const;
6461};
6562
6663#endif
plugins/Utils/windowstatestorage.cpp+131−293
@@ -1,6 +1,5 @@
11/*
22 * Copyright 2015-2016 Canonical Ltd.
3− * Copyright 2021 UBports Foundation
43 *
54 * This program is free software; you can redistribute it and/or modify
65 * it under the terms of the GNU Lesser General Public License as published by
@@ -17,344 +16,185 @@
1716
1817#include "windowstatestorage.h"
1918
19+#include <QtConcurrent>
2020#include <QDebug>
21−#include <QDir>
22−#include <QMetaObject>
23−#include <QObject>
21+#include <QFutureSynchronizer>
2422#include <QSqlQuery>
2523#include <QSqlError>
2624#include <QSqlResult>
27−#include <QStandardPaths>
2825#include <QRect>
2926#include <unity/shell/application/ApplicationInfoInterface.h>
3027
28+QMutex WindowStateStorage::s_mutex;
3129
32−class AsyncQuery: public QObject
33−{
34− Q_OBJECT
30+inline QString sanitiseString(QString string) {
31+ return string.remove(QLatin1Char('\"'))
32+ .remove(QLatin1Char('\''))
33+ .remove(QLatin1Char('\\'));
34+}
3535
36−public:
37− AsyncQuery(const QString &dbName):
38− m_dbName(dbName)
39− {
40− }
36+WindowStateStorage::WindowStateStorage(QObject *parent):
37+ QObject(parent)
38+{
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+}
4146
42− ~AsyncQuery()
43− {
44− QSqlDatabase::removeDatabase(m_connectionName);
47+WindowStateStorage::~WindowStateStorage()
48+{
49+ QFutureSynchronizer<void> futureSync;
50+ for (int i = 0; i < m_asyncQueries.count(); ++i) {
51+ futureSync.addFuture(m_asyncQueries[i]);
4552 }
53+ futureSync.waitForFinished();
54+ m_db.close();
55+}
4656
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− }
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);
5562
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− }
63+ saveValue(queryString);
64+}
9665
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− }
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));
12470
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− }
71+ QSqlQuery query = getValue(queryString);
16372
73+ if (!query.first()) {
74+ return defaultValue;
16475 }
76+ return (WindowState)query.value(QStringLiteral("state")).toInt();
77+}
16578
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− }
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+}
19390
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− }
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);
21096
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− }
97+ saveValue(queryString);
98+}
22899
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− }
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));
243104
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− }
105+ QSqlQuery query = getValue(queryString);
259106
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;
107+ if (!query.first()) {
108+ return defaultValue;
285109 }
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);
110+ return query.value("stage").toInt();
298111}
299112
300−WindowStateStorage::~WindowStateStorage()
113+void WindowStateStorage::executeAsyncQuery(const QString &queryString)
301114{
302− m_thread.quit();
303− m_thread.wait();
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+ }
304124}
305125
306−WindowStateStorage::WindowState WindowStateStorage::getState(const QString &windowId, WindowStateStorage::WindowState defaultValue) const
126+QRect WindowStateStorage::getGeometry(const QString &windowId, const QRect &defaultValue) const
307127{
308− int state;
128+ QString queryString = QStringLiteral("SELECT * FROM geometry WHERE windowId = '%1';")
129+ .arg(sanitiseString(windowId));
309130
310− QMetaObject::invokeMethod(m_asyncQuery, "getState", Qt::BlockingQueuedConnection,
311− Q_RETURN_ARG(int, state),
312− Q_ARG(const QString&, windowId)
313− );
131+ QSqlQuery query = getValue(queryString);
314132
315− if (state == -1) {
133+ if (!query.first()) {
316134 return defaultValue;
317135 }
318136
319− return (WindowState)state;
137+ const QRect result(query.value(QStringLiteral("x")).toInt(), query.value(QStringLiteral("y")).toInt(),
138+ query.value(QStringLiteral("width")).toInt(), query.value(QStringLiteral("height")).toInt());
139+
140+ if (result.isValid()) {
141+ return result;
142+ }
143+
144+ return defaultValue;
320145}
321146
322−int WindowStateStorage::getStage(const QString &appId, int defaultValue) const
147+void WindowStateStorage::initdb()
323148{
324− int stage;
149+ m_db.open();
150+ if (!m_db.open()) {
151+ qWarning() << "Error opening state database:" << m_db.lastError().driverText() << m_db.lastError().databaseText();
152+ return;
153+ }
325154
326− QMetaObject::invokeMethod(m_asyncQuery, "getStage", Qt::BlockingQueuedConnection,
327− Q_RETURN_ARG(int, stage),
328− Q_ARG(const QString&, appId)
329− );
155+ if (!m_db.tables().contains(QStringLiteral("geometry"))) {
156+ QSqlQuery query;
157+ query.exec(QStringLiteral("CREATE TABLE geometry(windowId TEXT UNIQUE, x INTEGER, y INTEGER, width INTEGER, height INTEGER);"));
158+ }
330159
331− if (stage == -1) {
332− return defaultValue;
160+ if (!m_db.tables().contains(QStringLiteral("state"))) {
161+ QSqlQuery query;
162+ query.exec(QStringLiteral("CREATE TABLE state(windowId TEXT UNIQUE, state INTEGER);"));
333163 }
334164
335− return stage;
165+ if (!m_db.tables().contains(QStringLiteral("stage"))) {
166+ QSqlQuery query;
167+ query.exec(QStringLiteral("CREATE TABLE stage(appId TEXT UNIQUE, stage INTEGER);"));
168+ }
336169}
337170
338−QRect WindowStateStorage::getGeometry(const QString &windowId, const QRect &defaultValue) const
171+void WindowStateStorage::saveValue(const QString &queryString)
339172{
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;
173+ QMutexLocker mutexLocker(&s_mutex);
174+
175+ QFuture<void> future = QtConcurrent::run(&m_threadPool, executeAsyncQuery, queryString);
176+ m_asyncQueries.append(future);
177+
178+ QFutureWatcher<void> *futureWatcher = new QFutureWatcher<void>();
179+ futureWatcher->setFuture(future);
180+ connect(futureWatcher, &QFutureWatcher<void>::finished,
181+ this,
182+ [=](){ m_asyncQueries.removeAll(futureWatcher->future());
183+ futureWatcher->deleteLater(); });
349184}
350185
351−const QString WindowStateStorage::getDbName()
186+QSqlQuery WindowStateStorage::getValue(const QString &queryString) const
352187{
353− QString dbName;
354− QMetaObject::invokeMethod(m_asyncQuery, "getDbName", Qt::BlockingQueuedConnection,
355− Q_RETURN_ARG(QString, dbName)
356− );
357− return QString(dbName);
188+ QMutexLocker l(&s_mutex);
189+ QSqlQuery query;
190+
191+ bool ok = query.exec(queryString);
192+ if (!ok) {
193+ qWarning() << "Error retrieving database query:" << queryString
194+ << "Driver error:" << query.lastError().driverText()
195+ << "Database error:" << query.lastError().databaseText();
196+ }
197+ return query;
358198}
359199
360200Mir::State WindowStateStorage::toMirState(WindowState state) const
@@ -379,5 +219,3 @@ Mir::State WindowStateStorage::toMirState(WindowState state) const
379219 return Mir::RestoredState;
380220 }
381221}
382−
383−#include "windowstatestorage.moc"
plugins/Utils/windowstatestorage.h+17−14
@@ -1,6 +1,5 @@
11/*
22 * Copyright 2015-2016 Canonical Ltd.
3− * Copyright 2021 UBports Foundation
43 *
54 * This program is free software; you can redistribute it and/or modify
65 * it under the terms of the GNU Lesser General Public License as published by
@@ -17,16 +16,13 @@
1716
1817#include <QObject>
1918#include <QSqlDatabase>
20−#include <QSqlQuery>
2119#include <QMutex>
2220#include <QFuture>
23−#include <QThread>
21+#include <QThreadPool>
2422
2523// unity-api
2624#include <unity/shell/application/Mir.h>
2725
28−class AsyncQuery;
29−
3026class WindowStateStorage: public QObject
3127{
3228 Q_OBJECT
@@ -50,25 +46,32 @@ public:
5046 Q_DECLARE_FLAGS(WindowStates, WindowState)
5147 Q_FLAG(WindowStates)
5248
53− WindowStateStorage(const QString &dbName = QString(), QObject *parent = nullptr);
49+ WindowStateStorage(QObject *parent = nullptr);
5450 virtual ~WindowStateStorage();
5551
52+ Q_INVOKABLE void saveState(const QString &windowId, WindowState state);
5653 Q_INVOKABLE WindowState getState(const QString &windowId, WindowState defaultValue) const;
5754
55+ Q_INVOKABLE void saveGeometry(const QString &windowId, const QRect &rect);
5856 Q_INVOKABLE QRect getGeometry(const QString &windowId, const QRect &defaultValue) const;
5957
58+ Q_INVOKABLE void saveStage(const QString &appId, int stage);
6059 Q_INVOKABLE int getStage(const QString &appId, int defaultValue) const;
6160
6261 Q_INVOKABLE Mir::State toMirState(WindowState state) const;
6362
64− const QString getDbName();
63+private:
64+ void initdb();
6565
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);
66+ void saveValue(const QString &queryString);
67+ QSqlQuery getValue(const QString &queryString) const;
7068
71−private:
72− QThread m_thread;
73− AsyncQuery *m_asyncQuery;
69+ static void executeAsyncQuery(const QString &queryString);
70+ static QMutex s_mutex;
71+
72+ // NB: This is accessed from threads. Make sure to mutex it.
73+ QSqlDatabase m_db;
74+
75+ QList<QFuture<void>> m_asyncQueries;
76+ QThreadPool m_threadPool;
7477};
plugins/WindowManager/CMakeLists.txt+1−2
@@ -4,7 +4,6 @@ set(WINDOWMANAGER_SRC
44 Window.cpp
55 WindowManagerPlugin.cpp
66 WindowMargins.cpp
7− InputMethodManager.cpp
87 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
98 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
109 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
@@ -21,6 +20,6 @@ include_directories(
2120
2221add_library(windowmanager-qml SHARED ${WINDOWMANAGER_SRC})
2322
24−target_link_libraries(windowmanager-qml Qt5::Qml Qt5::Quick Qt5::Gui)
23+qt5_use_modules(windowmanager-qml Qml Quick Gui)
2524
2625add_unity8_plugin(WindowManager 0.1 WindowManager TARGETS windowmanager-qml)
plugins/WindowManager/InputMethodManager.cppdeleted−56
@@ -1,56 +0,0 @@
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.hdeleted−55
@@ -1,55 +0,0 @@
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+42−103
@@ -1,6 +1,5 @@
11/*
22 * Copyright (C) 2016-2017 Canonical, Ltd.
3− * Copyright 2019 UBports Foundation
43 *
54 * This program is free software: you can redistribute it and/or modify it under
65 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -30,7 +29,6 @@
3029
3130// local
3231#include "Window.h"
33−#include "InputMethodManager.h"
3432
3533Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtInfoMsg)
3634
@@ -40,12 +38,7 @@ Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtInfoMsg)
4038namespace unityapi = unity::shell::application;
4139
4240TopLevelWindowModel::TopLevelWindowModel()
43− : m_nullWindow(createNullWindow()),
44− m_surfaceManagerBusy(false)
4541{
46− connect(m_nullWindow, &Window::focusedChanged, this, [this] {
47− Q_EMIT rootFocusChanged();
48− });
4942}
5043
5144void TopLevelWindowModel::setApplicationManager(unityapi::ApplicationManagerInterface* value)
@@ -195,8 +188,9 @@ void TopLevelWindowModel::prependSurfaceHelper(unityapi::MirSurfaceInterface *su
195188
196189 prependWindow(window, application);
197190
198− // Activate the newly-prepended window.
199− window->activate();
191+ if (!surface) {
192+ activateEmptyWindow(window);
193+ }
200194
201195 INFO_MSG << " after " << toString();
202196}
@@ -317,11 +311,10 @@ void TopLevelWindowModel::onSurfaceDied(unityapi::MirSurfaceInterface *surface)
317311
318312 auto application = m_windowModel[i].application;
319313
320− DEBUG_MSG << " application->name()=" << application->name()
321− << " application->state()=" << application->state();
314+ // can't be starting if it already has a surface
315+ Q_ASSERT(application->state() != unityapi::ApplicationInfoInterface::Starting);
322316
323− if (application->state() == unityapi::ApplicationInfoInterface::Running
324− || application->state() == unityapi::ApplicationInfoInterface::Starting) {
317+ if (application->state() == unityapi::ApplicationInfoInterface::Running) {
325318 m_windowModel[i].removeOnceSurfaceDestroyed = true;
326319 } else {
327320 // assume it got killed by the out-of-memory daemon.
@@ -351,17 +344,7 @@ void TopLevelWindowModel::onSurfaceDestroyed(unityapi::MirSurfaceInterface *surf
351344
352345Window *TopLevelWindowModel::createWindow(unityapi::MirSurfaceInterface *surface)
353346{
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−{
347+ int id = generateId();
365348 Window *qmlWindow = new Window(id, this);
366349 connectWindow(qmlWindow);
367350 if (surface) {
@@ -452,17 +435,7 @@ void TopLevelWindowModel::removeAt(int index)
452435 setFocusedWindow(nullptr);
453436 }
454437
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();
438+ INFO_MSG << " after " << toString();
466439}
467440
468441void TopLevelWindowModel::setInputMethodWindow(Window *window)
@@ -473,7 +446,6 @@ void TopLevelWindowModel::setInputMethodWindow(Window *window)
473446 }
474447 m_inputMethodWindow = window;
475448 Q_EMIT inputMethodSurfaceChanged(m_inputMethodWindow->surface());
476− InputMethodManager::instance()->setWindow(window);
477449}
478450
479451void TopLevelWindowModel::removeInputMethodWindow()
@@ -482,7 +454,6 @@ void TopLevelWindowModel::removeInputMethodWindow()
482454 delete m_inputMethodWindow;
483455 m_inputMethodWindow = nullptr;
484456 Q_EMIT inputMethodSurfaceChanged(nullptr);
485− InputMethodManager::instance()->setWindow(nullptr);
486457 }
487458}
488459
@@ -528,6 +499,37 @@ int TopLevelWindowModel::findIndexOf(const unityapi::MirSurfaceInterface *surfac
528499 return -1;
529500}
530501
502+int TopLevelWindowModel::generateId()
503+{
504+ int id = m_nextId;
505+ m_nextId = nextFreeId(nextId(id), id);
506+ return id;
507+}
508+
509+int TopLevelWindowModel::nextId(int id) const
510+{
511+ if (id == m_maxId) {
512+ return id = 1;
513+ } else {
514+ return id + 1;
515+ }
516+}
517+
518+int TopLevelWindowModel::nextFreeId(int candidateId, const int latestId)
519+{
520+ int firstCandidateId = candidateId;
521+
522+ while (indexForId(candidateId) != -1 || candidateId == latestId) {
523+ candidateId = nextId(candidateId);
524+
525+ if (candidateId == firstCandidateId) {
526+ qFatal("TopLevelWindowModel: run out of window ids.");
527+ }
528+ }
529+
530+ return candidateId;
531+}
532+
531533QString TopLevelWindowModel::toString()
532534{
533535 QString str;
@@ -641,19 +643,16 @@ void TopLevelWindowModel::setFocusedWindow(Window *window)
641643 if (window != m_focusedWindow) {
642644 INFO_MSG << "(" << window << ")";
643645
644− m_previousWindow = m_focusedWindow;
646+ Window* previousWindow = m_focusedWindow;
645647
646648 m_focusedWindow = window;
647649 Q_EMIT focusedWindowChanged(m_focusedWindow);
648650
649− if (m_previousWindow && m_previousWindow->focused() && !m_previousWindow->surface()) {
651+ if (previousWindow && previousWindow->focused() && !previousWindow->surface()) {
650652 // do it ourselves. miral doesn't know about this window
651− m_previousWindow->setFocused(false);
653+ previousWindow->setFocused(false);
652654 }
653655 }
654−
655− // Reset
656− m_pendingActivation = false;
657656}
658657
659658unityapi::MirSurfaceInterface* TopLevelWindowModel::inputMethodSurface() const
@@ -697,7 +696,6 @@ void TopLevelWindowModel::move(int from, int to)
697696}
698697void TopLevelWindowModel::onModificationsStarted()
699698{
700− m_surfaceManagerBusy = true;
701699}
702700
703701void TopLevelWindowModel::onModificationsEnded()
@@ -708,7 +706,6 @@ void TopLevelWindowModel::onModificationsEnded()
708706 // reset
709707 m_focusedWindowChanged = false;
710708 m_newlyFocusedWindow = nullptr;
711− m_surfaceManagerBusy = false;
712709}
713710
714711void TopLevelWindowModel::activateTopMostWindowWithoutId(int forbiddenId)
@@ -719,64 +716,6 @@ void TopLevelWindowModel::activateTopMostWindowWithoutId(int forbiddenId)
719716 Window *window = m_windowModel[i].window;
720717 if (window->id() != forbiddenId) {
721718 window->activate();
722− break;
723719 }
724720 }
725721}
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+8−50
@@ -1,6 +1,5 @@
11/*
22 * Copyright (C) 2016-2017 Canonical, Ltd.
3− * Copyright 2019 UBports Foundation
43 *
54 * This program is free software: you can redistribute it and/or modify it under
65 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -19,7 +18,6 @@
1918#define TOPLEVELWINDOWMODEL_H
2019
2120#include <QAbstractListModel>
22−#include <QAtomicInteger>
2321#include <QLoggingCategory>
2422
2523#include "WindowManagerGlobal.h"
@@ -88,28 +86,7 @@ class WINDOWMANAGERQML_EXPORT TopLevelWindowModel : public QAbstractListModel
8886 The id to be used on the next entry created
8987 Useful for tests
9088 */
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)
89+ Q_PROPERTY(int nextId READ nextId NOTIFY nextIdChanged)
11390
11491public:
11592 /**
@@ -145,7 +122,7 @@ public:
145122 unity::shell::application::SurfaceManagerInterface *surfaceManager() const { return m_surfaceManager; }
146123 void setSurfaceManager(unity::shell::application::SurfaceManagerInterface*);
147124
148− int nextId() const { return m_nextId.load(); }
125+ int nextId() const { return m_nextId; }
149126
150127public:
151128 /**
@@ -187,19 +164,6 @@ public:
187164 */
188165 Q_INVOKABLE void raiseId(int id);
189166
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−
203167Q_SIGNALS:
204168 void countChanged();
205169 void inputMethodSurfaceChanged(unity::shell::application::MirSurfaceInterface* inputMethodSurface);
@@ -214,9 +178,7 @@ Q_SIGNALS:
214178 */
215179 void listChanged();
216180
217− void closedAllWindows();
218−
219− void rootFocusChanged();
181+ void nextIdChanged();
220182
221183private Q_SLOTS:
222184 void onSurfaceCreated(unity::shell::application::MirSurfaceInterface *surface);
@@ -263,8 +225,6 @@ private:
263225 void activateTopMostWindowWithoutId(int forbiddenId);
264226
265227 Window *createWindow(unity::shell::application::MirSurfaceInterface *surface);
266− Window *createWindowWithId(unity::shell::application::MirSurfaceInterface *surface, int id);
267− Window *createNullWindow();
268228
269229 struct ModelEntry {
270230 ModelEntry() {}
@@ -279,15 +239,15 @@ private:
279239 QVector<ModelEntry> m_windowModel;
280240 Window* m_inputMethodWindow{nullptr};
281241 Window* m_focusedWindow{nullptr};
282− Window* m_nullWindow;
283− Window* m_previousWindow{nullptr};
284− bool m_pendingActivation;
285242
286− QAtomicInteger<int> m_nextId{1};
243+ int m_nextId{1};
244+ // Just something big enough that we don't risk running out of unused id numbers.
245+ // Not sure if QML int type supports something close to std::numeric_limits<int>::max() and
246+ // there's no reason to try out its limits.
247+ static const int m_maxId{1000000};
287248
288249 unity::shell::application::ApplicationManagerInterface* m_applicationManager{nullptr};
289250 unity::shell::application::SurfaceManagerInterface *m_surfaceManager{nullptr};
290− bool m_surfaceManagerBusy;
291251
292252 enum ModelState {
293253 IdleState,
@@ -301,8 +261,6 @@ private:
301261 // Valid between modificationsStarted and modificationsEnded
302262 bool m_focusedWindowChanged{false};
303263 Window *m_newlyFocusedWindow{nullptr};
304−
305− bool m_closingAllApps{false};
306264};
307265
308266#endif // TOPLEVELWINDOWMODEL_H
plugins/WindowManager/Window.cpp−9
@@ -27,7 +27,6 @@ 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__
3130
3231Window::Window(int id, QObject *parent)
3332 : QObject(parent)
@@ -185,15 +184,7 @@ void Window::setSurface(unityapi::MirSurfaceInterface *surface)
185184 setSurface(nullptr);
186185 });
187186
188− // Surface should never be focused at this point!
189− if (m_surface->focused()) {
190− WARNING_MSG << "Inital surface is focused!";
191− }
192−
193187 // bring it up to speed
194− if (m_focused) {
195− m_surface->activate();
196− }
197188 if (m_positionRequested) {
198189 m_surface->setRequestedPosition(m_requestedPosition);
199190 }
plugins/WindowManager/WindowManagerPlugin.cpp−9
@@ -20,23 +20,14 @@
2020#include "TopLevelWindowModel.h"
2121#include "Window.h"
2222#include "WindowMargins.h"
23−#include "InputMethodManager.h"
2423
2524#include <QtQml>
2625
27−QObject *inputMethodManager(QQmlEngine *engine, QJSEngine *scriptEngine)
28−{
29− Q_UNUSED(engine)
30− Q_UNUSED(scriptEngine)
31− return InputMethodManager::instance();
32−}
33−
3426void WindowManagerPlugin::registerTypes(const char *uri)
3527{
3628 qmlRegisterType<AvailableDesktopArea>(uri, 1, 0, "AvailableDesktopArea");
3729 qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel");
3830 qmlRegisterType<WindowMargins>(uri, 1, 0, "WindowMargins");
39− qmlRegisterSingletonType<InputMethodManager>(uri, 1, 0, "InputMethodManager", inputMethodManager);
4031
4132 qRegisterMetaType<Window*>("Window*");
4233
plugins/Wizard/CMakeLists.txt+2−5
@@ -10,13 +10,10 @@ add_library(Wizard-qml MODULE
1010 timezonemodel.cpp
1111 Status.cpp
1212 keyboardLayoutsModel.cpp
13− Changelog.cpp
1413)
1514
16−target_link_libraries(Wizard-qml
17− Qt5::DBus Qt5::Qml
18− ${GD3_LDFLAGS} ${GLIB_LDFLAGS} ${GEONAMES_LDFLAGS}
19−)
15+qt5_use_modules(Wizard-qml DBus Qml)
16+target_link_libraries(Wizard-qml ${GD3_LDFLAGS} ${GLIB_LDFLAGS} ${GEONAMES_LDFLAGS})
2017add_unity8_plugin(Wizard 0.1 Wizard TARGETS Wizard-qml)
2118
2219set(POLKIT_LIB_DIR "${CMAKE_INSTALL_LOCALSTATEDIR}/lib/polkit-1")
plugins/Wizard/Changelog.cppdeleted−58
@@ -1,58 +0,0 @@
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.hdeleted−52
@@ -1,52 +0,0 @@
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+5−6
@@ -46,7 +46,9 @@ PageList::PageList(QObject *parent)
4646 QSet<QString> disabledPages;
4747 QStringList dataDirs;
4848
49− if (!isRunningInstalled() && getenv("WIZARD_TESTING") == nullptr) {
49+ if (getenv("WIZARD_TESTING") != nullptr) {
50+ dataDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
51+ } else if (!isRunningInstalled()) {
5052 dataDirs << qmlDirectory();
5153 } else {
5254 dataDirs = shellDataDirs();
@@ -71,11 +73,8 @@ PageList::PageList(QObject *parent)
7173 // If there was a system update installed, skip until the last page to just greet the user
7274 QSettings settings;
7375 if (settings.value(QStringLiteral("Wizard/SkipUntilFinishedPage")).toBool()) {
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− }
76+ while (m_pages.count() > 1) {
77+ m_pages.erase(m_pages.begin());
7978 }
8079
8180 // ... and reset it again for the next run
plugins/Wizard/System.cpp+7−69
@@ -1,5 +1,4 @@
11/*
2− * Copyright (C) 2018 The UBports project
32 * Copyright (C) 2014-2016 Canonical Ltd.
43 *
54 * This program is free software: you can redistribute it and/or modify it
@@ -47,93 +46,29 @@ QString System::wizardEnabledPath()
4746 return QDir::home().filePath(QStringLiteral(".config/ubuntu-system-settings/wizard-has-run"));
4847}
4948
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−
6849bool System::wizardEnabled() const
6950{
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();
51+ return !QFile::exists(wizardEnabledPath());
10452}
10553
10654void System::setWizardEnabled(bool enabled)
10755{
108− if (wizardEnabled() == enabled && !isUpdate())
56+ if (wizardEnabled() == enabled)
10957 return;
11058
11159 if (enabled) {
11260 QFile::remove(wizardEnabledPath());
11361 } else {
11462 QDir(wizardEnabledPath()).mkpath(QStringLiteral(".."));
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− }
63+ QFile(wizardEnabledPath()).open(QIODevice::WriteOnly);
12764 m_fsWatcher.addPath(wizardEnabledPath());
12865 Q_EMIT wizardEnabledChanged();
129− Q_EMIT isUpdateChanged();
13066 }
13167}
13268
13369void System::watcherFileChanged()
13470{
13571 Q_EMIT wizardEnabledChanged();
136− Q_EMIT isUpdateChanged();
13772 m_fsWatcher.removePath(wizardEnabledPath());
13873}
13974
@@ -168,10 +103,13 @@ void System::updateSessionLocale(const QString &locale)
168103
169104 // Restart bits of the session to pick up new language.
170105 QProcess::startDetached(QStringLiteral("sh -c \"initctl emit indicator-services-end; \
106+ initctl stop scope-registry; \
107+ initctl stop smart-scopes-proxy; \
171108 initctl emit --no-wait indicator-services-start; \
172109 initctl restart --no-wait ubuntu-location-service-trust-stored; \
173110 initctl restart --no-wait maliit-server; \
174− initctl restart --no-wait indicator-messages"));
111+ initctl restart --no-wait indicator-messages; \
112+ initctl restart --no-wait unity8-dash\""));
175113}
176114
177115void System::skipUntilFinishedPage()
plugins/Wizard/System.h−17
@@ -1,5 +1,4 @@
11/*
2− * Copyright (C) 2018 The UBports project
32 * Copyright (C) 2014-2016 Canonical Ltd.
43 *
54 * This program is free software: you can redistribute it and/or modify it
@@ -19,7 +18,6 @@
1918#define WIZARD_SYSTEM_H
2019
2120#include <QFileSystemWatcher>
22−#include <QVersionNumber>
2321#include <QObject>
2422#include <QString>
2523
@@ -27,21 +25,12 @@ class System : public QObject
2725{
2826 Q_OBJECT
2927 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)
3228
3329public:
3430 System();
3531 ~System() = default;
3632
37− /**
38− * Checks whether the wizard is enabled for first-run or otherwise.
39− */
4033 bool wizardEnabled() const;
41−
42− QString version() const;
43− bool isUpdate() const;
44−
4534 void setWizardEnabled(bool enabled);
4635
4736public Q_SLOTS:
@@ -53,8 +42,6 @@ public Q_SLOTS:
5342
5443Q_SIGNALS:
5544 void wizardEnabledChanged();
56− void versionChanged();
57− void isUpdateChanged();
5845
5946private Q_SLOTS:
6047 void watcherFileChanged();
@@ -63,11 +50,7 @@ private:
6350 Q_DISABLE_COPY(System)
6451
6552 static QString wizardEnabledPath();
66− static QString currentFrameworkPath();
6753 static void setSessionVariable(const QString &variable, const QString &value);
68− static QString readCurrentFramework();
69− static QString readWizardEnabled();
70− static bool wizardPathExists();
7154
7255 QFileSystemWatcher m_fsWatcher;
7356};
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−target_link_libraries(WizardUtils-qml Qt5::DBus Qt5::Qml Qt5::Quick)
23+qt5_use_modules(WizardUtils-qml DBus Qml 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,7 +20,6 @@
2020#include "timezonemodel.h"
2121#include "LocalePlugin.h"
2222#include "Status.h"
23−#include "Changelog.h"
2423#include "keyboardLayoutsModel.h"
2524
2625#include <QtQml/qqml.h>
@@ -31,7 +30,6 @@ void WizardPlugin::registerTypes(const char *uri)
3130 qmlRegisterType<PageList>(uri, 0, 1, "PageList");
3231 qmlRegisterSingletonType<System>(uri, 0, 1, "System", [](QQmlEngine*, QJSEngine*) -> QObject* { return new System; });
3332 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; });
3533 qmlRegisterType<TimeZoneLocationModel>(uri, 0, 1, "TimeZoneModel");
3634 qmlRegisterType<KeyboardLayoutsModel>(uri, 0, 1, "KeyboardLayoutsModel");
3735 qmlRegisterType<LocalePlugin>(uri, 0, 1, "LocalePlugin");
plugins/Wizard/test.shnew file+18
@@ -0,0 +1,18 @@
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,7 +27,6 @@ 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)
3130
3231public:
3332 explicit TimeZoneLocationModel(QObject *parent = nullptr);
@@ -42,6 +41,7 @@ public:
4241 LatitudeRole,
4342 LongitudeRole
4443 };
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+309−184
@@ -6,62 +6,60 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity8\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"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2017-03-21 10:58+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"
1614"MIME-Version: 1.0\n"
1715"Content-Type: text/plain; charset=UTF-8\n"
1816"Content-Transfer-Encoding: 8bit\n"
1917"Plural-Forms: nplurals=2; plural=n != 1;\n"
20−"X-Generator: Weblate 3.11.3\n"
21−"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
18+"X-Launchpad-Export-Date: 2017-03-24 06:12+0000\n"
19+"X-Generator: Launchpad (build 18334)\n"
2220
23−#: plugins/LightDM/Greeter.cpp:199
21+#: plugins/LightDM/Greeter.cpp:188
2422msgid "Password: "
25−msgstr ""
23+msgstr "Cuumita "
2624
27−#: plugins/LightDM/Greeter.cpp:214
25+#: plugins/LightDM/Greeter.cpp:203
2826msgid "Username"
2927msgstr ""
3028
31−#: plugins/LightDM/Greeter.cpp:258
29+#: plugins/LightDM/Greeter.cpp:242
3230msgid "Failed to authenticate"
3331msgstr ""
3432
35−#: plugins/LightDM/Greeter.cpp:260
33+#: plugins/LightDM/Greeter.cpp:244
3634msgid "Invalid password, please try again"
3735msgstr ""
3836
39−#: plugins/LightDM/Greeter.cpp:270
37+#: plugins/LightDM/Greeter.cpp:254
4038msgid "Log In"
4139msgstr ""
4240
43−#: plugins/LightDM/Greeter.cpp:270
41+#: plugins/LightDM/Greeter.cpp:254
4442msgid "Retry"
4543msgstr "Qagis"
4644
47−#: plugins/LightDM/UsersModel.cpp:157
45+#: plugins/LightDM/UsersModel.cpp:152
4846msgid "Login"
4947msgstr ""
5048
51−#: plugins/LightDM/UsersModel.cpp:165
49+#: plugins/LightDM/UsersModel.cpp:160
5250msgid "Guest Session"
5351msgstr ""
5452
55−#: plugins/Unity/Launcher/launcheritem.cpp:48
56−#: plugins/Unity/Launcher/launcheritem.cpp:122
53+#: plugins/Unity/Launcher/launcheritem.cpp:49
54+#: plugins/Unity/Launcher/launcheritem.cpp:123
5755msgid "Pin shortcut"
5856msgstr ""
5957
60−#: plugins/Unity/Launcher/launcheritem.cpp:54
58+#: plugins/Unity/Launcher/launcheritem.cpp:55
6159msgid "Quit"
6260msgstr "Kat"
6361
64−#: plugins/Unity/Launcher/launcheritem.cpp:122
62+#: plugins/Unity/Launcher/launcheritem.cpp:123
6563msgid "Unpin shortcut"
6664msgstr ""
6765
@@ -84,8 +82,9 @@ msgctxt "Button: Log out from the system"
8482msgid "Log Out"
8583msgstr "Eweq"
8684
87−#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
88−#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
85+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:264
86+#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:222
87+#: qml/Wizard/Pages/passcode-confirm.qml:32
8988#: qml/Wizard/Pages/passcode-set.qml:32
9089msgid "Cancel"
9190msgstr "Bayis"
@@ -107,37 +106,33 @@ msgstr "Maleey"
107106msgid "Yes"
108107msgstr "Yeey"
109108
110−#: qml/Components/Dialogs.qml:243
109+#: qml/Components/Dialogs.qml:239
111110msgctxt "Title: Power off/Restart dialog"
112111msgid "Power"
113112msgstr "Cayla"
114113
115−#: qml/Components/Dialogs.qml:244
114+#: qml/Components/Dialogs.qml:240
116115msgid ""
117116"Are you sure you would like\n"
118117"to power off?"
119118msgstr "Timmi haytuh digga maay litoo?"
120119
121−#: qml/Components/Dialogs.qml:248
120+#: qml/Components/Dialogs.qml:244
122121msgctxt "Button: Power off the system"
123122msgid "Power off"
124123msgstr "Timmi hayis"
125124
126−#: qml/Components/Dialogs.qml:263
125+#: qml/Components/Dialogs.qml:255
127126msgctxt "Button: Restart the system"
128127msgid "Restart"
129128msgstr "Wadir-qimbis"
130129
131−#: qml/Components/Dialogs.qml:276
132−msgid "Screenshot"
133−msgstr ""
134−
135130#: qml/Components/KeyboardShortcutsOverlay.qml:41
136131msgid "Keyboard Shortcuts"
137132msgstr ""
138133
139134#: qml/Components/KeyboardShortcutsOverlay.qml:55
140−msgid "Lomiri"
135+msgid "Unity 8"
141136msgstr ""
142137
143138#: qml/Components/KeyboardShortcutsOverlay.qml:62
@@ -172,131 +167,135 @@ msgstr ""
172167msgid "Switches to previous keyboard layout."
173168msgstr ""
174169
175−#: qml/Components/KeyboardShortcutsOverlay.qml:114
176−msgid "Ctrl + Alt + T"
170+#: qml/Components/KeyboardShortcutsOverlay.qml:118
171+msgid "Launcher"
177172msgstr ""
178173
179−#: qml/Components/KeyboardShortcutsOverlay.qml:119
180−msgid "Starts the Terminal application."
174+#: qml/Components/KeyboardShortcutsOverlay.qml:125
175+msgid "Super (Hold)"
181176msgstr ""
182177
183−#: qml/Components/KeyboardShortcutsOverlay.qml:131
184−msgid "Launcher"
178+#: qml/Components/KeyboardShortcutsOverlay.qml:130
179+msgid "Opens the launcher, displays shortcuts."
185180msgstr ""
186181
187182#: qml/Components/KeyboardShortcutsOverlay.qml:138
188−msgid "Super (Hold)"
183+msgid "Alt + F1"
189184msgstr ""
190185
191186#: qml/Components/KeyboardShortcutsOverlay.qml:143
192−msgid "Opens the launcher, displays shortcuts."
187+msgid "Opens launcher keyboard navigation mode."
193188msgstr ""
194189
195190#: qml/Components/KeyboardShortcutsOverlay.qml:151
196−msgid "Alt + F1"
191+msgid "Super + Tab"
197192msgstr ""
198193
199194#: qml/Components/KeyboardShortcutsOverlay.qml:156
200−msgid "Opens launcher keyboard navigation mode."
195+msgid "Switches applications via the launcher."
201196msgstr ""
202197
203198#: qml/Components/KeyboardShortcutsOverlay.qml:164
204−msgid "Super + Tab"
199+msgid "Super + 1 to 0"
205200msgstr ""
206201
207202#: qml/Components/KeyboardShortcutsOverlay.qml:169
208−msgid "Switches applications via the launcher."
203+msgid "Same as clicking on a launcher icon."
209204msgstr ""
210205
211206#: qml/Components/KeyboardShortcutsOverlay.qml:177
212−msgid "Super + 1 to 0"
207+msgid "Super + A"
213208msgstr ""
214209
215210#: qml/Components/KeyboardShortcutsOverlay.qml:182
216−msgid "Same as clicking on a launcher icon."
211+msgid "Opens the Application Drawer."
217212msgstr ""
218213
219−#: qml/Components/KeyboardShortcutsOverlay.qml:190
220−msgid "Super + A"
214+#: qml/Components/KeyboardShortcutsOverlay.qml:194
215+msgid "Scopes"
221216msgstr ""
222217
223−#: qml/Components/KeyboardShortcutsOverlay.qml:195
224−msgid "Opens the Application Drawer."
218+#: qml/Components/KeyboardShortcutsOverlay.qml:201
219+msgid "Super (Tap)"
225220msgstr ""
226221
227−#: qml/Components/KeyboardShortcutsOverlay.qml:235
222+#: qml/Components/KeyboardShortcutsOverlay.qml:206
223+msgid "Opens the Scopes home."
224+msgstr ""
225+
226+#: qml/Components/KeyboardShortcutsOverlay.qml:222
228227msgid "Switching"
229228msgstr ""
230229
231−#: qml/Components/KeyboardShortcutsOverlay.qml:242
230+#: qml/Components/KeyboardShortcutsOverlay.qml:229
232231msgid "Alt + Tab"
233232msgstr ""
234233
235−#: qml/Components/KeyboardShortcutsOverlay.qml:247
234+#: qml/Components/KeyboardShortcutsOverlay.qml:234
236235msgid "Switches between applications."
237236msgstr ""
238237
239−#: qml/Components/KeyboardShortcutsOverlay.qml:255
238+#: qml/Components/KeyboardShortcutsOverlay.qml:242
240239msgid "Super + W"
241240msgstr ""
242241
243−#: qml/Components/KeyboardShortcutsOverlay.qml:260
242+#: qml/Components/KeyboardShortcutsOverlay.qml:247
244243msgid "Opens the desktop spread."
245244msgstr ""
246245
247−#: qml/Components/KeyboardShortcutsOverlay.qml:268
246+#: qml/Components/KeyboardShortcutsOverlay.qml:255
248247msgid "Cursor Left or Right"
249248msgstr ""
250249
251−#: qml/Components/KeyboardShortcutsOverlay.qml:273
250+#: qml/Components/KeyboardShortcutsOverlay.qml:260
252251msgid "Moves the focus."
253252msgstr ""
254253
255−#: qml/Components/KeyboardShortcutsOverlay.qml:285
254+#: qml/Components/KeyboardShortcutsOverlay.qml:272
256255msgid "Windows"
257256msgstr ""
258257
259−#: qml/Components/KeyboardShortcutsOverlay.qml:292
258+#: qml/Components/KeyboardShortcutsOverlay.qml:279
260259msgid "Ctrl + Super + D"
261260msgstr ""
262261
263−#: qml/Components/KeyboardShortcutsOverlay.qml:297
262+#: qml/Components/KeyboardShortcutsOverlay.qml:284
264263msgid "Minimizes all windows."
265264msgstr ""
266265
267−#: qml/Components/KeyboardShortcutsOverlay.qml:305
266+#: qml/Components/KeyboardShortcutsOverlay.qml:292
268267msgid "Ctrl + Super + Up"
269268msgstr ""
270269
271−#: qml/Components/KeyboardShortcutsOverlay.qml:310
270+#: qml/Components/KeyboardShortcutsOverlay.qml:297
272271msgid "Maximizes the current window."
273272msgstr ""
274273
275−#: qml/Components/KeyboardShortcutsOverlay.qml:318
274+#: qml/Components/KeyboardShortcutsOverlay.qml:305
276275msgid "Ctrl + Super + Down"
277276msgstr ""
278277
279−#: qml/Components/KeyboardShortcutsOverlay.qml:323
278+#: qml/Components/KeyboardShortcutsOverlay.qml:310
280279msgid "Minimizes or restores the current window."
281280msgstr ""
282281
283−#: qml/Components/KeyboardShortcutsOverlay.qml:331
282+#: qml/Components/KeyboardShortcutsOverlay.qml:318
284283msgid "Ctrl + Super + Left or Right"
285284msgstr ""
286285
287−#: qml/Components/KeyboardShortcutsOverlay.qml:336
286+#: qml/Components/KeyboardShortcutsOverlay.qml:323
288287msgid "Semi-maximizes the current window."
289288msgstr ""
290289
291−#: qml/Components/KeyboardShortcutsOverlay.qml:344
290+#: qml/Components/KeyboardShortcutsOverlay.qml:331
292291msgid "Alt + F4"
293292msgstr ""
294293
295−#: qml/Components/KeyboardShortcutsOverlay.qml:349
294+#: qml/Components/KeyboardShortcutsOverlay.qml:336
296295msgid "Closes the current window."
297296msgstr ""
298297
299−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
298+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:242
300299msgid "Return to Call"
301300msgstr "Seecol gacis"
302301
@@ -370,6 +369,103 @@ msgstr ""
370369msgid "Find more settings in the system settings."
371370msgstr ""
372371
372+#: qml/Dash/DashPageHeader.qml:361
373+msgctxt "Button: Open the Ubuntu Store"
374+msgid "Store"
375+msgstr ""
376+
377+#: qml/Dash/DashPageHeader.qml:368
378+msgctxt "Button: Start a search in the current dash scope"
379+msgid "Search"
380+msgstr "Goranto"
381+
382+#: qml/Dash/DashPageHeader.qml:378
383+msgctxt "Button: Show the current dash scope settings"
384+msgid "Settings"
385+msgstr "Massosu"
386+
387+#: qml/Dash/DashPageHeader.qml:385
388+msgid "Remove from Favorites"
389+msgstr ""
390+
391+#: qml/Dash/DashPageHeader.qml:385
392+msgid "Add to Favorites"
393+msgstr ""
394+
395+#: qml/Dash/FiltersPopover.qml:61
396+msgid "Refine your results"
397+msgstr ""
398+
399+#: qml/Dash/FiltersPopover.qml:70
400+msgid "Reset"
401+msgstr ""
402+
403+#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
404+msgid "Show less"
405+msgstr ""
406+
407+#: qml/Dash/GenericScopeView.qml:547
408+msgid "Show all"
409+msgstr ""
410+
411+#: qml/Dash/GenericScopeView.qml:578
412+msgctxt "Label: Hint for dash search line edit"
413+msgid "Search"
414+msgstr "Goranto"
415+
416+#: qml/Dash/PageHeaderExtraPanel.qml:67
417+msgid "Recent Searches"
418+msgstr ""
419+
420+#: qml/Dash/PageHeaderExtraPanel.qml:78
421+msgid "Clear All"
422+msgstr ""
423+
424+#: qml/Dash/Previews/PreviewActionCombo.qml:36
425+msgid "More..."
426+msgstr ""
427+
428+#: qml/Dash/Previews/PreviewActionCombo.qml:36
429+msgid "Less..."
430+msgstr ""
431+
432+#: qml/Dash/Previews/PreviewCommentInput.qml:83
433+#: qml/Dash/Previews/PreviewRatingInput.qml:202
434+msgid "Send"
435+msgstr "Rub"
436+
437+#: qml/Dash/Previews/PreviewRatingInput.qml:109
438+msgid "Rate this"
439+msgstr ""
440+
441+#: qml/Dash/Previews/PreviewRatingInput.qml:184
442+msgid "Add a review"
443+msgstr ""
444+
445+#: qml/Dash/PullToRefreshScopeStyle.qml:56
446+msgid "Pull to refresh…"
447+msgstr ""
448+
449+#: qml/Dash/PullToRefreshScopeStyle.qml:61
450+msgid "Release to refresh…"
451+msgstr ""
452+
453+#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
454+msgid "Enable location data"
455+msgstr ""
456+
457+#: qml/Dash/ScopesList.qml:146
458+msgid "Manage"
459+msgstr ""
460+
461+#: qml/Dash/ScopesList.qml:187
462+msgid "Home"
463+msgstr "Dabqi"
464+
465+#: qml/Dash/ScopesList.qml:188
466+msgid "Also installed"
467+msgstr ""
468+
373469#: qml/Greeter/CoverPage.qml:127
374470msgid "Unlock"
375471msgstr ""
@@ -393,23 +489,19 @@ msgid_plural "Please wait %1 minutes and then try again…"
393489msgstr[0] "Maganak %1 minit qambaalaay, kaadu gabbat"
394490msgstr[1] "Maganak %1 minit qambaalaay, kaadu gabbat"
395491
396−#: qml/Greeter/Greeter.qml:550
492+#: qml/Greeter/Greeter.qml:561
397493msgid "Try again"
398494msgstr ""
399495
400−#: qml/Greeter/Greeter.qml:551
401−#, fuzzy
402−#| msgid "Enter passphrase"
496+#: qml/Greeter/Greeter.qml:562
403497msgid "Enter passphrase to unlock"
404−msgstr "Tatur-maxco culus"
498+msgstr ""
405499
406−#: qml/Greeter/Greeter.qml:552
407−#, fuzzy
408−#| msgid "Enter passcode"
500+#: qml/Greeter/Greeter.qml:563
409501msgid "Enter passcode to unlock"
410−msgstr "Tatur-mudenta culus"
502+msgstr ""
411503
412−#: qml/Greeter/NarrowView.qml:235
504+#: qml/Greeter/NarrowView.qml:242
413505msgid "Emergency"
414506msgstr ""
415507
@@ -421,23 +513,21 @@ msgstr ""
421513msgid "Passcode"
422514msgstr ""
423515
424−#: qml/Greeter/SessionsList.qml:124
516+#: qml/Greeter/SessionsList.qml:122
425517msgid "Select desktop environment"
426518msgstr ""
427519
428−#: qml/Launcher/Drawer.qml:250
429−#, fuzzy
430−#| msgctxt "Button: Start a search in the current dash scope"
431−#| msgid "Search"
520+#: qml/Launcher/Drawer.qml:93
432521msgid "Search…"
433−msgstr "Goranto"
522+msgstr ""
434523
435−#: qml/Launcher/PullToRefreshScopeStyle.qml:56
436−msgid "Pull to refresh…"
524+#: qml/Launcher/Drawer.qml:128
525+msgctxt "Apps sorted alphabetically"
526+msgid "A-Z"
437527msgstr ""
438528
439−#: qml/Launcher/PullToRefreshScopeStyle.qml:61
440−msgid "Release to refresh…"
529+#: qml/Launcher/MoreAppsHeader.qml:55
530+msgid "More apps in the store"
441531msgstr ""
442532
443533#: qml/Notifications/NotificationMenuItemFactory.qml:124
@@ -528,20 +618,13 @@ msgid "Call back"
528618msgstr ""
529619
530620#: qml/Panel/PanelMenuPage.qml:92
531−#, fuzzy
532−#| msgctxt "Button: Go back one page in the Wizard"
533−#| msgid "Back"
534621msgid "Back"
535−msgstr "Derre"
622+msgstr ""
536623
537624#: qml/Stage/SideStage.qml:76
538625msgid "Drag using 3 fingers any application from one window to the other"
539626msgstr ""
540627
541−#: qml/Stage/Stage.qml:671
542−msgid "No running apps"
543−msgstr ""
544−
545628#: qml/Tutorial/TutorialLeftLong.qml:49
546629msgid "Long swipe from the left edge to open the Application Drawer"
547630msgstr ""
@@ -550,11 +633,11 @@ msgstr ""
550633msgid "Short swipe from the left edge to open the launcher"
551634msgstr ""
552635
553−#: qml/Tutorial/TutorialRight.qml:54
636+#: qml/Tutorial/TutorialRight.qml:55
554637msgid "Push your mouse against the right edge to view your open apps"
555638msgstr ""
556639
557−#: qml/Tutorial/TutorialRight.qml:55
640+#: qml/Tutorial/TutorialRight.qml:56
558641msgid "Swipe from the right edge to view your open apps"
559642msgstr ""
560643
@@ -562,41 +645,25 @@ msgstr ""
562645msgid "Swipe from the top edge to access notifications and quick settings"
563646msgstr ""
564647
565−#: qml/Wizard/Page.qml:59
648+#: qml/Wizard/Page.qml:54
566649msgctxt "Button: Go back one page in the Wizard"
567650msgid "Back"
568651msgstr "Derre"
569652
570−#: qml/Wizard/Pages/10-welcome.qml:29
653+#: qml/Wizard/Pages/10-welcome.qml:28
571654msgid "Language"
572655msgstr ""
573656
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
657+#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
658+#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
659+#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
660+#: qml/Wizard/Pages/70-passwd-type.qml:145
661+#: qml/Wizard/Pages/75-report-check.qml:84
662+#: qml/Wizard/Pages/passcode-desktop.qml:142
663+#: qml/Wizard/Pages/password-set.qml:142
581664msgid "Next"
582665msgstr ""
583666
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−
600667#: qml/Wizard/Pages/20-keyboard.qml:31
601668msgid "Select Keyboard"
602669msgstr ""
@@ -609,8 +676,8 @@ msgstr ""
609676msgid "Keyboard layout"
610677msgstr ""
611678
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
679+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
680+#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
614681#: qml/Wizard/Pages/sim.qml:101
615682msgid "Skip"
616683msgstr "Kaqit"
@@ -619,23 +686,55 @@ msgstr "Kaqit"
619686msgid "Connect to Wi‑Fi"
620687msgstr ""
621688
622−#: qml/Wizard/Pages/30-wifi.qml:139
689+#: qml/Wizard/Pages/30-wifi.qml:132
623690msgid "Connected"
624691msgstr ""
625692
626−#: qml/Wizard/Pages/30-wifi.qml:172
693+#: qml/Wizard/Pages/30-wifi.qml:165
627694msgid "Available Wi-Fi networks"
628695msgstr ""
629696
630−#: qml/Wizard/Pages/30-wifi.qml:173
697+#: qml/Wizard/Pages/30-wifi.qml:166
631698msgid "No available Wi-Fi networks"
632699msgstr ""
633700
701+#: qml/Wizard/Pages/40-location.qml:27
702+msgid "Location Services"
703+msgstr ""
704+
705+#: qml/Wizard/Pages/40-location.qml:83
706+msgid ""
707+"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
708+"(recommended)"
709+msgstr ""
710+
711+#: qml/Wizard/Pages/40-location.qml:105
712+#, qt-format
713+msgid "By selecting this option you agree to the Nokia HERE %1."
714+msgstr ""
715+
716+#: qml/Wizard/Pages/40-location.qml:106
717+msgctxt "part of: Nokia HERE terms and conditions"
718+msgid "terms and conditions"
719+msgstr ""
720+
721+#: qml/Wizard/Pages/40-location.qml:160
722+msgid "GPS only"
723+msgstr ""
724+
725+#: qml/Wizard/Pages/40-location.qml:214
726+msgid "Don't use my location"
727+msgstr ""
728+
729+#: qml/Wizard/Pages/40-location.qml:260
730+msgid "You can change it later in System Settings."
731+msgstr ""
732+
634733#: qml/Wizard/Pages/50-timezone.qml:30
635734msgid "Time Zone"
636735msgstr ""
637736
638−#: qml/Wizard/Pages/50-timezone.qml:183
737+#: qml/Wizard/Pages/50-timezone.qml:182
639738msgid "Enter your city"
640739msgstr ""
641740
@@ -643,7 +742,7 @@ msgstr ""
643742msgid "Personalize Your Device"
644743msgstr ""
645744
646−#: qml/Wizard/Pages/60-account.qml:54
745+#: qml/Wizard/Pages/60-account.qml:48
647746msgid "Preferred Name"
648747msgstr ""
649748
@@ -651,72 +750,110 @@ msgstr ""
651750msgid "Lock Screen"
652751msgstr ""
653752
654−#: qml/Wizard/Pages/70-passwd-type.qml:103
753+#: qml/Wizard/Pages/70-passwd-type.qml:102
655754msgctxt "Label: Type of security method"
656755msgid "Create new password"
657756msgstr ""
658757
659−#: qml/Wizard/Pages/70-passwd-type.qml:105
758+#: qml/Wizard/Pages/70-passwd-type.qml:104
660759msgctxt "Label: Type of security method"
661760msgid "Create passcode (numbers only)"
662761msgstr ""
663762
664−#: qml/Wizard/Pages/70-passwd-type.qml:107
763+#: qml/Wizard/Pages/70-passwd-type.qml:106
665764msgctxt "Label: Type of security method"
666765msgid "No lock code"
667766msgstr ""
668767
669−#: qml/Wizard/Pages/79-system-update.qml:28
768+#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
769+msgid "Privacy Policy"
770+msgstr ""
771+
772+#: qml/Wizard/Pages/75-report-check.qml:26
773+msgid "Help Us Improve"
774+msgstr ""
775+
776+#: qml/Wizard/Pages/75-report-check.qml:59
777+msgid "Improve system performance by sending us crashes and error reports."
778+msgstr ""
779+
780+#: qml/Wizard/Pages/75-report-check.qml:60
781+msgid "Privacy policy"
782+msgstr ""
783+
784+#: qml/Wizard/Pages/77-system-update.qml:28
670785msgid "Update Device"
671786msgstr ""
672787
673−#: qml/Wizard/Pages/79-system-update.qml:55
788+#: qml/Wizard/Pages/77-system-update.qml:55
674789msgid ""
675790"There is a system update available and ready to install. Afterwards, the "
676791"device will automatically restart."
677792msgstr ""
678793
679−#: qml/Wizard/Pages/79-system-update.qml:76
794+#: qml/Wizard/Pages/77-system-update.qml:76
680795msgctxt "string identifying name of the update"
681−msgid "Ubuntu Touch system"
796+msgid "Ubuntu system"
682797msgstr ""
683798
684−#: qml/Wizard/Pages/79-system-update.qml:83
799+#: qml/Wizard/Pages/77-system-update.qml:83
685800#, qt-format
686801msgctxt "version of the system update"
687802msgid "Version %1"
688803msgstr ""
689804
690−#: qml/Wizard/Pages/79-system-update.qml:95
805+#: qml/Wizard/Pages/77-system-update.qml:102
691806msgid "This could take a few minutes..."
692807msgstr ""
693808
694−#: qml/Wizard/Pages/79-system-update.qml:109
809+#: qml/Wizard/Pages/77-system-update.qml:116
695810msgid "Install and restart now"
696811msgstr ""
697812
698−#: qml/Wizard/Pages/80-finished.qml:91
699−msgid "Welcome Back"
700−msgstr ""
701−
702−#: qml/Wizard/Pages/80-finished.qml:91
813+#: qml/Wizard/Pages/80-finished.qml:89
703814msgid "Welcome to Ubuntu"
704815msgstr ""
705816
706−#: qml/Wizard/Pages/80-finished.qml:106
817+#: qml/Wizard/Pages/80-finished.qml:104
707818msgid "You are ready to use your device now"
708819msgstr ""
709820
710−#: qml/Wizard/Pages/80-finished.qml:126
711−msgid "Continue"
712−msgstr "Tatur"
713−
714−#: qml/Wizard/Pages/80-finished.qml:126
821+#: qml/Wizard/Pages/80-finished.qml:124
715822msgid "Get Started"
716823msgstr ""
717824
825+#: qml/Wizard/Pages/here-terms.qml:25
826+msgid "Terms & Conditions"
827+msgstr ""
828+
829+#: qml/Wizard/Pages/here-terms.qml:69
830+msgid "Your device uses positioning technologies provided by HERE."
831+msgstr ""
832+
833+#: qml/Wizard/Pages/here-terms.qml:81
834+msgid ""
835+"To provide you with positioning services and to improve their quality, HERE "
836+"collects information about nearby cell towers and Wi-Fi hotspots around your "
837+"current location whenever your position is being found."
838+msgstr ""
839+
840+#: qml/Wizard/Pages/here-terms.qml:93
841+msgid ""
842+"The information collected is used to analyze the service and to improve the "
843+"use of service, but not to identify you personally."
844+msgstr ""
845+
846+#: qml/Wizard/Pages/here-terms.qml:106
847+#, qt-format
848+msgid "By continuing, you agree to the HERE platform %1 and %2."
849+msgstr ""
850+
851+#: qml/Wizard/Pages/here-terms.qml:107
852+msgid "Service Terms"
853+msgstr ""
854+
718855#: qml/Wizard/Pages/passcode-confirm.qml:43
719−#: qml/Wizard/Pages/passcode-desktop.qml:104
856+#: qml/Wizard/Pages/passcode-desktop.qml:97
720857msgid "Confirm passcode"
721858msgstr ""
722859
@@ -733,24 +870,24 @@ msgstr ""
733870msgid "Lock Screen Passcode"
734871msgstr ""
735872
736−#: qml/Wizard/Pages/passcode-desktop.qml:68
873+#: qml/Wizard/Pages/passcode-desktop.qml:61
737874msgid "Enter 4 numbers to setup your passcode"
738875msgstr ""
739876
740−#: qml/Wizard/Pages/passcode-desktop.qml:84
877+#: qml/Wizard/Pages/passcode-desktop.qml:77
741878#: qml/Wizard/Pages/passcode-set.qml:54
742879msgid "Choose passcode"
743880msgstr ""
744881
745−#: qml/Wizard/Pages/passcode-desktop.qml:139
882+#: qml/Wizard/Pages/passcode-desktop.qml:127
746883msgid "Passcode too short"
747884msgstr ""
748885
749−#: qml/Wizard/Pages/passcode-desktop.qml:141
886+#: qml/Wizard/Pages/passcode-desktop.qml:129
750887msgid "Passcodes match"
751888msgstr ""
752889
753−#: qml/Wizard/Pages/passcode-desktop.qml:143
890+#: qml/Wizard/Pages/passcode-desktop.qml:131
754891msgid "Passcodes do not match"
755892msgstr ""
756893
@@ -762,15 +899,15 @@ msgstr ""
762899msgid "Lock Screen Password"
763900msgstr ""
764901
765−#: qml/Wizard/Pages/password-set.qml:68
902+#: qml/Wizard/Pages/password-set.qml:62
766903msgid "Enter at least 8 characters"
767904msgstr ""
768905
769−#: qml/Wizard/Pages/password-set.qml:80
906+#: qml/Wizard/Pages/password-set.qml:74
770907msgid "Choose password"
771908msgstr ""
772909
773−#: qml/Wizard/Pages/password-set.qml:110
910+#: qml/Wizard/Pages/password-set.qml:104
774911msgid "Confirm password"
775912msgstr ""
776913
@@ -826,28 +963,6 @@ msgstr ""
826963msgid "Very weak password"
827964msgstr ""
828965
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−
851966#~ msgctxt "Title: Reboot/Shut down dialog"
852967#~ msgid "Shut down"
853968#~ msgstr "Bargus"
@@ -863,9 +978,16 @@ msgstr ""
863978#~ msgid "Reboot"
864979#~ msgstr "Wadir-ugus"
865980
981+#, qt-format
866982#~ msgid "Enter %1"
867983#~ msgstr "%1 culus"
868984
985+#~ msgid "Enter passphrase"
986+#~ msgstr "Tatur-maxco culus"
987+
988+#~ msgid "Enter passcode"
989+#~ msgstr "Tatur-mudenta culus"
990+
869991#~ msgctxt "Label: Type of security method"
870992#~ msgid "Swipe"
871993#~ msgstr "Uysuttuc"
@@ -878,3 +1000,6 @@ msgstr ""
8781000
8791001#~ msgid "Let’s get started."
8801002#~ msgstr "Hayya qimbisnay."
1003+
1004+#~ msgid "Continue"
1005+#~ msgstr "Tatur"
po/am.po+357−392
@@ -6,62 +6,60 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity8\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"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2017-03-21 10:58+0000\n"
11+"PO-Revision-Date: 2017-01-26 15:04+0000\n"
12+"Last-Translator: samson <Unknown>\n"
13+"Language-Team: Amharic <am@li.org>\n"
1614"MIME-Version: 1.0\n"
1715"Content-Type: text/plain; charset=UTF-8\n"
1816"Content-Transfer-Encoding: 8bit\n"
1917"Plural-Forms: nplurals=2; plural=n > 1;\n"
20−"X-Generator: Weblate 3.11.3\n"
21−"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
18+"X-Launchpad-Export-Date: 2017-03-24 06:12+0000\n"
19+"X-Generator: Launchpad (build 18334)\n"
2220
23−#: plugins/LightDM/Greeter.cpp:199
21+#: plugins/LightDM/Greeter.cpp:188
2422msgid "Password: "
2523msgstr "የ መግቢያ ቃል: "
2624
27−#: plugins/LightDM/Greeter.cpp:214
25+#: plugins/LightDM/Greeter.cpp:203
2826msgid "Username"
2927msgstr "የ ተጠቃሚ ስም"
3028
31−#: plugins/LightDM/Greeter.cpp:258
29+#: plugins/LightDM/Greeter.cpp:242
3230msgid "Failed to authenticate"
3331msgstr "ማረጋገጥ አልተቻለም"
3432
35−#: plugins/LightDM/Greeter.cpp:260
33+#: plugins/LightDM/Greeter.cpp:244
3634msgid "Invalid password, please try again"
37−msgstr "ዋጋ የሌለው የ መግቢያ ቃል: እባክዎን እንደገና ይሞክሩ"
35+msgstr "እባክዎን እንደገና ይሞክሩ ዋጋ የሌለው የመግቢያ ቃል"
3836
39−#: plugins/LightDM/Greeter.cpp:270
37+#: plugins/LightDM/Greeter.cpp:254
4038msgid "Log In"
4139msgstr "መግቢያ"
4240
43−#: plugins/LightDM/Greeter.cpp:270
41+#: plugins/LightDM/Greeter.cpp:254
4442msgid "Retry"
4543msgstr "እንደገና ይሞክሩ"
4644
47−#: plugins/LightDM/UsersModel.cpp:157
45+#: plugins/LightDM/UsersModel.cpp:152
4846msgid "Login"
4947msgstr "መግቢያ"
5048
51−#: plugins/LightDM/UsersModel.cpp:165
49+#: plugins/LightDM/UsersModel.cpp:160
5250msgid "Guest Session"
5351msgstr "የ እንግዳ ክፍለ ጊዜ"
5452
55−#: plugins/Unity/Launcher/launcheritem.cpp:48
56−#: plugins/Unity/Launcher/launcheritem.cpp:122
53+#: plugins/Unity/Launcher/launcheritem.cpp:49
54+#: plugins/Unity/Launcher/launcheritem.cpp:123
5755msgid "Pin shortcut"
5856msgstr "አቋራጭ ማጣበቂያ"
5957
60−#: plugins/Unity/Launcher/launcheritem.cpp:54
58+#: plugins/Unity/Launcher/launcheritem.cpp:55
6159msgid "Quit"
6260msgstr "ማጥፊያ"
6361
64−#: plugins/Unity/Launcher/launcheritem.cpp:122
62+#: plugins/Unity/Launcher/launcheritem.cpp:123
6563msgid "Unpin shortcut"
6664msgstr "አቋራጭ መለያያ"
6765
@@ -84,8 +82,9 @@ msgctxt "Button: Log out from the system"
8482msgid "Log Out"
8583msgstr "መውጫ"
8684
87−#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
88−#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
85+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:264
86+#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:222
87+#: qml/Wizard/Pages/passcode-confirm.qml:32
8988#: qml/Wizard/Pages/passcode-set.qml:32
9089msgid "Cancel"
9190msgstr "መሰረዣ"
@@ -107,12 +106,12 @@ msgstr "አይ"
107106msgid "Yes"
108107msgstr "አዎ"
109108
110−#: qml/Components/Dialogs.qml:243
109+#: qml/Components/Dialogs.qml:239
111110msgctxt "Title: Power off/Restart dialog"
112111msgid "Power"
113112msgstr "ሐይል"
114113
115−#: qml/Components/Dialogs.qml:244
114+#: qml/Components/Dialogs.qml:240
116115msgid ""
117116"Are you sure you would like\n"
118117"to power off?"
@@ -120,27 +119,23 @@ msgstr ""
120119"በእርግጥ ሐይሉን ማጥፋት\n"
121120"ይፈልጋሉ?"
122121
123−#: qml/Components/Dialogs.qml:248
122+#: qml/Components/Dialogs.qml:244
124123msgctxt "Button: Power off the system"
125124msgid "Power off"
126125msgstr "ሐይል ማጥፊያ"
127126
128−#: qml/Components/Dialogs.qml:263
127+#: qml/Components/Dialogs.qml:255
129128msgctxt "Button: Restart the system"
130129msgid "Restart"
131130msgstr "እንደገና ማስጀመሪያ"
132131
133−#: qml/Components/Dialogs.qml:276
134−msgid "Screenshot"
135−msgstr "መመልከቻ ፎቶ ማንሻ"
136−
137132#: qml/Components/KeyboardShortcutsOverlay.qml:41
138133msgid "Keyboard Shortcuts"
139134msgstr "የ ፊደል ገበታ አቋራጮች"
140135
141136#: qml/Components/KeyboardShortcutsOverlay.qml:55
142−msgid "Lomiri"
143−msgstr "Lomiri"
137+msgid "Unity 8"
138+msgstr "Unity 8"
144139
145140#: qml/Components/KeyboardShortcutsOverlay.qml:62
146141msgid "PrtScr"
@@ -156,7 +151,7 @@ msgstr "Alt + PrtScr"
156151
157152#: qml/Components/KeyboardShortcutsOverlay.qml:80
158153msgid "Takes a screenshot of the current window."
159−msgstr "የ አሁኑን መስኮት መመልከቻ ፎቶ ማንሻ"
154+msgstr "የ አሁኑን መስኮት ፎቶ ማንሻ"
160155
161156#: qml/Components/KeyboardShortcutsOverlay.qml:88
162157msgid "Super + Space"
@@ -174,131 +169,135 @@ msgstr "Super + Shift + Space"
174169msgid "Switches to previous keyboard layout."
175170msgstr "ወዳለፈው የ ፊደል ገበታ እቅድ መቀየሪያ"
176171
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
172+#: qml/Components/KeyboardShortcutsOverlay.qml:118
186173msgid "Launcher"
187174msgstr "ማስነሻ"
188175
189−#: qml/Components/KeyboardShortcutsOverlay.qml:138
176+#: qml/Components/KeyboardShortcutsOverlay.qml:125
190177msgid "Super (Hold)"
191178msgstr "Super (ይጫኑ)"
192179
193−#: qml/Components/KeyboardShortcutsOverlay.qml:143
180+#: qml/Components/KeyboardShortcutsOverlay.qml:130
194181msgid "Opens the launcher, displays shortcuts."
195182msgstr "ማስነሻውን መክፈቻ እና አቋራጮች ማሳያ"
196183
197−#: qml/Components/KeyboardShortcutsOverlay.qml:151
184+#: qml/Components/KeyboardShortcutsOverlay.qml:138
198185msgid "Alt + F1"
199186msgstr "Alt + F1"
200187
201−#: qml/Components/KeyboardShortcutsOverlay.qml:156
188+#: qml/Components/KeyboardShortcutsOverlay.qml:143
202189msgid "Opens launcher keyboard navigation mode."
203190msgstr "መክፈቻ በ ፊደል ገበታ መቃኛ ዘዴ ማስነሻ"
204191
205−#: qml/Components/KeyboardShortcutsOverlay.qml:164
192+#: qml/Components/KeyboardShortcutsOverlay.qml:151
206193msgid "Super + Tab"
207194msgstr "Super + Tab"
208195
209−#: qml/Components/KeyboardShortcutsOverlay.qml:169
196+#: qml/Components/KeyboardShortcutsOverlay.qml:156
210197msgid "Switches applications via the launcher."
211198msgstr "መተግበሪያዎችን በ ማስጀመሪያ መቀየሪያ"
212199
213−#: qml/Components/KeyboardShortcutsOverlay.qml:177
200+#: qml/Components/KeyboardShortcutsOverlay.qml:164
214201msgid "Super + 1 to 0"
215−msgstr "Super + 0 እስከ 9"
202+msgstr "Super + 1 ወደ 0"
216203
217−#: qml/Components/KeyboardShortcutsOverlay.qml:182
204+#: qml/Components/KeyboardShortcutsOverlay.qml:169
218205msgid "Same as clicking on a launcher icon."
219206msgstr "ተመሳሳይ በ ማስጀመሪያ ምልክት ላይ እንደ መጫን"
220207
221−#: qml/Components/KeyboardShortcutsOverlay.qml:190
208+#: qml/Components/KeyboardShortcutsOverlay.qml:177
222209msgid "Super + A"
223210msgstr "Super + A"
224211
225−#: qml/Components/KeyboardShortcutsOverlay.qml:195
212+#: qml/Components/KeyboardShortcutsOverlay.qml:182
226213msgid "Opens the Application Drawer."
227−msgstr "የ መሳያ መተግበሪያ ማስጀመሪያ"
214+msgstr "መተግበሪያ መክፈቻ"
215+
216+#: qml/Components/KeyboardShortcutsOverlay.qml:194
217+msgid "Scopes"
218+msgstr "ክልል"
219+
220+#: qml/Components/KeyboardShortcutsOverlay.qml:201
221+msgid "Super (Tap)"
222+msgstr "Super (Tap)"
223+
224+#: qml/Components/KeyboardShortcutsOverlay.qml:206
225+msgid "Opens the Scopes home."
226+msgstr "የ ክልል ቤት መክፈቻ"
228227
229−#: qml/Components/KeyboardShortcutsOverlay.qml:235
228+#: qml/Components/KeyboardShortcutsOverlay.qml:222
230229msgid "Switching"
231230msgstr "በ መቀየር ላይ"
232231
233−#: qml/Components/KeyboardShortcutsOverlay.qml:242
232+#: qml/Components/KeyboardShortcutsOverlay.qml:229
234233msgid "Alt + Tab"
235234msgstr "Alt + Tab"
236235
237−#: qml/Components/KeyboardShortcutsOverlay.qml:247
236+#: qml/Components/KeyboardShortcutsOverlay.qml:234
238237msgid "Switches between applications."
239238msgstr "በ መተግበሪያዎች መካከል መቀያየሪያ"
240239
241−#: qml/Components/KeyboardShortcutsOverlay.qml:255
240+#: qml/Components/KeyboardShortcutsOverlay.qml:242
242241msgid "Super + W"
243242msgstr "Super + W"
244243
245−#: qml/Components/KeyboardShortcutsOverlay.qml:260
244+#: qml/Components/KeyboardShortcutsOverlay.qml:247
246245msgid "Opens the desktop spread."
247246msgstr "የ ዴስክቶፕ ማስፊያ መክፈቻ"
248247
249−#: qml/Components/KeyboardShortcutsOverlay.qml:268
248+#: qml/Components/KeyboardShortcutsOverlay.qml:255
250249msgid "Cursor Left or Right"
251250msgstr "መጠቆሚያ የ ግራ ወይንም የ ቀኝ"
252251
253−#: qml/Components/KeyboardShortcutsOverlay.qml:273
252+#: qml/Components/KeyboardShortcutsOverlay.qml:260
254253msgid "Moves the focus."
255254msgstr "ትኩረት ማንቀሳቀሻ"
256255
257−#: qml/Components/KeyboardShortcutsOverlay.qml:285
256+#: qml/Components/KeyboardShortcutsOverlay.qml:272
258257msgid "Windows"
259258msgstr "መስኮቶች"
260259
261−#: qml/Components/KeyboardShortcutsOverlay.qml:292
260+#: qml/Components/KeyboardShortcutsOverlay.qml:279
262261msgid "Ctrl + Super + D"
263262msgstr "Ctrl + Super + D"
264263
265−#: qml/Components/KeyboardShortcutsOverlay.qml:297
264+#: qml/Components/KeyboardShortcutsOverlay.qml:284
266265msgid "Minimizes all windows."
267266msgstr "ሁሉንም መስኮቶች ማሳነሻ"
268267
269−#: qml/Components/KeyboardShortcutsOverlay.qml:305
268+#: qml/Components/KeyboardShortcutsOverlay.qml:292
270269msgid "Ctrl + Super + Up"
271270msgstr "Ctrl + Super + Up"
272271
273−#: qml/Components/KeyboardShortcutsOverlay.qml:310
272+#: qml/Components/KeyboardShortcutsOverlay.qml:297
274273msgid "Maximizes the current window."
275274msgstr "የ አሁኑን መስኮት ማሳደጊያ"
276275
277−#: qml/Components/KeyboardShortcutsOverlay.qml:318
276+#: qml/Components/KeyboardShortcutsOverlay.qml:305
278277msgid "Ctrl + Super + Down"
279278msgstr "Ctrl + Super + Down"
280279
281−#: qml/Components/KeyboardShortcutsOverlay.qml:323
280+#: qml/Components/KeyboardShortcutsOverlay.qml:310
282281msgid "Minimizes or restores the current window."
283282msgstr "የ አሁኑን መስኮትማሳነሻ ወይንም እንደ ነበር መመለሻ"
284283
285−#: qml/Components/KeyboardShortcutsOverlay.qml:331
284+#: qml/Components/KeyboardShortcutsOverlay.qml:318
286285msgid "Ctrl + Super + Left or Right"
287286msgstr "Ctrl + Super + Left or Right"
288287
289−#: qml/Components/KeyboardShortcutsOverlay.qml:336
288+#: qml/Components/KeyboardShortcutsOverlay.qml:323
290289msgid "Semi-maximizes the current window."
291290msgstr "የ አሁኑን መስኮት በ ንዑስ-ማሳደጊያ"
292291
293−#: qml/Components/KeyboardShortcutsOverlay.qml:344
292+#: qml/Components/KeyboardShortcutsOverlay.qml:331
294293msgid "Alt + F4"
295294msgstr "Alt + F4"
296295
297−#: qml/Components/KeyboardShortcutsOverlay.qml:349
296+#: qml/Components/KeyboardShortcutsOverlay.qml:336
298297msgid "Closes the current window."
299298msgstr "የ አሁኑን መስኮት መዝጊያ"
300299
301−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
300+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:242
302301msgid "Return to Call"
303302msgstr "ወደ ጥሪ መመለሻ"
304303
@@ -358,19 +357,116 @@ msgstr "የ እርስዎ አካል አሁን ከ ውጪ ማሳያ ጋር ተገ
358357
359358#: qml/Components/VirtualTouchPad.qml:327
360359msgid "Tap left button to click."
361−msgstr "የ ግራ ቁልፍ መታ ያድርጉ ለ መጫን"
360+msgstr "መታ ያድርጉ በ ግራ ቁልፍ ላይ ለ መጫን"
362361
363362#: qml/Components/VirtualTouchPad.qml:339
364363msgid "Tap right button to right click."
365−msgstr "የ ቀኝ ቁልፍ መታ ያድርጉ በ ቀኝ ለ መጫን"
364+msgstr "መታ ያድርጉ በ ቀኝ ቁልፍ ላይ ለ መጫን"
366365
367366#: qml/Components/VirtualTouchPad.qml:351
368367msgid "Swipe with two fingers to scroll."
369−msgstr "ለ መሸብለል በ ሁለት ጣቶች ይጥረጉ"
368+msgstr "ለ መሽብለል በ ሁለት ጣት ይጥረጉ"
370369
371370#: qml/Components/VirtualTouchPad.qml:396
372371msgid "Find more settings in the system settings."
373−msgstr "ተጨማሪ ማሰናጃ በ ስርአት ማሰናጃ ውስጥ መፈለጊያ"
372+msgstr "ተጨማሪ ማሰናጃዎችን ያግኙ በ ስርአት ማሰናጃ ውስጥ"
373+
374+#: qml/Dash/DashPageHeader.qml:361
375+msgctxt "Button: Open the Ubuntu Store"
376+msgid "Store"
377+msgstr "ማስቀመጫ"
378+
379+#: qml/Dash/DashPageHeader.qml:368
380+msgctxt "Button: Start a search in the current dash scope"
381+msgid "Search"
382+msgstr "መፈለጊያ"
383+
384+#: qml/Dash/DashPageHeader.qml:378
385+msgctxt "Button: Show the current dash scope settings"
386+msgid "Settings"
387+msgstr "ማሰናጃዎች"
388+
389+#: qml/Dash/DashPageHeader.qml:385
390+msgid "Remove from Favorites"
391+msgstr "ከምወዳቸው ማስወገጃ"
392+
393+#: qml/Dash/DashPageHeader.qml:385
394+msgid "Add to Favorites"
395+msgstr "ወደምወዳቸው መጨመሪያ"
396+
397+#: qml/Dash/FiltersPopover.qml:61
398+msgid "Refine your results"
399+msgstr "የ እርስዎን ውጤቶች እንደገና ማጣሪያ"
400+
401+#: qml/Dash/FiltersPopover.qml:70
402+msgid "Reset"
403+msgstr "እንደ ነበረ መመለሻ"
404+
405+#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
406+msgid "Show less"
407+msgstr "ትንሽ ማሳያ"
408+
409+#: qml/Dash/GenericScopeView.qml:547
410+msgid "Show all"
411+msgstr "ሁሉንም ማሳያ"
412+
413+#: qml/Dash/GenericScopeView.qml:578
414+msgctxt "Label: Hint for dash search line edit"
415+msgid "Search"
416+msgstr "መፈለጊያ"
417+
418+#: qml/Dash/PageHeaderExtraPanel.qml:67
419+msgid "Recent Searches"
420+msgstr "የ ቅርብ ጊዜ ፍለጋዎች"
421+
422+#: qml/Dash/PageHeaderExtraPanel.qml:78
423+msgid "Clear All"
424+msgstr "ሁሉንም ማጽጃ"
425+
426+#: qml/Dash/Previews/PreviewActionCombo.qml:36
427+msgid "More..."
428+msgstr "ተጨማሪ..."
429+
430+#: qml/Dash/Previews/PreviewActionCombo.qml:36
431+msgid "Less..."
432+msgstr "አነስተኛ..."
433+
434+#: qml/Dash/Previews/PreviewCommentInput.qml:83
435+#: qml/Dash/Previews/PreviewRatingInput.qml:202
436+msgid "Send"
437+msgstr "መላኪያ"
438+
439+#: qml/Dash/Previews/PreviewRatingInput.qml:109
440+msgid "Rate this"
441+msgstr "ለዚህ ደረጃ ይስጡ"
442+
443+#: qml/Dash/Previews/PreviewRatingInput.qml:184
444+msgid "Add a review"
445+msgstr "ግምገማ መጨመሪያ"
446+
447+#: qml/Dash/PullToRefreshScopeStyle.qml:56
448+msgid "Pull to refresh…"
449+msgstr "ይሳቡ ለማነቃቃት…"
450+
451+#: qml/Dash/PullToRefreshScopeStyle.qml:61
452+msgid "Release to refresh…"
453+msgstr "ይልቀቁ ለማነቃቃት…"
454+
455+#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
456+msgid "Enable location data"
457+msgstr "የአካባቢ ዳታ ማስቻያ"
458+
459+#: qml/Dash/ScopesList.qml:146
460+msgid "Manage"
461+msgstr "አስተዳዳሪ"
462+
463+#: qml/Dash/ScopesList.qml:187
464+msgid "Home"
465+msgstr "ቤት"
466+
467+#: qml/Dash/ScopesList.qml:188
468+msgid "Also installed"
469+msgstr "እንዲሁም የተገጠሙ"
374470
375471#: qml/Greeter/CoverPage.qml:127
376472msgid "Unlock"
@@ -395,19 +491,19 @@ msgid_plural "Please wait %1 minutes and then try again…"
395491msgstr[0] "እባክዎን ይቆዩ %1 ደቂቃ እና ከዛ እንደ ገና ይምክሩ…"
396492msgstr[1] "እባክዎን ይቆዩ %1 ደቂቃዎች እና ከዛ እንደ ገና ይምክሩ…"
397493
398−#: qml/Greeter/Greeter.qml:550
494+#: qml/Greeter/Greeter.qml:561
399495msgid "Try again"
400496msgstr "እንደገና ይሞክሩ"
401497
402−#: qml/Greeter/Greeter.qml:551
498+#: qml/Greeter/Greeter.qml:562
403499msgid "Enter passphrase to unlock"
404−msgstr "የ ማለፊያ ሀረግ ያስገቡ"
500+msgstr "የ ማለፊያ ሀረግ ያስገቡ ለ መክፈት"
405501
406−#: qml/Greeter/Greeter.qml:552
502+#: qml/Greeter/Greeter.qml:563
407503msgid "Enter passcode to unlock"
408504msgstr "የ ማለፊያ ኮድ ያስገቡ ለ መክፈት"
409505
410−#: qml/Greeter/NarrowView.qml:235
506+#: qml/Greeter/NarrowView.qml:242
411507msgid "Emergency"
412508msgstr "ድንገተኛ"
413509
@@ -419,21 +515,22 @@ msgstr "የማለፊያ ሐረግ"
419515msgid "Passcode"
420516msgstr "ማለፊያ ኮድ"
421517
422−#: qml/Greeter/SessionsList.qml:124
518+#: qml/Greeter/SessionsList.qml:122
423519msgid "Select desktop environment"
424520msgstr "የ ዴስክቶፕ አይነት ይምረጡ"
425521
426−#: qml/Launcher/Drawer.qml:250
522+#: qml/Launcher/Drawer.qml:93
427523msgid "Search…"
428−msgstr "መፈለጊያ…"
524+msgstr "መፈለጊያ..."
429525
430−#: qml/Launcher/PullToRefreshScopeStyle.qml:56
431−msgid "Pull to refresh…"
432−msgstr "ይሳቡ ለማነቃቃት…"
526+#: qml/Launcher/Drawer.qml:128
527+msgctxt "Apps sorted alphabetically"
528+msgid "A-Z"
529+msgstr "A-Z"
433530
434−#: qml/Launcher/PullToRefreshScopeStyle.qml:61
435−msgid "Release to refresh…"
436−msgstr "ይልቀቁ ለማነቃቃት…"
531+#: qml/Launcher/MoreAppsHeader.qml:55
532+msgid "More apps in the store"
533+msgstr "ተጨማሪ መተግበሪያ በ ሱቅ ውስጥ"
437534
438535#: qml/Notifications/NotificationMenuItemFactory.qml:124
439536msgid "Show password"
@@ -530,25 +627,19 @@ msgstr "ወደ ኋላ"
530627msgid "Drag using 3 fingers any application from one window to the other"
531628msgstr "መጎተቻ 3 ጣቶች በ መጠቀም ማንኛውንም መተግበሪያ ከ አንድ መስኮት ወደ ሌላ"
532629
533−#: qml/Stage/Stage.qml:671
534−msgid "No running apps"
535−msgstr ""
536−
537630#: qml/Tutorial/TutorialLeftLong.qml:49
538−#, fuzzy
539−#| msgid "Long swipe from the left edge to open the Today scope"
540631msgid "Long swipe from the left edge to open the Application Drawer"
541−msgstr "በ ረጅሙ ከ ግራ ጠርዝ በኩል ይጥረጉ የ ዛሬን ክልል ለ መክፈት"
632+msgstr "በረጅሙ ይጥረጉ ከ ግራ ጠርዝ በኩል መተግበሪያ ለ መክፈት ከ መሳቢያ ውስጥ"
542633
543634#: qml/Tutorial/TutorialLeft.qml:47
544635msgid "Short swipe from the left edge to open the launcher"
545636msgstr "በ አጭሩ ይጥረጉ ከ ግራ ጠርዝ በኩል ማስጀመሪያውን ለ መክፈት"
546637
547−#: qml/Tutorial/TutorialRight.qml:54
638+#: qml/Tutorial/TutorialRight.qml:55
548639msgid "Push your mouse against the right edge to view your open apps"
549640msgstr "የ እርስዎን አይጥ መጠቆሚያ ወደ ቀኝ ጠርዝ በኩል ያስጠጉ የ ተከፈቱ መተግበሪያዎችን ለ መመልከት"
550641
551−#: qml/Tutorial/TutorialRight.qml:55
642+#: qml/Tutorial/TutorialRight.qml:56
552643msgid "Swipe from the right edge to view your open apps"
553644msgstr "ከ ቀኝ በኩል ይጥረጉ የ ተከፈቱ መተግበሪያዎችን ለ መመልከት"
554645
@@ -556,44 +647,28 @@ msgstr "ከ ቀኝ በኩል ይጥረጉ የ ተከፈቱ መተግበሪያዎ
556647msgid "Swipe from the top edge to access notifications and quick settings"
557648msgstr "ከ ላይ ጠረዝ በኩል ይጥረጉ ማስታወቂያዎች እና በፍጥነት ማሰናጃዎች ጋር ለ መድረስ"
558649
559−#: qml/Wizard/Page.qml:59
650+#: qml/Wizard/Page.qml:54
560651msgctxt "Button: Go back one page in the Wizard"
561652msgid "Back"
562653msgstr "ወደ ኋላ"
563654
564−#: qml/Wizard/Pages/10-welcome.qml:29
655+#: qml/Wizard/Pages/10-welcome.qml:28
565656msgid "Language"
566657msgstr "ቋንቋ"
567658
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
659+#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
660+#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
661+#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
662+#: qml/Wizard/Pages/70-passwd-type.qml:145
663+#: qml/Wizard/Pages/75-report-check.qml:84
664+#: qml/Wizard/Pages/passcode-desktop.qml:142
665+#: qml/Wizard/Pages/password-set.qml:142
575666msgid "Next"
576667msgstr "ይቀጥሉ"
577668
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−
594669#: qml/Wizard/Pages/20-keyboard.qml:31
595670msgid "Select Keyboard"
596−msgstr "የ ፊደል ገበታ ይምረጡ"
671+msgstr "ቋንቋ ይምረጡ"
597672
598673#: qml/Wizard/Pages/20-keyboard.qml:71
599674msgid "Keyboard language"
@@ -603,8 +678,8 @@ msgstr "የ ፊደል ገበታ ቋንቋ"
603678msgid "Keyboard layout"
604679msgstr "የ ፊደል ገበታ አቀራረብ"
605680
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
681+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
682+#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
608683#: qml/Wizard/Pages/sim.qml:101
609684msgid "Skip"
610685msgstr "መዝለያ"
@@ -613,23 +688,55 @@ msgstr "መዝለያ"
613688msgid "Connect to Wi‑Fi"
614689msgstr "ወደ ዋይ‑ፋይ መገናኛ"
615690
616−#: qml/Wizard/Pages/30-wifi.qml:139
691+#: qml/Wizard/Pages/30-wifi.qml:132
617692msgid "Connected"
618693msgstr "ተገናኝቷል"
619694
620−#: qml/Wizard/Pages/30-wifi.qml:172
695+#: qml/Wizard/Pages/30-wifi.qml:165
621696msgid "Available Wi-Fi networks"
622697msgstr "ዝግጁ የ ዋይ-ፋይ ኔትዎርኮች"
623698
624−#: qml/Wizard/Pages/30-wifi.qml:173
699+#: qml/Wizard/Pages/30-wifi.qml:166
625700msgid "No available Wi-Fi networks"
626701msgstr "ምንም ዝግጁ ዋይ-ፋይ ኔትዎርኮች አልተገኙም"
627702
703+#: qml/Wizard/Pages/40-location.qml:27
704+msgid "Location Services"
705+msgstr "የ አካባቢ ግልጋሎት"
706+
707+#: qml/Wizard/Pages/40-location.qml:83
708+msgid ""
709+"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
710+"(recommended)"
711+msgstr "ይጠቀሙ ጂፒኤስ: ዋይ-ፋይ: hotspots እና ተንቀሳቃሽ ኔትዎርክ ሳይታወቁ አካባቢ ለማግኘት (ይመከራሉ)"
712+
713+#: qml/Wizard/Pages/40-location.qml:105
714+#, qt-format
715+msgid "By selecting this option you agree to the Nokia HERE %1."
716+msgstr "ይህን ምርጫ በ መምረጥ እርስዎ ተስማምተዋል ከ Nokia HERE %1."
717+
718+#: qml/Wizard/Pages/40-location.qml:106
719+msgctxt "part of: Nokia HERE terms and conditions"
720+msgid "terms and conditions"
721+msgstr "ስምምነት እና ሁኔታዎች"
722+
723+#: qml/Wizard/Pages/40-location.qml:160
724+msgid "GPS only"
725+msgstr "ጂፒኤስ ብቻ"
726+
727+#: qml/Wizard/Pages/40-location.qml:214
728+msgid "Don't use my location"
729+msgstr "የ እኔን አካባቢ አትጠቀም"
730+
731+#: qml/Wizard/Pages/40-location.qml:260
732+msgid "You can change it later in System Settings."
733+msgstr "እርስዎ በኋላ በ ስርአት ማሰናጃ ውስጥ መቀየር ይችላሉ"
734+
628735#: qml/Wizard/Pages/50-timezone.qml:30
629736msgid "Time Zone"
630737msgstr "የ ሰአት ክልል"
631738
632−#: qml/Wizard/Pages/50-timezone.qml:183
739+#: qml/Wizard/Pages/50-timezone.qml:182
633740msgid "Enter your city"
634741msgstr "የ እርስዎን ከተማ ያስገቡ"
635742
@@ -637,7 +744,7 @@ msgstr "የ እርስዎን ከተማ ያስገቡ"
637744msgid "Personalize Your Device"
638745msgstr "የ እርስዎን አካል የ ግልዎ ያድርጉ"
639746
640−#: qml/Wizard/Pages/60-account.qml:54
747+#: qml/Wizard/Pages/60-account.qml:48
641748msgid "Preferred Name"
642749msgstr "የመረጡት ስም"
643750
@@ -645,75 +752,112 @@ msgstr "የመረጡት ስም"
645752msgid "Lock Screen"
646753msgstr "መመልከቻውን መቆለፊያ"
647754
648−#: qml/Wizard/Pages/70-passwd-type.qml:103
755+#: qml/Wizard/Pages/70-passwd-type.qml:102
649756msgctxt "Label: Type of security method"
650757msgid "Create new password"
651758msgstr "አዲስ የ መግቢያ ቃል መፍጠሪያ"
652759
653−#: qml/Wizard/Pages/70-passwd-type.qml:105
760+#: qml/Wizard/Pages/70-passwd-type.qml:104
654761msgctxt "Label: Type of security method"
655762msgid "Create passcode (numbers only)"
656763msgstr "አዲስ የ ማለፊያ ኮድ መፍጠሪያ (ቁጥር ብቻ)"
657764
658−#: qml/Wizard/Pages/70-passwd-type.qml:107
765+#: qml/Wizard/Pages/70-passwd-type.qml:106
659766msgctxt "Label: Type of security method"
660767msgid "No lock code"
661768msgstr "ምንም መቆለፊያ ኮድ አልተገኘም"
662769
663−#: qml/Wizard/Pages/79-system-update.qml:28
770+#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
771+msgid "Privacy Policy"
772+msgstr "የ ግላዊነት መመሪያ"
773+
774+#: qml/Wizard/Pages/75-report-check.qml:26
775+msgid "Help Us Improve"
776+msgstr "እንድንሻሻል ይርዱን"
777+
778+#: qml/Wizard/Pages/75-report-check.qml:59
779+msgid "Improve system performance by sending us crashes and error reports."
780+msgstr "የ ስርአቱን አፈጻጸም ለማሻሻል የ ግጭት እና የ ስህተት መልእክቶች ይላኩልን"
781+
782+#: qml/Wizard/Pages/75-report-check.qml:60
783+msgid "Privacy policy"
784+msgstr "የ ግላዊነት መመሪያ"
785+
786+#: qml/Wizard/Pages/77-system-update.qml:28
664787msgid "Update Device"
665788msgstr "አካሉን ማሻሻያ"
666789
667−#: qml/Wizard/Pages/79-system-update.qml:55
790+#: qml/Wizard/Pages/77-system-update.qml:55
668791msgid ""
669792"There is a system update available and ready to install. Afterwards, the "
670793"device will automatically restart."
671794msgstr "የ ስርአት ማሻሻያ ዝግጁ ነው ለ መግጠም: ከዚያ በኋላ አካሉ ራሱ በራሱ እንደገና ይጀምራል"
672795
673−#: qml/Wizard/Pages/79-system-update.qml:76
674−#, fuzzy
675−#| msgctxt "string identifying name of the update"
676−#| msgid "Ubuntu system"
796+#: qml/Wizard/Pages/77-system-update.qml:76
677797msgctxt "string identifying name of the update"
678−msgid "Ubuntu Touch system"
798+msgid "Ubuntu system"
679799msgstr "የ ኡቡቱ ስርአት"
680800
681−#: qml/Wizard/Pages/79-system-update.qml:83
801+#: qml/Wizard/Pages/77-system-update.qml:83
682802#, qt-format
683803msgctxt "version of the system update"
684804msgid "Version %1"
685805msgstr "እትም %1"
686806
687−#: qml/Wizard/Pages/79-system-update.qml:95
807+#: qml/Wizard/Pages/77-system-update.qml:102
688808msgid "This could take a few minutes..."
689−msgstr "ይህ ትንሽ ደቂቃዎች ይወስዳል..."
809+msgstr "ይህ ትንሽ ደቂቆች ይወስዳል"
690810
691−#: qml/Wizard/Pages/79-system-update.qml:109
811+#: qml/Wizard/Pages/77-system-update.qml:116
692812msgid "Install and restart now"
693813msgstr "መግጠሚያ እና እንደገና ማስጀመሪያ"
694814
695−#: qml/Wizard/Pages/80-finished.qml:91
696−msgid "Welcome Back"
697−msgstr "እንኳን ደህና መጡ:"
698−
699−#: qml/Wizard/Pages/80-finished.qml:91
815+#: qml/Wizard/Pages/80-finished.qml:89
700816msgid "Welcome to Ubuntu"
701817msgstr "እንኳን ደህና መጡ ወደ ኡቡንቱ"
702818
703−#: qml/Wizard/Pages/80-finished.qml:106
819+#: qml/Wizard/Pages/80-finished.qml:104
704820msgid "You are ready to use your device now"
705821msgstr "የ እርስዎን አካል ለ መጠቀም አሁን ዝግጁ ነው"
706822
707−#: qml/Wizard/Pages/80-finished.qml:126
708−msgid "Continue"
709−msgstr "ይቀጥሉ"
710−
711−#: qml/Wizard/Pages/80-finished.qml:126
823+#: qml/Wizard/Pages/80-finished.qml:124
712824msgid "Get Started"
713825msgstr "እንጀምር"
714826
827+#: qml/Wizard/Pages/here-terms.qml:25
828+msgid "Terms & Conditions"
829+msgstr "ውሎች & ሁኔታዎች"
830+
831+#: qml/Wizard/Pages/here-terms.qml:69
832+msgid "Your device uses positioning technologies provided by HERE."
833+msgstr "የ እርስዎ አካል ይጠቀማል ያሉበትን አካባቢ ቴክኖሎጂ የቀረበውን በ HERE."
834+
835+#: qml/Wizard/Pages/here-terms.qml:81
836+msgid ""
837+"To provide you with positioning services and to improve their quality, HERE "
838+"collects information about nearby cell towers and Wi-Fi hotspots around your "
839+"current location whenever your position is being found."
840+msgstr ""
841+"እርስዎ ያሉበትን አካባቢ ግልጋሎት ለ መስጠት እና ለማሻሻል: HERE መረጃ ይሰበስባል በቅርብ ያሉ የ ሴል ምሶሶዎች እና "
842+"ዋይ-ፋይ hotspots እርስዎ አሁን ያሉበትን አካባቢ ሲታወቅ"
843+
844+#: qml/Wizard/Pages/here-terms.qml:93
845+msgid ""
846+"The information collected is used to analyze the service and to improve the "
847+"use of service, but not to identify you personally."
848+msgstr "የ ተሰበሰበው መረጃ የሚጠቅመው ግልጋሎት ለማሻሻል ነው: ነገር ግን እርስዎን በ ግል ለ መለየት አይደለም"
849+
850+#: qml/Wizard/Pages/here-terms.qml:106
851+#, qt-format
852+msgid "By continuing, you agree to the HERE platform %1 and %2."
853+msgstr "በ መቀጠል እርስዎ ተስማምተዋል ከ HERE platform %1 እና %2."
854+
855+#: qml/Wizard/Pages/here-terms.qml:107
856+msgid "Service Terms"
857+msgstr "የ ግልጋሎት ስምምነቶች"
858+
715859#: qml/Wizard/Pages/passcode-confirm.qml:43
716−#: qml/Wizard/Pages/passcode-desktop.qml:104
860+#: qml/Wizard/Pages/passcode-desktop.qml:97
717861msgid "Confirm passcode"
718862msgstr "የማለፊያ ኮድ ማረጋገጫ"
719863
@@ -730,24 +874,24 @@ msgstr "እባክዎን እንደገና-ያስገቡ"
730874msgid "Lock Screen Passcode"
731875msgstr "የ መመልከቻው መቆለፊያ የ ማለፊያ ኮድ"
732876
733−#: qml/Wizard/Pages/passcode-desktop.qml:68
877+#: qml/Wizard/Pages/passcode-desktop.qml:61
734878msgid "Enter 4 numbers to setup your passcode"
735879msgstr "ያስገቡ 4 ቁጥሮች የ እርስዎን የ ማለፊያ ኮድ ለማሰናዳት"
736880
737−#: qml/Wizard/Pages/passcode-desktop.qml:84
881+#: qml/Wizard/Pages/passcode-desktop.qml:77
738882#: qml/Wizard/Pages/passcode-set.qml:54
739883msgid "Choose passcode"
740884msgstr "የ ማለፊያ ኮድ ይምረጡ"
741885
742−#: qml/Wizard/Pages/passcode-desktop.qml:139
886+#: qml/Wizard/Pages/passcode-desktop.qml:127
743887msgid "Passcode too short"
744888msgstr "የ ማለፊያ ኮዱ በጣም አጭር ነው"
745889
746−#: qml/Wizard/Pages/passcode-desktop.qml:141
890+#: qml/Wizard/Pages/passcode-desktop.qml:129
747891msgid "Passcodes match"
748892msgstr "የ ማለፊያ ኮዶቹ ተመሳሳይ ናቸው"
749893
750−#: qml/Wizard/Pages/passcode-desktop.qml:143
894+#: qml/Wizard/Pages/passcode-desktop.qml:131
751895msgid "Passcodes do not match"
752896msgstr "የ ማለፊያ ኮዶቹ አይመሳሰሉም"
753897
@@ -759,15 +903,15 @@ msgstr "የ ማለፊያ ኮድ 4 ባህሪዎች መሆን አለበት"
759903msgid "Lock Screen Password"
760904msgstr "የ መመልከቻ መቆለፊያ የ መግቢያ ቃል"
761905
762−#: qml/Wizard/Pages/password-set.qml:68
906+#: qml/Wizard/Pages/password-set.qml:62
763907msgid "Enter at least 8 characters"
764908msgstr "ያስገቡ ቢያንስ 8 ባህሪዎች"
765909
766−#: qml/Wizard/Pages/password-set.qml:80
910+#: qml/Wizard/Pages/password-set.qml:74
767911msgid "Choose password"
768912msgstr "የ መግቢያ ቃል ይምረጡ"
769913
770−#: qml/Wizard/Pages/password-set.qml:110
914+#: qml/Wizard/Pages/password-set.qml:104
771915msgid "Confirm password"
772916msgstr "የ መግቢያ ቃሉን ያረጋግጡ"
773917
@@ -823,217 +967,6 @@ msgstr "ደካማ የ መግቢያ ቃል"
823967msgid "Very weak password"
824968msgstr "በጣም ደካማ የ መግቢያ ቃል"
825969
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−
1037970#~ msgid "Top edge"
1038971#~ msgstr "የላይ ጠርዝ"
1039972
@@ -1049,12 +982,21 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
1049982#~ msgid "Type or say a command"
1050983#~ msgstr "ትእዛዝ ይናገሩ ወይንም ይጻፉ"
1051984
985+#~ msgid "Loading. Please Wait..."
986+#~ msgstr "እባክዎን ይቆዩ በመጫን ላይ..."
987+
988+#~ msgid "Speaking..."
989+#~ msgstr "በመናገር ላይ..."
990+
1052991#~ msgid "Speak Now..."
1053992#~ msgstr "አሁን ይናገሩ..."
1054993
1055994#~ msgid "Confirm"
1056995#~ msgstr "ማረጋገጫ"
1057996
997+#~ msgid "Search"
998+#~ msgstr "መፈለጊያ"
999+
10581000#~ msgid "See less"
10591001#~ msgstr "አነስተኛ መመልከቻ"
10601002
@@ -1097,6 +1039,7 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
10971039#~ msgid "This will be your last attempt."
10981040#~ msgstr "ይህ የመጨረሻ ሙከራዎ ነው"
10991041
1042+#, qt-format
11001043#~ msgid "Sorry, incorrect %1"
11011044#~ msgstr "አዝናለሁ: የተሳሳተ%1"
11021045
@@ -1137,12 +1080,11 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
11371080#~ "You have now mastered the edge gestures and can start using the "
11381081#~ "phone<br><br>Tap on the screen to start"
11391082#~ msgstr ""
1140−#~ "አሁን የ ጠርዝ እንቅስቃሴን አውቀዋል እና መጀመር ይችላሉ ስልኩን መጠቀም <br><br>መመልከቻውን መታ ያድርጉ "
1141−#~ "ለመጀመር"
1083+#~ "አሁን የ ጠርዝ እንቅስቃሴን አውቀዋል እና መጀመር ይችላሉ ስልኩን መጠቀም <br><br>መመልከቻውን መታ ያድርጉ ለመጀመር"
11421084
11431085#~ msgid ""
1144−#~ "If passcode is entered incorrectly, your phone will conduct a factory "
1145−#~ "reset and all personal data will be deleted."
1086+#~ "If passcode is entered incorrectly, your phone will conduct a factory reset "
1087+#~ "and all personal data will be deleted."
11461088#~ msgstr ""
11471089#~ "የተሳሳተ የማለፊያ ኮድ ካስገቡ የ እርስዎ ስልክ ወደ ነበረበት ወደ ፋክቶሪው ዘዴ ይመለሳል: እና የ ግል ዳታ በሙሉ "
11481090#~ "ይጠፋል"
@@ -1151,8 +1093,8 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
11511093#~ "If passphrase is entered incorrectly, your phone will conduct a factory "
11521094#~ "reset and all personal data will be deleted."
11531095#~ msgstr ""
1154−#~ "የተሳሳተ የማለፊያ ሐረግ ካስገቡ የ እርስዎ ስልክ ወደ ነበረበት ወደ ፋክቶሪው ዘዴ ይመለሳል: እና የ ግል ዳታ "
1155−#~ "በሙሉ ይጠፋል"
1096+#~ "የተሳሳተ የማለፊያ ሐረግ ካስገቡ የ እርስዎ ስልክ ወደ ነበረበት ወደ ፋክቶሪው ዘዴ ይመለሳል: እና የ ግል ዳታ በሙሉ "
1097+#~ "ይጠፋል"
11561098
11571099#~ msgid "Roaming"
11581100#~ msgstr "ማዘዋወሪያ"
@@ -1160,12 +1102,19 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
11601102#~ msgid "Manage Scopes"
11611103#~ msgstr "የ ክልል አስተዳዳሪ"
11621104
1105+#, qt-format
11631106#~ msgid "Enter %1"
11641107#~ msgstr "ማስገቢያ %1"
11651108
11661109#~ msgid "Please re-enter"
11671110#~ msgstr "እባክዎን እንደገና-ያስገቡ"
11681111
1112+#~ msgid "Enter passphrase"
1113+#~ msgstr "የ ማለፊያ ሀረግ ያስገቡ"
1114+
1115+#~ msgid "Enter passcode"
1116+#~ msgstr "የ ማለፊያ ኮድ ያስገቡ"
1117+
11691118#~ msgid "Lock security"
11701119#~ msgstr "ደህንነት መቆለፊያ"
11711120
@@ -1188,8 +1137,7 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
11881137#~ "This can be disabled in <b>System Settings</b> under <b>Security &amp; "
11891138#~ "Privacy</b>"
11901139#~ msgstr ""
1191−#~ "ይህን ግልጋሎት ማሰናከል ይችላሉ ከ <b>ስርአት ማሰናጃዎች</b> under <b>Security &amp; "
1192−#~ "Privacy</b>"
1140+#~ "ይህን ግልጋሎት ማሰናከል ይችላሉ ከ <b>ስርአት ማሰናጃዎች</b> under <b>Security &amp; Privacy</b>"
11931141
11941142#~ msgid "Nice work!"
11951143#~ msgstr "ጥሩ ሰርተዋል!"
@@ -1224,6 +1172,9 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
12241172#~ msgid "Let’s get started."
12251173#~ msgstr "ስራ እንጀምር"
12261174
1175+#~ msgid "Continue"
1176+#~ msgstr "ይቀጥሉ"
1177+
12271178#~ msgid "Passphrase must be 4 characters long"
12281179#~ msgstr "የ ማለፊያ ሀረግ ቢያንስ 4 ባህሪዎች መሆን አለበት"
12291180
@@ -1233,9 +1184,11 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
12331184#~ msgid "Let the phone detect your location:"
12341185#~ msgstr "እባክዎን እርስዎ ያሉበትን አካባቢ ስልኩ እራሱ ይፈልግ:"
12351186
1187+#, qt-format
12361188#~ msgid "〈 %1"
12371189#~ msgstr "〈 %1"
12381190
1191+#, qt-format
12391192#~ msgid "%1 〉"
12401193#~ msgstr "%1 〉"
12411194
@@ -1252,12 +1205,12 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
12521205#~ "Your phone is set up to automatically report errors to Canonical and its "
12531206#~ "partners, the makers of the operating system."
12541207#~ msgstr ""
1255−#~ "የ እርስዎ ስልክ ራሱ በራሱ የ ስህተት መግለጫዎች ወደ Canonical and its partners, የ መስሪያ "
1256−#~ "ስርአት አምራቾች"
1208+#~ "የ እርስዎ ስልክ ራሱ በራሱ የ ስህተት መግለጫዎች ወደ Canonical and its partners, የ መስሪያ ስርአት "
1209+#~ "አምራቾች"
12571210
12581211#~ msgid ""
1259−#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms "
1260−#~ "and conditions</a>."
1212+#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
1213+#~ "conditions</a>."
12611214#~ msgstr "ይህን ምርጫ በመምረጥ ተስማምቻለሁ ከ Nokia HERE <a href='#'>ውሎች እና ሁኔታዎች ጋር</a>."
12621215
12631216#~ msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
@@ -1272,6 +1225,9 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
12721225#~ msgid "Short swipe from the left edge."
12731226#~ msgstr "ከ ግራ ጠርዝ በኩል በትንሹ ይጥረጉ"
12741227
1228+#~ msgid "Open the launcher"
1229+#~ msgstr "ማስጀመሪያውን መክፈቻ"
1230+
12751231#~ msgid "Tap here to continue."
12761232#~ msgstr "እዚህ መታ ይድርጉ ለመቀጠል"
12771233
@@ -1399,8 +1355,17 @@ msgstr "በጣም ደካማ የ መግቢያ ቃል"
13991355#~ msgid "Short or long swipe from the right edge to view your open apps"
14001356#~ msgstr "በ አጭሩ ወይንም በ ረጅሙ ይጥረጉ ከ ቀኝ ጠረዝ በኩል የ ተከፈቱ መተግበሪያዎችን ለማየት"
14011357
1358+#~ msgid "Long swipe from the left edge to open the Today scope"
1359+#~ msgstr "በ ረጅሙ ከ ግራ ጠርዝ በኩል ይጥረጉ የ ዛሬን ክልል ለ መክፈት"
1360+
14021361#~ msgid "Swipe from the left edge to open the launcher"
14031362#~ msgstr "ከ ግራ ጠርዝ በኩል ይጥረጉ ማስጀመሪያውን ለ መክፈት"
14041363
14051364#~ msgid "Hover your mouse on the right edge to view your open apps"
14061365#~ msgstr "የ እርስዎን አይጥ ወደ ቀኝ ጠርዝ በኩል ሲያደርጉ የ ተከፈቱ መተግበሪያዎች መመልከቻ"
1366+
1367+#~ msgid "Takes a screenshot of a window."
1368+#~ msgstr "የ መስኮት መመልከቻ ፎቶ ማንሻ"
1369+
1370+#~ msgid "Super + 0 to 9"
1371+#~ msgstr "Super + 0 እስከ 9"
po/ar.po+482−434
@@ -6,74 +6,72 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity\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"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2017-03-21 10:58+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"
1614"MIME-Version: 1.0\n"
1715"Content-Type: text/plain; charset=UTF-8\n"
1816"Content-Transfer-Encoding: 8bit\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"
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-03-24 06:12+0000\n"
20+"X-Generator: Launchpad (build 18334)\n"
2321
24−#: plugins/LightDM/Greeter.cpp:199
22+#: plugins/LightDM/Greeter.cpp:188
2523msgid "Password: "
2624msgstr "كلمة السر: "
2725
28−#: plugins/LightDM/Greeter.cpp:214
26+#: plugins/LightDM/Greeter.cpp:203
2927msgid "Username"
30−msgstr "اسم المستخدم"
28+msgstr ""
3129
32−#: plugins/LightDM/Greeter.cpp:258
30+#: plugins/LightDM/Greeter.cpp:242
3331msgid "Failed to authenticate"
34−msgstr "فشل التحقق"
32+msgstr ""
3533
36−#: plugins/LightDM/Greeter.cpp:260
34+#: plugins/LightDM/Greeter.cpp:244
3735msgid "Invalid password, please try again"
38−msgstr "كلمة المرور غير صحيحة، الرجاء المحاولة مرة أخرى"
36+msgstr ""
3937
40−#: plugins/LightDM/Greeter.cpp:270
38+#: plugins/LightDM/Greeter.cpp:254
4139msgid "Log In"
42−msgstr "سجل الدخول"
40+msgstr ""
4341
44−#: plugins/LightDM/Greeter.cpp:270
42+#: plugins/LightDM/Greeter.cpp:254
4543msgid "Retry"
46−msgstr "حاول مجدداً"
44+msgstr "إعادة المحاولة"
4745
48−#: plugins/LightDM/UsersModel.cpp:157
46+#: plugins/LightDM/UsersModel.cpp:152
4947msgid "Login"
50−msgstr "سجل الدخول"
48+msgstr ""
5149
52−#: plugins/LightDM/UsersModel.cpp:165
50+#: plugins/LightDM/UsersModel.cpp:160
5351msgid "Guest Session"
54−msgstr "جلسة ضيف"
52+msgstr ""
5553
56−#: plugins/Unity/Launcher/launcheritem.cpp:48
57−#: plugins/Unity/Launcher/launcheritem.cpp:122
54+#: plugins/Unity/Launcher/launcheritem.cpp:49
55+#: plugins/Unity/Launcher/launcheritem.cpp:123
5856msgid "Pin shortcut"
59−msgstr "ثبت اختصارًا"
57+msgstr "تثبيت الاختصار"
6058
61−#: plugins/Unity/Launcher/launcheritem.cpp:54
59+#: plugins/Unity/Launcher/launcheritem.cpp:55
6260msgid "Quit"
6361msgstr "خروج"
6462
65−#: plugins/Unity/Launcher/launcheritem.cpp:122
63+#: plugins/Unity/Launcher/launcheritem.cpp:123
6664msgid "Unpin shortcut"
67−msgstr "ألغ تثبيت الاختصار"
65+msgstr "إزالة تثبيت الاختصار"
6866
6967#: qml/Components/Dialogs.qml:176
7068msgctxt "Title: Lock/Log out dialog"
7169msgid "Log out"
72−msgstr "اخرج"
70+msgstr "خروج"
7371
7472#: qml/Components/Dialogs.qml:177
7573msgid "Are you sure you want to log out?"
76−msgstr "أمتأكد أنك تريد تسجيل الخروج ؟"
74+msgstr "هل أنت متأكد من رغبتك في تسجيل الخروج؟"
7775
7876#: qml/Components/Dialogs.qml:180
7977msgctxt "Button: Lock the system"
@@ -83,22 +81,23 @@ msgstr "أوصِد"
8381#: qml/Components/Dialogs.qml:191
8482msgctxt "Button: Log out from the system"
8583msgid "Log Out"
86−msgstr "اخرج"
84+msgstr "خروج"
8785
88−#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
89−#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
86+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:264
87+#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:222
88+#: qml/Wizard/Pages/passcode-confirm.qml:32
9089#: qml/Wizard/Pages/passcode-set.qml:32
9190msgid "Cancel"
92−msgstr "ألغ"
91+msgstr "إلغاء"
9392
9493#: qml/Components/Dialogs.qml:211
9594msgctxt "Title: Reboot dialog"
9695msgid "Reboot"
97−msgstr "أعد التشغيل"
96+msgstr "إعادة التشغيل"
9897
9998#: qml/Components/Dialogs.qml:212
10099msgid "Are you sure you want to reboot?"
101−msgstr "أمتأكد أنك تريد إعادة التشغيل؟"
100+msgstr "هل أنت متأكد من رغبتك في إعادة تشغيل الجهاز؟"
102101
103102#: qml/Components/Dialogs.qml:215
104103msgid "No"
@@ -108,12 +107,12 @@ msgstr "لا"
108107msgid "Yes"
109108msgstr "نعم"
110109
111−#: qml/Components/Dialogs.qml:243
110+#: qml/Components/Dialogs.qml:239
112111msgctxt "Title: Power off/Restart dialog"
113112msgid "Power"
114113msgstr "الطاقة"
115114
116−#: qml/Components/Dialogs.qml:244
115+#: qml/Components/Dialogs.qml:240
117116msgid ""
118117"Are you sure you would like\n"
119118"to power off?"
@@ -121,27 +120,23 @@ msgstr ""
121120"هل أنت متأكد من رغبتك\n"
122121"في إيقاف التشغيل؟"
123122
124−#: qml/Components/Dialogs.qml:248
123+#: qml/Components/Dialogs.qml:244
125124msgctxt "Button: Power off the system"
126125msgid "Power off"
127−msgstr "أوقف التشغيل"
126+msgstr "إيقاف التشغيل"
128127
129−#: qml/Components/Dialogs.qml:263
128+#: qml/Components/Dialogs.qml:255
130129msgctxt "Button: Restart the system"
131130msgid "Restart"
132−msgstr "أعد التشغيل"
133−
134−#: qml/Components/Dialogs.qml:276
135−msgid "Screenshot"
136−msgstr "لقطة شاشة"
131+msgstr "إعادة التشغيل"
137132
138133#: qml/Components/KeyboardShortcutsOverlay.qml:41
139134msgid "Keyboard Shortcuts"
140135msgstr "اختصارات لوحة المفاتيح"
141136
142137#: qml/Components/KeyboardShortcutsOverlay.qml:55
143−msgid "Lomiri"
144−msgstr "لوميري"
138+msgid "Unity 8"
139+msgstr "يونتي 8"
145140
146141#: qml/Components/KeyboardShortcutsOverlay.qml:62
147142msgid "PrtScr"
@@ -149,7 +144,7 @@ msgstr "PrtScr"
149144
150145#: qml/Components/KeyboardShortcutsOverlay.qml:67
151146msgid "Takes a screenshot."
152−msgstr "خُذ لقطة للشاشة."
147+msgstr "أخذ لقطة للشاشة"
153148
154149#: qml/Components/KeyboardShortcutsOverlay.qml:75
155150msgid "Alt + PrtScr"
@@ -157,7 +152,7 @@ msgstr "Alt + PrtScr"
157152
158153#: qml/Components/KeyboardShortcutsOverlay.qml:80
159154msgid "Takes a screenshot of the current window."
160−msgstr "خُذ لقطة شاشة للنافذة الحالية."
155+msgstr ""
161156
162157#: qml/Components/KeyboardShortcutsOverlay.qml:88
163158msgid "Super + Space"
@@ -165,7 +160,7 @@ msgstr "Super + Space"
165160
166161#: qml/Components/KeyboardShortcutsOverlay.qml:93
167162msgid "Switches to next keyboard layout."
168−msgstr "بدل إلى تخطيط لوحة المفاتيح التالي."
163+msgstr "للتحويل إلى مخطط لوحة المفاتيح التالي."
169164
170165#: qml/Components/KeyboardShortcutsOverlay.qml:101
171166msgid "Super + Shift + Space"
@@ -173,135 +168,139 @@ msgstr "Super + Shift + Space"
173168
174169#: qml/Components/KeyboardShortcutsOverlay.qml:106
175170msgid "Switches to previous keyboard layout."
176−msgstr "بدل إلى تخطيط لوحة المفاتيح السابق."
177−
178−#: qml/Components/KeyboardShortcutsOverlay.qml:114
179−msgid "Ctrl + Alt + T"
180−msgstr "Ctrl + Alt + T"
181−
182−#: qml/Components/KeyboardShortcutsOverlay.qml:119
183−msgid "Starts the Terminal application."
184−msgstr "شغِل الطرفية."
171+msgstr "للتحويل إلى مخطط لوحة المفاتيح السابق."
185172
186−#: qml/Components/KeyboardShortcutsOverlay.qml:131
173+#: qml/Components/KeyboardShortcutsOverlay.qml:118
187174msgid "Launcher"
188−msgstr "مطلق"
175+msgstr "شريط بدء التطبيقات"
189176
190−#: qml/Components/KeyboardShortcutsOverlay.qml:138
177+#: qml/Components/KeyboardShortcutsOverlay.qml:125
191178msgid "Super (Hold)"
192−msgstr "Super (ضغط مع التعليق)"
179+msgstr "Super (Hold)"
193180
194−#: qml/Components/KeyboardShortcutsOverlay.qml:143
181+#: qml/Components/KeyboardShortcutsOverlay.qml:130
195182msgid "Opens the launcher, displays shortcuts."
196−msgstr "يشغل المطلق، ويعرض الاختصارات."
183+msgstr "لفتح شريط بدء التطبيقات، وإظهار الاختصارات."
197184
198−#: qml/Components/KeyboardShortcutsOverlay.qml:151
185+#: qml/Components/KeyboardShortcutsOverlay.qml:138
199186msgid "Alt + F1"
200187msgstr "Alt + F1"
201188
202−#: qml/Components/KeyboardShortcutsOverlay.qml:156
189+#: qml/Components/KeyboardShortcutsOverlay.qml:143
203190msgid "Opens launcher keyboard navigation mode."
204−msgstr "فتح وضع التنقل بلوحة المفاتيح المشغلة."
191+msgstr ""
205192
206−#: qml/Components/KeyboardShortcutsOverlay.qml:164
193+#: qml/Components/KeyboardShortcutsOverlay.qml:151
207194msgid "Super + Tab"
208195msgstr "Super + Tab"
209196
210−#: qml/Components/KeyboardShortcutsOverlay.qml:169
197+#: qml/Components/KeyboardShortcutsOverlay.qml:156
211198msgid "Switches applications via the launcher."
212−msgstr "انتقل بين التطبيقات عبر المُطلق."
199+msgstr "للتحويل بين التطبيقات عبر شريط بدء التطبيقات."
213200
214−#: qml/Components/KeyboardShortcutsOverlay.qml:177
201+#: qml/Components/KeyboardShortcutsOverlay.qml:164
215202msgid "Super + 1 to 0"
216−msgstr "Super + 1 to 0"
203+msgstr ""
217204
218−#: qml/Components/KeyboardShortcutsOverlay.qml:182
205+#: qml/Components/KeyboardShortcutsOverlay.qml:169
219206msgid "Same as clicking on a launcher icon."
220−msgstr "نفس تأثير النقر على أيقونة المطلق."
207+msgstr "نفس إجراء الضغط على أيقونة في الشريط."
221208
222−#: qml/Components/KeyboardShortcutsOverlay.qml:190
209+#: qml/Components/KeyboardShortcutsOverlay.qml:177
223210msgid "Super + A"
224211msgstr "Super + A"
225212
226−#: qml/Components/KeyboardShortcutsOverlay.qml:195
213+#: qml/Components/KeyboardShortcutsOverlay.qml:182
227214msgid "Opens the Application Drawer."
228−msgstr "يفتح درج التطبيقات."
215+msgstr ""
216+
217+#: qml/Components/KeyboardShortcutsOverlay.qml:194
218+msgid "Scopes"
219+msgstr ""
220+
221+#: qml/Components/KeyboardShortcutsOverlay.qml:201
222+msgid "Super (Tap)"
223+msgstr ""
224+
225+#: qml/Components/KeyboardShortcutsOverlay.qml:206
226+msgid "Opens the Scopes home."
227+msgstr ""
229228
230−#: qml/Components/KeyboardShortcutsOverlay.qml:235
229+#: qml/Components/KeyboardShortcutsOverlay.qml:222
231230msgid "Switching"
232−msgstr "يبدل"
231+msgstr "التبديل"
233232
234−#: qml/Components/KeyboardShortcutsOverlay.qml:242
233+#: qml/Components/KeyboardShortcutsOverlay.qml:229
235234msgid "Alt + Tab"
236235msgstr "Alt + Tab"
237236
238−#: qml/Components/KeyboardShortcutsOverlay.qml:247
237+#: qml/Components/KeyboardShortcutsOverlay.qml:234
239238msgid "Switches between applications."
240−msgstr "يبدل بين التطبيقات."
239+msgstr "للتبديل بين التطبيقات المفتوحة."
241240
242−#: qml/Components/KeyboardShortcutsOverlay.qml:255
241+#: qml/Components/KeyboardShortcutsOverlay.qml:242
243242msgid "Super + W"
244−msgstr "Super + W"
243+msgstr ""
245244
246−#: qml/Components/KeyboardShortcutsOverlay.qml:260
245+#: qml/Components/KeyboardShortcutsOverlay.qml:247
247246msgid "Opens the desktop spread."
248−msgstr "يفتح وضع سطح المكتب."
247+msgstr ""
249248
250−#: qml/Components/KeyboardShortcutsOverlay.qml:268
249+#: qml/Components/KeyboardShortcutsOverlay.qml:255
251250msgid "Cursor Left or Right"
252−msgstr "اتجاه المؤشر لليمين أو اليسار"
251+msgstr ""
253252
254−#: qml/Components/KeyboardShortcutsOverlay.qml:273
253+#: qml/Components/KeyboardShortcutsOverlay.qml:260
255254msgid "Moves the focus."
256−msgstr "بدّل التركيز."
255+msgstr "لنقل التركيز."
257256
258−#: qml/Components/KeyboardShortcutsOverlay.qml:285
257+#: qml/Components/KeyboardShortcutsOverlay.qml:272
259258msgid "Windows"
260−msgstr "نوافذ"
259+msgstr "النوافذ"
261260
262−#: qml/Components/KeyboardShortcutsOverlay.qml:292
261+#: qml/Components/KeyboardShortcutsOverlay.qml:279
263262msgid "Ctrl + Super + D"
264263msgstr "Ctrl + Super + D"
265264
266−#: qml/Components/KeyboardShortcutsOverlay.qml:297
265+#: qml/Components/KeyboardShortcutsOverlay.qml:284
267266msgid "Minimizes all windows."
268−msgstr "يصغر كل النوافذ."
267+msgstr "لتصغير جميع النوافذ."
269268
270−#: qml/Components/KeyboardShortcutsOverlay.qml:305
269+#: qml/Components/KeyboardShortcutsOverlay.qml:292
271270msgid "Ctrl + Super + Up"
272271msgstr "Ctrl + Super + Up"
273272
274−#: qml/Components/KeyboardShortcutsOverlay.qml:310
273+#: qml/Components/KeyboardShortcutsOverlay.qml:297
275274msgid "Maximizes the current window."
276−msgstr "يكبر النافذة الحالية."
275+msgstr "لتكبير النافذة الحالية."
277276
278−#: qml/Components/KeyboardShortcutsOverlay.qml:318
277+#: qml/Components/KeyboardShortcutsOverlay.qml:305
279278msgid "Ctrl + Super + Down"
280279msgstr "Ctrl + Super + Down"
281280
282−#: qml/Components/KeyboardShortcutsOverlay.qml:323
281+#: qml/Components/KeyboardShortcutsOverlay.qml:310
283282msgid "Minimizes or restores the current window."
284−msgstr "يصغر أو يستعيد النافذة الحالية."
283+msgstr "لتصغير او استعادة النافذة الحالية."
285284
286−#: qml/Components/KeyboardShortcutsOverlay.qml:331
285+#: qml/Components/KeyboardShortcutsOverlay.qml:318
287286msgid "Ctrl + Super + Left or Right"
288−msgstr "Ctrl + Super + Left or Right"
287+msgstr ""
289288
290−#: qml/Components/KeyboardShortcutsOverlay.qml:336
289+#: qml/Components/KeyboardShortcutsOverlay.qml:323
291290msgid "Semi-maximizes the current window."
292−msgstr "كبر النافذة الحالة جزئيا."
291+msgstr ""
293292
294−#: qml/Components/KeyboardShortcutsOverlay.qml:344
293+#: qml/Components/KeyboardShortcutsOverlay.qml:331
295294msgid "Alt + F4"
296−msgstr "Alt + F4"
295+msgstr ""
297296
298−#: qml/Components/KeyboardShortcutsOverlay.qml:349
297+#: qml/Components/KeyboardShortcutsOverlay.qml:336
299298msgid "Closes the current window."
300−msgstr "يغلق النافذة الحالية."
299+msgstr ""
301300
302−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
301+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:242
303302msgid "Return to Call"
304−msgstr "عُد للمكالمة"
303+msgstr "العودة إلى المكالمة"
305304
306305#: qml/Components/Lockscreen.qml:212
307306msgid "Emergency Call"
@@ -314,48 +313,48 @@ msgstr "موافق"
314313#: qml/Components/MediaServices/VideoPlayerControls.qml:44
315314#, qt-format
316315msgid "%1:%2:%3"
317−msgstr "%1:%2:%3"
316+msgstr ""
318317
319318#: qml/Components/MediaServices/VideoPlayerControls.qml:49
320319#, qt-format
321320msgid "%1:%2"
322−msgstr "%1:%2"
321+msgstr ""
323322
324323#: qml/Components/ModeSwitchWarningDialog.qml:33
325324msgid "Apps may have unsaved data:"
326−msgstr "ربما لم تَحفظ بيانات هذه التطبيقات:"
325+msgstr ""
327326
328327#: qml/Components/ModeSwitchWarningDialog.qml:60
329328msgctxt ""
330329"Re-dock means connect the device again to an external screen/mouse/keyboard"
331330msgid "Re-dock, save your work and close these apps to continue."
332−msgstr "أعد الوصل، احفظ عملك على هذه التطبيقات ثم أغلقها للمتابعة."
331+msgstr ""
333332
334333#: qml/Components/ModeSwitchWarningDialog.qml:67
335334msgid "Or force close now (unsaved data will be lost)."
336−msgstr "أو أغلقها قسريا (ستفقد البيانات غير المحفوظة)."
335+msgstr "أو أغلق إجباريا الآن (ستفقد أي بيانات غير محفوظة)."
337336
338337#: qml/Components/ModeSwitchWarningDialog.qml:80
339338msgid "OK, I will reconnect"
340−msgstr "موافق، سؤعيد الاتصال"
339+msgstr ""
341340
342341#: qml/Components/ModeSwitchWarningDialog.qml:81
343342msgid "Reconnect now!"
344−msgstr "أعد الاتصال الآن!"
343+msgstr ""
345344
346345#: qml/Components/ModeSwitchWarningDialog.qml:94
347346msgid "Close all"
348−msgstr "أغلق الكل"
347+msgstr ""
349348
350349#: qml/Components/SharingPicker.qml:54
351350msgid "Preview Share Item"
352−msgstr "معاينة الملف المشارك"
351+msgstr ""
353352
354353#: qml/Components/VirtualTouchPad.qml:317
355354msgid ""
356355"Your device is now connected to an external display. Use this screen as a "
357356"touch pad to interact with the pointer."
358−msgstr "جهازك متصل بجهاز عرض خارجي. استخدم جهازك كلوحة لمس لتحكم بالمؤشر."
357+msgstr ""
359358
360359#: qml/Components/VirtualTouchPad.qml:327
361360msgid "Tap left button to click."
@@ -363,19 +362,116 @@ msgstr "اضغط الزر الأيسر للنقر."
363362
364363#: qml/Components/VirtualTouchPad.qml:339
365364msgid "Tap right button to right click."
366−msgstr "اضغط على الزر الأيمن للنقر."
365+msgstr "اضغط الزر الأيمن للنقر الأيمن."
367366
368367#: qml/Components/VirtualTouchPad.qml:351
369368msgid "Swipe with two fingers to scroll."
370−msgstr "اسحب بإصبعين للتمرير."
369+msgstr ""
371370
372371#: qml/Components/VirtualTouchPad.qml:396
373372msgid "Find more settings in the system settings."
374−msgstr "جد إعدادات إضافية في إعدادات النظام."
373+msgstr "اعثر على مزيد من الإعدادات في إعدادات النظام."
374+
375+#: qml/Dash/DashPageHeader.qml:361
376+msgctxt "Button: Open the Ubuntu Store"
377+msgid "Store"
378+msgstr "المتجر"
379+
380+#: qml/Dash/DashPageHeader.qml:368
381+msgctxt "Button: Start a search in the current dash scope"
382+msgid "Search"
383+msgstr "بحث"
384+
385+#: qml/Dash/DashPageHeader.qml:378
386+msgctxt "Button: Show the current dash scope settings"
387+msgid "Settings"
388+msgstr "الإعدادات"
389+
390+#: qml/Dash/DashPageHeader.qml:385
391+msgid "Remove from Favorites"
392+msgstr "حذف من المفضلات"
393+
394+#: qml/Dash/DashPageHeader.qml:385
395+msgid "Add to Favorites"
396+msgstr "إضافة إلى المفضلات"
397+
398+#: qml/Dash/FiltersPopover.qml:61
399+msgid "Refine your results"
400+msgstr ""
401+
402+#: qml/Dash/FiltersPopover.qml:70
403+msgid "Reset"
404+msgstr ""
405+
406+#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
407+msgid "Show less"
408+msgstr "عرض أقل"
409+
410+#: qml/Dash/GenericScopeView.qml:547
411+msgid "Show all"
412+msgstr "عرض الكل"
413+
414+#: qml/Dash/GenericScopeView.qml:578
415+msgctxt "Label: Hint for dash search line edit"
416+msgid "Search"
417+msgstr "بحث"
418+
419+#: qml/Dash/PageHeaderExtraPanel.qml:67
420+msgid "Recent Searches"
421+msgstr ""
422+
423+#: qml/Dash/PageHeaderExtraPanel.qml:78
424+msgid "Clear All"
425+msgstr ""
426+
427+#: qml/Dash/Previews/PreviewActionCombo.qml:36
428+msgid "More..."
429+msgstr "المزيد..."
430+
431+#: qml/Dash/Previews/PreviewActionCombo.qml:36
432+msgid "Less..."
433+msgstr "أقل..."
434+
435+#: qml/Dash/Previews/PreviewCommentInput.qml:83
436+#: qml/Dash/Previews/PreviewRatingInput.qml:202
437+msgid "Send"
438+msgstr "أرسل"
439+
440+#: qml/Dash/Previews/PreviewRatingInput.qml:109
441+msgid "Rate this"
442+msgstr "قيّم ذلك"
443+
444+#: qml/Dash/Previews/PreviewRatingInput.qml:184
445+msgid "Add a review"
446+msgstr "أضف تعليق"
447+
448+#: qml/Dash/PullToRefreshScopeStyle.qml:56
449+msgid "Pull to refresh…"
450+msgstr "اسحب للتحديث..."
451+
452+#: qml/Dash/PullToRefreshScopeStyle.qml:61
453+msgid "Release to refresh…"
454+msgstr "حرّر للتحديث..."
455+
456+#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
457+msgid "Enable location data"
458+msgstr "تفعيل بيانات الموقع"
459+
460+#: qml/Dash/ScopesList.qml:146
461+msgid "Manage"
462+msgstr "إدارة"
463+
464+#: qml/Dash/ScopesList.qml:187
465+msgid "Home"
466+msgstr "الرئيسية"
467+
468+#: qml/Dash/ScopesList.qml:188
469+msgid "Also installed"
470+msgstr "أيضا تم تثبيت"
375471
376472#: qml/Greeter/CoverPage.qml:127
377473msgid "Unlock"
378−msgstr "فك الإيصاد"
474+msgstr "فك القفل"
379475
380476#: qml/Greeter/DelayedLockscreen.qml:43
381477msgid "Device Locked"
@@ -395,56 +491,57 @@ msgstr ""
395491#, qt-format
396492msgid "Please wait %1 minute and then try again…"
397493msgid_plural "Please wait %1 minutes and then try again…"
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
494+msgstr[0] "برجاء الانتظار %1 دقيقة ثم المحاولة مجددًا..."
495+msgstr[1] "برجاء الانتظار دقيقة واحدة (%1) ثم المحاولة مجددًا..."
496+msgstr[2] "برجاء الانتظار دقيقتين (%1) ثم المحاولة مجددًا..."
497+msgstr[3] "برجاء الانتظار %1 دقائق ثم المحاولة مجددًا..."
498+msgstr[4] "برجاء الانتظار %1 دقيقة ثم المحاولة مجددًا..."
499+msgstr[5] "برجاء الانتظار %1 دقيقة ثم المحاولة مجددًا..."
500+
501+#: qml/Greeter/Greeter.qml:561
406502msgid "Try again"
407−msgstr "حاول مجددا"
503+msgstr ""
408504
409−#: qml/Greeter/Greeter.qml:551
505+#: qml/Greeter/Greeter.qml:562
410506msgid "Enter passphrase to unlock"
411−msgstr "أدخِل العبارة السرية لفك الإيصاد"
507+msgstr ""
412508
413−#: qml/Greeter/Greeter.qml:552
509+#: qml/Greeter/Greeter.qml:563
414510msgid "Enter passcode to unlock"
415−msgstr "أدخِل الرمز السرّي لفك الإيصاد"
511+msgstr ""
416512
417−#: qml/Greeter/NarrowView.qml:235
513+#: qml/Greeter/NarrowView.qml:242
418514msgid "Emergency"
419−msgstr "طوارئ"
515+msgstr ""
420516
421517#: qml/Greeter/PromptList.qml:126
422518msgid "Passphrase"
423−msgstr "كلمة السر"
519+msgstr ""
424520
425521#: qml/Greeter/PromptList.qml:126
426522msgid "Passcode"
427−msgstr "الرمز السري"
523+msgstr ""
428524
429−#: qml/Greeter/SessionsList.qml:124
525+#: qml/Greeter/SessionsList.qml:122
430526msgid "Select desktop environment"
431−msgstr "اختر بيئة سطح المكتب"
527+msgstr ""
432528
433−#: qml/Launcher/Drawer.qml:250
529+#: qml/Launcher/Drawer.qml:93
434530msgid "Search…"
435−msgstr "ابحث…"
531+msgstr ""
436532
437−#: qml/Launcher/PullToRefreshScopeStyle.qml:56
438−msgid "Pull to refresh…"
439−msgstr "اسحب للتحديث…"
533+#: qml/Launcher/Drawer.qml:128
534+msgctxt "Apps sorted alphabetically"
535+msgid "A-Z"
536+msgstr ""
440537
441−#: qml/Launcher/PullToRefreshScopeStyle.qml:61
442−msgid "Release to refresh…"
443−msgstr "حرّر للتحديث…"
538+#: qml/Launcher/MoreAppsHeader.qml:55
539+msgid "More apps in the store"
540+msgstr ""
444541
445542#: qml/Notifications/NotificationMenuItemFactory.qml:124
446543msgid "Show password"
447−msgstr "اعرض كلمة السر"
544+msgstr "عرض كلمة السر"
448545
449546#: qml/Panel/ActiveCallHint.qml:79
450547msgid "Tap to return to call..."
@@ -473,9 +570,9 @@ msgstr[5] "%1 ساعة"
473570#, qt-format
474571msgid "%1 minute"
475572msgid_plural "%1 minutes"
476−msgstr[0] "%1 دقيقة"
477−msgstr[1] "دقيقة واحدة"
478−msgstr[2] "دقيقتان"
573+msgstr[0] "أقل من دقيقة (%1)"
574+msgstr[1] "دقيقة واحدة (%1)"
575+msgstr[2] "دقيقتان (%1)"
479576msgstr[3] "%1 دقائق"
480577msgstr[4] "%1 دقيقة"
481578msgstr[5] "%1 دقيقة"
@@ -503,11 +600,11 @@ msgstr "باق %1"
503600
504601#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1017
505602msgid "In queue…"
506−msgstr "في الانتظار…"
603+msgstr "في الانتظار..."
507604
508605#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1021
509606msgid "Downloading"
510−msgstr "ينزل"
607+msgstr "التنزيل"
511608
512609#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1023
513610msgid "Paused, tap to resume"
@@ -515,7 +612,7 @@ msgstr "مُلبث، انقر للاستئناف"
515612
516613#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1025
517614msgid "Canceled"
518−msgstr "أُلغي"
615+msgstr "تم إلغائه"
519616
520617#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1027
521618msgid "Finished"
@@ -523,13 +620,13 @@ msgstr "انتهى"
523620
524621#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1029
525622msgid "Failed, tap to retry"
526−msgstr "فشل، انقر لإعادة المحاولة"
623+msgstr "فشل، انقل لإعادة المحاولة"
527624
528625#: qml/Panel/Indicators/MessageMenuItemFactory.qml:151
529626#: qml/Panel/Indicators/MessageMenuItemFactory.qml:210
530627msgctxt "Button: Send a reply message"
531628msgid "Send"
532−msgstr "أرسل"
629+msgstr ""
533630
534631#: qml/Panel/Indicators/MessageMenuItemFactory.qml:152
535632msgctxt "Label: Hint in message indicator line edit"
@@ -539,431 +636,353 @@ msgstr "رد"
539636#: qml/Panel/Indicators/MessageMenuItemFactory.qml:209
540637msgctxt "Button: Call back on phone"
541638msgid "Call back"
542−msgstr "عاود الاتصال"
639+msgstr ""
543640
544641#: qml/Panel/PanelMenuPage.qml:92
545642msgid "Back"
546−msgstr "للخلف"
643+msgstr ""
547644
548645#: qml/Stage/SideStage.qml:76
549646msgid "Drag using 3 fingers any application from one window to the other"
550−msgstr "اسحب أي تطبيق بثلاث أصابع من نافذة لأخرى"
551−
552−#: qml/Stage/Stage.qml:671
553−msgid "No running apps"
554−msgstr "لا توجد تطبيقات مشغلة"
647+msgstr ""
555648
556649#: qml/Tutorial/TutorialLeftLong.qml:49
557650msgid "Long swipe from the left edge to open the Application Drawer"
558−msgstr "اسحب اصبعك مطولا بدءً من الحافة اليسرى لفتح درج التطبيقات"
651+msgstr ""
559652
560653#: qml/Tutorial/TutorialLeft.qml:47
561654msgid "Short swipe from the left edge to open the launcher"
562−msgstr "اسحب اصبعك سحبا قصيرا بدءً من الحافة اليسرى لفتح المُطلِق"
655+msgstr ""
563656
564−#: qml/Tutorial/TutorialRight.qml:54
657+#: qml/Tutorial/TutorialRight.qml:55
565658msgid "Push your mouse against the right edge to view your open apps"
566−msgstr "حرك المؤشر للحافة اليمنى لعرض التطبيقات المفتوحة"
659+msgstr ""
567660
568−#: qml/Tutorial/TutorialRight.qml:55
661+#: qml/Tutorial/TutorialRight.qml:56
569662msgid "Swipe from the right edge to view your open apps"
570−msgstr "اسحب اصبعك بدءً من الحافة اليمنى لعرض التطبيقات المفتوحة"
663+msgstr ""
571664
572665#: qml/Tutorial/TutorialTop.qml:53
573666msgid "Swipe from the top edge to access notifications and quick settings"
574667msgstr ""
575−"اسحب اصبعك بدءً من الحافة العلوية للوصول الى التنبيهات والإعدادات السريعة"
576668
577−#: qml/Wizard/Page.qml:59
669+#: qml/Wizard/Page.qml:54
578670msgctxt "Button: Go back one page in the Wizard"
579671msgid "Back"
580−msgstr "للخلف"
672+msgstr "عودة"
581673
582−#: qml/Wizard/Pages/10-welcome.qml:29
674+#: qml/Wizard/Pages/10-welcome.qml:28
583675msgid "Language"
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
593−msgid "Next"
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 "ما الجديد"
676+msgstr ""
607677
608−#: qml/Wizard/Pages/11-changelog.qml:74
609−msgid "Loading..."
610−msgstr "يحمل..."
678+#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
679+#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
680+#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
681+#: qml/Wizard/Pages/70-passwd-type.qml:145
682+#: qml/Wizard/Pages/75-report-check.qml:84
683+#: qml/Wizard/Pages/passcode-desktop.qml:142
684+#: qml/Wizard/Pages/password-set.qml:142
685+msgid "Next"
686+msgstr ""
611687
612688#: qml/Wizard/Pages/20-keyboard.qml:31
613689msgid "Select Keyboard"
614−msgstr "اختر لوحة المفاتيح"
690+msgstr ""
615691
616692#: qml/Wizard/Pages/20-keyboard.qml:71
617693msgid "Keyboard language"
618−msgstr "لغة لوحة المفاتيح"
694+msgstr ""
619695
620696#: qml/Wizard/Pages/20-keyboard.qml:93
621697msgid "Keyboard layout"
622−msgstr "تخطيط لوحة المفاتيح"
698+msgstr ""
623699
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
700+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
701+#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
626702#: qml/Wizard/Pages/sim.qml:101
627703msgid "Skip"
628−msgstr "تخط"
704+msgstr "تخطي"
629705
630706#: qml/Wizard/Pages/30-wifi.qml:31
631707msgid "Connect to Wi‑Fi"
632−msgstr "اتصل بالإنترنت"
708+msgstr "اتصل بالواي فاي"
633709
634−#: qml/Wizard/Pages/30-wifi.qml:139
710+#: qml/Wizard/Pages/30-wifi.qml:132
635711msgid "Connected"
636−msgstr "متصل"
712+msgstr ""
637713
638−#: qml/Wizard/Pages/30-wifi.qml:172
714+#: qml/Wizard/Pages/30-wifi.qml:165
639715msgid "Available Wi-Fi networks"
640−msgstr "شبكات الواي فاي المتاحة"
716+msgstr ""
641717
642−#: qml/Wizard/Pages/30-wifi.qml:173
718+#: qml/Wizard/Pages/30-wifi.qml:166
643719msgid "No available Wi-Fi networks"
644−msgstr "لا توجد شبكات واي فاي"
720+msgstr ""
721+
722+#: qml/Wizard/Pages/40-location.qml:27
723+msgid "Location Services"
724+msgstr ""
725+
726+#: qml/Wizard/Pages/40-location.qml:83
727+msgid ""
728+"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
729+"(recommended)"
730+msgstr ""
731+
732+#: qml/Wizard/Pages/40-location.qml:105
733+#, qt-format
734+msgid "By selecting this option you agree to the Nokia HERE %1."
735+msgstr ""
736+
737+#: qml/Wizard/Pages/40-location.qml:106
738+msgctxt "part of: Nokia HERE terms and conditions"
739+msgid "terms and conditions"
740+msgstr ""
741+
742+#: qml/Wizard/Pages/40-location.qml:160
743+msgid "GPS only"
744+msgstr ""
745+
746+#: qml/Wizard/Pages/40-location.qml:214
747+msgid "Don't use my location"
748+msgstr ""
749+
750+#: qml/Wizard/Pages/40-location.qml:260
751+msgid "You can change it later in System Settings."
752+msgstr ""
645753
646754#: qml/Wizard/Pages/50-timezone.qml:30
647755msgid "Time Zone"
648−msgstr "المنطقة الزمنية"
756+msgstr ""
649757
650−#: qml/Wizard/Pages/50-timezone.qml:183
758+#: qml/Wizard/Pages/50-timezone.qml:182
651759msgid "Enter your city"
652−msgstr "أدخل مدينتك"
760+msgstr ""
653761
654762#: qml/Wizard/Pages/60-account.qml:24
655763msgid "Personalize Your Device"
656−msgstr "خصص جهازك"
764+msgstr ""
657765
658−#: qml/Wizard/Pages/60-account.qml:54
766+#: qml/Wizard/Pages/60-account.qml:48
659767msgid "Preferred Name"
660−msgstr "اسم مستحسن"
768+msgstr ""
661769
662770#: qml/Wizard/Pages/70-passwd-type.qml:40
663771msgid "Lock Screen"
664−msgstr "قفل الشاشة"
772+msgstr ""
665773
666−#: qml/Wizard/Pages/70-passwd-type.qml:103
774+#: qml/Wizard/Pages/70-passwd-type.qml:102
667775msgctxt "Label: Type of security method"
668776msgid "Create new password"
669−msgstr "أنشئ كلمة سر جديدة"
777+msgstr ""
670778
671−#: qml/Wizard/Pages/70-passwd-type.qml:105
779+#: qml/Wizard/Pages/70-passwd-type.qml:104
672780msgctxt "Label: Type of security method"
673781msgid "Create passcode (numbers only)"
674−msgstr "أنشئ رمز مرور (أرقام فقط)"
782+msgstr ""
675783
676−#: qml/Wizard/Pages/70-passwd-type.qml:107
784+#: qml/Wizard/Pages/70-passwd-type.qml:106
677785msgctxt "Label: Type of security method"
678786msgid "No lock code"
679−msgstr "لا يوجد رمز إيصاد"
787+msgstr ""
788+
789+#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
790+msgid "Privacy Policy"
791+msgstr ""
792+
793+#: qml/Wizard/Pages/75-report-check.qml:26
794+msgid "Help Us Improve"
795+msgstr ""
796+
797+#: qml/Wizard/Pages/75-report-check.qml:59
798+msgid "Improve system performance by sending us crashes and error reports."
799+msgstr ""
800+
801+#: qml/Wizard/Pages/75-report-check.qml:60
802+msgid "Privacy policy"
803+msgstr ""
680804
681−#: qml/Wizard/Pages/79-system-update.qml:28
805+#: qml/Wizard/Pages/77-system-update.qml:28
682806msgid "Update Device"
683−msgstr "حدث الجهاز"
807+msgstr ""
684808
685−#: qml/Wizard/Pages/79-system-update.qml:55
809+#: qml/Wizard/Pages/77-system-update.qml:55
686810msgid ""
687811"There is a system update available and ready to install. Afterwards, the "
688812"device will automatically restart."
689−msgstr "يتوفر تحديث للنظام وهو جاهز للتثبيت، سيُعاد تشغيل الجهاز تلقائيا."
813+msgstr ""
690814
691−#: qml/Wizard/Pages/79-system-update.qml:76
815+#: qml/Wizard/Pages/77-system-update.qml:76
692816msgctxt "string identifying name of the update"
693−msgid "Ubuntu Touch system"
694−msgstr "نظام أبونتو تاتش"
817+msgid "Ubuntu system"
818+msgstr ""
695819
696−#: qml/Wizard/Pages/79-system-update.qml:83
820+#: qml/Wizard/Pages/77-system-update.qml:83
697821#, qt-format
698822msgctxt "version of the system update"
699823msgid "Version %1"
700−msgstr "الإصدار %1"
824+msgstr ""
701825
702−#: qml/Wizard/Pages/79-system-update.qml:95
826+#: qml/Wizard/Pages/77-system-update.qml:102
703827msgid "This could take a few minutes..."
704−msgstr "قد يحتاج بضع دقائق..."
828+msgstr ""
705829
706−#: qml/Wizard/Pages/79-system-update.qml:109
830+#: qml/Wizard/Pages/77-system-update.qml:116
707831msgid "Install and restart now"
708−msgstr "ثبت وأعد التشغيل الآن"
709−
710−#: qml/Wizard/Pages/80-finished.qml:91
711−msgid "Welcome Back"
712−msgstr "مرحبا بعودتك"
832+msgstr ""
713833
714−#: qml/Wizard/Pages/80-finished.qml:91
834+#: qml/Wizard/Pages/80-finished.qml:89
715835msgid "Welcome to Ubuntu"
716−msgstr "مرحبا بك في أبونتو"
836+msgstr ""
717837
718−#: qml/Wizard/Pages/80-finished.qml:106
838+#: qml/Wizard/Pages/80-finished.qml:104
719839msgid "You are ready to use your device now"
720−msgstr "أنت مستعد لاستخدام جهازك"
721−
722−#: qml/Wizard/Pages/80-finished.qml:126
723−msgid "Continue"
724−msgstr "تابع"
840+msgstr ""
725841
726−#: qml/Wizard/Pages/80-finished.qml:126
842+#: qml/Wizard/Pages/80-finished.qml:124
727843msgid "Get Started"
728−msgstr "ابدأ"
844+msgstr ""
845+
846+#: qml/Wizard/Pages/here-terms.qml:25
847+msgid "Terms & Conditions"
848+msgstr "الشروط والأحكام"
849+
850+#: qml/Wizard/Pages/here-terms.qml:69
851+msgid "Your device uses positioning technologies provided by HERE."
852+msgstr ""
853+
854+#: qml/Wizard/Pages/here-terms.qml:81
855+msgid ""
856+"To provide you with positioning services and to improve their quality, HERE "
857+"collects information about nearby cell towers and Wi-Fi hotspots around your "
858+"current location whenever your position is being found."
859+msgstr ""
860+
861+#: qml/Wizard/Pages/here-terms.qml:93
862+msgid ""
863+"The information collected is used to analyze the service and to improve the "
864+"use of service, but not to identify you personally."
865+msgstr ""
866+
867+#: qml/Wizard/Pages/here-terms.qml:106
868+#, qt-format
869+msgid "By continuing, you agree to the HERE platform %1 and %2."
870+msgstr ""
871+
872+#: qml/Wizard/Pages/here-terms.qml:107
873+msgid "Service Terms"
874+msgstr ""
729875
730876#: qml/Wizard/Pages/passcode-confirm.qml:43
731−#: qml/Wizard/Pages/passcode-desktop.qml:104
877+#: qml/Wizard/Pages/passcode-desktop.qml:97
732878msgid "Confirm passcode"
733−msgstr "تأكيد كلمة السر"
879+msgstr "تأكيد الرمز السري"
734880
735881#: qml/Wizard/Pages/passcode-confirm.qml:45
736882msgid "Incorrect passcode."
737−msgstr "الرمز السري غير صحيح."
883+msgstr ""
738884
739885#: qml/Wizard/Pages/passcode-confirm.qml:45
740886msgctxt "Enter the passcode again"
741887msgid "Please re-enter."
742−msgstr "رجاء أعد الإدخال."
888+msgstr ""
743889
744890#: qml/Wizard/Pages/passcode-desktop.qml:31
745891msgid "Lock Screen Passcode"
746−msgstr "الرمز السري لقفل الشاشة"
892+msgstr ""
747893
748−#: qml/Wizard/Pages/passcode-desktop.qml:68
894+#: qml/Wizard/Pages/passcode-desktop.qml:61
749895msgid "Enter 4 numbers to setup your passcode"
750−msgstr "أدخل 4 أرقام لإعداد الرمز السري"
896+msgstr ""
751897
752−#: qml/Wizard/Pages/passcode-desktop.qml:84
898+#: qml/Wizard/Pages/passcode-desktop.qml:77
753899#: qml/Wizard/Pages/passcode-set.qml:54
754900msgid "Choose passcode"
755−msgstr "اختر كلمة السر"
901+msgstr ""
756902
757−#: qml/Wizard/Pages/passcode-desktop.qml:139
903+#: qml/Wizard/Pages/passcode-desktop.qml:127
758904msgid "Passcode too short"
759−msgstr "الرمز السري قصير جدا"
905+msgstr ""
760906
761−#: qml/Wizard/Pages/passcode-desktop.qml:141
907+#: qml/Wizard/Pages/passcode-desktop.qml:129
762908msgid "Passcodes match"
763−msgstr "الرمزان السريان متطابقة"
909+msgstr ""
764910
765−#: qml/Wizard/Pages/passcode-desktop.qml:143
911+#: qml/Wizard/Pages/passcode-desktop.qml:131
766912msgid "Passcodes do not match"
767−msgstr "الرمزان السريان لا يتطبقان"
913+msgstr ""
768914
769915#: qml/Wizard/Pages/passcode-set.qml:62
770916msgid "Passcode must be 4 characters long"
771−msgstr "يجب أن يكون الرمز السري 4 محارف"
917+msgstr ""
772918
773919#: qml/Wizard/Pages/password-set.qml:31
774920msgid "Lock Screen Password"
775−msgstr "كلمة سر قفل الشاشة"
921+msgstr ""
776922
777−#: qml/Wizard/Pages/password-set.qml:68
923+#: qml/Wizard/Pages/password-set.qml:62
778924msgid "Enter at least 8 characters"
779−msgstr "أدخل 8 محارف على الأقل"
925+msgstr ""
780926
781−#: qml/Wizard/Pages/password-set.qml:80
927+#: qml/Wizard/Pages/password-set.qml:74
782928msgid "Choose password"
783−msgstr "اختر كلمة السر"
929+msgstr ""
784930
785−#: qml/Wizard/Pages/password-set.qml:110
931+#: qml/Wizard/Pages/password-set.qml:104
786932msgid "Confirm password"
787−msgstr "أكد كلمة السر"
933+msgstr ""
788934
789935#: qml/Wizard/Pages/sim.qml:27
790936msgid "No SIM card installed"
791−msgstr "لم تدخل بطاقة SIM"
937+msgstr ""
792938
793939#: qml/Wizard/Pages/sim.qml:54
794940msgid "SIM card added"
795−msgstr "أُدخلت بطاقة SIM"
941+msgstr ""
796942
797943#: qml/Wizard/Pages/sim.qml:55
798944msgid "You must restart the device to access the mobile network."
799−msgstr "يجب عليك إعادة تشغيل الجهاز لتتمكن من دخول شبكة الجوال."
945+msgstr ""
800946
801947#: qml/Wizard/Pages/sim.qml:59
802948msgid "Restart"
803−msgstr "أعد التشغيل"
949+msgstr ""
804950
805951#: qml/Wizard/Pages/sim.qml:78
806952msgid "You won’t be able to make calls or use text messaging without a SIM."
807−msgstr "لن تتمكن من إجراء المكالمات أو إرسال الرسائل القصيرة بدون بطاقة SIM."
953+msgstr ""
808954
809955#: qml/Wizard/Pages/sim.qml:90
810956msgid "To proceed with no SIM tap Skip."
811−msgstr "للاستمرار بدون بطاقة SIM اضغط تخطى."
957+msgstr ""
812958
813959#: qml/Wizard/PasswordMeter.qml:87
814960msgid "Password too short"
815−msgstr "كلمة السر قصيرة جداً"
961+msgstr ""
816962
817963#: qml/Wizard/PasswordMeter.qml:89
818964msgid "Passwords match"
819−msgstr "كلمتا المرور متطابقتان"
965+msgstr ""
820966
821967#: qml/Wizard/PasswordMeter.qml:91
822968msgid "Passwords do not match"
823−msgstr "كلمتا المرور غير متطابقتين"
969+msgstr ""
824970
825971#: qml/Wizard/PasswordMeter.qml:95
826972msgid "Strong password"
827−msgstr "كلمة سر قوية"
973+msgstr ""
828974
829975#: qml/Wizard/PasswordMeter.qml:97
830976msgid "Fair password"
831−msgstr "كلمة سر متوسطة"
977+msgstr ""
832978
833979#: qml/Wizard/PasswordMeter.qml:99
834980msgid "Weak password"
835−msgstr "كلمة سر ضعيفة"
981+msgstr ""
836982
837983#: qml/Wizard/PasswordMeter.qml:101
838984msgid "Very weak password"
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 "الشروط والأحكام"
985+msgstr ""
967986
968987#~ msgid "Confirm"
969988#~ msgstr "التأكيد"
@@ -971,9 +990,21 @@ msgstr "كلمة السر ضعيفة جداً"
971990#~ msgid "Type or say a command"
972991#~ msgstr "اكتب أو قُل أمرا"
973992
993+#~ msgid "Loading. Please Wait..."
994+#~ msgstr "يجري التحميل. برجاء الانتظار..."
995+
974996#~ msgid "Speak Now..."
975997#~ msgstr "تكلم الآن..."
976998
999+#~ msgid "Speaking..."
1000+#~ msgstr "تتكلم الآن..."
1001+
1002+#~ msgid "Search"
1003+#~ msgstr "ابحث"
1004+
1005+#~ msgid "Try swiping from the top edge to access the indicators"
1006+#~ msgstr "اسحب اصبعك من الحافة العلوية للوصول إلى المؤشرات"
1007+
9771008#~ msgid "Top edge"
9781009#~ msgstr "الحافة العلوية"
9791010
@@ -1009,8 +1040,8 @@ msgstr "كلمة السر ضعيفة جداً"
10091040#~ "You have now mastered the edge gestures and can start using the "
10101041#~ "phone<br><br>Tap on the screen to start"
10111042#~ msgstr ""
1012−#~ "أنت الآن بارع في إيماءات الحواف ويمكنك البدء باستخدام هاتفك<br><br>انقر "
1013−#~ "على الشاشة للبدء"
1043+#~ "أنت الآن بارع في إيماءات الحواف ويمكنك البدء باستخدام هاتفك<br><br>انقر على "
1044+#~ "الشاشة للبدء"
10141045
10151046#~ msgid "%a %l:%M %p"
10161047#~ msgstr "%a %l:%M %p"
@@ -1063,18 +1094,26 @@ msgstr "كلمة السر ضعيفة جداً"
10631094#~ msgid "Tap to unlock"
10641095#~ msgstr "انقر لفك القفل"
10651096
1097+#, qt-format
10661098#~ msgid "Enter %1"
10671099#~ msgstr "أدخِل %1"
10681100
10691101#~ msgid "Sorry, incorrect passcode."
10701102#~ msgstr "عذرًا، رمز سرّي خاطيء."
10711103
1104+#~ msgid "Enter passphrase"
1105+#~ msgstr "أدخِل العبارة السرية"
1106+
1107+#~ msgid "Enter passcode"
1108+#~ msgstr "أدخِل الرمز السرّي"
1109+
10721110#~ msgid "Sorry, incorrect passphrase."
10731111#~ msgstr "عذرًا، عبارة سرّية خاطئة."
10741112
10751113#~ msgid "This will be your last attempt."
10761114#~ msgstr "هذه ستكون المحاولة الأخيرة لك."
10771115
1116+#, qt-format
10781117#~ msgid "Sorry, incorrect %1"
10791118#~ msgstr "نأسف، %1 غير صحيحية"
10801119
@@ -1145,6 +1184,9 @@ msgstr "كلمة السر ضعيفة جداً"
11451184#~ msgid "Let’s get started."
11461185#~ msgstr "هيا بنا نبدأ."
11471186
1187+#~ msgid "Continue"
1188+#~ msgstr "متابعة"
1189+
11481190#~ msgid "Choose your passcode"
11491191#~ msgstr "اختر الرمز السري خاصتك"
11501192
@@ -1241,15 +1283,15 @@ msgstr "كلمة السر ضعيفة جداً"
12411283#~ msgstr "فتح قفل بطاقة SIM"
12421284
12431285#~ msgid ""
1244−#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms "
1245−#~ "and conditions</a>."
1286+#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
1287+#~ "conditions</a>."
12461288#~ msgstr ""
1247−#~ "باختيارك لهذا الخيار فإنك توافق على <a href='#'>الشروط والأحكام</a> "
1248−#~ "الخاصة بـ Nokia HERE."
1289+#~ "باختيارك لهذا الخيار فإنك توافق على <a href='#'>الشروط والأحكام</a> الخاصة "
1290+#~ "بـ Nokia HERE."
12491291
12501292#~ msgid ""
1251−#~ "If passcode is entered incorrectly, your phone will conduct a factory "
1252−#~ "reset and all personal data will be deleted."
1293+#~ "If passcode is entered incorrectly, your phone will conduct a factory reset "
1294+#~ "and all personal data will be deleted."
12531295#~ msgstr ""
12541296#~ "إذا تم إدخال العبارة السرية بشكل خاطئ، فسوف يتم إعادة الهاتف لحالة ضبط "
12551297#~ "المصنع وسيتم حذف كافة البيانات الشخصية."
@@ -1260,3 +1302,9 @@ msgstr "كلمة السر ضعيفة جداً"
12601302#~ msgstr ""
12611303#~ "إذا تم إدخال العبارة السرية بشكل خاطئ، فسوف يتم إعادة الهاتف لحالة ضبط "
12621304#~ "المصنع وسيتم حذف كافة البيانات الشخصية."
1305+
1306+#~ msgid "Takes a screenshot of a window."
1307+#~ msgstr "أخذ لقطة شاشة للنافذة"
1308+
1309+#~ msgid "Super + 0 to 9"
1310+#~ msgstr "Super + 0 to 9"
po/ast.po+478−495
@@ -6,69 +6,67 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity8\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"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2017-03-21 10:58+0000\n"
11+"PO-Revision-Date: 2016-12-16 02:13+0000\n"
1212"Last-Translator: enolp <enolp@softastur.org>\n"
13−"Language-Team: Asturian <https://translate.ubports.com/projects/unity8/"
14−"unity8/ast/>\n"
15−"Language: ast\n"
13+"Language-Team: Asturian <ast@li.org>\n"
1614"MIME-Version: 1.0\n"
1715"Content-Type: text/plain; charset=UTF-8\n"
1816"Content-Transfer-Encoding: 8bit\n"
1917"Plural-Forms: nplurals=2; plural=n != 1;\n"
20−"X-Generator: Weblate 3.8\n"
21−"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
18+"X-Launchpad-Export-Date: 2017-03-24 06:12+0000\n"
19+"X-Generator: Launchpad (build 18334)\n"
2220
23−#: plugins/LightDM/Greeter.cpp:199
21+#: plugins/LightDM/Greeter.cpp:188
2422msgid "Password: "
2523msgstr "Contraseña: "
2624
27−#: plugins/LightDM/Greeter.cpp:214
25+#: plugins/LightDM/Greeter.cpp:203
2826msgid "Username"
2927msgstr ""
3028
31−#: plugins/LightDM/Greeter.cpp:258
29+#: plugins/LightDM/Greeter.cpp:242
3230msgid "Failed to authenticate"
3331msgstr ""
3432
35−#: plugins/LightDM/Greeter.cpp:260
33+#: plugins/LightDM/Greeter.cpp:244
3634msgid "Invalid password, please try again"
3735msgstr ""
3836
39−#: plugins/LightDM/Greeter.cpp:270
37+#: plugins/LightDM/Greeter.cpp:254
4038msgid "Log In"
41−msgstr ""
39+msgstr "Aniciar sesión"
4240
43−#: plugins/LightDM/Greeter.cpp:270
41+#: plugins/LightDM/Greeter.cpp:254
4442msgid "Retry"
45−msgstr ""
43+msgstr "Reintentar"
4644
47−#: plugins/LightDM/UsersModel.cpp:157
45+#: plugins/LightDM/UsersModel.cpp:152
4846msgid "Login"
4947msgstr ""
5048
51−#: plugins/LightDM/UsersModel.cpp:165
49+#: plugins/LightDM/UsersModel.cpp:160
5250msgid "Guest Session"
5351msgstr ""
5452
55−#: plugins/Unity/Launcher/launcheritem.cpp:48
56−#: plugins/Unity/Launcher/launcheritem.cpp:122
53+#: plugins/Unity/Launcher/launcheritem.cpp:49
54+#: plugins/Unity/Launcher/launcheritem.cpp:123
5755msgid "Pin shortcut"
58−msgstr "Fixar l'atayu"
56+msgstr "Anclar atayu"
5957
60−#: plugins/Unity/Launcher/launcheritem.cpp:54
58+#: plugins/Unity/Launcher/launcheritem.cpp:55
6159msgid "Quit"
6260msgstr "Colar"
6361
64−#: plugins/Unity/Launcher/launcheritem.cpp:122
62+#: plugins/Unity/Launcher/launcheritem.cpp:123
6563msgid "Unpin shortcut"
66−msgstr "Quitar l'atayu"
64+msgstr "Desanclar atayu"
6765
6866#: qml/Components/Dialogs.qml:176
6967msgctxt "Title: Lock/Log out dialog"
7068msgid "Log out"
71−msgstr "Zarru de la sesión"
69+msgstr "Zarrar sesión"
7270
7371#: qml/Components/Dialogs.qml:177
7472msgid "Are you sure you want to log out?"
@@ -84,8 +82,9 @@ msgctxt "Button: Log out from the system"
8482msgid "Log Out"
8583msgstr "Zarrar sesión"
8684
87−#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
88−#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
85+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:264
86+#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:222
87+#: qml/Wizard/Pages/passcode-confirm.qml:32
8988#: qml/Wizard/Pages/passcode-set.qml:32
9089msgid "Cancel"
9190msgstr "Encaboxar"
@@ -107,42 +106,36 @@ msgstr "Non"
107106msgid "Yes"
108107msgstr "Sí"
109108
110−#: qml/Components/Dialogs.qml:243
109+#: qml/Components/Dialogs.qml:239
111110msgctxt "Title: Power off/Restart dialog"
112111msgid "Power"
113−msgstr "Enerxía"
112+msgstr "Apagáu"
114113
115−#: qml/Components/Dialogs.qml:244
114+#: qml/Components/Dialogs.qml:240
116115msgid ""
117116"Are you sure you would like\n"
118117"to power off?"
119118msgstr ""
120−"¿De xuru que quies\n"
119+"¿De xuru que te prestaría\n"
121120"apagar?"
122121
123−#: qml/Components/Dialogs.qml:248
122+#: qml/Components/Dialogs.qml:244
124123msgctxt "Button: Power off the system"
125124msgid "Power off"
126125msgstr "Apagar"
127126
128−#: qml/Components/Dialogs.qml:263
127+#: qml/Components/Dialogs.qml:255
129128msgctxt "Button: Restart the system"
130129msgid "Restart"
131130msgstr "Reaniciar"
132131
133−#: qml/Components/Dialogs.qml:276
134−#, fuzzy
135−#| msgid "Takes a screenshot."
136−msgid "Screenshot"
137−msgstr "Fai una captura de pantalla."
138−
139132#: qml/Components/KeyboardShortcutsOverlay.qml:41
140133msgid "Keyboard Shortcuts"
141−msgstr "Atayos del tecláu"
134+msgstr "Atayos de tecláu"
142135
143136#: qml/Components/KeyboardShortcutsOverlay.qml:55
144−msgid "Lomiri"
145−msgstr ""
137+msgid "Unity 8"
138+msgstr "Unity 8"
146139
147140#: qml/Components/KeyboardShortcutsOverlay.qml:62
148141msgid "PrtScr"
@@ -150,169 +143,163 @@ msgstr "ImprPant"
150143
151144#: qml/Components/KeyboardShortcutsOverlay.qml:67
152145msgid "Takes a screenshot."
153−msgstr "Fai una captura de pantalla."
146+msgstr "Saca una imaxe de la pantalla."
154147
155148#: qml/Components/KeyboardShortcutsOverlay.qml:75
156149msgid "Alt + PrtScr"
157150msgstr "Alt + ImprPant"
158151
159152#: qml/Components/KeyboardShortcutsOverlay.qml:80
160−#, fuzzy
161−#| msgid "Takes a screenshot of a window."
162153msgid "Takes a screenshot of the current window."
163−msgstr "Fai una captura d'una ventana."
154+msgstr ""
164155
165156#: qml/Components/KeyboardShortcutsOverlay.qml:88
166157msgid "Super + Space"
167−msgstr "Súper + Espaciu"
158+msgstr "Super + Espaciu"
168159
169160#: qml/Components/KeyboardShortcutsOverlay.qml:93
170161msgid "Switches to next keyboard layout."
171−msgstr "Cambia a la distribución siguiente del tecláu."
162+msgstr "Salta al siguiente diseñu de tecláu."
172163
173164#: qml/Components/KeyboardShortcutsOverlay.qml:101
174165msgid "Super + Shift + Space"
175−msgstr "Súper + Mayús + Espaciu"
166+msgstr "Super +Mayús + Espaciu"
176167
177168#: qml/Components/KeyboardShortcutsOverlay.qml:106
178169msgid "Switches to previous keyboard layout."
179−msgstr "Cambia a la distribución anterior del tecláu."
170+msgstr "Salta al diseñu de tecláu anterior."
180171
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
172+#: qml/Components/KeyboardShortcutsOverlay.qml:118
192173msgid "Launcher"
193174msgstr "Llanzador"
194175
195−#: qml/Components/KeyboardShortcutsOverlay.qml:138
176+#: qml/Components/KeyboardShortcutsOverlay.qml:125
196177msgid "Super (Hold)"
197−msgstr ""
178+msgstr "Super (Caltener)"
198179
199−#: qml/Components/KeyboardShortcutsOverlay.qml:143
180+#: qml/Components/KeyboardShortcutsOverlay.qml:130
200181msgid "Opens the launcher, displays shortcuts."
201−msgstr "Abre'l llanzador, amuesa los atayos."
182+msgstr "Abre'l llanzador, amuesa atayos."
202183
203−#: qml/Components/KeyboardShortcutsOverlay.qml:151
184+#: qml/Components/KeyboardShortcutsOverlay.qml:138
204185msgid "Alt + F1"
205186msgstr "Alt + F1"
206187
207−#: qml/Components/KeyboardShortcutsOverlay.qml:156
188+#: qml/Components/KeyboardShortcutsOverlay.qml:143
208189msgid "Opens launcher keyboard navigation mode."
209−msgstr ""
190+msgstr "Abre'l mou de navegación con tecláu del llanzador."
210191
211−#: qml/Components/KeyboardShortcutsOverlay.qml:164
192+#: qml/Components/KeyboardShortcutsOverlay.qml:151
212193msgid "Super + Tab"
213−msgstr "Súper + Tabulador"
194+msgstr "Super + Tab"
214195
215−#: qml/Components/KeyboardShortcutsOverlay.qml:169
196+#: qml/Components/KeyboardShortcutsOverlay.qml:156
216197msgid "Switches applications via the launcher."
217−msgstr ""
198+msgstr "Cambia d'aplicaciones col llanzador."
218199
219−#: qml/Components/KeyboardShortcutsOverlay.qml:177
220−#, fuzzy
221−#| msgid "Super + 0 to 9"
200+#: qml/Components/KeyboardShortcutsOverlay.qml:164
222201msgid "Super + 1 to 0"
223−msgstr "Súper + 0 a 9"
202+msgstr ""
224203
225−#: qml/Components/KeyboardShortcutsOverlay.qml:182
204+#: qml/Components/KeyboardShortcutsOverlay.qml:169
226205msgid "Same as clicking on a launcher icon."
227−msgstr "Igual que calcar nun iconu del llanzador."
206+msgstr "Igual que facer click nel iconu del llanzador."
228207
229−#: qml/Components/KeyboardShortcutsOverlay.qml:190
230−#, fuzzy
231−#| msgid "Super + W"
208+#: qml/Components/KeyboardShortcutsOverlay.qml:177
232209msgid "Super + A"
233−msgstr "Súper + W"
210+msgstr ""
234211
235−#: qml/Components/KeyboardShortcutsOverlay.qml:195
236−#, fuzzy
237−#| msgid "Open the launcher"
212+#: qml/Components/KeyboardShortcutsOverlay.qml:182
238213msgid "Opens the Application Drawer."
239−msgstr "Abrir el llanzador"
214+msgstr "Abre'l caxón d'aplicaciones."
215+
216+#: qml/Components/KeyboardShortcutsOverlay.qml:194
217+msgid "Scopes"
218+msgstr "Ámbitos"
219+
220+#: qml/Components/KeyboardShortcutsOverlay.qml:201
221+msgid "Super (Tap)"
222+msgstr "Super (Tocar)"
223+
224+#: qml/Components/KeyboardShortcutsOverlay.qml:206
225+msgid "Opens the Scopes home."
226+msgstr "Abre'l principiu d'Ámbitos"
240227
241−#: qml/Components/KeyboardShortcutsOverlay.qml:235
228+#: qml/Components/KeyboardShortcutsOverlay.qml:222
242229msgid "Switching"
243−msgstr "Cambéu"
230+msgstr "Conmutación"
244231
245−#: qml/Components/KeyboardShortcutsOverlay.qml:242
232+#: qml/Components/KeyboardShortcutsOverlay.qml:229
246233msgid "Alt + Tab"
247−msgstr "Alt + Tabulador"
234+msgstr "Alt + Tab"
248235
249−#: qml/Components/KeyboardShortcutsOverlay.qml:247
236+#: qml/Components/KeyboardShortcutsOverlay.qml:234
250237msgid "Switches between applications."
251−msgstr ""
238+msgstr "Conmuta ente aplicaciones."
252239
253−#: qml/Components/KeyboardShortcutsOverlay.qml:255
240+#: qml/Components/KeyboardShortcutsOverlay.qml:242
254241msgid "Super + W"
255−msgstr "Súper + W"
242+msgstr "Super + W"
256243
257−#: qml/Components/KeyboardShortcutsOverlay.qml:260
244+#: qml/Components/KeyboardShortcutsOverlay.qml:247
258245msgid "Opens the desktop spread."
259−msgstr ""
246+msgstr "Abre esparder l'escritoriu."
260247
261−#: qml/Components/KeyboardShortcutsOverlay.qml:268
248+#: qml/Components/KeyboardShortcutsOverlay.qml:255
262249msgid "Cursor Left or Right"
263−msgstr ""
250+msgstr "Flecha izq. o dre."
264251
265−#: qml/Components/KeyboardShortcutsOverlay.qml:273
252+#: qml/Components/KeyboardShortcutsOverlay.qml:260
266253msgid "Moves the focus."
267−msgstr "Mueve'l focu."
254+msgstr "Mueve'l focu"
268255
269−#: qml/Components/KeyboardShortcutsOverlay.qml:285
256+#: qml/Components/KeyboardShortcutsOverlay.qml:272
270257msgid "Windows"
271−msgstr ""
258+msgstr "Ventanes"
272259
273−#: qml/Components/KeyboardShortcutsOverlay.qml:292
260+#: qml/Components/KeyboardShortcutsOverlay.qml:279
274261msgid "Ctrl + Super + D"
275−msgstr "Ctrl + Súper + D"
262+msgstr "Ctrl + Super + D"
276263
277−#: qml/Components/KeyboardShortcutsOverlay.qml:297
264+#: qml/Components/KeyboardShortcutsOverlay.qml:284
278265msgid "Minimizes all windows."
279−msgstr "Minimiza toles ventanes."
266+msgstr "Amenorga toles ventanes."
280267
281−#: qml/Components/KeyboardShortcutsOverlay.qml:305
268+#: qml/Components/KeyboardShortcutsOverlay.qml:292
282269msgid "Ctrl + Super + Up"
283−msgstr "Ctrl + Súper + Arriba"
270+msgstr "Ctrl + Super + Arriba"
284271
285−#: qml/Components/KeyboardShortcutsOverlay.qml:310
272+#: qml/Components/KeyboardShortcutsOverlay.qml:297
286273msgid "Maximizes the current window."
287274msgstr "Maximiza la ventana actual."
288275
289−#: qml/Components/KeyboardShortcutsOverlay.qml:318
276+#: qml/Components/KeyboardShortcutsOverlay.qml:305
290277msgid "Ctrl + Super + Down"
291−msgstr "Ctrl + Súper + Abaxo"
278+msgstr "Ctrl + Super + Abaxo"
292279
293−#: qml/Components/KeyboardShortcutsOverlay.qml:323
280+#: qml/Components/KeyboardShortcutsOverlay.qml:310
294281msgid "Minimizes or restores the current window."
295−msgstr "Minimiza o restaura la ventana actual."
282+msgstr "Amenorga o restaura la ventana actual."
296283
297−#: qml/Components/KeyboardShortcutsOverlay.qml:331
284+#: qml/Components/KeyboardShortcutsOverlay.qml:318
298285msgid "Ctrl + Super + Left or Right"
299−msgstr "Ctrl + Súper + Esquierda o Drecha"
286+msgstr "Ctrl + Super + Izquierda o Drecha"
300287
301−#: qml/Components/KeyboardShortcutsOverlay.qml:336
288+#: qml/Components/KeyboardShortcutsOverlay.qml:323
302289msgid "Semi-maximizes the current window."
303−msgstr ""
290+msgstr "Semi-maximiza la ventana actual."
304291
305−#: qml/Components/KeyboardShortcutsOverlay.qml:344
292+#: qml/Components/KeyboardShortcutsOverlay.qml:331
306293msgid "Alt + F4"
307294msgstr "Alt + F4"
308295
309−#: qml/Components/KeyboardShortcutsOverlay.qml:349
296+#: qml/Components/KeyboardShortcutsOverlay.qml:336
310297msgid "Closes the current window."
311−msgstr "Zarra toles ventanes actuales."
298+msgstr "Zarra la ventana actual."
312299
313−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
300+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:242
314301msgid "Return to Call"
315−msgstr ""
302+msgstr "Tornar a la llamada"
316303
317304#: qml/Components/Lockscreen.qml:212
318305msgid "Emergency Call"
@@ -320,7 +307,7 @@ msgstr "Llamada d'emerxencia"
320307
321308#: qml/Components/Lockscreen.qml:245
322309msgid "OK"
323−msgstr ""
310+msgstr "Aceutar"
324311
325312#: qml/Components/MediaServices/VideoPlayerControls.qml:44
326313#, qt-format
@@ -334,25 +321,25 @@ msgstr "%1:%2"
334321
335322#: qml/Components/ModeSwitchWarningDialog.qml:33
336323msgid "Apps may have unsaved data:"
337−msgstr "Aplicaciones con datos ensin guardar:"
324+msgstr "Apps que pueden tener datos sin guardar:"
338325
339326#: qml/Components/ModeSwitchWarningDialog.qml:60
340327msgctxt ""
341328"Re-dock means connect the device again to an external screen/mouse/keyboard"
342329msgid "Re-dock, save your work and close these apps to continue."
343−msgstr ""
330+msgstr "Reconeuta, guarda'l trabayu y zarra eses apps pa siguir."
344331
345332#: qml/Components/ModeSwitchWarningDialog.qml:67
346333msgid "Or force close now (unsaved data will be lost)."
347−msgstr ""
334+msgstr "O fuerza salir agora (perderás tolos datos sin guardar)."
348335
349336#: qml/Components/ModeSwitchWarningDialog.qml:80
350337msgid "OK, I will reconnect"
351−msgstr ""
338+msgstr "D'alcuerdu, reconeutaré"
352339
353340#: qml/Components/ModeSwitchWarningDialog.qml:81
354341msgid "Reconnect now!"
355−msgstr ""
342+msgstr "Reconeutar agora."
356343
357344#: qml/Components/ModeSwitchWarningDialog.qml:94
358345msgid "Close all"
@@ -360,33 +347,128 @@ msgstr "Zarrar too"
360347
361348#: qml/Components/SharingPicker.qml:54
362349msgid "Preview Share Item"
363−msgstr ""
350+msgstr "Entever l'elementu compartíu"
364351
365352#: qml/Components/VirtualTouchPad.qml:317
366353msgid ""
367354"Your device is now connected to an external display. Use this screen as a "
368355"touch pad to interact with the pointer."
369356msgstr ""
370−"Agora'l preséu ta coneutáu a una pantalla esterna. Usa esta pantalla como "
371−"panel táutil pa interactuar col punteru."
357+"El preséu agora ta coneutáu con una pantalla esterna. Usa esta pantalla como "
358+"touch pad pa interactuar col punteru."
372359
373360#: qml/Components/VirtualTouchPad.qml:327
374−#, fuzzy
375−#| msgid "Tap to return to call..."
376361msgid "Tap left button to click."
377−msgstr "Toca pa volver a la llamada…"
362+msgstr "Calca nel botón esquierdu pa facer clic."
378363
379364#: qml/Components/VirtualTouchPad.qml:339
380365msgid "Tap right button to right click."
381−msgstr ""
366+msgstr "Calca nel botón drechu pa facer clic."
382367
383368#: qml/Components/VirtualTouchPad.qml:351
384369msgid "Swipe with two fingers to scroll."
385−msgstr ""
370+msgstr "Esliza con dos deos pa desplazate."
386371
387372#: qml/Components/VirtualTouchPad.qml:396
388373msgid "Find more settings in the system settings."
389−msgstr ""
374+msgstr "Alcuentra más axustes nos Axustes del Sistema."
375+
376+#: qml/Dash/DashPageHeader.qml:361
377+msgctxt "Button: Open the Ubuntu Store"
378+msgid "Store"
379+msgstr "Tienda"
380+
381+#: qml/Dash/DashPageHeader.qml:368
382+msgctxt "Button: Start a search in the current dash scope"
383+msgid "Search"
384+msgstr "Guetar"
385+
386+#: qml/Dash/DashPageHeader.qml:378
387+msgctxt "Button: Show the current dash scope settings"
388+msgid "Settings"
389+msgstr "Axustes"
390+
391+#: qml/Dash/DashPageHeader.qml:385
392+msgid "Remove from Favorites"
393+msgstr "Desaniciar de favoritos"
394+
395+#: qml/Dash/DashPageHeader.qml:385
396+msgid "Add to Favorites"
397+msgstr "Amestar a favoritos"
398+
399+#: qml/Dash/FiltersPopover.qml:61
400+msgid "Refine your results"
401+msgstr "Refina los resultaos"
402+
403+#: qml/Dash/FiltersPopover.qml:70
404+msgid "Reset"
405+msgstr "Reafitar"
406+
407+#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
408+msgid "Show less"
409+msgstr "Ver menos"
410+
411+#: qml/Dash/GenericScopeView.qml:547
412+msgid "Show all"
413+msgstr "Ver too"
414+
415+#: qml/Dash/GenericScopeView.qml:578
416+msgctxt "Label: Hint for dash search line edit"
417+msgid "Search"
418+msgstr "Guetar"
419+
420+#: qml/Dash/PageHeaderExtraPanel.qml:67
421+msgid "Recent Searches"
422+msgstr "Guetes recién"
423+
424+#: qml/Dash/PageHeaderExtraPanel.qml:78
425+msgid "Clear All"
426+msgstr "Llimpiar too"
427+
428+#: qml/Dash/Previews/PreviewActionCombo.qml:36
429+msgid "More..."
430+msgstr "Más…"
431+
432+#: qml/Dash/Previews/PreviewActionCombo.qml:36
433+msgid "Less..."
434+msgstr "Menos…"
435+
436+#: qml/Dash/Previews/PreviewCommentInput.qml:83
437+#: qml/Dash/Previews/PreviewRatingInput.qml:202
438+msgid "Send"
439+msgstr "Unviar"
440+
441+#: qml/Dash/Previews/PreviewRatingInput.qml:109
442+msgid "Rate this"
443+msgstr "Valorar esto"
444+
445+#: qml/Dash/Previews/PreviewRatingInput.qml:184
446+msgid "Add a review"
447+msgstr "Amestar una reseña"
448+
449+#: qml/Dash/PullToRefreshScopeStyle.qml:56
450+msgid "Pull to refresh…"
451+msgstr "Tira p'anovar..."
452+
453+#: qml/Dash/PullToRefreshScopeStyle.qml:61
454+msgid "Release to refresh…"
455+msgstr "Sueltar p'anovar..."
456+
457+#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
458+msgid "Enable location data"
459+msgstr "Habilitar datos d'allugamientu"
460+
461+#: qml/Dash/ScopesList.qml:146
462+msgid "Manage"
463+msgstr "Xestionar"
464+
465+#: qml/Dash/ScopesList.qml:187
466+msgid "Home"
467+msgstr "Aniciu"
468+
469+#: qml/Dash/ScopesList.qml:188
470+msgid "Also installed"
471+msgstr "Tamién instalaos"
390472
391473#: qml/Greeter/CoverPage.qml:127
392474msgid "Unlock"
@@ -398,39 +480,33 @@ msgstr "Preséu bloquiáu"
398480
399481#: qml/Greeter/DelayedLockscreen.qml:58
400482msgid "You have been locked out due to too many failed passphrase attempts."
401−msgstr ""
402−"Bloquióse'l preséu dempués d'introducir mal el códigu numbéricu milenta "
403−"vegaes."
483+msgstr "Quedasti bloquiáu polos escesivos intentos fallíos de fras de pasu."
404484
405485#: qml/Greeter/DelayedLockscreen.qml:59
406486msgid "You have been locked out due to too many failed passcode attempts."
407487msgstr ""
408−"Bloquióse'l preséu dempués d'introducir mal la contraseña milenta vegaes."
488+"Quedasti bloquiáu polos escesivos intentos fallíos de códigu de pasu."
409489
410490#: qml/Greeter/DelayedLockscreen.qml:68
411491#, qt-format
412492msgid "Please wait %1 minute and then try again…"
413493msgid_plural "Please wait %1 minutes and then try again…"
414−msgstr[0] "Espera %1 minutu y volvi tentalo darréu…"
415−msgstr[1] "Espera %1 minutos y volvi tentalo darréu…"
494+msgstr[0] "Por favor, espera %1 minutu y vuelvi a intentalo…"
495+msgstr[1] "Por favor, espera %1 minutos y vuelvi a intentalo…"
416496
417−#: qml/Greeter/Greeter.qml:550
497+#: qml/Greeter/Greeter.qml:561
418498msgid "Try again"
419−msgstr ""
499+msgstr "Tentar otra vuelta"
420500
421−#: qml/Greeter/Greeter.qml:551
422−#, fuzzy
423−#| msgid "Enter passphrase"
501+#: qml/Greeter/Greeter.qml:562
424502msgid "Enter passphrase to unlock"
425−msgstr "Introduz la fras de pasu"
503+msgstr ""
426504
427−#: qml/Greeter/Greeter.qml:552
428−#, fuzzy
429−#| msgid "Enter passcode"
505+#: qml/Greeter/Greeter.qml:563
430506msgid "Enter passcode to unlock"
431−msgstr "Introduz el códigu de pasu"
507+msgstr ""
432508
433−#: qml/Greeter/NarrowView.qml:235
509+#: qml/Greeter/NarrowView.qml:242
434510msgid "Emergency"
435511msgstr "Emerxencia"
436512
@@ -440,33 +516,32 @@ msgstr "Fras de pasu"
440516
441517#: qml/Greeter/PromptList.qml:126
442518msgid "Passcode"
443−msgstr "Códigu numbéricu"
519+msgstr "Códigu de pasu"
444520
445−#: qml/Greeter/SessionsList.qml:124
521+#: qml/Greeter/SessionsList.qml:122
446522msgid "Select desktop environment"
447−msgstr ""
523+msgstr "Esbillar entornu d'escritoriu"
448524
449−#: qml/Launcher/Drawer.qml:250
450−#, fuzzy
451−#| msgid "Search"
525+#: qml/Launcher/Drawer.qml:93
452526msgid "Search…"
453−msgstr "Guetar"
527+msgstr "Guetar..."
454528
455−#: qml/Launcher/PullToRefreshScopeStyle.qml:56
456−msgid "Pull to refresh…"
457−msgstr "Tira pa refrescar…"
529+#: qml/Launcher/Drawer.qml:128
530+msgctxt "Apps sorted alphabetically"
531+msgid "A-Z"
532+msgstr "A-Z"
458533
459−#: qml/Launcher/PullToRefreshScopeStyle.qml:61
460−msgid "Release to refresh…"
461−msgstr "Suelta pa refrescar…"
534+#: qml/Launcher/MoreAppsHeader.qml:55
535+msgid "More apps in the store"
536+msgstr "Más aplicaciones na tienda"
462537
463538#: qml/Notifications/NotificationMenuItemFactory.qml:124
464539msgid "Show password"
465−msgstr "Amosar la contraseña"
540+msgstr "Amosar contraseña"
466541
467542#: qml/Panel/ActiveCallHint.qml:79
468543msgid "Tap to return to call..."
469−msgstr "Toca pa volver a la llamada…"
544+msgstr "Toca pa tornar a la llamada..."
470545
471546#: qml/Panel/ActiveCallHint.qml:92
472547msgid "Conference"
@@ -474,7 +549,7 @@ msgstr "Conferencia"
474549
475550#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:869
476551msgid "Nothing is playing"
477−msgstr "Nada en reproducción"
552+msgstr "Nun ta reproduciéndose nada"
478553
479554#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:997
480555#, qt-format
@@ -505,11 +580,11 @@ msgstr "0 segundos"
505580#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1011
506581#, qt-format
507582msgid "%1 remaining"
508−msgstr "%1 restante(s)"
583+msgstr "Queden %1"
509584
510585#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1017
511586msgid "In queue…"
512−msgstr "Na cola…"
587+msgstr "Na cola..."
513588
514589#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1021
515590msgid "Downloading"
@@ -517,11 +592,11 @@ msgstr "Baxando"
517592
518593#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1023
519594msgid "Paused, tap to resume"
520−msgstr "Posóse, toca pa siguir"
595+msgstr "Posáu, toca pa reanudar"
521596
522597#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1025
523598msgid "Canceled"
524−msgstr "Encaboxóse"
599+msgstr "Encaboxáu"
525600
526601#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1027
527602msgid "Finished"
@@ -529,7 +604,7 @@ msgstr "Finó"
529604
530605#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1029
531606msgid "Failed, tap to retry"
532−msgstr "Falló, toca pa retentar"
607+msgstr "Falló, toca pa reintentar"
533608
534609#: qml/Panel/Indicators/MessageMenuItemFactory.qml:151
535610#: qml/Panel/Indicators/MessageMenuItemFactory.qml:210
@@ -540,88 +615,65 @@ msgstr "Unviar"
540615#: qml/Panel/Indicators/MessageMenuItemFactory.qml:152
541616msgctxt "Label: Hint in message indicator line edit"
542617msgid "Reply"
543−msgstr ""
618+msgstr "Responder"
544619
545620#: qml/Panel/Indicators/MessageMenuItemFactory.qml:209
546621msgctxt "Button: Call back on phone"
547622msgid "Call back"
548−msgstr "Rellamar"
623+msgstr "Devolver llamada"
549624
550625#: qml/Panel/PanelMenuPage.qml:92
551−#, fuzzy
552−#| msgctxt "Button: Go back one page in the Wizard"
553−#| msgid "Back"
554626msgid "Back"
555−msgstr "Atrás"
627+msgstr ""
556628
557629#: qml/Stage/SideStage.qml:76
558630msgid "Drag using 3 fingers any application from one window to the other"
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 ""
631+msgstr "Abasnar cualquier aplicación d'una ventana a otra usando 3 deos"
564632
565633#: qml/Tutorial/TutorialLeftLong.qml:49
566−#, fuzzy
567−#| msgid "Long swipe from the left edge to open the Today scope"
568634msgid "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"
635+msgstr ""
570636
571637#: qml/Tutorial/TutorialLeft.qml:47
572638msgid "Short swipe from the left edge to open the launcher"
573−msgstr "Esliza dende'l berbesu esquierdu p'abrir el llanzador"
639+msgstr "Barríu curtiu dende'l berbesu izquierdu p'abrir el llanzador"
574640
575−#: qml/Tutorial/TutorialRight.qml:54
641+#: qml/Tutorial/TutorialRight.qml:55
576642msgid "Push your mouse against the right edge to view your open apps"
577−msgstr "Lleva'l mur al berbesu drechu pa ver les aplicaciones abiertes"
643+msgstr "Emburria'l mur escontra'l berbesu drechu pa ver les apps abiertes"
578644
579−#: qml/Tutorial/TutorialRight.qml:55
645+#: qml/Tutorial/TutorialRight.qml:56
580646msgid "Swipe from the right edge to view your open apps"
581−msgstr "Esliza dende'l berbesu drechu pa ver les aplicaciones abiertes"
647+msgstr "Barríu dende'l berbesu drechu pa ver les apps abiertes"
582648
583649#: qml/Tutorial/TutorialTop.qml:53
584650msgid "Swipe from the top edge to access notifications and quick settings"
585−msgstr "Esliza dende'l berbesu cimeru p'acceder a los avisos y axustes rápidos"
651+msgstr ""
652+"Barríu dende'l berbesu superior pa tener accesu a los avisos y configuración "
653+"nel intre"
586654
587−#: qml/Wizard/Page.qml:59
655+#: qml/Wizard/Page.qml:54
588656msgctxt "Button: Go back one page in the Wizard"
589657msgid "Back"
590−msgstr "Atrás"
658+msgstr "Atrás"
591659
592−#: qml/Wizard/Pages/10-welcome.qml:29
660+#: qml/Wizard/Pages/10-welcome.qml:28
593661msgid "Language"
594662msgstr "Llingua"
595663
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
664+#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
665+#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
666+#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
667+#: qml/Wizard/Pages/70-passwd-type.qml:145
668+#: qml/Wizard/Pages/75-report-check.qml:84
669+#: qml/Wizard/Pages/passcode-desktop.qml:142
670+#: qml/Wizard/Pages/password-set.qml:142
603671msgid "Next"
604672msgstr "Siguiente"
605673
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−
622674#: qml/Wizard/Pages/20-keyboard.qml:31
623675msgid "Select Keyboard"
624−msgstr ""
676+msgstr "Escoyer tecláu"
625677
626678#: qml/Wizard/Pages/20-keyboard.qml:71
627679msgid "Keyboard language"
@@ -631,203 +683,279 @@ msgstr "Llingua del tecláu"
631683msgid "Keyboard layout"
632684msgstr "Distribución del tecláu"
633685
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
686+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
687+#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
636688#: qml/Wizard/Pages/sim.qml:101
637689msgid "Skip"
638690msgstr "Saltar"
639691
640692#: qml/Wizard/Pages/30-wifi.qml:31
641693msgid "Connect to Wi‑Fi"
642−msgstr "Conexón a una Wi-Fi"
694+msgstr "Coneutase al WiFi"
643695
644−#: qml/Wizard/Pages/30-wifi.qml:139
696+#: qml/Wizard/Pages/30-wifi.qml:132
645697msgid "Connected"
646−msgstr "Coneutóse"
698+msgstr "Coneutáu"
647699
648−#: qml/Wizard/Pages/30-wifi.qml:172
700+#: qml/Wizard/Pages/30-wifi.qml:165
649701msgid "Available Wi-Fi networks"
650702msgstr "Redes Wi-Fi disponibles"
651703
652−#: qml/Wizard/Pages/30-wifi.qml:173
704+#: qml/Wizard/Pages/30-wifi.qml:166
653705msgid "No available Wi-Fi networks"
654706msgstr "Nun hai redes Wi-Fi disponibles"
655707
708+#: qml/Wizard/Pages/40-location.qml:27
709+msgid "Location Services"
710+msgstr "Servicios d'allugamientu"
711+
712+#: qml/Wizard/Pages/40-location.qml:83
713+msgid ""
714+"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
715+"(recommended)"
716+msgstr ""
717+"Usar GPS, puntos Wi-Fi y redes móviles de mou anónimu pa detectar "
718+"l'allugamientu (recomendao)"
719+
720+#: qml/Wizard/Pages/40-location.qml:105
721+#, qt-format
722+msgid "By selecting this option you agree to the Nokia HERE %1."
723+msgstr "Seleicionando esta opción aceutes los %1 de Nokia HERE."
724+
725+#: qml/Wizard/Pages/40-location.qml:106
726+msgctxt "part of: Nokia HERE terms and conditions"
727+msgid "terms and conditions"
728+msgstr "términos y condiciones"
729+
730+#: qml/Wizard/Pages/40-location.qml:160
731+msgid "GPS only"
732+msgstr "Sólo GPS"
733+
734+#: qml/Wizard/Pages/40-location.qml:214
735+msgid "Don't use my location"
736+msgstr "Nun usar l'allugamientu"
737+
738+#: qml/Wizard/Pages/40-location.qml:260
739+msgid "You can change it later in System Settings."
740+msgstr "Pues camudalo sero na Configuración del Sistema."
741+
656742#: qml/Wizard/Pages/50-timezone.qml:30
657743msgid "Time Zone"
658−msgstr "Fusu horariu"
744+msgstr "Estaya horaria"
659745
660−#: qml/Wizard/Pages/50-timezone.qml:183
746+#: qml/Wizard/Pages/50-timezone.qml:182
661747msgid "Enter your city"
662−msgstr "Introduz la to ciudá"
748+msgstr "Escribe la ciudá"
663749
664750#: qml/Wizard/Pages/60-account.qml:24
665751msgid "Personalize Your Device"
666−msgstr "Personalización del preséu"
752+msgstr "Personaliza'l preséu"
667753
668−#: qml/Wizard/Pages/60-account.qml:54
754+#: qml/Wizard/Pages/60-account.qml:48
669755msgid "Preferred Name"
670756msgstr "Nome preferíu"
671757
672758#: qml/Wizard/Pages/70-passwd-type.qml:40
673759msgid "Lock Screen"
674−msgstr "Pantalla de bloquéu"
760+msgstr "Bloquiar pantalla"
675761
676−#: qml/Wizard/Pages/70-passwd-type.qml:103
762+#: qml/Wizard/Pages/70-passwd-type.qml:102
677763msgctxt "Label: Type of security method"
678764msgid "Create new password"
679−msgstr "Crear una contraseña"
765+msgstr "Crear contraseña nueva"
680766
681−#: qml/Wizard/Pages/70-passwd-type.qml:105
767+#: qml/Wizard/Pages/70-passwd-type.qml:104
682768msgctxt "Label: Type of security method"
683769msgid "Create passcode (numbers only)"
684−msgstr "Crear un códigu numbéricu"
770+msgstr "Crear códigu d'accesu (sólo númberos)"
685771
686−#: qml/Wizard/Pages/70-passwd-type.qml:107
772+#: qml/Wizard/Pages/70-passwd-type.qml:106
687773msgctxt "Label: Type of security method"
688774msgid "No lock code"
689−msgstr "Nada"
775+msgstr "Ensin códigu de bloquéu"
690776
691−#: qml/Wizard/Pages/79-system-update.qml:28
692−msgid "Update Device"
777+#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
778+msgid "Privacy Policy"
779+msgstr "Política d'intimidá"
780+
781+#: qml/Wizard/Pages/75-report-check.qml:26
782+msgid "Help Us Improve"
783+msgstr "Ayúdanos a meyorar"
784+
785+#: qml/Wizard/Pages/75-report-check.qml:59
786+msgid "Improve system performance by sending us crashes and error reports."
693787msgstr ""
788+"Ameyora'l rindimientu del sistema unviándonos los informes d'errores y "
789+"cuelgues."
790+
791+#: qml/Wizard/Pages/75-report-check.qml:60
792+msgid "Privacy policy"
793+msgstr "Política d'intimidá"
794+
795+#: qml/Wizard/Pages/77-system-update.qml:28
796+msgid "Update Device"
797+msgstr "Anovar preséu"
694798
695−#: qml/Wizard/Pages/79-system-update.qml:55
799+#: qml/Wizard/Pages/77-system-update.qml:55
696800msgid ""
697801"There is a system update available and ready to install. Afterwards, the "
698802"device will automatically restart."
699803msgstr ""
700−"Hai un anovamientu del sistema disponible y preparáu pa instalase. Dempués, "
701−"el preséu va reaniciase automáticamente."
804+"Hai un anovamientu del sistema disponible y preparáu pa instalar. Darréu, el "
805+"preséu reaniciará de mou automáticu."
702806
703−#: qml/Wizard/Pages/79-system-update.qml:76
704−#, fuzzy
705−#| msgctxt "string identifying name of the update"
706−#| msgid "Ubuntu system"
807+#: qml/Wizard/Pages/77-system-update.qml:76
707808msgctxt "string identifying name of the update"
708−msgid "Ubuntu Touch system"
809+msgid "Ubuntu system"
709810msgstr "Sistema Ubuntu"
710811
711−#: qml/Wizard/Pages/79-system-update.qml:83
812+#: qml/Wizard/Pages/77-system-update.qml:83
712813#, qt-format
713814msgctxt "version of the system update"
714815msgid "Version %1"
715816msgstr "Versión %1"
716817
717−#: qml/Wizard/Pages/79-system-update.qml:95
818+#: qml/Wizard/Pages/77-system-update.qml:102
718819msgid "This could take a few minutes..."
719−msgstr "Esto podría tardar unos minutos…"
820+msgstr "Esto podría tardar dellos minutos..."
720821
721−#: qml/Wizard/Pages/79-system-update.qml:109
822+#: qml/Wizard/Pages/77-system-update.qml:116
722823msgid "Install and restart now"
723−msgstr ""
724−
725−#: qml/Wizard/Pages/80-finished.qml:91
726−msgid "Welcome Back"
727−msgstr "Volvi afayate"
824+msgstr "Instalar y reaniciar agora"
728825
729−#: qml/Wizard/Pages/80-finished.qml:91
826+#: qml/Wizard/Pages/80-finished.qml:89
730827msgid "Welcome to Ubuntu"
731−msgstr "Afáyate n'Ubuntu"
828+msgstr "Bienveníu/a a Ubuntu"
732829
733−#: qml/Wizard/Pages/80-finished.qml:106
830+#: qml/Wizard/Pages/80-finished.qml:104
734831msgid "You are ready to use your device now"
735−msgstr "Agora tas preparáu pa usar el preséu"
832+msgstr "Ya tas preparáu pa usar el preséu"
736833
737−#: qml/Wizard/Pages/80-finished.qml:126
738−msgid "Continue"
739−msgstr "Siguir"
740−
741−#: qml/Wizard/Pages/80-finished.qml:126
834+#: qml/Wizard/Pages/80-finished.qml:124
742835msgid "Get Started"
743−msgstr "Entamar"
836+msgstr "Primeros pasos"
837+
838+#: qml/Wizard/Pages/here-terms.qml:25
839+msgid "Terms & Conditions"
840+msgstr "Términos y condiciones"
841+
842+#: qml/Wizard/Pages/here-terms.qml:69
843+msgid "Your device uses positioning technologies provided by HERE."
844+msgstr "El preséu usa teunoloxíes de posición qu'ufre HERE."
845+
846+#: qml/Wizard/Pages/here-terms.qml:81
847+msgid ""
848+"To provide you with positioning services and to improve their quality, HERE "
849+"collects information about nearby cell towers and Wi-Fi hotspots around your "
850+"current location whenever your position is being found."
851+msgstr ""
852+"Pa ufrir los servicios de posición y ameyorar la so calidá, HERE collecha "
853+"información de les antenes celulares y puntos d'accesu Wi-Fi cercanos al to "
854+"allugamientu actual siempre que se conoza la to posición."
855+
856+#: qml/Wizard/Pages/here-terms.qml:93
857+msgid ""
858+"The information collected is used to analyze the service and to improve the "
859+"use of service, but not to identify you personally."
860+msgstr ""
861+"La información collechada úsase p'analizar el serviciu y ameyorar l'usu del "
862+"serviciu, non pa identificate personalmente."
863+
864+#: qml/Wizard/Pages/here-terms.qml:106
865+#, qt-format
866+msgid "By continuing, you agree to the HERE platform %1 and %2."
867+msgstr "Al siguir, aceutes %1 y %2 de la plataforma HERE."
868+
869+#: qml/Wizard/Pages/here-terms.qml:107
870+msgid "Service Terms"
871+msgstr "Términos del serviciu"
744872
745873#: qml/Wizard/Pages/passcode-confirm.qml:43
746−#: qml/Wizard/Pages/passcode-desktop.qml:104
874+#: qml/Wizard/Pages/passcode-desktop.qml:97
747875msgid "Confirm passcode"
748−msgstr "Confirmación"
876+msgstr "Confirmar códigu de pasu"
749877
750878#: qml/Wizard/Pages/passcode-confirm.qml:45
751879msgid "Incorrect passcode."
752−msgstr "El códigu numbéricu ye incorreutu."
880+msgstr "Códigu de pasu incorreutu."
753881
754882#: qml/Wizard/Pages/passcode-confirm.qml:45
755883msgctxt "Enter the passcode again"
756884msgid "Please re-enter."
757−msgstr "Volvi introducilu."
885+msgstr "Vuelve a escribilu."
758886
759887#: qml/Wizard/Pages/passcode-desktop.qml:31
760888msgid "Lock Screen Passcode"
761−msgstr "Códigu numbéricu de la pantalla de bloquéu"
889+msgstr "Códigu de pasu de bloquéu de pantalla"
762890
763−#: qml/Wizard/Pages/passcode-desktop.qml:68
891+#: qml/Wizard/Pages/passcode-desktop.qml:61
764892msgid "Enter 4 numbers to setup your passcode"
765−msgstr "Introduz 4 númberos pa configurar el códigu numbéricu"
893+msgstr "Escribi 4 númberos pa configurar el códigu de pasu"
766894
767−#: qml/Wizard/Pages/passcode-desktop.qml:84
895+#: qml/Wizard/Pages/passcode-desktop.qml:77
768896#: qml/Wizard/Pages/passcode-set.qml:54
769897msgid "Choose passcode"
770−msgstr "Códigu numbéricu"
898+msgstr "Escueyi'l códigu de pasu"
771899
772−#: qml/Wizard/Pages/passcode-desktop.qml:139
900+#: qml/Wizard/Pages/passcode-desktop.qml:127
773901msgid "Passcode too short"
774−msgstr "El códigu numbéricu ye percurtiu"
902+msgstr "Códigu de pasu curtiu enforma"
775903
776−#: qml/Wizard/Pages/passcode-desktop.qml:141
904+#: qml/Wizard/Pages/passcode-desktop.qml:129
777905msgid "Passcodes match"
778−msgstr "Los códigos numbéricos concasen"
906+msgstr "Los códigos de pasu casen"
779907
780−#: qml/Wizard/Pages/passcode-desktop.qml:143
908+#: qml/Wizard/Pages/passcode-desktop.qml:131
781909msgid "Passcodes do not match"
782−msgstr "Los códigos numbéricos nun concasen"
910+msgstr "Los códigos de pasu nun casen"
783911
784912#: qml/Wizard/Pages/passcode-set.qml:62
785913msgid "Passcode must be 4 characters long"
786−msgstr "El códigu numbéricu a ser de 4 caráuteres"
914+msgstr "El códigu de pasu tien de tener 4 caráuteres de llargo"
787915
788916#: qml/Wizard/Pages/password-set.qml:31
789917msgid "Lock Screen Password"
790−msgstr "Contraseña de la pantalla de bloquéu"
918+msgstr "Contraseña del Bloquéu de pantalla"
791919
792−#: qml/Wizard/Pages/password-set.qml:68
920+#: qml/Wizard/Pages/password-set.qml:62
793921msgid "Enter at least 8 characters"
794−msgstr "Introduz 8 caráuteres polo menos"
922+msgstr "Escribe polo menos 8 caráuteres"
795923
796−#: qml/Wizard/Pages/password-set.qml:80
924+#: qml/Wizard/Pages/password-set.qml:74
797925msgid "Choose password"
798−msgstr "Contraseña"
926+msgstr "Escueye la contraseña"
799927
800−#: qml/Wizard/Pages/password-set.qml:110
928+#: qml/Wizard/Pages/password-set.qml:104
801929msgid "Confirm password"
802−msgstr "Confirmación"
930+msgstr "Confirmar contraseña"
803931
804932#: qml/Wizard/Pages/sim.qml:27
805933msgid "No SIM card installed"
806−msgstr "Nun s'instaló denguna tarxeta SIM"
934+msgstr "Nun ta instalada nenguna tarxeta SIM"
807935
808936#: qml/Wizard/Pages/sim.qml:54
809937msgid "SIM card added"
810−msgstr ""
938+msgstr "Amestóse tarxeta SIM"
811939
812940#: qml/Wizard/Pages/sim.qml:55
813941msgid "You must restart the device to access the mobile network."
814−msgstr "Has reaniciar el preséu p'acceder a la rede móvil."
942+msgstr "Tienes de reaniciar el preséu pa tener accesu a la rede móvil."
815943
816944#: qml/Wizard/Pages/sim.qml:59
817945msgid "Restart"
818−msgstr ""
946+msgstr "Reaniciar"
819947
820948#: qml/Wizard/Pages/sim.qml:78
821949msgid "You won’t be able to make calls or use text messaging without a SIM."
822−msgstr "Nun vas ser a facer llamaes o unviar SMS ensin una SIM."
950+msgstr "Nun podrás facer llamaes nin usar mensaxería de testu sin una SIM."
823951
824952#: qml/Wizard/Pages/sim.qml:90
825953msgid "To proceed with no SIM tap Skip."
826−msgstr "Pa siguir ensin una tarxeta SIM toca Saltar."
954+msgstr "Pa siguir ensin SIM toca Saltar."
827955
828956#: qml/Wizard/PasswordMeter.qml:87
829957msgid "Password too short"
830−msgstr "La contraseña ye percurtia"
958+msgstr "Contraseña curtia enforma"
831959
832960#: qml/Wizard/PasswordMeter.qml:89
833961msgid "Passwords match"
@@ -839,11 +967,11 @@ msgstr "Les contraseñes nun concasen"
839967
840968#: qml/Wizard/PasswordMeter.qml:95
841969msgid "Strong password"
842−msgstr "Contraseña perbona"
970+msgstr "Contraseña fuerte"
843971
844972#: qml/Wizard/PasswordMeter.qml:97
845973msgid "Fair password"
846−msgstr "Contraseña bona"
974+msgstr "Contraseña aceutable"
847975
848976#: qml/Wizard/PasswordMeter.qml:99
849977msgid "Weak password"
@@ -851,185 +979,7 @@ msgstr "Contraseña feble"
851979
852980#: qml/Wizard/PasswordMeter.qml:101
853981msgid "Very weak password"
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"
982+msgstr "Contraseña feble enforma"
1033983
1034984#~ msgid "Skip intro"
1035985#~ msgstr "Omitir la intro"
@@ -1057,8 +1007,8 @@ msgstr "Contraseña perfeble"
10571007
10581008#~ msgid "Swipe from the left to reveal the launcher for quick access to apps"
10591009#~ msgstr ""
1060−#~ "Esliza'l deu dende la esquierda p'amosar el llanzador y acceder "
1061−#~ "rápidamente a les aplicaciones"
1010+#~ "Esliza'l deu dende la esquierda p'amosar el llanzador y acceder rápidamente "
1011+#~ "a les aplicaciones"
10621012
10631013#~ msgid "Well done"
10641014#~ msgstr "Bien fecho"
@@ -1066,12 +1016,21 @@ msgstr "Contraseña perfeble"
10661016#~ msgid "Confirm"
10671017#~ msgstr "Confirmar"
10681018
1019+#~ msgid "Speaking..."
1020+#~ msgstr "Falando…"
1021+
1022+#~ msgid "Loading. Please Wait..."
1023+#~ msgstr "Cargando, espera…"
1024+
10691025#~ msgid "Type or say a command"
10701026#~ msgstr "Escribi o di una orde"
10711027
10721028#~ msgid "Speak Now..."
10731029#~ msgstr "Fala agora…"
10741030
1031+#~ msgid "Search"
1032+#~ msgstr "Guetar"
1033+
10751034#~ msgid "See less"
10761035#~ msgstr "Ver menos"
10771036
@@ -1118,6 +1077,7 @@ msgstr "Contraseña perfeble"
11181077#~ msgid "Store"
11191078#~ msgstr "Tienda"
11201079
1080+#, qt-format
11211081#~ msgid "Sorry, incorrect %1"
11221082#~ msgstr "Sentímoslo, %1 incorreutu"
11231083
@@ -1133,6 +1093,9 @@ msgstr "Contraseña perfeble"
11331093#~ msgid "Manage Scopes"
11341094#~ msgstr "Xestionar ámbitos"
11351095
1096+#~ msgid "Continue"
1097+#~ msgstr "Siguir"
1098+
11361099#~ msgid "Without it, you won’t be able to make calls or use text messaging."
11371100#~ msgstr "Ensin ella, nun vas poder facer llamaes nin unviar mensaxes."
11381101
@@ -1164,12 +1127,17 @@ msgstr "Contraseña perfeble"
11641127#~ msgid "Not at all"
11651128#~ msgstr "De nengún mou"
11661129
1130+#, qt-format
11671131#~ msgid "〈 %1"
11681132#~ msgstr "〈 %1"
11691133
1134+#, qt-format
11701135#~ msgid "%1 〉"
11711136#~ msgstr "%1 〉"
11721137
1138+#~ msgid "Open the launcher"
1139+#~ msgstr "Abrir el llanzador"
1140+
11731141#~ msgid "Tap here to continue."
11741142#~ msgstr "Toca equí pa siguir."
11751143
@@ -1210,28 +1178,35 @@ msgstr "Contraseña perfeble"
12101178#~ msgid "Sorry, incorrect passphrase."
12111179#~ msgstr "Perdón, fras de pasu incorreuta"
12121180
1181+#, qt-format
12131182#~ msgid "Enter %1"
12141183#~ msgstr "Introduz %1"
12151184
12161185#~ msgid "Sorry, incorrect passcode."
12171186#~ msgstr "Perdón, códigu de pasu incorreutu."
12181187
1188+#~ msgid "Enter passcode"
1189+#~ msgstr "Introduz el códigu de pasu"
1190+
1191+#~ msgid "Enter passphrase"
1192+#~ msgstr "Introduz la fras de pasu"
1193+
12191194#~ msgid "Please re-enter"
12201195#~ msgstr "Por favor, reintroduzla"
12211196
12221197#~ msgid ""
1223−#~ "If passcode is entered incorrectly, your phone will conduct a factory "
1224−#~ "reset and all personal data will be deleted."
1198+#~ "If passcode is entered incorrectly, your phone will conduct a factory reset "
1199+#~ "and all personal data will be deleted."
12251200#~ msgstr ""
1226−#~ "Si s'inxerta'l códigu de pasu incorreutamente, el to teléfonu va "
1227−#~ "reafitase y van desaniciase tolos datos personales."
1201+#~ "Si s'inxerta'l códigu de pasu incorreutamente, el to teléfonu va reafitase y "
1202+#~ "van desaniciase tolos datos personales."
12281203
12291204#~ msgid ""
12301205#~ "If passphrase is entered incorrectly, your phone will conduct a factory "
12311206#~ "reset and all personal data will be deleted."
12321207#~ msgstr ""
1233−#~ "Si s'inxerta la fras de pasu incorreutamente, el to teléfonu va reafitase "
1234−#~ "y van desaniciase tolos datos personales."
1208+#~ "Si s'inxerta la fras de pasu incorreutamente, el to teléfonu va reafitase y "
1209+#~ "van desaniciase tolos datos personales."
12351210
12361211#~ msgid "This will be your last attempt."
12371212#~ msgstr "Esti sedra'l to caberu intentu"
@@ -1315,11 +1290,11 @@ msgstr "Contraseña perfeble"
13151290#~ msgstr "¡Bon trabayu!"
13161291
13171292#~ msgid ""
1318−#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms "
1319−#~ "and conditions</a>."
1293+#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
1294+#~ "conditions</a>."
13201295#~ msgstr ""
1321−#~ "Esbillando esta opción aceutes los <a href='#'>términos y condiciones</a> "
1322−#~ "de Nokia HERE."
1296+#~ "Esbillando esta opción aceutes los <a href='#'>términos y condiciones</a> de "
1297+#~ "Nokia HERE."
13231298
13241299#~ msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
13251300#~ msgstr ""
@@ -1398,11 +1373,19 @@ msgstr "Contraseña perfeble"
13981373
13991374#~ msgid "Short or long swipe from the right edge to view your open apps"
14001375#~ msgstr ""
1401−#~ "Eslizamientu curtiu o llargu dende'l berbesu drechu pa ver les apps "
1402−#~ "abiertes"
1376+#~ "Eslizamientu curtiu o llargu dende'l berbesu drechu pa ver les apps abiertes"
14031377
14041378#~ msgid "Swipe up to manage the app"
14051379#~ msgstr "Eslizar p'alministrar la app"
14061380
14071381#~ msgid "Swipe up to create a message"
14081382#~ msgstr "Eslizar pa crear un mensaxe"
1383+
1384+#~ msgid "Long swipe from the left edge to open the Today scope"
1385+#~ msgstr "Eslizamientu llargu dende'l berbesu izquierdu pa ver el scope Güei"
1386+
1387+#~ msgid "Takes a screenshot of a window."
1388+#~ msgstr "Saca una imaxe d'una ventana."
1389+
1390+#~ msgid "Super + 0 to 9"
1391+#~ msgstr "Super + 0 a 9"
po/az.po+312−191
@@ -6,61 +6,60 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
9−"Report-Msgid-Bugs-To: \n"
10−"POT-Creation-Date: 2021-01-29 11:42-0600\n"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2017-03-21 10:58+0000\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"
1514"MIME-Version: 1.0\n"
1615"Content-Type: text/plain; charset=UTF-8\n"
1716"Content-Transfer-Encoding: 8bit\n"
1817"Plural-Forms: nplurals=2; plural=n != 1;\n"
19−"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
20−"X-Generator: Launchpad (build 18269)\n"
18+"X-Launchpad-Export-Date: 2017-03-24 06:12+0000\n"
19+"X-Generator: Launchpad (build 18334)\n"
2120
22−#: plugins/LightDM/Greeter.cpp:199
21+#: plugins/LightDM/Greeter.cpp:188
2322msgid "Password: "
2423msgstr "Şifrә: "
2524
26−#: plugins/LightDM/Greeter.cpp:214
25+#: plugins/LightDM/Greeter.cpp:203
2726msgid "Username"
2827msgstr ""
2928
30−#: plugins/LightDM/Greeter.cpp:258
29+#: plugins/LightDM/Greeter.cpp:242
3130msgid "Failed to authenticate"
3231msgstr ""
3332
34−#: plugins/LightDM/Greeter.cpp:260
33+#: plugins/LightDM/Greeter.cpp:244
3534msgid "Invalid password, please try again"
3635msgstr ""
3736
38−#: plugins/LightDM/Greeter.cpp:270
37+#: plugins/LightDM/Greeter.cpp:254
3938msgid "Log In"
4039msgstr ""
4140
42−#: plugins/LightDM/Greeter.cpp:270
41+#: plugins/LightDM/Greeter.cpp:254
4342msgid "Retry"
4443msgstr ""
4544
46−#: plugins/LightDM/UsersModel.cpp:157
45+#: plugins/LightDM/UsersModel.cpp:152
4746msgid "Login"
4847msgstr ""
4948
50−#: plugins/LightDM/UsersModel.cpp:165
49+#: plugins/LightDM/UsersModel.cpp:160
5150msgid "Guest Session"
5251msgstr ""
5352
54−#: plugins/Unity/Launcher/launcheritem.cpp:48
55−#: plugins/Unity/Launcher/launcheritem.cpp:122
53+#: plugins/Unity/Launcher/launcheritem.cpp:49
54+#: plugins/Unity/Launcher/launcheritem.cpp:123
5655msgid "Pin shortcut"
5756msgstr "Pin qısayolu"
5857
59−#: plugins/Unity/Launcher/launcheritem.cpp:54
58+#: plugins/Unity/Launcher/launcheritem.cpp:55
6059msgid "Quit"
6160msgstr ""
6261
63−#: plugins/Unity/Launcher/launcheritem.cpp:122
62+#: plugins/Unity/Launcher/launcheritem.cpp:123
6463msgid "Unpin shortcut"
6564msgstr "Açma qısayolu"
6665
@@ -83,8 +82,9 @@ msgctxt "Button: Log out from the system"
8382msgid "Log Out"
8483msgstr ""
8584
86−#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
87−#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
85+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:264
86+#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:222
87+#: qml/Wizard/Pages/passcode-confirm.qml:32
8888#: qml/Wizard/Pages/passcode-set.qml:32
8989msgid "Cancel"
9090msgstr "İmtina"
@@ -106,37 +106,33 @@ msgstr "Yox"
106106msgid "Yes"
107107msgstr "Hə"
108108
109−#: qml/Components/Dialogs.qml:243
109+#: qml/Components/Dialogs.qml:239
110110msgctxt "Title: Power off/Restart dialog"
111111msgid "Power"
112112msgstr ""
113113
114−#: qml/Components/Dialogs.qml:244
114+#: qml/Components/Dialogs.qml:240
115115msgid ""
116116"Are you sure you would like\n"
117117"to power off?"
118118msgstr ""
119119
120−#: qml/Components/Dialogs.qml:248
120+#: qml/Components/Dialogs.qml:244
121121msgctxt "Button: Power off the system"
122122msgid "Power off"
123123msgstr ""
124124
125−#: qml/Components/Dialogs.qml:263
125+#: qml/Components/Dialogs.qml:255
126126msgctxt "Button: Restart the system"
127127msgid "Restart"
128128msgstr ""
129129
130−#: qml/Components/Dialogs.qml:276
131−msgid "Screenshot"
132−msgstr ""
133−
134130#: qml/Components/KeyboardShortcutsOverlay.qml:41
135131msgid "Keyboard Shortcuts"
136132msgstr ""
137133
138134#: qml/Components/KeyboardShortcutsOverlay.qml:55
139−msgid "Lomiri"
135+msgid "Unity 8"
140136msgstr ""
141137
142138#: qml/Components/KeyboardShortcutsOverlay.qml:62
@@ -171,131 +167,135 @@ msgstr ""
171167msgid "Switches to previous keyboard layout."
172168msgstr ""
173169
174−#: qml/Components/KeyboardShortcutsOverlay.qml:114
175−msgid "Ctrl + Alt + T"
170+#: qml/Components/KeyboardShortcutsOverlay.qml:118
171+msgid "Launcher"
176172msgstr ""
177173
178−#: qml/Components/KeyboardShortcutsOverlay.qml:119
179−msgid "Starts the Terminal application."
174+#: qml/Components/KeyboardShortcutsOverlay.qml:125
175+msgid "Super (Hold)"
180176msgstr ""
181177
182−#: qml/Components/KeyboardShortcutsOverlay.qml:131
183−msgid "Launcher"
178+#: qml/Components/KeyboardShortcutsOverlay.qml:130
179+msgid "Opens the launcher, displays shortcuts."
184180msgstr ""
185181
186182#: qml/Components/KeyboardShortcutsOverlay.qml:138
187−msgid "Super (Hold)"
183+msgid "Alt + F1"
188184msgstr ""
189185
190186#: qml/Components/KeyboardShortcutsOverlay.qml:143
191−msgid "Opens the launcher, displays shortcuts."
187+msgid "Opens launcher keyboard navigation mode."
192188msgstr ""
193189
194190#: qml/Components/KeyboardShortcutsOverlay.qml:151
195−msgid "Alt + F1"
191+msgid "Super + Tab"
196192msgstr ""
197193
198194#: qml/Components/KeyboardShortcutsOverlay.qml:156
199−msgid "Opens launcher keyboard navigation mode."
195+msgid "Switches applications via the launcher."
200196msgstr ""
201197
202198#: qml/Components/KeyboardShortcutsOverlay.qml:164
203−msgid "Super + Tab"
199+msgid "Super + 1 to 0"
204200msgstr ""
205201
206202#: qml/Components/KeyboardShortcutsOverlay.qml:169
207−msgid "Switches applications via the launcher."
203+msgid "Same as clicking on a launcher icon."
208204msgstr ""
209205
210206#: qml/Components/KeyboardShortcutsOverlay.qml:177
211−msgid "Super + 1 to 0"
207+msgid "Super + A"
212208msgstr ""
213209
214210#: qml/Components/KeyboardShortcutsOverlay.qml:182
215−msgid "Same as clicking on a launcher icon."
211+msgid "Opens the Application Drawer."
216212msgstr ""
217213
218−#: qml/Components/KeyboardShortcutsOverlay.qml:190
219−msgid "Super + A"
214+#: qml/Components/KeyboardShortcutsOverlay.qml:194
215+msgid "Scopes"
220216msgstr ""
221217
222−#: qml/Components/KeyboardShortcutsOverlay.qml:195
223−msgid "Opens the Application Drawer."
218+#: qml/Components/KeyboardShortcutsOverlay.qml:201
219+msgid "Super (Tap)"
220+msgstr ""
221+
222+#: qml/Components/KeyboardShortcutsOverlay.qml:206
223+msgid "Opens the Scopes home."
224224msgstr ""
225225
226−#: qml/Components/KeyboardShortcutsOverlay.qml:235
226+#: qml/Components/KeyboardShortcutsOverlay.qml:222
227227msgid "Switching"
228228msgstr ""
229229
230−#: qml/Components/KeyboardShortcutsOverlay.qml:242
230+#: qml/Components/KeyboardShortcutsOverlay.qml:229
231231msgid "Alt + Tab"
232232msgstr ""
233233
234−#: qml/Components/KeyboardShortcutsOverlay.qml:247
234+#: qml/Components/KeyboardShortcutsOverlay.qml:234
235235msgid "Switches between applications."
236236msgstr ""
237237
238−#: qml/Components/KeyboardShortcutsOverlay.qml:255
238+#: qml/Components/KeyboardShortcutsOverlay.qml:242
239239msgid "Super + W"
240240msgstr ""
241241
242−#: qml/Components/KeyboardShortcutsOverlay.qml:260
242+#: qml/Components/KeyboardShortcutsOverlay.qml:247
243243msgid "Opens the desktop spread."
244244msgstr ""
245245
246−#: qml/Components/KeyboardShortcutsOverlay.qml:268
246+#: qml/Components/KeyboardShortcutsOverlay.qml:255
247247msgid "Cursor Left or Right"
248248msgstr ""
249249
250−#: qml/Components/KeyboardShortcutsOverlay.qml:273
250+#: qml/Components/KeyboardShortcutsOverlay.qml:260
251251msgid "Moves the focus."
252252msgstr ""
253253
254−#: qml/Components/KeyboardShortcutsOverlay.qml:285
254+#: qml/Components/KeyboardShortcutsOverlay.qml:272
255255msgid "Windows"
256256msgstr ""
257257
258−#: qml/Components/KeyboardShortcutsOverlay.qml:292
258+#: qml/Components/KeyboardShortcutsOverlay.qml:279
259259msgid "Ctrl + Super + D"
260260msgstr ""
261261
262−#: qml/Components/KeyboardShortcutsOverlay.qml:297
262+#: qml/Components/KeyboardShortcutsOverlay.qml:284
263263msgid "Minimizes all windows."
264264msgstr ""
265265
266−#: qml/Components/KeyboardShortcutsOverlay.qml:305
266+#: qml/Components/KeyboardShortcutsOverlay.qml:292
267267msgid "Ctrl + Super + Up"
268268msgstr ""
269269
270−#: qml/Components/KeyboardShortcutsOverlay.qml:310
270+#: qml/Components/KeyboardShortcutsOverlay.qml:297
271271msgid "Maximizes the current window."
272272msgstr ""
273273
274−#: qml/Components/KeyboardShortcutsOverlay.qml:318
274+#: qml/Components/KeyboardShortcutsOverlay.qml:305
275275msgid "Ctrl + Super + Down"
276276msgstr ""
277277
278−#: qml/Components/KeyboardShortcutsOverlay.qml:323
278+#: qml/Components/KeyboardShortcutsOverlay.qml:310
279279msgid "Minimizes or restores the current window."
280280msgstr ""
281281
282−#: qml/Components/KeyboardShortcutsOverlay.qml:331
282+#: qml/Components/KeyboardShortcutsOverlay.qml:318
283283msgid "Ctrl + Super + Left or Right"
284284msgstr ""
285285
286−#: qml/Components/KeyboardShortcutsOverlay.qml:336
286+#: qml/Components/KeyboardShortcutsOverlay.qml:323
287287msgid "Semi-maximizes the current window."
288288msgstr ""
289289
290−#: qml/Components/KeyboardShortcutsOverlay.qml:344
290+#: qml/Components/KeyboardShortcutsOverlay.qml:331
291291msgid "Alt + F4"
292292msgstr ""
293293
294−#: qml/Components/KeyboardShortcutsOverlay.qml:349
294+#: qml/Components/KeyboardShortcutsOverlay.qml:336
295295msgid "Closes the current window."
296296msgstr ""
297297
298−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
298+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:242
299299msgid "Return to Call"
300300msgstr ""
301301
@@ -354,10 +354,8 @@ msgid ""
354354msgstr ""
355355
356356#: qml/Components/VirtualTouchPad.qml:327
357−#, fuzzy
358−#| msgid "Tap to return to call..."
359357msgid "Tap left button to click."
360−msgstr "Zəngə qayıtmaq üçün toxunun..."
358+msgstr ""
361359
362360#: qml/Components/VirtualTouchPad.qml:339
363361msgid "Tap right button to right click."
@@ -371,6 +369,103 @@ msgstr ""
371369msgid "Find more settings in the system settings."
372370msgstr ""
373371
372+#: qml/Dash/DashPageHeader.qml:361
373+msgctxt "Button: Open the Ubuntu Store"
374+msgid "Store"
375+msgstr ""
376+
377+#: qml/Dash/DashPageHeader.qml:368
378+msgctxt "Button: Start a search in the current dash scope"
379+msgid "Search"
380+msgstr ""
381+
382+#: qml/Dash/DashPageHeader.qml:378
383+msgctxt "Button: Show the current dash scope settings"
384+msgid "Settings"
385+msgstr ""
386+
387+#: qml/Dash/DashPageHeader.qml:385
388+msgid "Remove from Favorites"
389+msgstr "Seçilmişlәrdәn çıxart"
390+
391+#: qml/Dash/DashPageHeader.qml:385
392+msgid "Add to Favorites"
393+msgstr "Seçilmişlәrә әlavә et"
394+
395+#: qml/Dash/FiltersPopover.qml:61
396+msgid "Refine your results"
397+msgstr ""
398+
399+#: qml/Dash/FiltersPopover.qml:70
400+msgid "Reset"
401+msgstr ""
402+
403+#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
404+msgid "Show less"
405+msgstr ""
406+
407+#: qml/Dash/GenericScopeView.qml:547
408+msgid "Show all"
409+msgstr ""
410+
411+#: qml/Dash/GenericScopeView.qml:578
412+msgctxt "Label: Hint for dash search line edit"
413+msgid "Search"
414+msgstr ""
415+
416+#: qml/Dash/PageHeaderExtraPanel.qml:67
417+msgid "Recent Searches"
418+msgstr ""
419+
420+#: qml/Dash/PageHeaderExtraPanel.qml:78
421+msgid "Clear All"
422+msgstr ""
423+
424+#: qml/Dash/Previews/PreviewActionCombo.qml:36
425+msgid "More..."
426+msgstr "Daha çox..."
427+
428+#: qml/Dash/Previews/PreviewActionCombo.qml:36
429+msgid "Less..."
430+msgstr "Az..."
431+
432+#: qml/Dash/Previews/PreviewCommentInput.qml:83
433+#: qml/Dash/Previews/PreviewRatingInput.qml:202
434+msgid "Send"
435+msgstr "Göndər"
436+
437+#: qml/Dash/Previews/PreviewRatingInput.qml:109
438+msgid "Rate this"
439+msgstr "Qiymәtlәndir"
440+
441+#: qml/Dash/Previews/PreviewRatingInput.qml:184
442+msgid "Add a review"
443+msgstr "Rəy yaz"
444+
445+#: qml/Dash/PullToRefreshScopeStyle.qml:56
446+msgid "Pull to refresh…"
447+msgstr ""
448+
449+#: qml/Dash/PullToRefreshScopeStyle.qml:61
450+msgid "Release to refresh…"
451+msgstr ""
452+
453+#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
454+msgid "Enable location data"
455+msgstr ""
456+
457+#: qml/Dash/ScopesList.qml:146
458+msgid "Manage"
459+msgstr ""
460+
461+#: qml/Dash/ScopesList.qml:187
462+msgid "Home"
463+msgstr ""
464+
465+#: qml/Dash/ScopesList.qml:188
466+msgid "Also installed"
467+msgstr ""
468+
374469#: qml/Greeter/CoverPage.qml:127
375470msgid "Unlock"
376471msgstr ""
@@ -394,19 +489,19 @@ msgid_plural "Please wait %1 minutes and then try again…"
394489msgstr[0] ""
395490msgstr[1] ""
396491
397−#: qml/Greeter/Greeter.qml:550
492+#: qml/Greeter/Greeter.qml:561
398493msgid "Try again"
399494msgstr ""
400495
401−#: qml/Greeter/Greeter.qml:551
496+#: qml/Greeter/Greeter.qml:562
402497msgid "Enter passphrase to unlock"
403498msgstr ""
404499
405−#: qml/Greeter/Greeter.qml:552
500+#: qml/Greeter/Greeter.qml:563
406501msgid "Enter passcode to unlock"
407502msgstr ""
408503
409−#: qml/Greeter/NarrowView.qml:235
504+#: qml/Greeter/NarrowView.qml:242
410505msgid "Emergency"
411506msgstr ""
412507
@@ -418,22 +513,21 @@ msgstr ""
418513msgid "Passcode"
419514msgstr ""
420515
421−#: qml/Greeter/SessionsList.qml:124
516+#: qml/Greeter/SessionsList.qml:122
422517msgid "Select desktop environment"
423518msgstr ""
424519
425−#: qml/Launcher/Drawer.qml:250
426−#, fuzzy
427−#| msgid "Search"
520+#: qml/Launcher/Drawer.qml:93
428521msgid "Search…"
429−msgstr "Axtar"
522+msgstr ""
430523
431−#: qml/Launcher/PullToRefreshScopeStyle.qml:56
432−msgid "Pull to refresh…"
524+#: qml/Launcher/Drawer.qml:128
525+msgctxt "Apps sorted alphabetically"
526+msgid "A-Z"
433527msgstr ""
434528
435−#: qml/Launcher/PullToRefreshScopeStyle.qml:61
436−msgid "Release to refresh…"
529+#: qml/Launcher/MoreAppsHeader.qml:55
530+msgid "More apps in the store"
437531msgstr ""
438532
439533#: qml/Notifications/NotificationMenuItemFactory.qml:124
@@ -531,25 +625,19 @@ msgstr ""
531625msgid "Drag using 3 fingers any application from one window to the other"
532626msgstr ""
533627
534−#: qml/Stage/Stage.qml:671
535−msgid "No running apps"
536−msgstr ""
537−
538628#: qml/Tutorial/TutorialLeftLong.qml:49
539−#, fuzzy
540−#| msgid "Try swiping from the top edge to access the indicators"
541629msgid "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"
630+msgstr ""
543631
544632#: qml/Tutorial/TutorialLeft.qml:47
545633msgid "Short swipe from the left edge to open the launcher"
546634msgstr ""
547635
548−#: qml/Tutorial/TutorialRight.qml:54
636+#: qml/Tutorial/TutorialRight.qml:55
549637msgid "Push your mouse against the right edge to view your open apps"
550638msgstr ""
551639
552−#: qml/Tutorial/TutorialRight.qml:55
640+#: qml/Tutorial/TutorialRight.qml:56
553641msgid "Swipe from the right edge to view your open apps"
554642msgstr ""
555643
@@ -557,42 +645,25 @@ msgstr ""
557645msgid "Swipe from the top edge to access notifications and quick settings"
558646msgstr ""
559647
560−#: qml/Wizard/Page.qml:59
648+#: qml/Wizard/Page.qml:54
561649msgctxt "Button: Go back one page in the Wizard"
562650msgid "Back"
563651msgstr ""
564652
565−#: qml/Wizard/Pages/10-welcome.qml:29
653+#: qml/Wizard/Pages/10-welcome.qml:28
566654msgid "Language"
567655msgstr ""
568656
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
657+#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
658+#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
659+#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
660+#: qml/Wizard/Pages/70-passwd-type.qml:145
661+#: qml/Wizard/Pages/75-report-check.qml:84
662+#: qml/Wizard/Pages/passcode-desktop.qml:142
663+#: qml/Wizard/Pages/password-set.qml:142
576664msgid "Next"
577665msgstr ""
578666
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−
596667#: qml/Wizard/Pages/20-keyboard.qml:31
597668msgid "Select Keyboard"
598669msgstr ""
@@ -605,8 +676,8 @@ msgstr ""
605676msgid "Keyboard layout"
606677msgstr ""
607678
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
679+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
680+#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
610681#: qml/Wizard/Pages/sim.qml:101
611682msgid "Skip"
612683msgstr ""
@@ -615,23 +686,55 @@ msgstr ""
615686msgid "Connect to Wi‑Fi"
616687msgstr ""
617688
618−#: qml/Wizard/Pages/30-wifi.qml:139
689+#: qml/Wizard/Pages/30-wifi.qml:132
619690msgid "Connected"
620691msgstr ""
621692
622−#: qml/Wizard/Pages/30-wifi.qml:172
693+#: qml/Wizard/Pages/30-wifi.qml:165
623694msgid "Available Wi-Fi networks"
624695msgstr ""
625696
626−#: qml/Wizard/Pages/30-wifi.qml:173
697+#: qml/Wizard/Pages/30-wifi.qml:166
627698msgid "No available Wi-Fi networks"
628699msgstr ""
629700
701+#: qml/Wizard/Pages/40-location.qml:27
702+msgid "Location Services"
703+msgstr ""
704+
705+#: qml/Wizard/Pages/40-location.qml:83
706+msgid ""
707+"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
708+"(recommended)"
709+msgstr ""
710+
711+#: qml/Wizard/Pages/40-location.qml:105
712+#, qt-format
713+msgid "By selecting this option you agree to the Nokia HERE %1."
714+msgstr ""
715+
716+#: qml/Wizard/Pages/40-location.qml:106
717+msgctxt "part of: Nokia HERE terms and conditions"
718+msgid "terms and conditions"
719+msgstr ""
720+
721+#: qml/Wizard/Pages/40-location.qml:160
722+msgid "GPS only"
723+msgstr ""
724+
725+#: qml/Wizard/Pages/40-location.qml:214
726+msgid "Don't use my location"
727+msgstr ""
728+
729+#: qml/Wizard/Pages/40-location.qml:260
730+msgid "You can change it later in System Settings."
731+msgstr ""
732+
630733#: qml/Wizard/Pages/50-timezone.qml:30
631734msgid "Time Zone"
632735msgstr ""
633736
634−#: qml/Wizard/Pages/50-timezone.qml:183
737+#: qml/Wizard/Pages/50-timezone.qml:182
635738msgid "Enter your city"
636739msgstr ""
637740
@@ -639,7 +742,7 @@ msgstr ""
639742msgid "Personalize Your Device"
640743msgstr ""
641744
642−#: qml/Wizard/Pages/60-account.qml:54
745+#: qml/Wizard/Pages/60-account.qml:48
643746msgid "Preferred Name"
644747msgstr ""
645748
@@ -647,72 +750,110 @@ msgstr ""
647750msgid "Lock Screen"
648751msgstr ""
649752
650−#: qml/Wizard/Pages/70-passwd-type.qml:103
753+#: qml/Wizard/Pages/70-passwd-type.qml:102
651754msgctxt "Label: Type of security method"
652755msgid "Create new password"
653756msgstr ""
654757
655−#: qml/Wizard/Pages/70-passwd-type.qml:105
758+#: qml/Wizard/Pages/70-passwd-type.qml:104
656759msgctxt "Label: Type of security method"
657760msgid "Create passcode (numbers only)"
658761msgstr ""
659762
660−#: qml/Wizard/Pages/70-passwd-type.qml:107
763+#: qml/Wizard/Pages/70-passwd-type.qml:106
661764msgctxt "Label: Type of security method"
662765msgid "No lock code"
663766msgstr ""
664767
665−#: qml/Wizard/Pages/79-system-update.qml:28
768+#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
769+msgid "Privacy Policy"
770+msgstr ""
771+
772+#: qml/Wizard/Pages/75-report-check.qml:26
773+msgid "Help Us Improve"
774+msgstr ""
775+
776+#: qml/Wizard/Pages/75-report-check.qml:59
777+msgid "Improve system performance by sending us crashes and error reports."
778+msgstr ""
779+
780+#: qml/Wizard/Pages/75-report-check.qml:60
781+msgid "Privacy policy"
782+msgstr ""
783+
784+#: qml/Wizard/Pages/77-system-update.qml:28
666785msgid "Update Device"
667786msgstr ""
668787
669−#: qml/Wizard/Pages/79-system-update.qml:55
788+#: qml/Wizard/Pages/77-system-update.qml:55
670789msgid ""
671790"There is a system update available and ready to install. Afterwards, the "
672791"device will automatically restart."
673792msgstr ""
674793
675−#: qml/Wizard/Pages/79-system-update.qml:76
794+#: qml/Wizard/Pages/77-system-update.qml:76
676795msgctxt "string identifying name of the update"
677−msgid "Ubuntu Touch system"
796+msgid "Ubuntu system"
678797msgstr ""
679798
680−#: qml/Wizard/Pages/79-system-update.qml:83
799+#: qml/Wizard/Pages/77-system-update.qml:83
681800#, qt-format
682801msgctxt "version of the system update"
683802msgid "Version %1"
684803msgstr ""
685804
686−#: qml/Wizard/Pages/79-system-update.qml:95
805+#: qml/Wizard/Pages/77-system-update.qml:102
687806msgid "This could take a few minutes..."
688807msgstr ""
689808
690−#: qml/Wizard/Pages/79-system-update.qml:109
809+#: qml/Wizard/Pages/77-system-update.qml:116
691810msgid "Install and restart now"
692811msgstr ""
693812
694−#: qml/Wizard/Pages/80-finished.qml:91
695−msgid "Welcome Back"
696−msgstr ""
697−
698−#: qml/Wizard/Pages/80-finished.qml:91
813+#: qml/Wizard/Pages/80-finished.qml:89
699814msgid "Welcome to Ubuntu"
700815msgstr ""
701816
702−#: qml/Wizard/Pages/80-finished.qml:106
817+#: qml/Wizard/Pages/80-finished.qml:104
703818msgid "You are ready to use your device now"
704819msgstr ""
705820
706−#: qml/Wizard/Pages/80-finished.qml:126
707−msgid "Continue"
821+#: qml/Wizard/Pages/80-finished.qml:124
822+msgid "Get Started"
708823msgstr ""
709824
710−#: qml/Wizard/Pages/80-finished.qml:126
711−msgid "Get Started"
825+#: qml/Wizard/Pages/here-terms.qml:25
826+msgid "Terms & Conditions"
827+msgstr ""
828+
829+#: qml/Wizard/Pages/here-terms.qml:69
830+msgid "Your device uses positioning technologies provided by HERE."
831+msgstr ""
832+
833+#: qml/Wizard/Pages/here-terms.qml:81
834+msgid ""
835+"To provide you with positioning services and to improve their quality, HERE "
836+"collects information about nearby cell towers and Wi-Fi hotspots around your "
837+"current location whenever your position is being found."
838+msgstr ""
839+
840+#: qml/Wizard/Pages/here-terms.qml:93
841+msgid ""
842+"The information collected is used to analyze the service and to improve the "
843+"use of service, but not to identify you personally."
844+msgstr ""
845+
846+#: qml/Wizard/Pages/here-terms.qml:106
847+#, qt-format
848+msgid "By continuing, you agree to the HERE platform %1 and %2."
849+msgstr ""
850+
851+#: qml/Wizard/Pages/here-terms.qml:107
852+msgid "Service Terms"
712853msgstr ""
713854
714855#: qml/Wizard/Pages/passcode-confirm.qml:43
715−#: qml/Wizard/Pages/passcode-desktop.qml:104
856+#: qml/Wizard/Pages/passcode-desktop.qml:97
716857msgid "Confirm passcode"
717858msgstr ""
718859
@@ -729,24 +870,24 @@ msgstr ""
729870msgid "Lock Screen Passcode"
730871msgstr ""
731872
732−#: qml/Wizard/Pages/passcode-desktop.qml:68
873+#: qml/Wizard/Pages/passcode-desktop.qml:61
733874msgid "Enter 4 numbers to setup your passcode"
734875msgstr ""
735876
736−#: qml/Wizard/Pages/passcode-desktop.qml:84
877+#: qml/Wizard/Pages/passcode-desktop.qml:77
737878#: qml/Wizard/Pages/passcode-set.qml:54
738879msgid "Choose passcode"
739880msgstr ""
740881
741−#: qml/Wizard/Pages/passcode-desktop.qml:139
882+#: qml/Wizard/Pages/passcode-desktop.qml:127
742883msgid "Passcode too short"
743884msgstr ""
744885
745−#: qml/Wizard/Pages/passcode-desktop.qml:141
886+#: qml/Wizard/Pages/passcode-desktop.qml:129
746887msgid "Passcodes match"
747888msgstr ""
748889
749−#: qml/Wizard/Pages/passcode-desktop.qml:143
890+#: qml/Wizard/Pages/passcode-desktop.qml:131
750891msgid "Passcodes do not match"
751892msgstr ""
752893
@@ -758,15 +899,15 @@ msgstr ""
758899msgid "Lock Screen Password"
759900msgstr ""
760901
761−#: qml/Wizard/Pages/password-set.qml:68
902+#: qml/Wizard/Pages/password-set.qml:62
762903msgid "Enter at least 8 characters"
763904msgstr ""
764905
765−#: qml/Wizard/Pages/password-set.qml:80
906+#: qml/Wizard/Pages/password-set.qml:74
766907msgid "Choose password"
767908msgstr ""
768909
769−#: qml/Wizard/Pages/password-set.qml:110
910+#: qml/Wizard/Pages/password-set.qml:104
770911msgid "Confirm password"
771912msgstr ""
772913
@@ -822,42 +963,12 @@ msgstr ""
822963msgid "Very weak password"
823964msgstr ""
824965
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−
858966#~ msgid "Confirm"
859967#~ msgstr "Təsdiqlə"
860968
969+#~ msgid "Search"
970+#~ msgstr "Axtar"
971+
861972#~ msgid "Top edge"
862973#~ msgstr "Yuxarı künc"
863974
@@ -873,6 +984,12 @@ msgstr ""
873984#~ msgid "Right edge"
874985#~ msgstr "Sağ Künc"
875986
987+#~ msgid "Speaking..."
988+#~ msgstr "Danışır..."
989+
990+#~ msgid "Loading. Please Wait..."
991+#~ msgstr "Yüklənir. Zəhmət olmasa, gözləyin..."
992+
876993#~ msgid "Speak Now..."
877994#~ msgstr "Danışın..."
878995
@@ -908,18 +1025,18 @@ msgstr ""
9081025#~ msgstr "Bu sizin son cəhdiniz olacaq."
9091026
9101027#~ msgid ""
911−#~ "If passcode is entered incorrectly, your phone will conduct a factory "
912−#~ "reset and all personal data will be deleted."
1028+#~ "If passcode is entered incorrectly, your phone will conduct a factory reset "
1029+#~ "and all personal data will be deleted."
9131030#~ msgstr ""
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."
1031+#~ "Əgər açar kod yanlış daxil edilibsə, onda telefonunuz fabrika parametrlərinə "
1032+#~ "geri qayıdacaq və bütün şəxsi məlumatlarınız silinəcək."
9161033
9171034#~ msgid ""
9181035#~ "If passphrase is entered incorrectly, your phone will conduct a factory "
9191036#~ "reset and all personal data will be deleted."
9201037#~ msgstr ""
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."
1038+#~ "Əgər açar söz yanlış daxil edilibsə, onda telefonunuz fabrika parametrlərinə "
1039+#~ "geri qayıdacaq və bütün şəxsi məlumatlarınız silinəcək."
9231040
9241041#~ msgid "Log out"
9251042#~ msgstr "Çıxış"
@@ -933,6 +1050,9 @@ msgstr ""
9331050#~ msgid "Reboot"
9341051#~ msgstr "Yenidən yüklə"
9351052
1053+#~ msgid "Try swiping from the top edge to access the indicators"
1054+#~ msgstr "Göstəriciləri görmәk üçün yuxarı küncdən sürüşdürün"
1055+
9361056#~ msgid "Skip intro"
9371057#~ msgstr "Tәqdimatı keç"
9381058
@@ -961,6 +1081,7 @@ msgstr ""
9611081#~ msgid "Sorry, incorrect passphrase"
9621082#~ msgstr "Bağışlayın, açar söz yanlışdır"
9631083
1084+#, qt-format
9641085#~ msgid "Sorry, incorrect %1"
9651086#~ msgstr "Bağışlayın, %1 yanlışdır"
9661087
po/be.po+483−402
@@ -6,74 +6,72 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
9−"Report-Msgid-Bugs-To: \n"
10−"POT-Creation-Date: 2021-01-29 11:42-0600\n"
11−"PO-Revision-Date: 2021-03-07 20:28+0000\n"
12−"Last-Translator: Zmicer <nashtlumach@gmail.com>\n"
13−"Language-Team: Belarusian <https://translate.ubports.com/projects/ubports/"
14−"lomiri/be/>\n"
15−"Language: be\n"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2017-03-21 10:58+0000\n"
11+"PO-Revision-Date: 2015-12-13 13:12+0000\n"
12+"Last-Translator: Mikhail_SaTuRn <mikhail_saturn@tut.by>\n"
13+"Language-Team: Belarusian <be@li.org>\n"
1614"MIME-Version: 1.0\n"
1715"Content-Type: text/plain; charset=UTF-8\n"
1816"Content-Transfer-Encoding: 8bit\n"
19−"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
20−"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
21−"X-Generator: Weblate 3.11.3\n"
22−"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
17+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
19+"X-Launchpad-Export-Date: 2017-03-24 06:13+0000\n"
20+"X-Generator: Launchpad (build 18334)\n"
2321
24−#: plugins/LightDM/Greeter.cpp:199
22+#: plugins/LightDM/Greeter.cpp:188
2523msgid "Password: "
2624msgstr "Пароль: "
2725
28−#: plugins/LightDM/Greeter.cpp:214
26+#: plugins/LightDM/Greeter.cpp:203
2927msgid "Username"
30−msgstr "Імя карыстальніка"
28+msgstr ""
3129
32−#: plugins/LightDM/Greeter.cpp:258
30+#: plugins/LightDM/Greeter.cpp:242
3331msgid "Failed to authenticate"
34−msgstr "Не атрымалася выканаць аўтэнтыфікацыю"
32+msgstr ""
3533
36−#: plugins/LightDM/Greeter.cpp:260
34+#: plugins/LightDM/Greeter.cpp:244
3735msgid "Invalid password, please try again"
38−msgstr "Хібны пароль, паспрабуйце яшчэ раз"
36+msgstr ""
3937
40−#: plugins/LightDM/Greeter.cpp:270
38+#: plugins/LightDM/Greeter.cpp:254
4139msgid "Log In"
42−msgstr "Увайсці"
40+msgstr ""
4341
44−#: plugins/LightDM/Greeter.cpp:270
42+#: plugins/LightDM/Greeter.cpp:254
4543msgid "Retry"
4644msgstr "Паспрабаваць зноў"
4745
48−#: plugins/LightDM/UsersModel.cpp:157
46+#: plugins/LightDM/UsersModel.cpp:152
4947msgid "Login"
50−msgstr "Увайсці"
48+msgstr ""
5149
52−#: plugins/LightDM/UsersModel.cpp:165
50+#: plugins/LightDM/UsersModel.cpp:160
5351msgid "Guest Session"
54−msgstr "Гасцявы сеанс"
52+msgstr ""
5553
56−#: plugins/Unity/Launcher/launcheritem.cpp:48
57−#: plugins/Unity/Launcher/launcheritem.cpp:122
54+#: plugins/Unity/Launcher/launcheritem.cpp:49
55+#: plugins/Unity/Launcher/launcheritem.cpp:123
5856msgid "Pin shortcut"
59−msgstr "Замацаваць цэтлік"
57+msgstr "Замацаваць кнопку"
6058
61−#: plugins/Unity/Launcher/launcheritem.cpp:54
59+#: plugins/Unity/Launcher/launcheritem.cpp:55
6260msgid "Quit"
6361msgstr "Выйсці"
6462
65−#: plugins/Unity/Launcher/launcheritem.cpp:122
63+#: plugins/Unity/Launcher/launcheritem.cpp:123
6664msgid "Unpin shortcut"
67−msgstr "Адмацаваць цэтлік"
65+msgstr "Адмацаваць кнопку"
6866
6967#: qml/Components/Dialogs.qml:176
7068msgctxt "Title: Lock/Log out dialog"
7169msgid "Log out"
72−msgstr "Завяршыць сеанс"
70+msgstr "Выйсці"
7371
7472#: qml/Components/Dialogs.qml:177
7573msgid "Are you sure you want to log out?"
76−msgstr "Сапраўды завяршыць сеанс?"
74+msgstr "Вы ўпэўненыя, што хочаце выйсці?"
7775
7876#: qml/Components/Dialogs.qml:180
7977msgctxt "Button: Lock the system"
@@ -85,8 +83,9 @@ msgctxt "Button: Log out from the system"
8583msgid "Log Out"
8684msgstr "Выйсці"
8785
88−#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
89−#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
86+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:264
87+#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:222
88+#: qml/Wizard/Pages/passcode-confirm.qml:32
9089#: qml/Wizard/Pages/passcode-set.qml:32
9190msgid "Cancel"
9291msgstr "Скасаваць"
@@ -98,7 +97,7 @@ msgstr "Перазагрузіць"
9897
9998#: qml/Components/Dialogs.qml:212
10099msgid "Are you sure you want to reboot?"
101−msgstr "Сапраўды хочаце перазагрузіць сістэму?"
100+msgstr "Вы ўпэўнены, што жадаеце перазагрузіць?"
102101
103102#: qml/Components/Dialogs.qml:215
104103msgid "No"
@@ -108,206 +107,204 @@ msgstr "Не"
108107msgid "Yes"
109108msgstr "Так"
110109
111−#: qml/Components/Dialogs.qml:243
110+#: qml/Components/Dialogs.qml:239
112111msgctxt "Title: Power off/Restart dialog"
113112msgid "Power"
114113msgstr "Сілкаванне"
115114
116−#: qml/Components/Dialogs.qml:244
115+#: qml/Components/Dialogs.qml:240
117116msgid ""
118117"Are you sure you would like\n"
119118"to power off?"
120119msgstr ""
121−"Сапраўды хочаце\n"
122−"выключыць?"
120+"Вы ўпэўнены, што хочаце\n"
121+"выключыць камп'ютэр?"
123122
124−#: qml/Components/Dialogs.qml:248
123+#: qml/Components/Dialogs.qml:244
125124msgctxt "Button: Power off the system"
126125msgid "Power off"
127126msgstr "Выключыць"
128127
129−#: qml/Components/Dialogs.qml:263
128+#: qml/Components/Dialogs.qml:255
130129msgctxt "Button: Restart the system"
131130msgid "Restart"
132−msgstr "Перазапусціць"
133−
134−#: qml/Components/Dialogs.qml:276
135−#, fuzzy
136−#| msgid "Takes a screenshot."
137−msgid "Screenshot"
138−msgstr "Здымак экрана."
131+msgstr "Перазапуск"
139132
140133#: qml/Components/KeyboardShortcutsOverlay.qml:41
141134msgid "Keyboard Shortcuts"
142−msgstr "Спалучэнні клавіш"
135+msgstr ""
143136
144137#: qml/Components/KeyboardShortcutsOverlay.qml:55
145−msgid "Lomiri"
138+msgid "Unity 8"
146139msgstr ""
147140
148141#: qml/Components/KeyboardShortcutsOverlay.qml:62
149142msgid "PrtScr"
150−msgstr "PrtScr"
143+msgstr ""
151144
152145#: qml/Components/KeyboardShortcutsOverlay.qml:67
153146msgid "Takes a screenshot."
154−msgstr "Здымак экрана."
147+msgstr ""
155148
156149#: qml/Components/KeyboardShortcutsOverlay.qml:75
157150msgid "Alt + PrtScr"
158−msgstr "Alt + PrtScr"
151+msgstr ""
159152
160153#: qml/Components/KeyboardShortcutsOverlay.qml:80
161154msgid "Takes a screenshot of the current window."
162−msgstr "Робіць здымак экрана бягучага акна."
155+msgstr ""
163156
164157#: qml/Components/KeyboardShortcutsOverlay.qml:88
165158msgid "Super + Space"
166−msgstr "Super + Прагал"
159+msgstr ""
167160
168161#: qml/Components/KeyboardShortcutsOverlay.qml:93
169162msgid "Switches to next keyboard layout."
170−msgstr "Пераключыцца на наступную раскладку клавіятуры."
163+msgstr ""
171164
172165#: qml/Components/KeyboardShortcutsOverlay.qml:101
173166msgid "Super + Shift + Space"
174−msgstr "Super + Shift + Прагал"
167+msgstr ""
175168
176169#: qml/Components/KeyboardShortcutsOverlay.qml:106
177170msgid "Switches to previous keyboard layout."
178−msgstr "Пераключыцца на папярэднюю раскладку клавіятуры."
179−
180−#: qml/Components/KeyboardShortcutsOverlay.qml:114
181−msgid "Ctrl + Alt + T"
182−msgstr "Ctrl + Alt + T"
183−
184−#: qml/Components/KeyboardShortcutsOverlay.qml:119
185−msgid "Starts the Terminal application."
186−msgstr "Запускае тэрмінал."
171+msgstr ""
187172
188−#: qml/Components/KeyboardShortcutsOverlay.qml:131
173+#: qml/Components/KeyboardShortcutsOverlay.qml:118
189174msgid "Launcher"
190−msgstr "Панэль запуску"
175+msgstr ""
191176
192−#: qml/Components/KeyboardShortcutsOverlay.qml:138
177+#: qml/Components/KeyboardShortcutsOverlay.qml:125
193178msgid "Super (Hold)"
194−msgstr "Super (утрыманне)"
179+msgstr ""
195180
196−#: qml/Components/KeyboardShortcutsOverlay.qml:143
181+#: qml/Components/KeyboardShortcutsOverlay.qml:130
197182msgid "Opens the launcher, displays shortcuts."
198−msgstr "Адкрывае панэль запуску, паказвае спалучэнні клавіш."
183+msgstr ""
199184
200−#: qml/Components/KeyboardShortcutsOverlay.qml:151
185+#: qml/Components/KeyboardShortcutsOverlay.qml:138
201186msgid "Alt + F1"
202−msgstr "Alt + F1"
187+msgstr ""
203188
204−#: qml/Components/KeyboardShortcutsOverlay.qml:156
189+#: qml/Components/KeyboardShortcutsOverlay.qml:143
205190msgid "Opens launcher keyboard navigation mode."
206−msgstr "Актывуе рэжым навігацыі па панэлі запуску з клавіятуры."
191+msgstr ""
207192
208−#: qml/Components/KeyboardShortcutsOverlay.qml:164
193+#: qml/Components/KeyboardShortcutsOverlay.qml:151
209194msgid "Super + Tab"
210−msgstr "Super + Tab"
195+msgstr ""
211196
212−#: qml/Components/KeyboardShortcutsOverlay.qml:169
197+#: qml/Components/KeyboardShortcutsOverlay.qml:156
213198msgid "Switches applications via the launcher."
214−msgstr "Пераключае праграмы праз панэль запуску."
199+msgstr ""
215200
216−#: qml/Components/KeyboardShortcutsOverlay.qml:177
201+#: qml/Components/KeyboardShortcutsOverlay.qml:164
217202msgid "Super + 1 to 0"
218−msgstr "Super + лічба ад 1 да 0"
203+msgstr ""
219204
220−#: qml/Components/KeyboardShortcutsOverlay.qml:182
205+#: qml/Components/KeyboardShortcutsOverlay.qml:169
221206msgid "Same as clicking on a launcher icon."
222−msgstr "Адпаведнік націскання на значок запуску."
207+msgstr ""
223208
224−#: qml/Components/KeyboardShortcutsOverlay.qml:190
209+#: qml/Components/KeyboardShortcutsOverlay.qml:177
225210msgid "Super + A"
226−msgstr "Super + A"
211+msgstr ""
227212
228−#: qml/Components/KeyboardShortcutsOverlay.qml:195
213+#: qml/Components/KeyboardShortcutsOverlay.qml:182
229214msgid "Opens the Application Drawer."
230−msgstr "Адкрывае спіс усталяваных праграм."
215+msgstr ""
231216
232−#: qml/Components/KeyboardShortcutsOverlay.qml:235
217+#: qml/Components/KeyboardShortcutsOverlay.qml:194
218+msgid "Scopes"
219+msgstr ""
220+
221+#: qml/Components/KeyboardShortcutsOverlay.qml:201
222+msgid "Super (Tap)"
223+msgstr ""
224+
225+#: qml/Components/KeyboardShortcutsOverlay.qml:206
226+msgid "Opens the Scopes home."
227+msgstr ""
228+
229+#: qml/Components/KeyboardShortcutsOverlay.qml:222
233230msgid "Switching"
234−msgstr "Пераключэнне"
231+msgstr ""
235232
236−#: qml/Components/KeyboardShortcutsOverlay.qml:242
233+#: qml/Components/KeyboardShortcutsOverlay.qml:229
237234msgid "Alt + Tab"
238−msgstr "Alt + Tab"
235+msgstr ""
239236
240−#: qml/Components/KeyboardShortcutsOverlay.qml:247
237+#: qml/Components/KeyboardShortcutsOverlay.qml:234
241238msgid "Switches between applications."
242−msgstr "Пераключэнне паміж праграмамі."
239+msgstr ""
243240
244−#: qml/Components/KeyboardShortcutsOverlay.qml:255
241+#: qml/Components/KeyboardShortcutsOverlay.qml:242
245242msgid "Super + W"
246−msgstr "Super + W"
243+msgstr ""
247244
248−#: qml/Components/KeyboardShortcutsOverlay.qml:260
245+#: qml/Components/KeyboardShortcutsOverlay.qml:247
249246msgid "Opens the desktop spread."
250−msgstr "Адкрывае працоўны стол."
247+msgstr ""
251248
252−#: qml/Components/KeyboardShortcutsOverlay.qml:268
249+#: qml/Components/KeyboardShortcutsOverlay.qml:255
253250msgid "Cursor Left or Right"
254−msgstr "Улева ці ўправа"
251+msgstr ""
255252
256−#: qml/Components/KeyboardShortcutsOverlay.qml:273
253+#: qml/Components/KeyboardShortcutsOverlay.qml:260
257254msgid "Moves the focus."
258−msgstr "Перамяшчае фокус."
255+msgstr ""
259256
260−#: qml/Components/KeyboardShortcutsOverlay.qml:285
257+#: qml/Components/KeyboardShortcutsOverlay.qml:272
261258msgid "Windows"
262−msgstr "Вокны"
259+msgstr ""
263260
264−#: qml/Components/KeyboardShortcutsOverlay.qml:292
261+#: qml/Components/KeyboardShortcutsOverlay.qml:279
265262msgid "Ctrl + Super + D"
266−msgstr "Ctrl + Super + D"
263+msgstr ""
267264
268−#: qml/Components/KeyboardShortcutsOverlay.qml:297
265+#: qml/Components/KeyboardShortcutsOverlay.qml:284
269266msgid "Minimizes all windows."
270−msgstr "Згарнуць усе вокны."
267+msgstr ""
271268
272−#: qml/Components/KeyboardShortcutsOverlay.qml:305
269+#: qml/Components/KeyboardShortcutsOverlay.qml:292
273270msgid "Ctrl + Super + Up"
274−msgstr "Ctrl + Super + уверх"
271+msgstr ""
275272
276−#: qml/Components/KeyboardShortcutsOverlay.qml:310
273+#: qml/Components/KeyboardShortcutsOverlay.qml:297
277274msgid "Maximizes the current window."
278−msgstr "Разгарнуць бягучае акно."
275+msgstr ""
279276
280−#: qml/Components/KeyboardShortcutsOverlay.qml:318
277+#: qml/Components/KeyboardShortcutsOverlay.qml:305
281278msgid "Ctrl + Super + Down"
282−msgstr "Ctrl + Super + уніз"
279+msgstr ""
283280
284−#: qml/Components/KeyboardShortcutsOverlay.qml:323
281+#: qml/Components/KeyboardShortcutsOverlay.qml:310
285282msgid "Minimizes or restores the current window."
286−msgstr "Згарнуць альбо аднавіць бягучае акно."
283+msgstr ""
287284
288−#: qml/Components/KeyboardShortcutsOverlay.qml:331
285+#: qml/Components/KeyboardShortcutsOverlay.qml:318
289286msgid "Ctrl + Super + Left or Right"
290−msgstr "Ctrl + Super + улева ці ўправа"
287+msgstr ""
291288
292−#: qml/Components/KeyboardShortcutsOverlay.qml:336
289+#: qml/Components/KeyboardShortcutsOverlay.qml:323
293290msgid "Semi-maximizes the current window."
294−msgstr "Разгортвае бягучае акно напалову."
291+msgstr ""
295292
296−#: qml/Components/KeyboardShortcutsOverlay.qml:344
293+#: qml/Components/KeyboardShortcutsOverlay.qml:331
297294msgid "Alt + F4"
298−msgstr "Alt + F4"
295+msgstr ""
299296
300−#: qml/Components/KeyboardShortcutsOverlay.qml:349
297+#: qml/Components/KeyboardShortcutsOverlay.qml:336
301298msgid "Closes the current window."
302−msgstr "Закрывае бягучае акно."
299+msgstr ""
303300
304−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
301+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:242
305302msgid "Return to Call"
306303msgstr "Вярнуцца да выкліку"
307304
308305#: qml/Components/Lockscreen.qml:212
309306msgid "Emergency Call"
310−msgstr "Экстраны выклік"
307+msgstr "Терміновы выклік"
311308
312309#: qml/Components/Lockscreen.qml:245
313310msgid "OK"
@@ -316,28 +313,26 @@ msgstr "Добра"
316313#: qml/Components/MediaServices/VideoPlayerControls.qml:44
317314#, qt-format
318315msgid "%1:%2:%3"
319−msgstr "%1:%2:%3"
316+msgstr ""
320317
321318#: qml/Components/MediaServices/VideoPlayerControls.qml:49
322319#, qt-format
323320msgid "%1:%2"
324−msgstr "%1:%2"
321+msgstr ""
325322
326323#: qml/Components/ModeSwitchWarningDialog.qml:33
327324msgid "Apps may have unsaved data:"
328−msgstr "У праграм могуць быць незахаваныя даныя:"
325+msgstr "Прылады могуць мець незахованыя дадзеныя:"
329326
330327#: qml/Components/ModeSwitchWarningDialog.qml:60
331328msgctxt ""
332329"Re-dock means connect the device again to an external screen/mouse/keyboard"
333330msgid "Re-dock, save your work and close these apps to continue."
334331msgstr ""
335−"Перападлучыцеся, захавайце вынікі працы і закрыйце вокны праграм, каб "
336−"працягнуць."
337332
338333#: qml/Components/ModeSwitchWarningDialog.qml:67
339334msgid "Or force close now (unsaved data will be lost)."
340−msgstr "Альбо закрыйце прымусова (незахаваныя даныя страцяцца)."
335+msgstr "Прымусіць зачыніць (незахаваныя дадзеныя будуць страчаны)."
341336
342337#: qml/Components/ModeSwitchWarningDialog.qml:80
343338msgid "OK, I will reconnect"
@@ -349,35 +344,130 @@ msgstr "Перападлучыцца зараз!"
349344
350345#: qml/Components/ModeSwitchWarningDialog.qml:94
351346msgid "Close all"
352−msgstr "Закрыць усе"
347+msgstr "Зачыніць усё"
353348
354349#: qml/Components/SharingPicker.qml:54
355350msgid "Preview Share Item"
356−msgstr "Папярэдні прагляд"
351+msgstr "Праглядзець элемент"
357352
358353#: qml/Components/VirtualTouchPad.qml:317
359354msgid ""
360355"Your device is now connected to an external display. Use this screen as a "
361356"touch pad to interact with the pointer."
362357msgstr ""
363−"Ваша прылада падлучаная да вонкавага дысплея. Выкарыстоўвайце гэты экран як "
364−"сэнсарную панэль для кіравання курсорам."
365358
366359#: qml/Components/VirtualTouchPad.qml:327
367360msgid "Tap left button to click."
368−msgstr "Націсніце левую кнопку, каб пстрыкнуць."
361+msgstr ""
369362
370363#: qml/Components/VirtualTouchPad.qml:339
371364msgid "Tap right button to right click."
372−msgstr "Націсніце правую кнопку, каб пстрыкнуць правай клавішай мышы."
365+msgstr ""
373366
374367#: qml/Components/VirtualTouchPad.qml:351
375368msgid "Swipe with two fingers to scroll."
376−msgstr "Правядзіце двума пальцамі, каб пракруціць."
369+msgstr ""
377370
378371#: qml/Components/VirtualTouchPad.qml:396
379372msgid "Find more settings in the system settings."
380−msgstr "Больш налад можна знайсці ў сістэмных наладах."
373+msgstr ""
374+
375+#: qml/Dash/DashPageHeader.qml:361
376+msgctxt "Button: Open the Ubuntu Store"
377+msgid "Store"
378+msgstr "Крама"
379+
380+#: qml/Dash/DashPageHeader.qml:368
381+msgctxt "Button: Start a search in the current dash scope"
382+msgid "Search"
383+msgstr "Пошук"
384+
385+#: qml/Dash/DashPageHeader.qml:378
386+msgctxt "Button: Show the current dash scope settings"
387+msgid "Settings"
388+msgstr "Налады"
389+
390+#: qml/Dash/DashPageHeader.qml:385
391+msgid "Remove from Favorites"
392+msgstr "Выдаліць з абранага"
393+
394+#: qml/Dash/DashPageHeader.qml:385
395+msgid "Add to Favorites"
396+msgstr "Дадаць да абранага"
397+
398+#: qml/Dash/FiltersPopover.qml:61
399+msgid "Refine your results"
400+msgstr ""
401+
402+#: qml/Dash/FiltersPopover.qml:70
403+msgid "Reset"
404+msgstr ""
405+
406+#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
407+msgid "Show less"
408+msgstr ""
409+
410+#: qml/Dash/GenericScopeView.qml:547
411+msgid "Show all"
412+msgstr ""
413+
414+#: qml/Dash/GenericScopeView.qml:578
415+msgctxt "Label: Hint for dash search line edit"
416+msgid "Search"
417+msgstr "Пошук"
418+
419+#: qml/Dash/PageHeaderExtraPanel.qml:67
420+msgid "Recent Searches"
421+msgstr ""
422+
423+#: qml/Dash/PageHeaderExtraPanel.qml:78
424+msgid "Clear All"
425+msgstr ""
426+
427+#: qml/Dash/Previews/PreviewActionCombo.qml:36
428+msgid "More..."
429+msgstr "Болей…"
430+
431+#: qml/Dash/Previews/PreviewActionCombo.qml:36
432+msgid "Less..."
433+msgstr "Менш..."
434+
435+#: qml/Dash/Previews/PreviewCommentInput.qml:83
436+#: qml/Dash/Previews/PreviewRatingInput.qml:202
437+msgid "Send"
438+msgstr "Адправіць"
439+
440+#: qml/Dash/Previews/PreviewRatingInput.qml:109
441+msgid "Rate this"
442+msgstr "Ацаніць"
443+
444+#: qml/Dash/Previews/PreviewRatingInput.qml:184
445+msgid "Add a review"
446+msgstr "Дадаць рэцэнзію"
447+
448+#: qml/Dash/PullToRefreshScopeStyle.qml:56
449+msgid "Pull to refresh…"
450+msgstr "Пацягніце для абнаўлення..."
451+
452+#: qml/Dash/PullToRefreshScopeStyle.qml:61
453+msgid "Release to refresh…"
454+msgstr "Адпусціце для абнаўлення..."
455+
456+#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
457+msgid "Enable location data"
458+msgstr "Уключыць дадзеныя аб месцазнаходжанні"
459+
460+#: qml/Dash/ScopesList.qml:146
461+msgid "Manage"
462+msgstr "Кіраванне"
463+
464+#: qml/Dash/ScopesList.qml:187
465+msgid "Home"
466+msgstr "Хатняя папка"
467+
468+#: qml/Dash/ScopesList.qml:188
469+msgid "Also installed"
470+msgstr "Таксама ўсталявана"
381471
382472#: qml/Greeter/CoverPage.qml:127
383473msgid "Unlock"
@@ -390,13 +480,12 @@ msgstr "Прылада заблакаваная"
390480#: qml/Greeter/DelayedLockscreen.qml:58
391481msgid "You have been locked out due to too many failed passphrase attempts."
392482msgstr ""
393−"Вы былі заблакаваныя праз занадта вялікую колькасць няўдалых спробаў уводу "
394−"пароля."
483+"Вы былі заблакаваныя з-за занадта вялікай колькасці няўдалых спробаў."
395484
396485#: qml/Greeter/DelayedLockscreen.qml:59
397486msgid "You have been locked out due to too many failed passcode attempts."
398487msgstr ""
399−"Вы былі заблакаваныя праз занадта вялікую колькасць няўдалых спробаў уводу "
488+"Вы былі заблакаваныя з-за занадта вялікай колькасці няўдалых спробаў уводу "
400489"кода доступу."
401490
402491#: qml/Greeter/DelayedLockscreen.qml:68
@@ -407,45 +496,46 @@ msgstr[0] "Пачакайце %1 хвіліну і паўтарыце спроб
407496msgstr[1] "Пачакайце %1 хвіліны і паўтарыце спробу…"
408497msgstr[2] "Пачакайце %1 хвілін і паўтарыце спробу…"
409498
410−#: qml/Greeter/Greeter.qml:550
499+#: qml/Greeter/Greeter.qml:561
411500msgid "Try again"
412−msgstr "Паспрабаваць зноў"
501+msgstr ""
413502
414−#: qml/Greeter/Greeter.qml:551
503+#: qml/Greeter/Greeter.qml:562
415504msgid "Enter passphrase to unlock"
416−msgstr "Увядзіце парольную фразу, каб разблакаваць"
505+msgstr ""
417506
418−#: qml/Greeter/Greeter.qml:552
507+#: qml/Greeter/Greeter.qml:563
419508msgid "Enter passcode to unlock"
420−msgstr "Увядзіце код доступу, каб разблакаваць"
509+msgstr ""
421510
422−#: qml/Greeter/NarrowView.qml:235
511+#: qml/Greeter/NarrowView.qml:242
423512msgid "Emergency"
424−msgstr "Экстраны выклік"
513+msgstr ""
425514
426515#: qml/Greeter/PromptList.qml:126
427516msgid "Passphrase"
428−msgstr "Парольная фраза"
517+msgstr ""
429518
430519#: qml/Greeter/PromptList.qml:126
431520msgid "Passcode"
432−msgstr "Код доступу"
521+msgstr ""
433522
434−#: qml/Greeter/SessionsList.qml:124
523+#: qml/Greeter/SessionsList.qml:122
435524msgid "Select desktop environment"
436−msgstr "Абраць працоўнае асяроддзе"
525+msgstr ""
437526
438−#: qml/Launcher/Drawer.qml:250
527+#: qml/Launcher/Drawer.qml:93
439528msgid "Search…"
440−msgstr "Пошук…"
529+msgstr ""
441530
442−#: qml/Launcher/PullToRefreshScopeStyle.qml:56
443−msgid "Pull to refresh…"
444−msgstr "Пацягніце для абнаўлення..."
531+#: qml/Launcher/Drawer.qml:128
532+msgctxt "Apps sorted alphabetically"
533+msgid "A-Z"
534+msgstr ""
445535
446−#: qml/Launcher/PullToRefreshScopeStyle.qml:61
447−msgid "Release to refresh…"
448−msgstr "Адпусціце для абнаўлення..."
536+#: qml/Launcher/MoreAppsHeader.qml:55
537+msgid "More apps in the store"
538+msgstr ""
449539
450540#: qml/Notifications/NotificationMenuItemFactory.qml:124
451541msgid "Show password"
@@ -461,7 +551,7 @@ msgstr "Канферэнцыя"
461551
462552#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:869
463553msgid "Nothing is playing"
464−msgstr "Нічога не прайграецца"
554+msgstr "Нічога не грае"
465555
466556#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:997
467557#, qt-format
@@ -469,7 +559,7 @@ msgid "%1 hour"
469559msgid_plural "%1 hours"
470560msgstr[0] "%1 гадзіна"
471561msgstr[1] "%1 гадзіны"
472−msgstr[2] "%1 гадзін"
562+msgstr[2] "%1 гадзінаў"
473563
474564#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1001
475565#, qt-format
@@ -477,7 +567,7 @@ msgid "%1 minute"
477567msgid_plural "%1 minutes"
478568msgstr[0] "%1 хвіліна"
479569msgstr[1] "%1 хвіліны"
480−msgstr[2] "%1 хвілін"
570+msgstr[2] "%1 хвілінаў"
481571
482572#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1006
483573#, qt-format
@@ -485,7 +575,7 @@ msgid "%1 second"
485575msgid_plural "%1 seconds"
486576msgstr[0] "%1 секунда"
487577msgstr[1] "%1 секунды"
488−msgstr[2] "%1 секунд"
578+msgstr[2] "%1 секундаў"
489579
490580#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1009
491581msgid "0 seconds"
@@ -495,15 +585,15 @@ msgstr "0 секунд"
495585#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1011
496586#, qt-format
497587msgid "%1 remaining"
498−msgstr "Засталося %1"
588+msgstr "%1 засталося"
499589
500590#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1017
501591msgid "In queue…"
502−msgstr "У чарзе…"
592+msgstr "У чарзе..."
503593
504594#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1021
505595msgid "Downloading"
506−msgstr "Запампоўванне"
596+msgstr "Запампоўка"
507597
508598#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1023
509599msgid "Paused, tap to resume"
@@ -515,7 +605,7 @@ msgstr "Скасавана"
515605
516606#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1027
517607msgid "Finished"
518−msgstr "Завершана"
608+msgstr "Скончана"
519609
520610#: qml/Panel/Indicators/IndicatorMenuItemFactory.qml:1029
521611msgid "Failed, tap to retry"
@@ -525,7 +615,7 @@ msgstr "Не атрымалася, націсніце, каб паўтарыць
525615#: qml/Panel/Indicators/MessageMenuItemFactory.qml:210
526616msgctxt "Button: Send a reply message"
527617msgid "Send"
528−msgstr "Адправіць"
618+msgstr "Даслаць"
529619
530620#: qml/Panel/Indicators/MessageMenuItemFactory.qml:152
531621msgctxt "Label: Hint in message indicator line edit"
@@ -539,265 +629,309 @@ msgstr "Патэлефанаваць"
539629
540630#: qml/Panel/PanelMenuPage.qml:92
541631msgid "Back"
542−msgstr "Назад"
632+msgstr ""
543633
544634#: qml/Stage/SideStage.qml:76
545635msgid "Drag using 3 fingers any application from one window to the other"
546−msgstr "Перацягвайце любую праграму пры дапамозе трох пальцаў"
547−
548−#: qml/Stage/Stage.qml:671
549−msgid "No running apps"
550−msgstr "Няма запушчаных праграм"
636+msgstr ""
551637
552638#: qml/Tutorial/TutorialLeftLong.qml:49
553639msgid "Long swipe from the left edge to open the Application Drawer"
554−msgstr "Правядзіце ад левага краю, каб адкрыць панэль праграм"
640+msgstr ""
555641
556642#: qml/Tutorial/TutorialLeft.qml:47
557643msgid "Short swipe from the left edge to open the launcher"
558−msgstr "Коратка правядзіце ад левага краю, каб адкрыць панэль запуску"
644+msgstr ""
559645
560−#: qml/Tutorial/TutorialRight.qml:54
646+#: qml/Tutorial/TutorialRight.qml:55
561647msgid "Push your mouse against the right edge to view your open apps"
562648msgstr ""
563−"Навядзіце курсор мышы на правы край экрана, каб праглядзець спіс адкрытых "
564−"акон праграм"
565649
566−#: qml/Tutorial/TutorialRight.qml:55
650+#: qml/Tutorial/TutorialRight.qml:56
567651msgid "Swipe from the right edge to view your open apps"
568−msgstr "Правядзіце ад правага краю, каб праглядзець спіс адкрытых акон праграм"
652+msgstr ""
569653
570654#: qml/Tutorial/TutorialTop.qml:53
571655msgid "Swipe from the top edge to access notifications and quick settings"
572656msgstr ""
573−"Правядзіце ад верхняга краю, каб атрымаць доступ да апавяшчэнняў і хуткіх "
574−"налад"
575657
576−#: qml/Wizard/Page.qml:59
658+#: qml/Wizard/Page.qml:54
577659msgctxt "Button: Go back one page in the Wizard"
578660msgid "Back"
579−msgstr "Назад"
661+msgstr "Вярнуцца"
580662
581−#: qml/Wizard/Pages/10-welcome.qml:29
663+#: qml/Wizard/Pages/10-welcome.qml:28
582664msgid "Language"
583−msgstr "Мова"
584−
585−#: qml/Wizard/Pages/10-welcome.qml:176
586−#: qml/Wizard/Pages/10-welcome-update.qml:126
587−#: qml/Wizard/Pages/11-changelog.qml:74 qml/Wizard/Pages/20-keyboard.qml:152
588−#: qml/Wizard/Pages/30-wifi.qml:214 qml/Wizard/Pages/50-timezone.qml:272
589−#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/70-passwd-type.qml:146
590−#: qml/Wizard/Pages/passcode-desktop.qml:154
591−#: qml/Wizard/Pages/password-set.qml:153
592−msgid "Next"
593−msgstr "Далей"
594−
595−#: qml/Wizard/Pages/10-welcome-update.qml:91
596−msgid "Welcome to "
597−msgstr "Вітаем у "
598−
599−#: qml/Wizard/Pages/10-welcome-update.qml:106
600−msgid "We will make sure your device is ready to use "
601−msgstr "Мы праверым, ці гатовая да выкарыстання вашая прылада "
602−
603−#: qml/Wizard/Pages/11-changelog.qml:28
604−msgid "What's new"
605−msgstr "Што новага"
665+msgstr ""
606666
607−#: qml/Wizard/Pages/11-changelog.qml:74
608−msgid "Loading..."
609−msgstr "Загрузка..."
667+#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
668+#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
669+#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
670+#: qml/Wizard/Pages/70-passwd-type.qml:145
671+#: qml/Wizard/Pages/75-report-check.qml:84
672+#: qml/Wizard/Pages/passcode-desktop.qml:142
673+#: qml/Wizard/Pages/password-set.qml:142
674+msgid "Next"
675+msgstr ""
610676
611677#: qml/Wizard/Pages/20-keyboard.qml:31
612678msgid "Select Keyboard"
613−msgstr "Абярыце клавіятуру"
679+msgstr ""
614680
615681#: qml/Wizard/Pages/20-keyboard.qml:71
616682msgid "Keyboard language"
617−msgstr "Мова клавіятуры"
683+msgstr ""
618684
619685#: qml/Wizard/Pages/20-keyboard.qml:93
620686msgid "Keyboard layout"
621−msgstr "Раскладка клавіятуры"
687+msgstr ""
622688
623−#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:214
624−#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/79-system-update.qml:144
689+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
690+#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
625691#: qml/Wizard/Pages/sim.qml:101
626692msgid "Skip"
627−msgstr "Мінуць"
693+msgstr "Прапусціць"
628694
629695#: qml/Wizard/Pages/30-wifi.qml:31
630696msgid "Connect to Wi‑Fi"
631−msgstr "Злучэнне з Wi-Fi"
697+msgstr "Злучыцца з Wi-Fi"
632698
633−#: qml/Wizard/Pages/30-wifi.qml:139
699+#: qml/Wizard/Pages/30-wifi.qml:132
634700msgid "Connected"
635−msgstr "Падлучана"
701+msgstr ""
636702
637−#: qml/Wizard/Pages/30-wifi.qml:172
703+#: qml/Wizard/Pages/30-wifi.qml:165
638704msgid "Available Wi-Fi networks"
639−msgstr "Даступныя сеткі Wi-Fi"
705+msgstr ""
640706
641−#: qml/Wizard/Pages/30-wifi.qml:173
707+#: qml/Wizard/Pages/30-wifi.qml:166
642708msgid "No available Wi-Fi networks"
643−msgstr "Няма даступных сетак Wi-Fi"
709+msgstr ""
710+
711+#: qml/Wizard/Pages/40-location.qml:27
712+msgid "Location Services"
713+msgstr ""
714+
715+#: qml/Wizard/Pages/40-location.qml:83
716+msgid ""
717+"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
718+"(recommended)"
719+msgstr ""
720+
721+#: qml/Wizard/Pages/40-location.qml:105
722+#, qt-format
723+msgid "By selecting this option you agree to the Nokia HERE %1."
724+msgstr ""
725+
726+#: qml/Wizard/Pages/40-location.qml:106
727+msgctxt "part of: Nokia HERE terms and conditions"
728+msgid "terms and conditions"
729+msgstr ""
730+
731+#: qml/Wizard/Pages/40-location.qml:160
732+msgid "GPS only"
733+msgstr ""
734+
735+#: qml/Wizard/Pages/40-location.qml:214
736+msgid "Don't use my location"
737+msgstr ""
738+
739+#: qml/Wizard/Pages/40-location.qml:260
740+msgid "You can change it later in System Settings."
741+msgstr ""
644742
645743#: qml/Wizard/Pages/50-timezone.qml:30
646744msgid "Time Zone"
647−msgstr "Часавы пояс"
745+msgstr ""
648746
649−#: qml/Wizard/Pages/50-timezone.qml:183
747+#: qml/Wizard/Pages/50-timezone.qml:182
650748msgid "Enter your city"
651−msgstr "Увядзіце ваш горад"
749+msgstr ""
652750
653751#: qml/Wizard/Pages/60-account.qml:24
654752msgid "Personalize Your Device"
655−msgstr "Персаналізацыя прылады"
753+msgstr ""
656754
657−#: qml/Wizard/Pages/60-account.qml:54
755+#: qml/Wizard/Pages/60-account.qml:48
658756msgid "Preferred Name"
659−msgstr "Пераважнае імя"
757+msgstr ""
660758
661759#: qml/Wizard/Pages/70-passwd-type.qml:40
662760msgid "Lock Screen"
663−msgstr "Заблакаваць экран"
761+msgstr ""
664762
665−#: qml/Wizard/Pages/70-passwd-type.qml:103
763+#: qml/Wizard/Pages/70-passwd-type.qml:102
666764msgctxt "Label: Type of security method"
667765msgid "Create new password"
668−msgstr "Стварыць новы пароль"
766+msgstr ""
669767
670−#: qml/Wizard/Pages/70-passwd-type.qml:105
768+#: qml/Wizard/Pages/70-passwd-type.qml:104
671769msgctxt "Label: Type of security method"
672770msgid "Create passcode (numbers only)"
673−msgstr "Стварыць код доступу (толькі лічбы)"
771+msgstr ""
674772
675−#: qml/Wizard/Pages/70-passwd-type.qml:107
773+#: qml/Wizard/Pages/70-passwd-type.qml:106
676774msgctxt "Label: Type of security method"
677775msgid "No lock code"
678−msgstr "Без кода блакавання"
776+msgstr ""
777+
778+#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
779+msgid "Privacy Policy"
780+msgstr ""
781+
782+#: qml/Wizard/Pages/75-report-check.qml:26
783+msgid "Help Us Improve"
784+msgstr ""
785+
786+#: qml/Wizard/Pages/75-report-check.qml:59
787+msgid "Improve system performance by sending us crashes and error reports."
788+msgstr ""
679789
680−#: qml/Wizard/Pages/79-system-update.qml:28
790+#: qml/Wizard/Pages/75-report-check.qml:60
791+msgid "Privacy policy"
792+msgstr ""
793+
794+#: qml/Wizard/Pages/77-system-update.qml:28
681795msgid "Update Device"
682−msgstr "Абнавіць прыладу"
796+msgstr ""
683797
684−#: qml/Wizard/Pages/79-system-update.qml:55
798+#: qml/Wizard/Pages/77-system-update.qml:55
685799msgid ""
686800"There is a system update available and ready to install. Afterwards, the "
687801"device will automatically restart."
688802msgstr ""
689−"Ёсць даступнае абнаўленне сістэмы, якое можна ўсталяваць. Пасля ўсталёўкі "
690−"сістэма аўтаматычна перазапусціцца."
691803
692−#: qml/Wizard/Pages/79-system-update.qml:76
804+#: qml/Wizard/Pages/77-system-update.qml:76
693805msgctxt "string identifying name of the update"
694−msgid "Ubuntu Touch system"
695−msgstr "Сістэма Ubuntu Touch"
806+msgid "Ubuntu system"
807+msgstr ""
696808
697−#: qml/Wizard/Pages/79-system-update.qml:83
809+#: qml/Wizard/Pages/77-system-update.qml:83
698810#, qt-format
699811msgctxt "version of the system update"
700812msgid "Version %1"
701−msgstr "Версія %1"
813+msgstr ""
702814
703−#: qml/Wizard/Pages/79-system-update.qml:95
815+#: qml/Wizard/Pages/77-system-update.qml:102
704816msgid "This could take a few minutes..."
705−msgstr "Аперацыя можа заняць некалькі хвілін…"
817+msgstr ""
706818
707−#: qml/Wizard/Pages/79-system-update.qml:109
819+#: qml/Wizard/Pages/77-system-update.qml:116
708820msgid "Install and restart now"
709−msgstr "Усталяваць і перазапусціць"
710−
711−#: qml/Wizard/Pages/80-finished.qml:91
712−msgid "Welcome Back"
713−msgstr "Сардэчна запрашаем назад"
821+msgstr ""
714822
715−#: qml/Wizard/Pages/80-finished.qml:91
823+#: qml/Wizard/Pages/80-finished.qml:89
716824msgid "Welcome to Ubuntu"
717−msgstr "Вітаем ва Ubuntu"
825+msgstr ""
718826
719−#: qml/Wizard/Pages/80-finished.qml:106
827+#: qml/Wizard/Pages/80-finished.qml:104
720828msgid "You are ready to use your device now"
721−msgstr "Цяпер прылада гатовая да выкарыстання"
722−
723−#: qml/Wizard/Pages/80-finished.qml:126
724−msgid "Continue"
725−msgstr "Працягнуць"
829+msgstr ""
726830
727−#: qml/Wizard/Pages/80-finished.qml:126
831+#: qml/Wizard/Pages/80-finished.qml:124
728832msgid "Get Started"
729−msgstr "Пачаць"
833+msgstr ""
834+
835+#: qml/Wizard/Pages/here-terms.qml:25
836+msgid "Terms & Conditions"
837+msgstr "Умовы карыстання"
838+
839+#: qml/Wizard/Pages/here-terms.qml:69
840+msgid "Your device uses positioning technologies provided by HERE."
841+msgstr ""
842+
843+#: qml/Wizard/Pages/here-terms.qml:81
844+msgid ""
845+"To provide you with positioning services and to improve their quality, HERE "
846+"collects information about nearby cell towers and Wi-Fi hotspots around your "
847+"current location whenever your position is being found."
848+msgstr ""
849+
850+#: qml/Wizard/Pages/here-terms.qml:93
851+msgid ""
852+"The information collected is used to analyze the service and to improve the "
853+"use of service, but not to identify you personally."
854+msgstr ""
855+
856+#: qml/Wizard/Pages/here-terms.qml:106
857+#, qt-format
858+msgid "By continuing, you agree to the HERE platform %1 and %2."
859+msgstr ""
860+
861+#: qml/Wizard/Pages/here-terms.qml:107
862+msgid "Service Terms"
863+msgstr ""
730864
731865#: qml/Wizard/Pages/passcode-confirm.qml:43
732−#: qml/Wizard/Pages/passcode-desktop.qml:104
866+#: qml/Wizard/Pages/passcode-desktop.qml:97
733867msgid "Confirm passcode"
734−msgstr "Пацвердзіце код доступу"
868+msgstr "Пацвердзіце код-пароль"
735869
736870#: qml/Wizard/Pages/passcode-confirm.qml:45
737871msgid "Incorrect passcode."
738−msgstr "Няправільны код доступу."
872+msgstr ""
739873
740874#: qml/Wizard/Pages/passcode-confirm.qml:45
741875msgctxt "Enter the passcode again"
742876msgid "Please re-enter."
743−msgstr "Увядзіце нанова."
877+msgstr ""
744878
745879#: qml/Wizard/Pages/passcode-desktop.qml:31
746880msgid "Lock Screen Passcode"
747−msgstr "Код блакавання экрана"
881+msgstr ""
748882
749−#: qml/Wizard/Pages/passcode-desktop.qml:68
883+#: qml/Wizard/Pages/passcode-desktop.qml:61
750884msgid "Enter 4 numbers to setup your passcode"
751−msgstr "Увядзіце код блакавання з чаторых лічбаў"
885+msgstr ""
752886
753−#: qml/Wizard/Pages/passcode-desktop.qml:84
887+#: qml/Wizard/Pages/passcode-desktop.qml:77
754888#: qml/Wizard/Pages/passcode-set.qml:54
755889msgid "Choose passcode"
756−msgstr "Абраць код доступу"
890+msgstr ""
757891
758−#: qml/Wizard/Pages/passcode-desktop.qml:139
892+#: qml/Wizard/Pages/passcode-desktop.qml:127
759893msgid "Passcode too short"
760−msgstr "Код доступу занадта кароткі"
894+msgstr ""
761895
762−#: qml/Wizard/Pages/passcode-desktop.qml:141
896+#: qml/Wizard/Pages/passcode-desktop.qml:129
763897msgid "Passcodes match"
764−msgstr "Коды доступу супадаюць"
898+msgstr ""
765899
766−#: qml/Wizard/Pages/passcode-desktop.qml:143
900+#: qml/Wizard/Pages/passcode-desktop.qml:131
767901msgid "Passcodes do not match"
768−msgstr "Коды доступу не супадаюць"
902+msgstr ""
769903
770904#: qml/Wizard/Pages/passcode-set.qml:62
771905msgid "Passcode must be 4 characters long"
772−msgstr "Код доступу павінен складацца з чатырох лічбаў"
906+msgstr ""
773907
774908#: qml/Wizard/Pages/password-set.qml:31
775909msgid "Lock Screen Password"
776−msgstr "Пароль блакавання экрана"
910+msgstr ""
777911
778−#: qml/Wizard/Pages/password-set.qml:68
912+#: qml/Wizard/Pages/password-set.qml:62
779913msgid "Enter at least 8 characters"
780−msgstr "Увядзіце прынамсі 8 сімвалаў"
914+msgstr ""
781915
782−#: qml/Wizard/Pages/password-set.qml:80
916+#: qml/Wizard/Pages/password-set.qml:74
783917msgid "Choose password"
784−msgstr "Абярыце пароль"
918+msgstr ""
785919
786−#: qml/Wizard/Pages/password-set.qml:110
920+#: qml/Wizard/Pages/password-set.qml:104
787921msgid "Confirm password"
788−msgstr "Пацвердзіце пароль"
922+msgstr ""
789923
790924#: qml/Wizard/Pages/sim.qml:27
791925msgid "No SIM card installed"
792−msgstr "SIM-картка не ўстаўленая"
926+msgstr ""
793927
794928#: qml/Wizard/Pages/sim.qml:54
795929msgid "SIM card added"
796−msgstr "Дададзена SIM-картка"
930+msgstr ""
797931
798932#: qml/Wizard/Pages/sim.qml:55
799933msgid "You must restart the device to access the mobile network."
800−msgstr "Для доступу да мабільнай сеткі неабходна перазапусціць прыладу."
934+msgstr ""
801935
802936#: qml/Wizard/Pages/sim.qml:59
803937msgid "Restart"
@@ -805,123 +939,39 @@ msgstr "Перазапусціць"
805939
806940#: qml/Wizard/Pages/sim.qml:78
807941msgid "You won’t be able to make calls or use text messaging without a SIM."
808−msgstr "Без SIM-карткі немагчыма тэлефанаваць і адпраўляць SMS."
942+msgstr ""
809943
810944#: qml/Wizard/Pages/sim.qml:90
811945msgid "To proceed with no SIM tap Skip."
812−msgstr "Каб працягнуць працу без SIM-карткі, націсніце \"Прамінуць\"."
946+msgstr ""
813947
814948#: qml/Wizard/PasswordMeter.qml:87
815949msgid "Password too short"
816−msgstr "Пароль занадта кароткі"
950+msgstr ""
817951
818952#: qml/Wizard/PasswordMeter.qml:89
819953msgid "Passwords match"
820−msgstr "Паролі супадаюць"
954+msgstr ""
821955
822956#: qml/Wizard/PasswordMeter.qml:91
823957msgid "Passwords do not match"
824−msgstr "Паролі не супадаюць"
958+msgstr ""
825959
826960#: qml/Wizard/PasswordMeter.qml:95
827961msgid "Strong password"
828−msgstr "Надзейны пароль"
962+msgstr ""
829963
830964#: qml/Wizard/PasswordMeter.qml:97
831965msgid "Fair password"
832−msgstr "Неблагі пароль"
966+msgstr ""
833967
834968#: qml/Wizard/PasswordMeter.qml:99
835969msgid "Weak password"
836−msgstr "Слабы пароль"
970+msgstr ""
837971
838972#: qml/Wizard/PasswordMeter.qml:101
839973msgid "Very weak password"
840−msgstr "Вельмы слабы пароль"
841−
842−#~ msgid "Unity 8"
843−#~ msgstr "Unity 8"
844−
845−#~ msgid "Scopes"
846−#~ msgstr "Лінзы"
847−
848−#~ msgid "Super (Tap)"
849−#~ msgstr "Super (націск)"
850−
851−#~ msgid "Opens the Scopes home."
852−#~ msgstr "Адкрывае старонку лінзаў."
853−
854−#~ msgctxt "Button: Open the Ubuntu Store"
855−#~ msgid "Store"
856−#~ msgstr "Крама"
857−
858−#~ msgctxt "Button: Start a search in the current dash scope"
859−#~ msgid "Search"
860−#~ msgstr "Пошук"
861−
862−#~ msgctxt "Button: Show the current dash scope settings"
863−#~ msgid "Settings"
864−#~ msgstr "Налады"
865−
866−#~ msgid "Remove from Favorites"
867−#~ msgstr "Выдаліць з абранага"
868−
869−#~ msgid "Add to Favorites"
870−#~ msgstr "Дадаць да абранага"
871−
872−#~ msgctxt "Label: Hint for dash search line edit"
873−#~ msgid "Search"
874−#~ msgstr "Пошук"
875−
876−#~ msgid "More..."
877−#~ msgstr "Болей…"
878−
879−#~ msgid "Less..."
880−#~ msgstr "Менш..."
881−
882−#~ msgid "Send"
883−#~ msgstr "Адправіць"
884−
885−#~ msgid "Rate this"
886−#~ msgstr "Ацаніць"
887−
888−#~ msgid "Add a review"
889−#~ msgstr "Дадаць рэцэнзію"
890−
891−#~ msgid "Enable location data"
892−#~ msgstr "Уключыць дадзеныя аб месцазнаходжанні"
893−
894−#~ msgid "Manage"
895−#~ msgstr "Кіраванне"
896−
897−#~ msgid "Home"
898−#~ msgstr "Хатняя папка"
899−
900−#~ msgid "Also installed"
901−#~ msgstr "Таксама ўсталявана"
902−
903−#, fuzzy
904−#~ msgid "Please wait..."
905−#~ msgstr "Загрузка. Чакайце..."
906−
907−#, fuzzy
908−#~ msgid "Update all"
909−#~ msgstr "Не дазваляць"
910−
911−#, fuzzy
912−#~ msgid "Download"
913−#~ msgstr "Запампоўка"
914−
915−#, fuzzy
916−#~ msgid "Downloaded"
917−#~ msgstr "Запампоўка"
918−
919−#, fuzzy
920−#~ msgid "Installed"
921−#~ msgstr "Таксама ўсталявана"
922−
923−#~ msgid "Terms & Conditions"
924−#~ msgstr "Умовы карыстання"
974+msgstr ""
925975
926976#~ msgid "Reboot"
927977#~ msgstr "Перазагрузіць"
@@ -938,6 +988,9 @@ msgstr "Вельмы слабы пароль"
938988#~ msgid "Left edge"
939989#~ msgstr "Левы край"
940990
991+#~ msgid "Search"
992+#~ msgstr "Пошук"
993+
941994#~ msgid "Confirm"
942995#~ msgstr "Пацвердзіць"
943996
@@ -950,18 +1003,29 @@ msgstr "Вельмы слабы пароль"
9501003#~ msgid "Try swiping from the right edge to unlock the phone"
9511004#~ msgstr "Правядзіце пальцам з правага краю, каб разблакаваць тэлефон"
9521005
1006+#~ msgid "Loading. Please Wait..."
1007+#~ msgstr "Загрузка. Чакайце..."
1008+
1009+#~ msgid "Speaking..."
1010+#~ msgstr "Кажа..."
1011+
9531012#~ msgid "Speak Now..."
9541013#~ msgstr "Кажыце..."
9551014
9561015#~ msgid "Type or say a command"
9571016#~ msgstr "Напішыце або вымавіце каманду"
9581017
1018+#, qt-format
9591019#~ msgid "Enter %1"
9601020#~ msgstr "Увядзіце %1"
9611021
1022+#, qt-format
9621023#~ msgid "Sorry, incorrect %1"
9631024#~ msgstr "Даруйце, некарэктны %1"
9641025
1026+#~ msgid "Enter passcode"
1027+#~ msgstr "Увядзіце код"
1028+
9651029#~ msgid "This will be your last attempt."
9661030#~ msgstr "Апошняя спроба."
9671031
@@ -985,8 +1049,8 @@ msgstr "Вельмы слабы пароль"
9851049
9861050#~ msgid "Swipe from the left to reveal the launcher for quick access to apps"
9871051#~ msgstr ""
988−#~ "Правядзіце пальцам ад левага краю, каб адкрыць панэль запуску для "
989−#~ "паскарэння доступу да праграм"
1052+#~ "Правядзіце пальцам ад левага краю, каб адкрыць панэль запуску для паскарэння "
1053+#~ "доступу да праграм"
9901054
9911055#~ msgid "Skip intro"
9921056#~ msgstr "Прапусціць уводзіны"
@@ -1012,6 +1076,9 @@ msgstr "Вельмы слабы пароль"
10121076#~ msgid "Let’s get started."
10131077#~ msgstr "Пачнем."
10141078
1079+#~ msgid "Continue"
1080+#~ msgstr "Працягнуць"
1081+
10151082#~ msgid "Please select how you’d like to unlock your phone."
10161083#~ msgstr "Калі ласка, абярыце спосаб разблакавання тэлефона."
10171084
@@ -1032,8 +1099,7 @@ msgstr "Вельмы слабы пароль"
10321099
10331100#~ msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
10341101#~ msgstr ""
1035−#~ "На аснове GPS, ананімізаванага Wi-Fi і дадзеных сотавай сеткі "
1036−#~ "(рэкамендуецца)"
1102+#~ "На аснове GPS, ананімізаванага Wi-Fi і дадзеных сотавай сеткі (рэкамендуецца)"
10371103
10381104#~ msgid "Improving your experience"
10391105#~ msgstr "Спрашчэнне вашай працы"
@@ -1058,18 +1124,23 @@ msgstr "Вельмы слабы пароль"
10581124#~ msgstr "Цяпер Вашым тэлефонам можна карыстацца."
10591125
10601126#~ msgid ""
1061−#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms "
1062−#~ "and conditions</a>."
1127+#~ "By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
1128+#~ "conditions</a>."
10631129#~ msgstr ""
10641130#~ "Выбарам гэтага варыянту дзеянняў вы згаджаецеся з <a href='#'> умовамі "
10651131#~ "прадстаўлення паслуг Nokia HERE</a>."
10661132
1133+#~ msgid "Not at all"
1134+#~ msgstr "Не дазваляць"
1135+
1136+#, qt-format
10671137#~ msgid "〈 %1"
10681138#~ msgstr "〈 %1"
10691139
10701140#~ msgid "Confirm passphrase"
10711141#~ msgstr "Пацвердзіце пароль"
10721142
1143+#, qt-format
10731144#~ msgid "%1 〉"
10741145#~ msgstr "%1 〉"
10751146
@@ -1079,6 +1150,10 @@ msgstr "Вельмы слабы пароль"
10791150#~ msgid "Close"
10801151#~ msgstr "Закрыць"
10811152
1153+#~ msgid "Try swiping from the top edge to access the indicators"
1154+#~ msgstr ""
1155+#~ "Паспрабуйце правесці пальцам ад верхняга краю для доступу да індыкатараў"
1156+
10821157#~ msgid "Settings"
10831158#~ msgstr "Наладкі"
10841159
@@ -1089,6 +1164,9 @@ msgstr "Вельмы слабы пароль"
10891164#~ "Вы толькі што асвоілі асноўная жэсты і можаце пачаць выкарыстоўваць "
10901165#~ "тэлефон<br><br>Дакраніцеся да экрана, каб пачаць"
10911166
1167+#~ msgid "Enter passphrase"
1168+#~ msgstr "Увядзіце пароль"
1169+
10921170#~ msgid "Sorry, incorrect passcode."
10931171#~ msgstr "Даруйце, няслушны код."
10941172
@@ -1156,6 +1234,9 @@ msgstr "Вельмы слабы пароль"
11561234#~ msgid "Try again."
11571235#~ msgstr "Паспрабуйце яшчэ."
11581236
1237+#~ msgid "Open the launcher"
1238+#~ msgstr "Адкрыць панэль запуску"
1239+
11591240#~ msgid "Tap here to continue."
11601241#~ msgstr "Націсніце тут, каб працягнуць."
11611242
@@ -1239,15 +1320,15 @@ msgstr "Вельмы слабы пароль"
12391320#~ msgstr "Даруйце, некарэктны код"
12401321
12411322#~ msgid ""
1242−#~ "If passcode is entered incorrectly, your phone will conduct a factory "
1243−#~ "reset and all personal data will be deleted."
1323+#~ "If passcode is entered incorrectly, your phone will conduct a factory reset "
1324+#~ "and all personal data will be deleted."
12441325#~ msgstr ""
1245−#~ "Калі ўведзены код неправільны, Ваш тэлефон зробіць агульны скід налад і "
1246−#~ "ўсе асабістыя дадзеныя будуць выдалены."
1326+#~ "Калі ўведзены код неправільны, Ваш тэлефон зробіць агульны скід налад і ўсе "
1327+#~ "асабістыя дадзеныя будуць выдалены."
12471328
12481329#~ msgid ""
12491330#~ "If passphrase is entered incorrectly, your phone will conduct a factory "
12501331#~ "reset and all personal data will be deleted."
12511332#~ msgstr ""
1252−#~ "Калі ўведзены пароль неправільны, Ваш тэлефон зробіць агульны скід налад "
1253−#~ "і ўсе асабістыя дадзеныя будуць выдалены."
1333+#~ "Калі ўведзены пароль неправільны, Ваш тэлефон зробіць агульны скід налад і "
1334+#~ "ўсе асабістыя дадзеныя будуць выдалены."
po/bg.po+307−168
@@ -6,61 +6,60 @@
66msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
9−"Report-Msgid-Bugs-To: \n"
10−"POT-Creation-Date: 2021-01-29 11:42-0600\n"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2017-03-21 10:58+0000\n"
1111"PO-Revision-Date: 2015-04-12 14:43+0000\n"
1212"Last-Translator: George Karavasilev <kokoto-java@ubuntu.com>\n"
1313"Language-Team: Bulgarian <bg@li.org>\n"
14−"Language: bg\n"
1514"MIME-Version: 1.0\n"
1615"Content-Type: text/plain; charset=UTF-8\n"
1716"Content-Transfer-Encoding: 8bit\n"
1817"Plural-Forms: nplurals=2; plural=n != 1;\n"
19−"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
20−"X-Generator: Launchpad (build 18269)\n"
18+"X-Launchpad-Export-Date: 2017-03-24 06:13+0000\n"
19+"X-Generator: Launchpad (build 18334)\n"
2120
22−#: plugins/LightDM/Greeter.cpp:199
21+#: plugins/LightDM/Greeter.cpp:188
2322msgid "Password: "
2423msgstr ""
2524
26−#: plugins/LightDM/Greeter.cpp:214
25+#: plugins/LightDM/Greeter.cpp:203
2726msgid "Username"
2827msgstr ""
2928
30−#: plugins/LightDM/Greeter.cpp:258
29+#: plugins/LightDM/Greeter.cpp:242
3130msgid "Failed to authenticate"
3231msgstr ""
3332
34−#: plugins/LightDM/Greeter.cpp:260
33+#: plugins/LightDM/Greeter.cpp:244
3534msgid "Invalid password, please try again"
3635msgstr ""
3736
38−#: plugins/LightDM/Greeter.cpp:270
37+#: plugins/LightDM/Greeter.cpp:254
3938msgid "Log In"
4039msgstr ""
4140
42−#: plugins/LightDM/Greeter.cpp:270
41+#: plugins/LightDM/Greeter.cpp:254
4342msgid "Retry"
4443msgstr ""
4544
46−#: plugins/LightDM/UsersModel.cpp:157
45+#: plugins/LightDM/UsersModel.cpp:152
4746msgid "Login"
4847msgstr ""
4948
50−#: plugins/LightDM/UsersModel.cpp:165
49+#: plugins/LightDM/UsersModel.cpp:160
5150msgid "Guest Session"
5251msgstr ""
5352
54−#: plugins/Unity/Launcher/launcheritem.cpp:48
55−#: plugins/Unity/Launcher/launcheritem.cpp:122
53+#: plugins/Unity/Launcher/launcheritem.cpp:49
54+#: plugins/Unity/Launcher/launcheritem.cpp:123
5655msgid "Pin shortcut"
5756msgstr ""
5857
59−#: plugins/Unity/Launcher/launcheritem.cpp:54
58+#: plugins/Unity/Launcher/launcheritem.cpp:55
6059msgid "Quit"
6160msgstr ""
6261
63−#: plugins/Unity/Launcher/launcheritem.cpp:122
62+#: plugins/Unity/Launcher/launcheritem.cpp:123
6463msgid "Unpin shortcut"
6564msgstr ""
6665
@@ -83,8 +82,9 @@ msgctxt "Button: Log out from the system"
8382msgid "Log Out"
8483msgstr ""
8584
86−#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:284
87−#: qml/Greeter/NarrowView.qml:215 qml/Wizard/Pages/passcode-confirm.qml:32
85+#: qml/Components/Dialogs.qml:199 qml/Components/Dialogs.qml:264
86+#: qml/Dash/DashPageHeader.qml:324 qml/Greeter/NarrowView.qml:222
87+#: qml/Wizard/Pages/passcode-confirm.qml:32
8888#: qml/Wizard/Pages/passcode-set.qml:32
8989msgid "Cancel"
9090msgstr ""
@@ -106,12 +106,12 @@ msgstr ""
106106msgid "Yes"
107107msgstr ""
108108
109−#: qml/Components/Dialogs.qml:243
109+#: qml/Components/Dialogs.qml:239
110110msgctxt "Title: Power off/Restart dialog"
111111msgid "Power"
112112msgstr ""
113113
114−#: qml/Components/Dialogs.qml:244
114+#: qml/Components/Dialogs.qml:240
115115msgid ""
116116"Are you sure you would like\n"
117117"to power off?"
@@ -119,26 +119,22 @@ msgstr ""
119119"Искате ли да \n"
120120"изключите захранването на устройството?"
121121
122−#: qml/Components/Dialogs.qml:248
122+#: qml/Components/Dialogs.qml:244
123123msgctxt "Button: Power off the system"
124124msgid "Power off"
125125msgstr ""
126126
127−#: qml/Components/Dialogs.qml:263
127+#: qml/Components/Dialogs.qml:255
128128msgctxt "Button: Restart the system"
129129msgid "Restart"
130130msgstr ""
131131
132−#: qml/Components/Dialogs.qml:276
133−msgid "Screenshot"
134−msgstr ""
135−
136132#: qml/Components/KeyboardShortcutsOverlay.qml:41
137133msgid "Keyboard Shortcuts"
138134msgstr ""
139135
140136#: qml/Components/KeyboardShortcutsOverlay.qml:55
141−msgid "Lomiri"
137+msgid "Unity 8"
142138msgstr ""
143139
144140#: qml/Components/KeyboardShortcutsOverlay.qml:62
@@ -173,131 +169,135 @@ msgstr ""
173169msgid "Switches to previous keyboard layout."
174170msgstr ""
175171
176−#: qml/Components/KeyboardShortcutsOverlay.qml:114
177−msgid "Ctrl + Alt + T"
172+#: qml/Components/KeyboardShortcutsOverlay.qml:118
173+msgid "Launcher"
178174msgstr ""
179175
180−#: qml/Components/KeyboardShortcutsOverlay.qml:119
181−msgid "Starts the Terminal application."
176+#: qml/Components/KeyboardShortcutsOverlay.qml:125
177+msgid "Super (Hold)"
182178msgstr ""
183179
184−#: qml/Components/KeyboardShortcutsOverlay.qml:131
185−msgid "Launcher"
180+#: qml/Components/KeyboardShortcutsOverlay.qml:130
181+msgid "Opens the launcher, displays shortcuts."
186182msgstr ""
187183
188184#: qml/Components/KeyboardShortcutsOverlay.qml:138
189−msgid "Super (Hold)"
185+msgid "Alt + F1"
190186msgstr ""
191187
192188#: qml/Components/KeyboardShortcutsOverlay.qml:143
193−msgid "Opens the launcher, displays shortcuts."
189+msgid "Opens launcher keyboard navigation mode."
194190msgstr ""
195191
196192#: qml/Components/KeyboardShortcutsOverlay.qml:151
197−msgid "Alt + F1"
193+msgid "Super + Tab"
198194msgstr ""
199195
200196#: qml/Components/KeyboardShortcutsOverlay.qml:156
201−msgid "Opens launcher keyboard navigation mode."
197+msgid "Switches applications via the launcher."
202198msgstr ""
203199
204200#: qml/Components/KeyboardShortcutsOverlay.qml:164
205−msgid "Super + Tab"
201+msgid "Super + 1 to 0"
206202msgstr ""
207203
208204#: qml/Components/KeyboardShortcutsOverlay.qml:169
209−msgid "Switches applications via the launcher."
205+msgid "Same as clicking on a launcher icon."
210206msgstr ""
211207
212208#: qml/Components/KeyboardShortcutsOverlay.qml:177
213−msgid "Super + 1 to 0"
209+msgid "Super + A"
214210msgstr ""
215211
216212#: qml/Components/KeyboardShortcutsOverlay.qml:182
217−msgid "Same as clicking on a launcher icon."
213+msgid "Opens the Application Drawer."
218214msgstr ""
219215
220−#: qml/Components/KeyboardShortcutsOverlay.qml:190
221−msgid "Super + A"
216+#: qml/Components/KeyboardShortcutsOverlay.qml:194
217+msgid "Scopes"
222218msgstr ""
223219
224−#: qml/Components/KeyboardShortcutsOverlay.qml:195
225−msgid "Opens the Application Drawer."
220+#: qml/Components/KeyboardShortcutsOverlay.qml:201
221+msgid "Super (Tap)"
226222msgstr ""
227223
228−#: qml/Components/KeyboardShortcutsOverlay.qml:235
224+#: qml/Components/KeyboardShortcutsOverlay.qml:206
225+msgid "Opens the Scopes home."
226+msgstr ""
227+
228+#: qml/Components/KeyboardShortcutsOverlay.qml:222
229229msgid "Switching"
230230msgstr ""
231231
232−#: qml/Components/KeyboardShortcutsOverlay.qml:242
232+#: qml/Components/KeyboardShortcutsOverlay.qml:229
233233msgid "Alt + Tab"
234234msgstr ""
235235
236−#: qml/Components/KeyboardShortcutsOverlay.qml:247
236+#: qml/Components/KeyboardShortcutsOverlay.qml:234
237237msgid "Switches between applications."
238238msgstr ""
239239
240−#: qml/Components/KeyboardShortcutsOverlay.qml:255
240+#: qml/Components/KeyboardShortcutsOverlay.qml:242
241241msgid "Super + W"
242242msgstr ""
243243
244−#: qml/Components/KeyboardShortcutsOverlay.qml:260
244+#: qml/Components/KeyboardShortcutsOverlay.qml:247
245245msgid "Opens the desktop spread."
246246msgstr ""
247247
248−#: qml/Components/KeyboardShortcutsOverlay.qml:268
248+#: qml/Components/KeyboardShortcutsOverlay.qml:255
249249msgid "Cursor Left or Right"
250250msgstr ""
251251
252−#: qml/Components/KeyboardShortcutsOverlay.qml:273
252+#: qml/Components/KeyboardShortcutsOverlay.qml:260
253253msgid "Moves the focus."
254254msgstr ""
255255
256−#: qml/Components/KeyboardShortcutsOverlay.qml:285
256+#: qml/Components/KeyboardShortcutsOverlay.qml:272
257257msgid "Windows"
258258msgstr ""
259259
260−#: qml/Components/KeyboardShortcutsOverlay.qml:292
260+#: qml/Components/KeyboardShortcutsOverlay.qml:279
261261msgid "Ctrl + Super + D"
262262msgstr ""
263263
264−#: qml/Components/KeyboardShortcutsOverlay.qml:297
264+#: qml/Components/KeyboardShortcutsOverlay.qml:284
265265msgid "Minimizes all windows."
266266msgstr ""
267267
268−#: qml/Components/KeyboardShortcutsOverlay.qml:305
268+#: qml/Components/KeyboardShortcutsOverlay.qml:292
269269msgid "Ctrl + Super + Up"
270270msgstr ""
271271
272−#: qml/Components/KeyboardShortcutsOverlay.qml:310
272+#: qml/Components/KeyboardShortcutsOverlay.qml:297
273273msgid "Maximizes the current window."
274274msgstr ""
275275
276−#: qml/Components/KeyboardShortcutsOverlay.qml:318
276+#: qml/Components/KeyboardShortcutsOverlay.qml:305
277277msgid "Ctrl + Super + Down"
278278msgstr ""
279279
280−#: qml/Components/KeyboardShortcutsOverlay.qml:323
280+#: qml/Components/KeyboardShortcutsOverlay.qml:310
281281msgid "Minimizes or restores the current window."
282282msgstr ""
283283
284−#: qml/Components/KeyboardShortcutsOverlay.qml:331
284+#: qml/Components/KeyboardShortcutsOverlay.qml:318
285285msgid "Ctrl + Super + Left or Right"
286286msgstr ""
287287
288−#: qml/Components/KeyboardShortcutsOverlay.qml:336
288+#: qml/Components/KeyboardShortcutsOverlay.qml:323
289289msgid "Semi-maximizes the current window."
290290msgstr ""
291291
292−#: qml/Components/KeyboardShortcutsOverlay.qml:344
292+#: qml/Components/KeyboardShortcutsOverlay.qml:331
293293msgid "Alt + F4"
294294msgstr ""
295295
296−#: qml/Components/KeyboardShortcutsOverlay.qml:349
296+#: qml/Components/KeyboardShortcutsOverlay.qml:336
297297msgid "Closes the current window."
298298msgstr ""
299299
300−#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:235
300+#: qml/Components/Lockscreen.qml:212 qml/Greeter/NarrowView.qml:242
301301msgid "Return to Call"
302302msgstr ""
303303
@@ -371,6 +371,103 @@ msgstr ""
371371msgid "Find more settings in the system settings."
372372msgstr ""
373373
374+#: qml/Dash/DashPageHeader.qml:361
375+msgctxt "Button: Open the Ubuntu Store"
376+msgid "Store"
377+msgstr ""
378+
379+#: qml/Dash/DashPageHeader.qml:368
380+msgctxt "Button: Start a search in the current dash scope"
381+msgid "Search"
382+msgstr ""
383+
384+#: qml/Dash/DashPageHeader.qml:378
385+msgctxt "Button: Show the current dash scope settings"
386+msgid "Settings"
387+msgstr ""
388+
389+#: qml/Dash/DashPageHeader.qml:385
390+msgid "Remove from Favorites"
391+msgstr ""
392+
393+#: qml/Dash/DashPageHeader.qml:385
394+msgid "Add to Favorites"
395+msgstr ""
396+
397+#: qml/Dash/FiltersPopover.qml:61
398+msgid "Refine your results"
399+msgstr ""
400+
401+#: qml/Dash/FiltersPopover.qml:70
402+msgid "Reset"
403+msgstr ""
404+
405+#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
406+msgid "Show less"
407+msgstr ""
408+
409+#: qml/Dash/GenericScopeView.qml:547
410+msgid "Show all"
411+msgstr ""
412+
413+#: qml/Dash/GenericScopeView.qml:578
414+msgctxt "Label: Hint for dash search line edit"
415+msgid "Search"
416+msgstr ""
417+
418+#: qml/Dash/PageHeaderExtraPanel.qml:67
419+msgid "Recent Searches"
420+msgstr ""
421+
422+#: qml/Dash/PageHeaderExtraPanel.qml:78
423+msgid "Clear All"
424+msgstr ""
425+
426+#: qml/Dash/Previews/PreviewActionCombo.qml:36
427+msgid "More..."
428+msgstr ""
429+
430+#: qml/Dash/Previews/PreviewActionCombo.qml:36
431+msgid "Less..."
432+msgstr "По-малко..."
433+
434+#: qml/Dash/Previews/PreviewCommentInput.qml:83
435+#: qml/Dash/Previews/PreviewRatingInput.qml:202
436+msgid "Send"
437+msgstr "Изпрати"
438+
439+#: qml/Dash/Previews/PreviewRatingInput.qml:109
440+msgid "Rate this"
441+msgstr "Оценете това"
442+
443+#: qml/Dash/Previews/PreviewRatingInput.qml:184
444+msgid "Add a review"
445+msgstr "Добави отзив"
446+
447+#: qml/Dash/PullToRefreshScopeStyle.qml:56
448+msgid "Pull to refresh…"
449+msgstr ""
450+
451+#: qml/Dash/PullToRefreshScopeStyle.qml:61
452+msgid "Release to refresh…"
453+msgstr ""
454+
455+#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
456+msgid "Enable location data"
457+msgstr ""
458+
459+#: qml/Dash/ScopesList.qml:146
460+msgid "Manage"
461+msgstr ""
462+
463+#: qml/Dash/ScopesList.qml:187
464+msgid "Home"
465+msgstr ""
466+
467+#: qml/Dash/ScopesList.qml:188
468+msgid "Also installed"
469+msgstr ""
470+
374471#: qml/Greeter/CoverPage.qml:127
375472msgid "Unlock"
376473msgstr ""
@@ -394,19 +491,19 @@ msgid_plural "Please wait %1 minutes and then try again…"
394491msgstr[0] ""
395492msgstr[1] ""
396493
397−#: qml/Greeter/Greeter.qml:550
494+#: qml/Greeter/Greeter.qml:561
398495msgid "Try again"
399496msgstr ""
400497
401−#: qml/Greeter/Greeter.qml:551
498+#: qml/Greeter/Greeter.qml:562
402499msgid "Enter passphrase to unlock"
403500msgstr ""
404501
405−#: qml/Greeter/Greeter.qml:552
502+#: qml/Greeter/Greeter.qml:563
406503msgid "Enter passcode to unlock"
407504msgstr ""
408505
409−#: qml/Greeter/NarrowView.qml:235
506+#: qml/Greeter/NarrowView.qml:242
410507msgid "Emergency"
411508msgstr ""
412509
@@ -418,22 +515,21 @@ msgstr ""
418515msgid "Passcode"
419516msgstr ""
420517
421−#: qml/Greeter/SessionsList.qml:124
518+#: qml/Greeter/SessionsList.qml:122
422519msgid "Select desktop environment"
423520msgstr ""
424521
425−#: qml/Launcher/Drawer.qml:250
426−#, fuzzy
427−#| msgid "Search"
522+#: qml/Launcher/Drawer.qml:93
428523msgid "Search…"
429−msgstr "Търсене"
524+msgstr ""
430525
431−#: qml/Launcher/PullToRefreshScopeStyle.qml:56
432−msgid "Pull to refresh…"
526+#: qml/Launcher/Drawer.qml:128
527+msgctxt "Apps sorted alphabetically"
528+msgid "A-Z"
433529msgstr ""
434530
435−#: qml/Launcher/PullToRefreshScopeStyle.qml:61
436−msgid "Release to refresh…"
531+#: qml/Launcher/MoreAppsHeader.qml:55
532+msgid "More apps in the store"
437533msgstr ""
438534
439535#: qml/Notifications/NotificationMenuItemFactory.qml:124
@@ -531,27 +627,19 @@ msgstr ""
531627msgid "Drag using 3 fingers any application from one window to the other"
532628msgstr ""
533629
534−#: qml/Stage/Stage.qml:671
535−msgid "No running apps"
536−msgstr ""
537−
538630#: qml/Tutorial/TutorialLeftLong.qml:49
539−#, fuzzy
540−#| msgid "Try swiping from the top edge to access the indicators"
541631msgid "Long swipe from the left edge to open the Application Drawer"
542632msgstr ""
543−"Опитайте се да приплъзнете пръста си от горния край към долния, за да "
544−"получите достъп до индикаторите"
545633
546634#: qml/Tutorial/TutorialLeft.qml:47
547635msgid "Short swipe from the left edge to open the launcher"
548636msgstr ""
549637
550−#: qml/Tutorial/TutorialRight.qml:54
638+#: qml/Tutorial/TutorialRight.qml:55
551639msgid "Push your mouse against the right edge to view your open apps"
552640msgstr ""
553641
554−#: qml/Tutorial/TutorialRight.qml:55
642+#: qml/Tutorial/TutorialRight.qml:56
555643msgid "Swipe from the right edge to view your open apps"
556644msgstr ""
557645
@@ -559,42 +647,25 @@ msgstr ""
559647msgid "Swipe from the top edge to access notifications and quick settings"
560648msgstr ""
561649
562−#: qml/Wizard/Page.qml:59
650+#: qml/Wizard/Page.qml:54
563651msgctxt "Button: Go back one page in the Wizard"
564652msgid "Back"
565653msgstr ""
566654
567−#: qml/Wizard/Pages/10-welcome.qml:29
655+#: qml/Wizard/Pages/10-welcome.qml:28
568656msgid "Language"
569657msgstr ""
570658
571−#: qml/Wizard/Pages/10-welcome.qml:176
572−#: qml/Wizard/Pages/10-welcome-update.qml:126
573−#: qml/Wizard/Pages/11-changelog.qml:74 qml/Wizard/Pages/20-keyboard.qml:152
574−#: qml/Wizard/Pages/30-wifi.qml:214 qml/Wizard/Pages/50-timezone.qml:272
575−#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/70-passwd-type.qml:146
576−#: qml/Wizard/Pages/passcode-desktop.qml:154
577−#: qml/Wizard/Pages/password-set.qml:153
659+#: qml/Wizard/Pages/10-welcome.qml:173 qml/Wizard/Pages/20-keyboard.qml:152
660+#: qml/Wizard/Pages/30-wifi.qml:207 qml/Wizard/Pages/40-location.qml:271
661+#: qml/Wizard/Pages/50-timezone.qml:271 qml/Wizard/Pages/60-account.qml:65
662+#: qml/Wizard/Pages/70-passwd-type.qml:145
663+#: qml/Wizard/Pages/75-report-check.qml:84
664+#: qml/Wizard/Pages/passcode-desktop.qml:142
665+#: qml/Wizard/Pages/password-set.qml:142
578666msgid "Next"
579667msgstr ""
580668
581−#: qml/Wizard/Pages/10-welcome-update.qml:91
582−msgid "Welcome to "
583−msgstr ""
584−
585−#: qml/Wizard/Pages/10-welcome-update.qml:106
586−msgid "We will make sure your device is ready to use "
587−msgstr ""
588−
589−#: qml/Wizard/Pages/11-changelog.qml:28
590−msgid "What's new"
591−msgstr ""
592−
593−#: qml/Wizard/Pages/11-changelog.qml:74
594−#, fuzzy
595−msgid "Loading..."
596−msgstr "Говорете..."
597−
598669#: qml/Wizard/Pages/20-keyboard.qml:31
599670msgid "Select Keyboard"
600671msgstr ""
@@ -607,8 +678,8 @@ msgstr ""
607678msgid "Keyboard layout"
608679msgstr ""
609680
610−#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:214
611−#: qml/Wizard/Pages/60-account.qml:72 qml/Wizard/Pages/79-system-update.qml:144
681+#: qml/Wizard/Pages/20-keyboard.qml:152 qml/Wizard/Pages/30-wifi.qml:207
682+#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/77-system-update.qml:152
612683#: qml/Wizard/Pages/sim.qml:101
613684msgid "Skip"
614685msgstr ""
@@ -617,23 +688,55 @@ msgstr ""
617688msgid "Connect to Wi‑Fi"
618689msgstr ""
619690
620−#: qml/Wizard/Pages/30-wifi.qml:139
691+#: qml/Wizard/Pages/30-wifi.qml:132
621692msgid "Connected"
622693msgstr ""
623694
624−#: qml/Wizard/Pages/30-wifi.qml:172
695+#: qml/Wizard/Pages/30-wifi.qml:165
625696msgid "Available Wi-Fi networks"
626697msgstr ""
627698
628−#: qml/Wizard/Pages/30-wifi.qml:173
699+#: qml/Wizard/Pages/30-wifi.qml:166
629700msgid "No available Wi-Fi networks"
630701msgstr ""
631702
703+#: qml/Wizard/Pages/40-location.qml:27
704+msgid "Location Services"
705+msgstr ""
706+
707+#: qml/Wizard/Pages/40-location.qml:83
708+msgid ""
709+"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
710+"(recommended)"
711+msgstr ""
712+
713+#: qml/Wizard/Pages/40-location.qml:105
714+#, qt-format
715+msgid "By selecting this option you agree to the Nokia HERE %1."
716+msgstr ""
717+
718+#: qml/Wizard/Pages/40-location.qml:106
719+msgctxt "part of: Nokia HERE terms and conditions"
720+msgid "terms and conditions"
721+msgstr ""
722+
723+#: qml/Wizard/Pages/40-location.qml:160
724+msgid "GPS only"
725+msgstr ""
726+
727+#: qml/Wizard/Pages/40-location.qml:214
728+msgid "Don't use my location"
729+msgstr ""
730+
731+#: qml/Wizard/Pages/40-location.qml:260
732+msgid "You can change it later in System Settings."
733+msgstr ""
734+
632735#: qml/Wizard/Pages/50-timezone.qml:30
633736msgid "Time Zone"
634737msgstr ""
635738
636−#: qml/Wizard/Pages/50-timezone.qml:183
739+#: qml/Wizard/Pages/50-timezone.qml:182
637740msgid "Enter your city"
638741msgstr ""
639742
@@ -641,7 +744,7 @@ msgstr ""
641744msgid "Personalize Your Device"
642745msgstr ""
643746
644−#: qml/Wizard/Pages/60-account.qml:54
747+#: qml/Wizard/Pages/60-account.qml:48
645748msgid "Preferred Name"
646749msgstr ""
647750
@@ -649,72 +752,110 @@ msgstr ""
649752msgid "Lock Screen"
650753msgstr ""
651754
652−#: qml/Wizard/Pages/70-passwd-type.qml:103
755+#: qml/Wizard/Pages/70-passwd-type.qml:102
653756msgctxt "Label: Type of security method"
654757msgid "Create new password"
655758msgstr ""
656759
657−#: qml/Wizard/Pages/70-passwd-type.qml:105
760+#: qml/Wizard/Pages/70-passwd-type.qml:104
658761msgctxt "Label: Type of security method"
659762msgid "Create passcode (numbers only)"
660763msgstr ""
661764
662−#: qml/Wizard/Pages/70-passwd-type.qml:107
765+#: qml/Wizard/Pages/70-passwd-type.qml:106
663766msgctxt "Label: Type of security method"
664767msgid "No lock code"
665768msgstr ""
666769
667−#: qml/Wizard/Pages/79-system-update.qml:28
770+#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
771+msgid "Privacy Policy"
772+msgstr ""
773+
774+#: qml/Wizard/Pages/75-report-check.qml:26
775+msgid "Help Us Improve"
776+msgstr ""
777+
778+#: qml/Wizard/Pages/75-report-check.qml:59
779+msgid "Improve system performance by sending us crashes and error reports."
780+msgstr ""
781+
782+#: qml/Wizard/Pages/75-report-check.qml:60
783+msgid "Privacy policy"
784+msgstr ""
785+
786+#: qml/Wizard/Pages/77-system-update.qml:28
668787msgid "Update Device"
669788msgstr ""
670789
671−#: qml/Wizard/Pages/79-system-update.qml:55
790+#: qml/Wizard/Pages/77-system-update.qml:55
672791msgid ""
673792"There is a system update available and ready to install. Afterwards, the "
674793"device will automatically restart."
675794msgstr ""
676795
677−#: qml/Wizard/Pages/79-system-update.qml:76
796+#: qml/Wizard/Pages/77-system-update.qml:76
678797msgctxt "string identifying name of the update"
679−msgid "Ubuntu Touch system"
798+msgid "Ubuntu system"
680799msgstr ""
681800
682−#: qml/Wizard/Pages/79-system-update.qml:83
801+#: qml/Wizard/Pages/77-system-update.qml:83
683802#, qt-format
684803msgctxt "version of the system update"
685804msgid "Version %1"
686805msgstr ""
687806
688−#: qml/Wizard/Pages/79-system-update.qml:95
807+#: qml/Wizard/Pages/77-system-update.qml:102
689808msgid "This could take a few minutes..."
690809msgstr ""
691810
692−#: qml/Wizard/Pages/79-system-update.qml:109
811+#: qml/Wizard/Pages/77-system-update.qml:116
693812msgid "Install and restart now"
694813msgstr ""
695814
696−#: qml/Wizard/Pages/80-finished.qml:91
697−msgid "Welcome Back"
698−msgstr ""
699−
700−#: qml/Wizard/Pages/80-finished.qml:91
815+#: qml/Wizard/Pages/80-finished.qml:89
701816msgid "Welcome to Ubuntu"
702817msgstr ""
703818
704−#: qml/Wizard/Pages/80-finished.qml:106
819+#: qml/Wizard/Pages/80-finished.qml:104
705820msgid "You are ready to use your device now"
706821msgstr ""
707822
708−#: qml/Wizard/Pages/80-finished.qml:126
709−msgid "Continue"
823+#: qml/Wizard/Pages/80-finished.qml:124
824+msgid "Get Started"
710825msgstr ""
711826
712−#: qml/Wizard/Pages/80-finished.qml:126
713−msgid "Get Started"
827+#: qml/Wizard/Pages/here-terms.qml:25
828+msgid "Terms & Conditions"
829+msgstr ""
830+
831+#: qml/Wizard/Pages/here-terms.qml:69
832+msgid "Your device uses positioning technologies provided by HERE."
833+msgstr ""
834+
835+#: qml/Wizard/Pages/here-terms.qml:81
836+msgid ""
837+"To provide you with positioning services and to improve their quality, HERE "
838+"collects information about nearby cell towers and Wi-Fi hotspots around your "
839+"current location whenever your position is being found."
840+msgstr ""
841+
842+#: qml/Wizard/Pages/here-terms.qml:93
843+msgid ""
844+"The information collected is used to analyze the service and to improve the "
845+"use of service, but not to identify you personally."
846+msgstr ""
847+
848+#: qml/Wizard/Pages/here-terms.qml:106
849+#, qt-format
850+msgid "By continuing, you agree to the HERE platform %1 and %2."
851+msgstr ""
852+
853+#: qml/Wizard/Pages/here-terms.qml:107
854+msgid "Service Terms"
714855msgstr ""
715856
716857#: qml/Wizard/Pages/passcode-confirm.qml:43
717−#: qml/Wizard/Pages/passcode-desktop.qml:104
858+#: qml/Wizard/Pages/passcode-desktop.qml:97
718859msgid "Confirm passcode"
719860msgstr ""
720861
@@ -731,24 +872,24 @@ msgstr ""
731872msgid "Lock Screen Passcode"
732873msgstr ""
733874
734−#: qml/Wizard/Pages/passcode-desktop.qml:68
875+#: qml/Wizard/Pages/passcode-desktop.qml:61
735876msgid "Enter 4 numbers to setup your passcode"
736877msgstr ""
737878
738−#: qml/Wizard/Pages/passcode-desktop.qml:84
879+#: qml/Wizard/Pages/passcode-desktop.qml:77
739880#: qml/Wizard/Pages/passcode-set.qml:54
740881msgid "Choose passcode"
741882msgstr ""
742883
743−#: qml/Wizard/Pages/passcode-desktop.qml:139
884+#: qml/Wizard/Pages/passcode-desktop.qml:127
744885msgid "Passcode too short"
745886msgstr ""
746887
747−#: qml/Wizard/Pages/passcode-desktop.qml:141
888+#: qml/Wizard/Pages/passcode-desktop.qml:129
748889msgid "Passcodes match"
749890msgstr ""
750891
751−#: qml/Wizard/Pages/passcode-desktop.qml:143
892+#: qml/Wizard/Pages/passcode-desktop.qml:131
752893msgid "Passcodes do not match"
753894msgstr ""
754895
@@ -760,15 +901,15 @@ msgstr ""
760901msgid "Lock Screen Password"
761902msgstr ""
762903
763−#: qml/Wizard/Pages/password-set.qml:68
904+#: qml/Wizard/Pages/password-set.qml:62
764905msgid "Enter at least 8 characters"
765906msgstr ""
766907
767−#: qml/Wizard/Pages/password-set.qml:80
908+#: qml/Wizard/Pages/password-set.qml:74
768909msgid "Choose password"
769910msgstr ""
770911
771−#: qml/Wizard/Pages/password-set.qml:110
912+#: qml/Wizard/Pages/password-set.qml:104
772913msgid "Confirm password"
773914msgstr ""
774915
@@ -824,25 +965,12 @@ msgstr ""
824965msgid "Very weak password"
825966msgstr ""
826967
827−#~ msgid "Less..."
828−#~ msgstr "По-малко..."
829−
830−#~ msgid "Send"
831−#~ msgstr "Изпрати"
832−
833−#~ msgid "Rate this"
834−#~ msgstr "Оценете това"
835−
836−#~ msgid "Add a review"
837−#~ msgstr "Добави отзив"
838−
839−#, fuzzy
840−#~ msgid "Please wait..."
841−#~ msgstr "Зарежда се. Моля, почакайте..."
842−
843968#~ msgid "Confirm"
844969#~ msgstr "Потвърди"
845970
971+#~ msgid "Search"
972+#~ msgstr "Търсене"
973+
846974#~ msgid "Top edge"
847975#~ msgstr "Горен край"
848976
@@ -858,6 +986,9 @@ msgstr ""
858986#~ msgid "Type or say a command"
859987#~ msgstr "Въведете или кажете команда"
860988
989+#~ msgid "Speaking..."
990+#~ msgstr "Говорете..."
991+
861992#~ msgid "Speak Now..."
862993#~ msgstr "Говорете сега..."
863994
@@ -867,14 +998,22 @@ msgstr ""
867998#~ msgid "Skip intro"
868999#~ msgstr "Пропусни интрото"
8691000
1001+#~ msgid "Loading. Please Wait..."
1002+#~ msgstr "Зарежда се. Моля, почакайте..."
1003+
1004+#~ msgid "Try swiping from the top edge to access the indicators"
1005+#~ msgstr ""
1006+#~ "Опитайте се да приплъзнете пръста си от горния край към долния, за да "
1007+#~ "получите достъп до индикаторите"
1008+
8701009#~ msgid "Swipe up again to close the settings screen"
8711010#~ msgstr ""
8721011#~ "Отново приплъзнете пръста си нагоре за да затворите екрана с настройките"
8731012
8741013#~ msgid "Swipe from the left to reveal the launcher for quick access to apps"
8751014#~ msgstr ""
876−#~ "Приплъзнете пръста си от левия край към десния, за да отворите стартера "
877−#~ "за бърз достъп до приложенията"
1015+#~ "Приплъзнете пръста си от левия край към десния, за да отворите стартера за "
1016+#~ "бърз достъп до приложенията"
8781017
8791018#~ msgid "Try swiping from the right edge to unlock the phone"
8801019#~ msgstr ""
po/bn.po+470−378

This diff is too big to show here.

po/br.po+370−349

This diff is too big to show here.

po/bs.po+329−241

This diff is too big to show here.

po/ca.po+378−418

This diff is too big to show here.

po/ca@valencia.po+334−225

This diff is too big to show here.

po/ce.po+290−142

This diff is too big to show here.

po/ckb.po+304−162

This diff is too big to show here.

po/co.po+324−309

This diff is too big to show here.

po/cs.po+485−497

This diff is too big to show here.

po/cy.po+328−241

This diff is too big to show here.

po/da.po+409−323

This diff is too big to show here.

po/de.po+387−428

This diff is too big to show here.

po/el.po+442−402

This diff is too big to show here.

po/en_AU.po+409−479

This diff is too big to show here.

po/en_GB.po+361−381

This diff is too big to show here.

po/en_US.podeleted−814

This diff is too big to show here.

po/eo.po+316−206

This diff is too big to show here.

po/es.po+385−423

This diff is too big to show here.

po/et.po+290−142

This diff is too big to show here.

po/eu.po+337−246

This diff is too big to show here.

po/fa.po+377−442

This diff is too big to show here.

po/fi.po+364−405

This diff is too big to show here.

po/fo.po+312−216

This diff is too big to show here.

po/fr.po+426−466

This diff is too big to show here.

po/ga.po+327−234

This diff is too big to show here.

po/gd.po+371−391

This diff is too big to show here.

po/gl.po+382−423

This diff is too big to show here.

po/gu.podeleted−814

This diff is too big to show here.

po/gv.po+304−182

This diff is too big to show here.

po/he.po+464−373

This diff is too big to show here.

po/hi.po+300−156

This diff is too big to show here.

po/hr.po+392−384

This diff is too big to show here.

po/hu.po+399−436

This diff is too big to show here.

po/hy.po+406−279

This diff is too big to show here.

po/ia.po+359−381

This diff is too big to show here.

po/id.po+340−232

This diff is too big to show here.

po/is.po+327−203

This diff is too big to show here.

po/it.po+391−430

This diff is too big to show here.

po/ja.po+389−282

This diff is too big to show here.

po/kk.podeleted−841

This diff is too big to show here.

po/km.po+332−239

This diff is too big to show here.

po/kn.po+300−150

This diff is too big to show here.

po/ko.po+458−386

This diff is too big to show here.

po/ku.po+337−217

This diff is too big to show here.

po/ky.po+300−150

This diff is too big to show here.

po/lo.po+297−149

This diff is too big to show here.

po/lt.po+414−432

This diff is too big to show here.

po/lv.po+344−254

This diff is too big to show here.

po/ml.po+306−163

This diff is too big to show here.

po/mr.po+295−165

This diff is too big to show here.

po/ms.po+427−401

This diff is too big to show here.

po/my.po+305−200

This diff is too big to show here.

po/nb.po+369−408

This diff is too big to show here.

po/ne.po+290−145

This diff is too big to show here.

po/nl.po+461−499

This diff is too big to show here.

po/nn.po+290−142

This diff is too big to show here.

po/oc.po+342−336

This diff is too big to show here.

po/or.po+290−142

This diff is too big to show here.

po/pa.po+340−250

This diff is too big to show here.

po/pl.po+402−442

This diff is too big to show here.

po/pt.po+390−430

This diff is too big to show here.

po/pt_BR.po+443−367

This diff is too big to show here.

po/ro.po+348−256

This diff is too big to show here.

po/ru.po+381−431

This diff is too big to show here.

po/sc.podeleted−904

This diff is too big to show here.

po/shn.po+290−142

This diff is too big to show here.

po/si.po+310−169

This diff is too big to show here.

po/sk.po+382−424

This diff is too big to show here.

po/sl.po+354−366

This diff is too big to show here.

po/sq.po+314−232

This diff is too big to show here.

po/sr.po+362−382

This diff is too big to show here.

po/sv.po+368−407

This diff is too big to show here.

po/sw.po+321−219

This diff is too big to show here.

po/ta.po+322−177

This diff is too big to show here.

po/te.po+304−170

This diff is too big to show here.

po/th.po+317−170

This diff is too big to show here.

po/tr.po+367−439

This diff is too big to show here.

po/ug.po+347−293

This diff is too big to show here.

po/uk.po+374−391

This diff is too big to show here.

po/unity8.pot+238−111

This diff is too big to show here.

po/ur.po+316−171

This diff is too big to show here.

po/uz.po+290−142

This diff is too big to show here.

po/vi.po+290−142

This diff is too big to show here.

po/wo.po+341−250

This diff is too big to show here.

po/xh.po+290−142

This diff is too big to show here.

po/zh_CN.po+383−424

This diff is too big to show here.

po/zh_HK.po+305−179

This diff is too big to show here.

po/zh_TW.po+420−427

This diff is too big to show here.

qml/ApplicationMenus/ApplicationMenuItemFactory.qml+7−7

This diff is too big to show here.

qml/ApplicationMenus/MenuItem.qml+3−3

This diff is too big to show here.

qml/ApplicationMenus/RegisteredApplicationMenuModel.qml+1−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.qmlnew file+42

This diff is too big to show here.

qml/Components/Carousel.qmlnew file+335

This diff is too big to show here.

qml/Components/Dialogs.qml+20−44

This diff is too big to show here.

qml/Components/InputMethod.qml+1−2

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

This diff is too big to show here.

qml/Components/Lockscreen.qml−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.qmlnew file+98

This diff is too big to show here.

qml/Components/ResponsiveVerticalJournal.qmlnew file+81

This diff is too big to show here.

qml/Components/ShellDialog.qml+10−7

This diff is too big to show here.

qml/Components/Showable.qml+12−15

This diff is too big to show here.

qml/Components/Wallpaper.qml+16−68

This diff is too big to show here.

qml/Components/WallpaperResolver.qml+6−17

This diff is too big to show here.

qml/Dash/CardCarousel.qmlnew file+74

This diff is too big to show here.

qml/Dash/CardGrid.qmlnew file+83

This diff is too big to show here.

qml/Dash/CardHorizontalList.qmlnew file+66

This diff is too big to show here.

qml/Dash/CardTool.qmlnew file+274

This diff is too big to show here.

qml/Dash/CardVerticalJournal.qmlnew file+85

This diff is too big to show here.

qml/Dash/Dash.qmlnew file+381

This diff is too big to show here.

qml/Dash/DashApplication.qmlnew file+39

This diff is too big to show here.

qml/Dash/DashBackground.qmlnew file+21

This diff is too big to show here.

qml/Dash/DashCategoryBase.qmlnew file+54

This diff is too big to show here.

qml/Dash/DashContent.qmlnew file+211

This diff is too big to show here.

qml/Dash/DashContentTabBarStyle.qmlnew file+24

This diff is too big to show here.

qml/Dash/DashNavigation.qmlnew file+199

This diff is too big to show here.

qml/Dash/DashNavigationHeader.qmlnew file+73

This diff is too big to show here.

qml/Dash/DashNavigationList.qmlnew file+118

This diff is too big to show here.

qml/Dash/DashPageHeader.qmlnew file+448

This diff is too big to show here.

qml/Dash/DashRenderer.qmlnew file+66

This diff is too big to show here.

qml/Dash/DashSectionHeader.qmlnew file+64

This diff is too big to show here.

qml/Dash/Filters/FilterExpandableWidget.qmlnew file+97

This diff is too big to show here.

qml/Dash/Filters/FilterOptionSelector.qmlnew file+97

This diff is too big to show here.

qml/Dash/Filters/FilterRangeInput.qmlnew file+136

This diff is too big to show here.

qml/Dash/Filters/FilterValueSlider.qmlnew file+87

This diff is too big to show here.

tests/plugins/Unity/Launcher/xdgwatcher.cpp → qml/Dash/Filters/FilterWidget.qmlrenamed+11−24

This diff is too big to show here.

qml/Dash/Filters/FilterWidgetFactory.qmlnew file+89

This diff is too big to show here.

qml/Dash/FiltersPopover.qmlnew file+106

This diff is too big to show here.

qml/Dash/GenericScopeView.qmlnew file+797

This diff is too big to show here.

qml/Dash/PageHeaderExtraPanel.qmlnew file+201

This diff is too big to show here.

qml/Dash/PreviewView.qmlnew file+76

This diff is too big to show here.

qml/Dash/Previews/Preview.qmlnew file+145

This diff is too big to show here.

qml/Dash/Previews/PreviewActionButton.qmlnew file+27

This diff is too big to show here.

qml/Dash/Previews/PreviewActionCombo.qmlnew file+79

This diff is too big to show here.

qml/Dash/Previews/PreviewActions.qmlnew file+73

This diff is too big to show here.

qml/Dash/Previews/PreviewAudioPlayback.qmlnew file+152

This diff is too big to show here.

qml/Dash/Previews/PreviewComment.qmlnew file+86

This diff is too big to show here.

qml/Dash/Previews/PreviewCommentInput.qmlnew file+88

This diff is too big to show here.

qml/Dash/Previews/PreviewExpandable.qmlnew file+104

This diff is too big to show here.

qml/Dash/Previews/PreviewHeader.qmlnew file+170

This diff is too big to show here.

qml/Dash/Previews/PreviewIconActions.qmlnew file+88

This diff is too big to show here.

qml/Dash/Previews/PreviewImageGallery.qmlnew file+150

This diff is too big to show here.

qml/Dash/Previews/PreviewInlineVideo.qmlnew file+112

This diff is too big to show here.

qml/Dash/Previews/PreviewMediaToolbar.qmlnew file+57

This diff is too big to show here.

qml/Dash/Previews/PreviewOverlay.qmlnew file+166

This diff is too big to show here.

qml/Dash/Previews/PreviewProgress.qmlnew file+74

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingDisplay.qmlnew file+117

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingEdit.qmlnew file+83

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingInput.qmlnew file+207

This diff is too big to show here.

qml/Dash/Previews/PreviewRatingSingleDisplay.qmlnew file+73

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/Update/MockSystemImage.qml → qml/Dash/Previews/PreviewSingleton/PreviewSingleton.qmlrenamed+5−13

This diff is too big to show here.

qml/Dash/Previews/PreviewSingleton/qmldirnew file+1

This diff is too big to show here.

qml/Dash/Previews/PreviewTable.qmlnew file+91

This diff is too big to show here.

qml/Dash/Previews/PreviewTextSummary.qmlnew file+78

This diff is too big to show here.

qml/Dash/Previews/PreviewVideoPlayback.qmlnew file+87

This diff is too big to show here.

qml/Dash/Previews/PreviewWidget.qmlnew file+60

This diff is too big to show here.

qml/Dash/Previews/PreviewWidgetFactory.qmlnew file+101

This diff is too big to show here.

qml/Dash/Previews/PreviewZoomableImage.qmlnew file+103

This diff is too big to show here.

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

The content is the same.

qml/Dash/ScopeListView.qmlnew file+28

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSetting.qmlnew file+46

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSettingBoolean.qmlnew file+63

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSettingList.qmlnew file+50

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSettingNumber.qmlnew file+21

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSettingString.qmlnew file+89

This diff is too big to show here.

qml/Dash/ScopeSettings/ScopeSettingsWidgetFactory.qmlnew file+61

This diff is too big to show here.

qml/Dash/ScopeSettingsPage.qmlnew file+72

This diff is too big to show here.

qml/Dash/ScopesList.qmlnew file+206

This diff is too big to show here.

qml/Dash/ScopesListCategory.qmlnew file+184

This diff is too big to show here.

qml/Dash/ScopesListCategoryItem.qmlnew file+113

This diff is too big to show here.

qml/Dash/graphics/dark_background.jpgnew file

Binary file not shown.

qml/Dash/graphics/header_handlearrow2@27.pngnew file

Binary file not shown.

qml/Dash/graphics/header_handlearrow@27.pngnew file

Binary file not shown.

qml/Dash/graphics/icon_clear@20.pngnew file

Binary file not shown.

qml/Dash/graphics/icon_search_active@20.pngnew file

Binary file not shown.

qml/Dash/graphics/icon_search_inactive@20.pngnew file

Binary file not shown.

qml/Dash/graphics/overview_hint@30.pngnew file

Binary file not shown.

qml/Dash/graphics/pixel.pngnew file

Binary file not shown.

qml/Dash/graphics/play_button@18.pngnew file

Binary file not shown.

qml/Dash/graphics/play_button_active@18.pngnew file

Binary file not shown.

qml/Dash/graphics/play_button_active_big@20.pngnew file

Binary file not shown.

qml/Dash/graphics/play_button_big@20.pngnew file

Binary file not shown.

qml/Dash/graphics/rectangular_dropshadow@30.pngnew file

Binary file not shown.

qml/Dash/graphics/rectangular_dropshadow@30.scinew file+5

This diff is too big to show here.

qml/Dash/graphics/tabbarchevron@27.pngnew file

Binary file not shown.

qml/Dash/graphics/tablet/icon_close_preview@20.pngnew file

Binary file not shown.

qml/Dash/graphics/tooltip_arrow@27.pngnew file

Binary file not shown.

qml/DeviceConfiguration.qml−12

This diff is too big to show here.

qml/Greeter/ButtonPrompt.qmldeleted−51

This diff is too big to show here.

qml/Greeter/CoverPage.qml+11−32

This diff is too big to show here.

qml/Greeter/Greeter.qml+5−51

This diff is too big to show here.

qml/Greeter/GreeterPrompt.qml+185−64

This diff is too big to show here.

qml/Greeter/GreeterView.qmldeleted−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+84−73

This diff is too big to show here.

qml/Greeter/NarrowView.qmlnew file+263

This diff is too big to show here.

qml/Greeter/PinPrompt.qmldeleted−184

This diff is too big to show here.

qml/Greeter/PromptList.qml+18−21

This diff is too big to show here.

qml/Greeter/SessionsList.qml+18−36

This diff is too big to show here.

qml/Greeter/ShimGreeter.qml−2

This diff is too big to show here.

qml/Greeter/TextPrompt.qmldeleted−198

This diff is too big to show here.

qml/Greeter/WideView.qmlnew file+205

This diff is too big to show here.

qml/Launcher/Drawer.qml+247−263

This diff is too big to show here.

qml/Launcher/DrawerGridView.qml+5−41

This diff is too big to show here.

qml/Launcher/DrawerListView.qmlnew file+38

This diff is too big to show here.

qml/Launcher/Launcher.qml+44−72

This diff is too big to show here.

qml/Launcher/LauncherDelegate.qml+3−1

This diff is too big to show here.

qml/Launcher/LauncherPanel.qml+11−15

This diff is too big to show here.

qml/Launcher/MoreAppsHeader.qmlnew file+69

This diff is too big to show here.

qml/Notifications/Notification.qml+3−8

This diff is too big to show here.

qml/Notifications/NotificationButton.qml+1−2

This diff is too big to show here.

qml/Notifications/SwipeToAct.qml−4

This diff is too big to show here.

qml/OrientedShell.qml+1−11

This diff is too big to show here.

qml/Panel/ActiveCallHint.qml−3

This diff is too big to show here.

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

This diff is too big to show here.

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

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

This diff is too big to show here.

qml/Panel/MenuContent.qml+1−4

This diff is too big to show here.

qml/Panel/Panel.qml+22−60

This diff is too big to show here.

qml/Panel/PanelBar.qml+8−10

This diff is too big to show here.

qml/Panel/PanelItemRow.qml+4−6

This diff is too big to show here.

qml/Panel/PanelMenu.qml+9−15

This diff is too big to show here.

qml/Panel/PanelMenuPage.qml+1−1

This diff is too big to show here.

qml/Rotation/RotationStates.qml+3

This diff is too big to show here.

qml/ScopeTool.qmlnew file+165

This diff is too big to show here.

qml/Shell.qml+66−119

This diff is too big to show here.

qml/Stage/AbstractStage.qmlnew file+93

This diff is too big to show here.

qml/Stage/ApplicationWindow.qml+4−15

This diff is too big to show here.

qml/Stage/ChildWindow.qml+4

This diff is too big to show here.

qml/Stage/DecoratedWindow.qml+1−1

This diff is too big to show here.

qml/Stage/DesktopSpread.qmlnew file+576

This diff is too big to show here.

qml/Stage/DesktopSpreadDelegate.qmlnew file+126

This diff is too big to show here.

qml/Stage/MoveHandler.qml+7−7

This diff is too big to show here.

qml/Stage/PhoneStage.qmlnew file+806

This diff is too big to show here.

qml/Stage/SideStage.qml+6−10

This diff is too big to show here.

qml/Stage/Splash.qml+4−4

This diff is too big to show here.

qml/Stage/SpreadDelegate.qmlnew file+424

This diff is too big to show here.

qml/Stage/SpreadMaths.qmlnew file+164

This diff is too big to show here.

qml/Stage/Stage.qml+44−166

This diff is too big to show here.

qml/Stage/StageMaths.qml+2−5

This diff is too big to show here.

qml/Stage/TabletStage.qmlnew file+1201

This diff is too big to show here.

qml/Stage/TransformedSpreadDelegate.qmlnew file+391

This diff is too big to show here.

qml/Stage/TransformedTabletSpreadDelegate.qmlnew file+437

This diff is too big to show here.

qml/Stage/WindowDecoration.qml+6−5

This diff is too big to show here.

qml/Stage/WindowedFullscreenPolicy.qml+1−1

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+43−61

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

This diff is too big to show here.

qml/Tutorial/TutorialRight.qml+3−2

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+16−90

This diff is too big to show here.

qml/Wizard/Pages/10-welcome-update.qmldeleted−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.qmldeleted−95

This diff is too big to show here.

qml/Wizard/Pages/30-wifi.qml+6−13

This diff is too big to show here.

qml/Wizard/Pages/40-location.qmlnew file+290

This diff is too big to show here.

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

This diff is too big to show here.

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

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

This diff is too big to show here.

qml/Wizard/Pages/78-firmware-update.qml.disableddeleted−246

This diff is too big to show here.

qml/Wizard/Pages/79-system-update.qmldeleted−148

This diff is too big to show here.

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

This diff is too big to show here.

qml/Wizard/Pages/here-terms.qmlnew file+126

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

qml/Wizard/Wizard.qml+2−5

This diff is too big to show here.

src/ApplicationArguments.h−5

This diff is too big to show here.

src/CMakeLists.txt+4−5

This diff is too big to show here.

src/Dash/CMakeLists.txtnew file+29

This diff is too big to show here.

src/Dash/main.cppnew file+146

This diff is too big to show here.

src/ShellApplication.cpp+4−14

This diff is too big to show here.

src/ShellApplication.h+3−1

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

This diff is too big to show here.

tests/CMakeLists.txt+2−9

This diff is too big to show here.

tests/autopilot/unity8/dash.pynew file+247

This diff is too big to show here.

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

This diff is too big to show here.

tests/autopilot/unity8/shell/tests/test_helpers.py+74

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

This diff is too big to show here.

tests/data/unity/backgrounds/20x30.pngdeleted

Binary file not shown.

tests/data/unity/backgrounds/black.pngdeleted

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

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/GSettings.1.0/fake_gsettings.cpp+35−19

This diff is too big to show here.

tests/mocks/GSettings.1.0/fake_gsettings.h+15−8

This diff is too big to show here.

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

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

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/Ubuntu/Connectivity/networking-status.h+3−5

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/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.txtdeleted−1

This diff is too big to show here.

tests/mocks/Ubuntu/SystemSettings/Update/qmldirdeleted−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+4−7

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/Unity/Application/ApplicationManager.cpp+1−14

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/MirSurface.h−1

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

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.txtnew file+18

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/dashcommunicator.cppnew file+42

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/dashcommunicator.hnew file+39

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cppnew file+46

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.hnew file+41

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/plugin.cppnew file+31

This diff is too big to show here.

tests/mocks/Unity/DashCommunicator/plugin.hnew file+34

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

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

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

This diff is too big to show here.

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

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/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.cppnew file+165

This diff is too big to show here.

tests/mocks/Unity/fake_categories.hnew file+54

This diff is too big to show here.

tests/mocks/Unity/fake_expandablefilterwidget.cppnew file+53

This diff is too big to show here.

tests/mocks/Unity/fake_expandablefilterwidget.hnew file+48

This diff is too big to show here.

tests/mocks/Unity/fake_filters.cppnew file+136

This diff is too big to show here.

tests/mocks/Unity/fake_filters.hnew file+46

This diff is too big to show here.

tests/mocks/Unity/fake_navigation.cppnew file+123

This diff is too big to show here.

tests/mocks/Unity/fake_navigation.hnew file+61

This diff is too big to show here.

tests/mocks/Unity/fake_optionselectorfilter.cppnew file+70

This diff is too big to show here.

tests/mocks/Unity/fake_optionselectorfilter.hnew file+54

This diff is too big to show here.

tests/mocks/Unity/fake_optionselectoroptions.cppnew file+90

This diff is too big to show here.

tests/mocks/Unity/fake_optionselectoroptions.hnew file+49

This diff is too big to show here.

tests/mocks/Unity/fake_previewmodel.cppnew file+103

This diff is too big to show here.

tests/mocks/Unity/fake_previewmodel.hnew file+58

This diff is too big to show here.

tests/mocks/Unity/fake_previewwidgetmodel.cppnew file+97

This diff is too big to show here.

tests/mocks/Unity/fake_previewwidgetmodel.hnew file+47

This diff is too big to show here.

tests/mocks/Unity/fake_rangeinputfilter.cppnew file+167

This diff is too big to show here.

tests/mocks/Unity/fake_rangeinputfilter.hnew file+79

This diff is too big to show here.

tests/mocks/Unity/fake_resultsmodel.cppnew file+92

This diff is too big to show here.

tests/mocks/Unity/fake_resultsmodel.hnew file+52

This diff is too big to show here.

tests/mocks/Unity/fake_scope.cppnew file+372

This diff is too big to show here.

tests/mocks/Unity/fake_scope.hnew file+128

This diff is too big to show here.

tests/mocks/Unity/fake_scopes.cppnew file+286

This diff is too big to show here.

tests/mocks/Unity/fake_scopes.hnew file+83

This diff is too big to show here.

tests/mocks/Unity/fake_scopesoverview.cppnew file+340

This diff is too big to show here.

tests/mocks/Unity/fake_scopesoverview.hnew file+119

This diff is too big to show here.

tests/mocks/Unity/fake_settingsmodel.cppnew file+95

This diff is too big to show here.

tests/mocks/Unity/fake_settingsmodel.hnew file+54

This diff is too big to show here.

tests/mocks/Unity/fake_unity_plugin.cppnew file+62

This diff is too big to show here.

tests/mocks/Unity/fake_unity_plugin.hnew file+34

This diff is too big to show here.

tests/mocks/Unity/fake_valuesliderfilter.cppnew file+84

This diff is too big to show here.

tests/mocks/Unity/fake_valuesliderfilter.hnew file+55

This diff is too big to show here.

tests/mocks/Unity/fake_valueslidervalues.cppnew file+51

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/Unity/qmldirnew file+3

This diff is too big to show here.

tests/mocks/Utils/CMakeLists.txt+3−4

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+4−19

This diff is too big to show here.

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

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/MockUsersModel.cpp−1

This diff is too big to show here.

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

This diff is too big to show here.

tests/mocks/libusermetrics/CMakeLists.txt+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+34−6

This diff is too big to show here.

tests/plugins/CMakeLists.txt+3−1

This diff is too big to show here.

tests/plugins/Dash/CMakeLists.txtnew file+104

This diff is too big to show here.

tests/plugins/Dash/cardcreator/1.resnew file+82

This diff is too big to show here.

tests/plugins/Dash/cardcreator/1.res.cardcreatornew file+69

This diff is too big to show here.

tests/plugins/Dash/cardcreator/1.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/10.resnew file+129

This diff is too big to show here.

tests/plugins/Dash/cardcreator/10.res.cardcreatornew file+127

This diff is too big to show here.

tests/plugins/Dash/cardcreator/10.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/11.resnew file+176

This diff is too big to show here.

tests/plugins/Dash/cardcreator/11.res.cardcreatornew file+160

This diff is too big to show here.

tests/plugins/Dash/cardcreator/11.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/12.resnew file+108

This diff is too big to show here.

tests/plugins/Dash/cardcreator/12.res.cardcreatornew file+95

This diff is too big to show here.

tests/plugins/Dash/cardcreator/12.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/2.resnew file+128

This diff is too big to show here.

tests/plugins/Dash/cardcreator/2.res.cardcreatornew file+126

This diff is too big to show here.

tests/plugins/Dash/cardcreator/2.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/3.resnew file+90

This diff is too big to show here.

tests/plugins/Dash/cardcreator/3.res.cardcreatornew file+86

This diff is too big to show here.

tests/plugins/Dash/cardcreator/3.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/4.resnew file+111

This diff is too big to show here.

tests/plugins/Dash/cardcreator/4.res.cardcreatornew file+99

This diff is too big to show here.

tests/plugins/Dash/cardcreator/4.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/5.resnew file+102

This diff is too big to show here.

tests/plugins/Dash/cardcreator/5.res.cardcreatornew file+99

This diff is too big to show here.

tests/plugins/Dash/cardcreator/5.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/6.resnew file+127

This diff is too big to show here.

tests/plugins/Dash/cardcreator/6.res.cardcreatornew file+116

This diff is too big to show here.

tests/plugins/Dash/cardcreator/6.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/7.resnew file+141

This diff is too big to show here.

tests/plugins/Dash/cardcreator/7.res.cardcreatornew file+139

This diff is too big to show here.

tests/plugins/Dash/cardcreator/7.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/8.resnew file+109

This diff is too big to show here.

tests/plugins/Dash/cardcreator/8.res.cardcreatornew file+97

This diff is too big to show here.

tests/plugins/Dash/cardcreator/8.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreator/9.resnew file+120

This diff is too big to show here.

tests/plugins/Dash/cardcreator/9.res.cardcreatornew file+109

This diff is too big to show here.

tests/plugins/Dash/cardcreator/9.tstnew file+4

This diff is too big to show here.

tests/plugins/Dash/cardcreatortest.cppnew file+126

This diff is too big to show here.

tests/plugins/Dash/cardcreatortest.qmlnew file+29

This diff is too big to show here.

tests/plugins/Dash/horizontaljournaltest.cppnew file+490

This diff is too big to show here.

tests/plugins/Dash/horizontaljournaltest.qmlnew file+44

This diff is too big to show here.

tests/plugins/Dash/horizontaljournaltry.cppnew file+91

This diff is too big to show here.

tests/plugins/Dash/horizontaljournaltry.qmlnew file+120

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadersectionexternalmodeltest.cppnew file+246

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadersectiontest.cppnew file+2212

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertest.cppnew file+2038

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertest.qmlnew file+96

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertestsection.qmlnew file+119

This diff is too big to show here.

tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qmlnew file+76

This diff is too big to show here.

tests/plugins/Dash/organicgridtest.cppnew file+533

This diff is too big to show here.

tests/plugins/Dash/organicgridtest.qmlnew file+44

This diff is too big to show here.

tests/plugins/Dash/organicgridtry.cppnew file+99

This diff is too big to show here.

tests/plugins/Dash/organicgridtry.qmlnew file+114

This diff is too big to show here.

tests/plugins/Dash/tst_CardAttributes.qmlnew file+57

This diff is too big to show here.

tests/plugins/Dash/tst_CroppedImageMinimumSourceSize.qmlnew file+56

This diff is too big to show here.

tests/plugins/Dash/tst_ListViewWithPageHeaderQML.qmlnew file+140

This diff is too big to show here.

tests/plugins/Dash/tst_ScopeStyle.qmlnew file+188

This diff is too big to show here.

tests/plugins/Dash/verticaljournaltest.cppnew file+564

This diff is too big to show here.

tests/plugins/Dash/verticaljournaltest.qmlnew file+45

This diff is too big to show here.

tests/plugins/Dash/verticaljournaltry.cppnew file+91

This diff is too big to show here.

tests/plugins/Dash/verticaljournaltry.qmlnew file+121

This diff is too big to show here.

tests/plugins/GlobalShortcut/CMakeLists.txt+2−1

This diff is too big to show here.

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

This diff is too big to show here.

tests/plugins/ImageCache/CMakeLists.txtnew file+30

This diff is too big to show here.

tests/plugins/ImageCache/graphics/wide.jpgnew file

Binary file not shown.

tests/plugins/ImageCache/test.cppnew file+216

This diff is too big to show here.

tests/plugins/ImageCache/test.qmlnew file+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+5−18

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

This diff is too big to show here.

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

This diff is too big to show here.

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

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

This diff is too big to show here.

tests/plugins/Unity/Launcher/CMakeLists.txt+1−36

This diff is too big to show here.

tests/plugins/Unity/Launcher/appdrawermodeltest.cppdeleted−68

This diff is too big to show here.

tests/plugins/Unity/Launcher/launchermodeltest.cpp−1

This diff is too big to show here.

tests/plugins/Unity/Launcher/ualwrapper.cppdeleted−58

This diff is too big to show here.

tests/plugins/Unity/Launcher/ualwrapper.hdeleted−55

This diff is too big to show here.

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

This diff is too big to show here.

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

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

This diff is too big to show here.

tests/plugins/Utils/WindowStateStorageTest.cpp+1−49

This diff is too big to show here.

tests/plugins/WindowManager/CMakeLists.txt+2−4

This diff is too big to show here.

tests/plugins/WindowManager/UnityApplicationMocks.h−1

This diff is too big to show here.

tests/plugins/WindowManager/tst_TopLevelWindowModel.cpp−63

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

This diff is too big to show here.

tests/qmltests/ApplicationMenus/tst_MenuBar.qml+18−46

This diff is too big to show here.

tests/qmltests/ApplicationMenus/tst_MenuPopup.qml+9−10

This diff is too big to show here.

tests/qmltests/CMakeLists.txt+51−5

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Components/tst_Carousel.qmlnew file+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+2−19

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

This diff is too big to show here.

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

This diff is too big to show here.

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

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

This diff is too big to show here.

tests/qmltests/Components/tst_ResponsiveVerticalJournal.qmlnew file+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.qmldeleted−118

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Dash/CardHelpers.jsnew file+115

This diff is too big to show here.

tests/qmltests/Dash/Filters/tst_FilterExpandableWidget.qmlnew file+99

This diff is too big to show here.

tests/qmltests/Dash/Filters/tst_FilterOptionSelector.qmlnew file+96

This diff is too big to show here.

tests/qmltests/Dash/Filters/tst_FilterRangeInput.qmlnew file+247

This diff is too big to show here.

tests/qmltests/Dash/Filters/tst_FilterValueSlider.qmlnew file+101

This diff is too big to show here.

tests/qmltests/Dash/Filters/tst_FilterWidgetFactory.qmlnew file+59

This diff is too big to show here.

tests/qmltests/Dash/Previews/MockPreviewWidget.qmlnew file+27

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_Preview.qmlnew file+214

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewActions.qmlnew file+262

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qmlnew file+182

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewComment.qmlnew file+84

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewCommentInput.qmlnew file+113

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewExpandable.qmlnew file+353

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewHeader.qmlnew file+183

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewIconActions.qmlnew file+136

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewImageGallery.qmlnew file+147

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewInlineVideo.qmlnew file+155

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewMediaToolbar.qmlnew file+69

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewProgress.qmlnew file+100

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingDisplay.qmlnew file+123

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingDisplayCreationRanges.qmlnew file+131

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingEdit.qmlnew file+87

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewRatingInput.qmlnew file+246

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewTable.qmlnew file+147

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewTextSummary.qmlnew file+87

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewVideoPlayback.qmlnew file+61

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qmlnew file+104

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qmlnew file+138

This diff is too big to show here.

tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qmlnew file+62

This diff is too big to show here.

tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingList.qmlnew file+84

This diff is too big to show here.

tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qmlnew file+98

This diff is too big to show here.

tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qmlnew file+88

This diff is too big to show here.

tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingsWidgetFactory.qmlnew file+65

This diff is too big to show here.

tests/qmltests/Dash/artwork/avatar@12.pngnew file

Binary file not shown.

tests/qmltests/Dash/artwork/background.pngnew file

Binary file not shown.

tests/qmltests/Dash/artwork/checkers.pngnew file

Binary file not shown.

tests/qmltests/Dash/artwork/emblem.pngnew file

Binary file not shown.

tests/qmltests/Dash/artwork/music-player-design.pngnew file

Binary file not shown.

tests/qmltests/Dash/tst_Card.qmlnew file+682

This diff is too big to show here.

tests/qmltests/Dash/tst_CardBenchmark.qmlnew file+95

This diff is too big to show here.

tests/qmltests/Dash/tst_CardCarousel.qmlnew file+111

This diff is too big to show here.

tests/qmltests/Dash/tst_CardTool.qmlnew file+379

This diff is too big to show here.

tests/qmltests/Dash/tst_Dash.qmlnew file+648

This diff is too big to show here.

tests/qmltests/Dash/tst_DashContent.qmlnew file+730

This diff is too big to show here.

tests/qmltests/Dash/tst_DashPageHeader.qmlnew file+357

This diff is too big to show here.

tests/qmltests/Dash/tst_DashShell.qmlnew file+84

This diff is too big to show here.

tests/qmltests/Dash/tst_GenericScopeView.qmlnew file+706

This diff is too big to show here.

tests/qmltests/Dash/tst_PageHeader/logo-ubuntu-orange.svgnew file+60

This diff is too big to show here.

tests/qmltests/Dash/tst_PreviewView.qmlnew file+122

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Greeter/tst_GreeterView.qmldeleted−1366

This diff is too big to show here.

tests/qmltests/Greeter/tst_NarrowView.qmlnew file+566

This diff is too big to show here.

tests/qmltests/Greeter/tst_WideView.qmlnew file+765

This diff is too big to show here.

tests/qmltests/Launcher/tst_Drawer.qml+51−200

This diff is too big to show here.

tests/qmltests/Launcher/tst_Launcher.qml+83−167

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

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

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+79−33

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Panel/PanelUI.qmldeleted−286

This diff is too big to show here.

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

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+240−58

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+22−61

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

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Stage/tst_DesktopStage.qml+11−22

This diff is too big to show here.

tests/qmltests/Stage/tst_PhoneStage.qml+60−87

This diff is too big to show here.

tests/qmltests/Stage/tst_QMLTopLevelWindowModel.qmldeleted−191

This diff is too big to show here.

tests/qmltests/Stage/tst_SpreadDelegate.qmlnew file+423

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Stage/tst_TabletStage.qml+151−112

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

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/tst_OrientedShell.qml+266−312

This diff is too big to show here.

tests/qmltests/tst_Shell.qml+543−635

This diff is too big to show here.

tests/qmltests/tst_ShellWithPin.qml+79−96

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

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+18−14

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tools/CMakeLists.txt+1

This diff is too big to show here.

tools/indicatorsclient/CMakeLists.txt+1−1

This diff is too big to show here.

tools/menutool/CMakeLists.txt+1−1

This diff is too big to show here.

tools/scopetool/CMakeLists.txtnew file+12

This diff is too big to show here.

tools/scopetool/registry-tracker.cppnew file+146

This diff is too big to show here.

tools/scopetool/registry-tracker.hnew file+49

This diff is too big to show here.

tools/scopetool/scopetool.cppnew file+116

This diff is too big to show here.