Merge lp:~cimi/unity8/card_touchdown_2 into lp:unity8

Proposed by Andrea Cimitan
Status: Superseded
Proposed branch: lp:~cimi/unity8/card_touchdown_2
Merge into: lp:unity8
Diff against target: 1524 lines (+807/-345)
17 files modified
plugins/Dash/CardAttributes.qml (+65/-0)
plugins/Dash/CardCreator.js (+96/-7)
plugins/Dash/qmldir (+1/-0)
qml/Dash/CardTool.qml (+27/-2)
tests/plugins/Dash/CMakeLists.txt (+1/-0)
tests/plugins/Dash/cardcreator/1.res (+59/-49)
tests/plugins/Dash/cardcreator/2.res (+100/-90)
tests/plugins/Dash/cardcreator/3.res (+85/-74)
tests/plugins/Dash/cardcreator/4.res (+8/-0)
tests/plugins/Dash/cardcreator/5.res (+127/-117)
tests/plugins/Dash/cardcreator/6.res (+8/-0)
tests/plugins/Dash/cardcreator/7.res (+136/-0)
tests/plugins/Dash/cardcreator/7.tst (+3/-0)
tests/plugins/Dash/cardcreatortest.cpp (+17/-2)
tests/plugins/Dash/tst_CardAttributes.qml (+54/-0)
tests/qmltests/Dash/CardHelpers.js (+5/-3)
tests/qmltests/Dash/tst_Card.qml (+15/-1)
To merge this branch: bzr merge lp:~cimi/unity8/card_touchdown_2
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Unity Team Pending
Review via email: mp+228312@code.launchpad.net

Commit message

Add touchdown effect to cards

Description of the change

Add touchdown

 * Are there any related MPs required for this MP to build/function as expected? Please list.
No
 * Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
 * Did you make sure that your branch does not contain spurious tags?
Yes
 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
 * If you changed the UI, has there been a design review?
Yes

To post a comment you must log in.
lp:~cimi/unity8/card_touchdown_2 updated
1082. By Andrea Cimitan

Better test for cardcreator, line by line

1083. By Andrea Cimitan

Removed commented code

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~cimi/unity8/card_touchdown_2 updated
1084. By Andrea Cimitan

