@@ -142,10 +142,9 @@ var kOverlayLoaderCode = 'Loader { \n\
145−// %1 is used as anchors of row
145+// multiple row version of HeaderRowCode
146−// %2 is used as first child of the row
146+function kHeaderRowCodeGenerator() {
147−// %3 is used as second child of the row
147+var kHeaderRowCodeTemplate = 'Row { \n\
148−var kHeaderRow2Code = 'Row { \n\
149 id: row; \n\
148 id: row; \n\
150 objectName: "outerRow"; \n\
149 objectName: "outerRow"; \n\
151 property real margins: units.gu(1); \n\
150 property real margins: units.gu(1); \n\
@@ -153,35 +152,19 @@ var kHeaderRow2Code = 'Row { \n\
153 height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight; \n\
152 height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight; \n\
154 anchors { %1 } \n\
153 anchors { %1 } \n\
155 anchors.right: parent.right; \n\
154 anchors.right: parent.right; \n\
156− anchors.margins: margins;\n\
155+ anchors.margins: margins; \n\
157− data: [ %2\n\
156+ anchors.rightMargin: units.gu(0); \n\
163−// %1 is used as anchors of row
164−// %2 is used as first child of the row
165−// %3 is used as second child of the row
166−// %4 is used as third child of the row
167−var kHeaderRow3Code = 'Row { \n\
169− objectName: "outerRow"; \n\
170− property real margins: units.gu(1); \n\
171− spacing: margins; \n\
172− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight; \n\
174− anchors.right: parent.right; \n\
175− anchors.margins: margins;\n\
176− data: [ %2\n\
157+ data: [ \n\
161+ var args = Array.prototype.slice.call(arguments);
162+ var HeaderRowAnchors = args.shift();
163+ var code = kHeaderRowCodeTemplate.arg(HeaderRowAnchors).arg(args.join(',\n'));
184−// multiple column version of kHeaderContainerCode.
167+// multiple item version of kHeaderContainerCode
185function kHeaderContainerCodeGenerator() {
168function kHeaderContainerCodeGenerator() {
186 var headerContainerCodeTemplate = 'Item { \n\
169 var headerContainerCodeTemplate = 'Item { \n\
187 id: headerTitleContainer; \n\
170 id: headerTitleContainer; \n\
@@ -193,9 +176,9 @@ function kHeaderContainerCodeGenerator() {
195 var args = Array.prototype.slice.call(arguments);
178 var args = Array.prototype.slice.call(arguments);
196− var anchors = args.shift();
179+ var headerContainerAnchors = args.shift();
197− var height = args.shift();
180+ var headerContainerHeight = args.shift();
198− var code = headerContainerCodeTemplate.arg(anchors).arg(height).arg(args.join(',\n'));
181+ var code = headerContainerCodeTemplate.arg(headerContainerAnchors).arg(headerContainerHeight).arg(args.join(',\n'));
199 return code;
182 return code;
@@ -248,14 +231,14 @@ var kTitleLabelCode = 'Label { \n\
248 horizontalAlignment: root.headerAlignment; \n\
231 horizontalAlignment: root.headerAlignment; \n\
251−// %1 is used as additional anchors of emblem image
252var kEmblemImageCode = 'Image { \n\
234var kEmblemImageCode = 'Image { \n\
253 id: emblemImage; \n\
235 id: emblemImage; \n\
254 objectName: "emblemImage"; \n\
236 objectName: "emblemImage"; \n\
255 anchors { \n\
237 anchors { \n\
256 bottom: titleLabel.baseline; \n\
238 bottom: titleLabel.baseline; \n\
257 right: parent.right; \n\
239 right: parent.right; \n\
240+ rightMargin: units.gu(1); \n\
259 source: cardData && cardData["emblem"]; \n\
242 source: cardData && cardData["emblem"]; \n\
260 width: height; \n\
243 width: height; \n\
261 height: titleLabel.font.pixelSize; \n\
244 height: titleLabel.font.pixelSize; \n\
@@ -289,6 +272,15 @@ var kSubtitleLabelCode = 'Label { \n\
289 horizontalAlignment: root.headerAlignment; \n\
272 horizontalAlignment: root.headerAlignment; \n\
275+// %1 is used as anchors of attributesRow
276+var kAttributesRowCode = 'CardAttributes { \n\
277+ id: attributesRow; \n\
278+ objectName: "attributesRow"; \n\
281+ model: cardData && cardData["attributes"] || undefined; \n\
292// %1 is used as top anchor of summary
284// %1 is used as top anchor of summary
293// %2 is used as topMargin anchor of summary
285// %2 is used as topMargin anchor of summary
294// %3 is used as color of summary
286// %3 is used as color of summary
@@ -340,6 +332,7 @@ function cardString(template, components) {
340 var headerAsOverlay = hasArt && template && template["overlay"] === true && (hasTitle || hasMascot);
332 var headerAsOverlay = hasArt && template && template["overlay"] === true && (hasTitle || hasMascot);
341 var hasSubtitle = hasTitle && components["subtitle"] || false;
333 var hasSubtitle = hasTitle && components["subtitle"] || false;
342 var hasHeaderRow = hasMascot && hasTitle;
334 var hasHeaderRow = hasMascot && hasTitle;
335+ var hasAttributes = hasTitle && components["attributes"] || false;
344 if (hasBackground) {
337 if (hasBackground) {
345 code += kBackgroundLoaderCode;
338 code += kBackgroundLoaderCode;
@@ -350,9 +343,9 @@ function cardString(template, components) {
350 code += 'readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);\n';
343 code += 'readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);\n';
352 var widthCode, heightCode;
345 var widthCode, heightCode;
353− var anchors;
346+ var artAnchors;
354 if (isHorizontal) {
347 if (isHorizontal) {
355− anchors = 'left: parent.left';
348+ artAnchors = 'left: parent.left';
356 if (hasMascot || hasTitle) {
349 if (hasMascot || hasTitle) {
357 widthCode = 'height * artShape.aspect'
350 widthCode = 'height * artShape.aspect'
358 heightCode = 'headerHeight + 2 * units.gu(1)';
351 heightCode = 'headerHeight + 2 * units.gu(1)';
@@ -363,12 +356,12 @@ function cardString(template, components) {
363 heightCode = 'units.gu(7.625)';
356 heightCode = 'units.gu(7.625)';
366− anchors = 'horizontalCenter: parent.horizontalCenter;';
359+ artAnchors = 'horizontalCenter: parent.horizontalCenter;';
367 widthCode = 'root.width'
360 widthCode = 'root.width'
368 heightCode = 'width / artShape.aspect';
361 heightCode = 'width / artShape.aspect';
371− code += kArtShapeHolderCode.arg(anchors).arg(widthCode).arg(heightCode);
364+ code += kArtShapeHolderCode.arg(artAnchors).arg(widthCode).arg(heightCode);
373 code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
366 code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
@@ -409,6 +402,14 @@ function cardString(template, components) {
409 code += 'readonly property int headerHeight: row.height;\n'
402 code += 'readonly property int headerHeight: row.height;\n'
410 } else if (hasMascot) {
403 } else if (hasMascot) {
411 code += 'readonly property int headerHeight: mascotImage.height;\n'
404 code += 'readonly property int headerHeight: mascotImage.height;\n'
405+ } else if (hasAttributes) {
406+ if (hasTitle && hasSubtitle) {
407+ code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + attributesRow.height + attributesRow.anchors.topMargin;\n'
408+ } else if (hasTitle) {
409+ code += 'readonly property int headerHeight: titleLabel.height + attributesRow.height + attributesRow.anchors.topMargin;\n'
411+ code += 'readonly property int headerHeight: attributesRow.height;\n'
412 } else if (hasSubtitle) {
413 } else if (hasSubtitle) {
413 code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;\n'
414 code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;\n'
414 } else if (hasTitle) {
415 } else if (hasTitle) {
@@ -417,49 +418,52 @@ function cardString(template, components) {
417 code += 'readonly property int headerHeight: 0;\n'
418 code += 'readonly property int headerHeight: 0;\n'
420− var mascotShapeCode = "";
421+ var mascotShapeCode = '';
421− var mascotCode = "";
422+ var mascotCode = '';
422 if (hasMascot) {
423 if (hasMascot) {
423 var useMascotShape = !hasBackground && !headerAsOverlay;
424 var useMascotShape = !hasBackground && !headerAsOverlay;
424− var anchors = "";
425+ var mascotAnchors = '';
425 if (!hasHeaderRow) {
426 if (!hasHeaderRow) {
426− anchors += headerLeftAnchor;
427+ mascotAnchors += headerLeftAnchor;
427− anchors += headerVerticalAnchors;
428+ mascotAnchors += headerVerticalAnchors;
428 if (!headerLeftAnchorHasMargin) {
429 if (!headerLeftAnchorHasMargin) {
429− anchors += 'leftMargin: units.gu(1);\n'
430+ mascotAnchors += 'leftMargin: units.gu(1);\n'
432− anchors = "verticalCenter: parent.verticalCenter;"
433+ mascotAnchors = 'verticalCenter: parent.verticalCenter;'
435 if (useMascotShape) {
436 if (useMascotShape) {
436− mascotShapeCode = kMascotShapeLoaderCode.arg(anchors);
437+ mascotShapeCode = kMascotShapeLoaderCode.arg(mascotAnchors);
439 var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
440 var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
440− mascotCode = kMascotImageCode.arg(anchors).arg(mascotImageVisible);
441+ mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible);
443 var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey")';
444 var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey")';
445− var titleSubtitleCode = "";
446+ var titleSubtitleCode = '';
446 if (hasTitle) {
447 if (hasTitle) {
447− var color;
448+ var titleColor;
448 if (headerAsOverlay) {
449 if (headerAsOverlay) {
449− color = '"white"';
450+ titleColor = '"white"';
450 } else if (hasSummary) {
451 } else if (hasSummary) {
451− color = 'summary.color';
452+ titleColor = 'summary.color';
452 } else if (hasBackground) {
453 } else if (hasBackground) {
453− color = summaryColorWithBackground;
454+ titleColor = summaryColorWithBackground;
455− color = 'root.scopeStyle ? root.scopeStyle.foreground : "grey"';
456+ titleColor = 'root.scopeStyle ? root.scopeStyle.foreground : "grey"';
458 var titleAnchors;
459 var titleAnchors;
459 var subtitleAnchors;
460 var subtitleAnchors;
461+ var attributesAnchors;
460 var titleRightAnchor;
462 var titleRightAnchor;
461 var titleContainerAnchors;
463 var titleContainerAnchors;
463 if (hasMascot) {
467 if (hasMascot) {
464 titleContainerAnchors = 'verticalCenter: parent.verticalCenter; ';
468 titleContainerAnchors = 'verticalCenter: parent.verticalCenter; ';
@@ -476,14 +480,20 @@ function cardString(template, components) {
476 titleRightAnchor = 'right: parent.right;\n';
480 titleRightAnchor = 'right: parent.right;\n';
479− if (hasEmblem || (hasMascot && hasSubtitle)) {
483+ if (hasEmblem || (hasMascot && (hasSubtitle || hasAttributes))) {
480− // Using titleContainer (and maybe row)
484+ // Using headerTitleContainer
481 titleAnchors = titleRightAnchor;
485 titleAnchors = titleRightAnchor;
482− titleAnchors += 'left: parent.left;\n\
486+ titleAnchors += 'left: parent.left; \n\
483− top: parent.top;';
487+ top: parent.top;';
484− subtitleAnchors = 'right: parent.right;\n\
488+ subtitleAnchors = 'right: parent.right; \n\
485− left: parent.left;\n\
489+ left: parent.left; \n\
490+ rightMargin: units.gu(1); \n';
492+ attributesAnchors = subtitleAnchors + 'top: subtitleLabel.bottom;\n';
486− top: titleLabel.bottom;\n';
493+ subtitleAnchors += 'top: titleLabel.bottom;\n';
495+ attributesAnchors = subtitleAnchors + 'top: titleLabel.bottom;\n';
487 } else if (hasMascot) {
497 } else if (hasMascot) {
488 // Using row + titleContainer
498 // Using row + titleContainer
489 titleAnchors = 'verticalCenter: parent.verticalCenter;\n';
499 titleAnchors = 'verticalCenter: parent.verticalCenter;\n';
@@ -501,81 +511,100 @@ function cardString(template, components) {
501 titleAnchors += headerLeftAnchor;
511 titleAnchors += headerLeftAnchor;
502 titleAnchors += headerVerticalAnchors;
512 titleAnchors += headerVerticalAnchors;
503 if (!headerLeftAnchorHasMargin) {
513 if (!headerLeftAnchorHasMargin) {
504− titleAnchors += 'leftMargin: units.gu(1);\n'
514+ titleAnchors += 'leftMargin: units.gu(1);\n';
507 subtitleAnchors = 'left: titleLabel.left; \n\
517 subtitleAnchors = 'left: titleLabel.left; \n\
508 leftMargin: titleLabel.leftMargin; \n\
518 leftMargin: titleLabel.leftMargin; \n\
509− top: titleLabel.bottom;\n';
519+ rightMargin: units.gu(1); \n';
510 if (hasEmblem) {
520 if (hasEmblem) {
511 // using container
521 // using container
512 subtitleAnchors += 'right: parent.right; \n';
522 subtitleAnchors += 'right: parent.right; \n';
514 subtitleAnchors += 'right: titleLabel.right; \n';
524 subtitleAnchors += 'right: titleLabel.right; \n';
528+ attributesAnchors = subtitleAnchors + 'top: subtitleLabel.bottom;\n';
529+ subtitleAnchors += 'top: titleLabel.bottom;\n';
531+ attributesAnchors = subtitleAnchors + 'top: titleLabel.bottom;\n';
535+ // code for different elements
518 var titleLabelVisibleExtra = (headerAsOverlay ? '&& overlayLoader.active': '');
536 var titleLabelVisibleExtra = (headerAsOverlay ? '&& overlayLoader.active': '');
520− titleCode = kTitleLabelCode.arg(titleAnchors).arg(color).arg(titleLabelVisibleExtra);
537+ var titleCode = kTitleLabelCode.arg(titleAnchors).arg(titleColor).arg(titleLabelVisibleExtra);
521− var subtitleCode = "";
538+ var subtitleCode;
542+ // code for the title container
543+ var containerCode = [];
544+ var containerHeight = 'titleLabel.height';
545+ containerCode.push(titleCode);
522 if (hasSubtitle) {
546 if (hasSubtitle) {
523− subtitleCode += kSubtitleLabelCode.arg(subtitleAnchors).arg(color);
547+ subtitleCode = kSubtitleLabelCode.arg(subtitleAnchors).arg(titleColor);
548+ containerCode.push(subtitleCode);
549+ containerHeight += ' + subtitleLabel.height';
525−
551+ if (hasEmblem) {
526− var emblemCode;
552+ containerCode.push(kEmblemImageCode);
527− if (hasMascot) {
553+ }
528− emblemCode = kEmblemImageCode.arg('');
554+ if (hasAttributes) {
529− } else {
555+ attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(titleColor);
530− emblemCode = kEmblemImageCode.arg('rightMargin: units.gu(1);');
556+ containerCode.push(kAttributesRowCode.arg(attributesAnchors).arg(titleColor));
557+ containerHeight += ' + attributesRow.height';
532− if (hasEmblem && hasSubtitle) {
559+
533− // using container 3
534− titleSubtitleCode = kHeaderContainerCodeGenerator(titleContainerAnchors, 'titleLabel.height + subtitleLabel.height', titleCode, emblemCode, kSubtitleLabelCode.arg(subtitleAnchors).arg(color));
535− } else if (hasEmblem) {
536− // container with emblem
537− titleSubtitleCode = kHeaderContainerCodeGenerator(titleContainerAnchors, 'titleLabel.height', titleCode, emblemCode);
538− } else if (hasMascot && hasSubtitle) {
560+ if (hasEmblem || (hasMascot && (hasSubtitle || hasAttributes))) {
539− // container with subtitle
561+ // use container
540− titleSubtitleCode = kHeaderContainerCodeGenerator(titleContainerAnchors, 'titleLabel.height + subtitleLabel.height', titleCode, subtitleCode);
562+ titleSubtitleCode = kHeaderContainerCodeGenerator(titleContainerAnchors, containerHeight, containerCode);
542 // no container
564 // no container
543− titleSubtitleCode = titleCode + subtitleCode;
565+ titleSubtitleCode = titleCode;
567+ titleSubtitleCode += subtitleCode;
569+ if (hasAttributes) {
570+ titleSubtitleCode += attributesCode;
547 if (hasHeaderRow) {
575 if (hasHeaderRow) {
576+ var rowCode = [mascotCode, titleSubtitleCode];
548− if (mascotShapeCode != "") {
577+ if (mascotShapeCode != '') {
549− code += kHeaderRow3Code.arg(headerVerticalAnchors + headerLeftAnchor).arg(mascotShapeCode).arg(mascotCode).arg(titleSubtitleCode);
578+ rowCode.unshift(mascotShapeCode);
551− code += kHeaderRow2Code.arg(headerVerticalAnchors + headerLeftAnchor).arg(mascotCode).arg(titleSubtitleCode);
580+ code += kHeaderRowCodeGenerator(headerVerticalAnchors + headerLeftAnchor, rowCode)
554 code += mascotShapeCode + mascotCode + titleSubtitleCode;
582 code += mascotShapeCode + mascotCode + titleSubtitleCode;
557 if (hasSummary) {
585 if (hasSummary) {
558 var summaryTopAnchor;
586 var summaryTopAnchor;
559− if (isHorizontal && hasArt) summaryTopAnchor = "artShapeHolder.bottom";
587+ if (isHorizontal && hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
560− else if (headerAsOverlay && hasArt) summaryTopAnchor = "artShapeHolder.bottom";
588+ else if (headerAsOverlay && hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
561− else if (hasHeaderRow) summaryTopAnchor = "row.bottom";
589+ else if (hasHeaderRow) summaryTopAnchor = 'row.bottom';
562− else if (hasEmblem || (hasMascot && hasSubtitle)) summaryTopAnchor = "headerTitleContainer.bottom";
590+ else if (hasEmblem || (hasMascot && (hasSubtitle || hasAttributes))) summaryTopAnchor = 'headerTitleContainer.bottom';
563− else if (hasMascot) summaryTopAnchor = "mascotImage.bottom";
591+ else if (hasMascot) summaryTopAnchor = 'mascotImage.bottom';
592+ else if (hasAttributes) summaryTopAnchor = 'attributesRow.bottom';
564− else if (hasSubtitle) summaryTopAnchor = "subtitleLabel.bottom";
593+ else if (hasSubtitle) summaryTopAnchor = 'subtitleLabel.bottom';
565− else if (hasTitle) summaryTopAnchor = "titleLabel.bottom";
594+ else if (hasTitle) summaryTopAnchor = 'titleLabel.bottom';
566− else if (hasArt) summaryTopAnchor = "artShapeHolder.bottom";
595+ else if (hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
567− else summaryTopAnchor = "parent.top";
596+ else summaryTopAnchor = 'parent.top';
569− var color;
598+ var summaryColor;
570 if (hasBackground) {
599 if (hasBackground) {
571− color = summaryColorWithBackground;
600+ summaryColor = summaryColorWithBackground;
573− color = 'root.scopeStyle ? root.scopeStyle.foreground : "grey"';
602+ summaryColor = 'root.scopeStyle ? root.scopeStyle.foreground : "grey"';
576− var summaryTopMargin = (hasMascot || hasSubtitle ? 'anchors.margins' : '0');
605+ var summaryTopMargin = (hasMascot || hasSubtitle || hasAttributes ? 'anchors.margins' : '0');
578− code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(color);
607+ code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(summaryColor);
581 var touchdownAnchors;
610 var touchdownAnchors;
@@ -594,6 +623,8 @@ function cardString(template, components) {
594 code += 'implicitHeight: row.y + row.height + units.gu(1);\n';
623 code += 'implicitHeight: row.y + row.height + units.gu(1);\n';
595 } else if (hasMascot) {
624 } else if (hasMascot) {
596 code += 'implicitHeight: mascotImage.y + mascotImage.height;\n';
625 code += 'implicitHeight: mascotImage.y + mascotImage.height;\n';
626+ } else if (hasAttributes) {
627+ code += 'implicitHeight: attributesRow.y + attributesRow.height + units.gu(1);\n';
597 } else if (hasSubtitle) {
628 } else if (hasSubtitle) {
598 code += 'implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
629 code += 'implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
599 } else if (hasTitle) {
630 } else if (hasTitle) {
@@ -610,8 +641,10 @@ function cardString(template, components) {
610function createCardComponent(parent, template, components) {
641function createCardComponent(parent, template, components) {
611 var imports = 'import QtQuick 2.2; \n\
642 var imports = 'import QtQuick 2.2; \n\
612 import Ubuntu.Components 0.1; \n\
643 import Ubuntu.Components 0.1; \n\
613− import Ubuntu.Thumbnailer 0.1;\n';
644+ import Ubuntu.Thumbnailer 0.1;\n\
645+ import Dash 0.1;\n';
614 var card = cardString(template, components);
646 var card = cardString(template, components);
615 var code = imports + 'Component {\n' + card + '}\n';
647 var code = imports + 'Component {\n' + card + '}\n';
616 return Qt.createQmlObject(code, parent, "createCardComponent");
649 return Qt.createQmlObject(code, parent, "createCardComponent");