~mterry/+junk/u8

« back to all changes in this revision

Viewing changes to plugins/Dash/CardCreator.js

Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
                                objectName: "backgroundLoader"; \n\
26
26
                                anchors.fill: parent; \n\
27
27
                                asynchronous: %3; \n\
28
 
                                visible: status == Loader.Ready; \n\
 
28
                                visible: status === Loader.Ready; \n\
29
29
                                sourceComponent: UbuntuShape { \n\
30
30
                                    objectName: "background"; \n\
31
 
                                    radius: "medium"; \n\
 
31
                                    radius: "small"; \n\
32
32
                                    aspect: { \n\
33
33
                                        switch (root.backgroundShapeStyle) { \n\
34
34
                                            case "inset": return UbuntuShape.Inset; \n\
64
64
                                anchors.fill: parent; \n\
65
65
                                source: artImage; \n\
66
66
                                sourceFillMode: UbuntuShape.PreserveAspectCrop; \n\
67
 
                                radius: "medium"; \n\
 
67
                                radius: "small"; \n\
68
68
                                aspect: %1; \n\
69
69
                            }';
70
70
 
71
71
var kArtProportionalShapeCode = 'ProportionalShape { \n\
72
 
                                    anchors.fill: parent; \n\
 
72
                                    anchors.left: parent.left; \n\
 
73
                                    anchors.right: parent.right; \n\
73
74
                                    source: artImage; \n\
74
75
                                    aspect: UbuntuShape.DropShadow; \n\
75
76
                                 }';
76
77
 
77
 
// %1 is used as anchors of artShapeHolder
78
 
// %2 is used as image width
79
 
// %3 is used as image height
80
 
// %4 is whether the image should be visible
81
 
// %5 is used as aspect ratio fallback
82
 
// %6 is whether the loader should be asynchronous or not
83
 
// %7 is the shape code we want to use
84
 
// %8 is injected as code to artImage
85
 
// %9 is used as image fallback
86
 
var kArtShapeHolderCode = 'Item { \n\
87
 
                            id: artShapeHolder; \n\
88
 
                            height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height; \n\
89
 
                            width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width; \n\
90
 
                            anchors { %1 } \n\
91
 
                            Loader { \n\
92
 
                                id: artShapeLoader; \n\
93
 
                                objectName: "artShapeLoader"; \n\
94
 
                                readonly property string cardArt: cardData && cardData["art"] || %9; \n\
95
 
                                onCardArtChanged: { if (item) { item.image.source = cardArt; } } \n\
96
 
                                active: cardArt != ""; \n\
97
 
                                asynchronous: %6; \n\
98
 
                                visible: status == Loader.Ready; \n\
99
 
                                sourceComponent: Item { \n\
100
 
                                    id: artShape; \n\
101
 
                                    objectName: "artShape"; \n\
102
 
                                    visible: image.status == Image.Ready; \n\
103
 
                                    readonly property alias image: artImage; \n\
104
 
                                    %7 \n\
105
 
                                    readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1; \n\
106
 
                                    readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : %5; \n\
107
 
                                    Component.onCompleted: { updateWidthHeightBindings(); } \n\
108
 
                                    Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); } \n\
109
 
                                    function updateWidthHeightBindings() { \n\
110
 
                                        if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) { \n\
111
 
                                            width = root.fixedArtShapeSize.width; \n\
112
 
                                            height = root.fixedArtShapeSize.height; \n\
113
 
                                        } else { \n\
114
 
                                            width = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.width }); \n\
115
 
                                            height = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.height }); \n\
116
 
                                        } \n\
117
 
                                    } \n\
118
 
                                    CroppedImageMinimumSourceSize { \n\
119
 
                                        id: artImage; \n\
120
 
                                        objectName: "artImage"; \n\
121
 
                                        source: artShapeLoader.cardArt; \n\
122
 
                                        asynchronous: %6; \n\
123
 
                                        visible: %4; \n\
124
 
                                        width: %2; \n\
125
 
                                        height: %3; \n\
126
 
                                        %8 \n\
127
 
                                    } \n\
 
