on xenial help sign in
Add dash PageHeader styling.
commit0df783e9f903df066c2da93f456723f0b8b22688 authorMichał Sawicz <michal.sawicz@canonical.com> dateThu 24 Jul 2014, 20:40 (12 years ago) parent3a31c3c6d76bc5
8 files changed+239−12
plugins/Dash/ScopeStyle.qml+6 qml/Components/Background.qml+77 qml/Components/PageHeader.qml+6−1 tests/mocks/Unity/fake_scope.cpp+6−4 tests/plugins/Dash/tst_ScopeStyle.qml+27−2 tests/qmltests/CMakeLists.txt+1 tests/qmltests/Components/tst_Background.qml+90 tests/qmltests/Dash/tst_GenericScopeView.qml+26−5
plugins/Dash/ScopeStyle.qml+6
@@ -70,6 +70,12 @@ QtObject {
7070 /// Source of the logo image for the header
7171 readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
7272
73+ /// Background style for the header
74+ readonly property url headerBackground: "background" in d.headerStyle ? d.headerStyle["background"] : ""
75+
76+ /// Foreground color for the header
77+ readonly property color headerForeground: "foreground-color" in d.headerStyle ? d.headerStyle["foreground-color"] : foreground
78+
7379 //! @cond
7480 property var d: QtObject {
7581 readonly property real foregroundLuminance: luminance(foreground)
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/PageHeader.qml+6−1
@@ -127,6 +127,11 @@ Item {
127127 property bool showSearch: false
128128 property var popover: null
129129
130+ Background {
131+ objectName: "headerBackground"
132+ style: scopeStyle.headerBackground
133+ }
134+
130135 Behavior on contentY {
131136 UbuntuNumberAnimation {
132137 id: openSearchAnimation
@@ -225,7 +230,7 @@ Item {
225230 height: headerContainer.height
226231 contentHeight: height
227232 separatorSource: ""
228− textColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
233+ textColor: root.scopeStyle ? root.scopeStyle.headerForeground : "grey"
229234 property var styledItem: header
230235 property string title: root.title
231236 property var config: PageHeadConfiguration {
tests/mocks/Unity/fake_scope.cpp+6−4
@@ -182,14 +182,16 @@ bool Scope::hasDepartments() const
182182
183183QVariantMap Scope::customizations() const
184184{
185− QVariantMap m;
185+ QVariantMap m, h;
186186 if (m_id == "clickscope") {
187+ h["foreground-color"] = "yellow";
187188 m["background-color"] = "red";
188189 m["foreground-color"] = "blue";
190+ m["page-header"] = h;
189191 } else if (m_id == "MockScope5") {
190− QVariantMap pageHeader;
191− pageHeader["logo"] = QUrl("../../../tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg");
192− m["page-header"] = pageHeader;
192+ h["background"] = "gradient:///lightgrey/grey";
193+ h["logo"] = QUrl("../../../tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg");
194+ m["page-header"] = h;
193195 }
194196 return m;
195197}
tests/plugins/Dash/tst_ScopeStyle.qml+27−2
@@ -36,8 +36,8 @@ Rectangle {
3636 property var styles: [
3737 {},
3838 { "foreground-color": "red", "background-color": "black", "page-header": { "logo": "/foo/bar" } },
39− { "foreground-color": "green", "background-color": "white" },
40− { "foreground-color": "blue", "background-color": "darkgrey" },
39+ { "foreground-color": "green", "background-color": "white", "page-header": { "foreground-color": "black" } },
40+ { "foreground-color": "blue", "background-color": "darkgrey", "page-header": { "background": "gradient:///white/blue" } },
4141 ]
4242
4343 function cleanup() {
@@ -147,5 +147,30 @@ Rectangle {
147147 tool.style = testCase.styles[data.index];
148148 compare(tool.headerLogo, data.headerLogo, "Header logo was incorrect.");
149149 }
150+
151+ function test_headerForeground_data() {
152+ return [
153+ { tag: "default", index: 0, headerForeground: "grey" },
154+ { tag: "black", index: 2, headerForeground: "black" },
155+ ];
156+ }
157+
158+ function test_headerForeground(data) {
159+ tool.style = testCase.styles[data.index];
160+ verify(Qt.colorEqual(tool.headerForeground, data.headerForeground),
161+ "Header foreground not equal: %1 != %2".arg(tool.headerForeground).arg(data.headerForeground));
162+ }
163+
164+ function test_headerBackground_data() {
165+ return [
166+ { tag: "default", index: 0, headerBackground: "" },
167+ { tag: "black", index: 3, headerBackground: "gradient:///white/blue" },
168+ ];
169+ }
170+
171+ function test_headerBackground(data) {
172+ tool.style = testCase.styles[data.index];
173+ compare(tool.headerBackground, data.headerBackground, "Header background was incorrect.");
174+ }
150175 }
151176}
tests/qmltests/CMakeLists.txt+1
@@ -21,6 +21,7 @@ set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
2121
2222add_qml_test(. Shell ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
2323add_qml_test(. ShellWithPin ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single-pin")
24+add_qml_test(Components Background)
2425add_qml_test(Components Carousel)
2526add_qml_test(Components DraggingArea)
2627add_qml_test(Components EdgeDemoOverlay)
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/Dash/tst_GenericScopeView.qml+26−5
@@ -58,6 +58,7 @@ Item {
5858 when: scopes.loaded && windowShown
5959
6060 property Item previewListView: findChild(genericScopeView, "previewListView")
61+ property Item header: findChild(genericScopeView, "scopePageHeader")
6162
6263 function init() {
6364 genericScopeView.scope = scopes.getScope(1)
@@ -324,13 +325,33 @@ Item {
324325 closePreview();
325326 }
326327
327− function test_header_logo() {
328− genericScopeView.scope = scopes.getScope(3);
328+ function test_header_style_data() {
329+ return [
330+ { tag: "Default", index: 0, foreground: "grey", background: "", logo: "" },
331+ { tag: "Foreground", index: 2, foreground: "yellow", background: "", logo: "" },
332+ { tag: "Logo+Background", index: 3, foreground: "grey", background: "gradient:///lightgrey/grey",
333+ logo: Qt.resolvedUrl("../Components/tst_PageHeader/logo-ubuntu-orange.svg") },
334+ ];
335+ }
329336
330− var image = findChild(genericScopeView, "titleImage");
331− verify(image, "Could not find the title image");
332− compare(image.source, Qt.resolvedUrl("../Components/tst_PageHeader/logo-ubuntu-orange.svg"), "Title image has the wrong source");
337+ function test_header_style(data) {
338+ genericScopeView.scope = scopes.getScope(data.index);
339+ waitForRendering(genericScopeView);
340+ verify(header, "Could not find the header.");
341+
342+ var innerHeader = findChild(header, "innerPageHeader");
343+ verify(innerHeader, "Could not find the inner header");
344+ verify(Qt.colorEqual(innerHeader.textColor, data.foreground),
345+ "Foreground color not equal: %1 != %2".arg(innerHeader.textColor).arg(data.foreground));
333346
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");
334355 }
335356 }
336357 }