on xenial help sign in
Merged with trunk
commit5211c9d1104c76e300d53c777c98f4e3cb74dc56 authorMirco Müller <mirco.mueller@ubuntu.com> dateFri 8 Aug 2014, 15:37 (12 years ago) parent400158a8705631
281 files changed+9315−5389
tests/autopilot/.project → .project+1−1 tests/autopilot/.pydevproject → .pydevproject+3−1 .settings/Autopilot List.launch+14 .settings/Autopilot Run.launch+14 CMakeLists.txt+1 cmake/modules/QmlTest.cmake+2−2 data/CMakeLists.txt+5−2 data/unity8-dash.conf+22 data/unity8-dash.desktop.in+9 data/unity8.conf+1−7 debian/changelog+193 debian/control+9−5 debian/rules+7 debian/unity8.install+3 plugins/AccountsService/AccountsService.cpp+21−1 plugins/AccountsService/AccountsService.h+13 plugins/AccountsService/plugin.cpp+1 plugins/Dash/CardAttributes.qml+65 plugins/Dash/CardCreator.js+100−17 plugins/Dash/ScopeStyle.qml+17−8 plugins/Dash/listviewwithpageheader.cpp+1−6 plugins/Dash/qmldir+1 plugins/LightDM/plugin.cpp+2 plugins/Ubuntu/Payments/CMakeLists.txt+1−1 plugins/Unity/CMakeLists.txt+1 plugins/Unity/DashCommunicator/CMakeLists.txt+19 plugins/Unity/DashCommunicator/dashcommunicator.cpp+43 plugins/Unity/DashCommunicator/dashcommunicator.h+35 plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp+30 plugins/Unity/DashCommunicator/dashcommunicatorservice.h+38 plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp+39 plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h+39 plugins/Unity/DashCommunicator/plugin.cpp+31 plugins/Unity/DashCommunicator/plugin.h+34 plugins/Unity/DashCommunicator/qmldir+3 plugins/Unity/Launcher/launchermodel.cpp+8−2 plugins/Utils/CMakeLists.txt+1 plugins/Utils/easingcurve.cpp+5−1 plugins/Utils/plugin.cpp+2 plugins/Utils/windowkeysfilter.cpp+57 plugins/Utils/windowkeysfilter.h+51 po/am.po+30−22 po/ar.po+19−11 po/ast.po+20−12 po/az.po+19−11 po/bg.po+19−11 po/br.po+20−12 po/bs.po+19−11 po/ca.po+28−20 po/ckb.po+19−11 po/cs.po+19−11 po/da.po+22−14 po/de.po+19−11 po/el.po+35−27 po/en_AU.po+20−12 po/en_GB.po+20−12 po/eo.po+19−11 po/es.po+21−13 po/eu.po+24−15 po/fa.po+65−55 po/fi.po+20−12 po/fo.po+19−11 po/fr.po+21−13 po/gd.po+21−13 po/gl.po+20−12 po/he.po+20−12 po/hi.po+19−11 po/hr.po+19−11 po/hu.po+45−35 po/hy.po+19−11 po/id.po+19−11 po/is.po+20−12 po/it.po+20−12 po/ja.po+32−24 po/km.po+21−13 po/kn.po+19−11 po/ko.po+19−11 po/ky.po+19−11 po/lo.po+19−11 po/lt.po+19−11 po/lv.po+23−15 po/ml.po+20−12 po/mr.po+19−11 po/ms.po+19−11 po/my.po+19−11 po/nb.po+20−12 po/nl.po+21−13 po/pl.po+21−13 po/pt.po+21−13 po/pt_BR.po+28−20 po/ro.po+19−11 po/ru.po+32−24 po/shn.po+19−11 po/si.po+19−11 po/sl.po+28−20 po/sq.po+19−11 po/sr.po+19−11 po/sv.po+39−30 po/sw.po+19−11 po/ta.po+19−11 po/te.po+19−11 po/tr.po+19−11 po/ug.po+20−12 po/uk.po+20−12 po/unity8.pot+17−9 po/vi.po+19−11 po/xh.po+19−11 po/zh_CN.po+29−21 po/zh_HK.po+19−11 po/zh_TW.po+21−13 qml/Components/Background.qml+77 qml/Components/Dialogs.qml+217 qml/Components/DraggingArea.qml+4 qml/Components/EdgeDemo.qml+15−16 qml/Components/FilterGrid.qml−124 qml/Components/InputMethod.qml+79 qml/Components/ListItems/Header.qml+17−26 qml/Components/PageHeader.qml+56−23 qml/Components/PassphraseLockscreen.qml+3 qml/Components/ResponsiveGridView.qml+2−1 qml/Components/SeeMore.qml−70 qml/Components/graphics/pagination_dot_off@30.png qml/Components/graphics/pagination_dot_on@30.png qml/Dash/Apps/CloseIcon.qml−62 qml/Dash/Apps/RunningApplicationTile.qml−128 qml/Dash/Apps/RunningApplicationsGrid.qml−105 qml/Dash/Apps/graphics/close_btn@9.png qml/Dash/CardCarousel.qml+2−7 qml/Dash/CardFilterGrid.qml → qml/Dash/CardGrid.qml+22−22 qml/Dash/CardTool.qml+28−3 qml/Dash/CardVerticalJournal.qml+3−21 qml/Dash/Dash.qml+92−11 qml/Dash/DashApplication.qml+36 qml/Dash/DashApps.qml−40 qml/Dash/DashContent.qml+12−7 qml/Dash/DashDepartments.qml → qml/Dash/DashNavigation.qml+50−43 qml/Dash/DashDepartmentsList.qml → qml/Dash/DashNavigationList.qml+14−18 qml/Dash/DashRenderer.qml+3−10 qml/Dash/GenericScopeView.qml+141−86 qml/Dash/PreviewListView.qml+23−27 qml/Dash/Previews/PreviewExpandable.qml+101 qml/Dash/Previews/PreviewImageGallery.qml+1 qml/Dash/Previews/PreviewTextSummary.qml+3−16 qml/Dash/Previews/PreviewWidget.qml+3 qml/Dash/Previews/PreviewWidgetFactory.qml+5 qml/Dash/ScopeListView.qml−5 qml/Dash/graphics/phone/screenshots/unity8-dash@12.png qml/Dash/graphics/phone/screenshots/vkb_portrait.png qml/Greeter/Greeter.qml+1−1 qml/Launcher/Launcher.qml+3−4 qml/Launcher/LauncherDelegate.qml+9−6 qml/Launcher/graphics/notification@30.png qml/Launcher/graphics/notification@30.sci−5 qml/Notifications/NotificationMenuItemFactory.qml+3 qml/Panel/Indicators.qml+3 qml/Panel/Indicators/DefaultIndicatorPage.qml+1−1 qml/Panel/Indicators/MenuItemFactory.qml+74 qml/Panel/Indicators/ModemInfoItem.qml+111 qml/Panel/Indicators/RoamingIndication.qml+40 qml/ScopeTool.qml+2−11 qml/Shell.qml+128−469 qml/Stages/Animations/BaseSurfaceAnimation.qml+93 qml/Stages/Animations/DarkenAndFadeInAnimation.qml+48 qml/Stages/Animations/SwipeFromBottomAnimation.qml+48 qml/Stages/Animations/SwipeUpAnimation.qml+49 qml/Stages/PhoneStage.qml+219−278 qml/Stages/Splash.qml+68 qml/Stages/SpreadDelegate.qml+193−23 qml/Stages/StageWithSideStage.qml−413 qml/Stages/SurfaceContainer.qml+123 qml/Stages/SwitchingApplicationImage.qml−81 qml/Stages/TabletStage.qml+612 qml/Stages/TransformedSpreadDelegate.qml+37−30 qml/Stages/TransformedTabletSpreadDelegate.qml+397 run.sh+15−6 run_on_device.sh+1−3 src/CMakeLists.txt+1−3 src/Dash/CMakeLists.txt+13 src/Dash/main.cpp+96 src/main.cpp+21−89 tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+1−1 tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.py+3−2 tests/autopilot/unity8/fixture_setup.py+64 tests/autopilot/unity8/process_helpers.py+89−20 tests/autopilot/unity8/shell/emulators/dash.py+34−19 tests/autopilot/unity8/shell/emulators/greeter.py+4−1 tests/autopilot/unity8/shell/emulators/main_window.py+34−20 tests/autopilot/unity8/shell/tests/__init__.py+141−48 tests/autopilot/unity8/shell/tests/test_emulators.py+23−24 tests/autopilot/unity8/shell/tests/test_lock_screen.py+7−47 tests/autopilot/unity8/shell/tests/test_notifications.py+12−7 tests/autopilot/unity8/shell/tests/test_upstart.py+33−5 tests/mocks/AccountsService/AccountsService.cpp+12−2 tests/mocks/AccountsService/AccountsService.h+12 tests/mocks/AccountsService/CMakeLists.txt+4−1 tests/mocks/AccountsService/plugin.cpp+1 tests/mocks/LightDM/GreeterPrivate.h+2 tests/mocks/LightDM/demo/CMakeLists.txt+4−2 tests/mocks/LightDM/demo/GreeterPrivate.cpp+202−30 tests/mocks/LightDM/demo/UsersModelPrivate.cpp+1−1 tests/mocks/LightDM/full/GreeterPrivate.cpp+1−1 tests/mocks/LightDM/single-pin/GreeterPrivate.cpp+1−1 tests/mocks/LightDM/single-pin/UsersModelPrivate.cpp+1−1 tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−9 tests/mocks/Unity/Application/Application.qmltypes−2 tests/mocks/Unity/Application/ApplicationDBusAdaptor.cpp+75 tests/mocks/Unity/Application/ApplicationDBusAdaptor.h+43 tests/mocks/Unity/Application/ApplicationInfo.cpp+49−63 tests/mocks/Unity/Application/ApplicationInfo.h+19−16 tests/mocks/Unity/Application/ApplicationManager.cpp+73−174 tests/mocks/Unity/Application/ApplicationManager.h+14−24 tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp+1−1 tests/mocks/Unity/Application/CMakeLists.txt+6−2 tests/mocks/Unity/Application/MirSurfaceItem.cpp+172 tests/mocks/Unity/Application/MirSurfaceItem.h+121 tests/mocks/Unity/Application/SurfaceManager.cpp+73 tests/mocks/Unity/Application/SurfaceManager.h+54 tests/mocks/Unity/Application/VirtualKeyboard.cpp+55 qml/Stages/SidestageHandle.qml → tests/mocks/Unity/Application/VirtualKeyboard.h+19−6 tests/mocks/Unity/Application/plugin.cpp+16−9 tests/mocks/Unity/CMakeLists.txt+4−3 tests/mocks/Unity/DashCommunicator/CMakeLists.txt+18 tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp+37 tests/mocks/Unity/DashCommunicator/dashcommunicator.h+39 tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp+33 tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h+36 tests/mocks/Unity/DashCommunicator/plugin.cpp+31 tests/mocks/Unity/DashCommunicator/plugin.h+34 tests/mocks/Unity/DashCommunicator/qmldir+3 tests/mocks/Unity/Unity.qmltypes+79−27 tests/mocks/Unity/fake_categories.cpp+13−1 tests/mocks/Unity/fake_categories.h+2 tests/mocks/Unity/fake_department.cpp → tests/mocks/Unity/fake_navigation.cpp+32−40 tests/mocks/Unity/fake_department.h → tests/mocks/Unity/fake_navigation.h+13−13 tests/mocks/Unity/fake_scope.cpp+69−24 tests/mocks/Unity/fake_scope.h+17−9 tests/mocks/Unity/fake_scopes.cpp+16−2 tests/mocks/Unity/fake_scopes.h+2 tests/mocks/Unity/fake_unity_plugin.cpp+2−2 tests/mocks/libusermetrics/UserMetrics.cpp+3 tests/plugins/Dash/CMakeLists.txt+1 tests/plugins/Dash/cardcreator/1.res+65−61 tests/plugins/Dash/cardcreator/1.tst+1−1 tests/plugins/Dash/cardcreator/2.res+101−90 tests/plugins/Dash/cardcreator/2.tst+1−1 tests/plugins/Dash/cardcreator/3.res+79−74 tests/plugins/Dash/cardcreator/3.tst+1−1 tests/plugins/Dash/cardcreator/4.res+8 tests/plugins/Dash/cardcreator/4.tst+1−1 tests/plugins/Dash/cardcreator/5.res+122−118 tests/plugins/Dash/cardcreator/5.tst+1−1 tests/plugins/Dash/cardcreator/6.res+10−8 tests/plugins/Dash/cardcreator/6.tst+1−1 tests/plugins/Dash/cardcreator/7.res+136 tests/plugins/Dash/cardcreator/7.tst+3 tests/plugins/Dash/cardcreatortest.cpp+19−2 tests/plugins/Dash/listviewwithpageheadersectiontest.cpp−1 tests/plugins/Dash/tst_CardAttributes.qml+54 tests/plugins/Dash/tst_ScopeStyle.qml+41−9 tests/plugins/Unity/Indicators/unitymenumodelstacktest.cpp+3 tests/qmltests/CMakeLists.txt+2−3 tests/qmltests/Components/tst_Background.qml+90 tests/qmltests/Components/tst_FilterGrid.qml−190 tests/qmltests/Components/tst_PageHeader.qml+57−29 tests/qmltests/Components/tst_SeeMore.qml−52 tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml−196 tests/qmltests/Dash/CardHelpers.js+8−5 tests/qmltests/Dash/Previews/tst_PreviewExpandable.qml+97 tests/qmltests/Dash/Previews/tst_PreviewTextSummary.qml+4−18 tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml+1 tests/qmltests/Dash/tst_Card.qml+19−5 tests/qmltests/Dash/tst_Dash.qml+47−15 tests/qmltests/Dash/tst_DashContent.qml+109−101 tests/qmltests/Dash/tst_GenericScopeView.qml+139−50 tests/qmltests/Greeter/tst_Lockscreen.qml+11−5 tests/qmltests/Launcher/tst_Launcher.qml+11−2 tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml+47 tests/qmltests/Panel/tst_ActiveCallHint.qml+1 tests/qmltests/Stages/tst_PhoneStage.qml+12−58 tests/qmltests/tst_Shell.qml+156−272 tests/qmltests/tst_ShellWithPin.qml+4−37
tests/autopilot/.project → .projectrenamed+1−1
@@ -1,6 +1,6 @@
11<?xml version="1.0" encoding="UTF-8"?>
22<projectDescription>
3− <name>Unity8 Autopilot</name>
3+ <name>Unity8</name>
44 <comment></comment>
55 <projects>
66 </projects>
tests/autopilot/.pydevproject → .pydevprojectrenamed+3−1
@@ -1,7 +1,9 @@
11<?xml version="1.0" encoding="UTF-8" standalone="no"?>
22<?eclipse-pydev version="1.0"?><pydev_project>
33<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
4−<path>/Unity8 Autopilot</path>
4+<path>/Unity8/tests/autopilot</path>
5+<path>/Unity8/.bazaar</path>
6+<path>/Unity8/tests/whitespace</path>
57</pydev_pathproperty>
68<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
79<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
.settings/Autopilot List.launchnew file+14
@@ -0,0 +1,14 @@
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
3+<stringAttribute key="bad_container_name" value="/Unity8/.pyd"/>
4+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"/>
5+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"/>
6+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
7+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
8+</listAttribute>
9+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/autopilot"/>
10+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value=""/>
11+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="list unity8"/>
12+<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
13+<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Unity8"/>
14+</launchConfiguration>
.settings/Autopilot Run.launchnew file+14
@@ -0,0 +1,14 @@
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
3+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"/>
4+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"/>
5+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
6+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
7+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
8+</listAttribute>
9+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/autopilot"/>
10+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value=""/>
11+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="run ${string_prompt:the test suite to run:unity8}"/>
12+<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
13+<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Unity8"/>
14+</launchConfiguration>
CMakeLists.txt+1
@@ -96,6 +96,7 @@ include(autopilot)
9696declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)
9797
9898set(SHELL_APP unity8)
99+set(DASH_APP unity8-dash)
99100set(SCOPE_TOOL unity-scope-tool)
100101
101102include_directories(
cmake/modules/QmlTest.cmake+2−2
@@ -135,7 +135,7 @@ macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS)
135135 set(testCommand
136136 LD_LIBRARY_PATH=${LD_PATH}
137137 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
138− -o ${CMAKE_BINARY_DIR}/${CLASSNAME}Test.xml,xunitxml
138+ -o ${CMAKE_BINARY_DIR}/test${CLASS_NAME}.xml,xunitxml
139139 -o -,txt)
140140
141141 add_qmltest_target(test${CLASS_NAME} "${testCommand}" FALSE TRUE)
@@ -151,7 +151,7 @@ macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS)
151151 LD_LIBRARY_PATH=${LD_PATH}
152152 xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
153153 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
154− -o ${CMAKE_BINARY_DIR}/${CLASS_NAME}Test.xml,xunitxml
154+ -o ${CMAKE_BINARY_DIR}/test${CLASS_NAME}.xml,xunitxml
155155 -o -,txt)
156156
157157 add_qmltest_target(xvfbtest${CLASS_NAME} "${xvfbtestCommand}" FALSE TRUE)
data/CMakeLists.txt+5−2
@@ -1,7 +1,10 @@
1−# generate desktop file
1+# 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)
34
45# install desktop files
5−install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
6+install(FILES
7+ ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
8+ ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
69 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
710 )
data/unity8-dash.confnew file+22
@@ -0,0 +1,22 @@
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+respawn
12+
13+pre-start script
14+ if [ -z "$UNITY_SCOPES_LIST" ]; then
15+ # FIXME: remove once we have this in dconf
16+ initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator"
17+ fi
18+
19+ initctl emit scope-ui-starting
20+end script
21+
22+exec ${BINARY:-unity8-dash} $ARGS --desktop_file_hint=/usr/share/applications/unity8-dash.desktop
data/unity8-dash.desktop.innew file+9
@@ -0,0 +1,9 @@
1+[Desktop Entry]
2+Type=Application
3+Name=Unity 8 Dash
4+Comment=The converged Unity shell dash
5+Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8-dash
6+Terminal=false
7+Icon=unity8
8+NoDisplay=true
9+X-Ubuntu-Touch=true
data/unity8.conf+1−7
@@ -1,7 +1,7 @@
11description "Unity Shell v8"
22author "Ricardo Mendoza <ricmm@ubuntu.com>"
33
4−emits scope-ui-starting indicator-services-start
4+emits indicator-services-start
55
66start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=ubuntu-touch-surfaceflinger)) and started dbus
77stop on desktop-end
@@ -34,11 +34,6 @@ pre-start script
3434 gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}"
3535 fi
3636
37− if [ -z "$UNITY_SCOPES_LIST" ]; then
38− # FIXME: remove once we have this in dconf
39− initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator"
40− fi
41−
4237 # Remove the socket if still there
4338 if [ -S "$MIR_SERVER_FILE" ]; then
4439 rm "$MIR_SERVER_FILE"
@@ -46,7 +41,6 @@ pre-start script
4641
4742 initctl set-env --global MIR_SERVER_PROMPT_FILE=1
4843
49− initctl emit scope-ui-starting
5044 initctl emit --no-wait indicator-services-start
5145end script
5246
debian/changelog+193
@@ -1,3 +1,196 @@
1+unity8 (8.00+14.10.20140806.1-0ubuntu1) utopic; urgency=low
2+
3+ [ Michal Hruby ]
4+ * Work with the scopes-v4 branch + departments->navigation renaming
5+
6+ [ Michał Sawicz ]
7+ * Hardcode art shape size for click scope local and predefined
8+ categories While at it, drop the fillmode of cards
9+ * Use the correct API in PageHeader. (LP: #1353048)
10+ * Refactor dash activity indicator. (LP: #1351539)
11+
12+ [ Albert Astals ]
13+ * Dash Departments fixes Update maxHeight manually since it depends on
14+ the position of the item and its parents and it can't know when the
15+ binding has to be updated Make parent stuff non interactive when the
16+ department list is shown
17+ * PageHeader: when on search clip y-coordinates otherwise the
18+ background spills out when on search (LP: #1350398)
19+ * Dash: Implement OverlayColor support in Cards
20+ * Hardcode art shape size for click scope local and predefined
21+ categories While at it, drop the fillmode of cards
22+ * Make test_departments test more stable There's various
23+ DashDepartments on the dash, make sure we're working over the one
24+ that is on screen, otherwise clicks don't end up where they should
25+ * Work with the scopes-v4 branch + departments->navigation renaming
26+ * Fixes for dash as app Load i18n catalog Process command line options
27+ Add the posibility to have a mouse touch adaptor (LP: #1353351)
28+ * Implement the Expandable Preview Widget Now TextSummary is not
29+ expandable by itself anymore, you have to use it inside an
30+ Expandable to get the behaviour
31+ * Add test prefix to xml output, seems CI needs it
32+
33+ [ Antti Kaijanmäki ]
34+ * Indicators: Adds new ModemInfoItem to be used with indicator-network
35+ (LP: #1329204)
36+
37+ [ Michael Terry ]
38+ * When the edge demo is running, don't show the greeter if the screen
39+ is turned off. This avoids an odd interaction where parts of the
40+ greeter are disabled but the edge demo isn't visible until you slide
41+ the greeter away. (LP: #1283425)
42+ * Don't hardcode the phablet password in our testing script.
43+
44+ [ Ying-Chun Liu ]
45+ * Add divider dots.
46+
47+ [ Mirco Müller ]
48+ * Make sure the TextField of a snap-decision notification has the
49+ active focus upon creation, thus the osk shows up right away. (LP:
50+ #1346867)
51+
52+ [ Andrea Cimitan ]
53+ * Add touchdown effect to dash cards.
54+ * Import Ubuntu.Components for preview image gallery to pick up
55+ default flicking speeds.
56+
57+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 06 Aug 2014 19:40:05 +0000
58+
59+unity8 (8.00+14.10.20140805-0ubuntu1) utopic; urgency=low
60+
61+ [ Michael Zanetti ]
62+ * Split the dash from the shell into a separate app (LP: #1232687)
63+
64+ [ Leo Arias ]
65+ * Update the autopilot tests to work with the new dash app.
66+
67+ [ Daniel d'Andrada ]
68+ * Split the dash from the shell into a separate app (LP: #1232687)
69+
70+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 05 Aug 2014 12:06:31 +0000
71+
72+unity8 (8.00+14.10.20140731.1-0ubuntu1) utopic; urgency=low
73+
74+ [ Gerry Boland ]
75+ * Fix the run.sh script - pretend to be running with qtmir and emit
76+ SIGSTOP at the right time
77+
78+ [ Ying-Chun Liu ]
79+ * Implement Attribute UI. (LP: #1282460)
80+
81+ [ Albert Astals ]
82+ * Hide search history popup as soon as you start typing As discussed
83+ with Mike and Saviq
84+ * Compile with for scopes-v3 unity-api
85+ * PageHeader: Unfocus search field when search entry is selected
86+ * Show search field if the search query changes
87+ * Test: Add a condition for art.height being > 0 means stuff has
88+ already been layouted a bit without it it can happen that we get 0
89+ for everything at startup and tests still pass
90+ * Remove leftover in test of an old headerless implementation
91+
92+ [ Michael Zanetti ]
93+ * Drop Recent apps category from Dash (LP: #1281092)
94+ * update launcher count emblems to match new spec (LP: #1338984)
95+
96+ [ Bill Filler ]
97+ * disable predictive text for dash search field (LP: #1340409)
98+
99+ [ CI bot ]
100+ * Resync trunk
101+
102+ [ Antti Kaijanmäki ]
103+ * DefaultIndicatorPage: use Loader status to determine the visible
104+ property. (LP: #1350555)
105+
106+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 31 Jul 2014 16:51:01 +0000
107+
108+unity8 (8.00+14.10.20140729.1-0ubuntu1) utopic; urgency=low
109+
110+ [ Michael Terry ]
111+ * Check user's pin/password using PAM, instead of a plaintext keyfile.
112+ New build dependency: libpam0g-dev for phone unlock with PAM (LP:
113+ #1234983)
114+
115+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 29 Jul 2014 23:36:30 +0000
116+
117+unity8 (8.00+14.10.20140729-0ubuntu1) utopic; urgency=medium
118+
119+ [ Gerry Boland ]
120+ [ Daniel d'Andrada ]
121+ * Re-architecture unity8 to use the QtMirCompositor library so that
122+ the Qt scenegraph renderer is used as the Mir compositor, and
123+ application surfaces are added to the QML scene as items.
124+
125+ [ Michael Zanetti ]
126+ * Port phone right-edge spread code to use QtCompositor
127+ * Add right-edge spread animation for tablet
128+
129+ [ Ubuntu daily release ]
130+ * New rebuild forced
131+
132+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 29 Jul 2014 15:07:32 +0000
133+
134+unity8 (7.90+14.10.20140725-0ubuntu1) utopic; urgency=low
135+
136+ [ CI bot ]
137+ * Resync trunk
138+
139+ [ Michał Sawicz ]
140+ * Fix the ap test for applications.
141+
142+ [ Albert Astals ]
143+ * Use deleteLater instead of a direct delete We are seeing a crash in
144+ QQuickWindowPrivate::polishItems because LVWPH is deleting items to
145+ polish from it's updatePolish which means the set in
146+ QQuickWindowPrivate::polishItems may end up with some yet-to-
147+ process-but-now-deleted items. Switching to deleteLater fixes this
148+
149+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 25 Jul 2014 10:47:34 +0000
150+
151+unity8 (7.90+14.10.20140724.1-0ubuntu1) utopic; urgency=low
152+
153+ [ Michael Zanetti ]
154+ * properly parent launcher items (LP: #1347902)
155+
156+ [ Michał Sawicz ]
157+ * Move the PyDev project files to the root, supporting .py scripts
158+ outside of tests/autopilot. Add Autopilot Run and List launch
159+ configurations to easily support debugging in Eclipse. Use
160+ add_unity8_mock macro in the Telephony plugin.
161+ * Drop FilterGrid and refactor height animations in GenericScopeView.
162+ Also implement forced category expansion. (LP: #1326470)
163+ * Move expansion button from section header to category footer. (LP:
164+ #1261300)
165+ * Fix expect-sigstop enviroment variable name. (LP: #1346819)
166+ * Make headerless categories easier Instead of having no header
167+ category (which is a bit confusing since the LVWPH code was designed
168+ so that when a category has no header it is because it shares the
169+ category with the previous one) what we have for headerless
170+ categories is a header of height 0, this way everything works as it
171+ should and results in cleaner code in the LVWPH and in
172+ GenericScopeView
173+ * Add support for header links.
174+ * Add dash PageHeader styling.
175+
176+ [ Albert Astals ]
177+ * Make headerless categories easier Instead of having no header
178+ category (which is a bit confusing since the LVWPH code was designed
179+ so that when a category has no header it is because it shares the
180+ category with the previous one) what we have for headerless
181+ categories is a header of height 0, this way everything works as it
182+ should and results in cleaner code in the LVWPH and in
183+ GenericScopeView
184+
185+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 24 Jul 2014 20:41:29 +0000
186+
187+unity8 (7.90+14.10.20140723.4-0ubuntu1) utopic; urgency=low
188+
189+ [ thomas-voss ]
190+ * Explicitly select gcc version.
191+
192+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 23 Jul 2014 15:32:41 +0000
193+
1194unity8 (7.90+14.10.20140721.1-0ubuntu1) utopic; urgency=low
2195
3196 [ Michael Terry ]
debian/control+9−5
@@ -7,6 +7,10 @@ Build-Depends: cmake,
77 debhelper (>= 9),
88 doxyqml,
99 graphviz,
10+# We rely on C++11 features, and to prevent from ABI breaks
11+# in libstdc++ causing us issues, we explicitly select a G++
12+# version.
13+ g++-4.9,
1014 libdee-qt5-dev (>= 3.2),
1115 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
1216 libgl1-mesa-dri,
@@ -15,12 +19,12 @@ Build-Depends: cmake,
1519 libgsettings-qt-dev,
1620 libhardware-dev,
1721 libhud-client2-dev,
18− libpay1-dev,
22+ libpam0g-dev,
23+ libpay2-dev,
1924 libpulse-dev,
2025 libqmenumodel-dev (>= 0.2.8),
2126 libqt5xmlpatterns5-dev,
22− libunity-api-dev (>= 7.85),
23− libunity-mir-dev,
27+ libunity-api-dev (>= 7.88),
2428 libusermetricsoutput1-dev,
2529 libxcb1-dev,
2630 pkg-config,
@@ -76,10 +80,10 @@ Provides: indicator-renderer,
7680Depends: gsettings-desktop-schemas,
7781 libcap2-bin,
7882 libglib2.0-bin,
79− libunity-mir1 (>= 0.4),
8083 qmenumodel-qml (>= 0.2.8),
8184 qml-module-qtquick-xmllistmodel,
8285 qtdeclarative5-gsettings1.0,
86+ qtdeclarative5-qtmir-plugin (>= 0.4),
8387 qtdeclarative5-ubuntu-settings-components (>= 0.3),
8488 qtdeclarative5-ubuntu-telephony0.1,
8589 unity-launcher-impl-3,
@@ -108,7 +112,7 @@ Depends: qtdeclarative5-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
108112 unity-application-impl-2,
109113 unity-notifications-impl-3,
110114 unity-plugin-scopes | unity-scopes-impl,
111− unity-scopes-impl-0,
115+ unity-scopes-impl-4,
112116 unity8-fake-env | unity-application-impl,
113117 ${misc:Depends},
114118Breaks: unity8 (<< 7.86),
debian/rules+7
@@ -1,11 +1,18 @@
11#!/usr/bin/make -f
22# -*- makefile -*-
33
4+include /usr/share/dpkg/default.mk
5+
46# Uncomment this to turn on verbose mode.
57#export DH_VERBOSE=1
68export DPKG_GENSYMBOLS_CHECK_LEVEL=4
79export NO_PNG_PKG_MANGLE=1
810
11+# Explicitly selecting a G{CC,++}-version here to avoid accidental
12+# ABI breaks introduced by toolchain updates.
13+export CC=$(DEB_HOST_GNU_TYPE)-gcc-4.9
14+export CXX=$(DEB_HOST_GNU_TYPE)-g++-4.9
15+
916%:
1017 dh $@ --parallel --fail-missing --with python2,python3
1118
debian/unity8.install+3
@@ -1,6 +1,9 @@
11data/unity8.conf usr/share/upstart/sessions/
2+data/unity8-dash.conf usr/share/upstart/sessions/
23usr/bin/unity8
4+usr/bin/unity8-dash
35usr/share/applications/unity8.desktop
6+usr/share/applications/unity8-dash.desktop
47usr/share/unity8/Greeter
58usr/share/unity8/Hud
69usr/share/unity8/Launcher
plugins/AccountsService/AccountsService.cpp+21−1
@@ -26,7 +26,8 @@ AccountsService::AccountsService(QObject* parent)
2626 m_service(new AccountsServiceDBusAdaptor(this)),
2727 m_user(qgetenv("USER")),
2828 m_demoEdges(false),
29− m_statsWelcomeScreen(false)
29+ m_statsWelcomeScreen(false),
30+ m_passwordDisplayHint(Keyboard)
3031{
3132 connect(m_service, SIGNAL(propertiesChanged(const QString &, const QString &, const QStringList &)),
3233 this, SLOT(propertiesChanged(const QString &, const QString &, const QStringList &)));
@@ -47,6 +48,7 @@ void AccountsService::setUser(const QString &user)
4748 updateDemoEdges();
4849 updateBackgroundFile();
4950 updateStatsWelcomeScreen();
51+ updatePasswordDisplayHint();
5052}
5153
5254bool AccountsService::demoEdges() const
@@ -70,6 +72,11 @@ bool AccountsService::statsWelcomeScreen() const
7072 return m_statsWelcomeScreen;
7173}
7274
75+AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const
76+{
77+ return m_passwordDisplayHint;
78+}
79+
7380void AccountsService::updateDemoEdges()
7481{
7582 auto demoEdges = m_service->getUserProperty(m_user, "com.canonical.unity.AccountsService", "demo-edges").toBool();
@@ -97,6 +104,15 @@ void AccountsService::updateStatsWelcomeScreen()
97104 }
98105}
99106
107+void AccountsService::updatePasswordDisplayHint()
108+{
109+ PasswordDisplayHint passwordDisplayHint = (PasswordDisplayHint)m_service->getUserProperty(m_user, "com.ubuntu.AccountsService.SecurityPrivacy", "PasswordDisplayHint").toInt();
110+ if (m_passwordDisplayHint != passwordDisplayHint) {
111+ m_passwordDisplayHint = passwordDisplayHint;
112+ Q_EMIT passwordDisplayHintChanged();
113+ }
114+}
115+
100116void AccountsService::propertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
101117{
102118 if (m_user != user) {
@@ -111,6 +127,10 @@ void AccountsService::propertiesChanged(const QString &user, const QString &inte
111127 if (changed.contains("StatsWelcomeScreen")) {
112128 updateStatsWelcomeScreen();
113129 }
130+ } else if (interface == "com.ubuntu.AccountsService.SecurityPrivacy") {
131+ if (changed.contains("PasswordDisplayHint")) {
132+ updatePasswordDisplayHint();
133+ }
114134 }
115135}
116136
plugins/AccountsService/AccountsService.h+13
@@ -27,6 +27,7 @@ class AccountsServiceDBusAdaptor;
2727class AccountsService: public QObject
2828{
2929 Q_OBJECT
30+ Q_ENUMS(PasswordDisplayHint)
3031 Q_PROPERTY (QString user
3132 READ user
3233 WRITE setUser
@@ -41,8 +42,16 @@ class AccountsService: public QObject
4142 Q_PROPERTY (bool statsWelcomeScreen
4243 READ statsWelcomeScreen
4344 NOTIFY statsWelcomeScreenChanged)
45+ Q_PROPERTY (PasswordDisplayHint passwordDisplayHint
46+ READ passwordDisplayHint
47+ NOTIFY passwordDisplayHintChanged)
4448
4549public:
50+ enum PasswordDisplayHint {
51+ Keyboard,
52+ Numeric,
53+ };
54+
4655 explicit AccountsService(QObject *parent = 0);
4756
4857 QString user() const;
@@ -51,12 +60,14 @@ public:
5160 void setDemoEdges(bool demoEdges);
5261 QString backgroundFile() const;
5362 bool statsWelcomeScreen() const;
63+ PasswordDisplayHint passwordDisplayHint() const;
5464
5565Q_SIGNALS:
5666 void userChanged();
5767 void demoEdgesChanged();
5868 void backgroundFileChanged();
5969 void statsWelcomeScreenChanged();
70+ void passwordDisplayHintChanged();
6071
6172private Q_SLOTS:
6273 void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
@@ -66,12 +77,14 @@ private:
6677 void updateDemoEdges();
6778 void updateBackgroundFile();
6879 void updateStatsWelcomeScreen();
80+ void updatePasswordDisplayHint();
6981
7082 AccountsServiceDBusAdaptor *m_service;
7183 QString m_user;
7284 bool m_demoEdges;
7385 QString m_backgroundFile;
7486 bool m_statsWelcomeScreen;
87+ PasswordDisplayHint m_passwordDisplayHint;
7588};
7689
7790#endif
plugins/AccountsService/plugin.cpp+1
@@ -33,5 +33,6 @@ void AccountsServicePlugin::registerTypes(const char *uri)
3333{
3434 Q_ASSERT(uri == QLatin1String("AccountsService"));
3535 qDBusRegisterMetaType<QList<QVariantMap>>();
36+ qRegisterMetaType<AccountsService::PasswordDisplayHint>("AccountsService::PasswordDisplayHint");
3637 qmlRegisterSingletonType<AccountsService>(uri, 0, 1, "AccountsService", service_provider);
3738}
plugins/Dash/CardAttributes.qmlnew file+65
@@ -0,0 +1,65 @@
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.2
18+import QtQuick.Layouts 1.1
19+import Ubuntu.Components 1.1
20+import Ubuntu.Settings.Components 0.1
21+
22+GridLayout {
23+ id: grid
24+ anchors {
25+ left: parent.left;
26+ right: parent.right;
27+ }
28+ columns: 2 + repeater.count % 2
29+ property alias model: repeater.model
30+ property var color
31+
32+ Repeater {
33+ id: repeater
34+ delegate: Row {
35+ spacing: units.gu(0.5)
36+ readonly property int column: index % grid.columns;
37+ Layout.alignment: {
38+ if (column == 0) return Qt.AlignLeft;
39+ if (column == grid.columns - 1 || index == repeater.count - 1) return Qt.AlignRight;
40+ if (column == 1) return Qt.AlignHCenter;
41+ }
42+ Layout.columnSpan: index == repeater.count - 1 && grid.columns == 3 && column == 1 ? 2 : 1
43+ Layout.maximumWidth: Math.max(icon.width, label.x + label.implicitWidth)
44+ Layout.fillWidth: true
45+ StatusIcon {
46+ id: icon
47+ height: units.gu(2)
48+ sets: ["actions", "status", "apps"]
49+ source: "icon" in modelData ? modelData["icon"] : ""
50+ }
51+ Label {
52+ id: label
53+ width: parent.width - x
54+ anchors.verticalCenter: parent.verticalCenter
55+ text: "value" in modelData ? modelData["value"] : "";
56+ elide: Text.ElideRight
57+ maximumLineCount: 1
58+ font.weight: "style" in modelData && modelData["style"] == "highlighted" ? Font.DemiBold : Font.Light
59+ fontSize: "small"
60+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale)
61+ color: grid.color
62+ }
63+ }
64+ }
65+}
plugins/Dash/CardCreator.js+100−17
@@ -71,19 +71,14 @@ var kArtShapeHolderCode = 'Item { \n\
7171 visible: image.status == Image.Ready; \n\
7272 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1; \n\
7373 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1; \n\
74− readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect; \n\
7574 Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; } \n\
76− onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings(); \n\
7775 Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); } \n\
7876 function updateWidthHeightBindings() { \n\
7977 if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) { \n\
8078 width = root.fixedArtShapeSize.width; \n\
8179 height = root.fixedArtShapeSize.height; \n\
82− } else if (aspectSmallerThanImageAspect) { \n\
83− width = Qt.binding(function() { return !visible ? 0 : image.width }); \n\
84− height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect }); \n\
8580 } else { \n\
86− width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect }); \n\
81+ width = Qt.binding(function() { return !visible ? 0 : image.width }); \n\
8782 height = Qt.binding(function() { return !visible ? 0 : image.height }); \n\
8883 } \n\
8984 } \n\
@@ -92,8 +87,7 @@ var kArtShapeHolderCode = 'Item { \n\
9287 source: cardData && cardData["art"] || ""; \n\
9388 cache: true; \n\
9489 asynchronous: root.asynchronous; \n\
95− fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop; \n\
96− readonly property real aspect: implicitWidth / implicitHeight; \n\
90+ fillMode: Image.PreserveAspectCrop; \n\
9791 width: %2; \n\
9892 height: %3; \n\
9993 } \n\
@@ -114,7 +108,7 @@ var kOverlayLoaderCode = 'Loader { \n\
114108 sourceComponent: ShaderEffect { \n\
115109 id: overlay; \n\
116110 height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
117− opacity: 0.6; \n\
111+ property color overlayColor: cardData && cardData["overlayColor"] || "#99000000"; \n\
118112 property var source: ShaderEffectSource { \n\
119113 id: shaderSource; \n\
120114 sourceItem: artShapeLoader.item; \n\
@@ -135,9 +129,10 @@ var kOverlayLoaderCode = 'Loader { \n\
135129 varying highp vec2 coord; \n\
136130 uniform sampler2D source; \n\
137131 uniform lowp float qt_Opacity; \n\
132+ uniform highp vec4 overlayColor; \n\
138133 void main() { \n\
139134 lowp vec4 tex = texture2D(source, coord); \n\
140− gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity; \n\
135+ gl_FragColor = vec4(overlayColor.r, overlayColor.g, overlayColor.b, 1) * qt_Opacity * overlayColor.a * tex.a; \n\
141136 }"; \n\
142137 } \n\
143138 }\n';
@@ -193,6 +188,21 @@ var kHeaderColumnCode = 'Column { \n\
193188 ] \n\
194189 }\n';
195190
191+// multiple column version of kHeaderColumnCode.
192+function kHeaderColumnCodeGenerator() {
193+ var headerColumnCodeTemplate = 'Column { \n\
194+ anchors.verticalCenter: parent.verticalCenter; \n\
195+ spacing: units.dp(2); \n\
196+ width: parent.width - x;\n\
197+ data: [ \n\
198+ %1 \n\
199+ ]\n\
200+ }\n';
201+ var args = Array.prototype.slice.call(arguments);
202+ var code = headerColumnCodeTemplate.arg(args.join(',\n'));
203+ return code;
204+}
205+
196206// %1 is used as anchors of mascotShapeLoader
197207var kMascotShapeLoaderCode = 'Loader { \n\
198208 id: mascotShapeLoader; \n\
@@ -224,7 +234,7 @@ var kMascotImageCode = 'Image { \n\
224234 }\n';
225235
226236// %1 is used as anchors of titleLabel
227−// %1 is used as color of titleLabel
237+// %2 is used as color of titleLabel
228238// %3 is used as extra condition for visible of titleLabel
229239var kTitleLabelCode = 'Label { \n\
230240 id: titleLabel; \n\
@@ -242,6 +252,16 @@ var kTitleLabelCode = 'Label { \n\
242252 horizontalAlignment: root.headerAlignment; \n\
243253 }\n';
244254
255+// %1 is used as anchors of touchdown effect
256+var kTouchdownCode = 'UbuntuShape { \n\
257+ id: touchdown; \n\
258+ objectName: "touchdown"; \n\
259+ anchors { %1 } \n\
260+ visible: root.pressed; \n\
261+ radius: "medium"; \n\
262+ borderSource: "radius_pressed.sci" \n\
263+ }\n';
264+
245265// %1 is used as anchors of subtitleLabel
246266// %2 is used as color of subtitleLabel
247267var kSubtitleLabelCode = 'Label { \n\
@@ -258,6 +278,15 @@ var kSubtitleLabelCode = 'Label { \n\
258278 horizontalAlignment: root.headerAlignment; \n\
259279 }\n';
260280
281+// %1 is used as anchors of attributesRow
282+var kAttributesRowCode = 'CardAttributes { \n\
283+ id: attributesRow; \n\
284+ objectName: "attributesRow"; \n\
285+ anchors { %1 } \n\
286+ color: %2; \n\
287+ model: cardData["attributes"]; \n\
288+ }\n';
289+
261290// %1 is used as top anchor of summary
262291// %2 is used as topMargin anchor of summary
263292// %3 is used as color of summary
@@ -308,6 +337,7 @@ function cardString(template, components) {
308337 var headerAsOverlay = hasArt && template && template["overlay"] === true && (hasTitle || hasMascot);
309338 var hasSubtitle = hasTitle && components["subtitle"] || false;
310339 var hasHeaderRow = hasMascot && hasTitle;
340+ var hasAttributes = hasTitle && components["attributes"] || false;
311341
312342 if (hasBackground) {
313343 code += kBackgroundLoaderCode;
@@ -377,6 +407,14 @@ function cardString(template, components) {
377407 code += 'readonly property int headerHeight: row.height;\n'
378408 } else if (hasMascot) {
379409 code += 'readonly property int headerHeight: mascotImage.height;\n'
410+ } else if (hasAttributes) {
411+ if (hasTitle && hasSubtitle) {
412+ code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + attributesRow.height + attributesRow.anchors.topMargin;\n'
413+ } else if (hasTitle) {
414+ code += 'readonly property int headerHeight: titleLabel.height + attributesRow.height + attributesRow.anchors.topMargin;\n'
415+ } else {
416+ code += 'readonly property int headerHeight: attributesRow.height;\n'
417+ }
380418 } else if (hasSubtitle) {
381419 code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;\n'
382420 } else if (hasTitle) {
@@ -425,10 +463,12 @@ function cardString(template, components) {
425463
426464 var titleAnchors;
427465 var subtitleAnchors;
428− if (hasMascot && hasSubtitle) {
466+ var attributesAnchors;
467+ if (hasMascot && (hasSubtitle || hasAttributes)) {
429468 // Using row + column
430469 titleAnchors = 'left: parent.left; right: parent.right';
431470 subtitleAnchors = titleAnchors;
471+ attributesAnchors = subtitleAnchors;
432472 } else if (hasMascot) {
433473 // Using row + label
434474 titleAnchors = 'verticalCenter: parent.verticalCenter;\n'
@@ -438,11 +478,13 @@ function cardString(template, components) {
438478 titleAnchors = 'left: parent.left; \n\
439479 leftMargin: units.gu(1); \n\
440480 right: parent.right; \n\
481+ rightMargin: units.gu(1); \n\
441482 top: overlayLoader.top; \n\
442483 topMargin: units.gu(1);\n';
443484 } else {
444485 // Using anchors to the mascot/parent
445− titleAnchors = "right: parent.right;";
486+ titleAnchors = "right: parent.right;\n";
487+ titleAnchors += "rightMargin: units.gu(1);\n";
446488 titleAnchors += headerLeftAnchor;
447489 titleAnchors += headerVerticalAnchors;
448490 if (!headerLeftAnchorHasMargin) {
@@ -452,8 +494,19 @@ function cardString(template, components) {
452494 subtitleAnchors = 'left: titleLabel.left; \n\
453495 leftMargin: titleLabel.leftMargin; \n\
454496 right: titleLabel.right; \n\
497+ rightMargin: titleLabel.rightMargin; \n\
455498 top: titleLabel.bottom; \n\
456499 topMargin: units.dp(2);\n';
500+ if (hasSubtitle) {
501+ attributesAnchors = 'left: subtitleLabel.left; \n\
502+ leftMargin: subtitleLabel.leftMargin; \n\
503+ right: subtitleLabel.right; \n\
504+ rightMargin: subtitleLabel.rightMargin; \n\
505+ top: subtitleLabel.bottom; \n\
506+ topMargin: units.dp(2);\n';
507+ } else {
508+ attributesAnchors = subtitleAnchors;
509+ }
457510 }
458511
459512 var titleLabelVisibleExtra = (headerAsOverlay ? '&& overlayLoader.active': '');
@@ -463,11 +516,27 @@ function cardString(template, components) {
463516 subtitleCode += kSubtitleLabelCode.arg(subtitleAnchors).arg(color);
464517 }
465518
466− if (hasMascot && hasSubtitle) {
519+ if (hasMascot && (hasSubtitle || hasAttributes)) {
467520 // If using row + column wrap the code in the column
468521 titleSubtitleCode = kHeaderColumnCode.arg(titleCode).arg(subtitleCode);
522+ if (hasSubtitle && hasAttributes) {
523+ var attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(color);
524+ titleSubtitleCode = kHeaderColumnCodeGenerator(titleCode, subtitleCode, attributesCode);
525+ } else if (hasSubtitle) {
526+ titleSubtitleCode = kHeaderColumnCode.arg(titleCode).arg(subtitleCode);
527+ } else if (hasAttributes) {
528+ var attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(color);
529+ titleSubtitleCode = kHeaderColumnCode.arg(titleCode).arg(attributesCode);
530+ }
469531 } else {
470− titleSubtitleCode = titleCode + subtitleCode;
532+ titleSubtitleCode = titleCode;
533+ if (hasSubtitle) {
534+ titleSubtitleCode = titleSubtitleCode + subtitleCode;
535+ }
536+ if (hasAttributes) {
537+ var attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(color);
538+ titleSubtitleCode = titleSubtitleCode + attributesCode;
539+ }
471540 }
472541 }
473542
@@ -487,6 +556,7 @@ function cardString(template, components) {
487556 else if (headerAsOverlay && hasArt) summaryTopAnchor = "artShapeHolder.bottom";
488557 else if (hasHeaderRow) summaryTopAnchor = "row.bottom";
489558 else if (hasMascot) summaryTopAnchor = "mascotImage.bottom";
559+ else if (hasAttributes) summaryTopAnchor = "attributesRow.bottom";
490560 else if (hasSubtitle) summaryTopAnchor = "subtitleLabel.bottom";
491561 else if (hasTitle) summaryTopAnchor = "titleLabel.bottom";
492562 else if (hasArt) summaryTopAnchor = "artShapeHolder.bottom";
@@ -499,17 +569,29 @@ function cardString(template, components) {
499569 color = 'root.scopeStyle ? root.scopeStyle.foreground : "grey"';
500570 }
501571
502− var summaryTopMargin = (hasMascot || hasSubtitle ? 'anchors.margins' : '0');
572+ var summaryTopMargin = (hasMascot || hasSubtitle || hasAttributes ? 'anchors.margins' : '0');
503573
504574 code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(color);
505575 }
506576
577+ var touchdownAnchors;
578+ if (hasBackground) {
579+ touchdownAnchors = 'fill: backgroundLoader';
580+ } else if (hasArt && !hasMascot && !hasSummary) {
581+ touchdownAnchors = 'fill: artShapeHolder';
582+ } else {
583+ touchdownAnchors = 'fill: root'
584+ }
585+ code += kTouchdownCode.arg(touchdownAnchors);
586+
507587 if (hasSummary) {
508588 code += 'implicitHeight: summary.y + summary.height + (summary.text ? units.gu(1) : 0);\n';
509589 } else if (hasHeaderRow) {
510590 code += 'implicitHeight: row.y + row.height + units.gu(1);\n';
511591 } else if (hasMascot) {
512592 code += 'implicitHeight: mascotImage.y + mascotImage.height;\n';
593+ } else if (hasAttributes) {
594+ code += 'implicitHeight: attributesRow.y + attributesRow.height + units.gu(1);\n';
513595 } else if (hasSubtitle) {
514596 code += 'implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
515597 } else if (hasTitle) {
@@ -526,8 +608,9 @@ function cardString(template, components) {
526608function createCardComponent(parent, template, components) {
527609 var imports = 'import QtQuick 2.2; \n\
528610 import Ubuntu.Components 0.1; \n\
529− import Ubuntu.Thumbnailer 0.1;\n';
611+ import Dash 0.1;\n';
530612 var card = cardString(template, components);
531613 var code = imports + 'Component {\n' + card + '}\n';
614+
532615 return Qt.createQmlObject(code, parent, "createCardComponent");
533616}
plugins/Dash/ScopeStyle.qml+17−8
@@ -38,14 +38,20 @@ QtObject {
3838 /// Color used for text and symbolic icons
3939 readonly property color foreground: "foreground-color" in style ? style["foreground-color"] : d.defaultDark
4040
41+ /// Luminance of the foreground color
42+ readonly property real foregroundLuminance: foreground ? luminance(foreground) : d.defaultForegroundLuminance
43+
4144 /// Color used for the overall background
4245 readonly property color background: "background-color" in style ? style["background-color"] : "transparent"
4346
47+ /// Luminance of the foreground color
48+ readonly property real backgroundLuminance: background ? luminance(background) : d.defaultBackgroundLuminance
49+
4450 /*! \brief Luminance threshold for switching between fore and background color
4551
4652 \note If background colour is not fully opaque, it's not taken into account.
4753 */
48− readonly property real threshold: background.a !== 1.0 ? d.foregroundLuminance : (d.foregroundLuminance + d.backgroundLuminance) / 2
54+ readonly property real threshold: background.a !== 1.0 ? foregroundLuminance : (foregroundLuminance + backgroundLuminance) / 2
4955
5056 /*! \brief The lighter of foreground and background colors
5157
@@ -53,8 +59,8 @@ QtObject {
5359 and defaults to the theme-provided light color.
5460 */
5561 readonly property color light: {
56− if (background.a !== 1.0) return d.foregroundLuminance > d.defaultLightLuminance ? foreground : d.defaultLight;
57− return d.foregroundLuminance > d.backgroundLuminance ? foreground : background;
62+ if (background.a !== 1.0) return foregroundLuminance > d.defaultLightLuminance ? foreground : d.defaultLight;
63+ return foregroundLuminance > backgroundLuminance ? foreground : background;
5864 }
5965
6066 /*! \brief The darker of foreground and background colors
@@ -63,18 +69,21 @@ QtObject {
6369 and defaults to the theme-provided dark color.
6470 */
6571 readonly property color dark: {
66− if (background.a !== 1.0) return d.foregroundLuminance < d.defaultDarkLuminance ? foreground : d.defaultDark;
67− return d.foregroundLuminance < d.backgroundLuminance ? foreground : background;
72+ if (background.a !== 1.0) return foregroundLuminance < d.defaultDarkLuminance ? foreground : d.defaultDark;
73+ return foregroundLuminance < backgroundLuminance ? foreground : background;
6874 }
6975
7076 /// Source of the logo image for the header
7177 readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
7278
79+ /// Background style for the header
80+ readonly property url headerBackground: "background" in d.headerStyle ? d.headerStyle["background"] : ""
81+
82+ /// Foreground color for the header
83+ readonly property color headerForeground: "foreground-color" in d.headerStyle ? d.headerStyle["foreground-color"] : foreground
84+
7385 //! @cond
7486 property var d: QtObject {
75− readonly property real foregroundLuminance: luminance(foreground)
76− readonly property real backgroundLuminance: luminance(background)
77−
7887 // FIXME: should be taken from the theme
7988 readonly property color defaultLight: "white"
8089 readonly property color defaultDark: "grey"
plugins/Dash/listviewwithpageheader.cpp+1−6
@@ -141,8 +141,6 @@ void ListViewWithPageHeader::ListItem::setCulled(bool culled)
141141void ListViewWithPageHeader::ListItem::setSectionItem(QQuickItem *sectionItem)
142142{
143143 m_sectionItem = sectionItem;
144− QQmlContext *context = QQmlEngine::contextForObject(m_item)->parentContext();
145− context->setContextProperty(QLatin1String("hasSectionHeader"), QVariant::fromValue<bool>(sectionItem != nullptr));
146144}
147145
148146ListViewWithPageHeader::ListViewWithPageHeader()
@@ -658,7 +656,7 @@ void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
658656 if (flags & QQmlDelegateModel::Destroyed) {
659657 item->setParentItem(nullptr);
660658 }
661− delete listItem->sectionItem();
659+ listItem->sectionItem()->deleteLater();
662660 delete listItem;
663661}
664662
@@ -685,8 +683,6 @@ QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyI
685683 return nullptr;
686684
687685 const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
688− if (section.isEmpty())
689− return nullptr;
690686
691687 if (modelIndex > 0) {
692688 const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
@@ -877,7 +873,6 @@ void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
877873 QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
878874 context->setContextProperty(QLatin1String("ListViewWithPageHeader"), this);
879875 context->setContextProperty(QLatin1String("heightToClip"), QVariant::fromValue<int>(0));
880− context->setContextProperty(QLatin1String("hasSectionHeader"), QVariant::fromValue<bool>(false));
881876 if (modelIndex == m_asyncRequestedIndex) {
882877 createItem(modelIndex, false);
883878 refill();
plugins/Dash/qmldir+1
@@ -3,3 +3,4 @@ plugin Dash-qml
33typeinfo Dash.qmltypes
44singleton CardCreatorCache 0.1 CardCreatorCache.qml
55ScopeStyle 0.1 ScopeStyle.qml
6+CardAttributes 0.1 CardAttributes.qml
plugins/LightDM/plugin.cpp+2
@@ -69,6 +69,8 @@ void LightDMPlugin::registerTypes(const char *uri)
6969 qmlRegisterType<UserMetricsOutput::ColorTheme>();
7070
7171 Q_ASSERT(uri == QLatin1String("LightDM"));
72+ qRegisterMetaType<QLightDM::Greeter::MessageType>("QLightDM::Greeter::MessageType");
73+ qRegisterMetaType<QLightDM::Greeter::PromptType>("QLightDM::Greeter::PromptType");
7274 qmlRegisterSingletonType<Greeter>(uri, 0, 1, "Greeter", greeter_provider);
7375 qmlRegisterSingletonType<UsersModel>(uri, 0, 1, "Users", users_provider);
7476 qmlRegisterUncreatableType<QLightDM::UsersModel>(uri, 0, 1, "UserRoles", "Type is not instantiable");
plugins/Ubuntu/Payments/CMakeLists.txt+1−1
@@ -14,7 +14,7 @@ qt5_use_modules(Payments Qml Quick DBus Core)
1414
1515add_unity8_plugin(Ubuntu.Payments 0.1 Ubuntu/Payments TARGETS Payments)
1616
17−pkg_check_modules(LIBPAY REQUIRED pay-1)
17+pkg_check_modules(LIBPAY REQUIRED pay-2)
1818add_definitions(${LIBPAY_CFLAGS} ${LIBPAY_CFLAGS_OTHER})
1919
2020target_link_libraries(Payments ${LIBPAY_LDFLAGS})
plugins/Unity/CMakeLists.txt+1
@@ -1,3 +1,4 @@
11add_subdirectory(Indicators)
22add_subdirectory(Launcher)
33add_subdirectory(Session)
4+add_subdirectory(DashCommunicator)
plugins/Unity/DashCommunicator/CMakeLists.txtnew file+19
@@ -0,0 +1,19 @@
1+include_directories(
2+ ${CMAKE_CURRENT_SOURCE_DIR}
3+)
4+
5+set(QMLDASHCOMMUNICATORPLUGIN_SRC
6+ plugin.cpp
7+ dbusdashcommunicatorservice.cpp
8+ dashcommunicatorservice.cpp
9+ dashcommunicator.cpp
10+ )
11+
12+add_library(DashCommunicator-qml MODULE
13+ ${QMLDASHCOMMUNICATORPLUGIN_SRC}
14+ )
15+
16+qt5_use_modules(DashCommunicator-qml DBus Qml)
17+
18+# export the qmldir and qmltypes files
19+add_unity8_plugin(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS DashCommunicator-qml)
plugins/Unity/DashCommunicator/dashcommunicator.cppnew file+43
@@ -0,0 +1,43 @@
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+
19+#include <QObject>
20+#include <QDBusConnection>
21+#include <QDBusInterface>
22+#include <QDebug>
23+
24+DashCommunicator::DashCommunicator(QObject *parent):
25+ QObject(parent)
26+{
27+}
28+
29+DashCommunicator::~DashCommunicator()
30+{
31+}
32+
33+
34+void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset)
35+{
36+ QDBusConnection connection = QDBusConnection::sessionBus();
37+ QDBusInterface dashIface ("com.canonical.UnityDash",
38+ "/com/canonical/UnityDash",
39+ "",
40+ connection);
41+
42+ dashIface.call("SetCurrentScope", scopeId, animate, reset);
43+}
plugins/Unity/DashCommunicator/dashcommunicator.hnew 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+#ifndef DASHCOMMUNICATOR_H
18+#define DASHCOMMUNICATOR_H
19+
20+#include <QObject>
21+
22+class DashCommunicator: public QObject
23+{
24+ Q_OBJECT
25+ Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26+
27+public:
28+ DashCommunicator(QObject *parent = 0);
29+ ~DashCommunicator();
30+
31+public Q_SLOTS:
32+ void setCurrentScope(const QString &scopeId, bool animate, bool reset);
33+};
34+
35+#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(const QString &scopeId, bool animate, bool reset);
33+
34+private:
35+ DBusDashCommunicatorService *m_dbusService;
36+};
37+
38+#endif // DBUSUNITYSESSIONSERVICE_H
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cppnew 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+#include "dbusdashcommunicatorservice.h"
18+
19+#include <QDBusConnection>
20+#include <QDBusInterface>
21+#include <QDebug>
22+
23+DBusDashCommunicatorService::DBusDashCommunicatorService(QObject *parent):
24+ QObject(parent)
25+{
26+ QDBusConnection connection = QDBusConnection::sessionBus();
27+
28+ connection.registerService("com.canonical.UnityDash");
29+ connection.registerObject("/com/canonical/UnityDash", this, QDBusConnection::ExportScriptableSlots);
30+}
31+
32+DBusDashCommunicatorService::~DBusDashCommunicatorService()
33+{
34+}
35+
36+void DBusDashCommunicatorService::SetCurrentScope(const QString &scopeId, bool animate, bool reset)
37+{
38+ Q_EMIT setCurrentScopeRequested(scopeId, animate, reset);
39+}
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 <QObject>
21+
22+class DBusDashCommunicatorService: public QObject
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(const QString &scopeId, bool animate, bool reset);
33+
34+public Q_SLOTS:
35+ Q_SCRIPTABLE void SetCurrentScope(const QString &scopeId, bool animate, bool reset);
36+
37+};
38+
39+#endif // DBUSUNITYSESSIONSERVICE_H
plugins/Unity/DashCommunicator/plugin.cppnew file+31
@@ -0,0 +1,31 @@
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+ Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator"));
29+ qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService");
30+ qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator");
31+}
plugins/Unity/DashCommunicator/plugin.hnew file+34
@@ -0,0 +1,34 @@
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+#ifndef DASHCOMMUNICATOR_PLUGIN_H
20+#define DASHCOMMUNICATOR_PLUGIN_H
21+
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlExtensionPlugin>
24+
25+class DashCommunicatorPlugin : public QQmlExtensionPlugin
26+{
27+ Q_OBJECT
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29+
30+public:
31+ void registerTypes(const char *uri);
32+};
33+
34+#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/Launcher/launchermodel.cpp+8−2
@@ -141,7 +141,8 @@ void LauncherModel::pin(const QString &appId, int index)
141141 beginInsertRows(QModelIndex(), index, index);
142142 LauncherItem *item = new LauncherItem(appId,
143143 m_backend->displayName(appId),
144− m_backend->icon(appId));
144+ m_backend->icon(appId),
145+ this);
145146 item->setPinned(true);
146147 m_list.insert(index, item);
147148 endInsertRows();
@@ -316,6 +317,11 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
316317 return;
317318 }
318319
320+ if (app->appId() == "unity8-dash") {
321+ // Not adding the dash app
322+ return;
323+ }
324+
319325 bool found = false;
320326 Q_FOREACH(LauncherItem *item, m_list) {
321327 if (app->appId() == item->appId()) {
@@ -326,7 +332,7 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
326332 if (found) {
327333 // Shall we paint some running/recent app highlight? If yes, do it here.
328334 } else {
329− LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString());
335+ LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString(), this);
330336 item->setRecent(true);
331337 item->setFocused(app->focused());
332338
plugins/Utils/CMakeLists.txt+1
@@ -15,6 +15,7 @@ set(QMLPLUGIN_SRC
1515 qsortfilterproxymodelqml.cpp
1616 timeformatter.cpp
1717 unitymenumodelpaths.cpp
18+ windowkeysfilter.cpp
1819 easingcurve.cpp
1920 plugin.cpp
2021 )
plugins/Utils/easingcurve.cpp+5−1
@@ -34,7 +34,11 @@ QEasingCurve::Type EasingCurve::type() const
3434
3535void EasingCurve::setType(const QEasingCurve::Type &type)
3636{
37− m_easingCurve.setType(type);
37+ // FIXME: Working around bug https://bugreports.qt-project.org/browse/QTBUG-38686 here
38+ QEasingCurve newCurve;
39+ newCurve.setType(type);
40+ newCurve.setPeriod(m_easingCurve.period());
41+ m_easingCurve = newCurve;
3842 Q_EMIT typeChanged();
3943}
4044
plugins/Utils/plugin.cpp+2
@@ -30,6 +30,7 @@
3030#include "qsortfilterproxymodelqml.h"
3131#include "timeformatter.h"
3232#include "unitymenumodelpaths.h"
33+#include "windowkeysfilter.h"
3334#include "easingcurve.h"
3435
3536void UtilsPlugin::registerTypes(const char *uri)
@@ -40,6 +41,7 @@ void UtilsPlugin::registerTypes(const char *uri)
4041 qmlRegisterType<QSortFilterProxyModelQML>(uri, 0, 1, "SortFilterProxyModel");
4142 qmlRegisterType<UnityMenuModelPaths>(uri, 0, 1, "UnityMenuModelPaths");
4243 qmlRegisterType<TimeFormatter>(uri, 0, 1, "TimeFormatter");
44+ qmlRegisterType<WindowKeysFilter>(uri, 0, 1, "WindowKeysFilter");
4345 qmlRegisterType<GDateTimeFormatter>(uri, 0, 1, "GDateTimeFormatter");
4446 qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
4547}
plugins/Utils/windowkeysfilter.cppnew file+57
@@ -0,0 +1,57 @@
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+ * Author: Daniel d'Andrada <daniel.dandrada@canonical.com>
17+ */
18+
19+#include "windowkeysfilter.h"
20+
21+#include <QQuickWindow>
22+
23+WindowKeysFilter::WindowKeysFilter(QQuickItem *parent)
24+ : QQuickItem(parent)
25+{
26+ connect(this, &QQuickItem::windowChanged,
27+ this, &WindowKeysFilter::setupFilterOnWindow);
28+}
29+
30+bool WindowKeysFilter::eventFilter(QObject *watched, QEvent *event)
31+{
32+ Q_ASSERT(!m_filteredWindow.isNull());
33+ Q_ASSERT(watched == static_cast<QObject*>(m_filteredWindow.data()));
34+
35+ if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
36+ // Let QML see this event and decide if it does not want it
37+ event->accept();
38+ QCoreApplication::sendEvent(this, event);
39+ return event->isAccepted();
40+ } else {
41+ // Not interested
42+ return false;
43+ }
44+}
45+
46+void WindowKeysFilter::setupFilterOnWindow(QQuickWindow *window)
47+{
48+ if (!m_filteredWindow.isNull()) {
49+ m_filteredWindow->removeEventFilter(this);
50+ m_filteredWindow.clear();
51+ }
52+
53+ if (window) {
54+ window->installEventFilter(this);
55+ m_filteredWindow = window;
56+ }
57+}
plugins/Utils/windowkeysfilter.hnew file+51
@@ -0,0 +1,51 @@
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+ * Author: Daniel d'Andrada <daniel.dandrada@canonical.com>
17+ */
18+
19+#ifndef UNITY_WINDOWKEYSFILTER_H
20+#define UNITY_WINDOWKEYSFILTER_H
21+
22+#include <QQuickItem>
23+#include <QPointer>
24+
25+/*
26+ Receives all key events that arrive in the QQuickWindow where this item is placed.
27+
28+ Rejected key events will be allowed to be processed normally by the QQuickWindow whereas
29+ accepted ones will be filtered out. Events are accepted by default, so make sure you reject
30+ the keys you're not interested in.
31+
32+ If more than one WindowKeysFilter exist in the same QML scene (and thus in the same QQuickWindow)
33+ they will be called in the order of creation, which can be tricky to assess. So the best practice
34+ is to have at most one WindowKeysFilter per QML scene.
35+ */
36+class WindowKeysFilter : public QQuickItem
37+{
38+ Q_OBJECT
39+public:
40+ WindowKeysFilter(QQuickItem *parent = 0);
41+
42+ bool eventFilter(QObject *watched, QEvent *event);
43+
44+private Q_SLOTS:
45+ void setupFilterOnWindow(QQuickWindow *window);
46+
47+private:
48+ QPointer<QQuickWindow> m_filteredWindow;
49+};
50+
51+#endif // UNITY_WINDOWKEYSFILTER_H
po/am.po+30−22
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-20 18:16+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-08-04 16:30+0000\n"
1212"Last-Translator: samson <Unknown>\n"
1313"Language-Team: Amharic <am@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-21 07:05+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-08-05 06:45+0000\n"
18+"X-Generator: Launchpad (build 17147)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -28,7 +28,7 @@ msgstr "አቋራጭ መለያያ"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
31−msgstr ""
31+msgstr "መግቢያውን መዝለያ"
3232
3333#: qml/Components/EdgeDemo.qml:113
3434msgid "Right edge"
@@ -36,7 +36,7 @@ msgstr "የቀኝ ጠርዝ"
3636
3737#: qml/Components/EdgeDemo.qml:114
3838msgid "Try swiping from the right edge to unlock the phone"
39−msgstr ""
39+msgstr "ስልኩን ለመክፈት ከ ቀኝ ጠርዝ በኩል ወደ ግራ ይጥረጉ"
4040
4141#: qml/Components/EdgeDemo.qml:145
4242msgid "Top edge"
@@ -44,7 +44,7 @@ msgstr "የላይ ጠርዝ"
4444
4545#: qml/Components/EdgeDemo.qml:146
4646msgid "Try swiping from the top edge to access the indicators"
47−msgstr ""
47+msgstr "ጠቋሚዎች ጋር ለመድረስ ከ ላይ ጠርዝ በኩል ወደ ታች ይጥረጉ"
4848
4949#: qml/Components/EdgeDemo.qml:171
5050msgid "Close"
@@ -52,7 +52,7 @@ msgstr "መዝጊያ"
5252
5353#: qml/Components/EdgeDemo.qml:172
5454msgid "Swipe up again to close the settings screen"
55−msgstr ""
55+msgstr "የማሰናጃውን መመልከቻ ለመዝጋት እንደገና ወደ ላይ ይጥረጉ"
5656
5757#: qml/Components/EdgeDemo.qml:199
5858msgid "Left edge"
@@ -60,11 +60,11 @@ msgstr "የግራ ጠርዝ"
6060
6161#: qml/Components/EdgeDemo.qml:200
6262msgid "Swipe from the left to reveal the launcher for quick access to apps"
63−msgstr ""
63+msgstr "ከ ግራ በኩል ወደ ቀኝ ይጥረጉ በፍጥነት መተግበሪያዎች ጋር ለመድረስ እና ለማስጀመር"
6464
6565#: qml/Components/EdgeDemo.qml:227
6666msgid "Well done"
67−msgstr ""
67+msgstr "ጥሩ አድረገዋል"
6868
6969#: qml/Components/EdgeDemo.qml:228
7070msgid ""
@@ -80,10 +80,6 @@ msgstr "የ ድንገተኛ ጥሪ"
8080msgid "OK"
8181msgstr "እሺ"
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "በቅርብ የፈለጉዋቸው"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr "ጨርሷል"
105101msgid "See more"
106102msgstr "ተጨማሪ መመልከቻ"
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr "አነስተኛ መመልከቻ"
111107
@@ -113,6 +109,10 @@ msgstr "አነስተኛ መመልከቻ"
113109msgid "Recent"
114110msgstr "የቅርብ ጊዜ"
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr "ሁሉንም መመልከቻ"
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr "ተጨማሪ..."
@@ -121,21 +121,21 @@ msgstr "ተጨማሪ..."
121121msgid "Less..."
122122msgstr "አነስተኛ..."
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126−msgstr ""
126+msgstr "ለዚህ ደረጃ ይስጡ"
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130−msgstr ""
130+msgstr "ግምገማ መጨመሪያ"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "መላኪያ"
135135
136136#: qml/Greeter/Greeter.qml:157
137137msgid "Swipe to unlock"
138−msgstr ""
138+msgstr "ለመክፈት ይጥረጉ"
139139
140140#: qml/Hud/HudParametrizedActionsPage.qml:132
141141msgid "Confirm"
@@ -165,9 +165,17 @@ msgstr "የመግቢያ ቃል ማሳያ"
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr "ስብሰባ"
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170−msgstr ""
178+msgstr "ወረፋ በመጠበቅ ላይ…"
171179
172180#: qml/Panel/Indicators/MenuItemFactory.qml:587
173181msgid "Downloading"
po/ar.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-05-22 08:22+0000\n"
1212"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
1313"Language-Team: Arabic <ar@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -83,10 +83,6 @@ msgstr "مكالمة طوارئ"
8383msgid "OK"
8484msgstr ""
8585
86−#: qml/Components/PageHeader.qml:366
87−msgid "Recent searches"
88−msgstr "عمليات البحث الأخيرة"
89−
9086#: qml/Components/PassphraseLockscreen.qml:60
9187#, qt-format
9288msgid "Hello %1"
@@ -108,7 +104,7 @@ msgstr ""
108104msgid "See more"
109105msgstr "شاهد المزيد"
110106
111−#: qml/Components/SeeMore.qml:58
107+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
112108msgid "See less"
113109msgstr "شاهد أقل"
114110
@@ -116,6 +112,10 @@ msgstr "شاهد أقل"
116112msgid "Recent"
117113msgstr "استُخدمت مؤخرًا"
118114
115+#: qml/Dash/GenericScopeView.qml:330
116+msgid "See all"
117+msgstr ""
118+
119119#: qml/Dash/Previews/PreviewActionCombo.qml:34
120120msgid "More..."
121121msgstr "المزيد..."
@@ -124,15 +124,15 @@ msgstr "المزيد..."
124124msgid "Less..."
125125msgstr "أقل..."
126126
127−#: qml/Dash/Previews/PreviewRatingInput.qml:82
127+#: qml/Dash/Previews/PreviewRatingInput.qml:81
128128msgid "Rate this"
129129msgstr "قيّم ذلك"
130130
131−#: qml/Dash/Previews/PreviewRatingInput.qml:128
131+#: qml/Dash/Previews/PreviewRatingInput.qml:126
132132msgid "Add a review"
133133msgstr "أضف تعليق"
134134
135−#: qml/Dash/Previews/PreviewRatingInput.qml:168
135+#: qml/Dash/Previews/PreviewRatingInput.qml:166
136136msgid "Send"
137137msgstr "أرسل"
138138
@@ -168,6 +168,14 @@ msgstr "عرض كلمة السر"
168168msgid "Please enter SIM PIN"
169169msgstr "من فضلك أدخِل رقم التعريف الشخصي لبطاقة SIM"
170170
171+#: qml/Panel/ActiveCallHint.qml:77
172+msgid "Tap to return to call..."
173+msgstr ""
174+
175+#: qml/Panel/ActiveCallHint.qml:90
176+msgid "Conference"
177+msgstr ""
178+
171179#: qml/Panel/Indicators/MenuItemFactory.qml:583
172180msgid "In queue…"
173181msgstr ""
po/ast.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-15 16:32+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-25 16:51+0000\n"
1212"Last-Translator: ivarela <ivarela@ubuntu.com>\n"
1313"Language-Team: Asturian <ast@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-16 07:27+0000\n"
18−"X-Generator: Launchpad (build 17112)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -84,10 +84,6 @@ msgstr "Llamada d'emerxencia"
8484msgid "OK"
8585msgstr "Aceutar"
8686
87−#: qml/Components/PageHeader.qml:366
88−msgid "Recent searches"
89−msgstr "Busques recientes"
90−
9187#: qml/Components/PassphraseLockscreen.qml:60
9288#, qt-format
9389msgid "Hello %1"
@@ -109,7 +105,7 @@ msgstr "FECHO"
109105msgid "See more"
110106msgstr "Ver más"
111107
112−#: qml/Components/SeeMore.qml:58
108+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
113109msgid "See less"
114110msgstr "Ver menos"
115111
@@ -117,6 +113,10 @@ msgstr "Ver menos"
117113msgid "Recent"
118114msgstr "Reciente"
119115
116+#: qml/Dash/GenericScopeView.qml:330
117+msgid "See all"
118+msgstr "Ver too"
119+
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
122122msgstr "Más…"
@@ -125,15 +125,15 @@ msgstr "Más…"
125125msgid "Less..."
126126msgstr "Menos…"
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:82
128+#: qml/Dash/Previews/PreviewRatingInput.qml:81
129129msgid "Rate this"
130130msgstr "Valorar esto"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:128
132+#: qml/Dash/Previews/PreviewRatingInput.qml:126
133133msgid "Add a review"
134134msgstr "Amestar una reseña"
135135
136−#: qml/Dash/Previews/PreviewRatingInput.qml:168
136+#: qml/Dash/Previews/PreviewRatingInput.qml:166
137137msgid "Send"
138138msgstr "Unviar"
139139
@@ -169,6 +169,14 @@ msgstr "Amosar contraseña"
169169msgid "Please enter SIM PIN"
170170msgstr "Escribi'l PIN de la SIM"
171171
172+#: qml/Panel/ActiveCallHint.qml:77
173+msgid "Tap to return to call..."
174+msgstr "Tocar pa tornar a la llamada..."
175+
176+#: qml/Panel/ActiveCallHint.qml:90
177+msgid "Conference"
178+msgstr "Conferencia"
179+
172180#: qml/Panel/Indicators/MenuItemFactory.qml:583
173181msgid "In queue…"
174182msgstr "N'espera…"
po/az.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-15 09:50+0000\n"
1212"Last-Translator: Turan Mahmudov <turan.mahmudov@gmail.com>\n"
1313"Language-Team: Azerbaijani <az@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -81,10 +81,6 @@ msgstr "Zərurət zəngi"
8181msgid "OK"
8282msgstr ""
8383
84−#: qml/Components/PageHeader.qml:366
85−msgid "Recent searches"
86−msgstr "Son axtarışlar"
87−
8884#: qml/Components/PassphraseLockscreen.qml:60
8985#, qt-format
9086msgid "Hello %1"
@@ -106,7 +102,7 @@ msgstr ""
106102msgid "See more"
107103msgstr ""
108104
109−#: qml/Components/SeeMore.qml:58
105+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
110106msgid "See less"
111107msgstr ""
112108
@@ -114,6 +110,10 @@ msgstr ""
114110msgid "Recent"
115111msgstr ""
116112
113+#: qml/Dash/GenericScopeView.qml:330
114+msgid "See all"
115+msgstr ""
116+
117117#: qml/Dash/Previews/PreviewActionCombo.qml:34
118118msgid "More..."
119119msgstr ""
@@ -122,15 +122,15 @@ msgstr ""
122122msgid "Less..."
123123msgstr ""
124124
125−#: qml/Dash/Previews/PreviewRatingInput.qml:82
125+#: qml/Dash/Previews/PreviewRatingInput.qml:81
126126msgid "Rate this"
127127msgstr "Qiymət ver"
128128
129−#: qml/Dash/Previews/PreviewRatingInput.qml:128
129+#: qml/Dash/Previews/PreviewRatingInput.qml:126
130130msgid "Add a review"
131131msgstr "Rəy yaz"
132132
133−#: qml/Dash/Previews/PreviewRatingInput.qml:168
133+#: qml/Dash/Previews/PreviewRatingInput.qml:166
134134msgid "Send"
135135msgstr "Göndər"
136136
@@ -166,6 +166,14 @@ msgstr "Parolu göstər"
166166msgid "Please enter SIM PIN"
167167msgstr ""
168168
169+#: qml/Panel/ActiveCallHint.qml:77
170+msgid "Tap to return to call..."
171+msgstr ""
172+
173+#: qml/Panel/ActiveCallHint.qml:90
174+msgid "Conference"
175+msgstr ""
176+
169177#: qml/Panel/Indicators/MenuItemFactory.qml:583
170178msgid "In queue…"
171179msgstr ""
po/bg.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-04-01 14:08+0000\n"
1212"Last-Translator: Atanas Kovachki <Unknown>\n"
1313"Language-Team: Bulgarian <bg@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -87,10 +87,6 @@ msgstr "Спешно повикване"
8787msgid "OK"
8888msgstr ""
8989
90−#: qml/Components/PageHeader.qml:366
91−msgid "Recent searches"
92−msgstr "Последни търсения"
93−
9490#: qml/Components/PassphraseLockscreen.qml:60
9591#, qt-format
9692msgid "Hello %1"
@@ -112,7 +108,7 @@ msgstr ""
112108msgid "See more"
113109msgstr ""
114110
115−#: qml/Components/SeeMore.qml:58
111+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
116112msgid "See less"
117113msgstr ""
118114
@@ -120,6 +116,10 @@ msgstr ""
120116msgid "Recent"
121117msgstr "Последни"
122118
119+#: qml/Dash/GenericScopeView.qml:330
120+msgid "See all"
121+msgstr ""
122+
123123#: qml/Dash/Previews/PreviewActionCombo.qml:34
124124msgid "More..."
125125msgstr ""
@@ -128,15 +128,15 @@ msgstr ""
128128msgid "Less..."
129129msgstr "По-малко..."
130130
131−#: qml/Dash/Previews/PreviewRatingInput.qml:82
131+#: qml/Dash/Previews/PreviewRatingInput.qml:81
132132msgid "Rate this"
133133msgstr "Оценете това"
134134
135−#: qml/Dash/Previews/PreviewRatingInput.qml:128
135+#: qml/Dash/Previews/PreviewRatingInput.qml:126
136136msgid "Add a review"
137137msgstr "Добави отзив"
138138
139−#: qml/Dash/Previews/PreviewRatingInput.qml:168
139+#: qml/Dash/Previews/PreviewRatingInput.qml:166
140140msgid "Send"
141141msgstr "Изпрати"
142142
@@ -172,6 +172,14 @@ msgstr "Покажи паролата"
172172msgid "Please enter SIM PIN"
173173msgstr ""
174174
175+#: qml/Panel/ActiveCallHint.qml:77
176+msgid "Tap to return to call..."
177+msgstr ""
178+
179+#: qml/Panel/ActiveCallHint.qml:90
180+msgid "Conference"
181+msgstr ""
182+
175183#: qml/Panel/Indicators/MenuItemFactory.qml:583
176184msgid "In queue…"
177185msgstr ""
po/br.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-15 06:44+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-28 06:44+0000\n"
1212"Last-Translator: Fohanno Thierry <thierry.fohanno@ofis-bzh.org>\n"
1313"Language-Team: Breton <br@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-16 07:27+0000\n"
18−"X-Generator: Launchpad (build 17112)\n"
17+"X-Launchpad-Export-Date: 2014-07-29 06:54+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -87,10 +87,6 @@ msgstr "Pellgomzadenn vallus"
8787msgid "OK"
8888msgstr "Mat eo"
8989
90−#: qml/Components/PageHeader.qml:366
91−msgid "Recent searches"
92−msgstr "Enklaskoù graet nevez zo"
93−
9490#: qml/Components/PassphraseLockscreen.qml:60
9591#, qt-format
9692msgid "Hello %1"
@@ -112,7 +108,7 @@ msgstr "ECHU"
112108msgid "See more"
113109msgstr "Gwelet muioc'h"
114110
115−#: qml/Components/SeeMore.qml:58
111+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
116112msgid "See less"
117113msgstr "Gwelet nebeutoc'h"
118114
@@ -120,6 +116,10 @@ msgstr "Gwelet nebeutoc'h"
120116msgid "Recent"
121117msgstr "Nevez zo"
122118
119+#: qml/Dash/GenericScopeView.qml:330
120+msgid "See all"
121+msgstr "Gwelet pep tra"
122+
123123#: qml/Dash/Previews/PreviewActionCombo.qml:34
124124msgid "More..."
125125msgstr "Muioc'h..."
@@ -128,15 +128,15 @@ msgstr "Muioc'h..."
128128msgid "Less..."
129129msgstr "Nebeutoc'h..."
130130
131−#: qml/Dash/Previews/PreviewRatingInput.qml:82
131+#: qml/Dash/Previews/PreviewRatingInput.qml:81
132132msgid "Rate this"
133133msgstr "Priziit an dra-mañ"
134134
135−#: qml/Dash/Previews/PreviewRatingInput.qml:128
135+#: qml/Dash/Previews/PreviewRatingInput.qml:126
136136msgid "Add a review"
137137msgstr "Ouzhpennañ un ali"
138138
139−#: qml/Dash/Previews/PreviewRatingInput.qml:168
139+#: qml/Dash/Previews/PreviewRatingInput.qml:166
140140msgid "Send"
141141msgstr "Kas"
142142
@@ -172,6 +172,14 @@ msgstr "Diskouez ar ger-tremen"
172172msgid "Please enter SIM PIN"
173173msgstr "Ebarzhit kod PIN ho kartenn SIM, mar plij"
174174
175+#: qml/Panel/ActiveCallHint.qml:77
176+msgid "Tap to return to call..."
177+msgstr "Touchit evit distreiñ d'ar bellgomzadenn..."
178+
179+#: qml/Panel/ActiveCallHint.qml:90
180+msgid "Conference"
181+msgstr "Kendiviz"
182+
175183#: qml/Panel/Indicators/MenuItemFactory.qml:583
176184msgid "In queue…"
177185msgstr "El lostennad..."
po/bs.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-16 22:33+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Bosnian <bs@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/ca.po+28−20
@@ -7,24 +7,24 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-06-13 07:47+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-25 10:21+0000\n"
1212"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
1313"Language-Team: Catalan <ca@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
2222msgid "Pin shortcut"
23−msgstr ""
23+msgstr "Enganxa la drecera"
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:73
2626msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "Desenganxa la drecera"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
@@ -88,10 +88,6 @@ msgstr "Trucada d'emergència"
8888msgid "OK"
8989msgstr "D'acord"
9090
91−#: qml/Components/PageHeader.qml:366
92−msgid "Recent searches"
93−msgstr "Cerques recents"
94−
9591#: qml/Components/PassphraseLockscreen.qml:60
9692#, qt-format
9793msgid "Hello %1"
@@ -113,7 +109,7 @@ msgstr "Fet"
113109msgid "See more"
114110msgstr "Mostra'n més"
115111
116−#: qml/Components/SeeMore.qml:58
112+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
117113msgid "See less"
118114msgstr "Mostra'n menys"
119115
@@ -121,6 +117,10 @@ msgstr "Mostra'n menys"
121117msgid "Recent"
122118msgstr "Recents"
123119
120+#: qml/Dash/GenericScopeView.qml:330
121+msgid "See all"
122+msgstr "Mostra-ho tot"
123+
124124#: qml/Dash/Previews/PreviewActionCombo.qml:34
125125msgid "More..."
126126msgstr "Més..."
@@ -129,15 +129,15 @@ msgstr "Més..."
129129msgid "Less..."
130130msgstr "Menys..."
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:82
132+#: qml/Dash/Previews/PreviewRatingInput.qml:81
133133msgid "Rate this"
134134msgstr "Puntueu-ho"
135135
136−#: qml/Dash/Previews/PreviewRatingInput.qml:128
136+#: qml/Dash/Previews/PreviewRatingInput.qml:126
137137msgid "Add a review"
138138msgstr "Afegiu una ressenya"
139139
140−#: qml/Dash/Previews/PreviewRatingInput.qml:168
140+#: qml/Dash/Previews/PreviewRatingInput.qml:166
141141msgid "Send"
142142msgstr "Envia"
143143
@@ -173,29 +173,37 @@ msgstr "Mostra la contrasenya"
173173msgid "Please enter SIM PIN"
174174msgstr "Introduïu el PIN de la targeta SIM"
175175
176+#: qml/Panel/ActiveCallHint.qml:77
177+msgid "Tap to return to call..."
178+msgstr "Feu un toc per tornar a la trucada..."
179+
180+#: qml/Panel/ActiveCallHint.qml:90
181+msgid "Conference"
182+msgstr "Conferència"
183+
176184#: qml/Panel/Indicators/MenuItemFactory.qml:583
177185msgid "In queue…"
178−msgstr ""
186+msgstr "A la cua..."
179187
180188#: qml/Panel/Indicators/MenuItemFactory.qml:587
181189msgid "Downloading"
182−msgstr ""
190+msgstr "S'està baixant"
183191
184192#: qml/Panel/Indicators/MenuItemFactory.qml:589
185193msgid "Paused, tap to resume"
186−msgstr ""
194+msgstr "En pausa, feu un toc per continuar"
187195
188196#: qml/Panel/Indicators/MenuItemFactory.qml:591
189197msgid "Canceled"
190−msgstr ""
198+msgstr "S'ha cancel·lat"
191199
192200#: qml/Panel/Indicators/MenuItemFactory.qml:593
193201msgid "Finished"
194−msgstr ""
202+msgstr "S'ha finalitzat"
195203
196204#: qml/Panel/Indicators/MenuItemFactory.qml:595
197205msgid "Failed, tap to retry"
198−msgstr ""
206+msgstr "Ha fallat, feu un toc per tornar-ho a intentar"
199207
200208#: qml/Panel/SearchIndicator.qml:27
201209msgid "Search"
po/ckb.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-21 11:05+0000\n"
1212"Last-Translator: Aras <aras.noori@gmail.com>\n"
1313"Language-Team: Kurdish (Sorani) <ckb@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr "هێڵی فریاگوزاری"
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "دوایین گەڕانەکان"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr "پلە دابنی بۆی"
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr "پێداچوونەوە زۆر بکە"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "ناردن"
135135
@@ -165,6 +165,14 @@ msgstr "تێپەڕەوشە پیشان بدە"
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/cs.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-08 10:11+0000\n"
1212"Last-Translator: Tadeáš Pařík <tadeas.parik@gmail.com>\n"
1313"Language-Team: Czech <cs@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr "Tísňové volání"
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "Poslední vyhledávání"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr "Ohodnoťte to"
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr "Přidat recenzi"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "Odeslat"
135135
@@ -165,6 +165,14 @@ msgstr "Zobrazit heslo"
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/da.po+22−14
@@ -8,15 +8,15 @@ msgid ""
88msgstr ""
99"Project-Id-Version: unity8\n"
1010"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
11−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
12−"PO-Revision-Date: 2014-07-22 15:46+0000\n"
13−"Last-Translator: Kenneth Ramsussen <kentora@kentora.dk>\n"
11+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
12+"PO-Revision-Date: 2014-07-30 12:37+0000\n"
13+"Last-Translator: Ask Hjorth Larsen <asklarsen@gmail.com>\n"
1414"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
1515"MIME-Version: 1.0\n"
1616"Content-Type: text/plain; charset=UTF-8\n"
1717"Content-Transfer-Encoding: 8bit\n"
18−"X-Launchpad-Export-Date: 2014-07-23 07:01+0000\n"
19−"X-Generator: Launchpad (build 17114)\n"
18+"X-Launchpad-Export-Date: 2014-07-31 07:15+0000\n"
19+"X-Generator: Launchpad (build 17131)\n"
2020
2121#: plugins/Unity/Launcher/launcheritem.cpp:43
2222#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -72,7 +72,7 @@ msgid ""
7272"You have now mastered the edge gestures and can start using the "
7373"phone<br><br>Tap on the screen to start"
7474msgstr ""
75−"Du mestrer nu kantgestusserne og kan begynde at bruge telefonen<br><br>Tryk "
75+"Du mestrer nu kantbevægelserne og kan begynde at bruge telefonen<br><br>Tryk "
7676"på skærmen for at starte"
7777
7878#: qml/Components/Lockscreen.qml:214
@@ -83,10 +83,6 @@ msgstr "Nødopkald"
8383msgid "OK"
8484msgstr "O.k."
8585
86−#: qml/Components/PageHeader.qml:366
87−msgid "Recent searches"
88−msgstr "Seneste søgninger"
89−
9086#: qml/Components/PassphraseLockscreen.qml:60
9187#, qt-format
9288msgid "Hello %1"
@@ -108,7 +104,7 @@ msgstr "FÆRDIG"
108104msgid "See more"
109105msgstr "Vis mere"
110106
111−#: qml/Components/SeeMore.qml:58
107+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
112108msgid "See less"
113109msgstr "Vis mindre"
114110
@@ -116,6 +112,10 @@ msgstr "Vis mindre"
116112msgid "Recent"
117113msgstr "Seneste"
118114
115+#: qml/Dash/GenericScopeView.qml:330
116+msgid "See all"
117+msgstr "Se alle"
118+
119119#: qml/Dash/Previews/PreviewActionCombo.qml:34
120120msgid "More..."
121121msgstr "Mere..."
@@ -124,15 +124,15 @@ msgstr "Mere..."
124124msgid "Less..."
125125msgstr "Mindre..."
126126
127−#: qml/Dash/Previews/PreviewRatingInput.qml:82
127+#: qml/Dash/Previews/PreviewRatingInput.qml:81
128128msgid "Rate this"
129129msgstr "Bedøm dette"
130130
131−#: qml/Dash/Previews/PreviewRatingInput.qml:128
131+#: qml/Dash/Previews/PreviewRatingInput.qml:126
132132msgid "Add a review"
133133msgstr "Tilføj en forhåndsvisning"
134134
135−#: qml/Dash/Previews/PreviewRatingInput.qml:168
135+#: qml/Dash/Previews/PreviewRatingInput.qml:166
136136msgid "Send"
137137msgstr "Send"
138138
@@ -168,6 +168,14 @@ msgstr "Vis adgangskode"
168168msgid "Please enter SIM PIN"
169169msgstr "Indtast venligst PIN for SIM"
170170
171+#: qml/Panel/ActiveCallHint.qml:77
172+msgid "Tap to return to call..."
173+msgstr "Tryk for at besvare opkaldet..."
174+
175+#: qml/Panel/ActiveCallHint.qml:90
176+msgid "Conference"
177+msgstr "Konference"
178+
171179#: qml/Panel/Indicators/MenuItemFactory.qml:583
172180msgid "In queue…"
173181msgstr "I kø…"
po/de.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-07-15 13:20+0000\n"
1212"Last-Translator: Phillip Sz <Unknown>\n"
1313"Language-Team: German <de@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-16 07:27+0000\n"
18−"X-Generator: Launchpad (build 17112)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -85,10 +85,6 @@ msgstr "Notruf"
8585msgid "OK"
8686msgstr "OK"
8787
88−#: qml/Components/PageHeader.qml:366
89−msgid "Recent searches"
90−msgstr "Zuletzt verwendete Suchbegriffe"
91−
9288#: qml/Components/PassphraseLockscreen.qml:60
9389#, qt-format
9490msgid "Hello %1"
@@ -110,7 +106,7 @@ msgstr "ERLEDIGT"
110106msgid "See more"
111107msgstr "Mehr ansehen"
112108
113−#: qml/Components/SeeMore.qml:58
109+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
114110msgid "See less"
115111msgstr "Weniger ansehen"
116112
@@ -118,6 +114,10 @@ msgstr "Weniger ansehen"
118114msgid "Recent"
119115msgstr "Kürzlich"
120116
117+#: qml/Dash/GenericScopeView.qml:330
118+msgid "See all"
119+msgstr ""
120+
121121#: qml/Dash/Previews/PreviewActionCombo.qml:34
122122msgid "More..."
123123msgstr "Mehr …"
@@ -126,15 +126,15 @@ msgstr "Mehr …"
126126msgid "Less..."
127127msgstr "Weniger …"
128128
129−#: qml/Dash/Previews/PreviewRatingInput.qml:82
129+#: qml/Dash/Previews/PreviewRatingInput.qml:81
130130msgid "Rate this"
131131msgstr "Bewerten"
132132
133−#: qml/Dash/Previews/PreviewRatingInput.qml:128
133+#: qml/Dash/Previews/PreviewRatingInput.qml:126
134134msgid "Add a review"
135135msgstr "Bewertung hinzufügen"
136136
137−#: qml/Dash/Previews/PreviewRatingInput.qml:168
137+#: qml/Dash/Previews/PreviewRatingInput.qml:166
138138msgid "Send"
139139msgstr "Senden"
140140
@@ -170,6 +170,14 @@ msgstr "Passwort anzeigen"
170170msgid "Please enter SIM PIN"
171171msgstr "Bitte die PIN der SIM eingeben"
172172
173+#: qml/Panel/ActiveCallHint.qml:77
174+msgid "Tap to return to call..."
175+msgstr ""
176+
177+#: qml/Panel/ActiveCallHint.qml:90
178+msgid "Conference"
179+msgstr ""
180+
173181#: qml/Panel/Indicators/MenuItemFactory.qml:583
174182msgid "In queue…"
175183msgstr "In Warteschlange …"
po/el.po+35−27
@@ -7,24 +7,24 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-02-26 09:58+0000\n"
12−"Last-Translator: j3lc <x_nikos@yahoo.gr>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-08-04 18:44+0000\n"
12+"Last-Translator: madvinegar <madvinegar@hotmail.com>\n"
1313"Language-Team: Greek <el@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-08-05 06:45+0000\n"
18+"X-Generator: Launchpad (build 17147)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
2222msgid "Pin shortcut"
23−msgstr ""
23+msgstr "Καρφίτσωμα συντόμευσης"
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:73
2626msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "Ξεκαρφίτσωμα συντόμευσης"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
@@ -82,11 +82,7 @@ msgstr "Κλήση έκτακτης ανάγκης"
8282
8383#: qml/Components/Lockscreen.qml:231
8484msgid "OK"
85−msgstr ""
86−
87−#: qml/Components/PageHeader.qml:366
88−msgid "Recent searches"
89−msgstr "Πρόσφατες αναζητήσεις"
85+msgstr "OK"
9086
9187#: qml/Components/PassphraseLockscreen.qml:60
9288#, qt-format
@@ -99,47 +95,51 @@ msgstr "Γεια σας"
9995
10096#: qml/Components/PinLockscreen.qml:198
10197msgid "CANCEL"
102−msgstr ""
98+msgstr "ΑΚΥΡΩΣΗ"
10399
104100#: qml/Components/PinLockscreen.qml:216
105101msgid "DONE"
106−msgstr ""
102+msgstr "ΟΛΟΚΛΗΡΩΣΗ"
107103
108104#: qml/Components/SeeMore.qml:35
109105msgid "See more"
110106msgstr "Περρισότερα"
111107
112−#: qml/Components/SeeMore.qml:58
108+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
113109msgid "See less"
114110msgstr "Λιγότερα"
115111
116112#: qml/Dash/DashApps.qml:37
117113msgid "Recent"
118−msgstr ""
114+msgstr "Πρόσφατα"
115+
116+#: qml/Dash/GenericScopeView.qml:330
117+msgid "See all"
118+msgstr "Εμφάνιση όλων"
119119
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
122−msgstr ""
122+msgstr "Περισσότερα..."
123123
124124#: qml/Dash/Previews/PreviewActionCombo.qml:34
125125msgid "Less..."
126−msgstr ""
126+msgstr "Λιγότερα..."
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:82
128+#: qml/Dash/Previews/PreviewRatingInput.qml:81
129129msgid "Rate this"
130130msgstr "Βαθμολογήστε το"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:128
132+#: qml/Dash/Previews/PreviewRatingInput.qml:126
133133msgid "Add a review"
134134msgstr "Προσθέστε την αξιολόγησή σας"
135135
136−#: qml/Dash/Previews/PreviewRatingInput.qml:168
136+#: qml/Dash/Previews/PreviewRatingInput.qml:166
137137msgid "Send"
138138msgstr "Αποστολή"
139139
140140#: qml/Greeter/Greeter.qml:157
141141msgid "Swipe to unlock"
142−msgstr ""
142+msgstr "Σύρετε για να ξεκλειδώσετε"
143143
144144#: qml/Hud/HudParametrizedActionsPage.qml:132
145145msgid "Confirm"
@@ -169,29 +169,37 @@ msgstr "Εμφάνιση κωδικού"
169169msgid "Please enter SIM PIN"
170170msgstr "Παρακαλώ εισάγετε το PIN της κάρτας SIM"
171171
172+#: qml/Panel/ActiveCallHint.qml:77
173+msgid "Tap to return to call..."
174+msgstr "Πατήστε για να γυρίσετε στην κλήση..."
175+
176+#: qml/Panel/ActiveCallHint.qml:90
177+msgid "Conference"
178+msgstr "Συνδιάσκεψη"
179+
172180#: qml/Panel/Indicators/MenuItemFactory.qml:583
173181msgid "In queue…"
174182msgstr ""
175183
176184#: qml/Panel/Indicators/MenuItemFactory.qml:587
177185msgid "Downloading"
178−msgstr ""
186+msgstr "Λήψη σε εξέλιξη"
179187
180188#: qml/Panel/Indicators/MenuItemFactory.qml:589
181189msgid "Paused, tap to resume"
182−msgstr ""
190+msgstr "Σταματημένο, αγγίξτε για συνέχιση"
183191
184192#: qml/Panel/Indicators/MenuItemFactory.qml:591
185193msgid "Canceled"
186−msgstr ""
194+msgstr "Ακυρώθηκε"
187195
188196#: qml/Panel/Indicators/MenuItemFactory.qml:593
189197msgid "Finished"
190−msgstr ""
198+msgstr "Ολοκληρώθηκε"
191199
192200#: qml/Panel/Indicators/MenuItemFactory.qml:595
193201msgid "Failed, tap to retry"
194−msgstr ""
202+msgstr "Αποτυχία, πατήστε για να ξαναπροσπαθήσετε"
195203
196204#: qml/Panel/SearchIndicator.qml:27
197205msgid "Search"
po/en_AU.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-18 10:38+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-27 12:14+0000\n"
1212"Last-Translator: Jared Norris <jarednorris@ubuntu.com>\n"
1313"Language-Team: English (Australia) <en_AU@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-19 06:19+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-28 06:44+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -82,10 +82,6 @@ msgstr "Emergency Call"
8282msgid "OK"
8383msgstr "OK"
8484
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "Recent searches"
88−
8985#: qml/Components/PassphraseLockscreen.qml:60
9086#, qt-format
9187msgid "Hello %1"
@@ -107,7 +103,7 @@ msgstr "DONE"
107103msgid "See more"
108104msgstr "See more"
109105
110−#: qml/Components/SeeMore.qml:58
106+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111107msgid "See less"
112108msgstr "See less"
113109
@@ -115,6 +111,10 @@ msgstr "See less"
115111msgid "Recent"
116112msgstr "Recent"
117113
114+#: qml/Dash/GenericScopeView.qml:330
115+msgid "See all"
116+msgstr "See all"
117+
118118#: qml/Dash/Previews/PreviewActionCombo.qml:34
119119msgid "More..."
120120msgstr "More..."
@@ -123,15 +123,15 @@ msgstr "More..."
123123msgid "Less..."
124124msgstr "Less..."
125125
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
126+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127127msgid "Rate this"
128128msgstr "Rate this"
129129
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
130+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131131msgid "Add a review"
132132msgstr "Add a review"
133133
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
134+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135135msgid "Send"
136136msgstr "Send"
137137
@@ -167,6 +167,14 @@ msgstr "Show password"
167167msgid "Please enter SIM PIN"
168168msgstr "Please enter SIM PIN"
169169
170+#: qml/Panel/ActiveCallHint.qml:77
171+msgid "Tap to return to call..."
172+msgstr "Tap to return to call..."
173+
174+#: qml/Panel/ActiveCallHint.qml:90
175+msgid "Conference"
176+msgstr "Conference"
177+
170178#: qml/Panel/Indicators/MenuItemFactory.qml:583
171179msgid "In queue…"
172180msgstr "In queue…"
po/en_GB.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-10 10:59+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-27 14:09+0000\n"
1212"Last-Translator: Alan Pope ㋛ <alan@ubuntu.com>\n"
1313"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-11 06:15+0000\n"
18−"X-Generator: Launchpad (build 17111)\n"
17+"X-Launchpad-Export-Date: 2014-07-28 06:44+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -82,10 +82,6 @@ msgstr "Emergency Call"
8282msgid "OK"
8383msgstr "OK"
8484
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "Recent searches"
88−
8985#: qml/Components/PassphraseLockscreen.qml:60
9086#, qt-format
9187msgid "Hello %1"
@@ -107,7 +103,7 @@ msgstr "DONE"
107103msgid "See more"
108104msgstr "See more"
109105
110−#: qml/Components/SeeMore.qml:58
106+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111107msgid "See less"
112108msgstr "See less"
113109
@@ -115,6 +111,10 @@ msgstr "See less"
115111msgid "Recent"
116112msgstr "Recent"
117113
114+#: qml/Dash/GenericScopeView.qml:330
115+msgid "See all"
116+msgstr "See all"
117+
118118#: qml/Dash/Previews/PreviewActionCombo.qml:34
119119msgid "More..."
120120msgstr "More..."
@@ -123,15 +123,15 @@ msgstr "More..."
123123msgid "Less..."
124124msgstr "Less..."
125125
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
126+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127127msgid "Rate this"
128128msgstr "Rate this"
129129
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
130+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131131msgid "Add a review"
132132msgstr "Add a review"
133133
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
134+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135135msgid "Send"
136136msgstr "Send"
137137
@@ -167,6 +167,14 @@ msgstr "Show password"
167167msgid "Please enter SIM PIN"
168168msgstr "Please enter SIM PIN"
169169
170+#: qml/Panel/ActiveCallHint.qml:77
171+msgid "Tap to return to call..."
172+msgstr "Tap to return to call..."
173+
174+#: qml/Panel/ActiveCallHint.qml:90
175+msgid "Conference"
176+msgstr "Conference"
177+
170178#: qml/Panel/Indicators/MenuItemFactory.qml:583
171179msgid "In queue…"
172180msgstr "In queue…"
po/eo.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-06-26 22:35+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Esperanto <eo@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/es.po+21−13
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-12 05:24+0000\n"
12−"Last-Translator: Adolfo Jayme <fitoschido@gmail.com>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-08-06 15:24+0000\n"
12+"Last-Translator: Leo Arias <leo.arias@canonical.com>\n"
1313"Language-Team: Spanish <es@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-13 06:33+0000\n"
18−"X-Generator: Launchpad (build 17111)\n"
17+"X-Launchpad-Export-Date: 2014-08-08 07:07+0000\n"
18+"X-Generator: Launchpad (build 17156)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -85,10 +85,6 @@ msgstr "Llamada de emergencia"
8585msgid "OK"
8686msgstr "Aceptar"
8787
88−#: qml/Components/PageHeader.qml:366
89−msgid "Recent searches"
90−msgstr "Búsquedas recientes"
91−
9288#: qml/Components/PassphraseLockscreen.qml:60
9389#, qt-format
9490msgid "Hello %1"
@@ -110,7 +106,7 @@ msgstr "HECHO"
110106msgid "See more"
111107msgstr "Ver más"
112108
113−#: qml/Components/SeeMore.qml:58
109+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
114110msgid "See less"
115111msgstr "Ver menos"
116112
@@ -118,6 +114,10 @@ msgstr "Ver menos"
118114msgid "Recent"
119115msgstr "Recientes"
120116
117+#: qml/Dash/GenericScopeView.qml:330
118+msgid "See all"
119+msgstr "Ver todas"
120+
121121#: qml/Dash/Previews/PreviewActionCombo.qml:34
122122msgid "More..."
123123msgstr "Más…"
@@ -126,15 +126,15 @@ msgstr "Más…"
126126msgid "Less..."
127127msgstr "Menos…"
128128
129−#: qml/Dash/Previews/PreviewRatingInput.qml:82
129+#: qml/Dash/Previews/PreviewRatingInput.qml:81
130130msgid "Rate this"
131131msgstr "Valorar esto"
132132
133−#: qml/Dash/Previews/PreviewRatingInput.qml:128
133+#: qml/Dash/Previews/PreviewRatingInput.qml:126
134134msgid "Add a review"
135135msgstr "Añadir una reseña"
136136
137−#: qml/Dash/Previews/PreviewRatingInput.qml:168
137+#: qml/Dash/Previews/PreviewRatingInput.qml:166
138138msgid "Send"
139139msgstr "Enviar"
140140
@@ -170,6 +170,14 @@ msgstr "Mostrar contraseña"
170170msgid "Please enter SIM PIN"
171171msgstr "Escriba el PIN de la SIM"
172172
173+#: qml/Panel/ActiveCallHint.qml:77
174+msgid "Tap to return to call..."
175+msgstr "Toque para volver a llamar..."
176+
177+#: qml/Panel/ActiveCallHint.qml:90
178+msgid "Conference"
179+msgstr "Conferencia"
180+
173181#: qml/Panel/Indicators/MenuItemFactory.qml:583
174182msgid "In queue…"
175183msgstr "En espera…"
po/eu.po+24−15
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-16 18:11+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-08-06 22:51+0000\n"
1212"Last-Translator: Ibai Oihanguren Sala <Unknown>\n"
1313"Language-Team: Basque <eu@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-17 06:38+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-08-08 07:07+0000\n"
18+"X-Generator: Launchpad (build 17156)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -36,7 +36,8 @@ msgstr "Eskuineko ertza"
3636
3737#: qml/Components/EdgeDemo.qml:114
3838msgid "Try swiping from the right edge to unlock the phone"
39−msgstr "Probatu eskuineko ertzetik arrastatzen telefonoa desblokeatzeko"
39+msgstr ""
40+"Pasatu hatza eskuineko ertzetik ezkerrerantz telefonoa desblokeatzeko"
4041
4142#: qml/Components/EdgeDemo.qml:145
4243msgid "Top edge"
@@ -44,7 +45,7 @@ msgstr "Goiko ertza"
4445
4546#: qml/Components/EdgeDemo.qml:146
4647msgid "Try swiping from the top edge to access the indicators"
47−msgstr "Probatu goiko ertzetik arrastatzen adierazleak ikusteko"
48+msgstr "Pasatu hatza goiko ertzetik beherantz adierazleak ikusteko"
4849
4950#: qml/Components/EdgeDemo.qml:171
5051msgid "Close"
@@ -52,7 +53,7 @@ msgstr "Itxi"
5253
5354#: qml/Components/EdgeDemo.qml:172
5455msgid "Swipe up again to close the settings screen"
55−msgstr "Pasatu hatza gora berriro ezarpenen leihoa ixteko"
56+msgstr "Pasatu hatza berriro gora ezarpenen leihoa ixteko"
5657
5758#: qml/Components/EdgeDemo.qml:199
5859msgid "Left edge"
@@ -84,10 +85,6 @@ msgstr "Larrialdi-deia"
8485msgid "OK"
8586msgstr "Ados"
8687
87−#: qml/Components/PageHeader.qml:366
88−msgid "Recent searches"
89−msgstr "Azken bilaketak"
90−
9188#: qml/Components/PassphraseLockscreen.qml:60
9289#, qt-format
9390msgid "Hello %1"
@@ -109,7 +106,7 @@ msgstr "EGINDA"
109106msgid "See more"
110107msgstr "Ikusi gehiago"
111108
112−#: qml/Components/SeeMore.qml:58
109+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
113110msgid "See less"
114111msgstr "Ikusi gutxiago"
115112
@@ -117,6 +114,10 @@ msgstr "Ikusi gutxiago"
117114msgid "Recent"
118115msgstr "Azkenak"
119116
117+#: qml/Dash/GenericScopeView.qml:330
118+msgid "See all"
119+msgstr "Ikusi guztiak"
120+
120121#: qml/Dash/Previews/PreviewActionCombo.qml:34
121122msgid "More..."
122123msgstr "Gehiago..."
@@ -125,15 +126,15 @@ msgstr "Gehiago..."
125126msgid "Less..."
126127msgstr "Gutxiago..."
127128
128−#: qml/Dash/Previews/PreviewRatingInput.qml:82
129+#: qml/Dash/Previews/PreviewRatingInput.qml:81
129130msgid "Rate this"
130131msgstr "Puntuatu hau"
131132
132−#: qml/Dash/Previews/PreviewRatingInput.qml:128
133+#: qml/Dash/Previews/PreviewRatingInput.qml:126
133134msgid "Add a review"
134135msgstr "Gehitu kritika"
135136
136−#: qml/Dash/Previews/PreviewRatingInput.qml:168
137+#: qml/Dash/Previews/PreviewRatingInput.qml:166
137138msgid "Send"
138139msgstr "Bidali"
139140
@@ -169,6 +170,14 @@ msgstr "Erakutsi pasahitza"
169170msgid "Please enter SIM PIN"
170171msgstr "Sartu SIMaren PINa"
171172
173+#: qml/Panel/ActiveCallHint.qml:77
174+msgid "Tap to return to call..."
175+msgstr "Sakatu deia itzultzeko..."
176+
177+#: qml/Panel/ActiveCallHint.qml:90
178+msgid "Conference"
179+msgstr "Konferentzia"
180+
172181#: qml/Panel/Indicators/MenuItemFactory.qml:583
173182msgid "In queue…"
174183msgstr "Ilaran..."
po/fa.po+65−55
@@ -7,193 +7,203 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2013-10-31 19:02+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-08-03 13:00+0000\n"
12+"Last-Translator: Arash Badie Modiri <arashbm@gmail.com>\n"
1313"Language-Team: Persian <fa@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-08-04 06:32+0000\n"
18+"X-Generator: Launchpad (build 17147)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
2222msgid "Pin shortcut"
23−msgstr ""
23+msgstr "سنجاق کردن میانبر"
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:73
2626msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "برداشتن سنجاق میانبر"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
31−msgstr ""
31+msgstr "پرش از مقدّمه"
3232
3333#: qml/Components/EdgeDemo.qml:113
3434msgid "Right edge"
35−msgstr ""
35+msgstr "لبه‌ی راست"
3636
3737#: qml/Components/EdgeDemo.qml:114
3838msgid "Try swiping from the right edge to unlock the phone"
39−msgstr ""
39+msgstr "برای باز کردن قفل تلفن، از لبه‌ی راست بکشید"
4040
4141#: qml/Components/EdgeDemo.qml:145
4242msgid "Top edge"
43−msgstr ""
43+msgstr "لبه‌ی بالا"
4444
4545#: qml/Components/EdgeDemo.qml:146
4646msgid "Try swiping from the top edge to access the indicators"
47−msgstr ""
47+msgstr "برای دست‌رسی به نشانگرها، از لبه‌ی بالا بکشید"
4848
4949#: qml/Components/EdgeDemo.qml:171
5050msgid "Close"
51−msgstr ""
51+msgstr "بستن"
5252
5353#: qml/Components/EdgeDemo.qml:172
5454msgid "Swipe up again to close the settings screen"
55−msgstr ""
55+msgstr "برای بستن صفحه‌ی تنظیمات، دوباره به بالا بکشپد"
5656
5757#: qml/Components/EdgeDemo.qml:199
5858msgid "Left edge"
59−msgstr ""
59+msgstr "لبه‌ی چپ"
6060
6161#: qml/Components/EdgeDemo.qml:200
6262msgid "Swipe from the left to reveal the launcher for quick access to apps"
63−msgstr ""
63+msgstr "برای آشکار شدن اجراگر به منظور دست‌رسی سریع به اپ‌ها از سمت چپ بکشید"
6464
6565#: qml/Components/EdgeDemo.qml:227
6666msgid "Well done"
67−msgstr ""
67+msgstr "عالی بود"
6868
6969#: qml/Components/EdgeDemo.qml:228
7070msgid ""
7171"You have now mastered the edge gestures and can start using the "
7272"phone<br><br>Tap on the screen to start"
7373msgstr ""
74+"هم اکنون در استفاده از ژست های حرکتی مهارت لازم را دارید و می‌توانید استفاده "
75+"از تلفن را آغاز کنید<br><br>برای شروع صفحه را لمس کنید"
7476
7577#: qml/Components/Lockscreen.qml:214
7678msgid "Emergency Call"
77−msgstr ""
79+msgstr "تماس اضطراری"
7880
7981#: qml/Components/Lockscreen.qml:231
8082msgid "OK"
81−msgstr ""
82−
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
83+msgstr "قبول"
8684
8785#: qml/Components/PassphraseLockscreen.qml:60
8886#, qt-format
8987msgid "Hello %1"
90−msgstr ""
88+msgstr "سلام %1"
9189
9290#: qml/Components/PassphraseLockscreen.qml:60
9391msgid "Hello"
94−msgstr ""
92+msgstr "سلام"
9593
9694#: qml/Components/PinLockscreen.qml:198
9795msgid "CANCEL"
98−msgstr ""
96+msgstr "لغو"
9997
10098#: qml/Components/PinLockscreen.qml:216
10199msgid "DONE"
102−msgstr ""
100+msgstr "انجام شد"
103101
104102#: qml/Components/SeeMore.qml:35
105103msgid "See more"
106−msgstr ""
104+msgstr "بیش‌تر ببینید"
107105
108−#: qml/Components/SeeMore.qml:58
106+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109107msgid "See less"
110−msgstr ""
108+msgstr "کم‌تر ببینید"
111109
112110#: qml/Dash/DashApps.qml:37
113111msgid "Recent"
114−msgstr ""
112+msgstr "موارد اخیر"
113+
114+#: qml/Dash/GenericScopeView.qml:330
115+msgid "See all"
116+msgstr "دیدن همه"
115117
116118#: qml/Dash/Previews/PreviewActionCombo.qml:34
117119msgid "More..."
118−msgstr ""
120+msgstr "بیش‌تر…"
119121
120122#: qml/Dash/Previews/PreviewActionCombo.qml:34
121123msgid "Less..."
122−msgstr ""
124+msgstr "کم‌تر…"
123125
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
126+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125127msgid "Rate this"
126−msgstr ""
128+msgstr "امتیاز دادن"
127129
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
130+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129131msgid "Add a review"
130−msgstr ""
132+msgstr "افزودن یک بازبینی"
131133
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
134+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133135msgid "Send"
134−msgstr ""
136+msgstr "ارسال"
135137
136138#: qml/Greeter/Greeter.qml:157
137139msgid "Swipe to unlock"
138−msgstr ""
140+msgstr "برای باز کردن قفل بکشد"
139141
140142#: qml/Hud/HudParametrizedActionsPage.qml:132
141143msgid "Confirm"
142−msgstr ""
144+msgstr "تأیید"
143145
144146#: qml/Hud/Hud.qml:61 qml/Hud/Hud.qml:99 qml/Hud/Hud.qml:372
145147msgid "Type or say a command"
146−msgstr ""
148+msgstr "دستوری را بنویسید یا بگویید"
147149
148150#: qml/Hud/Hud.qml:84
149151msgid "Loading. Please Wait..."
150−msgstr ""
152+msgstr "در حال بار کردن. لطفاً صبر کنید…"
151153
152154#: qml/Hud/Hud.qml:89
153155msgid "Speak Now..."
154−msgstr ""
156+msgstr "اکنون صحبت کنید…"
155157
156158#: qml/Hud/Hud.qml:94
157159msgid "Speaking..."
158−msgstr ""
160+msgstr "در حال صحبت کردن…"
159161
160162#: qml/Notifications/NotificationMenuItemFactory.qml:91
161163msgid "Show password"
162−msgstr ""
164+msgstr "نمایش گذرواژه"
163165
164166#: qml/Notifications/NotificationMenuItemFactory.qml:103
165167msgid "Please enter SIM PIN"
166−msgstr ""
168+msgstr "لطفاً PIN سیم‌کارت را وارد کنید"
169+
170+#: qml/Panel/ActiveCallHint.qml:77
171+msgid "Tap to return to call..."
172+msgstr "برای بازگشت به تماس ضربه بزنید…"
173+
174+#: qml/Panel/ActiveCallHint.qml:90
175+msgid "Conference"
176+msgstr "کنفرانس"
167177
168178#: qml/Panel/Indicators/MenuItemFactory.qml:583
169179msgid "In queue…"
170−msgstr ""
180+msgstr "در صف…"
171181
172182#: qml/Panel/Indicators/MenuItemFactory.qml:587
173183msgid "Downloading"
174−msgstr ""
184+msgstr "در حال بارگیری"
175185
176186#: qml/Panel/Indicators/MenuItemFactory.qml:589
177187msgid "Paused, tap to resume"
178−msgstr ""
188+msgstr "مکث شد، برای از سر گیری ضربه بزنید"
179189
180190#: qml/Panel/Indicators/MenuItemFactory.qml:591
181191msgid "Canceled"
182−msgstr ""
192+msgstr "لغو شد"
183193
184194#: qml/Panel/Indicators/MenuItemFactory.qml:593
185195msgid "Finished"
186−msgstr ""
196+msgstr "پایان یافت"
187197
188198#: qml/Panel/Indicators/MenuItemFactory.qml:595
189199msgid "Failed, tap to retry"
190−msgstr ""
200+msgstr "شکست خورد، برای تلاش دوباره ضربه بزنید"
191201
192202#: qml/Panel/SearchIndicator.qml:27
193203msgid "Search"
194−msgstr ""
204+msgstr "جست‌وجو"
195205
196206#: qml/Shell.qml:359
197207#, qt-format
198208msgid "Please enter %1"
199−msgstr ""
209+msgstr "لطفا %1 را وارد کنید"
po/fi.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-09 17:26+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-25 16:07+0000\n"
1212"Last-Translator: Jiri Grönroos <Unknown>\n"
1313"Language-Team: Finnish <fi@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-10 07:29+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -82,10 +82,6 @@ msgstr "Hätäpuhelu"
8282msgid "OK"
8383msgstr "OK"
8484
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "Viimeisimmät haut"
88−
8985#: qml/Components/PassphraseLockscreen.qml:60
9086#, qt-format
9187msgid "Hello %1"
@@ -107,7 +103,7 @@ msgstr "VALMIS"
107103msgid "See more"
108104msgstr "Näytä lisää"
109105
110−#: qml/Components/SeeMore.qml:58
106+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111107msgid "See less"
112108msgstr "Näytä vähemmän"
113109
@@ -115,6 +111,10 @@ msgstr "Näytä vähemmän"
115111msgid "Recent"
116112msgstr "Viimeisimmät"
117113
114+#: qml/Dash/GenericScopeView.qml:330
115+msgid "See all"
116+msgstr "Näytä kaikki"
117+
118118#: qml/Dash/Previews/PreviewActionCombo.qml:34
119119msgid "More..."
120120msgstr "Lisää..."
@@ -123,15 +123,15 @@ msgstr "Lisää..."
123123msgid "Less..."
124124msgstr "Vähemmän..."
125125
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
126+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127127msgid "Rate this"
128128msgstr "Arvioi tämä"
129129
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
130+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131131msgid "Add a review"
132132msgstr "Lisää arvostelu"
133133
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
134+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135135msgid "Send"
136136msgstr "Lähetä"
137137
@@ -167,6 +167,14 @@ msgstr "Näytä salasana"
167167msgid "Please enter SIM PIN"
168168msgstr "Anna SIM-kortin PIN-koodi"
169169
170+#: qml/Panel/ActiveCallHint.qml:77
171+msgid "Tap to return to call..."
172+msgstr "Napauta palataksesi puheluun..."
173+
174+#: qml/Panel/ActiveCallHint.qml:90
175+msgid "Conference"
176+msgstr "Ryhmäpuhelu"
177+
170178#: qml/Panel/Indicators/MenuItemFactory.qml:583
171179msgid "In queue…"
172180msgstr "Jonossa…"
po/fo.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-14 20:08+0000\n"
1212"Last-Translator: Jógvan Olsen <jeggy@jebster.net>\n"
1313"Language-Team: Faroese <fo@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/fr.po+21−13
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-18 18:31+0000\n"
12−"Last-Translator: Nicolas Delvaux <Unknown>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-26 20:52+0000\n"
12+"Last-Translator: Anne <anneonyme017@gmail.com>\n"
1313"Language-Team: French <fr@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-19 06:19+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-27 06:35+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -89,10 +89,6 @@ msgstr "Appel d'urgence"
8989msgid "OK"
9090msgstr "OK"
9191
92−#: qml/Components/PageHeader.qml:366
93−msgid "Recent searches"
94−msgstr "Recherches récentes"
95−
9692#: qml/Components/PassphraseLockscreen.qml:60
9793#, qt-format
9894msgid "Hello %1"
@@ -114,7 +110,7 @@ msgstr "VALIDER"
114110msgid "See more"
115111msgstr "Voir plus"
116112
117−#: qml/Components/SeeMore.qml:58
113+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
118114msgid "See less"
119115msgstr "Voir moins"
120116
@@ -122,6 +118,10 @@ msgstr "Voir moins"
122118msgid "Recent"
123119msgstr "Récent"
124120
121+#: qml/Dash/GenericScopeView.qml:330
122+msgid "See all"
123+msgstr "Tout voir"
124+
125125#: qml/Dash/Previews/PreviewActionCombo.qml:34
126126msgid "More..."
127127msgstr "Plus..."
@@ -130,15 +130,15 @@ msgstr "Plus..."
130130msgid "Less..."
131131msgstr "Moins..."
132132
133−#: qml/Dash/Previews/PreviewRatingInput.qml:82
133+#: qml/Dash/Previews/PreviewRatingInput.qml:81
134134msgid "Rate this"
135135msgstr "Evaluez ceci"
136136
137−#: qml/Dash/Previews/PreviewRatingInput.qml:128
137+#: qml/Dash/Previews/PreviewRatingInput.qml:126
138138msgid "Add a review"
139139msgstr "Ajouter un avis"
140140
141−#: qml/Dash/Previews/PreviewRatingInput.qml:168
141+#: qml/Dash/Previews/PreviewRatingInput.qml:166
142142msgid "Send"
143143msgstr "Envoyer"
144144
@@ -174,6 +174,14 @@ msgstr "Afficher le mot de passe"
174174msgid "Please enter SIM PIN"
175175msgstr "Entrez le code PIN"
176176
177+#: qml/Panel/ActiveCallHint.qml:77
178+msgid "Tap to return to call..."
179+msgstr "Appuyez pour revenir à l'appel…"
180+
181+#: qml/Panel/ActiveCallHint.qml:90
182+msgid "Conference"
183+msgstr "Conférence"
184+
177185#: qml/Panel/Indicators/MenuItemFactory.qml:583
178186msgid "In queue…"
179187msgstr "Dans la file d'attente..."
po/gd.po+21−13
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-16 14:48+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-25 22:02+0000\n"
1212"Last-Translator: GunChleoc <Unknown>\n"
1313"Language-Team: Fòram na Gàidhlig http://www.foramnagaidhlig.net\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-17 06:38+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919"Language: gd\n"
2020
2121#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -87,11 +87,7 @@ msgstr "Gairm èiginn"
8787
8888#: qml/Components/Lockscreen.qml:231
8989msgid "OK"
90−msgstr "Ceart ma-hà"
91−
92−#: qml/Components/PageHeader.qml:366
93−msgid "Recent searches"
94−msgstr "Na lorg thu o chionn goirid"
90+msgstr "Ceart ma-thà"
9591
9692#: qml/Components/PassphraseLockscreen.qml:60
9793#, qt-format
@@ -114,7 +110,7 @@ msgstr "DÈANTA"
114110msgid "See more"
115111msgstr "Seall barrachd"
116112
117−#: qml/Components/SeeMore.qml:58
113+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
118114msgid "See less"
119115msgstr "Seall nas lugha"
120116
@@ -122,6 +118,10 @@ msgstr "Seall nas lugha"
122118msgid "Recent"
123119msgstr "O chionn goirid"
124120
121+#: qml/Dash/GenericScopeView.qml:330
122+msgid "See all"
123+msgstr "Seall na h-uile"
124+
125125#: qml/Dash/Previews/PreviewActionCombo.qml:34
126126msgid "More..."
127127msgstr "Barrachd..."
@@ -130,15 +130,15 @@ msgstr "Barrachd..."
130130msgid "Less..."
131131msgstr "Nas lugha..."
132132
133−#: qml/Dash/Previews/PreviewRatingInput.qml:82
133+#: qml/Dash/Previews/PreviewRatingInput.qml:81
134134msgid "Rate this"
135135msgstr "Rangaich seo"
136136
137−#: qml/Dash/Previews/PreviewRatingInput.qml:128
137+#: qml/Dash/Previews/PreviewRatingInput.qml:126
138138msgid "Add a review"
139139msgstr "Cuir lèirmheas ris"
140140
141−#: qml/Dash/Previews/PreviewRatingInput.qml:168
141+#: qml/Dash/Previews/PreviewRatingInput.qml:166
142142msgid "Send"
143143msgstr "Cuir"
144144
@@ -174,6 +174,14 @@ msgstr "Seall am facal-faire"
174174msgid "Please enter SIM PIN"
175175msgstr "Cuir a-steach SIM PIN"
176176
177+#: qml/Panel/ActiveCallHint.qml:77
178+msgid "Tap to return to call..."
179+msgstr "Gnog gus tilleadh dhan ghairm..."
180+
181+#: qml/Panel/ActiveCallHint.qml:90
182+msgid "Conference"
183+msgstr "Gairm co-labhairt"
184+
177185#: qml/Panel/Indicators/MenuItemFactory.qml:583
178186msgid "In queue…"
179187msgstr "Air a' chiudha…"
po/gl.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-21 16:08+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-25 17:22+0000\n"
1212"Last-Translator: Marcos Lans <Unknown>\n"
1313"Language-Team: Galician <gl@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-22 07:17+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -84,10 +84,6 @@ msgstr "Chamada de emerxencia"
8484msgid "OK"
8585msgstr "Aceptar"
8686
87−#: qml/Components/PageHeader.qml:366
88−msgid "Recent searches"
89−msgstr "Buscas recentes"
90−
9187#: qml/Components/PassphraseLockscreen.qml:60
9288#, qt-format
9389msgid "Hello %1"
@@ -109,7 +105,7 @@ msgstr "FEITO"
109105msgid "See more"
110106msgstr "Ver máis"
111107
112−#: qml/Components/SeeMore.qml:58
108+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
113109msgid "See less"
114110msgstr "Ver menos"
115111
@@ -117,6 +113,10 @@ msgstr "Ver menos"
117113msgid "Recent"
118114msgstr "Recentes"
119115
116+#: qml/Dash/GenericScopeView.qml:330
117+msgid "See all"
118+msgstr "Ver todo"
119+
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
122122msgstr "Máis…"
@@ -125,15 +125,15 @@ msgstr "Máis…"
125125msgid "Less..."
126126msgstr "Menos..."
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:82
128+#: qml/Dash/Previews/PreviewRatingInput.qml:81
129129msgid "Rate this"
130130msgstr "Valore isto"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:128
132+#: qml/Dash/Previews/PreviewRatingInput.qml:126
133133msgid "Add a review"
134134msgstr "Engadir unha opinión"
135135
136−#: qml/Dash/Previews/PreviewRatingInput.qml:168
136+#: qml/Dash/Previews/PreviewRatingInput.qml:166
137137msgid "Send"
138138msgstr "Enviar"
139139
@@ -169,6 +169,14 @@ msgstr "Mostrar contrasinal"
169169msgid "Please enter SIM PIN"
170170msgstr "Introduza o PIN da SIM"
171171
172+#: qml/Panel/ActiveCallHint.qml:77
173+msgid "Tap to return to call..."
174+msgstr "Toque para volver a chamar..."
175+
176+#: qml/Panel/ActiveCallHint.qml:90
177+msgid "Conference"
178+msgstr "Conferencia"
179+
172180#: qml/Panel/Indicators/MenuItemFactory.qml:583
173181msgid "In queue…"
174182msgstr "Na cola..."
po/he.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-15 13:20+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-25 16:26+0000\n"
1212"Last-Translator: Yaron <sh.yaron@gmail.com>\n"
1313"Language-Team: Hebrew <he@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-16 07:27+0000\n"
18−"X-Generator: Launchpad (build 17112)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -82,10 +82,6 @@ msgstr "שיחת חירום"
8282msgid "OK"
8383msgstr "אישור"
8484
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "חיפושים אחרונים"
88−
8985#: qml/Components/PassphraseLockscreen.qml:60
9086#, qt-format
9187msgid "Hello %1"
@@ -107,7 +103,7 @@ msgstr "בוצע"
107103msgid "See more"
108104msgstr "לראות עוד"
109105
110−#: qml/Components/SeeMore.qml:58
106+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111107msgid "See less"
112108msgstr "לראות פחות"
113109
@@ -115,6 +111,10 @@ msgstr "לראות פחות"
115111msgid "Recent"
116112msgstr "בשימוש לאחרונה"
117113
114+#: qml/Dash/GenericScopeView.qml:330
115+msgid "See all"
116+msgstr "להציג הכול"
117+
118118#: qml/Dash/Previews/PreviewActionCombo.qml:34
119119msgid "More..."
120120msgstr "עוד…"
@@ -123,15 +123,15 @@ msgstr "עוד…"
123123msgid "Less..."
124124msgstr "פחות…"
125125
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
126+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127127msgid "Rate this"
128128msgstr "דירוג היישום"
129129
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
130+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131131msgid "Add a review"
132132msgstr "הוספת סקירה"
133133
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
134+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135135msgid "Send"
136136msgstr "שליחה"
137137
@@ -167,6 +167,14 @@ msgstr "הצגת הססמה"
167167msgid "Please enter SIM PIN"
168168msgstr "נא להזין את קוד ה־<U+200F>SIM"
169169
170+#: qml/Panel/ActiveCallHint.qml:77
171+msgid "Tap to return to call..."
172+msgstr "יש לגעת כדי להחזיר שיחה…"
173+
174+#: qml/Panel/ActiveCallHint.qml:90
175+msgid "Conference"
176+msgstr "ועידה"
177+
170178#: qml/Panel/Indicators/MenuItemFactory.qml:583
171179msgid "In queue…"
172180msgstr "בתור…"
po/hi.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-15 01:49+0000\n"
1212"Last-Translator: Siddhanathan S. <Unknown>\n"
1313"Language-Team: Hindi <hi@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr "आपातकालीन कॉल"
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "पिछले खोजों"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr "समीक्षा दे"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "भेजें"
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/hr.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-06-27 04:14+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Croatian <hr@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "Nedavne pretrage"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/hu.po+45−35
@@ -7,24 +7,24 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-01-14 23:02+0000\n"
12−"Last-Translator: Kristóf Kiszel <Unknown>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-08-06 07:41+0000\n"
12+"Last-Translator: Richard Somlói <ricsipontaz@gmail.com>\n"
1313"Language-Team: Hungarian <hu@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-08-08 07:07+0000\n"
18+"X-Generator: Launchpad (build 17156)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
2222msgid "Pin shortcut"
23−msgstr ""
23+msgstr "Indító rögzítése"
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:73
2626msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "Indító feloldása"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
@@ -44,7 +44,7 @@ msgstr "Felső szél"
4444
4545#: qml/Components/EdgeDemo.qml:146
4646msgid "Try swiping from the top edge to access the indicators"
47−msgstr "A jelzők eléréséhez csúsztassa ujját a felső szélről"
47+msgstr "Az állapotmenük eléréséhez csúsztassa ujját a felső szélről"
4848
4949#: qml/Components/EdgeDemo.qml:171
5050msgid "Close"
@@ -73,6 +73,8 @@ msgid ""
7373"You have now mastered the edge gestures and can start using the "
7474"phone<br><br>Tap on the screen to start"
7575msgstr ""
76+"Elsajátította a gesztusokat, és megkezdheti a telefon "
77+"használatát.<br><br>Koppintson a képernyőre a kezdéshez."
7678
7779#: qml/Components/Lockscreen.qml:214
7880msgid "Emergency Call"
@@ -80,64 +82,64 @@ msgstr "Vészhívás"
8082
8183#: qml/Components/Lockscreen.qml:231
8284msgid "OK"
83−msgstr ""
84−
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "Legutóbbi keresések"
85+msgstr "Ok"
8886
8987#: qml/Components/PassphraseLockscreen.qml:60
9088#, qt-format
9189msgid "Hello %1"
92−msgstr "Szia %1"
90+msgstr "Üdv %1"
9391
9492#: qml/Components/PassphraseLockscreen.qml:60
9593msgid "Hello"
96−msgstr "Szia"
94+msgstr "Üdvözöljük"
9795
9896#: qml/Components/PinLockscreen.qml:198
9997msgid "CANCEL"
100−msgstr ""
98+msgstr "MÉGSE"
10199
102100#: qml/Components/PinLockscreen.qml:216
103101msgid "DONE"
104−msgstr ""
102+msgstr "KÉSZ"
105103
106104#: qml/Components/SeeMore.qml:35
107105msgid "See more"
108−msgstr ""
106+msgstr "Több"
109107
110−#: qml/Components/SeeMore.qml:58
108+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111109msgid "See less"
112−msgstr ""
110+msgstr "Kevesebb"
113111
114112#: qml/Dash/DashApps.qml:37
115113msgid "Recent"
116−msgstr ""
114+msgstr "Legutóbbi"
115+
116+#: qml/Dash/GenericScopeView.qml:330
117+msgid "See all"
118+msgstr "Összes megtekintése"
117119
118120#: qml/Dash/Previews/PreviewActionCombo.qml:34
119121msgid "More..."
120−msgstr ""
122+msgstr "Több…"
121123
122124#: qml/Dash/Previews/PreviewActionCombo.qml:34
123125msgid "Less..."
124−msgstr ""
126+msgstr "Kevesebb…"
125127
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
128+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127129msgid "Rate this"
128−msgstr "Osztályzás"
130+msgstr "Értékelje"
129131
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
132+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131133msgid "Add a review"
132134msgstr "Értékelés hozzáadása"
133135
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
136+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135137msgid "Send"
136138msgstr "Küldés"
137139
138140#: qml/Greeter/Greeter.qml:157
139141msgid "Swipe to unlock"
140−msgstr ""
142+msgstr "Csúsztasson a feloldáshoz"
141143
142144#: qml/Hud/HudParametrizedActionsPage.qml:132
143145msgid "Confirm"
@@ -165,31 +167,39 @@ msgstr "Jelszó megjelenítése"
165167
166168#: qml/Notifications/NotificationMenuItemFactory.qml:103
167169msgid "Please enter SIM PIN"
168−msgstr ""
170+msgstr "Adja meg a SIM PIN kódját"
171+
172+#: qml/Panel/ActiveCallHint.qml:77
173+msgid "Tap to return to call..."
174+msgstr "Érintse meg, hogy visszatérjen a híváshoz..."
175+
176+#: qml/Panel/ActiveCallHint.qml:90
177+msgid "Conference"
178+msgstr "Konferencia"
169179
170180#: qml/Panel/Indicators/MenuItemFactory.qml:583
171181msgid "In queue…"
172−msgstr ""
182+msgstr "Sorban…"
173183
174184#: qml/Panel/Indicators/MenuItemFactory.qml:587
175185msgid "Downloading"
176−msgstr ""
186+msgstr "Letöltés"
177187
178188#: qml/Panel/Indicators/MenuItemFactory.qml:589
179189msgid "Paused, tap to resume"
180−msgstr ""
190+msgstr "Szüneteltetve, koppintson a folytatáshoz"
181191
182192#: qml/Panel/Indicators/MenuItemFactory.qml:591
183193msgid "Canceled"
184−msgstr ""
194+msgstr "Megszakítva"
185195
186196#: qml/Panel/Indicators/MenuItemFactory.qml:593
187197msgid "Finished"
188−msgstr ""
198+msgstr "Befejeződött"
189199
190200#: qml/Panel/Indicators/MenuItemFactory.qml:595
191201msgid "Failed, tap to retry"
192−msgstr ""
202+msgstr "Sikertelen, koppintson az újrapróbáláshoz"
193203
194204#: qml/Panel/SearchIndicator.qml:27
195205msgid "Search"
po/hy.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-06-27 04:43+0000\n"
1212"Last-Translator: iAbaS <sosabazyan@yandex.ru>\n"
1313"Language-Team: Armenian <hy@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "Վերջին որոնումներ"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/id.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-06-26 22:35+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Indonesian <id@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/is.po+20−12
@@ -9,15 +9,15 @@ msgid ""
99msgstr ""
1010"Project-Id-Version: po_unity8-is\n"
1111"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
12−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
13−"PO-Revision-Date: 2014-07-23 05:57+0000\n"
12+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
13+"PO-Revision-Date: 2014-07-31 16:10+0000\n"
1414"Last-Translator: Sveinn í Felli <sv1@fellsnet.is>\n"
1515"Language-Team: Icelandic <translation-team-is@lists.sourceforge.net>\n"
1616"MIME-Version: 1.0\n"
1717"Content-Type: text/plain; charset=UTF-8\n"
1818"Content-Transfer-Encoding: 8bit\n"
19−"X-Launchpad-Export-Date: 2014-07-23 07:01+0000\n"
20−"X-Generator: Launchpad (build 17114)\n"
19+"X-Launchpad-Export-Date: 2014-08-01 07:14+0000\n"
20+"X-Generator: Launchpad (build 17141)\n"
2121"Language: is\n"
2222
2323#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -86,10 +86,6 @@ msgstr "Neyðarsímtal"
8686msgid "OK"
8787msgstr "Í lagi"
8888
89−#: qml/Components/PageHeader.qml:366
90−msgid "Recent searches"
91−msgstr "Nýlegar leitir"
92−
9389#: qml/Components/PassphraseLockscreen.qml:60
9490#, qt-format
9591msgid "Hello %1"
@@ -111,7 +107,7 @@ msgstr "BÚIÐ"
111107msgid "See more"
112108msgstr "Sjá meira"
113109
114−#: qml/Components/SeeMore.qml:58
110+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
115111msgid "See less"
116112msgstr "Sjá minna"
117113
@@ -119,6 +115,10 @@ msgstr "Sjá minna"
119115msgid "Recent"
120116msgstr "Nýlegt"
121117
118+#: qml/Dash/GenericScopeView.qml:330
119+msgid "See all"
120+msgstr "Sjá allt"
121+
122122#: qml/Dash/Previews/PreviewActionCombo.qml:34
123123msgid "More..."
124124msgstr "Meira..."
@@ -127,15 +127,15 @@ msgstr "Meira..."
127127msgid "Less..."
128128msgstr "Minna..."
129129
130−#: qml/Dash/Previews/PreviewRatingInput.qml:82
130+#: qml/Dash/Previews/PreviewRatingInput.qml:81
131131msgid "Rate this"
132132msgstr "Gefa þessu einkunn"
133133
134−#: qml/Dash/Previews/PreviewRatingInput.qml:128
134+#: qml/Dash/Previews/PreviewRatingInput.qml:126
135135msgid "Add a review"
136136msgstr "Gefa umsögn"
137137
138−#: qml/Dash/Previews/PreviewRatingInput.qml:168
138+#: qml/Dash/Previews/PreviewRatingInput.qml:166
139139msgid "Send"
140140msgstr "Senda"
141141
@@ -171,6 +171,14 @@ msgstr "Birta lykilorð"
171171msgid "Please enter SIM PIN"
172172msgstr "Settu inn PIN fyrir SIM"
173173
174+#: qml/Panel/ActiveCallHint.qml:77
175+msgid "Tap to return to call..."
176+msgstr "Slá til að svara símtali..."
177+
178+#: qml/Panel/ActiveCallHint.qml:90
179+msgid "Conference"
180+msgstr "Ráðstefna"
181+
174182#: qml/Panel/Indicators/MenuItemFactory.qml:583
175183msgid "In queue…"
176184msgstr "Í biðröð..."
po/it.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-09 07:07+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-25 16:09+0000\n"
1212"Last-Translator: Claudio Arseni <claudio.arseni@gmail.com>\n"
1313"Language-Team: Italian <it@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-10 07:29+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -87,10 +87,6 @@ msgstr "Chiamata di emergenza"
8787msgid "OK"
8888msgstr "OK"
8989
90−#: qml/Components/PageHeader.qml:366
91−msgid "Recent searches"
92−msgstr "Ricerche recenti"
93−
9490#: qml/Components/PassphraseLockscreen.qml:60
9591#, qt-format
9692msgid "Hello %1"
@@ -112,7 +108,7 @@ msgstr "Fatto"
112108msgid "See more"
113109msgstr "Mostra di più"
114110
115−#: qml/Components/SeeMore.qml:58
111+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
116112msgid "See less"
117113msgstr "Mostra meno"
118114
@@ -120,6 +116,10 @@ msgstr "Mostra meno"
120116msgid "Recent"
121117msgstr "Recenti"
122118
119+#: qml/Dash/GenericScopeView.qml:330
120+msgid "See all"
121+msgstr "Mostra tutto"
122+
123123#: qml/Dash/Previews/PreviewActionCombo.qml:34
124124msgid "More..."
125125msgstr "Altro..."
@@ -128,15 +128,15 @@ msgstr "Altro..."
128128msgid "Less..."
129129msgstr "Meno..."
130130
131−#: qml/Dash/Previews/PreviewRatingInput.qml:82
131+#: qml/Dash/Previews/PreviewRatingInput.qml:81
132132msgid "Rate this"
133133msgstr "Valuta"
134134
135−#: qml/Dash/Previews/PreviewRatingInput.qml:128
135+#: qml/Dash/Previews/PreviewRatingInput.qml:126
136136msgid "Add a review"
137137msgstr "Aggiungi una recensione"
138138
139−#: qml/Dash/Previews/PreviewRatingInput.qml:168
139+#: qml/Dash/Previews/PreviewRatingInput.qml:166
140140msgid "Send"
141141msgstr "Invia"
142142
@@ -172,6 +172,14 @@ msgstr "Mostra password"
172172msgid "Please enter SIM PIN"
173173msgstr "Inserire il codice PIN"
174174
175+#: qml/Panel/ActiveCallHint.qml:77
176+msgid "Tap to return to call..."
177+msgstr "Tocca per tornare alla chiamata..."
178+
179+#: qml/Panel/ActiveCallHint.qml:90
180+msgid "Conference"
181+msgstr "Conferenza"
182+
175183#: qml/Panel/Indicators/MenuItemFactory.qml:583
176184msgid "In queue…"
177185msgstr "In coda..."
po/ja.po+32−24
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-01-18 07:01+0000\n"
12−"Last-Translator: Shushi Kurose <md81bird@hitaki.net>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-08-08 06:18+0000\n"
12+"Last-Translator: Mitsuya Shibata <mty.shibata@gmail.com>\n"
1313"Language-Team: Japanese <ja@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-08-08 07:07+0000\n"
18+"X-Generator: Launchpad (build 17156)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -28,7 +28,7 @@ msgstr ""
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
31−msgstr ""
31+msgstr "導入ガイドをスキップ"
3232
3333#: qml/Components/EdgeDemo.qml:113
3434msgid "Right edge"
@@ -44,7 +44,7 @@ msgstr "上端"
4444
4545#: qml/Components/EdgeDemo.qml:146
4646msgid "Try swiping from the top edge to access the indicators"
47−msgstr ""
47+msgstr "インジケーターにアクセスするには上端からスワイプしてみてください"
4848
4949#: qml/Components/EdgeDemo.qml:171
5050msgid "Close"
@@ -52,7 +52,7 @@ msgstr "閉じる"
5252
5353#: qml/Components/EdgeDemo.qml:172
5454msgid "Swipe up again to close the settings screen"
55−msgstr ""
55+msgstr "設定画面を閉じるにはもう一度上にスワイプしてください"
5656
5757#: qml/Components/EdgeDemo.qml:199
5858msgid "Left edge"
@@ -60,11 +60,11 @@ msgstr "左端"
6060
6161#: qml/Components/EdgeDemo.qml:200
6262msgid "Swipe from the left to reveal the launcher for quick access to apps"
63−msgstr ""
63+msgstr "アプリに素早くアクセスできるLauncherを表示するには左からスワイプしてください"
6464
6565#: qml/Components/EdgeDemo.qml:227
6666msgid "Well done"
67−msgstr ""
67+msgstr "よくできました!"
6868
6969#: qml/Components/EdgeDemo.qml:228
7070msgid ""
@@ -74,20 +74,16 @@ msgstr ""
7474
7575#: qml/Components/Lockscreen.qml:214
7676msgid "Emergency Call"
77−msgstr ""
77+msgstr "緊急通報"
7878
7979#: qml/Components/Lockscreen.qml:231
8080msgid "OK"
81−msgstr ""
82−
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "最近の検索"
81+msgstr "OK"
8682
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
90−msgstr ""
86+msgstr "こんにちは %1 さん"
9187
9288#: qml/Components/PassphraseLockscreen.qml:60
9389msgid "Hello"
@@ -103,9 +99,9 @@ msgstr ""
10399
104100#: qml/Components/SeeMore.qml:35
105101msgid "See more"
106−msgstr ""
102+msgstr "さらに表示する"
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130−msgstr ""
130+msgstr "レビューを追加"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "送信"
135135
@@ -155,7 +155,7 @@ msgstr "音声入力を開始..."
155155
156156#: qml/Hud/Hud.qml:94
157157msgid "Speaking..."
158−msgstr ""
158+msgstr "入力中..."
159159
160160#: qml/Notifications/NotificationMenuItemFactory.qml:91
161161msgid "Show password"
@@ -165,6 +165,14 @@ msgstr "パスワードを表示"
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/km.po+21−13
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-16 01:37+0000\n"
12−"Last-Translator: Khoem Sokhem <khoemsokhem@khmeros.info>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-08-01 04:02+0000\n"
12+"Last-Translator: Sok Sophea <sksophea@gmail.com>\n"
1313"Language-Team: Khmer <km@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-17 06:38+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-08-02 06:39+0000\n"
18+"X-Generator: Launchpad (build 17147)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -84,10 +84,6 @@ msgstr "ការ​ហៅ​ពេល​អាសន្ន"
8484msgid "OK"
8585msgstr "យល់ព្រម"
8686
87−#: qml/Components/PageHeader.qml:366
88−msgid "Recent searches"
89−msgstr "ការ​ស្វែងរក​ថ្មី"
90−
9187#: qml/Components/PassphraseLockscreen.qml:60
9288#, qt-format
9389msgid "Hello %1"
@@ -109,7 +105,7 @@ msgstr "រួចរាល់"
109105msgid "See more"
110106msgstr "មើល​ច្រើន​ទៀត"
111107
112−#: qml/Components/SeeMore.qml:58
108+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
113109msgid "See less"
114110msgstr "មើល​តិច​ជាង"
115111
@@ -117,6 +113,10 @@ msgstr "មើល​តិច​ជាង"
117113msgid "Recent"
118114msgstr "បច្ចុប្បន្ន"
119115
116+#: qml/Dash/GenericScopeView.qml:330
117+msgid "See all"
118+msgstr "មើល​ទាំងអស់"
119+
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
122122msgstr "ច្រើនជាង​..."
@@ -125,15 +125,15 @@ msgstr "ច្រើនជាង​..."
125125msgid "Less..."
126126msgstr "តិច​ជាង..."
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:82
128+#: qml/Dash/Previews/PreviewRatingInput.qml:81
129129msgid "Rate this"
130130msgstr "វាយតម្លៃ​វា"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:128
132+#: qml/Dash/Previews/PreviewRatingInput.qml:126
133133msgid "Add a review"
134134msgstr "បន្ថែម​ការ​ពិនិត្យ"
135135
136−#: qml/Dash/Previews/PreviewRatingInput.qml:168
136+#: qml/Dash/Previews/PreviewRatingInput.qml:166
137137msgid "Send"
138138msgstr "ផ្ញើ"
139139
@@ -169,6 +169,14 @@ msgstr "បង្ហាញ​ពាក្យ​សម្ងាត់"
169169msgid "Please enter SIM PIN"
170170msgstr "បញ្ចូល​កូដ PIN របស់​ស៊ីមកាត"
171171
172+#: qml/Panel/ActiveCallHint.qml:77
173+msgid "Tap to return to call..."
174+msgstr "ប៉ះ​ដើម្បី​ត្រឡប់​ទៅ​ការ​ហៅ..."
175+
176+#: qml/Panel/ActiveCallHint.qml:90
177+msgid "Conference"
178+msgstr "សន្និសីទ"
179+
172180#: qml/Panel/Indicators/MenuItemFactory.qml:583
173181msgid "In queue…"
174182msgstr "ក្នុងជួរ…"
po/kn.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-06-27 05:43+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Kannada <kn@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "ಇತ್ತೀಚಿನ ಹುಡುಕಾಟಗಳು"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/ko.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-07-17 03:56+0000\n"
1212"Last-Translator: MinSik CHO <Unknown>\n"
1313"Language-Team: Korean <ko@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-18 05:28+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -82,10 +82,6 @@ msgstr "긴급 통화"
8282msgid "OK"
8383msgstr "확인"
8484
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "최근 검색"
88−
8985#: qml/Components/PassphraseLockscreen.qml:60
9086#, qt-format
9187msgid "Hello %1"
@@ -107,7 +103,7 @@ msgstr "완료"
107103msgid "See more"
108104msgstr "더 보기"
109105
110−#: qml/Components/SeeMore.qml:58
106+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111107msgid "See less"
112108msgstr "간단히 표시하기"
113109
@@ -115,6 +111,10 @@ msgstr "간단히 표시하기"
115111msgid "Recent"
116112msgstr "최근"
117113
114+#: qml/Dash/GenericScopeView.qml:330
115+msgid "See all"
116+msgstr ""
117+
118118#: qml/Dash/Previews/PreviewActionCombo.qml:34
119119msgid "More..."
120120msgstr "더 보기..."
@@ -123,15 +123,15 @@ msgstr "더 보기..."
123123msgid "Less..."
124124msgstr "간단하게..."
125125
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
126+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127127msgid "Rate this"
128128msgstr "이 애플리케이션 평가하기"
129129
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
130+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131131msgid "Add a review"
132132msgstr "평가 제출하기"
133133
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
134+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135135msgid "Send"
136136msgstr "보내기"
137137
@@ -167,6 +167,14 @@ msgstr "비밀 번호 보기"
167167msgid "Please enter SIM PIN"
168168msgstr "심카드의 PIN 번호를 입력하세요."
169169
170+#: qml/Panel/ActiveCallHint.qml:77
171+msgid "Tap to return to call..."
172+msgstr ""
173+
174+#: qml/Panel/ActiveCallHint.qml:90
175+msgid "Conference"
176+msgstr ""
177+
170178#: qml/Panel/Indicators/MenuItemFactory.qml:583
171179msgid "In queue…"
172180msgstr "재생 중..."
po/ky.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-06-27 06:17+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Kirghiz <ky@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "Соңку издөөлөр"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/lo.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-10-02 10:00+0000\n"
1212"Last-Translator: Anousak <anousak@gmail.com>\n"
1313"Language-Team: Lao <lo@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "ສົ່ງ"
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/lt.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-05-19 17:15+0000\n"
1212"Last-Translator: Mantas Kriaučiūnas <mantas@akl.lt>\n"
1313"Language-Team: Lithuanian <lt@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -83,10 +83,6 @@ msgstr "Pagalbos skambutis"
8383msgid "OK"
8484msgstr ""
8585
86−#: qml/Components/PageHeader.qml:366
87−msgid "Recent searches"
88−msgstr "Paskiausios paieškos"
89−
9086#: qml/Components/PassphraseLockscreen.qml:60
9187#, qt-format
9288msgid "Hello %1"
@@ -108,7 +104,7 @@ msgstr ""
108104msgid "See more"
109105msgstr ""
110106
111−#: qml/Components/SeeMore.qml:58
107+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
112108msgid "See less"
113109msgstr ""
114110
@@ -116,6 +112,10 @@ msgstr ""
116112msgid "Recent"
117113msgstr "Paskiausieji"
118114
115+#: qml/Dash/GenericScopeView.qml:330
116+msgid "See all"
117+msgstr ""
118+
119119#: qml/Dash/Previews/PreviewActionCombo.qml:34
120120msgid "More..."
121121msgstr "Daugiau..."
@@ -124,15 +124,15 @@ msgstr "Daugiau..."
124124msgid "Less..."
125125msgstr "Mažiau..."
126126
127−#: qml/Dash/Previews/PreviewRatingInput.qml:82
127+#: qml/Dash/Previews/PreviewRatingInput.qml:81
128128msgid "Rate this"
129129msgstr "Įvertinkite tai"
130130
131−#: qml/Dash/Previews/PreviewRatingInput.qml:128
131+#: qml/Dash/Previews/PreviewRatingInput.qml:126
132132msgid "Add a review"
133133msgstr "Pridėkite apžvalgą"
134134
135−#: qml/Dash/Previews/PreviewRatingInput.qml:168
135+#: qml/Dash/Previews/PreviewRatingInput.qml:166
136136msgid "Send"
137137msgstr "Siųsti"
138138
@@ -168,6 +168,14 @@ msgstr "Rodyti slaptažodį"
168168msgid "Please enter SIM PIN"
169169msgstr "Įveskite SIM kortelės PIN kodą"
170170
171+#: qml/Panel/ActiveCallHint.qml:77
172+msgid "Tap to return to call..."
173+msgstr ""
174+
175+#: qml/Panel/ActiveCallHint.qml:90
176+msgid "Conference"
177+msgstr ""
178+
171179#: qml/Panel/Indicators/MenuItemFactory.qml:583
172180msgid "In queue…"
173181msgstr ""
po/lv.po+23−15
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-15 12:13+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-26 16:21+0000\n"
1212"Last-Translator: Jānis-Marks Gailis <jm-gailis@fai-vianet.fr>\n"
1313"Language-Team: Latvian <lv@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-16 07:27+0000\n"
18−"X-Generator: Launchpad (build 17112)\n"
17+"X-Launchpad-Export-Date: 2014-07-27 06:35+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr "Neatliekamās Palīdzības zvans"
8080msgid "OK"
8181msgstr "LABI"
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "Nesen veiktās meklēšanas"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr "IZDARĪTS"
105101msgid "See more"
106102msgstr "Redzēt vairāk"
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr "Redzēt mazāk"
111107
@@ -113,6 +109,10 @@ msgstr "Redzēt mazāk"
113109msgid "Recent"
114110msgstr "Nesens"
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr "Skatīt visus"
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr "Vairāk..."
@@ -121,15 +121,15 @@ msgstr "Vairāk..."
121121msgid "Less..."
122122msgstr "Mazāk..."
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr "Novērtēt šo"
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr "Komentēt"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "Sūtīt"
135135
@@ -165,13 +165,21 @@ msgstr "Rādīt paroli"
165165msgid "Please enter SIM PIN"
166166msgstr "Lūdzu ievadiet SIM PIN"
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr "Konference"
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
171179
172180#: qml/Panel/Indicators/MenuItemFactory.qml:587
173181msgid "Downloading"
174−msgstr ""
182+msgstr "Lejupielādē"
175183
176184#: qml/Panel/Indicators/MenuItemFactory.qml:589
177185msgid "Paused, tap to resume"
@@ -179,11 +187,11 @@ msgstr ""
179187
180188#: qml/Panel/Indicators/MenuItemFactory.qml:591
181189msgid "Canceled"
182−msgstr ""
190+msgstr "Atcelts"
183191
184192#: qml/Panel/Indicators/MenuItemFactory.qml:593
185193msgid "Finished"
186−msgstr ""
194+msgstr "Pabeigts"
187195
188196#: qml/Panel/Indicators/MenuItemFactory.qml:595
189197msgid "Failed, tap to retry"
po/ml.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-11-23 11:44+0000\n"
12−"Last-Translator: Stym alfaZ <Unknown>\n"
12+"Last-Translator: ST Alfas <Unknown>\n"
1313"Language-Team: Malayalam <ml@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -82,10 +82,6 @@ msgstr "അടിയന്തിര വിളി"
8282msgid "OK"
8383msgstr ""
8484
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "സമീപകാല തിരയലുകള്‍"
88−
8985#: qml/Components/PassphraseLockscreen.qml:60
9086#, qt-format
9187msgid "Hello %1"
@@ -107,7 +103,7 @@ msgstr ""
107103msgid "See more"
108104msgstr ""
109105
110−#: qml/Components/SeeMore.qml:58
106+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111107msgid "See less"
112108msgstr ""
113109
@@ -115,6 +111,10 @@ msgstr ""
115111msgid "Recent"
116112msgstr ""
117113
114+#: qml/Dash/GenericScopeView.qml:330
115+msgid "See all"
116+msgstr ""
117+
118118#: qml/Dash/Previews/PreviewActionCombo.qml:34
119119msgid "More..."
120120msgstr ""
@@ -123,15 +123,15 @@ msgstr ""
123123msgid "Less..."
124124msgstr ""
125125
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
126+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127127msgid "Rate this"
128128msgstr "ഇത് അവലോകനം ചെയ്യുക"
129129
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
130+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131131msgid "Add a review"
132132msgstr "ഒരു അവലോകനം ചേര്‍ക്കുക"
133133
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
134+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135135msgid "Send"
136136msgstr "അയയ്‌ക്കുക"
137137
@@ -167,6 +167,14 @@ msgstr "രഹസ്യവാക്ക് കാണിക്കുക"
167167msgid "Please enter SIM PIN"
168168msgstr ""
169169
170+#: qml/Panel/ActiveCallHint.qml:77
171+msgid "Tap to return to call..."
172+msgstr ""
173+
174+#: qml/Panel/ActiveCallHint.qml:90
175+msgid "Conference"
176+msgstr ""
177+
170178#: qml/Panel/Indicators/MenuItemFactory.qml:583
171179msgid "In queue…"
172180msgstr ""
po/mr.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-14 19:54+0000\n"
1212"Last-Translator: Rohan Deshmukh <Unknown>\n"
1313"Language-Team: Marathi <mr@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/ms.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-17 09:05+0000\n"
1212"Last-Translator: abuyop <Unknown>\n"
1313"Language-Team: Malay <ms@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr "panggilan Kecemasan"
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "Gelintar baru-baru ini"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr "Kadar ini"
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr "Tambah ulasan"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "Hantar"
135135
@@ -165,6 +165,14 @@ msgstr "Tunjuk kata laluan"
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/my.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-12-12 11:12+0000\n"
1212"Last-Translator: Pyae Sone <Unknown>\n"
1313"Language-Team: Burmese <my@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr "အရေးပေါ်ခေါ်မည်"
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "မကြာသေးခင်က ရှာဖွေခြင်း"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr "ဒီဟာကိုအမှတ်ပေးမည်"
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "ပို့မည်"
135135
@@ -165,6 +165,14 @@ msgstr "စကားဝှက်ကိုပြ"
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/nb.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-11 07:01+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-26 12:05+0000\n"
1212"Last-Translator: Åka Sikrom <Unknown>\n"
1313"Language-Team: Norwegian Bokmal <nb@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-12 06:58+0000\n"
18−"X-Generator: Launchpad (build 17111)\n"
17+"X-Launchpad-Export-Date: 2014-07-27 06:35+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -82,10 +82,6 @@ msgstr "Nødanrop"
8282msgid "OK"
8383msgstr "OK"
8484
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "Nylige søk"
88−
8985#: qml/Components/PassphraseLockscreen.qml:60
9086#, qt-format
9187msgid "Hello %1"
@@ -107,7 +103,7 @@ msgstr "FERDIG"
107103msgid "See more"
108104msgstr "Vis mer"
109105
110−#: qml/Components/SeeMore.qml:58
106+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111107msgid "See less"
112108msgstr "Vis mindre"
113109
@@ -115,6 +111,10 @@ msgstr "Vis mindre"
115111msgid "Recent"
116112msgstr "Nylig"
117113
114+#: qml/Dash/GenericScopeView.qml:330
115+msgid "See all"
116+msgstr "Vis alt"
117+
118118#: qml/Dash/Previews/PreviewActionCombo.qml:34
119119msgid "More..."
120120msgstr "Mer …"
@@ -123,15 +123,15 @@ msgstr "Mer …"
123123msgid "Less..."
124124msgstr "Mindre …"
125125
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
126+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127127msgid "Rate this"
128128msgstr "Vurder dette"
129129
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
130+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131131msgid "Add a review"
132132msgstr "Skriv en anmeldelse"
133133
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
134+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135135msgid "Send"
136136msgstr "Send"
137137
@@ -167,6 +167,14 @@ msgstr "Vis passord"
167167msgid "Please enter SIM PIN"
168168msgstr "Skriv inn PIN-koden til SIM-kortet"
169169
170+#: qml/Panel/ActiveCallHint.qml:77
171+msgid "Tap to return to call..."
172+msgstr "Trykk for å gå tilbake til anrop …"
173+
174+#: qml/Panel/ActiveCallHint.qml:90
175+msgid "Conference"
176+msgstr "Konferanse"
177+
170178#: qml/Panel/Indicators/MenuItemFactory.qml:583
171179msgid "In queue…"
172180msgstr "I kø …"
po/nl.po+21−13
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-20 17:25+0000\n"
12−"Last-Translator: Hannie Dumoleyn <Unknown>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-27 19:12+0000\n"
12+"Last-Translator: rob <linuxned@gmail.com>\n"
1313"Language-Team: Dutch <nl@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-21 07:05+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-28 06:44+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -82,10 +82,6 @@ msgstr "Noodoproep"
8282msgid "OK"
8383msgstr "Ok"
8484
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "Recente zoekopdrachten"
88−
8985#: qml/Components/PassphraseLockscreen.qml:60
9086#, qt-format
9187msgid "Hello %1"
@@ -107,7 +103,7 @@ msgstr "KLAAR"
107103msgid "See more"
108104msgstr "Meer zien"
109105
110−#: qml/Components/SeeMore.qml:58
106+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111107msgid "See less"
112108msgstr "Minder zien"
113109
@@ -115,6 +111,10 @@ msgstr "Minder zien"
115111msgid "Recent"
116112msgstr "Recent"
117113
114+#: qml/Dash/GenericScopeView.qml:330
115+msgid "See all"
116+msgstr "Alles zien"
117+
118118#: qml/Dash/Previews/PreviewActionCombo.qml:34
119119msgid "More..."
120120msgstr "Meer…"
@@ -123,15 +123,15 @@ msgstr "Meer…"
123123msgid "Less..."
124124msgstr "Minder…"
125125
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
126+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127127msgid "Rate this"
128128msgstr "Beoordeel dit"
129129
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
130+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131131msgid "Add a review"
132132msgstr "Voeg recensie toe"
133133
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
134+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135135msgid "Send"
136136msgstr "Versturen"
137137
@@ -167,6 +167,14 @@ msgstr "Wachtwoord tonen"
167167msgid "Please enter SIM PIN"
168168msgstr "Voer SIM-pincode in"
169169
170+#: qml/Panel/ActiveCallHint.qml:77
171+msgid "Tap to return to call..."
172+msgstr "Tik om terug te keren naar gesprek…"
173+
174+#: qml/Panel/ActiveCallHint.qml:90
175+msgid "Conference"
176+msgstr "Groepsgesprek"
177+
170178#: qml/Panel/Indicators/MenuItemFactory.qml:583
171179msgid "In queue…"
172180msgstr "In wachtrij…"
po/pl.po+21−13
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-19 14:10+0000\n"
12−"Last-Translator: GTriderXC <gtriderxc@yahoo.com>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-31 13:51+0000\n"
12+"Last-Translator: Michał Radwański <radwanski.michal@outlook.com>\n"
1313"Language-Team: Polish <pl@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-20 06:18+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-08-01 07:14+0000\n"
18+"X-Generator: Launchpad (build 17141)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -84,10 +84,6 @@ msgstr "Telefon ratunkowy"
8484msgid "OK"
8585msgstr "OK"
8686
87−#: qml/Components/PageHeader.qml:366
88−msgid "Recent searches"
89−msgstr "Ostatnie wyszukiwania"
90−
9187#: qml/Components/PassphraseLockscreen.qml:60
9288#, qt-format
9389msgid "Hello %1"
@@ -109,7 +105,7 @@ msgstr "ZROBIONE"
109105msgid "See more"
110106msgstr "Zobacz więcej"
111107
112−#: qml/Components/SeeMore.qml:58
108+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
113109msgid "See less"
114110msgstr "Zobacz mniej"
115111
@@ -117,6 +113,10 @@ msgstr "Zobacz mniej"
117113msgid "Recent"
118114msgstr "Ostatnio używane"
119115
116+#: qml/Dash/GenericScopeView.qml:330
117+msgid "See all"
118+msgstr "Zobacz wszystko"
119+
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
122122msgstr "Więcej..."
@@ -125,15 +125,15 @@ msgstr "Więcej..."
125125msgid "Less..."
126126msgstr "Mniej..."
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:82
128+#: qml/Dash/Previews/PreviewRatingInput.qml:81
129129msgid "Rate this"
130130msgstr "Oceń to"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:128
132+#: qml/Dash/Previews/PreviewRatingInput.qml:126
133133msgid "Add a review"
134134msgstr "Dodaj recenzję"
135135
136−#: qml/Dash/Previews/PreviewRatingInput.qml:168
136+#: qml/Dash/Previews/PreviewRatingInput.qml:166
137137msgid "Send"
138138msgstr "Wyślij"
139139
@@ -169,6 +169,14 @@ msgstr "Wyświetl hasło"
169169msgid "Please enter SIM PIN"
170170msgstr "Wprowadź kod PIN karty SIM"
171171
172+#: qml/Panel/ActiveCallHint.qml:77
173+msgid "Tap to return to call..."
174+msgstr "Dotknij aby powrócić do połączenia..."
175+
176+#: qml/Panel/ActiveCallHint.qml:90
177+msgid "Conference"
178+msgstr "Konferencja"
179+
172180#: qml/Panel/Indicators/MenuItemFactory.qml:583
173181msgid "In queue…"
174182msgstr "W kolejce..."
po/pt.po+21−13
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-18 22:56+0000\n"
12−"Last-Translator: Hugo Cardoso <hugocardoso94@gmail.com>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-25 12:04+0000\n"
12+"Last-Translator: Ivo Xavier <ivofernandes12@gmail.com>\n"
1313"Language-Team: Portuguese <pt@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-19 06:19+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -83,10 +83,6 @@ msgstr "Chamada de emergência"
8383msgid "OK"
8484msgstr "OK"
8585
86−#: qml/Components/PageHeader.qml:366
87−msgid "Recent searches"
88−msgstr "Pesquisas recentes"
89−
9086#: qml/Components/PassphraseLockscreen.qml:60
9187#, qt-format
9288msgid "Hello %1"
@@ -108,7 +104,7 @@ msgstr "FEITO"
108104msgid "See more"
109105msgstr "Ver mais"
110106
111−#: qml/Components/SeeMore.qml:58
107+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
112108msgid "See less"
113109msgstr "Ver menos"
114110
@@ -116,6 +112,10 @@ msgstr "Ver menos"
116112msgid "Recent"
117113msgstr "Recentes"
118114
115+#: qml/Dash/GenericScopeView.qml:330
116+msgid "See all"
117+msgstr "Ver todos"
118+
119119#: qml/Dash/Previews/PreviewActionCombo.qml:34
120120msgid "More..."
121121msgstr "Mais..."
@@ -124,15 +124,15 @@ msgstr "Mais..."
124124msgid "Less..."
125125msgstr "Menos..."
126126
127−#: qml/Dash/Previews/PreviewRatingInput.qml:82
127+#: qml/Dash/Previews/PreviewRatingInput.qml:81
128128msgid "Rate this"
129129msgstr "Classifique isto"
130130
131−#: qml/Dash/Previews/PreviewRatingInput.qml:128
131+#: qml/Dash/Previews/PreviewRatingInput.qml:126
132132msgid "Add a review"
133133msgstr "Adicione uma crítica"
134134
135−#: qml/Dash/Previews/PreviewRatingInput.qml:168
135+#: qml/Dash/Previews/PreviewRatingInput.qml:166
136136msgid "Send"
137137msgstr "Enviar"
138138
@@ -168,6 +168,14 @@ msgstr "Mostrar palavra-passe"
168168msgid "Please enter SIM PIN"
169169msgstr "Por favor insira o PIN"
170170
171+#: qml/Panel/ActiveCallHint.qml:77
172+msgid "Tap to return to call..."
173+msgstr "Tocar para ligar de volta..."
174+
175+#: qml/Panel/ActiveCallHint.qml:90
176+msgid "Conference"
177+msgstr "Conferência"
178+
171179#: qml/Panel/Indicators/MenuItemFactory.qml:583
172180msgid "In queue…"
173181msgstr "Em fila..."
po/pt_BR.po+28−20
@@ -7,24 +7,24 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-17 05:46+0000\n"
12−"Last-Translator: Tiago Hillebrandt <tiagohillebrandt@gmail.com>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-08-07 12:34+0000\n"
12+"Last-Translator: Salomão Carneiro de Brito <salomaocar@gmail.com>\n"
1313"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-18 05:28+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-08-08 07:07+0000\n"
18+"X-Generator: Launchpad (build 17156)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
2222msgid "Pin shortcut"
23−msgstr ""
23+msgstr "Fixar atalho"
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:73
2626msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "Desafixar atalho"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
@@ -84,10 +84,6 @@ msgstr "Chamada de emergência"
8484msgid "OK"
8585msgstr "OK"
8686
87−#: qml/Components/PageHeader.qml:366
88−msgid "Recent searches"
89−msgstr "Pesquisas recentes"
90−
9187#: qml/Components/PassphraseLockscreen.qml:60
9288#, qt-format
9389msgid "Hello %1"
@@ -103,13 +99,13 @@ msgstr "CANCELAR"
10399
104100#: qml/Components/PinLockscreen.qml:216
105101msgid "DONE"
106−msgstr ""
102+msgstr "FEITO"
107103
108104#: qml/Components/SeeMore.qml:35
109105msgid "See more"
110106msgstr "Ver mais"
111107
112−#: qml/Components/SeeMore.qml:58
108+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
113109msgid "See less"
114110msgstr "Ver menos"
115111
@@ -117,6 +113,10 @@ msgstr "Ver menos"
117113msgid "Recent"
118114msgstr "Recentes"
119115
116+#: qml/Dash/GenericScopeView.qml:330
117+msgid "See all"
118+msgstr "Ver todos"
119+
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
122122msgstr "Mais..."
@@ -125,15 +125,15 @@ msgstr "Mais..."
125125msgid "Less..."
126126msgstr "Menos..."
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:82
128+#: qml/Dash/Previews/PreviewRatingInput.qml:81
129129msgid "Rate this"
130130msgstr "Avaliar isto"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:128
132+#: qml/Dash/Previews/PreviewRatingInput.qml:126
133133msgid "Add a review"
134134msgstr "Adicionar uma análise"
135135
136−#: qml/Dash/Previews/PreviewRatingInput.qml:168
136+#: qml/Dash/Previews/PreviewRatingInput.qml:166
137137msgid "Send"
138138msgstr "Enviar"
139139
@@ -169,9 +169,17 @@ msgstr "Exibir senha"
169169msgid "Please enter SIM PIN"
170170msgstr "Por favor, digite o PIN do cartão SIM"
171171
172+#: qml/Panel/ActiveCallHint.qml:77
173+msgid "Tap to return to call..."
174+msgstr "Toque para retornar para a chamada..."
175+
176+#: qml/Panel/ActiveCallHint.qml:90
177+msgid "Conference"
178+msgstr "Conferência"
179+
172180#: qml/Panel/Indicators/MenuItemFactory.qml:583
173181msgid "In queue…"
174−msgstr ""
182+msgstr "Em fila..."
175183
176184#: qml/Panel/Indicators/MenuItemFactory.qml:587
177185msgid "Downloading"
@@ -179,7 +187,7 @@ msgstr "Baixando"
179187
180188#: qml/Panel/Indicators/MenuItemFactory.qml:589
181189msgid "Paused, tap to resume"
182−msgstr ""
190+msgstr "Em pausa, toque para continuar"
183191
184192#: qml/Panel/Indicators/MenuItemFactory.qml:591
185193msgid "Canceled"
@@ -187,11 +195,11 @@ msgstr "Cancelado"
187195
188196#: qml/Panel/Indicators/MenuItemFactory.qml:593
189197msgid "Finished"
190−msgstr ""
198+msgstr "Finalizado"
191199
192200#: qml/Panel/Indicators/MenuItemFactory.qml:595
193201msgid "Failed, tap to retry"
194−msgstr ""
202+msgstr "Falhou, toque para tentar novamente"
195203
196204#: qml/Panel/SearchIndicator.qml:27
197205msgid "Search"
po/ro.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-06-27 07:53+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Romanian <ro@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "Căutări recente"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/ru.po+32−24
@@ -7,24 +7,24 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-05-15 12:57+0000\n"
12−"Last-Translator: Zonov Roman <Unknown>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-31 09:39+0000\n"
12+"Last-Translator: Jay ZDLin <Unknown>\n"
1313"Language-Team: Russian <ru@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-08-01 07:14+0000\n"
18+"X-Generator: Launchpad (build 17141)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
2222msgid "Pin shortcut"
23−msgstr ""
23+msgstr "Закрепить ярлык"
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:73
2626msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "Изъять ярлык"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
@@ -85,11 +85,7 @@ msgstr "Экстренный вызов"
8585
8686#: qml/Components/Lockscreen.qml:231
8787msgid "OK"
88−msgstr ""
89−
90−#: qml/Components/PageHeader.qml:366
91−msgid "Recent searches"
92−msgstr "Последние поисковые запросы"
88+msgstr "ОК"
9389
9490#: qml/Components/PassphraseLockscreen.qml:60
9591#, qt-format
@@ -102,17 +98,17 @@ msgstr "Привет"
10298
10399#: qml/Components/PinLockscreen.qml:198
104100msgid "CANCEL"
105−msgstr ""
101+msgstr "ОТМЕНИТЬ"
106102
107103#: qml/Components/PinLockscreen.qml:216
108104msgid "DONE"
109−msgstr ""
105+msgstr "ГОТОВО"
110106
111107#: qml/Components/SeeMore.qml:35
112108msgid "See more"
113109msgstr "Подробнее"
114110
115−#: qml/Components/SeeMore.qml:58
111+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
116112msgid "See less"
117113msgstr "Вкратце"
118114
@@ -120,6 +116,10 @@ msgstr "Вкратце"
120116msgid "Recent"
121117msgstr "Недавние"
122118
119+#: qml/Dash/GenericScopeView.qml:330
120+msgid "See all"
121+msgstr "Показать всё"
122+
123123#: qml/Dash/Previews/PreviewActionCombo.qml:34
124124msgid "More..."
125125msgstr "Ещё..."
@@ -128,15 +128,15 @@ msgstr "Ещё..."
128128msgid "Less..."
129129msgstr "Меньше..."
130130
131−#: qml/Dash/Previews/PreviewRatingInput.qml:82
131+#: qml/Dash/Previews/PreviewRatingInput.qml:81
132132msgid "Rate this"
133133msgstr "Оцените это"
134134
135−#: qml/Dash/Previews/PreviewRatingInput.qml:128
135+#: qml/Dash/Previews/PreviewRatingInput.qml:126
136136msgid "Add a review"
137137msgstr "Добавьте отзыв"
138138
139−#: qml/Dash/Previews/PreviewRatingInput.qml:168
139+#: qml/Dash/Previews/PreviewRatingInput.qml:166
140140msgid "Send"
141141msgstr "Отправить"
142142
@@ -172,29 +172,37 @@ msgstr "Показать пароль"
172172msgid "Please enter SIM PIN"
173173msgstr "Введите PIN код"
174174
175+#: qml/Panel/ActiveCallHint.qml:77
176+msgid "Tap to return to call..."
177+msgstr "Коснитесь для возврата к вызову..."
178+
179+#: qml/Panel/ActiveCallHint.qml:90
180+msgid "Conference"
181+msgstr "Конференция"
182+
175183#: qml/Panel/Indicators/MenuItemFactory.qml:583
176184msgid "In queue…"
177−msgstr ""
185+msgstr "В очереди..."
178186
179187#: qml/Panel/Indicators/MenuItemFactory.qml:587
180188msgid "Downloading"
181−msgstr ""
189+msgstr "Загрузка"
182190
183191#: qml/Panel/Indicators/MenuItemFactory.qml:589
184192msgid "Paused, tap to resume"
185−msgstr ""
193+msgstr "Приостановлено, коснитесь для возобновления"
186194
187195#: qml/Panel/Indicators/MenuItemFactory.qml:591
188196msgid "Canceled"
189−msgstr ""
197+msgstr "Отменено"
190198
191199#: qml/Panel/Indicators/MenuItemFactory.qml:593
192200msgid "Finished"
193−msgstr ""
201+msgstr "Завершено"
194202
195203#: qml/Panel/Indicators/MenuItemFactory.qml:595
196204msgid "Failed, tap to retry"
197−msgstr ""
205+msgstr "Сбой, коснитесь для повтора"
198206
199207#: qml/Panel/SearchIndicator.qml:27
200208msgid "Search"
po/shn.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-10-07 11:46+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Shan <shn@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/si.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-06-26 22:36+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Sinhalese <si@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/sl.po+28−20
@@ -7,24 +7,24 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-06-23 09:29+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-08-06 06:11+0000\n"
1212"Last-Translator: Damir Jerovšek <Unknown>\n"
1313"Language-Team: Slovenian <sl@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-08-08 07:07+0000\n"
18+"X-Generator: Launchpad (build 17156)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
2222msgid "Pin shortcut"
23−msgstr ""
23+msgstr "Pripni bližnjico"
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:73
2626msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "Odpni bližnjico"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
@@ -84,10 +84,6 @@ msgstr "Klic v sili"
8484msgid "OK"
8585msgstr "V REDU"
8686
87−#: qml/Components/PageHeader.qml:366
88−msgid "Recent searches"
89−msgstr "Nedavna iskanja"
90−
9187#: qml/Components/PassphraseLockscreen.qml:60
9288#, qt-format
9389msgid "Hello %1"
@@ -109,7 +105,7 @@ msgstr "KONČANO"
109105msgid "See more"
110106msgstr "Pokaži več"
111107
112−#: qml/Components/SeeMore.qml:58
108+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
113109msgid "See less"
114110msgstr "Pokaži manj"
115111
@@ -117,6 +113,10 @@ msgstr "Pokaži manj"
117113msgid "Recent"
118114msgstr "Nedavno"
119115
116+#: qml/Dash/GenericScopeView.qml:330
117+msgid "See all"
118+msgstr "Ogled vsega"
119+
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
122122msgstr "Več ..."
@@ -125,15 +125,15 @@ msgstr "Več ..."
125125msgid "Less..."
126126msgstr "Manj ..."
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:82
128+#: qml/Dash/Previews/PreviewRatingInput.qml:81
129129msgid "Rate this"
130130msgstr "Ocenite"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:128
132+#: qml/Dash/Previews/PreviewRatingInput.qml:126
133133msgid "Add a review"
134134msgstr "Dodaj oceno"
135135
136−#: qml/Dash/Previews/PreviewRatingInput.qml:168
136+#: qml/Dash/Previews/PreviewRatingInput.qml:166
137137msgid "Send"
138138msgstr "Pošlji"
139139
@@ -169,29 +169,37 @@ msgstr "Pokaži geslo"
169169msgid "Please enter SIM PIN"
170170msgstr "Vnesite PIN kartice SIM"
171171
172+#: qml/Panel/ActiveCallHint.qml:77
173+msgid "Tap to return to call..."
174+msgstr "Tapnite za vrnitev v klic ..."
175+
176+#: qml/Panel/ActiveCallHint.qml:90
177+msgid "Conference"
178+msgstr "Konferenca"
179+
172180#: qml/Panel/Indicators/MenuItemFactory.qml:583
173181msgid "In queue…"
174−msgstr ""
182+msgstr "V vrsti ..."
175183
176184#: qml/Panel/Indicators/MenuItemFactory.qml:587
177185msgid "Downloading"
178−msgstr ""
186+msgstr "Prejemanje"
179187
180188#: qml/Panel/Indicators/MenuItemFactory.qml:589
181189msgid "Paused, tap to resume"
182−msgstr ""
190+msgstr "Premor, tapnite za nadaljevanje"
183191
184192#: qml/Panel/Indicators/MenuItemFactory.qml:591
185193msgid "Canceled"
186−msgstr ""
194+msgstr "Preklicano"
187195
188196#: qml/Panel/Indicators/MenuItemFactory.qml:593
189197msgid "Finished"
190−msgstr ""
198+msgstr "Končano"
191199
192200#: qml/Panel/Indicators/MenuItemFactory.qml:595
193201msgid "Failed, tap to retry"
194−msgstr ""
202+msgstr "Spodletelo, tapnite za ponovni poskus"
195203
196204#: qml/Panel/SearchIndicator.qml:27
197205msgid "Search"
po/sq.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-15 13:51+0000\n"
1212"Last-Translator: Besmir Zanaj <besmirzanaj@gmail.com>\n"
1313"Language-Team: Albanian <sq@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -81,10 +81,6 @@ msgstr ""
8181msgid "OK"
8282msgstr ""
8383
84−#: qml/Components/PageHeader.qml:366
85−msgid "Recent searches"
86−msgstr ""
87−
8884#: qml/Components/PassphraseLockscreen.qml:60
8985#, qt-format
9086msgid "Hello %1"
@@ -106,7 +102,7 @@ msgstr ""
106102msgid "See more"
107103msgstr ""
108104
109−#: qml/Components/SeeMore.qml:58
105+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
110106msgid "See less"
111107msgstr ""
112108
@@ -114,6 +110,10 @@ msgstr ""
114110msgid "Recent"
115111msgstr ""
116112
113+#: qml/Dash/GenericScopeView.qml:330
114+msgid "See all"
115+msgstr ""
116+
117117#: qml/Dash/Previews/PreviewActionCombo.qml:34
118118msgid "More..."
119119msgstr ""
@@ -122,15 +122,15 @@ msgstr ""
122122msgid "Less..."
123123msgstr ""
124124
125−#: qml/Dash/Previews/PreviewRatingInput.qml:82
125+#: qml/Dash/Previews/PreviewRatingInput.qml:81
126126msgid "Rate this"
127127msgstr "Vlerësoje këtë"
128128
129−#: qml/Dash/Previews/PreviewRatingInput.qml:128
129+#: qml/Dash/Previews/PreviewRatingInput.qml:126
130130msgid "Add a review"
131131msgstr "Shto një rishikim"
132132
133−#: qml/Dash/Previews/PreviewRatingInput.qml:168
133+#: qml/Dash/Previews/PreviewRatingInput.qml:166
134134msgid "Send"
135135msgstr ""
136136
@@ -166,6 +166,14 @@ msgstr ""
166166msgid "Please enter SIM PIN"
167167msgstr ""
168168
169+#: qml/Panel/ActiveCallHint.qml:77
170+msgid "Tap to return to call..."
171+msgstr ""
172+
173+#: qml/Panel/ActiveCallHint.qml:90
174+msgid "Conference"
175+msgstr ""
176+
169177#: qml/Panel/Indicators/MenuItemFactory.qml:583
170178msgid "In queue…"
171179msgstr ""
po/sr.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-06-27 09:19+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Serbian <sr@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "Скорашње претраге"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/sv.po+39−30
@@ -1,21 +1,22 @@
11# Swedish translation for unity
2−# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
2+# Copyright © 2013-2014 Rosetta Contributors and Canonical Ltd 2013-2014
33# This file is distributed under the same license as the unity package.
4−# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
4+# Josef Andersson <josef.andersson@fripost.org>, 2014.
55#
66msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-20 19:14+0000\n"
12−"Last-Translator: Gunnar Hjalmarsson <Unknown>\n"
13−"Language-Team: Swedish <sv@li.org>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-31 08:10+0000\n"
12+"Last-Translator: Peter Hultqvist <phq@silentorbit.com>\n"
13+"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-21 07:05+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-08-01 07:14+0000\n"
18+"X-Generator: Launchpad (build 17141)\n"
19+"Language: sv\n"
1920
2021#: plugins/Unity/Launcher/launcheritem.cpp:43
2122#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -28,7 +29,7 @@ msgstr "Släpp genväg"
2829
2930#: qml/Components/EdgeDemoOverlay.qml:151
3031msgid "Skip intro"
31−msgstr "Skippa intro"
32+msgstr "Hoppa över introduktion"
3233
3334#: qml/Components/EdgeDemo.qml:113
3435msgid "Right edge"
@@ -36,7 +37,7 @@ msgstr "Högerkant"
3637
3738#: qml/Components/EdgeDemo.qml:114
3839msgid "Try swiping from the right edge to unlock the phone"
39−msgstr "Dra med fingret från höger för att låsa upp telefonen"
40+msgstr "Svep från höger för att låsa upp telefonen"
4041
4142#: qml/Components/EdgeDemo.qml:145
4243msgid "Top edge"
@@ -71,8 +72,8 @@ msgid ""
7172"You have now mastered the edge gestures and can start using the "
7273"phone<br><br>Tap on the screen to start"
7374msgstr ""
74−"Du har nu bemästrat kantgesterna och kan börja använda telefonen<br><br>Peka "
75−"på skärmen för att starta"
75+"Du har nu bemästrat kantgesterna och kan börja använda "
76+"telefonen<br><br>Tryck på skärmen för att starta"
7677
7778#: qml/Components/Lockscreen.qml:214
7879msgid "Emergency Call"
@@ -82,10 +83,6 @@ msgstr "Nödsamtal"
8283msgid "OK"
8384msgstr "Ok"
8485
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "Senaste sökningar"
88−
8986#: qml/Components/PassphraseLockscreen.qml:60
9087#, qt-format
9188msgid "Hello %1"
@@ -105,33 +102,37 @@ msgstr "KLAR"
105102
106103#: qml/Components/SeeMore.qml:35
107104msgid "See more"
108−msgstr "Se mer"
105+msgstr "Visa mer"
109106
110−#: qml/Components/SeeMore.qml:58
107+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111108msgid "See less"
112−msgstr "Se mindre"
109+msgstr "Visa mindre"
113110
114111#: qml/Dash/DashApps.qml:37
115112msgid "Recent"
116113msgstr "Senaste"
117114
115+#: qml/Dash/GenericScopeView.qml:330
116+msgid "See all"
117+msgstr "Visa alla"
118+
118119#: qml/Dash/Previews/PreviewActionCombo.qml:34
119120msgid "More..."
120−msgstr "Mer..."
121+msgstr "Mer…"
121122
122123#: qml/Dash/Previews/PreviewActionCombo.qml:34
123124msgid "Less..."
124−msgstr "Mindre..."
125+msgstr "Mindre…"
125126
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
127+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127128msgid "Rate this"
128129msgstr "Betygsätt detta"
129130
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
131+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131132msgid "Add a review"
132133msgstr "Lägg till en recension"
133134
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
135+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135136msgid "Send"
136137msgstr "Skicka"
137138
@@ -149,15 +150,15 @@ msgstr "Skriv eller tala in ett kommando"
149150
150151#: qml/Hud/Hud.qml:84
151152msgid "Loading. Please Wait..."
152−msgstr "Laddar. Var god vänta..."
153+msgstr "Läser in. Var god vänta…"
153154
154155#: qml/Hud/Hud.qml:89
155156msgid "Speak Now..."
156−msgstr "Tala nu..."
157+msgstr "Tala nu…"
157158
158159#: qml/Hud/Hud.qml:94
159160msgid "Speaking..."
160−msgstr "Talar..."
161+msgstr "Talar…"
161162
162163#: qml/Notifications/NotificationMenuItemFactory.qml:91
163164msgid "Show password"
@@ -167,9 +168,17 @@ msgstr "Visa lösenord"
167168msgid "Please enter SIM PIN"
168169msgstr "Ange SIM PIN-kod"
169170
171+#: qml/Panel/ActiveCallHint.qml:77
172+msgid "Tap to return to call..."
173+msgstr "Tryck för att återgå till samtal..."
174+
175+#: qml/Panel/ActiveCallHint.qml:90
176+msgid "Conference"
177+msgstr "Konferens"
178+
170179#: qml/Panel/Indicators/MenuItemFactory.qml:583
171180msgid "In queue…"
172−msgstr "I kö..."
181+msgstr "I kö…"
173182
174183#: qml/Panel/Indicators/MenuItemFactory.qml:587
175184msgid "Downloading"
@@ -177,7 +186,7 @@ msgstr "Hämtar"
177186
178187#: qml/Panel/Indicators/MenuItemFactory.qml:589
179188msgid "Paused, tap to resume"
180−msgstr "Pausad, peka för att fortsätta"
189+msgstr "Pausad, tryck för att fortsätta"
181190
182191#: qml/Panel/Indicators/MenuItemFactory.qml:591
183192msgid "Canceled"
@@ -189,7 +198,7 @@ msgstr "Klart"
189198
190199#: qml/Panel/Indicators/MenuItemFactory.qml:595
191200msgid "Failed, tap to retry"
192−msgstr "Misslyckades, peka för att försöka igen"
201+msgstr "Misslyckades, tryck för att försöka igen"
193202
194203#: qml/Panel/SearchIndicator.qml:27
195204msgid "Search"
po/sw.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-14 19:28+0000\n"
1212"Last-Translator: Damas <Unknown>\n"
1313"Language-Team: Swahili <sw@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "Tuma"
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/ta.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-10-24 11:36+0000\n"
1212"Last-Translator: Arun Kumar - அருண் குமார் <thangam.arunx@gmail.com>\n"
1313"Language-Team: Ubuntu Tamil Team/Free Tamil Computing/Thamizha\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919"Language: ta\n"
2020
2121#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -83,10 +83,6 @@ msgstr "அவசர அழைப்பு"
8383msgid "OK"
8484msgstr ""
8585
86−#: qml/Components/PageHeader.qml:366
87−msgid "Recent searches"
88−msgstr "கடையாக தேடப்பட்டவைகள்"
89−
9086#: qml/Components/PassphraseLockscreen.qml:60
9187#, qt-format
9288msgid "Hello %1"
@@ -108,7 +104,7 @@ msgstr ""
108104msgid "See more"
109105msgstr ""
110106
111−#: qml/Components/SeeMore.qml:58
107+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
112108msgid "See less"
113109msgstr ""
114110
@@ -116,6 +112,10 @@ msgstr ""
116112msgid "Recent"
117113msgstr ""
118114
115+#: qml/Dash/GenericScopeView.qml:330
116+msgid "See all"
117+msgstr ""
118+
119119#: qml/Dash/Previews/PreviewActionCombo.qml:34
120120msgid "More..."
121121msgstr ""
@@ -124,15 +124,15 @@ msgstr ""
124124msgid "Less..."
125125msgstr ""
126126
127−#: qml/Dash/Previews/PreviewRatingInput.qml:82
127+#: qml/Dash/Previews/PreviewRatingInput.qml:81
128128msgid "Rate this"
129129msgstr "இதை மதிப்பிடு"
130130
131−#: qml/Dash/Previews/PreviewRatingInput.qml:128
131+#: qml/Dash/Previews/PreviewRatingInput.qml:126
132132msgid "Add a review"
133133msgstr "ஒரு பரிசீலனையை சேர்"
134134
135−#: qml/Dash/Previews/PreviewRatingInput.qml:168
135+#: qml/Dash/Previews/PreviewRatingInput.qml:166
136136msgid "Send"
137137msgstr "அனுப்பு"
138138
@@ -168,6 +168,14 @@ msgstr ""
168168msgid "Please enter SIM PIN"
169169msgstr ""
170170
171+#: qml/Panel/ActiveCallHint.qml:77
172+msgid "Tap to return to call..."
173+msgstr ""
174+
175+#: qml/Panel/ActiveCallHint.qml:90
176+msgid "Conference"
177+msgstr ""
178+
171179#: qml/Panel/Indicators/MenuItemFactory.qml:583
172180msgid "In queue…"
173181msgstr ""
po/te.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-07-19 10:04+0000\n"
1212"Last-Translator: Praveen Illa <mail2ipn@gmail.com>\n"
1313"Language-Team: Telugu <te@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-20 06:18+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr "అత్యవసర పిలుపు"
8080msgid "OK"
8181msgstr "సరే"
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "ఇటీవలి వెతుకులాటలు"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr "పూర్తయ్యింది"
105101msgid "See more"
106102msgstr "మరింత చూడండి"
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr "ఇటీవలివి"
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr "మరిన్ని..."
@@ -121,15 +121,15 @@ msgstr "మరిన్ని..."
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr "ఒక సమీక్షను వ్రాయండి"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "పంపు"
135135
@@ -165,6 +165,14 @@ msgstr "సంకేతపదాన్ని చూపించు"
165165msgid "Please enter SIM PIN"
166166msgstr "దయచేసి సిమ్ పిన్ ఇవ్వండి"
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/tr.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-07-16 17:58+0000\n"
1212"Last-Translator: Volkan Gezer <Unknown>\n"
1313"Language-Team: Turkish <tr@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-17 06:38+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -83,10 +83,6 @@ msgstr "Acil Arama"
8383msgid "OK"
8484msgstr "Tamam"
8585
86−#: qml/Components/PageHeader.qml:366
87−msgid "Recent searches"
88−msgstr "Son aramalar"
89−
9086#: qml/Components/PassphraseLockscreen.qml:60
9187#, qt-format
9288msgid "Hello %1"
@@ -108,7 +104,7 @@ msgstr "BİTTİ"
108104msgid "See more"
109105msgstr "Daha fazlası"
110106
111−#: qml/Components/SeeMore.qml:58
107+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
112108msgid "See less"
113109msgstr "Daha azını gör"
114110
@@ -116,6 +112,10 @@ msgstr "Daha azını gör"
116112msgid "Recent"
117113msgstr "En son"
118114
115+#: qml/Dash/GenericScopeView.qml:330
116+msgid "See all"
117+msgstr ""
118+
119119#: qml/Dash/Previews/PreviewActionCombo.qml:34
120120msgid "More..."
121121msgstr "Daha fazlası..."
@@ -124,15 +124,15 @@ msgstr "Daha fazlası..."
124124msgid "Less..."
125125msgstr "Daha az.."
126126
127−#: qml/Dash/Previews/PreviewRatingInput.qml:82
127+#: qml/Dash/Previews/PreviewRatingInput.qml:81
128128msgid "Rate this"
129129msgstr "Oyla"
130130
131−#: qml/Dash/Previews/PreviewRatingInput.qml:128
131+#: qml/Dash/Previews/PreviewRatingInput.qml:126
132132msgid "Add a review"
133133msgstr "Bir inceleme ekle"
134134
135−#: qml/Dash/Previews/PreviewRatingInput.qml:168
135+#: qml/Dash/Previews/PreviewRatingInput.qml:166
136136msgid "Send"
137137msgstr "Gönder"
138138
@@ -168,6 +168,14 @@ msgstr "Parolayı göster"
168168msgid "Please enter SIM PIN"
169169msgstr "Lütfen SIM PIN'inizi girin"
170170
171+#: qml/Panel/ActiveCallHint.qml:77
172+msgid "Tap to return to call..."
173+msgstr ""
174+
175+#: qml/Panel/ActiveCallHint.qml:90
176+msgid "Conference"
177+msgstr ""
178+
171179#: qml/Panel/Indicators/MenuItemFactory.qml:583
172180msgid "In queue…"
173181msgstr "Beklemede..."
po/ug.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-21 02:30+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-29 04:06+0000\n"
1212"Last-Translator: Gheyret T.Kenji <Unknown>\n"
1313"Language-Team: Uyghur Computer Science Association <UKIJ@yahoogroups.com>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-22 07:17+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-31 07:15+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -82,10 +82,6 @@ msgstr "جىددىي تېلېفون"
8282msgid "OK"
8383msgstr "تامام"
8484
85−#: qml/Components/PageHeader.qml:366
86−msgid "Recent searches"
87−msgstr "يېقىنقى ئىزدەشلەر"
88−
8985#: qml/Components/PassphraseLockscreen.qml:60
9086#, qt-format
9187msgid "Hello %1"
@@ -107,7 +103,7 @@ msgstr "تامام"
107103msgid "See more"
108104msgstr "جىقراق كۆرۈش"
109105
110−#: qml/Components/SeeMore.qml:58
106+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
111107msgid "See less"
112108msgstr "ئازراق كۆرۈش"
113109
@@ -115,6 +111,10 @@ msgstr "ئازراق كۆرۈش"
115111msgid "Recent"
116112msgstr "يېقىنقى"
117113
114+#: qml/Dash/GenericScopeView.qml:330
115+msgid "See all"
116+msgstr "ھەممىنى كۆرۈش…"
117+
118118#: qml/Dash/Previews/PreviewActionCombo.qml:34
119119msgid "More..."
120120msgstr "تېخىمۇ كۆپ…"
@@ -123,15 +123,15 @@ msgstr "تېخىمۇ كۆپ…"
123123msgid "Less..."
124124msgstr "ئازراق..."
125125
126−#: qml/Dash/Previews/PreviewRatingInput.qml:82
126+#: qml/Dash/Previews/PreviewRatingInput.qml:81
127127msgid "Rate this"
128128msgstr "بۇنى باھالاڭ"
129129
130−#: qml/Dash/Previews/PreviewRatingInput.qml:128
130+#: qml/Dash/Previews/PreviewRatingInput.qml:126
131131msgid "Add a review"
132132msgstr "باھا قوشۇش"
133133
134−#: qml/Dash/Previews/PreviewRatingInput.qml:168
134+#: qml/Dash/Previews/PreviewRatingInput.qml:166
135135msgid "Send"
136136msgstr "ئەۋەت"
137137
@@ -167,6 +167,14 @@ msgstr "ئىم كۆرسەت"
167167msgid "Please enter SIM PIN"
168168msgstr "سىم(SIM) كارتىڭىزنىڭ PIN نومۇرىنى كىرگۈزۈڭ"
169169
170+#: qml/Panel/ActiveCallHint.qml:77
171+msgid "Tap to return to call..."
172+msgstr "سۆزلىشىشكە قايتىش ئۈچۈن چېكىڭ…"
173+
174+#: qml/Panel/ActiveCallHint.qml:90
175+msgid "Conference"
176+msgstr "يىغىن"
177+
170178#: qml/Panel/Indicators/MenuItemFactory.qml:583
171179msgid "In queue…"
172180msgstr "قاتاردا…"
po/uk.po+20−12
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-13 17:03+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-29 07:53+0000\n"
1212"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
1313"Language-Team: Ukrainian <uk@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-14 07:10+0000\n"
18−"X-Generator: Launchpad (build 17111)\n"
17+"X-Launchpad-Export-Date: 2014-07-31 07:15+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -85,10 +85,6 @@ msgstr "Терміновий виклик"
8585msgid "OK"
8686msgstr "Гаразд"
8787
88−#: qml/Components/PageHeader.qml:366
89−msgid "Recent searches"
90−msgstr "Нещодавні пошуки"
91−
9288#: qml/Components/PassphraseLockscreen.qml:60
9389#, qt-format
9490msgid "Hello %1"
@@ -110,7 +106,7 @@ msgstr "Виконано"
110106msgid "See more"
111107msgstr "Докладніше"
112108
113−#: qml/Components/SeeMore.qml:58
109+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
114110msgid "See less"
115111msgstr "Стисліше"
116112
@@ -118,6 +114,10 @@ msgstr "Стисліше"
118114msgid "Recent"
119115msgstr "Нещодавні"
120116
117+#: qml/Dash/GenericScopeView.qml:330
118+msgid "See all"
119+msgstr "Детальніше"
120+
121121#: qml/Dash/Previews/PreviewActionCombo.qml:34
122122msgid "More..."
123123msgstr "Більше…"
@@ -126,15 +126,15 @@ msgstr "Більше…"
126126msgid "Less..."
127127msgstr "Менше..."
128128
129−#: qml/Dash/Previews/PreviewRatingInput.qml:82
129+#: qml/Dash/Previews/PreviewRatingInput.qml:81
130130msgid "Rate this"
131131msgstr "Оцінити"
132132
133−#: qml/Dash/Previews/PreviewRatingInput.qml:128
133+#: qml/Dash/Previews/PreviewRatingInput.qml:126
134134msgid "Add a review"
135135msgstr "Додати рецензію"
136136
137−#: qml/Dash/Previews/PreviewRatingInput.qml:168
137+#: qml/Dash/Previews/PreviewRatingInput.qml:166
138138msgid "Send"
139139msgstr "Надіслати"
140140
@@ -170,6 +170,14 @@ msgstr "Показати пароль"
170170msgid "Please enter SIM PIN"
171171msgstr "Введіть PIN-код SIM-картки"
172172
173+#: qml/Panel/ActiveCallHint.qml:77
174+msgid "Tap to return to call..."
175+msgstr "Торкніться, щоб повернутися до дзвінка…"
176+
177+#: qml/Panel/ActiveCallHint.qml:90
178+msgid "Conference"
179+msgstr "Конференція"
180+
173181#: qml/Panel/Indicators/MenuItemFactory.qml:583
174182msgid "In queue…"
175183msgstr "У черзі…"
po/unity8.pot+17−9
@@ -8,7 +8,7 @@ msgid ""
88msgstr ""
99"Project-Id-Version: unity8\n"
1010"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1212"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/vi.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-15 01:19+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Vietnamese <vi@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/xh.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2013-09-28 13:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Xhosa <xh@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr ""
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr ""
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr ""
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr ""
135135
@@ -165,6 +165,14 @@ msgstr ""
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/zh_CN.po+29−21
@@ -7,24 +7,24 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-06-12 08:55+0000\n"
12−"Last-Translator: Shengjing Zhu <Unknown>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-29 02:48+0000\n"
12+"Last-Translator: Luo Lei <luolei@ubuntukylin.com>\n"
1313"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-31 07:15+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
2222msgid "Pin shortcut"
23−msgstr ""
23+msgstr "固定快捷方式"
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:73
2626msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "取消固定快捷方式"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
@@ -80,10 +80,6 @@ msgstr "紧急电话"
8080msgid "OK"
8181msgstr "确定"
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "近期搜索"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr "完成"
105101msgid "See more"
106102msgstr "了解更多"
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr "显示更少"
111107
@@ -113,6 +109,10 @@ msgstr "显示更少"
113109msgid "Recent"
114110msgstr "最近使用过的"
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr "查看全部"
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr "更多..."
@@ -121,15 +121,15 @@ msgstr "更多..."
121121msgid "Less..."
122122msgstr "更少..."
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr "评分"
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr "添加评论"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "发送"
135135
@@ -165,29 +165,37 @@ msgstr "显示密码"
165165msgid "Please enter SIM PIN"
166166msgstr "请输入 SIM PIN"
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr "点击回到通话..."
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr "会议"
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170−msgstr ""
178+msgstr "排队中..."
171179
172180#: qml/Panel/Indicators/MenuItemFactory.qml:587
173181msgid "Downloading"
174−msgstr ""
182+msgstr "正在下载"
175183
176184#: qml/Panel/Indicators/MenuItemFactory.qml:589
177185msgid "Paused, tap to resume"
178−msgstr ""
186+msgstr "已暂停,点击继续"
179187
180188#: qml/Panel/Indicators/MenuItemFactory.qml:591
181189msgid "Canceled"
182−msgstr ""
190+msgstr "已取消"
183191
184192#: qml/Panel/Indicators/MenuItemFactory.qml:593
185193msgid "Finished"
186−msgstr ""
194+msgstr "已完成"
187195
188196#: qml/Panel/Indicators/MenuItemFactory.qml:595
189197msgid "Failed, tap to retry"
190−msgstr ""
198+msgstr "下载失败,请点击重试"
191199
192200#: qml/Panel/SearchIndicator.qml:27
193201msgid "Search"
po/zh_HK.po+19−11
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
1111"PO-Revision-Date: 2014-01-25 13:32+0000\n"
1212"Last-Translator: Daniel Cheung <daniel.2345@hotmail.com>\n"
1313"Language-Team: Chinese (Hong Kong) <zh_HK@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
17+"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr "緊急電話"
8080msgid "OK"
8181msgstr ""
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "最近的搜尋"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105101msgid "See more"
106102msgstr ""
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr ""
111107
@@ -113,6 +109,10 @@ msgstr ""
113109msgid "Recent"
114110msgstr ""
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121121msgid "Less..."
122122msgstr ""
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr "評價"
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr "新增評論"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "傳送"
135135
@@ -165,6 +165,14 @@ msgstr "顯示密碼"
165165msgid "Please enter SIM PIN"
166166msgstr ""
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr ""
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr ""
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr ""
po/zh_TW.po+21−13
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-18 10:14+0000\n"
12−"Last-Translator: Henry Yang <henry9846@hotmail.com>\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-26 16:21+0000\n"
12+"Last-Translator: Cheng-Chia Tseng <pswo10680@gmail.com>\n"
1313"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-19 06:19+0000\n"
18−"X-Generator: Launchpad (build 17114)\n"
17+"X-Launchpad-Export-Date: 2014-07-27 06:35+0000\n"
18+"X-Generator: Launchpad (build 17131)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -80,10 +80,6 @@ msgstr "緊急通話"
8080msgid "OK"
8181msgstr "確定"
8282
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr "最近搜尋"
86−
8783#: qml/Components/PassphraseLockscreen.qml:60
8884#, qt-format
8985msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr "完成"
105101msgid "See more"
106102msgstr "查看更多"
107103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109105msgid "See less"
110106msgstr "縮減查看"
111107
@@ -113,6 +109,10 @@ msgstr "縮減查看"
113109msgid "Recent"
114110msgstr "最近"
115111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr "查看全部"
115+
116116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117117msgid "More..."
118118msgstr "更多…"
@@ -121,15 +121,15 @@ msgstr "更多…"
121121msgid "Less..."
122122msgstr "縮減…"
123123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126126msgstr "給予評等"
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
130130msgstr "新增評論"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133133msgid "Send"
134134msgstr "發送"
135135
@@ -165,6 +165,14 @@ msgstr "顯示密碼"
165165msgid "Please enter SIM PIN"
166166msgstr "請輸入 SIM 卡 PIN 碼"
167167
168+#: qml/Panel/ActiveCallHint.qml:77
169+msgid "Tap to return to call..."
170+msgstr "輕觸可返回通話…"
171+
172+#: qml/Panel/ActiveCallHint.qml:90
173+msgid "Conference"
174+msgstr "會議"
175+
168176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169177msgid "In queue…"
170178msgstr "佇列中…"
qml/Components/Background.qmlnew file+77
@@ -0,0 +1,77 @@
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+import QtQuick 2.0
18+
19+Loader {
20+ id: root
21+ anchors.fill: parent
22+
23+ property url style
24+ readonly property var parsedStyle: String(style)
25+ .match(/^(color|gradient):\/\/\/(?:(#(?:[0-9a-f]{3,4}){1,2}|[a-z]{3,}))(?:\/(#(?:[0-9a-f]{3,4}){1,2}|[a-z]{3,}))?\/?$/i)
26+
27+ sourceComponent: {
28+ if (style == "") return null;
29+ if (!parsedStyle) return image;
30+ if (parsedStyle[1] === "color") return solid
31+ if (parsedStyle[1] === "gradient") return gradient
32+ }
33+
34+ onLoaded: if (item.hasOwnProperty("parsedStyle")) {
35+ item.parsedStyle = Qt.binding(function() { return root.parsedStyle } );
36+ }
37+
38+ Component {
39+ id: solid
40+
41+ Rectangle {
42+ objectName: "solid"
43+
44+ property var parsedStyle
45+
46+ color: parsedStyle ? parsedStyle[2] : "#ffffff"
47+ }
48+ }
49+
50+ Component {
51+ id: gradient
52+
53+ Rectangle {
54+ objectName: "gradient"
55+
56+ property var parsedStyle
57+
58+ gradient: Gradient {
59+ GradientStop { position: 0; color: parsedStyle ? parsedStyle[2] : "#000000" }
60+ GradientStop { position: 1; color: parsedStyle ? parsedStyle[3] : "#000000" }
61+ }
62+ }
63+ }
64+
65+ Component {
66+ id: image
67+
68+ Image {
69+ objectName: "image"
70+
71+ source: width > 0 && height > 0 && root.style
72+
73+ sourceSize.width: width
74+ sourceSize.height: height
75+ }
76+ }
77+}
qml/Components/Dialogs.qmlnew file+217
@@ -0,0 +1,217 @@
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+import QtQuick 2.0
18+
19+import Unity.Application 0.1
20+import Unity.Session 0.1
21+import Ubuntu.Components 0.1
22+import Ubuntu.Components.Popups 0.1
23+
24+Item {
25+ id: root
26+
27+ function onPowerKeyPressed() {
28+ if (!powerKeyTimer.running) {
29+ powerKeyTimer.start();
30+ }
31+ }
32+
33+ function onPowerKeyReleased() {
34+ powerKeyTimer.stop();
35+ }
36+
37+ signal powerOffClicked();
38+
39+ QtObject {
40+ id: d // private stuff
41+
42+ property bool dialogShown: false
43+
44+ function showPowerDialog() {
45+ if (!d.dialogShown) {
46+ d.dialogShown = true;
47+ PopupUtils.open(powerDialog, root, {"z": root.z});
48+ }
49+ }
50+ }
51+
52+ Timer {
53+ id: powerKeyTimer
54+ interval: 2000
55+ repeat: false
56+ triggeredOnStart: false
57+
58+ onTriggered: {
59+ d.showPowerDialog();
60+ }
61+ }
62+
63+ Component {
64+ id: logoutDialog
65+ Dialog {
66+ id: dialogueLogout
67+ title: "Logout"
68+ text: "Are you sure that you want to logout?"
69+ Button {
70+ text: "Cancel"
71+ onClicked: {
72+ PopupUtils.close(dialogueLogout);
73+ d.dialogShown = false;
74+ }
75+ }
76+ Button {
77+ text: "Yes"
78+ onClicked: {
79+ DBusUnitySessionService.Logout();
80+ PopupUtils.close(dialogueLogout);
81+ d.dialogShown = false;
82+ }
83+ }
84+ }
85+ }
86+
87+ Component {
88+ id: shutdownDialog
89+ Dialog {
90+ id: dialogueShutdown
91+ title: "Shutdown"
92+ text: "Are you sure that you want to shutdown?"
93+ Button {
94+ text: "Cancel"
95+ onClicked: {
96+ PopupUtils.close(dialogueShutdown);
97+ d.dialogShown = false;
98+ }
99+ }
100+ Button {
101+ text: "Yes"
102+ onClicked: {
103+ dBusUnitySessionServiceConnection.closeAllApps();
104+ DBusUnitySessionService.Shutdown();
105+ PopupUtils.close(dialogueShutdown);
106+ d.dialogShown = false;
107+ }
108+ }
109+ }
110+ }
111+
112+ Component {
113+ id: rebootDialog
114+ Dialog {
115+ id: dialogueReboot
116+ title: "Reboot"
117+ text: "Are you sure that you want to reboot?"
118+ Button {
119+ text: "Cancel"
120+ onClicked: {
121+ PopupUtils.close(dialogueReboot)
122+ d.dialogShown = false;
123+ }
124+ }
125+ Button {
126+ text: "Yes"
127+ onClicked: {
128+ dBusUnitySessionServiceConnection.closeAllApps();
129+ DBusUnitySessionService.Reboot();
130+ PopupUtils.close(dialogueReboot);
131+ d.dialogShown = false;
132+ }
133+ }
134+ }
135+ }
136+
137+ Component {
138+ id: powerDialog
139+ Dialog {
140+ id: dialoguePower
141+ title: "Power"
142+ text: i18n.tr("Are you sure you would like to turn power off?")
143+ Button {
144+ text: i18n.tr("Power off")
145+ onClicked: {
146+ dBusUnitySessionServiceConnection.closeAllApps();
147+ PopupUtils.close(dialoguePower);
148+ d.dialogShown = false;
149+ root.powerOffClicked();
150+ }
151+ }
152+ Button {
153+ text: i18n.tr("Restart")
154+ onClicked: {
155+ dBusUnitySessionServiceConnection.closeAllApps();
156+ DBusUnitySessionService.Reboot();
157+ PopupUtils.close(dialoguePower);
158+ d.dialogShown = false;
159+ }
160+ }
161+ Button {
162+ text: i18n.tr("Cancel")
163+ onClicked: {
164+ PopupUtils.close(dialoguePower);
165+ d.dialogShown = false;
166+ }
167+ }
168+ }
169+ }
170+
171+
172+ Connections {
173+ id: dBusUnitySessionServiceConnection
174+ objectName: "dBusUnitySessionServiceConnection"
175+ target: DBusUnitySessionService
176+
177+ function closeAllApps() {
178+ while (true) {
179+ var app = ApplicationManager.get(0);
180+ if (app === null) {
181+ break;
182+ }
183+ ApplicationManager.stopApplication(app.appId);
184+ }
185+ }
186+
187+ onLogoutRequested: {
188+ // Display a dialog to ask the user to confirm.
189+ if (!d.dialogShown) {
190+ d.dialogShown = true;
191+ PopupUtils.open(logoutDialog, root, {"z": root.z});
192+ }
193+ }
194+
195+ onShutdownRequested: {
196+ // Display a dialog to ask the user to confirm.
197+ if (!d.dialogShown) {
198+ d.dialogShown = true;
199+ PopupUtils.open(shutdownDialog, root, {"z": root.z});
200+ }
201+ }
202+
203+ onRebootRequested: {
204+ // Display a dialog to ask the user to confirm.
205+ if (!d.dialogShown) {
206+ d.dialogShown = true;
207+ PopupUtils.open(rebootDialog, root, {"z": root.z});
208+ }
209+ }
210+
211+ onLogoutReady: {
212+ closeAllApps();
213+ Qt.quit();
214+ }
215+ }
216+
217+}
qml/Components/DraggingArea.qml+4
@@ -117,4 +117,8 @@ MouseArea {
117117 dragging = false
118118 __pressedPosition = Qt.point(mouse.x, mouse.y)
119119 }
120+
121+ onCanceled: {
122+ dragging = false
123+ }
120124}
qml/Components/EdgeDemo.qml+15−16
@@ -22,16 +22,15 @@ Item {
2222 id: demo
2323
2424 property Item greeter
25− property Item dash
2625 property Item launcher
2726 property Item indicators
28− property Item underlay
27+ property Item stages
2928
3029 property bool launcherEnabled: true
31− property bool dashEnabled: true
30+ property bool stagesEnabled: true
3231 property bool panelEnabled: true
3332 property bool panelContentEnabled: true
34− property bool running: !launcherEnabled || !dashEnabled || !panelEnabled || !panelContentEnabled
33+ property bool running: !launcherEnabled || !stagesEnabled || !panelEnabled || !panelContentEnabled
3534
3635 property bool paused: false
3736
@@ -59,7 +58,7 @@ Item {
5958
6059 function stopDemo() {
6160 launcherEnabled = true
62− dashEnabled = true
61+ stagesEnabled = true
6362 panelEnabled = true
6463 panelContentEnabled = true
6564 if (d.rightEdgeDemo) d.rightEdgeDemo.destroy()
@@ -75,11 +74,11 @@ Item {
7574 }
7675
7776 launcherEnabled = false;
78− dashEnabled = false;
77+ stagesEnabled = false;
7978 panelEnabled = false;
8079 panelContentEnabled = false;
8180
82− // Begin with either greeter or dash, depending on which is visible
81+ // Begin with either greeter or top, depending on which is visible
8382 if (greeter && greeter.shown) {
8483 startRightEdgeDemo()
8584 } else {
@@ -139,12 +138,12 @@ Item {
139138
140139 function startTopEdgeDemo() {
141140 demo.panelEnabled = true;
142− if (demo.dash && demo.underlay) {
143− d.topEdgeDemo = d.overlay.createObject(demo.underlay, {
141+ if (demo.stages) {
142+ d.topEdgeDemo = d.overlay.createObject(demo.stages, {
144143 "edge": "top",
145144 "title": i18n.tr("Top edge"),
146145 "text": i18n.tr("Try swiping from the top edge to access the indicators"),
147− "anchors.fill": demo.dash,
146+ "anchors.fill": demo.stages,
148147 });
149148 }
150149 if (d.topEdgeDemo) {
@@ -193,12 +192,12 @@ Item {
193192 function startLeftEdgeDemo() {
194193 demo.panelEnabled = false;
195194 demo.launcherEnabled = true;
196− if (demo.dash && demo.underlay) {
197− d.leftEdgeDemo = d.overlay.createObject(demo.underlay, {
195+ if (demo.stages) {
196+ d.leftEdgeDemo = d.overlay.createObject(demo.stages, {
198197 "edge": "left",
199198 "title": i18n.tr("Left edge"),
200199 "text": i18n.tr("Swipe from the left to reveal the launcher for quick access to apps"),
201− "anchors.fill": demo.dash,
200+ "anchors.fill": demo.stages,
202201 });
203202 }
204203 if (d.leftEdgeDemo) {
@@ -221,12 +220,12 @@ Item {
221220
222221 function startFinalEdgeDemo() {
223222 demo.launcherEnabled = false;
224− if (demo.dash && demo.underlay) {
225− d.finalEdgeDemo = d.overlay.createObject(demo.underlay, {
223+ if (demo.stages) {
224+ d.finalEdgeDemo = d.overlay.createObject(demo.stages, {
226225 "edge": "none",
227226 "title": i18n.tr("Well done"),
228227 "text": i18n.tr("You have now mastered the edge gestures and can start using the phone<br><br>Tap on the screen to start"),
229− "anchors.fill": demo.dash,
228+ "anchors.fill": demo.stages,
230229 "showSkip": false,
231230 });
232231 }
qml/Components/FilterGrid.qmldeleted−124
@@ -1,124 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−import Utils 0.1
20−import "../Components"
21−
22−/*
23− A ResponsiveGridView that can optionally have the number of rows being displayed
24− reduced to collapsedRowCount, in which case a button saying "View all (123)"
25− will be shown at the bottom. If clicked, FilterGrid will them expand vertically
26− to display all rows.
27− */
28−Item {
29− id: root
30−
31− /* Whether, when collapsed, a button should be displayed enabling the user to expand
32− the grid to its full size. */
33− readonly property bool expandable: model.count > rowsWhenCollapsed * iconTileGrid.columns
34−
35− property var model: null
36−
37− /* Maximum number of rows to be show when filter=true. */
38− property int collapsedRowCount: 2
39− property int uncollapsedRowCount: Math.ceil(model.count / columns)
40− /* Never show more rows than model would fill up. */
41− readonly property int rowsWhenCollapsed: Math.min(collapsedRowCount, uncollapsedRowCount)
42− readonly property int collapsedHeight: iconTileGrid.contentHeightForRows(rowsWhenCollapsed)
43− readonly property int uncollapsedHeight: iconTileGrid.contentHeightForRows(uncollapsedRowCount)
44−
45− property alias minimumHorizontalSpacing: iconTileGrid.minimumHorizontalSpacing
46− property alias maximumNumberOfColumns: iconTileGrid.maximumNumberOfColumns
47− property alias columns: iconTileGrid.columns
48− property alias delegateWidth: iconTileGrid.delegateWidth
49− property alias delegateHeight: iconTileGrid.delegateHeight
50− property alias verticalSpacing: iconTileGrid.verticalSpacing
51− readonly property alias margins: iconTileGrid.margins
52− property alias delegate: iconTileGrid.delegate
53− property alias cellWidth: iconTileGrid.cellWidth
54− property alias cellHeight: iconTileGrid.cellHeight
55− property alias displayMarginBeginning: iconTileGrid.displayMarginBeginning
56− property alias displayMarginEnd: iconTileGrid.displayMarginEnd
57− readonly property alias originY: iconTileGrid.originY
58− readonly property alias flicking: iconTileGrid.flicking
59− readonly property alias moving: iconTileGrid.moving
60− readonly property alias pressDelay: iconTileGrid.pressDelay
61− property alias highlightIndex: iconTileGrid.highlightIndex
62− readonly property alias currentItem: iconTileGrid.currentItem
63− readonly property alias filtered: d.filter
64−
65− QtObject {
66− id: d
67− // We do have filter and collapsed properties because we need to decouple
68− // the real filtering with the animation since the closing animation
69− // i.e. setFilter(false. true) we still need to not be filtering until
70− // the animation finishes otherwise we hide the items when the animation
71− // is still running
72− property bool filter: true
73− property bool collapsed: true
74− }
75−
76− height: d.collapsed ? root.collapsedHeight : root.uncollapsedHeight
77− clip: filterAnimation.running
78−
79− Behavior on height {
80− id: heightBehaviour
81− enabled: false
82− NumberAnimation {
83− id: filterAnimation
84− // Duration and easing here match the ListViewWithPageHeader::m_contentYAnimation
85− // otherwise since both animations can run at the same time you'll get
86− // some visual weirdness.
87− duration: 200
88− easing.type: Easing.InOutQuad
89− onRunningChanged: {
90− if (!running) {
91− d.filter = d.collapsed;
92− }
93− heightBehaviour.enabled = false;
94− }
95− }
96− }
97−
98− function setFilter(filter, animate) {
99− heightBehaviour.enabled = animate;
100− d.collapsed = filter;
101− if (!animate || !filter) {
102− d.filter = filter;
103− }
104− }
105−
106− ResponsiveGridView {
107− id: iconTileGrid
108−
109− anchors { left: parent.left; right: parent.right }
110− height: totalContentHeight
111− interactive: false
112−
113− minimumHorizontalSpacing: units.gu(0.5)
114− maximumNumberOfColumns: 6
115− delegateWidth: units.gu(11)
116− delegateHeight: units.gu(9.5)
117− verticalSpacing: units.gu(2)
118−
119− model: LimitProxyModel {
120− model: root.model
121− limit: d.filter ? rowsWhenCollapsed * iconTileGrid.columns : -1
122− }
123− }
124−}
qml/Components/InputMethod.qmlnew file+79
@@ -0,0 +1,79 @@
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+import QtQuick 2.0
18+import Unity.Application 0.1
19+import Ubuntu.Components 0.1
20+
21+Item {
22+ id: root
23+
24+ property var surface: null
25+
26+ property int transitionDuration: UbuntuAnimation.FastDuration
27+
28+ state: {
29+ if (surface && surface.state != MirSurfaceItem.Minimized) {
30+ return "shown";
31+ } else {
32+ return "hidden";
33+ }
34+ }
35+
36+ states: [
37+ State {
38+ name: "shown"
39+ PropertyChanges {
40+ target: root
41+ visible: true
42+ y: 0
43+ }
44+ },
45+ State {
46+ name: "hidden"
47+ PropertyChanges {
48+ target: root
49+ visible: false
50+ // half-way down because the vkb occupies only the lower half of the surface
51+ // TODO: consider keyboard rotation
52+ y: root.parent.height / 2.0
53+ }
54+ }
55+ ]
56+
57+ transitions: [
58+ Transition {
59+ from: "*"; to: "*"
60+ PropertyAction { property: "visible"; value: true }
61+ UbuntuNumberAnimation { property: "y"; duration: transitionDuration }
62+ }
63+ ]
64+
65+ onSurfaceChanged: {
66+ if (surface) {
67+ surface.parent = root;
68+ surface.anchors.fill = root;
69+ }
70+ }
71+
72+ Component.onDestruction: {
73+ if (surface) {
74+ surface.parent = null;
75+ surface.release();
76+ surface = null;
77+ }
78+ }
79+}
qml/Components/ListItems/Header.qml+17−26
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013,2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -15,54 +15,45 @@
1515 */
1616
1717import QtQuick 2.0
18+import QtQuick.Layouts 1.1
1819import Ubuntu.Components 0.1
1920
2021Item {
21− /*!
22− \preliminary
23− The text that is shown as the header text.
24− \qmlproperty string text
25− */
2622 property alias text: label.text
27− property alias textColor: label.color
28− property alias image: image.source
23+ property alias color: label.color
24+ property alias iconName: icon.name
2925
3026 signal clicked(variant mouse)
3127
3228 height: units.gu(5)
3329
34− Item {
30+ RowLayout {
31+ spacing: units.gu(.5)
3532 anchors {
3633 left: parent.left
3734 right: parent.right
38− rightMargin: units.gu(0.5)
39− top: parent.top
40− bottom: parent.bottom
35+ verticalCenter: parent.verticalCenter
36+ margins: units.gu(1)
4137 }
4238
4339 Label {
4440 id: label
45− anchors {
46− left: parent.left
47− leftMargin: units.gu(2)
48− verticalCenter: parent.verticalCenter
49− }
41+ Layout.fillWidth: true
5042
51− color: "grey" // TODO karni: Update Ubuntu.Compoonents.Themes.Palette.
5243 font.family: "Ubuntu"
5344 fontSize: "medium"
5445 elide: Text.ElideRight
46+ maximumLineCount: 1
5547 textFormat: Text.PlainText
56− width: parent.width - image.width - image.leftMargin - anchors.leftMargin
48+ width: Math.min(parent.width - units.gu(4), implicitWidth)
5749 }
5850
59− Image {
60− id: image
61− readonly property double leftMargin: units.gu(1)
62− x: label.x + label.contentWidth + leftMargin
63− anchors {
64− verticalCenter: parent.verticalCenter
65− }
51+ Icon {
52+ id: icon
53+ visible: name != ""
54+ height: units.gu(2)
55+ width: height
56+ color: label.color
6657 }
6758 }
6859
qml/Components/PageHeader.qml+56−23
@@ -32,9 +32,10 @@ Item {
3232 property bool searchEntryEnabled: false
3333 property ListModel searchHistory: SearchHistoryModel
3434 property alias searchQuery: searchTextField.text
35− property bool searchInProgress: false
3635
3736 property alias bottomItem: bottomContainer.children
37+ property int paginationCount: 0
38+ property int paginationIndex: -1
3839
3940 // TODO We should use foreground for the icons
4041 // of the toolbar but unfortunately Action does not have
@@ -44,6 +45,12 @@ Item {
4445 signal backClicked()
4546
4647 onScopeStyleChanged: refreshLogo()
48+ onSearchQueryChanged: {
49+ // Make sure we are at the search page if the search query changes behind our feet
50+ if (searchQuery) {
51+ headerContainer.showSearch = true;
52+ }
53+ }
4754
4855 function triggerSearch() {
4956 if (searchEntryEnabled) {
@@ -52,6 +59,12 @@ Item {
5259 }
5360 }
5461
62+ function closePopup() {
63+ if (headerContainer.popover != null) {
64+ PopupUtils.close(headerContainer.popover);
65+ }
66+ }
67+
5568 function resetSearch(keepFocus) {
5669 if (searchHistory) {
5770 searchHistory.addQuery(searchTextField.text);
@@ -60,9 +73,7 @@ Item {
6073 unfocus();
6174 }
6275 searchTextField.text = "";
63− if (headerContainer.popover != null) {
64− PopupUtils.close(headerContainer.popover);
65− }
76+ closePopup();
6677 }
6778
6879 function unfocus() {
@@ -103,9 +114,7 @@ Item {
103114 anchors { fill: parent; margins: units.gu(1); bottomMargin: units.gu(3) + bottomContainer.height }
104115 visible: headerContainer.showSearch
105116 onPressed: {
106− if (headerContainer.popover) {
107− PopupUtils.close(headerContainer.popover);
108− }
117+ closePopup();
109118 if (!searchTextField.text) {
110119 headerContainer.showSearch = false;
111120 }
@@ -117,7 +126,7 @@ Item {
117126 Flickable {
118127 id: headerContainer
119128 objectName: "headerContainer"
120− clip: true
129+ clip: contentY < height
121130 anchors { left: parent.left; top: parent.top; right: parent.right }
122131 height: units.gu(6.5)
123132 contentHeight: headersColumn.height
@@ -127,6 +136,11 @@ Item {
127136 property bool showSearch: false
128137 property var popover: null
129138
139+ Background {
140+ objectName: "headerBackground"
141+ style: scopeStyle.headerBackground
142+ }
143+
130144 Behavior on contentY {
131145 UbuntuNumberAnimation {
132146 id: openSearchAnimation
@@ -150,11 +164,13 @@ Item {
150164 anchors { left: parent.left; right: parent.right }
151165 height: headerContainer.height
152166 contentHeight: height
167+ opacity: headerContainer.clip || headerContainer.showSearch ? 1 : 0 // setting visible false cause column to relayout
153168 separatorSource: ""
154169 // Required to keep PageHeadStyle noise down as it expects the Page's properties around.
155170 property var styledItem: searchHeader
156171 property string title
157172 property var config: PageHeadConfiguration {
173+ foregroundColor: root.scopeStyle ? root.scopeStyle.headerForeground : "grey"
158174 backAction: Action {
159175 iconName: "back"
160176 onTriggered: {
@@ -166,6 +182,7 @@ Item {
166182 property var contents: TextField {
167183 id: searchTextField
168184 objectName: "searchTextField"
185+ inputMethodHints: Qt.ImhNoPredictiveText
169186 hasClearButton: false
170187 anchors {
171188 fill: parent
@@ -185,25 +202,13 @@ Item {
185202 anchors.fill: parent
186203 anchors.margins: units.gu(.75)
187204 source: "image://theme/clear"
188− opacity: searchTextField.text.length > 0 && !searchActivityIndicator.running
205+ opacity: searchTextField.text.length > 0
189206 visible: opacity > 0
190207 Behavior on opacity {
191208 UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
192209 }
193210 }
194211
195− ActivityIndicator {
196− id: searchActivityIndicator
197− objectName: "searchIndicator"
198− anchors.fill: parent
199− anchors.margins: units.gu(.75)
200− running: root.searchInProgress
201− opacity: running ? 1 : 0
202− Behavior on opacity {
203− UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
204− }
205− }
206−
207212 onClicked: {
208213 root.resetSearch(true);
209214 root.openSearchHistory();
@@ -215,6 +220,12 @@ Item {
215220 root.openSearchHistory();
216221 }
217222 }
223+
224+ onTextChanged: {
225+ if (text != "") {
226+ closePopup();
227+ }
228+ }
218229 }
219230 }
220231
@@ -224,11 +235,12 @@ Item {
224235 anchors { left: parent.left; right: parent.right }
225236 height: headerContainer.height
226237 contentHeight: height
238+ opacity: headerContainer.clip || !headerContainer.showSearch ? 1 : 0 // setting visible false cause column to relayout
227239 separatorSource: ""
228− textColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
229240 property var styledItem: header
230241 property string title: root.title
231242 property var config: PageHeadConfiguration {
243+ foregroundColor: root.scopeStyle ? root.scopeStyle.headerForeground : "grey"
232244 backAction: Action {
233245 iconName: "back"
234246 visible: root.showBackButton
@@ -272,6 +284,25 @@ Item {
272284 }
273285 }
274286
287+ Row {
288+ spacing: units.gu(.5)
289+ Repeater {
290+ objectName: "paginationRepeater"
291+ model: root.paginationCount
292+ Image {
293+ objectName: "paginationDots_" + index
294+ height: units.gu(1)
295+ width: height
296+ source: (index == root.paginationIndex) ? "graphics/pagination_dot_on.png" : "graphics/pagination_dot_off.png"
297+ }
298+ }
299+ anchors {
300+ top: headerContainer.bottom
301+ horizontalCenter: headerContainer.horizontalCenter
302+ topMargin: units.gu(.5)
303+ }
304+ }
305+
275306 Component {
276307 id: popoverComponent
277308 Popover {
@@ -291,6 +322,7 @@ Item {
291322
292323 Repeater {
293324 id: recentSearches
325+ objectName: "recentSearches"
294326 model: searchHistory
295327
296328 delegate: Standard {
@@ -299,7 +331,8 @@ Item {
299331 onClicked: {
300332 searchHistory.addQuery(text);
301333 searchTextField.text = text;
302− PopupUtils.close(popover);
334+ closePopup();
335+ unfocus();
303336 }
304337 }
305338 }
qml/Components/PassphraseLockscreen.qml+3
@@ -31,8 +31,10 @@ Item {
3131
3232 function clear(playAnimation) {
3333 pinentryField.text = "";
34+ pinentryField.enabled = true
3435 if (playAnimation) {
3536 wrongPasswordAnimation.start();
37+ pinentryField.forceActiveFocus();
3638 } else {
3739 pinentryField.focus = false
3840 }
@@ -78,6 +80,7 @@ Item {
7880
7981 onAccepted: {
8082 if (pinentryField.text) {
83+ pinentryField.enabled = false;
8184 root.entered(pinentryField.text);
8285 }
8386 }
qml/Components/ResponsiveGridView.qml+2−1
@@ -44,10 +44,11 @@ Item {
4444 property alias displayMarginBeginning: gridView.displayMarginBeginning
4545 property alias displayMarginEnd: gridView.displayMarginEnd
4646 property alias highlightIndex: gridView.highlightIndex
47+ property alias cacheBuffer: gridView.cacheBuffer
4748 readonly property alias currentItem: gridView.currentItem
4849
4950 function contentHeightForRows(rows) {
50− return rows * cellHeight + verticalSpacing
51+ return rows * cellHeight;
5152 }
5253
5354 GridView {
qml/Components/SeeMore.qmldeleted−70
@@ -1,70 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−
20−/*! Widget that can be used in combination with a text area to allow easy 'expand/collapse' functionality. */
21−
22−Item {
23− //! Boolean set to true when it suggests expanded functionality
24− property bool more: false
25−
26− implicitHeight: seeMoreLabel.height + units.gu(2)
27−
28− Row {
29− anchors.centerIn: parent
30− spacing: units.gu(2)
31−
32− Label {
33− id: seeMoreLabel
34− objectName: "seeMoreLabel"
35− text: i18n.tr("See more")
36− opacity: !more ? 0.8 : 0.4
37− // TODO: Fix requiring Palette update
38− color: "grey" //Theme.palette.selected.backgroundText
39− font.weight: Font.Bold
40−
41− MouseArea {
42− anchors.fill: parent
43− onClicked: more = true
44− }
45− }
46−
47− Image {
48− anchors {
49− top: parent.top
50− bottom: parent.bottom
51− }
52− width: units.dp(2)
53− source: "ListItems/graphics/ListItemDividerVertical.png"
54− }
55−
56− Label {
57− objectName: "seeLessLabel"
58− text: i18n.tr("See less")
59− opacity: more ? 0.8 : 0.4
60− // TODO: Fix requiring Palette update
61− color: "grey" //Theme.palette.selected.backgroundText
62− font.weight: Font.Bold
63−
64− MouseArea {
65− anchors.fill: parent
66− onClicked: more = false
67− }
68− }
69− }
70−}
qml/Components/graphics/pagination_dot_off@30.pngnew file

Binary file not shown.

qml/Components/graphics/pagination_dot_on@30.pngnew file

Binary file not shown.

qml/Dash/Apps/CloseIcon.qmldeleted−62
@@ -1,62 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−
19−Item {
20− id: root
21−
22− Image {
23− id: closeIcon
24− anchors.centerIn: parent
25− source: "graphics/close_btn.png"
26−
27− state: (root.enabled) ? "shown" : "hidden"
28−
29− states: [
30− State {
31− name: "shown"
32− PropertyChanges {
33− target: closeIcon
34− height: root.height
35− width: root.width
36− }
37− },
38− State {
39− name: "hidden"
40− PropertyChanges {
41− target: closeIcon
42− height: 0
43− width: 0
44− }
45− }
46−
47− ]
48− transitions: [
49− Transition {
50− to: "shown"
51− NumberAnimation {
52− properties: "width, height"; duration: 300
53− easing { type: Easing.OutBack; overshoot: 5 }
54− }
55− },
56− Transition {
57− to: "hidden"
58− NumberAnimation { properties: "width, height"; duration: 250; }
59− }
60− ]
61− }
62−}
qml/Dash/Apps/RunningApplicationTile.qmldeleted−128
@@ -1,128 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−import Unity.Application 0.1
20−import "../../Components/"
21−import "../../Components/ListItems"
22−
23−AbstractButton {
24− id: root
25− property var application
26−
27− signal requestedApplicationActivation(var application)
28− signal requestedApplicationTermination(var application)
29− signal requestedActivationMode()
30− signal requestedTerminationMode()
31−
32− // Was: childrenRect.height
33− // To avoid "binding loop" warning
34− height: shapedApplicationImage.height + labelContainer.height
35−
36− width: shapedApplicationImage.width <= units.gu(11) ? units.gu(11) : height
37−
38− property bool terminationModeEnabled: false
39−
40− onClicked: {
41− if (!terminationModeEnabled)
42− requestedApplicationActivation(application)
43− }
44−
45− onPressAndHold: {
46− if (terminationModeEnabled) {
47− requestedActivationMode()
48− } else {
49− requestedTerminationMode()
50− }
51− }
52−
53− UbuntuShape {
54− id: shapedApplicationImage
55− anchors { top: parent.top; horizontalCenter: parent.horizontalCenter }
56−
57− height: units.gu(17)
58− width: applicationImage.width
59− radius: "medium"
60−
61− image: Image {
62− id: applicationImage
63− source: application.screenshot
64− // height : width = ss.height : ss.width
65− height: shapedApplicationImage.height
66− fillMode: Image.PreserveAspectCrop
67− width: Math.min(height, height * sourceSize.width / sourceSize.height)
68− }
69−
70− }
71−
72− UbuntuShape {
73− id: borderPressed
74−
75− anchors.fill: shapedApplicationImage
76− radius: "medium"
77− borderSource: "radius_pressed.sci"
78− opacity: root.pressed ? 1.0 : 0.0
79− Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
80− }
81−
82− // FIXME: label code duplicated with Tile
83− Item {
84− id: labelContainer
85− anchors {
86− left: parent.left
87− right: parent.right
88− top: shapedApplicationImage.bottom
89− }
90− height: units.gu(2)
91−
92− Label {
93− id: label
94− anchors {
95− baseline: parent.bottom
96− left: parent.left
97− right: parent.right
98− }
99− text: (application) ? application.name : ""
100−
101− // TODO karni: Update Ubuntu.Components.Themes.Palette and use theme color instead
102− color: "grey"
103− opacity: 0.9
104− fontSize: "small"
105− elide: Text.ElideMiddle
106− horizontalAlignment: Text.AlignHCenter
107− }
108− }
109−
110− CloseIcon {
111− objectName: "closeIcon " + model.name
112− anchors {
113− left: shapedApplicationImage.left
114− leftMargin: -units.gu(1)
115− top: parent.top
116− topMargin: -units.gu(1)
117− }
118− height: units.gu(6)
119− width: units.gu(6)
120− id: closeIcon
121− enabled: root.terminationModeEnabled
122−
123− MouseArea {
124− anchors { fill: parent; margins: -units.gu(1) }
125− onClicked: requestedApplicationTermination(application)
126− }
127− }
128−}
qml/Dash/Apps/RunningApplicationsGrid.qmldeleted−105
@@ -1,105 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import "../../Components"
19−
20−import Ubuntu.Gestures 0.1
21−import Unity.Application 0.1
22−
23−ResponsiveFlowView {
24− id: root
25− clip: true
26−
27− signal updateScreenshots
28− property alias enableHeightBehavior: heightBehaviour.enabled
29− property bool enableHeightBehaviorOnNextCreation: model.count === 0
30−
31− Behavior on height {
32− id: heightBehaviour
33− enabled: false
34− NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
35− }
36−
37− Connections {
38− target: root.model
39− onCountChanged: {
40− heightBehaviour.enabled = true;
41− }
42− }
43−
44− property bool canEnableTerminationMode: true
45−
46− onCanEnableTerminationModeChanged: {
47− if (!canEnableTerminationMode)
48− terminationModeEnabled = false
49− }
50−
51− // when false, it means it's on activation mode
52− property bool terminationModeEnabled: false
53−
54− maximumNumberOfColumns: 10
55− minimumHorizontalSpacing: units.gu(2)
56− referenceDelegateWidth: units.gu(11)
57− verticalSpacing: units.gu(2)
58−
59− delegate: Item {
60− width: runningAppTile.width + root.horizontalSpacing
61− height: runningAppTile.height + root.verticalSpacing
62−
63− RunningApplicationTile {
64− id: runningAppTile
65− objectName: "runningAppTile " + model.name
66− anchors {
67− top: parent.top
68− horizontalCenter: parent.horizontalCenter
69− }
70− application: model
71− onRequestedActivationMode: { root.terminationModeEnabled = false }
72− onRequestedTerminationMode: {
73− if (canEnableTerminationMode)
74− root.terminationModeEnabled = true
75− }
76− onRequestedApplicationTermination: {
77− ApplicationManager.stopApplication(model.appId)
78− }
79− onRequestedApplicationActivation: {
80− ApplicationManager.requestFocusApplication(model.appId)
81− }
82−
83− terminationModeEnabled: root.terminationModeEnabled
84− }
85− }
86−
87− move: Transition {
88− NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutCubic }
89− }
90−
91− MouseArea {
92− anchors.fill: parent
93− z: -1 // behind all RunningApplicationTiles
94− enabled: root.terminationModeEnabled
95− onPressed: { root.terminationModeEnabled = false; }
96− }
97−
98− PressedOutsideNotifier {
99− anchors.fill: parent
100− enabled: root.terminationModeEnabled
101− onPressedOutside: {
102− root.terminationModeEnabled = false;
103− }
104− }
105−}
qml/Dash/Apps/graphics/close_btn@9.pngdeleted

Binary file not shown.

qml/Dash/CardCarousel.qml+2−7
@@ -21,13 +21,8 @@ import "../Components"
2121DashRenderer {
2222 id: cardCarousel
2323
24− property alias cacheBuffer: carousel.cacheBuffer
25− property alias itemComponent: carousel.itemComponent
26− property alias minimumTileWidth: carousel.minimumTileWidth
27− property alias selectedItemScaleFactor: carousel.selectedItemScaleFactor
28− property alias tileAspectRatio: carousel.tileAspectRatio
29−
30− height: carousel.implicitHeight + units.gu(6)
24+ expandedHeight: carousel.implicitHeight + units.gu(6)
25+ collapsedHeight: expandedHeight
3126
3227 Carousel {
3328 id: carousel
qml/Dash/CardFilterGrid.qml → qml/Dash/CardGrid.qmlrenamed+22−22
@@ -18,33 +18,33 @@ import QtQuick 2.0
1818import "../Components"
1919
2020DashRenderer {
21− id: genericFilterGrid
21+ id: root
2222
23− expandable: filterGrid.expandable
24− collapsedHeight: filterGrid.collapsedHeight
25− uncollapsedHeight: filterGrid.uncollapsedHeight
26− originY: filterGrid.originY
27− height: filterGrid.height
28− filtered: filterGrid.filtered
29−
30− function setFilter(filter, animate) {
31− filterGrid.setFilter(filter, animate)
23+ readonly property int collapsedRows: {
24+ if (!cardTool || !cardTool.template || typeof cardTool.template["collapsed-rows"] != "number") return 2;
25+ return cardTool.template["collapsed-rows"];
3226 }
3327
34− FilterGrid {
35− id: filterGrid
36− width: genericFilterGrid.width
28+ expandedHeight: grid.totalContentHeight
29+ collapsedHeight: Math.min(grid.contentHeightForRows(collapsedRows), expandedHeight)
30+ collapsedItemCount: collapsedRows * grid.columns
31+ originY: grid.originY
32+
33+ ResponsiveGridView {
34+ id: grid
35+ anchors.fill: parent
3736 minimumHorizontalSpacing: units.gu(1)
3837 delegateWidth: cardTool.cardWidth
3938 delegateHeight: cardTool.cardHeight
4039 verticalSpacing: units.gu(1)
41− model: genericFilterGrid.model
42− collapsedRowCount: Math.min(2, cardTool && cardTool.template && cardTool.template["collapsed-rows"] || 2)
43− displayMarginBeginning: genericFilterGrid.displayMarginBeginning
44− displayMarginEnd: genericFilterGrid.displayMarginEnd
40+ model: root.model
41+ displayMarginBeginning: root.displayMarginBeginning
42+ displayMarginEnd: root.displayMarginEnd
43+ cacheBuffer: 0
44+ interactive: false
4545 delegate: Item {
46− width: filterGrid.cellWidth
47− height: filterGrid.cellHeight
46+ width: grid.cellWidth
47+ height: grid.cellHeight
4848 Loader {
4949 id: loader
5050 sourceComponent: cardTool.cardComponent
@@ -58,12 +58,12 @@ DashRenderer {
5858 item.template = Qt.binding(function() { return cardTool.template; });
5959 item.components = Qt.binding(function() { return cardTool.components; });
6060 item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
61− item.scopeStyle = genericFilterGrid.scopeStyle;
61+ item.scopeStyle = root.scopeStyle;
6262 }
6363 Connections {
6464 target: loader.item
65− onClicked: genericFilterGrid.clicked(index, result)
66− onPressAndHold: genericFilterGrid.pressAndHold(index)
65+ onClicked: root.clicked(index, result)
66+ onPressAndHold: root.pressAndHold(index)
6767 }
6868 }
6969 }
qml/Dash/CardTool.qml+28−3
@@ -126,7 +126,7 @@ Item {
126126 type:real \brief Height of the card's header.
127127 */
128128 readonly property int headerHeight: cardLoader.item ? cardLoader.item.headerHeight : 0
129− readonly property size artShapeSize: cardLoader.item ? cardLoader.item.artShapeSize : 0
129+ property size artShapeSize: cardLoader.item ? cardLoader.item.artShapeSize : 0
130130
131131 /*!
132132 \brief Desired alignment of header components.
@@ -165,15 +165,40 @@ Item {
165165 }
166166 }
167167
168+ Item {
169+ id: attributesModel
170+ property int numOfAttributes: 0
171+ property var model: []
172+ property bool hasAttributes: {
173+ var attributes = components["attributes"];
174+ var hasAttributesFlag = (attributes != undefined) && attributes["field"];
175+
176+ if (hasAttributesFlag) {
177+ if (attributes["max-count"]) {
178+ numOfAttributes = attributes["max-count"];
179+ }
180+ }
181+ return hasAttributesFlag
182+ }
183+
184+ onNumOfAttributesChanged: {
185+ model = []
186+ for (var i = 0; i < numOfAttributes; i++) {
187+ model.push( {"value":"text"+(i+1), "icon":"image://theme/ok" } );
188+ }
189+ }
190+ }
191+
168192 Loader {
169193 id: cardLoader
170− property var fields: ["art", "mascot", "title", "subtitle", "summary"]
194+ property var fields: ["art", "mascot", "title", "subtitle", "summary", "attributes"]
171195 property var maxData: {
172196 "art": Qt.resolvedUrl("graphics/checkers.png"),
173197 "mascot": Qt.resolvedUrl("graphics/checkers.png"),
174198 "title": "—\n—",
175199 "subtitle": "—",
176− "summary": "—\n—\n—\n—\n—"
200+ "summary": "—\n—\n—\n—\n—",
201+ "attributes": attributesModel.model
177202 }
178203 sourceComponent: cardTool.cardComponent
179204 onLoaded: {
qml/Dash/CardVerticalJournal.qml+3−21
@@ -23,33 +23,15 @@ DashRenderer {
2323
2424 readonly property double collapseLimit: units.gu(35)
2525
26− uncollapsedHeight: cardVerticalJournal.implicitHeight
27− collapsedHeight: Math.min(collapseLimit, cardVerticalJournal.implicitHeight)
28− expandable: uncollapsedHeight > collapseLimit
26+ expandedHeight: Math.max(cardVerticalJournal.implicitHeight, minHeight)
27+ collapsedHeight: Math.max(Math.min(collapseLimit, cardVerticalJournal.implicitHeight), minHeight)
28+ // TODO: implement collapsedItemCount
2929
3030 // This minHeight is used as bootstrapper for the height. Vertical Journal
3131 // is special by the fact that it doesn't know how to calculate its implicit height unless we give it
3232 // enough height that it can start creating its children so we make sure it has enough height for that
3333 // in case the model is non empty
3434 readonly property double minHeight: root.model.count >= 1 ? cardVerticalJournal.rowSpacing + 1 : 0
35− height: filtered ? Math.max(collapsedHeight, minHeight) : uncollapsedHeight
36−
37− Behavior on height {
38− id: heightBehaviour
39− enabled: false
40− animation: UbuntuNumberAnimation {
41− onRunningChanged: {
42− if (!running) {
43− heightBehaviour.enabled = false
44− }
45− }
46− }
47− }
48−
49− function setFilter(filter, animate) {
50− heightBehaviour.enabled = animate;
51− filtered = filter;
52− }
5335
5436 ResponsiveVerticalJournal {
5537 id: cardVerticalJournal
qml/Dash/Dash.qml+92−11
@@ -14,10 +14,11 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−import QtQuick 2.0
17+import QtQuick 2.2
1818import Ubuntu.Components 0.1
1919import Unity 0.2
2020import Utils 0.1
21+import Unity.DashCommunicator 0.1
2122import "../Components"
2223
2324Showable {
@@ -29,8 +30,21 @@ Showable {
2930 property string showScopeOnLoaded: "clickscope"
3031 property real contentScale: 1.0
3132
33+ DashCommunicatorService {
34+ objectName: "dashCommunicatorService"
35+ onSetCurrentScopeRequested: {
36+ dash.setCurrentScope(scopeId, animate, reset)
37+ }
38+ }
39+
3240 function setCurrentScope(scopeId, animate, reset) {
33− var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)
41+ var scopeIndex = -1;
42+ for (var i = 0; i < scopes.count; ++i) {
43+ if (scopes.getScope(i).id == scopeId) {
44+ scopeIndex = i;
45+ break;
46+ }
47+ }
3448
3549 if (scopeIndex == -1) {
3650 console.warn("No match for scope with id: %1".arg(scopeId))
@@ -55,15 +69,16 @@ Showable {
5569 }
5670 }
5771
58− SortFilterProxyModel {
59− id: filteredScopes
60− model: Scopes {
61− id: scopes
62− }
63− dynamicSortFilter: true
72+ Scopes {
73+ id: scopes
74+ }
6475
65− filterRole: Scopes.RoleVisible
66− filterRegExp: RegExp("^true$")
76+ Image {
77+ anchors.fill: parent
78+ source: parent.width > parent.height ? "graphics/paper_landscape.png" : "graphics/paper_portrait.png"
79+ fillMode: Image.PreserveAspectCrop
80+ horizontalAlignment: Image.AlignRight
81+ verticalAlignment: Image.AlignTop
6782 }
6883
6984 DashContent {
@@ -71,7 +86,6 @@ Showable {
7186 objectName: "dashContent"
7287 width: parent.width
7388 height: parent.height
74− model: filteredScopes
7589 scopes: scopes
7690 visible: x != -width
7791 onGotoScope: {
@@ -126,4 +140,71 @@ Showable {
126140 }
127141 }
128142 }
143+
144+ Rectangle {
145+ id: indicator
146+ objectName: "processingIndicator"
147+ anchors {
148+ left: parent.left
149+ right: parent.right
150+ bottom: parent.bottom
151+ }
152+ height: units.dp(3)
153+ color: scopeStyle.backgroundLuminance > 0.7 ? "#50000000" : "#50ffffff"
154+ opacity: 0
155+ visible: opacity > 0
156+
157+ readonly property bool processing: dashContent.processing || scopeItem.processing
158+
159+ Behavior on opacity {
160+ UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
161+ }
162+
163+ onProcessingChanged: {
164+ if (processing) delay.start();
165+ else if (!persist.running) indicator.opacity = 0;
166+ }
167+
168+ Timer {
169+ id: delay
170+ interval: 200
171+ onTriggered: if (indicator.processing) {
172+ persist.restart();
173+ indicator.opacity = 1;
174+ }
175+ }
176+
177+ Timer {
178+ id: persist
179+ interval: 2 * UbuntuAnimation.SleepyDuration - UbuntuAnimation.FastDuration
180+ onTriggered: if (!indicator.processing) indicator.opacity = 0
181+ }
182+
183+ Rectangle {
184+ id: orange
185+ anchors { top: parent.top; bottom: parent.bottom }
186+ width: parent.width / 4
187+ color: Theme.palette.selected.foreground
188+
189+ SequentialAnimation {
190+ running: indicator.visible
191+ loops: Animation.Infinite
192+ XAnimator {
193+ from: -orange.width / 2
194+ to: indicator.width - orange.width / 2
195+ duration: UbuntuAnimation.SleepyDuration
196+ easing.type: Easing.InOutSine
197+ target: orange
198+ }
199+ XAnimator {
200+ from: indicator.width - orange.width / 2
201+ to: -orange.width / 2
202+ duration: UbuntuAnimation.SleepyDuration
203+ easing.type: Easing.InOutSine
204+ target: orange
205+ }
206+ }
207+ }
208+ }
209+
129210}
qml/Dash/DashApplication.qmlnew file+36
@@ -0,0 +1,36 @@
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+import QtQuick 2.2
18+import Ubuntu.Components 1.0
19+import Ubuntu.Thumbnailer 0.1 // Register support for image://thumbnailer/ and image://albumart/
20+
21+MainView {
22+ width: units.gu(40)
23+ height: units.gu(71)
24+
25+ useDeprecatedToolbar: false
26+
27+ Binding {
28+ target: i18n
29+ property: "domain"
30+ value: "unity8"
31+ }
32+
33+ Dash {
34+ anchors.fill: parent
35+ }
36+}
qml/Dash/DashApps.qmldeleted−40
@@ -1,40 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−import Utils 0.1
20−import Unity.Application 0.1
21−import "../Components"
22−import "../Components/ListItems"
23−import "Apps"
24−
25−GenericScopeView {
26− id: scopeView
27− objectName: "DashApps"
28−
29− property var runningApps: ApplicationManager
30−
31− QtObject {
32− id: countObject
33− property int count: scopeView.scope.searchQuery.length == 0 ? scopeView.runningApps.count : 0
34− }
35−
36− onScopeChanged: {
37− scopeView.scope.categories.addSpecialCategory("running.apps.category", i18n.tr("Recent"), "", "{ \"template\": { \"category-layout\": \"running-apps\" } }", countObject);
38− enableHeightBehaviorOnNextCreation = scopeView.runningApps.count === 0
39− }
40−}
qml/Dash/DashContent.qml+12−7
@@ -23,9 +23,10 @@ import "../Components"
2323Item {
2424 id: dashContent
2525
26− property var model: null
27− property var scopes: null
26+ property alias scopes: dashContentList.model
2827 readonly property alias currentIndex: dashContentList.currentIndex
28+ readonly property bool processing: dashContentList.currentItem && dashContentList.currentItem.item
29+ && dashContentList.currentItem.item.processing || false
2930
3031 signal scopeLoaded(string scopeId)
3132 signal gotoScope(string scopeId)
@@ -89,10 +90,9 @@ Item {
8990 id: dashContentList
9091 objectName: "dashContentList"
9192
92− interactive: dashContent.scopes.loaded && currentItem && !currentItem.moving
93+ interactive: dashContent.scopes.loaded && currentItem && !currentItem.moving && !currentItem.navigationShown
9394
9495 anchors.fill: parent
95− model: dashContent.model
9696 orientation: ListView.Horizontal
9797 boundsBehavior: Flickable.DragAndOvershootBounds
9898 flickDeceleration: units.gu(625)
@@ -121,13 +121,16 @@ Item {
121121 Loader {
122122 width: ListView.view.width
123123 height: ListView.view.height
124+ opacity: { // hide delegate if offscreen
125+ var xPositionRelativetoView = ListView.view.contentX - x
126+ return (xPositionRelativetoView > -width && xPositionRelativetoView < width) ? 1 : 0
127+ }
124128 asynchronous: true
125− // TODO This if will eventually go away since we're killing DashApps.qml
126− // once we move app closing to the spread
127− source: (scope.id == "clickscope") ? "DashApps.qml" : "GenericScopeView.qml"
129+ source: "GenericScopeView.qml"
128130 objectName: scope.id + " loader"
129131
130132 readonly property bool moving: item ? item.moving : false
133+ readonly property bool navigationShown: item ? item.navigationShown : false
131134 readonly property var categoryView: item ? item.categoryView : null
132135 readonly property var theScope: scope
133136
@@ -141,6 +144,8 @@ Item {
141144 item.scope = Qt.binding(function() { return scope })
142145 item.isCurrent = Qt.binding(function() { return visible && ListView.isCurrentItem })
143146 dashContent.scopeLoaded(item.scope.id)
147+ item.paginationCount = Qt.binding(function() { return dashContentList.count } )
148+ item.paginationIndex = Qt.binding(function() { return dashContentList.currentIndex } )
144149 }
145150 Connections {
146151 target: isCurrent ? scope : null
qml/Dash/DashDepartments.qml → qml/Dash/DashNavigation.qmlrenamed+50−43
@@ -15,17 +15,17 @@
1515 */
1616
1717import QtQuick 2.2
18−import Ubuntu.Components 0.1
18+import Ubuntu.Components 1.1
1919
2020AbstractButton {
2121 id: root
22− objectName: "dashDepartments"
22+ objectName: "dashNavigation"
2323
2424 property var scope: null
2525
2626 property bool showList: false
2727
28− readonly property var currentDepartment: scope && scope.hasDepartments ? scope.getDepartment(scope.currentDepartmentId) : null
28+ readonly property var currentNavigation: scope && scope.hasNavigation ? scope.getNavigation(scope.currentNavigationId) : null
2929
3030 property alias windowWidth: blackRect.width
3131 property alias windowHeight: blackRect.height
@@ -34,20 +34,21 @@ AbstractButton {
3434 // Are we drilling down the tree or up?
3535 property bool isGoingBack: false
3636
37− visible: root.currentDepartment != null
37+ visible: root.currentNavigation != null
3838
3939 height: visible ? units.gu(5) : 0
4040
4141 onClicked: {
42+ navigationListView.updateMaxHeight();
4243 root.showList = !root.showList;
4344 }
4445
4546 Rectangle {
4647 id: blackRect
4748 color: "black"
48− opacity: departmentListView.currentItem && departmentListView.currentItem.visible ? 0.3 : 0
49+ opacity: navigationListView.currentItem && navigationListView.currentItem.visible ? 0.3 : 0
4950 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
50− anchors.top: departmentListView.top
51+ anchors.top: navigationListView.top
5152 anchors.right: parent.right
5253 visible: opacity != 0
5354 }
@@ -78,7 +79,7 @@ AbstractButton {
7879 anchors.fill: parent
7980 anchors.margins: units.gu(2)
8081 verticalAlignment: Text.AlignVCenter
81− text: root.currentDepartment ? root.currentDepartment.label : ""
82+ text: root.currentNavigation ? root.currentNavigation.label : ""
8283 color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
8384 }
8485
@@ -92,18 +93,18 @@ AbstractButton {
9293 color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
9394 }
9495
95− // departmentListView is outside root
96+ // navigationListView is outside root
9697 ListView {
97− id: departmentListView
98− objectName: "departmentListView"
98+ id: navigationListView
99+ objectName: "navigationListView"
99100 orientation: ListView.Horizontal
100101 interactive: false
101102 clip: root.width != windowWidth
102103 model: ListModel {
103− id: departmentModel
104+ id: navigationModel
104105 // We have two roles
105− // departmentId: the department id of the department the list represents
106− // nullifyDepartment: overrides departmentId to be null
106+ // navigationId: the navigation id of the navigation the list represents
107+ // nullifyNavigation: overrides navigationId to be null
107108 // This is used to "clear" the delegate when going "right" on the tree
108109 }
109110 anchors {
@@ -111,7 +112,12 @@ AbstractButton {
111112 right: parent.right
112113 top: root.bottom
113114 }
114− readonly property int maxHeight: (windowHeight - mapToItem(null, root.x, root.y).y) - units.gu(8)
115+ property int maxHeight: -1
116+ Component.onCompleted: updateMaxHeight();
117+ function updateMaxHeight()
118+ {
119+ maxHeight = (windowHeight - mapToItem(null, 0, 0).y) - units.gu(8);
120+ }
115121 property int prevHeight: maxHeight
116122 height: currentItem ? currentItem.height : maxHeight
117123 onHeightChanged: {
@@ -120,83 +126,84 @@ AbstractButton {
120126 }
121127 }
122128 highlightMoveDuration: UbuntuAnimation.FastDuration
123− delegate: DashDepartmentsList {
124− objectName: "department" + index
129+ delegate: DashNavigationList {
130+ objectName: "navigation" + index
125131 visible: height != 0
126− width: departmentListView.width
132+ width: navigationListView.width
127133 scopeStyle: root.scopeStyle
128134 property real desiredHeight: {
129135 if (root.showList) {
130− if (department && department.loaded && x == departmentListView.contentX)
136+ if (navigation && navigation.loaded && x == navigationListView.contentX)
131137 {
132− return Math.min(implicitHeight, departmentListView.maxHeight);
138+ navigationListView.updateMaxHeight();
139+ return Math.min(implicitHeight, navigationListView.maxHeight);
133140 } else {
134− return departmentListView.prevHeight;
141+ return navigationListView.prevHeight;
135142 }
136143 } else {
137144 return 0;
138145 }
139146 }
140147 height: desiredHeight
141− department: (nullifyDepartment || !scope) ? null : scope.getDepartment(departmentId)
142− currentDepartment: root.currentDepartment
143− onEnterDepartment: {
144− scope.loadDepartment(newDepartmentId);
148+ navigation: (nullifyNavigation || !scope) ? null : scope.getNavigation(navigationId)
149+ currentNavigation: root.currentNavigation
150+ onEnterNavigation: {
151+ scope.setNavigationState(newNavigationId, false);
145152 // We only need to add a new item to the model
146153 // if we have children, otherwise just load it
147154 if (hasChildren) {
148155 isGoingBack = false;
149− departmentModel.append({"departmentId": newDepartmentId, "nullifyDepartment": false});
150− departmentListView.currentIndex++;
156+ navigationModel.append({"navigationId": newNavigationId, "nullifyNavigation": false});
157+ navigationListView.currentIndex++;
151158 } else {
152159 showList = false;
153160 }
154161 }
155162 onGoBackToParentClicked: {
156− scope.loadDepartment(department.parentDepartmentId);
163+ scope.setNavigationState(navigation.parentNavigationId, false);
157164 isGoingBack = true;
158− departmentModel.setProperty(departmentListView.currentIndex - 1, "nullifyDepartment", false);
159− departmentListView.currentIndex--;
165+ navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", false);
166+ navigationListView.currentIndex--;
160167 }
161− onAllDepartmentClicked: {
168+ onAllNavigationClicked: {
162169 showList = false;
163− if (root.currentDepartment.parentDepartmentId == department.departmentId) {
170+ if (root.currentNavigation.parentNavigationId == navigation.navigationId) {
164171 // For leaves we have to go to the parent too
165− scope.loadDepartment(root.currentDepartment.parentDepartmentId);
172+ scope.setNavigationState(root.currentNavigation.parentNavigationId, false);
166173 }
167174 }
168175 }
169176 onContentXChanged: {
170− if (contentX == width * departmentListView.currentIndex) {
177+ if (contentX == width * navigationListView.currentIndex) {
171178 if (isGoingBack) {
172− departmentModel.remove(departmentListView.currentIndex + 1);
179+ navigationModel.remove(navigationListView.currentIndex + 1);
173180 } else {
174− departmentModel.setProperty(departmentListView.currentIndex - 1, "nullifyDepartment", true);
181+ navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", true);
175182 }
176183 }
177184 }
178185 }
179186
180187 InverseMouseArea {
181− anchors.fill: departmentListView
188+ anchors.fill: navigationListView
182189 enabled: root.showList
183190 onClicked: root.showList = false
184191 }
185192
186193 onScopeChanged: {
187− departmentModel.clear();
188− if (scope && scope.hasDepartments) {
189− departmentModel.append({"departmentId": scope.currentDepartmentId, "nullifyDepartment": false});
194+ navigationModel.clear();
195+ if (scope && scope.hasNavigation) {
196+ navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
190197 }
191198 }
192199
193200 Connections {
194201 target: scope
195− onHasDepartmentsChanged: {
196− if (scope.hasDepartments) {
197− departmentModel.append({"departmentId": scope.currentDepartmentId, "nullifyDepartment": false});
202+ onHasNavigationChanged: {
203+ if (scope.hasNavigation) {
204+ navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
198205 } else {
199− departmentModel.clear();
206+ navigationModel.clear();
200207 }
201208 }
202209 }
qml/Dash/DashDepartmentsList.qml → qml/Dash/DashNavigationList.qmlrenamed+14−18
@@ -15,16 +15,16 @@
1515 */
1616
1717import QtQuick 2.2
18−import Ubuntu.Components 0.1
18+import Ubuntu.Components 1.1
1919
2020Item {
2121 id: root
22− property var department: null
23− property var currentDepartment: null
22+ property var navigation: null
23+ property var currentNavigation: null
2424 property var scopeStyle: null
25− signal enterDepartment(var newDepartmentId, bool hasChildren)
25+ signal enterNavigation(var newNavigationId, bool hasChildren)
2626 signal goBackToParentClicked()
27− signal allDepartmentClicked()
27+ signal allNavigationClicked()
2828
2929 readonly property int itemHeight: units.gu(5)
3030 readonly property color foregroundColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
@@ -35,11 +35,6 @@ Item {
3535 anchors.fill: parent
3636 }
3737
38− ActivityIndicator {
39− id: loadingIndicator
40− anchors.centerIn: parent
41− running: !(department && department.loaded)
42− }
4338 clip: true
4439
4540 Behavior on height {
@@ -54,6 +49,7 @@ Item {
5449
5550 anchors.fill: parent
5651
52+ flickableDirection: Flickable.VerticalFlick
5753 contentHeight: column.height
5854 contentWidth: width
5955
@@ -68,7 +64,7 @@ Item {
6864 id: backButton
6965 objectName: "backButton"
7066 width: parent.width
71− visible: department && !department.isRoot || false
67+ visible: navigation && !navigation.isRoot || false
7268 height: itemHeight
7369
7470 onClicked: root.goBackToParentClicked();
@@ -92,7 +88,7 @@ Item {
9288 left: backImage.right
9389 leftMargin: units.gu(0.5)
9490 }
95− text: department ? department.parentLabel : ""
91+ text: navigation ? navigation.parentLabel : ""
9692 color: root.foregroundColor
9793 }
9894
@@ -114,7 +110,7 @@ Item {
114110 id: allButton
115111 objectName: "allButton"
116112 width: parent.width
117− visible: department && (!department.isRoot || (root.currentDepartment && !root.currentDepartment.isRoot && root.currentDepartment.parentDepartmentId == department.departmentId)) || false
113+ visible: navigation && (!navigation.isRoot || (root.currentNavigation && !root.currentNavigation.isRoot && root.currentNavigation.parentNavigationId == navigation.navigationId)) || false
118114 height: itemHeight
119115
120116 Label {
@@ -123,7 +119,7 @@ Item {
123119 left: parent.left
124120 leftMargin: units.gu(2)
125121 }
126− text: department ? (department.allLabel != "" ? department.allLabel : department.label) : ""
122+ text: navigation ? (navigation.allLabel != "" ? navigation.allLabel : navigation.label) : ""
127123 font.bold: true
128124 color: root.foregroundColor
129125 }
@@ -141,18 +137,18 @@ Item {
141137 height: units.dp(1)
142138 }
143139
144− onClicked: root.allDepartmentClicked();
140+ onClicked: root.allNavigationClicked();
145141 }
146142
147143 Repeater {
148− model: department && department.loaded ? department : null
144+ model: navigation && navigation.loaded ? navigation : null
149145 clip: true
150146 delegate: AbstractButton {
151147 objectName: root.objectName + "child" + index
152148 height: root.itemHeight
153149 width: root.width
154150
155− onClicked: root.enterDepartment(departmentId, hasChildren)
151+ onClicked: root.enterNavigation(navigationId, hasChildren)
156152
157153 Label {
158154 anchors {
@@ -188,7 +184,7 @@ Item {
188184 color: root.foregroundColor
189185 opacity: 0.1
190186 height: units.dp(1)
191− visible: index != department.count - 1
187+ visible: index != navigation.count - 1
192188 }
193189 }
194190 }
qml/Dash/DashRenderer.qml+3−10
@@ -17,15 +17,11 @@
1717import QtQuick 2.0
1818
1919Item {
20− // Can the item be expanded?
21− property bool expandable: false
20+ property int collapsedHeight
2221
23− // In case it can be expanded, is it filtered
24− property bool filtered: true
22+ property int expandedHeight
2523
26− property int collapsedHeight: height
27−
28− property int uncollapsedHeight: height
24+ property int collapsedItemCount: -1
2925
3026 property int displayMarginBeginning: 0
3127
@@ -50,7 +46,4 @@ Item {
5046 /// Emitted when the user pressed and held on an item
5147 /// @param index is the index of the held item
5248 signal pressAndHold(int index)
53−
54− function setFilter(filter, animate) {
55− }
5649}
qml/Dash/GenericScopeView.qml+141−86
@@ -18,7 +18,6 @@ import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Utils 0.1
2020import Unity 0.2
21−import Unity.Application 0.1
2221import Dash 0.1
2322import "../Components"
2423import "../Components/ListItems" as ListItems
@@ -26,6 +25,7 @@ import "../Components/ListItems" as ListItems
2625FocusScope {
2726 id: scopeView
2827
28+ readonly property alias navigationShown: dashNavigation.showList
2929 property var scope: null
3030 property SortFilterProxyModel categories: categoryFilter
3131 property bool isCurrent: false
@@ -33,22 +33,16 @@ FocusScope {
3333 property bool hasBackAction: false
3434 property bool enableHeightBehaviorOnNextCreation: false
3535 property var categoryView: categoryView
36+ property alias paginationCount: pageHeader.paginationCount
37+ property alias paginationIndex: pageHeader.paginationIndex
3638
3739 property var scopeStyle: ScopeStyle {
3840 style: scope ? scope.customizations : {}
3941 }
4042
41− signal backClicked()
42−
43− onScopeChanged: {
44− if (scope) {
45− scope.activateApplication.connect(activateApp);
46− }
47− }
43+ readonly property bool processing: scope ? scope.searchInProgress || previewListView.processing : false
4844
49− function activateApp(appId) {
50− shell.activateApplication(appId);
51− }
45+ signal backClicked()
5246
5347 function positionAtBeginning() {
5448 categoryView.positionAtBeginning()
@@ -119,6 +113,8 @@ FocusScope {
119113
120114 model: scopeView.categories
121115 forceNoClip: previewListView.open
116+ pixelAligned: true
117+ interactive: !dashNavigation.showList
122118
123119 property string expandedCategoryId: ""
124120
@@ -128,11 +124,22 @@ FocusScope {
128124 highlightWhenPressed: false
129125 showDivider: false
130126
131− readonly property bool expandable: rendererLoader.item ? rendererLoader.item.expandable : false
132− readonly property bool filtered: rendererLoader.item ? rendererLoader.item.filtered : true
127+ readonly property bool expandable: {
128+ if (categoryView.model.count === 1) return false;
129+ if (cardTool.template && cardTool.template["collapsed-rows"] === 0) return false;
130+ if (item && item.expandedHeight > item.collapsedHeight) return true;
131+ return false;
132+ }
133+ property bool expanded: false
133134 readonly property string category: categoryId
135+ readonly property string headerLink: model.headerLink
134136 readonly property var item: rendererLoader.item
135137
138+ function expand(expand, animate) {
139+ heightBehaviour.enabled = animate;
140+ expanded = expand;
141+ }
142+
136143 CardTool {
137144 id: cardTool
138145 objectName: "cardTool"
@@ -142,22 +149,48 @@ FocusScope {
142149 viewWidth: parent.width
143150 }
144151
152+ onExpandableChanged: {
153+ // This can happen with the VJ that doesn't know how height it will be on creation
154+ // so doesn't set expandable until a bit too late for onLoaded
155+ if (expandable) {
156+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
157+ baseItem.expand(shouldExpand, false /*animate*/);
158+ }
159+ }
160+
161+ onHeightChanged: rendererLoader.updateDelegateCreationRange();
162+ onYChanged: rendererLoader.updateDelegateCreationRange();
163+
145164 Loader {
146165 id: rendererLoader
147166 anchors {
148167 top: parent.top
149168 left: parent.left
150169 right: parent.right
151− topMargin: hasSectionHeader ? 0 : units.gu(2)
170+ topMargin: name != "" ? 0 : units.gu(2)
152171 }
153172
173+ Behavior on height {
174+ id: heightBehaviour
175+ enabled: false
176+ animation: UbuntuNumberAnimation {
177+ onRunningChanged: {
178+ if (!running) {
179+ heightBehaviour.enabled = false
180+ }
181+ }
182+ }
183+ }
184+
185+ readonly property bool expanded: baseItem.expanded || !baseItem.expandable
186+ height: expanded ? item.expandedHeight : item.collapsedHeight
187+
154188 source: {
155189 switch (cardTool.categoryLayout) {
156190 case "carousel": return "CardCarousel.qml";
157191 case "vertical-journal": return "CardVerticalJournal.qml";
158− case "running-apps": return "Apps/RunningApplicationsGrid.qml";
159192 case "grid":
160− default: return "CardFilterGrid.qml";
193+ default: return "CardGrid.qml";
161194 }
162195 }
163196
@@ -166,21 +199,18 @@ FocusScope {
166199 item.enableHeightBehavior = scopeView.enableHeightBehaviorOnNextCreation;
167200 scopeView.enableHeightBehaviorOnNextCreation = false;
168201 }
169− if (source.toString().indexOf("Apps/RunningApplicationsGrid.qml") != -1) {
170− // TODO: this is still a kludge :D Ideally add some kind of hook so that we
171− // can do this from DashApps.qml or think a better way that needs no special casing
172− item.model = Qt.binding(function() { return runningApps; })
173− item.canEnableTerminationMode = Qt.binding(function() { return scopeView.isCurrent })
174− } else {
175− item.model = Qt.binding(function() { return results })
176− }
202+ item.model = Qt.binding(function() { return results })
177203 item.objectName = Qt.binding(function() { return categoryId })
178204 item.scopeStyle = scopeView.scopeStyle;
179− if (item.expandable) {
180− var shouldFilter = categoryId != categoryView.expandedCategoryId;
181− item.setFilter(shouldFilter, false /*animate*/);
205+ if (baseItem.expandable) {
206+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
207+ baseItem.expand(shouldExpand, false /*animate*/);
182208 }
183209 updateDelegateCreationRange();
210+ if (scope && scope.id === "clickscope" && (categoryId === "predefined" || categoryId === "local")) {
211+ // Yeah, hackish :/
212+ cardTool.artShapeSize = Qt.size(units.gu(8), units.gu(7.5));
213+ }
184214 item.cardTool = cardTool;
185215 }
186216
@@ -199,25 +229,22 @@ FocusScope {
199229 // so it's not implemented
200230 scopeView.scope.activate(result)
201231 } else {
202− previewListView.model = target.model;
203− previewListView.currentIndex = -1
204− previewListView.currentIndex = index;
205− previewListView.open = true
232+ openPreview(index);
206233 }
207234 }
208− onPressAndHold: {
209− previewListView.model = target.model;
210− previewListView.currentIndex = -1
211− previewListView.currentIndex = index;
212− previewListView.open = true
213− }
214− onExpandableChanged: {
215− // This can happen with the VJ that doesn't know how height it will be on creation
216− // so doesn't set expandable until a bit too late for onLoaded
217− if (rendererLoader.item.expandable) {
218− var shouldFilter = baseItem.category != categoryView.expandedCategoryId;
219− rendererLoader.item.setFilter(shouldFilter, false /*animate*/);
235+ onPressAndHold: openPreview(index)
236+
237+ function openPreview(index) {
238+ if (!rendererLoader.expanded && !seeAllLabel.visible && target.collapsedItemCount > 0) {
239+ previewLimitModel.model = target.model;
240+ previewLimitModel.limit = target.collapsedItemCount;
241+ previewListView.model = previewLimitModel;
242+ } else {
243+ previewListView.model = target.model;
220244 }
245+ previewListView.currentIndex = -1;
246+ previewListView.currentIndex = index;
247+ previewListView.open = true;
221248 }
222249 }
223250 Connections {
@@ -227,17 +254,17 @@ FocusScope {
227254 }
228255 function collapseAllButExpandedCategory() {
229256 var item = rendererLoader.item;
230− if (item.expandable) {
231− var shouldFilter = categoryId != categoryView.expandedCategoryId;
232− if (shouldFilter != item.filter) {
257+ if (baseItem.expandable) {
258+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
259+ if (shouldExpand != baseItem.expanded) {
233260 // If the filter animation will be seen start it, otherwise, just flip the switch
234− var shrinkingVisible = shouldFilter && y + item.collapsedHeight < categoryView.height;
235− var growingVisible = !shouldFilter && y + height < categoryView.height;
236− if (!previewListView.open || !shouldFilter) {
261+ var shrinkingVisible = !shouldExpand && y + item.collapsedHeight + seeAll.height < categoryView.height;
262+ var growingVisible = shouldExpand && y + height < categoryView.height;
263+ if (!previewListView.open || shouldExpand) {
237264 var animate = shrinkingVisible || growingVisible;
238− item.setFilter(shouldFilter, animate)
239− if (!shouldFilter && !previewListView.open) {
240− categoryView.maximizeVisibleArea(index, item.uncollapsedHeight);
265+ baseItem.expand(shouldExpand, animate)
266+ if (shouldExpand && !previewListView.open) {
267+ categoryView.maximizeVisibleArea(index, item.expandedHeight + seeAll.height);
241268 }
242269 }
243270 }
@@ -274,58 +301,82 @@ FocusScope {
274301 item.displayMarginEnd = -baseItem.height;
275302 } else {
276303 item.displayMarginBeginning = -Math.max(-baseItem.y, 0);
277− item.displayMarginEnd = -Math.max(baseItem.height - categoryView.height + baseItem.y, 0)
304+ item.displayMarginEnd = -Math.max(baseItem.height - seeAll.height
305+ - categoryView.height + baseItem.y, 0)
278306 }
279307 }
280308 }
309+ }
281310
282− Image {
283− visible: index != 0
284− anchors {
285− top: parent.top
286− left: parent.left
287− right: parent.right
311+ AbstractButton {
312+ id: seeAll
313+ objectName: "seeAll"
314+ anchors {
315+ top: rendererLoader.bottom
316+ left: parent.left
317+ right: parent.right
318+ }
319+ height: seeAllLabel.visible ? seeAllLabel.font.pixelSize + units.gu(6) : 0
320+
321+ onClicked: {
322+ if (categoryView.expandedCategoryId != baseItem.category) {
323+ categoryView.expandedCategoryId = baseItem.category;
324+ } else {
325+ categoryView.expandedCategoryId = "";
288326 }
289− fillMode: Image.Stretch
290− source: "graphics/dash_divider_top_lightgrad.png"
291− z: -1
292327 }
293328
294− Image {
295− // FIXME Should not rely on model.count but view.count, but ListViewWithPageHeader doesn't expose it yet.
296− visible: index != categoryView.model.count - 1
329+ Label {
330+ id: seeAllLabel
331+ text: baseItem.expanded ? i18n.tr("See less") : i18n.tr("See all")
297332 anchors {
298− bottom: parent.bottom
299− left: parent.left
300− right: parent.right
333+ centerIn: parent
334+ verticalCenterOffset: units.gu(-0.5)
301335 }
302− fillMode: Image.Stretch
303− source: "graphics/dash_divider_top_darkgrad.png"
304− z: -1
336+ fontSize: "small"
337+ font.weight: Font.Bold
338+ color: scopeStyle ? scopeStyle.foreground : "grey"
339+ visible: baseItem.expandable && !baseItem.headerLink
305340 }
306341 }
307342
308− onHeightChanged: rendererLoader.updateDelegateCreationRange();
309− onYChanged: rendererLoader.updateDelegateCreationRange();
343+ Image {
344+ visible: index != 0
345+ anchors {
346+ top: parent.top
347+ left: parent.left
348+ right: parent.right
349+ }
350+ fillMode: Image.Stretch
351+ source: "graphics/dash_divider_top_lightgrad.png"
352+ z: -1
353+ }
354+
355+ Image {
356+ // FIXME Should not rely on model.count but view.count, but ListViewWithPageHeader doesn't expose it yet.
357+ visible: index != categoryView.model.count - 1
358+ anchors {
359+ bottom: seeAll.bottom
360+ left: parent.left
361+ right: parent.right
362+ }
363+ fillMode: Image.Stretch
364+ source: "graphics/dash_divider_top_darkgrad.png"
365+ z: -1
366+ }
310367 }
311368
312369 sectionProperty: "name"
313370 sectionDelegate: ListItems.Header {
314371 objectName: "dashSectionHeader" + (delegate ? delegate.category : "")
315− property var delegate: categoryView.item(delegateIndex)
372+ readonly property var delegate: categoryView.item(delegateIndex)
316373 width: categoryView.width
374+ height: section != "" ? units.gu(5) : 0
317375 text: section
318− textColor: scopeStyle ? scopeStyle.foreground : "grey"
319− image: {
320− if (delegate && delegate.expandable)
321− return delegate.filtered ? "graphics/header_handlearrow.png" : "graphics/header_handlearrow2.png"
322− return "";
323− }
376+ color: scopeStyle ? scopeStyle.foreground : "grey"
377+ iconName: delegate && delegate.headerLink ? "go-next" : ""
324378 onClicked: {
325− if (categoryView.expandedCategoryId != delegate.category)
326− categoryView.expandedCategoryId = delegate.category;
327− else
328− categoryView.expandedCategoryId = "";
379+ if (delegate.headerLink) scopeView.scope.performQuery(delegate.headerLink);
329380 }
330381 }
331382
@@ -336,10 +387,10 @@ FocusScope {
336387 title: scopeView.scope ? scopeView.scope.name : ""
337388 showBackButton: scopeView.hasBackAction
338389 searchEntryEnabled: true
339− searchInProgress: scopeView.scope ? scopeView.scope.searchInProgress : false
340390 scopeStyle: scopeView.scopeStyle
341391
342− bottomItem: DashDepartments {
392+ bottomItem: DashNavigation {
393+ id: dashNavigation
343394 scope: scopeView.scope
344395 width: parent.width <= units.gu(60) ? parent.width : units.gu(40)
345396 anchors.right: parent.right
@@ -352,6 +403,10 @@ FocusScope {
352403 }
353404 }
354405
406+ LimitProxyModel {
407+ id: previewLimitModel
408+ }
409+
355410 PreviewListView {
356411 id: previewListView
357412 objectName: "previewListView"
qml/Dash/PreviewListView.qml+23−27
@@ -32,6 +32,9 @@ Item {
3232 property alias currentItem: previewListView.currentItem
3333 property alias count: previewListView.count
3434
35+ readonly property bool processing: currentItem && (!currentItem.previewModel.loaded
36+ || currentItem.previewModel.processingAction)
37+
3538 PageHeader {
3639 id: header
3740 objectName: "pageHeader"
@@ -83,39 +86,32 @@ Item {
8386 }
8487 }
8588
86− delegate: Item {
87− objectName: "previewItem" + index
89+ delegate: Previews.Preview {
90+ id: preview
91+ objectName: "preview" + index
8892 height: previewListView.height
8993 width: previewListView.width
9094
91− readonly property bool ready: preview.previewModel.loaded
92−
93− Previews.Preview {
94− id: preview
95− objectName: "preview" + index
96− anchors.fill: parent
95+ isCurrent: ListView.isCurrentItem
9796
98− isCurrent: parent.ListView.isCurrentItem
99−
100− previewModel: {
101− var previewStack = root.scope.preview(result);
102− return previewStack.getPreviewModel(0);
103− }
104− scopeStyle: root.scopeStyle
97+ previewModel: {
98+ var previewStack = root.scope.preview(result);
99+ return previewStack.getPreviewModel(0);
105100 }
101+ scopeStyle: root.scopeStyle
102+ }
103+ }
106104
107− MouseArea {
108− id: processingMouseArea
109− objectName: "processingMouseArea"
110− anchors.fill: parent
111− enabled: !preview.previewModel.loaded || preview.previewModel.processingAction
112−
113− ActivityIndicator {
114− anchors.centerIn: parent
115− visible: root.open && parent.enabled
116− running: visible
117− }
118− }
105+ MouseArea {
106+ id: processingMouseArea
107+ objectName: "processingMouseArea"
108+ anchors {
109+ left: parent.left
110+ right: parent.right
111+ top: pageHeader.bottom
112+ bottom: parent.bottom
119113 }
114+
115+ enabled: root.processing
120116 }
121117}
qml/Dash/Previews/PreviewExpandable.qmlnew file+101
@@ -0,0 +1,101 @@
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+import QtQuick 2.3
18+import Ubuntu.Components 1.1
19+import "../../Components"
20+
21+/*! \brief Preview widget for expandable widgets.
22+
23+ This widget shows a list of widgets defined in widgetData["widgets"]
24+ Those widgets can be collapsed or uncollapsed. When uncollapsed
25+ all the widgets are shown, when collapsed only the first
26+ widgetData["collapsed-widgets"] are shown. It has a title that comes
27+ in via widgetData["title"]
28+ */
29+
30+PreviewWidget {
31+ id: root
32+ implicitHeight: childrenRect.height
33+
34+ expanded: false
35+
36+ Label {
37+ id: titleLabel
38+ objectName: "titleLabel"
39+ anchors {
40+ left: parent.left
41+ right: expandButton.left
42+ }
43+ fontSize: "large"
44+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
45+ visible: text !== ""
46+ opacity: .8
47+ text: widgetData["title"] || ""
48+ wrapMode: Text.Wrap
49+ }
50+
51+ AbstractButton {
52+ id: expandButton
53+ objectName: "expandButton"
54+ width: titleLabel.height
55+ height: titleLabel.height
56+ anchors.right: parent.right
57+ onClicked: {
58+ root.expanded = !root.expanded;
59+ }
60+ Icon {
61+ anchors.fill: parent
62+ width: 64
63+ height: 64
64+ name: root.expanded ? "view-collapse" : "view-expand"
65+ }
66+ }
67+
68+ Column {
69+ anchors {
70+ top: titleLabel.bottom
71+ topMargin: units.gu(1)
72+ left: parent.left
73+ right: parent.right
74+ }
75+ spacing: units.gu(1)
76+ Repeater {
77+ id: repeater
78+ objectName: "repeater"
79+ model: widgetData["widgets"]
80+ delegate: PreviewWidgetFactory {
81+ height: visible ? implicitHeight : 0
82+ width: parent.width
83+ widgetId: modelData.widgetId
84+ widgetType: modelData.type
85+ widgetData: modelData.properties
86+ isCurrentPreview: root.isCurrentPreview
87+ scopeStyle: root.scopeStyle
88+ anchors {
89+ left: parent.left
90+ right: parent.right
91+ }
92+ expanded: root.expanded
93+ visible: root.expanded || index < root.widgetData["collapsed-widgets"]
94+
95+ onTriggered: {
96+ root.triggered(widgetId, actionId, data);
97+ }
98+ }
99+ }
100+ }
101+}
qml/Dash/Previews/PreviewImageGallery.qml+1
@@ -15,6 +15,7 @@
1515 */
1616
1717import QtQuick 2.0
18+import Ubuntu.Components 1.1
1819import "../../Components"
1920
2021/*! This preview widget shows a horizontal list of images.
qml/Dash/Previews/PreviewTextSummary.qml+3−16
@@ -23,7 +23,7 @@ import "../../Components"
2323 This widget shows text contained in widgetData["text"]
2424 along with a title that comes from widgetData["title"].
2525
26− In case the text does not fit in 7 lines a See More / Less widget is also shown.
26+ In case the widget is collapsed it only shows 3 lines of text.
2727 */
2828
2929PreviewWidget {
@@ -50,14 +50,14 @@ PreviewWidget {
5050 id: textLabel
5151 objectName: "textLabel"
5252
53− readonly property int maximumCollapsedLineCount: 7
53+ readonly property int maximumCollapsedLineCount: 3
5454
5555 anchors {
5656 left: parent.left
5757 right: parent.right
5858 top: titleLabel.visible ? titleLabel.bottom : parent.top
5959 }
60− height: (!seeMore.visible || seeMore.more) ? contentHeight : contentHeight / lineCount * (maximumCollapsedLineCount - 2)
60+ height: (lineCount <= maximumCollapsedLineCount || root.expanded) ? contentHeight : contentHeight / lineCount * maximumCollapsedLineCount
6161 clip: true
6262 fontSize: "small"
6363 lineHeight: 1.2
@@ -70,17 +70,4 @@ PreviewWidget {
7070 UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
7171 }
7272 }
73−
74− SeeMore {
75− id: seeMore
76− objectName: "seeMore"
77− anchors {
78− left: parent.left
79− right: parent.right
80− top: textLabel.bottom
81− topMargin: visible ? units.gu(1) : 0
82− }
83− height: visible ? implicitHeight : 0
84− visible: textLabel.lineCount > textLabel.maximumCollapsedLineCount
85− }
8673}
qml/Dash/Previews/PreviewWidget.qml+3
@@ -31,6 +31,9 @@ Item {
3131 //! The ScopeStyle component.
3232 property var scopeStyle: null
3333
34+ //! Should the widget show in expanded mode (For those that support it)
35+ property bool expanded: true
36+
3437 /*! \brief This signal should be emitted when a preview action was triggered.
3538 *
3639 * \param widgetId, actionId Respective identifiers from widgetData.
qml/Dash/Previews/PreviewWidgetFactory.qml+5
@@ -34,6 +34,9 @@ Loader {
3434 //! The ScopeStyle component.
3535 property var scopeStyle: null
3636
37+ //! Should the widget show in expanded mode (For those that support it)
38+ property bool expanded: true
39+
3740 //! Set to true if the parent preview is displayed.
3841 property bool isCurrentPreview: false
3942
@@ -47,6 +50,7 @@ Loader {
4750 switch (widgetType) {
4851 case "actions": return "PreviewActions.qml";
4952 case "audio": return "PreviewAudioPlayback.qml";
53+ case "expandable": return "PreviewExpandable.qml";
5054 case "gallery": return "PreviewImageGallery.qml";
5155 case "header": return "PreviewHeader.qml";
5256 case "image": return "PreviewZoomableImage.qml";
@@ -65,6 +69,7 @@ Loader {
6569 item.widgetId = Qt.binding(function() { return root.widgetId } )
6670 item.widgetData = Qt.binding(function() { return root.widgetData } )
6771 item.isCurrentPreview = Qt.binding(function() { return root.isCurrentPreview } )
72+ item.expanded = Qt.binding(function() { return root.expanded } )
6873 if (item.hasOwnProperty("scopeStyle")) item.scopeStyle = root.scopeStyle;
6974 }
7075
qml/Dash/ScopeListView.qml−5
@@ -20,9 +20,4 @@ import Dash 0.1
2020ListViewWithPageHeader {
2121 maximumFlickVelocity: height * 10
2222 flickDeceleration: height * 2
23−
24− Connections {
25− target: greeter
26− onShownChanged: if (greeter.shown) showHeader()
27− }
2823}
qml/Dash/graphics/phone/screenshots/unity8-dash@12.pngnew file

Binary file not shown.

qml/Dash/graphics/phone/screenshots/vkb_portrait.pngnew file

Binary file not shown.

qml/Greeter/Greeter.qml+1−1
@@ -70,7 +70,7 @@ Showable {
7070 DraggingArea {
7171 id: dragHandle
7272 anchors.fill: parent
73− enabled: (greeter.narrowMode || !greeter.locked) && greeter.enabled
73+ enabled: (greeter.narrowMode || !greeter.locked) && greeter.enabled && greeter.shown
7474 orientation: Qt.Horizontal
7575 propagateComposedEvents: true
7676
qml/Launcher/Launcher.qml+3−4
@@ -29,8 +29,7 @@ Item {
2929 property int dragAreaWidth: units.gu(1)
3030 property int minimizeDistance: units.gu(26)
3131 property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?
32− (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) :
33− (dragArea.dragging ? 0.001 : 0)
32+ (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : 0
3433
3534 readonly property bool shown: panel.x > -panel.width
3635
@@ -181,7 +180,7 @@ Item {
181180 bottom: parent.bottom
182181 }
183182 x: -width
184− opacity: (x == -width && dragArea.status === DirectionalDragArea.WaitingForTouch) ? 0 : 1
183+ visible: x > -width || dragArea.status === DirectionalDragArea.Undecided
185184 model: LauncherModel
186185
187186 property bool animate: true
@@ -245,7 +244,7 @@ Item {
245244 if (!dragging) {
246245 if (distance > panel.width / 2) {
247246 if (distance > minimizeDistance) {
248− root.dash()
247+ root.dash();
249248 } else {
250249 root.switchToNextState("visible")
251250 }
qml/Launcher/LauncherDelegate.qml+9−6
@@ -70,28 +70,31 @@ Item {
7070 height: root.itemHeight - units.gu(1)
7171 }
7272
73− BorderImage {
73+ UbuntuShape {
7474 objectName: "countEmblem"
7575 anchors {
7676 right: parent.right
7777 top: parent.top
7878 margins: units.dp(3)
7979 }
80− width: Math.min(root.itemWidth, Math.max(units.gu(3), countLabel.implicitWidth + units.gu(2.5)))
81− height: units.gu(3)
82− source: "graphics/notification.sci"
80+ width: Math.min(root.itemWidth, Math.max(units.gu(2), countLabel.implicitWidth + units.gu(1)))
81+ height: units.gu(2)
82+ color: UbuntuColors.orange
8383 visible: root.count > 0
84+ borderSource: "none"
8485
8586 Label {
8687 id: countLabel
8788 text: root.count
8889 anchors.centerIn: parent
90+ // FIXME: verticalCenter seems to be off wee bit and QML doesn't have a centerLine
91+ // property for Text: https://bugreports.qt-project.org/browse/QTBUG-40479
92+ anchors.verticalCenterOffset: -units.dp(.5)
8993 width: root.itemWidth - units.gu(1)
9094 horizontalAlignment: Text.AlignHCenter
9195 elide: Text.ElideRight
9296 color: "white"
93− fontSize: "small"
94− font.bold: true
97+ fontSize: "x-small"
9598 }
9699 }
97100
qml/Launcher/graphics/notification@30.pngdeleted

Binary file not shown.

qml/Launcher/graphics/notification@30.scideleted−5
@@ -1,5 +0,0 @@
1−border.left: 36
2−border.top: 36
3−border.bottom: 36
4−border.right: 36
5−source: notification@30.png
qml/Notifications/NotificationMenuItemFactory.qml+3
@@ -78,6 +78,9 @@ Loader {
7878 }
7979 echoMode: checkBox.checked ? TextInput.Normal : TextInput.Password
8080 height: units.gu(5)
81+ Component.onCompleted: {
82+ forceActiveFocus();
83+ }
8184 onTextChanged: {
8285 menuModel.changeState(menuIndex, text);
8386 }
qml/Panel/Indicators.qml+3
@@ -37,6 +37,7 @@ Showable {
3737 readonly property int lockThreshold: openedHeight / 2
3838 property bool fullyOpened: height == openedHeight
3939 property bool partiallyOpened: height > panelHeight && !fullyOpened
40+ property bool fullyClosed: height <= panelHeight
4041 property bool contentEnabled: true
4142 property bool initalizeItem: true
4243 readonly property alias content: menuContent
@@ -187,6 +188,7 @@ Showable {
187188 bottom: handle.top
188189 }
189190 indicatorsModel: visibleIndicators.model
191+ visible: indicators.partiallyOpened || indicators.fullyOpened
190192 clip: !indicators.fullyOpened
191193 activeHeader: indicators.state == "hint" || indicators.state == "reveal"
192194 enabled: contentEnabled
@@ -219,6 +221,7 @@ Showable {
219221 }
220222 height: Math.max(Math.min(handleImage.height, indicators.height - handleImage.height), 0)
221223 clip: height < handleImage.height
224+ visible: menuContent.visible
222225
223226 BorderImage {
224227 id: handleImage
qml/Panel/Indicators/DefaultIndicatorPage.qml+1−1
@@ -126,7 +126,7 @@ IndicatorBase {
126126 id: loader
127127 objectName: "menuItem" + index
128128 asynchronous: false
129− visible: height > 0
129+ visible: status == Loader.Ready
130130
131131 property int modelIndex: index
132132
qml/Panel/Indicators/MenuItemFactory.qml+74
@@ -57,6 +57,7 @@ Item {
5757
5858 "unity.widgets.systemsettings.tablet.wifisection" : wifiSection,
5959 "unity.widgets.systemsettings.tablet.accesspoint" : accessPoint,
60+ "com.canonical.indicator.network.modeminfoitem" : modeminfoitem,
6061 }
6162
6263 function getExtendedProperty(object, propertyName, defaultValue) {
@@ -374,6 +375,79 @@ Item {
374375 }
375376 }
376377
378+ Component {
379+ id: modeminfoitem;
380+ ModemInfoItem {
381+ objectName: "modemInfoItem"
382+ property QtObject menuData: null
383+ property var menuModel: menuFactory.menuModel
384+ property int menuIndex: -1
385+ property var extendedData: menuData && menuData.ext || undefined
386+
387+ property var statusLabelAction: UnityMenuAction {
388+ model: menuModel
389+ index: menuIndex
390+ name: getExtendedProperty(extendedData, "xCanonicalModemStatusLabelAction", "")
391+ }
392+ statusText: statusLabelAction.valid ? statusLabelAction.state : ""
393+
394+ property var statusIconAction: UnityMenuAction {
395+ model: menuModel
396+ index: menuIndex
397+ name: getExtendedProperty(extendedData, "xCanonicalModemStatusIconAction", "")
398+ }
399+ statusIcon: statusIconAction.valid ? statusIconAction.state : ""
400+
401+ property var connectivityIconAction: UnityMenuAction {
402+ model: menuModel
403+ index: menuIndex
404+ name: getExtendedProperty(extendedData, "xCanonicalModemConnectivityIconAction", "")
405+ }
406+ connectivityIcon: connectivityIconAction.valid ? connectivityIconAction.state : ""
407+
408+ property var simIdentifierLabelAction: UnityMenuAction {
409+ model: menuModel
410+ index: menuIndex
411+ name: getExtendedProperty(extendedData, "xCanonicalModemSimIdentifierLabelAction", "")
412+ }
413+ simIdentifierText: simIdentifierLabelAction.valid ? simIdentifierLabelAction.state : ""
414+
415+ property var roamingAction: UnityMenuAction {
416+ model: menuModel
417+ index: menuIndex
418+ name: getExtendedProperty(extendedData, "xCanonicalModemRoamingAction", "")
419+ }
420+ roaming: roamingAction.valid ? roamingAction.state : false
421+
422+ property var unlockAction: UnityMenuAction {
423+ model: menuModel
424+ index: menuIndex
425+ name: getExtendedProperty(extendedData, "xCanonicalModemLockedAction", "")
426+ }
427+ onUnlock: {
428+ unlockAction.activate();
429+ }
430+ locked: unlockAction.valid ? unlockAction.state : false
431+
432+ onMenuModelChanged: {
433+ loadAttributes();
434+ }
435+ onMenuIndexChanged: {
436+ loadAttributes();
437+ }
438+
439+ function loadAttributes() {
440+ if (!menuModel || menuIndex == -1) return;
441+ menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-modem-status-label-action': 'string',
442+ 'x-canonical-modem-status-icon-action': 'string',
443+ 'x-canonical-modem-connectivity-icon-action': 'string',
444+ 'x-canonical-modem-sim-identifier-label-action': 'string',
445+ 'x-canonical-modem-roaming-action': 'string',
446+ 'x-canonical-modem-locked-action': 'string'});
447+ }
448+ }
449+ }
450+
377451 Component {
378452 id: messageItem
379453
qml/Panel/Indicators/ModemInfoItem.qmlnew file+111
@@ -0,0 +1,111 @@
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 Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtQuick.Layouts 1.1
19+import Ubuntu.Components 0.1
20+import Ubuntu.Components.ListItems 0.1 as ListItem
21+
22+ListItem.Empty {
23+ id: menu
24+ implicitHeight: mainColumn.implicitHeight
25+ + mainColumn.anchors.topMargin
26+ + mainColumn.anchors.bottomMargin
27+
28+ property alias statusIcon: statusIcon.name
29+ property alias statusText: labelStatus.text
30+ property alias connectivityIcon: iconConnectivity.name
31+ property alias simIdentifierText: labelSimIdentifier.text
32+ property bool locked : false
33+ property bool roaming: false
34+ signal unlock
35+
36+ ColumnLayout {
37+ id: mainColumn
38+ anchors.fill: parent
39+ anchors.margins: menu.__contentsMargins
40+ spacing: units.gu(0.5)
41+
42+ Label {
43+ id: labelSimIdentifier
44+ elide: Text.ElideRight
45+ visible: text !== ""
46+ font.bold: true
47+ opacity: menu.locked ? 0.6 : 1.0
48+ }
49+
50+ RowLayout {
51+ id: statusRow
52+ spacing: units.gu(1)
53+
54+ height: labelStatus.height
55+ width: parent.width
56+
57+ Label {
58+ id: labelStatus
59+ elide: Text.ElideRight
60+ opacity: 0.6
61+ }
62+
63+ RowLayout {
64+ spacing: 0.5
65+ height: parent.height
66+ Icon {
67+ id: statusIcon
68+ color: Theme.palette.selected.backgroundText
69+
70+ Layout.preferredHeight: parent.height
71+ Layout.preferredWidth: Layout.preferredHeight
72+
73+ visible: name !== ""
74+ }
75+
76+ Icon {
77+ id: iconConnectivity
78+ color: Theme.palette.selected.backgroundText
79+
80+ Layout.preferredHeight: parent.height
81+ Layout.preferredWidth: Layout.preferredHeight
82+
83+ visible: name !== ""
84+ }
85+ }
86+
87+ Item {
88+ // eat up all the excess space so that RoamingIndication
89+ // ends up to the far right
90+ Layout.fillWidth: true
91+ }
92+
93+ RoamingIndication {
94+ id: roamingIndication
95+ visible: menu.roaming
96+ Layout.fillHeight: true
97+ }
98+ }
99+
100+ Button {
101+ id: buttonUnlock
102+ objectName: "buttonUnlockSim"
103+ visible: menu.locked
104+
105+ text: i18n.tr("Unlock SIM")
106+ Layout.preferredWidth: implicitWidth + units.gu(5)
107+
108+ onTriggered: menu.unlock()
109+ }
110+ }
111+}
qml/Panel/Indicators/RoamingIndication.qmlnew file+40
@@ -0,0 +1,40 @@
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 Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtQuick.Layouts 1.1
19+import Ubuntu.Components 0.1
20+
21+RowLayout {
22+ spacing: units.gu(0.5)
23+ Label {
24+ id: labelRoaming
25+ elide: Text.ElideRight
26+ fontSize: "x-small"
27+ text: i18n.tr("Roaming")
28+ opacity: 0.6
29+ }
30+
31+ Icon {
32+ id: iconRoaming
33+ color: Theme.palette.selected.backgroundText
34+
35+ Layout.preferredHeight: parent.height
36+ Layout.preferredWidth: Layout.preferredHeight
37+
38+ name: "network-cellular-roaming"
39+ }
40+}
qml/ScopeTool.qml+2−11
@@ -17,6 +17,7 @@
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Ubuntu.Components.Popups 0.1
20+import Ubuntu.Thumbnailer 0.1 // Register support for image://thumbnailer/ and image://albumart/
2021import Utils 0.1
2122import Unity 0.2
2223import "Components"
@@ -45,16 +46,6 @@ Rectangle {
4546 signal searchClicked
4647 }
4748
48− SortFilterProxyModel {
49− id: filteredScopes
50− model: Scopes {
51− id: scopes
52− }
53− dynamicSortFilter: true
54−
55− filterRole: Scopes.RoleVisible
56− filterRegExp: RegExp("^true$")
57− }
5849
5950 Rectangle {
6051 anchors.fill: dashContent
@@ -72,8 +63,8 @@ Rectangle {
7263 DashContent {
7364 id: dashContent
7465
75− model: filteredScopes
7666 property var scope: scopes.getScope(currentIndex)
67+ scopes: Scopes { }
7768
7869 anchors {
7970 top: parent.top
qml/Shell.qml+128−469
@@ -19,22 +19,23 @@ import AccountsService 0.1
1919import GSettings 1.0
2020import Unity.Application 0.1
2121import Ubuntu.Components 0.1
22−import Ubuntu.Components.Popups 0.1
2322import Ubuntu.Gestures 0.1
2423import Unity.Launcher 0.1
24+import Utils 0.1
2525import LightDM 0.1 as LightDM
2626import Powerd 0.1
2727import SessionBroadcast 0.1
28−import "Dash"
2928import "Greeter"
3029import "Launcher"
3130import "Panel"
3231import "Components"
3332import "Notifications"
33+import "Stages"
3434import Unity.Notifications 1.0 as NotificationBackend
3535import Unity.Session 0.1
36+import Unity.DashCommunicator 0.1
3637
37−FocusScope {
38+Item {
3839 id: shell
3940
4041 // this is only here to select the width / height of the window if not running fullscreen
@@ -47,22 +48,15 @@ FocusScope {
4748 property url background
4849 readonly property real panelHeight: panel.panelHeight
4950
50− property bool dashShown: dash.shown
51−
5251 property bool sideStageEnabled: shell.width >= units.gu(100)
5352 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
5453
5554 function activateApplication(appId) {
5655 if (ApplicationManager.findApplication(appId)) {
5756 ApplicationManager.requestFocusApplication(appId);
58− stages.show(true);
59− if (stages.locked && ApplicationManager.focusedApplicationId == appId) {
60− applicationsDisplayLoader.item.select(appId);
61− }
6257 } else {
6358 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
6459 ApplicationManager.startApplication(appId, execFlags);
65− stages.show(false);
6660 }
6761 }
6862
@@ -89,105 +83,31 @@ FocusScope {
8983 id: volumeControl
9084 }
9185
92− Keys.onVolumeUpPressed: volumeControl.volumeUp()
93− Keys.onVolumeDownPressed: volumeControl.volumeDown()
94−
95− Item {
96− id: underlayClipper
97− anchors.fill: parent
98− anchors.rightMargin: stages.overlayWidth
99− clip: stages.overlayMode && !stages.painting
100−
101− InputFilterArea {
102− anchors.fill: parent
103− blockInput: parent.clip
104− }
105−
106− Item {
107− id: underlay
108− objectName: "underlay"
109− anchors.fill: parent
110− anchors.rightMargin: -parent.anchors.rightMargin
111−
112− // Whether the underlay is fully covered by opaque UI elements.
113− property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicators.width
114−
115− // Whether the user should see the topmost application surface (if there's one at all).
116− readonly property bool applicationSurfaceShouldBeSeen: stages.shown && !stages.painting && !stages.overlayMode
117−
118− // NB! Application surfaces are stacked behind the shell one. So they can only be seen by the user
119− // through the translucent parts of the shell surface.
120− visible: !fullyCovered && !applicationSurfaceShouldBeSeen
121−
122− Rectangle {
123− anchors.fill: parent
124− color: "black"
125− opacity: dash.disappearingAnimationProgress
126− }
127−
128− Image {
129− anchors.fill: dash
130− source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png"
131− fillMode: Image.PreserveAspectCrop
132− horizontalAlignment: Image.AlignRight
133− verticalAlignment: Image.AlignTop
134− }
135−
136− Dash {
137− id: dash
138− objectName: "dash"
139−
140− available: !LightDM.Greeter.active
141− hides: [stages, launcher, panel.indicators]
142− shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0
143− enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
144−
145− anchors {
146− fill: parent
147− topMargin: panel.panelHeight
148− }
149−
150− contentScale: 1.0 - 0.2 * disappearingAnimationProgress
151− opacity: 1.0 - disappearingAnimationProgress
152− property real disappearingAnimationProgress: {
153− if (stages.overlayMode) {
154− return 0;
155− } else {
156− return stages.showProgress
157− }
158− }
159−
160− // FIXME: only necessary because stages.showProgress is not animated
161− Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
162− }
163− }
86+ DashCommunicator {
87+ id: dash
88+ objectName: "dashCommunicator"
16489 }
16590
166− EdgeDragArea {
167− id: stagesDragHandle
168− direction: Direction.Leftwards
169−
170− anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
171− width: shell.edgeSize
91+ WindowKeysFilter {
92+ // Handle but do not filter out volume keys
93+ Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }
94+ Keys.onVolumeDownPressed: { volumeControl.volumeDown(); event.accepted = false; }
17295
173− property real progress: stages.width
174−
175− onTouchXChanged: {
176− if (status == DirectionalDragArea.Recognized) {
177− if (ApplicationManager.count == 0) {
178− progress = Math.max(stages.width - stagesDragHandle.width + touchX, stages.width * .3)
179− } else {
180− progress = stages.width - stagesDragHandle.width + touchX
181− }
96+ Keys.onPressed: {
97+ if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
98+ dialogs.onPowerKeyPressed();
99+ event.accepted = true;
100+ } else {
101+ event.accepted = false;
182102 }
183103 }
184104
185− onDraggingChanged: {
186− if (!dragging) {
187− if (ApplicationManager.count > 0 && progress < stages.width - units.gu(10)) {
188− stages.show(true)
189− }
190− stagesDragHandle.progress = stages.width;
105+ Keys.onReleased: {
106+ if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
107+ dialogs.onPowerKeyReleased();
108+ event.accepted = true;
109+ } else {
110+ event.accepted = false;
191111 }
192112 }
193113 }
@@ -197,254 +117,36 @@ FocusScope {
197117 objectName: "stages"
198118 width: parent.width
199119 height: parent.height
200−
201− x: {
202− if (shown) {
203− if (overlayMode || locked || greeter.fakeActiveForApp !== "") {
204− return 0;
205− }
206− return launcher.progress
207− } else {
208− return stagesDragHandle.progress
209− }
210− }
211−
212− Behavior on x { SmoothedAnimation { velocity: 600; duration: UbuntuAnimation.FastDuration } }
213−
214− property bool shown: false
215−
216− property real showProgress: overlayMode ? 0 : MathUtils.clamp(1 - x / shell.width, 0, 1)
217−
218− property bool fullyShown: x == 0
219− property bool fullyHidden: x == width
220−
221− property bool painting: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.painting : false
222− property bool fullscreen: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.fullscreen : false
223− property bool overlayMode: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.overlayMode : false
224− property int overlayWidth: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.overlayWidth : false
225− property bool locked: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.locked : false
226−
227− function show(focusApp) {
228− shown = true;
229− panel.indicators.hide();
230− edgeDemo.stopDemo();
231− greeter.hide();
232− if (!ApplicationManager.focusedApplicationId && ApplicationManager.count > 0 && focusApp) {
233− ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
234− }
235− }
236−
237− function hide() {
238− shown = false;
239− if (ApplicationManager.focusedApplicationId) {
240− ApplicationManager.unfocusCurrentApplication();
241− }
242− }
120+ visible: !ApplicationManager.empty
243121
244122 Connections {
245123 target: ApplicationManager
246−
247124 onFocusRequested: {
248125 if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== appId) {
249126 lockscreen.show();
250127 }
251128 greeter.hide();
252− stages.show(true);
253129 }
254130
255131 onFocusedApplicationIdChanged: {
256132 if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== ApplicationManager.focusedApplicationId) {
257133 lockscreen.show();
258134 }
259− if (ApplicationManager.focusedApplicationId.length > 0) {
260− stages.show(false);
261− } else {
262− if (!stages.overlayMode) {
263− stages.hide();
264− }
265− }
135+ panel.indicators.hide();
266136 }
267137
268138 onApplicationAdded: {
269− stages.show(false);
270− }
271−
272− onApplicationRemoved: {
273− if (ApplicationManager.focusedApplicationId.length == 0) {
274− stages.hide();
275− }
276− }
277− }
278−
279− property bool dialogShown: false
280−
281− Component {
282− id: logoutDialog
283− Dialog {
284− id: dialogueLogout
285− title: "Logout"
286− text: "Are you sure that you want to logout?"
287− Button {
288− text: "Cancel"
289− onClicked: {
290− PopupUtils.close(dialogueLogout);
291− stages.dialogShown = false;
292− }
293− }
294− Button {
295− text: "Yes"
296− onClicked: {
297− DBusUnitySessionService.Logout();
298− PopupUtils.close(dialogueLogout);
299− stages.dialogShown = false;
300− }
301− }
302− }
303− }
304−
305− Component {
306− id: shutdownDialog
307− Dialog {
308− id: dialogueShutdown
309− title: "Shutdown"
310− text: "Are you sure that you want to shutdown?"
311− Button {
312− text: "Cancel"
313− onClicked: {
314− PopupUtils.close(dialogueShutdown);
315− stages.dialogShown = false;
316− }
317− }
318− Button {
319− text: "Yes"
320− onClicked: {
321− dBusUnitySessionServiceConnection.closeAllApps();
322− DBusUnitySessionService.Shutdown();
323− PopupUtils.close(dialogueShutdown);
324− stages.dialogShown = false;
325− }
326− }
327− }
328− }
329−
330− Component {
331− id: rebootDialog
332− Dialog {
333− id: dialogueReboot
334− title: "Reboot"
335− text: "Are you sure that you want to reboot?"
336− Button {
337− text: "Cancel"
338− onClicked: {
339− PopupUtils.close(dialogueReboot)
340− stages.dialogShown = false;
341− }
342− }
343− Button {
344− text: "Yes"
345− onClicked: {
346− dBusUnitySessionServiceConnection.closeAllApps();
347− DBusUnitySessionService.Reboot();
348− PopupUtils.close(dialogueReboot);
349− stages.dialogShown = false;
350− }
351− }
352− }
353− }
354−
355− Component {
356− id: powerDialog
357− Dialog {
358− id: dialoguePower
359− title: "Power"
360− text: i18n.tr("Are you sure you would like to turn power off?")
361− Button {
362− text: i18n.tr("Power off")
363− onClicked: {
364− dBusUnitySessionServiceConnection.closeAllApps();
365− PopupUtils.close(dialoguePower);
366− stages.dialogShown = false;
367− shutdownFadeOutRectangle.enabled = true;
368− shutdownFadeOutRectangle.visible = true;
369− shutdownFadeOut.start();
370− }
371− }
372− Button {
373− text: i18n.tr("Restart")
374− onClicked: {
375− dBusUnitySessionServiceConnection.closeAllApps();
376− DBusUnitySessionService.Reboot();
377− PopupUtils.close(dialoguePower);
378− stages.dialogShown = false;
379− }
380− }
381− Button {
382− text: i18n.tr("Cancel")
383− onClicked: {
384− PopupUtils.close(dialoguePower);
385− stages.dialogShown = false;
386− }
387− }
388− }
389− }
390−
391− function showPowerDialog() {
392− if (!stages.dialogShown) {
393− stages.dialogShown = true;
394− PopupUtils.open(powerDialog);
395− }
396− }
397−
398− Connections {
399− id: dBusUnitySessionServiceConnection
400− objectName: "dBusUnitySessionServiceConnection"
401− target: DBusUnitySessionService
402−
403− function closeAllApps() {
404− while (true) {
405− var app = ApplicationManager.get(0);
406− if (app === null) {
407− break;
408− }
409− ApplicationManager.stopApplication(app.appId);
410− }
411− }
412−
413− onLogoutRequested: {
414− // Display a dialog to ask the user to confirm.
415− if (!stages.dialogShown) {
416− stages.dialogShown = true;
417− PopupUtils.open(logoutDialog);
418− }
419− }
420−
421− onShutdownRequested: {
422− // Display a dialog to ask the user to confirm.
423− if (!stages.dialogShown) {
424− stages.dialogShown = true;
425− PopupUtils.open(shutdownDialog);
426− }
427− }
428−
429− onRebootRequested: {
430− // Display a dialog to ask the user to confirm.
431− if (!stages.dialogShown) {
432− stages.dialogShown = true;
433− PopupUtils.open(rebootDialog);
139+ if (greeter.shown && appId != "unity8-dash") {
140+ greeter.hide();
434141 }
435142 }
436−
437− onLogoutReady: {
438− closeAllApps();
439− Qt.quit();
440− }
441143 }
442144
443145 Loader {
444146 id: applicationsDisplayLoader
445147 anchors.fill: parent
446148
447− source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
149+ source: shell.sideStageEnabled ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
448150
449151 Binding {
450152 target: applicationsDisplayLoader.item
@@ -453,23 +155,56 @@ FocusScope {
453155 }
454156 Binding {
455157 target: applicationsDisplayLoader.item
456− property: "moving"
457− value: !stages.fullyShown
158+ property: "dragAreaWidth"
159+ value: shell.edgeSize
458160 }
459161 Binding {
460162 target: applicationsDisplayLoader.item
461− property: "shown"
462− value: stages.shown
163+ property: "maximizedAppTopMargin"
164+ // Not just using panel.panelHeight as that changes depending on the focused app.
165+ value: panel.indicators.panelHeight
463166 }
464167 Binding {
465168 target: applicationsDisplayLoader.item
466− property: "dragAreaWidth"
467− value: shell.edgeSize
169+ property: "interactive"
170+ value: edgeDemo.stagesEnabled && !greeter.shown && !lockscreen.shown && panel.indicators.fullyClosed && launcher.progress == 0
468171 }
469172 Binding {
470173 target: applicationsDisplayLoader.item
471174 property: "spreadEnabled"
472− value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
175+ value: edgeDemo.stagesEnabled && greeter.fakeActiveForApp === "" // to support emergency dialer hack
176+ }
177+ Binding {
178+ target: applicationsDisplayLoader.item
179+ property: "inverseProgress"
180+ value: launcher.progress
181+ }
182+ }
183+ }
184+
185+ InputMethod {
186+ id: inputMethod
187+ objectName: "inputMethod"
188+ anchors { fill: parent; topMargin: panel.panelHeight }
189+ z: notifications.useModal || panel.indicators.shown ? overlay.z + 1 : overlay.z - 1
190+ }
191+
192+ Connections {
193+ target: SurfaceManager
194+ onSurfaceCreated: {
195+ if (surface.type == MirSurfaceItem.InputMethod) {
196+ inputMethod.surface = surface;
197+ }
198+ }
199+
200+ onSurfaceDestroyed: {
201+ if (inputMethod.surface == surface) {
202+ inputMethod.surface = null;
203+ surface.parent = null;
204+ }
205+ if (!surface.parent) {
206+ // there's no one displaying it. delete it right away
207+ surface.release();
473208 }
474209 }
475210 }
@@ -486,10 +221,11 @@ FocusScope {
486221 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
487222 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
488223 y: panel.panelHeight
489− x: required ? 0 : - width
224+ visible: required
490225 width: parent.width
491226 height: parent.height - panel.panelHeight
492227 background: shell.background
228+ alphaNumeric: AccountsService.passwordDisplayHint === AccountsService.Keyboard
493229 minPinLength: 4
494230 maxPinLength: 4
495231
@@ -504,7 +240,7 @@ FocusScope {
504240 onShownChanged: if (shown) greeter.fakeActiveForApp = ""
505241
506242 Component.onCompleted: {
507− if (LightDM.Users.count == 1) {
243+ if (greeter.narrowMode) {
508244 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
509245 }
510246 }
@@ -516,14 +252,17 @@ FocusScope {
516252 onShowGreeter: greeter.show()
517253
518254 onShowPrompt: {
519− if (LightDM.Users.count == 1) {
520− // TODO: There's no better way for now to determine if its a PIN or a passphrase.
521− if (text == "PIN") {
522− lockscreen.alphaNumeric = false
523− } else {
524− lockscreen.alphaNumeric = true
525− }
526− lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text);
255+ if (greeter.narrowMode) {
256+ lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text.toLowerCase());
257+ lockscreen.show();
258+ }
259+ }
260+
261+ onPromptlessChanged: {
262+ if (LightDM.Greeter.promptless) {
263+ lockscreen.hide()
264+ } else {
265+ lockscreen.reset();
527266 lockscreen.show();
528267 }
529268 }
@@ -537,6 +276,9 @@ FocusScope {
537276 greeter.login();
538277 } else {
539278 lockscreen.clear(true);
279+ if (greeter.narrowMode) {
280+ LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
281+ }
540282 }
541283 }
542284 }
@@ -566,6 +308,7 @@ FocusScope {
566308 StandardAnimation {}
567309 }
568310
311+ property bool fullyShown: showProgress === 1.0
569312 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
570313 onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
571314
@@ -590,25 +333,24 @@ FocusScope {
590333
591334 function login() {
592335 enabled = false;
593− LightDM.Greeter.startSessionSync();
594− sessionStarted();
595− greeter.hide();
596− lockscreen.hide();
597− launcher.hide();
336+ if (LightDM.Greeter.startSessionSync()) {
337+ sessionStarted();
338+ greeter.hide();
339+ lockscreen.hide();
340+ launcher.hide();
341+ }
598342 enabled = true;
599343 }
600344
601345 onShownChanged: {
602346 if (shown) {
603− lockscreen.reset();
604− if (!LightDM.Greeter.promptless) {
605− lockscreen.show();
606− }
607− // If there is only one user, we start authenticating with that one here.
608− // If there are more users, the Greeter will handle that
609− if (LightDM.Users.count == 1) {
347+ if (greeter.narrowMode) {
610348 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
611349 }
350+ if (!LightDM.Greeter.promptless) {
351+ lockscreen.reset();
352+ lockscreen.show();
353+ }
612354 greeter.fakeActiveForApp = "";
613355 greeter.forceActiveFocus();
614356 }
@@ -632,12 +374,6 @@ FocusScope {
632374 }
633375 }
634376
635− InputFilterArea {
636− anchors.fill: parent
637− blockInput: ApplicationManager.focusedApplicationId.length === 0 || greeter.shown || lockscreen.shown || launcher.shown
638− || panel.indicators.shown
639− }
640−
641377 Connections {
642378 id: powerConnection
643379 target: Powerd
@@ -645,7 +381,7 @@ FocusScope {
645381 onDisplayPowerStateChange: {
646382 // We ignore any display-off signals when the proximity sensor
647383 // is active. This usually indicates something like a phone call.
648− if (status == Powerd.Off && reason != Powerd.Proximity) {
384+ if (status == Powerd.Off && reason != Powerd.Proximity && !edgeDemo.running) {
649385 greeter.showNow();
650386 }
651387
@@ -672,29 +408,25 @@ FocusScope {
672408
673409 var animate = !LightDM.Greeter.active && !stages.shown
674410 dash.setCurrentScope("clickscope", animate, false)
675− stages.hide()
411+ ApplicationManager.requestFocusApplication("unity8-dash")
676412 }
677413
678414 function showDash() {
679415 if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
680416 return;
681417 }
682−
683− if (stages.shown && !stages.overlayMode && !stages.locked) {
684− stages.hide();
685− launcher.fadeOut();
686− } else {
687− launcher.switchToNextState("visible");
688− }
689−
690418 if (greeter.shown) {
691419 greeter.hideRight();
692420 launcher.fadeOut();
693421 }
422+
423+ ApplicationManager.requestFocusApplication("unity8-dash")
424+ launcher.fadeOut();
694425 }
695426
696427 Item {
697428 id: overlay
429+ z: 10
698430
699431 anchors.fill: parent
700432
@@ -709,29 +441,13 @@ FocusScope {
709441 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
710442 panelHeight: units.gu(3)
711443 }
712− property string focusedAppId: ApplicationManager.focusedApplicationId
713− property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
714− fullscreenMode: (focusedApplication && stages.fullscreen && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""
715444
716− InputFilterArea {
717− anchors {
718− top: parent.top
719− left: parent.left
720− right: parent.right
721− }
722− height: (panel.fullscreenMode) ? shell.edgeSize : panel.panelHeight
723− blockInput: true
724− }
725− }
445+ property bool topmostApplicationIsFullscreen:
446+ ApplicationManager.focusedApplicationId &&
447+ ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
726448
727− InputFilterArea {
728− blockInput: launcher.shown
729− anchors {
730− top: parent.top
731− bottom: parent.bottom
732− left: parent.left
733− }
734− width: launcher.width
449+ fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
450+ || greeter.fakeActiveForApp !== ""
735451 }
736452
737453 Launcher {
@@ -748,7 +464,11 @@ FocusScope {
748464
749465 onShowDashHome: showHome()
750466 onDash: showDash()
751− onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
467+ onDashSwipeChanged: {
468+ if (dashSwipe && ApplicationManager.focusedApplicationId !== "unity8-dash") {
469+ dash.setCurrentScope("clickscope", false, true)
470+ }
471+ }
752472 onLauncherApplicationSelected: {
753473 if (greeter.fakeActiveForApp !== "") {
754474 lockscreen.show()
@@ -774,11 +494,6 @@ FocusScope {
774494 MouseArea {
775495 anchors.fill: parent
776496 }
777−
778− InputFilterArea {
779− anchors.fill: parent
780− blockInput: modalNotificationBackground.visible
781− }
782497 }
783498
784499 Notifications {
@@ -804,62 +519,31 @@ FocusScope {
804519 PropertyChanges { target: notifications; width: units.gu(38) }
805520 }
806521 ]
807−
808− InputFilterArea {
809− anchors { left: parent.left; right: parent.right }
810− height: parent.contentHeight
811− blockInput: height > 0
812− }
813522 }
814523 }
815524
816− focus: true
817− onFocusChanged: if (!focus) forceActiveFocus();
818−
819− InputFilterArea {
820− anchors {
821− top: parent.top
822− bottom: parent.bottom
823− left: parent.left
824− }
825− width: shell.edgeSize
826− blockInput: true
827− }
828−
829− InputFilterArea {
830− anchors {
831− top: parent.top
832− bottom: parent.bottom
833− right: parent.right
834− }
835− width: shell.edgeSize
836− blockInput: true
837− }
838−
839525 Binding {
840526 target: i18n
841527 property: "domain"
842528 value: "unity8"
843529 }
844530
845− OSKController {
846− anchors.topMargin: panel.panelHeight
847− anchors.fill: parent // as needs to know the geometry of the shell
848− }
849−
850− //FIXME: This should be handled in the input stack, keyboard shouldnt propagate
851− MouseArea {
852− anchors.bottom: parent.bottom
853− anchors.left: parent.left
854− anchors.right: parent.right
855− height: ApplicationManager.keyboardVisible ? ApplicationManager.keyboardHeight : 0
856−
857− enabled: ApplicationManager.keyboardVisible
531+ Dialogs {
532+ id: dialogs
533+ anchors.fill: parent
534+ z: overlay.z + 10
535+ onPowerOffClicked: {
536+ shutdownFadeOutRectangle.enabled = true;
537+ shutdownFadeOutRectangle.visible = true;
538+ shutdownFadeOut.start();
539+ }
858540 }
859541
860542 Label {
543+ id: alphaDisclaimerLabel
861544 anchors.centerIn: parent
862545 visible: ApplicationManager.fake ? ApplicationManager.fake : false
546+ z: dialogs.z + 10
863547 text: "EARLY ALPHA\nNOT READY FOR USE"
864548 color: "lightgrey"
865549 opacity: 0.2
@@ -873,11 +557,11 @@ FocusScope {
873557
874558 EdgeDemo {
875559 id: edgeDemo
560+ z: alphaDisclaimerLabel.z + 10
876561 greeter: greeter
877562 launcher: launcher
878− dash: dash
879563 indicators: panel.indicators
880− underlay: underlay
564+ stages: stages
881565 }
882566
883567 Connections {
@@ -885,35 +569,9 @@ FocusScope {
885569 onShowHome: showHome()
886570 }
887571
888− Keys.onPressed: {
889− if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
890− if (!powerKeyTimer.running) {
891− powerKeyTimer.start();
892− }
893− event.accepted = true;
894− }
895− }
896−
897− Keys.onReleased: {
898− if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
899− powerKeyTimer.stop();
900− event.accepted = true;
901− }
902− }
903−
904− Timer {
905− id: powerKeyTimer
906− interval: 2000
907− repeat: false
908− triggeredOnStart: false
909−
910− onTriggered: {
911− stages.showPowerDialog();
912− }
913− }
914−
915572 Rectangle {
916573 id: shutdownFadeOutRectangle
574+ z: edgeDemo.z + 10
917575 enabled: false
918576 visible: false
919577 color: "black"
@@ -930,4 +588,5 @@ FocusScope {
930588 }
931589 }
932590 }
591+
933592}
qml/Stages/Animations/BaseSurfaceAnimation.qmlnew file+93
@@ -0,0 +1,93 @@
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+import QtQuick 2.0
18+
19+/* This is the base case for surface animations, used when adding/removing * child surfaces.
20+ * The class is meant to be overridden and changes/animations provided for state changes.
21+ * NB. It is important to release the surface at the end of the "out" animation.
22+ *
23+ * Example - Simple fade in/out
24+ *
25+ * BaseSurfaceAnimation {
26+ * outChanges: [ PropertyChanges { target: animation.surface; opacity: 0.0 } ]
27+ * outAnimations: [
28+ SequentialAnimation {
29+ * NumberAnimation { target: animation.surface; property: "opacity"; duration: 300 }
30+ * ScriptAction { script: { if (animation.parent.removing) animation.surface.release(); } }
31+ * }
32+ * ]
33+ *
34+ * inChanges: [ PropertyChanges { target: animation.surface; opacity: 1.0 } ]
35+ * inAnimations: [ NumberAnimation { target: animation.surface; property: "opacity"; duration: 300 } ]
36+ * }
37+ */
38+Item {
39+ id: base
40+ property Item surface: null
41+
42+ // changes applied when state changes to "in"
43+ property list<QtObject> outChanges
44+ // transition animations when changing state to "in"
45+ property list<QtObject> outAnimations
46+
47+ // changes applied when state changes to "out"
48+ property list<QtObject> inChanges
49+ // transition animations when changing state to "out"
50+ property list<QtObject> inAnimations
51+
52+ function start() {
53+ // "prep" state forces outChanges without transition animations.
54+ state = "prep"
55+ state = "in";
56+ }
57+ function end() {
58+ state = "out";
59+ }
60+
61+ states: [
62+ State {
63+ name: "baseAnimation"
64+ PropertyChanges { target: base.surface; anchors.fill: undefined }
65+ },
66+
67+ State {
68+ name: "prep"
69+ extend: "baseAnimation"
70+ changes: outChanges
71+ },
72+ State {
73+ name: "out"
74+ extend: "prep"
75+ },
76+ State {
77+ name: "in"
78+ extend: "baseAnimation"
79+ changes: inChanges
80+ }
81+ ]
82+
83+ transitions: [
84+ Transition {
85+ to: "out"
86+ animations: outAnimations
87+ },
88+ Transition {
89+ to: "in"
90+ animations: inAnimations
91+ }
92+ ]
93+}
qml/Stages/Animations/DarkenAndFadeInAnimation.qmlnew file+48
@@ -0,0 +1,48 @@
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+import QtQuick 2.0
18+import Ubuntu.Components 1.1
19+
20+BaseSurfaceAnimation {
21+ id: animation
22+
23+ property Rectangle darkenItem: Rectangle {
24+ parent: animation.surface.parent
25+ anchors.fill: parent
26+ color: Qt.rgba(0,0,0,0.0)
27+ }
28+
29+ outChanges: [ PropertyChanges { target: animation.surface; opacity: 0.0 } ]
30+ outAnimations: [
31+ SequentialAnimation {
32+ UbuntuNumberAnimation { target: animation.surface; property: "opacity"; duration: UbuntuAnimation.FastDuration }
33+ ColorAnimation { target: darkenItem; duration: UbuntuAnimation.FastDuration }
34+ ScriptAction { script: { if (animation.parent.removing) animation.surface.release(); } }
35+ }
36+ ]
37+
38+ inChanges: [
39+ PropertyChanges { target: darkenItem; color: Qt.rgba(0,0,0,0.7) },
40+ PropertyChanges { target: animation.surface; opacity: 1.0 }
41+ ]
42+ inAnimations: [
43+ SequentialAnimation {
44+ ColorAnimation { target: darkenItem; duration: UbuntuAnimation.FastDuration }
45+ UbuntuNumberAnimation { target: animation.surface; property: "opacity"; duration: UbuntuAnimation.FastDuration }
46+ }
47+ ]
48+}
qml/Stages/Animations/SwipeFromBottomAnimation.qmlnew file+48
@@ -0,0 +1,48 @@
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+import QtQuick 2.0
18+
19+BaseSurfaceAnimation {
20+ id: animation
21+
22+ outChanges: [ AnchorChanges { target: animation.surface; anchors.top: animation.parent.bottom } ]
23+ outAnimations: [
24+ SequentialAnimation {
25+ PropertyAction { target: animation.parent; property: "clip"; value: true }
26+ AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
27+ PropertyAction { target: animation.surface; property: "visible"; value: !animation.parent.removing }
28+ PropertyAction { target: animation.parent; property: "clip"; value: false }
29+ ScriptAction { script: { if (animation.parent.removing) animation.surface.release(); } }
30+ }
31+ ]
32+
33+ inChanges: [
34+ AnchorChanges {
35+ target: animation.surface;
36+ anchors.top: animation.parent.top
37+ anchors.right: undefined
38+ anchors.bottom: undefined
39+ anchors.left: undefined
40+ } ]
41+ inAnimations: [
42+ SequentialAnimation {
43+ PropertyAction { target: animation.parent; property: "clip"; value: true }
44+ AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
45+ PropertyAction { target: animation.parent; property: "clip"; value: false }
46+ }
47+ ]
48+}
qml/Stages/Animations/SwipeUpAnimation.qmlnew file+49
@@ -0,0 +1,49 @@
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+import QtQuick 2.0
18+
19+BaseSurfaceAnimation {
20+ id: animation
21+
22+ outAnimations: [
23+ SequentialAnimation {
24+ PropertyAction { target: animation.parent; property: "clip"; value: true }
25+ PropertyAction { target: animation.surface; property: "visible"; value: true }
26+ AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
27+ PropertyAction { target: animation.parent; property: "clip"; value: false }
28+ ScriptAction { script: { if (animation.parent.removing) animation.surface.release(); } }
29+ }
30+ ]
31+
32+ inChanges: [
33+ AnchorChanges {
34+ target: animation.surface;
35+ anchors.top: undefined
36+ anchors.right: undefined
37+ anchors.bottom: animation.parent.top
38+ anchors.left: undefined
39+ }
40+ ]
41+ inAnimations: [
42+ SequentialAnimation {
43+ PropertyAction { target: animation.parent; property: "clip"; value: true }
44+ AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
45+ PropertyAction { target: animation.surface; property: "visible"; value: false}
46+ PropertyAction { target: animation.parent; property: "clip"; value: false }
47+ }
48+ ]
49+}
qml/Stages/PhoneStage.qml+219−278
@@ -18,96 +18,68 @@ import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Ubuntu.Gestures 0.1
2020import Unity.Application 0.1
21−import LightDM 0.1 as LightDM
2221import Utils 0.1
2322import "../Components"
2423
25−Item {
24+Rectangle {
2625 id: root
2726
2827 // Controls to be set from outside
29− property bool shown: false
30− property bool moving: false
3128 property int dragAreaWidth
29+ property real maximizedAppTopMargin
30+ property bool interactive
31+ property bool spreadEnabled: true // If false, animations and right edge will be disabled
32+ property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
3233
33− // State information propagated to the outside
34− readonly property bool painting: mainScreenshotImage.visible || fadeInScreenshotImage.visible || appSplash.visible || spreadView.visible
35− property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
36− property bool locked: spreadView.visible
37− property bool spreadEnabled: true
38−
39− // Not used for PhoneStage, only useful for SideStage and similar
40− property bool overlayMode: false
41− property int overlayWidth: 0
34+ color: "black"
4235
4336 function select(appId) {
44− spreadView.snapTo(priv.indexOf(appId))
37+ spreadView.snapTo(priv.indexOf(appId));
4538 }
4639
47− onMovingChanged: {
48− if (moving) {
49− if (ApplicationManager.focusedApplicationId) {
50− priv.requestNewScreenshot();
51− } else {
52− mainScreenshotImage.anchors.leftMargin = 0;
53− mainScreenshotImage.source = ApplicationManager.get(0).screenshot;
54− mainScreenshotImage.visible = true;
40+ onWidthChanged: {
41+ spreadView.selectedIndex = -1;
42+ spreadView.phase = 0;
43+ spreadView.contentX = -spreadView.shift;
44+ }
45+
46+ onInverseProgressChanged: {
47+ if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
48+ // left edge drag released. Minimum distance is given by design.
49+ if (priv.oldInverseProgress > units.gu(22)) {
50+ ApplicationManager.focusApplication("unity8-dash");
5551 }
56− } else {
57− mainScreenshotImage.visible = false;
5852 }
53+ priv.oldInverseProgress = inverseProgress;
5954 }
6055
6156 Connections {
6257 target: ApplicationManager
6358
6459 onFocusRequested: {
65− if (spreadView.visible) {
60+ if (spreadView.phase > 0) {
6661 spreadView.snapTo(priv.indexOf(appId));
6762 } else {
68− priv.switchToApp(appId);
63+ ApplicationManager.focusApplication(appId);
6964 }
7065 }
7166
72− onFocusedApplicationIdChanged: {
73− if (ApplicationManager.focusedApplicationId.length > 0) {
74− if (priv.secondApplicationStarting || priv.applicationStarting) {
75− appSplashTimer.restart();
76− } else {
77− var application = priv.focusedApplication;
78− root.fullscreen = application.fullscreen;
79− mainScreenshotImage.source = application.screenshot;
80− }
67+ onApplicationAdded: {
68+ if (spreadView.phase == 2) {
69+ spreadView.snapTo(ApplicationManager.count - 1);
8170 } else {
82− spreadView.selectedIndex = -1;
8371 spreadView.phase = 0;
8472 spreadView.contentX = -spreadView.shift;
85− }
86− }
87−
88− onApplicationAdded: {
89− if (!priv.focusedApplication) {
90− mainScreenshotImage.source = "";
91− mainScreenshotImage.visible = false;
92− priv.applicationStarting = true;
93− } else {
94− mainScreenshotImage.source = "";
95− priv.newFocusedAppId = appId;
96− priv.secondApplicationStarting = true;
97− priv.requestNewScreenshot();
98− }
99−
100− if (spreadView.visible) {
101− spreadView.snapTo(0);
73+ ApplicationManager.focusApplication(appId);
10274 }
10375 }
10476
10577 onApplicationRemoved: {
106− if (ApplicationManager.count == 0) {
107− mainScreenshotImage.source = ""
108− mainScreenshotImage.visible = false;
109− } else {
110− mainScreenshotImage.source = ApplicationManager.get(0).screenshot;
78+ // Unless we're closing the app ourselves in the spread,
79+ // lets make sure the spread doesn't mess up by the changing app list.
80+ if (spreadView.closingIndex == -1) {
81+ spreadView.phase = 0;
82+ spreadView.contentX = -spreadView.shift;
11183 }
11284 }
11385 }
@@ -117,50 +89,11 @@ Item {
11789
11890 property string focusedAppId: ApplicationManager.focusedApplicationId
11991 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
120− property url focusedScreenshot: focusedApplication ? focusedApplication.screenshot : ""
121−
122− property bool waitingForScreenshot: false
123−
124− property bool applicationStarting: false
125− property bool secondApplicationStarting: false
126−
127− property string newFocusedAppId
128−
129− onFocusedScreenshotChanged: {
130− if (root.moving && priv.waitingForScreenshot) {
131− mainScreenshotImage.anchors.leftMargin = 0;
132− mainScreenshotImage.source = priv.focusedScreenshot
133− mainScreenshotImage.visible = true;
134− } else if (priv.secondApplicationStarting && priv.waitingForScreenshot) {
135− applicationSwitchingAnimation.start();
136− if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
137− // When greeter is up, no fancy animations, since user may
138− // glimpse an app they shouldn't
139− applicationSwitchingAnimation.complete();
140− }
141− }
142− waitingForScreenshot = false;
143− }
92+ property var focusedAppDelegate: null
14493
145− function requestNewScreenshot() {
146− waitingForScreenshot = true;
147− ApplicationManager.updateScreenshot(focusedAppId);
148− }
94+ property real oldInverseProgress: 0
14995
150− function switchToApp(appId) {
151− if (priv.focusedAppId) {
152− priv.newFocusedAppId = appId;
153− root.fullscreen = ApplicationManager.findApplication(appId).fullscreen;
154− applicationSwitchingAnimation.start();
155− if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
156− // When greeter is up, no fancy animations, since user may
157− // glimpse an app they shouldn't
158− applicationSwitchingAnimation.complete();
159− }
160− } else {
161− ApplicationManager.focusApplication(appId);
162− }
163− }
96+ onFocusedAppIdChanged: focusedAppDelegate = spreadRepeater.itemAt(0);
16497
16598 function indexOf(appId) {
16699 for (var i = 0; i < ApplicationManager.count; i++) {
@@ -173,185 +106,25 @@ Item {
173106
174107 }
175108
176− // FIXME: the signal connections seems to get lost.
177− Connections {
178− target: priv.focusedApplication
179− onScreenshotChanged: priv.focusedScreenshot = priv.focusedApplication.screenshot
180− }
181− Binding {
182− target: root
183− property: "fullscreen"
184− value: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
185− }
186−
187− Timer {
188− id: appSplashTimer
189− // FIXME: We really need to show something meaningful in the app surface instead of guessing
190− // when it might be ready
191− interval: 500
192− repeat: false
193− onTriggered: {
194− priv.applicationStarting = false;
195− priv.secondApplicationStarting = false;
196− }
197− }
198−
199− SequentialAnimation {
200− id: applicationSwitchingAnimation
201− // setup
202− PropertyAction { target: mainScreenshotImage; property: "anchors.leftMargin"; value: 0 }
203− PropertyAction { target: mainScreenshotImage; property: "source"; value: priv.focusedScreenshot }
204− PropertyAction { targets: [mainScreenshotImage, fadeInScreenshotImage]; property: "visible"; value: true }
205− PropertyAction { target: fadeInScreenshotImage; property: "source"; value: {
206− var newFocusedApp = ApplicationManager.findApplication(priv.newFocusedAppId);
207− return newFocusedApp ? newFocusedApp.screenshot : "" }
208− }
209− PropertyAction { target: fadeInScreenshotImage; property: "opacity"; value: 0 }
210− PropertyAction { target: fadeInScreenshotImage; property: "scale"; value: .8 }
211−
212−
213− // The actual animation
214− ParallelAnimation {
215− UbuntuNumberAnimation { target: mainScreenshotImage; property: "anchors.leftMargin"; to: root.width; duration: UbuntuAnimation.SlowDuration }
216− UbuntuNumberAnimation { target: fadeInScreenshotImage; properties: "opacity,scale"; to: 1; duration: UbuntuAnimation.SlowDuration }
217− }
218−
219− // restore stuff
220− ScriptAction { script: ApplicationManager.focusApplication(priv.newFocusedAppId); }
221− PropertyAction { target: fadeInScreenshotImage; property: "visible"; value: false }
222− PropertyAction { target: mainScreenshotImage; property: "visible"; value: false }
223− }
224−
225− // FIXME: Drop this and make the imageprovider show a splashscreen instead
226− Rectangle {
227− id: appSplash2
228− anchors.fill: parent
229− color: "black"
230− visible: priv.secondApplicationStarting
231− }
232− Image {
233− id: fadeInScreenshotImage
234− anchors { left: parent.left; bottom: parent.bottom }
235− width: parent.width
236− scale: .7
237− visible: false
238− }
239−
240− Rectangle {
241− id: appSplash
242− anchors.fill: parent
243− color: "black"
244− visible: priv.applicationStarting
245−
246− WaitingDots {
247− }
248− }
249− Image {
250− id: mainScreenshotImage
251− anchors { left: parent.left; bottom: parent.bottom }
252− width: parent.width
253− visible: false
254− }
255−
256− EdgeDragArea {
257− id: spreadDragArea
258− direction: Direction.Leftwards
259− enabled: ApplicationManager.count > 1 && spreadView.phase != 2 && root.spreadEnabled
260−
261− anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
262− width: root.dragAreaWidth
263−
264− // Sitting at the right edge of the screen, this EdgeDragArea directly controls the spreadView when
265− // attachedToView is true. When the finger movement passes positionMarker3 we detach it from the
266− // spreadView and make the spreadView snap to positionMarker4.
267− property bool attachedToView: true
268−
269− property var gesturePoints: new Array()
270−
271− onTouchXChanged: {
272− if (!dragging && !priv.waitingForScreenshot) {
273− // Initial touch. Let's update the screenshot and reset the spreadView to the starting position.
274− priv.requestNewScreenshot();
275− spreadView.phase = 0;
276− spreadView.contentX = -spreadView.shift;
277− }
278− if (dragging && attachedToView) {
279− // Gesture recognized. Let's move the spreadView with the finger
280− spreadView.contentX = -touchX - spreadView.shift;
281− }
282− if (attachedToView && spreadView.shiftedContentX >= spreadView.width * spreadView.positionMarker3) {
283− // We passed positionMarker3. Detach from spreadView and snap it.
284− attachedToView = false;
285− spreadView.snap();
286− }
287− gesturePoints.push(touchX);
288− }
289−
290− onStatusChanged: {
291− if (status == DirectionalDragArea.Recognized) {
292− attachedToView = true;
293− }
294− }
295−
296− onDraggingChanged: {
297− if (dragging) {
298− // Gesture recognized. Start recording this gesture
299− gesturePoints = [];
300− return;
301− }
302−
303− // Ok. The user released. Find out if it was a one-way movement.
304− var oneWayFlick = true;
305− var smallestX = spreadDragArea.width;
306− for (var i = 0; i < gesturePoints.length; i++) {
307− if (gesturePoints[i] >= smallestX) {
308− oneWayFlick = false;
309− break;
310− }
311− smallestX = gesturePoints[i];
312− }
313− gesturePoints = [];
314−
315− if (oneWayFlick && spreadView.shiftedContentX > units.gu(2) &&
316− spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
317− // If it was a short one-way movement, do the Alt+Tab switch
318− // no matter if we didn't cross positionMarker1 yet.
319− spreadView.snapTo(1);
320− } else if (!dragging && attachedToView) {
321− // otherwise snap to the closest snap position we can find
322− // (might be back to start, to app 1 or to spread)
323− spreadView.snap();
324− }
325− }
326− }
327−
328− Rectangle {
329− id: coverFlipBackground
330− anchors.fill: parent
331− color: "black"
332− visible: spreadView.visible
333− }
334−
335− InputFilterArea {
336− anchors.fill: root
337− blockInput: spreadView.visible
338− }
339−
340109 Flickable {
341110 id: spreadView
342111 objectName: "spreadView"
343112 anchors.fill: parent
344− visible: spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1 || snapAnimation.running
113+ interactive: (spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1) && draggedIndex == -1
345114 contentWidth: spreadRow.width - shift
346115 contentX: -shift
347116
117+ // This indicates when the spreadView is active. That means, all the animations
118+ // are activated and tiles need to line up for the spread.
119+ readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging
120+
348121 // The flickable needs to fill the screen in order to get touch events all over.
349122 // However, we don't want to the user to be able to scroll back all the way. For
350123 // that, the beginning of the gesture starts with a negative value for contentX
351124 // so the flickable wants to pull it into the view already. "shift" tunes the
352125 // distance where to "lock" the content.
353− property real shift: width / 2
354− property real shiftedContentX: contentX + shift
126+ readonly property real shift: width / 2
127+ readonly property real shiftedContentX: contentX + shift
355128
356129 property int tileDistance: width / 4
357130
@@ -375,6 +148,10 @@ Item {
375148 property int phase: 0
376149
377150 property int selectedIndex: -1
151+ property int draggedIndex: -1
152+ property int closingIndex: -1
153+
154+ property bool focusChanging: false
378155
379156 onShiftedContentXChanged: {
380157 switch (phase) {
@@ -398,9 +175,9 @@ Item {
398175 snapAnimation.targetContentX = -shift;
399176 snapAnimation.start();
400177 } else if (shiftedContentX < positionMarker2 * width) {
401− snapTo(1)
178+ snapTo(1);
402179 } else if (shiftedContentX < positionMarker3 * width) {
403− snapTo(1)
180+ snapTo(1);
404181 } else if (phase < 2){
405182 // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
406183 snapAnimation.targetContentX = width * positionMarker4 + 1 - shift;
@@ -408,12 +185,27 @@ Item {
408185 }
409186 }
410187 function snapTo(index) {
188+ if (ApplicationManager.count <= index) {
189+ // In case we're trying to snap to some non existing app, lets snap back to the first one
190+ index = 0;
191+ }
411192 spreadView.selectedIndex = index;
412− root.fullscreen = ApplicationManager.get(index).fullscreen;
413− snapAnimation.targetContentX = -shift;
193+ // If we're not in full spread mode yet, always unwind to start pos
194+ // otherwise unwind up to progress 0 of the selected index
195+ if (spreadView.phase < 2) {
196+ snapAnimation.targetContentX = -shift;
197+ } else {
198+ snapAnimation.targetContentX = -shift + index * spreadView.tileDistance;
199+ }
414200 snapAnimation.start();
415201 }
416202
203+ // In case the ApplicationManager already holds an app when starting up we're missing animations
204+ // Make sure we end up in the same state
205+ Component.onCompleted: {
206+ spreadView.contentX = -spreadView.shift
207+ }
208+
417209 SequentialAnimation {
418210 id: snapAnimation
419211 property int targetContentX: -spreadView.shift
@@ -429,7 +221,8 @@ Item {
429221 script: {
430222 if (spreadView.selectedIndex >= 0) {
431223 ApplicationManager.focusApplication(ApplicationManager.get(spreadView.selectedIndex).appId);
432− spreadView.selectedIndex = -1
224+
225+ spreadView.selectedIndex = -1;
433226 spreadView.phase = 0;
434227 spreadView.contentX = -spreadView.shift;
435228 }
@@ -443,6 +236,15 @@ Item {
443236 // tileDistance * app count (with a minimum of 3 apps, in order to also allow moving 1 and 2 apps a bit)
444237 // + some constant value (still scales with the screen width) which looks good and somewhat fills the screen
445238 width: Math.max(3, ApplicationManager.count) * spreadView.tileDistance + (spreadView.width - spreadView.tileDistance) * 1.5
239+ Behavior on width {
240+ enabled: spreadView.closingIndex >= 0
241+ UbuntuNumberAnimation {}
242+ }
243+ onWidthChanged: {
244+ if (spreadView.closingIndex >= 0) {
245+ spreadView.contentX = Math.min(spreadView.contentX, width - spreadView.width - spreadView.shift);
246+ }
247+ }
446248
447249 x: spreadView.contentX
448250
@@ -462,18 +264,76 @@ Item {
462264 height: spreadView.height
463265 selected: spreadView.selectedIndex == index
464266 otherSelected: spreadView.selectedIndex >= 0 && !selected
267+ interactive: !spreadView.interactive && spreadView.phase === 0
268+ && spreadView.shiftedContentX === 0 && root.interactive && index === 0
269+ swipeToCloseEnabled: spreadView.interactive
270+ maximizedAppTopMargin: root.maximizedAppTopMargin
271+ dropShadow: spreadView.active ||
272+ priv.focusedAppDelegate.x !== 0
273+
274+ readonly property bool isDash: model.appId == "unity8-dash"
275+
276+ z: isDash && !spreadView.active ? -1 : behavioredIndex
277+
278+ x: {
279+ // focused app is always positioned at 0 except when following left edge drag
280+ if (index == 0) {
281+ if (!isDash && root.inverseProgress > 0) {
282+ return root.inverseProgress;
283+ }
284+ return 0;
285+ }
286+ if (isDash && !spreadView.active && !spreadDragArea.dragging) {
287+ return 0;
288+ }
289+
290+ // Otherwise line up for the spread
291+ return spreadView.width + (index - 1) * spreadView.tileDistance;
292+ }
293+ property real behavioredIndex: index
294+ Behavior on behavioredIndex {
295+ enabled: spreadView.closingIndex >= 0
296+ UbuntuNumberAnimation {
297+ id: appXAnimation
298+ onRunningChanged: {
299+ if (!running) {
300+ spreadView.closingIndex = -1;
301+ }
302+ }
303+ }
304+ }
465305
466− z: index
467− x: index == 0 ? 0 : spreadView.width + (index - 1) * spreadView.tileDistance
306+ Behavior on x {
307+ enabled: root.spreadEnabled &&
308+ !spreadView.active &&
309+ !snapAnimation.running
310+ UbuntuNumberAnimation {
311+ duration: UbuntuAnimation.FastDuration
312+ onRunningChanged: {
313+ if (!running && root.inverseProgress == 0) {
314+ spreadView.focusChanging = false;
315+ }
316+ }
317+ }
318+ }
468319
469320 // Each tile has a different progress value running from 0 to 1.
470− // A progress value of 0 means the tile is at the right edge. 1 means the tile has reched the left edge.
321+ // 0: means the tile is at the right edge.
322+ // 1: means the tile has finished the main animation towards the left edge.
323+ // >1: after the main animation has finished, tiles will continue to move very slowly to the left
471324 progress: {
472− var tileProgress = (spreadView.shiftedContentX - index * spreadView.tileDistance) / spreadView.width;
325+ var tileProgress = (spreadView.shiftedContentX - behavioredIndex * spreadView.tileDistance) / spreadView.width;
473326 // Tile 1 needs to move directly from the beginning...
474− if (index == 1 && spreadView.phase < 2) {
327+ if (behavioredIndex == 1 && spreadView.phase < 2) {
475328 tileProgress += spreadView.tileDistance / spreadView.width;
476329 }
330+ // Limiting progress to ~0 and 1.7 to avoid binding calculations when tiles are not
331+ // visible.
332+ // < 0 : The tile is outside the screen on the right
333+ // > 1.7: The tile is *very* close to the left edge and covered by other tiles now.
334+ // Using 0.0001 to differentiate when a tile should still be visible (==0)
335+ // or we can hide it (< 0)
336+ tileProgress = Math.max(-0.0001, Math.min(1.7, tileProgress));
477337 return tileProgress;
478338 }
479339
@@ -491,9 +351,13 @@ Item {
491351 return progress;
492352 }
493353
354+ // Hiding tiles when their progress is negative or reached the maximum
355+ visible: (progress >= 0 && progress < 1.7) ||
356+ (isDash && priv.focusedAppDelegate.x !== 0)
357+
494358 EasingCurve {
495359 id: snappingCurve
496− type: EasingCurve.OutQuad
360+ type: EasingCurve.Linear
497361 period: 0.05
498362 progress: appDelegate.progress - spreadView.positionMarker1
499363 }
@@ -507,7 +371,84 @@ Item {
507371 }
508372 }
509373 }
374+
375+ onClosed: {
376+ spreadView.draggedIndex = -1;
377+ spreadView.closingIndex = index;
378+ ApplicationManager.stopApplication(ApplicationManager.get(index).appId);
379+ }
380+ }
381+ }
382+ }
383+ }
384+
385+ EdgeDragArea {
386+ id: spreadDragArea
387+ direction: Direction.Leftwards
388+ enabled: spreadView.phase != 2 && root.spreadEnabled
389+
390+ anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
391+ width: root.dragAreaWidth
392+
393+ // Sitting at the right edge of the screen, this EdgeDragArea directly controls the spreadView when
394+ // attachedToView is true. When the finger movement passes positionMarker3 we detach it from the
395+ // spreadView and make the spreadView snap to positionMarker4.
396+ property bool attachedToView: true
397+
398+ property var gesturePoints: new Array()
399+
400+ onTouchXChanged: {
401+ if (!dragging) {
402+ // Initial touch. Let's reset the spreadView to the starting position.
403+ spreadView.phase = 0;
404+ spreadView.contentX = -spreadView.shift;
405+ }
406+ if (dragging && attachedToView) {
407+ // Gesture recognized. Let's move the spreadView with the finger
408+ spreadView.contentX = -touchX + spreadDragArea.width - spreadView.shift;
409+ }
410+ if (attachedToView && spreadView.shiftedContentX >= spreadView.width * spreadView.positionMarker3) {
411+ // We passed positionMarker3. Detach from spreadView and snap it.
412+ attachedToView = false;
413+ spreadView.snap();
414+ }
415+ gesturePoints.push(touchX);
416+ }
417+
418+ onStatusChanged: {
419+ if (status == DirectionalDragArea.Recognized) {
420+ attachedToView = true;
421+ }
422+ }
423+
424+ onDraggingChanged: {
425+ if (dragging) {
426+ // Gesture recognized. Start recording this gesture
427+ gesturePoints = [];
428+ return;
429+ }
430+
431+ // Ok. The user released. Find out if it was a one-way movement.
432+ var oneWayFlick = true;
433+ var smallestX = spreadDragArea.width;
434+ for (var i = 0; i < gesturePoints.length; i++) {
435+ if (gesturePoints[i] >= smallestX) {
436+ oneWayFlick = false;
437+ break;
510438 }
439+ smallestX = gesturePoints[i];
440+ }
441+ gesturePoints = [];
442+
443+ if (oneWayFlick && spreadView.shiftedContentX > units.gu(2) &&
444+ spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
445+ // If it was a short one-way movement, do the Alt+Tab switch
446+ // no matter if we didn't cross positionMarker1 yet.
447+ spreadView.snapTo(1);
448+ } else if (!dragging && attachedToView) {
449+ // otherwise snap to the closest snap position we can find
450+ // (might be back to start, to app 1 or to spread)
451+ spreadView.snap();
511452 }
512453 }
513454 }
qml/Stages/Splash.qmlnew file+68
@@ -0,0 +1,68 @@
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 Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+*/
16+
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import "../Components"
20+
21+Rectangle {
22+ id: root
23+ color: "black"
24+
25+ property string name: ""
26+ property url image: ""
27+
28+ UbuntuShape {
29+ id: iconShape
30+ anchors.horizontalCenter: parent.horizontalCenter
31+ anchors.verticalCenter: parent.verticalCenter
32+ anchors.verticalCenterOffset: -units.gu(4)
33+ width: units.gu(8)
34+ height: units.gu(7.5)
35+
36+ radius: "medium"
37+ borderSource: "none"
38+
39+ image: Image {
40+ id: iconImage
41+ sourceSize.width: iconShape.width
42+ sourceSize.height: iconShape.height
43+ source: root.image
44+ fillMode: Image.PreserveAspectCrop
45+ }
46+ }
47+
48+ Label {
49+ text: root.name
50+ anchors.horizontalCenter: parent.horizontalCenter
51+ anchors.top: iconShape.bottom
52+ anchors.topMargin: units.gu(2)
53+ fontSize: "large"
54+ }
55+
56+ WaitingDots {
57+ visible: parent.visible
58+ anchors.horizontalCenter: parent.horizontalCenter
59+ anchors.bottom: parent.bottom
60+ anchors.bottomMargin: units.gu(12)
61+ }
62+
63+ MouseArea {
64+ anchors.fill: parent
65+ enabled: parent.visible
66+ // absorb all mouse events
67+ }
68+}
qml/Stages/SpreadDelegate.qml+193−23
@@ -17,39 +17,209 @@
1717*/
1818
1919import QtQuick 2.0
20+import Unity.Application 0.1
21+import Ubuntu.Components 1.1
22+import "../Components"
2023
2124Item {
2225 id: root
2326
27+ // to be set from outside
28+ property bool interactive: true
29+ property bool dropShadow: true
30+ property real maximizedAppTopMargin
31+ property alias swipeToCloseEnabled: dragArea.enabled
32+
33+ readonly property bool isFullscreen: surface !== null && surfaceContainer.surface.anchors.topMargin == 0
34+
2435 signal clicked()
36+ signal closed()
37+
38+ SurfaceContainer {
39+ id: surfaceContainer
40+ objectName: "surfaceContainer"
41+ anchors.fill: parent
42+ surface: model.surface
43+ property bool appHasCreatedASurface: false
44+
45+ onSurfaceChanged: {
46+ if (surface) {
47+ if (!appHasCreatedASurface) {
48+ surface.visible = false; // hide until splash screen removed
49+ appHasCreatedASurface = true;
50+ }
51+ }
52+ }
53+
54+ function revealSurface() {
55+ surface.visible = true;
56+ splashLoader.source = "";
57+ }
58+
59+ Binding {
60+ target: surfaceContainer.surface
61+ property: "anchors.topMargin"
62+ value: {
63+ return surfaceContainer.surface.state === MirSurfaceItem.Fullscreen ? 0 : maximizedAppTopMargin;
64+ }
65+ }
2566
26− property real topMarginProgress
67+ Binding {
68+ target: surface
69+ property: "enabled"
70+ value: root.interactive
71+ }
72+ Binding {
73+ target: surface
74+ property: "focus"
75+ value: root.interactive
76+ }
2777
28− QtObject {
29− id: priv
30− property real heightDifference: root.height - appImage.implicitHeight
78+ Timer { //FIXME - need to delay removing splash screen to allow surface resize to complete
79+ id: surfaceRevealDelay
80+ interval: 100
81+ onTriggered: surfaceContainer.revealSurface()
82+ }
83+
84+ Connections {
85+ target: surface
86+ // FIXME: I would rather not need to do this, but currently it doesn't get
87+ // active focus without it and I don't know why.
88+ onFocusChanged: forceSurfaceActiveFocusIfReady();
89+ onParentChanged: forceSurfaceActiveFocusIfReady();
90+ onEnabledChanged: forceSurfaceActiveFocusIfReady();
91+ function forceSurfaceActiveFocusIfReady() {
92+ if (surface.focus && surface.parent === surfaceContainer && surface.enabled) {
93+ surface.forceActiveFocus();
94+ }
95+ }
96+ }
97+
98+ BorderImage {
99+ id: dropShadowImage
100+ anchors {
101+ fill: parent
102+ leftMargin: -units.gu(2)
103+ rightMargin: -units.gu(2)
104+ bottomMargin: -units.gu(2)
105+ topMargin: -units.gu(2) + (root.isFullscreen ? 0 : maximizedAppTopMargin)
106+ }
107+ source: "graphics/dropshadow.png"
108+ border { left: 50; right: 50; top: 50; bottom: 50 }
109+ opacity: root.dropShadow ? .4 : 0
110+ Behavior on opacity { UbuntuNumberAnimation {} }
111+ }
112+
113+ transform: Translate {
114+ y: dragArea.distance
115+ }
31116 }
32117
33− Image {
34− id: dropShadow
35− anchors.fill: appImage
36− anchors.margins: -units.gu(2)
37− source: "graphics/dropshadow.png"
38− opacity: .4
118+
119+ StateGroup {
120+ id: appSurfaceState
121+ states: [
122+ State {
123+ name: "noSurfaceYet"
124+ when: !surfaceContainer.appHasCreatedASurface
125+ StateChangeScript {
126+ script: { splashLoader.setSource("Splash.qml", { "name": model.name, "image": model.icon }); }
127+ }
128+ },
129+ State {
130+ name: "hasSurface"
131+ when: surfaceContainer.appHasCreatedASurface && (surfaceContainer.surface !== null)
132+ StateChangeScript { script: { surfaceRevealDelay.start(); } }
133+ },
134+ State {
135+ name: "surfaceLostButAppStillAlive"
136+ when: surfaceContainer.appHasCreatedASurface && (surfaceContainer.surface === null)
137+ // TODO - use app snapshot
138+ }
139+ ]
140+ state: "noSurfaceYet"
39141 }
40− Image {
41− id: appImage
42− anchors {
43− left: parent.left;
44− bottom: parent.bottom;
45− top: parent.top;
46− topMargin: priv.heightDifference * Math.max(0, 1 - root.topMarginProgress)
47− }
48− source: model.screenshot
49− antialiasing: true
142+
143+ Loader {
144+ id: splashLoader
145+ anchors.fill: surfaceContainer
50146 }
51− MouseArea {
52− anchors.fill: appImage
53− onClicked: root.clicked()
147+
148+ DraggingArea {
149+ id: dragArea
150+ anchors.fill: parent
151+
152+ property bool moving: false
153+ property real distance: 0
154+
155+ onMovingChanged: {
156+ spreadView.draggedIndex = moving ? index : -1
157+ }
158+
159+ onDragValueChanged: {
160+ if (!dragging) {
161+ return;
162+ }
163+ moving = moving || Math.abs(dragValue) > units.gu(1)
164+ if (moving) {
165+ distance = dragValue;
166+ }
167+ }
168+
169+ onClicked: {
170+ if (!moving) {
171+ root.clicked();
172+ }
173+ }
174+
175+ onDragEnd: {
176+ if (model.appId == "unity8-dash") {
177+ animation.animate("center")
178+ return;
179+ }
180+
181+ // velocity and distance values specified by design prototype
182+ if ((dragVelocity < -units.gu(40) && distance < -units.gu(8)) || distance < -root.height / 2) {
183+ animation.animate("up")
184+ } else if ((dragVelocity > units.gu(40) && distance > units.gu(8)) || distance > root.height / 2) {
185+ animation.animate("down")
186+ } else {
187+ animation.animate("center")
188+ }
189+ }
190+
191+ UbuntuNumberAnimation {
192+ id: animation
193+ target: dragArea
194+ property: "distance"
195+ property bool requestClose: false
196+
197+ function animate(direction) {
198+ animation.from = dragArea.distance;
199+ switch (direction) {
200+ case "up":
201+ animation.to = -root.height * 1.5;
202+ requestClose = true;
203+ break;
204+ case "down":
205+ animation.to = root.height * 1.5;
206+ requestClose = true;
207+ break;
208+ default:
209+ animation.to = 0
210+ }
211+ animation.start();
212+ }
213+
214+ onRunningChanged: {
215+ if (!running) {
216+ dragArea.moving = false;
217+ dragArea.distance = 0;
218+ if (requestClose) {
219+ root.closed();
220+ }
221+ }
222+ }
223+ }
54224 }
55225}
qml/Stages/StageWithSideStage.qmldeleted−413
@@ -1,413 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−import "../Components"
20−import Unity.Application 0.1
21−import Ubuntu.Gestures 0.1
22−
23−Item {
24− id: root
25− objectName: "stages"
26− anchors.fill: parent
27−
28− // Controls to be set from outside
29− property bool shown: false
30− property bool moving: false
31− property int dragAreaWidth
32−
33− // State information propagated to the outside
34− readonly property bool painting: mainStageImage.visible || sideStageImage.visible || sideStageSnapAnimation.running
35− property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
36− property bool overlayMode: (sideStageImage.shown && priv.mainStageAppId.length == 0) || priv.overlayOverride
37− || (priv.mainStageAppId.length == 0 && sideStageSnapAnimation.running)
38−
39− readonly property int overlayWidth: priv.overlayOverride ? 0 : priv.sideStageWidth
40−
41− onShownChanged: {
42− if (!shown) {
43− priv.mainStageAppId = "";
44− }
45− }
46−
47− onMovingChanged: {
48− if (moving) {
49− if (!priv.mainStageAppId && !priv.sideStageAppId) {
50− // Pulling in from the right, make the last used (topmost) app visible
51− var application = ApplicationManager.get(0);
52− if (application.stage == ApplicationInfoInterface.SideStage) {
53− sideStageImage.application = application;
54− sideStageImage.x = root.width - sideStageImage.width
55− sideStageImage.visible = true;
56− } else {
57− mainStageImage.application = application;
58− mainStageImage.visible = true;
59− }
60− } else {
61− priv.requestNewScreenshot(ApplicationInfoInterface.MainStage)
62− if (priv.focusedApplicationId == priv.sideStageAppId) {
63− priv.requestNewScreenshot(ApplicationInfoInterface.SideStage)
64− }
65− }
66− } else {
67− mainStageImage.visible = false;
68− sideStageImage.visible = false;
69− }
70− }
71−
72− QtObject {
73− id: priv
74−
75− property int sideStageWidth: units.gu(40)
76−
77−
78− property string sideStageAppId
79− property string mainStageAppId
80−
81−
82− property var sideStageApp: ApplicationManager.findApplication(sideStageAppId)
83− property var mainStageApp: ApplicationManager.findApplication(mainStageAppId)
84−
85− property string sideStageScreenshot: sideStageApp ? sideStageApp.screenshot : ""
86− property string mainStageScreenshot: mainStageApp ? mainStageApp.screenshot : ""
87−
88− property string focusedApplicationId: ApplicationManager.focusedApplicationId
89− property var focusedApplication: ApplicationManager.findApplication(focusedApplicationId)
90− property url focusedScreenshot: focusedApplication ? focusedApplication.screenshot : ""
91−
92− property bool waitingForMainScreenshot: false
93− property bool waitingForSideScreenshot: false
94− property bool waitingForScreenshots: waitingForMainScreenshot || waitingForSideScreenshot
95−
96− property string startingAppId: ""
97−
98− // Keep overlayMode even if there is no focused app (to allow pulling in the sidestage from the right)
99− property bool overlayOverride: false
100−
101− onFocusedApplicationChanged: {
102− if (focusedApplication) {
103− if (focusedApplication.stage == ApplicationInfoInterface.MainStage) {
104− mainStageAppId = focusedApplicationId;
105− priv.overlayOverride = false;
106− if (priv.startingAppId == focusedApplicationId && sideStageImage.shown) {
107− // There was already a sidestage app on top. bring it back!
108− ApplicationManager.focusApplication(priv.sideStageAppId)
109− priv.startingAppId = "";
110− }
111− } else if (focusedApplication.stage == ApplicationInfoInterface.SideStage) {
112− sideStageAppId = focusedApplicationId;
113− if (priv.startingAppId == focusedApplicationId && !sideStageImage.shown) {
114− sideStageImage.snapToApp(focusedApplication);
115− priv.startingAppId = "";
116− }
117− }
118− } else if (root.overlayMode){
119− sideStageImage.snapTo(root.width)
120− }
121− }
122−
123− onMainStageScreenshotChanged: {
124− waitingForMainScreenshot = false;
125− }
126−
127− onSideStageScreenshotChanged: {
128− waitingForSideScreenshot = false;
129− }
130−
131− onFocusedScreenshotChanged: {
132− waitingForSideScreenshot = false;
133− }
134−
135− onWaitingForScreenshotsChanged: {
136− if (waitingForScreenshots) {
137− return;
138− }
139−
140− if (root.moving) {
141− if (mainStageAppId) {
142− mainStageImage.application = mainStageApp
143− mainStageImage.visible = true;
144− }
145− if (sideStageAppId && focusedApplicationId == sideStageAppId) {
146− sideStageImage.application = sideStageApp;
147− sideStageImage.x = root.width - sideStageImage.width
148− sideStageImage.visible = true;
149− }
150− }
151− if (sideStageHandleMouseArea.pressed) {
152− if (sideStageAppId) {
153− sideStageImage.application = sideStageApp;
154− sideStageImage.x = root.width - sideStageImage.width
155− sideStageImage.visible = true;
156− }
157− if (mainStageAppId) {
158− mainStageImage.application = mainStageApp
159− mainStageImage.visible = true;
160− }
161− }
162− }
163−
164− function requestNewScreenshot(stage) {
165− if (stage == ApplicationInfoInterface.MainStage && mainStageAppId) {
166− waitingForMainScreenshot = true;
167− ApplicationManager.updateScreenshot(mainStageAppId);
168− } else if (stage == ApplicationInfoInterface.SideStage && sideStageAppId) {
169− waitingForSideScreenshot = true;
170− ApplicationManager.updateScreenshot(sideStageAppId);
171− }
172− }
173−
174− }
175− // FIXME: the signal connection seems to get lost with the fake application manager.
176− Connections {
177− target: priv.sideStageApp
178− onScreenshotChanged: priv.sideStageScreenshot = priv.sideStageApp.screenshot
179− }
180− Connections {
181− target: priv.mainStageApp
182− onScreenshotChanged: priv.mainStageScreenshot = priv.mainStageApp.screenshot
183− }
184−
185− Connections {
186− target: ApplicationManager
187−
188− onApplicationAdded: {
189− priv.startingAppId = appId;
190− splashScreenTimer.start();
191− var application = ApplicationManager.findApplication(appId)
192− if (application.stage == ApplicationInfoInterface.SideStage) {
193− sideStageSplash.visible = true;
194− } else if (application.stage == ApplicationInfoInterface.MainStage) {
195− mainStageSplash.visible = true;
196− }
197− }
198−
199− onFocusRequested: {
200− var application = ApplicationManager.findApplication(appId)
201− if (application.stage == ApplicationInfoInterface.SideStage) {
202− if (!root.shown) {
203− priv.mainStageAppId = "";
204− mainStageImage.application = null
205− }
206− if (sideStageImage.shown) {
207− sideStageImage.switchTo(application);
208− if (priv.mainStageAppId) {
209− mainStageImage.application = priv.mainStageApp;
210− mainStageImage.visible = true;
211− }
212− } else {
213− sideStageImage.application = application;
214− sideStageImage.snapToApp(application);
215− }
216− } else if (application.stage == ApplicationInfoInterface.MainStage) {
217− if (root.shown) {
218− if (sideStageImage.shown) {
219− sideStageImage.application = priv.sideStageApp;
220− sideStageImage.visible = true;
221− }
222− priv.mainStageAppId = application.appId;
223− mainStageImage.switchTo(application)
224− ApplicationManager.focusApplication(appId)
225− if (sideStageImage.shown) {
226− // There was already a focused SS app. Bring it back
227− ApplicationManager.focusApplication(priv.sideStageAppId)
228− }
229− } else {
230− if (sideStageImage.shown) {
231− sideStageImage.visible = false;
232− sideStageImage.x = root.width;
233− }
234−
235− mainStageImage.application = application;
236− ApplicationManager.focusApplication(appId)
237− }
238− }
239− }
240−
241− onApplicationRemoved: {
242− if (priv.mainStageAppId == appId) {
243− priv.mainStageAppId = "";
244− }
245− if (priv.sideStageAppId == appId) {
246− priv.sideStageAppId = "";
247− }
248− if (priv.sideStageAppId.length == 0) {
249− sideStageImage.shown = false;
250− priv.overlayOverride = false;
251− }
252− }
253−
254− }
255−
256− Timer {
257− id: splashScreenTimer
258− // FIXME: apart from removing this completely in the future and make the app surface paint
259− // meaningful stuff, also check for colin's stuff to land so we can shape 1.4 secs away from here
260− // https://code.launchpad.net/~cjwatson/upstart-app-launch/libclick-manifest/+merge/210520
261− // https://code.launchpad.net/~cjwatson/upstart-app-launch/libclick-pkgdir/+merge/209909
262− interval: 1700
263− repeat: false
264− onTriggered: {
265− mainStageSplash.visible = false;
266− sideStageSplash.visible = false;
267− }
268− }
269−
270− SwitchingApplicationImage {
271− id: mainStageImage
272− anchors.bottom: parent.bottom
273− width: parent.width
274− visible: false
275−
276− onSwitched: {
277− sideStageImage.visible = false;
278− }
279− }
280−
281− Rectangle {
282− id: mainStageSplash
283− anchors.fill: root
284− anchors.rightMargin: root.width - sideStageImage.x
285− color: "black"
286−
287− WaitingDots {
288− }
289− }
290−
291− SidestageHandle {
292− id: sideStageHandle
293− anchors { top: parent.top; right: sideStageImage.left; bottom: parent.bottom }
294− width: root.dragAreaWidth
295− visible: root.shown && priv.sideStageAppId && sideStageImage.x < root.width
296−
297− }
298− MouseArea {
299− id: sideStageHandleMouseArea
300− anchors { top: parent.top; right: parent.right; bottom: parent.bottom; rightMargin: sideStageImage.shown ? sideStageImage.width : 0}
301− width: root.dragAreaWidth
302− visible: priv.sideStageAppId
303−
304− property var dragPoints: new Array()
305−
306− onPressed: {
307− priv.requestNewScreenshot(ApplicationInfoInterface.SideStage)
308− if (priv.mainStageAppId) {
309− priv.requestNewScreenshot(ApplicationInfoInterface.MainStage)
310− }
311− }
312−
313− onMouseXChanged: {
314− dragPoints.push(mouseX)
315−
316− var dragPoint = root.width + mouseX;
317− if (sideStageImage.shown) {
318− dragPoint -= sideStageImage.width
319− }
320− sideStageImage.x = Math.max(root.width - sideStageImage.width, dragPoint)
321− }
322−
323− onReleased: {
324− var distance = 0;
325− var lastX = dragPoints[0];
326− var oneWayFlick = true;
327− for (var i = 0; i < dragPoints.length; ++i) {
328− if (dragPoints[i] < lastX) {
329− oneWayFlick = false;
330− }
331− distance += dragPoints[i] - lastX;
332− lastX = dragPoints[i];
333− }
334− dragPoints = [];
335−
336− if (oneWayFlick || distance > sideStageImage.width / 2) {
337− sideStageImage.snapTo(root.width)
338− } else {
339− sideStageImage.snapToApp(priv.sideStageApp)
340− }
341− }
342− }
343−
344− SwitchingApplicationImage {
345− id: sideStageImage
346− width: priv.sideStageWidth
347− height: root.height
348− x: root.width
349− anchors.bottom: parent.bottom
350− visible: true
351− property bool shown: false
352−
353− onSwitched: {
354− mainStageImage.visible = false;
355− ApplicationManager.focusApplication(application.appId)
356− }
357−
358− function snapTo(targetX) {
359− sideStageSnapAnimation.targetX = targetX
360− sideStageImage.visible = true;
361− if (priv.mainStageAppId) {
362− mainStageImage.application = priv.mainStageApp
363− mainStageImage.visible = true;
364− }
365− sideStageSnapAnimation.start();
366− }
367−
368− function snapToApp(application) {
369− sideStageImage.application = application
370− sideStageSnapAnimation.snapToId = application.appId;
371− snapTo(root.width - sideStageImage.width);
372− }
373−
374− SequentialAnimation {
375− id: sideStageSnapAnimation
376− property int targetX: root.width
377− property string snapToId
378−
379− UbuntuNumberAnimation { target: sideStageImage; property: "x"; to: sideStageSnapAnimation.targetX; duration: UbuntuAnimation.SlowDuration }
380− ScriptAction {
381− script: {
382− if (sideStageSnapAnimation.targetX == root.width) {
383− if (priv.mainStageAppId) {
384− ApplicationManager.focusApplication(priv.mainStageAppId)
385− } else {
386− priv.overlayOverride = true;
387− ApplicationManager.unfocusCurrentApplication();
388− }
389− sideStageImage.shown = false;
390− }
391− if (sideStageSnapAnimation.snapToId) {
392− ApplicationManager.focusApplication(sideStageSnapAnimation.snapToId)
393− sideStageSnapAnimation.snapToId = "";
394− sideStageImage.shown = true;
395− priv.overlayOverride = false;
396− }
397− sideStageImage.visible = false;
398− mainStageImage.visible = false;
399− }
400− }
401− }
402− }
403−
404− Rectangle {
405− id: sideStageSplash
406− anchors.fill: parent
407− anchors.leftMargin: sideStageImage.x
408− color: "black"
409−
410− WaitingDots {
411− }
412− }
413−}
qml/Stages/SurfaceContainer.qmlnew file+123
@@ -0,0 +1,123 @@
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 Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+*/
16+
17+import QtQuick 2.0
18+import "Animations"
19+
20+Item {
21+ id: container
22+ property Item surface: null
23+ property bool removing: false
24+
25+ onSurfaceChanged: {
26+ if (surface) {
27+ surface.parent = container;
28+ surface.z = 1;
29+ state = "initial"
30+ }
31+ }
32+
33+ Connections {
34+ target: surface
35+ onRemoved: {
36+ container.removing = true;
37+
38+ var childSurfaces = surface.childSurfaces;
39+ for (var i=0; i<childSurfaces.length; i++) {
40+ childSurfaces[i].removed();
41+ }
42+
43+ //if we don't have children, nothing will tell us to animate out, so do it.
44+ if (childSurfaces.length === 0) {
45+ animateOut();
46+ }
47+ // tell our parent to animate out.
48+ if (surface.parentSurface) {
49+ surface.parentSurface.parent.animateOut();
50+ }
51+ }
52+ }
53+
54+ Repeater {
55+ model: container.surface ? container.surface.childSurfaces : 0
56+
57+ delegate: Loader {
58+ z: 2
59+ anchors {
60+ fill: container
61+ topMargin: container.surface.anchors.topMargin
62+ rightMargin: container.surface.anchors.rightMargin
63+ bottomMargin: container.surface.anchors.bottomMargin
64+ leftMargin: container.surface.anchors.leftMargin
65+ }
66+
67+ // Only way to do recursive qml items.
68+ source: Qt.resolvedUrl("SurfaceContainer.qml")
69+ onLoaded: {
70+ item.surface = modelData;
71+ item.animateIn(swipeFromBottom);
72+ container.animateIn(swipeUp);
73+ }
74+ }
75+ }
76+
77+ function animateIn(component) {
78+ var animation = component.createObject(container, { "surface": container.surface });
79+ animation.start();
80+
81+ var tmp = d.animations;
82+ tmp.push(animation);
83+ d.animations = tmp;
84+ }
85+
86+ function animateOut() {
87+ if (d.animations.length > 0) {
88+ var tmp = d.animations;
89+ var popped = tmp.pop();
90+ popped.end();
91+ d.animations = tmp;
92+ } else {
93+ container.state = "initial";
94+ }
95+ }
96+
97+ QtObject {
98+ id: d
99+ property var animations: []
100+ property var currentAnimation: animations.length > 0 ? animations[animations.length-1] : undefined
101+ }
102+
103+ Component {
104+ id: swipeFromBottom
105+ SwipeFromBottomAnimation {}
106+ }
107+ Component {
108+ id: swipeUp
109+ SwipeUpAnimation {}
110+ }
111+ Component {
112+ id: darkenFade
113+ DarkenAndFadeInAnimation {}
114+ }
115+
116+ states: [
117+ State {
118+ name: "initial"
119+ PropertyChanges { target: surface; anchors.fill: container }
120+ }
121+ // TODO: more animations!
122+ ]
123+}
qml/Stages/SwitchingApplicationImage.qmldeleted−81
@@ -1,81 +0,0 @@
1−/*
2− * Copyright 2014 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU 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− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17−*/
18−
19−import QtQuick 2.0
20−import Ubuntu.Components 0.1
21−
22−Rectangle {
23− id: root
24− implicitHeight: image.implicitHeight
25− implicitWidth: image.implicitWidth
26− color: "black"
27−
28− property var application
29−
30− signal switched()
31−
32− function switchTo(application) {
33− if (root.application == application) {
34− root.switched();
35− return;
36− }
37−
38− priv.newApplication = application
39− root.visible = true;
40− switchToAnimation.start()
41− }
42−
43− QtObject {
44− id: priv
45− property var newApplication
46− }
47−
48− Image {
49− id: newImage
50− anchors.bottom: parent.bottom
51− width: root.width
52− source: priv.newApplication ? priv.newApplication.screenshot : ""
53− }
54−
55− Image {
56− id: image
57− visible: true
58− source: root.application ? root.application.screenshot : ""
59− width: root.width
60− height: sourceSize.height
61− anchors.bottom: parent.bottom
62−
63− }
64−
65− SequentialAnimation {
66− id: switchToAnimation
67− ParallelAnimation {
68− UbuntuNumberAnimation { target: image; property: "x"; from: 0; to: root.width; duration: UbuntuAnimation.SlowDuration }
69− UbuntuNumberAnimation { target: newImage; property: "scale"; from: 0.7; to: 1; duration: UbuntuAnimation.SlowDuration }
70− }
71− ScriptAction {
72− script: {
73− image.x = 0
74− root.application = priv.newApplication
75− root.visible = false;
76− priv.newApplication = null
77− root.switched();
78− }
79− }
80− }
81−}
qml/Stages/TabletStage.qmlnew file+612
@@ -0,0 +1,612 @@
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+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import Ubuntu.Gestures 0.1
20+import Unity.Application 0.1
21+import Utils 0.1
22+import "../Components"
23+
24+Rectangle {
25+ id: root
26+ objectName: "stages"
27+ anchors.fill: parent
28+ color: "black"
29+
30+ // Controls to be set from outside
31+ property bool shown: false
32+ property bool moving: false
33+ property int dragAreaWidth
34+ property real maximizedAppTopMargin
35+ property bool interactive
36+ property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
37+
38+ onInverseProgressChanged: {
39+ if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
40+ // left edge drag released. Minimum distance is given by design.
41+ if (priv.oldInverseProgress > units.gu(22)) {
42+ ApplicationManager.focusApplication("unity8-dash");
43+ }
44+ }
45+ priv.oldInverseProgress = inverseProgress;
46+ }
47+
48+ QtObject {
49+ id: priv
50+
51+ property string focusedAppId: ApplicationManager.focusedApplicationId
52+ property string oldFocusedAppId: ""
53+
54+ property string mainStageAppId
55+ property string sideStageAppId
56+
57+ // For convenience, keep properties of the first two apps in the model
58+ property string appId0
59+ property string appId1
60+
61+ property int oldInverseProgress: 0
62+
63+ onFocusedAppIdChanged: {
64+ if (priv.focusedAppId.length > 0) {
65+ var focusedApp = ApplicationManager.findApplication(focusedAppId);
66+ if (focusedApp.stage == ApplicationInfoInterface.SideStage) {
67+ priv.sideStageAppId = focusedAppId;
68+ } else {
69+ priv.mainStageAppId = focusedAppId;
70+ }
71+ }
72+
73+ appId0 = ApplicationManager.count >= 1 ? ApplicationManager.get(0).appId : "";
74+ appId1 = ApplicationManager.count > 1 ? ApplicationManager.get(1).appId : "";
75+ }
76+
77+ function indexOf(appId) {
78+ for (var i = 0; i < ApplicationManager.count; i++) {
79+ if (ApplicationManager.get(i).appId == appId) {
80+ return i;
81+ }
82+ }
83+ return -1;
84+ }
85+
86+ function evaluateOneWayFlick(gesturePoints) {
87+ // Need to have at least 3 points to recognize it as a flick
88+ if (gesturePoints.length < 3) {
89+ return false;
90+ }
91+ // Need to have a movement of at least 2 grid units to recognize it as a flick
92+ if (Math.abs(gesturePoints[gesturePoints.length - 1] - gesturePoints[0]) < units.gu(2)) {
93+ return false;
94+ }
95+
96+ var oneWayFlick = true;
97+ var smallestX = gesturePoints[0];
98+ var leftWards = gesturePoints[1] < gesturePoints[0];
99+ for (var i = 1; i < gesturePoints.length; i++) {
100+ if ((leftWards && gesturePoints[i] >= smallestX)
101+ || (!leftWards && gesturePoints[i] <= smallestX)) {
102+ oneWayFlick = false;
103+ break;
104+ }
105+ smallestX = gesturePoints[i];
106+ }
107+ return oneWayFlick;
108+ }
109+ }
110+
111+ Connections {
112+ target: ApplicationManager
113+ onFocusRequested: {
114+ if (spreadView.interactive) {
115+ spreadView.snapTo(priv.indexOf(appId));
116+ } else {
117+ ApplicationManager.focusApplication(appId);
118+ }
119+ }
120+
121+ onApplicationAdded: {
122+ if (spreadView.phase == 2) {
123+ spreadView.snapTo(ApplicationManager.count - 1);
124+ } else {
125+ spreadView.phase = 0;
126+ spreadView.contentX = -spreadView.shift;
127+ ApplicationManager.focusApplication(appId);
128+ }
129+ }
130+
131+ onApplicationRemoved: {
132+ if (priv.mainStageAppId == appId) {
133+ ApplicationManager.focusApplication("unity8-dash")
134+ }
135+ if (priv.sideStageAppId == appId) {
136+ priv.sideStageAppId = "";
137+ }
138+ if (ApplicationManager.count == 0) {
139+ spreadView.phase = 0;
140+ spreadView.contentX = -spreadView.shift;
141+ }
142+ }
143+ }
144+
145+ Flickable {
146+ id: spreadView
147+ anchors.fill: parent
148+ interactive: (spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1) && draggedIndex == -1
149+ contentWidth: spreadRow.width - shift
150+ contentX: -shift
151+
152+ property int tileDistance: units.gu(20)
153+ property int sideStageWidth: units.gu(40)
154+ property bool sideStageVisible: priv.sideStageAppId
155+
156+ // This indicates when the spreadView is active. That means, all the animations
157+ // are activated and tiles need to line up for the spread.
158+ readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging
159+
160+ // The flickable needs to fill the screen in order to get touch events all over.
161+ // However, we don't want to the user to be able to scroll back all the way. For
162+ // that, the beginning of the gesture starts with a negative value for contentX
163+ // so the flickable wants to pull it into the view already. "shift" tunes the
164+ // distance where to "lock" the content.
165+ readonly property real shift: width / 2
166+ readonly property real shiftedContentX: contentX + shift
167+
168+ // Phase of the animation:
169+ // 0: Starting from right edge, a new app (index 1) comes in from the right
170+ // 1: The app has reached the first snap position.
171+ // 2: The list is dragged further and snaps into the spread view when entering phase 2
172+ property int phase
173+
174+ readonly property int phase0Width: sideStageWidth
175+ readonly property int phase1Width: sideStageWidth
176+
177+ // Those markers mark the various positions in the spread (ratio to screen width from right to left):
178+ // 0 - 1: following finger, snap back to the beginning on release
179+ readonly property real positionMarker1: 0.2
180+ // 1 - 2: curved snapping movement, snap to nextInStack on release
181+ readonly property real positionMarker2: sideStageWidth / spreadView.width
182+ // 2 - 3: movement follows finger, snaps to phase 2 (full spread) on release
183+ readonly property real positionMarker3: 0.6
184+ // passing 3, we detach movement from the finger and snap to phase 2 (full spread)
185+ readonly property real positionMarker4: 0.8
186+
187+ readonly property int startSnapPosition: phase0Width * 0.5
188+ readonly property int endSnapPosition: phase0Width * 0.75
189+ readonly property real snapPosition: 0.75
190+
191+ property int selectedIndex: -1
192+ property int draggedIndex: -1
193+ property int closingIndex: -1
194+
195+ property bool sideStageDragging: sideStageDragHandle.dragging
196+ property real sideStageDragProgress: sideStageDragHandle.progress
197+
198+ onSideStageDragProgressChanged: {
199+ if (sideStageDragProgress == 1) {
200+ ApplicationManager.focusApplication(priv.mainStageAppId);
201+ priv.sideStageAppId = "";
202+ }
203+ }
204+
205+ // In case the ApplicationManager already holds an app when starting up we're missing animations
206+ // Make sure we end up in the same state
207+ Component.onCompleted: {
208+ spreadView.contentX = -spreadView.shift
209+ }
210+
211+ property int nextInStack: {
212+ switch (state) {
213+ case "main":
214+ if (ApplicationManager.count > 1) {
215+ return 1;
216+ }
217+ return -1;
218+ case "mainAndOverlay":
219+ if (ApplicationManager.count <= 2) {
220+ return -1;
221+ }
222+ if (priv.appId0 == priv.mainStageAppId || priv.appId0 == priv.sideStageAppId) {
223+ if (priv.appId1 == priv.mainStageAppId || priv.appId1 == priv.sideStageAppId) {
224+ return 2;
225+ }
226+ return 1;
227+ }
228+ return 0;
229+ case "overlay":
230+ return 1;
231+ }
232+ print("Unhandled nextInStack case! This shouldn't happen any more when the Dash is an app!");
233+ return -1;
234+ }
235+ property int nextZInStack: indexToZIndex(nextInStack)
236+
237+ states: [
238+ State {
239+ name: "empty"
240+ },
241+ State {
242+ name: "main"
243+ },
244+ State { // Side Stage only in overlay mode
245+ name: "overlay"
246+ },
247+ State { // Main Stage and Side Stage in overlay mode
248+ name: "mainAndOverlay"
249+ },
250+ State { // Main Stage and Side Stage in split mode
251+ name: "mainAndSplit"
252+ }
253+ ]
254+ state: {
255+ if (priv.mainStageAppId && !priv.sideStageAppId) {
256+ return "main";
257+ }
258+ if (!priv.mainStageAppId && priv.sideStageAppId) {
259+ return "overlay";
260+ }
261+ if (priv.mainStageAppId && priv.sideStageAppId) {
262+ return "mainAndOverlay";
263+ }
264+ return "empty";
265+ }
266+
267+ onShiftedContentXChanged: {
268+ if (spreadView.phase == 0 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker2) {
269+ spreadView.phase = 1;
270+ } else if (spreadView.phase == 1 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker4) {
271+ spreadView.phase = 2;
272+ } else if (spreadView.phase == 1 && spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
273+ spreadView.phase = 0;
274+ }
275+ }
276+
277+ function snap() {
278+ if (shiftedContentX < phase0Width) {
279+ snapAnimation.targetContentX = -shift;
280+ snapAnimation.start();
281+ } else if (shiftedContentX < phase1Width) {
282+ snapTo(1);
283+ } else {
284+ // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
285+ snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1 - shift;
286+ snapAnimation.start();
287+ }
288+ }
289+ function snapTo(index) {
290+ spreadView.selectedIndex = index;
291+ snapAnimation.targetContentX = -shift;
292+ snapAnimation.start();
293+ }
294+
295+ // We need to shuffle z ordering a bit in order to keep side stage apps above main stage apps.
296+ // We don't want to really reorder them in the model because that allows us to keep track
297+ // of the last focused order.
298+ function indexToZIndex(index) {
299+ var app = ApplicationManager.get(index);
300+ if (!app) {
301+ return index;
302+ }
303+
304+ var active = app.appId == priv.mainStageAppId || app.appId == priv.sideStageAppId;
305+ if (active && app.stage == ApplicationInfoInterface.MainStage) {
306+ // if this app is active, and its the MainStage, always put it to index 0
307+ return 0;
308+ }
309+ if (active && app.stage == ApplicationInfoInterface.SideStage) {
310+ if (!priv.mainStageAppId) {
311+ // Only have SS apps running. Put the active one at 0
312+ return 0;
313+ }
314+
315+ // Precondition now: There's an active MS app and this is SS app:
316+ if (spreadView.nextInStack >= 0 && ApplicationManager.get(spreadView.nextInStack).stage == ApplicationInfoInterface.MainStage) {
317+ // If the next app coming from the right is a MS app, we need to elevate this SS ap above it.
318+ // Put it to at least level 2, or higher if there's more apps coming in before this one.
319+ return Math.max(index, 2);
320+ } else {
321+ // if this is no next app to come in from the right, place this one at index 1, just on top the active MS app.
322+ return 1;
323+ }
324+ }
325+ if (index <= 2 && app.stage == ApplicationInfoInterface.MainStage && priv.sideStageAppId) {
326+ // Ok, this is an inactive MS app. If there's an active SS app around, we need to place this one
327+ // in between the active MS app and the active SS app, so that it comes in from there when dragging from the right.
328+ // If there's now active SS app, just leave it where it is.
329+ return priv.indexOf(priv.sideStageAppId) < index ? index - 1 : index;
330+ }
331+ if (index == spreadView.nextInStack && app.stage == ApplicationInfoInterface.SideStage) {
332+ // This is a SS app and the next one to come in from the right:
333+ if (priv.sideStageAppId && priv.mainStageAppId) {
334+ // If there's both, an active MS and an active SS app, put this one right on top of that
335+ return 2;
336+ }
337+ // Or if there's only one other active app, put it on top of that.
338+ // The case that there isn't any other active app is already handled above.
339+ return 1;
340+ }
341+ if (index == 2 && spreadView.nextInStack == 1 && priv.sideStageAppId) {
342+ // If its index 2 but not the next one to come in, it means
343+ // we've pulled another one down to index 2. Move this one up to 2 instead.
344+ return 3;
345+ }
346+ // don't touch all others... (mostly index > 3 + simple cases where the above doesn't shuffle much)
347+ return index;
348+ }
349+
350+ SequentialAnimation {
351+ id: snapAnimation
352+ property int targetContentX: -spreadView.shift
353+
354+ UbuntuNumberAnimation {
355+ target: spreadView
356+ property: "contentX"
357+ to: snapAnimation.targetContentX
358+ duration: UbuntuAnimation.FastDuration
359+ }
360+
361+ ScriptAction {
362+ script: {
363+ if (spreadView.selectedIndex >= 0) {
364+ var newIndex = spreadView.selectedIndex;
365+ spreadView.selectedIndex = -1;
366+ ApplicationManager.focusApplication(ApplicationManager.get(newIndex).appId);
367+ spreadView.phase = 0;
368+ spreadView.contentX = -spreadView.shift;
369+ }
370+ }
371+ }
372+ }
373+
374+ Item {
375+ id: spreadRow
376+ x: spreadView.contentX
377+ height: root.height
378+ width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance)
379+
380+ Rectangle {
381+ id: sideStageBackground
382+ color: "black"
383+ anchors.fill: parent
384+ anchors.leftMargin: spreadView.width - (1 - sideStageDragHandle.progress) * spreadView.sideStageWidth
385+ z: spreadView.indexToZIndex(priv.indexOf(priv.sideStageAppId))
386+ opacity: spreadView.phase == 0 ? 1 : 0
387+ Behavior on opacity { UbuntuNumberAnimation {} }
388+ }
389+
390+ Item {
391+ id: sideStageDragHandle
392+ anchors { top: parent.top; bottom: parent.bottom; left: parent.left; leftMargin: spreadView.width - spreadView.sideStageWidth - width }
393+ width: units.gu(2)
394+ z: sideStageBackground.z
395+ opacity: spreadView.phase <= 0 && spreadView.sideStageVisible ? 1 : 0
396+ property real progress: 0
397+ property bool dragging: false
398+
399+ Behavior on opacity { UbuntuNumberAnimation {} }
400+
401+ Connections {
402+ target: spreadView
403+ onSideStageVisibleChanged: {
404+ if (spreadView.sideStageVisible) {
405+ sideStageDragHandle.progress = 0;
406+ }
407+ }
408+ }
409+
410+ Image {
411+ anchors.centerIn: parent
412+ anchors.horizontalCenterOffset: parent.progress * spreadView.sideStageWidth - (width - parent.width) / 2
413+ width: sideStageDragHandleMouseArea.pressed ? parent.width * 2 : parent.width
414+ height: parent.height
415+ source: "graphics/sidestage_handle@20.png"
416+ Behavior on width { UbuntuNumberAnimation {} }
417+ }
418+
419+ MouseArea {
420+ id: sideStageDragHandleMouseArea
421+ anchors.fill: parent
422+ enabled: spreadView.shiftedContentX == 0
423+ property int startX
424+ property var gesturePoints: new Array()
425+
426+ onPressed: {
427+ gesturePoints = [];
428+ startX = mouseX;
429+ sideStageDragHandle.progress = 0;
430+ sideStageDragHandle.dragging = true;
431+ }
432+ onMouseXChanged: {
433+ if (priv.mainStageAppId) {
434+ sideStageDragHandle.progress = Math.max(0, (-startX + mouseX) / spreadView.sideStageWidth);
435+ }
436+ gesturePoints.push(mouseX);
437+ }
438+ onReleased: {
439+ if (priv.mainStageAppId) {
440+ var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
441+ sideStageDragSnapAnimation.to = sideStageDragHandle.progress > 0.5 || oneWayFlick ? 1 : 0;
442+ sideStageDragSnapAnimation.start();
443+ } else {
444+ sideStageDragHandle.dragging = false;
445+ }
446+ }
447+ }
448+ UbuntuNumberAnimation {
449+ id: sideStageDragSnapAnimation
450+ target: sideStageDragHandle
451+ property: "progress"
452+
453+ onRunningChanged: {
454+ if (!running) {
455+ sideStageDragHandle.dragging = false;
456+ }
457+ }
458+ }
459+ }
460+
461+ Repeater {
462+ id: spreadRepeater
463+ model: ApplicationManager
464+
465+ delegate: TransformedTabletSpreadDelegate {
466+ id: spreadTile
467+ height: spreadView.height
468+ width: model.stage == ApplicationInfoInterface.MainStage ? spreadView.width : spreadView.sideStageWidth
469+ active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId
470+ zIndex: spreadView.indexToZIndex(index)
471+ selected: spreadView.selectedIndex == index
472+ otherSelected: spreadView.selectedIndex >= 0 && !selected
473+ isInSideStage: priv.sideStageAppId == model.appId
474+ interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive
475+ swipeToCloseEnabled: spreadView.interactive
476+ maximizedAppTopMargin: root.maximizedAppTopMargin
477+ dragOffset: !isDash && model.appId == priv.mainStageAppId && root.inverseProgress > 0 ? root.inverseProgress : 0
478+
479+ readonly property bool isDash: model.appId == "unity8-dash"
480+
481+ // FIXME: A regular binding doesn't update any more after closing an app.
482+ // Using a Binding for now.
483+ Binding {
484+ target: spreadTile
485+ property: "z"
486+ value: (!spreadView.active && isDash && !active) ? -1 : spreadTile.zIndex
487+ }
488+ x: spreadView.width
489+
490+ property real behavioredZIndex: zIndex
491+ Behavior on behavioredZIndex {
492+ enabled: spreadView.closingIndex >= 0
493+ UbuntuNumberAnimation {}
494+ }
495+
496+ // This is required because none of the bindings are triggered in some cases:
497+ // When an app is closed, it might happen that ApplicationManager.get(nextInStack)
498+ // returns a different app even though the nextInStackIndex and all the related
499+ // bindings (index, mainStageApp, sideStageApp, etc) don't change. Let's force a
500+ // binding update in that case.
501+ Connections {
502+ target: ApplicationManager
503+ onApplicationRemoved: spreadTile.z = Qt.binding(function() {
504+ return spreadView.indexToZIndex(index);
505+ })
506+ }
507+
508+ progress: {
509+ var tileProgress = (spreadView.shiftedContentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width;
510+ // Some tiles (nextInStack, active) need to move directly from the beginning, normalize progress to immediately start at 0
511+ if ((index == spreadView.nextInStack && spreadView.phase < 2) || (active && spreadView.phase < 1)) {
512+ tileProgress += behavioredZIndex * spreadView.tileDistance / spreadView.width;
513+ }
514+ return tileProgress;
515+ }
516+
517+ animatedProgress: {
518+ if (spreadView.phase == 0 && (spreadTile.active || spreadView.nextInStack == index)) {
519+ if (progress < spreadView.positionMarker1) {
520+ return progress;
521+ } else if (progress < spreadView.positionMarker1 + snappingCurve.period) {
522+ return spreadView.positionMarker1 + snappingCurve.value * 3;
523+ } else {
524+ return spreadView.positionMarker2;
525+ }
526+ }
527+ return progress;
528+ }
529+
530+ onClicked: {
531+ if (spreadView.phase == 2) {
532+ spreadView.snapTo(index);
533+ }
534+ }
535+
536+ onClosed: {
537+ spreadView.draggedIndex = -1;
538+ spreadView.closingIndex = index;
539+ ApplicationManager.stopApplication(ApplicationManager.get(index).appId);
540+ }
541+
542+ EasingCurve {
543+ id: snappingCurve
544+ type: EasingCurve.Linear
545+ period: (spreadView.positionMarker2 - spreadView.positionMarker1) / 3
546+ progress: spreadTile.progress - spreadView.positionMarker1
547+ }
548+ }
549+ }
550+ }
551+ }
552+
553+ EdgeDragArea {
554+ id: spreadDragArea
555+ anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
556+ width: root.dragAreaWidth
557+ direction: Direction.Leftwards
558+
559+ property bool attachedToView: false
560+ property var gesturePoints: new Array()
561+
562+ onTouchXChanged: {
563+ if (!dragging) {
564+ spreadView.phase = 0;
565+ spreadView.contentX = -spreadView.shift;
566+ }
567+
568+ if (dragging && attachedToView) {
569+ spreadView.contentX = -touchX + spreadDragArea.width - spreadView.shift;
570+ if (spreadView.shiftedContentX > spreadView.phase0Width + spreadView.phase1Width / 2) {
571+ attachedToView = false;
572+ spreadView.snap();
573+ }
574+ }
575+ gesturePoints.push(touchX);
576+ }
577+
578+ onStatusChanged: {
579+ if (status == DirectionalDragArea.Recognized) {
580+ attachedToView = true;
581+ }
582+ }
583+
584+ onDraggingChanged: {
585+ if (dragging) {
586+ // Gesture recognized. Start recording this gesture
587+ gesturePoints = [];
588+ return;
589+ }
590+
591+ // Ok. The user released. Find out if it was a one-way movement.
592+ var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
593+ gesturePoints = [];
594+
595+ if (oneWayFlick && spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
596+ // If it was a short one-way movement, do the Alt+Tab switch
597+ // no matter if we didn't cross positionMarker1 yet.
598+ spreadView.snapTo(spreadView.nextInStack);
599+ } else if (!dragging && attachedToView) {
600+ if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker1) {
601+ spreadView.snap();
602+ } else if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
603+ spreadView.snapTo(spreadView.nextInStack);
604+ } else {
605+ // otherwise snap to the closest snap position we can find
606+ // (might be back to start, to app 1 or to spread)
607+ spreadView.snap();
608+ }
609+ }
610+ }
611+ }
612+}
qml/Stages/TransformedSpreadDelegate.qml+37−30
@@ -23,7 +23,9 @@ import Ubuntu.Components 0.1
2323SpreadDelegate {
2424 id: root
2525
26+ // Set this to true when this tile is selected in the spread. The animation will change to bring the tile to front.
2627 property bool selected: false
28+ // Set this to true when another tile in the spread is selected. The animation will change to fade this tile out.
2729 property bool otherSelected: false
2830
2931 // The progress animates the tiles. A value > 0 makes it appear from the right edge. At 1 it reaches the end position.
@@ -106,16 +108,6 @@ SpreadDelegate {
106108 selectedTopMarginProgress = topMarginProgress;
107109 }
108110
109− // This calculates how much negative progress there can be if unwinding the spread completely
110− // the progress for each tile starts at 0 when it crosses the right edge, so the later a tile comes in,
111− // the bigger its negativeProgress can be.
112− property real negativeProgress: {
113− if (index == 1 && spreadView.phase < 2) {
114− return 0;
115− }
116− return -index * spreadView.tileDistance / spreadView.width;
117− }
118−
119111 function linearAnimation(startProgress, endProgress, startValue, endValue, progress) {
120112 // progress : progressDiff = value : valueDiff => value = progress * valueDiff / progressDiff
121113 return (progress - startProgress) * (endValue - startValue) / (endProgress - startProgress) + startValue;
@@ -127,22 +119,24 @@ SpreadDelegate {
127119 return helperEasingCurve.value * (endValue - startValue) + startValue;
128120 }
129121
130− property real animatedEndDistance: linearAnimation(0, 2, root.endDistance, 0, root.progress)
131−
132122 // The following blocks handle the animation of the tile in the spread.
133123 // At the beginning, each tile is attached at the right edge, outside the screen.
134124 // The progress for each tile starts at 0 and it reaches its end position at a progress of 1.
135− // The first phases are handled special for the first 2 tiles. as we do the alt-tab and snapping in there
136− // Once we reached phase 3, the animation is the same for all tiles.
137− // When a tile is selected, the animation state is snapshotted, and the spreadView is unwound (progress animates
138− // back to negativeProgress). All tiles are kept in place and faded out to 0 opacity except
125+ // The first phases are handled special for the first 2 tiles. as we do the alt-tab and snapping
126+ // in there. Once we reached phase 3, the animation is the same for all tiles.
127+ // When a tile is selected, the animation state is snapshotted, and the spreadView is unwound.
128+ // All tiles are kept in place and faded out to 0 opacity except
139129 // the selected tile, which is animated from the snapshotted position to be fullscreen.
140130
141− property real xTranslate: {
131+ readonly property real xTranslate: {
132+ if (!spreadView.active) {
133+ return 0;
134+ }
135+
142136 if (otherSelected) {
143137 if (spreadView.phase < 2 && index == 0) {
144− return linearAnimation(selectedProgress, negativeProgress,
145− selectedXTranslate, selectedXTranslate - spreadView.tileDistance, root.progress);
138+ return linearAnimation(selectedProgress, 0, selectedXTranslate,
139+ selectedXTranslate - spreadView.tileDistance, root.progress);
146140 }
147141
148142 return selectedXTranslate;
@@ -160,7 +154,7 @@ SpreadDelegate {
160154 // Apply the same animation as with the rest but add spreadView.width to align it with the others.
161155 return -easingCurve.value * spreadView.width + spreadView.width;
162156 } else if (priv.isSelected) {
163− return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, 0, root.progress);
157+ return linearAnimation(selectedProgress, 0, selectedXTranslate, 0, root.progress);
164158 }
165159
166160 case 1:
@@ -177,23 +171,28 @@ SpreadDelegate {
177171 if (priv.isSelected) {
178172 // Distance to left edge
179173 var targetTranslate = -spreadView.width - ((index - 1) * root.startDistance);
180− return linearAnimation(selectedProgress, negativeProgress,
174+ return linearAnimation(selectedProgress, 0,
181175 selectedXTranslate, targetTranslate, root.progress);
182176 }
183177
184178 // Fix it at the right edge...
185179 var rightEdgeOffset = -((index - 1) * root.startDistance);
186180 // ...and use our easing to move them to the left. Stop a bit earlier for each tile
181+ var animatedEndDistance = linearAnimation(0, 2, root.endDistance, 0, root.progress);
187182 return -easingCurve.value * spreadView.width + (index * animatedEndDistance) + rightEdgeOffset;
188183
189184 }
190185
191− property real angle: {
186+ readonly property real angle: {
187+ if (!spreadView.active) {
188+ return 0;
189+ }
190+
192191 if (priv.otherSelected) {
193192 return priv.selectedAngle;
194193 }
195194 if (priv.isSelected) {
196− return linearAnimation(selectedProgress, negativeProgress, selectedAngle, 0, root.progress);
195+ return linearAnimation(selectedProgress, 0, selectedAngle, 0, root.progress);
197196 }
198197 switch (index) {
199198 case 0:
@@ -217,12 +216,15 @@ SpreadDelegate {
217216 return root.startAngle - easingCurve.value * (root.startAngle - root.endAngle);
218217 }
219218
220− property real scale: {
219+ readonly property real scale: {
220+ if (!spreadView.active) {
221+ return 1;
222+ }
221223 if (priv.otherSelected) {
222224 return priv.selectedScale;
223225 }
224226 if (priv.isSelected) {
225− return linearAnimation(selectedProgress, negativeProgress, selectedScale, 1, root.progress);
227+ return linearAnimation(selectedProgress, 0, selectedScale, 1, root.progress);
226228 }
227229
228230 switch (index) {
@@ -247,7 +249,7 @@ SpreadDelegate {
247249 return root.startScale - easingCurve.value * (root.startScale - root.endScale);
248250 }
249251
250− property real opacity: {
252+ readonly property real opacity: {
251253 if (priv.otherSelected) {
252254 return linearAnimation (selectedProgress, Math.max(0, selectedProgress - .5),
253255 selectedOpacity, 0, root.progress);
@@ -265,9 +267,9 @@ SpreadDelegate {
265267 return 1;
266268 }
267269
268− property real topMarginProgress: {
270+ readonly property real topMarginProgress: {
269271 if (priv.isSelected) {
270− return linearAnimation(selectedProgress, negativeProgress, selectedTopMarginProgress, 0, root.progress);
272+ return linearAnimation(selectedProgress, 0, selectedTopMarginProgress, 0, root.progress);
271273 }
272274
273275 switch (index) {
@@ -290,6 +292,7 @@ SpreadDelegate {
290292
291293 return easingCurve.value;
292294 }
295+
293296 }
294297
295298 transform: [
@@ -303,18 +306,22 @@ SpreadDelegate {
303306 xScale: priv.scale
304307 yScale: xScale
305308 },
309+ Scale {
310+ origin { x: 0; y: (spreadView.height * priv.scale) + maximizedAppTopMargin * 3 }
311+ xScale: 1
312+ yScale: isFullscreen ? 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height : 1
313+ },
306314 Translate {
307315 x: priv.xTranslate
308316 }
309317 ]
310318 opacity: priv.opacity
311− topMarginProgress: priv.topMarginProgress
312319
313320 EasingCurve {
314321 id: easingCurve
315322 type: EasingCurve.OutSine
316323 period: 1 - spreadView.positionMarker2
317− progress: root.animatedProgress
324+ progress: root.progress
318325 }
319326
320327 // This is used as a calculation helper to figure values for progress other than the current one
qml/Stages/TransformedTabletSpreadDelegate.qmlnew file+397
@@ -0,0 +1,397 @@
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 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+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+*/
18+
19+import QtQuick 2.0
20+import Utils 0.1
21+import Ubuntu.Components 0.1
22+import Unity.Application 0.1
23+
24+SpreadDelegate {
25+ id: root
26+
27+ // Set this to true when this tile is selected in the spread. The animation will change to bring the tile to front.
28+ property bool selected: false
29+ // Set this to true when another tile in the spread is selected. The animation will change to fade this tile out.
30+ property bool otherSelected: false
31+ // Set this to true when this tile a currently active on either the MS or the SS.
32+ property bool active: false
33+
34+ property int zIndex
35+ property real progress: 0
36+ property real animatedProgress: 0
37+
38+ property real startDistance: units.gu(5)
39+ property real endDistance: units.gu(.5)
40+
41+ property real startScale: 1.1
42+ property real endScale: 0.7
43+ property real dragStartScale: startScale + .2
44+
45+ property real startAngle: 15
46+ property real endAngle: 5
47+
48+ property bool isInSideStage: false
49+
50+ property int dragOffset: 0
51+
52+ dropShadow: spreadView.active ||
53+ (active && model.stage == ApplicationInfoInterface.MainStage && priv.xTranslate != 0)
54+
55+ onSelectedChanged: {
56+ if (selected) {
57+ priv.snapshot();
58+ }
59+ priv.isSelected = selected;
60+ }
61+
62+ onOtherSelectedChanged: {
63+ if (otherSelected) {
64+ priv.snapshot();
65+ }
66+ priv.otherSelected = otherSelected;
67+ }
68+
69+ Connections {
70+ target: spreadView
71+
72+ onPhaseChanged: {
73+ if (spreadView.phase == 1) {
74+ var phase2Progress = spreadView.positionMarker4 - (root.zIndex * spreadView.tileDistance / spreadView.width);
75+ priv.phase2StartTranslate = priv.easingAnimation(0, 1, 0, -spreadView.width + (root.zIndex * root.endDistance), phase2Progress);
76+ priv.phase2StartScale = priv.easingAnimation(0, 1, root.startScale, root.endScale, phase2Progress);
77+ priv.phase2StartAngle = priv.easingAnimation(0, 1, root.startAngle, root.endAngle, phase2Progress);
78+ priv.phase2StartTopMarginProgress = priv.easingAnimation(0, 1, 0, 1, phase2Progress);
79+ }
80+ }
81+ }
82+
83+ // Required to be an item because we're using states on it.
84+ Item {
85+ id: priv
86+
87+ // true if this is the next tile on the stack that comes in when dragging from the right
88+ property bool nextInStack: spreadView.nextZInStack == zIndex
89+ // true if the next tile in the stack is the nextInStack one. This one will be moved a bit to the left
90+ property bool movedActive: spreadView.nextZInStack == zIndex + 1
91+ property real animatedEndDistance: linearAnimation(0, 2, root.endDistance, 0, root.progress)
92+
93+ property real phase2StartTranslate
94+ property real phase2StartScale
95+ property real phase2StartAngle
96+ property real phase2StartTopMarginProgress
97+
98+ property bool isSelected: false
99+ property bool otherSelected: false
100+ property real selectedProgress
101+ property real selectedXTranslate
102+ property real selectedAngle
103+ property real selectedScale
104+ property real selectedOpacity
105+ property real selectedTopMarginProgress
106+
107+ function snapshot() {
108+ selectedProgress = root.progress;
109+ selectedXTranslate = xTranslate;
110+ selectedAngle = angle;
111+ selectedScale = priv.scale;
112+ selectedOpacity = priv.opacityTransform;
113+ selectedTopMarginProgress = topMarginProgress;
114+ }
115+
116+ // This calculates how much negative progress there can be if unwinding the spread completely
117+ // the progress for each tile starts at 0 when it crosses the right edge, so the later a tile comes in,
118+ // the bigger its negativeProgress can be.
119+ property real negativeProgress: {
120+ if (nextInStack && spreadView.phase < 2) {
121+ return 0;
122+ }
123+ return -root.zIndex * spreadView.tileDistance / spreadView.width;
124+ }
125+
126+ function linearAnimation(startProgress, endProgress, startValue, endValue, progress) {
127+ // progress : progressDiff = value : valueDiff => value = progress * valueDiff / progressDiff
128+ return (progress - startProgress) * (endValue - startValue) / (endProgress - startProgress) + startValue;
129+ }
130+
131+ function easingAnimation(startProgress, endProgress, startValue, endValue, progress) {
132+ helperEasingCurve.progress = progress - startProgress;
133+ helperEasingCurve.period = endProgress - startProgress;
134+ return helperEasingCurve.value * (endValue - startValue) + startValue;
135+ }
136+
137+ Behavior on xTranslate {
138+ enabled: !spreadView.active &&
139+ !snapAnimation.running &&
140+ model.appId !== "unity8-dash" &&
141+ !spreadView.sideStageDragging
142+ UbuntuNumberAnimation {
143+ duration: UbuntuAnimation.FastDuration
144+ }
145+ }
146+
147+ property real xTranslate: {
148+ var newTranslate = 0;
149+
150+ if (otherSelected) {
151+ return priv.selectedXTranslate;
152+ }
153+
154+ if (isSelected) {
155+ if (model.stage == ApplicationInfoInterface.MainStage) {
156+ return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, -spreadView.width, root.progress);
157+ } else {
158+ return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, -spreadView.sideStageWidth, root.progress);
159+ }
160+ }
161+
162+ // The tile should move a bit to the left if a new one comes on top of it, but not for the Side Stage and not
163+ // when we're only dragging the side stage in on top of a main stage app
164+ var shouldMoveAway = spreadView.nextInStack >= 0 && priv.movedActive && model.stage === ApplicationInfoInterface.MainStage &&
165+ ApplicationManager.get(spreadView.nextInStack).stage === ApplicationInfoInterface.MainStage;
166+
167+ if (active) {
168+ newTranslate -= root.width
169+ // Only do the hide animation for active apps in the mainstage, and not if we only drag the ss in
170+ if (spreadView.phase == 0 && shouldMoveAway) {
171+ newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -units.gu(4), root.animatedProgress);
172+ }
173+ newTranslate += root.dragOffset;
174+ }
175+ if (!spreadView.active && model.appId == "unity8-dash" && !root.active) {
176+ newTranslate -= root.width;
177+ }
178+
179+ if (nextInStack && spreadView.phase == 0) {
180+ if (model.stage == ApplicationInfoInterface.MainStage) {
181+ if (spreadView.sideStageVisible && root.progress > 0) {
182+ // Move it so it appears from behind the side stage immediately
183+ newTranslate += -spreadView.sideStageWidth;
184+ }
185+ }
186+
187+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
188+ // This is when we only drag the side stage in, without rotation or snapping
189+ newTranslate = linearAnimation(0, spreadView.positionMarker2, 0, -spreadView.sideStageWidth, root.progress);
190+ } else {
191+ newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -spreadView.sideStageWidth * spreadView.snapPosition, root.animatedProgress);
192+ }
193+ }
194+
195+ if (spreadView.phase == 1) {
196+ if (nextInStack) {
197+ if (model.stage == ApplicationInfoInterface.MainStage) {
198+ var startValue = -spreadView.sideStageWidth * spreadView.snapPosition + (spreadView.sideStageVisible ? -spreadView.sideStageWidth : 0);
199+ newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, startValue, priv.phase2StartTranslate, root.animatedProgress);
200+ } else {
201+ var endValue = -spreadView.width + spreadView.width * root.zIndex / 6;
202+ if (!spreadView.sideStageVisible) {
203+ newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, -spreadView.sideStageWidth, priv.phase2StartTranslate, root.progress);
204+ } else {
205+ newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, -spreadView.sideStageWidth * spreadView.snapPosition, priv.phase2StartTranslate, root.animatedProgress);
206+ }
207+ }
208+ } else if (root.active) {
209+ var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
210+ var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
211+ var startTranslate = -root.width + (shouldMoveAway ? -units.gu(4) : 0);
212+ newTranslate = linearAnimation(startProgress, endProgress, startTranslate, priv.phase2StartTranslate, root.progress);
213+ } else {
214+ var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
215+ var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
216+ newTranslate = linearAnimation(startProgress, endProgress, 0, priv.phase2StartTranslate, root.progress);
217+ }
218+ }
219+
220+ if (spreadView.phase == 2) {
221+ newTranslate = -easingCurve.value * (spreadView.width - root.zIndex * animatedEndDistance);
222+ }
223+
224+ return newTranslate;
225+ }
226+
227+ property real scale: {
228+ if (!spreadView.active) {
229+ return 1;
230+ }
231+
232+ if (otherSelected) {
233+ return selectedScale;
234+ }
235+
236+ if (isSelected) {
237+ return linearAnimation(selectedProgress, negativeProgress, selectedScale, 1, root.progress);
238+ }
239+
240+ if (spreadView.phase == 0) {
241+ if (nextInStack) {
242+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
243+ return 1;
244+ } else {
245+ var targetScale = root.dragStartScale - ((root.dragStartScale - 1) * spreadView.snapPosition);
246+ return linearAnimation(0, spreadView.positionMarker2, root.dragStartScale, targetScale, root.animatedProgress);
247+ }
248+ } else if (active) {
249+ return 1;
250+ } else {
251+ return linearAnimation(0, spreadView.positionMarker2, root.startScale, root.endScale, root.progress);
252+ }
253+ }
254+
255+ if (spreadView.phase == 1) {
256+ if (nextInStack) {
257+ var startScale = 1;
258+ if (model.stage !== ApplicationInfoInterface.SideStage || spreadView.sideStageVisible) {
259+ startScale = root.dragStartScale - ((root.dragStartScale - 1) * spreadView.snapPosition);
260+ }
261+ return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, startScale, priv.phase2StartScale, root.animatedProgress);
262+ }
263+ var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
264+ var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
265+ return linearAnimation(startProgress, endProgress, 1, priv.phase2StartScale, root.animatedProgress);
266+ }
267+
268+ if (spreadView.phase == 2) {
269+ return root.startScale - easingCurve.value * (root.startScale - root.endScale);
270+ }
271+
272+ return 1;
273+ }
274+
275+ property real angle: {
276+ if (!spreadView.active) {
277+ return 0;
278+ }
279+
280+ if (otherSelected) {
281+ return selectedAngle;
282+ }
283+ if (isSelected) {
284+ return linearAnimation(selectedProgress, negativeProgress, selectedAngle, 0, root.progress);
285+ }
286+
287+ // The tile should rotate a bit when another one comes on top, but not when only dragging the side stage in
288+ var shouldMoveAway = spreadView.nextInStack >= 0 && movedActive &&
289+ (ApplicationManager.get(spreadView.nextInStack).stage === ApplicationInfoInterface.MainStage ||
290+ model.stage == ApplicationInfoInterface.SideStage);
291+
292+ if (spreadView.phase == 0) {
293+ if (nextInStack) {
294+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
295+ return 0;
296+ } else {
297+ return linearAnimation(0, spreadView.positionMarker2, root.startAngle, root.startAngle * (1-spreadView.snapPosition), root.animatedProgress);
298+ }
299+ }
300+ if (shouldMoveAway) {
301+ return linearAnimation(0, spreadView.positionMarker2, 0, root.startAngle * (1-spreadView.snapPosition), root.animatedProgress);
302+ }
303+ }
304+ if (spreadView.phase == 1) {
305+ if (nextInStack) {
306+ if (model.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
307+ return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, 0, priv.phase2StartAngle, root.animatedProgress);
308+ } else {
309+ return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, root.startAngle * (1-spreadView.snapPosition), priv.phase2StartAngle, root.animatedProgress);
310+ }
311+ }
312+ var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
313+ var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
314+ var startAngle = shouldMoveAway ? root.startAngle * (1-spreadView.snapPosition) : 0;
315+ return linearAnimation(startProgress, endProgress, startAngle, priv.phase2StartAngle, root.progress);
316+ }
317+ if (spreadView.phase == 2) {
318+ return root.startAngle - easingCurve.value * (root.startAngle - root.endAngle);
319+ }
320+
321+ return 0;
322+ }
323+
324+ property real opacityTransform: {
325+ if (otherSelected && spreadView.phase == 2) {
326+ return linearAnimation(selectedProgress, negativeProgress, selectedOpacity, 0, root.progress);
327+ }
328+
329+ return 1;
330+ }
331+
332+ property real topMarginProgress: {
333+ if (priv.isSelected) {
334+ return linearAnimation(selectedProgress, negativeProgress, selectedTopMarginProgress, 0, root.progress);
335+ }
336+ switch (spreadView.phase) {
337+ case 0:
338+ return 0;
339+ case 1:
340+ return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
341+ 0, priv.phase2StartTopMarginProgress, root.progress);
342+ }
343+ return 1;
344+ }
345+
346+ states: [
347+ State {
348+ name: "sideStageDragging"; when: spreadView.sideStageDragging && root.isInSideStage
349+ PropertyChanges { target: priv; xTranslate: -spreadView.sideStageWidth + spreadView.sideStageWidth * spreadView.sideStageDragProgress }
350+ }
351+ ]
352+ }
353+
354+ transform: [
355+ Rotation {
356+ origin { x: 0; y: spreadView.height / 2 }
357+ axis { x: 0; y: 1; z: 0 }
358+ angle: priv.angle
359+ },
360+ Scale {
361+ origin { x: 0; y: spreadView.height / 2 }
362+ xScale: priv.scale
363+ yScale: xScale
364+ },
365+ Scale {
366+ origin { x: 0; y: (spreadView.height * priv.scale) + maximizedAppTopMargin * 3 }
367+ xScale: 1
368+ yScale: isFullscreen ? 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height : 1
369+ },
370+ Translate {
371+ x: priv.xTranslate
372+ }
373+ ]
374+ opacity: priv.opacityTransform
375+
376+ UbuntuNumberAnimation {
377+ id: fadeBackInAnimation
378+ target: root
379+ property: "opacity"
380+ duration: UbuntuAnimation.SlowDuration
381+ from: 0
382+ to: 1
383+ }
384+
385+ EasingCurve {
386+ id: easingCurve
387+ type: EasingCurve.OutSine
388+ period: 1
389+ progress: root.progress
390+ }
391+
392+ EasingCurve {
393+ id: helperEasingCurve
394+ type: easingCurve.type
395+ period: easingCurve.period
396+ }
397+}
run.sh+15−6
@@ -8,6 +8,7 @@ GDB=false
88FAKE=false
99PINLOCK=false
1010KEYLOCK=false
11+USE_MOCKS=false
1112MOUSE_TOUCH=true
1213
1314usage() {
@@ -31,9 +32,9 @@ eval set -- "$ARGS"
3132while [ $# -gt 0 ]
3233do
3334 case "$1" in
34− -f|--fake) FAKE=true;;
35− -p|--pinlock) PINLOCK=true;;
36− -k|--keylock) KEYLOCK=true;;
35+ -f|--fake) FAKE=true; USE_MOCKS=true;;
36+ -p|--pinlock) PINLOCK=true; USE_MOCKS=true;;
37+ -k|--keylock) KEYLOCK=true; USE_MOCKS=true;;
3738 -g|--gdb) GDB=true;;
3839 -h|--help) usage;;
3940 -m|--nomousetouch) MOUSE_TOUCH=false;;
@@ -43,20 +44,28 @@ do
4344done
4445
4546if $FAKE; then
46− export QML2_IMPORT_PATH=$QML2_IMPORT_PATH:$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules
4747 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single
4848fi
4949
5050if $PINLOCK; then
51− export QML2_IMPORT_PATH=$QML2_IMPORT_PATH:$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules
5251 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single-pin
5352fi
5453
5554if $KEYLOCK; then
56− export QML2_IMPORT_PATH=$QML2_IMPORT_PATH:$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules
5755 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single-passphrase
5856fi
5957
58+if $USE_MOCKS; then
59+ rm -f $PWD/builddir/nonmirplugins/LightDM # undo symlink (from below) for cleanliness
60+ export QML2_IMPORT_PATH=$QML2_IMPORT_PATH:$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules
61+else
62+ # Still fake no-login user for convenience (it's annoying to be prompted for your password when testing)
63+ # And in particular, just link our LightDM mock into the nonmirplugins folder. We don't want the rest of
64+ # our plugins to be used.
65+ ln -s $PWD/builddir/tests/mocks/LightDM $PWD/builddir/nonmirplugins/
66+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/LightDM/single
67+fi
68+
6069QML_PHONE_SHELL_ARGS=""
6170if $MOUSE_TOUCH; then
6271 QML_PHONE_SHELL_ARGS="$QML_PHONE_SHELL_ARGS -mousetouch"
run_on_device.sh+1−3
@@ -2,7 +2,6 @@
22CODE_DIR=shell
33USER=phablet
44USER_ID=32011
5−PASSWORD=phablet
65PACKAGE=unity8
76BINARY=unity8
87TARGET_IP=${TARGET_IP-127.0.0.1}
@@ -13,7 +12,6 @@ SETUP=false
1312GDB=false
1413PINLOCK=false
1514KEYLOCK=false
16−SUDO="echo $PASSWORD | sudo -S"
1715NUM_JOBS='$(( `grep -c ^processor /proc/cpuinfo` + 1 ))'
1816FLIPPED=false
1917CHROOT_PREFIX="/data/ubuntu"
@@ -76,7 +74,7 @@ setup_adb_forwarding() {
7674
7775install_dependencies() {
7876 exec_with_adb apt-get update
79− exec_with_ssh $SUDO apt-get -y install build-essential rsync bzr ccache gdb ninja-build devscripts equivs unity-plugin-scopes
77+ exec_with_adb apt-get -y --force-yes install build-essential rsync bzr ccache gdb ninja-build devscripts equivs unity-plugin-scopes
8078}
8179
8280sync_code() {
src/CMakeLists.txt+1−3
@@ -1,8 +1,5 @@
1−pkg_check_modules(UNITY-MIR REQUIRED unity-mir)
2−
31include_directories(
42 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
5− ${UNITY-MIR_INCLUDE_DIRS}
63)
74
85file(GLOB_RECURSE QML_FILES
@@ -38,3 +35,4 @@ install(TARGETS ${SHELL_APP}
3835 )
3936
4037add_subdirectory(Panel)
38+add_subdirectory(Dash)
src/Dash/CMakeLists.txtnew file+13
@@ -0,0 +1,13 @@
1+set(DASH_SRCS
2+ main.cpp
3+ ../MouseTouchAdaptor.cpp
4+)
5+
6+add_executable(unity8-dash ${DASH_SRCS})
7+
8+qt5_use_modules(unity8-dash Gui Qml Quick Test)
9+
10+# install binaries
11+install(TARGETS ${DASH_APP}
12+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
13+)
src/Dash/main.cppnew file+96
@@ -0,0 +1,96 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Michael Zanetti <michael.zanetti@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#include <QtQuick/QQuickView>
21+#include <QtGui/QGuiApplication>
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlContext>
24+#include <QDebug>
25+#include <QCommandLineParser>
26+#include <QLibrary>
27+#include <libintl.h>
28+
29+#include <paths.h>
30+#include "../MouseTouchAdaptor.h"
31+
32+int main(int argc, const char *argv[])
33+{
34+ QGuiApplication *application = new QGuiApplication(argc, (char**)argv);
35+
36+ QCommandLineParser parser;
37+ parser.setApplicationDescription("Description: Unity 8 Shell Dash");
38+ parser.addHelpOption();
39+
40+ QCommandLineOption mousetouchOption("mousetouch",
41+ "Allow the mouse to provide touch input");
42+ parser.addOption(mousetouchOption);
43+
44+ // FIXME Remove once we drop the need of the hint
45+ QCommandLineOption desktopFileHintOption("desktop_file_hint",
46+ "The desktop_file_hint option for QtMir", "hint_file");
47+ parser.addOption(desktopFileHintOption);
48+
49+ // Treat args with single dashes the same as arguments with two dashes
50+ // Ex: -fullscreen == --fullscreen
51+ parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
52+ parser.process(*application);
53+
54+ if (getenv("QT_LOAD_TESTABILITY")) {
55+ QLibrary testLib(QLatin1String("qttestability"));
56+ if (testLib.load()) {
57+ typedef void (*TasInitialize)(void);
58+ TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
59+ if (initFunction) {
60+ initFunction();
61+ } else {
62+ qCritical("Library qttestability resolve failed!");
63+ }
64+ } else {
65+ qCritical("Library qttestability load failed!");
66+ }
67+ }
68+
69+ bindtextdomain("unity8", translationDirectory().toUtf8().data());
70+
71+ QQuickView* view = new QQuickView();
72+ view->setResizeMode(QQuickView::SizeRootObjectToView);
73+ view->setTitle("Unity Dash");
74+
75+ // You will need this if you want to interact with touch-only components using a mouse
76+ // Needed only when manually testing on a desktop.
77+ MouseTouchAdaptor *mouseTouchAdaptor = 0;
78+ if (parser.isSet(mousetouchOption)) {
79+ mouseTouchAdaptor = new MouseTouchAdaptor;
80+ application->installNativeEventFilter(mouseTouchAdaptor);
81+ }
82+
83+ QUrl source(::qmlDirectory()+"Dash/DashApplication.qml");
84+ prependImportPaths(view->engine(), ::overrideImportPaths());
85+ appendImportPaths(view->engine(), ::fallbackImportPaths());
86+
87+ view->setSource(source);
88+ view->show();
89+
90+ int result = application->exec();
91+
92+ delete view;
93+ delete application;
94+
95+ return result;
96+}
src/main.cpp+21−89
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012 Canonical, Ltd.
2+ * Copyright (C) 2012-2014 Canonical, Ltd.
33 *
44 * Authors:
55 * Gerry Boland <gerry.boland@canonical.com>
@@ -23,12 +23,10 @@
2323#include <QtGui/QGuiApplication>
2424#include <QtQml/QQmlEngine>
2525#include <QtQml/QQmlContext>
26−#include <qpa/qplatformnativeinterface.h>
2726#include <QLibrary>
2827#include <QDebug>
29−#include <libintl.h>
30−#include <dlfcn.h>
3128#include <csignal>
29+#include <libintl.h>
3230
3331// local
3432#include <paths.h>
@@ -36,11 +34,13 @@
3634#include "ApplicationArguments.h"
3735#include "CachingNetworkManagerFactory.h"
3836
39−#include <unity-mir/qmirserver.h>
40−
41−int startShell(int argc, const char** argv, void* server)
37+int main(int argc, const char *argv[])
4238{
43− const bool isUbuntuMirServer = qgetenv("QT_QPA_PLATFORM") == "ubuntumirserver";
39+ bool isMirServer = false;
40+ if (qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient") {
41+ setenv("QT_QPA_PLATFORM", "mirserver", 1 /* overwrite */);
42+ isMirServer = true;
43+ }
4444
4545 QGuiApplication::setApplicationName("unity8");
4646 QGuiApplication *application;
@@ -70,21 +70,7 @@ int startShell(int argc, const char** argv, void* server)
7070Load the testability driver");
7171 parser.addOption(testabilityOption);
7272
73− if (isUbuntuMirServer) {
74− QLibrary unityMir("unity-mir", 1);
75− unityMir.load();
76−
77− typedef QGuiApplication* (*createServerApplication_t)(int&, const char **, void*);
78− createServerApplication_t createQMirServerApplication = (createServerApplication_t) unityMir.resolve("createQMirServerApplication");
79− if (!createQMirServerApplication) {
80− qDebug() << "unable to resolve symbol: createQMirServerApplication";
81− return 4;
82− }
83−
84− application = createQMirServerApplication(argc, argv, server);
85− } else {
86− application = new QGuiApplication(argc, (char**)argv);
87− }
73+ application = new QGuiApplication(argc, (char**)argv);
8874
8975 // Treat args with single dashes the same as arguments with two dashes
9076 // Ex: -fullscreen == --fullscreen
@@ -100,8 +86,8 @@ Load the testability driver");
10086 if (parser.isSet(windowGeometryOption) &&
10187 parser.value(windowGeometryOption).split('x').size() == 2)
10288 {
103− QStringList geom = parser.value(windowGeometryOption).split('x');
104− qmlArgs.setSize(geom.at(0).toInt(), geom.at(1).toInt());
89+ QStringList geom = parser.value(windowGeometryOption).split('x');
90+ qmlArgs.setSize(geom.at(0).toInt(), geom.at(1).toInt());
10591 }
10692
10793 // The testability driver is only loaded by QApplication but not by QGuiApplication.
@@ -125,7 +111,8 @@ Load the testability driver");
125111
126112 QQuickView* view = new QQuickView();
127113 view->setResizeMode(QQuickView::SizeRootObjectToView);
128− view->setTitle("Qml Phone Shell");
114+ view->setColor("black");
115+ view->setTitle("Unity8 Shell");
129116 view->engine()->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory()));
130117 view->rootContext()->setContextProperty("applicationArguments", &qmlArgs);
131118 view->rootContext()->setContextProperty("indicatorProfile", indicatorProfile);
@@ -141,18 +128,9 @@ Load the testability driver");
141128 application->installNativeEventFilter(mouseTouchAdaptor);
142129 }
143130
144− QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface();
145− /* Shell is declared as a system session so that it always receives all
146− input events.
147− FIXME: use the enum value corresponding to SYSTEM_SESSION_TYPE (= 1)
148− when it becomes available.
149− */
150− nativeInterface->setProperty("ubuntuSessionType", 1);
151− view->setProperty("role", 2); // INDICATOR_ACTOR_ROLE
152−
153131 QUrl source(::qmlDirectory()+"Shell.qml");
154132 prependImportPaths(view->engine(), ::overrideImportPaths());
155− if (!isUbuntuMirServer) {
133+ if (!isMirServer) {
156134 prependImportPaths(view->engine(), ::nonMirImportPaths());
157135 }
158136 appendImportPaths(view->engine(), ::fallbackImportPaths());
@@ -161,10 +139,15 @@ Load the testability driver");
161139 view->engine()->setNetworkAccessManagerFactory(managerFactory);
162140
163141 view->setSource(source);
164− view->setColor("transparent");
165142 QObject::connect(view->engine(), SIGNAL(quit()), application, SLOT(quit()));
166143
167− if (qgetenv("QT_QPA_PLATFORM") == "ubuntu" || isUbuntuMirServer || parser.isSet(fullscreenOption)) {
144+ if (!isMirServer && qEnvironmentVariableIsSet("UNITY_MIR_EMITS_SIGSTOP")) {
145+ // Emit SIGSTOP as expected by upstart, under Mir it's qtmir that will raise it.
146+ // see http://upstart.ubuntu.com/cookbook/#expect-stop
147+ raise(SIGSTOP);
148+ }
149+
150+ if (isMirServer || parser.isSet(fullscreenOption)) {
168151 view->showFullScreen();
169152 } else {
170153 view->show();
@@ -178,54 +161,3 @@ Load the testability driver");
178161
179162 return result;
180163}
181−
182−int main(int argc, const char *argv[])
183−{
184− /* Workaround Qt platform integration plugin not advertising itself
185− as having the following capabilities:
186− - QPlatformIntegration::ThreadedOpenGL
187− - QPlatformIntegration::BufferQueueingOpenGL
188− */
189− setenv("QML_FORCE_THREADED_RENDERER", "1", 1);
190− setenv("QML_FIXED_ANIMATION_STEP", "1", 1);
191−
192− // For ubuntumirserver/ubuntumirclient
193− if (qgetenv("QT_QPA_PLATFORM").startsWith("ubuntumir")) {
194− setenv("QT_QPA_PLATFORM", "ubuntumirserver", 1);
195−
196− // If we use unity-mir directly, we automatically link to the Mir-server
197− // platform-api bindings, which result in unexpected behaviour when
198− // running the non-Mir scenario.
199− QLibrary unityMir("unity-mir", 1);
200− unityMir.load();
201− if (!unityMir.isLoaded()) {
202− qDebug() << "Library unity-mir not found/loaded";
203− return 1;
204− }
205−
206− typedef QMirServer* (*createServer_t)(int, const char **);
207− createServer_t createQMirServer = (createServer_t) unityMir.resolve("createQMirServer");
208− if (!createQMirServer) {
209− qDebug() << "unable to resolve symbol: createQMirServer";
210− return 2;
211− }
212−
213− QMirServer* mirServer = createQMirServer(argc, argv);
214−
215− typedef int (*runWithClient_t)(QMirServer*, std::function<int(int, const char**, void*)>);
216− runWithClient_t runWithClient = (runWithClient_t) unityMir.resolve("runQMirServerWithClient");
217− if (!runWithClient) {
218− qDebug() << "unable to resolve symbol: runWithClient";
219− return 3;
220− }
221−
222− return runWithClient(mirServer, startShell);
223− } else {
224− if (qgetenv("UPSTART_JOB") == "unity8") {
225− // Emit SIGSTOP as expected by upstart, under Mir it's unity-mir that will raise it.
226− // see http://upstart.ubuntu.com/cookbook/#expect-stop
227− raise(SIGSTOP);
228− }
229− return startShell(argc, argv, nullptr);
230− }
231−}
tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+1−1
@@ -106,7 +106,7 @@ class ApplicationLifecycleTests(tests.ApplicationLifeCycleTestCase):
106106 self.assert_current_focused_application(application_name)
107107
108108 self.main_window.show_dash_swiping()
109− self.assert_current_focused_application('')
109+ self.assert_current_focused_application('unity8-dash')
110110
111111 process_helpers.lock_unity()
112112 greeter = self.main_window.get_greeter()
tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.py+3−2
@@ -39,7 +39,8 @@ class URLDispatcherTestCase(tests.ApplicationLifeCycleTestCase):
3939 desktop_file_name = os.path.basename(desktop_file_path)
4040 application_name, _ = os.path.splitext(desktop_file_name)
4141
42− self.assertEqual('', self.main_window.get_current_focused_app_id())
42+ self.assertEqual(
43+ 'unity8-dash', self.main_window.get_current_focused_app_id())
4344 self.addCleanup(os.system, 'pkill qmlscene')
4445
4546 subprocess.check_call(
@@ -47,4 +48,4 @@ class URLDispatcherTestCase(tests.ApplicationLifeCycleTestCase):
4748 self.assert_current_focused_application(application_name)
4849
4950 self.main_window.show_dash_swiping()
50− self.assert_current_focused_application('')
51+ self.assert_current_focused_application('unity8-dash')
tests/autopilot/unity8/fixture_setup.pynew file+64
@@ -0,0 +1,64 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2014 Canonical
5+#
6+# This program is free software: you can redistribute it and/or modify
7+# it under the terms of the GNU General Public License as published by
8+# the Free Software Foundation, either version 3 of the License, or
9+# (at your option) any later version.
10+#
11+# This program is distributed in the hope that it will be useful,
12+# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+# GNU General Public License for more details.
15+#
16+# You should have received a copy of the GNU General Public License
17+# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+#
19+
20+import fixtures
21+from autopilot import introspection
22+
23+from unity8 import process_helpers
24+from unity8.shell import emulators
25+
26+
27+class LaunchDashApp(fixtures.Fixture):
28+
29+ """Fixture to launch the Dash app."""
30+
31+ def __init__(self, binary_path, variables):
32+ """Initialize an instance.
33+
34+ :param str binary_path: The path to the Dash app binary.
35+ :param variables: The variables to use when launching the app.
36+ :type variables: A dictionary.
37+
38+ """
39+ super(LaunchDashApp, self).__init__()
40+ self.binary_path = binary_path
41+ self.variables = variables
42+
43+ def setUp(self):
44+ """Launch the dash app when the fixture is used."""
45+ super(LaunchDashApp, self).setUp()
46+ self.addCleanup(self.stop_application)
47+ self.application_proxy = self.launch_application()
48+
49+ def launch_application(self):
50+ binary_arg = 'BINARY={}'.format(self.binary_path)
51+ testability_arg = 'QT_LOAD_TESTABILITY={}'.format(1)
52+ env_args = [
53+ '{}={}'.format(key, value) for key, value in self.variables.items()
54+ ]
55+ all_args = [binary_arg, testability_arg] + env_args
56+
57+ pid = process_helpers.start_job('unity8-dash', *all_args)
58+ return introspection.get_proxy_object_for_existing_process(
59+ pid=pid,
60+ emulator_base=emulators.UnityEmulatorBase,
61+ )
62+
63+ def stop_application(self):
64+ process_helpers.stop_job('unity8-dash')
tests/autopilot/unity8/process_helpers.py+89−20
@@ -36,6 +36,10 @@ from unity8.shell.emulators import main_window as main_window_emulator
3636logger = logging.getLogger(__name__)
3737
3838
39+class JobError(Exception):
40+ pass
41+
42+
3943class CannotAccessUnity(Exception):
4044 pass
4145
@@ -134,48 +138,113 @@ def restart_unity(*args):
134138 """
135139 status = _get_unity_status()
136140 if "start/" in status:
137− try:
138− output = subprocess.check_output(
139− ['/sbin/initctl', 'stop', 'unity8'])
140− logger.info(output)
141− except subprocess.CalledProcessError as e:
142− e.args += (
143− "Failed to stop running instance of unity8: %s" % e.output,
144− )
145− raise
141+ stop_job('unity8')
142+
143+ pid = start_job('unity8', *args)
144+ return _get_unity_proxy_object(pid)
146145
146+
147+def start_job(name, *args):
148+ """Start a job.
149+
150+ :param str name: The name of the job.
151+ :param args: The arguments to be used when starting the job.
152+ :return: The process id of the started job.
153+ :raises CalledProcessError: if the job failed to start.
154+
155+ """
156+ logger.info('Starting job {} with arguments {}.'.format(name, args))
157+ command = ['/sbin/initctl', 'start', name] + list(args)
147158 try:
148− command = ['/sbin/initctl', 'start', 'unity8'] + list(args)
149159 output = subprocess.check_output(
150160 command,
151161 stderr=subprocess.STDOUT,
152162 universal_newlines=True,
153163 )
154164 logger.info(output)
155− pid = _get_unity_pid()
165+ pid = get_job_pid(name)
156166 except subprocess.CalledProcessError as e:
157− e.args += ("Failed to start unity8: %s" % e.output,)
167+ e.args += ('Failed to start {}: {}.'.format(name, e.output),)
158168 raise
159169 else:
160− return _get_unity_proxy_object(pid)
170+ return pid
161171
162172
163−def _get_unity_status():
173+def get_job_pid(name):
174+ """Return the process id of a running job.
175+
176+ :param str name: The name of the job.
177+ :raises JobError: if the job is not running.
178+
179+ """
180+ status = get_job_status(name)
181+ if "start/" not in status:
182+ raise JobError('{} is not in the running state.'.format(name))
183+ return int(status.split()[-1])
184+
185+
186+def get_job_status(name):
187+ """Return the status of a job.
188+
189+ :param str name: The name of the job.
190+ :raises JobError: if it's not possible to get the status of the job.
191+
192+ """
164193 try:
165194 return subprocess.check_output([
166195 '/sbin/initctl',
167196 'status',
168− 'unity8'
197+ name
169198 ], universal_newlines=True)
199+ except subprocess.CalledProcessError as error:
200+ raise JobError(
201+ "Unable to get {}'s status: {}".format(name, error)
202+ )
203+
204+
205+def stop_job(name):
206+ """Stop a job.
207+
208+ :param str name: The name of the job.
209+ :raises CalledProcessError: if the job failed to stop.
210+
211+ """
212+ logger.info('Stoping job {}.'.format(name))
213+ command = ['/sbin/initctl', 'stop', name]
214+ try:
215+ output = subprocess.check_output(
216+ command,
217+ stderr=subprocess.STDOUT,
218+ universal_newlines=True,
219+ )
220+ logger.info(output)
170221 except subprocess.CalledProcessError as e:
171− raise CannotAccessUnity("Unable to get unity's status: %s" % str(e))
222+ e.args += ('Failed to stop {}: {}.'.format(name, e.output),)
223+ raise
224+
225+
226+def is_job_running(name):
227+ """Return True if the job is running. Otherwise, False.
228+
229+ :param str name: The name of the job.
230+ :raises JobError: if it's not possible to get the status of the job.
231+
232+ """
233+ return 'start/' in get_job_status(name)
234+
235+
236+def _get_unity_status():
237+ try:
238+ return get_job_status('unity8')
239+ except JobError as error:
240+ raise CannotAccessUnity(str(error))
172241
173242
174243def _get_unity_pid():
175− status = _get_unity_status()
176− if "start/" not in status:
177− raise CannotAccessUnity("Unity is not in the running state.")
178− return int(status.split()[-1])
244+ try:
245+ return get_job_pid('unity8')
246+ except JobError as error:
247+ raise CannotAccessUnity(str(error))
179248
180249
181250def _get_unity_proxy_object(pid):
tests/autopilot/unity8/shell/emulators/dash.py+34−19
@@ -18,6 +18,7 @@
1818#
1919
2020import logging
21+import ubuntuuitoolkit
2122
2223from unity8.shell import emulators
2324
@@ -30,6 +31,17 @@ from ubuntuuitoolkit import emulators as toolkit_emulators
3031logger = logging.getLogger(__name__)
3132
3233
34+class DashApp(object):
35+
36+ """Autopilot helper for the Dash app."""
37+
38+ def __init__(self, app_proxy):
39+ self.app_proxy = app_proxy
40+ self.main_view = self.app_proxy.select_single(
41+ toolkit_emulators.MainView)
42+ self.dash = self.main_view.select_single(Dash)
43+
44+
3345class Dash(emulators.UnityEmulatorBase):
3446 """An emulator that understands the Dash."""
3547
@@ -40,7 +52,7 @@ class Dash(emulators.UnityEmulatorBase):
4052
4153 def get_applications_grid(self):
4254 get_grid = self.get_scope('clickscope').wait_select_single(
43− 'CardFilterGrid', objectName='local')
55+ 'CardGrid', objectName='local')
4456 return get_grid
4557
4658 def get_application_icon(self, text):
@@ -108,35 +120,37 @@ class Dash(emulators.UnityEmulatorBase):
108120 @autopilot_logging.log_action(logger.info)
109121 def _scroll_to_left_scope(self):
110122 original_index = self.dash_content_list.currentIndex
111− dashContent = self.select_single(objectName="dashContent")
112− start_x = dashContent.width / 3
113− stop_x = dashContent.width / 3 * 2
114− start_y = stop_y = dashContent.globalRect.y + 1
123+ dash_content = self.select_single(objectName="dashContent")
124+ x, y, width, height = dash_content.globalRect
125+ start_x = x + width / 3
126+ stop_x = x + width / 3 * 2
127+ start_y = stop_y = y + 1
115128 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
116129 self.dash_content_list.currentIndex.wait_for(original_index - 1)
117130
118131 @autopilot_logging.log_action(logger.info)
119132 def _scroll_to_right_scope(self):
120133 original_index = self.dash_content_list.currentIndex
121− dashContent = self.select_single(objectName="dashContent")
122− start_x = dashContent.width / 3 * 2
123− stop_x = dashContent.width / 3
124− start_y = stop_y = dashContent.globalRect.y + 1
134+ dash_content = self.select_single(objectName="dashContent")
135+ x, y, width, height = dash_content.globalRect
136+ start_x = x + width / 3 * 2
137+ stop_x = x + width / 3
138+ start_y = stop_y = y + 1
125139 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
126140 self.dash_content_list.currentIndex.wait_for(original_index + 1)
127141
128142 def enter_search_query(self, query):
129143 current_header = self._get_current_page_header()
130144 self.pointing_device.move(current_header.globalRect.x +
131− current_header.width - current_header.height / 2,
145+ current_header.width - current_header.height / 4,
132146 current_header.globalRect.y +
133− current_header.height / 2)
147+ current_header.height / 4)
134148 self.pointing_device.click()
135149 headerContainer = current_header.select_single(objectName="headerContainer")
136150 headerContainer.contentY.wait_for(0)
137151 search_text_field = self._get_search_text_field()
138152 search_text_field.write(query)
139− current_header.select_single(objectName="searchIndicator").running.wait_for(False)
153+ self.select_single(objectName="processingIndicator").visible.wait_for(False)
140154
141155 def _get_search_text_field(self):
142156 page_header = self._get_current_page_header()
@@ -151,6 +165,10 @@ class Dash(emulators.UnityEmulatorBase):
151165 return None
152166
153167
168+class ListViewWithPageHeader(ubuntuuitoolkit.QQuickFlickable):
169+ pass
170+
171+
154172class GenericScopeView(emulators.UnityEmulatorBase):
155173 """Autopilot emulator for generic scopes."""
156174
@@ -183,10 +201,6 @@ class GenericScopeView(emulators.UnityEmulatorBase):
183201 raise emulators.UnityEmulatorException(
184202 'No category found with name {}'.format(category))
185203
186−
187−class DashApps(GenericScopeView):
188− """Autopilot emulator for the applications scope."""
189−
190204 def get_applications(self, category):
191205 """Return the list of applications on a category.
192206
@@ -194,16 +208,17 @@ class DashApps(GenericScopeView):
194208
195209 """
196210 category_element = self._get_category_element(category)
211+ see_all = category_element.select_single(objectName='seeAll')
197212 application_cards = category_element.select_many('AbstractButton')
198213
199− # sort by y, x
200214 application_cards = sorted(
201− application_cards,
215+ (card for card in application_cards
216+ if card.globalRect.y < see_all.globalRect.y),
202217 key=lambda card: (card.globalRect.y, card.globalRect.x))
203218
204219 result = []
205220 for card in application_cards:
206− if card.objectName != 'cardToolCard':
221+ if card.objectName not in ('cardToolCard', 'seeAll'):
207222 result.append(card.title)
208223 return result
209224
tests/autopilot/unity8/shell/emulators/greeter.py+4−1
@@ -17,6 +17,8 @@
1717# along with this program. If not, see <http://www.gnu.org/licenses/>.
1818#
1919
20+import ubuntuuitoolkit
21+
2022from unity8.shell.emulators import UnityEmulatorBase
2123
2224
@@ -37,4 +39,5 @@ class Greeter(UnityEmulatorBase):
3739 self.created.wait_for(False)
3840
3941 def get_prompt(self):
40− return self.select_single("TextField", objectName="passwordInput")
42+ return self.select_single(
43+ ubuntuuitoolkit.TextField, objectName='passwordInput')
tests/autopilot/unity8/shell/emulators/main_window.py+34−20
@@ -25,7 +25,6 @@ from autopilot import input
2525from unity8.shell import emulators
2626from unity8.shell.emulators.greeter import Greeter
2727from unity8.shell.emulators.hud import Hud
28−from unity8.shell.emulators.dash import Dash
2928from unity8.shell.emulators.launcher import Launcher
3029
3130logger = logging.getLogger(__name__)
@@ -61,9 +60,6 @@ class QQuickView(emulators.UnityEmulatorBase):
6160 def get_hud_edge_drag_area(self):
6261 return self.select_single(objectName="hudDragArea")
6362
64− def get_dash(self):
65− return self.select_single(Dash)
66−
6763 def get_bottombar(self):
6864 return self.select_single("Bottombar")
6965
@@ -76,12 +72,6 @@ class QQuickView(emulators.UnityEmulatorBase):
7672 objectName="pinPadLoader"
7773 )
7874
79− def get_pinPadButton(self, buttonId):
80− return self.select_single(
81− "PinPadButton",
82− objectName="pinPadButton%i" % buttonId
83− )
84−
8575 def get_lockscreen(self):
8676 return self.select_single("Lockscreen")
8777
@@ -117,20 +107,44 @@ class QQuickView(emulators.UnityEmulatorBase):
117107 @autopilot_logging.log_action(logger.info)
118108 def show_dash_swiping(self):
119109 """Show the dash swiping from the left."""
120− width = self.width
121− height = self.height
122− start_x = 0
123− start_y = height // 2
124− end_x = width
125− end_y = start_y
110+ x, y, width, height = self._get_shell().globalRect
111+ start_x = x
112+ end_x = x + width
113+ start_y = end_y = y + height // 2
126114
127115 self.pointing_device.drag(start_x, start_y, end_x, end_y)
128− return self.get_dash()
116+
117+ def _get_shell(self):
118+ return self.select_single('Shell')
129119
130120 def get_current_focused_app_id(self):
131121 """Return the id of the focused application."""
132− return self.select_single('Shell').focusedApplicationId
122+ return self._get_shell().focusedApplicationId
133123
134124 @autopilot_logging.log_action(logger.info)
135− def search(self, query):
136− self.get_dash().enter_search_query(query)
125+ def enter_pin_code(self, code):
126+ """Enter code 'code' into the single-pin lightdm pincode entry screen.
127+
128+ :param code: must be a string of numeric characters.
129+ :raises: TypeError if code is not a string.
130+ :raises: ValueError if code contains non-numeric characters.
131+
132+ """
133+ if not isinstance(code, str):
134+ raise TypeError(
135+ "'code' parameter must be a string, not %r."
136+ % type(code)
137+ )
138+ for num in code:
139+ if not num.isdigit():
140+ raise ValueError(
141+ "'code' parameter contains non-numeric characters."
142+ )
143+ self.pointing_device.click_object(
144+ self._get_pinpad_button(int(num)))
145+
146+ def _get_pinpad_button(self, button_id):
147+ return self.select_single(
148+ 'PinPadButton',
149+ objectName='pinPadButton{}'.format(button_id)
150+ )
tests/autopilot/unity8/shell/tests/__init__.py+141−48
@@ -24,6 +24,7 @@ try:
2424except ImportError:
2525 Gio = None
2626
27+from autopilot import introspection
2728from autopilot.platform import model
2829from autopilot.testcase import AutopilotTestCase
2930from autopilot.matchers import Eventually
@@ -34,6 +35,10 @@ import os.path
3435import subprocess
3536import sys
3637from testtools.matchers import Equals
38+from ubuntuuitoolkit import (
39+ fixture_setup as toolkit_fixtures,
40+ ubuntu_scenarios
41+)
3742
3843from unity8 import (
3944 get_lib_path,
@@ -42,9 +47,15 @@ from unity8 import (
4247 get_default_extra_mock_libraries,
4348 get_data_dirs
4449)
45−from unity8.process_helpers import restart_unity_with_testability
46−from unity8.shell.emulators import main_window as main_window_emulator
47−from unity8.shell.emulators.dash import Dash
50+from unity8 import (
51+ fixture_setup,
52+ process_helpers
53+)
54+from unity8.shell import emulators
55+from unity8.shell.emulators import (
56+ dash as dash_helpers,
57+ main_window as main_window_emulator,
58+)
4859
4960
5061logger = logging.getLogger(__name__)
@@ -78,6 +89,26 @@ def _get_device_emulation_scenarios(devices='All'):
7889 return [native]
7990
8091
92+def is_unity7_running():
93+ """Return True if Unity7 is running. Otherwise, return False."""
94+ return (
95+ Gio is not None and
96+ UNITYSHELL_GSETTINGS_SCHEMA in
97+ Gio.Settings.list_relocatable_schemas()
98+ )
99+
100+
101+def get_qml_import_path_with_mock():
102+ """Return the QML2_IMPORT_PATH value with the mock path prepended."""
103+ qml_import_path = [get_mocks_library_path()]
104+ if os.getenv('QML2_IMPORT_PATH') is not None:
105+ qml_import_path.append(os.getenv('QML2_IMPORT_PATH'))
106+
107+ qml_import_path = ':'.join(qml_import_path)
108+ logger.info("New QML2 import path: %s", qml_import_path)
109+ return qml_import_path
110+
111+
81112class UnityTestCase(AutopilotTestCase):
82113
83114 """A test case base class for the Unity shell tests."""
@@ -118,23 +149,8 @@ class UnityTestCase(AutopilotTestCase):
118149
119150 def setUp(self):
120151 super(UnityTestCase, self).setUp()
121− if (Gio is not None and
122− UNITYSHELL_GSETTINGS_SCHEMA in
123− Gio.Settings.list_relocatable_schemas()):
124−
125− # Hide Unity launcher
126− self._unityshell_schema = Gio.Settings.new_with_path(
127− UNITYSHELL_GSETTINGS_SCHEMA,
128− UNITYSHELL_GSETTINGS_PATH,
129− )
130− self._launcher_hide_mode = self._unityshell_schema.get_int(
131− UNITYSHELL_LAUNCHER_KEY,
132− )
133− self._unityshell_schema.set_int(
134− UNITYSHELL_LAUNCHER_KEY,
135− UNITYSHELL_LAUNCHER_MODE,
136− )
137− self.addCleanup(self._reset_launcher)
152+ if is_unity7_running():
153+ self.useFixture(toolkit_fixtures.HideUnity7Launcher())
138154
139155 self._proxy = None
140156 self._lightdm_mock_type = None
@@ -151,13 +167,6 @@ class UnityTestCase(AutopilotTestCase):
151167 self.touch = Touch.create()
152168 self._setup_display_details()
153169
154− def _reset_launcher(self):
155− """Reset Unity launcher hide mode"""
156− self._unityshell_schema.set_int(
157− UNITYSHELL_LAUNCHER_KEY,
158− self._launcher_hide_mode,
159− )
160−
161170 def _setup_display_details(self):
162171 scale_divisor = self._determine_geometry()
163172 self._setup_grid_size(scale_divisor)
@@ -263,7 +272,9 @@ class UnityTestCase(AutopilotTestCase):
263272 self.patch_lightdm_mock()
264273
265274 if self._qml_mock_enabled:
266− self._setup_extra_mock_environment_patch()
275+ self._environment['QML2_IMPORT_PATH'] = (
276+ get_qml_import_path_with_mock()
277+ )
267278
268279 if self._data_dirs_mock_enabled:
269280 self._patch_data_dirs()
@@ -292,9 +303,14 @@ class UnityTestCase(AutopilotTestCase):
292303
293304 # Ensure that the dash is visible before we return:
294305 logger.debug("Unity started, waiting for it to be ready.")
295− self.assertUnityReady()
306+ self.wait_for_unity()
296307 logger.debug("Unity loaded and ready.")
297308
309+ if model() == 'Desktop':
310+ # On desktop, close the dash because it's opened in a separate
311+ # window and it gets in the way.
312+ process_helpers.stop_job('unity8-dash')
313+
298314 return app_proxy
299315
300316 def _launch_unity_with_upstart(self, binary_path, args):
@@ -308,7 +324,7 @@ class UnityTestCase(AutopilotTestCase):
308324
309325 self.addCleanup(self._cleanup_launching_upstart_unity)
310326
311− return restart_unity_with_testability(*all_args)
327+ return process_helpers.restart_unity_with_testability(*all_args)
312328
313329 def _cleanup_launching_upstart_unity(self):
314330 logger.info("Stopping unity")
@@ -353,15 +369,6 @@ class UnityTestCase(AutopilotTestCase):
353369 )
354370 return lightdm_mock_path
355371
356− def _setup_extra_mock_environment_patch(self):
357− qml_import_path = [get_mocks_library_path()]
358− if os.getenv('QML2_IMPORT_PATH') is not None:
359− qml_import_path.append(os.getenv('QML2_IMPORT_PATH'))
360−
361− qml_import_path = ':'.join(qml_import_path)
362− logger.info("New QML2 import path: %s", qml_import_path)
363− self._environment['QML2_IMPORT_PATH'] = qml_import_path
364−
365372 def _set_proxy(self, proxy):
366373 """Keep a copy of the proxy object, so we can use it to get common
367374 parts of the shell later on.
@@ -373,10 +380,80 @@ class UnityTestCase(AutopilotTestCase):
373380 def _clear_proxy(self):
374381 self._proxy = None
375382
376− def assertUnityReady(self):
377− dash = self.get_dash()
378− home_scope = dash.get_scope('clickscope')
383+ def wait_for_unity(self):
384+ greeter_content_loader = self.main_window.wait_select_single(
385+ objectName='greeterContentLoader')
386+ greeter_content_loader.progress.wait_for(1)
387+
388+ def get_dash(self):
389+ pid = process_helpers.get_job_pid('unity8-dash')
390+ dash_proxy = introspection.get_proxy_object_for_existing_process(
391+ pid=pid,
392+ emulator_base=emulators.UnityEmulatorBase,
393+ )
394+ dash_app = dash_helpers.DashApp(dash_proxy)
395+ return dash_app.dash
396+
397+ @property
398+ def main_window(self):
399+ return self._proxy.select_single(main_window_emulator.QQuickView)
379400
401+
402+class DashBaseTestCase(AutopilotTestCase):
403+
404+ scenarios = ubuntu_scenarios.get_device_simulation_scenarios()
405+ qml_mock_enabled = True
406+ environment = {}
407+
408+ def setUp(self):
409+ super(DashBaseTestCase, self).setUp()
410+
411+ if is_unity7_running():
412+ self.useFixture(toolkit_fixtures.HideUnity7Launcher())
413+
414+ if model() != 'Desktop':
415+ # On the phone, we need unity to be running and unlocked.
416+ self.addCleanup(process_helpers.stop_job, 'unity8')
417+ process_helpers.restart_unity_with_testability()
418+ process_helpers.unlock_unity()
419+
420+ self.ensure_dash_not_running()
421+
422+ if self.qml_mock_enabled:
423+ self.environment['QML2_IMPORT_PATH'] = (
424+ get_qml_import_path_with_mock()
425+ )
426+
427+ if self.should_simulate_device():
428+ # This sets the grid units, so it should be called before launching
429+ # the app.
430+ self.simulate_device()
431+
432+ binary_path = get_binary_path('unity8-dash')
433+ dash_proxy = self.launch_dash(binary_path, self.environment)
434+
435+ if self.should_simulate_device():
436+ # XXX Currently we have no way to launch the application with a
437+ # specific size, so we must resize it after it's launched.
438+ # --elopio - 2014-06-25
439+ self.resize_window()
440+
441+ self.dash_app = dash_helpers.DashApp(dash_proxy)
442+ self.dash = self.dash_app.dash
443+ self.wait_for_dash()
444+
445+ def ensure_dash_not_running(self):
446+ if process_helpers.is_job_running('unity8-dash'):
447+ process_helpers.stop_job('unity8-dash')
448+
449+ def launch_dash(self, binary_path, variables):
450+ launch_dash_app_fixture = fixture_setup.LaunchDashApp(
451+ binary_path, variables)
452+ self.useFixture(launch_dash_app_fixture)
453+ return launch_dash_app_fixture.application_proxy
454+
455+ def wait_for_dash(self):
456+ home_scope = self.dash.get_scope('clickscope')
380457 # FIXME! There is a huge timeout here for when we're doing CI on
381458 # VMs. See lp:1203715
382459 self.assertThat(
@@ -385,10 +462,26 @@ class UnityTestCase(AutopilotTestCase):
385462 )
386463 self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
387464
388− def get_dash(self):
389− dash = self._proxy.wait_select_single(Dash)
390− return dash
465+ def should_simulate_device(self):
466+ return (hasattr(self, 'app_width') and hasattr(self, 'app_height') and
467+ hasattr(self, 'grid_unit_px'))
391468
392− @property
393− def main_window(self):
394− return self._proxy.select_single(main_window_emulator.QQuickView)
469+ def simulate_device(self):
470+ simulate_device_fixture = self.useFixture(
471+ toolkit_fixtures.SimulateDevice(
472+ self.app_width, self.app_height, self.grid_unit_px))
473+ self.app_width = simulate_device_fixture.app_width
474+ self.app_height = simulate_device_fixture.app_height
475+
476+ def resize_window(self):
477+ application = self.process_manager.get_running_applications()[0]
478+ window = application.get_windows()[0]
479+ window.resize(self.app_width, self.app_height)
480+
481+ def get_window_size():
482+ _, _, window_width, window_height = window.geometry
483+ return window_width, window_height
484+
485+ self.assertThat(
486+ get_window_size,
487+ Eventually(Equals((self.app_width, self.app_height))))
tests/autopilot/unity8/shell/tests/test_emulators.py+23−24
@@ -16,6 +16,7 @@
1616# You should have received a copy of the GNU General Public License
1717# along with this program. If not, see <http://www.gnu.org/licenses/>.
1818#
19+from unity8.shell.emulators.dash import ListViewWithPageHeader
1920
2021"""Tests for the Dash autopilot emulators.
2122
@@ -46,24 +47,13 @@ class MainWindowTestCase(tests.UnityTestCase):
4647 unity_proxy = self.launch_unity()
4748 process_helpers.unlock_unity(unity_proxy)
4849
49− def test_search(self):
50− self.main_window.search('Test')
51− text_field = self.main_window.get_dash()._get_search_text_field()
52− self.assertEqual(text_field.text, 'Test')
53−
54−
55−class DashBaseTestCase(tests.UnityTestCase):
5650
57− scenarios = tests._get_device_emulation_scenarios()
51+class DashEmulatorTestCase(tests.DashBaseTestCase):
5852
59− def setUp(self):
60− super(DashBaseTestCase, self).setUp()
61− unity_proxy = self.launch_unity()
62− process_helpers.unlock_unity(unity_proxy)
63− self.dash = self.main_window.get_dash()
64−
65−
66−class DashEmulatorTestCase(DashBaseTestCase):
53+ def test_search(self):
54+ self.dash.enter_search_query('Test')
55+ text_field = self.dash._get_search_text_field()
56+ self.assertEqual(text_field.text, 'Test')
6757
6858 def test_open_unexisting_scope(self):
6959 scope_name = 'unexisting'
@@ -141,10 +131,10 @@ class DashEmulatorTestCase(DashBaseTestCase):
141131 scope_id = 'clickscope'
142132 scope = self.dash.open_scope(scope_id)
143133 self._assert_scope_is_opened(scope, scope_id)
144− self.assertIsInstance(scope, dash_emulators.DashApps)
134+ self.assertIsInstance(scope, dash_emulators.GenericScopeView)
145135
146136
147−class GenericScopeViewEmulatorTestCase(DashBaseTestCase):
137+class GenericScopeViewEmulatorTestCase(tests.DashBaseTestCase):
148138
149139 def setUp(self):
150140 # Set up the fake scopes before launching unity.
@@ -158,7 +148,7 @@ class GenericScopeViewEmulatorTestCase(DashBaseTestCase):
158148 self.assertTrue(preview.isCurrent)
159149
160150
161−class DashAppsEmulatorTestCase(DashBaseTestCase):
151+class DashAppsEmulatorTestCase(tests.DashBaseTestCase):
162152
163153 available_applications = [
164154 'Title.2.0', 'Title.2.1', 'Title.2.2', 'Title.2.3', 'Title.2.4',
@@ -182,18 +172,27 @@ class DashAppsEmulatorTestCase(DashBaseTestCase):
182172
183173 def test_get_applications_should_return_correct_applications(self):
184174 category = '2'
175+ category_element = self.applications_scope._get_category_element(
176+ category)
177+ list_view = self.dash.get_scope('clickscope')\
178+ .select_single(ListViewWithPageHeader)
185179 expected_apps_count = self._get_number_of_application_slots(category)
186180 expected_applications = self.available_applications[
187181 :expected_apps_count]
182+ x_center = list_view.globalRect.x + list_view.width / 2
183+ y_center = list_view.globalRect.y + list_view.height / 2
184+ y_diff = category_element.y - list_view.height + category_element.height
185+ list_view._slow_drag(x_center, x_center,
186+ y_center, y_center - y_diff)
188187 applications = self.applications_scope.get_applications(category)
189188 self.assertEqual(expected_applications, applications)
190189
191190 def _get_number_of_application_slots(self, category):
192191 category_element = self.applications_scope._get_category_element(
193192 category)
194− grid = category_element.select_single('CardFilterGrid')
195− filtergrid = grid.select_single('FilterGrid')
196− if (grid.filtered):
197− return filtergrid.collapsedRowCount * filtergrid.columns
193+ cardgrid = category_element.select_single('CardGrid')
194+ if (category_element.expanded):
195+ return cardgrid.select_single('QQuickGridView').count
198196 else:
199− return filtergrid.uncollapsedRowCount * filtergrid.columns
197+ return cardgrid.collapsedRows \
198+ * cardgrid.select_single('ResponsiveGridView').columns
tests/autopilot/unity8/shell/tests/test_lock_screen.py+7−47
@@ -51,7 +51,7 @@ class TestLockscreen(UnityTestCase):
5151 if greeter.narrowMode:
5252 unlock_unity(unity_proxy)
5353 lockscreen = self._wait_for_lockscreen()
54− self._enter_pincode("1234")
54+ self.main_window.enter_pin_code("1234")
5555 self.assertThat(lockscreen.shown, Eventually(Equals(False)))
5656 else:
5757 self._enter_prompt_passphrase("1234")
@@ -81,7 +81,7 @@ class TestLockscreen(UnityTestCase):
8181 if greeter.narrowMode:
8282 unlock_unity(unity_proxy)
8383 lockscreen = self._wait_for_lockscreen()
84− self._enter_pincode("4321")
84+ self.main_window.enter_pin_code("4321")
8585 pinentryField = self.main_window.get_pinentryField()
8686 self.assertThat(pinentryField.text, Eventually(Equals("")))
8787 self.assertThat(lockscreen.shown, Eventually(Equals(True)))
@@ -118,28 +118,6 @@ class TestLockscreen(UnityTestCase):
118118 self.assertThat(lockscreen.shown, Eventually(Equals(True)))
119119 return lockscreen
120120
121− def _enter_pincode(self, code):
122− """Enter code 'code' into the single-pin lightdm pincode entry
123− screen.
124−
125− :param code: must be a string of numeric characters.
126− :raises: TypeError if code is not a string.
127− :raises: ValueError if code contains non-numeric characters.
128−
129− """
130−
131− if not isinstance(code, basestring):
132− raise TypeError(
133− "'code' parameter must be a string, not %r."
134− % type(code)
135− )
136− for num in code:
137− if not num.isdigit():
138− raise ValueError(
139− "'code' parameter contains non-numeric characters."
140− )
141− self.touch.tap_object(self.main_window.get_pinPadButton(int(num)))
142−
143121 def _enter_pin_passphrase(self, passphrase):
144122 """Enter the password specified in 'passphrase' into the password entry
145123 field of the pin lock screen.
@@ -148,18 +126,15 @@ class TestLockscreen(UnityTestCase):
148126 :raises: TypeError if passphrase is not a string.
149127
150128 """
151− if not isinstance(passphrase, basestring):
129+ if not isinstance(passphrase, str):
152130 raise TypeError(
153131 "'passphrase' parameter must be a string, not %r."
154132 % type(passphrase)
155133 )
156134
157− pinentryField = self.main_window.get_pinentryField()
158− self.touch.tap_object(pinentryField)
159− self.assertThat(pinentryField.activeFocus, Eventually(Equals(True)))
160− for character in passphrase:
161− self._type_character(character, pinentryField)
162− logger.debug("Typed passphrase: %s", pinentryField.text)
135+ pin_entry_field = self.main_window.get_pinentryField()
136+ pin_entry_field.write(passphrase)
137+ logger.debug("Typed passphrase: %s", pin_entry_field.text)
163138 self.keyboard.type("\n")
164139
165140 def _enter_prompt_passphrase(self, passphrase):
@@ -177,21 +152,6 @@ class TestLockscreen(UnityTestCase):
177152 )
178153
179154 prompt = self.main_window.get_greeter().get_prompt()
180− self.touch.tap_object(prompt)
181− self.assertThat(prompt.activeFocus, Eventually(Equals(True)))
182− for character in passphrase:
183− self._type_character(character, prompt)
155+ prompt.write(passphrase)
184156 logger.debug("Typed passphrase: %s", prompt.text)
185157 self.keyboard.type("\n")
186−
187− def _type_character(self, character, prompt, retries=5):
188− current_text = prompt.text
189− self.keyboard.type(character)
190− try:
191− self.assertThat(
192− prompt.text, Eventually(Equals(current_text + character)))
193− except AssertionError:
194− if retries > 0:
195− self._type_character(character, prompt, retries-1)
196− else:
197− raise
tests/autopilot/unity8/shell/tests/test_notifications.py+12−7
@@ -154,7 +154,7 @@ class InteractiveNotificationBase(NotificationsBase):
154154 'Notification', objectName='notification1')
155155 notification = get_notification()
156156
157− self.touch.tap_object(
157+ notification.pointing_device.click_object(
158158 notification.select_single(objectName="interactiveArea")
159159 )
160160
@@ -201,11 +201,14 @@ class InteractiveNotificationBase(NotificationsBase):
201201 'Notification', objectName='notification1')
202202 notification = get_notification()
203203 self._assert_notification(notification, summary, body, True, True, 1.0)
204− initial_height = notification.height
205− self.touch.tap_object(notification.select_single(objectName="combobutton_dropdown"))
206− self.assertThat(notification.select_single(objectName="button2").expanded, Eventually(Equals(True)))
204+ notification.pointing_device.click_object(
205+ notification.select_single(objectName="combobutton_dropdown"))
206+ self.assertThat(
207+ notification.select_single(objectName="button2").expanded,
208+ Eventually(Equals(True)))
207209 time.sleep(2)
208− self.touch.tap_object(notification.select_single(objectName="button4"))
210+ notification.pointing_device.click_object(
211+ notification.select_single(objectName="button4"))
209212 self.assert_notification_action_id_was_called("action_decline_4")
210213
211214 def test_modal_sd_without_greeter(self):
@@ -249,7 +252,8 @@ class InteractiveNotificationBase(NotificationsBase):
249252 notification = get_notification()
250253 self._assert_notification(
251254 notification, summary, body, True, False, 1.0)
252− self.touch.tap_object(notification.select_single(objectName="button0"))
255+ notification.pointing_device.click_object(
256+ notification.select_single(objectName="button0"))
253257 self.assert_notification_action_id_was_called("action_accept")
254258
255259 def test_modal_sd_with_greeter(self):
@@ -291,7 +295,8 @@ class InteractiveNotificationBase(NotificationsBase):
291295 notification = get_notification()
292296 self._assert_notification(
293297 notification, summary, body, True, False, 1.0)
294− self.touch.tap_object(notification.select_single(objectName="button0"))
298+ notification.pointing_device.click_object(
299+ notification.select_single(objectName="button0"))
295300 self.assert_notification_action_id_was_called("action_accept")
296301
297302 def _create_interactive_notification(
tests/autopilot/unity8/shell/tests/test_upstart.py+33−5
@@ -20,11 +20,13 @@
2020"""Tests for upstart integration."""
2121
2222import os
23+import stat
2324import signal
2425import subprocess
2526import time
2627
27−from testtools.matchers._basic import Equals
28+import fixtures
29+from testtools.matchers import Equals, MismatchError
2830from autopilot.matchers import Eventually
2931from autopilot.introspection import get_proxy_object_for_existing_process
3032
@@ -57,6 +59,18 @@ class UpstartIntegrationTests(UnityTestCase):
5759
5860 def _launch_unity(self):
5961 self.patch_environment("QT_LOAD_TESTABILITY", "1")
62+
63+ try:
64+ host_socket = os.getenv("MIR_SOCKET", "/run/mir_socket")
65+ if stat.S_ISSOCK(os.stat(host_socket).st_mode):
66+ self.patch_environment("MIR_SERVER_HOST_SOCKET",
67+ host_socket)
68+ socket = os.path.join(os.getenv("XDG_RUNTIME_DIR", "/tmp"),
69+ "mir_socket")
70+ self.patch_environment("MIR_SERVER_FILE", socket)
71+ except OSError:
72+ pass
73+
6074 self.process = subprocess.Popen(
6175 [get_binary_path()] + self.unity_geometry_args)
6276
@@ -87,16 +101,30 @@ class UpstartIntegrationTests(UnityTestCase):
87101 emulator_base=UnityEmulatorBase,))
88102
89103 def test_no_sigstop(self):
90− self.patch_environment("UNITY_MIR_EMITS_SIGSTOP", "")
104+ self.useFixture(
105+ fixtures.EnvironmentVariable(
106+ 'UNITY_MIR_EMITS_SIGSTOP', newvalue=None))
91107 self._launch_unity()
108+
109+ try:
110+ self.assertThat(
111+ lambda: os.WIFSTOPPED(self._get_status()),
112+ Eventually(Equals(True)))
113+ except MismatchError:
114+ pass
115+ else:
116+ self.process.send_signal(signal.SIGCONT)
117+ self.fail('Unity8 raised SIGSTOP')
118+
92119 self._set_proxy()
93120
94121 logger.debug("Unity started, waiting for it to be ready.")
95− self.assertUnityReady()
122+ self.wait_for_unity()
96123 logger.debug("Unity loaded and ready.")
97124
98125 def test_expect_sigstop(self):
99− self.patch_environment("UNITY_MIR_EMITS_SIGSTOP", "1")
126+ self.useFixture(
127+ fixtures.EnvironmentVariable('UNITY_MIR_EMITS_SIGSTOP', '1'))
100128 self._launch_unity()
101129 self.assertThat(
102130 lambda: os.WIFSTOPPED(self._get_status()),
@@ -109,5 +137,5 @@ class UpstartIntegrationTests(UnityTestCase):
109137
110138 logger.debug("Unity started, waiting for it to be ready.")
111139 self._set_proxy()
112− self.assertUnityReady()
140+ self.wait_for_unity()
113141 logger.debug("Unity loaded and ready.")
tests/mocks/AccountsService/AccountsService.cpp+12−2
@@ -29,12 +29,14 @@ AccountsService::AccountsService(QObject* parent)
2929
3030QString AccountsService::user() const
3131{
32− return "testuser";
32+ return m_user;
3333}
3434
3535void AccountsService::setUser(const QString &user)
3636{
37− Q_UNUSED(user)
37+ m_user = user;
38+ Q_EMIT userChanged();
39+ Q_EMIT passwordDisplayHintChanged();
3840}
3941
4042bool AccountsService::demoEdges() const
@@ -68,3 +70,11 @@ void AccountsService::setStatsWelcomeScreen(bool statsWelcomeScreen)
6870 m_statsWelcomeScreen = statsWelcomeScreen;
6971 statsWelcomeScreenChanged();
7072}
73+
74+AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const
75+{
76+ if (m_user == "has-pin")
77+ return PasswordDisplayHint::Numeric;
78+ else
79+ return PasswordDisplayHint::Keyboard;
80+}
tests/mocks/AccountsService/AccountsService.h+12
@@ -27,6 +27,7 @@
2727class AccountsService: public QObject
2828{
2929 Q_OBJECT
30+ Q_ENUMS(PasswordDisplayHint)
3031 Q_PROPERTY (QString user
3132 READ user
3233 WRITE setUser
@@ -43,8 +44,16 @@ class AccountsService: public QObject
4344 READ statsWelcomeScreen
4445 WRITE setStatsWelcomeScreen // only available in mock
4546 NOTIFY statsWelcomeScreenChanged)
47+ Q_PROPERTY (PasswordDisplayHint passwordDisplayHint
48+ READ passwordDisplayHint
49+ NOTIFY passwordDisplayHintChanged)
4650
4751public:
52+ enum PasswordDisplayHint {
53+ Keyboard,
54+ Numeric,
55+ };
56+
4857 explicit AccountsService(QObject *parent = 0);
4958
5059 QString user() const;
@@ -55,15 +64,18 @@ public:
5564 void setBackgroundFile(const QString &backgroundFile);
5665 bool statsWelcomeScreen() const;
5766 void setStatsWelcomeScreen(bool statsWelcomeScreen);
67+ PasswordDisplayHint passwordDisplayHint() const;
5868
5969Q_SIGNALS:
6070 void userChanged();
6171 void demoEdgesChanged();
6272 void backgroundFileChanged();
6373 void statsWelcomeScreenChanged();
74+ void passwordDisplayHintChanged();
6475
6576private:
6677 QString m_backgroundFile;
78+ QString m_user;
6779 bool m_statsWelcomeScreen;
6880};
6981
tests/mocks/AccountsService/CMakeLists.txt+4−1
@@ -5,4 +5,7 @@ add_library(MockAccountsService-qml MODULE
55
66qt5_use_modules(MockAccountsService-qml DBus Qml)
77
8−add_unity8_mock(AccountsService 0.1 AccountsService TARGETS MockAccountsService-qml)
8+add_unity8_mock(AccountsService 0.1 AccountsService
9+ PREFIX mocks
10+ TARGETS MockAccountsService-qml
11+ )
tests/mocks/AccountsService/plugin.cpp+1
@@ -32,5 +32,6 @@ static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
3232void AccountsServicePlugin::registerTypes(const char *uri)
3333{
3434 Q_ASSERT(uri == QLatin1String("AccountsService"));
35+ qRegisterMetaType<AccountsService::PasswordDisplayHint>("AccountsService::PasswordDisplayHint");
3536 qmlRegisterSingletonType<AccountsService>(uri, 0, 1, "AccountsService", service_provider);
3637}
tests/mocks/LightDM/GreeterPrivate.h+2
@@ -24,6 +24,7 @@
2424namespace QLightDM
2525{
2626class Greeter;
27+class GreeterImpl;
2728
2829class GreeterPrivate
2930{
@@ -40,6 +41,7 @@ public:
4041 void handleRespond(const QString &response);
4142
4243protected:
44+ GreeterImpl *m_impl; // if the backend needs more private data
4345 Greeter * const q_ptr;
4446
4547private:
tests/mocks/LightDM/demo/CMakeLists.txt+4−2
@@ -11,11 +11,13 @@ set(LibLightDM_SOURCES
1111add_library(MockLightDM-demo STATIC ${LibLightDM_SOURCES})
1212
1313include_directories(
14+ ${CMAKE_CURRENT_BINARY_DIR}
1415 ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
1516)
1617
1718target_link_libraries(MockLightDM-demo
1819 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
19− )
20+ -lpam
21+)
2022
21−qt5_use_modules(MockLightDM-demo Gui)
23+qt5_use_modules(MockLightDM-demo Concurrent Gui)
tests/mocks/LightDM/demo/GreeterPrivate.cpp+202−30
@@ -18,53 +18,225 @@
1818
1919#include "../Greeter.h"
2020#include "../GreeterPrivate.h"
21−#include <QtCore/QDir>
22−#include <QtCore/QSettings>
21+#include <QFuture>
22+#include <QFutureInterface>
23+#include <QFutureWatcher>
24+#include <QQueue>
25+#include <QtConcurrent>
26+#include <QVector>
27+#include <security/pam_appl.h>
2328
2429namespace QLightDM
2530{
2631
32+class GreeterImpl : public QObject
33+{
34+ Q_OBJECT
35+
36+ typedef QFutureInterface<QString> ResponseFuture;
37+
38+public:
39+ explicit GreeterImpl(Greeter *parent, GreeterPrivate *greeterPrivate)
40+ : QObject(parent),
41+ greeter(parent),
42+ greeterPrivate(greeterPrivate),
43+ pamHandle(NULL)
44+ {
45+ qRegisterMetaType<QLightDM::GreeterImpl::ResponseFuture>("QLightDM::GreeterImpl::ResponseFuture");
46+
47+ connect(&futureWatcher, SIGNAL(finished()),
48+ this, SLOT(finishPam()));
49+ connect(this, SIGNAL(showMessage(QString, QLightDM::Greeter::MessageType)),
50+ greeter, SIGNAL(showMessage(QString, QLightDM::Greeter::MessageType)));
51+ // This next connect is how we pass ResponseFutures between threads
52+ connect(this, SIGNAL(showPrompt(QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)),
53+ this, SLOT(handlePrompt(QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)));
54+ }
55+
56+ void start(QString username)
57+ {
58+ // Clear out any existing PAM interactions first (we can't simply
59+ // cancel our QFuture because QtConcurrent::run doesn't support cancel)
60+ if (pamHandle != NULL) {
61+ pam_handle *handle = pamHandle;
62+ pamHandle = NULL; // to disable normal finishPam() handling
63+ while (respond(QString())); // clear our local queue of QFutures
64+ pam_end(handle, PAM_CONV_ERR);
65+ }
66+
67+ // Now actually start a new conversation with PAM
68+ pam_conv conversation;
69+ conversation.conv = converseWithPam;
70+ conversation.appdata_ptr = static_cast<void*>(this);
71+
72+ if (pam_start("lightdm", username.toUtf8(), &conversation, &pamHandle) == PAM_SUCCESS) {
73+ futureWatcher.setFuture(QtConcurrent::run(authenticateWithPam, pamHandle));
74+ } else {
75+ greeterPrivate->authenticated = false;
76+ Q_EMIT greeter->showMessage("Internal error: could not start PAM authentication", QLightDM::Greeter::MessageTypeError);
77+ Q_EMIT greeter->authenticationComplete();
78+ }
79+ }
80+
81+ static int authenticateWithPam(pam_handle* pamHandle)
82+ {
83+ int pamStatus = pam_authenticate(pamHandle, 0);
84+ if (pamStatus == PAM_SUCCESS) {
85+ pamStatus = pam_acct_mgmt(pamHandle, 0);
86+ }
87+ if (pamStatus == PAM_NEW_AUTHTOK_REQD) {
88+ pamStatus = pam_chauthtok(pamHandle, PAM_CHANGE_EXPIRED_AUTHTOK);
89+ }
90+ if (pamStatus == PAM_SUCCESS) {
91+ pam_setcred(pamHandle, PAM_REINITIALIZE_CRED);
92+ }
93+ return pamStatus;
94+ }
95+
96+ static int converseWithPam(int num_msg, const pam_message** msg,
97+ pam_response** resp, void* appdata_ptr)
98+ {
99+ if (num_msg <= 0)
100+ return PAM_CONV_ERR;
101+
102+ auto* tmp_response = static_cast<pam_response*>(calloc(num_msg, sizeof(pam_response)));
103+ if (!tmp_response)
104+ return PAM_CONV_ERR;
105+
106+ GreeterImpl* impl = static_cast<GreeterImpl*>(appdata_ptr);
107+
108+ int count;
109+ QVector<ResponseFuture> responses;
110+
111+ for (count = 0; count < num_msg; ++count)
112+ {
113+ switch (msg[count]->msg_style)
114+ {
115+ case PAM_PROMPT_ECHO_ON:
116+ {
117+ QString message(msg[count]->msg);
118+ responses.append(ResponseFuture());
119+ responses.last().reportStarted();
120+ Q_EMIT impl->showPrompt(message, Greeter::PromptTypeQuestion, responses.last());
121+ break;
122+ }
123+ case PAM_PROMPT_ECHO_OFF:
124+ {
125+ QString message(msg[count]->msg);
126+ responses.append(ResponseFuture());
127+ responses.last().reportStarted();
128+ Q_EMIT impl->showPrompt(message, Greeter::PromptTypeSecret, responses.last());
129+ break;
130+ }
131+ case PAM_TEXT_INFO:
132+ {
133+ QString message(msg[count]->msg);
134+ Q_EMIT impl->showMessage(message, Greeter::MessageTypeInfo);
135+ break;
136+ }
137+ default:
138+ {
139+ QString message(msg[count]->msg);
140+ Q_EMIT impl->showMessage(message, Greeter::MessageTypeError);
141+ break;
142+ }
143+ }
144+ }
145+
146+ int i = 0;
147+ bool raise_error = false;
148+
149+ for (auto &response : responses)
150+ {
151+ pam_response* resp_item = &tmp_response[i++];
152+ resp_item->resp_retcode = 0;
153+ resp_item->resp = strdup(response.future().result().toUtf8());
154+
155+ if (!resp_item->resp)
156+ {
157+ raise_error = true;
158+ break;
159+ }
160+ }
161+
162+ if (raise_error)
163+ {
164+ for (int i = 0; i < count; ++i)
165+ free(tmp_response[i].resp);
166+
167+ free(tmp_response);
168+ return PAM_CONV_ERR;
169+ }
170+ else
171+ {
172+ *resp = tmp_response;
173+ return PAM_SUCCESS;
174+ }
175+ }
176+
177+public Q_SLOTS:
178+ bool respond(QString response)
179+ {
180+ if (!futures.isEmpty()) {
181+ futures.dequeue().reportFinished(&response);
182+ return true;
183+ } else {
184+ return false;
185+ }
186+ }
187+
188+Q_SIGNALS:
189+ void showMessage(QString text, QLightDM::Greeter::MessageType type);
190+ void showPrompt(QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture response);
191+
192+private Q_SLOTS:
193+ void finishPam()
194+ {
195+ if (pamHandle == NULL) {
196+ return;
197+ }
198+
199+ int pamStatus = futureWatcher.result();
200+
201+ pam_end(pamHandle, pamStatus);
202+ pamHandle = NULL;
203+
204+ greeterPrivate->authenticated = (pamStatus == PAM_SUCCESS);
205+ Q_EMIT greeter->authenticationComplete();
206+ }
207+
208+ void handlePrompt(QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture future)
209+ {
210+ futures.enqueue(future);
211+ Q_EMIT greeter->showPrompt(text, type);
212+ }
213+
214+private:
215+ Greeter *greeter;
216+ GreeterPrivate *greeterPrivate;
217+ pam_handle* pamHandle;
218+ QFutureWatcher<int> futureWatcher;
219+ QQueue<ResponseFuture> futures;
220+};
221+
27222GreeterPrivate::GreeterPrivate(Greeter* parent)
28223 : authenticated(false),
29224 authenticationUser(),
225+ m_impl(new GreeterImpl(parent, this)),
30226 q_ptr(parent)
31227{
32228}
33229
34230void GreeterPrivate::handleAuthenticate()
35231{
36− Q_Q(Greeter);
37−
38− QSettings settings(QDir::homePath() + "/.unity8-greeter-demo", QSettings::NativeFormat);
39− settings.beginGroup(authenticationUser);
40− QVariant password = settings.value("password", "none");
41−
42− if (password == "pin") {
43− Q_EMIT q->showPrompt("PIN", Greeter::PromptTypeSecret);
44− } else if (password == "keyboard") {
45− Q_EMIT q->showPrompt("Password", Greeter::PromptTypeSecret);
46− } else {
47− authenticated = true;
48− Q_EMIT q->authenticationComplete();
49− }
232+ m_impl->start(authenticationUser);
50233}
51234
52235void GreeterPrivate::handleRespond(const QString &response)
53236{
54− Q_Q(Greeter);
55−
56− QSettings settings(QDir::homePath() + "/.unity8-greeter-demo", QSettings::NativeFormat);
57− settings.beginGroup(authenticationUser);
58− QVariant password = settings.value("password", "none");
59−
60− QString passwordValue;
61− if (password == "pin") {
62− passwordValue = settings.value("passwordValue", "1234").toString();
63− } else {
64− passwordValue = settings.value("passwordValue", "password").toString();
65− }
66− authenticated = (response == passwordValue);
67− Q_EMIT q->authenticationComplete();
237+ m_impl->respond(response);
68238}
69239
70240}
241+
242+#include "GreeterPrivate.moc"
tests/mocks/LightDM/demo/UsersModelPrivate.cpp+1−1
@@ -29,7 +29,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
2929 : q_ptr(parent)
3030{
3131 QSettings settings(QDir::homePath() + "/.unity8-greeter-demo", QSettings::NativeFormat);
32− QStringList users = settings.value("users", QStringList() << "phablet").toStringList();
32+ QStringList users = settings.value("users", QStringList() << qgetenv("USER")).toStringList();
3333
3434 Q_FOREACH(const QString &user, users)
3535 {
tests/mocks/LightDM/full/GreeterPrivate.cpp+1−1
@@ -54,7 +54,7 @@ void GreeterPrivate::handleAuthenticate()
5454 authenticated = true;
5555 Q_EMIT q->authenticationComplete();
5656 } else if (authenticationUser == "has-pin"){
57− Q_EMIT q->showPrompt("PIN", Greeter::PromptTypeSecret);
57+ Q_EMIT q->showPrompt("Password:", Greeter::PromptTypeSecret);
5858 } else if (authenticationUser == "auth-error") {
5959 authenticated = false;
6060 Q_EMIT q->authenticationComplete();
tests/mocks/LightDM/single-pin/GreeterPrivate.cpp+1−1
@@ -32,7 +32,7 @@ GreeterPrivate::GreeterPrivate(Greeter* parent)
3232void GreeterPrivate::handleAuthenticate()
3333{
3434 Q_Q(Greeter);
35− Q_EMIT q->showPrompt("PIN", Greeter::PromptTypeSecret);
35+ Q_EMIT q->showPrompt("Password:", Greeter::PromptTypeSecret);
3636}
3737
3838void GreeterPrivate::handleRespond(const QString &response)
tests/mocks/LightDM/single-pin/UsersModelPrivate.cpp+1−1
@@ -26,7 +26,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
2626{
2727 entries =
2828 {
29− { "single", "Has PIN", 0, 0, false, false, 0, 0 },
29+ { "has-pin", "Has PIN", 0, 0, false, false, 0, 0 },
3030 };
3131}
3232
tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−9
@@ -11,12 +11,4 @@ add_library(FakeUbuntuTelephonyQml MODULE ${FakeUbuntuTelephonyQml_SOURCES})
1111
1212qt5_use_modules(FakeUbuntuTelephonyQml Core Quick)
1313
14−# copy files into build directory for shadow builds
15−add_custom_target(UbuntuTelephonyQmlDirFile ALL
16− COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" ${CMAKE_CURRENT_BINARY_DIR}
17− DEPENDS qmldir
18−)
19−
20−install(TARGETS FakeUbuntuTelephonyQml
21− DESTINATION ${SHELL_INSTALL_QML}/mocks/Ubuntu/Telephony
22− )
14+add_unity8_mock(Ubuntu.Telephony 0.1 Ubuntu/Telephony TARGETS FakeUbuntuTelephonyQml)
tests/mocks/Unity/Application/Application.qmltypes−2
@@ -102,8 +102,6 @@ Module {
102102 "ForceMainStage": 1
103103 }
104104 }
105− Property { name: "keyboardHeight"; type: "int"; isReadonly: true }
106− Property { name: "keyboardVisible"; type: "bool"; isReadonly: true }
107105 Property { name: "sideStageWidth"; type: "int"; isReadonly: true }
108106 Property { name: "stageHint"; type: "StageHint"; isReadonly: true }
109107 Property { name: "formFactorHint"; type: "FormFactorHint"; isReadonly: true }
tests/mocks/Unity/Application/ApplicationDBusAdaptor.cppnew file+75
@@ -0,0 +1,75 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "ApplicationInfo.h"
18+#include "ApplicationDBusAdaptor.h"
19+#include "ApplicationManager.h"
20+#include "SurfaceManager.h"
21+#include "MirSurfaceItem.h"
22+
23+quint32 nextId = 0;
24+
25+ApplicationDBusAdaptor::ApplicationDBusAdaptor(ApplicationManager* applicationManager)
26+ : QDBusAbstractAdaptor(applicationManager)
27+ , m_applicationManager(applicationManager)
28+{
29+}
30+
31+MirSurfaceItem* topSurface(MirSurfaceItem* surface)
32+{
33+ if (!surface)
34+ return nullptr;
35+
36+ MirSurfaceItem* child = NULL;
37+ Q_FOREACH (MirSurfaceItem *childSurface, surface->childSurfaceList()) {
38+ child = topSurface(childSurface);
39+ if (child) {
40+ break;
41+ }
42+ }
43+ return child ? child : surface;
44+}
45+
46+quint32 ApplicationDBusAdaptor::addChildSurface(const QString &appId, const QString &surfaceImage)
47+{
48+ qDebug() << "ApplicationDBusAdaptor::addChildSurface - " << appId;
49+
50+ ApplicationInfo* application = m_applicationManager->findApplication(appId);
51+ if (!application) {
52+ qDebug() << "ApplicationDBusAdaptor::addChildSurface - No application found for " << appId;
53+ return 0;
54+ }
55+ quint32 surfaceId = ++nextId;
56+ MirSurfaceItem* surface = new MirSurfaceItem(QString("ChildSurface%1").arg(surfaceId),
57+ MirSurfaceItem::Normal,
58+ MirSurfaceItem::Maximized,
59+ QUrl(surfaceImage));
60+ m_childItems[surfaceId] = surface;
61+ surface->setParentSurface(topSurface(application->surface()));
62+ return surfaceId;
63+}
64+
65+void ApplicationDBusAdaptor::removeChildSurface(int surfaceId)
66+{
67+ qDebug() << "ApplicationDBusAdaptor::removeChildSurface - " << surfaceId;
68+
69+ if (!m_childItems.contains(surfaceId)) {
70+ qDebug() << "ApplicationDBusAdaptor::removeChildSurface - No added surface for " << surfaceId;
71+ return;
72+ }
73+ MirSurfaceItem* surface = m_childItems.take(surfaceId);
74+ Q_EMIT surface->removed();
75+}
tests/mocks/Unity/Application/ApplicationDBusAdaptor.hnew file+43
@@ -0,0 +1,43 @@
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 APPLICATIONDBUSADAPTOR_H
18+#define APPLICATIONDBUSADAPTOR_H
19+
20+#include <QtDBus/QtDBus>
21+
22+class ApplicationManager;
23+class SurfaceManager;
24+class MirSurfaceItem;
25+
26+class ApplicationDBusAdaptor : public QDBusAbstractAdaptor
27+{
28+ Q_OBJECT
29+ Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity8.Mocks.Application")
30+public:
31+ ApplicationDBusAdaptor(ApplicationManager* applicationManager);
32+
33+public Q_SLOTS:
34+ quint32 addChildSurface(const QString& appId, const QString& surfaceImage);
35+ void removeChildSurface(int surfaceId);
36+
37+private:
38+ ApplicationManager* m_applicationManager;
39+
40+ QHash<quint32, MirSurfaceItem*> m_childItems;
41+};
42+
43+#endif // APPLICATIONDBUSADAPTOR_H
tests/mocks/Unity/Application/ApplicationInfo.cpp+49−63
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -15,6 +15,8 @@
1515 */
1616
1717#include "ApplicationInfo.h"
18+#include "MirSurfaceItem.h"
19+#include "SurfaceManager.h"
1820
1921#include <QGuiApplication>
2022#include <QQuickItem>
@@ -24,91 +26,75 @@
2426
2527ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
2628 : ApplicationInfoInterface(appId, parent)
27− ,m_appId(appId)
28− ,m_stage(MainStage)
29− ,m_state(Starting)
30− ,m_focused(false)
31− ,m_fullscreen(false)
32− ,m_windowItem(0)
33− ,m_windowComponent(0)
34− ,m_parentItem(0)
29+ , m_appId(appId)
30+ , m_stage(MainStage)
31+ , m_state(Starting)
32+ , m_focused(false)
33+ , m_fullscreen(false)
34+ , m_parentItem(0)
35+ , m_surface(0)
3536{
36− QTimer::singleShot(300, this, SLOT(setRunning()));
37+ connect(this, &ApplicationInfo::stateChanged, this, &ApplicationInfo::onStateChanged);
3738}
3839
3940ApplicationInfo::ApplicationInfo(QObject *parent)
4041 : ApplicationInfoInterface(QString(), parent)
41− ,m_stage(MainStage)
42− ,m_state(Starting)
43− ,m_focused(false)
44− ,m_fullscreen(false)
45− ,m_windowItem(0)
46− ,m_windowComponent(0)
47− ,m_parentItem(0)
42+ , m_stage(MainStage)
43+ , m_state(Starting)
44+ , m_focused(false)
45+ , m_fullscreen(false)
46+ , m_parentItem(0)
47+ , m_surface(0)
4848{
49− QTimer::singleShot(300, this, SLOT(setRunning()));
49+ connect(this, &ApplicationInfo::stateChanged, this, &ApplicationInfo::onStateChanged);
5050}
5151
52−void ApplicationInfo::onWindowComponentStatusChanged(QQmlComponent::Status status)
52+ApplicationInfo::~ApplicationInfo()
5353{
54− if (status == QQmlComponent::Ready && !m_windowItem)
55− doCreateWindowItem();
54+ if (m_surface) {
55+ Q_EMIT SurfaceManager::singleton()->surfaceDestroyed(m_surface);
56+ m_surface->deleteLater();
57+ }
5658}
5759
58−void ApplicationInfo::setRunning()
60+void ApplicationInfo::onStateChanged(State state)
5961{
60− m_state = Running;
61− Q_EMIT stateChanged();
62+ if (state == ApplicationInfo::Running) {
63+ QTimer::singleShot(1000, this, SLOT(createSurface()));
64+ } else if (state == ApplicationInfo::Stopped) {
65+ setSurface(nullptr);
66+ }
6267}
6368
64−void ApplicationInfo::createWindowComponent()
69+void ApplicationInfo::createSurface()
6570{
66− // The assumptions I make here really should hold.
67− QQuickView *quickView =
68− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
71+ if (m_surface || state() == ApplicationInfo::Stopped) return;
6972
70− QQmlEngine *engine = quickView->engine();
71−
72− m_windowComponent = new QQmlComponent(engine, this);
73− m_windowComponent->setData(m_windowQml.toLatin1(), QUrl());
73+ setSurface(new MirSurfaceItem(name(),
74+ MirSurfaceItem::Normal,
75+ fullscreen() ? MirSurfaceItem::Fullscreen : MirSurfaceItem::Maximized,
76+ screenshot()));
7477}
7578
76−void ApplicationInfo::doCreateWindowItem()
79+void ApplicationInfo::setSurface(MirSurfaceItem* surface)
7780{
78− m_windowItem = qobject_cast<QQuickItem *>(m_windowComponent->create());
79− m_windowItem->setParentItem(m_parentItem);
80−}
81−
82−void ApplicationInfo::createWindowItem()
83−{
84− if (!m_windowComponent)
85− createWindowComponent();
81+ if (m_surface == surface)
82+ return;
8683
87− // only create the windowItem once the component is ready
88− if (!m_windowComponent->isReady()) {
89− connect(m_windowComponent, &QQmlComponent::statusChanged,
90− this, &ApplicationInfo::onWindowComponentStatusChanged);
91− } else {
92− doCreateWindowItem();
84+ if (m_surface) {
85+ m_surface->setApplication(nullptr);
86+ m_surface->setParent(nullptr);
87+ SurfaceManager::singleton()->unregisterSurface(m_surface);
9388 }
94−}
95−
96−void ApplicationInfo::showWindow(QQuickItem *parent)
97−{
98− m_parentItem = parent;
9989
100− if (!m_windowItem)
101− createWindowItem();
90+ m_surface = surface;
10291
103− if (m_windowItem) {
104− m_windowItem->setVisible(true);
92+ if (m_surface) {
93+ m_surface->setApplication(this);
94+ m_surface->setParent(this);
95+ SurfaceManager::singleton()->registerSurface(m_surface);
10596 }
106−}
107−
108−void ApplicationInfo::hideWindow()
109−{
110− if (!m_windowItem)
111− return;
11297
113− m_windowItem->setVisible(false);
98+ Q_EMIT surfaceChanged(m_surface);
99+ SurfaceManager::singleton()->registerSurface(m_surface);
114100}
tests/mocks/Unity/Application/ApplicationInfo.h+19−16
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2014 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
@@ -21,6 +21,7 @@
2121#include <QQmlComponent>
2222
2323class QQuickItem;
24+class MirSurfaceItem;
2425
2526// unity-api
2627#include <unity/shell/application/ApplicationInfoInterface.h>
@@ -36,6 +37,7 @@ class ApplicationInfo : public ApplicationInfoInterface {
3637
3738 Q_PROPERTY(bool fullscreen READ fullscreen WRITE setFullscreen NOTIFY fullscreenChanged)
3839 Q_PROPERTY(Stage stage READ stage WRITE setStage NOTIFY stageChanged)
40+ Q_PROPERTY(MirSurfaceItem* surface READ surface NOTIFY surfaceChanged)
3941
4042 // Only exists in this fake implementation
4143
@@ -45,9 +47,10 @@ class ApplicationInfo : public ApplicationInfoInterface {
4547 // QML component used to represent the application window
4648 Q_PROPERTY(QString windowQml READ windowQml WRITE setWindowQml NOTIFY windowQmlChanged)
4749
48− public:
50+public:
4951 ApplicationInfo(QObject *parent = NULL);
5052 ApplicationInfo(const QString &appId, QObject *parent = NULL);
53+ ~ApplicationInfo();
5154
5255 #define IMPLEMENT_PROPERTY(name, Name, type) \
5356 public: \
@@ -56,11 +59,11 @@ class ApplicationInfo : public ApplicationInfoInterface {
5659 { \
5760 if (m_##name != value) { \
5861 m_##name = value; \
59− Q_EMIT name##Changed(); \
62+ Q_EMIT name##Changed(value); \
6063 } \
6164 } \
6265 Q_SIGNALS: \
63− void name##Changed(); \
66+ void name##Changed(const type&); \
6467 private: \
6568 type m_##name;
6669
@@ -78,21 +81,21 @@ class ApplicationInfo : public ApplicationInfoInterface {
7881
7982 #undef IMPLEMENT_PROPERTY
8083
81− public:
82− void showWindow(QQuickItem *parent);
83− void hideWindow();
84+public:
85+ void setSurface(MirSurfaceItem* surface);
86+ MirSurfaceItem* surface() const { return m_surface; }
8487
85− private Q_SLOTS:
86− void onWindowComponentStatusChanged(QQmlComponent::Status status);
87− void setRunning();
88+Q_SIGNALS:
89+ void surfaceChanged(MirSurfaceItem*);
8890
89− private:
90− void createWindowItem();
91− void doCreateWindowItem();
92− void createWindowComponent();
93− QQuickItem *m_windowItem;
94− QQmlComponent *m_windowComponent;
91+private Q_SLOTS:
92+ void onStateChanged(State state);
93+
94+ void createSurface();
95+
96+private:
9597 QQuickItem *m_parentItem;
98+ MirSurfaceItem* m_surface;
9699};
97100
98101Q_DECLARE_METATYPE(ApplicationInfo*)
tests/mocks/Unity/Application/ApplicationManager.cpp+73−174
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -15,7 +15,9 @@
1515 */
1616
1717#include "ApplicationManager.h"
18+#include "ApplicationDBusAdaptor.h"
1819#include "ApplicationInfo.h"
20+#include "MirSurfaceItem.h"
1921
2022#include <paths.h>
2123
@@ -26,17 +28,34 @@
2628#include <QQmlComponent>
2729#include <QTimer>
2830#include <QDateTime>
31+#include <QtDBus/QtDBus>
32+
33+ApplicationManager *ApplicationManager::the_application_manager = nullptr;
34+
35+ApplicationManager *ApplicationManager::singleton()
36+{
37+ if (!the_application_manager) {
38+ the_application_manager = new ApplicationManager();
39+ new ApplicationDBusAdaptor(the_application_manager);
40+
41+ QDBusConnection connection = QDBusConnection::sessionBus();
42+ connection.registerService("com.canonical.Unity8");
43+ connection.registerObject("/com/canonical/Unity8/Mocks", the_application_manager);
44+ }
45+ return the_application_manager;
46+}
2947
3048ApplicationManager::ApplicationManager(QObject *parent)
3149 : ApplicationManagerInterface(parent)
3250 , m_suspended(false)
33− , m_mainStageComponent(0)
34− , m_mainStage(0)
35− , m_sideStageComponent(0)
36− , m_sideStage(0)
37− , m_rightMargin(0)
3851{
52+ m_roleNames.insert(RoleSurface, "surface");
53+ m_roleNames.insert(RoleFullscreen, "fullscreen");
54+
3955 buildListOfAvailableApplications();
56+
57+ startApplication("unity8-dash");
58+ focusApplication("unity8-dash");
4059}
4160
4261ApplicationManager::~ApplicationManager()
@@ -69,6 +88,10 @@ QVariant ApplicationManager::data(const QModelIndex& index, int role) const {
6988 return app->focused();
7089 case RoleScreenshot:
7190 return app->screenshot();
91+ case RoleSurface:
92+ return QVariant::fromValue(app->surface());
93+ case RoleFullscreen:
94+ return app->fullscreen();
7295 default:
7396 return QVariant();
7497 }
@@ -89,6 +112,17 @@ ApplicationInfo *ApplicationManager::findApplication(const QString &appId) const
89112 return nullptr;
90113}
91114
115+QModelIndex ApplicationManager::findIndex(ApplicationInfo* application)
116+{
117+ for (int i = 0; i < m_runningApplications.size(); ++i) {
118+ if (m_runningApplications.at(i) == application) {
119+ return index(i);
120+ }
121+ }
122+
123+ return QModelIndex();
124+}
125+
92126void ApplicationManager::add(ApplicationInfo *application) {
93127 if (!application) {
94128 return;
@@ -99,7 +133,13 @@ void ApplicationManager::add(ApplicationInfo *application) {
99133 endInsertRows();
100134 Q_EMIT applicationAdded(application->appId());
101135 Q_EMIT countChanged();
102− Q_EMIT focusRequested(application->appId());
136+ if (count() == 1) Q_EMIT emptyChanged(isEmpty()); // was empty but not anymore
137+
138+ connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() {
139+ QModelIndex appIndex = findIndex(application);
140+ if (!appIndex.isValid()) return;
141+ Q_EMIT dataChanged(appIndex, appIndex, QVector<int>() << ApplicationManager::RoleSurface);
142+ });
103143}
104144
105145void ApplicationManager::remove(ApplicationInfo *application) {
@@ -110,7 +150,9 @@ void ApplicationManager::remove(ApplicationInfo *application) {
110150 endRemoveRows();
111151 Q_EMIT applicationRemoved(application->appId());
112152 Q_EMIT countChanged();
153+ if (isEmpty()) Q_EMIT emptyChanged(isEmpty());
113154 }
155+ disconnect(application, &ApplicationInfo::surfaceChanged, this, 0);
114156}
115157
116158void ApplicationManager::move(int from, int to) {
@@ -127,16 +169,6 @@ void ApplicationManager::move(int from, int to) {
127169 }
128170}
129171
130−int ApplicationManager::keyboardHeight() const
131−{
132− return 0;
133−}
134−
135−bool ApplicationManager::keyboardVisible() const
136−{
137− return false;
138−}
139−
140172int ApplicationManager::sideStageWidth() const
141173{
142174 return 0;
@@ -180,14 +212,17 @@ ApplicationInfo* ApplicationManager::startApplication(const QString &appId,
180212 application->setStage(ApplicationInfo::MainStage);
181213 }
182214 add(application);
183−
184− QMetaObject::invokeMethod(this, "focusApplication", Qt::QueuedConnection, Q_ARG(QString, appId));
215+ application->setState(ApplicationInfo::Running);
185216
186217 return application;
187218}
188219
189220bool ApplicationManager::stopApplication(const QString &appId)
190221{
222+ if (appId == "unity8-dash") {
223+ return false;
224+ }
225+
191226 ApplicationInfo *application = findApplication(appId);
192227 if (application == nullptr)
193228 return false;
@@ -195,6 +230,7 @@ bool ApplicationManager::stopApplication(const QString &appId)
195230 if (application->appId() == focusedApplicationId()) {
196231 unfocusCurrentApplication();
197232 }
233+ application->setState(ApplicationInfo::Stopped);
198234 remove(application);
199235 return true;
200236}
@@ -215,7 +251,6 @@ bool ApplicationManager::updateScreenshot(const QString &appId)
215251 return false;
216252 }
217253
218− application->setScreenshot(QString("image://application/%1/%2").arg(appId).arg(QDateTime::currentMSecsSinceEpoch()));
219254 QModelIndex appIndex = index(idx);
220255 Q_EMIT dataChanged(appIndex, appIndex, QVector<int>() << RoleScreenshot);
221256 return true;
@@ -260,35 +295,25 @@ bool ApplicationManager::focusApplication(const QString &appId)
260295 for (ApplicationInfo *app : m_runningApplications) {
261296 if (app->focused() && app->stage() == ApplicationInfo::MainStage) {
262297 app->setFocused(false);
263− app->hideWindow();
298+ app->setState(ApplicationInfo::Suspended);
264299 }
265300 }
266301
267302 // focus this app
268303 application->setFocused(true);
269− if (!m_mainStage)
270− createMainStage();
271− application->showWindow(m_mainStage);
272− m_mainStage->setZ(-1000);
273− if (m_sideStage)
274− m_sideStage->setZ(-2000);
304+ application->setState(ApplicationInfo::Running);
275305 } else if (application->stage() == ApplicationInfo::SideStage) {
276306 // unfocus currently focused sidestage app
277307 for (ApplicationInfo *app : m_runningApplications) {
278308 if (app->focused() && app->stage() == ApplicationInfo::SideStage) {
279309 app->setFocused(false);
280− app->hideWindow();
310+ app->setState(ApplicationInfo::Suspended);
281311 }
282312 }
283313
284314 // focus this app
285315 application->setFocused(true);
286− if (!m_sideStage)
287− createSideStage();
288− application->showWindow(m_sideStage);
289− m_sideStage->setZ(-1000);
290− if (m_mainStage)
291− m_mainStage->setZ(-2000);
316+ application->setState(ApplicationInfo::Running);
292317 }
293318
294319 // move app to top of stack
@@ -299,18 +324,14 @@ bool ApplicationManager::focusApplication(const QString &appId)
299324
300325bool ApplicationManager::requestFocusApplication(const QString &appId)
301326{
302− if (appId != focusedApplicationId()) {
303− QMetaObject::invokeMethod(this, "focusRequested", Qt::QueuedConnection, Q_ARG(QString, appId));
304− return true;
305− }
306− return false;
327+ QMetaObject::invokeMethod(this, "focusRequested", Qt::QueuedConnection, Q_ARG(QString, appId));
328+ return true;
307329}
308330
309331void ApplicationManager::unfocusCurrentApplication()
310332{
311333 for (ApplicationInfo *app : m_runningApplications) {
312334 if (app->focused()) {
313− app->hideWindow();
314335 app->setFocused(false);
315336 }
316337 }
@@ -319,53 +340,27 @@ void ApplicationManager::unfocusCurrentApplication()
319340
320341void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
321342{
322− // TODO: Is there a better way of solving this fullscreen vs. regular
323− // application height?
324− QString topMargin;
325− if (application->fullscreen()) {
326− topMargin.append("0");
327− } else {
328− // Taken from Panel.panelHeight
329− topMargin.append("units.gu(3) + units.dp(2)");
330− }
331−
332− QString windowQml = QString(
333− "import QtQuick 2.0\n"
334− "Image {\n"
335− " anchors.fill: parent\n"
336− " anchors.topMargin: %1\n"
337− " anchors.rightMargin: %2\n"
338− " source: \"file://%3/Dash/graphics/phone/screenshots/%4.png\"\n"
339− " smooth: true\n"
340− " fillMode: Image.PreserveAspectCrop\n"
341− "}").arg(topMargin)
342− .arg(m_rightMargin)
343− .arg(qmlDirectory())
344− .arg(application->icon().toString());
345− application->setWindowQml(windowQml);
346−
347− QString imageQml = QString(
348− "import QtQuick 2.0\n"
349− "Image {\n"
350− " anchors.fill: parent\n"
351− " source: \"file://%1/Dash/graphics/phone/screenshots/%2.png\"\n"
352− " smooth: true\n"
353− " fillMode: Image.PreserveAspectCrop\n"
354− "}").arg(qmlDirectory())
355− .arg(application->icon().toString());
356− application->setImageQml(imageQml);
343+ application->setScreenshot(QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png").arg(qmlDirectory())
344+ .arg(application->icon().toString()));
357345}
358346
359347void ApplicationManager::buildListOfAvailableApplications()
360348{
361349 ApplicationInfo *application;
362350
351+ application = new ApplicationInfo(this);
352+ application->setAppId("unity8-dash");
353+ application->setName("Unity 8 Mock Dash");
354+ application->setIcon(QUrl("unity8-dash"));
355+ application->setStage(ApplicationInfo::MainStage);
356+ generateQmlStrings(application);
357+ m_availableApplications.append(application);
358+
363359 application = new ApplicationInfo(this);
364360 application->setAppId("dialer-app");
365361 application->setName("Dialer");
366362 application->setIcon(QUrl("dialer"));
367363 application->setStage(ApplicationInfo::SideStage);
368− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
369364 generateQmlStrings(application);
370365 m_availableApplications.append(application);
371366
@@ -374,7 +369,6 @@ void ApplicationManager::buildListOfAvailableApplications()
374369 application->setName("Camera");
375370 application->setIcon(QUrl("camera"));
376371 application->setFullscreen(true);
377− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
378372 generateQmlStrings(application);
379373 m_availableApplications.append(application);
380374
@@ -382,7 +376,6 @@ void ApplicationManager::buildListOfAvailableApplications()
382376 application->setAppId("gallery-app");
383377 application->setName("Gallery");
384378 application->setIcon(QUrl("gallery"));
385− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
386379 generateQmlStrings(application);
387380 m_availableApplications.append(application);
388381
@@ -391,7 +384,6 @@ void ApplicationManager::buildListOfAvailableApplications()
391384 application->setName("Facebook");
392385 application->setIcon(QUrl("facebook"));
393386 application->setStage(ApplicationInfo::SideStage);
394− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
395387 generateQmlStrings(application);
396388 m_availableApplications.append(application);
397389
@@ -400,7 +392,6 @@ void ApplicationManager::buildListOfAvailableApplications()
400392 application->setFullscreen(true);
401393 application->setName("Browser");
402394 application->setIcon(QUrl("browser"));
403− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
404395 generateQmlStrings(application);
405396 m_availableApplications.append(application);
406397
@@ -409,7 +400,6 @@ void ApplicationManager::buildListOfAvailableApplications()
409400 application->setName("Twitter");
410401 application->setIcon(QUrl("twitter"));
411402 application->setStage(ApplicationInfo::SideStage);
412− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
413403 generateQmlStrings(application);
414404 m_availableApplications.append(application);
415405
@@ -417,7 +407,6 @@ void ApplicationManager::buildListOfAvailableApplications()
417407 application->setAppId("gmail-webapp");
418408 application->setName("GMail");
419409 application->setIcon(QUrl("gmail"));
420− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
421410 m_availableApplications.append(application);
422411
423412 application = new ApplicationInfo(this);
@@ -425,7 +414,6 @@ void ApplicationManager::buildListOfAvailableApplications()
425414 application->setName("Weather");
426415 application->setIcon(QUrl("weather"));
427416 application->setStage(ApplicationInfo::SideStage);
428− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
429417 generateQmlStrings(application);
430418 m_availableApplications.append(application);
431419
@@ -434,7 +422,6 @@ void ApplicationManager::buildListOfAvailableApplications()
434422 application->setName("Notepad");
435423 application->setIcon(QUrl("notepad"));
436424 application->setStage(ApplicationInfo::SideStage);
437− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
438425 m_availableApplications.append(application);
439426
440427 application = new ApplicationInfo(this);
@@ -442,7 +429,6 @@ void ApplicationManager::buildListOfAvailableApplications()
442429 application->setName("Calendar");
443430 application->setIcon(QUrl("calendar"));
444431 application->setStage(ApplicationInfo::SideStage);
445− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
446432 m_availableApplications.append(application);
447433
448434 application = new ApplicationInfo(this);
@@ -450,21 +436,18 @@ void ApplicationManager::buildListOfAvailableApplications()
450436 application->setName("Media Player");
451437 application->setIcon(QUrl("mediaplayer-app"));
452438 application->setFullscreen(true);
453− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
454439 m_availableApplications.append(application);
455440
456441 application = new ApplicationInfo(this);
457442 application->setAppId("evernote");
458443 application->setName("Evernote");
459444 application->setIcon(QUrl("evernote"));
460− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
461445 m_availableApplications.append(application);
462446
463447 application = new ApplicationInfo(this);
464448 application->setAppId("map");
465449 application->setName("Map");
466450 application->setIcon(QUrl("map"));
467− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
468451 generateQmlStrings(application);
469452 m_availableApplications.append(application);
470453
@@ -472,103 +455,27 @@ void ApplicationManager::buildListOfAvailableApplications()
472455 application->setAppId("pinterest");
473456 application->setName("Pinterest");
474457 application->setIcon(QUrl("pinterest"));
475− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
476458 m_availableApplications.append(application);
477459
478460 application = new ApplicationInfo(this);
479461 application->setAppId("soundcloud");
480462 application->setName("SoundCloud");
481463 application->setIcon(QUrl("soundcloud"));
482− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
483464 m_availableApplications.append(application);
484465
485466 application = new ApplicationInfo(this);
486467 application->setAppId("wikipedia");
487468 application->setName("Wikipedia");
488469 application->setIcon(QUrl("wikipedia"));
489− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
490470 m_availableApplications.append(application);
491471
492472 application = new ApplicationInfo(this);
493473 application->setAppId("youtube");
494474 application->setName("YouTube");
495475 application->setIcon(QUrl("youtube"));
496− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
497476 m_availableApplications.append(application);
498477}
499478
500−void ApplicationManager::createMainStageComponent()
501−{
502− // The assumptions I make here really should hold.
503− QQuickView *quickView =
504− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
505−
506− QQmlEngine *engine = quickView->engine();
507−
508− m_mainStageComponent = new QQmlComponent(engine, this);
509− QString mainStageQml =
510− "import QtQuick 2.0\n"
511− "Rectangle {\n"
512− " anchors.fill: parent\n"
513− " color: 'black'\n"
514− " z: -2000\n"
515− "}\n";
516− m_mainStageComponent->setData(mainStageQml.toLatin1(), QUrl());
517−}
518−
519−void ApplicationManager::createMainStage()
520−{
521− if (!m_mainStageComponent)
522− createMainStageComponent();
523−
524− // The assumptions I make here really should hold.
525− QQuickView *quickView =
526− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
527−
528− QQuickItem *shell = quickView->rootObject();
529−
530− m_mainStage = qobject_cast<QQuickItem *>(m_mainStageComponent->create());
531− m_mainStage->setParentItem(shell);
532−}
533−
534−void ApplicationManager::createSideStageComponent()
535−{
536− // The assumptions I make here really should hold.
537− QQuickView *quickView =
538− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
539−
540− QQmlEngine *engine = quickView->engine();
541−
542− m_sideStageComponent = new QQmlComponent(engine, this);
543− QString sideStageQml =
544− "import QtQuick 2.0\n"
545− "import Ubuntu.Components 0.1\n"
546− "Item {\n"
547− " width: units.gu(40)\n" // from SideStage in Shell.qml
548− " anchors.top: parent.top\n"
549− " anchors.bottom: parent.bottom\n"
550− " anchors.right: parent.right\n"
551− " z: -1000\n"
552− "}\n";
553− m_sideStageComponent->setData(sideStageQml.toLatin1(), QUrl());
554−}
555−
556−void ApplicationManager::createSideStage()
557−{
558− if (!m_sideStageComponent)
559− createSideStageComponent();
560−
561− // The assumptions I make here really should hold.
562− QQuickView *quickView =
563− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
564−
565− QQuickItem *shell = quickView->rootObject();
566−
567− m_sideStage = qobject_cast<QQuickItem *>(m_sideStageComponent->create());
568− m_sideStage->setParentItem(shell);
569− m_sideStage->setFlag(QQuickItem::ItemHasContents, false);
570−}
571−
572479QStringList ApplicationManager::availableApplications()
573480{
574481 QStringList appIds;
@@ -578,15 +485,7 @@ QStringList ApplicationManager::availableApplications()
578485 return appIds;
579486}
580487
581−int ApplicationManager::rightMargin() const
488+bool ApplicationManager::isEmpty() const
582489{
583− return m_rightMargin;
584−}
585−
586−void ApplicationManager::setRightMargin(int rightMargin)
587−{
588− m_rightMargin = rightMargin;
589− Q_FOREACH(ApplicationInfo *app, m_availableApplications) {
590− generateQmlStrings(app);
591− }
490+ return m_runningApplications.isEmpty();
592491}
tests/mocks/Unity/Application/ApplicationManager.h+14−24
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2014 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
@@ -36,8 +36,7 @@ class ApplicationManager : public ApplicationManagerInterface {
3636 Q_ENUMS(FavoriteApplication)
3737 Q_FLAGS(ExecFlags)
3838
39− Q_PROPERTY(int keyboardHeight READ keyboardHeight NOTIFY keyboardHeightChanged)
40− Q_PROPERTY(bool keyboardVisible READ keyboardVisible NOTIFY keyboardVisibleChanged)
39+ Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
4140
4241 Q_PROPERTY(int sideStageWidth READ sideStageWidth)
4342 Q_PROPERTY(StageHint stageHint READ stageHint)
@@ -45,14 +44,16 @@ class ApplicationManager : public ApplicationManagerInterface {
4544
4645 Q_PROPERTY(bool fake READ fake CONSTANT)
4746
48− // Only for testing
49− // This can be used to place some controls to right, like make tryPhoneStage for example
50− Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin)
51−
5247 public:
5348 ApplicationManager(QObject *parent = NULL);
5449 virtual ~ApplicationManager();
5550
51+ static ApplicationManager *singleton();
52+
53+ enum MoreRoles {
54+ RoleSurface = RoleScreenshot+1,
55+ RoleFullscreen,
56+ };
5657 enum Role {
5758 Dash, Default, Indicators, Notifications, Greeter, Launcher, OnScreenKeyboard,
5859 ShutdownDialog
@@ -74,8 +75,6 @@ class ApplicationManager : public ApplicationManagerInterface {
7475 };
7576 Q_DECLARE_FLAGS(ExecFlags, Flag)
7677
77− int keyboardHeight() const;
78− bool keyboardVisible() const;
7978 int sideStageWidth() const;
8079 StageHint stageHint() const;
8180 FormFactorHint formFactorHint() const;
@@ -105,14 +104,15 @@ class ApplicationManager : public ApplicationManagerInterface {
105104
106105 // Only for testing
107106 Q_INVOKABLE QStringList availableApplications();
108− int rightMargin() const;
109− void setRightMargin(int rightMargin);
107+
108+ QModelIndex findIndex(ApplicationInfo* application);
109+
110+ bool isEmpty() const;
110111
111112 Q_SIGNALS:
112− void keyboardHeightChanged();
113− void keyboardVisibleChanged();
114113 void focusRequested(FavoriteApplication favoriteApplication);
115114 void focusRequested(const QString &appId);
115+ void emptyChanged(bool empty);
116116
117117 private:
118118 void add(ApplicationInfo *application);
@@ -120,21 +120,11 @@ class ApplicationManager : public ApplicationManagerInterface {
120120 void showApplicationWindow(ApplicationInfo *application);
121121 void buildListOfAvailableApplications();
122122 void generateQmlStrings(ApplicationInfo *application);
123− void createMainStageComponent();
124− void createMainStage();
125− void createSideStageComponent();
126− void createSideStage();
127− int m_keyboardHeight;
128− bool m_keyboardVisible;
129123 bool m_suspended;
130124 QList<ApplicationInfo*> m_runningApplications;
131125 QList<ApplicationInfo*> m_availableApplications;
132− QQmlComponent *m_mainStageComponent;
133− QQuickItem *m_mainStage;
134− QQmlComponent *m_sideStageComponent;
135− QQuickItem *m_sideStage;
136126
137− int m_rightMargin;
127+ static ApplicationManager *the_application_manager;
138128};
139129
140130Q_DECLARE_OPERATORS_FOR_FLAGS(ApplicationManager::ExecFlags)
tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp+1−1
@@ -64,7 +64,7 @@ QImage ApplicationScreenshotProvider::requestImage(const QString &imageId, QSize
6464 Q_FOREACH (QWindow *win, unity->allWindows()) {
6565 QQuickWindow *quickWin = qobject_cast<QQuickWindow*>(win);
6666 if (quickWin) {
67− image = image.scaledToWidth(quickWin->width() - m_appManager->rightMargin());
67+ image = image.scaledToWidth(quickWin->width());
6868 break;
6969 }
7070 }
tests/mocks/Unity/Application/CMakeLists.txt+6−2
@@ -2,10 +2,14 @@ pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application)
22
33set(FakeUnityApplicationQml_SOURCES
44 plugin.cpp
5+ ApplicationDBusAdaptor.cpp
56 ApplicationInfo.cpp
67 ApplicationImage.cpp
78 ApplicationManager.cpp
89 ApplicationScreenshotProvider.cpp
10+ MirSurfaceItem.cpp
11+ SurfaceManager.cpp
12+ VirtualKeyboard.cpp
913 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
1014 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
1115)
@@ -15,8 +19,8 @@ add_library(FakeUnityApplicationQml MODULE ${FakeUnityApplicationQml_SOURCES})
1519add_library(NonMirUnityApplicationQml MODULE ${FakeUnityApplicationQml_SOURCES})
1620set_target_properties(NonMirUnityApplicationQml PROPERTIES OUTPUT_NAME FakeUnityApplicationQml)
1721
18−qt5_use_modules(FakeUnityApplicationQml Core Quick)
19−qt5_use_modules(NonMirUnityApplicationQml Core Quick)
22+qt5_use_modules(FakeUnityApplicationQml Core Quick DBus)
23+qt5_use_modules(NonMirUnityApplicationQml Core Quick DBus)
2024
2125add_unity8_mock(Unity.Application 0.1 Unity/Application PREFIX mocks TARGETS FakeUnityApplicationQml)
2226add_unity8_mock(Unity.Application 0.1 Unity/Application
tests/mocks/Unity/Application/MirSurfaceItem.cppnew file+172
@@ -0,0 +1,172 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "MirSurfaceItem.h"
18+#include "ApplicationInfo.h"
19+
20+#include <QPainter>
21+#include <QQmlEngine>
22+
23+MirSurfaceItem::MirSurfaceItem(const QString& name,
24+ MirSurfaceItem::Type type,
25+ MirSurfaceItem::State state,
26+ const QUrl& screenshot,
27+ QQuickItem *parent)
28+ : QQuickPaintedItem(parent)
29+ , m_application(nullptr)
30+ , m_name(name)
31+ , m_type(type)
32+ , m_state(state)
33+ , m_img(screenshot.isLocalFile() ? screenshot.toLocalFile() : screenshot.toString())
34+ , m_parentSurface(nullptr)
35+ , m_haveInputMethod(false)
36+{
37+ QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
38+
39+ // The virtual keyboard (input method) has a big transparent area so that
40+ // content behind it show through
41+ setFillColor(Qt::transparent);
42+
43+ connect(this, &QQuickItem::focusChanged,
44+ this, &MirSurfaceItem::onFocusChanged);
45+}
46+
47+MirSurfaceItem::~MirSurfaceItem()
48+{
49+ QList<MirSurfaceItem*> children(m_children);
50+ for (MirSurfaceItem* child : children) {
51+ child->setParentSurface(nullptr);
52+ }
53+ if (m_parentSurface)
54+ m_parentSurface->removeChildSurface(this);
55+
56+ if (m_application)
57+ m_application->setSurface(nullptr);
58+}
59+
60+void MirSurfaceItem::paint(QPainter * painter)
61+{
62+ if (!m_img.isNull()) {
63+ painter->drawImage(contentsBoundingRect(), m_img, QRect(QPoint(0,0), m_img.size()));
64+ }
65+}
66+
67+void MirSurfaceItem::release()
68+{
69+ QList<MirSurfaceItem*> children(m_children);
70+ for (MirSurfaceItem* child : children) {
71+ child->release();
72+ }
73+ if (m_parentSurface) {
74+ m_parentSurface->removeChildSurface(this);
75+ }
76+
77+ if (m_application) {
78+ m_application->setSurface(nullptr);
79+ }
80+ if (!parent()) {
81+ deleteLater();
82+ }
83+}
84+
85+void MirSurfaceItem::setApplication(ApplicationInfo* application)
86+{
87+ m_application = application;
88+}
89+
90+void MirSurfaceItem::setParentSurface(MirSurfaceItem* surface)
91+{
92+ if (m_parentSurface == surface || surface == this)
93+ return;
94+
95+ if (m_parentSurface) {
96+ m_parentSurface->removeChildSurface(this);
97+ }
98+
99+ m_parentSurface = surface;
100+
101+ if (m_parentSurface) {
102+ m_parentSurface->addChildSurface(this);
103+ }
104+ Q_EMIT parentSurfaceChanged(surface);
105+}
106+
107+void MirSurfaceItem::removeChildSurface(MirSurfaceItem* surface)
108+{
109+ if (m_children.contains(surface)) {
110+ m_children.removeOne(surface);
111+ Q_EMIT childSurfacesChanged();
112+ }
113+}
114+
115+void MirSurfaceItem::addChildSurface(MirSurfaceItem* surface)
116+{
117+ m_children.append(surface);
118+ Q_EMIT childSurfacesChanged();
119+}
120+
121+QList<MirSurfaceItem*> MirSurfaceItem::childSurfaceList()
122+{
123+ return m_children;
124+}
125+
126+QQmlListProperty<MirSurfaceItem> MirSurfaceItem::childSurfaces()
127+{
128+ return QQmlListProperty<MirSurfaceItem>(this,
129+ 0,
130+ MirSurfaceItem::childSurfaceCount,
131+ MirSurfaceItem::childSurfaceAt);
132+}
133+
134+int MirSurfaceItem::childSurfaceCount(QQmlListProperty<MirSurfaceItem> *prop)
135+{
136+ MirSurfaceItem *p = qobject_cast<MirSurfaceItem*>(prop->object);
137+ return p->m_children.count();
138+}
139+
140+MirSurfaceItem* MirSurfaceItem::childSurfaceAt(QQmlListProperty<MirSurfaceItem> *prop, int index)
141+{
142+ MirSurfaceItem *p = qobject_cast<MirSurfaceItem*>(prop->object);
143+
144+ if (index < 0 || index >= p->m_children.count())
145+ return nullptr;
146+ return p->m_children[index];
147+}
148+
149+
150+void MirSurfaceItem::touchEvent(QTouchEvent * event)
151+{
152+ if (event->type() == QEvent::TouchBegin && hasFocus()) {
153+ Q_EMIT inputMethodRequested();
154+ m_haveInputMethod = true;
155+ }
156+}
157+
158+void MirSurfaceItem::onFocusChanged()
159+{
160+ if (!hasFocus() && m_haveInputMethod) {
161+ Q_EMIT inputMethodDismissed();
162+ m_haveInputMethod = false;
163+ }
164+}
165+
166+void MirSurfaceItem::setState(MirSurfaceItem::State newState)
167+{
168+ if (newState != m_state) {
169+ m_state = newState;
170+ Q_EMIT stateChanged(newState);
171+ }
172+}
tests/mocks/Unity/Application/MirSurfaceItem.hnew file+121
@@ -0,0 +1,121 @@
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 MIRSURFACEITEM_H
18+#define MIRSURFACEITEM_H
19+
20+#include <QQuickPaintedItem>
21+#include <QImage>
22+
23+class ApplicationInfo;
24+
25+class MirSurfaceItem : public QQuickPaintedItem
26+{
27+ Q_OBJECT
28+ Q_ENUMS(Type)
29+ Q_ENUMS(State)
30+
31+ Q_PROPERTY(Type type READ type NOTIFY typeChanged)
32+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
33+ Q_PROPERTY(QString name READ name NOTIFY nameChanged)
34+ Q_PROPERTY(MirSurfaceItem* parentSurface READ parentSurface NOTIFY parentSurfaceChanged)
35+ Q_PROPERTY(QQmlListProperty<MirSurfaceItem> childSurfaces READ childSurfaces NOTIFY childSurfacesChanged DESIGNABLE false)
36+
37+public:
38+ enum Type {
39+ Normal,
40+ Utility,
41+ Dialog,
42+ Overlay,
43+ Freestyle,
44+ Popover,
45+ InputMethod,
46+ };
47+
48+ enum State {
49+ Unknown,
50+ Restored,
51+ Minimized,
52+ Maximized,
53+ VertMaximized,
54+ /* SemiMaximized, */
55+ Fullscreen,
56+ };
57+
58+ explicit MirSurfaceItem(const QString& name,
59+ Type type,
60+ State state,
61+ const QUrl& screenshot,
62+ QQuickItem *parent = 0);
63+ ~MirSurfaceItem();
64+
65+ //getters
66+ ApplicationInfo* application() const { return m_application; }
67+ Type type() const { return m_type; }
68+ State state() const { return m_state; }
69+ QString name() const { return m_name; }
70+ MirSurfaceItem* parentSurface() const { return m_parentSurface; }
71+ QList<MirSurfaceItem*> childSurfaceList();
72+
73+ void setApplication(ApplicationInfo* item);
74+ void setParentSurface(MirSurfaceItem* item);
75+
76+ Q_INVOKABLE void setState(State newState);
77+ Q_INVOKABLE void release();
78+
79+ void paint(QPainter * painter) override;
80+ void touchEvent(QTouchEvent * event) override;
81+
82+Q_SIGNALS:
83+ void typeChanged(Type);
84+ void stateChanged(State);
85+ void nameChanged(QString);
86+ void parentSurfaceChanged(MirSurfaceItem*);
87+ void childSurfacesChanged();
88+
89+ void removed();
90+
91+ void inputMethodRequested();
92+ void inputMethodDismissed();
93+
94+private Q_SLOTS:
95+ void onFocusChanged();
96+
97+protected:
98+ const QImage &screenshotImage() { return m_img; }
99+
100+private:
101+ void addChildSurface(MirSurfaceItem* surface);
102+ void removeChildSurface(MirSurfaceItem* surface);
103+
104+ QQmlListProperty<MirSurfaceItem> childSurfaces();
105+ static int childSurfaceCount(QQmlListProperty<MirSurfaceItem> *prop);
106+ static MirSurfaceItem* childSurfaceAt(QQmlListProperty<MirSurfaceItem> *prop, int index);
107+
108+ ApplicationInfo* m_application;
109+ const QString m_name;
110+ const Type m_type;
111+ State m_state;
112+ const QImage m_img;
113+
114+ MirSurfaceItem* m_parentSurface;
115+ QList<MirSurfaceItem*> m_children;
116+ bool m_haveInputMethod;
117+};
118+
119+Q_DECLARE_METATYPE(MirSurfaceItem*)
120+
121+#endif // MIRSURFACEITEM_H
tests/mocks/Unity/Application/SurfaceManager.cppnew file+73
@@ -0,0 +1,73 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "SurfaceManager.h"
18+
19+#include "MirSurfaceItem.h"
20+#include "VirtualKeyboard.h"
21+
22+
23+SurfaceManager *SurfaceManager::the_surface_manager = nullptr;
24+
25+SurfaceManager *SurfaceManager::singleton()
26+{
27+ if (!the_surface_manager) {
28+ the_surface_manager = new SurfaceManager();
29+ }
30+ return the_surface_manager;
31+}
32+
33+SurfaceManager::SurfaceManager(QObject *parent) :
34+ QObject(parent)
35+ , m_virtualKeyboard(nullptr)
36+{
37+}
38+
39+void SurfaceManager::registerSurface(MirSurfaceItem *surface)
40+{
41+ connect(surface, &MirSurfaceItem::inputMethodRequested,
42+ this, &SurfaceManager::showInputMethod);
43+ connect(surface, &MirSurfaceItem::inputMethodDismissed,
44+ this, &SurfaceManager::hideInputMethod);
45+ Q_EMIT surfaceCreated(surface);
46+}
47+
48+void SurfaceManager::unregisterSurface(MirSurfaceItem *surface)
49+{
50+ disconnect(surface, 0, this, 0);
51+ Q_EMIT surfaceDestroyed(surface);
52+}
53+
54+void SurfaceManager::showInputMethod()
55+{
56+ inputMethodSurface()->setState(MirSurfaceItem::Restored);
57+}
58+
59+void SurfaceManager::hideInputMethod()
60+{
61+ if (m_virtualKeyboard) {
62+ m_virtualKeyboard->setState(MirSurfaceItem::Minimized);
63+ }
64+}
65+
66+MirSurfaceItem *SurfaceManager::inputMethodSurface()
67+{
68+ if (!m_virtualKeyboard) {
69+ m_virtualKeyboard = new VirtualKeyboard(MirSurfaceItem::Minimized);
70+ Q_EMIT surfaceCreated(m_virtualKeyboard);
71+ }
72+ return m_virtualKeyboard;
73+}
tests/mocks/Unity/Application/SurfaceManager.hnew file+54
@@ -0,0 +1,54 @@
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 SURFACEMANAGER_H
18+#define SURFACEMANAGER_H
19+
20+#include <QObject>
21+
22+class MirSurfaceItem;
23+class VirtualKeyboard;
24+
25+class SurfaceManager : public QObject
26+{
27+ Q_OBJECT
28+public:
29+ explicit SurfaceManager(QObject *parent = 0);
30+
31+ static SurfaceManager *singleton();
32+
33+ // Internal mock use
34+ void registerSurface(MirSurfaceItem *surface);
35+ void unregisterSurface(MirSurfaceItem *surface);
36+
37+ // To be used in the tests
38+ Q_INVOKABLE MirSurfaceItem *inputMethodSurface();
39+
40+Q_SIGNALS:
41+ void countChanged();
42+ void surfaceCreated(MirSurfaceItem *surface);
43+ void surfaceDestroyed(MirSurfaceItem *surface);
44+
45+private Q_SLOTS:
46+ void showInputMethod();
47+ void hideInputMethod();
48+
49+private:
50+ static SurfaceManager *the_surface_manager;
51+ VirtualKeyboard *m_virtualKeyboard;
52+};
53+
54+#endif // SURFACEMANAGER_H
tests/mocks/Unity/Application/VirtualKeyboard.cppnew file+55
@@ -0,0 +1,55 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "VirtualKeyboard.h"
18+
19+#include <paths.h>
20+
21+VirtualKeyboard::VirtualKeyboard(State state, QQuickItem *parent)
22+ : MirSurfaceItem("input-method",
23+ MirSurfaceItem::InputMethod,
24+ state,
25+ QString("file://%1/Dash/graphics/phone/screenshots/vkb_portrait.png").arg(qmlDirectory()),
26+ parent)
27+{
28+}
29+
30+void VirtualKeyboard::touchEvent(QTouchEvent *event)
31+{
32+ if (event->type() == QEvent::TouchBegin && !hasTouchInsideKeyboard(event)) {
33+ event->ignore();
34+ }
35+}
36+
37+bool VirtualKeyboard::hasTouchInsideKeyboard(QTouchEvent *event)
38+{
39+ const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
40+ for (int i = 0; i < touchPoints.count(); ++i) {
41+ QPoint pos = touchPoints.at(i).pos().toPoint();
42+
43+ // Map to image coords
44+ int imageX = (int)( ( ((qreal)pos.x()) / width() ) * ((qreal)screenshotImage().size().width()) );
45+ int imageY = (int)( ( ((qreal)pos.y()) / height() ) * ((qreal)screenshotImage().size().height()) );
46+
47+ QRgb pixelHit = screenshotImage().pixel(imageX, imageY);
48+
49+ // The keyboard depicted in the image is in its opaque part.
50+ if (qAlpha(pixelHit) != 0) {
51+ return true;
52+ }
53+ }
54+ return false;
55+}
qml/Stages/SidestageHandle.qml → tests/mocks/Unity/Application/VirtualKeyboard.hrenamed+19−6
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -14,9 +14,22 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
17+#ifndef VIRTUALKEYBOARD_H
18+#define VIRTUALKEYBOARD_H
1919
20−BorderImage {
21− source: "graphics/sidestage_handle.sci"
22−}
20+#include "MirSurfaceItem.h"
21+
22+class VirtualKeyboard : public MirSurfaceItem
23+{
24+ Q_OBJECT
25+public:
26+ VirtualKeyboard(State state,
27+ QQuickItem *parent = 0);
28+
29+ void touchEvent(QTouchEvent * event) override;
30+
31+private:
32+ bool hasTouchInsideKeyboard(QTouchEvent *event);
33+};
34+
35+#endif // VIRTUALKEYBOARD_H
tests/mocks/Unity/Application/plugin.cpp+16−9
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -19,29 +19,37 @@
1919#include "ApplicationImage.h"
2020#include "ApplicationManager.h"
2121#include "ApplicationScreenshotProvider.h"
22+#include "MirSurfaceItem.h"
23+#include "SurfaceManager.h"
2224
2325#include <qqml.h>
2426#include <QQmlEngine>
2527
26−ApplicationManager *s_appManager = 0;
27−
2828static QObject* applicationManagerSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
2929 Q_UNUSED(engine);
3030 Q_UNUSED(scriptEngine);
31− if (!s_appManager) {
32− s_appManager = new ApplicationManager();
33− }
34− return s_appManager;
31+ return ApplicationManager::singleton();
32+}
33+
34+static QObject* surfaceManagerSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
35+ Q_UNUSED(engine);
36+ Q_UNUSED(scriptEngine);
37+ return SurfaceManager::singleton();
3538}
3639
3740void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri)
3841{
42+ qRegisterMetaType<MirSurfaceItem*>("MirSurfaceItem*");
43+
3944 qmlRegisterUncreatableType<unity::shell::application::ApplicationManagerInterface>(uri, 0, 1, "ApplicationManagerInterface", "Abstract interface. Cannot be created in QML");
4045 qmlRegisterSingletonType<ApplicationManager>(uri, 0, 1, "ApplicationManager", applicationManagerSingleton);
46+ qmlRegisterSingletonType<SurfaceManager>(uri, 0, 1, "SurfaceManager", surfaceManagerSingleton);
4147
4248 qmlRegisterUncreatableType<unity::shell::application::ApplicationInfoInterface>(uri, 0, 1, "ApplicationInfoInterface", "Abstract interface. Cannot be created in QML");
4349 qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");
4450
51+ qmlRegisterUncreatableType<MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem", "MirSurfaceItem can't be instantiated from QML");
52+
4553 qmlRegisterType<ApplicationImage>(uri, 0, 1, "ApplicationImage");
4654}
4755
@@ -49,6 +57,5 @@ void FakeUnityApplicationQmlPlugin::initializeEngine(QQmlEngine *engine, const c
4957{
5058 QQmlExtensionPlugin::initializeEngine(engine, uri);
5159
52− ApplicationManager* appManager = static_cast<ApplicationManager*>(applicationManagerSingleton(engine, NULL));
53− engine->addImageProvider(QLatin1String("application"), new ApplicationScreenshotProvider(appManager));
60+ engine->addImageProvider(QLatin1String("application"), new ApplicationScreenshotProvider(ApplicationManager::singleton()));
5461}
tests/mocks/Unity/CMakeLists.txt+4−3
@@ -2,11 +2,12 @@ add_subdirectory(Application)
22add_subdirectory(Indicators)
33add_subdirectory(Launcher)
44add_subdirectory(Notifications)
5+add_subdirectory(DashCommunicator)
56
67pkg_search_module(DEE dee-1.0 REQUIRED)
78pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
89pkg_search_module(DEEQT libdee-qt5 REQUIRED)
9−pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=2)
10+pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=4)
1011
1112include_directories(
1213 ${CMAKE_CURRENT_BINARY_DIR}
@@ -22,14 +23,14 @@ set(UnityQML_SOURCES
2223 fake_scope.cpp
2324 fake_scopes.cpp
2425 fake_categories.cpp
25− fake_department.cpp
26+ fake_navigation.cpp
2627 fake_resultsmodel.cpp
2728 fake_previewmodel.cpp
2829 fake_previewstack.cpp
2930 fake_previewwidgetmodel.cpp
3031 fake_unity_plugin.cpp
3132 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/CategoriesInterface.h
32− ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/DepartmentInterface.h
33+ ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/NavigationInterface.h
3334 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewModelInterface.h
3435 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewStackInterface.h
3536 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewWidgetModelInterface.h
tests/mocks/Unity/DashCommunicator/CMakeLists.txtnew file+18
@@ -0,0 +1,18 @@
1+include_directories(
2+ ${CMAKE_CURRENT_SOURCE_DIR}
3+)
4+
5+set(QMLDASHCOMMUNICATORPLUGIN_SRC
6+ plugin.cpp
7+ dashcommunicatorservice.cpp
8+ dashcommunicator.cpp
9+ )
10+
11+add_library(MockDashCommunicator-qml MODULE
12+ ${QMLDASHCOMMUNICATORPLUGIN_SRC}
13+ )
14+
15+qt5_use_modules(MockDashCommunicator-qml DBus Qml)
16+
17+# export the qmldir and qmltypes files
18+add_unity8_mock(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS MockDashCommunicator-qml)
tests/mocks/Unity/DashCommunicator/dashcommunicator.cppnew 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+#include "dashcommunicator.h"
18+
19+#include <QObject>
20+#include <QDBusConnection>
21+#include <QDBusInterface>
22+#include <QDebug>
23+
24+DashCommunicator::DashCommunicator(QObject *parent):
25+ QObject(parent)
26+{
27+}
28+
29+DashCommunicator::~DashCommunicator()
30+{
31+}
32+
33+
34+void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset)
35+{
36+ Q_EMIT setCurrentScopeCalled(scopeId, animate, reset);
37+}
tests/mocks/Unity/DashCommunicator/dashcommunicator.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 DASHCOMMUNICATOR_H
18+#define DASHCOMMUNICATOR_H
19+
20+#include <QObject>
21+
22+class DashCommunicator: public QObject
23+{
24+ Q_OBJECT
25+ Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26+
27+public:
28+ DashCommunicator(QObject *parent = 0);
29+ ~DashCommunicator();
30+
31+public Q_SLOTS:
32+ void setCurrentScope(const QString &scopeId, bool animate, bool reset);
33+
34+Q_SIGNALS:
35+ // This mock just emits calls back to the QML api for the plugin to verify calls
36+ void setCurrentScopeCalled(const QString &scopeId, bool animate, bool reset);
37+};
38+
39+#endif
tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cppnew file+33
@@ -0,0 +1,33 @@
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+{
22+}
23+
24+
25+DashCommunicatorService::~DashCommunicatorService()
26+{
27+
28+}
29+
30+void DashCommunicatorService::mockSetCurrentScope(const QString &scopeId, bool animate, bool reset)
31+{
32+ Q_EMIT setCurrentScopeRequested(scopeId, animate, reset);
33+}
tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.hnew file+36
@@ -0,0 +1,36 @@
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 <QObject>
21+
22+class DashCommunicatorService: public QObject
23+{
24+ Q_OBJECT
25+public:
26+ DashCommunicatorService(QObject *parent = 0);
27+ ~DashCommunicatorService();
28+
29+Q_SIGNALS:
30+ void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset);
31+
32+public Q_SLOTS:
33+ void mockSetCurrentScope(const QString &scopeId, bool animate, bool reset);
34+};
35+
36+#endif // DBUSUNITYSESSIONSERVICE_H
tests/mocks/Unity/DashCommunicator/plugin.cppnew file+31
@@ -0,0 +1,31 @@
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+ Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator"));
29+ qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService");
30+ qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator");
31+}
tests/mocks/Unity/DashCommunicator/plugin.hnew file+34
@@ -0,0 +1,34 @@
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+#ifndef DASHCOMMUNICATOR_PLUGIN_H
20+#define DASHCOMMUNICATOR_PLUGIN_H
21+
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlExtensionPlugin>
24+
25+class DashCommunicatorPlugin : public QQmlExtensionPlugin
26+{
27+ Q_OBJECT
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29+
30+public:
31+ void registerTypes(const char *uri);
32+};
33+
34+#endif
tests/mocks/Unity/DashCommunicator/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Unity.DashCommunicator
2+plugin MockDashCommunicator-qml
3+typeinfo DashCommunicator.qmltypes
tests/mocks/Unity/Unity.qmltypes+79−27
@@ -24,6 +24,12 @@ Module {
2424 Parameter { name: "categoryId"; type: "string" }
2525 Parameter { name: "json"; type: "string" }
2626 }
27+ Method {
28+ name: "data"
29+ type: "QVariant"
30+ Parameter { name: "row"; type: "int" }
31+ Parameter { name: "role"; type: "int" }
32+ }
2733 }
2834 Component {
2935 name: "PreviewModel"
@@ -62,6 +68,10 @@ Module {
6268 prototype: "unity::shell::scopes::ScopeInterface"
6369 exports: ["Unity/MockScope 0.2"]
6470 exportMetaObjectRevisions: [0]
71+ Signal {
72+ name: "performQuery"
73+ Parameter { name: "query"; type: "string" }
74+ }
6575 Method {
6676 name: "setSearchInProgress"
6777 Parameter { name: "inProg"; type: "bool" }
@@ -81,18 +91,21 @@ Module {
8191 Parameter { name: "scope"; type: "unity::shell::scopes::ScopeInterface"; isPointer: true }
8292 }
8393 Method {
84− name: "getDepartment"
85− type: "unity::shell::scopes::DepartmentInterface*"
86− Parameter { name: "id"; type: "string" }
94+ name: "getNavigation"
95+ type: "unity::shell::scopes::NavigationInterface*"
96+ Parameter { name: "navigationId"; type: "string" }
8797 }
8898 Method {
89− name: "loadDepartment"
90− Parameter { name: "id"; type: "string" }
99+ name: "getAltNavigation"
100+ type: "unity::shell::scopes::NavigationInterface*"
101+ Parameter { name: "altNavigationId"; type: "string" }
91102 }
92103 Method {
93− name: "performQuery"
94− Parameter { name: "query"; type: "string" }
104+ name: "setNavigationState"
105+ Parameter { name: "navigationId"; type: "string" }
106+ Parameter { name: "isAltNavigation"; type: "bool" }
95107 }
108+ Method { name: "refresh" }
96109 }
97110 Component {
98111 name: "Scopes"
@@ -137,6 +150,7 @@ Module {
137150 "RoleRawRendererTemplate": 3,
138151 "RoleRenderer": 4,
139152 "RoleComponents": 5,
153+ "RoleHeaderLink": 6,
140154 "RoleResults": 7,
141155 "RoleCount": 8
142156 }
@@ -157,27 +171,28 @@ Module {
157171 }
158172 }
159173 Component {
160− name: "unity::shell::scopes::DepartmentInterface"
174+ name: "unity::shell::scopes::NavigationInterface"
161175 prototype: "QAbstractListModel"
162− exports: ["Unity/Department 0.2"]
176+ exports: ["Unity/Navigation 0.2"]
163177 isCreatable: false
164178 exportMetaObjectRevisions: [0]
165179 Enum {
166180 name: "Roles"
167181 values: {
168− "RoleDepartmentId": 0,
182+ "RoleNavigationId": 0,
169183 "RoleLabel": 1,
170184 "RoleHasChildren": 2,
171185 "RoleIsActive": 3
172186 }
173187 }
174− Property { name: "departmentId"; type: "string"; isReadonly: true }
188+ Property { name: "navigationId"; type: "string"; isReadonly: true }
175189 Property { name: "label"; type: "string"; isReadonly: true }
176190 Property { name: "allLabel"; type: "string"; isReadonly: true }
177− Property { name: "parentDepartmentId"; type: "string"; isReadonly: true }
191+ Property { name: "parentNavigationId"; type: "string"; isReadonly: true }
178192 Property { name: "parentLabel"; type: "string"; isReadonly: true }
179193 Property { name: "loaded"; type: "bool"; isReadonly: true }
180194 Property { name: "isRoot"; type: "bool"; isReadonly: true }
195+ Property { name: "hidden"; type: "bool"; isReadonly: true }
181196 Property { name: "count"; type: "int"; isReadonly: true }
182197 }
183198 Component {
@@ -247,7 +262,8 @@ Module {
247262 "RoleEmblem": 8,
248263 "RoleSummary": 9,
249264 "RoleAttributes": 10,
250− "RoleBackground": 11
265+ "RoleBackground": 11,
266+ "RoleOverlayColor": 12
251267 }
252268 }
253269 Property { name: "categoryId"; type: "string" }
@@ -259,13 +275,22 @@ Module {
259275 exports: ["Unity/Scope 0.2"]
260276 isCreatable: false
261277 exportMetaObjectRevisions: [0]
278+ Enum {
279+ name: "Status"
280+ values: {
281+ "Okay": 0,
282+ "NoInternet": 1,
283+ "NoLocationData": 2,
284+ "Unknown": 3
285+ }
286+ }
262287 Property { name: "id"; type: "string"; isReadonly: true }
263288 Property { name: "name"; type: "string"; isReadonly: true }
264289 Property { name: "iconHint"; type: "string"; isReadonly: true }
265290 Property { name: "description"; type: "string"; isReadonly: true }
266291 Property { name: "searchHint"; type: "string"; isReadonly: true }
267292 Property { name: "searchInProgress"; type: "bool"; isReadonly: true }
268− Property { name: "visible"; type: "bool"; isReadonly: true }
293+ Property { name: "favorite"; type: "bool" }
269294 Property { name: "shortcut"; type: "string"; isReadonly: true }
270295 Property {
271296 name: "categories"
@@ -273,13 +298,27 @@ Module {
273298 isReadonly: true
274299 isPointer: true
275300 }
301+ Property {
302+ name: "settings"
303+ type: "unity::shell::scopes::SettingsModelInterface"
304+ isReadonly: true
305+ isPointer: true
306+ }
276307 Property { name: "searchQuery"; type: "string" }
277308 Property { name: "noResultsHint"; type: "string" }
278309 Property { name: "formFactor"; type: "string" }
279310 Property { name: "isActive"; type: "bool" }
280− Property { name: "currentDepartmentId"; type: "string"; isReadonly: true }
281− Property { name: "hasDepartments"; type: "bool"; isReadonly: true }
311+ Property { name: "currentNavigationId"; type: "string"; isReadonly: true }
312+ Property { name: "hasNavigation"; type: "bool"; isReadonly: true }
313+ Property { name: "currentAltNavigationId"; type: "string"; isReadonly: true }
314+ Property { name: "hasAltNavigation"; type: "bool"; isReadonly: true }
282315 Property { name: "customizations"; type: "QVariantMap"; isReadonly: true }
316+ Property {
317+ name: "status"
318+ type: "unity::shell::scopes::ScopeInterface::Status"
319+ isReadonly: true
320+ }
321+ Signal { name: "detailsChanged" }
283322 Signal { name: "showDash" }
284323 Signal { name: "hideDash" }
285324 Signal {
@@ -298,10 +337,6 @@ Module {
298337 name: "openScope"
299338 Parameter { name: "scope"; type: "unity::shell::scopes::ScopeInterface"; isPointer: true }
300339 }
301− Signal {
302− name: "activateApplication"
303− Parameter { name: "desktop"; type: "string" }
304− }
305340 Method {
306341 name: "activate"
307342 Parameter { name: "result"; type: "QVariant" }
@@ -317,14 +352,25 @@ Module {
317352 Parameter { name: "scope"; type: "unity::shell::scopes::ScopeInterface"; isPointer: true }
318353 }
319354 Method {
320− name: "getDepartment"
321− type: "unity::shell::scopes::DepartmentInterface*"
322− Parameter { name: "departmentId"; type: "string" }
355+ name: "getNavigation"
356+ type: "unity::shell::scopes::NavigationInterface*"
357+ Parameter { name: "navigationId"; type: "string" }
358+ }
359+ Method {
360+ name: "getAltNavigation"
361+ type: "unity::shell::scopes::NavigationInterface*"
362+ Parameter { name: "altNavigationId"; type: "string" }
323363 }
324364 Method {
325− name: "loadDepartment"
326− Parameter { name: "departmentId"; type: "string" }
365+ name: "setNavigationState"
366+ Parameter { name: "navId"; type: "string" }
367+ Parameter { name: "altNavigation"; type: "bool" }
327368 }
369+ Method {
370+ name: "performQuery"
371+ Parameter { name: "cannedQuery"; type: "string" }
372+ }
373+ Method { name: "refresh" }
328374 }
329375 Component {
330376 name: "unity::shell::scopes::ScopesInterface"
@@ -334,11 +380,17 @@ Module {
334380 values: {
335381 "RoleScope": 0,
336382 "RoleId": 1,
337− "RoleVisible": 2,
338− "RoleTitle": 3
383+ "RoleTitle": 2
339384 }
340385 }
341386 Property { name: "loaded"; type: "bool"; isReadonly: true }
387+ Property { name: "count"; type: "int"; isReadonly: true }
388+ Property {
389+ name: "overviewScope"
390+ type: "unity::shell::scopes::ScopeInterface"
391+ isReadonly: true
392+ isPointer: true
393+ }
342394 Method {
343395 name: "getScope"
344396 type: "unity::shell::scopes::ScopeInterface*"
tests/mocks/Unity/fake_categories.cpp+13−1
@@ -145,9 +145,12 @@ Categories::data(const QModelIndex& index, int role) const
145145 } else {
146146 map["category-layout"] = "carousel";
147147 map["card-size"] = "medium";
148− map["collapsed-rows"] = 2;
149148 map["overlay"] = true;
150149 }
150+ if (index.row() == 19) {
151+ map["category-layout"] = "grid";
152+ map["collapsed-rows"] = 0;
153+ }
151154 map["card-size"] = "small";
152155 return map;
153156 }
@@ -166,6 +169,9 @@ Categories::data(const QModelIndex& index, int role) const
166169 return map;
167170 }
168171 case RoleHeaderLink:
172+ if (index.row() == 1 || index.row() == 4) {
173+ return QString("scope://query/1");
174+ }
169175 return QString();
170176 case RoleResults:
171177 return QVariant::fromValue(resultsModel);
@@ -177,3 +183,9 @@ Categories::data(const QModelIndex& index, int role) const
177183 }
178184 }
179185}
186+
187+QVariant
188+Categories::data(int row, int role) const
189+{
190+ return data(index(row, 0), role);
191+}
tests/mocks/Unity/fake_categories.h+2
@@ -37,6 +37,8 @@ public:
3737 Q_INVOKABLE void addSpecialCategory(QString const& categoryId, QString const& name, QString const& icon, QString const& rawTemplate, QObject* countObject) override;
3838 Q_INVOKABLE bool overrideCategoryJson(QString const& categoryId, QString const& json) override;
3939
40+ Q_INVOKABLE QVariant data(int row, int role) const;
41+
4042private Q_SLOTS:
4143 void countChanged();
4244
tests/mocks/Unity/fake_department.cpp → tests/mocks/Unity/fake_navigation.cpprenamed+32−40
@@ -14,14 +14,15 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#include "fake_department.h"
17+#include "fake_navigation.h"
1818
1919#include "fake_scope.h"
2020
21+#include <QDebug>
2122#include <QTimer>
2223
23−Department::Department(const QString& departmentId, const QString& label, const QString& allLabel, const QString& parentId, const QString& parentLabel, Scope* scope)
24− : m_departmentId(departmentId)
24+Navigation::Navigation(const QString& navigationId, const QString& label, const QString& allLabel, const QString& parentId, const QString& parentLabel, Scope* scope)
25+ : m_navigationId(navigationId)
2526 , m_label(label)
2627 , m_allLabel(allLabel)
2728 , m_parentId(parentId)
@@ -30,96 +31,87 @@ Department::Department(const QString& departmentId, const QString& label, const
3031 , m_scope(scope)
3132{
3233 QTimer::singleShot(1500, this, SLOT(slotLoaded()));
33− connect(scope, SIGNAL(currentDepartmentIdChanged()), this, SLOT(slotCurrentDepartmentChanged()));
34+ connect(scope, SIGNAL(currentNavigationIdChanged()), this, SLOT(slotCurrentNavigationChanged()));
3435}
3536
36−QString Department::departmentId() const
37+QString Navigation::navigationId() const
3738{
38− return m_departmentId;
39+ return m_navigationId;
3940}
4041
41−QString Department::label() const
42+QString Navigation::label() const
4243{
4344 return m_label;
4445}
4546
46−QString Department::allLabel() const
47+QString Navigation::allLabel() const
4748{
4849 return m_allLabel;
4950}
5051
51−QString Department::parentDepartmentId() const
52+QString Navigation::parentNavigationId() const
5253{
5354 return m_parentId;
5455}
5556
56−QString Department::parentLabel() const
57+QString Navigation::parentLabel() const
5758{
5859 return m_parentLabel;
5960}
6061
61−void Department::slotLoaded()
62+void Navigation::slotLoaded()
6263{
6364 m_loaded = true;
6465 Q_EMIT loadedChanged();
6566}
6667
67−bool Department::loaded() const
68+bool Navigation::loaded() const
6869{
6970 return m_loaded;
7071}
7172
72−int Department::count() const
73+int Navigation::count() const
7374{
7475 return rowCount();
7576}
7677
77−bool Department::isRoot() const
78+bool Navigation::isRoot() const
7879{
79− return m_departmentId == "root";
80+ return m_navigationId == "root" || m_navigationId == "altroot";
8081}
8182
82−int Department::rowCount(const QModelIndex & /*parent*/) const
83+bool Navigation::hidden() const
8384{
84− if (!m_loaded || m_departmentId.startsWith("child") || m_departmentId == "middle3")
85− return 0;
86− else
87− return 8;
85+ return m_navigationId == "altroot";
8886}
8987
90−QHash<int, QByteArray> Department::roleNames() const
88+int Navigation::rowCount(const QModelIndex & /*parent*/) const
9189{
92− QHash<int, QByteArray> res;
93− res[RoleDepartmentId] = "departmentId";
94− res[RoleLabel] = "label";
95− res[RoleHasChildren] = "hasChildren";
96− res[RoleIsActive] = "isActive";
97− return res;
90+ if (!m_loaded || m_navigationId.startsWith("child") || m_navigationId == "middle3")
91+ return 0;
92+ else
93+ return 8;
9894}
9995
100−QVariant Department::data(const QModelIndex &index, int role) const
96+QVariant Navigation::data(const QModelIndex &index, int role) const
10197{
10298 switch (role) {
103− case RoleDepartmentId:
104− if (m_departmentId == "root")
99+ case RoleNavigationId:
100+ if (m_navigationId == "root")
105101 return QString("middle%1").arg(index.row());
106− else if (m_departmentId.startsWith("middle"))
107− return QString("child%1%2").arg(m_departmentId).arg(index.row());
108− break;
102+ else if (m_navigationId.startsWith("middle"))
103+ return QString("child%1%2").arg(m_navigationId).arg(index.row());
109104 case RoleLabel:
110− return QString("%1Child%2").arg(m_departmentId).arg(index.row());
111− break;
105+ return QString("%1Child%2").arg(m_navigationId).arg(index.row());
112106 case RoleHasChildren:
113− return m_departmentId == "root" && index.row() != 3;
114− break;
107+ return m_navigationId == "root" && index.row() != 3;
115108 case RoleIsActive:
116− return m_scope->currentDepartmentId() == data(index, RoleDepartmentId);
117− break;
109+ return m_scope->currentNavigationId() == data(index, RoleNavigationId);
118110 }
119111 return QVariant();
120112}
121113
122−void Department::slotCurrentDepartmentChanged()
114+void Navigation::slotCurrentNavigationChanged()
123115{
124116 // This is wasteful, should only emit it if really something changed in this
125117 // deparment, but this is a mock, so no need to optimize
tests/mocks/Unity/fake_department.h → tests/mocks/Unity/fake_navigation.hrenamed+13−13
@@ -14,48 +14,48 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#ifndef FAKE_DEPARTMENT_H
18−#define FAKE_DEPARTMENT_H
17+#ifndef FAKE_NAVIGATION_H
18+#define FAKE_NAVIGATION_H
1919
20−#include <unity/shell/scopes/DepartmentInterface.h>
20+#include <unity/shell/scopes/NavigationInterface.h>
2121
2222class Scope;
2323
24−class Department : public unity::shell::scopes::DepartmentInterface
24+class Navigation : public unity::shell::scopes::NavigationInterface
2525{
2626 Q_OBJECT
2727
2828public:
29− Department(const QString& departmentId, const QString& label, const QString& allLabel, const QString& parentId, const QString& parentLabel, Scope* scope);
29+ Navigation(const QString& navigationId, const QString& label, const QString& allLabel, const QString& parentId, const QString& parentLabel, Scope* scope);
3030
31− QString departmentId() const override;
31+ QString navigationId() const override;
3232 QString label() const override;
3333 QString allLabel() const override;
34− QString parentDepartmentId() const override;
34+ QString parentNavigationId() const override;
3535 QString parentLabel() const override;
3636 bool loaded() const override;
37− int count() const override;
3837 bool isRoot() const override;
38+ bool hidden() const override;
39+ int count() const override;
3940
4041 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
41− QHash<int, QByteArray> roleNames() const;
4242 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
4343
4444public Q_SLOTS:
45− void slotCurrentDepartmentChanged();
45+ void slotCurrentNavigationChanged();
4646
4747private Q_SLOTS:
4848 void slotLoaded();
4949
5050private:
51− QString m_departmentId;
51+ QString m_navigationId;
5252 QString m_label;
5353 QString m_allLabel;
5454 QString m_parentId;
5555 QString m_parentLabel;
5656 bool m_loaded;
57− QString m_currentDepartment;
57+ QString m_currentNavigation;
5858 Scope *m_scope;
5959};
6060
61−#endif // FAKE_DEPARTMENT_H
61+#endif // FAKE_NAVIGATION_H
tests/mocks/Unity/fake_scope.cpp+69−24
@@ -14,26 +14,28 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17+#include <QDebug>
1718#include <QUrl>
1819
1920#include "fake_scope.h"
20−#include "fake_department.h"
21+#include "fake_navigation.h"
2122#include "fake_resultsmodel.h"
2223
2324Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)
2425{
2526}
2627
27−Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
28+Scope::Scope(QString const& id, QString const& name, bool favorite, QObject* parent, int categories)
2829 : unity::shell::scopes::ScopeInterface(parent)
2930 , m_id(id)
3031 , m_name(name)
31− , m_visible(visible)
3232 , m_searching(false)
33+ , m_favorite(favorite)
3334 , m_isActive(false)
34− , m_currentDeparment("root")
35+ , m_currentNavigationId("root")
36+ , m_currentAltNavigationId("altroot")
3537 , m_previewRendererName("preview-generic")
36− , m_categories(new Categories(20, this))
38+ , m_categories(new Categories(categories, this))
3739{
3840}
3941
@@ -77,6 +79,11 @@ bool Scope::searchInProgress() const
7779 return m_searching;
7880}
7981
82+bool Scope::favorite() const
83+{
84+ return m_favorite;
85+}
86+
8087unity::shell::scopes::CategoriesInterface* Scope::categories() const
8188{
8289 return m_categories;
@@ -97,11 +104,6 @@ QString Scope::formFactor() const
97104 return m_formFactor;
98105}
99106
100−bool Scope::visible() const
101−{
102− return m_visible;
103−}
104−
105107bool Scope::isActive() const
106108{
107109 return m_isActive;
@@ -131,6 +133,13 @@ void Scope::setActive(const bool active)
131133 }
132134}
133135
136+void Scope::setFavorite(const bool favorite)
137+{
138+ if (favorite != m_favorite) {
139+ m_favorite = favorite;
140+ Q_EMIT favoriteChanged();
141+ }
142+}
134143void Scope::setSearchInProgress(const bool inProg)
135144{
136145 if (inProg != m_searching) {
@@ -170,31 +179,53 @@ void Scope::closeScope(unity::shell::scopes::ScopeInterface* /*scope*/)
170179 qFatal("Scope::closeScope is not implemented");
171180}
172181
173−QString Scope::currentDepartmentId() const
182+QString Scope::currentNavigationId() const
174183{
175− return m_currentDeparment;
184+ return m_currentNavigationId;
176185}
177186
178−bool Scope::hasDepartments() const
187+bool Scope::hasNavigation() const
179188{
180189 return true;
181190}
182191
192+QString Scope::currentAltNavigationId() const
193+{
194+ return m_currentAltNavigationId;
195+}
196+
197+bool Scope::hasAltNavigation() const
198+{
199+ return true;
200+}
201+
202+Scope::Status Scope::status() const
203+{
204+ return Status::Okay;
205+}
206+
183207QVariantMap Scope::customizations() const
184208{
185− QVariantMap m;
209+ QVariantMap m, h;
186210 if (m_id == "clickscope") {
211+ h["foreground-color"] = "yellow";
187212 m["background-color"] = "red";
188213 m["foreground-color"] = "blue";
214+ m["page-header"] = h;
189215 } else if (m_id == "MockScope5") {
190− QVariantMap pageHeader;
191− pageHeader["logo"] = QUrl("../../../tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg");
192− m["page-header"] = pageHeader;
216+ h["background"] = "gradient:///lightgrey/grey";
217+ h["logo"] = QUrl("../../../tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg");
218+ m["page-header"] = h;
193219 }
194220 return m;
195221}
196222
197−unity::shell::scopes::DepartmentInterface* Scope::getDepartment(const QString& id)
223+void Scope::refresh()
224+{
225+ qDebug() << "Scope::refresh is currently not implmented in the fake scopes plugin";
226+}
227+
228+unity::shell::scopes::NavigationInterface* Scope::getNavigation(const QString& id)
198229{
199230 if (id.isEmpty())
200231 return nullptr;
@@ -208,16 +239,30 @@ unity::shell::scopes::DepartmentInterface* Scope::getDepartment(const QString& i
208239 parentId = id.mid(5, 7);
209240 parentLabel = parentId;
210241 }
211− return new Department(id, id, "all"+id, parentId, parentLabel, this);
242+ return new Navigation(id, id, "all"+id, parentId, parentLabel, this);
212243}
213244
214−void Scope::loadDepartment(const QString& id)
245+unity::shell::scopes::NavigationInterface* Scope::getAltNavigation(QString const& id)
215246{
216− m_currentDeparment = id;
217− Q_EMIT currentDepartmentIdChanged();
247+ if (id.isEmpty())
248+ return nullptr;
249+
250+ QString parentId;
251+ QString parentLabel;
252+ if (id.startsWith("altmiddle")) {
253+ parentId = "altroot";
254+ parentLabel = "altroot";
255+ }
256+ return new Navigation(id, id, "all"+id, parentId, parentLabel, this);
218257}
219258
220−void Scope::performQuery(const QString& query)
259+void Scope::setNavigationState(const QString &navigationId, bool isAltNavigation)
221260{
222− Q_UNUSED(query);
261+ if (isAltNavigation) {
262+ m_currentAltNavigationId = navigationId;
263+ Q_EMIT currentAltNavigationIdChanged();
264+ } else {
265+ m_currentNavigationId = navigationId;
266+ Q_EMIT currentNavigationIdChanged();
267+ }
223268}
tests/mocks/Unity/fake_scope.h+17−9
@@ -30,7 +30,7 @@ class Scope : public unity::shell::scopes::ScopeInterface
3030
3131public:
3232 Scope(QObject* parent = 0);
33− Scope(QString const& id, QString const& name, bool visible, QObject* parent = 0);
33+ Scope(QString const& id, QString const& name, bool favorite, QObject* parent = 0, int categories = 20);
3434
3535 /* getters */
3636 QString id() const override;
@@ -38,9 +38,9 @@ public:
3838 QString iconHint() const override;
3939 QString description() const override;
4040 QString searchHint() const override;
41− bool visible() const override;
4241 QString shortcut() const override;
4342 bool searchInProgress() const override;
43+ bool favorite() const override;
4444 unity::shell::scopes::CategoriesInterface* categories() const override;
4545 QString searchQuery() const override;
4646 QString noResultsHint() const override;
@@ -53,6 +53,7 @@ public:
5353 void setNoResultsHint(const QString& hint) override;
5454 void setFormFactor(const QString& form_factor) override;
5555 void setActive(const bool) override;
56+ void setFavorite(const bool) override;
5657 Q_INVOKABLE void setSearchInProgress(const bool inProg); // This is not invokable in the Interface, here for testing benefits
5758
5859 Q_INVOKABLE void activate(QVariant const& result) override;
@@ -60,14 +61,20 @@ public:
6061 Q_INVOKABLE void cancelActivation() override;
6162 Q_INVOKABLE void closeScope(unity::shell::scopes::ScopeInterface* scope) override;
6263
63− QString currentDepartmentId() const override;
64− bool hasDepartments() const override;
65− Q_INVOKABLE unity::shell::scopes::DepartmentInterface* getDepartment(const QString& id) override;
66− Q_INVOKABLE void loadDepartment(const QString& id) override;
67− Q_INVOKABLE void performQuery(const QString& query) override;
64+ QString currentNavigationId() const override;
65+ bool hasNavigation() const override;
66+ QString currentAltNavigationId() const override;
67+ bool hasAltNavigation() const override;
68+ Q_INVOKABLE unity::shell::scopes::NavigationInterface* getNavigation(QString const& navigationId) override;
69+ Q_INVOKABLE unity::shell::scopes::NavigationInterface* getAltNavigation(QString const& altNavigationId) override;
70+ Q_INVOKABLE void setNavigationState(const QString &navigationId, bool isAltNavigation) override;
71+ Q_SIGNAL void performQuery(const QString& query) override;
6872
73+ Status status() const override;
6974 QVariantMap customizations() const override;
7075
76+ Q_INVOKABLE void refresh() override;
77+
7178protected:
7279
7380 QString m_id;
@@ -77,10 +84,11 @@ protected:
7784 QString m_searchQuery;
7885 QString m_noResultsHint;
7986 QString m_formFactor;
80− bool m_visible;
8187 bool m_searching;
88+ bool m_favorite;
8289 bool m_isActive;
83− QString m_currentDeparment;
90+ QString m_currentNavigationId;
91+ QString m_currentAltNavigationId;
8492
8593 QString m_previewRendererName;
8694
tests/mocks/Unity/fake_scopes.cpp+16−2
@@ -32,6 +32,11 @@ Scopes::Scopes(QObject *parent)
3232 timer.setSingleShot(true);
3333 timer.setInterval(100);
3434 QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(updateScopes()));
35+
36+ QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
37+ QObject::connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
38+ QObject::connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged()));
39+
3540 load();
3641}
3742
@@ -46,6 +51,7 @@ void Scopes::updateScopes()
4651 addScope(new Scope("MockScope2", "Music", false, this));
4752 addScope(new Scope("clickscope", "Apps", true, this));
4853 addScope(new Scope("MockScope5", "Videos", true, this));
54+ addScope(new Scope("SingleCategoryScope", "Single", true, this, 1));
4955
5056 if (!m_loaded) {
5157 m_loaded = true;
@@ -91,8 +97,6 @@ QVariant Scopes::data(const QModelIndex& index, int role) const
9197 return QVariant::fromValue(scope);
9298 } else if (role == Scopes::RoleId) {
9399 return QVariant::fromValue(scope->id());
94− } else if (role == Scopes::RoleVisible) {
95− return QVariant::fromValue(scope->visible());
96100 } else if (role == Scopes::RoleTitle) {
97101 return QVariant::fromValue(scope->name());
98102 } else {
@@ -124,6 +128,16 @@ bool Scopes::loaded() const
124128 return m_loaded;
125129}
126130
131+int Scopes::count() const
132+{
133+ return rowCount();
134+}
135+
136+unity::shell::scopes::ScopeInterface* Scopes::overviewScope() const
137+{
138+ return nullptr;
139+}
140+
127141void Scopes::addScope(Scope* scope)
128142{
129143 int index = rowCount();
tests/mocks/Unity/fake_scopes.h+2
@@ -50,6 +50,8 @@ public:
5050 QModelIndex parent ( const QModelIndex & index ) const;
5151
5252 bool loaded() const override;
53+ int count() const override;
54+ unity::shell::scopes::ScopeInterface* overviewScope() const override;
5355
5456private Q_SLOTS:
5557 void updateScopes();
tests/mocks/Unity/fake_unity_plugin.cpp+2−2
@@ -22,7 +22,7 @@
2222// local
2323#include "fake_scopes.h"
2424#include "fake_categories.h"
25−#include "fake_department.h"
25+#include "fake_navigation.h"
2626#include "fake_previewmodel.h"
2727#include "fake_previewwidgetmodel.h"
2828#include "fake_resultsmodel.h"
@@ -43,7 +43,7 @@ void FakeUnityPlugin::registerTypes(const char *uri)
4343 qmlRegisterType<Scopes>(uri, 0, 2, "Scopes");
4444 qmlRegisterType<Scope>(uri, 0, 2, "MockScope");
4545 qmlRegisterUncreatableType<unity::shell::scopes::ScopeInterface>(uri, 0, 2, "Scope", "Can't create Scope object in QML.");
46− qmlRegisterUncreatableType<unity::shell::scopes::DepartmentInterface>(uri, 0, 2, "Department", "Can't create Department object in QML.");
46+ qmlRegisterUncreatableType<unity::shell::scopes::NavigationInterface>(uri, 0, 2, "Navigation", "Can't create Navigation object in QML.");
4747 qmlRegisterUncreatableType<unity::shell::scopes::CategoriesInterface>(uri, 0, 2, "Categories", "Can't create Categories object in QML.");
4848 qmlRegisterUncreatableType<unity::shell::scopes::PreviewModelInterface>(uri, 0, 2, "PreviewModel", "Can't create new PreviewModel in QML. Get them from PreviewStack instance.");
4949 qmlRegisterUncreatableType<ResultsModel>(uri, 0, 2, "ResultsModel", "Can't create ResultsModel object in QML.");
tests/mocks/libusermetrics/UserMetrics.cpp+3
@@ -24,6 +24,9 @@
2424#include <QtGui/QIcon>
2525#include <QMultiMap>
2626
27+#include <functional>
28+#include <random>
29+
2730using namespace UserMetricsOutput;
2831
2932namespace UserMetricsOutput
tests/plugins/Dash/CMakeLists.txt+1
@@ -79,3 +79,4 @@ set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
7979set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
8080add_qml_test(. ScopeStyle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
8181add_qml_test(. ListViewWithPageHeaderQML IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
82+add_qml_test(. CardAttributes IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
tests/plugins/Dash/cardcreator/1.res+65−61
@@ -5,8 +5,8 @@ AbstractButton {
55 property var cardData;
66 property var artShapeBorderSource: undefined;
77 property real fontScale: 1.0;
8− property var scopeStyle: null;
9− property int headerAlignment: Text.AlignLeft;
8+ property var scopeStyle: null;
9+ property int headerAlignment: Text.AlignLeft;
1010 property int fixedHeaderHeight: -1;
1111 property size fixedArtShapeSize: Qt.size(-1, -1);
1212 readonly property string title: cardData && cardData["title"] || "";
@@ -16,71 +16,75 @@ AbstractButton {
1616onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
1717readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
1818Item {
19− id: artShapeHolder;
20− height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
21− width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
22− anchors { horizontalCenter: parent.horizontalCenter; }
23− Loader {
24− id: artShapeLoader;
25− objectName: "artShapeLoader";
26− active: cardData && cardData["art"] || false;
27− asynchronous: root.asynchronous;
28− visible: status == Loader.Ready;
29− sourceComponent: UbuntuShape {
30− id: artShape;
31− objectName: "artShape";
32− radius: "medium";
33− visible: image.status == Image.Ready;
34− readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35− readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36− readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
37− Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
38− onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
39− Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
40− function updateWidthHeightBindings() {
41− if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
42− width = root.fixedArtShapeSize.width;
43− height = root.fixedArtShapeSize.height;
44− } else if (aspectSmallerThanImageAspect) {
45− width = Qt.binding(function() { return !visible ? 0 : image.width });
46− height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
47− } else {
48− width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
49− height = Qt.binding(function() { return !visible ? 0 : image.height });
50− }
51− }
52− image: Image {
53− objectName: "artImage";
54− source: cardData && cardData["art"] || "";
55− cache: true;
19+ id: artShapeHolder;
20+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
21+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
22+ anchors { horizontalCenter: parent.horizontalCenter; }
23+ Loader {
24+ id: artShapeLoader;
25+ objectName: "artShapeLoader";
26+ active: cardData && cardData["art"] || false;
5627 asynchronous: root.asynchronous;
57− fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
58− readonly property real aspect: implicitWidth / implicitHeight;
59− width: root.width;
60− height: width / artShape.aspect;
28+ visible: status == Loader.Ready;
29+ sourceComponent: UbuntuShape {
30+ id: artShape;
31+ objectName: "artShape";
32+ radius: "medium";
33+ visible: image.status == Image.Ready;
34+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36+ Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
37+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
38+ function updateWidthHeightBindings() {
39+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
40+ width = root.fixedArtShapeSize.width;
41+ height = root.fixedArtShapeSize.height;
42+ } else {
43+ width = Qt.binding(function() { return !visible ? 0 : image.width });
44+ height = Qt.binding(function() { return !visible ? 0 : image.height });
45+ }
46+ }
47+ image: Image {
48+ objectName: "artImage";
49+ source: cardData && cardData["art"] || "";
50+ cache: true;
51+ asynchronous: root.asynchronous;
52+ fillMode: Image.PreserveAspectCrop;
53+ width: root.width;
54+ height: width / artShape.aspect;
55+ }
56+ }
6157 }
62− }
63− }
64− }
58+ }
6559readonly property int headerHeight: titleLabel.height;
6660Label {
67− id: titleLabel;
68− objectName: "titleLabel";
69− anchors { right: parent.right;left: parent.left;
61+ id: titleLabel;
62+ objectName: "titleLabel";
63+ anchors { right: parent.right;
64+rightMargin: units.gu(1);
65+left: parent.left;
7066top: artShapeHolder.bottom;
7167 topMargin: units.gu(1);
7268leftMargin: units.gu(1);
73− }
74− elide: Text.ElideRight;
75− fontSize: "small";
76− wrapMode: Text.Wrap;
77− maximumLineCount: 2;
78− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
79− color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
80− visible: showHeader ;
81− text: root.title;
82− font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
83− horizontalAlignment: root.headerAlignment;
84− }
69+ }
70+ elide: Text.ElideRight;
71+ fontSize: "small";
72+ wrapMode: Text.Wrap;
73+ maximumLineCount: 2;
74+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
75+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
76+ visible: showHeader ;
77+ text: root.title;
78+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
79+ horizontalAlignment: root.headerAlignment;
80+ }
81+UbuntuShape {
82+ id: touchdown;
83+ objectName: "touchdown";
84+ anchors { fill: artShapeHolder }
85+ visible: root.pressed;
86+ radius: "medium";
87+ borderSource: "radius_pressed.sci"
88+}
8589implicitHeight: titleLabel.y + titleLabel.height + units.gu(1);
8690}
tests/plugins/Dash/cardcreator/1.tst+1−1
@@ -1,3 +1,3 @@
11template: {"card-layout":"vertical","card-size":"small","category-layout":"grid","collapsed-rows":2}
2−components: {"art":{"aspect-ratio":1.6,"field":"art","fill-mode":"fit"},"title":{"field":"title"}}
2+components: {"art":{"aspect-ratio":1.6,"field":"art"},"title":{"field":"title"}}
33result: 1.res
tests/plugins/Dash/cardcreator/2.res+101−90
@@ -5,8 +5,8 @@ AbstractButton {
55 property var cardData;
66 property var artShapeBorderSource: undefined;
77 property real fontScale: 1.0;
8− property var scopeStyle: null;
9− property int headerAlignment: Text.AlignLeft;
8+ property var scopeStyle: null;
9+ property int headerAlignment: Text.AlignLeft;
1010 property int fixedHeaderHeight: -1;
1111 property size fixedArtShapeSize: Qt.size(-1, -1);
1212 readonly property string title: cardData && cardData["title"] || "";
@@ -14,104 +14,115 @@ AbstractButton {
1414 property bool showHeader: true;
1515 implicitWidth: childrenRect.width;
1616Loader {
17− id: backgroundLoader;
18− objectName: "backgroundLoader";
19− anchors.fill: parent;
20− asynchronous: root.asynchronous;
21− visible: status == Loader.Ready;
22− sourceComponent: UbuntuShape {
23− objectName: "background";
24− radius: "medium";
25− color: getColor(0) || "white";
26− gradientColor: getColor(1) || color;
27− anchors.fill: parent;
28− image: backgroundImage.source ? backgroundImage : null;
29− property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
30− property Image backgroundImage: Image {
31− objectName: "backgroundImage";
32− source: {
33− if (cardData && typeof cardData["background"] === "string") return cardData["background"];
34− else if (template && typeof template["card-background"] === "string") return template["card-background"];
35− else return "";
36− }
37− }
38− function getColor(index) {
39− if (cardData && typeof cardData["background"] === "object"
40− && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
41− return cardData["background"]["elements"][index];
42− } else if (template && typeof template["card-background"] === "object"
43− && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
44− return template["card-background"]["elements"][index];
45− } else return undefined;
46− }
47− }
48− }
17+ id: backgroundLoader;
18+ objectName: "backgroundLoader";
19+ anchors.fill: parent;
20+ asynchronous: root.asynchronous;
21+ visible: status == Loader.Ready;
22+ sourceComponent: UbuntuShape {
23+ objectName: "background";
24+ radius: "medium";
25+ color: getColor(0) || "white";
26+ gradientColor: getColor(1) || color;
27+ anchors.fill: parent;
28+ image: backgroundImage.source ? backgroundImage : null;
29+ property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
30+ property Image backgroundImage: Image {
31+ objectName: "backgroundImage";
32+ source: {
33+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
34+ else if (template && typeof template["card-background"] === "string") return template["card-background"];
35+ else return "";
36+ }
37+ }
38+ function getColor(index) {
39+ if (cardData && typeof cardData["background"] === "object"
40+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
41+ return cardData["background"]["elements"][index];
42+ } else if (template && typeof template["card-background"] === "object"
43+ && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
44+ return template["card-background"]["elements"][index];
45+ } else return undefined;
46+ }
47+ }
48+ }
4949readonly property size artShapeSize: Qt.size(-1, -1);
5050readonly property int headerHeight: row.height;
5151Row {
52− id: row;
53− objectName: "outerRow";
54− property real margins: units.gu(1);
55− spacing: margins;
56− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
57− anchors { top: parent.top;
52+ id: row;
53+ objectName: "outerRow";
54+ property real margins: units.gu(1);
55+ spacing: margins;
56+ height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
57+ anchors { top: parent.top;
5858 topMargin: units.gu(1);
59− left: parent.left;
60−}
61− anchors.right: parent.right;
62− anchors.margins: margins;
63−data: [ Image {
64− id: mascotImage;
65− objectName: "mascotImage";
66− anchors { verticalCenter: parent.verticalCenter; }
67− readonly property int maxSize: Math.max(width, height) * 4;
68− source: cardData && cardData["mascot"];
69− width: units.gu(6);
70− height: units.gu(5.625);
71− sourceSize { width: maxSize; height: maxSize }
72− fillMode: Image.PreserveAspectCrop;
73− horizontalAlignment: Image.AlignHCenter;
74− verticalAlignment: Image.AlignVCenter;
75− visible: showHeader;
76− }
77−,
78−Column {
79− anchors.verticalCenter: parent.verticalCenter;
80− spacing: units.dp(2);
81− width: parent.width - x;
82− data: [ Label {
83− id: titleLabel;
84− objectName: "titleLabel";
85− anchors { left: parent.left; right: parent.right }
86− elide: Text.ElideRight;
87− fontSize: "small";
88− wrapMode: Text.Wrap;
89− maximumLineCount: 2;
90− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
91− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
92− visible: showHeader ;
93− text: root.title;
94− font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
95− horizontalAlignment: root.headerAlignment;
96− }
97−,
98−Label {
99− id: subtitleLabel;
100− objectName: "subtitleLabel";
101− anchors { left: parent.left; right: parent.right }
59+left: parent.left;
60+ }
61+ anchors.right: parent.right;
62+ anchors.margins: margins;
63+ data: [ Image {
64+ id: mascotImage;
65+ objectName: "mascotImage";
66+ anchors { verticalCenter: parent.verticalCenter; }
67+ readonly property int maxSize: Math.max(width, height) * 4;
68+ source: cardData && cardData["mascot"];
69+ width: units.gu(6);
70+ height: units.gu(5.625);
71+ sourceSize { width: maxSize; height: maxSize }
72+ fillMode: Image.PreserveAspectCrop;
73+ horizontalAlignment: Image.AlignHCenter;
74+ verticalAlignment: Image.AlignVCenter;
75+ visible: showHeader;
76+ }
10277
78+ ,
79+ Column {
80+ anchors.verticalCenter: parent.verticalCenter;
81+ spacing: units.dp(2);
82+ width: parent.width - x;
83+ data: [ Label {
84+ id: titleLabel;
85+ objectName: "titleLabel";
86+ anchors { left: parent.left; right: parent.right }
10387 elide: Text.ElideRight;
10488 fontSize: "small";
89+ wrapMode: Text.Wrap;
90+ maximumLineCount: 2;
10591 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
106− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
107− visible: titleLabel.visible && titleLabel.text;
108− text: cardData && cardData["subtitle"] || "";
109− font.weight: Font.Light;
92+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
93+ visible: showHeader ;
94+ text: root.title;
95+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
11096 horizontalAlignment: root.headerAlignment;
11197 }
112−]
113−}
114−]
98+
99+ ,
100+ Label {
101+ id: subtitleLabel;
102+ objectName: "subtitleLabel";
103+ anchors { left: parent.left; right: parent.right }
104+ elide: Text.ElideRight;
105+ fontSize: "small";
106+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
107+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
108+ visible: titleLabel.visible && titleLabel.text;
109+ text: cardData && cardData["subtitle"] || "";
110+ font.weight: Font.Light;
111+ horizontalAlignment: root.headerAlignment;
112+ }
113+
114+ ]
115+ }
116+
117+ ]
118+ }
119+UbuntuShape {
120+ id: touchdown;
121+ objectName: "touchdown";
122+ anchors { fill: backgroundLoader }
123+ visible: root.pressed;
124+ radius: "medium";
125+ borderSource: "radius_pressed.sci"
115126}
116127implicitHeight: row.y + row.height + units.gu(1);
117128}
tests/plugins/Dash/cardcreator/2.tst+1−1
@@ -1,3 +1,3 @@
11template: {"card-background":{"elements":["#E9E9E9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
2−components: {"art":{"aspect-ratio":1,"fill-mode":"crop"},"background":{"field":"background"},"mascot":{"field":"icon"},"subtitle":{"field":"author"},"title":{"field":"title"}}
2+components: {"art":{"aspect-ratio":1},"background":{"field":"background"},"mascot":{"field":"icon"},"subtitle":{"field":"author"},"title":{"field":"title"}}
33result: 2.res
tests/plugins/Dash/cardcreator/3.res+79−74
@@ -5,8 +5,8 @@ AbstractButton {
55 property var cardData;
66 property var artShapeBorderSource: undefined;
77 property real fontScale: 1.0;
8− property var scopeStyle: null;
9− property int headerAlignment: Text.AlignLeft;
8+ property var scopeStyle: null;
9+ property int headerAlignment: Text.AlignLeft;
1010 property int fixedHeaderHeight: -1;
1111 property size fixedArtShapeSize: Qt.size(-1, -1);
1212 readonly property string title: cardData && cardData["title"] || "";
@@ -16,89 +16,94 @@ AbstractButton {
1616onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
1717readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
1818Item {
19− id: artShapeHolder;
20− height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
21− width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
22− anchors { horizontalCenter: parent.horizontalCenter; }
23− Loader {
24− id: artShapeLoader;
25− objectName: "artShapeLoader";
26− active: cardData && cardData["art"] || false;
27− asynchronous: root.asynchronous;
28− visible: status == Loader.Ready;
29− sourceComponent: UbuntuShape {
30− id: artShape;
31− objectName: "artShape";
32− radius: "medium";
33− visible: image.status == Image.Ready;
34− readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35− readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36− readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
37− Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
38− onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
39− Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
40− function updateWidthHeightBindings() {
41− if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
42− width = root.fixedArtShapeSize.width;
43− height = root.fixedArtShapeSize.height;
44− } else if (aspectSmallerThanImageAspect) {
45− width = Qt.binding(function() { return !visible ? 0 : image.width });
46− height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
47− } else {
48− width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
49− height = Qt.binding(function() { return !visible ? 0 : image.height });
50− }
51− }
52− image: Image {
53− objectName: "artImage";
54− source: cardData && cardData["art"] || "";
55− cache: true;
19+ id: artShapeHolder;
20+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
21+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
22+ anchors { horizontalCenter: parent.horizontalCenter; }
23+ Loader {
24+ id: artShapeLoader;
25+ objectName: "artShapeLoader";
26+ active: cardData && cardData["art"] || false;
5627 asynchronous: root.asynchronous;
57− fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
58− readonly property real aspect: implicitWidth / implicitHeight;
59− width: root.width;
60− height: width / artShape.aspect;
28+ visible: status == Loader.Ready;
29+ sourceComponent: UbuntuShape {
30+ id: artShape;
31+ objectName: "artShape";
32+ radius: "medium";
33+ visible: image.status == Image.Ready;
34+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36+ Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
37+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
38+ function updateWidthHeightBindings() {
39+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
40+ width = root.fixedArtShapeSize.width;
41+ height = root.fixedArtShapeSize.height;
42+ } else {
43+ width = Qt.binding(function() { return !visible ? 0 : image.width });
44+ height = Qt.binding(function() { return !visible ? 0 : image.height });
45+ }
46+ }
47+ image: Image {
48+ objectName: "artImage";
49+ source: cardData && cardData["art"] || "";
50+ cache: true;
51+ asynchronous: root.asynchronous;
52+ fillMode: Image.PreserveAspectCrop;
53+ width: root.width;
54+ height: width / artShape.aspect;
55+ }
56+ }
6157 }
62− }
63− }
64− }
58+ }
6559readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
6660Label {
67− id: titleLabel;
68− objectName: "titleLabel";
69− anchors { right: parent.right;left: parent.left;
61+ id: titleLabel;
62+ objectName: "titleLabel";
63+ anchors { right: parent.right;
64+rightMargin: units.gu(1);
65+left: parent.left;
7066top: artShapeHolder.bottom;
7167 topMargin: units.gu(1);
7268leftMargin: units.gu(1);
73−}
74− elide: Text.ElideRight;
75− fontSize: "small";
76− wrapMode: Text.Wrap;
77− maximumLineCount: 2;
78− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
79− color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
80− visible: showHeader ;
81− text: root.title;
82− font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
83− horizontalAlignment: root.headerAlignment;
84− }
85−Label {
86− id: subtitleLabel;
87− objectName: "subtitleLabel";
88− anchors { left: titleLabel.left;
89− leftMargin: titleLabel.leftMargin;
90− right: titleLabel.right;
91− top: titleLabel.bottom;
92− topMargin: units.dp(2);
93− }
69+ }
9470 elide: Text.ElideRight;
9571 fontSize: "small";
72+ wrapMode: Text.Wrap;
73+ maximumLineCount: 2;
9674 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
97− color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
98− visible: titleLabel.visible && titleLabel.text;
99− text: cardData && cardData["subtitle"] || "";
100− font.weight: Font.Light;
75+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
76+ visible: showHeader ;
77+ text: root.title;
78+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
10179 horizontalAlignment: root.headerAlignment;
10280 }
81+Label {
82+ id: subtitleLabel;
83+ objectName: "subtitleLabel";
84+ anchors { left: titleLabel.left;
85+ leftMargin: titleLabel.leftMargin;
86+ right: titleLabel.right;
87+ rightMargin: titleLabel.rightMargin;
88+ top: titleLabel.bottom;
89+ topMargin: units.dp(2);
90+ }
91+ elide: Text.ElideRight;
92+ fontSize: "small";
93+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
94+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
95+ visible: titleLabel.visible && titleLabel.text;
96+ text: cardData && cardData["subtitle"] || "";
97+ font.weight: Font.Light;
98+ horizontalAlignment: root.headerAlignment;
99+ }
100+UbuntuShape {
101+ id: touchdown;
102+ objectName: "touchdown";
103+ anchors { fill: artShapeHolder }
104+ visible: root.pressed;
105+ radius: "medium";
106+ borderSource: "radius_pressed.sci"
107+}
103108implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
104109}
tests/plugins/Dash/cardcreator/3.tst+1−1
@@ -1,3 +1,3 @@
11template: {"card-layout":"vertical","card-size":"small","category-layout":"grid","collapsed-rows":2}
2−components: {"art":{"aspect-ratio":0.75,"field":"art","fill-mode":"crop"},"subtitle":{"field":"price"},"title":{"field":"title"}}
2+components: {"art":{"aspect-ratio":0.75,"field":"art"},"subtitle":{"field":"price"},"title":{"field":"title"}}
33result: 3.res
tests/plugins/Dash/cardcreator/4.res+8
@@ -94,5 +94,13 @@ Label {
9494}
9595]
9696}
97+UbuntuShape {
98+ id: touchdown;
99+ objectName: "touchdown";
100+ anchors { fill: root }
101+ visible: root.pressed;
102+ radius: "medium";
103+ borderSource: "radius_pressed.sci"
104+}
97105implicitHeight: row.y + row.height + units.gu(1);
98106}
tests/plugins/Dash/cardcreator/4.tst+1−1
@@ -1,3 +1,3 @@
11template: {"card-layout":"horizontal","card-size":"large","category-layout":"grid","collapsed-rows":2}
2−components: {"art":{"aspect-ratio":1,"fill-mode":"crop"},"mascot":{"field":"mascot"},"subtitle":{"field":"domain"},"title":{"field":"title"}}
2+components: {"art":{"aspect-ratio":1},"mascot":{"field":"mascot"},"subtitle":{"field":"domain"},"title":{"field":"title"}}
33result: 4.res
tests/plugins/Dash/cardcreator/5.res+122−118
@@ -4,9 +4,9 @@ AbstractButton {
44 property var components;
55 property var cardData;
66 property var artShapeBorderSource: undefined;
7− property real fontScale: 1.0;
8− property var scopeStyle: null;
9− property int headerAlignment: Text.AlignLeft;
7+ property real fontScale: 1.0;
8+ property var scopeStyle: null;
9+ property int headerAlignment: Text.AlignLeft;
1010 property int fixedHeaderHeight: -1;
1111 property size fixedArtShapeSize: Qt.size(-1, -1);
1212 readonly property string title: cardData && cardData["title"] || "";
@@ -16,130 +16,134 @@ AbstractButton {
1616onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
1717readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
1818Item {
19− id: artShapeHolder;
20− height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
21− width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
22− anchors { horizontalCenter: parent.horizontalCenter; }
23− Loader {
24− id: artShapeLoader;
25− objectName: "artShapeLoader";
26− active: cardData && cardData["art"] || false;
27− asynchronous: root.asynchronous;
28− visible: status == Loader.Ready;
29− sourceComponent: UbuntuShape {
30− id: artShape;
31− objectName: "artShape";
32− radius: "medium";
33− visible: image.status == Image.Ready;
34− readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35− readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36− readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
37− Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
38− onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
39− Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
40− function updateWidthHeightBindings() {
41− if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
42− width = root.fixedArtShapeSize.width;
43− height = root.fixedArtShapeSize.height;
44− } else if (aspectSmallerThanImageAspect) {
45− width = Qt.binding(function() { return !visible ? 0 : image.width });
46− height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
47− } else {
48− width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
49− height = Qt.binding(function() { return !visible ? 0 : image.height });
50− }
51− }
52− image: Image {
53− objectName: "artImage";
54− source: cardData && cardData["art"] || "";
55− cache: true;
19+ id: artShapeHolder;
20+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
21+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
22+ anchors { horizontalCenter: parent.horizontalCenter; }
23+ Loader {
24+ id: artShapeLoader;
25+ objectName: "artShapeLoader";
26+ active: cardData && cardData["art"] || false;
5627 asynchronous: root.asynchronous;
57− fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
58− readonly property real aspect: implicitWidth / implicitHeight;
59− width: root.width;
60− height: width / artShape.aspect;
61− }
62− }
63− }
64− }
28+ visible: status == Loader.Ready;
29+ sourceComponent: UbuntuShape {
30+ id: artShape;
31+ objectName: "artShape";
32+ radius: "medium";
33+ visible: image.status == Image.Ready;
34+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36+ Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
37+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
38+ function updateWidthHeightBindings() {
39+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
40+ width = root.fixedArtShapeSize.width;
41+ height = root.fixedArtShapeSize.height;
42+ } else {
43+ width = Qt.binding(function() { return !visible ? 0 : image.width });
44+ height = Qt.binding(function() { return !visible ? 0 : image.height });
45+ }
46+ }
47+ image: Image {
48+ objectName: "artImage";
49+ source: cardData && cardData["art"] || "";
50+ cache: true;
51+ asynchronous: root.asynchronous;
52+ fillMode: Image.PreserveAspectCrop;
53+ width: root.width;
54+ height: width / artShape.aspect;
55+ }
56+ }
57+ }
58+ }
6559Loader {
66− id: overlayLoader;
67− anchors {
68− left: artShapeHolder.left;
69− right: artShapeHolder.right;
70− bottom: artShapeHolder.bottom;
71− }
72− active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false;
73− asynchronous: root.asynchronous;
74− visible: showHeader && status == Loader.Ready;
75− sourceComponent: ShaderEffect {
76− id: overlay;
77− height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
78− opacity: 0.6;
79− property var source: ShaderEffectSource {
80− id: shaderSource;
81− sourceItem: artShapeLoader.item;
82− onVisibleChanged: if (visible) scheduleUpdate();
83− live: false;
84− sourceRect: Qt.rect(0, artShapeLoader.height - overlay.height, artShapeLoader.width, overlay.height);
85− }
86− vertexShader: "
87− uniform highp mat4 qt_Matrix;
88− attribute highp vec4 qt_Vertex;
89− attribute highp vec2 qt_MultiTexCoord0;
90− varying highp vec2 coord;
91− void main() {
92− coord = qt_MultiTexCoord0;
93− gl_Position = qt_Matrix * qt_Vertex;
94− }";
95− fragmentShader: "
96− varying highp vec2 coord;
97− uniform sampler2D source;
98− uniform lowp float qt_Opacity;
99− void main() {
100− lowp vec4 tex = texture2D(source, coord);
101− gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
102− }";
103− }
104− }
60+ id: overlayLoader;
61+ anchors {
62+ left: artShapeHolder.left;
63+ right: artShapeHolder.right;
64+ bottom: artShapeHolder.bottom;
65+ }
66+ active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false;
67+ asynchronous: root.asynchronous;
68+ visible: showHeader && status == Loader.Ready;
69+ sourceComponent: ShaderEffect {
70+ id: overlay;
71+ height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
72+ opacity: 0.6;
73+ property var source: ShaderEffectSource {
74+ id: shaderSource;
75+ sourceItem: artShapeLoader.item;
76+ onVisibleChanged: if (visible) scheduleUpdate();
77+ live: false;
78+ sourceRect: Qt.rect(0, artShapeLoader.height - overlay.height, artShapeLoader.width, overlay.height);
79+ }
80+ vertexShader: "
81+ uniform highp mat4 qt_Matrix;
82+ attribute highp vec4 qt_Vertex;
83+ attribute highp vec2 qt_MultiTexCoord0;
84+ varying highp vec2 coord;
85+ void main() {
86+ coord = qt_MultiTexCoord0;
87+ gl_Position = qt_Matrix * qt_Vertex;
88+ }";
89+ fragmentShader: "
90+ varying highp vec2 coord;
91+ uniform sampler2D source;
92+ uniform lowp float qt_Opacity;
93+ void main() {
94+ lowp vec4 tex = texture2D(source, coord);
95+ gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
96+ }";
97+ }
98+ }
10599readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
106100Label {
107− id: titleLabel;
108− objectName: "titleLabel";
109− anchors { left: parent.left;
110− leftMargin: units.gu(1);
111− right: parent.right;
112− top: overlayLoader.top;
113− topMargin: units.gu(1);
114−}
115− elide: Text.ElideRight;
116− fontSize: "small";
117− wrapMode: Text.Wrap;
118− maximumLineCount: 2;
119− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
120− color: "white";
121− visible: showHeader && overlayLoader.active;
122− text: root.title;
123− font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
124− horizontalAlignment: root.headerAlignment;
125− }
126−Label {
127− id: subtitleLabel;
128− objectName: "subtitleLabel";
129− anchors { left: titleLabel.left;
130− leftMargin: titleLabel.leftMargin;
131− right: titleLabel.right;
132− top: titleLabel.bottom;
133− topMargin: units.dp(2);
134− }
101+ id: titleLabel;
102+ objectName: "titleLabel";
103+ anchors { left: parent.left;
104+ leftMargin: units.gu(1);
105+ right: parent.right;
106+ rightMargin: units.gu(1);
107+ top: overlayLoader.top;
108+ topMargin: units.gu(1);
109+ }
135110 elide: Text.ElideRight;
136111 fontSize: "small";
112+ wrapMode: Text.Wrap;
113+ maximumLineCount: 2;
137114 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
138115 color: "white";
139− visible: titleLabel.visible && titleLabel.text;
140− text: cardData && cardData["subtitle"] || "";
141− font.weight: Font.Light;
116+ visible: showHeader && overlayLoader.active;
117+ text: root.title;
118+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
142119 horizontalAlignment: root.headerAlignment;
143120 }
121+Label {
122+ id: subtitleLabel;
123+ objectName: "subtitleLabel";
124+ anchors { left: titleLabel.left;
125+ leftMargin: titleLabel.leftMargin;
126+ right: titleLabel.right;
127+ rightMargin: titleLabel.rightMargin;
128+ top: titleLabel.bottom;
129+ topMargin: units.dp(2);
130+ }
131+ elide: Text.ElideRight;
132+ fontSize: "small";
133+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
134+ color: "white";
135+ visible: titleLabel.visible && titleLabel.text;
136+ text: cardData && cardData["subtitle"] || "";
137+ font.weight: Font.Light;
138+ horizontalAlignment: root.headerAlignment;
139+ }
140+UbuntuShape {
141+ id: touchdown;
142+ objectName: "touchdown";
143+ anchors { fill: artShapeHolder }
144+ visible: root.pressed;
145+ radius: "medium";
146+ borderSource: "radius_pressed.sci"
147+}
144148implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
145149}
tests/plugins/Dash/cardcreator/5.tst+1−1
@@ -1,3 +1,3 @@
11template: {"card-layout":"vertical","card-size":"medium","category-layout":"carousel","collapsed-rows":2,"overlay":true}
2−components: {"art":{"aspect-ratio":1,"field":"art","fill-mode":"crop"},"subtitle":{"field":"artist"},"title":{"field":"title"}}
2+components: {"art":{"aspect-ratio":1,"field":"art"},"subtitle":{"field":"artist"},"title":{"field":"title"}}
33result: 5.res
tests/plugins/Dash/cardcreator/6.res+10−8
@@ -33,19 +33,14 @@ Item {
3333 visible: image.status == Image.Ready;
3434 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
3535 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36− readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
3736 Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
38− onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
3937 Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
4038 function updateWidthHeightBindings() {
4139 if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
4240 width = root.fixedArtShapeSize.width;
4341 height = root.fixedArtShapeSize.height;
44− } else if (aspectSmallerThanImageAspect) {
45− width = Qt.binding(function() { return !visible ? 0 : image.width });
46− height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
4742 } else {
48− width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
43+ width = Qt.binding(function() { return !visible ? 0 : image.width });
4944 height = Qt.binding(function() { return !visible ? 0 : image.height });
5045 }
5146 }
@@ -54,8 +49,7 @@ Item {
5449 source: cardData && cardData["art"] || "";
5550 cache: true;
5651 asynchronous: root.asynchronous;
57− fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
58− readonly property real aspect: implicitWidth / implicitHeight;
52+ fillMode: Image.PreserveAspectCrop;
5953 width: root.width;
6054 height: width / artShape.aspect;
6155 }
@@ -63,5 +57,13 @@ Item {
6357 }
6458 }
6559readonly property int headerHeight: 0;
60+UbuntuShape {
61+ id: touchdown;
62+ objectName: "touchdown";
63+ anchors { fill: artShapeHolder }
64+ visible: root.pressed;
65+ radius: "medium";
66+ borderSource: "radius_pressed.sci"
67+}
6668implicitHeight: artShapeHolder.height;
6769}
tests/plugins/Dash/cardcreator/6.tst+1−1
@@ -1,3 +1,3 @@
11template: {"card-layout":"vertical","card-size":"small","category-layout":"grid","collapsed-rows":2}
2−components: {"art":{"aspect-ratio":1.6,"field":"art","fill-mode":"fit"}}
2+components: {"art":{"aspect-ratio":1.6,"field":"art"}}
33result: 6.res
tests/plugins/Dash/cardcreator/7.resnew file+136
@@ -0,0 +1,136 @@
1+AbstractButton {
2+ id: root;
3+ property var template;
4+ property var components;
5+ property var cardData;
6+ property var artShapeBorderSource: undefined;
7+ property real fontScale: 1.0;
8+ property var scopeStyle: null;
9+ property int headerAlignment: Text.AlignLeft;
10+ property int fixedHeaderHeight: -1;
11+ property size fixedArtShapeSize: Qt.size(-1, -1);
12+ readonly property string title: cardData && cardData["title"] || "";
13+ property bool asynchronous: true;
14+ property bool showHeader: true;
15+ implicitWidth: childrenRect.width;
16+Loader {
17+ id: backgroundLoader;
18+ objectName: "backgroundLoader";
19+ anchors.fill: parent;
20+ asynchronous: root.asynchronous;
21+ visible: status == Loader.Ready;
22+ sourceComponent: UbuntuShape {
23+ objectName: "background";
24+ radius: "medium";
25+ color: getColor(0) || "white";
26+ gradientColor: getColor(1) || color;
27+ anchors.fill: parent;
28+ image: backgroundImage.source ? backgroundImage : null;
29+ property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
30+ property Image backgroundImage: Image {
31+ objectName: "backgroundImage";
32+ source: {
33+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
34+ else if (template && typeof template["card-background"] === "string") return template["card-background"];
35+ else return "";
36+ }
37+ }
38+ function getColor(index) {
39+ if (cardData && typeof cardData["background"] === "object"
40+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
41+ return cardData["background"]["elements"][index];
42+ } else if (template && typeof template["card-background"] === "object"
43+ && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
44+ return template["card-background"]["elements"][index];
45+ } else return undefined;
46+ }
47+ }
48+ }
49+readonly property size artShapeSize: Qt.size(-1, -1);
50+readonly property int headerHeight: row.height;
51+Row {
52+ id: row;
53+ objectName: "outerRow";
54+ property real margins: units.gu(1);
55+ spacing: margins;
56+ height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
57+ anchors { top: parent.top;
58+ topMargin: units.gu(1);
59+left: parent.left;
60+ }
61+ anchors.right: parent.right;
62+ anchors.margins: margins;
63+ data: [ Image {
64+ id: mascotImage;
65+ objectName: "mascotImage";
66+ anchors { verticalCenter: parent.verticalCenter; }
67+ readonly property int maxSize: Math.max(width, height) * 4;
68+ source: cardData && cardData["mascot"];
69+ width: units.gu(6);
70+ height: units.gu(5.625);
71+ sourceSize { width: maxSize; height: maxSize }
72+ fillMode: Image.PreserveAspectCrop;
73+ horizontalAlignment: Image.AlignHCenter;
74+ verticalAlignment: Image.AlignVCenter;
75+ visible: showHeader;
76+ }
77+
78+ ,
79+ Column {
80+ anchors.verticalCenter: parent.verticalCenter;
81+ spacing: units.dp(2);
82+ width: parent.width - x;
83+ data: [
84+ Label {
85+ id: titleLabel;
86+ objectName: "titleLabel";
87+ anchors { left: parent.left; right: parent.right }
88+ elide: Text.ElideRight;
89+ fontSize: "small";
90+ wrapMode: Text.Wrap;
91+ maximumLineCount: 2;
92+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
93+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
94+ visible: showHeader ;
95+ text: root.title;
96+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
97+ horizontalAlignment: root.headerAlignment;
98+ }
99+,
100+Label {
101+ id: subtitleLabel;
102+ objectName: "subtitleLabel";
103+ anchors { left: parent.left; right: parent.right }
104+ elide: Text.ElideRight;
105+ fontSize: "small";
106+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
107+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
108+ visible: titleLabel.visible && titleLabel.text;
109+ text: cardData && cardData["subtitle"] || "";
110+ font.weight: Font.Light;
111+ horizontalAlignment: root.headerAlignment;
112+ }
113+,
114+CardAttributes {
115+ id: attributesRow;
116+ objectName: "attributesRow";
117+ anchors { left: parent.left; right: parent.right }
118+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
119+ model: cardData["attributes"];
120+ }
121+
122+ ]
123+ }
124+
125+ ]
126+ }
127+UbuntuShape {
128+ id: touchdown;
129+ objectName: "touchdown";
130+ anchors { fill: backgroundLoader }
131+ visible: root.pressed;
132+ radius: "medium";
133+ borderSource: "radius_pressed.sci"
134+}
135+implicitHeight: row.y + row.height + units.gu(1);
136+}
tests/plugins/Dash/cardcreator/7.tstnew file+3
@@ -0,0 +1,3 @@
1+template: {"card-background":{"elements":["#E9E9E9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
2+components: {"art":{"aspect-ratio":1},"background":{"field":"background"},"mascot":{"field":"icon"},"subtitle":{"field":"author"},"title":{"field":"title"},"attributes":{"field":"attributes","max-count":2}}
3+result: 7.res
tests/plugins/Dash/cardcreatortest.cpp+19−2
@@ -19,6 +19,8 @@
1919#include <QQuickItem>
2020#include <QQuickView>
2121#include <QtTestGui>
22+#include <QDebug>
23+#include <QTemporaryFile>
2224
2325class CardCreatorTest : public QObject
2426{
@@ -73,8 +75,23 @@ private Q_SLOTS:
7375 QFile testResultFile(testDirPath + resultFileName);
7476 QVERIFY(testResultFile.open(QIODevice::ReadOnly));
7577 QTextStream ts2(&testResultFile);
76− const QString expectedResult = ts2.readAll();
77− QCOMPARE(cardStringResult.toString().simplified(), expectedResult.simplified());
78+
79+ // Record failed results to /tmp
80+ const QString executedResult = cardStringResult.toString();
81+ QTemporaryFile tmpFile(QDir::tempPath() + QDir::separator() + "testCardCreatorFailedResultXXXXXX");
82+ tmpFile.open();
83+ tmpFile.setAutoRemove(false);
84+ tmpFile.write(executedResult.toUtf8().constData());
85+
86+ // Line by line comparison
87+ const QStringList expectedLines = ts2.readAll().trimmed().replace(QRegExp("\n\\s*\n"),"\n").split("\n");
88+ const QStringList cardStringResultLines = cardStringResult.toString().trimmed().replace(QRegExp("\n\\s*\n"),"\n").split("\n");
89+ for (int i = 0; i < expectedLines.size(); ++i) {
90+ QCOMPARE(cardStringResultLines[i].simplified(), expectedLines[i].simplified());
91+ }
92+
93+ // Remove the result if it passed
94+ tmpFile.setAutoRemove(true);
7895
7996 QVariant createCardComponentResult;
8097 QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON));
tests/plugins/Dash/listviewwithpageheadersectiontest.cpp−1
@@ -40,7 +40,6 @@ private:
4040 QTRY_COMPARE(lvwph->m_visibleItems[visibleIndex]->height(), height);
4141 QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->m_item)->culled, culled);
4242 QCOMPARE(section(lvwph->m_visibleItems[visibleIndex]->sectionItem()), sectionHeader);
43− QTRY_COMPARE(hasSectionHeaderProperty(lvwph->m_visibleItems[visibleIndex]->m_item), !sectionHeader.isNull());
4443 if (!sectionHeader.isNull()) {
4544 QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->sectionItem())->culled, sectionHeaderCulled);
4645 QCOMPARE(sectionDelegateIndex(lvwph->m_visibleItems[visibleIndex]->sectionItem()), lvwph->m_firstVisibleIndex + visibleIndex);
tests/plugins/Dash/tst_CardAttributes.qmlnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright 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+import QtQuick 2.0
18+import QtTest 1.0
19+import Dash 0.1
20+
21+Item {
22+ width: units.gu(40)
23+ height: units.gu(4.5)
24+
25+ property var testData: [
26+ [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"}],
27+ [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3"}],
28+ [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3"},{"value":"text4"}],
29+ [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3","style":"highlighted"},{"value":"text4","icon":"image://theme/close","style":"highlighted"},{"value":"text5"}]
30+ ]
31+
32+ CardAttributes {
33+ id: cardAttributes
34+ model: testData[3]
35+ clip: true
36+ }
37+
38+ TestCase {
39+ name: "CardAttributesTest"
40+ when: windowShown
41+
42+ function init() {
43+ }
44+
45+ function test_columns_data() {
46+ return testData;
47+ }
48+
49+ function test_columns(data) {
50+ cardAttributes.model = data;
51+ compare(cardAttributes.columns, 2 + data.length % 2);
52+ }
53+ }
54+}
tests/plugins/Dash/tst_ScopeStyle.qml+41−9
@@ -36,8 +36,8 @@ Rectangle {
3636 property var styles: [
3737 {},
3838 { "foreground-color": "red", "background-color": "black", "page-header": { "logo": "/foo/bar" } },
39− { "foreground-color": "green", "background-color": "white" },
40− { "foreground-color": "blue", "background-color": "darkgrey" },
39+ { "foreground-color": "green", "background-color": "white", "page-header": { "foreground-color": "black" } },
40+ { "foreground-color": "blue", "background-color": "darkgrey", "page-header": { "background": "gradient:///white/blue" } },
4141 ]
4242
4343 function cleanup() {
@@ -54,6 +54,9 @@ Rectangle {
5454 { tag: "lightgrey", luminance: 0.8275 },
5555 { tag: "grey", luminance: 0.5020 },
5656 { tag: "darkgrey", luminance: 0.6627 },
57+ { tag: "red", luminance: 0.2126 },
58+ { tag: "green", luminance: 0.3590 },
59+ { tag: "blue", luminance: 0.0722 },
5760 ];
5861 }
5962
@@ -64,10 +67,10 @@ Rectangle {
6467
6568 function test_foreground_data() {
6669 return [
67− { tag: "default", index: 0, foreground: "grey" },
68− { tag: "red on black", index: 1, foreground: "red" },
69− { tag: "green on white", index: 2, foreground: "green" },
70− { tag: "blue on darkgrey", index: 3, foreground: "blue" },
70+ { tag: "default", index: 0, foreground: "grey", luminance: 0.5020 },
71+ { tag: "red on black", index: 1, foreground: "red", luminance: 0.2126 },
72+ { tag: "green on white", index: 2, foreground: "green", luminance: 0.3590 },
73+ { tag: "blue on darkgrey", index: 3, foreground: "blue", luminance: 0.0722 },
7174 ];
7275 }
7376
@@ -75,14 +78,15 @@ Rectangle {
7578 tool.style = testCase.styles[data.index];
7679 verify(Qt.colorEqual(tool.foreground, data.foreground),
7780 "Foreground color not equal: %1 != %2".arg(tool.foreground).arg(data.foreground));
81+ compare(tool.foregroundLuminance.toFixed(4), data.luminance.toFixed(4));
7882 }
7983
8084 function test_background_data() {
8185 return [
8286 { tag: "default", index: 0, background: "transparent" },
83− { tag: "red on black", index: 1, background: "black" },
84− { tag: "green on white", index: 2, background: "white" },
85− { tag: "blue on darkgrey", index: 3, background: "darkgrey" },
87+ { tag: "red on black", index: 1, background: "black", luminance: 0 },
88+ { tag: "green on white", index: 2, background: "white", luminance: 1 },
89+ { tag: "blue on darkgrey", index: 3, background: "darkgrey", luminance: 0.6627 },
8690 ];
8791 }
8892
@@ -90,6 +94,9 @@ Rectangle {
9094 tool.style = testCase.styles[data.index];
9195 verify(Qt.colorEqual(tool.background, data.background),
9296 "Background color not equal: %1 != %2".arg(tool.background).arg(data.background));
97+ if (data.hasOwnProperty("luminance")) {
98+ compare(tool.backgroundLuminance.toFixed(4), data.luminance.toFixed(4));
99+ }
93100 }
94101
95102 function test_threshold_data() {
@@ -147,5 +154,30 @@ Rectangle {
147154 tool.style = testCase.styles[data.index];
148155 compare(tool.headerLogo, data.headerLogo, "Header logo was incorrect.");
149156 }
157+
158+ function test_headerForeground_data() {
159+ return [
160+ { tag: "default", index: 0, headerForeground: "grey" },
161+ { tag: "black", index: 2, headerForeground: "black" },
162+ ];
163+ }
164+
165+ function test_headerForeground(data) {
166+ tool.style = testCase.styles[data.index];
167+ verify(Qt.colorEqual(tool.headerForeground, data.headerForeground),
168+ "Header foreground not equal: %1 != %2".arg(tool.headerForeground).arg(data.headerForeground));
169+ }
170+
171+ function test_headerBackground_data() {
172+ return [
173+ { tag: "default", index: 0, headerBackground: "" },
174+ { tag: "black", index: 3, headerBackground: "gradient:///white/blue" },
175+ ];
176+ }
177+
178+ function test_headerBackground(data) {
179+ tool.style = testCase.styles[data.index];
180+ compare(tool.headerBackground, data.headerBackground, "Header background was incorrect.");
181+ }
150182 }
151183}
tests/plugins/Unity/Indicators/unitymenumodelstacktest.cpp+3
@@ -24,6 +24,9 @@
2424#include <QDebug>
2525#include <unitymenumodel.h>
2626
27+#include <functional>
28+#include <chrono>
29+
2730class UnityMenuModelStackTest : public QObject
2831{
2932 Q_OBJECT
tests/qmltests/CMakeLists.txt+2−3
@@ -21,16 +21,15 @@ set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
2121
2222add_qml_test(. Shell ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
2323add_qml_test(. ShellWithPin ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single-pin")
24+add_qml_test(Components Background)
2425add_qml_test(Components Carousel)
2526add_qml_test(Components DraggingArea)
2627add_qml_test(Components EdgeDemoOverlay)
27−add_qml_test(Components FilterGrid)
2828add_qml_test(Components LazyImage)
2929add_qml_test(Components Rating)
3030add_qml_test(Components ResponsiveFlowView)
3131add_qml_test(Components ResponsiveGridView)
3232add_qml_test(Components ResponsiveVerticalJournal IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
33−add_qml_test(Components SeeMore)
3433add_qml_test(Components Showable)
3534add_qml_test(Components PageHeader)
3635add_qml_test(Components ZoomableImage)
@@ -40,10 +39,10 @@ add_qml_test(Dash Card)
4039add_qml_benchmark(Dash CardBenchmark 1000)
4140add_qml_test(Dash CardTool)
4241add_qml_test(Dash GenericScopeView)
43−add_qml_test(Dash/Apps RunningApplicationsGrid)
4442add_qml_test(Dash/Previews Preview)
4543add_qml_test(Dash/Previews PreviewActions)
4644add_qml_test(Dash/Previews PreviewAudioPlayback)
45+add_qml_test(Dash/Previews PreviewExpandable)
4746add_qml_test(Dash/Previews PreviewHeader)
4847add_qml_test(Dash/Previews PreviewImageGallery)
4948add_qml_test(Dash/Previews PreviewPayments)
tests/qmltests/Components/tst_Background.qmlnew file+90

This diff is too big to show here.

tests/qmltests/Components/tst_FilterGrid.qmldeleted−190

This diff is too big to show here.

tests/qmltests/Components/tst_PageHeader.qml+57−29

This diff is too big to show here.

tests/qmltests/Components/tst_SeeMore.qmldeleted−52

This diff is too big to show here.

tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qmldeleted−196

This diff is too big to show here.

tests/qmltests/Dash/CardHelpers.js+8−5

This diff is too big to show here.

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

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewTextSummary.qml+4−18

This diff is too big to show here.

tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml+1

This diff is too big to show here.

tests/qmltests/Dash/tst_Card.qml+19−5

This diff is too big to show here.

tests/qmltests/Dash/tst_Dash.qml+47−15

This diff is too big to show here.

tests/qmltests/Dash/tst_DashContent.qml+109−101

This diff is too big to show here.

tests/qmltests/Dash/tst_GenericScopeView.qml+139−50

This diff is too big to show here.

tests/qmltests/Greeter/tst_Lockscreen.qml+11−5

This diff is too big to show here.

tests/qmltests/Launcher/tst_Launcher.qml+11−2

This diff is too big to show here.

tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml+47

This diff is too big to show here.

tests/qmltests/Panel/tst_ActiveCallHint.qml+1

This diff is too big to show here.

tests/qmltests/Stages/tst_PhoneStage.qml+12−58

This diff is too big to show here.

tests/qmltests/tst_Shell.qml+156−272

This diff is too big to show here.

tests/qmltests/tst_ShellWithPin.qml+4−37

This diff is too big to show here.