on xenial help sign in
Create ratings on demand instead of all at the same time
34bcf71Albert Astals Cid
qml/Dash/Previews/Preview.qml+2
@@ -90,6 +90,8 @@ Item {
90 widgetData: model.properties
90 widgetData: model.properties
91 isCurrentPreview: root.isCurrent
91 isCurrentPreview: root.isCurrent
92 scopeStyle: root.scopeStyle
92 scopeStyle: root.scopeStyle
93+ parentList: column
94+
93 anchors {
95 anchors {
94 left: parent.left
96 left: parent.left
95 right: parent.right
97 right: parent.right
qml/Dash/Previews/PreviewRatingDisplay.qml+67−16
@@ -40,28 +40,79 @@ PreviewWidget {
40 id: root
40 id: root
41 implicitHeight: childrenRect.height
41 implicitHeight: childrenRect.height
42
42
43− Column {
43+ onIsCurrentPreviewChanged: ratingsList.updateRanges();
44+ onParentListChanged: ratingsList.updateRanges();
45+
46+ Connections {
47+ target: parentList
48+ onOriginYChanged: ratingsList.updateRanges();
49+ onContentYChanged: ratingsList.updateRanges();
50+ onHeightChanged: ratingsList.updateRanges();
51+ onContentHeightChanged: ratingsList.updateRanges();
52+ }
53+
54+ ListView {
55+ id: ratingsList
44 anchors { left: parent.left; right: parent.right; }
56 anchors { left: parent.left; right: parent.right; }
45− visible: reviewsRepeater.count > 0
57+ height: contentHeight
58+ interactive: false
59+
60+ model: root.widgetData["reviews"]
61+
62+ delegate: PreviewRatingSingleDisplay {
63+ id: prsd
64+ objectName: "reviewItem" + index
46
65
47− Repeater {
66+ anchors { left: parent.left; right: parent.right; }
48− id: reviewsRepeater
49− objectName: "reviewsRepeater"
50− model: root.widgetData["reviews"]
51
67
52− delegate: PreviewRatingSingleDisplay {
68+ rating: modelData["rating"] || -1
53− objectName: "reviewItem" + index
69+ author: modelData["author"] || ""
70+ review: modelData["review"] || ""
71+ urlIconEmpty: widgetData["rating-icon-empty"]
72+ urlIconFull: widgetData["rating-icon-full"]
73+ urlIconHalf: widgetData["rating-icon-half"]
74+ labelColor: scopeStyle ? scopeStyle.foreground : theme.palette.normal.baseText
75+ }
76+
77+ onContentHeightChanged: ratingsList.updateRanges();
54
78
55− anchors { left: parent.left; right: parent.right; }
79+ function updateRanges() {
80+ var baseItem = root.parent;
81+ if (!parentList || !baseItem) {
82+ ratingsList.displayMarginBeginning = 0;
83+ ratingsList.displayMarginEnd = 0;
84+ return;
85+ }
56
86
57− rating: modelData["rating"] || -1
87+ if (parentList.moving) {
58− author: modelData["author"] || ""
88+ // Do not update the range if we are overshooting up or down, since we'll come back
59− review: modelData["review"] || ""
89+ // to the stable position and delete/create items without any reason
60− urlIconEmpty: widgetData["rating-icon-empty"]
90+ if (parentList.contentY < parentList.originY) {
61− urlIconFull: widgetData["rating-icon-full"]
91+ return;
62− urlIconHalf: widgetData["rating-icon-half"]
92+ } else if (parentList.contentHeight - parentList.originY > parentList.height &&
63− labelColor: scopeStyle ? scopeStyle.foreground : theme.palette.normal.baseText
93+ parentList.contentY + parentList.height > parentList.contentHeight) {
94+ return;
95+ }
64 }
96 }
97+
98+ // A item view creates its delegates synchronously from
99+ // -displayMarginBeginning
100+ // to
101+ // height + displayMarginEnd
102+ // Around that area it adds the cacheBuffer area where delegates are created async
103+ //
104+ // We adjust displayMarginEnd to be negative so that the range of created delegates matches
105+ // from the beginning of the list to the end of the viewport.
106+ // Ideally we would also use displayMarginBeginning
107+ // so that delegates at the beginning get destroyed but that causes issues with
108+ // listview and is not really necessary to provide the better experience we're after
109+ var itemYOnViewPort = baseItem.y - parentList.contentY;
110+ var displayMarginEnd = -ratingsList.contentHeight + parentList.height - itemYOnViewPort;
111+ displayMarginEnd = -Math.max(-displayMarginEnd, 0);
112+ displayMarginEnd = -Math.min(-displayMarginEnd, ratingsList.contentHeight);
113+ displayMarginEnd = Math.round(displayMarginEnd);
114+
115+ ratingsList.displayMarginEnd = displayMarginEnd;
65 }
116 }
66 }
117 }
67}
118}
qml/Dash/Previews/PreviewWidget.qml+3
@@ -37,6 +37,9 @@ Item {
37 //! Set margins width.
37 //! Set margins width.
38 property real widgetMargins: units.gu(1)
38 property real widgetMargins: units.gu(1)
39
39
40+ /// The parent (vertical) list this widget is in (if any)
41+ property var parentList: null
42+
40 /*! \brief This signal should be emitted when a preview action was triggered.
43 /*! \brief This signal should be emitted when a preview action was triggered.
41 *
44 *
42 * \param widgetId, actionId Respective identifiers from widgetData.
45 * \param widgetId, actionId Respective identifiers from widgetData.
qml/Dash/Previews/PreviewWidgetFactory.qml+4
@@ -43,6 +43,9 @@ Loader {
43 //! Set margins width.
43 //! Set margins width.
44 property real widgetMargins: status === Loader.Ready ? item.widgetMargins : units.gu(1)
44 property real widgetMargins: status === Loader.Ready ? item.widgetMargins : units.gu(1)
45
45
46+ /// The parent (vertical) list this widget is in (if any)
47+ property var parentList: null
48+
46 //! Triggered signal forwarded from the widgets.
49 //! Triggered signal forwarded from the widgets.
47 signal triggered(string widgetId, string actionId, var data)
50 signal triggered(string widgetId, string actionId, var data)
48
51
@@ -82,6 +85,7 @@ Loader {
82 item.isCurrentPreview = Qt.binding(function() { return root.isCurrentPreview } )
85 item.isCurrentPreview = Qt.binding(function() { return root.isCurrentPreview } )
83 item.expanded = Qt.binding(function() { return root.expanded } )
86 item.expanded = Qt.binding(function() { return root.expanded } )
84 item.scopeStyle = Qt.binding(function() { return root.scopeStyle } )
87 item.scopeStyle = Qt.binding(function() { return root.scopeStyle } )
88+ item.parentList = Qt.binding(function() { return root.parentList } )
85 }
89 }
86
90
87 Connections {
91 Connections {