on xenial help sign in
Merge trunk.
f9a51e0Ying-Chun Liu
tests/autopilot/.project → .projectrenamed+1−1
@@ -1,6 +1,6 @@
1<?xml version="1.0" encoding="UTF-8"?>
1<?xml version="1.0" encoding="UTF-8"?>
2<projectDescription>
2<projectDescription>
3− <name>Unity8 Autopilot</name>
3+ <name>Unity8</name>
4 <comment></comment>
4 <comment></comment>
5 <projects>
5 <projects>
6 </projects>
6 </projects>
tests/autopilot/.pydevproject → .pydevprojectrenamed+3−1
@@ -1,7 +1,9 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<?eclipse-pydev version="1.0"?><pydev_project>
2<?eclipse-pydev version="1.0"?><pydev_project>
3<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
3<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>
5</pydev_pathproperty>
7</pydev_pathproperty>
6<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
8<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
7<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
9<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+
1unity8 (7.90+14.10.20140717.3-0ubuntu1) utopic; urgency=low
75unity8 (7.90+14.10.20140717.3-0ubuntu1) utopic; urgency=low
2
76
3 [ Nick Dedekind ]
77 [ Nick Dedekind ]
debian/control+6−2
@@ -7,6 +7,10 @@ Build-Depends: cmake,
7 debhelper (>= 9),
7 debhelper (>= 9),
8 doxyqml,
8 doxyqml,
9 graphviz,
9 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,
10 libdee-qt5-dev (>= 3.2),
14 libdee-qt5-dev (>= 3.2),
11 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
15 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
12 libgl1-mesa-dri,
16 libgl1-mesa-dri,
@@ -15,7 +19,7 @@ Build-Depends: cmake,
15 libgsettings-qt-dev,
19 libgsettings-qt-dev,
16 libhardware-dev,
20 libhardware-dev,
17 libhud-client2-dev,
21 libhud-client2-dev,
18− libpay1-dev,
22+ libpay2-dev,
19 libpulse-dev,
23 libpulse-dev,
20 libqmenumodel-dev (>= 0.2.8),
24 libqmenumodel-dev (>= 0.2.8),
21 libqt5xmlpatterns5-dev,
25 libqt5xmlpatterns5-dev,
@@ -108,7 +112,7 @@ Depends: qtdeclarative5-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
108 unity-application-impl-2,
112 unity-application-impl-2,
109 unity-notifications-impl-3,
113 unity-notifications-impl-3,
110 unity-plugin-scopes | unity-scopes-impl,
114 unity-plugin-scopes | unity-scopes-impl,
111− unity-scopes-impl-0,
115+ unity-scopes-impl-2,
112 unity8-fake-env | unity-application-impl,
116 unity8-fake-env | unity-application-impl,
113 ${misc:Depends},
117 ${misc:Depends},
114Breaks: unity8 (<< 7.86),
118Breaks: unity8 (<< 7.86),
debian/rules+7
@@ -1,11 +1,18 @@
1#!/usr/bin/make -f
1#!/usr/bin/make -f
2# -*- makefile -*-
2# -*- makefile -*-
3
3
4+include /usr/share/dpkg/default.mk
5+
4# Uncomment this to turn on verbose mode.
6# Uncomment this to turn on verbose mode.
5#export DH_VERBOSE=1
7#export DH_VERBOSE=1
6export DPKG_GENSYMBOLS_CHECK_LEVEL=4
8export DPKG_GENSYMBOLS_CHECK_LEVEL=4
7export NO_PNG_PKG_MANGLE=1
9export NO_PNG_PKG_MANGLE=1
8
10
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+
9%:
16%:
10 dh $@ --parallel --fail-missing --with python2,python3
17 dh $@ --parallel --fail-missing --with python2,python3
11
18
plugins/Dash/ScopeStyle.qml+6
@@ -70,6 +70,12 @@ QtObject {
70 /// Source of the logo image for the header
70 /// Source of the logo image for the header
71 readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
71 readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
72
72
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+
73 //! @cond
79 //! @cond
74 property var d: QtObject {
80 property var d: QtObject {
75 readonly property real foregroundLuminance: luminance(foreground)
81 readonly property real foregroundLuminance: luminance(foreground)
plugins/Dash/listviewwithpageheader.cpp+1−6
@@ -141,8 +141,6 @@ void ListViewWithPageHeader::ListItem::setCulled(bool culled)
141void ListViewWithPageHeader::ListItem::setSectionItem(QQuickItem *sectionItem)
141void ListViewWithPageHeader::ListItem::setSectionItem(QQuickItem *sectionItem)
142{
142{
143 m_sectionItem = sectionItem;
143 m_sectionItem = sectionItem;
144− QQmlContext *context = QQmlEngine::contextForObject(m_item)->parentContext();
145− context->setContextProperty(QLatin1String("hasSectionHeader"), QVariant::fromValue<bool>(sectionItem != nullptr));
146}
144}
147
145
148ListViewWithPageHeader::ListViewWithPageHeader()
146ListViewWithPageHeader::ListViewWithPageHeader()
@@ -658,7 +656,7 @@ void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
658 if (flags & QQmlDelegateModel::Destroyed) {
656 if (flags & QQmlDelegateModel::Destroyed) {
659 item->setParentItem(nullptr);
657 item->setParentItem(nullptr);
660 }
658 }
661− delete listItem->sectionItem();
659+ listItem->sectionItem()->deleteLater();
662 delete listItem;
660 delete listItem;
663}
661}
664
662
@@ -685,8 +683,6 @@ QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyI
685 return nullptr;
683 return nullptr;
686
684
687 const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
685 const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
688− if (section.isEmpty())
689− return nullptr;
690
686
691 if (modelIndex > 0) {
687 if (modelIndex > 0) {
692 const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
688 const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
@@ -877,7 +873,6 @@ void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
877 QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
873 QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
878 context->setContextProperty(QLatin1String("ListViewWithPageHeader"), this);
874 context->setContextProperty(QLatin1String("ListViewWithPageHeader"), this);
879 context->setContextProperty(QLatin1String("heightToClip"), QVariant::fromValue<int>(0));
875 context->setContextProperty(QLatin1String("heightToClip"), QVariant::fromValue<int>(0));
880− context->setContextProperty(QLatin1String("hasSectionHeader"), QVariant::fromValue<bool>(false));
881 if (modelIndex == m_asyncRequestedIndex) {
876 if (modelIndex == m_asyncRequestedIndex) {
882 createItem(modelIndex, false);
877 createItem(modelIndex, false);
883 refill();
878 refill();
plugins/Ubuntu/Payments/CMakeLists.txt+1−1
@@ -14,7 +14,7 @@ qt5_use_modules(Payments Qml Quick DBus Core)
14
14
15add_unity8_plugin(Ubuntu.Payments 0.1 Ubuntu/Payments TARGETS Payments)
15add_unity8_plugin(Ubuntu.Payments 0.1 Ubuntu/Payments TARGETS Payments)
16
16
17−pkg_check_modules(LIBPAY REQUIRED pay-1)
17+pkg_check_modules(LIBPAY REQUIRED pay-2)
18add_definitions(${LIBPAY_CFLAGS} ${LIBPAY_CFLAGS_OTHER})
18add_definitions(${LIBPAY_CFLAGS} ${LIBPAY_CFLAGS_OTHER})
19
19
20target_link_libraries(Payments ${LIBPAY_LDFLAGS})
20target_link_libraries(Payments ${LIBPAY_LDFLAGS})
plugins/Unity/Launcher/launchermodel.cpp+3−2
@@ -141,7 +141,8 @@ void LauncherModel::pin(const QString &appId, int index)
141 beginInsertRows(QModelIndex(), index, index);
141 beginInsertRows(QModelIndex(), index, index);
142 LauncherItem *item = new LauncherItem(appId,
142 LauncherItem *item = new LauncherItem(appId,
143 m_backend->displayName(appId),
143 m_backend->displayName(appId),
144− m_backend->icon(appId));
144+ m_backend->icon(appId),
145+ this);
145 item->setPinned(true);
146 item->setPinned(true);
146 m_list.insert(index, item);
147 m_list.insert(index, item);
147 endInsertRows();
148 endInsertRows();
@@ -326,7 +327,7 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
326 if (found) {
327 if (found) {
327 // Shall we paint some running/recent app highlight? If yes, do it here.
328 // Shall we paint some running/recent app highlight? If yes, do it here.
328 } else {
329 } 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);
330 item->setRecent(true);
331 item->setRecent(true);
331 item->setFocused(app->focused());
332 item->setFocused(app->focused());
332
333
po/da.po+52−49
@@ -1,199 +1,202 @@
1# Danish translation for unity8
1# Danish translation for unity8
2# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
2# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
3# This file is distributed under the same license as the unity8 package.
3# 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.
5#
6#
6msgid ""
7msgid ""
7msgstr ""
8msgstr ""
8"Project-Id-Version: unity8\n"
9"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-01-14 20:16+0000\n"
12+"PO-Revision-Date: 2014-07-22 15:46+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13+"Last-Translator: Kenneth Ramsussen <kentora@kentora.dk>\n"
13−"Language-Team: Danish <da@li.org>\n"
14+"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
14"MIME-Version: 1.0\n"
15"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:36+0000\n"
18+"X-Launchpad-Export-Date: 2014-07-23 07:01+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
19+"X-Generator: Launchpad (build 17114)\n"
19
20
20#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:73
22#: plugins/Unity/Launcher/launcheritem.cpp:73
22msgid "Pin shortcut"
23msgid "Pin shortcut"
23−msgstr ""
24+msgstr "Fastgør genvej"
24
25
25#: plugins/Unity/Launcher/launcheritem.cpp:73
26#: plugins/Unity/Launcher/launcheritem.cpp:73
26msgid "Unpin shortcut"
27msgid "Unpin shortcut"
27−msgstr ""
28+msgstr "Gør genvej flytbar"
28
29
29#: qml/Components/EdgeDemoOverlay.qml:151
30#: qml/Components/EdgeDemoOverlay.qml:151
30msgid "Skip intro"
31msgid "Skip intro"
31−msgstr ""
32+msgstr "Spring intro over"
32
33
33#: qml/Components/EdgeDemo.qml:113
34#: qml/Components/EdgeDemo.qml:113
34msgid "Right edge"
35msgid "Right edge"
35−msgstr ""
36+msgstr "Højre kant"
36
37
37#: qml/Components/EdgeDemo.qml:114
38#: qml/Components/EdgeDemo.qml:114
38msgid "Try swiping from the right edge to unlock the phone"
39msgid "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"
40
41
41#: qml/Components/EdgeDemo.qml:145
42#: qml/Components/EdgeDemo.qml:145
42msgid "Top edge"
43msgid "Top edge"
43−msgstr ""
44+msgstr "Øvre kant"
44
45
45#: qml/Components/EdgeDemo.qml:146
46#: qml/Components/EdgeDemo.qml:146
46msgid "Try swiping from the top edge to access the indicators"
47msgid "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"
48
49
49#: qml/Components/EdgeDemo.qml:171
50#: qml/Components/EdgeDemo.qml:171
50msgid "Close"
51msgid "Close"
51−msgstr ""
52+msgstr "Luk"
52
53
53#: qml/Components/EdgeDemo.qml:172
54#: qml/Components/EdgeDemo.qml:172
54msgid "Swipe up again to close the settings screen"
55msgid "Swipe up again to close the settings screen"
55−msgstr ""
56+msgstr "Stryg op igen for at låse indstillingsskærmen"
56
57
57#: qml/Components/EdgeDemo.qml:199
58#: qml/Components/EdgeDemo.qml:199
58msgid "Left edge"
59msgid "Left edge"
59−msgstr ""
60+msgstr "Venstre kant"
60
61
61#: qml/Components/EdgeDemo.qml:200
62#: qml/Components/EdgeDemo.qml:200
62msgid "Swipe from the left to reveal the launcher for quick access to apps"
63msgid "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"
64
65
65#: qml/Components/EdgeDemo.qml:227
66#: qml/Components/EdgeDemo.qml:227
66msgid "Well done"
67msgid "Well done"
67−msgstr ""
68+msgstr "Godt gjort"
68
69
69#: qml/Components/EdgeDemo.qml:228
70#: qml/Components/EdgeDemo.qml:228
70msgid ""
71msgid ""
71"You have now mastered the edge gestures and can start using the "
72"You have now mastered the edge gestures and can start using the "
72"phone<br><br>Tap on the screen to start"
73"phone<br><br>Tap on the screen to start"
73msgstr ""
74msgstr ""
75+"Du mestrer nu kantgestusserne og kan begynde at bruge telefonen<br><br>Tryk "
76+"på skærmen for at starte"
74
77
75#: qml/Components/Lockscreen.qml:214
78#: qml/Components/Lockscreen.qml:214
76msgid "Emergency Call"
79msgid "Emergency Call"
77−msgstr ""
80+msgstr "Nødopkald"
78
81
79#: qml/Components/Lockscreen.qml:231
82#: qml/Components/Lockscreen.qml:231
80msgid "OK"
83msgid "OK"
81−msgstr ""
84+msgstr "O.k."
82
85
83#: qml/Components/PageHeader.qml:366
86#: qml/Components/PageHeader.qml:366
84msgid "Recent searches"
87msgid "Recent searches"
85−msgstr ""
88+msgstr "Seneste søgninger"
86
89
87#: qml/Components/PassphraseLockscreen.qml:60
90#: qml/Components/PassphraseLockscreen.qml:60
88#, qt-format
91#, qt-format
89msgid "Hello %1"
92msgid "Hello %1"
90−msgstr ""
93+msgstr "Hej %1"
91
94
92#: qml/Components/PassphraseLockscreen.qml:60
95#: qml/Components/PassphraseLockscreen.qml:60
93msgid "Hello"
96msgid "Hello"
94−msgstr ""
97+msgstr "Hej"
95
98
96#: qml/Components/PinLockscreen.qml:198
99#: qml/Components/PinLockscreen.qml:198
97msgid "CANCEL"
100msgid "CANCEL"
98−msgstr ""
101+msgstr "ANNULLÉR"
99
102
100#: qml/Components/PinLockscreen.qml:216
103#: qml/Components/PinLockscreen.qml:216
101msgid "DONE"
104msgid "DONE"
102−msgstr ""
105+msgstr "FÆRDIG"
103
106
104#: qml/Components/SeeMore.qml:35
107#: qml/Components/SeeMore.qml:35
105msgid "See more"
108msgid "See more"
106−msgstr ""
109+msgstr "Vis mere"
107
110
108#: qml/Components/SeeMore.qml:58
111#: qml/Components/SeeMore.qml:58
109msgid "See less"
112msgid "See less"
110−msgstr ""
113+msgstr "Vis mindre"
111
114
112#: qml/Dash/DashApps.qml:37
115#: qml/Dash/DashApps.qml:37
113msgid "Recent"
116msgid "Recent"
114−msgstr ""
117+msgstr "Seneste"
115
118
116#: qml/Dash/Previews/PreviewActionCombo.qml:34
119#: qml/Dash/Previews/PreviewActionCombo.qml:34
117msgid "More..."
120msgid "More..."
118−msgstr ""
121+msgstr "Mere..."
119
122
120#: qml/Dash/Previews/PreviewActionCombo.qml:34
123#: qml/Dash/Previews/PreviewActionCombo.qml:34
121msgid "Less..."
124msgid "Less..."
122−msgstr ""
125+msgstr "Mindre..."
123
126
124#: qml/Dash/Previews/PreviewRatingInput.qml:82
127#: qml/Dash/Previews/PreviewRatingInput.qml:82
125msgid "Rate this"
128msgid "Rate this"
126−msgstr ""
129+msgstr "Bedøm dette"
127
130
128#: qml/Dash/Previews/PreviewRatingInput.qml:128
131#: qml/Dash/Previews/PreviewRatingInput.qml:128
129msgid "Add a review"
132msgid "Add a review"
130−msgstr ""
133+msgstr "Tilføj en forhåndsvisning"
131
134
132#: qml/Dash/Previews/PreviewRatingInput.qml:168
135#: qml/Dash/Previews/PreviewRatingInput.qml:168
133msgid "Send"
136msgid "Send"
134−msgstr ""
137+msgstr "Send"
135
138
136#: qml/Greeter/Greeter.qml:157
139#: qml/Greeter/Greeter.qml:157
137msgid "Swipe to unlock"
140msgid "Swipe to unlock"
138−msgstr ""
141+msgstr "Stryg for at låse op"
139
142
140#: qml/Hud/HudParametrizedActionsPage.qml:132
143#: qml/Hud/HudParametrizedActionsPage.qml:132
141msgid "Confirm"
144msgid "Confirm"
142−msgstr ""
145+msgstr "Bekræft"
143
146
144#: qml/Hud/Hud.qml:61 qml/Hud/Hud.qml:99 qml/Hud/Hud.qml:372
147#: qml/Hud/Hud.qml:61 qml/Hud/Hud.qml:99 qml/Hud/Hud.qml:372
145msgid "Type or say a command"
148msgid "Type or say a command"
146−msgstr ""
149+msgstr "Skriv eller indtal en kommando"
147
150
148#: qml/Hud/Hud.qml:84
151#: qml/Hud/Hud.qml:84
149msgid "Loading. Please Wait..."
152msgid "Loading. Please Wait..."
150−msgstr ""
153+msgstr "Indlæser. Vent venligst..."
151
154
152#: qml/Hud/Hud.qml:89
155#: qml/Hud/Hud.qml:89
153msgid "Speak Now..."
156msgid "Speak Now..."
154−msgstr ""
157+msgstr "Tal nu..."
155
158
156#: qml/Hud/Hud.qml:94
159#: qml/Hud/Hud.qml:94
157msgid "Speaking..."
160msgid "Speaking..."
158−msgstr ""
161+msgstr "Taler..."
159
162
160#: qml/Notifications/NotificationMenuItemFactory.qml:91
163#: qml/Notifications/NotificationMenuItemFactory.qml:91
161msgid "Show password"
164msgid "Show password"
162−msgstr ""
165+msgstr "Vis adgangskode"
163
166
164#: qml/Notifications/NotificationMenuItemFactory.qml:103
167#: qml/Notifications/NotificationMenuItemFactory.qml:103
165msgid "Please enter SIM PIN"
168msgid "Please enter SIM PIN"
166−msgstr ""
169+msgstr "Indtast venligst PIN for SIM"
167
170
168#: qml/Panel/Indicators/MenuItemFactory.qml:583
171#: qml/Panel/Indicators/MenuItemFactory.qml:583
169msgid "In queue…"
172msgid "In queue…"
170−msgstr ""
173+msgstr "I kø…"
171
174
172#: qml/Panel/Indicators/MenuItemFactory.qml:587
175#: qml/Panel/Indicators/MenuItemFactory.qml:587
173msgid "Downloading"
176msgid "Downloading"
174−msgstr ""
177+msgstr "Henter"
175
178
176#: qml/Panel/Indicators/MenuItemFactory.qml:589
179#: qml/Panel/Indicators/MenuItemFactory.qml:589
177msgid "Paused, tap to resume"
180msgid "Paused, tap to resume"
178−msgstr ""
181+msgstr "På pause; tryk for at fortsætte"
179
182
180#: qml/Panel/Indicators/MenuItemFactory.qml:591
183#: qml/Panel/Indicators/MenuItemFactory.qml:591
181msgid "Canceled"
184msgid "Canceled"
182−msgstr ""
185+msgstr "Annulleret"
183
186
184#: qml/Panel/Indicators/MenuItemFactory.qml:593
187#: qml/Panel/Indicators/MenuItemFactory.qml:593
185msgid "Finished"
188msgid "Finished"
186−msgstr ""
189+msgstr "Færdig"
187
190
188#: qml/Panel/Indicators/MenuItemFactory.qml:595
191#: qml/Panel/Indicators/MenuItemFactory.qml:595
189msgid "Failed, tap to retry"
192msgid "Failed, tap to retry"
190−msgstr ""
193+msgstr "Mislykkedes; tryk for at prøve igen"
191
194
192#: qml/Panel/SearchIndicator.qml:27
195#: qml/Panel/SearchIndicator.qml:27
193msgid "Search"
196msgid "Search"
194−msgstr ""
197+msgstr "Søg"
195
198
196#: qml/Shell.qml:359
199#: qml/Shell.qml:359
197#, qt-format
200#, qt-format
198msgid "Please enter %1"
201msgid "Please enter %1"
199−msgstr ""
202+msgstr "Indtast venligst %1"
po/gd.po+3−3
@@ -8,13 +8,13 @@ msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10"POT-Creation-Date: 2014-07-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"
12"Last-Translator: GunChleoc <Unknown>\n"
12"Last-Translator: GunChleoc <Unknown>\n"
13"Language-Team: Fòram na Gàidhlig http://www.foramnagaidhlig.net\n"
13"Language-Team: Fòram na Gàidhlig http://www.foramnagaidhlig.net\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"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"
18"X-Generator: Launchpad (build 17114)\n"
18"X-Generator: Launchpad (build 17114)\n"
19"Language: gd\n"
19"Language: gd\n"
20
20
@@ -87,7 +87,7 @@ msgstr "Gairm èiginn"
87
87
88#: qml/Components/Lockscreen.qml:231
88#: qml/Components/Lockscreen.qml:231
89msgid "OK"
89msgid "OK"
90−msgstr "Ceart ma-hà"
90+msgstr "Ceart ma-thà"
91
91
92#: qml/Components/PageHeader.qml:366
92#: qml/Components/PageHeader.qml:366
93msgid "Recent searches"
93msgid "Recent searches"
po/gl.po+4−4
@@ -8,13 +8,13 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10"POT-Creation-Date: 2014-07-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"
12"Last-Translator: Marcos Lans <Unknown>\n"
12"Last-Translator: Marcos Lans <Unknown>\n"
13"Language-Team: Galician <gl@li.org>\n"
13"Language-Team: Galician <gl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"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"
18"X-Generator: Launchpad (build 17114)\n"
18"X-Generator: Launchpad (build 17114)\n"
19
19
20#: plugins/Unity/Launcher/launcheritem.cpp:43
20#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -61,12 +61,12 @@ msgstr "Bordo esquerdo"
61#: qml/Components/EdgeDemo.qml:200
61#: qml/Components/EdgeDemo.qml:200
62msgid "Swipe from the left to reveal the launcher for quick access to apps"
62msgid "Swipe from the left to reveal the launcher for quick access to apps"
63msgstr ""
63msgstr ""
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 "
65"aplicativos"
65"aplicativos"
66
66
67#: qml/Components/EdgeDemo.qml:227
67#: qml/Components/EdgeDemo.qml:227
68msgid "Well done"
68msgid "Well done"
69−msgstr "Ben feito"
69+msgstr "Ben feito!"
70
70
71#: qml/Components/EdgeDemo.qml:228
71#: qml/Components/EdgeDemo.qml:228
72msgid ""
72msgid ""
po/hu.po+24−22
@@ -8,23 +8,23 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-01-14 23:02+0000\n"
11+"PO-Revision-Date: 2014-07-24 08:19+0000\n"
12−"Last-Translator: Kristóf Kiszel <Unknown>\n"
12+"Last-Translator: Gabor Kelemen <kelemeng@openscope.org>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2014-07-25 07:54+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
18+"X-Generator: Launchpad (build 17114)\n"
19
19
20#: plugins/Unity/Launcher/launcheritem.cpp:43
20#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:73
21#: plugins/Unity/Launcher/launcheritem.cpp:73
22msgid "Pin shortcut"
22msgid "Pin shortcut"
23−msgstr ""
23+msgstr "Indító rögzítése"
24
24
25#: plugins/Unity/Launcher/launcheritem.cpp:73
25#: plugins/Unity/Launcher/launcheritem.cpp:73
26msgid "Unpin shortcut"
26msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "Indító feloldása"
28
28
29#: qml/Components/EdgeDemoOverlay.qml:151
29#: qml/Components/EdgeDemoOverlay.qml:151
30msgid "Skip intro"
30msgid "Skip intro"
@@ -73,6 +73,8 @@ msgid ""
73"You have now mastered the edge gestures and can start using the "
73"You have now mastered the edge gestures and can start using the "
74"phone<br><br>Tap on the screen to start"
74"phone<br><br>Tap on the screen to start"
75msgstr ""
75msgstr ""
76+"Elsajátította a gesztusokat, és megkezdheti a telefon "
77+"használatát.<br><br>Koppintson a képernyőre a kezdéshez."
76
78
77#: qml/Components/Lockscreen.qml:214
79#: qml/Components/Lockscreen.qml:214
78msgid "Emergency Call"
80msgid "Emergency Call"
@@ -80,7 +82,7 @@ msgstr "Vészhívás"
80
82
81#: qml/Components/Lockscreen.qml:231
83#: qml/Components/Lockscreen.qml:231
82msgid "OK"
84msgid "OK"
83−msgstr ""
85+msgstr "OK"
84
86
85#: qml/Components/PageHeader.qml:366
87#: qml/Components/PageHeader.qml:366
86msgid "Recent searches"
88msgid "Recent searches"
@@ -97,31 +99,31 @@ msgstr "Szia"
97
99
98#: qml/Components/PinLockscreen.qml:198
100#: qml/Components/PinLockscreen.qml:198
99msgid "CANCEL"
101msgid "CANCEL"
100−msgstr ""
102+msgstr "MÉGSE"
101
103
102#: qml/Components/PinLockscreen.qml:216
104#: qml/Components/PinLockscreen.qml:216
103msgid "DONE"
105msgid "DONE"
104−msgstr ""
106+msgstr "KÉSZ"
105
107
106#: qml/Components/SeeMore.qml:35
108#: qml/Components/SeeMore.qml:35
107msgid "See more"
109msgid "See more"
108−msgstr ""
110+msgstr "Több"
109
111
110#: qml/Components/SeeMore.qml:58
112#: qml/Components/SeeMore.qml:58
111msgid "See less"
113msgid "See less"
112−msgstr ""
114+msgstr "Kevesebb"
113
115
114#: qml/Dash/DashApps.qml:37
116#: qml/Dash/DashApps.qml:37
115msgid "Recent"
117msgid "Recent"
116−msgstr ""
118+msgstr "Legutóbbi"
117
119
118#: qml/Dash/Previews/PreviewActionCombo.qml:34
120#: qml/Dash/Previews/PreviewActionCombo.qml:34
119msgid "More..."
121msgid "More..."
120−msgstr ""
122+msgstr "Több…"
121
123
122#: qml/Dash/Previews/PreviewActionCombo.qml:34
124#: qml/Dash/Previews/PreviewActionCombo.qml:34
123msgid "Less..."
125msgid "Less..."
124−msgstr ""
126+msgstr "Kevesebb…"
125
127
126#: qml/Dash/Previews/PreviewRatingInput.qml:82
128#: qml/Dash/Previews/PreviewRatingInput.qml:82
127msgid "Rate this"
129msgid "Rate this"
@@ -137,7 +139,7 @@ msgstr "Küldés"
137
139
138#: qml/Greeter/Greeter.qml:157
140#: qml/Greeter/Greeter.qml:157
139msgid "Swipe to unlock"
141msgid "Swipe to unlock"
140−msgstr ""
142+msgstr "Csúsztasson a feloldáshoz"
141
143
142#: qml/Hud/HudParametrizedActionsPage.qml:132
144#: qml/Hud/HudParametrizedActionsPage.qml:132
143msgid "Confirm"
145msgid "Confirm"
@@ -165,31 +167,31 @@ msgstr "Jelszó megjelenítése"
165
167
166#: qml/Notifications/NotificationMenuItemFactory.qml:103
168#: qml/Notifications/NotificationMenuItemFactory.qml:103
167msgid "Please enter SIM PIN"
169msgid "Please enter SIM PIN"
168−msgstr ""
170+msgstr "Adja meg a SIM PIN kódját"
169
171
170#: qml/Panel/Indicators/MenuItemFactory.qml:583
172#: qml/Panel/Indicators/MenuItemFactory.qml:583
171msgid "In queue…"
173msgid "In queue…"
172−msgstr ""
174+msgstr "Sorban…"
173
175
174#: qml/Panel/Indicators/MenuItemFactory.qml:587
176#: qml/Panel/Indicators/MenuItemFactory.qml:587
175msgid "Downloading"
177msgid "Downloading"
176−msgstr ""
178+msgstr "Letöltés"
177
179
178#: qml/Panel/Indicators/MenuItemFactory.qml:589
180#: qml/Panel/Indicators/MenuItemFactory.qml:589
179msgid "Paused, tap to resume"
181msgid "Paused, tap to resume"
180−msgstr ""
182+msgstr "Szüneteltetve, koppintson a folytatáshoz"
181
183
182#: qml/Panel/Indicators/MenuItemFactory.qml:591
184#: qml/Panel/Indicators/MenuItemFactory.qml:591
183msgid "Canceled"
185msgid "Canceled"
184−msgstr ""
186+msgstr "Megszakítva"
185
187
186#: qml/Panel/Indicators/MenuItemFactory.qml:593
188#: qml/Panel/Indicators/MenuItemFactory.qml:593
187msgid "Finished"
189msgid "Finished"
188−msgstr ""
190+msgstr "Befejeződött"
189
191
190#: qml/Panel/Indicators/MenuItemFactory.qml:595
192#: qml/Panel/Indicators/MenuItemFactory.qml:595
191msgid "Failed, tap to retry"
193msgid "Failed, tap to retry"
192−msgstr ""
194+msgstr "Sikertelen, koppintson az újrapróbáláshoz"
193
195
194#: qml/Panel/SearchIndicator.qml:27
196#: qml/Panel/SearchIndicator.qml:27
195msgid "Search"
197msgid "Search"
po/is.po+22−17
@@ -1,30 +1,33 @@
1+# translation of po_unity8-is.po to icelandic
1# Icelandic translation for unity8
2# Icelandic translation for unity8
2# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
3# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
3# This file is distributed under the same license as the unity8 package.
4# This file is distributed under the same license as the unity8 package.
4−# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
5#
5#
6+# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
7+# Sveinn í Felli <sv1@fellsnet.is>, 2014.
6msgid ""
8msgid ""
7msgstr ""
9msgstr ""
8−"Project-Id-Version: unity8\n"
10+"Project-Id-Version: po_unity8-is\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
11"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-07-07 12:15+0100\n"
12"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"
12"Last-Translator: Sveinn í Felli <sv1@fellsnet.is>\n"
14"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"
14"MIME-Version: 1.0\n"
16"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
18"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"
18"X-Generator: Launchpad (build 17114)\n"
20"X-Generator: Launchpad (build 17114)\n"
21+"Language: is\n"
19
22
20#: plugins/Unity/Launcher/launcheritem.cpp:43
23#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:73
24#: plugins/Unity/Launcher/launcheritem.cpp:73
22msgid "Pin shortcut"
25msgid "Pin shortcut"
23−msgstr ""
26+msgstr "Pinna flýtilykil"
24
27
25#: plugins/Unity/Launcher/launcheritem.cpp:73
28#: plugins/Unity/Launcher/launcheritem.cpp:73
26msgid "Unpin shortcut"
29msgid "Unpin shortcut"
27−msgstr ""
30+msgstr "Losa flýtilykil"
28
31
29#: qml/Components/EdgeDemoOverlay.qml:151
32#: qml/Components/EdgeDemoOverlay.qml:151
30msgid "Skip intro"
33msgid "Skip intro"
@@ -37,7 +40,7 @@ msgstr "Hægri brún"
37#: qml/Components/EdgeDemo.qml:114
40#: qml/Components/EdgeDemo.qml:114
38msgid "Try swiping from the right edge to unlock the phone"
41msgid "Try swiping from the right edge to unlock the phone"
39msgstr ""
42msgstr ""
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."
41
44
42#: qml/Components/EdgeDemo.qml:145
45#: qml/Components/EdgeDemo.qml:145
43msgid "Top edge"
46msgid "Top edge"
@@ -45,7 +48,7 @@ msgstr "Efri brún"
45
48
46#: qml/Components/EdgeDemo.qml:146
49#: qml/Components/EdgeDemo.qml:146
47msgid "Try swiping from the top edge to access the indicators"
50msgid "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"
49
52
50#: qml/Components/EdgeDemo.qml:171
53#: qml/Components/EdgeDemo.qml:171
51msgid "Close"
54msgid "Close"
@@ -53,7 +56,7 @@ msgstr "Loka"
53
56
54#: qml/Components/EdgeDemo.qml:172
57#: qml/Components/EdgeDemo.qml:172
55msgid "Swipe up again to close the settings screen"
58msgid "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"
57
60
58#: qml/Components/EdgeDemo.qml:199
61#: qml/Components/EdgeDemo.qml:199
59msgid "Left edge"
62msgid "Left edge"
@@ -61,7 +64,7 @@ msgstr "Vinstri brún"
61
64
62#: qml/Components/EdgeDemo.qml:200
65#: qml/Components/EdgeDemo.qml:200
63msgid "Swipe from the left to reveal the launcher for quick access to apps"
66msgid "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"
65
68
66#: qml/Components/EdgeDemo.qml:227
69#: qml/Components/EdgeDemo.qml:227
67msgid "Well done"
70msgid "Well done"
@@ -72,6 +75,8 @@ msgid ""
72"You have now mastered the edge gestures and can start using the "
75"You have now mastered the edge gestures and can start using the "
73"phone<br><br>Tap on the screen to start"
76"phone<br><br>Tap on the screen to start"
74msgstr ""
77msgstr ""
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"
75
80
76#: qml/Components/Lockscreen.qml:214
81#: qml/Components/Lockscreen.qml:214
77msgid "Emergency Call"
82msgid "Emergency Call"
@@ -136,7 +141,7 @@ msgstr "Senda"
136
141
137#: qml/Greeter/Greeter.qml:157
142#: qml/Greeter/Greeter.qml:157
138msgid "Swipe to unlock"
143msgid "Swipe to unlock"
139−msgstr "Strjóka til að aflæsa"
144+msgstr "Strjúka til að aflæsa"
140
145
141#: qml/Hud/HudParametrizedActionsPage.qml:132
146#: qml/Hud/HudParametrizedActionsPage.qml:132
142msgid "Confirm"
147msgid "Confirm"
@@ -144,15 +149,15 @@ msgstr "Staðfesta"
144
149
145#: qml/Hud/Hud.qml:61 qml/Hud/Hud.qml:99 qml/Hud/Hud.qml:372
150#: qml/Hud/Hud.qml:61 qml/Hud/Hud.qml:99 qml/Hud/Hud.qml:372
146msgid "Type or say a command"
151msgid "Type or say a command"
147−msgstr "Skrifaðu eða segðu eitthvað"
152+msgstr "Skrifaðu eða segðu skipun"
148
153
149#: qml/Hud/Hud.qml:84
154#: qml/Hud/Hud.qml:84
150msgid "Loading. Please Wait..."
155msgid "Loading. Please Wait..."
151−msgstr "Hleð. Vinsamlegast Bíðið..."
156+msgstr "Hleð. Bíddu aðeins..."
152
157
153#: qml/Hud/Hud.qml:89
158#: qml/Hud/Hud.qml:89
154msgid "Speak Now..."
159msgid "Speak Now..."
155−msgstr "Talaðu Núna..."
160+msgstr "Tala núna..."
156
161
157#: qml/Hud/Hud.qml:94
162#: qml/Hud/Hud.qml:94
158msgid "Speaking..."
163msgid "Speaking..."
@@ -176,7 +181,7 @@ msgstr "Sæki"
176
181
177#: qml/Panel/Indicators/MenuItemFactory.qml:589
182#: qml/Panel/Indicators/MenuItemFactory.qml:589
178msgid "Paused, tap to resume"
183msgid "Paused, tap to resume"
179−msgstr ""
184+msgstr "Í bið, sláðu létt til að halda áfram"
180
185
181#: qml/Panel/Indicators/MenuItemFactory.qml:591
186#: qml/Panel/Indicators/MenuItemFactory.qml:591
182msgid "Canceled"
187msgid "Canceled"
@@ -188,7 +193,7 @@ msgstr "Lokið"
188
193
189#: qml/Panel/Indicators/MenuItemFactory.qml:595
194#: qml/Panel/Indicators/MenuItemFactory.qml:595
190msgid "Failed, tap to retry"
195msgid "Failed, tap to retry"
191−msgstr ""
196+msgstr "Mistókst, sláðu létt til að reyna aftur"
192
197
193#: qml/Panel/SearchIndicator.qml:27
198#: qml/Panel/SearchIndicator.qml:27
194msgid "Search"
199msgid "Search"
po/sl.po+11−11
@@ -8,23 +8,23 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10"POT-Creation-Date: 2014-07-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"
12"Last-Translator: Damir Jerovšek <Unknown>\n"
12"Last-Translator: Damir Jerovšek <Unknown>\n"
13"Language-Team: Slovenian <sl@li.org>\n"
13"Language-Team: Slovenian <sl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-09 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2014-07-25 07:54+0000\n"
18−"X-Generator: Launchpad (build 17100)\n"
18+"X-Generator: Launchpad (build 17114)\n"
19
19
20#: plugins/Unity/Launcher/launcheritem.cpp:43
20#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:73
21#: plugins/Unity/Launcher/launcheritem.cpp:73
22msgid "Pin shortcut"
22msgid "Pin shortcut"
23−msgstr ""
23+msgstr "Pripni bližnjico"
24
24
25#: plugins/Unity/Launcher/launcheritem.cpp:73
25#: plugins/Unity/Launcher/launcheritem.cpp:73
26msgid "Unpin shortcut"
26msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "Odpni bližnjico"
28
28
29#: qml/Components/EdgeDemoOverlay.qml:151
29#: qml/Components/EdgeDemoOverlay.qml:151
30msgid "Skip intro"
30msgid "Skip intro"
@@ -171,27 +171,27 @@ msgstr "Vnesite PIN kartice SIM"
171
171
172#: qml/Panel/Indicators/MenuItemFactory.qml:583
172#: qml/Panel/Indicators/MenuItemFactory.qml:583
173msgid "In queue…"
173msgid "In queue…"
174−msgstr ""
174+msgstr "V vrsti ..."
175
175
176#: qml/Panel/Indicators/MenuItemFactory.qml:587
176#: qml/Panel/Indicators/MenuItemFactory.qml:587
177msgid "Downloading"
177msgid "Downloading"
178−msgstr ""
178+msgstr "Prejemanje"
179
179
180#: qml/Panel/Indicators/MenuItemFactory.qml:589
180#: qml/Panel/Indicators/MenuItemFactory.qml:589
181msgid "Paused, tap to resume"
181msgid "Paused, tap to resume"
182−msgstr ""
182+msgstr "Premor, tapnite za nadaljevanje"
183
183
184#: qml/Panel/Indicators/MenuItemFactory.qml:591
184#: qml/Panel/Indicators/MenuItemFactory.qml:591
185msgid "Canceled"
185msgid "Canceled"
186−msgstr ""
186+msgstr "Preklicano"
187
187
188#: qml/Panel/Indicators/MenuItemFactory.qml:593
188#: qml/Panel/Indicators/MenuItemFactory.qml:593
189msgid "Finished"
189msgid "Finished"
190−msgstr ""
190+msgstr "Končano"
191
191
192#: qml/Panel/Indicators/MenuItemFactory.qml:595
192#: qml/Panel/Indicators/MenuItemFactory.qml:595
193msgid "Failed, tap to retry"
193msgid "Failed, tap to retry"
194−msgstr ""
194+msgstr "Spodletelo, tapnite za ponovni poskus"
195
195
196#: qml/Panel/SearchIndicator.qml:27
196#: qml/Panel/SearchIndicator.qml:27
197msgid "Search"
197msgid "Search"
po/sv.po+19−18
@@ -1,21 +1,22 @@
1# Swedish translation for unity
1# 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
3# This file is distributed under the same license as the unity package.
3# 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.
5#
5#
6msgid ""
6msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-07-07 12:15+0100\n"
10"POT-Creation-Date: 2014-07-07 12:15+0100\n"
11−"PO-Revision-Date: 2014-07-20 19:14+0000\n"
11+"PO-Revision-Date: 2014-07-24 13:56+0000\n"
12−"Last-Translator: Gunnar Hjalmarsson <Unknown>\n"
12+"Last-Translator: Josef Andersson <Unknown>\n"
13−"Language-Team: Swedish <sv@li.org>\n"
13+"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"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"
18"X-Generator: Launchpad (build 17114)\n"
18"X-Generator: Launchpad (build 17114)\n"
19+"Language: sv\n"
19
20
20#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:73
22#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -28,7 +29,7 @@ msgstr "Släpp genväg"
28
29
29#: qml/Components/EdgeDemoOverlay.qml:151
30#: qml/Components/EdgeDemoOverlay.qml:151
30msgid "Skip intro"
31msgid "Skip intro"
31−msgstr "Skippa intro"
32+msgstr "Hoppa över introduktion"
32
33
33#: qml/Components/EdgeDemo.qml:113
34#: qml/Components/EdgeDemo.qml:113
34msgid "Right edge"
35msgid "Right edge"
@@ -36,7 +37,7 @@ msgstr "Högerkant"
36
37
37#: qml/Components/EdgeDemo.qml:114
38#: qml/Components/EdgeDemo.qml:114
38msgid "Try swiping from the right edge to unlock the phone"
39msgid "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"
40
41
41#: qml/Components/EdgeDemo.qml:145
42#: qml/Components/EdgeDemo.qml:145
42msgid "Top edge"
43msgid "Top edge"
@@ -71,8 +72,8 @@ msgid ""
71"You have now mastered the edge gestures and can start using the "
72"You have now mastered the edge gestures and can start using the "
72"phone<br><br>Tap on the screen to start"
73"phone<br><br>Tap on the screen to start"
73msgstr ""
74msgstr ""
74−"Du har nu bemästrat kantgesterna och kan börja använda telefonen<br><br>Peka "
75+"Du har nu bemästrat kantgesterna och kan börja använda "
75−"på skärmen för att starta"
76+"telefonen<br><br>Tryck på skärmen för att starta"
76
77
77#: qml/Components/Lockscreen.qml:214
78#: qml/Components/Lockscreen.qml:214
78msgid "Emergency Call"
79msgid "Emergency Call"
@@ -117,11 +118,11 @@ msgstr "Senaste"
117
118
118#: qml/Dash/Previews/PreviewActionCombo.qml:34
119#: qml/Dash/Previews/PreviewActionCombo.qml:34
119msgid "More..."
120msgid "More..."
120−msgstr "Mer..."
121+msgstr "Mer…"
121
122
122#: qml/Dash/Previews/PreviewActionCombo.qml:34
123#: qml/Dash/Previews/PreviewActionCombo.qml:34
123msgid "Less..."
124msgid "Less..."
124−msgstr "Mindre..."
125+msgstr "Mindre…"
125
126
126#: qml/Dash/Previews/PreviewRatingInput.qml:82
127#: qml/Dash/Previews/PreviewRatingInput.qml:82
127msgid "Rate this"
128msgid "Rate this"
@@ -149,15 +150,15 @@ msgstr "Skriv eller tala in ett kommando"
149
150
150#: qml/Hud/Hud.qml:84
151#: qml/Hud/Hud.qml:84
151msgid "Loading. Please Wait..."
152msgid "Loading. Please Wait..."
152−msgstr "Laddar. Var god vänta..."
153+msgstr "Läser in. Var god vänta…"
153
154
154#: qml/Hud/Hud.qml:89
155#: qml/Hud/Hud.qml:89
155msgid "Speak Now..."
156msgid "Speak Now..."
156−msgstr "Tala nu..."
157+msgstr "Tala nu…"
157
158
158#: qml/Hud/Hud.qml:94
159#: qml/Hud/Hud.qml:94
159msgid "Speaking..."
160msgid "Speaking..."
160−msgstr "Talar..."
161+msgstr "Talar…"
161
162
162#: qml/Notifications/NotificationMenuItemFactory.qml:91
163#: qml/Notifications/NotificationMenuItemFactory.qml:91
163msgid "Show password"
164msgid "Show password"
@@ -169,7 +170,7 @@ msgstr "Ange SIM PIN-kod"
169
170
170#: qml/Panel/Indicators/MenuItemFactory.qml:583
171#: qml/Panel/Indicators/MenuItemFactory.qml:583
171msgid "In queue…"
172msgid "In queue…"
172−msgstr "I kö..."
173+msgstr "I kö…"
173
174
174#: qml/Panel/Indicators/MenuItemFactory.qml:587
175#: qml/Panel/Indicators/MenuItemFactory.qml:587
175msgid "Downloading"
176msgid "Downloading"
@@ -177,7 +178,7 @@ msgstr "Hämtar"
177
178
178#: qml/Panel/Indicators/MenuItemFactory.qml:589
179#: qml/Panel/Indicators/MenuItemFactory.qml:589
179msgid "Paused, tap to resume"
180msgid "Paused, tap to resume"
180−msgstr "Pausad, peka för att fortsätta"
181+msgstr "Pausad, tryck för att fortsätta"
181
182
182#: qml/Panel/Indicators/MenuItemFactory.qml:591
183#: qml/Panel/Indicators/MenuItemFactory.qml:591
183msgid "Canceled"
184msgid "Canceled"
@@ -189,7 +190,7 @@ msgstr "Klart"
189
190
190#: qml/Panel/Indicators/MenuItemFactory.qml:595
191#: qml/Panel/Indicators/MenuItemFactory.qml:595
191msgid "Failed, tap to retry"
192msgid "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"
193
194
194#: qml/Panel/SearchIndicator.qml:27
195#: qml/Panel/SearchIndicator.qml:27
195msgid "Search"
196msgid "Search"
po/ug.po+1−1
@@ -14,7 +14,7 @@ msgstr ""
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"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"
18"X-Generator: Launchpad (build 17114)\n"
18"X-Generator: Launchpad (build 17114)\n"
19
19
20#: plugins/Unity/Launcher/launcheritem.cpp:43
20#: plugins/Unity/Launcher/launcheritem.cpp:43
po/unity8.pot+17−9
@@ -8,7 +8,7 @@ msgid ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity8\n"
9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: \n"
10"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"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -80,10 +80,6 @@ msgstr ""
80msgid "OK"
80msgid "OK"
81msgstr ""
81msgstr ""
82
82
83−#: qml/Components/PageHeader.qml:366
84−msgid "Recent searches"
85−msgstr ""
86−
87#: qml/Components/PassphraseLockscreen.qml:60
83#: qml/Components/PassphraseLockscreen.qml:60
88#, qt-format
84#, qt-format
89msgid "Hello %1"
85msgid "Hello %1"
@@ -105,7 +101,7 @@ msgstr ""
105msgid "See more"
101msgid "See more"
106msgstr ""
102msgstr ""
107
103
108−#: qml/Components/SeeMore.qml:58
104+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
109msgid "See less"
105msgid "See less"
110msgstr ""
106msgstr ""
111
107
@@ -113,6 +109,10 @@ msgstr ""
113msgid "Recent"
109msgid "Recent"
114msgstr ""
110msgstr ""
115
111
112+#: qml/Dash/GenericScopeView.qml:330
113+msgid "See all"
114+msgstr ""
115+
116#: qml/Dash/Previews/PreviewActionCombo.qml:34
116#: qml/Dash/Previews/PreviewActionCombo.qml:34
117msgid "More..."
117msgid "More..."
118msgstr ""
118msgstr ""
@@ -121,15 +121,15 @@ msgstr ""
121msgid "Less..."
121msgid "Less..."
122msgstr ""
122msgstr ""
123
123
124−#: qml/Dash/Previews/PreviewRatingInput.qml:82
124+#: qml/Dash/Previews/PreviewRatingInput.qml:81
125msgid "Rate this"
125msgid "Rate this"
126msgstr ""
126msgstr ""
127
127
128−#: qml/Dash/Previews/PreviewRatingInput.qml:128
128+#: qml/Dash/Previews/PreviewRatingInput.qml:126
129msgid "Add a review"
129msgid "Add a review"
130msgstr ""
130msgstr ""
131
131
132−#: qml/Dash/Previews/PreviewRatingInput.qml:168
132+#: qml/Dash/Previews/PreviewRatingInput.qml:166
133msgid "Send"
133msgid "Send"
134msgstr ""
134msgstr ""
135
135
@@ -165,6 +165,14 @@ msgstr ""
165msgid "Please enter SIM PIN"
165msgid "Please enter SIM PIN"
166msgstr ""
166msgstr ""
167
167
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+
168#: qml/Panel/Indicators/MenuItemFactory.qml:583
176#: qml/Panel/Indicators/MenuItemFactory.qml:583
169msgid "In queue…"
177msgid "In queue…"
170msgstr ""
178msgstr ""
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 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013,2014 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -15,54 +15,45 @@
15 */
15 */
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18+import QtQuick.Layouts 1.1
18import Ubuntu.Components 0.1
19import Ubuntu.Components 0.1
19
20
20Item {
21Item {
21− /*!
22− \preliminary
23− The text that is shown as the header text.
24− \qmlproperty string text
25− */
26 property alias text: label.text
22 property alias text: label.text
27− property alias textColor: label.color
23+ property alias color: label.color
28− property alias image: image.source
24+ property alias iconName: icon.name
29
25
30 signal clicked(variant mouse)
26 signal clicked(variant mouse)
31
27
32 height: units.gu(5)
28 height: units.gu(5)
33
29
34− Item {
30+ RowLayout {
31+ spacing: units.gu(.5)
35 anchors {
32 anchors {
36 left: parent.left
33 left: parent.left
37 right: parent.right
34 right: parent.right
35+ verticalCenter: parent.verticalCenter
38− rightMargin: units.gu(0.5)
36+ margins: units.gu(1)
39− top: parent.top
40− bottom: parent.bottom
41 }
37 }
42
38
43 Label {
39 Label {
44 id: label
40 id: label
45− anchors {
41+ Layout.fillWidth: true
46− left: parent.left
47− leftMargin: units.gu(2)
48− verticalCenter: parent.verticalCenter
49− }
50
42
51− color: "grey" // TODO karni: Update Ubuntu.Compoonents.Themes.Palette.
52 font.family: "Ubuntu"
43 font.family: "Ubuntu"
53 fontSize: "medium"
44 fontSize: "medium"
54 elide: Text.ElideRight
45 elide: Text.ElideRight
46+ maximumLineCount: 1
55 textFormat: Text.PlainText
47 textFormat: Text.PlainText
56− width: parent.width - image.width - image.leftMargin - anchors.leftMargin
48+ width: Math.min(parent.width - units.gu(4), implicitWidth)
57 }
49 }
58
50
59− Image {
51+ Icon {
60− id: image
52+ id: icon
61− readonly property double leftMargin: units.gu(1)
53+ visible: name != ""
62− x: label.x + label.contentWidth + leftMargin
54+ height: units.gu(2)
63− anchors {
55+ width: height
64− verticalCenter: parent.verticalCenter
56+ color: label.color
65− }
66 }
57 }
67 }
58 }
68
59
qml/Components/Lockscreen.qml+17−5
@@ -186,6 +186,17 @@ Showable {
186 }
186 }
187
187
188 Column {
188 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+
189 anchors {
200 anchors {
190 left: parent.left
201 left: parent.left
191 bottom: parent.bottom
202 bottom: parent.bottom
@@ -203,11 +214,6 @@ Showable {
203 name: "phone-app-call-symbolic"
214 name: "phone-app-call-symbolic"
204 color: "#f3f3e7"
215 color: "#f3f3e7"
205 opacity: 0.6
216 opacity: 0.6
206−
207− MouseArea {
208− anchors.fill: parent
209− onClicked: root.emergencyCall()
210− }
211 }
217 }
212
218
213 Label {
219 Label {
@@ -219,6 +225,12 @@ Showable {
219 }
225 }
220 }
226 }
221
227
228+ MouseArea {
229+ anchors.fill: emergencyCallColumn
230+ onClicked: root.emergencyCall()
231+ enabled: emergencyCallColumn.visible
232+ }
233+
222 Component {
234 Component {
223 id: infoPopupComponent
235 id: infoPopupComponent
224 Dialog {
236 Dialog {
qml/Components/PageHeader.qml+6−1
@@ -127,6 +127,11 @@ Item {
127 property bool showSearch: false
127 property bool showSearch: false
128 property var popover: null
128 property var popover: null
129
129
130+ Background {
131+ objectName: "headerBackground"
132+ style: scopeStyle.headerBackground
133+ }
134+
130 Behavior on contentY {
135 Behavior on contentY {
131 UbuntuNumberAnimation {
136 UbuntuNumberAnimation {
132 id: openSearchAnimation
137 id: openSearchAnimation
@@ -225,7 +230,7 @@ Item {
225 height: headerContainer.height
230 height: headerContainer.height
226 contentHeight: height
231 contentHeight: height
227 separatorSource: ""
232 separatorSource: ""
228− textColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
233+ textColor: root.scopeStyle ? root.scopeStyle.headerForeground : "grey"
229 property var styledItem: header
234 property var styledItem: header
230 property string title: root.title
235 property string title: root.title
231 property var config: PageHeadConfiguration {
236 property var config: PageHeadConfiguration {
qml/Components/ResponsiveGridView.qml+2−1
@@ -44,10 +44,11 @@ Item {
44 property alias displayMarginBeginning: gridView.displayMarginBeginning
44 property alias displayMarginBeginning: gridView.displayMarginBeginning
45 property alias displayMarginEnd: gridView.displayMarginEnd
45 property alias displayMarginEnd: gridView.displayMarginEnd
46 property alias highlightIndex: gridView.highlightIndex
46 property alias highlightIndex: gridView.highlightIndex
47+ property alias cacheBuffer: gridView.cacheBuffer
47 readonly property alias currentItem: gridView.currentItem
48 readonly property alias currentItem: gridView.currentItem
48
49
49 function contentHeightForRows(rows) {
50 function contentHeightForRows(rows) {
50− return rows * cellHeight + verticalSpacing
51+ return rows * cellHeight;
51 }
52 }
52
53
53 GridView {
54 GridView {
qml/Dash/CardCarousel.qml+2−7
@@ -21,13 +21,8 @@ import "../Components"
21DashRenderer {
21DashRenderer {
22 id: cardCarousel
22 id: cardCarousel
23
23
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
31
26
32 Carousel {
27 Carousel {
33 id: carousel
28 id: carousel
qml/Dash/CardFilterGrid.qml → qml/Dash/CardGrid.qmlrenamed+22−22
@@ -18,33 +18,33 @@ import QtQuick 2.0
18import "../Components"
18import "../Components"
19
19
20DashRenderer {
20DashRenderer {
21− id: genericFilterGrid
21+ id: root
22
22
23− expandable: filterGrid.expandable
23+ readonly property int collapsedRows: {
24− collapsedHeight: filterGrid.collapsedHeight
24+ if (!cardTool || !cardTool.template || typeof cardTool.template["collapsed-rows"] != "number") return 2;
25− uncollapsedHeight: filterGrid.uncollapsedHeight
25+ return cardTool.template["collapsed-rows"];
26− originY: filterGrid.originY
27− height: filterGrid.height
28− filtered: filterGrid.filtered
29−
30− function setFilter(filter, animate) {
31− filterGrid.setFilter(filter, animate)
32 }
26 }
33
27
34− FilterGrid {
28+ expandedHeight: grid.totalContentHeight
35− id: filterGrid
29+ collapsedHeight: Math.min(grid.contentHeightForRows(collapsedRows), expandedHeight)
36− width: genericFilterGrid.width
30+ collapsedItemCount: collapsedRows * grid.columns
31+ originY: grid.originY
32+
33+ ResponsiveGridView {
34+ id: grid
35+ anchors.fill: parent
37 minimumHorizontalSpacing: units.gu(1)
36 minimumHorizontalSpacing: units.gu(1)
38 delegateWidth: cardTool.cardWidth
37 delegateWidth: cardTool.cardWidth
39 delegateHeight: cardTool.cardHeight
38 delegateHeight: cardTool.cardHeight
40 verticalSpacing: units.gu(1)
39 verticalSpacing: units.gu(1)
41− model: genericFilterGrid.model
40+ model: root.model
42− collapsedRowCount: Math.min(2, cardTool && cardTool.template && cardTool.template["collapsed-rows"] || 2)
41+ displayMarginBeginning: root.displayMarginBeginning
43− displayMarginBeginning: genericFilterGrid.displayMarginBeginning
42+ displayMarginEnd: root.displayMarginEnd
44− displayMarginEnd: genericFilterGrid.displayMarginEnd
43+ cacheBuffer: 0
44+ interactive: false
45 delegate: Item {
45 delegate: Item {
46− width: filterGrid.cellWidth
46+ width: grid.cellWidth
47− height: filterGrid.cellHeight
47+ height: grid.cellHeight
48 Loader {
48 Loader {
49 id: loader
49 id: loader
50 sourceComponent: cardTool.cardComponent
50 sourceComponent: cardTool.cardComponent
@@ -58,12 +58,12 @@ DashRenderer {
58 item.template = Qt.binding(function() { return cardTool.template; });
58 item.template = Qt.binding(function() { return cardTool.template; });
59 item.components = Qt.binding(function() { return cardTool.components; });
59 item.components = Qt.binding(function() { return cardTool.components; });
60 item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
60 item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
61− item.scopeStyle = genericFilterGrid.scopeStyle;
61+ item.scopeStyle = root.scopeStyle;
62 }
62 }
63 Connections {
63 Connections {
64 target: loader.item
64 target: loader.item
65− onClicked: genericFilterGrid.clicked(index, result)
65+ onClicked: root.clicked(index, result)
66− onPressAndHold: genericFilterGrid.pressAndHold(index)
66+ onPressAndHold: root.pressAndHold(index)
67 }
67 }
68 }
68 }
69 }
69 }
qml/Dash/CardVerticalJournal.qml+3−21
@@ -23,33 +23,15 @@ DashRenderer {
23
23
24 readonly property double collapseLimit: units.gu(35)
24 readonly property double collapseLimit: units.gu(35)
25
25
26− uncollapsedHeight: cardVerticalJournal.implicitHeight
26+ expandedHeight: Math.max(cardVerticalJournal.implicitHeight, minHeight)
27− collapsedHeight: Math.min(collapseLimit, cardVerticalJournal.implicitHeight)
27+ collapsedHeight: Math.max(Math.min(collapseLimit, cardVerticalJournal.implicitHeight), minHeight)
28− expandable: uncollapsedHeight > collapseLimit
28+ // TODO: implement collapsedItemCount
29
29
30 // This minHeight is used as bootstrapper for the height. Vertical Journal
30 // This minHeight is used as bootstrapper for the height. Vertical Journal
31 // is special by the fact that it doesn't know how to calculate its implicit height unless we give it
31 // is special by the fact that it doesn't know how to calculate its implicit height unless we give it
32 // enough height that it can start creating its children so we make sure it has enough height for that
32 // enough height that it can start creating its children so we make sure it has enough height for that
33 // in case the model is non empty
33 // in case the model is non empty
34 readonly property double minHeight: root.model.count >= 1 ? cardVerticalJournal.rowSpacing + 1 : 0
34 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− }
53
35
54 ResponsiveVerticalJournal {
36 ResponsiveVerticalJournal {
55 id: cardVerticalJournal
37 id: cardVerticalJournal
qml/Dash/DashRenderer.qml+3−10
@@ -17,15 +17,11 @@
17import QtQuick 2.0
17import QtQuick 2.0
18
18
19Item {
19Item {
20− // Can the item be expanded?
20+ property int collapsedHeight
21− property bool expandable: false
22
21
23− // In case it can be expanded, is it filtered
22+ property int expandedHeight
24− property bool filtered: true
25
23
26− property int collapsedHeight: height
24+ property int collapsedItemCount: -1
27−
28− property int uncollapsedHeight: height
29
25
30 property int displayMarginBeginning: 0
26 property int displayMarginBeginning: 0
31
27
@@ -50,7 +46,4 @@ Item {
50 /// Emitted when the user pressed and held on an item
46 /// Emitted when the user pressed and held on an item
51 /// @param index is the index of the held item
47 /// @param index is the index of the held item
52 signal pressAndHold(int index)
48 signal pressAndHold(int index)
53−
54− function setFilter(filter, animate) {
55− }
56}
49}
qml/Dash/GenericScopeView.qml+132−64
@@ -119,6 +119,7 @@ FocusScope {
119
119
120 model: scopeView.categories
120 model: scopeView.categories
121 forceNoClip: previewListView.open
121 forceNoClip: previewListView.open
122+ pixelAligned: true
122
123
123 property string expandedCategoryId: ""
124 property string expandedCategoryId: ""
124
125
@@ -128,11 +129,22 @@ FocusScope {
128 highlightWhenPressed: false
129 highlightWhenPressed: false
129 showDivider: false
130 showDivider: false
130
131
131− readonly property bool expandable: rendererLoader.item ? rendererLoader.item.expandable : false
132+ readonly property bool expandable: {
132− readonly property bool filtered: rendererLoader.item ? rendererLoader.item.filtered : true
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
133 readonly property string category: categoryId
139 readonly property string category: categoryId
140+ readonly property string headerLink: model.headerLink
134 readonly property var item: rendererLoader.item
141 readonly property var item: rendererLoader.item
135
142
143+ function expand(expand, animate) {
144+ heightBehaviour.enabled = animate;
145+ expanded = expand;
146+ }
147+
136 CardTool {
148 CardTool {
137 id: cardTool
149 id: cardTool
138 objectName: "cardTool"
150 objectName: "cardTool"
@@ -142,22 +154,49 @@ FocusScope {
142 viewWidth: parent.width
154 viewWidth: parent.width
143 }
155 }
144
156
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+
145 Loader {
169 Loader {
146 id: rendererLoader
170 id: rendererLoader
147 anchors {
171 anchors {
148 top: parent.top
172 top: parent.top
149 left: parent.left
173 left: parent.left
150 right: parent.right
174 right: parent.right
151− topMargin: hasSectionHeader ? 0 : units.gu(2)
175+ topMargin: name != "" ? 0 : units.gu(2)
152 }
176 }
153
177
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+
154 source: {
193 source: {
155 switch (cardTool.categoryLayout) {
194 switch (cardTool.categoryLayout) {
156 case "carousel": return "CardCarousel.qml";
195 case "carousel": return "CardCarousel.qml";
157 case "vertical-journal": return "CardVerticalJournal.qml";
196 case "vertical-journal": return "CardVerticalJournal.qml";
158 case "running-apps": return "Apps/RunningApplicationsGrid.qml";
197 case "running-apps": return "Apps/RunningApplicationsGrid.qml";
159 case "grid":
198 case "grid":
160− default: return "CardFilterGrid.qml";
199+ default: return "CardGrid.qml";
161 }
200 }
162 }
201 }
163
202
@@ -176,9 +215,9 @@ FocusScope {
176 }
215 }
177 item.objectName = Qt.binding(function() { return categoryId })
216 item.objectName = Qt.binding(function() { return categoryId })
178 item.scopeStyle = scopeView.scopeStyle;
217 item.scopeStyle = scopeView.scopeStyle;
179− if (item.expandable) {
218+ if (baseItem.expandable) {
180− var shouldFilter = categoryId != categoryView.expandedCategoryId;
219+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
181− item.setFilter(shouldFilter, false /*animate*/);
220+ baseItem.expand(shouldExpand, false /*animate*/);
182 }
221 }
183 updateDelegateCreationRange();
222 updateDelegateCreationRange();
184 item.cardTool = cardTool;
223 item.cardTool = cardTool;
@@ -199,25 +238,22 @@ FocusScope {
199 // so it's not implemented
238 // so it's not implemented
200 scopeView.scope.activate(result)
239 scopeView.scope.activate(result)
201 } else {
240 } else {
202− previewListView.model = target.model;
241+ openPreview(index);
203− previewListView.currentIndex = -1
204− previewListView.currentIndex = index;
205− previewListView.open = true
206 }
242 }
207 }
243 }
208− onPressAndHold: {
244+ onPressAndHold: openPreview(index)
209− previewListView.model = target.model;
245+
210− previewListView.currentIndex = -1
246+ function openPreview(index) {
211− previewListView.currentIndex = index;
247+ if (!rendererLoader.expanded && !seeAllLabel.visible && target.collapsedItemCount > 0) {
212− previewListView.open = true
248+ previewLimitModel.model = target.model;
213− }
249+ previewLimitModel.limit = target.collapsedItemCount;
214− onExpandableChanged: {
250+ previewListView.model = previewLimitModel;
215− // This can happen with the VJ that doesn't know how height it will be on creation
251+ } else {
216− // so doesn't set expandable until a bit too late for onLoaded
252+ previewListView.model = target.model;
217− if (rendererLoader.item.expandable) {
218− var shouldFilter = baseItem.category != categoryView.expandedCategoryId;
219− rendererLoader.item.setFilter(shouldFilter, false /*animate*/);
220 }
253 }
254+ previewListView.currentIndex = -1;
255+ previewListView.currentIndex = index;
256+ previewListView.open = true;
221 }
257 }
222 }
258 }
223 Connections {
259 Connections {
@@ -227,17 +263,17 @@ FocusScope {
227 }
263 }
228 function collapseAllButExpandedCategory() {
264 function collapseAllButExpandedCategory() {
229 var item = rendererLoader.item;
265 var item = rendererLoader.item;
230− if (item.expandable) {
266+ if (baseItem.expandable) {
231− var shouldFilter = categoryId != categoryView.expandedCategoryId;
267+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
232− if (shouldFilter != item.filter) {
268+ if (shouldExpand != baseItem.expanded) {
233 // If the filter animation will be seen start it, otherwise, just flip the switch
269 // If the filter animation will be seen start it, otherwise, just flip the switch
234− var shrinkingVisible = shouldFilter && y + item.collapsedHeight < categoryView.height;
270+ var shrinkingVisible = !shouldExpand && y + item.collapsedHeight + seeAll.height < categoryView.height;
235− var growingVisible = !shouldFilter && y + height < categoryView.height;
271+ var growingVisible = shouldExpand && y + height < categoryView.height;
236− if (!previewListView.open || !shouldFilter) {
272+ if (!previewListView.open || shouldExpand) {
237 var animate = shrinkingVisible || growingVisible;
273 var animate = shrinkingVisible || growingVisible;
238− item.setFilter(shouldFilter, animate)
274+ baseItem.expand(shouldExpand, animate)
239− if (!shouldFilter && !previewListView.open) {
275+ if (shouldExpand && !previewListView.open) {
240− categoryView.maximizeVisibleArea(index, item.uncollapsedHeight);
276+ categoryView.maximizeVisibleArea(index, item.expandedHeight + seeAll.height);
241 }
277 }
242 }
278 }
243 }
279 }
@@ -274,58 +310,82 @@ FocusScope {
274 item.displayMarginEnd = -baseItem.height;
310 item.displayMarginEnd = -baseItem.height;
275 } else {
311 } else {
276 item.displayMarginBeginning = -Math.max(-baseItem.y, 0);
312 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)
278 }
315 }
279 }
316 }
280 }
317 }
318+ }
281
319
282− Image {
320+ AbstractButton {
283− visible: index != 0
321+ id: seeAll
284− anchors {
322+ objectName: "seeAll"
285− top: parent.top
323+ anchors {
286− left: parent.left
324+ top: rendererLoader.bottom
287− right: parent.right
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 = "";
288 }
335 }
289− fillMode: Image.Stretch
290− source: "graphics/dash_divider_top_lightgrad.png"
291− z: -1
292 }
336 }
293
337
294− Image {
338+ Label {
295− // FIXME Should not rely on model.count but view.count, but ListViewWithPageHeader doesn't expose it yet.
339+ id: seeAllLabel
296− visible: index != categoryView.model.count - 1
340+ text: baseItem.expanded ? i18n.tr("See less") : i18n.tr("See all")
297 anchors {
341 anchors {
298− bottom: parent.bottom
342+ centerIn: parent
299− left: parent.left
343+ verticalCenterOffset: units.gu(-0.5)
300− right: parent.right
301 }
344 }
302− fillMode: Image.Stretch
345+ fontSize: "small"
303− source: "graphics/dash_divider_top_darkgrad.png"
346+ font.weight: Font.Bold
304− z: -1
347+ color: scopeStyle ? scopeStyle.foreground : "grey"
348+ visible: baseItem.expandable && !baseItem.headerLink
305 }
349 }
306 }
350 }
307
351
308− onHeightChanged: rendererLoader.updateDelegateCreationRange();
352+ Image {
309− onYChanged: rendererLoader.updateDelegateCreationRange();
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+ }
310 }
376 }
311
377
312 sectionProperty: "name"
378 sectionProperty: "name"
313 sectionDelegate: ListItems.Header {
379 sectionDelegate: ListItems.Header {
314 objectName: "dashSectionHeader" + (delegate ? delegate.category : "")
380 objectName: "dashSectionHeader" + (delegate ? delegate.category : "")
315− property var delegate: categoryView.item(delegateIndex)
381+ readonly property var delegate: categoryView.item(delegateIndex)
316 width: categoryView.width
382 width: categoryView.width
383+ height: section != "" ? units.gu(5) : 0
317 text: section
384 text: section
318− textColor: scopeStyle ? scopeStyle.foreground : "grey"
385+ color: scopeStyle ? scopeStyle.foreground : "grey"
319− image: {
320− if (delegate && delegate.expandable)
386+ iconName: delegate && delegate.headerLink ? "go-next" : ""
321− return delegate.filtered ? "graphics/header_handlearrow.png" : "graphics/header_handlearrow2.png"
322− return "";
323− }
324 onClicked: {
387 onClicked: {
325− if (categoryView.expandedCategoryId != delegate.category)
388+ if (delegate.headerLink) scopeView.scope.performQuery(delegate.headerLink);
326− categoryView.expandedCategoryId = delegate.category;
327− else
328− categoryView.expandedCategoryId = "";
329 }
389 }
330 }
390 }
331
391
@@ -352,6 +412,10 @@ FocusScope {
352 }
412 }
353 }
413 }
354
414
415+ LimitProxyModel {
416+ id: previewLimitModel
417+ }
418+
355 PreviewListView {
419 PreviewListView {
356 id: previewListView
420 id: previewListView
357 objectName: "previewListView"
421 objectName: "previewListView"
@@ -361,6 +425,10 @@ FocusScope {
361 width: parent.width
425 width: parent.width
362 height: parent.height
426 height: parent.height
363 anchors.left: categoryView.right
427 anchors.left: categoryView.right
428+
429+ onOpenChanged: {
430+ pageHeader.unfocus();
431+ }
364 }
432 }
365
433
366}
434}
qml/Dash/PreviewListView.qml+1−3
@@ -73,9 +73,7 @@ Item {
73 property bool open: false
73 property bool open: false
74
74
75 onOpenChanged: {
75 onOpenChanged: {
76− if (open) {
76+ if (!open) {
77− pageHeader.unfocus();
78− } else {
79 // Cancel any pending preview requests or actions
77 // Cancel any pending preview requests or actions
80 if (previewListView.currentItem && previewListView.currentItem.previewData !== undefined) {
78 if (previewListView.currentItem && previewListView.currentItem.previewData !== undefined) {
81 previewListView.currentItem.previewData.cancelAction();
79 previewListView.currentItem.previewData.cancelAction();
qml/Greeter/Greeter.qml+1−1
@@ -70,7 +70,7 @@ Showable {
70 DraggingArea {
70 DraggingArea {
71 id: dragHandle
71 id: dragHandle
72 anchors.fill: parent
72 anchors.fill: parent
73− enabled: greeter.narrowMode || !greeter.locked
73+ enabled: (greeter.narrowMode || !greeter.locked) && greeter.enabled
74 orientation: Qt.Horizontal
74 orientation: Qt.Horizontal
75 propagateComposedEvents: true
75 propagateComposedEvents: true
76
76
qml/Shell.qml+84−27
@@ -137,7 +137,7 @@ FocusScope {
137 id: dash
137 id: dash
138 objectName: "dash"
138 objectName: "dash"
139
139
140− available: !greeter.shown && !lockscreen.shown
140+ available: !LightDM.Greeter.active
141 hides: [stages, launcher, panel.indicators]
141 hides: [stages, launcher, panel.indicators]
142 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0
142 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0
143 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
143 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
@@ -200,7 +200,7 @@ FocusScope {
200
200
201 x: {
201 x: {
202 if (shown) {
202 if (shown) {
203− if (overlayMode || locked) {
203+ if (overlayMode || locked || greeter.fakeActiveForApp !== "") {
204 return 0;
204 return 0;
205 }
205 }
206 return launcher.progress
206 return launcher.progress
@@ -245,10 +245,17 @@ FocusScope {
245 target: ApplicationManager
245 target: ApplicationManager
246
246
247 onFocusRequested: {
247 onFocusRequested: {
248+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== appId) {
249+ lockscreen.show();
250+ }
251+ greeter.hide();
248 stages.show(true);
252 stages.show(true);
249 }
253 }
250
254
251 onFocusedApplicationIdChanged: {
255 onFocusedApplicationIdChanged: {
256+ if (greeter.fakeActiveForApp !== "" && greeter.fakeActiveForApp !== ApplicationManager.focusedApplicationId) {
257+ lockscreen.show();
258+ }
252 if (ApplicationManager.focusedApplicationId.length > 0) {
259 if (ApplicationManager.focusedApplicationId.length > 0) {
253 stages.show(false);
260 stages.show(false);
254 } else {
261 } else {
@@ -439,6 +446,11 @@ FocusScope {
439
446
440 source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
447 source: shell.sideStageEnabled ? "Stages/StageWithSideStage.qml" : "Stages/PhoneStage.qml"
441
448
449+ Binding {
450+ target: applicationsDisplayLoader.item
451+ property: "objectName"
452+ value: "stage"
453+ }
442 Binding {
454 Binding {
443 target: applicationsDisplayLoader.item
455 target: applicationsDisplayLoader.item
444 property: "moving"
456 property: "moving"
@@ -454,6 +466,11 @@ FocusScope {
454 property: "dragAreaWidth"
466 property: "dragAreaWidth"
455 value: shell.edgeSize
467 value: shell.edgeSize
456 }
468 }
469+ Binding {
470+ target: applicationsDisplayLoader.item
471+ property: "spreadEnabled"
472+ value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
473+ }
457 }
474 }
458 }
475 }
459
476
@@ -478,6 +495,13 @@ FocusScope {
478
495
479 onEntered: LightDM.Greeter.respond(passphrase);
496 onEntered: LightDM.Greeter.respond(passphrase);
480 onCancel: greeter.show()
497 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 = ""
481
505
482 Component.onCompleted: {
506 Component.onCompleted: {
483 if (LightDM.Users.count == 1) {
507 if (LightDM.Users.count == 1) {
@@ -510,6 +534,7 @@ FocusScope {
510 }
534 }
511 if (LightDM.Greeter.authenticated) {
535 if (LightDM.Greeter.authenticated) {
512 lockscreen.hide();
536 lockscreen.hide();
537+ greeter.login();
513 } else {
538 } else {
514 lockscreen.clear(true);
539 lockscreen.clear(true);
515 }
540 }
@@ -519,7 +544,7 @@ FocusScope {
519 Binding {
544 Binding {
520 target: LightDM.Greeter
545 target: LightDM.Greeter
521 property: "active"
546 property: "active"
522− value: greeter.shown || lockscreen.shown
547+ value: greeter.shown || lockscreen.shown || greeter.fakeActiveForApp != ""
523 }
548 }
524
549
525 Rectangle {
550 Rectangle {
@@ -542,11 +567,16 @@ FocusScope {
542 }
567 }
543
568
544 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
569 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
570+ onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
545
571
546 Greeter {
572 Greeter {
547 id: greeter
573 id: greeter
548 objectName: "greeter"
574 objectName: "greeter"
549
575
576+ signal sessionStarted() // helpful for tests
577+
578+ property string fakeActiveForApp: ""
579+
550 available: true
580 available: true
551 hides: [launcher, panel.indicators]
581 hides: [launcher, panel.indicators]
552 shown: true
582 shown: true
@@ -558,6 +588,16 @@ FocusScope {
558
588
559 dragHandleWidth: shell.edgeSize
589 dragHandleWidth: shell.edgeSize
560
590
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+
561 onShownChanged: {
601 onShownChanged: {
562 if (shown) {
602 if (shown) {
563 lockscreen.reset();
603 lockscreen.reset();
@@ -569,6 +609,7 @@ FocusScope {
569 if (LightDM.Users.count == 1) {
609 if (LightDM.Users.count == 1) {
570 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
610 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
571 }
611 }
612+ greeter.fakeActiveForApp = "";
572 greeter.forceActiveFocus();
613 greeter.forceActiveFocus();
573 }
614 }
574 }
615 }
@@ -618,12 +659,40 @@ FocusScope {
618 }
659 }
619
660
620 function showHome() {
661 function showHome() {
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+
621− var animate = !greeter.shown && !stages.shown
673+ var animate = !LightDM.Greeter.active && !stages.shown
622− greeter.hide()
623 dash.setCurrentScope("clickscope", animate, false)
674 dash.setCurrentScope("clickscope", animate, false)
624 stages.hide()
675 stages.hide()
625 }
676 }
626
677
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+
627 Item {
696 Item {
628 id: overlay
697 id: overlay
629
698
@@ -631,17 +700,18 @@ FocusScope {
631
700
632 Panel {
701 Panel {
633 id: panel
702 id: panel
703+ objectName: "panel"
634 anchors.fill: parent //because this draws indicator menus
704 anchors.fill: parent //because this draws indicator menus
635 indicators {
705 indicators {
636 hides: [launcher]
706 hides: [launcher]
637− available: edgeDemo.panelEnabled
707+ available: edgeDemo.panelEnabled && greeter.fakeActiveForApp === ""
638 contentEnabled: edgeDemo.panelContentEnabled
708 contentEnabled: edgeDemo.panelContentEnabled
639 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
709 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
640 panelHeight: units.gu(3)
710 panelHeight: units.gu(3)
641 }
711 }
642 property string focusedAppId: ApplicationManager.focusedApplicationId
712 property string focusedAppId: ApplicationManager.focusedApplicationId
643 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
713 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 !== ""
645
715
646 InputFilterArea {
716 InputFilterArea {
647 anchors {
717 anchors {
@@ -666,6 +736,7 @@ FocusScope {
666
736
667 Launcher {
737 Launcher {
668 id: launcher
738 id: launcher
739+ objectName: "launcher"
669
740
670 readonly property bool dashSwipe: progress > 0
741 readonly property bool dashSwipe: progress > 0
671
742
@@ -673,29 +744,15 @@ FocusScope {
673 anchors.bottom: parent.bottom
744 anchors.bottom: parent.bottom
674 width: parent.width
745 width: parent.width
675 dragAreaWidth: shell.edgeSize
746 dragAreaWidth: shell.edgeSize
676− available: edgeDemo.launcherEnabled
747+ available: edgeDemo.launcherEnabled && greeter.fakeActiveForApp === ""
677
748
678− onShowDashHome: {
749+ onShowDashHome: showHome()
679− if (edgeDemo.running)
680− return;
681−
682− showHome()
683− }
684− onDash: {
750+ onDash: showDash()
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− }
697 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
751 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
698 onLauncherApplicationSelected: {
752 onLauncherApplicationSelected: {
753+ if (greeter.fakeActiveForApp !== "") {
754+ lockscreen.show()
755+ }
699 if (!edgeDemo.running)
756 if (!edgeDemo.running)
700 shell.activateApplication(appId)
757 shell.activateApplication(appId)
701 }
758 }
qml/Stages/PhoneStage.qml+13−1
@@ -18,6 +18,7 @@ import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import Ubuntu.Gestures 0.1
19import Ubuntu.Gestures 0.1
20import Unity.Application 0.1
20import Unity.Application 0.1
21+import LightDM 0.1 as LightDM
21import Utils 0.1
22import Utils 0.1
22import "../Components"
23import "../Components"
23
24
@@ -33,6 +34,7 @@ Item {
33 readonly property bool painting: mainScreenshotImage.visible || fadeInScreenshotImage.visible || appSplash.visible || spreadView.visible
34 readonly property bool painting: mainScreenshotImage.visible || fadeInScreenshotImage.visible || appSplash.visible || spreadView.visible
34 property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
35 property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
35 property bool locked: spreadView.visible
36 property bool locked: spreadView.visible
37+ property bool spreadEnabled: true
36
38
37 // Not used for PhoneStage, only useful for SideStage and similar
39 // Not used for PhoneStage, only useful for SideStage and similar
38 property bool overlayMode: false
40 property bool overlayMode: false
@@ -131,6 +133,11 @@ Item {
131 mainScreenshotImage.visible = true;
133 mainScreenshotImage.visible = true;
132 } else if (priv.secondApplicationStarting && priv.waitingForScreenshot) {
134 } else if (priv.secondApplicationStarting && priv.waitingForScreenshot) {
133 applicationSwitchingAnimation.start();
135 applicationSwitchingAnimation.start();
136+ if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
137+ // When greeter is up, no fancy animations, since user may
138+ // glimpse an app they shouldn't
139+ applicationSwitchingAnimation.complete();
140+ }
134 }
141 }
135 waitingForScreenshot = false;
142 waitingForScreenshot = false;
136 }
143 }
@@ -145,6 +152,11 @@ Item {
145 priv.newFocusedAppId = appId;
152 priv.newFocusedAppId = appId;
146 root.fullscreen = ApplicationManager.findApplication(appId).fullscreen;
153 root.fullscreen = ApplicationManager.findApplication(appId).fullscreen;
147 applicationSwitchingAnimation.start();
154 applicationSwitchingAnimation.start();
155+ if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
156+ // When greeter is up, no fancy animations, since user may
157+ // glimpse an app they shouldn't
158+ applicationSwitchingAnimation.complete();
159+ }
148 } else {
160 } else {
149 ApplicationManager.focusApplication(appId);
161 ApplicationManager.focusApplication(appId);
150 }
162 }
@@ -244,7 +256,7 @@ Item {
244 EdgeDragArea {
256 EdgeDragArea {
245 id: spreadDragArea
257 id: spreadDragArea
246 direction: Direction.Leftwards
258 direction: Direction.Leftwards
247− enabled: ApplicationManager.count > 1 && spreadView.phase != 2
259+ enabled: ApplicationManager.count > 1 && spreadView.phase != 2 && root.spreadEnabled
248
260
249 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
261 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
250 width: root.dragAreaWidth
262 width: root.dragAreaWidth
src/main.cpp+1−1
@@ -221,7 +221,7 @@ int main(int argc, const char *argv[])
221
221
222 return runWithClient(mirServer, startShell);
222 return runWithClient(mirServer, startShell);
223 } else {
223 } else {
224− if (qgetenv("UPSTART_JOB") == "unity8") {
224+ if (!qgetenv("UNITY_MIR_EMITS_SIGSTOP").isEmpty()) {
225 // Emit SIGSTOP as expected by upstart, under Mir it's unity-mir that will raise it.
225 // Emit SIGSTOP as expected by upstart, under Mir it's unity-mir that will raise it.
226 // see http://upstart.ubuntu.com/cookbook/#expect-stop
226 // see http://upstart.ubuntu.com/cookbook/#expect-stop
227 raise(SIGSTOP);
227 raise(SIGSTOP);
tests/autopilot/unity8/shell/emulators/dash.py+12−6
@@ -18,6 +18,7 @@
18#
18#
19
19
20import logging
20import logging
21+import ubuntuuitoolkit
21
22
22from unity8.shell import emulators
23from unity8.shell import emulators
23
24
@@ -40,7 +41,7 @@ class Dash(emulators.UnityEmulatorBase):
40
41
41 def get_applications_grid(self):
42 def get_applications_grid(self):
42 get_grid = self.get_scope('clickscope').wait_select_single(
43 get_grid = self.get_scope('clickscope').wait_select_single(
43− 'CardFilterGrid', objectName='local')
44+ 'CardGrid', objectName='local')
44 return get_grid
45 return get_grid
45
46
46 def get_application_icon(self, text):
47 def get_application_icon(self, text):
@@ -128,9 +129,9 @@ class Dash(emulators.UnityEmulatorBase):
128 def enter_search_query(self, query):
129 def enter_search_query(self, query):
129 current_header = self._get_current_page_header()
130 current_header = self._get_current_page_header()
130 self.pointing_device.move(current_header.globalRect.x +
131 self.pointing_device.move(current_header.globalRect.x +
131− current_header.width - current_header.height / 2,
132+ current_header.width - current_header.height / 4,
132 current_header.globalRect.y +
133 current_header.globalRect.y +
133− current_header.height / 2)
134+ current_header.height / 4)
134 self.pointing_device.click()
135 self.pointing_device.click()
135 headerContainer = current_header.select_single(objectName="headerContainer")
136 headerContainer = current_header.select_single(objectName="headerContainer")
136 headerContainer.contentY.wait_for(0)
137 headerContainer.contentY.wait_for(0)
@@ -151,6 +152,10 @@ class Dash(emulators.UnityEmulatorBase):
151 return None
152 return None
152
153
153
154
155+class ListViewWithPageHeader(ubuntuuitoolkit.QQuickFlickable):
156+ pass
157+
158+
154class GenericScopeView(emulators.UnityEmulatorBase):
159class GenericScopeView(emulators.UnityEmulatorBase):
155 """Autopilot emulator for generic scopes."""
160 """Autopilot emulator for generic scopes."""
156
161
@@ -194,16 +199,17 @@ class DashApps(GenericScopeView):
194
199
195 """
200 """
196 category_element = self._get_category_element(category)
201 category_element = self._get_category_element(category)
202+ see_all = category_element.select_single(objectName='seeAll')
197 application_cards = category_element.select_many('AbstractButton')
203 application_cards = category_element.select_many('AbstractButton')
198
204
199− # sort by y, x
200 application_cards = sorted(
205 application_cards = sorted(
201− application_cards,
206+ (card for card in application_cards
207+ if card.globalRect.y < see_all.globalRect.y),
202 key=lambda card: (card.globalRect.y, card.globalRect.x))
208 key=lambda card: (card.globalRect.y, card.globalRect.x))
203
209
204 result = []
210 result = []
205 for card in application_cards:
211 for card in application_cards:
206− if card.objectName != 'cardToolCard':
212+ if card.objectName not in ('cardToolCard', 'seeAll'):
207 result.append(card.title)
213 result.append(card.title)
208 return result
214 return result
209
215
tests/autopilot/unity8/shell/tests/test_emulators.py+15−5
@@ -16,6 +16,7 @@
16# You should have received a copy of the GNU General Public License
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18#
18#
19+from unity8.shell.emulators.dash import ListViewWithPageHeader
19
20
20"""Tests for the Dash autopilot emulators.
21"""Tests for the Dash autopilot emulators.
21
22
@@ -182,18 +183,27 @@ class DashAppsEmulatorTestCase(DashBaseTestCase):
182
183
183 def test_get_applications_should_return_correct_applications(self):
184 def test_get_applications_should_return_correct_applications(self):
184 category = '2'
185 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)
185 expected_apps_count = self._get_number_of_application_slots(category)
190 expected_apps_count = self._get_number_of_application_slots(category)
186 expected_applications = self.available_applications[
191 expected_applications = self.available_applications[
187 :expected_apps_count]
192 :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)
188 applications = self.applications_scope.get_applications(category)
198 applications = self.applications_scope.get_applications(category)
189 self.assertEqual(expected_applications, applications)
199 self.assertEqual(expected_applications, applications)
190
200
191 def _get_number_of_application_slots(self, category):
201 def _get_number_of_application_slots(self, category):
192 category_element = self.applications_scope._get_category_element(
202 category_element = self.applications_scope._get_category_element(
193 category)
203 category)
194− grid = category_element.select_single('CardFilterGrid')
204+ cardgrid = category_element.select_single('CardGrid')
195− filtergrid = grid.select_single('FilterGrid')
205+ if (category_element.expanded):
196− if (grid.filtered):
206+ return cardgrid.select_single('QQuickGridView').count
197− return filtergrid.collapsedRowCount * filtergrid.columns
198 else:
207 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 @@
20"""Tests for upstart integration."""
20"""Tests for upstart integration."""
21
21
22import os
22import os
23+import stat
23import signal
24import signal
24import subprocess
25import subprocess
25import time
26import time
@@ -57,6 +58,18 @@ class UpstartIntegrationTests(UnityTestCase):
57
58
58 def _launch_unity(self):
59 def _launch_unity(self):
59 self.patch_environment("QT_LOAD_TESTABILITY", "1")
60 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+
60 self.process = subprocess.Popen(
73 self.process = subprocess.Popen(
61 [get_binary_path()] + self.unity_geometry_args)
74 [get_binary_path()] + self.unity_geometry_args)
62
75
tests/mocks/LightDM/single-pin/GreeterPrivate.cpp+1−9
@@ -19,8 +19,6 @@
19#include "../Greeter.h"
19#include "../Greeter.h"
20#include "../GreeterPrivate.h"
20#include "../GreeterPrivate.h"
21
21
22−#include <QDebug>
23−
24namespace QLightDM
22namespace QLightDM
25{
23{
26
24
@@ -34,19 +32,13 @@ GreeterPrivate::GreeterPrivate(Greeter* parent)
34void GreeterPrivate::handleAuthenticate()
32void GreeterPrivate::handleAuthenticate()
35{
33{
36 Q_Q(Greeter);
34 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);
41}
36}
42
37
43void GreeterPrivate::handleRespond(const QString &response)
38void GreeterPrivate::handleRespond(const QString &response)
44{
39{
45 Q_Q(Greeter);
40 Q_Q(Greeter);
46−
47−
48 authenticated = (response == "1234");
41 authenticated = (response == "1234");
49− qDebug() << "responding" << response << authenticated;
50 Q_EMIT q->authenticationComplete();
42 Q_EMIT q->authenticationComplete();
51}
43}
52
44
tests/mocks/QMenuModel/unitymenumodel.cpp+5
@@ -126,6 +126,11 @@ void UnityMenuModel::setActionStateParser(ActionStateParser*)
126{
126{
127}
127}
128
128
129+QString UnityMenuModel::nameOwner() const
130+{
131+ return QString("");
132+}
133+
129int UnityMenuModel::rowCount(const QModelIndex&) const
134int UnityMenuModel::rowCount(const QModelIndex&) const
130{
135{
131 return m_modelData.count();
136 return m_modelData.count();
tests/mocks/QMenuModel/unitymenumodel.h+4
@@ -32,6 +32,7 @@ class Q_DECL_EXPORT UnityMenuModel : public QAbstractListModel
32 Q_PROPERTY(QVariantMap actions READ actions WRITE setActions NOTIFY actionsChanged)
32 Q_PROPERTY(QVariantMap actions READ actions WRITE setActions NOTIFY actionsChanged)
33 Q_PROPERTY(QByteArray menuObjectPath READ menuObjectPath WRITE setMenuObjectPath NOTIFY menuObjectPathChanged)
33 Q_PROPERTY(QByteArray menuObjectPath READ menuObjectPath WRITE setMenuObjectPath NOTIFY menuObjectPathChanged)
34 Q_PROPERTY(ActionStateParser* actionStateParser READ actionStateParser WRITE setActionStateParser NOTIFY actionStateParserChanged)
34 Q_PROPERTY(ActionStateParser* actionStateParser READ actionStateParser WRITE setActionStateParser NOTIFY actionStateParserChanged)
35+ Q_PROPERTY(QString nameOwner READ nameOwner NOTIFY nameOwnerChanged)
35
36
36public:
37public:
37 UnityMenuModel(QObject *parent = NULL);
38 UnityMenuModel(QObject *parent = NULL);
@@ -56,6 +57,8 @@ public:
56 ActionStateParser* actionStateParser() const;
57 ActionStateParser* actionStateParser() const;
57 void setActionStateParser(ActionStateParser* actionStateParser);
58 void setActionStateParser(ActionStateParser* actionStateParser);
58
59
60+ QString nameOwner() const;
61+
59 int rowCount(const QModelIndex &parent = QModelIndex()) const;
62 int rowCount(const QModelIndex &parent = QModelIndex()) const;
60 int columnCount(const QModelIndex &parent = QModelIndex()) const;
63 int columnCount(const QModelIndex &parent = QModelIndex()) const;
61 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
64 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
@@ -79,6 +82,7 @@ Q_SIGNALS:
79 void menuObjectPathChanged();
82 void menuObjectPathChanged();
80 void actionStateParserChanged();
83 void actionStateParserChanged();
81 void modelDataChanged();
84 void modelDataChanged();
85+ void nameOwnerChanged();
82
86
83private:
87private:
84 QVariantMap rowData(int row) const;
88 QVariantMap rowData(int row) const;
tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−9
@@ -11,12 +11,4 @@ add_library(FakeUbuntuTelephonyQml MODULE ${FakeUbuntuTelephonyQml_SOURCES})
11
11
12qt5_use_modules(FakeUbuntuTelephonyQml Core Quick)
12qt5_use_modules(FakeUbuntuTelephonyQml Core Quick)
13
13
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
14+add_unity8_mock(Ubuntu.Telephony 0.1 Ubuntu/Telephony TARGETS FakeUbuntuTelephonyQml)
21− DESTINATION ${SHELL_INSTALL_QML}/mocks/Ubuntu/Telephony
22− )
tests/mocks/Unity/fake_categories.cpp+13−1
@@ -145,9 +145,12 @@ Categories::data(const QModelIndex& index, int role) const
145 } else {
145 } else {
146 map["category-layout"] = "carousel";
146 map["category-layout"] = "carousel";
147 map["card-size"] = "medium";
147 map["card-size"] = "medium";
148− map["collapsed-rows"] = 2;
149 map["overlay"] = true;
148 map["overlay"] = true;
150 }
149 }
150+ if (index.row() == 19) {
151+ map["category-layout"] = "grid";
152+ map["collapsed-rows"] = 0;
153+ }
151 map["card-size"] = "small";
154 map["card-size"] = "small";
152 return map;
155 return map;
153 }
156 }
@@ -166,6 +169,9 @@ Categories::data(const QModelIndex& index, int role) const
166 return map;
169 return map;
167 }
170 }
168 case RoleHeaderLink:
171 case RoleHeaderLink:
172+ if (index.row() == 1 || index.row() == 4) {
173+ return QString("scope://query/1");
174+ }
169 return QString();
175 return QString();
170 case RoleResults:
176 case RoleResults:
171 return QVariant::fromValue(resultsModel);
177 return QVariant::fromValue(resultsModel);
@@ -177,3 +183,9 @@ Categories::data(const QModelIndex& index, int role) const
177 }
183 }
178 }
184 }
179}
185}
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:
37 Q_INVOKABLE void addSpecialCategory(QString const& categoryId, QString const& name, QString const& icon, QString const& rawTemplate, QObject* countObject) override;
37 Q_INVOKABLE void addSpecialCategory(QString const& categoryId, QString const& name, QString const& icon, QString const& rawTemplate, QObject* countObject) override;
38 Q_INVOKABLE bool overrideCategoryJson(QString const& categoryId, QString const& json) override;
38 Q_INVOKABLE bool overrideCategoryJson(QString const& categoryId, QString const& json) override;
39
39
40+ Q_INVOKABLE QVariant data(int row, int role) const;
41+
40private Q_SLOTS:
42private Q_SLOTS:
41 void countChanged();
43 void countChanged();
42
44
tests/mocks/Unity/fake_scope.cpp+8−11
@@ -24,7 +24,7 @@ Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)
24{
24{
25}
25}
26
26
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)
28 : unity::shell::scopes::ScopeInterface(parent)
28 : unity::shell::scopes::ScopeInterface(parent)
29 , m_id(id)
29 , m_id(id)
30 , m_name(name)
30 , m_name(name)
@@ -33,7 +33,7 @@ Scope::Scope(QString const& id, QString const& name, bool visible, QObject* pare
33 , m_isActive(false)
33 , m_isActive(false)
34 , m_currentDeparment("root")
34 , m_currentDeparment("root")
35 , m_previewRendererName("preview-generic")
35 , m_previewRendererName("preview-generic")
36− , m_categories(new Categories(20, this))
36+ , m_categories(new Categories(categories, this))
37{
37{
38}
38}
39
39
@@ -182,14 +182,16 @@ bool Scope::hasDepartments() const
182
182
183QVariantMap Scope::customizations() const
183QVariantMap Scope::customizations() const
184{
184{
185− QVariantMap m;
185+ QVariantMap m, h;
186 if (m_id == "clickscope") {
186 if (m_id == "clickscope") {
187+ h["foreground-color"] = "yellow";
187 m["background-color"] = "red";
188 m["background-color"] = "red";
188 m["foreground-color"] = "blue";
189 m["foreground-color"] = "blue";
190+ m["page-header"] = h;
189 } else if (m_id == "MockScope5") {
191 } else if (m_id == "MockScope5") {
190− QVariantMap pageHeader;
192+ h["background"] = "gradient:///lightgrey/grey";
191− pageHeader["logo"] = QUrl("../../../tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg");
193+ h["logo"] = QUrl("../../../tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg");
192− m["page-header"] = pageHeader;
194+ m["page-header"] = h;
193 }
195 }
194 return m;
196 return m;
195}
197}
@@ -216,8 +218,3 @@ void Scope::loadDepartment(const QString& id)
216 m_currentDeparment = id;
218 m_currentDeparment = id;
217 Q_EMIT currentDepartmentIdChanged();
219 Q_EMIT currentDepartmentIdChanged();
218}
220}
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
30
30
31public:
31public:
32 Scope(QObject* parent = 0);
32 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);
34
34
35 /* getters */
35 /* getters */
36 QString id() const override;
36 QString id() const override;
@@ -64,7 +64,7 @@ public:
64 bool hasDepartments() const override;
64 bool hasDepartments() const override;
65 Q_INVOKABLE unity::shell::scopes::DepartmentInterface* getDepartment(const QString& id) override;
65 Q_INVOKABLE unity::shell::scopes::DepartmentInterface* getDepartment(const QString& id) override;
66 Q_INVOKABLE void loadDepartment(const QString& id) override;
66 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;
68
68
69 QVariantMap customizations() const override;
69 QVariantMap customizations() const override;
70
70
tests/mocks/Unity/fake_scopes.cpp+1
@@ -46,6 +46,7 @@ void Scopes::updateScopes()
46 addScope(new Scope("MockScope2", "Music", false, this));
46 addScope(new Scope("MockScope2", "Music", false, this));
47 addScope(new Scope("clickscope", "Apps", true, this));
47 addScope(new Scope("clickscope", "Apps", true, this));
48 addScope(new Scope("MockScope5", "Videos", true, this));
48 addScope(new Scope("MockScope5", "Videos", true, this));
49+ addScope(new Scope("SingleCategoryScope", "Single", true, this, 1));
49
50
50 if (!m_loaded) {
51 if (!m_loaded) {
51 m_loaded = true;
52 m_loaded = true;
tests/mocks/libusermetrics/UserMetrics.cpp+3
@@ -24,6 +24,9 @@
24#include <QtGui/QIcon>
24#include <QtGui/QIcon>
25#include <QMultiMap>
25#include <QMultiMap>
26
26
27+#include <functional>
28+#include <random>
29+
27using namespace UserMetricsOutput;
30using namespace UserMetricsOutput;
28
31
29namespace UserMetricsOutput
32namespace UserMetricsOutput
tests/plugins/Dash/tst_ScopeStyle.qml+27−2
@@ -36,8 +36,8 @@ Rectangle {
36 property var styles: [
36 property var styles: [
37 {},
37 {},
38 { "foreground-color": "red", "background-color": "black", "page-header": { "logo": "/foo/bar" } },
38 { "foreground-color": "red", "background-color": "black", "page-header": { "logo": "/foo/bar" } },
39− { "foreground-color": "green", "background-color": "white" },
39+ { "foreground-color": "green", "background-color": "white", "page-header": { "foreground-color": "black" } },
40− { "foreground-color": "blue", "background-color": "darkgrey" },
40+ { "foreground-color": "blue", "background-color": "darkgrey", "page-header": { "background": "gradient:///white/blue" } },
41 ]
41 ]
42
42
43 function cleanup() {
43 function cleanup() {
@@ -147,5 +147,30 @@ Rectangle {
147 tool.style = testCase.styles[data.index];
147 tool.style = testCase.styles[data.index];
148 compare(tool.headerLogo, data.headerLogo, "Header logo was incorrect.");
148 compare(tool.headerLogo, data.headerLogo, "Header logo was incorrect.");
149 }
149 }
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+ }
150 }
175 }
151}
176}
tests/plugins/Unity/Indicators/unitymenumodelstacktest.cpp+3
@@ -24,6 +24,9 @@
24#include <QDebug>
24#include <QDebug>
25#include <unitymenumodel.h>
25#include <unitymenumodel.h>
26
26
27+#include <functional>
28+#include <chrono>
29+
27class UnityMenuModelStackTest : public QObject
30class UnityMenuModelStackTest : public QObject
28{
31{
29 Q_OBJECT
32 Q_OBJECT
tests/qmltests/CMakeLists.txt+4−4
@@ -19,12 +19,12 @@ set(qmltest_DEFAULT_TARGETS qmluitests)
19set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
19set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
20set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
20set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
21
21
22−add_qml_test(. Shell IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks
22+add_qml_test(. Shell ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
23− 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)
24add_qml_test(Components Carousel)
25add_qml_test(Components Carousel)
25add_qml_test(Components DraggingArea)
26add_qml_test(Components DraggingArea)
26add_qml_test(Components EdgeDemoOverlay)
27add_qml_test(Components EdgeDemoOverlay)
27−add_qml_test(Components FilterGrid)
28add_qml_test(Components LazyImage)
28add_qml_test(Components LazyImage)
29add_qml_test(Components Rating)
29add_qml_test(Components Rating)
30add_qml_test(Components ResponsiveFlowView)
30add_qml_test(Components ResponsiveFlowView)
@@ -75,4 +75,4 @@ add_qml_test(Panel/Indicators DefaultIndicatorPage ENVIRONMENT "LD_LIBRARY_PATH=
75# These MenuItemFactory tests need the test/mocks/ to come before plugins/
75# These MenuItemFactory tests need the test/mocks/ to come before plugins/
76add_qml_test(Panel/Indicators MenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
76add_qml_test(Panel/Indicators MenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
77add_qml_test(Panel/Indicators MessageMenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
77add_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 {
86 tryCompare(dashContentList, "count", 0);
86 tryCompare(dashContentList, "count", 0);
87 scopes.load();
87 scopes.load();
88 tryCompare(scopes, "loaded", true);
88 tryCompare(scopes, "loaded", true);
89− tryCompare(dashContentList, "count", 3);
89+ tryCompare(dashContentList, "count", 4);
90
90
91 verify(dashContentList != undefined);
91 verify(dashContentList != undefined);
92 tryCompare(dashContentList, "currentIndex", data.visualIndex);
92 tryCompare(dashContentList, "currentIndex", data.visualIndex);
tests/qmltests/Dash/tst_DashContent.qml+15−6
@@ -61,6 +61,11 @@ Item {
61 signalName: "movementStarted"
61 signalName: "movementStarted"
62 }
62 }
63
63
64+ SignalSpy {
65+ id: loadedSpy
66+ signalName: "loaded"
67+ }
68+
64 UT.UnityTestCase {
69 UT.UnityTestCase {
65 name: "DashContent"
70 name: "DashContent"
66 when: scopesModel.loaded && windowShown
71 when: scopesModel.loaded && windowShown
@@ -78,6 +83,7 @@ Item {
78
83
79 function cleanup() {
84 function cleanup() {
80 movementStartedSpy.clear();
85 movementStartedSpy.clear();
86+ loadedSpy.clear();
81 dashContent.visible = true;
87 dashContent.visible = true;
82
88
83 var dashContentList = findChild(dashContent, "dashContentList");
89 var dashContentList = findChild(dashContent, "dashContentList");
@@ -116,10 +122,11 @@ Item {
116
122
117 function test_show_header_on_list_movement() {
123 function test_show_header_on_list_movement() {
118 var dashContentList = findChild(dashContent, "dashContentList");
124 var dashContentList = findChild(dashContent, "dashContentList");
119− verify(dashContentList != undefined);
125+ verify(dashContentList !== null);
120− var categoryListView = findChild(dashContentList, "categoryListView");
126+ var scope = findChild(dashContent, "MockScope1 loader");
121− verify(categoryListView != undefined);
127+ waitForRendering(scope);
122
128
129+ var categoryListView = findChild(scope, "categoryListView");
123 waitForRendering(categoryListView);
130 waitForRendering(categoryListView);
124
131
125 categoryListView.contentY = units.gu(15);
132 categoryListView.contentY = units.gu(15);
@@ -133,10 +140,12 @@ Item {
133
140
134 function test_set_current_scope_reset() {
141 function test_set_current_scope_reset() {
135 var dashContentList = findChild(dashContent, "dashContentList");
142 var dashContentList = findChild(dashContent, "dashContentList");
136− verify(dashContentList != undefined);
143+ verify(dashContentList, "Couldn't find dashContentList");
137− var categoryListView = findChild(dashContentList, "categoryListView");
144+ var scope = findChild(dashContent, "MockScope1 loader");
138− verify(categoryListView != undefined);
139
145
146+ tryCompare(scope, "status", Loader.Ready);
147+
148+ var categoryListView = findChild(dashContentList, "categoryListView");
140 categoryListView.contentY = units.gu(10);
149 categoryListView.contentY = units.gu(10);
141
150
142 compare(dashContentList.currentItem.item.objectName, "MockScope1")
151 compare(dashContentList.currentItem.item.objectName, "MockScope1")
tests/qmltests/Dash/tst_GenericScopeView.qml+137−49
@@ -39,6 +39,10 @@ Item {
39 id: scopes
39 id: scopes
40 }
40 }
41
41
42+ SignalSpy {
43+ id: spy
44+ }
45+
42 property Item applicationManager: Item {
46 property Item applicationManager: Item {
43 signal sideStageFocusedApplicationChanged()
47 signal sideStageFocusedApplicationChanged()
44 signal mainStageFocusedApplicationChanged()
48 signal mainStageFocusedApplicationChanged()
@@ -54,12 +58,20 @@ Item {
54 when: scopes.loaded && windowShown
58 when: scopes.loaded && windowShown
55
59
56 property Item previewListView: findChild(genericScopeView, "previewListView")
60 property Item previewListView: findChild(genericScopeView, "previewListView")
61+ property Item header: findChild(genericScopeView, "scopePageHeader")
57
62
58 function init() {
63 function init() {
59 genericScopeView.scope = scopes.getScope(1)
64 genericScopeView.scope = scopes.getScope(1)
60 shell.width = units.gu(120)
65 shell.width = units.gu(120)
61 genericScopeView.categoryView.positionAtBeginning();
66 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 = "";
63 }
75 }
64
76
65 function test_isActive() {
77 function test_isActive() {
@@ -104,90 +116,146 @@ Item {
104 tryCompare(genericScopeView.scope, "searchQuery", "test")
116 tryCompare(genericScopeView.scope, "searchQuery", "test")
105 }
117 }
106
118
107− function test_filter_expand_collapse() {
119+ function test_expand_collapse() {
108− // wait for the item to be there
109− waitForRendering(genericScopeView);
110 tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader0") != null; }, true);
120 tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader0") != null; }, true);
111
121
112− var header = findChild(genericScopeView, "dashSectionHeader0")
113 var category = findChild(genericScopeView, "dashCategory0")
122 var category = findChild(genericScopeView, "dashCategory0")
123+ var seeAll = findChild(category, "seeAll")
114
124
115− waitForRendering(header);
125+ waitForRendering(seeAll);
116 verify(category.expandable);
126 verify(category.expandable);
117− verify(category.filtered);
127+ verify(!category.expanded);
118
128
119 var initialHeight = category.height;
129 var initialHeight = category.height;
120− var middleHeight;
121− mouseClick(header, header.width / 2, header.height / 2);
130+ mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
131+ verify(category.expanded);
122− tryCompareFunction(function() { middleHeight = category.height; return category.height > initialHeight; }, true);
132+ tryCompareFunction(function() { return category.height > initialHeight; }, true);
123− tryCompare(category, "filtered", false);
124− tryCompareFunction(function() { return category.height > middleHeight; }, true);
125
133
126− mouseClick(header, header.width / 2, header.height / 2);
134+ mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
127− verify(category.expandable);
135+ verify(!category.expanded);
128− tryCompare(category, "filtered", true);
129 }
136 }
130
137
131− function test_filter_expand_expand_collapse() {
138+ function test_expand_expand_collapse() {
132 // wait for the item to be there
139 // wait for the item to be there
133 tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader2") != null; }, true);
140 tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader2") != null; }, true);
134
141
135 var categoryListView = findChild(genericScopeView, "categoryListView");
142 var categoryListView = findChild(genericScopeView, "categoryListView");
136 categoryListView.contentY = categoryListView.height;
143 categoryListView.contentY = categoryListView.height;
137
144
138− var header2 = findChild(genericScopeView, "dashSectionHeader2")
139 var category2 = findChild(genericScopeView, "dashCategory2")
145 var category2 = findChild(genericScopeView, "dashCategory2")
140− var category2FilterGrid = category2.children[1].children[2];
146+ var seeAll2 = findChild(category2, "seeAll")
141− verify(UT.Util.isInstanceOf(category2FilterGrid, "CardFilterGrid"));
142
147
143− waitForRendering(header2);
148+ waitForRendering(seeAll2);
144 verify(category2.expandable);
149 verify(category2.expandable);
145− verify(category2.filtered);
150+ verify(!category2.expanded);
146
151
147− mouseClick(header2, header2.width / 2, header2.height / 2);
152+ mouseClick(seeAll2, seeAll2.width / 2, seeAll2.height / 2);
148− tryCompare(category2, "filtered", false);
153+ tryCompare(category2, "expanded", true);
149− tryCompare(category2FilterGrid, "filtered", false);
150
154
151 categoryListView.positionAtBeginning();
155 categoryListView.positionAtBeginning();
152
156
153− var header0 = findChild(genericScopeView, "dashSectionHeader0")
154 var category0 = findChild(genericScopeView, "dashCategory0")
157 var category0 = findChild(genericScopeView, "dashCategory0")
158+ var seeAll0 = findChild(category0, "seeAll")
155− mouseClick(header0, header0.width / 2, header0.height / 2);
159+ mouseClick(seeAll0, seeAll0.width / 2, seeAll0.height / 2);
156− tryCompare(category0, "filtered", false);
160+ tryCompare(category0, "expanded", true);
157− tryCompare(category2, "filtered", true);
161+ tryCompare(category2, "expanded", false);
158− tryCompare(category2FilterGrid, "filtered", true);
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+
159− mouseClick(header0, header0.width / 2, header0.height / 2);
174+ mouseClick(header, header.width / 2, header.height / 2);
160− tryCompare(category0, "filtered", true);
175+
161− tryCompare(category2, "filtered", true);
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.");
162 }
200 }
163
201
164 function test_narrow_delegate_ranges_expand() {
202 function test_narrow_delegate_ranges_expand() {
165− tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") != undefined; }, true);
203+ tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") !== null; }, true);
166 var category = findChild(genericScopeView, "dashCategory0")
204 var category = findChild(genericScopeView, "dashCategory0")
167− tryCompare(category, "filtered", true);
205+ tryCompare(category, "expanded", false);
168
206
169 shell.width = units.gu(20)
207 shell.width = units.gu(20)
170 var categoryListView = findChild(genericScopeView, "categoryListView");
208 var categoryListView = findChild(genericScopeView, "categoryListView");
171 categoryListView.contentY = units.gu(20);
209 categoryListView.contentY = units.gu(20);
172− var header0 = findChild(genericScopeView, "dashSectionHeader0")
210+ var seeAll = findChild(category, "seeAll")
173− mouseClick(header0, header0.width / 2, header0.height / 2);
211+ mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
174− tryCompare(category, "filtered", false);
212+ tryCompare(category, "expanded", true);
175 tryCompareFunction(function() { return category.item.height == genericScopeView.height - category.item.displayMarginBeginning - category.item.displayMarginEnd; }, true);
213 tryCompareFunction(function() { return category.item.height == genericScopeView.height - category.item.displayMarginBeginning - category.item.displayMarginEnd; }, true);
176− mouseClick(header0, header0.width / 2, header0.height / 2);
214+ mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
177− tryCompare(category, "filtered", true);
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");
178 }
244 }
179
245
180− function openPreview() {
246+ function openPreview(category, delegate) {
247+ if (category === undefined) category = 0;
248+ if (delegate === undefined) delegate = 0;
181 tryCompareFunction(function() {
249 tryCompareFunction(function() {
182− var filterGrid = findChild(genericScopeView, "0");
250+ var cardGrid = findChild(genericScopeView, category);
183− if (filterGrid != null) {
251+ if (cardGrid != null) {
184− var tile = findChild(filterGrid, "delegate0");
252+ var tile = findChild(cardGrid, "delegate"+delegate);
185 return tile != null;
253 return tile != null;
186 }
254 }
187 return false;
255 return false;
188 },
256 },
189 true);
257 true);
190− var tile = findChild(findChild(genericScopeView, "0"), "delegate0");
258+ var tile = findChild(findChild(genericScopeView, category), "delegate"+delegate);
191 mouseClick(tile, tile.width / 2, tile.height / 2);
259 mouseClick(tile, tile.width / 2, tile.height / 2);
192 tryCompare(testCase.previewListView, "open", true);
260 tryCompare(testCase.previewListView, "open", true);
193 tryCompare(testCase.previewListView, "x", 0);
261 tryCompare(testCase.previewListView, "x", 0);
@@ -257,13 +325,33 @@ Item {
257 closePreview();
325 closePreview();
258 }
326 }
259
327
260− function test_haeder_logo() {
328+ function test_header_style_data() {
261− genericScopeView.scope = scopes.getScope(3);
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+ }
262
336
263− var image = findChild(genericScopeView, "titleImage");
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");
264− verify(image, "Could not find the title image");
343+ verify(innerHeader, "Could not find the inner header");
265− compare(image.source, Qt.resolvedUrl("../Components/tst_PageHeader/logo-ubuntu-orange.svg"), "Title image has the wrong source");
344+ verify(Qt.colorEqual(innerHeader.textColor, data.foreground),
345+ "Foreground color not equal: %1 != %2".arg(innerHeader.textColor).arg(data.foreground));
266
346
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");
267 }
355 }
268 }
356 }
269 }
357 }
tests/qmltests/Greeter/tst_Lockscreen.qml+1−1
@@ -57,7 +57,7 @@ Rectangle {
57 target: LightDM.Greeter
57 target: LightDM.Greeter
58
58
59 onShowPrompt: {
59 onShowPrompt: {
60− if (text.indexOf("PIN") >= 0) {
60+ if (text === "PIN") {
61 pinPadCheckBox.checked = false
61 pinPadCheckBox.checked = false
62 } else {
62 } else {
63 pinPadCheckBox.checked = true
63 pinPadCheckBox.checked = true
tests/qmltests/tst_Shell.qml+19
@@ -51,6 +51,11 @@ Item {
51 id: shell
51 id: shell
52 }
52 }
53
53
54+ SignalSpy {
55+ id: sessionSpy
56+ signalName: "sessionStarted"
57+ }
58+
54 UT.UnityTestCase {
59 UT.UnityTestCase {
55 name: "Shell"
60 name: "Shell"
56 when: windowShown
61 when: windowShown
@@ -92,6 +97,8 @@ Item {
92 verify(ok);
97 verify(ok);
93
98
94 swipeAwayGreeter();
99 swipeAwayGreeter();
100+
101+ sessionSpy.target = findChild(shell, "greeter")
95 }
102 }
96
103
97 function cleanup() {
104 function cleanup() {
@@ -528,5 +535,17 @@ Item {
528 LightDM.Greeter.showGreeter()
535 LightDM.Greeter.showGreeter()
529 tryCompare(greeter, "showProgress", 1)
536 tryCompare(greeter, "showProgress", 1)
530 }
537 }
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+ }
531 }
550 }
532}
551}
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+}