78
// %1 is used as anchors of artShapeLoader
 
79
// %2 is used as image width
 
80
// %3 is used as image height
 
81
// %4 is whether the image should be visible
 
82
// %5 is whether the loader should be asynchronous or not
 
83
// %6 is the shape code we want to use
 
84
// %7 is injected as code to artImage
 
85
// %8 is used as image fallback
 
86
var kArtShapeHolderCode = 'Loader { \n\
 
87
                            id: artShapeLoader; \n\
 
88
                            height: root.fixedArtShapeSize.height; \n\
 
89
                            width: root.fixedArtShapeSize.width; \n\
 
90
                            anchors { %1 } \n\
 
91
                            objectName: "artShapeLoader"; \n\
 
92
                            readonly property string cardArt: cardData && cardData["art"] || %8; \n\
 
93
                            onCardArtChanged: { if (item) { item.image.source = cardArt; } } \n\
 
94
                            active: cardArt != ""; \n\
 
95
                            asynchronous: %5; \n\
 
96
                            visible: status === Loader.Ready; \n\
 
97
                            sourceComponent: Item { \n\
 
98
                                id: artShape; \n\
 
99
                                objectName: "artShape"; \n\
 
100
                                visible: image.status === Image.Ready; \n\
 
101
                                readonly property alias image: artImage; \n\
 
102
                                %6 \n\
 
103
                                width: root.fixedArtShapeSize.width; \n\
 
104
                                height: root.fixedArtShapeSize.height; \n\
 
105
                                CroppedImageMinimumSourceSize { \n\
 
106
                                    id: artImage; \n\
 
107
                                    objectName: "artImage"; \n\
 
108
                                    source: artShapeLoader.cardArt; \n\
 
109
                                    asynchronous: %5; \n\
 
110
                                    visible: %4; \n\
 
111
                                    width: %2; \n\
 
112
                                    height: %3; \n\
 
113
                                    %7 \n\
 
114
                                } \n\
 
115
                            } \n\
 
116
                        }\n';
 
117
 
 
118
// %1 is used as anchors of artShapeLoader
 
119
// %2 is used as image width
 
120
// %3 is used as image height
 
121
// %4 is whether the image should be visible
 
122
// %5 is whether the loader should be asynchronous or not
 
123
// %6 is the shape code we want to use
 
124
// %7 is injected as code to artImage
 
125
// %8 is used as image fallback
 
126
var kArtShapeHolderCodeCardToolCard = 'Loader { \n\
 
127
                            id: artShapeLoader; \n\
 
128
                            anchors { %1 } \n\
 
129
                            objectName: "artShapeLoader"; \n\
 
130
                            readonly property string cardArt: cardData && cardData["art"] || %8; \n\
 
131
                            onCardArtChanged: { if (item) { item.image.source = cardArt; } } \n\
 
132
                            active: cardArt != ""; \n\
 
133
                            asynchronous: %5; \n\
 
134
                            visible: status === Loader.Ready; \n\
 
135
                            sourceComponent: Item { \n\
 
136
                                id: artShape; \n\
 
137
                                objectName: "artShape"; \n\
 
138
                                visible: image.status === Image.Ready; \n\
 
139
                                readonly property alias image: artImage; \n\
 
140
                                %6 \n\
 
141
                                width: image.status !== Image.Ready ? 0 : image.width; \n\
 
142
                                height: image.status !== Image.Ready ? 0 : image.height; \n\
 
143
                                CroppedImageMinimumSourceSize { \n\
 
144
                                    id: artImage; \n\
 
145
                                    objectName: "artImage"; \n\
 
146
                                    source: artShapeLoader.cardArt; \n\
 
147
                                    asynchronous: %5; \n\
 
148
                                    visible: %4; \n\
 
149
                                    width: %2; \n\
 
150
                                    height: %3; \n\
 
151
                                    %7 \n\
128
152
                                } \n\
129
153
                            } \n\
