Warning, /frameworks/kirigami/src/controls/private/PullDownIndicator.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2023 Connor Carney <hello@connorcarney.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 import QtQuick 0008 import QtQuick.Controls as QQC2 0009 import org.kde.kirigami as Kirigami 0010 import QtQuick.Shapes as QQShapes 0011 0012 /** 0013 * @brief A pull-down to refresh indicator that can be added to any Flickable or ScrollablePage. 0014 */ 0015 Item { 0016 id: root 0017 0018 //BEGIN properties 0019 /** 0020 * @brief The flickable that this indicator is attached to. 0021 * 0022 * If this is not set, the indicator will search for a Flickable in its parent chain. 0023 */ 0024 property Flickable flickable: { 0025 let candidate = parent 0026 while (candidate) { 0027 if (candidate instanceof Flickable) { 0028 return candidate 0029 } else if (candidate instanceof Kirigami.ScrollablePage) { 0030 return candidate.flickable 0031 } 0032 candidate = candidate.parent 0033 } 0034 return null; 0035 } 0036 0037 /** 0038 * @brief Whether to show the busy indicator at the top of the flickable 0039 * 0040 * This should be set to true whenever a refresh is in progress. It should typically 0041 * be set to true whe triggered() is emitted, and set to false when the refresh is 0042 * complete. This is not done automatically because the refresh may be triggered 0043 * from outside the indicator. 0044 */ 0045 property bool active: false 0046 0047 /** 0048 * @brief How far the flickable has been pulled down, between 0 (not at all) and 1 (where a refresh is triggered). 0049 */ 0050 readonly property real progress: !refreshing ? Math.min(-Math.min(flickable?.verticalOvershoot ?? 0, 0) / indicatorContainer.height, 1) : 0 0051 0052 /** 0053 * @brief Time to wait after the flickable has been pulled down before triggering a refresh 0054 * 0055 * This gives the user a chance to back out of the refresh if they release the flickable 0056 * before the refreshDelay has elapsed. 0057 */ 0058 property int refreshDelay: 500 0059 0060 /** 0061 * @brief emitted when the flickable is pulled down far enough to trigger a refresh 0062 */ 0063 signal triggered() 0064 //END properties 0065 0066 Item { 0067 id: indicatorContainer 0068 parent: root.flickable 0069 anchors { 0070 bottom: parent?.contentItem?.top 0071 bottomMargin: root.flickable.topMargin 0072 } 0073 0074 width: flickable?.width 0075 height: Kirigami.Units.gridUnit * 4 0076 QQC2.BusyIndicator { 0077 id: busyIndicator 0078 z: 1 0079 anchors.centerIn: parent 0080 running: root.active 0081 visible: root.active 0082 // Android busywidget QQC seems to be broken at custom sizes 0083 } 0084 QQShapes.Shape { 0085 id: spinnerProgress 0086 anchors { 0087 fill: busyIndicator 0088 margins: Kirigami.Units.smallSpacing 0089 } 0090 visible: !root.active && root.progress > 0 0091 QQShapes.ShapePath { 0092 strokeWidth: Kirigami.Units.smallSpacing 0093 strokeColor: Kirigami.Theme.highlightColor 0094 fillColor: "transparent" 0095 PathAngleArc { 0096 centerX: spinnerProgress.width / 2 0097 centerY: spinnerProgress.height / 2 0098 radiusX: spinnerProgress.width / 2 - Kirigami.Units.smallSpacing / 2 0099 radiusY: spinnerProgress.height / 2 - Kirigami.Units.smallSpacing / 2 0100 startAngle: 0 0101 sweepAngle: 360 * root.progress 0102 } 0103 } 0104 } 0105 } 0106 0107 onProgressChanged: { 0108 if (!root.active && root.progress >= 1) { 0109 refreshTriggerTimer.running = true; 0110 } else { 0111 refreshTriggerTimer.running = false; 0112 } 0113 } 0114 0115 0116 states: [ 0117 State { 0118 name: "active" 0119 when: root.active 0120 PropertyChanges { 0121 target: indicatorContainer 0122 anchors.bottomMargin: root.flickable.topMargin - indicatorContainer.height 0123 } 0124 PropertyChanges { 0125 target: root.flickable 0126 explicit: true 0127 0128 // this is not a loop because of explicit:true above 0129 // It adds the height of the indicator to the topMargin of the flickable 0130 // when we enter the active state; the change is automatically reversed 0131 // when returning to the base state. 0132 topMargin: indicatorContainer.height + root.flickable.topMargin 0133 } 0134 } 0135 ] 0136 0137 transitions: [ 0138 Transition { 0139 from: "" 0140 to: "active" 0141 enabled: root.flickable.verticalOvershoot >= 0 0142 reversible: true 0143 NumberAnimation { 0144 target: root.flickable 0145 properties: "topMargin" 0146 easing.type: Easing.InOutQuad 0147 duration: Kirigami.Units.longDuration 0148 } 0149 } 0150 ] 0151 0152 Timer { 0153 id: refreshTriggerTimer 0154 interval: root.refreshDelay 0155 onTriggered: { 0156 if (!root.active && root.progress >= 1) { 0157 root.triggered() 0158 } 0159 } 0160 } 0161 0162 }