on xenial help sign in
Merge trunk
d26a12bAlbert Astals
debian/changelog+102
@@ -1,3 +1,105 @@
1+unity8 (7.84+14.04.20140128-0ubuntu1) trusty; urgency=low
2+
3+ [ Michal Hruby ]
4+ * Added unity-scope-tool, which will help when developing scopes.
5+
6+ [ Michał Sawicz ]
7+ * Added unity-scope-tool, which will help when developing scopes.
8+ * Use full DashContent, not just GenericScopeView in ScopeTool.qml.
9+ * Bring Card and CardHeader over from new-scopes.
10+ * Work around bug #1268578. (LP: #1268578)
11+ * Drop unnecessary version dependencies.
12+ * Return null instead of undefined from findChild and
13+ findInvisibleChild.
14+ * Fix CardHeader and Card heights (empty Label does have non-zero
15+ height apparently). Also improve test robustness and reduce future
16+ diffs.
17+
18+ [ Albert Astals ]
19+ * Do not assert if the item we are removing was not created yet
20+ (because e.g. it's not in the viewport).
21+ * Position correctly the pointer of the search history box .
22+ * Make test_filter_expand_expand less unstable in CI VMs Make sure
23+ header0 is the header0 we want to click On the CI VM stuff is a bit
24+ slower than on real hw and we were clicking in the wrong place.
25+ * Add TabBar to the Dash header navigation Changes this comes with: *
26+ DashBar at the bottom is gone * PageHeader doesn't have a Label
27+ anymore, it has the childItem property where you add which thing it
28+ has to contain * New: PageHeaderLabel mimics the old behaviour of
29+ PageHeader * The header of the LVWPH of GenericScopeView is now fake
30+ and only used for positioning. There is a single global floating
31+ header in DashContent (which is a PageHeader with a TabBar as
32+ childItem) * The GenericScopeView previewLoader and OpenEffect have
33+ been also moved to the DashContent so that the openEffect includes
34+ the floating header in the "animation" .
35+ * Introduce the HorizontalJournal.
36+ * If there are no items m_firstVisibleIndex has to be -1 .
37+ * Add some more documentation about tests to the CODING file.
38+ * Fixes to the journal cmake tests code * Output to the correct
39+ filename for the test * Don't output stuff from the tryXYZ targets.
40+ * Adapt to findChild return value changes .
41+ * Organic Grid for the Dash View.
42+ * Misc journal fixes Don't init *modelIndex to INT_MAX Makes no sense
43+ since we're not doing any qMin and the calling function also accepts
44+ any index >= 0 as valid so in some cases it may end up wanting to
45+ create an index that doesn't exist Don't refill if height() < 0,
46+ that gives bad ranges for from/to and the code gets confused .
47+
48+ [ Michał Karnicki ]
49+ * Fix grid view column count.
50+ * Add test for minimum number of items in a carousel.
51+
52+ [ Allan LeSage ]
53+ * Add stubs for indicators autopilot tests.
54+
55+ [ Andrea Cimitan ]
56+ * Avoid input falling through notifications onto surfaces below, thus
57+ fixing LP: #1257312. (LP: #1257312)
58+
59+ [ Leo Arias ]
60+ * Close the Touch devices after the tests. (LP: #1267600)
61+ * Added methods to scroll to other scopes on autopilot tests.
62+ * Added autopilot helpers for the app scope and the app preview.
63+ Install the fake scopes in order to use them on the tests. (LP:
64+ #1269114)
65+ * On autopilot helpers, wait for the scope category to appear.
66+
67+ [ Nick Dedekind ]
68+ * Visual updates for indicator panel highlight and opening opacity.
69+ * Added inidcator tests for page & item factories.
70+ * Fixes visible indicator misalignment in indicator items/menus
71+ (lp#1264678). (LP: #1264678)
72+
73+ [ Mirco Müller ]
74+ * Fixed the failure of notification autopilot-test
75+ test_sd_incoming_call.
76+
77+ [ Michael Zanetti ]
78+ * clean up fullscreen notifications code.
79+ * import qml files into cmake, drop qmlproject.
80+ * also add qml files in tests directory.
81+ * Added autopilot helpers for the app scope and the app preview.
82+ Install the fake scopes in order to use them on the tests. (LP:
83+ #1269114)
84+
85+ [ Michael Terry ]
86+ * Fix failure to build when using the ./build script with ninja-build
87+ installed. (LP: #1268525)
88+ * Point DBus-activated processes at unity8's MIR_SOCKET rather than
89+ the system socket.
90+
91+ [ Daniel d'Andrada ]
92+ * DragHandle: Never restart hinting animation while still pressed (LP:
93+ #1269022)
94+
95+ [ Bill Filler ]
96+ * fix for lp:1259294, turn off auto capitalization for wifi password
97+ field. (LP: #1259294)
98+ * disable predictive text in Dash search field as it interferes with
99+ built-in search (LP: #1273643)
100+
101+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 28 Jan 2014 15:58:45 +0000
102+
1unity8 (7.84+14.04.20131220-0ubuntu1) trusty; urgency=low
103unity8 (7.84+14.04.20131220-0ubuntu1) trusty; urgency=low
2
104
3 [ Michał Sawicz ]
105 [ Michał Sawicz ]
po/bg.po+39−31
@@ -8,113 +8,121 @@ 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: 2013-11-29 09:21+0100\n"
10"POT-Creation-Date: 2013-11-29 09:21+0100\n"
11−"PO-Revision-Date: 2013-06-27 00:06+0000\n"
11+"PO-Revision-Date: 2014-01-28 19:22+0000\n"
12−"Last-Translator: Miroslav E. Hadzhiev (Хаджиев) "
12+"Last-Translator: Atanas Kovachki <Unknown>\n"
13−"<miroslav.hadzhiev@gmail.com>\n"
14"Language-Team: Bulgarian <bg@li.org>\n"
13"Language-Team: Bulgarian <bg@li.org>\n"
15"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
16"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
19−"X-Launchpad-Export-Date: 2013-12-29 06:04+0000\n"
18+"X-Launchpad-Export-Date: 2014-01-29 06:08+0000\n"
20−"X-Generator: Launchpad (build 16877)\n"
19+"X-Generator: Launchpad (build 16916)\n"
21
20
22#: Components/EdgeDemoOverlay.qml:151
21#: Components/EdgeDemoOverlay.qml:151
23msgid "Skip intro"
22msgid "Skip intro"
24−msgstr ""
23+msgstr "Пропусни интрото"
25
24
26#: Components/EdgeDemo.qml:112
25#: Components/EdgeDemo.qml:112
27msgid "Right edge"
26msgid "Right edge"
28−msgstr ""
27+msgstr "Десен край"
29
28
30#: Components/EdgeDemo.qml:113
29#: Components/EdgeDemo.qml:113
31msgid "Try swiping from the right edge to unlock the phone"
30msgid "Try swiping from the right edge to unlock the phone"
32msgstr ""
31msgstr ""
32+"Опитайте се да приплъзнете пръста си от десния край към левия, за да "
33+"отключите телефона"
33
34
34#: Components/EdgeDemo.qml:144
35#: Components/EdgeDemo.qml:144
35msgid "Top edge"
36msgid "Top edge"
36−msgstr ""
37+msgstr "Горен край"
37
38
38#: Components/EdgeDemo.qml:145
39#: Components/EdgeDemo.qml:145
39msgid "Try swiping from the top edge to access the indicators"
40msgid "Try swiping from the top edge to access the indicators"
40msgstr ""
41msgstr ""
42+"Опитайте се да приплъзнете пръста си от горния край към долния, за да "
43+"получите достъп до индикаторите"
41
44
42#: Components/EdgeDemo.qml:170
45#: Components/EdgeDemo.qml:170
43msgid "Close"
46msgid "Close"
44−msgstr ""
47+msgstr "Затвори"
45
48
46#: Components/EdgeDemo.qml:171
49#: Components/EdgeDemo.qml:171
47msgid "Swipe up again to close the settings screen"
50msgid "Swipe up again to close the settings screen"
48msgstr ""
51msgstr ""
52+"Отново приплъзнете пръста си нагоре за да затворите екрана с настройките"
49
53
50#: Components/EdgeDemo.qml:198
54#: Components/EdgeDemo.qml:198
51msgid "Left edge"
55msgid "Left edge"
52−msgstr ""
56+msgstr "Ляв край"
53
57
54#: Components/EdgeDemo.qml:199
58#: Components/EdgeDemo.qml:199
55msgid "Swipe from the left to reveal the launcher for quick access to apps"
59msgid "Swipe from the left to reveal the launcher for quick access to apps"
56msgstr ""
60msgstr ""
61+"Приплъзнете пръста си от левия край към десния, за да отворите стартера за "
62+"бърз достъп до приложенията"
57
63
58#: Components/EdgeDemo.qml:226
64#: Components/EdgeDemo.qml:226
59msgid "Well done"
65msgid "Well done"
60−msgstr ""
66+msgstr "Великолепно"
61
67
62#: Components/EdgeDemo.qml:227
68#: Components/EdgeDemo.qml:227
63msgid ""
69msgid ""
64"You have now mastered the edge gestures and can start using the "
70"You have now mastered the edge gestures and can start using the "
65"phone<br><br>Tap anywhere to start"
71"phone<br><br>Tap anywhere to start"
66msgstr ""
72msgstr ""
73+"Сега, когато сте научили основните движения, можете да започнете да "
74+"използвате телефона си.<br><br>Натиснете някъде за да започнете"
67
75
68#: Components/PageHeader.qml:364
76#: Components/PageHeader.qml:364
69msgid "Recent searches"
77msgid "Recent searches"
70−msgstr "Скорошни търсения"
78+msgstr "Последни търсения"
71
79
72#: Dash/Apps/AppPreview.qml:135
80#: Dash/Apps/AppPreview.qml:135
73msgid "Rate this"
81msgid "Rate this"
74−msgstr ""
82+msgstr "Оценете това"
75
83
76#. TRANSLATORS: Number of persons who rated this app/video/whatever
84#. TRANSLATORS: Number of persons who rated this app/video/whatever
77#: Dash/Previews/Header.qml:93
85#: Dash/Previews/Header.qml:93
78#, qt-format
86#, qt-format
79msgid "(%1)"
87msgid "(%1)"
80−msgstr ""
88+msgstr "(%1)"
81
89
82#. TRANSLATORS: Number of persons who wrote reviews for this app/video/whatever
90#. TRANSLATORS: Number of persons who wrote reviews for this app/video/whatever
83#: Dash/Previews/Header.qml:105
91#: Dash/Previews/Header.qml:105
84#, qt-format
92#, qt-format
85msgid "%1 review"
93msgid "%1 review"
86msgid_plural "%1 reviews"
94msgid_plural "%1 reviews"
87−msgstr[0] ""
95+msgstr[0] "%1 отзив"
88−msgstr[1] ""
96+msgstr[1] "%1 отзива"
89
97
90#: Dash/Previews/Reviews.qml:74
98#: Dash/Previews/Reviews.qml:74
91msgid "Add a review"
99msgid "Add a review"
92−msgstr ""
100+msgstr "Добави отзив"
93
101
94#: Dash/Previews/Reviews.qml:86
102#: Dash/Previews/Reviews.qml:86
95msgid "Review"
103msgid "Review"
96−msgstr ""
104+msgstr "Отзив"
97
105
98#: Dash/Previews/Reviews.qml:121
106#: Dash/Previews/Reviews.qml:121
99msgid "Send"
107msgid "Send"
100−msgstr ""
108+msgstr "Изпрати"
101
109
102#: Dash/Previews/Reviews.qml:139
110#: Dash/Previews/Reviews.qml:139
103msgid "Comments:"
111msgid "Comments:"
104−msgstr ""
112+msgstr "Коментари:"
105
113
106#: Greeter/Lockscreen.qml:149
114#: Greeter/Lockscreen.qml:149
107msgid "Emergency Call"
115msgid "Emergency Call"
108−msgstr ""
116+msgstr "Спешно повикване"
109
117
110#: Greeter/PassphraseLockscreen.qml:59
118#: Greeter/PassphraseLockscreen.qml:59
111#, qt-format
119#, qt-format
112msgid "Hello %1"
120msgid "Hello %1"
113−msgstr ""
121+msgstr "Здравей, %1"
114
122
115#: Greeter/PassphraseLockscreen.qml:59
123#: Greeter/PassphraseLockscreen.qml:59
116msgid "Hello"
124msgid "Hello"
117−msgstr ""
125+msgstr "Здравей"
118
126
119#: Hud/HudParametrizedActionsPage.qml:132
127#: Hud/HudParametrizedActionsPage.qml:132
120msgid "Confirm"
128msgid "Confirm"
@@ -122,23 +130,23 @@ msgstr "Потвърди"
122
130
123#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
131#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
124msgid "Type or say a command"
132msgid "Type or say a command"
125−msgstr ""
133+msgstr "Въведете или кажете команда"
126
134
127#: Hud/Hud.qml:84
135#: Hud/Hud.qml:84
128msgid "Loading. Please Wait..."
136msgid "Loading. Please Wait..."
129−msgstr ""
137+msgstr "Зарежда се. Моля, почакайте..."
130
138
131#: Hud/Hud.qml:89
139#: Hud/Hud.qml:89
132msgid "Speak Now..."
140msgid "Speak Now..."
133−msgstr ""
141+msgstr "Говорете сега..."
134
142
135#: Hud/Hud.qml:94
143#: Hud/Hud.qml:94
136msgid "Speaking..."
144msgid "Speaking..."
137−msgstr ""
145+msgstr "Говорете..."
138
146
139#: Notifications/NotificationMenuItemFactory.qml:89
147#: Notifications/NotificationMenuItemFactory.qml:89
140msgid "Show password"
148msgid "Show password"
141−msgstr ""
149+msgstr "Покажи паролата"
142
150
143#: Panel/SearchIndicator.qml:27
151#: Panel/SearchIndicator.qml:27
144msgid "Search"
152msgid "Search"
@@ -147,13 +155,13 @@ msgstr "Търсене"
147#: plugins/Unity/Launcher/launcheritem.cpp:43
155#: plugins/Unity/Launcher/launcheritem.cpp:43
148#: plugins/Unity/Launcher/launcheritem.cpp:73
156#: plugins/Unity/Launcher/launcheritem.cpp:73
149msgid "Lock to Launcher"
157msgid "Lock to Launcher"
150−msgstr ""
158+msgstr "Заключване към панела"
151
159
152#: plugins/Unity/Launcher/launcheritem.cpp:73
160#: plugins/Unity/Launcher/launcheritem.cpp:73
153msgid "Unlock from Launcher"
161msgid "Unlock from Launcher"
154−msgstr ""
162+msgstr "Отключи от панела за стартиране"
155
163
156#: Shell.qml:439
164#: Shell.qml:439
157#, qt-format
165#, qt-format
158msgid "Please enter %1"
166msgid "Please enter %1"
159−msgstr ""
167+msgstr "Моля, въведете %1"
qml/Components/DragHandle.qml+7−7
@@ -97,7 +97,7 @@ EdgeDragArea {
97 // Private stuff
97 // Private stuff
98 QtObject {
98 QtObject {
99 id: d
99 id: d
100− property var previousStatus: undefined
100+ property var previousStatus: DirectionalDragArea.WaitingForTouch
101 property real startValue
101 property real startValue
102 property real minValue: Direction.isPositive(direction) ? startValue
102 property real minValue: Direction.isPositive(direction) ? startValue
103 : startValue - maxTotalDragDistance
103 : startValue - maxTotalDragDistance
@@ -193,14 +193,14 @@ EdgeDragArea {
193 d.rollbackDrag();
193 d.rollbackDrag();
194 }
194 }
195 } else /* Undecided || Recognized */ {
195 } else /* Undecided || Recognized */ {
196− if (d.previousStatus === DirectionalDragArea.WaitingForTouch ||
196+ if (d.previousStatus === DirectionalDragArea.WaitingForTouch) {
197− d.previousStatus === undefined) {
198 dragEvaluator.reset();
197 dragEvaluator.reset();
199 d.startValue = parent[d.targetProp];
198 d.startValue = parent[d.targetProp];
200− }
199+
201− if (hintDisplacement > 0) {
200+ if (hintDisplacement > 0) {
202− hintingAnimation.targetValue = d.startValue;
201+ hintingAnimation.targetValue = d.startValue;
203− hintingAnimation.start();
202+ hintingAnimation.start();
203+ }
204 }
204 }
205 }
205 }
206
206
qml/Components/PageHeader.qml+1
@@ -145,6 +145,7 @@ Item {
145 anchors.fill: parent
145 anchors.fill: parent
146 anchors.margins: units.gu(1)
146 anchors.margins: units.gu(1)
147
147
148+ inputMethodHints: Qt.ImhNoPredictiveText
148 hasClearButton: false
149 hasClearButton: false
149
150
150 primaryItem: AbstractButton {
151 primaryItem: AbstractButton {
qml/Components/ResponsiveGridView.qml+1−1
@@ -72,7 +72,7 @@ Item {
72
72
73 function columnsForSpacing(spacing) {
73 function columnsForSpacing(spacing) {
74 // minimum margin is half of the spacing
74 // minimum margin is half of the spacing
75− return Math.max(1, Math.floor((parent.width - spacing/2) / (delegateWidth + spacing)));
75+ return Math.max(1, Math.floor(parent.width / (delegateWidth + spacing)));
76 }
76 }
77
77
78 property real allocatableHorizontalSpace: parent.width - columns * delegateWidth
78 property real allocatableHorizontalSpace: parent.width - columns * delegateWidth
qml/Dash/Card.qml+1
@@ -79,5 +79,6 @@ Item {
79 maximumLineCount: 5
79 maximumLineCount: 5
80 elide: Text.ElideRight
80 elide: Text.ElideRight
81 text: cardData && cardData["summary"] || ""
81 text: cardData && cardData["summary"] || ""
82+ height: text ? implicitHeight : 0
82 }
83 }
83}
84}
qml/Dash/CardHeader.qml+5−1
@@ -56,9 +56,9 @@ Item {
56
56
57 Label {
57 Label {
58 id: titleLabel
58 id: titleLabel
59+ objectName: "titleLabel"
59 anchors { left: parent.left; right: parent.right }
60 anchors { left: parent.left; right: parent.right }
60 elide: Text.ElideRight
61 elide: Text.ElideRight
61− objectName: "titleLabel"
62 font.weight: Font.DemiBold
62 font.weight: Font.DemiBold
63 wrapMode: Text.Wrap
63 wrapMode: Text.Wrap
64 maximumLineCount: 2
64 maximumLineCount: 2
@@ -66,6 +66,7 @@ Item {
66
66
67 Label {
67 Label {
68 id: subtitleLabel
68 id: subtitleLabel
69+ objectName: "subtitleLabel"
69 anchors { left: parent.left; right: parent.right }
70 anchors { left: parent.left; right: parent.right }
70 elide: Text.ElideRight
71 elide: Text.ElideRight
71 visible: titleLabel.text && text
72 visible: titleLabel.text && text
@@ -90,6 +91,7 @@ Item {
90 elide: Text.ElideRight
91 elide: Text.ElideRight
91 font.weight: Font.DemiBold
92 font.weight: Font.DemiBold
92 color: Theme.palette.selected.foreground
93 color: Theme.palette.selected.foreground
94+ visible: text
93 }
95 }
94
96
95 Label {
97 Label {
@@ -98,6 +100,7 @@ Item {
98 width: parent.labelWidth
100 width: parent.labelWidth
99 elide: Text.ElideRight
101 elide: Text.ElideRight
100 horizontalAlignment: parent.labels === 3 ? Text.AlignHCenter : Text.AlignRight
102 horizontalAlignment: parent.labels === 3 ? Text.AlignHCenter : Text.AlignRight
103+ visible: text
101 }
104 }
102
105
103 Label {
106 Label {
@@ -105,6 +108,7 @@ Item {
105 width: parent.labelWidth
108 width: parent.labelWidth
106 elide: Text.ElideRight
109 elide: Text.ElideRight
107 horizontalAlignment: Text.AlignRight
110 horizontalAlignment: Text.AlignRight
111+ visible: text
108 }
112 }
109 }
113 }
110 }
114 }
tests/autopilot/unity8/shell/emulators/dash.py+1−1
@@ -158,7 +158,7 @@ class DashApps(emulators.UnityEmulatorBase):
158
158
159 def _get_category_element(self, category):
159 def _get_category_element(self, category):
160 try:
160 try:
161− return self.select_single(
161+ return self.wait_select_single(
162 'Base', objectName='dashCategory{}'.format(category))
162 'Base', objectName='dashCategory{}'.format(category))
163 except dbus.StateNotFoundError:
163 except dbus.StateNotFoundError:
164 raise emulators.UnityEmulatorException(
164 raise emulators.UnityEmulatorException(
tests/autopilot/unity8/shell/tests/test_notifications.py+3−4
@@ -59,7 +59,7 @@ class NotificationsBase(UnityTestCase):
59 return '/usr/share/unity8/graphics/' + icon_name
59 return '/usr/share/unity8/graphics/' + icon_name
60 else:
60 else:
61 return os.path.abspath(
61 return os.path.abspath(
62− os.getcwd() + "/../../graphics/" + icon_name
62+ os.getcwd() + "../../qml/graphics/" + icon_name
63 )
63 )
64
64
65 def _get_notifications_list(self):
65 def _get_notifications_list(self):
@@ -161,8 +161,6 @@ class InteractiveNotificationBase(NotificationsBase):
161 unity_proxy = self.launch_unity()
161 unity_proxy = self.launch_unity()
162 unlock_unity(unity_proxy)
162 unlock_unity(unity_proxy)
163
163
164− notify_list = self._get_notifications_list()
165−
166 summary = "Incoming call"
164 summary = "Incoming call"
167 body = "Frank Zappa\n+44 (0)7736 027340"
165 body = "Frank Zappa\n+44 (0)7736 027340"
168 icon_path = self._get_icon_path('avatars/anna_olsson.png')
166 icon_path = self._get_icon_path('avatars/anna_olsson.png')
@@ -191,8 +189,9 @@ class InteractiveNotificationBase(NotificationsBase):
191 hints
189 hints
192 )
190 )
193
191
192+ notify_list = self._get_notifications_list()
194 get_notification = lambda: notify_list.wait_select_single(
193 get_notification = lambda: notify_list.wait_select_single(
195− 'Notification', objectName='notification1')
194+ 'Notification', objectName='notification0')
196 notification = get_notification()
195 notification = get_notification()
197 self._assert_notification(notification, None, None, True, True, 1.0)
196 self._assert_notification(notification, None, None, True, True, 1.0)
198 initial_height = notification.height
197 initial_height = notification.height
tests/qmltests/Components/tst_DragHandle.cpp+65−10
@@ -62,9 +62,13 @@ private Q_SLOTS:
62 void stretch_horizontal();
62 void stretch_horizontal();
63 void stretch_vertical();
63 void stretch_vertical();
64 void hintingAnimation();
64 void hintingAnimation();
65+ void hintingAnimation_dontRestartAfterFinishedAndStillPressed();
66+
65
67
66private:
68private:
67 void flickAndHold(DirectionalDragArea *dragHandle, qreal distance);
69 void flickAndHold(DirectionalDragArea *dragHandle, qreal distance);
70+ void drag(QPointF &touchPoint, const QPointF& direction, qreal distance,
71+ int numSteps, qint64 timeMs = 500);
68 DirectionalDragArea *fetchAndSetupDragHandle(const char *objectName);
72 DirectionalDragArea *fetchAndSetupDragHandle(const char *objectName);
69 qreal fetchDragThreshold(DirectionalDragArea *dragHandle);
73 qreal fetchDragThreshold(DirectionalDragArea *dragHandle);
70 void tryCompare(std::function<qreal ()> actualFunc, qreal expectedValue);
74 void tryCompare(std::function<qreal ()> actualFunc, qreal expectedValue);
@@ -161,25 +165,29 @@ void tst_DragHandle::flickAndHold(DirectionalDragArea *dragHandle,
161 QPointF initialTouchPos = dragHandle->mapToScene(
165 QPointF initialTouchPos = dragHandle->mapToScene(
162 QPointF(dragHandle->width() / 2.0, dragHandle->height() / 2.0));
166 QPointF(dragHandle->width() / 2.0, dragHandle->height() / 2.0));
163 QPointF touchPoint = initialTouchPos;
167 QPointF touchPoint = initialTouchPos;
164− int numSteps = 10;
165− qint64 flickTimeMs = 500;
166− qint64 timeStep = flickTimeMs / numSteps;
167
168
169+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
170+
171+ int numSteps = 10;
168 QPointF dragDirectionVector = calculateDirectionVector(dragHandle);
172 QPointF dragDirectionVector = calculateDirectionVector(dragHandle);
169− QPointF touchMovement = dragDirectionVector * (distance / (qreal)numSteps);
173+ drag(touchPoint, dragDirectionVector, distance, numSteps);
170
174
175+ // Wait for quite a bit before finally releasing to make a very low flick/release
176+ // speed.
177+ m_fakeTimeSource->m_msecsSinceReference += 5000;
171− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
178+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
179+}
172
180
181+void tst_DragHandle::drag(QPointF &touchPoint, const QPointF& direction, qreal distance,
182+ int numSteps, qint64 timeMs)
183+{
184+ qint64 timeStep = timeMs / numSteps;
185+ QPointF touchMovement = direction * (distance / (qreal)numSteps);
173 for (int i = 0; i < numSteps; ++i) {
186 for (int i = 0; i < numSteps; ++i) {
174 touchPoint += touchMovement;
187 touchPoint += touchMovement;
175 m_fakeTimeSource->m_msecsSinceReference += timeStep;
188 m_fakeTimeSource->m_msecsSinceReference += timeStep;
176 QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
189 QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
177 }
190 }
178−
179− // Wait for quite a bit before finally releasing to make a very low flick/release
180− // speed.
181− m_fakeTimeSource->m_msecsSinceReference += 5000;
182− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
183}
191}
184
192
185DirectionalDragArea *tst_DragHandle::fetchAndSetupDragHandle(const char *objectName)
193DirectionalDragArea *tst_DragHandle::fetchAndSetupDragHandle(const char *objectName)
@@ -389,6 +397,53 @@ void tst_DragHandle::hintingAnimation()
389 QCOMPARE(parentItem->property("shown").toBool(), false);
397 QCOMPARE(parentItem->property("shown").toBool(), false);
390}
398}
391
399
400+/*
401+ Regression test for LP#1269022: https://bugs.launchpad.net/unity8/+bug/1269022
402+
403+ 1) Click on handle.
404+ 2) wait for hint portion to appear
405+ 3) slowly drag handle, only a few pixels
406+
407+ Expected outcome:
408+ Nothing happens
409+
410+ Actual outcome:
411+ Handle will momentarily move back to zero position, then back down to the
412+ hint displacement location.
413+ */
414+void tst_DragHandle::hintingAnimation_dontRestartAfterFinishedAndStillPressed()
415+{
416+ DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
417+ QQuickItem *parentItem = dragHandle->parentItem();
418+ qreal hintDisplacement = 100.0;
419+
420+ // enable hinting animations
421+ m_view->rootObject()->setProperty("hintDisplacement", QVariant(hintDisplacement));
422+ m_view->rootObject()->setProperty("stretch", QVariant(true));
423+
424+ QCOMPARE(parentItem->height(), 0.0);
425+
426+ QPointF initialTouchPos = dragHandle->mapToScene(
427+ QPointF(dragHandle->width() / 2.0, dragHandle->height() / 2.0));
428+ QPointF touchPoint = initialTouchPos;
429+
430+ // Pressing causes the Showable to be stretched by hintDisplacement pixels
431+ const int touchId = 0;
432+ QTest::touchEvent(m_view, m_device).press(touchId, touchPoint.toPoint());
433+ tryCompare([&](){ return parentItem->height(); }, hintDisplacement);
434+
435+
436+ QSignalSpy parentHeightChangedSpy(parentItem, SIGNAL(heightChanged()));
437+
438+ drag(touchPoint, QPointF(0.0, -1.0) /*dragDirectionVector*/, 15 /*distance*/, 3 /*numSteps*/);
439+
440+ // Give some time for animations to run, if any
441+ QTest::qWait(300);
442+
443+ // parentItem height shouldn't have changed at all
444+ QVERIFY(parentHeightChangedSpy.isEmpty());
445+}
446+
392QTEST_MAIN(tst_DragHandle)
447QTEST_MAIN(tst_DragHandle)
393
448
394#include "tst_DragHandle.moc"
449#include "tst_DragHandle.moc"
tests/qmltests/Components/tst_ResponsiveGridView.qml+1−1
@@ -152,7 +152,7 @@ Item {
152 var data = new Array()
152 var data = new Array()
153
153
154 data.push({selectedIndex: 0, minHSpacing:0, columnCount: 13})
154 data.push({selectedIndex: 0, minHSpacing:0, columnCount: 13})
155− data.push({selectedIndex: 1, minHSpacing:units.gu(2), columnCount: 9})
155+ data.push({selectedIndex: 1, minHSpacing:units.gu(2), columnCount: 10})
156 data.push({selectedIndex: 2, minHSpacing:units.gu(8), columnCount: 5})
156 data.push({selectedIndex: 2, minHSpacing:units.gu(8), columnCount: 5})
157 data.push({selectedIndex: 3, minHSpacing:units.gu(25), columnCount: 2})
157 data.push({selectedIndex: 3, minHSpacing:units.gu(25), columnCount: 2})
158
158
tests/qmltests/Dash/tst_Card.qml+21−4
@@ -106,6 +106,10 @@ Rectangle {
106 "layout": { "template": { "card-layout": "horizontal" },
106 "layout": { "template": { "card-layout": "horizontal" },
107 "components": JSON.parse(fullMapping) }
107 "components": JSON.parse(fullMapping) }
108 },
108 },
109+ {
110+ "name": "Art, header - vertical",
111+ "layout": { "components": Helpers.update(JSON.parse(root.fullMapping), { "summary": undefined }) }
112+ },
109 ]
113 ]
110
114
111 Card {
115 Card {
@@ -189,7 +193,10 @@ Rectangle {
189 property Item summary: findChild(card, "summaryLabel")
193 property Item summary: findChild(card, "summaryLabel")
190
194
191 function initTestCase() {
195 function initTestCase() {
192− verify(testCase.header !== undefined, "Couldn't find header object.");
196+ verify(typeof testCase.header === "object", "Couldn't find header object.");
197+ verify(typeof testCase.art === "object", "Couldn't find art object.");
198+ verify(typeof testCase.artImage === "object", "Couldn't find artImage object.");
199+ verify(typeof testCase.summary === "object", "Couldn't find summary object.");
193 }
200 }
194
201
195 function cleanup() {
202 function cleanup() {
@@ -237,6 +244,9 @@ Rectangle {
237 { tag: "Large", width: units.gu(38), size: "large", index: 0 },
244 { tag: "Large", width: units.gu(38), size: "large", index: 0 },
238 { tag: "Wide", width: units.gu(18.5), aspect: 0.5, index: 0 },
245 { tag: "Wide", width: units.gu(18.5), aspect: 0.5, index: 0 },
239 { tag: "Horizontal", width: units.gu(38), index: 5 },
246 { tag: "Horizontal", width: units.gu(38), index: 5 },
247+ // Make sure card ends with header when there's no summary
248+ { tag: "NoSummary", height: function() { return header.y + header.height }, index: 6 },
249+ { tag: "HorizontalNoSummary", height: function() { return header.height }, card_layout: "horizontal", index: 6 },
240 ]
250 ]
241 }
251 }
242
252
@@ -248,6 +258,11 @@ Rectangle {
248 card.templateChanged();
258 card.templateChanged();
249 }
259 }
250
260
261+ if (data.hasOwnProperty("card_layout")) {
262+ card.template['card-layout'] = data.card_layout;
263+ card.templateChanged();
264+ }
265+
251 if (data.hasOwnProperty("aspect")) {
266 if (data.hasOwnProperty("aspect")) {
252 card.components['art']['aspect-ratio'] = data.aspect;
267 card.components['art']['aspect-ratio'] = data.aspect;
253 card.componentsChanged();
268 card.componentsChanged();
@@ -257,7 +272,9 @@ Rectangle {
257 tryCompare(card, "width", data.width);
272 tryCompare(card, "width", data.width);
258 }
273 }
259
274
275+ if (typeof data.height === "function") {
276+ tryCompareFunction(function() { return card.height === data.height() }, true);
260− if (data.hasOwnProperty("height")) {
277+ } else if (data.hasOwnProperty("height")) {
261 tryCompare(card, "height", data.height);
278 tryCompare(card, "height", data.height);
262 }
279 }
263 }
280 }
@@ -308,7 +325,7 @@ Rectangle {
308 function test_art_layout_data() {
325 function test_art_layout_data() {
309 return [
326 return [
310 { tag: "Vertical", left: function() { return 0 }, index: 0},
327 { tag: "Vertical", left: function() { return 0 }, index: 0},
311− { tag: "Horizontal", left: function() { return art.width }, index: 5 }
328+ { tag: "Horizontal", left: function() { return art.width }, index: 5 },
312 ];
329 ];
313 }
330 }
314
331
@@ -323,7 +340,7 @@ Rectangle {
323 { tag: "Vertical", top: function() { return art.y + art.height },
340 { tag: "Vertical", top: function() { return art.y + art.height },
324 left: function() { return art.x }, index: 0 },
341 left: function() { return art.x }, index: 0 },
325 { tag: "Horizontal", top: function() { return art.y },
342 { tag: "Horizontal", top: function() { return art.y },
326− left: function() { return art.x + art.width }, index: 5 }
343+ left: function() { return art.x + art.width }, index: 5 },
327 ]
344 ]
328 }
345 }
329
346
tests/qmltests/Dash/tst_CardHeader.qml+13−8
@@ -52,11 +52,11 @@ Rectangle {
52 property Item column: findChild(cardHeader, "column")
52 property Item column: findChild(cardHeader, "column")
53
53
54 function initTestCase() {
54 function initTestCase() {
55− verify(testCase.mascot !== undefined, "Couldn't find mascot object.");
55+ verify(typeof testCase.mascot === "object", "Couldn't find mascot object.");
56− verify(testCase.titleLabel !== undefined, "Couldn't find titleLabel object.");
56+ verify(typeof testCase.titleLabel === "object", "Couldn't find titleLabel object.");
57− verify(testCase.subtitleLabel !== undefined, "Couldn't find subtitleLabel object.");
57+ verify(typeof testCase.subtitleLabel === "object", "Couldn't find subtitleLabel object.");
58− verify(testCase.prices !== undefined, "Couldn't find prices object.");
58+ verify(typeof testCase.prices === "object", "Couldn't find prices object.");
59− verify(testCase.oldPriceLabel !== undefined, "Couldn't find oldPriceLabel object.");
59+ verify(typeof testCase.oldPriceLabel === "object", "Couldn't find oldPriceLabel object.");
60 }
60 }
61
61
62 function cleanup() {
62 function cleanup() {
@@ -86,7 +86,7 @@ Rectangle {
86 { tag: "Empty", visible: false },
86 { tag: "Empty", visible: false },
87 { tag: "Title only", title: "Foo", visible: true },
87 { tag: "Title only", title: "Foo", visible: true },
88 { tag: "Subtitle only", subtitle: "Bar", visible: false },
88 { tag: "Subtitle only", subtitle: "Bar", visible: false },
89− { tag: "Both", title: "Foo", subtitle: "Bar", visible: true }
89+ { tag: "Both", title: "Foo", subtitle: "Bar", visible: true },
90 ]
90 ]
91 }
91 }
92
92
@@ -104,7 +104,7 @@ Rectangle {
104 { tag: "Main and Alt", main: "$1.25", alt: "€1.00", visible: true },
104 { tag: "Main and Alt", main: "$1.25", alt: "€1.00", visible: true },
105 { tag: "Main and Old", main: "$1.25", old: "$2.00", visible: true, oldAlign: Text.AlignRight },
105 { tag: "Main and Old", main: "$1.25", old: "$2.00", visible: true, oldAlign: Text.AlignRight },
106 { tag: "Alt and Old", alt: "€1.00", old: "$2.00", visible: false },
106 { tag: "Alt and Old", alt: "€1.00", old: "$2.00", visible: false },
107− { tag: "All", main: "$1.25", alt: "€1.00", old: "$2.00", visible: true, oldAlign: Text.AlignHCenter }
107+ { tag: "All", main: "$1.25", alt: "€1.00", old: "$2.00", visible: true, oldAlign: Text.AlignHCenter },
108 ]
108 ]
109 }
109 }
110
110
@@ -121,7 +121,8 @@ Rectangle {
121 function test_dimensions_data() {
121 function test_dimensions_data() {
122 return [
122 return [
123 { tag: "Column width", object: column, width: cardHeader.width - testCase.outerRow.spacing * 2 },
123 { tag: "Column width", object: column, width: cardHeader.width - testCase.outerRow.spacing * 2 },
124− { tag: "Column width", object: column, width: cardHeader.width - mascot.width - testCase.outerRow.spacing * 3, mascot: "artwork/avatar.png" }
124+ { tag: "Column width", object: column, width: cardHeader.width - mascot.width - testCase.outerRow.spacing * 3, mascot: "artwork/avatar.png" },
125+ { tag: "Header height", object: cardHeader, height: function() { return subtitleLabel.y + subtitleLabel.height + outerRow.spacing * 2 } },
125 ]
126 ]
126 }
127 }
127
128
@@ -133,6 +134,10 @@ Rectangle {
133 if (data.hasOwnProperty("width")) {
134 if (data.hasOwnProperty("width")) {
134 tryCompare(data.object, "width", data.width);
135 tryCompare(data.object, "width", data.width);
135 }
136 }
137+
138+ if (data.hasOwnProperty("height")) {
139+ tryCompareFunction(function() { return data.object.height === data.height() }, true);
140+ }
136 }
141 }
137 }
142 }
138}
143}
tests/qmltests/Dash/tst_GenericScopeView.qml+15
@@ -281,6 +281,21 @@ Item {
281 tryCompare(category, "filtered", true);
281 tryCompare(category, "filtered", true);
282 }
282 }
283
283
284+ function test_getRendererCarouselGridFallback() {
285+ var rendererId = "carousel"
286+ var contentType = ""
287+ var rendererHint = ""
288+ var results = new Object()
289+
290+ results.count = 7
291+ var renderer = genericScopeView.getRenderer(rendererId, contentType, rendererHint, results)
292+ compare(renderer, "Generic/GenericCarousel.qml")
293+
294+ results.count = 6
295+ renderer = genericScopeView.getRenderer(rendererId, contentType, rendererHint, results)
296+ compare(renderer, "Generic/GenericFilterGrid.qml")
297+ }
298+
284 function test_showPreviewCarousel() {
299 function test_showPreviewCarousel() {
285 tryCompareFunction(function() { return findChild(genericScopeView, "carouselDelegate") != null; }, true);
300 tryCompareFunction(function() { return findChild(genericScopeView, "carouselDelegate") != null; }, true);
286 var tile = findChild(genericScopeView, "carouselDelegate");
301 var tile = findChild(genericScopeView, "carouselDelegate");