130
154
                        }\n';
142
166
                            UbuntuShape { \n\
143
167
                                anchors.fill: parent; \n\
144
168
                                visible: parent.pressed; \n\
145
 
                                radius: "medium"; \n\
 
169
                                radius: "small"; \n\
146
170
                            } \n\
147
171
                            Rectangle { \n\
148
172
                                color: Qt.rgba(0, 0, 0, 0.5); \n\
182
206
var kOverlayLoaderCode = 'Loader { \n\
183
207
                            id: overlayLoader; \n\
184
208
                            readonly property real overlayHeight: %2 + units.gu(2); \n\
185
 
                            anchors.fill: artShapeHolder; \n\
 
209
                            anchors.fill: artShapeLoader; \n\
186
210
                            active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false; \n\
187
211
                            asynchronous: %1; \n\
188
 
                            visible: showHeader && status == Loader.Ready; \n\
 
212
                            visible: showHeader && status === Loader.Ready; \n\
189
213
                            sourceComponent: UbuntuShapeOverlay { \n\
190
214
                                id: overlay; \n\
191
215
                                property real luminance: Style.luminance(overlayColor); \n\
192
216
                                aspect: UbuntuShape.Flat; \n\
193
 
                                radius: "medium"; \n\
 
217
                                radius: "small"; \n\
194
218
                                overlayColor: cardData && cardData["overlayColor"] || "#99000000"; \n\
195
219
                                overlayRect: Qt.rect(0, 1 - overlayLoader.overlayHeight / height, 1, 1); \n\
196
220
                            } \n\
242
266
                                objectName: "mascotShapeLoader"; \n\
243
267
                                asynchronous: %2; \n\
244
268
                                active: mascotImage.status === Image.Ready; \n\
245
 
                                visible: showHeader && active && status == Loader.Ready; \n\
 
269
                                visible: showHeader && active && status === Loader.Ready; \n\
246
270
                                width: units.gu(6); \n\
247
271
                                height: units.gu(5.625); \n\
248
272
                                sourceComponent: UbuntuShape { image: mascotImage } \n\
284
308
                        visible: showHeader %3; \n\
285
309
                        width: %4; \n\
286
310
                        text: root.title; \n\
287
 
                        font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal; \n\
 
311
                        font.weight: Font.Normal; \n\
288
312
                        horizontalAlignment: %5; \n\
289
313
                    }\n';
290
314
 
307
331
                        }\n';
308
332
 
309
333
// %1 is used as anchors of touchdown effect
310
 
var kTouchdownCode = 'UbuntuShape { \n\
311
 
                        id: touchdown; \n\
312
 
                        objectName: "touchdown"; \n\
 
334
var kTouchdownCode = 'Loader { \n\
 
335
                        active: root.pressed; \n\
313
336
                        anchors { %1 } \n\
314
 
                        visible: root.pressed; \n\
315
 
                        radius: "medium"; \n\
316
 
                        borderSource: "radius_pressed.sci" \n\
 
337
                        sourceComponent: UbuntuShape { \n\
 
338
                            objectName: "touchdown"; \n\
 
339
                            anchors.fill: parent; \n\
 
340
                            radius: "small"; \n\
 
341
                            borderSource: "radius_pressed.sci" \n\
 
342
                        } \n\
317
343
                    }\n';
318
344
 
319
345
// %1 is used as anchors of subtitleLabel
373
399
                            elide: Text.ElideRight; \n\
374
400
                            text: cardData && cardData["summary"] || ""; \n\
375
401
                            height: text ? implicitHeight : 0; \n\
376
 
                            fontSize: "small"; \n\
 
402
                            fontSize: "x-small"; \n\
 
403
                            font.weight: Font.Light; \n\
377
404
                            color: %3; \n\
378
405
                        }\n';
