on xenial help sign in
Merged with trunk.
commitb8d6e6053893bf9c400feec36327bfc749899741 authorLeo Arias <leo.arias@canonical.com> dateFri 11 Apr 2014, 09:59 (13 years ago) parentb154d729c61eb8
43 files changed+444−1187
.bazaar/plugins/makecheck_unity_phablet.py+1−1 build+1 cmake/modules/QmlTest.cmake+62−17 debian/changelog+79 debian/unity8-autopilot.install+1 debian/unity8-fake-env.install+1 include/paths.h.in+10 po/ast.po+5−22 po/bg.po+1−1 po/fi.po+5−22 po/gl.po+5−22 po/ru.po+12−29 qml/Components/FilterGrid.qml+1 qml/Components/ResponsiveGridView.qml+1 qml/Components/Stage.qml−571 qml/Dash/CardFilterGrid.qml+2−4 qml/Dash/DashRenderer.qml+2−6 qml/Dash/GenericScopeView.qml+8−8 qml/Notifications/NotificationMenuItemFactory.qml+2−1 src/main.cpp+3 tests/CMakeLists.txt+2−2 tests/autopilot/unity8/indicators/tests/__init__.py+17 tests/autopilot/unity8/indicators/tests/test_indicators.py+69−13 tests/autopilot/unity8/shell/emulators/__init__.py+2−6 tests/autopilot/unity8/shell/emulators/dash.py+24−1 tests/autopilot/unity8/shell/emulators/main_window.py+32−2 tests/autopilot/unity8/shell/tests/test_emulators.py+24−6 tests/autopilot/unity8/shell/tests/test_system_integration.py+3−2 tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp+3 tests/mocks/Unity/Application/CMakeLists.txt+14 tests/plugins/Ubuntu/Gestures/CMakeLists.txt+2−11 tests/qmltests/CMakeLists.txt−4 tests/qmltests/Components/CMakeLists.txt+2−10 tests/qmltests/Components/tst_LazyImage.qml+1 tests/qmltests/Components/tst_Stage.qml−278 tests/qmltests/Components/tst_Stage/AppControl.qml−42 tests/qmltests/Components/tst_Stage/FakeApplicationScreenshot.qml−53 tests/qmltests/Dash/tst_GenericScopeView.qml+1 tests/qmltests/SideStage/tst_SideStage.qml−52 tests/qmltests/tst_Shell.qml+1−1 tools/CMakeLists.txt+2 tools/scopetool.cpp+1 tools/unlock-device+42
.bazaar/plugins/makecheck_unity_phablet.py+1−1
@@ -18,7 +18,7 @@ from bzrlib import branch, errors
1818from bzrlib.urlutils import dirname, local_path_from_url
1919
2020def execute_makecheck(local_branch, master_branch, old_revision_number, old_revision_id, future_revision_number, future_revision_id, tree_delta, future_tree):
21− if not master_branch.basis_tree().has_filename("Shell.qml"):
21+ if not master_branch.basis_tree().has_filename("qml/Shell.qml"):
2222 return
2323
2424 os.chdir(local_path_from_url(master_branch.base))
build+1
@@ -54,6 +54,7 @@ install_dependencies() {
5454 unity-scope-home \
5555 unity-lens-applications \
5656 unity-plugin-scopes \
57+ xvfb \
5758 || exit 5
5859}
5960
cmake/modules/QmlTest.cmake+62−17
@@ -65,6 +65,7 @@ macro(add_qml_test SUBPATH COMPONENT_NAME)
6565 cmake_parse_arguments(qmltest "${options}" "" "${multi_value_keywords}" ${ARGN})
6666
6767 set(qmltest_TARGET test${COMPONENT_NAME})
68+ set(qmltest_xvfb_TARGET xvfbtest${COMPONENT_NAME})
6869 set(qmltest_FILE ${SUBPATH}/tst_${COMPONENT_NAME})
6970
7071 set(qmltestrunner_imports "")
@@ -82,24 +83,69 @@ macro(add_qml_test SUBPATH COMPONENT_NAME)
8283
8384 string(TOLOWER "${CMAKE_GENERATOR}" cmake_generator_lower)
8485 if(cmake_generator_lower STREQUAL "unix makefiles")
85− set(qmltest_command
86− env ${qmltest_ENVIRONMENT}
87− ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
88− ${qmltestrunner_imports}
89− -o ${CMAKE_BINARY_DIR}/${qmltest_TARGET}.xml,xunitxml
90− -o -,txt
91− $(FUNCTION)
92− )
86+ set(function_ARGS $(FUNCTION))
9387 else()
94− set(qmltest_command
95− env ${qmltest_ENVIRONMENT}
96− ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
97− ${qmltestrunner_imports}
98− -o ${CMAKE_BINARY_DIR}/${qmltest_TARGET}.xml,xunitxml
99− -o -,txt
100− )
88+ set(function_ARGS "")
10189 endif()
10290
91+ set(qmltest_command
92+ env ${qmltest_ENVIRONMENT}
93+ ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
94+ ${qmltestrunner_imports}
95+ -o ${CMAKE_BINARY_DIR}/${qmltest_TARGET}.xml,xunitxml
96+ -o -,txt
97+ ${function_ARGS}
98+ )
99+ find_program( HAVE_GCC gcc )
100+ if (NOT ${HAVE_GCC} STREQUAL "")
101+ exec_program( gcc ARGS "-dumpmachine" OUTPUT_VARIABLE ARCH_TRIPLET )
102+ set(LD_PRELOAD_PATH "LD_PRELOAD=/usr/lib/${ARCH_TRIPLET}/mesa/libGL.so.1")
103+ endif()
104+ set(qmltest_xvfb_command
105+ env ${qmltest_ENVIRONMENT} ${LD_PRELOAD_PATH}
106+ xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
107+ ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
108+ ${qmltestrunner_imports}
109+ -o ${CMAKE_BINARY_DIR}/${qmltest_TARGET}.xml,xunitxml
110+ -o -,txt
111+ ${function_ARGS}
112+ )
113+
114+ add_qmltest_target(${qmltest_TARGET} "${qmltest_command}" TRUE ${qmltest_NO_ADD_TEST})
115+ add_qmltest_target(${qmltest_xvfb_TARGET} "${qmltest_xvfb_command}" ${qmltest_NO_TARGETS} TRUE)
116+ add_manual_qml_test(${SUBPATH} ${COMPONENT_NAME} ${ARGN})
117+endmacro(add_qml_test)
118+
119+macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS)
120+ set(testCommand
121+ LD_LIBRARY_PATH=${LD_PATH}
122+ ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
123+ -o ${CMAKE_BINARY_DIR}/${CLASSNAME}Test.xml,xunitxml
124+ -o -,txt)
125+
126+ add_qmltest_target(test${CLASS_NAME} "${testCommand}" FALSE TRUE)
127+ add_dependencies(test${CLASS_NAME} ${CLASS_NAME}TestExec ${DEPS})
128+
129+ find_program( HAVE_GCC gcc )
130+ if (NOT ${HAVE_GCC} STREQUAL "")
131+ exec_program( gcc ARGS "-dumpmachine" OUTPUT_VARIABLE ARCH_TRIPLET )
132+ set(LD_PRELOAD_PATH "LD_PRELOAD=/usr/lib/${ARCH_TRIPLET}/mesa/libGL.so.1")
133+ endif()
134+ set(xvfbtestCommand
135+ ${LD_PRELOAD_PATH}
136+ LD_LIBRARY_PATH=${LD_PATH}
137+ xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
138+ ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
139+ -o ${CMAKE_BINARY_DIR}/${CLASS_NAME}Test.xml,xunitxml
140+ -o -,txt)
141+
142+ add_qmltest_target(xvfbtest${CLASS_NAME} "${xvfbtestCommand}" FALSE TRUE)
143+ add_dependencies(qmluitests xvfbtest${CLASS_NAME})
144+
145+ add_manual_qml_test(. ${CLASS_NAME} IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
146+endmacro(add_binary_qml_test)
147+
148+macro(add_qmltest_target qmltest_TARGET qmltest_command qmltest_NO_TARGETS qmltest_NO_ADD_TEST)
103149 add_custom_target(${qmltest_TARGET} ${qmltest_command})
104150
105151 if(NOT "${qmltest_PROPERTIES}" STREQUAL "")
@@ -130,5 +176,4 @@ macro(add_qml_test SUBPATH COMPONENT_NAME)
130176 endif()
131177 endif("${qmltest_NO_TARGETS}" STREQUAL "FALSE")
132178
133− add_manual_qml_test(${SUBPATH} ${COMPONENT_NAME} ${ARGN})
134−endmacro(add_qml_test)
179+endmacro(add_qmltest_target)
debian/changelog+79
@@ -1,3 +1,82 @@
1+unity8 (7.85+14.04.20140410.1-0ubuntu1) trusty; urgency=medium
2+
3+ [ Didier Roche ]
4+ * Resync trunk with previous revert upload
5+
6+ [ Michał Sawicz ]
7+ * Set the Qt.ImhNoPredictiveText flag on wifi password field, fixes
8+ lp:1291575 (LP: #1291575)
9+
10+ [ Albert Astals ]
11+ * Take into account the originY when specifying the delegate ranges
12+ Fixes bug #1300302 (LP: #1300302)
13+
14+ [ CI bot ]
15+ * Resync trunk
16+
17+ [ Allan LeSage ]
18+ * Swiping open an indicator must show its correct title--protect
19+ against lp:1253804 . (LP: #1253804)
20+
21+ [ Alexander Sack ]
22+ * Fix TypeError: issue seen in system_integration autopilot test on
23+ image 279. (LP: #1303685)
24+
25+ [ Bill Filler ]
26+ * Set the Qt.ImhNoPredictiveText flag on wifi password field, fixes
27+ lp:1291575 (LP: #1291575)
28+
29+ [ Leo Arias ]
30+ * Added a search autopilot helper.
31+
32+ [ Michael Terry ]
33+ * Provide a all-in-one script for getting a device to an unlocked
34+ state.
35+
36+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 10 Apr 2014 10:03:31 +0000
37+
38+unity8 (7.85+14.04.20140404.is.7.85+14.04.20140403.1-0ubuntu1) trusty; urgency=medium
39+
40+ * Revert to previous version as it's linked to latest sdk change which
41+ is making gallery-app AP tests failing on the CI dashboard
42+
43+ -- Didier Roche <didrocks@ubuntu.com> Tue, 08 Apr 2014 13:53:47 +0200
44+
45+unity8 (7.85+14.04.20140404-0ubuntu1) trusty; urgency=low
46+
47+ [ Albert Astals ]
48+ * Adapt to new TabBar
49+
50+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 04 Apr 2014 15:03:00 +0000
51+
52+unity8 (7.85+14.04.20140403.1-0ubuntu1) trusty; urgency=low
53+
54+ [ Michael Terry ]
55+ * Re-enable test_networkmanager_integration autopilot test on phone
56+ platforms
57+
58+ [ CI bot ]
59+ * Resync trunk
60+
61+ [ Leo Arias ]
62+ * Reverted the open_preview autopilot helper to return a Preview
63+ object.
64+
65+ [ Albert Astals ]
66+ * If not running in Mir load the "fake" application manager (LP:
67+ #1301547)
68+ * Remove unused properties from DashRenderer
69+
70+ [ Michael Zanetti ]
71+ * Fix tests after right edge merge. Drop old stages tests. Fix right
72+ edge tests if someone doesn't have the GRID_UNIT_PX exported. make
73+ GenericScopeView test more robust that broke because the ordering
74+ changed
75+ * add "make xvfbtestSomething" target to run qml tests in xvfb
76+ * make the "make test" commit hook work again
77+
78+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 03 Apr 2014 10:38:53 +0000
79+
180unity8 (7.85+14.04.20140401.3-0ubuntu1) trusty; urgency=medium
281
382 [ Michał Sawicz ]
debian/unity8-autopilot.install+1
@@ -1 +1,2 @@
11usr/lib/python*/*/unity*
2+usr/share/unity8/unlock-device
debian/unity8-fake-env.install+1
@@ -1,3 +1,4 @@
1+usr/lib/*/unity8/qml/nonmirplugins
12usr/lib/*/unity8/qml/mocks
23usr/lib/*/unity8/qml/scopefakes
34usr/share/unity8/mocks
include/paths.h.in+10
@@ -57,6 +57,16 @@ inline QStringList overrideImportPaths() {
5757 return paths;
5858}
5959
60+inline QStringList nonMirImportPaths() {
61+ QStringList paths;
62+ if (isRunningInstalled()) {
63+ paths << QString("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/nonmirplugins");
64+ } else {
65+ paths << QString("@CMAKE_BINARY_DIR@/nonmirplugins");
66+ }
67+ return paths;
68+}
69+
6070inline QStringList fallbackImportPaths() {
6171 QStringList paths;
6272 if (isRunningInstalled()) {
po/ast.po+5−22
@@ -8,15 +8,14 @@ msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-03-25 16:48+0100\n"
11−"PO-Revision-Date: 2014-03-01 16:51+0000\n"
11+"PO-Revision-Date: 2014-04-04 02:16+0000\n"
1212"Last-Translator: Xuacu Saturio <xuacusk8@gmail.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−"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2014-03-28 06:48+0000\n"
19−"X-Generator: Launchpad (build 16967)\n"
17+"X-Launchpad-Export-Date: 2014-04-08 07:13+0000\n"
18+"X-Generator: Launchpad (build 16976)\n"
2019
2120#: plugins/Unity/Launcher/launcheritem.cpp:43
2221#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -91,12 +90,12 @@ msgstr "Ver menos"
9190
9291#: qml/Dash/DashApps.qml:38
9392msgid "Recent"
94−msgstr ""
93+msgstr "Reciente"
9594
9695#: qml/Dash/PreviewListView.qml:52
9796#, qt-format
9897msgid "%1 Preview"
99−msgstr ""
98+msgstr "Vista previa de %1"
10099
101100#: qml/Dash/Previews/PreviewActionCombo.qml:34
102101msgid "More..."
@@ -167,19 +166,3 @@ msgstr "Guetar"
167166#, qt-format
168167msgid "Please enter %1"
169168msgstr "Introduz %1"
170−
171−#, qt-format
172−#~ msgid "(%1)"
173−#~ msgstr "(%1)"
174−
175−#~ msgid "Comments:"
176−#~ msgstr "Comentarios:"
177−
178−#~ msgid "Review"
179−#~ msgstr "Revisar"
180−
181−#, qt-format
182−#~ msgid "%1 review"
183−#~ msgid_plural "%1 reviews"
184−#~ msgstr[0] "%1 reseña"
185−#~ msgstr[1] "%1 reseñes"
po/bg.po+1−1
@@ -14,7 +14,7 @@ msgstr ""
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-04-02 06:50+0000\n"
17+"X-Launchpad-Export-Date: 2014-04-03 06:06+0000\n"
1818"X-Generator: Launchpad (build 16967)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
po/fi.po+5−22
@@ -8,15 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-03-25 16:48+0100\n"
11−"PO-Revision-Date: 2014-03-09 19:22+0000\n"
11+"PO-Revision-Date: 2014-04-05 09:57+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−"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2014-03-28 06:48+0000\n"
19−"X-Generator: Launchpad (build 16967)\n"
17+"X-Launchpad-Export-Date: 2014-04-08 07:13+0000\n"
18+"X-Generator: Launchpad (build 16976)\n"
2019
2120#: plugins/Unity/Launcher/launcheritem.cpp:43
2221#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -89,12 +88,12 @@ msgstr "Näytä vähemmän"
8988
9089#: qml/Dash/DashApps.qml:38
9190msgid "Recent"
92−msgstr ""
91+msgstr "Viimeisimmät"
9392
9493#: qml/Dash/PreviewListView.qml:52
9594#, qt-format
9695msgid "%1 Preview"
97−msgstr ""
96+msgstr "%1 esikatselu"
9897
9998#: qml/Dash/Previews/PreviewActionCombo.qml:34
10099msgid "More..."
@@ -165,19 +164,3 @@ msgstr "Hae"
165164#, qt-format
166165msgid "Please enter %1"
167166msgstr "Kirjoita %1"
168−
169−#~ msgid "Comments:"
170−#~ msgstr "Kommentit:"
171−
172−#~ msgid "Review"
173−#~ msgstr "Arvostelu"
174−
175−#, qt-format
176−#~ msgid "%1 review"
177−#~ msgid_plural "%1 reviews"
178−#~ msgstr[0] "%1 arvostelu"
179−#~ msgstr[1] "%1 arvostelua"
180−
181−#, qt-format
182−#~ msgid "(%1)"
183−#~ msgstr "(%1)"
po/gl.po+5−22
@@ -8,15 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-03-25 16:48+0100\n"
11−"PO-Revision-Date: 2014-03-08 06:58+0000\n"
11+"PO-Revision-Date: 2014-04-08 07:04+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−"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2014-03-28 06:48+0000\n"
19−"X-Generator: Launchpad (build 16967)\n"
17+"X-Launchpad-Export-Date: 2014-04-09 07:31+0000\n"
18+"X-Generator: Launchpad (build 16976)\n"
2019
2120#: plugins/Unity/Launcher/launcheritem.cpp:43
2221#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -89,12 +88,12 @@ msgstr "Ver menos"
8988
9089#: qml/Dash/DashApps.qml:38
9190msgid "Recent"
92−msgstr ""
91+msgstr "Recentes"
9392
9493#: qml/Dash/PreviewListView.qml:52
9594#, qt-format
9695msgid "%1 Preview"
97−msgstr ""
96+msgstr "%1 previsualización"
9897
9998#: qml/Dash/Previews/PreviewActionCombo.qml:34
10099msgid "More..."
@@ -165,19 +164,3 @@ msgstr "Buscar"
165164#, qt-format
166165msgid "Please enter %1"
167166msgstr "Introduza %1"
168−
169−#, qt-format
170−#~ msgid "(%1)"
171−#~ msgstr "(%1)"
172−
173−#~ msgid "Comments:"
174−#~ msgstr "Comentarios:"
175−
176−#~ msgid "Review"
177−#~ msgstr "Opinión"
178−
179−#, qt-format
180−#~ msgid "%1 review"
181−#~ msgid_plural "%1 reviews"
182−#~ msgstr[0] "%1 opinión"
183−#~ msgstr[1] "%1 opinións"
po/ru.po+12−29
@@ -8,16 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-03-25 16:48+0100\n"
11−"PO-Revision-Date: 2014-01-26 15:56+0000\n"
11+"PO-Revision-Date: 2014-04-03 13:07+0000\n"
1212"Last-Translator: Zonov Roman <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−"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18−"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2014-03-28 06:49+0000\n"
20−"X-Generator: Launchpad (build 16967)\n"
17+"X-Launchpad-Export-Date: 2014-04-04 07:12+0000\n"
18+"X-Generator: Launchpad (build 16976)\n"
2119
2220#: plugins/Unity/Launcher/launcheritem.cpp:43
2321#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -78,6 +76,8 @@ msgid ""
7876"You have now mastered the edge gestures and can start using the "
7977"phone<br><br>Tap on the screen to start"
8078msgstr ""
79+"Вы научились пользоваться Ubuntu и можете начать использовать свой "
80+"телефон<br><br>Нажмите на экран"
8181
8282#: qml/Components/PageHeader.qml:365
8383msgid "Recent searches"
@@ -85,28 +85,28 @@ msgstr "Последние поисковые запросы"
8585
8686#: qml/Components/SeeMore.qml:35
8787msgid "See more"
88−msgstr ""
88+msgstr "Подробнее"
8989
9090#: qml/Components/SeeMore.qml:58
9191msgid "See less"
92−msgstr ""
92+msgstr "Вкратце"
9393
9494#: qml/Dash/DashApps.qml:38
9595msgid "Recent"
96−msgstr ""
96+msgstr "Недавние"
9797
9898#: qml/Dash/PreviewListView.qml:52
9999#, qt-format
100100msgid "%1 Preview"
101−msgstr ""
101+msgstr "Просмотр %1"
102102
103103#: qml/Dash/Previews/PreviewActionCombo.qml:34
104104msgid "More..."
105−msgstr ""
105+msgstr "Ещё..."
106106
107107#: qml/Dash/Previews/PreviewActionCombo.qml:34
108108msgid "Less..."
109−msgstr ""
109+msgstr "Меньше..."
110110
111111#: qml/Dash/Previews/PreviewRatingInput.qml:81
112112msgid "Rate this"
@@ -159,7 +159,7 @@ msgstr "Показать пароль"
159159
160160#: qml/Notifications/NotificationMenuItemFactory.qml:103
161161msgid "Please enter SIM PIN"
162−msgstr ""
162+msgstr "Введите PIN код"
163163
164164#: qml/Panel/SearchIndicator.qml:27
165165msgid "Search"
@@ -169,20 +169,3 @@ msgstr "Поиск"
169169#, qt-format
170170msgid "Please enter %1"
171171msgstr "Пожалуйста, введите %1"
172−
173−#, qt-format
174−#~ msgid "(%1)"
175−#~ msgstr "(%1)"
176−
177−#~ msgid "Comments:"
178−#~ msgstr "Комментарии:"
179−
180−#~ msgid "Review"
181−#~ msgstr "Отзыв"
182−
183−#, qt-format
184−#~ msgid "%1 review"
185−#~ msgid_plural "%1 reviews"
186−#~ msgstr[0] "%1 отзыв"
187−#~ msgstr[1] "%1 отзыва"
188−#~ msgstr[2] "%1 отзывов"
qml/Components/FilterGrid.qml+1
@@ -59,6 +59,7 @@ Item {
5959 property alias cellHeight: iconTileGrid.cellHeight
6060 property alias delegateCreationBegin: iconTileGrid.delegateCreationBegin
6161 property alias delegateCreationEnd: iconTileGrid.delegateCreationEnd
62+ readonly property alias originY: iconTileGrid.originY
6263 readonly property alias flicking: iconTileGrid.flicking
6364 readonly property alias moving: iconTileGrid.moving
6465 readonly property alias pressDelay: iconTileGrid.pressDelay
qml/Components/ResponsiveGridView.qml+1
@@ -40,6 +40,7 @@ Item {
4040 readonly property alias flicking: gridView.flicking
4141 readonly property alias moving: gridView.moving
4242 readonly property alias pressDelay: gridView.pressDelay
43+ readonly property alias originY: gridView.originY
4344 property alias delegateCreationBegin: gridView.delegateCreationBegin
4445 property alias delegateCreationEnd: gridView.delegateCreationEnd
4546 property alias highlightIndex: gridView.highlightIndex
qml/Components/Stage.qmldeleted−571
@@ -1,571 +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 Unity.Application 0.1
19−import Ubuntu.Components 0.1
20−import Ubuntu.Gestures 0.1
21−
22−/*
23− Responsible for application switching.
24−
25− Drag from the right edge to switch to the next application.
26− While being dragged, this component will show an animation for the user to
27− visualize that he's changing the stacking of applications (next/new app comes from
28− right edge and current/old app fades out).
29− */
30−Showable {
31− id: stage
32−
33− width: units.gu(40)
34− height: units.gu(71)
35−
36− property int type: ApplicationInfo.MainStage
37− property var applicationManager
38− readonly property var applications:
39− type == ApplicationInfo.MainStage ? applicationManager.mainStageApplications
40− : applicationManager.sideStageApplications
41− property bool fullyShown: false
42− property bool fullyHidden: true
43− readonly property var focusedApplication:
44− type == ApplicationInfo.MainStage ? applicationManager.mainStageFocusedApplication
45− : applicationManager.sideStageFocusedApplication
46− property bool shouldUseScreenshots: true
47−
48− /* Will be true whenever application screenshots are being shown.
49− i.e. during application window transitions */
50− readonly property bool usingScreenshots: {
51− if (newApplicationScreenshot.application != null && oldApplicationScreenshot.application != null) {
52− return newApplicationScreenshot.ready && oldApplicationScreenshot.ready;
53− } else {
54− return newApplicationScreenshot.ready || oldApplicationScreenshot.ready;
55− }
56− }
57−
58− property bool rightEdgeEnabled: true
59− property bool switchingFromFullscreenToFullscreen: false
60−
61− property alias rightEdgeDraggingAreaWidth: rightEdgeDraggingArea.width
62−
63− // Y coordinate for non-fullscreen applications
64− property int normalApplicationY: 0
65−
66− function activateApplication(desktopFile, addDelay) {
67− var application = applicationManager.getApplicationFromDesktopFile(desktopFile, stage.type);
68− if (application == null) {
69− return;
70− } else if (application == stage.focusedApplication) {
71− stage.show();
72− return;
73− }
74−
75− showStartingApplicationAnimation.prepare(application);
76− if (!stage.fullyShown) {
77− // if launching this app reveals the stage, make new application screenshot visible
78− newApplicationScreenshot.visible = true;
79− stage.show();
80− } else {
81− showStartingApplicationAnimation.start();
82− }
83−
84− if (addDelay) {
85− stage.__startingApplicationDesktopFile = desktopFile;
86− }
87− }
88−
89− Connections {
90− target: applicationManager
91− onFocusRequested: activateApplication(appId)
92− }
93−
94− /* Keep a reference to the focused application so that we can safely
95− unfocus it when the stage is not fully shown and refocus it when the stage
96− is fully shown again.
97− */
98− property var focusedApplicationWhenUsingScreenshots
99− onShouldUseScreenshotsChanged: {
100− if (showStartingApplicationAnimation.running || switchToApplicationAnimation.running) {
101− return;
102− }
103−
104− if (shouldUseScreenshots) {
105− stage.__focusApplicationUsingScreenshots(stage.focusedApplication);
106− } else {
107− if (stage.focusedApplicationWhenUsingScreenshots) {
108− stage.__focusActualApplication(stage.focusedApplicationWhenUsingScreenshots);
109− }
110− }
111− }
112−
113−
114− property Item newApplicationScreenshot: ApplicationScreenshot {
115− parent: stage
116− width: stage.width
117− height: stage.height - y
118− }
119− property Item oldApplicationScreenshot: ApplicationScreenshot {
120− parent: stage
121− width: stage.width
122− height: stage.height - y
123− }
124−
125− function __getApplicationIndex(application) {
126− if (!application)
127− return -1
128− for (var i = 0; i < stage.applications.count; i++ ) {
129− if (stage.applications.get(i).desktopFile == application.desktopFile) {
130− return i
131− }
132− }
133− return -1
134− }
135−
136−
137− property string __startingApplicationDesktopFile
138−
139− Timer {
140− id: delayedHideScreenshots
141− interval: 500 // on Galaxy Nexus, Telephony app is slowest application to draw a frame so needs this delay
142− onTriggered: {
143− __hideScreenshots();
144− }
145− }
146−
147− Timer {
148− id: hideScreenshotsAfterBriefDelay
149− // Since Mir & Qt have independent event loops, Mir often applies a focus request a frame later than when Qt
150− // asks for it. To work around, delay removing the screenshots a touch so Mir has definitely shown the app.
151− interval: 10
152− onTriggered: stage.__hideScreenshots();
153− }
154−
155− function __hideScreenshots() {
156− newApplicationScreenshot.clearApplication();
157− oldApplicationScreenshot.clearApplication();
158− newApplicationScreenshot.visible = false;
159− oldApplicationScreenshot.visible = false;
160− }
161−
162− function __focusApplication(application) {
163− if (!application) return
164− if (shouldUseScreenshots) {
165− stage.__focusApplicationUsingScreenshots(application);
166− } else {
167− stage.__focusActualApplication(application);
168− }
169− }
170−
171−
172− function __focusActualApplication(application) {
173− if (application == null) {
174− return;
175− }
176−
177− if (stage.focusedApplication == application) {
178− /* FIXME: this case is reached when showing the sidestage, we
179− need to refocus the side stage app in order to show it.
180− FIXME: this case is reached when doing a right edge swipe
181− while in the dash to bring back the stage.
182− FIXME: this case is reached when showStartingApplicationAnimation
183− finishes after the newly started application has been focused
184− automatically by the ApplicationManager.
185− */
186− if (stage.type == ApplicationInfo.SideStage) {
187− applicationManager.focusApplication(application);
188− }
189− if (!delayedHideScreenshots.running) {
190− hideScreenshotsAfterBriefDelay.start();
191− }
192− } else {
193− /* FIXME: calling ApplicationManager::focusApplication does not focus
194− the application immediately nor show the application's surface
195− immediately. Delay hiding the screenshots until it has done so.
196− */
197− delayedHideScreenshots.stop();
198− applicationManager.focusApplication(application);
199− }
200− stage.focusedApplicationWhenUsingScreenshots = null;
201− }
202−
203− function __focusApplicationUsingScreenshots(application) {
204− delayedHideScreenshots.stop();
205− if (application == null) {
206− return;
207− }
208−
209− if (newApplicationScreenshot.application != null) {
210− stage.focusedApplicationWhenUsingScreenshots = application;
211− return;
212− }
213−
214− newApplicationScreenshot.setApplication(application);
215− newApplicationScreenshot.scheduleUpdate();
216− newApplicationScreenshot.opacity = 1.0;
217− newApplicationScreenshot.x = 0.0;
218− newApplicationScreenshot.y = __getApplicationY(application);
219− newApplicationScreenshot.scale = 1.0;
220− newApplicationScreenshot.visible = true;
221− stage.focusedApplicationWhenUsingScreenshots = application;
222− stage.switchingFromFullscreenToFullscreen = false;
223− }
224−
225− function __getApplicationY(application) {
226− return Qt.binding( function(){
227− return (application && application.fullscreen
228− && application.stage !== ApplicationInfo.SideStage)
229− ? 0 : normalApplicationY;
230− } )
231− }
232−
233− /* FIXME: should hide the screenshots when the focused application's surface
234− is visible. There is no API in QtUbuntu to support that yet.
235− */
236− Connections {
237− target: stage
238− onFocusedApplicationChanged: {
239− if (stage.focusedApplication != null) {
240− /* Move application to the beginning of the list of running applications */
241− var index = stage.__getApplicationIndex(stage.focusedApplication);
242− applicationManager.moveRunningApplicationStackPosition(index, 0, stage.type);
243−
244− var startingApplication = applicationManager.getApplicationFromDesktopFile(
245− stage.__startingApplicationDesktopFile, stage.type);
246−
247− if (stage.focusedApplication == startingApplication) {
248− stage.__startingApplicationDesktopFile = "";
249−
250− /* Screenshots might still be in use at this point and their
251− use can be stopped before delayedHideScreenshots is complete.
252− Prepare for that case by setting appropriately
253− stage.focusedApplicationWhenUsingScreenshots.
254− */
255− stage.focusedApplicationWhenUsingScreenshots = stage.focusedApplication;
256−
257− /* FIXME: should hide the screenshots when the focused application's window
258− is visible. There is no API in qtubuntu to support that yet. Therefore
259− we delay their hiding to avoid a state where neither the screenshot nor
260− the application's window is visible.
261− */
262− delayedHideScreenshots.start();
263− } else {
264− stage.focusedApplicationWhenUsingScreenshots = null;
265− hideScreenshotsAfterBriefDelay.start();
266− }
267− }
268− }
269− }
270−
271− Connections {
272− target: stage.applications
273− onCountChanged: { __discardObsoleteScreenshots(); }
274− ignoreUnknownSignals: true
275− }
276− onFullyHiddenChanged: { __discardObsoleteScreenshots(); }
277− function __discardObsoleteScreenshots() {
278− if (stage.fullyHidden && stage.applications && stage.applications.count == 0) {
279− stage.focusedApplicationWhenUsingScreenshots = undefined;
280− stage.__hideScreenshots();
281− }
282− }
283−
284−
285− SequentialAnimation {
286− id: showStartingApplicationAnimation
287−
288− function prepare(newApplication) {
289− var oldApplication = stage.focusedApplication;
290− newApplicationScreenshot.setApplication(newApplication);
291− newApplicationScreenshot.updateFromCache();
292− oldApplicationScreenshot.setApplication(oldApplication);
293− oldApplicationScreenshot.scheduleUpdate();
294− newApplicationScreenshot.withBackground = true; // FIXME: should be withBackground = newApplication.state == Application.Starting
295− newApplicationScreenshot.y = __getApplicationY(newApplication);
296− oldApplicationScreenshot.y = __getApplicationY(oldApplication);
297− stage.focusedApplicationWhenUsingScreenshots = newApplication;
298− stage.switchingFromFullscreenToFullscreen = false;
299− }
300−
301− PropertyAction {target: newApplicationScreenshot; property: "visible"; value: false}
302− PropertyAction {target: oldApplicationScreenshot; property: "visible"; value: false}
303− PropertyAction {target: newApplicationScreenshot; property: "z"; value: 0}
304− PropertyAction {target: oldApplicationScreenshot; property: "z"; value: 1}
305− PropertyAction {target: newApplicationScreenshot; property: "scale"; value: 0.8}
306− PropertyAction {target: oldApplicationScreenshot; property: "scale"; value: 1.0}
307− PropertyAction {target: newApplicationScreenshot; property: "opacity"; value: 0.0}
308− PropertyAction {target: oldApplicationScreenshot; property: "opacity"; value: 1.0}
309− PropertyAction {target: newApplicationScreenshot; property: "x"; value: 0.0}
310− PropertyAction {target: oldApplicationScreenshot; property: "x"; value: 0.0}
311−
312− ParallelAnimation {
313− PropertyAction {target: newApplicationScreenshot; property: "visible"; value: true}
314− NumberAnimation {
315− target: newApplicationScreenshot
316− property: "scale"
317− duration: 500
318− easing.type: Easing.OutQuad
319− to: 1.0
320− }
321− NumberAnimation {
322− target: newApplicationScreenshot
323− property: "opacity"
324− duration: 500
325− easing.type: Easing.OutQuad
326− to: 1.0
327− }
328−
329− PropertyAction {target: oldApplicationScreenshot; property: "visible"; value: true}
330−
331− NumberAnimation {
332− target: oldApplicationScreenshot
333− property: "x"
334− duration: 400
335− easing.type: Easing.OutQuad
336− to: stage.width
337− }
338− }
339−
340− ScriptAction {
341− script: {
342− // FIXME: only here to support case where application does
343− // not exist yet but is about to
344− if (stage.focusedApplicationWhenUsingScreenshots) {
345− stage.__focusApplication(stage.focusedApplicationWhenUsingScreenshots);
346− }
347− }
348− }
349− }
350−
351−
352− SequentialAnimation {
353− id: switchToApplicationAnimation
354−
355− function prepare(newApplication) {
356− var oldApplication = stage.focusedApplication;
357− newApplicationScreenshot.setApplication(newApplication);
358− newApplicationScreenshot.updateFromCache();
359− oldApplicationScreenshot.setApplication(oldApplication);
360− oldApplicationScreenshot.scheduleUpdate();
361− newApplicationScreenshot.withBackground = false;
362− newApplicationScreenshot.y = __getApplicationY(newApplication);
363− oldApplicationScreenshot.y = __getApplicationY(oldApplication);
364− stage.focusedApplicationWhenUsingScreenshots = newApplication;
365− stage.switchingFromFullscreenToFullscreen = newApplication && newApplication.fullscreen;
366− }
367−
368− PropertyAction {target: newApplicationScreenshot; property: "visible"; value: false}
369− PropertyAction {target: oldApplicationScreenshot; property: "visible"; value: false}
370− PropertyAction {target: newApplicationScreenshot; property: "z"; value: 1}
371− PropertyAction {target: oldApplicationScreenshot; property: "z"; value: 0}
372− PropertyAction {target: newApplicationScreenshot; property: "scale"; value: 1.0}
373− PropertyAction {target: oldApplicationScreenshot; property: "scale"; value: 1.0}
374− PropertyAction {target: newApplicationScreenshot; property: "opacity"; value: 1.0}
375− PropertyAction {target: oldApplicationScreenshot; property: "opacity"; value: 1.0}
376− PropertyAction {target: newApplicationScreenshot; property: "x"; value: stage.width}
377− PropertyAction {target: oldApplicationScreenshot; property: "x"; value: 0.0}
378− PropertyAction {target: newApplicationScreenshot; property: "visible"; value: true}
379− PropertyAction {target: oldApplicationScreenshot; property: "visible"; value: true}
380−
381− ParallelAnimation {
382− NumberAnimation {
383− target: oldApplicationScreenshot
384− property: "scale"
385− duration: 500
386− easing.type: Easing.OutQuad
387− to: 0.8
388− }
389− NumberAnimation {
390− target: oldApplicationScreenshot
391− property: "opacity"
392− duration: 500
393− easing.type: Easing.OutQuad
394− to: 0.0
395− }
396−
397− NumberAnimation {
398− target: newApplicationScreenshot
399− property: "x"
400− duration: 500
401− easing.type: Easing.OutQuad
402− to: 0
403− }
404− }
405−
406− ScriptAction {
407− script: {
408− // move previously focused application to the end of the list of running applications
409− var oldApplication = oldApplicationScreenshot.application;
410− if (oldApplication != null) {
411− var oldApplicationIndex = stage.__getApplicationIndex(oldApplicationScreenshot.application);
412− applicationManager.moveRunningApplicationStackPosition(
413− oldApplicationIndex, stage.applications.count - 1, stage.type);
414− }
415−
416− stage.__focusApplication(stage.focusedApplicationWhenUsingScreenshots);
417− }
418− }
419− }
420−
421−
422− function __dragValueToProgress(dragValue, startValue, applicationsCount) {
423− if (applicationsCount == 0) {
424− return 0;
425− } else if (applicationsCount == 1) {
426− // prevent the current app from moving more than 1/4 of the screen
427− var elasticValue = __elastic(dragValue, startValue/4);
428− return elasticValue / startValue;
429− } else {
430− return dragValue / startValue;
431− }
432− }
433−
434− function __elastic(x, limit) {
435− return limit * ( 1 - Math.pow( ( limit - 1 ) / limit, x ) )
436− }
437−
438− property real __startValue: stage.width
439−
440− AnimationControllerWithSignals {
441− id: switchToApplicationAnimationController
442−
443− onAnimationCompletedAtBeginning: {
444− animation = null;
445− stage.__focusApplication(oldApplicationScreenshot.application);
446− }
447− }
448−
449− EdgeDragEvaluator {
450− id: dragEvaluator
451− trackedPosition: rightEdgeDraggingArea.touchX
452− direction: rightEdgeDraggingArea.direction
453− maxDragDistance: stage.width
454− }
455−
456− EdgeDragArea {
457− id: rightEdgeDraggingArea
458−
459− enabled: {
460− if (status == DirectionalDragArea.WaitingForTouch) {
461− return switchToApplicationAnimationController.completed
462− && stage.applications.count > 0 && stage.rightEdgeEnabled
463− && !delayedHideScreenshots.running
464− } else {
465− return true
466− }
467− }
468− width: units.gu(2)
469− anchors.top: parent.top
470− anchors.bottom: parent.bottom
471− anchors.right: parent.right
472−
473− direction: Direction.Leftwards
474−
475− onDistanceChanged: {
476− if (status !== DirectionalDragArea.Recognized)
477− return
478−
479− var targetProgress = __dragValueToProgress(-distance, __startValue,
480− stage.applications.count)
481− var delta = targetProgress - switchToApplicationAnimationController.progress
482−
483− // When the gesture finally gets recognized, the finger will likely be
484− // reasonably far from the edge. If we made the progress immediately
485− // follow the finger position it would be visually unpleasant as there
486− // would be a jump to meet the finger's current position.
487− //
488− // The trick is not to go all the way (1.0) as it would cause the
489− // aforementioned jump.
490− switchToApplicationAnimationController.progress += 0.4 * delta
491− }
492−
493− property int lastStatus: -1
494−
495− onStatusChanged: {
496− if (status == DirectionalDragArea.Undecided) {
497− onUndecided();
498− } else if (status == DirectionalDragArea.WaitingForTouch) {
499− if (lastStatus == DirectionalDragArea.Undecided) {
500− // got rejected
501− switchToApplicationAnimationController.completeToBeginningWithSignal();
502− } else {
503− onGestureEnded();
504− }
505− }
506− lastStatus = status;
507− }
508−
509− function onUndecided() {
510− dragEvaluator.reset();
511−
512− var nextApplication = null;
513− if (stage.applications.count > 1) {
514− nextApplication = stage.applications.get(1);
515− }
516− switchToApplicationAnimationController.progress = 0
517− switchToApplicationAnimation.prepare(nextApplication);
518− switchToApplicationAnimationController.animation = switchToApplicationAnimation;
519−
520− }
521−
522− function onGestureEnded() {
523− if (stage.applications.count > 1 && dragEvaluator.shouldAutoComplete()) {
524− switchToApplicationAnimationController.completeToEndWithSignal();
525− } else {
526− switchToApplicationAnimationController.completeToBeginningWithSignal();
527− }
528− }
529− }
530−
531−
532− // FIXME: very bad hack to detect when an application was closed or crashed
533− property var __previouslyFocusedApplication
534− Connections {
535− target: stage
536− onFocusedApplicationChanged: {
537− if (stage.focusedApplication == null
538− && __getApplicationIndex(stage.__previouslyFocusedApplication) == -1) {
539− stage.__onFocusedApplicationClosed();
540− }
541− stage.__previouslyFocusedApplication = stage.focusedApplication;
542− }
543− }
544−
545− function __onFocusedApplicationClosed() {
546− if (!stage.shown) {
547− return;
548− }
549−
550− if (stage.applications.count > 0) {
551− // Do not change the focused application from within onFocusedApplicationChanged.
552− // This causes binding loop warnings besides being a bad practice in general
553− // (setting a property from within its "changed" signal handling)
554− // Hence the timer.
555− focusTopmostAppTimer.start();
556− } else {
557− stage.hide();
558− }
559− }
560−
561− Timer {
562− id: focusTopmostAppTimer
563− interval: 1; repeat: false
564− onTriggered: {
565− if (stage.applications.count > 0) {
566− stage.__focusApplication(stage.applications.get(0));
567− }
568− }
569− }
570−
571−}
qml/Dash/CardFilterGrid.qml+2−4
@@ -21,12 +21,10 @@ DashRenderer {
2121 id: genericFilterGrid
2222
2323 expandable: filterGrid.expandable
24− collapsedRowCount: Math.min(2, cardTool && cardTool.template && cardTool.template["collapsed-rows"] || 2)
2524 collapsedHeight: filterGrid.collapsedHeight
26− columns: filterGrid.columns
27− rows: filter ? collapsedRowCount : uncollapsedRowCount
2825 margins: filterGrid.margins
2926 uncollapsedHeight: filterGrid.uncollapsedHeight
27+ originY: filterGrid.originY
3028 verticalSpacing: units.gu(1)
3129 currentItem: filterGrid.currentItem
3230 height: filterGrid.height
@@ -44,7 +42,7 @@ DashRenderer {
4442 verticalSpacing: genericFilterGrid.verticalSpacing
4543 model: genericFilterGrid.model
4644 filter: genericFilterGrid.filter
47− collapsedRowCount: genericFilterGrid.collapsedRowCount
45+ collapsedRowCount: Math.min(2, cardTool && cardTool.template && cardTool.template["collapsed-rows"] || 2)
4846 delegateCreationBegin: genericFilterGrid.delegateCreationBegin
4947 delegateCreationEnd: genericFilterGrid.delegateCreationEnd
5048 delegate: Item {
qml/Dash/DashRenderer.qml+2−6
@@ -23,14 +23,8 @@ Item {
2323 // In case it can be expanded, should we filter it
2424 property bool filter: true
2525
26− property int collapsedRowCount: 1
27−
2826 property int collapsedHeight: height
2927
30− property int columns: 1
31−
32− property int rows: 1
33−
3428 property int margins: 0
3529
3630 property int uncollapsedHeight: height
@@ -39,6 +33,8 @@ Item {
3933
4034 property var delegateCreationEnd: undefined
4135
36+ property real originY: 0
37+
4238 property real verticalSpacing: 0
4339
4440 // The current item of the renderer
qml/Dash/GenericScopeView.qml+8−8
@@ -247,16 +247,16 @@ FocusScope {
247247
248248 if (item && item.hasOwnProperty("delegateCreationBegin")) {
249249 if (baseItem.y + baseItem.height <= 0) {
250− // Not visible (item at top of the list)
251− item.delegateCreationBegin = baseItem.height
252− item.delegateCreationEnd = baseItem.height
250+ // Not visible (item at top of the list viewport)
251+ item.delegateCreationBegin = item.originY + baseItem.height
252+ item.delegateCreationEnd = item.originY + baseItem.height
253253 } else if (baseItem.y >= categoryView.height) {
254− // Not visible (item at bottom of the list)
255− item.delegateCreationBegin = 0
256− item.delegateCreationEnd = 0
254+ // Not visible (item at bottom of the list viewport)
255+ item.delegateCreationBegin = item.originY
256+ item.delegateCreationEnd = item.originY
257257 } else {
258− item.delegateCreationBegin = Math.max(-baseItem.y, 0)
259− item.delegateCreationEnd = Math.min(categoryView.height + item.delegateCreationBegin, baseItem.height)
258+ item.delegateCreationBegin = item.originY + Math.max(-baseItem.y, 0)
259+ item.delegateCreationEnd = item.originY + Math.min(categoryView.height + item.delegateCreationBegin, baseItem.height)
260260 }
261261 }
262262 }
qml/Notifications/NotificationMenuItemFactory.qml+2−1
@@ -66,7 +66,8 @@ Loader {
6666 TextField {
6767 id: textfield
6868
69− inputMethodHints: Qt.ImhNoAutoUppercase
69+ // TODO using Qt.ImhNoPredictiveText here until lp #1291575 is fixed for ubuntu-ui-toolkit
70+ inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText
7071 anchors.left: parent.left; anchors.right: parent.right
7172 echoMode: checkBox.checked ? TextInput.Normal : TextInput.Password
7273 height: units.gu(5)
src/main.cpp+3
@@ -117,6 +117,9 @@ int startShell(int argc, const char** argv, void* server)
117117
118118 QUrl source(::qmlDirectory()+"Shell.qml");
119119 prependImportPaths(view->engine(), ::overrideImportPaths());
120+ if (!isUbuntuMirServer) {
121+ prependImportPaths(view->engine(), ::nonMirImportPaths());
122+ }
120123 appendImportPaths(view->engine(), ::fallbackImportPaths());
121124
122125 view->setSource(source);
tests/CMakeLists.txt+2−2
@@ -1,7 +1,7 @@
1−# QML tests that do not require graphical capabitlies.
1+# QML tests that do not require graphical capabilities.
22add_custom_target(qmlunittests)
33
4−# QML tests that require graphical capabitlies.
4+# QML tests that require graphical capabilities.
55add_custom_target(qmluitests)
66
77add_custom_target(qmltests)
tests/autopilot/unity8/indicators/tests/__init__.py+17
@@ -0,0 +1,17 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity - Indicators Autopilot Test Suite
4+# Copyright (C) 2013, 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/>.
tests/autopilot/unity8/indicators/tests/test_indicators.py+69−13
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
3−# Unity - Indicators Autopilot Test Suite
4−# Copyright (C) 2013 Canonical
3+# Unity Indicators Autopilot Test Suite
4+# Copyright (C) 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -15,20 +15,32 @@
1515#
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/>.
18−#
1918
2019from __future__ import absolute_import
2120
21+from testscenarios import multiply_scenarios
22+
2223from autopilot import platform
23−from testtools import skipIf
2424
2525from unity8.process_helpers import unlock_unity
26−from unity8.shell.tests import UnityTestCase
26+from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
2727
2828
2929class IndicatorTestCase(UnityTestCase):
3030
31− scenarios = [
31+ device_emulation_scenarios = _get_device_emulation_scenarios()
32+
33+ def setUp(self):
34+ if platform.model() == 'Desktop':
35+ self.skipTest('Test cannot be run on the desktop.')
36+ super(IndicatorTestCase, self).setUp()
37+ self.unity_proxy = self.launch_unity()
38+ unlock_unity(self.unity_proxy)
39+
40+
41+class IndicatorExistsTestCase(IndicatorTestCase):
42+
43+ indicator_scenarios = [
3244 ('Bluetooth', dict(indicator_name='indicator-bluetooth')),
3345 ('Datetime', dict(indicator_name='indicator-datetime')),
3446 ('Location', dict(indicator_name='indicator-location')),
@@ -37,14 +49,58 @@ class IndicatorTestCase(UnityTestCase):
3749 ('Power', dict(indicator_name='indicator-power')),
3850 ('Sound', dict(indicator_name='indicator-sound')),
3951 ]
52+ scenarios = multiply_scenarios(
53+ indicator_scenarios,
54+ IndicatorTestCase.device_emulation_scenarios
55+ )
4056
41− @skipIf(platform.image_codename() == 'Desktop',
42− "Unity8/phablet-only test!")
4357 def setUp(self):
44− super(IndicatorTestCase, self).setUp()
58+ super(IndicatorExistsTestCase, self).setUp()
59+ if (platform.model() == 'Nexus 10' and
60+ self.indicator_name == 'indicator-bluetooth'):
61+ self.skipTest('Nexus 10 does not have bluetooth at the moment.')
4562
4663 def test_indicator_exists(self):
47− unity_proxy = self.launch_unity()
48− unlock_unity(unity_proxy)
49− indicator = self.main_window.get_indicator(self.indicator_name)
50− self.assertIsNotNone(indicator)
64+ self.main_window._get_indicator_widget(
65+ self.indicator_name
66+ )
67+
68+
69+class IndicatorPageTitleMatchesWidgetTestCase(IndicatorTestCase):
70+
71+ indicator_scenarios = [
72+ ('Bluetooth', dict(indicator_name='indicator-bluetooth',
73+ title='Bluetooth')),
74+ ('Datetime', dict(indicator_name='indicator-datetime',
75+ title='Upcoming')),
76+ ('Location', dict(indicator_name='indicator-location',
77+ title='Location')),
78+ ('Messaging', dict(indicator_name='indicator-messages',
79+ title='Incoming')),
80+ ('Network', dict(indicator_name='indicator-network',
81+ title='Network')),
82+ ('Power', dict(indicator_name='indicator-power',
83+ title='Battery')),
84+ ('Sound', dict(indicator_name='indicator-sound',
85+ title='Sound')),
86+ ]
87+ scenarios = multiply_scenarios(
88+ indicator_scenarios,
89+ IndicatorTestCase.device_emulation_scenarios
90+ )
91+
92+ def setUp(self):
93+ super(IndicatorPageTitleMatchesWidgetTestCase, self).setUp()
94+ if (platform.model() == 'Nexus 10' and
95+ self.indicator_name == 'indicator-bluetooth'):
96+ self.skipTest('Nexus 10 does not have bluetooth at the moment.')
97+
98+ def test_indicator_page_title_matches_widget(self):
99+ """Swiping open an indicator must show its correct title.
100+
101+ See https://bugs.launchpad.net/ubuntu-ux/+bug/1253804 .
102+ """
103+ indicator_page = self.main_window.open_indicator_page(
104+ self.indicator_name)
105+ self.assertTrue(indicator_page.visible)
106+ self.assertEqual(indicator_page.title, self.title)
tests/autopilot/unity8/shell/emulators/__init__.py+2−6
@@ -17,16 +17,12 @@
1717# along with this program. If not, see <http://www.gnu.org/licenses/>.
1818#
1919
20−from autopilot import input, introspection
20+from ubuntuuitoolkit import emulators as toolkit_emulators
2121
2222
23−class UnityEmulatorBase(introspection.CustomEmulatorBase):
23+class UnityEmulatorBase(toolkit_emulators.UbuntuUIToolkitEmulatorBase):
2424 """A base class for all unity emulators."""
2525
26− def __init__(self, *args):
27− super(UnityEmulatorBase, self).__init__(*args)
28− self.pointing_device = input.Pointer(device=input.Touch.create())
29−
3026
3127class UnityEmulatorException(Exception):
3228 """Exception raised when there is an error with the Unity emulators."""
tests/autopilot/unity8/shell/emulators/dash.py+24−1
@@ -23,6 +23,8 @@ from unity8.shell import emulators
2323
2424from autopilot import logging as autopilot_logging
2525from autopilot.introspection import dbus
26+from testtools.matchers import MatchesAny, Equals
27+from ubuntuuitoolkit import emulators as toolkit_emulators
2628
2729
2830logger = logging.getLogger(__name__)
@@ -132,6 +134,19 @@ class Dash(emulators.UnityEmulatorBase):
132134 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
133135 self.dash_content_list.currentIndex.wait_for(original_index + 1)
134136
137+ def enter_search_query(self, query):
138+ search_text_field = self._get_search_text_field()
139+ search_text_field.write(query)
140+ search_text_field.state.wait_for('idle')
141+
142+ def _get_search_text_field(self):
143+ page_header = self._get_page_header()
144+ search_container = page_header.select_single(
145+ 'QQuickItem', objectName='searchContainer')
146+ search_container.state.wait_for(
147+ MatchesAny(Equals('narrowActive'), Equals('active')))
148+ return search_container.select_single(toolkit_emulators.TextField)
149+
135150
136151class GenericScopeView(emulators.UnityEmulatorBase):
137152 """Autopilot emulator for generic scopes."""
@@ -142,6 +157,7 @@ class GenericScopeView(emulators.UnityEmulatorBase):
142157
143158 :parameter category: The name of the category where the application is.
144159 :app_name: The name of the application.
160+ :return: The opened preview.
145161
146162 """
147163 category_element = self._get_category_element(category)
@@ -150,8 +166,11 @@ class GenericScopeView(emulators.UnityEmulatorBase):
150166 # Some categories do not show previews, like recent apps.
151167 # --elopio - 2014-1-14
152168 self.pointing_device.click_object(icon)
153− return self.get_root_instance().wait_select_single(
169+ preview_list = self.get_root_instance().wait_select_single(
154170 'PreviewListView', objectName='dashContentPreviewList')
171+ preview_list.x.wait_for(0)
172+ return preview_list.select_single(
173+ Preview, objectName='preview{}'.format(preview_list.currentIndex))
155174
156175 def _get_category_element(self, category):
157176 try:
@@ -180,3 +199,7 @@ class DashApps(GenericScopeView):
180199 if card.objectName != 'cardToolCard':
181200 result.append(card)
182201 return result
202+
203+
204+class Preview(emulators.UnityEmulatorBase):
205+ """Autopilot custom proxy object for generic previews."""
tests/autopilot/unity8/shell/emulators/main_window.py+32−2
@@ -20,6 +20,7 @@
2020import logging
2121
2222from autopilot import logging as autopilot_logging
23+from autopilot import input
2324
2425from unity8.shell import emulators
2526from unity8.shell.emulators.greeter import Greeter
@@ -87,12 +88,32 @@ class QQuickView(emulators.UnityEmulatorBase):
8788 def get_pinentryField(self):
8889 return self.select_single(objectName="pinentryField")
8990
90− def get_indicator(self, indicator_name):
91− return self.wait_select_single(
91+ def _get_indicator_widget(self, indicator_name):
92+ return self.select_single(
9293 'DefaultIndicatorWidget',
9394 objectName=indicator_name+'-widget'
9495 )
9596
97+ def _get_indicator_page(self, indicator_name):
98+ return self.select_single(
99+ 'DefaultIndicatorPage',
100+ objectName=indicator_name+'-page'
101+ )
102+
103+ @autopilot_logging.log_action(logger.info)
104+ def open_indicator_page(self, indicator_name):
105+ """Swipe to open the indicator, wait until it's open.
106+
107+ :returns: The indicator page.
108+ """
109+ widget = self._get_indicator_widget(indicator_name)
110+ start_x, start_y = input.get_center_point(widget)
111+ end_x = start_x
112+ end_y = self.height
113+ self.pointing_device.drag(start_x, start_y, end_x, end_y)
114+ self.wait_select_single('Indicators', fullyOpened=True)
115+ return self._get_indicator_page(indicator_name)
116+
96117 def get_shell_background(self):
97118 return self.select_single(
98119 "CrossFadeImage", objectName="backgroundImage")
@@ -113,3 +134,12 @@ class QQuickView(emulators.UnityEmulatorBase):
113134 def get_current_focused_app_id(self):
114135 """Return the id of the focused application."""
115136 return self.select_single('Shell').focusedApplicationId
137+
138+ @autopilot_logging.log_action(logger.info)
139+ def search(self, query):
140+ search_indicator = self._get_search_indicator()
141+ self.pointing_device.click_object(search_indicator)
142+ self.get_dash().enter_search_query(query)
143+
144+ def _get_search_indicator(self):
145+ return self.select_single('SearchIndicator', objectName='search')
tests/autopilot/unity8/shell/tests/test_emulators.py+24−6
@@ -39,6 +39,22 @@ from unity8.shell import emulators, fixture_setup, tests
3939from unity8.shell.emulators import dash as dash_emulators
4040
4141
42+class MainWindowTestCase(tests.UnityTestCase):
43+
44+ scenarios = tests._get_device_emulation_scenarios()
45+
46+ def setUp(self):
47+ super(MainWindowTestCase, self).setUp()
48+ unity_proxy = self.launch_unity()
49+ process_helpers.unlock_unity(unity_proxy)
50+
51+ def test_search(self):
52+ self.main_window.search('Test')
53+ text_field = self.main_window.get_dash()._get_search_text_field()
54+ self.assertEqual(text_field.text, 'Test')
55+ self.assertEqual(text_field.state, 'idle')
56+
57+
4258class DashBaseTestCase(tests.UnityTestCase):
4359
4460 scenarios = tests._get_device_emulation_scenarios()
@@ -141,7 +157,9 @@ class GenericScopeViewEmulatorTestCase(DashBaseTestCase):
141157
142158 def test_open_preview(self):
143159 preview = self.generic_scope.open_preview('0', 'Title.0.0')
144− preview.x.wait_for(0)
160+ self.assertIsInstance(preview, dash_emulators.Preview)
161+ self.assertTrue(preview.isCurrent)
162+
145163
146164class DashAppsEmulatorTestCase(DashBaseTestCase):
147165
@@ -185,8 +203,8 @@ class DashAppsEmulatorTestCase(DashBaseTestCase):
185203 category_element = self.applications_scope._get_category_element(
186204 category)
187205 grid = category_element.select_single('CardFilterGrid')
188− return grid.columns * grid.rows
189−
190− def test_open_preview(self):
191− preview = self.applications_scope.open_preview('2', 'Title.2.1')
192− preview.x.wait_for(0)
206+ filtergrid = grid.select_single('FilterGrid')
207+ if (grid.filter):
208+ return filtergrid.collapsedRowCount * filtergrid.columns
209+ else:
210+ return filtergrid.uncollapsedRowCount * filtergrid.columns
tests/autopilot/unity8/shell/tests/test_system_integration.py+3−2
@@ -22,6 +22,7 @@
2222import subprocess
2323import unittest
2424
25+from autopilot import platform
2526from unity8.shell.emulators import UnityEmulatorBase
2627from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
2728
@@ -31,10 +32,10 @@ class SystemIntegrationTests(UnityTestCase):
3132
3233 scenarios = _get_device_emulation_scenarios()
3334
34− @unittest.skip("Disabled until we can investigate jenkins failure")
35+ @unittest.skipIf(platform.model() == "Desktop", "Test is broken on otto, see bug 1281634.")
3536 def test_networkmanager_integration(self):
3637 self.launch_unity()
3738
3839 # invoke policykit to check permissions
39− pid = subprocess.check_output("pidof -s unity8", shell=True)
40+ pid = subprocess.check_output(["pidof", "-s", "unity8"], universal_newlines=True)
4041 subprocess.check_call("pkcheck --action-id org.freedesktop.NetworkManager.enable-disable-network --process " + pid, shell=True)
tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp+3
@@ -54,6 +54,9 @@ QImage ApplicationScreenshotProvider::requestImage(const QString &imageId, QSize
5454
5555 if (app->stage() == ApplicationInfo::SideStage) {
5656 QByteArray gus = qgetenv("GRID_UNIT_PX");
57+ if (gus.isEmpty() || gus.toInt() == 0) {
58+ gus = "8";
59+ }
5760 image = image.scaledToWidth(gus.toInt() * 48);
5861 } else {
5962 // Lets scale main stage applications to be the size of the screen/window.
tests/mocks/Unity/Application/CMakeLists.txt+14
@@ -35,3 +35,17 @@ install(TARGETS FakeUnityApplicationQml
3535install(FILES qmldir InputFilterArea.qml OSKController.qml
3636 DESTINATION ${SHELL_INSTALL_QML}/mocks/Unity/Application
3737 )
38+
39+# Duplicate the mock to nonmirplugins
40+# In shadow builds we just link it, in real installs we also install it to the other path
41+add_custom_target(OSKControllerQmlFile2 ALL
42+ COMMAND mkdir -p ${CMAKE_BINARY_DIR}/nonmirplugins/Unity && rm -f ${CMAKE_BINARY_DIR}/nonmirplugins/Unity/Application && ln -s ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}/nonmirplugins/Unity
43+ DEPENDS qmldir
44+)
45+install(TARGETS FakeUnityApplicationQml
46+ DESTINATION ${SHELL_INSTALL_QML}/nonmirplugins/Unity/Application
47+ )
48+
49+install(FILES qmldir InputFilterArea.qml OSKController.qml
50+ DESTINATION ${SHELL_INSTALL_QML}/nonmirplugins/Unity/Application
51+ )
tests/plugins/Ubuntu/Gestures/CMakeLists.txt+2−11
@@ -15,20 +15,11 @@ add_custom_target(UbuntuGesturesTestQmlFiles ALL
1515add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
1616
1717macro(add_gesture_ui_test CLASSNAME)
18− set(testCommand
19− LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures
20− ${CMAKE_CURRENT_BINARY_DIR}/${CLASSNAME}TestExec
21− -o ${CMAKE_BINARY_DIR}/${CLASSNAME}Test.xml,xunitxml
22− -o -,txt)
23−
24− add_custom_target(test${CLASSNAME} ${testCommand})
25− add_dependencies(qmluitests test${CLASSNAME})
26− add_dependencies(test${CLASSNAME} ${CLASSNAME}TestExec UbuntuGesturesTestQmlFiles)
27−
2818 add_executable(${CLASSNAME}TestExec tst_${CLASSNAME}.cpp GestureTest.cpp)
2919 qt5_use_modules(${CLASSNAME}TestExec Test Core Qml Gui Quick)
3020 target_link_libraries(${CLASSNAME}TestExec UbuntuGestureQml)
31− add_manual_qml_test(. ${CLASSNAME} IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
21+
22+ add_binary_qml_test(${CLASSNAME} ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures UbuntuGesturesTestQmlFiles)
3223endmacro(add_gesture_ui_test)
3324
3425macro(add_gesture_test CLASSNAME)
tests/qmltests/CMakeLists.txt−4
@@ -21,7 +21,6 @@ set(qmltest_DEFAULT_PROPERTIES "")
2121
2222add_qml_test(. Shell IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks
2323 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
24−add_manual_qml_test(Components DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
2524add_qml_test(Components Carousel)
2625add_qml_test(Components DraggingArea)
2726add_qml_test(Components EdgeDemoOverlay)
@@ -33,9 +32,6 @@ add_qml_test(Components ResponsiveGridView)
3332add_qml_test(Components Revealer)
3433add_qml_test(Components SeeMore)
3534add_qml_test(Components Showable)
36−add_qml_test(Components Stage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
37− ${CMAKE_BINARY_DIR}/tests/mocks
38− ${CMAKE_BINARY_DIR}/plugins)
3935add_qml_test(Components PageHeaderLabel)
4036add_qml_test(Dash Dash IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
4137add_qml_test(Dash DashContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
tests/qmltests/Components/CMakeLists.txt+2−10
@@ -6,19 +6,11 @@ include_directories(
66 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
77 )
88
9−set(testCommand
10− LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures
11− ${CMAKE_CURRENT_BINARY_DIR}/DragHandleTestExec
12− -o ${CMAKE_BINARY_DIR}/DragHandleTest.xml,xunitxml
13− -o -,txt)
14−
15−add_custom_target(testDragHandle ${testCommand})
16−add_dependencies(qmluitests testDragHandle)
17−add_dependencies(testDragHandle DragHandleTestExec)
18−
199add_executable(DragHandleTestExec tst_DragHandle.cpp)
2010qt5_use_modules(DragHandleTestExec Test Core Qml Gui Quick)
2111target_link_libraries(DragHandleTestExec UbuntuGestureQml)
2212
13+add_binary_qml_test(DragHandle ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures "")
14+
2315add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
2416add_definitions(-DTEST_DIR="${CMAKE_CURRENT_LIST_DIR}")
tests/qmltests/Components/tst_LazyImage.qml+1
@@ -152,6 +152,7 @@ Rectangle {
152152
153153 function test_lazyimage(data) {
154154 data.func();
155+ waitForRendering(baseRect);
155156
156157 if (data.transition) {
157158 // wait for the transition to complete
tests/qmltests/Components/tst_Stage.qmldeleted−278
@@ -1,278 +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 ".."
20−import "../../../qml/Components"
21−import Unity.Application 0.1
22−import Ubuntu.Components 0.1
23−import Unity.Test 0.1 as UT
24−import "tst_Stage"
25−
26−Rectangle {
27− width: units.gu(70)
28− height: stageRect.height
29−
30− // Even though we replace the ApplicationScreenshot instances in Stage
31− // with our own fake ones, ApplicationScreenshot.qml still gives out a warning
32− // if shell.importUbuntuApplicationAvailable is missing.
33− // For we have this here for the sake of keeping a clean log output.
34− Item {
35− id: shell
36− property bool importUbuntuApplicationAvailable: false
37− }
38−
39− // A fake ApplicationManager implementation to be passed to Stage
40− QtObject {
41− id: fakeAppManager
42− property ListModel mainStageApplications: ListModel {}
43− property ListModel sideStageApplications: ListModel {}
44− property var mainStageFocusedApplication
45−
46− property Component fakeAppWindowComponent: Component {
47− Rectangle {
48− width: stage.width
49− height: stage.height
50− property alias text : txt.text
51− Text {id:txt}
52− }
53− }
54−
55− function activateApplication(desktopFile, argument) {
56− var appWindow = fakeAppWindowComponent.createObject(fakeWindowContainer)
57− var application = {
58− 'icon': "foo",
59− 'handle': desktopFile,
60− 'name': "Foo",
61− 'fullscreen': false,
62− 'desktopFile': desktopFile,
63− 'stage': ApplicationInfo.MainStage,
64− 'argument': 0,
65− 'color': desktopFile,
66− 'window': appWindow
67− };
68− appWindow.color = application.color
69− appWindow.text = desktopFile + " actual";
70−
71− mainStageApplications.append(application)
72− updateZOrderOfWindows(mainStageApplications)
73−
74− return application
75− }
76−
77− function focusApplication(application) {
78− mainStageFocusedApplication = application
79− }
80−
81− function getApplicationFromDesktopFile(desktopFile, stageType) {
82− var sideStage = (stage == ApplicationInfo.SideStage);
83− var applications = sideStage ? sideStageApplications
84− : mainStageApplications;
85−
86− for (var i = 0; i < applications.count; i++ ) {
87− var application = applications.get(i);
88− if (application.desktopFile === desktopFile) {
89− return application;
90− }
91− }
92− return null;
93− }
94−
95− function moveRunningApplicationStackPosition(from, to, stage) {
96− var sideStage = (stage == ApplicationInfo.SideStage);
97− var applications = sideStage ? sideStageApplications
98− : mainStageApplications;
99−
100− if (from !== to && applications.count > 0 && from >= 0 && to >= 0) {
101− applications.move(from, to, 1);
102− }
103−
104− updateZOrderOfWindows(applications)
105− }
106−
107− function updateZOrderOfWindows(applications) {
108− var nextZ = 100
109− for (var i = 0; i < applications.count; i++ ) {
110− var application = applications.get(i);
111− application.window.z = nextZ--;
112− }
113− }
114−
115− function deacticateApplication(desktopFile) {
116− for (var i = 0; i < mainStageApplications.count; i++ ) {
117− var application = mainStageApplications.get(i)
118− if (application.desktopFile === desktopFile) {
119− focusApplication(null)
120− application.window.destroy();
121− mainStageApplications.remove(i)
122− updateZOrderOfWindows(mainStageApplications)
123− return;
124− }
125− }
126− }
127− }
128−
129− Rectangle {
130− id: stageRect
131− x:0
132− y:0
133− width: childrenRect.width
134− height: childrenRect.height
135−
136− color: "grey"
137−
138− // This is where the fake windows are held.
139− // They stay behind the stage, so that the stage's screenshots are shown
140− // on top of them
141− // On a real usage scenario, the current application's surface is composited behind
142− // the shell's surface (where Stage lives). fakeWindowContainer simulates this stacking
143− Item {
144− id: fakeWindowContainer
145− anchors.fill: parent
146− }
147−
148−
149− // A black rectangle behind the stage so that the window switch animations
150− // look good, just like in Stage's real usage.
151− Rectangle {
152− anchors.fill: parent
153− color: "black"
154− visible: stage.usingScreenshots
155− }
156−
157− Stage {
158− id: stage
159− y: 0
160− shouldUseScreenshots: false
161− applicationManager: fakeAppManager
162− rightEdgeDraggingAreaWidth: units.gu(2)
163− fullyShown: true
164− fullyHidden: false
165− newApplicationScreenshot: FakeApplicationScreenshot {
166− id: newAppScreenshot
167− parent: stage
168− width: stage.width
169− height: stage.height - stage.y}
170− oldApplicationScreenshot: FakeApplicationScreenshot {
171− id: oldAppScreenshot
172− parent: stage
173− width: stage.width
174− height: stage.height - stage.y}
175− }
176− }
177−
178− Rectangle {
179− id: controlsRect
180− anchors.top: parent.top
181− anchors.bottom: parent.bottom
182− anchors.left: stageRect.right
183− anchors.right: parent.right
184− color: "lightgrey"
185−
186− Column {
187− id: controls
188− spacing: units.gu(1)
189− AppControl {id: redControl; desktopFile:"red"}
190− AppControl {id: greenControl; desktopFile:"green"}
191− AppControl {id: blueControl; desktopFile:"blue"}
192− }
193− }
194−
195− UT.UnityTestCase {
196− name: "Stage"
197− when: windowShown
198−
199− function isCurrentAppFadingOut() {
200− // it should get a bit translucent and smaller
201− return oldAppScreenshot.opacity < 0.99
202− && oldAppScreenshot.opacity >= 0.1
203− && oldAppScreenshot.scale < 0.99
204− && oldAppScreenshot.scale >= 0.1
205− && oldAppScreenshot.visible
206− }
207−
208− function init() {
209− redControl.checked = false;
210− greenControl.checked = false;
211− blueControl.checked = false;
212− // give some room for animations to start
213− wait(50)
214− // wait until animations end, if any
215− tryCompare(stage, "usingScreenshots", false)
216− }
217−
218− /* If you flick from the right edge of the stage leftwards it should cause an
219− application switch. */
220− function test_dragFromRightEdgeToSwitchApplication() {
221− redControl.checked = true
222−
223− tryCompare(stage, "usingScreenshots", true) // wait for the animation to start
224− tryCompare(stage, "usingScreenshots", false) // and then for it to end
225− compare(fakeAppManager.mainStageFocusedApplication.desktopFile, "red")
226− compare(fakeAppManager.mainStageApplications.get(0).desktopFile, "red")
227−
228− greenControl.checked = true
229−
230− tryCompare(stage, "usingScreenshots", true) // wait for the animation to start
231− tryCompare(stage, "usingScreenshots", false) // and then for it to end
232− compare(fakeAppManager.mainStageFocusedApplication.desktopFile, "green")
233− compare(fakeAppManager.mainStageApplications.get(0).desktopFile, "green")
234−
235− var touchX = stage.width - (stage.rightEdgeDraggingAreaWidth / 2)
236− var touchY = stage.height / 2
237− touchFlick(stage, touchX, touchY, stage.width * 0.25, touchY)
238−
239− // wait until animations end, if any
240− tryCompare(stage, "usingScreenshots", false)
241−
242− // "red" should be the new topmost, focused, application
243− compare(fakeAppManager.mainStageFocusedApplication.desktopFile, "red")
244− compare(fakeAppManager.mainStageApplications.get(0).desktopFile, "red")
245− }
246−
247− /* When an application is launched, it needs a background before it's drawn on screen
248− so that the user does not see the previous running app while the new one is launching.
249− When switching between applications, backgrounds are unnecessary, 'cause the
250− applications are in front of them. */
251− function test_background() {
252− redControl.checked = true
253− tryCompare(stage, "usingScreenshots", true) // wait for the animation to start
254−
255− compare(newAppScreenshot.withBackground, true, "starting app screenshot does not have background enabled")
256−
257− tryCompare(stage, "usingScreenshots", false) // wait for the animation to finish
258−
259− greenControl.checked = true
260− tryCompare(stage, "usingScreenshots", true) // wait for the animation to start
261− tryCompare(stage, "usingScreenshots", false) // and finish
262−
263− var draggingAreaCenterX = stage.width - (stage.rightEdgeDraggingAreaWidth / 2)
264− var draggingAreaCenterY = stage.height / 2
265− var finalTouchX = draggingAreaCenterX - units.gu(5)
266− touchFlick(stage, draggingAreaCenterX, draggingAreaCenterY,
267− finalTouchX, draggingAreaCenterY,
268− true /* beginTouch */, false /* endTouch */)
269−
270− // wait for the animation to start
271− tryCompare(stage, "usingScreenshots", true)
272−
273− compare(newAppScreenshot.withBackground, false, "switched app does have background enabled")
274−
275− touchRelease(stage, finalTouchX, draggingAreaCenterY)
276− }
277− }
278−}
tests/qmltests/Components/tst_Stage/AppControl.qmldeleted−42
@@ -1,42 +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 Ubuntu.Components 0.1
19−
20−Row {
21− id: root
22− property string desktopFile
23− spacing: units.gu(1)
24−
25− property alias checked: checkbox.checked
26−
27− Label {text: root.desktopFile
28− anchors.verticalCenter: parent.verticalCenter
29− width:units.gu(5)}
30−
31− CheckBox {
32− id: checkbox
33− onCheckedChanged: {
34− if (checked) {
35− var app = fakeAppManager.activateApplication(root.desktopFile)
36− stage.activateApplication(root.desktopFile)
37− } else {
38− fakeAppManager.deacticateApplication(root.desktopFile)
39− }
40− }
41− }
42−}
tests/qmltests/Components/tst_Stage/FakeApplicationScreenshot.qmldeleted−53
@@ -1,53 +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− property var application
21− property bool withBackground: true
22− property bool ready: application != undefined
23−
24− function setApplication(app) {
25− application = app
26− }
27−
28− function clearApplication() {
29− setApplication(undefined)
30− }
31−
32− function scheduleUpdate() {}
33−
34− function updateFromCache() {}
35−
36− Rectangle {
37− id: rect
38− anchors.fill: parent
39− Text {id:text}
40− }
41−
42− onApplicationChanged: {
43− if (application) {
44− rect.color = application.color
45− text.text = application.desktopFile + " screenshot"
46− rect.visible = true
47− } else {
48− rect.color = "white"
49− text.text = "<NULL> screenshot"
50− rect.visible = false
51− }
52− }
53−}
tests/qmltests/Dash/tst_GenericScopeView.qml+1
@@ -67,6 +67,7 @@ Item {
6767 when: scopes.loaded
6868
6969 function init() {
70+ genericScopeView.scope = scopes.get(2)
7071 shell.width = units.gu(120)
7172 genericScopeView.categoryView.positionAtBeginning();
7273 tryCompare(genericScopeView.categoryView, "contentY", 0)
tests/qmltests/SideStage/tst_SideStage.qmldeleted−52
@@ -1,52 +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 Unity.Test 0.1 as UT
20−import ".."
21−import "../../../qml/SideStage"
22−import Ubuntu.Components 0.1
23−
24−UT.UnityTestCase {
25− name: "SideStage"
26−
27− SideStage {
28− id: sideStage
29− width: units.gu(30)
30− height: units.gu(30)
31− handleExpanded: sideStageRevealer.pressed
32− handleSizeCollapsed: units.gu(2)
33− handleSizeExpanded: units.gu(5)
34− }
35−
36− function test_handle_data() {
37− return [
38− {tag: "expanded", expanded: true},
39− {tag: "collapsed", expanded: false}
40− ]
41− }
42−
43− function test_handle(data) {
44− sideStage.handleExpanded = data.expanded
45−
46− if (data.expanded) {
47− tryCompare(findChild(sideStage, "sideStageHandle"), "width", sideStage.handleSizeExpanded);
48− } else {
49− tryCompare(findChild(sideStage, "sideStageHandle"), "width", sideStage.handleSizeCollapsed);
50− }
51− }
52−}
tests/qmltests/tst_Shell.qml+1−1
@@ -192,7 +192,7 @@ Item {
192192 verify(mainAppId != "");
193193 var mainApp = ApplicationManager.findApplication(mainAppId);
194194 verify(mainApp);
195− tryCompare(mainApp.state, ApplicationInfo.Running);
195+ tryCompare(mainApp, "state", ApplicationInfo.Running);
196196
197197 // Try to suspend while proximity is engaged...
198198 Powerd.displayPowerStateChange(Powerd.Off, Powerd.UseProximity);
tools/CMakeLists.txt+2
@@ -9,3 +9,5 @@ qt5_use_modules(${SCOPE_TOOL} Qml Quick)
99install(TARGETS ${SCOPE_TOOL}
1010 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1111 )
12+
13+install(FILES unlock-device DESTINATION ${SHELL_APP_DIR})
tools/scopetool.cpp+1
@@ -88,6 +88,7 @@ int main(int argc, char *argv[])
8888
8989 QUrl source(::qmlDirectory() + "ScopeTool.qml");
9090 prependImportPaths(view->engine(), ::overrideImportPaths());
91+ prependImportPaths(view->engine(), ::nonMirImportPaths());
9192 appendImportPaths(view->engine(), ::fallbackImportPaths());
9293
9394 view->setSource(source);
tools/unlock-devicenew file+42
@@ -0,0 +1,42 @@
1+#!/bin/bash
2+# -*- Mode: sh; indent-tabs-mode: nil; tab-width: 4 -*-
3+
4+# Our goal here is to get an Ubuntu Touch device into a testable unlocked state.
5+# This will include a reboot.
6+
7+WAIT_COMMAND="sleep 20"
8+
9+while getopts s:w: opt; do
10+ case $opt in
11+ s)
12+ export ANDROID_SERIAL=$OPTARG
13+ ;;
14+ w)
15+ WAIT_COMMAND=$OPTARG
16+ ;;
17+ esac
18+done
19+
20+UNLOCK_SCRIPT='
21+import dbus, logging;
22+from unity8 import process_helpers as helpers;
23+logging.basicConfig(level=logging.INFO);
24+bus = dbus.SystemBus().get_object("com.canonical.powerd", "/com/canonical/powerd");
25+cookie = bus.requestSysState("unlock-device-hold", 1, dbus_interface="com.canonical.powerd");
26+helpers.restart_unity_with_testability();
27+bus.clearSysState(cookie, dbus_interface="com.canonical.powerd");
28+helpers.unlock_unity()
29+'
30+
31+adb reboot
32+sleep 5
33+adb "wait-for-device"
34+eval "$WAIT_COMMAND"
35+UNLOCK_OUTPUT=$(adb shell "sudo -u phablet -i python3 -c '$UNLOCK_SCRIPT'" 2>&1)
36+if echo "$UNLOCK_OUTPUT" | grep 'Greeter unlocked' >/dev/null; then
37+ echo "I: Unlock passed"
38+ exit 0
39+else
40+ echo "I: Unlock failed, script output: '$UNLOCK_OUTPUT'"
41+ exit 1
42+fi