on xenial help sign in
Merged with trunk
commitcde21f20516d90c529fe96f976059cd4df4ec8a7 authorMirco Müller <mirco.mueller@canonical.com> dateWed 6 Aug 2014, 15:22 (12 years ago) parent9f62a844b6a6fb
251 files changed+8383−4804
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+1−1 data/CMakeLists.txt+5−2 data/unity8-dash.conf+22 data/unity8-dash.desktop.in+9 data/unity8.conf+1−7 debian/changelog+149 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+76−7 plugins/Dash/ScopeStyle.qml+6 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+68−57 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+20−12 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+22−14 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+40−27 po/it.po+20−12 po/ja.po+19−11 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+25−17 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+5−6 qml/Components/FilterGrid.qml−124 qml/Components/InputMethod.qml+79 qml/Components/ListItems/Header.qml+17−26 qml/Components/Lockscreen.qml+17−5 qml/Components/PageHeader.qml+33−9 qml/Components/PassphraseLockscreen.qml+3 qml/Components/ResponsiveGridView.qml+2−1 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+27−2 qml/Dash/CardVerticalJournal.qml+3−21 qml/Dash/Dash.qml+8 qml/Stages/SidestageHandle.qml → qml/Dash/DashApplication.qml+12−5 qml/Dash/DashApps.qml−40 qml/Dash/DashContent.qml+5−3 qml/Dash/DashRenderer.qml+3−10 qml/Dash/GenericScopeView.qml+134−75 qml/Dash/PreviewListView.qml+1−3 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/Panel/Indicators.qml+3 qml/Panel/Indicators/DefaultIndicatorPage.qml+1−1 qml/Shell.qml+205−470 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−266 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 src/CMakeLists.txt+1−3 src/Dash/CMakeLists.txt+12 src/Dash/main.cpp+74 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+33−18 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−9 tests/mocks/LightDM/single-pin/UsersModelPrivate.cpp+1−1 tests/mocks/QMenuModel/unitymenumodel.cpp+5 tests/mocks/QMenuModel/unitymenumodel.h+4 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 tests/mocks/Unity/Application/VirtualKeyboard.h+35 tests/mocks/Unity/Application/plugin.cpp+16−9 tests/mocks/Unity/CMakeLists.txt+2−1 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/fake_categories.cpp+13−1 tests/mocks/Unity/fake_categories.h+2 tests/mocks/Unity/fake_scope.cpp+8−11 tests/mocks/Unity/fake_scope.h+2−2 tests/mocks/Unity/fake_scopes.cpp+6 tests/mocks/Unity/fake_scopes.h+1 tests/mocks/libusermetrics/UserMetrics.cpp+3 tests/plugins/Dash/CMakeLists.txt+1 tests/plugins/Dash/cardcreator/1.res+63−61 tests/plugins/Dash/cardcreator/2.res+94−91 tests/plugins/Dash/cardcreator/3.res+77−74 tests/plugins/Dash/cardcreator/5.res+119−117 tests/plugins/Dash/cardcreator/7.res+128 tests/plugins/Dash/cardcreator/7.tst+3 tests/plugins/Dash/cardcreatortest.cpp+9−1 tests/plugins/Dash/listviewwithpageheadersectiontest.cpp−1 tests/plugins/Dash/tst_CardAttributes.qml+54 tests/plugins/Dash/tst_ScopeStyle.qml+27−2 tests/plugins/Unity/Indicators/unitymenumodelstacktest.cpp+3 tests/qmltests/CMakeLists.txt+4−5 tests/qmltests/Components/tst_Background.qml+90 tests/qmltests/Components/tst_FilterGrid.qml−190 tests/qmltests/Components/tst_PageHeader.qml+36−6 tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml−196 tests/qmltests/Dash/CardHelpers.js+5−3 tests/qmltests/Dash/tst_Card.qml+4−2 tests/qmltests/Dash/tst_Dash.qml+20−1 tests/qmltests/Dash/tst_DashContent.qml+15−6 tests/qmltests/Dash/tst_GenericScopeView.qml+137−49 tests/qmltests/Greeter/tst_Lockscreen.qml+11−5 tests/qmltests/Launcher/tst_Launcher.qml+11−2 tests/qmltests/Panel/tst_ActiveCallHint.qml+1 tests/qmltests/Stages/tst_PhoneStage.qml+12−58 tests/qmltests/tst_Shell.qml+175−272 tests/qmltests/tst_ShellWithPin.qml+170
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+1−1
@@ -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}/${CLASS_NAME}Test.xml,xunitxml
139139 -o -,txt)
140140
141141 add_qmltest_target(test${CLASS_NAME} "${testCommand}" 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+149
@@ -1,3 +1,152 @@
1+unity8 (8.00+14.10.20140805-0ubuntu1) utopic; urgency=low
2+
3+ [ Michael Zanetti ]
4+ * Split the dash from the shell into a separate app (LP: #1232687)
5+
6+ [ Leo Arias ]
7+ * Update the autopilot tests to work with the new dash app.
8+
9+ [ Daniel d'Andrada ]
10+ * Split the dash from the shell into a separate app (LP: #1232687)
11+
12+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 05 Aug 2014 12:06:31 +0000
13+
14+unity8 (8.00+14.10.20140731.1-0ubuntu1) utopic; urgency=low
15+
16+ [ Gerry Boland ]
17+ * Fix the run.sh script - pretend to be running with qtmir and emit
18+ SIGSTOP at the right time
19+
20+ [ Ying-Chun Liu ]
21+ * Implement Attribute UI. (LP: #1282460)
22+
23+ [ Albert Astals ]
24+ * Hide search history popup as soon as you start typing As discussed
25+ with Mike and Saviq
26+ * Compile with for scopes-v3 unity-api
27+ * PageHeader: Unfocus search field when search entry is selected
28+ * Show search field if the search query changes
29+ * Test: Add a condition for art.height being > 0 means stuff has
30+ already been layouted a bit without it it can happen that we get 0
31+ for everything at startup and tests still pass
32+ * Remove leftover in test of an old headerless implementation
33+
34+ [ Michael Zanetti ]
35+ * Drop Recent apps category from Dash (LP: #1281092)
36+ * update launcher count emblems to match new spec (LP: #1338984)
37+
38+ [ Bill Filler ]
39+ * disable predictive text for dash search field (LP: #1340409)
40+
41+ [ CI bot ]
42+ * Resync trunk
43+
44+ [ Antti Kaijanmäki ]
45+ * DefaultIndicatorPage: use Loader status to determine the visible
46+ property. (LP: #1350555)
47+
48+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 31 Jul 2014 16:51:01 +0000
49+
50+unity8 (8.00+14.10.20140729.1-0ubuntu1) utopic; urgency=low
51+
52+ [ Michael Terry ]
53+ * Check user's pin/password using PAM, instead of a plaintext keyfile.
54+ New build dependency: libpam0g-dev for phone unlock with PAM (LP:
55+ #1234983)
56+
57+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 29 Jul 2014 23:36:30 +0000
58+
59+unity8 (8.00+14.10.20140729-0ubuntu1) utopic; urgency=medium
60+
61+ [ Gerry Boland ]
62+ [ Daniel d'Andrada ]
63+ * Re-architecture unity8 to use the QtMirCompositor library so that
64+ the Qt scenegraph renderer is used as the Mir compositor, and
65+ application surfaces are added to the QML scene as items.
66+
67+ [ Michael Zanetti ]
68+ * Port phone right-edge spread code to use QtCompositor
69+ * Add right-edge spread animation for tablet
70+
71+ [ Ubuntu daily release ]
72+ * New rebuild forced
73+
74+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 29 Jul 2014 15:07:32 +0000
75+
76+unity8 (7.90+14.10.20140725-0ubuntu1) utopic; urgency=low
77+
78+ [ CI bot ]
79+ * Resync trunk
80+
81+ [ Michał Sawicz ]
82+ * Fix the ap test for applications.
83+
84+ [ Albert Astals ]
85+ * Use deleteLater instead of a direct delete We are seeing a crash in
86+ QQuickWindowPrivate::polishItems because LVWPH is deleting items to
87+ polish from it's updatePolish which means the set in
88+ QQuickWindowPrivate::polishItems may end up with some yet-to-
89+ process-but-now-deleted items. Switching to deleteLater fixes this
90+
91+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 25 Jul 2014 10:47:34 +0000
92+
93+unity8 (7.90+14.10.20140724.1-0ubuntu1) utopic; urgency=low
94+
95+ [ Michael Zanetti ]
96+ * properly parent launcher items (LP: #1347902)
97+
98+ [ Michał Sawicz ]
99+ * Move the PyDev project files to the root, supporting .py scripts
100+ outside of tests/autopilot. Add Autopilot Run and List launch
101+ configurations to easily support debugging in Eclipse. Use
102+ add_unity8_mock macro in the Telephony plugin.
103+ * Drop FilterGrid and refactor height animations in GenericScopeView.
104+ Also implement forced category expansion. (LP: #1326470)
105+ * Move expansion button from section header to category footer. (LP:
106+ #1261300)
107+ * Fix expect-sigstop enviroment variable name. (LP: #1346819)
108+ * Make headerless categories easier Instead of having no header
109+ category (which is a bit confusing since the LVWPH code was designed
110+ so that when a category has no header it is because it shares the
111+ category with the previous one) what we have for headerless
112+ categories is a header of height 0, this way everything works as it
113+ should and results in cleaner code in the LVWPH and in
114+ GenericScopeView
115+ * Add support for header links.
116+ * Add dash PageHeader styling.
117+
118+ [ Albert Astals ]
119+ * Make headerless categories easier Instead of having no header
120+ category (which is a bit confusing since the LVWPH code was designed
121+ so that when a category has no header it is because it shares the
122+ category with the previous one) what we have for headerless
123+ categories is a header of height 0, this way everything works as it
124+ should and results in cleaner code in the LVWPH and in
125+ GenericScopeView
126+
127+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 24 Jul 2014 20:41:29 +0000
128+
129+unity8 (7.90+14.10.20140723.4-0ubuntu1) utopic; urgency=low
130+
131+ [ thomas-voss ]
132+ * Explicitly select gcc version.
133+
134+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 23 Jul 2014 15:32:41 +0000
135+
136+unity8 (7.90+14.10.20140721.1-0ubuntu1) utopic; urgency=low
137+
138+ [ Michael Terry ]
139+ * Allow running the dialer-app in emergency mode when the screen is
140+ locked.
141+
142+ [ Michał Sawicz ]
143+ * Add missing nameOwner property to mock UnityMenuModel.
144+
145+ [ Albert Astals ]
146+ * Fix name, There's nothing called pageHeader in this file
147+
148+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 21 Jul 2014 14:57:08 +0000
149+
1150unity8 (7.90+14.10.20140717.3-0ubuntu1) utopic; urgency=low
2151
3152 [ Nick Dedekind ]
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.87),
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-2,
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+76−7
@@ -193,6 +193,21 @@ var kHeaderColumnCode = 'Column { \n\
193193 ] \n\
194194 }\n';
195195
196+// multiple column version of kHeaderColumnCode.
197+function kHeaderColumnCodeGenerator() {
198+ var headerColumnCodeTemplate = 'Column { \n\
199+ anchors.verticalCenter: parent.verticalCenter; \n\
200+ spacing: units.dp(2); \n\
201+ width: parent.width - x;\n\
202+ data: [ \n\
203+ %1 \n\
204+ ]\n\
205+ }\n';
206+ var args = Array.prototype.slice.call(arguments);
207+ var code = headerColumnCodeTemplate.arg(args.join(',\n'));
208+ return code;
209+}
210+
196211// %1 is used as anchors of mascotShapeLoader
197212var kMascotShapeLoaderCode = 'Loader { \n\
198213 id: mascotShapeLoader; \n\
@@ -224,7 +239,7 @@ var kMascotImageCode = 'Image { \n\
224239 }\n';
225240
226241// %1 is used as anchors of titleLabel
227−// %1 is used as color of titleLabel
242+// %2 is used as color of titleLabel
228243// %3 is used as extra condition for visible of titleLabel
229244var kTitleLabelCode = 'Label { \n\
230245 id: titleLabel; \n\
@@ -258,6 +273,15 @@ var kSubtitleLabelCode = 'Label { \n\
258273 horizontalAlignment: root.headerAlignment; \n\
259274 }\n';
260275
276+// %1 is used as anchors of attributesRow
277+var kAttributesRowCode = 'CardAttributes { \n\
278+ id: attributesRow; \n\
279+ objectName: "attributesRow"; \n\
280+ anchors { %1 } \n\
281+ color: %2; \n\
282+ model: cardData && cardData["attributes"] || undefined; \n\
283+ }\n';
284+
261285// %1 is used as top anchor of summary
262286// %2 is used as topMargin anchor of summary
263287// %3 is used as color of summary
@@ -308,6 +332,7 @@ function cardString(template, components) {
308332 var headerAsOverlay = hasArt && template && template["overlay"] === true && (hasTitle || hasMascot);
309333 var hasSubtitle = hasTitle && components["subtitle"] || false;
310334 var hasHeaderRow = hasMascot && hasTitle;
335+ var hasAttributes = hasTitle && components["attributes"] || false;
311336
312337 if (hasBackground) {
313338 code += kBackgroundLoaderCode;
@@ -377,6 +402,14 @@ function cardString(template, components) {
377402 code += 'readonly property int headerHeight: row.height;\n'
378403 } else if (hasMascot) {
379404 code += 'readonly property int headerHeight: mascotImage.height;\n'
405+ } else if (hasAttributes) {
406+ if (hasTitle && hasSubtitle) {
407+ code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + attributesRow.height + attributesRow.anchors.topMargin;\n'
408+ } else if (hasTitle) {
409+ code += 'readonly property int headerHeight: titleLabel.height + attributesRow.height + attributesRow.anchors.topMargin;\n'
410+ } else {
411+ code += 'readonly property int headerHeight: attributesRow.height;\n'
412+ }
380413 } else if (hasSubtitle) {
381414 code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;\n'
382415 } else if (hasTitle) {
@@ -425,10 +458,12 @@ function cardString(template, components) {
425458
426459 var titleAnchors;
427460 var subtitleAnchors;
428− if (hasMascot && hasSubtitle) {
461+ var attributesAnchors;
462+ if (hasMascot && (hasSubtitle || hasAttributes)) {
429463 // Using row + column
430464 titleAnchors = 'left: parent.left; right: parent.right';
431465 subtitleAnchors = titleAnchors;
466+ attributesAnchors = subtitleAnchors;
432467 } else if (hasMascot) {
433468 // Using row + label
434469 titleAnchors = 'verticalCenter: parent.verticalCenter;\n'
@@ -438,11 +473,13 @@ function cardString(template, components) {
438473 titleAnchors = 'left: parent.left; \n\
439474 leftMargin: units.gu(1); \n\
440475 right: parent.right; \n\
476+ rightMargin: units.gu(1); \n\
441477 top: overlayLoader.top; \n\
442478 topMargin: units.gu(1);\n';
443479 } else {
444480 // Using anchors to the mascot/parent
445− titleAnchors = "right: parent.right;";
481+ titleAnchors = "right: parent.right;\n";
482+ titleAnchors += "rightMargin: units.gu(1);\n";
446483 titleAnchors += headerLeftAnchor;
447484 titleAnchors += headerVerticalAnchors;
448485 if (!headerLeftAnchorHasMargin) {
@@ -452,8 +489,19 @@ function cardString(template, components) {
452489 subtitleAnchors = 'left: titleLabel.left; \n\
453490 leftMargin: titleLabel.leftMargin; \n\
454491 right: titleLabel.right; \n\
492+ rightMargin: titleLabel.rightMargin; \n\
455493 top: titleLabel.bottom; \n\
456494 topMargin: units.dp(2);\n';
495+ if (hasSubtitle) {
496+ attributesAnchors = 'left: subtitleLabel.left; \n\
497+ leftMargin: subtitleLabel.leftMargin; \n\
498+ right: subtitleLabel.right; \n\
499+ rightMargin: subtitleLabel.rightMargin; \n\
500+ top: subtitleLabel.bottom; \n\
501+ topMargin: units.dp(2);\n';
502+ } else {
503+ attributesAnchors = subtitleAnchors;
504+ }
457505 }
458506
459507 var titleLabelVisibleExtra = (headerAsOverlay ? '&& overlayLoader.active': '');
@@ -463,11 +511,27 @@ function cardString(template, components) {
463511 subtitleCode += kSubtitleLabelCode.arg(subtitleAnchors).arg(color);
464512 }
465513
466− if (hasMascot && hasSubtitle) {
514+ if (hasMascot && (hasSubtitle || hasAttributes)) {
467515 // If using row + column wrap the code in the column
468516 titleSubtitleCode = kHeaderColumnCode.arg(titleCode).arg(subtitleCode);
517+ if (hasSubtitle && hasAttributes) {
518+ var attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(color);
519+ titleSubtitleCode = kHeaderColumnCodeGenerator(titleCode, subtitleCode, attributesCode);
520+ } else if (hasSubtitle) {
521+ titleSubtitleCode = kHeaderColumnCode.arg(titleCode).arg(subtitleCode);
522+ } else if (hasAttributes) {
523+ var attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(color);
524+ titleSubtitleCode = kHeaderColumnCode.arg(titleCode).arg(attributesCode);
525+ }
469526 } else {
470− titleSubtitleCode = titleCode + subtitleCode;
527+ titleSubtitleCode = titleCode;
528+ if (hasSubtitle) {
529+ titleSubtitleCode = titleSubtitleCode + subtitleCode;
530+ }
531+ if (hasAttributes) {
532+ var attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(color);
533+ titleSubtitleCode = titleSubtitleCode + attributesCode;
534+ }
471535 }
472536 }
473537
@@ -487,6 +551,7 @@ function cardString(template, components) {
487551 else if (headerAsOverlay && hasArt) summaryTopAnchor = "artShapeHolder.bottom";
488552 else if (hasHeaderRow) summaryTopAnchor = "row.bottom";
489553 else if (hasMascot) summaryTopAnchor = "mascotImage.bottom";
554+ else if (hasAttributes) summaryTopAnchor = "attributesRow.bottom";
490555 else if (hasSubtitle) summaryTopAnchor = "subtitleLabel.bottom";
491556 else if (hasTitle) summaryTopAnchor = "titleLabel.bottom";
492557 else if (hasArt) summaryTopAnchor = "artShapeHolder.bottom";
@@ -499,7 +564,7 @@ function cardString(template, components) {
499564 color = 'root.scopeStyle ? root.scopeStyle.foreground : "grey"';
500565 }
501566
502− var summaryTopMargin = (hasMascot || hasSubtitle ? 'anchors.margins' : '0');
567+ var summaryTopMargin = (hasMascot || hasSubtitle || hasAttributes ? 'anchors.margins' : '0');
503568
504569 code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(color);
505570 }
@@ -510,6 +575,8 @@ function cardString(template, components) {
510575 code += 'implicitHeight: row.y + row.height + units.gu(1);\n';
511576 } else if (hasMascot) {
512577 code += 'implicitHeight: mascotImage.y + mascotImage.height;\n';
578+ } else if (hasAttributes) {
579+ code += 'implicitHeight: attributesRow.y + attributesRow.height + units.gu(1);\n';
513580 } else if (hasSubtitle) {
514581 code += 'implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
515582 } else if (hasTitle) {
@@ -526,8 +593,10 @@ function cardString(template, components) {
526593function createCardComponent(parent, template, components) {
527594 var imports = 'import QtQuick 2.2; \n\
528595 import Ubuntu.Components 0.1; \n\
529− import Ubuntu.Thumbnailer 0.1;\n';
596+ import Ubuntu.Thumbnailer 0.1;\n\
597+ import Dash 0.1;\n';
530598 var card = cardString(template, components);
531599 var code = imports + 'Component {\n' + card + '}\n';
600+
532601 return Qt.createQmlObject(code, parent, "createCardComponent");
533602}
plugins/Dash/ScopeStyle.qml+6
@@ -70,6 +70,12 @@ QtObject {
7070 /// Source of the logo image for the header
7171 readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
7272
73+ /// Background style for the header
74+ readonly property url headerBackground: "background" in d.headerStyle ? d.headerStyle["background"] : ""
75+
76+ /// Foreground color for the header
77+ readonly property color headerForeground: "foreground-color" in d.headerStyle ? d.headerStyle["foreground-color"] : foreground
78+
7379 //! @cond
7480 property var d: QtObject {
7581 readonly property real foregroundLuminance: luminance(foreground)
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+68−57
@@ -1,199 +1,210 @@
11# Danish translation for unity8
22# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
33# This file is distributed under the same license as the unity8 package.
4−# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
4+#
5+# Ask Hjorth Larsen <asklarsen@gmail.com>, 2014.
56#
67msgid ""
78msgstr ""
89"Project-Id-Version: unity8\n"
910"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 20:16+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13−"Language-Team: Danish <da@li.org>\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"
14+"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
1415"MIME-Version: 1.0\n"
1516"Content-Type: text/plain; charset=UTF-8\n"
1617"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
18+"X-Launchpad-Export-Date: 2014-07-31 07:15+0000\n"
19+"X-Generator: Launchpad (build 17131)\n"
1920
2021#: plugins/Unity/Launcher/launcheritem.cpp:43
2122#: plugins/Unity/Launcher/launcheritem.cpp:73
2223msgid "Pin shortcut"
23−msgstr ""
24+msgstr "Fastgør genvej"
2425
2526#: plugins/Unity/Launcher/launcheritem.cpp:73
2627msgid "Unpin shortcut"
27−msgstr ""
28+msgstr "Gør genvej flytbar"
2829
2930#: qml/Components/EdgeDemoOverlay.qml:151
3031msgid "Skip intro"
31−msgstr ""
32+msgstr "Spring intro over"
3233
3334#: qml/Components/EdgeDemo.qml:113
3435msgid "Right edge"
35−msgstr ""
36+msgstr "Højre kant"
3637
3738#: qml/Components/EdgeDemo.qml:114
3839msgid "Try swiping from the right edge to unlock the phone"
39−msgstr ""
40+msgstr "Prøv at stryge fra højre kant for at låse telefonen op"
4041
4142#: qml/Components/EdgeDemo.qml:145
4243msgid "Top edge"
43−msgstr ""
44+msgstr "Øvre kant"
4445
4546#: qml/Components/EdgeDemo.qml:146
4647msgid "Try swiping from the top edge to access the indicators"
47−msgstr ""
48+msgstr "Prøv at stryge fra den øvre kant for at tilgå indikatorerne"
4849
4950#: qml/Components/EdgeDemo.qml:171
5051msgid "Close"
51−msgstr ""
52+msgstr "Luk"
5253
5354#: qml/Components/EdgeDemo.qml:172
5455msgid "Swipe up again to close the settings screen"
55−msgstr ""
56+msgstr "Stryg op igen for at låse indstillingsskærmen"
5657
5758#: qml/Components/EdgeDemo.qml:199
5859msgid "Left edge"
59−msgstr ""
60+msgstr "Venstre kant"
6061
6162#: qml/Components/EdgeDemo.qml:200
6263msgid "Swipe from the left to reveal the launcher for quick access to apps"
63−msgstr ""
64+msgstr "Stryg fra venstre for at vise opstarteren med hurtig adgang til apps"
6465
6566#: qml/Components/EdgeDemo.qml:227
6667msgid "Well done"
67−msgstr ""
68+msgstr "Godt gjort"
6869
6970#: qml/Components/EdgeDemo.qml:228
7071msgid ""
7172"You have now mastered the edge gestures and can start using the "
7273"phone<br><br>Tap on the screen to start"
7374msgstr ""
75+"Du mestrer nu kantbevægelserne og kan begynde at bruge telefonen<br><br>Tryk "
76+"på skærmen for at starte"
7477
7578#: qml/Components/Lockscreen.qml:214
7679msgid "Emergency Call"
77−msgstr ""
80+msgstr "Nødopkald"
7881
7982#: qml/Components/Lockscreen.qml:231
8083msgid "OK"
81−msgstr ""
82−
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
84+msgstr "O.k."
8685
8786#: qml/Components/PassphraseLockscreen.qml:60
8887#, qt-format
8988msgid "Hello %1"
90−msgstr ""
89+msgstr "Hej %1"
9190
9291#: qml/Components/PassphraseLockscreen.qml:60
9392msgid "Hello"
94−msgstr ""
93+msgstr "Hej"
9594
9695#: qml/Components/PinLockscreen.qml:198
9796msgid "CANCEL"
98−msgstr ""
97+msgstr "ANNULLÉR"
9998
10099#: qml/Components/PinLockscreen.qml:216
101100msgid "DONE"
102−msgstr ""
101+msgstr "FÆRDIG"
103102
104103#: qml/Components/SeeMore.qml:35
105104msgid "See more"
106−msgstr ""
105+msgstr "Vis mere"
107106
108−#: qml/Components/SeeMore.qml:58
107+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109108msgid "See less"
110−msgstr ""
109+msgstr "Vis mindre"
111110
112111#: qml/Dash/DashApps.qml:37
113112msgid "Recent"
114−msgstr ""
113+msgstr "Seneste"
114+
115+#: qml/Dash/GenericScopeView.qml:330
116+msgid "See all"
117+msgstr "Se alle"
115118
116119#: qml/Dash/Previews/PreviewActionCombo.qml:34
117120msgid "More..."
118−msgstr ""
121+msgstr "Mere..."
119122
120123#: qml/Dash/Previews/PreviewActionCombo.qml:34
121124msgid "Less..."
122−msgstr ""
125+msgstr "Mindre..."
123126
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
127+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125128msgid "Rate this"
126−msgstr ""
129+msgstr "Bedøm dette"
127130
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
131+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129132msgid "Add a review"
130−msgstr ""
133+msgstr "Tilføj en forhåndsvisning"
131134
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
135+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133136msgid "Send"
134−msgstr ""
137+msgstr "Send"
135138
136139#: qml/Greeter/Greeter.qml:157
137140msgid "Swipe to unlock"
138−msgstr ""
141+msgstr "Stryg for at låse op"
139142
140143#: qml/Hud/HudParametrizedActionsPage.qml:132
141144msgid "Confirm"
142−msgstr ""
145+msgstr "Bekræft"
143146
144147#: qml/Hud/Hud.qml:61 qml/Hud/Hud.qml:99 qml/Hud/Hud.qml:372
145148msgid "Type or say a command"
146−msgstr ""
149+msgstr "Skriv eller indtal en kommando"
147150
148151#: qml/Hud/Hud.qml:84
149152msgid "Loading. Please Wait..."
150−msgstr ""
153+msgstr "Indlæser. Vent venligst..."
151154
152155#: qml/Hud/Hud.qml:89
153156msgid "Speak Now..."
154−msgstr ""
157+msgstr "Tal nu..."
155158
156159#: qml/Hud/Hud.qml:94
157160msgid "Speaking..."
158−msgstr ""
161+msgstr "Taler..."
159162
160163#: qml/Notifications/NotificationMenuItemFactory.qml:91
161164msgid "Show password"
162−msgstr ""
165+msgstr "Vis adgangskode"
163166
164167#: qml/Notifications/NotificationMenuItemFactory.qml:103
165168msgid "Please enter SIM PIN"
166−msgstr ""
169+msgstr "Indtast venligst PIN for SIM"
170+
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"
167178
168179#: qml/Panel/Indicators/MenuItemFactory.qml:583
169180msgid "In queue…"
170−msgstr ""
181+msgstr "I kø…"
171182
172183#: qml/Panel/Indicators/MenuItemFactory.qml:587
173184msgid "Downloading"
174−msgstr ""
185+msgstr "Henter"
175186
176187#: qml/Panel/Indicators/MenuItemFactory.qml:589
177188msgid "Paused, tap to resume"
178−msgstr ""
189+msgstr "På pause; tryk for at fortsætte"
179190
180191#: qml/Panel/Indicators/MenuItemFactory.qml:591
181192msgid "Canceled"
182−msgstr ""
193+msgstr "Annulleret"
183194
184195#: qml/Panel/Indicators/MenuItemFactory.qml:593
185196msgid "Finished"
186−msgstr ""
197+msgstr "Færdig"
187198
188199#: qml/Panel/Indicators/MenuItemFactory.qml:595
189200msgid "Failed, tap to retry"
190−msgstr ""
201+msgstr "Mislykkedes; tryk for at prøve igen"
191202
192203#: qml/Panel/SearchIndicator.qml:27
193204msgid "Search"
194−msgstr ""
205+msgstr "Søg"
195206
196207#: qml/Shell.qml:359
197208#, qt-format
198209msgid "Please enter %1"
199−msgstr ""
210+msgstr "Indtast venligst %1"
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-07-26 06:22+0000\n"
12+"Last-Translator: Paco Molinero <paco@byasl.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-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
@@ -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 todo"
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+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-16 18:11+0000\n"
10+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11+"PO-Revision-Date: 2014-07-25 12:38+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-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 "Larrialdi-deia"
8484msgid "OK"
8585msgstr "Ados"
8686
87−#: qml/Components/PageHeader.qml:366
88−msgid "Recent searches"
89−msgstr "Azken bilaketak"
90−
9187#: qml/Components/PassphraseLockscreen.qml:60
9288#, qt-format
9389msgid "Hello %1"
@@ -109,7 +105,7 @@ msgstr "EGINDA"
109105msgid "See more"
110106msgstr "Ikusi gehiago"
111107
112−#: qml/Components/SeeMore.qml:58
108+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
113109msgid "See less"
114110msgstr "Ikusi gutxiago"
115111
@@ -117,6 +113,10 @@ msgstr "Ikusi gutxiago"
117113msgid "Recent"
118114msgstr "Azkenak"
119115
116+#: qml/Dash/GenericScopeView.qml:330
117+msgid "See all"
118+msgstr "Ikusi guztiak"
119+
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
122122msgstr "Gehiago..."
@@ -125,15 +125,15 @@ msgstr "Gehiago..."
125125msgid "Less..."
126126msgstr "Gutxiago..."
127127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:82
128+#: qml/Dash/Previews/PreviewRatingInput.qml:81
129129msgid "Rate this"
130130msgstr "Puntuatu hau"
131131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:128
132+#: qml/Dash/Previews/PreviewRatingInput.qml:126
133133msgid "Add a review"
134134msgstr "Gehitu kritika"
135135
136−#: qml/Dash/Previews/PreviewRatingInput.qml:168
136+#: qml/Dash/Previews/PreviewRatingInput.qml:166
137137msgid "Send"
138138msgstr "Bidali"
139139
@@ -169,6 +169,14 @@ msgstr "Erakutsi pasahitza"
169169msgid "Please enter SIM PIN"
170170msgstr "Sartu SIMaren PINa"
171171
172+#: qml/Panel/ActiveCallHint.qml:77
173+msgid "Tap to return to call..."
174+msgstr "Sakatu deia itzultzeko..."
175+
176+#: qml/Panel/ActiveCallHint.qml:90
177+msgid "Conference"
178+msgstr "Konferentzia"
179+
172180#: qml/Panel/Indicators/MenuItemFactory.qml:583
173181msgid "In queue…"
174182msgstr "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+22−14
@@ -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 17:04+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-20 06:18+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
@@ -61,12 +61,12 @@ msgstr "Bordo esquerdo"
6161#: qml/Components/EdgeDemo.qml:200
6262msgid "Swipe from the left to reveal the launcher for quick access to apps"
6363msgstr ""
64−"Esvare o dedo desde a esquerda para mostrar o iniciador rápido aos "
64+"Esvare o dedo desde a esquerda para mostrar o iniciador rápido dos "
6565"aplicativos"
6666
6767#: qml/Components/EdgeDemo.qml:227
6868msgid "Well done"
69−msgstr "Ben feito"
69+msgstr "Ben feito!"
7070
7171#: qml/Components/EdgeDemo.qml:228
7272msgid ""
@@ -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-04 09:10+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-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 "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"
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+40−27
@@ -1,30 +1,33 @@
1+# translation of po_unity8-is.po to icelandic
12# Icelandic translation for unity8
23# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
34# This file is distributed under the same license as the unity8 package.
4−# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
55#
6+# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
7+# Sveinn í Felli <sv1@fellsnet.is>, 2014.
68msgid ""
79msgstr ""
8−"Project-Id-Version: unity8\n"
10+"Project-Id-Version: po_unity8-is\n"
911"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 11:20+0000\n"
12+"POT-Creation-Date: 2014-07-11 14:59+0200\n"
13+"PO-Revision-Date: 2014-07-31 16:10+0000\n"
1214"Last-Translator: Sveinn í Felli <sv1@fellsnet.is>\n"
13−"Language-Team: Icelandic <is@li.org>\n"
15+"Language-Team: Icelandic <translation-team-is@lists.sourceforge.net>\n"
1416"MIME-Version: 1.0\n"
1517"Content-Type: text/plain; charset=UTF-8\n"
1618"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-19 06:19+0000\n"
18−"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"
21+"Language: is\n"
1922
2023#: plugins/Unity/Launcher/launcheritem.cpp:43
2124#: plugins/Unity/Launcher/launcheritem.cpp:73
2225msgid "Pin shortcut"
23−msgstr ""
26+msgstr "Pinna flýtilykil"
2427
2528#: plugins/Unity/Launcher/launcheritem.cpp:73
2629msgid "Unpin shortcut"
27−msgstr ""
30+msgstr "Losa flýtilykil"
2831
2932#: qml/Components/EdgeDemoOverlay.qml:151
3033msgid "Skip intro"
@@ -37,7 +40,7 @@ msgstr "Hægri brún"
3740#: qml/Components/EdgeDemo.qml:114
3841msgid "Try swiping from the right edge to unlock the phone"
3942msgstr ""
40−"Prufaðu að renna puttanum frá hægri brúninni til að aflæsa símanum þínum."
43+"Prófaðu að strjúka fingrinum frá hægri brúninni til að aflæsa símanum þínum."
4144
4245#: qml/Components/EdgeDemo.qml:145
4346msgid "Top edge"
@@ -45,7 +48,7 @@ msgstr "Efri brún"
4548
4649#: qml/Components/EdgeDemo.qml:146
4750msgid "Try swiping from the top edge to access the indicators"
48−msgstr "Reyndu að renna frá toppi til að fá aðgang að tilkynningum"
51+msgstr "Reyndu að strjúka frá toppi til að fá aðgang að tilkynningum"
4952
5053#: qml/Components/EdgeDemo.qml:171
5154msgid "Close"
@@ -53,7 +56,7 @@ msgstr "Loka"
5356
5457#: qml/Components/EdgeDemo.qml:172
5558msgid "Swipe up again to close the settings screen"
56−msgstr "Renndu upp til að loka stillingum"
59+msgstr "Strjúktu upp til að loka stillingum"
5760
5861#: qml/Components/EdgeDemo.qml:199
5962msgid "Left edge"
@@ -61,7 +64,7 @@ msgstr "Vinstri brún"
6164
6265#: qml/Components/EdgeDemo.qml:200
6366msgid "Swipe from the left to reveal the launcher for quick access to apps"
64−msgstr "Renndu frá vinstri til að afhjúpa flýtiræsi forrita"
67+msgstr "Strjúktu frá vinstri til að afhjúpa flýtiræsi forrita"
6568
6669#: qml/Components/EdgeDemo.qml:227
6770msgid "Well done"
@@ -72,6 +75,8 @@ msgid ""
7275"You have now mastered the edge gestures and can start using the "
7376"phone<br><br>Tap on the screen to start"
7477msgstr ""
78+"Þú ert núna með æfingu í að nota skjáhreyfingar og getur því farið að nota "
79+"símann<br><br>Sláðu létt á skjáinn til að byrja"
7580
7681#: qml/Components/Lockscreen.qml:214
7782msgid "Emergency Call"
@@ -81,10 +86,6 @@ msgstr "Neyðarsímtal"
8186msgid "OK"
8287msgstr "Í lagi"
8388
84−#: qml/Components/PageHeader.qml:366
85−msgid "Recent searches"
86−msgstr "Nýlegar leitir"
87−
8889#: qml/Components/PassphraseLockscreen.qml:60
8990#, qt-format
9091msgid "Hello %1"
@@ -106,7 +107,7 @@ msgstr "BÚIÐ"
106107msgid "See more"
107108msgstr "Sjá meira"
108109
109−#: qml/Components/SeeMore.qml:58
110+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
110111msgid "See less"
111112msgstr "Sjá minna"
112113
@@ -114,6 +115,10 @@ msgstr "Sjá minna"
114115msgid "Recent"
115116msgstr "Nýlegt"
116117
118+#: qml/Dash/GenericScopeView.qml:330
119+msgid "See all"
120+msgstr "Sjá allt"
121+
117122#: qml/Dash/Previews/PreviewActionCombo.qml:34
118123msgid "More..."
119124msgstr "Meira..."
@@ -122,21 +127,21 @@ msgstr "Meira..."
122127msgid "Less..."
123128msgstr "Minna..."
124129
125−#: qml/Dash/Previews/PreviewRatingInput.qml:82
130+#: qml/Dash/Previews/PreviewRatingInput.qml:81
126131msgid "Rate this"
127132msgstr "Gefa þessu einkunn"
128133
129−#: qml/Dash/Previews/PreviewRatingInput.qml:128
134+#: qml/Dash/Previews/PreviewRatingInput.qml:126
130135msgid "Add a review"
131136msgstr "Gefa umsögn"
132137
133−#: qml/Dash/Previews/PreviewRatingInput.qml:168
138+#: qml/Dash/Previews/PreviewRatingInput.qml:166
134139msgid "Send"
135140msgstr "Senda"
136141
137142#: qml/Greeter/Greeter.qml:157
138143msgid "Swipe to unlock"
139−msgstr "Strjóka til að aflæsa"
144+msgstr "Strjúka til að aflæsa"
140145
141146#: qml/Hud/HudParametrizedActionsPage.qml:132
142147msgid "Confirm"
@@ -144,15 +149,15 @@ msgstr "Staðfesta"
144149
145150#: qml/Hud/Hud.qml:61 qml/Hud/Hud.qml:99 qml/Hud/Hud.qml:372
146151msgid "Type or say a command"
147−msgstr "Skrifaðu eða segðu eitthvað"
152+msgstr "Skrifaðu eða segðu skipun"
148153
149154#: qml/Hud/Hud.qml:84
150155msgid "Loading. Please Wait..."
151−msgstr "Hleð. Vinsamlegast Bíðið..."
156+msgstr "Hleð. Bíddu aðeins..."
152157
153158#: qml/Hud/Hud.qml:89
154159msgid "Speak Now..."
155−msgstr "Talaðu Núna..."
160+msgstr "Tala núna..."
156161
157162#: qml/Hud/Hud.qml:94
158163msgid "Speaking..."
@@ -166,6 +171,14 @@ msgstr "Birta lykilorð"
166171msgid "Please enter SIM PIN"
167172msgstr "Settu inn PIN fyrir SIM"
168173
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+
169182#: qml/Panel/Indicators/MenuItemFactory.qml:583
170183msgid "In queue…"
171184msgstr "Í biðröð..."
@@ -176,7 +189,7 @@ msgstr "Sæki"
176189
177190#: qml/Panel/Indicators/MenuItemFactory.qml:589
178191msgid "Paused, tap to resume"
179−msgstr ""
192+msgstr "Í bið, sláðu létt til að halda áfram"
180193
181194#: qml/Panel/Indicators/MenuItemFactory.qml:591
182195msgid "Canceled"
@@ -188,7 +201,7 @@ msgstr "Lokið"
188201
189202#: qml/Panel/Indicators/MenuItemFactory.qml:595
190203msgid "Failed, tap to retry"
191−msgstr ""
204+msgstr "Mistókst, sláðu létt til að reyna aftur"
192205
193206#: qml/Panel/SearchIndicator.qml:27
194207msgid "Search"
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+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-18 07:01+0000\n"
1212"Last-Translator: Shushi Kurose <md81bird@hitaki.net>\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-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/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+25−17
@@ -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-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-04 18:33+0000\n"
12+"Last-Translator: Rafael Neri <Unknown>\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-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
@@ -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,6 +169,14 @@ 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…"
174182msgstr ""
@@ -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-06 06:55+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 "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-21 07:05+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+5−6
@@ -22,7 +22,6 @@ Item {
2222 id: demo
2323
2424 property Item greeter
25− property Item dash
2625 property Item launcher
2726 property Item indicators
2827 property Item underlay
@@ -144,7 +143,7 @@ Item {
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.underlay,
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) {
195+ if (demo.underlay) {
197196 d.leftEdgeDemo = d.overlay.createObject(demo.underlay, {
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.underlay,
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) {
223+ if (demo.underlay) {
225224 d.finalEdgeDemo = d.overlay.createObject(demo.underlay, {
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.underlay,
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/Lockscreen.qml+17−5
@@ -186,6 +186,17 @@ Showable {
186186 }
187187
188188 Column {
189+ id: emergencyCallColumn
190+
191+ // FIXME: We *should* show emergency dialer if there is a SIM present,
192+ // regardless of whether the side stage is enabled. But right now,
193+ // the assumption is that narrow screens are phones which have SIMs
194+ // and wider screens are tablets which don't. When we do allow this
195+ // on devices with a side stage and a SIM, work should be done to
196+ // ensure that the main stage is disabled while the dialer is present
197+ // in the side stage.
198+ visible: !shell.sideStageEnabled
199+
189200 anchors {
190201 left: parent.left
191202 bottom: parent.bottom
@@ -203,11 +214,6 @@ Showable {
203214 name: "phone-app-call-symbolic"
204215 color: "#f3f3e7"
205216 opacity: 0.6
206−
207− MouseArea {
208− anchors.fill: parent
209− onClicked: root.emergencyCall()
210− }
211217 }
212218
213219 Label {
@@ -219,6 +225,12 @@ Showable {
219225 }
220226 }
221227
228+ MouseArea {
229+ anchors.fill: emergencyCallColumn
230+ onClicked: root.emergencyCall()
231+ enabled: emergencyCallColumn.visible
232+ }
233+
222234 Component {
223235 id: infoPopupComponent
224236 Dialog {
qml/Components/PageHeader.qml+33−9
@@ -44,6 +44,12 @@ Item {
4444 signal backClicked()
4545
4646 onScopeStyleChanged: refreshLogo()
47+ onSearchQueryChanged: {
48+ // Make sure we are at the search page if the search query changes behind our feet
49+ if (searchQuery) {
50+ headerContainer.showSearch = true;
51+ }
52+ }
4753
4854 function triggerSearch() {
4955 if (searchEntryEnabled) {
@@ -52,6 +58,12 @@ Item {
5258 }
5359 }
5460
61+ function closePopup() {
62+ if (headerContainer.popover != null) {
63+ PopupUtils.close(headerContainer.popover);
64+ }
65+ }
66+
5567 function resetSearch(keepFocus) {
5668 if (searchHistory) {
5769 searchHistory.addQuery(searchTextField.text);
@@ -60,9 +72,7 @@ Item {
6072 unfocus();
6173 }
6274 searchTextField.text = "";
63− if (headerContainer.popover != null) {
64− PopupUtils.close(headerContainer.popover);
65− }
75+ closePopup();
6676 }
6777
6878 function unfocus() {
@@ -103,9 +113,7 @@ Item {
103113 anchors { fill: parent; margins: units.gu(1); bottomMargin: units.gu(3) + bottomContainer.height }
104114 visible: headerContainer.showSearch
105115 onPressed: {
106− if (headerContainer.popover) {
107− PopupUtils.close(headerContainer.popover);
108− }
116+ closePopup();
109117 if (!searchTextField.text) {
110118 headerContainer.showSearch = false;
111119 }
@@ -117,7 +125,7 @@ Item {
117125 Flickable {
118126 id: headerContainer
119127 objectName: "headerContainer"
120− clip: true
128+ clip: openSearchAnimation.running
121129 anchors { left: parent.left; top: parent.top; right: parent.right }
122130 height: units.gu(6.5)
123131 contentHeight: headersColumn.height
@@ -127,6 +135,11 @@ Item {
127135 property bool showSearch: false
128136 property var popover: null
129137
138+ Background {
139+ objectName: "headerBackground"
140+ style: scopeStyle.headerBackground
141+ }
142+
130143 Behavior on contentY {
131144 UbuntuNumberAnimation {
132145 id: openSearchAnimation
@@ -150,6 +163,7 @@ Item {
150163 anchors { left: parent.left; right: parent.right }
151164 height: headerContainer.height
152165 contentHeight: height
166+ opacity: headerContainer.clip || headerContainer.showSearch ? 1 : 0 // setting visible false cause column to relayout
153167 separatorSource: ""
154168 // Required to keep PageHeadStyle noise down as it expects the Page's properties around.
155169 property var styledItem: searchHeader
@@ -166,6 +180,7 @@ Item {
166180 property var contents: TextField {
167181 id: searchTextField
168182 objectName: "searchTextField"
183+ inputMethodHints: Qt.ImhNoPredictiveText
169184 hasClearButton: false
170185 anchors {
171186 fill: parent
@@ -215,6 +230,12 @@ Item {
215230 root.openSearchHistory();
216231 }
217232 }
233+
234+ onTextChanged: {
235+ if (text != "") {
236+ closePopup();
237+ }
238+ }
218239 }
219240 }
220241
@@ -224,8 +245,9 @@ Item {
224245 anchors { left: parent.left; right: parent.right }
225246 height: headerContainer.height
226247 contentHeight: height
248+ opacity: headerContainer.clip || !headerContainer.showSearch ? 1 : 0 // setting visible false cause column to relayout
227249 separatorSource: ""
228− textColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
250+ textColor: root.scopeStyle ? root.scopeStyle.headerForeground : "grey"
229251 property var styledItem: header
230252 property string title: root.title
231253 property var config: PageHeadConfiguration {
@@ -291,6 +313,7 @@ Item {
291313
292314 Repeater {
293315 id: recentSearches
316+ objectName: "recentSearches"
294317 model: searchHistory
295318
296319 delegate: Standard {
@@ -299,7 +322,8 @@ Item {
299322 onClicked: {
300323 searchHistory.addQuery(text);
301324 searchTextField.text = text;
302− PopupUtils.close(popover);
325+ closePopup();
326+ unfocus();
303327 }
304328 }
305329 }
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/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+27−2
@@ -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+8
@@ -18,6 +18,7 @@ import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Unity 0.2
2020import Utils 0.1
21+import Unity.DashCommunicator 0.1
2122import "../Components"
2223
2324Showable {
@@ -29,6 +30,13 @@ 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) {
3341 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)
3442
qml/Stages/SidestageHandle.qml → qml/Dash/DashApplication.qmlrenamed+12−5
@@ -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,16 @@
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+import QtQuick 2.2
18+import Ubuntu.Components 1.0
1919
20−BorderImage {
21− source: "graphics/sidestage_handle.sci"
20+MainView {
21+ width: units.gu(40)
22+ height: units.gu(71)
23+
24+ useDeprecatedToolbar: false
25+
26+ Dash {
27+ anchors.fill: parent
28+ }
2229}
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+5−3
@@ -121,10 +121,12 @@ 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
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+134−75
@@ -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
@@ -47,7 +46,7 @@ FocusScope {
4746 }
4847
4948 function activateApp(appId) {
50− shell.activateApplication(appId);
49+ Qt.openUrlExternally(appId);
5150 }
5251
5352 function positionAtBeginning() {
@@ -119,6 +118,7 @@ FocusScope {
119118
120119 model: scopeView.categories
121120 forceNoClip: previewListView.open
121+ pixelAligned: true
122122
123123 property string expandedCategoryId: ""
124124
@@ -128,11 +128,22 @@ FocusScope {
128128 highlightWhenPressed: false
129129 showDivider: false
130130
131− readonly property bool expandable: rendererLoader.item ? rendererLoader.item.expandable : false
132− readonly property bool filtered: rendererLoader.item ? rendererLoader.item.filtered : true
131+ readonly property bool expandable: {
132+ if (categoryView.model.count === 1) return false;
133+ if (cardTool.template && cardTool.template["collapsed-rows"] === 0) return false;
134+ if (item && item.expandedHeight > item.collapsedHeight) return true;
135+ return false;
136+ }
137+ property bool expanded: false
133138 readonly property string category: categoryId
139+ readonly property string headerLink: model.headerLink
134140 readonly property var item: rendererLoader.item
135141
142+ function expand(expand, animate) {
143+ heightBehaviour.enabled = animate;
144+ expanded = expand;
145+ }
146+
136147 CardTool {
137148 id: cardTool
138149 objectName: "cardTool"
@@ -142,22 +153,48 @@ FocusScope {
142153 viewWidth: parent.width
143154 }
144155
156+ onExpandableChanged: {
157+ // This can happen with the VJ that doesn't know how height it will be on creation
158+ // so doesn't set expandable until a bit too late for onLoaded
159+ if (expandable) {
160+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
161+ baseItem.expand(shouldExpand, false /*animate*/);
162+ }
163+ }
164+
165+ onHeightChanged: rendererLoader.updateDelegateCreationRange();
166+ onYChanged: rendererLoader.updateDelegateCreationRange();
167+
145168 Loader {
146169 id: rendererLoader
147170 anchors {
148171 top: parent.top
149172 left: parent.left
150173 right: parent.right
151− topMargin: hasSectionHeader ? 0 : units.gu(2)
174+ topMargin: name != "" ? 0 : units.gu(2)
175+ }
176+
177+ Behavior on height {
178+ id: heightBehaviour
179+ enabled: false
180+ animation: UbuntuNumberAnimation {
181+ onRunningChanged: {
182+ if (!running) {
183+ heightBehaviour.enabled = false
184+ }
185+ }
186+ }
152187 }
153188
189+ readonly property bool expanded: baseItem.expanded || !baseItem.expandable
190+ height: expanded ? item.expandedHeight : item.collapsedHeight
191+
154192 source: {
155193 switch (cardTool.categoryLayout) {
156194 case "carousel": return "CardCarousel.qml";
157195 case "vertical-journal": return "CardVerticalJournal.qml";
158− case "running-apps": return "Apps/RunningApplicationsGrid.qml";
159196 case "grid":
160− default: return "CardFilterGrid.qml";
197+ default: return "CardGrid.qml";
161198 }
162199 }
163200
@@ -166,19 +203,12 @@ FocusScope {
166203 item.enableHeightBehavior = scopeView.enableHeightBehaviorOnNextCreation;
167204 scopeView.enableHeightBehaviorOnNextCreation = false;
168205 }
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− }
206+ item.model = Qt.binding(function() { return results })
177207 item.objectName = Qt.binding(function() { return categoryId })
178208 item.scopeStyle = scopeView.scopeStyle;
179− if (item.expandable) {
180− var shouldFilter = categoryId != categoryView.expandedCategoryId;
181− item.setFilter(shouldFilter, false /*animate*/);
209+ if (baseItem.expandable) {
210+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
211+ baseItem.expand(shouldExpand, false /*animate*/);
182212 }
183213 updateDelegateCreationRange();
184214 item.cardTool = cardTool;
@@ -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
@@ -352,6 +403,10 @@ FocusScope {
352403 }
353404 }
354405
406+ LimitProxyModel {
407+ id: previewLimitModel
408+ }
409+
355410 PreviewListView {
356411 id: previewListView
357412 objectName: "previewListView"
@@ -361,6 +416,10 @@ FocusScope {
361416 width: parent.width
362417 height: parent.height
363418 anchors.left: categoryView.right
419+
420+ onOpenChanged: {
421+ pageHeader.unfocus();
422+ }
364423 }
365424
366425}
qml/Dash/PreviewListView.qml+1−3
@@ -73,9 +73,7 @@ Item {
7373 property bool open: false
7474
7575 onOpenChanged: {
76− if (open) {
77− pageHeader.unfocus();
78− } else {
76+ if (!open) {
7977 // Cancel any pending preview requests or actions
8078 if (previewListView.currentItem && previewListView.currentItem.previewData !== undefined) {
8179 previewListView.currentItem.previewData.cancelAction();
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
73+ enabled: (greeter.narrowMode || !greeter.locked) && greeter.enabled
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/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/Shell.qml+205−470
@@ -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,106 +83,51 @@ 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
86+ DashCommunicator {
87+ id: dash
88+ objectName: "dashCommunicator"
89+ }
12190
122− Rectangle {
123− anchors.fill: parent
124− color: "black"
125− opacity: dash.disappearingAnimationProgress
126− }
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; }
12795
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
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;
134102 }
103+ }
135104
136− Dash {
137− id: dash
138− objectName: "dash"
139−
140− available: !greeter.shown && !lockscreen.shown
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 }}
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;
162111 }
163112 }
164113 }
165114
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
115+ Item {
116+ id: underlay
117+ objectName: "underlay"
118+ anchors.fill: parent
172119
173− property real progress: stages.width
120+ // Whether the underlay is fully covered by opaque UI elements.
121+ property bool fullyCovered: (panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth)
122+ || stages.fullyShown || greeterWrapper.fullyShown
123+ visible: !fullyCovered
174124
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− }
182− }
183− }
184−
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;
191− }
125+ Image {
126+ anchors.fill: underlay
127+ source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png"
128+ fillMode: Image.PreserveAspectCrop
129+ horizontalAlignment: Image.AlignRight
130+ verticalAlignment: Image.AlignTop
192131 }
193132 }
194133
@@ -197,262 +136,94 @@ FocusScope {
197136 objectName: "stages"
198137 width: parent.width
199138 height: parent.height
200−
201− x: {
202− if (shown) {
203− if (overlayMode || locked) {
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− }
139+ visible: !ApplicationManager.empty
243140
244141 Connections {
245142 target: ApplicationManager
246−
247143 onFocusRequested: {
248− stages.show(true);
144+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== appId) {
145+ lockscreen.show();
146+ }
147+ greeter.hide();
249148 }
250149
251150 onFocusedApplicationIdChanged: {
252− if (ApplicationManager.focusedApplicationId.length > 0) {
253− stages.show(false);
254− } else {
255− if (!stages.overlayMode) {
256− stages.hide();
257− }
151+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== ApplicationManager.focusedApplicationId) {
152+ lockscreen.show();
258153 }
154+ panel.indicators.hide();
259155 }
260156
261157 onApplicationAdded: {
262− stages.show(false);
263− }
264−
265− onApplicationRemoved: {
266− if (ApplicationManager.focusedApplicationId.length == 0) {
267− stages.hide();
158+ if (greeter.shown && appId != "unity8-dash") {
159+ greeter.hide();
268160 }
269161 }
270162 }
271163
272− property bool dialogShown: false
273−
274− Component {
275− id: logoutDialog
276− Dialog {
277− id: dialogueLogout
278− title: "Logout"
279− text: "Are you sure that you want to logout?"
280− Button {
281− text: "Cancel"
282− onClicked: {
283− PopupUtils.close(dialogueLogout);
284− stages.dialogShown = false;
285− }
286− }
287− Button {
288− text: "Yes"
289− onClicked: {
290− DBusUnitySessionService.Logout();
291− PopupUtils.close(dialogueLogout);
292− stages.dialogShown = false;
293− }
294− }
295− }
296− }
164+ Loader {
165+ id: applicationsDisplayLoader
166+ anchors.fill: parent
297167
298− Component {
299− id: shutdownDialog
300− Dialog {
301− id: dialogueShutdown
302− title: "Shutdown"
303− text: "Are you sure that you want to shutdown?"
304− Button {
305− text: "Cancel"
306− onClicked: {
307− PopupUtils.close(dialogueShutdown);
308− stages.dialogShown = false;
309− }
310− }
311− Button {
312− text: "Yes"
313− onClicked: {
314− dBusUnitySessionServiceConnection.closeAllApps();
315− DBusUnitySessionService.Shutdown();
316− PopupUtils.close(dialogueShutdown);
317− stages.dialogShown = false;
318− }
319− }
320− }
321− }
168+ source: shell.sideStageEnabled ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
322169
323− Component {
324− id: rebootDialog
325− Dialog {
326− id: dialogueReboot
327− title: "Reboot"
328− text: "Are you sure that you want to reboot?"
329− Button {
330− text: "Cancel"
331− onClicked: {
332− PopupUtils.close(dialogueReboot)
333− stages.dialogShown = false;
334− }
335− }
336− Button {
337− text: "Yes"
338− onClicked: {
339− dBusUnitySessionServiceConnection.closeAllApps();
340− DBusUnitySessionService.Reboot();
341− PopupUtils.close(dialogueReboot);
342− stages.dialogShown = false;
343− }
344− }
170+ Binding {
171+ target: applicationsDisplayLoader.item
172+ property: "objectName"
173+ value: "stage"
345174 }
346− }
347−
348− Component {
349− id: powerDialog
350− Dialog {
351− id: dialoguePower
352− title: "Power"
353− text: i18n.tr("Are you sure you would like to turn power off?")
354− Button {
355− text: i18n.tr("Power off")
356− onClicked: {
357− dBusUnitySessionServiceConnection.closeAllApps();
358− PopupUtils.close(dialoguePower);
359− stages.dialogShown = false;
360− shutdownFadeOutRectangle.enabled = true;
361− shutdownFadeOutRectangle.visible = true;
362− shutdownFadeOut.start();
363− }
364− }
365− Button {
366− text: i18n.tr("Restart")
367− onClicked: {
368− dBusUnitySessionServiceConnection.closeAllApps();
369− DBusUnitySessionService.Reboot();
370− PopupUtils.close(dialoguePower);
371− stages.dialogShown = false;
372− }
373− }
374− Button {
375− text: i18n.tr("Cancel")
376− onClicked: {
377− PopupUtils.close(dialoguePower);
378− stages.dialogShown = false;
379− }
380− }
175+ Binding {
176+ target: applicationsDisplayLoader.item
177+ property: "dragAreaWidth"
178+ value: shell.edgeSize
381179 }
382− }
383−
384− function showPowerDialog() {
385− if (!stages.dialogShown) {
386− stages.dialogShown = true;
387− PopupUtils.open(powerDialog);
180+ Binding {
181+ target: applicationsDisplayLoader.item
182+ property: "maximizedAppTopMargin"
183+ // Not just using panel.panelHeight as that changes depending on the focused app.
184+ value: panel.indicators.panelHeight
388185 }
389− }
390−
391− Connections {
392− id: dBusUnitySessionServiceConnection
393− objectName: "dBusUnitySessionServiceConnection"
394− target: DBusUnitySessionService
395−
396− function closeAllApps() {
397− while (true) {
398− var app = ApplicationManager.get(0);
399− if (app === null) {
400− break;
401− }
402− ApplicationManager.stopApplication(app.appId);
403− }
186+ Binding {
187+ target: applicationsDisplayLoader.item
188+ property: "interactive"
189+ value: !greeter.shown && !lockscreen.shown && panel.indicators.fullyClosed && launcher.progress == 0
404190 }
405−
406− onLogoutRequested: {
407− // Display a dialog to ask the user to confirm.
408− if (!stages.dialogShown) {
409− stages.dialogShown = true;
410− PopupUtils.open(logoutDialog);
411− }
191+ Binding {
192+ target: applicationsDisplayLoader.item
193+ property: "spreadEnabled"
194+ value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
412195 }
413−
414− onShutdownRequested: {
415− // Display a dialog to ask the user to confirm.
416− if (!stages.dialogShown) {
417− stages.dialogShown = true;
418− PopupUtils.open(shutdownDialog);
419− }
196+ Binding {
197+ target: applicationsDisplayLoader.item
198+ property: "inverseProgress"
199+ value: launcher.progress
420200 }
201+ }
202+ }
421203
422− onRebootRequested: {
423− // Display a dialog to ask the user to confirm.
424− if (!stages.dialogShown) {
425− stages.dialogShown = true;
426− PopupUtils.open(rebootDialog);
427− }
428− }
204+ InputMethod {
205+ id: inputMethod
206+ objectName: "inputMethod"
207+ anchors { fill: parent; topMargin: panel.panelHeight }
208+ z: notifications.useModal || panel.indicators.shown ? overlay.z + 1 : overlay.z - 1
209+ }
429210
430− onLogoutReady: {
431− closeAllApps();
432− Qt.quit();
211+ Connections {
212+ target: SurfaceManager
213+ onSurfaceCreated: {
214+ if (surface.type == MirSurfaceItem.InputMethod) {
215+ inputMethod.surface = surface;
433216 }
434217 }
435218
436− Loader {
437− id: applicationsDisplayLoader
438− anchors.fill: parent
439−
440− source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
441−
442− Binding {
443− target: applicationsDisplayLoader.item
444− property: "moving"
445− value: !stages.fullyShown
446− }
447− Binding {
448− target: applicationsDisplayLoader.item
449− property: "shown"
450− value: stages.shown
219+ onSurfaceDestroyed: {
220+ if (inputMethod.surface == surface) {
221+ inputMethod.surface = null;
222+ surface.parent = null;
451223 }
452− Binding {
453− target: applicationsDisplayLoader.item
454− property: "dragAreaWidth"
455− value: shell.edgeSize
224+ if (!surface.parent) {
225+ // there's no one displaying it. delete it right away
226+ surface.release();
456227 }
457228 }
458229 }
@@ -469,18 +240,26 @@ FocusScope {
469240 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
470241 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
471242 y: panel.panelHeight
472− x: required ? 0 : - width
243+ visible: required
473244 width: parent.width
474245 height: parent.height - panel.panelHeight
475246 background: shell.background
247+ alphaNumeric: AccountsService.passwordDisplayHint === AccountsService.Keyboard
476248 minPinLength: 4
477249 maxPinLength: 4
478250
479251 onEntered: LightDM.Greeter.respond(passphrase);
480252 onCancel: greeter.show()
253+ onEmergencyCall: {
254+ greeter.fakeActiveForApp = "dialer-app"
255+ shell.activateApplication("dialer-app")
256+ lockscreen.hide()
257+ }
258+
259+ onShownChanged: if (shown) greeter.fakeActiveForApp = ""
481260
482261 Component.onCompleted: {
483− if (LightDM.Users.count == 1) {
262+ if (greeter.narrowMode) {
484263 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
485264 }
486265 }
@@ -492,14 +271,17 @@ FocusScope {
492271 onShowGreeter: greeter.show()
493272
494273 onShowPrompt: {
495− if (LightDM.Users.count == 1) {
496− // TODO: There's no better way for now to determine if its a PIN or a passphrase.
497− if (text == "PIN") {
498− lockscreen.alphaNumeric = false
499− } else {
500− lockscreen.alphaNumeric = true
501− }
502− lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text);
274+ if (greeter.narrowMode) {
275+ lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text.toLowerCase());
276+ lockscreen.show();
277+ }
278+ }
279+
280+ onPromptlessChanged: {
281+ if (LightDM.Greeter.promptless) {
282+ lockscreen.hide()
283+ } else {
284+ lockscreen.reset();
503285 lockscreen.show();
504286 }
505287 }
@@ -510,8 +292,12 @@ FocusScope {
510292 }
511293 if (LightDM.Greeter.authenticated) {
512294 lockscreen.hide();
295+ greeter.login();
513296 } else {
514297 lockscreen.clear(true);
298+ if (greeter.narrowMode) {
299+ LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole))
300+ }
515301 }
516302 }
517303 }
@@ -519,7 +305,7 @@ FocusScope {
519305 Binding {
520306 target: LightDM.Greeter
521307 property: "active"
522− value: greeter.shown || lockscreen.shown
308+ value: greeter.shown || lockscreen.shown || greeter.fakeActiveForApp != ""
523309 }
524310
525311 Rectangle {
@@ -541,12 +327,18 @@ FocusScope {
541327 StandardAnimation {}
542328 }
543329
330+ property bool fullyShown: showProgress === 1.0
544331 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
332+ onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
545333
546334 Greeter {
547335 id: greeter
548336 objectName: "greeter"
549337
338+ signal sessionStarted() // helpful for tests
339+
340+ property string fakeActiveForApp: ""
341+
550342 available: true
551343 hides: [launcher, panel.indicators]
552344 shown: true
@@ -558,17 +350,27 @@ FocusScope {
558350
559351 dragHandleWidth: shell.edgeSize
560352
353+ function login() {
354+ enabled = false;
355+ if (LightDM.Greeter.startSessionSync()) {
356+ sessionStarted();
357+ greeter.hide();
358+ lockscreen.hide();
359+ launcher.hide();
360+ }
361+ enabled = true;
362+ }
363+
561364 onShownChanged: {
562365 if (shown) {
563− lockscreen.reset();
564− if (!LightDM.Greeter.promptless) {
565− lockscreen.show();
566− }
567− // If there is only one user, we start authenticating with that one here.
568− // If there are more users, the Greeter will handle that
569− if (LightDM.Users.count == 1) {
366+ if (greeter.narrowMode) {
570367 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
571368 }
369+ if (!LightDM.Greeter.promptless) {
370+ lockscreen.reset();
371+ lockscreen.show();
372+ }
373+ greeter.fakeActiveForApp = "";
572374 greeter.forceActiveFocus();
573375 }
574376 }
@@ -591,12 +393,6 @@ FocusScope {
591393 }
592394 }
593395
594− InputFilterArea {
595− anchors.fill: parent
596− blockInput: ApplicationManager.focusedApplicationId.length === 0 || greeter.shown || lockscreen.shown || launcher.shown
597− || panel.indicators.shown
598− }
599−
600396 Connections {
601397 id: powerConnection
602398 target: Powerd
@@ -618,54 +414,64 @@ FocusScope {
618414 }
619415
620416 function showHome() {
621− var animate = !greeter.shown && !stages.shown
622− greeter.hide()
417+ if (edgeDemo.running) {
418+ return
419+ }
420+
421+ if (LightDM.Greeter.active) {
422+ if (!LightDM.Greeter.promptless) {
423+ lockscreen.show()
424+ }
425+ greeter.hide()
426+ }
427+
428+ var animate = !LightDM.Greeter.active && !stages.shown
623429 dash.setCurrentScope("clickscope", animate, false)
624− stages.hide()
430+ ApplicationManager.requestFocusApplication("unity8-dash")
431+ }
432+
433+ function showDash() {
434+ if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
435+ return;
436+ }
437+ if (greeter.shown) {
438+ greeter.hideRight();
439+ launcher.fadeOut();
440+ }
441+
442+ ApplicationManager.requestFocusApplication("unity8-dash")
443+ launcher.fadeOut();
625444 }
626445
627446 Item {
628447 id: overlay
448+ z: 10
629449
630450 anchors.fill: parent
631451
632452 Panel {
633453 id: panel
454+ objectName: "panel"
634455 anchors.fill: parent //because this draws indicator menus
635456 indicators {
636457 hides: [launcher]
637− available: edgeDemo.panelEnabled
458+ available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
638459 contentEnabled: edgeDemo.panelContentEnabled
639460 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
640461 panelHeight: units.gu(3)
641462 }
642− property string focusedAppId: ApplicationManager.focusedApplicationId
643− property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
644− fullscreenMode: focusedApplication && stages.fullscreen && !greeter.shown && !lockscreen.shown
645463
646− InputFilterArea {
647− anchors {
648− top: parent.top
649− left: parent.left
650− right: parent.right
651− }
652− height: (panel.fullscreenMode) ? shell.edgeSize : panel.panelHeight
653− blockInput: true
654− }
655− }
464+ property bool topmostApplicationIsFullscreen:
465+ ApplicationManager.focusedApplicationId &&
466+ ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
656467
657− InputFilterArea {
658− blockInput: launcher.shown
659− anchors {
660− top: parent.top
661− bottom: parent.bottom
662− left: parent.left
663− }
664− width: launcher.width
468+ fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
469+ || greeter.fakeActiveForApp !== ""
665470 }
666471
667472 Launcher {
668473 id: launcher
474+ objectName: "launcher"
669475
670476 readonly property bool dashSwipe: progress > 0
671477
@@ -673,29 +479,19 @@ FocusScope {
673479 anchors.bottom: parent.bottom
674480 width: parent.width
675481 dragAreaWidth: shell.edgeSize
676− available: edgeDemo.launcherEnabled
677−
678− onShowDashHome: {
679− if (edgeDemo.running)
680− return;
681−
682− showHome()
683− }
684− onDash: {
685− if (stages.shown && !stages.overlayMode && !stages.locked) {
686− stages.hide();
687− launcher.fadeOut();
688− } else {
689− launcher.switchToNextState("visible");
690− }
482+ available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
691483
692− if (greeter.shown) {
693− greeter.hideRight();
694− launcher.fadeOut();
484+ onShowDashHome: showHome()
485+ onDash: showDash()
486+ onDashSwipeChanged: {
487+ if (dashSwipe && ApplicationManager.focusedApplicationId !== "unity8-dash") {
488+ dash.setCurrentScope("clickscope", false, true)
695489 }
696490 }
697− onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
698491 onLauncherApplicationSelected: {
492+ if (greeter.fakeActiveForApp !== "") {
493+ lockscreen.show()
494+ }
699495 if (!edgeDemo.running)
700496 shell.activateApplication(appId)
701497 }
@@ -717,11 +513,6 @@ FocusScope {
717513 MouseArea {
718514 anchors.fill: parent
719515 }
720−
721− InputFilterArea {
722− anchors.fill: parent
723− blockInput: modalNotificationBackground.visible
724− }
725516 }
726517
727518 Notifications {
@@ -747,62 +538,31 @@ FocusScope {
747538 PropertyChanges { target: notifications; width: units.gu(38) }
748539 }
749540 ]
750−
751− InputFilterArea {
752− anchors { left: parent.left; right: parent.right }
753− height: parent.contentHeight
754− blockInput: height > 0
755− }
756541 }
757542 }
758543
759− focus: true
760− onFocusChanged: if (!focus) forceActiveFocus();
761−
762− InputFilterArea {
763− anchors {
764− top: parent.top
765− bottom: parent.bottom
766− left: parent.left
767− }
768− width: shell.edgeSize
769− blockInput: true
770− }
771−
772− InputFilterArea {
773− anchors {
774− top: parent.top
775− bottom: parent.bottom
776− right: parent.right
777− }
778− width: shell.edgeSize
779− blockInput: true
780− }
781−
782544 Binding {
783545 target: i18n
784546 property: "domain"
785547 value: "unity8"
786548 }
787549
788− OSKController {
789− anchors.topMargin: panel.panelHeight
790− anchors.fill: parent // as needs to know the geometry of the shell
791− }
792−
793− //FIXME: This should be handled in the input stack, keyboard shouldnt propagate
794− MouseArea {
795− anchors.bottom: parent.bottom
796− anchors.left: parent.left
797− anchors.right: parent.right
798− height: ApplicationManager.keyboardVisible ? ApplicationManager.keyboardHeight : 0
799−
800− enabled: ApplicationManager.keyboardVisible
550+ Dialogs {
551+ id: dialogs
552+ anchors.fill: parent
553+ z: overlay.z + 10
554+ onPowerOffClicked: {
555+ shutdownFadeOutRectangle.enabled = true;
556+ shutdownFadeOutRectangle.visible = true;
557+ shutdownFadeOut.start();
558+ }
801559 }
802560
803561 Label {
562+ id: alphaDisclaimerLabel
804563 anchors.centerIn: parent
805564 visible: ApplicationManager.fake ? ApplicationManager.fake : false
565+ z: dialogs.z + 10
806566 text: "EARLY ALPHA\nNOT READY FOR USE"
807567 color: "lightgrey"
808568 opacity: 0.2
@@ -816,9 +576,9 @@ FocusScope {
816576
817577 EdgeDemo {
818578 id: edgeDemo
579+ z: alphaDisclaimerLabel.z + 10
819580 greeter: greeter
820581 launcher: launcher
821− dash: dash
822582 indicators: panel.indicators
823583 underlay: underlay
824584 }
@@ -828,35 +588,9 @@ FocusScope {
828588 onShowHome: showHome()
829589 }
830590
831− Keys.onPressed: {
832− if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
833− if (!powerKeyTimer.running) {
834− powerKeyTimer.start();
835− }
836− event.accepted = true;
837− }
838− }
839−
840− Keys.onReleased: {
841− if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
842− powerKeyTimer.stop();
843− event.accepted = true;
844− }
845− }
846−
847− Timer {
848− id: powerKeyTimer
849− interval: 2000
850− repeat: false
851− triggeredOnStart: false
852−
853− onTriggered: {
854− stages.showPowerDialog();
855− }
856− }
857−
858591 Rectangle {
859592 id: shutdownFadeOutRectangle
593+ z: edgeDemo.z + 10
860594 enabled: false
861595 visible: false
862596 color: "black"
@@ -873,4 +607,5 @@ FocusScope {
873607 }
874608 }
875609 }
610+
876611}
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−266
@@ -21,91 +21,65 @@ import Unity.Application 0.1
2121import Utils 0.1
2222import "../Components"
2323
24−Item {
24+Rectangle {
2525 id: root
2626
2727 // Controls to be set from outside
28− property bool shown: false
29− property bool moving: false
3028 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.
3133
32− // State information propagated to the outside
33− readonly property bool painting: mainScreenshotImage.visible || fadeInScreenshotImage.visible || appSplash.visible || spreadView.visible
34− property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
35− property bool locked: spreadView.visible
36−
37− // Not used for PhoneStage, only useful for SideStage and similar
38− property bool overlayMode: false
39− property int overlayWidth: 0
34+ color: "black"
4035
4136 function select(appId) {
42− spreadView.snapTo(priv.indexOf(appId))
37+ spreadView.snapTo(priv.indexOf(appId));
4338 }
4439
45− onMovingChanged: {
46− if (moving) {
47− if (ApplicationManager.focusedApplicationId) {
48− priv.requestNewScreenshot();
49− } else {
50− mainScreenshotImage.anchors.leftMargin = 0;
51− mainScreenshotImage.source = ApplicationManager.get(0).screenshot;
52− 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");
5351 }
54− } else {
55− mainScreenshotImage.visible = false;
5652 }
53+ priv.oldInverseProgress = inverseProgress;
5754 }
5855
5956 Connections {
6057 target: ApplicationManager
6158
6259 onFocusRequested: {
63− if (spreadView.visible) {
60+ if (spreadView.phase > 0) {
6461 spreadView.snapTo(priv.indexOf(appId));
6562 } else {
66− priv.switchToApp(appId);
63+ ApplicationManager.focusApplication(appId);
6764 }
6865 }
6966
70− onFocusedApplicationIdChanged: {
71− if (ApplicationManager.focusedApplicationId.length > 0) {
72− if (priv.secondApplicationStarting || priv.applicationStarting) {
73− appSplashTimer.restart();
74− } else {
75− var application = priv.focusedApplication;
76− root.fullscreen = application.fullscreen;
77− mainScreenshotImage.source = application.screenshot;
78− }
67+ onApplicationAdded: {
68+ if (spreadView.phase == 2) {
69+ spreadView.snapTo(ApplicationManager.count - 1);
7970 } else {
80− spreadView.selectedIndex = -1;
8171 spreadView.phase = 0;
8272 spreadView.contentX = -spreadView.shift;
83− }
84− }
85−
86− onApplicationAdded: {
87− if (!priv.focusedApplication) {
88− mainScreenshotImage.source = "";
89− mainScreenshotImage.visible = false;
90− priv.applicationStarting = true;
91− } else {
92− mainScreenshotImage.source = "";
93− priv.newFocusedAppId = appId;
94− priv.secondApplicationStarting = true;
95− priv.requestNewScreenshot();
96− }
97−
98− if (spreadView.visible) {
99− spreadView.snapTo(0);
73+ ApplicationManager.focusApplication(appId);
10074 }
10175 }
10276
10377 onApplicationRemoved: {
104− if (ApplicationManager.count == 0) {
105− mainScreenshotImage.source = ""
106− mainScreenshotImage.visible = false;
107− } else {
108− 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;
10983 }
11084 }
11185 }
@@ -115,40 +89,11 @@ Item {
11589
11690 property string focusedAppId: ApplicationManager.focusedApplicationId
11791 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
118− property url focusedScreenshot: focusedApplication ? focusedApplication.screenshot : ""
119−
120− property bool waitingForScreenshot: false
121−
122− property bool applicationStarting: false
123− property bool secondApplicationStarting: false
124−
125− property string newFocusedAppId
92+ property var focusedAppDelegate: null
12693
127− onFocusedScreenshotChanged: {
128− if (root.moving && priv.waitingForScreenshot) {
129− mainScreenshotImage.anchors.leftMargin = 0;
130− mainScreenshotImage.source = priv.focusedScreenshot
131− mainScreenshotImage.visible = true;
132− } else if (priv.secondApplicationStarting && priv.waitingForScreenshot) {
133− applicationSwitchingAnimation.start();
134− }
135− waitingForScreenshot = false;
136− }
94+ property real oldInverseProgress: 0
13795
138− function requestNewScreenshot() {
139− waitingForScreenshot = true;
140− ApplicationManager.updateScreenshot(focusedAppId);
141− }
142−
143− function switchToApp(appId) {
144− if (priv.focusedAppId) {
145− priv.newFocusedAppId = appId;
146− root.fullscreen = ApplicationManager.findApplication(appId).fullscreen;
147− applicationSwitchingAnimation.start();
148− } else {
149− ApplicationManager.focusApplication(appId);
150− }
151− }
96+ onFocusedAppIdChanged: focusedAppDelegate = spreadRepeater.itemAt(0);
15297
15398 function indexOf(appId) {
15499 for (var i = 0; i < ApplicationManager.count; i++) {
@@ -161,185 +106,25 @@ Item {
161106
162107 }
163108
164− // FIXME: the signal connections seems to get lost.
165− Connections {
166− target: priv.focusedApplication
167− onScreenshotChanged: priv.focusedScreenshot = priv.focusedApplication.screenshot
168− }
169− Binding {
170− target: root
171− property: "fullscreen"
172− value: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
173− }
174−
175− Timer {
176− id: appSplashTimer
177− // FIXME: We really need to show something meaningful in the app surface instead of guessing
178− // when it might be ready
179− interval: 500
180− repeat: false
181− onTriggered: {
182− priv.applicationStarting = false;
183− priv.secondApplicationStarting = false;
184− }
185− }
186−
187− SequentialAnimation {
188− id: applicationSwitchingAnimation
189− // setup
190− PropertyAction { target: mainScreenshotImage; property: "anchors.leftMargin"; value: 0 }
191− PropertyAction { target: mainScreenshotImage; property: "source"; value: priv.focusedScreenshot }
192− PropertyAction { targets: [mainScreenshotImage, fadeInScreenshotImage]; property: "visible"; value: true }
193− PropertyAction { target: fadeInScreenshotImage; property: "source"; value: {
194− var newFocusedApp = ApplicationManager.findApplication(priv.newFocusedAppId);
195− return newFocusedApp ? newFocusedApp.screenshot : "" }
196− }
197− PropertyAction { target: fadeInScreenshotImage; property: "opacity"; value: 0 }
198− PropertyAction { target: fadeInScreenshotImage; property: "scale"; value: .8 }
199−
200−
201− // The actual animation
202− ParallelAnimation {
203− UbuntuNumberAnimation { target: mainScreenshotImage; property: "anchors.leftMargin"; to: root.width; duration: UbuntuAnimation.SlowDuration }
204− UbuntuNumberAnimation { target: fadeInScreenshotImage; properties: "opacity,scale"; to: 1; duration: UbuntuAnimation.SlowDuration }
205− }
206−
207− // restore stuff
208− ScriptAction { script: ApplicationManager.focusApplication(priv.newFocusedAppId); }
209− PropertyAction { target: fadeInScreenshotImage; property: "visible"; value: false }
210− PropertyAction { target: mainScreenshotImage; property: "visible"; value: false }
211− }
212−
213− // FIXME: Drop this and make the imageprovider show a splashscreen instead
214− Rectangle {
215− id: appSplash2
216− anchors.fill: parent
217− color: "black"
218− visible: priv.secondApplicationStarting
219− }
220− Image {
221− id: fadeInScreenshotImage
222− anchors { left: parent.left; bottom: parent.bottom }
223− width: parent.width
224− scale: .7
225− visible: false
226− }
227−
228− Rectangle {
229− id: appSplash
230− anchors.fill: parent
231− color: "black"
232− visible: priv.applicationStarting
233−
234− WaitingDots {
235− }
236− }
237− Image {
238− id: mainScreenshotImage
239− anchors { left: parent.left; bottom: parent.bottom }
240− width: parent.width
241− visible: false
242− }
243−
244− EdgeDragArea {
245− id: spreadDragArea
246− direction: Direction.Leftwards
247− enabled: ApplicationManager.count > 1 && spreadView.phase != 2
248−
249− anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
250− width: root.dragAreaWidth
251−
252− // Sitting at the right edge of the screen, this EdgeDragArea directly controls the spreadView when
253− // attachedToView is true. When the finger movement passes positionMarker3 we detach it from the
254− // spreadView and make the spreadView snap to positionMarker4.
255− property bool attachedToView: true
256−
257− property var gesturePoints: new Array()
258−
259− onTouchXChanged: {
260− if (!dragging && !priv.waitingForScreenshot) {
261− // Initial touch. Let's update the screenshot and reset the spreadView to the starting position.
262− priv.requestNewScreenshot();
263− spreadView.phase = 0;
264− spreadView.contentX = -spreadView.shift;
265− }
266− if (dragging && attachedToView) {
267− // Gesture recognized. Let's move the spreadView with the finger
268− spreadView.contentX = -touchX - spreadView.shift;
269− }
270− if (attachedToView && spreadView.shiftedContentX >= spreadView.width * spreadView.positionMarker3) {
271− // We passed positionMarker3. Detach from spreadView and snap it.
272− attachedToView = false;
273− spreadView.snap();
274− }
275− gesturePoints.push(touchX);
276− }
277−
278− onStatusChanged: {
279− if (status == DirectionalDragArea.Recognized) {
280− attachedToView = true;
281− }
282− }
283−
284− onDraggingChanged: {
285− if (dragging) {
286− // Gesture recognized. Start recording this gesture
287− gesturePoints = [];
288− return;
289− }
290−
291− // Ok. The user released. Find out if it was a one-way movement.
292− var oneWayFlick = true;
293− var smallestX = spreadDragArea.width;
294− for (var i = 0; i < gesturePoints.length; i++) {
295− if (gesturePoints[i] >= smallestX) {
296− oneWayFlick = false;
297− break;
298− }
299− smallestX = gesturePoints[i];
300− }
301− gesturePoints = [];
302−
303− if (oneWayFlick && spreadView.shiftedContentX > units.gu(2) &&
304− spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
305− // If it was a short one-way movement, do the Alt+Tab switch
306− // no matter if we didn't cross positionMarker1 yet.
307− spreadView.snapTo(1);
308− } else if (!dragging && attachedToView) {
309− // otherwise snap to the closest snap position we can find
310− // (might be back to start, to app 1 or to spread)
311− spreadView.snap();
312− }
313− }
314− }
315−
316− Rectangle {
317− id: coverFlipBackground
318− anchors.fill: parent
319− color: "black"
320− visible: spreadView.visible
321− }
322−
323− InputFilterArea {
324− anchors.fill: root
325− blockInput: spreadView.visible
326− }
327−
328109 Flickable {
329110 id: spreadView
330111 objectName: "spreadView"
331112 anchors.fill: parent
332− visible: spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1 || snapAnimation.running
113+ interactive: (spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1) && draggedIndex == -1
333114 contentWidth: spreadRow.width - shift
334115 contentX: -shift
335116
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+
336121 // The flickable needs to fill the screen in order to get touch events all over.
337122 // However, we don't want to the user to be able to scroll back all the way. For
338123 // that, the beginning of the gesture starts with a negative value for contentX
339124 // so the flickable wants to pull it into the view already. "shift" tunes the
340125 // distance where to "lock" the content.
341− property real shift: width / 2
342− property real shiftedContentX: contentX + shift
126+ readonly property real shift: width / 2
127+ readonly property real shiftedContentX: contentX + shift
343128
344129 property int tileDistance: width / 4
345130
@@ -363,6 +148,10 @@ Item {
363148 property int phase: 0
364149
365150 property int selectedIndex: -1
151+ property int draggedIndex: -1
152+ property int closingIndex: -1
153+
154+ property bool focusChanging: false
366155
367156 onShiftedContentXChanged: {
368157 switch (phase) {
@@ -386,9 +175,9 @@ Item {
386175 snapAnimation.targetContentX = -shift;
387176 snapAnimation.start();
388177 } else if (shiftedContentX < positionMarker2 * width) {
389− snapTo(1)
178+ snapTo(1);
390179 } else if (shiftedContentX < positionMarker3 * width) {
391− snapTo(1)
180+ snapTo(1);
392181 } else if (phase < 2){
393182 // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
394183 snapAnimation.targetContentX = width * positionMarker4 + 1 - shift;
@@ -396,12 +185,27 @@ Item {
396185 }
397186 }
398187 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+ }
399192 spreadView.selectedIndex = index;
400− root.fullscreen = ApplicationManager.get(index).fullscreen;
401− 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+ }
402200 snapAnimation.start();
403201 }
404202
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+
405209 SequentialAnimation {
406210 id: snapAnimation
407211 property int targetContentX: -spreadView.shift
@@ -417,7 +221,8 @@ Item {
417221 script: {
418222 if (spreadView.selectedIndex >= 0) {
419223 ApplicationManager.focusApplication(ApplicationManager.get(spreadView.selectedIndex).appId);
420− spreadView.selectedIndex = -1
224+
225+ spreadView.selectedIndex = -1;
421226 spreadView.phase = 0;
422227 spreadView.contentX = -spreadView.shift;
423228 }
@@ -431,6 +236,15 @@ Item {
431236 // tileDistance * app count (with a minimum of 3 apps, in order to also allow moving 1 and 2 apps a bit)
432237 // + some constant value (still scales with the screen width) which looks good and somewhat fills the screen
433238 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+ }
434248
435249 x: spreadView.contentX
436250
@@ -450,18 +264,76 @@ Item {
450264 height: spreadView.height
451265 selected: spreadView.selectedIndex == index
452266 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+ }
453305
454− z: index
455− 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+ }
456319
457320 // Each tile has a different progress value running from 0 to 1.
458− // 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
459324 progress: {
460− var tileProgress = (spreadView.shiftedContentX - index * spreadView.tileDistance) / spreadView.width;
325+ var tileProgress = (spreadView.shiftedContentX - behavioredIndex * spreadView.tileDistance) / spreadView.width;
461326 // Tile 1 needs to move directly from the beginning...
462− if (index == 1 && spreadView.phase < 2) {
327+ if (behavioredIndex == 1 && spreadView.phase < 2) {
463328 tileProgress += spreadView.tileDistance / spreadView.width;
464329 }
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));
465337 return tileProgress;
466338 }
467339
@@ -479,9 +351,13 @@ Item {
479351 return progress;
480352 }
481353
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+
482358 EasingCurve {
483359 id: snappingCurve
484− type: EasingCurve.OutQuad
360+ type: EasingCurve.Linear
485361 period: 0.05
486362 progress: appDelegate.progress - spreadView.positionMarker1
487363 }
@@ -495,8 +371,85 @@ Item {
495371 }
496372 }
497373 }
374+
375+ onClosed: {
376+ spreadView.draggedIndex = -1;
377+ spreadView.closingIndex = index;
378+ ApplicationManager.stopApplication(ApplicationManager.get(index).appId);
379+ }
498380 }
499381 }
500382 }
501383 }
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;
438+ }
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();
452+ }
453+ }
454+ }
502455}
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"
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+12
@@ -0,0 +1,12 @@
1+set(DASH_SRCS
2+ main.cpp
3+)
4+
5+add_executable(unity8-dash ${DASH_SRCS})
6+
7+qt5_use_modules(unity8-dash Gui Qml Quick Test)
8+
9+# install binaries
10+install(TARGETS ${DASH_APP}
11+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
12+)
src/Dash/main.cppnew file+74
@@ -0,0 +1,74 @@
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+
28+#include <paths.h>
29+
30+int main(int argc, const char *argv[])
31+{
32+ QGuiApplication *application = new QGuiApplication(argc, (char**)argv);
33+
34+ QCommandLineParser parser;
35+ parser.setApplicationDescription("Description: Unity 8 Shell Dash");
36+ parser.addHelpOption();
37+
38+ QCommandLineOption testabilityOption("testability",
39+ "Load the testability driver (Alternatively export QT_LOAD_TESTABILITY");
40+ parser.addOption(testabilityOption);
41+
42+ if (parser.isSet(testabilityOption) || getenv("QT_LOAD_TESTABILITY")) {
43+ QLibrary testLib(QLatin1String("qttestability"));
44+ if (testLib.load()) {
45+ typedef void (*TasInitialize)(void);
46+ TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
47+ if (initFunction) {
48+ initFunction();
49+ } else {
50+ qCritical("Library qttestability resolve failed!");
51+ }
52+ } else {
53+ qCritical("Library qttestability load failed!");
54+ }
55+ }
56+
57+ QQuickView* view = new QQuickView();
58+ view->setResizeMode(QQuickView::SizeRootObjectToView);
59+ view->setTitle("Unity Dash");
60+
61+ QUrl source(::qmlDirectory()+"Dash/DashApplication.qml");
62+ prependImportPaths(view->engine(), ::overrideImportPaths());
63+ appendImportPaths(view->engine(), ::fallbackImportPaths());
64+
65+ view->setSource(source);
66+ view->show();
67+
68+ int result = application->exec();
69+
70+ delete view;
71+ delete application;
72+
73+ return result;
74+}
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+33−18
@@ -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,29 +120,31 @@ 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)
@@ -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−9
@@ -19,8 +19,6 @@
1919#include "../Greeter.h"
2020#include "../GreeterPrivate.h"
2121
22−#include <QDebug>
23−
2422namespace QLightDM
2523{
2624
@@ -34,19 +32,13 @@ GreeterPrivate::GreeterPrivate(Greeter* parent)
3432void GreeterPrivate::handleAuthenticate()
3533{
3634 Q_Q(Greeter);
37−
38− qDebug() << "handleAuthentication called!" << authenticationUser;
39−
40− Q_EMIT q->showPrompt("PIN:", Greeter::PromptTypeSecret);
35+ Q_EMIT q->showPrompt("Password:", Greeter::PromptTypeSecret);
4136}
4237
4338void GreeterPrivate::handleRespond(const QString &response)
4439{
4540 Q_Q(Greeter);
46−
47−
4841 authenticated = (response == "1234");
49− qDebug() << "responding" << response << authenticated;
5042 Q_EMIT q->authenticationComplete();
5143}
5244
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/QMenuModel/unitymenumodel.cpp+5
@@ -126,6 +126,11 @@ void UnityMenuModel::setActionStateParser(ActionStateParser*)
126126{
127127}
128128
129+QString UnityMenuModel::nameOwner() const
130+{
131+ return QString("");
132+}
133+
129134int UnityMenuModel::rowCount(const QModelIndex&) const
130135{
131136 return m_modelData.count();
tests/mocks/QMenuModel/unitymenumodel.h+4
@@ -32,6 +32,7 @@ class Q_DECL_EXPORT UnityMenuModel : public QAbstractListModel
3232 Q_PROPERTY(QVariantMap actions READ actions WRITE setActions NOTIFY actionsChanged)
3333 Q_PROPERTY(QByteArray menuObjectPath READ menuObjectPath WRITE setMenuObjectPath NOTIFY menuObjectPathChanged)
3434 Q_PROPERTY(ActionStateParser* actionStateParser READ actionStateParser WRITE setActionStateParser NOTIFY actionStateParserChanged)
35+ Q_PROPERTY(QString nameOwner READ nameOwner NOTIFY nameOwnerChanged)
3536
3637public:
3738 UnityMenuModel(QObject *parent = NULL);
@@ -56,6 +57,8 @@ public:
5657 ActionStateParser* actionStateParser() const;
5758 void setActionStateParser(ActionStateParser* actionStateParser);
5859
60+ QString nameOwner() const;
61+
5962 int rowCount(const QModelIndex &parent = QModelIndex()) const;
6063 int columnCount(const QModelIndex &parent = QModelIndex()) const;
6164 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
@@ -79,6 +82,7 @@ Q_SIGNALS:
7982 void menuObjectPathChanged();
8083 void actionStateParserChanged();
8184 void modelDataChanged();
85+ void nameOwnerChanged();
8286
8387private:
8488 QVariantMap rowData(int row) const;
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+}
tests/mocks/Unity/Application/VirtualKeyboard.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
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 VIRTUALKEYBOARD_H
18+#define VIRTUALKEYBOARD_H
19+
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+2−1
@@ -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=3)
1011
1112include_directories(
1213 ${CMAKE_CURRENT_BINARY_DIR}
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/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_scope.cpp+8−11
@@ -24,7 +24,7 @@ Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)
2424{
2525}
2626
27−Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
27+Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent, int categories)
2828 : unity::shell::scopes::ScopeInterface(parent)
2929 , m_id(id)
3030 , m_name(name)
@@ -33,7 +33,7 @@ Scope::Scope(QString const& id, QString const& name, bool visible, QObject* pare
3333 , m_isActive(false)
3434 , m_currentDeparment("root")
3535 , m_previewRendererName("preview-generic")
36− , m_categories(new Categories(20, this))
36+ , m_categories(new Categories(categories, this))
3737{
3838}
3939
@@ -182,14 +182,16 @@ bool Scope::hasDepartments() const
182182
183183QVariantMap Scope::customizations() const
184184{
185− QVariantMap m;
185+ QVariantMap m, h;
186186 if (m_id == "clickscope") {
187+ h["foreground-color"] = "yellow";
187188 m["background-color"] = "red";
188189 m["foreground-color"] = "blue";
190+ m["page-header"] = h;
189191 } 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;
192+ h["background"] = "gradient:///lightgrey/grey";
193+ h["logo"] = QUrl("../../../tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg");
194+ m["page-header"] = h;
193195 }
194196 return m;
195197}
@@ -216,8 +218,3 @@ void Scope::loadDepartment(const QString& id)
216218 m_currentDeparment = id;
217219 Q_EMIT currentDepartmentIdChanged();
218220}
219−
220−void Scope::performQuery(const QString& query)
221−{
222− Q_UNUSED(query);
223−}
tests/mocks/Unity/fake_scope.h+2−2
@@ -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 visible, QObject* parent = 0, int categories = 20);
3434
3535 /* getters */
3636 QString id() const override;
@@ -64,7 +64,7 @@ public:
6464 bool hasDepartments() const override;
6565 Q_INVOKABLE unity::shell::scopes::DepartmentInterface* getDepartment(const QString& id) override;
6666 Q_INVOKABLE void loadDepartment(const QString& id) override;
67− Q_INVOKABLE void performQuery(const QString& query) override;
67+ Q_SIGNAL void performQuery(const QString& query) override;
6868
6969 QVariantMap customizations() const override;
7070
tests/mocks/Unity/fake_scopes.cpp+6
@@ -46,6 +46,7 @@ void Scopes::updateScopes()
4646 addScope(new Scope("MockScope2", "Music", false, this));
4747 addScope(new Scope("clickscope", "Apps", true, this));
4848 addScope(new Scope("MockScope5", "Videos", true, this));
49+ addScope(new Scope("SingleCategoryScope", "Single", true, this, 1));
4950
5051 if (!m_loaded) {
5152 m_loaded = true;
@@ -124,6 +125,11 @@ bool Scopes::loaded() const
124125 return m_loaded;
125126}
126127
128+unity::shell::scopes::ScopeInterface* Scopes::overviewScope() const
129+{
130+ return nullptr;
131+}
132+
127133void Scopes::addScope(Scope* scope)
128134{
129135 int index = rowCount();
tests/mocks/Unity/fake_scopes.h+1
@@ -50,6 +50,7 @@ public:
5050 QModelIndex parent ( const QModelIndex & index ) const;
5151
5252 bool loaded() const override;
53+ unity::shell::scopes::ScopeInterface* overviewScope() const override;
5354
5455private Q_SLOTS:
5556 void updateScopes();
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+63−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,73 @@ 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+ 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;
56+ 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+ }
6163 }
62− }
63− }
64− }
64+ }
6565readonly property int headerHeight: titleLabel.height;
6666Label {
67− id: titleLabel;
68− objectName: "titleLabel";
69− anchors { right: parent.right;left: parent.left;
67+ id: titleLabel;
68+ objectName: "titleLabel";
69+ anchors { right: parent.right;
70+rightMargin: units.gu(1);
71+left: parent.left;
7072top: artShapeHolder.bottom;
7173 topMargin: units.gu(1);
7274leftMargin: 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− }
75+ }
76+ elide: Text.ElideRight;
77+ fontSize: "small";
78+ wrapMode: Text.Wrap;
79+ maximumLineCount: 2;
80+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
81+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
82+ visible: showHeader ;
83+ text: root.title;
84+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
85+ horizontalAlignment: root.headerAlignment;
86+ }
8587implicitHeight: titleLabel.y + titleLabel.height + units.gu(1);
8688}
tests/plugins/Dash/cardcreator/2.res+94−91
@@ -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,107 @@ 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−]
115−}
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+ }
116119implicitHeight: row.y + row.height + units.gu(1);
117120}
tests/plugins/Dash/cardcreator/3.res+77−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,92 @@ 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+ 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;
56+ 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+ }
6163 }
62− }
63− }
64− }
64+ }
6565readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
6666Label {
67− id: titleLabel;
68− objectName: "titleLabel";
69− anchors { right: parent.right;left: parent.left;
67+ id: titleLabel;
68+ objectName: "titleLabel";
69+ anchors { right: parent.right;
70+rightMargin: units.gu(1);
71+left: parent.left;
7072top: artShapeHolder.bottom;
7173 topMargin: units.gu(1);
7274leftMargin: 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− }
75+ }
9476 elide: Text.ElideRight;
9577 fontSize: "small";
78+ wrapMode: Text.Wrap;
79+ maximumLineCount: 2;
9680 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;
81+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
82+ visible: showHeader ;
83+ text: root.title;
84+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
10185 horizontalAlignment: root.headerAlignment;
10286 }
87+Label {
88+ id: subtitleLabel;
89+ objectName: "subtitleLabel";
90+ anchors { left: titleLabel.left;
91+ leftMargin: titleLabel.leftMargin;
92+ right: titleLabel.right;
93+ rightMargin: titleLabel.rightMargin;
94+ top: titleLabel.bottom;
95+ topMargin: units.dp(2);
96+ }
97+ elide: Text.ElideRight;
98+ fontSize: "small";
99+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
100+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
101+ visible: titleLabel.visible && titleLabel.text;
102+ text: cardData && cardData["subtitle"] || "";
103+ font.weight: Font.Light;
104+ horizontalAlignment: root.headerAlignment;
105+ }
103106implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
104107}
tests/plugins/Dash/cardcreator/5.res+119−117
@@ -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,132 @@ 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+ 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;
56+ 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+ }
6163 }
62− }
63− }
64− }
64+ }
6565Loader {
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− }
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+ }
105105readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
106106Label {
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− }
107+ id: titleLabel;
108+ objectName: "titleLabel";
109+ anchors { left: parent.left;
110+ leftMargin: units.gu(1);
111+ right: parent.right;
112+ rightMargin: units.gu(1);
113+ top: overlayLoader.top;
114+ topMargin: units.gu(1);
115+ }
135116 elide: Text.ElideRight;
136117 fontSize: "small";
118+ wrapMode: Text.Wrap;
119+ maximumLineCount: 2;
137120 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
138121 color: "white";
139− visible: titleLabel.visible && titleLabel.text;
140− text: cardData && cardData["subtitle"] || "";
141− font.weight: Font.Light;
122+ visible: showHeader && overlayLoader.active;
123+ text: root.title;
124+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
142125 horizontalAlignment: root.headerAlignment;
143126 }
127+Label {
128+ id: subtitleLabel;
129+ objectName: "subtitleLabel";
130+ anchors { left: titleLabel.left;
131+ leftMargin: titleLabel.leftMargin;
132+ right: titleLabel.right;
133+ rightMargin: titleLabel.rightMargin;
134+ top: titleLabel.bottom;
135+ topMargin: units.dp(2);
136+ }
137+ elide: Text.ElideRight;
138+ fontSize: "small";
139+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
140+ color: "white";
141+ visible: titleLabel.visible && titleLabel.text;
142+ text: cardData && cardData["subtitle"] || "";
143+ font.weight: Font.Light;
144+ horizontalAlignment: root.headerAlignment;
145+ }
144146implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
145147}
tests/plugins/Dash/cardcreator/7.resnew file+128
@@ -0,0 +1,128 @@
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+implicitHeight: row.y + row.height + units.gu(1);
128+}
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,"fill-mode":"crop"},"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+9−1
@@ -19,6 +19,7 @@
1919#include <QQuickItem>
2020#include <QQuickView>
2121#include <QtTestGui>
22+#include <QTemporaryFile>
2223
2324class CardCreatorTest : public QObject
2425{
@@ -74,7 +75,14 @@ private Q_SLOTS:
7475 QVERIFY(testResultFile.open(QIODevice::ReadOnly));
7576 QTextStream ts2(&testResultFile);
7677 const QString expectedResult = ts2.readAll();
77− QCOMPARE(cardStringResult.toString().simplified(), expectedResult.simplified());
78+ const QString executedResult = cardStringResult.toString();
79+ // Record failed results to /tmp
80+ QTemporaryFile tmpFile(QDir::tempPath() + QDir::separator() + "testCardCreatorFailedResultXXXXXX");
81+ tmpFile.open();
82+ tmpFile.setAutoRemove(false);
83+ tmpFile.write(executedResult.toUtf8().constData());
84+ QCOMPARE(executedResult.simplified(), expectedResult.simplified());
85+ tmpFile.setAutoRemove(true); // Remove the result if it passed
7886
7987 QVariant createCardComponentResult;
8088 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+27−2
@@ -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() {
@@ -147,5 +147,30 @@ Rectangle {
147147 tool.style = testCase.styles[data.index];
148148 compare(tool.headerLogo, data.headerLogo, "Header logo was incorrect.");
149149 }
150+
151+ function test_headerForeground_data() {
152+ return [
153+ { tag: "default", index: 0, headerForeground: "grey" },
154+ { tag: "black", index: 2, headerForeground: "black" },
155+ ];
156+ }
157+
158+ function test_headerForeground(data) {
159+ tool.style = testCase.styles[data.index];
160+ verify(Qt.colorEqual(tool.headerForeground, data.headerForeground),
161+ "Header foreground not equal: %1 != %2".arg(tool.headerForeground).arg(data.headerForeground));
162+ }
163+
164+ function test_headerBackground_data() {
165+ return [
166+ { tag: "default", index: 0, headerBackground: "" },
167+ { tag: "black", index: 3, headerBackground: "gradient:///white/blue" },
168+ ];
169+ }
170+
171+ function test_headerBackground(data) {
172+ tool.style = testCase.styles[data.index];
173+ compare(tool.headerBackground, data.headerBackground, "Header background was incorrect.");
174+ }
150175 }
151176}
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+4−5
@@ -19,12 +19,12 @@ set(qmltest_DEFAULT_TARGETS qmluitests)
1919set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
2020set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
2121
22−add_qml_test(. Shell IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks
23− ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
22+add_qml_test(. Shell ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
23+add_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)
@@ -40,7 +40,6 @@ add_qml_test(Dash Card)
4040add_qml_benchmark(Dash CardBenchmark 1000)
4141add_qml_test(Dash CardTool)
4242add_qml_test(Dash GenericScopeView)
43−add_qml_test(Dash/Apps RunningApplicationsGrid)
4443add_qml_test(Dash/Previews Preview)
4544add_qml_test(Dash/Previews PreviewActions)
4645add_qml_test(Dash/Previews PreviewAudioPlayback)
@@ -75,4 +74,4 @@ add_qml_test(Panel/Indicators DefaultIndicatorPage ENVIRONMENT "LD_LIBRARY_PATH=
7574# These MenuItemFactory tests need the test/mocks/ to come before plugins/
7675add_qml_test(Panel/Indicators MenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
7776add_qml_test(Panel/Indicators MessageMenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
78−add_qml_test(Stages PhoneStage)
77+add_qml_test(Stages PhoneStage ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
tests/qmltests/Components/tst_Background.qmlnew file+90
@@ -0,0 +1,90 @@
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 QtTest 1.0
19+import Unity.Test 0.1
20+
21+import "../../../qml/Components"
22+
23+Rectangle {
24+ width: units.gu(40)
25+ height: units.gu(71)
26+
27+ Background {
28+ id: background
29+ }
30+
31+ UnityTestCase {
32+ id: testCase
33+ name: "Background"
34+ when: windowShown
35+
36+ SignalSpy {
37+ id: loadedSpy
38+ target: background
39+ signalName: "loaded"
40+ }
41+
42+ function cleanup() {
43+ background.style = "";
44+ loadedSpy.clear();
45+ }
46+
47+ function test_style_data() {
48+ return [
49+ { tag: "empty", style: "" },
50+ { tag: "solid", style: "color:///black" },
51+ { tag: "gradient", style: "gradient:///black/red" },
52+ { tag: "image", style: "/some/path" },
53+ ];
54+ }
55+
56+ function test_style(data) {
57+ background.style = data.style;
58+ expectFail("empty", "Empty style should not create a background.");
59+ loadedSpy.wait();
60+ compare(background.item.objectName, data.tag, "Background should be %1".arg(data.style));
61+ }
62+
63+ function test_solid() {
64+ background.style = "color:///black";
65+ loadedSpy.wait();
66+
67+ verify(Qt.colorEqual(background.item.color, "black"),
68+ "Solid color not equal: %1 != black".arg(background.item.color));
69+ }
70+
71+ function test_gradient() {
72+ background.style = "gradient:///black/red";
73+ loadedSpy.wait();
74+
75+ var stops = background.item.gradient.stops;
76+
77+ verify(Qt.colorEqual(stops[0].color, "black"),
78+ "Top gradient color not equal: %1 != black".arg(stops[0].color));
79+ verify(Qt.colorEqual(stops[1].color, "red"),
80+ "Bottom gradient color not equal: %1 != black".arg(stops[1].color));
81+ }
82+
83+ function test_image() {
84+ background.style = "/some/path";
85+ loadedSpy.wait();
86+
87+ compare(background.item.source, Qt.resolvedUrl("/some/path"), "Image path is incorrect.");
88+ }
89+ }
90+}
tests/qmltests/Components/tst_FilterGrid.qmldeleted−190
@@ -1,190 +0,0 @@
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 "../../../qml/Components"
20−import Ubuntu.Components.ListItems 0.1 as ListItem
21−import Ubuntu.Components 0.1
22−import Unity.Test 0.1 as UT
23−import Utils 0.1
24−
25−/*
26− You should see 6 green squares (from "A" to "F") and a button "View all (12)".
27− Once you press that button other 6 green squares (from "G" to "L") should show up.
28−*/
29−Rectangle {
30− width: gridRect.width + controls.width
31− height: units.gu(50)
32− color: "white"
33−
34− Column {
35− id: controls
36− width: units.gu(30)
37− height: parent.height
38− anchors.top: parent.top
39− anchors.right: parent.right
40− ListItem.ValueSelector {
41− id: collapsedRowCountSelector
42− text: "collapsedRowCount"
43− values: [1,2,3,4]
44− selectedIndex: 1
45− }
46− Row {
47− spacing: units.gu(1)
48− Label { anchors.verticalCenter: parent.verticalCenter
49− text: "Filter" }
50− CheckBox {
51− id: filterCheckBox
52− checked: true
53− onCheckedChanged: filterGrid.setFilter(checked, false /*animate*/)
54− }
55− }
56− }
57−
58− ListModel {
59− id: fakeModel
60− ListElement { name: "A" }
61− ListElement { name: "B" }
62− ListElement { name: "C" }
63− ListElement { name: "D" }
64− ListElement { name: "E" }
65− ListElement { name: "F" }
66− ListElement { name: "G" }
67− ListElement { name: "H" }
68− ListElement { name: "I" }
69− ListElement { name: "J" }
70− ListElement { name: "K" }
71− ListElement { name: "L" }
72− }
73−
74− ListModel {
75− id: fakeModelTwoItems
76− ListElement { name: "A" }
77− ListElement { name: "B" }
78− }
79−
80− ListModel {
81− id: fakeModelFourItems
82− ListElement { name: "A" }
83− ListElement { name: "B" }
84− ListElement { name: "C" }
85− ListElement { name: "D" }
86− }
87−
88− Rectangle {
89− id: gridRect
90− width: units.gu(30)
91− height: parent.height
92− color: "grey"
93− anchors.top: parent.top
94− anchors.left: parent.left
95−
96− FilterGrid {
97− id: filterGrid
98− anchors.fill: parent
99− model: fakeModel
100− maximumNumberOfColumns: 3
101− collapsedRowCount:
102− collapsedRowCountSelector.values[collapsedRowCountSelector.selectedIndex]
103− minimumHorizontalSpacing: units.gu(1)
104− delegateWidth: units.gu(6)
105− delegateHeight: units.gu(6)
106− verticalSpacing: units.gu(1)
107−
108− delegate: Rectangle {
109− // So that it can be identified by countVisibleDelegates()
110− property bool isGridDelegate: true
111−
112− color: "green"
113− width: units.gu(6)
114− height: units.gu(6)
115− Text {
116− anchors.centerIn: parent
117− text: name
118− }
119− }
120− }
121− }
122−
123− UT.UnityTestCase {
124− name: "FilterGrid"
125− when: windowShown
126−
127− function init() {
128− filterGrid.model = fakeModel
129− }
130−
131− function cleanup() {
132− filterCheckBox.checked = true
133− collapsedRowCountSelector.selectedIndex = 1
134− }
135−
136− function test_turningFilterOffShowsAllElements() {
137− tryCompareFunction(countVisibleDelegates, 6)
138−
139− filterCheckBox.checked = false
140−
141− tryCompareFunction(countVisibleDelegates, 12)
142− }
143−
144− function test_collapsedRowCount() {
145− for (var i = 0; i < 4; ++i) {
146− collapsedRowCountSelector.selectedIndex = i
147− // We have 3 elements per row.
148− // row count == index + 1
149− tryCompareFunction(countVisibleDelegates, 3*(i+1))
150− }
151− }
152−
153− function test_modelSizeAffectsCollapsedRowCount_data() {
154− return [
155− { tag: "2 items, collapsedRows 1", model: fakeModelTwoItems, collapsedRowCountIndex: 0,
156− rowsWhenCollapsed: 1, visibleDelegates: 2 },
157− { tag: "2 items, collapsedRows 2", model: fakeModelTwoItems, collapsedRowCountIndex: 1,
158− rowsWhenCollapsed: 1, visibleDelegates: 2 },
159− { tag: "4 items, collapsedRows 1", model: fakeModelFourItems, collapsedRowCountIndex: 0,
160− rowsWhenCollapsed: 1, visibleDelegates: 3 },
161− { tag: "4 items, collapsedRows 2", model: fakeModelFourItems, collapsedRowCountIndex: 1,
162− rowsWhenCollapsed: 2, visibleDelegates: 4 },
163− ]
164− }
165−
166− function test_modelSizeAffectsCollapsedRowCount(data) {
167− filterGrid.model = data.model
168− collapsedRowCountSelector.selectedIndex = data.collapsedRowCountIndex
169−
170− tryCompare(filterGrid, "rowsWhenCollapsed", data.rowsWhenCollapsed)
171− tryCompareFunction(countVisibleDelegates, data.visibleDelegates)
172− }
173−
174− function countVisibleDelegates() {
175− return __countVisibleDelegates(filterGrid.visibleChildren, 0)
176− }
177−
178− function __countVisibleDelegates(objList, total) {
179− for (var i = 0; i < objList.length; ++i) {
180− var child = objList[i];
181− if (child.isGridDelegate !== undefined) {
182− ++total;
183− } else {
184− total = __countVisibleDelegates(child.visibleChildren, total)
185− }
186− }
187− return total
188− }
189− }
190−}
tests/qmltests/Components/tst_PageHeader.qml+36−6
@@ -36,6 +36,16 @@ Item {
3636
3737 function init() {
3838 searchEnabled = true;
39+
40+ // Reset to initial state
41+ pageHeader.searchQuery = "";
42+ pageHeader.closePopup();
43+ pageHeader.searchHistory.clear();
44+
45+ // Check initial state
46+ var headerContainer = findChild(pageHeader, "headerContainer");
47+ tryCompareFunction(function() { return headerContainer.popover === null; }, true);
48+ compare(pageHeader.searchHistory.count, 0);
3949 }
4050
4151 function test_search_disabled() {
@@ -80,9 +90,6 @@ Item {
8090 }
8191
8292 function test_history() {
83− pageHeader.searchHistory.clear()
84− compare(pageHeader.searchHistory.count, 0)
85−
8693 pageHeader.triggerSearch()
8794 typeString("humppa1")
8895 pageHeader.resetSearch()
@@ -166,16 +173,26 @@ Item {
166173 tryCompareFunction(function() { return headerContainer.popover !== null; }, true);
167174
168175 tryCompare(headerContainer.popover, "visible", true);
176+
177+ var searchTextField = findChild(pageHeader, "searchTextField");
178+ compare(searchTextField.focus, true);
179+
180+ var recentSearches = findChild(headerContainer.popover, "recentSearches");
181+ mouseClick(recentSearches.itemAt(0), 0, 0);
182+
183+ compare(pageHeader.searchQuery, "Search2");
184+ tryCompareFunction(function() { return headerContainer.popover === null; }, true);
185+ compare(searchTextField.focus, false);
169186 }
170187
171− function test_tap_outside_closes_popup_data() {
188+ function test_popup_closing_data() {
172189 return [
173190 { tag: "with search text", searchText: "foobar", hideSearch: false },
174191 { tag: "without search text", searchText: "", hideSearch: true }
175192 ];
176193 }
177194
178− function test_tap_outside_closes_popup(data) {
195+ function test_popup_closing(data) {
179196 searchEnabled = true;
180197 pageHeader.searchHistory.clear();
181198
@@ -191,13 +208,26 @@ Item {
191208
192209 pageHeader.searchQuery = data.searchText;
193210
194− mouseClick(root, root.width / 2, root.height - 1);
211+ if (data.searchText == "") {
212+ // When the text is empty the user can also close the
213+ // popup by clicking outside the header instead of by starting a search
214+ mouseClick(root, root.width / 2, root.height - 1);
215+ }
195216
196217 tryCompare(headerContainer, "showSearch", !data.hideSearch);
197218 tryCompareFunction(function() { return headerContainer.popover === null; }, true);
198219
199220 pageHeader.resetSearch();
200221 }
222+
223+ function test_search_change_shows_search() {
224+ var headerContainer = findChild(pageHeader, "headerContainer");
225+ compare(headerContainer.showSearch, false);
226+ compare(searchQuery, "");
227+
228+ searchQuery = "H";
229+ compare(headerContainer.showSearch, true);
230+ }
201231 }
202232
203233 Column {
tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qmldeleted−196
@@ -1,196 +0,0 @@
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 "../../../../qml/Dash/Apps"
20−import Unity.Test 0.1 as UT
21−import Unity.Application 0.1
22−
23−// Using Rectangle to have an opaque surface because AppManager paints app surfaces behind it.
24−Rectangle {
25− width: units.gu(50)
26− height: units.gu(40)
27−
28− function resetRunningApplications() {
29− while (ApplicationManager.count > 0) {
30− ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
31− }
32−
33− ApplicationManager.startApplication("dialer-app");
34− ApplicationManager.startApplication("webbrowser-app");
35− }
36−
37− Component.onCompleted: {
38− resetRunningApplications()
39− }
40−
41− // The component under test
42− RunningApplicationsGrid {
43− id: runningApplicationsGrid
44− anchors.fill: parent
45− model: ApplicationManager
46− }
47−
48− UT.UnityTestCase {
49− name: "RunningApplicationsGrid"
50− when: windowShown
51−
52− function init() {
53− runningApplicationsGrid.terminationModeEnabled = false
54− resetRunningApplications()
55− }
56−
57− property var browserTile
58− property var phoneTile
59−
60− property var isBrowserLongPressed: false
61− function onBrowserLongPressed() {isBrowserLongPressed = true}
62−
63− property var isPhoneLongPressed: false
64− function onPhoneLongPressed() {isPhoneLongPressed = true}
65−
66− // Tiles should go to termination mode when any one of them is long-pressed.
67− // Long-pressing when they're in termination mode brings them back to activation mode
68− function test_enterTerminationMode() {
69− browserTile = findChild(runningApplicationsGrid, "runningAppTile Browser")
70− verify(browserTile != undefined)
71− browserTile.onPressAndHold.connect(onBrowserLongPressed)
72−
73− phoneTile = findChild(runningApplicationsGrid, "runningAppTile Dialer")
74− verify(phoneTile != undefined)
75− phoneTile.onPressAndHold.connect(onPhoneLongPressed)
76−
77− compare(browserTile.terminationModeEnabled, false)
78− compare(phoneTile.terminationModeEnabled, false)
79− compare(runningApplicationsGrid.terminationModeEnabled, false)
80−
81− isBrowserLongPressed = false
82− mousePress(browserTile, browserTile.width/2, browserTile.height/2)
83− tryCompareFunction(checkSwitchToTerminationModeAfterLongPress, true)
84−
85− mouseRelease(browserTile, browserTile.width/2, browserTile.height/2)
86−
87− compare(browserTile.terminationModeEnabled, true)
88− compare(phoneTile.terminationModeEnabled, true)
89− compare(runningApplicationsGrid.terminationModeEnabled, true)
90−
91− isPhoneLongPressed = false
92− mousePress(phoneTile, phoneTile.width/2, phoneTile.height/2)
93− tryCompareFunction(checkSwitchToActivationModeAfterLongPress, true)
94−
95− mouseRelease(phoneTile, phoneTile.width/2, phoneTile.height/2)
96−
97− compare(browserTile.terminationModeEnabled, false)
98− compare(phoneTile.terminationModeEnabled, false)
99− compare(runningApplicationsGrid.terminationModeEnabled, false)
100−
101− browserTile.onPressAndHold.disconnect(onBrowserLongPressed)
102− phoneTile.onPressAndHold.disconnect(onPhoneLongPressed)
103− }
104−
105− // Checks that components swicth to termination mode after (and only after) a long
106− // press happens on Browser tile.
107− function checkSwitchToTerminationModeAfterLongPress() {
108− compare(browserTile.terminationModeEnabled, isBrowserLongPressed)
109− compare(phoneTile.terminationModeEnabled, isBrowserLongPressed)
110− compare(runningApplicationsGrid.terminationModeEnabled, isBrowserLongPressed)
111−
112− return isBrowserLongPressed &&
113− browserTile.terminationModeEnabled &&
114− phoneTile.terminationModeEnabled &&
115− runningApplicationsGrid.terminationModeEnabled
116− }
117−
118− // Checks that components swicth to activation mode after (and only after) a long
119− // press happens on Phone tile.
120− function checkSwitchToActivationModeAfterLongPress() {
121− compare(browserTile.terminationModeEnabled, !isPhoneLongPressed)
122− compare(phoneTile.terminationModeEnabled, !isPhoneLongPressed)
123− compare(runningApplicationsGrid.terminationModeEnabled, !isPhoneLongPressed)
124−
125− return isPhoneLongPressed &&
126− !browserTile.terminationModeEnabled &&
127− !phoneTile.terminationModeEnabled &&
128− !runningApplicationsGrid.terminationModeEnabled
129− }
130−
131− // While on termination mode, clicking a running application tile, outside of
132− // the close icon should do nothing
133− function test_clickTileNotClose() {
134− runningApplicationsGrid.terminationModeEnabled = true
135−
136− var browserTile = findChild(runningApplicationsGrid, "runningAppTile Browser")
137− verify(browserTile != undefined)
138−
139− verify(ApplicationManager.findApplication("webbrowser-app") !== null)
140−
141− mouseClick(browserTile, browserTile.width/2, browserTile.height/2)
142−
143− verify(ApplicationManager.findApplication("webbrowser-app") !== null)
144−
145− // The tile for the Browser app should stay there
146− tryCompareFunction(checkBrowserTileExists, true)
147− }
148−
149− // While in termination mode, clicking on a running application tile's close icon
150− // causes the corresponding application to be terminated
151− function test_clickCloseIconToTerminateApp() {
152− runningApplicationsGrid.terminationModeEnabled = true
153−
154− var browserTile = findChild(runningApplicationsGrid, "runningAppTile Browser")
155− var browserTileCloseButton = findChild(runningApplicationsGrid, "closeIcon Browser")
156−
157− verify(browserTile != undefined)
158− verify(browserTileCloseButton != undefined)
159− verify(ApplicationManager.findApplication("webbrowser-app") !== 0)
160−
161− mouseClick(browserTileCloseButton, browserTileCloseButton.width/2, browserTileCloseButton.height/2)
162− wait(0) // spin event loop to start any pending animation
163−
164− verify(ApplicationManager.findApplication("webbrowser-app") === null)
165−
166− // The tile for the Browser app should eventually vanish since the
167− // application has been terminated.
168− tryCompareFunction(checkBrowserTileExists, false)
169− }
170−
171− function checkBrowserTileExists() {
172− return findChild(runningApplicationsGrid, "runningAppTile Browser")
173− != undefined
174− }
175−
176− // While in termination mode, if you click outside any of the tiles, the
177− // termination mode is disabled (i.e. we switch back to activation mode).
178− function test_clickOutsideTilesDisablesTerminationMode() {
179− runningApplicationsGrid.terminationModeEnabled = true
180−
181− var browserTile = findChild(runningApplicationsGrid, "runningAppTile Browser")
182− verify(browserTile != undefined)
183−
184− verify(runningApplicationsGrid.terminationModeEnabled);
185−
186− // Click on the bottom right corner of the grid, where there's no
187− // RunningApplicationTile lying around
188− mouseClick(runningApplicationsGrid,
189− runningApplicationsGrid.width - 1, runningApplicationsGrid.height - 1);
190−
191− wait(0) // spin event loop to ensure that any pending signal emission went through
192−
193− verify(!runningApplicationsGrid.terminationModeEnabled);
194− }
195− }
196−}
tests/qmltests/Dash/CardHelpers.js+5−3
@@ -16,7 +16,7 @@
1616
1717.pragma library
1818
19−var components = ["title", "art", "subtitle", "mascot", "emblem", "old-price", "price", "alt-price", "rating", "alt-rating", "summary"]
19+var components = ["title", "art", "subtitle", "mascot", "emblem", "old-price", "price", "alt-price", "rating", "alt-rating", "summary", "attributes"]
2020
2121var defaultLayout = ' \
2222{ \
@@ -48,7 +48,8 @@ var defaultLayout = ' \
4848 "empty": "image://theme/rating-star-empty" \
4949 }, \
5050 "alt-rating": null, \
51− "summary": null \
51+ "summary": null, \
52+ "attributes": { "max-count": 2 } \
5253 }, \
5354 "resources": {} \
5455}'
@@ -59,7 +60,8 @@ var fullMapping = ' \
5960 "art": "art", \
6061 "subtitle": "subtitle", \
6162 "mascot": "mascot", \
62− "summary": "summary" \
63+ "summary": "summary", \
64+ "attributes": "attributes" \
6365}'
6466
6567
tests/qmltests/Dash/tst_Card.qml+4−2
@@ -33,7 +33,8 @@ Rectangle {
3333 "mascot": "../../../tests/qmltests/Dash/artwork/avatar.png",
3434 "title": "foo",
3535 "subtitle": "bar",
36− "summary": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
36+ "summary": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
37+ "attributes": [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"}]
3738 }'
3839
3940 property var cardsModel: [
@@ -110,6 +111,7 @@ Rectangle {
110111 anchors { top: parent.top; left: parent.left; margins: units.gu(1) }
111112
112113 sourceComponent: cardTool.cardComponent
114+ clip: true
113115 onLoaded: {
114116 item.template = Qt.binding(function() { return cardTool.template; });
115117 item.components = Qt.binding(function() { return cardTool.components; });
@@ -359,7 +361,7 @@ Rectangle {
359361
360362 waitForRendering(card);
361363
362− tryCompareFunction(function() { return testCase.summary.y === data.top() }, true);
364+ tryCompareFunction(function() { return art.height > 0 && testCase.summary.y === data.top() }, true);
363365 }
364366
365367 function test_art_visibility() {
tests/qmltests/Dash/tst_Dash.qml+20−1
@@ -59,6 +59,7 @@ Item {
5959 verify(dashContentList != undefined);
6060 tryCompare(dashContentList, "count", 0);
6161 scopes.load();
62+ tryCompare(dashContentList, "currentIndex", 0);
6263 }
6364
6465 function get_scope_data() {
@@ -86,10 +87,28 @@ Item {
8687 tryCompare(dashContentList, "count", 0);
8788 scopes.load();
8889 tryCompare(scopes, "loaded", true);
89− tryCompare(dashContentList, "count", 3);
90+ tryCompare(dashContentList, "count", 4);
9091
9192 verify(dashContentList != undefined);
9293 tryCompare(dashContentList, "currentIndex", data.visualIndex);
9394 }
95+
96+ function test_setCurrentScope() {
97+ var dashContentList = findChild(dash, "dashContentList");
98+ var startX = dash.width - units.gu(1);
99+ var startY = dash.height / 2;
100+ var stopX = units.gu(1)
101+ var stopY = startY;
102+ var retry = 0;
103+ while (dashContentList.currentIndex != 2 && retry <= 5) {
104+ mouseFlick(dash, startX, startY, stopX, stopY)
105+ waitForRendering(dashContentList)
106+ retry++;
107+ }
108+ compare(dashContentList.currentIndex, 2);
109+ var dashCommunicatorService = findInvisibleChild(dash, "dashCommunicatorService");
110+ dashCommunicatorService.mockSetCurrentScope("clickscope", true, true);
111+ tryCompare(dashContentList, "currentIndex", 1)
112+ }
94113 }
95114}
tests/qmltests/Dash/tst_DashContent.qml+15−6
@@ -61,6 +61,11 @@ Item {
6161 signalName: "movementStarted"
6262 }
6363
64+ SignalSpy {
65+ id: loadedSpy
66+ signalName: "loaded"
67+ }
68+
6469 UT.UnityTestCase {
6570 name: "DashContent"
6671 when: scopesModel.loaded && windowShown
@@ -78,6 +83,7 @@ Item {
7883
7984 function cleanup() {
8085 movementStartedSpy.clear();
86+ loadedSpy.clear();
8187 dashContent.visible = true;
8288
8389 var dashContentList = findChild(dashContent, "dashContentList");
@@ -116,10 +122,11 @@ Item {
116122
117123 function test_show_header_on_list_movement() {
118124 var dashContentList = findChild(dashContent, "dashContentList");
119− verify(dashContentList != undefined);
120− var categoryListView = findChild(dashContentList, "categoryListView");
121− verify(categoryListView != undefined);
125+ verify(dashContentList !== null);
126+ var scope = findChild(dashContent, "MockScope1 loader");
127+ waitForRendering(scope);
122128
129+ var categoryListView = findChild(scope, "categoryListView");
123130 waitForRendering(categoryListView);
124131
125132 categoryListView.contentY = units.gu(15);
@@ -133,10 +140,12 @@ Item {
133140
134141 function test_set_current_scope_reset() {
135142 var dashContentList = findChild(dashContent, "dashContentList");
136− verify(dashContentList != undefined);
137− var categoryListView = findChild(dashContentList, "categoryListView");
138− verify(categoryListView != undefined);
143+ verify(dashContentList, "Couldn't find dashContentList");
144+ var scope = findChild(dashContent, "MockScope1 loader");
139145
146+ tryCompare(scope, "status", Loader.Ready);
147+
148+ var categoryListView = findChild(dashContentList, "categoryListView");
140149 categoryListView.contentY = units.gu(10);
141150
142151 compare(dashContentList.currentItem.item.objectName, "MockScope1")
tests/qmltests/Dash/tst_GenericScopeView.qml+137−49
@@ -39,6 +39,10 @@ Item {
3939 id: scopes
4040 }
4141
42+ SignalSpy {
43+ id: spy
44+ }
45+
4246 property Item applicationManager: Item {
4347 signal sideStageFocusedApplicationChanged()
4448 signal mainStageFocusedApplicationChanged()
@@ -54,12 +58,20 @@ Item {
5458 when: scopes.loaded && windowShown
5559
5660 property Item previewListView: findChild(genericScopeView, "previewListView")
61+ property Item header: findChild(genericScopeView, "scopePageHeader")
5762
5863 function init() {
5964 genericScopeView.scope = scopes.getScope(1)
6065 shell.width = units.gu(120)
6166 genericScopeView.categoryView.positionAtBeginning();
62− tryCompare(genericScopeView.categoryView, "contentY", 0)
67+ waitForRendering(genericScopeView.categoryView);
68+ }
69+
70+ function cleanup() {
71+ genericScopeView.scope = null;
72+ spy.clear();
73+ spy.target = null;
74+ spy.signalName = "";
6375 }
6476
6577 function test_isActive() {
@@ -104,90 +116,146 @@ Item {
104116 tryCompare(genericScopeView.scope, "searchQuery", "test")
105117 }
106118
107− function test_filter_expand_collapse() {
108− // wait for the item to be there
109− waitForRendering(genericScopeView);
119+ function test_expand_collapse() {
110120 tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader0") != null; }, true);
111121
112− var header = findChild(genericScopeView, "dashSectionHeader0")
113122 var category = findChild(genericScopeView, "dashCategory0")
123+ var seeAll = findChild(category, "seeAll")
114124
115− waitForRendering(header);
125+ waitForRendering(seeAll);
116126 verify(category.expandable);
117− verify(category.filtered);
127+ verify(!category.expanded);
118128
119129 var initialHeight = category.height;
120− var middleHeight;
121− mouseClick(header, header.width / 2, header.height / 2);
122− tryCompareFunction(function() { middleHeight = category.height; return category.height > initialHeight; }, true);
123− tryCompare(category, "filtered", false);
124− tryCompareFunction(function() { return category.height > middleHeight; }, true);
130+ mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
131+ verify(category.expanded);
132+ tryCompareFunction(function() { return category.height > initialHeight; }, true);
125133
126− mouseClick(header, header.width / 2, header.height / 2);
127− verify(category.expandable);
128− tryCompare(category, "filtered", true);
134+ mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
135+ verify(!category.expanded);
129136 }
130137
131− function test_filter_expand_expand_collapse() {
138+ function test_expand_expand_collapse() {
132139 // wait for the item to be there
133140 tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader2") != null; }, true);
134141
135142 var categoryListView = findChild(genericScopeView, "categoryListView");
136143 categoryListView.contentY = categoryListView.height;
137144
138− var header2 = findChild(genericScopeView, "dashSectionHeader2")
139145 var category2 = findChild(genericScopeView, "dashCategory2")
140− var category2FilterGrid = category2.children[1].children[2];
141− verify(UT.Util.isInstanceOf(category2FilterGrid, "CardFilterGrid"));
146+ var seeAll2 = findChild(category2, "seeAll")
142147
143− waitForRendering(header2);
148+ waitForRendering(seeAll2);
144149 verify(category2.expandable);
145− verify(category2.filtered);
150+ verify(!category2.expanded);
146151
147− mouseClick(header2, header2.width / 2, header2.height / 2);
148− tryCompare(category2, "filtered", false);
149− tryCompare(category2FilterGrid, "filtered", false);
152+ mouseClick(seeAll2, seeAll2.width / 2, seeAll2.height / 2);
153+ tryCompare(category2, "expanded", true);
150154
151155 categoryListView.positionAtBeginning();
152156
153− var header0 = findChild(genericScopeView, "dashSectionHeader0")
154157 var category0 = findChild(genericScopeView, "dashCategory0")
155− mouseClick(header0, header0.width / 2, header0.height / 2);
156− tryCompare(category0, "filtered", false);
157− tryCompare(category2, "filtered", true);
158− tryCompare(category2FilterGrid, "filtered", true);
159− mouseClick(header0, header0.width / 2, header0.height / 2);
160− tryCompare(category0, "filtered", true);
161− tryCompare(category2, "filtered", true);
158+ var seeAll0 = findChild(category0, "seeAll")
159+ mouseClick(seeAll0, seeAll0.width / 2, seeAll0.height / 2);
160+ tryCompare(category0, "expanded", true);
161+ tryCompare(category2, "expanded", false);
162+ mouseClick(seeAll0, seeAll0.width / 2, seeAll0.height / 2);
163+ tryCompare(category0, "expanded", false);
164+ tryCompare(category2, "expanded", false);
165+ }
166+
167+ function test_headerLink() {
168+ tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader1") != null; }, true);
169+ var header = findChild(genericScopeView, "dashSectionHeader1");
170+
171+ spy.target = genericScopeView.scope;
172+ spy.signalName = "performQuery";
173+
174+ mouseClick(header, header.width / 2, header.height / 2);
175+
176+ spy.wait();
177+ compare(spy.signalArguments[0][0], genericScopeView.scope.categories.data(1, Categories.RoleHeaderLink));
178+ }
179+
180+ function test_headerLink_disable_expansion() {
181+ var categoryListView = findChild(genericScopeView, "categoryListView");
182+ waitForRendering(categoryListView);
183+
184+ categoryListView.contentY = categoryListView.height * 2;
185+
186+ // wait for the item to be there
187+ tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader4") != null; }, true);
188+
189+ var categoryView = findChild(genericScopeView, "dashCategory4");
190+ verify(categoryView, "Can't find the category view.");
191+
192+ var seeAll = findChild(categoryView, "seeAll");
193+ verify(seeAll, "Can't find the seeAll element");
194+
195+ compare(seeAll.height, 0, "SeeAll should be 0-height.");
196+
197+ openPreview(4, 0);
198+
199+ compare(testCase.previewListView.count, 12, "There should only be 12 items in preview.");
162200 }
163201
164202 function test_narrow_delegate_ranges_expand() {
165− tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") != undefined; }, true);
203+ tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") !== null; }, true);
166204 var category = findChild(genericScopeView, "dashCategory0")
167− tryCompare(category, "filtered", true);
205+ tryCompare(category, "expanded", false);
168206
169207 shell.width = units.gu(20)
170208 var categoryListView = findChild(genericScopeView, "categoryListView");
171209 categoryListView.contentY = units.gu(20);
172− var header0 = findChild(genericScopeView, "dashSectionHeader0")
173− mouseClick(header0, header0.width / 2, header0.height / 2);
174− tryCompare(category, "filtered", false);
210+ var seeAll = findChild(category, "seeAll")
211+ mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
212+ tryCompare(category, "expanded", true);
175213 tryCompareFunction(function() { return category.item.height == genericScopeView.height - category.item.displayMarginBeginning - category.item.displayMarginEnd; }, true);
176− mouseClick(header0, header0.width / 2, header0.height / 2);
177− tryCompare(category, "filtered", true);
214+ mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
215+ tryCompare(category, "expanded", false);
216+ }
217+
218+ function test_forced_category_expansion() {
219+ tryCompareFunction(function() {
220+ mouseFlick(genericScopeView, genericScopeView.width/2, genericScopeView.height,
221+ genericScopeView.width/2, genericScopeView.y)
222+ return findChild(genericScopeView, "dashCategory19") !== null;
223+ }, true);
224+ var category = findChild(genericScopeView, "dashCategory19")
225+ compare(category.expandable, false, "Category with collapsed-rows: 0 should not be expandable");
226+
227+ var grid = findChild(category, "19");
228+ verify(grid, "Could not find the category renderer.");
229+
230+ compare(grid.height, grid.expandedHeight, "Category with collapsed-rows: 0 should always be expanded.");
231+ }
232+
233+ function test_single_category_expansion() {
234+ genericScopeView.scope = scopes.getScope(4);
235+
236+ tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") != undefined; }, true);
237+ var category = findChild(genericScopeView, "dashCategory0")
238+ compare(category.expandable, false, "Only category should not be expandable.");
239+
240+ var grid = findChild(category, "0");
241+ verify(grid, "Could not find the category renderer.");
242+
243+ compare(grid.height, grid.expandedHeight, "Only category should always be expanded");
178244 }
179245
180− function openPreview() {
246+ function openPreview(category, delegate) {
247+ if (category === undefined) category = 0;
248+ if (delegate === undefined) delegate = 0;
181249 tryCompareFunction(function() {
182− var filterGrid = findChild(genericScopeView, "0");
183− if (filterGrid != null) {
184− var tile = findChild(filterGrid, "delegate0");
250+ var cardGrid = findChild(genericScopeView, category);
251+ if (cardGrid != null) {
252+ var tile = findChild(cardGrid, "delegate"+delegate);
185253 return tile != null;
186254 }
187255 return false;
188256 },
189257 true);
190− var tile = findChild(findChild(genericScopeView, "0"), "delegate0");
258+ var tile = findChild(findChild(genericScopeView, category), "delegate"+delegate);
191259 mouseClick(tile, tile.width / 2, tile.height / 2);
192260 tryCompare(testCase.previewListView, "open", true);
193261 tryCompare(testCase.previewListView, "x", 0);
@@ -257,13 +325,33 @@ Item {
257325 closePreview();
258326 }
259327
260− function test_haeder_logo() {
261− genericScopeView.scope = scopes.getScope(3);
328+ function test_header_style_data() {
329+ return [
330+ { tag: "Default", index: 0, foreground: "grey", background: "", logo: "" },
331+ { tag: "Foreground", index: 2, foreground: "yellow", background: "", logo: "" },
332+ { tag: "Logo+Background", index: 3, foreground: "grey", background: "gradient:///lightgrey/grey",
333+ logo: Qt.resolvedUrl("../Components/tst_PageHeader/logo-ubuntu-orange.svg") },
334+ ];
335+ }
262336
263− var image = findChild(genericScopeView, "titleImage");
264− verify(image, "Could not find the title image");
265− compare(image.source, Qt.resolvedUrl("../Components/tst_PageHeader/logo-ubuntu-orange.svg"), "Title image has the wrong source");
337+ function test_header_style(data) {
338+ genericScopeView.scope = scopes.getScope(data.index);
339+ waitForRendering(genericScopeView);
340+ verify(header, "Could not find the header.");
341+
342+ var innerHeader = findChild(header, "innerPageHeader");
343+ verify(innerHeader, "Could not find the inner header");
344+ verify(Qt.colorEqual(innerHeader.textColor, data.foreground),
345+ "Foreground color not equal: %1 != %2".arg(innerHeader.textColor).arg(data.foreground));
266346
347+ var background = findChild(header, "headerBackground");
348+ verify(background, "Could not find the background");
349+ compare(background.style, data.background);
350+
351+ var image = findChild(genericScopeView, "titleImage");
352+ if (data.logo == "") expectFail(data.tag, "Title image should not exist.");
353+ verify(image, "Could not find the title image.");
354+ compare(image.source, data.logo, "Title image has the wrong source");
267355 }
268356 }
269357 }
tests/qmltests/Greeter/tst_Lockscreen.qml+11−5
@@ -18,8 +18,9 @@ import QtQuick 2.0
1818import QtTest 1.0
1919import ".."
2020import "../../../qml/Components"
21−import Ubuntu.Components 0.1
21+import AccountsService 0.1
2222import LightDM 0.1 as LightDM
23+import Ubuntu.Components 0.1
2324import Unity.Test 0.1 as UT
2425
2526Rectangle {
@@ -53,11 +54,16 @@ Rectangle {
5354 }
5455 }
5556
57+ function setUser(username) {
58+ AccountsService.user = username
59+ LightDM.Greeter.authenticate(username)
60+ }
61+
5662 Connections {
5763 target: LightDM.Greeter
5864
5965 onShowPrompt: {
60− if (text.indexOf("PIN") >= 0) {
66+ if (AccountsService.passwordDisplayHint === AccountsService.Numeric) {
6167 pinPadCheckBox.checked = false
6268 } else {
6369 pinPadCheckBox.checked = true
@@ -139,12 +145,12 @@ Rectangle {
139145 Button {
140146 text: "start auth (1234)"
141147 width: parent.width
142− onClicked: LightDM.Greeter.authenticate("has-pin")
148+ onClicked: setUser("has-pin")
143149 }
144150 Button {
145151 text: "start auth (password)"
146152 width: parent.width
147− onClicked: LightDM.Greeter.authenticate("has-password")
153+ onClicked: setUser("has-password")
148154 }
149155
150156 TextField {
@@ -255,7 +261,7 @@ Rectangle {
255261 enteredLabel.text = ""
256262 minPinLengthTextField.text = data.minPinLength
257263 maxPinLengthTextField.text = data.maxPinLength
258− LightDM.Greeter.authenticate(data.username)
264+ setUser(data.username)
259265 waitForLockscreenReady();
260266
261267 var inputField = findChild(lockscreen, "pinentryField")
tests/qmltests/Launcher/tst_Launcher.qml+11−2
@@ -94,9 +94,16 @@ Item {
9494 name: "Launcher"
9595 when: windowShown && initTestCase.completed
9696
97+ function cleanup() {
98+ mouseClick(root, root.width / 2, root.height / 2);
99+ revealer.waitUntilLauncherDisappears();
100+ }
101+
97102 // Drag from the left edge of the screen rightwards and check that the launcher
98103 // appears (as if being dragged by the finger/pointer)
99104 function test_dragLeftEdgeToRevealLauncherAndTapCenterToDismiss() {
105+ revealer.waitUntilLauncherDisappears();
106+
100107 var panel = findChild(launcher, "launcherPanel")
101108 verify(panel != undefined)
102109
@@ -117,10 +124,9 @@ Item {
117124 corresponding desktop file. E.g. clicking on phone icon should yield
118125 launcherApplicationSelected("[...]dialer-app.desktop") */
119126 function test_clickingOnAppIconCausesSignalEmission() {
127+ revealer.dragLauncherIntoView();
120128 launcher.lastSelectedApplication = ""
121129
122− revealer.dragLauncherIntoView()
123−
124130 var listView = findChild(launcher, "launcherListView");
125131 listView.positionViewAtEnd();
126132
@@ -184,6 +190,7 @@ Item {
184190 }
185191
186192 function test_countEmblems() {
193+ revealer.dragLauncherIntoView();
187194 var launcherListView = findChild(launcher, "launcherListView");
188195 for (var i = 0; i < launcherListView.count; ++i) {
189196 var delegate = findChild(launcherListView, "launcherDelegate" + i)
@@ -192,6 +199,7 @@ Item {
192199 }
193200
194201 function test_progressOverlays() {
202+ revealer.dragLauncherIntoView();
195203 var launcherListView = findChild(launcher, "launcherListView");
196204 for (var i = 0; i < launcherListView.count; ++i) {
197205 var delegate = findChild(launcherListView, "launcherDelegate" + i)
@@ -200,6 +208,7 @@ Item {
200208 }
201209
202210 function test_focusedHighlight() {
211+ revealer.dragLauncherIntoView();
203212 var launcherListView = findChild(launcher, "launcherListView");
204213 for (var i = 0; i < launcherListView.count; ++i) {
205214 var delegate = findChild(launcherListView, "launcherDelegate" + i)
tests/qmltests/Panel/tst_ActiveCallHint.qml+1
@@ -95,6 +95,7 @@ Item {
9595 function test_activeHint(data) {
9696 if (data.dialer) {
9797 var application = ApplicationManager.startApplication("dialer-app");
98+ ApplicationManager.focusApplication("dialer-app");
9899 tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app");
99100 tryCompare(application, "state", ApplicationInfo.Running);
100101
tests/qmltests/Stages/tst_PhoneStage.qml+12−58
@@ -33,7 +33,6 @@ Item {
3333 PhoneStage {
3434 id: phoneStage
3535 anchors { fill: parent; rightMargin: units.gu(30) }
36− shown: true
3736 dragAreaWidth: units.gu(2)
3837 }
3938
@@ -45,7 +44,6 @@ Item {
4544
4645 Rectangle {
4746 anchors { fill: parent; leftMargin: phoneStage.width }
48−// color: "blue"
4947
5048 Column {
5149 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
@@ -59,7 +57,10 @@ Item {
5957 }
6058 Button {
6159 anchors { left: parent.left; right: parent.right }
62− text: "Add App"
60+ text: "Remove App"
61+ onClicked: {
62+ ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
63+ }
6364 }
6465 }
6566 }
@@ -74,11 +75,8 @@ Item {
7475 for (var i = 0; i < count; i++) {
7576 var app = ApplicationManager.startApplication(ApplicationManager.availableApplications()[ApplicationManager.count])
7677 tryCompare(app, "state", ApplicationInfoInterface.Running)
77− // Fixme: Right now there is a timeout in the PhoneStage that displays a white splash
78− // screen rectangle when an app starts. This is because we don't yet have a way of
79− // knowing when an app has finished launching. That workaround and this wait() should
80− // go away at some point and the app's state only changing to Running when ready for real.
81−// wait(1000)
78+ var spreadView = findChild(phoneStage, "spreadView");
79+ tryCompare(spreadView, "contentX", -spreadView.shift);
8280 waitForRendering(phoneStage)
8381 }
8482 }
@@ -114,8 +112,6 @@ Item {
114112 true /* beginTouch */, true /* endTouch */, units.gu(10), 50);
115113
116114 tryCompare(ApplicationManager, "focusedApplicationId", activeApp.appId)
117−
118− tryCompare(phoneStage, "painting", false);
119115 }
120116
121117 function test_enterSpread_data() {
@@ -139,7 +135,7 @@ Item {
139135 var startX = phoneStage.width;
140136 var startY = phoneStage.height / 2;
141137 var endY = startY;
142− var endX = spreadView.width - (spreadView.width * spreadView[data.positionMarker]) - data.offset - phoneStage.dragAreaWidth;
138+ var endX = spreadView.width - (spreadView.width * spreadView[data.positionMarker]) - data.offset;
143139
144140 var oldFocusedApp = ApplicationManager.get(0);
145141 var newFocusedApp = ApplicationManager.get(data.newFocusedIndex);
@@ -165,7 +161,6 @@ Item {
165161 mouseClick(app2, units.gu(1), units.gu(1));
166162 }
167163
168− tryCompare(phoneStage, "painting", false);
169164 tryCompare(ApplicationManager, "focusedApplicationId", newFocusedApp.appId);
170165 }
171166
@@ -212,16 +207,6 @@ Item {
212207 tryCompare(spreadView, "phase", 0);
213208 }
214209
215− function test_animateAppStartup() {
216− compare(phoneStage.painting, false);
217− addApps(2);
218− tryCompare(phoneStage, "painting", true);
219− tryCompare(phoneStage, "painting", false);
220− addApps(1);
221− tryCompare(phoneStage, "painting", true);
222− tryCompare(phoneStage, "painting", false);
223− }
224−
225210 function test_select_data() {
226211 return [
227212 { tag: "0", index: 0 },
@@ -240,47 +225,16 @@ Item {
240225
241226 phoneStage.select(selectedApp.appId);
242227
243− tryCompare(phoneStage, "painting", false);
244− compare(ApplicationManager.focusedApplicationId, selectedApp.appId);
245− }
228+ tryCompare(spreadView, "contentX", -spreadView.shift);
246229
247− function test_fullscreenMode() {
248− var fullscreenApp = null;
249− var normalApp = null;
250−
251− for (var i = 0; i < 5; i++) {
252− addApps(1);
253− var newApp = ApplicationManager.get(0);
254− tryCompare(phoneStage, "fullscreen", newApp.fullscreen);
255− if (newApp.fullscreen && fullscreenApp == null) {
256− fullscreenApp = newApp;
257− } else if (!newApp.fullscreen && normalApp == null){
258− normalApp = newApp;
259− }
260− }
261− verify(fullscreenApp != null); // Can't continue the test without having a fullscreen app
262− verify(normalApp != null); // Can't continue the test without having a non-fullscreen app
263−
264− // Select a normal app
265− goToSpread();
266− phoneStage.select(normalApp.appId);
267− tryCompare(phoneStage, "fullscreen", false);
268−
269− // Select a fullscreen app
270− goToSpread();
271− phoneStage.select(fullscreenApp.appId);
272− tryCompare(phoneStage, "fullscreen", true);
273−
274− // Select a normal app
275− goToSpread();
276− phoneStage.select(normalApp.appId);
277− tryCompare(phoneStage, "fullscreen", false);
230+ compare(ApplicationManager.focusedApplicationId, selectedApp.appId);
278231 }
279232
280233 function cleanup() {
281− while (ApplicationManager.count > 0) {
234+ while (ApplicationManager.count > 1) {
282235 var oldCount = ApplicationManager.count;
283− ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
236+ var closingIndex = ApplicationManager.focusedApplicationId == "unity8-dash" ? 1 : 0
237+ ApplicationManager.stopApplication(ApplicationManager.get(closingIndex).appId)
284238 tryCompare(ApplicationManager, "count", oldCount - 1)
285239 }
286240 }
tests/qmltests/tst_Shell.qml+175−272
@@ -51,47 +51,25 @@ Item {
5151 id: shell
5252 }
5353
54+ SignalSpy {
55+ id: sessionSpy
56+ signalName: "sessionStarted"
57+ }
58+
59+ SignalSpy {
60+ id: dashCommunicatorSpy
61+ signalName: "setCurrentScopeCalled"
62+ }
63+
5464 UT.UnityTestCase {
5565 name: "Shell"
5666 when: windowShown
5767
5868 function initTestCase() {
59− var ok = false;
60− var attempts = 0;
61− var maxAttempts = 1000;
62−
63− // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
64− // tests may fail because the desired child item wasn't loaded yet.
65− // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
66− // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
67− // (all items instantiated, etc), I resort to checking the existence of some key items until
68− // repeatedly until they're all there.
69− do {
70− var dashContentList = findChild(shell, "dashContentList");
71− waitForRendering(dashContentList);
72− var homeLoader = findChild(dashContentList, "clickscope loader");
73− ok = homeLoader !== null
74− && homeLoader.item !== undefined;
75−
76− var greeter = findChild(shell, "greeter");
77− ok &= greeter !== null;
78−
79− var launcherPanel = findChild(shell, "launcherPanel");
80− ok &= launcherPanel !== null;
81−
82− attempts++;
83− if (!ok) {
84− console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
85− // wait a bit before retrying
86− wait(100);
87− } else {
88− console.log("All seem fine after " + attempts + " attempts.");
89− }
90− } while (!ok && attempts <= maxAttempts);
91−
92− verify(ok);
93−
9469 swipeAwayGreeter();
70+
71+ sessionSpy.target = findChild(shell, "greeter")
72+ dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator");
9573 }
9674
9775 function cleanup() {
@@ -104,56 +82,16 @@ Item {
10482 // kill all (fake) running apps
10583 killApps(ApplicationManager);
10684
107− var dashContent = findChild(shell, "dashContent");
108− dashContent.closePreview();
109−
110− var dashHome = findChild(shell, "clickscope loader");
111− swipeUntilScopeViewIsReached(dashHome);
112−
85+ waitForUIToSettle();
11386 hideIndicators();
11487 }
11588
116− function killApps(apps) {
117− if (!apps) return;
118− while (apps.count > 0) {
119− ApplicationManager.stopApplication(apps.get(0).appId);
89+ function killApps() {
90+ while (ApplicationManager.count > 1) {
91+ var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
92+ ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
12093 }
121− compare(ApplicationManager.count, 0)
122− }
123−
124− /*
125− Test the effect of a right-edge drag on the dash in 3 situations:
126− 1 - when no application has been launched yet
127− 2 - when there's a minimized application
128− 3 - after the last running application has been closed/stopped
129−
130− The behavior of Dash on 3 should be the same as on 1.
131− */
132− function test_rightEdgeDrag() {
133− checkRightEdgeDragWithNoRunningApps();
134−
135− dragLauncherIntoView();
136−
137− // Launch an app from the launcher
138− tapOnAppIconInLauncher();
139− waitUntilApplicationWindowIsFullyVisible();
140−
141− // Minimize the application we just launched
142− swipeFromLeftEdge(units.gu(27));
143−
144− waitForUIToSettle();
145−
146− checkRightEdgeDragWithMinimizedApp();
147−
148− // Minimize that application once again
149− swipeFromLeftEdge(units.gu(27));
150−
151− // Right edge behavior should now be the same as before that app,
152− // was launched. Manually cleanup beforehand to get to initial
153− // state.
154− cleanup();
155− waitForUIToSettle();
156− checkRightEdgeDragWithNoRunningApps();
94+ compare(ApplicationManager.count, 1)
15795 }
15896
15997 function test_leftEdgeDrag_data() {
@@ -176,7 +114,7 @@ Item {
176114
177115 swipeFromLeftEdge(data.swipeLength);
178116 if (data.appHides)
179− waitUntilApplicationWindowIsFullyHidden();
117+ waitUntilDashIsFocused();
180118 else
181119 waitUntilApplicationWindowIsFullyVisible();
182120 }
@@ -229,133 +167,114 @@ Item {
229167
230168 // wait until the animation has finished
231169 tryCompare(greeter, "showProgress", 0);
170+ waitForRendering(greeter);
232171 }
233172
234173 /*
235− Perform a right-edge drag when the Dash is being show and there are
236− no running/minimized apps to be restored.
174+ Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419
175+
176+ When the user minimizes an application (left-edge swipe) he should always end up in the
177+ "Applications" scope view.
237178
238− The expected behavior is that an animation should be played to hint the
239− user that his right-edge drag gesture has been successfully recognized
240− but there is no application to be brought to foreground.
179+ Steps:
180+ - reveal launcher and launch an app that covers the dash
181+ - perform long left edge swipe to go minimize the app and go back to the dash.
182+ - verify the setCurrentScope() D-Bus call to the dash has been called for the correct scope id.
241183 */
242− function checkRightEdgeDragWithNoRunningApps() {
243− var touchX = shell.width - (shell.edgeSize / 2);
244− var touchY = shell.height / 2;
184+ function test_minimizingAppTakesToDashApps() {
185+ dragLauncherIntoView();
245186
246− var dash = findChild(shell, "dash");
247− // check that dash has normal scale and opacity
248− tryCompare(dash, "contentScale", 1.0);
249− tryCompare(dash, "opacity", 1.0);
187+ // Launch an app from the launcher
188+ tapOnAppIconInLauncher();
250189
251− touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
252− true /* beginTouch */, false /* endTouch */, units.gu(10), 50);
190+ waitUntilApplicationWindowIsFullyVisible();
253191
254− // check that Dash has been scaled down and had its opacity reduced
255− tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
256− tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
192+ verify(ApplicationManager.focusedApplicationId !== "unity8-dash")
257193
258− touchRelease(shell, shell.width * 0.1, touchY);
194+ dashCommunicatorSpy.clear();
195+ // Minimize the application we just launched
196+ swipeFromLeftEdge(units.gu(27));
259197
260− // and now everything should have gone back to normal
261− tryCompare(dash, "contentScale", 1.0);
262− tryCompare(dash, "opacity", 1.0);
263− }
198+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
264199
265− /*
266− Perform a right-edge drag when the Dash is being show and there is
267− a running/minimized app to be restored.
200+ compare(dashCommunicatorSpy.count, 1);
201+ compare(dashCommunicatorSpy.signalArguments[0][0], "clickscope");
202+ }
268203
269− The expected behavior is that the dash should fade away and ultimately be
270− made invisible once the gesture is finished as the restored app will now
271− be on foreground.
272− */
273− function checkRightEdgeDragWithMinimizedApp() {
274− var touchX = shell.width - (shell.edgeSize / 2);
275− var touchY = shell.height / 2;
204+ function test_showInputMethod() {
205+ var item = findChild(shell, "inputMethod");
206+ var surface = SurfaceManager.inputMethodSurface();
276207
277− var dash = findChild(shell, "dash");
278− // check that dash has normal scale and opacity
279− tryCompare(dash, "contentScale", 1.0);
280− tryCompare(dash, "opacity", 1.0);
208+ surface.setState(MirSurfaceItem.Minimized);
209+ tryCompare(item, "visible", false);
281210
282− touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
283− true /* beginTouch */, false /* endTouch */, units.gu(10), 50);
211+ surface.setState(MirSurfaceItem.Restored);
212+ tryCompare(item, "visible", true);
284213
285− // check that Dash has been scaled down and had its opacity reduced
286− tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
287− tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
214+ surface.setState(MirSurfaceItem.Minimized);
215+ tryCompare(item, "visible", false);
288216
289− touchRelease(shell, shell.width * 0.1, touchY);
217+ surface.setState(MirSurfaceItem.Maximized);
218+ tryCompare(item, "visible", true);
290219
291− // dash should have gone away, now that the app is on foreground
292− tryCompare(dash, "visible", false);
220+ surface.setState(MirSurfaceItem.Minimized);
221+ tryCompare(item, "visible", false);
293222 }
294223
295− /*
296− Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419
297−
298− When the user minimizes an application (left-edge swipe) he should always end up in the "Running Apps"
299− category of the "Applications" scope view.
224+ function test_surfaceLosesFocusWhilePanelIsOpen() {
225+ var app = ApplicationManager.startApplication("dialer-app");
226+ // wait until the app is fully loaded (ie, real surface replaces splash screen)
227+ tryCompareFunction(function() { return app.surface != null }, true);
300228
301− Steps:
302− - go to apps lens
303− - scroll to the bottom
304− - reveal launcher and launch an app
305− - perform long left edge swipe to go minimize the app and go back to the dash.
229+ tryCompare(app.surface, "focus", true);
306230
307− Expected Results
308− - apps lens shown and Running Apps visible on screen
309− */
310− function test_minimizingAppTakesToRunningApps() {
311− var dashApps = findChild(shell, "clickscope");
312− swipeUntilScopeViewIsReached(dashApps);
313−
314− // swipe finger up until the running/recent apps section (which we assume
315− // it's the first one) is as far from view as possible.
316− // We also assume that DashApps is tall enough that it's scrollable
317− var appsCategoryListView = findChild(dashApps, "categoryListView");
318− while (!appsCategoryListView.atYEnd) {
319− swipeUpFromCenter();
320− tryCompare(appsCategoryListView, "moving", false);
321− }
231+ // Drag the indicators panel half-open
232+ var touchX = shell.width / 2;
233+ var indicators = findChild(shell, "indicators");
234+ touchFlick(indicators,
235+ touchX /* fromX */, indicators.panelHeight * 0.5 /* fromY */,
236+ touchX /* toX */, shell.height * 0.5 /* toY */,
237+ true /* beginTouch */, false /* endTouch */);
238+ verify(indicators.partiallyOpened);
239+
240+ tryCompare(app.surface, "focus", false);
241+
242+ // And finish getting it open
243+ touchFlick(indicators,
244+ touchX /* fromX */, shell.height * 0.5 /* fromY */,
245+ touchX /* toX */, shell.height * 0.9 /* toY */,
246+ false /* beginTouch */, true /* endTouch */);
247+ tryCompare(indicators, "fullyOpened", true);
322248
323− // Switch away from the Applications scope.
324− swipeRightFromCenter();
325− waitUntilItemStopsMoving(dashApps);
326− verify(!itemIsOnScreen(dashApps));
249+ tryCompare(app.surface, "focus", false);
327250
328− dragLauncherIntoView();
251+ dragToCloseIndicatorsPanel();
329252
330− // Launch an app from the launcher
331− tapOnAppIconInLauncher();
332−
333− waitUntilApplicationWindowIsFullyVisible();
334−
335− // Dragging launcher into view with a little bit of gap (units.gu(1)) should switch to Apps scope
336− dragLauncherIntoView();
337− verify(itemIsOnScreen(dashApps));
253+ tryCompare(app.surface, "focus", true);
254+ }
338255
339− // Minimize the application we just launched
340− swipeFromLeftEdge(units.gu(27));
256+ // Wait for the whole UI to settle down
257+ function waitForUIToSettle() {
258+ var launcher = findChild(shell, "launcherPanel")
259+ tryCompareFunction(function() {return launcher.x === 0 || launcher.x === -launcher.width;}, true);
260+ if (launcher.x === 0) {
261+ mouseClick(shell, shell.width / 2, shell.height / 2)
262+ }
263+ tryCompare(launcher, "x", -launcher.width)
341264
342− // Wait for the whole UI to settle down
343− waitUntilApplicationWindowIsFullyHidden();
344− waitUntilItemStopsMoving(dashApps);
345− tryCompare(appsCategoryListView, "moving", false);
265+ waitForRendering(shell)
266+ }
346267
347− verify(itemIsOnScreen(dashApps));
268+ function dragToCloseIndicatorsPanel() {
269+ var indicators = findChild(shell, "indicators");
348270
349− var runningApplicationsGrid = findChild(appsCategoryListView, "running.apps.category");
350− verify(runningApplicationsGrid);
351− verify(itemIsOnScreen(runningApplicationsGrid));
352− }
271+ var touchStartX = shell.width / 2;
272+ var touchStartY = shell.height - (indicators.panelHeight * 0.5);
273+ touchFlick(shell,
274+ touchStartX, touchStartY,
275+ touchStartX, shell.height * 0.1);
353276
354− // Wait for the whole UI to settle down
355− function waitForUIToSettle() {
356− waitUntilApplicationWindowIsFullyHidden();
357− var dashContentList = findChild(shell, "dashContentList");
358− tryCompare(dashContentList, "moving", false);
277+ tryCompare(indicators, "fullyClosed", true);
359278 }
360279
361280 function dragLauncherIntoView() {
@@ -400,24 +319,13 @@ Item {
400319 }
401320
402321 function waitUntilApplicationWindowIsFullyVisible() {
403− var underlay = findChild(shell, "underlay");
404− tryCompare(underlay, "visible", false);
322+ var appDelegate = findChild(shell, "appDelegate0")
323+ var surfaceContainer = findChild(appDelegate, "surfaceContainer");
324+ tryCompareFunction(function() { return surfaceContainer.surface !== null; }, true);
405325 }
406326
407− function waitUntilApplicationWindowIsFullyHidden() {
408− var stages = findChild(shell, "stages");
409− tryCompare(stages, "fullyHidden", true);
410− }
411−
412− function swipeUntilScopeViewIsReached(scopeView) {
413− while (!itemIsOnScreen(scopeView)) {
414− if (itemIsToLeftOfScreen(scopeView)) {
415− swipeRightFromCenter();
416− } else {
417− swipeLeftFromCenter();
418− }
419− waitUntilItemStopsMoving(scopeView);
420− }
327+ function waitUntilDashIsFocused() {
328+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
421329 }
422330
423331 function swipeFromLeftEdge(swipeLength) {
@@ -426,24 +334,6 @@ Item {
426334 touchFlick(shell, touchStartX, touchStartY, swipeLength, touchStartY);
427335 }
428336
429− function swipeLeftFromCenter() {
430− var touchStartX = shell.width * 3 / 4;
431− var touchStartY = shell.height / 2;
432− touchFlick(shell, touchStartX, touchStartY, 0, touchStartY);
433− }
434−
435− function swipeRightFromCenter() {
436− var touchStartX = shell.width * 3 / 4;
437− var touchStartY = shell.height / 2;
438− touchFlick(shell, touchStartX, touchStartY, shell.width, touchStartY);
439− }
440−
441− function swipeUpFromCenter() {
442− var touchStartX = shell.width / 2;
443− var touchStartY = shell.height / 2;
444− touchFlick(shell, touchStartX, touchStartY, touchStartX, 0);
445− }
446−
447337 function itemIsOnScreen(item) {
448338 var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
449339
@@ -453,80 +343,93 @@ Item {
453343 && itemRectInShell.y + itemRectInShell.height <= shell.height;
454344 }
455345
456− function itemIsToLeftOfScreen(item) {
457− var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
458− return itemRectInShell.x < 0;
459− }
460−
461− function waitUntilItemStopsMoving(item) {
462− var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
463− var previousX = itemRectInShell.x;
464− var previousY = itemRectInShell.y;
465− var isStill = false;
466−
467− do {
468− wait(100);
469− itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
470− if (itemRectInShell.x == previousX && itemRectInShell.y == previousY) {
471− isStill = true;
472− } else {
473− previousX = itemRectInShell.x;
474− previousY = itemRectInShell.y;
475− }
476− } while (!isStill);
477− }
478−
479− function test_DashShown_data() {
480− return [
481− {tag: "in focus", greeter: false, app: false, launcher: false, indicators: false, expectedShown: true},
482− {tag: "under greeter", greeter: true, app: false, launcher: false, indicators: false, expectedShown: false},
483− {tag: "under app", greeter: false, app: true, launcher: false, indicators: false, expectedShown: false},
484− {tag: "under launcher", greeter: false, app: false, launcher: true, indicators: false, expectedShown: true},
485− {tag: "under indicators", greeter: false, app: false, launcher: false, indicators: true, expectedShown: true},
486− ]
487− }
346+ function test_focusRequestedHidesGreeter() {
347+ var greeter = findChild(shell, "greeter");
488348
489− function test_DashShown(data) {
490− if (data.greeter) {
491− // Swipe the greeter in
492− var greeter = findChild(shell, "greeter");
493− Powerd.displayPowerStateChange(Powerd.Off, 0);
494− tryCompare(greeter, "showProgress", 1);
495− }
349+ var app = ApplicationManager.startApplication("dialer-app");
350+ // wait until the app is fully loaded (ie, real surface replaces splash screen)
351+ tryCompareFunction(function() { return app.surface != null }, true);
496352
497− if (data.app) {
498− dragLauncherIntoView();
499− tapOnAppIconInLauncher();
500− }
353+ // Minimize the application we just launched
354+ swipeFromLeftEdge(units.gu(26) + 1);
501355
502− if (data.launcher) {
503− dragLauncherIntoView();
504− }
356+ waitUntilDashIsFocused();
505357
506− if (data.indicators) {
507− showIndicators();
508− }
358+ greeter.show();
359+ tryCompare(greeter, "showProgress", 1);
509360
510− var dash = findChild(shell, "dash");
511− tryCompare(dash, "shown", data.expectedShown);
361+ // The main point of this test
362+ ApplicationManager.requestFocusApplication("dialer-app");
363+ tryCompare(greeter, "showProgress", 0);
364+ waitForRendering(greeter);
512365 }
513366
514− function test_focusRequestedHidesGreeter() {
515− var greeter = findChild(shell, "greeter")
367+ function test_focusRequestedHidesIndicators() {
368+ var indicators = findChild(shell, "indicators");
516369
517− greeter.show()
518− tryCompare(greeter, "showProgress", 1)
370+ showIndicators();
519371
520− ApplicationManager.focusRequested("notes-app")
521− tryCompare(greeter, "showProgress", 0)
522− waitUntilApplicationWindowIsFullyVisible()
372+ var oldCount = ApplicationManager.count;
373+ ApplicationManager.startApplication("camera-app");
374+ tryCompare(ApplicationManager, "count", oldCount + 1);
375+
376+ tryCompare(indicators, "fullyClosed", true);
523377 }
524378
379+
525380 function test_showGreeterDBusCall() {
526381 var greeter = findChild(shell, "greeter")
527382 tryCompare(greeter, "showProgress", 0)
383+ waitForRendering(greeter);
528384 LightDM.Greeter.showGreeter()
529385 tryCompare(greeter, "showProgress", 1)
530386 }
387+
388+ function test_login() {
389+ sessionSpy.clear()
390+
391+ var greeter = findChild(shell, "greeter")
392+ waitForRendering(greeter)
393+ greeter.show()
394+ tryCompare(greeter, "showProgress", 1)
395+
396+ tryCompare(sessionSpy, "count", 0)
397+ swipeAwayGreeter()
398+ tryCompare(sessionSpy, "count", 1)
399+ }
400+
401+ function test_fullscreen() {
402+ var panel = findChild(shell, "panel");
403+ compare(panel.fullscreenMode, false);
404+ ApplicationManager.startApplication("camera-app");
405+ tryCompare(panel, "fullscreenMode", true);
406+ ApplicationManager.startApplication("gallery-app");
407+ tryCompare(panel, "fullscreenMode", false);
408+ ApplicationManager.requestFocusApplication("camera-app");
409+ tryCompare(panel, "fullscreenMode", true);
410+ ApplicationManager.requestFocusApplication("gallery-app");
411+ tryCompare(panel, "fullscreenMode", false);
412+ }
413+
414+ function test_leftEdgeDragFullscreen() {
415+ var panel = findChild(shell, "panel");
416+ tryCompare(panel, "fullscreenMode", false)
417+
418+ ApplicationManager.startApplication("camera-app");
419+ tryCompare(panel, "fullscreenMode", true)
420+
421+ var touchStartX = 2;
422+ var touchStartY = shell.height / 2;
423+
424+ touchFlick(shell, touchStartX, touchStartY, units.gu(2), touchStartY, true, false);
425+
426+ compare(panel.fullscreenMode, true);
427+
428+ touchFlick(shell, units.gu(2), touchStartY, units.gu(10), touchStartY, false, false);
429+
430+ tryCompare(panel, "fullscreenMode", false);
431+
432+ touchRelease(shell);
433+ }
531434 }
532435}
tests/qmltests/tst_ShellWithPin.qmlnew file+170
@@ -0,0 +1,170 @@
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 QtTest 1.0
19+import GSettings 1.0
20+import LightDM 0.1 as LightDM
21+import Unity.Application 0.1
22+import Unity.Test 0.1 as UT
23+import Powerd 0.1
24+
25+import "../../qml"
26+
27+Item {
28+ width: shell.width
29+ height: shell.height
30+
31+ QtObject {
32+ id: applicationArguments
33+
34+ function hasGeometry() {
35+ return false;
36+ }
37+
38+ function width() {
39+ return 0;
40+ }
41+
42+ function height() {
43+ return 0;
44+ }
45+ }
46+
47+ Shell {
48+ id: shell
49+ }
50+
51+ SignalSpy {
52+ id: sessionSpy
53+ signalName: "sessionStarted"
54+ }
55+
56+ UT.UnityTestCase {
57+ name: "ShellWithPin"
58+ when: windowShown
59+
60+ function initTestCase() {
61+
62+ sessionSpy.target = findChild(shell, "greeter")
63+ }
64+
65+ function init() {
66+ swipeAwayGreeter()
67+ }
68+
69+ function cleanup() {
70+ LightDM.Greeter.showGreeter()
71+ var greeter = findChild(shell, "greeter")
72+ tryCompare(greeter, "showProgress", 1)
73+
74+ // kill all (fake) running apps
75+ killApps()
76+ }
77+
78+ function killApps() {
79+ while (ApplicationManager.count > 1) {
80+ var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
81+ ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
82+ }
83+ compare(ApplicationManager.count, 1)
84+ }
85+
86+ function swipeAwayGreeter() {
87+ var greeter = findChild(shell, "greeter");
88+ tryCompare(greeter, "showProgress", 1);
89+
90+ var touchX = shell.width - (shell.edgeSize / 2);
91+ var touchY = shell.height / 2;
92+ touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY);
93+
94+ // wait until the animation has finished
95+ tryCompare(greeter, "showProgress", 0);
96+
97+ // and for pin to be ready
98+ var lockscreen = findChild(shell, "lockscreen");
99+ var pinPadLoader = findChild(lockscreen, "pinPadLoader");
100+ tryCompare(pinPadLoader, "status", Loader.Ready)
101+ waitForRendering(lockscreen)
102+ }
103+
104+ function enterPin(pin) {
105+ var inputField = findChild(shell, "pinentryField")
106+ for (var i = 0; i < pin.length; ++i) {
107+ var character = pin.charAt(i)
108+ var button = findChild(shell, "pinPadButton" + character)
109+ mouseClick(button, units.gu(1), units.gu(1))
110+ }
111+ }
112+
113+ function test_login() {
114+ tryCompare(sessionSpy, "count", 0)
115+ enterPin("1234")
116+ tryCompare(sessionSpy, "count", 1)
117+ }
118+
119+ function test_emergencyCall() {
120+ var greeter = findChild(shell, "greeter")
121+ var lockscreen = findChild(shell, "lockscreen")
122+ var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
123+ var panel = findChild(shell, "panel")
124+ var indicators = findChild(shell, "indicators")
125+ var launcher = findChild(shell, "launcher")
126+ var stage = findChild(shell, "stage")
127+
128+ mouseClick(emergencyButton, units.gu(1), units.gu(1))
129+
130+ tryCompare(greeter, "fakeActiveForApp", "dialer-app")
131+ tryCompare(lockscreen, "shown", false)
132+ tryCompare(panel, "fullscreenMode", true)
133+ tryCompare(indicators, "available", false)
134+ tryCompare(launcher, "available", false)
135+ tryCompare(stage, "spreadEnabled", false)
136+
137+ // Cancel emergency mode, and go back to normal
138+ waitForRendering(greeter)
139+ LightDM.Greeter.showGreeter()
140+
141+ tryCompare(greeter, "shown", true)
142+ tryCompare(greeter, "fakeActiveForApp", "")
143+ tryCompare(lockscreen, "shown", true)
144+ tryCompare(panel, "fullscreenMode", false)
145+ tryCompare(indicators, "available", true)
146+ tryCompare(launcher, "available", true)
147+ tryCompare(stage, "spreadEnabled", true)
148+ }
149+
150+ function test_emergencyCallCrash() {
151+ var lockscreen = findChild(shell, "lockscreen")
152+ var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
153+ mouseClick(emergencyButton, units.gu(1), units.gu(1))
154+
155+ tryCompare(lockscreen, "shown", false)
156+ killApps() // kill dialer-app, as if it crashed
157+ tryCompare(lockscreen, "shown", true)
158+ }
159+
160+ function test_emergencyCallAppLaunch() {
161+ var lockscreen = findChild(shell, "lockscreen")
162+ var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
163+ mouseClick(emergencyButton, units.gu(1), units.gu(1))
164+
165+ tryCompare(lockscreen, "shown", false)
166+ ApplicationManager.startApplication("gallery-app", ApplicationManager.NoFlag)
167+ tryCompare(lockscreen, "shown", true)
168+ }
169+ }
170+}