379
406
 
405
432
    return colorString;
406
433
}
407
434
 
408
 
function cardString(template, components, isCardTool, artShapeStyle) {
 
435
function cardString(template, components, isCardTool, artShapeStyle, categoryLayout) {
409
436
    var code;
410
437
 
411
438
    var templateInteractive = (template == null ? true : (template["non-interactive"] !== undefined ? !template["non-interactive"] : true)) ? "true" : "false";
413
440
    code = 'AbstractButton { \n\
414
441
                id: root; \n\
415
442
                property var cardData; \n\
416
 
                property string backgroundShapeStyle: "inset"; \n\
 
443
                property string backgroundShapeStyle: "flat"; \n\
417
444
                property real fontScale: 1.0; \n\
418
445
                property var scopeStyle: null; \n\
419
 
                %2\
420
 
                property size fixedArtShapeSize: Qt.size(-1, -1); \n\
421
446
                readonly property string title: cardData && cardData["title"] || ""; \n\
422
447
                property bool showHeader: true; \n\
423
448
                implicitWidth: childrenRect.width; \n\
424
449
                enabled: %1; \n\
425
450
                \n'.arg(templateInteractive);
426
451
 
427
 
    code = code.arg(isCardTool ? "" : "property int fixedHeaderHeight: -1; \n");
 
452
    if (!isCardTool) {
 
453
        code += "property int fixedHeaderHeight: -1; \n\
 
454
                 property size fixedArtShapeSize: Qt.size(-1, -1); \n";
 
455
    }
428
456
 
429
457
    var hasArt = components["art"] && components["art"]["field"] || false;
430
458
    var hasSummary = components["summary"] || false;
481
509
    }
482
510
 
483
511
    if (hasArt) {
484
 
        code += 'readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);\n';
 
512
        var artShapeAspect;
 
513
        if (isCardTool) {
 
514
            code += 'readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);\n';
 
515
 
 
516
            var artShapeAspect = components["art"] && components["art"]["aspect-ratio"] || 1;
 
517
            if (isNaN(artShapeAspect)) {
 
518
                artShapeAspect = 1;
 
519
            }
 
520
        } else {
 
521
            artShapeAspect = "(root.fixedArtShapeSize.width / root.fixedArtShapeSize.height)";
 
522
        }
485
523
 
486
524
        var widthCode, heightCode;
487
525
        var artAnchors;
488
526
        if (isHorizontal) {
489
527
            artAnchors = 'left: parent.left';
490
528
            if (hasMascot || hasTitle) {
491
 
                widthCode = 'height * artShape.aspect'
 
529
                widthCode = 'height * ' + artShapeAspect;
492
530
                heightCode = 'headerHeight + 2 * units.gu(1)';
493
531
            } else {
494
532
                // This side of the else is a bit silly, who wants an horizontal layout without mascot and title?
495
533
                // So we define a "random" height of the image height + 2 gu for the margins
496
 
                widthCode = 'height * artShape.aspect'
 
534
                widthCode = 'height * ' + artShapeAspect
497
535
                heightCode = 'units.gu(7.625)';
498
536
            }
499
537
        } else {
500
538
            artAnchors = 'horizontalCenter: parent.horizontalCenter;';
501
539
            widthCode = 'root.width'
502
 
            heightCode = 'width / artShape.aspect';
 
540
            heightCode = 'width / ' + artShapeAspect;
503
541
        }
504
542
 
505
 
        var aspectRatio = components["art"] && components["art"]["aspect-ratio"] || 1;
506
 
        if (isNaN(aspectRatio)) {
507
 
            aspectRatio = 1;
508
 
        }
509
543
        var fallback = !isCardTool && components["art"] && components["art"]["fallback"] || "";
510
544
        fallback = encodeURI(fallback);
511
545
        var fallbackStatusCode = "";
512
546
        var fallbackURICode = '""';
513
547
        if (fallback !== "") {
514
 
            // fallbackStatusCode has %9 in it because we want to substitute it for fallbackURICode
515
 
            // which in kArtShapeHolderCode is %9
516
 
            fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %9;';
 
548
            // fallbackStatusCode has %8 in it because we want to substitute it for fallbackURICode
 
549
            // which in kArtShapeHolderCode is %8
 
550
            fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %8;';
517
551
            fallbackURICode = 'decodeURI("%1")'.arg(fallback);
518
552
        }
519
553
        var artShapeHolderShapeCode;
533
567
        } else {
534
568
            artShapeHolderShapeCode = "";
535
569
        }
536
 
        code += kArtShapeHolderCode.arg(artAnchors)
537
 
                                   .arg(widthCode)
538
 
                                   .arg(heightCode)
539
 
                                   .arg(isConciergeMode ? "true" : "false")
540
 
                                   .arg(aspectRatio)
541
 
                                   .arg(asynchronous)
542
 
                                   .arg(artShapeHolderShapeCode)
543
 
                                   .arg(fallbackStatusCode)
544
 
                                   .arg(fallbackURICode);
545
 
    } else {
 
570
        var artShapeHolderCode = isCardTool ? kArtShapeHolderCodeCardToolCard : kArtShapeHolderCode;
 
571
        code += artShapeHolderCode.arg(artAnchors)
 
572
                                  .arg(widthCode)
 
573
                                  .arg(heightCode)
 
574
                                  .arg(isConciergeMode ? "true" : "false")
 
575
                                  .arg(asynchronous)
 
576
                                  .arg(artShapeHolderShapeCode)
 
577
                                  .arg(fallbackStatusCode)
 
578
                                  .arg(fallbackURICode);
 
579
    } else if (isCardTool) {
546
580
        code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
547
581
    }
