on xenial help sign in
Merge trunk.
commitf9a51e017f1faa7bdb4c5848590d5ed5d0e4ea1e authorYing-Chun Liu <paul.liu@canonical.com> dateSat 26 Jul 2014, 00:36 (12 years ago) parente6c322a31927c6
60 files changed+1244−757
tests/autopilot/.project → .project+1−1 tests/autopilot/.pydevproject → .pydevproject+3−1 .settings/Autopilot List.launch+14 .settings/Autopilot Run.launch+14 debian/changelog+74 debian/control+6−2 debian/rules+7 plugins/Dash/ScopeStyle.qml+6 plugins/Dash/listviewwithpageheader.cpp+1−6 plugins/Ubuntu/Payments/CMakeLists.txt+1−1 plugins/Unity/Launcher/launchermodel.cpp+3−2 po/da.po+52−49 po/gd.po+3−3 po/gl.po+4−4 po/hu.po+24−22 po/is.po+22−17 po/sl.po+11−11 po/sv.po+19−18 po/ug.po+1−1 po/unity8.pot+17−9 qml/Components/Background.qml+77 qml/Components/FilterGrid.qml−124 qml/Components/ListItems/Header.qml+17−26 qml/Components/Lockscreen.qml+17−5 qml/Components/PageHeader.qml+6−1 qml/Components/ResponsiveGridView.qml+2−1 qml/Dash/CardCarousel.qml+2−7 qml/Dash/CardFilterGrid.qml → qml/Dash/CardGrid.qml+22−22 qml/Dash/CardVerticalJournal.qml+3−21 qml/Dash/DashRenderer.qml+3−10 qml/Dash/GenericScopeView.qml+132−64 qml/Dash/PreviewListView.qml+1−3 qml/Greeter/Greeter.qml+1−1 qml/Shell.qml+84−27 qml/Stages/PhoneStage.qml+13−1 src/main.cpp+1−1 tests/autopilot/unity8/shell/emulators/dash.py+12−6 tests/autopilot/unity8/shell/tests/test_emulators.py+15−5 tests/autopilot/unity8/shell/tests/test_upstart.py+13 tests/mocks/LightDM/single-pin/GreeterPrivate.cpp+1−9 tests/mocks/QMenuModel/unitymenumodel.cpp+5 tests/mocks/QMenuModel/unitymenumodel.h+4 tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−9 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+1 tests/mocks/libusermetrics/UserMetrics.cpp+3 tests/plugins/Dash/tst_ScopeStyle.qml+27−2 tests/plugins/Unity/Indicators/unitymenumodelstacktest.cpp+3 tests/qmltests/CMakeLists.txt+4−4 tests/qmltests/Components/tst_Background.qml+90 tests/qmltests/Components/tst_FilterGrid.qml−190 tests/qmltests/Dash/tst_Dash.qml+1−1 tests/qmltests/Dash/tst_DashContent.qml+15−6 tests/qmltests/Dash/tst_GenericScopeView.qml+137−49 tests/qmltests/Greeter/tst_Lockscreen.qml+1−1 tests/qmltests/tst_Shell.qml+19 tests/qmltests/tst_ShellWithPin.qml+203
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>
debian/changelog+74
@@ -1,3 +1,77 @@
1+unity8 (7.90+14.10.20140725-0ubuntu1) utopic; urgency=low
2+
3+ [ CI bot ]
4+ * Resync trunk
5+
6+ [ Michał Sawicz ]
7+ * Fix the ap test for applications.
8+
9+ [ Albert Astals ]
10+ * Use deleteLater instead of a direct delete We are seeing a crash in
11+ QQuickWindowPrivate::polishItems because LVWPH is deleting items to
12+ polish from it's updatePolish which means the set in
13+ QQuickWindowPrivate::polishItems may end up with some yet-to-
14+ process-but-now-deleted items. Switching to deleteLater fixes this
15+
16+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 25 Jul 2014 10:47:34 +0000
17+
18+unity8 (7.90+14.10.20140724.1-0ubuntu1) utopic; urgency=low
19+
20+ [ Michael Zanetti ]
21+ * properly parent launcher items (LP: #1347902)
22+
23+ [ Michał Sawicz ]
24+ * Move the PyDev project files to the root, supporting .py scripts
25+ outside of tests/autopilot. Add Autopilot Run and List launch
26+ configurations to easily support debugging in Eclipse. Use
27+ add_unity8_mock macro in the Telephony plugin.
28+ * Drop FilterGrid and refactor height animations in GenericScopeView.
29+ Also implement forced category expansion. (LP: #1326470)
30+ * Move expansion button from section header to category footer. (LP:
31+ #1261300)
32+ * Fix expect-sigstop enviroment variable name. (LP: #1346819)
33+ * Make headerless categories easier Instead of having no header
34+ category (which is a bit confusing since the LVWPH code was designed
35+ so that when a category has no header it is because it shares the
36+ category with the previous one) what we have for headerless
37+ categories is a header of height 0, this way everything works as it
38+ should and results in cleaner code in the LVWPH and in
39+ GenericScopeView
40+ * Add support for header links.
41+ * Add dash PageHeader styling.
42+
43+ [ Albert Astals ]
44+ * Make headerless categories easier Instead of having no header
45+ category (which is a bit confusing since the LVWPH code was designed
46+ so that when a category has no header it is because it shares the
47+ category with the previous one) what we have for headerless
48+ categories is a header of height 0, this way everything works as it
49+ should and results in cleaner code in the LVWPH and in
50+ GenericScopeView
51+
52+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 24 Jul 2014 20:41:29 +0000
53+
54+unity8 (7.90+14.10.20140723.4-0ubuntu1) utopic; urgency=low
55+
56+ [ thomas-voss ]
57+ * Explicitly select gcc version.
58+
59+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 23 Jul 2014 15:32:41 +0000
60+
61+unity8 (7.90+14.10.20140721.1-0ubuntu1) utopic; urgency=low
62+
63+ [ Michael Terry ]
64+ * Allow running the dialer-app in emergency mode when the screen is
65+ locked.
66+
67+ [ Michał Sawicz ]
68+ * Add missing nameOwner property to mock UnityMenuModel.
69+
70+ [ Albert Astals ]
71+ * Fix name, There's nothing called pageHeader in this file
72+
73+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 21 Jul 2014 14:57:08 +0000
74+
175unity8 (7.90+14.10.20140717.3-0ubuntu1) utopic; urgency=low
276
377 [ Nick Dedekind ]
debian/control+6−2
@@ -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,7 +19,7 @@ Build-Depends: cmake,
1519 libgsettings-qt-dev,
1620 libhardware-dev,
1721 libhud-client2-dev,
18− libpay1-dev,
22+ libpay2-dev,
1923 libpulse-dev,
2024 libqmenumodel-dev (>= 0.2.8),
2125 libqt5xmlpatterns5-dev,
@@ -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
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/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/Launcher/launchermodel.cpp+3−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();
@@ -326,7 +327,7 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
326327 if (found) {
327328 // Shall we paint some running/recent app highlight? If yes, do it here.
328329 } else {
329− LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString());
330+ LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString(), this);
330331 item->setRecent(true);
331332 item->setFocused(app->focused());
332333
po/da.po+52−49
@@ -1,199 +1,202 @@
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"
1011"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"
12+"PO-Revision-Date: 2014-07-22 15:46+0000\n"
13+"Last-Translator: Kenneth Ramsussen <kentora@kentora.dk>\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-23 07:01+0000\n"
19+"X-Generator: Launchpad (build 17114)\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 kantgestusserne 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 ""
84+msgstr "O.k."
8285
8386#: qml/Components/PageHeader.qml:366
8487msgid "Recent searches"
85−msgstr ""
88+msgstr "Seneste søgninger"
8689
8790#: qml/Components/PassphraseLockscreen.qml:60
8891#, qt-format
8992msgid "Hello %1"
90−msgstr ""
93+msgstr "Hej %1"
9194
9295#: qml/Components/PassphraseLockscreen.qml:60
9396msgid "Hello"
94−msgstr ""
97+msgstr "Hej"
9598
9699#: qml/Components/PinLockscreen.qml:198
97100msgid "CANCEL"
98−msgstr ""
101+msgstr "ANNULLÉR"
99102
100103#: qml/Components/PinLockscreen.qml:216
101104msgid "DONE"
102−msgstr ""
105+msgstr "FÆRDIG"
103106
104107#: qml/Components/SeeMore.qml:35
105108msgid "See more"
106−msgstr ""
109+msgstr "Vis mere"
107110
108111#: qml/Components/SeeMore.qml:58
109112msgid "See less"
110−msgstr ""
113+msgstr "Vis mindre"
111114
112115#: qml/Dash/DashApps.qml:37
113116msgid "Recent"
114−msgstr ""
117+msgstr "Seneste"
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
124127#: qml/Dash/Previews/PreviewRatingInput.qml:82
125128msgid "Rate this"
126−msgstr ""
129+msgstr "Bedøm dette"
127130
128131#: qml/Dash/Previews/PreviewRatingInput.qml:128
129132msgid "Add a review"
130−msgstr ""
133+msgstr "Tilføj en forhåndsvisning"
131134
132135#: qml/Dash/Previews/PreviewRatingInput.qml:168
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"
167170
168171#: qml/Panel/Indicators/MenuItemFactory.qml:583
169172msgid "In queue…"
170−msgstr ""
173+msgstr "I kø…"
171174
172175#: qml/Panel/Indicators/MenuItemFactory.qml:587
173176msgid "Downloading"
174−msgstr ""
177+msgstr "Henter"
175178
176179#: qml/Panel/Indicators/MenuItemFactory.qml:589
177180msgid "Paused, tap to resume"
178−msgstr ""
181+msgstr "På pause; tryk for at fortsætte"
179182
180183#: qml/Panel/Indicators/MenuItemFactory.qml:591
181184msgid "Canceled"
182−msgstr ""
185+msgstr "Annulleret"
183186
184187#: qml/Panel/Indicators/MenuItemFactory.qml:593
185188msgid "Finished"
186−msgstr ""
189+msgstr "Færdig"
187190
188191#: qml/Panel/Indicators/MenuItemFactory.qml:595
189192msgid "Failed, tap to retry"
190−msgstr ""
193+msgstr "Mislykkedes; tryk for at prøve igen"
191194
192195#: qml/Panel/SearchIndicator.qml:27
193196msgid "Search"
194−msgstr ""
197+msgstr "Søg"
195198
196199#: qml/Shell.qml:359
197200#, qt-format
198201msgid "Please enter %1"
199−msgstr ""
202+msgstr "Indtast venligst %1"
po/gd.po+3−3
@@ -8,13 +8,13 @@ msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-16 14:48+0000\n"
11+"PO-Revision-Date: 2014-07-24 22:26+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"
17+"X-Launchpad-Export-Date: 2014-07-25 07:54+0000\n"
1818"X-Generator: Launchpad (build 17114)\n"
1919"Language: gd\n"
2020
@@ -87,7 +87,7 @@ msgstr "Gairm èiginn"
8787
8888#: qml/Components/Lockscreen.qml:231
8989msgid "OK"
90−msgstr "Ceart ma-hà"
90+msgstr "Ceart ma-thà"
9191
9292#: qml/Components/PageHeader.qml:366
9393msgid "Recent searches"
po/gl.po+4−4
@@ -8,13 +8,13 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-19 17:04+0000\n"
11+"PO-Revision-Date: 2014-07-21 16:08+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"
17+"X-Launchpad-Export-Date: 2014-07-22 07:17+0000\n"
1818"X-Generator: Launchpad (build 17114)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -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 ""
po/hu.po+24−22
@@ -8,23 +8,23 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"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"
11+"PO-Revision-Date: 2014-07-24 08:19+0000\n"
12+"Last-Translator: Gabor Kelemen <kelemeng@openscope.org>\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-07-25 07:54+0000\n"
18+"X-Generator: Launchpad (build 17114)\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"
@@ -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,7 +82,7 @@ msgstr "Vészhívás"
8082
8183#: qml/Components/Lockscreen.qml:231
8284msgid "OK"
83−msgstr ""
85+msgstr "OK"
8486
8587#: qml/Components/PageHeader.qml:366
8688msgid "Recent searches"
@@ -97,31 +99,31 @@ msgstr "Szia"
9799
98100#: qml/Components/PinLockscreen.qml:198
99101msgid "CANCEL"
100−msgstr ""
102+msgstr "MÉGSE"
101103
102104#: qml/Components/PinLockscreen.qml:216
103105msgid "DONE"
104−msgstr ""
106+msgstr "KÉSZ"
105107
106108#: qml/Components/SeeMore.qml:35
107109msgid "See more"
108−msgstr ""
110+msgstr "Több"
109111
110112#: qml/Components/SeeMore.qml:58
111113msgid "See less"
112−msgstr ""
114+msgstr "Kevesebb"
113115
114116#: qml/Dash/DashApps.qml:37
115117msgid "Recent"
116−msgstr ""
118+msgstr "Legutóbbi"
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
126128#: qml/Dash/Previews/PreviewRatingInput.qml:82
127129msgid "Rate this"
@@ -137,7 +139,7 @@ msgstr "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,31 @@ 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"
169171
170172#: qml/Panel/Indicators/MenuItemFactory.qml:583
171173msgid "In queue…"
172−msgstr ""
174+msgstr "Sorban…"
173175
174176#: qml/Panel/Indicators/MenuItemFactory.qml:587
175177msgid "Downloading"
176−msgstr ""
178+msgstr "Letöltés"
177179
178180#: qml/Panel/Indicators/MenuItemFactory.qml:589
179181msgid "Paused, tap to resume"
180−msgstr ""
182+msgstr "Szüneteltetve, koppintson a folytatáshoz"
181183
182184#: qml/Panel/Indicators/MenuItemFactory.qml:591
183185msgid "Canceled"
184−msgstr ""
186+msgstr "Megszakítva"
185187
186188#: qml/Panel/Indicators/MenuItemFactory.qml:593
187189msgid "Finished"
188−msgstr ""
190+msgstr "Befejeződött"
189191
190192#: qml/Panel/Indicators/MenuItemFactory.qml:595
191193msgid "Failed, tap to retry"
192−msgstr ""
194+msgstr "Sikertelen, koppintson az újrapróbáláshoz"
193195
194196#: qml/Panel/SearchIndicator.qml:27
195197msgid "Search"
po/is.po+22−17
@@ -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"
1012"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-18 11:20+0000\n"
13+"PO-Revision-Date: 2014-07-23 05:57+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"
19+"X-Launchpad-Export-Date: 2014-07-24 06:32+0000\n"
1820"X-Generator: Launchpad (build 17114)\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"
@@ -136,7 +141,7 @@ msgstr "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..."
@@ -176,7 +181,7 @@ msgstr "Sæki"
176181
177182#: qml/Panel/Indicators/MenuItemFactory.qml:589
178183msgid "Paused, tap to resume"
179−msgstr ""
184+msgstr "Í bið, sláðu létt til að halda áfram"
180185
181186#: qml/Panel/Indicators/MenuItemFactory.qml:591
182187msgid "Canceled"
@@ -188,7 +193,7 @@ msgstr "Lokið"
188193
189194#: qml/Panel/Indicators/MenuItemFactory.qml:595
190195msgid "Failed, tap to retry"
191−msgstr ""
196+msgstr "Mistókst, sláðu létt til að reyna aftur"
192197
193198#: qml/Panel/SearchIndicator.qml:27
194199msgid "Search"
po/sl.po+11−11
@@ -8,23 +8,23 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-06-23 09:29+0000\n"
11+"PO-Revision-Date: 2014-07-24 09:01+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-07-25 07:54+0000\n"
18+"X-Generator: Launchpad (build 17114)\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"
@@ -171,27 +171,27 @@ msgstr "Vnesite PIN kartice SIM"
171171
172172#: qml/Panel/Indicators/MenuItemFactory.qml:583
173173msgid "In queue…"
174−msgstr ""
174+msgstr "V vrsti ..."
175175
176176#: qml/Panel/Indicators/MenuItemFactory.qml:587
177177msgid "Downloading"
178−msgstr ""
178+msgstr "Prejemanje"
179179
180180#: qml/Panel/Indicators/MenuItemFactory.qml:589
181181msgid "Paused, tap to resume"
182−msgstr ""
182+msgstr "Premor, tapnite za nadaljevanje"
183183
184184#: qml/Panel/Indicators/MenuItemFactory.qml:591
185185msgid "Canceled"
186−msgstr ""
186+msgstr "Preklicano"
187187
188188#: qml/Panel/Indicators/MenuItemFactory.qml:593
189189msgid "Finished"
190−msgstr ""
190+msgstr "Končano"
191191
192192#: qml/Panel/Indicators/MenuItemFactory.qml:595
193193msgid "Failed, tap to retry"
194−msgstr ""
194+msgstr "Spodletelo, tapnite za ponovni poskus"
195195
196196#: qml/Panel/SearchIndicator.qml:27
197197msgid "Search"
po/sv.po+19−18
@@ -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"
1010"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"
11+"PO-Revision-Date: 2014-07-24 13:56+0000\n"
12+"Last-Translator: Josef Andersson <Unknown>\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"
17+"X-Launchpad-Export-Date: 2014-07-25 07:54+0000\n"
1818"X-Generator: Launchpad (build 17114)\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"
@@ -117,11 +118,11 @@ msgstr "Senaste"
117118
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
126127#: qml/Dash/Previews/PreviewRatingInput.qml:82
127128msgid "Rate this"
@@ -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"
@@ -169,7 +170,7 @@ msgstr "Ange SIM PIN-kod"
169170
170171#: qml/Panel/Indicators/MenuItemFactory.qml:583
171172msgid "In queue…"
172−msgstr "I kö..."
173+msgstr "I kö…"
173174
174175#: qml/Panel/Indicators/MenuItemFactory.qml:587
175176msgid "Downloading"
@@ -177,7 +178,7 @@ msgstr "Hämtar"
177178
178179#: qml/Panel/Indicators/MenuItemFactory.qml:589
179180msgid "Paused, tap to resume"
180−msgstr "Pausad, peka för att fortsätta"
181+msgstr "Pausad, tryck för att fortsätta"
181182
182183#: qml/Panel/Indicators/MenuItemFactory.qml:591
183184msgid "Canceled"
@@ -189,7 +190,7 @@ msgstr "Klart"
189190
190191#: qml/Panel/Indicators/MenuItemFactory.qml:595
191192msgid "Failed, tap to retry"
192−msgstr "Misslyckades, peka för att försöka igen"
193+msgstr "Misslyckades, tryck för att försöka igen"
193194
194195#: qml/Panel/SearchIndicator.qml:27
195196msgid "Search"
po/ug.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-07-21 07:05+0000\n"
17+"X-Launchpad-Export-Date: 2014-07-22 07:17+0000\n"
1818"X-Generator: Launchpad (build 17114)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
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 ""
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/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/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+6−1
@@ -127,6 +127,11 @@ Item {
127127 property bool showSearch: false
128128 property var popover: null
129129
130+ Background {
131+ objectName: "headerBackground"
132+ style: scopeStyle.headerBackground
133+ }
134+
130135 Behavior on contentY {
131136 UbuntuNumberAnimation {
132137 id: openSearchAnimation
@@ -225,7 +230,7 @@ Item {
225230 height: headerContainer.height
226231 contentHeight: height
227232 separatorSource: ""
228− textColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
233+ textColor: root.scopeStyle ? root.scopeStyle.headerForeground : "grey"
229234 property var styledItem: header
230235 property string title: root.title
231236 property var config: PageHeadConfiguration {
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/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/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/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+132−64
@@ -119,6 +119,7 @@ FocusScope {
119119
120120 model: scopeView.categories
121121 forceNoClip: previewListView.open
122+ pixelAligned: true
122123
123124 property string expandedCategoryId: ""
124125
@@ -128,11 +129,22 @@ FocusScope {
128129 highlightWhenPressed: false
129130 showDivider: false
130131
131− readonly property bool expandable: rendererLoader.item ? rendererLoader.item.expandable : false
132− readonly property bool filtered: rendererLoader.item ? rendererLoader.item.filtered : true
132+ readonly property bool expandable: {
133+ if (categoryView.model.count === 1) return false;
134+ if (cardTool.template && cardTool.template["collapsed-rows"] === 0) return false;
135+ if (item && item.expandedHeight > item.collapsedHeight) return true;
136+ return false;
137+ }
138+ property bool expanded: false
133139 readonly property string category: categoryId
140+ readonly property string headerLink: model.headerLink
134141 readonly property var item: rendererLoader.item
135142
143+ function expand(expand, animate) {
144+ heightBehaviour.enabled = animate;
145+ expanded = expand;
146+ }
147+
136148 CardTool {
137149 id: cardTool
138150 objectName: "cardTool"
@@ -142,22 +154,49 @@ FocusScope {
142154 viewWidth: parent.width
143155 }
144156
157+ onExpandableChanged: {
158+ // This can happen with the VJ that doesn't know how height it will be on creation
159+ // so doesn't set expandable until a bit too late for onLoaded
160+ if (expandable) {
161+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
162+ baseItem.expand(shouldExpand, false /*animate*/);
163+ }
164+ }
165+
166+ onHeightChanged: rendererLoader.updateDelegateCreationRange();
167+ onYChanged: rendererLoader.updateDelegateCreationRange();
168+
145169 Loader {
146170 id: rendererLoader
147171 anchors {
148172 top: parent.top
149173 left: parent.left
150174 right: parent.right
151− topMargin: hasSectionHeader ? 0 : units.gu(2)
175+ topMargin: name != "" ? 0 : units.gu(2)
152176 }
153177
178+ Behavior on height {
179+ id: heightBehaviour
180+ enabled: false
181+ animation: UbuntuNumberAnimation {
182+ onRunningChanged: {
183+ if (!running) {
184+ heightBehaviour.enabled = false
185+ }
186+ }
187+ }
188+ }
189+
190+ readonly property bool expanded: baseItem.expanded || !baseItem.expandable
191+ height: expanded ? item.expandedHeight : item.collapsedHeight
192+
154193 source: {
155194 switch (cardTool.categoryLayout) {
156195 case "carousel": return "CardCarousel.qml";
157196 case "vertical-journal": return "CardVerticalJournal.qml";
158197 case "running-apps": return "Apps/RunningApplicationsGrid.qml";
159198 case "grid":
160− default: return "CardFilterGrid.qml";
199+ default: return "CardGrid.qml";
161200 }
162201 }
163202
@@ -176,9 +215,9 @@ FocusScope {
176215 }
177216 item.objectName = Qt.binding(function() { return categoryId })
178217 item.scopeStyle = scopeView.scopeStyle;
179− if (item.expandable) {
180− var shouldFilter = categoryId != categoryView.expandedCategoryId;
181− item.setFilter(shouldFilter, false /*animate*/);
218+ if (baseItem.expandable) {
219+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
220+ baseItem.expand(shouldExpand, false /*animate*/);
182221 }
183222 updateDelegateCreationRange();
184223 item.cardTool = cardTool;
@@ -199,25 +238,22 @@ FocusScope {
199238 // so it's not implemented
200239 scopeView.scope.activate(result)
201240 } else {
202− previewListView.model = target.model;
203− previewListView.currentIndex = -1
204− previewListView.currentIndex = index;
205− previewListView.open = true
241+ openPreview(index);
206242 }
207243 }
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*/);
244+ onPressAndHold: openPreview(index)
245+
246+ function openPreview(index) {
247+ if (!rendererLoader.expanded && !seeAllLabel.visible && target.collapsedItemCount > 0) {
248+ previewLimitModel.model = target.model;
249+ previewLimitModel.limit = target.collapsedItemCount;
250+ previewListView.model = previewLimitModel;
251+ } else {
252+ previewListView.model = target.model;
220253 }
254+ previewListView.currentIndex = -1;
255+ previewListView.currentIndex = index;
256+ previewListView.open = true;
221257 }
222258 }
223259 Connections {
@@ -227,17 +263,17 @@ FocusScope {
227263 }
228264 function collapseAllButExpandedCategory() {
229265 var item = rendererLoader.item;
230− if (item.expandable) {
231− var shouldFilter = categoryId != categoryView.expandedCategoryId;
232− if (shouldFilter != item.filter) {
266+ if (baseItem.expandable) {
267+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
268+ if (shouldExpand != baseItem.expanded) {
233269 // 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) {
270+ var shrinkingVisible = !shouldExpand && y + item.collapsedHeight + seeAll.height < categoryView.height;
271+ var growingVisible = shouldExpand && y + height < categoryView.height;
272+ if (!previewListView.open || shouldExpand) {
237273 var animate = shrinkingVisible || growingVisible;
238− item.setFilter(shouldFilter, animate)
239− if (!shouldFilter && !previewListView.open) {
240− categoryView.maximizeVisibleArea(index, item.uncollapsedHeight);
274+ baseItem.expand(shouldExpand, animate)
275+ if (shouldExpand && !previewListView.open) {
276+ categoryView.maximizeVisibleArea(index, item.expandedHeight + seeAll.height);
241277 }
242278 }
243279 }
@@ -274,58 +310,82 @@ FocusScope {
274310 item.displayMarginEnd = -baseItem.height;
275311 } else {
276312 item.displayMarginBeginning = -Math.max(-baseItem.y, 0);
277− item.displayMarginEnd = -Math.max(baseItem.height - categoryView.height + baseItem.y, 0)
313+ item.displayMarginEnd = -Math.max(baseItem.height - seeAll.height
314+ - categoryView.height + baseItem.y, 0)
278315 }
279316 }
280317 }
318+ }
281319
282− Image {
283− visible: index != 0
284− anchors {
285− top: parent.top
286− left: parent.left
287− right: parent.right
320+ AbstractButton {
321+ id: seeAll
322+ objectName: "seeAll"
323+ anchors {
324+ top: rendererLoader.bottom
325+ left: parent.left
326+ right: parent.right
327+ }
328+ height: seeAllLabel.visible ? seeAllLabel.font.pixelSize + units.gu(6) : 0
329+
330+ onClicked: {
331+ if (categoryView.expandedCategoryId != baseItem.category) {
332+ categoryView.expandedCategoryId = baseItem.category;
333+ } else {
334+ categoryView.expandedCategoryId = "";
288335 }
289− fillMode: Image.Stretch
290− source: "graphics/dash_divider_top_lightgrad.png"
291− z: -1
292336 }
293337
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
338+ Label {
339+ id: seeAllLabel
340+ text: baseItem.expanded ? i18n.tr("See less") : i18n.tr("See all")
297341 anchors {
298− bottom: parent.bottom
299− left: parent.left
300− right: parent.right
342+ centerIn: parent
343+ verticalCenterOffset: units.gu(-0.5)
301344 }
302− fillMode: Image.Stretch
303− source: "graphics/dash_divider_top_darkgrad.png"
304− z: -1
345+ fontSize: "small"
346+ font.weight: Font.Bold
347+ color: scopeStyle ? scopeStyle.foreground : "grey"
348+ visible: baseItem.expandable && !baseItem.headerLink
305349 }
306350 }
307351
308− onHeightChanged: rendererLoader.updateDelegateCreationRange();
309− onYChanged: rendererLoader.updateDelegateCreationRange();
352+ Image {
353+ visible: index != 0
354+ anchors {
355+ top: parent.top
356+ left: parent.left
357+ right: parent.right
358+ }
359+ fillMode: Image.Stretch
360+ source: "graphics/dash_divider_top_lightgrad.png"
361+ z: -1
362+ }
363+
364+ Image {
365+ // FIXME Should not rely on model.count but view.count, but ListViewWithPageHeader doesn't expose it yet.
366+ visible: index != categoryView.model.count - 1
367+ anchors {
368+ bottom: seeAll.bottom
369+ left: parent.left
370+ right: parent.right
371+ }
372+ fillMode: Image.Stretch
373+ source: "graphics/dash_divider_top_darkgrad.png"
374+ z: -1
375+ }
310376 }
311377
312378 sectionProperty: "name"
313379 sectionDelegate: ListItems.Header {
314380 objectName: "dashSectionHeader" + (delegate ? delegate.category : "")
315− property var delegate: categoryView.item(delegateIndex)
381+ readonly property var delegate: categoryView.item(delegateIndex)
316382 width: categoryView.width
383+ height: section != "" ? units.gu(5) : 0
317384 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− }
385+ color: scopeStyle ? scopeStyle.foreground : "grey"
386+ iconName: delegate && delegate.headerLink ? "go-next" : ""
324387 onClicked: {
325− if (categoryView.expandedCategoryId != delegate.category)
326− categoryView.expandedCategoryId = delegate.category;
327− else
328− categoryView.expandedCategoryId = "";
388+ if (delegate.headerLink) scopeView.scope.performQuery(delegate.headerLink);
329389 }
330390 }
331391
@@ -352,6 +412,10 @@ FocusScope {
352412 }
353413 }
354414
415+ LimitProxyModel {
416+ id: previewLimitModel
417+ }
418+
355419 PreviewListView {
356420 id: previewListView
357421 objectName: "previewListView"
@@ -361,6 +425,10 @@ FocusScope {
361425 width: parent.width
362426 height: parent.height
363427 anchors.left: categoryView.right
428+
429+ onOpenChanged: {
430+ pageHeader.unfocus();
431+ }
364432 }
365433
366434}
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/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/Shell.qml+84−27
@@ -137,7 +137,7 @@ FocusScope {
137137 id: dash
138138 objectName: "dash"
139139
140− available: !greeter.shown && !lockscreen.shown
140+ available: !LightDM.Greeter.active
141141 hides: [stages, launcher, panel.indicators]
142142 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0
143143 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
@@ -200,7 +200,7 @@ FocusScope {
200200
201201 x: {
202202 if (shown) {
203− if (overlayMode || locked) {
203+ if (overlayMode || locked || greeter.fakeActiveForApp !== "") {
204204 return 0;
205205 }
206206 return launcher.progress
@@ -245,10 +245,17 @@ FocusScope {
245245 target: ApplicationManager
246246
247247 onFocusRequested: {
248+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== appId) {
249+ lockscreen.show();
250+ }
251+ greeter.hide();
248252 stages.show(true);
249253 }
250254
251255 onFocusedApplicationIdChanged: {
256+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== ApplicationManager.focusedApplicationId) {
257+ lockscreen.show();
258+ }
252259 if (ApplicationManager.focusedApplicationId.length > 0) {
253260 stages.show(false);
254261 } else {
@@ -439,6 +446,11 @@ FocusScope {
439446
440447 source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
441448
449+ Binding {
450+ target: applicationsDisplayLoader.item
451+ property: "objectName"
452+ value: "stage"
453+ }
442454 Binding {
443455 target: applicationsDisplayLoader.item
444456 property: "moving"
@@ -454,6 +466,11 @@ FocusScope {
454466 property: "dragAreaWidth"
455467 value: shell.edgeSize
456468 }
469+ Binding {
470+ target: applicationsDisplayLoader.item
471+ property: "spreadEnabled"
472+ value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
473+ }
457474 }
458475 }
459476
@@ -478,6 +495,13 @@ FocusScope {
478495
479496 onEntered: LightDM.Greeter.respond(passphrase);
480497 onCancel: greeter.show()
498+ onEmergencyCall: {
499+ greeter.fakeActiveForApp = "dialer-app"
500+ shell.activateApplication("dialer-app")
501+ lockscreen.hide()
502+ }
503+
504+ onShownChanged: if (shown) greeter.fakeActiveForApp = ""
481505
482506 Component.onCompleted: {
483507 if (LightDM.Users.count == 1) {
@@ -510,6 +534,7 @@ FocusScope {
510534 }
511535 if (LightDM.Greeter.authenticated) {
512536 lockscreen.hide();
537+ greeter.login();
513538 } else {
514539 lockscreen.clear(true);
515540 }
@@ -519,7 +544,7 @@ FocusScope {
519544 Binding {
520545 target: LightDM.Greeter
521546 property: "active"
522− value: greeter.shown || lockscreen.shown
547+ value: greeter.shown || lockscreen.shown || greeter.fakeActiveForApp != ""
523548 }
524549
525550 Rectangle {
@@ -542,11 +567,16 @@ FocusScope {
542567 }
543568
544569 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
570+ onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
545571
546572 Greeter {
547573 id: greeter
548574 objectName: "greeter"
549575
576+ signal sessionStarted() // helpful for tests
577+
578+ property string fakeActiveForApp: ""
579+
550580 available: true
551581 hides: [launcher, panel.indicators]
552582 shown: true
@@ -558,6 +588,16 @@ FocusScope {
558588
559589 dragHandleWidth: shell.edgeSize
560590
591+ function login() {
592+ enabled = false;
593+ LightDM.Greeter.startSessionSync();
594+ sessionStarted();
595+ greeter.hide();
596+ lockscreen.hide();
597+ launcher.hide();
598+ enabled = true;
599+ }
600+
561601 onShownChanged: {
562602 if (shown) {
563603 lockscreen.reset();
@@ -569,6 +609,7 @@ FocusScope {
569609 if (LightDM.Users.count == 1) {
570610 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
571611 }
612+ greeter.fakeActiveForApp = "";
572613 greeter.forceActiveFocus();
573614 }
574615 }
@@ -618,12 +659,40 @@ FocusScope {
618659 }
619660
620661 function showHome() {
621− var animate = !greeter.shown && !stages.shown
622− greeter.hide()
662+ if (edgeDemo.running) {
663+ return
664+ }
665+
666+ if (LightDM.Greeter.active) {
667+ if (!LightDM.Greeter.promptless) {
668+ lockscreen.show()
669+ }
670+ greeter.hide()
671+ }
672+
673+ var animate = !LightDM.Greeter.active && !stages.shown
623674 dash.setCurrentScope("clickscope", animate, false)
624675 stages.hide()
625676 }
626677
678+ function showDash() {
679+ if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
680+ return;
681+ }
682+
683+ if (stages.shown && !stages.overlayMode && !stages.locked) {
684+ stages.hide();
685+ launcher.fadeOut();
686+ } else {
687+ launcher.switchToNextState("visible");
688+ }
689+
690+ if (greeter.shown) {
691+ greeter.hideRight();
692+ launcher.fadeOut();
693+ }
694+ }
695+
627696 Item {
628697 id: overlay
629698
@@ -631,17 +700,18 @@ FocusScope {
631700
632701 Panel {
633702 id: panel
703+ objectName: "panel"
634704 anchors.fill: parent //because this draws indicator menus
635705 indicators {
636706 hides: [launcher]
637− available: edgeDemo.panelEnabled
707+ available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
638708 contentEnabled: edgeDemo.panelContentEnabled
639709 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
640710 panelHeight: units.gu(3)
641711 }
642712 property string focusedAppId: ApplicationManager.focusedApplicationId
643713 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
644− fullscreenMode: focusedApplication && stages.fullscreen && !greeter.shown && !lockscreen.shown
714+ fullscreenMode: (focusedApplication && stages.fullscreen && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""
645715
646716 InputFilterArea {
647717 anchors {
@@ -666,6 +736,7 @@ FocusScope {
666736
667737 Launcher {
668738 id: launcher
739+ objectName: "launcher"
669740
670741 readonly property bool dashSwipe: progress > 0
671742
@@ -673,29 +744,15 @@ FocusScope {
673744 anchors.bottom: parent.bottom
674745 width: parent.width
675746 dragAreaWidth: shell.edgeSize
676− available: edgeDemo.launcherEnabled
747+ available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
677748
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− }
691−
692− if (greeter.shown) {
693− greeter.hideRight();
694− launcher.fadeOut();
695− }
696− }
749+ onShowDashHome: showHome()
750+ onDash: showDash()
697751 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
698752 onLauncherApplicationSelected: {
753+ if (greeter.fakeActiveForApp !== "") {
754+ lockscreen.show()
755+ }
699756 if (!edgeDemo.running)
700757 shell.activateApplication(appId)
701758 }
qml/Stages/PhoneStage.qml+13−1
@@ -18,6 +18,7 @@ import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Ubuntu.Gestures 0.1
2020import Unity.Application 0.1
21+import LightDM 0.1 as LightDM
2122import Utils 0.1
2223import "../Components"
2324
@@ -33,6 +34,7 @@ Item {
3334 readonly property bool painting: mainScreenshotImage.visible || fadeInScreenshotImage.visible || appSplash.visible || spreadView.visible
3435 property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
3536 property bool locked: spreadView.visible
37+ property bool spreadEnabled: true
3638
3739 // Not used for PhoneStage, only useful for SideStage and similar
3840 property bool overlayMode: false
@@ -131,6 +133,11 @@ Item {
131133 mainScreenshotImage.visible = true;
132134 } else if (priv.secondApplicationStarting && priv.waitingForScreenshot) {
133135 applicationSwitchingAnimation.start();
136+ if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
137+ // When greeter is up, no fancy animations, since user may
138+ // glimpse an app they shouldn't
139+ applicationSwitchingAnimation.complete();
140+ }
134141 }
135142 waitingForScreenshot = false;
136143 }
@@ -145,6 +152,11 @@ Item {
145152 priv.newFocusedAppId = appId;
146153 root.fullscreen = ApplicationManager.findApplication(appId).fullscreen;
147154 applicationSwitchingAnimation.start();
155+ if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
156+ // When greeter is up, no fancy animations, since user may
157+ // glimpse an app they shouldn't
158+ applicationSwitchingAnimation.complete();
159+ }
148160 } else {
149161 ApplicationManager.focusApplication(appId);
150162 }
@@ -244,7 +256,7 @@ Item {
244256 EdgeDragArea {
245257 id: spreadDragArea
246258 direction: Direction.Leftwards
247− enabled: ApplicationManager.count > 1 && spreadView.phase != 2
259+ enabled: ApplicationManager.count > 1 && spreadView.phase != 2 && root.spreadEnabled
248260
249261 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
250262 width: root.dragAreaWidth
src/main.cpp+1−1
@@ -221,7 +221,7 @@ int main(int argc, const char *argv[])
221221
222222 return runWithClient(mirServer, startShell);
223223 } else {
224− if (qgetenv("UPSTART_JOB") == "unity8") {
224+ if (!qgetenv("UNITY_MIR_EMITS_SIGSTOP").isEmpty()) {
225225 // Emit SIGSTOP as expected by upstart, under Mir it's unity-mir that will raise it.
226226 // see http://upstart.ubuntu.com/cookbook/#expect-stop
227227 raise(SIGSTOP);
tests/autopilot/unity8/shell/emulators/dash.py+12−6
@@ -18,6 +18,7 @@
1818#
1919
2020import logging
21+import ubuntuuitoolkit
2122
2223from unity8.shell import emulators
2324
@@ -40,7 +41,7 @@ class Dash(emulators.UnityEmulatorBase):
4041
4142 def get_applications_grid(self):
4243 get_grid = self.get_scope('clickscope').wait_select_single(
43− 'CardFilterGrid', objectName='local')
44+ 'CardGrid', objectName='local')
4445 return get_grid
4546
4647 def get_application_icon(self, text):
@@ -128,9 +129,9 @@ class Dash(emulators.UnityEmulatorBase):
128129 def enter_search_query(self, query):
129130 current_header = self._get_current_page_header()
130131 self.pointing_device.move(current_header.globalRect.x +
131− current_header.width - current_header.height / 2,
132+ current_header.width - current_header.height / 4,
132133 current_header.globalRect.y +
133− current_header.height / 2)
134+ current_header.height / 4)
134135 self.pointing_device.click()
135136 headerContainer = current_header.select_single(objectName="headerContainer")
136137 headerContainer.contentY.wait_for(0)
@@ -151,6 +152,10 @@ class Dash(emulators.UnityEmulatorBase):
151152 return None
152153
153154
155+class ListViewWithPageHeader(ubuntuuitoolkit.QQuickFlickable):
156+ pass
157+
158+
154159class GenericScopeView(emulators.UnityEmulatorBase):
155160 """Autopilot emulator for generic scopes."""
156161
@@ -194,16 +199,17 @@ class DashApps(GenericScopeView):
194199
195200 """
196201 category_element = self._get_category_element(category)
202+ see_all = category_element.select_single(objectName='seeAll')
197203 application_cards = category_element.select_many('AbstractButton')
198204
199− # sort by y, x
200205 application_cards = sorted(
201− application_cards,
206+ (card for card in application_cards
207+ if card.globalRect.y < see_all.globalRect.y),
202208 key=lambda card: (card.globalRect.y, card.globalRect.x))
203209
204210 result = []
205211 for card in application_cards:
206− if card.objectName != 'cardToolCard':
212+ if card.objectName not in ('cardToolCard', 'seeAll'):
207213 result.append(card.title)
208214 return result
209215
tests/autopilot/unity8/shell/tests/test_emulators.py+15−5
@@ -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
@@ -182,18 +183,27 @@ class DashAppsEmulatorTestCase(DashBaseTestCase):
182183
183184 def test_get_applications_should_return_correct_applications(self):
184185 category = '2'
186+ category_element = self.applications_scope._get_category_element(
187+ category)
188+ list_view = self.dash.get_scope('clickscope')\
189+ .select_single(ListViewWithPageHeader)
185190 expected_apps_count = self._get_number_of_application_slots(category)
186191 expected_applications = self.available_applications[
187192 :expected_apps_count]
193+ x_center = list_view.globalRect.x + list_view.width / 2
194+ y_center = list_view.globalRect.y + list_view.height / 2
195+ y_diff = category_element.y - list_view.height + category_element.height
196+ list_view._slow_drag(x_center, x_center,
197+ y_center, y_center - y_diff)
188198 applications = self.applications_scope.get_applications(category)
189199 self.assertEqual(expected_applications, applications)
190200
191201 def _get_number_of_application_slots(self, category):
192202 category_element = self.applications_scope._get_category_element(
193203 category)
194− grid = category_element.select_single('CardFilterGrid')
195− filtergrid = grid.select_single('FilterGrid')
196− if (grid.filtered):
197− return filtergrid.collapsedRowCount * filtergrid.columns
204+ cardgrid = category_element.select_single('CardGrid')
205+ if (category_element.expanded):
206+ return cardgrid.select_single('QQuickGridView').count
198207 else:
199− return filtergrid.uncollapsedRowCount * filtergrid.columns
208+ return cardgrid.collapsedRows \
209+ * cardgrid.select_single('ResponsiveGridView').columns
tests/autopilot/unity8/shell/tests/test_upstart.py+13
@@ -20,6 +20,7 @@
2020"""Tests for upstart integration."""
2121
2222import os
23+import stat
2324import signal
2425import subprocess
2526import time
@@ -57,6 +58,18 @@ class UpstartIntegrationTests(UnityTestCase):
5758
5859 def _launch_unity(self):
5960 self.patch_environment("QT_LOAD_TESTABILITY", "1")
61+
62+ try:
63+ host_socket = os.getenv("MIR_SOCKET", "/run/mir_socket")
64+ if stat.S_ISSOCK(os.stat(host_socket).st_mode):
65+ self.patch_environment("MIR_SERVER_HOST_SOCKET",
66+ host_socket)
67+ socket = os.path.join(os.getenv("XDG_RUNTIME_DIR", "/tmp"),
68+ "mir_socket")
69+ self.patch_environment("MIR_SERVER_FILE", socket)
70+ except OSError:
71+ pass
72+
6073 self.process = subprocess.Popen(
6174 [get_binary_path()] + self.unity_geometry_args)
6275
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("PIN", 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/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/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+1
@@ -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;
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/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−4
@@ -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)
@@ -75,4 +75,4 @@ add_qml_test(Panel/Indicators DefaultIndicatorPage ENVIRONMENT "LD_LIBRARY_PATH=
7575# These MenuItemFactory tests need the test/mocks/ to come before plugins/
7676add_qml_test(Panel/Indicators MenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
7777add_qml_test(Panel/Indicators MessageMenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
78−add_qml_test(Stages PhoneStage)
78+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/Dash/tst_Dash.qml+1−1
@@ -86,7 +86,7 @@ Item {
8686 tryCompare(dashContentList, "count", 0);
8787 scopes.load();
8888 tryCompare(scopes, "loaded", true);
89− tryCompare(dashContentList, "count", 3);
89+ tryCompare(dashContentList, "count", 4);
9090
9191 verify(dashContentList != undefined);
9292 tryCompare(dashContentList, "currentIndex", data.visualIndex);
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+1−1
@@ -57,7 +57,7 @@ Rectangle {
5757 target: LightDM.Greeter
5858
5959 onShowPrompt: {
60− if (text.indexOf("PIN") >= 0) {
60+ if (text === "PIN") {
6161 pinPadCheckBox.checked = false
6262 } else {
6363 pinPadCheckBox.checked = true
tests/qmltests/tst_Shell.qml+19
@@ -51,6 +51,11 @@ Item {
5151 id: shell
5252 }
5353
54+ SignalSpy {
55+ id: sessionSpy
56+ signalName: "sessionStarted"
57+ }
58+
5459 UT.UnityTestCase {
5560 name: "Shell"
5661 when: windowShown
@@ -92,6 +97,8 @@ Item {
9297 verify(ok);
9398
9499 swipeAwayGreeter();
100+
101+ sessionSpy.target = findChild(shell, "greeter")
95102 }
96103
97104 function cleanup() {
@@ -528,5 +535,17 @@ Item {
528535 LightDM.Greeter.showGreeter()
529536 tryCompare(greeter, "showProgress", 1)
530537 }
538+
539+ function test_login() {
540+ sessionSpy.clear()
541+
542+ var greeter = findChild(shell, "greeter")
543+ greeter.show()
544+ tryCompare(greeter, "showProgress", 1)
545+
546+ tryCompare(sessionSpy, "count", 0)
547+ swipeAwayGreeter()
548+ tryCompare(sessionSpy, "count", 1)
549+ }
531550 }
532551}
tests/qmltests/tst_ShellWithPin.qmlnew file+203
@@ -0,0 +1,203 @@
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+ var ok = false;
62+ var attempts = 0;
63+ var maxAttempts = 1000;
64+
65+ // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
66+ // tests may fail because the desired child item wasn't loaded yet.
67+ // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
68+ // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
69+ // (all items instantiated, etc), I resort to checking the existence of some key items until
70+ // repeatedly until they're all there.
71+ do {
72+ var dashContentList = findChild(shell, "dashContentList");
73+ waitForRendering(dashContentList);
74+ var homeLoader = findChild(dashContentList, "clickscope loader");
75+ ok = homeLoader !== null
76+ && homeLoader.item !== undefined;
77+
78+ var greeter = findChild(shell, "greeter");
79+ ok &= greeter !== null;
80+
81+ var launcherPanel = findChild(shell, "launcherPanel");
82+ ok &= launcherPanel !== null;
83+
84+ attempts++;
85+ if (!ok) {
86+ console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
87+ // wait a bit before retrying
88+ wait(100);
89+ } else {
90+ console.log("All seem fine after " + attempts + " attempts.");
91+ }
92+ } while (!ok && attempts <= maxAttempts);
93+
94+ verify(ok);
95+
96+ sessionSpy.target = findChild(shell, "greeter")
97+ }
98+
99+ function init() {
100+ swipeAwayGreeter()
101+ }
102+
103+ function cleanup() {
104+ LightDM.Greeter.showGreeter()
105+ var greeter = findChild(shell, "greeter")
106+ tryCompare(greeter, "showProgress", 1)
107+
108+ // kill all (fake) running apps
109+ killApps()
110+ }
111+
112+ function killApps() {
113+ while (ApplicationManager.count > 0) {
114+ ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
115+ }
116+ compare(ApplicationManager.count, 0)
117+ }
118+
119+ function swipeAwayGreeter() {
120+ var greeter = findChild(shell, "greeter");
121+ tryCompare(greeter, "showProgress", 1);
122+
123+ var touchX = shell.width - (shell.edgeSize / 2);
124+ var touchY = shell.height / 2;
125+ touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY);
126+
127+ // wait until the animation has finished
128+ tryCompare(greeter, "showProgress", 0);
129+
130+ // and for pin to be ready
131+ var lockscreen = findChild(shell, "lockscreen");
132+ var pinPadLoader = findChild(lockscreen, "pinPadLoader");
133+ tryCompare(pinPadLoader, "status", Loader.Ready)
134+ waitForRendering(lockscreen)
135+ }
136+
137+ function enterPin(pin) {
138+ var inputField = findChild(shell, "pinentryField")
139+ for (var i = 0; i < pin.length; ++i) {
140+ var character = pin.charAt(i)
141+ var button = findChild(shell, "pinPadButton" + character)
142+ mouseClick(button, units.gu(1), units.gu(1))
143+ }
144+ }
145+
146+ function test_login() {
147+ tryCompare(sessionSpy, "count", 0)
148+ enterPin("1234")
149+ tryCompare(sessionSpy, "count", 1)
150+ }
151+
152+ function test_emergencyCall() {
153+ var greeter = findChild(shell, "greeter")
154+ var lockscreen = findChild(shell, "lockscreen")
155+ var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
156+ var panel = findChild(shell, "panel")
157+ var indicators = findChild(shell, "indicators")
158+ var launcher = findChild(shell, "launcher")
159+ var stage = findChild(shell, "stage")
160+
161+ mouseClick(emergencyButton, units.gu(1), units.gu(1))
162+
163+ tryCompare(greeter, "fakeActiveForApp", "dialer-app")
164+ tryCompare(lockscreen, "shown", false)
165+ tryCompare(panel, "fullscreenMode", true)
166+ tryCompare(indicators, "available", false)
167+ tryCompare(launcher, "available", false)
168+ tryCompare(stage, "spreadEnabled", false)
169+
170+ // Cancel emergency mode, and go back to normal
171+ waitForRendering(greeter)
172+ LightDM.Greeter.showGreeter()
173+
174+ tryCompare(greeter, "shown", true)
175+ tryCompare(greeter, "fakeActiveForApp", "")
176+ tryCompare(lockscreen, "shown", true)
177+ tryCompare(panel, "fullscreenMode", false)
178+ tryCompare(indicators, "available", true)
179+ tryCompare(launcher, "available", true)
180+ tryCompare(stage, "spreadEnabled", true)
181+ }
182+
183+ function test_emergencyCallCrash() {
184+ var lockscreen = findChild(shell, "lockscreen")
185+ var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
186+ mouseClick(emergencyButton, units.gu(1), units.gu(1))
187+
188+ tryCompare(lockscreen, "shown", false)
189+ killApps() // kill dialer-app, as if it crashed
190+ tryCompare(lockscreen, "shown", true)
191+ }
192+
193+ function test_emergencyCallAppLaunch() {
194+ var lockscreen = findChild(shell, "lockscreen")
195+ var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
196+ mouseClick(emergencyButton, units.gu(1), units.gu(1))
197+
198+ tryCompare(lockscreen, "shown", false)
199+ ApplicationManager.startApplication("gallery-app", ApplicationManager.NoFlag)
200+ tryCompare(lockscreen, "shown", true)
201+ }
202+ }
203+}