[ Michael Terry ]
* Check user's pin/password using PAM, instead of a plaintext keyfile.
  New build dependency: libpam0g-dev for phone unlock with PAM (LP:
  #1234983)
[ Gerry Boland ]
[ Daniel d'Andrada ]
* Re-architecture unity8 to use the QtMirCompositor library so that
  the Qt scenegraph renderer is used as the Mir compositor, and
  application surfaces are added to the QML scene as items.

[ Michael Zanetti ]
* Port phone right-edge spread code to use QtCompositor
* Add right-edge spread animation for tablet
[ Ubuntu daily release ]
* New rebuild forced
[ CI bot ]
* Resync trunk
[ Michał Sawicz ]
* Fix the ap test for applications.
[ Albert Astals ]
* Use deleteLater instead of a direct delete We are seeing a crash in
  QQuickWindowPrivate::polishItems because LVWPH is deleting items to
  polish from it's updatePolish which means the set in
  QQuickWindowPrivate::polishItems may end up with some yet-to-
  process-but-now-deleted items. Switching to deleteLater fixes this

1085. By Andrea Cimitan

Merge attribute branch and add improved tests

1086. By Andrea Cimitan

Readd line

1087. By Andrea Cimitan

Indent

1088. By Andrea Cimitan

Tests code

1089. By Andrea Cimitan

Indent

1090. By Andrea Cimitan

Indent

1091. By Andrea Cimitan

[ Gerry Boland ]
* Fix the run.sh script - pretend to be running with qtmir and emit
  SIGSTOP at the right time
[ Ying-Chun Liu ]
* Implement Attribute UI. (LP: #1282460)
[ Albert Astals ]
* Hide search history popup as soon as you start typing As discussed
  with Mike and Saviq
* Compile with for scopes-v3 unity-api
* PageHeader: Unfocus search field when search entry is selected
* Show search field if the search query changes
* Test: Add a condition for art.height being > 0 means stuff has
  already been layouted a bit without it it can happen that we get 0
  for everything at startup and tests still pass
* Remove leftover in test of an old headerless implementation
[ Michael Zanetti ]
* Drop Recent apps category from Dash (LP: #1281092)
* update launcher count emblems to match new spec (LP: #1338984)
[ Bill Filler ]
* disable predictive text for dash search field (LP: #1340409)
[ CI bot ]
* Resync trunk
[ Antti Kaijanmäki ]
* DefaultIndicatorPage: use Loader status to determine the visible
  property. (LP: #1350555)

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'plugins/Dash/CardAttributes.qml'
2--- plugins/Dash/CardAttributes.qml 1970-01-01 00:00:00 +0000
3+++ plugins/Dash/CardAttributes.qml 2014-07-31 13:13:08 +0000
4@@ -0,0 +1,65 @@
5+/*
6+ * Copyright 2014 Canonical Ltd.
7+ *
8+ * This program is free software; you can redistribute it and/or modify
9+ * it under the terms of the GNU General Public License as published by
10+ * the Free Software Foundation; version 3.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ */
20+
21+import QtQuick 2.2
22+import QtQuick.Layouts 1.1
23+import Ubuntu.Components 1.1
24+import Ubuntu.Settings.Components 0.1
25+
26+GridLayout {
27+ id: grid
28+ anchors {
29+ left: parent.left;
30+ right: parent.right;
31+ }
32+ columns: 2 + repeater.count % 2
33+ property alias model: repeater.model
34+ property var color
35+
36+ Repeater {
37+ id: repeater
38+ delegate: Row {
39+ spacing: units.gu(0.5)
40+ readonly property int column: index % grid.columns;
41+ Layout.alignment: {
42+ if (column == 0) return Qt.AlignLeft;
43+ if (column == grid.columns - 1 || index == repeater.count - 1) return Qt.AlignRight;
44+ if (column == 1) return Qt.AlignHCenter;
45+ }
46+ Layout.columnSpan: index == repeater.count - 1 && grid.columns == 3 && column == 1 ? 2 : 1
47+ Layout.maximumWidth: Math.max(icon.width, label.x + label.implicitWidth)
48+ Layout.fillWidth: true
49+ StatusIcon {
50+ id: icon
51+ height: units.gu(2)
52+ sets: ["actions", "status", "apps"]
53+ source: "icon" in modelData ? modelData["icon"] : ""
54+ }
55+ Label {
56+ id: label
57+ width: parent.width - x
58+ anchors.verticalCenter: parent.verticalCenter
59+ text: "value" in modelData ? modelData["value"] : "";
60+ elide: Text.ElideRight
61+ maximumLineCount: 1
62+ font.weight: "style" in modelData && modelData["style"] == "highlighted" ? Font.DemiBold : Font.Light
63+ fontSize: "small"
64+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale)
65+ color: grid.color
66+ }
67+ }
68+ }
69+}
70
71=== modified file 'plugins/Dash/CardCreator.js'
72--- plugins/Dash/CardCreator.js 2014-07-09 19:44:44 +0000
73+++ plugins/Dash/CardCreator.js 2014-07-31 13:13:08 +0000
74@@ -193,6 +193,21 @@
75 ] \n\
76 }\n';
77
78+// multiple column version of kHeaderColumnCode.
79+function kHeaderColumnCodeGenerator() {
80+ var headerColumnCodeTemplate = 'Column { \n\
81+ anchors.verticalCenter: parent.verticalCenter; \n\
82+ spacing: units.dp(2); \n\
83+ width: parent.width - x;\n\
84+ data: [ \n\
85+ %1 \n\
86+ ]\n\
87+ }\n';
88+ var args = Array.prototype.slice.call(arguments);
89+ var code = headerColumnCodeTemplate.arg(args.join(',\n'));
90+ return code;
91+}
92+
93 // %1 is used as anchors of mascotShapeLoader
94 var kMascotShapeLoaderCode = 'Loader { \n\
95 id: mascotShapeLoader; \n\
96@@ -224,7 +239,7 @@
97 }\n';
98
99 // %1 is used as anchors of titleLabel
100-// %1 is used as color of titleLabel
101+// %2 is used as color of titleLabel
102 // %3 is used as extra condition for visible of titleLabel
103 var kTitleLabelCode = 'Label { \n\
104 id: titleLabel; \n\
105@@ -242,6 +257,16 @@
106 horizontalAlignment: root.headerAlignment; \n\
107 }\n';
108
109+// %1 is used as anchors of touchdown effect
110+var kTouchdownCode = 'UbuntuShape { \n\
111+ id: touchdown; \n\
112+ objectName: "touchdown"; \n\
113+ anchors { %1 } \n\
114+ visible: root.pressed; \n\
115+ radius: "medium"; \n\
116+ borderSource: "radius_pressed.sci" \n\
117+ }\n';
118+
119 // %1 is used as anchors of subtitleLabel
120 // %2 is used as color of subtitleLabel
121 var kSubtitleLabelCode = 'Label { \n\
122@@ -258,6 +283,15 @@
123 horizontalAlignment: root.headerAlignment; \n\
124 }\n';
125
126+// %1 is used as anchors of attributesRow
127+var kAttributesRowCode = 'CardAttributes { \n\
128+ id: attributesRow; \n\
129+ objectName: "attributesRow"; \n\
130+ anchors { %1 } \n\
131+ color: %2; \n\
132+ model: cardData["attributes"]; \n\
133+ }\n';
134+
135 // %1 is used as top anchor of summary
136 // %2 is used as topMargin anchor of summary
137 // %3 is used as color of summary
138@@ -308,6 +342,7 @@
139 var headerAsOverlay = hasArt && template && template["overlay"] === true && (hasTitle || hasMascot);
140 var hasSubtitle = hasTitle && components["subtitle"] || false;
141 var hasHeaderRow = hasMascot && hasTitle;
142+ var hasAttributes = hasTitle && components["attributes"] || false;
143
144 if (hasBackground) {
145 code += kBackgroundLoaderCode;
146@@ -377,6 +412,14 @@
147 code += 'readonly property int headerHeight: row.height;\n'
148 } else if (hasMascot) {
149 code += 'readonly property int headerHeight: mascotImage.height;\n'
150+ } else if (hasAttributes) {
151+ if (hasTitle && hasSubtitle) {
152+ code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + attributesRow.height + attributesRow.anchors.topMargin;\n'
153+ } else if (hasTitle) {
154+ code += 'readonly property int headerHeight: titleLabel.height + attributesRow.height + attributesRow.anchors.topMargin;\n'
155+ } else {
156+ code += 'readonly property int headerHeight: attributesRow.height;\n'
157+ }
158 } else if (hasSubtitle) {
159 code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;\n'
160 } else if (hasTitle) {
161@@ -425,10 +468,12 @@
162
163 var titleAnchors;
164 var subtitleAnchors;
165- if (hasMascot && hasSubtitle) {
166+ var attributesAnchors;
167+ if (hasMascot && (hasSubtitle || hasAttributes)) {
168 // Using row + column
169 titleAnchors = 'left: parent.left; right: parent.right';
170 subtitleAnchors = titleAnchors;
171+ attributesAnchors = subtitleAnchors;
172 } else if (hasMascot) {
173 // Using row + label
174 titleAnchors = 'verticalCenter: parent.verticalCenter;\n'
175@@ -438,11 +483,13 @@
176 titleAnchors = 'left: parent.left; \n\
177 leftMargin: units.gu(1); \n\
178 right: parent.right; \n\
179+ rightMargin: units.gu(1); \n\
180 top: overlayLoader.top; \n\
181 topMargin: units.gu(1);\n';
182 } else {
183 // Using anchors to the mascot/parent
184- titleAnchors = "right: parent.right;";
185+ titleAnchors = "right: parent.right;\n";
186+ titleAnchors += "rightMargin: units.gu(1);\n";
187 titleAnchors += headerLeftAnchor;
188 titleAnchors += headerVerticalAnchors;
189 if (!headerLeftAnchorHasMargin) {
190@@ -452,8 +499,19 @@
191 subtitleAnchors = 'left: titleLabel.left; \n\
192 leftMargin: titleLabel.leftMargin; \n\
193 right: titleLabel.right; \n\
194+ rightMargin: titleLabel.rightMargin; \n\
195 top: titleLabel.bottom; \n\
196 topMargin: units.dp(2);\n';
197+ if (hasSubtitle) {
198+ attributesAnchors = 'left: subtitleLabel.left; \n\
199+ leftMargin: subtitleLabel.leftMargin; \n\
200+ right: subtitleLabel.right; \n\
201+ rightMargin: subtitleLabel.rightMargin; \n\
202+ top: subtitleLabel.bottom; \n\
203+ topMargin: units.dp(2);\n';
204+ } else {
205+ attributesAnchors = subtitleAnchors;
206+ }
207 }
208
209 var titleLabelVisibleExtra = (headerAsOverlay ? '&& overlayLoader.active': '');
210@@ -463,11 +521,27 @@
211 subtitleCode += kSubtitleLabelCode.arg(subtitleAnchors).arg(color);
212 }
213
214- if (hasMascot && hasSubtitle) {
215+ if (hasMascot && (hasSubtitle || hasAttributes)) {
216 // If using row + column wrap the code in the column
217 titleSubtitleCode = kHeaderColumnCode.arg(titleCode).arg(subtitleCode);
218+ if (hasSubtitle && hasAttributes) {
219+ var attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(color);
220+ titleSubtitleCode = kHeaderColumnCodeGenerator(titleCode, subtitleCode, attributesCode);
221+ } else if (hasSubtitle) {
222+ titleSubtitleCode = kHeaderColumnCode.arg(titleCode).arg(subtitleCode);
223+ } else if (hasAttributes) {
224+ var attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(color);
225+ titleSubtitleCode = kHeaderColumnCode.arg(titleCode).arg(attributesCode);
226+ }
227 } else {
228- titleSubtitleCode = titleCode + subtitleCode;
229+ titleSubtitleCode = titleCode;
230+ if (hasSubtitle) {
231+ titleSubtitleCode = titleSubtitleCode + subtitleCode;
232+ }
233+ if (hasAttributes) {
234+ var attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(color);
235+ titleSubtitleCode = titleSubtitleCode + attributesCode;
236+ }
237 }
238 }
239
240@@ -487,6 +561,7 @@
241 else if (headerAsOverlay && hasArt) summaryTopAnchor = "artShapeHolder.bottom";
242 else if (hasHeaderRow) summaryTopAnchor = "row.bottom";
243 else if (hasMascot) summaryTopAnchor = "mascotImage.bottom";
244+ else if (hasAttributes) summaryTopAnchor = "attributesRow.bottom";
245 else if (hasSubtitle) summaryTopAnchor = "subtitleLabel.bottom";
246 else if (hasTitle) summaryTopAnchor = "titleLabel.bottom";
247 else if (hasArt) summaryTopAnchor = "artShapeHolder.bottom";
248@@ -499,17 +574,29 @@
249 color = 'root.scopeStyle ? root.scopeStyle.foreground : "grey"';
250 }
251
252- var summaryTopMargin = (hasMascot || hasSubtitle ? 'anchors.margins' : '0');
253+ var summaryTopMargin = (hasMascot || hasSubtitle || hasAttributes ? 'anchors.margins' : '0');
254
255 code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(color);
256 }
257
258+ var touchdownAnchors;
259+ if (hasBackground) {
260+ touchdownAnchors = 'fill: backgroundLoader';
261+ } else if (hasArt && !hasMascot && !hasSummary) {
262+ touchdownAnchors = 'fill: artShapeHolder';
263+ } else {
264+ touchdownAnchors = 'fill: root'
265+ }
266+ code += kTouchdownCode.arg(touchdownAnchors);
267+
268 if (hasSummary) {
269 code += 'implicitHeight: summary.y + summary.height + (summary.text ? units.gu(1) : 0);\n';
270 } else if (hasHeaderRow) {
271 code += 'implicitHeight: row.y + row.height + units.gu(1);\n';
272 } else if (hasMascot) {
273 code += 'implicitHeight: mascotImage.y + mascotImage.height;\n';
274+ } else if (hasAttributes) {
275+ code += 'implicitHeight: attributesRow.y + attributesRow.height + units.gu(1);\n';
276 } else if (hasSubtitle) {
277 code += 'implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
278 } else if (hasTitle) {
279@@ -526,8 +613,10 @@
280 function createCardComponent(parent, template, components) {
281 var imports = 'import QtQuick 2.2; \n\
282 import Ubuntu.Components 0.1; \n\
283- import Ubuntu.Thumbnailer 0.1;\n';
284+ import Ubuntu.Thumbnailer 0.1;\n\
285+ import Dash 0.1;\n';
286 var card = cardString(template, components);
287 var code = imports + 'Component {\n' + card + '}\n';
288+
289 return Qt.createQmlObject(code, parent, "createCardComponent");
290 }
291
292=== modified file 'plugins/Dash/qmldir'
293--- plugins/Dash/qmldir 2014-07-08 08:30:46 +0000
294+++ plugins/Dash/qmldir 2014-07-31 13:13:08 +0000
295@@ -3,3 +3,4 @@
296 typeinfo Dash.qmltypes
297 singleton CardCreatorCache 0.1 CardCreatorCache.qml
298 ScopeStyle 0.1 ScopeStyle.qml
299+CardAttributes 0.1 CardAttributes.qml
300\ No newline at end of file
301
302=== modified file 'qml/Dash/CardTool.qml'
303--- qml/Dash/CardTool.qml 2014-05-02 14:51:22 +0000
304+++ qml/Dash/CardTool.qml 2014-07-31 13:13:08 +0000
305@@ -165,15 +165,40 @@
306 }
307 }
308
309+ Item {
310+ id: attributesModel
311+ property int numOfAttributes: 0
312+ property var model: []
313+ property bool hasAttributes: {
314+ var attributes = components["attributes"];
315+ var hasAttributesFlag = (attributes != undefined) && attributes["field"];
316+
317+ if (hasAttributesFlag) {
318+ if (attributes["max-count"]) {
319+ numOfAttributes = attributes["max-count"];
320+ }
321+ }
322+ return hasAttributesFlag
323+ }
324+
325+ onNumOfAttributesChanged: {
326+ model = []
327+ for (var i = 0; i < numOfAttributes; i++) {
328+ model.push( {"value":"text"+(i+1), "icon":"image://theme/ok" } );
329+ }
330+ }
331+ }
332+
333 Loader {
334 id: cardLoader
335- property var fields: ["art", "mascot", "title", "subtitle", "summary"]
336+ property var fields: ["art", "mascot", "title", "subtitle", "summary", "attributes"]
337 property var maxData: {
338 "art": Qt.resolvedUrl("graphics/checkers.png"),
339 "mascot": Qt.resolvedUrl("graphics/checkers.png"),
340 "title": "—\n—",
341 "subtitle": "—",
342- "summary": "—\n—\n—\n—\n—"
343+ "summary": "—\n—\n—\n—\n—",
344+ "attributes": attributesModel.model
345 }
346 sourceComponent: cardTool.cardComponent
347 onLoaded: {
348
349=== modified file 'tests/plugins/Dash/CMakeLists.txt'
350--- tests/plugins/Dash/CMakeLists.txt 2014-07-08 08:35:20 +0000
351+++ tests/plugins/Dash/CMakeLists.txt 2014-07-31 13:13:08 +0000
352@@ -79,3 +79,4 @@
353 set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
354 add_qml_test(. ScopeStyle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
355 add_qml_test(. ListViewWithPageHeaderQML IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
356+add_qml_test(. CardAttributes IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
357
358=== modified file 'tests/plugins/Dash/cardcreator/1.res'
359--- tests/plugins/Dash/cardcreator/1.res 2014-07-08 12:37:34 +0000
360+++ tests/plugins/Dash/cardcreator/1.res 2014-07-31 13:13:08 +0000
361@@ -5,8 +5,8 @@
362 property var cardData;
363 property var artShapeBorderSource: undefined;
364 property real fontScale: 1.0;
365- property var scopeStyle: null;
366- property int headerAlignment: Text.AlignLeft;
367+ property var scopeStyle: null;
368+ property int headerAlignment: Text.AlignLeft;
369 property int fixedHeaderHeight: -1;
370 property size fixedArtShapeSize: Qt.size(-1, -1);
371 readonly property string title: cardData && cardData["title"] || "";
372@@ -16,57 +16,59 @@
373 onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
374 readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
375 Item {
376- id: artShapeHolder;
377- height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
378- width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
379- anchors { horizontalCenter: parent.horizontalCenter; }
380- Loader {
381- id: artShapeLoader;
382- objectName: "artShapeLoader";
383- active: cardData && cardData["art"] || false;
384- asynchronous: root.asynchronous;
385- visible: status == Loader.Ready;
386- sourceComponent: UbuntuShape {
387- id: artShape;
388- objectName: "artShape";
389- radius: "medium";
390- visible: image.status == Image.Ready;
391- readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
392- readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
393- readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
394- Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
395- onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
396- Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
397- function updateWidthHeightBindings() {
398- if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
399- width = root.fixedArtShapeSize.width;
400- height = root.fixedArtShapeSize.height;
401- } else if (aspectSmallerThanImageAspect) {
402- width = Qt.binding(function() { return !visible ? 0 : image.width });
403- height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
404- } else {
405- width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
406- height = Qt.binding(function() { return !visible ? 0 : image.height });
407+ id: artShapeHolder;
408+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
409+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
410+ anchors { horizontalCenter: parent.horizontalCenter; }
411+ Loader {
412+ id: artShapeLoader;
413+ objectName: "artShapeLoader";
414+ active: cardData && cardData["art"] || false;
415+ asynchronous: root.asynchronous;
416+ visible: status == Loader.Ready;
417+ sourceComponent: UbuntuShape {
418+ id: artShape;
419+ objectName: "artShape";
420+ radius: "medium";
421+ visible: image.status == Image.Ready;
422+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
423+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
424+ readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
425+ Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
426+ onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
427+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
428+ function updateWidthHeightBindings() {
429+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
430+ width = root.fixedArtShapeSize.width;
431+ height = root.fixedArtShapeSize.height;
432+ } else if (aspectSmallerThanImageAspect) {
433+ width = Qt.binding(function() { return !visible ? 0 : image.width });
434+ height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
435+ } else {
436+ width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
437+ height = Qt.binding(function() { return !visible ? 0 : image.height });
438+ }
439+ }
440+ image: Image {
441+ objectName: "artImage";
442+ source: cardData && cardData["art"] || "";
443+ cache: true;
444+ asynchronous: root.asynchronous;
445+ fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
446+ readonly property real aspect: implicitWidth / implicitHeight;
447+ width: root.width;
448+ height: width / artShape.aspect;
449+ }
450 }
451 }
452- image: Image {
453- objectName: "artImage";
454- source: cardData && cardData["art"] || "";
455- cache: true;
456- asynchronous: root.asynchronous;
457- fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
458- readonly property real aspect: implicitWidth / implicitHeight;
459- width: root.width;
460- height: width / artShape.aspect;
461- }
462- }
463- }
464- }
465+ }
466 readonly property int headerHeight: titleLabel.height;
467 Label {
468- id: titleLabel;
469- objectName: "titleLabel";
470- anchors { right: parent.right;left: parent.left;
471+ id: titleLabel;
472+ objectName: "titleLabel";
473+ anchors { right: parent.right;
474+rightMargin: units.gu(1);
475+left: parent.left;
476 top: artShapeHolder.bottom;
477 topMargin: units.gu(1);
478 leftMargin: units.gu(1);
479@@ -82,5 +84,13 @@
480 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
481 horizontalAlignment: root.headerAlignment;
482 }
483+UbuntuShape {
484+ id: touchdown;
485+ objectName: "touchdown";
486+ anchors { fill: artShapeHolder }
487+ visible: root.pressed;
488+ radius: "medium";
489+ borderSource: "radius_pressed.sci"
490+}
491 implicitHeight: titleLabel.y + titleLabel.height + units.gu(1);
492 }
493
494=== modified file 'tests/plugins/Dash/cardcreator/2.res'
495--- tests/plugins/Dash/cardcreator/2.res 2014-07-08 12:53:51 +0000
496+++ tests/plugins/Dash/cardcreator/2.res 2014-07-31 13:13:08 +0000
497@@ -5,8 +5,8 @@
498 property var cardData;
499 property var artShapeBorderSource: undefined;
500 property real fontScale: 1.0;
501- property var scopeStyle: null;
502- property int headerAlignment: Text.AlignLeft;
503+ property var scopeStyle: null;
504+ property int headerAlignment: Text.AlignLeft;
505 property int fixedHeaderHeight: -1;
506 property size fixedArtShapeSize: Qt.size(-1, -1);
507 readonly property string title: cardData && cardData["title"] || "";
508@@ -14,104 +14,114 @@
509 property bool showHeader: true;
510 implicitWidth: childrenRect.width;
511 Loader {
512- id: backgroundLoader;
513- objectName: "backgroundLoader";
514- anchors.fill: parent;
515- asynchronous: root.asynchronous;
516- visible: status == Loader.Ready;
517- sourceComponent: UbuntuShape {
518- objectName: "background";
519- radius: "medium";
520- color: getColor(0) || "white";
521- gradientColor: getColor(1) || color;
522- anchors.fill: parent;
523- image: backgroundImage.source ? backgroundImage : null;
524- property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
525- property Image backgroundImage: Image {
526- objectName: "backgroundImage";
527- source: {
528- if (cardData && typeof cardData["background"] === "string") return cardData["background"];
529- else if (template && typeof template["card-background"] === "string") return template["card-background"];
530- else return "";
531- }
532- }
533- function getColor(index) {
534- if (cardData && typeof cardData["background"] === "object"
535- && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
536- return cardData["background"]["elements"][index];
537- } else if (template && typeof template["card-background"] === "object"
538- && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
539- return template["card-background"]["elements"][index];
540- } else return undefined;
541- }
542- }
543- }
544+ id: backgroundLoader;
545+ objectName: "backgroundLoader";
546+ anchors.fill: parent;
547+ asynchronous: root.asynchronous;
548+ visible: status == Loader.Ready;
549+ sourceComponent: UbuntuShape {
550+ objectName: "background";
551+ radius: "medium";
552+ color: getColor(0) || "white";
553+ gradientColor: getColor(1) || color;
554+ anchors.fill: parent;
555+ image: backgroundImage.source ? backgroundImage : null;
556+ property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
557+ property Image backgroundImage: Image {
558+ objectName: "backgroundImage";
559+ source: {
560+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
561+ else if (template && typeof template["card-background"] === "string") return template["card-background"];
562+ else return "";
563+ }
564+ }
565+ function getColor(index) {
566+ if (cardData && typeof cardData["background"] === "object"
567+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
568+ return cardData["background"]["elements"][index];
569+ } else if (template && typeof template["card-background"] === "object"
570+ && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
571+ return template["card-background"]["elements"][index];
572+ } else return undefined;
573+ }
574+ }
575+ }
576 readonly property size artShapeSize: Qt.size(-1, -1);
577 readonly property int headerHeight: row.height;
578 Row {
579- id: row;
580- objectName: "outerRow";
581- property real margins: units.gu(1);
582- spacing: margins;
583- height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
584- anchors { top: parent.top;
585+ id: row;
586+ objectName: "outerRow";
587+ property real margins: units.gu(1);
588+ spacing: margins;
589+ height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
590+ anchors { top: parent.top;
591 topMargin: units.gu(1);
592- left: parent.left;
593-}
594- anchors.right: parent.right;
595- anchors.margins: margins;
596-data: [ Image {
597- id: mascotImage;
598- objectName: "mascotImage";
599- anchors { verticalCenter: parent.verticalCenter; }
600- readonly property int maxSize: Math.max(width, height) * 4;
601- source: cardData && cardData["mascot"];
602- width: units.gu(6);
603- height: units.gu(5.625);
604- sourceSize { width: maxSize; height: maxSize }
605- fillMode: Image.PreserveAspectCrop;
606- horizontalAlignment: Image.AlignHCenter;
607- verticalAlignment: Image.AlignVCenter;
608- visible: showHeader;
609- }
610-,
611-Column {
612- anchors.verticalCenter: parent.verticalCenter;
613- spacing: units.dp(2);
614- width: parent.width - x;
615- data: [ Label {
616- id: titleLabel;
617- objectName: "titleLabel";
618- anchors { left: parent.left; right: parent.right }
619- elide: Text.ElideRight;
620- fontSize: "small";
621- wrapMode: Text.Wrap;
622- maximumLineCount: 2;
623- font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
624- color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
625- visible: showHeader ;
626- text: root.title;
627- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
628- horizontalAlignment: root.headerAlignment;
629- }
630-,
631-Label {
632- id: subtitleLabel;
633- objectName: "subtitleLabel";
634- anchors { left: parent.left; right: parent.right }
635+left: parent.left;
636+ }
637+ anchors.right: parent.right;
638+ anchors.margins: margins;
639+ data: [ Image {
640+ id: mascotImage;
641+ objectName: "mascotImage";
642+ anchors { verticalCenter: parent.verticalCenter; }
643+ readonly property int maxSize: Math.max(width, height) * 4;
644+ source: cardData && cardData["mascot"];
645+ width: units.gu(6);
646+ height: units.gu(5.625);
647+ sourceSize { width: maxSize; height: maxSize }
648+ fillMode: Image.PreserveAspectCrop;
649+ horizontalAlignment: Image.AlignHCenter;
650+ verticalAlignment: Image.AlignVCenter;
651+ visible: showHeader;
652+ }
653
654+ ,
655+ Column {
656+ anchors.verticalCenter: parent.verticalCenter;
657+ spacing: units.dp(2);
658+ width: parent.width - x;
659+ data: [ Label {
660+ id: titleLabel;
661+ objectName: "titleLabel";
662+ anchors { left: parent.left; right: parent.right }
663 elide: Text.ElideRight;
664 fontSize: "small";
665+ wrapMode: Text.Wrap;
666+ maximumLineCount: 2;
667 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
668- color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
669- visible: titleLabel.visible && titleLabel.text;
670- text: cardData && cardData["subtitle"] || "";
671- font.weight: Font.Light;
672+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
673+ visible: showHeader ;
674+ text: root.title;
675+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
676 horizontalAlignment: root.headerAlignment;
677 }
678-]
679-}
680-]
681+ ,
682+ Label {
683+ id: subtitleLabel;
684+ objectName: "subtitleLabel";
685+ anchors { left: parent.left; right: parent.right }
686+ elide: Text.ElideRight;
687+ fontSize: "small";
688+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
689+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
690+ visible: titleLabel.visible && titleLabel.text;
691+ text: cardData && cardData["subtitle"] || "";
692+ font.weight: Font.Light;
693+ horizontalAlignment: root.headerAlignment;
694+ }
695+
696+ ]
697+ }
698+
699+ ]
700+ }
701+UbuntuShape {
702+ id: touchdown;
703+ objectName: "touchdown";
704+ anchors { fill: backgroundLoader }
705+ visible: root.pressed;
706+ radius: "medium";
707+ borderSource: "radius_pressed.sci"
708 }
709 implicitHeight: row.y + row.height + units.gu(1);
710 }
711
712=== modified file 'tests/plugins/Dash/cardcreator/3.res'
713--- tests/plugins/Dash/cardcreator/3.res 2014-07-08 12:37:34 +0000
714+++ tests/plugins/Dash/cardcreator/3.res 2014-07-31 13:13:08 +0000
715@@ -5,8 +5,8 @@
716 property var cardData;
717 property var artShapeBorderSource: undefined;
718 property real fontScale: 1.0;
719- property var scopeStyle: null;
720- property int headerAlignment: Text.AlignLeft;
721+ property var scopeStyle: null;
722+ property int headerAlignment: Text.AlignLeft;
723 property int fixedHeaderHeight: -1;
724 property size fixedArtShapeSize: Qt.size(-1, -1);
725 readonly property string title: cardData && cardData["title"] || "";
726@@ -16,89 +16,100 @@
727 onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
728 readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
729 Item {
730- id: artShapeHolder;
731- height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
732- width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
733- anchors { horizontalCenter: parent.horizontalCenter; }
734- Loader {
735- id: artShapeLoader;
736- objectName: "artShapeLoader";
737- active: cardData && cardData["art"] || false;
738- asynchronous: root.asynchronous;
739- visible: status == Loader.Ready;
740- sourceComponent: UbuntuShape {
741- id: artShape;
742- objectName: "artShape";
743- radius: "medium";
744- visible: image.status == Image.Ready;
745- readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
746- readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
747- readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
748- Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
749- onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
750- Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
751- function updateWidthHeightBindings() {
752- if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
753- width = root.fixedArtShapeSize.width;
754- height = root.fixedArtShapeSize.height;
755- } else if (aspectSmallerThanImageAspect) {
756- width = Qt.binding(function() { return !visible ? 0 : image.width });
757- height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
758- } else {
759- width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
760- height = Qt.binding(function() { return !visible ? 0 : image.height });
761- }
762- }
763- image: Image {
764- objectName: "artImage";
765- source: cardData && cardData["art"] || "";
766- cache: true;
767+ id: artShapeHolder;
768+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
769+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
770+ anchors { horizontalCenter: parent.horizontalCenter; }
771+ Loader {
772+ id: artShapeLoader;
773+ objectName: "artShapeLoader";
774+ active: cardData && cardData["art"] || false;
775 asynchronous: root.asynchronous;
776- fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
777- readonly property real aspect: implicitWidth / implicitHeight;
778- width: root.width;
779- height: width / artShape.aspect;
780+ visible: status == Loader.Ready;
781+ sourceComponent: UbuntuShape {
782+ id: artShape;
783+ objectName: "artShape";
784+ radius: "medium";
785+ visible: image.status == Image.Ready;
786+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
787+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
788+ readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
789+ Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
790+ onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
791+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
792+ function updateWidthHeightBindings() {
793+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
794+ width = root.fixedArtShapeSize.width;
795+ height = root.fixedArtShapeSize.height;
796+ } else if (aspectSmallerThanImageAspect) {
797+ width = Qt.binding(function() { return !visible ? 0 : image.width });
798+ height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
799+ } else {
800+ width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
801+ height = Qt.binding(function() { return !visible ? 0 : image.height });
802+ }
803+ }
804+ image: Image {
805+ objectName: "artImage";
806+ source: cardData && cardData["art"] || "";
807+ cache: true;
808+ asynchronous: root.asynchronous;
809+ fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
810+ readonly property real aspect: implicitWidth / implicitHeight;
811+ width: root.width;
812+ height: width / artShape.aspect;
813+ }
814+ }
815 }
816- }
817- }
818- }
819+ }
820 readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
821 Label {
822- id: titleLabel;
823- objectName: "titleLabel";
824- anchors { right: parent.right;left: parent.left;
825+ id: titleLabel;
826+ objectName: "titleLabel";
827+ anchors { right: parent.right;
828+rightMargin: units.gu(1);
829+left: parent.left;
830 top: artShapeHolder.bottom;
831 topMargin: units.gu(1);
832 leftMargin: units.gu(1);
833-}
834- elide: Text.ElideRight;
835- fontSize: "small";
836- wrapMode: Text.Wrap;
837- maximumLineCount: 2;
838- font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
839- color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
840- visible: showHeader ;
841- text: root.title;
842- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
843- horizontalAlignment: root.headerAlignment;
844- }
845-Label {
846- id: subtitleLabel;
847- objectName: "subtitleLabel";
848- anchors { left: titleLabel.left;
849- leftMargin: titleLabel.leftMargin;
850- right: titleLabel.right;
851- top: titleLabel.bottom;
852- topMargin: units.dp(2);
853- }
854+ }
855 elide: Text.ElideRight;
856 fontSize: "small";
857+ wrapMode: Text.Wrap;
858+ maximumLineCount: 2;
859 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
860- color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
861- visible: titleLabel.visible && titleLabel.text;
862- text: cardData && cardData["subtitle"] || "";
863- font.weight: Font.Light;
864+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
865+ visible: showHeader ;
866+ text: root.title;
867+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
868 horizontalAlignment: root.headerAlignment;
869 }
870+Label {
871+ id: subtitleLabel;
872+ objectName: "subtitleLabel";
873+ anchors { left: titleLabel.left;
874+ leftMargin: titleLabel.leftMargin;
875+ right: titleLabel.right;
876+ rightMargin: titleLabel.rightMargin;
877+ top: titleLabel.bottom;
878+ topMargin: units.dp(2);
879+ }
880+ elide: Text.ElideRight;
881+ fontSize: "small";
882+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
883+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
884+ visible: titleLabel.visible && titleLabel.text;
885+ text: cardData && cardData["subtitle"] || "";
886+ font.weight: Font.Light;
887+ horizontalAlignment: root.headerAlignment;
888+ }
889+UbuntuShape {
890+ id: touchdown;
891+ objectName: "touchdown";
892+ anchors { fill: artShapeHolder }
893+ visible: root.pressed;
894+ radius: "medium";
895+ borderSource: "radius_pressed.sci"
896+}
897 implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
898 }
899
900=== modified file 'tests/plugins/Dash/cardcreator/4.res'
901--- tests/plugins/Dash/cardcreator/4.res 2014-07-08 12:37:34 +0000
902+++ tests/plugins/Dash/cardcreator/4.res 2014-07-31 13:13:08 +0000
903@@ -94,5 +94,13 @@
904 }
905 ]
906 }
907+UbuntuShape {
908+ id: touchdown;
909+ objectName: "touchdown";
910+ anchors { fill: root }
911+ visible: root.pressed;
912+ radius: "medium";
913+ borderSource: "radius_pressed.sci"
914+}
915 implicitHeight: row.y + row.height + units.gu(1);
916 }
917
918=== modified file 'tests/plugins/Dash/cardcreator/5.res'
919--- tests/plugins/Dash/cardcreator/5.res 2014-07-08 12:37:34 +0000
920+++ tests/plugins/Dash/cardcreator/5.res 2014-07-31 13:13:08 +0000
921@@ -4,9 +4,9 @@
922 property var components;
923 property var cardData;
924 property var artShapeBorderSource: undefined;
925- property real fontScale: 1.0;
926- property var scopeStyle: null;
927- property int headerAlignment: Text.AlignLeft;
928+ property real fontScale: 1.0;
929+ property var scopeStyle: null;
930+ property int headerAlignment: Text.AlignLeft;
931 property int fixedHeaderHeight: -1;
932 property size fixedArtShapeSize: Qt.size(-1, -1);
933 readonly property string title: cardData && cardData["title"] || "";
934@@ -16,130 +16,140 @@
935 onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
936 readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
937 Item {
938- id: artShapeHolder;
939- height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
940- width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
941- anchors { horizontalCenter: parent.horizontalCenter; }
942- Loader {
943- id: artShapeLoader;
944- objectName: "artShapeLoader";
945- active: cardData && cardData["art"] || false;
946- asynchronous: root.asynchronous;
947- visible: status == Loader.Ready;
948- sourceComponent: UbuntuShape {
949- id: artShape;
950- objectName: "artShape";
951- radius: "medium";
952- visible: image.status == Image.Ready;
953- readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
954- readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
955- readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
956- Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
957- onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
958- Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
959- function updateWidthHeightBindings() {
960- if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
961- width = root.fixedArtShapeSize.width;
962- height = root.fixedArtShapeSize.height;
963- } else if (aspectSmallerThanImageAspect) {
964- width = Qt.binding(function() { return !visible ? 0 : image.width });
965- height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
966- } else {
967- width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
968- height = Qt.binding(function() { return !visible ? 0 : image.height });
969- }
970- }
971- image: Image {
972- objectName: "artImage";
973- source: cardData && cardData["art"] || "";
974- cache: true;
975+ id: artShapeHolder;
976+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
977+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
978+ anchors { horizontalCenter: parent.horizontalCenter; }
979+ Loader {
980+ id: artShapeLoader;
981+ objectName: "artShapeLoader";
982+ active: cardData && cardData["art"] || false;
983 asynchronous: root.asynchronous;
984- fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
985- readonly property real aspect: implicitWidth / implicitHeight;
986- width: root.width;
987- height: width / artShape.aspect;
988+ visible: status == Loader.Ready;
989+ sourceComponent: UbuntuShape {
990+ id: artShape;
991+ objectName: "artShape";
992+ radius: "medium";
993+ visible: image.status == Image.Ready;
994+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
995+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
996+ readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
997+ Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
998+ onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
999+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
1000+ function updateWidthHeightBindings() {
1001+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
1002+ width = root.fixedArtShapeSize.width;
1003+ height = root.fixedArtShapeSize.height;
1004+ } else if (aspectSmallerThanImageAspect) {
1005+ width = Qt.binding(function() { return !visible ? 0 : image.width });
1006+ height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
1007+ } else {
1008+ width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
1009+ height = Qt.binding(function() { return !visible ? 0 : image.height });
1010+ }
1011+ }
1012+ image: Image {
1013+ objectName: "artImage";
1014+ source: cardData && cardData["art"] || "";
1015+ cache: true;
1016+ asynchronous: root.asynchronous;
1017+ fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
1018+ readonly property real aspect: implicitWidth / implicitHeight;
1019+ width: root.width;
1020+ height: width / artShape.aspect;
1021+ }
1022+ }
1023 }
1024- }
1025- }
1026- }
1027+ }
1028 Loader {
1029- id: overlayLoader;
1030- anchors {
1031- left: artShapeHolder.left;
1032- right: artShapeHolder.right;
1033- bottom: artShapeHolder.bottom;
1034- }
1035- active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false;
1036- asynchronous: root.asynchronous;
1037- visible: showHeader && status == Loader.Ready;
1038- sourceComponent: ShaderEffect {
1039- id: overlay;
1040- height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
1041- opacity: 0.6;
1042- property var source: ShaderEffectSource {
1043- id: shaderSource;
1044- sourceItem: artShapeLoader.item;
1045- onVisibleChanged: if (visible) scheduleUpdate();
1046- live: false;
1047- sourceRect: Qt.rect(0, artShapeLoader.height - overlay.height, artShapeLoader.width, overlay.height);
1048- }
1049- vertexShader: "
1050- uniform highp mat4 qt_Matrix;
1051- attribute highp vec4 qt_Vertex;
1052- attribute highp vec2 qt_MultiTexCoord0;
1053- varying highp vec2 coord;
1054- void main() {
1055- coord = qt_MultiTexCoord0;
1056- gl_Position = qt_Matrix * qt_Vertex;
1057- }";
1058- fragmentShader: "
1059- varying highp vec2 coord;
1060- uniform sampler2D source;
1061- uniform lowp float qt_Opacity;
1062- void main() {
1063- lowp vec4 tex = texture2D(source, coord);
1064- gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
1065- }";
1066- }
1067- }
1068+ id: overlayLoader;
1069+ anchors {
1070+ left: artShapeHolder.left;
1071+ right: artShapeHolder.right;
1072+ bottom: artShapeHolder.bottom;
1073+ }
1074+ active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false;
1075+ asynchronous: root.asynchronous;
1076+ visible: showHeader && status == Loader.Ready;
1077+ sourceComponent: ShaderEffect {
1078+ id: overlay;
1079+ height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
1080+ opacity: 0.6;
1081+ property var source: ShaderEffectSource {
1082+ id: shaderSource;
1083+ sourceItem: artShapeLoader.item;
1084+ onVisibleChanged: if (visible) scheduleUpdate();
1085+ live: false;
1086+ sourceRect: Qt.rect(0, artShapeLoader.height - overlay.height, artShapeLoader.width, overlay.height);
1087+ }
1088+ vertexShader: "
1089+ uniform highp mat4 qt_Matrix;
1090+ attribute highp vec4 qt_Vertex;
1091+ attribute highp vec2 qt_MultiTexCoord0;
1092+ varying highp vec2 coord;
1093+ void main() {
1094+ coord = qt_MultiTexCoord0;
1095+ gl_Position = qt_Matrix * qt_Vertex;
1096+ }";
1097+ fragmentShader: "
1098+ varying highp vec2 coord;
1099+ uniform sampler2D source;
1100+ uniform lowp float qt_Opacity;
1101+ void main() {
1102+ lowp vec4 tex = texture2D(source, coord);
1103+ gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
1104+ }";
1105+ }
1106+ }
1107 readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
1108 Label {
1109- id: titleLabel;
1110- objectName: "titleLabel";
1111- anchors { left: parent.left;
1112- leftMargin: units.gu(1);
1113- right: parent.right;
1114- top: overlayLoader.top;
1115- topMargin: units.gu(1);
1116-}
1117- elide: Text.ElideRight;
1118- fontSize: "small";
1119- wrapMode: Text.Wrap;
1120- maximumLineCount: 2;
1121- font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1122- color: "white";
1123- visible: showHeader && overlayLoader.active;
1124- text: root.title;
1125- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
1126- horizontalAlignment: root.headerAlignment;
1127- }
1128-Label {
1129- id: subtitleLabel;
1130- objectName: "subtitleLabel";
1131- anchors { left: titleLabel.left;
1132- leftMargin: titleLabel.leftMargin;
1133- right: titleLabel.right;
1134- top: titleLabel.bottom;
1135- topMargin: units.dp(2);
1136- }
1137+ id: titleLabel;
1138+ objectName: "titleLabel";
1139+ anchors { left: parent.left;
1140+ leftMargin: units.gu(1);
1141+ right: parent.right;
1142+ rightMargin: units.gu(1);
1143+ top: overlayLoader.top;
1144+ topMargin: units.gu(1);
1145+ }
1146 elide: Text.ElideRight;
1147 fontSize: "small";
1148+ wrapMode: Text.Wrap;
1149+ maximumLineCount: 2;
1150 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1151 color: "white";
1152- visible: titleLabel.visible && titleLabel.text;
1153- text: cardData && cardData["subtitle"] || "";
1154- font.weight: Font.Light;
1155+ visible: showHeader && overlayLoader.active;
1156+ text: root.title;
1157+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
1158 horizontalAlignment: root.headerAlignment;
1159 }
1160+Label {
1161+ id: subtitleLabel;
1162+ objectName: "subtitleLabel";
1163+ anchors { left: titleLabel.left;
1164+ leftMargin: titleLabel.leftMargin;
1165+ right: titleLabel.right;
1166+ rightMargin: titleLabel.rightMargin;
1167+ top: titleLabel.bottom;
1168+ topMargin: units.dp(2);
1169+ }
1170+ elide: Text.ElideRight;
1171+ fontSize: "small";
1172+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1173+ color: "white";
1174+ visible: titleLabel.visible && titleLabel.text;
1175+ text: cardData && cardData["subtitle"] || "";
1176+ font.weight: Font.Light;
1177+ horizontalAlignment: root.headerAlignment;
1178+ }
1179+UbuntuShape {
1180+ id: touchdown;
1181+ objectName: "touchdown";
1182+ anchors { fill: artShapeHolder }
1183+ visible: root.pressed;
1184+ radius: "medium";
1185+ borderSource: "radius_pressed.sci"
1186+}
1187 implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
1188 }
1189
1190=== modified file 'tests/plugins/Dash/cardcreator/6.res'
1191--- tests/plugins/Dash/cardcreator/6.res 2014-07-10 18:03:16 +0000
1192+++ tests/plugins/Dash/cardcreator/6.res 2014-07-31 13:13:08 +0000
1193@@ -63,5 +63,13 @@
1194 }
1195 }
1196 readonly property int headerHeight: 0;
1197+UbuntuShape {
1198+ id: touchdown;
1199+ objectName: "touchdown";
1200+ anchors { fill: artShapeHolder }
1201+ visible: root.pressed;
1202+ radius: "medium";
1203+ borderSource: "radius_pressed.sci"
1204+}
1205 implicitHeight: artShapeHolder.height;
1206 }
1207
1208=== added file 'tests/plugins/Dash/cardcreator/7.res'
1209--- tests/plugins/Dash/cardcreator/7.res 1970-01-01 00:00:00 +0000
1210+++ tests/plugins/Dash/cardcreator/7.res 2014-07-31 13:13:08 +0000
1211@@ -0,0 +1,136 @@
1212+AbstractButton {
1213+ id: root;
1214+ property var template;
1215+ property var components;
1216+ property var cardData;
1217+ property var artShapeBorderSource: undefined;
1218+ property real fontScale: 1.0;
1219+ property var scopeStyle: null;
1220+ property int headerAlignment: Text.AlignLeft;
1221+ property int fixedHeaderHeight: -1;
1222+ property size fixedArtShapeSize: Qt.size(-1, -1);
1223+ readonly property string title: cardData && cardData["title"] || "";
1224+ property bool asynchronous: true;
1225+ property bool showHeader: true;
1226+ implicitWidth: childrenRect.width;
1227+Loader {
1228+ id: backgroundLoader;
1229+ objectName: "backgroundLoader";
1230+ anchors.fill: parent;
1231+ asynchronous: root.asynchronous;
1232+ visible: status == Loader.Ready;
1233+ sourceComponent: UbuntuShape {
1234+ objectName: "background";
1235+ radius: "medium";
1236+ color: getColor(0) || "white";
1237+ gradientColor: getColor(1) || color;
1238+ anchors.fill: parent;
1239+ image: backgroundImage.source ? backgroundImage : null;
1240+ property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
1241+ property Image backgroundImage: Image {
1242+ objectName: "backgroundImage";
1243+ source: {
1244+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
1245+ else if (template && typeof template["card-background"] === "string") return template["card-background"];
1246+ else return "";
1247+ }
1248+ }
1249+ function getColor(index) {
1250+ if (cardData && typeof cardData["background"] === "object"
1251+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
1252+ return cardData["background"]["elements"][index];
1253+ } else if (template && typeof template["card-background"] === "object"
1254+ && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
1255+ return template["card-background"]["elements"][index];
1256+ } else return undefined;
1257+ }
1258+ }
1259+ }
1260+readonly property size artShapeSize: Qt.size(-1, -1);
1261+readonly property int headerHeight: row.height;
1262+Row {
1263+ id: row;
1264+ objectName: "outerRow";
1265+ property real margins: units.gu(1);
1266+ spacing: margins;
1267+ height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
1268+ anchors { top: parent.top;
1269+ topMargin: units.gu(1);
1270+left: parent.left;
1271+ }
1272+ anchors.right: parent.right;
1273+ anchors.margins: margins;
1274+ data: [ Image {
1275+ id: mascotImage;
1276+ objectName: "mascotImage";
1277+ anchors { verticalCenter: parent.verticalCenter; }
1278+ readonly property int maxSize: Math.max(width, height) * 4;
1279+ source: cardData && cardData["mascot"];
1280+ width: units.gu(6);
1281+ height: units.gu(5.625);
1282+ sourceSize { width: maxSize; height: maxSize }
1283+ fillMode: Image.PreserveAspectCrop;
1284+ horizontalAlignment: Image.AlignHCenter;
1285+ verticalAlignment: Image.AlignVCenter;
1286+ visible: showHeader;
1287+ }
1288+
1289+ ,
1290+ Column {
1291+ anchors.verticalCenter: parent.verticalCenter;
1292+ spacing: units.dp(2);
1293+ width: parent.width - x;
1294+ data: [
1295+ Label {
1296+ id: titleLabel;
1297+ objectName: "titleLabel";
1298+ anchors { left: parent.left; right: parent.right }
1299+ elide: Text.ElideRight;
1300+ fontSize: "small";
1301+ wrapMode: Text.Wrap;
1302+ maximumLineCount: 2;
1303+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1304+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
1305+ visible: showHeader ;
1306+ text: root.title;
1307+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
1308+ horizontalAlignment: root.headerAlignment;
1309+ }
1310+,
1311+Label {
1312+ id: subtitleLabel;
1313+ objectName: "subtitleLabel";
1314+ anchors { left: parent.left; right: parent.right }
1315+ elide: Text.ElideRight;
1316+ fontSize: "small";
1317+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1318+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
1319+ visible: titleLabel.visible && titleLabel.text;
1320+ text: cardData && cardData["subtitle"] || "";
1321+ font.weight: Font.Light;
1322+ horizontalAlignment: root.headerAlignment;
1323+ }
1324+,
1325+CardAttributes {
1326+ id: attributesRow;
1327+ objectName: "attributesRow";
1328+ anchors { left: parent.left; right: parent.right }
1329+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
1330+ model: cardData["attributes"];
1331+ }
1332+
1333+ ]
1334+ }
1335+
1336+ ]
1337+ }
1338+UbuntuShape {
1339+ id: touchdown;
1340+ objectName: "touchdown";
1341+ anchors { fill: backgroundLoader }
1342+ visible: root.pressed;
1343+ radius: "medium";
1344+ borderSource: "radius_pressed.sci"
1345+ }
1346+implicitHeight: row.y + row.height + units.gu(1);
1347+}
1348
1349=== added file 'tests/plugins/Dash/cardcreator/7.tst'
1350--- tests/plugins/Dash/cardcreator/7.tst 1970-01-01 00:00:00 +0000
1351+++ tests/plugins/Dash/cardcreator/7.tst 2014-07-31 13:13:08 +0000
1352@@ -0,0 +1,3 @@
1353+template: {"card-background":{"elements":["#E9E9E9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
1354+components: {"art":{"aspect-ratio":1,"fill-mode":"crop"},"background":{"field":"background"},"mascot":{"field":"icon"},"subtitle":{"field":"author"},"title":{"field":"title"},"attributes":{"field":"attributes","max-count":2}}
1355+result: 7.res
1356
1357=== modified file 'tests/plugins/Dash/cardcreatortest.cpp'
1358--- tests/plugins/Dash/cardcreatortest.cpp 2014-05-06 13:09:08 +0000
1359+++ tests/plugins/Dash/cardcreatortest.cpp 2014-07-31 13:13:08 +0000
1360@@ -19,6 +19,8 @@
1361 #include <QQuickItem>
1362 #include <QQuickView>
1363 #include <QtTestGui>
1364+#include <QDebug>
1365+#include <QTemporaryFile>
1366
1367 class CardCreatorTest : public QObject
1368 {
1369@@ -73,8 +75,21 @@
1370 QFile testResultFile(testDirPath + resultFileName);
1371 QVERIFY(testResultFile.open(QIODevice::ReadOnly));
1372 QTextStream ts2(&testResultFile);
1373- const QString expectedResult = ts2.readAll();
1374- QCOMPARE(cardStringResult.toString().simplified(), expectedResult.simplified());
1375+
1376+ // Record failed results to /tmp
1377+ const QString executedResult = cardStringResult.toString();
1378+ QTemporaryFile tmpFile(QDir::tempPath() + QDir::separator() + "testCardCreatorFailedResultXXXXXX");
1379+ tmpFile.open();
1380+ tmpFile.setAutoRemove(false);
1381+ tmpFile.write(executedResult.toUtf8().constData());
1382+
1383+ const QStringList expectedLines = ts2.readAll().trimmed().replace(QRegExp("\n\\s*\n"),"\n").split("\n");
1384+ const QStringList cardStringResultLines = cardStringResult.toString().trimmed().replace(QRegExp("\n\\s*\n"),"\n").split("\n");
1385+ for (int i = 0; i < expectedLines.size(); ++i) {
1386+ QCOMPARE(cardStringResultLines[i].simplified(), expectedLines[i].simplified());
1387+ }
1388+
1389+ tmpFile.setAutoRemove(true); // Remove the result if it passed
1390
1391 QVariant createCardComponentResult;
1392 QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON));
1393
1394=== added file 'tests/plugins/Dash/tst_CardAttributes.qml'
1395--- tests/plugins/Dash/tst_CardAttributes.qml 1970-01-01 00:00:00 +0000
1396+++ tests/plugins/Dash/tst_CardAttributes.qml 2014-07-31 13:13:08 +0000
1397@@ -0,0 +1,54 @@
1398+/*
1399+ * Copyright 2013 Canonical Ltd.
1400+ *
1401+ * This program is free software; you can redistribute it and/or modify
1402+ * it under the terms of the GNU General Public License as published by
1403+ * the Free Software Foundation; version 3.
1404+ *
1405+ * This program is distributed in the hope that it will be useful,
1406+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1407+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1408+ * GNU General Public License for more details.
1409+ *
1410+ * You should have received a copy of the GNU General Public License
1411+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1412+ */
1413+
1414+import QtQuick 2.0
1415+import QtTest 1.0
1416+import Dash 0.1
1417+
1418+Item {
1419+ width: units.gu(40)
1420+ height: units.gu(4.5)
1421+
1422+ property var testData: [
1423+ [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"}],
1424+ [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3"}],
1425+ [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3"},{"value":"text4"}],
1426+ [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3","style":"highlighted"},{"value":"text4","icon":"image://theme/close","style":"highlighted"},{"value":"text5"}]
1427+ ]
1428+
1429+ CardAttributes {
1430+ id: cardAttributes
1431+ model: testData[3]
1432+ clip: true
1433+ }
1434+
1435+ TestCase {
1436+ name: "CardAttributesTest"
1437+ when: windowShown
1438+
1439+ function init() {
1440+ }
1441+
1442+ function test_columns_data() {
1443+ return testData;
1444+ }
1445+
1446+ function test_columns(data) {
1447+ cardAttributes.model = data;
1448+ compare(cardAttributes.columns, 2 + data.length % 2);
1449+ }
1450+ }
1451+}
1452
1453=== modified file 'tests/qmltests/Dash/CardHelpers.js'
1454--- tests/qmltests/Dash/CardHelpers.js 2014-02-04 18:14:07 +0000
1455+++ tests/qmltests/Dash/CardHelpers.js 2014-07-31 13:13:08 +0000
1456@@ -16,7 +16,7 @@
1457
1458 .pragma library
1459
1460-var components = ["title", "art", "subtitle", "mascot", "emblem", "old-price", "price", "alt-price", "rating", "alt-rating", "summary"]
1461+var components = ["title", "art", "subtitle", "mascot", "emblem", "old-price", "price", "alt-price", "rating", "alt-rating", "summary", "attributes"]
1462
1463 var defaultLayout = ' \
1464 { \
1465@@ -48,7 +48,8 @@
1466 "empty": "image://theme/rating-star-empty" \
1467 }, \
1468 "alt-rating": null, \
1469- "summary": null \
1470+ "summary": null, \
1471+ "attributes": { "max-count": 2 } \
1472 }, \
1473 "resources": {} \
1474 }'
1475@@ -59,7 +60,8 @@
1476 "art": "art", \
1477 "subtitle": "subtitle", \
1478 "mascot": "mascot", \
1479- "summary": "summary" \
1480+ "summary": "summary", \
1481+ "attributes": "attributes" \
1482 }'
1483
1484
1485
1486=== modified file 'tests/qmltests/Dash/tst_Card.qml'
1487--- tests/qmltests/Dash/tst_Card.qml 2014-06-27 08:47:04 +0000
1488+++ tests/qmltests/Dash/tst_Card.qml 2014-07-31 13:13:08 +0000
1489@@ -33,7 +33,8 @@
1490 "mascot": "../../../tests/qmltests/Dash/artwork/avatar.png",
1491 "title": "foo",
1492 "subtitle": "bar",
1493- "summary": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
1494+ "summary": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
1495+ "attributes": [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"}]
1496 }'
1497
1498 property var cardsModel: [
1499@@ -110,6 +111,7 @@
1500 anchors { top: parent.top; left: parent.left; margins: units.gu(1) }
1501
1502 sourceComponent: cardTool.cardComponent
1503+ clip: true
1504 onLoaded: {
1505 item.template = Qt.binding(function() { return cardTool.template; });
1506 item.components = Qt.binding(function() { return cardTool.components; });
1507@@ -473,5 +475,17 @@
1508 compare(shape !== null, data.shape);
1509 tryCompare(mascotImage, "visible", !data.shape);
1510 }
1511+
1512+ function test_touchdown_visibility() {
1513+ selector.selectedIndex = 0;
1514+
1515+ var touchdown = findChild(card, "touchdown");
1516+
1517+ compare(touchdown.visible, false);
1518+ mousePress(card, card.width/2, card.height/2);
1519+ compare(touchdown.visible, true);
1520+ mouseRelease(card, card.width/2, card.height/2);
1521+ compare(touchdown.visible, false);
1522+ }
1523 }
1524 }

Subscribers

People subscribed via source and target branches