548
582
 
553
587
 
554
588
    var headerVerticalAnchors;
555
589
    if (headerAsOverlay) {
556
 
        headerVerticalAnchors = 'bottom: artShapeHolder.bottom; \n\
 
590
        headerVerticalAnchors = 'bottom: artShapeLoader.bottom; \n\
557
591
                                 bottomMargin: units.gu(1);\n';
558
592
    } else {
559
593
        if (hasArt) {
560
594
            if (isHorizontal) {
561
 
                headerVerticalAnchors = 'top: artShapeHolder.top; \n\
 
595
                headerVerticalAnchors = 'top: artShapeLoader.top; \n\
562
596
                                         topMargin: units.gu(1);\n';
563
597
            } else {
564
 
                headerVerticalAnchors = 'top: artShapeHolder.bottom; \n\
 
598
                headerVerticalAnchors = 'top: artShapeLoader.bottom; \n\
565
599
                                         topMargin: units.gu(1);\n';
566
600
            }
567
601
        } else {
573
607
    var headerLeftAnchor;
574
608
    var headerLeftAnchorHasMargin = false;
575
609
    if (isHorizontal && hasArt) {
576
 
        headerLeftAnchor = 'left: artShapeHolder.right; \n\
 
610
        headerLeftAnchor = 'left: artShapeLoader.right; \n\
577
611
                            leftMargin: units.gu(1);\n';
578
612
        headerLeftAnchorHasMargin = true;
579
613
    } else if (isHorizontal && isAudio) {
827
861
        var audioButtonWidth;
828
862
        var audioButtonHeight;
829
863
        if (hasArt) {
830
 
            audioButtonAnchorsFill = 'artShapeHolder';
 
864
            audioButtonAnchorsFill = 'artShapeLoader';
831
865
            audioButtonWidth = 'undefined';
832
866
            audioButtonHeight = 'undefined';
833
867
        } else {
841
875
 
842
876
    if (hasSummary) {
843
877
        var summaryTopAnchor;
844
 
        if (isHorizontal && hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
845
 
        else if (headerAsOverlay && hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
 
878
        if (isHorizontal && hasArt) summaryTopAnchor = 'artShapeLoader.bottom';
 
879
        else if (headerAsOverlay && hasArt) summaryTopAnchor = 'artShapeLoader.bottom';
846
880
        else if (hasHeaderRow) summaryTopAnchor = 'row.bottom';
847
881
        else if (hasTitleContainer) summaryTopAnchor = 'headerTitleContainer.bottom';
848
882
        else if (hasMascot) summaryTopAnchor = 'mascotImage.bottom';
849
883
        else if (hasAttributes) summaryTopAnchor = 'attributesRow.bottom';
850
884
        else if (hasSubtitle) summaryTopAnchor = 'subtitleLabel.bottom';
851
885
        else if (hasTitle) summaryTopAnchor = 'titleLabel.bottom';
852
 
        else if (hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
 
886
        else if (hasArt) summaryTopAnchor = 'artShapeLoader.bottom';
853
887
        else summaryTopAnchor = 'parent.top';
854
888
 
855
889
        var summaryColor;
864
898
        code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(summaryColor);
865
899
    }
866
900
 
867
 
// <<<<<<< TREE
868
 
//     if (artShapeStyle != "shadow" && artShapeStyle != "icon") {
869
 
//         var touchdownAnchors;
870
 
// =======
871
901
    if (hasSocialActions) {
872
902
        var socialAnchors;
873
903
        var socialTopAnchor;
874
904
 
875
905
        if (hasSummary) socialTopAnchor = 'summary.bottom;';
876
 
        else if (isHorizontal && hasArt) socialTopAnchor = 'artShapeHolder.bottom;';
877
 
        else if (headerAsOverlay && hasArt) socialTopAnchor = 'artShapeHolder.bottom;';
 
906
        else if (isHorizontal && hasArt) socialTopAnchor = 'artShapeLoader.bottom;';
 
907
        else if (headerAsOverlay && hasArt) socialTopAnchor = 'artShapeLoader.bottom;';
878
908
        else if (hasHeaderRow) socialTopAnchor = 'row.bottom;';
879
909
        else if (hasTitleContainer) socialTopAnchor = 'headerTitleContainer.bottom;';
880
910
        else if (hasMascot) socialTopAnchor = 'mascotImage.bottom;';
881
911
        else if (hasAttributes) socialTopAnchor = 'attributesRow.bottom;';
882
912
        else if (hasSubtitle) socialTopAnchor = 'subtitleLabel.bottom;';
883
913
        else if (hasTitle) socialTopAnchor = 'titleLabel.bottom;';
884
 
        else if (hasArt) socialTopAnchor = 'artShapeHolder.bottom;';
 
914
        else if (hasArt) socialTopAnchor = 'artShapeLoader.bottom;';
885
915
        else socialTopAnchor = 'parent.top';
886
916
 
887
917
        socialAnchors = 'top: ' + socialTopAnchor + ' left: parent.left; right: parent.right; topMargin: units.gu(1);'
896
926
        code += kSocialActionsRowCode.arg(socialAnchors).arg(socialColor);
897
927
    }
898
928
 
899
 
    if (artShapeStyle != "shadow" && artShapeStyle != "icon") {
 
929
    if (artShapeStyle != "shadow" && artShapeStyle != "icon" && !isCardTool) {
900
930
        var touchdownAnchors;
901
931
        if (hasBackground) {
902
932
            touchdownAnchors = 'fill: backgroundLoader';
903
933
        } else if (touchdownOnArtShape) {
904
 
            touchdownAnchors = 'fill: artShapeHolder';
 
934
            touchdownAnchors = 'fill: artShapeLoader';
905
935
        } else {
906
936
            touchdownAnchors = 'fill: root'
907
937
        }
908
938
        code += kTouchdownCode.arg(touchdownAnchors);
909
939
    }
910
940
 
911
 
    var implicitHeight = 'implicitHeight: ';
912
 
    if (hasSocialActions) {
913
 
        implicitHeight += 'socialActionsRow.y + socialActionsRow.height + units.gu(1);\n';
914
 
    } else if (hasSummary) {
915
 
        implicitHeight += 'summary.y + summary.height + units.gu(1);\n';
916
 
    } else if (isAudio) {
917
 
        implicitHeight += 'audioButton.height;\n';
918
 
    } else if (headerAsOverlay) {
919
 
        implicitHeight += 'artShapeHolder.height;\n';
920
 
    } else if (hasHeaderRow) {
921
 
        implicitHeight += 'row.y + row.height + units.gu(1);\n';
922
 
    } else if (hasMascot) {
923
 
        implicitHeight += 'mascotImage.y + mascotImage.height;\n';
924
 
    } else if (hasTitleContainer) {
925
 
        implicitHeight += 'headerTitleContainer.y + headerTitleContainer.height + units.gu(1);\n';
926
 
    } else if (hasAttributes) {
927
 
        implicitHeight += 'attributesRow.y + attributesRow.height + units.gu(1);\n';
928
 
    } else if (hasSubtitle) {
929
 
        implicitHeight += 'subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
930
 
    } else if (hasTitle) {
931
 
        implicitHeight += 'titleLabel.y + titleLabel.height + units.gu(1);\n';
932
 
    } else if (hasArt) {
933
 
        implicitHeight += 'artShapeHolder.height;\n';
 
941
    if (isCardTool || categoryLayout !== "grid") {
 
942
        var implicitHeight = 'implicitHeight: ';
 
943
        if (hasSocialActions) {
 
944
            implicitHeight += 'socialActionsRow.y + socialActionsRow.height + units.gu(1);\n';
 
945
        } else if (hasSummary) {
 
946
            implicitHeight += 'summary.y + summary.height + units.gu(1);\n';
 
947
        } else if (isAudio) {
 
948
            implicitHeight += 'audioButton.height;\n';
 
949
        } else if (headerAsOverlay) {
 
950
            implicitHeight += 'artShapeLoader.height;\n';
 
951
        } else if (hasHeaderRow) {
 
952
            implicitHeight += 'row.y + row.height + units.gu(1);\n';
 
953
        } else if (hasMascot) {
 
954
            implicitHeight += 'mascotImage.y + mascotImage.height;\n';
 
955
        } else if (hasTitleContainer) {
 
956
            implicitHeight += 'headerTitleContainer.y + headerTitleContainer.height + units.gu(1);\n';
 
957
        } else if (hasAttributes) {
 
958
            implicitHeight += 'attributesRow.y + attributesRow.height + units.gu(1);\n';
 
959
        } else if (hasSubtitle) {
 
960
            implicitHeight += 'subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
 
961
        } else if (hasTitle) {
 
962
            implicitHeight += 'titleLabel.y + titleLabel.height + units.gu(1);\n';
 
963
        } else if (hasArt) {
 
964
            implicitHeight += 'artShapeLoader.height;\n';
 
965
        } else {
 
966
            implicitHeight = '';
 
967
        }
934
968
    } else {
935
969
        implicitHeight = '';
936
970
    }
941
975
    return code;
942
976
}
943
977
 
944
 
function createCardComponent(parent, template, components, isCardTool, artShapeStyle, identifier) {
 
978
function createCardComponent(parent, template, components, isCardTool, artShapeStyle, categoryLayout, identifier) {
945
979
    var imports = 'import QtQuick 2.4; \n\
946
980
                   import Ubuntu.Components 1.3; \n\
947
981
                   import Ubuntu.Settings.Components 0.1; \n\
948
982
                   import Dash 0.1;\n\
949
983
                   import Utils 0.1;\n';
950
 
    var card = cardString(template, components, isCardTool, artShapeStyle);
 
984
    var card = cardString(template, components, isCardTool, artShapeStyle, categoryLayout);
951
985
    var code = imports + 'Component {\n' + card + '}\n';
952
986
 
953
987
    try {