32
32
property int columnWidth: parent.width / columns
33
33
property int contentHeight: 0
34
34
property int count: model === undefined ? 0 : model.count
35
property int delayRebuildIndex: -1
35
36
property var incubating: ({}) // incubating objects
36
37
property var items: ({})
37
38
property var itemToColumn: ({}) // cache of the columns of indexes
38
39
property int lastIndex: 0 // the furtherest index loaded
40
property bool removing: false
39
41
property bool restoring: false // is the view restoring?
40
42
property var restoreItems: ({}) // when rebuilding items are stored here temporarily
63
if (!visible) { // store changes for when visible
64
if (count === 0 && lastIndex > -1) {
66
} else if (lastIndex > -1) {
67
lastIndex = -(lastIndex + 2); // save the index to restore later
69
} else if (count === 0) { // likely the model is been reset so reset the view
71
} else { // likely new items in the model check if any can be shown
64
onModelChanged: { // reload the model when it is set
66
append(true, model.count - 1)
76
69
onVisibleChanged: {
77
if (columns != columnHeights.length && visible) { // number of columns has changed while invisible so reset
81
} else if (lastIndex < 0 && visible) { // restore from count change
82
if (lastIndex === -1) {
85
lastIndex = (-lastIndex) - 2
70
if (visible && delayRebuildIndex !== -1) { // restore from count change
71
if (delayRebuildIndex === 0) {
74
removeIndex(delayRebuildIndex)
77
delayRebuildIndex = -1
81
// number of columns has changed while invisible so reset if not already restoring
82
if (visible && !restoring && columns != columnHeights.length) {
87
ListModel { // fakemodel for connections to link to when there is no model
92
target: model === undefined ? fakeModel : model
103
setDelayRebuildIndex(first)
105
if (first <= lastIndex) {
109
removeIndex(first) // remove earliest index and all items after
113
// Supply last index if larger as count is not updated until after insertion
114
append(true, last > count ? last : count)
119
setDelayRebuildIndex(first)
121
if (first <= lastIndex) {
125
removeIndex(first) // remove earliest index and all items after
128
// count is not updated until after removal, so send insertMax
129
// insertMax is count - removal region inclusive - 1 (lastIndex is 1 infront)
131
append(true, count - (1 + last - first) - 1) // rebuild any items on screen or before
141
append() // Append any new items (scrolling down)
92
147
// Append a new row of items if possible
148
function append(loadBefore, insertMax)
95
150
// Do not allow append to run if incubating
96
if (isIncubating() || restoring) {
151
if (isIncubating() || restoring || removing) {
106
161
var y = columnHeightsMax[columnsByHeight[i]];
108
163
// build new object in column if possible
109
if (count > 0 && lastIndex < count && inViewport(y, 0)) {
164
// if insertMax is undefined then allow if there is work todo (from the count in the model)
165
// otherwise use the insertMax as the count to compare with the lastIndex added to the columnFlow
167
// allow if the y position is within the viewport
168
// or if loadBefore is true then allow if the y position is before the viewport
169
if (((count > 0 && lastIndex < count && insertMax === undefined) || (insertMax !== undefined && lastIndex <= insertMax)) && (inViewport(y, 0) || (loadBefore === true && beforeViewport(y)))) {
110
170
incubateObject(lastIndex++, columnsByHeight[i], getMaxInColumn(columnsByHeight[i]), append);
182
// Detect if a loaded object is before the viewport with a buffer
183
function beforeViewport(y)
185
return y <= flickable.contentY - buffer;
122
188
// Cache the size of the columns for use later
123
189
function cacheColumnHeights()
388
// Remove an index from the model (invalidating anything after)
389
function removeIndex(index)
393
forceIncubationCompletion()
395
for (var i in items) {
396
if (i >= index && items.hasOwnProperty(i)) {
397
delete columnHeights[itemToColumn[i]][i]
398
delete itemToColumn[i]
322
411
// Restores existing items into potentially new positions
323
412
function restoreExisting()