37
38
readonly property alias subPageShown: subPageLoader.subPageShown
38
39
property int paginationCount: 0
39
40
property int paginationIndex: 0
41
property bool visibleToParent: false
40
42
property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible
43
property var holdingList: null
42
45
property var scopeStyle: ScopeStyle {
43
46
style: scope ? scope.customizations : {}
66
73
// so it's not implemented
67
74
scope.activate(result)
69
openPreview(index, resultsModel, limitedCategoryItemCount);
76
if (scope.preview(result)) {
77
openPreview(index, resultsModel, limitedCategoryItemCount);
73
function itemPressedAndHeld(index, itemModel, resultsModel, limitedCategoryItemCount) {
82
function itemPressedAndHeld(index, result, itemModel, resultsModel, limitedCategoryItemCount) {
74
83
if (itemModel.uri.indexOf("scope://") !== 0) {
75
openPreview(index, resultsModel, limitedCategoryItemCount);
84
if (scope.preview(result)) {
85
openPreview(index, resultsModel, limitedCategoryItemCount);
152
165
forceNoClip: subPageLoader.open
153
166
pixelAligned: true
155
property Item expandedCategoryItem: null
168
property string expandedCategoryId: ""
169
property int runMaximizeAfterSizeChanges: 0
157
171
readonly property bool pageHeaderTotallyVisible: scopeView.showPageHeader &&
158
172
((headerItemShownHeight == 0 && categoryView.contentY <= categoryView.originY) || (headerItemShownHeight == pageHeaderLoader.item.height))
160
delegate: ListItems.Base {
174
onExpandedCategoryIdChanged: {
175
var firstCreated = firstCreatedIndex();
176
var shrinkingAny = false;
177
var shrinkHeightDifference = 0;
178
for (var i = 0; i < createdItemCount(); ++i) {
179
var baseItem = item(firstCreated + i);
180
if (baseItem.expandable) {
181
var shouldExpand = baseItem.category === expandedCategoryId;
182
if (shouldExpand != baseItem.expanded) {
184
if (!subPageLoader.open) {
185
var animateShrinking = !shouldExpand && baseItem.y + baseItem.item.collapsedHeight + baseItem.seeAllButton.height < categoryView.height;
186
var animateGrowing = shouldExpand && baseItem.y + baseItem.height < categoryView.height;
187
animate = shrinkingAny || animateShrinking || animateGrowing;
192
shrinkHeightDifference = baseItem.item.expandedHeight - baseItem.item.collapsedHeight;
195
if (shouldExpand && !subPageLoader.open) {
197
categoryView.maximizeVisibleArea(firstCreated + i, baseItem.item.expandedHeight + baseItem.seeAllButton.height);
199
// If the space that shrinking is smaller than the one we need to grow we'll call maximizeVisibleArea
200
// after the shrink/grow animation ends
201
var growHeightDifference = baseItem.item.expandedHeight - baseItem.item.collapsedHeight;
202
if (growHeightDifference > shrinkHeightDifference) {
203
runMaximizeAfterSizeChanges = 2;
205
runMaximizeAfterSizeChanges = 0;
210
baseItem.expand(shouldExpand, animate);
216
delegate: DashCategoryBase {
162
218
objectName: "dashCategory" + category
163
highlightWhenPressed: false
166
220
property Item seeAllButton: seeAll
194
248
// This can happen with the VJ that doesn't know how height it will be on creation
195
249
// so doesn't set expandable until a bit too late for onLoaded
196
250
if (expandable) {
197
var shouldExpand = baseItem === categoryView.expandedCategoryItem;
251
var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
198
252
baseItem.expand(shouldExpand, false /*animate*/);
202
onHeightChanged: rendererLoader.updateDelegateCreationRange();
203
onYChanged: rendererLoader.updateDelegateCreationRange();
256
onHeightChanged: rendererLoader.updateRanges();
257
onYChanged: rendererLoader.updateRanges();
206
260
id: rendererLoader
215
269
id: heightBehaviour
217
271
animation: UbuntuNumberAnimation {
272
duration: UbuntuAnimation.FastDuration
218
273
onRunningChanged: {
220
275
heightBehaviour.enabled = false
276
if (categoryView.runMaximizeAfterSizeChanges > 0) {
277
categoryView.runMaximizeAfterSizeChanges--;
278
if (categoryView.runMaximizeAfterSizeChanges == 0) {
279
var firstCreated = categoryView.firstCreatedIndex();
280
for (var i = 0; i < categoryView.createdItemCount(); ++i) {
281
var baseItem = categoryView.item(firstCreated + i);
282
if (baseItem.category === categoryView.expandedCategoryId) {
283
categoryView.maximizeVisibleArea(firstCreated + i, baseItem.item.expandedHeight + baseItem.seeAllButton.height);
245
313
item.objectName = Qt.binding(function() { return categoryId })
246
314
item.scopeStyle = scopeView.scopeStyle;
247
315
if (baseItem.expandable) {
248
var shouldExpand = baseItem === categoryView.expandedCategoryItem;
316
var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
249
317
baseItem.expand(shouldExpand, false /*animate*/);
251
updateDelegateCreationRange();
252
320
if (scope && scope.id === "clickscope" && (categoryId === "predefined" || categoryId === "local")) {
253
321
// Yeah, hackish :/
254
322
cardTool.artShapeSize = Qt.size(units.gu(8), units.gu(7.5));
284
352
target: categoryView
285
onExpandedCategoryItemChanged: {
286
collapseAllButExpandedCategory();
288
function collapseAllButExpandedCategory() {
289
var item = rendererLoader.item;
290
if (baseItem.expandable) {
291
var shouldExpand = baseItem === categoryView.expandedCategoryItem;
292
if (shouldExpand != baseItem.expanded) {
293
// If the filter animation will be seen start it, otherwise, just flip the switch
294
var shrinkingVisible = !shouldExpand && y + item.collapsedHeight + seeAll.height < categoryView.height;
295
var growingVisible = shouldExpand && y + height < categoryView.height;
296
if (!subPageLoader.open || shouldExpand) {
297
var animate = shrinkingVisible || growingVisible;
298
baseItem.expand(shouldExpand, animate)
299
if (shouldExpand && !subPageLoader.open) {
300
categoryView.maximizeVisibleArea(index, item.expandedHeight + seeAll.height);
306
onOriginYChanged: rendererLoader.updateDelegateCreationRange();
307
onContentYChanged: rendererLoader.updateDelegateCreationRange();
308
onHeightChanged: rendererLoader.updateDelegateCreationRange();
309
onContentHeightChanged: rendererLoader.updateDelegateCreationRange();
312
function updateDelegateCreationRange() {
353
onOriginYChanged: rendererLoader.updateRanges();
354
onContentYChanged: rendererLoader.updateRanges();
355
onHeightChanged: rendererLoader.updateRanges();
356
onContentHeightChanged: rendererLoader.updateRanges();
360
onIsCurrentChanged: rendererLoader.updateRanges();
361
onVisibleToParentChanged: rendererLoader.updateRanges();
365
onMovingChanged: if (!moving) rendererLoader.updateRanges();
368
function updateRanges() {
369
// Don't want to create stress by requesting more items during scope
370
// changes so unless you're not part of the visible scopes just return
371
if (holdingList && holdingList.moving && !scopeView.visibleToParent) {
313
375
if (categoryView.moving) {
314
376
// Do not update the range if we are overshooting up or down, since we'll come back
315
377
// to the stable position and delete/create items without any reason
324
386
if (item && item.hasOwnProperty("displayMarginBeginning")) {
325
// TODO do we need item.originY here, test 1300302 once we have a silo
326
// and we can run it on the phone
327
if (baseItem.y + baseItem.height <= 0) {
328
// Not visible (item at top of the list viewport)
329
item.displayMarginBeginning = -baseItem.height;
330
item.displayMarginEnd = 0;
331
} else if (baseItem.y >= categoryView.height) {
332
// Not visible (item at bottom of the list viewport)
333
item.displayMarginBeginning = 0;
334
item.displayMarginEnd = -baseItem.height;
387
// A item view creates its delegates synchronously from
388
// -displayMarginBeginning
390
// height + displayMarginEnd
391
// Around that area it adds the cacheBuffer area where delegates are created async
393
// We adjust displayMarginBeginning and displayMarginEnd so
394
// * In non visible scopes nothing is considered visible and we set cacheBuffer
395
// so that creates the items that would be in the viewport asynchronously
396
// * For the current scope set the visible range to the viewport and then
397
// use cacheBuffer to create extra items for categoryView.height * 1.5
398
// to make scrolling nicer by mantaining a higher number of
400
// * For non current but visible scopes (i.e. when the user changes from one scope
401
// to the next, we set the visible range to the viewport so
402
// items are not culled (invisible) but still use no cacheBuffer
403
// (it will be set once the scope is the current one)
404
var displayMarginBeginning = baseItem.y;
405
displayMarginBeginning = -Math.max(-displayMarginBeginning, 0);
406
displayMarginBeginning = -Math.min(-displayMarginBeginning, baseItem.height);
407
displayMarginBeginning = Math.round(displayMarginBeginning);
408
var displayMarginEnd = -baseItem.height + seeAll.height + categoryView.height - baseItem.y;
409
displayMarginEnd = -Math.max(-displayMarginEnd, 0);
410
displayMarginEnd = -Math.min(-displayMarginEnd, baseItem.height);
411
displayMarginEnd = Math.round(displayMarginEnd);
412
if (scopeView.isCurrent || scopeView.visibleToParent) {
413
item.displayMarginBeginning = displayMarginBeginning;
414
item.displayMarginEnd = displayMarginEnd;
415
item.cacheBuffer = scopeView.isCurrent ? categoryView.height * 1.5 : 0;
336
item.displayMarginBeginning = -Math.max(-baseItem.y, 0);
337
item.displayMarginEnd = -Math.max(baseItem.height - seeAll.height
338
- categoryView.height + baseItem.y, 0)
417
var visibleRange = baseItem.height + displayMarginEnd + displayMarginBeginning;
418
if (visibleRange < 0) {
419
item.displayMarginBeginning = displayMarginBeginning;
420
item.displayMarginEnd = displayMarginEnd;
421
item.cacheBuffer = 0;
423
// This should be visibleRange/2 in each of the properties
424
// but some item views still (like GridView) like creating sync delegates even if
425
// the visible range is 0 so let's make sure the visible range is negative
426
item.displayMarginBeginning = displayMarginBeginning - visibleRange;
427
item.displayMarginEnd = displayMarginEnd - visibleRange;
428
item.cacheBuffer = visibleRange;
349
440
left: parent.left
350
441
right: parent.right
352
height: seeAllLabel.visible ? seeAllLabel.font.pixelSize + units.gu(4) : 0
443
height: baseItem.expandable && !baseItem.headerLink ? seeAllLabel.font.pixelSize + units.gu(4) : 0
355
if (categoryView.expandedCategoryItem !== baseItem) {
356
categoryView.expandedCategoryItem = baseItem;
447
if (categoryView.expandedCategoryId !== baseItem.category) {
448
categoryView.expandedCategoryId = baseItem.category;
449
floatingSeeLess.companionBase = baseItem;
358
categoryView.expandedCategoryItem = null;
451
categoryView.expandedCategoryId = "";
546
id: pullToRefreshClippingItem
547
anchors.left: parent.left
548
anchors.right: parent.right
549
anchors.bottom: parent.bottom
550
height: parent.height - pullToRefresh.contentY + (pageHeaderLoader.item ? pageHeaderLoader.item.bottomItem[0].height - pageHeaderLoader.item.height : 0)
555
objectName: "pullToRefresh"
558
readonly property real contentY: categoryView.contentY - categoryView.originY
559
y: -contentY - units.gu(5)
563
scopeView.scope.refresh()
565
anchors.left: parent.left
566
anchors.right: parent.right
570
onProcessingChanged: if (!scopeView.processing) pullToRefresh.refreshing = false
573
style: PullToRefreshScopeStyle {
575
activationThreshold: units.gu(14)
454
581
id: floatingSeeLess
455
582
objectName: "floatingSeeLess"
457
584
property Item companionTo: companionBase ? companionBase.seeAllButton : null
458
property Item companionBase: categoryView.expandedCategoryItem
585
property Item companionBase: null
459
586
property bool showBecausePosition: false
460
587
property real yOffset: 0