on xenial help sign in
Add initial support for scope customizations.
4c3de71Michał Sawicz
doc/CMakeLists.txt+2
@@ -15,6 +15,8 @@ else()
15 ${CMAKE_SOURCE_DIR}/src/*.cpp
15 ${CMAKE_SOURCE_DIR}/src/*.cpp
16 ${CMAKE_SOURCE_DIR}/plugins/*.h
16 ${CMAKE_SOURCE_DIR}/plugins/*.h
17 ${CMAKE_SOURCE_DIR}/plugins/*.cpp
17 ${CMAKE_SOURCE_DIR}/plugins/*.cpp
18+ ${CMAKE_SOURCE_DIR}/plugins/*.qml
19+ ${CMAKE_SOURCE_DIR}/plugins/*.js
18 ${CMAKE_SOURCE_DIR}/qml/*.qml
20 ${CMAKE_SOURCE_DIR}/qml/*.qml
19 ${CMAKE_SOURCE_DIR}/qml/*.js
21 ${CMAKE_SOURCE_DIR}/qml/*.js
20 ${CMAKE_SOURCE_DIR}/tests/autopilot/*.py
22 ${CMAKE_SOURCE_DIR}/tests/autopilot/*.py
plugins/Dash/CardCreator.js+4−3
@@ -289,6 +289,7 @@ function cardString(template, components) {
289 property var cardData; \n\
289 property var cardData; \n\
290 property var artShapeBorderSource: undefined; \n\
290 property var artShapeBorderSource: undefined; \n\
291 property real fontScale: 1.0; \n\
291 property real fontScale: 1.0; \n\
292+ property var scopeStyle: null; \n\
292 property int headerAlignment: Text.AlignLeft; \n\
293 property int headerAlignment: Text.AlignLeft; \n\
293 property int fixedHeaderHeight: -1; \n\
294 property int fixedHeaderHeight: -1; \n\
294 property size fixedArtShapeSize: Qt.size(-1, -1); \n\
295 property size fixedArtShapeSize: Qt.size(-1, -1); \n\
@@ -407,7 +408,7 @@ function cardString(template, components) {
407 mascotCode = kMascotImageCode.arg(anchors).arg(mascotImageVisible);
408 mascotCode = kMascotImageCode.arg(anchors).arg(mascotImageVisible);
408 }
409 }
409
410
410− var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : "grey"';
411+ var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey")';
411
412
412 var titleSubtitleCode = "";
413 var titleSubtitleCode = "";
413 if (hasTitle) {
414 if (hasTitle) {
@@ -419,7 +420,7 @@ function cardString(template, components) {
419 } else if (hasBackground) {
420 } else if (hasBackground) {
420 color = summaryColorWithBackground;
421 color = summaryColorWithBackground;
421 } else {
422 } else {
422− color = '"grey"';
423+ color = 'root.scopeStyle ? root.scopeStyle.foreground : "grey"';
423 }
424 }
424
425
425 var titleAnchors;
426 var titleAnchors;
@@ -495,7 +496,7 @@ function cardString(template, components) {
495 if (hasBackground) {
496 if (hasBackground) {
496 color = summaryColorWithBackground;
497 color = summaryColorWithBackground;
497 } else {
498 } else {
498− color = '"grey"';
499+ color = 'root.scopeStyle ? root.scopeStyle.foreground : "grey"';
499 }
500 }
500
501
501 var summaryTopMargin = (hasMascot || hasSubtitle ? 'anchors.margins' : '0');
502 var summaryTopMargin = (hasMascot || hasSubtitle ? 'anchors.margins' : '0');
plugins/Dash/ScopeStyle.qmlnew file+87
@@ -0,0 +1,87 @@
1+/*
2+ * Copyright 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+
19+/*! \brief Helper for processing scope customization options.
20+
21+ It will take the customizations object passed by the scope and
22+ process it to provide the scope UI with data such as colors or
23+ image paths.
24+ */
25+
26+QtObject {
27+ /// Style object passed from the scope
28+ property var style: Object()
29+
30+ /*! \brief Calculate luminance of the passed color
31+
32+ \note If not fully opaque, luminance is dependant on blending.
33+ */
34+ function luminance(color) {
35+ return 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
36+ }
37+
38+ /// Color used for text and symbolic icons
39+ readonly property color foreground: "foreground-color" in style ? style["foreground-color"] : d.defaultDark
40+
41+ /// Color used for the overall background
42+ readonly property color background: "background-color" in style ? style["background-color"] : "transparent"
43+
44+ /*! \brief Luminance threshold for switching between fore and background color
45+
46+ \note If background colour is not fully opaque, it's not taken into account.
47+ */
48+ readonly property real threshold: background.a !== 1.0 ? d.foregroundLuminance : (d.foregroundLuminance + d.backgroundLuminance) / 2
49+
50+ /*! \brief The lighter of foreground and background colors
51+
52+ \note If background color is not fully opaque, it's not taken into account
53+ and defaults to the theme-provided light color.
54+ */
55+ readonly property color light: {
56+ if (background.a !== 1.0) return d.foregroundLuminance > d.defaultLightLuminance ? foreground : d.defaultLight;
57+ return d.foregroundLuminance > d.backgroundLuminance ? foreground : background;
58+ }
59+
60+ /*! \brief The darker of foreground and background colors
61+
62+ \note If background color is not fully opaque, it's not taken into account
63+ and defaults to the theme-provided dark color.
64+ */
65+ readonly property color dark: {
66+ if (background.a !== 1.0) return d.foregroundLuminance < d.defaultDarkLuminance ? foreground : d.defaultDark;
67+ return d.foregroundLuminance < d.backgroundLuminance ? foreground : background;
68+ }
69+
70+ /// Source of the logo image for the header
71+ readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
72+
73+ //! @cond
74+ property var d: QtObject {
75+ readonly property real foregroundLuminance: luminance(foreground)
76+ readonly property real backgroundLuminance: luminance(background)
77+
78+ // FIXME: should be taken from the theme
79+ readonly property color defaultLight: "white"
80+ readonly property color defaultDark: "grey"
81+ readonly property real defaultLightLuminance: luminance(defaultLight)
82+ readonly property real defaultDarkLuminance: luminance(defaultDark)
83+
84+ readonly property var headerStyle: "page-header" in style ? style["page-header"] : { }
85+ }
86+ //! @endcond
87+}
plugins/Dash/qmldir+1
@@ -2,3 +2,4 @@ module Dash
2plugin Dash-qml
2plugin Dash-qml
3typeinfo Dash.qmltypes
3typeinfo Dash.qmltypes
4singleton CardCreatorCache 0.1 CardCreatorCache.qml
4singleton CardCreatorCache 0.1 CardCreatorCache.qml
5+ScopeStyle 0.1 ScopeStyle.qml
qml/Components/ListItems/Header.qml+1
@@ -24,6 +24,7 @@ Item {
24 \qmlproperty string text
24 \qmlproperty string text
25 */
25 */
26 property alias text: label.text
26 property alias text: label.text
27+ property alias textColor: label.color
27 property alias image: image.source
28 property alias image: image.source
28
29
29 signal clicked(variant mouse)
30 signal clicked(variant mouse)
qml/Components/PageHeader.qml+19−12
@@ -28,7 +28,6 @@ Item {
28
28
29 property bool showBackButton: false
29 property bool showBackButton: false
30 property string title
30 property string title
31− property string imageSource
32
31
33 property bool searchEntryEnabled: false
32 property bool searchEntryEnabled: false
34 property ListModel searchHistory: SearchHistoryModel
33 property ListModel searchHistory: SearchHistoryModel
@@ -37,8 +36,15 @@ Item {
37
36
38 property alias bottomItem: bottomContainer.children
37 property alias bottomItem: bottomContainer.children
39
38
39+ // TODO We should use foreground for the icons
40+ // of the toolbar but unfortunately Action does not have
41+ // the keyColor property as Icon does :-/
42+ property var scopeStyle: null
43+
40 signal backClicked()
44 signal backClicked()
41
45
46+ onScopeStyleChanged: refreshLogo()
47+
42 function triggerSearch() {
48 function triggerSearch() {
43 if (searchEntryEnabled) {
49 if (searchEntryEnabled) {
44 headerContainer.showSearch = true;
50 headerContainer.showSearch = true;
@@ -79,15 +85,20 @@ Item {
79 }
85 }
80 }
86 }
81
87
82− onImageSourceChanged: {
88+ function refreshLogo() {
83− if (imageSource) {
89+ if (scopeStyle ? scopeStyle.headerLogo != "" : false) {
84 header.contents = imageComponent.createObject();
90 header.contents = imageComponent.createObject();
85− } else {
91+ } else if (header.contents) {
86 header.contents.destroy();
92 header.contents.destroy();
87 header.contents = null;
93 header.contents = null;
88 }
94 }
89 }
95 }
90
96
97+ Connections {
98+ target: root.scopeStyle
99+ onHeaderLogoChanged: root.refreshLogo()
100+ }
101+
91 InverseMouseArea {
102 InverseMouseArea {
92 anchors { fill: parent; margins: units.gu(1); bottomMargin: units.gu(3) + bottomContainer.height }
103 anchors { fill: parent; margins: units.gu(1); bottomMargin: units.gu(3) + bottomContainer.height }
93 visible: headerContainer.showSearch
104 visible: headerContainer.showSearch
@@ -214,8 +225,7 @@ Item {
214 height: headerContainer.height
225 height: headerContainer.height
215 contentHeight: height
226 contentHeight: height
216 separatorSource: ""
227 separatorSource: ""
217− // FIXME: Use the theme's color once we're split from the shell
218− textColor: "grey"
228+ textColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
219 property var styledItem: header
229 property var styledItem: header
220 property string title: root.title
230 property string title: root.title
221 property var config: PageHeadConfiguration {
231 property var config: PageHeadConfiguration {
@@ -240,11 +250,8 @@ Item {
240 }
250 }
241
251
242 property var contents: null
252 property var contents: null
243− Component.onCompleted: {
253+ Component.onCompleted: root.refreshLogo()
244− if (root.imageSource) {
254+
245− header.contents = imageComponent.createObject();
246− }
247− }
248 Component {
255 Component {
249 id: imageComponent
256 id: imageComponent
250
257
@@ -254,7 +261,7 @@ Item {
254 Image {
261 Image {
255 objectName: "titleImage"
262 objectName: "titleImage"
256 anchors.fill: parent
263 anchors.fill: parent
257− source: root.imageSource
264+ source: root.scopeStyle ? root.scopeStyle.headerLogo : ""
258 fillMode: Image.PreserveAspectFit
265 fillMode: Image.PreserveAspectFit
259 horizontalAlignment: Image.AlignLeft
266 horizontalAlignment: Image.AlignLeft
260 sourceSize.height: height
267 sourceSize.height: height
qml/Dash/CardCarousel.qml+1
@@ -66,6 +66,7 @@ DashRenderer {
66 item.fontScale = Qt.binding(function() { return carousel.fontScale; });
66 item.fontScale = Qt.binding(function() { return carousel.fontScale; });
67 item.showHeader = Qt.binding(function() { return loader.explicitlyScaled; });
67 item.showHeader = Qt.binding(function() { return loader.explicitlyScaled; });
68 item.artShapeBorderSource = "none";
68 item.artShapeBorderSource = "none";
69+ item.scopeStyle = cardCarousel.scopeStyle;
69 }
70 }
70
71
71 BorderImage {
72 BorderImage {
qml/Dash/CardFilterGrid.qml+1
@@ -58,6 +58,7 @@ 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 }
62 }
62 Connections {
63 Connections {
63 target: loader.item
64 target: loader.item
qml/Dash/CardVerticalJournal.qml+1
@@ -75,6 +75,7 @@ DashRenderer {
75 item.template = Qt.binding(function() { return cardTool.template; });
75 item.template = Qt.binding(function() { return cardTool.template; });
76 item.components = Qt.binding(function() { return cardTool.components; });
76 item.components = Qt.binding(function() { return cardTool.components; });
77 item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
77 item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
78+ item.scopeStyle = root.scopeStyle;
78 }
79 }
79 Connections {
80 Connections {
80 target: loader.item
81 target: loader.item
qml/Dash/DashDepartments.qml+8−7
@@ -29,6 +29,7 @@ AbstractButton {
29
29
30 property alias windowWidth: blackRect.width
30 property alias windowWidth: blackRect.width
31 property alias windowHeight: blackRect.height
31 property alias windowHeight: blackRect.height
32+ property var scopeStyle: null
32
33
33 // Are we drilling down the tree or up?
34 // Are we drilling down the tree or up?
34 property bool isGoingBack: false
35 property bool isGoingBack: false
@@ -78,18 +79,17 @@ AbstractButton {
78 anchors.margins: units.gu(2)
79 anchors.margins: units.gu(2)
79 verticalAlignment: Text.AlignVCenter
80 verticalAlignment: Text.AlignVCenter
80 text: root.currentDepartment ? root.currentDepartment.label : ""
81 text: root.currentDepartment ? root.currentDepartment.label : ""
81− color: "gray" // TODO remove once we're a separate app
82+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
82 }
83 }
83
84
84− Image {
85+ Icon {
85 anchors.verticalCenter: parent.verticalCenter
86 anchors.verticalCenter: parent.verticalCenter
86 anchors.right: parent.right
87 anchors.right: parent.right
87 anchors.rightMargin: units.gu(2)
88 anchors.rightMargin: units.gu(2)
88− rotation: showList ? 180 : 0
89+ name: showList ? "up" : "down"
89− source: "image://theme/dropdown-menu"
90− sourceSize.height: parent.height - units.gu(2)
90+ height: units.gu(2)
91− sourceSize.width: units.gu(2)
91+ width: height
92− fillMode: Image.PreserveAspectFit
92+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
93 }
93 }
94
94
95 // departmentListView is outside root
95 // departmentListView is outside root
@@ -124,6 +124,7 @@ AbstractButton {
124 objectName: "department" + index
124 objectName: "department" + index
125 visible: height != 0
125 visible: height != 0
126 width: departmentListView.width
126 width: departmentListView.width
127+ scopeStyle: root.scopeStyle
127 property real desiredHeight: {
128 property real desiredHeight: {
128 if (root.showList) {
129 if (root.showList) {
129 if (department && department.loaded && x == departmentListView.contentX)
130 if (department && department.loaded && x == departmentListView.contentX)
qml/Dash/DashDepartmentsList.qml+19−17
@@ -21,15 +21,17 @@ Item {
21 id: root
21 id: root
22 property var department: null
22 property var department: null
23 property var currentDepartment: null
23 property var currentDepartment: null
24+ property var scopeStyle: null
24 signal enterDepartment(var newDepartmentId, bool hasChildren)
25 signal enterDepartment(var newDepartmentId, bool hasChildren)
25 signal goBackToParentClicked()
26 signal goBackToParentClicked()
26 signal allDepartmentClicked()
27 signal allDepartmentClicked()
27
28
28 readonly property int itemHeight: units.gu(5)
29 readonly property int itemHeight: units.gu(5)
30+ readonly property color foregroundColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
29 implicitHeight: flickable.contentHeight
31 implicitHeight: flickable.contentHeight
30
32
31 Rectangle {
33 Rectangle {
32− color: "white"
34+ color: !root.scopeStyle || Qt.colorEqual(root.scopeStyle.background, "transparent") ? "white" : root.scopeStyle.background
33 anchors.fill: parent
35 anchors.fill: parent
34 }
36 }
35
37
@@ -71,17 +73,17 @@ Item {
71
73
72 onClicked: root.goBackToParentClicked();
74 onClicked: root.goBackToParentClicked();
73
75
74− Image {
76+ Icon {
75 id: backImage
77 id: backImage
76 anchors {
78 anchors {
77 verticalCenter: parent.verticalCenter
79 verticalCenter: parent.verticalCenter
78 left: parent.left
80 left: parent.left
79 leftMargin: units.gu(2)
81 leftMargin: units.gu(2)
80 }
82 }
81− source: "image://theme/back"
83+ name: "back"
82− sourceSize.height: parent.height - units.gu(3)
84+ height: units.gu(2)
83− sourceSize.width: units.gu(3)
85+ width: height
84− fillMode: Image.PreserveAspectFit
86+ color: root.foregroundColor
85 }
87 }
86
88
87 Label {
89 Label {
@@ -91,7 +93,7 @@ Item {
91 leftMargin: units.gu(0.5)
93 leftMargin: units.gu(0.5)
92 }
94 }
93 text: department ? department.parentLabel : ""
95 text: department ? department.parentLabel : ""
94− color: "gray" // TODO remove once we're a separate app
96+ color: root.foregroundColor
95 }
97 }
96
98
97 Rectangle {
99 Rectangle {
@@ -102,7 +104,7 @@ Item {
102 leftMargin: units.gu(2)
104 leftMargin: units.gu(2)
103 rightMargin: units.gu(2)
105 rightMargin: units.gu(2)
104 }
106 }
105− color: "gray"
107+ color: root.foregroundColor
106 opacity: 0.2
108 opacity: 0.2
107 height: units.dp(1)
109 height: units.dp(1)
108 }
110 }
@@ -123,7 +125,7 @@ Item {
123 }
125 }
124 text: department ? (department.allLabel != "" ? department.allLabel : department.label) : ""
126 text: department ? (department.allLabel != "" ? department.allLabel : department.label) : ""
125 font.bold: true
127 font.bold: true
126− color: "gray" // TODO remove once we're a separate app
128+ color: root.foregroundColor
127 }
129 }
128
130
129 Rectangle {
131 Rectangle {
@@ -134,7 +136,7 @@ Item {
134 leftMargin: units.gu(2)
136 leftMargin: units.gu(2)
135 rightMargin: units.gu(2)
137 rightMargin: units.gu(2)
136 }
138 }
137− color: "gray"
139+ color: root.foregroundColor
138 opacity: 0.2
140 opacity: 0.2
139 height: units.dp(1)
141 height: units.dp(1)
140 }
142 }
@@ -159,19 +161,19 @@ Item {
159 leftMargin: units.gu(2)
161 leftMargin: units.gu(2)
160 }
162 }
161 text: label
163 text: label
162− color: "gray" // TODO remove once we're a separate app
164+ color: root.foregroundColor
163 }
165 }
164
166
165− Image {
167+ Icon {
166 anchors {
168 anchors {
167 verticalCenter: parent.verticalCenter
169 verticalCenter: parent.verticalCenter
168 right: parent.right
170 right: parent.right
169 rightMargin: units.gu(2)
171 rightMargin: units.gu(2)
170 }
172 }
173+ height: units.gu(2)
174+ width: height
171− source: hasChildren ? "image://theme/chevron" : "graphics/tick.png"
175+ name: hasChildren ? "go-next" : "tick"
172− sourceSize.height: parent.height - units.gu(3)
176+ color: root.foregroundColor
173− sourceSize.width: units.gu(3)
174− fillMode: Image.PreserveAspectFit
175 visible: hasChildren || isActive
177 visible: hasChildren || isActive
176 }
178 }
177
179
@@ -183,7 +185,7 @@ Item {
183 leftMargin: units.gu(2)
185 leftMargin: units.gu(2)
184 rightMargin: units.gu(2)
186 rightMargin: units.gu(2)
185 }
187 }
186− color: "gray"
188+ color: root.foregroundColor
187 opacity: 0.1
189 opacity: 0.1
188 height: units.dp(1)
190 height: units.dp(1)
189 visible: index != department.count - 1
191 visible: index != department.count - 1
qml/Dash/DashRenderer.qml+5−4
@@ -36,10 +36,11 @@ Item {
36 // The model to renderer
36 // The model to renderer
37 property var model
37 property var model
38
38
39− /*!
40− \brief CardTool component.
39+ /// CardTool component.
41− */
42− property var cardTool: undefined
40+ property var cardTool: null
41+
42+ /// ScopeStyle component.
43+ property var scopeStyle: null
43
44
44 /// Emitted when the user clicked on an item
45 /// Emitted when the user clicked on an item
45 /// @param index is the index of the clicked item
46 /// @param index is the index of the clicked item
qml/Dash/GenericScopeView.qml+16
@@ -19,6 +19,7 @@ import Ubuntu.Components 0.1
19import Utils 0.1
19import Utils 0.1
20import Unity 0.2
20import Unity 0.2
21import Unity.Application 0.1
21import Unity.Application 0.1
22+import Dash 0.1
22import "../Components"
23import "../Components"
23import "../Components/ListItems" as ListItems
24import "../Components/ListItems" as ListItems
24
25
@@ -33,6 +34,10 @@ FocusScope {
33 property bool enableHeightBehaviorOnNextCreation: false
34 property bool enableHeightBehaviorOnNextCreation: false
34 property var categoryView: categoryView
35 property var categoryView: categoryView
35
36
37+ property var scopeStyle: ScopeStyle {
38+ style: scope ? scope.customizations : {}
39+ }
40+
36 signal backClicked()
41 signal backClicked()
37
42
38 onScopeChanged: {
43 onScopeChanged: {
@@ -97,6 +102,12 @@ FocusScope {
97 onHideDash: previewListView.open = false;
102 onHideDash: previewListView.open = false;
98 }
103 }
99
104
105+ Rectangle {
106+ anchors.fill: parent
107+ color: scopeView.scopeStyle ? scopeView.scopeStyle.background : "transparent"
108+ visible: color != "transparent"
109+ }
110+
100 ScopeListView {
111 ScopeListView {
101 id: categoryView
112 id: categoryView
102 objectName: "categoryListView"
113 objectName: "categoryListView"
@@ -164,6 +175,7 @@ FocusScope {
164 item.model = Qt.binding(function() { return results })
175 item.model = Qt.binding(function() { return results })
165 }
176 }
166 item.objectName = Qt.binding(function() { return categoryId })
177 item.objectName = Qt.binding(function() { return categoryId })
178+ item.scopeStyle = scopeView.scopeStyle;
167 if (item.expandable) {
179 if (item.expandable) {
168 var shouldFilter = categoryId != categoryView.expandedCategoryId;
180 var shouldFilter = categoryId != categoryView.expandedCategoryId;
169 item.setFilter(shouldFilter, false /*animate*/);
181 item.setFilter(shouldFilter, false /*animate*/);
@@ -303,6 +315,7 @@ FocusScope {
303 property var delegate: categoryView.item(delegateIndex)
315 property var delegate: categoryView.item(delegateIndex)
304 width: categoryView.width
316 width: categoryView.width
305 text: section
317 text: section
318+ textColor: scopeStyle ? scopeStyle.foreground : "grey"
306 image: {
319 image: {
307 if (delegate && delegate.expandable)
320 if (delegate && delegate.expandable)
308 return delegate.filtered ? "graphics/header_handlearrow.png" : "graphics/header_handlearrow2.png"
321 return delegate.filtered ? "graphics/header_handlearrow.png" : "graphics/header_handlearrow2.png"
@@ -324,6 +337,7 @@ FocusScope {
324 showBackButton: scopeView.hasBackAction
337 showBackButton: scopeView.hasBackAction
325 searchEntryEnabled: true
338 searchEntryEnabled: true
326 searchInProgress: scopeView.scope ? scopeView.scope.searchInProgress : false
339 searchInProgress: scopeView.scope ? scopeView.scope.searchInProgress : false
340+ scopeStyle: scopeView.scopeStyle
327
341
328 bottomItem: DashDepartments {
342 bottomItem: DashDepartments {
329 scope: scopeView.scope
343 scope: scopeView.scope
@@ -331,6 +345,7 @@ FocusScope {
331 anchors.right: parent.right
345 anchors.right: parent.right
332 windowHeight: scopeView.height
346 windowHeight: scopeView.height
333 windowWidth: scopeView.width
347 windowWidth: scopeView.width
348+ scopeStyle: scopeView.scopeStyle
334 }
349 }
335
350
336 onBackClicked: scopeView.backClicked()
351 onBackClicked: scopeView.backClicked()
@@ -342,6 +357,7 @@ FocusScope {
342 objectName: "previewListView"
357 objectName: "previewListView"
343 visible: x != width
358 visible: x != width
344 scope: scopeView.scope
359 scope: scopeView.scope
360+ scopeStyle: scopeView.scopeStyle
345 width: parent.width
361 width: parent.width
346 height: parent.height
362 height: parent.height
347 anchors.left: categoryView.right
363 anchors.left: categoryView.right
qml/Dash/PreviewListView.qml+3
@@ -24,6 +24,7 @@ Item {
24 id: root
24 id: root
25
25
26 property var scope: null
26 property var scope: null
27+ property var scopeStyle: null
27
28
28 property alias open: previewListView.open
29 property alias open: previewListView.open
29 property alias model: previewListView.model
30 property alias model: previewListView.model
@@ -38,6 +39,7 @@ Item {
38 title: scope ? scope.name : ""
39 title: scope ? scope.name : ""
39 showBackButton: true
40 showBackButton: true
40 searchEntryEnabled: false
41 searchEntryEnabled: false
42+ scopeStyle: root.scopeStyle
41
43
42 onBackClicked: root.open = false
44 onBackClicked: root.open = false
43 }
45 }
@@ -101,6 +103,7 @@ Item {
101 var previewStack = root.scope.preview(result);
103 var previewStack = root.scope.preview(result);
102 return previewStack.getPreviewModel(0);
104 return previewStack.getPreviewModel(0);
103 }
105 }
106+ scopeStyle: root.scopeStyle
104 }
107 }
105
108
106 MouseArea {
109 MouseArea {
qml/Dash/Previews/Preview.qml+4
@@ -36,6 +36,9 @@ Item {
36 //! \brief Should be set to true if this preview is currently displayed.
36 //! \brief Should be set to true if this preview is currently displayed.
37 property bool isCurrent: false
37 property bool isCurrent: false
38
38
39+ //! \brief The ScopeStyle component.
40+ property var scopeStyle: null
41+
39 clip: true
42 clip: true
40
43
41 Binding {
44 Binding {
@@ -77,6 +80,7 @@ Item {
77 widgetType: model.type
80 widgetType: model.type
78 widgetData: model.properties
81 widgetData: model.properties
79 isCurrentPreview: root.isCurrent
82 isCurrentPreview: root.isCurrent
83+ scopeStyle: root.scopeStyle
80 anchors {
84 anchors {
81 left: parent.left
85 left: parent.left
82 right: parent.right
86 right: parent.right
qml/Dash/Previews/PreviewAudioPlayback.qml+3−3
@@ -139,7 +139,7 @@ PreviewWidget {
139 objectName: "trackTitleLabel"
139 objectName: "trackTitleLabel"
140 anchors { top: parent.top; left: parent.left; right: parent.right }
140 anchors { top: parent.top; left: parent.left; right: parent.right }
141 opacity: 0.9
141 opacity: 0.9
142− color: "grey"//Theme.palette.selected.backgroundText // TODO karni: Use updated Palette.
142+ color: scopeStyle ? scopeStyle.foreground : "grey"
143 fontSize: "small"
143 fontSize: "small"
144 horizontalAlignment: Text.AlignLeft
144 horizontalAlignment: Text.AlignLeft
145 text: modelData["title"]
145 text: modelData["title"]
@@ -152,7 +152,7 @@ PreviewWidget {
152 anchors { top: trackTitleLabel.bottom; left: parent.left; right: parent.right }
152 anchors { top: trackTitleLabel.bottom; left: parent.left; right: parent.right }
153 visible: text !== ""
153 visible: text !== ""
154 opacity: 0.9
154 opacity: 0.9
155− color: "grey"//Theme.palette.selected.backgroundText // TODO karni: Use updated Palette.
155+ color: scopeStyle ? scopeStyle.foreground : "grey"
156 font.weight: Font.Light
156 font.weight: Font.Light
157 fontSize: "small"
157 fontSize: "small"
158 horizontalAlignment: Text.AlignLeft
158 horizontalAlignment: Text.AlignLeft
@@ -193,7 +193,7 @@ PreviewWidget {
193 anchors.verticalCenter: parent.verticalCenter
193 anchors.verticalCenter: parent.verticalCenter
194 width: parent.column3Width
194 width: parent.column3Width
195 opacity: 0.9
195 opacity: 0.9
196− color: "grey"//Theme.palette.selected.backgroundText // TODO karni: Use updated Palette.
196+ color: scopeStyle ? scopeStyle.foreground : "grey"
197 fontSize: "small"
197 fontSize: "small"
198 horizontalAlignment: Text.AlignRight
198 horizontalAlignment: Text.AlignRight
199 text: audio.lengthToString(modelData["length"])
199 text: audio.lengthToString(modelData["length"])
qml/Dash/Previews/PreviewHeader.qml+1−1
@@ -35,7 +35,7 @@ PreviewWidget {
35 readonly property url mascot: root.widgetData["mascot"] || ""
35 readonly property url mascot: root.widgetData["mascot"] || ""
36 readonly property string title: root.widgetData["title"] || ""
36 readonly property string title: root.widgetData["title"] || ""
37 readonly property string subtitle: root.widgetData["subtitle"] || ""
37 readonly property string subtitle: root.widgetData["subtitle"] || ""
38− readonly property color fontColor: "grey"
38+ readonly property color fontColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
39
39
40 implicitHeight: row.height + row.margins * 2
40 implicitHeight: row.height + row.margins * 2
41 width: parent.width
41 width: parent.width
qml/Dash/Previews/PreviewRatingDisplay.qml+2−4
@@ -71,8 +71,7 @@ PreviewWidget {
71 id: authorLabel
71 id: authorLabel
72 objectName: "authorLabel"
72 objectName: "authorLabel"
73 anchors { left: parent.left; right: parent.right }
73 anchors { left: parent.left; right: parent.right }
74− // TODO cimi: Yet another fix requiring Palette update.
74+ color: scopeStyle ? scopeStyle.foreground : "grey"
75− color: "grey" //Theme.palette.selected.backgroundText
76 opacity: .8
75 opacity: .8
77 text: modelData["author"] || ""
76 text: modelData["author"] || ""
78 visible: text !== ""
77 visible: text !== ""
@@ -83,8 +82,7 @@ PreviewWidget {
83 id: reviewLabel
82 id: reviewLabel
84 objectName: "reviewLabel"
83 objectName: "reviewLabel"
85 anchors { left: parent.left; right: parent.right }
84 anchors { left: parent.left; right: parent.right }
86− // TODO cimi: Yet another fix requiring Palette update.
85+ color: scopeStyle ? scopeStyle.foreground : "grey"
87− color: "grey" //Theme.palette.selected.backgroundText
88 opacity: .8
86 opacity: .8
89 text: modelData["review"] || ""
87 text: modelData["review"] || ""
90 visible: text !== ""
88 visible: text !== ""
qml/Dash/Previews/PreviewRatingInput.qml+2−4
@@ -76,8 +76,7 @@ PreviewWidget {
76 verticalCenter: parent.verticalCenter
76 verticalCenter: parent.verticalCenter
77 left: parent.left
77 left: parent.left
78 }
78 }
79− // TODO cimi: Yet another fix requiring Palette update.
79+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
80− color: "grey" //Theme.palette.selected.backgroundText
81 opacity: .8
80 opacity: .8
82 text: widgetData["rating-label"] || i18n.tr("Rate this")
81 text: widgetData["rating-label"] || i18n.tr("Rate this")
83 }
82 }
@@ -122,8 +121,7 @@ PreviewWidget {
122 left: parent.left
121 left: parent.left
123 right: parent.right
122 right: parent.right
124 }
123 }
125− // TODO cimi: Yet another fix requiring Palette update.
124+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
126− color: "grey" //Theme.palette.selected.backgroundText
127 opacity: .8
125 opacity: .8
128 text: widgetData["review-label"] || i18n.tr("Add a review")
126 text: widgetData["review-label"] || i18n.tr("Add a review")
129 }
127 }
qml/Dash/Previews/PreviewTextSummary.qml+2−4
@@ -39,8 +39,7 @@ PreviewWidget {
39 }
39 }
40 height: visible ? implicitHeight : 0
40 height: visible ? implicitHeight : 0
41 fontSize: "large"
41 fontSize: "large"
42− // TODO karni: Yet another fix requiring Palette update.
42+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
43− color: "grey" //Theme.palette.selected.backgroundText
44 visible: text !== ""
43 visible: text !== ""
45 opacity: .8
44 opacity: .8
46 text: widgetData["title"] || ""
45 text: widgetData["title"] || ""
@@ -62,8 +61,7 @@ PreviewWidget {
62 clip: true
61 clip: true
63 fontSize: "small"
62 fontSize: "small"
64 lineHeight: 1.2
63 lineHeight: 1.2
65− // TODO karni: Yet another fix requiring Palette update.
64+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
66− color: "grey" //Theme.palette.selected.backgroundText
67 opacity: .8
65 opacity: .8
68 text: widgetData["text"]
66 text: widgetData["text"]
69 wrapMode: Text.Wrap
67 wrapMode: Text.Wrap
qml/Dash/Previews/PreviewWidget.qml+3
@@ -28,6 +28,9 @@ Item {
28 //! Variable used to contain widget's data
28 //! Variable used to contain widget's data
29 property var widgetData
29 property var widgetData
30
30
31+ //! The ScopeStyle component.
32+ property var scopeStyle: null
33+
31 /*! \brief This signal should be emitted when a preview action was triggered.
34 /*! \brief This signal should be emitted when a preview action was triggered.
32 *
35 *
33 * \param widgetId, actionId Respective identifiers from widgetData.
36 * \param widgetId, actionId Respective identifiers from widgetData.
qml/Dash/Previews/PreviewWidgetFactory.qml+4
@@ -31,6 +31,9 @@ Loader {
31 //! Widget data, forwarded to the widget as is.
31 //! Widget data, forwarded to the widget as is.
32 property var widgetData: null
32 property var widgetData: null
33
33
34+ //! The ScopeStyle component.
35+ property var scopeStyle: null
36+
34 //! Set to true if the parent preview is displayed.
37 //! Set to true if the parent preview is displayed.
35 property bool isCurrentPreview: false
38 property bool isCurrentPreview: false
36
39
@@ -62,6 +65,7 @@ Loader {
62 item.widgetId = Qt.binding(function() { return root.widgetId } )
65 item.widgetId = Qt.binding(function() { return root.widgetId } )
63 item.widgetData = Qt.binding(function() { return root.widgetData } )
66 item.widgetData = Qt.binding(function() { return root.widgetData } )
64 item.isCurrentPreview = Qt.binding(function() { return root.isCurrentPreview } )
67 item.isCurrentPreview = Qt.binding(function() { return root.isCurrentPreview } )
68+ if (item.hasOwnProperty("scopeStyle")) item.scopeStyle = root.scopeStyle;
65 }
69 }
66
70
67 Connections {
71 Connections {
qml/Dash/graphics/tick@30.pngdeleted

Binary file not shown.

tests/mocks/Unity/fake_scope.cpp+12−1
@@ -14,6 +14,8 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17+#include <QUrl>
18+
17#include "fake_scope.h"
19#include "fake_scope.h"
18#include "fake_department.h"
20#include "fake_department.h"
19#include "fake_resultsmodel.h"
21#include "fake_resultsmodel.h"
@@ -180,7 +182,16 @@ bool Scope::hasDepartments() const
180
182
181QVariantMap Scope::customizations() const
183QVariantMap Scope::customizations() const
182{
184{
185+ QVariantMap m;
186+ if (m_id == "clickscope") {
187+ m["background-color"] = "red";
188+ m["foreground-color"] = "blue";
189+ } 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;
193+ }
183− return QVariantMap();
194+ return m;
184}
195}
185
196
186unity::shell::scopes::DepartmentInterface* Scope::getDepartment(const QString& id)
197unity::shell::scopes::DepartmentInterface* Scope::getDepartment(const QString& id)
tests/plugins/Dash/CMakeLists.txt+2
@@ -76,4 +76,6 @@ add_binary_qml_test(CardCreator "" "Dash-qml")
76# plain qml test
76# plain qml test
77set(qmltest_DEFAULT_TARGETS qmluitests)
77set(qmltest_DEFAULT_TARGETS qmluitests)
78set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
78set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
79+set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
80+add_qml_test(. ScopeStyle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
79add_qml_test(. ListViewWithPageHeaderQML IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
81add_qml_test(. ListViewWithPageHeaderQML IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
tests/plugins/Dash/cardcreator/1.res+3−2
@@ -5,7 +5,8 @@ AbstractButton {
5 property var cardData;
5 property var cardData;
6 property var artShapeBorderSource: undefined;
6 property var artShapeBorderSource: undefined;
7 property real fontScale: 1.0;
7 property real fontScale: 1.0;
8+ property var scopeStyle: null;
8− property int headerAlignment: Text.AlignLeft;
9+ property int headerAlignment: Text.AlignLeft;
9 property int fixedHeaderHeight: -1;
10 property int fixedHeaderHeight: -1;
10 property size fixedArtShapeSize: Qt.size(-1, -1);
11 property size fixedArtShapeSize: Qt.size(-1, -1);
11 readonly property string title: cardData && cardData["title"] || "";
12 readonly property string title: cardData && cardData["title"] || "";
@@ -75,7 +76,7 @@ leftMargin: units.gu(1);
75 wrapMode: Text.Wrap;
76 wrapMode: Text.Wrap;
76 maximumLineCount: 2;
77 maximumLineCount: 2;
77 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
78 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
78− color: "grey";
79+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
79 visible: showHeader ;
80 visible: showHeader ;
80 text: root.title;
81 text: root.title;
81 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
82 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
tests/plugins/Dash/cardcreator/2.res+5−5
@@ -5,7 +5,8 @@ AbstractButton {
5 property var cardData;
5 property var cardData;
6 property var artShapeBorderSource: undefined;
6 property var artShapeBorderSource: undefined;
7 property real fontScale: 1.0;
7 property real fontScale: 1.0;
8+ property var scopeStyle: null;
8− property int headerAlignment: Text.AlignLeft;
9+ property int headerAlignment: Text.AlignLeft;
9 property int fixedHeaderHeight: -1;
10 property int fixedHeaderHeight: -1;
10 property size fixedArtShapeSize: Qt.size(-1, -1);
11 property size fixedArtShapeSize: Qt.size(-1, -1);
11 readonly property string title: cardData && cardData["title"] || "";
12 readonly property string title: cardData && cardData["title"] || "";
@@ -78,8 +79,7 @@ Column {
78 anchors.verticalCenter: parent.verticalCenter;
79 anchors.verticalCenter: parent.verticalCenter;
79 spacing: units.dp(2);
80 spacing: units.dp(2);
80 width: parent.width - x;
81 width: parent.width - x;
81− data: [
82−Label {
82+ data: [ Label {
83 id: titleLabel;
83 id: titleLabel;
84 objectName: "titleLabel";
84 objectName: "titleLabel";
85 anchors { left: parent.left; right: parent.right }
85 anchors { left: parent.left; right: parent.right }
@@ -88,7 +88,7 @@ Label {
88 wrapMode: Text.Wrap;
88 wrapMode: Text.Wrap;
89 maximumLineCount: 2;
89 maximumLineCount: 2;
90 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
90 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
91− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : "grey";
91+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
92 visible: showHeader ;
92 visible: showHeader ;
93 text: root.title;
93 text: root.title;
94 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
94 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -103,7 +103,7 @@ Label {
103 elide: Text.ElideRight;
103 elide: Text.ElideRight;
104 fontSize: "small";
104 fontSize: "small";
105 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
105 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
106− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : "grey";
106+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
107 visible: titleLabel.visible && titleLabel.text;
107 visible: titleLabel.visible && titleLabel.text;
108 text: cardData && cardData["subtitle"] || "";
108 text: cardData && cardData["subtitle"] || "";
109 font.weight: Font.Light;
109 font.weight: Font.Light;
tests/plugins/Dash/cardcreator/3.res+6−4
@@ -5,7 +5,8 @@ AbstractButton {
5 property var cardData;
5 property var cardData;
6 property var artShapeBorderSource: undefined;
6 property var artShapeBorderSource: undefined;
7 property real fontScale: 1.0;
7 property real fontScale: 1.0;
8+ property var scopeStyle: null;
8− property int headerAlignment: Text.AlignLeft;
9+ property int headerAlignment: Text.AlignLeft;
9 property int fixedHeaderHeight: -1;
10 property int fixedHeaderHeight: -1;
10 property size fixedArtShapeSize: Qt.size(-1, -1);
11 property size fixedArtShapeSize: Qt.size(-1, -1);
11 readonly property string title: cardData && cardData["title"] || "";
12 readonly property string title: cardData && cardData["title"] || "";
@@ -75,7 +76,7 @@ leftMargin: units.gu(1);
75 wrapMode: Text.Wrap;
76 wrapMode: Text.Wrap;
76 maximumLineCount: 2;
77 maximumLineCount: 2;
77 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
78 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
78− color: "grey";
79+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
79 visible: showHeader ;
80 visible: showHeader ;
80 text: root.title;
81 text: root.title;
81 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
82 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -88,11 +89,12 @@ Label {
88 leftMargin: titleLabel.leftMargin;
89 leftMargin: titleLabel.leftMargin;
89 right: titleLabel.right;
90 right: titleLabel.right;
90 top: titleLabel.bottom;
91 top: titleLabel.bottom;
91− topMargin: units.dp(2); }
92+ topMargin: units.dp(2);
93+ }
92 elide: Text.ElideRight;
94 elide: Text.ElideRight;
93 fontSize: "small";
95 fontSize: "small";
94 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
96 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
95− color: "grey";
97+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
96 visible: titleLabel.visible && titleLabel.text;
98 visible: titleLabel.visible && titleLabel.text;
97 text: cardData && cardData["subtitle"] || "";
99 text: cardData && cardData["subtitle"] || "";
98 font.weight: Font.Light;
100 font.weight: Font.Light;
tests/plugins/Dash/cardcreator/4.res+4−3
@@ -5,7 +5,8 @@ AbstractButton {
5 property var cardData;
5 property var cardData;
6 property var artShapeBorderSource: undefined;
6 property var artShapeBorderSource: undefined;
7 property real fontScale: 1.0;
7 property real fontScale: 1.0;
8+ property var scopeStyle: null;
8− property int headerAlignment: Text.AlignLeft;
9+ property int headerAlignment: Text.AlignLeft;
9 property int fixedHeaderHeight: -1;
10 property int fixedHeaderHeight: -1;
10 property size fixedArtShapeSize: Qt.size(-1, -1);
11 property size fixedArtShapeSize: Qt.size(-1, -1);
11 readonly property string title: cardData && cardData["title"] || "";
12 readonly property string title: cardData && cardData["title"] || "";
@@ -68,7 +69,7 @@ data: [ Label {
68 wrapMode: Text.Wrap;
69 wrapMode: Text.Wrap;
69 maximumLineCount: 2;
70 maximumLineCount: 2;
70 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
71 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
71− color: "grey";
72+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
72 visible: showHeader ;
73 visible: showHeader ;
73 text: root.title;
74 text: root.title;
74 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
75 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -83,7 +84,7 @@ Label {
83 elide: Text.ElideRight;
84 elide: Text.ElideRight;
84 fontSize: "small";
85 fontSize: "small";
85 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
86 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
86− color: "grey";
87+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
87 visible: titleLabel.visible && titleLabel.text;
88 visible: titleLabel.visible && titleLabel.text;
88 text: cardData && cardData["subtitle"] || "";
89 text: cardData && cardData["subtitle"] || "";
89 font.weight: Font.Light;
90 font.weight: Font.Light;
tests/plugins/Dash/cardcreator/5.res+3−2
@@ -4,8 +4,9 @@ AbstractButton {
4 property var components;
4 property var components;
5 property var cardData;
5 property var cardData;
6 property var artShapeBorderSource: undefined;
6 property var artShapeBorderSource: undefined;
7− property real fontScale: 1.0;
7+ property real fontScale: 1.0;
8+ property var scopeStyle: null;
8− property int headerAlignment: Text.AlignLeft;
9+ property int headerAlignment: Text.AlignLeft;
9 property int fixedHeaderHeight: -1;
10 property int fixedHeaderHeight: -1;
10 property size fixedArtShapeSize: Qt.size(-1, -1);
11 property size fixedArtShapeSize: Qt.size(-1, -1);
11 readonly property string title: cardData && cardData["title"] || "";
12 readonly property string title: cardData && cardData["title"] || "";
tests/plugins/Dash/tst_ScopeStyle.qmlnew file+151
@@ -0,0 +1,151 @@
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 Dash 0.1
20+import Ubuntu.Components 1.1
21+
22+Rectangle {
23+ width: units.gu(40)
24+ height: units.gu(71)
25+
26+ ScopeStyle {
27+ id: tool
28+ }
29+
30+ TestCase {
31+ id: testCase
32+ name: "ScopeStyle"
33+ when: windowShown
34+
35+ property color color
36+ property var styles: [
37+ {},
38+ { "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" },
41+ ]
42+
43+ function cleanup() {
44+ testCase.color = "transparent";
45+ }
46+
47+ function test_luminance_data() {
48+ return [
49+ { tag: "#F00", luminance: 0.2126 },
50+ { tag: "#0F0", luminance: 0.7152 },
51+ { tag: "#00F", luminance: 0.0722 },
52+ { tag: "white", luminance: 1.0 },
53+ { tag: "black", luminance: 0.0 },
54+ { tag: "lightgrey", luminance: 0.8275 },
55+ { tag: "grey", luminance: 0.5020 },
56+ { tag: "darkgrey", luminance: 0.6627 },
57+ ];
58+ }
59+
60+ function test_luminance(data) {
61+ testCase.color = data.tag;
62+ compare(tool.luminance(testCase.color).toFixed(4), data.luminance.toFixed(4));
63+ }
64+
65+ function test_foreground_data() {
66+ return [
67+ { tag: "default", index: 0, foreground: "grey" },
68+ { tag: "red on black", index: 1, foreground: "red" },
69+ { tag: "green on white", index: 2, foreground: "green" },
70+ { tag: "blue on darkgrey", index: 3, foreground: "blue" },
71+ ];
72+ }
73+
74+ function test_foreground(data) {
75+ tool.style = testCase.styles[data.index];
76+ verify(Qt.colorEqual(tool.foreground, data.foreground),
77+ "Foreground color not equal: %1 != %2".arg(tool.foreground).arg(data.foreground));
78+ }
79+
80+ function test_background_data() {
81+ return [
82+ { tag: "default", index: 0, background: "transparent" },
83+ { tag: "red on black", index: 1, background: "black" },
84+ { tag: "green on white", index: 2, background: "white" },
85+ { tag: "blue on darkgrey", index: 3, background: "darkgrey" },
86+ ];
87+ }
88+
89+ function test_background(data) {
90+ tool.style = testCase.styles[data.index];
91+ verify(Qt.colorEqual(tool.background, data.background),
92+ "Background color not equal: %1 != %2".arg(tool.background).arg(data.background));
93+ }
94+
95+ function test_threshold_data() {
96+ return [
97+ { tag: "default", index: 0, threshold: 0.5020 },
98+ { tag: "red on black", index: 1, threshold: 0.1063 },
99+ { tag: "green on white", index: 2, threshold: 0.6795 },
100+ { tag: "blue on darkgrey", index: 3, threshold: 0.3675 },
101+ ];
102+ }
103+
104+ function test_threshold(data) {
105+ tool.style = testCase.styles[data.index];
106+ compare(tool.threshold.toFixed(4), data.threshold.toFixed(4), "Luminance threshold was incorrect.");
107+ }
108+
109+ function test_light_data() {
110+ return [
111+ { tag: "default", index: 0, light: "white" },
112+ { tag: "red on black", index: 1, light: "red" },
113+ { tag: "green on white", index: 2, light: "white" },
114+ { tag: "blue on darkgrey", index: 3, light: "darkgrey" },
115+ ];
116+ }
117+
118+ function test_light(data) {
119+ tool.style = testCase.styles[data.index];
120+ verify(Qt.colorEqual(tool.light, data.light),
121+ "Light color not equal: %1 != %2".arg(tool.light).arg(data.light));
122+ }
123+
124+ function test_dark_data() {
125+ return [
126+ { tag: "default", index: 0, dark: "grey" },
127+ { tag: "red on black", index: 1, dark: "black" },
128+ { tag: "green on white", index: 2, dark: "green" },
129+ { tag: "blue on darkgrey", index: 3, dark: "blue" },
130+ ];
131+ }
132+
133+ function test_dark(data) {
134+ tool.style = testCase.styles[data.index];
135+ verify(Qt.colorEqual(tool.dark, data.dark),
136+ "Dark color not equal: %1 != %2".arg(tool.dark).arg(data.dark));
137+ }
138+
139+ function test_headerLogo_data() {
140+ return [
141+ { tag: "default", index: 0, headerLogo: "" },
142+ { tag: "with logo", index: 1, headerLogo: "file:///foo/bar" },
143+ ];
144+ }
145+
146+ function test_headerLogo(data) {
147+ tool.style = testCase.styles[data.index];
148+ compare(tool.headerLogo, data.headerLogo, "Header logo was incorrect.");
149+ }
150+ }
151+}
tests/qmltests/Components/tst_PageHeader.qml+4−1
@@ -213,7 +213,10 @@ Item {
213
213
214 searchEntryEnabled: true
214 searchEntryEnabled: true
215 title: "%^$%^%^&%^&%^$%GHR%"
215 title: "%^$%^%^&%^&%^$%GHR%"
216+ scopeStyle: QtObject {
217+ readonly property color foreground: "grey"
216− imageSource: showImageCheckBox.checked ? titleImageSource : ""
218+ readonly property url headerLogo: showImageCheckBox.checked ? pageHeader.titleImageSource : ""
219+ }
217 showBackButton: showBackButtonCheckBox.checked
220 showBackButton: showBackButtonCheckBox.checked
218
221
219 property string titleImageSource: Qt.resolvedUrl("tst_PageHeader/logo-ubuntu-orange.svg")
222 property string titleImageSource: Qt.resolvedUrl("tst_PageHeader/logo-ubuntu-orange.svg")
tests/qmltests/Dash/tst_GenericScopeView.qml+9−4
@@ -37,10 +37,6 @@ Item {
37
37
38 Scopes {
38 Scopes {
39 id: scopes
39 id: scopes
40−
41− onLoadedChanged: {
42− genericScopeView.scope = scopes.getScope(2)
43− }
44 }
40 }
45
41
46 property Item applicationManager: Item {
42 property Item applicationManager: Item {
@@ -260,6 +256,15 @@ Item {
260 }
256 }
261 closePreview();
257 closePreview();
262 }
258 }
259+
260+ function test_haeder_logo() {
261+ genericScopeView.scope = scopes.getScope(3);
262+
263+ var image = findChild(genericScopeView, "titleImage");
264+ verify(image, "Could not find the title image");
265+ compare(image.source, Qt.resolvedUrl("../Components/tst_PageHeader/logo-ubuntu-orange.svg"), "Title image has the wrong source");
266+
267+ }
263 }
268 }
264 }
269 }
265}
270}